From 8a3883e8321c4dcbd03e857ea2134438a882d990 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 27 Oct 2022 16:43:54 -0700 Subject: [PATCH 001/337] [Internal] Client Telemetry: Fixes tests leaking environment variables (#3517) * Adding log lines * More logs * Debugging further * Removing other builds * And more debugging * Wrong build parameters * Wrong category * Removing noise * Fixing test * Adding utils * Adding test with client telemetry enabled * Fixing leak in Client Telemetry Tests * Reenabling test * cpu monitor initialization * Adding name details * Undo another file --- .../ClientTelemetryTests.cs | 27 ++++----- .../PartitionKeyRangeCacheTests.cs | 14 ++++- .../SynchronizationContextTests.cs | 22 ++++++-- .../Utils/Util.cs | 56 +++++++++++++++++++ 4 files changed, 97 insertions(+), 22 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 93e0cd8837..961c5d25d1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -30,7 +30,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests [TestClass] public class ClientTelemetryTests : BaseCosmosClientHelper { - private const string telemetryEndpointUrl = "http://dummy.telemetry.endpoint/"; private const int scheduledInSeconds = 1; private static readonly object jsonObject = JsonConvert.DeserializeObject("{\"compute\":{\"azEnvironment\":\"AzurePublicCloud\",\"customData\":\"\",\"isHostCompatibilityLayerVm\":\"false\",\"licenseType\":\"\",\"location\":\"eastus\",\"name\":\"sourabh-testing\",\"offer\":\"UbuntuServer\",\"osProfile\":{\"adminUsername\":\"azureuser\",\"computerName\":\"sourabh-testing\"},\"osType\":\"Linux\",\"placementGroupId\":\"\",\"plan\":{\"name\":\"\",\"product\":\"\",\"publisher\":\"\"},\"platformFaultDomain\":\"0\",\"platformUpdateDomain\":\"0\",\"provider\":\"Microsoft.Compute\",\"publicKeys\":[{\"keyData\":\"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5uCeOAm3ehmhI+2PbMoMl17Eo\r\nqfHKCycSaBJsv9qxlmBOuFheSJc1XknJleXUSsuTO016/d1PyWpevnqOZNRksWoa\r\nJvQ23sDTxcK+X2OP3QlCUeX4cMjPXqlL8z1UYzU4Bx3fFvf8fs67G3N72sxWBw5P\r\nZyuXyhBm0NCe/2NYMKgEDT4ma8XszO0ikbhoPKbMbgHAQk/ktWQHNcqYOPQKEWqp\r\nEK1R0rjS2nmtovfScP/ZGXcvOpJ1/NDBo4dh1K+OxOGM/4PSH/F448J5Zy4eAyEk\r\nscys+IpeIOTOlRUy/703SNIX0LEWlnYqbyL9c1ypcYLQqF76fKkDfzzFI/OWVlGw\r\nhj/S9uP8iMsR+fhGIbn6MAa7O4DWPWLuedSp7KDYyjY09gqNJsfuaAJN4LiC6bPy\r\nhknm0PVLK3ux7EUOt+cZrHCdIFWbdOtxiPNIl1tkv9kV5aE5Aj2gJm4MeB9uXYhS\r\nOuksboBc0wyUGrl9+XZJ1+NlZOf7IjVi86CieK8= generated-by-azure\r\n\",\"path\":\"/home/azureuser/.ssh/authorized_keys\"}],\"publisher\":\"Canonical\",\"resourceGroupName\":\"sourabh-telemetry-sdk\",\"resourceId\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/virtualMachines/sourabh-testing\",\"securityProfile\":{\"secureBootEnabled\":\"false\",\"virtualTpmEnabled\":\"false\"},\"sku\":\"18.04-LTS\",\"storageProfile\":{\"dataDisks\":[],\"imageReference\":{\"id\":\"\",\"offer\":\"UbuntuServer\",\"publisher\":\"Canonical\",\"sku\":\"18.04-LTS\",\"version\":\"latest\"},\"osDisk\":{\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\",\"diffDiskSettings\":{\"option\":\"\"},\"diskSizeGB\":\"30\",\"encryptionSettings\":{\"enabled\":\"false\"},\"image\":{\"uri\":\"\"},\"managedDisk\":{\"id\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/disks/sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"storageAccountType\":\"Premium_LRS\"},\"name\":\"sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"osType\":\"Linux\",\"vhd\":{\"uri\":\"\"},\"writeAcceleratorEnabled\":\"false\"}},\"subscriptionId\":\"8fba6d4f-7c37-4d13-9063-fd58ad2b86e2\",\"tags\":\"azsecpack:nonprod;platformsettings.host_environment.service.platform_optedin_for_rootcerts:true\",\"tagsList\":[{\"name\":\"azsecpack\",\"value\":\"nonprod\"},{\"name\":\"platformsettings.host_environment.service.platform_optedin_for_rootcerts\",\"value\":\"true\"}],\"version\":\"18.04.202103250\",\"vmId\":\"d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd\",\"vmScaleSetName\":\"\",\"vmSize\":\"Standard_D2s_v3\",\"zone\":\"1\"},\"network\":{\"interface\":[{\"ipv4\":{\"ipAddress\":[{\"privateIpAddress\":\"10.0.7.5\",\"publicIpAddress\":\"\"}],\"subnet\":[{\"address\":\"10.0.7.0\",\"prefix\":\"24\"}]},\"ipv6\":{\"ipAddress\":[]},\"macAddress\":\"000D3A8F8BA0\"}]}}"); @@ -46,12 +45,8 @@ public class ClientTelemetryTests : BaseCosmosClientHelper private HttpClientHandlerHelper httpHandlerForNonAzureInstance; [ClassInitialize] - public static void ClassInitialize(TestContext context) + public static void ClassInitialize(TestContext _) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "true"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, telemetryEndpointUrl); - SystemUsageMonitor oldSystemUsageMonitor = (SystemUsageMonitor)typeof(DiagnosticsHandlerHelper) .GetField("systemUsageMonitor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DiagnosticsHandlerHelper.Instance); oldSystemUsageMonitor.Stop(); @@ -62,6 +57,8 @@ public static void ClassInitialize(TestContext context) [TestInitialize] public void TestInitialize() { + Util.EnableClientTelemetryEnvironmentVariables(); + this.actualInfo = new List(); this.httpHandler = new HttpClientHandlerHelper @@ -134,16 +131,6 @@ public void TestInitialize() .WithApplicationPreferredRegions(this.preferredRegionList); } - [ClassCleanup] - public static void FinalCleanup() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, null); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); - - ClientTelemetryTests.ResetSystemUsageMonitor(false); - } - private static void ResetSystemUsageMonitor(bool isTelemetryEnabled) { ClientTelemetryTests.systemUsageMonitor?.Stop(); @@ -186,6 +173,14 @@ public async Task Cleanup() azMetadataField.SetValue(null, null); await base.TestCleanup(); + + Util.DisableClientTelemetryEnvironmentVariables(); + } + + [ClassCleanup] + public static void FinalCleanup() + { + ClientTelemetryTests.ResetSystemUsageMonitor(false); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs index 504f06467f..1b7d554772 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs @@ -19,11 +19,21 @@ public class PartitionKeyRangeCacheTests { private bool loopBackgroundOperaitons = false; - [TestMethod] - public async Task VerifyPkRangeCacheRefreshOnSplitWithErrorsAsync() + [TestInitialize] + public void TestInitialize() + { + this.loopBackgroundOperaitons = false; + } + + [TestCleanup] + public void TestCleanup() { this.loopBackgroundOperaitons = false; + } + [TestMethod] + public async Task VerifyPkRangeCacheRefreshOnSplitWithErrorsAsync() + { int throwOnPkRefreshCount = 3; int pkRangeCalls = 0; bool causeSplitExceptionInRntbdCall = false; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs index 7721c41e7b..a8ae6ce1a4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs @@ -13,10 +13,17 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests [TestClass] public class SynchronizationContextTests { - [TestMethod] + [DataTestMethod] + [DataRow(false, DisplayName = "SynchronizationContextTests - Client Telemetry disabled")] + [DataRow(true, DisplayName = "SynchronizationContextTests - Client Telemetry enabled")] [Timeout(30000)] - public void VerifySynchronizationContextDoesNotLock() + public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) { + if (withClientTelemetry) + { + Util.EnableClientTelemetryEnvironmentVariables(); + } + string databaseId = Guid.NewGuid().ToString(); SynchronizationContext prevContext = SynchronizationContext.Current; try @@ -29,7 +36,6 @@ public void VerifySynchronizationContextDoesNotLock() { Cosmos.Database database = client.CreateDatabaseAsync(databaseId).GetAwaiter().GetResult(); database = client.CreateDatabaseIfNotExistsAsync(databaseId).GetAwaiter().GetResult(); - database.ReadStreamAsync().ConfigureAwait(false).GetAwaiter().GetResult(); database.ReadAsync().ConfigureAwait(false).GetAwaiter().GetResult(); @@ -118,7 +124,7 @@ public void VerifySynchronizationContextDoesNotLock() double cost = container.GetItemLinqQueryable( allowSynchronousQueryExecution: true).Select(x => x.cost).Sum(); - + ItemResponse deleteResponse = container.DeleteItemAsync(partitionKey: new Cosmos.PartitionKey(testItem.pk), id: testItem.id).ConfigureAwait(false).GetAwaiter().GetResult(); Assert.IsNotNull(deleteResponse); } @@ -127,13 +133,21 @@ public void VerifySynchronizationContextDoesNotLock() finally { SynchronizationContext.SetSynchronizationContext(prevContext); + using (CosmosClient client = TestCommon.CreateCosmosClient()) { client.GetDatabase(databaseId).DeleteAsync().GetAwaiter().GetResult(); } + + if (withClientTelemetry) + { + Util.DisableClientTelemetryEnvironmentVariables(); + } } } + + public class TestSynchronizationContext : SynchronizationContext { private object locker = new object(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index b17a575223..4533b2b562 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -5,11 +5,15 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Globalization; + using System.IO; using System.Linq; using System.Net; + using System.Text; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Services.Management.Tests; + using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Documents.Collections; @@ -514,5 +518,57 @@ internal static void LogRequestOptions(RequestOptions options, bool shouldLogOff options.OfferType, options.OfferThroughput); } + + internal static void EnableClientTelemetryEnvironmentVariables() + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "true"); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1"); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); + } + + internal static void DisableClientTelemetryEnvironmentVariables() + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, null); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); + } + + /// + /// Enables traces for local debugging + /// + internal static void EnableTracesForDebugging() + { + Type defaultTrace = Type.GetType("Microsoft.Azure.Cosmos.Core.Trace.DefaultTrace,Microsoft.Azure.Cosmos.Direct"); + TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null); + traceSource.Switch.Level = SourceLevels.All; + traceSource.Listeners.Clear(); + traceSource.Listeners.Add(new DirectToConsoleTraceListener()); + } + + public class DirectToConsoleTraceListener : TextWriterTraceListener + { + public DirectToConsoleTraceListener() : base(new DirectToConsoleTextWriter()) + { + } + + public override void Close() + { + } + } + + public class DirectToConsoleTextWriter : TextWriter + { + public override Encoding Encoding => Console.Out.Encoding; + + public override void Write(string value) + { + Logger.LogLine(value); + } + + public override void WriteLine(string value) + { + Logger.LogLine(value); + } + } } } From 543294cd7e49c9322661422ea602bc911c434972 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Sat, 29 Oct 2022 14:08:48 -0700 Subject: [PATCH 002/337] Updated change log and bumped up the version. (#3526) --- Directory.Build.props | 6 +- .../contracts/API_3.31.1-preview.txt | 1526 +++++++++++++++++ .../contracts/API_3.31.1.txt | 1476 ++++++++++++++++ changelog.md | 6 + 4 files changed, 3011 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.31.1-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.31.1.txt diff --git a/Directory.Build.props b/Directory.Build.props index a8ce493c15..d95c118656 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,10 +1,10 @@ - 3.31.0 - 3.31.0 + 3.31.1 + 3.31.1 preview - 3.29.2 + 3.29.4 2.0.0 2.0.0 preview diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.31.1-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.31.1-preview.txt new file mode 100644 index 0000000000..e299887d03 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.31.1-preview.txt @@ -0,0 +1,1526 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode FullFidelity { get; } + public static ChangeFeedMode Incremental { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.31.1.txt b/Microsoft.Azure.Cosmos/contracts/API_3.31.1.txt new file mode 100644 index 0000000000..9227774985 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.31.1.txt @@ -0,0 +1,1476 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 4d8bce7541..186c764c81 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.31.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.1) - 2022-10-29 +### [3.31.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.1-preview) - 2022-10-29 + +#### Fixed +- Connection: Fixes health check to identify broken connections earlier. + ### [3.31.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.0) - 2022-10-03 ### [3.31.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.0-preview) - 2022-10-03 From abf3d93f88894aa495c70fcc7b4ca0c9d55c7e89 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Mon, 31 Oct 2022 14:12:32 -0700 Subject: [PATCH 003/337] Query: Fixes performance regression on target partition on some ORDER BY queries with continuation (#3525) * Revert performance regression caused by https://github.com/Azure/azure-cosmos-dotnet-v3/pull/1289/ * Remove irrelevant comment * Add a test for validating formatted filters for the target partition --- ...OrderByCrossPartitionQueryPipelineStage.cs | 4 +- ...ByCrossPartitionQueryPipelineStageTests.cs | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index a660f29d0b..bbd3d7be4e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -1027,9 +1027,7 @@ private static (string leftFilter, string targetFilter, string rightFilter) GetF } } - // For the target filter we can make an optimization to just return "true", - // since we already have the backend continuation token to resume with. - return (left.ToString(), TrueFilter, right.ToString()); + return (left.ToString(), target.ToString(), right.ToString()); } private static async Task monadicQueryByPage)>> FilterNextAsync( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs index 448f63f02c..52062c8afb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs @@ -278,6 +278,63 @@ public void MonadicCreate_MultipleOrderByContinuationToken() } } + [TestMethod] + public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsync() + { + QueryPage emptyPage = new QueryPage( + documents: new List(), + requestCharge: 0, + activityId: string.Empty, + responseLengthInBytes: 0, + cosmosQueryExecutionInfo: default, + disallowContinuationTokenMessage: default, + additionalHeaders: default, + state: default); + + string expectedQuerySpec = "SELECT * FROM c WHERE ( c._ts >= 1665482200 OR IS_STRING(c._ts) OR IS_ARRAY(c._ts) OR IS_OBJECT(c._ts) ) ORDER BY c._ts"; + Mock mockContainer = new Mock(MockBehavior.Strict); + mockContainer + .Setup( + c => c.MonadicQueryAsync( + It.Is(sqlQuerySpec => expectedQuerySpec.Equals(sqlQuerySpec.QueryText)), + It.IsAny>(), + It.IsAny(), + NoOpTrace.Singleton, + default)) + .ReturnsAsync(TryCatch.FromResult(emptyPage)); + + string continuationToken = @"[{""compositeToken"":{""token"":null,""range"":{""min"":""A"",""max"":""B""}},""orderByItems"":[{""item"":1665482200}],""rid"":""64kUAPYyHHk6XgIAAADACQ=="",""skipCount"":1,""filter"":""( c._ts >= 1665482198 OR IS_STRING(c._ts) OR IS_ARRAY(c._ts) OR IS_OBJECT(c._ts) )""}]"; + + IReadOnlyList targetRanges = new List() + { + new FeedRangeEpk(new Range(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)), + new FeedRangeEpk(new Range(min: "B", max: "C", isMinInclusive: true, isMaxInclusive: false)) + }; + + TryCatch monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: mockContainer.Object, + sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c WHERE {documentdb-formattableorderbyquery-filter} ORDER BY c._ts"), + targetRanges: targetRanges, + partitionKey: null, + orderByColumns: new List() + { + new OrderByColumn("c._ts", SortOrder.Ascending) + }, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 1), + maxConcurrency: 0, + cancellationToken: default, + continuationToken: CosmosElement.Parse(continuationToken)); + Assert.IsTrue(monadicCreate.Succeeded); + + IQueryPipelineStage queryPipelineStage = monadicCreate.Result; + for (int i = 0; i < targetRanges.Count; ++i) + { + Assert.IsTrue(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)); + } + + Assert.IsFalse(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)); + } + [TestMethod] public async Task TestDrainFully_StartFromBeginingAsync_NoDocuments() { From 84ef54516b5e14db1c1302b84d69fe325456205e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 2 Nov 2022 19:44:30 +0530 Subject: [PATCH 004/337] [Internal] AI Integration: Adds SubStatusCode Information in attributes (#3533) * wip * regenerated baseline * add test * fix test Co-authored-by: Sourabh Jain --- .../CosmosExceptions/CosmosException.cs | 1 + .../OpenTelemetryAttributeKeys.cs | 1 + .../OpenTelemetry/OpenTelemetryAttributes.cs | 5 + .../OpenTelemetryCoreRecorder.cs | 1 + .../OpenTelemetry/OpenTelemetryResponse.cs | 12 +- .../OpenTelemetry/OpenTelemetryResponse{T}.cs | 10 +- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 46 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 14 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Tracing/OpenTelemetryListener.cs | 44 +++- 17 files changed, 259 insertions(+), 205 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs index d789c97b03..f6544e3545 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs @@ -290,6 +290,7 @@ private string ToStringHelper( internal static void RecordOtelAttributes(CosmosException exception, DiagnosticScope scope) { scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, exception.StatusCode); + scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, exception.SubStatusCode); scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, exception.RequestCharge); scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(exception.Diagnostics?.GetContactedRegions())); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 2ea3fb1cdc..033a8744b6 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -29,6 +29,7 @@ internal sealed class OpenTelemetryAttributeKeys public const string RequestContentLength = "db.cosmosdb.request_content_length_bytes"; public const string ResponseContentLength = "db.cosmosdb.response_content_length_bytes"; public const string StatusCode = "db.cosmosdb.status_code"; + public const string SubStatusCode = "db.cosmosdb.sub_status_code"; public const string RequestCharge = "db.cosmosdb.request_charge"; public const string Region = "db.cosmosdb.regions_contacted"; public const string RetryCount = "db.cosmosdb.retry_count"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs index 26760f8de4..636ccd5714 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs @@ -70,5 +70,10 @@ internal OpenTelemetryAttributes(RequestMessage requestMessage, string container /// OperationType /// internal string OperationType { get; set; } + + /// + /// SubStatusCode + /// + internal int SubStatusCode { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index f825fbf3b7..c70b14a550 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -82,6 +82,7 @@ public void Record(OpenTelemetryAttributes response) this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, response.RequestContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, response.ResponseContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, response.StatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, response.SubStatusCode); this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, response.RequestCharge); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, response.ItemCount); this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, response.OperationType); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs index 6df9b774cc..0547fda4bd 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs @@ -19,7 +19,8 @@ internal OpenTelemetryResponse(TransactionalBatchResponse responseMessage, strin itemCount: responseMessage.Headers?.ItemCount, databaseName: databaseName, containerName: containerName, - requestMessage: null) + requestMessage: null, + subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } @@ -32,7 +33,8 @@ internal OpenTelemetryResponse(ResponseMessage responseMessage, string container itemCount: responseMessage.Headers?.ItemCount, databaseName: databaseName, containerName: containerName, - requestMessage: responseMessage.RequestMessage) + requestMessage: responseMessage.RequestMessage, + subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } @@ -44,14 +46,16 @@ private OpenTelemetryResponse( string itemCount, string databaseName, string containerName, - RequestMessage requestMessage) + RequestMessage requestMessage, + int subStatusCode) : base(requestMessage, containerName, databaseName) { this.StatusCode = statusCode; this.RequestCharge = requestCharge; this.ResponseContentLength = responseContentLength ?? OpenTelemetryAttributes.NotAvailable; this.Diagnostics = diagnostics; - this.ItemCount = itemCount ?? OpenTelemetryAttributes.NotAvailable; + this.ItemCount = itemCount ?? OpenTelemetryAttributes.NotAvailable; + this.SubStatusCode = subStatusCode; } private static string GetPayloadSize(ResponseMessage response) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs index 6f0ab85081..68301f4f4e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs @@ -18,7 +18,8 @@ internal OpenTelemetryResponse(FeedResponse responseMessage, string container itemCount: responseMessage.Headers?.ItemCount, databaseName: databaseName, containerName: containerName, - requestMessage: responseMessage.RequestMessage) + requestMessage: responseMessage.RequestMessage, + subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } @@ -31,7 +32,8 @@ internal OpenTelemetryResponse(Response responseMessage, string containerName itemCount: responseMessage.Headers?.ItemCount, databaseName: databaseName, containerName: containerName, - requestMessage: responseMessage.RequestMessage) + requestMessage: responseMessage.RequestMessage, + subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } @@ -43,7 +45,8 @@ private OpenTelemetryResponse( string itemCount, string databaseName, string containerName, - RequestMessage requestMessage) + RequestMessage requestMessage, + int subStatusCode) : base(requestMessage, containerName, databaseName) { this.StatusCode = statusCode; @@ -51,6 +54,7 @@ private OpenTelemetryResponse( this.ResponseContentLength = responseContentLength ?? OpenTelemetryAttributes.NotAvailable; this.Diagnostics = diagnostics; this.ItemCount = itemCount ?? OpenTelemetryAttributes.NotAvailable; + this.SubStatusCode = subStatusCode; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 2c5242bbda..f2df88ec68 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -150,7 +150,7 @@ } ] }]]> - Cosmos.ExecuteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ExecuteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index bb65e30393..41d8aca522 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -159,16 +159,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -342,16 +342,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -525,16 +525,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -708,16 +708,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -891,16 +891,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1074,16 +1074,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1257,16 +1257,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1440,16 +1440,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1623,16 +1623,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1806,16 +1806,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2699,7 +2699,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 1ca6744db1..0d9f75e0a8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -1201,11 +1201,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1977,11 +1977,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2726,11 +2726,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3503,11 +3503,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3837,9 +3837,9 @@ } ] }]]> - Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.ReadAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.ReadAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 8a4cf2f12f..98ac9c485a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -126,8 +126,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -241,8 +241,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index dad3787a12..7fc2fa5639 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -173,7 +173,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -459,7 +459,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -715,7 +715,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1009,7 +1009,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1379,7 +1379,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1558,9 +1558,9 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 8bd3e5f26d..c217c523a3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -709,10 +709,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1458,10 +1458,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2180,10 +2180,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2930,10 +2930,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3759,10 +3759,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4492,10 +4492,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -5253,10 +5253,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 836e4aa4ab..6d05d3ce0e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -671,10 +671,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1382,10 +1382,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2066,10 +2066,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2778,10 +2778,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 7afb14c5e7..20203e0664 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -681,12 +681,12 @@ } ] }]]> - Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1396,7 +1396,7 @@ } ] }]]> - Cosmos.ReadManyItemsAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadManyItemsAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 371cf51a53..b2d281b020 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -102,7 +102,7 @@ } ] }]]> - Cosmos.CreateItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -204,7 +204,7 @@ } ] }]]> - Cosmos.ReadItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -314,7 +314,7 @@ } ] }]]> - Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -419,7 +419,7 @@ } ] }]]> - Cosmos.DeleteItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index fb4bcb22c0..4e64df5dae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -130,7 +130,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -239,7 +239,7 @@ } ] }]]> - Cosmos.ReadItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -363,7 +363,7 @@ } ] }]]> - Cosmos.ReplaceItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReplaceItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -474,7 +474,7 @@ } ] }]]> - Cosmos.DeleteItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs index e8e53b6ff1..fd50cd7365 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs @@ -136,10 +136,10 @@ private void RecordAttributes(string name, IEnumerable"); + OpenTelemetryListener.AssertData(name, tags); + foreach (KeyValuePair tag in tags) { - this.ValidateData(name, tag); - builder .Append("") .Append(tag.Key) @@ -149,7 +149,45 @@ private void RecordAttributes(string name, IEnumerable tag) + private static void AssertData(string name, IEnumerable> tags) + { + IList allowedAttributes = new List + { + "az.namespace", + "kind", + "db.system", + "db.name", + "db.operation", + "net.peer.name", + "db.cosmosdb.client_id", + "db.cosmosdb.hashed_machine_id", + "db.cosmosdb.user_agent", + "db.cosmosdb.connection_mode", + "db.cosmosdb.operation_type", + "db.cosmosdb.container", + "db.cosmosdb.request_content_length_bytes", + "db.cosmosdb.response_content_length_bytes", + "db.cosmosdb.status_code", + "db.cosmosdb.sub_status_code", + "db.cosmosdb.request_charge", + "db.cosmosdb.regions_contacted", + "db.cosmosdb.retry_count", + "db.cosmosdb.item_count", + "db.cosmosdb.request_diagnostics", + "exception.type", + "exception.message", + "exception.stacktrace" + }; + + foreach (KeyValuePair tag in tags) + { + Assert.IsTrue(allowedAttributes.Contains(tag.Key), $"{tag.Key} is not allowed for {name}"); + + OpenTelemetryListener.AssertDatabaseAndContainerName(name, tag); + } + } + + private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) { IList exceptionsForContainerAttribute = new List { From 68b980523bd89fa4b298b1589e6d7d5148df3748 Mon Sep 17 00:00:00 2001 From: aavasthy <113193425+aavasthy@users.noreply.github.com> Date: Wed, 2 Nov 2022 13:39:44 -0400 Subject: [PATCH 005/337] Diagnostics: Removes unused properties and reduces size (#3519) * Remove starttime and id from diagnostics string * Remove starttime and id from diagnostics string * Update xml files for trace baseline tests * Update xml files for trace baseline tests * Update xml files for trace baseline tests * Whitespaces update * Changed starttime position based on code review Co-authored-by: Matias Quaranta --- .../Tracing/TraceWriter.TraceJsonWriter.cs | 12 +- ...iterBaselineTests.BatchOperationsAsync.xml | 21 - ...riterBaselineTests.BulkOperationsAsync.xml | 411 -------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 771 -------------- ...eWriterBaselineTests.MiscellanousAsync.xml | 34 - ...neTests.PointOperationsExceptionsAsync.xml | 210 ---- ...EndTraceWriterBaselineTests.QueryAsync.xml | 993 ------------------ ...TraceWriterBaselineTests.ReadFeedAsync.xml | 556 ---------- ...TraceWriterBaselineTests.ReadManyAsync.xml | 284 ----- ...selineTests.StreamPointOperationsAsync.xml | 52 - ...aselineTests.TypedPointOperationsAsync.xml | 68 -- ...raceWriterBaselineTests.ScenariosAsync.xml | 473 --------- ...TraceWriterBaselineTests.Serialization.xml | 33 - .../TraceWriterBaselineTests.TraceData.xml | 7 - 14 files changed, 5 insertions(+), 3920 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs index b38c5a948a..a190f2e5e2 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs @@ -41,16 +41,14 @@ public static void WriteTrace( SummaryDiagnostics summaryDiagnostics = new SummaryDiagnostics(trace); summaryDiagnostics.WriteSummaryDiagnostics(writer); } - writer.WriteFieldName("name"); writer.WriteStringValue(trace.Name); - writer.WriteFieldName("id"); - writer.WriteStringValue(trace.Id.ToString()); - - writer.WriteFieldName("start time"); - writer.WriteStringValue(trace.StartTime.ToString("hh:mm:ss:fff")); - + if (isRootTrace) + { + writer.WriteFieldName("start time"); + writer.WriteStringValue(trace.StartTime.ToString("hh:mm:ss:fff")); + } writer.WriteFieldName("duration in milliseconds"); writer.WriteNumber64Value(trace.Duration.TotalMilliseconds); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index f2df88ec68..49f8d13a83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -61,7 +61,6 @@ @@ -72,7 +71,6 @@ Date: Wed, 2 Nov 2022 15:24:30 -0700 Subject: [PATCH 006/337] [Internal] docs: Add address caches conceptual flow (#3534) * Rough draft * Some more changes * Adding a new section * Some more refinement * Some changes Lets get the feedback * Some MISC changes --- docs/SdkDesign.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/docs/SdkDesign.md b/docs/SdkDesign.md index e1be7d282a..f277661544 100644 --- a/docs/SdkDesign.md +++ b/docs/SdkDesign.md @@ -17,6 +17,74 @@ flowchart LR TransportClient <--> Service[(Cosmos DB Service)] ``` +## Address caches conceptual model + +![image](https://user-images.githubusercontent.com/6880899/199167007-bcc054c3-ecb1-4469-ba7d-eae52362e9cd.png) + + +- CollectionCache: Dictionary +- CollectionRoutingMap: Single collection PartitionKeyRanges map +- PartitionKeyRangeCache: Dictionary +- GlobalPartitionEndpointManager: Per partition override state. Every reqeust will flow throgh + - Today GlobalEndpointManager is at region scope only and doesn't look at the partition + - Ideal abstraction is to fold it into GlobalEndpointManager --> extra hash computation + - Posible to refactor direct code and flow HashedValue down stream (more contract work with direct package) +- AddressResolver: It does use IAddressCache (Above diagram missing it) + + +```mermaid +flowchart LR + subgraph CDB_account + subgraph CDB_Account_Endpoint + CDB_EP[[CosmosDB-Account/Endpoint]] + end + + subgraph CDB_Account_Region1 + CDBR1_GW[[CosmosDB-Account/Gateway/Region1]] + CDBR1_BE[[CosmosDB-Account/Backend/Region1]] + end + subgraph CDB_Account_RegionN + CDBRN_GW[[CosmosDB-Account/Gateway/Region1]] + CDBRN_BE[[CosmosDB-Account/Backend/RegionN]] + end + end + subgraph AddressCaches + GAC1[GatewayAddressCache/R1] + GACN[GatewayAddressCache/RN] + + GAC1 --> |NonBlockingAsyncCache| CDBR1_GW + GAC1 -.-> CDBR1_BE + GACN --> |NonBlockingAsyncCache| CDBRN_GW + GACN -.-> CDBRN_BE + end +``` + +### Sequence of interaction + +```mermaid +sequenceDiagram + GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) + GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) + GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion).AddressResolver + + critical RegularAddressResolution(Implicit contract of dsr.RequestContext.ResolvedPartitionKeyRange population) + GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) + AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation + end + + critical AnyPerpartitionOverrides + GlobalAddressResolver->>GlobalPartitionEndpointManager: TryAddPartitionLevelLocationOverride(DocumentServiceRequest) + GlobalPartitionEndpointManager-->>GlobalAddressResolver: (bool, DSR.RequestContext.RouteToLocation) + + option YES + GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) + GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) + end + GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion) + GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) + AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation +``` + ## Handler pipeline The handler pipeline processes the RequestMessage and each handler can choose to augment it in different ways, as shown in our [handler samples](../Microsoft.Azure.Cosmos.Samples/Usage/Handlers/) and also handle certain error conditions and retry, like our own [RetryHandler](../Microsoft.Azure.Cosmos/src/Handler/RetryHandler.cs). The RetryHandler will handle any failures from the [Transport layer](#transport) that should be [handled as regional failovers](#cross-region-retries). From 6762e07ed50757954043c79624f0d3e9a185e9d1 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Thu, 3 Nov 2022 13:47:15 -0700 Subject: [PATCH 007/337] Release: Adds SDK version and changelog for 3.31.2 (#3546) * Bumped SDK version and changelog * Added contracts file for 3.31.2 --- Directory.Build.props | 4 +- .../contracts/API_3.31.2.txt | 1476 +++++++++++++++++ changelog.md | 6 + 3 files changed, 1484 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.31.2.txt diff --git a/Directory.Build.props b/Directory.Build.props index d95c118656..651e1f89e5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.31.1 - 3.31.1 + 3.31.2 + 3.31.2 preview 3.29.4 2.0.0 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.31.2.txt b/Microsoft.Azure.Cosmos/contracts/API_3.31.2.txt new file mode 100644 index 0000000000..9227774985 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.31.2.txt @@ -0,0 +1,1476 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 186c764c81..add5a1de66 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.31.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.2) - 2022-11-03 +### [3.31.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.2-preview) - 2022-11-03 + +#### Fixed +- [#3525](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3525) Query: Fixes performance regression on target partition on some ORDER BY queries with continuation + ### [3.31.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.1) - 2022-10-29 ### [3.31.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.1-preview) - 2022-10-29 From ef7339ec793eb9b91ea566cf7f1e12a7ec934c7c Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Fri, 4 Nov 2022 10:52:54 -0700 Subject: [PATCH 008/337] [Internal] Documentation: Removes invalid comment from ReadThroughputAsync (#3516) --- Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs b/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs index a13f5224a4..a59dcb8be9 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs @@ -124,9 +124,6 @@ public abstract Task DeleteAsync( /// /// The provisioned throughput for this database. /// - /// - /// Null value indicates a database with no throughput provisioned. - /// /// Request Units /// Set throughput on a database /// From 825595a431a641368ea75b0401b56278d99be6fb Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Mon, 7 Nov 2022 10:53:55 -0800 Subject: [PATCH 009/337] [Internal] nugetconfig: Removes specific overrides (#3551) --- Microsoft.Azure.Cosmos.Samples/Usage/NuGet.config | 6 ------ NuGet.config | 6 ------ 2 files changed, 12 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/NuGet.config delete mode 100644 NuGet.config diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/NuGet.config b/Microsoft.Azure.Cosmos.Samples/Usage/NuGet.config deleted file mode 100644 index cbb81b2617..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Usage/NuGet.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/NuGet.config b/NuGet.config deleted file mode 100644 index cbb81b2617..0000000000 --- a/NuGet.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - From 4746a6fecc19c5b7e7f6ee602b3970298aa68e25 Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 8 Nov 2022 18:28:44 -0800 Subject: [PATCH 010/337] Query: Fixes partition range evaluation for spatial queries (#3495) * Initial commit * Update. * Pull/Rebase * Addressed comments. * Build fix --- .../CosmosQueryExecutionContextFactory.cs | 1 + .../QueryClient/ContainerQueryProperties.cs | 5 +- .../Core/QueryClient/CosmosQueryClient.cs | 1 + .../Core/QueryPlan/QueryPartitionProvider.cs | 12 +- .../Query/Core/QueryPlan/QueryPlanHandler.cs | 6 + .../Core/QueryPlan/QueryPlanRetriever.cs | 2 + .../DefaultDocumentQueryExecutionContext.cs | 1 + .../DocumentQueryExecutionContextBase.cs | 2 + .../DocumentQueryExecutionContextFactory.cs | 1 + .../Query/v3Query/CosmosQueryClientCore.cs | 7 +- .../Resource/Container/ContainerCore.Items.cs | 2 + .../Resource/Container/ContainerInternal.cs | 1 + .../src/Routing/PartitionRoutingHelper.cs | 4 +- .../CosmosItemTests.cs | 3 +- .../FeedToken/QueryFeedTokenTests.cs | 3 +- .../Query/PartitioningQueryTests.cs | 85 +++ .../Query/QueryTestsBase.cs | 75 ++- .../Query/SanityQueryTests.cs | 9 +- .../Utils/NonPartitionedContainerHelper.cs | 10 +- .../Query/ParsingBenchmark.cs | 3 +- .../QueryPlanBaselineTests.Spatial.xml | 548 ++++++++++++++++++ .../Microsoft.Azure.Cosmos.Tests.csproj | 3 + ...misticDirectExecutionQueryBaselineTests.cs | 5 +- .../Query/Pipeline/FullPipelineTests.cs | 3 +- .../Query/QueryPartitionProviderTests.cs | 6 +- .../Query/QueryPlanBaselineTests.cs | 48 +- .../Query/QueryPlanRetrieverTests.cs | 4 + .../Routing/PartitionRoutingHelperTest.cs | 1 + .../Tracing/TraceWriterBaselineTests.cs | 3 +- 29 files changed, 805 insertions(+), 49 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 21b512166e..fec5fa4d4a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -248,6 +248,7 @@ private static async Task> TryCreateCoreContextAsy cosmosQueryContext.ResourceTypeEnum, partitionKeyDefinition, inputParameters.PartitionKey != null, + containerQueryProperties.GeospatialType, cosmosQueryContext.UseSystemPrefix, createQueryPipelineTrace, cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs index 4d80412388..0baaceb9c6 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs @@ -11,15 +11,18 @@ internal readonly struct ContainerQueryProperties public ContainerQueryProperties( string resourceId, string effectivePartitionKeyString, - PartitionKeyDefinition partitionKeyDefinition) + PartitionKeyDefinition partitionKeyDefinition, + Cosmos.GeospatialType geospatialType) { this.ResourceId = resourceId; this.EffectivePartitionKeyString = effectivePartitionKeyString; this.PartitionKeyDefinition = partitionKeyDefinition; + this.GeospatialType = geospatialType; } public string ResourceId { get; } public string EffectivePartitionKeyString { get; } public PartitionKeyDefinition PartitionKeyDefinition { get; } + public Cosmos.GeospatialType GeospatialType { get; } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs index e066ec2140..c2bcf91619 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs @@ -47,6 +47,7 @@ public abstract Task> TryGetPartitionedQ bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, + Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken); public abstract Task> ExecuteItemQueryAsync( diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs index 8d09a074c9..6e7b0b4a8f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs @@ -118,7 +118,8 @@ public TryCatch TryGetPartitionedQueryExecutionIn bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, - bool useSystemPrefix) + bool useSystemPrefix, + GeospatialType geospatialType) { TryCatch tryGetInternalQueryInfo = this.TryGetPartitionedQueryExecutionInfoInternal( querySpecJsonString: querySpecJsonString, @@ -128,7 +129,8 @@ public TryCatch TryGetPartitionedQueryExecutionIn allowNonValueAggregateQuery: allowNonValueAggregateQuery, hasLogicalPartitionKey: hasLogicalPartitionKey, allowDCount: allowDCount, - useSystemPrefix: useSystemPrefix); + useSystemPrefix: useSystemPrefix, + geospatialType: geospatialType); if (!tryGetInternalQueryInfo.Succeeded) { return TryCatch.FromException(tryGetInternalQueryInfo.Exception); @@ -169,7 +171,8 @@ internal TryCatch TryGetPartitionedQueryE bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, - bool useSystemPrefix) + bool useSystemPrefix, + GeospatialType geospatialType) { if (querySpecJsonString == null || partitionKeyDefinition == null) { @@ -200,7 +203,6 @@ internal TryCatch TryGetPartitionedQueryE } PartitionKind partitionKind = partitionKeyDefinition.Kind; - GeospatialType defaultGeopatialType = GeospatialType.Geography; this.Initialize(); @@ -219,7 +221,7 @@ internal TryCatch TryGetPartitionedQueryE bIsContinuationExpected = Convert.ToInt32(isContinuationExpected), bRequireFormattableOrderByQuery = Convert.ToInt32(requireFormattableOrderByQuery), bUseSystemPrefix = Convert.ToInt32(useSystemPrefix), - eGeospatialType = Convert.ToInt32(defaultGeopatialType), + eGeospatialType = Convert.ToInt32(geospatialType), ePartitionKind = Convert.ToInt32(partitionKind) }; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanHandler.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanHandler.cs index e6f8ec06bf..30be0a4903 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanHandler.cs @@ -29,6 +29,7 @@ public async Task> TryGetQueryPlanAsync( QueryFeatures supportedQueryFeatures, bool hasLogicalPartitionKey, bool useSystemPrefix, + GeospatialType geospatialType, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -49,6 +50,7 @@ public async Task> TryGetQueryPlanAsync( partitionKeyDefinition, hasLogicalPartitionKey, useSystemPrefix, + geospatialType, cancellationToken); if (!tryGetQueryInfo.Succeeded) { @@ -76,6 +78,7 @@ public async Task> TryGetQueryPlanAsync( PartitionKeyDefinition partitionKeyDefinition, bool hasLogicalPartitionKey, bool useSystemPrefix, + GeospatialType geospatialType, CancellationToken cancellationToken = default) { if (sqlQuerySpec == null) @@ -96,6 +99,7 @@ public async Task> TryGetQueryPlanAsync( partitionKeyDefinition, hasLogicalPartitionKey, useSystemPrefix, + geospatialType, cancellationToken); if (tryGetQueryInfo.Failed) { @@ -114,6 +118,7 @@ private Task> TryGetQueryInfoAsync( PartitionKeyDefinition partitionKeyDefinition, bool hasLogicalPartitionKey, bool useSystemPrefix, + Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); @@ -128,6 +133,7 @@ private Task> TryGetQueryInfoAsync( hasLogicalPartitionKey: hasLogicalPartitionKey, allowDCount: true, useSystemPrefix: useSystemPrefix, + geospatialType: geospatialType, cancellationToken: cancellationToken); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs index 6a6d7d5777..32e061dfd8 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs @@ -38,6 +38,7 @@ public static async Task GetQueryPlanWithServiceI Documents.ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool hasLogicalPartitionKey, + GeospatialType geospatialType, bool useSystemPrefix, ITrace trace, CancellationToken cancellationToken = default) @@ -70,6 +71,7 @@ public static async Task GetQueryPlanWithServiceI QueryPlanRetriever.SupportedQueryFeatures, hasLogicalPartitionKey, useSystemPrefix, + geospatialType, cancellationToken); if (!tryGetQueryPlan.Succeeded) diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs index e3425f3199..b53c3c5c71 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs @@ -319,6 +319,7 @@ private static bool ServiceInteropAvailable() partitionKeyDefinition: partitionKeyDefinition, queryPartitionProvider: queryPartitionProvider, clientApiVersion: version, + geospatialType: collection.GeospatialConfig.GeospatialType, out QueryInfo _); } else if (request.Properties != null && request.Properties.TryGetValue( diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs index 52458f35f1..ec4e6d9185 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs @@ -160,6 +160,7 @@ public async Task GetPartitionedQueryExecutionInf bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, + Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -174,6 +175,7 @@ public async Task GetPartitionedQueryExecutionInf allowNonValueAggregateQuery: allowNonValueAggregateQuery, hasLogicalPartitionKey: hasLogicalPartitionKey, allowDCount: allowDCount, + geospatialType: geospatialType, useSystemPrefix: false); if (!tryGetPartitionedQueryExecutionInfo.Succeeded) { diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextFactory.cs index 63f17406c5..f7861f5a2c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextFactory.cs @@ -104,6 +104,7 @@ public static async Task CreateDocumentQueryExec allowNonValueAggregateQuery: true, hasLogicalPartitionKey: feedOptions.PartitionKey != null, allowDCount: true, + geospatialType: collection.GeospatialConfig.GeospatialType, cancellationToken: token); if (DocumentQueryExecutionContextFactory.ShouldCreateSpecializedDocumentQueryExecutionContext( diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index e541f51774..138f32c593 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -74,7 +74,8 @@ public override async Task GetCachedContainerQueryProp return new ContainerQueryProperties( containerProperties.ResourceId, effectivePartitionKeyString, - containerProperties.PartitionKey); + containerProperties.PartitionKey, + containerProperties.GeospatialConfig.GeospatialType); } public override async Task> TryGetPartitionedQueryExecutionInfoAsync( @@ -87,6 +88,7 @@ public override async Task> TryGetPartit bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, + Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { string queryString = null; @@ -109,7 +111,8 @@ public override async Task> TryGetPartit allowNonValueAggregateQuery: allowNonValueAggregateQuery, hasLogicalPartitionKey: hasLogicalPartitionKey, allowDCount: allowDCount, - useSystemPrefix: useSystemPrefix); + useSystemPrefix: useSystemPrefix, + geospatialType: geospatialType); } public override async Task> ExecuteItemQueryAsync( diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 60b8db6776..0018eca9b7 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -351,6 +351,7 @@ public override async Task TryExecuteQueryAsync( string continuationToken, FeedRangeInternal feedRangeInternal, QueryRequestOptions requestOptions, + GeospatialType geospatialType, CancellationToken cancellationToken = default) { if (queryDefinition == null) @@ -418,6 +419,7 @@ public override async Task TryExecuteQueryAsync( partitionKeyDefinition, requestOptions.PartitionKey.HasValue, useSystemPrefix: QueryIterator.IsSystemPrefixExpected(requestOptions), + geospatialType: geospatialType, cancellationToken); if (tryGetQueryInfoAndIfSupported.Failed) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index e6d21ba01a..920fc5d694 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -71,6 +71,7 @@ public abstract Task TryExecuteQueryAsync( string continuationToken, FeedRangeInternal feedRangeInternal, QueryRequestOptions requestOptions, + GeospatialType geospatialType, CancellationToken cancellationToken = default); public abstract FeedIterator GetStandByFeedIterator( diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionRoutingHelper.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionRoutingHelper.cs index a91c1dba5f..68f6214f17 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionRoutingHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionRoutingHelper.cs @@ -37,6 +37,7 @@ public static IReadOnlyList> GetProvidedPartitionKeyRanges( PartitionKeyDefinition partitionKeyDefinition, QueryPartitionProvider queryPartitionProvider, string clientApiVersion, + Cosmos.GeospatialType geospatialType, out QueryInfo queryInfo) { if (querySpecJsonString == null) @@ -62,7 +63,8 @@ public static IReadOnlyList> GetProvidedPartitionKeyRanges( allowNonValueAggregateQuery: allowNonValueAggregates, hasLogicalPartitionKey: hasLogicalPartitionKey, allowDCount: allowDCount, - useSystemPrefix: useSystemPrefix); + useSystemPrefix: useSystemPrefix, + geospatialType: geospatialType); if (!tryGetPartitionQueryExecutionInfo.Succeeded) { throw new BadRequestException(tryGetPartitionQueryExecutionInfo.Exception); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index ca6f1495f5..da6d79c333 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -1589,7 +1589,8 @@ public async Task ItemEpkQuerySingleKeyRangeValidation() ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties( containerResponse.Resource.ResourceId, null, - containerResponse.Resource.PartitionKey); + containerResponse.Resource.PartitionKey, + containerResponse.Resource.GeospatialConfig.GeospatialType); // There should only be one range since the EPK option is set. List partitionKeyRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs index 8e36c206f1..1e26ef0738 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs @@ -55,7 +55,8 @@ public async Task GetTargetPartitionKeyRangesAsyncWithFeedRange() ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties( containerResponse.Resource.ResourceId, null, - containerResponse.Resource.PartitionKey); + containerResponse.Resource.PartitionKey, + containerResponse.Resource.GeospatialConfig.GeospatialType); IReadOnlyList feedTokens = await container.GetFeedRangesAsync(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PartitioningQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PartitioningQueryTests.cs index c925c95d67..ed61b8fc8e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PartitioningQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PartitioningQueryTests.cs @@ -489,5 +489,90 @@ async Task ImplementationAsync( Assert.IsTrue(actualPartitionKeyValues.SetEquals(args.ExpectedPartitionKeyValues)); } } + + [TestMethod] + public async Task TestGeospatial() + { + string[] inputDocs = new[] + { + @"{""id"":""documentId1"",""key"":""A"",""prop"":3,""shortArray"":[{""a"":5}]}", + @"{""id"":""documentId2"",""key"":""A"",""prop"":2,""shortArray"":[{""a"":6}]}", + @"{""id"":""documentId3"",""key"":""A"",""prop"":1,""shortArray"":[{""a"":7}]}", + @"{""id"":""documentId4"",""key"":5,""prop"":3,""shortArray"":[{""a"":5}]}", + @"{""id"":""documentId5"",""key"":5,""prop"":2,""shortArray"":[{""a"":6}]}", + @"{""id"":""documentId6"",""key"":5,""prop"":1,""shortArray"":[{""a"":7}]}", + @"{""id"":""documentId10"",""prop"":3,""shortArray"":[{""a"":5}]}", + @"{""id"":""documentId11"",""prop"":2,""shortArray"":[{""a"":6}]}", + @"{""id"":""documentId12"",""prop"":1,""shortArray"":[{""a"":7}]}", + }; + + string All = "documentId4,documentId5,documentId6,documentId10,documentId11,documentId12,documentId1,documentId2,documentId3"; + string None = string.Empty; + var testVariations = new[] + { + new + { + Query = "SELECT c.id FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, {'type': 'Point', 'coordinates': [30, 10]}) > 66408.034483", + Expected = new Dictionary + { + { Cosmos.GeospatialType.Geography, All }, + { Cosmos.GeospatialType.Geometry, None }, + } + }, + new + { + Query = "SELECT c.id FROM c WHERE ST_ISVALID({'type': 'Polygon', 'coordinates': [[[-1000, 1000], [1000, 1000], [1000, 4000], [-1000, 4000], [-1000, 1000]]]})", + Expected = new Dictionary + { + { Cosmos.GeospatialType.Geography, None }, + { Cosmos.GeospatialType.Geometry, All }, + } + }, + new + { + Query = "SELECT * FROM c WHERE NOT ST_WITHIN({'type': 'Point', 'coordinates': [0, 40]}, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})", + Expected = new Dictionary + { + { Cosmos.GeospatialType.Geography, All }, + { Cosmos.GeospatialType.Geometry, None }, + } + }, + }; + + foreach (Cosmos.GeospatialType geospatialType in new[] { Cosmos.GeospatialType.Geography, Cosmos.GeospatialType.Geometry }) + { + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct, + CollectionTypes.MultiPartition, + inputDocs, + ImplementationAsync, + "/key", + geospatialType: geospatialType); + + async Task ImplementationAsync(Container container, IReadOnlyList documents) + { + foreach (var testVariation in testVariations) + { + string expectedResult = string.Join(",", testVariation.Expected[geospatialType]); + + FeedIterator resultSetIterator = container.GetItemQueryIterator( + queryText: testVariation.Query, + requestOptions: new QueryRequestOptions()); + + List result = new List(); + while (resultSetIterator.HasMoreResults) + { + result.AddRange(await resultSetIterator.ReadNextAsync()); + } + + string resultDocIds = string.Join(",", result.Select(doc => doc.Id)); + Assert.AreEqual( + expectedResult, + resultDocIds, + $"{Environment.NewLine}Query failed for geospatial type '{geospatialType}'{Environment.NewLine}{testVariation.Query}"); + } + } + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs index f40015473a..269e8448bd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs @@ -113,12 +113,14 @@ private async Task> GetPartitionKeyRanges(Conta private async Task CreateMultiPartitionContainer( string partitionKey = "/id", - Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null) + Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { ContainerResponse containerResponse = await this.CreatePartitionedContainer( throughput: 25000, partitionKey: partitionKey, - indexingPolicy: indexingPolicy); + indexingPolicy: indexingPolicy, + geospatialType); IReadOnlyList ranges = await this.GetPartitionKeyRanges(containerResponse); Assert.IsTrue( @@ -130,12 +132,14 @@ private async Task CreateMultiPartitionContainer( private async Task CreateSinglePartitionContainer( string partitionKey = "/id", - Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null) + Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { ContainerResponse containerResponse = await this.CreatePartitionedContainer( throughput: 4000, partitionKey: partitionKey, - indexingPolicy: indexingPolicy); + indexingPolicy: indexingPolicy, + geospatialType: geospatialType); Assert.IsNotNull(containerResponse); Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); @@ -149,13 +153,15 @@ private async Task CreateSinglePartitionContainer( } private async Task CreateNonPartitionedContainerAsync( - Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null) + Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { string containerName = Guid.NewGuid().ToString() + "container"; await NonPartitionedContainerHelper.CreateNonPartitionedContainer( this.database, containerName, - indexingPolicy == null ? null : JsonConvert.SerializeObject(indexingPolicy)); + indexingPolicy == null ? null : JsonConvert.SerializeObject(indexingPolicy), + geospatialType); return this.database.GetContainer(containerName); } @@ -163,7 +169,8 @@ await NonPartitionedContainerHelper.CreateNonPartitionedContainer( private async Task CreatePartitionedContainer( int throughput, string partitionKey = "/id", - Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null) + Microsoft.Azure.Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { // Assert that database exists (race deletes are possible when used concurrently) ResponseMessage responseMessage = await this.database.ReadStreamAsync(); @@ -192,7 +199,8 @@ private async Task CreatePartitionedContainer( { Paths = new Collection { partitionKey }, Kind = PartitionKind.Hash - } + }, + GeospatialConfig = new Cosmos.GeospatialConfig(geospatialType) }, // This throughput needs to be about half the max with multi master // otherwise it will create about twice as many partitions. @@ -208,50 +216,57 @@ private async Task CreatePartitionedContainer( private Task<(Container, IReadOnlyList)> CreateNonPartitionedContainerAndIngestDocumentsAsync( IEnumerable documents, - Cosmos.IndexingPolicy indexingPolicy = null) + Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { return this.CreateContainerAndIngestDocumentsAsync( CollectionTypes.NonPartitioned, documents, partitionKey: null, - indexingPolicy: indexingPolicy); + indexingPolicy: indexingPolicy, + geospatialType: geospatialType); } private Task<(Container, IReadOnlyList)> CreateSinglePartitionContainerAndIngestDocumentsAsync( IEnumerable documents, string partitionKey = "/id", - Cosmos.IndexingPolicy indexingPolicy = null) + Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { return this.CreateContainerAndIngestDocumentsAsync( CollectionTypes.SinglePartition, documents, partitionKey, - indexingPolicy); + indexingPolicy, + geospatialType); } private Task<(Container, IReadOnlyList)> CreateMultiPartitionContainerAndIngestDocumentsAsync( IEnumerable documents, string partitionKey = "/id", - Cosmos.IndexingPolicy indexingPolicy = null) + Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { return this.CreateContainerAndIngestDocumentsAsync( CollectionTypes.MultiPartition, documents, partitionKey, - indexingPolicy); + indexingPolicy, + geospatialType); } private async Task<(Container, IReadOnlyList)> CreateContainerAndIngestDocumentsAsync( CollectionTypes collectionType, IEnumerable documents, string partitionKey = "/id", - Cosmos.IndexingPolicy indexingPolicy = null) + Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { Container container = collectionType switch { - CollectionTypes.NonPartitioned => await this.CreateNonPartitionedContainerAsync(indexingPolicy), - CollectionTypes.SinglePartition => await this.CreateSinglePartitionContainer(partitionKey, indexingPolicy), - CollectionTypes.MultiPartition => await this.CreateMultiPartitionContainer(partitionKey, indexingPolicy), + CollectionTypes.NonPartitioned => await this.CreateNonPartitionedContainerAsync(indexingPolicy, geospatialType), + CollectionTypes.SinglePartition => await this.CreateSinglePartitionContainer(partitionKey, indexingPolicy, geospatialType), + CollectionTypes.MultiPartition => await this.CreateMultiPartitionContainer(partitionKey, indexingPolicy, geospatialType), _ => throw new ArgumentException($"Unknown {nameof(CollectionTypes)} : {collectionType}"), }; List insertedDocuments = new List(); @@ -369,7 +384,8 @@ internal Task CreateIngestQueryDeleteAsync( Query query, string partitionKey = "/id", Cosmos.IndexingPolicy indexingPolicy = null, - CosmosClientFactory cosmosClientFactory = null) + CosmosClientFactory cosmosClientFactory = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { Task queryWrapper(Container container, IReadOnlyList inputDocuments, object throwaway) { @@ -384,7 +400,8 @@ Task queryWrapper(Container container, IReadOnlyList inputDocument null, partitionKey, indexingPolicy, - cosmosClientFactory); + cosmosClientFactory, + geospatialType); } internal Task CreateIngestQueryDeleteAsync( @@ -395,7 +412,8 @@ internal Task CreateIngestQueryDeleteAsync( T testArgs, string partitionKey = "/id", Cosmos.IndexingPolicy indexingPolicy = null, - CosmosClientFactory cosmosClientFactory = null) + CosmosClientFactory cosmosClientFactory = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { return this.CreateIngestQueryDeleteAsync( connectionModes, @@ -405,7 +423,8 @@ internal Task CreateIngestQueryDeleteAsync( cosmosClientFactory ?? this.CreateDefaultCosmosClient, testArgs, partitionKey, - indexingPolicy); + indexingPolicy, + geospatialType); } /// @@ -434,7 +453,8 @@ internal async Task CreateIngestQueryDeleteAsync( CosmosClientFactory cosmosClientFactory, T testArgs, string partitionKey = "/id", - Cosmos.IndexingPolicy indexingPolicy = null) + Cosmos.IndexingPolicy indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { try { @@ -450,15 +470,18 @@ internal async Task CreateIngestQueryDeleteAsync( { CollectionTypes.NonPartitioned => this.CreateNonPartitionedContainerAndIngestDocumentsAsync( documents, - indexingPolicy), + indexingPolicy, + geospatialType), CollectionTypes.SinglePartition => this.CreateSinglePartitionContainerAndIngestDocumentsAsync( documents, partitionKey, - indexingPolicy), + indexingPolicy, + geospatialType), CollectionTypes.MultiPartition => this.CreateMultiPartitionContainerAndIngestDocumentsAsync( documents, partitionKey, - indexingPolicy), + indexingPolicy, + geospatialType), _ => throw new ArgumentException($"Unknown {nameof(CollectionTypes)} : {collectionType}"), }; collectionsAndDocuments.Add(await createContainerTask); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index bc04ba6ebe..60ab6f9fe4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -604,7 +604,8 @@ private async Task TestTryExecuteQueryHelper( MaxItemCount = maxItemCount, }, feedRangeInternal: null, - continuationToken: continuationToken); + continuationToken: continuationToken, + geospatialType: Cosmos.GeospatialType.Geography); if (canSupportExpected) { @@ -637,7 +638,8 @@ private async Task TestTryExecuteQueryHelper( MaxItemCount = 1, }, feedRangeInternal: null, - continuationToken: null); + continuationToken: null, + geospatialType: Cosmos.GeospatialType.Geography); Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.FailedToGetQueryPlanResult); } @@ -653,7 +655,8 @@ private async Task TestTryExecuteQueryHelper( MaxItemCount = 1, }, feedRangeInternal: new FeedRangePartitionKeyRange("0"), // filtering on a PkRangeId. - continuationToken: null); + continuationToken: null, + geospatialType: Cosmos.GeospatialType.Geography); Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanIsSupportedResult); ContainerInternal.QueryPlanIsSupportedResult queryPlanIsSupportedResult = (ContainerInternal.QueryPlanIsSupportedResult)tryExecuteQueryResult; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/NonPartitionedContainerHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/NonPartitionedContainerHelper.cs index 8748360c9a..0482695ec2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/NonPartitionedContainerHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/NonPartitionedContainerHelper.cs @@ -18,7 +18,8 @@ internal static class NonPartitionedContainerHelper internal static async Task CreateNonPartitionedContainer( Cosmos.Database database, string containerId, - string indexingPolicy = null) + string indexingPolicy = null, + Cosmos.GeospatialType geospatialType = Cosmos.GeospatialType.Geography) { DocumentCollection documentCollection = new DocumentCollection() { @@ -30,6 +31,13 @@ internal static async Task CreateNonPartitionedContainer( documentCollection.IndexingPolicy = JsonConvert.DeserializeObject(indexingPolicy); } + documentCollection.GeospatialConfig = geospatialType switch + { + Cosmos.GeospatialType.Geography => new GeospatialConfig(GeospatialType.Geography), + Cosmos.GeospatialType.Geometry => new GeospatialConfig(GeospatialType.Geometry), + _ => throw new InvalidOperationException($"Unsupported geospatialType {geospatialType}") + }; + await NonPartitionedContainerHelper.CreateNonPartitionedContainer( database, documentCollection); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/ParsingBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/ParsingBenchmark.cs index 9ac18a7068..2a17267604 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/ParsingBenchmark.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/ParsingBenchmark.cs @@ -126,7 +126,8 @@ private static void ParseUsingNativeParser(SqlQuerySpec sqlQuerySpec) allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); tryGetQueryPlan.ThrowIfFailed(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml new file mode 100644 index 0000000000..1d67b08708 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml @@ -0,0 +1,548 @@ + + + + ST_DISTANCE Constant Foldable Geography + SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, {'type': 'Point', 'coordinates': [30, 10]}) > 66408.034483 + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_DISTANCE Constant Foldable Geometry + SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, {'type': 'Point', 'coordinates': [30, 10]}) > 66408.034483 + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],[]] + + + + + + + + + ST_DISTANCE Geography + SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, c.geojson) > 66408.034483 + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_DISTANCE Geometry + SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, c.geojson) > 66408.034483 + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_INTERSECTS Constant Foldable Geography + SELECT * FROM c WHERE ST_INTERSECTS({'type':'LineString', 'coordinates':[ [ 0, 0 ], [ 0, 40 ] ]}, {'type':'Polygon',"coordinates":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],[]] + + + + + + + + + ST_INTERSECTS Constant Foldable Geometry + SELECT * FROM c WHERE ST_INTERSECTS({'type':'LineString', 'coordinates':[ [ 0, 0 ], [ 0, 40 ] ]}, {'type':'Polygon',"coordinates":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_INTERSECTS Geography + SELECT * FROM c WHERE ST_INTERSECTS(c.geojson, {'type':'Polygon',"coordinates":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_INTERSECTS Geometry + SELECT * FROM c WHERE ST_INTERSECTS(c.geojson, {'type':'Polygon',"coordinates":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_ISVALID Constant Foldable Geography + SELECT * FROM c WHERE ST_ISVALID({'type': 'Polygon', 'coordinates': [[[-1000, 1000], [1000, 1000], [1000, 4000], [-1000, 4000], [-1000, 1000]]]}) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],[]] + + + + + + + + + ST_ISVALID Constant Foldable Geometry + SELECT * FROM c WHERE ST_ISVALID({'type': 'Polygon', 'coordinates': [[[-1000, 1000], [1000, 1000], [1000, 4000], [-1000, 4000], [-1000, 1000]]]}) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_ISVALID Geography + SELECT * FROM c WHERE ST_ISVALID(c.geojson) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_ISVALID Geometry + SELECT * FROM c WHERE ST_ISVALID(c.geojson) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_WITHIN Constant Foldable Geography + SELECT * FROM c WHERE NOT ST_WITHIN({'type': 'Point', 'coordinates': [0, 40]}, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_WITHIN Constant Foldable Geometry + SELECT * FROM c WHERE NOT ST_WITHIN({'type': 'Point', 'coordinates': [0, 40]}, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],[]] + + + + + + + + + ST_WITHIN Geography + SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, + {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geography + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + + + ST_WITHIN Geometry + SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, + {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + + /key + + Hash + Geometry + + + + + None + + + + + + + + + + False + + + + [[],"Infinity") + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 2fe8b7feec..ef7e193dbf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -222,6 +222,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index c2ac15064d..960235dcae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -388,7 +388,8 @@ private static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(st allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); return tryGetQueryPlan.Result; } @@ -611,7 +612,7 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, CancellationToken cancellationToken) + public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { throw new NotImplementedException(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index e1cc776d4f..0f8f6f2be7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -421,7 +421,8 @@ private static QueryInfo GetQueryPlan(string query) allowNonValueAggregateQuery: true, allowDCount: true, hasLogicalPartitionKey: false, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); info.ThrowIfFailed(); return info.Result.QueryInfo; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionProviderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionProviderTests.cs index ccd7a81dfd..e4e6f48846 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionProviderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionProviderTests.cs @@ -39,7 +39,8 @@ public void TestQueryPartitionProviderUpdate() allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); Assert.IsTrue(tryGetQueryPlan.Failed); Assert.IsTrue(tryGetQueryPlan.Exception.ToString().Contains("The SQL query text exceeded the maximum limit of 5 characters")); @@ -54,7 +55,8 @@ public void TestQueryPartitionProviderUpdate() allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); Assert.IsTrue(tryGetQueryPlan.Succeeded); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs index dbdace2923..79d674d7b9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs @@ -15,6 +15,7 @@ using System.Linq; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Serialization.HybridRow.Schemas; /// /// Tests for . @@ -1292,6 +1293,44 @@ public void SystemFunctions() this.ExecuteTestSuite(testVariations); } + [TestMethod] + [Owner("adityasa")] + public void Spatial() + { + var variations = new[] + { + // ST_DISTANCE + new { Description = @"ST_DISTANCE Constant Foldable", Query = @"SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, {'type': 'Point', 'coordinates': [30, 10]}) > 66408.034483" }, + new { Description = @"ST_DISTANCE", Query = @"SELECT * FROM c WHERE ST_DISTANCE({'type': 'Polygon', 'coordinates': [[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]], [[20, 30], [35, 35], [30, 20], [20, 30]]]}, c.geojson) > 66408.034483" }, + + // ST_INTERSECTS + new { Description = @"ST_INTERSECTS Constant Foldable", Query = @"SELECT * FROM c WHERE ST_INTERSECTS({'type':'LineString', 'coordinates':[ [ 0, 0 ], [ 0, 40 ] ]}, {'type':'Polygon',""coordinates"":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})" }, + new { Description = @"ST_INTERSECTS", Query = @"SELECT * FROM c WHERE ST_INTERSECTS(c.geojson, {'type':'Polygon',""coordinates"":[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})" }, + + // ST_ISVALID + new { Description = @"ST_ISVALID Constant Foldable", Query = @"SELECT * FROM c WHERE ST_ISVALID({'type': 'Polygon', 'coordinates': [[[-1000, 1000], [1000, 1000], [1000, 4000], [-1000, 4000], [-1000, 1000]]]})" }, + new { Description = @"ST_ISVALID", Query = @"SELECT * FROM c WHERE ST_ISVALID(c.geojson)" }, + + // ST_WITHIN + new { Description = @"ST_WITHIN Constant Foldable", Query = @"SELECT * FROM c WHERE NOT ST_WITHIN({'type': 'Point', 'coordinates': [0, 40]}, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})" }, + new { Description = @"ST_WITHIN", Query = @"SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]})" }, + }; + + List testVariations = variations + .SelectMany(variation => + { + PartitionKeyDefinition pkDefinitions = CreateHashPartitionKey("/key"); + return new List + { + new QueryPlanBaselineTestInput($"{variation.Description} Geography", pkDefinitions, new SqlQuerySpec(variation.Query)) { GeospatialType = Cosmos.GeospatialType.Geography }, + new QueryPlanBaselineTestInput($"{variation.Description} Geometry", pkDefinitions, new SqlQuerySpec(variation.Query)) { GeospatialType = Cosmos.GeospatialType.Geometry } + }; + }) + .ToList(); + + this.ExecuteTestSuite(testVariations); + } + private static PartitionKeyDefinition CreateHashPartitionKey( params string[] partitionKeys) => new PartitionKeyDefinition() { @@ -1386,7 +1425,8 @@ public override QueryPlanBaselineTestOutput ExecuteTest(QueryPlanBaselineTestInp allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: input.GeospatialType ?? Cosmos.GeospatialType.Geography); if (info.Failed) { @@ -1401,6 +1441,7 @@ public sealed class QueryPlanBaselineTestInput : BaselineTestInput { internal PartitionKeyDefinition PartitionKeyDefinition { get; set; } internal SqlQuerySpec SqlQuerySpec { get; set; } + internal Cosmos.GeospatialType? GeospatialType { get; set; } internal QueryPlanBaselineTestInput( string description, @@ -1434,6 +1475,11 @@ public override void SerializeAsXml(XmlWriter xmlWriter) this.PartitionKeyDefinition.Kind == PartitionKind.MultiHash ? "MultiHash" : "Range")); } + if (this.GeospatialType != null) + { + xmlWriter.WriteElementString("GeospatialType", this.GeospatialType.Value.ToString()); + } + if (this.SqlQuerySpec.ShouldSerializeParameters()) { xmlWriter.WriteStartElement("QueryParameters"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs index ffad405d08..47a681eb1a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs @@ -38,6 +38,7 @@ public async Task ServiceInterop_BadRequestContainsInnerException() It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny())).ReturnsAsync(TryCatch.FromException(innerException)); Mock trace = new Mock(); @@ -47,6 +48,7 @@ public async Task ServiceInterop_BadRequestContainsInnerException() ResourceType.Document, new Documents.PartitionKeyDefinition() { Paths = new Collection() { "/id" } }, hasLogicalPartitionKey: false, + geospatialType: Cosmos.GeospatialType.Geography, useSystemPrefix: false, trace.Object, default)); @@ -73,6 +75,7 @@ public async Task ServiceInterop_BadRequestContainsOriginalCosmosException() It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny())).ReturnsAsync(TryCatch.FromException(expectedException)); Mock trace = new Mock(); @@ -82,6 +85,7 @@ public async Task ServiceInterop_BadRequestContainsOriginalCosmosException() ResourceType.Document, new Documents.PartitionKeyDefinition() { Paths = new Collection() { "/id" } }, hasLogicalPartitionKey: false, + geospatialType: Cosmos.GeospatialType.Geography, useSystemPrefix: false, trace.Object, default)); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs index 0201b92327..35ffaa65bb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs @@ -348,6 +348,7 @@ FROM c partitionKeyDefinition: new PartitionKeyDefinition { Paths = new Collection { testcase.PartitionKey }, Kind = PartitionKind.Hash }, queryPartitionProvider: QueryPartitionProviderTestInstance.Object, clientApiVersion: testcase.ClientApiVersion, + geospatialType: Cosmos.GeospatialType.Geography, out QueryInfo info); Assert.Fail(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index 2421060b65..eace2eb9df 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -815,7 +815,8 @@ private static QueryInfo GetQueryPlan(string query) allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, - useSystemPrefix: false); + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); info.ThrowIfFailed(); return info.Result.QueryInfo; From acd899e5c0be882c5e962103cc626ee8495a07a8 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 9 Nov 2022 11:04:47 -0800 Subject: [PATCH 011/337] [Internal] Documentation: Refactors cache content on its own document (#3554) * Add cache file * Moving content away --- docs/SdkDesign.md | 76 ++++------------------------------------------- docs/caches.md | 67 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 70 deletions(-) create mode 100644 docs/caches.md diff --git a/docs/SdkDesign.md b/docs/SdkDesign.md index f277661544..f3f2ec1581 100644 --- a/docs/SdkDesign.md +++ b/docs/SdkDesign.md @@ -17,74 +17,6 @@ flowchart LR TransportClient <--> Service[(Cosmos DB Service)] ``` -## Address caches conceptual model - -![image](https://user-images.githubusercontent.com/6880899/199167007-bcc054c3-ecb1-4469-ba7d-eae52362e9cd.png) - - -- CollectionCache: Dictionary -- CollectionRoutingMap: Single collection PartitionKeyRanges map -- PartitionKeyRangeCache: Dictionary -- GlobalPartitionEndpointManager: Per partition override state. Every reqeust will flow throgh - - Today GlobalEndpointManager is at region scope only and doesn't look at the partition - - Ideal abstraction is to fold it into GlobalEndpointManager --> extra hash computation - - Posible to refactor direct code and flow HashedValue down stream (more contract work with direct package) -- AddressResolver: It does use IAddressCache (Above diagram missing it) - - -```mermaid -flowchart LR - subgraph CDB_account - subgraph CDB_Account_Endpoint - CDB_EP[[CosmosDB-Account/Endpoint]] - end - - subgraph CDB_Account_Region1 - CDBR1_GW[[CosmosDB-Account/Gateway/Region1]] - CDBR1_BE[[CosmosDB-Account/Backend/Region1]] - end - subgraph CDB_Account_RegionN - CDBRN_GW[[CosmosDB-Account/Gateway/Region1]] - CDBRN_BE[[CosmosDB-Account/Backend/RegionN]] - end - end - subgraph AddressCaches - GAC1[GatewayAddressCache/R1] - GACN[GatewayAddressCache/RN] - - GAC1 --> |NonBlockingAsyncCache| CDBR1_GW - GAC1 -.-> CDBR1_BE - GACN --> |NonBlockingAsyncCache| CDBRN_GW - GACN -.-> CDBRN_BE - end -``` - -### Sequence of interaction - -```mermaid -sequenceDiagram - GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) - GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) - GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion).AddressResolver - - critical RegularAddressResolution(Implicit contract of dsr.RequestContext.ResolvedPartitionKeyRange population) - GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) - AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation - end - - critical AnyPerpartitionOverrides - GlobalAddressResolver->>GlobalPartitionEndpointManager: TryAddPartitionLevelLocationOverride(DocumentServiceRequest) - GlobalPartitionEndpointManager-->>GlobalAddressResolver: (bool, DSR.RequestContext.RouteToLocation) - - option YES - GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) - GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) - end - GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion) - GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) - AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation -``` - ## Handler pipeline The handler pipeline processes the RequestMessage and each handler can choose to augment it in different ways, as shown in our [handler samples](../Microsoft.Azure.Cosmos.Samples/Usage/Handlers/) and also handle certain error conditions and retry, like our own [RetryHandler](../Microsoft.Azure.Cosmos/src/Handler/RetryHandler.cs). The RetryHandler will handle any failures from the [Transport layer](#transport) that should be [handled as regional failovers](#cross-region-retries). @@ -234,6 +166,12 @@ flowchart ``` +## Direct mode caches + +Per our [connectivity documentation](https://learn.microsoft.com/azure/cosmos-db/nosql/sdk-connection-modes#routing), the SDK will store, in internal caches, critical information to allow for request routing. + +For details on the caches, please see the [cache design documentation](caches.md). + ## Consistency (direct mode) When performing operations through Direct mode, the SDK is involved in checking consistency for Bounded Staleness and Strong accounts. Read requests are handled by the [ConsistencyReader](https://github.com/Azure/azure-cosmos-dotnet-v3/blob/msdata/direct/Microsoft.Azure.Cosmos/src/direct/ConsistencyReader.cs) and write requests are handled by the [ConsistencyWriter](https://github.com/Azure/azure-cosmos-dotnet-v3/blob/msdata/direct/Microsoft.Azure.Cosmos/src/direct/ConsistencyWriter.cs). The `ConsistencyReader` uses the [QuorumReader](https://github.com/Azure/azure-cosmos-dotnet-v3/blob/msdata/direct/Microsoft.Azure.Cosmos/src/direct/QuorumReader.cs) when the consistency is Bounded Staleness or Strong to verify quorum after performing two requests and comparing the LSNs. If quorum cannot be achieved, the SDK starts what is defined as "barrier requests" to the container and waits for it to achieve quorum. The `ConsistencyWriter` also performs a similar LSN check after receiving the response from the write, the `GlobalCommittedLSN` and the item `LSN`. If they don't match, barrier requests are also performed. @@ -248,5 +186,3 @@ flowchart LR ConsistencyWriter --> TCPClient ``` - - diff --git a/docs/caches.md b/docs/caches.md new file mode 100644 index 0000000000..91f5eea16f --- /dev/null +++ b/docs/caches.md @@ -0,0 +1,67 @@ +# Caches conceptual model + +![image](https://user-images.githubusercontent.com/6880899/199167007-bcc054c3-ecb1-4469-ba7d-eae52362e9cd.png) + + +- CollectionCache: Dictionary +- CollectionRoutingMap: Single collection PartitionKeyRanges map +- PartitionKeyRangeCache: Dictionary +- GlobalPartitionEndpointManager: Per partition override state. Every request will flow through + - Today GlobalEndpointManager is at region scope only and doesn't look at the partition + - Ideal abstraction is to fold it into GlobalEndpointManager --> extra hash computation + - Posible to refactor direct code and flow HashedValue down stream (more contract work with direct package) +- AddressResolver: It does use IAddressCache (Above diagram missing it) + + +```mermaid +flowchart LR + subgraph CDB_account + subgraph CDB_Account_Endpoint + CDB_EP[[CosmosDB-Account/Endpoint]] + end + + subgraph CDB_Account_Region1 + CDBR1_GW[[CosmosDB-Account/Gateway/Region1]] + CDBR1_BE[[CosmosDB-Account/Backend/Region1]] + end + subgraph CDB_Account_RegionN + CDBRN_GW[[CosmosDB-Account/Gateway/Region1]] + CDBRN_BE[[CosmosDB-Account/Backend/RegionN]] + end + end + subgraph AddressCaches + GAC1[GatewayAddressCache/R1] + GACN[GatewayAddressCache/RN] + + GAC1 --> |NonBlockingAsyncCache| CDBR1_GW + GAC1 -.-> CDBR1_BE + GACN --> |NonBlockingAsyncCache| CDBRN_GW + GACN -.-> CDBRN_BE + end +``` + +## Sequence of interaction + +```mermaid +sequenceDiagram + GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) + GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) + GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion).AddressResolver + + critical RegularAddressResolution(Implicit contract of dsr.RequestContext.ResolvedPartitionKeyRange population) + GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) + AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation + end + + critical AnyPerpartitionOverrides + GlobalAddressResolver->>GlobalPartitionEndpointManager: TryAddPartitionLevelLocationOverride(DocumentServiceRequest) + GlobalPartitionEndpointManager-->>GlobalAddressResolver: (bool, DSR.RequestContext.RouteToLocation) + + option YES + GlobalAddressResolver->>GlobalEndpointManager: ResolveServiceEndpoint(DocumentServiceRequest) + GlobalEndpointManager-->>GlobalAddressResolver: URI (ServingRegion) + end + GlobalAddressResolver->>GlobalAddressResolver: GetEndpointCache(ServingRegion) + GlobalAddressResolver->>AddressResolver: ResolveAsync(DocumentServiceRequest) + AddressResolver-->>GlobalAddressResolver: PartitionAddressInformation +``` \ No newline at end of file From 01c1cd447d567f7f1f77daf1d7807e76f5b2face Mon Sep 17 00:00:00 2001 From: Fabian Meiswinkel Date: Thu, 10 Nov 2022 22:29:39 +0000 Subject: [PATCH 012/337] [Internal] Emulator unit tests: Adds IdEncoding unit tests for ComputeGateway (#3556) * Adding IdEncoding unit tests for ComputeGateway * Reacting to code review feedback * Updating md files --- CONTRIBUTING.md | 6 ++ ...ComputeGatewayCosmosItemIdEncodingTests.cs | 16 ++++++ .../CosmosItemIdEncodingTestsBase.cs | 57 +++++++++++++++---- ...outingGatewayCosmosItemIdEncodingTests.cs} | 5 +- .../Utils/BaseCosmosClientHelper.cs | 8 ++- .../Utils/TestCommon.cs | 12 ++-- .../settings.json | 2 + templates/emulator-setup.yml | 2 +- 8 files changed, 87 insertions(+), 21 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{GatewayCosmosItemIdEncodingTests.cs => RoutingGatewayCosmosItemIdEncodingTests.cs} (63%) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc1d06f852..e3cb1edc66 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -125,6 +125,12 @@ Or all through `Re-run failed checks` on the top right corner: ![Re-run all failures](docs/images/contributing-rerunall.png) +## Usage of Cosmos DB Emulator for running unit tests + +- - The same version of the emulator used in the CI pipelines can be downloaded [here](https://aka.ms/cosmosdb-emulator) +- More information about how ro use the emulator for development is documented [here](https://github.com/Azure/azure-documentdb-dotnet/blob/master/docs/documentdb-nosql-local-emulator.md) +- You can start the emulator with same parameters as the emulator unit tests in the CI pipeline via `.\CosmosDB.Emulator.exe /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint` + ## Troubleshooting - [General .NET SDK Troubleshooting](https://docs.microsoft.com/azure/cosmos-db/sql/troubleshoot-dot-net-sdk) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs new file mode 100644 index 0000000000..a3dcb8b52a --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputeGatewayCosmosItemIdEncodingTests.cs @@ -0,0 +1,16 @@ +namespace Microsoft.Azure.Cosmos +{ + using Microsoft.Azure.Cosmos.Fluent; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + + [TestClass] + public class ComputeGatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase + { + protected override string AccountEndpointOverride => Utils.ConfigurationManager.AppSettings["ComputeGatewayEndpoint"]; + + protected override void ConfigureClientBuilder(CosmosClientBuilder builder) + { + builder.WithConnectionModeGateway(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs index 36be8df06d..aef4323045 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs @@ -19,9 +19,13 @@ public abstract class CosmosItemIdEncodingTestsBase : BaseCosmosClientHelper encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); + private static readonly int computeGatewayPort = Int32.Parse(Utils.ConfigurationManager.AppSettings["ComputeGatewayPort"]); + private Container Container = null; private ContainerProperties containerSettings = null; + protected virtual String AccountEndpointOverride => null; + protected abstract void ConfigureClientBuilder(CosmosClientBuilder builder); [TestInitialize] @@ -29,7 +33,8 @@ public async Task TestInitialize() { await base.TestInit( validateSinglePartitionKeyRangeCacheCall: true, - customizeClientBuilder: this.ConfigureClientBuilder); + customizeClientBuilder: this.ConfigureClientBuilder, + accountEndpointOverride: this.AccountEndpointOverride); string PartitionKey = "/pk"; this.containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: PartitionKey); @@ -483,9 +488,17 @@ public async Task IdWithCarriageReturn() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -511,9 +524,17 @@ public async Task IdWithTab() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -539,9 +560,17 @@ public async Task IdWithLineFeed() { TransportMode = ConnectionMode.Gateway, ExpectedCreateStatusCode = HttpStatusCode.Created, - ExpectedReadStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedReplaceStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.OK, - ExpectedDeleteStatusCode = HttpStatusCode.BadRequest,// CGW - HttpStatusCode.NoContent, + ExpectedReadStatusCode = HttpStatusCode.BadRequest, + ExpectedReplaceStatusCode = HttpStatusCode.BadRequest, + ExpectedDeleteStatusCode = HttpStatusCode.BadRequest, + }, + ComputeGateway = new TestScenarioExpectations + { + TransportMode = ConnectionMode.Gateway, + ExpectedCreateStatusCode = HttpStatusCode.Created, + ExpectedReadStatusCode = HttpStatusCode.OK, + ExpectedReplaceStatusCode = HttpStatusCode.OK, + ExpectedDeleteStatusCode = HttpStatusCode.NoContent, }, Direct = new TestScenarioExpectations { @@ -559,8 +588,10 @@ public async Task IdWithLineFeed() private async Task ExecuteTestCase(TestScenario scenario) { TestScenarioExpectations expected = - this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? - scenario.Gateway : scenario.Direct; + this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Direct ? + scenario.Direct : + this.cosmosClient.Endpoint.Port == computeGatewayPort ? + scenario.ComputeGateway ?? scenario.Gateway : scenario.Gateway; Console.WriteLine($"Scenario: {scenario.Name}, Id: \"{scenario.Id}\""); @@ -671,6 +702,8 @@ private class TestScenario public TestScenarioExpectations Gateway { get; set; } + public TestScenarioExpectations ComputeGateway { get; set; } + public TestScenarioExpectations Direct { get; set; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs similarity index 63% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs index 5cd9e53a37..5052e629f5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayCosmosItemIdEncodingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/RoutingGatewayCosmosItemIdEncodingTests.cs @@ -4,11 +4,12 @@ using Microsoft.Azure.Cosmos.SDK.EmulatorTests; [TestClass] - public class GatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase + public class RoutingGatewayCosmosItemIdEncodingTests : CosmosItemIdEncodingTestsBase { protected override void ConfigureClientBuilder(CosmosClientBuilder builder) { - builder.WithConnectionModeGateway(); + builder + .WithConnectionModeGateway(); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs index ab4027925a..20f083d85d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs @@ -18,12 +18,16 @@ public abstract class BaseCosmosClientHelper public async Task TestInit( bool validateSinglePartitionKeyRangeCacheCall = false, - Action customizeClientBuilder = null) + Action customizeClientBuilder = null, + string accountEndpointOverride = null) { this.cancellationTokenSource = new CancellationTokenSource(); this.cancellationToken = this.cancellationTokenSource.Token; - this.cosmosClient = TestCommon.CreateCosmosClient(validatePartitionKeyRangeCalls: validateSinglePartitionKeyRangeCacheCall, customizeClientBuilder: customizeClientBuilder); + this.cosmosClient = TestCommon.CreateCosmosClient( + validatePartitionKeyRangeCalls: validateSinglePartitionKeyRangeCacheCall, + customizeClientBuilder: customizeClientBuilder, + accountEndpointOverride: accountEndpointOverride); this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: this.cancellationToken); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index e85f9c565c..265e9542ef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -75,10 +75,13 @@ internal static (string endpoint, string authKey) GetAccountInfo() internal static CosmosClientBuilder GetDefaultConfiguration( bool useCustomSeralizer = true, - bool validatePartitionKeyRangeCalls = false) + bool validatePartitionKeyRangeCalls = false, + string accountEndpointOverride = null) { (string endpoint, string authKey) = TestCommon.GetAccountInfo(); - CosmosClientBuilder clientBuilder = new CosmosClientBuilder(accountEndpoint: endpoint, authKeyOrResourceToken: authKey); + CosmosClientBuilder clientBuilder = new CosmosClientBuilder( + accountEndpoint: accountEndpointOverride ?? endpoint, + authKeyOrResourceToken: authKey); if (useCustomSeralizer) { clientBuilder.WithCustomSerializer(new CosmosJsonDotNetSerializer()); @@ -95,9 +98,10 @@ internal static CosmosClientBuilder GetDefaultConfiguration( internal static CosmosClient CreateCosmosClient( Action customizeClientBuilder = null, bool useCustomSeralizer = true, - bool validatePartitionKeyRangeCalls = false) + bool validatePartitionKeyRangeCalls = false, + string accountEndpointOverride = null) { - CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(useCustomSeralizer, validatePartitionKeyRangeCalls); + CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(useCustomSeralizer, validatePartitionKeyRangeCalls, accountEndpointOverride); customizeClientBuilder?.Invoke(cosmosClientBuilder); CosmosClient client = cosmosClientBuilder.Build(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json index 31350d975b..51ecc8a707 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json @@ -1,6 +1,8 @@ { "AppSettings": { "GatewayEndpoint": "https://127.0.0.1:8081/", + "ComputeGatewayEndpoint": "https://localhost:8903/", + "ComputeGatewayPort": "8903", "Location": "South Central US", "Location2": "West US", "GlobalDatabaseAccountId": "globaldb", diff --git a/templates/emulator-setup.yml b/templates/emulator-setup.yml index 533e07a19d..10b5664d82 100644 --- a/templates/emulator-setup.yml +++ b/templates/emulator-setup.yml @@ -11,7 +11,7 @@ steps: mkdir "$env:temp\Azure Cosmos DB Emulator" lessmsi x "$env:temp\azure-cosmosdb-emulator.msi" "$env:temp\Azure Cosmos DB Emulator\" Write-Host "Starting Comsos DB Emulator" -ForegroundColor green - Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication" -Verb RunAs + Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint" -Verb RunAs Import-Module "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" Get-Item env:* | Sort-Object -Property Name for ($i=0; $i -lt 10; $i++) { From ab1f249c4074545765e466ece547a8c96fe51095 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 15 Nov 2022 10:44:55 -0800 Subject: [PATCH 013/337] Change Feed Processor: Adds support for Resource Tokens (#3566) * Adding rid parsing * Test * Removing dead code * Contract update --- .../Utils/CosmosContainerExtensions.cs | 6 +- .../src/Resource/Conflict/ConflictsCore.cs | 6 +- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 2 - .../ChangeFeed/SmokeTests.cs | 59 +++++++++++++++++++ .../ChangeFeedEstimatorIteratorTests.cs | 8 +-- .../ChangeFeedProcessorCoreTests.cs | 4 ++ .../CosmosConflictTests.cs | 18 +++++- 7 files changed, 88 insertions(+), 15 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Utils/CosmosContainerExtensions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Utils/CosmosContainerExtensions.cs index f88b1e9e5f..d37e8c295c 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Utils/CosmosContainerExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Utils/CosmosContainerExtensions.cs @@ -121,7 +121,11 @@ public static async Task GetMonitoredDatabaseAndContainerRidAsync( forceRefresh: false, NoOpTrace.Singleton, cancellationToken: cancellationToken); - string databaseRid = await ((DatabaseInternal)((ContainerInternal)monitoredContainer).Database).GetRIDAsync(cancellationToken); + + // Extract DbRid from ContainerRid + Documents.ResourceId resourceId = Documents.ResourceId.Parse(containerRid); + string databaseRid = resourceId.DatabaseId.ToString(); + return $"{databaseRid}_{containerRid}"; } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsCore.cs index 0f52956fb6..78f6a46eef 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsCore.cs @@ -144,14 +144,14 @@ public async Task> ReadCurrentAsync( throw new ArgumentNullException(nameof(cosmosConflict)); } - // SourceResourceId is RID based on Conflicts, so we need to obtain the db and container rid - DatabaseInternal databaseCore = (DatabaseInternal)this.container.Database; - string databaseResourceId = await databaseCore.GetRIDAsync(cancellationToken); string containerResourceId = await this.container.GetCachedRIDAsync( forceRefresh: false, trace, cancellationToken: cancellationToken); + ResourceId resourceId = ResourceId.Parse(containerResourceId); + string databaseResourceId = resourceId.DatabaseId.ToString(); + string dbLink = this.ClientContext.CreateLink( parentLink: string.Empty, uriPathSegment: Paths.DatabasesPathSegment, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index e055a4f178..07da410dcf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -3068,8 +3068,6 @@ }]]> Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.ReadAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs index f00d9055d8..b4460b6ad6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs @@ -77,6 +77,65 @@ public async Task WritesTriggerDelegate_WithLeaseContainer() CollectionAssert.AreEqual(expectedIds.ToList(), receivedIds); } + [TestMethod] + public async Task WritesTriggerDelegate_WithLeaseContainer_UsingResourceTokens() + { + User user = await this.Container.Database.CreateUserAsync("testUser"); + PermissionResponse monitoredContainerPermissions = await user.CreatePermissionAsync( + new PermissionProperties( + id: "testPermission", + permissionMode: PermissionMode.All, + container: this.Container) + ); + + PermissionResponse leaseContainerPermissions = await user.CreatePermissionAsync( + new PermissionProperties( + id: "testPermission2", + permissionMode: PermissionMode.All, + container: this.LeaseContainer) + ); + + using CosmosClient clientForMonitoredContainer = new CosmosClient(this.Container.Database.Client.Endpoint.ToString(), authKeyOrResourceToken: monitoredContainerPermissions.Resource.Token); + using CosmosClient clientForLeaseContainer = new CosmosClient(this.Container.Database.Client.Endpoint.ToString(), authKeyOrResourceToken: leaseContainerPermissions.Resource.Token); + + ManualResetEvent allDocsProcessed = new ManualResetEvent(false); + IEnumerable expectedIds = Enumerable.Range(0, 100); + List receivedIds = new List(); + ChangeFeedProcessor processor = clientForMonitoredContainer.GetContainer(this.Container.Database.Id, this.Container.Id) + .GetChangeFeedProcessorBuilder("test", (IReadOnlyCollection docs, CancellationToken token) => + { + foreach (TestClass doc in docs) + { + receivedIds.Add(int.Parse(doc.id)); + } + + if (receivedIds.Count == 100) + { + allDocsProcessed.Set(); + } + + return Task.CompletedTask; + }) + .WithInstanceName("random") + .WithLeaseContainer(clientForLeaseContainer.GetContainer(this.LeaseContainer.Database.Id, this.LeaseContainer.Id)).Build(); + + await processor.StartAsync(); + // Letting processor initialize + await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); + // Inserting documents + foreach (int id in expectedIds) + { + await this.Container.CreateItemAsync(new { id = id.ToString() }); + } + + // Waiting on all notifications to finish + bool isStartOk = allDocsProcessed.WaitOne(30 * BaseChangeFeedClientHelper.ChangeFeedCleanupTime); + await processor.StopAsync(); + Assert.IsTrue(isStartOk, "Timed out waiting for docs to process"); + // Verify that we maintain order + CollectionAssert.AreEqual(expectedIds.ToList(), receivedIds); + } + [TestMethod] public async Task ExceptionsRetryBatch() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs index bf33fe06a5..4b9a50c75d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs @@ -350,14 +350,10 @@ static FeedIteratorInternal feedCreator(DocumentServiceLease lease, string conti } }); - string databaseRid = Guid.NewGuid().ToString(); - Mock mockedMonitoredDatabase = new Mock(MockBehavior.Strict); - mockedMonitoredDatabase.Setup(c => c.GetRIDAsync(It.IsAny())).ReturnsAsync(databaseRid); - - string monitoredContainerRid = Guid.NewGuid().ToString(); + string monitoredContainerRid = "V4lVAMl0wuQ="; + string databaseRid = Documents.ResourceId.Parse(monitoredContainerRid).DatabaseId.ToString(); Mock mockedMonitoredContainer = new Mock(MockBehavior.Strict); mockedMonitoredContainer.Setup(c => c.GetCachedRIDAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(monitoredContainerRid); - mockedMonitoredContainer.Setup(c => c.Database).Returns(mockedMonitoredDatabase.Object); mockedMonitoredContainer.Setup(c => c.ClientContext).Returns(mockedContext.Object); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs index a7ba782230..c5e74fbfd9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs @@ -7,11 +7,13 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.Tests using System; using System.Collections.Generic; using System.Linq; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.ChangeFeed.Configuration; using Microsoft.Azure.Cosmos.ChangeFeed.FeedProcessing; using Microsoft.Azure.Cosmos.ChangeFeed.LeaseManagement; using Microsoft.Azure.Cosmos.Tests; + using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -233,6 +235,8 @@ private static ContainerInternal GetMockedContainer(string containerName = null) { Mock mockedContainer = MockCosmosUtil.CreateMockContainer(containerName: containerName); mockedContainer.Setup(c => c.ClientContext).Returns(ChangeFeedProcessorCoreTests.GetMockedClientContext()); + string monitoredContainerRid = "V4lVAMl0wuQ="; + mockedContainer.Setup(c => c.GetCachedRIDAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(monitoredContainerRid); Mock mockedDatabase = MockCosmosUtil.CreateMockDatabase(); mockedContainer.Setup(c => c.Database).Returns(mockedDatabase.Object); return mockedContainer.Object; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs index e2361bddf8..2bb48fc75b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.Tests using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json.Linq; + using Microsoft.Azure.Cosmos.Tracing; [TestClass] public class CosmosConflictTests @@ -38,7 +39,7 @@ public async Task ReadCurrentGetsCorrectRID() const string expectedRID = "something"; Cosmos.PartitionKey partitionKey = new Cosmos.PartitionKey("pk"); // Using "test" as container name because the Mocked DocumentClient has it hardcoded - Uri expectedRequestUri = new Uri($"dbs/conflictsDb/colls/test/docs/{expectedRID}", UriKind.Relative); + Uri expectedRequestUri = new Uri($"dbs/V4lVAA==/colls/V4lVAMl0wuQ=/docs/{expectedRID}", UriKind.Relative); ContainerInternal container = CosmosConflictTests.GetMockedContainer((request, cancellationToken) => { Assert.AreEqual(OperationType.Read, request.OperationType); Assert.AreEqual(ResourceType.Document, request.ResourceType); @@ -74,7 +75,7 @@ public async Task DeleteSendsCorrectPayload() { const string expectedId = "something"; Cosmos.PartitionKey partitionKey = new Cosmos.PartitionKey("pk"); - Uri expectedRequestUri = new Uri($"/dbs/conflictsDb/colls/conflictsColl/conflicts/{expectedId}", UriKind.Relative); + Uri expectedRequestUri = new Uri($"/dbs/myDb/colls/conflictsColl/conflicts/{expectedId}", UriKind.Relative); ContainerInternal container = CosmosConflictTests.GetMockedContainer((request, cancellationToken) => { Assert.AreEqual(OperationType.Delete, request.OperationType); Assert.AreEqual(ResourceType.Conflict, request.ResourceType); @@ -91,7 +92,18 @@ public async Task DeleteSendsCorrectPayload() private static ContainerInternal GetMockedContainer(Func> handlerFunc) { - return new ContainerInlineCore(CosmosConflictTests.GetMockedClientContext(handlerFunc), MockCosmosUtil.CreateMockDatabase("conflictsDb").Object, "conflictsColl"); + CosmosClientContext clientContext = CosmosConflictTests.GetMockedClientContext(handlerFunc); + Mock mockedContainer = MockCosmosUtil.CreateMockContainer(containerName: "conflictsColl"); + DatabaseInternal database = MockCosmosUtil.CreateMockDatabase("conflictsDb").Object; + string monitoredContainerRid = "V4lVAMl0wuQ="; + mockedContainer.Setup(c => c.GetCachedRIDAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(monitoredContainerRid); + mockedContainer.Setup(c => c.Database).Returns(database); + mockedContainer.Setup(c => c.GetReadFeedIterator(It.IsAny(), It.IsAny(), It.IsAny(), It.Is(r => r == ResourceType.Conflict), It.IsAny(), It.IsAny())) + .Returns( + (QueryDefinition qd, QueryRequestOptions o, string link, ResourceType t, string ct, int p) => new ContainerInlineCore(clientContext, database, "conflictsColl").GetReadFeedIterator(qd, o, link, t, ct, p)); + mockedContainer.Setup(c => c.ClientContext).Returns(clientContext); + mockedContainer.Setup(c => c.Conflicts).Returns(new ConflictsInlineCore(clientContext, mockedContainer.Object)); + return mockedContainer.Object; } private static CosmosClientContext GetMockedClientContext( From 9fb3a12de33557ae90f408bea01575172e9d1e98 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 16 Nov 2022 03:11:07 +0530 Subject: [PATCH 014/337] [Internal] AI integration: Refactor code how container and database name is flowing to opentelemetry module (#3532) * wip * WIP * Revert "WIP" This reverts commit 71275de54b9e67fa54a37e79d450b9597e173934. * Revert "wip" This reverts commit 586fa9865cc3f40dabd7ef90fb3e0cf499a045bc. * wip add containe and database info * redesign how container and database name information flows into opne telemetry data * test fix * fix test * fix tests * fix typos * baseline test fix Co-authored-by: Sourabh Jain --- Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs | 15 +- .../src/ChangeFeed/ChangeFeedIteratorCore.cs | 10 +- ...geFeedPartitionKeyResultSetIteratorCore.cs | 10 +- .../ChangeFeedEstimatorIterator.cs | 11 +- Microsoft.Azure.Cosmos/src/CosmosClient.cs | 164 ++++----- .../src/Resource/ClientContextCore.cs | 35 +- .../ClientEncryptionKeyInlineCore.cs | 22 +- .../Resource/Conflict/ConflictsInlineCore.cs | 6 + .../Resource/Container/ContainerInlineCore.cs | 320 +++++++++++------- .../src/Resource/CosmosClientContext.cs | 3 + .../Resource/Database/DatabaseInlineCore.cs | 228 +++++++------ .../FeedIterators/FeedIteratorInlineCore.cs | 20 +- .../FeedIteratorInlineCore{T}.cs | 21 +- .../Permission/PermissionInlineCore.cs | 31 +- .../src/Resource/Scripts/ScriptsInlineCore.cs | 163 +++++---- .../src/Resource/User/UserInlineCore.cs | 55 +-- .../OpenTelemetry/CosmosDbEventSource.cs | 5 +- .../Filters/DiagnosticsFilterHelper.cs | 3 +- .../OpenTelemetry/OpenTelemetryAttributes.cs | 20 +- .../OpenTelemetryCoreRecorder.cs | 50 ++- .../OpenTelemetryRecorderFactory.cs | 9 +- .../OpenTelemetry/OpenTelemetryResponse.cs | 12 +- .../OpenTelemetry/OpenTelemetryResponse{T}.cs | 12 +- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++++------ ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 +-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 12 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 +-- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../QueryPlanBaselineTests.Spatial.xml | 6 +- .../Batch/BatchAsyncBatcherTests.cs | 7 +- .../Batch/BatchAsyncContainerExecutorTests.cs | 7 +- .../Batch/BatchAsyncStreamerTests.cs | 7 +- .../ChangeFeedEstimatorIteratorTests.cs | 19 +- ...dPartitionKeyResultSetIteratorCoreTests.cs | 45 ++- .../CosmosDiagnosticsUnitTests.cs | 18 +- .../CosmosItemUnitTests.cs | 14 +- .../FeedRange/ChangeFeedIteratorCoreTests.cs | 7 +- .../Telemetry/DiagnosticsFilterHelperTest.cs | 4 +- 43 files changed, 1014 insertions(+), 731 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs b/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs index 24975c0d12..e211117d6f 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs @@ -219,9 +219,12 @@ public override Task ExecuteAsync( CancellationToken cancellationToken = default) { return this.container.ClientContext.OperationHelperAsync( - nameof(ExecuteAsync), - requestOptions, - (trace) => + operationName: nameof(ExecuteAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => { BatchExecutor executor = new BatchExecutor( container: this.container, @@ -232,10 +235,8 @@ public override Task ExecuteAsync( this.operations = new List(); return executor.ExecuteAsync(trace, cancellationToken); }, - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.container?.Id, - databaseName: this.container?.Database?.Id)); + openTelemetry: (response) => new OpenTelemetryResponse( + responseMessage: response)); } /// diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs index ca1f60ba0b..87b34cca17 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs @@ -13,8 +13,8 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; internal sealed class ChangeFeedIteratorCore : FeedIteratorInternal { @@ -222,12 +222,12 @@ public ChangeFeedIteratorCore( public override async Task ReadNextAsync(CancellationToken cancellationToken = default) { return await this.clientContext.OperationHelperAsync("Change Feed Iterator Read Next Async", + containerName: this.container?.Id, + databaseName: this.container?.Database?.Id ?? this.databaseName, + operationType: OperationType.ReadFeed, requestOptions: this.changeFeedRequestOptions, task: (trace) => this.ReadNextInternalAsync(trace, cancellationToken), - openTelemetry: (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.container?.Id, - databaseName: this.container?.Database?.Id), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response), traceComponent: TraceComponent.ChangeFeed, traceLevel: TraceLevel.Info); } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs index 4c275227bf..4c7b8f34f0 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs @@ -91,13 +91,15 @@ public override CosmosElement GetCosmosElementContinuationToken() /// A change feed response from cosmos service public override Task ReadNextAsync(CancellationToken cancellationToken = default) { - return this.clientContext.OperationHelperAsync("Change Feed Processor Read Next Async", + return this.clientContext.OperationHelperAsync( + operationName: "Change Feed Processor Read Next Async", + containerName: this.container?.Id, + databaseName: this.container?.Database?.Id ?? this.databaseName, + operationType: Documents.OperationType.ReadFeed, requestOptions: this.changeFeedOptions, task: (trace) => this.ReadNextAsync(trace, cancellationToken), openTelemetry: (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.container?.Id, - databaseName: this.container?.Database?.Id), + responseMessage: response), traceComponent: TraceComponent.ChangeFeed, traceLevel: TraceLevel.Info); } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs index d8dca1ef60..47469542de 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs @@ -111,13 +111,14 @@ private ChangeFeedEstimatorIterator( public override Task> ReadNextAsync(CancellationToken cancellationToken = default) { - return this.monitoredContainer.ClientContext.OperationHelperAsync("Change Feed Estimator Read Next Async", + return this.monitoredContainer.ClientContext.OperationHelperAsync( + operationName: "Change Feed Estimator Read Next Async", + containerName: this.monitoredContainer?.Id, + databaseName: this.monitoredContainer?.Database?.Id, + operationType: Documents.OperationType.ReadFeed, requestOptions: null, task: (trace) => this.ReadNextAsync(trace, cancellationToken), - openTelemetry: (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.monitoredContainer?.Id, - databaseName: this.monitoredContainer?.Database?.Id ?? this.databaseName), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response), traceComponent: TraceComponent.ChangeFeed, traceLevel: TraceLevel.Info); } diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index c4ab25f4e6..e5ca2d8b53 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -18,8 +18,6 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; - using Microsoft.Azure.Cosmos.Routing; - using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; @@ -629,9 +627,12 @@ internal CosmosClient( public virtual Task ReadAccountAsync() { return this.ClientContext.OperationHelperAsync( - nameof(ReadAccountAsync), - null, - (trace) => ((IDocumentClientInternal)this.DocumentClient).GetDatabaseAccountInternalAsync(this.Endpoint)); + operationName: nameof(ReadAccountAsync), + containerName: null, + databaseName: null, + operationType: OperationType.Read, + requestOptions: null, + task: (trace) => ((IDocumentClientInternal)this.DocumentClient).GetDatabaseAccountInternalAsync(this.Endpoint)); } /// @@ -715,9 +716,12 @@ public virtual Task CreateDatabaseAsync( } return this.ClientContext.OperationHelperAsync( - nameof(CreateDatabaseAsync), - requestOptions, - (trace) => + operationName: nameof(CreateDatabaseAsync), + containerName: null, + databaseName: id, + operationType: OperationType.Create, + requestOptions: requestOptions, + task: (trace) => { DatabaseProperties databaseProperties = this.PrepareDatabaseProperties(id); ThroughputProperties throughputProperties = ThroughputProperties.CreateManualThroughput(throughput); @@ -729,10 +733,7 @@ public virtual Task CreateDatabaseAsync( trace: trace, cancellationToken: cancellationToken); }, - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: response.Resource?.Id)); + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } /// @@ -765,9 +766,12 @@ public virtual Task CreateDatabaseAsync( } return this.ClientContext.OperationHelperAsync( - nameof(CreateDatabaseAsync), - requestOptions, - (trace) => + operationName: nameof(CreateDatabaseAsync), + containerName: null, + databaseName: id, + operationType: OperationType.Create, + requestOptions: requestOptions, + task: (trace) => { DatabaseProperties databaseProperties = this.PrepareDatabaseProperties(id); return this.CreateDatabaseInternalAsync( @@ -777,10 +781,7 @@ public virtual Task CreateDatabaseAsync( trace: trace, cancellationToken: cancellationToken); }, - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: response.Resource?.Id)); + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } /// @@ -824,59 +825,60 @@ public virtual Task CreateDatabaseIfNotExistsAsync( return string.IsNullOrEmpty(id) ? throw new ArgumentNullException(nameof(id)) : this.ClientContext.OperationHelperAsync( - nameof(CreateDatabaseIfNotExistsAsync), - requestOptions, - async (trace) => - { - double totalRequestCharge = 0; - // Doing a Read before Create will give us better latency for existing databases - DatabaseProperties databaseProperties = this.PrepareDatabaseProperties(id); - DatabaseCore database = (DatabaseCore)this.GetDatabase(id); - using (ResponseMessage readResponse = await database.ReadStreamAsync( + operationName: nameof(CreateDatabaseIfNotExistsAsync), + containerName: null, + databaseName: id, + operationType: OperationType.Create, requestOptions: requestOptions, - trace: trace, - cancellationToken: cancellationToken)) - { - totalRequestCharge = readResponse.Headers.RequestCharge; - if (readResponse.StatusCode != HttpStatusCode.NotFound) + task: async (trace) => { - return this.ClientContext.ResponseFactory.CreateDatabaseResponse(database, readResponse); - } - } - - using (ResponseMessage createResponse = await this.CreateDatabaseStreamInternalAsync( - databaseProperties, - throughputProperties, - requestOptions, - trace, - cancellationToken)) - { - totalRequestCharge += createResponse.Headers.RequestCharge; - createResponse.Headers.RequestCharge = totalRequestCharge; - - if (createResponse.StatusCode != HttpStatusCode.Conflict) - { - return this.ClientContext.ResponseFactory.CreateDatabaseResponse(this.GetDatabase(databaseProperties.Id), createResponse); - } - } - - // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create - // so for the remaining ones we should do a Read instead of throwing Conflict exception - using (ResponseMessage readResponseAfterConflict = await database.ReadStreamAsync( - requestOptions: requestOptions, - trace: trace, - cancellationToken: cancellationToken)) - { - totalRequestCharge += readResponseAfterConflict.Headers.RequestCharge; - readResponseAfterConflict.Headers.RequestCharge = totalRequestCharge; - - return this.ClientContext.ResponseFactory.CreateDatabaseResponse(this.GetDatabase(databaseProperties.Id), readResponseAfterConflict); - } - }, - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: response.Resource?.Id)); + double totalRequestCharge = 0; + // Doing a Read before Create will give us better latency for existing databases + DatabaseProperties databaseProperties = this.PrepareDatabaseProperties(id); + DatabaseCore database = (DatabaseCore)this.GetDatabase(id); + using (ResponseMessage readResponse = await database.ReadStreamAsync( + requestOptions: requestOptions, + trace: trace, + cancellationToken: cancellationToken)) + { + totalRequestCharge = readResponse.Headers.RequestCharge; + if (readResponse.StatusCode != HttpStatusCode.NotFound) + { + return this.ClientContext.ResponseFactory.CreateDatabaseResponse(database, readResponse); + } + } + + using (ResponseMessage createResponse = await this.CreateDatabaseStreamInternalAsync( + databaseProperties, + throughputProperties, + requestOptions, + trace, + cancellationToken)) + { + totalRequestCharge += createResponse.Headers.RequestCharge; + createResponse.Headers.RequestCharge = totalRequestCharge; + + if (createResponse.StatusCode != HttpStatusCode.Conflict) + { + return this.ClientContext.ResponseFactory.CreateDatabaseResponse(this.GetDatabase(databaseProperties.Id), createResponse); + } + } + + // This second Read is to handle the race condition when 2 or more threads have Read the database and only one succeeds with Create + // so for the remaining ones we should do a Read instead of throwing Conflict exception + using (ResponseMessage readResponseAfterConflict = await database.ReadStreamAsync( + requestOptions: requestOptions, + trace: trace, + cancellationToken: cancellationToken)) + { + totalRequestCharge += readResponseAfterConflict.Headers.RequestCharge; + readResponseAfterConflict.Headers.RequestCharge = totalRequestCharge; + + return this.ClientContext.ResponseFactory.CreateDatabaseResponse(this.GetDatabase(databaseProperties.Id), readResponseAfterConflict); + } + }, + openTelemetry: (response) => new OpenTelemetryResponse( + responseMessage: response)); } /// @@ -1165,9 +1167,12 @@ public virtual Task CreateDatabaseStreamAsync( } return this.ClientContext.OperationHelperAsync( - nameof(CreateDatabaseStreamAsync), - requestOptions, - (trace) => + operationName: nameof(CreateDatabaseStreamAsync), + containerName: null, + databaseName: databaseProperties.Id, + operationType: OperationType.Create, + requestOptions: requestOptions, + task: (trace) => { this.ClientContext.ValidateResource(databaseProperties.Id); return this.CreateDatabaseStreamInternalAsync( @@ -1177,7 +1182,7 @@ public virtual Task CreateDatabaseStreamAsync( trace, cancellationToken); }, - (response) => new OpenTelemetryResponse(response)); + openTelemetry: (response) => new OpenTelemetryResponse(response)); } /// @@ -1260,9 +1265,12 @@ internal virtual Task CreateDatabaseStreamAsync( } return this.ClientContext.OperationHelperAsync( - nameof(CreateDatabaseIfNotExistsAsync), - requestOptions, - (trace) => + operationName: nameof(CreateDatabaseIfNotExistsAsync), + containerName: null, + databaseName: databaseProperties.Id, + operationType: OperationType.Create, + requestOptions: requestOptions, + task: (trace) => { this.ClientContext.ValidateResource(databaseProperties.Id); return this.CreateDatabaseStreamInternalAsync( @@ -1272,7 +1280,7 @@ internal virtual Task CreateDatabaseStreamAsync( trace, cancellationToken); }, - (response) => new OpenTelemetryResponse(response)); + openTelemetry: (response) => new OpenTelemetryResponse(response)); } private async Task CreateDatabaseInternalAsync( diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index 7bbb6c639b..191399943f 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -194,6 +194,9 @@ internal override void ValidateResource(string resourceId) internal override Task OperationHelperAsync( string operationName, + string containerName, + string databaseName, + OperationType operationType, RequestOptions requestOptions, Func> task, Func openTelemetry, @@ -201,13 +204,20 @@ internal override Task Tracing.TraceLevel traceLevel = Tracing.TraceLevel.Info) { return SynchronizationContext.Current == null ? - this.OperationHelperWithRootTraceAsync(operationName, + this.OperationHelperWithRootTraceAsync(operationName, + containerName, + databaseName, + operationType, requestOptions, task, openTelemetry, traceComponent, traceLevel) : - this.OperationHelperWithRootTraceWithSynchronizationContextAsync(operationName, + this.OperationHelperWithRootTraceWithSynchronizationContextAsync( + operationName, + containerName, + databaseName, + operationType, requestOptions, task, openTelemetry, @@ -217,6 +227,9 @@ internal override Task private async Task OperationHelperWithRootTraceAsync( string operationName, + string containerName, + string databaseName, + OperationType operationType, RequestOptions requestOptions, Func> task, Func openTelemetry, @@ -230,6 +243,9 @@ private async Task OperationHelperWithRootTraceAsync( trace.AddDatum("Client Configuration", this.client.ClientConfigurationTraceDatum); return await this.RunWithDiagnosticsHelperAsync( + containerName, + databaseName, + operationType, trace, task, openTelemetry, @@ -240,6 +256,9 @@ private async Task OperationHelperWithRootTraceAsync( private Task OperationHelperWithRootTraceWithSynchronizationContextAsync( string operationName, + string containerName, + string databaseName, + OperationType operationType, RequestOptions requestOptions, Func> task, Func openTelemetry, @@ -260,6 +279,9 @@ private Task OperationHelperWithRootTraceWithSynchronizationContextAsyn trace.AddDatum("Synchronization Context", syncContextVirtualAddress); return await this.RunWithDiagnosticsHelperAsync( + containerName, + databaseName, + operationType, trace, task, openTelemetry, @@ -449,6 +471,9 @@ protected virtual void Dispose(bool disposing) } private async Task RunWithDiagnosticsHelperAsync( + string containerName, + string databaseName, + OperationType operationType, ITrace trace, Func> task, Func openTelemetry, @@ -458,15 +483,15 @@ private async Task RunWithDiagnosticsHelperAsync( using (OpenTelemetryCoreRecorder recorder = OpenTelemetryRecorderFactory.CreateRecorder( operationName: operationName, + containerName: containerName, + databaseName: databaseName, + operationType: operationType, requestOptions: requestOptions, clientContext: this.isDisposed ? null : this)) using (new ActivityScope(Guid.NewGuid())) { try { - // Record Operation Name - recorder.Record(OpenTelemetryAttributeKeys.DbOperation, operationName); - TResult result = await task(trace).ConfigureAwait(false); if (openTelemetry != null && recorder.IsEnabled) { diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/ClientEncryptionKeyInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/ClientEncryptionKeyInlineCore.cs index 74f17b62c0..6d6305e30b 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/ClientEncryptionKeyInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientEncryptionKey/ClientEncryptionKeyInlineCore.cs @@ -29,10 +29,13 @@ public override Task ReadAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadAsync), - requestOptions, - (trace) => base.ReadAsync(requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadAsync(requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceAsync( @@ -41,10 +44,13 @@ public override Task ReplaceAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceAsync), - requestOptions, - (trace) => base.ReplaceAsync(clientEncryptionKeyProperties, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceAsync(clientEncryptionKeyProperties, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsInlineCore.cs index 6c691f1eff..17caba406e 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Conflict/ConflictsInlineCore.cs @@ -26,6 +26,9 @@ public override Task DeleteAsync( { return this.ClientContext.OperationHelperAsync( operationName: nameof(DeleteAsync), + containerName: null, + databaseName: null, + operationType: Documents.OperationType.Delete, requestOptions: null, task: (trace) => base.DeleteAsync(conflict, partitionKey, trace, cancellationToken), openTelemetry: (response) => new OpenTelemetryResponse(response)); @@ -86,6 +89,9 @@ public override Task> ReadCurrentAsync( { return this.ClientContext.OperationHelperAsync( operationName: nameof(ReadCurrentAsync), + containerName: null, + databaseName: null, + operationType: Documents.OperationType.Read, requestOptions: null, task: (trace) => base.ReadCurrentAsync(cosmosConflict, partitionKey, trace, cancellationToken), openTelemetry: (response) => new OpenTelemetryResponse(response)); diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs index 6cabc1a069..8e6e4495aa 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs @@ -37,10 +37,13 @@ public override Task ReadContainerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadContainerAsync), - requestOptions, - (trace) => base.ReadContainerAsync(trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadContainerAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadContainerAsync(trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadContainerStreamAsync( @@ -48,10 +51,13 @@ public override Task ReadContainerStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadContainerStreamAsync), - requestOptions, - (trace) => base.ReadContainerStreamAsync(trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadContainerStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadContainerStreamAsync(trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceContainerAsync( @@ -60,10 +66,13 @@ public override Task ReplaceContainerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceContainerAsync), - requestOptions, - (trace) => base.ReplaceContainerAsync(containerProperties, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceContainerAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceContainerAsync(containerProperties, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceContainerStreamAsync( @@ -72,10 +81,13 @@ public override Task ReplaceContainerStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceContainerStreamAsync), - requestOptions, - (trace) => base.ReplaceContainerStreamAsync(containerProperties, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceContainerStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceContainerStreamAsync(containerProperties, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteContainerAsync( @@ -83,10 +95,13 @@ public override Task DeleteContainerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteContainerAsync), - requestOptions, - (trace) => base.DeleteContainerAsync(trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteContainerAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteContainerAsync(trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteContainerStreamAsync( @@ -94,18 +109,24 @@ public override Task DeleteContainerStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteContainerStreamAsync), - requestOptions, - (trace) => base.DeleteContainerStreamAsync(trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteContainerStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteContainerStreamAsync(trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadThroughputAsync(CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadThroughputAsync), - null, - (trace) => base.ReadThroughputAsync(trace, cancellationToken)); + operationName: nameof(ReadThroughputAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: null, + task: (trace) => base.ReadThroughputAsync(trace, cancellationToken)); } public override Task ReadThroughputAsync( @@ -113,10 +134,13 @@ public override Task ReadThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadThroughputAsync), - requestOptions, - (trace) => base.ReadThroughputAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadThroughputAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadThroughputAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceThroughputAsync( @@ -125,10 +149,13 @@ public override Task ReplaceThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceThroughputAsync), - requestOptions, - (trace) => base.ReplaceThroughputAsync(throughput, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceThroughputAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceThroughputAsync(throughput, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceThroughputAsync( @@ -137,28 +164,37 @@ public override Task ReplaceThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceThroughputAsync), - requestOptions, - (trace) => base.ReplaceThroughputAsync(throughputProperties, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceThroughputAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceThroughputAsync(throughputProperties, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadThroughputIfExistsAsync(RequestOptions requestOptions, CancellationToken cancellationToken) { return this.ClientContext.OperationHelperAsync( - nameof(ReadThroughputIfExistsAsync), - requestOptions, - (trace) => base.ReadThroughputIfExistsAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadThroughputIfExistsAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadThroughputIfExistsAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceThroughputIfExistsAsync(ThroughputProperties throughput, RequestOptions requestOptions, CancellationToken cancellationToken) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceThroughputIfExistsAsync), - requestOptions, - (trace) => base.ReplaceThroughputIfExistsAsync(throughput, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceThroughputIfExistsAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceThroughputIfExistsAsync(throughput, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateItemStreamAsync( @@ -178,10 +214,13 @@ Task func(ITrace trace) } return this.ClientContext.OperationHelperAsync( - nameof(CreateItemStreamAsync), - requestOptions, - func, - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: func, + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> CreateItemAsync(T item, @@ -190,10 +229,13 @@ public override Task> CreateItemAsync(T item, CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateItemAsync), - requestOptions, - (trace) => base.CreateItemAsync(item, trace, partitionKey, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateItemAsync(item, trace, partitionKey, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadItemStreamAsync( @@ -203,10 +245,13 @@ public override Task ReadItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadItemStreamAsync), - requestOptions, - (trace) => base.ReadItemStreamAsync(id, partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadItemStreamAsync(id, partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> ReadItemAsync( @@ -217,6 +262,9 @@ public override Task> ReadItemAsync( { return this.ClientContext.OperationHelperAsync( nameof(ReadItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, requestOptions, (trace) => base.ReadItemAsync(id, partitionKey, trace, requestOptions, cancellationToken), (response) => new OpenTelemetryResponse(response)); @@ -229,10 +277,13 @@ public override Task UpsertItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(UpsertItemStreamAsync), - requestOptions, - (trace) => base.UpsertItemStreamAsync(streamPayload, partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(UpsertItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Upsert, + requestOptions: requestOptions, + task: (trace) => base.UpsertItemStreamAsync(streamPayload, partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> UpsertItemAsync( @@ -242,10 +293,13 @@ public override Task> UpsertItemAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(UpsertItemAsync), - requestOptions, - (trace) => base.UpsertItemAsync(item, trace, partitionKey, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(UpsertItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Upsert, + requestOptions: requestOptions, + task: (trace) => base.UpsertItemAsync(item, trace, partitionKey, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceItemStreamAsync( @@ -256,10 +310,13 @@ public override Task ReplaceItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceItemStreamAsync), - requestOptions, - (trace) => base.ReplaceItemStreamAsync(streamPayload, id, partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceItemStreamAsync(streamPayload, id, partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> ReplaceItemAsync( @@ -270,10 +327,13 @@ public override Task> ReplaceItemAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceItemAsync), - requestOptions, - (trace) => base.ReplaceItemAsync(item, id, trace, partitionKey, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceItemAsync(item, id, trace, partitionKey, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteItemStreamAsync( @@ -283,10 +343,13 @@ public override Task DeleteItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteItemStreamAsync), - requestOptions, - (trace) => base.DeleteItemStreamAsync(id, partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteItemStreamAsync(id, partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> DeleteItemAsync( @@ -296,10 +359,13 @@ public override Task> DeleteItemAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteItemAsync), - requestOptions, - (trace) => base.DeleteItemAsync(id, partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteItemAsync(id, partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task PatchItemStreamAsync( @@ -310,10 +376,13 @@ public override Task PatchItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(PatchItemStreamAsync), - requestOptions, - (trace) => base.PatchItemStreamAsync(id, partitionKey, patchOperations, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(PatchItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Patch, + requestOptions: requestOptions, + task: (trace) => base.PatchItemStreamAsync(id, partitionKey, patchOperations, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task PatchItemStreamAsync( @@ -324,10 +393,13 @@ public override Task PatchItemStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(PatchItemStreamAsync), - requestOptions, - (trace) => base.PatchItemStreamAsync(id, partitionKey, streamPayload, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(PatchItemStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Patch, + requestOptions: requestOptions, + task: (trace) => base.PatchItemStreamAsync(id, partitionKey, streamPayload, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> PatchItemAsync( @@ -338,10 +410,13 @@ public override Task> PatchItemAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(PatchItemAsync), - requestOptions, - (trace) => base.PatchItemAsync(id, partitionKey, patchOperations, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(PatchItemAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Patch, + requestOptions: requestOptions, + task: (trace) => base.PatchItemAsync(id, partitionKey, patchOperations, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadManyItemsStreamAsync( @@ -350,13 +425,13 @@ public override Task ReadManyItemsStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadManyItemsStreamAsync), - null, - (trace) => base.ReadManyItemsStreamAsync(items, trace, readManyRequestOptions, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.Id, - databaseName: this.Database?.Id)); + operationName: nameof(ReadManyItemsStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: null, + task: (trace) => base.ReadManyItemsStreamAsync(items, trace, readManyRequestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task> ReadManyItemsAsync( @@ -366,12 +441,12 @@ public override Task> ReadManyItemsAsync( { return this.ClientContext.OperationHelperAsync( nameof(ReadManyItemsAsync), - null, - (trace) => base.ReadManyItemsAsync(items, trace, readManyRequestOptions, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: this.Id, - databaseName: this.Database?.Id)); + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: null, + task: (trace) => base.ReadManyItemsAsync(items, trace, readManyRequestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override FeedIterator GetItemQueryStreamIterator( @@ -490,9 +565,12 @@ public override TransactionalBatch CreateTransactionalBatch(PartitionKey partiti public override Task> GetFeedRangesAsync(CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(GetFeedRangesAsync), - null, - (trace) => base.GetFeedRangesAsync(trace, cancellationToken)); + operationName: nameof(GetFeedRangesAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.ReadFeed, + requestOptions: null, + task: (trace) => base.GetFeedRangesAsync(trace, cancellationToken)); } public override FeedIterator GetChangeFeedStreamIterator( @@ -519,9 +597,12 @@ public override Task> GetPartitionKeyRangesAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(GetPartitionKeyRangesAsync), - null, - (trace) => base.GetPartitionKeyRangesAsync(feedRange, trace, cancellationToken)); + operationName: nameof(GetPartitionKeyRangesAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: null, + task: (trace) => base.GetPartitionKeyRangesAsync(feedRange, trace, cancellationToken)); } public override FeedIterator GetItemQueryStreamIterator( @@ -572,10 +653,13 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( CancellationToken cancellationToken = default(CancellationToken)) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteAllItemsByPartitionKeyStreamAsync), - requestOptions, - (trace) => base.DeleteAllItemsByPartitionKeyStreamAsync(partitionKey, trace, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteAllItemsByPartitionKeyStreamAsync), + containerName: this.Id, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteAllItemsByPartitionKeyStreamAsync(partitionKey, trace, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosClientContext.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosClientContext.cs index ef3aa09643..5bd2cc1848 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosClientContext.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosClientContext.cs @@ -60,6 +60,9 @@ internal abstract Task GetCachedContainerPropertiesAsync( internal abstract Task OperationHelperAsync( string operationName, + string containerName, + string databaseName, + OperationType operationType, RequestOptions requestOptions, Func> task, Func openTelemetry = null, diff --git a/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseInlineCore.cs index 4b5073289a..fb25ef4190 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseInlineCore.cs @@ -27,13 +27,13 @@ public override Task CreateContainerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerAsync), - requestOptions, - (trace) => base.CreateContainerAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: response.Resource?.Id, - databaseName: this.Id)); + operationName: nameof(CreateContainerAsync), + containerName: containerProperties.Id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task CreateContainerAsync(string id, @@ -43,13 +43,13 @@ public override Task CreateContainerAsync(string id, CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerAsync), - requestOptions, - (trace) => base.CreateContainerAsync(id, partitionKeyPath, throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: response.Resource?.Id, - databaseName: this.Id)); + operationName: nameof(CreateContainerAsync), + containerName: id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerAsync(id, partitionKeyPath, throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task CreateContainerIfNotExistsAsync( @@ -59,13 +59,13 @@ public override Task CreateContainerIfNotExistsAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerIfNotExistsAsync), - requestOptions, - (trace) => base.CreateContainerIfNotExistsAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: response.Resource?.Id, - databaseName: this.Id)); + operationName: nameof(CreateContainerIfNotExistsAsync), + containerName: containerProperties.Id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerIfNotExistsAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task CreateContainerIfNotExistsAsync( @@ -76,13 +76,13 @@ public override Task CreateContainerIfNotExistsAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerIfNotExistsAsync), - requestOptions, - (trace) => base.CreateContainerIfNotExistsAsync(id, partitionKeyPath, throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: response.Resource?.Id, - databaseName: this.Id)); + operationName: nameof(CreateContainerIfNotExistsAsync), + containerName: id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerIfNotExistsAsync(id, partitionKeyPath, throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task CreateContainerStreamAsync( @@ -92,10 +92,13 @@ public override Task CreateContainerStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerStreamAsync), - requestOptions, - (trace) => base.CreateContainerStreamAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateContainerStreamAsync), + containerName: containerProperties.Id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerStreamAsync(containerProperties, throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateUserAsync(string id, @@ -103,10 +106,13 @@ public override Task CreateUserAsync(string id, CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateUserAsync), - requestOptions, - (trace) => base.CreateUserAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateUserAsync), + containerName: id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateUserAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override ContainerBuilder DefineContainer( @@ -121,13 +127,13 @@ public override Task DeleteAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteAsync), - requestOptions, - (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: response.Resource?.Id)); + operationName: nameof(DeleteAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task DeleteStreamAsync( @@ -135,10 +141,13 @@ public override Task DeleteStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteStreamAsync), - requestOptions, - (trace) => base.DeleteStreamAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteStreamAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteStreamAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Container GetContainer(string id) @@ -226,13 +235,13 @@ public override Task ReadAsync(RequestOptions requestOptions = CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadAsync), - requestOptions, - (trace) => base.ReadAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: response.Resource?.Id)); + operationName: nameof(ReadAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task ReadStreamAsync( @@ -240,18 +249,24 @@ public override Task ReadStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadStreamAsync), - requestOptions, - (trace) => base.ReadStreamAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadStreamAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadStreamAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReadThroughputAsync(CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadThroughputAsync), - null, - (trace) => base.ReadThroughputAsync(trace, cancellationToken)); + operationName: nameof(ReadThroughputAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Read, + requestOptions: null, + task: (trace) => base.ReadThroughputAsync(trace, cancellationToken)); } public override Task ReadThroughputAsync( @@ -259,10 +274,13 @@ public override Task ReadThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadThroughputAsync), - requestOptions, - (trace) => base.ReadThroughputAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadThroughputAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadThroughputAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceThroughputAsync( @@ -271,10 +289,13 @@ public override Task ReplaceThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceThroughputAsync), - requestOptions, - (trace) => base.ReplaceThroughputAsync(throughput, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceThroughputAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceThroughputAsync(throughput, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceThroughputAsync( @@ -283,10 +304,13 @@ public override Task ReplaceThroughputAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceThroughputAsync), - requestOptions, - (trace) => base.ReplaceThroughputAsync(throughputProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceThroughputAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceThroughputAsync(throughputProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateContainerAsync( @@ -296,13 +320,13 @@ public override Task CreateContainerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerAsync), - requestOptions, - (trace) => base.CreateContainerAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse( - responseMessage: response, - containerName: response.Resource?.Id, - databaseName: this.Id)); + operationName: nameof(CreateContainerAsync), + containerName: containerProperties.Id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task CreateContainerIfNotExistsAsync( @@ -312,10 +336,13 @@ public override Task CreateContainerIfNotExistsAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerIfNotExistsAsync), - requestOptions, - (trace) => base.CreateContainerIfNotExistsAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response, response.Resource?.Id, this.Id)); + operationName: nameof(CreateContainerIfNotExistsAsync), + containerName: containerProperties.Id, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerIfNotExistsAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateContainerStreamAsync( @@ -325,10 +352,13 @@ public override Task CreateContainerStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateContainerStreamAsync), - requestOptions, - (trace) => base.CreateContainerStreamAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateContainerStreamAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateContainerStreamAsync(containerProperties, throughputProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task UpsertUserAsync( @@ -337,10 +367,13 @@ public override Task UpsertUserAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(UpsertUserAsync), - requestOptions, - (trace) => base.UpsertUserAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(UpsertUserAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Upsert, + requestOptions: requestOptions, + task: (trace) => base.UpsertUserAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override ClientEncryptionKey GetClientEncryptionKey(string id) @@ -362,10 +395,13 @@ public override Task CreateClientEncryptionKeyAsync CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateClientEncryptionKeyAsync), - requestOptions, - (trace) => base.CreateClientEncryptionKeyAsync(trace, clientEncryptionKeyProperties, requestOptions, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateClientEncryptionKeyAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateClientEncryptionKeyAsync(trace, clientEncryptionKeyProperties, requestOptions, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs index bf19fa7743..e1d18b72af 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs @@ -51,22 +51,14 @@ public override CosmosElement GetCosmosElementContinuationToken() public override Task ReadNextAsync(CancellationToken cancellationToken = default) { - return this.clientContext.OperationHelperAsync("FeedIterator Read Next Async", + return this.clientContext.OperationHelperAsync( + operationName: "FeedIterator Read Next Async", + containerName: this.container?.Id, + databaseName: this.container?.Database?.Id ?? this.databaseName, + operationType: Documents.OperationType.ReadFeed, requestOptions: null, task: (trace) => this.feedIteratorInternal.ReadNextAsync(trace, cancellationToken), - openTelemetry: (response) => - { - if (this.container == null) - { - return new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: this.databaseName); - } - return new OpenTelemetryResponse(responseMessage: response, - containerName: this.container?.Id, - databaseName: this.container?.Database?.Id ?? this.databaseName); - }); + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task ReadNextAsync(ITrace trace, CancellationToken cancellationToken = default) diff --git a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore{T}.cs b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore{T}.cs index d115dcd175..cebfadb4c4 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore{T}.cs @@ -46,23 +46,14 @@ internal FeedIteratorInlineCore( public override Task> ReadNextAsync(CancellationToken cancellationToken = default) { - return this.clientContext.OperationHelperAsync("Typed FeedIterator ReadNextAsync", + return this.clientContext.OperationHelperAsync( + operationName: "Typed FeedIterator ReadNextAsync", + containerName: this.container?.Id, + databaseName: this.container?.Database.Id ?? this.databaseName, + operationType: Documents.OperationType.ReadFeed, requestOptions: null, task: trace => this.feedIteratorInternal.ReadNextAsync(trace, cancellationToken), - openTelemetry: (response) => - { - if (this.container == null) - { - return new OpenTelemetryResponse( - responseMessage: response, - containerName: null, - databaseName: this.databaseName); - } - return new OpenTelemetryResponse( - responseMessage: response, - containerName: this.container?.Id, - databaseName: this.container?.Database?.Id ?? this.databaseName); - }); + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response)); } public override Task> ReadNextAsync(ITrace trace, CancellationToken cancellationToken) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Permission/PermissionInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Permission/PermissionInlineCore.cs index 121e0c245a..ecf8e36d95 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Permission/PermissionInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Permission/PermissionInlineCore.cs @@ -27,10 +27,13 @@ public override Task ReadAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadAsync), - requestOptions, - (trace) => base.ReadAsync(tokenExpiryInSeconds, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadAsync(tokenExpiryInSeconds, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceAsync( @@ -40,10 +43,13 @@ public override Task ReplaceAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceAsync), - requestOptions, - (trace) => base.ReplaceAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteAsync( @@ -51,10 +57,13 @@ public override Task DeleteAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteAsync), + operationName: nameof(DeleteAsync), + containerName: null, + databaseName: this.Id, + operationType: Documents.OperationType.Delete, requestOptions, - (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + task: (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Scripts/ScriptsInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Scripts/ScriptsInlineCore.cs index 0eae93212c..15059c1def 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Scripts/ScriptsInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Scripts/ScriptsInlineCore.cs @@ -27,10 +27,13 @@ public override Task CreateStoredProcedureAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateStoredProcedureAsync), - requestOptions, - (trace) => base.CreateStoredProcedureAsync(storedProcedureProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateStoredProcedureAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateStoredProcedureAsync(storedProcedureProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override FeedIterator GetStoredProcedureQueryIterator( @@ -87,10 +90,13 @@ public override Task ReadStoredProcedureAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadStoredProcedureAsync), - requestOptions, - (trace) => base.ReadStoredProcedureAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadStoredProcedureAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadStoredProcedureAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceStoredProcedureAsync( @@ -99,10 +105,13 @@ public override Task ReplaceStoredProcedureAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceStoredProcedureAsync), + operationName: nameof(ReplaceStoredProcedureAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Replace, requestOptions, - (trace) => base.ReplaceStoredProcedureAsync(storedProcedureProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + task: (trace) => base.ReplaceStoredProcedureAsync(storedProcedureProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteStoredProcedureAsync( @@ -111,10 +120,13 @@ public override Task DeleteStoredProcedureAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteStoredProcedureAsync), - requestOptions, - (trace) => base.DeleteStoredProcedureAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteStoredProcedureAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteStoredProcedureAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task> ExecuteStoredProcedureAsync( @@ -125,10 +137,13 @@ public override Task> ExecuteStoredProce CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ExecuteStoredProcedureAsync), - requestOptions, - (trace) => base.ExecuteStoredProcedureAsync(storedProcedureId, partitionKey, parameters, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ExecuteStoredProcedureAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Execute, + requestOptions: requestOptions, + task: (trace) => base.ExecuteStoredProcedureAsync(storedProcedureId, partitionKey, parameters, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ExecuteStoredProcedureStreamAsync( @@ -139,10 +154,13 @@ public override Task ExecuteStoredProcedureStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ExecuteStoredProcedureStreamAsync), - requestOptions, - (trace) => base.ExecuteStoredProcedureStreamAsync(storedProcedureId, partitionKey, parameters, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ExecuteStoredProcedureStreamAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Execute, + requestOptions: requestOptions, + task: (trace) => base.ExecuteStoredProcedureStreamAsync(storedProcedureId, partitionKey, parameters, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ExecuteStoredProcedureStreamAsync( @@ -153,10 +171,13 @@ public override Task ExecuteStoredProcedureStreamAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ExecuteStoredProcedureStreamAsync), - requestOptions, - (trace) => base.ExecuteStoredProcedureStreamAsync(storedProcedureId, streamPayload, partitionKey, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ExecuteStoredProcedureStreamAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Execute, + requestOptions: requestOptions, + task: (trace) => base.ExecuteStoredProcedureStreamAsync(storedProcedureId, streamPayload, partitionKey, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateTriggerAsync( @@ -165,10 +186,13 @@ public override Task CreateTriggerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateTriggerAsync), - requestOptions, - (trace) => base.CreateTriggerAsync(triggerProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateTriggerAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateTriggerAsync(triggerProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override FeedIterator GetTriggerQueryIterator( @@ -225,10 +249,13 @@ public override Task ReadTriggerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadTriggerAsync), - requestOptions, - (trace) => base.ReadTriggerAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadTriggerAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadTriggerAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceTriggerAsync( @@ -237,10 +264,13 @@ public override Task ReplaceTriggerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceTriggerAsync), - requestOptions, - (trace) => base.ReplaceTriggerAsync(triggerProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceTriggerAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceTriggerAsync(triggerProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteTriggerAsync( @@ -249,10 +279,13 @@ public override Task DeleteTriggerAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteTriggerAsync), - requestOptions, - (trace) => base.DeleteTriggerAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteTriggerAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteTriggerAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task CreateUserDefinedFunctionAsync( @@ -261,10 +294,13 @@ public override Task CreateUserDefinedFunctionAsync CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreateUserDefinedFunctionAsync), - requestOptions, - (trace) => base.CreateUserDefinedFunctionAsync(userDefinedFunctionProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreateUserDefinedFunctionAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreateUserDefinedFunctionAsync(userDefinedFunctionProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override FeedIterator GetUserDefinedFunctionQueryIterator( @@ -321,10 +357,13 @@ public override Task ReadUserDefinedFunctionAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadUserDefinedFunctionAsync), - requestOptions, - (trace) => base.ReadUserDefinedFunctionAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadUserDefinedFunctionAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadUserDefinedFunctionAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceUserDefinedFunctionAsync( @@ -333,10 +372,13 @@ public override Task ReplaceUserDefinedFunctionAsyn CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceUserDefinedFunctionAsync), - requestOptions, - (trace) => base.ReplaceUserDefinedFunctionAsync(userDefinedFunctionProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceUserDefinedFunctionAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceUserDefinedFunctionAsync(userDefinedFunctionProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteUserDefinedFunctionAsync( @@ -345,10 +387,13 @@ public override Task DeleteUserDefinedFunctionAsync CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteUserDefinedFunctionAsync), - requestOptions, - (trace) => base.DeleteUserDefinedFunctionAsync(id, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteUserDefinedFunctionAsync), + containerName: this.container.Id, + databaseName: this.container.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteUserDefinedFunctionAsync(id, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/User/UserInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/User/UserInlineCore.cs index 6969e67d3e..c50ab7ff22 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/User/UserInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/User/UserInlineCore.cs @@ -26,10 +26,13 @@ public override Task ReadAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReadAsync), - requestOptions, - (trace) => base.ReadAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReadAsync), + containerName: null, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Read, + requestOptions: requestOptions, + task: (trace) => base.ReadAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task ReplaceAsync( @@ -38,10 +41,13 @@ public override Task ReplaceAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(ReplaceAsync), - requestOptions, - (trace) => base.ReplaceAsync(userProperties, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(ReplaceAsync), + containerName: null, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Replace, + requestOptions: requestOptions, + task: (trace) => base.ReplaceAsync(userProperties, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task DeleteAsync( @@ -49,10 +55,13 @@ public override Task DeleteAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(DeleteAsync), - requestOptions, - (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(DeleteAsync), + containerName: null, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Delete, + requestOptions: requestOptions, + task: (trace) => base.DeleteAsync(requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Permission GetPermission(string id) @@ -67,10 +76,13 @@ public override Task CreatePermissionAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(CreatePermissionAsync), - requestOptions, - (trace) => base.CreatePermissionAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(CreatePermissionAsync), + containerName: null, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Create, + requestOptions: requestOptions, + task: (trace) => base.CreatePermissionAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override Task UpsertPermissionAsync( @@ -80,10 +92,13 @@ public override Task UpsertPermissionAsync( CancellationToken cancellationToken = default) { return this.ClientContext.OperationHelperAsync( - nameof(UpsertPermissionAsync), - requestOptions, - (trace) => base.UpsertPermissionAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), - (response) => new OpenTelemetryResponse(response)); + operationName: nameof(UpsertPermissionAsync), + containerName: null, + databaseName: this.Database.Id, + operationType: Documents.OperationType.Upsert, + requestOptions: requestOptions, + task: (trace) => base.UpsertPermissionAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(response)); } public override FeedIterator GetPermissionQueryIterator( diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index d53dab1e50..41ae6e1e77 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -26,7 +26,9 @@ public static bool IsEnabled(EventLevel level) } [NonEvent] - public static void RecordDiagnosticsForRequests(DistributedTracingOptions config, + public static void RecordDiagnosticsForRequests( + DistributedTracingOptions config, + Documents.OperationType operationType, OpenTelemetryAttributes response) { if (CosmosDbEventSource.IsEnabled(EventLevel.Informational)) @@ -37,6 +39,7 @@ public static void RecordDiagnosticsForRequests(DistributedTracingOptions config { if (DiagnosticsFilterHelper.IsTracingNeeded( config: config, + operationType: operationType, response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) { CosmosDbEventSource.Singleton.WriteWarningEvent(response.Diagnostics.ToString()); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index 56a4abd648..e4db97bc3f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -17,6 +17,7 @@ internal static class DiagnosticsFilterHelper /// true or false public static bool IsTracingNeeded( DistributedTracingOptions config, + OperationType operationType, OpenTelemetryAttributes response) { TimeSpan latencyThreshold; @@ -27,7 +28,7 @@ public static bool IsTracingNeeded( } else { - latencyThreshold = response.OperationType == OperationType.Query.ToOperationTypeString() ? DistributedTracingOptions.DefaultQueryTimeoutThreshold : DistributedTracingOptions.DefaultCrudLatencyThreshold; + latencyThreshold = operationType == OperationType.Query ? DistributedTracingOptions.DefaultQueryTimeoutThreshold : DistributedTracingOptions.DefaultCrudLatencyThreshold; } return response.Diagnostics.GetClientElapsedTime() > latencyThreshold || !response.StatusCode.IsSuccess(); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs index 636ccd5714..3d9ee4afbb 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs @@ -18,12 +18,9 @@ internal OpenTelemetryAttributes() { } - internal OpenTelemetryAttributes(RequestMessage requestMessage, string containerName, string databaseName) + internal OpenTelemetryAttributes(RequestMessage requestMessage) { this.RequestContentLength = requestMessage?.Headers?.ContentLength ?? OpenTelemetryAttributes.NotAvailable; - this.OperationType = requestMessage?.OperationType.ToOperationTypeString() ?? OpenTelemetryAttributes.NotAvailable; - this.DatabaseName = requestMessage?.DatabaseId ?? databaseName ?? OpenTelemetryAttributes.NotAvailable; - this.ContainerName = requestMessage?.ContainerId ?? containerName ?? OpenTelemetryAttributes.NotAvailable; } /// @@ -46,16 +43,6 @@ internal OpenTelemetryAttributes(RequestMessage requestMessage, string container /// internal string ResponseContentLength { get; set; } - /// - /// DatabaseName - /// - internal string DatabaseName { get; set; } - - /// - /// ContainerName - /// - internal string ContainerName { get; set; } - /// /// ItemCount /// @@ -66,11 +53,6 @@ internal OpenTelemetryAttributes(RequestMessage requestMessage, string container /// internal CosmosDiagnostics Diagnostics { get; set; } - /// - /// OperationType - /// - internal string OperationType { get; set; } - /// /// SubStatusCode /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index c70b14a550..b8be214392 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -7,7 +7,9 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System; using System.Collections.Generic; using Diagnostics; + using global::Azure; using global::Azure.Core.Pipeline; + using HdrHistogram; internal struct OpenTelemetryCoreRecorder : IDisposable { @@ -16,6 +18,8 @@ internal struct OpenTelemetryCoreRecorder : IDisposable private readonly DiagnosticScope scope; private readonly DistributedTracingOptions config; + private readonly Documents.OperationType operationType; + internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() { { typeof(CosmosNullReferenceException), (exception, scope) => CosmosNullReferenceException.RecordOtelAttributes((CosmosNullReferenceException)exception, scope)}, @@ -25,16 +29,28 @@ internal struct OpenTelemetryCoreRecorder : IDisposable { typeof(ChangeFeedProcessorUserException), (exception, scope) => ChangeFeedProcessorUserException.RecordOtelAttributes((ChangeFeedProcessorUserException)exception, scope)} }; - public OpenTelemetryCoreRecorder(DiagnosticScope scope, CosmosClientContext clientContext, DistributedTracingOptions config) + public OpenTelemetryCoreRecorder( + DiagnosticScope scope, + string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, + CosmosClientContext clientContext, DistributedTracingOptions config) { this.scope = scope; this.config = config; - + this.operationType = operationType; + if (this.IsEnabled) { this.scope.Start(); - this.Record(clientContext); + this.Record( + operationName: operationName, + containerName: containerName, + databaseName: databaseName, + operationType: operationType, + clientContext: clientContext); } } @@ -47,15 +63,29 @@ public void Record(string key, string value) this.scope.AddAttribute(key, value); } } - + /// - /// System Level and Client level attributes + /// Recording information /// + /// + /// + /// + /// /// - public void Record(CosmosClientContext clientContext) + public void Record( + string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, + CosmosClientContext clientContext) { if (this.IsEnabled) { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbOperation, operationName); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, operationType); + // Other information this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb); this.scope.AddAttribute(OpenTelemetryAttributeKeys.MachineId, VmMetadataApiHandler.GetMachineId()); @@ -76,21 +106,17 @@ public void Record(OpenTelemetryAttributes response) { if (this.IsEnabled) { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, response.DatabaseName); - - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, response.ContainerName); this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, response.RequestContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, response.ResponseContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, response.StatusCode); this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, response.SubStatusCode); this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, response.RequestCharge); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, response.ItemCount); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, response.OperationType); - + if (response.Diagnostics != null) { this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions()) ?? OpenTelemetryAttributes.NotAvailable); - CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, response); + CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, this.operationType, response); } else { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index f72954045b..c66339e51e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -10,7 +10,10 @@ internal static class OpenTelemetryRecorderFactory { private static DiagnosticScopeFactory ScopeFactory { get; set; } - public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, + public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, RequestOptions requestOptions, CosmosClientContext clientContext) { @@ -27,6 +30,10 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, { return new OpenTelemetryCoreRecorder( scope: scope, + operationName: operationName, + containerName: containerName, + databaseName: databaseName, + operationType: operationType, clientContext: clientContext, config: requestOptions?.DistributedTracingOptions ?? clientContext.ClientOptions?.DistributedTracingOptions); } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs index 0547fda4bd..7bb1fdc12e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs @@ -10,29 +10,25 @@ namespace Microsoft.Azure.Cosmos internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes { - internal OpenTelemetryResponse(TransactionalBatchResponse responseMessage, string containerName = null, string databaseName = null) + internal OpenTelemetryResponse(TransactionalBatchResponse responseMessage) : this( statusCode: responseMessage.StatusCode, requestCharge: responseMessage.Headers?.RequestCharge, responseContentLength: null, diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, - databaseName: databaseName, - containerName: containerName, requestMessage: null, subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } - internal OpenTelemetryResponse(ResponseMessage responseMessage, string containerName = null, string databaseName = null) + internal OpenTelemetryResponse(ResponseMessage responseMessage) : this( statusCode: responseMessage.StatusCode, requestCharge: responseMessage.Headers?.RequestCharge, responseContentLength: OpenTelemetryResponse.GetPayloadSize(responseMessage), diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, - databaseName: databaseName, - containerName: containerName, requestMessage: responseMessage.RequestMessage, subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { @@ -44,11 +40,9 @@ private OpenTelemetryResponse( string responseContentLength, CosmosDiagnostics diagnostics, string itemCount, - string databaseName, - string containerName, RequestMessage requestMessage, int subStatusCode) - : base(requestMessage, containerName, databaseName) + : base(requestMessage) { this.StatusCode = statusCode; this.RequestCharge = requestCharge; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs index 68301f4f4e..3d7359da75 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs @@ -9,29 +9,25 @@ namespace Microsoft.Azure.Cosmos internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes { - internal OpenTelemetryResponse(FeedResponse responseMessage, string containerName = null, string databaseName = null) + internal OpenTelemetryResponse(FeedResponse responseMessage) : this( statusCode: responseMessage.StatusCode, requestCharge: responseMessage.Headers?.RequestCharge, responseContentLength: responseMessage?.Headers?.ContentLength, diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, - databaseName: databaseName, - containerName: containerName, requestMessage: responseMessage.RequestMessage, subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { } - internal OpenTelemetryResponse(Response responseMessage, string containerName = null, string databaseName = null) + internal OpenTelemetryResponse(Response responseMessage) : this( statusCode: responseMessage.StatusCode, requestCharge: responseMessage.Headers?.RequestCharge, responseContentLength: responseMessage?.Headers?.ContentLength, diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, - databaseName: databaseName, - containerName: containerName, requestMessage: responseMessage.RequestMessage, subStatusCode: (int)responseMessage.Headers?.SubStatusCode) { @@ -43,11 +39,9 @@ private OpenTelemetryResponse( string responseContentLength, CosmosDiagnostics diagnostics, string itemCount, - string databaseName, - string containerName, RequestMessage requestMessage, int subStatusCode) - : base(requestMessage, containerName, databaseName) + : base(requestMessage) { this.StatusCode = statusCode; this.RequestCharge = requestCharge; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 49f8d13a83..15d67f3483 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Cosmos.ExecuteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 41dca40b1e..bc0240518f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -134,16 +134,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -292,16 +292,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -450,16 +450,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -608,16 +608,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -766,16 +766,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -924,16 +924,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1082,16 +1082,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1240,16 +1240,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1398,16 +1398,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1556,16 +1556,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2288,7 +2288,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 07da410dcf..1a1f0b40ee 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -952,11 +952,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1569,11 +1569,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2167,11 +2167,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2785,11 +2785,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3066,8 +3066,8 @@ } ] }]]> - Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index a011bb4d54..bffa1a103a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -107,8 +107,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -207,8 +207,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 3d7eb4ca65..d87ec949cd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -148,7 +148,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -391,7 +391,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -616,7 +616,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -873,7 +873,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1194,7 +1194,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1348,7 +1348,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 5909fa5328..5368aad0e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -574,10 +574,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1180,10 +1180,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1767,10 +1767,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2374,10 +2374,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3048,10 +3048,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3644,10 +3644,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4260,10 +4260,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index b5ed674d20..8860741fc2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -536,10 +536,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1104,10 +1104,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1653,10 +1653,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2222,10 +2222,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 4aec783e49..5cc059c7a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -542,12 +542,12 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1112,7 +1112,7 @@ } ] }]]> - Cosmos.ReadManyItemsAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 59937f5675..665f74396c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -89,7 +89,7 @@ } ] }]]> - Cosmos.CreateItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -178,7 +178,7 @@ } ] }]]> - Cosmos.ReadItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -275,7 +275,7 @@ } ] }]]> - Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -367,7 +367,7 @@ } ] }]]> - Cosmos.DeleteItemStreamAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 8eb9eebaea..8042b6e21d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -109,7 +109,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -203,7 +203,7 @@ } ] }]]> - Cosmos.ReadItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -310,7 +310,7 @@ } ] }]]> - Cosmos.ReplaceItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -406,7 +406,7 @@ } ] }]]> - Cosmos.DeleteItemAsynckindaz.namespacedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.operation_typedb.cosmosdb.regions_contacted + Cosmos.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml index 1d67b08708..cff22b3e76 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.Spatial.xml @@ -478,8 +478,7 @@ ST_WITHIN Geography - SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, - {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) /key @@ -513,8 +512,7 @@ ST_WITHIN Geometry - SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, - {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) + SELECT * FROM c WHERE NOT ST_WITHIN(c.geojson, {'type':'Polygon','coordinates':[[[-60,20], [70,20], [70,70], [-60,70], [-60,20]]]}) /key diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs index 28913390ec..044a735734 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs @@ -757,13 +757,16 @@ private static CosmosClientContext MockClientContext() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.IsAny(), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType,requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); return mockContext.Object; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs index a51ff0ef3a..993afa449b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs @@ -345,13 +345,16 @@ private Mock MockClientContext() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.IsAny(), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName,containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); mockContext.Setup(x => x.Client).Returns(MockCosmosUtil.CreateMockCosmosClient()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncStreamerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncStreamerTests.cs index 9e72ada29b..896eb0fade 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncStreamerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncStreamerTests.cs @@ -201,13 +201,16 @@ private CosmosClientContext GetMockClientContext() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.IsAny(), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); return mockContext.Object; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs index 4b9a50c75d..4cc722528b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs @@ -336,13 +336,16 @@ static FeedIteratorInternal feedCreator(DocumentServiceLease lease, string conti mockedContext.Setup(c => c.Client).Returns(MockCosmosUtil.CreateMockCosmosClient()); mockedContext.Setup(x => x.OperationHelperAsync>( It.Is(str => str.Contains("Change Feed Estimator")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>>(), It.IsAny, OpenTelemetryAttributes>>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { @@ -355,7 +358,7 @@ static FeedIteratorInternal feedCreator(DocumentServiceLease lease, string conti Mock mockedMonitoredContainer = new Mock(MockBehavior.Strict); mockedMonitoredContainer.Setup(c => c.GetCachedRIDAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(monitoredContainerRid); mockedMonitoredContainer.Setup(c => c.ClientContext).Returns(mockedContext.Object); - + mockedMonitoredContainer.Setup(c => c.Id).Returns("containerId"); Mock leaseFeedIterator = new Mock(); leaseFeedIterator.Setup(i => i.HasMoreResults).Returns(false); @@ -425,15 +428,21 @@ private static ContainerInternal GetMockedContainer() Mock mockContext = new Mock(MockBehavior.Strict); mockContext.Setup(x => x.Client).Returns(mockClient.Object); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); + containerMock.Setup(c => c.Id).Returns("containerId"); + containerMock.Setup(c => c.Database.Id).Returns("databaseId"); + mockContext.Setup(x => x.OperationHelperAsync>( It.Is(str => str.Contains("Change Feed Estimator")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>>(), It.IsAny, OpenTelemetryAttributes>>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs index 42de6190f4..ebbb837943 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs @@ -41,13 +41,16 @@ public async Task EtagPassesContinuation() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.Is(str => str.Contains("Change Feed Processor")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>,Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>,Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { @@ -70,7 +73,9 @@ public async Task EtagPassesContinuation() ).ReturnsAsync(responseMessage); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); - + containerMock.Setup(c => c.Id).Returns("containerId"); + containerMock.Setup(c => c.Database.Id).Returns("databaseId"); + ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, @@ -115,13 +120,16 @@ public async Task NextReadHasUpdatedContinuation() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.Is(str => str.Contains("Change Feed Processor")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { @@ -146,7 +154,9 @@ public async Task NextReadHasUpdatedContinuation() .ReturnsAsync(secondResponse); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); - + containerMock.Setup(c => c.Id).Returns("containerId"); + containerMock.Setup(c => c.Database.Id).Returns("databaseId"); + ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, @@ -179,13 +189,16 @@ public async Task ShouldSetFeedRangePartitionKeyRange() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.Is(str => str.Contains("Change Feed Processor")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { @@ -208,7 +221,9 @@ public async Task ShouldSetFeedRangePartitionKeyRange() ).ReturnsAsync(new ResponseMessage(System.Net.HttpStatusCode.OK)); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); - + containerMock.Setup(c => c.Id).Returns("containerId"); + containerMock.Setup(c => c.Database.Id).Returns("databaseId"); + ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, continuationToken: null, @@ -255,13 +270,16 @@ public async Task ShouldUseFeedRangeEpk() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.Is(str => str.Contains("Change Feed Processor")), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.Is(tc => tc == TraceComponent.ChangeFeed), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => { using (ITrace trace = Trace.GetRootTrace(operationName, comp, level)) { @@ -283,7 +301,10 @@ public async Task ShouldUseFeedRangeEpk() ) ).ReturnsAsync(new ResponseMessage(System.Net.HttpStatusCode.OK)); containerMock.Setup(c => c.ClientContext).Returns(mockContext.Object); - containerMock.Setup(c => c.LinkUri).Returns("http://localhot"); + containerMock.Setup(c => c.LinkUri).Returns("http://localhost"); + containerMock.Setup(c => c.Id).Returns("containerId"); + containerMock.Setup(c => c.Database.Id).Returns("databaseId"); + MockDocumentClient mockDocumentClient = new MockDocumentClient(); mockContext.Setup(c => c.DocumentClient).Returns(mockDocumentClient); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosDiagnosticsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosDiagnosticsUnitTests.cs index 905fbd8757..404955997d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosDiagnosticsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosDiagnosticsUnitTests.cs @@ -93,9 +93,12 @@ public async Task ValidateActivityId() new CosmosClientOptions()); Guid result = await clientContext.OperationHelperAsync( - nameof(ValidateActivityId), - new RequestOptions(), - (trace) => this.ValidateActivityIdHelper()); + operationName: nameof(ValidateActivityId), + containerName: null, + databaseName: null, + operationType: Documents.OperationType.Replace, + requestOptions: new RequestOptions(), + task: (trace) => this.ValidateActivityIdHelper()); Assert.AreEqual(Guid.Empty, System.Diagnostics.Trace.CorrelationManager.ActivityId, "ActivityScope was not disposed of"); } @@ -119,9 +122,12 @@ public async Task ValidateActivityIdWithSynchronizationContext() SynchronizationContext.SetSynchronizationContext(mockSynchronizationContext.Object); Guid result = await clientContext.OperationHelperAsync( - nameof(ValidateActivityIdWithSynchronizationContext), - new RequestOptions(), - (trace) => this.ValidateActivityIdHelper()); + operationName: nameof(ValidateActivityIdWithSynchronizationContext), + containerName: null, + databaseName: null, + operationType: Documents.OperationType.Replace, + requestOptions: new RequestOptions(), + task: (trace) => this.ValidateActivityIdHelper()); Assert.AreEqual(Guid.Empty, System.Diagnostics.Trace.CorrelationManager.ActivityId, "ActivityScope was not disposed of"); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosItemUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosItemUnitTests.cs index 589ad47efc..5f9b3d3dad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosItemUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosItemUnitTests.cs @@ -711,23 +711,29 @@ public async Task TestMultipleNestedPartitionKeyValueFromStreamAsync() mockContext.Setup(x => x.OperationHelperAsync( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.IsAny(), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); mockContext.Setup(x => x.OperationHelperAsync>( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>>(), It.IsAny, OpenTelemetryAttributes>>(), It.IsAny(), It.IsAny())) - .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>>, Func, OpenTelemetryAttributes>, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); mockContext.Setup(x => x.ProcessResourceOperationStreamAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/FeedRange/ChangeFeedIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/FeedRange/ChangeFeedIteratorCoreTests.cs index 32bbc1173f..6594bd926e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/FeedRange/ChangeFeedIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/FeedRange/ChangeFeedIteratorCoreTests.cs @@ -477,13 +477,16 @@ private CosmosClientContext MockClientContext() Mock mockContext = new Mock(); mockContext.Setup(x => x.OperationHelperAsync( It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), It.IsAny>>(), It.IsAny>(), It.IsAny(), It.IsAny())) - .Returns>, Func, TraceComponent, TraceLevel>( - (operationName, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); + .Returns>, Func, TraceComponent, TraceLevel>( + (operationName, containerName, databaseName, operationType, requestOptions, func, oTelFunc, comp, level) => func(NoOpTrace.Singleton)); return mockContext.Object; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index b86883c451..9474239569 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -49,7 +49,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() Assert.IsFalse( DiagnosticsFilterHelper - .IsTracingNeeded(distributedTracingOptions, response), + .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}" ); @@ -74,7 +74,7 @@ public void CheckReturnTrueOnFailedStatusCode() Assert.IsTrue( DiagnosticsFilterHelper - .IsTracingNeeded(distributedTracingOptions, response), + .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); From 9c2015bb47f53e92cdc78fd0c105896aefe9d859 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 16 Nov 2022 20:11:55 +0530 Subject: [PATCH 015/337] [Internal] AI Integration: Adds a new flag in DistributedTracingOptions (#3562) * add flag in diagnostic options * test fixes * rename variable * test fix * add validation * fix baseline * test fix Co-authored-by: Sourabh Jain --- .../OpenTelemetry/CosmosDbEventSource.cs | 2 +- .../DistributedTracingOptions.cs | 33 ++++++++++++++++++- ...riterBaselineTests.BulkOperationsAsync.xml | 2 +- ...neTests.PointOperationsExceptionsAsync.xml | 2 +- .../EndToEndTraceWriterBaselineTests.cs | 13 ++++---- .../ChangeFeedEstimatorIteratorTests.cs | 1 + .../CosmosClientOptionsUnitTests.cs | 19 +++++++++++ .../Telemetry/DiagnosticsFilterHelperTest.cs | 4 +-- 8 files changed, 63 insertions(+), 13 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index 41ae6e1e77..f0ac635d81 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -31,7 +31,7 @@ public static void RecordDiagnosticsForRequests( Documents.OperationType operationType, OpenTelemetryAttributes response) { - if (CosmosDbEventSource.IsEnabled(EventLevel.Informational)) + if (config.EnableDiagnosticsTraceForAllRequests) { CosmosDbEventSource.Singleton.WriteInfoEvent(response.Diagnostics.ToString()); } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs index 34c7ae69dc..078a554980 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs @@ -21,12 +21,43 @@ internal sealed class DistributedTracingOptions /// Default Latency threshold for QUERY operation /// internal static readonly TimeSpan DefaultQueryTimeoutThreshold = TimeSpan.FromMilliseconds(500); + private bool enableDiagnosticsTraceForAllRequests; + private TimeSpan? diagnosticsLatencyThreshold; /// /// Latency Threshold to generate () with Request diagnostics in distributing Tracing.

/// If it is not set then by default it will generate () for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. ///
- public TimeSpan? DiagnosticsLatencyThreshold { get; set; } + public TimeSpan? DiagnosticsLatencyThreshold + { + get => this.diagnosticsLatencyThreshold; + set + { + if (this.EnableDiagnosticsTraceForAllRequests) + { + throw new ArgumentException("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold."); + } + + this.diagnosticsLatencyThreshold = value; + } + } + /// + /// Set this flag as true if you want to generate () containing request diagnostics string for all the operations. + /// If this flag is true then, it won't honour value to generate diagnostic traces. + /// + public bool EnableDiagnosticsTraceForAllRequests + { + get => this.enableDiagnosticsTraceForAllRequests; + set + { + if (value && this.DiagnosticsLatencyThreshold != null) + { + throw new ArgumentException("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold."); + } + + this.enableDiagnosticsTraceForAllRequests = value; + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index bc0240518f..a31ad6433d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -1602,7 +1602,7 @@ throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(DiagnosticsLatencyThresholdValue) + EnableDiagnosticsTraceForAllRequests = true }; ItemRequestOptions requestOptions = new ItemRequestOptions(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index d87ec949cd..019adb993e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -175,7 +175,7 @@ throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(DiagnosticsLatencyThresholdValue) + EnableDiagnosticsTraceForAllRequests = true }; ItemRequestOptions requestOptions = new ItemRequestOptions(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 855bea096d..aea21c9655 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -37,8 +37,7 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests mockedMonitoredContainer = new Mock(MockBehavior.Strict); mockedMonitoredContainer.Setup(c => c.GetCachedRIDAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(monitoredContainerRid); mockedMonitoredContainer.Setup(c => c.ClientContext).Returns(mockedContext.Object); + mockedMonitoredContainer.Setup(c => c.Database.Id).Returns("databaseId"); mockedMonitoredContainer.Setup(c => c.Id).Returns("containerId"); Mock leaseFeedIterator = new Mock(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index e39bb8d0f3..6078570d96 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -186,6 +186,25 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, policy.PortReuseMode); Assert.IsTrue(policy.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); + + // Verify DiagnosticsLatencyThreshold + cosmosClientBuilder = new CosmosClientBuilder( + accountEndpoint: endpoint, + authKeyOrResourceToken: key); + var exception = Assert.ThrowsException(() => cosmosClientBuilder.WithConnectionModeDirect( + idleTcpConnectionTimeout, + openTcpConnectionTimeout, + maxRequestsPerTcpConnection, + maxTcpConnectionsPerEndpoint, + portReuseMode, + enableTcpConnectionEndpointRediscovery) + .WithApplicationPreferredRegions(preferredLocations) + .WithDistributingTracing(new DistributedTracingOptions + { + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(100), + EnableDiagnosticsTraceForAllRequests = true + })); + Assert.AreEqual("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold.", exception.Message); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 9474239569..98f4d62954 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -38,7 +38,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(20) + DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -63,7 +63,7 @@ public void CheckReturnTrueOnFailedStatusCode() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(20) + DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes From c38346dd8d029bf32dc523c678b6df95e8c1b9b9 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Wed, 16 Nov 2022 17:05:16 -0800 Subject: [PATCH 016/337] Query: Fixes default to BadRequestException in case of internal errors in ServiceInterop (#3399) * Don't default to BadRequestException in case of errors in ServiceInterop * Incorporate code review feedback * Fix build error * fix up failing test --- .../Query/Core/ExceptionToCosmosException.cs | 32 +++++++-------- .../Core/QueryPlan/QueryPlanRetriever.cs | 16 +++----- .../Query/QueryPlanRetrieverTests.cs | 39 +++++++++++++++++-- 3 files changed, 56 insertions(+), 31 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ExceptionToCosmosException.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ExceptionToCosmosException.cs index 966c603f5d..02c1882e26 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ExceptionToCosmosException.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ExceptionToCosmosException.cs @@ -76,32 +76,28 @@ private static bool TryCreateFromExceptionWithStackTrace( ITrace trace, out CosmosException cosmosException) { - // Use the original stack trace from the inner exception. - if (exceptionWithStackTrace.InnerException is Microsoft.Azure.Documents.DocumentClientException - || exceptionWithStackTrace.InnerException is CosmosException) - { - return ExceptionToCosmosException.TryCreateFromException( - exceptionWithStackTrace.InnerException, - trace, - out cosmosException); - } + Exception innerException = ExceptionWithStackTraceException.UnWrapMonadExcepion(exceptionWithStackTrace, trace); if (!ExceptionToCosmosException.TryCreateFromException( - exceptionWithStackTrace.InnerException, + innerException, trace, out cosmosException)) { return false; } - cosmosException = CosmosExceptionFactory.Create( - cosmosException.StatusCode, - cosmosException.Message, - exceptionWithStackTrace.StackTrace, - headers: cosmosException.Headers, - cosmosException.Trace, - cosmosException.Error, - cosmosException.InnerException); + if (innerException is not CosmosException && innerException is not Documents.DocumentClientException) + { + cosmosException = CosmosExceptionFactory.Create( + cosmosException.StatusCode, + cosmosException.Message, + exceptionWithStackTrace.StackTrace, + headers: cosmosException.Headers, + cosmosException.Trace, + cosmosException.Error, + cosmosException.InnerException); + } + return true; } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs index 32e061dfd8..09ad98f395 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPlanRetriever.cs @@ -76,18 +76,14 @@ public static async Task GetQueryPlanWithServiceI if (!tryGetQueryPlan.Succeeded) { - Exception originalException = ExceptionWithStackTraceException.UnWrapMonadExcepion(tryGetQueryPlan.Exception, serviceInteropTrace); - if (originalException is CosmosException) + if (ExceptionToCosmosException.TryCreateFromException(tryGetQueryPlan.Exception, serviceInteropTrace, out CosmosException cosmosException)) { - throw originalException; + throw cosmosException; + } + else + { + throw ExceptionWithStackTraceException.UnWrapMonadExcepion(tryGetQueryPlan.Exception, serviceInteropTrace); } - - throw CosmosExceptionFactory.CreateBadRequestException( - message: originalException.Message, - headers: new Headers(), - stackTrace: tryGetQueryPlan.Exception.StackTrace, - innerException: originalException, - trace: trace); } return tryGetQueryPlan.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs index 47a681eb1a..c1dc2fc3ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanRetrieverTests.cs @@ -41,7 +41,6 @@ public async Task ServiceInterop_BadRequestContainsInnerException() It.IsAny(), It.IsAny())).ReturnsAsync(TryCatch.FromException(innerException)); - Mock trace = new Mock(); CosmosException cosmosException = await Assert.ThrowsExceptionAsync(() => QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( queryClient.Object, new SqlQuerySpec("selectttttt * from c"), @@ -50,8 +49,7 @@ public async Task ServiceInterop_BadRequestContainsInnerException() hasLogicalPartitionKey: false, geospatialType: Cosmos.GeospatialType.Geography, useSystemPrefix: false, - trace.Object, - default)); + NoOpTrace.Singleton)); Assert.AreEqual(HttpStatusCode.BadRequest, cosmosException.StatusCode); Assert.AreEqual(innerException, cosmosException.InnerException); @@ -92,5 +90,40 @@ public async Task ServiceInterop_BadRequestContainsOriginalCosmosException() Assert.AreEqual(expectedException, cosmosException); } + + [TestMethod] + public async Task ServiceInterop_E_UNEXPECTED() + { + UnexpectedQueryPartitionProviderException innerException = new UnexpectedQueryPartitionProviderException("E_UNEXPECTED"); + Mock queryClient = new Mock(); + + queryClient.Setup(c => c.TryGetPartitionedQueryExecutionInfoAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(TryCatch.FromException(innerException)); + + CosmosException cosmosException = await Assert.ThrowsExceptionAsync(() => QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( + queryClient.Object, + new SqlQuerySpec("Super secret query that triggers bug"), + ResourceType.Document, + new Documents.PartitionKeyDefinition() { Paths = new Collection() { "/id" } }, + hasLogicalPartitionKey: false, + geospatialType: Cosmos.GeospatialType.Geography, + useSystemPrefix: false, + NoOpTrace.Singleton)); + + Assert.AreEqual(HttpStatusCode.InternalServerError, cosmosException.StatusCode); + Assert.AreEqual(innerException, cosmosException.InnerException); + Assert.IsNotNull(cosmosException.Trace); + Assert.IsNotNull(cosmosException.Diagnostics); + } } } From 9cafaa85c651761fe9eb099e996afb6e1f2dd149 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:18:45 -0800 Subject: [PATCH 017/337] [Internal] Query: Adds unit tests for Merge/Split implementation with OptimisticDirectExecution pipeline (#3510) * Added tests to test different aspects of merge/split support with OptimisticDirectExecution pipeline. Tests check for gone exception handling, pipeline switching etc. * Added gone exception simulation tests. * Added new tests and improved test infra * Removed ParalleContEvocation test. Fixed comments * Removed CreateParallelCrossPartitionPipelineStateAsync() as it is not being used anymore * Removed while loop in CreateDocumentContainerAsync() * Fixed comments. * Updated ExecuteGoneExceptionOnODEPipeline() * Added type Assert for ExecuteGoneExceptionOnODEPipeline() * Updated OptimisticDirectExecution pipeline abbreviation * Updated TestBaseline folder with new xml --- .../CosmosQueryExecutionContextFactory.cs | 4 +- ...ositiveOptimisticDirectExecutionOutput.xml | 12 +- ...misticDirectExecutionQueryBaselineTests.cs | 478 +++++++++--------- 3 files changed, 260 insertions(+), 234 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index fec5fa4d4a..4e6bacb145 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -266,7 +266,7 @@ private static async Task> TryCreateCoreContextAsy } } - public static async Task> TryCreateFromPartitionedQueryExecutionInfoAsync( + private static async Task> TryCreateFromPartitionedQueryExecutionInfoAsync( DocumentContainer documentContainer, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ContainerQueryProperties containerQueryProperties, @@ -537,7 +537,7 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx return targetRanges; } - public static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) + private static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) { TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; if (responseStats != null) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml index 950947ff5a..7d4f7ce18d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml @@ -1,8 +1,8 @@  - Partition Key + Value and Distinct - SELECT DISTINCT c.key FROM c + Single Partition Key and Distinct + SELECT DISTINCT c.age FROM c /pk @@ -14,8 +14,8 @@ - Partition Key + Value and Min Aggregate - SELECT VALUE MIN(c.key) FROM c + Single Partition Key and Min Aggregate + SELECT VALUE MIN(c.age) FROM c /pk @@ -27,8 +27,8 @@ - Partition Key + Value Fields - SELECT c.key FROM c + Single Partition Key and Value Field + SELECT c.age FROM c /pk diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 960235dcae..f849a04913 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -29,58 +29,110 @@ using System.IO; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.IdentityModel.Tokens; [TestClass] public class OptimisticDirectExecutionQueryBaselineTests : BaselineTests { [TestMethod] [Owner("akotalwar")] - public void TestPipelineNullContinuationToken() + public void PositiveOptimisticDirectExecutionOutput() { - Mock mockDocumentContainer = new Mock(); + List testVariations = new List + { + CreateInput( + description: @"Single Partition Key and Distinct", + query: "SELECT DISTINCT c.age FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: @"value"), - TryCatch monadicCreate = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: mockDocumentContainer.Object, - sqlQuerySpec: new SqlQuerySpec("SELECT VALUE COUNT(1) FROM c"), - targetRange: FeedRangeEpk.FullRange, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - cancellationToken: default, - continuationToken: null); - Assert.IsTrue(monadicCreate.Succeeded); + CreateInput( + description: @"Single Partition Key and Min Aggregate", + query: "SELECT VALUE MIN(c.age) FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: @"value"), + + CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT c.age FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: @"value"), + }; + this.ExecuteTestSuite(testVariations); } [TestMethod] [Owner("akotalwar")] - public void TestPipelineSingleContinuationToken() + public void NegativeOptimisticDirectExecutionOutput() { - Mock mockDocumentContainer = new Mock(); + List testVariations = new List + { + CreateInput( + description: @"Null Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: Cosmos.PartitionKey.Null), - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: "asdf", - range: new Documents.Routing.Range("A", "B", true, false)); + CreateInput( + description: @"None Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: Cosmos.PartitionKey.None), - OptimisticDirectExecutionContinuationToken token = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(token); + CreateInput( + description: @"C# Null Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: null), + }; + this.ExecuteTestSuite(testVariations); + } - TryCatch monadicCreate = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: mockDocumentContainer.Object, - sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c"), - targetRange: new FeedRangeEpk(new Documents.Routing.Range(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)), - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - cancellationToken: default, - continuationToken: cosmosElementContinuationToken); - Assert.IsTrue(monadicCreate.Succeeded); + // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. + // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done + [TestMethod] + public async Task TestDefaultTestInjectionSettings() + { + TestInjections testInjection = new TestInjections(simulate429s: false, simulateEmptyPages: false); + + Assert.AreEqual(testInjection.EnableOptimisticDirectExecution, false); } - // test checks that the pipeline can take a query to the backend and returns its associated document(s). [TestMethod] - public async Task TestPipelineForBackendDocumentsAsync() + [Owner("akotalwar")] + public async Task TestMonadicCreateOdePipeline() { int numItems = 10; + bool multiPartition = false; + string query = "SELECT * FROM c"; + + // null continuation token + Assert.IsTrue(await TryMonadicCreate(numItems, multiPartition, query, targetRange: FeedRangeEpk.FullRange, continuationToken: null)); + + CosmosElement cosmosElementContinuationToken = CosmosElement.Parse( + "{\"OptimisticDirectExecutionToken\":{\"token\":\"{\\\"resourceId\\\":\\\"AQAAAMmFOw8LAAAAAAAAAA==\\\",\\\"skipCount\\\":1}\"," + + "\"range\":{\"min\":\"\",\"max\":\"FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF\"}}}"); + Range range = new Documents.Routing.Range("", "FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF", isMinInclusive: true, isMaxInclusive: false); + + // single continuation token + Assert.IsTrue(await TryMonadicCreate(numItems, multiPartition, query, targetRange: new FeedRangeEpk(range), continuationToken: cosmosElementContinuationToken)); + + //TODO: Add non Ode continuation token case + } + + // test checks that the pipeline can take a query to the backend and returns its associated document(s). + [TestMethod] + public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() + { + int numItems = 100; string query = "SELECT VALUE COUNT(1) FROM c"; - IDocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: false); IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); int documentCountInSinglePartition = 0; @@ -92,17 +144,94 @@ public async Task TestPipelineForBackendDocumentsAsync() documentCountInSinglePartition += Int32.Parse(tryGetPage.Result.Documents[0].ToString()); } - Assert.AreEqual(documentCountInSinglePartition, 4); + Assert.AreEqual(100, documentCountInSinglePartition); } // test checks that the pipeline can take a query to the backend and returns its associated document(s) + continuation token. [TestMethod] - public async Task TestPipelineForContinuationTokenAsync() + public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() { int numItems = 100; - string query = "SELECT * FROM c"; - IDocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems); + int result = await this.CreateOptimisticPipelineAndDrainAsync( + numItems: numItems, + isMultiPartition: false, + query: "SELECT * FROM c", + expectedContinuationTokenCount: 10); + + Assert.AreEqual(numItems, result); + } + + // test to check if pipeline handles a 410 exception properly and returns all the documents. + [TestMethod] + public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync() + { + Assert.IsTrue(await ExecuteGoneExceptionOnOdePipeline(isMultiPartition: false)); + + Assert.IsTrue(await ExecuteGoneExceptionOnOdePipeline(isMultiPartition: true)); + } + + // The reason we have the below test is to show the missing capabilities of the OptimisticDirectExecution pipeline. + // Currently this pipeline cannot handle distributed queries as it does not have the logic to sum up the values it gets from the backend in partial results. + // This functionality is available for other pipelines such as the ParallelCrossPartitionQueryPipelineStage. + [TestMethod] + public async Task TestPipelineForDistributedQueryAsync() + { + int numItems = 100; + int result = await this.CreateOptimisticPipelineAndDrainAsync( + numItems: numItems, + isMultiPartition: false, + query: "SELECT AVG(c) FROM c", + expectedContinuationTokenCount: 0); + + //TODO: Add validation for actual value of average + Assert.AreEqual(1, result); + } + + private static async Task TryMonadicCreate(int numItems, bool multiPartition, string query, FeedRangeEpk targetRange, CosmosElement continuationToken) + { + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition); + + TryCatch monadicQueryPipelineStage = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( + documentContainer: inMemoryCollection, + sqlQuerySpec: new SqlQuerySpec(query), + targetRange: targetRange, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), + partitionKey: null, + cancellationToken: default, + continuationToken: continuationToken); + + return monadicQueryPipelineStage.Succeeded; + } + + private static async Task CreateOptimisticDirectExecutionPipelineStateAsync(DocumentContainer documentContainer, string query, CosmosElement continuationToken) + { + List targetRanges = await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + + // only one range is taken because Ode pipeline can only accept one range + FeedRangeEpk firstRange = targetRanges[0]; + + TryCatch monadicQueryPipelineStage = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: new SqlQuerySpec(query), + targetRange: firstRange, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), + partitionKey: null, + continuationToken: continuationToken, + cancellationToken: default); + + Assert.IsTrue(monadicQueryPipelineStage.Succeeded); + IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; + + return queryPipelineStage; + } + + private async Task CreateOptimisticPipelineAndDrainAsync(int numItems, bool isMultiPartition, string query, int expectedContinuationTokenCount) + { + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition); IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); + List documents = new List(); int continuationTokenCount = 0; @@ -125,126 +254,66 @@ public async Task TestPipelineForContinuationTokenAsync() continuationTokenCount++; } - Assert.AreEqual(continuationTokenCount, 2); - Assert.AreEqual(documents.Count, 17); + Assert.AreEqual(expectedContinuationTokenCount, continuationTokenCount); + return documents.Count; } - // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. - // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done - [TestMethod] - public async Task TestDefaultTestInjectionSettings() - { - TestInjections testInjection = new TestInjections(simulate429s: false, simulateEmptyPages: false); - - Assert.AreEqual(testInjection.EnableOptimisticDirectExecution, false); - } - - // The reason we have the below test is to show the missing capabilities of the OptimisticDirectExecution pipeline. - // Currently this pipeline cannot handle distributed queries as it does not have the logic to sum up the values it gets from the backend in partial results. - // This functionality is available for other pipelines such as the ParallelCrossPartitionQueryPipelineStage as evident below - [TestMethod] - public async Task TestPipelineForDistributedQueryAsync() + // it creates a gone exception after the first MoveNexyAsync() call. This allows for the pipeline to return some documents before failing + // TODO: With the addition of the merge/split support, this queryPipelineStage should be able to return all documents regardless of a gone exception happening + private static async Task ExecuteGoneExceptionOnOdePipeline(bool isMultiPartition) { int numItems = 100; - string query = "SELECT VALUE COUNT(1) FROM c"; - IDocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems); - IQueryPipelineStage optimisticDirectExecutionQueryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); - IQueryPipelineStage parallelQueryPipelineStage = await CreateParallelCrossPartitionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); - int documentCountOptimisticPipeline = 0; - int documentCountParallelPipeline = 0; - - List queryPipelineStages = new List - { - optimisticDirectExecutionQueryPipelineStage, - parallelQueryPipelineStage - }; - - List documentPipelinesCount = new List - { - documentCountOptimisticPipeline, - documentCountParallelPipeline - }; + string query = "SELECT * FROM c"; + List documents = new List(); + string goneExceptionMessage = $"Epk Range: Partition does not exist at the given range."; + CosmosException goneException = new CosmosException( + message: goneExceptionMessage, + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: "0f8fad5b-d9cb-469f-a165-70867728950e", + requestCharge: default); + + int moveNextAsyncCounter = 0; + bool caughtGoneException = false; + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync( + numItems, + multiPartition: isMultiPartition, + failureConfigs: new FlakyDocumentContainer.FailureConfigs( + inject429s: false, + injectEmptyPages: false, + shouldReturnFailure: () => Task.FromResult(moveNextAsyncCounter == 1 ? goneException : null))); - for (int i = 0; i < queryPipelineStages.Count(); i++) + IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { - while (await queryPipelineStages[i].MoveNextAsync(NoOpTrace.Singleton)) - { - TryCatch tryGetPage = queryPipelineStages[i].Current; - tryGetPage.ThrowIfFailed(); + moveNextAsyncCounter++; + TryCatch tryGetPage = queryPipelineStage.Current; - documentPipelinesCount[i] += Int32.Parse(tryGetPage.Result.Documents[0].ToString()); + if (tryGetPage.Failed == true) + { + string errorRecieved = tryGetPage.Exception.InnerException.Message; + Assert.AreEqual(goneException.GetType(), tryGetPage.Exception.InnerException.GetType()); - if (tryGetPage.Result.State == null) + if (errorRecieved.Equals(goneExceptionMessage)) { + caughtGoneException = true; break; } - else - { - queryPipelineStages[i] = queryPipelineStages[i].Equals(optimisticDirectExecutionQueryPipelineStage) - ? await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: tryGetPage.Result.State.Value) - : await CreateParallelCrossPartitionPipelineStateAsync(inMemoryCollection, query, continuationToken: tryGetPage.Result.State.Value); - } } - } - - documentCountOptimisticPipeline = documentPipelinesCount[0]; - documentCountParallelPipeline = documentPipelinesCount[1]; - int countDifference = documentCountParallelPipeline - documentCountOptimisticPipeline; - - Assert.AreNotEqual(documentCountOptimisticPipeline, documentCountParallelPipeline, countDifference.ToString()); - Assert.AreEqual(documentCountOptimisticPipeline, 17); - Assert.AreEqual(documentCountParallelPipeline, 100); - Assert.AreEqual(countDifference, 83); - Assert.AreEqual(documentCountParallelPipeline, numItems); - } - - private static async Task CreateOptimisticDirectExecutionPipelineStateAsync(IDocumentContainer documentContainer, string query, CosmosElement continuationToken) - { - List targetRanges = await documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - FeedRangeEpk firstRange = targetRanges[0]; - - TryCatch monadicQueryPipelineStage = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: documentContainer, - sqlQuerySpec: new SqlQuerySpec(query), - targetRange: firstRange, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - cancellationToken: default, - continuationToken: continuationToken); - - Assert.IsTrue(monadicQueryPipelineStage.Succeeded); - IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; - - return queryPipelineStage; - } - private static async Task CreateParallelCrossPartitionPipelineStateAsync(IDocumentContainer documentContainer, string query, CosmosElement continuationToken) - { - List targetRanges = await documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - - TryCatch monadicQueryPipelineStage = ParallelCrossPartitionQueryPipelineStage.MonadicCreate( - documentContainer: documentContainer, - sqlQuerySpec: new SqlQuerySpec(query), - targetRanges: targetRanges, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - maxConcurrency: 10, - prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, - continuationToken: continuationToken); + documents.AddRange(tryGetPage.Result.Documents); + } - Assert.IsTrue(monadicQueryPipelineStage.Succeeded); - IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; + // Once fallback plan is implemented, this test should be able to return all 100 documents + Assert.AreEqual(10, documents.Count); + Assert.IsTrue(caughtGoneException); - return queryPipelineStage; + return true; } - private static async Task CreateDocumentContainerAsync( + private static async Task CreateDocumentContainerAsync( int numItems, + bool multiPartition, FlakyDocumentContainer.FailureConfigs failureConfigs = null) { PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() @@ -265,107 +334,59 @@ private static async Task CreateDocumentContainerAsync( DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - for (int i = 0; i < 3; i++) + // a value of 2 would lead to 4 partitions (2 * 2). 4 partitions are used because they're easy to manage + demonstrates multi partition use case + int exponentPartitionKeyRanges = 2; + + IReadOnlyList ranges; + + for (int i = 0; i < exponentPartitionKeyRanges; i++) { - IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( + ranges = await documentContainer.GetFeedRangesAsync( trace: NoOpTrace.Singleton, cancellationToken: default); - foreach (FeedRangeInternal range in ranges) + + if (multiPartition) { - await documentContainer.SplitAsync(range, cancellationToken: default); + foreach (FeedRangeInternal range in ranges) + { + await documentContainer.SplitAsync(range, cancellationToken: default); + } } await documentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); } + ranges = await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + + int rangeCount = multiPartition ? 4 : 1; + + Assert.AreEqual(rangeCount, ranges.Count); + for (int i = 0; i < numItems; i++) { // Insert an item CosmosObject item = CosmosObject.Parse($"{{\"pk\" : {i} }}"); - while (true) - { - TryCatch monadicCreateRecord = await documentContainer.MonadicCreateItemAsync(item, cancellationToken: default); - if (monadicCreateRecord.Succeeded) - { - break; - } - } + TryCatch monadicCreateRecord = await documentContainer.MonadicCreateItemAsync(item, cancellationToken: default); + Assert.IsTrue(monadicCreateRecord.Succeeded); } return documentContainer; } - [TestMethod] - [Owner("akotalwar")] - public void PositiveOptimisticDirectExecutionOutput() - { - List testVariations = new List - { - CreateInput( - @"Partition Key + Value and Distinct", - "SELECT DISTINCT c.key FROM c", - true, - @"/pk", - @"/value"), - - CreateInput( - @"Partition Key + Value and Min Aggregate", - "SELECT VALUE MIN(c.key) FROM c", - true, - @"/pk", - @"/value"), - - CreateInput( - @"Partition Key + Value Fields", - "SELECT c.key FROM c", - true, - @"/pk", - @"/value"), - }; - this.ExecuteTestSuite(testVariations); - } - - [TestMethod] - [Owner("akotalwar")] - public void NegativeOptimisticDirectExecutionOutput() - { - List testVariations = new List - { - CreateInput( - @"Null Partition Key Value", - "SELECT * FROM c", - false, - @"/pk", - Cosmos.PartitionKey.Null), - - CreateInput( - @"None Partition Key Value", - "SELECT * FROM c", - false, - @"/pk", - Cosmos.PartitionKey.None), - - CreateInput( - @"C# Null Partition Key Value", - "SELECT * FROM c", - false, - @"/pk", - null), - }; - this.ExecuteTestSuite(testVariations); - } - private static OptimisticDirectExecutionTestInput CreateInput( string description, string query, bool expectedOptimisticDirectExecution, string partitionKeyPath, - string partitionKeyValue) + string partitionKeyValue, + CosmosElement continuationToken = null) { PartitionKeyBuilder pkBuilder = new PartitionKeyBuilder(); pkBuilder.Add(partitionKeyValue); - return CreateInput(description, query, expectedOptimisticDirectExecution, partitionKeyPath, pkBuilder.Build()); + return CreateInput(description, query, expectedOptimisticDirectExecution, partitionKeyPath, pkBuilder.Build(), continuationToken); } private static OptimisticDirectExecutionTestInput CreateInput( @@ -373,18 +394,19 @@ private static OptimisticDirectExecutionTestInput CreateInput( string query, bool expectedOptimisticDirectExecution, string partitionKeyPath, - Cosmos.PartitionKey partitionKeyValue) + Cosmos.PartitionKey partitionKeyValue, + CosmosElement continuationToken = null) { - return new OptimisticDirectExecutionTestInput(description, query, new SqlQuerySpec(query), expectedOptimisticDirectExecution, partitionKeyPath, partitionKeyValue); + return new OptimisticDirectExecutionTestInput(description, query, new SqlQuerySpec(query), expectedOptimisticDirectExecution, partitionKeyPath, partitionKeyValue, continuationToken); } - + private static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) { TryCatch tryGetQueryPlan = QueryPartitionProviderTestInstance.Object.TryGetPartitionedQueryExecutionInfo( querySpecJsonString: querySpecJsonString, partitionKeyDefinition: pkDefinition, requireFormattableOrderByQuery: true, - isContinuationExpected: false, + isContinuationExpected: true, allowNonValueAggregateQuery: true, hasLogicalPartitionKey: false, allowDCount: true, @@ -404,14 +426,14 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect // gets query context string databaseId = "db1234"; - string resourceLink = string.Format("dbs/{0}/colls", databaseId); + string resourceLink = $"dbs/{databaseId}/colls"; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( client: new TestCosmosQueryClient(), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, - isContinuationExpected: false, + isContinuationExpected: true, allowNonValueAggregateQuery: true, useSystemPrefix: false, correlatedActivityId: Guid.NewGuid()); @@ -419,7 +441,6 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect // gets input parameters QueryRequestOptions queryRequestOptions = new QueryRequestOptions { - MaxBufferedItemCount = 7000, TestSettings = new TestInjections(simulate429s: true, simulateEmptyPages: false, enableOptimisticDirectExecution: true, new TestInjections.ResponseStats()) }; @@ -435,7 +456,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, - initialUserContinuationToken: null, + initialUserContinuationToken: input.ContinuationToken, initialFeedRange: null, maxConcurrency: queryRequestOptions.MaxConcurrency, maxItemCount: queryRequestOptions.MaxItemCount, @@ -447,25 +468,27 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect returnResultsInDeterministicOrder: null, forcePassthrough: true, testInjections: queryRequestOptions.TestSettings); - + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, inputParameters, NoOpTrace.Singleton); + bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton).Result; if (input.ExpectedOptimisticDirectExecution) { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - else { + else + { Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - + Assert.IsNotNull(queryPipelineStage); Assert.IsTrue(result); - + return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); } } @@ -495,6 +518,7 @@ public sealed class OptimisticDirectExecutionTestInput : BaselineTestInput internal bool ExpectedOptimisticDirectExecution { get; set; } internal PartitionKeyRangeIdentity PartitionKeyRangeId { get; set; } internal string Query { get; set; } + internal CosmosElement ContinuationToken { get; set; } internal OptimisticDirectExecutionTestInput( string description, @@ -502,7 +526,8 @@ internal OptimisticDirectExecutionTestInput( SqlQuerySpec sqlQuerySpec, bool expectedOptimisticDirectExecution, string partitionKeyPath, - Cosmos.PartitionKey partitionKeyValue) + Cosmos.PartitionKey partitionKeyValue, + CosmosElement continuationToken) : base(description) { this.PartitionKeyDefinition = new PartitionKeyDefinition() @@ -518,6 +543,7 @@ internal OptimisticDirectExecutionTestInput( this.ExpectedOptimisticDirectExecution = expectedOptimisticDirectExecution; this.Query = query; this.PartitionKeyValue = partitionKeyValue; + this.ContinuationToken = continuationToken; } public override void SerializeAsXml(XmlWriter xmlWriter) @@ -533,7 +559,7 @@ public override void SerializeAsXml(XmlWriter xmlWriter) } } - xmlWriter.WriteEndElement(); + xmlWriter.WriteEndElement(); if (this.PartitionKeyDefinition != null) { xmlWriter.WriteElementString( @@ -596,8 +622,8 @@ public override Task> GetTargetPartitionKeyRangesAsync(s { return Task.FromResult(new List{new PartitionKeyRange() { - MinInclusive = PartitionKeyHash.V2.Hash("abc").ToString(), - MaxExclusive = PartitionKeyHash.V2.Hash("def").ToString() + MinInclusive = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, + MaxExclusive = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey } }); } From 2681be80b9674fc8a09f1a7552894ef8741b23e2 Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Fri, 18 Nov 2022 11:06:27 -0500 Subject: [PATCH 018/337] Client Retry Policy: Adds HTTP timeouts with request-level cross-region retry (#3555) * Fixes to ReadThroughputAsync for databases with no provisioned throughput and null as request options * fixed failure to ReadReplaceThroughputResponseTests * Added Stream Method * Ran UpdateContract.ps1 * Encryption implemtation * Fixed spelling error * Update Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabase.cs Co-authored-by: Matias Quaranta * Variable name change * Update Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs Co-authored-by: Matias Quaranta * Suggested Changes and fixes * Removed manufactured ResponseMessage + nits * Simplified PR * nits * nits * initial changes TODO: Update tests * updated tests * nits' * Ran UpdateContracts.ps1 * nits + requested changes * Delete NuGet.Config * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Use Cosmos Exception Factory, Simplified Tests * removed unused code * nits: removed unused code * removed unused code Co-authored-by: Matias Quaranta Co-authored-by: Nalu Tripician --- .../src/HttpClient/CosmosHttpClientCore.cs | 13 ++++ .../src/HttpClient/HttpTimeoutPolicy.cs | 26 +++++++- .../HttpTimeoutPolicyControlPlaneRead.cs | 2 + ...meoutPolicyControlPlaneRetriableHotPath.cs | 9 ++- .../HttpClient/HttpTimeoutPolicyDefault.cs | 9 ++- .../CosmosExceptionFactory.cs | 18 ++++++ .../CosmosHttpClientCoreTests.cs | 63 ++++++++++++++++++- .../GatewayAccountReaderTests.cs | 2 +- .../GatewayStoreModelTest.cs | 2 +- 9 files changed, 136 insertions(+), 8 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs index fa8463e64b..f86bd6b183 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs @@ -296,6 +296,19 @@ private async Task SendHttpHelperAsync( string message = $"GatewayStoreClient Request Timeout. Start Time UTC:{startDateTimeUtc}; Total Duration:{(DateTime.UtcNow - startDateTimeUtc).TotalMilliseconds} Ms; Request Timeout {requestTimeout.TotalMilliseconds} Ms; Http Client Timeout:{this.httpClient.Timeout.TotalMilliseconds} Ms; Activity id: {System.Diagnostics.Trace.CorrelationManager.ActivityId};"; e.Data.Add("Message", message); + + if (timeoutPolicy.ShouldThrow503OnTimeout) + { + throw CosmosExceptionFactory.CreateServiceUnavailableException( + message: message, + headers: new Headers() + { + ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), + SubStatusCode = SubStatusCodes.TransportGenerated503 + }, + innerException: e); + } + throw; } diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs index 413205cdba..a3fc51dd91 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs @@ -18,21 +18,45 @@ internal abstract class HttpTimeoutPolicy public abstract bool ShouldRetryBasedOnResponse(HttpMethod requestHttpMethod, HttpResponseMessage responseMessage); + public virtual bool ShouldThrow503OnTimeout => false; + public static HttpTimeoutPolicy GetTimeoutPolicy( DocumentServiceRequest documentServiceRequest) { + //Query Plan Requests if (documentServiceRequest.ResourceType == ResourceType.Document && documentServiceRequest.OperationType == OperationType.QueryPlan) { - return HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance; + return HttpTimeoutPolicyControlPlaneRetriableHotPath.InstanceShouldThrow503OnTimeout; } + //Partition Key Requests if (documentServiceRequest.ResourceType == ResourceType.PartitionKeyRange) { return HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance; } + //Data Plane Read & Write + if (!HttpTimeoutPolicy.IsMetaData(documentServiceRequest)) + { + return HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout; + } + + //Meta Data Read + if (HttpTimeoutPolicy.IsMetaData(documentServiceRequest) && documentServiceRequest.IsReadOnlyRequest) + { + return HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout; + } + + //Default behavior return HttpTimeoutPolicyDefault.Instance; } + + private static bool IsMetaData(DocumentServiceRequest request) + { + return (request.OperationType != Documents.OperationType.ExecuteJavaScript && request.ResourceType == ResourceType.StoredProcedure) || + request.ResourceType != ResourceType.Document; + + } } } diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs index 56c55901bb..757134a576 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs @@ -44,5 +44,7 @@ public override bool ShouldRetryBasedOnResponse(HttpMethod requestHttpMethod, Ht { return false; } + + public override bool ShouldThrow503OnTimeout => true; } } diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs index c8b8dbfb50..8dbb8a2a44 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs @@ -10,11 +10,14 @@ namespace Microsoft.Azure.Cosmos internal sealed class HttpTimeoutPolicyControlPlaneRetriableHotPath : HttpTimeoutPolicy { - public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyControlPlaneRetriableHotPath(); + public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyControlPlaneRetriableHotPath(false); + public static readonly HttpTimeoutPolicy InstanceShouldThrow503OnTimeout = new HttpTimeoutPolicyControlPlaneRetriableHotPath(true); + public bool shouldThrow503OnTimeout; private static readonly string Name = nameof(HttpTimeoutPolicyControlPlaneRetriableHotPath); - private HttpTimeoutPolicyControlPlaneRetriableHotPath() + private HttpTimeoutPolicyControlPlaneRetriableHotPath(bool shouldThrow503OnTimeout) { + this.shouldThrow503OnTimeout = shouldThrow503OnTimeout; } private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelays = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>() @@ -61,5 +64,7 @@ public override bool ShouldRetryBasedOnResponse(HttpMethod requestHttpMethod, Ht return true; } + + public override bool ShouldThrow503OnTimeout => this.shouldThrow503OnTimeout; } } diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs index 949afc0513..974509c70c 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs @@ -10,11 +10,14 @@ namespace Microsoft.Azure.Cosmos internal sealed class HttpTimeoutPolicyDefault : HttpTimeoutPolicy { - public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyDefault(); + public static readonly HttpTimeoutPolicy Instance = new HttpTimeoutPolicyDefault(false); + public static readonly HttpTimeoutPolicy InstanceShouldThrow503OnTimeout = new HttpTimeoutPolicyDefault(true); + public bool shouldThrow503OnTimeout; private static readonly string Name = nameof(HttpTimeoutPolicyDefault); - private HttpTimeoutPolicyDefault() + private HttpTimeoutPolicyDefault(bool shouldThrow503OnTimeout) { + this.shouldThrow503OnTimeout = shouldThrow503OnTimeout; } private readonly IReadOnlyList<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> TimeoutsAndDelays = new List<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)>() @@ -46,5 +49,7 @@ public override bool ShouldRetryBasedOnResponse(HttpMethod requestHttpMethod, Ht { return false; } + + public override bool ShouldThrow503OnTimeout => this.shouldThrow503OnTimeout; } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs index fff41258b2..0648aecbc3 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs @@ -283,6 +283,24 @@ internal static CosmosException CreateBadRequestException( innerException); } + internal static CosmosException CreateServiceUnavailableException( + string message, + Headers headers, + string stackTrace = default, + ITrace trace = default, + Error error = default, + Exception innerException = default) + { + return CosmosExceptionFactory.Create( + HttpStatusCode.ServiceUnavailable, + message, + stackTrace, + headers, + trace, + error, + innerException); + } + internal static CosmosException CreateUnauthorizedException( string message, Headers headers, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 00d156e8b7..67c653498b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -259,6 +259,67 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio Assert.AreEqual(3, count, "Should retry 3 times"); } + [TestMethod] + public async Task HttpTimeoutThrow503TestAsync() + { + + async Task TestScenarioAsync(HttpMethod method, ResourceType resourceType, HttpTimeoutPolicy timeoutPolicy, Type expectedException, int expectedNumberOfRetrys) + { + int count = 0; + async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + { + count++; + + throw new OperationCanceledException("API with exception"); + + } + + DocumentClientEventSource eventSource = DocumentClientEventSource.Instance; + HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); + using CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)); + + try + { + + HttpResponseMessage responseMessage1 = await cosmoshttpClient.SendHttpAsync(() => + new ValueTask( + result: new HttpRequestMessage(method, new Uri("http://localhost"))), + resourceType: resourceType, + timeoutPolicy: timeoutPolicy, + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + cancellationToken: default); + } + catch (Exception e) + { + Assert.AreEqual(expectedNumberOfRetrys, count, "Should retry 3 times for read methods, for writes should only be tried once"); + Assert.AreEqual(e.GetType(), expectedException); + + if (e.GetType() == typeof(CosmosException)) + { + CosmosException cosmosException = (CosmosException)e; + Assert.AreEqual(cosmosException.StatusCode, System.Net.HttpStatusCode.ServiceUnavailable); + Assert.AreEqual((int)cosmosException.SubStatusCode,(int)SubStatusCodes.TransportGenerated503); + } + } + + } + + //Data plane read + await TestScenarioAsync(HttpMethod.Get, ResourceType.Document, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 3); + + //Data plane write + await TestScenarioAsync(HttpMethod.Post, ResourceType.Document, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 1); + + //Meta data read + await TestScenarioAsync(HttpMethod.Get, ResourceType.Database, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 3); + + //Query plan read (note all query plan operations are reads). + await TestScenarioAsync(HttpMethod.Get, ResourceType.Document, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 3); + + //Metadata Write (Should throw a 408 OperationCanceledException rather than a 503) + await TestScenarioAsync(HttpMethod.Post, ResourceType.Document, HttpTimeoutPolicyDefault.Instance, typeof(TaskCanceledException), 1); + } + [TestMethod] public async Task NoRetryOnNoRetryPolicyTestAsync() { @@ -309,7 +370,7 @@ public async Task RetryTransientIssuesForQueryPlanTestAsync() new Documents.Collections.RequestNameValueCollection()); HttpTimeoutPolicy retryPolicy = HttpTimeoutPolicy.GetTimeoutPolicy(documentServiceRequest); - Assert.AreEqual(HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance, retryPolicy); + Assert.AreEqual(HttpTimeoutPolicyControlPlaneRetriableHotPath.InstanceShouldThrow503OnTimeout, retryPolicy); int count = 0; IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> retry = retryPolicy.GetTimeoutEnumerator(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs index e1cfeb5f40..2fc8359f68 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs @@ -61,7 +61,7 @@ public async Task DocumentClient_BuildHttpClientFactory_WithHandler() uri: new Uri("https://localhost"), additionalHeaders: new RequestNameValueCollection(), resourceType: ResourceType.Document, - timeoutPolicy: HttpTimeoutPolicyDefault.Instance, + timeoutPolicy: HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), cancellationToken: default); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index fe4287484c..43078d1866 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -808,7 +808,7 @@ public async Task GatewayStatsDurationTest() await cosmosHttpClient.SendHttpAsync(() => new ValueTask(new HttpRequestMessage(HttpMethod.Get, "http://someuri.com")), ResourceType.Document, - HttpTimeoutPolicyDefault.Instance, + HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, clientSideRequestStatistics, CancellationToken.None); From 010e4ba7198b62cb13b680baf4f6b2d6f9538cef Mon Sep 17 00:00:00 2001 From: Pramod Valavala <43602528+PramodValavala-MSFT@users.noreply.github.com> Date: Mon, 21 Nov 2022 17:56:48 -0500 Subject: [PATCH 019/337] Documentation: Fixes EUAP in Comments (#3579) --- Microsoft.Azure.Cosmos/src/Regions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index 64729bd21a..f08bbf4c91 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -186,12 +186,12 @@ public static class Regions public const string USGovVirginia = "USGov Virginia"; /// - /// Name of the Azure East US 2 EUAP region in the Azure Cosmos DB service. + /// Name of the Azure East US 2 Early Updates Access Program (EUAP) region in the Azure Cosmos DB service. /// public const string EastUS2EUAP = "East US 2 EUAP"; /// - /// Name of the Azure Central US EUAP region in the Azure Cosmos DB service. + /// Name of the Azure Central US Early Updates Access Program (EUAP) region in the Azure Cosmos DB service. /// public const string CentralUSEUAP = "Central US EUAP"; From b24eeb96babef246d8deb2305e08accb7ceffc7d Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Wed, 23 Nov 2022 10:28:19 -0800 Subject: [PATCH 020/337] Query: Fixes incorrect FeedResponse.Count when result contains undefined elements (#3574) * Do not maintain an independent count on QueryResponse that can go out of sync * Add more test coverage for QueryResponse.Count * Output the correct count from CosmosElementSerializer when the input contains CosmosUndefined * Add untyped tests for CosmosUndefined * Remove commented code --- .../src/Query/v3Query/QueryResponse.cs | 8 +-- .../src/Serializer/CosmosElementSerializer.cs | 7 +- .../Query/CosmosUndefinedQueryTests.cs | 65 +++++++++++++++++++ .../Query/QueryTestsBase.cs | 24 +++++++ 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs index e9d0b5856b..6c7777ebff 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs @@ -163,6 +163,7 @@ class QueryResponse : FeedResponse { private readonly CosmosSerializerCore serializerCore; private readonly CosmosSerializationFormatOptions serializationOptions; + private readonly IReadOnlyList resource; private QueryResponse( HttpStatusCode httpStatusCode, @@ -178,8 +179,7 @@ private QueryResponse( this.serializerCore = serializerCore; this.serializationOptions = serializationOptions; this.StatusCode = httpStatusCode; - this.Count = cosmosElements.Count; - this.Resource = CosmosElementSerializer.GetResources( + this.resource = CosmosElementSerializer.GetResources( cosmosArray: cosmosElements, serializerCore: serializerCore); @@ -197,7 +197,7 @@ private QueryResponse( public override CosmosDiagnostics Diagnostics { get; } - public override int Count { get; } + public override int Count => this.resource.Count; internal CosmosQueryResponseMessageHeaders QueryHeaders { get; } @@ -210,7 +210,7 @@ public override IEnumerator GetEnumerator() return this.Resource.GetEnumerator(); } - public override IEnumerable Resource { get; } + public override IEnumerable Resource => this.resource; internal override RequestMessage RequestMessage { get; } diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosElementSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosElementSerializer.cs index 1c4cb96a24..0564727b0c 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosElementSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosElementSerializer.cs @@ -74,8 +74,11 @@ internal static MemoryStream ToStream( jsonWriter.WriteArrayStart(); foreach (CosmosElement element in cosmosElements) { - count++; - element.WriteTo(jsonWriter); + if (element is not CosmosUndefined) + { + count++; + element.WriteTo(jsonWriter); + } } jsonWriter.WriteArrayEnd(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs index 42cb70fe16..3945169330 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Query using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; + using Azure; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Json; @@ -50,6 +51,70 @@ private static async Task RunTests(Container container, IReadOnlyList results = RunSimpleQueryAsync( + container, + testCase.Query, + new QueryRequestOptions { MaxItemCount = pageSize }); + + long actualCount = 0; + await foreach (ResponseMessage responseMessage in results) + { + Assert.IsTrue(responseMessage.IsSuccessStatusCode); + + string content = responseMessage.Content.ReadAsString(); + IJsonNavigator navigator = JsonNavigator.Create(System.Text.Encoding.UTF8.GetBytes(content)); + IJsonNavigatorNode rootNode = navigator.GetRootNode(); + Assert.IsTrue(navigator.TryGetObjectProperty(rootNode, "_count", out ObjectProperty countProperty)); + + long count = Number64.ToLong(navigator.GetNumber64Value(countProperty.ValueNode)); + actualCount += count; + + Assert.IsTrue(navigator.TryGetObjectProperty(rootNode, "Documents", out ObjectProperty documentsProperty)); + int documentCount = navigator.GetArrayItemCount(documentsProperty.ValueNode); + Assert.AreEqual(count, documentCount); + + for (int index= 0; index < documentCount; ++index) + { + IJsonNavigatorNode documentNode = navigator.GetArrayItemAt(documentsProperty.ValueNode, index); + int propertyCount = navigator.GetObjectPropertyCount(documentNode); + Assert.AreEqual(0, propertyCount); + } + } + + Assert.AreEqual(testCase.ExpectedResultCount, actualCount); + } + } } private static async Task OrderByTests(Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs index 269e8448bd..4775716efa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs @@ -645,6 +645,7 @@ internal static async Task> QueryWithContinuationTokensAsync( } List resultsFromContinuationToken = new List(); + int resultCount = 0; string continuationToken = null; do { @@ -668,6 +669,7 @@ internal static async Task> QueryWithContinuationTokensAsync( } resultsFromContinuationToken.AddRange(cosmosQueryResponse); + resultCount += cosmosQueryResponse.Count; continuationToken = cosmosQueryResponse.ContinuationToken; break; } @@ -687,6 +689,7 @@ internal static async Task> QueryWithContinuationTokensAsync( } } while (continuationToken != null); + Assert.AreEqual(resultsFromContinuationToken.Count, resultCount); return resultsFromContinuationToken; } @@ -700,6 +703,7 @@ internal static async Task> QueryWithoutContinuationTokensAsync( queryRequestOptions = new QueryRequestOptions(); } + int resultCount = 0; List results = new List(); FeedIterator itemQuery = container.GetItemQueryIterator( queryText: query, @@ -713,6 +717,7 @@ internal static async Task> QueryWithoutContinuationTokensAsync( { FeedResponse page = await itemQuery.ReadNextAsync(); results.AddRange(page); + resultCount += page.Count; if (queryRequestOptions.MaxItemCount.HasValue) { @@ -746,6 +751,7 @@ internal static async Task> QueryWithoutContinuationTokensAsync( { // The query failed and we don't have a save point, so just restart the whole thing. results = new List(); + resultCount = 0; } } } @@ -755,6 +761,7 @@ internal static async Task> QueryWithoutContinuationTokensAsync( itemQuery.Dispose(); } + Assert.AreEqual(results.Count, resultCount); return results; } @@ -907,6 +914,23 @@ internal static async IAsyncEnumerable> RunSimpleQueryWithNewIte } } + internal static async IAsyncEnumerable RunSimpleQueryAsync( + Container container, + string query, + QueryRequestOptions requestOptions = null) + { + using FeedIterator resultSetIterator = container.GetItemQueryStreamIterator( + query, + null, + requestOptions: requestOptions); + + while (resultSetIterator.HasMoreResults) + { + ResponseMessage response = await resultSetIterator.ReadNextAsync(); + yield return response; + } + } + internal async Task> RunSinglePartitionQuery( Container container, string query, From 9734ec5ed0d462aff0b312aee8999ffe3968fb68 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 24 Nov 2022 07:36:37 +0530 Subject: [PATCH 021/337] removed allr eference (#3581) Co-authored-by: Sourabh Jain --- .../OpenTelemetry/CosmosDbEventSource.cs | 17 +++------- .../DistributedTracingOptions.cs | 34 +------------------ ...riterBaselineTests.BulkOperationsAsync.xml | 2 +- ...neTests.PointOperationsExceptionsAsync.xml | 2 +- .../EndToEndTraceWriterBaselineTests.cs | 10 +++--- .../CosmosClientOptionsUnitTests.cs | 19 ----------- 6 files changed, 13 insertions(+), 71 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index f0ac635d81..6700697914 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -31,19 +31,12 @@ public static void RecordDiagnosticsForRequests( Documents.OperationType operationType, OpenTelemetryAttributes response) { - if (config.EnableDiagnosticsTraceForAllRequests) + if (DiagnosticsFilterHelper.IsTracingNeeded( + config: config, + operationType: operationType, + response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) { - CosmosDbEventSource.Singleton.WriteInfoEvent(response.Diagnostics.ToString()); - } - else - { - if (DiagnosticsFilterHelper.IsTracingNeeded( - config: config, - operationType: operationType, - response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) - { - CosmosDbEventSource.Singleton.WriteWarningEvent(response.Diagnostics.ToString()); - } + CosmosDbEventSource.Singleton.WriteWarningEvent(response.Diagnostics.ToString()); } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs index 078a554980..652b6b9e3f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs @@ -21,43 +21,11 @@ internal sealed class DistributedTracingOptions /// Default Latency threshold for QUERY operation /// internal static readonly TimeSpan DefaultQueryTimeoutThreshold = TimeSpan.FromMilliseconds(500); - private bool enableDiagnosticsTraceForAllRequests; - private TimeSpan? diagnosticsLatencyThreshold; /// /// Latency Threshold to generate () with Request diagnostics in distributing Tracing.

/// If it is not set then by default it will generate () for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. ///
- public TimeSpan? DiagnosticsLatencyThreshold - { - get => this.diagnosticsLatencyThreshold; - set - { - if (this.EnableDiagnosticsTraceForAllRequests) - { - throw new ArgumentException("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold."); - } - - this.diagnosticsLatencyThreshold = value; - } - } - - /// - /// Set this flag as true if you want to generate () containing request diagnostics string for all the operations. - /// If this flag is true then, it won't honour value to generate diagnostic traces. - /// - public bool EnableDiagnosticsTraceForAllRequests - { - get => this.enableDiagnosticsTraceForAllRequests; - set - { - if (value && this.DiagnosticsLatencyThreshold != null) - { - throw new ArgumentException("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold."); - } - - this.enableDiagnosticsTraceForAllRequests = value; - } - } + public TimeSpan? DiagnosticsLatencyThreshold { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index a31ad6433d..3eb9468e57 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -1602,7 +1602,7 @@ throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; ItemRequestOptions requestOptions = new ItemRequestOptions(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 019adb993e..d074dbb221 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -175,7 +175,7 @@ throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; ItemRequestOptions requestOptions = new ItemRequestOptions(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index aea21c9655..f64d289cfe 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -57,17 +57,17 @@ public static async Task ClassInitAsync(TestContext context) client.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; bulkClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; miscCosmosClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( @@ -984,7 +984,7 @@ public async Task PointOperationsExceptionsAsync() throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; ItemRequestOptions requestOptions = new ItemRequestOptions(); @@ -1271,7 +1271,7 @@ public async Task BulkOperationsAsync() throttleClient.ClientOptions.EnableDistributedTracing = true; throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() { - EnableDiagnosticsTraceForAllRequests = true + DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) }; ItemRequestOptions requestOptions = new ItemRequestOptions(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 6078570d96..e39bb8d0f3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -186,25 +186,6 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, policy.PortReuseMode); Assert.IsTrue(policy.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); - - // Verify DiagnosticsLatencyThreshold - cosmosClientBuilder = new CosmosClientBuilder( - accountEndpoint: endpoint, - authKeyOrResourceToken: key); - var exception = Assert.ThrowsException(() => cosmosClientBuilder.WithConnectionModeDirect( - idleTcpConnectionTimeout, - openTcpConnectionTimeout, - maxRequestsPerTcpConnection, - maxTcpConnectionsPerEndpoint, - portReuseMode, - enableTcpConnectionEndpointRediscovery) - .WithApplicationPreferredRegions(preferredLocations) - .WithDistributingTracing(new DistributedTracingOptions - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(100), - EnableDiagnosticsTraceForAllRequests = true - })); - Assert.AreEqual("EnableDiagnosticsTraceForAllRequests can not be true along with DiagnosticsLatencyThreshold.", exception.Message); } [TestMethod] From 6632168410079b849aa5d6f31f9bdd6f1ef52da1 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Wed, 23 Nov 2022 18:11:55 -0800 Subject: [PATCH 022/337] Trace: Fixes Tracing/diagnostics hour-times to 24Hours (#3577) * Trace: Fixes Tracing/diagnostics hour-times to 24Hours * fixing baseline tests Co-authored-by: Matias Quaranta --- .../Tracing/TraceWriter.TraceJsonWriter.cs | 2 +- .../Tracing/TraceWriter.TraceTextWriter.cs | 22 +- ...raceWriterBaselineTests.ScenariosAsync.xml | 482 +++++++++--------- ...TraceWriterBaselineTests.Serialization.xml | 54 +- .../TraceWriterBaselineTests.TraceData.xml | 54 +- 5 files changed, 308 insertions(+), 306 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs index a190f2e5e2..4710f00a2e 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs @@ -47,7 +47,7 @@ public static void WriteTrace( if (isRootTrace) { writer.WriteFieldName("start time"); - writer.WriteStringValue(trace.StartTime.ToString("hh:mm:ss:fff")); + writer.WriteStringValue(trace.StartTime.ToString(TraceWriter.HourTimeFormatString)); } writer.WriteFieldName("duration in milliseconds"); writer.WriteNumber64Value(trace.Duration.TotalMilliseconds); diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs index a55860655c..f77307b359 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs @@ -17,6 +17,8 @@ namespace Microsoft.Azure.Cosmos.Tracing internal static partial class TraceWriter { + internal static readonly string HourTimeFormatString = "HH:mm:ss:fff"; + private static class TraceTextWriter { private const string space = " "; @@ -97,8 +99,8 @@ private static class Headers private static class HeaderLengths { - public static readonly int StartTime = Math.Max(Headers.StartTime.Length, DateTime.MaxValue.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture).Length); - public static readonly int EndTime = Math.Max(Headers.EndTime.Length, DateTime.MaxValue.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture).Length); + public static readonly int StartTime = Math.Max(Headers.StartTime.Length, DateTime.MaxValue.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture).Length); + public static readonly int EndTime = Math.Max(Headers.EndTime.Length, DateTime.MaxValue.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture).Length); public static readonly int Endpoint = 80 - (StartTime + EndTime); } @@ -177,7 +179,7 @@ private static void WriteTraceRecursive( writer.Write("Component"); writer.Write(space); - writer.Write(trace.StartTime.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)); + writer.Write(trace.StartTime.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)); writer.Write(space); writer.Write(trace.Duration.TotalMilliseconds.ToString("0.00")); @@ -316,7 +318,7 @@ public void Visit(PointOperationStatisticsTraceDatum pointOperationStatisticsTra StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Activity ID: {pointOperationStatisticsTraceDatum.ActivityId ?? ""}"); stringBuilder.AppendLine($"Status Code: {pointOperationStatisticsTraceDatum.StatusCode}/{pointOperationStatisticsTraceDatum.SubStatusCode}"); - stringBuilder.AppendLine($"Response Time: {pointOperationStatisticsTraceDatum.ResponseTimeUtc.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)}"); + stringBuilder.AppendLine($"Response Time: {pointOperationStatisticsTraceDatum.ResponseTimeUtc.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)}"); stringBuilder.AppendLine($"Request Charge: {pointOperationStatisticsTraceDatum.RequestCharge}"); stringBuilder.AppendLine($"Request URI: {pointOperationStatisticsTraceDatum.RequestUri ?? ""}"); stringBuilder.AppendLine($"Session Tokens: {pointOperationStatisticsTraceDatum.RequestSessionToken ?? ""} / {pointOperationStatisticsTraceDatum.ResponseSessionToken ?? ""}"); @@ -331,10 +333,10 @@ public void Visit(PointOperationStatisticsTraceDatum pointOperationStatisticsTra public void Visit(ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) { StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine($"Start Time: {clientSideRequestStatisticsTraceDatum.RequestStartTimeUtc.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)}"); + stringBuilder.AppendLine($"Start Time: {clientSideRequestStatisticsTraceDatum.RequestStartTimeUtc.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)}"); if (clientSideRequestStatisticsTraceDatum.RequestEndTimeUtc.HasValue) { - stringBuilder.AppendLine($"End Time: {clientSideRequestStatisticsTraceDatum.RequestEndTimeUtc.Value.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)}"); + stringBuilder.AppendLine($"End Time: {clientSideRequestStatisticsTraceDatum.RequestEndTimeUtc.Value.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)}"); } stringBuilder.AppendLine("Contacted Replicas"); @@ -378,8 +380,8 @@ public void Visit(ClientSideRequestStatisticsTraceDatum clientSideRequestStatist foreach (KeyValuePair stat in clientSideRequestStatisticsTraceDatum.EndpointToAddressResolutionStatistics) { string row = AddressResolutionStatisticsTextTable.Singleton.GetRow( - stat.Value.StartTime.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture), - stat.Value.EndTime.HasValue ? stat.Value.EndTime.Value.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture) : "NO END TIME", + stat.Value.StartTime.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture), + stat.Value.EndTime.HasValue ? stat.Value.EndTime.Value.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture) : "NO END TIME", stat.Value.TargetEndpoint); stringBuilder.AppendLine(row); } @@ -391,14 +393,14 @@ public void Visit(ClientSideRequestStatisticsTraceDatum clientSideRequestStatist { if (stat.RequestStartTime.HasValue) { - stringBuilder.AppendLine($"{space}Start Time: {stat.RequestStartTime.Value.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)}"); + stringBuilder.AppendLine($"{space}Start Time: {stat.RequestStartTime.Value.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)}"); } else { stringBuilder.AppendLine("{space}Start Time Not Found"); } - stringBuilder.AppendLine($"{space}End Time: {stat.RequestResponseTime.ToString("hh:mm:ss:fff", CultureInfo.InvariantCulture)}"); + stringBuilder.AppendLine($"{space}End Time: {stat.RequestResponseTime.ToString(TraceWriter.HourTimeFormatString, CultureInfo.InvariantCulture)}"); stringBuilder.AppendLine($"{space}Resource Type: {stat.RequestResourceType}"); stringBuilder.AppendLine($"{space}Operation Type: {stat.RequestOperationType}"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml index 92d4a7344c..eecc33b72f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml @@ -26,108 +26,108 @@ @@ -34,7 +34,7 @@ Status Code: 0/Unknown - Response Time: 12:00:00:000 + Response Time: 00:00:00:000 Request Charge: 0 Request URI: Session Tokens: / @@ -97,7 +97,7 @@ @@ -484,12 +484,12 @@ ┌────────────────┬──────────────┬──────────────────────────────────────────────────┐ │Start Time (utc)│End Time (utc)│Endpoint │ ├────────────────┼──────────────┼──────────────────────────────────────────────────┤ - │ 12:00:00:000│ NO END TIME│ │ - │ 12:00:00:000│ NO END TIME│ │ + │ 00:00:00:000│ NO END TIME│ │ + │ 00:00:00:000│ NO END TIME│ │ └────────────────┴──────────────┴──────────────────────────────────────────────────┘ Store Response Statistics {space}Start Time Not Found - End Time: 12:00:00:000 + End Time: 00:00:00:000 Resource Type: Database Operation Type: Create Store Result @@ -518,7 +518,7 @@ "RegionsContacted": 1 }, "name": "Trace For Baseline Testing", - "start time": "12:00:00:000", + "start time": "00:00:00:000", "duration in milliseconds": 0, "data": { "Client Side Request Stats Default": { @@ -662,11 +662,11 @@ Date: Sat, 26 Nov 2022 07:14:25 +0530 Subject: [PATCH 023/337] AI Integration: Adds cosmetic fixes (#3576) * wip * status code int and internal and client kind activity * remove unused imports * update baselines * fix test * fixed baseline tests * fix tests * update base tetss Co-authored-by: Sourabh Jain --- .../CosmosExceptions/CosmosException.cs | 4 +- .../OpenTelemetryAttributeKeys.cs | 2 +- .../OpenTelemetry/OpenTelemetryAttributes.cs | 5 +- .../OpenTelemetryCoreRecorder.cs | 18 +- .../OpenTelemetryRecorderFactory.cs | 3 +- .../OpenTelemetry/OpenTelemetryResponse.cs | 6 +- .../OpenTelemetry/OpenTelemetryResponse{T}.cs | 4 +- ...iterBaselineTests.BatchOperationsAsync.xml | 26 +- ...riterBaselineTests.BulkOperationsAsync.xml | 646 +++++----- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 830 ++++++------- ...eWriterBaselineTests.MiscellanousAsync.xml | 48 +- ...neTests.PointOperationsExceptionsAsync.xml | 240 ++-- ...EndTraceWriterBaselineTests.QueryAsync.xml | 1070 ++++++++--------- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 600 ++++----- ...TraceWriterBaselineTests.ReadManyAsync.xml | 304 ++--- ...selineTests.StreamPointOperationsAsync.xml | 72 +- ...aselineTests.TypedPointOperationsAsync.xml | 88 +- .../Tracing/OpenTelemetryListener.cs | 17 +- 18 files changed, 1984 insertions(+), 1999 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs index f6544e3545..12db379f0c 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs @@ -289,8 +289,8 @@ private string ToStringHelper( /// internal static void RecordOtelAttributes(CosmosException exception, DiagnosticScope scope) { - scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, exception.StatusCode); - scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, exception.SubStatusCode); + scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)exception.StatusCode); + scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)exception.SubStatusCode); scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, exception.RequestCharge); scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(exception.Diagnostics?.GetContactedRegions())); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 033a8744b6..801824b791 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -19,7 +19,7 @@ internal sealed class OpenTelemetryAttributeKeys // Cosmos Db Specific public const string ClientId = "db.cosmosdb.client_id"; - public const string MachineId = "db.cosmosdb.hashed_machine_id"; + public const string MachineId = "db.cosmosdb.machine_id"; public const string UserAgent = "db.cosmosdb.user_agent"; public const string ConnectionMode = "db.cosmosdb.connection_mode"; public const string OperationType = "db.cosmosdb.operation_type"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs index 3d9ee4afbb..7e9c798f9d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs @@ -5,12 +5,9 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System.Net; - using Microsoft.Azure.Documents; internal class OpenTelemetryAttributes { - internal const string NotAvailable = "information not available"; - /// /// For testing purpose only, to make initialization of this class easy /// @@ -20,7 +17,7 @@ internal OpenTelemetryAttributes() internal OpenTelemetryAttributes(RequestMessage requestMessage) { - this.RequestContentLength = requestMessage?.Headers?.ContentLength ?? OpenTelemetryAttributes.NotAvailable; + this.RequestContentLength = requestMessage?.Headers?.ContentLength; } /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index b8be214392..e0b47e744f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -6,10 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; using System.Collections.Generic; - using Diagnostics; - using global::Azure; using global::Azure.Core.Pipeline; - using HdrHistogram; internal struct OpenTelemetryCoreRecorder : IDisposable { @@ -92,8 +89,8 @@ public void Record( this.scope.AddAttribute(OpenTelemetryAttributeKeys.NetPeerName, clientContext.Client?.Endpoint?.Host); // Client Information - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id ?? OpenTelemetryAttributes.NotAvailable); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent ?? OpenTelemetryAttributes.NotAvailable); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, clientContext.ClientOptions.ConnectionMode); } } @@ -108,21 +105,16 @@ public void Record(OpenTelemetryAttributes response) { this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, response.RequestContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, response.ResponseContentLength); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, response.StatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, response.SubStatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)response.StatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)response.SubStatusCode); this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, response.RequestCharge); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, response.ItemCount); if (response.Diagnostics != null) { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions()) ?? OpenTelemetryAttributes.NotAvailable); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions())); CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, this.operationType, response); } - else - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, OpenTelemetryAttributes.NotAvailable); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestDiagnostics, OpenTelemetryAttributes.NotAvailable); - } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index c66339e51e..88f149d608 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -24,7 +24,8 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, isActivityEnabled: true); DiagnosticScope scope = OpenTelemetryRecorderFactory .ScopeFactory - .CreateScope($"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}"); + .CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", + kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); if (scope.IsEnabled) { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs index 7bb1fdc12e..98c1bfab8d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs @@ -46,9 +46,9 @@ private OpenTelemetryResponse( { this.StatusCode = statusCode; this.RequestCharge = requestCharge; - this.ResponseContentLength = responseContentLength ?? OpenTelemetryAttributes.NotAvailable; + this.ResponseContentLength = responseContentLength; this.Diagnostics = diagnostics; - this.ItemCount = itemCount ?? OpenTelemetryAttributes.NotAvailable; + this.ItemCount = itemCount; this.SubStatusCode = subStatusCode; } @@ -60,7 +60,7 @@ private static string GetPayloadSize(ResponseMessage response) { return response.Content.Length.ToString(); } - return response?.Headers?.ContentLength ?? OpenTelemetryAttributes.NotAvailable; + return response?.Headers?.ContentLength; } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs index 3d7359da75..71ca5cfba2 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs @@ -45,9 +45,9 @@ private OpenTelemetryResponse( { this.StatusCode = statusCode; this.RequestCharge = requestCharge; - this.ResponseContentLength = responseContentLength ?? OpenTelemetryAttributes.NotAvailable; + this.ResponseContentLength = responseContentLength; this.Diagnostics = diagnostics; - this.ItemCount = itemCount ?? OpenTelemetryAttributes.NotAvailable; + this.ItemCount = itemCount; this.SubStatusCode = subStatusCode; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 15d67f3483..ffce1a6bf4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -34,34 +34,34 @@ - Cosmos.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 3eb9468e57..e999759bd3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -31,36 +31,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -189,36 +189,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -347,36 +347,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -505,36 +505,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -663,36 +663,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -821,36 +821,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -979,36 +979,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1137,36 +1137,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1295,36 +1295,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1453,36 +1453,36 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1629,176 +1629,176 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 1a1f0b40ee..2d747e9e45 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -25,220 +25,220 @@ - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -992,139 +992,139 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1610,135 +1610,135 @@ - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2208,139 +2208,139 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2821,65 +2821,65 @@ - Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index bffa1a103a..5b29ba3737 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -16,35 +16,35 @@ - Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -128,33 +128,33 @@ - Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index d074dbb221..7dea567de8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -33,42 +33,42 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -201,61 +201,61 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -469,30 +469,30 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -694,30 +694,30 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -951,30 +951,30 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1233,42 +1233,42 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 5368aad0e7..937daa7a49 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -19,151 +19,151 @@ - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -605,155 +605,155 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1212,151 +1212,151 @@ - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1799,155 +1799,155 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2409,175 +2409,175 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3082,152 +3082,152 @@ - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3678,156 +3678,156 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 8860741fc2..ee1302e06e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -19,118 +19,118 @@ - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -567,131 +567,131 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1136,118 +1136,118 @@ - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1685,131 +1685,131 @@ - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 5cc059c7a7..9558168b76 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -12,133 +12,133 @@ - Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -567,136 +567,136 @@ - Cosmos.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 665f74396c..a1b5ceb966 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -18,21 +18,21 @@ - Cosmos.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -107,21 +107,21 @@ - Cosmos.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -204,21 +204,21 @@ - Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -296,21 +296,21 @@ - Cosmos.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 8042b6e21d..dfe617f632 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -16,34 +16,34 @@ - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -127,31 +127,31 @@ - Cosmos.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -229,32 +229,32 @@ - Cosmos.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -330,31 +330,31 @@ - Cosmos.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.hashed_machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Cosmos.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs index fd50cd7365..05763f0bdb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs @@ -160,7 +160,7 @@ private static void AssertData(string name, IEnumerable exceptionsForDbNameAttribute = new List - { - "Cosmos.DeleteAsync", - "Cosmos.ExecuteAsync", "Cosmos.DeleteStreamAsync" }; if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || - (tag.Key == OpenTelemetryAttributeKeys.DbName && !exceptionsForDbNameAttribute.Contains(name))) + (tag.Key == OpenTelemetryAttributeKeys.DbName)) { Assert.IsNotNull(tag.Value, $"{tag.Key} is 'null' for {name} operation"); - Assert.AreNotEqual(OpenTelemetryAttributes.NotAvailable, tag.Value, $"{tag.Key} is {OpenTelemetryAttributes.NotAvailable} for {name} operation"); + } + else if (tag.Key == OpenTelemetryAttributeKeys.ContainerName && exceptionsForContainerAttribute.Contains(name)) + { + Assert.IsNull(tag.Value, $"{tag.Key} is '{tag.Value}' for {name} operation"); } } From 2f047e1cf3c0d94d9fb13f66739952acf7467e9d Mon Sep 17 00:00:00 2001 From: Ezra Haleva <115735172+ezrahaleva-msft@users.noreply.github.com> Date: Mon, 28 Nov 2022 09:45:40 -0800 Subject: [PATCH 024/337] Query: Adds ALL Scalar Expression (#3509) * Add SqlAllScalarExpression to v3 DOM * updated generated parser files * Parsing for ALL * Added tests for ALL and baselines * Added more tests * added new test, cleanup * cleaning & fix typos * fixed typo * Added new baseline test file names to csproj file * renamed AggregateAll to AggregateSubquery to accomodate FIRST and LAST later * Added keywords for 'left' and 'right' and respective function calls * fixed bug from last commit * cleaning * replace tabs with spaces * cleaning --- .../src/Query/Core/Parser/CstToAstVisitor.cs | 59 +- .../src/Query/Core/Parser/IsqlListener.cs | 116 +- .../src/Query/Core/Parser/IsqlVisitor.cs | 61 +- .../src/Query/Core/Parser/sql.g4 | 235 +-- .../src/Query/Core/Parser/sqlBaseListener.cs | 122 +- .../src/Query/Core/Parser/sqlBaseVisitor.cs | 73 +- .../src/Query/Core/Parser/sqlLexer.cs | 919 ++++----- .../src/Query/Core/Parser/sqlParser.cs | 1640 ++++++++++------- .../CosmosQueryExecutionContextFactory.cs | 6 + .../src/SqlObjects/SqlAllScalarExpression.cs | 40 + .../Visitors/SqlObjectEqualityVisitor.cs | 15 + .../SqlObjects/Visitors/SqlObjectHasher.cs | 8 + .../Visitors/SqlObjectObfuscator.cs | 5 + .../Visitors/SqlObjectTextSerializer.cs | 8 + .../SqlObjects/Visitors/SqlObjectVisitor.cs | 1 + .../SqlObjectVisitor{TArg,TOutput}.cs | 1 + .../Visitors/SqlObjectVisitor{TResult}.cs | 1 + .../Visitors/SqlScalarExpressionVisitor.cs | 1 + ...qlScalarExpressionVisitor{TArg,TOutput}.cs | 1 + .../SqlScalarExpressionVisitor{TResult}.cs | 1 + ...gateSubquerySqlParserBaselineTests.All.xml | 92 + ...arExpressionSqlParserBaselineTests.All.xml | 47 + .../Microsoft.Azure.Cosmos.Tests.csproj | 8 +- .../AggregateProjectionDector.cs | 6 + .../AggregateProjectionTransformer.cs | 6 + .../ScalarExpressionEvaluator.cs | 48 + .../Query/OfflineEngine/SqlInterpreter.cs | 5 + ...AggregateSubquerySqlParserBaselineTests.cs | 68 + .../ScalarExpressionSqlParserBaselineTests.cs | 32 + 29 files changed, 2218 insertions(+), 1407 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/SqlObjects/SqlAllScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.All.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.All.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/AggregateSubquerySqlParserBaselineTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs index 6b1de2883e..448b8f4ca6 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs @@ -183,9 +183,9 @@ public override SqlObject VisitSelect_item([NotNull] sqlParser.Select_itemContex SqlScalarExpression sqlScalarExpression = (SqlScalarExpression)this.Visit(context.scalar_expression()); SqlIdentifier alias; - if (context.IDENTIFIER() != null) + if (context.identifier() != null) { - alias = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + alias = SqlIdentifier.Create(context.identifier().GetText()); } else { @@ -233,9 +233,9 @@ public override SqlObject VisitAliasedCollectionExpression([NotNull] sqlParser.A SqlCollection sqlCollection = (SqlCollection)this.Visit(context.collection()); SqlIdentifier alias; - if (context.IDENTIFIER() != null) + if (context.identifier() != null) { - alias = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + alias = SqlIdentifier.Create(context.identifier().GetText()); } else { @@ -250,7 +250,7 @@ public override SqlObject VisitArrayIteratorCollectionExpression([NotNull] sqlPa Contract.Requires(context != null); SqlCollection sqlCollection = (SqlCollection)this.Visit(context.collection()); - SqlIdentifier identifier = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + SqlIdentifier identifier = SqlIdentifier.Create(context.identifier().GetText()); return SqlArrayIteratorCollectionExpression.Create(identifier, sqlCollection); } @@ -269,7 +269,7 @@ public override SqlObject VisitInputPathCollection([NotNull] sqlParser.InputPath { Contract.Requires(context != null); - SqlIdentifier identifier = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + SqlIdentifier identifier = SqlIdentifier.Create(context.identifier().GetText()); SqlPathExpression pathExpression; if (context.path_expression() != null) { @@ -302,7 +302,7 @@ public override SqlObject VisitIdentifierPathExpression([NotNull] sqlParser.Iden Contract.Requires(context != null); SqlPathExpression pathExpression = (SqlPathExpression)this.Visit(context.path_expression()); - SqlIdentifier identifier = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + SqlIdentifier identifier = SqlIdentifier.Create(context.identifier().GetText()); return SqlIdentifierPathExpression.Create(parentPath: pathExpression, value: identifier); } @@ -458,6 +458,15 @@ public override SqlObject VisitLimit_count([NotNull] sqlParser.Limit_countContex #endregion #region ScalarExpressions + public override SqlObject VisitAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context) + { + Contract.Requires(context != null); + // K_ALL '(' sql_query ')' + Contract.Requires(context.ChildCount == 4); + + SqlQuery subquery = (SqlQuery)this.Visit(context.children[2]); + return SqlAllScalarExpression.Create(subquery); + } public override SqlObject VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { Contract.Requires(context != null); @@ -562,10 +571,34 @@ public override SqlObject VisitExistsScalarExpression([NotNull] sqlParser.Exists public override SqlObject VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { Contract.Requires(context != null); - // (K_UDF '.')? IDENTIFIER '(' scalar_expression_list? ')' + // function_call_scalar_expression + + return this.Visit(context.function_call_scalar_expression()); + } + + public override SqlObject VisitFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context) + { + Contract.Requires(context != null); + // : (K_UDF '.')? identifier '(' scalar_expression_list ? ')' + // | K_LEFT '(' scalar_expression_list ? ')' + // | K_RIGHT '(' scalar_expression_list ? ')' bool udf = context.K_UDF() != null; - SqlIdentifier identifier = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + SqlIdentifier identifier; + + if (context.identifier() != null) + { + identifier = SqlIdentifier.Create(context.identifier().GetText()); + } + else if (context.K_LEFT() != null) + { + identifier = SqlIdentifier.Create(context.K_LEFT().GetText()); + } + else + { + identifier = SqlIdentifier.Create(context.K_RIGHT().GetText()); + } + List arguments = new List(); if (context.scalar_expression_list() != null) { @@ -719,20 +752,20 @@ public override SqlObject VisitParameterRefScalarExpression([NotNull] sqlParser. public override SqlObject VisitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { Contract.Requires(context != null); - // IDENTIFIER + // identifier return SqlPropertyRefScalarExpression.Create( member: null, - SqlIdentifier.Create(context.IDENTIFIER().GetText())); + SqlIdentifier.Create(context.identifier().GetText())); } public override SqlObject VisitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { Contract.Requires(context != null); - // primary_expression '.' IDENTIFIER + // primary_expression '.' identifier SqlScalarExpression memberExpression = (SqlScalarExpression)this.Visit(context.primary_expression()); - SqlIdentifier indentifier = SqlIdentifier.Create(context.IDENTIFIER().GetText()); + SqlIdentifier indentifier = SqlIdentifier.Create(context.identifier().GetText()); return SqlPropertyRefScalarExpression.Create(memberExpression, indentifier); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs index ed0eb42e76..24a4a0694a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs @@ -526,101 +526,125 @@ internal interface IsqlListener : IParseTreeListener { /// The parse tree. void ExitUnary_operator([NotNull] sqlParser.Unary_operatorContext context); /// - /// Enter a parse tree produced by the SubqueryScalarExpression + /// Enter a parse tree produced by the AllScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); + void EnterAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context); /// - /// Exit a parse tree produced by the SubqueryScalarExpression + /// Exit a parse tree produced by the AllScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); + void ExitAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context); /// - /// Enter a parse tree produced by the PropertyRefScalarExpressionBase + /// Enter a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); + void EnterLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); /// - /// Exit a parse tree produced by the PropertyRefScalarExpressionBase + /// Exit a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); + void ExitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); /// - /// Enter a parse tree produced by the FunctionCallScalarExpression + /// Enter a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); + void EnterObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); /// - /// Exit a parse tree produced by the FunctionCallScalarExpression + /// Exit a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); + void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); /// - /// Enter a parse tree produced by the LiteralScalarExpression + /// Enter a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); + void EnterArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); /// - /// Exit a parse tree produced by the LiteralScalarExpression + /// Exit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); + void ExitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); /// - /// Enter a parse tree produced by the ObjectCreateScalarExpression + /// Enter a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); + void EnterMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); /// - /// Exit a parse tree produced by the ObjectCreateScalarExpression + /// Exit a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); + void ExitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); /// - /// Enter a parse tree produced by the ParenthesizedScalarExperession + /// Enter a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + void EnterSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); /// - /// Exit a parse tree produced by the ParenthesizedScalarExperession + /// Exit a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + void ExitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); /// - /// Enter a parse tree produced by the ParameterRefScalarExpression + /// Enter a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// /// The parse tree. - void EnterParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); + void EnterPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); /// - /// Exit a parse tree produced by the ParameterRefScalarExpression + /// Exit a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// /// The parse tree. - void ExitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); + void ExitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); /// - /// Enter a parse tree produced by the ArrayCreateScalarExpression + /// Enter a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// /// The parse tree. - void EnterArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); + void EnterFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); /// - /// Exit a parse tree produced by the ArrayCreateScalarExpression + /// Exit a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// /// The parse tree. - void ExitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); + void ExitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); + /// + /// Enter a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// + /// The parse tree. + void EnterParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + /// + /// Exit a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// + /// The parse tree. + void ExitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + /// + /// Enter a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void EnterParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); + /// + /// Exit a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void ExitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); /// /// Enter a parse tree produced by the ExistsScalarExpression /// labeled alternative in . @@ -646,29 +670,27 @@ internal interface IsqlListener : IParseTreeListener { /// The parse tree. void ExitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context); /// - /// Enter a parse tree produced by the MemberIndexerScalarExpression + /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// /// The parse tree. - void EnterMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); + void EnterPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); /// - /// Exit a parse tree produced by the MemberIndexerScalarExpression + /// Exit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// /// The parse tree. - void ExitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); + void ExitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); /// - /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Enter a parse tree produced by . /// /// The parse tree. - void EnterPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); + void EnterFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context); /// - /// Exit a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Exit a parse tree produced by . /// /// The parse tree. - void ExitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); + void ExitFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context); /// /// Enter a parse tree produced by . /// @@ -700,6 +722,16 @@ internal interface IsqlListener : IParseTreeListener { /// The parse tree. void ExitObject_property([NotNull] sqlParser.Object_propertyContext context); /// + /// Enter a parse tree produced by . + /// + /// The parse tree. + void EnterIdentifier([NotNull] sqlParser.IdentifierContext context); + /// + /// Exit a parse tree produced by . + /// + /// The parse tree. + void ExitIdentifier([NotNull] sqlParser.IdentifierContext context); + /// /// Enter a parse tree produced by . /// /// The parse tree. diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs index 2e96892783..e22a9d4218 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs @@ -326,61 +326,75 @@ internal interface IsqlVisitor : IParseTreeVisitor { /// The visitor result. Result VisitUnary_operator([NotNull] sqlParser.Unary_operatorContext context); /// - /// Visit a parse tree produced by the SubqueryScalarExpression + /// Visit a parse tree produced by the AllScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); + Result VisitAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context); /// - /// Visit a parse tree produced by the PropertyRefScalarExpressionBase + /// Visit a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); + Result VisitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); /// - /// Visit a parse tree produced by the FunctionCallScalarExpression + /// Visit a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); + Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); /// - /// Visit a parse tree produced by the LiteralScalarExpression + /// Visit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context); + Result VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); /// - /// Visit a parse tree produced by the ObjectCreateScalarExpression + /// Visit a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); + Result VisitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); /// - /// Visit a parse tree produced by the ParenthesizedScalarExperession + /// Visit a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + Result VisitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context); /// - /// Visit a parse tree produced by the ParameterRefScalarExpression + /// Visit a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); + Result VisitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context); /// - /// Visit a parse tree produced by the ArrayCreateScalarExpression + /// Visit a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context); + Result VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context); + /// + /// Visit a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context); + /// + /// Visit a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context); /// /// Visit a parse tree produced by the ExistsScalarExpression /// labeled alternative in . @@ -396,19 +410,18 @@ internal interface IsqlVisitor : IParseTreeVisitor { /// The visitor result. Result VisitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context); /// - /// Visit a parse tree produced by the MemberIndexerScalarExpression + /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// /// The parse tree. /// The visitor result. - Result VisitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context); + Result VisitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); /// - /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Visit a parse tree produced by . /// /// The parse tree. /// The visitor result. - Result VisitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context); + Result VisitFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context); /// /// Visit a parse tree produced by . /// @@ -428,6 +441,12 @@ internal interface IsqlVisitor : IParseTreeVisitor { /// The visitor result. Result VisitObject_property([NotNull] sqlParser.Object_propertyContext context); /// + /// Visit a parse tree produced by . + /// + /// The parse tree. + /// The visitor result. + Result VisitIdentifier([NotNull] sqlParser.IdentifierContext context); + /// /// Visit a parse tree produced by . /// /// The parse tree. diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 index ef9361f67b..42ac229557 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 @@ -1,8 +1,8 @@ grammar sql; program - : sql_query EOF - ; + : sql_query EOF + ; sql_query : select_clause from_clause? where_clause? group_by_clause? order_by_clause? offset_limit_clause? ; @@ -12,14 +12,14 @@ sql_query : select_clause from_clause? where_clause? group_by_clause? order_by_c select_clause : K_SELECT K_DISTINCT? top_spec? selection ; top_spec : K_TOP (NUMERIC_LITERAL | PARAMETER); selection - : select_star_spec - | select_value_spec - | select_list_spec - ; + : select_star_spec + | select_value_spec + | select_list_spec + ; select_star_spec : '*' ; select_value_spec : K_VALUE scalar_expression ; select_list_spec : select_item ( ',' select_item )* ; -select_item : scalar_expression (K_AS IDENTIFIER)? ; +select_item : scalar_expression (K_AS identifier)? ; /*--------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------*/ @@ -27,20 +27,20 @@ select_item : scalar_expression (K_AS IDENTIFIER)? ; /*--------------------------------------------------------------------------------*/ from_clause : K_FROM collection_expression ; collection_expression - : collection (K_AS? IDENTIFIER)? #AliasedCollectionExpression - | IDENTIFIER K_IN collection #ArrayIteratorCollectionExpression - | collection_expression K_JOIN collection_expression #JoinCollectionExpression - ; + : collection (K_AS? identifier)? #AliasedCollectionExpression + | identifier K_IN collection #ArrayIteratorCollectionExpression + | collection_expression K_JOIN collection_expression #JoinCollectionExpression + ; collection - : IDENTIFIER path_expression? #InputPathCollection - | '(' sql_query ')' #SubqueryCollection - ; + : identifier path_expression? #InputPathCollection + | '(' sql_query ')' #SubqueryCollection + ; path_expression - : path_expression'.'IDENTIFIER #IdentifierPathExpression - | path_expression'[' NUMERIC_LITERAL ']' #NumberPathExpression - | path_expression'[' STRING_LITERAL ']' #StringPathExpression - | /*epsilon*/ #EpsilonPathExpression - ; + : path_expression'.'identifier #IdentifierPathExpression + | path_expression'[' NUMERIC_LITERAL ']' #NumberPathExpression + | path_expression'[' STRING_LITERAL ']' #StringPathExpression + | /*epsilon*/ #EpsilonPathExpression + ; /*--------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------*/ @@ -62,9 +62,9 @@ order_by_clause : K_ORDER K_BY order_by_items ; order_by_items : order_by_item (',' order_by_item)* ; order_by_item : scalar_expression sort_order? ; sort_order - : K_ASC - | K_DESC - ; + : K_ASC + | K_DESC + ; /*--------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------*/ @@ -79,66 +79,66 @@ limit_count : NUMERIC_LITERAL | PARAMETER; /* SCALAR EXPRESSIONs */ /*--------------------------------------------------------------------------------*/ scalar_expression - : scalar_expression '?' scalar_expression ':' scalar_expression #ConditionalScalarExpression - | scalar_expression '??' scalar_expression #CoalesceScalarExpression - | logical_scalar_expression #LogicalScalarExpression - | binary_scalar_expression K_NOT? K_BETWEEN binary_scalar_expression K_AND binary_scalar_expression #BetweenScalarExpression - ; + : scalar_expression '?' scalar_expression ':' scalar_expression #ConditionalScalarExpression + | scalar_expression '??' scalar_expression #CoalesceScalarExpression + | logical_scalar_expression #LogicalScalarExpression + | binary_scalar_expression K_NOT? K_BETWEEN binary_scalar_expression K_AND binary_scalar_expression #BetweenScalarExpression + ; logical_scalar_expression - : binary_scalar_expression - | in_scalar_expression - | like_scalar_expression - | logical_scalar_expression K_AND logical_scalar_expression - | logical_scalar_expression K_OR logical_scalar_expression - ; + : binary_scalar_expression + | in_scalar_expression + | like_scalar_expression + | logical_scalar_expression K_AND logical_scalar_expression + | logical_scalar_expression K_OR logical_scalar_expression + ; in_scalar_expression - : binary_scalar_expression K_NOT? K_IN '(' scalar_expression_list ')' - ; + : binary_scalar_expression K_NOT? K_IN '(' scalar_expression_list ')' + ; like_scalar_expression - : binary_scalar_expression K_NOT? K_LIKE binary_scalar_expression escape_expression? - ; + : binary_scalar_expression K_NOT? K_LIKE binary_scalar_expression escape_expression? + ; escape_expression - : K_ESCAPE STRING_LITERAL - ; + : K_ESCAPE STRING_LITERAL + ; binary_scalar_expression - : unary_scalar_expression - | binary_scalar_expression multiplicative_operator binary_scalar_expression - | binary_scalar_expression additive_operator binary_scalar_expression - | binary_scalar_expression relational_operator binary_scalar_expression - | binary_scalar_expression equality_operator binary_scalar_expression - | binary_scalar_expression bitwise_and_operator binary_scalar_expression - | binary_scalar_expression bitwise_exclusive_or_operator binary_scalar_expression - | binary_scalar_expression bitwise_inclusive_or_operator binary_scalar_expression - | binary_scalar_expression string_concat_operator binary_scalar_expression - ; + : unary_scalar_expression + | binary_scalar_expression multiplicative_operator binary_scalar_expression + | binary_scalar_expression additive_operator binary_scalar_expression + | binary_scalar_expression relational_operator binary_scalar_expression + | binary_scalar_expression equality_operator binary_scalar_expression + | binary_scalar_expression bitwise_and_operator binary_scalar_expression + | binary_scalar_expression bitwise_exclusive_or_operator binary_scalar_expression + | binary_scalar_expression bitwise_inclusive_or_operator binary_scalar_expression + | binary_scalar_expression string_concat_operator binary_scalar_expression + ; multiplicative_operator - : '*' - | '/' - | '%' - ; + : '*' + | '/' + | '%' + ; additive_operator - : '+' - | '-' - ; + : '+' + | '-' + ; relational_operator - : '<' - | '>' - | '>=' - | '<=' - ; + : '<' + | '>' + | '>=' + | '<=' + ; equality_operator - : '=' - | '!=' - ; + : '=' + | '!=' + ; bitwise_and_operator : '&' ; @@ -149,42 +149,55 @@ bitwise_inclusive_or_operator : '|'; string_concat_operator : '||'; unary_scalar_expression - : primary_expression - | unary_operator unary_scalar_expression - ; + : primary_expression + | unary_operator unary_scalar_expression + ; unary_operator - : '-' - | '+' - | '~' - | K_NOT - ; + : '-' + | '+' + | '~' + | K_NOT + ; primary_expression - : IDENTIFIER #PropertyRefScalarExpressionBase - | PARAMETER #ParameterRefScalarExpression - | literal #LiteralScalarExpression - | '[' scalar_expression_list? ']' #ArrayCreateScalarExpression - | '{' object_property_list? '}' #ObjectCreateScalarExpression - | (K_UDF '.')? IDENTIFIER '(' scalar_expression_list? ')' #FunctionCallScalarExpression - | '(' scalar_expression ')' #ParenthesizedScalarExperession - | '(' sql_query ')' #SubqueryScalarExpression - | primary_expression '.' IDENTIFIER #PropertyRefScalarExpressionRecursive - | primary_expression '[' scalar_expression ']' #MemberIndexerScalarExpression - | K_EXISTS '(' sql_query ')' #ExistsScalarExpression - | K_ARRAY '(' sql_query ')' #ArrayScalarExpression - ; + : identifier #PropertyRefScalarExpressionBase + | PARAMETER #ParameterRefScalarExpression + | literal #LiteralScalarExpression + | '[' scalar_expression_list? ']' #ArrayCreateScalarExpression + | '{' object_property_list? '}' #ObjectCreateScalarExpression + | '(' scalar_expression ')' #ParenthesizedScalarExperession + | '(' sql_query ')' #SubqueryScalarExpression + | primary_expression '.' identifier #PropertyRefScalarExpressionRecursive + | primary_expression '[' scalar_expression ']' #MemberIndexerScalarExpression + | K_EXISTS '(' sql_query ')' #ExistsScalarExpression + | K_ARRAY '(' sql_query ')' #ArrayScalarExpression + | K_ALL '(' sql_query ')' #AllScalarExpression + | function_call_scalar_expression #FunctionCallScalarExpression + ; + +function_call_scalar_expression + : (K_UDF '.')? identifier '(' scalar_expression_list? ')' + | K_LEFT '(' scalar_expression_list? ')' + | K_RIGHT '(' scalar_expression_list? ')' + ; scalar_expression_list : scalar_expression (',' scalar_expression)*; object_property_list : object_property (',' object_property)* ; object_property : STRING_LITERAL ':' scalar_expression ; + +identifier + : LEX_IDENTIFIER + | K_ALL + ; /*--------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------*/ /* KEYWORDS */ /*--------------------------------------------------------------------------------*/ +K_ALL : A L L; K_AND : A N D; K_ARRAY : A R R A Y; K_AS : A S; @@ -200,6 +213,7 @@ K_FROM : F R O M; K_GROUP : G R O U P; K_IN : I N ; K_JOIN : J O I N; +K_LEFT : L E F T; K_LIKE : L I K E; K_LIMIT : L I M I T; K_NOT : N O T; @@ -207,6 +221,7 @@ K_NULL : 'null'; K_OFFSET : O F F S E T; K_OR : O R; K_ORDER : O R D E R; +K_RIGHT : R I G H T; K_SELECT : S E L E C T; K_TOP : T O P; K_TRUE : 'true'; @@ -224,27 +239,27 @@ WS /* LITERALS */ /*--------------------------------------------------------------------------------*/ literal - : STRING_LITERAL - | NUMERIC_LITERAL - | K_TRUE - | K_FALSE - | K_NULL - | K_UNDEFINED - ; + : STRING_LITERAL + | NUMERIC_LITERAL + | K_TRUE + | K_FALSE + | K_NULL + | K_UNDEFINED + ; NUMERIC_LITERAL - : ( '+' | '-' )? DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )? - | ( '+' | '-' )? '.' DIGIT+ ( E [-+]? DIGIT+ )? - ; + : ( '+' | '-' )? DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )? + | ( '+' | '-' )? '.' DIGIT+ ( E [-+]? DIGIT+ )? + ; STRING_LITERAL - : '"' (ESC | SAFECODEPOINTWITHDOUBLEQUOTATION)* '"' - | '\'' (ESC | SAFECODEPOINTWITHSINGLEQUOTATION)* '\'' - ; + : '"' (ESC | SAFECODEPOINTWITHDOUBLEQUOTATION)* '"' + | '\'' (ESC | SAFECODEPOINTWITHSINGLEQUOTATION)* '\'' + ; fragment ESC - : '\\' (["\\/bfnrt] | UNICODE) - ; + : '\\' (["\\/bfnrt] | UNICODE) + ; fragment UNICODE : 'u' HEX HEX HEX HEX @@ -255,21 +270,21 @@ fragment HEX ; fragment SAFECODEPOINTWITHSINGLEQUOTATION - : ~ ['\\\u0000-\u001F] - ; + : ~ ['\\\u0000-\u001F] + ; fragment SAFECODEPOINTWITHDOUBLEQUOTATION - : ~ ["\\\u0000-\u001F] - ; + : ~ ["\\\u0000-\u001F] + ; -IDENTIFIER - : - | [a-zA-Z_]([a-zA-Z_]|DIGIT)* - ; +LEX_IDENTIFIER + : + | [a-zA-Z_]([a-zA-Z_]|DIGIT)* + ; PARAMETER - : '@'IDENTIFIER - ; + : '@'LEX_IDENTIFIER + ; /*--------------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------------*/ diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs index 5a52445735..18003391b1 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs @@ -624,117 +624,145 @@ public virtual void EnterUnary_operator([NotNull] sqlParser.Unary_operatorContex /// The parse tree. public virtual void ExitUnary_operator([NotNull] sqlParser.Unary_operatorContext context) { } /// - /// Enter a parse tree produced by the SubqueryScalarExpression + /// Enter a parse tree produced by the AllScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { } + public virtual void EnterAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the SubqueryScalarExpression + /// Exit a parse tree produced by the AllScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { } + public virtual void ExitAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the PropertyRefScalarExpressionBase + /// Enter a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { } + public virtual void EnterLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the PropertyRefScalarExpressionBase + /// Exit a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { } + public virtual void ExitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the FunctionCallScalarExpression + /// Enter a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { } + public virtual void EnterObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the FunctionCallScalarExpression + /// Exit a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { } + public virtual void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the LiteralScalarExpression + /// Enter a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { } + public virtual void EnterArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the LiteralScalarExpression + /// Exit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { } + public virtual void ExitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the ObjectCreateScalarExpression + /// Enter a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { } + public virtual void EnterMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the ObjectCreateScalarExpression + /// Exit a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { } + public virtual void ExitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the ParenthesizedScalarExperession + /// Enter a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { } + public virtual void EnterSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the ParenthesizedScalarExperession + /// Exit a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { } + public virtual void ExitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the ParameterRefScalarExpression + /// Enter a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { } + public virtual void EnterPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { } /// - /// Exit a parse tree produced by the ParameterRefScalarExpression + /// Exit a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { } + public virtual void ExitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { } /// - /// Enter a parse tree produced by the ArrayCreateScalarExpression + /// Enter a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { } + public virtual void EnterFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { } /// - /// Exit a parse tree produced by the ArrayCreateScalarExpression + /// Exit a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { } + public virtual void ExitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { } + /// + /// Enter a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { } + /// + /// Exit a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { } + /// + /// Enter a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { } + /// + /// Exit a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { } /// /// Enter a parse tree produced by the ExistsScalarExpression /// labeled alternative in . @@ -764,33 +792,31 @@ public virtual void EnterArrayScalarExpression([NotNull] sqlParser.ArrayScalarEx /// The parse tree. public virtual void ExitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context) { } /// - /// Enter a parse tree produced by the MemberIndexerScalarExpression + /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { } + public virtual void EnterPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { } /// - /// Exit a parse tree produced by the MemberIndexerScalarExpression + /// Exit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { } + public virtual void ExitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { } /// - /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Enter a parse tree produced by . /// The default implementation does nothing. /// /// The parse tree. - public virtual void EnterPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { } + public virtual void EnterFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context) { } /// - /// Exit a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Exit a parse tree produced by . /// The default implementation does nothing. /// /// The parse tree. - public virtual void ExitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { } + public virtual void ExitFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context) { } /// /// Enter a parse tree produced by . /// The default implementation does nothing. @@ -828,6 +854,18 @@ public virtual void EnterObject_property([NotNull] sqlParser.Object_propertyCont /// The parse tree. public virtual void ExitObject_property([NotNull] sqlParser.Object_propertyContext context) { } /// + /// Enter a parse tree produced by . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterIdentifier([NotNull] sqlParser.IdentifierContext context) { } + /// + /// Exit a parse tree produced by . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitIdentifier([NotNull] sqlParser.IdentifierContext context) { } + /// /// Enter a parse tree produced by . /// The default implementation does nothing. /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs index 287851e115..bb3b86379d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs @@ -516,7 +516,7 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// The visitor result. public virtual Result VisitUnary_operator([NotNull] sqlParser.Unary_operatorContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the SubqueryScalarExpression + /// Visit a parse tree produced by the AllScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -525,9 +525,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitAllScalarExpression([NotNull] sqlParser.AllScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the PropertyRefScalarExpressionBase + /// Visit a parse tree produced by the LiteralScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -536,9 +536,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { return VisitChildren(context); } + public virtual Result VisitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the FunctionCallScalarExpression + /// Visit a parse tree produced by the ObjectCreateScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -547,9 +547,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the LiteralScalarExpression + /// Visit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -558,9 +558,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitLiteralScalarExpression([NotNull] sqlParser.LiteralScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the ObjectCreateScalarExpression + /// Visit a parse tree produced by the MemberIndexerScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -569,9 +569,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the ParenthesizedScalarExperession + /// Visit a parse tree produced by the SubqueryScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -580,9 +580,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { return VisitChildren(context); } + public virtual Result VisitSubqueryScalarExpression([NotNull] sqlParser.SubqueryScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the ParameterRefScalarExpression + /// Visit a parse tree produced by the PropertyRefScalarExpressionBase /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -591,9 +591,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitPropertyRefScalarExpressionBase([NotNull] sqlParser.PropertyRefScalarExpressionBaseContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the ArrayCreateScalarExpression + /// Visit a parse tree produced by the FunctionCallScalarExpression /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -602,7 +602,29 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitArrayCreateScalarExpression([NotNull] sqlParser.ArrayCreateScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the ParenthesizedScalarExperession + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitParenthesizedScalarExperession([NotNull] sqlParser.ParenthesizedScalarExperessionContext context) { return VisitChildren(context); } + /// + /// Visit a parse tree produced by the ParameterRefScalarExpression + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitParameterRefScalarExpression([NotNull] sqlParser.ParameterRefScalarExpressionContext context) { return VisitChildren(context); } /// /// Visit a parse tree produced by the ExistsScalarExpression /// labeled alternative in . @@ -626,7 +648,7 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// The visitor result. public virtual Result VisitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the MemberIndexerScalarExpression + /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// /// The default implementation returns the result of calling @@ -635,10 +657,9 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitMemberIndexerScalarExpression([NotNull] sqlParser.MemberIndexerScalarExpressionContext context) { return VisitChildren(context); } + public virtual Result VisitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { return VisitChildren(context); } /// - /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive - /// labeled alternative in . + /// Visit a parse tree produced by . /// /// The default implementation returns the result of calling /// on . @@ -646,7 +667,7 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// /// The parse tree. /// The visitor result. - public virtual Result VisitPropertyRefScalarExpressionRecursive([NotNull] sqlParser.PropertyRefScalarExpressionRecursiveContext context) { return VisitChildren(context); } + public virtual Result VisitFunction_call_scalar_expression([NotNull] sqlParser.Function_call_scalar_expressionContext context) { return VisitChildren(context); } /// /// Visit a parse tree produced by . /// @@ -678,6 +699,16 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// The visitor result. public virtual Result VisitObject_property([NotNull] sqlParser.Object_propertyContext context) { return VisitChildren(context); } /// + /// Visit a parse tree produced by . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitIdentifier([NotNull] sqlParser.IdentifierContext context) { return VisitChildren(context); } + /// /// Visit a parse tree produced by . /// /// The default implementation returns the result of calling diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs index 23f23fbed2..1d5b7262bd 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs @@ -35,12 +35,13 @@ public const int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, K_AND=28, K_ARRAY=29, K_AS=30, K_ASC=31, - K_BETWEEN=32, K_BY=33, K_DESC=34, K_DISTINCT=35, K_ESCAPE=36, K_EXISTS=37, - K_FALSE=38, K_FROM=39, K_GROUP=40, K_IN=41, K_JOIN=42, K_LIKE=43, K_LIMIT=44, - K_NOT=45, K_NULL=46, K_OFFSET=47, K_OR=48, K_ORDER=49, K_SELECT=50, K_TOP=51, - K_TRUE=52, K_UDF=53, K_UNDEFINED=54, K_VALUE=55, K_WHERE=56, WS=57, NUMERIC_LITERAL=58, - STRING_LITERAL=59, IDENTIFIER=60, PARAMETER=61; + T__24=25, T__25=26, T__26=27, K_ALL=28, K_AND=29, K_ARRAY=30, K_AS=31, + K_ASC=32, K_BETWEEN=33, K_BY=34, K_DESC=35, K_DISTINCT=36, K_ESCAPE=37, + K_EXISTS=38, K_FALSE=39, K_FROM=40, K_GROUP=41, K_IN=42, K_JOIN=43, K_LEFT=44, + K_LIKE=45, K_LIMIT=46, K_NOT=47, K_NULL=48, K_OFFSET=49, K_OR=50, K_ORDER=51, + K_RIGHT=52, K_SELECT=53, K_TOP=54, K_TRUE=55, K_UDF=56, K_UNDEFINED=57, + K_VALUE=58, K_WHERE=59, WS=60, NUMERIC_LITERAL=61, STRING_LITERAL=62, + LEX_IDENTIFIER=63, PARAMETER=64; public static string[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -53,15 +54,15 @@ public const int "T__0", "T__1", "T__2", "T__3", "T__4", "T__5", "T__6", "T__7", "T__8", "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", - "T__25", "T__26", "K_AND", "K_ARRAY", "K_AS", "K_ASC", "K_BETWEEN", "K_BY", - "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", "K_FROM", "K_GROUP", - "K_IN", "K_JOIN", "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", "K_OFFSET", - "K_OR", "K_ORDER", "K_SELECT", "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", - "K_VALUE", "K_WHERE", "WS", "NUMERIC_LITERAL", "STRING_LITERAL", "ESC", - "UNICODE", "HEX", "SAFECODEPOINTWITHSINGLEQUOTATION", "SAFECODEPOINTWITHDOUBLEQUOTATION", - "IDENTIFIER", "PARAMETER", "DIGIT", "A", "B", "C", "D", "E", "F", "G", - "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", - "V", "W", "X", "Y", "Z" + "T__25", "T__26", "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", "K_BETWEEN", + "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", "K_FROM", + "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", + "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", "K_TOP", "K_TRUE", + "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", "NUMERIC_LITERAL", + "STRING_LITERAL", "ESC", "UNICODE", "HEX", "SAFECODEPOINTWITHSINGLEQUOTATION", + "SAFECODEPOINTWITHDOUBLEQUOTATION", "LEX_IDENTIFIER", "PARAMETER", "DIGIT", + "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", + "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; @@ -78,19 +79,19 @@ public sqlLexer(ICharStream input, TextWriter output, TextWriter errorOutput) null, "'*'", "','", "'('", "')'", "'.'", "'['", "']'", "'?'", "':'", "'??'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'>='", "'<='", "'='", "'!='", "'&'", "'^'", "'|'", "'||'", "'~'", "'{'", "'}'", null, null, null, null, - null, null, null, null, null, null, "'false'", null, null, null, null, - null, null, null, "'null'", null, null, null, null, null, "'true'", "'udf'", - "'undefined'" + null, null, null, null, null, null, null, "'false'", null, null, null, + null, null, null, null, null, "'null'", null, null, null, null, null, + null, "'true'", "'udf'", "'undefined'" }; private static readonly string[] _SymbolicNames = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, "K_AND", "K_ARRAY", "K_AS", "K_ASC", "K_BETWEEN", - "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", "K_FROM", - "K_GROUP", "K_IN", "K_JOIN", "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", "K_OFFSET", - "K_OR", "K_ORDER", "K_SELECT", "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", - "K_VALUE", "K_WHERE", "WS", "NUMERIC_LITERAL", "STRING_LITERAL", "IDENTIFIER", - "PARAMETER" + null, null, null, null, "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", + "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", + "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", + "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", + "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", + "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", "PARAMETER" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -121,7 +122,7 @@ static sqlLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', '?', '\x239', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x5964', '\x2', '\x42', '\x24E', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', @@ -154,6 +155,7 @@ static sqlLexer() { '\t', 'U', '\x4', 'V', '\t', 'V', '\x4', 'W', '\t', 'W', '\x4', 'X', '\t', 'X', '\x4', 'Y', '\t', 'Y', '\x4', 'Z', '\t', 'Z', '\x4', '[', '\t', '[', '\x4', '\\', '\t', '\\', '\x4', ']', '\t', ']', '\x4', '^', '\t', '^', + '\x4', '_', '\t', '_', '\x4', '`', '\t', '`', '\x4', '\x61', '\t', '\x61', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', @@ -167,56 +169,58 @@ static sqlLexer() { '\x19', '\x3', '\x19', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', - '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', - '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', '!', '\x3', - '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '!', '\x3', - '!', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', + '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', + '\x1F', '\x3', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', '!', + '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '\"', '\x3', '\"', '\x3', '\"', + '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', '#', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', - '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', - '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', - '%', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', - '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', - '\'', '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', - '(', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', - ')', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '+', '\x3', '+', '\x3', - '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', - ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', - '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', - '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '\x30', '\x3', - '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', - '\x30', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x32', '\x3', - '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', - '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', - '\x33', '\x3', '\x33', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', - '\x34', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', - '\x35', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', - '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', - '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', - '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', - '\x38', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', '\x3', - '\x39', '\x3', '\x39', '\x3', ':', '\x6', ':', '\x199', '\n', ':', '\r', - ':', '\xE', ':', '\x19A', '\x3', ':', '\x3', ':', '\x3', ';', '\x5', ';', - '\x1A0', '\n', ';', '\x3', ';', '\x6', ';', '\x1A3', '\n', ';', '\r', - ';', '\xE', ';', '\x1A4', '\x3', ';', '\x3', ';', '\a', ';', '\x1A9', - '\n', ';', '\f', ';', '\xE', ';', '\x1AC', '\v', ';', '\x5', ';', '\x1AE', - '\n', ';', '\x3', ';', '\x3', ';', '\x5', ';', '\x1B2', '\n', ';', '\x3', - ';', '\x6', ';', '\x1B5', '\n', ';', '\r', ';', '\xE', ';', '\x1B6', '\x5', - ';', '\x1B9', '\n', ';', '\x3', ';', '\x5', ';', '\x1BC', '\n', ';', '\x3', - ';', '\x3', ';', '\x6', ';', '\x1C0', '\n', ';', '\r', ';', '\xE', ';', - '\x1C1', '\x3', ';', '\x3', ';', '\x5', ';', '\x1C6', '\n', ';', '\x3', - ';', '\x6', ';', '\x1C9', '\n', ';', '\r', ';', '\xE', ';', '\x1CA', '\x5', - ';', '\x1CD', '\n', ';', '\x5', ';', '\x1CF', '\n', ';', '\x3', '<', '\x3', - '<', '\x3', '<', '\a', '<', '\x1D4', '\n', '<', '\f', '<', '\xE', '<', - '\x1D7', '\v', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\a', - '<', '\x1DD', '\n', '<', '\f', '<', '\xE', '<', '\x1E0', '\v', '<', '\x3', - '<', '\x5', '<', '\x1E3', '\n', '<', '\x3', '=', '\x3', '=', '\x3', '=', - '\x5', '=', '\x1E8', '\n', '=', '\x3', '>', '\x3', '>', '\x3', '>', '\x3', - '>', '\x3', '>', '\x3', '>', '\x3', '?', '\x3', '?', '\x3', '@', '\x3', - '@', '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', '\x3', '\x42', '\x3', - '\x42', '\x3', '\x42', '\a', '\x42', '\x1FA', '\n', '\x42', '\f', '\x42', - '\xE', '\x42', '\x1FD', '\v', '\x42', '\x5', '\x42', '\x1FF', '\n', '\x42', - '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x44', '\x3', '\x44', - '\x3', '\x45', '\x3', '\x45', '\x3', '\x46', '\x3', '\x46', '\x3', 'G', + '$', '\x3', '$', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', + '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', + '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', + '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', + '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', + '\x3', '(', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', + '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', + '\x3', '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x3', ',', + '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', + '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', + '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', + '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x31', + '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x32', + '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', + '\x3', '\x32', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x34', + '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', + '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', + '\x3', '\x35', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', + '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x37', '\x3', '\x37', + '\x3', '\x37', '\x3', '\x37', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', + '\x3', '\x38', '\x3', '\x38', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', + '\x3', '\x39', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', + ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', + ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', + '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', + '=', '\x6', '=', '\x1AE', '\n', '=', '\r', '=', '\xE', '=', '\x1AF', '\x3', + '=', '\x3', '=', '\x3', '>', '\x5', '>', '\x1B5', '\n', '>', '\x3', '>', + '\x6', '>', '\x1B8', '\n', '>', '\r', '>', '\xE', '>', '\x1B9', '\x3', + '>', '\x3', '>', '\a', '>', '\x1BE', '\n', '>', '\f', '>', '\xE', '>', + '\x1C1', '\v', '>', '\x5', '>', '\x1C3', '\n', '>', '\x3', '>', '\x3', + '>', '\x5', '>', '\x1C7', '\n', '>', '\x3', '>', '\x6', '>', '\x1CA', + '\n', '>', '\r', '>', '\xE', '>', '\x1CB', '\x5', '>', '\x1CE', '\n', + '>', '\x3', '>', '\x5', '>', '\x1D1', '\n', '>', '\x3', '>', '\x3', '>', + '\x6', '>', '\x1D5', '\n', '>', '\r', '>', '\xE', '>', '\x1D6', '\x3', + '>', '\x3', '>', '\x5', '>', '\x1DB', '\n', '>', '\x3', '>', '\x6', '>', + '\x1DE', '\n', '>', '\r', '>', '\xE', '>', '\x1DF', '\x5', '>', '\x1E2', + '\n', '>', '\x5', '>', '\x1E4', '\n', '>', '\x3', '?', '\x3', '?', '\x3', + '?', '\a', '?', '\x1E9', '\n', '?', '\f', '?', '\xE', '?', '\x1EC', '\v', + '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\a', '?', '\x1F2', + '\n', '?', '\f', '?', '\xE', '?', '\x1F5', '\v', '?', '\x3', '?', '\x5', + '?', '\x1F8', '\n', '?', '\x3', '@', '\x3', '@', '\x3', '@', '\x5', '@', + '\x1FD', '\n', '@', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', + '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', '\x3', '\x42', '\x3', + '\x43', '\x3', '\x43', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', + '\x45', '\x3', '\x45', '\x3', '\x45', '\a', '\x45', '\x20F', '\n', '\x45', + '\f', '\x45', '\xE', '\x45', '\x212', '\v', '\x45', '\x5', '\x45', '\x214', + '\n', '\x45', '\x3', '\x46', '\x3', '\x46', '\x3', '\x46', '\x3', 'G', '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'I', '\x3', 'I', '\x3', 'J', '\x3', 'J', '\x3', 'K', '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', 'M', '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', 'O', '\x3', 'O', '\x3', 'P', @@ -224,382 +228,397 @@ static sqlLexer() { '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', 'U', '\x3', 'U', '\x3', 'V', '\x3', 'V', '\x3', 'W', '\x3', 'W', '\x3', 'X', '\x3', 'X', '\x3', 'Y', '\x3', 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', '[', '\x3', '[', '\x3', '\\', - '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x2', '\x2', - '_', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', '\a', - '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', '\x17', - '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x11', '!', - '\x12', '#', '\x13', '%', '\x14', '\'', '\x15', ')', '\x16', '+', '\x17', - '-', '\x18', '/', '\x19', '\x31', '\x1A', '\x33', '\x1B', '\x35', '\x1C', - '\x37', '\x1D', '\x39', '\x1E', ';', '\x1F', '=', ' ', '?', '!', '\x41', - '\"', '\x43', '#', '\x45', '$', 'G', '%', 'I', '&', 'K', '\'', 'M', '(', - 'O', ')', 'Q', '*', 'S', '+', 'U', ',', 'W', '-', 'Y', '.', '[', '/', - ']', '\x30', '_', '\x31', '\x61', '\x32', '\x63', '\x33', '\x65', '\x34', - 'g', '\x35', 'i', '\x36', 'k', '\x37', 'm', '\x38', 'o', '\x39', 'q', - ':', 's', ';', 'u', '<', 'w', '=', 'y', '\x2', '{', '\x2', '}', '\x2', - '\x7F', '\x2', '\x81', '\x2', '\x83', '>', '\x85', '?', '\x87', '\x2', - '\x89', '\x2', '\x8B', '\x2', '\x8D', '\x2', '\x8F', '\x2', '\x91', '\x2', - '\x93', '\x2', '\x95', '\x2', '\x97', '\x2', '\x99', '\x2', '\x9B', '\x2', - '\x9D', '\x2', '\x9F', '\x2', '\xA1', '\x2', '\xA3', '\x2', '\xA5', '\x2', - '\xA7', '\x2', '\xA9', '\x2', '\xAB', '\x2', '\xAD', '\x2', '\xAF', '\x2', - '\xB1', '\x2', '\xB3', '\x2', '\xB5', '\x2', '\xB7', '\x2', '\xB9', '\x2', - '\xBB', '\x2', '\x3', '\x2', '$', '\x5', '\x2', '\v', '\f', '\xF', '\xF', - '\"', '\"', '\x4', '\x2', '-', '-', '/', '/', '\n', '\x2', '$', '$', '\x31', - '\x31', '^', '^', '\x64', '\x64', 'h', 'h', 'p', 'p', 't', 't', 'v', 'v', - '\x5', '\x2', '\x32', ';', '\x43', 'H', '\x63', 'h', '\x5', '\x2', '\x2', - '!', ')', ')', '^', '^', '\x5', '\x2', '\x2', '!', '$', '$', '^', '^', - '\x5', '\x2', '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x3', '\x2', - '\x32', ';', '\x4', '\x2', '\x43', '\x43', '\x63', '\x63', '\x4', '\x2', - '\x44', '\x44', '\x64', '\x64', '\x4', '\x2', '\x45', '\x45', '\x65', - '\x65', '\x4', '\x2', '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', 'G', - 'G', 'g', 'g', '\x4', '\x2', 'H', 'H', 'h', 'h', '\x4', '\x2', 'I', 'I', - 'i', 'i', '\x4', '\x2', 'J', 'J', 'j', 'j', '\x4', '\x2', 'K', 'K', 'k', - 'k', '\x4', '\x2', 'L', 'L', 'l', 'l', '\x4', '\x2', 'M', 'M', 'm', 'm', - '\x4', '\x2', 'N', 'N', 'n', 'n', '\x4', '\x2', 'O', 'O', 'o', 'o', '\x4', - '\x2', 'P', 'P', 'p', 'p', '\x4', '\x2', 'Q', 'Q', 'q', 'q', '\x4', '\x2', - 'R', 'R', 'r', 'r', '\x4', '\x2', 'S', 'S', 's', 's', '\x4', '\x2', 'T', - 'T', 't', 't', '\x4', '\x2', 'U', 'U', 'u', 'u', '\x4', '\x2', 'V', 'V', - 'v', 'v', '\x4', '\x2', 'W', 'W', 'w', 'w', '\x4', '\x2', 'X', 'X', 'x', - 'x', '\x4', '\x2', 'Y', 'Y', 'y', 'y', '\x4', '\x2', 'Z', 'Z', 'z', 'z', - '\x4', '\x2', '[', '[', '{', '{', '\x4', '\x2', '\\', '\\', '|', '|', - '\x2', '\x22F', '\x2', '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', - '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', - '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', - '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', '\x2', - '!', '\x3', '\x2', '\x2', '\x2', '\x2', '#', '\x3', '\x2', '\x2', '\x2', - '\x2', '%', '\x3', '\x2', '\x2', '\x2', '\x2', '\'', '\x3', '\x2', '\x2', - '\x2', '\x2', ')', '\x3', '\x2', '\x2', '\x2', '\x2', '+', '\x3', '\x2', - '\x2', '\x2', '\x2', '-', '\x3', '\x2', '\x2', '\x2', '\x2', '/', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x31', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x33', '\x3', '\x2', '\x2', '\x2', '\x2', '\x35', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x37', '\x3', '\x2', '\x2', '\x2', '\x2', '\x39', '\x3', - '\x2', '\x2', '\x2', '\x2', ';', '\x3', '\x2', '\x2', '\x2', '\x2', '=', - '\x3', '\x2', '\x2', '\x2', '\x2', '?', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x41', '\x3', '\x2', '\x2', '\x2', '\x2', '\x43', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x45', '\x3', '\x2', '\x2', '\x2', '\x2', 'G', '\x3', '\x2', - '\x2', '\x2', '\x2', 'I', '\x3', '\x2', '\x2', '\x2', '\x2', 'K', '\x3', - '\x2', '\x2', '\x2', '\x2', 'M', '\x3', '\x2', '\x2', '\x2', '\x2', 'O', - '\x3', '\x2', '\x2', '\x2', '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', '\x2', - 'S', '\x3', '\x2', '\x2', '\x2', '\x2', 'U', '\x3', '\x2', '\x2', '\x2', - '\x2', 'W', '\x3', '\x2', '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', '\x2', - '\x2', '\x2', '[', '\x3', '\x2', '\x2', '\x2', '\x2', ']', '\x3', '\x2', - '\x2', '\x2', '\x2', '_', '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x65', '\x3', '\x2', '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', '\x2', - '\x2', 'i', '\x3', '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', '\x2', - '\x2', '\x2', 'm', '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', '\x2', - '\x2', '\x2', '\x2', 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', '\x3', - '\x2', '\x2', '\x2', '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', 'w', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x83', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x85', '\x3', '\x2', '\x2', '\x2', '\x3', '\xBD', '\x3', '\x2', - '\x2', '\x2', '\x5', '\xBF', '\x3', '\x2', '\x2', '\x2', '\a', '\xC1', - '\x3', '\x2', '\x2', '\x2', '\t', '\xC3', '\x3', '\x2', '\x2', '\x2', - '\v', '\xC5', '\x3', '\x2', '\x2', '\x2', '\r', '\xC7', '\x3', '\x2', - '\x2', '\x2', '\xF', '\xC9', '\x3', '\x2', '\x2', '\x2', '\x11', '\xCB', - '\x3', '\x2', '\x2', '\x2', '\x13', '\xCD', '\x3', '\x2', '\x2', '\x2', - '\x15', '\xCF', '\x3', '\x2', '\x2', '\x2', '\x17', '\xD2', '\x3', '\x2', - '\x2', '\x2', '\x19', '\xD4', '\x3', '\x2', '\x2', '\x2', '\x1B', '\xD6', - '\x3', '\x2', '\x2', '\x2', '\x1D', '\xD8', '\x3', '\x2', '\x2', '\x2', - '\x1F', '\xDA', '\x3', '\x2', '\x2', '\x2', '!', '\xDC', '\x3', '\x2', - '\x2', '\x2', '#', '\xDE', '\x3', '\x2', '\x2', '\x2', '%', '\xE1', '\x3', - '\x2', '\x2', '\x2', '\'', '\xE4', '\x3', '\x2', '\x2', '\x2', ')', '\xE6', - '\x3', '\x2', '\x2', '\x2', '+', '\xE9', '\x3', '\x2', '\x2', '\x2', '-', - '\xEB', '\x3', '\x2', '\x2', '\x2', '/', '\xED', '\x3', '\x2', '\x2', - '\x2', '\x31', '\xEF', '\x3', '\x2', '\x2', '\x2', '\x33', '\xF2', '\x3', - '\x2', '\x2', '\x2', '\x35', '\xF4', '\x3', '\x2', '\x2', '\x2', '\x37', - '\xF6', '\x3', '\x2', '\x2', '\x2', '\x39', '\xF8', '\x3', '\x2', '\x2', - '\x2', ';', '\xFC', '\x3', '\x2', '\x2', '\x2', '=', '\x102', '\x3', '\x2', - '\x2', '\x2', '?', '\x105', '\x3', '\x2', '\x2', '\x2', '\x41', '\x109', - '\x3', '\x2', '\x2', '\x2', '\x43', '\x111', '\x3', '\x2', '\x2', '\x2', - '\x45', '\x114', '\x3', '\x2', '\x2', '\x2', 'G', '\x119', '\x3', '\x2', - '\x2', '\x2', 'I', '\x122', '\x3', '\x2', '\x2', '\x2', 'K', '\x129', - '\x3', '\x2', '\x2', '\x2', 'M', '\x130', '\x3', '\x2', '\x2', '\x2', - 'O', '\x136', '\x3', '\x2', '\x2', '\x2', 'Q', '\x13B', '\x3', '\x2', - '\x2', '\x2', 'S', '\x141', '\x3', '\x2', '\x2', '\x2', 'U', '\x144', - '\x3', '\x2', '\x2', '\x2', 'W', '\x149', '\x3', '\x2', '\x2', '\x2', - 'Y', '\x14E', '\x3', '\x2', '\x2', '\x2', '[', '\x154', '\x3', '\x2', - '\x2', '\x2', ']', '\x158', '\x3', '\x2', '\x2', '\x2', '_', '\x15D', - '\x3', '\x2', '\x2', '\x2', '\x61', '\x164', '\x3', '\x2', '\x2', '\x2', - '\x63', '\x167', '\x3', '\x2', '\x2', '\x2', '\x65', '\x16D', '\x3', '\x2', - '\x2', '\x2', 'g', '\x174', '\x3', '\x2', '\x2', '\x2', 'i', '\x178', - '\x3', '\x2', '\x2', '\x2', 'k', '\x17D', '\x3', '\x2', '\x2', '\x2', - 'm', '\x181', '\x3', '\x2', '\x2', '\x2', 'o', '\x18B', '\x3', '\x2', - '\x2', '\x2', 'q', '\x191', '\x3', '\x2', '\x2', '\x2', 's', '\x198', - '\x3', '\x2', '\x2', '\x2', 'u', '\x1CE', '\x3', '\x2', '\x2', '\x2', - 'w', '\x1E2', '\x3', '\x2', '\x2', '\x2', 'y', '\x1E4', '\x3', '\x2', - '\x2', '\x2', '{', '\x1E9', '\x3', '\x2', '\x2', '\x2', '}', '\x1EF', - '\x3', '\x2', '\x2', '\x2', '\x7F', '\x1F1', '\x3', '\x2', '\x2', '\x2', - '\x81', '\x1F3', '\x3', '\x2', '\x2', '\x2', '\x83', '\x1FE', '\x3', '\x2', - '\x2', '\x2', '\x85', '\x200', '\x3', '\x2', '\x2', '\x2', '\x87', '\x203', - '\x3', '\x2', '\x2', '\x2', '\x89', '\x205', '\x3', '\x2', '\x2', '\x2', - '\x8B', '\x207', '\x3', '\x2', '\x2', '\x2', '\x8D', '\x209', '\x3', '\x2', - '\x2', '\x2', '\x8F', '\x20B', '\x3', '\x2', '\x2', '\x2', '\x91', '\x20D', - '\x3', '\x2', '\x2', '\x2', '\x93', '\x20F', '\x3', '\x2', '\x2', '\x2', - '\x95', '\x211', '\x3', '\x2', '\x2', '\x2', '\x97', '\x213', '\x3', '\x2', - '\x2', '\x2', '\x99', '\x215', '\x3', '\x2', '\x2', '\x2', '\x9B', '\x217', - '\x3', '\x2', '\x2', '\x2', '\x9D', '\x219', '\x3', '\x2', '\x2', '\x2', - '\x9F', '\x21B', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x21D', '\x3', '\x2', - '\x2', '\x2', '\xA3', '\x21F', '\x3', '\x2', '\x2', '\x2', '\xA5', '\x221', - '\x3', '\x2', '\x2', '\x2', '\xA7', '\x223', '\x3', '\x2', '\x2', '\x2', - '\xA9', '\x225', '\x3', '\x2', '\x2', '\x2', '\xAB', '\x227', '\x3', '\x2', - '\x2', '\x2', '\xAD', '\x229', '\x3', '\x2', '\x2', '\x2', '\xAF', '\x22B', - '\x3', '\x2', '\x2', '\x2', '\xB1', '\x22D', '\x3', '\x2', '\x2', '\x2', - '\xB3', '\x22F', '\x3', '\x2', '\x2', '\x2', '\xB5', '\x231', '\x3', '\x2', - '\x2', '\x2', '\xB7', '\x233', '\x3', '\x2', '\x2', '\x2', '\xB9', '\x235', - '\x3', '\x2', '\x2', '\x2', '\xBB', '\x237', '\x3', '\x2', '\x2', '\x2', - '\xBD', '\xBE', '\a', ',', '\x2', '\x2', '\xBE', '\x4', '\x3', '\x2', - '\x2', '\x2', '\xBF', '\xC0', '\a', '.', '\x2', '\x2', '\xC0', '\x6', - '\x3', '\x2', '\x2', '\x2', '\xC1', '\xC2', '\a', '*', '\x2', '\x2', '\xC2', - '\b', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC4', '\a', '+', '\x2', '\x2', - '\xC4', '\n', '\x3', '\x2', '\x2', '\x2', '\xC5', '\xC6', '\a', '\x30', - '\x2', '\x2', '\xC6', '\f', '\x3', '\x2', '\x2', '\x2', '\xC7', '\xC8', - '\a', ']', '\x2', '\x2', '\xC8', '\xE', '\x3', '\x2', '\x2', '\x2', '\xC9', - '\xCA', '\a', '_', '\x2', '\x2', '\xCA', '\x10', '\x3', '\x2', '\x2', - '\x2', '\xCB', '\xCC', '\a', '\x41', '\x2', '\x2', '\xCC', '\x12', '\x3', - '\x2', '\x2', '\x2', '\xCD', '\xCE', '\a', '<', '\x2', '\x2', '\xCE', - '\x14', '\x3', '\x2', '\x2', '\x2', '\xCF', '\xD0', '\a', '\x41', '\x2', - '\x2', '\xD0', '\xD1', '\a', '\x41', '\x2', '\x2', '\xD1', '\x16', '\x3', - '\x2', '\x2', '\x2', '\xD2', '\xD3', '\a', '\x31', '\x2', '\x2', '\xD3', - '\x18', '\x3', '\x2', '\x2', '\x2', '\xD4', '\xD5', '\a', '\'', '\x2', - '\x2', '\xD5', '\x1A', '\x3', '\x2', '\x2', '\x2', '\xD6', '\xD7', '\a', - '-', '\x2', '\x2', '\xD7', '\x1C', '\x3', '\x2', '\x2', '\x2', '\xD8', - '\xD9', '\a', '/', '\x2', '\x2', '\xD9', '\x1E', '\x3', '\x2', '\x2', - '\x2', '\xDA', '\xDB', '\a', '>', '\x2', '\x2', '\xDB', ' ', '\x3', '\x2', - '\x2', '\x2', '\xDC', '\xDD', '\a', '@', '\x2', '\x2', '\xDD', '\"', '\x3', - '\x2', '\x2', '\x2', '\xDE', '\xDF', '\a', '@', '\x2', '\x2', '\xDF', - '\xE0', '\a', '?', '\x2', '\x2', '\xE0', '$', '\x3', '\x2', '\x2', '\x2', - '\xE1', '\xE2', '\a', '>', '\x2', '\x2', '\xE2', '\xE3', '\a', '?', '\x2', - '\x2', '\xE3', '&', '\x3', '\x2', '\x2', '\x2', '\xE4', '\xE5', '\a', - '?', '\x2', '\x2', '\xE5', '(', '\x3', '\x2', '\x2', '\x2', '\xE6', '\xE7', - '\a', '#', '\x2', '\x2', '\xE7', '\xE8', '\a', '?', '\x2', '\x2', '\xE8', - '*', '\x3', '\x2', '\x2', '\x2', '\xE9', '\xEA', '\a', '(', '\x2', '\x2', - '\xEA', ',', '\x3', '\x2', '\x2', '\x2', '\xEB', '\xEC', '\a', '`', '\x2', - '\x2', '\xEC', '.', '\x3', '\x2', '\x2', '\x2', '\xED', '\xEE', '\a', - '~', '\x2', '\x2', '\xEE', '\x30', '\x3', '\x2', '\x2', '\x2', '\xEF', - '\xF0', '\a', '~', '\x2', '\x2', '\xF0', '\xF1', '\a', '~', '\x2', '\x2', - '\xF1', '\x32', '\x3', '\x2', '\x2', '\x2', '\xF2', '\xF3', '\a', '\x80', - '\x2', '\x2', '\xF3', '\x34', '\x3', '\x2', '\x2', '\x2', '\xF4', '\xF5', - '\a', '}', '\x2', '\x2', '\xF5', '\x36', '\x3', '\x2', '\x2', '\x2', '\xF6', - '\xF7', '\a', '\x7F', '\x2', '\x2', '\xF7', '\x38', '\x3', '\x2', '\x2', - '\x2', '\xF8', '\xF9', '\x5', '\x89', '\x45', '\x2', '\xF9', '\xFA', '\x5', - '\xA3', 'R', '\x2', '\xFA', '\xFB', '\x5', '\x8F', 'H', '\x2', '\xFB', - ':', '\x3', '\x2', '\x2', '\x2', '\xFC', '\xFD', '\x5', '\x89', '\x45', - '\x2', '\xFD', '\xFE', '\x5', '\xAB', 'V', '\x2', '\xFE', '\xFF', '\x5', - '\xAB', 'V', '\x2', '\xFF', '\x100', '\x5', '\x89', '\x45', '\x2', '\x100', - '\x101', '\x5', '\xB9', ']', '\x2', '\x101', '<', '\x3', '\x2', '\x2', - '\x2', '\x102', '\x103', '\x5', '\x89', '\x45', '\x2', '\x103', '\x104', - '\x5', '\xAD', 'W', '\x2', '\x104', '>', '\x3', '\x2', '\x2', '\x2', '\x105', - '\x106', '\x5', '\x89', '\x45', '\x2', '\x106', '\x107', '\x5', '\xAD', - 'W', '\x2', '\x107', '\x108', '\x5', '\x8D', 'G', '\x2', '\x108', '@', - '\x3', '\x2', '\x2', '\x2', '\x109', '\x10A', '\x5', '\x8B', '\x46', '\x2', - '\x10A', '\x10B', '\x5', '\x91', 'I', '\x2', '\x10B', '\x10C', '\x5', - '\xAF', 'X', '\x2', '\x10C', '\x10D', '\x5', '\xB5', '[', '\x2', '\x10D', - '\x10E', '\x5', '\x91', 'I', '\x2', '\x10E', '\x10F', '\x5', '\x91', 'I', - '\x2', '\x10F', '\x110', '\x5', '\xA3', 'R', '\x2', '\x110', '\x42', '\x3', - '\x2', '\x2', '\x2', '\x111', '\x112', '\x5', '\x8B', '\x46', '\x2', '\x112', - '\x113', '\x5', '\xB9', ']', '\x2', '\x113', '\x44', '\x3', '\x2', '\x2', - '\x2', '\x114', '\x115', '\x5', '\x8F', 'H', '\x2', '\x115', '\x116', - '\x5', '\x91', 'I', '\x2', '\x116', '\x117', '\x5', '\xAD', 'W', '\x2', - '\x117', '\x118', '\x5', '\x8D', 'G', '\x2', '\x118', '\x46', '\x3', '\x2', - '\x2', '\x2', '\x119', '\x11A', '\x5', '\x8F', 'H', '\x2', '\x11A', '\x11B', - '\x5', '\x99', 'M', '\x2', '\x11B', '\x11C', '\x5', '\xAD', 'W', '\x2', - '\x11C', '\x11D', '\x5', '\xAF', 'X', '\x2', '\x11D', '\x11E', '\x5', - '\x99', 'M', '\x2', '\x11E', '\x11F', '\x5', '\xA3', 'R', '\x2', '\x11F', - '\x120', '\x5', '\x8D', 'G', '\x2', '\x120', '\x121', '\x5', '\xAF', 'X', - '\x2', '\x121', 'H', '\x3', '\x2', '\x2', '\x2', '\x122', '\x123', '\x5', - '\x91', 'I', '\x2', '\x123', '\x124', '\x5', '\xAD', 'W', '\x2', '\x124', - '\x125', '\x5', '\x8D', 'G', '\x2', '\x125', '\x126', '\x5', '\x89', '\x45', - '\x2', '\x126', '\x127', '\x5', '\xA7', 'T', '\x2', '\x127', '\x128', - '\x5', '\x91', 'I', '\x2', '\x128', 'J', '\x3', '\x2', '\x2', '\x2', '\x129', - '\x12A', '\x5', '\x91', 'I', '\x2', '\x12A', '\x12B', '\x5', '\xB7', '\\', - '\x2', '\x12B', '\x12C', '\x5', '\x99', 'M', '\x2', '\x12C', '\x12D', - '\x5', '\xAD', 'W', '\x2', '\x12D', '\x12E', '\x5', '\xAF', 'X', '\x2', - '\x12E', '\x12F', '\x5', '\xAD', 'W', '\x2', '\x12F', 'L', '\x3', '\x2', - '\x2', '\x2', '\x130', '\x131', '\a', 'h', '\x2', '\x2', '\x131', '\x132', - '\a', '\x63', '\x2', '\x2', '\x132', '\x133', '\a', 'n', '\x2', '\x2', - '\x133', '\x134', '\a', 'u', '\x2', '\x2', '\x134', '\x135', '\a', 'g', - '\x2', '\x2', '\x135', 'N', '\x3', '\x2', '\x2', '\x2', '\x136', '\x137', - '\x5', '\x93', 'J', '\x2', '\x137', '\x138', '\x5', '\xAB', 'V', '\x2', - '\x138', '\x139', '\x5', '\xA5', 'S', '\x2', '\x139', '\x13A', '\x5', - '\xA1', 'Q', '\x2', '\x13A', 'P', '\x3', '\x2', '\x2', '\x2', '\x13B', - '\x13C', '\x5', '\x95', 'K', '\x2', '\x13C', '\x13D', '\x5', '\xAB', 'V', - '\x2', '\x13D', '\x13E', '\x5', '\xA5', 'S', '\x2', '\x13E', '\x13F', - '\x5', '\xB1', 'Y', '\x2', '\x13F', '\x140', '\x5', '\xA7', 'T', '\x2', - '\x140', 'R', '\x3', '\x2', '\x2', '\x2', '\x141', '\x142', '\x5', '\x99', - 'M', '\x2', '\x142', '\x143', '\x5', '\xA3', 'R', '\x2', '\x143', 'T', - '\x3', '\x2', '\x2', '\x2', '\x144', '\x145', '\x5', '\x9B', 'N', '\x2', - '\x145', '\x146', '\x5', '\xA5', 'S', '\x2', '\x146', '\x147', '\x5', - '\x99', 'M', '\x2', '\x147', '\x148', '\x5', '\xA3', 'R', '\x2', '\x148', - 'V', '\x3', '\x2', '\x2', '\x2', '\x149', '\x14A', '\x5', '\x9F', 'P', - '\x2', '\x14A', '\x14B', '\x5', '\x99', 'M', '\x2', '\x14B', '\x14C', - '\x5', '\x9D', 'O', '\x2', '\x14C', '\x14D', '\x5', '\x91', 'I', '\x2', - '\x14D', 'X', '\x3', '\x2', '\x2', '\x2', '\x14E', '\x14F', '\x5', '\x9F', - 'P', '\x2', '\x14F', '\x150', '\x5', '\x99', 'M', '\x2', '\x150', '\x151', - '\x5', '\xA1', 'Q', '\x2', '\x151', '\x152', '\x5', '\x99', 'M', '\x2', - '\x152', '\x153', '\x5', '\xAF', 'X', '\x2', '\x153', 'Z', '\x3', '\x2', - '\x2', '\x2', '\x154', '\x155', '\x5', '\xA3', 'R', '\x2', '\x155', '\x156', - '\x5', '\xA5', 'S', '\x2', '\x156', '\x157', '\x5', '\xAF', 'X', '\x2', - '\x157', '\\', '\x3', '\x2', '\x2', '\x2', '\x158', '\x159', '\a', 'p', - '\x2', '\x2', '\x159', '\x15A', '\a', 'w', '\x2', '\x2', '\x15A', '\x15B', - '\a', 'n', '\x2', '\x2', '\x15B', '\x15C', '\a', 'n', '\x2', '\x2', '\x15C', - '^', '\x3', '\x2', '\x2', '\x2', '\x15D', '\x15E', '\x5', '\xA5', 'S', - '\x2', '\x15E', '\x15F', '\x5', '\x93', 'J', '\x2', '\x15F', '\x160', - '\x5', '\x93', 'J', '\x2', '\x160', '\x161', '\x5', '\xAD', 'W', '\x2', - '\x161', '\x162', '\x5', '\x91', 'I', '\x2', '\x162', '\x163', '\x5', - '\xAF', 'X', '\x2', '\x163', '`', '\x3', '\x2', '\x2', '\x2', '\x164', - '\x165', '\x5', '\xA5', 'S', '\x2', '\x165', '\x166', '\x5', '\xAB', 'V', - '\x2', '\x166', '\x62', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', - '\x5', '\xA5', 'S', '\x2', '\x168', '\x169', '\x5', '\xAB', 'V', '\x2', - '\x169', '\x16A', '\x5', '\x8F', 'H', '\x2', '\x16A', '\x16B', '\x5', - '\x91', 'I', '\x2', '\x16B', '\x16C', '\x5', '\xAB', 'V', '\x2', '\x16C', - '\x64', '\x3', '\x2', '\x2', '\x2', '\x16D', '\x16E', '\x5', '\xAD', 'W', - '\x2', '\x16E', '\x16F', '\x5', '\x91', 'I', '\x2', '\x16F', '\x170', - '\x5', '\x9F', 'P', '\x2', '\x170', '\x171', '\x5', '\x91', 'I', '\x2', - '\x171', '\x172', '\x5', '\x8D', 'G', '\x2', '\x172', '\x173', '\x5', - '\xAF', 'X', '\x2', '\x173', '\x66', '\x3', '\x2', '\x2', '\x2', '\x174', - '\x175', '\x5', '\xAF', 'X', '\x2', '\x175', '\x176', '\x5', '\xA5', 'S', - '\x2', '\x176', '\x177', '\x5', '\xA7', 'T', '\x2', '\x177', 'h', '\x3', - '\x2', '\x2', '\x2', '\x178', '\x179', '\a', 'v', '\x2', '\x2', '\x179', - '\x17A', '\a', 't', '\x2', '\x2', '\x17A', '\x17B', '\a', 'w', '\x2', - '\x2', '\x17B', '\x17C', '\a', 'g', '\x2', '\x2', '\x17C', 'j', '\x3', - '\x2', '\x2', '\x2', '\x17D', '\x17E', '\a', 'w', '\x2', '\x2', '\x17E', - '\x17F', '\a', '\x66', '\x2', '\x2', '\x17F', '\x180', '\a', 'h', '\x2', - '\x2', '\x180', 'l', '\x3', '\x2', '\x2', '\x2', '\x181', '\x182', '\a', - 'w', '\x2', '\x2', '\x182', '\x183', '\a', 'p', '\x2', '\x2', '\x183', - '\x184', '\a', '\x66', '\x2', '\x2', '\x184', '\x185', '\a', 'g', '\x2', - '\x2', '\x185', '\x186', '\a', 'h', '\x2', '\x2', '\x186', '\x187', '\a', - 'k', '\x2', '\x2', '\x187', '\x188', '\a', 'p', '\x2', '\x2', '\x188', - '\x189', '\a', 'g', '\x2', '\x2', '\x189', '\x18A', '\a', '\x66', '\x2', - '\x2', '\x18A', 'n', '\x3', '\x2', '\x2', '\x2', '\x18B', '\x18C', '\x5', - '\xB3', 'Z', '\x2', '\x18C', '\x18D', '\x5', '\x89', '\x45', '\x2', '\x18D', - '\x18E', '\x5', '\x9F', 'P', '\x2', '\x18E', '\x18F', '\x5', '\xB1', 'Y', - '\x2', '\x18F', '\x190', '\x5', '\x91', 'I', '\x2', '\x190', 'p', '\x3', - '\x2', '\x2', '\x2', '\x191', '\x192', '\x5', '\xB5', '[', '\x2', '\x192', - '\x193', '\x5', '\x97', 'L', '\x2', '\x193', '\x194', '\x5', '\x91', 'I', - '\x2', '\x194', '\x195', '\x5', '\xAB', 'V', '\x2', '\x195', '\x196', - '\x5', '\x91', 'I', '\x2', '\x196', 'r', '\x3', '\x2', '\x2', '\x2', '\x197', - '\x199', '\t', '\x2', '\x2', '\x2', '\x198', '\x197', '\x3', '\x2', '\x2', - '\x2', '\x199', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x19A', '\x198', - '\x3', '\x2', '\x2', '\x2', '\x19A', '\x19B', '\x3', '\x2', '\x2', '\x2', - '\x19B', '\x19C', '\x3', '\x2', '\x2', '\x2', '\x19C', '\x19D', '\b', - ':', '\x2', '\x2', '\x19D', 't', '\x3', '\x2', '\x2', '\x2', '\x19E', - '\x1A0', '\t', '\x3', '\x2', '\x2', '\x19F', '\x19E', '\x3', '\x2', '\x2', - '\x2', '\x19F', '\x1A0', '\x3', '\x2', '\x2', '\x2', '\x1A0', '\x1A2', - '\x3', '\x2', '\x2', '\x2', '\x1A1', '\x1A3', '\x5', '\x87', '\x44', '\x2', - '\x1A2', '\x1A1', '\x3', '\x2', '\x2', '\x2', '\x1A3', '\x1A4', '\x3', - '\x2', '\x2', '\x2', '\x1A4', '\x1A2', '\x3', '\x2', '\x2', '\x2', '\x1A4', - '\x1A5', '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1AD', '\x3', '\x2', '\x2', - '\x2', '\x1A6', '\x1AA', '\a', '\x30', '\x2', '\x2', '\x1A7', '\x1A9', - '\x5', '\x87', '\x44', '\x2', '\x1A8', '\x1A7', '\x3', '\x2', '\x2', '\x2', - '\x1A9', '\x1AC', '\x3', '\x2', '\x2', '\x2', '\x1AA', '\x1A8', '\x3', - '\x2', '\x2', '\x2', '\x1AA', '\x1AB', '\x3', '\x2', '\x2', '\x2', '\x1AB', - '\x1AE', '\x3', '\x2', '\x2', '\x2', '\x1AC', '\x1AA', '\x3', '\x2', '\x2', - '\x2', '\x1AD', '\x1A6', '\x3', '\x2', '\x2', '\x2', '\x1AD', '\x1AE', - '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1B8', '\x3', '\x2', '\x2', '\x2', - '\x1AF', '\x1B1', '\x5', '\x91', 'I', '\x2', '\x1B0', '\x1B2', '\t', '\x3', - '\x2', '\x2', '\x1B1', '\x1B0', '\x3', '\x2', '\x2', '\x2', '\x1B1', '\x1B2', - '\x3', '\x2', '\x2', '\x2', '\x1B2', '\x1B4', '\x3', '\x2', '\x2', '\x2', - '\x1B3', '\x1B5', '\x5', '\x87', '\x44', '\x2', '\x1B4', '\x1B3', '\x3', - '\x2', '\x2', '\x2', '\x1B5', '\x1B6', '\x3', '\x2', '\x2', '\x2', '\x1B6', - '\x1B4', '\x3', '\x2', '\x2', '\x2', '\x1B6', '\x1B7', '\x3', '\x2', '\x2', - '\x2', '\x1B7', '\x1B9', '\x3', '\x2', '\x2', '\x2', '\x1B8', '\x1AF', - '\x3', '\x2', '\x2', '\x2', '\x1B8', '\x1B9', '\x3', '\x2', '\x2', '\x2', - '\x1B9', '\x1CF', '\x3', '\x2', '\x2', '\x2', '\x1BA', '\x1BC', '\t', - '\x3', '\x2', '\x2', '\x1BB', '\x1BA', '\x3', '\x2', '\x2', '\x2', '\x1BB', - '\x1BC', '\x3', '\x2', '\x2', '\x2', '\x1BC', '\x1BD', '\x3', '\x2', '\x2', - '\x2', '\x1BD', '\x1BF', '\a', '\x30', '\x2', '\x2', '\x1BE', '\x1C0', - '\x5', '\x87', '\x44', '\x2', '\x1BF', '\x1BE', '\x3', '\x2', '\x2', '\x2', - '\x1C0', '\x1C1', '\x3', '\x2', '\x2', '\x2', '\x1C1', '\x1BF', '\x3', - '\x2', '\x2', '\x2', '\x1C1', '\x1C2', '\x3', '\x2', '\x2', '\x2', '\x1C2', - '\x1CC', '\x3', '\x2', '\x2', '\x2', '\x1C3', '\x1C5', '\x5', '\x91', - 'I', '\x2', '\x1C4', '\x1C6', '\t', '\x3', '\x2', '\x2', '\x1C5', '\x1C4', - '\x3', '\x2', '\x2', '\x2', '\x1C5', '\x1C6', '\x3', '\x2', '\x2', '\x2', - '\x1C6', '\x1C8', '\x3', '\x2', '\x2', '\x2', '\x1C7', '\x1C9', '\x5', - '\x87', '\x44', '\x2', '\x1C8', '\x1C7', '\x3', '\x2', '\x2', '\x2', '\x1C9', - '\x1CA', '\x3', '\x2', '\x2', '\x2', '\x1CA', '\x1C8', '\x3', '\x2', '\x2', - '\x2', '\x1CA', '\x1CB', '\x3', '\x2', '\x2', '\x2', '\x1CB', '\x1CD', - '\x3', '\x2', '\x2', '\x2', '\x1CC', '\x1C3', '\x3', '\x2', '\x2', '\x2', - '\x1CC', '\x1CD', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1CF', '\x3', - '\x2', '\x2', '\x2', '\x1CE', '\x19F', '\x3', '\x2', '\x2', '\x2', '\x1CE', - '\x1BB', '\x3', '\x2', '\x2', '\x2', '\x1CF', 'v', '\x3', '\x2', '\x2', - '\x2', '\x1D0', '\x1D5', '\a', '$', '\x2', '\x2', '\x1D1', '\x1D4', '\x5', - 'y', '=', '\x2', '\x1D2', '\x1D4', '\x5', '\x81', '\x41', '\x2', '\x1D3', - '\x1D1', '\x3', '\x2', '\x2', '\x2', '\x1D3', '\x1D2', '\x3', '\x2', '\x2', - '\x2', '\x1D4', '\x1D7', '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D3', - '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D6', '\x3', '\x2', '\x2', '\x2', - '\x1D6', '\x1D8', '\x3', '\x2', '\x2', '\x2', '\x1D7', '\x1D5', '\x3', - '\x2', '\x2', '\x2', '\x1D8', '\x1E3', '\a', '$', '\x2', '\x2', '\x1D9', - '\x1DE', '\a', ')', '\x2', '\x2', '\x1DA', '\x1DD', '\x5', 'y', '=', '\x2', - '\x1DB', '\x1DD', '\x5', '\x7F', '@', '\x2', '\x1DC', '\x1DA', '\x3', - '\x2', '\x2', '\x2', '\x1DC', '\x1DB', '\x3', '\x2', '\x2', '\x2', '\x1DD', - '\x1E0', '\x3', '\x2', '\x2', '\x2', '\x1DE', '\x1DC', '\x3', '\x2', '\x2', - '\x2', '\x1DE', '\x1DF', '\x3', '\x2', '\x2', '\x2', '\x1DF', '\x1E1', - '\x3', '\x2', '\x2', '\x2', '\x1E0', '\x1DE', '\x3', '\x2', '\x2', '\x2', - '\x1E1', '\x1E3', '\a', ')', '\x2', '\x2', '\x1E2', '\x1D0', '\x3', '\x2', - '\x2', '\x2', '\x1E2', '\x1D9', '\x3', '\x2', '\x2', '\x2', '\x1E3', 'x', - '\x3', '\x2', '\x2', '\x2', '\x1E4', '\x1E7', '\a', '^', '\x2', '\x2', - '\x1E5', '\x1E8', '\t', '\x4', '\x2', '\x2', '\x1E6', '\x1E8', '\x5', - '{', '>', '\x2', '\x1E7', '\x1E5', '\x3', '\x2', '\x2', '\x2', '\x1E7', - '\x1E6', '\x3', '\x2', '\x2', '\x2', '\x1E8', 'z', '\x3', '\x2', '\x2', - '\x2', '\x1E9', '\x1EA', '\a', 'w', '\x2', '\x2', '\x1EA', '\x1EB', '\x5', - '}', '?', '\x2', '\x1EB', '\x1EC', '\x5', '}', '?', '\x2', '\x1EC', '\x1ED', - '\x5', '}', '?', '\x2', '\x1ED', '\x1EE', '\x5', '}', '?', '\x2', '\x1EE', - '|', '\x3', '\x2', '\x2', '\x2', '\x1EF', '\x1F0', '\t', '\x5', '\x2', - '\x2', '\x1F0', '~', '\x3', '\x2', '\x2', '\x2', '\x1F1', '\x1F2', '\n', - '\x6', '\x2', '\x2', '\x1F2', '\x80', '\x3', '\x2', '\x2', '\x2', '\x1F3', - '\x1F4', '\n', '\a', '\x2', '\x2', '\x1F4', '\x82', '\x3', '\x2', '\x2', - '\x2', '\x1F5', '\x1FF', '\x3', '\x2', '\x2', '\x2', '\x1F6', '\x1FB', - '\t', '\b', '\x2', '\x2', '\x1F7', '\x1FA', '\t', '\b', '\x2', '\x2', - '\x1F8', '\x1FA', '\x5', '\x87', '\x44', '\x2', '\x1F9', '\x1F7', '\x3', - '\x2', '\x2', '\x2', '\x1F9', '\x1F8', '\x3', '\x2', '\x2', '\x2', '\x1FA', - '\x1FD', '\x3', '\x2', '\x2', '\x2', '\x1FB', '\x1F9', '\x3', '\x2', '\x2', - '\x2', '\x1FB', '\x1FC', '\x3', '\x2', '\x2', '\x2', '\x1FC', '\x1FF', - '\x3', '\x2', '\x2', '\x2', '\x1FD', '\x1FB', '\x3', '\x2', '\x2', '\x2', - '\x1FE', '\x1F5', '\x3', '\x2', '\x2', '\x2', '\x1FE', '\x1F6', '\x3', - '\x2', '\x2', '\x2', '\x1FF', '\x84', '\x3', '\x2', '\x2', '\x2', '\x200', - '\x201', '\a', '\x42', '\x2', '\x2', '\x201', '\x202', '\x5', '\x83', - '\x42', '\x2', '\x202', '\x86', '\x3', '\x2', '\x2', '\x2', '\x203', '\x204', - '\t', '\t', '\x2', '\x2', '\x204', '\x88', '\x3', '\x2', '\x2', '\x2', - '\x205', '\x206', '\t', '\n', '\x2', '\x2', '\x206', '\x8A', '\x3', '\x2', - '\x2', '\x2', '\x207', '\x208', '\t', '\v', '\x2', '\x2', '\x208', '\x8C', - '\x3', '\x2', '\x2', '\x2', '\x209', '\x20A', '\t', '\f', '\x2', '\x2', - '\x20A', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x20B', '\x20C', '\t', '\r', - '\x2', '\x2', '\x20C', '\x90', '\x3', '\x2', '\x2', '\x2', '\x20D', '\x20E', - '\t', '\xE', '\x2', '\x2', '\x20E', '\x92', '\x3', '\x2', '\x2', '\x2', - '\x20F', '\x210', '\t', '\xF', '\x2', '\x2', '\x210', '\x94', '\x3', '\x2', - '\x2', '\x2', '\x211', '\x212', '\t', '\x10', '\x2', '\x2', '\x212', '\x96', - '\x3', '\x2', '\x2', '\x2', '\x213', '\x214', '\t', '\x11', '\x2', '\x2', - '\x214', '\x98', '\x3', '\x2', '\x2', '\x2', '\x215', '\x216', '\t', '\x12', - '\x2', '\x2', '\x216', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x217', '\x218', - '\t', '\x13', '\x2', '\x2', '\x218', '\x9C', '\x3', '\x2', '\x2', '\x2', - '\x219', '\x21A', '\t', '\x14', '\x2', '\x2', '\x21A', '\x9E', '\x3', - '\x2', '\x2', '\x2', '\x21B', '\x21C', '\t', '\x15', '\x2', '\x2', '\x21C', - '\xA0', '\x3', '\x2', '\x2', '\x2', '\x21D', '\x21E', '\t', '\x16', '\x2', - '\x2', '\x21E', '\xA2', '\x3', '\x2', '\x2', '\x2', '\x21F', '\x220', - '\t', '\x17', '\x2', '\x2', '\x220', '\xA4', '\x3', '\x2', '\x2', '\x2', - '\x221', '\x222', '\t', '\x18', '\x2', '\x2', '\x222', '\xA6', '\x3', - '\x2', '\x2', '\x2', '\x223', '\x224', '\t', '\x19', '\x2', '\x2', '\x224', - '\xA8', '\x3', '\x2', '\x2', '\x2', '\x225', '\x226', '\t', '\x1A', '\x2', - '\x2', '\x226', '\xAA', '\x3', '\x2', '\x2', '\x2', '\x227', '\x228', - '\t', '\x1B', '\x2', '\x2', '\x228', '\xAC', '\x3', '\x2', '\x2', '\x2', - '\x229', '\x22A', '\t', '\x1C', '\x2', '\x2', '\x22A', '\xAE', '\x3', - '\x2', '\x2', '\x2', '\x22B', '\x22C', '\t', '\x1D', '\x2', '\x2', '\x22C', - '\xB0', '\x3', '\x2', '\x2', '\x2', '\x22D', '\x22E', '\t', '\x1E', '\x2', - '\x2', '\x22E', '\xB2', '\x3', '\x2', '\x2', '\x2', '\x22F', '\x230', - '\t', '\x1F', '\x2', '\x2', '\x230', '\xB4', '\x3', '\x2', '\x2', '\x2', - '\x231', '\x232', '\t', ' ', '\x2', '\x2', '\x232', '\xB6', '\x3', '\x2', - '\x2', '\x2', '\x233', '\x234', '\t', '!', '\x2', '\x2', '\x234', '\xB8', - '\x3', '\x2', '\x2', '\x2', '\x235', '\x236', '\t', '\"', '\x2', '\x2', - '\x236', '\xBA', '\x3', '\x2', '\x2', '\x2', '\x237', '\x238', '\t', '#', - '\x2', '\x2', '\x238', '\xBC', '\x3', '\x2', '\x2', '\x2', '\x1A', '\x2', - '\x19A', '\x19F', '\x1A4', '\x1AA', '\x1AD', '\x1B1', '\x1B6', '\x1B8', - '\x1BB', '\x1C1', '\x1C5', '\x1CA', '\x1CC', '\x1CE', '\x1D3', '\x1D5', - '\x1DC', '\x1DE', '\x1E2', '\x1E7', '\x1F9', '\x1FB', '\x1FE', '\x3', - '\b', '\x2', '\x2', + '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x3', '_', + '\x3', '_', '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', '\x2', + '\x2', '\x62', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', + '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', + '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x11', + '!', '\x12', '#', '\x13', '%', '\x14', '\'', '\x15', ')', '\x16', '+', + '\x17', '-', '\x18', '/', '\x19', '\x31', '\x1A', '\x33', '\x1B', '\x35', + '\x1C', '\x37', '\x1D', '\x39', '\x1E', ';', '\x1F', '=', ' ', '?', '!', + '\x41', '\"', '\x43', '#', '\x45', '$', 'G', '%', 'I', '&', 'K', '\'', + 'M', '(', 'O', ')', 'Q', '*', 'S', '+', 'U', ',', 'W', '-', 'Y', '.', + '[', '/', ']', '\x30', '_', '\x31', '\x61', '\x32', '\x63', '\x33', '\x65', + '\x34', 'g', '\x35', 'i', '\x36', 'k', '\x37', 'm', '\x38', 'o', '\x39', + 'q', ':', 's', ';', 'u', '<', 'w', '=', 'y', '>', '{', '?', '}', '@', + '\x7F', '\x2', '\x81', '\x2', '\x83', '\x2', '\x85', '\x2', '\x87', '\x2', + '\x89', '\x41', '\x8B', '\x42', '\x8D', '\x2', '\x8F', '\x2', '\x91', + '\x2', '\x93', '\x2', '\x95', '\x2', '\x97', '\x2', '\x99', '\x2', '\x9B', + '\x2', '\x9D', '\x2', '\x9F', '\x2', '\xA1', '\x2', '\xA3', '\x2', '\xA5', + '\x2', '\xA7', '\x2', '\xA9', '\x2', '\xAB', '\x2', '\xAD', '\x2', '\xAF', + '\x2', '\xB1', '\x2', '\xB3', '\x2', '\xB5', '\x2', '\xB7', '\x2', '\xB9', + '\x2', '\xBB', '\x2', '\xBD', '\x2', '\xBF', '\x2', '\xC1', '\x2', '\x3', + '\x2', '$', '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', '\"', '\x4', + '\x2', '-', '-', '/', '/', '\n', '\x2', '$', '$', '\x31', '\x31', '^', + '^', '\x64', '\x64', 'h', 'h', 'p', 'p', 't', 't', 'v', 'v', '\x5', '\x2', + '\x32', ';', '\x43', 'H', '\x63', 'h', '\x5', '\x2', '\x2', '!', ')', + ')', '^', '^', '\x5', '\x2', '\x2', '!', '$', '$', '^', '^', '\x5', '\x2', + '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x3', '\x2', '\x32', ';', + '\x4', '\x2', '\x43', '\x43', '\x63', '\x63', '\x4', '\x2', '\x44', '\x44', + '\x64', '\x64', '\x4', '\x2', '\x45', '\x45', '\x65', '\x65', '\x4', '\x2', + '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', + '\x2', 'H', 'H', 'h', 'h', '\x4', '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', + 'J', 'J', 'j', 'j', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', 'L', + 'L', 'l', 'l', '\x4', '\x2', 'M', 'M', 'm', 'm', '\x4', '\x2', 'N', 'N', + 'n', 'n', '\x4', '\x2', 'O', 'O', 'o', 'o', '\x4', '\x2', 'P', 'P', 'p', + 'p', '\x4', '\x2', 'Q', 'Q', 'q', 'q', '\x4', '\x2', 'R', 'R', 'r', 'r', + '\x4', '\x2', 'S', 'S', 's', 's', '\x4', '\x2', 'T', 'T', 't', 't', '\x4', + '\x2', 'U', 'U', 'u', 'u', '\x4', '\x2', 'V', 'V', 'v', 'v', '\x4', '\x2', + 'W', 'W', 'w', 'w', '\x4', '\x2', 'X', 'X', 'x', 'x', '\x4', '\x2', 'Y', + 'Y', 'y', 'y', '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x4', '\x2', '[', '[', + '{', '{', '\x4', '\x2', '\\', '\\', '|', '|', '\x2', '\x244', '\x2', '\x3', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', '\x2', + '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', '\t', '\x3', '\x2', '\x2', + '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', '\x2', '\r', '\x3', '\x2', + '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', '\x2', '\x2', '\x11', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', '\x17', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1B', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', '\x2', '!', '\x3', '\x2', '\x2', + '\x2', '\x2', '#', '\x3', '\x2', '\x2', '\x2', '\x2', '%', '\x3', '\x2', + '\x2', '\x2', '\x2', '\'', '\x3', '\x2', '\x2', '\x2', '\x2', ')', '\x3', + '\x2', '\x2', '\x2', '\x2', '+', '\x3', '\x2', '\x2', '\x2', '\x2', '-', + '\x3', '\x2', '\x2', '\x2', '\x2', '/', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x31', '\x3', '\x2', '\x2', '\x2', '\x2', '\x33', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x35', '\x3', '\x2', '\x2', '\x2', '\x2', '\x37', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x39', '\x3', '\x2', '\x2', '\x2', '\x2', + ';', '\x3', '\x2', '\x2', '\x2', '\x2', '=', '\x3', '\x2', '\x2', '\x2', + '\x2', '?', '\x3', '\x2', '\x2', '\x2', '\x2', '\x41', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x43', '\x3', '\x2', '\x2', '\x2', '\x2', '\x45', '\x3', + '\x2', '\x2', '\x2', '\x2', 'G', '\x3', '\x2', '\x2', '\x2', '\x2', 'I', + '\x3', '\x2', '\x2', '\x2', '\x2', 'K', '\x3', '\x2', '\x2', '\x2', '\x2', + 'M', '\x3', '\x2', '\x2', '\x2', '\x2', 'O', '\x3', '\x2', '\x2', '\x2', + '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', '\x2', 'S', '\x3', '\x2', '\x2', + '\x2', '\x2', 'U', '\x3', '\x2', '\x2', '\x2', '\x2', 'W', '\x3', '\x2', + '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', '\x2', '\x2', '\x2', '[', '\x3', + '\x2', '\x2', '\x2', '\x2', ']', '\x3', '\x2', '\x2', '\x2', '\x2', '_', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', '\x2', '\x65', '\x3', '\x2', + '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', '\x2', '\x2', 'i', '\x3', + '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', '\x2', '\x2', '\x2', 'm', + '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', '\x2', '\x2', '\x2', '\x2', + 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', '\x3', '\x2', '\x2', '\x2', + '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', 'w', '\x3', '\x2', '\x2', + '\x2', '\x2', 'y', '\x3', '\x2', '\x2', '\x2', '\x2', '{', '\x3', '\x2', + '\x2', '\x2', '\x2', '}', '\x3', '\x2', '\x2', '\x2', '\x2', '\x89', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x8B', '\x3', '\x2', '\x2', '\x2', '\x3', + '\xC3', '\x3', '\x2', '\x2', '\x2', '\x5', '\xC5', '\x3', '\x2', '\x2', + '\x2', '\a', '\xC7', '\x3', '\x2', '\x2', '\x2', '\t', '\xC9', '\x3', + '\x2', '\x2', '\x2', '\v', '\xCB', '\x3', '\x2', '\x2', '\x2', '\r', '\xCD', + '\x3', '\x2', '\x2', '\x2', '\xF', '\xCF', '\x3', '\x2', '\x2', '\x2', + '\x11', '\xD1', '\x3', '\x2', '\x2', '\x2', '\x13', '\xD3', '\x3', '\x2', + '\x2', '\x2', '\x15', '\xD5', '\x3', '\x2', '\x2', '\x2', '\x17', '\xD8', + '\x3', '\x2', '\x2', '\x2', '\x19', '\xDA', '\x3', '\x2', '\x2', '\x2', + '\x1B', '\xDC', '\x3', '\x2', '\x2', '\x2', '\x1D', '\xDE', '\x3', '\x2', + '\x2', '\x2', '\x1F', '\xE0', '\x3', '\x2', '\x2', '\x2', '!', '\xE2', + '\x3', '\x2', '\x2', '\x2', '#', '\xE4', '\x3', '\x2', '\x2', '\x2', '%', + '\xE7', '\x3', '\x2', '\x2', '\x2', '\'', '\xEA', '\x3', '\x2', '\x2', + '\x2', ')', '\xEC', '\x3', '\x2', '\x2', '\x2', '+', '\xEF', '\x3', '\x2', + '\x2', '\x2', '-', '\xF1', '\x3', '\x2', '\x2', '\x2', '/', '\xF3', '\x3', + '\x2', '\x2', '\x2', '\x31', '\xF5', '\x3', '\x2', '\x2', '\x2', '\x33', + '\xF8', '\x3', '\x2', '\x2', '\x2', '\x35', '\xFA', '\x3', '\x2', '\x2', + '\x2', '\x37', '\xFC', '\x3', '\x2', '\x2', '\x2', '\x39', '\xFE', '\x3', + '\x2', '\x2', '\x2', ';', '\x102', '\x3', '\x2', '\x2', '\x2', '=', '\x106', + '\x3', '\x2', '\x2', '\x2', '?', '\x10C', '\x3', '\x2', '\x2', '\x2', + '\x41', '\x10F', '\x3', '\x2', '\x2', '\x2', '\x43', '\x113', '\x3', '\x2', + '\x2', '\x2', '\x45', '\x11B', '\x3', '\x2', '\x2', '\x2', 'G', '\x11E', + '\x3', '\x2', '\x2', '\x2', 'I', '\x123', '\x3', '\x2', '\x2', '\x2', + 'K', '\x12C', '\x3', '\x2', '\x2', '\x2', 'M', '\x133', '\x3', '\x2', + '\x2', '\x2', 'O', '\x13A', '\x3', '\x2', '\x2', '\x2', 'Q', '\x140', + '\x3', '\x2', '\x2', '\x2', 'S', '\x145', '\x3', '\x2', '\x2', '\x2', + 'U', '\x14B', '\x3', '\x2', '\x2', '\x2', 'W', '\x14E', '\x3', '\x2', + '\x2', '\x2', 'Y', '\x153', '\x3', '\x2', '\x2', '\x2', '[', '\x158', + '\x3', '\x2', '\x2', '\x2', ']', '\x15D', '\x3', '\x2', '\x2', '\x2', + '_', '\x163', '\x3', '\x2', '\x2', '\x2', '\x61', '\x167', '\x3', '\x2', + '\x2', '\x2', '\x63', '\x16C', '\x3', '\x2', '\x2', '\x2', '\x65', '\x173', + '\x3', '\x2', '\x2', '\x2', 'g', '\x176', '\x3', '\x2', '\x2', '\x2', + 'i', '\x17C', '\x3', '\x2', '\x2', '\x2', 'k', '\x182', '\x3', '\x2', + '\x2', '\x2', 'm', '\x189', '\x3', '\x2', '\x2', '\x2', 'o', '\x18D', + '\x3', '\x2', '\x2', '\x2', 'q', '\x192', '\x3', '\x2', '\x2', '\x2', + 's', '\x196', '\x3', '\x2', '\x2', '\x2', 'u', '\x1A0', '\x3', '\x2', + '\x2', '\x2', 'w', '\x1A6', '\x3', '\x2', '\x2', '\x2', 'y', '\x1AD', + '\x3', '\x2', '\x2', '\x2', '{', '\x1E3', '\x3', '\x2', '\x2', '\x2', + '}', '\x1F7', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x1F9', '\x3', '\x2', + '\x2', '\x2', '\x81', '\x1FE', '\x3', '\x2', '\x2', '\x2', '\x83', '\x204', + '\x3', '\x2', '\x2', '\x2', '\x85', '\x206', '\x3', '\x2', '\x2', '\x2', + '\x87', '\x208', '\x3', '\x2', '\x2', '\x2', '\x89', '\x213', '\x3', '\x2', + '\x2', '\x2', '\x8B', '\x215', '\x3', '\x2', '\x2', '\x2', '\x8D', '\x218', + '\x3', '\x2', '\x2', '\x2', '\x8F', '\x21A', '\x3', '\x2', '\x2', '\x2', + '\x91', '\x21C', '\x3', '\x2', '\x2', '\x2', '\x93', '\x21E', '\x3', '\x2', + '\x2', '\x2', '\x95', '\x220', '\x3', '\x2', '\x2', '\x2', '\x97', '\x222', + '\x3', '\x2', '\x2', '\x2', '\x99', '\x224', '\x3', '\x2', '\x2', '\x2', + '\x9B', '\x226', '\x3', '\x2', '\x2', '\x2', '\x9D', '\x228', '\x3', '\x2', + '\x2', '\x2', '\x9F', '\x22A', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x22C', + '\x3', '\x2', '\x2', '\x2', '\xA3', '\x22E', '\x3', '\x2', '\x2', '\x2', + '\xA5', '\x230', '\x3', '\x2', '\x2', '\x2', '\xA7', '\x232', '\x3', '\x2', + '\x2', '\x2', '\xA9', '\x234', '\x3', '\x2', '\x2', '\x2', '\xAB', '\x236', + '\x3', '\x2', '\x2', '\x2', '\xAD', '\x238', '\x3', '\x2', '\x2', '\x2', + '\xAF', '\x23A', '\x3', '\x2', '\x2', '\x2', '\xB1', '\x23C', '\x3', '\x2', + '\x2', '\x2', '\xB3', '\x23E', '\x3', '\x2', '\x2', '\x2', '\xB5', '\x240', + '\x3', '\x2', '\x2', '\x2', '\xB7', '\x242', '\x3', '\x2', '\x2', '\x2', + '\xB9', '\x244', '\x3', '\x2', '\x2', '\x2', '\xBB', '\x246', '\x3', '\x2', + '\x2', '\x2', '\xBD', '\x248', '\x3', '\x2', '\x2', '\x2', '\xBF', '\x24A', + '\x3', '\x2', '\x2', '\x2', '\xC1', '\x24C', '\x3', '\x2', '\x2', '\x2', + '\xC3', '\xC4', '\a', ',', '\x2', '\x2', '\xC4', '\x4', '\x3', '\x2', + '\x2', '\x2', '\xC5', '\xC6', '\a', '.', '\x2', '\x2', '\xC6', '\x6', + '\x3', '\x2', '\x2', '\x2', '\xC7', '\xC8', '\a', '*', '\x2', '\x2', '\xC8', + '\b', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xCA', '\a', '+', '\x2', '\x2', + '\xCA', '\n', '\x3', '\x2', '\x2', '\x2', '\xCB', '\xCC', '\a', '\x30', + '\x2', '\x2', '\xCC', '\f', '\x3', '\x2', '\x2', '\x2', '\xCD', '\xCE', + '\a', ']', '\x2', '\x2', '\xCE', '\xE', '\x3', '\x2', '\x2', '\x2', '\xCF', + '\xD0', '\a', '_', '\x2', '\x2', '\xD0', '\x10', '\x3', '\x2', '\x2', + '\x2', '\xD1', '\xD2', '\a', '\x41', '\x2', '\x2', '\xD2', '\x12', '\x3', + '\x2', '\x2', '\x2', '\xD3', '\xD4', '\a', '<', '\x2', '\x2', '\xD4', + '\x14', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD6', '\a', '\x41', '\x2', + '\x2', '\xD6', '\xD7', '\a', '\x41', '\x2', '\x2', '\xD7', '\x16', '\x3', + '\x2', '\x2', '\x2', '\xD8', '\xD9', '\a', '\x31', '\x2', '\x2', '\xD9', + '\x18', '\x3', '\x2', '\x2', '\x2', '\xDA', '\xDB', '\a', '\'', '\x2', + '\x2', '\xDB', '\x1A', '\x3', '\x2', '\x2', '\x2', '\xDC', '\xDD', '\a', + '-', '\x2', '\x2', '\xDD', '\x1C', '\x3', '\x2', '\x2', '\x2', '\xDE', + '\xDF', '\a', '/', '\x2', '\x2', '\xDF', '\x1E', '\x3', '\x2', '\x2', + '\x2', '\xE0', '\xE1', '\a', '>', '\x2', '\x2', '\xE1', ' ', '\x3', '\x2', + '\x2', '\x2', '\xE2', '\xE3', '\a', '@', '\x2', '\x2', '\xE3', '\"', '\x3', + '\x2', '\x2', '\x2', '\xE4', '\xE5', '\a', '@', '\x2', '\x2', '\xE5', + '\xE6', '\a', '?', '\x2', '\x2', '\xE6', '$', '\x3', '\x2', '\x2', '\x2', + '\xE7', '\xE8', '\a', '>', '\x2', '\x2', '\xE8', '\xE9', '\a', '?', '\x2', + '\x2', '\xE9', '&', '\x3', '\x2', '\x2', '\x2', '\xEA', '\xEB', '\a', + '?', '\x2', '\x2', '\xEB', '(', '\x3', '\x2', '\x2', '\x2', '\xEC', '\xED', + '\a', '#', '\x2', '\x2', '\xED', '\xEE', '\a', '?', '\x2', '\x2', '\xEE', + '*', '\x3', '\x2', '\x2', '\x2', '\xEF', '\xF0', '\a', '(', '\x2', '\x2', + '\xF0', ',', '\x3', '\x2', '\x2', '\x2', '\xF1', '\xF2', '\a', '`', '\x2', + '\x2', '\xF2', '.', '\x3', '\x2', '\x2', '\x2', '\xF3', '\xF4', '\a', + '~', '\x2', '\x2', '\xF4', '\x30', '\x3', '\x2', '\x2', '\x2', '\xF5', + '\xF6', '\a', '~', '\x2', '\x2', '\xF6', '\xF7', '\a', '~', '\x2', '\x2', + '\xF7', '\x32', '\x3', '\x2', '\x2', '\x2', '\xF8', '\xF9', '\a', '\x80', + '\x2', '\x2', '\xF9', '\x34', '\x3', '\x2', '\x2', '\x2', '\xFA', '\xFB', + '\a', '}', '\x2', '\x2', '\xFB', '\x36', '\x3', '\x2', '\x2', '\x2', '\xFC', + '\xFD', '\a', '\x7F', '\x2', '\x2', '\xFD', '\x38', '\x3', '\x2', '\x2', + '\x2', '\xFE', '\xFF', '\x5', '\x8F', 'H', '\x2', '\xFF', '\x100', '\x5', + '\xA5', 'S', '\x2', '\x100', '\x101', '\x5', '\xA5', 'S', '\x2', '\x101', + ':', '\x3', '\x2', '\x2', '\x2', '\x102', '\x103', '\x5', '\x8F', 'H', + '\x2', '\x103', '\x104', '\x5', '\xA9', 'U', '\x2', '\x104', '\x105', + '\x5', '\x95', 'K', '\x2', '\x105', '<', '\x3', '\x2', '\x2', '\x2', '\x106', + '\x107', '\x5', '\x8F', 'H', '\x2', '\x107', '\x108', '\x5', '\xB1', 'Y', + '\x2', '\x108', '\x109', '\x5', '\xB1', 'Y', '\x2', '\x109', '\x10A', + '\x5', '\x8F', 'H', '\x2', '\x10A', '\x10B', '\x5', '\xBF', '`', '\x2', + '\x10B', '>', '\x3', '\x2', '\x2', '\x2', '\x10C', '\x10D', '\x5', '\x8F', + 'H', '\x2', '\x10D', '\x10E', '\x5', '\xB3', 'Z', '\x2', '\x10E', '@', + '\x3', '\x2', '\x2', '\x2', '\x10F', '\x110', '\x5', '\x8F', 'H', '\x2', + '\x110', '\x111', '\x5', '\xB3', 'Z', '\x2', '\x111', '\x112', '\x5', + '\x93', 'J', '\x2', '\x112', '\x42', '\x3', '\x2', '\x2', '\x2', '\x113', + '\x114', '\x5', '\x91', 'I', '\x2', '\x114', '\x115', '\x5', '\x97', 'L', + '\x2', '\x115', '\x116', '\x5', '\xB5', '[', '\x2', '\x116', '\x117', + '\x5', '\xBB', '^', '\x2', '\x117', '\x118', '\x5', '\x97', 'L', '\x2', + '\x118', '\x119', '\x5', '\x97', 'L', '\x2', '\x119', '\x11A', '\x5', + '\xA9', 'U', '\x2', '\x11A', '\x44', '\x3', '\x2', '\x2', '\x2', '\x11B', + '\x11C', '\x5', '\x91', 'I', '\x2', '\x11C', '\x11D', '\x5', '\xBF', '`', + '\x2', '\x11D', '\x46', '\x3', '\x2', '\x2', '\x2', '\x11E', '\x11F', + '\x5', '\x95', 'K', '\x2', '\x11F', '\x120', '\x5', '\x97', 'L', '\x2', + '\x120', '\x121', '\x5', '\xB3', 'Z', '\x2', '\x121', '\x122', '\x5', + '\x93', 'J', '\x2', '\x122', 'H', '\x3', '\x2', '\x2', '\x2', '\x123', + '\x124', '\x5', '\x95', 'K', '\x2', '\x124', '\x125', '\x5', '\x9F', 'P', + '\x2', '\x125', '\x126', '\x5', '\xB3', 'Z', '\x2', '\x126', '\x127', + '\x5', '\xB5', '[', '\x2', '\x127', '\x128', '\x5', '\x9F', 'P', '\x2', + '\x128', '\x129', '\x5', '\xA9', 'U', '\x2', '\x129', '\x12A', '\x5', + '\x93', 'J', '\x2', '\x12A', '\x12B', '\x5', '\xB5', '[', '\x2', '\x12B', + 'J', '\x3', '\x2', '\x2', '\x2', '\x12C', '\x12D', '\x5', '\x97', 'L', + '\x2', '\x12D', '\x12E', '\x5', '\xB3', 'Z', '\x2', '\x12E', '\x12F', + '\x5', '\x93', 'J', '\x2', '\x12F', '\x130', '\x5', '\x8F', 'H', '\x2', + '\x130', '\x131', '\x5', '\xAD', 'W', '\x2', '\x131', '\x132', '\x5', + '\x97', 'L', '\x2', '\x132', 'L', '\x3', '\x2', '\x2', '\x2', '\x133', + '\x134', '\x5', '\x97', 'L', '\x2', '\x134', '\x135', '\x5', '\xBD', '_', + '\x2', '\x135', '\x136', '\x5', '\x9F', 'P', '\x2', '\x136', '\x137', + '\x5', '\xB3', 'Z', '\x2', '\x137', '\x138', '\x5', '\xB5', '[', '\x2', + '\x138', '\x139', '\x5', '\xB3', 'Z', '\x2', '\x139', 'N', '\x3', '\x2', + '\x2', '\x2', '\x13A', '\x13B', '\a', 'h', '\x2', '\x2', '\x13B', '\x13C', + '\a', '\x63', '\x2', '\x2', '\x13C', '\x13D', '\a', 'n', '\x2', '\x2', + '\x13D', '\x13E', '\a', 'u', '\x2', '\x2', '\x13E', '\x13F', '\a', 'g', + '\x2', '\x2', '\x13F', 'P', '\x3', '\x2', '\x2', '\x2', '\x140', '\x141', + '\x5', '\x99', 'M', '\x2', '\x141', '\x142', '\x5', '\xB1', 'Y', '\x2', + '\x142', '\x143', '\x5', '\xAB', 'V', '\x2', '\x143', '\x144', '\x5', + '\xA7', 'T', '\x2', '\x144', 'R', '\x3', '\x2', '\x2', '\x2', '\x145', + '\x146', '\x5', '\x9B', 'N', '\x2', '\x146', '\x147', '\x5', '\xB1', 'Y', + '\x2', '\x147', '\x148', '\x5', '\xAB', 'V', '\x2', '\x148', '\x149', + '\x5', '\xB7', '\\', '\x2', '\x149', '\x14A', '\x5', '\xAD', 'W', '\x2', + '\x14A', 'T', '\x3', '\x2', '\x2', '\x2', '\x14B', '\x14C', '\x5', '\x9F', + 'P', '\x2', '\x14C', '\x14D', '\x5', '\xA9', 'U', '\x2', '\x14D', 'V', + '\x3', '\x2', '\x2', '\x2', '\x14E', '\x14F', '\x5', '\xA1', 'Q', '\x2', + '\x14F', '\x150', '\x5', '\xAB', 'V', '\x2', '\x150', '\x151', '\x5', + '\x9F', 'P', '\x2', '\x151', '\x152', '\x5', '\xA9', 'U', '\x2', '\x152', + 'X', '\x3', '\x2', '\x2', '\x2', '\x153', '\x154', '\x5', '\xA5', 'S', + '\x2', '\x154', '\x155', '\x5', '\x97', 'L', '\x2', '\x155', '\x156', + '\x5', '\x99', 'M', '\x2', '\x156', '\x157', '\x5', '\xB5', '[', '\x2', + '\x157', 'Z', '\x3', '\x2', '\x2', '\x2', '\x158', '\x159', '\x5', '\xA5', + 'S', '\x2', '\x159', '\x15A', '\x5', '\x9F', 'P', '\x2', '\x15A', '\x15B', + '\x5', '\xA3', 'R', '\x2', '\x15B', '\x15C', '\x5', '\x97', 'L', '\x2', + '\x15C', '\\', '\x3', '\x2', '\x2', '\x2', '\x15D', '\x15E', '\x5', '\xA5', + 'S', '\x2', '\x15E', '\x15F', '\x5', '\x9F', 'P', '\x2', '\x15F', '\x160', + '\x5', '\xA7', 'T', '\x2', '\x160', '\x161', '\x5', '\x9F', 'P', '\x2', + '\x161', '\x162', '\x5', '\xB5', '[', '\x2', '\x162', '^', '\x3', '\x2', + '\x2', '\x2', '\x163', '\x164', '\x5', '\xA9', 'U', '\x2', '\x164', '\x165', + '\x5', '\xAB', 'V', '\x2', '\x165', '\x166', '\x5', '\xB5', '[', '\x2', + '\x166', '`', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', '\a', 'p', + '\x2', '\x2', '\x168', '\x169', '\a', 'w', '\x2', '\x2', '\x169', '\x16A', + '\a', 'n', '\x2', '\x2', '\x16A', '\x16B', '\a', 'n', '\x2', '\x2', '\x16B', + '\x62', '\x3', '\x2', '\x2', '\x2', '\x16C', '\x16D', '\x5', '\xAB', 'V', + '\x2', '\x16D', '\x16E', '\x5', '\x99', 'M', '\x2', '\x16E', '\x16F', + '\x5', '\x99', 'M', '\x2', '\x16F', '\x170', '\x5', '\xB3', 'Z', '\x2', + '\x170', '\x171', '\x5', '\x97', 'L', '\x2', '\x171', '\x172', '\x5', + '\xB5', '[', '\x2', '\x172', '\x64', '\x3', '\x2', '\x2', '\x2', '\x173', + '\x174', '\x5', '\xAB', 'V', '\x2', '\x174', '\x175', '\x5', '\xB1', 'Y', + '\x2', '\x175', '\x66', '\x3', '\x2', '\x2', '\x2', '\x176', '\x177', + '\x5', '\xAB', 'V', '\x2', '\x177', '\x178', '\x5', '\xB1', 'Y', '\x2', + '\x178', '\x179', '\x5', '\x95', 'K', '\x2', '\x179', '\x17A', '\x5', + '\x97', 'L', '\x2', '\x17A', '\x17B', '\x5', '\xB1', 'Y', '\x2', '\x17B', + 'h', '\x3', '\x2', '\x2', '\x2', '\x17C', '\x17D', '\x5', '\xB1', 'Y', + '\x2', '\x17D', '\x17E', '\x5', '\x9F', 'P', '\x2', '\x17E', '\x17F', + '\x5', '\x9B', 'N', '\x2', '\x17F', '\x180', '\x5', '\x9D', 'O', '\x2', + '\x180', '\x181', '\x5', '\xB5', '[', '\x2', '\x181', 'j', '\x3', '\x2', + '\x2', '\x2', '\x182', '\x183', '\x5', '\xB3', 'Z', '\x2', '\x183', '\x184', + '\x5', '\x97', 'L', '\x2', '\x184', '\x185', '\x5', '\xA5', 'S', '\x2', + '\x185', '\x186', '\x5', '\x97', 'L', '\x2', '\x186', '\x187', '\x5', + '\x93', 'J', '\x2', '\x187', '\x188', '\x5', '\xB5', '[', '\x2', '\x188', + 'l', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\x5', '\xB5', '[', + '\x2', '\x18A', '\x18B', '\x5', '\xAB', 'V', '\x2', '\x18B', '\x18C', + '\x5', '\xAD', 'W', '\x2', '\x18C', 'n', '\x3', '\x2', '\x2', '\x2', '\x18D', + '\x18E', '\a', 'v', '\x2', '\x2', '\x18E', '\x18F', '\a', 't', '\x2', + '\x2', '\x18F', '\x190', '\a', 'w', '\x2', '\x2', '\x190', '\x191', '\a', + 'g', '\x2', '\x2', '\x191', 'p', '\x3', '\x2', '\x2', '\x2', '\x192', + '\x193', '\a', 'w', '\x2', '\x2', '\x193', '\x194', '\a', '\x66', '\x2', + '\x2', '\x194', '\x195', '\a', 'h', '\x2', '\x2', '\x195', 'r', '\x3', + '\x2', '\x2', '\x2', '\x196', '\x197', '\a', 'w', '\x2', '\x2', '\x197', + '\x198', '\a', 'p', '\x2', '\x2', '\x198', '\x199', '\a', '\x66', '\x2', + '\x2', '\x199', '\x19A', '\a', 'g', '\x2', '\x2', '\x19A', '\x19B', '\a', + 'h', '\x2', '\x2', '\x19B', '\x19C', '\a', 'k', '\x2', '\x2', '\x19C', + '\x19D', '\a', 'p', '\x2', '\x2', '\x19D', '\x19E', '\a', 'g', '\x2', + '\x2', '\x19E', '\x19F', '\a', '\x66', '\x2', '\x2', '\x19F', 't', '\x3', + '\x2', '\x2', '\x2', '\x1A0', '\x1A1', '\x5', '\xB9', ']', '\x2', '\x1A1', + '\x1A2', '\x5', '\x8F', 'H', '\x2', '\x1A2', '\x1A3', '\x5', '\xA5', 'S', + '\x2', '\x1A3', '\x1A4', '\x5', '\xB7', '\\', '\x2', '\x1A4', '\x1A5', + '\x5', '\x97', 'L', '\x2', '\x1A5', 'v', '\x3', '\x2', '\x2', '\x2', '\x1A6', + '\x1A7', '\x5', '\xBB', '^', '\x2', '\x1A7', '\x1A8', '\x5', '\x9D', 'O', + '\x2', '\x1A8', '\x1A9', '\x5', '\x97', 'L', '\x2', '\x1A9', '\x1AA', + '\x5', '\xB1', 'Y', '\x2', '\x1AA', '\x1AB', '\x5', '\x97', 'L', '\x2', + '\x1AB', 'x', '\x3', '\x2', '\x2', '\x2', '\x1AC', '\x1AE', '\t', '\x2', + '\x2', '\x2', '\x1AD', '\x1AC', '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1AF', + '\x3', '\x2', '\x2', '\x2', '\x1AF', '\x1AD', '\x3', '\x2', '\x2', '\x2', + '\x1AF', '\x1B0', '\x3', '\x2', '\x2', '\x2', '\x1B0', '\x1B1', '\x3', + '\x2', '\x2', '\x2', '\x1B1', '\x1B2', '\b', '=', '\x2', '\x2', '\x1B2', + 'z', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B5', '\t', '\x3', '\x2', + '\x2', '\x1B4', '\x1B3', '\x3', '\x2', '\x2', '\x2', '\x1B4', '\x1B5', + '\x3', '\x2', '\x2', '\x2', '\x1B5', '\x1B7', '\x3', '\x2', '\x2', '\x2', + '\x1B6', '\x1B8', '\x5', '\x8D', 'G', '\x2', '\x1B7', '\x1B6', '\x3', + '\x2', '\x2', '\x2', '\x1B8', '\x1B9', '\x3', '\x2', '\x2', '\x2', '\x1B9', + '\x1B7', '\x3', '\x2', '\x2', '\x2', '\x1B9', '\x1BA', '\x3', '\x2', '\x2', + '\x2', '\x1BA', '\x1C2', '\x3', '\x2', '\x2', '\x2', '\x1BB', '\x1BF', + '\a', '\x30', '\x2', '\x2', '\x1BC', '\x1BE', '\x5', '\x8D', 'G', '\x2', + '\x1BD', '\x1BC', '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1C1', '\x3', + '\x2', '\x2', '\x2', '\x1BF', '\x1BD', '\x3', '\x2', '\x2', '\x2', '\x1BF', + '\x1C0', '\x3', '\x2', '\x2', '\x2', '\x1C0', '\x1C3', '\x3', '\x2', '\x2', + '\x2', '\x1C1', '\x1BF', '\x3', '\x2', '\x2', '\x2', '\x1C2', '\x1BB', + '\x3', '\x2', '\x2', '\x2', '\x1C2', '\x1C3', '\x3', '\x2', '\x2', '\x2', + '\x1C3', '\x1CD', '\x3', '\x2', '\x2', '\x2', '\x1C4', '\x1C6', '\x5', + '\x97', 'L', '\x2', '\x1C5', '\x1C7', '\t', '\x3', '\x2', '\x2', '\x1C6', + '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C6', '\x1C7', '\x3', '\x2', '\x2', + '\x2', '\x1C7', '\x1C9', '\x3', '\x2', '\x2', '\x2', '\x1C8', '\x1CA', + '\x5', '\x8D', 'G', '\x2', '\x1C9', '\x1C8', '\x3', '\x2', '\x2', '\x2', + '\x1CA', '\x1CB', '\x3', '\x2', '\x2', '\x2', '\x1CB', '\x1C9', '\x3', + '\x2', '\x2', '\x2', '\x1CB', '\x1CC', '\x3', '\x2', '\x2', '\x2', '\x1CC', + '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1C4', '\x3', '\x2', '\x2', + '\x2', '\x1CD', '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1E4', + '\x3', '\x2', '\x2', '\x2', '\x1CF', '\x1D1', '\t', '\x3', '\x2', '\x2', + '\x1D0', '\x1CF', '\x3', '\x2', '\x2', '\x2', '\x1D0', '\x1D1', '\x3', + '\x2', '\x2', '\x2', '\x1D1', '\x1D2', '\x3', '\x2', '\x2', '\x2', '\x1D2', + '\x1D4', '\a', '\x30', '\x2', '\x2', '\x1D3', '\x1D5', '\x5', '\x8D', + 'G', '\x2', '\x1D4', '\x1D3', '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D6', + '\x3', '\x2', '\x2', '\x2', '\x1D6', '\x1D4', '\x3', '\x2', '\x2', '\x2', + '\x1D6', '\x1D7', '\x3', '\x2', '\x2', '\x2', '\x1D7', '\x1E1', '\x3', + '\x2', '\x2', '\x2', '\x1D8', '\x1DA', '\x5', '\x97', 'L', '\x2', '\x1D9', + '\x1DB', '\t', '\x3', '\x2', '\x2', '\x1DA', '\x1D9', '\x3', '\x2', '\x2', + '\x2', '\x1DA', '\x1DB', '\x3', '\x2', '\x2', '\x2', '\x1DB', '\x1DD', + '\x3', '\x2', '\x2', '\x2', '\x1DC', '\x1DE', '\x5', '\x8D', 'G', '\x2', + '\x1DD', '\x1DC', '\x3', '\x2', '\x2', '\x2', '\x1DE', '\x1DF', '\x3', + '\x2', '\x2', '\x2', '\x1DF', '\x1DD', '\x3', '\x2', '\x2', '\x2', '\x1DF', + '\x1E0', '\x3', '\x2', '\x2', '\x2', '\x1E0', '\x1E2', '\x3', '\x2', '\x2', + '\x2', '\x1E1', '\x1D8', '\x3', '\x2', '\x2', '\x2', '\x1E1', '\x1E2', + '\x3', '\x2', '\x2', '\x2', '\x1E2', '\x1E4', '\x3', '\x2', '\x2', '\x2', + '\x1E3', '\x1B4', '\x3', '\x2', '\x2', '\x2', '\x1E3', '\x1D0', '\x3', + '\x2', '\x2', '\x2', '\x1E4', '|', '\x3', '\x2', '\x2', '\x2', '\x1E5', + '\x1EA', '\a', '$', '\x2', '\x2', '\x1E6', '\x1E9', '\x5', '\x7F', '@', + '\x2', '\x1E7', '\x1E9', '\x5', '\x87', '\x44', '\x2', '\x1E8', '\x1E6', + '\x3', '\x2', '\x2', '\x2', '\x1E8', '\x1E7', '\x3', '\x2', '\x2', '\x2', + '\x1E9', '\x1EC', '\x3', '\x2', '\x2', '\x2', '\x1EA', '\x1E8', '\x3', + '\x2', '\x2', '\x2', '\x1EA', '\x1EB', '\x3', '\x2', '\x2', '\x2', '\x1EB', + '\x1ED', '\x3', '\x2', '\x2', '\x2', '\x1EC', '\x1EA', '\x3', '\x2', '\x2', + '\x2', '\x1ED', '\x1F8', '\a', '$', '\x2', '\x2', '\x1EE', '\x1F3', '\a', + ')', '\x2', '\x2', '\x1EF', '\x1F2', '\x5', '\x7F', '@', '\x2', '\x1F0', + '\x1F2', '\x5', '\x85', '\x43', '\x2', '\x1F1', '\x1EF', '\x3', '\x2', + '\x2', '\x2', '\x1F1', '\x1F0', '\x3', '\x2', '\x2', '\x2', '\x1F2', '\x1F5', + '\x3', '\x2', '\x2', '\x2', '\x1F3', '\x1F1', '\x3', '\x2', '\x2', '\x2', + '\x1F3', '\x1F4', '\x3', '\x2', '\x2', '\x2', '\x1F4', '\x1F6', '\x3', + '\x2', '\x2', '\x2', '\x1F5', '\x1F3', '\x3', '\x2', '\x2', '\x2', '\x1F6', + '\x1F8', '\a', ')', '\x2', '\x2', '\x1F7', '\x1E5', '\x3', '\x2', '\x2', + '\x2', '\x1F7', '\x1EE', '\x3', '\x2', '\x2', '\x2', '\x1F8', '~', '\x3', + '\x2', '\x2', '\x2', '\x1F9', '\x1FC', '\a', '^', '\x2', '\x2', '\x1FA', + '\x1FD', '\t', '\x4', '\x2', '\x2', '\x1FB', '\x1FD', '\x5', '\x81', '\x41', + '\x2', '\x1FC', '\x1FA', '\x3', '\x2', '\x2', '\x2', '\x1FC', '\x1FB', + '\x3', '\x2', '\x2', '\x2', '\x1FD', '\x80', '\x3', '\x2', '\x2', '\x2', + '\x1FE', '\x1FF', '\a', 'w', '\x2', '\x2', '\x1FF', '\x200', '\x5', '\x83', + '\x42', '\x2', '\x200', '\x201', '\x5', '\x83', '\x42', '\x2', '\x201', + '\x202', '\x5', '\x83', '\x42', '\x2', '\x202', '\x203', '\x5', '\x83', + '\x42', '\x2', '\x203', '\x82', '\x3', '\x2', '\x2', '\x2', '\x204', '\x205', + '\t', '\x5', '\x2', '\x2', '\x205', '\x84', '\x3', '\x2', '\x2', '\x2', + '\x206', '\x207', '\n', '\x6', '\x2', '\x2', '\x207', '\x86', '\x3', '\x2', + '\x2', '\x2', '\x208', '\x209', '\n', '\a', '\x2', '\x2', '\x209', '\x88', + '\x3', '\x2', '\x2', '\x2', '\x20A', '\x214', '\x3', '\x2', '\x2', '\x2', + '\x20B', '\x210', '\t', '\b', '\x2', '\x2', '\x20C', '\x20F', '\t', '\b', + '\x2', '\x2', '\x20D', '\x20F', '\x5', '\x8D', 'G', '\x2', '\x20E', '\x20C', + '\x3', '\x2', '\x2', '\x2', '\x20E', '\x20D', '\x3', '\x2', '\x2', '\x2', + '\x20F', '\x212', '\x3', '\x2', '\x2', '\x2', '\x210', '\x20E', '\x3', + '\x2', '\x2', '\x2', '\x210', '\x211', '\x3', '\x2', '\x2', '\x2', '\x211', + '\x214', '\x3', '\x2', '\x2', '\x2', '\x212', '\x210', '\x3', '\x2', '\x2', + '\x2', '\x213', '\x20A', '\x3', '\x2', '\x2', '\x2', '\x213', '\x20B', + '\x3', '\x2', '\x2', '\x2', '\x214', '\x8A', '\x3', '\x2', '\x2', '\x2', + '\x215', '\x216', '\a', '\x42', '\x2', '\x2', '\x216', '\x217', '\x5', + '\x89', '\x45', '\x2', '\x217', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x218', + '\x219', '\t', '\t', '\x2', '\x2', '\x219', '\x8E', '\x3', '\x2', '\x2', + '\x2', '\x21A', '\x21B', '\t', '\n', '\x2', '\x2', '\x21B', '\x90', '\x3', + '\x2', '\x2', '\x2', '\x21C', '\x21D', '\t', '\v', '\x2', '\x2', '\x21D', + '\x92', '\x3', '\x2', '\x2', '\x2', '\x21E', '\x21F', '\t', '\f', '\x2', + '\x2', '\x21F', '\x94', '\x3', '\x2', '\x2', '\x2', '\x220', '\x221', + '\t', '\r', '\x2', '\x2', '\x221', '\x96', '\x3', '\x2', '\x2', '\x2', + '\x222', '\x223', '\t', '\xE', '\x2', '\x2', '\x223', '\x98', '\x3', '\x2', + '\x2', '\x2', '\x224', '\x225', '\t', '\xF', '\x2', '\x2', '\x225', '\x9A', + '\x3', '\x2', '\x2', '\x2', '\x226', '\x227', '\t', '\x10', '\x2', '\x2', + '\x227', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x228', '\x229', '\t', '\x11', + '\x2', '\x2', '\x229', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x22A', '\x22B', + '\t', '\x12', '\x2', '\x2', '\x22B', '\xA0', '\x3', '\x2', '\x2', '\x2', + '\x22C', '\x22D', '\t', '\x13', '\x2', '\x2', '\x22D', '\xA2', '\x3', + '\x2', '\x2', '\x2', '\x22E', '\x22F', '\t', '\x14', '\x2', '\x2', '\x22F', + '\xA4', '\x3', '\x2', '\x2', '\x2', '\x230', '\x231', '\t', '\x15', '\x2', + '\x2', '\x231', '\xA6', '\x3', '\x2', '\x2', '\x2', '\x232', '\x233', + '\t', '\x16', '\x2', '\x2', '\x233', '\xA8', '\x3', '\x2', '\x2', '\x2', + '\x234', '\x235', '\t', '\x17', '\x2', '\x2', '\x235', '\xAA', '\x3', + '\x2', '\x2', '\x2', '\x236', '\x237', '\t', '\x18', '\x2', '\x2', '\x237', + '\xAC', '\x3', '\x2', '\x2', '\x2', '\x238', '\x239', '\t', '\x19', '\x2', + '\x2', '\x239', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x23A', '\x23B', + '\t', '\x1A', '\x2', '\x2', '\x23B', '\xB0', '\x3', '\x2', '\x2', '\x2', + '\x23C', '\x23D', '\t', '\x1B', '\x2', '\x2', '\x23D', '\xB2', '\x3', + '\x2', '\x2', '\x2', '\x23E', '\x23F', '\t', '\x1C', '\x2', '\x2', '\x23F', + '\xB4', '\x3', '\x2', '\x2', '\x2', '\x240', '\x241', '\t', '\x1D', '\x2', + '\x2', '\x241', '\xB6', '\x3', '\x2', '\x2', '\x2', '\x242', '\x243', + '\t', '\x1E', '\x2', '\x2', '\x243', '\xB8', '\x3', '\x2', '\x2', '\x2', + '\x244', '\x245', '\t', '\x1F', '\x2', '\x2', '\x245', '\xBA', '\x3', + '\x2', '\x2', '\x2', '\x246', '\x247', '\t', ' ', '\x2', '\x2', '\x247', + '\xBC', '\x3', '\x2', '\x2', '\x2', '\x248', '\x249', '\t', '!', '\x2', + '\x2', '\x249', '\xBE', '\x3', '\x2', '\x2', '\x2', '\x24A', '\x24B', + '\t', '\"', '\x2', '\x2', '\x24B', '\xC0', '\x3', '\x2', '\x2', '\x2', + '\x24C', '\x24D', '\t', '#', '\x2', '\x2', '\x24D', '\xC2', '\x3', '\x2', + '\x2', '\x2', '\x1A', '\x2', '\x1AF', '\x1B4', '\x1B9', '\x1BF', '\x1C2', + '\x1C6', '\x1CB', '\x1CD', '\x1D0', '\x1D6', '\x1DA', '\x1DF', '\x1E1', + '\x1E3', '\x1E8', '\x1EA', '\x1F1', '\x1F3', '\x1F7', '\x1FC', '\x20E', + '\x210', '\x213', '\x3', '\b', '\x2', '\x2', }; public static readonly ATN _ATN = diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs index 5de50b9faa..53293f9382 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs @@ -38,12 +38,13 @@ public const int T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, - T__24=25, T__25=26, T__26=27, K_AND=28, K_ARRAY=29, K_AS=30, K_ASC=31, - K_BETWEEN=32, K_BY=33, K_DESC=34, K_DISTINCT=35, K_ESCAPE=36, K_EXISTS=37, - K_FALSE=38, K_FROM=39, K_GROUP=40, K_IN=41, K_JOIN=42, K_LIKE=43, K_LIMIT=44, - K_NOT=45, K_NULL=46, K_OFFSET=47, K_OR=48, K_ORDER=49, K_SELECT=50, K_TOP=51, - K_TRUE=52, K_UDF=53, K_UNDEFINED=54, K_VALUE=55, K_WHERE=56, WS=57, NUMERIC_LITERAL=58, - STRING_LITERAL=59, IDENTIFIER=60, PARAMETER=61; + T__24=25, T__25=26, T__26=27, K_ALL=28, K_AND=29, K_ARRAY=30, K_AS=31, + K_ASC=32, K_BETWEEN=33, K_BY=34, K_DESC=35, K_DISTINCT=36, K_ESCAPE=37, + K_EXISTS=38, K_FALSE=39, K_FROM=40, K_GROUP=41, K_IN=42, K_JOIN=43, K_LEFT=44, + K_LIKE=45, K_LIMIT=46, K_NOT=47, K_NULL=48, K_OFFSET=49, K_OR=50, K_ORDER=51, + K_RIGHT=52, K_SELECT=53, K_TOP=54, K_TRUE=55, K_UDF=56, K_UNDEFINED=57, + K_VALUE=58, K_WHERE=59, WS=60, NUMERIC_LITERAL=61, STRING_LITERAL=62, + LEX_IDENTIFIER=63, PARAMETER=64; public const int RULE_program = 0, RULE_sql_query = 1, RULE_select_clause = 2, RULE_top_spec = 3, RULE_selection = 4, RULE_select_star_spec = 5, RULE_select_value_spec = 6, @@ -58,8 +59,9 @@ public const int RULE_equality_operator = 31, RULE_bitwise_and_operator = 32, RULE_bitwise_exclusive_or_operator = 33, RULE_bitwise_inclusive_or_operator = 34, RULE_string_concat_operator = 35, RULE_unary_scalar_expression = 36, RULE_unary_operator = 37, RULE_primary_expression = 38, - RULE_scalar_expression_list = 39, RULE_object_property_list = 40, RULE_object_property = 41, - RULE_literal = 42; + RULE_function_call_scalar_expression = 39, RULE_scalar_expression_list = 40, + RULE_object_property_list = 41, RULE_object_property = 42, RULE_identifier = 43, + RULE_literal = 44; public static readonly string[] ruleNames = { "program", "sql_query", "select_clause", "top_spec", "selection", "select_star_spec", "select_value_spec", "select_list_spec", "select_item", "from_clause", @@ -70,27 +72,28 @@ public const int "escape_expression", "binary_scalar_expression", "multiplicative_operator", "additive_operator", "relational_operator", "equality_operator", "bitwise_and_operator", "bitwise_exclusive_or_operator", "bitwise_inclusive_or_operator", "string_concat_operator", - "unary_scalar_expression", "unary_operator", "primary_expression", "scalar_expression_list", - "object_property_list", "object_property", "literal" + "unary_scalar_expression", "unary_operator", "primary_expression", "function_call_scalar_expression", + "scalar_expression_list", "object_property_list", "object_property", "identifier", + "literal" }; private static readonly string[] _LiteralNames = { null, "'*'", "','", "'('", "')'", "'.'", "'['", "']'", "'?'", "':'", "'??'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'>='", "'<='", "'='", "'!='", "'&'", "'^'", "'|'", "'||'", "'~'", "'{'", "'}'", null, null, null, null, - null, null, null, null, null, null, "'false'", null, null, null, null, - null, null, null, "'null'", null, null, null, null, null, "'true'", "'udf'", - "'undefined'" + null, null, null, null, null, null, null, "'false'", null, null, null, + null, null, null, null, null, "'null'", null, null, null, null, null, + null, "'true'", "'udf'", "'undefined'" }; private static readonly string[] _SymbolicNames = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, - null, null, null, null, "K_AND", "K_ARRAY", "K_AS", "K_ASC", "K_BETWEEN", - "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", "K_FROM", - "K_GROUP", "K_IN", "K_JOIN", "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", "K_OFFSET", - "K_OR", "K_ORDER", "K_SELECT", "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", - "K_VALUE", "K_WHERE", "WS", "NUMERIC_LITERAL", "STRING_LITERAL", "IDENTIFIER", - "PARAMETER" + null, null, null, null, "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", + "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", + "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", + "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", + "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", + "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", "PARAMETER" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -123,7 +126,6 @@ public sqlParser(ITokenStream input, TextWriter output, TextWriter errorOutput) { Interpreter = new ParserATNSimulator(this, _ATN, decisionToDFA, sharedContextCache); } - public partial class ProgramContext : ParserRuleContext { public Sql_queryContext sql_query() { return GetRuleContext(0); @@ -156,8 +158,8 @@ public ProgramContext program() { try { EnterOuterAlt(_localctx, 1); { - State = 86; sql_query(); - State = 87; Match(Eof); + State = 90; sql_query(); + State = 91; Match(Eof); } } catch (RecognitionException re) { @@ -218,49 +220,49 @@ public Sql_queryContext sql_query() { try { EnterOuterAlt(_localctx, 1); { - State = 89; select_clause(); - State = 91; + State = 93; select_clause(); + State = 95; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_FROM) { { - State = 90; from_clause(); + State = 94; from_clause(); } } - State = 94; + State = 98; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_WHERE) { { - State = 93; where_clause(); + State = 97; where_clause(); } } - State = 97; + State = 101; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_GROUP) { { - State = 96; group_by_clause(); + State = 100; group_by_clause(); } } - State = 100; + State = 104; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_ORDER) { { - State = 99; order_by_clause(); + State = 103; order_by_clause(); } } - State = 103; + State = 107; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_OFFSET) { { - State = 102; offset_limit_clause(); + State = 106; offset_limit_clause(); } } @@ -314,26 +316,26 @@ public Select_clauseContext select_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 105; Match(K_SELECT); - State = 107; + State = 109; Match(K_SELECT); + State = 111; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_DISTINCT) { { - State = 106; Match(K_DISTINCT); + State = 110; Match(K_DISTINCT); } } - State = 110; + State = 114; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_TOP) { { - State = 109; top_spec(); + State = 113; top_spec(); } } - State = 112; selection(); + State = 116; selection(); } } catch (RecognitionException re) { @@ -379,8 +381,8 @@ public Top_specContext top_spec() { try { EnterOuterAlt(_localctx, 1); { - State = 114; Match(K_TOP); - State = 115; + State = 118; Match(K_TOP); + State = 119; _la = TokenStream.LA(1); if ( !(_la==NUMERIC_LITERAL || _la==PARAMETER) ) { ErrorHandler.RecoverInline(this); @@ -437,19 +439,19 @@ public SelectionContext selection() { SelectionContext _localctx = new SelectionContext(Context, State); EnterRule(_localctx, 8, RULE_selection); try { - State = 120; + State = 124; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case T__0: EnterOuterAlt(_localctx, 1); { - State = 117; select_star_spec(); + State = 121; select_star_spec(); } break; case K_VALUE: EnterOuterAlt(_localctx, 2); { - State = 118; select_value_spec(); + State = 122; select_value_spec(); } break; case T__2: @@ -458,21 +460,24 @@ public SelectionContext selection() { case T__13: case T__24: case T__25: + case K_ALL: case K_ARRAY: case K_EXISTS: case K_FALSE: + case K_LEFT: case K_NOT: case K_NULL: + case K_RIGHT: case K_TRUE: case K_UDF: case K_UNDEFINED: case NUMERIC_LITERAL: case STRING_LITERAL: - case IDENTIFIER: + case LEX_IDENTIFIER: case PARAMETER: EnterOuterAlt(_localctx, 3); { - State = 119; select_list_spec(); + State = 123; select_list_spec(); } break; default: @@ -518,7 +523,7 @@ public Select_star_specContext select_star_spec() { try { EnterOuterAlt(_localctx, 1); { - State = 122; Match(T__0); + State = 126; Match(T__0); } } catch (RecognitionException re) { @@ -564,8 +569,8 @@ public Select_value_specContext select_value_spec() { try { EnterOuterAlt(_localctx, 1); { - State = 124; Match(K_VALUE); - State = 125; scalar_expression(0); + State = 128; Match(K_VALUE); + State = 129; scalar_expression(0); } } catch (RecognitionException re) { @@ -614,18 +619,18 @@ public Select_list_specContext select_list_spec() { try { EnterOuterAlt(_localctx, 1); { - State = 127; select_item(); - State = 132; + State = 131; select_item(); + State = 136; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 128; Match(T__1); - State = 129; select_item(); + State = 132; Match(T__1); + State = 133; select_item(); } } - State = 134; + State = 138; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -647,7 +652,9 @@ public Scalar_expressionContext scalar_expression() { return GetRuleContext(0); } public ITerminalNode K_AS() { return GetToken(sqlParser.K_AS, 0); } - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public Select_itemContext(ParserRuleContext parent, int invokingState) : base(parent, invokingState) { @@ -676,14 +683,14 @@ public Select_itemContext select_item() { try { EnterOuterAlt(_localctx, 1); { - State = 135; scalar_expression(0); - State = 138; + State = 139; scalar_expression(0); + State = 142; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_AS) { { - State = 136; Match(K_AS); - State = 137; Match(IDENTIFIER); + State = 140; Match(K_AS); + State = 141; identifier(); } } @@ -732,8 +739,8 @@ public From_clauseContext from_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 140; Match(K_FROM); - State = 141; collection_expression(0); + State = 144; Match(K_FROM); + State = 145; collection_expression(0); } } catch (RecognitionException re) { @@ -786,7 +793,9 @@ public partial class AliasedCollectionExpressionContext : Collection_expressionC public CollectionContext collection() { return GetRuleContext(0); } - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public ITerminalNode K_AS() { return GetToken(sqlParser.K_AS, 0); } public AliasedCollectionExpressionContext(Collection_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { @@ -804,7 +813,9 @@ public override TResult Accept(IParseTreeVisitor visitor) { } } public partial class ArrayIteratorCollectionExpressionContext : Collection_expressionContext { - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public ITerminalNode K_IN() { return GetToken(sqlParser.K_IN, 0); } public CollectionContext collection() { return GetRuleContext(0); @@ -842,7 +853,7 @@ private Collection_expressionContext collection_expression(int _p) { int _alt; EnterOuterAlt(_localctx, 1); { - State = 154; + State = 159; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,12,Context) ) { case 1: @@ -851,22 +862,22 @@ private Collection_expressionContext collection_expression(int _p) { Context = _localctx; _prevctx = _localctx; - State = 144; collection(); - State = 149; + State = 148; collection(); + State = 153; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,11,Context) ) { case 1: { - State = 146; + State = 150; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_AS) { { - State = 145; Match(K_AS); + State = 149; Match(K_AS); } } - State = 148; Match(IDENTIFIER); + State = 152; identifier(); } break; } @@ -877,14 +888,14 @@ private Collection_expressionContext collection_expression(int _p) { _localctx = new ArrayIteratorCollectionExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 151; Match(IDENTIFIER); - State = 152; Match(K_IN); - State = 153; collection(); + State = 155; identifier(); + State = 156; Match(K_IN); + State = 157; collection(); } break; } Context.Stop = TokenStream.LT(-1); - State = 161; + State = 166; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,13,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -896,14 +907,14 @@ private Collection_expressionContext collection_expression(int _p) { { _localctx = new JoinCollectionExpressionContext(new Collection_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_collection_expression); - State = 156; + State = 161; if (!(Precpred(Context, 1))) throw new FailedPredicateException(this, "Precpred(Context, 1)"); - State = 157; Match(K_JOIN); - State = 158; collection_expression(2); + State = 162; Match(K_JOIN); + State = 163; collection_expression(2); } } } - State = 163; + State = 168; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,13,Context); } @@ -933,7 +944,9 @@ public virtual void CopyFrom(CollectionContext context) { } } public partial class InputPathCollectionContext : CollectionContext { - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public Path_expressionContext path_expression() { return GetRuleContext(0); } @@ -977,20 +990,21 @@ public CollectionContext collection() { CollectionContext _localctx = new CollectionContext(Context, State); EnterRule(_localctx, 22, RULE_collection); try { - State = 172; + State = 177; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { - case IDENTIFIER: + case K_ALL: + case LEX_IDENTIFIER: _localctx = new InputPathCollectionContext(_localctx); EnterOuterAlt(_localctx, 1); { - State = 164; Match(IDENTIFIER); - State = 166; + State = 169; identifier(); + State = 171; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,14,Context) ) { case 1: { - State = 165; path_expression(0); + State = 170; path_expression(0); } break; } @@ -1000,9 +1014,9 @@ public CollectionContext collection() { _localctx = new SubqueryCollectionContext(_localctx); EnterOuterAlt(_localctx, 2); { - State = 168; Match(T__2); - State = 169; sql_query(); - State = 170; Match(T__3); + State = 173; Match(T__2); + State = 174; sql_query(); + State = 175; Match(T__3); } break; default: @@ -1072,7 +1086,9 @@ public partial class IdentifierPathExpressionContext : Path_expressionContext { public Path_expressionContext path_expression() { return GetRuleContext(0); } - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public IdentifierPathExpressionContext(Path_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; @@ -1132,7 +1148,7 @@ private Path_expressionContext path_expression(int _p) { } Context.Stop = TokenStream.LT(-1); - State = 188; + State = 193; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,17,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -1141,45 +1157,45 @@ private Path_expressionContext path_expression(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 186; + State = 191; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,16,Context) ) { case 1: { _localctx = new IdentifierPathExpressionContext(new Path_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_path_expression); - State = 175; + State = 180; if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)"); - State = 176; Match(T__4); - State = 177; Match(IDENTIFIER); + State = 181; Match(T__4); + State = 182; identifier(); } break; case 2: { _localctx = new NumberPathExpressionContext(new Path_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_path_expression); - State = 178; + State = 183; if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)"); - State = 179; Match(T__5); - State = 180; Match(NUMERIC_LITERAL); - State = 181; Match(T__6); + State = 184; Match(T__5); + State = 185; Match(NUMERIC_LITERAL); + State = 186; Match(T__6); } break; case 3: { _localctx = new StringPathExpressionContext(new Path_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_path_expression); - State = 182; + State = 187; if (!(Precpred(Context, 2))) throw new FailedPredicateException(this, "Precpred(Context, 2)"); - State = 183; Match(T__5); - State = 184; Match(STRING_LITERAL); - State = 185; Match(T__6); + State = 188; Match(T__5); + State = 189; Match(STRING_LITERAL); + State = 190; Match(T__6); } break; } } } - State = 190; + State = 195; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,17,Context); } @@ -1228,8 +1244,8 @@ public Where_clauseContext where_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 191; Match(K_WHERE); - State = 192; scalar_expression(0); + State = 196; Match(K_WHERE); + State = 197; scalar_expression(0); } } catch (RecognitionException re) { @@ -1276,9 +1292,9 @@ public Group_by_clauseContext group_by_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 194; Match(K_GROUP); - State = 195; Match(K_BY); - State = 196; scalar_expression_list(); + State = 199; Match(K_GROUP); + State = 200; Match(K_BY); + State = 201; scalar_expression_list(); } } catch (RecognitionException re) { @@ -1325,9 +1341,9 @@ public Order_by_clauseContext order_by_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 198; Match(K_ORDER); - State = 199; Match(K_BY); - State = 200; order_by_items(); + State = 203; Match(K_ORDER); + State = 204; Match(K_BY); + State = 205; order_by_items(); } } catch (RecognitionException re) { @@ -1376,18 +1392,18 @@ public Order_by_itemsContext order_by_items() { try { EnterOuterAlt(_localctx, 1); { - State = 202; order_by_item(); - State = 207; + State = 207; order_by_item(); + State = 212; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 203; Match(T__1); - State = 204; order_by_item(); + State = 208; Match(T__1); + State = 209; order_by_item(); } } - State = 209; + State = 214; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -1439,13 +1455,13 @@ public Order_by_itemContext order_by_item() { try { EnterOuterAlt(_localctx, 1); { - State = 210; scalar_expression(0); - State = 212; + State = 215; scalar_expression(0); + State = 217; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_ASC || _la==K_DESC) { { - State = 211; sort_order(); + State = 216; sort_order(); } } @@ -1493,7 +1509,7 @@ public Sort_orderContext sort_order() { try { EnterOuterAlt(_localctx, 1); { - State = 214; + State = 219; _la = TokenStream.LA(1); if ( !(_la==K_ASC || _la==K_DESC) ) { ErrorHandler.RecoverInline(this); @@ -1551,10 +1567,10 @@ public Offset_limit_clauseContext offset_limit_clause() { try { EnterOuterAlt(_localctx, 1); { - State = 216; Match(K_OFFSET); - State = 217; offset_count(); - State = 218; Match(K_LIMIT); - State = 219; limit_count(); + State = 221; Match(K_OFFSET); + State = 222; offset_count(); + State = 223; Match(K_LIMIT); + State = 224; limit_count(); } } catch (RecognitionException re) { @@ -1599,7 +1615,7 @@ public Offset_countContext offset_count() { try { EnterOuterAlt(_localctx, 1); { - State = 221; + State = 226; _la = TokenStream.LA(1); if ( !(_la==NUMERIC_LITERAL || _la==PARAMETER) ) { ErrorHandler.RecoverInline(this); @@ -1652,7 +1668,7 @@ public Limit_countContext limit_count() { try { EnterOuterAlt(_localctx, 1); { - State = 223; + State = 228; _la = TokenStream.LA(1); if ( !(_la==NUMERIC_LITERAL || _la==PARAMETER) ) { ErrorHandler.RecoverInline(this); @@ -1792,7 +1808,7 @@ private Scalar_expressionContext scalar_expression(int _p) { int _alt; EnterOuterAlt(_localctx, 1); { - State = 236; + State = 241; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,21,Context) ) { case 1: @@ -1801,7 +1817,7 @@ private Scalar_expressionContext scalar_expression(int _p) { Context = _localctx; _prevctx = _localctx; - State = 226; logical_scalar_expression(0); + State = 231; logical_scalar_expression(0); } break; case 2: @@ -1809,25 +1825,25 @@ private Scalar_expressionContext scalar_expression(int _p) { _localctx = new BetweenScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 227; binary_scalar_expression(0); - State = 229; + State = 232; binary_scalar_expression(0); + State = 234; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_NOT) { { - State = 228; Match(K_NOT); + State = 233; Match(K_NOT); } } - State = 231; Match(K_BETWEEN); - State = 232; binary_scalar_expression(0); - State = 233; Match(K_AND); - State = 234; binary_scalar_expression(0); + State = 236; Match(K_BETWEEN); + State = 237; binary_scalar_expression(0); + State = 238; Match(K_AND); + State = 239; binary_scalar_expression(0); } break; } Context.Stop = TokenStream.LT(-1); - State = 249; + State = 254; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,23,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -1836,35 +1852,35 @@ private Scalar_expressionContext scalar_expression(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 247; + State = 252; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,22,Context) ) { case 1: { _localctx = new ConditionalScalarExpressionContext(new Scalar_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_scalar_expression); - State = 238; + State = 243; if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)"); - State = 239; Match(T__7); - State = 240; scalar_expression(0); - State = 241; Match(T__8); - State = 242; scalar_expression(5); + State = 244; Match(T__7); + State = 245; scalar_expression(0); + State = 246; Match(T__8); + State = 247; scalar_expression(5); } break; case 2: { _localctx = new CoalesceScalarExpressionContext(new Scalar_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_scalar_expression); - State = 244; + State = 249; if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)"); - State = 245; Match(T__9); - State = 246; scalar_expression(4); + State = 250; Match(T__9); + State = 251; scalar_expression(4); } break; } } } - State = 251; + State = 256; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,23,Context); } @@ -1935,27 +1951,27 @@ private Logical_scalar_expressionContext logical_scalar_expression(int _p) { int _alt; EnterOuterAlt(_localctx, 1); { - State = 256; + State = 261; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,24,Context) ) { case 1: { - State = 253; binary_scalar_expression(0); + State = 258; binary_scalar_expression(0); } break; case 2: { - State = 254; in_scalar_expression(); + State = 259; in_scalar_expression(); } break; case 3: { - State = 255; like_scalar_expression(); + State = 260; like_scalar_expression(); } break; } Context.Stop = TokenStream.LT(-1); - State = 266; + State = 271; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,26,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -1964,33 +1980,33 @@ private Logical_scalar_expressionContext logical_scalar_expression(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 264; + State = 269; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,25,Context) ) { case 1: { _localctx = new Logical_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_logical_scalar_expression); - State = 258; + State = 263; if (!(Precpred(Context, 2))) throw new FailedPredicateException(this, "Precpred(Context, 2)"); - State = 259; Match(K_AND); - State = 260; logical_scalar_expression(3); + State = 264; Match(K_AND); + State = 265; logical_scalar_expression(3); } break; case 2: { _localctx = new Logical_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_logical_scalar_expression); - State = 261; + State = 266; if (!(Precpred(Context, 1))) throw new FailedPredicateException(this, "Precpred(Context, 1)"); - State = 262; Match(K_OR); - State = 263; logical_scalar_expression(2); + State = 267; Match(K_OR); + State = 268; logical_scalar_expression(2); } break; } } } - State = 268; + State = 273; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,26,Context); } @@ -2044,20 +2060,20 @@ public In_scalar_expressionContext in_scalar_expression() { try { EnterOuterAlt(_localctx, 1); { - State = 269; binary_scalar_expression(0); - State = 271; + State = 274; binary_scalar_expression(0); + State = 276; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_NOT) { { - State = 270; Match(K_NOT); + State = 275; Match(K_NOT); } } - State = 273; Match(K_IN); - State = 274; Match(T__2); - State = 275; scalar_expression_list(); - State = 276; Match(T__3); + State = 278; Match(K_IN); + State = 279; Match(T__2); + State = 280; scalar_expression_list(); + State = 281; Match(T__3); } } catch (RecognitionException re) { @@ -2111,24 +2127,24 @@ public Like_scalar_expressionContext like_scalar_expression() { try { EnterOuterAlt(_localctx, 1); { - State = 278; binary_scalar_expression(0); - State = 280; + State = 283; binary_scalar_expression(0); + State = 285; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_NOT) { { - State = 279; Match(K_NOT); + State = 284; Match(K_NOT); } } - State = 282; Match(K_LIKE); - State = 283; binary_scalar_expression(0); - State = 285; + State = 287; Match(K_LIKE); + State = 288; binary_scalar_expression(0); + State = 290; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,29,Context) ) { case 1: { - State = 284; escape_expression(); + State = 289; escape_expression(); } break; } @@ -2175,8 +2191,8 @@ public Escape_expressionContext escape_expression() { try { EnterOuterAlt(_localctx, 1); { - State = 287; Match(K_ESCAPE); - State = 288; Match(STRING_LITERAL); + State = 292; Match(K_ESCAPE); + State = 293; Match(STRING_LITERAL); } } catch (RecognitionException re) { @@ -2261,10 +2277,10 @@ private Binary_scalar_expressionContext binary_scalar_expression(int _p) { EnterOuterAlt(_localctx, 1); { { - State = 291; unary_scalar_expression(); + State = 296; unary_scalar_expression(); } Context.Stop = TokenStream.LT(-1); - State = 327; + State = 332; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,31,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -2273,93 +2289,93 @@ private Binary_scalar_expressionContext binary_scalar_expression(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 325; + State = 330; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,30,Context) ) { case 1: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 293; + State = 298; if (!(Precpred(Context, 8))) throw new FailedPredicateException(this, "Precpred(Context, 8)"); - State = 294; multiplicative_operator(); - State = 295; binary_scalar_expression(9); + State = 299; multiplicative_operator(); + State = 300; binary_scalar_expression(9); } break; case 2: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 297; + State = 302; if (!(Precpred(Context, 7))) throw new FailedPredicateException(this, "Precpred(Context, 7)"); - State = 298; additive_operator(); - State = 299; binary_scalar_expression(8); + State = 303; additive_operator(); + State = 304; binary_scalar_expression(8); } break; case 3: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 301; + State = 306; if (!(Precpred(Context, 6))) throw new FailedPredicateException(this, "Precpred(Context, 6)"); - State = 302; relational_operator(); - State = 303; binary_scalar_expression(7); + State = 307; relational_operator(); + State = 308; binary_scalar_expression(7); } break; case 4: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 305; + State = 310; if (!(Precpred(Context, 5))) throw new FailedPredicateException(this, "Precpred(Context, 5)"); - State = 306; equality_operator(); - State = 307; binary_scalar_expression(6); + State = 311; equality_operator(); + State = 312; binary_scalar_expression(6); } break; case 5: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 309; + State = 314; if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)"); - State = 310; bitwise_and_operator(); - State = 311; binary_scalar_expression(5); + State = 315; bitwise_and_operator(); + State = 316; binary_scalar_expression(5); } break; case 6: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 313; + State = 318; if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)"); - State = 314; bitwise_exclusive_or_operator(); - State = 315; binary_scalar_expression(4); + State = 319; bitwise_exclusive_or_operator(); + State = 320; binary_scalar_expression(4); } break; case 7: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 317; + State = 322; if (!(Precpred(Context, 2))) throw new FailedPredicateException(this, "Precpred(Context, 2)"); - State = 318; bitwise_inclusive_or_operator(); - State = 319; binary_scalar_expression(3); + State = 323; bitwise_inclusive_or_operator(); + State = 324; binary_scalar_expression(3); } break; case 8: { _localctx = new Binary_scalar_expressionContext(_parentctx, _parentState); PushNewRecursionContext(_localctx, _startState, RULE_binary_scalar_expression); - State = 321; + State = 326; if (!(Precpred(Context, 1))) throw new FailedPredicateException(this, "Precpred(Context, 1)"); - State = 322; string_concat_operator(); - State = 323; binary_scalar_expression(2); + State = 327; string_concat_operator(); + State = 328; binary_scalar_expression(2); } break; } } } - State = 329; + State = 334; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,31,Context); } @@ -2405,7 +2421,7 @@ public Multiplicative_operatorContext multiplicative_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 330; + State = 335; _la = TokenStream.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__0) | (1L << T__10) | (1L << T__11))) != 0)) ) { ErrorHandler.RecoverInline(this); @@ -2456,7 +2472,7 @@ public Additive_operatorContext additive_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 332; + State = 337; _la = TokenStream.LA(1); if ( !(_la==T__12 || _la==T__13) ) { ErrorHandler.RecoverInline(this); @@ -2507,7 +2523,7 @@ public Relational_operatorContext relational_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 334; + State = 339; _la = TokenStream.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__14) | (1L << T__15) | (1L << T__16) | (1L << T__17))) != 0)) ) { ErrorHandler.RecoverInline(this); @@ -2558,7 +2574,7 @@ public Equality_operatorContext equality_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 336; + State = 341; _la = TokenStream.LA(1); if ( !(_la==T__18 || _la==T__19) ) { ErrorHandler.RecoverInline(this); @@ -2608,7 +2624,7 @@ public Bitwise_and_operatorContext bitwise_and_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 338; Match(T__20); + State = 343; Match(T__20); } } catch (RecognitionException re) { @@ -2650,7 +2666,7 @@ public Bitwise_exclusive_or_operatorContext bitwise_exclusive_or_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 340; Match(T__21); + State = 345; Match(T__21); } } catch (RecognitionException re) { @@ -2692,7 +2708,7 @@ public Bitwise_inclusive_or_operatorContext bitwise_inclusive_or_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 342; Match(T__22); + State = 347; Match(T__22); } } catch (RecognitionException re) { @@ -2734,7 +2750,7 @@ public String_concat_operatorContext string_concat_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 344; Match(T__23); + State = 349; Match(T__23); } } catch (RecognitionException re) { @@ -2783,26 +2799,29 @@ public Unary_scalar_expressionContext unary_scalar_expression() { Unary_scalar_expressionContext _localctx = new Unary_scalar_expressionContext(Context, State); EnterRule(_localctx, 72, RULE_unary_scalar_expression); try { - State = 350; + State = 355; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case T__2: case T__5: case T__25: + case K_ALL: case K_ARRAY: case K_EXISTS: case K_FALSE: + case K_LEFT: case K_NULL: + case K_RIGHT: case K_TRUE: case K_UDF: case K_UNDEFINED: case NUMERIC_LITERAL: case STRING_LITERAL: - case IDENTIFIER: + case LEX_IDENTIFIER: case PARAMETER: EnterOuterAlt(_localctx, 1); { - State = 346; primary_expression(0); + State = 351; primary_expression(0); } break; case T__12: @@ -2811,8 +2830,8 @@ public Unary_scalar_expressionContext unary_scalar_expression() { case K_NOT: EnterOuterAlt(_localctx, 2); { - State = 347; unary_operator(); - State = 348; unary_scalar_expression(); + State = 352; unary_operator(); + State = 353; unary_scalar_expression(); } break; default: @@ -2860,7 +2879,7 @@ public Unary_operatorContext unary_operator() { try { EnterOuterAlt(_localctx, 1); { - State = 352; + State = 357; _la = TokenStream.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__12) | (1L << T__13) | (1L << T__24) | (1L << K_NOT))) != 0)) ) { ErrorHandler.RecoverInline(this); @@ -2894,98 +2913,159 @@ public virtual void CopyFrom(Primary_expressionContext context) { base.CopyFrom(context); } } - public partial class SubqueryScalarExpressionContext : Primary_expressionContext { + public partial class AllScalarExpressionContext : Primary_expressionContext { + public ITerminalNode K_ALL() { return GetToken(sqlParser.K_ALL, 0); } public Sql_queryContext sql_query() { return GetRuleContext(0); } - public SubqueryScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public AllScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterSubqueryScalarExpression(this); + if (typedListener != null) typedListener.EnterAllScalarExpression(this); } public override void ExitRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitSubqueryScalarExpression(this); + if (typedListener != null) typedListener.ExitAllScalarExpression(this); } public override TResult Accept(IParseTreeVisitor visitor) { IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitSubqueryScalarExpression(this); + if (typedVisitor != null) return typedVisitor.VisitAllScalarExpression(this); else return visitor.VisitChildren(this); } } - public partial class PropertyRefScalarExpressionBaseContext : Primary_expressionContext { - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } - public PropertyRefScalarExpressionBaseContext(Primary_expressionContext context) { CopyFrom(context); } + public partial class LiteralScalarExpressionContext : Primary_expressionContext { + public LiteralContext literal() { + return GetRuleContext(0); + } + public LiteralScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterPropertyRefScalarExpressionBase(this); + if (typedListener != null) typedListener.EnterLiteralScalarExpression(this); } public override void ExitRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitPropertyRefScalarExpressionBase(this); + if (typedListener != null) typedListener.ExitLiteralScalarExpression(this); } public override TResult Accept(IParseTreeVisitor visitor) { IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitPropertyRefScalarExpressionBase(this); + if (typedVisitor != null) return typedVisitor.VisitLiteralScalarExpression(this); else return visitor.VisitChildren(this); } } - public partial class FunctionCallScalarExpressionContext : Primary_expressionContext { - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } - public ITerminalNode K_UDF() { return GetToken(sqlParser.K_UDF, 0); } + public partial class ObjectCreateScalarExpressionContext : Primary_expressionContext { + public Object_property_listContext object_property_list() { + return GetRuleContext(0); + } + public ObjectCreateScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterObjectCreateScalarExpression(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitObjectCreateScalarExpression(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitObjectCreateScalarExpression(this); + else return visitor.VisitChildren(this); + } + } + public partial class ArrayCreateScalarExpressionContext : Primary_expressionContext { public Scalar_expression_listContext scalar_expression_list() { return GetRuleContext(0); } - public FunctionCallScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public ArrayCreateScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterFunctionCallScalarExpression(this); + if (typedListener != null) typedListener.EnterArrayCreateScalarExpression(this); } public override void ExitRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitFunctionCallScalarExpression(this); + if (typedListener != null) typedListener.ExitArrayCreateScalarExpression(this); } public override TResult Accept(IParseTreeVisitor visitor) { IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitFunctionCallScalarExpression(this); + if (typedVisitor != null) return typedVisitor.VisitArrayCreateScalarExpression(this); else return visitor.VisitChildren(this); } } - public partial class LiteralScalarExpressionContext : Primary_expressionContext { - public LiteralContext literal() { - return GetRuleContext(0); + public partial class MemberIndexerScalarExpressionContext : Primary_expressionContext { + public Primary_expressionContext primary_expression() { + return GetRuleContext(0); } - public LiteralScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public Scalar_expressionContext scalar_expression() { + return GetRuleContext(0); + } + public MemberIndexerScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterLiteralScalarExpression(this); + if (typedListener != null) typedListener.EnterMemberIndexerScalarExpression(this); } public override void ExitRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitLiteralScalarExpression(this); + if (typedListener != null) typedListener.ExitMemberIndexerScalarExpression(this); } public override TResult Accept(IParseTreeVisitor visitor) { IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitLiteralScalarExpression(this); + if (typedVisitor != null) return typedVisitor.VisitMemberIndexerScalarExpression(this); else return visitor.VisitChildren(this); } } - public partial class ObjectCreateScalarExpressionContext : Primary_expressionContext { - public Object_property_listContext object_property_list() { - return GetRuleContext(0); + public partial class SubqueryScalarExpressionContext : Primary_expressionContext { + public Sql_queryContext sql_query() { + return GetRuleContext(0); } - public ObjectCreateScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public SubqueryScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterObjectCreateScalarExpression(this); + if (typedListener != null) typedListener.EnterSubqueryScalarExpression(this); } public override void ExitRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitObjectCreateScalarExpression(this); + if (typedListener != null) typedListener.ExitSubqueryScalarExpression(this); } public override TResult Accept(IParseTreeVisitor visitor) { IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitObjectCreateScalarExpression(this); + if (typedVisitor != null) return typedVisitor.VisitSubqueryScalarExpression(this); + else return visitor.VisitChildren(this); + } + } + public partial class PropertyRefScalarExpressionBaseContext : Primary_expressionContext { + public IdentifierContext identifier() { + return GetRuleContext(0); + } + public PropertyRefScalarExpressionBaseContext(Primary_expressionContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterPropertyRefScalarExpressionBase(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitPropertyRefScalarExpressionBase(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitPropertyRefScalarExpressionBase(this); + else return visitor.VisitChildren(this); + } + } + public partial class FunctionCallScalarExpressionContext : Primary_expressionContext { + public Function_call_scalar_expressionContext function_call_scalar_expression() { + return GetRuleContext(0); + } + public FunctionCallScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterFunctionCallScalarExpression(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitFunctionCallScalarExpression(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitFunctionCallScalarExpression(this); else return visitor.VisitChildren(this); } } @@ -3025,25 +3105,6 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } - public partial class ArrayCreateScalarExpressionContext : Primary_expressionContext { - public Scalar_expression_listContext scalar_expression_list() { - return GetRuleContext(0); - } - public ArrayCreateScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } - public override void EnterRule(IParseTreeListener listener) { - IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterArrayCreateScalarExpression(this); - } - public override void ExitRule(IParseTreeListener listener) { - IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitArrayCreateScalarExpression(this); - } - public override TResult Accept(IParseTreeVisitor visitor) { - IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitArrayCreateScalarExpression(this); - else return visitor.VisitChildren(this); - } - } public partial class ExistsScalarExpressionContext : Primary_expressionContext { public ITerminalNode K_EXISTS() { return GetToken(sqlParser.K_EXISTS, 0); } public Sql_queryContext sql_query() { @@ -3084,33 +3145,13 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } - public partial class MemberIndexerScalarExpressionContext : Primary_expressionContext { - public Primary_expressionContext primary_expression() { - return GetRuleContext(0); - } - public Scalar_expressionContext scalar_expression() { - return GetRuleContext(0); - } - public MemberIndexerScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } - public override void EnterRule(IParseTreeListener listener) { - IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.EnterMemberIndexerScalarExpression(this); - } - public override void ExitRule(IParseTreeListener listener) { - IsqlListener typedListener = listener as IsqlListener; - if (typedListener != null) typedListener.ExitMemberIndexerScalarExpression(this); - } - public override TResult Accept(IParseTreeVisitor visitor) { - IsqlVisitor typedVisitor = visitor as IsqlVisitor; - if (typedVisitor != null) return typedVisitor.VisitMemberIndexerScalarExpression(this); - else return visitor.VisitChildren(this); - } - } public partial class PropertyRefScalarExpressionRecursiveContext : Primary_expressionContext { public Primary_expressionContext primary_expression() { return GetRuleContext(0); } - public ITerminalNode IDENTIFIER() { return GetToken(sqlParser.IDENTIFIER, 0); } + public IdentifierContext identifier() { + return GetRuleContext(0); + } public PropertyRefScalarExpressionRecursiveContext(Primary_expressionContext context) { CopyFrom(context); } public override void EnterRule(IParseTreeListener listener) { IsqlListener typedListener = listener as IsqlListener; @@ -3144,16 +3185,16 @@ private Primary_expressionContext primary_expression(int _p) { int _alt; EnterOuterAlt(_localctx, 1); { - State = 396; + State = 397; ErrorHandler.Sync(this); - switch ( Interpreter.AdaptivePredict(TokenStream,37,Context) ) { + switch ( Interpreter.AdaptivePredict(TokenStream,35,Context) ) { case 1: { _localctx = new PropertyRefScalarExpressionBaseContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 355; Match(IDENTIFIER); + State = 360; identifier(); } break; case 2: @@ -3161,7 +3202,7 @@ private Primary_expressionContext primary_expression(int _p) { _localctx = new ParameterRefScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 356; Match(PARAMETER); + State = 361; Match(PARAMETER); } break; case 3: @@ -3169,7 +3210,7 @@ private Primary_expressionContext primary_expression(int _p) { _localctx = new LiteralScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 357; literal(); + State = 362; literal(); } break; case 4: @@ -3177,17 +3218,17 @@ private Primary_expressionContext primary_expression(int _p) { _localctx = new ArrayCreateScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 358; Match(T__5); - State = 360; + State = 363; Match(T__5); + State = 365; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__5) | (1L << T__12) | (1L << T__13) | (1L << T__24) | (1L << T__25) | (1L << K_ARRAY) | (1L << K_EXISTS) | (1L << K_FALSE) | (1L << K_NOT) | (1L << K_NULL) | (1L << K_TRUE) | (1L << K_UDF) | (1L << K_UNDEFINED) | (1L << NUMERIC_LITERAL) | (1L << STRING_LITERAL) | (1L << IDENTIFIER) | (1L << PARAMETER))) != 0)) { + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { { - State = 359; scalar_expression_list(); + State = 364; scalar_expression_list(); } } - State = 362; Match(T__6); + State = 367; Match(T__6); } break; case 5: @@ -3195,63 +3236,45 @@ private Primary_expressionContext primary_expression(int _p) { _localctx = new ObjectCreateScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 363; Match(T__25); - State = 365; + State = 368; Match(T__25); + State = 370; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==STRING_LITERAL) { { - State = 364; object_property_list(); + State = 369; object_property_list(); } } - State = 367; Match(T__26); + State = 372; Match(T__26); } break; case 6: { - _localctx = new FunctionCallScalarExpressionContext(_localctx); + _localctx = new ParenthesizedScalarExperessionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 370; - ErrorHandler.Sync(this); - _la = TokenStream.LA(1); - if (_la==K_UDF) { - { - State = 368; Match(K_UDF); - State = 369; Match(T__4); - } - } - - State = 372; Match(IDENTIFIER); State = 373; Match(T__2); - State = 375; - ErrorHandler.Sync(this); - _la = TokenStream.LA(1); - if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__2) | (1L << T__5) | (1L << T__12) | (1L << T__13) | (1L << T__24) | (1L << T__25) | (1L << K_ARRAY) | (1L << K_EXISTS) | (1L << K_FALSE) | (1L << K_NOT) | (1L << K_NULL) | (1L << K_TRUE) | (1L << K_UDF) | (1L << K_UNDEFINED) | (1L << NUMERIC_LITERAL) | (1L << STRING_LITERAL) | (1L << IDENTIFIER) | (1L << PARAMETER))) != 0)) { - { - State = 374; scalar_expression_list(); - } - } - - State = 377; Match(T__3); + State = 374; scalar_expression(0); + State = 375; Match(T__3); } break; case 7: { - _localctx = new ParenthesizedScalarExperessionContext(_localctx); + _localctx = new SubqueryScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 378; Match(T__2); - State = 379; scalar_expression(0); - State = 380; Match(T__3); + State = 377; Match(T__2); + State = 378; sql_query(); + State = 379; Match(T__3); } break; case 8: { - _localctx = new SubqueryScalarExpressionContext(_localctx); + _localctx = new ExistsScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; + State = 381; Match(K_EXISTS); State = 382; Match(T__2); State = 383; sql_query(); State = 384; Match(T__3); @@ -3259,10 +3282,10 @@ private Primary_expressionContext primary_expression(int _p) { break; case 9: { - _localctx = new ExistsScalarExpressionContext(_localctx); + _localctx = new ArrayScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 386; Match(K_EXISTS); + State = 386; Match(K_ARRAY); State = 387; Match(T__2); State = 388; sql_query(); State = 389; Match(T__3); @@ -3270,56 +3293,64 @@ private Primary_expressionContext primary_expression(int _p) { break; case 10: { - _localctx = new ArrayScalarExpressionContext(_localctx); + _localctx = new AllScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 391; Match(K_ARRAY); + State = 391; Match(K_ALL); State = 392; Match(T__2); State = 393; sql_query(); State = 394; Match(T__3); } break; + case 11: + { + _localctx = new FunctionCallScalarExpressionContext(_localctx); + Context = _localctx; + _prevctx = _localctx; + State = 396; function_call_scalar_expression(); + } + break; } Context.Stop = TokenStream.LT(-1); - State = 408; + State = 409; ErrorHandler.Sync(this); - _alt = Interpreter.AdaptivePredict(TokenStream,39,Context); + _alt = Interpreter.AdaptivePredict(TokenStream,37,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { if ( _alt==1 ) { if ( ParseListeners!=null ) TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 406; + State = 407; ErrorHandler.Sync(this); - switch ( Interpreter.AdaptivePredict(TokenStream,38,Context) ) { + switch ( Interpreter.AdaptivePredict(TokenStream,36,Context) ) { case 1: { _localctx = new PropertyRefScalarExpressionRecursiveContext(new Primary_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_primary_expression); - State = 398; - if (!(Precpred(Context, 4))) throw new FailedPredicateException(this, "Precpred(Context, 4)"); - State = 399; Match(T__4); - State = 400; Match(IDENTIFIER); + State = 399; + if (!(Precpred(Context, 6))) throw new FailedPredicateException(this, "Precpred(Context, 6)"); + State = 400; Match(T__4); + State = 401; identifier(); } break; case 2: { _localctx = new MemberIndexerScalarExpressionContext(new Primary_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_primary_expression); - State = 401; - if (!(Precpred(Context, 3))) throw new FailedPredicateException(this, "Precpred(Context, 3)"); - State = 402; Match(T__5); - State = 403; scalar_expression(0); - State = 404; Match(T__6); + State = 402; + if (!(Precpred(Context, 5))) throw new FailedPredicateException(this, "Precpred(Context, 5)"); + State = 403; Match(T__5); + State = 404; scalar_expression(0); + State = 405; Match(T__6); } break; } } } - State = 410; + State = 411; ErrorHandler.Sync(this); - _alt = Interpreter.AdaptivePredict(TokenStream,39,Context); + _alt = Interpreter.AdaptivePredict(TokenStream,37,Context); } } } @@ -3334,6 +3365,123 @@ private Primary_expressionContext primary_expression(int _p) { return _localctx; } + public partial class Function_call_scalar_expressionContext : ParserRuleContext { + public IdentifierContext identifier() { + return GetRuleContext(0); + } + public ITerminalNode K_UDF() { return GetToken(sqlParser.K_UDF, 0); } + public Scalar_expression_listContext scalar_expression_list() { + return GetRuleContext(0); + } + public ITerminalNode K_LEFT() { return GetToken(sqlParser.K_LEFT, 0); } + public ITerminalNode K_RIGHT() { return GetToken(sqlParser.K_RIGHT, 0); } + public Function_call_scalar_expressionContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_function_call_scalar_expression; } } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterFunction_call_scalar_expression(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitFunction_call_scalar_expression(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitFunction_call_scalar_expression(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public Function_call_scalar_expressionContext function_call_scalar_expression() { + Function_call_scalar_expressionContext _localctx = new Function_call_scalar_expressionContext(Context, State); + EnterRule(_localctx, 78, RULE_function_call_scalar_expression); + int _la; + try { + State = 435; + ErrorHandler.Sync(this); + switch (TokenStream.LA(1)) { + case K_ALL: + case K_UDF: + case LEX_IDENTIFIER: + EnterOuterAlt(_localctx, 1); + { + State = 414; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (_la==K_UDF) { + { + State = 412; Match(K_UDF); + State = 413; Match(T__4); + } + } + + State = 416; identifier(); + State = 417; Match(T__2); + State = 419; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + { + State = 418; scalar_expression_list(); + } + } + + State = 421; Match(T__3); + } + break; + case K_LEFT: + EnterOuterAlt(_localctx, 2); + { + State = 423; Match(K_LEFT); + State = 424; Match(T__2); + State = 426; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + { + State = 425; scalar_expression_list(); + } + } + + State = 428; Match(T__3); + } + break; + case K_RIGHT: + EnterOuterAlt(_localctx, 3); + { + State = 429; Match(K_RIGHT); + State = 430; Match(T__2); + State = 432; + ErrorHandler.Sync(this); + _la = TokenStream.LA(1); + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + { + State = 431; scalar_expression_list(); + } + } + + State = 434; Match(T__3); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + public partial class Scalar_expression_listContext : ParserRuleContext { public Scalar_expressionContext[] scalar_expression() { return GetRuleContexts(); @@ -3364,23 +3512,23 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public Scalar_expression_listContext scalar_expression_list() { Scalar_expression_listContext _localctx = new Scalar_expression_listContext(Context, State); - EnterRule(_localctx, 78, RULE_scalar_expression_list); + EnterRule(_localctx, 80, RULE_scalar_expression_list); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 411; scalar_expression(0); - State = 416; + State = 437; scalar_expression(0); + State = 442; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 412; Match(T__1); - State = 413; scalar_expression(0); + State = 438; Match(T__1); + State = 439; scalar_expression(0); } } - State = 418; + State = 444; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -3427,23 +3575,23 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public Object_property_listContext object_property_list() { Object_property_listContext _localctx = new Object_property_listContext(Context, State); - EnterRule(_localctx, 80, RULE_object_property_list); + EnterRule(_localctx, 82, RULE_object_property_list); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 419; object_property(); - State = 424; + State = 445; object_property(); + State = 450; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 420; Match(T__1); - State = 421; object_property(); + State = 446; Match(T__1); + State = 447; object_property(); } } - State = 426; + State = 452; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -3488,13 +3636,66 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public Object_propertyContext object_property() { Object_propertyContext _localctx = new Object_propertyContext(Context, State); - EnterRule(_localctx, 82, RULE_object_property); + EnterRule(_localctx, 84, RULE_object_property); try { EnterOuterAlt(_localctx, 1); { - State = 427; Match(STRING_LITERAL); - State = 428; Match(T__8); - State = 429; scalar_expression(0); + State = 453; Match(STRING_LITERAL); + State = 454; Match(T__8); + State = 455; scalar_expression(0); + } + } + catch (RecognitionException re) { + _localctx.exception = re; + ErrorHandler.ReportError(this, re); + ErrorHandler.Recover(this, re); + } + finally { + ExitRule(); + } + return _localctx; + } + + public partial class IdentifierContext : ParserRuleContext { + public ITerminalNode LEX_IDENTIFIER() { return GetToken(sqlParser.LEX_IDENTIFIER, 0); } + public ITerminalNode K_ALL() { return GetToken(sqlParser.K_ALL, 0); } + public IdentifierContext(ParserRuleContext parent, int invokingState) + : base(parent, invokingState) + { + } + public override int RuleIndex { get { return RULE_identifier; } } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterIdentifier(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitIdentifier(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitIdentifier(this); + else return visitor.VisitChildren(this); + } + } + + [RuleVersion(0)] + public IdentifierContext identifier() { + IdentifierContext _localctx = new IdentifierContext(Context, State); + EnterRule(_localctx, 86, RULE_identifier); + int _la; + try { + EnterOuterAlt(_localctx, 1); + { + State = 457; + _la = TokenStream.LA(1); + if ( !(_la==K_ALL || _la==LEX_IDENTIFIER) ) { + ErrorHandler.RecoverInline(this); + } + else { + ErrorHandler.ReportMatch(this); + Consume(); + } } } catch (RecognitionException re) { @@ -3538,12 +3739,12 @@ public override TResult Accept(IParseTreeVisitor visitor) { [RuleVersion(0)] public LiteralContext literal() { LiteralContext _localctx = new LiteralContext(Context, State); - EnterRule(_localctx, 84, RULE_literal); + EnterRule(_localctx, 88, RULE_literal); int _la; try { EnterOuterAlt(_localctx, 1); { - State = 431; + State = 459; _la = TokenStream.LA(1); if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << K_FALSE) | (1L << K_NULL) | (1L << K_TRUE) | (1L << K_UNDEFINED) | (1L << NUMERIC_LITERAL) | (1L << STRING_LITERAL))) != 0)) ) { ErrorHandler.RecoverInline(this); @@ -3619,15 +3820,15 @@ private bool binary_scalar_expression_sempred(Binary_scalar_expressionContext _l } private bool primary_expression_sempred(Primary_expressionContext _localctx, int predIndex) { switch (predIndex) { - case 16: return Precpred(Context, 4); - case 17: return Precpred(Context, 3); + case 16: return Precpred(Context, 6); + case 17: return Precpred(Context, 5); } return true; } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x3', '?', '\x1B4', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\x5964', '\x3', '\x42', '\x1D0', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v', @@ -3643,358 +3844,383 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int '#', '\t', '#', '\x4', '$', '\t', '$', '\x4', '%', '\t', '%', '\x4', '&', '\t', '&', '\x4', '\'', '\t', '\'', '\x4', '(', '\t', '(', '\x4', ')', '\t', ')', '\x4', '*', '\t', '*', '\x4', '+', '\t', '+', '\x4', ',', '\t', - ',', '\x3', '\x2', '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', - '\x5', '\x3', '^', '\n', '\x3', '\x3', '\x3', '\x5', '\x3', '\x61', '\n', - '\x3', '\x3', '\x3', '\x5', '\x3', '\x64', '\n', '\x3', '\x3', '\x3', - '\x5', '\x3', 'g', '\n', '\x3', '\x3', '\x3', '\x5', '\x3', 'j', '\n', - '\x3', '\x3', '\x4', '\x3', '\x4', '\x5', '\x4', 'n', '\n', '\x4', '\x3', - '\x4', '\x5', '\x4', 'q', '\n', '\x4', '\x3', '\x4', '\x3', '\x4', '\x3', - '\x5', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', - '\x6', '\x5', '\x6', '{', '\n', '\x6', '\x3', '\a', '\x3', '\a', '\x3', - '\b', '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\t', - '\a', '\t', '\x85', '\n', '\t', '\f', '\t', '\xE', '\t', '\x88', '\v', - '\t', '\x3', '\n', '\x3', '\n', '\x3', '\n', '\x5', '\n', '\x8D', '\n', - '\n', '\x3', '\v', '\x3', '\v', '\x3', '\v', '\x3', '\f', '\x3', '\f', - '\x3', '\f', '\x5', '\f', '\x95', '\n', '\f', '\x3', '\f', '\x5', '\f', - '\x98', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', - '\x9D', '\n', '\f', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\a', '\f', - '\xA2', '\n', '\f', '\f', '\f', '\xE', '\f', '\xA5', '\v', '\f', '\x3', - '\r', '\x3', '\r', '\x5', '\r', '\xA9', '\n', '\r', '\x3', '\r', '\x3', - '\r', '\x3', '\r', '\x3', '\r', '\x5', '\r', '\xAF', '\n', '\r', '\x3', + ',', '\x4', '-', '\t', '-', '\x4', '.', '\t', '.', '\x3', '\x2', '\x3', + '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x5', '\x3', '\x62', + '\n', '\x3', '\x3', '\x3', '\x5', '\x3', '\x65', '\n', '\x3', '\x3', '\x3', + '\x5', '\x3', 'h', '\n', '\x3', '\x3', '\x3', '\x5', '\x3', 'k', '\n', + '\x3', '\x3', '\x3', '\x5', '\x3', 'n', '\n', '\x3', '\x3', '\x4', '\x3', + '\x4', '\x5', '\x4', 'r', '\n', '\x4', '\x3', '\x4', '\x5', '\x4', 'u', + '\n', '\x4', '\x3', '\x4', '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', + '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\x6', '\x5', '\x6', '\x7F', + '\n', '\x6', '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', '\x3', + '\b', '\x3', '\t', '\x3', '\t', '\x3', '\t', '\a', '\t', '\x89', '\n', + '\t', '\f', '\t', '\xE', '\t', '\x8C', '\v', '\t', '\x3', '\n', '\x3', + '\n', '\x3', '\n', '\x5', '\n', '\x91', '\n', '\n', '\x3', '\v', '\x3', + '\v', '\x3', '\v', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', + '\x99', '\n', '\f', '\x3', '\f', '\x5', '\f', '\x9C', '\n', '\f', '\x3', + '\f', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\x5', '\f', '\xA2', '\n', + '\f', '\x3', '\f', '\x3', '\f', '\x3', '\f', '\a', '\f', '\xA7', '\n', + '\f', '\f', '\f', '\xE', '\f', '\xAA', '\v', '\f', '\x3', '\r', '\x3', + '\r', '\x5', '\r', '\xAE', '\n', '\r', '\x3', '\r', '\x3', '\r', '\x3', + '\r', '\x3', '\r', '\x5', '\r', '\xB4', '\n', '\r', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', '\xE', '\x3', - '\xE', '\x3', '\xE', '\a', '\xE', '\xBD', '\n', '\xE', '\f', '\xE', '\xE', - '\xE', '\xC0', '\v', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', - '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', - '\x3', '\x11', '\x3', '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', - '\x3', '\x12', '\a', '\x12', '\xD0', '\n', '\x12', '\f', '\x12', '\xE', - '\x12', '\xD3', '\v', '\x12', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', - '\xD7', '\n', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x15', '\x3', - '\x15', '\x3', '\x15', '\x3', '\x15', '\x3', '\x15', '\x3', '\x16', '\x3', - '\x16', '\x3', '\x17', '\x3', '\x17', '\x3', '\x18', '\x3', '\x18', '\x3', - '\x18', '\x3', '\x18', '\x5', '\x18', '\xE8', '\n', '\x18', '\x3', '\x18', - '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x5', '\x18', - '\xEF', '\n', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', + '\xE', '\a', '\xE', '\xC2', '\n', '\xE', '\f', '\xE', '\xE', '\xE', '\xC5', + '\v', '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\xF', '\x3', '\x10', + '\x3', '\x10', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', '\x3', '\x11', + '\x3', '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', + '\a', '\x12', '\xD5', '\n', '\x12', '\f', '\x12', '\xE', '\x12', '\xD8', + '\v', '\x12', '\x3', '\x13', '\x3', '\x13', '\x5', '\x13', '\xDC', '\n', + '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x15', '\x3', '\x15', '\x3', + '\x15', '\x3', '\x15', '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', + '\x17', '\x3', '\x17', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', + '\x18', '\x5', '\x18', '\xED', '\n', '\x18', '\x3', '\x18', '\x3', '\x18', + '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x5', '\x18', '\xF4', '\n', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', - '\x18', '\a', '\x18', '\xFA', '\n', '\x18', '\f', '\x18', '\xE', '\x18', - '\xFD', '\v', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', - '\x19', '\x5', '\x19', '\x103', '\n', '\x19', '\x3', '\x19', '\x3', '\x19', - '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\a', '\x19', - '\x10B', '\n', '\x19', '\f', '\x19', '\xE', '\x19', '\x10E', '\v', '\x19', - '\x3', '\x1A', '\x3', '\x1A', '\x5', '\x1A', '\x112', '\n', '\x1A', '\x3', - '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', - '\x1B', '\x3', '\x1B', '\x5', '\x1B', '\x11B', '\n', '\x1B', '\x3', '\x1B', - '\x3', '\x1B', '\x3', '\x1B', '\x5', '\x1B', '\x120', '\n', '\x1B', '\x3', - '\x1C', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', + '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\x3', '\x18', '\a', + '\x18', '\xFF', '\n', '\x18', '\f', '\x18', '\xE', '\x18', '\x102', '\v', + '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\x5', + '\x19', '\x108', '\n', '\x19', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', + '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', '\a', '\x19', '\x110', '\n', + '\x19', '\f', '\x19', '\xE', '\x19', '\x113', '\v', '\x19', '\x3', '\x1A', + '\x3', '\x1A', '\x5', '\x1A', '\x117', '\n', '\x1A', '\x3', '\x1A', '\x3', + '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1B', '\x3', + '\x1B', '\x5', '\x1B', '\x120', '\n', '\x1B', '\x3', '\x1B', '\x3', '\x1B', + '\x3', '\x1B', '\x5', '\x1B', '\x125', '\n', '\x1B', '\x3', '\x1C', '\x3', + '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', - '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\a', '\x1D', '\x148', '\n', '\x1D', - '\f', '\x1D', '\xE', '\x1D', '\x14B', '\v', '\x1D', '\x3', '\x1E', '\x3', - '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', '!', - '\x3', '!', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', '$', - '\x3', '$', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '&', - '\x3', '&', '\x5', '&', '\x161', '\n', '&', '\x3', '\'', '\x3', '\'', - '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', - '\x5', '(', '\x16B', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x5', - '(', '\x170', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x5', '(', - '\x175', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x5', '(', '\x17A', + '\x1D', '\x3', '\x1D', '\a', '\x1D', '\x14D', '\n', '\x1D', '\f', '\x1D', + '\xE', '\x1D', '\x150', '\v', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x3', + '\x1F', '\x3', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', '!', '\x3', '!', + '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', '$', '\x3', '$', + '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', + '\x5', '&', '\x166', '\n', '&', '\x3', '\'', '\x3', '\'', '\x3', '(', + '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x5', '(', + '\x170', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x5', '(', '\x175', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', - '\x3', '(', '\x3', '(', '\x5', '(', '\x18F', '\n', '(', '\x3', '(', '\x3', + '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', + '\x3', '(', '\x3', '(', '\x5', '(', '\x190', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', - '(', '\a', '(', '\x199', '\n', '(', '\f', '(', '\xE', '(', '\x19C', '\v', - '(', '\x3', ')', '\x3', ')', '\x3', ')', '\a', ')', '\x1A1', '\n', ')', - '\f', ')', '\xE', ')', '\x1A4', '\v', ')', '\x3', '*', '\x3', '*', '\x3', - '*', '\a', '*', '\x1A9', '\n', '*', '\f', '*', '\xE', '*', '\x1AC', '\v', - '*', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', - ',', '\x3', ',', '\x2', '\b', '\x16', '\x1A', '.', '\x30', '\x38', 'N', - '-', '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x14', + '(', '\a', '(', '\x19A', '\n', '(', '\f', '(', '\xE', '(', '\x19D', '\v', + '(', '\x3', ')', '\x3', ')', '\x5', ')', '\x1A1', '\n', ')', '\x3', ')', + '\x3', ')', '\x3', ')', '\x5', ')', '\x1A6', '\n', ')', '\x3', ')', '\x3', + ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x5', ')', '\x1AD', '\n', ')', + '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x5', ')', '\x1B3', '\n', + ')', '\x3', ')', '\x5', ')', '\x1B6', '\n', ')', '\x3', '*', '\x3', '*', + '\x3', '*', '\a', '*', '\x1BB', '\n', '*', '\f', '*', '\xE', '*', '\x1BE', + '\v', '*', '\x3', '+', '\x3', '+', '\x3', '+', '\a', '+', '\x1C3', '\n', + '+', '\f', '+', '\xE', '+', '\x1C6', '\v', '+', '\x3', ',', '\x3', ',', + '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', + '\x3', '.', '\x2', '\b', '\x16', '\x1A', '.', '\x30', '\x38', 'N', '/', + '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x14', '\x16', '\x18', '\x1A', '\x1C', '\x1E', ' ', '\"', '$', '&', '(', '*', ',', '.', '\x30', '\x32', '\x34', '\x36', '\x38', ':', '<', '>', '@', - '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', '\x2', - '\n', '\x4', '\x2', '<', '<', '?', '?', '\x4', '\x2', '!', '!', '$', '$', - '\x4', '\x2', '\x3', '\x3', '\r', '\xE', '\x3', '\x2', '\xF', '\x10', - '\x3', '\x2', '\x11', '\x14', '\x3', '\x2', '\x15', '\x16', '\x5', '\x2', - '\xF', '\x10', '\x1B', '\x1B', '/', '/', '\a', '\x2', '(', '(', '\x30', - '\x30', '\x36', '\x36', '\x38', '\x38', '<', '=', '\x2', '\x1C3', '\x2', - 'X', '\x3', '\x2', '\x2', '\x2', '\x4', '[', '\x3', '\x2', '\x2', '\x2', - '\x6', 'k', '\x3', '\x2', '\x2', '\x2', '\b', 't', '\x3', '\x2', '\x2', - '\x2', '\n', 'z', '\x3', '\x2', '\x2', '\x2', '\f', '|', '\x3', '\x2', - '\x2', '\x2', '\xE', '~', '\x3', '\x2', '\x2', '\x2', '\x10', '\x81', - '\x3', '\x2', '\x2', '\x2', '\x12', '\x89', '\x3', '\x2', '\x2', '\x2', - '\x14', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x16', '\x9C', '\x3', '\x2', - '\x2', '\x2', '\x18', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x1A', '\xB0', - '\x3', '\x2', '\x2', '\x2', '\x1C', '\xC1', '\x3', '\x2', '\x2', '\x2', - '\x1E', '\xC4', '\x3', '\x2', '\x2', '\x2', ' ', '\xC8', '\x3', '\x2', - '\x2', '\x2', '\"', '\xCC', '\x3', '\x2', '\x2', '\x2', '$', '\xD4', '\x3', - '\x2', '\x2', '\x2', '&', '\xD8', '\x3', '\x2', '\x2', '\x2', '(', '\xDA', - '\x3', '\x2', '\x2', '\x2', '*', '\xDF', '\x3', '\x2', '\x2', '\x2', ',', - '\xE1', '\x3', '\x2', '\x2', '\x2', '.', '\xEE', '\x3', '\x2', '\x2', - '\x2', '\x30', '\x102', '\x3', '\x2', '\x2', '\x2', '\x32', '\x10F', '\x3', - '\x2', '\x2', '\x2', '\x34', '\x118', '\x3', '\x2', '\x2', '\x2', '\x36', - '\x121', '\x3', '\x2', '\x2', '\x2', '\x38', '\x124', '\x3', '\x2', '\x2', - '\x2', ':', '\x14C', '\x3', '\x2', '\x2', '\x2', '<', '\x14E', '\x3', - '\x2', '\x2', '\x2', '>', '\x150', '\x3', '\x2', '\x2', '\x2', '@', '\x152', - '\x3', '\x2', '\x2', '\x2', '\x42', '\x154', '\x3', '\x2', '\x2', '\x2', - '\x44', '\x156', '\x3', '\x2', '\x2', '\x2', '\x46', '\x158', '\x3', '\x2', - '\x2', '\x2', 'H', '\x15A', '\x3', '\x2', '\x2', '\x2', 'J', '\x160', - '\x3', '\x2', '\x2', '\x2', 'L', '\x162', '\x3', '\x2', '\x2', '\x2', - 'N', '\x18E', '\x3', '\x2', '\x2', '\x2', 'P', '\x19D', '\x3', '\x2', - '\x2', '\x2', 'R', '\x1A5', '\x3', '\x2', '\x2', '\x2', 'T', '\x1AD', - '\x3', '\x2', '\x2', '\x2', 'V', '\x1B1', '\x3', '\x2', '\x2', '\x2', - 'X', 'Y', '\x5', '\x4', '\x3', '\x2', 'Y', 'Z', '\a', '\x2', '\x2', '\x3', - 'Z', '\x3', '\x3', '\x2', '\x2', '\x2', '[', ']', '\x5', '\x6', '\x4', - '\x2', '\\', '^', '\x5', '\x14', '\v', '\x2', ']', '\\', '\x3', '\x2', - '\x2', '\x2', ']', '^', '\x3', '\x2', '\x2', '\x2', '^', '`', '\x3', '\x2', - '\x2', '\x2', '_', '\x61', '\x5', '\x1C', '\xF', '\x2', '`', '_', '\x3', - '\x2', '\x2', '\x2', '`', '\x61', '\x3', '\x2', '\x2', '\x2', '\x61', - '\x63', '\x3', '\x2', '\x2', '\x2', '\x62', '\x64', '\x5', '\x1E', '\x10', - '\x2', '\x63', '\x62', '\x3', '\x2', '\x2', '\x2', '\x63', '\x64', '\x3', - '\x2', '\x2', '\x2', '\x64', '\x66', '\x3', '\x2', '\x2', '\x2', '\x65', - 'g', '\x5', ' ', '\x11', '\x2', '\x66', '\x65', '\x3', '\x2', '\x2', '\x2', - '\x66', 'g', '\x3', '\x2', '\x2', '\x2', 'g', 'i', '\x3', '\x2', '\x2', - '\x2', 'h', 'j', '\x5', '(', '\x15', '\x2', 'i', 'h', '\x3', '\x2', '\x2', - '\x2', 'i', 'j', '\x3', '\x2', '\x2', '\x2', 'j', '\x5', '\x3', '\x2', - '\x2', '\x2', 'k', 'm', '\a', '\x34', '\x2', '\x2', 'l', 'n', '\a', '%', - '\x2', '\x2', 'm', 'l', '\x3', '\x2', '\x2', '\x2', 'm', 'n', '\x3', '\x2', - '\x2', '\x2', 'n', 'p', '\x3', '\x2', '\x2', '\x2', 'o', 'q', '\x5', '\b', - '\x5', '\x2', 'p', 'o', '\x3', '\x2', '\x2', '\x2', 'p', 'q', '\x3', '\x2', - '\x2', '\x2', 'q', 'r', '\x3', '\x2', '\x2', '\x2', 'r', 's', '\x5', '\n', - '\x6', '\x2', 's', '\a', '\x3', '\x2', '\x2', '\x2', 't', 'u', '\a', '\x35', - '\x2', '\x2', 'u', 'v', '\t', '\x2', '\x2', '\x2', 'v', '\t', '\x3', '\x2', - '\x2', '\x2', 'w', '{', '\x5', '\f', '\a', '\x2', 'x', '{', '\x5', '\xE', - '\b', '\x2', 'y', '{', '\x5', '\x10', '\t', '\x2', 'z', 'w', '\x3', '\x2', - '\x2', '\x2', 'z', 'x', '\x3', '\x2', '\x2', '\x2', 'z', 'y', '\x3', '\x2', - '\x2', '\x2', '{', '\v', '\x3', '\x2', '\x2', '\x2', '|', '}', '\a', '\x3', - '\x2', '\x2', '}', '\r', '\x3', '\x2', '\x2', '\x2', '~', '\x7F', '\a', - '\x39', '\x2', '\x2', '\x7F', '\x80', '\x5', '.', '\x18', '\x2', '\x80', - '\xF', '\x3', '\x2', '\x2', '\x2', '\x81', '\x86', '\x5', '\x12', '\n', - '\x2', '\x82', '\x83', '\a', '\x4', '\x2', '\x2', '\x83', '\x85', '\x5', - '\x12', '\n', '\x2', '\x84', '\x82', '\x3', '\x2', '\x2', '\x2', '\x85', - '\x88', '\x3', '\x2', '\x2', '\x2', '\x86', '\x84', '\x3', '\x2', '\x2', - '\x2', '\x86', '\x87', '\x3', '\x2', '\x2', '\x2', '\x87', '\x11', '\x3', - '\x2', '\x2', '\x2', '\x88', '\x86', '\x3', '\x2', '\x2', '\x2', '\x89', - '\x8C', '\x5', '.', '\x18', '\x2', '\x8A', '\x8B', '\a', ' ', '\x2', '\x2', - '\x8B', '\x8D', '\a', '>', '\x2', '\x2', '\x8C', '\x8A', '\x3', '\x2', - '\x2', '\x2', '\x8C', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x8D', '\x13', - '\x3', '\x2', '\x2', '\x2', '\x8E', '\x8F', '\a', ')', '\x2', '\x2', '\x8F', - '\x90', '\x5', '\x16', '\f', '\x2', '\x90', '\x15', '\x3', '\x2', '\x2', - '\x2', '\x91', '\x92', '\b', '\f', '\x1', '\x2', '\x92', '\x97', '\x5', - '\x18', '\r', '\x2', '\x93', '\x95', '\a', ' ', '\x2', '\x2', '\x94', - '\x93', '\x3', '\x2', '\x2', '\x2', '\x94', '\x95', '\x3', '\x2', '\x2', - '\x2', '\x95', '\x96', '\x3', '\x2', '\x2', '\x2', '\x96', '\x98', '\a', - '>', '\x2', '\x2', '\x97', '\x94', '\x3', '\x2', '\x2', '\x2', '\x97', - '\x98', '\x3', '\x2', '\x2', '\x2', '\x98', '\x9D', '\x3', '\x2', '\x2', - '\x2', '\x99', '\x9A', '\a', '>', '\x2', '\x2', '\x9A', '\x9B', '\a', - '+', '\x2', '\x2', '\x9B', '\x9D', '\x5', '\x18', '\r', '\x2', '\x9C', - '\x91', '\x3', '\x2', '\x2', '\x2', '\x9C', '\x99', '\x3', '\x2', '\x2', - '\x2', '\x9D', '\xA3', '\x3', '\x2', '\x2', '\x2', '\x9E', '\x9F', '\f', - '\x3', '\x2', '\x2', '\x9F', '\xA0', '\a', ',', '\x2', '\x2', '\xA0', - '\xA2', '\x5', '\x16', '\f', '\x4', '\xA1', '\x9E', '\x3', '\x2', '\x2', - '\x2', '\xA2', '\xA5', '\x3', '\x2', '\x2', '\x2', '\xA3', '\xA1', '\x3', - '\x2', '\x2', '\x2', '\xA3', '\xA4', '\x3', '\x2', '\x2', '\x2', '\xA4', - '\x17', '\x3', '\x2', '\x2', '\x2', '\xA5', '\xA3', '\x3', '\x2', '\x2', - '\x2', '\xA6', '\xA8', '\a', '>', '\x2', '\x2', '\xA7', '\xA9', '\x5', - '\x1A', '\xE', '\x2', '\xA8', '\xA7', '\x3', '\x2', '\x2', '\x2', '\xA8', - '\xA9', '\x3', '\x2', '\x2', '\x2', '\xA9', '\xAF', '\x3', '\x2', '\x2', - '\x2', '\xAA', '\xAB', '\a', '\x5', '\x2', '\x2', '\xAB', '\xAC', '\x5', - '\x4', '\x3', '\x2', '\xAC', '\xAD', '\a', '\x6', '\x2', '\x2', '\xAD', - '\xAF', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xA6', '\x3', '\x2', '\x2', - '\x2', '\xAE', '\xAA', '\x3', '\x2', '\x2', '\x2', '\xAF', '\x19', '\x3', - '\x2', '\x2', '\x2', '\xB0', '\xBE', '\b', '\xE', '\x1', '\x2', '\xB1', - '\xB2', '\f', '\x6', '\x2', '\x2', '\xB2', '\xB3', '\a', '\a', '\x2', - '\x2', '\xB3', '\xBD', '\a', '>', '\x2', '\x2', '\xB4', '\xB5', '\f', - '\x5', '\x2', '\x2', '\xB5', '\xB6', '\a', '\b', '\x2', '\x2', '\xB6', - '\xB7', '\a', '<', '\x2', '\x2', '\xB7', '\xBD', '\a', '\t', '\x2', '\x2', - '\xB8', '\xB9', '\f', '\x4', '\x2', '\x2', '\xB9', '\xBA', '\a', '\b', - '\x2', '\x2', '\xBA', '\xBB', '\a', '=', '\x2', '\x2', '\xBB', '\xBD', - '\a', '\t', '\x2', '\x2', '\xBC', '\xB1', '\x3', '\x2', '\x2', '\x2', - '\xBC', '\xB4', '\x3', '\x2', '\x2', '\x2', '\xBC', '\xB8', '\x3', '\x2', - '\x2', '\x2', '\xBD', '\xC0', '\x3', '\x2', '\x2', '\x2', '\xBE', '\xBC', - '\x3', '\x2', '\x2', '\x2', '\xBE', '\xBF', '\x3', '\x2', '\x2', '\x2', - '\xBF', '\x1B', '\x3', '\x2', '\x2', '\x2', '\xC0', '\xBE', '\x3', '\x2', - '\x2', '\x2', '\xC1', '\xC2', '\a', ':', '\x2', '\x2', '\xC2', '\xC3', - '\x5', '.', '\x18', '\x2', '\xC3', '\x1D', '\x3', '\x2', '\x2', '\x2', - '\xC4', '\xC5', '\a', '*', '\x2', '\x2', '\xC5', '\xC6', '\a', '#', '\x2', - '\x2', '\xC6', '\xC7', '\x5', 'P', ')', '\x2', '\xC7', '\x1F', '\x3', - '\x2', '\x2', '\x2', '\xC8', '\xC9', '\a', '\x33', '\x2', '\x2', '\xC9', - '\xCA', '\a', '#', '\x2', '\x2', '\xCA', '\xCB', '\x5', '\"', '\x12', - '\x2', '\xCB', '!', '\x3', '\x2', '\x2', '\x2', '\xCC', '\xD1', '\x5', - '$', '\x13', '\x2', '\xCD', '\xCE', '\a', '\x4', '\x2', '\x2', '\xCE', - '\xD0', '\x5', '$', '\x13', '\x2', '\xCF', '\xCD', '\x3', '\x2', '\x2', - '\x2', '\xD0', '\xD3', '\x3', '\x2', '\x2', '\x2', '\xD1', '\xCF', '\x3', - '\x2', '\x2', '\x2', '\xD1', '\xD2', '\x3', '\x2', '\x2', '\x2', '\xD2', - '#', '\x3', '\x2', '\x2', '\x2', '\xD3', '\xD1', '\x3', '\x2', '\x2', - '\x2', '\xD4', '\xD6', '\x5', '.', '\x18', '\x2', '\xD5', '\xD7', '\x5', - '&', '\x14', '\x2', '\xD6', '\xD5', '\x3', '\x2', '\x2', '\x2', '\xD6', - '\xD7', '\x3', '\x2', '\x2', '\x2', '\xD7', '%', '\x3', '\x2', '\x2', - '\x2', '\xD8', '\xD9', '\t', '\x3', '\x2', '\x2', '\xD9', '\'', '\x3', - '\x2', '\x2', '\x2', '\xDA', '\xDB', '\a', '\x31', '\x2', '\x2', '\xDB', - '\xDC', '\x5', '*', '\x16', '\x2', '\xDC', '\xDD', '\a', '.', '\x2', '\x2', - '\xDD', '\xDE', '\x5', ',', '\x17', '\x2', '\xDE', ')', '\x3', '\x2', - '\x2', '\x2', '\xDF', '\xE0', '\t', '\x2', '\x2', '\x2', '\xE0', '+', - '\x3', '\x2', '\x2', '\x2', '\xE1', '\xE2', '\t', '\x2', '\x2', '\x2', - '\xE2', '-', '\x3', '\x2', '\x2', '\x2', '\xE3', '\xE4', '\b', '\x18', - '\x1', '\x2', '\xE4', '\xEF', '\x5', '\x30', '\x19', '\x2', '\xE5', '\xE7', - '\x5', '\x38', '\x1D', '\x2', '\xE6', '\xE8', '\a', '/', '\x2', '\x2', - '\xE7', '\xE6', '\x3', '\x2', '\x2', '\x2', '\xE7', '\xE8', '\x3', '\x2', - '\x2', '\x2', '\xE8', '\xE9', '\x3', '\x2', '\x2', '\x2', '\xE9', '\xEA', - '\a', '\"', '\x2', '\x2', '\xEA', '\xEB', '\x5', '\x38', '\x1D', '\x2', - '\xEB', '\xEC', '\a', '\x1E', '\x2', '\x2', '\xEC', '\xED', '\x5', '\x38', - '\x1D', '\x2', '\xED', '\xEF', '\x3', '\x2', '\x2', '\x2', '\xEE', '\xE3', - '\x3', '\x2', '\x2', '\x2', '\xEE', '\xE5', '\x3', '\x2', '\x2', '\x2', - '\xEF', '\xFB', '\x3', '\x2', '\x2', '\x2', '\xF0', '\xF1', '\f', '\x6', - '\x2', '\x2', '\xF1', '\xF2', '\a', '\n', '\x2', '\x2', '\xF2', '\xF3', - '\x5', '.', '\x18', '\x2', '\xF3', '\xF4', '\a', '\v', '\x2', '\x2', '\xF4', - '\xF5', '\x5', '.', '\x18', '\a', '\xF5', '\xFA', '\x3', '\x2', '\x2', - '\x2', '\xF6', '\xF7', '\f', '\x5', '\x2', '\x2', '\xF7', '\xF8', '\a', - '\f', '\x2', '\x2', '\xF8', '\xFA', '\x5', '.', '\x18', '\x6', '\xF9', - '\xF0', '\x3', '\x2', '\x2', '\x2', '\xF9', '\xF6', '\x3', '\x2', '\x2', - '\x2', '\xFA', '\xFD', '\x3', '\x2', '\x2', '\x2', '\xFB', '\xF9', '\x3', - '\x2', '\x2', '\x2', '\xFB', '\xFC', '\x3', '\x2', '\x2', '\x2', '\xFC', - '/', '\x3', '\x2', '\x2', '\x2', '\xFD', '\xFB', '\x3', '\x2', '\x2', - '\x2', '\xFE', '\xFF', '\b', '\x19', '\x1', '\x2', '\xFF', '\x103', '\x5', - '\x38', '\x1D', '\x2', '\x100', '\x103', '\x5', '\x32', '\x1A', '\x2', - '\x101', '\x103', '\x5', '\x34', '\x1B', '\x2', '\x102', '\xFE', '\x3', - '\x2', '\x2', '\x2', '\x102', '\x100', '\x3', '\x2', '\x2', '\x2', '\x102', - '\x101', '\x3', '\x2', '\x2', '\x2', '\x103', '\x10C', '\x3', '\x2', '\x2', - '\x2', '\x104', '\x105', '\f', '\x4', '\x2', '\x2', '\x105', '\x106', - '\a', '\x1E', '\x2', '\x2', '\x106', '\x10B', '\x5', '\x30', '\x19', '\x5', - '\x107', '\x108', '\f', '\x3', '\x2', '\x2', '\x108', '\x109', '\a', '\x32', - '\x2', '\x2', '\x109', '\x10B', '\x5', '\x30', '\x19', '\x4', '\x10A', - '\x104', '\x3', '\x2', '\x2', '\x2', '\x10A', '\x107', '\x3', '\x2', '\x2', - '\x2', '\x10B', '\x10E', '\x3', '\x2', '\x2', '\x2', '\x10C', '\x10A', - '\x3', '\x2', '\x2', '\x2', '\x10C', '\x10D', '\x3', '\x2', '\x2', '\x2', - '\x10D', '\x31', '\x3', '\x2', '\x2', '\x2', '\x10E', '\x10C', '\x3', - '\x2', '\x2', '\x2', '\x10F', '\x111', '\x5', '\x38', '\x1D', '\x2', '\x110', - '\x112', '\a', '/', '\x2', '\x2', '\x111', '\x110', '\x3', '\x2', '\x2', - '\x2', '\x111', '\x112', '\x3', '\x2', '\x2', '\x2', '\x112', '\x113', - '\x3', '\x2', '\x2', '\x2', '\x113', '\x114', '\a', '+', '\x2', '\x2', - '\x114', '\x115', '\a', '\x5', '\x2', '\x2', '\x115', '\x116', '\x5', - 'P', ')', '\x2', '\x116', '\x117', '\a', '\x6', '\x2', '\x2', '\x117', - '\x33', '\x3', '\x2', '\x2', '\x2', '\x118', '\x11A', '\x5', '\x38', '\x1D', - '\x2', '\x119', '\x11B', '\a', '/', '\x2', '\x2', '\x11A', '\x119', '\x3', - '\x2', '\x2', '\x2', '\x11A', '\x11B', '\x3', '\x2', '\x2', '\x2', '\x11B', - '\x11C', '\x3', '\x2', '\x2', '\x2', '\x11C', '\x11D', '\a', '-', '\x2', - '\x2', '\x11D', '\x11F', '\x5', '\x38', '\x1D', '\x2', '\x11E', '\x120', - '\x5', '\x36', '\x1C', '\x2', '\x11F', '\x11E', '\x3', '\x2', '\x2', '\x2', - '\x11F', '\x120', '\x3', '\x2', '\x2', '\x2', '\x120', '\x35', '\x3', - '\x2', '\x2', '\x2', '\x121', '\x122', '\a', '&', '\x2', '\x2', '\x122', - '\x123', '\a', '=', '\x2', '\x2', '\x123', '\x37', '\x3', '\x2', '\x2', - '\x2', '\x124', '\x125', '\b', '\x1D', '\x1', '\x2', '\x125', '\x126', - '\x5', 'J', '&', '\x2', '\x126', '\x149', '\x3', '\x2', '\x2', '\x2', - '\x127', '\x128', '\f', '\n', '\x2', '\x2', '\x128', '\x129', '\x5', ':', - '\x1E', '\x2', '\x129', '\x12A', '\x5', '\x38', '\x1D', '\v', '\x12A', - '\x148', '\x3', '\x2', '\x2', '\x2', '\x12B', '\x12C', '\f', '\t', '\x2', - '\x2', '\x12C', '\x12D', '\x5', '<', '\x1F', '\x2', '\x12D', '\x12E', - '\x5', '\x38', '\x1D', '\n', '\x12E', '\x148', '\x3', '\x2', '\x2', '\x2', - '\x12F', '\x130', '\f', '\b', '\x2', '\x2', '\x130', '\x131', '\x5', '>', - ' ', '\x2', '\x131', '\x132', '\x5', '\x38', '\x1D', '\t', '\x132', '\x148', - '\x3', '\x2', '\x2', '\x2', '\x133', '\x134', '\f', '\a', '\x2', '\x2', - '\x134', '\x135', '\x5', '@', '!', '\x2', '\x135', '\x136', '\x5', '\x38', - '\x1D', '\b', '\x136', '\x148', '\x3', '\x2', '\x2', '\x2', '\x137', '\x138', - '\f', '\x6', '\x2', '\x2', '\x138', '\x139', '\x5', '\x42', '\"', '\x2', - '\x139', '\x13A', '\x5', '\x38', '\x1D', '\a', '\x13A', '\x148', '\x3', - '\x2', '\x2', '\x2', '\x13B', '\x13C', '\f', '\x5', '\x2', '\x2', '\x13C', - '\x13D', '\x5', '\x44', '#', '\x2', '\x13D', '\x13E', '\x5', '\x38', '\x1D', - '\x6', '\x13E', '\x148', '\x3', '\x2', '\x2', '\x2', '\x13F', '\x140', - '\f', '\x4', '\x2', '\x2', '\x140', '\x141', '\x5', '\x46', '$', '\x2', - '\x141', '\x142', '\x5', '\x38', '\x1D', '\x5', '\x142', '\x148', '\x3', - '\x2', '\x2', '\x2', '\x143', '\x144', '\f', '\x3', '\x2', '\x2', '\x144', - '\x145', '\x5', 'H', '%', '\x2', '\x145', '\x146', '\x5', '\x38', '\x1D', - '\x4', '\x146', '\x148', '\x3', '\x2', '\x2', '\x2', '\x147', '\x127', - '\x3', '\x2', '\x2', '\x2', '\x147', '\x12B', '\x3', '\x2', '\x2', '\x2', - '\x147', '\x12F', '\x3', '\x2', '\x2', '\x2', '\x147', '\x133', '\x3', - '\x2', '\x2', '\x2', '\x147', '\x137', '\x3', '\x2', '\x2', '\x2', '\x147', - '\x13B', '\x3', '\x2', '\x2', '\x2', '\x147', '\x13F', '\x3', '\x2', '\x2', - '\x2', '\x147', '\x143', '\x3', '\x2', '\x2', '\x2', '\x148', '\x14B', - '\x3', '\x2', '\x2', '\x2', '\x149', '\x147', '\x3', '\x2', '\x2', '\x2', - '\x149', '\x14A', '\x3', '\x2', '\x2', '\x2', '\x14A', '\x39', '\x3', - '\x2', '\x2', '\x2', '\x14B', '\x149', '\x3', '\x2', '\x2', '\x2', '\x14C', - '\x14D', '\t', '\x4', '\x2', '\x2', '\x14D', ';', '\x3', '\x2', '\x2', - '\x2', '\x14E', '\x14F', '\t', '\x5', '\x2', '\x2', '\x14F', '=', '\x3', - '\x2', '\x2', '\x2', '\x150', '\x151', '\t', '\x6', '\x2', '\x2', '\x151', - '?', '\x3', '\x2', '\x2', '\x2', '\x152', '\x153', '\t', '\a', '\x2', - '\x2', '\x153', '\x41', '\x3', '\x2', '\x2', '\x2', '\x154', '\x155', - '\a', '\x17', '\x2', '\x2', '\x155', '\x43', '\x3', '\x2', '\x2', '\x2', - '\x156', '\x157', '\a', '\x18', '\x2', '\x2', '\x157', '\x45', '\x3', - '\x2', '\x2', '\x2', '\x158', '\x159', '\a', '\x19', '\x2', '\x2', '\x159', - 'G', '\x3', '\x2', '\x2', '\x2', '\x15A', '\x15B', '\a', '\x1A', '\x2', - '\x2', '\x15B', 'I', '\x3', '\x2', '\x2', '\x2', '\x15C', '\x161', '\x5', - 'N', '(', '\x2', '\x15D', '\x15E', '\x5', 'L', '\'', '\x2', '\x15E', '\x15F', - '\x5', 'J', '&', '\x2', '\x15F', '\x161', '\x3', '\x2', '\x2', '\x2', - '\x160', '\x15C', '\x3', '\x2', '\x2', '\x2', '\x160', '\x15D', '\x3', - '\x2', '\x2', '\x2', '\x161', 'K', '\x3', '\x2', '\x2', '\x2', '\x162', - '\x163', '\t', '\b', '\x2', '\x2', '\x163', 'M', '\x3', '\x2', '\x2', - '\x2', '\x164', '\x165', '\b', '(', '\x1', '\x2', '\x165', '\x18F', '\a', - '>', '\x2', '\x2', '\x166', '\x18F', '\a', '?', '\x2', '\x2', '\x167', - '\x18F', '\x5', 'V', ',', '\x2', '\x168', '\x16A', '\a', '\b', '\x2', - '\x2', '\x169', '\x16B', '\x5', 'P', ')', '\x2', '\x16A', '\x169', '\x3', - '\x2', '\x2', '\x2', '\x16A', '\x16B', '\x3', '\x2', '\x2', '\x2', '\x16B', - '\x16C', '\x3', '\x2', '\x2', '\x2', '\x16C', '\x18F', '\a', '\t', '\x2', - '\x2', '\x16D', '\x16F', '\a', '\x1C', '\x2', '\x2', '\x16E', '\x170', - '\x5', 'R', '*', '\x2', '\x16F', '\x16E', '\x3', '\x2', '\x2', '\x2', - '\x16F', '\x170', '\x3', '\x2', '\x2', '\x2', '\x170', '\x171', '\x3', - '\x2', '\x2', '\x2', '\x171', '\x18F', '\a', '\x1D', '\x2', '\x2', '\x172', - '\x173', '\a', '\x37', '\x2', '\x2', '\x173', '\x175', '\a', '\a', '\x2', - '\x2', '\x174', '\x172', '\x3', '\x2', '\x2', '\x2', '\x174', '\x175', - '\x3', '\x2', '\x2', '\x2', '\x175', '\x176', '\x3', '\x2', '\x2', '\x2', - '\x176', '\x177', '\a', '>', '\x2', '\x2', '\x177', '\x179', '\a', '\x5', - '\x2', '\x2', '\x178', '\x17A', '\x5', 'P', ')', '\x2', '\x179', '\x178', - '\x3', '\x2', '\x2', '\x2', '\x179', '\x17A', '\x3', '\x2', '\x2', '\x2', - '\x17A', '\x17B', '\x3', '\x2', '\x2', '\x2', '\x17B', '\x18F', '\a', - '\x6', '\x2', '\x2', '\x17C', '\x17D', '\a', '\x5', '\x2', '\x2', '\x17D', - '\x17E', '\x5', '.', '\x18', '\x2', '\x17E', '\x17F', '\a', '\x6', '\x2', - '\x2', '\x17F', '\x18F', '\x3', '\x2', '\x2', '\x2', '\x180', '\x181', - '\a', '\x5', '\x2', '\x2', '\x181', '\x182', '\x5', '\x4', '\x3', '\x2', - '\x182', '\x183', '\a', '\x6', '\x2', '\x2', '\x183', '\x18F', '\x3', - '\x2', '\x2', '\x2', '\x184', '\x185', '\a', '\'', '\x2', '\x2', '\x185', - '\x186', '\a', '\x5', '\x2', '\x2', '\x186', '\x187', '\x5', '\x4', '\x3', - '\x2', '\x187', '\x188', '\a', '\x6', '\x2', '\x2', '\x188', '\x18F', - '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\a', '\x1F', '\x2', '\x2', - '\x18A', '\x18B', '\a', '\x5', '\x2', '\x2', '\x18B', '\x18C', '\x5', - '\x4', '\x3', '\x2', '\x18C', '\x18D', '\a', '\x6', '\x2', '\x2', '\x18D', - '\x18F', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x164', '\x3', '\x2', '\x2', - '\x2', '\x18E', '\x166', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x167', - '\x3', '\x2', '\x2', '\x2', '\x18E', '\x168', '\x3', '\x2', '\x2', '\x2', - '\x18E', '\x16D', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x174', '\x3', - '\x2', '\x2', '\x2', '\x18E', '\x17C', '\x3', '\x2', '\x2', '\x2', '\x18E', - '\x180', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x184', '\x3', '\x2', '\x2', - '\x2', '\x18E', '\x189', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x19A', - '\x3', '\x2', '\x2', '\x2', '\x190', '\x191', '\f', '\x6', '\x2', '\x2', - '\x191', '\x192', '\a', '\a', '\x2', '\x2', '\x192', '\x199', '\a', '>', - '\x2', '\x2', '\x193', '\x194', '\f', '\x5', '\x2', '\x2', '\x194', '\x195', - '\a', '\b', '\x2', '\x2', '\x195', '\x196', '\x5', '.', '\x18', '\x2', - '\x196', '\x197', '\a', '\t', '\x2', '\x2', '\x197', '\x199', '\x3', '\x2', - '\x2', '\x2', '\x198', '\x190', '\x3', '\x2', '\x2', '\x2', '\x198', '\x193', - '\x3', '\x2', '\x2', '\x2', '\x199', '\x19C', '\x3', '\x2', '\x2', '\x2', - '\x19A', '\x198', '\x3', '\x2', '\x2', '\x2', '\x19A', '\x19B', '\x3', - '\x2', '\x2', '\x2', '\x19B', 'O', '\x3', '\x2', '\x2', '\x2', '\x19C', - '\x19A', '\x3', '\x2', '\x2', '\x2', '\x19D', '\x1A2', '\x5', '.', '\x18', - '\x2', '\x19E', '\x19F', '\a', '\x4', '\x2', '\x2', '\x19F', '\x1A1', - '\x5', '.', '\x18', '\x2', '\x1A0', '\x19E', '\x3', '\x2', '\x2', '\x2', - '\x1A1', '\x1A4', '\x3', '\x2', '\x2', '\x2', '\x1A2', '\x1A0', '\x3', - '\x2', '\x2', '\x2', '\x1A2', '\x1A3', '\x3', '\x2', '\x2', '\x2', '\x1A3', - 'Q', '\x3', '\x2', '\x2', '\x2', '\x1A4', '\x1A2', '\x3', '\x2', '\x2', - '\x2', '\x1A5', '\x1AA', '\x5', 'T', '+', '\x2', '\x1A6', '\x1A7', '\a', - '\x4', '\x2', '\x2', '\x1A7', '\x1A9', '\x5', 'T', '+', '\x2', '\x1A8', - '\x1A6', '\x3', '\x2', '\x2', '\x2', '\x1A9', '\x1AC', '\x3', '\x2', '\x2', - '\x2', '\x1AA', '\x1A8', '\x3', '\x2', '\x2', '\x2', '\x1AA', '\x1AB', - '\x3', '\x2', '\x2', '\x2', '\x1AB', 'S', '\x3', '\x2', '\x2', '\x2', - '\x1AC', '\x1AA', '\x3', '\x2', '\x2', '\x2', '\x1AD', '\x1AE', '\a', - '=', '\x2', '\x2', '\x1AE', '\x1AF', '\a', '\v', '\x2', '\x2', '\x1AF', - '\x1B0', '\x5', '.', '\x18', '\x2', '\x1B0', 'U', '\x3', '\x2', '\x2', - '\x2', '\x1B1', '\x1B2', '\t', '\t', '\x2', '\x2', '\x1B2', 'W', '\x3', - '\x2', '\x2', '\x2', ',', ']', '`', '\x63', '\x66', 'i', 'm', 'p', 'z', - '\x86', '\x8C', '\x94', '\x97', '\x9C', '\xA3', '\xA8', '\xAE', '\xBC', - '\xBE', '\xD1', '\xD6', '\xE7', '\xEE', '\xF9', '\xFB', '\x102', '\x10A', - '\x10C', '\x111', '\x11A', '\x11F', '\x147', '\x149', '\x160', '\x16A', - '\x16F', '\x174', '\x179', '\x18E', '\x198', '\x19A', '\x1A2', '\x1AA', + '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', 'Z', + '\x2', '\v', '\x4', '\x2', '?', '?', '\x42', '\x42', '\x4', '\x2', '\"', + '\"', '%', '%', '\x4', '\x2', '\x3', '\x3', '\r', '\xE', '\x3', '\x2', + '\xF', '\x10', '\x3', '\x2', '\x11', '\x14', '\x3', '\x2', '\x15', '\x16', + '\x5', '\x2', '\xF', '\x10', '\x1B', '\x1B', '\x31', '\x31', '\x4', '\x2', + '\x1E', '\x1E', '\x41', '\x41', '\a', '\x2', ')', ')', '\x32', '\x32', + '\x39', '\x39', ';', ';', '?', '@', '\x2', '\x1E2', '\x2', '\\', '\x3', + '\x2', '\x2', '\x2', '\x4', '_', '\x3', '\x2', '\x2', '\x2', '\x6', 'o', + '\x3', '\x2', '\x2', '\x2', '\b', 'x', '\x3', '\x2', '\x2', '\x2', '\n', + '~', '\x3', '\x2', '\x2', '\x2', '\f', '\x80', '\x3', '\x2', '\x2', '\x2', + '\xE', '\x82', '\x3', '\x2', '\x2', '\x2', '\x10', '\x85', '\x3', '\x2', + '\x2', '\x2', '\x12', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x14', '\x92', + '\x3', '\x2', '\x2', '\x2', '\x16', '\xA1', '\x3', '\x2', '\x2', '\x2', + '\x18', '\xB3', '\x3', '\x2', '\x2', '\x2', '\x1A', '\xB5', '\x3', '\x2', + '\x2', '\x2', '\x1C', '\xC6', '\x3', '\x2', '\x2', '\x2', '\x1E', '\xC9', + '\x3', '\x2', '\x2', '\x2', ' ', '\xCD', '\x3', '\x2', '\x2', '\x2', '\"', + '\xD1', '\x3', '\x2', '\x2', '\x2', '$', '\xD9', '\x3', '\x2', '\x2', + '\x2', '&', '\xDD', '\x3', '\x2', '\x2', '\x2', '(', '\xDF', '\x3', '\x2', + '\x2', '\x2', '*', '\xE4', '\x3', '\x2', '\x2', '\x2', ',', '\xE6', '\x3', + '\x2', '\x2', '\x2', '.', '\xF3', '\x3', '\x2', '\x2', '\x2', '\x30', + '\x107', '\x3', '\x2', '\x2', '\x2', '\x32', '\x114', '\x3', '\x2', '\x2', + '\x2', '\x34', '\x11D', '\x3', '\x2', '\x2', '\x2', '\x36', '\x126', '\x3', + '\x2', '\x2', '\x2', '\x38', '\x129', '\x3', '\x2', '\x2', '\x2', ':', + '\x151', '\x3', '\x2', '\x2', '\x2', '<', '\x153', '\x3', '\x2', '\x2', + '\x2', '>', '\x155', '\x3', '\x2', '\x2', '\x2', '@', '\x157', '\x3', + '\x2', '\x2', '\x2', '\x42', '\x159', '\x3', '\x2', '\x2', '\x2', '\x44', + '\x15B', '\x3', '\x2', '\x2', '\x2', '\x46', '\x15D', '\x3', '\x2', '\x2', + '\x2', 'H', '\x15F', '\x3', '\x2', '\x2', '\x2', 'J', '\x165', '\x3', + '\x2', '\x2', '\x2', 'L', '\x167', '\x3', '\x2', '\x2', '\x2', 'N', '\x18F', + '\x3', '\x2', '\x2', '\x2', 'P', '\x1B5', '\x3', '\x2', '\x2', '\x2', + 'R', '\x1B7', '\x3', '\x2', '\x2', '\x2', 'T', '\x1BF', '\x3', '\x2', + '\x2', '\x2', 'V', '\x1C7', '\x3', '\x2', '\x2', '\x2', 'X', '\x1CB', + '\x3', '\x2', '\x2', '\x2', 'Z', '\x1CD', '\x3', '\x2', '\x2', '\x2', + '\\', ']', '\x5', '\x4', '\x3', '\x2', ']', '^', '\a', '\x2', '\x2', '\x3', + '^', '\x3', '\x3', '\x2', '\x2', '\x2', '_', '\x61', '\x5', '\x6', '\x4', + '\x2', '`', '\x62', '\x5', '\x14', '\v', '\x2', '\x61', '`', '\x3', '\x2', + '\x2', '\x2', '\x61', '\x62', '\x3', '\x2', '\x2', '\x2', '\x62', '\x64', + '\x3', '\x2', '\x2', '\x2', '\x63', '\x65', '\x5', '\x1C', '\xF', '\x2', + '\x64', '\x63', '\x3', '\x2', '\x2', '\x2', '\x64', '\x65', '\x3', '\x2', + '\x2', '\x2', '\x65', 'g', '\x3', '\x2', '\x2', '\x2', '\x66', 'h', '\x5', + '\x1E', '\x10', '\x2', 'g', '\x66', '\x3', '\x2', '\x2', '\x2', 'g', 'h', + '\x3', '\x2', '\x2', '\x2', 'h', 'j', '\x3', '\x2', '\x2', '\x2', 'i', + 'k', '\x5', ' ', '\x11', '\x2', 'j', 'i', '\x3', '\x2', '\x2', '\x2', + 'j', 'k', '\x3', '\x2', '\x2', '\x2', 'k', 'm', '\x3', '\x2', '\x2', '\x2', + 'l', 'n', '\x5', '(', '\x15', '\x2', 'm', 'l', '\x3', '\x2', '\x2', '\x2', + 'm', 'n', '\x3', '\x2', '\x2', '\x2', 'n', '\x5', '\x3', '\x2', '\x2', + '\x2', 'o', 'q', '\a', '\x37', '\x2', '\x2', 'p', 'r', '\a', '&', '\x2', + '\x2', 'q', 'p', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\x3', '\x2', '\x2', + '\x2', 'r', 't', '\x3', '\x2', '\x2', '\x2', 's', 'u', '\x5', '\b', '\x5', + '\x2', 't', 's', '\x3', '\x2', '\x2', '\x2', 't', 'u', '\x3', '\x2', '\x2', + '\x2', 'u', 'v', '\x3', '\x2', '\x2', '\x2', 'v', 'w', '\x5', '\n', '\x6', + '\x2', 'w', '\a', '\x3', '\x2', '\x2', '\x2', 'x', 'y', '\a', '\x38', + '\x2', '\x2', 'y', 'z', '\t', '\x2', '\x2', '\x2', 'z', '\t', '\x3', '\x2', + '\x2', '\x2', '{', '\x7F', '\x5', '\f', '\a', '\x2', '|', '\x7F', '\x5', + '\xE', '\b', '\x2', '}', '\x7F', '\x5', '\x10', '\t', '\x2', '~', '{', + '\x3', '\x2', '\x2', '\x2', '~', '|', '\x3', '\x2', '\x2', '\x2', '~', + '}', '\x3', '\x2', '\x2', '\x2', '\x7F', '\v', '\x3', '\x2', '\x2', '\x2', + '\x80', '\x81', '\a', '\x3', '\x2', '\x2', '\x81', '\r', '\x3', '\x2', + '\x2', '\x2', '\x82', '\x83', '\a', '<', '\x2', '\x2', '\x83', '\x84', + '\x5', '.', '\x18', '\x2', '\x84', '\xF', '\x3', '\x2', '\x2', '\x2', + '\x85', '\x8A', '\x5', '\x12', '\n', '\x2', '\x86', '\x87', '\a', '\x4', + '\x2', '\x2', '\x87', '\x89', '\x5', '\x12', '\n', '\x2', '\x88', '\x86', + '\x3', '\x2', '\x2', '\x2', '\x89', '\x8C', '\x3', '\x2', '\x2', '\x2', + '\x8A', '\x88', '\x3', '\x2', '\x2', '\x2', '\x8A', '\x8B', '\x3', '\x2', + '\x2', '\x2', '\x8B', '\x11', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A', + '\x3', '\x2', '\x2', '\x2', '\x8D', '\x90', '\x5', '.', '\x18', '\x2', + '\x8E', '\x8F', '\a', '!', '\x2', '\x2', '\x8F', '\x91', '\x5', 'X', '-', + '\x2', '\x90', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\x3', + '\x2', '\x2', '\x2', '\x91', '\x13', '\x3', '\x2', '\x2', '\x2', '\x92', + '\x93', '\a', '*', '\x2', '\x2', '\x93', '\x94', '\x5', '\x16', '\f', + '\x2', '\x94', '\x15', '\x3', '\x2', '\x2', '\x2', '\x95', '\x96', '\b', + '\f', '\x1', '\x2', '\x96', '\x9B', '\x5', '\x18', '\r', '\x2', '\x97', + '\x99', '\a', '!', '\x2', '\x2', '\x98', '\x97', '\x3', '\x2', '\x2', + '\x2', '\x98', '\x99', '\x3', '\x2', '\x2', '\x2', '\x99', '\x9A', '\x3', + '\x2', '\x2', '\x2', '\x9A', '\x9C', '\x5', 'X', '-', '\x2', '\x9B', '\x98', + '\x3', '\x2', '\x2', '\x2', '\x9B', '\x9C', '\x3', '\x2', '\x2', '\x2', + '\x9C', '\xA2', '\x3', '\x2', '\x2', '\x2', '\x9D', '\x9E', '\x5', 'X', + '-', '\x2', '\x9E', '\x9F', '\a', ',', '\x2', '\x2', '\x9F', '\xA0', '\x5', + '\x18', '\r', '\x2', '\xA0', '\xA2', '\x3', '\x2', '\x2', '\x2', '\xA1', + '\x95', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x9D', '\x3', '\x2', '\x2', + '\x2', '\xA2', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA3', '\xA4', '\f', + '\x3', '\x2', '\x2', '\xA4', '\xA5', '\a', '-', '\x2', '\x2', '\xA5', + '\xA7', '\x5', '\x16', '\f', '\x4', '\xA6', '\xA3', '\x3', '\x2', '\x2', + '\x2', '\xA7', '\xAA', '\x3', '\x2', '\x2', '\x2', '\xA8', '\xA6', '\x3', + '\x2', '\x2', '\x2', '\xA8', '\xA9', '\x3', '\x2', '\x2', '\x2', '\xA9', + '\x17', '\x3', '\x2', '\x2', '\x2', '\xAA', '\xA8', '\x3', '\x2', '\x2', + '\x2', '\xAB', '\xAD', '\x5', 'X', '-', '\x2', '\xAC', '\xAE', '\x5', + '\x1A', '\xE', '\x2', '\xAD', '\xAC', '\x3', '\x2', '\x2', '\x2', '\xAD', + '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xB4', '\x3', '\x2', '\x2', + '\x2', '\xAF', '\xB0', '\a', '\x5', '\x2', '\x2', '\xB0', '\xB1', '\x5', + '\x4', '\x3', '\x2', '\xB1', '\xB2', '\a', '\x6', '\x2', '\x2', '\xB2', + '\xB4', '\x3', '\x2', '\x2', '\x2', '\xB3', '\xAB', '\x3', '\x2', '\x2', + '\x2', '\xB3', '\xAF', '\x3', '\x2', '\x2', '\x2', '\xB4', '\x19', '\x3', + '\x2', '\x2', '\x2', '\xB5', '\xC3', '\b', '\xE', '\x1', '\x2', '\xB6', + '\xB7', '\f', '\x6', '\x2', '\x2', '\xB7', '\xB8', '\a', '\a', '\x2', + '\x2', '\xB8', '\xC2', '\x5', 'X', '-', '\x2', '\xB9', '\xBA', '\f', '\x5', + '\x2', '\x2', '\xBA', '\xBB', '\a', '\b', '\x2', '\x2', '\xBB', '\xBC', + '\a', '?', '\x2', '\x2', '\xBC', '\xC2', '\a', '\t', '\x2', '\x2', '\xBD', + '\xBE', '\f', '\x4', '\x2', '\x2', '\xBE', '\xBF', '\a', '\b', '\x2', + '\x2', '\xBF', '\xC0', '\a', '@', '\x2', '\x2', '\xC0', '\xC2', '\a', + '\t', '\x2', '\x2', '\xC1', '\xB6', '\x3', '\x2', '\x2', '\x2', '\xC1', + '\xB9', '\x3', '\x2', '\x2', '\x2', '\xC1', '\xBD', '\x3', '\x2', '\x2', + '\x2', '\xC2', '\xC5', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC1', '\x3', + '\x2', '\x2', '\x2', '\xC3', '\xC4', '\x3', '\x2', '\x2', '\x2', '\xC4', + '\x1B', '\x3', '\x2', '\x2', '\x2', '\xC5', '\xC3', '\x3', '\x2', '\x2', + '\x2', '\xC6', '\xC7', '\a', '=', '\x2', '\x2', '\xC7', '\xC8', '\x5', + '.', '\x18', '\x2', '\xC8', '\x1D', '\x3', '\x2', '\x2', '\x2', '\xC9', + '\xCA', '\a', '+', '\x2', '\x2', '\xCA', '\xCB', '\a', '$', '\x2', '\x2', + '\xCB', '\xCC', '\x5', 'R', '*', '\x2', '\xCC', '\x1F', '\x3', '\x2', + '\x2', '\x2', '\xCD', '\xCE', '\a', '\x35', '\x2', '\x2', '\xCE', '\xCF', + '\a', '$', '\x2', '\x2', '\xCF', '\xD0', '\x5', '\"', '\x12', '\x2', '\xD0', + '!', '\x3', '\x2', '\x2', '\x2', '\xD1', '\xD6', '\x5', '$', '\x13', '\x2', + '\xD2', '\xD3', '\a', '\x4', '\x2', '\x2', '\xD3', '\xD5', '\x5', '$', + '\x13', '\x2', '\xD4', '\xD2', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD8', + '\x3', '\x2', '\x2', '\x2', '\xD6', '\xD4', '\x3', '\x2', '\x2', '\x2', + '\xD6', '\xD7', '\x3', '\x2', '\x2', '\x2', '\xD7', '#', '\x3', '\x2', + '\x2', '\x2', '\xD8', '\xD6', '\x3', '\x2', '\x2', '\x2', '\xD9', '\xDB', + '\x5', '.', '\x18', '\x2', '\xDA', '\xDC', '\x5', '&', '\x14', '\x2', + '\xDB', '\xDA', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xDC', '\x3', '\x2', + '\x2', '\x2', '\xDC', '%', '\x3', '\x2', '\x2', '\x2', '\xDD', '\xDE', + '\t', '\x3', '\x2', '\x2', '\xDE', '\'', '\x3', '\x2', '\x2', '\x2', '\xDF', + '\xE0', '\a', '\x33', '\x2', '\x2', '\xE0', '\xE1', '\x5', '*', '\x16', + '\x2', '\xE1', '\xE2', '\a', '\x30', '\x2', '\x2', '\xE2', '\xE3', '\x5', + ',', '\x17', '\x2', '\xE3', ')', '\x3', '\x2', '\x2', '\x2', '\xE4', '\xE5', + '\t', '\x2', '\x2', '\x2', '\xE5', '+', '\x3', '\x2', '\x2', '\x2', '\xE6', + '\xE7', '\t', '\x2', '\x2', '\x2', '\xE7', '-', '\x3', '\x2', '\x2', '\x2', + '\xE8', '\xE9', '\b', '\x18', '\x1', '\x2', '\xE9', '\xF4', '\x5', '\x30', + '\x19', '\x2', '\xEA', '\xEC', '\x5', '\x38', '\x1D', '\x2', '\xEB', '\xED', + '\a', '\x31', '\x2', '\x2', '\xEC', '\xEB', '\x3', '\x2', '\x2', '\x2', + '\xEC', '\xED', '\x3', '\x2', '\x2', '\x2', '\xED', '\xEE', '\x3', '\x2', + '\x2', '\x2', '\xEE', '\xEF', '\a', '#', '\x2', '\x2', '\xEF', '\xF0', + '\x5', '\x38', '\x1D', '\x2', '\xF0', '\xF1', '\a', '\x1F', '\x2', '\x2', + '\xF1', '\xF2', '\x5', '\x38', '\x1D', '\x2', '\xF2', '\xF4', '\x3', '\x2', + '\x2', '\x2', '\xF3', '\xE8', '\x3', '\x2', '\x2', '\x2', '\xF3', '\xEA', + '\x3', '\x2', '\x2', '\x2', '\xF4', '\x100', '\x3', '\x2', '\x2', '\x2', + '\xF5', '\xF6', '\f', '\x6', '\x2', '\x2', '\xF6', '\xF7', '\a', '\n', + '\x2', '\x2', '\xF7', '\xF8', '\x5', '.', '\x18', '\x2', '\xF8', '\xF9', + '\a', '\v', '\x2', '\x2', '\xF9', '\xFA', '\x5', '.', '\x18', '\a', '\xFA', + '\xFF', '\x3', '\x2', '\x2', '\x2', '\xFB', '\xFC', '\f', '\x5', '\x2', + '\x2', '\xFC', '\xFD', '\a', '\f', '\x2', '\x2', '\xFD', '\xFF', '\x5', + '.', '\x18', '\x6', '\xFE', '\xF5', '\x3', '\x2', '\x2', '\x2', '\xFE', + '\xFB', '\x3', '\x2', '\x2', '\x2', '\xFF', '\x102', '\x3', '\x2', '\x2', + '\x2', '\x100', '\xFE', '\x3', '\x2', '\x2', '\x2', '\x100', '\x101', + '\x3', '\x2', '\x2', '\x2', '\x101', '/', '\x3', '\x2', '\x2', '\x2', + '\x102', '\x100', '\x3', '\x2', '\x2', '\x2', '\x103', '\x104', '\b', + '\x19', '\x1', '\x2', '\x104', '\x108', '\x5', '\x38', '\x1D', '\x2', + '\x105', '\x108', '\x5', '\x32', '\x1A', '\x2', '\x106', '\x108', '\x5', + '\x34', '\x1B', '\x2', '\x107', '\x103', '\x3', '\x2', '\x2', '\x2', '\x107', + '\x105', '\x3', '\x2', '\x2', '\x2', '\x107', '\x106', '\x3', '\x2', '\x2', + '\x2', '\x108', '\x111', '\x3', '\x2', '\x2', '\x2', '\x109', '\x10A', + '\f', '\x4', '\x2', '\x2', '\x10A', '\x10B', '\a', '\x1F', '\x2', '\x2', + '\x10B', '\x110', '\x5', '\x30', '\x19', '\x5', '\x10C', '\x10D', '\f', + '\x3', '\x2', '\x2', '\x10D', '\x10E', '\a', '\x34', '\x2', '\x2', '\x10E', + '\x110', '\x5', '\x30', '\x19', '\x4', '\x10F', '\x109', '\x3', '\x2', + '\x2', '\x2', '\x10F', '\x10C', '\x3', '\x2', '\x2', '\x2', '\x110', '\x113', + '\x3', '\x2', '\x2', '\x2', '\x111', '\x10F', '\x3', '\x2', '\x2', '\x2', + '\x111', '\x112', '\x3', '\x2', '\x2', '\x2', '\x112', '\x31', '\x3', + '\x2', '\x2', '\x2', '\x113', '\x111', '\x3', '\x2', '\x2', '\x2', '\x114', + '\x116', '\x5', '\x38', '\x1D', '\x2', '\x115', '\x117', '\a', '\x31', + '\x2', '\x2', '\x116', '\x115', '\x3', '\x2', '\x2', '\x2', '\x116', '\x117', + '\x3', '\x2', '\x2', '\x2', '\x117', '\x118', '\x3', '\x2', '\x2', '\x2', + '\x118', '\x119', '\a', ',', '\x2', '\x2', '\x119', '\x11A', '\a', '\x5', + '\x2', '\x2', '\x11A', '\x11B', '\x5', 'R', '*', '\x2', '\x11B', '\x11C', + '\a', '\x6', '\x2', '\x2', '\x11C', '\x33', '\x3', '\x2', '\x2', '\x2', + '\x11D', '\x11F', '\x5', '\x38', '\x1D', '\x2', '\x11E', '\x120', '\a', + '\x31', '\x2', '\x2', '\x11F', '\x11E', '\x3', '\x2', '\x2', '\x2', '\x11F', + '\x120', '\x3', '\x2', '\x2', '\x2', '\x120', '\x121', '\x3', '\x2', '\x2', + '\x2', '\x121', '\x122', '\a', '/', '\x2', '\x2', '\x122', '\x124', '\x5', + '\x38', '\x1D', '\x2', '\x123', '\x125', '\x5', '\x36', '\x1C', '\x2', + '\x124', '\x123', '\x3', '\x2', '\x2', '\x2', '\x124', '\x125', '\x3', + '\x2', '\x2', '\x2', '\x125', '\x35', '\x3', '\x2', '\x2', '\x2', '\x126', + '\x127', '\a', '\'', '\x2', '\x2', '\x127', '\x128', '\a', '@', '\x2', + '\x2', '\x128', '\x37', '\x3', '\x2', '\x2', '\x2', '\x129', '\x12A', + '\b', '\x1D', '\x1', '\x2', '\x12A', '\x12B', '\x5', 'J', '&', '\x2', + '\x12B', '\x14E', '\x3', '\x2', '\x2', '\x2', '\x12C', '\x12D', '\f', + '\n', '\x2', '\x2', '\x12D', '\x12E', '\x5', ':', '\x1E', '\x2', '\x12E', + '\x12F', '\x5', '\x38', '\x1D', '\v', '\x12F', '\x14D', '\x3', '\x2', + '\x2', '\x2', '\x130', '\x131', '\f', '\t', '\x2', '\x2', '\x131', '\x132', + '\x5', '<', '\x1F', '\x2', '\x132', '\x133', '\x5', '\x38', '\x1D', '\n', + '\x133', '\x14D', '\x3', '\x2', '\x2', '\x2', '\x134', '\x135', '\f', + '\b', '\x2', '\x2', '\x135', '\x136', '\x5', '>', ' ', '\x2', '\x136', + '\x137', '\x5', '\x38', '\x1D', '\t', '\x137', '\x14D', '\x3', '\x2', + '\x2', '\x2', '\x138', '\x139', '\f', '\a', '\x2', '\x2', '\x139', '\x13A', + '\x5', '@', '!', '\x2', '\x13A', '\x13B', '\x5', '\x38', '\x1D', '\b', + '\x13B', '\x14D', '\x3', '\x2', '\x2', '\x2', '\x13C', '\x13D', '\f', + '\x6', '\x2', '\x2', '\x13D', '\x13E', '\x5', '\x42', '\"', '\x2', '\x13E', + '\x13F', '\x5', '\x38', '\x1D', '\a', '\x13F', '\x14D', '\x3', '\x2', + '\x2', '\x2', '\x140', '\x141', '\f', '\x5', '\x2', '\x2', '\x141', '\x142', + '\x5', '\x44', '#', '\x2', '\x142', '\x143', '\x5', '\x38', '\x1D', '\x6', + '\x143', '\x14D', '\x3', '\x2', '\x2', '\x2', '\x144', '\x145', '\f', + '\x4', '\x2', '\x2', '\x145', '\x146', '\x5', '\x46', '$', '\x2', '\x146', + '\x147', '\x5', '\x38', '\x1D', '\x5', '\x147', '\x14D', '\x3', '\x2', + '\x2', '\x2', '\x148', '\x149', '\f', '\x3', '\x2', '\x2', '\x149', '\x14A', + '\x5', 'H', '%', '\x2', '\x14A', '\x14B', '\x5', '\x38', '\x1D', '\x4', + '\x14B', '\x14D', '\x3', '\x2', '\x2', '\x2', '\x14C', '\x12C', '\x3', + '\x2', '\x2', '\x2', '\x14C', '\x130', '\x3', '\x2', '\x2', '\x2', '\x14C', + '\x134', '\x3', '\x2', '\x2', '\x2', '\x14C', '\x138', '\x3', '\x2', '\x2', + '\x2', '\x14C', '\x13C', '\x3', '\x2', '\x2', '\x2', '\x14C', '\x140', + '\x3', '\x2', '\x2', '\x2', '\x14C', '\x144', '\x3', '\x2', '\x2', '\x2', + '\x14C', '\x148', '\x3', '\x2', '\x2', '\x2', '\x14D', '\x150', '\x3', + '\x2', '\x2', '\x2', '\x14E', '\x14C', '\x3', '\x2', '\x2', '\x2', '\x14E', + '\x14F', '\x3', '\x2', '\x2', '\x2', '\x14F', '\x39', '\x3', '\x2', '\x2', + '\x2', '\x150', '\x14E', '\x3', '\x2', '\x2', '\x2', '\x151', '\x152', + '\t', '\x4', '\x2', '\x2', '\x152', ';', '\x3', '\x2', '\x2', '\x2', '\x153', + '\x154', '\t', '\x5', '\x2', '\x2', '\x154', '=', '\x3', '\x2', '\x2', + '\x2', '\x155', '\x156', '\t', '\x6', '\x2', '\x2', '\x156', '?', '\x3', + '\x2', '\x2', '\x2', '\x157', '\x158', '\t', '\a', '\x2', '\x2', '\x158', + '\x41', '\x3', '\x2', '\x2', '\x2', '\x159', '\x15A', '\a', '\x17', '\x2', + '\x2', '\x15A', '\x43', '\x3', '\x2', '\x2', '\x2', '\x15B', '\x15C', + '\a', '\x18', '\x2', '\x2', '\x15C', '\x45', '\x3', '\x2', '\x2', '\x2', + '\x15D', '\x15E', '\a', '\x19', '\x2', '\x2', '\x15E', 'G', '\x3', '\x2', + '\x2', '\x2', '\x15F', '\x160', '\a', '\x1A', '\x2', '\x2', '\x160', 'I', + '\x3', '\x2', '\x2', '\x2', '\x161', '\x166', '\x5', 'N', '(', '\x2', + '\x162', '\x163', '\x5', 'L', '\'', '\x2', '\x163', '\x164', '\x5', 'J', + '&', '\x2', '\x164', '\x166', '\x3', '\x2', '\x2', '\x2', '\x165', '\x161', + '\x3', '\x2', '\x2', '\x2', '\x165', '\x162', '\x3', '\x2', '\x2', '\x2', + '\x166', 'K', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', '\t', '\b', + '\x2', '\x2', '\x168', 'M', '\x3', '\x2', '\x2', '\x2', '\x169', '\x16A', + '\b', '(', '\x1', '\x2', '\x16A', '\x190', '\x5', 'X', '-', '\x2', '\x16B', + '\x190', '\a', '\x42', '\x2', '\x2', '\x16C', '\x190', '\x5', 'Z', '.', + '\x2', '\x16D', '\x16F', '\a', '\b', '\x2', '\x2', '\x16E', '\x170', '\x5', + 'R', '*', '\x2', '\x16F', '\x16E', '\x3', '\x2', '\x2', '\x2', '\x16F', + '\x170', '\x3', '\x2', '\x2', '\x2', '\x170', '\x171', '\x3', '\x2', '\x2', + '\x2', '\x171', '\x190', '\a', '\t', '\x2', '\x2', '\x172', '\x174', '\a', + '\x1C', '\x2', '\x2', '\x173', '\x175', '\x5', 'T', '+', '\x2', '\x174', + '\x173', '\x3', '\x2', '\x2', '\x2', '\x174', '\x175', '\x3', '\x2', '\x2', + '\x2', '\x175', '\x176', '\x3', '\x2', '\x2', '\x2', '\x176', '\x190', + '\a', '\x1D', '\x2', '\x2', '\x177', '\x178', '\a', '\x5', '\x2', '\x2', + '\x178', '\x179', '\x5', '.', '\x18', '\x2', '\x179', '\x17A', '\a', '\x6', + '\x2', '\x2', '\x17A', '\x190', '\x3', '\x2', '\x2', '\x2', '\x17B', '\x17C', + '\a', '\x5', '\x2', '\x2', '\x17C', '\x17D', '\x5', '\x4', '\x3', '\x2', + '\x17D', '\x17E', '\a', '\x6', '\x2', '\x2', '\x17E', '\x190', '\x3', + '\x2', '\x2', '\x2', '\x17F', '\x180', '\a', '(', '\x2', '\x2', '\x180', + '\x181', '\a', '\x5', '\x2', '\x2', '\x181', '\x182', '\x5', '\x4', '\x3', + '\x2', '\x182', '\x183', '\a', '\x6', '\x2', '\x2', '\x183', '\x190', + '\x3', '\x2', '\x2', '\x2', '\x184', '\x185', '\a', ' ', '\x2', '\x2', + '\x185', '\x186', '\a', '\x5', '\x2', '\x2', '\x186', '\x187', '\x5', + '\x4', '\x3', '\x2', '\x187', '\x188', '\a', '\x6', '\x2', '\x2', '\x188', + '\x190', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\a', '\x1E', '\x2', + '\x2', '\x18A', '\x18B', '\a', '\x5', '\x2', '\x2', '\x18B', '\x18C', + '\x5', '\x4', '\x3', '\x2', '\x18C', '\x18D', '\a', '\x6', '\x2', '\x2', + '\x18D', '\x190', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x190', '\x5', + 'P', ')', '\x2', '\x18F', '\x169', '\x3', '\x2', '\x2', '\x2', '\x18F', + '\x16B', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x16C', '\x3', '\x2', '\x2', + '\x2', '\x18F', '\x16D', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x172', + '\x3', '\x2', '\x2', '\x2', '\x18F', '\x177', '\x3', '\x2', '\x2', '\x2', + '\x18F', '\x17B', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x17F', '\x3', + '\x2', '\x2', '\x2', '\x18F', '\x184', '\x3', '\x2', '\x2', '\x2', '\x18F', + '\x189', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x18E', '\x3', '\x2', '\x2', + '\x2', '\x190', '\x19B', '\x3', '\x2', '\x2', '\x2', '\x191', '\x192', + '\f', '\b', '\x2', '\x2', '\x192', '\x193', '\a', '\a', '\x2', '\x2', + '\x193', '\x19A', '\x5', 'X', '-', '\x2', '\x194', '\x195', '\f', '\a', + '\x2', '\x2', '\x195', '\x196', '\a', '\b', '\x2', '\x2', '\x196', '\x197', + '\x5', '.', '\x18', '\x2', '\x197', '\x198', '\a', '\t', '\x2', '\x2', + '\x198', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x199', '\x191', '\x3', + '\x2', '\x2', '\x2', '\x199', '\x194', '\x3', '\x2', '\x2', '\x2', '\x19A', + '\x19D', '\x3', '\x2', '\x2', '\x2', '\x19B', '\x199', '\x3', '\x2', '\x2', + '\x2', '\x19B', '\x19C', '\x3', '\x2', '\x2', '\x2', '\x19C', 'O', '\x3', + '\x2', '\x2', '\x2', '\x19D', '\x19B', '\x3', '\x2', '\x2', '\x2', '\x19E', + '\x19F', '\a', ':', '\x2', '\x2', '\x19F', '\x1A1', '\a', '\a', '\x2', + '\x2', '\x1A0', '\x19E', '\x3', '\x2', '\x2', '\x2', '\x1A0', '\x1A1', + '\x3', '\x2', '\x2', '\x2', '\x1A1', '\x1A2', '\x3', '\x2', '\x2', '\x2', + '\x1A2', '\x1A3', '\x5', 'X', '-', '\x2', '\x1A3', '\x1A5', '\a', '\x5', + '\x2', '\x2', '\x1A4', '\x1A6', '\x5', 'R', '*', '\x2', '\x1A5', '\x1A4', + '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1A6', '\x3', '\x2', '\x2', '\x2', + '\x1A6', '\x1A7', '\x3', '\x2', '\x2', '\x2', '\x1A7', '\x1A8', '\a', + '\x6', '\x2', '\x2', '\x1A8', '\x1B6', '\x3', '\x2', '\x2', '\x2', '\x1A9', + '\x1AA', '\a', '.', '\x2', '\x2', '\x1AA', '\x1AC', '\a', '\x5', '\x2', + '\x2', '\x1AB', '\x1AD', '\x5', 'R', '*', '\x2', '\x1AC', '\x1AB', '\x3', + '\x2', '\x2', '\x2', '\x1AC', '\x1AD', '\x3', '\x2', '\x2', '\x2', '\x1AD', + '\x1AE', '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1B6', '\a', '\x6', '\x2', + '\x2', '\x1AF', '\x1B0', '\a', '\x36', '\x2', '\x2', '\x1B0', '\x1B2', + '\a', '\x5', '\x2', '\x2', '\x1B1', '\x1B3', '\x5', 'R', '*', '\x2', '\x1B2', + '\x1B1', '\x3', '\x2', '\x2', '\x2', '\x1B2', '\x1B3', '\x3', '\x2', '\x2', + '\x2', '\x1B3', '\x1B4', '\x3', '\x2', '\x2', '\x2', '\x1B4', '\x1B6', + '\a', '\x6', '\x2', '\x2', '\x1B5', '\x1A0', '\x3', '\x2', '\x2', '\x2', + '\x1B5', '\x1A9', '\x3', '\x2', '\x2', '\x2', '\x1B5', '\x1AF', '\x3', + '\x2', '\x2', '\x2', '\x1B6', 'Q', '\x3', '\x2', '\x2', '\x2', '\x1B7', + '\x1BC', '\x5', '.', '\x18', '\x2', '\x1B8', '\x1B9', '\a', '\x4', '\x2', + '\x2', '\x1B9', '\x1BB', '\x5', '.', '\x18', '\x2', '\x1BA', '\x1B8', + '\x3', '\x2', '\x2', '\x2', '\x1BB', '\x1BE', '\x3', '\x2', '\x2', '\x2', + '\x1BC', '\x1BA', '\x3', '\x2', '\x2', '\x2', '\x1BC', '\x1BD', '\x3', + '\x2', '\x2', '\x2', '\x1BD', 'S', '\x3', '\x2', '\x2', '\x2', '\x1BE', + '\x1BC', '\x3', '\x2', '\x2', '\x2', '\x1BF', '\x1C4', '\x5', 'V', ',', + '\x2', '\x1C0', '\x1C1', '\a', '\x4', '\x2', '\x2', '\x1C1', '\x1C3', + '\x5', 'V', ',', '\x2', '\x1C2', '\x1C0', '\x3', '\x2', '\x2', '\x2', + '\x1C3', '\x1C6', '\x3', '\x2', '\x2', '\x2', '\x1C4', '\x1C2', '\x3', + '\x2', '\x2', '\x2', '\x1C4', '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C5', + 'U', '\x3', '\x2', '\x2', '\x2', '\x1C6', '\x1C4', '\x3', '\x2', '\x2', + '\x2', '\x1C7', '\x1C8', '\a', '@', '\x2', '\x2', '\x1C8', '\x1C9', '\a', + '\v', '\x2', '\x2', '\x1C9', '\x1CA', '\x5', '.', '\x18', '\x2', '\x1CA', + 'W', '\x3', '\x2', '\x2', '\x2', '\x1CB', '\x1CC', '\t', '\t', '\x2', + '\x2', '\x1CC', 'Y', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1CE', '\t', + '\n', '\x2', '\x2', '\x1CE', '[', '\x3', '\x2', '\x2', '\x2', '/', '\x61', + '\x64', 'g', 'j', 'm', 'q', 't', '~', '\x8A', '\x90', '\x98', '\x9B', + '\xA1', '\xA8', '\xAD', '\xB3', '\xC1', '\xC3', '\xD6', '\xDB', '\xEC', + '\xF3', '\xFE', '\x100', '\x107', '\x10F', '\x111', '\x116', '\x11F', + '\x124', '\x14C', '\x14E', '\x165', '\x16F', '\x174', '\x18F', '\x199', + '\x19B', '\x1A0', '\x1A5', '\x1AC', '\x1B2', '\x1B5', '\x1BC', '\x1C4', }; public static readonly ATN _ATN = diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 4e6bacb145..36e14d78bd 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -789,6 +789,12 @@ private enum Aggregate public static readonly AggregateScalarExpressionDetector Singleton = new AggregateScalarExpressionDetector(); + public override bool Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + public override bool Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { bool hasAggregates = false; diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlAllScalarExpression.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlAllScalarExpression.cs new file mode 100644 index 0000000000..4bfbee4668 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlAllScalarExpression.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SqlObjects +{ + using System; + using Microsoft.Azure.Cosmos.SqlObjects.Visitors; + +#if INTERNAL +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member +#pragma warning disable SA1600 // Elements should be documented + public +#else + internal +#endif + sealed class SqlAllScalarExpression : SqlScalarExpression + { + private SqlAllScalarExpression(SqlQuery subquery) + { + this.Subquery = subquery ?? throw new ArgumentNullException(nameof(subquery)); + } + + public SqlQuery Subquery { get; } + + public static SqlAllScalarExpression Create(SqlQuery subquery) => new SqlAllScalarExpression(subquery); + + public override void Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor, T input) => visitor.Visit(this, input); + + public override void Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor, T input) => visitor.Visit(this, input); + } +} diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs index 5a4bd72d63..3a9bf01970 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs @@ -36,6 +36,21 @@ public override bool Visit(SqlAliasedCollectionExpression first, SqlObject secon return true; } + public override bool Visit(SqlAllScalarExpression first, SqlObject secondAsObject) + { + if (!(secondAsObject is SqlAllScalarExpression second)) + { + return false; + } + + if (!Equals(first.Subquery, second.Subquery)) + { + return false; + } + + return true; + } + public override bool Visit(SqlArrayCreateScalarExpression first, SqlObject secondAsObject) { if (!(secondAsObject is SqlArrayCreateScalarExpression second)) diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs index a5f11d45c3..dfbab84bc0 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs @@ -12,6 +12,7 @@ internal sealed class SqlObjectHasher : SqlObjectVisitor public static readonly SqlObjectHasher Singleton = new SqlObjectHasher(true); private const int SqlAliasedCollectionExpressionHashCode = 1202039781; + private const int SqlAllScalarExpressionHashCode = 1369048120; private const int SqlArrayCreateScalarExpressionHashCode = 1760950661; private const int SqlArrayIteratorCollectionExpressionHashCode = -468874086; private const int SqlArrayScalarExpressionHashCode = -1093553293; @@ -119,6 +120,13 @@ public override int Visit(SqlAliasedCollectionExpression sqlAliasedCollectionExp return hashCode; } + public override int Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + int hashCode = SqlAllScalarExpressionHashCode; + hashCode = CombineHashes(hashCode, sqlAllScalarExpression.Subquery.Accept(this)); + return hashCode; + } + public override int Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { int hashCode = SqlArrayCreateScalarExpressionHashCode; diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs index 7fa52c4437..5e6faaef45 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs @@ -44,6 +44,11 @@ public override SqlObject Visit(SqlAliasedCollectionExpression sqlAliasedCollect sqlAliasedCollectionExpression.Alias.Accept(this) as SqlIdentifier); } + public override SqlObject Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + return SqlExistsScalarExpression.Create(sqlAllScalarExpression.Subquery.Accept(this) as SqlQuery); + } + public override SqlObject Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { List items = new List(); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs index c4d3dfa68d..75076e512c 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs @@ -39,6 +39,14 @@ public override void Visit(SqlAliasedCollectionExpression sqlAliasedCollectionEx } } + public override void Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + this.writer.Write("ALL"); + this.WriteStartContext("("); + sqlAllScalarExpression.Subquery.Accept(this); + this.WriteEndContext(")"); + } + public override void Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { int numberOfItems = sqlArrayCreateScalarExpression.Items.Count(); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs index ada48254b6..d8d8899395 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs @@ -14,6 +14,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors abstract class SqlObjectVisitor { public abstract void Visit(SqlAliasedCollectionExpression sqlObject); + public abstract void Visit(SqlAllScalarExpression sqlObject); public abstract void Visit(SqlArrayCreateScalarExpression sqlObject); public abstract void Visit(SqlArrayIteratorCollectionExpression sqlObject); public abstract void Visit(SqlArrayScalarExpression sqlObject); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs index eda7022f3b..3ba9878ae6 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs @@ -14,6 +14,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors abstract class SqlObjectVisitor { public abstract TOutput Visit(SqlAliasedCollectionExpression sqlObject, TArg input); + public abstract TOutput Visit(SqlAllScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlArrayCreateScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlArrayIteratorCollectionExpression sqlObject, TArg input); public abstract TOutput Visit(SqlArrayScalarExpression sqlObject, TArg input); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs index 08d8b7ef10..6f0ce75e99 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs @@ -14,6 +14,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors abstract class SqlObjectVisitor { public abstract TResult Visit(SqlAliasedCollectionExpression sqlObject); + public abstract TResult Visit(SqlAllScalarExpression sqlObject); public abstract TResult Visit(SqlArrayCreateScalarExpression sqlObject); public abstract TResult Visit(SqlArrayIteratorCollectionExpression sqlObject); public abstract TResult Visit(SqlArrayScalarExpression sqlObject); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs index 1e1770403b..8e6e75b7f0 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors #endif abstract class SqlScalarExpressionVisitor { + public abstract void Visit(SqlAllScalarExpression scalarExpression); public abstract void Visit(SqlArrayCreateScalarExpression scalarExpression); public abstract void Visit(SqlArrayScalarExpression scalarExpression); public abstract void Visit(SqlBetweenScalarExpression scalarExpression); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs index 3862aaab40..ff5cdbc019 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors #endif abstract class SqlScalarExpressionVisitor { + public abstract TOutput Visit(SqlAllScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlArrayCreateScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlArrayScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlBetweenScalarExpression scalarExpression, TArg input); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs index 1ca9150582..bdc7b5f04f 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.SqlObjects.Visitors #endif abstract class SqlScalarExpressionVisitor { + public abstract TResult Visit(SqlAllScalarExpression scalarExpression); public abstract TResult Visit(SqlArrayCreateScalarExpression scalarExpression); public abstract TResult Visit(SqlArrayScalarExpression scalarExpression); public abstract TResult Visit(SqlBetweenScalarExpression scalarExpression); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.All.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.All.xml new file mode 100644 index 0000000000..4df32ccb12 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.All.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.All.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.All.xml new file mode 100644 index 0000000000..70040beaf4 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.All.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index ef7e193dbf..dc5f2c8e41 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -1,4 +1,4 @@ - + true @@ -174,6 +174,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs index f0ee3beb3d..ca162fc467 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs @@ -55,6 +55,12 @@ public override bool Visit(SqlSelectStarSpec selectSpec) private sealed class AggregateScalarExpressionDetector : SqlScalarExpressionVisitor { public static readonly AggregateScalarExpressionDetector Singleton = new AggregateScalarExpressionDetector(); + + public override bool Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } public override bool Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs index 15411612f1..1ce82d3c98 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs @@ -79,6 +79,12 @@ public AggregateScalarExpressionTransformer(IEnumerable dataSourc this.dataSource = dataSource; } + public override SqlScalarExpression Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return sqlAllScalarExpression; + } + public override SqlScalarExpression Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) { List items = new List(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs index 2274c876a5..2a671f2568 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs @@ -24,6 +24,54 @@ private ScalarExpressionEvaluator() { } + public override CosmosElement Visit( + SqlAllScalarExpression scalarExpression, + CosmosElement document) + { + // We evaluate the ALL expression by constructing an equivalent EXISTS and evaluating that. + // ALL ( Filter Expression ) ==> NOT EXISTS ( NOT Filter Expression ) + + // If there is is no filter expression, then an equivalent filter expression of just true is created. + SqlScalarExpression filterExpression; + if (scalarExpression.Subquery.WhereClause == null) + { + SqlLiteral trueLiteral = SqlBooleanLiteral.Create(true); + filterExpression = SqlLiteralScalarExpression.Create(trueLiteral); + } + else + { + filterExpression = scalarExpression.Subquery.WhereClause.FilterExpression; + } + + // Create a NOT unary with filter expression. + SqlUnaryScalarExpression negatedFilterExpression = SqlUnaryScalarExpression.Create( + SqlUnaryScalarOperatorKind.Not, + filterExpression); + + // Create new where clause with negated filter expression. + SqlWhereClause newWhereClause = SqlWhereClause.Create(negatedFilterExpression); + + // create new subquery with new where clause. + SqlQuery newSqlQuery = SqlQuery.Create( + scalarExpression.Subquery.SelectClause, + scalarExpression.Subquery.FromClause, + newWhereClause, + scalarExpression.Subquery.GroupByClause, + scalarExpression.Subquery.OrderByClause, + scalarExpression.Subquery.OffsetLimitClause); + + // Create an exists expression with new subquery. + SqlExistsScalarExpression newExistsScalarExpression = SqlExistsScalarExpression.Create(newSqlQuery); + + // Create a not unary with the exists expression. + SqlUnaryScalarExpression negatedExistsExpression = SqlUnaryScalarExpression.Create( + SqlUnaryScalarOperatorKind.Not, + newExistsScalarExpression); + + // Visit the equivalent NOT EXISTS expression. + return this.Visit(negatedExistsExpression, document); + } + public override CosmosElement Visit( SqlArrayCreateScalarExpression scalarExpression, CosmosElement document) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs index ec02c45bde..ba45092faa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs @@ -631,6 +631,11 @@ public GroupByProjectionScalarExpressionVisitor(IReadOnlyList inputs = new List() + { + CreateInput( + description: "ALL in an SqlSelectItem as an alias", + query: "SELECT 1 AS ALL"), + CreateInput( + description: "ALL in an AliasedCollectionExpression as an alias", + query: "SELECT * " + + "FROM (SELECT VALUE 1) AS ALL"), + CreateInput( + description: "ALL in an ArrayIteratorCollectionExpression", + query: "SELECT * " + + "FROM ALL IN (SELECT VALUE 1)"), + CreateInput( + description: "ALL in an InputPathCollection and IdentifierPathExpression", + query: "SELECT * " + + "FROM ALL.ALL"), + CreateInput( + description: "ALL in a PropertyRefScalarExpression", + query: "SELECT ALL"), + CreateInput( + description: "ALL in a PropertyRefScalarExpression as child", + query: "SELECT c.ALL"), + CreateInput( + description: "ALL in a PropertyRefScalarExpression as parent and child", + query: "SELECT ALL.ALL"), + CreateInput( + description: "ALL in a function call", + query: "SELECT ALL(1, 2)"), + CreateInput( + description: "ALL in a UDF function call", + query: "SELECT udf.ALL(1, 2)"), + CreateInput( + description: "ALL in every possible grammar rule at the same time", + query: "SELECT ALL(1, 2) AS ALL " + + "FROM ALL IN (SELECT ALL.ALL) " + + "WHERE ALL( " + + " SELECT ALL " + + " FROM (SELECT udf.ALL(1, 2)) AS ALL " + + " WHERE ALL( SELECT VALUE 1) " + + ")") + + }; + + this.ExecuteTestSuite(inputs); + } + + public static SqlParserBaselineTestInput CreateInput(string description, string query) + { + return new SqlParserBaselineTestInput(description, query); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs index 7f0ec89943..2faed74686 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs @@ -8,6 +8,38 @@ [TestClass] public sealed class ScalarExpressionSqlParserBaselineTests : SqlParserBaselineTests { + [TestMethod] + public void All() + { + List inputs = new List() + { + // Positive + CreateInput(description: "Basic", scalarExpression: "ALL(SELECT *)"), + CreateInput(description: "case insensitive", scalarExpression: "aLl(SELECT *)"), + CreateInput(description: "nested", scalarExpression:"ALL( SELECT * WHERE ALL( SELECT *))"), + CreateInput( + description: "multiple nested", + scalarExpression: + "ALL( " + + " SELECT * " + + " WHERE ALL( " + + " SELECT *" + + " WHERE ALL(" + + " SELECT *" + + " WHERE ALL(" + + " SELECT VALUE 1" + + " )" + + " )" + + " )" + + ")"), + + // Negative + CreateInput(description: "No closing parens", scalarExpression: "ALL(SELECT *") + }; + + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void ArrayCreate() { From 07b34e6213a628f9580717d198faeb7268c8ce80 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Mon, 28 Nov 2022 11:50:57 -0800 Subject: [PATCH 025/337] Release: Adds API contracts for 3.31.2-preview (#3586) --- .../contracts/API_3.31.2-preview.txt | 1526 +++++++++++++++++ 1 file changed, 1526 insertions(+) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.31.2-preview.txt diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.31.2-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.31.2-preview.txt new file mode 100644 index 0000000000..e299887d03 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.31.2-preview.txt @@ -0,0 +1,1526 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode FullFidelity { get; } + public static ChangeFeedMode Incremental { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} From 531864605930ad4ac7eb405889affb21f231fcc8 Mon Sep 17 00:00:00 2001 From: Vivek Ravindran Date: Tue, 29 Nov 2022 06:38:22 -0800 Subject: [PATCH 026/337] [Internal] sccignore: Adds a .sccignore file to apply an exception for artifacts configuration issues (#3589) --- .sscignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .sscignore diff --git a/.sscignore b/.sscignore new file mode 100644 index 0000000000..1558a1ea7b --- /dev/null +++ b/.sscignore @@ -0,0 +1,3 @@ +{ +"cfs" : ["CFS0011"] +} \ No newline at end of file From 28318b0fe2cbfceb80276574f131f6b79f4b64ed Mon Sep 17 00:00:00 2001 From: Prasad Ullal <36418906+prasadu-microsoft@users.noreply.github.com> Date: Thu, 1 Dec 2022 08:24:15 -0800 Subject: [PATCH 027/337] [Internal] PermissionTests: Adds CosmosPermissionTests Coverage (#3593) * Ensures that both Direct and Gateway connection modes are tested * Validates that container read works with PermissionMode.Read (test was previously only validating that Delete was blocked - i.e. the negative case). --- .../CosmosPermissionTests.cs | 100 ++++++++++++++---- 1 file changed, 80 insertions(+), 20 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs index 531757c3ba..003ca8690b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs @@ -107,8 +107,15 @@ public async Task CRUDTest() } [TestMethod] - public async Task ContainerResourcePermissionTest() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task ContainerResourcePermissionTest(ConnectionMode mode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = mode, + }; + //create user string userId = Guid.NewGuid().ToString(); UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); @@ -121,7 +128,7 @@ public async Task ContainerResourcePermissionTest() ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(containerId, "/id"); Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); Container container = containerResponse.Container; - + //create permission string permissionId = Guid.NewGuid().ToString(); PermissionProperties permissionProperties = new PermissionProperties(permissionId, PermissionMode.Read, container); @@ -131,9 +138,18 @@ public async Task ContainerResourcePermissionTest() Assert.AreEqual(permissionId, permission.Id); Assert.AreEqual(permissionProperties.PermissionMode, permission.PermissionMode); - //delete resource with PermissionMode.Read - using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: null, resourceToken: permission.Token)) + using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions, resourceToken: permission.Token)) { + Container readContainerRef = tokenCosmosClient.GetContainer(this.cosmosDatabase.Id, containerId); + + //read resource with PermissionMode.Read + using FeedIterator feedIterator = readContainerRef.GetItemQueryIterator("SELECT * FROM c"); + while (feedIterator.HasMoreResults) + { + _ = await feedIterator.ReadNextAsync(); + } + + //delete resource with PermissionMode.Read try { ContainerResponse response = await tokenCosmosClient @@ -147,14 +163,14 @@ public async Task ContainerResourcePermissionTest() Assert.AreEqual(HttpStatusCode.Forbidden, ex.StatusCode); } } - + //update permission to PermissionMode.All permissionProperties = new PermissionProperties(permissionId, PermissionMode.All, container); permissionResponse = await user.GetPermission(permissionId).ReplaceAsync(permissionProperties); permission = permissionResponse.Resource; //delete resource with PermissionMode.All - using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: null, resourceToken: permission.Token)) + using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions, resourceToken: permission.Token)) { ContainerResponse response = await tokenCosmosClient .GetDatabase(this.cosmosDatabase.Id) @@ -284,8 +300,15 @@ await container.CreateItemAsync( } [TestMethod] - public async Task ItemResourcePermissionTest() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task ItemResourcePermissionTest(ConnectionMode connectionMode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode + }; + //create user string userId = Guid.NewGuid().ToString(); UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); @@ -313,13 +336,15 @@ public async Task ItemResourcePermissionTest() Assert.AreEqual(permissionId, permission.Id); Assert.AreEqual(permissionProperties.PermissionMode, permission.PermissionMode); - //delete resource with PermissionMode.Read - using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: null, resourceToken: permission.Token)) + using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: cosmosClientOptions, resourceToken: permission.Token)) { Container tokenContainer = tokenCosmosClient.GetContainer(this.cosmosDatabase.Id, containerId); + + //read resource with PermissionMode.Read ItemResponse readPermissionItem = await tokenContainer.ReadItemAsync(itemId, partitionKey); Assert.AreEqual(itemId, readPermissionItem.Resource.id.ToString()); + //delete resource with PermissionMode.Read try { ItemResponse response = await tokenContainer.DeleteItemAsync( @@ -340,7 +365,7 @@ public async Task ItemResourcePermissionTest() permission = permissionResponse.Resource; //delete resource with PermissionMode.All - using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: null, resourceToken: permission.Token)) + using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: cosmosClientOptions, resourceToken: permission.Token)) { using (FeedIterator feed = tokenCosmosClient .GetDatabase(this.cosmosDatabase.Id) @@ -357,8 +382,15 @@ public async Task ItemResourcePermissionTest() } [TestMethod] - public async Task EnsureUnauthorized_ThrowsCosmosClientException() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task EnsureUnauthorized_ThrowsCosmosClientException(ConnectionMode connectionMode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode + }; + string authKey = ConfigurationManager.AppSettings["MasterKey"]; string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; @@ -367,21 +399,32 @@ public async Task EnsureUnauthorized_ThrowsCosmosClientException() using CosmosClient cosmosClient = new CosmosClient( endpoint, - authKey); + authKey, + cosmosClientOptions); CosmosException exception = await Assert.ThrowsExceptionAsync(() => cosmosClient.GetContainer("test", "test").ReadItemAsync("test", new PartitionKey("test"))); Assert.AreEqual(HttpStatusCode.Unauthorized, exception.StatusCode); } [TestMethod] - public async Task EnsureUnauthorized_ThrowsCosmosClientException_ReadAccountAsync() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task EnsureUnauthorized_ThrowsCosmosClientException_ReadAccountAsync(ConnectionMode connectionMode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode + }; + string authKey = ConfigurationManager.AppSettings["MasterKey"]; string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; // Take the key and change some middle character authKey = authKey.Replace("m", "M"); - CosmosClient cosmosClient = new CosmosClient(endpoint, authKey); + using CosmosClient cosmosClient = new CosmosClient( + endpoint, + authKey, + cosmosClientOptions); CosmosException exception1 = await Assert.ThrowsExceptionAsync(() => cosmosClient.ReadAccountAsync()); Assert.AreEqual(HttpStatusCode.Unauthorized, exception1.StatusCode); @@ -389,33 +432,50 @@ public async Task EnsureUnauthorized_ThrowsCosmosClientException_ReadAccountAsyn } [TestMethod] - public async Task EnsureUnauthorized_Writes_ThrowsCosmosClientException() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task EnsureUnauthorized_Writes_ThrowsCosmosClientException(ConnectionMode connectionMode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode + }; + string authKey = ConfigurationManager.AppSettings["MasterKey"]; string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; - + // Take the key and change some middle character authKey = authKey.Replace("m", "M"); using CosmosClient cosmosClient = new CosmosClient( endpoint, - authKey); + authKey, + cosmosClientOptions); + CosmosException exception = await Assert.ThrowsExceptionAsync(() => cosmosClient.GetContainer("test", "test").CreateItemAsync(new { id = "test" })); Assert.AreEqual(HttpStatusCode.Unauthorized, exception.StatusCode); } [TestMethod] - public async Task EnsureUnauthorized_Query_ThrowsCosmosClientException() + [DataRow(ConnectionMode.Gateway)] + [DataRow(ConnectionMode.Direct)] + public async Task EnsureUnauthorized_Query_ThrowsCosmosClientException(ConnectionMode connectionMode) { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode + }; + string authKey = ConfigurationManager.AppSettings["MasterKey"]; string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; - + // Take the key and change some middle character authKey = authKey.Replace("m", "M"); using CosmosClient cosmosClient = new CosmosClient( endpoint, - authKey); + authKey, + cosmosClientOptions); using FeedIterator iterator = cosmosClient.GetContainer("test", "test").GetItemQueryIterator("SELECT * FROM c"); From a34bac772e11642b8855251467d3f5a36a6c1fb8 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 6 Dec 2022 01:02:13 +0530 Subject: [PATCH 028/337] [Internal] AI Integration: Refactors to Operation prefix and add tests (#3583) * add tests for otel and custome listener * clean up * null pointer fix * fix tets * handle event generation also at operation level * added documentation * wip * change event sourcename * rename event Name Co-authored-by: Sourabh Jain --- .../OpenTelemetry/CosmosDbEventSource.cs | 6 +- .../OpenTelemetryAttributeKeys.cs | 2 +- .../OpenTelemetryCoreRecorder.cs | 3 + .../OpenTelemetryRecorderFactory.cs | 9 + ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++++++------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 12 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++-- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 7 +- .../Tracing/AssertActivity.cs | 90 +++++++ ...TelemetryListener.cs => CustomListener.cs} | 249 ++++++++---------- .../Tracing/CustomOtelExporter.cs | 57 ++++ .../EndToEndTraceWriterBaselineTests.cs | 109 +++++--- 19 files changed, 532 insertions(+), 386 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/{OpenTelemetryListener.cs => CustomListener.cs} (61%) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index 6700697914..af1115367f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -8,10 +8,14 @@ namespace Microsoft.Azure.Cosmos.Telemetry using global::Azure.Core.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; + /// + /// This class is used to generate events with Azure.Cosmos.Operation Source Name + /// [EventSource(Name = EventSourceName)] internal sealed class CosmosDbEventSource : AzureEventSource { - private const string EventSourceName = OpenTelemetryAttributeKeys.DiagnosticNamespace; + internal const string EventSourceName = "Azure-Cosmos-Operation-Request-Diagnostics"; + private static CosmosDbEventSource Singleton { get; } = new CosmosDbEventSource(); private CosmosDbEventSource() diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 801824b791..eb8382c0b0 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -9,7 +9,7 @@ internal sealed class OpenTelemetryAttributeKeys // Azure defaults public const string DiagnosticNamespace = "Azure.Cosmos"; public const string ResourceProviderNamespace = "Microsoft.DocumentDB"; - public const string OperationPrefix = "Cosmos"; + public const string OperationPrefix = "Operation"; // Common database attributes public const string DbSystemName = "db.system"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index e0b47e744f..32e4fde67f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -8,6 +8,9 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System.Collections.Generic; using global::Azure.Core.Pipeline; + /// + /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 + /// internal struct OpenTelemetryCoreRecorder : IDisposable { private const string CosmosDb = "cosmosdb"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 88f149d608..2cd6e3a481 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -6,8 +6,14 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using global::Azure.Core.Pipeline; + /// + /// This class is used to generate Activities with Azure.Cosmos.Operation Source Name + /// internal static class OpenTelemetryRecorderFactory { + /// + /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once + /// private static DiagnosticScopeFactory ScopeFactory { get; set; } public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, @@ -22,11 +28,14 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, ScopeFactory = new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, isActivityEnabled: true); + + // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = OpenTelemetryRecorderFactory .ScopeFactory .CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); + // Record values only when we have a valid Diagnostic Scope if (scope.IsEnabled) { return new OpenTelemetryCoreRecorder( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index ffce1a6bf4..f650f1e6f5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Cosmos.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index e999759bd3..c10633d3fa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -134,16 +134,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -292,16 +292,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -450,16 +450,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -608,16 +608,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -766,16 +766,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -924,16 +924,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1082,16 +1082,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1240,16 +1240,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1398,16 +1398,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1556,16 +1556,16 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2288,7 +2288,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 2d747e9e45..e4fa3665a8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -952,11 +952,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1569,11 +1569,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2167,11 +2167,11 @@ } ] }]]> - Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2785,11 +2785,11 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3066,8 +3066,8 @@ } ] }]]> - Cosmos.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 5b29ba3737..3825735788 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -107,8 +107,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -207,8 +207,8 @@ } ] }]]> - Cosmos.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 7dea567de8..80dbbfb7f1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -148,7 +148,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -391,7 +391,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -616,7 +616,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -873,7 +873,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1194,7 +1194,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1348,7 +1348,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 937daa7a49..5b54a51e31 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -574,10 +574,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1180,10 +1180,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1767,10 +1767,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2374,10 +2374,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3048,10 +3048,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3644,10 +3644,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4260,10 +4260,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index ee1302e06e..22feeace3c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -536,10 +536,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1104,10 +1104,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1653,10 +1653,10 @@ } ] }]]> - Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2222,10 +2222,10 @@ } ] }]]> - Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 9558168b76..c6a9fcee7f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -542,12 +542,12 @@ } ] }]]> - Cosmos.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1112,7 +1112,7 @@ } ] }]]> - Cosmos.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index a1b5ceb966..5a764d9525 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -89,7 +89,7 @@ } ] }]]> - Cosmos.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -178,7 +178,7 @@ } ] }]]> - Cosmos.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -275,7 +275,7 @@ } ] }]]> - Cosmos.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -367,7 +367,7 @@ } ] }]]> - Cosmos.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index dfe617f632..63edd0154e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -109,7 +109,7 @@ } ] }]]> - Cosmos.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -203,7 +203,7 @@ } ] }]]> - Cosmos.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -310,7 +310,7 @@ } ] }]]> - Cosmos.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -406,7 +406,7 @@ } ] }]]> - Cosmos.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 9849750f54..10e0462cef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -1,4 +1,4 @@ - + true true @@ -42,11 +42,12 @@ - + + - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs new file mode 100644 index 0000000000..f62d89e016 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -0,0 +1,90 @@ +namespace Microsoft.Azure.Cosmos.Tracing +{ + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Tests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + + internal static class AssertActivity + { + public static void IsValid(Activity activity) + { + Assert.IsTrue(activity.OperationName == activity.DisplayName); + Assert.IsNotNull(activity.GetTagItem("db.cosmosdb.connection_mode")); + if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) + { + Assert.AreEqual(ActivityKind.Internal, activity.Kind); + } + else + { + Assert.AreEqual(ActivityKind.Client, activity.Kind); + } + + IList expectedTags = new List + { + "az.namespace", + "kind", + "db.system", + "db.name", + "db.operation", + "net.peer.name", + "db.cosmosdb.client_id", + "db.cosmosdb.machine_id", + "db.cosmosdb.user_agent", + "db.cosmosdb.connection_mode", + "db.cosmosdb.operation_type", + "db.cosmosdb.container", + "db.cosmosdb.request_content_length_bytes", + "db.cosmosdb.response_content_length_bytes", + "db.cosmosdb.status_code", + "db.cosmosdb.sub_status_code", + "db.cosmosdb.request_charge", + "db.cosmosdb.regions_contacted", + "db.cosmosdb.retry_count", + "db.cosmosdb.item_count", + "db.cosmosdb.request_diagnostics", + "exception.type", + "exception.message", + "exception.stacktrace" + }; + + foreach (KeyValuePair actualTag in activity.Tags) + { + Assert.IsTrue(expectedTags.Contains(actualTag.Key), $"{actualTag.Key} is not allowed for {activity.OperationName}"); + + AssertActivity.AssertDatabaseAndContainerName(activity.OperationName, actualTag); + } + } + + public static void AreEqualAcrossListeners() + { + Assert.AreEqual( + JsonConvert.SerializeObject(CustomListener.CollectedActivities.OrderBy(x => x.Id)), + JsonConvert.SerializeObject(CustomOtelExporter.CollectedActivities.OrderBy(x => x.Id))); + } + + private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) + { + IList exceptionsForContainerAttribute = new List + { + "Operation.CreateDatabaseAsync", + "Operation.ReadAsync", + "Operation.DeleteAsync" + }; + + if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || + (tag.Key == OpenTelemetryAttributeKeys.DbName)) + { + Assert.IsNotNull(tag.Value, $"{tag.Key} is 'null' for {name} operation"); + } + else if (tag.Key == OpenTelemetryAttributeKeys.ContainerName && exceptionsForContainerAttribute.Contains(name)) + { + Assert.IsNull(tag.Value, $"{tag.Key} is '{tag.Value}' for {name} operation"); + } + } + + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs similarity index 61% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 05763f0bdb..5e86ee7270 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/OpenTelemetryListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -12,62 +12,61 @@ namespace Microsoft.Azure.Cosmos.Tests using System.Linq; using System.Reflection; using System.Text; - using System.Threading; - using Microsoft.Azure.Cosmos.Telemetry; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - public class OpenTelemetryListener : - EventListener, - IObserver>, + using System.Text.RegularExpressions; + using Microsoft.Azure.Cosmos.Tracing; + + /// + /// It is a custom listener for Activities and Event. It is used to validate the Activities generated by cosmosDb SDK. + /// + public class CustomListener : + EventListener, // Override Event Listener to capture Event source events + IObserver>, // Override IObserver to capture Activity events IObserver, IDisposable { - private readonly string EventSourceName; - private readonly Func sourceNameFilter; - private readonly AsyncLocal collectThisStack; - - private List subscriptions = new List(); - private readonly Action scopeStartCallback; - - private List Scopes { get; } = new List(); - - private ConcurrentBag GeneratedActivities { set; get; } - private ConcurrentBag GeneratedEvents { set; get; } - - public OpenTelemetryListener(string name, bool asyncLocal = false, Action scopeStartCallback = default) - : this(n => n == name, asyncLocal, scopeStartCallback) + private readonly string eventName; + + private List subscriptions = new(); + private List Scopes { get; } = new(); + + public static ConcurrentBag CollectedActivities { private set; get; } = new(); + private static ConcurrentBag CollectedEvents { set; get; } = new(); + + public CustomListener(string name, string eventName) + : this(n => Regex.Match(n, name).Success, eventName) { - this.EventSourceName = name; } - public OpenTelemetryListener(Func filter, bool asyncLocal = false, Action scopeStartCallback = default) + public CustomListener(Func filter, string eventName) { - if (asyncLocal) - { - this.collectThisStack = new AsyncLocal { Value = true }; - } this.sourceNameFilter = filter; - this.scopeStartCallback = scopeStartCallback; - - this.GeneratedActivities = new ConcurrentBag(); - this.GeneratedEvents = new ConcurrentBag(); - + this.eventName = eventName; + DiagnosticListener.AllListeners.Subscribe(this); } + /// + /// IObserver Override + /// public void OnCompleted() { + // Unimplemented Method } + /// + /// IObserver Override + /// public void OnError(Exception error) { + // Unimplemented Method } + /// + /// IObserver Override + /// public void OnNext(KeyValuePair value) { - if (this.collectThisStack?.Value == false) return; - lock (this.Scopes) { // Check for disposal @@ -92,7 +91,6 @@ public void OnNext(KeyValuePair value) }; this.Scopes.Add(scope); - this.scopeStartCallback?.Invoke(scope); } else if (value.Key.EndsWith(stopSuffix)) { @@ -101,7 +99,9 @@ public void OnNext(KeyValuePair value) { if (producedDiagnosticScope.Activity.Id == Activity.Current.Id) { - this.RecordAttributes(producedDiagnosticScope.Name, producedDiagnosticScope.Activity.Tags); + AssertActivity.IsValid(producedDiagnosticScope.Activity); + + CustomListener.CollectedActivities.Add(producedDiagnosticScope.Activity); producedDiagnosticScope.IsCompleted = true; return; @@ -128,142 +128,51 @@ public void OnNext(KeyValuePair value) } } - private void RecordAttributes(string name, IEnumerable> tags) - { - StringBuilder builder = new StringBuilder(); - builder.Append("") - .Append("") - .Append(name) - .Append(""); - - OpenTelemetryListener.AssertData(name, tags); - - foreach (KeyValuePair tag in tags) - { - builder - .Append("") - .Append(tag.Key) - .Append(""); - } - builder.Append(""); - this.GeneratedActivities.Add(builder.ToString()); - } - - private static void AssertData(string name, IEnumerable> tags) - { - IList allowedAttributes = new List - { - "az.namespace", - "kind", - "db.system", - "db.name", - "db.operation", - "net.peer.name", - "db.cosmosdb.client_id", - "db.cosmosdb.machine_id", - "db.cosmosdb.user_agent", - "db.cosmosdb.connection_mode", - "db.cosmosdb.operation_type", - "db.cosmosdb.container", - "db.cosmosdb.request_content_length_bytes", - "db.cosmosdb.response_content_length_bytes", - "db.cosmosdb.status_code", - "db.cosmosdb.sub_status_code", - "db.cosmosdb.request_charge", - "db.cosmosdb.regions_contacted", - "db.cosmosdb.retry_count", - "db.cosmosdb.item_count", - "db.cosmosdb.request_diagnostics", - "exception.type", - "exception.message", - "exception.stacktrace" - }; - - foreach (KeyValuePair tag in tags) - { - Assert.IsTrue(allowedAttributes.Contains(tag.Key), $"{tag.Key} is not allowed for {name}"); - - OpenTelemetryListener.AssertDatabaseAndContainerName(name, tag); - } - } - - private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) - { - IList exceptionsForContainerAttribute = new List - { - "Cosmos.CreateDatabaseAsync", - "Cosmos.ReadAsync", - "Cosmos.DeleteAsync", - "Cosmos.DeleteStreamAsync" - }; - - if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || - (tag.Key == OpenTelemetryAttributeKeys.DbName)) - { - Assert.IsNotNull(tag.Value, $"{tag.Key} is 'null' for {name} operation"); - } - else if (tag.Key == OpenTelemetryAttributeKeys.ContainerName && exceptionsForContainerAttribute.Contains(name)) - { - Assert.IsNull(tag.Value, $"{tag.Key} is '{tag.Value}' for {name} operation"); - } - } - - public List GetRecordedAttributes() - { - List outputList = new List(); - if(this.GeneratedActivities != null && this.GeneratedActivities.Count > 0) - { - outputList.AddRange(this.GeneratedActivities); - - } - if (this.GeneratedEvents != null && this.GeneratedEvents.Count > 0) - { - outputList.AddRange(this.GeneratedEvents); - } - - return outputList; - } - - public void ResetAttributes() - { - this.GeneratedActivities = new ConcurrentBag(); - this.GeneratedEvents = new ConcurrentBag(); - } - + /// + /// IObserver Override + /// public void OnNext(DiagnosticListener value) { if (this.sourceNameFilter(value.Name) && this.subscriptions != null) { lock (this.Scopes) { - if (this.subscriptions != null) - { - this.subscriptions.Add(value.Subscribe(this)); - } + this.subscriptions?.Add(value.Subscribe(this)); } } } + /// + /// EventListener Override + /// protected override void OnEventSourceCreated(EventSource eventSource) { - if (eventSource.Name == this.EventSourceName) + if (eventSource != null && eventSource.Name.Equals(this.eventName)) { - this.EnableEvents(eventSource, EventLevel.Informational); + this.EnableEvents(eventSource, EventLevel.Informational); // Enable information level events } } + /// + /// EventListener Override + /// protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder builder = new StringBuilder(); + Console.WriteLine(eventData.Payload[0].ToString()); builder.Append("") .Append("Ideally, this should contain request diagnostics but request diagnostics is " + "subject to change with each request as it contains few unique id. " + "So just putting this tag with this static text to make sure event is getting generated" + " for each test.") .Append(""); - this.GeneratedEvents.Add(builder.ToString()); + CustomListener.CollectedEvents.Add(builder.ToString()); } - + + /// + /// Dispose Override + /// + /// public override void Dispose() { base.Dispose(); @@ -310,6 +219,54 @@ public override void Dispose() this.ResetAttributes(); } + + private string GenerateTagForBaselineTest(Activity activity) + { + + StringBuilder builder = new StringBuilder(); + builder.Append("") + .Append("") + .Append(activity.OperationName) + .Append(""); + + foreach (KeyValuePair tag in activity.Tags) + { + builder + .Append("") + .Append(tag.Key) + .Append(""); + } + builder.Append(""); + + return builder.ToString(); + } + + public List GetRecordedAttributes() + { + List generatedActivityTagsForBaselineXmls = new(); + List collectedActivities = new List(CustomListener.CollectedActivities); + + collectedActivities.ForEach(activity => generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity))); + + List outputList = new List(); + if(generatedActivityTagsForBaselineXmls != null && generatedActivityTagsForBaselineXmls.Count > 0) + { + outputList.AddRange(generatedActivityTagsForBaselineXmls); + + } + if (CustomListener.CollectedEvents != null && CustomListener.CollectedEvents.Count > 0) + { + outputList.AddRange(CustomListener.CollectedEvents); + } + + return outputList; + } + + public void ResetAttributes() + { + CustomListener.CollectedEvents = new(); + CustomListener.CollectedActivities = new(); + } public class ProducedDiagnosticScope { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs new file mode 100644 index 0000000000..1f6c335fdd --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -0,0 +1,57 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tracing +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using OpenTelemetry; + using OpenTelemetry.Trace; + + /// + /// It is a custom exporter for OpenTelemetry. It is used to validate the Activities generated by cosmosDb SDK. + /// As of now, it doesn not capture Events from event Source. + /// + internal class CustomOtelExporter : BaseExporter + { + private readonly string _name; + + public static List CollectedActivities = new List(); + + public CustomOtelExporter(string name = "CustomOtelExporter") + { + this._name = name; + } + + public override ExportResult Export(in Batch batch) + { + // SuppressInstrumentationScope should be used to prevent exporter + // code from generating telemetry and causing live-loop. + using IDisposable scope = SuppressInstrumentationScope.Begin(); + + foreach (Activity activity in batch) + { + AssertActivity.IsValid(activity); + + CollectedActivities.Add(activity); + } + + return ExportResult.Success; + } + } + + internal static class OTelExtensions + { + public static TracerProviderBuilder AddCustomOtelExporter(this TracerProviderBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + return builder.AddProcessor(new SimpleActivityExportProcessor(new CustomOtelExporter())); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index f64d289cfe..b91fc76b8b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -19,8 +19,10 @@ using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; + using OpenTelemetry; using Telemetry; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; + using OpenTelemetry.Trace; [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] @@ -33,15 +35,26 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests builder @@ -90,7 +103,7 @@ public static async Task ClassInitAsync(TestContext context) await container.CreateItemAsync(JToken.Parse(cosmosObject.ToString())); } - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } [ClassCleanup()] @@ -101,13 +114,25 @@ public static async Task ClassCleanupAsync() await EndToEndTraceWriterBaselineTests.database.DeleteStreamAsync(); } + oTelTracerProvider?.Dispose(); testListener?.Dispose(); + + await Task.Delay(5000); + } + + private static void AssertAndResetActivityInformation() + { + AssertActivity.AreEqualAcrossListeners(); + + CustomOtelExporter.CollectedActivities = new(); + testListener.ResetAttributes(); } + [TestMethod] public async Task ReadFeedAsync() { - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); List inputs = new List(); @@ -140,7 +165,7 @@ public async Task ReadFeedAsync() endLineNumber: endLineNumber, oTelActivities: testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -171,7 +196,7 @@ public async Task ReadFeedAsync() endLineNumber: endLineNumber, oTelActivities: testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -202,7 +227,7 @@ public async Task ReadFeedAsync() endLineNumber: endLineNumber, oTelActivities: testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -228,7 +253,7 @@ public async Task ReadFeedAsync() inputs.Add(new Input("ReadFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -270,7 +295,7 @@ public async Task ChangeFeedAsync() inputs.Add(new Input("ChangeFeed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -302,7 +327,7 @@ public async Task ChangeFeedAsync() inputs.Add(new Input("ChangeFeed Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -335,7 +360,7 @@ public async Task ChangeFeedAsync() inputs.Add(new Input("ChangeFeed Public API", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -368,7 +393,7 @@ public async Task ChangeFeedAsync() inputs.Add(new Input("ChangeFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -407,7 +432,8 @@ public async Task ChangeFeedAsync() await processor.StopAsync(); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); + startLineNumber = GetLineNumber(); ChangeFeedEstimator estimator = container.GetChangeFeedEstimator( "test", @@ -428,7 +454,7 @@ public async Task ChangeFeedAsync() inputs.Add(new Input("Change Feed Estimator", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -464,7 +490,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -489,7 +515,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -515,7 +541,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query Public API", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -541,7 +567,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -570,7 +596,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query - Without ServiceInterop", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -598,7 +624,7 @@ public async Task QueryAsync() inputs.Add(new Input("Query Public API with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -626,14 +652,13 @@ public async Task QueryAsync() inputs.Add(new Input("Query Public API Typed with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- this.ExecuteTestSuite(inputs); } - [TestMethod] public async Task ValidateInvalidCredentialsTraceAsync() { @@ -698,7 +723,7 @@ public async Task TypedPointOperationsAsync() inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -716,7 +741,7 @@ public async Task TypedPointOperationsAsync() inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -742,7 +767,7 @@ public async Task TypedPointOperationsAsync() inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -784,7 +809,7 @@ public async Task TypedPointOperationsAsync() inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -819,7 +844,7 @@ public async Task StreamPointOperationsAsync() inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -837,7 +862,7 @@ public async Task StreamPointOperationsAsync() inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -863,7 +888,7 @@ public async Task StreamPointOperationsAsync() inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -908,7 +933,7 @@ public async Task StreamPointOperationsAsync() inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -957,7 +982,7 @@ public async Task PointOperationsExceptionsAsync() inputs.Add(new Input("Point Operation with Request Timeout", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1010,7 +1035,7 @@ public async Task PointOperationsExceptionsAsync() inputs.Add(new Input("Point Operation With Throttle", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1090,7 +1115,7 @@ void interceptor(Uri uri, Documents.ResourceOperation operation, Documents.Docum endLineNumber = GetLineNumber(); inputs.Add(new Input($"Point Operation With Forbidden + Max Count = {maxCount}", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } // Check if the exception message is not growing exponentially @@ -1141,7 +1166,7 @@ void interceptor(Uri uri, Documents.ResourceOperation operation, Documents.Docum inputs.Add(new Input("Point Operation with Service Unavailable", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1192,7 +1217,7 @@ public async Task BatchOperationsAsync() inputs.Add(new Input("Batch Operation", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1243,7 +1268,7 @@ public async Task BulkOperationsAsync() inputs.Add(new Input("Bulk Operation", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); } - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1298,7 +1323,7 @@ public async Task BulkOperationsAsync() inputs.Add(new Input("Bulk Operation With Throttle", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } this.ExecuteTestSuite(inputs); @@ -1330,7 +1355,7 @@ public async Task MiscellanousAsync() inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1349,7 +1374,7 @@ public async Task MiscellanousAsync() inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1390,7 +1415,7 @@ public async Task ReadManyAsync() inputs.Add(new Input("Read Many Stream Api", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- @@ -1405,7 +1430,7 @@ public async Task ReadManyAsync() inputs.Add(new Input("Read Many Typed Api", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); - testListener.ResetAttributes(); + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } //---------------------------------------------------------------- From 6b1fa035cdb50201aa7483cc3774eb0b521e8a47 Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Thu, 15 Dec 2022 12:20:48 -0500 Subject: [PATCH 029/337] [Internal] HttpTimeoutPolicy: Removes Data Plane Writes from being able to be retried (#3607) * data plane writes no longer failover on timeout * removed duplication of test\ --- Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs | 4 ++-- .../CosmosHttpClientCoreTests.cs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs index a3fc51dd91..fa2fc25bf7 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs @@ -36,8 +36,8 @@ public static HttpTimeoutPolicy GetTimeoutPolicy( return HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance; } - //Data Plane Read & Write - if (!HttpTimeoutPolicy.IsMetaData(documentServiceRequest)) + //Data Plane Read + if (!HttpTimeoutPolicy.IsMetaData(documentServiceRequest) && documentServiceRequest.IsReadOnlyRequest) { return HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 67c653498b..3ac919bf83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -258,7 +258,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio Assert.AreEqual(3, count, "Should retry 3 times"); } - + [TestMethod] public async Task HttpTimeoutThrow503TestAsync() { @@ -307,8 +307,8 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio //Data plane read await TestScenarioAsync(HttpMethod.Get, ResourceType.Document, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 3); - //Data plane write - await TestScenarioAsync(HttpMethod.Post, ResourceType.Document, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 1); + //Data plane write (Should throw a 408 OperationCanceledException rather than a 503) + await TestScenarioAsync(HttpMethod.Post, ResourceType.Document, HttpTimeoutPolicyDefault.Instance, typeof(TaskCanceledException), 1); //Meta data read await TestScenarioAsync(HttpMethod.Get, ResourceType.Database, HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, typeof(CosmosException), 3); From 814e72eca593e855838434766596e7bf8945e1b7 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 20 Dec 2022 16:03:20 +0530 Subject: [PATCH 030/337] [Internal] Performance Testing: Adds Distributed Tracing option in benchmarks (#3611) Co-authored-by: Sourabh Jain --- .../Tools/Benchmark/BenchmarkConfig.cs | 5 +++++ Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index dc287c8a4d..590e89297a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -101,6 +101,9 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Enable Client Telemetry")] public bool EnableTelemetry { get; set; } + [Option(Required = false, HelpText = "Enable Distributed Tracing")] + public bool EnableDistributedTracing { get; set; } + [Option(Required = false, HelpText = "Client Telemetry Schedule in Seconds")] public int TelemetryScheduleInSec { get; set; } @@ -219,6 +222,8 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe clientOptions.ConsistencyLevel = (Microsoft.Azure.Cosmos.ConsistencyLevel)Enum.Parse(typeof(Microsoft.Azure.Cosmos.ConsistencyLevel), this.ConsistencyLevel, ignoreCase: true); } + clientOptions.EnableDistributedTracing = this.EnableDistributedTracing; + return new Microsoft.Azure.Cosmos.CosmosClient( this.EndPoint, accountKey, diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh index 2edfb67530..81cafc4a4a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh @@ -54,8 +54,8 @@ sleep 10 #Wait dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithTelemetry --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait -# Open telemetry enabled ReadStreamExistsV3. This is needed to see the impact of open telemetry. -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithOpenTelemetry --enableOpenTelemetry --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk +# Open telemetry enabled ReadStreamExistsV3. This is needed to see the impact of distributed tracing (without listener) +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithDistributedTracingWOListener --enableDistributedTracing --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait #Point read operations From 5c05fbb2d63e632f34831b8f0f200a089623695c Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 4 Jan 2023 21:38:48 +0530 Subject: [PATCH 031/337] [Internal] Benchmark: Refactors code to make Memory Stream capacity configurable (#3624) Co-authored-by: Sourabh Jain --- .../Tools/Benchmark/BenchmarkConfig.cs | 4 +++- .../Tools/Benchmark/JsonHelper.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index 590e89297a..b9235d2232 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -143,7 +143,9 @@ internal void Print() Utility.TeeTraceInformation($"{nameof(BenchmarkConfig)} arguments"); Utility.TeeTraceInformation($"IsServerGC: {GCSettings.IsServerGC}"); Utility.TeeTraceInformation("--------------------------------------------------------------------- "); - Utility.TeeTraceInformation(JsonHelper.ToString(this)); + Utility.TeeTraceInformation(JsonHelper.ToString( + input: this, + capacity: 2048)); Utility.TeeTraceInformation("--------------------------------------------------------------------- "); Utility.TeeTraceInformation(string.Empty); } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/JsonHelper.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/JsonHelper.cs index 3e9da1ef06..6d5bed44d3 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/JsonHelper.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/JsonHelper.cs @@ -17,9 +17,9 @@ internal static class JsonHelper }); private const int DefaultCapacity = 1024; - public static string ToString(T input) + public static string ToString(T input, int capacity = JsonHelper.DefaultCapacity) { - using (MemoryStream stream = JsonHelper.ToStream(input)) + using (MemoryStream stream = JsonHelper.ToStream(input, capacity)) using (StreamReader sr = new StreamReader(stream)) { return sr.ReadToEnd(); @@ -31,15 +31,15 @@ public static T Deserialize(string payload) return JsonConvert.DeserializeObject(payload); } - public static MemoryStream ToStream(T input) + public static MemoryStream ToStream(T input, int capacity = JsonHelper.DefaultCapacity) { - byte[] blob = System.Buffers.ArrayPool.Shared.Rent(JsonHelper.DefaultCapacity); - MemoryStream memStreamPayload = new MemoryStream(blob, 0, JsonHelper.DefaultCapacity, writable: true, publiclyVisible: true); + byte[] blob = System.Buffers.ArrayPool.Shared.Rent(capacity); + MemoryStream memStreamPayload = new MemoryStream(blob, 0, capacity, writable: true, publiclyVisible: true); memStreamPayload.SetLength(0); memStreamPayload.Position = 0; using (StreamWriter streamWriter = new StreamWriter(memStreamPayload, encoding: JsonHelper.DefaultEncoding, - bufferSize: JsonHelper.DefaultCapacity, + bufferSize: capacity, leaveOpen: true)) { using (JsonWriter writer = new JsonTextWriter(streamWriter)) From 73c9e08d2796c64e016fdf80007c0f8c72f8e47b Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 4 Jan 2023 15:37:36 -0500 Subject: [PATCH 032/337] add new LatestVersion changefeed mode that has same behavior as Incremental; renamed FullFidelity to AllVersionsAndDeletes (#3596) --- .../src/ChangeFeed/ChangeFeedMode.cs | 16 +++++++++++++++- .../FullFidelity/ChangeFeedItemChange{T}.cs | 4 ++-- .../FullFidelity/ChangeFeedMetadata.cs | 2 +- .../FullFidelity/ChangeFeedOperationType.cs | 2 +- .../src/Resource/Settings/ChangeFeedPolicy.cs | 2 +- .../FeedToken/ChangeFeedIteratorCoreTests.cs | 14 +++++++------- .../NetworkAttachedDocumentContainerTests.cs | 2 +- .../Contracts/DotNetPreviewSDKAPI.json | 18 ++++++++++++++---- 8 files changed, 42 insertions(+), 18 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs index d64a9942d5..7df0871d74 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs @@ -31,6 +31,20 @@ internal ChangeFeedMode() /// A to receive incremental item changes. public static ChangeFeedMode Incremental => ChangeFeedModeIncremental.Instance; + /// + /// Creates a to receive latest version item changes. + /// + /// + /// Latest version mode includes item creations and updates, not deletions. + /// + /// A to receive latest version item changes. +#if PREVIEW + public +#else + internal +#endif + static ChangeFeedMode LatestVersion => ChangeFeedModeIncremental.Instance; + /// /// Creates a to receive notifications for creations, deletes, as well as all intermediary snapshots for updates. /// @@ -49,6 +63,6 @@ internal ChangeFeedMode() #else internal #endif - static ChangeFeedMode FullFidelity => ChangeFeedModeFullFidelity.Instance; + static ChangeFeedMode AllVersionsAndDeletes => ChangeFeedModeFullFidelity.Instance; } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs index 1a564443bd..deb9c7db87 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos using Newtonsoft.Json; /// - /// The typed response that contains the current, previous, and metadata change feed resource when is initialized to . + /// The typed response that contains the current, previous, and metadata change feed resource when is initialized to . /// /// /// @@ -19,7 +19,7 @@ namespace Microsoft.Azure.Cosmos /// public string status { get; set; } /// } /// - /// ChangeFeedMode changeFeedMode = ChangeFeedMode.FullFidelity; + /// ChangeFeedMode changeFeedMode = ChangeFeedMode.AllVersionsAndDeletes; /// PartitionKey partitionKey = new PartitionKey(@"learning"); /// ChangeFeedStartFrom changeFeedStartFrom = ChangeFeedStartFrom.Now(FeedRange.FromPartitionKey(partitionKey)); /// diff --git a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs index 75abc2ef1e..81b10461f9 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Cosmos using Newtonsoft.Json.Converters; /// - /// The metadata of a change feed resource with is initialized to . + /// The metadata of a change feed resource with is initialized to . /// #if PREVIEW public diff --git a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedOperationType.cs b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedOperationType.cs index 48e70b2260..9144556e91 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedOperationType.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedOperationType.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos using System.Runtime.Serialization; /// - /// The operation type of a change feed resource with is initialized to . Upsert operations will yield or . + /// The operation type of a change feed resource with is initialized to . Upsert operations will yield or . /// #if PREVIEW public diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ChangeFeedPolicy.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ChangeFeedPolicy.cs index e0b6d3ad16..e411d8ea2e 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ChangeFeedPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ChangeFeedPolicy.cs @@ -16,7 +16,7 @@ namespace Microsoft.Azure.Cosmos /// /// The example below creates a new container with a custom change feed policy for full fidelity change feed with a retention window of 5 minutes - so intermediary snapshots of changes as well as deleted documents would be /// available for processing for 5 minutes before they vanish. - /// Processing the change feed with will only be able within this retention window - if you attempt to process a change feed after more + /// Processing the change feed with will only be able within this retention window - if you attempt to process a change feed after more /// than the retention window (5 minutes in this sample) an error (Status Code 400) will be returned. /// It would still be possible to process changes using mode even when configuring a full fidelity change /// feed policy with retention window on the container and when using Incremental mode it doesn't matter whether your are out of the retention window or not. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs index e34bf128fc..b9d179c0c1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs @@ -788,7 +788,7 @@ public async Task ChangeFeedIteratorCore_WithFullFidelityReadFromBeginning() // FF does not work with StartFromBeginning currently, capture error FeedIterator fullFidelityIterator = container.GetChangeFeedIterator( ChangeFeedStartFrom.Beginning(), - ChangeFeedMode.FullFidelity); + ChangeFeedMode.AllVersionsAndDeletes); CosmosException cosmosException = await Assert.ThrowsExceptionAsync(() => fullFidelityIterator.ReadNextAsync()); Assert.AreEqual(HttpStatusCode.BadRequest, cosmosException.StatusCode, "Full Fidelity Change Feed does not work with StartFromBeginning currently."); @@ -829,7 +829,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( // FF does not work with StartFromBeginning currently, so we capture an initial continuation. FeedIterator> fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.Now(), - ChangeFeedMode.FullFidelity, + ChangeFeedMode.AllVersionsAndDeletes, querySpec, null); @@ -862,7 +862,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( // Resume Change Feed and verify we pickup the events where documents matches the query fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.ContinuationToken(initialContinuation), - ChangeFeedMode.FullFidelity, + ChangeFeedMode.AllVersionsAndDeletes, querySpec, null); int detectedEvents = 0; @@ -891,7 +891,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.ContinuationToken(initialContinuation), - ChangeFeedMode.FullFidelity, + ChangeFeedMode.AllVersionsAndDeletes, querySpec, null); detectedEvents = 0; @@ -927,7 +927,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_VerifyingWir string otherId = Guid.NewGuid().ToString(); PartitionKey partitionKey = new PartitionKey(id); - ChangeFeedMode changeFeedMode = ChangeFeedMode.FullFidelity; + ChangeFeedMode changeFeedMode = ChangeFeedMode.AllVersionsAndDeletes; ChangeFeedStartFrom changeFeedStartFrom = ChangeFeedStartFrom.Now(FeedRange.FromPartitionKey(partitionKey)); using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( @@ -1017,7 +1017,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( changeFeedStartFrom: ChangeFeedStartFrom.Now(), - changeFeedMode: ChangeFeedMode.FullFidelity)) + changeFeedMode: ChangeFeedMode.AllVersionsAndDeletes)) { string continuation = null; while (feedIterator.HasMoreResults) @@ -1124,7 +1124,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_Dynamic_Veri string otherId = Guid.NewGuid().ToString(); using (FeedIterator feedIterator = container.GetChangeFeedIterator( changeFeedStartFrom: ChangeFeedStartFrom.Now(FeedRange.FromPartitionKey(new PartitionKey(id))), - changeFeedMode: ChangeFeedMode.FullFidelity)) + changeFeedMode: ChangeFeedMode.AllVersionsAndDeletes)) { string continuation = null; while (feedIterator.HasMoreResults) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs index 5e62114c1e..a8f5c4810c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs @@ -144,7 +144,7 @@ public async Task MonadicChangeFeedAsync_ChangeFeedMode_FullFidelity() await networkAttachedDocumentContainer.MonadicChangeFeedAsync( feedRangeState: new FeedRangeState(new FeedRangePartitionKeyRange("0"), ChangeFeedState.Beginning()), - changeFeedPaginationOptions: new ChangeFeedPaginationOptions(ChangeFeedMode.FullFidelity, pageSizeHint: 10), + changeFeedPaginationOptions: new ChangeFeedPaginationOptions(ChangeFeedMode.AllVersionsAndDeletes, pageSizeHint: 10), trace: NoOpTrace.Singleton, cancellationToken: default); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 07d725e2c5..add1fce30e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -160,15 +160,25 @@ "Microsoft.Azure.Cosmos.ChangeFeedMode;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { - "Microsoft.Azure.Cosmos.ChangeFeedMode FullFidelity": { + "Microsoft.Azure.Cosmos.ChangeFeedMode AllVersionsAndDeletes": { "Type": "Property", "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode FullFidelity;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_FullFidelity();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode AllVersionsAndDeletes;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Microsoft.Azure.Cosmos.ChangeFeedMode get_FullFidelity()": { + "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion()": { "Type": "Method", "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_FullFidelity();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} From 77e3aa44c5704f82fcfd6e1028327e4259b40f5f Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Fri, 6 Jan 2023 16:43:57 -0800 Subject: [PATCH 033/337] Query: Fixes handling of CosmosUndefined, CosmosGuid and CosmosBinary in unordered DISTINCT (#3632) * Handle CosmosUndefined, CosmosGuid and CosmosBinary in DistinctMap.UnorderedDistinctMap * Address code review feedback and remove unnecessary allocations from DistinctQueryPipelineStageTests --- .../DistinctMap.UnorderedDistinctMap.cs | 218 +++++++++++----- .../Core/Pipeline/Distinct/DistinctMap.cs | 2 +- .../Query/CosmosUndefinedQueryTests.cs | 5 +- .../DistinctQueryPipelineStageTests.cs | 237 ++++++++++++++++-- 4 files changed, 378 insertions(+), 84 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.UnorderedDistinctMap.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.UnorderedDistinctMap.cs index a0860957f5..f1d9b78fb8 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.UnorderedDistinctMap.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.UnorderedDistinctMap.cs @@ -12,8 +12,8 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - + using Microsoft.Azure.Cosmos.Query.Core.Monads; + /// /// Partial wrapper /// @@ -72,7 +72,7 @@ private enum SimpleValues /// This class does that with the additional optimization that it doesn't store the whole JSON. /// Instead this class takes a GUID like hash and store that instead. /// - private sealed class UnorderdDistinctMap : DistinctMap + private sealed class UnorderedDistinctMap : DistinctMap { /// /// Length of UInt128 (in bytes). @@ -97,7 +97,9 @@ private static class PropertyNames public const string StringsLength16 = "StringsLength16"; public const string StringsLength16Plus = "StringsLength16+"; public const string Arrays = "Arrays"; - public const string Object = "Object"; + public const string Object = "Object"; + public const string Guids = "Guids"; + public const string Blobs = "Blobs"; public const string SimpleValues = "SimpleValues"; } @@ -141,14 +143,31 @@ private static class PropertyNames /// HashSet for all object seen. /// This set only stores the hash, since we don't want to spend the space for storing large objects. /// - private readonly HashSet objects; + private readonly HashSet objects; + + /// + /// HashSet for all CosmosGuids seen. + /// This set only stores the hash, since we don't want to spend the space for storing large CosmosGuids. + /// + private readonly HashSet guids; /// - /// Stores all the simple values that we don't want to dedicate a hash set for. + /// HashSet for all CosmosBinarys seen. + /// This set only stores the hash, since we don't want to spend the space for storing large CosmosBinary objects. + /// + private readonly HashSet blobs; + + /// + /// Used to dispatch Add calls. /// - private SimpleValues simpleValues; + private readonly CosmosElementVisitor visitor; - private UnorderdDistinctMap( + /// + /// Stores all the simple values that we don't want to dedicate a hash set for. + /// + private SimpleValues simpleValues; + + private UnorderedDistinctMap( HashSet numbers, HashSet stringsLength4, HashSet stringsLength8, @@ -156,6 +175,8 @@ private UnorderdDistinctMap( HashSet stringsLength16Plus, HashSet arrays, HashSet objects, + HashSet guids, + HashSet blobs, SimpleValues simpleValues) { this.numbers = numbers ?? throw new ArgumentNullException(nameof(numbers)); @@ -165,7 +186,10 @@ private UnorderdDistinctMap( this.stringsLength16Plus = stringsLength16Plus ?? throw new ArgumentNullException(nameof(stringsLength16Plus)); this.arrays = arrays ?? throw new ArgumentNullException(nameof(arrays)); this.objects = objects ?? throw new ArgumentNullException(nameof(objects)); - this.simpleValues = simpleValues; + this.guids = guids ?? throw new ArgumentNullException(nameof(guids)); + this.blobs = blobs ?? throw new ArgumentNullException(nameof(blobs)); + this.simpleValues = simpleValues; + this.visitor = new CosmosElementVisitor(this); } /// @@ -179,16 +203,7 @@ public override bool Add(CosmosElement cosmosElement, out UInt128 hash) // Unordered distinct does not need to return a valid hash. // Since it doesn't need the last hash for a continuation. hash = default; - return cosmosElement switch - { - CosmosArray cosmosArray => this.AddArrayValue(cosmosArray), - CosmosBoolean cosmosBoolean => this.AddSimpleValue(cosmosBoolean.Value ? SimpleValues.True : SimpleValues.False), - CosmosNull _ => this.AddSimpleValue(SimpleValues.Null), - CosmosNumber cosmosNumber => this.AddNumberValue(cosmosNumber.Value), - CosmosObject cosmosObject => this.AddObjectValue(cosmosObject), - CosmosString cosmosString => this.AddStringValue(cosmosString.Value), - _ => throw new ArgumentOutOfRangeException($"Unexpected {nameof(CosmosElement)}: {cosmosElement}"), - }; + return cosmosElement.Accept(this.visitor); } public override string GetContinuationToken() @@ -201,35 +216,43 @@ public override CosmosElement GetCosmosElementContinuationToken() Dictionary dictionary = new Dictionary() { { - UnorderdDistinctMap.PropertyNames.Numbers, + UnorderedDistinctMap.PropertyNames.Numbers, CosmosArray.Create(this.numbers.Select(x => CosmosNumber64.Create(x))) }, { - UnorderdDistinctMap.PropertyNames.StringsLength4, + UnorderedDistinctMap.PropertyNames.StringsLength4, CosmosArray.Create(this.stringsLength4.Select(x => CosmosUInt32.Create(x))) }, { - UnorderdDistinctMap.PropertyNames.StringsLength8, + UnorderedDistinctMap.PropertyNames.StringsLength8, CosmosArray.Create(this.stringsLength8.Select(x => CosmosInt64.Create((long)x))) }, { - UnorderdDistinctMap.PropertyNames.StringsLength16, + UnorderedDistinctMap.PropertyNames.StringsLength16, CosmosArray.Create(this.stringsLength16.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { - UnorderdDistinctMap.PropertyNames.StringsLength16Plus, + UnorderedDistinctMap.PropertyNames.StringsLength16Plus, CosmosArray.Create(this.stringsLength16Plus.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { - UnorderdDistinctMap.PropertyNames.Arrays, + UnorderedDistinctMap.PropertyNames.Arrays, CosmosArray.Create(this.arrays.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { - UnorderdDistinctMap.PropertyNames.Object, + UnorderedDistinctMap.PropertyNames.Object, CosmosArray.Create(this.objects.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) }, { - UnorderdDistinctMap.PropertyNames.SimpleValues, + UnorderedDistinctMap.PropertyNames.Guids, + CosmosArray.Create(this.guids.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) + }, + { + UnorderedDistinctMap.PropertyNames.Blobs, + CosmosArray.Create(this.blobs.Select(x => CosmosBinary.Create(UInt128.ToByteArray(x)))) + }, + { + UnorderedDistinctMap.PropertyNames.SimpleValues, CosmosString.Create(this.simpleValues.ToString()) } }; @@ -274,7 +297,7 @@ private bool AddStringValue(string value) int utf8Length = Encoding.UTF8.GetByteCount(value); // If you can fit the string with full fidelity in 16 bytes, then you might as well just hash the string itself. - if (utf8Length <= UnorderdDistinctMap.UInt128Length) + if (utf8Length <= UnorderedDistinctMap.UInt128Length) { Span utf8Buffer = stackalloc byte[UInt128Length]; Encoding.UTF8.GetBytes(value, utf8Buffer); @@ -282,12 +305,12 @@ private bool AddStringValue(string value) { added = this.AddSimpleValue(SimpleValues.EmptyString); } - else if (utf8Length <= UnorderdDistinctMap.UIntLength) + else if (utf8Length <= UnorderedDistinctMap.UIntLength) { uint uintValue = MemoryMarshal.Read(utf8Buffer); added = this.stringsLength4.Add(uintValue); } - else if (utf8Length <= UnorderdDistinctMap.ULongLength) + else if (utf8Length <= UnorderedDistinctMap.ULongLength) { ulong uLongValue = MemoryMarshal.Read(utf8Buffer); added = this.stringsLength8.Add(uLongValue); @@ -328,6 +351,28 @@ private bool AddObjectValue(CosmosObject cosmosObject) { UInt128 hash = DistinctHash.GetHash(cosmosObject); return this.objects.Add(hash); + } + + /// + /// Adds a guid value to the distinct map. + /// + /// The guid to add. + /// Whether or not the value was successfully added. + private bool AddGuidValue(CosmosGuid guid) + { + UInt128 hash = DistinctHash.GetHash(guid); + return this.guids.Add(hash); + } + + /// + /// Adds a binary value to the distinct map. + /// + /// The array to add. + /// Whether or not the value was successfully added. + private bool AddBinaryValue(CosmosBinary binary) + { + UInt128 hash = DistinctHash.GetHash(binary); + return this.blobs.Add(hash); } public static TryCatch TryCreate(CosmosElement continuationToken) @@ -337,8 +382,10 @@ public static TryCatch TryCreate(CosmosElement continuationToken) HashSet stringsLength8 = new HashSet(); HashSet stringsLength16 = new HashSet(); HashSet stringsLength16Plus = new HashSet(); - HashSet arrays = new HashSet(); - HashSet objects = new HashSet(); + HashSet arrays = new HashSet(); + HashSet objects = new HashSet(); + HashSet guids = new HashSet(); + HashSet blobs = new HashSet(); SimpleValues simpleValues = SimpleValues.None; if (continuationToken != null) @@ -347,15 +394,15 @@ public static TryCatch TryCreate(CosmosElement continuationToken) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } // Numbers - if (!hashDictionary.TryGetValue(UnorderdDistinctMap.PropertyNames.Numbers, out CosmosArray numbersArray)) + if (!hashDictionary.TryGetValue(UnorderedDistinctMap.PropertyNames.Numbers, out CosmosArray numbersArray)) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } foreach (CosmosElement rawNumber in numbersArray) @@ -364,18 +411,18 @@ public static TryCatch TryCreate(CosmosElement continuationToken) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } numbers.Add(number.GetValue()); } // Strings Length 4 - if (!hashDictionary.TryGetValue(UnorderdDistinctMap.PropertyNames.StringsLength4, out CosmosArray stringsLength4Array)) + if (!hashDictionary.TryGetValue(UnorderedDistinctMap.PropertyNames.StringsLength4, out CosmosArray stringsLength4Array)) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } foreach (CosmosElement rawStringLength4 in stringsLength4Array) @@ -384,18 +431,18 @@ public static TryCatch TryCreate(CosmosElement continuationToken) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } stringsLength4.Add(stringlength4.GetValue()); } // Strings Length 8 - if (!hashDictionary.TryGetValue(UnorderdDistinctMap.PropertyNames.StringsLength8, out CosmosArray stringsLength8Array)) + if (!hashDictionary.TryGetValue(UnorderedDistinctMap.PropertyNames.StringsLength8, out CosmosArray stringsLength8Array)) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } foreach (CosmosElement rawStringLength8 in stringsLength8Array) @@ -404,49 +451,51 @@ public static TryCatch TryCreate(CosmosElement continuationToken) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } stringsLength8.Add((ulong)stringlength8.GetValue()); } - // Strings Length 16 - stringsLength16 = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.PropertyNames.StringsLength16); + stringsLength16 = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.StringsLength16); - // Strings Length 24 - stringsLength16Plus = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.PropertyNames.StringsLength16Plus); + stringsLength16Plus = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.StringsLength16Plus); - // Array - arrays = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.PropertyNames.Arrays); + arrays = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.Arrays); - // Object - objects = Parse128BitHashes(hashDictionary, UnorderdDistinctMap.PropertyNames.Object); + objects = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.Object); + + guids = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.Guids); + + blobs = Parse128BitHashes(hashDictionary, UnorderedDistinctMap.PropertyNames.Blobs); // Simple Values - CosmosElement rawSimpleValues = hashDictionary[UnorderdDistinctMap.PropertyNames.SimpleValues]; + CosmosElement rawSimpleValues = hashDictionary[UnorderedDistinctMap.PropertyNames.SimpleValues]; if (!(rawSimpleValues is CosmosString simpleValuesString)) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } if (!Enum.TryParse(simpleValuesString.Value, out simpleValues)) { return TryCatch.FromException( new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed.")); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed.")); } } - return TryCatch.FromResult(new UnorderdDistinctMap( + return TryCatch.FromResult(new UnorderedDistinctMap( numbers, stringsLength4, stringsLength8, stringsLength16, stringsLength16Plus, arrays, - objects, + objects, + guids, + blobs, simpleValues)); } @@ -456,7 +505,7 @@ private static HashSet Parse128BitHashes(CosmosObject hashDictionary, s if (!hashDictionary.TryGetValue(propertyName, out CosmosArray array)) { throw new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed."); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed."); } foreach (CosmosElement item in array) @@ -464,7 +513,7 @@ private static HashSet Parse128BitHashes(CosmosObject hashDictionary, s if (!(item is CosmosBinary binary)) { throw new MalformedContinuationTokenException( - $"{nameof(UnorderdDistinctMap)} continuation token was malformed."); + $"{nameof(UnorderedDistinctMap)} continuation token was malformed."); } UInt128 uint128 = UInt128.FromByteArray(binary.Value.Span); @@ -472,6 +521,61 @@ private static HashSet Parse128BitHashes(CosmosObject hashDictionary, s } return hashSet; + } + + private sealed class CosmosElementVisitor : ICosmosElementVisitor + { + private readonly UnorderedDistinctMap parent; + + public CosmosElementVisitor(UnorderedDistinctMap parent) + { + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + } + + public bool Visit(CosmosArray cosmosArray) + { + return this.parent.AddArrayValue(cosmosArray); + } + + public bool Visit(CosmosBinary cosmosBinary) + { + return this.parent.AddBinaryValue(cosmosBinary); + } + + public bool Visit(CosmosBoolean cosmosBoolean) + { + return this.parent.AddSimpleValue(cosmosBoolean.Value ? SimpleValues.True : SimpleValues.False); + } + + public bool Visit(CosmosGuid cosmosGuid) + { + return this.parent.AddGuidValue(cosmosGuid); + } + + public bool Visit(CosmosNull cosmosNull) + { + return this.parent.AddSimpleValue(SimpleValues.Null); + } + + public bool Visit(CosmosNumber cosmosNumber) + { + return this.parent.AddNumberValue(cosmosNumber.Value); + } + + public bool Visit(CosmosObject cosmosObject) + { + return this.parent.AddObjectValue(cosmosObject); + } + + public bool Visit(CosmosString cosmosString) + { + return this.parent.AddStringValue(cosmosString.Value); + } + + public bool Visit(CosmosUndefined cosmosUndefined) + { + return this.parent.AddSimpleValue(SimpleValues.Undefined); + } } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.cs index 821c5ff4bf..db01fbe32d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctMap.cs @@ -30,7 +30,7 @@ public static TryCatch TryCreate( CosmosElement distinctMapContinuationToken) => distinctQueryType switch { DistinctQueryType.None => throw new ArgumentException("distinctQueryType can not be None. This part of code is not supposed to be reachable. Please contact support to resolve this issue."), - DistinctQueryType.Unordered => UnorderdDistinctMap.TryCreate(distinctMapContinuationToken), + DistinctQueryType.Unordered => UnorderedDistinctMap.TryCreate(distinctMapContinuationToken), DistinctQueryType.Ordered => OrderedDistinctMap.TryCreate(distinctMapContinuationToken), _ => throw new ArgumentException($"Unrecognized DistinctQueryType: {distinctQueryType}."), }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs index 3945169330..1b44c773fa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs @@ -75,7 +75,10 @@ private static async Task UntypedTests(Container container) expectedCount: 0), MakeUndefinedProjectionTest( query: $"SELECT VALUE AVG(c.{nameof(MixedTypeDocument.MixedTypeField)}) FROM c", - expectedCount: 0), + expectedCount: 0), + MakeUndefinedProjectionTest( + query: $"SELECT DISTINCT VALUE SUM(c.{nameof(MixedTypeDocument.MixedTypeField)}) FROM c", + expectedCount: 0) }; foreach (UndefinedProjectionTestCase testCase in undefinedProjectionTestCases) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs index 3fc5eaa05f..9b9ade94c6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs @@ -2,11 +2,12 @@ { using System; using System.Collections.Generic; - using System.Linq; + using System.Linq; + using System.Text; using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; @@ -16,28 +17,198 @@ [TestClass] public sealed class DistinctQueryPipelineStageTests - { + { + private const int InputElementCount = 400; + + // This list SHOULD NOT contain duplicates + private static readonly IReadOnlyList Literals = new List + { + CosmosUndefined.Create(), + + CosmosNull.Create(), + + CosmosBoolean.Create(true), + CosmosBoolean.Create(false), + + CosmosNumber64.Create(0), + CosmosNumber64.Create(42), + CosmosNumber64.Create(-1), + CosmosNumber64.Create(100010), + CosmosNumber64.Create(3.141619), + CosmosNumber64.Create(Math.PI), + + CosmosString.Create(string.Empty), + CosmosString.Create("Hello World"), + CosmosString.Create(string.Join(',', Enumerable.Repeat("Hello World", 75))), + CosmosString.Create(string.Join(',', Enumerable.Repeat("Hello World", 100))), + CosmosString.Create("敏捷的棕色狐狸跳过了懒狗"), + CosmosString.Create(string.Join(',', Enumerable.Repeat("敏捷的棕色狐狸跳过了懒狗", 50))), + CosmosString.Create(string.Join(',', Enumerable.Repeat("敏捷的棕色狐狸跳过了懒狗", 60))), + + CosmosArray.Create(), + CosmosArray.Create(new CosmosElement[] + { + CosmosUndefined.Create(), + CosmosNull.Create(), + CosmosBoolean.Create(true), + CosmosBoolean.Create(false), + CosmosNumber64.Create(0), + }), + CosmosArray.Create(new CosmosElement[] + { + CosmosUndefined.Create(), + CosmosNull.Create(), + CosmosBoolean.Create(true), + CosmosBoolean.Create(false) + }), + CosmosArray.Create(new CosmosElement[] + { + CosmosUndefined.Create(), + CosmosNull.Create(), + CosmosBoolean.Create(true), + CosmosBoolean.Create(false), + CosmosNumber64.Create(0), + CosmosNumber64.Create(42), + CosmosNumber64.Create(-1), + CosmosNumber64.Create(100010), + CosmosNumber64.Create(3.141619), + }), + + CosmosObject.Create(new Dictionary()), + CosmosObject.Create(new Dictionary + { + ["敏"] = CosmosUndefined.Create(), + ["b"] = CosmosNull.Create(), + ["c"] = CosmosBoolean.Create(true), + ["d"] = CosmosBoolean.Create(false), + ["懒"] = CosmosNumber64.Create(0), + }), + CosmosObject.Create(new Dictionary + { + ["敏"] = CosmosUndefined.Create(), + ["b"] = CosmosNull.Create(), + ["c"] = CosmosBoolean.Create(true), + ["d"] = CosmosBoolean.Create(false), + ["懒"] = CosmosNumber64.Create(0), + ["e"] = CosmosNumber64.Create(42), + ["f"] = CosmosNumber64.Create(-1), + ["فوق"] = CosmosNumber64.Create(100010), + ["g"] = CosmosNumber64.Create(3.141619), + }), + + CosmosGuid.Create(Guid.Parse("D29F71E3-2D43-4573-A0E6-16D7E03FDEB5")), + CosmosGuid.Create(Guid.Parse("D29F71E3-2D43-4573-B0E6-16D7E03FDEB5")), + CosmosGuid.Create(Guid.Parse("D29F71E3-2D43-4573-C0E6-16D7E03FDEB5")), + CosmosGuid.Create(Guid.Parse("D29F71E3-2D43-4573-D0E6-16D7E03FDEB5")), + CosmosGuid.Create(Guid.Parse("D29F71E3-2D43-4573-E0E6-16D7E03FDEB5")), + + CosmosBinary.Create(Guid.Parse("D29F71E3-2D43-4573-A0E6-16D7E03FDEB5").ToByteArray()), + CosmosBinary.Create(Guid.Parse("D29F71E3-2D43-4573-B0E6-16D7E03FDEB5").ToByteArray()), + CosmosBinary.Create(Guid.Parse("D29F71E3-2D43-4573-C0E6-16D7E03FDEB5").ToByteArray()), + CosmosBinary.Create(Guid.Parse("D29F71E3-2D43-4573-D0E6-16D7E03FDEB5").ToByteArray()), + CosmosBinary.Create(Guid.Parse("D29F71E3-2D43-4573-E0E6-16D7E03FDEB5").ToByteArray()), + CosmosBinary.Create(Encoding.UTF8.GetBytes("Hello World")), + CosmosBinary.Create(Encoding.UTF8.GetBytes(string.Join(',', Enumerable.Repeat("Hello World", 75)))), + CosmosBinary.Create(Encoding.UTF8.GetBytes(string.Join(',', Enumerable.Repeat("Hello World", 100)))), + CosmosBinary.Create(Encoding.UTF8.GetBytes("敏捷的棕色狐狸跳过了懒狗")), + CosmosBinary.Create(Encoding.UTF8.GetBytes(string.Join(',', Enumerable.Repeat("敏捷的棕色狐狸跳过了懒狗", 50)))), + CosmosBinary.Create(Encoding.UTF8.GetBytes(string.Join(',', Enumerable.Repeat("敏捷的棕色狐狸跳过了懒狗", 60)))), + }; + [TestMethod] public async Task SanityTests() - { - long[] values = new long[] { 42, 1337, 1337, 42 }; - IReadOnlyList> pages = values - .Select(value => new List() + { + long[] values = { 42, 1337, 1337, 42 }; + + IEnumerable input = values + .Select(value => CosmosObject.Create(new Dictionary + { + ["item"] = CosmosNumber64.Create(value) + })); + + IEnumerable expected = values + .Distinct() + .Select(value => CosmosObject.Create(new Dictionary + { + ["item"] = CosmosNumber64.Create(value) + })); + + DistinctQueryPipelineStageTestCase MakeTest(int pageSize) + { + return new DistinctQueryPipelineStageTestCase(input: input, pageSize: pageSize, expected: expected); + } + + IEnumerable testCases = new List + { + MakeTest(pageSize: 1), + MakeTest(pageSize: 3), + MakeTest(pageSize : 10), + }; + + await RunTests(testCases); + } + + [TestMethod] + public async Task MixedTypeTests() + { + IEnumerable mixedTypeValues = Enumerable + .Range(0, InputElementCount) + .Select(index => Literals[index % Literals.Count]); + + DistinctQueryPipelineStageTestCase MakeTest(int pageSize) + { + return new DistinctQueryPipelineStageTestCase(input: mixedTypeValues, pageSize: pageSize, expected: Literals); + } + + int[] pageSizes = { 400, 100, 10, 1 }; + IEnumerable testCases = pageSizes + .Select(x => MakeTest(pageSize: x)) + .ToList(); + + await RunTests(testCases); + } + + private static async Task RunTests(IEnumerable testCases) + { + foreach (DistinctQueryPipelineStageTestCase testCase in testCases) + { + IEnumerator enumerator = testCase.Input.GetEnumerator(); + int pageSize = 0; + List> pages = new List>() { new List() }; + while(enumerator.MoveNext()) + { + if (pageSize > testCase.PageSize) + { + pageSize = 0; + pages.Add(new List()); + } + + pages[pages.Count - 1].Add(enumerator.Current); + ++pageSize; + } + + foreach (ExecutionEnvironment env in new[] { ExecutionEnvironment.Compute, ExecutionEnvironment.Client }) { - CosmosElement.Parse($"{{\"item\": {value}}}") - }) - .ToList(); - - List elements = await DistinctQueryPipelineStageTests.CreateAndDrainAsync( - pages: pages, - executionEnvironment: ExecutionEnvironment.Compute, - continuationToken: null, - distinctQueryType: DistinctQueryType.Unordered); - - Assert.AreEqual(values.Distinct().Count(), elements.Count); + IEnumerable elements = await DistinctQueryPipelineStageTests.CreateAndDrainAsync( + pages: pages, + executionEnvironment: env, + continuationToken: null, + distinctQueryType: DistinctQueryType.Unordered); + + List actual = elements + .Select(value => value.ToString()) + .ToList(); + + List expected = testCase.Expected + .Select(value => value.ToString()) + .ToList(); + + CollectionAssert.AreEquivalent(expected, actual); + } + } } - private static async Task> CreateAndDrainAsync( + private static async Task> CreateAndDrainAsync( IReadOnlyList> pages, ExecutionEnvironment executionEnvironment, CosmosElement continuationToken, @@ -55,15 +226,31 @@ private static async Task> CreateAndDrainAsync( IQueryPipelineStage distinctQueryPipelineStage = tryCreateDistinctQueryPipelineStage.Result; - List elements = new List(); + IEnumerable elements = Enumerable.Empty(); await foreach (TryCatch page in new EnumerableStage(distinctQueryPipelineStage, NoOpTrace.Singleton)) { page.ThrowIfFailed(); - elements.AddRange(page.Result.Documents); + elements = elements.Concat(page.Result.Documents); } return elements; - } - } + } + + private struct DistinctQueryPipelineStageTestCase + { + public IEnumerable Input { get; } + + public int PageSize { get; } + + public IEnumerable Expected { get; } + + public DistinctQueryPipelineStageTestCase(IEnumerable input, int pageSize, IEnumerable expected) + { + this.Input = input ?? throw new ArgumentNullException(nameof(input)); + this.PageSize = pageSize; + this.Expected = expected ?? throw new ArgumentNullException(nameof(expected)); + } + } + } } From 3c875c7c15822f518c742dd4392cc6c093320b27 Mon Sep 17 00:00:00 2001 From: Nalu Tripician Date: Mon, 9 Jan 2023 10:50:57 -0800 Subject: [PATCH 034/337] [Internal] Subpartitioning: Adds updates to test coverage for subpartitioning (#3618) * updates to test coverage for subpartitioning * bug fixes * now useses Assert.ThrowsException * Seperated into multiple tests for clarity * Put MultiHash test into seperate test file * nit --- .../CosmosItemTests.cs | 110 ----- .../CosmosMultiHashTest.cs | 445 ++++++++++++++++++ 2 files changed, 445 insertions(+), 110 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index da6d79c333..50bc71f276 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -27,7 +27,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Newtonsoft.Json; using Newtonsoft.Json.Linq; using JsonReader = Json.JsonReader; - using JsonSerializer = Json.JsonSerializer; using JsonWriter = Json.JsonWriter; using PartitionKey = Documents.PartitionKey; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; @@ -3006,115 +3005,6 @@ public async Task HaLayerDoesNotThrowNullOnGoneExceptionTest() } } -#if PREVIEW - [TestMethod] - public async Task VerifyDocumentCrudWithMultiHashKind() - { - string currentVersion = HttpConstants.Versions.CurrentVersion; - HttpConstants.Versions.CurrentVersion = "2020-07-15"; - CosmosClient client = TestCommon.CreateCosmosClient(true); - Cosmos.Database database = null; - database = await client.CreateDatabaseIfNotExistsAsync("mydb"); - try - { - ContainerProperties containerProperties = new ContainerProperties("mycoll", new List { "/ZipCode", "/Address" }); - Container container = await database.CreateContainerAsync(containerProperties); - - //Document create. - ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - documents[0] = await container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - documents[1] = await container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - documents[2] = await container.CreateItemAsync(doc1); - - Assert.AreEqual(3, documents.Select(document => ((Document)document).SelfLink).Distinct().Count()); - - //Negative test - { - doc1 = new Document { Id = "doc1" }; - doc1.SetValue("Zipcode", 11790); - - PartitionKeyBuilder pKValueList = new PartitionKeyBuilder(); - pKValueList.Add(doc1.GetPropertyValue("ZipCode")); - - Cosmos.PartitionKey pKeyErr = pKValueList.Build(); - ResponseMessage response = await this.Container.CreateItemStreamAsync(streamPayload: TestCommon.SerializerCore.ToStream(doc1), partitionKey: pKeyErr); - - Assert.IsNotNull(response); - Assert.IsNull(response.Content); - Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode); - } - - //Document Read. - foreach (Document document in documents) - { - Cosmos.PartitionKey pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) - .Build(); - - Document readDocument = (await container.ReadItemAsync(document.Id, pKey)).Resource; - Assert.AreEqual(document.ToString(), readDocument.ToString()); - } - - //Document Update. - foreach (ItemResponse obj in documents) - { - Cosmos.PartitionKey pKey = new PartitionKeyBuilder() - .Add(obj.Resource.GetValue("ZipCode")) - .Add(obj.Resource.GetPropertyValue("Address")) - .Build(); - - Document document = (await container.ReadItemAsync(obj.Resource.Id, pKey)).Resource; - document.SetPropertyValue("Name", document.Id); - - Document readDocument = (await container.ReplaceItemAsync(document, document.Id, pKey)).Resource; - Assert.AreEqual(readDocument.GetValue("Name"), document.GetValue("Name")); - } - - //Document Delete. - foreach (Document document in documents) - { - Cosmos.PartitionKey pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) - .Build(); - - Document readDocument = (await container.DeleteItemAsync(document.Id, pKey)).Resource; - try - { - readDocument = await container.ReadItemAsync(document.Id, pKey); - } - catch (CosmosException clientException) - { - Assert.AreEqual(clientException.StatusCode, HttpStatusCode.NotFound); - } - } - - } - catch (Exception) - { - Assert.Fail(); - } - finally - { - await database.DeleteAsync(); - HttpConstants.Versions.CurrentVersion = currentVersion; - } - - } - -#endif private async Task AutoGenerateIdPatternTest(Cosmos.PartitionKey pk, T itemWithoutId) { string autoId = Guid.NewGuid().ToString(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs new file mode 100644 index 0000000000..d069e87935 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -0,0 +1,445 @@ +#if PREVIEW +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net; + using System.Threading.Tasks; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class CosmosMultiHashTest + { + private Cosmos.Database database = null; + + private Container container = null; + private ContainerProperties containerProperties = null; + + private readonly string currentVersion = HttpConstants.Versions.CurrentVersion; + + + [TestInitialize] + public async Task TestInitialize() + { + HttpConstants.Versions.CurrentVersion = "2020-07-15"; + CosmosClient client = TestCommon.CreateCosmosClient(true); + this.database = await client.CreateDatabaseIfNotExistsAsync("mydb"); + + this.containerProperties = new ContainerProperties("mycoll", new List { "/ZipCode", "/Address" }); + this.container = await this.database.CreateContainerAsync(this.containerProperties); + } + + [TestCleanup] + public async Task Cleanup() + { + await this.database.DeleteAsync(); + HttpConstants.Versions.CurrentVersion = this.currentVersion; + } + + [TestMethod] + public async Task MultiHashCreateDocumentTest() + { + //Document create test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + Assert.AreEqual(3, documents.Select(document => ((Document)document).SelfLink).Distinct().Count()); + + //Negative test - using incomplete partition key + Cosmos.PartitionKey badPKey; + + foreach (Document document in documents) + { + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("Address")) + .Build(); + + document.Id += "Bad"; + + ArgumentException createException = await Assert.ThrowsExceptionAsync(() => + this.container.CreateItemAsync(document, badPKey) + ); + } + } + + [TestMethod] + public async Task MultiHashDeleteDocumentTest() + { + Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; + + //Create Items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Document Delete Test + foreach (Document document in documents) + { + //Negative test - using incomplete partition key + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("Address")) + .Build(); + + CosmosException deleteException = await Assert.ThrowsExceptionAsync(() => + this.container.DeleteItemAsync(document.Id, badPKey) + ); + + Assert.AreEqual(deleteException.StatusCode, HttpStatusCode.BadRequest); + + //Positive test + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("Address")) + .Build(); + + Document readDocument = (await this.container.DeleteItemAsync(document.Id, pKey)).Resource; + + CosmosException clientException = await Assert.ThrowsExceptionAsync(() => + this.container.ReadItemAsync(document.Id, pKey) + ); + + Assert.AreEqual(clientException.StatusCode, HttpStatusCode.NotFound); + } + } + + [TestMethod] + public async Task MultiHashReadItemTest() + { + Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; + + //Create Items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Document Read Test + foreach (Document document in documents) + { + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("Address")) + .Build(); + + Document readDocument = (await this.container.ReadItemAsync(document.Id, pKey)).Resource; + Assert.AreEqual(document.ToString(), readDocument.ToString()); + + //Negative test - using incomplete partition key + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("Address")) + .Build(); + + CosmosException clientException = await Assert.ThrowsExceptionAsync(() => + this.container.ReadItemAsync(document.Id, badPKey) + ); + + Assert.AreEqual(clientException.StatusCode, HttpStatusCode.BadRequest); + } + } + + [TestMethod] + public async Task MultiHashReadManyTest() + { + Cosmos.PartitionKey pKey; + + //Create Items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Read Many Test + List<(string, Cosmos.PartitionKey)> itemList = new List<(string, Cosmos.PartitionKey)>(); + foreach (Document document in documents) + { + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("Address")) + .Build(); + + itemList.Add((document.Id, pKey)); + } + + FeedResponse feedResponse = await this.container.ReadManyItemsAsync(itemList); + + Assert.IsNotNull(feedResponse); + Assert.AreEqual(feedResponse.Count, 3); + Assert.IsTrue(feedResponse.Headers.RequestCharge > 0); + Assert.IsNotNull(feedResponse.Diagnostics); + + int count = 0; + foreach (ToDoActivity item in feedResponse) + { + count++; + Assert.IsNotNull(item); + Assert.IsNotNull(item.pk); + } + Assert.AreEqual(count, 3); + } + + [TestMethod] + public async Task MultiHashUpsetItemTest() + { + Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; + int count; + + //Create Items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Document Upsert Test + doc1 = new Document { Id = "document4" }; + doc1.SetValue("ZipCode", "97756"); + doc1.SetValue("Address", "Redmond"); + doc1.SetValue("Type", "Residence"); + + pKey = new PartitionKeyBuilder() + .Add(doc1.GetPropertyValue("ZipCode")) + .Add(doc1.GetPropertyValue("Address")) + .Build(); + + //insert check + await this.container.UpsertItemAsync(doc1, pKey); + + Document readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + + Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); + Assert.AreEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + + doc1 = new Document { Id = "document4" }; + doc1.SetValue("ZipCode", "97756"); + doc1.SetValue("Address", "Redmond"); + doc1.SetValue("Type", "Business"); + + //update check + pKey = new PartitionKeyBuilder() + .Add(doc1.GetPropertyValue("ZipCode")) + .Add(doc1.GetPropertyValue("Address")) + .Build(); + + documents.Append>(await this.container.UpsertItemAsync(doc1, pKey)); + + readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + + Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); + Assert.AreEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + + count = 0; + + foreach (Document doc in this.container.GetItemLinqQueryable(true)) + { + count++; + } + Assert.AreEqual(4, count); + + //Negative test - using incomplete partition key + doc1 = new Document { Id = "document4" }; + doc1.SetValue("ZipCode", "97756"); + doc1.SetValue("Address", "Redmond"); + doc1.SetValue("Type", "Residence"); + + badPKey = new PartitionKeyBuilder() + .Add(doc1.GetPropertyValue("ZipCode")) + .Build(); + + await Assert.ThrowsExceptionAsync(() => + this.container.UpsertItemAsync(doc1, badPKey) + ); + + readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + + Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); + Assert.AreNotEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + } + + [TestMethod] + public async Task MultiHashReplaceItemTest() + { + Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; + + //Create items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Document Replace Test + foreach (Document document in documents) + { + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("Address")) + .Build(); + + + Document readDocument = (await this.container.ReadItemAsync(document.Id, pKey)).Resource; + readDocument.SetValue("Type", "Park"); + + ItemResponse item = await this.container.ReplaceItemAsync(readDocument, readDocument.Id, pKey); + + Document checkDocument = (await this.container.ReadItemAsync(document.Id, pKey)).Resource; + Assert.AreEqual(checkDocument.GetPropertyValue("Type"), readDocument.GetPropertyValue("Type")); + + //Negative test - using incomplete partition key + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("Address")) + .Build(); + + readDocument.SetValue("Type", "Goverment"); + + await Assert.ThrowsExceptionAsync(() => + this.container.ReplaceItemAsync(document, document.Id, partitionKey: badPKey) + ); + } + } + + [TestMethod] + public async Task MultiHashQueryItemTest() + { + Cosmos.PartitionKey pKey; + + //Create items for test + ItemResponse[] documents = new ItemResponse[3]; + Document doc1 = new Document { Id = "document1" }; + doc1.SetValue("ZipCode", "500026"); + doc1.SetValue("Address", "Secunderabad"); + doc1.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document2" }; + doc1.SetValue("ZipCode", "15232"); + doc1.SetValue("Address", "Pittsburgh"); + doc1.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc1); + + doc1 = new Document { Id = "document3" }; + doc1.SetValue("ZipCode", "11790"); + doc1.SetValue("Address", "Stonybrook"); + doc1.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc1); + + //Query + foreach (Document document in documents) + { + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("Address")) + .Build(); + + String query = $"SELECT * from c where c.id = {document.GetPropertyValue("Id")}"; + + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); + + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + } + + } + } + + } +} +#endif From 416b154a7f90d35bf572d05ff69c70c5737cfaf0 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 9 Jan 2023 14:18:54 -0800 Subject: [PATCH 035/337] [Internal] ContainerProperties: Fixes version reset when setting PartitionKeyPath (#3637) * Remember previous value * test --- .../src/Resource/Settings/ContainerProperties.cs | 7 +++++++ .../CosmosContainerSettingsTests.cs | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs index e1eaa6ca96..b95efb99c8 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs @@ -362,10 +362,17 @@ public string PartitionKeyPath throw new ArgumentNullException(nameof(this.PartitionKeyPath)); } + PartitionKeyDefinitionVersion? currentDefinitionVersion = this.PartitionKeyDefinitionVersion; + this.PartitionKey = new PartitionKeyDefinition { Paths = new Collection() { value } }; + + if (currentDefinitionVersion.HasValue) + { + this.PartitionKeyDefinitionVersion = currentDefinitionVersion.Value; + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs index 84618705de..865bb71d18 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs @@ -165,6 +165,17 @@ public void ValidateIncludedPathSerialization() } } + [TestMethod] + public void SettingPKShouldNotResetVersion() + { + ContainerProperties containerProperties = new(); + containerProperties.Id = "test"; + containerProperties.PartitionKeyDefinitionVersion = Cosmos.PartitionKeyDefinitionVersion.V2; + containerProperties.PartitionKeyPath = "/id"; + + Assert.AreEqual(Cosmos.PartitionKeyDefinitionVersion.V2, containerProperties.PartitionKeyDefinitionVersion); + } + private static string SerializeDocumentCollection(DocumentCollection collection) { using (MemoryStream ms = new MemoryStream()) From 59b70a6284483bfc79c6c96a2207905c652a1620 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 10 Jan 2023 21:15:04 +0530 Subject: [PATCH 036/337] [Internal] AI Integration: Adds CorrelationId and Activity Id Attributes for query operation (#3630) * add activityid in Otel attributes * added correlation id * operation type fix * remove test changes * test fix * fix baseline test * rename correlationId * fix tests again * include only not null attributes in test * fixed tests * changefeedxml * test fix * ordering activity in operationname oerder * fix test * review comments * refator header getter setter * clean up Co-authored-by: Sourabh Jain --- .../CosmosQueryResponseMessageHeaders.cs | 6 +- Microsoft.Azure.Cosmos/src/Headers/Headers.cs | 9 + .../src/Query/v3Query/QueryIterator.cs | 1 + .../OpenTelemetryAttributeKeys.cs | 4 +- .../OpenTelemetry/OpenTelemetryAttributes.cs | 15 ++ .../OpenTelemetryCoreRecorder.cs | 47 ++-- .../OpenTelemetry/OpenTelemetryResponse.cs | 18 +- .../OpenTelemetry/OpenTelemetryResponse{T}.cs | 18 +- .../BaselineTest/BaselineTests.cs | 4 - ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 12 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Tracing/AssertActivity.cs | 4 +- .../Tracing/CustomListener.cs | 28 ++- 21 files changed, 312 insertions(+), 228 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Headers/CosmosQueryResponseMessageHeaders.cs b/Microsoft.Azure.Cosmos/src/Headers/CosmosQueryResponseMessageHeaders.cs index 4c962cb6d8..2e37e62e9b 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/CosmosQueryResponseMessageHeaders.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/CosmosQueryResponseMessageHeaders.cs @@ -73,7 +73,8 @@ internal CosmosQueryResponseMessageHeaders CloneKnownProperties( SubStatusCodeLiteral = this.SubStatusCodeLiteral, ContentType = this.ContentType, QueryMetricsText = QueryMetricsText, - IndexUtilizationText = IndexUtilizationText + IndexUtilizationText = IndexUtilizationText, + CorrelatedActivityId = this.CorrelatedActivityId }; } @@ -108,7 +109,8 @@ internal static CosmosQueryResponseMessageHeaders ConvertToQueryHeaders( SubStatusCodeLiteral = sourceHeaders.SubStatusCodeLiteral ?? (substatusCode.HasValue ? substatusCode.Value.ToString() : null), ContentType = sourceHeaders.ContentType, QueryMetricsText = sourceHeaders.QueryMetricsText, - IndexUtilizationText = sourceHeaders.IndexUtilizationText + IndexUtilizationText = sourceHeaders.IndexUtilizationText, + CorrelatedActivityId = sourceHeaders.CorrelatedActivityId }; } } diff --git a/Microsoft.Azure.Cosmos/src/Headers/Headers.cs b/Microsoft.Azure.Cosmos/src/Headers/Headers.cs index fda0536da2..611de5f147 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/Headers.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/Headers.cs @@ -36,6 +36,15 @@ public virtual string ContinuationToken internal set => this.CosmosMessageHeaders.Continuation = value; } + /// + /// Gets or Set the CoorelatedActivityId in the current . + /// + internal virtual string CorrelatedActivityId + { + get => this.CosmosMessageHeaders.Get(HttpConstants.HttpHeaders.CorrelatedActivityId); + set => this.CosmosMessageHeaders.Set(HttpConstants.HttpHeaders.CorrelatedActivityId, value); + } + /// /// Gets the request charge for this request from the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index b7c43c8443..01a4e1b12e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -235,6 +235,7 @@ public override async Task ReadNextAsync(ITrace trace, Cancella { RequestCharge = tryGetQueryPage.Result.RequestCharge, ActivityId = tryGetQueryPage.Result.ActivityId, + CorrelatedActivityId = this.correlatedActivityId.ToString(), SubStatusCode = Documents.SubStatusCodes.Unknown }; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index eb8382c0b0..e7c4d96cc2 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -24,7 +24,7 @@ internal sealed class OpenTelemetryAttributeKeys public const string ConnectionMode = "db.cosmosdb.connection_mode"; public const string OperationType = "db.cosmosdb.operation_type"; - // Request Specifics + // Request/Response Specifics public const string ContainerName = "db.cosmosdb.container"; public const string RequestContentLength = "db.cosmosdb.request_content_length_bytes"; public const string ResponseContentLength = "db.cosmosdb.response_content_length_bytes"; @@ -35,6 +35,8 @@ internal sealed class OpenTelemetryAttributeKeys public const string RetryCount = "db.cosmosdb.retry_count"; public const string ItemCount = "db.cosmosdb.item_count"; public const string RequestDiagnostics = "db.cosmosdb.request_diagnostics"; + public const string ActivityId = "db.cosmosdb.activity_id"; + public const string CorrelatedActivityId = "db.cosmosdb.correlated_activity_id"; // Exceptions public const string ExceptionType = "exception.type"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs index 7e9c798f9d..70b6cea4ef 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributes.cs @@ -54,5 +54,20 @@ internal OpenTelemetryAttributes(RequestMessage requestMessage) /// SubStatusCode /// internal int SubStatusCode { get; set; } + + /// + /// ActivityId + /// + internal string ActivityId { get; set; } + + /// + /// CorrelatedActivityId + /// + internal string CorrelatedActivityId { get; set; } + + /// + /// OperationType + /// + internal Documents.OperationType OperationType { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 32e4fde67f..51aa1ee794 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -14,12 +14,13 @@ namespace Microsoft.Azure.Cosmos.Telemetry internal struct OpenTelemetryCoreRecorder : IDisposable { private const string CosmosDb = "cosmosdb"; - + private readonly DiagnosticScope scope; private readonly DistributedTracingOptions config; private readonly Documents.OperationType operationType; - + private OpenTelemetryAttributes response = null; + internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() { { typeof(CosmosNullReferenceException), (exception, scope) => CosmosNullReferenceException.RecordOtelAttributes((CosmosNullReferenceException)exception, scope)}, @@ -41,7 +42,7 @@ public OpenTelemetryCoreRecorder( this.config = config; this.operationType = operationType; - if (this.IsEnabled) + if (scope.IsEnabled) { this.scope.Start(); @@ -49,7 +50,6 @@ public OpenTelemetryCoreRecorder( operationName: operationName, containerName: containerName, databaseName: databaseName, - operationType: operationType, clientContext: clientContext); } } @@ -70,13 +70,11 @@ public void Record(string key, string value) /// /// /// - /// /// public void Record( string operationName, string containerName, string databaseName, - Documents.OperationType operationType, CosmosClientContext clientContext) { if (this.IsEnabled) @@ -84,7 +82,6 @@ public void Record( this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbOperation, operationName); this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, operationType); // Other information this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb); @@ -106,18 +103,7 @@ public void Record(OpenTelemetryAttributes response) { if (this.IsEnabled) { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, response.RequestContentLength); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, response.ResponseContentLength); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)response.StatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)response.SubStatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, response.RequestCharge); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, response.ItemCount); - - if (response.Diagnostics != null) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(response.Diagnostics.GetContactedRegions())); - CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, this.operationType, response); - } + this.response = response; } } @@ -168,6 +154,29 @@ public void Dispose() { if (this.scope.IsEnabled) { + Documents.OperationType operationType + = (this.response == null || this.response?.OperationType == Documents.OperationType.Invalid) ? this.operationType : this.response.OperationType; + + this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, operationType); + + if (this.response != null) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, this.response.RequestContentLength); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, this.response.ResponseContentLength); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)this.response.SubStatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, this.response.RequestCharge); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, this.response.ItemCount); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, this.response.ActivityId); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.CorrelatedActivityId, this.response.CorrelatedActivityId); + + if (this.response.Diagnostics != null) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(this.response.Diagnostics.GetContactedRegions())); + CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, operationType, this.response); + } + } + this.scope.Dispose(); } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs index 98c1bfab8d..c9aba10ee6 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs @@ -18,7 +18,9 @@ internal OpenTelemetryResponse(TransactionalBatchResponse responseMessage) diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, requestMessage: null, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode) + subStatusCode: (int)responseMessage.Headers?.SubStatusCode, + activityId: responseMessage.Headers?.ActivityId, + correlationId: responseMessage.Headers?.CorrelatedActivityId) { } @@ -30,7 +32,11 @@ internal OpenTelemetryResponse(ResponseMessage responseMessage) diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode) + subStatusCode: (int)responseMessage.Headers?.SubStatusCode, + activityId: responseMessage.Headers?.ActivityId, + correlationId: responseMessage.Headers?.CorrelatedActivityId, + operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid + ) { } @@ -41,7 +47,10 @@ private OpenTelemetryResponse( CosmosDiagnostics diagnostics, string itemCount, RequestMessage requestMessage, - int subStatusCode) + int subStatusCode, + string activityId, + string correlationId, + Documents.OperationType operationType = Documents.OperationType.Invalid) : base(requestMessage) { this.StatusCode = statusCode; @@ -50,6 +59,9 @@ private OpenTelemetryResponse( this.Diagnostics = diagnostics; this.ItemCount = itemCount; this.SubStatusCode = subStatusCode; + this.ActivityId = activityId; + this.CorrelatedActivityId = correlationId; + this.OperationType = operationType; } private static string GetPayloadSize(ResponseMessage response) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs index 71ca5cfba2..4c96306a30 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs @@ -17,7 +17,10 @@ internal OpenTelemetryResponse(FeedResponse responseMessage) diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode) + subStatusCode: (int)responseMessage.Headers?.SubStatusCode, + activityId: responseMessage.Headers?.ActivityId, + correlatedActivityId: responseMessage.Headers?.CorrelatedActivityId, + operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid) { } @@ -29,7 +32,10 @@ internal OpenTelemetryResponse(Response responseMessage) diagnostics: responseMessage.Diagnostics, itemCount: responseMessage.Headers?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode) + subStatusCode: (int)responseMessage.Headers?.SubStatusCode, + activityId: responseMessage.Headers?.ActivityId, + correlatedActivityId: responseMessage.Headers?.CorrelatedActivityId, + operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid) { } @@ -40,7 +46,10 @@ private OpenTelemetryResponse( CosmosDiagnostics diagnostics, string itemCount, RequestMessage requestMessage, - int subStatusCode) + int subStatusCode, + string activityId, + string correlatedActivityId, + Documents.OperationType operationType) : base(requestMessage) { this.StatusCode = statusCode; @@ -49,6 +58,9 @@ private OpenTelemetryResponse( this.Diagnostics = diagnostics; this.ItemCount = itemCount; this.SubStatusCode = subStatusCode; + this.ActivityId = activityId; + this.CorrelatedActivityId = correlatedActivityId; + this.OperationType = operationType; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs index c68a6e6bdc..e9fbc54267 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs @@ -116,17 +116,13 @@ public void ExecuteTestSuite(IEnumerable inputs, [CallerMemberName] stri string outputText = Regex.Replace( Regex.Replace( - Regex.Replace( File.ReadAllText(outputPath), @"\s+", string.Empty), - @"[\w\W]*?", string.Empty), @"[\w\W]*?", string.Empty); // in changefeed test in was changing string baselineText = Regex.Replace( Regex.Replace( - Regex.Replace( File.ReadAllText(baselinePath), @"\s+", string.Empty), - @"[\w\W]*?", string.Empty), @"[\w\W]*?", string.Empty); int commonPrefixLength = 0; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index f650f1e6f5..a6683679f7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Operation.ExecuteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index c10633d3fa..6fd72499bb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -134,16 +134,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -292,16 +292,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -450,16 +450,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -608,16 +608,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -766,16 +766,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -924,16 +924,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1082,16 +1082,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1240,16 +1240,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1398,16 +1398,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1556,16 +1556,16 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2288,7 +2288,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index e4fa3665a8..c04d573153 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -952,11 +952,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1569,11 +1569,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2167,11 +2167,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Change Feed Iterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2785,11 +2785,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3066,8 +3066,8 @@ } ] }]]> - Operation.Change Feed Estimator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Change Feed Estimator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 3825735788..cd053b58e2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -107,8 +107,8 @@ } ] }]]> - Operation.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -207,8 +207,8 @@ } ] }]]> - Operation.DeleteAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 80dbbfb7f1..7d6a68adca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -148,7 +148,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -391,7 +391,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -616,7 +616,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -873,7 +873,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1194,7 +1194,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1348,7 +1348,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.message + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 5b54a51e31..21db429e27 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -574,10 +574,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1180,10 +1180,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1767,10 +1767,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2374,10 +2374,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3048,10 +3048,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3644,10 +3644,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4260,10 +4260,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 22feeace3c..070da7032d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -536,10 +536,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1104,10 +1104,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1653,10 +1653,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.FeedIterator Read Next Asynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2222,10 +2222,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.Typed FeedIterator ReadNextAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index c6a9fcee7f..dd99e1694b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -542,12 +542,12 @@ } ] }]]> - Operation.ReadManyItemsStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadManyItemsStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1112,7 +1112,7 @@ } ] }]]> - Operation.ReadManyItemsAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadManyItemsAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 5a764d9525..6172446645 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -89,7 +89,7 @@ } ] }]]> - Operation.CreateItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -178,7 +178,7 @@ } ] }]]> - Operation.ReadItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -275,7 +275,7 @@ } ] }]]> - Operation.ReplaceItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReplaceItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -367,7 +367,7 @@ } ] }]]> - Operation.DeleteItemStreamAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 63edd0154e..2aeaf80b15 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -109,7 +109,7 @@ } ] }]]> - Operation.CreateItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -203,7 +203,7 @@ } ] }]]> - Operation.ReadItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReadItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -310,7 +310,7 @@ } ] }]]> - Operation.ReplaceItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.ReplaceItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -406,7 +406,7 @@ } ] }]]> - Operation.DeleteItemAsynckindaz.namespacedb.operationdb.namedb.cosmosdb.containerdb.cosmosdb.operation_typedb.systemdb.cosmosdb.machine_idnet.peer.namedb.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.regions_contacted + Operation.DeleteItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index f62d89e016..b0c605839e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -48,7 +48,9 @@ public static void IsValid(Activity activity) "db.cosmosdb.request_diagnostics", "exception.type", "exception.message", - "exception.stacktrace" + "exception.stacktrace", + "db.cosmosdb.activity_id", + "db.cosmosdb.correlated_activity_id" }; foreach (KeyValuePair actualTag in activity.Tags) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 5e86ee7270..c46d8578b0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -159,7 +159,6 @@ protected override void OnEventSourceCreated(EventSource eventSource) protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder builder = new StringBuilder(); - Console.WriteLine(eventData.Payload[0].ToString()); builder.Append("") .Append("Ideally, this should contain request diagnostics but request diagnostics is " + "subject to change with each request as it contains few unique id. " + @@ -222,6 +221,17 @@ public override void Dispose() private string GenerateTagForBaselineTest(Activity activity) { + List tagsWithStaticValue = new List + { + "kind", + "az.namespace", + "db.operation", + "db.system", + "net.peer.name", + "db.cosmosdb.connection_mode", + "db.cosmosdb.operation_type", + "db.cosmosdb.regions_contacted" + }; StringBuilder builder = new StringBuilder(); builder.Append("") @@ -235,7 +245,16 @@ private string GenerateTagForBaselineTest(Activity activity) .Append("") .Append(tag.Key) .Append(""); + + if (tagsWithStaticValue.Contains(tag.Key)) + { + builder + .Append("") + .Append(tag.Value) + .Append(""); + } } + builder.Append(""); return builder.ToString(); @@ -246,7 +265,12 @@ public List GetRecordedAttributes() List generatedActivityTagsForBaselineXmls = new(); List collectedActivities = new List(CustomListener.CollectedActivities); - collectedActivities.ForEach(activity => generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity))); + collectedActivities.OrderBy(act => act.OperationName); + + foreach (Activity activity in collectedActivities) + { + generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); + } List outputList = new List(); if(generatedActivityTagsForBaselineXmls != null && generatedActivityTagsForBaselineXmls.Count > 0) From 612337cfbd445a95042457b672819e36e0a6319e Mon Sep 17 00:00:00 2001 From: Arthur Augsten Date: Wed, 11 Jan 2023 10:24:53 -0500 Subject: [PATCH 037/337] Documentation: Fixes CosmosClientBuilder.WithConnectionModeGateway parameter description (#3643) * Fixed CosmosClientBuilder.WithConnectionModeGateway documentation * Update Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs Co-authored-by: Ruben Bartelink Co-authored-by: Augsten Co-authored-by: Ruben Bartelink --- Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 4621e13557..d47f168764 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -438,7 +438,7 @@ internal CosmosClientBuilder WithDistributingTracing(DistributedTracingOptions o /// /// Sets the connection mode to Gateway. This is used by the client when connecting to the Azure Cosmos DB service. /// - /// The number specifies the time to wait for response to come back from network peer. Default is 60 connections + /// The number specifies the number of connections that may be opened simultaneously. Default is 50 connections /// Get or set the proxy information used for web requests. /// /// For more information, see Connection policy: Use direct connection mode. From 55f9ce8a5f07a99209b8b6a8d633d8ed15b14d5b Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 11 Jan 2023 13:07:42 -0800 Subject: [PATCH 038/337] Upgrade Resiliency: Refactors Implementation for Opening Rntbd Connections to Backend Replicas in Direct Mode. (#3640) * Code changes to refactor implementations for opening connections to all replicas. Fixed test failures due to Direct package upgrade. * Code changes to add poland central region as a part of Regions.cs * Code changes to update contract to reflect new regions. * Revert "Code changes to update contract to reflect new regions." This reverts commit f171b3c1c9889043556ddf96bcd33ccd79565ad9. * Revert "Code changes to add poland central region as a part of Regions.cs" This reverts commit 1aafbf18f6d80e9a92baa301b6b23cf065e4b155. --- Directory.Build.props | 2 +- .../src/Routing/GatewayAddressCache.cs | 46 +-- .../src/Routing/GlobalAddressResolver.cs | 24 +- .../src/Routing/IAddressCache.cs | 7 + .../CosmosHeaderTests.cs | 9 +- .../TransportWrapperTests.cs | 25 +- .../TraceWriterBaselineTests.TraceData.xml | 94 +----- .../ClientRetryPolicyTests.cs | 7 +- .../GatewayAddressCacheTests.cs | 268 +++++++++++++----- .../StoreReaderTest.cs | 2 +- ...entSideRequestStatisticsTraceDatumTests.cs | 21 +- .../Tracing/TraceTests.cs | 29 +- .../Tracing/TraceWriterBaselineTests.cs | 42 +-- 13 files changed, 266 insertions(+), 310 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 651e1f89e5..658186357b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ 3.31.2 3.31.2 preview - 3.29.4 + 3.30.0 2.0.0 2.0.0 preview diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 210e5951fe..7c6355591e 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -50,6 +50,7 @@ internal class GatewayAddressCache : IAddressCache, IDisposable private Tuple masterPartitionAddressCache; private DateTime suboptimalMasterPartitionTimestamp; private bool disposedValue; + private IOpenConnectionsHandler openConnectionsHandler; public GatewayAddressCache( Uri serviceEndpoint, @@ -57,6 +58,7 @@ public GatewayAddressCache( ICosmosAuthorizationTokenProvider tokenProvider, IServiceConfigurationReader serviceConfigReader, CosmosHttpClient httpClient, + IOpenConnectionsHandler openConnectionsHandler, long suboptimalPartitionForceRefreshIntervalInSeconds = 600, bool enableTcpConnectionEndpointRediscovery = false) { @@ -80,6 +82,8 @@ public GatewayAddressCache( GatewayAddressCache.protocolFilterFormat, Constants.Properties.Protocol, GatewayAddressCache.ProtocolString(this.protocol)); + + this.openConnectionsHandler = openConnectionsHandler; } public Uri ServiceEndpoint => this.serviceEndpoint; @@ -88,7 +92,7 @@ public async Task OpenConnectionsAsync( string databaseName, ContainerProperties collection, IReadOnlyList partitionKeyRangeIdentities, - Func openConnectionHandler, + bool shouldOpenRntbdChannels, CancellationToken cancellationToken) { List>> tasks = new (); @@ -157,47 +161,21 @@ public async Task OpenConnectionsAsync( new PartitionKeyRangeIdentity(collection.ResourceId, addressInfo.Item1.PartitionKeyRangeId), addressInfo.Item2); - if (openConnectionHandler != null) + if (this.openConnectionsHandler != null && shouldOpenRntbdChannels) { - await this.OpenRntbdChannelsAsync( - addressInfo, - openConnectionHandler); + await this.openConnectionsHandler + .TryOpenRntbdChannelsAsync( + addresses: addressInfo.Item2.Get(Protocol.Tcp)?.ReplicaTransportAddressUris); } } } } } - /// - /// Invokes the transport client delegate to open the Rntbd connection - /// and establish Rntbd context negotiation to the backend replica nodes. - /// - /// An instance of containing the partition key id - /// and it's corresponding address information. - /// The transport client callback delegate to be invoked at a - /// later point of time. - private async Task OpenRntbdChannelsAsync( - Tuple addressInfo, - Func openConnectionHandlerAsync) + /// + public void SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHandler) { - foreach (AddressInformation address in addressInfo.Item2.AllAddresses) - { - DefaultTrace.TraceVerbose("Attempting to open Rntbd connection to backend uri: {0}. '{1}'", - address.PhysicalUri, - System.Diagnostics.Trace.CorrelationManager.ActivityId); - try - { - await openConnectionHandlerAsync( - new Uri(address.PhysicalUri)); - } - catch (Exception ex) - { - DefaultTrace.TraceWarning("Failed to open Rntbd connection to backend uri: {0} with exception: {1}. '{2}'", - address.PhysicalUri, - ex, - System.Diagnostics.Trace.CorrelationManager.ActivityId); - } - } + this.openConnectionsHandler = openConnectionsHandler; } public async Task TryGetAddressesAsync( diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs index 4e31b0fb40..51a6c6d2f3 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs @@ -39,6 +39,7 @@ internal sealed class GlobalAddressResolver : IAddressResolverExtension, IDispos private readonly CosmosHttpClient httpClient; private readonly ConcurrentDictionary addressCacheByEndpoint; private readonly bool enableTcpConnectionEndpointRediscovery; + private IOpenConnectionsHandler openConnectionsHandler; public GlobalAddressResolver( GlobalEndpointManager endpointManager, @@ -108,7 +109,7 @@ public async Task OpenAsync( databaseName: databaseName, collection: collection, partitionKeyRangeIdentities: ranges, - openConnectionHandler: null, + shouldOpenRntbdChannels: false, cancellationToken: cancellationToken)); } @@ -116,16 +117,14 @@ public async Task OpenAsync( } /// - /// Invokes the gateway address cache and passes the deligate to be invoked from the same. + /// Invokes the gateway address cache to open the rntbd connections to the backend replicas. /// /// A string containing the name of the database. /// A string containing the container's link uri. - /// The transport client callback delegate to be invoked at a later point of time. /// An Instance of the . public async Task OpenConnectionsToAllReplicasAsync( string databaseName, string containerLinkUri, - Func openConnectionHandlerAsync, CancellationToken cancellationToken = default) { try @@ -180,7 +179,7 @@ await this.addressCacheByEndpoint[firstPreferredReadRegion] databaseName: databaseName, collection: collection, partitionKeyRangeIdentities: partitionKeyRangeIdentities, - openConnectionHandler: openConnectionHandlerAsync, + shouldOpenRntbdChannels: true, cancellationToken: cancellationToken); } @@ -197,6 +196,20 @@ await this.addressCacheByEndpoint[firstPreferredReadRegion] } } + /// + public void SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHandler) + { + this.openConnectionsHandler = openConnectionsHandler; + + // Sets the openConnectionsHandler for the existing address cache. + // For the new address caches added later, the openConnectionsHandler + // will be set through the constructor. + foreach (EndpointCache endpointCache in this.addressCacheByEndpoint.Values) + { + endpointCache.AddressCache.SetOpenConnectionsHandler(openConnectionsHandler); + } + } + public async Task ResolveAsync( DocumentServiceRequest request, bool forceRefresh, @@ -284,6 +297,7 @@ private EndpointCache GetOrAddEndpoint(Uri endpoint) this.tokenProvider, this.serviceConfigReader, this.httpClient, + this.openConnectionsHandler, enableTcpConnectionEndpointRediscovery: this.enableTcpConnectionEndpointRediscovery); string location = this.endpointManager.GetLocation(endpoint); diff --git a/Microsoft.Azure.Cosmos/src/Routing/IAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/IAddressCache.cs index e8a6ade3ba..35d10fa622 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/IAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/IAddressCache.cs @@ -29,5 +29,12 @@ Task TryGetAddressesAsync( ServiceIdentity serviceIdentity, bool forceRefreshPartitionAddresses, CancellationToken cancellationToken); + + /// + /// Sets the instance to a global readonly + /// field for invoking the open connection request at a later point of time. + /// + /// An instance of . + void SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHandler); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosHeaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosHeaderTests.cs index 95501d0b91..4bc35b105c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosHeaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosHeaderTests.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Collections.Generic; + using System.Linq; using System.Net; using System.Reflection; using System.Threading; @@ -102,13 +103,13 @@ public override async Task SendAsync(RequestMessage request, Ca private void ValidateLazyHeadersAreNotCreated(CosmosMessageHeadersInternal internalHeaders) { RequestNameValueCollection storeRequestHeaders = (RequestNameValueCollection)internalHeaders.INameValueCollection; - FieldInfo lazyHeaders = typeof(Documents.Collections.RequestNameValueCollection).GetField("lazyNotCommonHeaders", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); - Lazy> lazyNotCommonHeaders = (Lazy>)lazyHeaders.GetValue(storeRequestHeaders); + FieldInfo fieldInfo = storeRequestHeaders.GetType().GetField("notCommonHeaders", BindingFlags.Instance | BindingFlags.NonPublic); + Dictionary notCommonHeaders = (Dictionary)fieldInfo.GetValue(storeRequestHeaders); // Use the if instead of Assert.IsFalse to avoid creating the dictionary in the error message - if (lazyNotCommonHeaders.IsValueCreated) + if (notCommonHeaders != null && notCommonHeaders.Any()) { - Assert.Fail($"The lazy dictionary should not be created. Please add the following headers to the {nameof(Documents.Collections.RequestNameValueCollection)}: {JsonConvert.SerializeObject(lazyNotCommonHeaders.Value)}"); + Assert.Fail($"The lazy dictionary should not be created. Please add the following headers to the {nameof(Documents.Collections.RequestNameValueCollection)}: {JsonConvert.SerializeObject(notCommonHeaders)}"); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs index d90e23a397..720f37375c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs @@ -144,33 +144,10 @@ private static void ThrowTransportExceptionOnItemOperation( userPayload: true, payloadSent: false); - DocumentClientException documentClientException = new DocumentClientException( - message: "Exception", - innerException: transportException, - statusCode: System.Net.HttpStatusCode.Gone); IClientSideRequestStatistics requestStatistics = request.RequestContext.ClientRequestStatistics; requestStatistics.RecordResponse( request, - new StoreResult( - storeResponse: null, - exception: documentClientException, - partitionKeyRangeId: "PkRange", - lsn: 42, - quorumAckedLsn: 4242, - requestCharge: 9000.42, - currentReplicaSetSize: 3, - currentWriteQuorum: 4, - isValid: true, - storePhysicalAddress: physicalAddress, - globalCommittedLSN: 2, - numberOfReadRegions: 1, - itemLSN: 5, - sessionToken: null, - usingLocalLSN: true, - activityId: Guid.NewGuid().ToString(), - backendRequestDurationInMs: "0", - retryAfterInMs: "42", - transportRequestStats: new TransportRequestStats()), + StoreResult.CreateForTesting(transportRequestStats: new TransportRequestStats()).Target, DateTime.MinValue, DateTime.MaxValue); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml index f38fc77bb8..96c67772e6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml @@ -214,26 +214,7 @@ StoreResponseStatistics storeResponseStatistics = new StoreResponseStatistics( DateTime.MinValue, DateTime.MaxValue, - new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: 42.ToString(), - lsn: 1337, - quorumAckedLsn: 23, - requestCharge: 3.14, - currentReplicaSetSize: 4, - currentWriteQuorum: 3, - isValid: true, - storePhysicalAddress: new Uri("http://storephysicaladdress.com"), - globalCommittedLSN: 1234, - numberOfReadRegions: 13, - itemLSN: 15, - sessionToken: new SimpleSessionToken(42), - usingLocalLSN: true, - activityId: Guid.Empty.ToString(), - backendRequestDurationInMs: "4.2", - retryAfterInMs: "42", - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()), + StoreResult.CreateForTesting(transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()).Target, ResourceType.Document, OperationType.Query, "42", @@ -357,7 +338,7 @@ "IsValid": true, "StorePhysicalAddress": "http://storephysicaladdress.com/", "RequestCharge": 3.14, - "RetryAfterInMs": "42", + "RetryAfterInMs": "9000", "BELatencyInMs": "4.2", "transportRequestTimeline": { "requestTimeline": [ @@ -439,26 +420,7 @@ StoreResponseStatistics storeResponseStatistics = new StoreResponseStatistics( requestStartTime: default, requestResponseTime: default, - new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: default, - partitionKeyRangeId: default, - lsn: default, - quorumAckedLsn: default, - requestCharge: default, - currentReplicaSetSize: default, - currentWriteQuorum: default, - isValid: default, - storePhysicalAddress: default, - globalCommittedLSN: default, - numberOfReadRegions: default, - itemLSN: default, - sessionToken: default, - usingLocalLSN: default, - activityId: default, - retryAfterInMs: default, - backendRequestDurationInMs: default, - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()), + StoreResult.CreateForTesting(storeResponse: new StoreResponse()).Target, resourceType: default, operationType: default, requestSessionToken: default, @@ -567,55 +529,7 @@ "RequestCharge": 0, "RetryAfterInMs": null, "BELatencyInMs": null, - "transportRequestTimeline": { - "requestTimeline": [ - { - "event": "Created", - "startTimeUtc": "2021-12-31T23:59:59.059Z", - "durationInMs": 1 - }, - { - "event": "ChannelAcquisitionStarted", - "startTimeUtc": "2021-12-31T23:59:59.06Z", - "durationInMs": 0 - }, - { - "event": "Pipelined", - "startTimeUtc": "2021-12-31T23:59:59.06Z", - "durationInMs": 0 - }, - { - "event": "Transit Time", - "startTimeUtc": "2021-12-31T23:59:59.06Z", - "durationInMs": 0 - }, - { - "event": "Received", - "startTimeUtc": "2021-12-31T23:59:59.06Z", - "durationInMs": 0 - }, - { - "event": "Completed", - "startTimeUtc": "2021-12-31T23:59:59.06Z", - "durationInMs": 0 - } - ], - "serviceEndpointStats": { - "inflightRequests": 2, - "openConnections": 1 - }, - "connectionStats": { - "waitforConnectionInit": "True", - "callsPendingReceive": 1, - "lastSendAttempt": "2021-12-31T23:59:59.059Z", - "lastSend": "2021-12-31T23:59:59.059Z", - "lastReceive": "2021-12-31T23:59:59.059Z" - }, - "requestSizeInBytes": 2, - "requestBodySizeInBytes": 1, - "responseMetadataSizeInBytes": 1, - "responseBodySizeInBytes": 1 - }, + "transportRequestTimeline": null, "TransportException": null } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs index 7faeba2a35..a41f08afa1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs @@ -521,7 +521,6 @@ public Task UpdateAsync(IReadOnlyList addressCacheTokens, Can public Task OpenConnectionsToAllReplicasAsync( string databaseName, string containerLinkUri, - Func openConnectionHandlerAsync, CancellationToken cancellationToken = default) { throw new NotImplementedException(); @@ -531,6 +530,12 @@ public Task UpdateAsync(Documents.Rntbd.ServerKey serverKey, CancellationToken c { throw new NotImplementedException(); } + + public void SetOpenConnectionsHandler( + IOpenConnectionsHandler openConnectionHandler) + { + throw new NotImplementedException(); + } } private class MockTransportClient : TransportClient diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 46dbbc609e..3954b4ae8f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -81,6 +81,7 @@ public void TestGatewayAddressCacheAutoRefreshOnSuboptimalPartition() this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: null, suboptimalPartitionForceRefreshIntervalInSeconds: 2); int initialAddressesCount = cache.TryGetAddressesAsync( @@ -116,6 +117,7 @@ public async Task TestGatewayAddressCacheUpdateOnConnectionResetAsync() this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: null, suboptimalPartitionForceRefreshIntervalInSeconds: 2, enableTcpConnectionEndpointRediscovery: true); @@ -173,6 +175,7 @@ public async Task TestGatewayAddressCacheAvoidCacheRefresWhenAlreadyUpdatedAsync this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: null, suboptimalPartitionForceRefreshIntervalInSeconds: 2, enableTcpConnectionEndpointRediscovery: true); @@ -224,7 +227,6 @@ public async Task TestGatewayAddressCacheAvoidCacheRefresWhenAlreadyUpdatedAsync mockHttpHandler.VerifyAll(); } - [TestMethod] [Timeout(2000)] public void GlobalAddressResolverUpdateAsyncSynchronizationTest() @@ -287,6 +289,7 @@ public async Task GatewayAddressCacheInNetworkRequestTestAsync() this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: null, suboptimalPartitionForceRefreshIntervalInSeconds: 2, enableTcpConnectionEndpointRediscovery: true); @@ -323,15 +326,15 @@ public async Task GatewayAddressCacheInNetworkRequestTestAsync() /// /// Test to validate that when is called with a - /// valid open connection handler callback delegate, the delegate method is indeed invoked. + /// valid open connection handler, the handler method is indeed invoked. /// [TestMethod] [Owner("dkunda")] - public async Task OpenConnectionsAsync_WithValidOpenConnectionHandlerDelegate_ShouldInvokeDelegateMethod() + public async Task OpenConnectionsAsync_WithValidOpenConnectionHandler_ShouldInvokeHandlerMethod() { // Arrange. FakeMessageHandler messageHandler = new (); - FakeTransportClient transportClient = new (shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk="); containerProperties.Id = "TestId"; containerProperties.PartitionKeyPath = "/pk"; @@ -346,6 +349,7 @@ public async Task OpenConnectionsAsync_WithValidOpenConnectionHandlerDelegate_Sh this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, suboptimalPartitionForceRefreshIntervalInSeconds: 2); // Act. @@ -356,26 +360,30 @@ await cache.OpenConnectionsAsync( { this.testPartitionKeyRangeIdentity }, - openConnectionHandler: transportClient.OpenConnectionAsync, + shouldOpenRntbdChannels: true, cancellationToken: CancellationToken.None); // Assert. - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(3, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 3, + expectedSuccessCount: 3); } /// /// Test to validate that when is invoked with a - /// open connection handler callback delegate that throws an exception, the delegate method is indeed invoked + /// open connection handler that throws an exception, the handler method is indeed invoked /// and the exception is handled in such a way that the cosmos client initialization does not fail. /// [TestMethod] [Owner("dkunda")] - public async Task OpenConnectionsAsync_WhenConnectionHandlerDelegateThrowsException_ShouldNotFailInitialization() + public async Task OpenConnectionsAsync_WhenConnectionHandlerThrowsException_ShouldNotFailInitialization() { // Arrange. FakeMessageHandler messageHandler = new (); - FakeTransportClient transportClient = new (shouldFailTransport: true); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new(failingIndexes: new HashSet() { 0, 1, 2}); ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk="); containerProperties.Id = "TestId"; containerProperties.PartitionKeyPath = "/pk"; @@ -387,6 +395,7 @@ public async Task OpenConnectionsAsync_WhenConnectionHandlerDelegateThrowsExcept this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, suboptimalPartitionForceRefreshIntervalInSeconds: 2); // Act. @@ -397,26 +406,30 @@ await cache.OpenConnectionsAsync( { this.testPartitionKeyRangeIdentity }, - openConnectionHandler: transportClient.OpenConnectionAsync, + shouldOpenRntbdChannels: true, cancellationToken: CancellationToken.None); // Assert. - Assert.AreEqual(3, transportClient.GetExceptionCount()); - Assert.AreEqual(0, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 3, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 3, + expectedSuccessCount: 0); } /// /// Test to validate that when is invoked with a null - /// open connection handler callback delegate, the delegate is never invoked, thus no attempt to open connection + /// open connection handler, the handler method is never invoked, thus no attempt to open connections /// to the backend replica happens. /// [TestMethod] [Owner("dkunda")] - public async Task OpenConnectionsAsync_WithNullOpenConnectionHandlerDelegate_ShouldNotInvokeDelegateMethod() + public async Task OpenConnectionsAsync_WithNullOpenConnectionHandler_ShouldNotInvokeHandlerMethod() { // Arrange. FakeMessageHandler messageHandler = new (); - FakeTransportClient transportClient = new(shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk="); containerProperties.Id = "TestId"; containerProperties.PartitionKeyPath = "/pk"; @@ -431,6 +444,7 @@ public async Task OpenConnectionsAsync_WithNullOpenConnectionHandlerDelegate_Sho this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: null, suboptimalPartitionForceRefreshIntervalInSeconds: 2); // Act. @@ -441,25 +455,29 @@ await cache.OpenConnectionsAsync( { this.testPartitionKeyRangeIdentity }, - openConnectionHandler: null, + shouldOpenRntbdChannels: true, cancellationToken: CancellationToken.None); // Assert. - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(0, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 0, + expectedReceivedAddressesCount: 0, + expectedSuccessCount: 0); } /// /// Test to validate that when is called with a - /// valid open connection handler callback delegate, the delegate method is indeed invoked and an attempt is made to open + /// valid open connection handler, the handler method is indeed invoked and an attempt is made to open /// the connections to the backend replicas. /// [TestMethod] [Owner("dkunda")] - public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WithValidHandlerDelegate_ShouldOpenConnectionsToBackend() + public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WithValidHandler_ShouldOpenConnectionsToBackend() { // Arrange. - FakeTransportClient transportClient = new (shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); UserAgentContainer container = new (clientId: 0); FakeMessageHandler messageHandler = new (); AccountProperties databaseAccount = new (); @@ -509,29 +527,35 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WithVa connectionPolicy: connectionPolicy, httpClient: MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler))); + globalAddressResolver.SetOpenConnectionsHandler( + openConnectionsHandler: fakeOpenConnectionHandler); + // Act. await globalAddressResolver.OpenConnectionsToAllReplicasAsync( databaseName: "test-db", containerLinkUri: "https://test.uri.cosmos.com", - openConnectionHandlerAsync: transportClient.OpenConnectionAsync, CancellationToken.None); // Assert. - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(3, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 3, + expectedSuccessCount: 3); } /// /// Test to validate that when is called with a - /// open connection handler callback delegate that throws an exception, the delegate method is indeed invoked and the - /// exception is handled in such a way that the cosmos client initialization does not fail. + /// open connection handler that throws an exception, the handler method is indeed invoked and the exception is handled + /// in such a way that the cosmos client initialization does not fail. /// [TestMethod] [Owner("dkunda")] public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenHandlerDelegateThrowsException_ShouldNotFailInitialization() { // Arrange. - FakeTransportClient transportClient = new(shouldFailTransport: true); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet() { 0, 2}); UserAgentContainer container = new(clientId: 0); FakeMessageHandler messageHandler = new(); AccountProperties databaseAccount = new(); @@ -581,16 +605,22 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenHa connectionPolicy: connectionPolicy, httpClient: MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler))); + globalAddressResolver.SetOpenConnectionsHandler( + openConnectionsHandler: fakeOpenConnectionHandler); + // Act. await globalAddressResolver.OpenConnectionsToAllReplicasAsync( databaseName: "test-db", containerLinkUri: "https://test.uri.cosmos.com", - openConnectionHandlerAsync: transportClient.OpenConnectionAsync, CancellationToken.None); // Assert. - Assert.AreEqual(3, transportClient.GetExceptionCount()); - Assert.AreEqual(0, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 2, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 3, + expectedSuccessCount: 1); } /// @@ -603,7 +633,7 @@ await globalAddressResolver.OpenConnectionsToAllReplicasAsync( public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenInternalExceptionThrownApartFromTransportError_ShouldThrowException() { // Arrange. - FakeTransportClient transportClient = new(shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); UserAgentContainer container = new(clientId: 0); FakeMessageHandler messageHandler = new(); AccountProperties databaseAccount = new(); @@ -664,18 +694,24 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenIn connectionPolicy: connectionPolicy, httpClient: MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler))); + globalAddressResolver.SetOpenConnectionsHandler( + openConnectionsHandler: fakeOpenConnectionHandler); + // Act. Exception ex = await Assert.ThrowsExceptionAsync(() => globalAddressResolver.OpenConnectionsToAllReplicasAsync( databaseName: "test-db", containerLinkUri: "https://test.uri.cosmos.com", - openConnectionHandlerAsync: transportClient.OpenConnectionAsync, CancellationToken.None)); // Assert. Assert.IsNotNull(ex); Assert.AreEqual(exceptionMessage, ex.Message); - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(0, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 0, + expectedReceivedAddressesCount: 0, + expectedSuccessCount: 0); } /// @@ -688,7 +724,7 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenIn public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenNullCollectionReturned_ShouldThrowException() { // Arrange. - FakeTransportClient transportClient = new (shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); UserAgentContainer container = new (clientId: 0); FakeMessageHandler messageHandler = new (); AccountProperties databaseAccount = new (); @@ -734,33 +770,39 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenNu connectionPolicy: connectionPolicy, httpClient: MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler))); + globalAddressResolver.SetOpenConnectionsHandler( + openConnectionsHandler: fakeOpenConnectionHandler); + // Act. CosmosException ce = await Assert.ThrowsExceptionAsync(() => globalAddressResolver.OpenConnectionsToAllReplicasAsync( databaseName: "test-db", containerLinkUri: "https://test.uri.cosmos.com", - openConnectionHandlerAsync: transportClient.OpenConnectionAsync, CancellationToken.None)); // Assert. Assert.IsNotNull(ce); Assert.IsTrue(ce.Message.Contains("Could not resolve the collection")); - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(0, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 0, + expectedReceivedAddressesCount: 0, + expectedSuccessCount: 0); } /// /// Test to validate that when is called with a - /// valid open connection handler callback delegate and some of the address resolving fails with exception, - /// then the GatewayAddressCache should ignore the failed addresses and the delegate method is indeed invoked + /// valid open connection handler and some of the address resolving fails with exception, then the + /// GatewayAddressCache should ignore the failed addresses and the handler method is indeed invoked /// for all resolved addresses. /// [TestMethod] [Owner("dkunda")] - public async Task OpenConnectionsAsync_WhenSomeAddressResolvingFailsWithException_ShouldIgnoreExceptionsAndInvokeDelegateMethodForOtherAddresses() + public async Task OpenConnectionsAsync_WhenSomeAddressResolvingFailsWithException_ShouldIgnoreExceptionsAndInvokeHandlerMethodForOtherAddresses() { // Arrange. FakeMessageHandler messageHandler = new (); - FakeTransportClient transportClient = new (shouldFailTransport: false); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new (failingIndexes: new HashSet()); ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk="); containerProperties.Id = "TestId"; containerProperties.PartitionKeyPath = "/pk"; @@ -810,6 +852,7 @@ public async Task OpenConnectionsAsync_WhenSomeAddressResolvingFailsWithExceptio this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, mockHttpClient.Object, + openConnectionsHandler: fakeOpenConnectionHandler, suboptimalPartitionForceRefreshIntervalInSeconds: 2); // Act. @@ -817,12 +860,38 @@ await cache.OpenConnectionsAsync( databaseName: "test-database", collection: containerProperties, partitionKeyRangeIdentities: partitionKeyRangeIdentities, - openConnectionHandler: transportClient.OpenConnectionAsync, + shouldOpenRntbdChannels: true, cancellationToken: CancellationToken.None); // Assert. - Assert.AreEqual(0, transportClient.GetExceptionCount()); - Assert.AreEqual(addresses.Count, transportClient.GetSuccessfulInvocationCount()); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: addresses.Count, + expectedSuccessCount: addresses.Count); + } + + /// + /// Helper method to assert on the class attributes + /// to match with that of the expected ones. + /// + /// An instance of the . + /// The expected exception count for the test. + /// The expected method invocation count for the test. + /// The expected received addresses count for the test. + /// The expected successful messages count for the test. + private static void AssertOpenConnectionHandlerAttributes( + FakeOpenConnectionHandler fakeOpenConnectionHandler, + int expectedExceptionCount, + int expectedMethodInvocationCount, + int expectedReceivedAddressesCount, + int expectedSuccessCount) + { + Assert.AreEqual(expectedExceptionCount, fakeOpenConnectionHandler.GetExceptionCount()); + Assert.AreEqual(expectedMethodInvocationCount, fakeOpenConnectionHandler.GetMethodInvocationCount()); + Assert.AreEqual(expectedReceivedAddressesCount, fakeOpenConnectionHandler.GetReceivedAddressesCount()); + Assert.AreEqual(expectedSuccessCount, fakeOpenConnectionHandler.GetSuccessfulInvocationCount()); } private class FakeMessageHandler : HttpMessageHandler @@ -911,44 +980,111 @@ public override void Post(SendOrPostCallback d, object state) } } - public class FakeTransportClient + public class FakeOpenConnectionHandler : IOpenConnectionsHandler { private int exceptionCounter = 0; + private int methodInvocationCounter = 0; private int successInvocationCounter = 0; - private readonly bool shouldFailTransport; + private int totalReceivedAddressesCounter = 0; + private readonly HashSet failingIndexes; + private readonly bool useAttemptBasedFailingIndexs; + private readonly ManualResetEvent manualResetEvent; + private readonly Dictionary> failIndexesByAttempts; + + public FakeOpenConnectionHandler( + HashSet failingIndexes, + ManualResetEvent manualResetEvent = null) + { + this.failingIndexes = failingIndexes; + this.manualResetEvent = manualResetEvent; + } + + public FakeOpenConnectionHandler( + Dictionary> failIndexesByAttempts, + ManualResetEvent manualResetEvent = null) + { + this.useAttemptBasedFailingIndexs = true; + this.failIndexesByAttempts = failIndexesByAttempts; + this.manualResetEvent = manualResetEvent; + } + + public int GetSuccessfulInvocationCount() + { + return this.successInvocationCounter; + } + + public int GetExceptionCount() + { + return this.exceptionCounter; + } - public FakeTransportClient(bool shouldFailTransport) + public int GetReceivedAddressesCount() { - this.shouldFailTransport = shouldFailTransport; + return this.totalReceivedAddressesCounter; } - public Task OpenConnectionAsync(Uri physicalAddress) + public int GetMethodInvocationCount() { - if (this.shouldFailTransport) + return this.methodInvocationCounter; + } + + Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( + IReadOnlyList addresses) + { + this.totalReceivedAddressesCounter = addresses.Count; + for (int i = 0; i < addresses.Count; i++) { - this.exceptionCounter++; - throw new TransportException( - errorCode: TransportErrorCode.ConnectionBroken, - innerException: new Exception("Transport Error Occurred."), - activityId: Guid.NewGuid(), - requestUri: physicalAddress, - sourceDescription: "SourceDescription", - userPayload: true, - payloadSent: false); + if (this.useAttemptBasedFailingIndexs) + { + if (this.failIndexesByAttempts.ContainsKey(i) && this.failIndexesByAttempts[i].Contains(this.methodInvocationCounter)) + { + this.ExecuteFailureCondition( + addresses: addresses, + index: i); + } + else + { + this.ExecuteSuccessCondition( + addresses: addresses, + index: i); + } + } + else + { + if (this.failingIndexes.Contains(i)) + { + this.ExecuteFailureCondition( + addresses: addresses, + index: i); + } + else + { + this.ExecuteSuccessCondition( + addresses: addresses, + index: i); + } + } } - this.successInvocationCounter++; + this.methodInvocationCounter++; + this.manualResetEvent?.Set(); return Task.CompletedTask; } - public int GetSuccessfulInvocationCount() + private void ExecuteSuccessCondition( + IReadOnlyList addresses, + int index) { - return this.successInvocationCounter; + addresses[index].SetConnected(); + this.successInvocationCounter++; } - public int GetExceptionCount() + private void ExecuteFailureCondition( + IReadOnlyList addresses, + int index) { - return this.exceptionCounter; + addresses[index].SetUnhealthy(); + this.exceptionCounter++; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs index 7251848ea7..b92ca3c804 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs @@ -541,7 +541,7 @@ public void StoreReaderBarrierTest() // reads always go to read quorum (2) replicas int replicaCountToRead = 2; - IList result = storeReader.ReadMultipleReplicaAsync( + IList> result = storeReader.ReadMultipleReplicaAsync( entity, false /*includePrimary*/, replicaCountToRead, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs index aac19174c9..2ec6e9db62 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs @@ -21,26 +21,7 @@ public class ClientSideRequestStatisticsTraceDatumTests private static readonly HttpRequestMessage request = new HttpRequestMessage(); private static readonly Uri uri = new Uri("http://someUri1.com"); private static readonly DocumentServiceRequest requestDsr = DocumentServiceRequest.Create(OperationType.Read, resourceType: ResourceType.Document, authorizationTokenType: AuthorizationTokenType.PrimaryMasterKey); - private static readonly StoreResult storeResult = new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: 42.ToString(), - lsn: 1337, - quorumAckedLsn: 23, - requestCharge: 3.14, - currentReplicaSetSize: 4, - currentWriteQuorum: 3, - isValid: true, - storePhysicalAddress: new Uri("http://storephysicaladdress.com"), - globalCommittedLSN: 1234, - numberOfReadRegions: 13, - itemLSN: 15, - sessionToken: new SimpleSessionToken(42), - usingLocalLSN: true, - activityId: Guid.Empty.ToString(), - backendRequestDurationInMs: "4.2", - retryAfterInMs: "42", - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()); + private static readonly StoreResult storeResult = StoreResult.CreateForTesting(storeResponse: new StoreResponse()).Target; /// /// This test is needed because different parts of the SDK use the same ClientSideRequestStatisticsTraceDatum across multiple diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs index 3a883d2456..f747d35d22 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs @@ -100,31 +100,12 @@ public void ValidateStoreResultSerialization() ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); trace.AddDatum(datumKey, datum); - StoreResult storeResult = new StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: 42.ToString(), - lsn: 1337, - quorumAckedLsn: 23, - requestCharge: 3.14, - currentReplicaSetSize: 4, - currentWriteQuorum: 3, - isValid: true, - storePhysicalAddress: new Uri("http://storephysicaladdress.com"), - globalCommittedLSN: 1234, - numberOfReadRegions: 13, - itemLSN: 15, - sessionToken: new SimpleSessionToken(42), - usingLocalLSN: true, - activityId: Guid.Empty.ToString(), - backendRequestDurationInMs: "4.2", - retryAfterInMs: "42", - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()); + ReferenceCountedDisposable storeResult = StoreResult.CreateForTesting(storeResponse: new StoreResponse()); StoreResponseStatistics storeResponseStatistics = new StoreResponseStatistics( DateTime.MinValue, DateTime.MaxValue, - storeResult, + storeResult.Target, ResourceType.Document, OperationType.Query, "42", @@ -139,11 +120,11 @@ public void ValidateStoreResultSerialization() List jsonPropertyNames = storeResultJObject.Properties().Select(p => p.Name).ToList(); storeResultProperties.Add("BELatencyInMs"); - storeResultProperties.Remove(nameof(storeResult.BackendRequestDurationInMs)); + storeResultProperties.Remove(nameof(storeResult.Target.BackendRequestDurationInMs)); storeResultProperties.Add("TransportException"); - storeResultProperties.Remove(nameof(storeResult.Exception)); + storeResultProperties.Remove(nameof(storeResult.Target.Exception)); storeResultProperties.Add("transportRequestTimeline"); - storeResultProperties.Remove(nameof(storeResult.TransportRequestStats)); + storeResultProperties.Remove(nameof(storeResult.Target.TransportRequestStats)); foreach (string key in jsonPropertyNames) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index eace2eb9df..67bafdbf56 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -363,26 +363,7 @@ public void TraceData() StoreResponseStatistics storeResponseStatistics = new StoreResponseStatistics( DateTime.MinValue, DateTime.MaxValue, - new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: 42.ToString(), - lsn: 1337, - quorumAckedLsn: 23, - requestCharge: 3.14, - currentReplicaSetSize: 4, - currentWriteQuorum: 3, - isValid: true, - storePhysicalAddress: new Uri("http://storephysicaladdress.com"), - globalCommittedLSN: 1234, - numberOfReadRegions: 13, - itemLSN: 15, - sessionToken: new SimpleSessionToken(42), - usingLocalLSN: true, - activityId: Guid.Empty.ToString(), - backendRequestDurationInMs: "4.2", - retryAfterInMs: "42", - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()), + StoreResult.CreateForTesting(transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()).Target, ResourceType.Document, OperationType.Query, "42", @@ -416,26 +397,7 @@ public void TraceData() StoreResponseStatistics storeResponseStatistics = new StoreResponseStatistics( requestStartTime: default, requestResponseTime: default, - new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: default, - partitionKeyRangeId: default, - lsn: default, - quorumAckedLsn: default, - requestCharge: default, - currentReplicaSetSize: default, - currentWriteQuorum: default, - isValid: default, - storePhysicalAddress: default, - globalCommittedLSN: default, - numberOfReadRegions: default, - itemLSN: default, - sessionToken: default, - usingLocalLSN: default, - activityId: default, - retryAfterInMs: default, - backendRequestDurationInMs: default, - transportRequestStats: TraceWriterBaselineTests.CreateTransportRequestStats()), + StoreResult.CreateForTesting(storeResponse: new StoreResponse()).Target, resourceType: default, operationType: default, requestSessionToken: default, From 9dde99e697eacc9c61b6272fb0ea3b761ca041d6 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 13 Jan 2023 01:45:47 +0530 Subject: [PATCH 039/337] [Preview] AI integration: Adds IsDistributedTracingEnabled flag as public API to enable/disable this feature (#3598) * make api public for preview * add null check * fix tests * singleton listener initialization * assign null to listeners * fix test * concurrent bag in listener * renamed to LatencyThresholdForDiagnosticEvent * renamed to IsDistributedTracingEnabled * updated xml * update contract * made latency threshold flag internal * fix test * regeneratebaselines * update documentation * rename builder api * add docs * updated contracts and all * doc update * import cleanup Co-authored-by: Sourabh Jain --- .../src/CosmosClientOptions.cs | 20 ++++- .../src/Fluent/CosmosClientBuilder.cs | 24 ++++- .../DistributedTracingOptions.cs | 9 +- .../Filters/DiagnosticsFilterHelper.cs | 4 +- .../OpenTelemetryRecorderFactory.cs | 11 +-- ...riterBaselineTests.BulkOperationsAsync.xml | 10 +-- ...neTests.PointOperationsExceptionsAsync.xml | 15 ++-- .../Tracing/AssertActivity.cs | 20 +++-- .../Tracing/CustomListener.cs | 10 +-- .../EndToEndTraceWriterBaselineTests.cs | 89 +++++++------------ .../Utils/TestCommon.cs | 11 ++- .../Utils/TransportClientHelper.cs | 19 ++-- .../Utils/Util.cs | 38 ++++++++ .../Contracts/DotNetPreviewSDKAPI.json | 36 ++++++++ .../CosmosClientOptionsUnitTests.cs | 8 +- .../Telemetry/DiagnosticsFilterHelperTest.cs | 8 +- 16 files changed, 213 insertions(+), 119 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 21df876c68..a75b508e3b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -988,17 +988,29 @@ public override bool CanConvert(Type objectType) return objectType == typeof(DateTime); } } - + /// /// Distributed Tracing Options. /// + /// Applicable only when Operation level distributed tracing is enabled through internal DistributedTracingOptions DistributedTracingOptions { get; set; } /// - /// Gets or sets value indicating whether distributed tracing activities () are going to be created for the SDK methods calls and HTTP calls. - /// By default true for Preview package + /// Gets or sets the flag to generate operation level for methods calls using the Source Name "Azure.Cosmos.Operation". /// - internal bool EnableDistributedTracing { get; set; } + /// + /// The default value is true (for preview package). + /// + /// This flag is there to disable it from source. Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters +#if PREVIEW + public +#else + internal +#endif + bool IsDistributedTracingEnabled { get; set; } +#if PREVIEW + = true; +#endif } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index d47f168764..44c38ec51b 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -424,12 +424,30 @@ public CosmosClientBuilder WithConsistencyLevel(Cosmos.ConsistencyLevel consiste } /// - /// If Open Telemetry listener is subscribed for Azure.Cosmos namespace, There are you can leverage to control it.

+ /// Sets whether Distributed Tracing for "Azure.Cosmos.Operation" source is enabled. ///
- /// Tracing Options + /// Whether is enabled. /// The current . - internal CosmosClientBuilder WithDistributingTracing(DistributedTracingOptions options) +#if PREVIEW + public +#else + internal +#endif + CosmosClientBuilder WithDistributedTracing(bool isEnabled = true) + { + this.clientOptions.IsDistributedTracingEnabled = isEnabled; + return this; + } + + /// + /// Enables Distributed Tracing with a Configuration ref. + /// + /// . + /// The current .] + /// Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters + internal CosmosClientBuilder WithDistributedTracingOptions(DistributedTracingOptions options) { + this.clientOptions.IsDistributedTracingEnabled = true; this.clientOptions.DistributedTracingOptions = options; return this; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs index 652b6b9e3f..6c44f06bf2 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs @@ -7,8 +7,7 @@ namespace Microsoft.Azure.Cosmos using System; /// - /// Open Telemetry Configuration - /// It needs to be public once AppInsight is ready + /// Options for configuring the distributed tracing and event tracing /// internal sealed class DistributedTracingOptions { @@ -23,9 +22,9 @@ internal sealed class DistributedTracingOptions internal static readonly TimeSpan DefaultQueryTimeoutThreshold = TimeSpan.FromMilliseconds(500); /// - /// Latency Threshold to generate () with Request diagnostics in distributing Tracing.

- /// If it is not set then by default it will generate () for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. + /// SDK generates (Event Source Name is "Azure-Cosmos-Operation-Request-Diagnostics") with Request Diagnostics String, If Operation level distributed tracing is not disabled i.e. ///
- public TimeSpan? DiagnosticsLatencyThreshold { get; set; } + /// If it is not set then, by default, it will generate for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. + public TimeSpan? LatencyThresholdForDiagnosticEvent { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index e4db97bc3f..7649977fa0 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -22,9 +22,9 @@ public static bool IsTracingNeeded( { TimeSpan latencyThreshold; - if (config?.DiagnosticsLatencyThreshold != null) + if (config?.LatencyThresholdForDiagnosticEvent != null) { - latencyThreshold = config.DiagnosticsLatencyThreshold.Value; + latencyThreshold = config.LatencyThresholdForDiagnosticEvent.Value; } else { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 2cd6e3a481..6c88b3d5db 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -4,6 +4,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { + using System; using global::Azure.Core.Pipeline; /// @@ -15,7 +16,7 @@ internal static class OpenTelemetryRecorderFactory /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once /// private static DiagnosticScopeFactory ScopeFactory { get; set; } - + public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, string containerName, string databaseName, @@ -23,11 +24,11 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, RequestOptions requestOptions, CosmosClientContext clientContext) { - if (clientContext is { ClientOptions.EnableDistributedTracing: true }) + if (clientContext is { ClientOptions.IsDistributedTracingEnabled: true }) { - ScopeFactory = new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, - resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true); + OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, + resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, + isActivityEnabled: true); // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = OpenTelemetryRecorderFactory diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 6fd72499bb..e79fa6d301 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -1590,6 +1590,10 @@ maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -1599,12 +1603,6 @@ exceptionActivityId, errorMessage)))); - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 7d6a68adca..2a3b1439ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -160,7 +160,12 @@ string errorMessage = "Mock throttle exception" + Guid.NewGuid().ToString(); Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => - builder.WithThrottlingRetryOptions( + builder + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) + .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( @@ -171,13 +176,7 @@ request, exceptionActivityId, errorMessage)))); - - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - + ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index b0c605839e..d19b330d98 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -1,4 +1,8 @@ -namespace Microsoft.Azure.Cosmos.Tracing +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tracing { using System.Collections.Generic; using System.Diagnostics; @@ -13,14 +17,16 @@ internal static class AssertActivity public static void IsValid(Activity activity) { Assert.IsTrue(activity.OperationName == activity.DisplayName); - Assert.IsNotNull(activity.GetTagItem("db.cosmosdb.connection_mode")); + + Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is emtpy for {activity.OperationName}"); + if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) { - Assert.AreEqual(ActivityKind.Internal, activity.Kind); + Assert.AreEqual(ActivityKind.Internal, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Internal} for {activity.OperationName}"); } - else + else if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Direct.ToString()) { - Assert.AreEqual(ActivityKind.Client, activity.Kind); + Assert.AreEqual(ActivityKind.Client, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Client} for {activity.OperationName}"); } IList expectedTags = new List @@ -73,8 +79,10 @@ private static void AssertDatabaseAndContainerName(string name, KeyValuePair exceptionsForContainerAttribute = new List { "Operation.CreateDatabaseAsync", + "Operation.CreateDatabaseIfNotExistsAsync", "Operation.ReadAsync", - "Operation.DeleteAsync" + "Operation.DeleteAsync", + "Operation.DeleteStreamAsync" }; if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index c46d8578b0..410843f3d2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -18,7 +18,7 @@ namespace Microsoft.Azure.Cosmos.Tests /// /// It is a custom listener for Activities and Event. It is used to validate the Activities generated by cosmosDb SDK. /// - public class CustomListener : + internal class CustomListener : EventListener, // Override Event Listener to capture Event source events IObserver>, // Override IObserver to capture Activity events IObserver, @@ -27,8 +27,8 @@ public class CustomListener : private readonly Func sourceNameFilter; private readonly string eventName; - private List subscriptions = new(); - private List Scopes { get; } = new(); + private ConcurrentBag subscriptions = new(); + private ConcurrentBag Scopes { get; } = new(); public static ConcurrentBag CollectedActivities { private set; get; } = new(); private static ConcurrentBag CollectedEvents { set; get; } = new(); @@ -75,7 +75,7 @@ public void OnNext(KeyValuePair value) string startSuffix = ".Start"; string stopSuffix = ".Stop"; string exceptionSuffix = ".Exception"; - + if (value.Key.EndsWith(startSuffix)) { string name = value.Key[..^startSuffix.Length]; @@ -181,7 +181,7 @@ public override void Dispose() return; } - List subscriptions; + ConcurrentBag subscriptions; lock (this.Scopes) { subscriptions = this.subscriptions; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index b91fc76b8b..22b4be1814 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -1,4 +1,8 @@ -namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing { using System; using System.Collections.Generic; @@ -19,10 +23,7 @@ using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; - using OpenTelemetry; - using Telemetry; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; - using OpenTelemetry.Trace; [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] @@ -34,55 +35,35 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests builder - .WithBulkExecution(true)); + .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + })); // Set a small retry count to reduce test time miscCosmosClient = TestCommon.CreateCosmosClient(builder => builder - .AddCustomHandlers(requestHandler)); - - client.ClientOptions.EnableDistributedTracing = true; - bulkClient.ClientOptions.EnableDistributedTracing = true; - miscCosmosClient.ClientOptions.EnableDistributedTracing = true; - - client.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - - bulkClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; + .AddCustomHandlers(requestHandler) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + })); - miscCosmosClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( Guid.NewGuid().ToString(), cancellationToken: default); @@ -114,8 +95,7 @@ public static async Task ClassCleanupAsync() await EndToEndTraceWriterBaselineTests.database.DeleteStreamAsync(); } - oTelTracerProvider?.Dispose(); - testListener?.Dispose(); + Util.DisposeOpenTelemetryAndCustomListeners(); await Task.Delay(5000); } @@ -994,7 +974,12 @@ public async Task PointOperationsExceptionsAsync() string errorMessage = "Mock throttle exception" + Guid.NewGuid().ToString(); Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => - builder.WithThrottlingRetryOptions( + builder + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) + .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( @@ -1005,13 +990,7 @@ public async Task PointOperationsExceptionsAsync() request, exceptionActivityId, errorMessage)))); - - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - + ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, @@ -1284,6 +1263,10 @@ public async Task BulkOperationsAsync() maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -1293,12 +1276,6 @@ public async Task BulkOperationsAsync() exceptionActivityId, errorMessage)))); - throttleClient.ClientOptions.EnableDistributedTracing = true; - throttleClient.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(0) - }; - ItemRequestOptions requestOptions = new ItemRequestOptions(); Container containerWithThrottleException = throttleClient.GetContainer( database.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index 265e9542ef..8cfa5be33b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -130,7 +130,8 @@ internal static CosmosClient CreateCosmosClient( internal static CosmosClient CreateCosmosClient( bool useGateway, - Action customizeClientBuilder = null) + Action customizeClientBuilder = null, + bool enableDistributingTracing = false) { CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(); @@ -140,6 +141,14 @@ internal static CosmosClient CreateCosmosClient( { cosmosClientBuilder.WithConnectionModeGateway(); } + + if(enableDistributingTracing) + { + cosmosClientBuilder.WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }); + } return cosmosClientBuilder.Build(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs index d701c069c0..f34135b695 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs @@ -81,21 +81,20 @@ internal static Container GetContainerWithIntercepter( builder.WithSessionContainer(sessionContainer); } + if (enableDistributingTracing) + { + builder.WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(.0001) + }); + } + builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, interceptor, interceptorWithStoreResult)); }); - - if(enableDistributingTracing) - { - clientWithIntercepter.ClientOptions.EnableDistributedTracing = true; - clientWithIntercepter.ClientOptions.DistributedTracingOptions = new DistributedTracingOptions() - { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(.0001) - }; - } - + return clientWithIntercepter.GetContainer(databaseId, containerId); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 4533b2b562..bdb688673d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -14,10 +14,14 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Services.Management.Tests; using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Tests; + using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Documents.Collections; using Microsoft.VisualStudio.TestTools.UnitTesting; + using OpenTelemetry; + using OpenTelemetry.Trace; internal enum DocumentClientType { @@ -533,6 +537,40 @@ internal static void DisableClientTelemetryEnvironmentVariables() Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); } + private static TracerProvider OTelTracerProvider; + private static CustomListener TestListener; + + internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() + { + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); + + // Open Telemetry Listener + Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() + .AddCustomOtelExporter() // use any exporter here + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") // Right now, it will capture only "Azure.Cosmos.Operation" + .Build(); + + // Custom Listener + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); + + return Util.TestListener; + + } + + internal static void DisposeOpenTelemetryAndCustomListeners() + { + // Open Telemetry Listener + Util.OTelTracerProvider?.Dispose(); + + // Custom Listener + Util.TestListener?.Dispose(); + + Util.OTelTracerProvider = null; + Util.TestListener = null; + + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", false); + } + /// /// Enables traces for local debugging /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index add1fce30e..c5bb91849b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -314,6 +314,31 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosClientOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Boolean get_IsDistributedTracingEnabled()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean IsDistributedTracingEnabled": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean IsDistributedTracingEnabled;CanRead:True;CanWrite:True;Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_IsDistributedTracingEnabled(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Fluent.ChangeFeedPolicyDefinition;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -336,6 +361,17 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index e39bb8d0f3..986b9cc997 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -159,9 +159,9 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() portReuseMode, enableTcpConnectionEndpointRediscovery) .WithApplicationPreferredRegions(preferredLocations) - .WithDistributingTracing(new DistributedTracingOptions + .WithDistributedTracingOptions(new DistributedTracingOptions { - DiagnosticsLatencyThreshold = TimeSpan.FromMilliseconds(100) + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(100) }); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); @@ -174,8 +174,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, clientOptions.PortReuseMode); Assert.IsTrue(clientOptions.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), clientOptions.ApplicationPreferredRegions.ToArray()); - Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.DistributedTracingOptions.DiagnosticsLatencyThreshold); - Assert.IsFalse(clientOptions.EnableDistributedTracing); + Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.DistributedTracingOptions.LatencyThresholdForDiagnosticEvent); + Assert.IsTrue(clientOptions.IsDistributedTracingEnabled); //Verify GetConnectionPolicy returns the correct values policy = clientOptions.GetConnectionPolicy(clientId: 0); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 98f4d62954..698b99524e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -38,7 +38,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) + LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -51,7 +51,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DiagnosticsFilterHelper .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}" ); } @@ -63,7 +63,7 @@ public void CheckReturnTrueOnFailedStatusCode() DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions { - DiagnosticsLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) + LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -76,7 +76,7 @@ public void CheckReturnTrueOnFailedStatusCode() DiagnosticsFilterHelper .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.DiagnosticsLatencyThreshold.Value.Milliseconds}ms " + + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); } From 36d0e0f4f8e9919f2512d7520f6f159a9cec0825 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Fri, 13 Jan 2023 07:41:33 -0800 Subject: [PATCH 040/337] Change Feed Processor: Fixes behavior with StartTime on Local (#3645) * To UTC * Test --- .../ChangeFeedProcessorOptions.cs | 2 +- .../ChangeFeedProcessorBuilderTests.cs | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs index 81e38dde16..3c9223a02e 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs @@ -66,7 +66,7 @@ public DateTime? StartTime throw new ArgumentException("StartTime cannot have DateTimeKind.Unspecified", nameof(value)); } - this.startTime = value; + this.startTime = value.HasValue && value.Value.Kind == DateTimeKind.Local ? value.Value.ToUniversalTime() : value; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorBuilderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorBuilderTests.cs index 939bfdec8c..ae44b20d71 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorBuilderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorBuilderTests.cs @@ -220,6 +220,41 @@ public void CanBuildWithInMemoryContainer() Assert.IsInstanceOfType(builder.Build(), typeof(ChangeFeedProcessor)); } + [TestMethod] + public void ConvertsToUTC() + { + DateTime localTime = DateTime.Now; + + Assert.AreEqual(DateTimeKind.Local, localTime.Kind); + + Action verifier = (DocumentServiceLeaseStoreManager leaseStoreManager, + Container leaseContainer, + string instanceName, + ChangeFeedLeaseOptions changeFeedLeaseOptions, + ChangeFeedProcessorOptions changeFeedProcessorOptions, + Container monitoredContainer) => + { + Assert.AreEqual(DateTimeKind.Utc, changeFeedProcessorOptions.StartTime.Value.Kind); + Assert.AreEqual(localTime.ToUniversalTime(), changeFeedProcessorOptions.StartTime.Value); + }; + + ChangeFeedProcessorBuilder builder = new ChangeFeedProcessorBuilder("workflowName", + ChangeFeedProcessorBuilderTests.GetMockedContainer(), + ChangeFeedProcessorBuilderTests.GetMockedProcessor(), + verifier); + + builder.WithLeaseContainer(ChangeFeedProcessorBuilderTests.GetMockedContainer()); + + builder.WithStartTime(localTime); + + Assert.IsInstanceOfType(builder.Build(), typeof(ChangeFeedProcessor)); + } + private static ContainerInternal GetMockedContainer(string containerName = null) { Mock mockedContainer = MockCosmosUtil.CreateMockContainer(containerName: containerName); From bdd059d1bf60af19442cbc4b879f093581d871a3 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 17 Jan 2023 20:42:26 +0530 Subject: [PATCH 041/337] [Internal] Client Telemetry: Refactors code to use base useragent string (#3653) --- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 2 +- .../ClientTelemetryTests.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 8aafec61fc..61e7c99665 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -1036,7 +1036,7 @@ private void InitializeClientTelemetry() this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( clientId: this.clientId, httpClient: this.httpClient, - userAgent: this.ConnectionPolicy.UserAgentContainer.UserAgent, + userAgent: this.ConnectionPolicy.UserAgentContainer.BaseUserAgent, connectionMode: this.ConnectionPolicy.ConnectionMode, authorizationTokenProvider: this.cosmosAuthorization, diagnosticsHelper: DiagnosticsHandlerHelper.Instance, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 961c5d25d1..737be92e05 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -974,6 +974,7 @@ private static void AssertAccountLevelInformation( Assert.IsNotNull(telemetryInfo.ProcessId); Assert.AreEqual(HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), telemetryInfo.ProcessId); Assert.IsNotNull(telemetryInfo.UserAgent); + Assert.IsFalse(telemetryInfo.UserAgent.Contains("userAgentSuffix"), "Useragent should not have suffix appended"); // Useragent should not contain useragentsuffix as it can have PII Assert.IsNotNull(telemetryInfo.ConnectionMode); if(!string.IsNullOrEmpty(telemetryInfo.MachineId)) @@ -1090,7 +1091,8 @@ private async Task CreateClientAndContainer(ConnectionMode mode, } this.cosmosClientBuilder = this.cosmosClientBuilder - .WithHttpClientFactory(() => new HttpClient(handlerHelper)); + .WithHttpClientFactory(() => new HttpClient(handlerHelper)) + .WithApplicationName("userAgentSuffix"); this.cosmosClient = mode == ConnectionMode.Gateway ? this.cosmosClientBuilder.WithConnectionModeGateway().Build() From b3cf7dfb0a156d3e4fdfbb6a8832339d07241b8f Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 18 Jan 2023 00:24:51 +0530 Subject: [PATCH 042/337] [Internal] AI Integration: Refactors code to rename event name (#3648) * first draft * rename event name * updated xmls * update files --- .../OpenTelemetry/CosmosDbEventSource.cs | 14 +- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 208 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 20 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Tracing/CustomListener.cs | 5 +- .../EndToEndTraceWriterBaselineTests.cs | 100 ++++----- 13 files changed, 257 insertions(+), 262 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index af1115367f..091373b0de 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -40,7 +40,7 @@ public static void RecordDiagnosticsForRequests( operationType: operationType, response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) { - CosmosDbEventSource.Singleton.WriteWarningEvent(response.Diagnostics.ToString()); + CosmosDbEventSource.Singleton.LatencyOverThreshold(response.Diagnostics.ToString()); } } @@ -49,26 +49,20 @@ public static void RecordDiagnosticsForExceptions(CosmosDiagnostics diagnostics) { if (CosmosDbEventSource.IsEnabled(EventLevel.Error)) { - CosmosDbEventSource.Singleton.WriteErrorEvent(diagnostics.ToString()); + CosmosDbEventSource.Singleton.Exception(diagnostics.ToString()); } } [Event(1, Level = EventLevel.Error)] - private void WriteErrorEvent(string message) + private void Exception(string message) { this.WriteEvent(1, message); } [Event(2, Level = EventLevel.Warning)] - private void WriteWarningEvent(string message) + private void LatencyOverThreshold(string message) { this.WriteEvent(2, message); } - - [Event(3, Level = EventLevel.Informational)] - private void WriteInfoEvent(string message) - { - this.WriteEvent(3, message); - } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index a6683679f7..0bee1cd007 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -130,7 +130,7 @@ ] }]]> Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index e79fa6d301..b99e457c3b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -144,16 +144,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -302,16 +302,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -460,16 +460,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -618,16 +618,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -776,16 +776,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -934,16 +934,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1092,16 +1092,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1250,16 +1250,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1408,16 +1408,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1566,16 +1566,16 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1591,9 +1591,9 @@ maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }) + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -2287,7 +2287,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index c04d573153..1415343fc9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -957,11 +957,11 @@ Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1574,11 +1574,11 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2172,11 +2172,11 @@ Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2790,11 +2790,11 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3068,8 +3068,8 @@ }]]> Operation.Change Feed Estimator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index cd053b58e2..a6a935fe01 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -109,8 +109,8 @@ }]]> Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -209,8 +209,8 @@ }]]> Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 2a3b1439ae..c409236892 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -149,7 +149,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -161,10 +161,10 @@ Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => builder - .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) @@ -391,7 +391,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -616,7 +616,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -873,7 +873,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1194,7 +1194,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1348,7 +1348,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 21db429e27..ba77a115a1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -578,10 +578,10 @@ Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1184,10 +1184,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1771,10 +1771,10 @@ Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2378,10 +2378,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3052,10 +3052,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3648,10 +3648,10 @@ Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4264,10 +4264,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 070da7032d..be14de122e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -540,10 +540,10 @@ Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1108,10 +1108,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1657,10 +1657,10 @@ Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2226,10 +2226,10 @@ Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index dd99e1694b..5b8f8e29a0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -548,12 +548,12 @@ Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1113,7 +1113,7 @@ ] }]]> Operation.ReadManyItemsAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 6172446645..8f2ad00f94 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -90,7 +90,7 @@ ] }]]> Operation.CreateItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -179,7 +179,7 @@ ] }]]> Operation.ReadItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -276,7 +276,7 @@ ] }]]> Operation.ReplaceItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -368,7 +368,7 @@ ] }]]> Operation.DeleteItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 2aeaf80b15..603fec2b24 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -110,7 +110,7 @@ ] }]]> Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -204,7 +204,7 @@ ] }]]> Operation.ReadItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -311,7 +311,7 @@ ] }]]> Operation.ReplaceItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -407,7 +407,7 @@ ] }]]> Operation.DeleteItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Ideally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. +LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 410843f3d2..1f192bb086 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -160,10 +160,11 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder builder = new StringBuilder(); builder.Append("") - .Append("Ideally, this should contain request diagnostics but request diagnostics is " + + .Append("").Append(eventData.EventName).Append("") + .Append("Ideally, this should contain request diagnostics but request diagnostics is " + "subject to change with each request as it contains few unique id. " + "So just putting this tag with this static text to make sure event is getting generated" + - " for each test.") + " for each test.") .Append(""); CustomListener.CollectedEvents.Add(builder.ToString()); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 22b4be1814..bb46c0f3f3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -35,9 +35,9 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests builder .WithBulkExecution(true) .WithDistributedTracingOptions(new DistributedTracingOptions() - { + { LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - })); + })); + // Set a small retry count to reduce test time miscCosmosClient = TestCommon.CreateCosmosClient(builder => builder @@ -63,7 +64,7 @@ public static async Task ClassInitAsync(TestContext context) { LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) })); - + EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( Guid.NewGuid().ToString(), cancellationToken: default); @@ -105,10 +106,9 @@ private static void AssertAndResetActivityInformation() AssertActivity.AreEqualAcrossListeners(); CustomOtelExporter.CollectedActivities = new(); - testListener.ResetAttributes(); + testListener?.ResetAttributes(); } - [TestMethod] public async Task ReadFeedAsync() { @@ -143,7 +143,7 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener.GetRecordedAttributes())); + oTelActivities: testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); @@ -174,7 +174,7 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener.GetRecordedAttributes())); + oTelActivities: testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -205,7 +205,7 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener.GetRecordedAttributes())); + oTelActivities: testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -231,7 +231,7 @@ public async Task ReadFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ReadFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("ReadFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -273,7 +273,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -305,7 +305,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -338,7 +338,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Public API", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Public API", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -371,7 +371,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -432,7 +432,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Change Feed Estimator", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Change Feed Estimator", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -468,7 +468,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -493,7 +493,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -519,7 +519,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -545,7 +545,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API Typed", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -574,7 +574,7 @@ public async Task QueryAsync() Documents.ServiceInteropWrapper.AssembliesExist = currentLazy; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query - Without ServiceInterop", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query - Without ServiceInterop", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -602,7 +602,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -630,7 +630,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API Typed with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API Typed with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -701,7 +701,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -719,7 +719,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -745,7 +745,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -787,7 +787,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -822,7 +822,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -840,7 +840,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -866,7 +866,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -911,7 +911,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -960,7 +960,7 @@ public async Task PointOperationsExceptionsAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation with Request Timeout", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation with Request Timeout", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -975,10 +975,10 @@ public async Task PointOperationsExceptionsAsync() Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => builder - .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }) + .WithDistributedTracingOptions(new DistributedTracingOptions() + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) @@ -1012,7 +1012,7 @@ public async Task PointOperationsExceptionsAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation With Throttle", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation With Throttle", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1143,7 +1143,7 @@ void interceptor(Uri uri, Documents.ResourceOperation operation, Documents.Docum } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation with Service Unavailable", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation with Service Unavailable", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1194,7 +1194,7 @@ public async Task BatchOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)response.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Batch Operation", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Batch Operation", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1244,7 +1244,7 @@ public async Task BulkOperationsAsync() foreach (ITrace trace in traces) { - inputs.Add(new Input("Bulk Operation", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Bulk Operation", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); } EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); @@ -1264,9 +1264,9 @@ public async Task BulkOperationsAsync() maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }) + { + LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, (uri, resourceOperation, request) => TransportClientHelper.ReturnThrottledStoreResponseOnItemOperation( @@ -1298,7 +1298,7 @@ public async Task BulkOperationsAsync() endLineNumber = GetLineNumber(); - inputs.Add(new Input("Bulk Operation With Throttle", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Bulk Operation With Throttle", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1330,7 +1330,7 @@ public async Task MiscellanousAsync() await databaseResponse.Database.DeleteAsync(); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1349,7 +1349,7 @@ public async Task MiscellanousAsync() await databaseResponse.Database.DeleteAsync(); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1390,7 +1390,7 @@ public async Task ReadManyAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Read Many Stream Api", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Read Many Stream Api", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1405,7 +1405,7 @@ public async Task ReadManyAsync() ITrace trace = ((CosmosTraceDiagnostics)feedResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Read Many Typed Api", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input("Read Many Typed Api", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } From 4b77519162968e8b7fe29c04ccdfa3dcb403888c Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Tue, 17 Jan 2023 14:17:22 -0800 Subject: [PATCH 043/337] Region Availability: Adds Poland Central Region For Public Usage (#3656) --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/Regions.cs | 5 +++++ .../Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 658186357b..b163dedaac 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,7 +4,7 @@ 3.31.2 3.31.2 preview - 3.30.0 + 3.30.1 2.0.0 2.0.0 preview diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index f08bbf4c91..853bc48267 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -344,5 +344,10 @@ public static class Regions /// Name of the Azure China East 3 region in the Azure Cosmos DB service. ///
public const string ChinaEast3 = "China East 3"; + + /// + /// Name of the Azure Poland Central region in the Azure Cosmos DB service. + /// + public const string PolandCentral = "Poland Central"; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 4e18b8084b..70e4a5d780 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6570,6 +6570,11 @@ "Attributes": [], "MethodInfo": "System.String NorwayWest;IsInitOnly:False;IsStatic:True;" }, + "System.String PolandCentral": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String PolandCentral;IsInitOnly:False;IsStatic:True;" + }, "System.String QatarCentral": { "Type": "Field", "Attributes": [], From 171011567abbffac60cf1e61f9fa4bb7ad081ad6 Mon Sep 17 00:00:00 2001 From: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> Date: Thu, 19 Jan 2023 20:02:16 +0530 Subject: [PATCH 044/337] Client Encryption: Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier. (#3642) * Check if the key vault uri provided is a valid Kid * test fix. * update changelog and build props * Update Directory.Build.props * Update Microsoft.Azure.Cosmos.Encryption.csproj * Fixed preview version * Refactor * Update EncryptionDatabaseExtensions.cs --- Directory.Build.props | 5 +- .../changelog.md | 10 +++ .../src/EncryptionDatabaseExtensions.cs | 22 +++++++ .../Microsoft.Azure.Cosmos.Encryption.csproj | 4 +- .../tests/EmulatorTests/MdeEncryptionTests.cs | 63 +++++++++++++++++++ 5 files changed, 99 insertions(+), 5 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b163dedaac..2891c05569 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,12 +1,11 @@ - 3.31.2 3.31.2 preview 3.30.1 - 2.0.0 - 2.0.0 + 2.0.1 + 2.0.1 preview 1.0.0-preview04 1.1.0-preview3 diff --git a/Microsoft.Azure.Cosmos.Encryption/changelog.md b/Microsoft.Azure.Cosmos.Encryption/changelog.md index e3274bce7e..a5e7101074 100644 --- a/Microsoft.Azure.Cosmos.Encryption/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption/changelog.md @@ -3,6 +3,16 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [2.0.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.1) - 2023-03-11 + +#### Added +- [#3642](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3642) Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier. + +### [2.0.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.1-preview) - 2023-01-11 + +#### Added +- [#3642](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3642) Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier. + ### [2.0.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.0) - 2022-06-28 #### Added diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs index 47a68b38ae..f867921946 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs +++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabaseExtensions.cs @@ -91,6 +91,17 @@ public static async Task CreateClientEncryptionKeyA + " Please refer to https://aka.ms/CosmosClientEncryption for more details."); } + if (string.Equals(encryptionCosmosClient.KeyEncryptionKeyResolverName, KeyEncryptionKeyResolverName.AzureKeyVault)) + { + // https://KEYVAULTNAME.vault.azure.net/keys/KEYNAME/KEYVERSION + string[] keyVaultUriSegments = new Uri(encryptionKeyWrapMetadata.Value).Segments; + + if (keyVaultUriSegments.Length != 4 || !string.Equals(keyVaultUriSegments[1], "keys/", StringComparison.InvariantCultureIgnoreCase)) + { + throw new ArgumentException($"Invalid Key Vault URI'{encryptionKeyWrapMetadata.Value}' passed. Pass the complete Azure keyvault key identifier. Please refer to https://aka.ms/CosmosClientEncryption for more details."); + } + } + KeyEncryptionKey keyEncryptionKey = KeyEncryptionKey.GetOrCreate( encryptionKeyWrapMetadata.Name, encryptionKeyWrapMetadata.Value, @@ -192,6 +203,17 @@ public static async Task RewrapClientEncryptionKeyA + " Please refer to https://aka.ms/CosmosClientEncryption for more details."); } + if (string.Equals(encryptionCosmosClient.KeyEncryptionKeyResolverName, KeyEncryptionKeyResolverName.AzureKeyVault)) + { + // https://KEYVAULTNAME.vault.azure.net/keys/KEYNAME/KEYVERSION + string[] keyVaultUriSegments = new Uri(newEncryptionKeyWrapMetadata.Value).Segments; + + if (keyVaultUriSegments.Length != 4 || !string.Equals(keyVaultUriSegments[1], "keys/", StringComparison.InvariantCultureIgnoreCase)) + { + throw new ArgumentException($"Invalid Key Vault URI'{newEncryptionKeyWrapMetadata.Value}' passed. Pass the complete Azure keyvault key identifier. Please refer to https://aka.ms/CosmosClientEncryption for more details."); + } + } + ClientEncryptionKeyProperties clientEncryptionKeyProperties = await clientEncryptionKey.ReadAsync(cancellationToken: cancellationToken); RequestOptions requestOptions = new RequestOptions diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj index 6aa1f85932..9fe41b765f 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj @@ -28,11 +28,11 @@ - + - + diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs index 6ab6d8c333..65efd425aa 100644 --- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs @@ -296,6 +296,69 @@ await MdeEncryptionTests.CreateClientEncryptionKeyAsync( if (ex is CosmosException cosmosException) Assert.AreEqual(HttpStatusCode.Conflict, cosmosException.StatusCode); } + + cekId = "testAkvKid"; + CosmosClient client = TestCommon.CreateCosmosClient(); + TestKeyEncryptionKeyResolver testKeyEncryptionKeyResolver = new TestKeyEncryptionKeyResolver(); + + EncryptionKeyWrapMetadata metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey/12345678"); + + CosmosClient encryptionCosmosClient = client.WithEncryption( + testKeyEncryptionKeyResolver, + KeyEncryptionKeyResolverName.AzureKeyVault, + TimeSpan.Zero); + + Database database = await encryptionCosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); + + ClientEncryptionKeyResponse clientEncrytionKeyResponse = await database.CreateClientEncryptionKeyAsync( + cekId, + DataEncryptionAlgorithm.AeadAes256CbcHmacSha256, + metadata); + + Assert.AreEqual(HttpStatusCode.Created, clientEncrytionKeyResponse.StatusCode); + + metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey/9101112"); + + clientEncrytionKeyResponse = await database.RewrapClientEncryptionKeyAsync( + cekId, + metadata); + + Assert.AreEqual(HttpStatusCode.OK, clientEncrytionKeyResponse.StatusCode); + + // complete key identifier not passed + metadata = MdeEncryptionTests.CreateEncryptionKeyWrapMetadata(KeyEncryptionKeyResolverName.AzureKeyVault, "key1", "https://testkeyvault.vault.azure.net/keys/testkey"); + + try + { + clientEncrytionKeyResponse = await database.CreateClientEncryptionKeyAsync( + cekId, + DataEncryptionAlgorithm.AeadAes256CbcHmacSha256, + metadata); + + Assert.Fail("Key creation should have failed."); + + } + catch(Exception ex) + { + Assert.AreEqual(true, ex.Message.Contains("Invalid Key Vault URI")); + } + + // rewrap old key with new key vault uri without complete key identifier + try + { + clientEncrytionKeyResponse = await database.RewrapClientEncryptionKeyAsync( + cekId, + metadata); + + Assert.Fail("Key rewrap should have failed."); + + } + catch (Exception ex) + { + Assert.AreEqual(true, ex.Message.Contains("Invalid Key Vault URI")); + } + + encryptionCosmosClient.Dispose(); } [TestMethod] From e383d83946bf7c9eddeb161cd577b18609e2ac19 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 19 Jan 2023 17:32:54 -0800 Subject: [PATCH 045/337] [Internal] Query: Adds Split Support for Ode (#3572) * Added tests to test different aspects of merge/split support with OptimisticDirectExecution pipeline. Tests check for gone exception handling, pipeline switching etc. * Added gone exception simulation tests. * Added new tests and improved test infra * Removed ParalleContEvocation test. Fixed comments * Removed CreateParallelCrossPartitionPipelineStateAsync() as it is not being used anymore * Removed while loop in CreateDocumentContainerAsync() * Fixed comments. * Updated ExecuteGoneExceptionOnODEPipeline() * Added type Assert for ExecuteGoneExceptionOnODEPipeline() * Replaced try-catch with if statement in MoveNextAsync() * Added delegate to access TryCreateCoreContextAsync() * Added check to confirm Ode pipeline is not called in fallback plan * Updated method name from OptimisticDirectExecutionContext() to TryCreateOptimisticDirectExecutionContext() * Using delegate instead of Func<>. * Ode fallback plan always calls Specialized pipeline * Using ServiceInterop/Gateway to get QueryPlan for Specialized Pipeline * Added new test to check handling of failing fallback pipeline * Code cleanup * Added logic for handling non ODE continuation tokens * Moved delegate away from member variables * Added tests for Merge case * Updated method names * Added checks for tryCatch * Updated SetCancellationToken() to use Try * Updated TryUnwrapContinuationToken() * Removed changes in FlakyDocumentContainer.cs * Removed unused imports * Updated comments * Fixed comments and cleaned up test code * Added CosmosElement null check in TryUnwrapContinuationToken() * Removed FlakyDocumentContainer.cs from pull request * Removed unused imports * Updated TryUnwrapContinuationToken() * Update MoveNextAsync() call in OptimisticDirectExecutionQueryBaselineTests.cs * Made MergeTestUtil.IsFailedFallbackPipelineTest a readonly property * Added IsPartitionSplitException() overload to take CosmosElement * Fixed bug regarding syntax error queries --- .../Query/Core/Monads/TryCatch{TResult}.cs | 32 + .../Pipeline/CosmosExceptionExtensions.cs | 28 + .../CosmosQueryExecutionContextFactory.cs | 339 ++++++++--- ...OrderByCrossPartitionQueryPipelineStage.cs | 4 +- ...imisticDirectExecutionContinuationToken.cs | 6 +- ...misticDirectExecutionQueryPipelineStage.cs | 316 ++++++---- ...egativeOptimisticDirectExecutionOutput.xml | 26 + ...ositiveOptimisticDirectExecutionOutput.xml | 26 + ...misticDirectExecutionQueryBaselineTests.cs | 553 +++++++++++------- 9 files changed, 929 insertions(+), 401 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosExceptionExtensions.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Monads/TryCatch{TResult}.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Monads/TryCatch{TResult}.cs index 8d9c43b036..38d0f4d1fc 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Monads/TryCatch{TResult}.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Monads/TryCatch{TResult}.cs @@ -126,6 +126,38 @@ public async Task> TryAsync( return matchResult; } + public async ValueTask> TryAsync( + Func> onSuccess) + { + TryCatch matchResult; + if (this.Succeeded) + { + matchResult = TryCatch.FromResult(await onSuccess(this.either.FromRight(default))); + } + else + { + matchResult = TryCatch.FromException(this.either.FromLeft(default)); + } + + return matchResult; + } + + public TryCatch Try( + Func> onSuccess) + { + TryCatch matchResult; + if (this.Succeeded) + { + matchResult = onSuccess(this.either.FromRight(default)); + } + else + { + matchResult = TryCatch.FromException(this.either.FromLeft(default)); + } + + return matchResult; + } + public TryCatch Catch( Action onError) { diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosExceptionExtensions.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosExceptionExtensions.cs new file mode 100644 index 0000000000..dca1ef488d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosExceptionExtensions.cs @@ -0,0 +1,28 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline +{ + using System; + + internal static class CosmosExceptionExtensions + { + public static bool IsPartitionSplitException(this Exception ex) + { + if (ex != null) + { + return IsPartitionSplitException(ex as CosmosException); + } + + return false; + } + + public static bool IsPartitionSplitException(this CosmosException ex) + { + return ex is CosmosException cosmosException + && (cosmosException.StatusCode == System.Net.HttpStatusCode.Gone) + && (cosmosException.SubStatusCode == (int)Documents.SubStatusCodes.PartitionKeyRangeGone); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 36e14d78bd..371391386e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -136,23 +136,24 @@ private static async Task> TryCreateCoreContextAsy cancellationToken); cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; - Documents.PartitionKeyRange targetRange = await GetTargetRangeOptimisticDirectExecutionAsync( - inputParameters, - queryPlanFromContinuationToken, - cosmosQueryContext, - containerQueryProperties, + Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( + inputParameters, + queryPlanFromContinuationToken, + cosmosQueryContext, + containerQueryProperties, trace); - + if (targetRange != null) { - // Test code added to confirm the correct pipeline is being utilized - SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); - - return OptimisticDirectExecutionContext( - documentContainer, - inputParameters, - targetRange, - cancellationToken); + return await TryCreateExecutionContextAsync( + documentContainer, + partitionedQueryExecutionInfo: null, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + targetRange, + trace, + cancellationToken); } PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; @@ -226,33 +227,12 @@ private static async Task> TryCreateCoreContextAsy } } - if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) - { - // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. - // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this - partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( - cosmosQueryContext, - inputParameters.SqlQuerySpec, - cosmosQueryContext.ResourceLink, - inputParameters.PartitionKey, - createQueryPipelineTrace, - cancellationToken); - } - else - { - Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - - partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( - cosmosQueryContext.QueryClient, - inputParameters.SqlQuerySpec, - cosmosQueryContext.ResourceTypeEnum, - partitionKeyDefinition, - inputParameters.PartitionKey != null, - containerQueryProperties.GeospatialType, - cosmosQueryContext.UseSystemPrefix, - createQueryPipelineTrace, - cancellationToken); - } + partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + createQueryPipelineTrace, + cancellationToken); } return await TryCreateFromPartitionedQueryExecutionInfoAsync( @@ -306,79 +286,187 @@ private static async Task> TryCreateFromPartitione TryCatch tryCreatePipelineStage; - Documents.PartitionKeyRange targetRange = await GetTargetRangeOptimisticDirectExecutionAsync( + Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( inputParameters, partitionedQueryExecutionInfo, cosmosQueryContext, - containerQueryProperties, + containerQueryProperties, trace); if (targetRange != null) { - SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); - - tryCreatePipelineStage = CosmosQueryExecutionContextFactory.OptimisticDirectExecutionContext( + tryCreatePipelineStage = await TryCreateExecutionContextAsync( documentContainer, + partitionedQueryExecutionInfo, + cosmosQueryContext, + containerQueryProperties, inputParameters, targetRange, + trace, cancellationToken); - - return tryCreatePipelineStage; } - - if (createPassthroughQuery) + else { - SetTestInjectionPipelineType(inputParameters, Passthrough); + if (createPassthroughQuery) + { + SetTestInjectionPipelineType(inputParameters, Passthrough); - tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContext( - documentContainer, - inputParameters, - targetRanges, - cancellationToken); + tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContext( + documentContainer, + inputParameters, + targetRanges, + cancellationToken); + } + else + { + tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext(documentContainer, cosmosQueryContext, inputParameters, targetRanges, partitionedQueryExecutionInfo, cancellationToken); + } } - else + + return tryCreatePipelineStage; + } + + private static async Task> TryCreateExecutionContextAsync( + DocumentContainer documentContainer, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + InputParameters inputParameters, + Documents.PartitionKeyRange targetRange, + ITrace trace, + CancellationToken cancellationToken) + { + // Test code added to confirm the correct pipeline is being utilized + SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); + + TryCatch tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreateOptimisticDirectExecutionContext( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + targetRange, + cancellationToken); + + // A malformed continuation token exception would happen for 2 reasons here + // 1. the token is actually malformed + // 2. Its a non Ode continuation token + // In both cases, Ode pipeline delegates the work to the Specialized pipeline + // as Ode pipeline should not take over execution while some other pipeline is already handling it + if (tryCreatePipelineStage.Failed && tryCreatePipelineStage.InnerMostException is MalformedContinuationTokenException) { SetTestInjectionPipelineType(inputParameters, Specialized); - if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery)) + if (partitionedQueryExecutionInfo != null) { - // We need pass down the rewritten query. - SqlQuerySpec rewrittenQuerySpec = new SqlQuerySpec() + List targetRanges = new List { - QueryText = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, - Parameters = inputParameters.SqlQuerySpec.Parameters + targetRange }; - inputParameters = new InputParameters( - rewrittenQuerySpec, - inputParameters.InitialUserContinuationToken, - inputParameters.InitialFeedRange, - inputParameters.MaxConcurrency, - inputParameters.MaxItemCount, - inputParameters.MaxBufferedItemCount, - inputParameters.PartitionKey, - inputParameters.Properties, - inputParameters.PartitionedQueryExecutionInfo, - inputParameters.ExecutionEnvironment, - inputParameters.ReturnResultsInDeterministicOrder, - inputParameters.ForcePassthrough, - inputParameters.TestInjections); + tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext( + documentContainer, + cosmosQueryContext, + inputParameters, + targetRanges, + partitionedQueryExecutionInfo, + cancellationToken); + } + else + { + tryCreatePipelineStage = await TryCreateSpecializedDocumentQueryExecutionContextAsync( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + trace, + cancellationToken); } - - tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContext( - documentContainer, - cosmosQueryContext, - inputParameters, - partitionedQueryExecutionInfo, - targetRanges, - cancellationToken); } return tryCreatePipelineStage; } - - private static TryCatch OptimisticDirectExecutionContext( + + private static TryCatch TryCreateSpecializedDocumentQueryExecutionContext( DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + List targetRanges, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + CancellationToken cancellationToken) + { + SetTestInjectionPipelineType(inputParameters, Specialized); + + if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery)) + { + // We need pass down the rewritten query. + SqlQuerySpec rewrittenQuerySpec = new SqlQuerySpec() + { + QueryText = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, + Parameters = inputParameters.SqlQuerySpec.Parameters + }; + + inputParameters = new InputParameters( + rewrittenQuerySpec, + inputParameters.InitialUserContinuationToken, + inputParameters.InitialFeedRange, + inputParameters.MaxConcurrency, + inputParameters.MaxItemCount, + inputParameters.MaxBufferedItemCount, + inputParameters.PartitionKey, + inputParameters.Properties, + inputParameters.PartitionedQueryExecutionInfo, + inputParameters.ExecutionEnvironment, + inputParameters.ReturnResultsInDeterministicOrder, + inputParameters.ForcePassthrough, + inputParameters.TestInjections); + } + + return CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContext( + documentContainer, + cosmosQueryContext, + inputParameters, + partitionedQueryExecutionInfo, + targetRanges, + cancellationToken); + } + + private static async Task> TryCreateSpecializedDocumentQueryExecutionContextAsync( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + InputParameters inputParameters, + ITrace trace, + CancellationToken cancellationToken) + { + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + trace, + cancellationToken); + + List targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( + cosmosQueryContext.QueryClient, + cosmosQueryContext.ResourceLink, + partitionedQueryExecutionInfo, + containerQueryProperties, + inputParameters.Properties, + inputParameters.InitialFeedRange, + trace); + + return TryCreateSpecializedDocumentQueryExecutionContext( + documentContainer, + cosmosQueryContext, + inputParameters, + targetRanges, + partitionedQueryExecutionInfo, + cancellationToken); + } + + private static TryCatch TryCreateOptimisticDirectExecutionContext( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, InputParameters inputParameters, Documents.PartitionKeyRange targetRange, CancellationToken cancellationToken) @@ -386,14 +474,26 @@ private static TryCatch OptimisticDirectExecutionContext( // Return a OptimisticDirectExecution context return OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( documentContainer: documentContainer, - sqlQuerySpec: inputParameters.SqlQuerySpec, + inputParameters: inputParameters, targetRange: new FeedRangeEpk(targetRange.ToRange()), queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: inputParameters.MaxItemCount), - partitionKey: inputParameters.PartitionKey, - continuationToken: inputParameters.InitialUserContinuationToken, + fallbackQueryPipelineStageFactory: (continuationToken) => + { + // In fallback scenario, the Specialized pipeline is always invoked + Task> tryCreateContext = + CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContextAsync( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters.WithContinuationToken(continuationToken), + NoOpTrace.Singleton, + default); + + return tryCreateContext; + }, cancellationToken: cancellationToken); } - + private static TryCatch TryCreatePassthroughQueryExecutionContext( DocumentContainer documentContainer, InputParameters inputParameters, @@ -478,6 +578,45 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx requestCancellationToken: cancellationToken); } + private static async Task GetPartitionedQueryExecutionInfoAsync( + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + ContainerQueryProperties containerQueryProperties, + ITrace trace, + CancellationToken cancellationToken) + { + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; + if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) + { + // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. + // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this + partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( + cosmosQueryContext, + inputParameters.SqlQuerySpec, + cosmosQueryContext.ResourceLink, + inputParameters.PartitionKey, + trace, + cancellationToken); + } + else + { + Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); + + partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( + cosmosQueryContext.QueryClient, + inputParameters.SqlQuerySpec, + cosmosQueryContext.ResourceTypeEnum, + partitionKeyDefinition, + inputParameters.PartitionKey != null, + containerQueryProperties.GeospatialType, + cosmosQueryContext.UseSystemPrefix, + trace, + cancellationToken); + } + + return partitionedQueryExecutionInfo; + } + /// /// Gets the list of partition key ranges. /// 1. Check partition key range id @@ -606,7 +745,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP return partitionKeyDefinition; } - private static async Task GetTargetRangeOptimisticDirectExecutionAsync( + private static async Task TryGetTargetRangeOptimisticDirectExecutionAsync( InputParameters inputParameters, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, CosmosQueryContext cosmosQueryContext, @@ -734,6 +873,24 @@ public InputParameters( public bool ReturnResultsInDeterministicOrder { get; } public TestInjections TestInjections { get; } public bool ForcePassthrough { get; } + + public InputParameters WithContinuationToken(CosmosElement token) + { + return new InputParameters( + this.SqlQuerySpec, + token, + this.InitialFeedRange, + this.MaxConcurrency, + this.MaxItemCount, + this.MaxBufferedItemCount, + this.PartitionKey, + this.Properties, + this.PartitionedQueryExecutionInfo, + this.ExecutionEnvironment, + this.ReturnResultsInDeterministicOrder, + this.ForcePassthrough, + this.TestInjections); + } } internal sealed class AggregateProjectionDetector diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index bbd3d7be4e..10c3b0ee5e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -1153,9 +1153,7 @@ private static bool IsSplitException(Exception exception) exception = exception.InnerException; } - return exception is CosmosException cosmosException - && (cosmosException.StatusCode == HttpStatusCode.Gone) - && (cosmosException.SubStatusCode == (int)Documents.SubStatusCodes.PartitionKeyRangeGone); + return exception.IsPartitionSplitException(); } public void SetCancellationToken(CancellationToken cancellationToken) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs index c81c378029..59f87295f3 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs @@ -43,11 +43,11 @@ public static CosmosElement ToCosmosElement(OptimisticDirectExecutionContinuatio public static TryCatch TryCreateFromCosmosElement(CosmosElement cosmosElement) { CosmosObject cosmosObjectContinuationToken = cosmosElement as CosmosObject; - if (cosmosObjectContinuationToken == null) + if (cosmosObjectContinuationToken == null || !cosmosObjectContinuationToken.ContainsKey(OptimisticDirectExecutionToken)) { return TryCatch.FromException( - new MalformedChangeFeedContinuationTokenException( - message: $"Malformed Continuation Token")); + new MalformedContinuationTokenException( + message: $"Malformed Continuation Token: Expected OptimisticDirectExecutionToken\r\n")); } TryCatch inner = ParallelContinuationToken.TryCreateFromCosmosElement(cosmosObjectContinuationToken[OptimisticDirectExecutionToken]); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index 9f86b0ad8b..0664603024 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -12,168 +12,268 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQu using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Exceptions; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Tracing; - using static Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.PartitionMapper; internal sealed class OptimisticDirectExecutionQueryPipelineStage : IQueryPipelineStage { - private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; - - private OptimisticDirectExecutionQueryPipelineStage( - QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator) + private enum ExecutionState { - this.queryPartitionRangePageAsyncEnumerator = queryPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(queryPartitionRangePageAsyncEnumerator)); + OptimisticDirectExecution, + SpecializedDocumentQueryExecution, } - public TryCatch Current { get; private set; } + private const string optimisticDirectExecutionToken = "OptimisticDirectExecutionToken"; + private readonly FallbackQueryPipelineStageFactory queryPipelineStageFactory; + private TryCatch inner; + private CosmosElement continuationToken; + private ExecutionState executionState; - public ValueTask DisposeAsync() + private OptimisticDirectExecutionQueryPipelineStage(TryCatch inner, FallbackQueryPipelineStageFactory queryPipelineStageFactory, CosmosElement continuationToken) { - return this.queryPartitionRangePageAsyncEnumerator.DisposeAsync(); + this.inner = inner; + this.queryPipelineStageFactory = queryPipelineStageFactory; + this.continuationToken = continuationToken; + this.executionState = ExecutionState.OptimisticDirectExecution; } - public void SetCancellationToken(CancellationToken cancellationToken) + public delegate Task> FallbackQueryPipelineStageFactory(CosmosElement continuationToken); + + public TryCatch Current => this.inner.Try(pipelineStage => pipelineStage.Current); + + public ValueTask DisposeAsync() { - this.queryPartitionRangePageAsyncEnumerator.SetCancellationToken(cancellationToken); + return this.inner.Failed ? default : this.inner.Result.DisposeAsync(); } public async ValueTask MoveNextAsync(ITrace trace) { - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } + TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace)); + bool success = hasNext.Succeeded && hasNext.Result; + bool isPartitionSplitException = hasNext.Succeeded && this.Current.Failed && this.Current.InnerMostException.IsPartitionSplitException(); - if (!await this.queryPartitionRangePageAsyncEnumerator.MoveNextAsync(trace)) + if (success && !isPartitionSplitException) { - this.Current = default; - return false; + this.continuationToken = this.Current.Succeeded ? this.Current.Result.State?.Value : null; } - - TryCatch partitionPage = this.queryPartitionRangePageAsyncEnumerator.Current; - if (partitionPage.Failed) + else if (isPartitionSplitException && this.executionState == ExecutionState.OptimisticDirectExecution) { - this.Current = partitionPage; - return true; + this.inner = await this.queryPipelineStageFactory(this.TryUnwrapContinuationToken()); + this.executionState = ExecutionState.SpecializedDocumentQueryExecution; + if (this.inner.Failed) + { + return false; + } + + success = await this.inner.Result.MoveNextAsync(trace); } - QueryPage backendQueryPage = partitionPage.Result; + return success; + } - QueryState queryState; - if (backendQueryPage.State == null) - { - queryState = null; - } - else + public void SetCancellationToken(CancellationToken cancellationToken) + { + this.inner.Try(pipelineStage => pipelineStage.SetCancellationToken(cancellationToken)); + } + + private CosmosElement TryUnwrapContinuationToken() + { + if (this.continuationToken != null) { - QueryState backendQueryState = backendQueryPage.State; - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: (backendQueryState?.Value as CosmosString)?.Value, - range: ((FeedRangeEpk)this.queryPartitionRangePageAsyncEnumerator.FeedRangeState.FeedRange).Range); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - queryState = new QueryState(cosmosElementContinuationToken); + CosmosObject cosmosObject = this.continuationToken as CosmosObject; + CosmosElement backendContinuationToken = cosmosObject[optimisticDirectExecutionToken]; + Debug.Assert(backendContinuationToken != null); + return CosmosArray.Create(backendContinuationToken); } - QueryPage queryPage = new QueryPage( - backendQueryPage.Documents, - backendQueryPage.RequestCharge, - backendQueryPage.ActivityId, - backendQueryPage.ResponseLengthInBytes, - backendQueryPage.CosmosQueryExecutionInfo, - disallowContinuationTokenMessage: null, - backendQueryPage.AdditionalHeaders, - queryState); - - this.Current = TryCatch.FromResult(queryPage); - return true; + return null; } public static TryCatch MonadicCreate( - IDocumentContainer documentContainer, - SqlQuerySpec sqlQuerySpec, - FeedRangeEpk targetRange, - Cosmos.PartitionKey? partitionKey, - QueryPaginationOptions queryPaginationOptions, - CosmosElement continuationToken, - CancellationToken cancellationToken) + DocumentContainer documentContainer, + CosmosQueryExecutionContextFactory.InputParameters inputParameters, + FeedRangeEpk targetRange, + QueryPaginationOptions queryPaginationOptions, + FallbackQueryPipelineStageFactory fallbackQueryPipelineStageFactory, + CancellationToken cancellationToken) { - if (targetRange == null) + TryCatch pipelineStage = OptimisticDirectExecutionQueryPipelineImpl.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: inputParameters.SqlQuerySpec, + targetRange: targetRange, + queryPaginationOptions: queryPaginationOptions, + partitionKey: inputParameters.PartitionKey, + continuationToken: inputParameters.InitialUserContinuationToken, + cancellationToken: cancellationToken); + + if (pipelineStage.Failed) { - throw new ArgumentNullException(nameof(targetRange)); + return pipelineStage; } - - TryCatch> monadicExtractState; - if (continuationToken == null) + + OptimisticDirectExecutionQueryPipelineStage odePipelineStageMonadicCreate = new OptimisticDirectExecutionQueryPipelineStage(pipelineStage, fallbackQueryPipelineStageFactory, inputParameters.InitialUserContinuationToken); + return TryCatch.FromResult(odePipelineStageMonadicCreate); + } + + private class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage + { + private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; + + private OptimisticDirectExecutionQueryPipelineImpl( + QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator) { - FeedRangeState getState = new (targetRange, (QueryState)null); - monadicExtractState = TryCatch>.FromResult(getState); + this.queryPartitionRangePageAsyncEnumerator = queryPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(queryPartitionRangePageAsyncEnumerator)); } - else + + public TryCatch Current { get; private set; } + + public ValueTask DisposeAsync() { - monadicExtractState = MonadicExtractState(continuationToken, targetRange); + return this.queryPartitionRangePageAsyncEnumerator.DisposeAsync(); } - - if (monadicExtractState.Failed) + + public void SetCancellationToken(CancellationToken cancellationToken) { - return TryCatch.FromException(monadicExtractState.Exception); + this.queryPartitionRangePageAsyncEnumerator.SetCancellationToken(cancellationToken); } - FeedRangeState feedRangeState = monadicExtractState.Result; + public async ValueTask MoveNextAsync(ITrace trace) + { + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } - QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( - documentContainer, - sqlQuerySpec, - feedRangeState, - partitionKey, - queryPaginationOptions, - cancellationToken); + if (!await this.queryPartitionRangePageAsyncEnumerator.MoveNextAsync(trace)) + { + this.Current = default; + return false; + } - OptimisticDirectExecutionQueryPipelineStage stage = new OptimisticDirectExecutionQueryPipelineStage(partitionPageEnumerator); - return TryCatch.FromResult(stage); - } + TryCatch partitionPage = this.queryPartitionRangePageAsyncEnumerator.Current; + if (partitionPage.Failed) + { + this.Current = TryCatch.FromException(partitionPage.Exception); + return true; + } - private static TryCatch> MonadicExtractState( - CosmosElement continuationToken, - FeedRangeEpk range) - { - if (continuationToken == null) - { - throw new ArgumentNullException(nameof(continuationToken)); + QueryPage backendQueryPage = partitionPage.Result; + + QueryState queryState; + if (backendQueryPage.State == null) + { + queryState = null; + } + else + { + QueryState backendQueryState = backendQueryPage.State; + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: (backendQueryState?.Value as CosmosString)?.Value, + range: ((FeedRangeEpk)this.queryPartitionRangePageAsyncEnumerator.FeedRangeState.FeedRange).Range); + + OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); + CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); + queryState = new QueryState(cosmosElementContinuationToken); + } + + QueryPage queryPage = new QueryPage( + backendQueryPage.Documents, + backendQueryPage.RequestCharge, + backendQueryPage.ActivityId, + backendQueryPage.ResponseLengthInBytes, + backendQueryPage.CosmosQueryExecutionInfo, + disallowContinuationTokenMessage: null, + backendQueryPage.AdditionalHeaders, + queryState); + + this.Current = TryCatch.FromResult(queryPage); + return true; } - TryCatch tryCreateContinuationToken = OptimisticDirectExecutionContinuationToken.TryCreateFromCosmosElement(continuationToken); - if (tryCreateContinuationToken.Failed) + public static TryCatch MonadicCreate( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + FeedRangeEpk targetRange, + Cosmos.PartitionKey? partitionKey, + QueryPaginationOptions queryPaginationOptions, + CosmosElement continuationToken, + CancellationToken cancellationToken) { - return TryCatch>.FromException(tryCreateContinuationToken.Exception); - } + if (targetRange == null) + { + throw new ArgumentNullException(nameof(targetRange)); + } - TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( - range, - tryCreateContinuationToken.Result); + TryCatch> monadicExtractState; + if (continuationToken == null) + { + FeedRangeState getState = new (targetRange, (QueryState)null); + monadicExtractState = TryCatch>.FromResult(getState); + } + else + { + monadicExtractState = MonadicExtractState(continuationToken, targetRange); + } - if (partitionMappingMonad.Failed) + if (monadicExtractState.Failed) + { + return TryCatch.FromException(monadicExtractState.Exception); + } + + FeedRangeState feedRangeState = monadicExtractState.Result; + + QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( + documentContainer, + sqlQuerySpec, + feedRangeState, + partitionKey, + queryPaginationOptions, + cancellationToken); + + OptimisticDirectExecutionQueryPipelineImpl stage = new OptimisticDirectExecutionQueryPipelineImpl(partitionPageEnumerator); + return TryCatch.FromResult(stage); + } + + private static TryCatch> MonadicExtractState( + CosmosElement continuationToken, + FeedRangeEpk range) { - return TryCatch>.FromException( - partitionMappingMonad.Exception); + if (continuationToken == null) + { + throw new ArgumentNullException(nameof(continuationToken)); + } + + TryCatch tryCreateContinuationToken = OptimisticDirectExecutionContinuationToken.TryCreateFromCosmosElement(continuationToken); + if (tryCreateContinuationToken.Failed) + { + return TryCatch>.FromException(tryCreateContinuationToken.Exception); + } + + TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( + range, + tryCreateContinuationToken.Result); + + if (partitionMappingMonad.Failed) + { + return TryCatch>.FromException( + partitionMappingMonad.Exception); + } + + PartitionMapper.PartitionMapping partitionMapping = partitionMappingMonad.Result; + + KeyValuePair kvpRange = new KeyValuePair( + partitionMapping.TargetMapping.Keys.First(), + partitionMapping.TargetMapping.Values.First()); + + FeedRangeState feedRangeState = new FeedRangeState(kvpRange.Key, kvpRange.Value?.Token != null ? new QueryState(CosmosString.Create(kvpRange.Value.Token.Token)) : null); + + return TryCatch>.FromResult(feedRangeState); } - - PartitionMapping partitionMapping = partitionMappingMonad.Result; - - KeyValuePair kvpRange = new KeyValuePair( - partitionMapping.TargetMapping.Keys.First(), - partitionMapping.TargetMapping.Values.First()); - - FeedRangeState feedRangeState = new FeedRangeState(kvpRange.Key, kvpRange.Value?.Token != null ? new QueryState(CosmosString.Create(kvpRange.Value.Token.Token)) : null); - - return TryCatch>.FromResult(feedRangeState); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml index b56c470469..7a8259eefc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml @@ -38,4 +38,30 @@ false + + + Single Partition Key with Parallel continuation token + SELECT * FROM c + + /pk + + Hash + + + false + + + + + Single Partition Key with OrderBy continuation token + SELECT * FROM c ORDER BY c._ts + + /pk + + Hash + + + false + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml index 7d4f7ce18d..2482925bd8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml @@ -38,4 +38,30 @@ true + + + Single Partition Key and Value Field + SELECT * FROM c + + /pk + + Hash + + + true + + + + + Single Partition Key and Ode continuation token + SELECT * FROM c + + /pk + + Hash + + + true + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index f849a04913..6737a3d338 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -3,33 +3,31 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; - using System.Xml; - using Microsoft.Azure.Documents; - using Microsoft.Azure.Documents.Routing; - using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Cosmos.Test.BaselineTest; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; - using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; + using System.IO; + using System.Linq; + using System.Net; + using System.Threading; using System.Threading.Tasks; + using System.Xml; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Tests.Pagination; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Cosmos.Query.Core.QueryClient; - using Moq; using Microsoft.Azure.Cosmos.Query; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; + using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; - using Microsoft.Azure.Cosmos.Routing; - using System.Threading; - using System.Linq; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using System.IO; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.IdentityModel.Tokens; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; + using Microsoft.Azure.Cosmos.Test.BaselineTest; + using Microsoft.Azure.Cosmos.Tests.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Routing; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; [TestClass] public class OptimisticDirectExecutionQueryBaselineTests : BaselineTests @@ -38,6 +36,10 @@ public class OptimisticDirectExecutionQueryBaselineTests : BaselineTests testVariations = new List { CreateInput( @@ -60,6 +62,22 @@ public void PositiveOptimisticDirectExecutionOutput() expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", partitionKeyValue: @"value"), + + CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: null), + + CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: cosmosElementOdeContinuationToken), }; this.ExecuteTestSuite(testVariations); } @@ -68,6 +86,23 @@ public void PositiveOptimisticDirectExecutionOutput() [Owner("akotalwar")] public void NegativeOptimisticDirectExecutionOutput() { + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: Guid.NewGuid().ToString(), + range: new Documents.Routing.Range("A", "B", true, false)); + + OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + parallelContinuationToken, + new List() { new OrderByItem(CosmosObject.Create(new Dictionary() { { "item", CosmosString.Create("asdf") } })) }, + rid: "43223532", + skipCount: 42, + filter: "filter"); + + CosmosElement cosmosElementOrderByContinuationToken = CosmosArray.Create( + new List() + { + OrderByContinuationToken.ToCosmosElement(orderByContinuationToken) + }); + List testVariations = new List { CreateInput( @@ -90,58 +125,67 @@ public void NegativeOptimisticDirectExecutionOutput() expectedOptimisticDirectExecution: false, partitionKeyPath: @"/pk", partitionKeyValue: null), + + CreateInput( + description: @"Single Partition Key with Parallel continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: CosmosArray.Create(new List() { ParallelContinuationToken.ToCosmosElement(parallelContinuationToken) })), + + CreateInput( + description: @"Single Partition Key with OrderBy continuation token", + query: "SELECT * FROM c ORDER BY c._ts", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: cosmosElementOrderByContinuationToken), }; this.ExecuteTestSuite(testVariations); } - + // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done [TestMethod] - public async Task TestDefaultTestInjectionSettings() + public async Task TestDefaultTestInjectionSettingsAsync() { TestInjections testInjection = new TestInjections(simulate429s: false, simulateEmptyPages: false); Assert.AreEqual(testInjection.EnableOptimisticDirectExecution, false); } - [TestMethod] - [Owner("akotalwar")] - public async Task TestMonadicCreateOdePipeline() - { - int numItems = 10; - bool multiPartition = false; - string query = "SELECT * FROM c"; - - // null continuation token - Assert.IsTrue(await TryMonadicCreate(numItems, multiPartition, query, targetRange: FeedRangeEpk.FullRange, continuationToken: null)); - - CosmosElement cosmosElementContinuationToken = CosmosElement.Parse( - "{\"OptimisticDirectExecutionToken\":{\"token\":\"{\\\"resourceId\\\":\\\"AQAAAMmFOw8LAAAAAAAAAA==\\\",\\\"skipCount\\\":1}\"," + - "\"range\":{\"min\":\"\",\"max\":\"FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF\"}}}"); - Range range = new Documents.Routing.Range("", "FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF", isMinInclusive: true, isMaxInclusive: false); - - // single continuation token - Assert.IsTrue(await TryMonadicCreate(numItems, multiPartition, query, targetRange: new FeedRangeEpk(range), continuationToken: cosmosElementContinuationToken)); - - //TODO: Add non Ode continuation token case - } - - // test checks that the pipeline can take a query to the backend and returns its associated document(s). + // test checks that the pipeline can take a query to the backend and returns its associated document(s). [TestMethod] public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() { int numItems = 100; - string query = "SELECT VALUE COUNT(1) FROM c"; + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT VALUE COUNT(1) FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: false); - IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); + IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); int documentCountInSinglePartition = 0; while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); documentCountInSinglePartition += Int32.Parse(tryGetPage.Result.Documents[0].ToString()); + + if (tryGetPage.Result.State == null) + { + break; + } } Assert.AreEqual(100, documentCountInSinglePartition); @@ -152,10 +196,17 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() { int numItems = 100; - int result = await this.CreateOptimisticPipelineAndDrainAsync( - numItems: numItems, - isMultiPartition: false, - query: "SELECT * FROM c", + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, expectedContinuationTokenCount: 10); Assert.AreEqual(numItems, result); @@ -165,9 +216,18 @@ public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() [TestMethod] public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync() { - Assert.IsTrue(await ExecuteGoneExceptionOnOdePipeline(isMultiPartition: false)); + Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: false)); + + Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: true)); + } + + // test to check if failing fallback pipeline is handled properly + [TestMethod] + public async Task TestHandlingOfFailedFallbackPipelineOnSingleAndMultiplePartitionAsync() + { + Assert.IsTrue(await TestHandlingOfFailedFallbackPipeline(isMultiPartition: false)); - Assert.IsTrue(await ExecuteGoneExceptionOnOdePipeline(isMultiPartition: true)); + Assert.IsTrue(await TestHandlingOfFailedFallbackPipeline(isMultiPartition: true)); } // The reason we have the below test is to show the missing capabilities of the OptimisticDirectExecution pipeline. @@ -177,66 +237,126 @@ public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync( public async Task TestPipelineForDistributedQueryAsync() { int numItems = 100; - int result = await this.CreateOptimisticPipelineAndDrainAsync( - numItems: numItems, - isMultiPartition: false, - query: "SELECT AVG(c) FROM c", + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT AVG(c) FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, expectedContinuationTokenCount: 0); //TODO: Add validation for actual value of average Assert.AreEqual(1, result); } - private static async Task TryMonadicCreate(int numItems, bool multiPartition, string query, FeedRangeEpk targetRange, CosmosElement continuationToken) + // Creates a gone exception after the first MoveNexyAsync() call. This allows for the pipeline to return some documents before failing + private static async Task ExecuteGoneExceptionOnODEPipeline(bool isMultiPartition) + { + int numItems = 100; + List documents = new List(); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); + (MergeTestUtil mergeTest, IQueryPipelineStage queryPipelineStage) = await CreateFallbackPipelineTestInfrastructure(numItems, isFailedFallbackPipelineTest: false, isMultiPartition, queryRequestOptions); + + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + { + if (mergeTest.MoveNextCounter == 1) + { + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } + else + { + Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } + + TryCatch tryGetPage = queryPipelineStage.Current; + + if (tryGetPage.Failed) + { + // failure should never come till here. Should be handled before + Assert.Fail("Unexpected error. Gone Exception should not reach till here"); + } + + documents.AddRange(tryGetPage.Result.Documents); + } + + Assert.AreEqual(numItems, documents.Count); + return true; + } + + private static async Task TestHandlingOfFailedFallbackPipeline(bool isMultiPartition) { - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition); + int numItems = 100; + List documents = new List(); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); + (MergeTestUtil mergeTest, IQueryPipelineStage queryPipelineStage) = await CreateFallbackPipelineTestInfrastructure(numItems, isFailedFallbackPipelineTest: true, isMultiPartition, queryRequestOptions); + + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + { + TryCatch tryGetPage = queryPipelineStage.Current; + if (tryGetPage.Failed) + { + if (mergeTest.MoveNextCounter == 3) + { + Assert.IsTrue(tryGetPage.InnerMostException.Message.Equals("Injected failure")); + Assert.AreNotEqual(numItems, documents.Count); + return true; + } + else + { + Assert.Fail("Fallback pipeline failure not handled correctly"); + return false; + } + } - TryCatch monadicQueryPipelineStage = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: inMemoryCollection, - sqlQuerySpec: new SqlQuerySpec(query), - targetRange: targetRange, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - cancellationToken: default, - continuationToken: continuationToken); + documents.AddRange(tryGetPage.Result.Documents); + } - return monadicQueryPipelineStage.Succeeded; + return false; } - private static async Task CreateOptimisticDirectExecutionPipelineStateAsync(DocumentContainer documentContainer, string query, CosmosElement continuationToken) + private static async Task<(MergeTestUtil, IQueryPipelineStage)> CreateFallbackPipelineTestInfrastructure(int numItems, bool isFailedFallbackPipelineTest, bool isMultiPartition, QueryRequestOptions queryRequestOptions) { - List targetRanges = await documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); + List documents = new List(); + MergeTestUtil mergeTest = new MergeTestUtil(isFailedFallbackPipelineTest); - // only one range is taken because Ode pipeline can only accept one range - FeedRangeEpk firstRange = targetRanges[0]; + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); - TryCatch monadicQueryPipelineStage = OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: documentContainer, - sqlQuerySpec: new SqlQuerySpec(query), - targetRange: firstRange, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - partitionKey: null, - continuationToken: continuationToken, - cancellationToken: default); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync( + numItems, + multiPartition: isMultiPartition, + failureConfigs: new FlakyDocumentContainer.FailureConfigs( + inject429s: false, + injectEmptyPages: false, + shouldReturnFailure: mergeTest.ShouldReturnFailure)); - Assert.IsTrue(monadicQueryPipelineStage.Succeeded); - IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; + IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); - return queryPipelineStage; + return (mergeTest, queryPipelineStage); } - private async Task CreateOptimisticPipelineAndDrainAsync(int numItems, bool isMultiPartition, string query, int expectedContinuationTokenCount) + private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestInput input, int numItems, bool isMultiPartition, int expectedContinuationTokenCount) { + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition); - IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); - + IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); + List documents = new List(); int continuationTokenCount = 0; while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); @@ -248,7 +368,15 @@ private async Task CreateOptimisticPipelineAndDrainAsync(int numItems, bool } else { - queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: tryGetPage.Result.State.Value); + input = CreateInput( + description: input.Description, + query: input.Query, + expectedOptimisticDirectExecution: input.ExpectedOptimisticDirectExecution, + partitionKeyPath: @"/pk", + partitionKeyValue: input.PartitionKeyValue, + continuationToken: tryGetPage.Result.State.Value); + + queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); } continuationTokenCount++; @@ -258,57 +386,34 @@ private async Task CreateOptimisticPipelineAndDrainAsync(int numItems, bool return documents.Count; } - // it creates a gone exception after the first MoveNexyAsync() call. This allows for the pipeline to return some documents before failing - // TODO: With the addition of the merge/split support, this queryPipelineStage should be able to return all documents regardless of a gone exception happening - private static async Task ExecuteGoneExceptionOnOdePipeline(bool isMultiPartition) + internal static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) { - int numItems = 100; - string query = "SELECT * FROM c"; - List documents = new List(); - string goneExceptionMessage = $"Epk Range: Partition does not exist at the given range."; - CosmosException goneException = new CosmosException( - message: goneExceptionMessage, - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: "0f8fad5b-d9cb-469f-a165-70867728950e", - requestCharge: default); - - int moveNextAsyncCounter = 0; - bool caughtGoneException = false; - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync( - numItems, - multiPartition: isMultiPartition, - failureConfigs: new FlakyDocumentContainer.FailureConfigs( - inject429s: false, - injectEmptyPages: false, - shouldReturnFailure: () => Task.FromResult(moveNextAsyncCounter == 1 ? goneException : null))); - - IQueryPipelineStage queryPipelineStage = await CreateOptimisticDirectExecutionPipelineStateAsync(inMemoryCollection, query, continuationToken: null); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) - { - moveNextAsyncCounter++; - TryCatch tryGetPage = queryPipelineStage.Current; - - if (tryGetPage.Failed == true) - { - string errorRecieved = tryGetPage.Exception.InnerException.Message; - Assert.AreEqual(goneException.GetType(), tryGetPage.Exception.InnerException.GetType()); + TryCatch tryGetQueryPlan = QueryPartitionProviderTestInstance.Object.TryGetPartitionedQueryExecutionInfo( + querySpecJsonString: querySpecJsonString, + partitionKeyDefinition: pkDefinition, + requireFormattableOrderByQuery: true, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + hasLogicalPartitionKey: false, + allowDCount: true, + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); - if (errorRecieved.Equals(goneExceptionMessage)) - { - caughtGoneException = true; - break; - } - } + return tryGetQueryPlan.Result; + } - documents.AddRange(tryGetPage.Result.Documents); - } + private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) + { + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - // Once fallback plan is implemented, this test should be able to return all 100 documents - Assert.AreEqual(10, documents.Count); - Assert.IsTrue(caughtGoneException); + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); - return true; + Assert.IsNotNull(queryPipelineStage); + return queryPipelineStage; } private static async Task CreateDocumentContainerAsync( @@ -335,7 +440,7 @@ private static async Task CreateDocumentContainerAsync( DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); // a value of 2 would lead to 4 partitions (2 * 2). 4 partitions are used because they're easy to manage + demonstrates multi partition use case - int exponentPartitionKeyRanges = 2; + int exponentPartitionKeyRanges = 2; IReadOnlyList ranges; @@ -359,7 +464,7 @@ private static async Task CreateDocumentContainerAsync( ranges = await documentContainer.GetFeedRangesAsync( trace: NoOpTrace.Singleton, cancellationToken: default); - + int rangeCount = multiPartition ? 4 : 1; Assert.AreEqual(rangeCount, ranges.Count); @@ -367,7 +472,7 @@ private static async Task CreateDocumentContainerAsync( for (int i = 0; i < numItems; i++) { // Insert an item - CosmosObject item = CosmosObject.Parse($"{{\"pk\" : {i} }}"); + CosmosObject item = CosmosObject.Parse($"{{\"pk\" : \"a\" }}"); TryCatch monadicCreateRecord = await documentContainer.MonadicCreateItemAsync(item, cancellationToken: default); Assert.IsTrue(monadicCreateRecord.Succeeded); } @@ -400,52 +505,43 @@ private static OptimisticDirectExecutionTestInput CreateInput( return new OptimisticDirectExecutionTestInput(description, query, new SqlQuerySpec(query), expectedOptimisticDirectExecution, partitionKeyPath, partitionKeyValue, continuationToken); } - private static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) - { - TryCatch tryGetQueryPlan = QueryPartitionProviderTestInstance.Object.TryGetPartitionedQueryExecutionInfo( - querySpecJsonString: querySpecJsonString, - partitionKeyDefinition: pkDefinition, - requireFormattableOrderByQuery: true, - isContinuationExpected: true, - allowNonValueAggregateQuery: true, - hasLogicalPartitionKey: false, - allowDCount: true, - useSystemPrefix: false, - geospatialType: Cosmos.GeospatialType.Geography); - - return tryGetQueryPlan.Result; - } - public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirectExecutionTestInput input) { // gets DocumentContainer IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(input.PartitionKeyDefinition); DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - SqlQuerySpec sqlQuerySpec = new SqlQuerySpec(input.Query); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - // gets query context - string databaseId = "db1234"; - string resourceLink = $"dbs/{databaseId}/colls"; - CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(), - resourceTypeEnum: Documents.ResourceType.Document, - operationType: Documents.OperationType.Query, - resourceType: typeof(QueryResponseCore), - resourceLink: resourceLink, - isContinuationExpected: true, - allowNonValueAggregateQuery: true, - useSystemPrefix: false, - correlatedActivityId: Guid.NewGuid()); + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - // gets input parameters - QueryRequestOptions queryRequestOptions = new QueryRequestOptions + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); + + bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton).AsTask().GetAwaiter().GetResult(); + + if (input.ExpectedOptimisticDirectExecution) { - TestSettings = new TestInjections(simulate429s: true, simulateEmptyPages: false, enableOptimisticDirectExecution: true, new TestInjections.ResponseStats()) - }; + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } + else + { + Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } + + Assert.IsNotNull(queryPipelineStage); + Assert.IsTrue(result); + return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); + } + + private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions) + { CosmosSerializerCore serializerCore = new(); - using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(input.Query), Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = GetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, input.PartitionKeyDefinition); @@ -455,7 +551,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect } CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( - sqlQuerySpec: sqlQuerySpec, + sqlQuerySpec: new SqlQuerySpec(input.Query), initialUserContinuationToken: input.ContinuationToken, initialFeedRange: null, maxConcurrency: queryRequestOptions.MaxConcurrency, @@ -466,30 +562,81 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: null, returnResultsInDeterministicOrder: null, - forcePassthrough: true, + forcePassthrough: false, testInjections: queryRequestOptions.TestSettings); - IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( - documentContainer, - cosmosQueryContextCore, - inputParameters, - NoOpTrace.Singleton); + string databaseId = "db1234"; + string resourceLink = $"dbs/{databaseId}/colls"; + CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( + client: new TestCosmosQueryClient(), + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); - bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton).Result; + return Tuple.Create(inputParameters, cosmosQueryContextCore); + } - if (input.ExpectedOptimisticDirectExecution) + private static QueryRequestOptions GetQueryRequestOptions(bool enableOptimisticDirectExecution) + { + return new QueryRequestOptions { - Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + MaxConcurrency = 0, + MaxItemCount = 10, + TestSettings = new TestInjections(simulate429s: true, simulateEmptyPages: false, enableOptimisticDirectExecution: enableOptimisticDirectExecution, new TestInjections.ResponseStats()), + Properties = new Dictionary() + { + { HttpConstants.HttpHeaders.EnumerationDirection, ""}, } - else + }; + } + + private class MergeTestUtil + { + public int MoveNextCounter { get; private set; } + + public bool GoneExceptionCreated { get; private set; } + + public bool TooManyRequestsFailureCreated { get; private set; } + + public bool IsFailedFallbackPipelineTest { get; } + + public MergeTestUtil(bool isFailedFallbackPipelineTest) { - Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + this.IsFailedFallbackPipelineTest = isFailedFallbackPipelineTest; } - Assert.IsNotNull(queryPipelineStage); - Assert.IsTrue(result); + public async Task ShouldReturnFailure() + { + this.MoveNextCounter++; + if (this.MoveNextCounter == 2 && !this.GoneExceptionCreated) + { + this.GoneExceptionCreated = true; + return new CosmosException( + message: $"Epk Range: Partition does not exist at the given range.", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: "0f8fad5b-d9cb-469f-a165-70867728950e", + requestCharge: default); + } + + if (this.IsFailedFallbackPipelineTest && this.GoneExceptionCreated && !this.TooManyRequestsFailureCreated) + { + this.TooManyRequestsFailureCreated = true; + return new CosmosException( + message: "Injected failure", + statusCode: HttpStatusCode.TooManyRequests, + subStatusCode: 3200, + activityId: "111fad5b-d9cb-469f-a165-70867728950e", + requestCharge: 0); + } - return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); + return null; + } } } @@ -578,14 +725,14 @@ public override void SerializeAsXml(XmlWriter xmlWriter) } } } - + internal class TestCosmosQueryClient : CosmosQueryClient { public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); public override bool ByPassQueryParsing() { - throw new NotImplementedException(); + return false; } public override void ClearSessionTokenCache(string collectionFullName) @@ -610,7 +757,11 @@ public override Task ForceRefreshCollectionCacheAsync(string collectionLink, Can public override Task GetCachedContainerQueryPropertiesAsync(string containerLink, Cosmos.PartitionKey? partitionKey, ITrace trace, CancellationToken cancellationToken) { - return Task.FromResult(new ContainerQueryProperties()); + return Task.FromResult(new ContainerQueryProperties( + "test", + WFConstants.BackendHeaders.EffectivePartitionKeyString, + new PartitionKeyDefinition(), + Cosmos.GeospatialType.Geometry)); } public override Task> GetTargetPartitionKeyRangeByFeedRangeAsync(string resourceLink, string collectionResourceId, PartitionKeyDefinition partitionKeyDefinition, FeedRangeInternal feedRangeInternal, bool forceRefresh, ITrace trace) @@ -630,7 +781,12 @@ public override Task> GetTargetPartitionKeyRangesAsync(s public override Task> GetTargetPartitionKeyRangesByEpkStringAsync(string resourceLink, string collectionResourceId, string effectivePartitionKeyString, bool forceRefresh, ITrace trace) { - throw new NotImplementedException(); + return Task.FromResult(new List{new PartitionKeyRange() + { + MinInclusive = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, + MaxExclusive = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey + } + }); } public override Task> TryGetOverlappingRangesAsync(string collectionResourceId, Range range, bool forceRefresh = false) @@ -638,9 +794,14 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) - { - throw new NotImplementedException(); + public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); + return TryCatch.FromResult(partitionedQueryExecutionInfo); } } } From ccaf8fb9dd8517295044e32f1af43b7d0437c64b Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Mon, 23 Jan 2023 20:58:16 +0530 Subject: [PATCH 046/337] [Internal] AI Integration : Fixes operation type for batch (#3660) * fix op type * fix conflict --- Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs | 2 +- .../EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs b/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs index e211117d6f..35aad1be10 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/BatchCore.cs @@ -222,7 +222,7 @@ public override Task ExecuteAsync( operationName: nameof(ExecuteAsync), containerName: this.container.Id, databaseName: this.container.Database.Id, - operationType: Documents.OperationType.Replace, + operationType: Documents.OperationType.Batch, requestOptions: requestOptions, task: (trace) => { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 0bee1cd007..59a5eabf76 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. From c29abfedcbd98edf5ac49c9e58c3befc21dd9c3e Mon Sep 17 00:00:00 2001 From: aavasthy <113193425+aavasthy@users.noreply.github.com> Date: Tue, 24 Jan 2023 11:52:53 -0500 Subject: [PATCH 047/337] CosmosClientOptions: Adds ServerCertificateCustomValidationCallback for Http and TCP (#3636) * Adding ServerCertificateCustomValidationCallback in clientoptions * Adding Server callback for Http and fixing tests * Fixing failing E2Etests * Resolving merge conflicts * Running update contracts script * Running Update contracts script * Running Update contracts script * Reverting the v3 version change * Update based on review comments * Added unit tests * Added remarks for callback delegate * Ran update contracts script * Update based on review comments * Ran update contracts script * Updated unit tests * Making ssl validation function private * Updating test files * Update remarks for sslvalidation public contract * Added emulator tests for server validation Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> --- .../src/ConnectionPolicy.cs | 13 +++++- .../src/CosmosClientOptions.cs | 15 +++++- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 18 ++++++-- .../src/HttpClient/CosmosHttpClientCore.cs | 11 ++++- .../src/Resource/ClientContextCore.cs | 13 +++++- .../ClientTests.cs | 37 ++++++++++++++- .../Contracts/DotNetPreviewSDKAPI.json | 10 ++-- .../Contracts/DotNetSDKAPI.json | 19 ++++++++ .../CosmosClientResourceUnitTests.cs | 46 ++++++++++++++++++- 9 files changed, 164 insertions(+), 18 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index dca46a883f..172aac4fbb 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -8,6 +8,8 @@ namespace Microsoft.Azure.Cosmos using System.Collections.ObjectModel; using System.Collections.Specialized; using System.Net.Http; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; @@ -46,8 +48,8 @@ public ConnectionPolicy() this.MaxConnectionLimit = defaultMaxConcurrentConnectionLimit; this.RetryOptions = new RetryOptions(); this.EnableReadRequestsFallback = null; - this.EnableClientTelemetry = ClientTelemetryOptions.IsClientTelemetryEnabled(); + this.ServerCertificateCustomValidationCallback = null; } /// @@ -295,6 +297,15 @@ public bool EnablePartitionLevelFailover set; } + /// + /// Gets or sets the certificate validation callback. + /// + internal Func ServerCertificateCustomValidationCallback + { + get; + set; + } + /// /// Gets or sets the flag to enable writes on any locations (regions) for geo-replicated database accounts in the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index a75b508e3b..fec7f4ac2f 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -12,6 +12,8 @@ namespace Microsoft.Azure.Cosmos using System.Net; using System.Net.Http; using System.Net.Http.Headers; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; @@ -633,6 +635,16 @@ internal Protocol ConnectionProtocol /// internal Func TransportClientHandlerFactory { get; set; } + /// + /// A callback delegate to do custom certificate validation for both HTTP and TCP. + /// + /// + /// + /// Customizing SSL verification is not recommended in production environments. + /// + /// + public Func ServerCertificateCustomValidationCallback { get; set; } + /// /// API type for the account /// @@ -746,7 +758,8 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) EnablePartitionLevelFailover = this.EnablePartitionLevelFailover, PortReuseMode = this.portReuseMode, EnableTcpConnectionEndpointRediscovery = this.EnableTcpConnectionEndpointRediscovery, - HttpClientFactory = this.httpClientFactory + HttpClientFactory = this.httpClientFactory, + ServerCertificateCustomValidationCallback = this.ServerCertificateCustomValidationCallback }; if (this.EnableClientTelemetry.HasValue) diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 61e7c99665..c7504d312c 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos using System.Linq; using System.Net; using System.Net.Http; + using System.Net.Security; using System.Security; using System.Text; using System.Threading; @@ -163,6 +164,9 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider //Trace Id. private int traceId; + //RemoteCertificateValidationCallback + internal RemoteCertificateValidationCallback remoteCertificateValidationCallback; + //SessionContainer. internal ISessionContainer sessionContainer; @@ -421,6 +425,7 @@ internal DocumentClient(Uri serviceEndpoint, /// Factory that creates store clients sharing the same transport client to optimize network resource reuse across multiple document clients in the same process. /// Flag to allow Quorum Read with Eventual Consistency Account /// + /// This delegate responsible for validating the third party certificate. /// /// The service endpoint can be obtained from the Azure Management Portal. /// If you are connecting using one of the Master Keys, these can be obtained along with the endpoint from the Azure Management Portal @@ -446,7 +451,8 @@ internal DocumentClient(Uri serviceEndpoint, Func transportClientHandlerFactory = null, IStoreClientFactory storeClientFactory = null, bool isLocalQuorumConsistency = false, - string cosmosClientId = null) + string cosmosClientId = null, + RemoteCertificateValidationCallback remoteCertificateValidationCallback = null) { if (sendingRequestEventArgs != null) { @@ -478,7 +484,8 @@ internal DocumentClient(Uri serviceEndpoint, sessionContainer: sessionContainer, enableCpuMonitor: enableCpuMonitor, storeClientFactory: storeClientFactory, - cosmosClientId: cosmosClientId); + cosmosClientId: cosmosClientId, + remoteCertificateValidationCallback: remoteCertificateValidationCallback); } /// @@ -660,7 +667,8 @@ internal virtual void Initialize(Uri serviceEndpoint, bool? enableCpuMonitor = null, IStoreClientFactory storeClientFactory = null, TokenCredential tokenCredential = null, - string cosmosClientId = null) + string cosmosClientId = null, + RemoteCertificateValidationCallback remoteCertificateValidationCallback = null) { if (serviceEndpoint == null) { @@ -668,6 +676,7 @@ internal virtual void Initialize(Uri serviceEndpoint, } this.clientId = cosmosClientId; + this.remoteCertificateValidationCallback = remoteCertificateValidationCallback; this.queryPartitionProvider = new AsyncLazy(async () => { @@ -6648,7 +6657,8 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory retryWithConfiguration: this.ConnectionPolicy.RetryOptions?.GetRetryWithConfiguration(), enableTcpConnectionEndpointRediscovery: this.ConnectionPolicy.EnableTcpConnectionEndpointRediscovery, addressResolver: this.AddressResolver, - rntbdMaxConcurrentOpeningConnectionCount: this.rntbdMaxConcurrentOpeningConnectionCount); + rntbdMaxConcurrentOpeningConnectionCount: this.rntbdMaxConcurrentOpeningConnectionCount, + remoteCertificateValidationCallback: this.remoteCertificateValidationCallback ); if (this.transportClientHandlerFactory != null) { diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs index f86bd6b183..a48666f16d 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs @@ -10,6 +10,8 @@ namespace Microsoft.Azure.Cosmos using System.Net; using System.Net.Http; using System.Net.Http.Headers; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; @@ -73,7 +75,8 @@ public static CosmosHttpClient CreateWithConnectionPolicy( { httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( gatewayModeMaxConnectionLimit: connectionPolicy.MaxConnectionLimit, - webProxy: null); + webProxy: null, + serverCertificateCustomValidationCallback: connectionPolicy.ServerCertificateCustomValidationCallback); } if (sendingRequestEventArgs != null || @@ -96,7 +99,7 @@ public static CosmosHttpClient CreateWithConnectionPolicy( eventSource: eventSource); } - public static HttpMessageHandler CreateHttpClientHandler(int gatewayModeMaxConnectionLimit, IWebProxy webProxy) + public static HttpMessageHandler CreateHttpClientHandler(int gatewayModeMaxConnectionLimit, IWebProxy webProxy, Func serverCertificateCustomValidationCallback) { HttpClientHandler httpClientHandler = new HttpClientHandler(); @@ -110,6 +113,10 @@ public static HttpMessageHandler CreateHttpClientHandler(int gatewayModeMaxConne try { httpClientHandler.MaxConnectionsPerServer = gatewayModeMaxConnectionLimit; + if (serverCertificateCustomValidationCallback != null) + { + httpClientHandler.ServerCertificateCustomValidationCallback = (_, certificate2, x509Chain, sslPolicyErrors) => serverCertificateCustomValidationCallback(certificate2, x509Chain, sslPolicyErrors); + } } // MaxConnectionsPerServer is not supported on some platforms. catch (PlatformNotSupportedException) diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index 191399943f..a9c475615a 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -8,6 +8,8 @@ namespace Microsoft.Azure.Cosmos using System.Diagnostics; using System.IO; using System.Net.Http; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -65,7 +67,8 @@ internal static CosmosClientContext Create( clientOptions = ClientContextCore.CreateOrCloneClientOptions(clientOptions); HttpMessageHandler httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( clientOptions.GatewayModeMaxConnectionLimit, - clientOptions.WebProxy); + clientOptions.WebProxy, + clientOptions.ServerCertificateCustomValidationCallback); DocumentClient documentClient = new DocumentClient( cosmosClient.Endpoint, @@ -79,7 +82,8 @@ internal static CosmosClientContext Create( desiredConsistencyLevel: clientOptions.GetDocumentsConsistencyLevel(), handler: httpMessageHandler, sessionContainer: clientOptions.SessionContainer, - cosmosClientId: cosmosClient.Id); + cosmosClientId: cosmosClient.Id, + remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback)); return ClientContextCore.Create( cosmosClient, @@ -87,6 +91,11 @@ internal static CosmosClientContext Create( clientOptions); } + private static RemoteCertificateValidationCallback SslCustomValidationCallBack(Func serverCertificateCustomValidationCallback) + { + return serverCertificateCustomValidationCallback == null ? null : (_, cert, chain, policy) => serverCertificateCustomValidationCallback((X509Certificate2)cert, chain, policy); + } + internal static CosmosClientContext Create( CosmosClient cosmosClient, DocumentClient documentClient, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index c6a7bc16f7..2c9bf3325c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -7,13 +7,13 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System; using System.Collections.Generic; using System.Diagnostics; - using System.Formats.Asn1; using System.IO; using System.Linq; using System.Net; using System.Net.Http; - using System.Net.NetworkInformation; + using System.Net.Security; using System.Reflection; + using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -446,6 +446,39 @@ internal async Task TestEtagOnUpsertOperation(bool useGateway, Protocol protocol } } } + + [TestMethod] + public async Task Verify_CertificateCallBackGetsCalled_ForTCP_HTTP() + { + string authKey = ConfigurationManager.AppSettings["MasterKey"]; + string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; + int counter = 0; + AzureKeyCredential masterKeyCredential = new AzureKeyCredential(authKey); + CosmosClient cosmosClient = new CosmosClient( + endpoint, + masterKeyCredential, + new CosmosClientOptions() + { + ConnectionMode = ConnectionMode.Direct, + ConnectionProtocol = Protocol.Tcp, + ServerCertificateCustomValidationCallback = (X509Certificate2 cerf, X509Chain chain, SslPolicyErrors error) => { counter ++; return true; } + }); + + string databaseName = Guid.NewGuid().ToString(); + string databaseId = Guid.NewGuid().ToString(); + Cosmos.Database database = null; + //HTTP callback + database = await cosmosClient.CreateDatabaseAsync(databaseId); + + Cosmos.Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); + + //TCP callback + ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); + ResponseMessage responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id)); + + Assert.IsTrue(counter >= 2); + + } [TestMethod] public void SqlQuerySpecSerializationTest() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index c5bb91849b..43801584fe 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -165,11 +165,6 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode AllVersionsAndDeletes;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, "Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes()": { "Type": "Method", "Attributes": [], @@ -179,6 +174,11 @@ "Type": "Method", "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 70e4a5d780..9edd8d6de1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2764,6 +2764,18 @@ ], "MethodInfo": "System.Func`1[System.Net.Http.HttpClient] HttpClientFactory;CanRead:True;CanWrite:True;System.Func`1[System.Net.Http.HttpClient] get_HttpClientFactory();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_HttpClientFactory(System.Func`1[System.Net.Http.HttpClient]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean] get_ServerCertificateCustomValidationCallback()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean] get_ServerCertificateCustomValidationCallback();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean] ServerCertificateCustomValidationCallback": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean] ServerCertificateCustomValidationCallback;CanRead:True;CanWrite:True;System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean] get_ServerCertificateCustomValidationCallback();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ServerCertificateCustomValidationCallback(System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Net.IWebProxy get_WebProxy()": { "Type": "Method", "Attributes": [], @@ -3050,6 +3062,13 @@ "Attributes": [], "MethodInfo": "Void set_SerializerOptions(Microsoft.Azure.Cosmos.CosmosSerializationOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_ServerCertificateCustomValidationCallback(System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_ServerCertificateCustomValidationCallback(System.Func`4[System.Security.Cryptography.X509Certificates.X509Certificate2,System.Security.Cryptography.X509Certificates.X509Chain,System.Net.Security.SslPolicyErrors,System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_TokenCredentialBackgroundRefreshInterval(System.Nullable`1[System.TimeSpan])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientResourceUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientResourceUnitTests.cs index 8ca17376ed..8d3f53edfb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientResourceUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientResourceUnitTests.cs @@ -7,10 +7,16 @@ namespace Microsoft.Azure.Cosmos.Core.Tests using System; using System.Collections.Generic; using System.Net.Http; + using System.Net.Security; + using System.Security.Cryptography.X509Certificates; + using System.Security.Cryptography; using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; + using System.Globalization; + using System.Threading.Tasks; + using Microsoft.Azure.Documents.Collections; [TestClass] public class CosmosClientResourceUnitTests @@ -132,6 +138,44 @@ public void InitializeBatchExecutorForContainer_NotNull_WhenAllowBulk_True() Assert.IsNotNull(container.BatchExecutor); } + [TestMethod] + public void WithServerCertificateAddedClientOptions_CreateContext_RemoteCertificateCallbackReturnsTrue() + { + //Arrange + X509Certificate2 x509Certificate2 = new CertificateRequest("cn=www.test", ECDsa.Create(), HashAlgorithmName.SHA256).CreateSelfSigned(DateTime.Now, DateTime.Now.AddYears(1)); + X509Chain x509Chain = new X509Chain(); + SslPolicyErrors sslPolicyErrors = new SslPolicyErrors(); + + string authKeyValue = "MockAuthKey"; + Mock mockAuth = new Mock(MockBehavior.Strict); + mockAuth.Setup(x => x.Dispose()); + mockAuth.Setup(x => x.AddAuthorizationHeaderAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback( + (headers, uri, verb, tokenType) => headers.Add(Documents.HttpConstants.HttpHeaders.Authorization, authKeyValue)) + .Returns(() => new ValueTask()); + + CosmosClient client = new CosmosClient( + "https://localhost:8081", + authorizationTokenProvider: mockAuth.Object, + new CosmosClientOptions() + { + ServerCertificateCustomValidationCallback = (X509Certificate2 cerf, X509Chain chain, SslPolicyErrors error) => true + }); + + //Act + CosmosClientContext context = ClientContextCore.Create( + client, + client.ClientOptions); + + //Assert + Assert.IsTrue(context.DocumentClient.remoteCertificateValidationCallback(new object(), x509Certificate2, x509Chain, sslPolicyErrors)); + + } + private CosmosClientContext CreateMockClientContext(bool allowBulkExecution = false) { Mock mockClient = new Mock(); @@ -141,6 +185,6 @@ private CosmosClientContext CreateMockClientContext(bool allowBulkExecution = fa mockClient.Object, new MockDocumentClient(), new CosmosClientOptions() { AllowBulkExecution = allowBulkExecution }); - } + } } } From 2608d4af7c45ffb417b72c11d711bca2c570a739 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 26 Jan 2023 11:36:56 -0800 Subject: [PATCH 048/337] Query: Adds EnableOptimisticDirectExecution flag to QueryRequestOptions (#3664) * Added new flag to QueryRequestOptions to allow customers to use Ode pipeline * Updated comments in QueryRequestOptions.cs * Renamed enabledOde to enableOde * Removed default setting for EnableOptimisticDirectExecution --- .../CosmosQueryExecutionContextFactory.cs | 7 +++++- .../src/Query/Core/TestInjections.cs | 5 +--- .../src/Query/v3Query/QueryIterator.cs | 1 + .../src/RequestOptions/QueryRequestOptions.cs | 8 +++++++ .../OptimisticDirectExecutionQueryTests.cs | 23 ++++++------------- .../Query/QueryTestsBase.cs | 1 + ...misticDirectExecutionQueryBaselineTests.cs | 11 +++++---- 7 files changed, 31 insertions(+), 25 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 371391386e..d8a885a07b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -418,6 +418,7 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx inputParameters.ExecutionEnvironment, inputParameters.ReturnResultsInDeterministicOrder, inputParameters.ForcePassthrough, + inputParameters.EnableOptimisticDirectExecution, inputParameters.TestInjections); } @@ -752,7 +753,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ContainerQueryProperties containerQueryProperties, ITrace trace) { - if (inputParameters.TestInjections == null || !inputParameters.TestInjections.EnableOptimisticDirectExecution) return null; + if (!inputParameters.EnableOptimisticDirectExecution) return null; // case 1: Is query going to a single partition bool hasPartitionKey = inputParameters.PartitionKey.HasValue @@ -824,6 +825,7 @@ public InputParameters( ExecutionEnvironment? executionEnvironment, bool? returnResultsInDeterministicOrder, bool forcePassthrough, + bool enableOptimisticDirectExecution, TestInjections testInjections) { this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); @@ -857,6 +859,7 @@ public InputParameters( this.ExecutionEnvironment = executionEnvironment.GetValueOrDefault(InputParameters.DefaultExecutionEnvironment); this.ReturnResultsInDeterministicOrder = returnResultsInDeterministicOrder.GetValueOrDefault(InputParameters.DefaultReturnResultsInDeterministicOrder); this.ForcePassthrough = forcePassthrough; + this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; this.TestInjections = testInjections; } @@ -873,6 +876,7 @@ public InputParameters( public bool ReturnResultsInDeterministicOrder { get; } public TestInjections TestInjections { get; } public bool ForcePassthrough { get; } + public bool EnableOptimisticDirectExecution { get; } public InputParameters WithContinuationToken(CosmosElement token) { @@ -889,6 +893,7 @@ public InputParameters WithContinuationToken(CosmosElement token) this.ExecutionEnvironment, this.ReturnResultsInDeterministicOrder, this.ForcePassthrough, + this.EnableOptimisticDirectExecution, this.TestInjections); } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/TestInjections.cs b/Microsoft.Azure.Cosmos/src/Query/Core/TestInjections.cs index 7ee877bd14..1328d4dbab 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/TestInjections.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/TestInjections.cs @@ -13,16 +13,13 @@ public enum PipelineType OptimisticDirectExecution, } - public TestInjections(bool simulate429s, bool simulateEmptyPages, bool enableOptimisticDirectExecution = false, ResponseStats responseStats = null) + public TestInjections(bool simulate429s, bool simulateEmptyPages, ResponseStats responseStats = null) { this.SimulateThrottles = simulate429s; this.SimulateEmptyPages = simulateEmptyPages; this.Stats = responseStats; - this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; } - public bool EnableOptimisticDirectExecution { get; } - public bool SimulateThrottles { get; } public bool SimulateEmptyPages { get; } diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index 01a4e1b12e..a820a0a49a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -144,6 +144,7 @@ public static QueryIterator Create( executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, forcePassthrough: forcePassthrough, + enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); return new QueryIterator( diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 9e478c96b9..8711836191 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -43,6 +43,14 @@ public class QueryRequestOptions : RequestOptions /// public bool? EnableLowPrecisionOrderBy { get; set; } + /// + /// Gets or sets the option for customers to opt in for direct (optimistic) execution of the query.. + /// + /// + /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. + /// + internal bool EnableOptimisticDirectExecution { get; set; } + /// /// Gets or sets the maximum number of items that can be buffered client side during /// parallel query execution in the Azure Cosmos DB service. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index acdb4d92de..9d89f6362a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -67,7 +67,8 @@ private static async Task TestPositiveOptimisticDirectExecutionOutput( QueryRequestOptions feedOptions = new QueryRequestOptions { MaxItemCount = -1, - TestSettings = GetTestInjections(simulate429s:false, simulateEmptyPages:false, enableOptimisticDirectExecution:true) + EnableOptimisticDirectExecution = true, + TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; // check if pipeline returns empty continuation token @@ -172,13 +173,11 @@ private static async Task TestPositiveOptimisticDirectExecutionOutput( feedOptions = new QueryRequestOptions { MaxItemCount = pageSizeOptions[i], - PartitionKey = queryAndResults[j].PartitionKey == null + PartitionKey = queryAndResults[j].PartitionKey == null ? null : new Cosmos.PartitionKey(queryAndResults[j].PartitionKey), - TestSettings = GetTestInjections( - simulate429s: false, - simulateEmptyPages: false, - enableOptimisticDirectExecution: queryAndResults[j].EnableOptimisticDirectExecution) + EnableOptimisticDirectExecution = queryAndResults[j].EnableOptimisticDirectExecution, + TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; List items = await RunQueryAsync( @@ -208,7 +207,8 @@ private static async Task TestNegativeOptimisticDirectExecutionOutput( QueryRequestOptions feedOptions = new QueryRequestOptions { PartitionKey = new Cosmos.PartitionKey("/value"), - TestSettings = GetTestInjections(simulate429s: false, simulateEmptyPages: false, enableOptimisticDirectExecution: true) + EnableOptimisticDirectExecution = true, + TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; // check if bad continuation queries and syntax error queries are handled by pipeline @@ -241,15 +241,6 @@ await container.GetItemQueryIterator( } } - private static TestInjections GetTestInjections(bool simulate429s, bool simulateEmptyPages, bool enableOptimisticDirectExecution) - { - return new TestInjections( - simulate429s, - simulateEmptyPages, - enableOptimisticDirectExecution, - new TestInjections.ResponseStats()); - } - private struct SinglePartitionWithContinuationsArgs { public int NumberOfDocuments; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs index 4775716efa..c196af9d44 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs @@ -597,6 +597,7 @@ internal static async Task> QueryWithCosmosElementContinuationTokenAsync Properties = queryRequestOptions.Properties, IsEffectivePartitionKeyRouting = queryRequestOptions.IsEffectivePartitionKeyRouting, CosmosElementContinuationToken = queryRequestOptions.CosmosElementContinuationToken, + EnableOptimisticDirectExecution = queryRequestOptions.EnableOptimisticDirectExecution, TestSettings = queryRequestOptions.TestSettings, }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 6737a3d338..b6a78c111d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -148,11 +148,12 @@ public void NegativeOptimisticDirectExecutionOutput() // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done [TestMethod] - public async Task TestDefaultTestInjectionSettingsAsync() + public async Task TestDefaultQueryRequestOptionsSettings() { - TestInjections testInjection = new TestInjections(simulate429s: false, simulateEmptyPages: false); - Assert.AreEqual(testInjection.EnableOptimisticDirectExecution, false); + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + Assert.AreEqual(requestOptions.EnableOptimisticDirectExecution, false); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). @@ -563,6 +564,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect executionEnvironment: null, returnResultsInDeterministicOrder: null, forcePassthrough: false, + enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); string databaseId = "db1234"; @@ -587,7 +589,8 @@ private static QueryRequestOptions GetQueryRequestOptions(bool enableOptimisticD { MaxConcurrency = 0, MaxItemCount = 10, - TestSettings = new TestInjections(simulate429s: true, simulateEmptyPages: false, enableOptimisticDirectExecution: enableOptimisticDirectExecution, new TestInjections.ResponseStats()), + EnableOptimisticDirectExecution = enableOptimisticDirectExecution, + TestSettings = new TestInjections(simulate429s: true, simulateEmptyPages: false, new TestInjections.ResponseStats()), Properties = new Dictionary() { { HttpConstants.HttpHeaders.EnumerationDirection, ""}, From d6a439f3ef766a911b569fdaf901f422cd50720a Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 1 Feb 2023 16:09:03 -0800 Subject: [PATCH 049/337] [Internal] Tests: Removes Direct/HTTPS emulator tests (#3679) * Removing direct/https tests * mppreference --- .../ClientTests.cs | 6 -- .../GatewayTests.cs | 35 ----------- .../HeadersValidationTests.cs | 63 ------------------- .../NameRoutingTests.cs | 60 ------------------ .../QueryTests.cs | 6 -- .../SmokeTests.cs | 35 ----------- .../Utils/Util.cs | 6 +- templates/emulator-setup.yml | 1 + 8 files changed, 3 insertions(+), 209 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index 2c9bf3325c..a2fcc1f598 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -384,12 +384,6 @@ public async Task TestHeadersPassedinByClient() Assert.AreEqual((ulong)SDKSupportedCapabilities.PartitionMerge, capability & (ulong)SDKSupportedCapabilities.PartitionMerge,$" received header value as {sdkSupportedCapability}"); } - [TestMethod] - public async Task TestEtagOnUpsertOperationForHttpsClient() - { - await this.TestEtagOnUpsertOperation(false, Protocol.Https); - } - [TestMethod] public async Task TestEtagOnUpsertOperationForGatewayClient() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs index d0366cf9b8..0d7eaa7ea5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs @@ -285,13 +285,6 @@ await this.ValidateStoredProcedureCrudAsync(ConsistencyLevel.Session, new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Tcp }); } - [TestMethod] - public async Task ValidateStoredProcedureCrud_SessionDirectHttps() - { - await this.ValidateStoredProcedureCrudAsync(ConsistencyLevel.Session, - new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Https }); - } - internal async Task ValidateStoredProcedureCrudAsync(ConsistencyLevel consistencyLevel, ConnectionPolicy connectionPolicy) { DocumentClient client = TestCommon.CreateClient(connectionPolicy.ConnectionMode == ConnectionMode.Gateway, @@ -432,13 +425,6 @@ public void ValidateTriggerCrud_SessionDirectTcp() new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Tcp }); } - [TestMethod] - public void ValidateTriggerCrud_SessionDirectHttps() - { - this.ValidateTriggerCrud(ConsistencyLevel.Session, - new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Https }); - } - internal void ValidateTriggerCrud(ConsistencyLevel consistencyLevel, ConnectionPolicy connectionPolicy) { DocumentClient client = TestCommon.CreateClient(connectionPolicy.ConnectionMode == ConnectionMode.Gateway, @@ -566,14 +552,6 @@ public void ValidateUserDefinedFunctionCrud_SessionDirectTcp() new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Tcp }); } - [TestMethod] - - public void ValidateUserDefinedFunctionCrud_SessionDirectHttps() - { - this.ValidateUserDefinedFunctionCrud(ConsistencyLevel.Session, - new ConnectionPolicy { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Protocol.Https }); - } - [TestMethod] public void ValidateUserDefinedFunctionTimeout() { @@ -1501,7 +1479,6 @@ public async Task ValidateSystemSproc() await this.ValidateSystemSprocInternal(true); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - ValidateSystemSprocInternal(false, Protocol.Https); ValidateSystemSprocInternal(false, Protocol.Tcp); #endif } @@ -2183,7 +2160,6 @@ public async Task ValidateReadOnlyStoredProcedureExecution() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await ValidateReadOnlyStoredProcedureExecutionInternal(false, Protocol.Tcp); - await ValidateReadOnlyStoredProcedureExecutionInternal(false, Protocol.Https); #endif } @@ -2559,7 +2535,6 @@ public async Task ValidateChangeFeedIfNoneMatch() await this.ValidateChangeFeedIfNoneMatchHelper(true); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - await ValidateChangeFeedIfNoneMatchHelper(false, Protocol.Https); await ValidateChangeFeedIfNoneMatchHelper(false, Protocol.Tcp); #endif } @@ -2709,7 +2684,6 @@ public async Task ValidateChangeFeedIfModifiedSince() await this.ValidateChangeFeedIfModifiedSinceHelper(true); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - await ValidateChangeFeedIfModifiedSinceHelper(false, Protocol.Https); await ValidateChangeFeedIfModifiedSinceHelper(false, Protocol.Tcp); #endif } @@ -2822,7 +2796,6 @@ private async Task ValidateChangeFeedIfModifiedSinceHelper(bool useGateway, Prot public async Task ValidateChangeFeedWithPartitionKey() { await this.ValidateChangeFeedWithPartitionKeyHelper(true); - await this.ValidateChangeFeedWithPartitionKeyHelper(false, Protocol.Https); await this.ValidateChangeFeedWithPartitionKeyHelper(false, Protocol.Tcp); } @@ -2999,7 +2972,6 @@ public async Task ValidateReadPartitionKeyRange() await this.ValidateReadPartitionKeyRangeHelper(true); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - await ValidateReadPartitionKeyRangeHelper(false, Protocol.Https); await ValidateReadPartitionKeyRangeHelper(false, Protocol.Tcp); #endif } @@ -3109,13 +3081,6 @@ public void ValidateGenericReadDocumentDirectTcp() this.ValidateGenericReadDocumentFromResource(false, Protocol.Tcp).Wait(); } - [TestMethod] - public void ValidateGenericReadDocumentDirectHttps() - { - this.ValidateGenericReadDocument(false, Protocol.Https).Wait(); - this.ValidateGenericReadDocumentFromResource(false, Protocol.Tcp).Wait(); - } - private async Task ValidateGenericReadDocument(bool useGateway, Protocol protocol) { CosmosClient client = TestCommon.CreateCosmosClient(useGateway); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs index d8cf36f5de..be83b0e1fd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs @@ -57,14 +57,6 @@ public void TestCleanup() HttpConstants.Versions.CurrentVersionUTF8 = this.currentVersionUTF8; } - [TestMethod] - public void ValidatePageSizeHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidatePageSize(client); - ValidatePageSize(client); - } - [TestMethod] public void ValidatePageSizeRntbd() { @@ -182,13 +174,6 @@ public async Task ValidateConsistencyLevelRntbd() await ValidateCosistencyLevel(client); } - [TestMethod] - public async Task ValidateConsistencyLevelHttps() - { - DocumentClient client = TestCommon.CreateClient(false, Protocol.Https); - await ValidateCosistencyLevel(client); - } - private async Task ValidateCosistencyLevel(DocumentClient client) { DocumentCollection collection = TestCommon.CreateOrGetDocumentCollection(client); @@ -232,13 +217,6 @@ public void ValidateJsonSerializationFormatRntbd() ValidateJsonSerializationFormat(client); } - [TestMethod] - public void ValidateJsonSerializationFormatHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidateJsonSerializationFormat(client); - } - private void ValidateJsonSerializationFormat(DocumentClient client) { DocumentCollection collection = TestCommon.CreateOrGetDocumentCollection(client); @@ -342,14 +320,6 @@ public void ValidateIndexingDirectiveRntbd() ValidateIndexingDirective(client); } - [TestMethod] - public void ValidateIndexingDirectiveHttps() - { - //var client = TestCommon.CreateClient(false, Protocol.Https); - var client = TestCommon.CreateClient(true, Protocol.Https); - ValidateIndexingDirective(client); - } - private void ValidateIndexingDirective(DocumentClient client) { // Number out of range. @@ -407,13 +377,6 @@ public void ValidateEnableScanInQueryRntbd() ValidateEnableScanInQuery(client); } - [TestMethod] - public void ValidateEnableScanInQueryHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidateEnableScanInQuery(client); - } - private void ValidateEnableScanInQuery(DocumentClient client, bool isHttps = false) { // Value not boolean @@ -460,14 +423,6 @@ public void ValidateEnableLowPrecisionOrderByRntbd() ValidateEnableLowPrecisionOrderBy(client); } - [TestMethod] - - public void ValidateEnableLowPrecisionOrderByHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidateEnableLowPrecisionOrderBy(client, true); - } - private void ValidateEnableLowPrecisionOrderBy(DocumentClient client, bool isHttps = false) { // Value not boolean @@ -516,13 +471,6 @@ public void ValidateEmitVerboseTracesInQueryRntbd() ValidateEmitVerboseTracesInQuery(client); } - [TestMethod] - public void ValidateEmitVerboseTracesInQueryHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidateEmitVerboseTracesInQuery(client, true); - } - private void ValidateEmitVerboseTracesInQuery(DocumentClient client, bool isHttps = false) { // Value not boolean @@ -562,12 +510,6 @@ public void ValidateIfNonMatchGateway() ValidateIfNonMatch(client); } - [TestMethod] - public void ValidateIfNonMatchHttps() - { - var client = TestCommon.CreateClient(false, Protocol.Https); - ValidateIfNonMatch(client); - } [TestMethod] public void ValidateIfNonMatchRntbd() @@ -719,11 +661,6 @@ public async Task ValidateCollectionIndexProgressHeaders() await ValidateCollectionIndexProgressHeadersAsync(client, isElasticCollection: true); } - using (var client = TestCommon.CreateClient(false, Protocol.Https)) - { - await ValidateCollectionIndexProgressHeadersAsync(client, isElasticCollection: true); - } - using (var client = TestCommon.CreateClient(false, Protocol.Tcp)) { await ValidateCollectionIndexProgressHeadersAsync(client, isElasticCollection: true); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs index c17c310fdb..6c29791783 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs @@ -40,15 +40,6 @@ public async Task NameRoutingSmokeGatewayTest() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - [TestMethod] - public void NameRoutingSmokeDirectHttpsTest() - { - DocumentClient client; - client = TestCommon.CreateClient(false, Protocol.Https, 10, ConsistencyLevel.Session); - - this.NameRoutingSmokeTestPrivateAsync(client).Wait(); - } - [TestMethod] public void NameRoutingSmokeDirectTcpTest() { @@ -436,8 +427,6 @@ public void ReplaceDocumentWithUri() this.ReplaceDocumentWithUriPrivateAsync(client).Wait(); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - this.ReplaceDocumentWithUriPrivateAsync(client).Wait(); client = TestCommon.CreateClient(false, Protocol.Tcp); this.ReplaceDocumentWithUriPrivateAsync(client).Wait(); @@ -501,10 +490,6 @@ public async Task CollectionDeleteAndCreateWithSameNameTest() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - await this.CollectionDeleteAndCreateWithSameNameTestPrivateAsync(client); - - client = TestCommon.CreateClient(false, Protocol.Tcp); await this.CollectionDeleteAndCreateWithSameNameTestPrivateAsync(client); #endif @@ -606,14 +591,6 @@ private async Task CollectionDeleteAndCreateWithSameNameTestPrivateAsync(Documen // 11. Now it succeed. #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - - [TestMethod] - public void VerifyGatewayNameIdCacheRefreshDirectHttp() - { - DocumentClient client = TestCommon.CreateClient(false, Protocol.Https); - this.VerifyGatewayNameIdCacheRefreshPrivateAsync(client).Wait(); - } - [TestMethod] public void VerifyGatewayNameIdCacheRefreshDirectTcp() { @@ -760,9 +737,6 @@ public void VerifyInvalidPartitionException() this.VerifyInvalidPartitionExceptionPrivateAsync(client).Wait(); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - this.VerifyInvalidPartitionExceptionPrivateAsync(client).Wait(); - client = TestCommon.CreateClient(false, Protocol.Tcp); this.VerifyInvalidPartitionExceptionPrivateAsync(client).Wait(); #endif @@ -797,9 +771,6 @@ public async Task VerifyInvalidPartitionExceptionWithPopulateQuotaInfo() await this.VerifyInvalidPartitionExceptionWithPopulateQuotaInfo(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - await this.VerifyInvalidPartitionExceptionWithPopulateQuotaInfo(client); - client = TestCommon.CreateClient(false, Protocol.Tcp); await this.VerifyInvalidPartitionExceptionWithPopulateQuotaInfo(client); #endif @@ -850,9 +821,6 @@ public void VerifyNameIdCacheTaskReuse() this.VerifyNameIdCacheTaskReusePrivateAsync(client).Wait(); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - this.VerifyNameIdCacheTaskReusePrivateAsync(client).Wait(); - client = TestCommon.CreateClient(false, Protocol.Tcp); this.VerifyNameIdCacheTaskReusePrivateAsync(client).Wait(); #endif @@ -903,10 +871,6 @@ public void CrazyNameTest() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - - client = TestCommon.CreateClient(false, Protocol.Https); - this.CrazyNameTestPrivateAsync(client, false).Wait(); - client = TestCommon.CreateClient(false, Protocol.Tcp); this.CrazyNameTestPrivateAsync(client, false, true).Wait(); #endif @@ -1019,9 +983,6 @@ public void NameRoutingBadUrlTest() this.NameRoutingBadUrlTestPrivateAsync(client, false).Wait(); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - this.NameRoutingBadUrlTestPrivateAsync(client, false).Wait(); - client = TestCommon.CreateClient(false, Protocol.Tcp); this.NameRoutingBadUrlTestPrivateAsync(client, false, true).Wait(); #endif @@ -1106,8 +1067,6 @@ public void VerifyInvalidNameTest() this.VerifyInvalidNameTestPrivateAsync(client).Wait(); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - this.VerifyInvalidNameTestPrivateAsync(client).Wait(); client = TestCommon.CreateClient(false, Protocol.Tcp); this.VerifyInvalidNameTestPrivateAsync(client).Wait(); @@ -1249,14 +1208,6 @@ public void NameParsingTest() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - [TestMethod] - [TestCategory("Ignore")] - public void VerifyMasterNodeThrottlingDirectHttp() - { - DocumentClient client = TestCommon.CreateClient(false, Protocol.Https); - this.VerifyMasterNodeThrottlingPrivateAsync(client).Wait(); - } - [TestMethod] public void VerifyMasterNodeThrottlingDirectTcp() { @@ -1271,9 +1222,6 @@ public async Task VerifyNameBasedCollectionCRUDOperations() await this.VerifyNameBasedCollectionCRUDOperationsAsync(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - client = TestCommon.CreateClient(false, Protocol.Https); - await this.VerifyNameBasedCollectionCRUDOperationsAsync(client); - client = TestCommon.CreateClient(false, Protocol.Tcp); await this.VerifyNameBasedCollectionCRUDOperationsAsync(client); #endif @@ -1291,7 +1239,6 @@ public async Task TestPartitionKeyDefinitionOnCollectionRecreate() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestPartitionKeyDefinitionOnCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1328,7 +1275,6 @@ public async Task TestPartitionKeyDefinitionOnContainerRecreateFromDifferentPart #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnContainerRecreateFromDifferentPartitionKeyPath(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestPartitionKeyDefinitionOnContainerRecreateFromDifferentPartitionKeyPath(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1426,7 +1372,6 @@ public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartition #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1484,7 +1429,6 @@ public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartition #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1537,7 +1481,6 @@ public async Task TestCollectionRecreateFromMultipartitionToSinglePartitionedFor { await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(TestCommon.CreateClient(true)); await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Https)); } internal async Task TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(DocumentClient client) @@ -1584,7 +1527,6 @@ public async Task TestRouteToNonExistentRangeAfterCollectionRecreate() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestRouteToNonExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestRouteToNonExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1657,7 +1599,6 @@ public async Task TestRouteToExistentRangeAfterCollectionRecreate() #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestRouteToExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestRouteToExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } @@ -1736,7 +1677,6 @@ public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedT #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Https)); #endif } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index ebf90f2fd1..6d6484e5a9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -777,12 +777,6 @@ public void TestQueryUnicodeDocumentHttpsGateway() this.TestQueryUnicodeDocument(useGateway: true, protocol: Protocol.Https); } - [TestMethod] - public void TestQueryUnicodeDocumentHttpsDirect() - { - this.TestQueryUnicodeDocument(useGateway: false, protocol: Protocol.Https); - } - private void TestQueryUnicodeDocument(bool useGateway, Protocol protocol) { try diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs index a222e232f9..6aa1b2ca16 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs @@ -67,13 +67,6 @@ public async Task DocumentInsertsTest_GatewayHttps() await this.DocumentInsertsTest(); } - [TestMethod] - public async Task DocumentInsertsTest_DirectHttps() - { - this.client = this.GetDocumentClient(ConnectionMode.Direct, Documents.Client.Protocol.Https); - await this.DocumentInsertsTest(); - } - [TestMethod] public async Task DocumentInsertsTest_DirectTcp() { @@ -107,13 +100,6 @@ public async Task QueryWithPaginationTest_GatewayHttps() await this.QueryWithPagination(); } - [TestMethod] - public async Task QueryWithPaginationTest_DirectHttps() - { - this.client = this.GetDocumentClient(ConnectionMode.Direct, Documents.Client.Protocol.Https); - await this.QueryWithPagination(); - } - [TestMethod] public async Task QueryWithPaginationTest_DirectTcp() { @@ -173,13 +159,6 @@ public async Task CrossPartitionQueries_GatewayHttps() await this.CrossPartitionQueries(); } - [TestMethod] - public async Task CrossPartitionQueries_DirectHttps() - { - this.client = this.GetDocumentClient(ConnectionMode.Direct, Documents.Client.Protocol.Https); - await this.CrossPartitionQueries(); - } - [TestMethod] public async Task CrossPartitionQueries_DirectTcp() { @@ -220,13 +199,6 @@ public async Task CreateDatabaseIfNotExists_GatewayHttps() await this.CreateDatabaseIfNotExists(this.client); } - [TestMethod] - public async Task CreateDatabaseIfNotExists_DirectHttps() - { - this.client = this.GetDocumentClient(ConnectionMode.Direct, Documents.Client.Protocol.Https); - await this.CreateDatabaseIfNotExists(this.client); - } - [TestMethod] public async Task CreateDatabaseIfNotExists_DirectTcp() { @@ -266,13 +238,6 @@ public async Task CreateDocumentCollectionIfNotExists_GatewayHttps() await this.CreateDocumentCollectionIfNotExists(); } - [TestMethod] - public async Task CreateDocumentCollectionIfNotExists_DirectHttps() - { - this.client = this.GetDocumentClient(ConnectionMode.Direct, Documents.Client.Protocol.Https); - await this.CreateDocumentCollectionIfNotExists(); - } - [TestMethod] public async Task CreateDocumentCollectionIfNotExists_DirectTcp() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index bdb688673d..8c71a6b168 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -112,8 +112,7 @@ internal static void TestForEachClient( new Dictionary { {DocumentClientType.Gateway, TestCommon.CreateClient(true, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)}, - {DocumentClientType.DirectTcp, TestCommon.CreateClient(false, Protocol.Tcp, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)}, - {DocumentClientType.DirectHttps, TestCommon.CreateClient(false, Protocol.Https, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)} + {DocumentClientType.DirectTcp, TestCommon.CreateClient(false, Protocol.Tcp, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)} }; foreach (KeyValuePair clientEntry in clients) @@ -149,8 +148,7 @@ internal static void TestForAnyClient( new Dictionary { {DocumentClientType.Gateway, TestCommon.CreateClient(true, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)}, - {DocumentClientType.DirectTcp, TestCommon.CreateClient(false, Protocol.Tcp, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)}, - {DocumentClientType.DirectHttps, TestCommon.CreateClient(false, Protocol.Https, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)} + {DocumentClientType.DirectTcp, TestCommon.CreateClient(false, Protocol.Tcp, tokenType: authTokenType, defaultConsistencyLevel: consistencyLevel)} }; int seed = (int)DateTime.Now.Ticks; diff --git a/templates/emulator-setup.yml b/templates/emulator-setup.yml index 10b5664d82..56ba69b98b 100644 --- a/templates/emulator-setup.yml +++ b/templates/emulator-setup.yml @@ -11,6 +11,7 @@ steps: mkdir "$env:temp\Azure Cosmos DB Emulator" lessmsi x "$env:temp\azure-cosmosdb-emulator.msi" "$env:temp\Azure Cosmos DB Emulator\" Write-Host "Starting Comsos DB Emulator" -ForegroundColor green + Add-MpPreference -ExclusionPath "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator" Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint" -Verb RunAs Import-Module "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" Get-Item env:* | Sort-Object -Property Name From 393ae2396c2ef7f34dae6ebf221339780c800c8c Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 2 Feb 2023 06:16:37 +0530 Subject: [PATCH 050/337] [Internal] Benchmark : Fixes issue with dependency on Cosmos Project (#3673) * users/sourabhjain/benchmarkfix * update pipeline * Revert "users/sourabhjain/benchmarkfix" This reverts commit 81b48f0e47aed7a75540c2c83f62cea98d86824f. * fix compilation error * add parama for preview pkg also --------- Co-authored-by: Matias Quaranta --- .../Tools/Benchmark/BenchmarkConfig.cs | 2 +- templates/build-benchmark.yml | 2 +- templates/build-preview.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index b9235d2232..6f89776370 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -224,7 +224,7 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe clientOptions.ConsistencyLevel = (Microsoft.Azure.Cosmos.ConsistencyLevel)Enum.Parse(typeof(Microsoft.Azure.Cosmos.ConsistencyLevel), this.ConsistencyLevel, ignoreCase: true); } - clientOptions.EnableDistributedTracing = this.EnableDistributedTracing; + clientOptions.IsDistributedTracingEnabled = this.EnableDistributedTracing; return new Microsoft.Azure.Cosmos.CosmosClient( this.EndPoint, diff --git a/templates/build-benchmark.yml b/templates/build-benchmark.yml index a072c5cb81..7e73842ee1 100644 --- a/templates/build-benchmark.yml +++ b/templates/build-benchmark.yml @@ -30,5 +30,5 @@ jobs: configuration: $(parameters.BuildConfiguration) nugetConfigPath: NuGet.config projects: 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.sln' - arguments: -p:Optimize=true + arguments: -p:Optimize=true -p:OSSProjectRef=true versioningScheme: OFF \ No newline at end of file diff --git a/templates/build-preview.yml b/templates/build-preview.yml index 05387989c6..e9919878ff 100644 --- a/templates/build-preview.yml +++ b/templates/build-preview.yml @@ -167,5 +167,5 @@ jobs: configuration: $(parameters.BuildConfiguration) nugetConfigPath: NuGet.config projects: 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.sln' - arguments: -p:Optimize=true -p:IsPreview=true + arguments: -p:Optimize=true -p:IsPreview=true -p:OSSProjectRef=true versioningScheme: OFF \ No newline at end of file From 122bc561e606c52168614694b824520cd6530013 Mon Sep 17 00:00:00 2001 From: pravengithub <124255233+pravengithub@users.noreply.github.com> Date: Fri, 3 Feb 2023 06:41:28 -0800 Subject: [PATCH 051/337] LocalQuorum: Adds Quorum reads on Consistent Prefix Accounts (#3680) Co-authored-by: DESKTOP-ED57J7H\Prashanth Venkataram --- .../src/CosmosClientOptions.cs | 2 +- .../src/Fluent/CosmosClientBuilder.cs | 2 +- .../src/ValidationHelpers.cs | 15 ++-- .../ValidationHelpersTests.cs | 72 +++++++++++++++++++ 4 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index fec7f4ac2f..c826bb90d1 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -600,7 +600,7 @@ public Func HttpClientFactory internal bool EnablePartitionLevelFailover { get; set; } = false; /// - /// Quorum Read allowed with eventual consistency account + /// Quorum Read allowed with eventual consistency account or consistent prefix account. /// internal bool EnableUpgradeConsistencyToLocalQuorum { get; set; } = false; diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 44c38ec51b..692d5b498a 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -698,7 +698,7 @@ internal CosmosClientBuilder WithPartitionLevelFailoverEnabled() } /// - /// To enable LocalQuorum Consistency, i.e. Allow Quorum read with Eventual Consistency Account + /// To enable LocalQuorum Consistency, i.e. Allows Quorum read with Eventual Consistency Account or with Consistent Prefix Account. /// Use By Compute Only /// internal CosmosClientBuilder AllowUpgradeConsistencyToLocalQuorum() diff --git a/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs b/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs index 14256919c6..58a7a55ddb 100644 --- a/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs +++ b/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs @@ -10,12 +10,12 @@ namespace Microsoft.Azure.Cosmos internal static class ValidationHelpers { /// - /// If isLocalQuorumConsistency flag is true, it allows only "Quorum Read with Eventual Consistency Account". + /// If isLocalQuorumConsistency flag is true, it allows only "Quorum Read with either an Eventual Consistency Account or a Consistent Prefix Account". /// It goes through a validation where it doesn't allow strong consistency over weaker consistency. /// /// Account Level Consistency /// Request/Client Level Consistency - /// Allows Quorum Read with Eventual Account + /// Allows Quorum Read with Eventual or Consistent Prefix Account /// /// /// true/false @@ -36,12 +36,12 @@ public static bool IsValidConsistencyLevelOverwrite( } /// - /// If isLocalQuorumConsistency flag is true, it allows only "Quorum Read with Eventual Consistency Account". + /// If isLocalQuorumConsistency flag is true, it allows only "Quorum Read with either an Eventual Consistency Account or a Consistent Prefix Account". /// It goes through a validation where it doesn't allow strong consistency over weaker consistency. /// /// Account Level Consistency /// Request/Client Level Consistency - /// Allows Quorum Read with Eventual Account + /// Allows Quorum Read with Eventual or Consistent Prefix Account /// /// /// true/false @@ -107,7 +107,7 @@ private static bool IsValidConsistencyLevelOverwrite( } /// - /// Condition to check Quorum(i.e. Strong) read with eventual account + /// Condition to check Quorum(i.e. Strong) read with either an eventual consistency account or a consistent prefix account. /// /// /// @@ -119,7 +119,7 @@ private static bool IsLocalQuorumConsistency(Documents.ConsistencyLevel backendC OperationType? operationType, ResourceType? resourceType) { - if (backendConsistency != Documents.ConsistencyLevel.Eventual) + if (backendConsistency != Documents.ConsistencyLevel.Eventual && backendConsistency != Documents.ConsistencyLevel.ConsistentPrefix) { return false; } @@ -136,7 +136,8 @@ private static bool IsLocalQuorumConsistency(Documents.ConsistencyLevel backendC } if (!operationType.HasValue || - (operationType.HasValue && !(operationType == OperationType.Read || operationType == OperationType.ReadFeed))) + (operationType.HasValue && + !(operationType == OperationType.Read || operationType == OperationType.ReadFeed || operationType == OperationType.SqlQuery || operationType == OperationType.Query))) { return false; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs new file mode 100644 index 0000000000..2c9db33cec --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests +{ + using System.Data; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ValidationHelpersTest + { + [TestMethod] + [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)] + [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)] + [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)] + [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.BoundedStaleness)] + [DataRow(false, ConsistencyLevel.Session, ConsistencyLevel.Strong)] + [DataRow(false, ConsistencyLevel.BoundedStaleness, ConsistencyLevel.Strong)] + public void TestIsValidConsistencyLevelOverwrite(bool isValidConsistencyLevelOverwrite, + ConsistencyLevel backendConsistencyLevel, + ConsistencyLevel desiredConsistencyLevel) + { + bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, + desiredConsistencyLevel, + true, + Documents.OperationType.Read, + Documents.ResourceType.Document); + + Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + } + + [TestMethod] + [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)] + [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)] + public void TestIsValidConsistencyLevelOverwrite_OnlyWhenSpecifyingExplicitOverwrite(bool isValidConsistencyLevelOverwrite, + ConsistencyLevel backendConsistencyLevel, + ConsistencyLevel desiredConsistencyLevel) + { + bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, + desiredConsistencyLevel, + false, + Documents.OperationType.Read, + Documents.ResourceType.Document); + + Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + } + + [TestMethod] + [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.Read)] + [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.ReadFeed)] + [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Query)] + [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.SqlQuery)] + [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.QueryPlan)] + [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Create)] + [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Batch)] + public void TestIsValidConsistencyLevelOverwrite_OnlyAllowedForCertainOperationTypes( + bool isValidConsistencyLevelOverwrite, + ConsistencyLevel backendConsistencyLevel, + ConsistencyLevel desiredConsistencyLevel, + dynamic operationType) + { + bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, + desiredConsistencyLevel, + true, + (Documents.OperationType) operationType, + Documents.ResourceType.Document); + + Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + } + } +} \ No newline at end of file From 8a537ce93a8ee3074e3eb35a5339675a6b93a90c Mon Sep 17 00:00:00 2001 From: aavasthy <113193425+aavasthy@users.noreply.github.com> Date: Mon, 6 Feb 2023 10:39:11 -0800 Subject: [PATCH 052/337] 3.32.0: Adds new SDK version and contract files (#3687) * 3.32.0: Adds new SDK version and contract files * 3.32.0: Adds new SDK version and contract files * Updating changelog version * Updating changelog version * Added more commits to changelog and updated release contract * Added documentation tags PR in changelog * Updated changelog based on reviews * Updated PR decsription in changelog * Update changelog.md Updated full fidelity change description Co-authored-by: Matias Quaranta --------- Co-authored-by: Matias Quaranta --- Directory.Build.props | 4 +- .../contracts/API_3.32.0-preview.txt | 1531 +++++++++++++++++ .../contracts/API_3.32.0.txt | 1478 ++++++++++++++++ changelog.md | 34 + 4 files changed, 3045 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 2891c05569..887ca2d334 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.31.2 - 3.31.2 + 3.32.0 + 3.32.0 preview 3.30.1 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.0-preview.txt new file mode 100644 index 0000000000..69b7a4b83e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.0-preview.txt @@ -0,0 +1,1531 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.0.txt new file mode 100644 index 0000000000..5218206b0e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.0.txt @@ -0,0 +1,1478 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index add5a1de66..aa2aaad67d 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,40 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.32.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.0) - 2023-02-03 +#### Fixed +- [#3466](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3466) ClientRetryPolicy: Fixes behavior to Meta-data write operations in multimaster accounts +- [#3498](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3498) PartitionKey: Fixes NullRef in toString handling for None for PartitionKey.ToString() +- [#3385](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3385) Query: Fixes LINQ ToString got absorbed during translation +- [#3406](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3406) Query: Fixes LINQ to use custom serializer to serialize constant values in Query +- [#3496](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3496) Documentation: Adds XML comment to Database.ReadThroughputAsync definition +- [#3508](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3508), [#3640](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3640) CosmosClient Initialization: Refactors implementation for opening Rntbd connections to backend replica nodes in Direct mode +- [#3519](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3519) Diagnostics: Removes unused properties and reduces size +- [#3495](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3495) Query: Fixes partition range evaluation for spatial queries +- [#3399](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3399) Query: Fixes default to BadRequestException in case of internal errors in ServiceInterop +- [#3574](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3574) Query: Fixes incorrect FeedResponse.Count when result contains undefined elements +- [#3577](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3577) Trace: Fixes Tracing/diagnostics hour-times to 24Hours +- [#3632](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3632) Query: Fixes handling of CosmosUndefined, CosmosGuid and CosmosBinary in unordered DISTINCT +- [#3640](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3640) Token expiration: Fixes token expired errors happening on some environments +- [#3645](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3645) Change Feed Processor: Fixes behavior with StartTime on Local +- [#3643](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3643) Documentation: Fixed CosmosClientBuilder.WithConnectionModeGateway documentation +- [#3579](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3579) Documentation: Fixes EUAP in Comments + +#### Added +- [#3566](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3566) Change Feed Processor: Adds support for Resource Tokens +- [#3555](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3555) Availability: Adds HTTP timeouts with request-level cross-region retry +- [#3509](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3509) Query: Adds ALL Scalar Expression +- [#3656](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3656) Region Availability: Adds Poland Central Region For Public Usage. +- [#3636](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3636) CosmosClientOptions: Adds ServerCertificateCustomValidationCallback for Http and TCP + +### [3.32.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.0-preview) - 2023-02-03 + +#### Added +- [#3596](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3596) Full Fidelity Change Feed: Adds new LatestVersion to ChangeFeedMode. `FullFidelity` is now renamed to `AllVersionsAndDeletes`. +- [#3598](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3598) AI integration: Adds Distributed Tracing support. Enabled by default, which can be disabled through + `CosmosClientOptions.IsDistributedTracingEnabled` + + ### [3.31.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.2) - 2022-11-03 ### [3.31.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.31.2-preview) - 2022-11-03 From bf9a6d499579fc9f9e46804ae99f13eb00fc3eba Mon Sep 17 00:00:00 2001 From: Justine Cocchi Date: Thu, 9 Feb 2023 08:40:18 -0800 Subject: [PATCH 053/337] [Internal] Samples: Adds change feed pull model samples (#3646) * add change feed pull samples * refactor appsettings validation * addressing pr comments * move task delay * update sample to use latest change feed mode names --------- Co-authored-by: Matias Quaranta --- ...FPullModelAllVersionsAndDeletesMode.csproj | 21 ++ .../Program.cs | 225 ++++++++++++++++++ .../CFPullModelLatestVersionMode.csproj | 21 ++ .../CFPullModelLatestVersionMode/Program.cs | 155 ++++++++++++ .../Usage/Cosmos.Samples.Usage.sln | 16 +- 5 files changed, 436 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/CFPullModelAllVersionsAndDeletesMode.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/Program.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/CFPullModelLatestVersionMode.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/Program.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/CFPullModelAllVersionsAndDeletesMode.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/CFPullModelAllVersionsAndDeletesMode.csproj new file mode 100644 index 0000000000..4cea61605d --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/CFPullModelAllVersionsAndDeletesMode.csproj @@ -0,0 +1,21 @@ + + + + Exe + net6.0 + Cosmos.Samples.CFPullModelAllVersionsAndDeletesMode + Cosmos.Samples.CFPullModelAllVersionsAndDeletesMode + latest + + + + + + + + + + PreserveNewest + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/Program.cs new file mode 100644 index 0000000000..69d28cbfae --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelAllVersionsAndDeletesMode/Program.cs @@ -0,0 +1,225 @@ +namespace CFPullModelAllVersionsAndDeletesMode +{ + using System; + using System.Net; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Configuration; + using Newtonsoft.Json; + + class Program + { + private static readonly string databaseName = "db"; + private static readonly string containerName = "container"; + + static async Task Main() + { + try + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddJsonFile("appSettings.json") + .Build(); + + string endpoint = configuration["EndPointUrl"]; + if (string.IsNullOrEmpty(endpoint)) + { + throw new ArgumentNullException("Please specify a valid EndPointUrl in the appSettings.json"); + } + + string authKey = configuration["AuthorizationKey"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) + { + throw new ArgumentException("Please specify a valid AuthorizationKey in the appSettings.json"); + } + + using (CosmosClient client = new CosmosClient(endpoint, authKey)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + string allVersionsContinuationToken = await CreateAllVersionsAndDeletesChangeFeedIterator(container); + + await IngestData(container); + await DeleteData(container); + + await ReadAllVersionsAndDeletesChangeFeed(container, allVersionsContinuationToken); + } + } + finally + { + Console.WriteLine("End of demo."); + } + } + + static async Task CreateAllVersionsAndDeletesChangeFeedIterator(Container container) + { + Console.WriteLine("Creating ChangeFeedIterator to read the change feed in All Versions and Deletes mode."); + + // + using (FeedIterator allVersionsIterator = container + .GetChangeFeedIterator(ChangeFeedStartFrom.Now(), ChangeFeedMode.AllVersionsAndDeletes)) + { + while (allVersionsIterator.HasMoreResults) + { + FeedResponse response = await allVersionsIterator.ReadNextAsync(); + + if (response.StatusCode == HttpStatusCode.NotModified) + { + return response.ContinuationToken; + } + } + } + // + + return null; + } + + static async Task IngestData(Container container) + { + Console.Clear(); + + Console.WriteLine("Press any key to begin ingesting data."); + Console.ReadKey(true); + + Console.WriteLine("Press any key to stop."); + + while (!Console.KeyAvailable) + { + Item item = GenerateItem(); + await container.UpsertItemAsync(item, new PartitionKey(item.Id)); + Console.Write("*"); + } + } + + static async Task DeleteData(Container container) + { + Console.ReadKey(true); + Console.Clear(); + + Console.WriteLine("Press any key to begin deleting data."); + Console.ReadKey(true); + + Console.WriteLine("Press any key to stop"); + + int deleteItemCounter = 0; + while (!Console.KeyAvailable) + { + deleteItemCounter++; + try + { + await container.DeleteItemAsync( + partitionKey: new PartitionKey(deleteItemCounter.ToString()), + id: deleteItemCounter.ToString()); + Console.Write("-"); + } + catch (CosmosException cosmosException) when (cosmosException.StatusCode == HttpStatusCode.NotFound) + { + // Deleting by a random id that might not exist in the container will likely throw errors that are safe to ignore for this purpose + } + } + } + + static async Task ReadAllVersionsAndDeletesChangeFeed(Container container, string allVersionsContinuationToken) + { + Console.ReadKey(true); + Console.Clear(); + + Console.WriteLine("Press any key to start reading the change feed in All Versions and Deletes mode."); + Console.ReadKey(true); + + Console.WriteLine("Press any key to stop."); + + // + using (FeedIterator allVersionsIterator = container.GetChangeFeedIterator(ChangeFeedStartFrom.ContinuationToken(allVersionsContinuationToken), ChangeFeedMode.AllVersionsAndDeletes, new ChangeFeedRequestOptions { PageSizeHint = 10 })) + { + while (allVersionsIterator.HasMoreResults) + { + FeedResponse response = await allVersionsIterator.ReadNextAsync(); + + if (response.StatusCode == HttpStatusCode.NotModified) + { + Console.WriteLine($"No new changes"); + await Task.Delay(1000); + } + else + { + foreach (AllVersionsAndDeletesCFResponse r in response) + { + // if operaiton is delete + if (r.Metadata.OperationType == "delete") + { + Item item = r.Previous; + + if (r.Metadata.TimeToLiveExpired == true) + { + Console.WriteLine($"Operation: {r.Metadata.OperationType} (due to TTL). Item id: {item.Id}. Previous value: {item.Value}"); + } + else + { + Console.WriteLine($"Operation: {r.Metadata.OperationType} (not due to TTL). Item id: {item.Id}. Previous value: {item.Value}"); + } + } + // if operation is create or replace + else + { + Item item = r.Current; + + Console.WriteLine($"Operation: {r.Metadata.OperationType}. Item id: {item.Id}. Current value: {item.Value}"); + } + } + } + + if (Console.KeyAvailable) + { + break; + } + } + } + // + } + + private static Item GenerateItem() + { + Random random = new Random(); + + return new Item + { + Id = random.Next(1, 999).ToString(), + Value = random.Next(1, 100000), + }; + } + } + + internal class AllVersionsAndDeletesCFResponse + { + [JsonProperty("current")] + public Item Current { get; set; } + + [JsonProperty("previous")] + public Item Previous { get; set; } + + [JsonProperty("metadata")] + public Metadata Metadata { get; set; } + } + + internal class Item + { + [JsonProperty("id")] + public string Id { get; set; } + + public double Value { get; set; } + } + + internal class Metadata + { + [JsonProperty("operationType")] + public string OperationType { get; set; } + + [JsonProperty("timeToLiveExpired")] + public Boolean TimeToLiveExpired { get; set; } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/CFPullModelLatestVersionMode.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/CFPullModelLatestVersionMode.csproj new file mode 100644 index 0000000000..66a155278d --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/CFPullModelLatestVersionMode.csproj @@ -0,0 +1,21 @@ + + + + Exe + net6.0 + Cosmos.Samples.CFPullModelLatestVersionMode + Cosmos.Samples.CFPullModelLatestVersionMode + latest + + + + + + + + + + PreserveNewest + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/Program.cs new file mode 100644 index 0000000000..f87a0e1eff --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CFPullModelLatestVersionMode/Program.cs @@ -0,0 +1,155 @@ +namespace CFPullModelLatestVersionMode +{ + using System; + using System.Collections.Generic; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Configuration; + using Newtonsoft.Json; + + class Program + { + private static readonly string databaseName = "db"; + private static readonly string containerName = "container"; + + static async Task Main() + { + try + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddJsonFile("appSettings.json") + .Build(); + + string endpoint = configuration["EndPointUrl"]; + if (string.IsNullOrEmpty(endpoint)) + { + throw new ArgumentNullException("Please specify a valid EndPointUrl in the appSettings.json"); + } + + string authKey = configuration["AuthorizationKey"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) + { + throw new ArgumentException("Please specify a valid AuthorizationKey in the appSettings.json"); + } + + using (CosmosClient client = new CosmosClient(endpoint, authKey)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + string latestVersionContinuationToken = await CreateLatestVersionChangeFeedIterator(container); + + await IngestData(container); + await ReadLatestVersionChangeFeed(container, latestVersionContinuationToken); + } + } + finally + { + Console.WriteLine("End of demo."); + } + } + + static async Task CreateLatestVersionChangeFeedIterator(Container container) + { + Console.WriteLine("Creating ChangeFeedIterator to read the change feed in Latest Version mode."); + + // + using (FeedIterator latestVersionIterator = container.GetChangeFeedIterator(ChangeFeedStartFrom.Now(), ChangeFeedMode.LatestVersion)) + { + while (latestVersionIterator.HasMoreResults) + { + FeedResponse response = await latestVersionIterator.ReadNextAsync(); + + if (response.StatusCode == HttpStatusCode.NotModified) + { + return response.ContinuationToken; + } + } + } + // + + return null; + } + + static async Task ReadLatestVersionChangeFeed(Container container, string latestVersionContinuationToken) + { + Console.ReadKey(true); + Console.Clear(); + + Console.WriteLine("Press any key to begin reading the change feed in Latest Version mode."); + Console.ReadKey(true); + + Console.WriteLine("Press any key to stop."); + + // + using (FeedIterator latestVersionIterator = container.GetChangeFeedIterator(ChangeFeedStartFrom.ContinuationToken(latestVersionContinuationToken), ChangeFeedMode.LatestVersion, new ChangeFeedRequestOptions { PageSizeHint = 10 })) + { + while (latestVersionIterator.HasMoreResults) + { + FeedResponse response = await latestVersionIterator.ReadNextAsync(); + + if (response.StatusCode == HttpStatusCode.NotModified) + { + Console.WriteLine($"No new changes"); + await Task.Delay(1000); + } + else + { + foreach (Item item in response) + { + Console.WriteLine($"Change in item: {item.Id}. New value: {item.Value}."); + } + } + + if (Console.KeyAvailable) + { + break; + } + } + } + // + } + + static async Task IngestData(Container container) + { + Console.Clear(); + + Console.WriteLine("Press any key to begin ingesting data."); + Console.ReadKey(true); + + Console.WriteLine("Press any key to stop."); + + while (!Console.KeyAvailable) + { + Item item = GenerateItem(); + await container.UpsertItemAsync(item, new PartitionKey(item.Id)); + Console.Write("*"); + } + } + + private static Item GenerateItem() + { + Random random = new Random(); + + return new Item + { + Id = random.Next(1, 999).ToString(), + Value = random.Next(1, 100000), + }; + } + } + + internal class Item + { + [JsonProperty("id")] + public string Id { get; set; } + + public double Value { get; set; } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln index 954c0c606a..de1e1f4731 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29411.108 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33205.214 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DatabaseManagement", "DatabaseManagement\DatabaseManagement.csproj", "{F972386A-B03D-4453-88C7-948CB107C029}" EndProject @@ -47,6 +47,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SystemTextJson", "SystemTex EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReEncryption", "ReEncryption\ReEncryption.csproj", "{AD6DEC94-EF8E-4C42-8A99-B98E101F933D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFPullModelAllVersionsAndDeletesMode", "CFPullModelAllVersionsAndDeletesMode\CFPullModelAllVersionsAndDeletesMode.csproj", "{7D808579-73BD-4D60-A7A5-D88FFF568C37}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFPullModelLatestVersionMode", "CFPullModelLatestVersionMode\CFPullModelLatestVersionMode.csproj", "{985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,6 +145,14 @@ Global {AD6DEC94-EF8E-4C42-8A99-B98E101F933D}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD6DEC94-EF8E-4C42-8A99-B98E101F933D}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD6DEC94-EF8E-4C42-8A99-B98E101F933D}.Release|Any CPU.Build.0 = Release|Any CPU + {7D808579-73BD-4D60-A7A5-D88FFF568C37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7D808579-73BD-4D60-A7A5-D88FFF568C37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7D808579-73BD-4D60-A7A5-D88FFF568C37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7D808579-73BD-4D60-A7A5-D88FFF568C37}.Release|Any CPU.Build.0 = Release|Any CPU + {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 16caa1b9d40ab639085d932ec887474a8498aeb2 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 13 Feb 2023 09:44:12 -0800 Subject: [PATCH 054/337] [Internal] Tests: Refactors emulator CI (#3688) --- .../Batch/BatchSinglePartitionKeyTests.cs | 8 +- .../Batch/BatchTestBase.cs | 52 ++-- .../Batch/CosmosItemBulkTests.cs | 6 +- .../ChangeFeed/BaseChangeFeedClientHelper.cs | 2 +- .../ChangeFeed/DynamicStreamTests.cs | 2 +- .../ChangeFeed/DynamicTests.cs | 2 +- .../ChangeFeed/EstimatorTests.cs | 2 +- .../ChangeFeed/SmokeTests.cs | 2 +- .../ClientCreateAndInitializeTest.cs | 23 +- .../ClientTelemetryTests.cs | 6 +- .../ClientTests.cs | 91 +++--- .../CosmosAadTests.cs | 150 ++++----- .../CosmosBasicQueryTests.cs | 37 ++- .../CosmosContainerTests.cs | 90 +++--- .../CosmosContentResponseTests.cs | 24 +- .../CosmosDatabaseTests.cs | 64 ++-- .../CosmosItemIdEncodingTestsBase.cs | 6 +- .../CosmosItemSessionTokenTests.cs | 2 +- .../CosmosItemTests.cs | 23 +- .../CosmosMultiHashTest.cs | 8 +- .../CosmosNotFoundTests.cs | 3 +- .../CosmosPermissionTests.cs | 52 ++-- .../CosmosReadFeedTests.cs | 2 +- .../CosmosReadManyItemsTests.cs | 10 +- .../CosmosUserTests.cs | 44 +-- .../DocumentClientUnitTests.cs | 19 +- .../FeedToken/ChangeFeedIteratorCoreTests.cs | 12 +- .../FeedToken/QueryFeedTokenTests.cs | 2 +- .../Fluent/ContainerSettingsTests.cs | 4 +- .../GatewayClientSideRequestStatsTests.cs | 1 - .../GatewayTests.cs | 218 ++++++------- .../HeadersValidationTests.cs | 49 ++- .../IndexMetricsParserBaselineTest.cs | 2 + .../InternalFriendsTest.cs | 8 +- .../LinqAggregateFunctionsBaselineTests.cs | 2 + .../LinqAttributeContractBaselineTests.cs | 6 +- .../LinqGeneralBaselineTests.cs | 2 + .../LinqSQLTranslationBaselineTests.cs | 2 + .../LinqTranslationBaselineTests.cs | 2 + ...TranslationWithCustomSerializerBaseline.cs | 2 + .../MultiRegionStrongTests.cs | 286 ------------------ .../NameRoutingTests.cs | 47 +-- .../OfferTests.cs | 8 +- .../PartitionKeyRangeCacheTests.cs | 18 +- .../Query/QueryTestsBase.cs | 20 +- .../QueryTests.cs | 10 + .../SmokeTests.cs | 7 + .../SpatialTest.cs | 12 +- .../StoredProcedureTests.cs | 9 +- .../SummaryDiagnosticsTests.cs | 1 + .../EndToEndTraceWriterBaselineTests.cs | 4 + .../TransportWrapperTests.cs | 9 +- .../TriggersTests.cs | 4 +- .../UniqueIndexTests.cs | 2 + .../UserDefinedFunctionsTests.cs | 4 +- .../Utils/BaseCosmosClientHelper.cs | 48 ++- templates/emulator-setup.yml | 66 ++-- 57 files changed, 689 insertions(+), 908 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/MultiRegionStrongTests.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs index d8cc17966d..675ed6b20e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs @@ -19,15 +19,15 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public class BatchSinglePartitionKeyTests : BatchTestBase { [ClassInitialize] - public static void ClassInitialize(TestContext context) + public static async Task ClassInitialize(TestContext context) { - BatchTestBase.ClassInit(context); + await BatchTestBase.ClassInitAsync(context); } [ClassCleanup] - public static void ClassCleanup() + public static async Task ClassCleanup() { - BatchTestBase.ClassClean(); + await BatchTestBase.ClassCleanAsync(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchTestBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchTestBase.cs index 89b00f8c57..929ed2cfa9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchTestBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchTestBase.cs @@ -63,41 +63,40 @@ public class BatchTestBase protected TestDoc TestDocPk1ExistingD { get; set; } protected TestDoc TestDocPk1ExistingE { get; set; } - public static void ClassInit(TestContext context) + public static async Task ClassInitAsync(TestContext context) { - InitializeDirectContainers(); + await InitializeDirectContainers(); InitializeGatewayContainers(); - InitializeSharedThroughputContainer(); + await InitializeSharedThroughputContainer(); } - private static void InitializeDirectContainers() + private static async Task InitializeDirectContainers() { - + BatchTestBase.Client = TestCommon.CreateCosmosClient(builder => builder.WithConsistencyLevel(Cosmos.ConsistencyLevel.Session)); - BatchTestBase.Database = BatchTestBase.Client.CreateDatabaseAsync(Guid.NewGuid().ToString()) - .GetAwaiter().GetResult().Database; + BatchTestBase.Database = await BatchTestBase.Client.CreateDatabaseAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition(); partitionKeyDefinition.Paths.Add("/Status"); - BatchTestBase.LowThroughputJsonContainer = BatchTestBase.Database.CreateContainerAsync( + BatchTestBase.LowThroughputJsonContainer = (await BatchTestBase.Database.CreateContainerAsync( new ContainerProperties() { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }, - throughput: 400).GetAwaiter().GetResult().Container; + throughput: 400)).Container; - BatchTestBase.PartitionKeyDefinition = ((ContainerInternal)(ContainerInlineCore)BatchTestBase.LowThroughputJsonContainer).GetPartitionKeyDefinitionAsync(CancellationToken.None).GetAwaiter().GetResult(); + BatchTestBase.PartitionKeyDefinition = await ((ContainerInternal)(ContainerInlineCore)BatchTestBase.LowThroughputJsonContainer).GetPartitionKeyDefinitionAsync(CancellationToken.None); // Create a container with at least 2 physical partitions for effective cross-partition testing - BatchTestBase.JsonContainer = BatchTestBase.Database.CreateContainerAsync( + BatchTestBase.JsonContainer = (await BatchTestBase.Database.CreateContainerAsync( new ContainerProperties() { Id = Guid.NewGuid().ToString(), PartitionKey = BatchTestBase.PartitionKeyDefinition }, - throughput: 12000).GetAwaiter().GetResult().Container; + throughput: 12000)).Container; Serialization.HybridRow.Schemas.Schema testSchema = TestDoc.GetSchema(); Namespace testNamespace = new Namespace() @@ -127,9 +126,9 @@ private static void InitializeDirectContainers() schematizedContainerProperties.SchemaPolicy = schemaPolicy; - BatchTestBase.SchematizedContainer = BatchTestBase.Database.CreateContainerAsync( + BatchTestBase.SchematizedContainer = (await BatchTestBase.Database.CreateContainerAsync( schematizedContainerProperties, - throughput: 12000).GetAwaiter().GetResult().Container; + throughput: 12000)).Container; } private static void InitializeGatewayContainers() @@ -142,20 +141,18 @@ private static void InitializeGatewayContainers() BatchTestBase.GatewaySchematizedContainer = BatchTestBase.GatewayDatabase.GetContainer(BatchTestBase.SchematizedContainer.Id); } - private static void InitializeSharedThroughputContainer() + private static async Task InitializeSharedThroughputContainer() { - CosmosClient client = TestCommon.CreateCosmosClient(); - Cosmos.Database db = client.CreateDatabaseAsync(string.Format("Shared_{0}", Guid.NewGuid().ToString("N")), throughput: 20000).GetAwaiter().GetResult().Database; + Cosmos.Database db = (await BatchTestBase.Client.CreateDatabaseAsync(string.Format("Shared_{0}", Guid.NewGuid().ToString("N")), throughput: 20000)).Database; for (int index = 0; index < 5; index++) { - ContainerResponse containerResponse = db.CreateContainerAsync( + ContainerResponse containerResponse = await db.CreateContainerAsync( new ContainerProperties { Id = Guid.NewGuid().ToString(), PartitionKey = BatchTestBase.PartitionKeyDefinition - }) - .GetAwaiter().GetResult(); + }); Assert.AreEqual(true, bool.Parse(containerResponse.Headers.Get(WFConstants.BackendHeaders.ShareThroughput))); @@ -168,24 +165,25 @@ private static void InitializeSharedThroughputContainer() BatchTestBase.SharedThroughputDatabase = db; } - public static void ClassClean() + public static async Task ClassCleanAsync() { - if (BatchTestBase.Client == null) + if (BatchTestBase.Database != null) { - return; + await BatchTestBase.Database.DeleteStreamAsync(); } - if (BatchTestBase.Database != null) + if (BatchTestBase.GatewayDatabase != null) { - BatchTestBase.Database.DeleteStreamAsync().GetAwaiter().GetResult(); + await BatchTestBase.GatewayDatabase.DeleteStreamAsync(); } if (BatchTestBase.SharedThroughputDatabase != null) { - BatchTestBase.SharedThroughputDatabase.DeleteStreamAsync().GetAwaiter().GetResult(); + await BatchTestBase.SharedThroughputDatabase.DeleteStreamAsync(); } - BatchTestBase.Client.Dispose(); + BatchTestBase.Client?.Dispose(); + BatchTestBase.GatewayClient?.Dispose(); } protected virtual async Task CreateJsonTestDocsAsync(Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs index 0e818611a8..2658b00dfc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs @@ -18,6 +18,7 @@ public class CosmosItemBulkTests { private Container container; private Database database; + private CosmosClient client; [TestInitialize] public async Task TestInitialize() @@ -26,9 +27,9 @@ public async Task TestInitialize() { AllowBulkExecution = true }; - CosmosClient client = TestCommon.CreateCosmosClient(clientOptions); + this.client = TestCommon.CreateCosmosClient(clientOptions); - DatabaseResponse response = await client.CreateDatabaseIfNotExistsAsync(Guid.NewGuid().ToString()); + DatabaseResponse response = await this.client.CreateDatabaseIfNotExistsAsync(Guid.NewGuid().ToString()); this.database = response.Database; ContainerResponse containerResponse = await this.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk", 10000); @@ -39,6 +40,7 @@ public async Task TestInitialize() public async Task Cleanup() { await this.database.DeleteAsync(); + this.client?.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/BaseChangeFeedClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/BaseChangeFeedClientHelper.cs index 14c362ee90..12cd3768ee 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/BaseChangeFeedClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/BaseChangeFeedClientHelper.cs @@ -16,7 +16,7 @@ public class BaseChangeFeedClientHelper : BaseCosmosClientHelper public async Task ChangeFeedTestInit(string leaseContainerPk = "/id") { - await base.TestInit(customizeClientBuilder: (builder) => builder.WithContentResponseOnWrite(false)); + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder.WithContentResponseOnWrite(false)); ContainerResponse response = await this.database.CreateContainerAsync( new ContainerProperties(id: "leases", partitionKeyPath: leaseContainerPk), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicStreamTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicStreamTests.cs index dba803d10b..f63ef4dbda 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicStreamTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicStreamTests.cs @@ -147,7 +147,7 @@ await NonPartitionedContainerHelper.CreateNonPartitionedContainer( this.database, "fixedLeases"); - Container fixedLeasesContainer = this.cosmosClient.GetContainer(this.database.Id, "fixedLeases"); + Container fixedLeasesContainer = this.GetClient().GetContainer(this.database.Id, "fixedLeases"); try { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicTests.cs index d7bf0d12f5..cefb823caa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/DynamicTests.cs @@ -168,7 +168,7 @@ await NonPartitionedContainerHelper.CreateNonPartitionedContainer( this.database, "fixedLeases"); - Container fixedLeasesContainer = this.cosmosClient.GetContainer(this.database.Id, "fixedLeases"); + Container fixedLeasesContainer = this.GetClient().GetContainer(this.database.Id, "fixedLeases"); try { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/EstimatorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/EstimatorTests.cs index ce139a47a4..7c92ef80c2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/EstimatorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/EstimatorTests.cs @@ -58,7 +58,7 @@ public async Task WhenNoLeasesExist() [TestMethod] public async Task StartAsync_ShouldThrowIfContainerDoesNotExist() { - ChangeFeedProcessor estimator = this.cosmosClient.GetContainer(this.database.Id, "DoesNotExist") + ChangeFeedProcessor estimator = this.GetClient().GetContainer(this.database.Id, "DoesNotExist") .GetChangeFeedEstimatorBuilder("test", (long estimation, CancellationToken token) => { return Task.CompletedTask; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs index b4460b6ad6..1291cc0b57 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/SmokeTests.cs @@ -322,7 +322,7 @@ public async Task Schema_OnV2MigrationMaintainPartitionId() [TestMethod] public async Task NotExistentLeaseContainer() { - Container notFoundContainer = this.cosmosClient.GetContainer(this.database.Id, "NonExistent"); + Container notFoundContainer = this.GetClient().GetContainer(this.database.Id, "NonExistent"); ChangeFeedProcessor processor = this.Container .GetChangeFeedProcessorBuilder("test", (IReadOnlyCollection docs, CancellationToken token) => Task.CompletedTask) .WithInstanceName("random") diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs index 0ea1e4d6fd..e977a8b459 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs @@ -23,9 +23,8 @@ public class ClientCreateAndInitializeTest : BaseCosmosClientHelper [TestInitialize] public async Task TestInitialize() { - this.cosmosClient = TestCommon.CreateCosmosClient(useGateway: false); - this.database = await this.cosmosClient.CreateDatabaseAsync( - id: "ClientCreateAndInitializeDatabase"); + await this.TestInit(); + ContainerResponse response = await this.database.CreateContainerAsync( new ContainerProperties(id: "ClientCreateAndInitializeContainer", partitionKeyPath: PartitionKey), throughput: 20000, @@ -67,7 +66,7 @@ public async Task CreateAndInitializeTest() (string endpoint, string authKey) = TestCommon.GetAccountInfo(); List<(string, string)> containers = new List<(string, string)> - { ("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer")}; + { (this.database.Id, "ClientCreateAndInitializeContainer")}; CosmosClientOptions cosmosClientOptions = new CosmosClientOptions { @@ -78,7 +77,7 @@ public async Task CreateAndInitializeTest() Assert.IsNotNull(cosmosClient); int httpCallsMadeAfterCreation = httpCallsMade; - ContainerInternal container = (ContainerInternal)cosmosClient.GetContainer("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer"); + ContainerInternal container = (ContainerInternal)cosmosClient.GetContainer(this.database.Id, "ClientCreateAndInitializeContainer"); ItemResponse readResponse = await container.ReadItemAsync("1", new Cosmos.PartitionKey("Status1")); string diagnostics = readResponse.Diagnostics.ToString(); Assert.IsTrue(diagnostics.Contains("\"ConnectionMode\":\"Direct\"")); @@ -101,14 +100,14 @@ public async Task CreateAndInitializeWithCosmosClientBuilderTest() (string endpoint, string authKey) = TestCommon.GetAccountInfo(); List<(string, string)> containers = new List<(string, string)> - { ("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer")}; + { (this.database.Id, "ClientCreateAndInitializeContainer")}; CosmosClientBuilder builder = new CosmosClientBuilder(endpoint, authKey).WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper)); CosmosClient cosmosClient = await builder.BuildAndInitializeAsync(containers); Assert.IsNotNull(cosmosClient); int httpCallsMadeAfterCreation = httpCallsMade; - ContainerInternal container = (ContainerInternal)cosmosClient.GetContainer("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer"); + ContainerInternal container = (ContainerInternal)cosmosClient.GetContainer(this.database.Id, "ClientCreateAndInitializeContainer"); ItemResponse readResponse = await container.ReadItemAsync("1", new Cosmos.PartitionKey("Status1")); Assert.AreEqual(httpCallsMade, httpCallsMadeAfterCreation); cosmosClient.Dispose(); @@ -119,7 +118,7 @@ public async Task CreateAndInitializeWithCosmosClientBuilderTest() public async Task AuthIncorrectTest() { List<(string databaseId, string containerId)> containers = new List<(string databaseId, string containerId)> - { ("ClientCreateAndInitializeDatabase", "ClientCreateAndInitializeContainer")}; + { (this.database.Id, "ClientCreateAndInitializeContainer")}; string authKey = TestCommon.GetAccountInfo().authKey; CosmosClient cosmosClient = await CosmosClient.CreateAndInitializeAsync("https://127.0.0.1:0000/", authKey, containers); cosmosClient.Dispose(); @@ -148,7 +147,7 @@ public async Task DatabaseIncorrectTest() public async Task ContainerIncorrectTest() { List<(string databaseId, string containerId)> containers = new List<(string databaseId, string containerId)> - { ("ClientCreateAndInitializeDatabase", "IncorrectContainer")}; + { (this.database.Id, "IncorrectContainer")}; (string endpoint, string authKey) = TestCommon.GetAccountInfo(); try { @@ -218,7 +217,7 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndContainer_ShouldO List<(string, string)> containers = new () { ( - "ClientCreateAndInitializeDatabase", + this.database.Id, "ClientCreateAndInitializeContainer" ) }; @@ -306,7 +305,7 @@ public async Task CreateAndInitializeAsync_WithGatewayModeEnabled_ShouldNotOpenC List<(string, string)> containers = new() { ( - "ClientCreateAndInitializeDatabase", + this.database.Id, "ClientCreateAndInitializeContainer" ) }; @@ -343,7 +342,7 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndInvalidContainer_ List<(string, string)> containers = new() { ( - "ClientCreateAndInitializeDatabase", + this.database.Id, "ClientCreateAndInitializeInvalidContainer" ) }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 737be92e05..d9bd416530 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -1094,11 +1094,11 @@ private async Task CreateClientAndContainer(ConnectionMode mode, .WithHttpClientFactory(() => new HttpClient(handlerHelper)) .WithApplicationName("userAgentSuffix"); - this.cosmosClient = mode == ConnectionMode.Gateway + this.SetClient(mode == ConnectionMode.Gateway ? this.cosmosClientBuilder.WithConnectionModeGateway().Build() - : this.cosmosClientBuilder.Build(); + : this.cosmosClientBuilder.Build()); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); return await this.database.CreateContainerAsync( id: Guid.NewGuid().ToString(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index a2fcc1f598..1f419c4eb8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -401,42 +401,49 @@ internal async Task TestEtagOnUpsertOperation(bool useGateway, Protocol protocol using (DocumentClient client = TestCommon.CreateClient(false, Protocol.Tcp)) { Database db = (await client.CreateDatabaseAsync(new Database() { Id = Guid.NewGuid().ToString() })).Resource; - DocumentCollection coll = await TestCommon.CreateCollectionAsync(client, db, new DocumentCollection() + try { - Id = Guid.NewGuid().ToString(), - PartitionKey = new PartitionKeyDefinition() + DocumentCollection coll = await TestCommon.CreateCollectionAsync(client, db, new DocumentCollection() { - Paths = new System.Collections.ObjectModel.Collection() { "/id" } - } - }); + Id = Guid.NewGuid().ToString(), + PartitionKey = new PartitionKeyDefinition() + { + Paths = new System.Collections.ObjectModel.Collection() { "/id" } + } + }); - LinqGeneralBaselineTests.Book myBook = new LinqGeneralBaselineTests.Book(); - myBook.Id = Guid.NewGuid().ToString(); - myBook.Title = "Azure DocumentDB 101"; + LinqGeneralBaselineTests.Book myBook = new LinqGeneralBaselineTests.Book(); + myBook.Id = Guid.NewGuid().ToString(); + myBook.Title = "Azure DocumentDB 101"; - Document doc = (await client.CreateDocumentAsync(coll.SelfLink, myBook)).Resource; + Document doc = (await client.CreateDocumentAsync(coll.SelfLink, myBook)).Resource; - myBook.Title = "Azure DocumentDB 201"; - await client.ReplaceDocumentAsync(doc.SelfLink, myBook); + myBook.Title = "Azure DocumentDB 201"; + await client.ReplaceDocumentAsync(doc.SelfLink, myBook); - AccessCondition condition = new AccessCondition(); - condition.Type = AccessConditionType.IfMatch; - condition.Condition = doc.ETag; + AccessCondition condition = new AccessCondition(); + condition.Type = AccessConditionType.IfMatch; + condition.Condition = doc.ETag; - RequestOptions requestOptions = new RequestOptions(); - requestOptions.AccessCondition = condition; + RequestOptions requestOptions = new RequestOptions(); + requestOptions.AccessCondition = condition; - myBook.Title = "Azure DocumentDB 301"; + myBook.Title = "Azure DocumentDB 301"; - try - { - await client.UpsertDocumentAsync(coll.SelfLink, myBook, requestOptions); - Assert.Fail("Upsert Document should fail since the Etag is not matching."); + try + { + await client.UpsertDocumentAsync(coll.SelfLink, myBook, requestOptions); + Assert.Fail("Upsert Document should fail since the Etag is not matching."); + } + catch (Exception ex) + { + DocumentClientException innerException = ex as DocumentClientException; + Assert.AreEqual(HttpStatusCode.PreconditionFailed, innerException.StatusCode, "Invalid status code"); + } } - catch (Exception ex) + finally { - DocumentClientException innerException = ex as DocumentClientException; - Assert.AreEqual(HttpStatusCode.PreconditionFailed, innerException.StatusCode, "Invalid status code"); + await client.DeleteDatabaseAsync(db); } } } @@ -448,7 +455,7 @@ public async Task Verify_CertificateCallBackGetsCalled_ForTCP_HTTP() string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; int counter = 0; AzureKeyCredential masterKeyCredential = new AzureKeyCredential(authKey); - CosmosClient cosmosClient = new CosmosClient( + using CosmosClient cosmosClient = new CosmosClient( endpoint, masterKeyCredential, new CosmosClientOptions() @@ -458,19 +465,27 @@ public async Task Verify_CertificateCallBackGetsCalled_ForTCP_HTTP() ServerCertificateCustomValidationCallback = (X509Certificate2 cerf, X509Chain chain, SslPolicyErrors error) => { counter ++; return true; } }); - string databaseName = Guid.NewGuid().ToString(); - string databaseId = Guid.NewGuid().ToString(); Cosmos.Database database = null; - //HTTP callback - database = await cosmosClient.CreateDatabaseAsync(databaseId); - - Cosmos.Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); + try + { + string databaseName = Guid.NewGuid().ToString(); + string databaseId = Guid.NewGuid().ToString(); + + //HTTP callback + database = await cosmosClient.CreateDatabaseAsync(databaseId); + + Cosmos.Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); - //TCP callback - ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); - ResponseMessage responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id)); + //TCP callback + ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); + ResponseMessage responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id)); - Assert.IsTrue(counter >= 2); + Assert.IsTrue(counter >= 2); + } + finally + { + await database?.DeleteStreamAsync(); + } } @@ -786,6 +801,7 @@ await Assert.ThrowsExceptionAsync(async () => proxy = new TestWebProxy { Credentials = new NetworkCredential("test", "test") }; + cosmosClient.Dispose(); cosmosClient = new CosmosClient( endpoint, ConfigurationManager.AppSettings["MasterKey"], @@ -801,6 +817,7 @@ await Assert.ThrowsExceptionAsync(async () => { DatabaseResponse databaseResponse = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); }); + cosmosClient.Dispose(); } [TestMethod] @@ -809,7 +826,7 @@ public async Task HttpClientFactorySmokeTest() HttpClient client = new HttpClient(); Mock> factory = new Mock>(); factory.Setup(f => f()).Returns(client); - CosmosClient cosmosClient = new CosmosClient( + using CosmosClient cosmosClient = new CosmosClient( ConfigurationManager.AppSettings["GatewayEndpoint"], ConfigurationManager.AppSettings["MasterKey"], new CosmosClientOptions diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosAadTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosAadTests.cs index c8ffd8cf29..01ffcdc674 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosAadTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosAadTests.cs @@ -29,98 +29,102 @@ public async Task AadMockTest(ConnectionMode connectionMode) int requestCount = 0; string databaseId = Guid.NewGuid().ToString(); string containerId = Guid.NewGuid().ToString(); - using (CosmosClient cosmosClient = TestCommon.CreateCosmosClient()) - { - Database database = await cosmosClient.CreateDatabaseAsync(databaseId); - Container container = await database.CreateContainerAsync( - containerId, - "/id"); - } + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient(); + Database database = await cosmosClient.CreateDatabaseAsync(databaseId); + Container container = await database.CreateContainerAsync( + containerId, + "/id"); - - (string endpoint, string authKey) = TestCommon.GetAccountInfo(); - LocalEmulatorTokenCredential simpleEmulatorTokenCredential = new LocalEmulatorTokenCredential(authKey); - CosmosClientOptions clientOptions = new CosmosClientOptions() + try { - ConnectionMode = connectionMode, - ConnectionProtocol = connectionMode == ConnectionMode.Direct ? Protocol.Tcp : Protocol.Https, - }; + (string endpoint, string authKey) = TestCommon.GetAccountInfo(); + LocalEmulatorTokenCredential simpleEmulatorTokenCredential = new LocalEmulatorTokenCredential(authKey); + CosmosClientOptions clientOptions = new CosmosClientOptions() + { + ConnectionMode = connectionMode, + ConnectionProtocol = connectionMode == ConnectionMode.Direct ? Protocol.Tcp : Protocol.Https, + }; - if (connectionMode == ConnectionMode.Direct) - { - long lsn = 2; - clientOptions.TransportClientHandlerFactory = (transport) => new TransportClientWrapper(transport, - interceptorAfterResult: (request, storeResponse) => - { - // Force a barrier request on create item. - // There needs to be 2 regions and the GlobalCommittedLSN must be behind the LSN. - if (storeResponse.StatusCode == HttpStatusCode.Created) + if (connectionMode == ConnectionMode.Direct) + { + long lsn = 2; + clientOptions.TransportClientHandlerFactory = (transport) => new TransportClientWrapper(transport, + interceptorAfterResult: (request, storeResponse) => { - if (requestCount == 0) + // Force a barrier request on create item. + // There needs to be 2 regions and the GlobalCommittedLSN must be behind the LSN. + if (storeResponse.StatusCode == HttpStatusCode.Created) { - requestCount++; - lsn = storeResponse.LSN; - storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); - storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, "0"); + if (requestCount == 0) + { + requestCount++; + lsn = storeResponse.LSN; + storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); + storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, "0"); + } } - } - // Head request is the barrier request - // The GlobalCommittedLSN is set to -1 because the local emulator doesn't have geo-dr so it has to be - // overridden for the validation to succeed. - if (request.OperationType == Documents.OperationType.Head) - { - if (requestCount == 1) + // Head request is the barrier request + // The GlobalCommittedLSN is set to -1 because the local emulator doesn't have geo-dr so it has to be + // overridden for the validation to succeed. + if (request.OperationType == Documents.OperationType.Head) { - requestCount++; - storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); - storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, lsn.ToString(CultureInfo.InvariantCulture)); + if (requestCount == 1) + { + requestCount++; + storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.NumberOfReadRegions, "2"); + storeResponse.Headers.Set(Documents.WFConstants.BackendHeaders.GlobalCommittedLSN, lsn.ToString(CultureInfo.InvariantCulture)); + } } - } - return storeResponse; - }); - } + return storeResponse; + }); + } - using CosmosClient aadClient = new CosmosClient( - endpoint, - simpleEmulatorTokenCredential, - clientOptions); + using CosmosClient aadClient = new CosmosClient( + endpoint, + simpleEmulatorTokenCredential, + clientOptions); - TokenCredentialCache tokenCredentialCache = ((AuthorizationTokenProviderTokenCredential)aadClient.AuthorizationTokenProvider).tokenCredentialCache; + TokenCredentialCache tokenCredentialCache = ((AuthorizationTokenProviderTokenCredential)aadClient.AuthorizationTokenProvider).tokenCredentialCache; - // The refresh interval changes slightly based on how fast machine calculate the interval based on the expire time. - Assert.IsTrue(15 <= tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); - Assert.IsTrue(tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes > 14.7 , "Default background refresh should be 25% of the token life which is defaulted to 1hr"); + // The refresh interval changes slightly based on how fast machine calculate the interval based on the expire time. + Assert.IsTrue(15 <= tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); + Assert.IsTrue(tokenCredentialCache.BackgroundTokenCredentialRefreshInterval.Value.TotalMinutes > 14.7, "Default background refresh should be 25% of the token life which is defaulted to 1hr"); - Database aadDatabase = await aadClient.GetDatabase(databaseId).ReadAsync(); - Container aadContainer = await aadDatabase.GetContainer(containerId).ReadContainerAsync(); - ToDoActivity toDoActivity = ToDoActivity.CreateRandomToDoActivity(); - ItemResponse itemResponse = await aadContainer.CreateItemAsync( - toDoActivity, - new PartitionKey(toDoActivity.id)); + Database aadDatabase = await aadClient.GetDatabase(databaseId).ReadAsync(); + Container aadContainer = await aadDatabase.GetContainer(containerId).ReadContainerAsync(); + ToDoActivity toDoActivity = ToDoActivity.CreateRandomToDoActivity(); + ItemResponse itemResponse = await aadContainer.CreateItemAsync( + toDoActivity, + new PartitionKey(toDoActivity.id)); - // Gateway does the barrier requests so only direct mode needs to be validated. - if (connectionMode == ConnectionMode.Direct) - { - Assert.AreEqual(2, requestCount, "The barrier request was never called."); - } + // Gateway does the barrier requests so only direct mode needs to be validated. + if (connectionMode == ConnectionMode.Direct) + { + Assert.AreEqual(2, requestCount, "The barrier request was never called."); + } - toDoActivity.cost = 42.42; - await aadContainer.ReplaceItemAsync( - toDoActivity, - toDoActivity.id, - new PartitionKey(toDoActivity.id)); + toDoActivity.cost = 42.42; + await aadContainer.ReplaceItemAsync( + toDoActivity, + toDoActivity.id, + new PartitionKey(toDoActivity.id)); - await aadContainer.ReadItemAsync( - toDoActivity.id, - new PartitionKey(toDoActivity.id)); + await aadContainer.ReadItemAsync( + toDoActivity.id, + new PartitionKey(toDoActivity.id)); - await aadContainer.UpsertItemAsync(toDoActivity); + await aadContainer.UpsertItemAsync(toDoActivity); - await aadContainer.DeleteItemAsync( - toDoActivity.id, - new PartitionKey(toDoActivity.id)); + await aadContainer.DeleteItemAsync( + toDoActivity.id, + new PartitionKey(toDoActivity.id)); + } + finally + { + await database?.DeleteStreamAsync(); + } } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs index 0f55c04ba8..7ae2b28cc6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs @@ -930,25 +930,32 @@ public async Task InvalidRangesOnQuery() DatabaseResponse databaseResponse = await cosmosClient.CreateDatabaseIfNotExistsAsync(DatabaseName, Throughput); Database database = databaseResponse.Database; - Container container = await database.DefineContainer(TestCollection, $"/{DefaultKey}") - .WithUniqueKey().Path($"/{DefaultKey}").Attach().CreateIfNotExistsAsync(); + try + { + Container container = await database.DefineContainer(TestCollection, $"/{DefaultKey}") + .WithUniqueKey().Path($"/{DefaultKey}").Attach().CreateIfNotExistsAsync(); - List queryKeys = new List(); + List queryKeys = new List(); - List testCollectionObjects = JsonConvert.DeserializeObject>( - "[{\"id\":\"70627503-7cb2-4a79-bcec-5e55765aa080\",\"objectKey\":\"message~phone~u058da564bfaa66cb031606db664dbfda~phone~ud75ce020af5f8bfb75a9097a66d452f2~Chat~20190927000042Z\",\"text\":null,\"text2\":null},{\"id\":\"507079b7-a5be-4da4-9158-16fc961cd474\",\"objectKey\":\"message~phone~u058da564bfaa66cb031606db664dbfda~phone~ud75ce020af5f8bfb75a9097a66d452f2~Chat~20190927125742Z\",\"text\":null,\"text2\":null}]"); - foreach (TestCollectionObject testCollectionObject in testCollectionObjects) - { - await WriteDocument(container, testCollectionObject); - queryKeys.Add(testCollectionObject.ObjectKey); - } + List testCollectionObjects = JsonConvert.DeserializeObject>( + "[{\"id\":\"70627503-7cb2-4a79-bcec-5e55765aa080\",\"objectKey\":\"message~phone~u058da564bfaa66cb031606db664dbfda~phone~ud75ce020af5f8bfb75a9097a66d452f2~Chat~20190927000042Z\",\"text\":null,\"text2\":null},{\"id\":\"507079b7-a5be-4da4-9158-16fc961cd474\",\"objectKey\":\"message~phone~u058da564bfaa66cb031606db664dbfda~phone~ud75ce020af5f8bfb75a9097a66d452f2~Chat~20190927125742Z\",\"text\":null,\"text2\":null}]"); + foreach (TestCollectionObject testCollectionObject in testCollectionObjects) + { + await WriteDocument(container, testCollectionObject); + queryKeys.Add(testCollectionObject.ObjectKey); + } - List results = container - .GetItemLinqQueryable(true, requestOptions: RunInParallelOptions()) - .Where(r => queryKeys.Contains(r.ObjectKey)) - .ToList(); // ERROR OCCURS WHEN QUERY IS EXECUTED + List results = container + .GetItemLinqQueryable(true, requestOptions: RunInParallelOptions()) + .Where(r => queryKeys.Contains(r.ObjectKey)) + .ToList(); // ERROR OCCURS WHEN QUERY IS EXECUTED - Console.WriteLine($"[\"{string.Join("\", \n\"", results.Select(r => r.ObjectKey))}\"]"); + Console.WriteLine($"[\"{string.Join("\", \n\"", results.Select(r => r.ObjectKey))}\"]"); + } + finally + { + await database.DeleteAsync(); + } } private static async Task WriteDocument(Container container, TestCollectionObject testData) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs index 208b08ec11..07cb6a4dca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs @@ -1167,62 +1167,68 @@ public async Task ReadReplaceThroughputResponseTests() (x) => toStreamCount++); //Create a new cosmos client with the mocked cosmos json serializer - CosmosClient client = TestCommon.CreateCosmosClient( + using CosmosClient client = TestCommon.CreateCosmosClient( (cosmosClientBuilder) => cosmosClientBuilder.WithCustomSerializer(mockJsonSerializer)); int databaseThroughput = 10000; Cosmos.Database databaseNoThroughput = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), throughput: null); Cosmos.Database databaseWithThroughput = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), databaseThroughput, null); - - string containerId = Guid.NewGuid().ToString(); - string partitionPath = "/users"; - Container containerNoThroughput = await databaseWithThroughput.CreateContainerAsync(containerId, partitionPath, throughput: null); try { - await containerNoThroughput.ReadThroughputAsync(new RequestOptions()); - Assert.Fail("Should through not found exception as throughput is not configured"); - } - catch (CosmosException exception) - { - Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode); - } + string containerId = Guid.NewGuid().ToString(); + string partitionPath = "/users"; + Container containerNoThroughput = await databaseWithThroughput.CreateContainerAsync(containerId, partitionPath, throughput: null); + try + { + await containerNoThroughput.ReadThroughputAsync(new RequestOptions()); + Assert.Fail("Should through not found exception as throughput is not configured"); + } + catch (CosmosException exception) + { + Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode); + } - try - { - await containerNoThroughput.ReplaceThroughputAsync(2000, new RequestOptions()); - Assert.Fail("Should through not found exception as throughput is not configured"); - } - catch (CosmosException exception) - { - Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode); - } + try + { + await containerNoThroughput.ReplaceThroughputAsync(2000, new RequestOptions()); + Assert.Fail("Should through not found exception as throughput is not configured"); + } + catch (CosmosException exception) + { + Assert.AreEqual(HttpStatusCode.NotFound, exception.StatusCode); + } - int containerThroughput = 1000; - Container container = await databaseNoThroughput.CreateContainerAsync(Guid.NewGuid().ToString(), "/id", throughput: containerThroughput); + int containerThroughput = 1000; + Container container = await databaseNoThroughput.CreateContainerAsync(Guid.NewGuid().ToString(), "/id", throughput: containerThroughput); - int? containerResponseThroughput = await container.ReadThroughputAsync(); - Assert.AreEqual(containerThroughput, containerResponseThroughput); + int? containerResponseThroughput = await container.ReadThroughputAsync(); + Assert.AreEqual(containerThroughput, containerResponseThroughput); - ThroughputResponse containerThroughputResponse = await container.ReadThroughputAsync(new RequestOptions()); - Assert.IsNotNull(containerThroughputResponse); - Assert.IsNotNull(containerThroughputResponse.Resource); - Assert.IsNotNull(containerThroughputResponse.MinThroughput); - Assert.IsNotNull(containerThroughputResponse.Resource.Throughput); - Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value); - SelflinkValidator.ValidateTroughputSelfLink(containerThroughputResponse.Resource.SelfLink); + ThroughputResponse containerThroughputResponse = await container.ReadThroughputAsync(new RequestOptions()); + Assert.IsNotNull(containerThroughputResponse); + Assert.IsNotNull(containerThroughputResponse.Resource); + Assert.IsNotNull(containerThroughputResponse.MinThroughput); + Assert.IsNotNull(containerThroughputResponse.Resource.Throughput); + Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value); + SelflinkValidator.ValidateTroughputSelfLink(containerThroughputResponse.Resource.SelfLink); - containerThroughput += 500; - containerThroughputResponse = await container.ReplaceThroughputAsync(containerThroughput, new RequestOptions()); - Assert.IsNotNull(containerThroughputResponse); - Assert.IsNotNull(containerThroughputResponse.Resource); - Assert.IsNotNull(containerThroughputResponse.Resource.Throughput); - Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value); - SelflinkValidator.ValidateTroughputSelfLink(containerThroughputResponse.Resource.SelfLink); + containerThroughput += 500; + containerThroughputResponse = await container.ReplaceThroughputAsync(containerThroughput, new RequestOptions()); + Assert.IsNotNull(containerThroughputResponse); + Assert.IsNotNull(containerThroughputResponse.Resource); + Assert.IsNotNull(containerThroughputResponse.Resource.Throughput); + Assert.AreEqual(containerThroughput, containerThroughputResponse.Resource.Throughput.Value); + SelflinkValidator.ValidateTroughputSelfLink(containerThroughputResponse.Resource.SelfLink); - Assert.AreEqual(0, toStreamCount, "Custom serializer to stream should not be used for offer operations"); - Assert.AreEqual(0, fromStreamCount, "Custom serializer from stream should not be used for offer operations"); - await databaseNoThroughput.DeleteAsync(); + Assert.AreEqual(0, toStreamCount, "Custom serializer to stream should not be used for offer operations"); + Assert.AreEqual(0, fromStreamCount, "Custom serializer from stream should not be used for offer operations"); + } + finally + { + await databaseNoThroughput.DeleteAsync(); + await databaseWithThroughput.DeleteAsync(); + } } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContentResponseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContentResponseTests.cs index fd3f8bf175..ecc7faffd6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContentResponseTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContentResponseTests.cs @@ -6,28 +6,20 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Collections.Generic; - using System.Linq; using System.Net; - using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] - public class CosmosContentResponseTests + public class CosmosContentResponseTests : BaseCosmosClientHelper { - private CosmosClient cosmosClient; - private Database database; private Container container; private ContainerInternal containerInternal; [TestInitialize] - public async Task TestInit() + public async Task TestInitialize() { - this.cosmosClient = TestCommon.CreateCosmosClient(); - this.database = await this.cosmosClient.CreateDatabaseAsync( - id: Guid.NewGuid().ToString()); + await base.TestInit(); this.container = await this.database.CreateContainerAsync( id: "ItemNoResponseTest", @@ -36,15 +28,9 @@ public async Task TestInit() } [TestCleanup] - public async Task TestCleanup() + public async Task TestCleanUp() { - if (this.cosmosClient == null) - { - return; - } - - using (await this.database.DeleteStreamAsync()) { } - this.cosmosClient.Dispose(); + await base.TestCleanup(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs index 9370345d81..ba6d33d55e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosDatabaseTests.cs @@ -10,42 +10,26 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Linq; using System.Net; using System.Security.Cryptography; - using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; - using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [TestClass] - public class CosmosDatabaseTests + public class CosmosDatabaseTests : BaseCosmosClientHelper { - protected CosmosClient cosmosClient = null; - protected CancellationTokenSource cancellationTokenSource = null; - protected CancellationToken cancellationToken; - [TestInitialize] - public void TestInit() + public async Task TestInitialize() { - this.cancellationTokenSource = new CancellationTokenSource(); - this.cancellationToken = this.cancellationTokenSource.Token; - - this.cosmosClient = TestCommon.CreateCosmosClient(); + await base.TestInit(); } [TestCleanup] - public void TestCleanup() + public async Task TestCleanUp() { - if (this.cosmosClient == null) - { - return; - } - - this.cancellationTokenSource?.Cancel(); - this.cosmosClient.Dispose(); + await base.TestCleanup(); } [TestMethod] @@ -121,7 +105,7 @@ public async Task StreamCreateConflictTestAsync() Id = Guid.NewGuid().ToString() }; - using (ResponseMessage response = await this.cosmosClient.CreateDatabaseStreamAsync(databaseSettings)) + using (ResponseMessage response = await this.GetClient().CreateDatabaseStreamAsync(databaseSettings)) { Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); Assert.IsNotNull(response.Headers); @@ -129,14 +113,14 @@ public async Task StreamCreateConflictTestAsync() } // Stream operations do not throw exceptions. - using (ResponseMessage response = await this.cosmosClient.CreateDatabaseStreamAsync(databaseSettings)) + using (ResponseMessage response = await this.GetClient().CreateDatabaseStreamAsync(databaseSettings)) { Assert.AreEqual(HttpStatusCode.Conflict, response.StatusCode); Assert.IsNotNull(response.Headers); Assert.IsTrue(response.Headers.RequestCharge > 0); } - using (ResponseMessage response = await this.cosmosClient.GetDatabase(databaseSettings.Id).DeleteStreamAsync()) + using (ResponseMessage response = await this.GetClient().GetDatabase(databaseSettings.Id).DeleteStreamAsync()) { Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); Assert.IsNotNull(response.Headers); @@ -185,7 +169,7 @@ public async Task DropNonExistingDatabase() { try { - DatabaseResponse response = await this.cosmosClient.GetDatabase(Guid.NewGuid().ToString()).DeleteAsync(cancellationToken: this.cancellationToken); + DatabaseResponse response = await this.GetClient().GetDatabase(Guid.NewGuid().ToString()).DeleteAsync(cancellationToken: this.cancellationToken); Assert.Fail(); } catch (CosmosException ex) @@ -218,7 +202,7 @@ public async Task CreateIfNotExists() RequestChargeHandlerHelper requestChargeHandler = new RequestChargeHandlerHelper(); RequestHandlerHelper requestHandlerHelper = new RequestHandlerHelper(); - CosmosClient client = TestCommon.CreateCosmosClient(x => x.AddCustomHandlers(requestChargeHandler, requestHandlerHelper)); + using CosmosClient client = TestCommon.CreateCosmosClient(x => x.AddCustomHandlers(requestChargeHandler, requestHandlerHelper)); // Create a new database requestChargeHandler.TotalRequestCharges = 0; @@ -292,7 +276,7 @@ public async Task ReadReplaceThroughputResponseTests() (x) => toStreamCount++); //Create a new cosmos client with the mocked cosmos json serializer - CosmosClient client = TestCommon.CreateCosmosClient( + using CosmosClient client = TestCommon.CreateCosmosClient( (cosmosClientBuilder) => cosmosClientBuilder.WithCustomSerializer(mockJsonSerializer)); string databaseId = Guid.NewGuid().ToString(); @@ -372,7 +356,7 @@ public async Task DatabaseIterator() databaseIds.Add(createResponse.Resource.Id); } - FeedIterator feedIterator = this.cosmosClient.GetDatabaseQueryIterator( + FeedIterator feedIterator = this.GetClient().GetDatabaseQueryIterator( queryDefinition: null, continuationToken: null, requestOptions: new QueryRequestOptions() { MaxItemCount = 2 }); @@ -420,7 +404,7 @@ public async Task EncryptionCreateReplaceCek() cekProperties.EncryptionKeyWrapMetadata); // Use a different client instance to avoid (unintentional) cache impact - ClientEncryptionKeyProperties readProperties = await ((DatabaseInlineCore)this.cosmosClient.GetDatabase(response.Database.Id)).GetClientEncryptionKey(cekId).ReadAsync(); + ClientEncryptionKeyProperties readProperties = await ((DatabaseInlineCore)this.GetClient().GetDatabase(response.Database.Id)).GetClientEncryptionKey(cekId).ReadAsync(); Assert.AreEqual(cekProperties, readProperties); // Replace @@ -438,7 +422,7 @@ public async Task EncryptionCreateReplaceCek() // Use a different client instance to avoid (unintentional) cache impact readProperties = - await ((DatabaseCore)(DatabaseInlineCore)this.cosmosClient.GetDatabase(response.Database.Id)).GetClientEncryptionKey(cekId).ReadAsync(); + await ((DatabaseCore)(DatabaseInlineCore)this.GetClient().GetDatabase(response.Database.Id)).GetClientEncryptionKey(cekId).ReadAsync(); Assert.AreEqual(cekProperties, readProperties); response = await response.Database.DeleteAsync(cancellationToken: this.cancellationToken); @@ -558,15 +542,15 @@ public async Task DatabaseQueryIterator() string secondDb = "Bcdefgh"; string thirdDb = "Zoo"; - DatabaseResponse createResponse2 = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(secondDb); + DatabaseResponse createResponse2 = await this.GetClient().CreateDatabaseIfNotExistsAsync(secondDb); deleteList.Add(createResponse2.Database); - DatabaseResponse createResponse = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(firstDb); + DatabaseResponse createResponse = await this.GetClient().CreateDatabaseIfNotExistsAsync(firstDb); deleteList.Add(createResponse.Database); - DatabaseResponse createResponse3 = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(thirdDb); + DatabaseResponse createResponse3 = await this.GetClient().CreateDatabaseIfNotExistsAsync(thirdDb); deleteList.Add(createResponse3.Database); using (FeedIterator feedIterator = - this.cosmosClient.GetDatabaseQueryIterator( + this.GetClient().GetDatabaseQueryIterator( new QueryDefinition("select c.id From c where c.id = @id ") .WithParameter("@id", createResponse.Database.Id), requestOptions: new QueryRequestOptions() { MaxItemCount = 1 })) @@ -579,7 +563,7 @@ public async Task DatabaseQueryIterator() } using (FeedIterator feedIterator = - this.cosmosClient.GetDatabaseQueryStreamIterator( + this.GetClient().GetDatabaseQueryStreamIterator( "select value c.id From c ")) { while (feedIterator.HasMoreResults) @@ -603,7 +587,7 @@ public async Task DatabaseQueryIterator() List ids = new List(); using (FeedIterator feedIterator = - this.cosmosClient.GetDatabaseQueryIterator( + this.GetClient().GetDatabaseQueryIterator( "select value c.id From c ")) { while (feedIterator.HasMoreResults) @@ -637,14 +621,14 @@ private async Task CreateDatabaseHelper( DatabaseResponse response = null; if (databaseExists) { - response = await this.cosmosClient.CreateDatabaseIfNotExistsAsync( + response = await this.GetClient().CreateDatabaseIfNotExistsAsync( databaseId, throughput, cancellationToken: this.cancellationToken); } else { - response = await this.cosmosClient.CreateDatabaseAsync( + response = await this.GetClient().CreateDatabaseAsync( databaseId, throughput, cancellationToken: this.cancellationToken); @@ -673,7 +657,7 @@ private async Task CreateDatabaseHelper( } DatabaseProperties databaseSettings = new DatabaseProperties() { Id = databaseId }; - ResponseMessage response = await this.cosmosClient.CreateDatabaseStreamAsync( + ResponseMessage response = await this.GetClient().CreateDatabaseStreamAsync( databaseSettings, throughput: 400); @@ -683,7 +667,7 @@ private async Task CreateDatabaseHelper( Assert.IsTrue(response.StatusCode == HttpStatusCode.OK || (response.StatusCode == HttpStatusCode.Created && !databaseExists)); - return this.cosmosClient.GetDatabase(databaseId); + return this.GetClient().GetDatabase(databaseId); } private void ValidateHeaders(DatabaseResponse cosmosDatabaseResponse) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs index aef4323045..257c1ba0d3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemIdEncodingTestsBase.cs @@ -588,9 +588,9 @@ public async Task IdWithLineFeed() private async Task ExecuteTestCase(TestScenario scenario) { TestScenarioExpectations expected = - this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Direct ? + this.GetClient().ClientOptions.ConnectionMode == ConnectionMode.Direct ? scenario.Direct : - this.cosmosClient.Endpoint.Port == computeGatewayPort ? + this.GetClient().Endpoint.Port == computeGatewayPort ? scenario.ComputeGateway ?? scenario.Gateway : scenario.Gateway; Console.WriteLine($"Scenario: {scenario.Name}, Id: \"{scenario.Id}\""); @@ -638,7 +638,7 @@ await CreateItemPayload(scenario.Id), Assert.AreEqual(expected.ExpectedDeleteStatusCode, response.StatusCode); if (response.IsSuccessStatusCode) { - if (this.cosmosClient.ClientOptions.ConnectionMode == ConnectionMode.Gateway) + if (this.GetClient().ClientOptions.ConnectionMode == ConnectionMode.Gateway) { await ValidateEmptyPayload(response.Content); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs index 652cb01441..f815eba08e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs @@ -237,7 +237,7 @@ public async Task NoSessionTokenCaptureForThrottledUpsertRequestsTest() return throttledResponse; }, - this.cosmosClient.DocumentClient.sessionContainer); + this.GetClient().DocumentClient.sessionContainer); try { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index 50bc71f276..c5d6347dd1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -69,7 +69,7 @@ public async Task Cleanup() public void ParentResourceTest() { Assert.AreEqual(this.database, this.Container.Database); - Assert.AreEqual(this.cosmosClient, this.Container.Database.Client); + Assert.AreEqual(this.GetClient(), this.Container.Database.Client); } [TestMethod] @@ -96,7 +96,7 @@ public async Task CreateDropItemWithInvalidIdCharactersTest() string[] selfLinkSegments = containerProperties.SelfLink.Split('/'); string databaseRid = selfLinkSegments[1]; string containerRid = selfLinkSegments[3]; - Container containerByRid = this.cosmosClient.GetContainer(databaseRid, containerRid); + Container containerByRid = this.GetClient().GetContainer(databaseRid, containerRid); // List of invalid characters are listed here. //https://docs.microsoft.com/dotnet/api/microsoft.azure.documents.resource.id?view=azure-dotnet#remarks @@ -416,7 +416,7 @@ public async Task ReadCollectionNotExists() // Item -> Container -> Database contract string dbName = Guid.NewGuid().ToString(); - testContainer = this.cosmosClient.GetDatabase(dbName).GetContainer(collectionName); + testContainer = this.GetClient().GetDatabase(dbName).GetContainer(collectionName); await CosmosItemTests.TestNonePKForNonExistingContainer(testContainer); } @@ -424,7 +424,7 @@ public async Task ReadCollectionNotExists() public async Task NonPartitionKeyLookupCacheTest() { int count = 0; - CosmosClient client = TestCommon.CreateCosmosClient(builder => + using CosmosClient client = TestCommon.CreateCosmosClient(builder => { builder.WithConnectionModeDirect(); builder.WithSendingRequestEventArgs((sender, e) => @@ -509,6 +509,8 @@ public async Task NonPartitionKeyLookupCacheTest() // OkRagnes should be fetched only once. // Possible to make multiple calls for ranges Assert.AreEqual(expected, count); + + await db.DeleteStreamAsync(); } [TestMethod] @@ -767,11 +769,10 @@ public async Task PartitionKeyDeleteTestForSubpartitionedContainer() { string currentVersion = HttpConstants.Versions.CurrentVersion; HttpConstants.Versions.CurrentVersion = "2020-07-15"; + using CosmosClient client = TestCommon.CreateCosmosClient(true); Cosmos.Database database = null; try { - CosmosClient client = TestCommon.CreateCosmosClient(true); - database = await client.CreateDatabaseIfNotExistsAsync("mydb"); ContainerProperties containerProperties = new ContainerProperties("subpartitionedcontainer", new List { "/Country", "/City" }); @@ -1575,7 +1576,7 @@ public async Task ItemEpkQuerySingleKeyRangeValidation() container = (ContainerInlineCore)containerResponse; // Get all the partition key ranges to verify there is more than one partition - IRoutingMapProvider routingMapProvider = await this.cosmosClient.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); + IRoutingMapProvider routingMapProvider = await this.GetClient().DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); IReadOnlyList ranges = await routingMapProvider.TryGetOverlappingRangesAsync( containerResponse.Resource.ResourceId, new Documents.Routing.Range("00", "FF", isMaxInclusive: true, isMinInclusive: true), @@ -2692,7 +2693,7 @@ public async Task MigrateDataInNonPartitionContainer() [TestCategory("Quarantine") /* Gated runs emulator as rate limiting disabled */] public async Task VerifyToManyRequestTest(bool isQuery) { - CosmosClient client = TestCommon.CreateCosmosClient(); + using CosmosClient client = TestCommon.CreateCosmosClient(); Cosmos.Database db = await client.CreateDatabaseIfNotExistsAsync("LoadTest"); Container container = await db.CreateContainerIfNotExistsAsync("LoadContainer", "/pk"); @@ -2755,7 +2756,7 @@ public async Task VerifySessionTokenPassThrough() [TestMethod] public async Task VerifySessionNotFoundStatistics() { - CosmosClient cosmosClient = TestCommon.CreateCosmosClient(new CosmosClientOptions() { ConsistencyLevel = Cosmos.ConsistencyLevel.Session }); + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient(new CosmosClientOptions() { ConsistencyLevel = Cosmos.ConsistencyLevel.Session }); DatabaseResponse database = await cosmosClient.CreateDatabaseIfNotExistsAsync("NoSession"); Container container = await database.Database.CreateContainerIfNotExistsAsync("NoSession", "/pk"); @@ -2815,8 +2816,8 @@ public async Task ContainterReCreateStatelessTest(bool operationBetweenRecreate, operation = ExecuteReadFeedAsync; } - CosmosClient cc1 = TestCommon.CreateCosmosClient(); - CosmosClient cc2 = TestCommon.CreateCosmosClient(); + using CosmosClient cc1 = TestCommon.CreateCosmosClient(); + using CosmosClient cc2 = TestCommon.CreateCosmosClient(); Cosmos.Database db1 = null; try { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs index d069e87935..c77352d07f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -14,7 +14,8 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public class CosmosMultiHashTest { private Cosmos.Database database = null; - + + private CosmosClient client = null; private Container container = null; private ContainerProperties containerProperties = null; @@ -25,8 +26,8 @@ public class CosmosMultiHashTest public async Task TestInitialize() { HttpConstants.Versions.CurrentVersion = "2020-07-15"; - CosmosClient client = TestCommon.CreateCosmosClient(true); - this.database = await client.CreateDatabaseIfNotExistsAsync("mydb"); + this.client = TestCommon.CreateCosmosClient(true); + this.database = await this.client.CreateDatabaseIfNotExistsAsync("mydb"); this.containerProperties = new ContainerProperties("mycoll", new List { "/ZipCode", "/Address" }); this.container = await this.database.CreateContainerAsync(this.containerProperties); @@ -37,6 +38,7 @@ public async Task Cleanup() { await this.database.DeleteAsync(); HttpConstants.Versions.CurrentVersion = this.currentVersion; + this.client.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosNotFoundTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosNotFoundTests.cs index a136cfe4b3..1903a04861 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosNotFoundTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosNotFoundTests.cs @@ -39,6 +39,7 @@ public async Task ValidateContainerNotFoundResponse() Database dbExists = await client.CreateDatabaseAsync("NotFoundTest" + Guid.NewGuid().ToString()); await this.ContainerOperations(database: dbExists, dbNotExist: false); + await dbExists.DeleteStreamAsync(); } [TestMethod] @@ -76,7 +77,7 @@ public async Task ValidateQueryNotFoundResponse() { // Recreate the collection with the same name on a different client. - CosmosClient newClient = TestCommon.CreateCosmosClient(); + using CosmosClient newClient = TestCommon.CreateCosmosClient(); Database db2 = newClient.GetDatabase(db.Id); Container container2 = await db2.CreateContainerAsync( id: container.Id, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs index 003ca8690b..753fe93899 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosPermissionTests.cs @@ -13,45 +13,29 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] - public class CosmosPermissionTests + public class CosmosPermissionTests : BaseCosmosClientHelper { - private CosmosClient cosmosClient = null; - private Database cosmosDatabase = null; - [TestInitialize] - public async Task TestInit() + public async Task TestInitialize() { - this.cosmosClient = TestCommon.CreateCosmosClient(); - - string databaseName = Guid.NewGuid().ToString(); - DatabaseResponse cosmosDatabaseResponse = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(databaseName); - this.cosmosDatabase = cosmosDatabaseResponse; + await base.TestInit(); } [TestCleanup] - public async Task TestCleanup() + public async Task Cleanup() { - if (this.cosmosClient == null) - { - return; - } - - if (this.cosmosDatabase != null) - { - await this.cosmosDatabase.DeleteStreamAsync(); - } - this.cosmosClient.Dispose(); + await base.TestCleanup(); } [TestMethod] public async Task CRUDTest() { string containerId = Guid.NewGuid().ToString(); - ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(containerId, "/id"); + ContainerResponse containerResponse = await this.database.CreateContainerAsync(containerId, "/id"); Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); string userId = Guid.NewGuid().ToString(); - UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); + UserResponse userResponse = await this.database.CreateUserAsync(userId); User user = userResponse.User; Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode); Assert.AreEqual(userId, user.Id); @@ -118,14 +102,14 @@ public async Task ContainerResourcePermissionTest(ConnectionMode mode) //create user string userId = Guid.NewGuid().ToString(); - UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); + UserResponse userResponse = await this.database.CreateUserAsync(userId); Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode); Assert.AreEqual(userId, userResponse.Resource.Id); User user = userResponse.User; //create resource string containerId = Guid.NewGuid().ToString(); - ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(containerId, "/id"); + ContainerResponse containerResponse = await this.database.CreateContainerAsync(containerId, "/id"); Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); Container container = containerResponse.Container; @@ -140,7 +124,7 @@ public async Task ContainerResourcePermissionTest(ConnectionMode mode) using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions, resourceToken: permission.Token)) { - Container readContainerRef = tokenCosmosClient.GetContainer(this.cosmosDatabase.Id, containerId); + Container readContainerRef = tokenCosmosClient.GetContainer(this.database.Id, containerId); //read resource with PermissionMode.Read using FeedIterator feedIterator = readContainerRef.GetItemQueryIterator("SELECT * FROM c"); @@ -153,7 +137,7 @@ public async Task ContainerResourcePermissionTest(ConnectionMode mode) try { ContainerResponse response = await tokenCosmosClient - .GetDatabase(this.cosmosDatabase.Id) + .GetDatabase(this.database.Id) .GetContainer(containerId) .DeleteContainerAsync(); Assert.Fail(); @@ -173,7 +157,7 @@ public async Task ContainerResourcePermissionTest(ConnectionMode mode) using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions, resourceToken: permission.Token)) { ContainerResponse response = await tokenCosmosClient - .GetDatabase(this.cosmosDatabase.Id) + .GetDatabase(this.database.Id) .GetContainer(containerId) .DeleteContainerAsync(); Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); @@ -190,7 +174,7 @@ public async Task ContainerPartitionResourcePermissionTest(ConnectionMode connec ConnectionMode = connectionMode }; - CosmosClient cosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions); + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient(cosmosClientOptions); Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync("PermissionTest"); @@ -297,6 +281,8 @@ await container.CreateItemAsync( Assert.AreEqual(1, resultGateway.Count); } + + await database.DeleteStreamAsync(); } [TestMethod] @@ -311,14 +297,14 @@ public async Task ItemResourcePermissionTest(ConnectionMode connectionMode) //create user string userId = Guid.NewGuid().ToString(); - UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); + UserResponse userResponse = await this.database.CreateUserAsync(userId); Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode); Assert.AreEqual(userId, userResponse.Resource.Id); User user = userResponse.User; //create resource string containerId = Guid.NewGuid().ToString(); - ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(containerId, "/id"); + ContainerResponse containerResponse = await this.database.CreateContainerAsync(containerId, "/id"); Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); Container container = containerResponse.Container; string itemId = Guid.NewGuid().ToString(); @@ -338,7 +324,7 @@ public async Task ItemResourcePermissionTest(ConnectionMode connectionMode) using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: cosmosClientOptions, resourceToken: permission.Token)) { - Container tokenContainer = tokenCosmosClient.GetContainer(this.cosmosDatabase.Id, containerId); + Container tokenContainer = tokenCosmosClient.GetContainer(this.database.Id, containerId); //read resource with PermissionMode.Read ItemResponse readPermissionItem = await tokenContainer.ReadItemAsync(itemId, partitionKey); @@ -368,7 +354,7 @@ public async Task ItemResourcePermissionTest(ConnectionMode connectionMode) using (CosmosClient tokenCosmosClient = TestCommon.CreateCosmosClient(clientOptions: cosmosClientOptions, resourceToken: permission.Token)) { using (FeedIterator feed = tokenCosmosClient - .GetDatabase(this.cosmosDatabase.Id) + .GetDatabase(this.database.Id) .GetContainer(containerId) .GetItemQueryIterator(new QueryDefinition("select * from t"))) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadFeedTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadFeedTests.cs index 08c65ea00d..6bd4bcbdb8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadFeedTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadFeedTests.cs @@ -33,7 +33,7 @@ public async Task TestInitialize() Assert.IsNotNull(response.Resource); this.Container = (ContainerInlineCore)response; - DocumentFeedResponse pkRangesFeed = await this.cosmosClient.DocumentClient.ReadPartitionKeyRangeFeedAsync(this.Container.LinkUri); + DocumentFeedResponse pkRangesFeed = await this.GetClient().DocumentClient.ReadPartitionKeyRangeFeedAsync(this.Container.LinkUri); Assert.IsTrue(pkRangesFeed.Count > 1, "Refresh container throughput to have at-least > 1 pk-range"); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs index 4a406c29d1..ede534cb9d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs @@ -95,7 +95,7 @@ public async Task ReadManyStreamTest() Assert.IsTrue(responseMessage.Headers.RequestCharge > 0); Assert.IsNotNull(responseMessage.Diagnostics); - ToDoActivity[] items = this.cosmosClient.ClientContext.SerializerCore.FromFeedStream( + ToDoActivity[] items = this.GetClient().ClientContext.SerializerCore.FromFeedStream( CosmosFeedResponseSerializer.GetStreamWithoutServiceEnvelope(responseMessage.Content)); Assert.AreEqual(items.Length, 5); } @@ -147,7 +147,7 @@ public async Task ReadManyWithIdasPk() Assert.IsTrue(responseMessage.Headers.RequestCharge > 0); Assert.IsNotNull(responseMessage.Diagnostics); - ToDoActivity[] items = this.cosmosClient.ClientContext.SerializerCore.FromFeedStream( + ToDoActivity[] items = this.GetClient().ClientContext.SerializerCore.FromFeedStream( CosmosFeedResponseSerializer.GetStreamWithoutServiceEnvelope(responseMessage.Content)); Assert.AreEqual(items.Length, 5); } @@ -323,7 +323,7 @@ public async Task ReadManyTestWithIncorrectIntendedContainerRid() Assert.IsTrue(responseMessage.Headers.RequestCharge > 0); Assert.IsNotNull(responseMessage.Diagnostics); - ToDoActivity[] items = this.cosmosClient.ClientContext.SerializerCore.FromFeedStream( + ToDoActivity[] items = this.GetClient().ClientContext.SerializerCore.FromFeedStream( CosmosFeedResponseSerializer.GetStreamWithoutServiceEnvelope(responseMessage.Content)); Assert.AreEqual(items.Length, 2); } @@ -332,7 +332,7 @@ public async Task ReadManyTestWithIncorrectIntendedContainerRid() [TestMethod] public async Task ReadMany404ExceptionTest() { - Database database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); + Database database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk"); for (int i = 0; i < 5; i++) { @@ -483,7 +483,7 @@ public async Task ReadManyExceptionsTest(HttpStatusCode statusCode) CosmosClientBuilder builder = TestCommon.GetDefaultConfiguration(); builder.AddCustomHandlers(requestHandlers); - CosmosClient client = builder.Build(); + using CosmosClient client = builder.Build(); Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/pk"); for (int i = 0; i < 5; i++) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosUserTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosUserTests.cs index a0b849c775..f5943a4d66 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosUserTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosUserTests.cs @@ -5,45 +5,23 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Linq; using System.Net; using System.Threading.Tasks; - using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json.Linq; [TestClass] - public class CosmosUserTests + public class CosmosUserTests : BaseCosmosClientHelper { - - private CosmosClient cosmosClient = null; - private Cosmos.Database cosmosDatabase = null; - [TestInitialize] - public async Task TestInit() + public async Task TestInitialize() { - this.cosmosClient = TestCommon.CreateCosmosClient(); - - string databaseName = Guid.NewGuid().ToString(); - DatabaseResponse cosmosDatabaseResponse = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(databaseName); - this.cosmosDatabase = cosmosDatabaseResponse; + await base.TestInit(); } [TestCleanup] - public async Task TestCleanup() + public async Task Cleanup() { - if (this.cosmosClient == null) - { - return; - } - - if (this.cosmosDatabase != null) - { - await this.cosmosDatabase.DeleteStreamAsync(); - } - this.cosmosClient.Dispose(); + await base.TestCleanup(); } [TestMethod] @@ -51,7 +29,7 @@ public async Task CRUDTest() { string userId = Guid.NewGuid().ToString(); - UserResponse userResponse = await this.cosmosDatabase.CreateUserAsync(userId); + UserResponse userResponse = await this.database.CreateUserAsync(userId); Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode); Assert.AreEqual(userId, userResponse.Resource.Id); Assert.IsNotNull(userResponse.Resource.ResourceId); @@ -60,21 +38,21 @@ public async Task CRUDTest() string newUserId = Guid.NewGuid().ToString(); userResponse.Resource.Id = newUserId; - userResponse = await this.cosmosDatabase.GetUser(userId).ReplaceAsync(userResponse.Resource); + userResponse = await this.database.GetUser(userId).ReplaceAsync(userResponse.Resource); Assert.AreEqual(HttpStatusCode.OK, userResponse.StatusCode); Assert.AreEqual(newUserId, userResponse.Resource.Id); SelflinkValidator.ValidateUserSelfLink(userResponse.Resource.SelfLink); - userResponse = await this.cosmosDatabase.GetUser(userResponse.Resource.Id).ReadAsync(); + userResponse = await this.database.GetUser(userResponse.Resource.Id).ReadAsync(); Assert.AreEqual(HttpStatusCode.OK, userResponse.StatusCode); Assert.AreEqual(newUserId, userResponse.Resource.Id); SelflinkValidator.ValidateUserSelfLink(userResponse.Resource.SelfLink); - userResponse = await this.cosmosDatabase.GetUser(newUserId).DeleteAsync(); + userResponse = await this.database.GetUser(newUserId).DeleteAsync(); Assert.AreEqual(HttpStatusCode.NoContent, userResponse.StatusCode); userId = Guid.NewGuid().ToString(); - userResponse = await this.cosmosDatabase.UpsertUserAsync(userId); + userResponse = await this.database.UpsertUserAsync(userId); Assert.AreEqual(HttpStatusCode.Created, userResponse.StatusCode); Assert.AreEqual(userId, userResponse.Resource.Id); Assert.IsNotNull(userResponse.Resource.ResourceId); @@ -82,7 +60,7 @@ public async Task CRUDTest() newUserId = Guid.NewGuid().ToString(); userResponse.Resource.Id = newUserId; - userResponse = await this.cosmosDatabase.UpsertUserAsync(userResponse.Resource.Id); + userResponse = await this.database.UpsertUserAsync(userResponse.Resource.Id); Assert.AreEqual(newUserId, userResponse.Resource.Id); SelflinkValidator.ValidateUserSelfLink(userResponse.Resource.SelfLink); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs index 74eb1dbced..227f308baf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DocumentClientUnitTests.cs @@ -40,7 +40,7 @@ public void NoRetryOnThrottledOverride() } [TestMethod] - public void RetryExceedingMaxTimeLimit() + public async Task RetryExceedingMaxTimeLimit() { Mock mockStoreModel = new Mock(); mockStoreModel.Setup(model => model.ProcessMessageAsync(It.IsAny(), default(CancellationToken))) @@ -52,13 +52,13 @@ public void RetryExceedingMaxTimeLimit() RetryOptions = new RetryOptions { MaxRetryAttemptsOnThrottledRequests = 100, MaxRetryWaitTimeInSeconds = 1 } }; - DocumentClient client = new DocumentClient( + using DocumentClient client = new DocumentClient( new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), ConfigurationManager.AppSettings["MasterKey"], (HttpMessageHandler)null, connectionPolicy); - client.GetDatabaseAccountAsync().Wait(); + await client.GetDatabaseAccountAsync(); int expectedExecutionTimes = 11; @@ -68,11 +68,10 @@ public void RetryExceedingMaxTimeLimit() try { Database db = new Database { Id = "test db 1" }; - client.CreateDatabaseAsync(db).Wait(); + await client.CreateDatabaseAsync(db); } - catch (Exception exp) + catch (DocumentClientException docExp) { - DocumentClientException docExp = exp.InnerException as DocumentClientException; Assert.AreEqual((HttpStatusCode)429, docExp.StatusCode); throttled = true; } @@ -97,7 +96,7 @@ public async Task OpenConnectionsToAllReplicasAsync_WithEmptyDatabaseName_Should RetryOptions = new RetryOptions { MaxRetryAttemptsOnThrottledRequests = 100, MaxRetryWaitTimeInSeconds = 1 } }; - DocumentClient client = new ( + using DocumentClient client = new ( new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), ConfigurationManager.AppSettings["MasterKey"], (HttpMessageHandler)null, @@ -139,13 +138,13 @@ public async Task OpenConnectionsToAllReplicasAsync_WhenStoreModelThrowsInternal RetryOptions = new RetryOptions { MaxRetryAttemptsOnThrottledRequests = 100, MaxRetryWaitTimeInSeconds = 1 } }; - DocumentClient client = new ( + using DocumentClient client = new ( new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), ConfigurationManager.AppSettings["MasterKey"], (HttpMessageHandler)null, connectionPolicy); - client.GetDatabaseAccountAsync().Wait(); + await client.GetDatabaseAccountAsync(); client.StoreModel = mockStoreModel.Object; client.GatewayStoreModel = mockStoreModel.Object; @@ -167,7 +166,7 @@ public async Task OpenConnectionsToAllReplicasAsync_WhenStoreModelThrowsInternal [TestMethod] public async Task QueryPartitionProviderSingletonTestAsync() { - DocumentClient client = new DocumentClient( + using DocumentClient client = new DocumentClient( new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), ConfigurationManager.AppSettings["MasterKey"], (HttpMessageHandler)null, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs index b9d179c0c1..4a1d92c59c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs @@ -707,8 +707,8 @@ public async Task TestCancellationTokenAsync() await this.CreateRandomItems(itemsCore, 100, randomPartitionKey: true); // Inject validating handler - RequestHandler currentInnerHandler = this.cosmosClient.RequestHandler.InnerHandler; - this.cosmosClient.RequestHandler.InnerHandler = cancellationTokenHandler; + RequestHandler currentInnerHandler = this.GetClient().RequestHandler.InnerHandler; + this.GetClient().RequestHandler.InnerHandler = cancellationTokenHandler; cancellationTokenHandler.InnerHandler = currentInnerHandler; { @@ -808,17 +808,13 @@ public async Task ChangeFeedIteratorCore_WithQuery() private async Task ValidateChangeFeedIteratorCore_WithQuery( bool useGateway) { - await this.Cleanup(); - this.cancellationTokenSource = new CancellationTokenSource(); this.cancellationToken = this.cancellationTokenSource.Token; - this.cosmosClient = TestCommon.CreateCosmosClient(useGateway: useGateway); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), - cancellationToken: this.cancellationToken); + CosmosClient cosmosClient = useGateway ? TestCommon.CreateCosmosClient(useGateway: useGateway) : this.GetClient(); ContainerProperties properties = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pkey"); properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5); - ContainerResponse response = await this.database.CreateContainerAsync( + ContainerResponse response = await cosmosClient.GetDatabase(this.database.Id).CreateContainerAsync( properties, cancellationToken: this.cancellationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs index 1e26ef0738..df61615fe6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs @@ -50,7 +50,7 @@ public async Task GetTargetPartitionKeyRangesAsyncWithFeedRange() container = (ContainerInlineCore)containerResponse; // Get all the partition key ranges to verify there is more than one partition - IRoutingMapProvider routingMapProvider = await this.cosmosClient.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); + IRoutingMapProvider routingMapProvider = await this.GetClient().DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties( containerResponse.Resource.ResourceId, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs index 9c1724fc26..9de85f9f7e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs @@ -315,7 +315,7 @@ await this.database.DefineContainer(containerName, partitionKeyPath) [TestMethod] public async Task TestConflictResolutionPolicy() { - Database databaseForConflicts = await this.cosmosClient.CreateDatabaseAsync("conflictResolutionContainerTest", + Database databaseForConflicts = await this.GetClient().CreateDatabaseAsync("conflictResolutionContainerTest", cancellationToken: this.cancellationToken); try @@ -368,7 +368,7 @@ await databaseForConflicts.DefineContainer(containerName, partitionKeyPath) [TestMethod] public async Task TestChangeFeedPolicy() { - Database databaseForChangeFeed = await this.cosmosClient.CreateDatabaseAsync("changeFeedRetentionContainerTest", + Database databaseForChangeFeed = await this.GetClient().CreateDatabaseAsync("changeFeedRetentionContainerTest", cancellationToken: this.cancellationToken); try diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayClientSideRequestStatsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayClientSideRequestStatsTests.cs index 8d65a5e7f0..3a5e08a2fc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayClientSideRequestStatsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayClientSideRequestStatsTests.cs @@ -8,7 +8,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Net.Http; using System.Threading; using System.Threading.Tasks; - using Antlr4.Runtime.Tree; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs index 0d7eaa7ea5..41ccbc2da4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/GatewayTests.cs @@ -739,25 +739,25 @@ private async Task CreateTriggerAndValidateAsync(DocumentClient client, } [TestMethod] - public void ValidateTriggers() + public async Task ValidateTriggers() { - this.ValidateTriggersInternal(Protocol.Https, ConsistencyLevel.Session); - this.ValidateTriggersInternal(Protocol.Tcp, ConsistencyLevel.Session); + await this.ValidateTriggersInternal(Protocol.Https, ConsistencyLevel.Session); + await this.ValidateTriggersInternal(Protocol.Tcp, ConsistencyLevel.Session); } - internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, ConsistencyLevel? consistencyLevel = null) + internal async Task ValidateTriggersInternal(Protocol protocol = Protocol.Https, ConsistencyLevel? consistencyLevel = null) { #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - DocumentClient client = TestCommon.CreateClient(false, protocol: protocol, defaultConsistencyLevel: consistencyLevel); + using DocumentClient client = TestCommon.CreateClient(false, protocol: protocol, defaultConsistencyLevel: consistencyLevel); #endif #if !DIRECT_MODE - DocumentClient client = TestCommon.CreateClient(true, defaultConsistencyLevel: consistencyLevel); + using DocumentClient client = TestCommon.CreateClient(true, defaultConsistencyLevel: consistencyLevel); #endif TestCommon.DeleteAllDatabasesAsync().Wait(); Documents.Database database = TestCommon.CreateOrGetDatabase(client); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; - DocumentCollection collection1 = TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + DocumentCollection collection1 = await TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }); // 1. Basic tests @@ -773,7 +773,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - Trigger retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection1, t1).Result; + Trigger retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection1, t1); dynamic doct1 = GatewayTests.CreateDocument(client, this.baseUri, collection1, "Doc1", "empty", 0, pretrigger: "t1"); Assert.AreEqual("DOC1t1", doct1.Id); @@ -791,7 +791,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection1, response1).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection1, response1); dynamic docresponse1 = GatewayTests.CreateDocument(client, this.baseUri, collection1, "testing post trigger", "empty", 0, pretrigger: "t1", posttrigger: "response1"); Assert.AreEqual("TESTING POST TRIGGERt1", docresponse1.Id); @@ -809,7 +809,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection1, response2).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection1, response2); dynamic docresponse2 = GatewayTests.CreateDocument(client, this.baseUri, collection1, "post trigger output", "empty", 0, pretrigger: "t1", posttrigger: "response2"); Assert.AreEqual("POST TRIGGER OUTPUTt1POST TRIGGER OUTPUTt1response2", docresponse2.Id); @@ -842,7 +842,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection1, response3).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection1, response3); dynamic docresponse3 = GatewayTests.CreateDocument(client, this.baseUri, collection1, "testing post trigger2", "empty", 0, pretrigger: "t1", posttrigger: "response3"); Assert.AreEqual("TESTING POST TRIGGER2t1", docresponse3.Id); @@ -857,7 +857,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, t2).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, t2); dynamic doct2 = GatewayTests.CreateDocument(client, this.baseUri, collection2, "Doc2", "Prop1Value", 101, pretrigger: "t2"); Assert.AreEqual("Doc2", doct2.Id); @@ -874,7 +874,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, t3).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, t3); dynamic doct3 = GatewayTests.CreateDocument(client, this.baseUri, collection2, "Doc3", "empty", 0, pretrigger: "t3"); Assert.AreEqual("doc3t3", doct3.Id); @@ -887,7 +887,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, triggerTypeMismatch).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, triggerTypeMismatch); bool exceptionThrown = false; try @@ -909,7 +909,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, preTriggerThatThrows).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, preTriggerThatThrows); try { @@ -931,7 +931,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, postTriggerThatThrows).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, postTriggerThatThrows); try { @@ -954,13 +954,12 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi }; try { - Trigger retrievedTriggerNoBody = client.CreateTriggerAsync(collection2, triggerNoBody).Result; + Trigger retrievedTriggerNoBody = await client.CreateTriggerAsync(collection2, triggerNoBody); } catch (Exception ex) { Assert.IsNotNull(ex); - Assert.IsNotNull(ex.InnerException); - Assert.IsTrue(ex.InnerException.Message.Contains("The input content is invalid because the required properties - 'body; ' - are missing")); + Assert.IsTrue(ex.Message.Contains("The input content is invalid because the required properties - 'body; ' - are missing")); } // failure test - trigger without trigger type @@ -972,13 +971,12 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi }; try { - Trigger retrievedTriggerNoType = client.CreateTriggerAsync(collection2, triggerNoType).Result; + Trigger retrievedTriggerNoType = await client.CreateTriggerAsync(collection2, triggerNoType); } catch (Exception ex) { Assert.IsNotNull(ex); - Assert.IsNotNull(ex.InnerException); - Assert.IsTrue(ex.InnerException.Message.Contains("The input content is invalid because the required properties - 'triggerType; ' - are missing")); + Assert.IsTrue(ex.Message.Contains("The input content is invalid because the required properties - 'triggerType; ' - are missing")); } // failure test - trigger without trigger operation @@ -990,13 +988,12 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi }; try { - Trigger retrievedTriggerNoType = client.CreateTriggerAsync(collection2, triggerNoOperation).Result; + Trigger retrievedTriggerNoType = await client.CreateTriggerAsync(collection2, triggerNoOperation); } catch (Exception ex) { Assert.IsNotNull(ex); - Assert.IsNotNull(ex.InnerException); - Assert.IsTrue(ex.InnerException.Message.Contains("The input content is invalid because the required properties - 'triggerOperation; ' - are missing")); + Assert.IsTrue(ex.Message.Contains("The input content is invalid because the required properties - 'triggerOperation; ' - are missing")); } // TODO: uncomment when preserializedScripts is enabled. @@ -1028,14 +1025,11 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi }; try { - dbToCreate = client.CreateDatabaseAsync(dbToCreate, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1" } }).Result; + dbToCreate = await client.CreateDatabaseAsync(dbToCreate, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1" } }); } - catch (Exception e) + catch (DocumentClientException de) { - Assert.IsNotNull(e); - Assert.IsNotNull(e.InnerException); - - DocumentClientException de = e.InnerException as DocumentClientException; + Assert.IsNotNull(de); Assert.AreEqual(HttpStatusCode.BadRequest.ToString(), de.Error.Code); } @@ -1098,12 +1092,12 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection2, request1).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection2, request1); dynamic docrequest1 = GatewayTests.CreateDocument(client, this.baseUri, collection2, "abc", "empty", 0, pretrigger: "request1"); Assert.AreEqual("def", docrequest1.Id); - DocumentCollection collection3 = TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + DocumentCollection collection3 = await TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }); // set request body multiple times Trigger request2 = new Trigger @@ -1120,7 +1114,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, request2).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, request2); dynamic docrequest2 = GatewayTests.CreateDocument(client, this.baseUri, collection3, "doc", "empty", 0, pretrigger: "request2"); Assert.AreEqual(203, docrequest2.Id.Length); @@ -1142,7 +1136,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, request3).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, request3); dynamic docrequest3 = GatewayTests.CreateDocument(client, this.baseUri, collection3, "noname", "empty", 0, pretrigger: "request3"); Assert.AreEqual("noresponse", docrequest3.Id); @@ -1164,9 +1158,9 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Pre, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, request4).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, request4); - ResourceResponse docrequest4 = client.CreateDocumentAsync(collection3, new Document { Id = "noname" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "request4" } }).Result; + ResourceResponse docrequest4 = await client.CreateDocumentAsync(collection3, new Document { Id = "noname" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "request4" } }); Assert.IsTrue(docrequest4.Resource.Id == "noheaders"); Assert.IsTrue(docrequest4.ResponseHeaders["Test"] == null); @@ -1186,9 +1180,9 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, responseQuotaHeader).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, responseQuotaHeader); - Book docresponseQuotaHeader = (dynamic)client.CreateDocumentAsync(collection3, new Book { Id = "quotaDocument" }, new Documents.Client.RequestOptions { PostTriggerInclude = new List { "responseQuotaHeader" } }).Result.Resource; + Book docresponseQuotaHeader = (await (dynamic)client.CreateDocumentAsync(collection3, new Book { Id = "quotaDocument" }, new Documents.Client.RequestOptions { PostTriggerInclude = new List { "responseQuotaHeader" } })).Resource; Assert.IsTrue(docresponseQuotaHeader.Author.Contains("collectionSize")); Assert.IsTrue(docresponseQuotaHeader.Title.Contains("collectionSize")); @@ -1202,7 +1196,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.Delete }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, triggerOpType).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, triggerOpType); exceptionThrown = false; try @@ -1224,7 +1218,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection3, triggerAbortTransaction).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection3, triggerAbortTransaction); exceptionThrown = false; try @@ -1244,7 +1238,7 @@ internal void ValidateTriggersInternal(Protocol protocol = Protocol.Https, Consi Assert.AreNotEqual(doc.Id, "Docabort"); // make sure the doc isnt present } - DocumentCollection collection4 = TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + DocumentCollection collection4 = await TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }); // delete post trigger Trigger deletePostTrigger = new Trigger @@ -1280,7 +1274,7 @@ function callback(err, docFeed, responseOptions) TriggerType = Documents.TriggerType.Post, TriggerOperation = Documents.TriggerOperation.All }; - retrievedTrigger = this.CreateTriggerAndValidateAsync(client, collection4, deletePostTrigger).Result; + retrievedTrigger = await this.CreateTriggerAndValidateAsync(client, collection4, deletePostTrigger); dynamic docDeletePostTrigger = null; try @@ -1307,12 +1301,10 @@ function callback(err, docFeed, responseOptions) exceptionThrown = false; try { - Document doc5 = client.CreateDocumentAsync(collection4, new Document { Id = "Doc5" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1", "t3" } }).Result.Resource; + Document doc5 = (await client.CreateDocumentAsync(collection4, new Document { Id = "Doc5" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1", "t3" } })).Resource; } - catch (Exception e) + catch (DocumentClientException de) { - Assert.IsNotNull(e); - DocumentClientException de = e.InnerException as DocumentClientException; Assert.IsNotNull(de); exceptionThrown = true; } @@ -1321,17 +1313,20 @@ function callback(err, docFeed, responseOptions) exceptionThrown = false; try { - ResourceResponse docMultiple1 = client.CreateDocumentAsync(collection4, new Document { Id = "multipleHeaders1" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1" }, PostTriggerInclude = new List { "response2", "multiple1" } }).Result; + ResourceResponse docMultiple1 = await client.CreateDocumentAsync(collection4, new Document { Id = "multipleHeaders1" }, new Documents.Client.RequestOptions { PreTriggerInclude = new List { "t1" }, PostTriggerInclude = new List { "response2", "multiple1" } }); } - catch (Exception e) + catch (DocumentClientException de) { - Assert.IsNotNull(e); - DocumentClientException de = e.InnerException as DocumentClientException; Assert.IsNotNull(de); exceptionThrown = true; } Assert.IsTrue(exceptionThrown, "multiple post-triggers didn't cause failure"); + if (dbToCreate != null) + { + await client.DeleteDatabaseAsync(database); + } + // re-enable these tests if we re-enable multiple triggers // // pre-trigger request body // Document doc5 = client.CreateDocumentAsync(collection1, new Document { Id = "Doc5" }, new RequestOptions { PreTriggerInclude = new List { "t1", "t3" } }).Result.Resource; @@ -1384,7 +1379,7 @@ function callback(err, docFeed, responseOptions) [TestMethod] public async Task ValidateLongProcessingStoredProcedures() { - CosmosClient client = TestCommon.CreateCosmosClient(true); + using CosmosClient client = TestCommon.CreateCosmosClient(true); Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; @@ -1422,7 +1417,7 @@ function callback(err, docFeed, responseOptions) { [TestMethod] public async Task ValidateSprocWithFailedUpdates() { - CosmosClient client = TestCommon.CreateCosmosClient(true); + using CosmosClient client = TestCommon.CreateCosmosClient(true); Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; @@ -1468,7 +1463,7 @@ public async Task ValidateSprocWithFailedUpdates() } catch (DocumentClientException exception) { - Assert.Fail("Exception should not have occurred. {0}", exception.InnerException.ToString()); + Assert.Fail("Exception should not have occurred. {0}", exception.ToString()); } await database.DeleteAsync(); } @@ -1485,7 +1480,7 @@ public async Task ValidateSystemSproc() internal async Task ValidateSystemSprocInternal(bool useGateway, Protocol protocol = Protocol.Tcp) { - CosmosClient client = TestCommon.CreateCosmosClient(useGateway); + using CosmosClient client = TestCommon.CreateCosmosClient(useGateway); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); ContainerProperties collectionSpec = new ContainerProperties @@ -2238,13 +2233,13 @@ await masterClient.CreateStoredProcedureAsync(UriFactory.CreateDocumentCollectio } [TestMethod] - public void ValidateStoredProceduresBlacklisting() + public async Task ValidateStoredProceduresBlacklisting() { try { TestCommon.SetDoubleConfigurationProperty("StoredProcedureMaximumChargeInSeconds", 0.0); TestCommon.WaitForConfigRefresh(); - this.ValidateStoredProceduresBlacklistingInternal(); + await this.ValidateStoredProceduresBlacklistingInternal(); } finally { @@ -2253,14 +2248,14 @@ public void ValidateStoredProceduresBlacklisting() } } - public void ValidateStoredProceduresBlacklistingInternal() + public async Task ValidateStoredProceduresBlacklistingInternal() { - DocumentClient client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); Documents.Database database = TestCommon.CreateOrGetDatabase(client); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; DocumentCollection inputCollection = new DocumentCollection { Id = "ValidateStoredProceduresBlacklisting" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }; - DocumentCollection collection = TestCommon.CreateCollectionAsync(client, database, inputCollection).Result; + DocumentCollection collection = await TestCommon.CreateCollectionAsync(client, database, inputCollection); string badScript = @"function() { var start = new Date(); @@ -2301,18 +2296,20 @@ public void ValidateStoredProceduresBlacklistingInternal() isBlacklisted = true; } + await client.DeleteDatabaseAsync(database); + Assert.IsTrue(isBlacklisted); } [TestMethod] - public void ValidateUserDefinedFunctions() + public async Task ValidateUserDefinedFunctions() { - DocumentClient client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); - DocumentClient secondary1Client = TestCommon.CreateClient(false, Protocol.Tcp); + using DocumentClient secondary1Client = TestCommon.CreateClient(false, Protocol.Tcp); secondary1Client.LockClient(1); - DocumentClient secondary2Client = TestCommon.CreateClient(false, Protocol.Tcp); + using DocumentClient secondary2Client = TestCommon.CreateClient(false, Protocol.Tcp); secondary1Client.LockClient(2); Documents.Database database = TestCommon.CreateOrGetDatabase(client); @@ -2333,7 +2330,7 @@ public void ValidateUserDefinedFunctions() if(label.toLowerCase() == testLabel.toLowerCase()) return true; };", }; - UserDefinedFunction retrievedUdf = client.CreateUserDefinedFunctionAsync(collection.UserDefinedFunctionsLink, udf1).Result; + UserDefinedFunction retrievedUdf = await client.CreateUserDefinedFunctionAsync(collection.UserDefinedFunctionsLink, udf1); this.Retry(() => { @@ -2362,13 +2359,12 @@ public void ValidateUserDefinedFunctions() }; try { - UserDefinedFunction retrievedUdfNoBody = client.CreateUserDefinedFunctionAsync(collection.UserDefinedFunctionsLink, udfNoBody).Result; + UserDefinedFunction retrievedUdfNoBody = await client.CreateUserDefinedFunctionAsync(collection.UserDefinedFunctionsLink, udfNoBody); } catch (Exception ex) { Assert.IsNotNull(ex); - Assert.IsNotNull(ex.InnerException); - Assert.IsTrue(ex.InnerException.Message.Contains("The input content is invalid because the required properties - 'body; ' - are missing")); + Assert.IsTrue(ex.Message.Contains("The input content is invalid because the required properties - 'body; ' - are missing")); } // failure test - UDF that throws specific error number. @@ -2396,6 +2392,8 @@ public void ValidateUserDefinedFunctions() } } + await client.DeleteDatabaseAsync(database); + // // precompilation should catch errors on create // UserDefinedFunction udfSyntaxError = new UserDefinedFunction // { @@ -2421,13 +2419,13 @@ public void ValidateUserDefinedFunctions() } [TestMethod] - public void ValidateUserDefinedFunctionsBlacklisting() + public async Task ValidateUserDefinedFunctionsBlacklisting() { try { TestCommon.SetDoubleConfigurationProperty("UdfMaximumChargeInSeconds", 0.0); TestCommon.WaitForConfigRefresh(); - this.ValidateUserDefinedFunctionsBlacklistingInternal(); + await this.ValidateUserDefinedFunctionsBlacklistingInternal(); } finally { @@ -2436,9 +2434,9 @@ public void ValidateUserDefinedFunctionsBlacklisting() } } - public void ValidateUserDefinedFunctionsBlacklistingInternal() + public async Task ValidateUserDefinedFunctionsBlacklistingInternal() { - DocumentClient client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); Documents.Database database = TestCommon.CreateOrGetDatabase(client); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; @@ -2457,7 +2455,7 @@ public void ValidateUserDefinedFunctionsBlacklistingInternal() return name; }" }; - UserDefinedFunction udf = client.CreateUserDefinedFunctionAsync(collection, udfSpec).Result; + UserDefinedFunction udf = await client.CreateUserDefinedFunctionAsync(collection, udfSpec); DocumentClient secondaryClient = TestCommon.CreateClient(false); secondaryClient.LockClient(1); // lock so we can get reliable blacklistling @@ -2468,18 +2466,18 @@ public void ValidateUserDefinedFunctionsBlacklistingInternal() "select udf.badUdf(r.id) from root r", new FeedOptions { EnableCrossPartitionQuery = true }).AsDocumentQuery(); // with 0 docs, UDF shouldn't be blacklisted - DocumentFeedResponse docCollection = docQuery.ExecuteNextAsync().Result; + DocumentFeedResponse docCollection = await docQuery.ExecuteNextAsync(); Assert.AreEqual(0, docCollection.Count); } // create one doc and try again - client.CreateDocumentAsync(collection, new Document() { Id = "newdoc1" }).Wait(); + await client.CreateDocumentAsync(collection, new Document() { Id = "newdoc1" }); for (int i = 0; i < 3; i++) { IDocumentQuery docQuery2 = secondaryClient.CreateDocumentQuery(collection.DocumentsLink, "select udf.badUdf(r.id) from root r", new FeedOptions { EnableCrossPartitionQuery = true }).AsDocumentQuery(); - DocumentFeedResponse docCollection2 = docQuery2.ExecuteNextAsync().Result; + DocumentFeedResponse docCollection2 = await docQuery2.ExecuteNextAsync(); } IDocumentQuery docQuery2BlackListed = secondaryClient.CreateDocumentQuery(collection.DocumentsLink, @@ -2488,12 +2486,10 @@ public void ValidateUserDefinedFunctionsBlacklistingInternal() bool isBlacklisted = false; try { - DocumentFeedResponse docCollection2 = docQuery2BlackListed.ExecuteNextAsync().Result; + DocumentFeedResponse docCollection2 = await docQuery2BlackListed.ExecuteNextAsync(); } - catch (Exception e) + catch (DocumentClientException de) { - Assert.IsNotNull(e); - DocumentClientException de = e.InnerException as DocumentClientException; Assert.IsNotNull(de); Assert.AreEqual(HttpStatusCode.Forbidden.ToString(), de.Error.Code); Assert.IsTrue(de.Message.Contains("is blocked for execution because it has violated its allowed resources limit several times.")); @@ -2511,7 +2507,7 @@ public void ValidateUserDefinedFunctionsBlacklistingInternal() // create lots of documents for (int i = 0; i < 1000; i++) { - client.CreateDocumentAsync(collection2, new Document() { Id = "newdoc" + Guid.NewGuid().ToString() }).Wait(); + await client.CreateDocumentAsync(collection2, new Document() { Id = "newdoc" + Guid.NewGuid().ToString() }); } UserDefinedFunction udfSpec2 = new UserDefinedFunction @@ -2519,12 +2515,15 @@ public void ValidateUserDefinedFunctionsBlacklistingInternal() Id = "goodUdf", Body = "function(name) { return name; }" }; - UserDefinedFunction udf2 = client.CreateUserDefinedFunctionAsync(collection2, udfSpec2).Result; + UserDefinedFunction udf2 = await client.CreateUserDefinedFunctionAsync(collection2, udfSpec2); IDocumentQuery docQuery3 = secondaryClient.CreateDocumentQuery(collection2.DocumentsLink, "select udf.goodUdf(r.id) from root r", new FeedOptions { MaxItemCount = 1000, EnableCrossPartitionQuery = true }).AsDocumentQuery(); - DocumentFeedResponse docCollection3 = docQuery3.ExecuteNextAsync().Result; + DocumentFeedResponse docCollection3 = await docQuery3.ExecuteNextAsync(); + + await client.DeleteDatabaseAsync(database); + Assert.AreEqual(1000, docCollection3.Count); } @@ -2541,7 +2540,7 @@ public async Task ValidateChangeFeedIfNoneMatch() private async Task ValidateChangeFeedIfNoneMatchHelper(bool useGateway, Protocol protocol = Protocol.Tcp) { - DocumentClient client = TestCommon.CreateClient(useGateway, protocol); + using DocumentClient client = TestCommon.CreateClient(useGateway, protocol); ResourceResponse db = await client.CreateDatabaseAsync(new Documents.Database() { Id = Guid.NewGuid().ToString() }); try { @@ -2673,7 +2672,7 @@ private async Task ValidateChangeFeedIfNoneMatchHelper(bool useGateway, Protocol } finally { - client.DeleteDatabaseAsync(db).Wait(); + await client.DeleteDatabaseAsync(db); } } @@ -2690,7 +2689,7 @@ public async Task ValidateChangeFeedIfModifiedSince() private async Task ValidateChangeFeedIfModifiedSinceHelper(bool useGateway, Protocol protocol = Protocol.Tcp) { - DocumentClient client = TestCommon.CreateClient(useGateway, protocol); + using DocumentClient client = TestCommon.CreateClient(useGateway, protocol); ResourceResponse db = await client.CreateDatabaseAsync(new Documents.Database() { Id = Guid.NewGuid().ToString() }); try { @@ -2788,7 +2787,7 @@ private async Task ValidateChangeFeedIfModifiedSinceHelper(bool useGateway, Prot } finally { - client.DeleteDatabaseAsync(db).Wait(); + await client.DeleteDatabaseAsync(db); } } @@ -2840,7 +2839,7 @@ private async Task GetPKRangeIdForPartitionKey( private async Task ValidateChangeFeedWithPartitionKeyHelper(bool useGateway, Protocol protocol = Protocol.Tcp) { - DocumentClient client = TestCommon.CreateClient(useGateway, protocol); + using DocumentClient client = TestCommon.CreateClient(useGateway, protocol); Documents.Database db = await client.CreateDatabaseAsync(new Documents.Database() { Id = Guid.NewGuid().ToString() }); string pk1 = "4", pk2 = "6", pk3 = "22"; // The values are chosen in such a way that hash lands on the same range. @@ -2928,7 +2927,7 @@ private async Task ValidateChangeFeedWithPartitionKeyHelper(bool useGateway, Pro } finally { - client.DeleteDatabaseAsync(db).Wait(); + await client.DeleteDatabaseAsync(db); } } @@ -2978,7 +2977,7 @@ public async Task ValidateReadPartitionKeyRange() private async Task ValidateReadPartitionKeyRangeHelper(bool useGateway, Protocol protocol = Protocol.Tcp) { - DocumentClient client = TestCommon.CreateClient(useGateway, protocol); + using DocumentClient client = TestCommon.CreateClient(useGateway, protocol); Documents.Database db = await client.CreateDatabaseAsync(new Documents.Database() { Id = Guid.NewGuid().ToString() }); try { @@ -3020,14 +3019,14 @@ private async Task ValidateReadPartitionKeyRangeHelper(bool useGateway, Protocol } finally { - client.DeleteDatabaseAsync(db).Wait(); + await client.DeleteDatabaseAsync(db); } } [TestMethod] public async Task ValidateStoredProcedureExecutionWithPartitionKey() { - DocumentClient client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); await TestCommon.DeleteAllDatabasesAsync(); Documents.Database database = await client.CreateDatabaseAsync(new Documents.Database { Id = "db" }); @@ -3064,26 +3063,27 @@ public async Task ValidateStoredProcedureExecutionWithPartitionKey() new Documents.Client.RequestOptions { PartitionKey = new Documents.PartitionKey("1") }, "DocumentDB").Result; Assert.IsTrue(string.CompareOrdinal(output, "Hello World, DocumentDB!") == 0); - client.DeleteStoredProcedureAsync(UriFactory.CreateStoredProcedureUri(database.Id, collection.Id, sproc.Id)).Wait(); + await client.DeleteStoredProcedureAsync(UriFactory.CreateStoredProcedureUri(database.Id, collection.Id, sproc.Id)); + await client.DeleteDatabaseAsync(database); } [TestMethod] - public void ValidateGenericReadDocumentGateway() + public async Task ValidateGenericReadDocumentGateway() { - this.ValidateGenericReadDocument(true, Protocol.Https).Wait(); - this.ValidateGenericReadDocumentFromResource(true, Protocol.Https).Wait(); + await this.ValidateGenericReadDocument(true, Protocol.Https); + await this.ValidateGenericReadDocumentFromResource(true, Protocol.Https); } [TestMethod] - public void ValidateGenericReadDocumentDirectTcp() + public async Task ValidateGenericReadDocumentDirectTcp() { - this.ValidateGenericReadDocument(false, Protocol.Tcp).Wait(); - this.ValidateGenericReadDocumentFromResource(false, Protocol.Tcp).Wait(); + await this.ValidateGenericReadDocument(false, Protocol.Tcp); + await this.ValidateGenericReadDocumentFromResource(false, Protocol.Tcp); } private async Task ValidateGenericReadDocument(bool useGateway, Protocol protocol) { - CosmosClient client = TestCommon.CreateCosmosClient(useGateway); + using CosmosClient client = TestCommon.CreateCosmosClient(useGateway); Cosmos.Database database = await client.CreateDatabaseIfNotExistsAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; @@ -3122,7 +3122,7 @@ private async Task ValidateGenericReadDocument(bool useGateway, Protocol protoco private async Task ValidateGenericReadDocumentFromResource(bool useGateway, Protocol protocol) { - CosmosClient client = TestCommon.CreateCosmosClient(useGateway); + using CosmosClient client = TestCommon.CreateCosmosClient(useGateway); Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; @@ -3156,16 +3156,18 @@ private async Task ValidateGenericReadDocumentFromResource(bool useGateway, Prot // This tests the implicit operator for ReadDocumentAsync CustomerObjectFromResource doc1 = await collection.ReadItemAsync(partitionKey: new Cosmos.PartitionKey(customerObjectFromResource.id), id: customerObjectFromResource.id); Assert.IsNotNull(doc1.id); + + await database.DeleteStreamAsync(); } [TestMethod] - public void ValidatePOCODocumentSerialization() + public async Task ValidatePOCODocumentSerialization() { // 1. Verify the customer can serialize their POCO object in their own ways - DocumentClient client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); Documents.Database database = TestCommon.CreateOrGetDatabase(client); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; - DocumentCollection collection1 = TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + DocumentCollection collection1 = await TestCommon.CreateCollectionAsync(client, database, new DocumentCollection { Id = "TestTriggers" + Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }); CustomerPOCO poco = new CustomerPOCO() { @@ -3298,6 +3300,8 @@ public void ValidatePOCODocumentSerialization() CustomerObjectFromDocumentEx doc5 = (dynamic)client.CreateDocumentAsync(collection1, testobject5).Result.Resource; Assert.AreEqual(doc5.TestProperty, testobject5.TestProperty); Assert.IsFalse(doc5.ToString().Contains("TestProperty")); + + await client.DeleteDatabaseAsync(database); } [TestMethod] @@ -3305,10 +3309,10 @@ public async Task ValidateIndexingDirectives() { #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator - DocumentClient client = TestCommon.CreateClient(false); + using DocumentClient client = TestCommon.CreateClient(false); #endif #if !DIRECT_MODE - CosmosClient client = TestCommon.CreateCosmosClient(true); + using CosmosClient client = TestCommon.CreateCosmosClient(true); #endif Cosmos.Database database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString()); PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; @@ -3400,7 +3404,7 @@ public static string DumpFullExceptionMessage(Exception e) private async Task ValidateCollectionQuotaTestsWithFailure(bool useGateway) { - DocumentClient client = TestCommon.CreateClient(useGateway); + using DocumentClient client = TestCommon.CreateClient(useGateway); Documents.Database database = null; try { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs index be83b0e1fd..b24ce5f03b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs @@ -46,7 +46,7 @@ public async Task Startup() this.currentVersionUTF8 = HttpConstants.Versions.CurrentVersionUTF8; //var client = TestCommon.CreateClient(false, Protocol.Tcp); - var client = TestCommon.CreateClient(true); + using var client = TestCommon.CreateClient(true); await TestCommon.DeleteAllDatabasesAsync(); } @@ -60,14 +60,14 @@ public void TestCleanup() [TestMethod] public void ValidatePageSizeRntbd() { - var client = TestCommon.CreateClient(false, Protocol.Tcp); + using var client = TestCommon.CreateClient(false, Protocol.Tcp); ValidatePageSize(client); } [TestMethod] public void ValidatePageSizeGatway() { - var client = TestCommon.CreateClient(true); + using var client = TestCommon.CreateClient(true); ValidatePageSize(client); } @@ -506,7 +506,7 @@ private void ValidateEmitVerboseTracesInQuery(DocumentClient client, bool isHttp [TestMethod] public void ValidateIfNonMatchGateway() { - var client = TestCommon.CreateClient(true); + using var client = TestCommon.CreateClient(true); ValidateIfNonMatch(client); } @@ -514,7 +514,7 @@ public void ValidateIfNonMatchGateway() [TestMethod] public void ValidateIfNonMatchRntbd() { - var client = TestCommon.CreateClient(false, Protocol.Tcp); + using var client = TestCommon.CreateClient(false, Protocol.Tcp); ValidateIfNonMatch(client); } @@ -557,48 +557,45 @@ public void ValidateCustomUserAgentContainerHeader() } [TestMethod] - public void ValidateVersionHeader() + public async Task ValidateVersionHeader() { string correctVersion = HttpConstants.Versions.CurrentVersion; + Database db = null; try { DocumentClient client = TestCommon.CreateClient(true); - var db = client.CreateDatabaseAsync(new Database() { Id = Guid.NewGuid().ToString() }).Result.Resource; + db = (await client.CreateDatabaseAsync(new Database() { Id = Guid.NewGuid().ToString() })).Resource; PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; - var coll = client.CreateDocumentCollectionAsync(db.SelfLink, new DocumentCollection() { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result.Resource; - var doc = client.CreateDocumentAsync(coll.SelfLink, new Document()).Result.Resource; + var coll = (await client.CreateDocumentCollectionAsync(db.SelfLink, new DocumentCollection() { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition })).Resource; + var doc = (await client.CreateDocumentAsync(coll.SelfLink, new Document())).Resource; + client.Dispose(); client = TestCommon.CreateClient(true); - doc = client.CreateDocumentAsync(coll.SelfLink, new Document()).Result.Resource; + doc = (await client.CreateDocumentAsync(coll.SelfLink, new Document())).Resource; HttpConstants.Versions.CurrentVersion = "2015-01-01"; + client.Dispose(); client = TestCommon.CreateClient(true); try { - doc = client.CreateDocumentAsync(coll.SelfLink, new Document()).Result.Resource; + doc = (await client.CreateDocumentAsync(coll.SelfLink, new Document())).Resource; Assert.Fail("Should have faild because of version error"); } - catch (AggregateException exception) + catch (CosmosException dce) { - var dce = exception.InnerException as CosmosException; - if (dce != null) - { - Assert.AreEqual(dce.StatusCode, HttpStatusCode.BadRequest); - } - else - { - Assert.Fail("Should have faild because of version error with DocumentClientException BadRequest"); - } + Assert.AreEqual(dce.StatusCode, HttpStatusCode.BadRequest); } } finally { HttpConstants.Versions.CurrentVersion = correctVersion; + using DocumentClient client = TestCommon.CreateClient(true); + await client.DeleteDatabaseAsync(db); } } [TestMethod] public async Task ValidateCurrentWriteQuorumAndReplicaSetHeader() { - CosmosClient client = TestCommon.CreateCosmosClient(false); + using CosmosClient client = TestCommon.CreateCosmosClient(false); Cosmos.Database db = null; try { @@ -626,7 +623,7 @@ public async Task ValidateCurrentWriteQuorumAndReplicaSetHeader() [TestCategory("Ignore") /* Used to filter out ignored tests in lab runs */] public void ValidateGlobalCompltedLSNAndNumberOfReadRegionsHeader() { - DocumentClient client = TestCommon.CreateClient(false); + using DocumentClient client = TestCommon.CreateClient(false); Database db = null; try { @@ -670,7 +667,7 @@ public async Task ValidateCollectionIndexProgressHeaders() [TestMethod] public async Task ValidateExcludeSystemProperties() { - var client = TestCommon.CreateClient(true); + using var client = TestCommon.CreateClient(true); await ValidateExcludeSystemProperties(client); } @@ -785,6 +782,8 @@ private async Task ValidateExcludeSystemProperties(DocumentClient client) //read document with default settings (system properties should be included) Document readDoc3Default = await client.ReadDocumentAsync(coll.AltLink + "/docs/doc3", new RequestOptions() { PartitionKey = new PartitionKey("doc3") }); Assert.AreEqual(readDoc3WithProps.ToString(), readDoc3Default.ToString()); + + await client.DeleteDatabaseAsync(db); } private async Task ValidateCollectionIndexProgressHeadersAsync(DocumentClient client, bool isElasticCollection) @@ -879,7 +878,7 @@ private async Task ValidateCollectionIndexProgressHeadersAsync(DocumentClient cl } finally { - client.DeleteDatabaseAsync(db).Wait(); + await client.DeleteDatabaseAsync(db); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index 92425bf39c..6ae91f1375 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -40,6 +40,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + cosmosClient.Dispose(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/InternalFriendsTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/InternalFriendsTest.cs index b1572e6f3c..a256394681 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/InternalFriendsTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/InternalFriendsTest.cs @@ -18,10 +18,12 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public class InternalFriendsTest { private CosmosClient cosmosClient; + private Database database; [TestCleanup] - public void Cleanup() + public async Task Cleanup() { + await this.database?.DeleteAsync(); this.cosmosClient?.Dispose(); } @@ -99,10 +101,10 @@ private async Task CreateContainer(bool isLocalQuorumConsistency) } }); - Database database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), + this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: new CancellationTokenSource().Token); - return await database.CreateContainerAsync(id: Guid.NewGuid().ToString(), + return await this.database.CreateContainerAsync(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk"); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs index 1beab5131b..0734f4dfad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs @@ -54,6 +54,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + client?.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs index d311794526..7ffc36bdbd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs @@ -39,12 +39,14 @@ public async static Task Initialize(TestContext textContext) } [ClassCleanup] - public static void CleanUp() + public static async Task CleanUp() { if (testDb != null) { - testDb.DeleteStreamAsync().Wait(); + await testDb.DeleteStreamAsync(); } + + client?.Dispose(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs index aa5e68141c..a9782bb26b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs @@ -46,6 +46,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + cosmosClient?.Dispose(); } public class Address diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs index d3fecc59e6..f3c27a2230 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs @@ -64,6 +64,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + cosmosClient?.Dispose(); } struct simple diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 67a4aa9364..01b64cd4fd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -60,6 +60,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + cosmosClient?.Dispose(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs index be3412e05f..c81beaaeb8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs @@ -47,6 +47,8 @@ public async static Task CleanUp() { await testDb.DeleteStreamAsync(); } + + cosmosClient?.Dispose(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/MultiRegionStrongTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/MultiRegionStrongTests.cs deleted file mode 100644 index 1b17f6cac2..0000000000 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/MultiRegionStrongTests.cs +++ /dev/null @@ -1,286 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Utils; - using Microsoft.Azure.Cosmos.Services.Management.Tests; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Microsoft.Azure.Documents.Client; - using Microsoft.Azure.Documents; - using System.Net.Http; - - [TestClass] - public sealed class MultiRegionStrongTests - { - private const string repairInProgressFileName = "ManualRepair.InProgress"; - - private string DatabaseName; - private string CollectionName; - - private DocumentClient read0; - private DocumentClient read1; - private DocumentClient read2; - - private DocumentClient write0; - private DocumentClient write1; - private DocumentClient write2; - - - [TestInitialize] - public void TestInitialize() - { - this.DatabaseName = Guid.NewGuid().ToString(); - this.CollectionName = Guid.NewGuid().ToString(); - - this.read0 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: true); - read0.LockClient(0); - - this.read1 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: true); - read1.LockClient(1); - - this.read2 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: true); - read2.LockClient(2); - - this.write0 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: false); - write0.LockClient(0); - - this.write1 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: false); - write1.LockClient(1); - - this.write2 = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: false); - write2.LockClient(2); - } - - private async Task SetupSingleCollectionScenario() - { - DocumentClient client = TestCommon.CreateClient(true); - await TestCommon.DeleteAllDatabasesAsync(); - - Database database = (await client.CreateDatabaseAsync(new Database { Id = this.DatabaseName })).Resource; - DocumentCollection collection = (await client.CreateDocumentCollectionIfNotExistsAsync(database.SelfLink, new DocumentCollection { Id = this.CollectionName }, new RequestOptions { OfferThroughput = 10000 })).Resource; - - // await Task.Delay(30000); - - return collection; - } - - private DocumentClient GetDocumentClient(ConnectionMode connectionMode, Protocol protocol, List preferredRegions) - { - ConnectionPolicy connectionPolicy = new ConnectionPolicy { ConnectionMode = connectionMode, ConnectionProtocol = protocol }; - foreach (string preferredRegion in preferredRegions) - { - connectionPolicy.PreferredLocations.Add(preferredRegion); - } - - return new DocumentClient( - new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), - ConfigurationManager.AppSettings["MasterKey"], - (HttpMessageHandler)null, - connectionPolicy); - } - - private async Task CreateDocumentsAsync(string collectionSelfLink, DocumentClient client, CancellationToken cancellationToken) - { - int writeCount = 0; - - int i = 0; - while (i < 50000) - { - if (cancellationToken.IsCancellationRequested) - { - Logger.LogLine("WriteCount: {0}", writeCount); - return; - } - - Document doc = (await client.CreateDocumentAsync(collectionSelfLink, new Document { Id = Guid.NewGuid().ToString() })).Resource; - writeCount++; - await client.ReadDocumentAsync(doc.SelfLink); - - i++; - } - } - - private async Task ReadDocumentsAsync(string collectionSelfLink, DocumentClient client, CancellationToken cancellationToken) - { - int readFeedCount = 0; - int readCount = 0; - - int i = 0; - while (i < 50000) - { - if (cancellationToken.IsCancellationRequested) - { - Logger.LogLine("ReadFeedCount: {0}, ReadCount: {1}", readFeedCount, readCount); - return; - } - - DocumentFeedResponse response = await client.ReadDocumentFeedAsync(collectionSelfLink); - readFeedCount++; - - foreach (var doc in response) - { - await client.ReadDocumentAsync(doc.SelfLink); - readCount++; - } - - i++; - } - } - - private void ResumeReplicas(string documentId) - { - ResourceId documentRId = ResourceId.Parse(documentId); - string collectionId = documentRId.DocumentCollectionId.ToString(); - IEnumerable indexFiles = Directory.EnumerateFiles("c:\\wfroot\\", "*.bwdata", SearchOption.AllDirectories); - List collectionIndexFiles = new List(); - - foreach (string indexFile in indexFiles) - { - if (indexFile.Contains(collectionId)) - { - collectionIndexFiles.Add(indexFile); - } - } - - foreach (string fileName in collectionIndexFiles) - { - string directoryName = Path.GetDirectoryName(fileName); - string manualRecoveryFileFullName = Path.Combine(directoryName, MultiRegionStrongTests.repairInProgressFileName); - try - { - File.Delete(manualRecoveryFileFullName); - } - catch (FileNotFoundException) - { - } - } - } - /* - private async Task TestGlobalStrongAsync(ConnectionMode connectionMode, Protocol protocol) - { - await TestCommon.DeleteAllDatabasesAsync(TestCommon.CreateClient(true)); - using (await TestCommon.OverrideGlobalDatabaseAccountConfigurationsAsync(Tuple.Create("defaultConsistencyLevel", "Strong"))) - { - await Task.Delay(TimeSpan.FromSeconds(35)); - - ConnectionPolicy scusConnectionPolicy = new ConnectionPolicy { ConnectionMode = connectionMode, ConnectionProtocol = protocol }; - scusConnectionPolicy.PreferredLocations.Add("South Central US"); - - ConnectionPolicy wusConnectionPolicy = new ConnectionPolicy { ConnectionMode = connectionMode, ConnectionProtocol = protocol }; - wusConnectionPolicy.PreferredLocations.Add("West US"); - - DocumentClient scusClient = new DocumentClient( - new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), - ConfigurationManager.AppSettings["MasterKey"], - scusConnectionPolicy); - - DocumentClient wusClient = new DocumentClient( - new Uri(ConfigurationManager.AppSettings["GatewayEndpoint"]), - ConfigurationManager.AppSettings["MasterKey"], - wusConnectionPolicy); - - Database database = (await scusClient.CreateDatabaseIfNotExistsAsync(new Database { Id = "database" })).Resource; - DocumentCollection collection = (await scusClient.CreateDocumentCollectionIfNotExistsAsync(database.SelfLink, new DocumentCollection { Id = "collection" }, new RequestOptions { OfferThroughput = 10000 })).Resource; - Document doc = (await scusClient.CreateDocumentAsync(collection.SelfLink, new Document { Id = "lockDoc" })).Resource; - await Task.Delay(TimeSpan.FromSeconds(30)); - - CancellationTokenSource tokenSource = new CancellationTokenSource(); - Task writeTask = Task.Factory.StartNew(async () => await CreateDocumentsAsync(collection.SelfLink, scusClient, tokenSource.Token)); - Task readTask1 = Task.Factory.StartNew(async () => await ReadDocumentsAsync(collection.SelfLink, scusClient, tokenSource.Token)); - Task readTask2 = Task.Factory.StartNew(async () => await ReadDocumentsAsync(collection.SelfLink, wusClient, tokenSource.Token)); - - for (uint i = 0; i < 10; i++) - { - bool isReadRegion = i % 2 == 1; - uint replicaIndexToLock = i % 3; - DocumentClient crashClient = TestCommon.CreateClient(false, enableEndpointDiscovery: false, tokenType: AuthorizationTokenType.SystemAll, createForGeoRegion: isReadRegion); - crashClient.LockClient(replicaIndexToLock); - - try - { - await crashClient.CrashAsync(doc.ResourceId, typeof(Document)); - } - catch (DocumentClientException ex) - { - Logger.LogLine("Hit exception {0} while crashing replica index {1}, isReadRegion: {2}", ex.ToString(), replicaIndexToLock, isReadRegion); - } - } - - tokenSource.Cancel(); - await writeTask; - await readTask1; - await readTask2; - - Assert.IsTrue(!this.isWriteExceptionCaught); - Assert.IsTrue(!this.isReadExceptionCaught); - } - } - - private async Task CreateDocumentsAsync(string collectionSelfLink, DocumentClient client, CancellationToken cancellationToken) - { - this.isWriteExceptionCaught = false; - int writeCount = 0; - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - Logger.LogLine("WriteCount: {0}", writeCount); - return; - } - - try - { - await client.CreateDocumentAsync(collectionSelfLink, new Document { Id = Guid.NewGuid().ToString() }); - writeCount++; - } - catch (DocumentClientException ex) - { - Logger.LogLine("Hit exception {0} while creating document.", ex.ToString()); - this.isWriteExceptionCaught = true; - } - } - } - - private async Task ReadDocumentsAsync(string collectionSelfLink, DocumentClient client, CancellationToken cancellationToken) - { - this.isReadExceptionCaught = false; - int readFeedCount = 0; - int readCount = 0; - while (true) - { - if (cancellationToken.IsCancellationRequested) - { - Logger.LogLine("ReadFeedCount: {0}, ReadCount: {1}", readFeedCount, readCount); - return; - } - - string continuationToken = null; - try - { - DoucmentFeedResponse response = await client.ReadDocumentFeedAsync(collectionSelfLink, new FeedOptions { RequestContinuation = continuationToken }); - readFeedCount++; - continuationToken = response.ResponseContinuation; - - foreach(var doc in response) - { - await client.ReadDocumentAsync(doc.SelfLink); - readCount++; - } - } - catch (DocumentClientException ex) - { - Logger.LogLine("Hit exception {0} while reading document.", ex.ToString()); - this.isReadExceptionCaught = true; - } - } - } - */ - } -} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs index 6c29791783..1dc1cd9af0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/NameRoutingTests.cs @@ -32,7 +32,7 @@ public class NameRoutingTests [TestMethod] public async Task NameRoutingSmokeGatewayTest() { - CosmosClient client = TestCommon.CreateCosmosClient(true); + using CosmosClient client = TestCommon.CreateCosmosClient(true); await SmokeTestForNameAPI(client); } @@ -419,12 +419,10 @@ private async Task SmokeTestForNameAPI(CosmosClient client) } [TestMethod] - public void ReplaceDocumentWithUri() + public async Task ReplaceDocumentWithUri() { - CosmosClient client; - - client = TestCommon.CreateCosmosClient(true); - this.ReplaceDocumentWithUriPrivateAsync(client).Wait(); + using CosmosClient client = TestCommon.CreateCosmosClient(true); + await this.ReplaceDocumentWithUriPrivateAsync(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator @@ -477,6 +475,8 @@ private async Task ReplaceDocumentWithUriPrivateAsync(CosmosClient client) sqlQueryText = @"select * from root r where r.title = ""My old Book"""; cosmosResultSet = collection.GetItemQueryIterator(queryText: sqlQueryText, requestOptions: options); Assert.AreEqual(1, await GetCountFromIterator(cosmosResultSet), "Query Count doesnt match"); + + await database.DeleteStreamAsync(); } [TestMethod] @@ -484,8 +484,7 @@ public async Task CollectionDeleteAndCreateWithSameNameTest() { // when collection name changes, the collectionName ->Id cache at the gateway need to get invalidated and refreshed. // This test is to verify this case is working well. - DocumentClient client; - client = TestCommon.CreateClient(true); + using DocumentClient client = TestCommon.CreateClient(true); await this.CollectionDeleteAndCreateWithSameNameTestPrivateAsync(client); #if DIRECT_MODE @@ -557,7 +556,7 @@ private async Task CollectionDeleteAndCreateWithSameNameTestPrivateAsync(Documen finally { - TestCommon.DeleteAllDatabasesAsync().Wait(); + await TestCommon.DeleteAllDatabasesAsync(); } } @@ -1368,7 +1367,8 @@ public async Task TestInvalidPartitionKeyException() [Ignore /* TODO: This tests throws a "The read session is not available for the input session token" */] public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery() { - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery(TestCommon.CreateClient(true)); + using DocumentClient client = TestCommon.CreateClient(true); + await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); @@ -1425,7 +1425,8 @@ internal async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartiti [Ignore /* TODO: This tests throws a "The read session is not available for the input session token" */] public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery() { - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery(TestCommon.CreateClient(true)); + using DocumentClient client = TestCommon.CreateClient(true); + await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartitionedToPartitionedForParallelQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); @@ -1442,12 +1443,12 @@ internal async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartiti await client.CreateDocumentAsync("/dbs/db1/colls/coll1", document1); Assert.AreEqual(1, client.CreateDocumentQuery("/dbs/db1/colls/coll1", "SELECT * FROM c WHERE c.field1 IN (1, 2)", new FeedOptions { EnableCrossPartitionQuery = true }).AsEnumerable().Count()); - DocumentClient otherClient = TestCommon.CreateClient(false); + using DocumentClient otherClient = TestCommon.CreateClient(false); await otherClient.DeleteDocumentCollectionAsync("/dbs/db1/colls/coll1"); PartitionKeyDefinition partitionKeyDefinition2 = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/field2" }), Kind = PartitionKind.Hash }; DocumentCollection coll = await TestCommon.CreateCollectionAsync(otherClient, "/dbs/db1", new DocumentCollection { Id = "coll1", PartitionKey = partitionKeyDefinition2 }, new RequestOptions { OfferThroughput = 12000 }); - DocumentClient directClient = TestCommon.CreateClient(false); + using DocumentClient directClient = TestCommon.CreateClient(false); string sessionToken1 = (await directClient.CreateDocumentAsync("/dbs/db1/colls/coll1", document1)).SessionToken; document1 = new Document { Id = "doc2" }; document1.SetPropertyValue("field1", 2); @@ -1466,7 +1467,7 @@ internal async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartiti Assert.AreEqual(2, client.CreateDocumentQuery("/dbs/db1/colls/coll1", "SELECT * FROM c WHERE c.field1 IN (1, 2)", new FeedOptions { EnableCrossPartitionQuery = true }).AsEnumerable().Count()); - DocumentClient newClient = TestCommon.CreateClient(false); + using DocumentClient newClient = TestCommon.CreateClient(false); Assert.AreEqual(2, newClient.CreateDocumentQuery("/dbs/db1/colls/coll1", "SELECT * FROM c WHERE c.field1 IN (1, 2)", new FeedOptions { EnableCrossPartitionQuery = true }).AsEnumerable().Count()); } @@ -1479,8 +1480,10 @@ internal async Task TestPartitionKeyDefinitionOnCollectionRecreateFromNonPartiti [TestMethod] public async Task TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery() { - await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(TestCommon.CreateClient(true)); - await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); + using DocumentClient client = TestCommon.CreateClient(true); + await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(client); + using DocumentClient directClient = TestCommon.CreateClient(false, protocol: Protocol.Tcp); + await this.TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(directClient); } internal async Task TestCollectionRecreateFromMultipartitionToSinglePartitionedForQuery(DocumentClient client) @@ -1523,7 +1526,8 @@ internal async Task TestCollectionRecreateFromMultipartitionToSinglePartitionedF [TestMethod] public async Task TestRouteToNonExistentRangeAfterCollectionRecreate() { - await this.TestRouteToNonExistentRangeAfterCollectionRecreate(TestCommon.CreateCosmosClient(true)); + using CosmosClient client = TestCommon.CreateCosmosClient(true); + await this.TestRouteToNonExistentRangeAfterCollectionRecreate(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestRouteToNonExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); @@ -1595,7 +1599,8 @@ internal async Task TestRouteToNonExistentRangeAfterCollectionRecreate(CosmosCli [TestMethod] public async Task TestRouteToExistentRangeAfterCollectionRecreate() { - await this.TestRouteToExistentRangeAfterCollectionRecreate(TestCommon.CreateCosmosClient(true)); + using CosmosClient client = TestCommon.CreateCosmosClient(true); + await this.TestRouteToExistentRangeAfterCollectionRecreate(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestRouteToExistentRangeAfterCollectionRecreate(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); @@ -1673,7 +1678,8 @@ internal async Task TestRouteToExistentRangeAfterCollectionRecreate(CosmosClient [TestMethod] public async Task TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery() { - await this.TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery(TestCommon.CreateClient(true)); + using DocumentClient client = TestCommon.CreateClient(true); + await this.TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery(client); #if DIRECT_MODE // DIRECT MODE has ReadFeed issues in the Public emulator await this.TestPartitionKeyDefinitionOnCollectionRecreateFromPartitionedToNonPartitionedForQuery(TestCommon.CreateClient(false, protocol: Protocol.Tcp)); @@ -1724,7 +1730,8 @@ internal async Task TestPartitionKeyDefinitionOnCollectionRecreateFromPartitione [TestMethod] public async Task TestScriptCreateOnContainerRecreateFromDifferentPartitionKeyPath() { - await this.TestScriptCreateOnContainerRecreateFromDifferentPartitionKeyPath(TestCommon.CreateCosmosClient(true)); + using CosmosClient client = TestCommon.CreateCosmosClient(true); + await this.TestScriptCreateOnContainerRecreateFromDifferentPartitionKeyPath(client); } internal async Task TestScriptCreateOnContainerRecreateFromDifferentPartitionKeyPath(CosmosClient client) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/OfferTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/OfferTests.cs index aa92401e3e..d2015cc8ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/OfferTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/OfferTests.cs @@ -88,11 +88,11 @@ public static void Initialize(TestContext textContext) } [TestInitialize] - public void TestInitialize() + public async Task TestInitialize() { using (DocumentClient client = TestCommon.CreateClient(true)) { - TestCommon.DeleteAllDatabasesAsync().Wait(); + await TestCommon.DeleteAllDatabasesAsync(); } } @@ -100,7 +100,7 @@ public void TestInitialize() [Ignore] //Not a valid scenerio for V3 SDK onwards public async Task ValidateOfferCreateNegative_1() { - DocumentClient client = TestCommon.CreateClient(false); + using DocumentClient client = TestCommon.CreateClient(false); Database database = (await client.CreateDatabaseAsync(new Database { Id = Guid.NewGuid().ToString("N") })).Resource; @@ -123,7 +123,7 @@ public async Task ValidateOfferCreateNegative_1() [TestMethod] public async Task ValidateOfferDefaults() { - DocumentClient client = TestCommon.CreateClient(false); + using DocumentClient client = TestCommon.CreateClient(false); Database database = (await client.CreateDatabaseAsync(new Database { Id = Guid.NewGuid().ToString("N") })).Resource; string collectionId = Guid.NewGuid().ToString("N"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs index 1b7d554772..d0bdb59adb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/PartitionKeyRangeCacheTests.cs @@ -79,7 +79,7 @@ public async Task VerifyPkRangeCacheRefreshOnSplitWithErrorsAsync() }) }; - CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); + using CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); string dbName = Guid.NewGuid().ToString(); string containerName = nameof(PartitionKeyRangeCacheTests); @@ -143,6 +143,8 @@ public async Task VerifyPkRangeCacheRefreshOnSplitWithErrorsAsync() } Assert.AreEqual(0, exceptions.Count, $"Unexpected exceptions: {string.Join(';', exceptions)}"); + + await db.DeleteStreamAsync(); } private async Task CreateAndReadItemBackgroundLoop(Container container, List exceptions) @@ -213,7 +215,7 @@ public async Task VerifyPkRangeCacheRefreshOnThrottlesAsync() }) }; - CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); + using CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); string dbName = Guid.NewGuid().ToString(); string containerName = nameof(PartitionKeyRangeCacheTests); @@ -239,6 +241,8 @@ public async Task VerifyPkRangeCacheRefreshOnThrottlesAsync() Assert.AreEqual(4, pkRangeCalls); Assert.AreEqual(0, ifNoneMatchValues.Count(x => string.IsNullOrEmpty(x)), "The cache is already init. It should never re-initialize the cache."); + + await db.DeleteStreamAsync(); } [TestMethod] @@ -272,7 +276,7 @@ public async Task VerifyPkRangeCacheRefreshOnTimeoutsAsync() HttpClientFactory = () => new HttpClient(httpHandlerHelper), }; - CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); + using CosmosClient resourceClient = TestCommon.CreateCosmosClient(clientOptions); string dbName = Guid.NewGuid().ToString(); string containerName = nameof(PartitionKeyRangeCacheTests); @@ -288,12 +292,14 @@ public async Task VerifyPkRangeCacheRefreshOnTimeoutsAsync() Assert.AreEqual(3, pkRangeCalls); Assert.AreEqual(2, ifNoneMatchValues.Count(x => string.IsNullOrEmpty(x)), "First call is a 408"); + + await db.DeleteStreamAsync(); } [TestMethod] public async Task TestRidRefreshOnNotFoundAsync() { - CosmosClient resourceClient = TestCommon.CreateCosmosClient(); + using CosmosClient resourceClient = TestCommon.CreateCosmosClient(); string dbName = Guid.NewGuid().ToString(); string containerName = Guid.NewGuid().ToString(); @@ -301,7 +307,7 @@ public async Task TestRidRefreshOnNotFoundAsync() Database db = await resourceClient.CreateDatabaseAsync(dbName); Container container = await db.CreateContainerAsync(containerName, "/_id"); - CosmosClient testClient = TestCommon.CreateCosmosClient(); + using CosmosClient testClient = TestCommon.CreateCosmosClient(); ContainerInternal testContainer = (ContainerInlineCore)testClient.GetContainer(dbName, containerName); // Populate the RID cache. @@ -326,6 +332,8 @@ public async Task TestRidRefreshOnNotFoundAsync() CollectionRoutingMap collectionRoutingMapFromCache = await testContainer.GetRoutingMapAsync(cancellationToken: default); Assert.AreEqual(collectionRoutingMap, collectionRoutingMapFromCache); + + await db.DeleteStreamAsync(); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs index c196af9d44..8af5eeafef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryTestsBase.cs @@ -40,12 +40,6 @@ public abstract class QueryTestsBase internal CosmosClient Client; internal Cosmos.Database database; - public QueryTestsBase() - { - this.GatewayClient = TestCommon.CreateCosmosClient(true, builder => builder.AddCustomHandlers(this.GatewayRequestChargeHandler)); - this.Client = TestCommon.CreateCosmosClient(false, builder => builder.AddCustomHandlers(this.DirectRequestChargeHandler)); - } - [FlagsAttribute] internal enum ConnectionModes { @@ -63,17 +57,11 @@ internal enum CollectionTypes MultiPartition = 0x4, } - [ClassInitialize] - [ClassCleanup] - public static void ClassSetup(TestContext testContext = null) - { - CosmosClient client = TestCommon.CreateCosmosClient(false); - QueryTestsBase.CleanUp(client).Wait(); - } - [TestInitialize] public async Task Initialize() { + this.GatewayClient = TestCommon.CreateCosmosClient(true, builder => builder.AddCustomHandlers(this.GatewayRequestChargeHandler)); + this.Client = TestCommon.CreateCosmosClient(false, builder => builder.AddCustomHandlers(this.DirectRequestChargeHandler)); this.database = await this.Client.CreateDatabaseAsync(Guid.NewGuid().ToString() + "db"); } @@ -81,6 +69,8 @@ public async Task Initialize() public async Task Cleanup() { await this.database.DeleteStreamAsync(); + this.Client.Dispose(); + this.GatewayClient.Dispose(); } private static string GetApiVersion() @@ -359,6 +349,8 @@ internal async Task RunWithApiVersion(string apiVersion, Func function) } finally { + this.Client.Dispose(); + this.GatewayClient.Dispose(); this.Client = originalCosmosClient; this.GatewayClient = originalGatewayClient; this.database = originalDatabase; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index 6d6484e5a9..afc25ec771 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -68,6 +68,16 @@ public void TestInitialize() this.CleanUp(); } + [TestCleanup] + public void TestCleanup() + { + this.CleanUp(); + + this.client.Dispose(); + this.primaryReadonlyClient.Dispose(); + this.secondaryReadonlyClient.Dispose(); + } + [ClassInitialize] public static void Initialize(TestContext textContext) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs index 6aa1b2ca16..485f75a2a5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SmokeTests.cs @@ -33,6 +33,13 @@ static SmokeTests() { } + [TestCleanup] + public async Task Cleanup() + { + await this.client.GetDatabase(DatabaseName).DeleteStreamAsync(); + this.client?.Dispose(); + } + /// /// Test for the existence of native assembly dependencies /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SpatialTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SpatialTest.cs index 63eaaeda46..279014dccf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SpatialTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SpatialTest.cs @@ -27,14 +27,22 @@ private class SpatialSampleClass public Geometry Location { get; set; } } - private readonly DocumentClient client; + private DocumentClient client; - public SpatialTest() + [TestInitialize] + public void TestInitialize() { this.client = TestCommon.CreateClient(true, defaultConsistencyLevel: ConsistencyLevel.Session); this.CleanUp(); } + [TestCleanup] + public void TestCleanup() + { + this.CleanUp(); + this.client.Dispose(); + } + [TestMethod] public async Task TestDistanceAndWithin() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/StoredProcedureTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/StoredProcedureTests.cs index 8e61c2dcc9..6d8a0f7873 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/StoredProcedureTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/StoredProcedureTests.cs @@ -2,11 +2,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ -using System.Net.Http; -using Microsoft.Azure.Documents.Client; - namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { + using System.Net.Http; using System; using System.Collections.Generic; using System.IO; @@ -14,7 +12,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Text; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Cosmos.Scripts; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -34,8 +31,8 @@ public async Task TestInitialize() SendingRequestEventArgs = this.SendingRequestEventHandlerScriptsVerifier, }; - this.cosmosClient = TestCommon.CreateCosmosClient(clientOptions); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), + this.SetClient(TestCommon.CreateCosmosClient(clientOptions)); + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: this.cancellationToken); string containerName = Guid.NewGuid().ToString(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs index 9f200af263..ae94a7220d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs @@ -32,6 +32,7 @@ public async Task TestInitialize() public async Task Cleanup() { await this.Database.DeleteAsync(); + this.Client.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index bb46c0f3f3..e81eda0d01 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -98,6 +98,10 @@ public static async Task ClassCleanupAsync() Util.DisposeOpenTelemetryAndCustomListeners(); + EndToEndTraceWriterBaselineTests.client?.Dispose(); + EndToEndTraceWriterBaselineTests.bulkClient?.Dispose(); + EndToEndTraceWriterBaselineTests.miscCosmosClient?.Dispose(); + await Task.Delay(5000); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs index 720f37375c..9e7394bf21 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TransportWrapperTests.cs @@ -19,7 +19,7 @@ public class TransportWrapperTests [TestMethod] public async Task TransportInterceptorContractTest() { - CosmosClient cosmosClient = TestCommon.CreateCosmosClient( + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient( builder => { builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper(transportClient, TransportWrapperTests.Interceptor)); @@ -31,12 +31,13 @@ public async Task TransportInterceptorContractTest() string id1 = Guid.NewGuid().ToString(); TestPayload payload1 = await container.CreateItemAsync(new TestPayload { id = id1 }); payload1 = await container.ReadItemAsync(id1, new Cosmos.PartitionKey(id1)); + await database.DeleteStreamAsync(); } [TestMethod] public async Task TransportExceptionValidationTest() { - CosmosClient cosmosClient = TestCommon.CreateCosmosClient( + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient( builder => { builder.WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( @@ -79,7 +80,9 @@ public async Task TransportExceptionValidationTest() using (ResponseMessage responseMessage = await streamIterator.ReadNextAsync()) { this.ValidateTransportException(responseMessage); - } + } + + await database.DeleteStreamAsync(); } private void ValidateTransportException(CosmosException cosmosException) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs index d32f33643d..82d76427d5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs @@ -29,8 +29,8 @@ public async Task TestInitialize() SendingRequestEventArgs = this.SendingRequestEventHandlerTriggersVerifier, }; - this.cosmosClient = TestCommon.CreateCosmosClient(clientOptions); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), + this.SetClient(TestCommon.CreateCosmosClient(clientOptions)); + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: this.cancellationToken); string PartitionKey = "/pk"; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UniqueIndexTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UniqueIndexTests.cs index e6a33ab170..f2c856b837 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UniqueIndexTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UniqueIndexTests.cs @@ -34,6 +34,8 @@ public async Task TestCleanupAsync() { using (await this.database.DeleteStreamAsync()) { } } + + this.client.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UserDefinedFunctionsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UserDefinedFunctionsTests.cs index 6ff6c117ee..cf3354575d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UserDefinedFunctionsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/UserDefinedFunctionsTests.cs @@ -28,8 +28,8 @@ public async Task TestInitialize() SendingRequestEventArgs = this.SendingRequestEventHandlerUdfVerifier, }; - this.cosmosClient = TestCommon.CreateCosmosClient(clientOptions); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), + this.SetClient(TestCommon.CreateCosmosClient(clientOptions)); + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString(), cancellationToken: this.cancellationToken); string PartitionKey = "/pk"; ContainerResponse response = await this.database.CreateContainerAsync( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs index 20f083d85d..26930a59a0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/BaseCosmosClientHelper.cs @@ -11,34 +11,44 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public abstract class BaseCosmosClientHelper { - protected CosmosClient cosmosClient = null; + private static readonly CosmosClient defaultCosmosClient = TestCommon.CreateCosmosClient(); + + private CosmosClient cosmosClient = null; protected Database database = null; protected CancellationTokenSource cancellationTokenSource = null; protected CancellationToken cancellationToken; - public async Task TestInit( - bool validateSinglePartitionKeyRangeCacheCall = false, - Action customizeClientBuilder = null, - string accountEndpointOverride = null) + private async Task BaseInit(CosmosClient client) + { + this.cancellationTokenSource = new CancellationTokenSource(); + this.cancellationToken = this.cancellationTokenSource.Token; + + this.database = await client.CreateDatabaseAsync(Guid.NewGuid().ToString(), + cancellationToken: this.cancellationToken); + } + + public async Task TestInit() { this.cancellationTokenSource = new CancellationTokenSource(); this.cancellationToken = this.cancellationTokenSource.Token; + await this.BaseInit(BaseCosmosClientHelper.defaultCosmosClient); + } + + public async Task TestInit( + bool validateSinglePartitionKeyRangeCacheCall, + Action customizeClientBuilder = null, + string accountEndpointOverride = null) + { this.cosmosClient = TestCommon.CreateCosmosClient( validatePartitionKeyRangeCalls: validateSinglePartitionKeyRangeCacheCall, customizeClientBuilder: customizeClientBuilder, accountEndpointOverride: accountEndpointOverride); - this.database = await this.cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString(), - cancellationToken: this.cancellationToken); + await this.BaseInit(this.cosmosClient); } public async Task TestCleanup() { - if (this.cosmosClient == null) - { - return; - } - if (this.database != null) { await this.database.DeleteStreamAsync( @@ -48,7 +58,19 @@ await this.database.DeleteStreamAsync( this.cancellationTokenSource?.Cancel(); - this.cosmosClient.Dispose(); + // Only dispose if the caller set a custom client + this.cosmosClient?.Dispose(); + } + + public CosmosClient GetClient() + { + return this.cosmosClient ?? BaseCosmosClientHelper.defaultCosmosClient; + } + + public void SetClient(CosmosClient client) + { + this.cosmosClient?.Dispose(); + this.cosmosClient = client; } } } diff --git a/templates/emulator-setup.yml b/templates/emulator-setup.yml index 56ba69b98b..f081209295 100644 --- a/templates/emulator-setup.yml +++ b/templates/emulator-setup.yml @@ -1,30 +1,52 @@ # File: templates/emulator-setup.yml steps: - - pwsh: | - Write-Host "Downloading Cosmos Emulator - $env:EMULATORMSIURL" -ForegroundColor green - Invoke-WebRequest "$env:EMULATORMSIURL" -OutFile "$env:temp\azure-cosmosdb-emulator.msi" - Write-Host "Finished Downloading Cosmos Emulator - $env:temp\azure-cosmosdb-emulator.msi" -ForegroundColor green - dir "$env:temp" - choco install lessmsi - choco upgrade lessmsi - mkdir "$env:temp\Azure Cosmos DB Emulator" - lessmsi x "$env:temp\azure-cosmosdb-emulator.msi" "$env:temp\Azure Cosmos DB Emulator\" - Write-Host "Starting Comsos DB Emulator" -ForegroundColor green - Add-MpPreference -ExclusionPath "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator" - Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=100 /Consistency=Strong /enableRio /EnablePreview /EnableAadAuthentication /EnableSqlComputeEndpoint" -Verb RunAs - Import-Module "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" - Get-Item env:* | Sort-Object -Property Name - for ($i=0; $i -lt 10; $i++) { - $status=Get-CosmosDbEmulatorStatus + - pwsh: | + Write-Host "Downloading Cosmos Emulator - $env:EMULATORMSIURL" -ForegroundColor green + Invoke-WebRequest "$env:EMULATORMSIURL" -OutFile "$env:temp\azure-cosmosdb-emulator.msi" + Write-Host "Finished Downloading Cosmos Emulator - $env:temp\azure-cosmosdb-emulator.msi" -ForegroundColor green + dir "$env:temp" + choco install lessmsi + choco upgrade lessmsi + mkdir "$env:temp\Azure Cosmos DB Emulator" + lessmsi x "$env:temp\azure-cosmosdb-emulator.msi" "$env:temp\Azure Cosmos DB Emulator\" + Add-MpPreference -ExclusionPath "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator" + Add-MpPreference -ExclusionPath "$env:localappdata\CosmosDBEmulator" + displayName: Downloading and Installing Cosmos DB Emulator + failOnStderr: true + errorActionPreference: stop + - pwsh: | + Write-Host "Starting Cosmos DB Emulator" -ForegroundColor green + Import-Module "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator" + Get-Item env:* | Sort-Object -Property Name + + for ($j=0; $j -lt 3; $j++) { + Write-Host "Attempt $j" + Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/NoExplorer /NoUI /DisableRateLimiting /PartitionCount=50 /Consistency=Strong /EnablePreview /EnableSqlComputeEndpoint" -Verb RunAs + for ($i=0; $i -lt 5; $i++) { + $status = Get-CosmosDbEmulatorStatus + Write-Host "Cosmos DB Emulator Status: $status" if ($status -ne "Running") { sleep 30; - Write-Host "Cosmos DB Emulator Status: $status" -ForegroundColor yellow - } else { + } + else { break; } } - - displayName: Install Public Cosmos DB Emulator - failOnStderr: true - errorActionPreference: stop + if ($status -ne "Running") { + Write-Host "Shutting down and restarting" + Start-Process "$env:temp\Azure Cosmos DB Emulator\SourceDir\Azure Cosmos DB Emulator\CosmosDB.Emulator.exe" "/Shutdown" -Verb RunAs + sleep 30; + } + else { + break; + } + } + + if ($status -ne "Running") { + Write-Error "Emulator failed to start" + } + + displayName: Waiting for Cosmos DB Emulator status + failOnStderr: true + errorActionPreference: stop From 6434c1074615cf435085cba5a5e31f62d3ea6b37 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 14 Feb 2023 14:52:55 -0800 Subject: [PATCH 055/337] [Internal] GitHub Template: Adds needs-investigation label (#3708) By default, all "Bug report" issues will have "needs-investigation" --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 40d469e6fe..39dc8d035f 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,7 +2,7 @@ name: Bug report about: Create a report to help us improve title: '' -labels: '' +labels: needs-investigation assignees: '' --- From 4e923da024956732acfa44a5205104cdd751bee4 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 14 Feb 2023 15:57:51 -0800 Subject: [PATCH 056/337] Adding fabric bot action (#3709) --- .github/fabricbot.json | 56 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/.github/fabricbot.json b/.github/fabricbot.json index eddfa52721..90924da0c3 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -6,7 +6,6 @@ "capabilityId": "ScheduledSearch", "subCapability": "ScheduledSearch", "version": "1.1", - "id": "a-PNOJWK3Jbr7QY7vkc2O", "config": { "frequency": [ { @@ -50,7 +49,60 @@ ] }, "disabled": true + }, + { + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isAssignedToSomeone", + "parameters": {} + } + ] + }, + { + "name": "isAction", + "parameters": { + "action": "opened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-investigation" + } + } + ] + } + ] + }, + "eventType": "issue", + "eventNames": [ + "issues", + "project_card" + ], + "taskName": "Add needs-investigation", + "actions": [ + { + "name": "addLabel", + "parameters": { + "label": "needs-investigation" + } + } + ] + } } ], "userGroups": [] -} +} \ No newline at end of file From 38d1bcc09022b3d96fcc34cb51aa0912f211b10b Mon Sep 17 00:00:00 2001 From: Abhijeet Mohanty Date: Fri, 17 Feb 2023 14:46:38 -0500 Subject: [PATCH 057/337] CosmosNullReferenceException: Refactors CosmosNullReferenceException to pass along InnerException property on parent NullReferenceException (#3713) * Passed inner exception details to NullReferenceException ctor when instantiating CosmosNullReferenceException. * Added unit tests. * Addressed PR feedback. --- .../CosmosExceptions/CosmosNullReferenceException.cs | 5 +++-- .../CosmosNullReferenceExceptionTests.cs | 10 +++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs index 03e4cb21e8..4e7aa73f54 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs @@ -25,9 +25,10 @@ internal class CosmosNullReferenceException : NullReferenceException /// internal CosmosNullReferenceException( NullReferenceException originalException, - ITrace trace) + ITrace trace) + : base(originalException?.Message ?? throw new ArgumentNullException(nameof(originalException)), originalException ?? throw new ArgumentNullException(nameof(originalException))) { - this.originalException = originalException ?? throw new ArgumentNullException(nameof(originalException)); + this.originalException = originalException; if (trace == null) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosNullReferenceExceptionTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosNullReferenceExceptionTests.cs index a97b56189b..072b63a660 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosNullReferenceExceptionTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosNullReferenceExceptionTests.cs @@ -37,9 +37,10 @@ public void CosmosNullRefWrapingTest() trace); Assert.AreEqual(nullReferenceException.StackTrace, cosmosNullReferenceException.StackTrace); - Assert.AreEqual(nullReferenceException.InnerException, cosmosNullReferenceException.InnerException); + Assert.AreEqual(nullReferenceException, cosmosNullReferenceException.InnerException); Assert.AreEqual(nullReferenceException.Data, cosmosNullReferenceException.Data); + Assert.IsTrue(cosmosNullReferenceException.Message.Contains(message)); Assert.IsTrue(cosmosNullReferenceException.Message.Contains(rootTraceName)); Assert.AreNotEqual(nullReferenceException.Message, cosmosNullReferenceException.Message); @@ -48,5 +49,12 @@ public void CosmosNullRefWrapingTest() Assert.IsTrue(cosmosToString.Contains(message)); Assert.IsTrue(cosmosToString.Contains(rootTraceName)); } + + [TestMethod] + [ExpectedException(typeof(ArgumentNullException))] + public void ExpectArgumentNullExceptionTest() + { + _ = new CosmosNullReferenceException(null, NoOpTrace.Singleton); + } } } From 209e4733a7047e57439f2fa40a016ea8cfc77e2c Mon Sep 17 00:00:00 2001 From: Achint-Agrawal <45819170+Achint-Agrawal@users.noreply.github.com> Date: Sat, 18 Feb 2023 02:54:37 +0530 Subject: [PATCH 058/337] [Internal] PriorityRequests: Fixes header value (#3714) Co-authored-by: Matias Quaranta --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 887ca2d334..a4a5b0a087 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.32.0 3.32.0 preview - 3.30.1 + 3.30.2 2.0.1 2.0.1 preview From 67e1a90a5a2f4a33123e714d80393bdf937343ba Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:59:15 -0800 Subject: [PATCH 059/337] [Internal] Query: Adds single physical partition check for OptimisticDirectExecution queries (#3699) * Added single physical partition check for Ode queries. Updated test infrastructure for Ode emulator tests too. * Refactored emulator tests to have all the test cases at the top of the file * Updated TryGetTargetRangeOptimisticDirectExecutionAsync() * Uodated logic on how many times CreateIngestQueryDeleteAsync() gets called * Added debug asserts for partitionKeyDefinition * Added pageSizeOptions parameter in CreateInput() in EmulatorTests * Fixed comments --- .../CosmosQueryExecutionContextFactory.cs | 30 +- .../OptimisticDirectExecutionQueryTests.cs | 309 ++++++++---------- ...egativeOptimisticDirectExecutionOutput.xml | 39 --- ...ositiveOptimisticDirectExecutionOutput.xml | 39 +++ ...misticDirectExecutionQueryBaselineTests.cs | 54 +-- 5 files changed, 218 insertions(+), 253 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index d8a885a07b..a7f7f17934 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -755,22 +755,9 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP { if (!inputParameters.EnableOptimisticDirectExecution) return null; - // case 1: Is query going to a single partition - bool hasPartitionKey = inputParameters.PartitionKey.HasValue - && inputParameters.PartitionKey != PartitionKey.Null - && inputParameters.PartitionKey != PartitionKey.None; - - // case 2: does query execution plan have a single query range - bool hasQueryRanges = partitionedQueryExecutionInfo != null - && partitionedQueryExecutionInfo.QueryRanges.Count == 1 - && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue; - - if (!hasPartitionKey && !hasQueryRanges) return null; - - //TODO: does collection have only one physical partition - - List targetRanges = new List(); + Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); + List targetRanges; if (partitionedQueryExecutionInfo != null) { targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( @@ -785,8 +772,10 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP else { Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - if (partitionKeyDefinition != null && containerQueryProperties.ResourceId != null && inputParameters.PartitionKey != null) + if (inputParameters.PartitionKey != null) { + Debug.Assert(partitionKeyDefinition != null, "CosmosQueryExecutionContextFactory Assert!", "PartitionKeyDefinition cannot be null if partitionKey is defined"); + targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, @@ -794,6 +783,15 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP forceRefresh: false, trace); } + else + { + targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( + cosmosQueryContext.ResourceLink, + containerQueryProperties.ResourceId, + new List> { FeedRangeEpk.FullRange.Range }, + forceRefresh: false, + trace); + } } if (targetRanges.Count == 1) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 9d89f6362a..751c21b64b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -14,195 +14,131 @@ [TestCategory("Query")] public sealed class OptimisticDirectExecutionQueryTests : QueryTestsBase { + private static class PageSizeOptions + { + public static readonly int[] NonGroupByPageSizeOptions = { -1, 1, 2, 10, 100 }; + public static readonly int[] GroupByPageSizeOptions = { -1 }; + } + [TestMethod] - public async Task TestOptimisticDirectExecutionQueries() + public async Task TestPassingOptimisticDirectExecutionQueries() { int numberOfDocuments = 8; string partitionKey = "key"; string numberField = "numberField"; string nullField = "nullField"; - List documents = new List(numberOfDocuments); - for (int i = 0; i < numberOfDocuments; ++i) + List documents = CreateDocuments(numberOfDocuments, partitionKey, numberField, nullField); + + List singlePartitionContainerTestCases = new List() { - Document doc = new Document(); - doc.SetPropertyValue(partitionKey, "/value"); - doc.SetPropertyValue(numberField, i % 8); - doc.SetPropertyValue(nullField, null); - documents.Add(doc.ToString()); - } + // Tests for bool enableOptimisticDirectExecution + CreateInput( query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{partitionKey}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{partitionKey}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: false, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), + + // Simple query + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + // DISTINCT with ORDER BY + CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + // TOP with GROUP BY + CreateInput( query: $"SELECT TOP 5 VALUE r.{numberField} FROM r GROUP BY r.{numberField}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT TOP 5 VALUE r.{numberField} FROM r GROUP BY r.{numberField}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + // OFFSET LIMIT with WHERE and BETWEEN + CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, partition: CollectionTypes.SinglePartition, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution) + }; - SinglePartitionWithContinuationsArgs args = new SinglePartitionWithContinuationsArgs + List multiPartitionContainerTestCases = new List() { - NumberOfDocuments = numberOfDocuments, - PartitionKey = partitionKey, - NumberField = numberField, - NullField = nullField, + // Simple query + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), + + // DISTINCT with ORDER BY + CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized), + + // OFFSET LIMIT with WHERE and BETWEEN + CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized) }; - await this.CreateIngestQueryDeleteAsync( + await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, - CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + CollectionTypes.SinglePartition, documents, - RunTests, - args, + (container, documents) => RunPassingTests(singlePartitionContainerTestCases, container), "/" + partitionKey); - } - private static async Task RunTests(Container container, IReadOnlyList documents, SinglePartitionWithContinuationsArgs args) - { - await TestPositiveOptimisticDirectExecutionOutput(container, args); - await TestNegativeOptimisticDirectExecutionOutput(container); + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.MultiPartition, + documents, + (container, documents) => RunPassingTests(multiPartitionContainerTestCases, container), + "/" + partitionKey); } - private static async Task TestPositiveOptimisticDirectExecutionOutput( - Container container, - SinglePartitionWithContinuationsArgs args) + [TestMethod] + public async Task TestFailingOptimisticDirectExecutionOutput() { - int documentCount = args.NumberOfDocuments; - string partitionKey = args.PartitionKey; - string numberField = args.NumberField; - string nullField = args.NullField; - - QueryRequestOptions feedOptions = new QueryRequestOptions - { - MaxItemCount = -1, - EnableOptimisticDirectExecution = true, - TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) - }; - - // check if pipeline returns empty continuation token - FeedResponse responseWithEmptyContinuationExpected = await container.GetItemQueryIterator( - $"SELECT TOP 0 * FROM r", - requestOptions: feedOptions).ReadNextAsync(); - - Assert.AreEqual(null, responseWithEmptyContinuationExpected.ContinuationToken); - - List queries = new List - { - $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{partitionKey}", - $"SELECT VALUE r.numberField FROM r", - $"SELECT VALUE r.numberField FROM r", - $"SELECT TOP 4 VALUE r.numberField FROM r ORDER BY r.{numberField}", - $"SELECT TOP 3 VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {documentCount} ORDER BY r.{numberField} DESC", - $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {documentCount} OFFSET 1 LIMIT 1", - $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField}", - $"SELECT TOP 3 VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {documentCount} ORDER BY r.{numberField} DESC", - $"SELECT TOP 4 VALUE r.numberField FROM r ORDER BY r.{numberField}", - $"SELECT VALUE r.numberField FROM r", - }; - - List> results = new List> - { - new List { 0, 1, 2, 3, 4 }, - new List { 0, 1, 2, 3, 4, 5, 6, 7 }, - new List { 0, 1, 2, 3, 4, 5, 6, 7 }, - new List { 0, 1, 2, 3}, - new List { 7, 6, 5}, - new List { 1}, - new List { 0, 1, 2, 3, 4, 5, 6, 7}, - new List { 7, 6, 5}, - new List { 0, 1, 2, 3}, - new List { 0, 1, 2, 3, 4, 5, 6, 7 }, - }; - - List partitionKeys = new List - { - "/value", - null, - "/value", - "/value", - "/value", - null, - null, - "/value", - "/value", - "/value", - }; + int numberOfDocuments = 8; + string partitionKey = "key"; + string numberField = "numberField"; + string nullField = "nullField"; - List expectedPipelineType = new List - { - TestInjections.PipelineType.OptimisticDirectExecution, - TestInjections.PipelineType.Passthrough, - TestInjections.PipelineType.OptimisticDirectExecution, - TestInjections.PipelineType.OptimisticDirectExecution, - TestInjections.PipelineType.OptimisticDirectExecution, - TestInjections.PipelineType.Specialized, - TestInjections.PipelineType.Specialized, - TestInjections.PipelineType.Specialized, - TestInjections.PipelineType.Specialized, - TestInjections.PipelineType.Passthrough, - }; + List documents = CreateDocuments(numberOfDocuments, partitionKey, numberField, nullField); - List enabledOptimisticDirectExecution = new List + // check if bad continuation queries and syntax error queries are handled by pipeline + IDictionary invalidQueries = new Dictionary { - true, - true, - true, - true, - true, - true, - true, - false, - false, - false, + { "SELECT * FROM t", Guid.NewGuid().ToString() }, + { "SELECT TOP 10 * FOM r", null }, + { "this is not a valid query", null }, }; + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + documents, + (container, documents) => RunFailingTests(container, invalidQueries), + "/" + partitionKey); + } - List queryAndResults = new List(); - - for (int i = 0; i < queries.Count(); i++) - { - QueryResultsAndPipelineType queryAndResult = new QueryResultsAndPipelineType() - { - Query = queries[i], - Result = results[i], - PartitionKey = partitionKeys[i], - ExpectedPipelineType = expectedPipelineType[i], - EnableOptimisticDirectExecution = enabledOptimisticDirectExecution[i], - }; - - queryAndResults.Add(queryAndResult); - } - - int[] pageSizeOptions = new[] { -1, 1, 2, 10, 100 }; - - for (int i = 0; i < pageSizeOptions.Length; i++) + private static async Task RunPassingTests(IEnumerable testCases, Container container) + { + foreach (DirectExecutionTestCase testCase in testCases) { - for(int j = 0; j < queryAndResults.Count(); j++) + foreach (int pageSize in testCase.PageSizeOptions) { - feedOptions = new QueryRequestOptions + QueryRequestOptions feedOptions = new QueryRequestOptions { - MaxItemCount = pageSizeOptions[i], - PartitionKey = queryAndResults[j].PartitionKey == null - ? null - : new Cosmos.PartitionKey(queryAndResults[j].PartitionKey), - EnableOptimisticDirectExecution = queryAndResults[j].EnableOptimisticDirectExecution, + MaxItemCount = pageSize, + PartitionKey = testCase.PartitionKey == null + ? null + : new Cosmos.PartitionKey(testCase.PartitionKey), + EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution, TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; List items = await RunQueryAsync( container, - queryAndResults[j].Query, + testCase.Query, feedOptions); long[] actual = items.Cast().Select(x => Number64.ToLong(x.Value)).ToArray(); - Assert.IsTrue(queryAndResults[j].Result.SequenceEqual(actual)); - - if (queryAndResults[j].EnableOptimisticDirectExecution) - { - Assert.AreEqual(queryAndResults[j].ExpectedPipelineType, feedOptions.TestSettings.Stats.PipelineType.Value); - } - else - { // test if pipeline is called if TestInjection.EnableOptimisticDirectExecution is false - Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, feedOptions.TestSettings.Stats.PipelineType.Value); - } + Assert.IsTrue(testCase.ExpectedResult.SequenceEqual(actual)); + Assert.AreEqual(testCase.ExpectedPipelineType, feedOptions.TestSettings.Stats.PipelineType.Value); } } } - private static async Task TestNegativeOptimisticDirectExecutionOutput( - Container container) + private static async Task RunFailingTests(Container container, IDictionary invalidQueries) { QueryRequestOptions feedOptions = new QueryRequestOptions { @@ -211,21 +147,13 @@ private static async Task TestNegativeOptimisticDirectExecutionOutput( TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; - // check if bad continuation queries and syntax error queries are handled by pipeline - IDictionary invalidQueries = new Dictionary - { - { "SELECT * FROM t", Guid.NewGuid().ToString() }, - { "SELECT TOP 10 * FOM r", null }, - { "this is not a valid query", null }, - }; - - foreach (KeyValuePair entry in invalidQueries) + foreach (KeyValuePair queryAndResult in invalidQueries) { try { await container.GetItemQueryIterator( - queryDefinition: new QueryDefinition(entry.Key), - continuationToken: entry.Value, + queryDefinition: new QueryDefinition(queryAndResult.Key), + continuationToken: queryAndResult.Value, requestOptions: feedOptions).ReadNextAsync(); Assert.Fail("Expect exception"); @@ -241,21 +169,60 @@ await container.GetItemQueryIterator( } } - private struct SinglePartitionWithContinuationsArgs + private static List CreateDocuments(int documentCount, string partitionKey, string numberField, string nullField) + { + List documents = new List(documentCount); + for (int i = 0; i < documentCount; ++i) + { + Document doc = new Document(); + doc.SetPropertyValue(partitionKey, "/value"); + doc.SetPropertyValue(numberField, i % documentCount); + doc.SetPropertyValue(nullField, null); + documents.Add(doc.ToString()); + } + + return documents; + } + + private static DirectExecutionTestCase CreateInput( + string query, + List expectedResult, + string partitionKey, + CollectionTypes partition, + bool enableOptimisticDirectExecution, + int[] pageSizeOptions, + TestInjections.PipelineType expectedPipelineType) { - public int NumberOfDocuments; - public string PartitionKey; - public string NumberField; - public string NullField; + return new DirectExecutionTestCase(query, expectedResult, partitionKey, partition, enableOptimisticDirectExecution, pageSizeOptions, expectedPipelineType); } - private struct QueryResultsAndPipelineType + internal readonly struct DirectExecutionTestCase { - public string Query { get; set; } - public List Result { get; set; } - public string PartitionKey { get; set; } - public TestInjections.PipelineType ExpectedPipelineType { get; set; } - public bool EnableOptimisticDirectExecution { get; set; } + public string Query { get; } + public List ExpectedResult { get; } + public string PartitionKey { get; } + public CollectionTypes Partition { get; } + public bool EnableOptimisticDirectExecution { get; } + public int[] PageSizeOptions { get; } + public TestInjections.PipelineType ExpectedPipelineType { get; } + + public DirectExecutionTestCase( + string query, + List expectedResult, + string partitionKey, + CollectionTypes partition, + bool enableOptimisticDirectExecution, + int[] pageSizeOptions, + TestInjections.PipelineType expectedPipelineType) + { + this.Query = query; + this.ExpectedResult = expectedResult; + this.PartitionKey = partitionKey; + this.Partition = partition; + this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; + this.PageSizeOptions = pageSizeOptions; + this.ExpectedPipelineType = expectedPipelineType; + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml index 7a8259eefc..4685001217 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.NegativeOptimisticDirectExecutionOutput.xml @@ -1,43 +1,4 @@  - - - Null Partition Key Value - SELECT * FROM c - - /pk - - Hash - - - false - - - - - None Partition Key Value - SELECT * FROM c - - /pk - - Hash - - - false - - - - - C# Null Partition Key Value - SELECT * FROM c - - /pk - - Hash - - - false - - Single Partition Key with Parallel continuation token diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml index 2482925bd8..5e496fc564 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml @@ -64,4 +64,43 @@ true + + + Null Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + true + + + + + None Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + true + + + + + C# Null Partition Key Value + SELECT * FROM c + + /pk + + Hash + + + true + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index b6a78c111d..20de3f1f03 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -36,10 +36,6 @@ public class OptimisticDirectExecutionQueryBaselineTests : BaselineTests testVariations = new List { CreateInput( @@ -77,7 +73,32 @@ public void PositiveOptimisticDirectExecutionOutput() expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", partitionKeyValue: "a", - continuationToken: cosmosElementOdeContinuationToken), + continuationToken: CosmosElement.Parse( + "{\"OptimisticDirectExecutionToken\":{\"token\":\"{\\\"resourceId\\\":\\\"AQAAAMmFOw8LAAAAAAAAAA==\\\"," + + "\\\"skipCount\\\":1}\", \"range\":{\"min\":\"\",\"max\":\"FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF\"}}}")), + + // Below cases are Ode because they have a collection with a single physical partition. + // Added emulator tests (TestPassingOptimisticDirectExecutionQueries()) to verify the negation of the below cases. + CreateInput( + description: @"Null Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: Cosmos.PartitionKey.Null), + + CreateInput( + description: @"None Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: Cosmos.PartitionKey.None), + + CreateInput( + description: @"C# Null Partition Key Value", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: null), }; this.ExecuteTestSuite(testVariations); } @@ -105,27 +126,6 @@ public void NegativeOptimisticDirectExecutionOutput() List testVariations = new List { - CreateInput( - description: @"Null Partition Key Value", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: false, - partitionKeyPath: @"/pk", - partitionKeyValue: Cosmos.PartitionKey.Null), - - CreateInput( - description: @"None Partition Key Value", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: false, - partitionKeyPath: @"/pk", - partitionKeyValue: Cosmos.PartitionKey.None), - - CreateInput( - description: @"C# Null Partition Key Value", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: false, - partitionKeyPath: @"/pk", - partitionKeyValue: null), - CreateInput( description: @"Single Partition Key with Parallel continuation token", query: "SELECT * FROM c", @@ -798,7 +798,7 @@ public override Task> TryGetOverlappingRangesAs } public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) - { + { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); From b257f8e9b14ee1eae243b2c462d7582dbf5fb07f Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 17 Feb 2023 15:26:51 -0800 Subject: [PATCH 060/337] [Internal] CTL: Fixes Reservoir Sampling Logic (#3712) * Code changes to fix the reservoir sampling logic in CTL * Code changes to modify help text on reservoir type. * Code changes to address minor code refactor. --- .../Tools/CTL/CTLConfig.cs | 9 +++- .../Tools/CTL/ReservoirProvider.cs | 49 +++++++++++++++++++ .../CTL/Scenarios/ChangeFeedPullScenario.cs | 2 +- .../Tools/CTL/Scenarios/ReadManyScenario.cs | 2 +- .../CTL/Scenarios/ReadWriteQueryScenario.cs | 14 +++--- 5 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/CTL/ReservoirProvider.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs index ae930dd7ba..05064003ce 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs @@ -11,6 +11,7 @@ namespace CosmosCTL using CommandLine.Text; using Microsoft.Azure.Cosmos; using Newtonsoft.Json; + using static CosmosCTL.ReservoirProvider; public class CTLConfig { @@ -76,7 +77,7 @@ public string DiagnosticsThresholdDuration } [Option("ctl_content_response_on_write", Required = false, HelpText = "Should return content response on writes")] - public bool IsContentResponseOnWriteEnabled { get; set; } = true; + public bool? IsContentResponseOnWriteEnabled { get; set; } = true; [Option("ctl_output_event_traces", Required = false, HelpText = "Outputs TraceSource to console")] public bool OutputEventTraces { get; set; } = false; @@ -102,6 +103,12 @@ public string DiagnosticsThresholdDuration [Option("ctl_telemetry_schedule_in_sec", Required = false, HelpText = "telemetry task schedule time in sec")] public string TelemetryScheduleInSeconds { get; set; } + [Option("ctl_reservoir_type", Required = false, HelpText = "Defines the reservoir type. Valid values are: Uniform, SlidingWindow and ExponentialDecay. The default value is SlidingWindow.")] + public ReservoirTypes ReservoirType { get; set; } = ReservoirTypes.SlidingWindow; + + [Option("ctl_reservoir_sample_size", Required = false, HelpText = "The reservoir sample size.")] + public int ReservoirSampleSize { get; set; } = 1028; + internal TimeSpan RunningTimeDurationAsTimespan { get; private set; } = TimeSpan.FromHours(10); internal TimeSpan DiagnosticsThresholdDurationAsTimespan { get; private set; } = TimeSpan.FromSeconds(60); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/ReservoirProvider.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/ReservoirProvider.cs new file mode 100644 index 0000000000..9f655bbd0d --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/ReservoirProvider.cs @@ -0,0 +1,49 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosCTL +{ + using System; + using App.Metrics.ReservoirSampling; + + /// + /// Returns the based on the CTL configuration. + /// + public class ReservoirProvider + { + /// + /// Create and returns a new instance of the based on the CTL configuration. + /// + /// An instance of containing the CTL config params. + /// An implementation of . + public static IReservoir GetReservoir(CTLConfig ctlConfig) + { + return ctlConfig.ReservoirType switch + { + ReservoirTypes.Uniform => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir( + sampleSize: ctlConfig.ReservoirSampleSize), + + ReservoirTypes.SlidingWindow => new App.Metrics.ReservoirSampling.SlidingWindow.DefaultSlidingWindowReservoir( + sampleSize: ctlConfig.ReservoirSampleSize), + + ReservoirTypes.ExponentialDecay => new App.Metrics.ReservoirSampling.ExponentialDecay.DefaultForwardDecayingReservoir( + sampleSize: ctlConfig.ReservoirSampleSize, + alpha: 0.015), + + _ => throw new ArgumentException( + message: "Invalid ReservoirType Specified."), + }; + } + + /// + /// An enum containing different reservoir types. + /// + public enum ReservoirTypes + { + Uniform, + SlidingWindow, + ExponentialDecay + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ChangeFeedPullScenario.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ChangeFeedPullScenario.cs index d549f398d1..65c40864f7 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ChangeFeedPullScenario.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ChangeFeedPullScenario.cs @@ -64,7 +64,7 @@ public async Task RunAsync( DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Seconds, Context = loggingContextIdentifier, - Reservoir = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir() + Reservoir = () => ReservoirProvider.GetReservoir(config) }; Container container = cosmosClient.GetContainer(config.Database, config.Collection); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadManyScenario.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadManyScenario.cs index ae53acb07f..09a84530a6 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadManyScenario.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadManyScenario.cs @@ -76,7 +76,7 @@ public async Task RunAsync( DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Seconds, Context = loggingContextIdentifier, - Reservoir = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir() + Reservoir = () => ReservoirProvider.GetReservoir(config) }; Container container = cosmosClient.GetContainer(config.Database, config.Collection); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadWriteQueryScenario.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadWriteQueryScenario.cs index fe15e4efaa..db85445bef 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadWriteQueryScenario.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Scenarios/ReadWriteQueryScenario.cs @@ -105,34 +105,34 @@ private async Task ExecuteOperationsAsync( CounterOptions querySuccessMeter = new CounterOptions { Name = "#Query Successful Operations", Context = loggingContextIdentifier }; CounterOptions queryFailureMeter = new CounterOptions { Name = "#Query Unsuccessful Operations", Context = loggingContextIdentifier }; - TimerOptions readLatencyTimer = new TimerOptions + TimerOptions readLatencyTimer = new() { Name = "Read latency", MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Seconds, Context = loggingContextIdentifier, - Reservoir = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir() + Reservoir = () => ReservoirProvider.GetReservoir(config) }; - TimerOptions writeLatencyTimer = new TimerOptions + TimerOptions writeLatencyTimer = new () { Name = "Write latency", MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Seconds, Context = loggingContextIdentifier, - Reservoir = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir() + Reservoir = () => ReservoirProvider.GetReservoir(config) }; - TimerOptions queryLatencyTimer = new TimerOptions + TimerOptions queryLatencyTimer = new () { Name = "Query latency", MeasurementUnit = Unit.Requests, DurationUnit = TimeUnit.Milliseconds, RateUnit = TimeUnit.Seconds, Context = loggingContextIdentifier, - Reservoir = () => new App.Metrics.ReservoirSampling.Uniform.DefaultAlgorithmRReservoir() + Reservoir = () => ReservoirProvider.GetReservoir(config) }; SemaphoreSlim concurrencyControlSemaphore = new SemaphoreSlim(config.Concurrency); @@ -178,7 +178,7 @@ private async Task ExecuteOperationsAsync( operation: i, partitionKeyAttributeName: config.CollectionPartitionKey, containers: initializationResult.Containers, - isContentResponseOnWriteEnabled: config.IsContentResponseOnWriteEnabled)), + isContentResponseOnWriteEnabled: config.IsContentResponseOnWriteEnabled.Value)), onSuccess: () => { concurrencyControlSemaphore.Release(); From 94c83f58ed9f83b36b5e42b6a5187b579f666d0d Mon Sep 17 00:00:00 2001 From: Nimit Shah Date: Mon, 27 Feb 2023 07:53:21 -0800 Subject: [PATCH 061/337] Diagnostics: Adds startDate in Summary (#3707) * Adding start date * Updated trace files * PR comment * Committing missing tests --------- Co-authored-by: Matias Quaranta --- .../Tracing/TraceWriter.TraceJsonWriter.cs | 4 ++-- .../Tracing/TraceWriter.TraceTextWriter.cs | 1 + ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 22 +++++++++---------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 10 ++++----- ...eWriterBaselineTests.MiscellanousAsync.xml | 4 ++-- ...neTests.PointOperationsExceptionsAsync.xml | 12 +++++----- ...EndTraceWriterBaselineTests.QueryAsync.xml | 14 ++++++------ ...TraceWriterBaselineTests.ReadFeedAsync.xml | 8 +++---- ...TraceWriterBaselineTests.ReadManyAsync.xml | 4 ++-- ...selineTests.StreamPointOperationsAsync.xml | 8 +++---- ...aselineTests.TypedPointOperationsAsync.xml | 8 +++---- ...raceWriterBaselineTests.ScenariosAsync.xml | 6 ++--- ...TraceWriterBaselineTests.Serialization.xml | 14 ++++++------ .../TraceWriterBaselineTests.TraceData.xml | 14 ++++++------ 15 files changed, 66 insertions(+), 65 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs index 4710f00a2e..74363c8ca1 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs @@ -46,8 +46,8 @@ public static void WriteTrace( if (isRootTrace) { - writer.WriteFieldName("start time"); - writer.WriteStringValue(trace.StartTime.ToString(TraceWriter.HourTimeFormatString)); + writer.WriteFieldName("start datetime"); + writer.WriteStringValue(trace.StartTime.ToString(TraceWriter.DateTimeFormatString)); } writer.WriteFieldName("duration in milliseconds"); writer.WriteNumber64Value(trace.Duration.TotalMilliseconds); diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs index f77307b359..502c87c4fe 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceTextWriter.cs @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos.Tracing internal static partial class TraceWriter { internal static readonly string HourTimeFormatString = "HH:mm:ss:fff"; + internal static readonly string DateTimeFormatString = "yyyy-MM-ddTHH:mm:ss.fffZ"; private static class TraceTextWriter { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 59a5eabf76..d468fe87f5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -61,7 +61,7 @@ @@ -71,7 +71,7 @@ Date: Tue, 28 Feb 2023 01:04:01 +0530 Subject: [PATCH 062/337] [Internal] Client Telemetry: Adds network information in the payload (#3691) * first draft * clean code * add test * fix test * add replica info collection * fix substatuscode and operation type error * fix code * collect http infor in cache also * message to stacktrace * remove rntbd recording from cache * print proper exception message * fix test * cleanup unused code and added few status codes in ignore list * fixed all exception logging * refactor conditions * fix tests --- .../src/Handler/TelemetryHandler.cs | 5 +- .../src/Telemetry/ClientTelemetry.cs | 73 +++++++++++++++---- .../src/Telemetry/ClientTelemetryHelper.cs | 35 +++++++-- .../src/Telemetry/ClientTelemetryOptions.cs | 38 +++++++++- .../Models/ClientTelemetryProperties.cs | 5 ++ .../src/Telemetry/Models/RequestInfo.cs | 66 +++++++++++++++++ .../ClientSideRequestStatisticsTraceDatum.cs | 1 + .../Tracing/TraceData/SummaryDiagnostics.cs | 24 ++++-- .../ClientTelemetryTests.cs | 58 ++++++++++++--- .../ClientTelemetryTests.cs | 57 +++++++++------ 10 files changed, 300 insertions(+), 62 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs diff --git a/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs index 449a981d0d..9d7e504eba 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs @@ -40,11 +40,12 @@ public override async Task SendAsync( resourceType: request.ResourceType, consistencyLevel: request.Headers?[Documents.HttpConstants.HttpHeaders.ConsistencyLevel], requestCharge: response.Headers.RequestCharge, - subStatusCode: response.Headers.SubStatusCode); + subStatusCode: response.Headers.SubStatusCode, + trace: response.Trace); } catch (Exception ex) { - DefaultTrace.TraceError("Error while collecting telemetry information : " + ex.Message); + DefaultTrace.TraceError("Error while collecting telemetry information : {0}", ex); } } return response; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 3f124e2ee0..82e212f7f3 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -17,11 +17,14 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Telemetry.Models; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Collections; using Microsoft.Azure.Documents.Rntbd; using Newtonsoft.Json; using Util; + using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; /// /// This class collects and send all the telemetry information. @@ -53,6 +56,9 @@ internal class ClientTelemetry : IDisposable private ConcurrentDictionary cacheRefreshInfoMap = new ConcurrentDictionary(); + private ConcurrentDictionary requestInfoMap + = new ConcurrentDictionary(); + private int numberOfFailures = 0; /// @@ -182,22 +188,26 @@ private async Task EnrichAndSendAsync() this.RecordSystemUtilization(); this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); - + ConcurrentDictionary operationInfoSnapshot = Interlocked.Exchange(ref this.operationInfoMap, new ConcurrentDictionary()); ConcurrentDictionary cacheRefreshInfoSnapshot = Interlocked.Exchange(ref this.cacheRefreshInfoMap, new ConcurrentDictionary()); + ConcurrentDictionary requestInfoSnapshot + = Interlocked.Exchange(ref this.requestInfoMap, new ConcurrentDictionary()); + this.clientTelemetryInfo.OperationInfo = ClientTelemetryHelper.ToListWithMetricsInfo(operationInfoSnapshot); this.clientTelemetryInfo.CacheRefreshInfo = ClientTelemetryHelper.ToListWithMetricsInfo(cacheRefreshInfoSnapshot); - + this.clientTelemetryInfo.RequestInfo = ClientTelemetryHelper.ToListWithMetricsInfo(requestInfoSnapshot); + await this.SendAsync(); } } catch (Exception ex) { - DefaultTrace.TraceError("Exception in EnrichAndSendAsync() : {0}", ex.Message); + DefaultTrace.TraceError("Exception in EnrichAndSendAsync() : {0}", ex); } DefaultTrace.TraceInformation("Telemetry Job Stopped."); @@ -224,7 +234,7 @@ internal void CollectCacheInfo(string cacheRefreshSource, } DefaultTrace.TraceVerbose($"Collecting cacheRefreshSource {cacheRefreshSource} data for Telemetry."); - + string regionsContacted = ClientTelemetryHelper.GetContactedRegions(regionsContactedList); // Recording Request Latency @@ -249,7 +259,7 @@ internal void CollectCacheInfo(string cacheRefreshSource, } catch (Exception ex) { - DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex.Message); + DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex); } } @@ -266,6 +276,7 @@ internal void CollectCacheInfo(string cacheRefreshSource, /// /// /// + /// internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, HttpStatusCode statusCode, long responseSizeInBytes, @@ -275,17 +286,22 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, ResourceType resourceType, string consistencyLevel, double requestCharge, - SubStatusCodes subStatusCode) + SubStatusCodes subStatusCode, + ITrace trace) { DefaultTrace.TraceVerbose("Collecting Operation data for Telemetry."); - + if (cosmosDiagnostics == null) { throw new ArgumentNullException(nameof(cosmosDiagnostics)); } - string regionsContacted = ClientTelemetryHelper.GetContactedRegions(cosmosDiagnostics.GetContactedRegions()); + // Record Network/Replica Information + SummaryDiagnostics summaryDiagnostics = new SummaryDiagnostics(trace); + this.RecordRntbdResponses(containerId, databaseId, summaryDiagnostics.StoreResponseStatistics.Value); + string regionsContacted = ClientTelemetryHelper.GetContactedRegions(cosmosDiagnostics.GetContactedRegions()); + // Recording Request Latency and Request Charge OperationInfo payloadKey = new OperationInfo(regionsContacted: regionsContacted?.ToString(), responseSizeInBytes: responseSizeInBytes, @@ -307,10 +323,10 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, try { latency.RecordValue(cosmosDiagnostics.GetClientElapsedTime().Ticks); - } + } catch (Exception ex) { - DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex.Message); + DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex); } long requestChargeToRecord = (long)(requestCharge * ClientTelemetryOptions.HistogramPrecisionFactor); @@ -320,10 +336,41 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, } catch (Exception ex) { - DefaultTrace.TraceError("Request Charge Recording Failed by Telemetry. Request Charge Value : {0} Exception : {1} ", requestChargeToRecord, ex.Message); + DefaultTrace.TraceError("Request Charge Recording Failed by Telemetry. Request Charge Value : {0} Exception : {1} ", requestChargeToRecord, ex); } } + /// + /// Records RNTBD calls statistics + /// + /// + /// + /// + private void RecordRntbdResponses(string containerId, string databaseId, List storeResponseStatistics) + { + foreach (StoreResponseStatistics storetatistics in storeResponseStatistics) + { + if (ClientTelemetryOptions.IsEligible((int)storetatistics.StoreResult.StatusCode, (int)storetatistics.StoreResult.SubStatusCode, storetatistics.RequestLatency)) + { + RequestInfo requestInfo = new RequestInfo() + { + DatabaseName = databaseId, + ContainerName = containerId, + Uri = storetatistics.StoreResult.StorePhysicalAddress.ToString(), + StatusCode = (int)storetatistics.StoreResult.StatusCode, + SubStatusCode = (int)storetatistics.StoreResult.SubStatusCode, + Resource = storetatistics.RequestResourceType.ToString(), + Operation = storetatistics.RequestOperationType.ToString(), + }; + + LongConcurrentHistogram latencyHist = this.requestInfoMap.GetOrAdd(requestInfo, x => new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision)); + latencyHist.RecordValue(storetatistics.RequestLatency.Ticks); + } + } + } + /// /// Record CPU and memory usage which will be sent as part of telemetry information /// @@ -349,7 +396,7 @@ private void RecordSystemUtilization() } catch (Exception ex) { - DefaultTrace.TraceError("System Usage Recording Error : {0}", ex.Message); + DefaultTrace.TraceError("System Usage Recording Error : {0} ", ex); } } @@ -427,7 +474,7 @@ await this.tokenProvider.AddAuthorizationHeaderAsync( { this.numberOfFailures++; - DefaultTrace.TraceError("Exception while sending telemetry data : {0}", ex.Message); + DefaultTrace.TraceError("Exception while sending telemetry data : {0}", ex); } finally { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs index dca2ef6b94..2a29ef9454 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs @@ -6,15 +6,12 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System; using System.Collections.Generic; using System.Linq; - using System.Net.Http; using System.Text; - using System.Threading; using System.Threading.Tasks; using HdrHistogram; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Telemetry.Models; - using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Rntbd; internal static class ClientTelemetryHelper @@ -93,7 +90,7 @@ internal static List ToListWithMetricsInfo( OperationInfo payloadForLatency = entry.Key; payloadForLatency.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); payloadForLatency.SetAggregators(entry.Value.latency, ClientTelemetryOptions.TicksToMsFactor); - + payloadWithMetricInformation.Add(payloadForLatency); OperationInfo payloadForRequestCharge = payloadForLatency.Copy(); @@ -103,7 +100,35 @@ internal static List ToListWithMetricsInfo( payloadWithMetricInformation.Add(payloadForRequestCharge); } - DefaultTrace.TraceInformation("Aggregating operation information to list done"); + DefaultTrace.TraceVerbose("Aggregating operation information to list done"); + + return payloadWithMetricInformation; + } + + /// + /// Convert map with request information to list of operations along with request latency and request charge metrics + /// + /// + /// Collection of ReportPayload + internal static List ToListWithMetricsInfo( + IDictionary metrics) + { + DefaultTrace.TraceVerbose("Aggregating RequestInfo information to list started"); + + List payloadWithMetricInformation = new List(); + foreach (KeyValuePair entry in metrics) + { + MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); + + RequestInfo payloadForLatency = entry.Key; + payloadForLatency.Metrics.Add(metricInfo); + + payloadWithMetricInformation.Add(payloadForLatency); + } + + DefaultTrace.TraceVerbose("Aggregating RequestInfo information to list done"); return payloadWithMetricInformation; } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index f114483b07..3b69e0c621 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -4,11 +4,11 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; + using System.Collections.Generic; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Telemetry.Models; using Microsoft.Azure.Documents; using Newtonsoft.Json; - using Util; internal static class ClientTelemetryOptions { @@ -79,7 +79,7 @@ internal static class ClientTelemetryOptions internal const double Percentile99 = 99.0; internal const double Percentile999 = 99.9; internal const string DateFormat = "yyyy-MM-ddTHH:mm:ssZ"; - + internal const string EnvPropsClientTelemetrySchedulingInSeconds = "COSMOS.CLIENT_TELEMETRY_SCHEDULING_IN_SECONDS"; internal const string EnvPropsClientTelemetryEnabled = "COSMOS.CLIENT_TELEMETRY_ENABLED"; internal const string EnvPropsClientTelemetryVmMetadataUrl = "COSMOS.VM_METADATA_URL"; @@ -87,17 +87,20 @@ internal static class ClientTelemetryOptions internal const string EnvPropsClientTelemetryEnvironmentName = "COSMOS.ENVIRONMENT_NAME"; internal static readonly ResourceType AllowedResourceTypes = ResourceType.Document; - + // Why 5 sec? As of now, if any network request is taking more than 5 millisecond sec, we will consider it slow request this value can be revisited in future + private static readonly TimeSpan NetworkLatencyThreshold = TimeSpan.FromMilliseconds(5); internal static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr }; + private static readonly List ExcludedStatusCodes = new List { 404, 409 }; + private static Uri clientTelemetryEndpoint; private static string environmentName; private static TimeSpan scheduledTimeSpan = TimeSpan.Zero; - + internal static bool IsClientTelemetryEnabled() { bool isTelemetryEnabled = ConfigurationManager @@ -175,5 +178,32 @@ internal static string GetEnvironmentName() } return environmentName; } + + /// + /// This method will return true if the request is failed with User or Server Exception and not excluded from telemetry. + /// This method will return true if the request latency is more than the threshold. + /// otherwise return false + /// + /// + /// + /// + /// true/false + internal static bool IsEligible(int statusCode, int subStatusCode, TimeSpan latencyInMs) + { + return + ClientTelemetryOptions.IsStatusCodeNotExcluded(statusCode, subStatusCode) && + (ClientTelemetryOptions.IsUserOrServerError(statusCode) || latencyInMs >= ClientTelemetryOptions.NetworkLatencyThreshold); + } + + private static bool IsUserOrServerError(int statusCode) + { + return statusCode >= 400 && statusCode <= 599; + } + + private static bool IsStatusCodeNotExcluded(int statusCode, int subStatusCode) + { + return !(ClientTelemetryOptions.ExcludedStatusCodes.Contains(statusCode) && subStatusCode == 0); + } + } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs index 87418ac8d7..6ad08f694e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs @@ -60,6 +60,9 @@ internal sealed class ClientTelemetryProperties [JsonProperty(PropertyName = "operationInfo")] internal List OperationInfo { get; set; } + [JsonProperty(PropertyName = "requestInfo")] + internal List RequestInfo { get; set; } + [JsonIgnore] internal bool IsDirectConnectionMode { get; } @@ -97,6 +100,7 @@ public ClientTelemetryProperties(string dateTimeUtc, List systemInfo, List cacheRefreshInfo, List operationInfo, + List requestInfo, string machineId) { this.DateTimeUtc = dateTimeUtc; @@ -111,6 +115,7 @@ public ClientTelemetryProperties(string dateTimeUtc, this.SystemInfo = systemInfo; this.CacheRefreshInfo = cacheRefreshInfo; this.OperationInfo = operationInfo; + this.RequestInfo = requestInfo; this.PreferredRegions = preferredRegions; this.MachineId = machineId; } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs new file mode 100644 index 0000000000..d71f0fa446 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry.Models +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + [Serializable] + internal sealed class RequestInfo + { + [JsonProperty("uri")] + public string Uri { get; set; } + + [JsonProperty("databaseName")] + public string DatabaseName { get; set; } + + [JsonProperty("containerName")] + public string ContainerName { get; set; } + + [JsonProperty("operation")] + public string Operation { get; set; } + + [JsonProperty("resource")] + public string Resource { get; set; } + + [JsonProperty("statusCode")] + public int? StatusCode { get; set; } + + [JsonProperty("subStatusCode")] + public int SubStatusCode { get; set; } + + [JsonProperty("metricInfo")] + public List Metrics { get; set; } = new List(); + + public override int GetHashCode() + { + int hash = 3; + hash = (hash * 7) ^ (this.Uri == null ? 0 : this.Uri.GetHashCode()); + hash = (hash * 7) ^ (this.DatabaseName == null ? 0 : this.DatabaseName.GetHashCode()); + hash = (hash * 7) ^ (this.ContainerName == null ? 0 : this.ContainerName.GetHashCode()); + hash = (hash * 7) ^ (this.Operation == null ? 0 : this.Operation.GetHashCode()); + hash = (hash * 7) ^ (this.Resource == null ? 0 : this.Resource.GetHashCode()); + hash = (hash * 7) ^ (this.StatusCode == null ? 0 : this.StatusCode.GetHashCode()); + hash = (hash * 7) ^ (this.SubStatusCode.GetHashCode()); + return hash; + } + + public override bool Equals(object obj) + { + bool isequal = obj is RequestInfo payload && + ((this.Uri == null && payload.Uri == null) || (this.Uri != null && payload.Uri != null && this.Uri.Equals(payload.Uri))) && + ((this.DatabaseName == null && payload.DatabaseName == null) || (this.DatabaseName != null && payload.DatabaseName != null && this.DatabaseName.Equals(payload.DatabaseName))) && + ((this.ContainerName == null && payload.ContainerName == null) || (this.ContainerName != null && payload.ContainerName != null && this.ContainerName.Equals(payload.ContainerName))) && + ((this.Operation == null && payload.Operation == null) || (this.Operation != null && payload.Operation != null && this.Operation.Equals(payload.Operation))) && + ((this.Resource == null && payload.Resource == null) || (this.Resource != null && payload.Resource != null && this.Resource.Equals(payload.Resource))) && + ((this.StatusCode == null && payload.StatusCode == null) || (this.StatusCode != null && payload.StatusCode != null && this.StatusCode.Equals(payload.StatusCode))) && + this.SubStatusCode.Equals(payload.SubStatusCode); + + return isequal; + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs index e4e160c13a..10845f133f 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs @@ -477,6 +477,7 @@ public StoreResponseStatistics( public string RequestSessionToken { get; } public Uri LocationEndpoint { get; } public bool IsSupplementalResponse { get; } + public TimeSpan RequestLatency => this.RequestResponseTime - this.RequestStartTime.GetValueOrDefault(); } public readonly struct HttpResponseStatistics diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs index b01ddcfb77..1838cb72c5 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs @@ -8,25 +8,31 @@ namespace Microsoft.Azure.Cosmos.Tracing.TraceData using System.Collections.Generic; using System.Globalization; using Microsoft.Azure.Cosmos.Json; + using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; internal struct SummaryDiagnostics { public SummaryDiagnostics(ITrace trace) : this() { - this.DirectRequestsSummary = new Lazy>(() => - new Dictionary<(int, int), int>()); - this.GatewayRequestsSummary = new Lazy>(() => - new Dictionary<(int, int), int>()); - this.AllRegionsContacted = new Lazy>(() => new HashSet()); + this.DirectRequestsSummary + = new Lazy>(() => new Dictionary<(int, int), int>()); + this.GatewayRequestsSummary + = new Lazy>(() => new Dictionary<(int, int), int>()); + this.AllRegionsContacted + = new Lazy>(() => new HashSet()); + this.CollectSummaryFromTraceTree(trace); } + public Lazy> AllRegionsNameContacted { get; private set; } = new Lazy>(() => new HashSet()); public Lazy> AllRegionsContacted { get; private set; } + public Lazy> StoreResponseStatistics { get; private set; } = new Lazy>(() => new List()); // Count of (StatusCode, SubStatusCode) tuples public Lazy> DirectRequestsSummary { get; private set; } + public Lazy> HttpResponseStatistics { get; private set; } = new Lazy>(() => new List()); public Lazy> GatewayRequestsSummary { get; private set; } private void CollectSummaryFromTraceTree(ITrace currentTrace) @@ -49,9 +55,10 @@ private void CollectSummaryFromTraceTree(ITrace currentTrace) private void AggregateRegionsContacted(HashSet<(string, Uri)> regionsContacted) { - foreach ((string _, Uri uri) in regionsContacted) + foreach ((string name, Uri uri) in regionsContacted) { this.AllRegionsContacted.Value.Add(uri); + this.AllRegionsNameContacted.Value.Add(name); } } @@ -59,6 +66,8 @@ private void AggregateGatewayStatistics(IReadOnlyList( await this.WaitAndAssert(expectedOperationCount: 2, expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual, expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedCacheSource: null); + expectedCacheSource: null, + isExpectedNetworkTelemetry: false); } [TestMethod] @@ -303,7 +302,8 @@ await container.ReadItemStreamAsync( await this.WaitAndAssert(expectedOperationCount: 2, expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedCacheSource: null); + expectedCacheSource: null, + isExpectedNetworkTelemetry: false); } [TestMethod] @@ -758,10 +758,11 @@ public async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) { { Documents.OperationType.Create.ToString(), 1} }; - + await this.WaitAndAssert(expectedOperationCount: 2, expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedSubstatuscode: 999999); + expectedSubstatuscode: 999999, + isExpectedNetworkTelemetry: false); } @@ -778,19 +779,23 @@ private async Task WaitAndAssert( IDictionary expectedOperationRecordCountMap = null, int expectedSubstatuscode = 0, bool? isAzureInstance = null, - string expectedCacheSource = "ClientCollectionCache") + string expectedCacheSource = "ClientCollectionCache", + bool isExpectedNetworkTelemetry = true) { Assert.IsNotNull(this.actualInfo, "Telemetry Information not available"); // As this feature is thread based execution so wait for the results to avoid test flakiness List localCopyOfActualInfo = null; ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + HashSet cacheRefreshInfoSet = new HashSet(); do { await Task.Delay(TimeSpan.FromMilliseconds(1500)); // wait at least for 1 round of telemetry HashSet actualOperationSet = new HashSet(); + HashSet requestInfoSet = new HashSet(); + lock (this.actualInfo) { // Setting the number of unique OperationInfo irrespective of response size as response size is varying in case of queries. @@ -830,7 +835,8 @@ private async Task WaitAndAssert( List actualOperationList = new List(); List actualSystemInformation = new List(); - + List actualRequestInformation = new List(); + if (localCopyOfActualInfo[0].ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) { this.expectedMetricNameUnitMap.Add(ClientTelemetryOptions.NumberOfTcpConnectionName, ClientTelemetryOptions.NumberOfTcpConnectionUnit); @@ -840,6 +846,7 @@ private async Task WaitAndAssert( localCopyOfActualInfo: localCopyOfActualInfo, actualOperationList: actualOperationList, actualSystemInformation: actualSystemInformation, + actualRequestInformation: actualRequestInformation, isAzureInstance: isAzureInstance); ClientTelemetryTests.AssertOperationLevelInformation( @@ -858,8 +865,37 @@ private async Task WaitAndAssert( } ClientTelemetryTests.AssertSystemLevelInformation(actualSystemInformation, this.expectedMetricNameUnitMap); + if (localCopyOfActualInfo.First().ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant() + && isExpectedNetworkTelemetry) + { + ClientTelemetryTests.AssertNetworkLevelInformation(actualRequestInformation); + } + else + { + Assert.IsTrue(actualRequestInformation == null || actualRequestInformation.Count == 0, "Request Information is not expected in Gateway mode"); + } } - + + private static void AssertNetworkLevelInformation(List actualRequestInformation) + { + Assert.IsNotNull(actualRequestInformation); + Assert.IsTrue(actualRequestInformation.Count > 0); + + foreach(RequestInfo requestInfo in actualRequestInformation) + { + Assert.IsNotNull(requestInfo.Uri); + Assert.IsNotNull(requestInfo.DatabaseName); + Assert.IsNotNull(requestInfo.ContainerName); + Assert.IsNotNull(requestInfo.Operation); + Assert.IsNotNull(requestInfo.Resource); + Assert.IsNotNull(requestInfo.StatusCode); + Assert.AreNotEqual(0, requestInfo.StatusCode); + Assert.IsNotNull(requestInfo.SubStatusCode); + + Assert.IsNotNull(requestInfo.Metrics, "MetricInfo is null"); + } + } + private static void AssertSystemLevelInformation(List actualSystemInformation, IDictionary expectedMetricNameUnitMap) { IDictionary actualMetricNameUnitMap = new Dictionary(); @@ -903,12 +939,12 @@ private static void AssertOperationLevelInformation( int expectedSubstatuscode = 0) { IDictionary actualOperationRecordCountMap = new Dictionary(); - // Asserting If operation list is as expected foreach (OperationInfo operation in actualOperationList) { Assert.IsNotNull(operation.Operation, "Operation Type is null"); Assert.IsNotNull(operation.Resource, "Resource Type is null"); + Assert.AreEqual(expectedSubstatuscode, operation.SubStatusCode); Assert.AreEqual(expectedConsistencyLevel?.ToString(), operation.Consistency, $"Consistency is not {expectedConsistencyLevel}"); @@ -944,6 +980,7 @@ private static void AssertAccountLevelInformation( List localCopyOfActualInfo, List actualOperationList, List actualSystemInformation, + List actualRequestInformation, bool? isAzureInstance) { ISet machineId = new HashSet(); @@ -953,6 +990,7 @@ private static void AssertAccountLevelInformation( { actualOperationList.AddRange(telemetryInfo.OperationInfo); actualSystemInformation.AddRange(telemetryInfo.SystemInfo); + actualRequestInformation.AddRange(telemetryInfo.RequestInfo); if (telemetryInfo.ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs index 3bbbd1d3ac..b7e5d1f08e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs @@ -30,13 +30,13 @@ public void CheckMetricsAggregationLogic() MetricInfo metrics = new MetricInfo("metricsName", "unitName"); LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, - Int64.MaxValue, + long.MaxValue, 5); - histogram.RecordValue((long)10); - histogram.RecordValue((long)20); - histogram.RecordValue((long)30); - histogram.RecordValue((long)40); + histogram.RecordValue(10); + histogram.RecordValue(20); + histogram.RecordValue(30); + histogram.RecordValue(40); metrics.SetAggregators(histogram); @@ -58,14 +58,14 @@ public void CheckMetricsAggregationLogicWithAdjustment() MetricInfo metrics = new MetricInfo("metricsName", "unitName"); long adjustmentFactor = 1000; - LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, - Int64.MaxValue, - 5); + LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, + long.MaxValue, + 5); - histogram.RecordValue((long)(10 * adjustmentFactor)); - histogram.RecordValue((long)(20 * adjustmentFactor)); - histogram.RecordValue((long)(30 * adjustmentFactor)); - histogram.RecordValue((long)(40 * adjustmentFactor)); + histogram.RecordValue(10 * adjustmentFactor); + histogram.RecordValue(20 * adjustmentFactor); + histogram.RecordValue(30 * adjustmentFactor); + histogram.RecordValue(40 * adjustmentFactor); metrics.SetAggregators(histogram, adjustmentFactor); @@ -85,11 +85,11 @@ public void CheckMetricsAggregationLogicWithAdjustment() [TestMethod] public void CheckJsonSerializerContract() { - string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", - processId: "", - userAgent: null, - connectionMode: ConnectionMode.Direct, - preferredRegions: null, + string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", + processId: "", + userAgent: null, + connectionMode: ConnectionMode.Direct, + preferredRegions: null, aggregationIntervalInSec: 10), ClientTelemetryOptions.JsonSerializerSettings); Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"aggregationIntervalInSec\":10,\"systemInfo\":[]}", json); } @@ -101,21 +101,34 @@ public void CheckJsonSerializerContractWithPreferredRegions() { "region1" }; - string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", - processId: "", - userAgent: null, - connectionMode: ConnectionMode.Direct, + string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", + processId: "", + userAgent: null, + connectionMode: ConnectionMode.Direct, preferredRegions: preferredRegion, aggregationIntervalInSec: 1), ClientTelemetryOptions.JsonSerializerSettings); Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"preferredRegions\":[\"region1\"],\"aggregationIntervalInSec\":1,\"systemInfo\":[]}", json); } [TestMethod] - [ExpectedException(typeof(System.FormatException))] + [ExpectedException(typeof(FormatException))] public void CheckMisconfiguredTelemetry_should_fail() { Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "non-boolean"); using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); } + + [TestMethod] + [DataRow(200, 0 ,1, false)] + [DataRow(404, 0, 1, false)] + [DataRow(404, 1002, 1, true)] + [DataRow(409, 0, 1, false)] + [DataRow(409, 1002, 1, true)] + [DataRow(503, 2001, 1, true)] + [DataRow(200, 0, 6, true)] + public void CheckEligibleStatistics(int statusCode, int subStatusCode, int latencyInMs, bool expectedFlag) + { + Assert.AreEqual(expectedFlag, ClientTelemetryOptions.IsEligible(statusCode, subStatusCode, TimeSpan.FromMilliseconds(latencyInMs))); + } } } From 0088c2f8e4f8562c03f06ff852337b6aeca7d75c Mon Sep 17 00:00:00 2001 From: SaurabhSharma-MSFT <38112130+SaurabhSharma-MSFT@users.noreply.github.com> Date: Tue, 28 Feb 2023 19:31:29 -0800 Subject: [PATCH 063/337] Documentation: Fixes Database.ReadAsync description (#3457) * Documentation: Modify retry time to timespan Modify retry time in seconds to timespan of parameter maxRetryWaitTimeOnThrottledRequests (Method: [WithThrottlingRetryOptions](https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.fluent.cosmosclientbuilder.withthrottlingretryoptions?view=azure-dotnet#feedback)) Resolves https://github.com/Azure/azure-sdk-for-net/issues/29567 * Documentation: Fixes DeleteItemAsync Example Documentation: Fixes DeleteItemAsync Example * Documentation: Fixes ItemRequestOptions Example Documentation: Fixes ItemRequestOptions Example * Documentation:Update Database.ReadAsync description Documentation: Update Database.ReadAsync description * Documentation: Update Database.ReadAsync description Documentation: Update Database.ReadAsync description * Documentation: Updated ToStreamIterator example Documentation: Updated ToStreamIterator example * Modified StreamIterator section * Update Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs Co-authored-by: Matias Quaranta * Remarks correction * Revert the StreamIterator changes Revert the StreamIterator changes Co-authored-by: Matias Quaranta Co-authored-by: Kiran Kumar Kolli --- Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs | 2 +- Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs index baddf0fe31..dc86de0cb6 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs @@ -186,7 +186,7 @@ public static FeedIterator ToFeedIterator(this IQueryable query) /// /// linqQueryable = this.Container.GetItemLinqQueryable(); - /// using (FeedIterator setIterator = linqQueryable.Where(item => (item.taskNum < 100)).ToFeedIterator() + /// using (FeedIterator setIterator = linqQueryable.Where(item => (item.taskNum < 100)).ToStreamIterator()) /// ]]> /// /// diff --git a/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs b/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs index a59dcb8be9..8a62f9ec56 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs @@ -31,8 +31,8 @@ public abstract class Database /// public abstract CosmosClient Client { get; } - /// - /// Reads a from the Azure Cosmos service as an asynchronous operation. + /// + /// Reads a from the Azure Cosmos service as an asynchronous operation. /// /// (Optional) The options for the request. /// (Optional) representing request cancellation. @@ -40,6 +40,9 @@ public abstract class Database /// A containing a which wraps a containing the read resource record. /// /// https://aka.ms/cosmosdb-dot-net-exceptions + /// + /// contains the that include the resource information. + /// /// /// /// Date: Wed, 1 Mar 2023 08:02:15 -0800 Subject: [PATCH 064/337] Upgrade Resiliency: Adds Implementation for Validating the Unhealthy Backend Replicas in Direct mode (#3631) * Code changes to implement replica validation in dotnet v3 sdk. * Cosmetic changes to add inline code comments. * Code chages to address review comments. * Code changes to cover a scenario for async cache. * Code changes to refactor async non-blocking cache code. * Code changes to address minor review comments. --------- Co-authored-by: Kiran Kumar Kolli --- .../src/Routing/AsyncCacheNonBlocking.cs | 93 +++- .../src/Routing/GatewayAddressCache.cs | 154 +++++++ .../GatewayAddressCacheTests.cs | 433 +++++++++++++++++- .../Routing/AsyncCacheNonBlockingTests.cs | 145 ++++++ .../Utils/ReflectionUtils.cs | 43 ++ docs/ReplicaValidationDesign.md | 338 ++++++++++++++ 6 files changed, 1180 insertions(+), 26 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/ReflectionUtils.cs create mode 100644 docs/ReplicaValidationDesign.md diff --git a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs index 2b1f82ea3a..9fb908d83f 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs @@ -120,30 +120,11 @@ public async Task GetAsync( throw; } - try - { - return await initialLazyValue.CreateAndWaitForBackgroundRefreshTaskAsync( - createRefreshTask: singleValueInitFunc); - } - catch (Exception e) - { - if (initialLazyValue.ShouldRemoveFromCacheThreadSafe()) - { - DefaultTrace.TraceError( - "AsyncCacheNonBlocking.GetAsync with ForceRefresh Failed. key: {0}, Exception: {1}", - key, - e); - - // In some scenarios when a background failure occurs like a 404 - // the initial cache value should be removed. - if (this.removeFromCacheOnBackgroundRefreshException(e)) - { - this.TryRemove(key); - } - } - - throw; - } + return await this.UpdateCacheAndGetValueFromBackgroundTaskAsync( + key: key, + initialValue: initialLazyValue, + callbackDelegate: singleValueInitFunc, + operationName: nameof(GetAsync)); } // The AsyncLazyWithRefreshTask is lazy and won't create the task until GetValue is called. @@ -196,6 +177,70 @@ public bool TryRemove(TKey key) return this.values.TryRemove(key, out _); } + /// + /// Refreshes the async non blocking cache on-demand for the given + /// and caches the result for later usage. + /// + /// The requested key to be refreshed. + /// A func delegate to be invoked at a later point of time. + public async Task RefreshAsync( + TKey key, + Func> singleValueInitFunc) + { + if (this.values.TryGetValue(key, out AsyncLazyWithRefreshTask initialLazyValue)) + { + await this.UpdateCacheAndGetValueFromBackgroundTaskAsync( + key: key, + initialValue: initialLazyValue, + callbackDelegate: singleValueInitFunc, + operationName: nameof(RefreshAsync)); + } + } + + /// + /// Creates a background task to invoke the callback delegate and updates the cache with the value returned from the delegate. + /// + /// The requested key to be updated. + /// An instance of containing the initial cached value. + /// A func callback delegate to be invoked at a later point of time. + /// A string indicating the operation on the cache. + /// A containing the updated, refreshed value. + private async Task UpdateCacheAndGetValueFromBackgroundTaskAsync( + TKey key, + AsyncLazyWithRefreshTask initialValue, + Func> callbackDelegate, + string operationName) + { + try + { + return await initialValue.CreateAndWaitForBackgroundRefreshTaskAsync( + createRefreshTask: callbackDelegate); + } + catch (Exception ex) + { + if (initialValue.ShouldRemoveFromCacheThreadSafe()) + { + bool removed = false; + + // In some scenarios when a background failure occurs like a 404 + // the initial cache value should be removed. + if (this.removeFromCacheOnBackgroundRefreshException(ex)) + { + removed = this.TryRemove(key); + } + + DefaultTrace.TraceError( + "AsyncCacheNonBlocking Failed. key: {0}, operation: {1}, tryRemoved: {2}, Exception: {3}", + key, + operationName, + removed, + ex); + } + + throw; + } + } + /// /// This is AsyncLazy that has an additional Task that can /// be used to update the value. This allows concurrent requests diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 7c6355591e..b577443761 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -46,6 +46,7 @@ internal class GatewayAddressCache : IAddressCache, IDisposable private readonly bool enableTcpConnectionEndpointRediscovery; private readonly CosmosHttpClient httpClient; + private readonly bool isReplicaAddressValidationEnabled; private Tuple masterPartitionAddressCache; private DateTime suboptimalMasterPartitionTimestamp; @@ -84,10 +85,27 @@ public GatewayAddressCache( GatewayAddressCache.ProtocolString(this.protocol)); this.openConnectionsHandler = openConnectionsHandler; + this.isReplicaAddressValidationEnabled = Helpers.GetEnvironmentVariableAsBool( + name: Constants.EnvironmentVariables.ReplicaConnectivityValidationEnabled, + defaultValue: false); } public Uri ServiceEndpoint => this.serviceEndpoint; + /// + /// Gets the address information from the gateway and sets them into the async non blocking cache for later lookup. + /// Additionally attempts to establish Rntbd connections to the backend replicas based on `shouldOpenRntbdChannels` + /// boolean flag. + /// + /// A string containing the database name. + /// An instance of containing the collection properties. + /// A read only list containing the partition key range identities. + /// A boolean flag indicating whether Rntbd connections are required to be established + /// to the backend replica nodes. For cosmos client initialization and cache warmups, the Rntbd connection are needed to be + /// openned deterministically to the backend replicas to reduce latency, thus the + /// should be set to `true` during cosmos client initialization and cache warmups. The OpenAsync flow from DocumentClient + /// doesn't require the connections to be opened deterministically thus should set the parameter to `false`. + /// An instance of . public async Task OpenConnectionsAsync( string databaseName, ContainerProperties collection, @@ -161,6 +179,10 @@ public async Task OpenConnectionsAsync( new PartitionKeyRangeIdentity(collection.ResourceId, addressInfo.Item1.PartitionKeyRangeId), addressInfo.Item2); + // The `shouldOpenRntbdChannels` boolean flag indicates whether the SDK should establish Rntbd connections to the + // backend replica nodes. For the `CosmosClient.CreateAndInitializeAsync()` flow, the flag should be passed as + // `true` so that the Rntbd connections to the backend replicas could be established deterministically. For any + // other flow, the flag should be passed as `false`. if (this.openConnectionsHandler != null && shouldOpenRntbdChannels) { await this.openConnectionsHandler @@ -178,6 +200,7 @@ public void SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHan this.openConnectionsHandler = openConnectionsHandler; } + /// public async Task TryGetAddressesAsync( DocumentServiceRequest request, PartitionKeyRangeIdentity partitionKeyRangeIdentity, @@ -229,6 +252,7 @@ public async Task TryGetAddressesAsync( return this.GetAddressesForRangeIdAsync( request, + cachedAddresses: currentCachedValue, partitionKeyRangeIdentity.CollectionRid, partitionKeyRangeIdentity.PartitionKeyRangeId, forceRefresh: forceRefreshPartitionAddresses); @@ -259,6 +283,7 @@ public async Task TryGetAddressesAsync( key: partitionKeyRangeIdentity, singleValueInitFunc: (_) => this.GetAddressesForRangeIdAsync( request, + cachedAddresses: null, partitionKeyRangeIdentity.CollectionRid, partitionKeyRangeIdentity.PartitionKeyRangeId, forceRefresh: false), @@ -278,6 +303,27 @@ public async Task TryGetAddressesAsync( this.suboptimalServerPartitionTimestamps.TryAdd(partitionKeyRangeIdentity, DateTime.UtcNow); } + // Refresh the cache on-demand, if there were some address that remained as unhealthy long enough (more than 1 minute) + // and need to revalidate its status. The reason it is not dependent on 410 to force refresh the addresses, is being: + // When an address is marked as unhealthy, then the address enumerator will deprioritize it and move it back to the + // end of the transport uris list. Therefore, it could happen that no request will land on the unhealthy address for + // an extended period of time therefore, the chances of 410 (Gone Exception) to trigger the forceRefresh workflow may + // not happen for that particular replica. + if (addresses + .Get(Protocol.Tcp) + .ReplicaTransportAddressUris + .Any(x => x.ShouldRefreshHealthStatus())) + { + Task refreshAddressesInBackgroundTask = Task.Run(async () => await this.serverPartitionAddressCache.RefreshAsync( + key: partitionKeyRangeIdentity, + singleValueInitFunc: (currentCachedValue) => this.GetAddressesForRangeIdAsync( + request, + cachedAddresses: currentCachedValue, + partitionKeyRangeIdentity.CollectionRid, + partitionKeyRangeIdentity.PartitionKeyRangeId, + forceRefresh: true))); + } + return addresses; } catch (DocumentClientException ex) @@ -384,6 +430,7 @@ public async Task UpdateAsync( key: partitionKeyRangeIdentity, singleValueInitFunc: (_) => this.GetAddressesForRangeIdAsync( null, + cachedAddresses: null, partitionKeyRangeIdentity.CollectionRid, partitionKeyRangeIdentity.PartitionKeyRangeId, forceRefresh: true), @@ -444,6 +491,7 @@ private async Task private async Task GetAddressesForRangeIdAsync( DocumentServiceRequest request, + PartitionAddressInformation cachedAddresses, string collectionRid, string partitionKeyRangeId, bool forceRefresh) @@ -475,6 +523,32 @@ await this.GetServerAddressesViaGatewayAsync(request, collectionRid, new[] { par throw new PartitionKeyRangeGoneException(errorMessage) { ResourceAddress = collectionRid }; } + if (this.isReplicaAddressValidationEnabled) + { + // The purpose of this step is to merge the new transport addresses with the old one. What this means is - + // 1. If a newly returned address from gateway is already a part of the cache, then restore the health state + // of the new address with that of the cached one. + // 2. If a newly returned address from gateway doesn't exist in the cache, then keep using the new address + // with `Unknown` (initial) status. + PartitionAddressInformation mergedAddresses = GatewayAddressCache.MergeAddresses(result.Item2, cachedAddresses); + IReadOnlyList transportAddressUris = mergedAddresses.Get(Protocol.Tcp)?.ReplicaTransportAddressUris; + + // If cachedAddresses are null, that would mean that the returned address from gateway would remain in Unknown + // status and there is no cached state that could transition them into Unhealthy. + if (cachedAddresses != null) + { + foreach (TransportAddressUri address in transportAddressUris) + { + // The main purpose for this step is to move address health status from Unhealthy to UnhealthyPending. + address.SetRefreshedIfUnhealthy(); + } + } + + this.ValidateUnhealthyPendingReplicas(transportAddressUris); + + return mergedAddresses; + } + return result.Item2; } } @@ -760,6 +834,86 @@ await this.GetServerAddressesViaGatewayAsync( } } + /// + /// Validates the unhealthy pending replicas by attempting to open the Rntbd connection. This operation + /// will eventually marks the unhealthy pending replicas to healthy, if the rntbd connection attempt made was + /// successful or unhealthy otherwise. + /// + /// A read-only list of needs to be validated. + private void ValidateUnhealthyPendingReplicas( + IReadOnlyList addresses) + { + if (addresses == null) + { + throw new ArgumentNullException(nameof(addresses)); + } + + IEnumerable addressesNeedToValidation = addresses + .Where(address => address + .GetCurrentHealthState() + .GetHealthStatus() == TransportAddressHealthState.HealthStatus.UnhealthyPending); + + if (addressesNeedToValidation.Any()) + { + Task openConnectionsInBackgroundTask = Task.Run(async () => await this.openConnectionsHandler.TryOpenRntbdChannelsAsync( + addresses: addressesNeedToValidation.ToList())); + } + } + + /// + /// Merge the new addresses returned from gateway service with that of the cached addresses. If the returned + /// new addresses list contains some of the addresses, which are already cached, then reset the health state + /// of the new address to that of the cached one. If the the new addresses doesn't contain any of the cached + /// addresses, then keep using the health state of the new addresses, which should be `unknown`. + /// + /// A list of containing the latest + /// addresses being returned from gateway. + /// A list of containing the cached + /// addresses from the async non blocking cache. + /// A list of containing the merged addresses. + private static PartitionAddressInformation MergeAddresses( + PartitionAddressInformation newAddresses, + PartitionAddressInformation cachedAddresses) + { + if (newAddresses == null) + { + throw new ArgumentNullException(nameof(newAddresses)); + } + + if (cachedAddresses == null) + { + return newAddresses; + } + + PerProtocolPartitionAddressInformation currentAddressInfo = newAddresses.Get(Protocol.Tcp); + PerProtocolPartitionAddressInformation cachedAddressInfo = cachedAddresses.Get(Protocol.Tcp); + Dictionary cachedAddressDict = new (); + + foreach (TransportAddressUri transportAddressUri in cachedAddressInfo.ReplicaTransportAddressUris) + { + cachedAddressDict[transportAddressUri.ToString()] = transportAddressUri; + } + + foreach (TransportAddressUri transportAddressUri in currentAddressInfo.ReplicaTransportAddressUris) + { + if (cachedAddressDict.ContainsKey(transportAddressUri.ToString())) + { + TransportAddressUri cachedTransportAddressUri = cachedAddressDict[transportAddressUri.ToString()]; + transportAddressUri.ResetHealthStatus( + status: cachedTransportAddressUri.GetCurrentHealthState().GetHealthStatus(), + lastUnknownTimestamp: cachedTransportAddressUri.GetCurrentHealthState().GetLastKnownTimestampByHealthStatus( + healthStatus: TransportAddressHealthState.HealthStatus.Unknown), + lastUnhealthyPendingTimestamp: cachedTransportAddressUri.GetCurrentHealthState().GetLastKnownTimestampByHealthStatus( + healthStatus: TransportAddressHealthState.HealthStatus.UnhealthyPending), + lastUnhealthyTimestamp: cachedTransportAddressUri.GetCurrentHealthState().GetLastKnownTimestampByHealthStatus( + healthStatus: TransportAddressHealthState.HealthStatus.Unhealthy)); + + } + } + + return newAddresses; + } + protected virtual void Dispose(bool disposing) { if (this.disposedValue) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 3954b4ae8f..9e3b87ec83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -6,16 +6,15 @@ namespace Microsoft.Azure.Cosmos using System; using System.Collections.Generic; using System.Collections.ObjectModel; - using System.Collections.Specialized; using System.Linq; using System.Net; using System.Net.Http; + using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Common; using Microsoft.Azure.Cosmos.Routing; - using Microsoft.Azure.Cosmos.Serialization.HybridRow; using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; @@ -872,6 +871,436 @@ await cache.OpenConnectionsAsync( expectedSuccessCount: addresses.Count); } + /// + /// Test to validate that when replica validation is enabled and force address refresh happens to fetch the latest address from gateway, + /// if in case the gateway returns the same address which was previously unhealthy, the gateway address cache resets the returned status + /// to unhealthy and validates that replica using the open connection handler and finally marks it to connected. + /// + [TestMethod] + [Owner("dkunda")] + public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidateUnhealthyReplicasHealth() + { + // Arrange. + ManualResetEvent manualResetEvent = new(initialState: false); + Mock mockHttpHandler = new (MockBehavior.Strict); + string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; + string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; + string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + oldAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })); + + FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + failingIndexes: new HashSet(), + manualResetEvent: manualResetEvent); + + HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new ( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Documents.Client.Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2, + enableTcpConnectionEndpointRediscovery: true); + + // By default, the replica validation feature is disabled in GatewayAddressCache. Reflection is used to enable the feature + // for the purpose of this test. + FieldInfo fieldInfo = cache + .GetType() + .GetField( + name: "isReplicaAddressValidationEnabled", + bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); + + fieldInfo.SetValue( + obj: cache, + value: true); + + DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); + + // Act and Assert. + PartitionAddressInformation addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + TransportAddressUri refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Unknown, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + // Because force refresh is requested, an unhealthy replica is added to the failed endpoint so that it's status could be validted. + request.RequestContext.FailedEndpoints.Value.Add( + new TransportAddressUri( + addressUri: new Uri( + uriString: addressTobeMarkedUnhealthy))); + + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: true, + cancellationToken: CancellationToken.None); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: false); + + refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Connected, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + mockHttpHandler.VerifyAll(); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 1, + expectedSuccessCount: 1); + } + + /// + /// Test to validate that when replica validation is enabled and there exists a replica such that it remained unhealthy for a period of one minute or + /// more, then even though a force refresh is not requested, the unhealthy replicas at least get a chance to re-validate it's status by the + /// on-demand async non-blocking cache refresh flow and eventually marks itself as healthy once the open connection attempt is successful. + /// + [TestMethod] + [Owner("dkunda")] + public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUriExistsForOneMinute_ShouldForceRefreshUnhealthyReplicas() + { + // Arrange. + ManualResetEvent manualResetEvent = new (initialState: false); + Mock mockHttpHandler = new(MockBehavior.Strict); + string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; + string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; + string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + oldAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })); + + FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + failIndexesByAttempts: new Dictionary>() + { + { 0, new HashSet() { 0 } } + }, + manualResetEvent: manualResetEvent); + + HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new ( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Documents.Client.Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2, + enableTcpConnectionEndpointRediscovery: true); + + // By default, the replica validation feature is disabled in GatewayAddressCache. Reflection is used to enable the feature + // for the purpose of this test. + FieldInfo fieldInfo = cache + .GetType() + .GetField( + name: "isReplicaAddressValidationEnabled", + bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); + + fieldInfo.SetValue( + obj: cache, + value: true); + + DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); + + // Act and Assert. + PartitionAddressInformation addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + TransportAddressUri refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Unknown, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + // Because force refresh is requested, an unhealthy replica is added to the failed endpoint so that it's health status could be validted. + request.RequestContext.FailedEndpoints.Value.Add( + new TransportAddressUri( + addressUri: new Uri( + uriString: addressTobeMarkedUnhealthy))); + + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: true, + cancellationToken: CancellationToken.None); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: true); + + // During the replica validation flow, the connection attempt was not successful thus the replica + // was marked unhealthy. + refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Unhealthy, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 1, + expectedMethodInvocationCount: 1, + expectedReceivedAddressesCount: 1, + expectedSuccessCount: 0); + + // A delay of 2 minute was added to make the replica unhealthy for more than one minute. This + // will make sure the unhealthy replica gets a chance to re-validate it's health status. + ReflectionUtils.AddMinuteToDateTimeFieldUsingReflection( + objectName: refreshedUri.GetCurrentHealthState(), + fieldName: "lastUnhealthyTimestamp", + delayInMinutes: -2); + + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: false); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 1, + expectedMethodInvocationCount: 2, + expectedReceivedAddressesCount: 1, + expectedSuccessCount: 1); + + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + // Because the open connection attempt to the unhealthy replica was successful, the replica was + // marked as healthy. + mockHttpHandler.VerifyAll(); + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Connected, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + // This assertion makes sure that no additional calls were made to the open connection handler after + // since the last address refresh, because all the replicas are now either Unknown or Connected. + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 1, + expectedMethodInvocationCount: 2, + expectedReceivedAddressesCount: 1, + expectedSuccessCount: 1); + } + + /// + /// Test to validate that when replica validation is disabled and there exists some unhealthy replicas, the gateway address + /// cache doesn't validate the health state of the unhealthy replicas. + /// + [TestMethod] + [Owner("dkunda")] + public async Task TryGetAddressesAsync_WhenReplicaVlidationDisabled_ShouldNotValidateUnhealthyReplicas() + { + // Arrange. + Mock mockHttpHandler = new(MockBehavior.Strict); + string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; + string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; + string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + oldAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })); + + FakeOpenConnectionHandler fakeOpenConnectionHandler = new(failingIndexes: new HashSet()); + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Documents.Client.Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2, + enableTcpConnectionEndpointRediscovery: true); + + DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); + + // Act and Assert. + PartitionAddressInformation addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + // Because force refresh is requested, an unhealthy replica is added to the failed endpoint so that it's status could be validted. + request.RequestContext.FailedEndpoints.Value.Add( + new TransportAddressUri( + addressUri: new Uri( + uriString: addressTobeMarkedUnhealthy))); + + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: true, + cancellationToken: CancellationToken.None); + + Assert.AreEqual(4, addressInfo.AllAddresses.Count); + Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); + Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); + + TransportAddressUri refreshedUri = addressInfo + .Get(Documents.Client.Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + Assert.IsNotNull(refreshedUri); + Assert.AreEqual( + expected: TransportAddressHealthState.HealthStatus.Unknown, + actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + + mockHttpHandler.VerifyAll(); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedExceptionCount: 0, + expectedMethodInvocationCount: 0, + expectedReceivedAddressesCount: 0, + expectedSuccessCount: 0); + } + + /// + /// Blocks the current thread until a completion signal on the ManualResetEvent + /// is received. A timeout of 5 seconds is added to avoid any thread starvation. + /// + /// An instance of . + /// A boolean flag indicating if a Reset on the manualResetEvent is required. + private static void WaitForManualResetEventSignal( + ManualResetEvent manualResetEvent, + bool shouldReset) + { + manualResetEvent.WaitOne( + millisecondsTimeout: 5000); + + if (shouldReset) + { + manualResetEvent.Reset(); + } + } + /// /// Helper method to assert on the class attributes /// to match with that of the expected ones. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs index d5250b0408..d58ab3db5b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs @@ -392,5 +392,150 @@ await asyncCache.GetAsync( Assert.AreEqual(1, totalLazyCalls); Assert.AreEqual("Test3", result); } + + /// + /// Test to validate that when RefreshAsync() is invoked for a valid existing key, the + /// cache refreshes the key successfully and the new value is updated in the cache. + /// + [TestMethod] + [Owner("dkunda")] + public async Task RefreshAsync_WhenRefreshRequestedForAnExistingKey_ShouldRefreshTheCache() + { + // Arrange. + AsyncCacheNonBlocking asyncCache = new (); + + // Act and Assert. + string result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value1"), + (_) => false); + + Assert.AreEqual("value1", result); + + await asyncCache.RefreshAsync( + "key", + (_) => Task.FromResult("value2")); + + result = await asyncCache.GetAsync( + "key", + (_) => throw new Exception("Should not refresh."), + (_) => false); + + Assert.AreEqual("value2", result); + } + + /// + /// Test to validate that when a DocumentClientException is thrown during RefreshAsync() operation, + /// then the cache removes the key for which a refresh was requested. + /// + [TestMethod] + [Owner("dkunda")] + public async Task RefreshAsync_WhenThrowsDocumentClientException_ShouldRemoveKeyFromTheCache() + { + // Arrange. + AsyncCacheNonBlocking asyncCache = new (); + + // Act and Assert. + string result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value1"), + (_) => false); + + Assert.AreEqual("value1", result); + + result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value2"), + (_) => false); + + // Because the key is already present in the cache and a force refresh was not requested + // the func delegate should not get invoked and thus the cache should not be updated + // and still return the old cached value. + Assert.AreEqual("value1", result); + + NotFoundException notFoundException = new ( + message: "Item was deleted."); + try + { + await asyncCache.RefreshAsync( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw notFoundException; + }); + Assert.Fail("Should throw a NotFoundException"); + } + catch (NotFoundException exception) + { + Assert.AreEqual(notFoundException, exception); + } + + // Because the key was deleted from the cache, the func delegate should get invoked at + // this point and update the value to value2. + result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value2"), + (_) => false); + + Assert.AreEqual("value2", result); + } + + /// + /// Test to validate that when some other Exception is thrown during RefreshAsync() operation, + /// then the cache does not remove the key for which the refresh was originally requested. + /// + [TestMethod] + [Owner("dkunda")] + public async Task RefreshAsync_WhenThrowsOtherException_ShouldNotRemoveKeyFromTheCache() + { + // Arrange. + AsyncCacheNonBlocking asyncCache = new(); + + // Act and Assert. + string result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value1"), + (_) => false); + + Assert.AreEqual("value1", result); + + result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value2"), + (_) => false); + + // Because the key is already present in the cache and a force refresh was not requested + // the func delegate should not get invoked and thus the cache should not be updated + // and still return the old cached value. + Assert.AreEqual("value1", result); + + Exception exception = new( + message: "Timeout exception."); + try + { + await asyncCache.RefreshAsync( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw exception; + }); + Assert.Fail("Should throw a NotFoundException"); + } + catch (Exception ex) + { + Assert.AreEqual(ex, exception); + } + + // Because the key should not get deleted from the cache, the func delegate should not get invoked at + // this point. + result = await asyncCache.GetAsync( + "key", + (_) => Task.FromResult("value2"), + (_) => false); + + Assert.AreEqual("value1", result); + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/ReflectionUtils.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/ReflectionUtils.cs new file mode 100644 index 0000000000..78bf6fafb2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/ReflectionUtils.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests +{ + using System; + using System.Reflection; + + /// + /// Common utility class for reflaction related operations. + /// + internal static class ReflectionUtils + { + /// + /// This helper method uses reflection to set the private and read only fields + /// to the disered values to help the test cases mimic the expected behavior. + /// + /// An object where reflection will be applied to update the field. + /// A string containing the internal field name. + /// An integer to add or substract the desired delay in minutes. + internal static void AddMinuteToDateTimeFieldUsingReflection( + object objectName, + string fieldName, + int delayInMinutes) + { + FieldInfo fieldInfo = objectName + .GetType() + .GetField( + name: fieldName, + bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); + + DateTime? fieldValue = (DateTime?)fieldInfo + .GetValue( + obj: objectName); + + fieldInfo + .SetValue( + obj: objectName, + value: ((DateTime)fieldValue).AddMinutes(delayInMinutes)); + } + } +} diff --git a/docs/ReplicaValidationDesign.md b/docs/ReplicaValidationDesign.md new file mode 100644 index 0000000000..0e23db09d7 --- /dev/null +++ b/docs/ReplicaValidationDesign.md @@ -0,0 +1,338 @@ +# Design Approach to Validate Backend Replicas During Service Upgrade in Direct Mode + +## Table of Contents + +* [Scope.](#scope) +* [Backgraound.](#backgraound) +* [Proposed Solution.](#proposed-solution) +* [Design Approach.](#design-approach) + * [Outline.](#outline) + * [Updated Sequence Diagram for `CosmosClient` initialization.](#updated-sequence-diagram-for-cosmosclient-initialization) + * [Sequence Diagram when `StoreReader` invokes the `GatewayAddressCache` to resolve addresses and leverages `AddressEnumerator` to enumerate the transport addresses.](#sequence-diagram-when-storereader-invokes-the-gatewayaddresscache-to-resolve-addresses-and-leverages-addressenumerator-to-enumerate-the-transport-addresses) + * [State Diagram to Understand the `TransportAddressUri` Health State Transformations.](#state-diagram-to-understand-the-transportaddressuri-health-state-transformations) + * [`Microsoft.Azure.Cosmos.Direct` package class diagrams.](#azurecosmosdirect-package-class-diagrams) + * [`Microsoft.Azure.Cosmos` package class diagrams.](#microsoftazurecosmos-package-class-diagrams) +* [Pull Request with Sample Code Changes.](#pull-request-with-sample-code-changes) +* [References.](#references) + +## Scope + +The scope of the replica validation workstream is targed for the `CosmosClient` configured for `Direct` mode. + +## Backgraund + +During an upgrade scenario in the backend replica nodes, there has been an observation of increased request latency. One of the primary reason for the latency is that, during an upgrade, a replica which is still undergoing upgrade may still be returned back to SDK, when an address refresh occurres. As of today, the incoming request will have `25%` chance to hit the replica that not ready yet, therefore causing the `ConnectionTimeoutException`, which contributes to the increased latency. + +To understand the problem statement better, please take a look at the below sequence diagram which reflects the connection timeouts caused by the replica upgrade. + +```mermaid +sequenceDiagram + autonumber + participant A as StoreReader
[Direct Code] + participant B as GlobalAddressResolver
[v3 Code] + participant C as GatewayAddressCache
[v3 Code] + participant D as GatewayService
[External Service] + participant E as BackendReplica
[A Replica Node Still Undergoing Upgrade
Address: rntbd://test.azure.com:443/partitions/2s] + A->>+B: Request (forceRefresh - false) + B->>+C: TryGetAddresses (forceRefresh - false) + C->>-B: Fetch Cached Addresses
rntbd://test.azure.com:443/partitions/2s + B->>-A: Return Addresses
rntbd://test.azure.com:443/partitions/2s + A->>+E: Request Sent to Backend Replica + E-x-A: Request fails with 410 GoneException + A->>+B: Request (forceRefresh - true)
GoneWithRetryAttempt + B->>+C: TryGetAddresses (forceRefresh - true) + C->>+D: GetServerAddresses + D->>-C: Returns the new refreshed addresses
rntbd://test.azure.com:443/partitions/2s + Note over D: Note that the returned addresses from
GatewayService may still undergoing
the upgrade, thus and they are not in a ready state. + C->>-B: Returns the refreshed addresses
rntbd://test.azure.com:443/partitions/2s + B->>-A: Returns the refreshed addresses
rntbd://test.azure.com:443/partitions/2s + A->>+E: Request Sent to Backend Replica + E-x-A: Request fails again with 410 GoneException + Note over A: Note that the request fails to connect to the replica
which causes a "ConnectionTimeoutException". +``` + +## Proposed Solution + +The .NET SDK will track the replica endpoint health based on client side metrics, and de-prioritize any replica which were marked as - `Unhealthy`. SDK will validate the health of the replica by attempting to open RNTBD connections to the backend. When SDK refresh addresses back from gateway for a partition, **SDK will only validate the replica/s which were in `Unhealthy` status, by opening RNTBD connection requests**. This process will be completed with best effort, which means: + +- If the validation can not finish within `1 min` of opening connections, the de-prioritize will stop for certain status. + +- The selection of the replica will not be blocked by the validation process. To better understand this - if a request needs to be sent to `N` replicas, and if there is only `N-1` replica in good status, it will still go ahead selecting the `Nth` replica which needs validation. + +- It is opt in only for now, by setting the environment variable `AZURE_COSMOS_REPLICA_VALIDATION_ENABLED` to `true`. + +## Design Approach + +### Outline + +The basic idea for this design approach has been divited into *three* parts, which has been mentioned below in detail: + +- Maintain `4` new health statuses into the `TransportAddressUri`, which are : + + - **`Connected`** (Indicates that there is already a connection made successfully to the backend replica) + - **`Unknown`** (Indicates that the connection exists however the status is unknown at the moment) + - **`Unhealthy Pending`** (Indicates that the connection was unhealthy previously, but an attempt will be made to validate the replica to check the current status) + - **`Unhealthy`** (Indicates that the connection is unhealthy at the moment) + +- Validate the `Unhealthy` replicas returned from the Address Cache, by attempting to open the RNTBD connection. Note that the validation task and the connection opening part has been done as a background task, so that the address resolving doesn't wait on the RNTBD context negotiation to finish. + +- Leverage the `AddressEnumerator` to reorder the replicas by their health statuses. For instance, if the replica validation is enabled, the `AddressEnumerator` will reorder the replicas by sorting them in the order of **Connected/ Unknown** > **Unhealthy Pending** > **Unhealthy**. However, if the replica validation is disabled, the replicas will be sorted in the order of **Connected/ Unknown/ Unhealthy Pending** > **Unhealthy**. + +Prior discussing the replica validation, it is very important to understand the changes in the flow while opening the RNTBD connections to the backend replica nodes, during the `CosmosClient` initialization. The changes in the flow are mentioned below as an updated sequence diagram. + +### Updated Sequence Diagram for `CosmosClient` initialization. + +```mermaid +sequenceDiagram + participant A as CosmosClient
[v3 Code] + participant B as ClientContextCore
[v3 Code] + participant C as DocumentClient
[v3 Code] + participant D as ServerStoreModel
[Direct Code] + participant K as StoreClientFactory
[Direct Code] + participant E as StoreClient
[Direct Code] + participant F as ReplicatedResourceClient
[Direct Code] + participant G as GlobalAddressResolver
[v3 Code] + participant H as GatewayAddressCache
[v3 Code] + participant J as RntbdOpenConnectionHandler
[Direct Code] + participant I as TransportClient
[Direct Code] + A->>B: 1. InitializeContainerWithRntbdAsync() + B->>C: 2. OpenConnectionsAsync() + C->>C: 2.1. CreateStoreModel() + C->>K: 3. CreateStoreClient(addressResolver) + K->>E: 4. new StoreClient(addressResolver) + E->>G: 5. SetOpenConnectionsHandler(new RntbdOpenConnectionHandler(transportClient)) + Note over E: a) Creates a new instance of RntbdOpenConnectionHandler
and sets it to the IAddressResolverExtension.
Note that the GlobalAddressResolver implements the
IAddressResolverExtension today.
b) Sets the IAddressResolverExtension to the Replicated
ResourceClient. + G->>H: 6. SetOpenConnectionsHandler(openConnectionHandler) + C->>D: 7. OpenConnectionsToAllReplicasAsync() + D->>E: 8. OpenConnectionsToAllReplicasAsync() + E->>F: 9. OpenConnectionsToAllReplicasAsync() + F->>G: 10. OpenConnectionsToAllReplicasAsync() + G->>G: 10.1 collection = collectionCache.
ResolveByNameAsync() + G->>G: 10.2 partitionKeyRanges = routingMapProvider.
TryGetOverlappingRangesAsync(FullRange) + G->>H: 11. OpenAsync
(partitionKeyRangeIdentities) + Note over G: Resolves the collection by the
container link url and fetches
the partition key full ranges. + H->>H: 11.1 GetServerAddressesViaGatewayAsync() + H->>J: 12. OpenRntbdChannelsAsync() + Note over H: Gets the transport address uris from address info
and invokes the RntbdOpenConnectionHandler
OpenRntbdChannelsAsync() method with the transport uris
to establish the Rntbd connection. + J->>I: 13. OpenConnectionAsync()
using the resolved transport address uris. +``` + +Now that we are well aware of the changes in the RNTBD open connection flow, let's leverage the changes in the replica validation flow. The below sequence diagram describes the request and response flow from `StoreReader` (present in the `Cosmos.Direct` namespace) to the `GatewayAddressCache` (present in the `Microsoft.Azure.Cosmos` namespace), during the read request to backend replica/s. + +### Sequence Diagram when `StoreReader` invokes the `GatewayAddressCache` to resolve addresses and leverages `AddressEnumerator` to enumerate the transport addresses. + +```mermaid +sequenceDiagram + participant A as StoreReader
[Direct Code] + participant B as AddressSelector
[v3 Code] + participant C as GlobalAddressResolver
[v3 Code] + participant D as AddressResolver
[v3 Code] + participant E as GatewayAddressCache
[v3 Code] + participant F as RntbdOpenConnectionHandler
[Direct Code] + participant G as AsyncCacheNonBlocking
[v3 Code] + participant H as GatewayService
[external service] + participant I as AddressEnumerator
[Direct Code] + participant J as TransportClient
[Direct Code] + participant K as Channel
[Direct Code] + participant L as TransportAddressUri
[Direct Code] + A->>A: 1. ReadMultipleReplicaAsync() + A->>B: 2. ResolveAllTransportAddressUriAsync(forceRefresh - false) + B->>C: 3. ResolveAsync(forceRefresh - false) + C->>D: 4. ResolveAsync(forceRefresh - false) + D->>D: 5. ResolveAddressesAndIdentityAsync() + D->>E: 6. TryGetAddressesAsync(forceRefresh - false) + E->>G: 7. GetAsync ("singleValueInitFunc delegate", "forceRefresh - false") + Note over L: Initial health status of a
TransportAddressUri is "Unknown". + Note over E: Passes the SingleValueInitFunc delegate
to async nonblocking cache. + G->>E: 8. Returns the cached addresses + E->>D: 9. Returns the resolved addresses + D->>C: 10. Returns the resolved addresses + C->>B: 11. Returns the resolved addresses + B->>A: 12. Returns the resolved addresses + A->>A: 13. Request failes with "GoneException" + Note over A: Sets Force Refresh
header to true. + A->>A: 14. ReadMultipleReplicaAsync() + A->>B: 15. ResolveAllTransportAddressUriAsync (forceRefresh - true) + B->>C: 16. ResolveAsync(forceRefresh - true) + C->>D: 17. ResolveAsync(forceRefresh - true) + D->>D: 18. ResolveAddressesAndIdentityAsync(forceRefresh - true) + D->>E: 19. TryGetAddressesAsync(forceRefresh - true) + E->>G: 20. GetAsync ("singleValueInitFunc delegate", "forceRefresh - true") + Note over E: Passes the SingleValueInitFunc delegate
to async nonblocking cache. + G->>E: 21. Invokes the singleValueInitFunc delegate + E->>E: 22. SetTransportAddressUrisToUnhealthy(currentCachedValue, failedEndpoints) + Note over E: Sets the failed TransportAddressUris
to an "Unhealthy" status. + E->>L: 23. SetUnhealthy() + E->>E: 24. GetAddressesForRangeIdAsync(forceRefresh - true, cachedAddresses) + E->>H: 25. Invokes the GatewayService using GetServerAddressesViaGatewayAsync()
to receive new addresses. + H->>E: 26. Receives the resolved new addresses. + E->>E: 27. MergeAddresses + Note over E: The purpose of the merge is to restore the health statuses of all the new addresses to
that of their recpective cached addresses, if returned same addresses. + E->>L: 28. SetRefreshedIfUnhealthy() + Note over E: Sets any TransportAddressUri with
an "Unhealthy" status to "UnhealthyPending". + E->>E: 29. ValidateReplicaAddresses(mergedTransportAddress) + Note over E: Validates the backend replicas,
if the replica validation env variable is enabled. + E-->>F: 30. OpenRntbdChannelsAsync(mergedTransportAddress) + Note over E: If replica validation is enabled, then validate unhealthy pending
replicas by opening RNTBD connections. Note that this
operations executes as a background task. + F-->>J: 31. OpenConnectionAsync()
using the resolved transport address uris + J-->>K: 32. OpenConnectionAsync()
using the resolved physical address uris + K-->>L: 33. SetConnected() + Note over K: Initializes and Establishes a RNTBD
context negotiation to the backend replica nodes. + E->>G: 34. Returns the merged addresses to cache and store into the Async Nonblocking Cache + G->>E: 35. Returns the resolved addresses + E->>E: 36. ShouldRefreshHealthStatus() + Note over E: Refresh the cache if there was an address
has been marked as unhealthy long enough (more than a minute)
and need to revalidate its status. + E-->>G: 37. Refresh ("GetAddressesForRangeIdAsync() as the singleValueInitFunc delegate", "forceRefresh - true") + Note over E: Note that the refresh operation
happens as a background task. + E->>D: 38. Returns the resolved addresses + D->>C: 39. Returns the resolved addresses + C->>B: 40. Returns the resolved addresses + B->>A: 41. Returns the resolved transport addresses + A->>I: 42. GetTransportAddresses("transportAddressUris", "replicaAddressValidationEnabled") + I->>I: 43. ReorderReplicasByHealthStatus() + Note over I: Re-orders the transport addresses
by their health statuses
Connected/Unknown >> UnhealthyPending >> Unhealthy. + I->>A: 44. Returns the transport addresses re-ordered by their health statuses +``` +### State Diagram to Understand the `TransportAddressUri` Health State Transformations. + +To better understand the design, it is critical to understand the `TransportAddressUri` health state transformations. The below state diagram depicts the `TransportAddressUri` state transitions in detail. + +```mermaid + stateDiagram-v2 + [*] --> Unknown + note right of Unknown + Initial state of
a TransportAddressUri + end note + Unknown --> Connected: Channel Aquire
Successful + Unknown --> Unhealthy: Channel Aquire
Failed + Unhealthy --> Connected: Channel Aquire
Successful after 1 Min + Unhealthy --> UnhealthyPending: Refresh Addresses
from Gateway when
Replica Validation
is enabled + UnhealthyPending --> Unhealthy: RntbdOpenConnectionHandler -
Channel Aquire
Failed + UnhealthyPending --> Connected: RntbdOpenConnectionHandler -
Channel Aquire
Successful + Connected --> Unhealthy: Request failed with 410
GoneException and
force refresh + Connected --> [*] +``` + +To accomplish the above changes in the replica validation flow, below are the class diagrams and the proposed code changes in both `Microsoft.Azure.Cosmos.Direct` and `Microsoft.Azure.Cosmos` packages. + +### `Microsoft.Azure.Cosmos.Direct` package class diagrams. + +Introduce a new `IOpenConnectionsHandler` interface with `OpenRntbdChannelsAsync()` method. Create a new class `RntbdOpenConnectionHandler` that will eventually implement the `IOpenConnectionsHandler` interface and override the `OpenRntbdChannelsAsync()` method to establish Rntbd connections to the transport address uris. Note that, this class will also add the concurrency control logic, so that any burst of connection creation could be avoided. The below class diagram depicts the same behavior. + +```mermaid +classDiagram + IOpenConnectionsHandler --|> RntbdOpenConnectionHandler : implements + <> IOpenConnectionsHandler + IOpenConnectionsHandler: +OpenRntbdChannelsAsync(IReadOnlyList~TransportAddressUri~ addresses) + class RntbdOpenConnectionHandler{ + -TransportClient transportClient + -SemaphoreSlim semaphore + -int SemaphoreAcquireTimeoutInMillis + +OpenRntbdChannelsAsync() + } +``` + +Extend the `IAddressResolverExtension` interface with `SetOpenConnectionsHandler()` method. The benefits and the utilizations are provided below: + +- The `GlobalAddressResolver` can then implement the `SetOpenConnectionsHandler()` method, which will be invoked by the `StoreClient` constructor to set the `RntbdOpenConnectionHandler`. + +- The `OpenConnectionsAsync()` method present inside `GlobalAddressResolver`, will be invoked from the `ReplicatedResourceClient` eventually. The `AddressResolver` class can simply implement the method/s and return an empty `Task`. The `GlobalAddressResolver`.`OpenConnectionsAsync()` is responsible for + + - Resolving the collection by the database name and container link, + - Fetching the partition key full ranges and + - Invoking the `GatewayAddressCache` for the preferred region, with the `RntbdOpenConnectionHandler` instance, passed by the `StoreClient`. + +The below class diagram depicts the same behavior. + +*[Note: The `IAddressResolverExtension` was introduced to hold the new methods, which could break the existing build, if put directly into `IAddressResolver` interface. The `IAddressResolverExtension` will be removed eventually and the existing methods will be moved into `IAddressResolver` interface.]* + +```mermaid +classDiagram + IAddressResolver --|> IAddressResolverExtension : extends + IAddressResolverExtension --|> GlobalAddressResolver : implements + <> IAddressResolver + <> IAddressResolverExtension + IAddressResolverExtension: +OpenConnectionsAsync(string databaseName, string containerLinkUri) + IAddressResolverExtension: +SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionHandler) + class GlobalAddressResolver{ + +OpenConnectionsAsync() + +SetOpenConnectionsHandler() + } +``` + +Update the method definition of `GetTransportAddresses()` present in `IAddressEnumerator` to add a new `boolean` argument `replicaAddressValidationEnabled`. This will help to choose the correct set of replica/s when replica validation is enabled or disabled. Additionally, a new private method `ReorderReplicasByHealthStatus()` will be added in `AddressEnumerator` to re-order the transport uri/s by their health status priority. The below class diagram depicts the same changes. + +```mermaid +classDiagram + IAddressEnumerator --|> AddressEnumerator : implements + <> IAddressEnumerator + IAddressEnumerator: +GetTransportAddresses(IReadOnlyList~TransportAddressUri~ transportAddressUris, Lazy~HashSet~TransportAddressUri~~ failedEndpoints, bool replicaAddressValidationEnabled) IEnumerable~TransportAddressUri~ + class AddressEnumerator{ + +GetTransportAddresses() + -ReorderReplicasByHealthStatus(IReadOnlyList~TransportAddressUri~ transportAddressUris, Lazy~HashSet~TransportAddressUri~~ failedEndpoints, bool replicaAddressValidationEnabled) IEnumerable~TransportAddressUri~ + } +``` + +This class will be updated eventually, with critical set of changes required for the replica validation workstream. It will introduce an enum `HealthStatus` with `4` new health statuses - `Connected`, `Unknown`, `UnhealthyPending` and `Unhealthy` to re-order the replicas with their status priorities. The setters will help to capture the correct health state of the `TransportAddressUri` at any given point of time. The below class diagram depicts the same behavior. + +```mermaid +classDiagram + class TransportAddressUri { + -DateTime? lastUnknownTimestamp + -DateTime? lastUnhealthyPendingTimestamp + -DateTime? lastUnhealthyTimestamp + -HealthStatus healthStatus + -ReaderWriterLockSlim healthStatusLock + +SetConnected() + +SetRefreshedIfUnhealthy() + +SetHealthStatus(HealthStatus status, bool forceSet) + +GetHealthStatus() HealthStatus + +GetEffectiveHealthStatus() HealthStatus + +ShouldRefreshHealthStatus() bool + } + + class HealthStatus { + <> + Connected : 100 + Unknown : 200 + UnhealthyPending : 300 + Unhealthy : 400 + } +``` + +### `Microsoft.Azure.Cosmos` package class diagrams. + +Extend the `IAddressCache` interface with `SetOpenConnectionsHandler()` method. This method should take an instance of the `RntbdOpenConnectionHandler` (which implements the `IOpenConnectionsHandler`) and sets it to a private field for later usage, to establish the Rntbd connectivity to the backend replica nodes. + +```mermaid +classDiagram + IAddressCache --|> GatewayAddressCache : implements + <> IAddressCache + IAddressCache: +SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHandler) + class GatewayAddressCache { + -IOpenConnectionsHandler openConnectionsHandler + -string replicaValidationVariableName + +SetOpenConnectionsHandler(IOpenConnectionsHandler openConnectionsHandler) + -MergeAddresses(PartitionAddressInformation newAddresses, PartitionAddressInformation cachedAddresses) PartitionAddressInformation + -ValidateReplicaAddresses(IReadOnlyList~TransportAddressUri~ addresses) + } +``` + +Add a new method `Refresh()` into the `AsyncCacheNonBlocking` to force refresh the address cache on demand. Note that `Refresh()` is used to force refresh any `Unhealthy` replica nodes, which has been in `Unhealthy` state for more than `1` minute. That way, any `Unhealthy` replica nodes will be back into the validation pool, which will eventually be useful to avoid any skewed replica selection. + +```mermaid +classDiagram + class AsyncCacheNonBlocking~TKey, TValue~ { + +Task Refresh(TKey key, Func~TValue, Task~TValue~~ singleValueInitFunc) + } +``` + +## Pull Request with Sample Code Changes + +Here is the [link to a sample PR](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3570) which provides an overview of the incoming changes. + +## References + +- [Mermaid Documentation.](https://mermaid-js.github.io/mermaid/#/) +- [Upgrade Resiliency Tasks List.](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3409) +- [Design Document to Utilize RNTBD Context Negotiation During `CosmosClient` Initialization.](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3442) \ No newline at end of file From 93bb10b47b6bc96b3b647daf84cccb0e850ca9f9 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 1 Mar 2023 13:06:30 -0800 Subject: [PATCH 065/337] ReadMany: Fixes BadRequest when using Ids with single quotes (#3732) * Use parameters * Emulator tests --- .../src/ReadManyQueryHelper.cs | 8 +++-- .../CosmosReadManyItemsTests.cs | 31 ++++++++----------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ReadManyQueryHelper.cs b/Microsoft.Azure.Cosmos/src/ReadManyQueryHelper.cs index e69476129c..6ebcda267c 100644 --- a/Microsoft.Azure.Cosmos/src/ReadManyQueryHelper.cs +++ b/Microsoft.Azure.Cosmos/src/ReadManyQueryHelper.cs @@ -249,10 +249,13 @@ private QueryDefinition CreateReadManyQueryDefinitionForId(List<(string, Partiti { int totalItemCount = Math.Min(items.Count, startIndex + this.maxItemsPerQuery); StringBuilder queryStringBuilder = new StringBuilder(); + SqlParameterCollection sqlParameters = new SqlParameterCollection(); queryStringBuilder.Append("SELECT * FROM c WHERE c.id IN ( "); for (int i = startIndex; i < totalItemCount; i++) { - queryStringBuilder.Append($"'{items[i].Item1}'"); + string idParamName = "@param_id" + i; + sqlParameters.Add(new SqlParameter(idParamName, items[i].Item1)); + queryStringBuilder.Append(idParamName); if (i < totalItemCount - 1) { queryStringBuilder.Append(","); @@ -260,7 +263,8 @@ private QueryDefinition CreateReadManyQueryDefinitionForId(List<(string, Partiti } queryStringBuilder.Append(" )"); - return new QueryDefinition(queryStringBuilder.ToString()); + return QueryDefinition.CreateFromQuerySpec(new SqlQuerySpec(queryStringBuilder.ToString(), + sqlParameters)); } private QueryDefinition CreateReadManyQueryDefinitionForOther(List<(string, PartitionKey)> items, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs index ede534cb9d..c3949d763f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs @@ -5,16 +5,11 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; - using System.Collections.Concurrent; using System.Collections.Generic; - using System.Collections.ObjectModel; using System.Net; - using System.Net.Http; - using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Fluent; - using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -22,16 +17,15 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public class CosmosReadManyItemsTests : BaseCosmosClientHelper { private Container Container = null; - private ContainerProperties containerSettings = null; [TestInitialize] public async Task TestInitialize() { await base.TestInit(); string PartitionKey = "/pk"; - this.containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: PartitionKey); + ContainerProperties containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: PartitionKey); ContainerResponse response = await this.database.CreateContainerAsync( - this.containerSettings, + containerSettings, throughput: 20000, cancellationToken: this.cancellationToken); Assert.IsNotNull(response); @@ -122,23 +116,24 @@ public async Task ReadManyDoesNotFetchQueryPlan() [TestMethod] public async Task ReadManyWithIdasPk() { - string PartitionKey = "/id"; - ContainerProperties containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: PartitionKey); - Container container = await this.database.CreateContainerAsync(containerSettings); + Container container = await this.database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); List<(string, PartitionKey)> itemList = new List<(string, PartitionKey)>(); - for (int i = 0; i < 5; i++) - { - itemList.Add((i.ToString(), new PartitionKey(i.ToString()))); - } // Create items with different pk values for (int i = 0; i < 5; i++) { ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); - item.id = i.ToString(); ItemResponse itemResponse = await container.CreateItemAsync(item); Assert.AreEqual(HttpStatusCode.Created, itemResponse.StatusCode); + + itemList.Add((item.id, new PartitionKey(item.id))); + + ToDoActivity itemWithSingleQuotes = ToDoActivity.CreateRandomToDoActivity(id: item.id + "'singlequote"); + ItemResponse itemResponseWithSingleQuotes = await container.CreateItemAsync(itemWithSingleQuotes); + Assert.AreEqual(HttpStatusCode.Created, itemResponseWithSingleQuotes.StatusCode); + + itemList.Add((itemWithSingleQuotes.id, new PartitionKey(itemWithSingleQuotes.id))); } using (ResponseMessage responseMessage = await container.ReadManyItemsStreamAsync(itemList)) @@ -149,12 +144,12 @@ public async Task ReadManyWithIdasPk() ToDoActivity[] items = this.GetClient().ClientContext.SerializerCore.FromFeedStream( CosmosFeedResponseSerializer.GetStreamWithoutServiceEnvelope(responseMessage.Content)); - Assert.AreEqual(items.Length, 5); + Assert.AreEqual(items.Length, 10); } FeedResponse feedResponse = await container.ReadManyItemsAsync(itemList); Assert.IsNotNull(feedResponse); - Assert.AreEqual(feedResponse.Count, 5); + Assert.AreEqual(feedResponse.Count, 10); Assert.IsTrue(feedResponse.Headers.RequestCharge > 0); Assert.IsNotNull(feedResponse.Diagnostics); } From 45c0d147ab35ddc6e9c13e91919b147ee6ea06c0 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 1 Mar 2023 14:39:47 -0800 Subject: [PATCH 066/337] Release: Adds SDK version and changelog for 3.32.1 (#3733) * version bump * Contracts --- Directory.Build.props | 4 +- .../contracts/API_3.32.1-preview.txt | 1531 +++++++++++++++++ .../contracts/API_3.32.1.txt | 1478 ++++++++++++++++ changelog.md | 6 + 4 files changed, 3017 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.1-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.1.txt diff --git a/Directory.Build.props b/Directory.Build.props index a4a5b0a087..aa8918e3b1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.32.0 - 3.32.0 + 3.32.1 + 3.32.1 preview 3.30.2 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.1-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.1-preview.txt new file mode 100644 index 0000000000..69b7a4b83e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.1-preview.txt @@ -0,0 +1,1531 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.1.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.1.txt new file mode 100644 index 0000000000..5218206b0e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.1.txt @@ -0,0 +1,1478 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index aa2aaad67d..b201ba77fb 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +###
[3.32.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.1) - 2023-03-01 +### [3.32.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.1-preview) - 2023-03-01 + +#### Fixed +- [#3732](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3732) ReadMany: Fixes BadRequest when using Ids with single quotes + ### [3.32.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.0) - 2023-02-03 #### Fixed - [#3466](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3466) ClientRetryPolicy: Fixes behavior to Meta-data write operations in multimaster accounts From 0018c4a1c165dd3bbbca704abdae645fa2cd4182 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 2 Mar 2023 13:11:10 -0800 Subject: [PATCH 067/337] [Internal] Build: Fixes static tool analysis versions (#3736) * Update Binskim and follow warnings * Fixing task * More version bumps * binskim args * Padding * policheck * postanalysis parameters * analysis settings --- templates/static-tools.yml | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/templates/static-tools.yml b/templates/static-tools.yml index b3ce2b11de..fb7b375586 100644 --- a/templates/static-tools.yml +++ b/templates/static-tools.yml @@ -23,30 +23,16 @@ jobs: arguments: '-p:Optimize=true -p:IsPreview=true --configuration Release' versioningScheme: OFF - - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@3 + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@4 displayName: 'BinSkim' inputs: - toolVersion: Latest - InputType: Basic - Function: analyze - AnalyzeTarget: $(Build.SourcesDirectory)\Microsoft.Azure.Cosmos\src\bin\Release\netstandard2.0\Microsoft.Azure.Cosmos.Client.dll - AnalyzeConfigPath: default + AnalyzeTargetGlob: $(Build.SourcesDirectory)\Microsoft.Azure.Cosmos\src\bin\Release\netstandard2.0\Microsoft.Azure.Cosmos.Client.dll AnalyzeRecurse: true AnalyzeVerbose: true AnalyzeHashes: false AnalyzeStatistics: false AnalyzeEnvironment: false - #Analyze source code for type of content and target types to help determine which tools to run - - task: securedevelopmentteam.vss-secure-development-tools.build-task-autoapplicability.AutoApplicability@1 - displayName: 'AutoApplicability' - inputs: - VerboseWriter: true - ExternalRelease: true - InternalRelease: true - IsService: true - IsSoftware: true - # Analyze source and build output text files for credentials - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3 displayName: 'CredScan' @@ -58,22 +44,19 @@ jobs: verboseOutput: false # Scan text elements including code, code comments, and content/web pages, for sensitive terms based on legal, cultural, or geopolitical reasons - - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@1 + - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2 displayName: 'PoliCheck' inputs: targetType: F + optionsFC: 0 # AntiMalware scan - - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@3 + - task: securedevelopmentteam.vss-secure-development-tools.build-task-antimalware.AntiMalware@4 displayName: 'AntiMalware' continueOnError: true # signature refresh failing resulting in tasks failures inputs: EnableServices: true - # Run checks for recently discovered vulnerabilities which are not yet incorporated to another tool - - task: securedevelopmentteam.vss-secure-development-tools.build-task-vulnerabilityassessment.VulnerabilityAssessment@0 - displayName: 'Vulnerability Assessment' - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 displayName: 'Component Governance Detection' #https://docs.opensource.microsoft.com/tools/cg.html inputs: @@ -81,11 +64,16 @@ jobs: failOnAlert: true # Publish Analysis Results (position after all tools ran) - - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@2 + - task: securedevelopmentteam.vss-secure-development-tools.build-task-publishsecurityanalysislogs.PublishSecurityAnalysisLogs@3 displayName: 'Publish Security Analysis Logs' # The Post-Analysis build task will analyze the log files produced by the tools, and introduce a build break - - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1 + - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@2 displayName: 'Post Analysis' inputs: - AllTools: true + GdnBreakFast: true + GdnBreakAllTools: false + GdnBreakGdnToolCredScan: true + GdnBreakGdnToolBinSkim: true + GdnBreakGdnToolPoliCheck: true + GdnBreakGdnToolPoliCheckSeverity: Error From d6e04a92f8778565eb1d1452738d37c7faf3c47a Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Thu, 2 Mar 2023 14:11:14 -0800 Subject: [PATCH 068/337] Query: Fixes System.ArgumentException when using PartitionKey.None on x86, Linux or in Optimistic Direct Execution (#3730) * Minor clean up of OptimisticDirectExecutionQueryTests * More minor cleanup in OptimisticDirectExecutionQueryTests * Add emulator tests for the bypass query parsing scenario * Handle PartitionKey.None while creating QueryIterator. This is a workaround for the PartitionKeyInternal.None not following its own contract * Fix up to correctly handle PartitionKey.None using the CachedContainerQueryProperties * Add more tests where PartitionKey.None maps to PartitionKey.Undefined --------- Co-authored-by: Matias Quaranta --- .../CosmosQueryExecutionContextFactory.cs | 4 +- .../src/Query/v3Query/QueryIterator.cs | 6 +- .../Query/BypassQueryParsingTests.cs | 64 ++++ .../OptimisticDirectExecutionQueryTests.cs | 298 ++++++++++++++---- 4 files changed, 303 insertions(+), 69 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index a7f7f17934..744d98bf44 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -214,7 +214,7 @@ private static async Task> TryCreateCoreContextAsy List targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, - inputParameters.PartitionKey.Value.InternalKey.GetEffectivePartitionKeyString(partitionKeyDefinition), + containerQueryProperties.EffectivePartitionKeyString, forceRefresh: false, createQueryPipelineTrace); @@ -779,7 +779,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, - inputParameters.PartitionKey.Value.InternalKey.GetEffectivePartitionKeyString(partitionKeyDefinition), + containerQueryProperties.EffectivePartitionKeyString, forceRefresh: false, trace); } diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index a820a0a49a..7dfcea9818 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -129,9 +129,9 @@ public static QueryIterator Create( default: throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {queryRequestOptions.ExecutionEnvironment.Value}."); - } - - CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( + } + + CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: sqlQuerySpec, initialUserContinuationToken: requestContinuationToken, initialFeedRange: feedRangeInternal, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs new file mode 100644 index 0000000000..a0c821c72d --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs @@ -0,0 +1,64 @@ +namespace Microsoft.Azure.Cosmos.EmulatorTests.Query +{ + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + [TestCategory("Query")] + public sealed class BypassQueryParsingTests : QueryTestsBase + { + [TestMethod] + public async Task TestBypassQueryParsingWithNonePartitionKey() + { + int documentCount = 400; + QueryRequestOptions feedOptions = new QueryRequestOptions { PartitionKey = PartitionKey.None }; + string query = "SELECT VALUE r.numberField FROM r"; + IReadOnlyList expected = Enumerable.Range(0, documentCount).ToList(); + + async Task ImplementationAsync(Container container, IReadOnlyList documents) + { + ContainerInternal containerCore = container as ContainerInlineCore; + + MockCosmosQueryClient cosmosQueryClientCore = new MockCosmosQueryClient( + containerCore.ClientContext, + containerCore, + forceQueryPlanGatewayElseServiceInterop: true); + + ContainerInternal containerWithBypassParsing = new ContainerInlineCore( + containerCore.ClientContext, + (DatabaseCore)containerCore.Database, + containerCore.Id, + cosmosQueryClientCore); + + List items = await RunQueryAsync(containerWithBypassParsing, query, feedOptions); + int[] actual = items.Cast().Select(x => (int)Number64.ToLong(x.Value)).ToArray(); + + Assert.IsTrue(expected.SequenceEqual(actual)); + } + + IReadOnlyList documents = CreateDocuments(documentCount); + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.NonPartitioned | CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + documents, + ImplementationAsync, + "/undefinedPartitionKey"); + } + + private static IReadOnlyList CreateDocuments(int documentCount) + { + List documents = new List(documentCount); + for (int i = 0; i < documentCount; ++i) + { + string document = $@"{{ ""numberField"": {i}, ""nullField"": null }}"; + documents.Add(document); + } + + return documents; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 751c21b64b..cc9ef91733 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -7,91 +7,270 @@ using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] [TestCategory("Query")] public sealed class OptimisticDirectExecutionQueryTests : QueryTestsBase - { + { + private const int NumberOfDocuments = 8; + private const string PartitionKeyField = "key"; + private const string NumberField = "numberField"; + private const string NullField = "nullField"; + private static class PageSizeOptions { public static readonly int[] NonGroupByPageSizeOptions = { -1, 1, 2, 10, 100 }; - public static readonly int[] GroupByPageSizeOptions = { -1 }; + public static readonly int[] GroupByPageSizeOptions = { -1 }; + public static readonly int[] PageSize100 = { 100 }; } [TestMethod] public async Task TestPassingOptimisticDirectExecutionQueries() - { - int numberOfDocuments = 8; - string partitionKey = "key"; - string numberField = "numberField"; - string nullField = "nullField"; - - List documents = CreateDocuments(numberOfDocuments, partitionKey, numberField, nullField); + { + IReadOnlyList empty = new List(0); + IReadOnlyList first5Integers = Enumerable.Range(0, 5).ToList(); + IReadOnlyList first7Integers = Enumerable.Range(0, NumberOfDocuments).ToList(); + IReadOnlyList first7IntegersReversed = Enumerable.Range(0, NumberOfDocuments).Reverse().ToList(); + PartitionKey partitionKeyValue = new PartitionKey("/value"); List singlePartitionContainerTestCases = new List() { // Tests for bool enableOptimisticDirectExecution - CreateInput( query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{partitionKey}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{partitionKey}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: false, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: false, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Passthrough), // Simple query - CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // DISTINCT with ORDER BY - CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // TOP with GROUP BY - CreateInput( query: $"SELECT TOP 5 VALUE r.{numberField} FROM r GROUP BY r.{numberField}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT TOP 5 VALUE r.{numberField} FROM r GROUP BY r.{numberField}", expectedResult: new List { 0, 1, 2, 3, 4 }, partitionKey: null, partition: CollectionTypes.SinglePartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r GROUP BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r GROUP BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // OFFSET LIMIT with WHERE and BETWEEN - CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: "/value", partition: CollectionTypes.SinglePartition, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, partition: CollectionTypes.SinglePartition, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution) + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: partitionKeyValue, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + enableOptimisticDirectExecution: true, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: null, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + enableOptimisticDirectExecution: true, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution) }; List multiPartitionContainerTestCases = new List() { // Simple query - CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: new List { 0, 1, 2, 3, 4, 5, 6, 7 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Passthrough), // DISTINCT with ORDER BY - CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT DISTINCT VALUE r.{numberField} FROM r ORDER BY r.{numberField} DESC", expectedResult: new List { 7, 6, 5, 4, 3, 2, 1, 0 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), // OFFSET LIMIT with WHERE and BETWEEN - CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: "/value", partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{numberField} BETWEEN 0 AND {numberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, partition: CollectionTypes.MultiPartition, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized) - }; + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized) + }; + + IReadOnlyList documents = CreateDocuments(NumberOfDocuments, PartitionKeyField, NumberField, NullField); await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition, documents, - (container, documents) => RunPassingTests(singlePartitionContainerTestCases, container), - "/" + partitionKey); + (container, documents) => RunTests(singlePartitionContainerTestCases, container), + "/" + PartitionKeyField); await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.MultiPartition, documents, - (container, documents) => RunPassingTests(multiPartitionContainerTestCases, container), - "/" + partitionKey); + (container, documents) => RunTests(multiPartitionContainerTestCases, container), + "/" + PartitionKeyField); + } + + [TestMethod] + public async Task TestQueriesWithPartitionKeyNone() + { + int documentCount = 400; + IReadOnlyList first400Integers = Enumerable.Range(0, documentCount).ToList(); + IReadOnlyList first400IntegersReversed = Enumerable.Range(0, documentCount).Reverse().ToList(); + + IReadOnlyList testCases = new List + { + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first400Integers, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: false, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} ASC", + expectedResult: first400Integers, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: false, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first400IntegersReversed, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: false, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: false, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first400Integers, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} ASC", + expectedResult: first400Integers, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first400IntegersReversed, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + }; + + List documents = new List(documentCount); + for (int i = 0; i < documentCount; ++i) + { + string document = $@"{{ {NumberField}: {i}, {NullField}: null }}"; + documents.Add(document); + } + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.NonPartitioned | CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + documents, + (container, documents) => RunTests(testCases, container), + "/undefinedPartitionKey"); } [TestMethod] public async Task TestFailingOptimisticDirectExecutionOutput() { - int numberOfDocuments = 8; - string partitionKey = "key"; - string numberField = "numberField"; - string nullField = "nullField"; - - List documents = CreateDocuments(numberOfDocuments, partitionKey, numberField, nullField); + IReadOnlyList documents = CreateDocuments(NumberOfDocuments, PartitionKeyField, NumberField, NullField); // check if bad continuation queries and syntax error queries are handled by pipeline IDictionary invalidQueries = new Dictionary @@ -106,10 +285,10 @@ await this.CreateIngestQueryDeleteAsync( CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, documents, (container, documents) => RunFailingTests(container, invalidQueries), - "/" + partitionKey); + "/" + PartitionKeyField); } - private static async Task RunPassingTests(IEnumerable testCases, Container container) + private static async Task RunTests(IEnumerable testCases, Container container) { foreach (DirectExecutionTestCase testCase in testCases) { @@ -118,9 +297,7 @@ private static async Task RunPassingTests(IEnumerable t QueryRequestOptions feedOptions = new QueryRequestOptions { MaxItemCount = pageSize, - PartitionKey = testCase.PartitionKey == null - ? null - : new Cosmos.PartitionKey(testCase.PartitionKey), + PartitionKey = testCase.PartitionKey, EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution, TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) }; @@ -130,7 +307,7 @@ private static async Task RunPassingTests(IEnumerable t testCase.Query, feedOptions); - long[] actual = items.Cast().Select(x => Number64.ToLong(x.Value)).ToArray(); + int[] actual = items.Cast().Select(x => (int)Number64.ToLong(x.Value)).ToArray(); Assert.IsTrue(testCase.ExpectedResult.SequenceEqual(actual)); Assert.AreEqual(testCase.ExpectedPipelineType, feedOptions.TestSettings.Stats.PipelineType.Value); @@ -151,7 +328,7 @@ private static async Task RunFailingTests(Container container, IDictionary( + await container.GetItemQueryIterator( queryDefinition: new QueryDefinition(queryAndResult.Key), continuationToken: queryAndResult.Value, requestOptions: feedOptions).ReadNextAsync(); @@ -169,16 +346,13 @@ await container.GetItemQueryIterator( } } - private static List CreateDocuments(int documentCount, string partitionKey, string numberField, string nullField) + private static IReadOnlyList CreateDocuments(int documentCount, string partitionKey, string numberField, string nullField) { List documents = new List(documentCount); for (int i = 0; i < documentCount; ++i) { - Document doc = new Document(); - doc.SetPropertyValue(partitionKey, "/value"); - doc.SetPropertyValue(numberField, i % documentCount); - doc.SetPropertyValue(nullField, null); - documents.Add(doc.ToString()); + string document = $@"{{ {partitionKey}: ""/value"", {numberField}: {i}, {nullField}: null }}"; + documents.Add(document); } return documents; @@ -186,31 +360,28 @@ private static List CreateDocuments(int documentCount, string partitionK private static DirectExecutionTestCase CreateInput( string query, - List expectedResult, - string partitionKey, - CollectionTypes partition, + IReadOnlyList expectedResult, + PartitionKey? partitionKey, bool enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) { - return new DirectExecutionTestCase(query, expectedResult, partitionKey, partition, enableOptimisticDirectExecution, pageSizeOptions, expectedPipelineType); - } - - internal readonly struct DirectExecutionTestCase + return new DirectExecutionTestCase(query, expectedResult, partitionKey, enableOptimisticDirectExecution, pageSizeOptions, expectedPipelineType); + } + + private readonly struct DirectExecutionTestCase { public string Query { get; } - public List ExpectedResult { get; } - public string PartitionKey { get; } - public CollectionTypes Partition { get; } + public IReadOnlyList ExpectedResult { get; } + public PartitionKey? PartitionKey { get; } public bool EnableOptimisticDirectExecution { get; } public int[] PageSizeOptions { get; } public TestInjections.PipelineType ExpectedPipelineType { get; } public DirectExecutionTestCase( string query, - List expectedResult, - string partitionKey, - CollectionTypes partition, + IReadOnlyList expectedResult, + PartitionKey? partitionKey, bool enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) @@ -218,7 +389,6 @@ public DirectExecutionTestCase( this.Query = query; this.ExpectedResult = expectedResult; this.PartitionKey = partitionKey; - this.Partition = partition; this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; this.PageSizeOptions = pageSizeOptions; this.ExpectedPipelineType = expectedPipelineType; From f262f8941f541332509eba64a2297e9d5e221675 Mon Sep 17 00:00:00 2001 From: Ezra Haleva <115735172+ezrahaleva-msft@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:50:04 -0800 Subject: [PATCH 069/337] Query: Adds FIRST and LAST Scalar Expressions (#3629) * Add FIRST and LAST objects and update visitors * add FIRST LAST evaluation and update offline engine visitors * Add FIRST and LAST to parser * update another visitor * Fix typo * fix typo * added new tests and baselines * cleaning * cleaning --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../src/Query/Core/Parser/CstToAstVisitor.cs | 20 + .../src/Query/Core/Parser/IsqlListener.cs | 24 + .../src/Query/Core/Parser/IsqlVisitor.cs | 14 + .../src/Query/Core/Parser/sql.g4 | 6 + .../src/Query/Core/Parser/sqlBaseListener.cs | 28 + .../src/Query/Core/Parser/sqlBaseVisitor.cs | 22 + .../src/Query/Core/Parser/sqlLexer.cs | 978 +++++++++--------- .../src/Query/Core/Parser/sqlParser.cs | 579 ++++++----- .../CosmosQueryExecutionContextFactory.cs | 12 + .../SqlObjects/SqlFirstScalarExpression.cs | 40 + .../src/SqlObjects/SqlLastScalarExpression.cs | 40 + .../Visitors/SqlObjectEqualityVisitor.cs | 30 + .../SqlObjects/Visitors/SqlObjectHasher.cs | 16 + .../Visitors/SqlObjectObfuscator.cs | 12 +- .../Visitors/SqlObjectTextSerializer.cs | 16 + .../SqlObjects/Visitors/SqlObjectVisitor.cs | 2 + .../SqlObjectVisitor{TArg,TOutput}.cs | 2 + .../Visitors/SqlObjectVisitor{TResult}.cs | 2 + .../Visitors/SqlScalarExpressionVisitor.cs | 2 + ...qlScalarExpressionVisitor{TArg,TOutput}.cs | 2 + .../SqlScalarExpressionVisitor{TResult}.cs | 2 + ...teSubquerySqlParserBaselineTests.First.xml | 92 ++ ...ateSubquerySqlParserBaselineTests.Last.xml | 92 ++ ...ExpressionSqlParserBaselineTests.First.xml | 47 + ...rExpressionSqlParserBaselineTests.Last.xml | 47 + .../Microsoft.Azure.Cosmos.Tests.csproj | 30 +- .../AggregateProjectionDector.cs | 12 + .../AggregateProjectionTransformer.cs | 12 + .../ScalarExpressionEvaluator.cs | 20 + .../Query/OfflineEngine/SqlInterpreter.cs | 10 + ...AggregateSubquerySqlParserBaselineTests.cs | 99 +- .../ScalarExpressionSqlParserBaselineTests.cs | 64 ++ 32 files changed, 1633 insertions(+), 741 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/SqlObjects/SqlFirstScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/SqlObjects/SqlLastScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.First.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.Last.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.First.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.Last.xml diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs index 448b8f4ca6..8ba6c4fc45 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs @@ -568,6 +568,16 @@ public override SqlObject VisitExistsScalarExpression([NotNull] sqlParser.Exists return SqlExistsScalarExpression.Create(subquery); } + public override SqlObject VisitFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context) + { + Contract.Requires(context != null); + // K_FIRST '(' sql_query ')' + Contract.Requires(context.ChildCount == 4); + + SqlQuery subquery = (SqlQuery)this.Visit(context.children[2]); + return SqlFirstScalarExpression.Create(subquery); + } + public override SqlObject VisitFunctionCallScalarExpression([NotNull] sqlParser.FunctionCallScalarExpressionContext context) { Contract.Requires(context != null); @@ -627,6 +637,16 @@ public override SqlObject VisitIn_scalar_expression([NotNull] sqlParser.In_scala return SqlInScalarExpression.Create(needle, not, searchList.ToImmutableArray()); } + public override SqlObject VisitLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context) + { + Contract.Requires(context != null); + // K_LAST '(' sql_query ')' + Contract.Requires(context.ChildCount == 4); + + SqlQuery subquery = (SqlQuery)this.Visit(context.children[2]); + return SqlLastScalarExpression.Create(subquery); + } + public override SqlObject VisitLike_scalar_expression([NotNull] sqlParser.Like_scalar_expressionContext context) { Contract.Requires(context != null); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs index 24a4a0694a..9cde50fb6b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlListener.cs @@ -562,6 +562,18 @@ internal interface IsqlListener : IParseTreeListener { /// The parse tree. void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); /// + /// Enter a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void EnterFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context); + /// + /// Exit a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void ExitFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context); + /// /// Enter a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// @@ -670,6 +682,18 @@ internal interface IsqlListener : IParseTreeListener { /// The parse tree. void ExitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context); /// + /// Enter a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void EnterLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context); + /// + /// Exit a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + void ExitLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context); + /// /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs index e22a9d4218..b9bea8ca1d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/IsqlVisitor.cs @@ -347,6 +347,13 @@ internal interface IsqlVisitor : IParseTreeVisitor { /// The visitor result. Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context); /// + /// Visit a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context); + /// /// Visit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// @@ -410,6 +417,13 @@ internal interface IsqlVisitor : IParseTreeVisitor { /// The visitor result. Result VisitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context); /// + /// Visit a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// + /// The parse tree. + /// The visitor result. + Result VisitLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context); + /// /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 index 42ac229557..2b0002a8ab 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sql.g4 @@ -173,6 +173,8 @@ primary_expression | K_EXISTS '(' sql_query ')' #ExistsScalarExpression | K_ARRAY '(' sql_query ')' #ArrayScalarExpression | K_ALL '(' sql_query ')' #AllScalarExpression + | K_FIRST '(' sql_query ')' #FirstScalarExpression + | K_LAST '(' sql_query ')' #LastScalarExpression | function_call_scalar_expression #FunctionCallScalarExpression ; @@ -191,6 +193,8 @@ object_property : STRING_LITERAL ':' scalar_expression ; identifier : LEX_IDENTIFIER | K_ALL + | K_FIRST + | K_LAST ; /*--------------------------------------------------------------------------------*/ @@ -208,11 +212,13 @@ K_DESC : D E S C; K_DISTINCT : D I S T I N C T; K_ESCAPE: E S C A P E; K_EXISTS : E X I S T S; +K_FIRST : F I R S T; K_FALSE : 'false'; K_FROM : F R O M; K_GROUP : G R O U P; K_IN : I N ; K_JOIN : J O I N; +K_LAST : L A S T; K_LEFT : L E F T; K_LIKE : L I K E; K_LIMIT : L I M I T; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs index 18003391b1..62f2873d72 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseListener.cs @@ -666,6 +666,20 @@ public virtual void EnterObjectCreateScalarExpression([NotNull] sqlParser.Object /// The parse tree. public virtual void ExitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { } /// + /// Enter a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context) { } + /// + /// Exit a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context) { } + /// /// Enter a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// The default implementation does nothing. @@ -792,6 +806,20 @@ public virtual void EnterArrayScalarExpression([NotNull] sqlParser.ArrayScalarEx /// The parse tree. public virtual void ExitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context) { } /// + /// Enter a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void EnterLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context) { } + /// + /// Exit a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// The default implementation does nothing. + /// + /// The parse tree. + public virtual void ExitLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context) { } + /// /// Enter a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// The default implementation does nothing. diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs index bb3b86379d..4594f5fc79 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlBaseVisitor.cs @@ -549,6 +549,17 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// The visitor result. public virtual Result VisitObjectCreateScalarExpression([NotNull] sqlParser.ObjectCreateScalarExpressionContext context) { return VisitChildren(context); } /// + /// Visit a parse tree produced by the FirstScalarExpression + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitFirstScalarExpression([NotNull] sqlParser.FirstScalarExpressionContext context) { return VisitChildren(context); } + /// /// Visit a parse tree produced by the ArrayCreateScalarExpression /// labeled alternative in . /// @@ -648,6 +659,17 @@ internal partial class sqlBaseVisitor : AbstractParseTreeVisitor /// The visitor result. public virtual Result VisitArrayScalarExpression([NotNull] sqlParser.ArrayScalarExpressionContext context) { return VisitChildren(context); } /// + /// Visit a parse tree produced by the LastScalarExpression + /// labeled alternative in . + /// + /// The default implementation returns the result of calling + /// on . + /// + /// + /// The parse tree. + /// The visitor result. + public virtual Result VisitLastScalarExpression([NotNull] sqlParser.LastScalarExpressionContext context) { return VisitChildren(context); } + /// /// Visit a parse tree produced by the PropertyRefScalarExpressionRecursive /// labeled alternative in . /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs index 1d5b7262bd..88888fea5d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlLexer.cs @@ -37,11 +37,11 @@ public const int T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, T__24=25, T__25=26, T__26=27, K_ALL=28, K_AND=29, K_ARRAY=30, K_AS=31, K_ASC=32, K_BETWEEN=33, K_BY=34, K_DESC=35, K_DISTINCT=36, K_ESCAPE=37, - K_EXISTS=38, K_FALSE=39, K_FROM=40, K_GROUP=41, K_IN=42, K_JOIN=43, K_LEFT=44, - K_LIKE=45, K_LIMIT=46, K_NOT=47, K_NULL=48, K_OFFSET=49, K_OR=50, K_ORDER=51, - K_RIGHT=52, K_SELECT=53, K_TOP=54, K_TRUE=55, K_UDF=56, K_UNDEFINED=57, - K_VALUE=58, K_WHERE=59, WS=60, NUMERIC_LITERAL=61, STRING_LITERAL=62, - LEX_IDENTIFIER=63, PARAMETER=64; + K_EXISTS=38, K_FIRST=39, K_FALSE=40, K_FROM=41, K_GROUP=42, K_IN=43, K_JOIN=44, + K_LAST=45, K_LEFT=46, K_LIKE=47, K_LIMIT=48, K_NOT=49, K_NULL=50, K_OFFSET=51, + K_OR=52, K_ORDER=53, K_RIGHT=54, K_SELECT=55, K_TOP=56, K_TRUE=57, K_UDF=58, + K_UNDEFINED=59, K_VALUE=60, K_WHERE=61, WS=62, NUMERIC_LITERAL=63, STRING_LITERAL=64, + LEX_IDENTIFIER=65, PARAMETER=66; public static string[] channelNames = { "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; @@ -55,11 +55,11 @@ public const int "T__9", "T__10", "T__11", "T__12", "T__13", "T__14", "T__15", "T__16", "T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", "T__25", "T__26", "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", "K_BETWEEN", - "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", "K_FROM", - "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", - "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", "K_TOP", "K_TRUE", - "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", "NUMERIC_LITERAL", - "STRING_LITERAL", "ESC", "UNICODE", "HEX", "SAFECODEPOINTWITHSINGLEQUOTATION", + "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FIRST", "K_FALSE", + "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LAST", "K_LEFT", "K_LIKE", "K_LIMIT", + "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", + "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", + "NUMERIC_LITERAL", "STRING_LITERAL", "ESC", "UNICODE", "HEX", "SAFECODEPOINTWITHSINGLEQUOTATION", "SAFECODEPOINTWITHDOUBLEQUOTATION", "LEX_IDENTIFIER", "PARAMETER", "DIGIT", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" @@ -79,19 +79,20 @@ public sqlLexer(ICharStream input, TextWriter output, TextWriter errorOutput) null, "'*'", "','", "'('", "')'", "'.'", "'['", "']'", "'?'", "':'", "'??'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'>='", "'<='", "'='", "'!='", "'&'", "'^'", "'|'", "'||'", "'~'", "'{'", "'}'", null, null, null, null, - null, null, null, null, null, null, null, "'false'", null, null, null, - null, null, null, null, null, "'null'", null, null, null, null, null, - null, "'true'", "'udf'", "'undefined'" + null, null, null, null, null, null, null, null, "'false'", null, null, + null, null, null, null, null, null, null, "'null'", null, null, null, + null, null, null, "'true'", "'udf'", "'undefined'" }; private static readonly string[] _SymbolicNames = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", - "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", - "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", - "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", - "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", - "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", "PARAMETER" + "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FIRST", + "K_FALSE", "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LAST", "K_LEFT", + "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", + "K_RIGHT", "K_SELECT", "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", + "K_WHERE", "WS", "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", + "PARAMETER" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -122,7 +123,7 @@ static sqlLexer() { } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x2', '\x42', '\x24E', '\b', '\x1', '\x4', '\x2', '\t', '\x2', + '\x5964', '\x2', '\x44', '\x25D', '\b', '\x1', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', @@ -156,469 +157,482 @@ static sqlLexer() { 'X', '\x4', 'Y', '\t', 'Y', '\x4', 'Z', '\t', 'Z', '\x4', '[', '\t', '[', '\x4', '\\', '\t', '\\', '\x4', ']', '\t', ']', '\x4', '^', '\t', '^', '\x4', '_', '\t', '_', '\x4', '`', '\t', '`', '\x4', '\x61', '\t', '\x61', - '\x3', '\x2', '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', - '\x3', '\x4', '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', - '\x3', '\a', '\x3', '\a', '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', - '\t', '\x3', '\n', '\x3', '\n', '\x3', '\v', '\x3', '\v', '\x3', '\v', - '\x3', '\f', '\x3', '\f', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', - '\xE', '\x3', '\xF', '\x3', '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', - '\x11', '\x3', '\x11', '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x3', - '\x13', '\x3', '\x13', '\x3', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', - '\x15', '\x3', '\x15', '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', - '\x17', '\x3', '\x17', '\x3', '\x18', '\x3', '\x18', '\x3', '\x19', '\x3', - '\x19', '\x3', '\x19', '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1B', '\x3', - '\x1B', '\x3', '\x1C', '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', - '\x1D', '\x3', '\x1D', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', - '\x1E', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', - '\x1F', '\x3', '\x1F', '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', '!', - '\x3', '!', '\x3', '!', '\x3', '!', '\x3', '\"', '\x3', '\"', '\x3', '\"', - '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', - '#', '\x3', '#', '\x3', '#', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', - '$', '\x3', '$', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', - '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', - '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', - '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', - '\x3', '\'', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', - '\x3', '(', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', - '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', - '\x3', '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', '\x3', ',', - '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', - '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', - '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', - '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x31', - '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x32', - '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', - '\x3', '\x32', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x34', - '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', - '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', - '\x3', '\x35', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', - '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x37', '\x3', '\x37', - '\x3', '\x37', '\x3', '\x37', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', - '\x3', '\x38', '\x3', '\x38', '\x3', '\x39', '\x3', '\x39', '\x3', '\x39', - '\x3', '\x39', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', - ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', - ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', - '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', - '=', '\x6', '=', '\x1AE', '\n', '=', '\r', '=', '\xE', '=', '\x1AF', '\x3', - '=', '\x3', '=', '\x3', '>', '\x5', '>', '\x1B5', '\n', '>', '\x3', '>', - '\x6', '>', '\x1B8', '\n', '>', '\r', '>', '\xE', '>', '\x1B9', '\x3', - '>', '\x3', '>', '\a', '>', '\x1BE', '\n', '>', '\f', '>', '\xE', '>', - '\x1C1', '\v', '>', '\x5', '>', '\x1C3', '\n', '>', '\x3', '>', '\x3', - '>', '\x5', '>', '\x1C7', '\n', '>', '\x3', '>', '\x6', '>', '\x1CA', - '\n', '>', '\r', '>', '\xE', '>', '\x1CB', '\x5', '>', '\x1CE', '\n', - '>', '\x3', '>', '\x5', '>', '\x1D1', '\n', '>', '\x3', '>', '\x3', '>', - '\x6', '>', '\x1D5', '\n', '>', '\r', '>', '\xE', '>', '\x1D6', '\x3', - '>', '\x3', '>', '\x5', '>', '\x1DB', '\n', '>', '\x3', '>', '\x6', '>', - '\x1DE', '\n', '>', '\r', '>', '\xE', '>', '\x1DF', '\x5', '>', '\x1E2', - '\n', '>', '\x5', '>', '\x1E4', '\n', '>', '\x3', '?', '\x3', '?', '\x3', - '?', '\a', '?', '\x1E9', '\n', '?', '\f', '?', '\xE', '?', '\x1EC', '\v', - '?', '\x3', '?', '\x3', '?', '\x3', '?', '\x3', '?', '\a', '?', '\x1F2', - '\n', '?', '\f', '?', '\xE', '?', '\x1F5', '\v', '?', '\x3', '?', '\x5', - '?', '\x1F8', '\n', '?', '\x3', '@', '\x3', '@', '\x3', '@', '\x5', '@', - '\x1FD', '\n', '@', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', - '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x42', '\x3', '\x42', '\x3', - '\x43', '\x3', '\x43', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', - '\x45', '\x3', '\x45', '\x3', '\x45', '\a', '\x45', '\x20F', '\n', '\x45', - '\f', '\x45', '\xE', '\x45', '\x212', '\v', '\x45', '\x5', '\x45', '\x214', - '\n', '\x45', '\x3', '\x46', '\x3', '\x46', '\x3', '\x46', '\x3', 'G', - '\x3', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'I', '\x3', 'I', '\x3', 'J', - '\x3', 'J', '\x3', 'K', '\x3', 'K', '\x3', 'L', '\x3', 'L', '\x3', 'M', - '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', 'O', '\x3', 'O', '\x3', 'P', - '\x3', 'P', '\x3', 'Q', '\x3', 'Q', '\x3', 'R', '\x3', 'R', '\x3', 'S', - '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', 'U', '\x3', 'U', '\x3', 'V', - '\x3', 'V', '\x3', 'W', '\x3', 'W', '\x3', 'X', '\x3', 'X', '\x3', 'Y', - '\x3', 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', '[', '\x3', '[', '\x3', '\\', - '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', '^', '\x3', '^', '\x3', '_', - '\x3', '_', '\x3', '`', '\x3', '`', '\x3', '\x61', '\x3', '\x61', '\x2', - '\x2', '\x62', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', '\t', '\x6', '\v', - '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', '\v', '\x15', '\f', - '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', '\x10', '\x1F', '\x11', - '!', '\x12', '#', '\x13', '%', '\x14', '\'', '\x15', ')', '\x16', '+', - '\x17', '-', '\x18', '/', '\x19', '\x31', '\x1A', '\x33', '\x1B', '\x35', - '\x1C', '\x37', '\x1D', '\x39', '\x1E', ';', '\x1F', '=', ' ', '?', '!', - '\x41', '\"', '\x43', '#', '\x45', '$', 'G', '%', 'I', '&', 'K', '\'', - 'M', '(', 'O', ')', 'Q', '*', 'S', '+', 'U', ',', 'W', '-', 'Y', '.', - '[', '/', ']', '\x30', '_', '\x31', '\x61', '\x32', '\x63', '\x33', '\x65', - '\x34', 'g', '\x35', 'i', '\x36', 'k', '\x37', 'm', '\x38', 'o', '\x39', - 'q', ':', 's', ';', 'u', '<', 'w', '=', 'y', '>', '{', '?', '}', '@', - '\x7F', '\x2', '\x81', '\x2', '\x83', '\x2', '\x85', '\x2', '\x87', '\x2', - '\x89', '\x41', '\x8B', '\x42', '\x8D', '\x2', '\x8F', '\x2', '\x91', - '\x2', '\x93', '\x2', '\x95', '\x2', '\x97', '\x2', '\x99', '\x2', '\x9B', - '\x2', '\x9D', '\x2', '\x9F', '\x2', '\xA1', '\x2', '\xA3', '\x2', '\xA5', - '\x2', '\xA7', '\x2', '\xA9', '\x2', '\xAB', '\x2', '\xAD', '\x2', '\xAF', - '\x2', '\xB1', '\x2', '\xB3', '\x2', '\xB5', '\x2', '\xB7', '\x2', '\xB9', - '\x2', '\xBB', '\x2', '\xBD', '\x2', '\xBF', '\x2', '\xC1', '\x2', '\x3', - '\x2', '$', '\x5', '\x2', '\v', '\f', '\xF', '\xF', '\"', '\"', '\x4', - '\x2', '-', '-', '/', '/', '\n', '\x2', '$', '$', '\x31', '\x31', '^', - '^', '\x64', '\x64', 'h', 'h', 'p', 'p', 't', 't', 'v', 'v', '\x5', '\x2', - '\x32', ';', '\x43', 'H', '\x63', 'h', '\x5', '\x2', '\x2', '!', ')', - ')', '^', '^', '\x5', '\x2', '\x2', '!', '$', '$', '^', '^', '\x5', '\x2', - '\x43', '\\', '\x61', '\x61', '\x63', '|', '\x3', '\x2', '\x32', ';', - '\x4', '\x2', '\x43', '\x43', '\x63', '\x63', '\x4', '\x2', '\x44', '\x44', - '\x64', '\x64', '\x4', '\x2', '\x45', '\x45', '\x65', '\x65', '\x4', '\x2', - '\x46', '\x46', '\x66', '\x66', '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', - '\x2', 'H', 'H', 'h', 'h', '\x4', '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', - 'J', 'J', 'j', 'j', '\x4', '\x2', 'K', 'K', 'k', 'k', '\x4', '\x2', 'L', - 'L', 'l', 'l', '\x4', '\x2', 'M', 'M', 'm', 'm', '\x4', '\x2', 'N', 'N', - 'n', 'n', '\x4', '\x2', 'O', 'O', 'o', 'o', '\x4', '\x2', 'P', 'P', 'p', - 'p', '\x4', '\x2', 'Q', 'Q', 'q', 'q', '\x4', '\x2', 'R', 'R', 'r', 'r', - '\x4', '\x2', 'S', 'S', 's', 's', '\x4', '\x2', 'T', 'T', 't', 't', '\x4', - '\x2', 'U', 'U', 'u', 'u', '\x4', '\x2', 'V', 'V', 'v', 'v', '\x4', '\x2', - 'W', 'W', 'w', 'w', '\x4', '\x2', 'X', 'X', 'x', 'x', '\x4', '\x2', 'Y', - 'Y', 'y', 'y', '\x4', '\x2', 'Z', 'Z', 'z', 'z', '\x4', '\x2', '[', '[', - '{', '{', '\x4', '\x2', '\\', '\\', '|', '|', '\x2', '\x244', '\x2', '\x3', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x5', '\x3', '\x2', '\x2', '\x2', - '\x2', '\a', '\x3', '\x2', '\x2', '\x2', '\x2', '\t', '\x3', '\x2', '\x2', - '\x2', '\x2', '\v', '\x3', '\x2', '\x2', '\x2', '\x2', '\r', '\x3', '\x2', - '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', '\x2', '\x2', '\x2', '\x11', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', '\x2', '\x17', '\x3', '\x2', - '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1B', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', '\x2', '!', '\x3', '\x2', '\x2', - '\x2', '\x2', '#', '\x3', '\x2', '\x2', '\x2', '\x2', '%', '\x3', '\x2', - '\x2', '\x2', '\x2', '\'', '\x3', '\x2', '\x2', '\x2', '\x2', ')', '\x3', - '\x2', '\x2', '\x2', '\x2', '+', '\x3', '\x2', '\x2', '\x2', '\x2', '-', - '\x3', '\x2', '\x2', '\x2', '\x2', '/', '\x3', '\x2', '\x2', '\x2', '\x2', - '\x31', '\x3', '\x2', '\x2', '\x2', '\x2', '\x33', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x35', '\x3', '\x2', '\x2', '\x2', '\x2', '\x37', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x39', '\x3', '\x2', '\x2', '\x2', '\x2', - ';', '\x3', '\x2', '\x2', '\x2', '\x2', '=', '\x3', '\x2', '\x2', '\x2', - '\x2', '?', '\x3', '\x2', '\x2', '\x2', '\x2', '\x41', '\x3', '\x2', '\x2', - '\x2', '\x2', '\x43', '\x3', '\x2', '\x2', '\x2', '\x2', '\x45', '\x3', - '\x2', '\x2', '\x2', '\x2', 'G', '\x3', '\x2', '\x2', '\x2', '\x2', 'I', - '\x3', '\x2', '\x2', '\x2', '\x2', 'K', '\x3', '\x2', '\x2', '\x2', '\x2', - 'M', '\x3', '\x2', '\x2', '\x2', '\x2', 'O', '\x3', '\x2', '\x2', '\x2', - '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', '\x2', 'S', '\x3', '\x2', '\x2', - '\x2', '\x2', 'U', '\x3', '\x2', '\x2', '\x2', '\x2', 'W', '\x3', '\x2', - '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', '\x2', '\x2', '\x2', '[', '\x3', - '\x2', '\x2', '\x2', '\x2', ']', '\x3', '\x2', '\x2', '\x2', '\x2', '_', - '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', '\x3', '\x2', '\x2', '\x2', - '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', '\x2', '\x65', '\x3', '\x2', - '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', '\x2', '\x2', 'i', '\x3', - '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', '\x2', '\x2', '\x2', 'm', - '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', '\x2', '\x2', '\x2', '\x2', - 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', '\x3', '\x2', '\x2', '\x2', - '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', 'w', '\x3', '\x2', '\x2', - '\x2', '\x2', 'y', '\x3', '\x2', '\x2', '\x2', '\x2', '{', '\x3', '\x2', - '\x2', '\x2', '\x2', '}', '\x3', '\x2', '\x2', '\x2', '\x2', '\x89', '\x3', - '\x2', '\x2', '\x2', '\x2', '\x8B', '\x3', '\x2', '\x2', '\x2', '\x3', - '\xC3', '\x3', '\x2', '\x2', '\x2', '\x5', '\xC5', '\x3', '\x2', '\x2', - '\x2', '\a', '\xC7', '\x3', '\x2', '\x2', '\x2', '\t', '\xC9', '\x3', - '\x2', '\x2', '\x2', '\v', '\xCB', '\x3', '\x2', '\x2', '\x2', '\r', '\xCD', - '\x3', '\x2', '\x2', '\x2', '\xF', '\xCF', '\x3', '\x2', '\x2', '\x2', - '\x11', '\xD1', '\x3', '\x2', '\x2', '\x2', '\x13', '\xD3', '\x3', '\x2', - '\x2', '\x2', '\x15', '\xD5', '\x3', '\x2', '\x2', '\x2', '\x17', '\xD8', - '\x3', '\x2', '\x2', '\x2', '\x19', '\xDA', '\x3', '\x2', '\x2', '\x2', - '\x1B', '\xDC', '\x3', '\x2', '\x2', '\x2', '\x1D', '\xDE', '\x3', '\x2', - '\x2', '\x2', '\x1F', '\xE0', '\x3', '\x2', '\x2', '\x2', '!', '\xE2', - '\x3', '\x2', '\x2', '\x2', '#', '\xE4', '\x3', '\x2', '\x2', '\x2', '%', - '\xE7', '\x3', '\x2', '\x2', '\x2', '\'', '\xEA', '\x3', '\x2', '\x2', - '\x2', ')', '\xEC', '\x3', '\x2', '\x2', '\x2', '+', '\xEF', '\x3', '\x2', - '\x2', '\x2', '-', '\xF1', '\x3', '\x2', '\x2', '\x2', '/', '\xF3', '\x3', - '\x2', '\x2', '\x2', '\x31', '\xF5', '\x3', '\x2', '\x2', '\x2', '\x33', - '\xF8', '\x3', '\x2', '\x2', '\x2', '\x35', '\xFA', '\x3', '\x2', '\x2', - '\x2', '\x37', '\xFC', '\x3', '\x2', '\x2', '\x2', '\x39', '\xFE', '\x3', - '\x2', '\x2', '\x2', ';', '\x102', '\x3', '\x2', '\x2', '\x2', '=', '\x106', - '\x3', '\x2', '\x2', '\x2', '?', '\x10C', '\x3', '\x2', '\x2', '\x2', - '\x41', '\x10F', '\x3', '\x2', '\x2', '\x2', '\x43', '\x113', '\x3', '\x2', - '\x2', '\x2', '\x45', '\x11B', '\x3', '\x2', '\x2', '\x2', 'G', '\x11E', - '\x3', '\x2', '\x2', '\x2', 'I', '\x123', '\x3', '\x2', '\x2', '\x2', - 'K', '\x12C', '\x3', '\x2', '\x2', '\x2', 'M', '\x133', '\x3', '\x2', - '\x2', '\x2', 'O', '\x13A', '\x3', '\x2', '\x2', '\x2', 'Q', '\x140', - '\x3', '\x2', '\x2', '\x2', 'S', '\x145', '\x3', '\x2', '\x2', '\x2', - 'U', '\x14B', '\x3', '\x2', '\x2', '\x2', 'W', '\x14E', '\x3', '\x2', - '\x2', '\x2', 'Y', '\x153', '\x3', '\x2', '\x2', '\x2', '[', '\x158', - '\x3', '\x2', '\x2', '\x2', ']', '\x15D', '\x3', '\x2', '\x2', '\x2', - '_', '\x163', '\x3', '\x2', '\x2', '\x2', '\x61', '\x167', '\x3', '\x2', - '\x2', '\x2', '\x63', '\x16C', '\x3', '\x2', '\x2', '\x2', '\x65', '\x173', - '\x3', '\x2', '\x2', '\x2', 'g', '\x176', '\x3', '\x2', '\x2', '\x2', - 'i', '\x17C', '\x3', '\x2', '\x2', '\x2', 'k', '\x182', '\x3', '\x2', - '\x2', '\x2', 'm', '\x189', '\x3', '\x2', '\x2', '\x2', 'o', '\x18D', - '\x3', '\x2', '\x2', '\x2', 'q', '\x192', '\x3', '\x2', '\x2', '\x2', - 's', '\x196', '\x3', '\x2', '\x2', '\x2', 'u', '\x1A0', '\x3', '\x2', - '\x2', '\x2', 'w', '\x1A6', '\x3', '\x2', '\x2', '\x2', 'y', '\x1AD', - '\x3', '\x2', '\x2', '\x2', '{', '\x1E3', '\x3', '\x2', '\x2', '\x2', - '}', '\x1F7', '\x3', '\x2', '\x2', '\x2', '\x7F', '\x1F9', '\x3', '\x2', - '\x2', '\x2', '\x81', '\x1FE', '\x3', '\x2', '\x2', '\x2', '\x83', '\x204', - '\x3', '\x2', '\x2', '\x2', '\x85', '\x206', '\x3', '\x2', '\x2', '\x2', - '\x87', '\x208', '\x3', '\x2', '\x2', '\x2', '\x89', '\x213', '\x3', '\x2', - '\x2', '\x2', '\x8B', '\x215', '\x3', '\x2', '\x2', '\x2', '\x8D', '\x218', - '\x3', '\x2', '\x2', '\x2', '\x8F', '\x21A', '\x3', '\x2', '\x2', '\x2', - '\x91', '\x21C', '\x3', '\x2', '\x2', '\x2', '\x93', '\x21E', '\x3', '\x2', - '\x2', '\x2', '\x95', '\x220', '\x3', '\x2', '\x2', '\x2', '\x97', '\x222', - '\x3', '\x2', '\x2', '\x2', '\x99', '\x224', '\x3', '\x2', '\x2', '\x2', - '\x9B', '\x226', '\x3', '\x2', '\x2', '\x2', '\x9D', '\x228', '\x3', '\x2', - '\x2', '\x2', '\x9F', '\x22A', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x22C', - '\x3', '\x2', '\x2', '\x2', '\xA3', '\x22E', '\x3', '\x2', '\x2', '\x2', - '\xA5', '\x230', '\x3', '\x2', '\x2', '\x2', '\xA7', '\x232', '\x3', '\x2', - '\x2', '\x2', '\xA9', '\x234', '\x3', '\x2', '\x2', '\x2', '\xAB', '\x236', - '\x3', '\x2', '\x2', '\x2', '\xAD', '\x238', '\x3', '\x2', '\x2', '\x2', - '\xAF', '\x23A', '\x3', '\x2', '\x2', '\x2', '\xB1', '\x23C', '\x3', '\x2', - '\x2', '\x2', '\xB3', '\x23E', '\x3', '\x2', '\x2', '\x2', '\xB5', '\x240', - '\x3', '\x2', '\x2', '\x2', '\xB7', '\x242', '\x3', '\x2', '\x2', '\x2', - '\xB9', '\x244', '\x3', '\x2', '\x2', '\x2', '\xBB', '\x246', '\x3', '\x2', - '\x2', '\x2', '\xBD', '\x248', '\x3', '\x2', '\x2', '\x2', '\xBF', '\x24A', - '\x3', '\x2', '\x2', '\x2', '\xC1', '\x24C', '\x3', '\x2', '\x2', '\x2', - '\xC3', '\xC4', '\a', ',', '\x2', '\x2', '\xC4', '\x4', '\x3', '\x2', - '\x2', '\x2', '\xC5', '\xC6', '\a', '.', '\x2', '\x2', '\xC6', '\x6', - '\x3', '\x2', '\x2', '\x2', '\xC7', '\xC8', '\a', '*', '\x2', '\x2', '\xC8', - '\b', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xCA', '\a', '+', '\x2', '\x2', - '\xCA', '\n', '\x3', '\x2', '\x2', '\x2', '\xCB', '\xCC', '\a', '\x30', - '\x2', '\x2', '\xCC', '\f', '\x3', '\x2', '\x2', '\x2', '\xCD', '\xCE', - '\a', ']', '\x2', '\x2', '\xCE', '\xE', '\x3', '\x2', '\x2', '\x2', '\xCF', - '\xD0', '\a', '_', '\x2', '\x2', '\xD0', '\x10', '\x3', '\x2', '\x2', - '\x2', '\xD1', '\xD2', '\a', '\x41', '\x2', '\x2', '\xD2', '\x12', '\x3', - '\x2', '\x2', '\x2', '\xD3', '\xD4', '\a', '<', '\x2', '\x2', '\xD4', - '\x14', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD6', '\a', '\x41', '\x2', - '\x2', '\xD6', '\xD7', '\a', '\x41', '\x2', '\x2', '\xD7', '\x16', '\x3', - '\x2', '\x2', '\x2', '\xD8', '\xD9', '\a', '\x31', '\x2', '\x2', '\xD9', - '\x18', '\x3', '\x2', '\x2', '\x2', '\xDA', '\xDB', '\a', '\'', '\x2', - '\x2', '\xDB', '\x1A', '\x3', '\x2', '\x2', '\x2', '\xDC', '\xDD', '\a', - '-', '\x2', '\x2', '\xDD', '\x1C', '\x3', '\x2', '\x2', '\x2', '\xDE', - '\xDF', '\a', '/', '\x2', '\x2', '\xDF', '\x1E', '\x3', '\x2', '\x2', - '\x2', '\xE0', '\xE1', '\a', '>', '\x2', '\x2', '\xE1', ' ', '\x3', '\x2', - '\x2', '\x2', '\xE2', '\xE3', '\a', '@', '\x2', '\x2', '\xE3', '\"', '\x3', - '\x2', '\x2', '\x2', '\xE4', '\xE5', '\a', '@', '\x2', '\x2', '\xE5', - '\xE6', '\a', '?', '\x2', '\x2', '\xE6', '$', '\x3', '\x2', '\x2', '\x2', - '\xE7', '\xE8', '\a', '>', '\x2', '\x2', '\xE8', '\xE9', '\a', '?', '\x2', - '\x2', '\xE9', '&', '\x3', '\x2', '\x2', '\x2', '\xEA', '\xEB', '\a', - '?', '\x2', '\x2', '\xEB', '(', '\x3', '\x2', '\x2', '\x2', '\xEC', '\xED', - '\a', '#', '\x2', '\x2', '\xED', '\xEE', '\a', '?', '\x2', '\x2', '\xEE', - '*', '\x3', '\x2', '\x2', '\x2', '\xEF', '\xF0', '\a', '(', '\x2', '\x2', - '\xF0', ',', '\x3', '\x2', '\x2', '\x2', '\xF1', '\xF2', '\a', '`', '\x2', - '\x2', '\xF2', '.', '\x3', '\x2', '\x2', '\x2', '\xF3', '\xF4', '\a', - '~', '\x2', '\x2', '\xF4', '\x30', '\x3', '\x2', '\x2', '\x2', '\xF5', - '\xF6', '\a', '~', '\x2', '\x2', '\xF6', '\xF7', '\a', '~', '\x2', '\x2', - '\xF7', '\x32', '\x3', '\x2', '\x2', '\x2', '\xF8', '\xF9', '\a', '\x80', - '\x2', '\x2', '\xF9', '\x34', '\x3', '\x2', '\x2', '\x2', '\xFA', '\xFB', - '\a', '}', '\x2', '\x2', '\xFB', '\x36', '\x3', '\x2', '\x2', '\x2', '\xFC', - '\xFD', '\a', '\x7F', '\x2', '\x2', '\xFD', '\x38', '\x3', '\x2', '\x2', - '\x2', '\xFE', '\xFF', '\x5', '\x8F', 'H', '\x2', '\xFF', '\x100', '\x5', - '\xA5', 'S', '\x2', '\x100', '\x101', '\x5', '\xA5', 'S', '\x2', '\x101', - ':', '\x3', '\x2', '\x2', '\x2', '\x102', '\x103', '\x5', '\x8F', 'H', - '\x2', '\x103', '\x104', '\x5', '\xA9', 'U', '\x2', '\x104', '\x105', - '\x5', '\x95', 'K', '\x2', '\x105', '<', '\x3', '\x2', '\x2', '\x2', '\x106', - '\x107', '\x5', '\x8F', 'H', '\x2', '\x107', '\x108', '\x5', '\xB1', 'Y', - '\x2', '\x108', '\x109', '\x5', '\xB1', 'Y', '\x2', '\x109', '\x10A', - '\x5', '\x8F', 'H', '\x2', '\x10A', '\x10B', '\x5', '\xBF', '`', '\x2', - '\x10B', '>', '\x3', '\x2', '\x2', '\x2', '\x10C', '\x10D', '\x5', '\x8F', - 'H', '\x2', '\x10D', '\x10E', '\x5', '\xB3', 'Z', '\x2', '\x10E', '@', - '\x3', '\x2', '\x2', '\x2', '\x10F', '\x110', '\x5', '\x8F', 'H', '\x2', - '\x110', '\x111', '\x5', '\xB3', 'Z', '\x2', '\x111', '\x112', '\x5', - '\x93', 'J', '\x2', '\x112', '\x42', '\x3', '\x2', '\x2', '\x2', '\x113', - '\x114', '\x5', '\x91', 'I', '\x2', '\x114', '\x115', '\x5', '\x97', 'L', - '\x2', '\x115', '\x116', '\x5', '\xB5', '[', '\x2', '\x116', '\x117', - '\x5', '\xBB', '^', '\x2', '\x117', '\x118', '\x5', '\x97', 'L', '\x2', - '\x118', '\x119', '\x5', '\x97', 'L', '\x2', '\x119', '\x11A', '\x5', - '\xA9', 'U', '\x2', '\x11A', '\x44', '\x3', '\x2', '\x2', '\x2', '\x11B', - '\x11C', '\x5', '\x91', 'I', '\x2', '\x11C', '\x11D', '\x5', '\xBF', '`', - '\x2', '\x11D', '\x46', '\x3', '\x2', '\x2', '\x2', '\x11E', '\x11F', - '\x5', '\x95', 'K', '\x2', '\x11F', '\x120', '\x5', '\x97', 'L', '\x2', - '\x120', '\x121', '\x5', '\xB3', 'Z', '\x2', '\x121', '\x122', '\x5', - '\x93', 'J', '\x2', '\x122', 'H', '\x3', '\x2', '\x2', '\x2', '\x123', - '\x124', '\x5', '\x95', 'K', '\x2', '\x124', '\x125', '\x5', '\x9F', 'P', - '\x2', '\x125', '\x126', '\x5', '\xB3', 'Z', '\x2', '\x126', '\x127', - '\x5', '\xB5', '[', '\x2', '\x127', '\x128', '\x5', '\x9F', 'P', '\x2', - '\x128', '\x129', '\x5', '\xA9', 'U', '\x2', '\x129', '\x12A', '\x5', - '\x93', 'J', '\x2', '\x12A', '\x12B', '\x5', '\xB5', '[', '\x2', '\x12B', - 'J', '\x3', '\x2', '\x2', '\x2', '\x12C', '\x12D', '\x5', '\x97', 'L', - '\x2', '\x12D', '\x12E', '\x5', '\xB3', 'Z', '\x2', '\x12E', '\x12F', - '\x5', '\x93', 'J', '\x2', '\x12F', '\x130', '\x5', '\x8F', 'H', '\x2', - '\x130', '\x131', '\x5', '\xAD', 'W', '\x2', '\x131', '\x132', '\x5', - '\x97', 'L', '\x2', '\x132', 'L', '\x3', '\x2', '\x2', '\x2', '\x133', - '\x134', '\x5', '\x97', 'L', '\x2', '\x134', '\x135', '\x5', '\xBD', '_', - '\x2', '\x135', '\x136', '\x5', '\x9F', 'P', '\x2', '\x136', '\x137', - '\x5', '\xB3', 'Z', '\x2', '\x137', '\x138', '\x5', '\xB5', '[', '\x2', - '\x138', '\x139', '\x5', '\xB3', 'Z', '\x2', '\x139', 'N', '\x3', '\x2', - '\x2', '\x2', '\x13A', '\x13B', '\a', 'h', '\x2', '\x2', '\x13B', '\x13C', - '\a', '\x63', '\x2', '\x2', '\x13C', '\x13D', '\a', 'n', '\x2', '\x2', - '\x13D', '\x13E', '\a', 'u', '\x2', '\x2', '\x13E', '\x13F', '\a', 'g', - '\x2', '\x2', '\x13F', 'P', '\x3', '\x2', '\x2', '\x2', '\x140', '\x141', - '\x5', '\x99', 'M', '\x2', '\x141', '\x142', '\x5', '\xB1', 'Y', '\x2', - '\x142', '\x143', '\x5', '\xAB', 'V', '\x2', '\x143', '\x144', '\x5', - '\xA7', 'T', '\x2', '\x144', 'R', '\x3', '\x2', '\x2', '\x2', '\x145', - '\x146', '\x5', '\x9B', 'N', '\x2', '\x146', '\x147', '\x5', '\xB1', 'Y', - '\x2', '\x147', '\x148', '\x5', '\xAB', 'V', '\x2', '\x148', '\x149', - '\x5', '\xB7', '\\', '\x2', '\x149', '\x14A', '\x5', '\xAD', 'W', '\x2', - '\x14A', 'T', '\x3', '\x2', '\x2', '\x2', '\x14B', '\x14C', '\x5', '\x9F', - 'P', '\x2', '\x14C', '\x14D', '\x5', '\xA9', 'U', '\x2', '\x14D', 'V', - '\x3', '\x2', '\x2', '\x2', '\x14E', '\x14F', '\x5', '\xA1', 'Q', '\x2', - '\x14F', '\x150', '\x5', '\xAB', 'V', '\x2', '\x150', '\x151', '\x5', - '\x9F', 'P', '\x2', '\x151', '\x152', '\x5', '\xA9', 'U', '\x2', '\x152', - 'X', '\x3', '\x2', '\x2', '\x2', '\x153', '\x154', '\x5', '\xA5', 'S', - '\x2', '\x154', '\x155', '\x5', '\x97', 'L', '\x2', '\x155', '\x156', - '\x5', '\x99', 'M', '\x2', '\x156', '\x157', '\x5', '\xB5', '[', '\x2', - '\x157', 'Z', '\x3', '\x2', '\x2', '\x2', '\x158', '\x159', '\x5', '\xA5', - 'S', '\x2', '\x159', '\x15A', '\x5', '\x9F', 'P', '\x2', '\x15A', '\x15B', - '\x5', '\xA3', 'R', '\x2', '\x15B', '\x15C', '\x5', '\x97', 'L', '\x2', - '\x15C', '\\', '\x3', '\x2', '\x2', '\x2', '\x15D', '\x15E', '\x5', '\xA5', - 'S', '\x2', '\x15E', '\x15F', '\x5', '\x9F', 'P', '\x2', '\x15F', '\x160', - '\x5', '\xA7', 'T', '\x2', '\x160', '\x161', '\x5', '\x9F', 'P', '\x2', - '\x161', '\x162', '\x5', '\xB5', '[', '\x2', '\x162', '^', '\x3', '\x2', - '\x2', '\x2', '\x163', '\x164', '\x5', '\xA9', 'U', '\x2', '\x164', '\x165', - '\x5', '\xAB', 'V', '\x2', '\x165', '\x166', '\x5', '\xB5', '[', '\x2', - '\x166', '`', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', '\a', 'p', - '\x2', '\x2', '\x168', '\x169', '\a', 'w', '\x2', '\x2', '\x169', '\x16A', - '\a', 'n', '\x2', '\x2', '\x16A', '\x16B', '\a', 'n', '\x2', '\x2', '\x16B', - '\x62', '\x3', '\x2', '\x2', '\x2', '\x16C', '\x16D', '\x5', '\xAB', 'V', - '\x2', '\x16D', '\x16E', '\x5', '\x99', 'M', '\x2', '\x16E', '\x16F', - '\x5', '\x99', 'M', '\x2', '\x16F', '\x170', '\x5', '\xB3', 'Z', '\x2', - '\x170', '\x171', '\x5', '\x97', 'L', '\x2', '\x171', '\x172', '\x5', - '\xB5', '[', '\x2', '\x172', '\x64', '\x3', '\x2', '\x2', '\x2', '\x173', - '\x174', '\x5', '\xAB', 'V', '\x2', '\x174', '\x175', '\x5', '\xB1', 'Y', - '\x2', '\x175', '\x66', '\x3', '\x2', '\x2', '\x2', '\x176', '\x177', - '\x5', '\xAB', 'V', '\x2', '\x177', '\x178', '\x5', '\xB1', 'Y', '\x2', - '\x178', '\x179', '\x5', '\x95', 'K', '\x2', '\x179', '\x17A', '\x5', - '\x97', 'L', '\x2', '\x17A', '\x17B', '\x5', '\xB1', 'Y', '\x2', '\x17B', - 'h', '\x3', '\x2', '\x2', '\x2', '\x17C', '\x17D', '\x5', '\xB1', 'Y', - '\x2', '\x17D', '\x17E', '\x5', '\x9F', 'P', '\x2', '\x17E', '\x17F', - '\x5', '\x9B', 'N', '\x2', '\x17F', '\x180', '\x5', '\x9D', 'O', '\x2', - '\x180', '\x181', '\x5', '\xB5', '[', '\x2', '\x181', 'j', '\x3', '\x2', - '\x2', '\x2', '\x182', '\x183', '\x5', '\xB3', 'Z', '\x2', '\x183', '\x184', - '\x5', '\x97', 'L', '\x2', '\x184', '\x185', '\x5', '\xA5', 'S', '\x2', - '\x185', '\x186', '\x5', '\x97', 'L', '\x2', '\x186', '\x187', '\x5', - '\x93', 'J', '\x2', '\x187', '\x188', '\x5', '\xB5', '[', '\x2', '\x188', - 'l', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\x5', '\xB5', '[', - '\x2', '\x18A', '\x18B', '\x5', '\xAB', 'V', '\x2', '\x18B', '\x18C', - '\x5', '\xAD', 'W', '\x2', '\x18C', 'n', '\x3', '\x2', '\x2', '\x2', '\x18D', - '\x18E', '\a', 'v', '\x2', '\x2', '\x18E', '\x18F', '\a', 't', '\x2', - '\x2', '\x18F', '\x190', '\a', 'w', '\x2', '\x2', '\x190', '\x191', '\a', - 'g', '\x2', '\x2', '\x191', 'p', '\x3', '\x2', '\x2', '\x2', '\x192', - '\x193', '\a', 'w', '\x2', '\x2', '\x193', '\x194', '\a', '\x66', '\x2', - '\x2', '\x194', '\x195', '\a', 'h', '\x2', '\x2', '\x195', 'r', '\x3', - '\x2', '\x2', '\x2', '\x196', '\x197', '\a', 'w', '\x2', '\x2', '\x197', - '\x198', '\a', 'p', '\x2', '\x2', '\x198', '\x199', '\a', '\x66', '\x2', - '\x2', '\x199', '\x19A', '\a', 'g', '\x2', '\x2', '\x19A', '\x19B', '\a', - 'h', '\x2', '\x2', '\x19B', '\x19C', '\a', 'k', '\x2', '\x2', '\x19C', - '\x19D', '\a', 'p', '\x2', '\x2', '\x19D', '\x19E', '\a', 'g', '\x2', - '\x2', '\x19E', '\x19F', '\a', '\x66', '\x2', '\x2', '\x19F', 't', '\x3', - '\x2', '\x2', '\x2', '\x1A0', '\x1A1', '\x5', '\xB9', ']', '\x2', '\x1A1', - '\x1A2', '\x5', '\x8F', 'H', '\x2', '\x1A2', '\x1A3', '\x5', '\xA5', 'S', - '\x2', '\x1A3', '\x1A4', '\x5', '\xB7', '\\', '\x2', '\x1A4', '\x1A5', - '\x5', '\x97', 'L', '\x2', '\x1A5', 'v', '\x3', '\x2', '\x2', '\x2', '\x1A6', - '\x1A7', '\x5', '\xBB', '^', '\x2', '\x1A7', '\x1A8', '\x5', '\x9D', 'O', - '\x2', '\x1A8', '\x1A9', '\x5', '\x97', 'L', '\x2', '\x1A9', '\x1AA', - '\x5', '\xB1', 'Y', '\x2', '\x1AA', '\x1AB', '\x5', '\x97', 'L', '\x2', - '\x1AB', 'x', '\x3', '\x2', '\x2', '\x2', '\x1AC', '\x1AE', '\t', '\x2', - '\x2', '\x2', '\x1AD', '\x1AC', '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1AF', - '\x3', '\x2', '\x2', '\x2', '\x1AF', '\x1AD', '\x3', '\x2', '\x2', '\x2', - '\x1AF', '\x1B0', '\x3', '\x2', '\x2', '\x2', '\x1B0', '\x1B1', '\x3', - '\x2', '\x2', '\x2', '\x1B1', '\x1B2', '\b', '=', '\x2', '\x2', '\x1B2', - 'z', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B5', '\t', '\x3', '\x2', - '\x2', '\x1B4', '\x1B3', '\x3', '\x2', '\x2', '\x2', '\x1B4', '\x1B5', - '\x3', '\x2', '\x2', '\x2', '\x1B5', '\x1B7', '\x3', '\x2', '\x2', '\x2', - '\x1B6', '\x1B8', '\x5', '\x8D', 'G', '\x2', '\x1B7', '\x1B6', '\x3', - '\x2', '\x2', '\x2', '\x1B8', '\x1B9', '\x3', '\x2', '\x2', '\x2', '\x1B9', - '\x1B7', '\x3', '\x2', '\x2', '\x2', '\x1B9', '\x1BA', '\x3', '\x2', '\x2', - '\x2', '\x1BA', '\x1C2', '\x3', '\x2', '\x2', '\x2', '\x1BB', '\x1BF', - '\a', '\x30', '\x2', '\x2', '\x1BC', '\x1BE', '\x5', '\x8D', 'G', '\x2', - '\x1BD', '\x1BC', '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1C1', '\x3', - '\x2', '\x2', '\x2', '\x1BF', '\x1BD', '\x3', '\x2', '\x2', '\x2', '\x1BF', - '\x1C0', '\x3', '\x2', '\x2', '\x2', '\x1C0', '\x1C3', '\x3', '\x2', '\x2', - '\x2', '\x1C1', '\x1BF', '\x3', '\x2', '\x2', '\x2', '\x1C2', '\x1BB', - '\x3', '\x2', '\x2', '\x2', '\x1C2', '\x1C3', '\x3', '\x2', '\x2', '\x2', - '\x1C3', '\x1CD', '\x3', '\x2', '\x2', '\x2', '\x1C4', '\x1C6', '\x5', - '\x97', 'L', '\x2', '\x1C5', '\x1C7', '\t', '\x3', '\x2', '\x2', '\x1C6', - '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C6', '\x1C7', '\x3', '\x2', '\x2', - '\x2', '\x1C7', '\x1C9', '\x3', '\x2', '\x2', '\x2', '\x1C8', '\x1CA', - '\x5', '\x8D', 'G', '\x2', '\x1C9', '\x1C8', '\x3', '\x2', '\x2', '\x2', - '\x1CA', '\x1CB', '\x3', '\x2', '\x2', '\x2', '\x1CB', '\x1C9', '\x3', - '\x2', '\x2', '\x2', '\x1CB', '\x1CC', '\x3', '\x2', '\x2', '\x2', '\x1CC', - '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1C4', '\x3', '\x2', '\x2', - '\x2', '\x1CD', '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1E4', - '\x3', '\x2', '\x2', '\x2', '\x1CF', '\x1D1', '\t', '\x3', '\x2', '\x2', - '\x1D0', '\x1CF', '\x3', '\x2', '\x2', '\x2', '\x1D0', '\x1D1', '\x3', - '\x2', '\x2', '\x2', '\x1D1', '\x1D2', '\x3', '\x2', '\x2', '\x2', '\x1D2', - '\x1D4', '\a', '\x30', '\x2', '\x2', '\x1D3', '\x1D5', '\x5', '\x8D', - 'G', '\x2', '\x1D4', '\x1D3', '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D6', - '\x3', '\x2', '\x2', '\x2', '\x1D6', '\x1D4', '\x3', '\x2', '\x2', '\x2', - '\x1D6', '\x1D7', '\x3', '\x2', '\x2', '\x2', '\x1D7', '\x1E1', '\x3', - '\x2', '\x2', '\x2', '\x1D8', '\x1DA', '\x5', '\x97', 'L', '\x2', '\x1D9', - '\x1DB', '\t', '\x3', '\x2', '\x2', '\x1DA', '\x1D9', '\x3', '\x2', '\x2', - '\x2', '\x1DA', '\x1DB', '\x3', '\x2', '\x2', '\x2', '\x1DB', '\x1DD', - '\x3', '\x2', '\x2', '\x2', '\x1DC', '\x1DE', '\x5', '\x8D', 'G', '\x2', - '\x1DD', '\x1DC', '\x3', '\x2', '\x2', '\x2', '\x1DE', '\x1DF', '\x3', - '\x2', '\x2', '\x2', '\x1DF', '\x1DD', '\x3', '\x2', '\x2', '\x2', '\x1DF', - '\x1E0', '\x3', '\x2', '\x2', '\x2', '\x1E0', '\x1E2', '\x3', '\x2', '\x2', - '\x2', '\x1E1', '\x1D8', '\x3', '\x2', '\x2', '\x2', '\x1E1', '\x1E2', - '\x3', '\x2', '\x2', '\x2', '\x1E2', '\x1E4', '\x3', '\x2', '\x2', '\x2', - '\x1E3', '\x1B4', '\x3', '\x2', '\x2', '\x2', '\x1E3', '\x1D0', '\x3', - '\x2', '\x2', '\x2', '\x1E4', '|', '\x3', '\x2', '\x2', '\x2', '\x1E5', - '\x1EA', '\a', '$', '\x2', '\x2', '\x1E6', '\x1E9', '\x5', '\x7F', '@', - '\x2', '\x1E7', '\x1E9', '\x5', '\x87', '\x44', '\x2', '\x1E8', '\x1E6', - '\x3', '\x2', '\x2', '\x2', '\x1E8', '\x1E7', '\x3', '\x2', '\x2', '\x2', - '\x1E9', '\x1EC', '\x3', '\x2', '\x2', '\x2', '\x1EA', '\x1E8', '\x3', - '\x2', '\x2', '\x2', '\x1EA', '\x1EB', '\x3', '\x2', '\x2', '\x2', '\x1EB', - '\x1ED', '\x3', '\x2', '\x2', '\x2', '\x1EC', '\x1EA', '\x3', '\x2', '\x2', - '\x2', '\x1ED', '\x1F8', '\a', '$', '\x2', '\x2', '\x1EE', '\x1F3', '\a', - ')', '\x2', '\x2', '\x1EF', '\x1F2', '\x5', '\x7F', '@', '\x2', '\x1F0', - '\x1F2', '\x5', '\x85', '\x43', '\x2', '\x1F1', '\x1EF', '\x3', '\x2', - '\x2', '\x2', '\x1F1', '\x1F0', '\x3', '\x2', '\x2', '\x2', '\x1F2', '\x1F5', - '\x3', '\x2', '\x2', '\x2', '\x1F3', '\x1F1', '\x3', '\x2', '\x2', '\x2', - '\x1F3', '\x1F4', '\x3', '\x2', '\x2', '\x2', '\x1F4', '\x1F6', '\x3', - '\x2', '\x2', '\x2', '\x1F5', '\x1F3', '\x3', '\x2', '\x2', '\x2', '\x1F6', - '\x1F8', '\a', ')', '\x2', '\x2', '\x1F7', '\x1E5', '\x3', '\x2', '\x2', - '\x2', '\x1F7', '\x1EE', '\x3', '\x2', '\x2', '\x2', '\x1F8', '~', '\x3', - '\x2', '\x2', '\x2', '\x1F9', '\x1FC', '\a', '^', '\x2', '\x2', '\x1FA', - '\x1FD', '\t', '\x4', '\x2', '\x2', '\x1FB', '\x1FD', '\x5', '\x81', '\x41', - '\x2', '\x1FC', '\x1FA', '\x3', '\x2', '\x2', '\x2', '\x1FC', '\x1FB', - '\x3', '\x2', '\x2', '\x2', '\x1FD', '\x80', '\x3', '\x2', '\x2', '\x2', - '\x1FE', '\x1FF', '\a', 'w', '\x2', '\x2', '\x1FF', '\x200', '\x5', '\x83', - '\x42', '\x2', '\x200', '\x201', '\x5', '\x83', '\x42', '\x2', '\x201', - '\x202', '\x5', '\x83', '\x42', '\x2', '\x202', '\x203', '\x5', '\x83', - '\x42', '\x2', '\x203', '\x82', '\x3', '\x2', '\x2', '\x2', '\x204', '\x205', - '\t', '\x5', '\x2', '\x2', '\x205', '\x84', '\x3', '\x2', '\x2', '\x2', - '\x206', '\x207', '\n', '\x6', '\x2', '\x2', '\x207', '\x86', '\x3', '\x2', - '\x2', '\x2', '\x208', '\x209', '\n', '\a', '\x2', '\x2', '\x209', '\x88', - '\x3', '\x2', '\x2', '\x2', '\x20A', '\x214', '\x3', '\x2', '\x2', '\x2', - '\x20B', '\x210', '\t', '\b', '\x2', '\x2', '\x20C', '\x20F', '\t', '\b', - '\x2', '\x2', '\x20D', '\x20F', '\x5', '\x8D', 'G', '\x2', '\x20E', '\x20C', - '\x3', '\x2', '\x2', '\x2', '\x20E', '\x20D', '\x3', '\x2', '\x2', '\x2', - '\x20F', '\x212', '\x3', '\x2', '\x2', '\x2', '\x210', '\x20E', '\x3', - '\x2', '\x2', '\x2', '\x210', '\x211', '\x3', '\x2', '\x2', '\x2', '\x211', - '\x214', '\x3', '\x2', '\x2', '\x2', '\x212', '\x210', '\x3', '\x2', '\x2', - '\x2', '\x213', '\x20A', '\x3', '\x2', '\x2', '\x2', '\x213', '\x20B', - '\x3', '\x2', '\x2', '\x2', '\x214', '\x8A', '\x3', '\x2', '\x2', '\x2', - '\x215', '\x216', '\a', '\x42', '\x2', '\x2', '\x216', '\x217', '\x5', - '\x89', '\x45', '\x2', '\x217', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x218', - '\x219', '\t', '\t', '\x2', '\x2', '\x219', '\x8E', '\x3', '\x2', '\x2', - '\x2', '\x21A', '\x21B', '\t', '\n', '\x2', '\x2', '\x21B', '\x90', '\x3', - '\x2', '\x2', '\x2', '\x21C', '\x21D', '\t', '\v', '\x2', '\x2', '\x21D', - '\x92', '\x3', '\x2', '\x2', '\x2', '\x21E', '\x21F', '\t', '\f', '\x2', - '\x2', '\x21F', '\x94', '\x3', '\x2', '\x2', '\x2', '\x220', '\x221', - '\t', '\r', '\x2', '\x2', '\x221', '\x96', '\x3', '\x2', '\x2', '\x2', - '\x222', '\x223', '\t', '\xE', '\x2', '\x2', '\x223', '\x98', '\x3', '\x2', - '\x2', '\x2', '\x224', '\x225', '\t', '\xF', '\x2', '\x2', '\x225', '\x9A', - '\x3', '\x2', '\x2', '\x2', '\x226', '\x227', '\t', '\x10', '\x2', '\x2', - '\x227', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x228', '\x229', '\t', '\x11', - '\x2', '\x2', '\x229', '\x9E', '\x3', '\x2', '\x2', '\x2', '\x22A', '\x22B', - '\t', '\x12', '\x2', '\x2', '\x22B', '\xA0', '\x3', '\x2', '\x2', '\x2', - '\x22C', '\x22D', '\t', '\x13', '\x2', '\x2', '\x22D', '\xA2', '\x3', - '\x2', '\x2', '\x2', '\x22E', '\x22F', '\t', '\x14', '\x2', '\x2', '\x22F', - '\xA4', '\x3', '\x2', '\x2', '\x2', '\x230', '\x231', '\t', '\x15', '\x2', - '\x2', '\x231', '\xA6', '\x3', '\x2', '\x2', '\x2', '\x232', '\x233', - '\t', '\x16', '\x2', '\x2', '\x233', '\xA8', '\x3', '\x2', '\x2', '\x2', - '\x234', '\x235', '\t', '\x17', '\x2', '\x2', '\x235', '\xAA', '\x3', - '\x2', '\x2', '\x2', '\x236', '\x237', '\t', '\x18', '\x2', '\x2', '\x237', - '\xAC', '\x3', '\x2', '\x2', '\x2', '\x238', '\x239', '\t', '\x19', '\x2', - '\x2', '\x239', '\xAE', '\x3', '\x2', '\x2', '\x2', '\x23A', '\x23B', - '\t', '\x1A', '\x2', '\x2', '\x23B', '\xB0', '\x3', '\x2', '\x2', '\x2', - '\x23C', '\x23D', '\t', '\x1B', '\x2', '\x2', '\x23D', '\xB2', '\x3', - '\x2', '\x2', '\x2', '\x23E', '\x23F', '\t', '\x1C', '\x2', '\x2', '\x23F', - '\xB4', '\x3', '\x2', '\x2', '\x2', '\x240', '\x241', '\t', '\x1D', '\x2', - '\x2', '\x241', '\xB6', '\x3', '\x2', '\x2', '\x2', '\x242', '\x243', - '\t', '\x1E', '\x2', '\x2', '\x243', '\xB8', '\x3', '\x2', '\x2', '\x2', - '\x244', '\x245', '\t', '\x1F', '\x2', '\x2', '\x245', '\xBA', '\x3', - '\x2', '\x2', '\x2', '\x246', '\x247', '\t', ' ', '\x2', '\x2', '\x247', - '\xBC', '\x3', '\x2', '\x2', '\x2', '\x248', '\x249', '\t', '!', '\x2', - '\x2', '\x249', '\xBE', '\x3', '\x2', '\x2', '\x2', '\x24A', '\x24B', - '\t', '\"', '\x2', '\x2', '\x24B', '\xC0', '\x3', '\x2', '\x2', '\x2', - '\x24C', '\x24D', '\t', '#', '\x2', '\x2', '\x24D', '\xC2', '\x3', '\x2', - '\x2', '\x2', '\x1A', '\x2', '\x1AF', '\x1B4', '\x1B9', '\x1BF', '\x1C2', - '\x1C6', '\x1CB', '\x1CD', '\x1D0', '\x1D6', '\x1DA', '\x1DF', '\x1E1', - '\x1E3', '\x1E8', '\x1EA', '\x1F1', '\x1F3', '\x1F7', '\x1FC', '\x20E', - '\x210', '\x213', '\x3', '\b', '\x2', '\x2', + '\x4', '\x62', '\t', '\x62', '\x4', '\x63', '\t', '\x63', '\x3', '\x2', + '\x3', '\x2', '\x3', '\x3', '\x3', '\x3', '\x3', '\x4', '\x3', '\x4', + '\x3', '\x5', '\x3', '\x5', '\x3', '\x6', '\x3', '\x6', '\x3', '\a', '\x3', + '\a', '\x3', '\b', '\x3', '\b', '\x3', '\t', '\x3', '\t', '\x3', '\n', + '\x3', '\n', '\x3', '\v', '\x3', '\v', '\x3', '\v', '\x3', '\f', '\x3', + '\f', '\x3', '\r', '\x3', '\r', '\x3', '\xE', '\x3', '\xE', '\x3', '\xF', + '\x3', '\xF', '\x3', '\x10', '\x3', '\x10', '\x3', '\x11', '\x3', '\x11', + '\x3', '\x12', '\x3', '\x12', '\x3', '\x12', '\x3', '\x13', '\x3', '\x13', + '\x3', '\x13', '\x3', '\x14', '\x3', '\x14', '\x3', '\x15', '\x3', '\x15', + '\x3', '\x15', '\x3', '\x16', '\x3', '\x16', '\x3', '\x17', '\x3', '\x17', + '\x3', '\x18', '\x3', '\x18', '\x3', '\x19', '\x3', '\x19', '\x3', '\x19', + '\x3', '\x1A', '\x3', '\x1A', '\x3', '\x1B', '\x3', '\x1B', '\x3', '\x1C', + '\x3', '\x1C', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', '\x3', '\x1D', + '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1E', '\x3', '\x1F', + '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', '\x3', '\x1F', + '\x3', ' ', '\x3', ' ', '\x3', ' ', '\x3', '!', '\x3', '!', '\x3', '!', + '\x3', '!', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', + '\"', '\x3', '\"', '\x3', '\"', '\x3', '\"', '\x3', '#', '\x3', '#', '\x3', + '#', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', '$', '\x3', + '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', '%', '\x3', + '%', '\x3', '%', '\x3', '%', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', + '&', '\x3', '&', '\x3', '&', '\x3', '&', '\x3', '\'', '\x3', '\'', '\x3', + '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '\'', '\x3', '(', + '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', ')', + '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', '*', + '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '*', '\x3', '+', '\x3', '+', + '\x3', '+', '\x3', '+', '\x3', '+', '\x3', '+', '\x3', ',', '\x3', ',', + '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', '\x3', '-', + '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '.', '\x3', '/', + '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '/', '\x3', '\x30', '\x3', + '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x30', '\x3', '\x31', '\x3', + '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', '\x31', '\x3', + '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x32', '\x3', '\x33', '\x3', + '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x33', '\x3', '\x34', '\x3', + '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', '\x34', '\x3', + '\x34', '\x3', '\x35', '\x3', '\x35', '\x3', '\x35', '\x3', '\x36', '\x3', + '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', '\x36', '\x3', + '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', '\x37', '\x3', + '\x37', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', + '\x38', '\x3', '\x38', '\x3', '\x38', '\x3', '\x39', '\x3', '\x39', '\x3', + '\x39', '\x3', '\x39', '\x3', ':', '\x3', ':', '\x3', ':', '\x3', ':', + '\x3', ':', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', ';', '\x3', '<', + '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '<', + '\x3', '<', '\x3', '<', '\x3', '<', '\x3', '=', '\x3', '=', '\x3', '=', + '\x3', '=', '\x3', '=', '\x3', '=', '\x3', '>', '\x3', '>', '\x3', '>', + '\x3', '>', '\x3', '>', '\x3', '>', '\x3', '?', '\x6', '?', '\x1BD', '\n', + '?', '\r', '?', '\xE', '?', '\x1BE', '\x3', '?', '\x3', '?', '\x3', '@', + '\x5', '@', '\x1C4', '\n', '@', '\x3', '@', '\x6', '@', '\x1C7', '\n', + '@', '\r', '@', '\xE', '@', '\x1C8', '\x3', '@', '\x3', '@', '\a', '@', + '\x1CD', '\n', '@', '\f', '@', '\xE', '@', '\x1D0', '\v', '@', '\x5', + '@', '\x1D2', '\n', '@', '\x3', '@', '\x3', '@', '\x5', '@', '\x1D6', + '\n', '@', '\x3', '@', '\x6', '@', '\x1D9', '\n', '@', '\r', '@', '\xE', + '@', '\x1DA', '\x5', '@', '\x1DD', '\n', '@', '\x3', '@', '\x5', '@', + '\x1E0', '\n', '@', '\x3', '@', '\x3', '@', '\x6', '@', '\x1E4', '\n', + '@', '\r', '@', '\xE', '@', '\x1E5', '\x3', '@', '\x3', '@', '\x5', '@', + '\x1EA', '\n', '@', '\x3', '@', '\x6', '@', '\x1ED', '\n', '@', '\r', + '@', '\xE', '@', '\x1EE', '\x5', '@', '\x1F1', '\n', '@', '\x5', '@', + '\x1F3', '\n', '@', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\a', + '\x41', '\x1F8', '\n', '\x41', '\f', '\x41', '\xE', '\x41', '\x1FB', '\v', + '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\x3', '\x41', '\a', + '\x41', '\x201', '\n', '\x41', '\f', '\x41', '\xE', '\x41', '\x204', '\v', + '\x41', '\x3', '\x41', '\x5', '\x41', '\x207', '\n', '\x41', '\x3', '\x42', + '\x3', '\x42', '\x3', '\x42', '\x5', '\x42', '\x20C', '\n', '\x42', '\x3', + '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', '\x43', '\x3', + '\x43', '\x3', '\x44', '\x3', '\x44', '\x3', '\x45', '\x3', '\x45', '\x3', + '\x46', '\x3', '\x46', '\x3', 'G', '\x3', 'G', '\x3', 'G', '\x3', 'G', + '\a', 'G', '\x21E', '\n', 'G', '\f', 'G', '\xE', 'G', '\x221', '\v', 'G', + '\x5', 'G', '\x223', '\n', 'G', '\x3', 'H', '\x3', 'H', '\x3', 'H', '\x3', + 'I', '\x3', 'I', '\x3', 'J', '\x3', 'J', '\x3', 'K', '\x3', 'K', '\x3', + 'L', '\x3', 'L', '\x3', 'M', '\x3', 'M', '\x3', 'N', '\x3', 'N', '\x3', + 'O', '\x3', 'O', '\x3', 'P', '\x3', 'P', '\x3', 'Q', '\x3', 'Q', '\x3', + 'R', '\x3', 'R', '\x3', 'S', '\x3', 'S', '\x3', 'T', '\x3', 'T', '\x3', + 'U', '\x3', 'U', '\x3', 'V', '\x3', 'V', '\x3', 'W', '\x3', 'W', '\x3', + 'X', '\x3', 'X', '\x3', 'Y', '\x3', 'Y', '\x3', 'Z', '\x3', 'Z', '\x3', + '[', '\x3', '[', '\x3', '\\', '\x3', '\\', '\x3', ']', '\x3', ']', '\x3', + '^', '\x3', '^', '\x3', '_', '\x3', '_', '\x3', '`', '\x3', '`', '\x3', + '\x61', '\x3', '\x61', '\x3', '\x62', '\x3', '\x62', '\x3', '\x63', '\x3', + '\x63', '\x2', '\x2', '\x64', '\x3', '\x3', '\x5', '\x4', '\a', '\x5', + '\t', '\x6', '\v', '\a', '\r', '\b', '\xF', '\t', '\x11', '\n', '\x13', + '\v', '\x15', '\f', '\x17', '\r', '\x19', '\xE', '\x1B', '\xF', '\x1D', + '\x10', '\x1F', '\x11', '!', '\x12', '#', '\x13', '%', '\x14', '\'', '\x15', + ')', '\x16', '+', '\x17', '-', '\x18', '/', '\x19', '\x31', '\x1A', '\x33', + '\x1B', '\x35', '\x1C', '\x37', '\x1D', '\x39', '\x1E', ';', '\x1F', '=', + ' ', '?', '!', '\x41', '\"', '\x43', '#', '\x45', '$', 'G', '%', 'I', + '&', 'K', '\'', 'M', '(', 'O', ')', 'Q', '*', 'S', '+', 'U', ',', 'W', + '-', 'Y', '.', '[', '/', ']', '\x30', '_', '\x31', '\x61', '\x32', '\x63', + '\x33', '\x65', '\x34', 'g', '\x35', 'i', '\x36', 'k', '\x37', 'm', '\x38', + 'o', '\x39', 'q', ':', 's', ';', 'u', '<', 'w', '=', 'y', '>', '{', '?', + '}', '@', '\x7F', '\x41', '\x81', '\x42', '\x83', '\x2', '\x85', '\x2', + '\x87', '\x2', '\x89', '\x2', '\x8B', '\x2', '\x8D', '\x43', '\x8F', '\x44', + '\x91', '\x2', '\x93', '\x2', '\x95', '\x2', '\x97', '\x2', '\x99', '\x2', + '\x9B', '\x2', '\x9D', '\x2', '\x9F', '\x2', '\xA1', '\x2', '\xA3', '\x2', + '\xA5', '\x2', '\xA7', '\x2', '\xA9', '\x2', '\xAB', '\x2', '\xAD', '\x2', + '\xAF', '\x2', '\xB1', '\x2', '\xB3', '\x2', '\xB5', '\x2', '\xB7', '\x2', + '\xB9', '\x2', '\xBB', '\x2', '\xBD', '\x2', '\xBF', '\x2', '\xC1', '\x2', + '\xC3', '\x2', '\xC5', '\x2', '\x3', '\x2', '$', '\x5', '\x2', '\v', '\f', + '\xF', '\xF', '\"', '\"', '\x4', '\x2', '-', '-', '/', '/', '\n', '\x2', + '$', '$', '\x31', '\x31', '^', '^', '\x64', '\x64', 'h', 'h', 'p', 'p', + 't', 't', 'v', 'v', '\x5', '\x2', '\x32', ';', '\x43', 'H', '\x63', 'h', + '\x5', '\x2', '\x2', '!', ')', ')', '^', '^', '\x5', '\x2', '\x2', '!', + '$', '$', '^', '^', '\x5', '\x2', '\x43', '\\', '\x61', '\x61', '\x63', + '|', '\x3', '\x2', '\x32', ';', '\x4', '\x2', '\x43', '\x43', '\x63', + '\x63', '\x4', '\x2', '\x44', '\x44', '\x64', '\x64', '\x4', '\x2', '\x45', + '\x45', '\x65', '\x65', '\x4', '\x2', '\x46', '\x46', '\x66', '\x66', + '\x4', '\x2', 'G', 'G', 'g', 'g', '\x4', '\x2', 'H', 'H', 'h', 'h', '\x4', + '\x2', 'I', 'I', 'i', 'i', '\x4', '\x2', 'J', 'J', 'j', 'j', '\x4', '\x2', + 'K', 'K', 'k', 'k', '\x4', '\x2', 'L', 'L', 'l', 'l', '\x4', '\x2', 'M', + 'M', 'm', 'm', '\x4', '\x2', 'N', 'N', 'n', 'n', '\x4', '\x2', 'O', 'O', + 'o', 'o', '\x4', '\x2', 'P', 'P', 'p', 'p', '\x4', '\x2', 'Q', 'Q', 'q', + 'q', '\x4', '\x2', 'R', 'R', 'r', 'r', '\x4', '\x2', 'S', 'S', 's', 's', + '\x4', '\x2', 'T', 'T', 't', 't', '\x4', '\x2', 'U', 'U', 'u', 'u', '\x4', + '\x2', 'V', 'V', 'v', 'v', '\x4', '\x2', 'W', 'W', 'w', 'w', '\x4', '\x2', + 'X', 'X', 'x', 'x', '\x4', '\x2', 'Y', 'Y', 'y', 'y', '\x4', '\x2', 'Z', + 'Z', 'z', 'z', '\x4', '\x2', '[', '[', '{', '{', '\x4', '\x2', '\\', '\\', + '|', '|', '\x2', '\x253', '\x2', '\x3', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x5', '\x3', '\x2', '\x2', '\x2', '\x2', '\a', '\x3', '\x2', '\x2', '\x2', + '\x2', '\t', '\x3', '\x2', '\x2', '\x2', '\x2', '\v', '\x3', '\x2', '\x2', + '\x2', '\x2', '\r', '\x3', '\x2', '\x2', '\x2', '\x2', '\xF', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x11', '\x3', '\x2', '\x2', '\x2', '\x2', '\x13', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x15', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x17', '\x3', '\x2', '\x2', '\x2', '\x2', '\x19', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x1B', '\x3', '\x2', '\x2', '\x2', '\x2', '\x1D', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x1F', '\x3', '\x2', '\x2', '\x2', + '\x2', '!', '\x3', '\x2', '\x2', '\x2', '\x2', '#', '\x3', '\x2', '\x2', + '\x2', '\x2', '%', '\x3', '\x2', '\x2', '\x2', '\x2', '\'', '\x3', '\x2', + '\x2', '\x2', '\x2', ')', '\x3', '\x2', '\x2', '\x2', '\x2', '+', '\x3', + '\x2', '\x2', '\x2', '\x2', '-', '\x3', '\x2', '\x2', '\x2', '\x2', '/', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x31', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x33', '\x3', '\x2', '\x2', '\x2', '\x2', '\x35', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x37', '\x3', '\x2', '\x2', '\x2', '\x2', '\x39', + '\x3', '\x2', '\x2', '\x2', '\x2', ';', '\x3', '\x2', '\x2', '\x2', '\x2', + '=', '\x3', '\x2', '\x2', '\x2', '\x2', '?', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x41', '\x3', '\x2', '\x2', '\x2', '\x2', '\x43', '\x3', '\x2', + '\x2', '\x2', '\x2', '\x45', '\x3', '\x2', '\x2', '\x2', '\x2', 'G', '\x3', + '\x2', '\x2', '\x2', '\x2', 'I', '\x3', '\x2', '\x2', '\x2', '\x2', 'K', + '\x3', '\x2', '\x2', '\x2', '\x2', 'M', '\x3', '\x2', '\x2', '\x2', '\x2', + 'O', '\x3', '\x2', '\x2', '\x2', '\x2', 'Q', '\x3', '\x2', '\x2', '\x2', + '\x2', 'S', '\x3', '\x2', '\x2', '\x2', '\x2', 'U', '\x3', '\x2', '\x2', + '\x2', '\x2', 'W', '\x3', '\x2', '\x2', '\x2', '\x2', 'Y', '\x3', '\x2', + '\x2', '\x2', '\x2', '[', '\x3', '\x2', '\x2', '\x2', '\x2', ']', '\x3', + '\x2', '\x2', '\x2', '\x2', '_', '\x3', '\x2', '\x2', '\x2', '\x2', '\x61', + '\x3', '\x2', '\x2', '\x2', '\x2', '\x63', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x65', '\x3', '\x2', '\x2', '\x2', '\x2', 'g', '\x3', '\x2', '\x2', + '\x2', '\x2', 'i', '\x3', '\x2', '\x2', '\x2', '\x2', 'k', '\x3', '\x2', + '\x2', '\x2', '\x2', 'm', '\x3', '\x2', '\x2', '\x2', '\x2', 'o', '\x3', + '\x2', '\x2', '\x2', '\x2', 'q', '\x3', '\x2', '\x2', '\x2', '\x2', 's', + '\x3', '\x2', '\x2', '\x2', '\x2', 'u', '\x3', '\x2', '\x2', '\x2', '\x2', + 'w', '\x3', '\x2', '\x2', '\x2', '\x2', 'y', '\x3', '\x2', '\x2', '\x2', + '\x2', '{', '\x3', '\x2', '\x2', '\x2', '\x2', '}', '\x3', '\x2', '\x2', + '\x2', '\x2', '\x7F', '\x3', '\x2', '\x2', '\x2', '\x2', '\x81', '\x3', + '\x2', '\x2', '\x2', '\x2', '\x8D', '\x3', '\x2', '\x2', '\x2', '\x2', + '\x8F', '\x3', '\x2', '\x2', '\x2', '\x3', '\xC7', '\x3', '\x2', '\x2', + '\x2', '\x5', '\xC9', '\x3', '\x2', '\x2', '\x2', '\a', '\xCB', '\x3', + '\x2', '\x2', '\x2', '\t', '\xCD', '\x3', '\x2', '\x2', '\x2', '\v', '\xCF', + '\x3', '\x2', '\x2', '\x2', '\r', '\xD1', '\x3', '\x2', '\x2', '\x2', + '\xF', '\xD3', '\x3', '\x2', '\x2', '\x2', '\x11', '\xD5', '\x3', '\x2', + '\x2', '\x2', '\x13', '\xD7', '\x3', '\x2', '\x2', '\x2', '\x15', '\xD9', + '\x3', '\x2', '\x2', '\x2', '\x17', '\xDC', '\x3', '\x2', '\x2', '\x2', + '\x19', '\xDE', '\x3', '\x2', '\x2', '\x2', '\x1B', '\xE0', '\x3', '\x2', + '\x2', '\x2', '\x1D', '\xE2', '\x3', '\x2', '\x2', '\x2', '\x1F', '\xE4', + '\x3', '\x2', '\x2', '\x2', '!', '\xE6', '\x3', '\x2', '\x2', '\x2', '#', + '\xE8', '\x3', '\x2', '\x2', '\x2', '%', '\xEB', '\x3', '\x2', '\x2', + '\x2', '\'', '\xEE', '\x3', '\x2', '\x2', '\x2', ')', '\xF0', '\x3', '\x2', + '\x2', '\x2', '+', '\xF3', '\x3', '\x2', '\x2', '\x2', '-', '\xF5', '\x3', + '\x2', '\x2', '\x2', '/', '\xF7', '\x3', '\x2', '\x2', '\x2', '\x31', + '\xF9', '\x3', '\x2', '\x2', '\x2', '\x33', '\xFC', '\x3', '\x2', '\x2', + '\x2', '\x35', '\xFE', '\x3', '\x2', '\x2', '\x2', '\x37', '\x100', '\x3', + '\x2', '\x2', '\x2', '\x39', '\x102', '\x3', '\x2', '\x2', '\x2', ';', + '\x106', '\x3', '\x2', '\x2', '\x2', '=', '\x10A', '\x3', '\x2', '\x2', + '\x2', '?', '\x110', '\x3', '\x2', '\x2', '\x2', '\x41', '\x113', '\x3', + '\x2', '\x2', '\x2', '\x43', '\x117', '\x3', '\x2', '\x2', '\x2', '\x45', + '\x11F', '\x3', '\x2', '\x2', '\x2', 'G', '\x122', '\x3', '\x2', '\x2', + '\x2', 'I', '\x127', '\x3', '\x2', '\x2', '\x2', 'K', '\x130', '\x3', + '\x2', '\x2', '\x2', 'M', '\x137', '\x3', '\x2', '\x2', '\x2', 'O', '\x13E', + '\x3', '\x2', '\x2', '\x2', 'Q', '\x144', '\x3', '\x2', '\x2', '\x2', + 'S', '\x14A', '\x3', '\x2', '\x2', '\x2', 'U', '\x14F', '\x3', '\x2', + '\x2', '\x2', 'W', '\x155', '\x3', '\x2', '\x2', '\x2', 'Y', '\x158', + '\x3', '\x2', '\x2', '\x2', '[', '\x15D', '\x3', '\x2', '\x2', '\x2', + ']', '\x162', '\x3', '\x2', '\x2', '\x2', '_', '\x167', '\x3', '\x2', + '\x2', '\x2', '\x61', '\x16C', '\x3', '\x2', '\x2', '\x2', '\x63', '\x172', + '\x3', '\x2', '\x2', '\x2', '\x65', '\x176', '\x3', '\x2', '\x2', '\x2', + 'g', '\x17B', '\x3', '\x2', '\x2', '\x2', 'i', '\x182', '\x3', '\x2', + '\x2', '\x2', 'k', '\x185', '\x3', '\x2', '\x2', '\x2', 'm', '\x18B', + '\x3', '\x2', '\x2', '\x2', 'o', '\x191', '\x3', '\x2', '\x2', '\x2', + 'q', '\x198', '\x3', '\x2', '\x2', '\x2', 's', '\x19C', '\x3', '\x2', + '\x2', '\x2', 'u', '\x1A1', '\x3', '\x2', '\x2', '\x2', 'w', '\x1A5', + '\x3', '\x2', '\x2', '\x2', 'y', '\x1AF', '\x3', '\x2', '\x2', '\x2', + '{', '\x1B5', '\x3', '\x2', '\x2', '\x2', '}', '\x1BC', '\x3', '\x2', + '\x2', '\x2', '\x7F', '\x1F2', '\x3', '\x2', '\x2', '\x2', '\x81', '\x206', + '\x3', '\x2', '\x2', '\x2', '\x83', '\x208', '\x3', '\x2', '\x2', '\x2', + '\x85', '\x20D', '\x3', '\x2', '\x2', '\x2', '\x87', '\x213', '\x3', '\x2', + '\x2', '\x2', '\x89', '\x215', '\x3', '\x2', '\x2', '\x2', '\x8B', '\x217', + '\x3', '\x2', '\x2', '\x2', '\x8D', '\x222', '\x3', '\x2', '\x2', '\x2', + '\x8F', '\x224', '\x3', '\x2', '\x2', '\x2', '\x91', '\x227', '\x3', '\x2', + '\x2', '\x2', '\x93', '\x229', '\x3', '\x2', '\x2', '\x2', '\x95', '\x22B', + '\x3', '\x2', '\x2', '\x2', '\x97', '\x22D', '\x3', '\x2', '\x2', '\x2', + '\x99', '\x22F', '\x3', '\x2', '\x2', '\x2', '\x9B', '\x231', '\x3', '\x2', + '\x2', '\x2', '\x9D', '\x233', '\x3', '\x2', '\x2', '\x2', '\x9F', '\x235', + '\x3', '\x2', '\x2', '\x2', '\xA1', '\x237', '\x3', '\x2', '\x2', '\x2', + '\xA3', '\x239', '\x3', '\x2', '\x2', '\x2', '\xA5', '\x23B', '\x3', '\x2', + '\x2', '\x2', '\xA7', '\x23D', '\x3', '\x2', '\x2', '\x2', '\xA9', '\x23F', + '\x3', '\x2', '\x2', '\x2', '\xAB', '\x241', '\x3', '\x2', '\x2', '\x2', + '\xAD', '\x243', '\x3', '\x2', '\x2', '\x2', '\xAF', '\x245', '\x3', '\x2', + '\x2', '\x2', '\xB1', '\x247', '\x3', '\x2', '\x2', '\x2', '\xB3', '\x249', + '\x3', '\x2', '\x2', '\x2', '\xB5', '\x24B', '\x3', '\x2', '\x2', '\x2', + '\xB7', '\x24D', '\x3', '\x2', '\x2', '\x2', '\xB9', '\x24F', '\x3', '\x2', + '\x2', '\x2', '\xBB', '\x251', '\x3', '\x2', '\x2', '\x2', '\xBD', '\x253', + '\x3', '\x2', '\x2', '\x2', '\xBF', '\x255', '\x3', '\x2', '\x2', '\x2', + '\xC1', '\x257', '\x3', '\x2', '\x2', '\x2', '\xC3', '\x259', '\x3', '\x2', + '\x2', '\x2', '\xC5', '\x25B', '\x3', '\x2', '\x2', '\x2', '\xC7', '\xC8', + '\a', ',', '\x2', '\x2', '\xC8', '\x4', '\x3', '\x2', '\x2', '\x2', '\xC9', + '\xCA', '\a', '.', '\x2', '\x2', '\xCA', '\x6', '\x3', '\x2', '\x2', '\x2', + '\xCB', '\xCC', '\a', '*', '\x2', '\x2', '\xCC', '\b', '\x3', '\x2', '\x2', + '\x2', '\xCD', '\xCE', '\a', '+', '\x2', '\x2', '\xCE', '\n', '\x3', '\x2', + '\x2', '\x2', '\xCF', '\xD0', '\a', '\x30', '\x2', '\x2', '\xD0', '\f', + '\x3', '\x2', '\x2', '\x2', '\xD1', '\xD2', '\a', ']', '\x2', '\x2', '\xD2', + '\xE', '\x3', '\x2', '\x2', '\x2', '\xD3', '\xD4', '\a', '_', '\x2', '\x2', + '\xD4', '\x10', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD6', '\a', '\x41', + '\x2', '\x2', '\xD6', '\x12', '\x3', '\x2', '\x2', '\x2', '\xD7', '\xD8', + '\a', '<', '\x2', '\x2', '\xD8', '\x14', '\x3', '\x2', '\x2', '\x2', '\xD9', + '\xDA', '\a', '\x41', '\x2', '\x2', '\xDA', '\xDB', '\a', '\x41', '\x2', + '\x2', '\xDB', '\x16', '\x3', '\x2', '\x2', '\x2', '\xDC', '\xDD', '\a', + '\x31', '\x2', '\x2', '\xDD', '\x18', '\x3', '\x2', '\x2', '\x2', '\xDE', + '\xDF', '\a', '\'', '\x2', '\x2', '\xDF', '\x1A', '\x3', '\x2', '\x2', + '\x2', '\xE0', '\xE1', '\a', '-', '\x2', '\x2', '\xE1', '\x1C', '\x3', + '\x2', '\x2', '\x2', '\xE2', '\xE3', '\a', '/', '\x2', '\x2', '\xE3', + '\x1E', '\x3', '\x2', '\x2', '\x2', '\xE4', '\xE5', '\a', '>', '\x2', + '\x2', '\xE5', ' ', '\x3', '\x2', '\x2', '\x2', '\xE6', '\xE7', '\a', + '@', '\x2', '\x2', '\xE7', '\"', '\x3', '\x2', '\x2', '\x2', '\xE8', '\xE9', + '\a', '@', '\x2', '\x2', '\xE9', '\xEA', '\a', '?', '\x2', '\x2', '\xEA', + '$', '\x3', '\x2', '\x2', '\x2', '\xEB', '\xEC', '\a', '>', '\x2', '\x2', + '\xEC', '\xED', '\a', '?', '\x2', '\x2', '\xED', '&', '\x3', '\x2', '\x2', + '\x2', '\xEE', '\xEF', '\a', '?', '\x2', '\x2', '\xEF', '(', '\x3', '\x2', + '\x2', '\x2', '\xF0', '\xF1', '\a', '#', '\x2', '\x2', '\xF1', '\xF2', + '\a', '?', '\x2', '\x2', '\xF2', '*', '\x3', '\x2', '\x2', '\x2', '\xF3', + '\xF4', '\a', '(', '\x2', '\x2', '\xF4', ',', '\x3', '\x2', '\x2', '\x2', + '\xF5', '\xF6', '\a', '`', '\x2', '\x2', '\xF6', '.', '\x3', '\x2', '\x2', + '\x2', '\xF7', '\xF8', '\a', '~', '\x2', '\x2', '\xF8', '\x30', '\x3', + '\x2', '\x2', '\x2', '\xF9', '\xFA', '\a', '~', '\x2', '\x2', '\xFA', + '\xFB', '\a', '~', '\x2', '\x2', '\xFB', '\x32', '\x3', '\x2', '\x2', + '\x2', '\xFC', '\xFD', '\a', '\x80', '\x2', '\x2', '\xFD', '\x34', '\x3', + '\x2', '\x2', '\x2', '\xFE', '\xFF', '\a', '}', '\x2', '\x2', '\xFF', + '\x36', '\x3', '\x2', '\x2', '\x2', '\x100', '\x101', '\a', '\x7F', '\x2', + '\x2', '\x101', '\x38', '\x3', '\x2', '\x2', '\x2', '\x102', '\x103', + '\x5', '\x93', 'J', '\x2', '\x103', '\x104', '\x5', '\xA9', 'U', '\x2', + '\x104', '\x105', '\x5', '\xA9', 'U', '\x2', '\x105', ':', '\x3', '\x2', + '\x2', '\x2', '\x106', '\x107', '\x5', '\x93', 'J', '\x2', '\x107', '\x108', + '\x5', '\xAD', 'W', '\x2', '\x108', '\x109', '\x5', '\x99', 'M', '\x2', + '\x109', '<', '\x3', '\x2', '\x2', '\x2', '\x10A', '\x10B', '\x5', '\x93', + 'J', '\x2', '\x10B', '\x10C', '\x5', '\xB5', '[', '\x2', '\x10C', '\x10D', + '\x5', '\xB5', '[', '\x2', '\x10D', '\x10E', '\x5', '\x93', 'J', '\x2', + '\x10E', '\x10F', '\x5', '\xC3', '\x62', '\x2', '\x10F', '>', '\x3', '\x2', + '\x2', '\x2', '\x110', '\x111', '\x5', '\x93', 'J', '\x2', '\x111', '\x112', + '\x5', '\xB7', '\\', '\x2', '\x112', '@', '\x3', '\x2', '\x2', '\x2', + '\x113', '\x114', '\x5', '\x93', 'J', '\x2', '\x114', '\x115', '\x5', + '\xB7', '\\', '\x2', '\x115', '\x116', '\x5', '\x97', 'L', '\x2', '\x116', + '\x42', '\x3', '\x2', '\x2', '\x2', '\x117', '\x118', '\x5', '\x95', 'K', + '\x2', '\x118', '\x119', '\x5', '\x9B', 'N', '\x2', '\x119', '\x11A', + '\x5', '\xB9', ']', '\x2', '\x11A', '\x11B', '\x5', '\xBF', '`', '\x2', + '\x11B', '\x11C', '\x5', '\x9B', 'N', '\x2', '\x11C', '\x11D', '\x5', + '\x9B', 'N', '\x2', '\x11D', '\x11E', '\x5', '\xAD', 'W', '\x2', '\x11E', + '\x44', '\x3', '\x2', '\x2', '\x2', '\x11F', '\x120', '\x5', '\x95', 'K', + '\x2', '\x120', '\x121', '\x5', '\xC3', '\x62', '\x2', '\x121', '\x46', + '\x3', '\x2', '\x2', '\x2', '\x122', '\x123', '\x5', '\x99', 'M', '\x2', + '\x123', '\x124', '\x5', '\x9B', 'N', '\x2', '\x124', '\x125', '\x5', + '\xB7', '\\', '\x2', '\x125', '\x126', '\x5', '\x97', 'L', '\x2', '\x126', + 'H', '\x3', '\x2', '\x2', '\x2', '\x127', '\x128', '\x5', '\x99', 'M', + '\x2', '\x128', '\x129', '\x5', '\xA3', 'R', '\x2', '\x129', '\x12A', + '\x5', '\xB7', '\\', '\x2', '\x12A', '\x12B', '\x5', '\xB9', ']', '\x2', + '\x12B', '\x12C', '\x5', '\xA3', 'R', '\x2', '\x12C', '\x12D', '\x5', + '\xAD', 'W', '\x2', '\x12D', '\x12E', '\x5', '\x97', 'L', '\x2', '\x12E', + '\x12F', '\x5', '\xB9', ']', '\x2', '\x12F', 'J', '\x3', '\x2', '\x2', + '\x2', '\x130', '\x131', '\x5', '\x9B', 'N', '\x2', '\x131', '\x132', + '\x5', '\xB7', '\\', '\x2', '\x132', '\x133', '\x5', '\x97', 'L', '\x2', + '\x133', '\x134', '\x5', '\x93', 'J', '\x2', '\x134', '\x135', '\x5', + '\xB1', 'Y', '\x2', '\x135', '\x136', '\x5', '\x9B', 'N', '\x2', '\x136', + 'L', '\x3', '\x2', '\x2', '\x2', '\x137', '\x138', '\x5', '\x9B', 'N', + '\x2', '\x138', '\x139', '\x5', '\xC1', '\x61', '\x2', '\x139', '\x13A', + '\x5', '\xA3', 'R', '\x2', '\x13A', '\x13B', '\x5', '\xB7', '\\', '\x2', + '\x13B', '\x13C', '\x5', '\xB9', ']', '\x2', '\x13C', '\x13D', '\x5', + '\xB7', '\\', '\x2', '\x13D', 'N', '\x3', '\x2', '\x2', '\x2', '\x13E', + '\x13F', '\x5', '\x9D', 'O', '\x2', '\x13F', '\x140', '\x5', '\xA3', 'R', + '\x2', '\x140', '\x141', '\x5', '\xB5', '[', '\x2', '\x141', '\x142', + '\x5', '\xB7', '\\', '\x2', '\x142', '\x143', '\x5', '\xB9', ']', '\x2', + '\x143', 'P', '\x3', '\x2', '\x2', '\x2', '\x144', '\x145', '\a', 'h', + '\x2', '\x2', '\x145', '\x146', '\a', '\x63', '\x2', '\x2', '\x146', '\x147', + '\a', 'n', '\x2', '\x2', '\x147', '\x148', '\a', 'u', '\x2', '\x2', '\x148', + '\x149', '\a', 'g', '\x2', '\x2', '\x149', 'R', '\x3', '\x2', '\x2', '\x2', + '\x14A', '\x14B', '\x5', '\x9D', 'O', '\x2', '\x14B', '\x14C', '\x5', + '\xB5', '[', '\x2', '\x14C', '\x14D', '\x5', '\xAF', 'X', '\x2', '\x14D', + '\x14E', '\x5', '\xAB', 'V', '\x2', '\x14E', 'T', '\x3', '\x2', '\x2', + '\x2', '\x14F', '\x150', '\x5', '\x9F', 'P', '\x2', '\x150', '\x151', + '\x5', '\xB5', '[', '\x2', '\x151', '\x152', '\x5', '\xAF', 'X', '\x2', + '\x152', '\x153', '\x5', '\xBB', '^', '\x2', '\x153', '\x154', '\x5', + '\xB1', 'Y', '\x2', '\x154', 'V', '\x3', '\x2', '\x2', '\x2', '\x155', + '\x156', '\x5', '\xA3', 'R', '\x2', '\x156', '\x157', '\x5', '\xAD', 'W', + '\x2', '\x157', 'X', '\x3', '\x2', '\x2', '\x2', '\x158', '\x159', '\x5', + '\xA5', 'S', '\x2', '\x159', '\x15A', '\x5', '\xAF', 'X', '\x2', '\x15A', + '\x15B', '\x5', '\xA3', 'R', '\x2', '\x15B', '\x15C', '\x5', '\xAD', 'W', + '\x2', '\x15C', 'Z', '\x3', '\x2', '\x2', '\x2', '\x15D', '\x15E', '\x5', + '\xA9', 'U', '\x2', '\x15E', '\x15F', '\x5', '\x93', 'J', '\x2', '\x15F', + '\x160', '\x5', '\xB7', '\\', '\x2', '\x160', '\x161', '\x5', '\xB9', + ']', '\x2', '\x161', '\\', '\x3', '\x2', '\x2', '\x2', '\x162', '\x163', + '\x5', '\xA9', 'U', '\x2', '\x163', '\x164', '\x5', '\x9B', 'N', '\x2', + '\x164', '\x165', '\x5', '\x9D', 'O', '\x2', '\x165', '\x166', '\x5', + '\xB9', ']', '\x2', '\x166', '^', '\x3', '\x2', '\x2', '\x2', '\x167', + '\x168', '\x5', '\xA9', 'U', '\x2', '\x168', '\x169', '\x5', '\xA3', 'R', + '\x2', '\x169', '\x16A', '\x5', '\xA7', 'T', '\x2', '\x16A', '\x16B', + '\x5', '\x9B', 'N', '\x2', '\x16B', '`', '\x3', '\x2', '\x2', '\x2', '\x16C', + '\x16D', '\x5', '\xA9', 'U', '\x2', '\x16D', '\x16E', '\x5', '\xA3', 'R', + '\x2', '\x16E', '\x16F', '\x5', '\xAB', 'V', '\x2', '\x16F', '\x170', + '\x5', '\xA3', 'R', '\x2', '\x170', '\x171', '\x5', '\xB9', ']', '\x2', + '\x171', '\x62', '\x3', '\x2', '\x2', '\x2', '\x172', '\x173', '\x5', + '\xAD', 'W', '\x2', '\x173', '\x174', '\x5', '\xAF', 'X', '\x2', '\x174', + '\x175', '\x5', '\xB9', ']', '\x2', '\x175', '\x64', '\x3', '\x2', '\x2', + '\x2', '\x176', '\x177', '\a', 'p', '\x2', '\x2', '\x177', '\x178', '\a', + 'w', '\x2', '\x2', '\x178', '\x179', '\a', 'n', '\x2', '\x2', '\x179', + '\x17A', '\a', 'n', '\x2', '\x2', '\x17A', '\x66', '\x3', '\x2', '\x2', + '\x2', '\x17B', '\x17C', '\x5', '\xAF', 'X', '\x2', '\x17C', '\x17D', + '\x5', '\x9D', 'O', '\x2', '\x17D', '\x17E', '\x5', '\x9D', 'O', '\x2', + '\x17E', '\x17F', '\x5', '\xB7', '\\', '\x2', '\x17F', '\x180', '\x5', + '\x9B', 'N', '\x2', '\x180', '\x181', '\x5', '\xB9', ']', '\x2', '\x181', + 'h', '\x3', '\x2', '\x2', '\x2', '\x182', '\x183', '\x5', '\xAF', 'X', + '\x2', '\x183', '\x184', '\x5', '\xB5', '[', '\x2', '\x184', 'j', '\x3', + '\x2', '\x2', '\x2', '\x185', '\x186', '\x5', '\xAF', 'X', '\x2', '\x186', + '\x187', '\x5', '\xB5', '[', '\x2', '\x187', '\x188', '\x5', '\x99', 'M', + '\x2', '\x188', '\x189', '\x5', '\x9B', 'N', '\x2', '\x189', '\x18A', + '\x5', '\xB5', '[', '\x2', '\x18A', 'l', '\x3', '\x2', '\x2', '\x2', '\x18B', + '\x18C', '\x5', '\xB5', '[', '\x2', '\x18C', '\x18D', '\x5', '\xA3', 'R', + '\x2', '\x18D', '\x18E', '\x5', '\x9F', 'P', '\x2', '\x18E', '\x18F', + '\x5', '\xA1', 'Q', '\x2', '\x18F', '\x190', '\x5', '\xB9', ']', '\x2', + '\x190', 'n', '\x3', '\x2', '\x2', '\x2', '\x191', '\x192', '\x5', '\xB7', + '\\', '\x2', '\x192', '\x193', '\x5', '\x9B', 'N', '\x2', '\x193', '\x194', + '\x5', '\xA9', 'U', '\x2', '\x194', '\x195', '\x5', '\x9B', 'N', '\x2', + '\x195', '\x196', '\x5', '\x97', 'L', '\x2', '\x196', '\x197', '\x5', + '\xB9', ']', '\x2', '\x197', 'p', '\x3', '\x2', '\x2', '\x2', '\x198', + '\x199', '\x5', '\xB9', ']', '\x2', '\x199', '\x19A', '\x5', '\xAF', 'X', + '\x2', '\x19A', '\x19B', '\x5', '\xB1', 'Y', '\x2', '\x19B', 'r', '\x3', + '\x2', '\x2', '\x2', '\x19C', '\x19D', '\a', 'v', '\x2', '\x2', '\x19D', + '\x19E', '\a', 't', '\x2', '\x2', '\x19E', '\x19F', '\a', 'w', '\x2', + '\x2', '\x19F', '\x1A0', '\a', 'g', '\x2', '\x2', '\x1A0', 't', '\x3', + '\x2', '\x2', '\x2', '\x1A1', '\x1A2', '\a', 'w', '\x2', '\x2', '\x1A2', + '\x1A3', '\a', '\x66', '\x2', '\x2', '\x1A3', '\x1A4', '\a', 'h', '\x2', + '\x2', '\x1A4', 'v', '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1A6', '\a', + 'w', '\x2', '\x2', '\x1A6', '\x1A7', '\a', 'p', '\x2', '\x2', '\x1A7', + '\x1A8', '\a', '\x66', '\x2', '\x2', '\x1A8', '\x1A9', '\a', 'g', '\x2', + '\x2', '\x1A9', '\x1AA', '\a', 'h', '\x2', '\x2', '\x1AA', '\x1AB', '\a', + 'k', '\x2', '\x2', '\x1AB', '\x1AC', '\a', 'p', '\x2', '\x2', '\x1AC', + '\x1AD', '\a', 'g', '\x2', '\x2', '\x1AD', '\x1AE', '\a', '\x66', '\x2', + '\x2', '\x1AE', 'x', '\x3', '\x2', '\x2', '\x2', '\x1AF', '\x1B0', '\x5', + '\xBD', '_', '\x2', '\x1B0', '\x1B1', '\x5', '\x93', 'J', '\x2', '\x1B1', + '\x1B2', '\x5', '\xA9', 'U', '\x2', '\x1B2', '\x1B3', '\x5', '\xBB', '^', + '\x2', '\x1B3', '\x1B4', '\x5', '\x9B', 'N', '\x2', '\x1B4', 'z', '\x3', + '\x2', '\x2', '\x2', '\x1B5', '\x1B6', '\x5', '\xBF', '`', '\x2', '\x1B6', + '\x1B7', '\x5', '\xA1', 'Q', '\x2', '\x1B7', '\x1B8', '\x5', '\x9B', 'N', + '\x2', '\x1B8', '\x1B9', '\x5', '\xB5', '[', '\x2', '\x1B9', '\x1BA', + '\x5', '\x9B', 'N', '\x2', '\x1BA', '|', '\x3', '\x2', '\x2', '\x2', '\x1BB', + '\x1BD', '\t', '\x2', '\x2', '\x2', '\x1BC', '\x1BB', '\x3', '\x2', '\x2', + '\x2', '\x1BD', '\x1BE', '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1BC', + '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1BF', '\x3', '\x2', '\x2', '\x2', + '\x1BF', '\x1C0', '\x3', '\x2', '\x2', '\x2', '\x1C0', '\x1C1', '\b', + '?', '\x2', '\x2', '\x1C1', '~', '\x3', '\x2', '\x2', '\x2', '\x1C2', + '\x1C4', '\t', '\x3', '\x2', '\x2', '\x1C3', '\x1C2', '\x3', '\x2', '\x2', + '\x2', '\x1C3', '\x1C4', '\x3', '\x2', '\x2', '\x2', '\x1C4', '\x1C6', + '\x3', '\x2', '\x2', '\x2', '\x1C5', '\x1C7', '\x5', '\x91', 'I', '\x2', + '\x1C6', '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C7', '\x1C8', '\x3', + '\x2', '\x2', '\x2', '\x1C8', '\x1C6', '\x3', '\x2', '\x2', '\x2', '\x1C8', + '\x1C9', '\x3', '\x2', '\x2', '\x2', '\x1C9', '\x1D1', '\x3', '\x2', '\x2', + '\x2', '\x1CA', '\x1CE', '\a', '\x30', '\x2', '\x2', '\x1CB', '\x1CD', + '\x5', '\x91', 'I', '\x2', '\x1CC', '\x1CB', '\x3', '\x2', '\x2', '\x2', + '\x1CD', '\x1D0', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1CC', '\x3', + '\x2', '\x2', '\x2', '\x1CE', '\x1CF', '\x3', '\x2', '\x2', '\x2', '\x1CF', + '\x1D2', '\x3', '\x2', '\x2', '\x2', '\x1D0', '\x1CE', '\x3', '\x2', '\x2', + '\x2', '\x1D1', '\x1CA', '\x3', '\x2', '\x2', '\x2', '\x1D1', '\x1D2', + '\x3', '\x2', '\x2', '\x2', '\x1D2', '\x1DC', '\x3', '\x2', '\x2', '\x2', + '\x1D3', '\x1D5', '\x5', '\x9B', 'N', '\x2', '\x1D4', '\x1D6', '\t', '\x3', + '\x2', '\x2', '\x1D5', '\x1D4', '\x3', '\x2', '\x2', '\x2', '\x1D5', '\x1D6', + '\x3', '\x2', '\x2', '\x2', '\x1D6', '\x1D8', '\x3', '\x2', '\x2', '\x2', + '\x1D7', '\x1D9', '\x5', '\x91', 'I', '\x2', '\x1D8', '\x1D7', '\x3', + '\x2', '\x2', '\x2', '\x1D9', '\x1DA', '\x3', '\x2', '\x2', '\x2', '\x1DA', + '\x1D8', '\x3', '\x2', '\x2', '\x2', '\x1DA', '\x1DB', '\x3', '\x2', '\x2', + '\x2', '\x1DB', '\x1DD', '\x3', '\x2', '\x2', '\x2', '\x1DC', '\x1D3', + '\x3', '\x2', '\x2', '\x2', '\x1DC', '\x1DD', '\x3', '\x2', '\x2', '\x2', + '\x1DD', '\x1F3', '\x3', '\x2', '\x2', '\x2', '\x1DE', '\x1E0', '\t', + '\x3', '\x2', '\x2', '\x1DF', '\x1DE', '\x3', '\x2', '\x2', '\x2', '\x1DF', + '\x1E0', '\x3', '\x2', '\x2', '\x2', '\x1E0', '\x1E1', '\x3', '\x2', '\x2', + '\x2', '\x1E1', '\x1E3', '\a', '\x30', '\x2', '\x2', '\x1E2', '\x1E4', + '\x5', '\x91', 'I', '\x2', '\x1E3', '\x1E2', '\x3', '\x2', '\x2', '\x2', + '\x1E4', '\x1E5', '\x3', '\x2', '\x2', '\x2', '\x1E5', '\x1E3', '\x3', + '\x2', '\x2', '\x2', '\x1E5', '\x1E6', '\x3', '\x2', '\x2', '\x2', '\x1E6', + '\x1F0', '\x3', '\x2', '\x2', '\x2', '\x1E7', '\x1E9', '\x5', '\x9B', + 'N', '\x2', '\x1E8', '\x1EA', '\t', '\x3', '\x2', '\x2', '\x1E9', '\x1E8', + '\x3', '\x2', '\x2', '\x2', '\x1E9', '\x1EA', '\x3', '\x2', '\x2', '\x2', + '\x1EA', '\x1EC', '\x3', '\x2', '\x2', '\x2', '\x1EB', '\x1ED', '\x5', + '\x91', 'I', '\x2', '\x1EC', '\x1EB', '\x3', '\x2', '\x2', '\x2', '\x1ED', + '\x1EE', '\x3', '\x2', '\x2', '\x2', '\x1EE', '\x1EC', '\x3', '\x2', '\x2', + '\x2', '\x1EE', '\x1EF', '\x3', '\x2', '\x2', '\x2', '\x1EF', '\x1F1', + '\x3', '\x2', '\x2', '\x2', '\x1F0', '\x1E7', '\x3', '\x2', '\x2', '\x2', + '\x1F0', '\x1F1', '\x3', '\x2', '\x2', '\x2', '\x1F1', '\x1F3', '\x3', + '\x2', '\x2', '\x2', '\x1F2', '\x1C3', '\x3', '\x2', '\x2', '\x2', '\x1F2', + '\x1DF', '\x3', '\x2', '\x2', '\x2', '\x1F3', '\x80', '\x3', '\x2', '\x2', + '\x2', '\x1F4', '\x1F9', '\a', '$', '\x2', '\x2', '\x1F5', '\x1F8', '\x5', + '\x83', '\x42', '\x2', '\x1F6', '\x1F8', '\x5', '\x8B', '\x46', '\x2', + '\x1F7', '\x1F5', '\x3', '\x2', '\x2', '\x2', '\x1F7', '\x1F6', '\x3', + '\x2', '\x2', '\x2', '\x1F8', '\x1FB', '\x3', '\x2', '\x2', '\x2', '\x1F9', + '\x1F7', '\x3', '\x2', '\x2', '\x2', '\x1F9', '\x1FA', '\x3', '\x2', '\x2', + '\x2', '\x1FA', '\x1FC', '\x3', '\x2', '\x2', '\x2', '\x1FB', '\x1F9', + '\x3', '\x2', '\x2', '\x2', '\x1FC', '\x207', '\a', '$', '\x2', '\x2', + '\x1FD', '\x202', '\a', ')', '\x2', '\x2', '\x1FE', '\x201', '\x5', '\x83', + '\x42', '\x2', '\x1FF', '\x201', '\x5', '\x89', '\x45', '\x2', '\x200', + '\x1FE', '\x3', '\x2', '\x2', '\x2', '\x200', '\x1FF', '\x3', '\x2', '\x2', + '\x2', '\x201', '\x204', '\x3', '\x2', '\x2', '\x2', '\x202', '\x200', + '\x3', '\x2', '\x2', '\x2', '\x202', '\x203', '\x3', '\x2', '\x2', '\x2', + '\x203', '\x205', '\x3', '\x2', '\x2', '\x2', '\x204', '\x202', '\x3', + '\x2', '\x2', '\x2', '\x205', '\x207', '\a', ')', '\x2', '\x2', '\x206', + '\x1F4', '\x3', '\x2', '\x2', '\x2', '\x206', '\x1FD', '\x3', '\x2', '\x2', + '\x2', '\x207', '\x82', '\x3', '\x2', '\x2', '\x2', '\x208', '\x20B', + '\a', '^', '\x2', '\x2', '\x209', '\x20C', '\t', '\x4', '\x2', '\x2', + '\x20A', '\x20C', '\x5', '\x85', '\x43', '\x2', '\x20B', '\x209', '\x3', + '\x2', '\x2', '\x2', '\x20B', '\x20A', '\x3', '\x2', '\x2', '\x2', '\x20C', + '\x84', '\x3', '\x2', '\x2', '\x2', '\x20D', '\x20E', '\a', 'w', '\x2', + '\x2', '\x20E', '\x20F', '\x5', '\x87', '\x44', '\x2', '\x20F', '\x210', + '\x5', '\x87', '\x44', '\x2', '\x210', '\x211', '\x5', '\x87', '\x44', + '\x2', '\x211', '\x212', '\x5', '\x87', '\x44', '\x2', '\x212', '\x86', + '\x3', '\x2', '\x2', '\x2', '\x213', '\x214', '\t', '\x5', '\x2', '\x2', + '\x214', '\x88', '\x3', '\x2', '\x2', '\x2', '\x215', '\x216', '\n', '\x6', + '\x2', '\x2', '\x216', '\x8A', '\x3', '\x2', '\x2', '\x2', '\x217', '\x218', + '\n', '\a', '\x2', '\x2', '\x218', '\x8C', '\x3', '\x2', '\x2', '\x2', + '\x219', '\x223', '\x3', '\x2', '\x2', '\x2', '\x21A', '\x21F', '\t', + '\b', '\x2', '\x2', '\x21B', '\x21E', '\t', '\b', '\x2', '\x2', '\x21C', + '\x21E', '\x5', '\x91', 'I', '\x2', '\x21D', '\x21B', '\x3', '\x2', '\x2', + '\x2', '\x21D', '\x21C', '\x3', '\x2', '\x2', '\x2', '\x21E', '\x221', + '\x3', '\x2', '\x2', '\x2', '\x21F', '\x21D', '\x3', '\x2', '\x2', '\x2', + '\x21F', '\x220', '\x3', '\x2', '\x2', '\x2', '\x220', '\x223', '\x3', + '\x2', '\x2', '\x2', '\x221', '\x21F', '\x3', '\x2', '\x2', '\x2', '\x222', + '\x219', '\x3', '\x2', '\x2', '\x2', '\x222', '\x21A', '\x3', '\x2', '\x2', + '\x2', '\x223', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x224', '\x225', + '\a', '\x42', '\x2', '\x2', '\x225', '\x226', '\x5', '\x8D', 'G', '\x2', + '\x226', '\x90', '\x3', '\x2', '\x2', '\x2', '\x227', '\x228', '\t', '\t', + '\x2', '\x2', '\x228', '\x92', '\x3', '\x2', '\x2', '\x2', '\x229', '\x22A', + '\t', '\n', '\x2', '\x2', '\x22A', '\x94', '\x3', '\x2', '\x2', '\x2', + '\x22B', '\x22C', '\t', '\v', '\x2', '\x2', '\x22C', '\x96', '\x3', '\x2', + '\x2', '\x2', '\x22D', '\x22E', '\t', '\f', '\x2', '\x2', '\x22E', '\x98', + '\x3', '\x2', '\x2', '\x2', '\x22F', '\x230', '\t', '\r', '\x2', '\x2', + '\x230', '\x9A', '\x3', '\x2', '\x2', '\x2', '\x231', '\x232', '\t', '\xE', + '\x2', '\x2', '\x232', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x233', '\x234', + '\t', '\xF', '\x2', '\x2', '\x234', '\x9E', '\x3', '\x2', '\x2', '\x2', + '\x235', '\x236', '\t', '\x10', '\x2', '\x2', '\x236', '\xA0', '\x3', + '\x2', '\x2', '\x2', '\x237', '\x238', '\t', '\x11', '\x2', '\x2', '\x238', + '\xA2', '\x3', '\x2', '\x2', '\x2', '\x239', '\x23A', '\t', '\x12', '\x2', + '\x2', '\x23A', '\xA4', '\x3', '\x2', '\x2', '\x2', '\x23B', '\x23C', + '\t', '\x13', '\x2', '\x2', '\x23C', '\xA6', '\x3', '\x2', '\x2', '\x2', + '\x23D', '\x23E', '\t', '\x14', '\x2', '\x2', '\x23E', '\xA8', '\x3', + '\x2', '\x2', '\x2', '\x23F', '\x240', '\t', '\x15', '\x2', '\x2', '\x240', + '\xAA', '\x3', '\x2', '\x2', '\x2', '\x241', '\x242', '\t', '\x16', '\x2', + '\x2', '\x242', '\xAC', '\x3', '\x2', '\x2', '\x2', '\x243', '\x244', + '\t', '\x17', '\x2', '\x2', '\x244', '\xAE', '\x3', '\x2', '\x2', '\x2', + '\x245', '\x246', '\t', '\x18', '\x2', '\x2', '\x246', '\xB0', '\x3', + '\x2', '\x2', '\x2', '\x247', '\x248', '\t', '\x19', '\x2', '\x2', '\x248', + '\xB2', '\x3', '\x2', '\x2', '\x2', '\x249', '\x24A', '\t', '\x1A', '\x2', + '\x2', '\x24A', '\xB4', '\x3', '\x2', '\x2', '\x2', '\x24B', '\x24C', + '\t', '\x1B', '\x2', '\x2', '\x24C', '\xB6', '\x3', '\x2', '\x2', '\x2', + '\x24D', '\x24E', '\t', '\x1C', '\x2', '\x2', '\x24E', '\xB8', '\x3', + '\x2', '\x2', '\x2', '\x24F', '\x250', '\t', '\x1D', '\x2', '\x2', '\x250', + '\xBA', '\x3', '\x2', '\x2', '\x2', '\x251', '\x252', '\t', '\x1E', '\x2', + '\x2', '\x252', '\xBC', '\x3', '\x2', '\x2', '\x2', '\x253', '\x254', + '\t', '\x1F', '\x2', '\x2', '\x254', '\xBE', '\x3', '\x2', '\x2', '\x2', + '\x255', '\x256', '\t', ' ', '\x2', '\x2', '\x256', '\xC0', '\x3', '\x2', + '\x2', '\x2', '\x257', '\x258', '\t', '!', '\x2', '\x2', '\x258', '\xC2', + '\x3', '\x2', '\x2', '\x2', '\x259', '\x25A', '\t', '\"', '\x2', '\x2', + '\x25A', '\xC4', '\x3', '\x2', '\x2', '\x2', '\x25B', '\x25C', '\t', '#', + '\x2', '\x2', '\x25C', '\xC6', '\x3', '\x2', '\x2', '\x2', '\x1A', '\x2', + '\x1BE', '\x1C3', '\x1C8', '\x1CE', '\x1D1', '\x1D5', '\x1DA', '\x1DC', + '\x1DF', '\x1E5', '\x1E9', '\x1EE', '\x1F0', '\x1F2', '\x1F7', '\x1F9', + '\x200', '\x202', '\x206', '\x20B', '\x21D', '\x21F', '\x222', '\x3', + '\b', '\x2', '\x2', }; public static readonly ATN _ATN = diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs index 53293f9382..e68b8e18f5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/sqlParser.cs @@ -40,11 +40,11 @@ public const int T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, T__24=25, T__25=26, T__26=27, K_ALL=28, K_AND=29, K_ARRAY=30, K_AS=31, K_ASC=32, K_BETWEEN=33, K_BY=34, K_DESC=35, K_DISTINCT=36, K_ESCAPE=37, - K_EXISTS=38, K_FALSE=39, K_FROM=40, K_GROUP=41, K_IN=42, K_JOIN=43, K_LEFT=44, - K_LIKE=45, K_LIMIT=46, K_NOT=47, K_NULL=48, K_OFFSET=49, K_OR=50, K_ORDER=51, - K_RIGHT=52, K_SELECT=53, K_TOP=54, K_TRUE=55, K_UDF=56, K_UNDEFINED=57, - K_VALUE=58, K_WHERE=59, WS=60, NUMERIC_LITERAL=61, STRING_LITERAL=62, - LEX_IDENTIFIER=63, PARAMETER=64; + K_EXISTS=38, K_FIRST=39, K_FALSE=40, K_FROM=41, K_GROUP=42, K_IN=43, K_JOIN=44, + K_LAST=45, K_LEFT=46, K_LIKE=47, K_LIMIT=48, K_NOT=49, K_NULL=50, K_OFFSET=51, + K_OR=52, K_ORDER=53, K_RIGHT=54, K_SELECT=55, K_TOP=56, K_TRUE=57, K_UDF=58, + K_UNDEFINED=59, K_VALUE=60, K_WHERE=61, WS=62, NUMERIC_LITERAL=63, STRING_LITERAL=64, + LEX_IDENTIFIER=65, PARAMETER=66; public const int RULE_program = 0, RULE_sql_query = 1, RULE_select_clause = 2, RULE_top_spec = 3, RULE_selection = 4, RULE_select_star_spec = 5, RULE_select_value_spec = 6, @@ -81,19 +81,20 @@ public const int null, "'*'", "','", "'('", "')'", "'.'", "'['", "']'", "'?'", "':'", "'??'", "'/'", "'%'", "'+'", "'-'", "'<'", "'>'", "'>='", "'<='", "'='", "'!='", "'&'", "'^'", "'|'", "'||'", "'~'", "'{'", "'}'", null, null, null, null, - null, null, null, null, null, null, null, "'false'", null, null, null, - null, null, null, null, null, "'null'", null, null, null, null, null, - null, "'true'", "'udf'", "'undefined'" + null, null, null, null, null, null, null, null, "'false'", null, null, + null, null, null, null, null, null, null, "'null'", null, null, null, + null, null, null, "'true'", "'udf'", "'undefined'" }; private static readonly string[] _SymbolicNames = { null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "K_ALL", "K_AND", "K_ARRAY", "K_AS", "K_ASC", - "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FALSE", - "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LEFT", "K_LIKE", "K_LIMIT", - "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", "K_RIGHT", "K_SELECT", - "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", "K_WHERE", "WS", - "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", "PARAMETER" + "K_BETWEEN", "K_BY", "K_DESC", "K_DISTINCT", "K_ESCAPE", "K_EXISTS", "K_FIRST", + "K_FALSE", "K_FROM", "K_GROUP", "K_IN", "K_JOIN", "K_LAST", "K_LEFT", + "K_LIKE", "K_LIMIT", "K_NOT", "K_NULL", "K_OFFSET", "K_OR", "K_ORDER", + "K_RIGHT", "K_SELECT", "K_TOP", "K_TRUE", "K_UDF", "K_UNDEFINED", "K_VALUE", + "K_WHERE", "WS", "NUMERIC_LITERAL", "STRING_LITERAL", "LEX_IDENTIFIER", + "PARAMETER" }; public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames); @@ -463,7 +464,9 @@ public SelectionContext selection() { case K_ALL: case K_ARRAY: case K_EXISTS: + case K_FIRST: case K_FALSE: + case K_LAST: case K_LEFT: case K_NOT: case K_NULL: @@ -994,6 +997,8 @@ public CollectionContext collection() { ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case K_ALL: + case K_FIRST: + case K_LAST: case LEX_IDENTIFIER: _localctx = new InputPathCollectionContext(_localctx); EnterOuterAlt(_localctx, 1); @@ -2808,7 +2813,9 @@ public Unary_scalar_expressionContext unary_scalar_expression() { case K_ALL: case K_ARRAY: case K_EXISTS: + case K_FIRST: case K_FALSE: + case K_LAST: case K_LEFT: case K_NULL: case K_RIGHT: @@ -2971,6 +2978,26 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } + public partial class FirstScalarExpressionContext : Primary_expressionContext { + public ITerminalNode K_FIRST() { return GetToken(sqlParser.K_FIRST, 0); } + public Sql_queryContext sql_query() { + return GetRuleContext(0); + } + public FirstScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterFirstScalarExpression(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitFirstScalarExpression(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitFirstScalarExpression(this); + else return visitor.VisitChildren(this); + } + } public partial class ArrayCreateScalarExpressionContext : Primary_expressionContext { public Scalar_expression_listContext scalar_expression_list() { return GetRuleContext(0); @@ -3145,6 +3172,26 @@ public override TResult Accept(IParseTreeVisitor visitor) { else return visitor.VisitChildren(this); } } + public partial class LastScalarExpressionContext : Primary_expressionContext { + public ITerminalNode K_LAST() { return GetToken(sqlParser.K_LAST, 0); } + public Sql_queryContext sql_query() { + return GetRuleContext(0); + } + public LastScalarExpressionContext(Primary_expressionContext context) { CopyFrom(context); } + public override void EnterRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.EnterLastScalarExpression(this); + } + public override void ExitRule(IParseTreeListener listener) { + IsqlListener typedListener = listener as IsqlListener; + if (typedListener != null) typedListener.ExitLastScalarExpression(this); + } + public override TResult Accept(IParseTreeVisitor visitor) { + IsqlVisitor typedVisitor = visitor as IsqlVisitor; + if (typedVisitor != null) return typedVisitor.VisitLastScalarExpression(this); + else return visitor.VisitChildren(this); + } + } public partial class PropertyRefScalarExpressionRecursiveContext : Primary_expressionContext { public Primary_expressionContext primary_expression() { return GetRuleContext(0); @@ -3185,7 +3232,7 @@ private Primary_expressionContext primary_expression(int _p) { int _alt; EnterOuterAlt(_localctx, 1); { - State = 397; + State = 407; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,35,Context) ) { case 1: @@ -3222,7 +3269,7 @@ private Primary_expressionContext primary_expression(int _p) { State = 365; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FIRST - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LAST - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { { State = 364; scalar_expression_list(); } @@ -3303,16 +3350,38 @@ private Primary_expressionContext primary_expression(int _p) { } break; case 11: + { + _localctx = new FirstScalarExpressionContext(_localctx); + Context = _localctx; + _prevctx = _localctx; + State = 396; Match(K_FIRST); + State = 397; Match(T__2); + State = 398; sql_query(); + State = 399; Match(T__3); + } + break; + case 12: + { + _localctx = new LastScalarExpressionContext(_localctx); + Context = _localctx; + _prevctx = _localctx; + State = 401; Match(K_LAST); + State = 402; Match(T__2); + State = 403; sql_query(); + State = 404; Match(T__3); + } + break; + case 13: { _localctx = new FunctionCallScalarExpressionContext(_localctx); Context = _localctx; _prevctx = _localctx; - State = 396; function_call_scalar_expression(); + State = 406; function_call_scalar_expression(); } break; } Context.Stop = TokenStream.LT(-1); - State = 409; + State = 419; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,37,Context); while ( _alt!=2 && _alt!=global::Antlr4.Runtime.Atn.ATN.INVALID_ALT_NUMBER ) { @@ -3321,34 +3390,34 @@ private Primary_expressionContext primary_expression(int _p) { TriggerExitRuleEvent(); _prevctx = _localctx; { - State = 407; + State = 417; ErrorHandler.Sync(this); switch ( Interpreter.AdaptivePredict(TokenStream,36,Context) ) { case 1: { _localctx = new PropertyRefScalarExpressionRecursiveContext(new Primary_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_primary_expression); - State = 399; - if (!(Precpred(Context, 6))) throw new FailedPredicateException(this, "Precpred(Context, 6)"); - State = 400; Match(T__4); - State = 401; identifier(); + State = 409; + if (!(Precpred(Context, 8))) throw new FailedPredicateException(this, "Precpred(Context, 8)"); + State = 410; Match(T__4); + State = 411; identifier(); } break; case 2: { _localctx = new MemberIndexerScalarExpressionContext(new Primary_expressionContext(_parentctx, _parentState)); PushNewRecursionContext(_localctx, _startState, RULE_primary_expression); - State = 402; - if (!(Precpred(Context, 5))) throw new FailedPredicateException(this, "Precpred(Context, 5)"); - State = 403; Match(T__5); - State = 404; scalar_expression(0); - State = 405; Match(T__6); + State = 412; + if (!(Precpred(Context, 7))) throw new FailedPredicateException(this, "Precpred(Context, 7)"); + State = 413; Match(T__5); + State = 414; scalar_expression(0); + State = 415; Match(T__6); } break; } } } - State = 411; + State = 421; ErrorHandler.Sync(this); _alt = Interpreter.AdaptivePredict(TokenStream,37,Context); } @@ -3401,70 +3470,72 @@ public Function_call_scalar_expressionContext function_call_scalar_expression() EnterRule(_localctx, 78, RULE_function_call_scalar_expression); int _la; try { - State = 435; + State = 445; ErrorHandler.Sync(this); switch (TokenStream.LA(1)) { case K_ALL: + case K_FIRST: + case K_LAST: case K_UDF: case LEX_IDENTIFIER: EnterOuterAlt(_localctx, 1); { - State = 414; + State = 424; ErrorHandler.Sync(this); _la = TokenStream.LA(1); if (_la==K_UDF) { { - State = 412; Match(K_UDF); - State = 413; Match(T__4); + State = 422; Match(K_UDF); + State = 423; Match(T__4); } } - State = 416; identifier(); - State = 417; Match(T__2); - State = 419; + State = 426; identifier(); + State = 427; Match(T__2); + State = 429; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FIRST - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LAST - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { { - State = 418; scalar_expression_list(); + State = 428; scalar_expression_list(); } } - State = 421; Match(T__3); + State = 431; Match(T__3); } break; case K_LEFT: EnterOuterAlt(_localctx, 2); { - State = 423; Match(K_LEFT); - State = 424; Match(T__2); - State = 426; + State = 433; Match(K_LEFT); + State = 434; Match(T__2); + State = 436; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FIRST - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LAST - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { { - State = 425; scalar_expression_list(); + State = 435; scalar_expression_list(); } } - State = 428; Match(T__3); + State = 438; Match(T__3); } break; case K_RIGHT: EnterOuterAlt(_localctx, 3); { - State = 429; Match(K_RIGHT); - State = 430; Match(T__2); - State = 432; + State = 439; Match(K_RIGHT); + State = 440; Match(T__2); + State = 442; ErrorHandler.Sync(this); _la = TokenStream.LA(1); - if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { + if (((((_la - 3)) & ~0x3f) == 0 && ((1L << (_la - 3)) & ((1L << (T__2 - 3)) | (1L << (T__5 - 3)) | (1L << (T__12 - 3)) | (1L << (T__13 - 3)) | (1L << (T__24 - 3)) | (1L << (T__25 - 3)) | (1L << (K_ALL - 3)) | (1L << (K_ARRAY - 3)) | (1L << (K_EXISTS - 3)) | (1L << (K_FIRST - 3)) | (1L << (K_FALSE - 3)) | (1L << (K_LAST - 3)) | (1L << (K_LEFT - 3)) | (1L << (K_NOT - 3)) | (1L << (K_NULL - 3)) | (1L << (K_RIGHT - 3)) | (1L << (K_TRUE - 3)) | (1L << (K_UDF - 3)) | (1L << (K_UNDEFINED - 3)) | (1L << (NUMERIC_LITERAL - 3)) | (1L << (STRING_LITERAL - 3)) | (1L << (LEX_IDENTIFIER - 3)) | (1L << (PARAMETER - 3)))) != 0)) { { - State = 431; scalar_expression_list(); + State = 441; scalar_expression_list(); } } - State = 434; Match(T__3); + State = 444; Match(T__3); } break; default: @@ -3517,18 +3588,18 @@ public Scalar_expression_listContext scalar_expression_list() { try { EnterOuterAlt(_localctx, 1); { - State = 437; scalar_expression(0); - State = 442; + State = 447; scalar_expression(0); + State = 452; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 438; Match(T__1); - State = 439; scalar_expression(0); + State = 448; Match(T__1); + State = 449; scalar_expression(0); } } - State = 444; + State = 454; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -3580,18 +3651,18 @@ public Object_property_listContext object_property_list() { try { EnterOuterAlt(_localctx, 1); { - State = 445; object_property(); - State = 450; + State = 455; object_property(); + State = 460; ErrorHandler.Sync(this); _la = TokenStream.LA(1); while (_la==T__1) { { { - State = 446; Match(T__1); - State = 447; object_property(); + State = 456; Match(T__1); + State = 457; object_property(); } } - State = 452; + State = 462; ErrorHandler.Sync(this); _la = TokenStream.LA(1); } @@ -3640,9 +3711,9 @@ public Object_propertyContext object_property() { try { EnterOuterAlt(_localctx, 1); { - State = 453; Match(STRING_LITERAL); - State = 454; Match(T__8); - State = 455; scalar_expression(0); + State = 463; Match(STRING_LITERAL); + State = 464; Match(T__8); + State = 465; scalar_expression(0); } } catch (RecognitionException re) { @@ -3659,6 +3730,8 @@ public Object_propertyContext object_property() { public partial class IdentifierContext : ParserRuleContext { public ITerminalNode LEX_IDENTIFIER() { return GetToken(sqlParser.LEX_IDENTIFIER, 0); } public ITerminalNode K_ALL() { return GetToken(sqlParser.K_ALL, 0); } + public ITerminalNode K_FIRST() { return GetToken(sqlParser.K_FIRST, 0); } + public ITerminalNode K_LAST() { return GetToken(sqlParser.K_LAST, 0); } public IdentifierContext(ParserRuleContext parent, int invokingState) : base(parent, invokingState) { @@ -3687,9 +3760,9 @@ public IdentifierContext identifier() { try { EnterOuterAlt(_localctx, 1); { - State = 457; + State = 467; _la = TokenStream.LA(1); - if ( !(_la==K_ALL || _la==LEX_IDENTIFIER) ) { + if ( !(((((_la - 28)) & ~0x3f) == 0 && ((1L << (_la - 28)) & ((1L << (K_ALL - 28)) | (1L << (K_FIRST - 28)) | (1L << (K_LAST - 28)) | (1L << (LEX_IDENTIFIER - 28)))) != 0)) ) { ErrorHandler.RecoverInline(this); } else { @@ -3744,9 +3817,9 @@ public LiteralContext literal() { try { EnterOuterAlt(_localctx, 1); { - State = 459; + State = 469; _la = TokenStream.LA(1); - if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << K_FALSE) | (1L << K_NULL) | (1L << K_TRUE) | (1L << K_UNDEFINED) | (1L << NUMERIC_LITERAL) | (1L << STRING_LITERAL))) != 0)) ) { + if ( !(((((_la - 40)) & ~0x3f) == 0 && ((1L << (_la - 40)) & ((1L << (K_FALSE - 40)) | (1L << (K_NULL - 40)) | (1L << (K_TRUE - 40)) | (1L << (K_UNDEFINED - 40)) | (1L << (NUMERIC_LITERAL - 40)) | (1L << (STRING_LITERAL - 40)))) != 0)) ) { ErrorHandler.RecoverInline(this); } else { @@ -3820,15 +3893,15 @@ private bool binary_scalar_expression_sempred(Binary_scalar_expressionContext _l } private bool primary_expression_sempred(Primary_expressionContext _localctx, int predIndex) { switch (predIndex) { - case 16: return Precpred(Context, 6); - case 17: return Precpred(Context, 5); + case 16: return Precpred(Context, 8); + case 17: return Precpred(Context, 7); } return true; } private static char[] _serializedATN = { '\x3', '\x608B', '\xA72A', '\x8133', '\xB9ED', '\x417C', '\x3BE7', '\x7786', - '\x5964', '\x3', '\x42', '\x1D0', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', + '\x5964', '\x3', '\x44', '\x1DA', '\x4', '\x2', '\t', '\x2', '\x4', '\x3', '\t', '\x3', '\x4', '\x4', '\t', '\x4', '\x4', '\x5', '\t', '\x5', '\x4', '\x6', '\t', '\x6', '\x4', '\a', '\t', '\a', '\x4', '\b', '\t', '\b', '\x4', '\t', '\t', '\t', '\x4', '\n', '\t', '\n', '\x4', '\v', '\t', '\v', @@ -3906,29 +3979,31 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', - '\x3', '(', '\x3', '(', '\x5', '(', '\x190', '\n', '(', '\x3', '(', '\x3', - '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', - '(', '\a', '(', '\x19A', '\n', '(', '\f', '(', '\xE', '(', '\x19D', '\v', - '(', '\x3', ')', '\x3', ')', '\x5', ')', '\x1A1', '\n', ')', '\x3', ')', - '\x3', ')', '\x3', ')', '\x5', ')', '\x1A6', '\n', ')', '\x3', ')', '\x3', - ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x5', ')', '\x1AD', '\n', ')', - '\x3', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x5', ')', '\x1B3', '\n', - ')', '\x3', ')', '\x5', ')', '\x1B6', '\n', ')', '\x3', '*', '\x3', '*', - '\x3', '*', '\a', '*', '\x1BB', '\n', '*', '\f', '*', '\xE', '*', '\x1BE', - '\v', '*', '\x3', '+', '\x3', '+', '\x3', '+', '\a', '+', '\x1C3', '\n', - '+', '\f', '+', '\xE', '+', '\x1C6', '\v', '+', '\x3', ',', '\x3', ',', - '\x3', ',', '\x3', ',', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', - '\x3', '.', '\x2', '\b', '\x16', '\x1A', '.', '\x30', '\x38', 'N', '/', - '\x2', '\x4', '\x6', '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x14', - '\x16', '\x18', '\x1A', '\x1C', '\x1E', ' ', '\"', '$', '&', '(', '*', - ',', '.', '\x30', '\x32', '\x34', '\x36', '\x38', ':', '<', '>', '@', - '\x42', '\x44', '\x46', 'H', 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', 'Z', - '\x2', '\v', '\x4', '\x2', '?', '?', '\x42', '\x42', '\x4', '\x2', '\"', - '\"', '%', '%', '\x4', '\x2', '\x3', '\x3', '\r', '\xE', '\x3', '\x2', - '\xF', '\x10', '\x3', '\x2', '\x11', '\x14', '\x3', '\x2', '\x15', '\x16', - '\x5', '\x2', '\xF', '\x10', '\x1B', '\x1B', '\x31', '\x31', '\x4', '\x2', - '\x1E', '\x1E', '\x41', '\x41', '\a', '\x2', ')', ')', '\x32', '\x32', - '\x39', '\x39', ';', ';', '?', '@', '\x2', '\x1E2', '\x2', '\\', '\x3', + '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', + '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', + '\x5', '(', '\x19A', '\n', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', + '(', '\x3', '(', '\x3', '(', '\x3', '(', '\x3', '(', '\a', '(', '\x1A4', + '\n', '(', '\f', '(', '\xE', '(', '\x1A7', '\v', '(', '\x3', ')', '\x3', + ')', '\x5', ')', '\x1AB', '\n', ')', '\x3', ')', '\x3', ')', '\x3', ')', + '\x5', ')', '\x1B0', '\n', ')', '\x3', ')', '\x3', ')', '\x3', ')', '\x3', + ')', '\x3', ')', '\x5', ')', '\x1B7', '\n', ')', '\x3', ')', '\x3', ')', + '\x3', ')', '\x3', ')', '\x5', ')', '\x1BD', '\n', ')', '\x3', ')', '\x5', + ')', '\x1C0', '\n', ')', '\x3', '*', '\x3', '*', '\x3', '*', '\a', '*', + '\x1C5', '\n', '*', '\f', '*', '\xE', '*', '\x1C8', '\v', '*', '\x3', + '+', '\x3', '+', '\x3', '+', '\a', '+', '\x1CD', '\n', '+', '\f', '+', + '\xE', '+', '\x1D0', '\v', '+', '\x3', ',', '\x3', ',', '\x3', ',', '\x3', + ',', '\x3', '-', '\x3', '-', '\x3', '.', '\x3', '.', '\x3', '.', '\x2', + '\b', '\x16', '\x1A', '.', '\x30', '\x38', 'N', '/', '\x2', '\x4', '\x6', + '\b', '\n', '\f', '\xE', '\x10', '\x12', '\x14', '\x16', '\x18', '\x1A', + '\x1C', '\x1E', ' ', '\"', '$', '&', '(', '*', ',', '.', '\x30', '\x32', + '\x34', '\x36', '\x38', ':', '<', '>', '@', '\x42', '\x44', '\x46', 'H', + 'J', 'L', 'N', 'P', 'R', 'T', 'V', 'X', 'Z', '\x2', '\v', '\x4', '\x2', + '\x41', '\x41', '\x44', '\x44', '\x4', '\x2', '\"', '\"', '%', '%', '\x4', + '\x2', '\x3', '\x3', '\r', '\xE', '\x3', '\x2', '\xF', '\x10', '\x3', + '\x2', '\x11', '\x14', '\x3', '\x2', '\x15', '\x16', '\x5', '\x2', '\xF', + '\x10', '\x1B', '\x1B', '\x33', '\x33', '\x6', '\x2', '\x1E', '\x1E', + ')', ')', '/', '/', '\x43', '\x43', '\a', '\x2', '*', '*', '\x34', '\x34', + ';', ';', '=', '=', '\x41', '\x42', '\x2', '\x1EE', '\x2', '\\', '\x3', '\x2', '\x2', '\x2', '\x4', '_', '\x3', '\x2', '\x2', '\x2', '\x6', 'o', '\x3', '\x2', '\x2', '\x2', '\b', 'x', '\x3', '\x2', '\x2', '\x2', '\n', '~', '\x3', '\x2', '\x2', '\x2', '\f', '\x80', '\x3', '\x2', '\x2', '\x2', @@ -3950,11 +4025,11 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int '\x2', '\x2', '\x2', '\x42', '\x159', '\x3', '\x2', '\x2', '\x2', '\x44', '\x15B', '\x3', '\x2', '\x2', '\x2', '\x46', '\x15D', '\x3', '\x2', '\x2', '\x2', 'H', '\x15F', '\x3', '\x2', '\x2', '\x2', 'J', '\x165', '\x3', - '\x2', '\x2', '\x2', 'L', '\x167', '\x3', '\x2', '\x2', '\x2', 'N', '\x18F', - '\x3', '\x2', '\x2', '\x2', 'P', '\x1B5', '\x3', '\x2', '\x2', '\x2', - 'R', '\x1B7', '\x3', '\x2', '\x2', '\x2', 'T', '\x1BF', '\x3', '\x2', - '\x2', '\x2', 'V', '\x1C7', '\x3', '\x2', '\x2', '\x2', 'X', '\x1CB', - '\x3', '\x2', '\x2', '\x2', 'Z', '\x1CD', '\x3', '\x2', '\x2', '\x2', + '\x2', '\x2', '\x2', 'L', '\x167', '\x3', '\x2', '\x2', '\x2', 'N', '\x199', + '\x3', '\x2', '\x2', '\x2', 'P', '\x1BF', '\x3', '\x2', '\x2', '\x2', + 'R', '\x1C1', '\x3', '\x2', '\x2', '\x2', 'T', '\x1C9', '\x3', '\x2', + '\x2', '\x2', 'V', '\x1D1', '\x3', '\x2', '\x2', '\x2', 'X', '\x1D5', + '\x3', '\x2', '\x2', '\x2', 'Z', '\x1D7', '\x3', '\x2', '\x2', '\x2', '\\', ']', '\x5', '\x4', '\x3', '\x2', ']', '^', '\a', '\x2', '\x2', '\x3', '^', '\x3', '\x3', '\x2', '\x2', '\x2', '_', '\x61', '\x5', '\x6', '\x4', '\x2', '`', '\x62', '\x5', '\x14', '\v', '\x2', '\x61', '`', '\x3', '\x2', @@ -3968,89 +4043,89 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int 'j', 'k', '\x3', '\x2', '\x2', '\x2', 'k', 'm', '\x3', '\x2', '\x2', '\x2', 'l', 'n', '\x5', '(', '\x15', '\x2', 'm', 'l', '\x3', '\x2', '\x2', '\x2', 'm', 'n', '\x3', '\x2', '\x2', '\x2', 'n', '\x5', '\x3', '\x2', '\x2', - '\x2', 'o', 'q', '\a', '\x37', '\x2', '\x2', 'p', 'r', '\a', '&', '\x2', + '\x2', 'o', 'q', '\a', '\x39', '\x2', '\x2', 'p', 'r', '\a', '&', '\x2', '\x2', 'q', 'p', '\x3', '\x2', '\x2', '\x2', 'q', 'r', '\x3', '\x2', '\x2', '\x2', 'r', 't', '\x3', '\x2', '\x2', '\x2', 's', 'u', '\x5', '\b', '\x5', '\x2', 't', 's', '\x3', '\x2', '\x2', '\x2', 't', 'u', '\x3', '\x2', '\x2', '\x2', 'u', 'v', '\x3', '\x2', '\x2', '\x2', 'v', 'w', '\x5', '\n', '\x6', - '\x2', 'w', '\a', '\x3', '\x2', '\x2', '\x2', 'x', 'y', '\a', '\x38', - '\x2', '\x2', 'y', 'z', '\t', '\x2', '\x2', '\x2', 'z', '\t', '\x3', '\x2', - '\x2', '\x2', '{', '\x7F', '\x5', '\f', '\a', '\x2', '|', '\x7F', '\x5', - '\xE', '\b', '\x2', '}', '\x7F', '\x5', '\x10', '\t', '\x2', '~', '{', - '\x3', '\x2', '\x2', '\x2', '~', '|', '\x3', '\x2', '\x2', '\x2', '~', - '}', '\x3', '\x2', '\x2', '\x2', '\x7F', '\v', '\x3', '\x2', '\x2', '\x2', - '\x80', '\x81', '\a', '\x3', '\x2', '\x2', '\x81', '\r', '\x3', '\x2', - '\x2', '\x2', '\x82', '\x83', '\a', '<', '\x2', '\x2', '\x83', '\x84', - '\x5', '.', '\x18', '\x2', '\x84', '\xF', '\x3', '\x2', '\x2', '\x2', - '\x85', '\x8A', '\x5', '\x12', '\n', '\x2', '\x86', '\x87', '\a', '\x4', - '\x2', '\x2', '\x87', '\x89', '\x5', '\x12', '\n', '\x2', '\x88', '\x86', - '\x3', '\x2', '\x2', '\x2', '\x89', '\x8C', '\x3', '\x2', '\x2', '\x2', - '\x8A', '\x88', '\x3', '\x2', '\x2', '\x2', '\x8A', '\x8B', '\x3', '\x2', - '\x2', '\x2', '\x8B', '\x11', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A', - '\x3', '\x2', '\x2', '\x2', '\x8D', '\x90', '\x5', '.', '\x18', '\x2', - '\x8E', '\x8F', '\a', '!', '\x2', '\x2', '\x8F', '\x91', '\x5', 'X', '-', - '\x2', '\x90', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\x3', - '\x2', '\x2', '\x2', '\x91', '\x13', '\x3', '\x2', '\x2', '\x2', '\x92', - '\x93', '\a', '*', '\x2', '\x2', '\x93', '\x94', '\x5', '\x16', '\f', - '\x2', '\x94', '\x15', '\x3', '\x2', '\x2', '\x2', '\x95', '\x96', '\b', - '\f', '\x1', '\x2', '\x96', '\x9B', '\x5', '\x18', '\r', '\x2', '\x97', - '\x99', '\a', '!', '\x2', '\x2', '\x98', '\x97', '\x3', '\x2', '\x2', - '\x2', '\x98', '\x99', '\x3', '\x2', '\x2', '\x2', '\x99', '\x9A', '\x3', - '\x2', '\x2', '\x2', '\x9A', '\x9C', '\x5', 'X', '-', '\x2', '\x9B', '\x98', - '\x3', '\x2', '\x2', '\x2', '\x9B', '\x9C', '\x3', '\x2', '\x2', '\x2', - '\x9C', '\xA2', '\x3', '\x2', '\x2', '\x2', '\x9D', '\x9E', '\x5', 'X', - '-', '\x2', '\x9E', '\x9F', '\a', ',', '\x2', '\x2', '\x9F', '\xA0', '\x5', - '\x18', '\r', '\x2', '\xA0', '\xA2', '\x3', '\x2', '\x2', '\x2', '\xA1', - '\x95', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x9D', '\x3', '\x2', '\x2', - '\x2', '\xA2', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA3', '\xA4', '\f', - '\x3', '\x2', '\x2', '\xA4', '\xA5', '\a', '-', '\x2', '\x2', '\xA5', - '\xA7', '\x5', '\x16', '\f', '\x4', '\xA6', '\xA3', '\x3', '\x2', '\x2', - '\x2', '\xA7', '\xAA', '\x3', '\x2', '\x2', '\x2', '\xA8', '\xA6', '\x3', - '\x2', '\x2', '\x2', '\xA8', '\xA9', '\x3', '\x2', '\x2', '\x2', '\xA9', - '\x17', '\x3', '\x2', '\x2', '\x2', '\xAA', '\xA8', '\x3', '\x2', '\x2', - '\x2', '\xAB', '\xAD', '\x5', 'X', '-', '\x2', '\xAC', '\xAE', '\x5', - '\x1A', '\xE', '\x2', '\xAD', '\xAC', '\x3', '\x2', '\x2', '\x2', '\xAD', - '\xAE', '\x3', '\x2', '\x2', '\x2', '\xAE', '\xB4', '\x3', '\x2', '\x2', - '\x2', '\xAF', '\xB0', '\a', '\x5', '\x2', '\x2', '\xB0', '\xB1', '\x5', - '\x4', '\x3', '\x2', '\xB1', '\xB2', '\a', '\x6', '\x2', '\x2', '\xB2', - '\xB4', '\x3', '\x2', '\x2', '\x2', '\xB3', '\xAB', '\x3', '\x2', '\x2', - '\x2', '\xB3', '\xAF', '\x3', '\x2', '\x2', '\x2', '\xB4', '\x19', '\x3', - '\x2', '\x2', '\x2', '\xB5', '\xC3', '\b', '\xE', '\x1', '\x2', '\xB6', - '\xB7', '\f', '\x6', '\x2', '\x2', '\xB7', '\xB8', '\a', '\a', '\x2', - '\x2', '\xB8', '\xC2', '\x5', 'X', '-', '\x2', '\xB9', '\xBA', '\f', '\x5', - '\x2', '\x2', '\xBA', '\xBB', '\a', '\b', '\x2', '\x2', '\xBB', '\xBC', - '\a', '?', '\x2', '\x2', '\xBC', '\xC2', '\a', '\t', '\x2', '\x2', '\xBD', - '\xBE', '\f', '\x4', '\x2', '\x2', '\xBE', '\xBF', '\a', '\b', '\x2', - '\x2', '\xBF', '\xC0', '\a', '@', '\x2', '\x2', '\xC0', '\xC2', '\a', - '\t', '\x2', '\x2', '\xC1', '\xB6', '\x3', '\x2', '\x2', '\x2', '\xC1', - '\xB9', '\x3', '\x2', '\x2', '\x2', '\xC1', '\xBD', '\x3', '\x2', '\x2', - '\x2', '\xC2', '\xC5', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC1', '\x3', - '\x2', '\x2', '\x2', '\xC3', '\xC4', '\x3', '\x2', '\x2', '\x2', '\xC4', - '\x1B', '\x3', '\x2', '\x2', '\x2', '\xC5', '\xC3', '\x3', '\x2', '\x2', - '\x2', '\xC6', '\xC7', '\a', '=', '\x2', '\x2', '\xC7', '\xC8', '\x5', - '.', '\x18', '\x2', '\xC8', '\x1D', '\x3', '\x2', '\x2', '\x2', '\xC9', - '\xCA', '\a', '+', '\x2', '\x2', '\xCA', '\xCB', '\a', '$', '\x2', '\x2', - '\xCB', '\xCC', '\x5', 'R', '*', '\x2', '\xCC', '\x1F', '\x3', '\x2', - '\x2', '\x2', '\xCD', '\xCE', '\a', '\x35', '\x2', '\x2', '\xCE', '\xCF', - '\a', '$', '\x2', '\x2', '\xCF', '\xD0', '\x5', '\"', '\x12', '\x2', '\xD0', - '!', '\x3', '\x2', '\x2', '\x2', '\xD1', '\xD6', '\x5', '$', '\x13', '\x2', - '\xD2', '\xD3', '\a', '\x4', '\x2', '\x2', '\xD3', '\xD5', '\x5', '$', - '\x13', '\x2', '\xD4', '\xD2', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD8', - '\x3', '\x2', '\x2', '\x2', '\xD6', '\xD4', '\x3', '\x2', '\x2', '\x2', - '\xD6', '\xD7', '\x3', '\x2', '\x2', '\x2', '\xD7', '#', '\x3', '\x2', - '\x2', '\x2', '\xD8', '\xD6', '\x3', '\x2', '\x2', '\x2', '\xD9', '\xDB', - '\x5', '.', '\x18', '\x2', '\xDA', '\xDC', '\x5', '&', '\x14', '\x2', - '\xDB', '\xDA', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xDC', '\x3', '\x2', - '\x2', '\x2', '\xDC', '%', '\x3', '\x2', '\x2', '\x2', '\xDD', '\xDE', - '\t', '\x3', '\x2', '\x2', '\xDE', '\'', '\x3', '\x2', '\x2', '\x2', '\xDF', - '\xE0', '\a', '\x33', '\x2', '\x2', '\xE0', '\xE1', '\x5', '*', '\x16', - '\x2', '\xE1', '\xE2', '\a', '\x30', '\x2', '\x2', '\xE2', '\xE3', '\x5', + '\x2', 'w', '\a', '\x3', '\x2', '\x2', '\x2', 'x', 'y', '\a', ':', '\x2', + '\x2', 'y', 'z', '\t', '\x2', '\x2', '\x2', 'z', '\t', '\x3', '\x2', '\x2', + '\x2', '{', '\x7F', '\x5', '\f', '\a', '\x2', '|', '\x7F', '\x5', '\xE', + '\b', '\x2', '}', '\x7F', '\x5', '\x10', '\t', '\x2', '~', '{', '\x3', + '\x2', '\x2', '\x2', '~', '|', '\x3', '\x2', '\x2', '\x2', '~', '}', '\x3', + '\x2', '\x2', '\x2', '\x7F', '\v', '\x3', '\x2', '\x2', '\x2', '\x80', + '\x81', '\a', '\x3', '\x2', '\x2', '\x81', '\r', '\x3', '\x2', '\x2', + '\x2', '\x82', '\x83', '\a', '>', '\x2', '\x2', '\x83', '\x84', '\x5', + '.', '\x18', '\x2', '\x84', '\xF', '\x3', '\x2', '\x2', '\x2', '\x85', + '\x8A', '\x5', '\x12', '\n', '\x2', '\x86', '\x87', '\a', '\x4', '\x2', + '\x2', '\x87', '\x89', '\x5', '\x12', '\n', '\x2', '\x88', '\x86', '\x3', + '\x2', '\x2', '\x2', '\x89', '\x8C', '\x3', '\x2', '\x2', '\x2', '\x8A', + '\x88', '\x3', '\x2', '\x2', '\x2', '\x8A', '\x8B', '\x3', '\x2', '\x2', + '\x2', '\x8B', '\x11', '\x3', '\x2', '\x2', '\x2', '\x8C', '\x8A', '\x3', + '\x2', '\x2', '\x2', '\x8D', '\x90', '\x5', '.', '\x18', '\x2', '\x8E', + '\x8F', '\a', '!', '\x2', '\x2', '\x8F', '\x91', '\x5', 'X', '-', '\x2', + '\x90', '\x8E', '\x3', '\x2', '\x2', '\x2', '\x90', '\x91', '\x3', '\x2', + '\x2', '\x2', '\x91', '\x13', '\x3', '\x2', '\x2', '\x2', '\x92', '\x93', + '\a', '+', '\x2', '\x2', '\x93', '\x94', '\x5', '\x16', '\f', '\x2', '\x94', + '\x15', '\x3', '\x2', '\x2', '\x2', '\x95', '\x96', '\b', '\f', '\x1', + '\x2', '\x96', '\x9B', '\x5', '\x18', '\r', '\x2', '\x97', '\x99', '\a', + '!', '\x2', '\x2', '\x98', '\x97', '\x3', '\x2', '\x2', '\x2', '\x98', + '\x99', '\x3', '\x2', '\x2', '\x2', '\x99', '\x9A', '\x3', '\x2', '\x2', + '\x2', '\x9A', '\x9C', '\x5', 'X', '-', '\x2', '\x9B', '\x98', '\x3', + '\x2', '\x2', '\x2', '\x9B', '\x9C', '\x3', '\x2', '\x2', '\x2', '\x9C', + '\xA2', '\x3', '\x2', '\x2', '\x2', '\x9D', '\x9E', '\x5', 'X', '-', '\x2', + '\x9E', '\x9F', '\a', '-', '\x2', '\x2', '\x9F', '\xA0', '\x5', '\x18', + '\r', '\x2', '\xA0', '\xA2', '\x3', '\x2', '\x2', '\x2', '\xA1', '\x95', + '\x3', '\x2', '\x2', '\x2', '\xA1', '\x9D', '\x3', '\x2', '\x2', '\x2', + '\xA2', '\xA8', '\x3', '\x2', '\x2', '\x2', '\xA3', '\xA4', '\f', '\x3', + '\x2', '\x2', '\xA4', '\xA5', '\a', '.', '\x2', '\x2', '\xA5', '\xA7', + '\x5', '\x16', '\f', '\x4', '\xA6', '\xA3', '\x3', '\x2', '\x2', '\x2', + '\xA7', '\xAA', '\x3', '\x2', '\x2', '\x2', '\xA8', '\xA6', '\x3', '\x2', + '\x2', '\x2', '\xA8', '\xA9', '\x3', '\x2', '\x2', '\x2', '\xA9', '\x17', + '\x3', '\x2', '\x2', '\x2', '\xAA', '\xA8', '\x3', '\x2', '\x2', '\x2', + '\xAB', '\xAD', '\x5', 'X', '-', '\x2', '\xAC', '\xAE', '\x5', '\x1A', + '\xE', '\x2', '\xAD', '\xAC', '\x3', '\x2', '\x2', '\x2', '\xAD', '\xAE', + '\x3', '\x2', '\x2', '\x2', '\xAE', '\xB4', '\x3', '\x2', '\x2', '\x2', + '\xAF', '\xB0', '\a', '\x5', '\x2', '\x2', '\xB0', '\xB1', '\x5', '\x4', + '\x3', '\x2', '\xB1', '\xB2', '\a', '\x6', '\x2', '\x2', '\xB2', '\xB4', + '\x3', '\x2', '\x2', '\x2', '\xB3', '\xAB', '\x3', '\x2', '\x2', '\x2', + '\xB3', '\xAF', '\x3', '\x2', '\x2', '\x2', '\xB4', '\x19', '\x3', '\x2', + '\x2', '\x2', '\xB5', '\xC3', '\b', '\xE', '\x1', '\x2', '\xB6', '\xB7', + '\f', '\x6', '\x2', '\x2', '\xB7', '\xB8', '\a', '\a', '\x2', '\x2', '\xB8', + '\xC2', '\x5', 'X', '-', '\x2', '\xB9', '\xBA', '\f', '\x5', '\x2', '\x2', + '\xBA', '\xBB', '\a', '\b', '\x2', '\x2', '\xBB', '\xBC', '\a', '\x41', + '\x2', '\x2', '\xBC', '\xC2', '\a', '\t', '\x2', '\x2', '\xBD', '\xBE', + '\f', '\x4', '\x2', '\x2', '\xBE', '\xBF', '\a', '\b', '\x2', '\x2', '\xBF', + '\xC0', '\a', '\x42', '\x2', '\x2', '\xC0', '\xC2', '\a', '\t', '\x2', + '\x2', '\xC1', '\xB6', '\x3', '\x2', '\x2', '\x2', '\xC1', '\xB9', '\x3', + '\x2', '\x2', '\x2', '\xC1', '\xBD', '\x3', '\x2', '\x2', '\x2', '\xC2', + '\xC5', '\x3', '\x2', '\x2', '\x2', '\xC3', '\xC1', '\x3', '\x2', '\x2', + '\x2', '\xC3', '\xC4', '\x3', '\x2', '\x2', '\x2', '\xC4', '\x1B', '\x3', + '\x2', '\x2', '\x2', '\xC5', '\xC3', '\x3', '\x2', '\x2', '\x2', '\xC6', + '\xC7', '\a', '?', '\x2', '\x2', '\xC7', '\xC8', '\x5', '.', '\x18', '\x2', + '\xC8', '\x1D', '\x3', '\x2', '\x2', '\x2', '\xC9', '\xCA', '\a', ',', + '\x2', '\x2', '\xCA', '\xCB', '\a', '$', '\x2', '\x2', '\xCB', '\xCC', + '\x5', 'R', '*', '\x2', '\xCC', '\x1F', '\x3', '\x2', '\x2', '\x2', '\xCD', + '\xCE', '\a', '\x37', '\x2', '\x2', '\xCE', '\xCF', '\a', '$', '\x2', + '\x2', '\xCF', '\xD0', '\x5', '\"', '\x12', '\x2', '\xD0', '!', '\x3', + '\x2', '\x2', '\x2', '\xD1', '\xD6', '\x5', '$', '\x13', '\x2', '\xD2', + '\xD3', '\a', '\x4', '\x2', '\x2', '\xD3', '\xD5', '\x5', '$', '\x13', + '\x2', '\xD4', '\xD2', '\x3', '\x2', '\x2', '\x2', '\xD5', '\xD8', '\x3', + '\x2', '\x2', '\x2', '\xD6', '\xD4', '\x3', '\x2', '\x2', '\x2', '\xD6', + '\xD7', '\x3', '\x2', '\x2', '\x2', '\xD7', '#', '\x3', '\x2', '\x2', + '\x2', '\xD8', '\xD6', '\x3', '\x2', '\x2', '\x2', '\xD9', '\xDB', '\x5', + '.', '\x18', '\x2', '\xDA', '\xDC', '\x5', '&', '\x14', '\x2', '\xDB', + '\xDA', '\x3', '\x2', '\x2', '\x2', '\xDB', '\xDC', '\x3', '\x2', '\x2', + '\x2', '\xDC', '%', '\x3', '\x2', '\x2', '\x2', '\xDD', '\xDE', '\t', + '\x3', '\x2', '\x2', '\xDE', '\'', '\x3', '\x2', '\x2', '\x2', '\xDF', + '\xE0', '\a', '\x35', '\x2', '\x2', '\xE0', '\xE1', '\x5', '*', '\x16', + '\x2', '\xE1', '\xE2', '\a', '\x32', '\x2', '\x2', '\xE2', '\xE3', '\x5', ',', '\x17', '\x2', '\xE3', ')', '\x3', '\x2', '\x2', '\x2', '\xE4', '\xE5', '\t', '\x2', '\x2', '\x2', '\xE5', '+', '\x3', '\x2', '\x2', '\x2', '\xE6', '\xE7', '\t', '\x2', '\x2', '\x2', '\xE7', '-', '\x3', '\x2', '\x2', '\x2', '\xE8', '\xE9', '\b', '\x18', '\x1', '\x2', '\xE9', '\xF4', '\x5', '\x30', '\x19', '\x2', '\xEA', '\xEC', '\x5', '\x38', '\x1D', '\x2', '\xEB', '\xED', - '\a', '\x31', '\x2', '\x2', '\xEC', '\xEB', '\x3', '\x2', '\x2', '\x2', + '\a', '\x33', '\x2', '\x2', '\xEC', '\xEB', '\x3', '\x2', '\x2', '\x2', '\xEC', '\xED', '\x3', '\x2', '\x2', '\x2', '\xED', '\xEE', '\x3', '\x2', '\x2', '\x2', '\xEE', '\xEF', '\a', '#', '\x2', '\x2', '\xEF', '\xF0', '\x5', '\x38', '\x1D', '\x2', '\xF0', '\xF1', '\a', '\x1F', '\x2', '\x2', @@ -4074,27 +4149,27 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int '\x2', '\x108', '\x111', '\x3', '\x2', '\x2', '\x2', '\x109', '\x10A', '\f', '\x4', '\x2', '\x2', '\x10A', '\x10B', '\a', '\x1F', '\x2', '\x2', '\x10B', '\x110', '\x5', '\x30', '\x19', '\x5', '\x10C', '\x10D', '\f', - '\x3', '\x2', '\x2', '\x10D', '\x10E', '\a', '\x34', '\x2', '\x2', '\x10E', + '\x3', '\x2', '\x2', '\x10D', '\x10E', '\a', '\x36', '\x2', '\x2', '\x10E', '\x110', '\x5', '\x30', '\x19', '\x4', '\x10F', '\x109', '\x3', '\x2', '\x2', '\x2', '\x10F', '\x10C', '\x3', '\x2', '\x2', '\x2', '\x110', '\x113', '\x3', '\x2', '\x2', '\x2', '\x111', '\x10F', '\x3', '\x2', '\x2', '\x2', '\x111', '\x112', '\x3', '\x2', '\x2', '\x2', '\x112', '\x31', '\x3', '\x2', '\x2', '\x2', '\x113', '\x111', '\x3', '\x2', '\x2', '\x2', '\x114', - '\x116', '\x5', '\x38', '\x1D', '\x2', '\x115', '\x117', '\a', '\x31', + '\x116', '\x5', '\x38', '\x1D', '\x2', '\x115', '\x117', '\a', '\x33', '\x2', '\x2', '\x116', '\x115', '\x3', '\x2', '\x2', '\x2', '\x116', '\x117', '\x3', '\x2', '\x2', '\x2', '\x117', '\x118', '\x3', '\x2', '\x2', '\x2', - '\x118', '\x119', '\a', ',', '\x2', '\x2', '\x119', '\x11A', '\a', '\x5', + '\x118', '\x119', '\a', '-', '\x2', '\x2', '\x119', '\x11A', '\a', '\x5', '\x2', '\x2', '\x11A', '\x11B', '\x5', 'R', '*', '\x2', '\x11B', '\x11C', '\a', '\x6', '\x2', '\x2', '\x11C', '\x33', '\x3', '\x2', '\x2', '\x2', '\x11D', '\x11F', '\x5', '\x38', '\x1D', '\x2', '\x11E', '\x120', '\a', - '\x31', '\x2', '\x2', '\x11F', '\x11E', '\x3', '\x2', '\x2', '\x2', '\x11F', + '\x33', '\x2', '\x2', '\x11F', '\x11E', '\x3', '\x2', '\x2', '\x2', '\x11F', '\x120', '\x3', '\x2', '\x2', '\x2', '\x120', '\x121', '\x3', '\x2', '\x2', - '\x2', '\x121', '\x122', '\a', '/', '\x2', '\x2', '\x122', '\x124', '\x5', - '\x38', '\x1D', '\x2', '\x123', '\x125', '\x5', '\x36', '\x1C', '\x2', - '\x124', '\x123', '\x3', '\x2', '\x2', '\x2', '\x124', '\x125', '\x3', - '\x2', '\x2', '\x2', '\x125', '\x35', '\x3', '\x2', '\x2', '\x2', '\x126', - '\x127', '\a', '\'', '\x2', '\x2', '\x127', '\x128', '\a', '@', '\x2', - '\x2', '\x128', '\x37', '\x3', '\x2', '\x2', '\x2', '\x129', '\x12A', + '\x2', '\x121', '\x122', '\a', '\x31', '\x2', '\x2', '\x122', '\x124', + '\x5', '\x38', '\x1D', '\x2', '\x123', '\x125', '\x5', '\x36', '\x1C', + '\x2', '\x124', '\x123', '\x3', '\x2', '\x2', '\x2', '\x124', '\x125', + '\x3', '\x2', '\x2', '\x2', '\x125', '\x35', '\x3', '\x2', '\x2', '\x2', + '\x126', '\x127', '\a', '\'', '\x2', '\x2', '\x127', '\x128', '\a', '\x42', + '\x2', '\x2', '\x128', '\x37', '\x3', '\x2', '\x2', '\x2', '\x129', '\x12A', '\b', '\x1D', '\x1', '\x2', '\x12A', '\x12B', '\x5', 'J', '&', '\x2', '\x12B', '\x14E', '\x3', '\x2', '\x2', '\x2', '\x12C', '\x12D', '\f', '\n', '\x2', '\x2', '\x12D', '\x12E', '\x5', ':', '\x1E', '\x2', '\x12E', @@ -4140,87 +4215,95 @@ private bool primary_expression_sempred(Primary_expressionContext _localctx, int '\x3', '\x2', '\x2', '\x2', '\x165', '\x162', '\x3', '\x2', '\x2', '\x2', '\x166', 'K', '\x3', '\x2', '\x2', '\x2', '\x167', '\x168', '\t', '\b', '\x2', '\x2', '\x168', 'M', '\x3', '\x2', '\x2', '\x2', '\x169', '\x16A', - '\b', '(', '\x1', '\x2', '\x16A', '\x190', '\x5', 'X', '-', '\x2', '\x16B', - '\x190', '\a', '\x42', '\x2', '\x2', '\x16C', '\x190', '\x5', 'Z', '.', + '\b', '(', '\x1', '\x2', '\x16A', '\x19A', '\x5', 'X', '-', '\x2', '\x16B', + '\x19A', '\a', '\x44', '\x2', '\x2', '\x16C', '\x19A', '\x5', 'Z', '.', '\x2', '\x16D', '\x16F', '\a', '\b', '\x2', '\x2', '\x16E', '\x170', '\x5', 'R', '*', '\x2', '\x16F', '\x16E', '\x3', '\x2', '\x2', '\x2', '\x16F', '\x170', '\x3', '\x2', '\x2', '\x2', '\x170', '\x171', '\x3', '\x2', '\x2', - '\x2', '\x171', '\x190', '\a', '\t', '\x2', '\x2', '\x172', '\x174', '\a', + '\x2', '\x171', '\x19A', '\a', '\t', '\x2', '\x2', '\x172', '\x174', '\a', '\x1C', '\x2', '\x2', '\x173', '\x175', '\x5', 'T', '+', '\x2', '\x174', '\x173', '\x3', '\x2', '\x2', '\x2', '\x174', '\x175', '\x3', '\x2', '\x2', - '\x2', '\x175', '\x176', '\x3', '\x2', '\x2', '\x2', '\x176', '\x190', + '\x2', '\x175', '\x176', '\x3', '\x2', '\x2', '\x2', '\x176', '\x19A', '\a', '\x1D', '\x2', '\x2', '\x177', '\x178', '\a', '\x5', '\x2', '\x2', '\x178', '\x179', '\x5', '.', '\x18', '\x2', '\x179', '\x17A', '\a', '\x6', - '\x2', '\x2', '\x17A', '\x190', '\x3', '\x2', '\x2', '\x2', '\x17B', '\x17C', + '\x2', '\x2', '\x17A', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x17B', '\x17C', '\a', '\x5', '\x2', '\x2', '\x17C', '\x17D', '\x5', '\x4', '\x3', '\x2', - '\x17D', '\x17E', '\a', '\x6', '\x2', '\x2', '\x17E', '\x190', '\x3', + '\x17D', '\x17E', '\a', '\x6', '\x2', '\x2', '\x17E', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x17F', '\x180', '\a', '(', '\x2', '\x2', '\x180', '\x181', '\a', '\x5', '\x2', '\x2', '\x181', '\x182', '\x5', '\x4', '\x3', - '\x2', '\x182', '\x183', '\a', '\x6', '\x2', '\x2', '\x183', '\x190', + '\x2', '\x182', '\x183', '\a', '\x6', '\x2', '\x2', '\x183', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x184', '\x185', '\a', ' ', '\x2', '\x2', '\x185', '\x186', '\a', '\x5', '\x2', '\x2', '\x186', '\x187', '\x5', '\x4', '\x3', '\x2', '\x187', '\x188', '\a', '\x6', '\x2', '\x2', '\x188', - '\x190', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\a', '\x1E', '\x2', + '\x19A', '\x3', '\x2', '\x2', '\x2', '\x189', '\x18A', '\a', '\x1E', '\x2', '\x2', '\x18A', '\x18B', '\a', '\x5', '\x2', '\x2', '\x18B', '\x18C', '\x5', '\x4', '\x3', '\x2', '\x18C', '\x18D', '\a', '\x6', '\x2', '\x2', - '\x18D', '\x190', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x190', '\x5', - 'P', ')', '\x2', '\x18F', '\x169', '\x3', '\x2', '\x2', '\x2', '\x18F', - '\x16B', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x16C', '\x3', '\x2', '\x2', - '\x2', '\x18F', '\x16D', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x172', - '\x3', '\x2', '\x2', '\x2', '\x18F', '\x177', '\x3', '\x2', '\x2', '\x2', - '\x18F', '\x17B', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x17F', '\x3', - '\x2', '\x2', '\x2', '\x18F', '\x184', '\x3', '\x2', '\x2', '\x2', '\x18F', - '\x189', '\x3', '\x2', '\x2', '\x2', '\x18F', '\x18E', '\x3', '\x2', '\x2', - '\x2', '\x190', '\x19B', '\x3', '\x2', '\x2', '\x2', '\x191', '\x192', - '\f', '\b', '\x2', '\x2', '\x192', '\x193', '\a', '\a', '\x2', '\x2', - '\x193', '\x19A', '\x5', 'X', '-', '\x2', '\x194', '\x195', '\f', '\a', - '\x2', '\x2', '\x195', '\x196', '\a', '\b', '\x2', '\x2', '\x196', '\x197', - '\x5', '.', '\x18', '\x2', '\x197', '\x198', '\a', '\t', '\x2', '\x2', - '\x198', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x199', '\x191', '\x3', - '\x2', '\x2', '\x2', '\x199', '\x194', '\x3', '\x2', '\x2', '\x2', '\x19A', - '\x19D', '\x3', '\x2', '\x2', '\x2', '\x19B', '\x199', '\x3', '\x2', '\x2', - '\x2', '\x19B', '\x19C', '\x3', '\x2', '\x2', '\x2', '\x19C', 'O', '\x3', - '\x2', '\x2', '\x2', '\x19D', '\x19B', '\x3', '\x2', '\x2', '\x2', '\x19E', - '\x19F', '\a', ':', '\x2', '\x2', '\x19F', '\x1A1', '\a', '\a', '\x2', - '\x2', '\x1A0', '\x19E', '\x3', '\x2', '\x2', '\x2', '\x1A0', '\x1A1', - '\x3', '\x2', '\x2', '\x2', '\x1A1', '\x1A2', '\x3', '\x2', '\x2', '\x2', - '\x1A2', '\x1A3', '\x5', 'X', '-', '\x2', '\x1A3', '\x1A5', '\a', '\x5', - '\x2', '\x2', '\x1A4', '\x1A6', '\x5', 'R', '*', '\x2', '\x1A5', '\x1A4', - '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1A6', '\x3', '\x2', '\x2', '\x2', - '\x1A6', '\x1A7', '\x3', '\x2', '\x2', '\x2', '\x1A7', '\x1A8', '\a', - '\x6', '\x2', '\x2', '\x1A8', '\x1B6', '\x3', '\x2', '\x2', '\x2', '\x1A9', - '\x1AA', '\a', '.', '\x2', '\x2', '\x1AA', '\x1AC', '\a', '\x5', '\x2', - '\x2', '\x1AB', '\x1AD', '\x5', 'R', '*', '\x2', '\x1AC', '\x1AB', '\x3', - '\x2', '\x2', '\x2', '\x1AC', '\x1AD', '\x3', '\x2', '\x2', '\x2', '\x1AD', - '\x1AE', '\x3', '\x2', '\x2', '\x2', '\x1AE', '\x1B6', '\a', '\x6', '\x2', - '\x2', '\x1AF', '\x1B0', '\a', '\x36', '\x2', '\x2', '\x1B0', '\x1B2', - '\a', '\x5', '\x2', '\x2', '\x1B1', '\x1B3', '\x5', 'R', '*', '\x2', '\x1B2', - '\x1B1', '\x3', '\x2', '\x2', '\x2', '\x1B2', '\x1B3', '\x3', '\x2', '\x2', - '\x2', '\x1B3', '\x1B4', '\x3', '\x2', '\x2', '\x2', '\x1B4', '\x1B6', - '\a', '\x6', '\x2', '\x2', '\x1B5', '\x1A0', '\x3', '\x2', '\x2', '\x2', - '\x1B5', '\x1A9', '\x3', '\x2', '\x2', '\x2', '\x1B5', '\x1AF', '\x3', - '\x2', '\x2', '\x2', '\x1B6', 'Q', '\x3', '\x2', '\x2', '\x2', '\x1B7', - '\x1BC', '\x5', '.', '\x18', '\x2', '\x1B8', '\x1B9', '\a', '\x4', '\x2', - '\x2', '\x1B9', '\x1BB', '\x5', '.', '\x18', '\x2', '\x1BA', '\x1B8', - '\x3', '\x2', '\x2', '\x2', '\x1BB', '\x1BE', '\x3', '\x2', '\x2', '\x2', - '\x1BC', '\x1BA', '\x3', '\x2', '\x2', '\x2', '\x1BC', '\x1BD', '\x3', - '\x2', '\x2', '\x2', '\x1BD', 'S', '\x3', '\x2', '\x2', '\x2', '\x1BE', - '\x1BC', '\x3', '\x2', '\x2', '\x2', '\x1BF', '\x1C4', '\x5', 'V', ',', - '\x2', '\x1C0', '\x1C1', '\a', '\x4', '\x2', '\x2', '\x1C1', '\x1C3', - '\x5', 'V', ',', '\x2', '\x1C2', '\x1C0', '\x3', '\x2', '\x2', '\x2', - '\x1C3', '\x1C6', '\x3', '\x2', '\x2', '\x2', '\x1C4', '\x1C2', '\x3', - '\x2', '\x2', '\x2', '\x1C4', '\x1C5', '\x3', '\x2', '\x2', '\x2', '\x1C5', - 'U', '\x3', '\x2', '\x2', '\x2', '\x1C6', '\x1C4', '\x3', '\x2', '\x2', - '\x2', '\x1C7', '\x1C8', '\a', '@', '\x2', '\x2', '\x1C8', '\x1C9', '\a', - '\v', '\x2', '\x2', '\x1C9', '\x1CA', '\x5', '.', '\x18', '\x2', '\x1CA', - 'W', '\x3', '\x2', '\x2', '\x2', '\x1CB', '\x1CC', '\t', '\t', '\x2', - '\x2', '\x1CC', 'Y', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1CE', '\t', - '\n', '\x2', '\x2', '\x1CE', '[', '\x3', '\x2', '\x2', '\x2', '/', '\x61', - '\x64', 'g', 'j', 'm', 'q', 't', '~', '\x8A', '\x90', '\x98', '\x9B', - '\xA1', '\xA8', '\xAD', '\xB3', '\xC1', '\xC3', '\xD6', '\xDB', '\xEC', - '\xF3', '\xFE', '\x100', '\x107', '\x10F', '\x111', '\x116', '\x11F', - '\x124', '\x14C', '\x14E', '\x165', '\x16F', '\x174', '\x18F', '\x199', - '\x19B', '\x1A0', '\x1A5', '\x1AC', '\x1B2', '\x1B5', '\x1BC', '\x1C4', + '\x18D', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x18E', '\x18F', '\a', + ')', '\x2', '\x2', '\x18F', '\x190', '\a', '\x5', '\x2', '\x2', '\x190', + '\x191', '\x5', '\x4', '\x3', '\x2', '\x191', '\x192', '\a', '\x6', '\x2', + '\x2', '\x192', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x193', '\x194', + '\a', '/', '\x2', '\x2', '\x194', '\x195', '\a', '\x5', '\x2', '\x2', + '\x195', '\x196', '\x5', '\x4', '\x3', '\x2', '\x196', '\x197', '\a', + '\x6', '\x2', '\x2', '\x197', '\x19A', '\x3', '\x2', '\x2', '\x2', '\x198', + '\x19A', '\x5', 'P', ')', '\x2', '\x199', '\x169', '\x3', '\x2', '\x2', + '\x2', '\x199', '\x16B', '\x3', '\x2', '\x2', '\x2', '\x199', '\x16C', + '\x3', '\x2', '\x2', '\x2', '\x199', '\x16D', '\x3', '\x2', '\x2', '\x2', + '\x199', '\x172', '\x3', '\x2', '\x2', '\x2', '\x199', '\x177', '\x3', + '\x2', '\x2', '\x2', '\x199', '\x17B', '\x3', '\x2', '\x2', '\x2', '\x199', + '\x17F', '\x3', '\x2', '\x2', '\x2', '\x199', '\x184', '\x3', '\x2', '\x2', + '\x2', '\x199', '\x189', '\x3', '\x2', '\x2', '\x2', '\x199', '\x18E', + '\x3', '\x2', '\x2', '\x2', '\x199', '\x193', '\x3', '\x2', '\x2', '\x2', + '\x199', '\x198', '\x3', '\x2', '\x2', '\x2', '\x19A', '\x1A5', '\x3', + '\x2', '\x2', '\x2', '\x19B', '\x19C', '\f', '\n', '\x2', '\x2', '\x19C', + '\x19D', '\a', '\a', '\x2', '\x2', '\x19D', '\x1A4', '\x5', 'X', '-', + '\x2', '\x19E', '\x19F', '\f', '\t', '\x2', '\x2', '\x19F', '\x1A0', '\a', + '\b', '\x2', '\x2', '\x1A0', '\x1A1', '\x5', '.', '\x18', '\x2', '\x1A1', + '\x1A2', '\a', '\t', '\x2', '\x2', '\x1A2', '\x1A4', '\x3', '\x2', '\x2', + '\x2', '\x1A3', '\x19B', '\x3', '\x2', '\x2', '\x2', '\x1A3', '\x19E', + '\x3', '\x2', '\x2', '\x2', '\x1A4', '\x1A7', '\x3', '\x2', '\x2', '\x2', + '\x1A5', '\x1A3', '\x3', '\x2', '\x2', '\x2', '\x1A5', '\x1A6', '\x3', + '\x2', '\x2', '\x2', '\x1A6', 'O', '\x3', '\x2', '\x2', '\x2', '\x1A7', + '\x1A5', '\x3', '\x2', '\x2', '\x2', '\x1A8', '\x1A9', '\a', '<', '\x2', + '\x2', '\x1A9', '\x1AB', '\a', '\a', '\x2', '\x2', '\x1AA', '\x1A8', '\x3', + '\x2', '\x2', '\x2', '\x1AA', '\x1AB', '\x3', '\x2', '\x2', '\x2', '\x1AB', + '\x1AC', '\x3', '\x2', '\x2', '\x2', '\x1AC', '\x1AD', '\x5', 'X', '-', + '\x2', '\x1AD', '\x1AF', '\a', '\x5', '\x2', '\x2', '\x1AE', '\x1B0', + '\x5', 'R', '*', '\x2', '\x1AF', '\x1AE', '\x3', '\x2', '\x2', '\x2', + '\x1AF', '\x1B0', '\x3', '\x2', '\x2', '\x2', '\x1B0', '\x1B1', '\x3', + '\x2', '\x2', '\x2', '\x1B1', '\x1B2', '\a', '\x6', '\x2', '\x2', '\x1B2', + '\x1C0', '\x3', '\x2', '\x2', '\x2', '\x1B3', '\x1B4', '\a', '\x30', '\x2', + '\x2', '\x1B4', '\x1B6', '\a', '\x5', '\x2', '\x2', '\x1B5', '\x1B7', + '\x5', 'R', '*', '\x2', '\x1B6', '\x1B5', '\x3', '\x2', '\x2', '\x2', + '\x1B6', '\x1B7', '\x3', '\x2', '\x2', '\x2', '\x1B7', '\x1B8', '\x3', + '\x2', '\x2', '\x2', '\x1B8', '\x1C0', '\a', '\x6', '\x2', '\x2', '\x1B9', + '\x1BA', '\a', '\x38', '\x2', '\x2', '\x1BA', '\x1BC', '\a', '\x5', '\x2', + '\x2', '\x1BB', '\x1BD', '\x5', 'R', '*', '\x2', '\x1BC', '\x1BB', '\x3', + '\x2', '\x2', '\x2', '\x1BC', '\x1BD', '\x3', '\x2', '\x2', '\x2', '\x1BD', + '\x1BE', '\x3', '\x2', '\x2', '\x2', '\x1BE', '\x1C0', '\a', '\x6', '\x2', + '\x2', '\x1BF', '\x1AA', '\x3', '\x2', '\x2', '\x2', '\x1BF', '\x1B3', + '\x3', '\x2', '\x2', '\x2', '\x1BF', '\x1B9', '\x3', '\x2', '\x2', '\x2', + '\x1C0', 'Q', '\x3', '\x2', '\x2', '\x2', '\x1C1', '\x1C6', '\x5', '.', + '\x18', '\x2', '\x1C2', '\x1C3', '\a', '\x4', '\x2', '\x2', '\x1C3', '\x1C5', + '\x5', '.', '\x18', '\x2', '\x1C4', '\x1C2', '\x3', '\x2', '\x2', '\x2', + '\x1C5', '\x1C8', '\x3', '\x2', '\x2', '\x2', '\x1C6', '\x1C4', '\x3', + '\x2', '\x2', '\x2', '\x1C6', '\x1C7', '\x3', '\x2', '\x2', '\x2', '\x1C7', + 'S', '\x3', '\x2', '\x2', '\x2', '\x1C8', '\x1C6', '\x3', '\x2', '\x2', + '\x2', '\x1C9', '\x1CE', '\x5', 'V', ',', '\x2', '\x1CA', '\x1CB', '\a', + '\x4', '\x2', '\x2', '\x1CB', '\x1CD', '\x5', 'V', ',', '\x2', '\x1CC', + '\x1CA', '\x3', '\x2', '\x2', '\x2', '\x1CD', '\x1D0', '\x3', '\x2', '\x2', + '\x2', '\x1CE', '\x1CC', '\x3', '\x2', '\x2', '\x2', '\x1CE', '\x1CF', + '\x3', '\x2', '\x2', '\x2', '\x1CF', 'U', '\x3', '\x2', '\x2', '\x2', + '\x1D0', '\x1CE', '\x3', '\x2', '\x2', '\x2', '\x1D1', '\x1D2', '\a', + '\x42', '\x2', '\x2', '\x1D2', '\x1D3', '\a', '\v', '\x2', '\x2', '\x1D3', + '\x1D4', '\x5', '.', '\x18', '\x2', '\x1D4', 'W', '\x3', '\x2', '\x2', + '\x2', '\x1D5', '\x1D6', '\t', '\t', '\x2', '\x2', '\x1D6', 'Y', '\x3', + '\x2', '\x2', '\x2', '\x1D7', '\x1D8', '\t', '\n', '\x2', '\x2', '\x1D8', + '[', '\x3', '\x2', '\x2', '\x2', '/', '\x61', '\x64', 'g', 'j', 'm', 'q', + 't', '~', '\x8A', '\x90', '\x98', '\x9B', '\xA1', '\xA8', '\xAD', '\xB3', + '\xC1', '\xC3', '\xD6', '\xDB', '\xEC', '\xF3', '\xFE', '\x100', '\x107', + '\x10F', '\x111', '\x116', '\x11F', '\x124', '\x14C', '\x14E', '\x165', + '\x16F', '\x174', '\x199', '\x1A3', '\x1A5', '\x1AA', '\x1AF', '\x1B6', + '\x1BC', '\x1BF', '\x1C6', '\x1CE', }; public static readonly ATN _ATN = diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 744d98bf44..e276466f9d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -1004,6 +1004,12 @@ public override bool Visit(SqlExistsScalarExpression sqlExistsScalarExpression) return false; } + public override bool Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + public override bool Visit(SqlFunctionCallScalarExpression sqlFunctionCallScalarExpression) { return !sqlFunctionCallScalarExpression.IsUdf && @@ -1021,6 +1027,12 @@ public override bool Visit(SqlInScalarExpression sqlInScalarExpression) return hasAggregates; } + public override bool Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + public override bool Visit(SqlLiteralScalarExpression sqlLiteralScalarExpression) { return false; diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFirstScalarExpression.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFirstScalarExpression.cs new file mode 100644 index 0000000000..556da872e8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFirstScalarExpression.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SqlObjects +{ + using System; + using Microsoft.Azure.Cosmos.SqlObjects.Visitors; + +#if INTERNAL +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member +#pragma warning disable SA1600 // Elements should be documented + public +#else + internal +#endif + sealed class SqlFirstScalarExpression : SqlScalarExpression + { + private SqlFirstScalarExpression(SqlQuery subquery) + { + this.Subquery = subquery ?? throw new ArgumentNullException(nameof(subquery)); + } + + public SqlQuery Subquery { get; } + + public static SqlFirstScalarExpression Create(SqlQuery subquery) => new SqlFirstScalarExpression(subquery); + + public override void Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor, T input) => visitor.Visit(this, input); + + public override void Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor, T input) => visitor.Visit(this, input); + } +} diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlLastScalarExpression.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlLastScalarExpression.cs new file mode 100644 index 0000000000..36707d1c80 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlLastScalarExpression.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SqlObjects +{ + using System; + using Microsoft.Azure.Cosmos.SqlObjects.Visitors; + +#if INTERNAL +#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member +#pragma warning disable SA1600 // Elements should be documented + public +#else + internal +#endif + sealed class SqlLastScalarExpression : SqlScalarExpression + { + private SqlLastScalarExpression(SqlQuery subquery) + { + this.Subquery = subquery ?? throw new ArgumentNullException(nameof(subquery)); + } + + public SqlQuery Subquery { get; } + + public static SqlLastScalarExpression Create(SqlQuery subquery) => new SqlLastScalarExpression(subquery); + + public override void Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlObjectVisitor visitor, T input) => visitor.Visit(this, input); + + public override void Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor) => visitor.Visit(this); + + public override TResult Accept(SqlScalarExpressionVisitor visitor, T input) => visitor.Visit(this, input); + } +} diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs index 3a9bf01970..8d7770ba9e 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectEqualityVisitor.cs @@ -231,6 +231,21 @@ public override bool Visit(SqlExistsScalarExpression first, SqlObject secondAsOb return true; } + public override bool Visit(SqlFirstScalarExpression first, SqlObject secondAsObject) + { + if (!(secondAsObject is SqlFirstScalarExpression second)) + { + return false; + } + + if (!Equals(first.Subquery, second.Subquery)) + { + return false; + } + + return true; + } + public override bool Visit(SqlFromClause first, SqlObject secondAsObject) { if (!(secondAsObject is SqlFromClause second)) @@ -386,6 +401,21 @@ public override bool Visit(SqlJoinCollectionExpression first, SqlObject secondAs return true; } + public override bool Visit(SqlLastScalarExpression first, SqlObject secondAsObject) + { + if (!(secondAsObject is SqlLastScalarExpression second)) + { + return false; + } + + if (!Equals(first.Subquery, second.Subquery)) + { + return false; + } + + return true; + } + public override bool Visit(SqlLikeScalarExpression first, SqlObject secondAsObject) { if (!(secondAsObject is SqlLikeScalarExpression second)) diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs index dfbab84bc0..f4f55009ec 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectHasher.cs @@ -25,6 +25,7 @@ internal sealed class SqlObjectHasher : SqlObjectVisitor private const int SqlCoalesceScalarExpressionHashCode = -1400659633; private const int SqlConditionalScalarExpressionHashCode = -421337832; private const int SqlExistsScalarExpressionHashCode = 1168675587; + private const int SqlFirstScalarExpressionHashCode = -754458752; private const int SqlFromClauseHashCode = 52588336; private const int SqlFunctionCallScalarExpressionHashCode = 496783446; private const int SqlFunctionCallScalarExpressionUdfHashCode = 1547906315; @@ -35,6 +36,7 @@ internal sealed class SqlObjectHasher : SqlObjectVisitor private const int SqlInScalarExpressionHashCode = 1439386783; private const int SqlInScalarExpressionNotHashCode = -1131398119; private const int SqlJoinCollectionExpressionHashCode = 1000382226; + private const int SqlLastScalarExpressionHashCode = 2018370813; private const int SqlLikeScalarExpressionHashCode = 317861; private const int SqlLimitSpecHashCode = 92601316; private const int SqlLiteralScalarExpressionHashCode = -158339101; @@ -207,6 +209,13 @@ public override int Visit(SqlExistsScalarExpression sqlExistsScalarExpression) return hashCode; } + public override int Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + int hashCode = SqlFirstScalarExpressionHashCode; + hashCode = CombineHashes(hashCode, sqlFirstScalarExpression.Subquery.Accept(this)); + return hashCode; + } + public override int Visit(SqlFromClause sqlFromClause) { int hashCode = SqlFromClauseHashCode; @@ -298,6 +307,13 @@ public override int Visit(SqlJoinCollectionExpression sqlJoinCollectionExpressio return hashCode; } + public override int Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + int hashCode = SqlLastScalarExpressionHashCode; + hashCode = CombineHashes(hashCode, sqlLastScalarExpression.Subquery.Accept(this)); + return hashCode; + } + public override int Visit(SqlLimitSpec sqlObject) { int hashCode = SqlLimitSpecHashCode; diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs index 5e6faaef45..2120f16567 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectObfuscator.cs @@ -46,7 +46,7 @@ public override SqlObject Visit(SqlAliasedCollectionExpression sqlAliasedCollect public override SqlObject Visit(SqlAllScalarExpression sqlAllScalarExpression) { - return SqlExistsScalarExpression.Create(sqlAllScalarExpression.Subquery.Accept(this) as SqlQuery); + return SqlAllScalarExpression.Create(sqlAllScalarExpression.Subquery.Accept(this) as SqlQuery); } public override SqlObject Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) @@ -115,6 +115,11 @@ public override SqlObject Visit(SqlExistsScalarExpression sqlExistsScalarExpress return SqlExistsScalarExpression.Create(sqlExistsScalarExpression.Subquery.Accept(this) as SqlQuery); } + public override SqlObject Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + return SqlFirstScalarExpression.Create(sqlFirstScalarExpression.Subquery.Accept(this) as SqlQuery); + } + public override SqlObject Visit(SqlFromClause sqlFromClause) { return SqlFromClause.Create(sqlFromClause.Expression.Accept(this) as SqlCollectionExpression); @@ -189,6 +194,11 @@ public override SqlObject Visit(SqlJoinCollectionExpression sqlJoinCollectionExp sqlJoinCollectionExpression.Right.Accept(this) as SqlCollectionExpression); } + public override SqlObject Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + return SqlLastScalarExpression.Create(sqlLastScalarExpression.Subquery.Accept(this) as SqlQuery); + } + public override SqlObject Visit(SqlLikeScalarExpression sqlLikeScalarExpression) { return SqlLikeScalarExpression.Create( diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs index 75076e512c..a29435744d 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs @@ -154,6 +154,14 @@ public override void Visit(SqlExistsScalarExpression sqlExistsScalarExpression) this.WriteEndContext(")"); } + public override void Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + this.writer.Write("FIRST"); + this.WriteStartContext("("); + sqlFirstScalarExpression.Subquery.Accept(this); + this.WriteEndContext(")"); + } + public override void Visit(SqlFromClause sqlFromClause) { this.writer.Write("FROM "); @@ -284,6 +292,14 @@ public override void Visit(SqlJoinCollectionExpression sqlJoinCollectionExpressi sqlJoinCollectionExpression.Right.Accept(this); } + public override void Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + this.writer.Write("LAST"); + this.WriteStartContext("("); + sqlLastScalarExpression.Subquery.Accept(this); + this.WriteEndContext(")"); + } + public override void Visit(SqlLimitSpec sqlObject) { this.writer.Write("LIMIT "); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs index d8d8899395..3dfe3a9193 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor.cs @@ -24,6 +24,7 @@ abstract class SqlObjectVisitor public abstract void Visit(SqlCoalesceScalarExpression sqlObject); public abstract void Visit(SqlConditionalScalarExpression sqlObject); public abstract void Visit(SqlExistsScalarExpression sqlObject); + public abstract void Visit(SqlFirstScalarExpression sqlObject); public abstract void Visit(SqlFromClause sqlObject); public abstract void Visit(SqlFunctionCallScalarExpression sqlObject); public abstract void Visit(SqlGroupByClause sqlObject); @@ -32,6 +33,7 @@ abstract class SqlObjectVisitor public abstract void Visit(SqlInputPathCollection sqlObject); public abstract void Visit(SqlInScalarExpression sqlObject); public abstract void Visit(SqlJoinCollectionExpression sqlObject); + public abstract void Visit(SqlLastScalarExpression sqlObject); public abstract void Visit(SqlLikeScalarExpression sqlObject); public abstract void Visit(SqlLimitSpec sqlObject); public abstract void Visit(SqlLiteralScalarExpression sqlObject); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs index 3ba9878ae6..449cd6adaf 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TArg,TOutput}.cs @@ -24,6 +24,7 @@ abstract class SqlObjectVisitor public abstract TOutput Visit(SqlCoalesceScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlConditionalScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlExistsScalarExpression sqlObject, TArg input); + public abstract TOutput Visit(SqlFirstScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlFromClause sqlObject, TArg input); public abstract TOutput Visit(SqlFunctionCallScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlGroupByClause sqlObject, TArg input); @@ -32,6 +33,7 @@ abstract class SqlObjectVisitor public abstract TOutput Visit(SqlInputPathCollection sqlObject, TArg input); public abstract TOutput Visit(SqlInScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlJoinCollectionExpression sqlObject, TArg input); + public abstract TOutput Visit(SqlLastScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlLikeScalarExpression sqlObject, TArg input); public abstract TOutput Visit(SqlLimitSpec sqlObject, TArg input); public abstract TOutput Visit(SqlLiteralScalarExpression sqlObject, TArg input); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs index 6f0ce75e99..3d1000a171 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectVisitor{TResult}.cs @@ -24,6 +24,7 @@ abstract class SqlObjectVisitor public abstract TResult Visit(SqlCoalesceScalarExpression sqlObject); public abstract TResult Visit(SqlConditionalScalarExpression sqlObject); public abstract TResult Visit(SqlExistsScalarExpression sqlObject); + public abstract TResult Visit(SqlFirstScalarExpression sqlObject); public abstract TResult Visit(SqlFromClause sqlObject); public abstract TResult Visit(SqlFunctionCallScalarExpression sqlObject); public abstract TResult Visit(SqlGroupByClause sqlObject); @@ -31,6 +32,7 @@ abstract class SqlObjectVisitor public abstract TResult Visit(SqlIdentifierPathExpression sqlObject); public abstract TResult Visit(SqlInputPathCollection sqlObject); public abstract TResult Visit(SqlJoinCollectionExpression sqlObject); + public abstract TResult Visit(SqlLastScalarExpression sqlObject); public abstract TResult Visit(SqlLikeScalarExpression sqlObject); public abstract TResult Visit(SqlInScalarExpression sqlObject); public abstract TResult Visit(SqlLimitSpec sqlObject); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs index 8e6e75b7f0..d807395055 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor.cs @@ -20,8 +20,10 @@ abstract class SqlScalarExpressionVisitor public abstract void Visit(SqlCoalesceScalarExpression scalarExpression); public abstract void Visit(SqlConditionalScalarExpression scalarExpression); public abstract void Visit(SqlExistsScalarExpression scalarExpression); + public abstract void Visit(SqlFirstScalarExpression scalarExpression); public abstract void Visit(SqlFunctionCallScalarExpression scalarExpression); public abstract void Visit(SqlInScalarExpression scalarExpression); + public abstract void Visit(SqlLastScalarExpression scalarExpression); public abstract void Visit(SqlLikeScalarExpression scalarExpression); public abstract void Visit(SqlLiteralScalarExpression scalarExpression); public abstract void Visit(SqlMemberIndexerScalarExpression scalarExpression); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs index ff5cdbc019..256482b151 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TArg,TOutput}.cs @@ -21,8 +21,10 @@ abstract class SqlScalarExpressionVisitor public abstract TOutput Visit(SqlCoalesceScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlConditionalScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlExistsScalarExpression scalarExpression, TArg input); + public abstract TOutput Visit(SqlFirstScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlFunctionCallScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlInScalarExpression scalarExpression, TArg input); + public abstract TOutput Visit(SqlLastScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlLikeScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlLiteralScalarExpression scalarExpression, TArg input); public abstract TOutput Visit(SqlMemberIndexerScalarExpression scalarExpression, TArg input); diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs index bdc7b5f04f..e419b9758d 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlScalarExpressionVisitor{TResult}.cs @@ -21,8 +21,10 @@ abstract class SqlScalarExpressionVisitor public abstract TResult Visit(SqlCoalesceScalarExpression scalarExpression); public abstract TResult Visit(SqlConditionalScalarExpression scalarExpression); public abstract TResult Visit(SqlExistsScalarExpression scalarExpression); + public abstract TResult Visit(SqlFirstScalarExpression scalarExpression); public abstract TResult Visit(SqlFunctionCallScalarExpression scalarExpression); public abstract TResult Visit(SqlInScalarExpression scalarExpression); + public abstract TResult Visit(SqlLastScalarExpression scalarExpression); public abstract TResult Visit(SqlLikeScalarExpression scalarExpression); public abstract TResult Visit(SqlLiteralScalarExpression scalarExpression); public abstract TResult Visit(SqlMemberIndexerScalarExpression scalarExpression); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.First.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.First.xml new file mode 100644 index 0000000000..ae098baddc --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.First.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.Last.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.Last.xml new file mode 100644 index 0000000000..68b61ba3f1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/AggregateSubquerySqlParserBaselineTests.Last.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.First.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.First.xml new file mode 100644 index 0000000000..10b917f519 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.First.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.Last.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.Last.xml new file mode 100644 index 0000000000..ba5694ca80 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.Last.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index dc5f2c8e41..1d4e4e166c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -9,7 +9,7 @@ false false Microsoft.Azure.Cosmos.Tests - $(LangVersion) + $(LangVersion) @@ -174,12 +174,24 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -198,9 +210,9 @@ PreserveNewest - + PreserveNewest - + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs index ca162fc467..18c59fcc49 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionDector.cs @@ -111,6 +111,12 @@ public override bool Visit(SqlExistsScalarExpression sqlExistsScalarExpression) return false; } + public override bool Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + public override bool Visit(SqlFunctionCallScalarExpression sqlFunctionCallScalarExpression) { Aggregate aggregate; @@ -129,6 +135,12 @@ public override bool Visit(SqlInScalarExpression sqlInScalarExpression) return hasAggregates; } + public override bool Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + public override bool Visit(SqlLikeScalarExpression sqlLikeScalarExpression) { return false; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs index 1ce82d3c98..e644eeee43 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/AggregateProjectionTransformer.cs @@ -140,6 +140,12 @@ public override SqlScalarExpression Visit(SqlExistsScalarExpression sqlExistsSca return sqlExistsScalarExpression; } + public override SqlScalarExpression Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return sqlFirstScalarExpression; + } + public override SqlScalarExpression Visit(SqlFunctionCallScalarExpression sqlFunctionCallScalarExpression) { SqlScalarExpression rewrittenExpression; @@ -293,6 +299,12 @@ public override SqlScalarExpression Visit(SqlInScalarExpression sqlInScalarExpre items); } + public override SqlScalarExpression Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return sqlLastScalarExpression; + } + public override SqlScalarExpression Visit(SqlLikeScalarExpression sqlLikeScalarExpression) { return sqlLikeScalarExpression; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs index 2a671f2568..4c0cda94dc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/ScalarExpressionEvaluator.cs @@ -257,6 +257,16 @@ public override CosmosElement Visit(SqlExistsScalarExpression scalarExpression, return CosmosBoolean.Create(subqueryResults.Any()); } + public override CosmosElement Visit(SqlFirstScalarExpression scalarExpression, CosmosElement document) + { + // Only run on the current document since the subquery is always correlated. + IEnumerable subqueryResults = SqlInterpreter.ExecuteQuery( + new CosmosElement[] { document }, + scalarExpression.Subquery); + + return subqueryResults.FirstOrDefault(CosmosUndefined.Create()); + } + public override CosmosElement Visit(SqlFunctionCallScalarExpression scalarExpression, CosmosElement document) { List arguments = new List(); @@ -304,6 +314,16 @@ public override CosmosElement Visit(SqlInScalarExpression scalarExpression, Cosm return CosmosBoolean.Create(contains); } + public override CosmosElement Visit(SqlLastScalarExpression scalarExpression, CosmosElement document) + { + // Only run on the current document since the subquery is always correlated. + IEnumerable subqueryResults = SqlInterpreter.ExecuteQuery( + new CosmosElement[] { document }, + scalarExpression.Subquery); + + return subqueryResults.LastOrDefault(CosmosUndefined.Create()); + } + public override CosmosElement Visit(SqlLikeScalarExpression scalarExpression, CosmosElement document) { // Consider the necessity of having v3 offline engine. Should we remove this altogether? diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs index ba45092faa..c9da37b7c4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OfflineEngine/SqlInterpreter.cs @@ -755,6 +755,11 @@ public override bool Visit(SqlExistsScalarExpression scalarExpression) return false; } + public override bool Visit(SqlFirstScalarExpression scalarExpression) + { + return false; + } + public override bool Visit(SqlFunctionCallScalarExpression scalarExpression) { if (this.MatchesGroupByExpression(scalarExpression)) @@ -805,6 +810,11 @@ public override bool Visit(SqlInScalarExpression scalarExpression) return true; } + public override bool Visit(SqlLastScalarExpression scalarExpression) + { + return false; + } + public override bool Visit(SqlLikeScalarExpression scalarExpression) { return false; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/AggregateSubquerySqlParserBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/AggregateSubquerySqlParserBaselineTests.cs index 079fbbba46..92c6d6056b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/AggregateSubquerySqlParserBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/AggregateSubquerySqlParserBaselineTests.cs @@ -54,12 +54,109 @@ public void All() " FROM (SELECT udf.ALL(1, 2)) AS ALL " + " WHERE ALL( SELECT VALUE 1) " + ")") - }; this.ExecuteTestSuite(inputs); } + [TestMethod] + public void First() + { + List inputs = new List() + { + CreateInput( + description: "FIRST in an SqlSelectItem as an alias", + query: "SELECT 1 AS FIRST"), + CreateInput( + description: "FIRST in an AliasedCollectionExpression as an alias", + query: "SELECT * " + + "FROM (SELECT VALUE 1) AS FIRST"), + CreateInput( + description: "FIRST in an ArrayIteratorCollectionExpression", + query: "SELECT * " + + "FROM FIRST IN (SELECT VALUE 1)"), + CreateInput( + description: "FIRST in an InputPathCollection and IdentifierPathExpression", + query: "SELECT * " + + "FROM FIRST.FIRST"), + CreateInput( + description: "FIRST in a PropertyRefScalarExpression", + query: "SELECT FIRST"), + CreateInput( + description: "FIRST in a PropertyRefScalarExpression as child", + query: "SELECT c.FIRST"), + CreateInput( + description: "FIRST in a PropertyRefScalarExpression as parent and child", + query: "SELECT FIRST.FIRST"), + CreateInput( + description: "FIRST in a function cFIRST", + query: "SELECT FIRST(1, 2)"), + CreateInput( + description: "FIRST in a UDF function cFIRST", + query: "SELECT udf.FIRST(1, 2)"), + CreateInput( + description: "FIRST in every possible grammar rule at the same time", + query: "SELECT FIRST(1, 2) AS FIRST " + + "FROM FIRST IN (SELECT FIRST.FIRST) " + + "WHERE FIRST( " + + " SELECT FIRST " + + " FROM (SELECT udf.FIRST(1, 2)) AS FIRST " + + " WHERE FIRST( SELECT VALUE 1) " + + ")") + }; + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void Last() + { + List inputs = new List() + { + CreateInput( + description: "LAST in an SqlSelectItem as an alias", + query: "SELECT 1 AS LAST"), + CreateInput( + description: "LAST in an AliasedCollectionExpression as an alias", + query: "SELECT * " + + "FROM (SELECT VALUE 1) AS LAST"), + CreateInput( + description: "LAST in an ArrayIteratorCollectionExpression", + query: "SELECT * " + + "FROM LAST IN (SELECT VALUE 1)"), + CreateInput( + description: "LAST in an InputPathCollection and IdentifierPathExpression", + query: "SELECT * " + + "FROM LAST.LAST"), + CreateInput( + description: "LAST in a PropertyRefScalarExpression", + query: "SELECT LAST"), + CreateInput( + description: "LAST in a PropertyRefScalarExpression as child", + query: "SELECT c.LAST"), + CreateInput( + description: "LAST in a PropertyRefScalarExpression as parent and child", + query: "SELECT LAST.LAST"), + CreateInput( + description: "LAST in a function cLAST", + query: "SELECT LAST(1, 2)"), + CreateInput( + description: "LAST in a UDF function cLAST", + query: "SELECT udf.LAST(1, 2)"), + CreateInput( + description: "LAST in every possible grammar rule at the same time", + query: "SELECT LAST(1, 2) AS LAST " + + "FROM LAST IN (SELECT LAST.LAST) " + + "WHERE LAST( " + + " SELECT LAST " + + " FROM (SELECT udf.LAST(1, 2)) AS LAST " + + " WHERE LAST( SELECT VALUE 1) " + + ")") + }; + + this.ExecuteTestSuite(inputs); + } + public static SqlParserBaselineTestInput CreateInput(string description, string query) { return new SqlParserBaselineTestInput(description, query); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs index 2faed74686..43377f0074 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs @@ -246,6 +246,38 @@ public void Exists() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void First() + { + List inputs = new List() + { + // Positive + CreateInput(description: "Basic", scalarExpression: "FIRST(SELECT *)"), + CreateInput(description: "case insensitive", scalarExpression: "FIRST(SELECT *)"), + CreateInput(description: "nested", scalarExpression:"FIRST( SELECT * WHERE FIRST( SELECT *))"), + CreateInput( + description: "multiple nested", + scalarExpression: + "FIRST( " + + " SELECT * " + + " WHERE FIRST( " + + " SELECT *" + + " WHERE FIRST(" + + " SELECT *" + + " WHERE FIRST(" + + " SELECT VALUE 1" + + " )" + + " )" + + " )" + + ")"), + + // Negative + CreateInput(description: "No closing parens", scalarExpression: "FIRST(SELECT *") + }; + + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void FunctionCall() { @@ -291,6 +323,38 @@ public void In() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void Last() + { + List inputs = new List() + { + // Positive + CreateInput(description: "Basic", scalarExpression: "LAST(SELECT *)"), + CreateInput(description: "case insensitive", scalarExpression: "LAST(SELECT *)"), + CreateInput(description: "nested", scalarExpression:"LAST( SELECT * WHERE LAST( SELECT *))"), + CreateInput( + description: "multiple nested", + scalarExpression: + "LAST( " + + " SELECT * " + + " WHERE LAST( " + + " SELECT *" + + " WHERE LAST(" + + " SELECT *" + + " WHERE LAST(" + + " SELECT VALUE 1" + + " )" + + " )" + + " )" + + ")"), + + // Negative + CreateInput(description: "No closing parens", scalarExpression: "LAST(SELECT *") + }; + + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void Literal() { From dc3d0377cab69bf79449d3fcc72da9ea60082f72 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Tue, 7 Mar 2023 14:39:57 -0500 Subject: [PATCH 070/337] Subpartitioning: Adds support for Prefix Partition Key searches for sub partitioned containers (#3109) * 1st round of changes to support subpartitioning for ChangeFeed * name change and moved a method to FeedRangePartitionKey * support for prefix partition change feed and query including unit and emulator tests. need to verify using FeedRange with QueryIterator * splitting out unit tests from emulator tests * 1st round of changes to support subpartitioning for ChangeFeed * name change and moved a method to FeedRangePartitionKey * support for prefix partition change feed and query including unit and emulator tests. need to verify using FeedRange with QueryIterator * splitting out unit tests from emulator tests * moved logic to choose for prefix partition query and change feed * additional conditional to check for MultiHash partitionkeydefinition kind * removed unnecessary using * cleanup * unnecessary using * removed PREVIEW from proj * unit tests for ResolveFeedRangeBasedOnPrefixContainerAsync * change access modifier * since I changed to static, needed to fix tests * dealing with some testing nits * removed Console.Writeline * slight change in test use containerProperties and partitionKeyDefinition * big fix for resolve feedrange, changes to error behavior, added additional test coverage * test changes * ran updateContracts.ps1 * reverting to 3ad5309e9e22a7376e836cfdbe11fa2438a59133 * Ran Update Contracts * ran updateContracts.ps1 * UpdateContracts.ps1 * updatecontracts * removed bad check from test, removed changes from updatecontracts.ps1 * revert UpdateContracts changes * Reverting to 756a123160d14c424c5e11c4f3520094115aa5d4 * removed accidental change from changelog * removed unwanted change from Directory.build.props * added test clean up * removed console.writelines * updates to query test * removed preview flag * ran UpdateContrats.ps1 * no longer recread feedRange for queries unless using prefix pk * simplified if statement * fixed bug --------- Co-authored-by: Nalu Tripician --- .../src/Handler/RequestInvokerHandler.cs | 29 ++ .../Resource/Container/ContainerCore.Items.cs | 6 - ...riterBaselineTests.BulkOperationsAsync.xml | 42 +- .../CosmosMultiHashTest.cs | 426 ++++++++++-------- ...reateFromPartitionKeyAsyncEmulatorTests.cs | 344 ++++++++++++++ .../HandlerTests.cs | 148 ++++++ 6 files changed, 809 insertions(+), 186 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedRangeCreateFromPartitionKeyAsyncEmulatorTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs index 96b889832e..bb322f19b1 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs @@ -161,6 +161,14 @@ public virtual async Task SendAsync( if (feedRange != null) { + if (!request.OperationType.IsPointOperation()) + { + feedRange = await RequestInvokerHandler.ResolveFeedRangeBasedOnPrefixContainerAsync( + feedRange: feedRange, + cosmosContainerCore: cosmosContainerCore, + cancellationToken: cancellationToken); + } + if (feedRange is FeedRangePartitionKey feedRangePartitionKey) { if (cosmosContainerCore == null && object.ReferenceEquals(feedRangePartitionKey.PartitionKey, Cosmos.PartitionKey.None)) @@ -480,5 +488,26 @@ private static bool IsClientNoResponseSet(CosmosClientOptions clientOptions, Ope && clientOptions.EnableContentResponseOnWrite.HasValue && RequestInvokerHandler.IsItemNoRepsonseSet(clientOptions.EnableContentResponseOnWrite.Value, operationType); } + + internal static async Task ResolveFeedRangeBasedOnPrefixContainerAsync( + FeedRange feedRange, + ContainerInternal cosmosContainerCore, + CancellationToken cancellationToken) + { + if (feedRange is FeedRangePartitionKey feedRangePartitionKey) + { + PartitionKeyDefinition partitionKeyDefinition = await cosmosContainerCore + .GetPartitionKeyDefinitionAsync(cancellationToken) + .ConfigureAwait(false); + + if (partitionKeyDefinition != null && partitionKeyDefinition.Kind == PartitionKind.MultiHash + && feedRangePartitionKey.PartitionKey.InternalKey?.Components?.Count < partitionKeyDefinition.Paths?.Count) + { + feedRange = new FeedRangeEpk(feedRangePartitionKey.PartitionKey.InternalKey.GetEPKRangeForPrefixPartitionKey(partitionKeyDefinition)); + } + } + + return feedRange; + } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 0018eca9b7..31a3ccc5ca 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -959,12 +959,6 @@ private async Task ExtractPartitionKeyAndProcessItemStreamAsync // User specified PK value, no need to extract it if (partitionKey.HasValue) { - PartitionKeyDefinition pKeyDefinition = await this.GetPartitionKeyDefinitionAsync(); - if (partitionKey.HasValue && partitionKey.Value != PartitionKey.None && partitionKey.Value.InternalKey.Components.Count != pKeyDefinition.Paths.Count) - { - throw new ArgumentException(RMResources.MissingPartitionKeyValue); - } - return await this.ProcessItemStreamAsync( partitionKey, itemId, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index ed39221a61..041523ff8a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -38,6 +38,12 @@ │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Waiting for Initialization of client to complete(00000000-0000-0000-0000-000000000000) Unknown-Component 00:00:00:000 0.00 milliseconds + ├── Read Collection(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Batch Dispatch Async(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ ├── Using Wait(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -72,7 +78,20 @@ }, { "name": "Get Collection Cache", - "duration in milliseconds": 0 + "duration in milliseconds": 0, + "children": [ + { + "name": "Waiting for Initialization of client to complete", + "duration in milliseconds": 0 + } + ] + }, + { + "name": "Read Collection", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } }, { "name": "Batch Dispatch Async", @@ -1634,6 +1653,12 @@ │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Waiting for Initialization of client to complete(00000000-0000-0000-0000-000000000000) Unknown-Component 00:00:00:000 0.00 milliseconds + ├── Read Collection(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Batch Dispatch Async(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ ├── Using Wait(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -1808,7 +1833,20 @@ }, { "name": "Get Collection Cache", - "duration in milliseconds": 0 + "duration in milliseconds": 0, + "children": [ + { + "name": "Waiting for Initialization of client to complete", + "duration in milliseconds": 0 + } + ] + }, + { + "name": "Read Collection", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } }, { "name": "Batch Dispatch Async", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs index c77352d07f..3c590092db 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -1,5 +1,4 @@ -#if PREVIEW -namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Collections.Generic; @@ -13,9 +12,9 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests [TestClass] public class CosmosMultiHashTest { + private CosmosClient client = null; private Cosmos.Database database = null; - private CosmosClient client = null; private Container container = null; private ContainerProperties containerProperties = null; @@ -29,7 +28,7 @@ public async Task TestInitialize() this.client = TestCommon.CreateCosmosClient(true); this.database = await this.client.CreateDatabaseIfNotExistsAsync("mydb"); - this.containerProperties = new ContainerProperties("mycoll", new List { "/ZipCode", "/Address" }); + this.containerProperties = new ContainerProperties("mycoll", new List { "/ZipCode", "/City" }); this.container = await this.database.CreateContainerAsync(this.containerProperties); } @@ -37,6 +36,8 @@ public async Task TestInitialize() public async Task Cleanup() { await this.database.DeleteAsync(); + this.client.Dispose(); + HttpConstants.Versions.CurrentVersion = this.currentVersion; this.client.Dispose(); } @@ -44,25 +45,38 @@ public async Task Cleanup() [TestMethod] public async Task MultiHashCreateDocumentTest() { + Cosmos.PartitionKey pKey; //Document create test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + pKey= new PartitionKeyBuilder() + .Add(doc.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("City")) + .Build(); + documents[0] = await this.container.CreateItemAsync(doc, pKey); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + pKey = new PartitionKeyBuilder() + .Add(doc.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("City")) + .Build(); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + pKey = new PartitionKeyBuilder() + .Add(doc.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("City")) + .Build(); + documents[2] = await this.container.CreateItemAsync(doc); Assert.AreEqual(3, documents.Select(document => ((Document)document).SelfLink).Distinct().Count()); @@ -72,14 +86,16 @@ public async Task MultiHashCreateDocumentTest() foreach (Document document in documents) { badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("ZipCode")) .Build(); document.Id += "Bad"; - ArgumentException createException = await Assert.ThrowsExceptionAsync(() => + CosmosException createException = await Assert.ThrowsExceptionAsync(() => this.container.CreateItemAsync(document, badPKey) ); + + Assert.AreEqual(createException.StatusCode, HttpStatusCode.BadRequest); } } @@ -91,45 +107,44 @@ public async Task MultiHashDeleteDocumentTest() //Create Items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Document Delete Test foreach (Document document in documents) { - //Negative test - using incomplete partition key + //Negative test - using incomplete partition key (try one with more values too) badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("ZipCode")) .Build(); CosmosException deleteException = await Assert.ThrowsExceptionAsync(() => this.container.DeleteItemAsync(document.Id, badPKey) ); - Assert.AreEqual(deleteException.StatusCode, HttpStatusCode.BadRequest); //Positive test pKey = new PartitionKeyBuilder() .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("City")) .Build(); - Document readDocument = (await this.container.DeleteItemAsync(document.Id, pKey)).Resource; + Document deleteDocument = (await this.container.DeleteItemAsync(document.Id, pKey)).Resource; CosmosException clientException = await Assert.ThrowsExceptionAsync(() => this.container.ReadItemAsync(document.Id, pKey) @@ -147,30 +162,30 @@ public async Task MultiHashReadItemTest() //Create Items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Document Read Test foreach (Document document in documents) { pKey = new PartitionKeyBuilder() .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("City")) .Build(); Document readDocument = (await this.container.ReadItemAsync(document.Id, pKey)).Resource; @@ -178,7 +193,7 @@ public async Task MultiHashReadItemTest() //Negative test - using incomplete partition key badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("ZipCode")) .Build(); CosmosException clientException = await Assert.ThrowsExceptionAsync(() => @@ -193,40 +208,47 @@ public async Task MultiHashReadItemTest() public async Task MultiHashReadManyTest() { Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; //Create Items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Read Many Test List<(string, Cosmos.PartitionKey)> itemList = new List<(string, Cosmos.PartitionKey)>(); + List<(string, Cosmos.PartitionKey)> incompleteList = new List<(string, Cosmos.PartitionKey)>(); foreach (Document document in documents) { pKey = new PartitionKeyBuilder() .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("City")) + .Build(); + + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) .Build(); itemList.Add((document.Id, pKey)); + incompleteList.Add((document.Id, badPKey)); } - FeedResponse feedResponse = await this.container.ReadManyItemsAsync(itemList); + FeedResponse feedResponse = await this.container.ReadManyItemsAsync(itemList); Assert.IsNotNull(feedResponse); Assert.AreEqual(feedResponse.Count, 3); @@ -234,17 +256,25 @@ public async Task MultiHashReadManyTest() Assert.IsNotNull(feedResponse.Diagnostics); int count = 0; - foreach (ToDoActivity item in feedResponse) + foreach (Document item in feedResponse) { count++; Assert.IsNotNull(item); - Assert.IsNotNull(item.pk); } Assert.AreEqual(count, 3); + + //Negative test - using incomplete partition key + await Assert.ThrowsExceptionAsync(() => + this.container.ReadManyItemsAsync(incompleteList)); } + public record DatabaseItem( + string Id, + string Pk + ); + [TestMethod] - public async Task MultiHashUpsetItemTest() + public async Task MultiHashUpsertItemTest() { Cosmos.PartitionKey pKey; Cosmos.PartitionKey badPKey; @@ -252,90 +282,92 @@ public async Task MultiHashUpsetItemTest() //Create Items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Document Upsert Test - doc1 = new Document { Id = "document4" }; - doc1.SetValue("ZipCode", "97756"); - doc1.SetValue("Address", "Redmond"); - doc1.SetValue("Type", "Residence"); + doc = new Document { Id = "document4" }; + doc.SetValue("ZipCode", "97756"); + doc.SetValue("City", "Redmond"); + doc.SetValue("Type", "Residence"); pKey = new PartitionKeyBuilder() - .Add(doc1.GetPropertyValue("ZipCode")) - .Add(doc1.GetPropertyValue("Address")) + .Add(doc.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("City")) .Build(); //insert check - await this.container.UpsertItemAsync(doc1, pKey); + await this.container.UpsertItemAsync(doc, pKey); - Document readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + Document readCheck = (await this.container.ReadItemAsync(doc.Id, pKey)).Resource; - Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); - Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); - Assert.AreEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + Assert.AreEqual(doc.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc.GetPropertyValue("City"), readCheck.GetPropertyValue("City")); + Assert.AreEqual(doc.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); - doc1 = new Document { Id = "document4" }; - doc1.SetValue("ZipCode", "97756"); - doc1.SetValue("Address", "Redmond"); - doc1.SetValue("Type", "Business"); + doc = new Document { Id = "document4" }; + doc.SetValue("ZipCode", "97756"); + doc.SetValue("City", "Redmond"); + doc.SetValue("Type", "Business"); //update check pKey = new PartitionKeyBuilder() - .Add(doc1.GetPropertyValue("ZipCode")) - .Add(doc1.GetPropertyValue("Address")) + .Add(doc.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("City")) .Build(); - documents.Append>(await this.container.UpsertItemAsync(doc1, pKey)); + documents.Append>(await this.container.UpsertItemAsync(doc, pKey)); - readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + readCheck = (await this.container.ReadItemAsync(doc.Id, pKey)).Resource; - Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); - Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); - Assert.AreEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + Assert.AreEqual(doc.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc.GetPropertyValue("City"), readCheck.GetPropertyValue("City")); + Assert.AreEqual(doc.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); count = 0; - foreach (Document doc in this.container.GetItemLinqQueryable(true)) + foreach (Document document in this.container.GetItemLinqQueryable(true)) { count++; } Assert.AreEqual(4, count); //Negative test - using incomplete partition key - doc1 = new Document { Id = "document4" }; - doc1.SetValue("ZipCode", "97756"); - doc1.SetValue("Address", "Redmond"); - doc1.SetValue("Type", "Residence"); + doc = new Document { Id = "document4" }; + doc.SetValue("ZipCode", "97756"); + doc.SetValue("City", "Redmond"); + doc.SetValue("Type", "Residence"); badPKey = new PartitionKeyBuilder() - .Add(doc1.GetPropertyValue("ZipCode")) + .Add(doc.GetPropertyValue("ZipCode")) .Build(); - await Assert.ThrowsExceptionAsync(() => - this.container.UpsertItemAsync(doc1, badPKey) + CosmosException clientException = await Assert.ThrowsExceptionAsync(() => + this.container.UpsertItemAsync(doc, badPKey) ); - readCheck = (await this.container.ReadItemAsync(doc1.Id, pKey)).Resource; + Assert.AreEqual(clientException.StatusCode, HttpStatusCode.BadRequest); + + readCheck = (await this.container.ReadItemAsync(doc.Id, pKey)).Resource; - Assert.AreEqual(doc1.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); - Assert.AreEqual(doc1.GetPropertyValue("Address"), readCheck.GetPropertyValue("Address")); - Assert.AreNotEqual(doc1.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); + Assert.AreEqual(doc.GetPropertyValue("ZipCode"), readCheck.GetPropertyValue("ZipCode")); + Assert.AreEqual(doc.GetPropertyValue("City"), readCheck.GetPropertyValue("City")); + Assert.AreNotEqual(doc.GetPropertyValue("Type"), readCheck.GetPropertyValue("Type")); } [TestMethod] @@ -346,30 +378,30 @@ public async Task MultiHashReplaceItemTest() //Create items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Document Replace Test foreach (Document document in documents) { pKey = new PartitionKeyBuilder() .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("City")) .Build(); @@ -383,14 +415,16 @@ public async Task MultiHashReplaceItemTest() //Negative test - using incomplete partition key badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("ZipCode")) .Build(); readDocument.SetValue("Type", "Goverment"); - await Assert.ThrowsExceptionAsync(() => + CosmosException clientException = await Assert.ThrowsExceptionAsync(() => this.container.ReplaceItemAsync(document, document.Id, partitionKey: badPKey) ); + + Assert.AreEqual(clientException.StatusCode, HttpStatusCode.BadRequest); } } @@ -398,37 +432,59 @@ await Assert.ThrowsExceptionAsync(() => public async Task MultiHashQueryItemTest() { Cosmos.PartitionKey pKey; + Cosmos.PartitionKey badPKey; //Create items for test ItemResponse[] documents = new ItemResponse[3]; - Document doc1 = new Document { Id = "document1" }; - doc1.SetValue("ZipCode", "500026"); - doc1.SetValue("Address", "Secunderabad"); - doc1.SetValue("Type", "Residence"); - documents[0] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document2" }; - doc1.SetValue("ZipCode", "15232"); - doc1.SetValue("Address", "Pittsburgh"); - doc1.SetValue("Type", "Business"); - documents[1] = await this.container.CreateItemAsync(doc1); - - doc1 = new Document { Id = "document3" }; - doc1.SetValue("ZipCode", "11790"); - doc1.SetValue("Address", "Stonybrook"); - doc1.SetValue("Type", "Goverment"); - documents[2] = await this.container.CreateItemAsync(doc1); + Document doc = new Document { Id = "document1" }; + doc.SetValue("ZipCode", "500026"); + doc.SetValue("City", "Secunderabad"); + doc.SetValue("Type", "Residence"); + documents[0] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document2" }; + doc.SetValue("ZipCode", "15232"); + doc.SetValue("City", "Pittsburgh"); + doc.SetValue("Type", "Business"); + documents[1] = await this.container.CreateItemAsync(doc); + + doc = new Document { Id = "document3" }; + doc.SetValue("ZipCode", "11790"); + doc.SetValue("City", "Stonybrook"); + doc.SetValue("Type", "Goverment"); + documents[2] = await this.container.CreateItemAsync(doc); //Query foreach (Document document in documents) { pKey = new PartitionKeyBuilder() .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("Address")) + .Add(document.GetPropertyValue("City")) .Build(); - String query = $"SELECT * from c where c.id = {document.GetPropertyValue("Id")}"; + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("City")) + .Build(); + + String query = $"SELECT * from c where c.id = \"{document.GetPropertyValue("id")}\""; + + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); + + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + feedIterator.Dispose(); + } + //Using an incomplete partition key with prefix of PK path definition + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Build(); using (FeedIterator feedIterator = this.container.GetItemQueryIterator( query, null, @@ -437,11 +493,25 @@ public async Task MultiHashQueryItemTest() Assert.IsTrue(feedIterator.HasMoreResults); FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + feedIterator.Dispose(); } + //Negative test - using incomplete partition key + using (FeedIterator badFeedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { PartitionKey = badPKey})) + { + FeedResponse queryDocBad = await badFeedIterator.ReadNextAsync(); + Assert.ThrowsException(() => + queryDocBad.First() + ); + badFeedIterator.Dispose(); + } } } } -} -#endif +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedRangeCreateFromPartitionKeyAsyncEmulatorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedRangeCreateFromPartitionKeyAsyncEmulatorTests.cs new file mode 100644 index 0000000000..6df5b0a66f --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedRangeCreateFromPartitionKeyAsyncEmulatorTests.cs @@ -0,0 +1,344 @@ +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Threading.Tasks; + using System.Xml; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using Database = Database; + using PartitionKey = PartitionKey; + using PartitionKeyDefinitionVersion = PartitionKeyDefinitionVersion; + + /// + /// Testing Prefix and Full Partition for , against a with Hierarchical Partition Keys. + /// + /// + [TestClass] + public class FeedRangeCreateFromPartitionKeyAsyncEmulatorTests + { + private CosmosClient client = null; + private Database database = null; + + private readonly string currentVersion = HttpConstants.Versions.CurrentVersion; + + [TestInitialize] + public async Task TestInit() + { + HttpConstants.Versions.CurrentVersion = "2020-07-15"; + this.client = TestCommon.CreateCosmosClient(true); + + string databaseName = Guid.NewGuid().ToString(); + DatabaseResponse databaseResponse = await this.client.CreateDatabaseIfNotExistsAsync(databaseName); + this.database = databaseResponse; + } + + [TestCleanup] + public async Task TestCleanup() + { + await this.database.DeleteAsync(); + this.client.Dispose(); + + HttpConstants.Versions.CurrentVersion = this.currentVersion; + } + + /// + /// Using to create a new with Hierarchical Partition Keys. + /// Using with a Prefix partition on a MultiHash V2 . + /// + /// + /// + [TestMethod] + public async Task GetChangeFeedIteratorWithPrefixPartitionKeyReturnsFeedIterator() + { + Container container = await this.database.CreateContainerIfNotExistsAsync(new(id: @"TestMultiHashedContainer", partitionKeyPaths: new List() { "/city", "/state", "/zipCode" })); + ContainerProperties containerProperties = await container.ReadContainerAsync(); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98502" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Build(); + + FeedRange feedRange = new FeedRangePartitionKey(partitionKey); + FeedIterator iterator = container.GetChangeFeedIterator(ChangeFeedStartFrom.Beginning(feedRange), ChangeFeedMode.Incremental); + FeedResponse response = await iterator.ReadNextAsync(); + + string json = JsonConvert.SerializeObject(response.First()); + JObject @object = JObject.Parse(json); + + Assert.AreEqual(expected: item.id, actual: @object["id"]); + Assert.AreEqual(expected: item.city, actual: @object["city"]); + Assert.AreEqual(expected: item.state, actual: @object["state"]); + Assert.AreEqual(expected: item.zipCode, actual: @object["zipCode"]); + } + + /// + /// Using to create a new with hierarchical partition keys. + /// Using with a Prefix Partition on a MultiHash . + /// + /// + /// + [TestMethod] + public async Task GetChangeFeedStreamIteratorWithPrefixPartitionKeyReturnsFeedIterator() + { + Container container = await this.database.CreateContainerIfNotExistsAsync(new(id: @"TestMultiHashedContainer", partitionKeyPaths: new List() { "/city", "/state", "/zipCode" })); + ContainerProperties containerProperties = await container.ReadContainerAsync(); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98502" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Build(); + + FeedRange feedRange = new FeedRangePartitionKey(partitionKey); + using (FeedIterator iterator = container.GetChangeFeedStreamIterator(ChangeFeedStartFrom.Beginning(feedRange), ChangeFeedMode.Incremental)) + { + ResponseMessage responseMessage = await iterator.ReadNextAsync(); + + using (StreamReader streamReader = new(responseMessage.Content)) + { + string content = await streamReader.ReadToEndAsync(); + + JObject @object = JObject.Parse(content); + JToken token = @object["Documents"].First(); + + Assert.AreEqual(expected: item.id, actual: token["id"]); + Assert.AreEqual(expected: item.city, actual: token["city"]); + Assert.AreEqual(expected: item.state, actual: token["state"]); + Assert.AreEqual(expected: item.zipCode, actual: token["zipCode"]); + } + } + } + + /// + /// Using to create a new with Hierarchical Partition Keys. + /// using with a Prefix partition on a MultiHash V2 . + /// + /// + /// + [TestMethod] + [Ignore("Query is returning 'Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document.' Investigation.")] + [Owner("naga.naravamakula")] + public async Task GetItemQueryIteratorWithPrefixPartitionKeyReturnsFeedIterator() + { + Container container = await this.database.CreateContainerIfNotExistsAsync(new(id: @"TestMultiHashedContainer", partitionKeyPaths: new List() { "/city", "/state", "/zipCode" })); + ContainerProperties containerProperties = await container.ReadContainerAsync(); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98052" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + QueryDefinition queryDefinition = new QueryDefinition(query: "SELECT * FROM c WHERE c.city = @cityInput AND c.state = @stateInput") + .WithParameter("@cityInput", "Redmond") + .WithParameter("@stateInput", "WA"); + + partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Build(); + + FeedRange feedRange = new FeedRangePartitionKey(partitionKey); + Console.WriteLine(feedRange.ToJsonString()); + using (FeedIterator iterator = container.GetItemQueryIterator(feedRange: feedRange, queryDefinition: queryDefinition, requestOptions: new() { PartitionKey = partitionKey })) + { + FeedResponse feedResponse = await iterator.ReadNextAsync(); + + string content = JsonConvert.SerializeObject(feedResponse.First()); + JObject @object = JObject.Parse(content); + + Assert.AreEqual(expected: item.id, actual: @object["id"]); + Assert.AreEqual(expected: item.city, actual: @object["city"]); + Assert.AreEqual(expected: item.state, actual: @object["state"]); + Assert.AreEqual(expected: item.zipCode, actual: @object["zipCode"]); + } + } + + /// + /// Using to create a new with Hierarchical Partition Keys. + /// Using with a Prefix Partition on a MultiHash V2 . + /// + /// + /// + [TestMethod] + public async Task GetItemQueryStreamIteratorWithPrefixPartitionKeyReturnsFeedIterator() + { + Container container = await this.database.CreateContainerIfNotExistsAsync(new(id: @"TestMultiHashedContainer", partitionKeyPaths: new List() { "/city", "/state", "/zipCode" })); + ContainerProperties containerProperties = await container.ReadContainerAsync(); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98052" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + QueryDefinition queryDefinition = new QueryDefinition(query: "SELECT * FROM c WHERE c.city = @cityInput AND c.state = @stateInput") + .WithParameter("@cityInput", "Redmond") + .WithParameter("@stateInput", "WA"); + + using (FeedIterator iterator = container.GetItemQueryStreamIterator(queryDefinition: queryDefinition, requestOptions: new() { PartitionKey = partitionKey })) + { + ResponseMessage responseMessage = await iterator.ReadNextAsync(); + + using (StreamReader streamReader = new(responseMessage.Content)) + { + string content = await streamReader.ReadToEndAsync(); + + JObject @object = JObject.Parse(content); + JToken token = @object["Documents"].First(); + + Assert.AreEqual(expected: item.id, actual: token["id"]); + Assert.AreEqual(expected: item.city, actual: token["city"]); + Assert.AreEqual(expected: item.state, actual: token["state"]); + Assert.AreEqual(expected: item.zipCode, actual: token["zipCode"]); + } + } + } + + /// + /// Using to create a new with Hierarchical Partition Keys. + /// Using with a Full Partition on a MultiHash V2 . + /// + /// + /// + [TestMethod] + public async Task ReadItemWithFullPartitionKeyReturnsFeedIterator() + { + ContainerProperties containerProperties = new(id: @"TestMultiHashedContainer", partitionKeyDefinition: new Documents.PartitionKeyDefinition + { + Kind = Documents.PartitionKind.MultiHash, + Version = Documents.PartitionKeyDefinitionVersion.V2, + Paths = new System.Collections.ObjectModel.Collection(new List() { "/city", "/state", "/zipCode" }) + }); + + Container container = await this.database.CreateContainerIfNotExistsAsync(containerProperties: containerProperties); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98052" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + ItemResponse itemResponse = await container.ReadItemAsync(id: item.id, partitionKey: partitionKey); + + string content = JsonConvert.SerializeObject(itemResponse.Resource); + JObject @object = JObject.Parse(content); + + Assert.AreEqual(expected: item.id, actual: @object["id"]); + Assert.AreEqual(expected: item.city, actual: @object["city"]); + Assert.AreEqual(expected: item.state, actual: @object["state"]); + Assert.AreEqual(expected: item.zipCode, actual: @object["zipCode"]); + } + + /// + /// Using to create a new with Hierarchical Partition Keys. + /// Using + /// Using with a Full Partition on a MultiHash V2 . + /// + /// + /// + [TestMethod] + public async Task ReadItemStreamWithFullPartitionKeyReturnsFeedIterator() + { + Container container = await this.database.CreateContainerIfNotExistsAsync(new(id: @"TestMultiHashedContainer", partitionKeyPaths: new List() { "/city", "/state", "/zipCode" })); + ContainerProperties containerProperties = await container.ReadContainerAsync(); + + Assert.AreEqual(expected: PartitionKeyDefinitionVersion.V2, actual: containerProperties.PartitionKeyDefinitionVersion); + Assert.AreEqual(expected: 3, actual: containerProperties.PartitionKey.Paths.Count); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/city")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/state")); + Assert.IsTrue(containerProperties.PartitionKey.Paths.Contains("/zipCode")); + Assert.AreEqual(expected: Documents.PartitionKind.MultiHash, actual: containerProperties.PartitionKey.Kind); + + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98052" }; + PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Add(item.zipCode) + .Build(); + + _ = await container.CreateItemAsync(item: item, partitionKey: partitionKey); + + using (ResponseMessage responseMessage = await container.ReadItemStreamAsync(id: item.id, partitionKey: partitionKey)) + { + using (StreamReader streamReader = new(responseMessage.Content)) + { + string content = await streamReader.ReadToEndAsync(); + JObject @object = JObject.Parse(content); + + Assert.AreEqual(expected: item.id, actual: @object["id"]); + Assert.AreEqual(expected: item.city, actual: @object["city"]); + Assert.AreEqual(expected: item.state, actual: @object["state"]); + Assert.AreEqual(expected: item.zipCode, actual: @object["zipCode"]); + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs index 8884e22815..ae5dccd2c8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Tests using System; using System.Collections; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; @@ -438,6 +439,153 @@ public void TestAggregateExceptionConverter() Assert.IsTrue(response.ErrorMessage.Contains(errorMessage)); } + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangePartitionKeyAndMultiHashContainerAsync() + { + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond", state = "WA", zipCode = "98502" }; + Cosmos.PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Add(item.state) + .Build(); + + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.MultiHash, + Paths = new Collection(new List() { "/city", "/state", "/zipCode" }) + }, + inputFeedRange: new FeedRangePartitionKey(partitionKey), + expectedFeedRange: new FeedRangeEpk(new Documents.Routing.Range( + min: "01620B162169497AFD85FA66E99F73760845FB119899DE50766A2C4CEFC2FA73", + max: "01620B162169497AFD85FA66E99F73760845FB119899DE50766A2C4CEFC2FA73FF", + isMinInclusive: true, + isMaxInclusive: default)), + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Once()); + } + + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangePartitionKeyOnHashContainerAsync() + { + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond" }; + Cosmos.PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Build(); + + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.Hash, + Paths = new Collection(new List() { "/city" }) + }, + inputFeedRange: new FeedRangePartitionKey(partitionKey), + expectedFeedRange: new FeedRangePartitionKey(partitionKey), + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Once()); + } + + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangePartitionKeyOnRangeContainerAsync() + { + dynamic item = new { id = Guid.NewGuid().ToString(), city = "Redmond" }; + Cosmos.PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(item.city) + .Build(); + + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.Range, + Paths = new Collection(new List() { "/city" }) + }, + inputFeedRange: new FeedRangePartitionKey(partitionKey), + expectedFeedRange: new FeedRangePartitionKey(partitionKey), + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Once()); + } + + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangeEpkOnMultiHashContainerAsync() + { + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.MultiHash, + Paths = new Collection(new List() { "/city", "/state", "/zipCode" }) + }, + inputFeedRange: FeedRangeEpk.FullRange, + expectedFeedRange: FeedRangeEpk.FullRange, + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Never()); + } + + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangeEpkOnHashContainerAsync() + { + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.Hash, + Paths = new Collection(new List() { "/city" }) + }, + inputFeedRange: FeedRangeEpk.FullRange, + expectedFeedRange: FeedRangeEpk.FullRange, + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Never()); + } + + [TestMethod] + public async Task TestResolveFeedRangeBasedOnPrefixWithFeedRangeEpkOnRangeContainerAsync() + { + await HandlerTests.TestResolveFeedRangeBasedOnPrefixAsync( + partitionKeyDefinition: new PartitionKeyDefinition() + { + Kind = PartitionKind.Range, + Paths = new Collection(new List() { "/city" }) + }, + inputFeedRange: FeedRangeEpk.FullRange, + expectedFeedRange: FeedRangeEpk.FullRange, + getPartitionKeyDefinitionAsyncExecutions: Moq.Times.Never()); + } + + private static async Task TestResolveFeedRangeBasedOnPrefixAsync( + PartitionKeyDefinition partitionKeyDefinition, + FeedRangeInternal inputFeedRange, + FeedRangeInternal expectedFeedRange, + Moq.Times getPartitionKeyDefinitionAsyncExecutions) + where TFeedRange : FeedRangeInternal + { + using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( + accountConsistencyLevel: Cosmos.ConsistencyLevel.Strong, + customizeClientBuilder: builder => builder.WithConsistencyLevel(Cosmos.ConsistencyLevel.Eventual)); + + Moq.Mock mockContainer = MockCosmosUtil.CreateMockContainer( + dbName: Guid.NewGuid().ToString(), + containerName: Guid.NewGuid().ToString()); + + CancellationToken cancellationToken = CancellationToken.None; + + mockContainer + .Setup(container => container.GetPartitionKeyDefinitionAsync(cancellationToken)) + .Returns(Task.FromResult(partitionKeyDefinition)); + + RequestInvokerHandler invoker = new( + client: client, + requestedClientConsistencyLevel: default); + + Cosmos.FeedRange feedRange = await RequestInvokerHandler.ResolveFeedRangeBasedOnPrefixContainerAsync( + feedRange: inputFeedRange, + cosmosContainerCore: mockContainer.Object, + cancellationToken: cancellationToken); + + mockContainer.Verify(x => x.GetPartitionKeyDefinitionAsync(Moq.It.IsAny()), getPartitionKeyDefinitionAsyncExecutions); + + Assert.IsNotNull(feedRange, "FeedRange did not initialize"); + + Assert.IsInstanceOfType( + value: feedRange, + expectedType: typeof(TFeedRange)); + + Assert.AreEqual( + expected: expectedFeedRange.ToJsonString(), + actual: feedRange.ToJsonString()); + } + private class SomePayload { public string V1 { get; set; } From 6ebb8d4c22fc1f7d4329ac1956c6102d3f0f883c Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 9 Mar 2023 21:07:11 +0530 Subject: [PATCH 071/337] [Internal] ClientTelemetry: Adds logic to limit payload size to 2 MB (#3717) * first draft wip fix test and logic * resolve conflicts * limit 2 mb * ad callback * fix tests * code refactor * cosmos json to newtosoft json * clean up files * fix logging to argumrnt based * code refactor * add null check --- .../src/Telemetry/ClientTelemetry.cs | 184 +++---------- .../src/Telemetry/ClientTelemetryHelper.cs | 117 +++----- .../src/Telemetry/ClientTelemetryOptions.cs | 8 +- .../Telemetry/ClientTelemetryPayloadWriter.cs | 161 +++++++++++ .../src/Telemetry/ClientTelemetryProcessor.cs | 142 ++++++++++ .../Models/ClientTelemetryProperties.cs | 72 +++++ .../ClientTelemetryTests.cs | 36 +-- .../Microsoft.Azure.Cosmos.Tests.csproj | 4 + .../ClientTelemetryPayloadWithoutMetrics.json | 135 +++++++++ .../Telemetry/ClientTelemetryTests.cs | 258 ++++++++++++++++++ 10 files changed, 859 insertions(+), 258 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryPayloadWithoutMetrics.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 82e212f7f3..d0ca7d8ac8 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -8,8 +8,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System.Collections.Concurrent; using System.Collections.Generic; using System.Net; - using System.Net.Http; - using System.Text; using System.Threading; using System.Threading.Tasks; using Handler; @@ -20,9 +18,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.Rntbd; - using Newtonsoft.Json; using Util; using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; @@ -36,12 +31,10 @@ internal class ClientTelemetry : IDisposable { private const int allowedNumberOfFailures = 3; - private static readonly Uri endpointUrl = ClientTelemetryOptions.GetClientTelemetryEndpoint(); private static readonly TimeSpan observingWindow = ClientTelemetryOptions.GetScheduledTimeSpan(); private readonly ClientTelemetryProperties clientTelemetryInfo; - private readonly CosmosHttpClient httpClient; - private readonly AuthorizationTokenProvider tokenProvider; + private readonly ClientTelemetryProcessor processor; private readonly DiagnosticsHandlerHelper diagnosticsHelper; private readonly CancellationTokenSource cancellationTokenSource; @@ -108,7 +101,7 @@ public static ClientTelemetry CreateAndStartBackgroundTelemetry( return clientTelemetry; } - private ClientTelemetry( + internal ClientTelemetry( string clientId, CosmosHttpClient httpClient, string userAgent, @@ -118,9 +111,8 @@ private ClientTelemetry( IReadOnlyList preferredRegions, GlobalEndpointManager globalEndpointManager) { - this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); this.diagnosticsHelper = diagnosticsHelper ?? throw new ArgumentNullException(nameof(diagnosticsHelper)); - this.tokenProvider = authorizationTokenProvider ?? throw new ArgumentNullException(nameof(authorizationTokenProvider)); + this.processor = new ClientTelemetryProcessor(httpClient, authorizationTokenProvider); this.clientTelemetryInfo = new ClientTelemetryProperties( clientId: clientId, @@ -170,6 +162,7 @@ private async Task EnrichAndSendAsync() await Task.Delay(observingWindow, this.cancellationTokenSource.Token); + this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); this.clientTelemetryInfo.MachineId = VmMetadataApiHandler.GetMachineId(); // Load host information from cache @@ -177,32 +170,37 @@ private async Task EnrichAndSendAsync() this.clientTelemetryInfo.ApplicationRegion = vmInformation?.Location; this.clientTelemetryInfo.HostEnvInfo = ClientTelemetryOptions.GetHostInformation(vmInformation); - // If cancellation is requested after the delay then return from here. - if (this.cancellationTokenSource.IsCancellationRequested) - { - DefaultTrace.TraceInformation("Observer Task Cancelled."); - - break; - } - - this.RecordSystemUtilization(); + this.clientTelemetryInfo.SystemInfo = ClientTelemetryHelper.RecordSystemUtilization(this.diagnosticsHelper, + this.clientTelemetryInfo.IsDirectConnectionMode); - this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); - - ConcurrentDictionary operationInfoSnapshot + // Take the copy for further processing i.e. serializing and dividing into chunks + ConcurrentDictionary operationInfoSnapshot = Interlocked.Exchange(ref this.operationInfoMap, new ConcurrentDictionary()); ConcurrentDictionary cacheRefreshInfoSnapshot - = Interlocked.Exchange(ref this.cacheRefreshInfoMap, new ConcurrentDictionary()); + = Interlocked.Exchange(ref this.cacheRefreshInfoMap, new ConcurrentDictionary()); ConcurrentDictionary requestInfoSnapshot = Interlocked.Exchange(ref this.requestInfoMap, new ConcurrentDictionary()); - this.clientTelemetryInfo.OperationInfo = ClientTelemetryHelper.ToListWithMetricsInfo(operationInfoSnapshot); - this.clientTelemetryInfo.CacheRefreshInfo = ClientTelemetryHelper.ToListWithMetricsInfo(cacheRefreshInfoSnapshot); - this.clientTelemetryInfo.RequestInfo = ClientTelemetryHelper.ToListWithMetricsInfo(requestInfoSnapshot); - - await this.SendAsync(); + try + { + await this.processor + .ProcessAndSendAsync( + clientTelemetryInfo: this.clientTelemetryInfo, + operationInfoSnapshot: operationInfoSnapshot, + cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, + requestInfoSnapshot: requestInfoSnapshot, + cancellationToken: this.cancellationTokenSource.Token); + + this.numberOfFailures = 0; + } + catch (Exception ex) + { + this.numberOfFailures++; + + DefaultTrace.TraceError("Telemetry Job Processor failed with error : {0}", ex); + } } } catch (Exception ex) @@ -233,8 +231,8 @@ internal void CollectCacheInfo(string cacheRefreshSource, throw new ArgumentNullException(nameof(cacheRefreshSource)); } - DefaultTrace.TraceVerbose($"Collecting cacheRefreshSource {cacheRefreshSource} data for Telemetry."); - + DefaultTrace.TraceVerbose($"Collecting cacheRefreshSource {0} data for Telemetry.", cacheRefreshSource); + string regionsContacted = ClientTelemetryHelper.GetContactedRegions(regionsContactedList); // Recording Request Latency @@ -290,7 +288,7 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, ITrace trace) { DefaultTrace.TraceVerbose("Collecting Operation data for Telemetry."); - + if (cosmosDiagnostics == null) { throw new ArgumentNullException(nameof(cosmosDiagnostics)); @@ -301,7 +299,7 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, this.RecordRntbdResponses(containerId, databaseId, summaryDiagnostics.StoreResponseStatistics.Value); string regionsContacted = ClientTelemetryHelper.GetContactedRegions(cosmosDiagnostics.GetContactedRegions()); - + // Recording Request Latency and Request Charge OperationInfo payloadKey = new OperationInfo(regionsContacted: regionsContacted?.ToString(), responseSizeInBytes: responseSizeInBytes, @@ -370,126 +368,6 @@ private void RecordRntbdResponses(string containerId, string databaseId, List - /// Record CPU and memory usage which will be sent as part of telemetry information - /// - private void RecordSystemUtilization() - { - try - { - DefaultTrace.TraceVerbose("Started Recording System Usage for telemetry."); - - SystemUsageHistory systemUsageHistory = this.diagnosticsHelper.GetClientTelemetrySystemHistory(); - - if (systemUsageHistory != null ) - { - ClientTelemetryHelper.RecordSystemUsage( - systemUsageHistory: systemUsageHistory, - systemInfoCollection: this.clientTelemetryInfo.SystemInfo, - isDirectConnectionMode: this.clientTelemetryInfo.IsDirectConnectionMode); - } - else - { - DefaultTrace.TraceWarning("System Usage History not available"); - } - } - catch (Exception ex) - { - DefaultTrace.TraceError("System Usage Recording Error : {0} ", ex); - } - } - - /// - /// Task to send telemetry information to configured Juno endpoint. - /// If endpoint is not configured then it won't even try to send information. It will just trace an error message. - /// In any case it resets the telemetry information to collect the latest one. - /// - /// Async Task - private async Task SendAsync() - { - if (endpointUrl == null) - { - DefaultTrace.TraceError("Telemetry is enabled but endpoint is not configured"); - return; - } - - try - { - DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl.AbsoluteUri); - - string json = JsonConvert.SerializeObject(this.clientTelemetryInfo, ClientTelemetryOptions.JsonSerializerSettings); - - using HttpRequestMessage request = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = endpointUrl, - Content = new StringContent(json, Encoding.UTF8, "application/json") - }; - - async ValueTask CreateRequestMessage() - { - INameValueCollection headersCollection = new StoreResponseNameValueCollection(); - await this.tokenProvider.AddAuthorizationHeaderAsync( - headersCollection, - endpointUrl, - "POST", - AuthorizationTokenType.PrimaryMasterKey); - - foreach (string key in headersCollection.AllKeys()) - { - request.Headers.Add(key, headersCollection[key]); - } - - request.Headers.Add(HttpConstants.HttpHeaders.DatabaseAccountName, this.clientTelemetryInfo.GlobalDatabaseAccountName); - String envName = ClientTelemetryOptions.GetEnvironmentName(); - if (!String.IsNullOrEmpty(envName)) - { - request.Headers.Add(HttpConstants.HttpHeaders.EnvironmentName, envName); - } - - return request; - } - - using HttpResponseMessage response = await this.httpClient.SendHttpAsync(CreateRequestMessage, - ResourceType.Telemetry, - HttpTimeoutPolicyNoRetry.Instance, - null, - this.cancellationTokenSource.Token); - - if (!response.IsSuccessStatusCode) - { - this.numberOfFailures++; - - DefaultTrace.TraceError("Juno API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase); - } - else - { - this.numberOfFailures = 0; // Ressetting failure counts on success call. - DefaultTrace.TraceInformation("Telemetry data sent successfully."); - } - - } - catch (Exception ex) - { - this.numberOfFailures++; - - DefaultTrace.TraceError("Exception while sending telemetry data : {0}", ex); - } - finally - { - // Reset SystemInfo Dictionary for new data. - this.Reset(); - } - } - - /// - /// Reset all the operation, System Utilization and Cache refresh related collections - /// - private void Reset() - { - this.clientTelemetryInfo.SystemInfo.Clear(); - } /// /// Dispose of cosmos client.It will get disposed with client so not making it thread safe. diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs index 2a29ef9454..2399bcb9fb 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryHelper.cs @@ -8,8 +8,8 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System.Linq; using System.Text; using System.Threading.Tasks; - using HdrHistogram; using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Cosmos.Handler; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Telemetry.Models; using Microsoft.Azure.Documents.Rntbd; @@ -46,115 +46,62 @@ internal static async Task SetAccountNameAsync(GlobalEndpoint /// /// /// - /// /// - internal static void RecordSystemUsage( + private static List RecordSystemUsage( SystemUsageHistory systemUsageHistory, - List systemInfoCollection, bool isDirectConnectionMode) { if (systemUsageHistory.Values == null) { - return; + return null; } DefaultTrace.TraceVerbose("System Usage recorded by telemetry is : {0}", systemUsageHistory); - - systemInfoCollection.Add(TelemetrySystemUsage.GetCpuInfo(systemUsageHistory.Values)); - systemInfoCollection.Add(TelemetrySystemUsage.GetMemoryRemainingInfo(systemUsageHistory.Values)); - systemInfoCollection.Add(TelemetrySystemUsage.GetAvailableThreadsInfo(systemUsageHistory.Values)); - systemInfoCollection.Add(TelemetrySystemUsage.GetThreadWaitIntervalInMs(systemUsageHistory.Values)); - systemInfoCollection.Add(TelemetrySystemUsage.GetThreadStarvationSignalCount(systemUsageHistory.Values)); + + List systemInfoCollection = new List(6) + { + TelemetrySystemUsage.GetCpuInfo(systemUsageHistory.Values), + TelemetrySystemUsage.GetMemoryRemainingInfo(systemUsageHistory.Values), + TelemetrySystemUsage.GetAvailableThreadsInfo(systemUsageHistory.Values), + TelemetrySystemUsage.GetThreadWaitIntervalInMs(systemUsageHistory.Values), + TelemetrySystemUsage.GetThreadStarvationSignalCount(systemUsageHistory.Values) + }; // Reset System Information if (isDirectConnectionMode) { systemInfoCollection.Add(TelemetrySystemUsage.GetTcpConnectionCount(systemUsageHistory.Values)); } + return systemInfoCollection; } - + /// - /// Convert map with operation information to list of operations along with request latency and request charge metrics + /// Record CPU and memory usage which will be sent as part of telemetry information /// - /// - /// Collection of ReportPayload - internal static List ToListWithMetricsInfo( - IDictionary metrics) + internal static List RecordSystemUtilization(DiagnosticsHandlerHelper helper, bool isDirectMode) { - DefaultTrace.TraceVerbose("Aggregating operation information to list started"); - - List payloadWithMetricInformation = new List(); - foreach (KeyValuePair entry in metrics) + try { - OperationInfo payloadForLatency = entry.Key; - payloadForLatency.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); - payloadForLatency.SetAggregators(entry.Value.latency, ClientTelemetryOptions.TicksToMsFactor); - - payloadWithMetricInformation.Add(payloadForLatency); + DefaultTrace.TraceVerbose("Started Recording System Usage for telemetry."); - OperationInfo payloadForRequestCharge = payloadForLatency.Copy(); - payloadForRequestCharge.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestChargeName, ClientTelemetryOptions.RequestChargeUnit); - payloadForRequestCharge.SetAggregators(entry.Value.requestcharge, ClientTelemetryOptions.HistogramPrecisionFactor); - - payloadWithMetricInformation.Add(payloadForRequestCharge); - } + SystemUsageHistory systemUsageHistory = helper.GetClientTelemetrySystemHistory(); - DefaultTrace.TraceVerbose("Aggregating operation information to list done"); - - return payloadWithMetricInformation; - } - - /// - /// Convert map with request information to list of operations along with request latency and request charge metrics - /// - /// - /// Collection of ReportPayload - internal static List ToListWithMetricsInfo( - IDictionary metrics) - { - DefaultTrace.TraceVerbose("Aggregating RequestInfo information to list started"); - - List payloadWithMetricInformation = new List(); - foreach (KeyValuePair entry in metrics) - { - MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); - metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); - - RequestInfo payloadForLatency = entry.Key; - payloadForLatency.Metrics.Add(metricInfo); - - payloadWithMetricInformation.Add(payloadForLatency); + if (systemUsageHistory != null) + { + return ClientTelemetryHelper.RecordSystemUsage( + systemUsageHistory: systemUsageHistory, + isDirectConnectionMode: isDirectMode); + } + else + { + DefaultTrace.TraceWarning("System Usage History not available"); + } } - - DefaultTrace.TraceVerbose("Aggregating RequestInfo information to list done"); - - return payloadWithMetricInformation; - } - - /// - /// Convert map with CacheRefreshInfo information to list of operations along with request latency and request charge metrics - /// - /// - /// Collection of ReportPayload - internal static List ToListWithMetricsInfo(IDictionary metrics) - { - DefaultTrace.TraceVerbose("Aggregating CacheRefreshInfo information to list started"); - - List payloadWithMetricInformation = new List(); - foreach (KeyValuePair entry in metrics) + catch (Exception ex) { - CacheRefreshInfo payloadForLatency = entry.Key; - payloadForLatency.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); - payloadForLatency.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); - - payloadWithMetricInformation.Add(payloadForLatency); + DefaultTrace.TraceError("System Usage Recording Error : {0} ", ex); } - - DefaultTrace.TraceVerbose("Aggregating CacheRefreshInfo information to list done"); - - return payloadWithMetricInformation; + return null; } /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index 3b69e0c621..f2caaf50d5 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -18,7 +18,7 @@ internal static class ClientTelemetryOptions internal const int KbToMbFactor = 1024; internal const int OneKbToBytes = 1024; - + // Expecting histogram to have Minimum Latency of 1 and Maximum Latency of 1 hour (which is never going to happen) internal const long RequestLatencyMax = TimeSpan.TicksPerHour; internal const long RequestLatencyMin = 1; @@ -94,9 +94,11 @@ internal static class ClientTelemetryOptions NullValueHandling = NullValueHandling.Ignore, MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr }; - - private static readonly List ExcludedStatusCodes = new List { 404, 409 }; + private static readonly List ExcludedStatusCodes = new List { 404, 409 }; + + internal static int PayloadSizeThreshold = 1024 * 1024 * 2; // 2MB + private static Uri clientTelemetryEndpoint; private static string environmentName; private static TimeSpan scheduledTimeSpan = TimeSpan.Zero; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs new file mode 100644 index 0000000000..1158c7d639 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs @@ -0,0 +1,161 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using HdrHistogram; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using Newtonsoft.Json; + + internal static class ClientTelemetryPayloadWriter + { + public static async Task SerializedPayloadChunksAsync( + ClientTelemetryProperties properties, + ConcurrentDictionary operationInfoSnapshot, + ConcurrentDictionary cacheRefreshInfoSnapshot, + ConcurrentDictionary requestInfoSnapshot, + Func callback) + { + if (properties == null) + { + throw new ArgumentNullException(nameof(properties)); + } + + StringBuilder stringBuilder = new StringBuilder(ClientTelemetryOptions.PayloadSizeThreshold); + + JsonWriter writer = ClientTelemetryPayloadWriter.GetWriterWithSectionStartTag(stringBuilder, properties, "operationInfo"); + + if (operationInfoSnapshot?.Any() == true) + { + foreach (KeyValuePair entry in operationInfoSnapshot) + { + long lengthNow = stringBuilder.Length; + + OperationInfo payloadForLatency = entry.Key; + payloadForLatency.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + payloadForLatency.SetAggregators(entry.Value.latency, ClientTelemetryOptions.TicksToMsFactor); + + OperationInfo payloadForRequestCharge = payloadForLatency.Copy(); + payloadForRequestCharge.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestChargeName, ClientTelemetryOptions.RequestChargeUnit); + payloadForRequestCharge.SetAggregators(entry.Value.requestcharge, ClientTelemetryOptions.HistogramPrecisionFactor); + + string latencyMetrics = JsonConvert.SerializeObject(payloadForLatency); + string requestChargeMetrics = JsonConvert.SerializeObject(payloadForRequestCharge); + + if (lengthNow + latencyMetrics.Length + requestChargeMetrics.Length > ClientTelemetryOptions.PayloadSizeThreshold) + { + writer.WriteEndArray(); + writer.WriteEndObject(); + + await callback.Invoke(stringBuilder.ToString()); + + writer = ClientTelemetryPayloadWriter.GetWriterWithSectionStartTag(stringBuilder, properties, "operationInfo"); + } + + writer.WriteRawValue(latencyMetrics); + writer.WriteRawValue(requestChargeMetrics); + } + + } + writer.WriteEndArray(); + + if (cacheRefreshInfoSnapshot?.Any() == true) + { + writer.WritePropertyName("cacheRefreshInfo"); + writer.WriteStartArray(); + + foreach (KeyValuePair entry in cacheRefreshInfoSnapshot) + { + long lengthNow = stringBuilder.Length; + + CacheRefreshInfo payloadForLatency = entry.Key; + payloadForLatency.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + payloadForLatency.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); + + string latencyMetrics = JsonConvert.SerializeObject(payloadForLatency); + + if (lengthNow + latencyMetrics.Length > ClientTelemetryOptions.PayloadSizeThreshold) + { + writer.WriteEndArray(); + writer.WriteEndObject(); + + await callback.Invoke(stringBuilder.ToString()); + + writer = ClientTelemetryPayloadWriter.GetWriterWithSectionStartTag(stringBuilder, properties, "cacheRefreshInfo"); + } + + writer.WriteRawValue(latencyMetrics); + } + writer.WriteEndArray(); + + } + + if (requestInfoSnapshot?.Any() == true) + { + writer.WritePropertyName("requestInfo"); + writer.WriteStartArray(); + + foreach (KeyValuePair entry in requestInfoSnapshot) + { + long lengthNow = stringBuilder.Length; + + MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); + + RequestInfo payloadForLatency = entry.Key; + payloadForLatency.Metrics.Add(metricInfo); + string latencyMetrics = JsonConvert.SerializeObject(payloadForLatency); + + if (lengthNow + latencyMetrics.Length > ClientTelemetryOptions.PayloadSizeThreshold) + { + writer.WriteEndArray(); + writer.WriteEndObject(); + + await callback.Invoke(stringBuilder.ToString()); + + writer = ClientTelemetryPayloadWriter.GetWriterWithSectionStartTag(stringBuilder, properties, "requestInfo"); + } + + writer.WriteRawValue(latencyMetrics); + } + writer.WriteEndArray(); + } + + writer.WriteEndObject(); + + await callback.Invoke(stringBuilder.ToString()); + } + + private static JsonWriter GetWriterWithSectionStartTag( + StringBuilder stringBuilder, + ClientTelemetryProperties properties, + string sectionName) + { + stringBuilder.Clear(); + + StringWriter stringWriter = new StringWriter(stringBuilder); + + JsonWriter writer = new JsonTextWriter(stringWriter) + { + AutoCompleteOnClose = false + }; + + writer.WriteStartObject(); + + properties.Write(writer); + + writer.WritePropertyName(sectionName); + + writer.WriteStartArray(); + return writer; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs new file mode 100644 index 0000000000..b91eb96832 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs @@ -0,0 +1,142 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Collections.Concurrent; + using System.Net.Http; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using HdrHistogram; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Collections; + + internal class ClientTelemetryProcessor + { + private static readonly Uri endpointUrl = ClientTelemetryOptions.GetClientTelemetryEndpoint(); + + private readonly AuthorizationTokenProvider tokenProvider; + private readonly CosmosHttpClient httpClient; + + internal ClientTelemetryProcessor(CosmosHttpClient httpClient, AuthorizationTokenProvider tokenProvider) + { + this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); + this.tokenProvider = tokenProvider ?? throw new ArgumentNullException(nameof(tokenProvider)); + } + + /// + /// It will create Task to process and send client telemetry payload to Client Telemetry Service. + /// + /// + /// + /// + /// + /// + /// Task + internal async Task ProcessAndSendAsync( + ClientTelemetryProperties clientTelemetryInfo, + ConcurrentDictionary operationInfoSnapshot, + ConcurrentDictionary cacheRefreshInfoSnapshot, + ConcurrentDictionary requestInfoSnapshot, + CancellationToken cancellationToken) + { + try + { + await ClientTelemetryPayloadWriter.SerializedPayloadChunksAsync( + properties: clientTelemetryInfo, + operationInfoSnapshot: operationInfoSnapshot, + cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, + requestInfoSnapshot: requestInfoSnapshot, + callback: async (payload) => await this.SendAsync(clientTelemetryInfo.GlobalDatabaseAccountName, payload, cancellationToken)); + } + catch (Exception ex) + { + DefaultTrace.TraceError($"Exception while serializing telemetry payload: {ex}"); + throw; + } + + } + + /// + /// Task to send telemetry information to configured Juno endpoint. + /// If endpoint is not configured then it won't even try to send information. It will just trace an error message. + /// In any case it resets the telemetry information to collect the latest one. + /// + /// Async Task + private async Task SendAsync( + string globalDatabaseAccountName, + string jsonPayload, + CancellationToken cancellationToken) + { + if (endpointUrl == null) + { + DefaultTrace.TraceError("Telemetry is enabled but endpoint is not configured"); + return; + } + + try + { + DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl.AbsoluteUri); + + using HttpRequestMessage request = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = endpointUrl, + Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json") + }; + + async ValueTask CreateRequestMessage() + { + INameValueCollection headersCollection = new StoreResponseNameValueCollection(); + await this.tokenProvider.AddAuthorizationHeaderAsync( + headersCollection, + endpointUrl, + "POST", + AuthorizationTokenType.PrimaryMasterKey); + + foreach (string key in headersCollection.AllKeys()) + { + request.Headers.Add(key, headersCollection[key]); + } + + request.Headers.Add(HttpConstants.HttpHeaders.DatabaseAccountName, globalDatabaseAccountName); + String envName = ClientTelemetryOptions.GetEnvironmentName(); + if (!String.IsNullOrEmpty(envName)) + { + request.Headers.Add(HttpConstants.HttpHeaders.EnvironmentName, envName); + } + + return request; + } + + using HttpResponseMessage response = await this.httpClient.SendHttpAsync(CreateRequestMessage, + ResourceType.Telemetry, + HttpTimeoutPolicyNoRetry.Instance, + null, + cancellationToken); + + if (!response.IsSuccessStatusCode) + { + DefaultTrace.TraceError("Telemetry Service API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase); + throw new Exception(string.Format("Telemetry Service API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase)); + } + else + { + DefaultTrace.TraceInformation("Telemetry data sent successfully."); + } + + } + catch (Exception ex) + { + DefaultTrace.TraceError("Exception while sending telemetry data : {0}", ex.Message); + throw; + } + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs index 6ad08f694e..22089191fd 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Models/ClientTelemetryProperties.cs @@ -119,5 +119,77 @@ public ClientTelemetryProperties(string dateTimeUtc, this.PreferredRegions = preferredRegions; this.MachineId = machineId; } + + public void Write(JsonWriter writer) + { + writer.WritePropertyName("timeStamp"); + writer.WriteValue(this.DateTimeUtc); + + writer.WritePropertyName("clientId"); + writer.WriteValue(this.ClientId); + + writer.WritePropertyName("machineId"); + writer.WriteValue(this.MachineId); + + writer.WritePropertyName("processId"); + writer.WriteValue(this.ProcessId); + + writer.WritePropertyName("userAgent"); + writer.WriteValue(this.UserAgent); + + writer.WritePropertyName("connectionMode"); + writer.WriteValue(this.ConnectionMode); + + writer.WritePropertyName("globalDatabaseAccountName"); + writer.WriteValue(this.GlobalDatabaseAccountName); + + writer.WritePropertyName("applicationRegion"); + if (this.ApplicationRegion != null) + { + writer.WriteValue(this.ApplicationRegion); + } + else + { + writer.WriteNull(); + } + + writer.WritePropertyName("hostEnvInfo"); + writer.WriteValue(this.HostEnvInfo); + + writer.WritePropertyName("acceleratedNetworking"); + if (this.AcceleratedNetworking.HasValue) + { + writer.WriteValue(this.AcceleratedNetworking.Value); + } + else + { + writer.WriteNull(); + } + + writer.WritePropertyName("preferredRegions"); + + if (this.PreferredRegions != null) + { + writer.WriteStartArray(); + foreach (string region in this.PreferredRegions) + { + writer.WriteValue(region); + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull(); + } + + writer.WritePropertyName("aggregationIntervalInSec"); + writer.WriteValue(this.AggregationIntervalInSec); + + if (this.SystemInfo != null && this.SystemInfo.Count > 0) + { + writer.WritePropertyName("systemInfo"); + writer.WriteRawValue(JsonConvert.SerializeObject(this.SystemInfo)); + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index be6dfcd332..7e924ffd53 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -988,9 +988,23 @@ private static void AssertAccountLevelInformation( // Asserting If basic client telemetry object is as expected foreach (ClientTelemetryProperties telemetryInfo in localCopyOfActualInfo) { - actualOperationList.AddRange(telemetryInfo.OperationInfo); - actualSystemInformation.AddRange(telemetryInfo.SystemInfo); - actualRequestInformation.AddRange(telemetryInfo.RequestInfo); + if (telemetryInfo.OperationInfo != null) + { + actualOperationList.AddRange(telemetryInfo.OperationInfo); + } + + if (telemetryInfo.SystemInfo != null) + { + foreach (SystemInfo sysInfo in telemetryInfo.SystemInfo) + { + actualSystemInformation.Add(sysInfo); + } + } + + if (telemetryInfo.RequestInfo != null) + { + actualRequestInformation.AddRange(telemetryInfo.RequestInfo); + } if (telemetryInfo.ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) { @@ -1083,20 +1097,8 @@ public async Task CheckMisconfiguredTelemetryEndpoint_should_stop_the_job() mode: ConnectionMode.Direct, customHttpHandler: customHttpHandler); - // Create an item - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); - ItemResponse createResponse = await container.CreateItemAsync(testItem); - ToDoActivity testItemCreated = createResponse.Resource; - - // Read an Item - ItemResponse response = await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - await Task.Delay(1500); - - response = await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - await Task.Delay(3500); - + await Task.Delay(TimeSpan.FromMilliseconds(5000)); // wait for 5 sec, ideally telemetry would be sent 5 times but client telemetry endpoint is not functional (in this test), it should try 3 times maximum and after that client telemetry job should be stopped. + Assert.AreEqual(3, retryCounter); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 1d4e4e166c..4d25f7e5a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -34,6 +34,7 @@ + @@ -375,6 +376,9 @@ PreserveNewest + + PreserveNewest + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryPayloadWithoutMetrics.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryPayloadWithoutMetrics.json new file mode 100644 index 0000000000..a17f0fd74c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryPayloadWithoutMetrics.json @@ -0,0 +1,135 @@ +{ + "timeStamp": "2022-07-12T10:37:40Z", + "clientId": "1d5a40cf-d1a3-4ac5-ad34-307ad9243985", + "machineId": "vmId:d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd", + "processId": "dotnet", + "userAgent": "cosmos-netstandard-sdk/3.28.0|8|X64|Microsoft Windows 10.0.22000|.NET 6.0.6|L|F 00000010|", + "connectionMode": "DIRECT", + "globalDatabaseAccountName": "localhost", + "applicationRegion": "eastus", + "hostEnvInfo": "Linux|18.04-LTS|Standard_D2s_v3|AzurePublicCloud", + "preferredRegions": [ "region1", "region2" ], + "aggregationIntervalInSec": 1, + "acceleratedNetworking": false, + "systemInfo": [ + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "CPU", + "unitName": "Percentage", + "mean": 38.55, + "count": 4, + "min": 10.96, + "max": 73.27, + "percentiles": { + "50": 33.11, + "90": 73.27, + "95": 73.27, + "99": 73.27, + "99.9": 73.27 + } + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "MemoryRemaining", + "unitName": "MB", + "mean": 31904.0, + "count": 4, + "min": 31744.0, + "max": 31999.9990234375, + "percentiles": { + "50": 31999.9990234375, + "90": 31999.9990234375, + "95": 31999.9990234375, + "99": 31999.9990234375, + "99.9": 31999.9990234375 + } + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "SystemPool_AvailableThreads", + "unitName": "ThreadCount", + "mean": 32704.0, + "count": 4, + "min": 32640.0, + "max": 32767.0, + "percentiles": { + "50": 32767.0, + "90": 32767.0, + "95": 32767.0, + "99": 32767.0, + "99.9": 32767.0 + } + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "SystemPool_ThreadWaitInterval", + "unitName": "MilliSecond", + "mean": 0.1743, + "count": 3, + "min": 0.0488, + "max": 0.3359, + "percentiles": { + "50": 0.1391, + "90": 0.3359, + "95": 0.3359, + "99": 0.3359, + "99.9": 0.3359 + } + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "SystemPool_IsThreadStarving_True", + "unitName": "Count", + "mean": 0.1, + "count": 2, + "min": 0.1, + "max": 0.1 + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "RntbdOpenConnections", + "unitName": "Count", + "mean": 0.25, + "count": 4, + "min": 0.1, + "max": 1.0, + "percentiles": { + "50": 0.1, + "90": 1.0, + "95": 1.0, + "99": 1.0, + "99.9": 1.0 + } + } + }, + { + "resource": "HostMachine", + "metricInfo": { + "metricsName": "TcpNewChannelOpenLatency", + "unitName": "MilliSecond", + "mean": 0.25, + "count": 4, + "min": 0.1, + "max": 1.0, + "percentiles": { + "50": 0.1, + "90": 1.0, + "95": 1.0, + "99": 1.0, + "99.9": 1.0 + } + } + } + ] +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs new file mode 100644 index 0000000000..48cb0d1e42 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs @@ -0,0 +1,258 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Telemetry +{ + using System; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using HdrHistogram; + using Newtonsoft.Json; + using Microsoft.Azure.Cosmos.Telemetry; + using System.Collections.Generic; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using System.Text; + using System.IO; + using System.Net.Http; + using Moq; + using System.Threading.Tasks; + using System.Threading; + using System.Net; + using System.Collections.Concurrent; + + /// + /// Tests for . + /// + [TestClass] + public class ClientTelemetryTests + { + [TestCleanup] + public void Cleanup() + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); + } + + [TestMethod] + public void CheckMetricsAggregationLogic() + { + MetricInfo metrics = new MetricInfo("metricsName", "unitName"); + + LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, + long.MaxValue, + 5); + + histogram.RecordValue(10); + histogram.RecordValue(20); + histogram.RecordValue(30); + histogram.RecordValue(40); + + metrics.SetAggregators(histogram); + + Assert.AreEqual(40, metrics.Max); + Assert.AreEqual(10, metrics.Min); + Assert.AreEqual(4, metrics.Count); + Assert.AreEqual(25, metrics.Mean); + + Assert.AreEqual(20, metrics.Percentiles[ClientTelemetryOptions.Percentile50]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile90]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile95]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile99]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile999]); + } + + [TestMethod] + public void CheckMetricsAggregationLogicWithAdjustment() + { + MetricInfo metrics = new MetricInfo("metricsName", "unitName"); + long adjustmentFactor = 1000; + + LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, + long.MaxValue, + 5); + + histogram.RecordValue(10 * adjustmentFactor); + histogram.RecordValue(20 * adjustmentFactor); + histogram.RecordValue(30 * adjustmentFactor); + histogram.RecordValue(40 * adjustmentFactor); + + metrics.SetAggregators(histogram, adjustmentFactor); + + Assert.AreEqual(40, metrics.Max); + Assert.AreEqual(10, metrics.Min); + Assert.AreEqual(4, metrics.Count); + + Assert.AreEqual(25, metrics.Mean); + + Assert.AreEqual(20, metrics.Percentiles[ClientTelemetryOptions.Percentile50]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile90]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile95]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile99]); + Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile999]); + } + + [TestMethod] + public void CheckJsonSerializerContract() + { + string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", + processId: "", + userAgent: null, + connectionMode: ConnectionMode.Direct, + preferredRegions: null, + aggregationIntervalInSec: 10), ClientTelemetryOptions.JsonSerializerSettings); + Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"aggregationIntervalInSec\":10,\"systemInfo\":[]}", json); + } + + [TestMethod] + public void CheckJsonSerializerContractWithPreferredRegions() + { + List preferredRegion = new List + { + "region1" + }; + string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", + processId: "", + userAgent: null, + connectionMode: ConnectionMode.Direct, + preferredRegions: preferredRegion, + aggregationIntervalInSec: 1), ClientTelemetryOptions.JsonSerializerSettings); + Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"preferredRegions\":[\"region1\"],\"aggregationIntervalInSec\":1,\"systemInfo\":[]}", json); + } + + [TestMethod] + [DataRow(100, 50, 200)] // When operation, cacherefresh and request info is there in payload + [DataRow(0, 50, 0)] // When only cacherefresh info is there in payload + [DataRow(100, 50, 0)] // When only operation and cacherefresh info is there in payload + [DataRow(100, 0, 0)] // When only operation info is there in payload + public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInfoSize, int expectedCacheRefreshInfoSize, int expectedRequestInfoSize) + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); + ClientTelemetryOptions.PayloadSizeThreshold = 1024 * 15; //15 Kb + + string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); + ClientTelemetryProperties clientTelemetryProperties = JsonConvert.DeserializeObject(data); + + int totalPayloadSizeInBytes = data.Length; + + int actualOperationInfoSize = 0; + int actualCacheRefreshInfoSize = 0; + int actualRequestInfoSize = 0; + + Mock mockHttpHandler = new Mock(); + _ = mockHttpHandler.Setup(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Callback( + (request, cancellationToken) => + { + string payloadJson = request.Content.ReadAsStringAsync().Result; + Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); + + ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); + + Assert.AreEqual(7, propertiesToSend.SystemInfo.Count, "System Info is not correct"); + + actualOperationInfoSize += propertiesToSend.OperationInfo?.Count ?? 0; + actualCacheRefreshInfoSize += propertiesToSend.CacheRefreshInfo?.Count ?? 0; + actualRequestInfoSize += propertiesToSend.RequestInfo?.Count ?? 0; + }) + .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + + ClientTelemetryProcessor processor = new ClientTelemetryProcessor( + MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object))), + Mock.Of()); + + ConcurrentDictionary operationInfoSnapshot + = new ConcurrentDictionary(); + + for (int i = 0; i < (expectedOperationInfoSize/2); i++) + { + OperationInfo opeInfo = new OperationInfo(Regions.WestUS, + 0, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + 200, + 0); + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10l); + + LongConcurrentHistogram requestcharge = new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, + ClientTelemetryOptions.RequestChargeMax, + ClientTelemetryOptions.RequestChargePrecision); + requestcharge.RecordValue(11l); + + operationInfoSnapshot.TryAdd(opeInfo, (latency, requestcharge)); + } + + ConcurrentDictionary cacheRefreshInfoSnapshot + = new ConcurrentDictionary(); + for (int i = 0; i < expectedCacheRefreshInfoSize; i++) + { + CacheRefreshInfo crInfo = new CacheRefreshInfo(Regions.WestUS, + 10, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + 200, + 1002, + "dummycache") ; + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10l); + + cacheRefreshInfoSnapshot.TryAdd(crInfo, latency); + } + + ConcurrentDictionary requestInfoInfoSnapshot + = new ConcurrentDictionary(); + for (int i = 0; i < expectedRequestInfoSize; i++) + { + RequestInfo reqInfo = new RequestInfo + { + Uri = "https://dummyuri.com", + DatabaseName = "databaseName" + i, + ContainerName = "containerName" + i, + Operation = Documents.OperationType.Read.ToString(), + Resource = Documents.ResourceType.Document.ToString(), + StatusCode = 200, + SubStatusCode = 0 + }; + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10l); + + requestInfoInfoSnapshot.TryAdd(reqInfo, latency); + } + + await processor.ProcessAndSendAsync( + clientTelemetryProperties, + operationInfoSnapshot, + cacheRefreshInfoSnapshot, + requestInfoInfoSnapshot, + new CancellationToken()); + + Assert.AreEqual(expectedOperationInfoSize, actualOperationInfoSize, "Operation Info is not correct"); + Assert.AreEqual(expectedCacheRefreshInfoSize, actualCacheRefreshInfoSize, "Cache Refresh Info is not correct"); + Assert.AreEqual(expectedRequestInfoSize, actualRequestInfoSize, "Request Info is not correct"); + } + + [TestMethod] + [ExpectedException(typeof(FormatException))] + public void CheckMisconfiguredTelemetry_should_fail() + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "non-boolean"); + using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); + } + } +} From 682b0011dd8224fbbd8f66691abf28cb53929e28 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Fri, 10 Mar 2023 09:51:03 -0800 Subject: [PATCH 072/337] Query: Fixes regression from LINQ custom serializer fix (#3749) Co-authored-by: Minh Le Co-authored-by: Matias Quaranta --- .../src/Linq/ExpressionToSQL.cs | 17 -- .../Resource/Container/ContainerCore.Items.cs | 7 +- .../Serializer/CosmosLinqSerializerOptions.cs | 9 - ...BaselineTests.TestLiteralSerialization.xml | 2 +- ...rializerBaseline.TestMemberInitializer.xml | 48 ------ .../LinqTestsCommon.cs | 4 +- .../LinqTranslationBaselineTests.cs | 2 +- ...TranslationWithCustomSerializerBaseline.cs | 159 ------------------ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 4 - 9 files changed, 7 insertions(+), 245 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializer.xml delete mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index d15f67fece..476774e137 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; - using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -713,22 +712,6 @@ public static SqlScalarExpression VisitConstant(ConstantExpression inputExpressi return SqlArrayCreateScalarExpression.Create(arrayItems.ToImmutableArray()); } - if (context.linqSerializerOptions?.CustomCosmosSerializer != null) - { - StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); - - // Use the user serializer for the parameter values so custom conversions are correctly handled - using (Stream stream = context.linqSerializerOptions.CustomCosmosSerializer.ToStream(inputExpression.Value)) - { - using (StreamReader streamReader = new StreamReader(stream)) - { - string propertyValue = streamReader.ReadToEnd(); - writer.Write(propertyValue); - return CosmosElement.Parse(writer.ToString()).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); - } - } - } - return CosmosElement.Parse(JsonConvert.SerializeObject(inputExpression.Value)).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 31a3ccc5ca..a694b78019 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -505,14 +505,11 @@ public override IOrderedQueryable GetItemLinqQueryable( { requestOptions ??= new QueryRequestOptions(); - if (linqSerializerOptions == null && this.ClientContext.ClientOptions != null) + if (linqSerializerOptions == null && this.ClientContext.ClientOptions.SerializerOptions != null) { linqSerializerOptions = new CosmosLinqSerializerOptions { - PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions != null - ? this.ClientContext.ClientOptions.SerializerOptions.PropertyNamingPolicy - : CosmosPropertyNamingPolicy.Default, - CustomCosmosSerializer = this.ClientContext.ClientOptions.Serializer + PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions.PropertyNamingPolicy }; } diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs index 0affdde976..b7523b2c6a 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs @@ -22,15 +22,6 @@ public CosmosLinqSerializerOptions() this.PropertyNamingPolicy = CosmosPropertyNamingPolicy.Default; } - /// - /// Gets or sets the user defined customer serializer. If no customer serializer was defined, - /// then the value is set to the default value - /// - /// - /// The default value is null - /// - internal CosmosSerializer CustomCosmosSerializer { get; set; } - /// /// Gets or sets whether the naming policy used to convert a string-based name to another format, /// such as a camel-casing format. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestLiteralSerialization.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestLiteralSerialization.xml index b72807f399..c4c2fb38dd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestLiteralSerialization.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestLiteralSerialization.xml @@ -435,7 +435,7 @@ FROM root]]> diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializer.xml deleted file mode 100644 index 8763ef6866..0000000000 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializer.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - (doc == new DataObject() {NumericField = 12, StringField = "12"}))]]> - - - - - - - - - new DataObject() {NumericField = 12, StringField = "12"})]]> - - - - - - - - - IIF((doc.NumericField > 12), new DataObject() {NumericField = 12, StringField = "12"}, new DataObject() {NumericField = 12, StringField = "12"}))]]> - - - 12) ? {"number": 12, "String_value": "12", "id": null, "Pk": null} : {"number": 12, "String_value": "12", "id": null, "Pk": null}) -FROM root]]> - - - - - - (doc == new DataObject() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> - - - - - - \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs index 2b8f5c2d4a..5907d861fc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs @@ -455,7 +455,9 @@ Family createDataObj(Random random) return getQuery; } - public static Func> GenerateSimpleCosmosData(Cosmos.Database cosmosDatabase) + public static Func> GenerateSimpleCosmosData( + Cosmos.Database cosmosDatabase + ) { const int DocumentCount = 10; PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 01b64cd4fd..14aadd354f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -1,5 +1,5 @@ //----------------------------------------------------------------------- -// +// // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------- diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs deleted file mode 100644 index c81beaaeb8..0000000000 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs +++ /dev/null @@ -1,159 +0,0 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests -{ - using BaselineTest; - using Microsoft.Azure.Cosmos.Linq; - using Microsoft.Azure.Cosmos.Spatial; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Linq.Dynamic; - using System.Text; - using System.Text.Json; - using Microsoft.Azure.Documents; - using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using System.Threading.Tasks; - using global::Azure.Core.Serialization; - using System.IO; - using System.Text.Json.Serialization; - - [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] - public class LinqTranslationWithCustomSerializerBaseline : BaselineTests - { - private static CosmosClient cosmosClient; - private static Cosmos.Database testDb; - private static Container testContainer; - - [ClassInitialize] - public async static Task Initialize(TestContext textContext) - { - cosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) - => cosmosClientBuilder.WithCustomSerializer(new SystemTextJsonSerializer(new JsonSerializerOptions())).WithConnectionModeGateway()); - - string dbName = $"{nameof(LinqTranslationBaselineTests)}-{Guid.NewGuid().ToString("N")}"; - testDb = await cosmosClient.CreateDatabaseAsync(dbName); - } - - [ClassCleanup] - public async static Task CleanUp() - { - if (testDb != null) - { - await testDb.DeleteStreamAsync(); - } - - cosmosClient?.Dispose(); - } - - [TestInitialize] - public async Task TestInitialize() - { - testContainer = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")); - } - - [TestCleanup] - public async Task TestCleanUp() - { - await testContainer.DeleteContainerStreamAsync(); - } - - // Custom serializer that uses System.Text.Json.JsonSerializer instead of NewtonsoftJson.JsonSerializer - private class SystemTextJsonSerializer : CosmosSerializer - { - private readonly JsonObjectSerializer systemTextJsonSerializer; - - public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) - { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); - } - - public override T FromStream(Stream stream) - { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); - - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } - - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } - - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } - } - - public override Stream ToStream(T input) - { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, typeof(T), default); - streamPayload.Position = 0; - return streamPayload; - } - } - - internal class DataObject : LinqTestObject - { - [JsonPropertyName("number")] - public double NumericField { get; set; } - - [JsonPropertyName("String_value")] - public string StringField { get; set; } - - [JsonPropertyName("id")] - public string Id { get; set; } - - [JsonPropertyName("Pk")] - public string Pk { get; set; } - } - - [TestMethod] - public void TestMemberInitializer() - { - const int Records = 100; - const int NumAbsMax = 500; - const int MaxStringLength = 100; - DataObject createDataObj(Random random) - { - DataObject obj = new DataObject - { - NumericField = random.Next(NumAbsMax * 2) - NumAbsMax, - StringField = LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)), - Id = Guid.NewGuid().ToString(), - Pk = "Test" - }; - return obj; - } - Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, testContainer); - - List inputs = new List - { - new LinqTestInput("Filter w/ DataObject initializer with constant value", b => getQuery(b).Where(doc => doc == new DataObject() { NumericField = 12, StringField = "12" })), - new LinqTestInput("Select w/ DataObject initializer", b => getQuery(b).Select(doc => new DataObject() { NumericField = 12, StringField = "12" })), - new LinqTestInput("Deeper than top level reference", b => getQuery(b).Select(doc => doc.NumericField > 12 ? new DataObject() { NumericField = 12, StringField = "12" } : new DataObject() { NumericField = 12, StringField = "12" })), - - - // Negative test case: serializing only field name using custom serializer not currently supported - new LinqTestInput("Filter w/ DataObject initializer with member initialization", b => getQuery(b).Where(doc => doc == new DataObject() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A")) - }; - this.ExecuteTestSuite(inputs); - } - - - public override LinqTestOutput ExecuteTest(LinqTestInput input) - { - return LinqTestsCommon.ExecuteTest(input); - } - } -} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 10e0462cef..a504adc855 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -37,7 +37,6 @@ - @@ -248,9 +247,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From f2a3078bdb796d1234c2a7d52b3639bb8ddddc7a Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Fri, 10 Mar 2023 15:55:11 -0800 Subject: [PATCH 073/337] [Internal] LocalQuorum: Refactors override (i.e. strong) to allow from any account consistency (#3753) - Localquorum override (i.e. strong) to allow from any account consistency - Facilitates no-downtime downgrade of existing accounts (i.e. existing Strong/bounded accounts migration to Eventual) --- .../src/ValidationHelpers.cs | 9 +- .../ValidationHelpersTests.cs | 98 +++++++++++-------- 2 files changed, 56 insertions(+), 51 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs b/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs index 58a7a55ddb..4810d99f66 100644 --- a/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs +++ b/Microsoft.Azure.Cosmos/src/ValidationHelpers.cs @@ -55,7 +55,6 @@ public static bool IsValidConsistencyLevelOverwrite( { if (isLocalQuorumConsistency && ValidationHelpers.IsLocalQuorumConsistency( - backendConsistency: backendConsistency, desiredConsistency: desiredConsistency, operationType: operationType, resourceType: resourceType)) @@ -109,21 +108,15 @@ private static bool IsValidConsistencyLevelOverwrite( /// /// Condition to check Quorum(i.e. Strong) read with either an eventual consistency account or a consistent prefix account. /// - /// /// /// /// /// true/false - private static bool IsLocalQuorumConsistency(Documents.ConsistencyLevel backendConsistency, + private static bool IsLocalQuorumConsistency( Documents.ConsistencyLevel desiredConsistency, OperationType? operationType, ResourceType? resourceType) { - if (backendConsistency != Documents.ConsistencyLevel.Eventual && backendConsistency != Documents.ConsistencyLevel.ConsistentPrefix) - { - return false; - } - if (desiredConsistency != Documents.ConsistencyLevel.Strong) { return false; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs index 2c9db33cec..dbfc45eb36 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs @@ -4,6 +4,8 @@ namespace Microsoft.Azure.Cosmos.Tests { + using System; + using System.Collections.Generic; using System.Data; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -11,62 +13,72 @@ namespace Microsoft.Azure.Cosmos.Tests public class ValidationHelpersTest { [TestMethod] - [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)] - [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)] - [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)] - [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.BoundedStaleness)] - [DataRow(false, ConsistencyLevel.Session, ConsistencyLevel.Strong)] - [DataRow(false, ConsistencyLevel.BoundedStaleness, ConsistencyLevel.Strong)] - public void TestIsValidConsistencyLevelOverwrite(bool isValidConsistencyLevelOverwrite, - ConsistencyLevel backendConsistencyLevel, - ConsistencyLevel desiredConsistencyLevel) + [DataRow(true)] + [DataRow(false)] + public void TestIsValidConsistencyLevelOverwrite_AllCombinations( + bool isValidConsistencyLevelOverwrite) { - bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, - desiredConsistencyLevel, - true, - Documents.OperationType.Read, - Documents.ResourceType.Document); + ConsistencyLevel[] allConsistencies = Enum.GetValues(); + + // All overrides when target is 'Strong' are VALID + ConsistencyLevel desiredConsistencyLevel = ConsistencyLevel.Strong; + foreach (ConsistencyLevel backendConsistencyLevel in allConsistencies) + { + if (backendConsistencyLevel == desiredConsistencyLevel) + { + continue; + } + + foreach (KeyValuePair entry in ValidationHelpersTest.GetPerOperationExpectations()) + { + bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, + desiredConsistencyLevel, + isValidConsistencyLevelOverwrite, + (Documents.OperationType)entry.Key, + Documents.ResourceType.Document); - Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + Assert.AreEqual(isValidConsistencyLevelOverwrite && entry.Value, result, + $"({isValidConsistencyLevelOverwrite}, {backendConsistencyLevel}, {desiredConsistencyLevel}) ({entry.Key}, {entry.Value})"); + } + } } [TestMethod] - [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong)] - [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong)] - public void TestIsValidConsistencyLevelOverwrite_OnlyWhenSpecifyingExplicitOverwrite(bool isValidConsistencyLevelOverwrite, + [DataRow(ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)] + [DataRow(ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.BoundedStaleness)] + [DataRow(ConsistencyLevel.Session, ConsistencyLevel.BoundedStaleness)] + public void TestIsValidConsistencyLevelOverwrite_BoundedPromotionsRejected( ConsistencyLevel backendConsistencyLevel, ConsistencyLevel desiredConsistencyLevel) { - bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, - desiredConsistencyLevel, - false, - Documents.OperationType.Read, - Documents.ResourceType.Document); + foreach (KeyValuePair entry in ValidationHelpersTest.GetPerOperationExpectations()) + { + bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, + desiredConsistencyLevel, + true, + (Documents.OperationType)entry.Key, + Documents.ResourceType.Document); - Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + Assert.AreEqual(false, result, + $"({backendConsistencyLevel}, {desiredConsistencyLevel}) ({entry.Key}, {entry.Value})"); + } } - [TestMethod] - [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.Read)] - [DataRow(true, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.ReadFeed)] - [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Query)] - [DataRow(true, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.SqlQuery)] - [DataRow(false, ConsistencyLevel.Eventual, ConsistencyLevel.Strong, Documents.OperationType.QueryPlan)] - [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Create)] - [DataRow(false, ConsistencyLevel.ConsistentPrefix, ConsistencyLevel.Strong, Documents.OperationType.Batch)] - public void TestIsValidConsistencyLevelOverwrite_OnlyAllowedForCertainOperationTypes( - bool isValidConsistencyLevelOverwrite, - ConsistencyLevel backendConsistencyLevel, - ConsistencyLevel desiredConsistencyLevel, - dynamic operationType) + private static Dictionary GetPerOperationExpectations() { - bool result = ValidationHelpers.IsValidConsistencyLevelOverwrite(backendConsistencyLevel, - desiredConsistencyLevel, - true, - (Documents.OperationType) operationType, - Documents.ResourceType.Document); + Dictionary perOperationOverride = new Dictionary(); + + foreach (Documents.OperationType operationType in Enum.GetValues()) + { + perOperationOverride.Add( + operationType, + Documents.OperationTypeExtensions.IsReadOperation(operationType) + && operationType != Documents.OperationType.Head + && operationType != Documents.OperationType.HeadFeed + && operationType != Documents.OperationType.QueryPlan); + } - Assert.AreEqual(isValidConsistencyLevelOverwrite, result); + return perOperationOverride; } } } \ No newline at end of file From d41f0995618cb344fcaf3c16e002960493aaa016 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Fri, 10 Mar 2023 18:07:24 -0800 Subject: [PATCH 074/337] Release: Adds SDK version and change log for 3.32.2 (#3752) * version bump * contract * changelog * version bump * Fixing changelog text * Add another PR --- Directory.Build.props | 4 +- .../contracts/API_3.32.2-preview.txt | 1531 +++++++++++++++++ .../contracts/API_3.32.2.txt | 1478 ++++++++++++++++ changelog.md | 7 + 4 files changed, 3018 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.2-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.2.txt diff --git a/Directory.Build.props b/Directory.Build.props index aa8918e3b1..e7ca7a8727 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.32.1 - 3.32.1 + 3.32.2 + 3.32.2 preview 3.30.2 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.2-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.2-preview.txt new file mode 100644 index 0000000000..69b7a4b83e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.2-preview.txt @@ -0,0 +1,1531 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.2.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.2.txt new file mode 100644 index 0000000000..5218206b0e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.2.txt @@ -0,0 +1,1478 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index b201ba77fb..a8a156b922 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,13 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.32.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.2) - 2023-03-10 +### [3.32.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.2-preview) - 2023-03-10 + +#### Fixed +- [#3713](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3713) CosmosNullReferenceException: Refactors CosmosNullReferenceException to pass along InnerException property on parent NullReferenceException. +- [#3749](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3749) Query: Fixes regression from LINQ custom serializer fix. Introduced in 3.32.0 PR [3749](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3749) + ### [3.32.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.1) - 2023-03-01 ### [3.32.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.1-preview) - 2023-03-01 From 1acfaa280561286d661605b3a793b4e2d1790ada Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Tue, 21 Mar 2023 16:21:35 -0700 Subject: [PATCH 075/337] Subpartitioning: Adds APIs for public release and increase REST API version (#3763) * initial commit, Http version issues still needs to be resolved * updateContracts + update Http Version * updateded version in test * update contracts * requested changed * changed name in comments to subpartitioning from multihash * undid changes to TestLiteralSerialization.xml * removed changes to non API.json files * removed non XXXAPI.json file changes * changed verbage on public comments * changed error message to reflect verbage change --- Microsoft.Azure.Cosmos/src/CosmosClient.cs | 5 +- .../src/PartitionKeyBuilder.cs | 7 +-- .../src/Resource/Database/DatabaseCore.cs | 8 +-- .../Resource/Settings/ContainerProperties.cs | 26 ++------ .../CosmosContainerTests.cs | 4 +- .../CosmosMultiHashTest.cs | 7 --- .../CosmosReadManyItemsTests.cs | 39 +----------- .../Contracts/ContractTests.cs | 6 +- .../Contracts/DotNetPreviewSDKAPI.json | 63 ------------------- .../Contracts/DotNetSDKAPI.json | 63 +++++++++++++++++++ 10 files changed, 77 insertions(+), 151 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index e5ca2d8b53..d4fe7dcb9b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -115,11 +115,8 @@ public class CosmosClient : IDisposable static CosmosClient() { -#if PREVIEW HttpConstants.Versions.CurrentVersion = HttpConstants.Versions.v2020_07_15; -#else - HttpConstants.Versions.CurrentVersion = HttpConstants.Versions.v2018_12_31; -#endif + HttpConstants.Versions.CurrentVersionUTF8 = Encoding.UTF8.GetBytes(HttpConstants.Versions.CurrentVersion); ServiceInteropWrapper.AssembliesExist = new Lazy(() => diff --git a/Microsoft.Azure.Cosmos/src/PartitionKeyBuilder.cs b/Microsoft.Azure.Cosmos/src/PartitionKeyBuilder.cs index 6154921a86..e9b0e70a7d 100644 --- a/Microsoft.Azure.Cosmos/src/PartitionKeyBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/PartitionKeyBuilder.cs @@ -11,12 +11,7 @@ namespace Microsoft.Azure.Cosmos /// /// Represents a partition key value list in the Azure Cosmos DB service. /// -#if PREVIEW - public -#else - internal -#endif - sealed class PartitionKeyBuilder + public sealed class PartitionKeyBuilder { private readonly List partitionKeyValues; diff --git a/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseCore.cs index f8bbb95276..5f97a15286 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Database/DatabaseCore.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos { using System; + using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -15,10 +16,6 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; -#if PREVIEW - using System.Collections.Generic; -#endif - /// /// Operations for reading or deleting an existing database. /// @@ -219,7 +216,6 @@ public async Task CreateContainerIfNotExistsAsync( nameof(containerProperties.PartitionKey)); } } -#if PREVIEW else { IReadOnlyList retrivedPartitionKeyPaths = retrivedContainerResponse.Resource.PartitionKeyPaths; @@ -236,7 +232,7 @@ public async Task CreateContainerIfNotExistsAsync( nameof(containerProperties.PartitionKey)); } } -#endif + return retrivedContainerResponse; } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs index b95efb99c8..94cb93cff5 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs @@ -112,14 +112,8 @@ public ContainerProperties(string id, string partitionKeyPath) /// Initializes a new instance of the class for the Azure Cosmos DB service. /// /// The Id of the resource in the Azure Cosmos service. - /// The path to the partition key. Example: /location -#if PREVIEW - public -#else - internal -#endif - - ContainerProperties(string id, IReadOnlyList partitionKeyPaths) + /// The paths of the hierarchical partition keys. Example: ["/tenantId", "/userId"] + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths) { this.Id = id; @@ -347,12 +341,11 @@ public string PartitionKeyPath { get { -#if PREVIEW if (this.PartitionKey?.Kind == PartitionKind.MultiHash && this.PartitionKey?.Paths.Count > 1) { - throw new NotImplementedException($"This MultiHash collection has more than 1 partition key path please use `PartitionKeyPaths`"); + throw new NotImplementedException($"This subpartitioned container has more than 1 partition key path please use `PartitionKeyPaths`"); } -#endif + return this.PartitionKey?.Paths != null && this.PartitionKey.Paths.Count > 0 ? this.PartitionKey?.Paths[0] : null; } set @@ -377,15 +370,10 @@ public string PartitionKeyPath } /// - /// JSON path used for containers partitioning + /// List of JSON paths used for containers with hierarchical partition keys /// [JsonIgnore] -#if PREVIEW - public -#else - internal -#endif - IReadOnlyList PartitionKeyPaths + public IReadOnlyList PartitionKeyPaths { get => this.PartitionKey?.Paths; set @@ -657,12 +645,10 @@ internal IReadOnlyList> PartitionKeyPathTokens throw new ArgumentOutOfRangeException($"Container {this.Id} is not partitioned"); } -#if PREVIEW if (this.PartitionKey.Kind == Documents.PartitionKind.MultiHash && this.PartitionKeyPaths == null) { throw new ArgumentOutOfRangeException($"Container {this.Id} is not partitioned"); } -#endif List> partitionKeyPathTokensList = new List>(); foreach (string path in this.PartitionKey?.Paths) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs index 07cb6a4dca..f3befc588b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs @@ -11,6 +11,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Linq; using System.Net; using System.Threading.Tasks; + using HttpConstants = Microsoft.Azure.Documents.HttpConstants; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -22,6 +23,7 @@ public class CosmosContainerTests { private CosmosClient cosmosClient = null; private Cosmos.Database cosmosDatabase = null; + private static long ToEpoch(DateTime dateTime) { return (long)(dateTime - new DateTime(1970, 1, 1)).TotalSeconds; @@ -713,7 +715,6 @@ public async Task GetFeedRangeOnContainerRecreateScenariosTestAsync() } } -#if PREVIEW //MultiHash container checks. [TestMethod] public async Task CreateContainerIfNotExistsAsyncForMultiHashCollectionsTest() @@ -798,7 +799,6 @@ public async Task CreateContainerIfNotExistsAsyncForMultiHashCollectionsTest() } -#endif [TestMethod] public async Task StreamPartitionedCreateWithPathDelete() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs index 3c590092db..5307145dfc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -18,13 +18,9 @@ public class CosmosMultiHashTest private Container container = null; private ContainerProperties containerProperties = null; - private readonly string currentVersion = HttpConstants.Versions.CurrentVersion; - - [TestInitialize] public async Task TestInitialize() { - HttpConstants.Versions.CurrentVersion = "2020-07-15"; this.client = TestCommon.CreateCosmosClient(true); this.database = await this.client.CreateDatabaseIfNotExistsAsync("mydb"); @@ -37,9 +33,6 @@ public async Task Cleanup() { await this.database.DeleteAsync(); this.client.Dispose(); - - HttpConstants.Versions.CurrentVersion = this.currentVersion; - this.client.Dispose(); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs index c3949d763f..d215b6b18b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs @@ -510,44 +510,7 @@ await container.CreateItemAsync( await database.DeleteAsync(); client.Dispose(); - } - -#if PREVIEW - [TestMethod] - public async Task ReadManyMultiplePK() - { - IReadOnlyList pkPaths = new List { "/pk", "/description" }; - ContainerProperties containerSettings = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPaths: pkPaths); - Container container = await this.database.CreateContainerAsync(containerSettings); - - for (int i = 0; i < 5; i++) - { - ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); - item.pk = "pk" + i.ToString(); - item.id = i.ToString(); - item.description = "description" + i; - ItemResponse itemResponse = await container.CreateItemAsync(item); - Assert.AreEqual(HttpStatusCode.Created, itemResponse.StatusCode); - } - - List<(string, PartitionKey)> itemList = new List<(string, PartitionKey)>(); - for (int i = 0; i < 5; i++) - { - PartitionKey partitionKey = new PartitionKeyBuilder() - .Add("pk" + i) - .Add("description" + i) - .Build(); - - itemList.Add((i.ToString(), partitionKey)); - } - - FeedResponse feedResponse = await container.ReadManyItemsAsync(itemList); - Assert.IsNotNull(feedResponse); - Assert.AreEqual(feedResponse.Count, 5); - Assert.IsTrue(feedResponse.Headers.RequestCharge > 0); - Assert.IsNotNull(feedResponse.Diagnostics); - } -#endif + } private class NestedToDoActivity { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractTests.cs index 9501dee4ce..a4d295a634 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractTests.cs @@ -23,13 +23,9 @@ public void ApiVersionTest() } catch(ArgumentNullException) { } -#if PREVIEW + Assert.AreEqual(HttpConstants.Versions.v2020_07_15, HttpConstants.Versions.CurrentVersion); CollectionAssert.AreEqual(Encoding.UTF8.GetBytes(HttpConstants.Versions.v2020_07_15), HttpConstants.Versions.CurrentVersionUTF8); -#else - Assert.AreEqual(HttpConstants.Versions.v2018_12_31, HttpConstants.Versions.CurrentVersion); - CollectionAssert.AreEqual(Encoding.UTF8.GetBytes(HttpConstants.Versions.v2018_12_31), HttpConstants.Versions.CurrentVersionUTF8); -#endif ulong capabilitites = SDKSupportedCapabilitiesHelpers.GetSDKSupportedCapabilities(); Assert.AreEqual(capabilitites & (ulong)SDKSupportedCapabilities.PartitionMerge, (ulong)SDKSupportedCapabilities.PartitionMerge); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 43801584fe..39ae1d2eca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -284,32 +284,10 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedPolicy get_ChangeFeedPolicy();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths()": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.Collections.Generic.IReadOnlyList`1[System.String] PartitionKeyPaths[Newtonsoft.Json.JsonIgnoreAttribute()]": { - "Type": "Property", - "Attributes": [ - "JsonIgnoreAttribute" - ], - "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[System.String] PartitionKeyPaths;CanRead:True;CanWrite:True;System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String])": { - "Type": "Constructor", - "Attributes": [], - "MethodInfo": "[Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String]), Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String])]" - }, "Void set_ChangeFeedPolicy(Microsoft.Azure.Cosmos.ChangeFeedPolicy)": { "Type": "Method", "Attributes": [], "MethodInfo": "Void set_ChangeFeedPolicy(Microsoft.Azure.Cosmos.ChangeFeedPolicy);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String])": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} @@ -384,47 +362,6 @@ } }, "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Microsoft.Azure.Cosmos.PartitionKey Build()": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKey Build();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Boolean)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Double)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Double);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(System.String)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNoneType()": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNoneType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNullValue()": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNullValue();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void .ctor()": { - "Type": "Constructor", - "Attributes": [], - "MethodInfo": "[Void .ctor(), Void .ctor()]" - } - }, - "NestedTypes": {} } }, "Members": {}, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 9edd8d6de1..3cf5c017c2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2167,6 +2167,18 @@ ], "MethodInfo": "Microsoft.Azure.Cosmos.UniqueKeyPolicy UniqueKeyPolicy;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.UniqueKeyPolicy get_UniqueKeyPolicy();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_UniqueKeyPolicy(Microsoft.Azure.Cosmos.UniqueKeyPolicy);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.IReadOnlyList`1[System.String] PartitionKeyPaths[Newtonsoft.Json.JsonIgnoreAttribute()]": { + "Type": "Property", + "Attributes": [ + "JsonIgnoreAttribute" + ], + "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[System.String] PartitionKeyPaths;CanRead:True;CanWrite:True;System.Collections.Generic.IReadOnlyList`1[System.String] get_PartitionKeyPaths();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Nullable`1[Microsoft.Azure.Cosmos.PartitionKeyDefinitionVersion] get_PartitionKeyDefinitionVersion()": { "Type": "Method", "Attributes": [], @@ -2294,6 +2306,11 @@ "Attributes": [], "MethodInfo": "[Void .ctor(), Void .ctor()]" }, + "Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String])": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String]), Void .ctor(System.String, System.Collections.Generic.IReadOnlyList`1[System.String])]" + }, "Void .ctor(System.String, System.String)": { "Type": "Constructor", "Attributes": [], @@ -2348,6 +2365,11 @@ "Attributes": [], "MethodInfo": "Void set_PartitionKeyPath(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String])": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void set_PartitionKeyPaths(System.Collections.Generic.IReadOnlyList`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_TimeToLivePropertyPath(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -5589,6 +5611,47 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.PartitionKey Build()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKey Build();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Boolean)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Double)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(Double);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(System.String)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder Add(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNoneType()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNoneType();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNullValue()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PartitionKeyBuilder AddNullValue();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.PartitionKeyDefinitionVersion;System.Enum;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:True;IsClass:False;IsValueType:True;IsNested:False;IsGenericType:False;IsSerializable:True": { "Subclasses": {}, "Members": { From d0c05781c6953128167b0a0eb4b023d2e56066c2 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 22 Mar 2023 19:47:03 -0700 Subject: [PATCH 076/337] Change Feed Processor: Fixes LeaseLostException leaks on notification APIs for Renew scenarios (#3775) * Adding cases * Tests --- .../DocumentServiceLeaseManagerCosmos.cs | 48 ++++- .../DocumentServiceLeaseManagerCosmosTests.cs | 195 ++++++++++++++++++ 2 files changed, 239 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs index 260bff3161..d5a75abb47 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs @@ -190,7 +190,17 @@ await this.leaseUpdater.UpdateLeaseAsync( if (serverLease.Owner != lease.Owner) { DefaultTrace.TraceInformation("Lease with token {0} no need to release lease. The lease was already taken by another host '{1}'.", lease.CurrentLeaseToken, serverLease.Owner); - throw new LeaseLostException(lease); + throw new LeaseLostException( + lease, + CosmosExceptionFactory.Create( + statusCode: HttpStatusCode.PreconditionFailed, + message: $"{lease.CurrentLeaseToken} lease token was taken over by owner '{serverLease.Owner}'", + headers: new Headers(), + stackTrace: default, + trace: NoOpTrace.Singleton, + error: default, + innerException: default), + isGone: false); } serverLease.Owner = null; return serverLease; @@ -232,7 +242,17 @@ public override async Task RenewAsync(DocumentServiceLease if (serverLease.Owner != lease.Owner) { DefaultTrace.TraceInformation("Lease with token {0} was taken over by owner '{1}'", lease.CurrentLeaseToken, serverLease.Owner); - throw new LeaseLostException(lease); + throw new LeaseLostException( + lease, + CosmosExceptionFactory.Create( + statusCode: HttpStatusCode.PreconditionFailed, + message: $"{lease.CurrentLeaseToken} lease token was taken over by owner '{serverLease.Owner}'", + headers: new Headers(), + stackTrace: default, + trace: NoOpTrace.Singleton, + error: default, + innerException: default), + isGone: false); } return serverLease; }).ConfigureAwait(false); @@ -245,7 +265,17 @@ public override async Task UpdatePropertiesAsync(DocumentS if (lease.Owner != this.options.HostName) { DefaultTrace.TraceInformation("Lease with token '{0}' was taken over by owner '{1}' before lease properties update", lease.CurrentLeaseToken, lease.Owner); - throw new LeaseLostException(lease); + throw new LeaseLostException( + lease, + CosmosExceptionFactory.Create( + statusCode: HttpStatusCode.PreconditionFailed, + message: $"{lease.CurrentLeaseToken} lease token was taken over by owner '{lease.Owner}'", + headers: new Headers(), + stackTrace: default, + trace: NoOpTrace.Singleton, + error: default, + innerException: default), + isGone: false); } return await this.leaseUpdater.UpdateLeaseAsync( @@ -257,7 +287,17 @@ public override async Task UpdatePropertiesAsync(DocumentS if (serverLease.Owner != lease.Owner) { DefaultTrace.TraceInformation("Lease with token '{0}' was taken over by owner '{1}'", lease.CurrentLeaseToken, serverLease.Owner); - throw new LeaseLostException(lease); + throw new LeaseLostException( + lease, + CosmosExceptionFactory.Create( + statusCode: HttpStatusCode.PreconditionFailed, + message: $"{lease.CurrentLeaseToken} lease token was taken over by owner '{serverLease.Owner}'", + headers: new Headers(), + stackTrace: default, + trace: NoOpTrace.Singleton, + error: default, + innerException: default), + isGone: false); } serverLease.Properties = lease.Properties; return serverLease; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseManagerCosmosTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseManagerCosmosTests.cs index 19a0710e66..88f945ae43 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseManagerCosmosTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseManagerCosmosTests.cs @@ -356,6 +356,201 @@ public async Task IfOwnerChangedThrow() && innerCosmosException.StatusCode == HttpStatusCode.PreconditionFailed); } + /// + /// Verifies that if the renewed read a different Owner from the captured in memory, throws a LeaseLost + /// + [TestMethod] + public async Task IfOwnerChangedThrowOnRenew() + { + DocumentServiceLeaseStoreManagerOptions options = new DocumentServiceLeaseStoreManagerOptions + { + HostName = Guid.NewGuid().ToString() + }; + + DocumentServiceLeaseCore lease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + + Mock mockUpdater = new Mock(); + + Func, bool> validateUpdater = (Func updater) => + { + // Simulate dirty read from db + DocumentServiceLeaseCore serverLease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + DocumentServiceLease afterUpdateLease = updater(serverLease); + return true; + }; + + mockUpdater.Setup(c => c.UpdateLeaseAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is>(f => validateUpdater(f)))) + .ReturnsAsync(lease); + + ResponseMessage leaseResponse = new ResponseMessage(System.Net.HttpStatusCode.OK) + { + Content = new CosmosJsonDotNetSerializer().ToStream(lease) + }; + + Mock leaseContainer = new Mock(); + leaseContainer.Setup(c => c.ReadItemStreamAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(leaseResponse); + + DocumentServiceLeaseManagerCosmos documentServiceLeaseManagerCosmos = new DocumentServiceLeaseManagerCosmos( + Mock.Of(), + leaseContainer.Object, + mockUpdater.Object, + options, + Mock.Of()); + + LeaseLostException leaseLost = await Assert.ThrowsExceptionAsync(() => documentServiceLeaseManagerCosmos.RenewAsync(lease)); + + Assert.IsTrue(leaseLost.InnerException is CosmosException innerCosmosException + && innerCosmosException.StatusCode == HttpStatusCode.PreconditionFailed); + } + + /// + /// Verifies that if the update properties read a different Owner from the captured in memory, throws a LeaseLost + /// + [TestMethod] + public async Task IfOwnerChangedThrowOnUpdateProperties() + { + DocumentServiceLeaseCore lease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + + DocumentServiceLeaseStoreManagerOptions options = new DocumentServiceLeaseStoreManagerOptions + { + HostName = lease.Owner + }; + + Mock mockUpdater = new Mock(); + + Func, bool> validateUpdater = (Func updater) => + { + // Simulate dirty read from db + DocumentServiceLeaseCore serverLease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + DocumentServiceLease afterUpdateLease = updater(serverLease); + return true; + }; + + mockUpdater.Setup(c => c.UpdateLeaseAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is>(f => validateUpdater(f)))) + .ReturnsAsync(lease); + + ResponseMessage leaseResponse = new ResponseMessage(System.Net.HttpStatusCode.OK) + { + Content = new CosmosJsonDotNetSerializer().ToStream(lease) + }; + + Mock leaseContainer = new Mock(); + leaseContainer.Setup(c => c.ReadItemStreamAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(leaseResponse); + + DocumentServiceLeaseManagerCosmos documentServiceLeaseManagerCosmos = new DocumentServiceLeaseManagerCosmos( + Mock.Of(), + leaseContainer.Object, + mockUpdater.Object, + options, + Mock.Of()); + + LeaseLostException leaseLost = await Assert.ThrowsExceptionAsync(() => documentServiceLeaseManagerCosmos.UpdatePropertiesAsync(lease)); + + Assert.IsTrue(leaseLost.InnerException is CosmosException innerCosmosException + && innerCosmosException.StatusCode == HttpStatusCode.PreconditionFailed); + } + + /// + /// Verifies that if the update properties read a different Owner from the captured in memory, throws a LeaseLost + /// + [TestMethod] + public async Task IfOwnerChangedThrowOnRelease() + { + DocumentServiceLeaseStoreManagerOptions options = new DocumentServiceLeaseStoreManagerOptions + { + HostName = Guid.NewGuid().ToString() + }; + + DocumentServiceLeaseCore lease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + + Mock mockUpdater = new Mock(); + + Func, bool> validateUpdater = (Func updater) => + { + // Simulate dirty read from db + DocumentServiceLeaseCore serverLease = new DocumentServiceLeaseCore() + { + LeaseToken = "0", + Owner = Guid.NewGuid().ToString(), + FeedRange = new FeedRangePartitionKeyRange("0") + }; + DocumentServiceLease afterUpdateLease = updater(serverLease); + return true; + }; + + mockUpdater.Setup(c => c.UpdateLeaseAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.Is>(f => validateUpdater(f)))) + .ReturnsAsync(lease); + + ResponseMessage leaseResponse = new ResponseMessage(System.Net.HttpStatusCode.OK) + { + Content = new CosmosJsonDotNetSerializer().ToStream(lease) + }; + + Mock leaseContainer = new Mock(); + leaseContainer.Setup(c => c.ReadItemStreamAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(leaseResponse); + + DocumentServiceLeaseManagerCosmos documentServiceLeaseManagerCosmos = new DocumentServiceLeaseManagerCosmos( + Mock.Of(), + leaseContainer.Object, + mockUpdater.Object, + options, + Mock.Of()); + + LeaseLostException leaseLost = await Assert.ThrowsExceptionAsync(() => documentServiceLeaseManagerCosmos.ReleaseAsync(lease)); + + Assert.IsTrue(leaseLost.InnerException is CosmosException innerCosmosException + && innerCosmosException.StatusCode == HttpStatusCode.PreconditionFailed); + } + /// /// When a lease is missing the range information, check that we are adding it /// From 4ab62933d2e8ab33c5ad1be7d2d9e711d1a51776 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 23 Mar 2023 10:57:39 -0700 Subject: [PATCH 077/337] Upgrade Resiliency: Refactors GatewayAddressCache to Mark TransportAddresses to Unhealthy when Connection Reset Event Occurs (#3768) * Code changes to mark the transport uri to unhealthy for which a connection reset event occures through the connection state listener. * Code changes to bump up the direct version. * Code changes to clean up Gateway Address Cache. * Code changes to fix pipeline build. * Code changes to fix serilization test failures. * Code changes to add force refresh to the gateway function callback delegate. --- Directory.Build.props | 2 +- .../src/Routing/GatewayAddressCache.cs | 61 ++++++++++--------- .../src/Routing/GlobalAddressResolver.cs | 25 ++------ .../GatewayAddressCacheTests.cs | 38 ++++++++---- .../Tracing/TraceTests.cs | 2 + 5 files changed, 66 insertions(+), 62 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index e7ca7a8727..39004a08ab 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.32.2 3.32.2 preview - 3.30.2 + 3.30.4 2.0.1 2.0.1 preview diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index b577443761..eba425fb0d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -387,7 +387,13 @@ private static void LogPartitionCacheRefresh( } } - public void TryRemoveAddresses( + /// + /// Marks the to Unhealthy that matches with the faulted + /// server key. + /// + /// An instance of that contains the host and + /// port of the backend replica. + public async Task MarkAddressesToUnhealthyAsync( ServerKey serverKey) { if (serverKey == null) @@ -395,7 +401,7 @@ public void TryRemoveAddresses( throw new ArgumentNullException(nameof(serverKey)); } - if (this.serverPartitionAddressToPkRangeIdMap.TryRemove(serverKey, out HashSet pkRangeIds)) + if (this.serverPartitionAddressToPkRangeIdMap.TryGetValue(serverKey, out HashSet pkRangeIds)) { PartitionKeyRangeIdentity[] pkRangeIdsCopy; lock (pkRangeIds) @@ -405,36 +411,35 @@ public void TryRemoveAddresses( foreach (PartitionKeyRangeIdentity pkRangeId in pkRangeIdsCopy) { - DefaultTrace.TraceInformation("Remove addresses for collectionRid :{0}, pkRangeId: {1}, serviceEndpoint: {2}", - pkRangeId.CollectionRid, - pkRangeId.PartitionKeyRangeId, - this.serviceEndpoint); - - this.serverPartitionAddressCache.TryRemove(pkRangeId); - } - } - } - - public async Task UpdateAsync( - PartitionKeyRangeIdentity partitionKeyRangeIdentity, - CancellationToken cancellationToken) - { - if (partitionKeyRangeIdentity == null) - { - throw new ArgumentNullException(nameof(partitionKeyRangeIdentity)); - } - - cancellationToken.ThrowIfCancellationRequested(); - - return await this.serverPartitionAddressCache.GetAsync( - key: partitionKeyRangeIdentity, + // The forceRefresh flag is set to true for the callback delegate is because, if the GetAsync() from the async + // non-blocking cache fails to look up the pkRangeId, then there are some inconsistency present in the cache, and it is + // more safe to do a force refresh to fetch the addresses from the gateway, instead of fetching it from the cache itself. + // Please note that, the chances of encountering such scenario is highly unlikely. + PartitionAddressInformation addressInfo = await this.serverPartitionAddressCache.GetAsync( + key: pkRangeId, singleValueInitFunc: (_) => this.GetAddressesForRangeIdAsync( null, cachedAddresses: null, - partitionKeyRangeIdentity.CollectionRid, - partitionKeyRangeIdentity.PartitionKeyRangeId, + pkRangeId.CollectionRid, + pkRangeId.PartitionKeyRangeId, forceRefresh: true), - forceRefresh: (_) => true); + forceRefresh: (_) => false); + + IReadOnlyList transportAddresses = addressInfo.Get(Protocol.Tcp)?.ReplicaTransportAddressUris; + foreach (TransportAddressUri address in from TransportAddressUri transportAddress in transportAddresses + where serverKey.Equals(transportAddress.ReplicaServerKey) + select transportAddress) + { + DefaultTrace.TraceInformation("Marking a backend replica to Unhealthy for collectionRid :{0}, pkRangeId: {1}, serviceEndpoint: {2}, transportAddress: {3}", + pkRangeId.CollectionRid, + pkRangeId.PartitionKeyRangeId, + this.serviceEndpoint, + address.ToString()); + + address.SetUnhealthy(); + } + } + } } private async Task> ResolveMasterAsync(DocumentServiceRequest request, bool forceRefresh) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs index 51a6c6d2f3..344f994395 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs @@ -228,33 +228,16 @@ public async Task ResolveAsync( } public async Task UpdateAsync( - IReadOnlyList addressCacheTokens, - CancellationToken cancellationToken) - { - List tasks = new List(); - - foreach (AddressCacheToken cacheToken in addressCacheTokens) - { - if (this.addressCacheByEndpoint.TryGetValue(cacheToken.ServiceEndpoint, out EndpointCache endpointCache)) - { - tasks.Add(endpointCache.AddressCache.UpdateAsync(cacheToken.PartitionKeyRangeIdentity, cancellationToken)); - } - } - - await Task.WhenAll(tasks); - } - - public Task UpdateAsync( ServerKey serverKey, CancellationToken cancellationToken) { foreach (KeyValuePair addressCache in this.addressCacheByEndpoint) { - // since we don't know which address cache contains the pkRanges mapped to this node, we do a tryRemove on all AddressCaches of all regions - addressCache.Value.AddressCache.TryRemoveAddresses(serverKey); + // since we don't know which address cache contains the pkRanges mapped to this node, + // we mark all transport uris that has the same server key to unhealthy status in the + // AddressCaches of all regions. + await addressCache.Value.AddressCache.MarkAddressesToUnhealthyAsync(serverKey); } - - return Task.CompletedTask; } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 9e3b87ec83..809814aef1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -18,6 +18,8 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Client; + using Microsoft.Azure.Documents.Rntbd; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -108,8 +110,11 @@ public void TestGatewayAddressCacheAutoRefreshOnSuboptimalPartition() public async Task TestGatewayAddressCacheUpdateOnConnectionResetAsync() { FakeMessageHandler messageHandler = new FakeMessageHandler(); - HttpClient httpClient = new HttpClient(messageHandler); - httpClient.Timeout = TimeSpan.FromSeconds(120); + HttpClient httpClient = new HttpClient(messageHandler) + { + Timeout = TimeSpan.FromSeconds(120) + }; + GatewayAddressCache cache = new GatewayAddressCache( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Tcp, @@ -129,8 +134,9 @@ public async Task TestGatewayAddressCacheUpdateOnConnectionResetAsync() Assert.IsNotNull(addresses.AllAddresses.Select(address => address.PhysicalUri == "https://blabla.com")); - // call updateAddress - cache.TryRemoveAddresses(new Documents.Rntbd.ServerKey(new Uri("https://blabla.com"))); + // Mark transport addresses to Unhealthy depcting a connection reset event. + ServerKey faultyServerKey = new (new Uri("https://blabla2.com")); + await cache.MarkAddressesToUnhealthyAsync(faultyServerKey); // check if the addresss is updated addresses = await cache.TryGetAddressesAsync( @@ -140,7 +146,15 @@ public async Task TestGatewayAddressCacheUpdateOnConnectionResetAsync() false, CancellationToken.None); - Assert.IsNotNull(addresses.AllAddresses.Select(address => address.PhysicalUri == "https://blabla5.com")); + // Validate that the above transport uri with host blabla2.com has been marked Unhealthy. + IReadOnlyList transportAddressUris = addresses + .Get(Protocol.Tcp)? + .ReplicaTransportAddressUris; + + TransportAddressUri transportAddressUri = transportAddressUris + .Single(x => x.ReplicaServerKey.Equals(faultyServerKey)); + + Assert.IsTrue(condition: transportAddressUri.GetCurrentHealthState().GetHealthStatus().Equals(TransportAddressHealthState.HealthStatus.Unhealthy)); } [TestMethod] @@ -1458,23 +1472,23 @@ public int GetMethodInvocationCount() } Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( - IReadOnlyList addresses) + IEnumerable addresses) { - this.totalReceivedAddressesCounter = addresses.Count; - for (int i = 0; i < addresses.Count; i++) + this.totalReceivedAddressesCounter = addresses.Count(); + for (int i = 0; i < addresses.Count(); i++) { if (this.useAttemptBasedFailingIndexs) { if (this.failIndexesByAttempts.ContainsKey(i) && this.failIndexesByAttempts[i].Contains(this.methodInvocationCounter)) { this.ExecuteFailureCondition( - addresses: addresses, + addresses: addresses.ToList(), index: i); } else { this.ExecuteSuccessCondition( - addresses: addresses, + addresses: addresses.ToList(), index: i); } } @@ -1483,13 +1497,13 @@ Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( if (this.failingIndexes.Contains(i)) { this.ExecuteFailureCondition( - addresses: addresses, + addresses: addresses.ToList(), index: i); } else { this.ExecuteSuccessCondition( - addresses: addresses, + addresses: addresses.ToList(), index: i); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs index f747d35d22..ff27842308 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs @@ -125,6 +125,8 @@ public void ValidateStoreResultSerialization() storeResultProperties.Remove(nameof(storeResult.Target.Exception)); storeResultProperties.Add("transportRequestTimeline"); storeResultProperties.Remove(nameof(storeResult.Target.TransportRequestStats)); + storeResultProperties.Add("ReplicaHealthStatuses"); + storeResultProperties.Remove(nameof(storeResult.Target.ReplicaHealthStatuses)); foreach (string key in jsonPropertyNames) { From d822239439c6b42973525fd2910720b69c464253 Mon Sep 17 00:00:00 2001 From: Achint-Agrawal <45819170+Achint-Agrawal@users.noreply.github.com> Date: Tue, 28 Mar 2023 01:50:11 +0530 Subject: [PATCH 078/337] [Preview] PriorityBasedExecution: Adds PriorityLevel as a RequestOption (#3672) * Added Priority Level as a Request Option * Changed Priority Level Low and High to 1 and 2 respectively * Bumped DirectVersion * Added made PriorityLevel internal for non preview packages * Deleted PriorityLevelTests.cs * Added description of Priority Level in RequestOptions.cs * Modified comments for PriorityLevel in RequestOptions.cs * Updated Contracts * Modified Remarks for PriorityLevel and added see also link. * Updated contracts --------- Co-authored-by: Matias Quaranta --- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 5 ++ .../src/RequestOptions/RequestOptions.cs | 28 ++++++++++- .../src/Resource/Settings/PriorityLevel.cs | 39 ++++++++++++++++ .../Contracts/DotNetPreviewSDKAPI.json | 46 +++++++++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index c7504d312c..cbd4e06674 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -6909,6 +6909,11 @@ private INameValueCollection GetRequestHeaders( headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, options.ConsistencyLevel.ToString()); } + if (options.PriorityLevel.HasValue) + { + headers.Set(HttpConstants.HttpHeaders.PriorityLevel, options.PriorityLevel.ToString()); + } + if (options.IndexingDirective.HasValue) { headers.Set(HttpConstants.HttpHeaders.IndexingDirective, options.IndexingDirective.ToString()); diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index 5387a0fbac..dc02f9a248 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -42,11 +42,32 @@ public class RequestOptions /// public Action AddRequestHeaders { get; set; } + /// + /// Gets or sets the priority level for a request. + /// + /// + /// Setting priority level only has an effect if Priority Based Execution is enabled. + /// If it is not enabled, the priority level is ignored by the backend. + /// Default PriorityLevel for each request is treated as High. It can be explicitly set to Low for some requests. + /// When Priority based execution is enabled, if there are more requests than the configured RU/S in a second, + /// then Cosmos DB will throttle low priority requests to allow high priority requests to execute. + /// This does not limit the throughput available to each priority level. Each priority level can consume the complete + /// provisioned throughput in absence of the other. If both priorities are present and the user goes above the + /// configured RU/s, low priority requests start getting throttled first to allow execution of mission critical workloads. + /// + /// +#if PREVIEW + public +#else + internal +#endif + PriorityLevel? PriorityLevel { get; set; } + /// /// Set Request Level Distributed Tracing Options. /// internal DistributedTracingOptions DistributedTracingOptions { get; set; } - + /// /// Gets or sets the boolean to use effective partition key routing in the cosmos db request. /// @@ -91,6 +112,11 @@ internal virtual void PopulateRequestOptions(RequestMessage request) request.Headers.Add(HttpConstants.HttpHeaders.IfNoneMatch, this.IfNoneMatchEtag); } + if (this.PriorityLevel.HasValue) + { + request.Headers.Add(HttpConstants.HttpHeaders.PriorityLevel, this.PriorityLevel.ToString()); + } + this.AddRequestHeaders?.Invoke(request.Headers); } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs new file mode 100644 index 0000000000..6644d0931f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs @@ -0,0 +1,39 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + /// + /// Valid values of Priority Level for a request + /// + /// + /// Setting priority level only has an effect if Priority Based Execution is enabled. + /// If it is not enabled, the priority level is ignored by the backend. + /// Default PriorityLevel for each request is treated as High. It can be explicitly set to Low for some requests. + /// When Priority based execution is enabled, if there are more requests than the configured RU/S in a second, + /// then Cosmos DB will throttle low priority requests to allow high priority requests to execute. + /// This does not limit the throughput available to each priority level. Each priority level can consume the complete + /// provisioned throughput in absence of the other. If both priorities are present and the user goes above the + /// configured RU/s, low priority requests start getting throttled first to allow execution of mission critical workloads. + /// + /// + +#if PREVIEW + public +#else + internal +#endif + enum PriorityLevel + { + /// + /// High Priority + /// + High = 1, + + /// + /// Low Priority + /// + Low = 2, + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 39ae1d2eca..8a3d326d50 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -362,6 +362,52 @@ } }, "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.PriorityLevel;System.Enum;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:True;IsClass:False;IsValueType:True;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Int32 value__": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Int32 value__;IsInitOnly:False;IsStatic:False;" + }, + "Microsoft.Azure.Cosmos.PriorityLevel High": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel High;IsInitOnly:False;IsStatic:True;" + }, + "Microsoft.Azure.Cosmos.PriorityLevel Low": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel Low;IsInitOnly:False;IsStatic:True;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} } }, "Members": {}, From 1c544bf651e097aaa696bff0abe8a7a3d651f512 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 29 Mar 2023 20:50:33 +0530 Subject: [PATCH 079/337] [Internal] Client Telemetry: Adds sampling logic for network level telemetry (#3750) * sampling logic add * throttlinfix * fix tests * fix tests * remove dispose from sampler * add 412 * draft push * refactor code for sampling * clean up * start testing * adding tests * wip * test fix * fix test * fix tests * deleted extra file * remove one toList * add custome logic for sampling * code refactor * replace key * remove commented code from test * added more comments * simpler sampler logic * refactor code --- .../src/Telemetry/ClientTelemetry.cs | 55 ++----- .../src/Telemetry/ClientTelemetryOptions.cs | 34 +---- .../Telemetry/ClientTelemetryPayloadWriter.cs | 22 ++- .../src/Telemetry/ClientTelemetryProcessor.cs | 14 +- .../src/Telemetry/Models/RequestInfo.cs | 31 +++- .../src/Telemetry/NetworkDataRecorder.cs | 139 ++++++++++++++++++ .../src/Telemetry/Sampler/DataSampler.cs | 84 +++++++++++ .../ClientTelemetryTests.cs | 134 ----------------- .../Telemetry/ClientTelemetryTests.cs | 40 ++--- .../Telemetry/DataSamplerTests.cs | 119 +++++++++++++++ .../Telemetry/DiagnosticsFilterHelperTest.cs | 3 - .../Telemetry/NetworkDataRecorderTest.cs | 92 ++++++++++++ 12 files changed, 516 insertions(+), 251 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/NetworkDataRecorder.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Sampler/DataSampler.cs delete mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DataSamplerTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/NetworkDataRecorderTest.cs diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index d0ca7d8ac8..8a83778fdb 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -36,7 +36,8 @@ internal class ClientTelemetry : IDisposable private readonly ClientTelemetryProperties clientTelemetryInfo; private readonly ClientTelemetryProcessor processor; private readonly DiagnosticsHandlerHelper diagnosticsHelper; - + private readonly NetworkDataRecorder networkDataRecorder; + private readonly CancellationTokenSource cancellationTokenSource; private readonly GlobalEndpointManager globalEndpointManager; @@ -49,11 +50,8 @@ internal class ClientTelemetry : IDisposable private ConcurrentDictionary cacheRefreshInfoMap = new ConcurrentDictionary(); - private ConcurrentDictionary requestInfoMap - = new ConcurrentDictionary(); - private int numberOfFailures = 0; - + /// /// Only for Mocking in tests /// @@ -112,6 +110,8 @@ internal ClientTelemetry( GlobalEndpointManager globalEndpointManager) { this.diagnosticsHelper = diagnosticsHelper ?? throw new ArgumentNullException(nameof(diagnosticsHelper)); + this.globalEndpointManager = globalEndpointManager; + this.processor = new ClientTelemetryProcessor(httpClient, authorizationTokenProvider); this.clientTelemetryInfo = new ClientTelemetryProperties( @@ -122,8 +122,9 @@ internal ClientTelemetry( preferredRegions: preferredRegions, aggregationIntervalInSec: (int)observingWindow.TotalSeconds); + this.networkDataRecorder = new NetworkDataRecorder(); + this.cancellationTokenSource = new CancellationTokenSource(); - this.globalEndpointManager = globalEndpointManager; } /// @@ -179,18 +180,15 @@ private async Task EnrichAndSendAsync() ConcurrentDictionary cacheRefreshInfoSnapshot = Interlocked.Exchange(ref this.cacheRefreshInfoMap, new ConcurrentDictionary()); - - ConcurrentDictionary requestInfoSnapshot - = Interlocked.Exchange(ref this.requestInfoMap, new ConcurrentDictionary()); - + try { await this.processor - .ProcessAndSendAsync( + .ProcessAndSendAsync( clientTelemetryInfo: this.clientTelemetryInfo, operationInfoSnapshot: operationInfoSnapshot, cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, - requestInfoSnapshot: requestInfoSnapshot, + requestInfoSnapshot: this.networkDataRecorder.GetRequests(), cancellationToken: this.cancellationTokenSource.Token); this.numberOfFailures = 0; @@ -296,7 +294,7 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, // Record Network/Replica Information SummaryDiagnostics summaryDiagnostics = new SummaryDiagnostics(trace); - this.RecordRntbdResponses(containerId, databaseId, summaryDiagnostics.StoreResponseStatistics.Value); + this.networkDataRecorder.Record(summaryDiagnostics.StoreResponseStatistics.Value, databaseId, containerId); string regionsContacted = ClientTelemetryHelper.GetContactedRegions(cosmosDiagnostics.GetContactedRegions()); @@ -338,37 +336,6 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, } } - /// - /// Records RNTBD calls statistics - /// - /// - /// - /// - private void RecordRntbdResponses(string containerId, string databaseId, List storeResponseStatistics) - { - foreach (StoreResponseStatistics storetatistics in storeResponseStatistics) - { - if (ClientTelemetryOptions.IsEligible((int)storetatistics.StoreResult.StatusCode, (int)storetatistics.StoreResult.SubStatusCode, storetatistics.RequestLatency)) - { - RequestInfo requestInfo = new RequestInfo() - { - DatabaseName = databaseId, - ContainerName = containerId, - Uri = storetatistics.StoreResult.StorePhysicalAddress.ToString(), - StatusCode = (int)storetatistics.StoreResult.StatusCode, - SubStatusCode = (int)storetatistics.StoreResult.SubStatusCode, - Resource = storetatistics.RequestResourceType.ToString(), - Operation = storetatistics.RequestOperationType.ToString(), - }; - - LongConcurrentHistogram latencyHist = this.requestInfoMap.GetOrAdd(requestInfo, x => new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, - ClientTelemetryOptions.RequestLatencyMax, - ClientTelemetryOptions.RequestLatencyPrecision)); - latencyHist.RecordValue(storetatistics.RequestLatency.Ticks); - } - } - } - /// /// Dispose of cosmos client.It will get disposed with client so not making it thread safe. /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index f2caaf50d5..47232a187e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -88,15 +88,18 @@ internal static class ClientTelemetryOptions internal static readonly ResourceType AllowedResourceTypes = ResourceType.Document; // Why 5 sec? As of now, if any network request is taking more than 5 millisecond sec, we will consider it slow request this value can be revisited in future - private static readonly TimeSpan NetworkLatencyThreshold = TimeSpan.FromMilliseconds(5); + internal static readonly TimeSpan NetworkLatencyThreshold = TimeSpan.FromMilliseconds(5); + internal static readonly int NetworkRequestsSampleSizeThreshold = 10; + internal static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr }; - private static readonly List ExcludedStatusCodes = new List { 404, 409 }; + internal static readonly List ExcludedStatusCodes = new List { 404, 409, 412 }; + internal static readonly int NetworkTelemetrySampleSize = 200; internal static int PayloadSizeThreshold = 1024 * 1024 * 2; // 2MB private static Uri clientTelemetryEndpoint; @@ -180,32 +183,5 @@ internal static string GetEnvironmentName() } return environmentName; } - - /// - /// This method will return true if the request is failed with User or Server Exception and not excluded from telemetry. - /// This method will return true if the request latency is more than the threshold. - /// otherwise return false - /// - /// - /// - /// - /// true/false - internal static bool IsEligible(int statusCode, int subStatusCode, TimeSpan latencyInMs) - { - return - ClientTelemetryOptions.IsStatusCodeNotExcluded(statusCode, subStatusCode) && - (ClientTelemetryOptions.IsUserOrServerError(statusCode) || latencyInMs >= ClientTelemetryOptions.NetworkLatencyThreshold); - } - - private static bool IsUserOrServerError(int statusCode) - { - return statusCode >= 400 && statusCode <= 599; - } - - private static bool IsStatusCodeNotExcluded(int statusCode, int subStatusCode) - { - return !(ClientTelemetryOptions.ExcludedStatusCodes.Contains(statusCode) && subStatusCode == 0); - } - } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs index 1158c7d639..370d576fcc 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryPayloadWriter.cs @@ -21,7 +21,7 @@ public static async Task SerializedPayloadChunksAsync( ClientTelemetryProperties properties, ConcurrentDictionary operationInfoSnapshot, ConcurrentDictionary cacheRefreshInfoSnapshot, - ConcurrentDictionary requestInfoSnapshot, + IReadOnlyList sampledRequestInfo, Func callback) { if (properties == null) @@ -46,11 +46,12 @@ public static async Task SerializedPayloadChunksAsync( OperationInfo payloadForRequestCharge = payloadForLatency.Copy(); payloadForRequestCharge.MetricInfo = new MetricInfo(ClientTelemetryOptions.RequestChargeName, ClientTelemetryOptions.RequestChargeUnit); payloadForRequestCharge.SetAggregators(entry.Value.requestcharge, ClientTelemetryOptions.HistogramPrecisionFactor); - + string latencyMetrics = JsonConvert.SerializeObject(payloadForLatency); string requestChargeMetrics = JsonConvert.SerializeObject(payloadForRequestCharge); - - if (lengthNow + latencyMetrics.Length + requestChargeMetrics.Length > ClientTelemetryOptions.PayloadSizeThreshold) + + int thisSectionLength = latencyMetrics.Length + requestChargeMetrics.Length; + if (lengthNow + thisSectionLength > ClientTelemetryOptions.PayloadSizeThreshold) { writer.WriteEndArray(); writer.WriteEndObject(); @@ -98,21 +99,16 @@ public static async Task SerializedPayloadChunksAsync( } - if (requestInfoSnapshot?.Any() == true) + if (sampledRequestInfo?.Any() == true) { writer.WritePropertyName("requestInfo"); writer.WriteStartArray(); - foreach (KeyValuePair entry in requestInfoSnapshot) + foreach (RequestInfo entry in sampledRequestInfo) { long lengthNow = stringBuilder.Length; - - MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); - metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); - - RequestInfo payloadForLatency = entry.Key; - payloadForLatency.Metrics.Add(metricInfo); - string latencyMetrics = JsonConvert.SerializeObject(payloadForLatency); + + string latencyMetrics = JsonConvert.SerializeObject(entry); if (lengthNow + latencyMetrics.Length > ClientTelemetryOptions.PayloadSizeThreshold) { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs index b91eb96832..c9511cb4e4 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; using System.Collections.Concurrent; + using System.Collections.Generic; using System.Net.Http; using System.Text; using System.Threading; @@ -22,7 +23,7 @@ internal class ClientTelemetryProcessor private readonly AuthorizationTokenProvider tokenProvider; private readonly CosmosHttpClient httpClient; - + internal ClientTelemetryProcessor(CosmosHttpClient httpClient, AuthorizationTokenProvider tokenProvider) { this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); @@ -32,17 +33,12 @@ internal ClientTelemetryProcessor(CosmosHttpClient httpClient, AuthorizationToke /// /// It will create Task to process and send client telemetry payload to Client Telemetry Service. /// - /// - /// - /// - /// - /// /// Task internal async Task ProcessAndSendAsync( ClientTelemetryProperties clientTelemetryInfo, - ConcurrentDictionary operationInfoSnapshot, + ConcurrentDictionary operationInfoSnapshot, ConcurrentDictionary cacheRefreshInfoSnapshot, - ConcurrentDictionary requestInfoSnapshot, + IReadOnlyList requestInfoSnapshot, CancellationToken cancellationToken) { try @@ -51,7 +47,7 @@ await ClientTelemetryPayloadWriter.SerializedPayloadChunksAsync( properties: clientTelemetryInfo, operationInfoSnapshot: operationInfoSnapshot, cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, - requestInfoSnapshot: requestInfoSnapshot, + sampledRequestInfo: requestInfoSnapshot, callback: async (payload) => await this.SendAsync(clientTelemetryInfo.GlobalDatabaseAccountName, payload, cancellationToken)); } catch (Exception ex) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs index d71f0fa446..382f37260d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Models/RequestInfo.cs @@ -37,8 +37,14 @@ internal sealed class RequestInfo public override int GetHashCode() { - int hash = 3; + int hash = this.GetHashCodeForSampler(); hash = (hash * 7) ^ (this.Uri == null ? 0 : this.Uri.GetHashCode()); + return hash; + } + + public int GetHashCodeForSampler() + { + int hash = 3; hash = (hash * 7) ^ (this.DatabaseName == null ? 0 : this.DatabaseName.GetHashCode()); hash = (hash * 7) ^ (this.ContainerName == null ? 0 : this.ContainerName.GetHashCode()); hash = (hash * 7) ^ (this.Operation == null ? 0 : this.Operation.GetHashCode()); @@ -47,7 +53,7 @@ public override int GetHashCode() hash = (hash * 7) ^ (this.SubStatusCode.GetHashCode()); return hash; } - + public override bool Equals(object obj) { bool isequal = obj is RequestInfo payload && @@ -62,5 +68,26 @@ public override bool Equals(object obj) return isequal; } + public double GetP99Latency() + { + foreach (MetricInfo metric in this.Metrics) + { + if (metric.MetricsName.Equals(ClientTelemetryOptions.RequestLatencyName, StringComparison.OrdinalIgnoreCase)) + { + return metric.Percentiles[ClientTelemetryOptions.Percentile99]; + } + } + return Double.MinValue; // least prioity for request info w/o latency info + } + + public double GetSampleCount() + { + return (double)this.Metrics[0].Count; + } + + public override string ToString() + { + return "Latency : " + this.GetP99Latency() + ", SampleCount : " + this.GetSampleCount(); + } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/NetworkDataRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/NetworkDataRecorder.cs new file mode 100644 index 0000000000..20e6f975da --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/NetworkDataRecorder.cs @@ -0,0 +1,139 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Threading; + using HdrHistogram; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; + + internal class NetworkDataRecorder + { + private ConcurrentDictionary RequestInfoHighLatencyBucket + = new ConcurrentDictionary(); + private ConcurrentDictionary RequestInfoErrorBucket + = new ConcurrentDictionary(); + + public void Record(List storeResponseStatistics, string databaseId, string containerId) + { + foreach (StoreResponseStatistics storeStatistics in storeResponseStatistics) + { + if (NetworkDataRecorder.IsStatusCodeNotExcluded((int)storeStatistics.StoreResult.StatusCode, (int)storeStatistics.StoreResult.SubStatusCode)) + { + if (NetworkDataRecorder.IsUserOrServerError((int)storeStatistics.StoreResult.StatusCode)) + { + RequestInfo requestInfo = this.CreateRequestInfo(storeStatistics, databaseId, containerId); + LongConcurrentHistogram latencyHist = this.RequestInfoErrorBucket.GetOrAdd(requestInfo, x => new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision)); + latencyHist.RecordValue(storeStatistics.RequestLatency.Ticks); + + } + else + { + RequestInfo requestInfo = this.CreateRequestInfo(storeStatistics, databaseId, containerId); + LongConcurrentHistogram latencyHist = this.RequestInfoHighLatencyBucket.GetOrAdd(requestInfo, x => new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision)); + latencyHist.RecordValue(storeStatistics.RequestLatency.Ticks); + } + } + } + } + + internal void GetErroredRequests(List requestInfoList) + { + ConcurrentDictionary requestInfoErrorList + = Interlocked.Exchange(ref this.RequestInfoErrorBucket, new ConcurrentDictionary()); + + List allRequests = new List(); + foreach (KeyValuePair entry in requestInfoErrorList) + { + MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); + + RequestInfo payloadForLatency = entry.Key; + payloadForLatency.Metrics.Add(metricInfo); + + allRequests.Add(payloadForLatency); + } + + requestInfoList.AddRange(DataSampler.OrderAndSample(allRequests, DataSampleCountComparer.Instance)); + } + + internal void GetHighLatencyRequests(List requestInfoList) + { + ConcurrentDictionary requestInfoHighLatencyList + = Interlocked.Exchange(ref this.RequestInfoHighLatencyBucket, new ConcurrentDictionary()); + + List allRequests = new List(); + foreach (KeyValuePair entry in requestInfoHighLatencyList) + { + MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); + metricInfo.SetAggregators(entry.Value, ClientTelemetryOptions.TicksToMsFactor); + + // Don't record if p99 latency is less than threshold + if (!NetworkDataRecorder.IsHighLatency(metricInfo.Percentiles[ClientTelemetryOptions.Percentile99])) + { + continue; + } + + RequestInfo payloadForLatency = entry.Key; + payloadForLatency.Metrics.Add(metricInfo); + + allRequests.Add(payloadForLatency); + } + + requestInfoList.AddRange(DataSampler.OrderAndSample(allRequests, DataLatencyComparer.Instance)); + } + + internal RequestInfo CreateRequestInfo(StoreResponseStatistics storeResponseStatistic, string databaseId, string containerId) + { + return new RequestInfo() + { + DatabaseName = databaseId, + ContainerName = containerId, + Uri = storeResponseStatistic.StoreResult?.StorePhysicalAddress?.ToString(), + StatusCode = (int)storeResponseStatistic.StoreResult?.StatusCode, + SubStatusCode = (int)storeResponseStatistic.StoreResult?.SubStatusCode, + Resource = storeResponseStatistic.RequestResourceType.ToString(), + Operation = storeResponseStatistic.RequestOperationType.ToString(), + }; + + } + + public List GetRequests() + { + List requestInfoList = new List(); + this.GetErroredRequests(requestInfoList); + this.GetHighLatencyRequests(requestInfoList); + + return requestInfoList; + } + + internal static bool IsHighLatency(double latency) + { + return + latency >= ClientTelemetryOptions.NetworkLatencyThreshold.TotalMilliseconds; + } + + /// + /// This method will return true if the request is failed with User or Server Exception and not excluded from telemetry. + /// otherwise return false + /// + /// true/false + internal static bool IsUserOrServerError(int statusCode) + { + return statusCode >= 400 && statusCode <= 599; + } + + internal static bool IsStatusCodeNotExcluded(int statusCode, int subStatusCode) + { + return !(ClientTelemetryOptions.ExcludedStatusCodes.Contains(statusCode) && subStatusCode == 0); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Sampler/DataSampler.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Sampler/DataSampler.cs new file mode 100644 index 0000000000..b01e723365 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Sampler/DataSampler.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using Newtonsoft.Json.Linq; + + /// + /// Sampler to select top N unique records and return true/false on the basis of elements already selected. + /// + internal sealed class DataSampler + { + public static List OrderAndSample(List requestInfoList, IComparer comparer) + { + // It will store final result + List sampledData = new List(capacity: requestInfoList.Count); + + // Processing (Grouping, Sorting will happen in this collection) + IDictionary> sampledRawData = new Dictionary>(); + + foreach (RequestInfo requestInfo in requestInfoList) + { + // Get a unique key identifier for an object + int key = requestInfo.GetHashCodeForSampler(); + + // Check if similar object is already present otherwise create a new list and add + if (sampledRawData.TryGetValue(key, out List groupedData)) + { + groupedData.Add(requestInfo); + sampledRawData[key] = groupedData; + } + else + { + sampledRawData.Add(key, new List() { requestInfo }); + } + } + + // If list is greater than threshold then sort it and get top N objects otherwise add list as it is + foreach (List sampledRequestInfo in sampledRawData.Values) + { + if (sampledRequestInfo.Count > ClientTelemetryOptions.NetworkRequestsSampleSizeThreshold) + { + sampledRequestInfo.Sort(comparer); + sampledData.AddRange(sampledRequestInfo.GetRange( + index: 0, + count: ClientTelemetryOptions.NetworkRequestsSampleSizeThreshold)); + } + else + { + sampledData.AddRange(sampledRequestInfo); + } + } + + return sampledData; + } + + } + + internal class DataLatencyComparer : IComparer + { + public static DataLatencyComparer Instance = new DataLatencyComparer(); + public int Compare(RequestInfo a, RequestInfo b) + { + return b.GetP99Latency().CompareTo(a.GetP99Latency()); + } + } + + internal class DataSampleCountComparer : IComparer + { + public static DataSampleCountComparer Instance = new DataSampleCountComparer(); + public int Compare(RequestInfo a, RequestInfo b) + { + return b.GetSampleCount().CompareTo(a.GetSampleCount()); + } + } + +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs deleted file mode 100644 index b7e5d1f08e..0000000000 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientTelemetryTests.cs +++ /dev/null @@ -1,134 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Tests -{ - using System; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using HdrHistogram; - using Newtonsoft.Json; - using Microsoft.Azure.Cosmos.Telemetry; - using System.Collections.Generic; - using Microsoft.Azure.Cosmos.Telemetry.Models; - - /// - /// Tests for . - /// - [TestClass] - public class ClientTelemetryTests - { - [TestCleanup] - public void Cleanup() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); - } - - [TestMethod] - public void CheckMetricsAggregationLogic() - { - MetricInfo metrics = new MetricInfo("metricsName", "unitName"); - - LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, - long.MaxValue, - 5); - - histogram.RecordValue(10); - histogram.RecordValue(20); - histogram.RecordValue(30); - histogram.RecordValue(40); - - metrics.SetAggregators(histogram); - - Assert.AreEqual(40, metrics.Max); - Assert.AreEqual(10, metrics.Min); - Assert.AreEqual(4, metrics.Count); - Assert.AreEqual(25, metrics.Mean); - - Assert.AreEqual(20, metrics.Percentiles[ClientTelemetryOptions.Percentile50]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile90]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile95]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile99]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile999]); - } - - [TestMethod] - public void CheckMetricsAggregationLogicWithAdjustment() - { - MetricInfo metrics = new MetricInfo("metricsName", "unitName"); - long adjustmentFactor = 1000; - - LongConcurrentHistogram histogram = new LongConcurrentHistogram(1, - long.MaxValue, - 5); - - histogram.RecordValue(10 * adjustmentFactor); - histogram.RecordValue(20 * adjustmentFactor); - histogram.RecordValue(30 * adjustmentFactor); - histogram.RecordValue(40 * adjustmentFactor); - - metrics.SetAggregators(histogram, adjustmentFactor); - - Assert.AreEqual(40, metrics.Max); - Assert.AreEqual(10, metrics.Min); - Assert.AreEqual(4, metrics.Count); - - Assert.AreEqual(25, metrics.Mean); - - Assert.AreEqual(20, metrics.Percentiles[ClientTelemetryOptions.Percentile50]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile90]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile95]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile99]); - Assert.AreEqual(40, metrics.Percentiles[ClientTelemetryOptions.Percentile999]); - } - - [TestMethod] - public void CheckJsonSerializerContract() - { - string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", - processId: "", - userAgent: null, - connectionMode: ConnectionMode.Direct, - preferredRegions: null, - aggregationIntervalInSec: 10), ClientTelemetryOptions.JsonSerializerSettings); - Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"aggregationIntervalInSec\":10,\"systemInfo\":[]}", json); - } - - [TestMethod] - public void CheckJsonSerializerContractWithPreferredRegions() - { - List preferredRegion = new List - { - "region1" - }; - string json = JsonConvert.SerializeObject(new ClientTelemetryProperties(clientId: "clientId", - processId: "", - userAgent: null, - connectionMode: ConnectionMode.Direct, - preferredRegions: preferredRegion, - aggregationIntervalInSec: 1), ClientTelemetryOptions.JsonSerializerSettings); - Assert.AreEqual("{\"clientId\":\"clientId\",\"processId\":\"\",\"connectionMode\":\"DIRECT\",\"preferredRegions\":[\"region1\"],\"aggregationIntervalInSec\":1,\"systemInfo\":[]}", json); - } - - [TestMethod] - [ExpectedException(typeof(FormatException))] - public void CheckMisconfiguredTelemetry_should_fail() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "non-boolean"); - using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - } - - [TestMethod] - [DataRow(200, 0 ,1, false)] - [DataRow(404, 0, 1, false)] - [DataRow(404, 1002, 1, true)] - [DataRow(409, 0, 1, false)] - [DataRow(409, 1002, 1, true)] - [DataRow(503, 2001, 1, true)] - [DataRow(200, 0, 6, true)] - public void CheckEligibleStatistics(int statusCode, int subStatusCode, int latencyInMs, bool expectedFlag) - { - Assert.AreEqual(expectedFlag, ClientTelemetryOptions.IsEligible(statusCode, subStatusCode, TimeSpan.FromMilliseconds(latencyInMs))); - } - } -} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs index 48cb0d1e42..4a6b077baa 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs @@ -119,10 +119,10 @@ public void CheckJsonSerializerContractWithPreferredRegions() } [TestMethod] - [DataRow(100, 50, 200)] // When operation, cacherefresh and request info is there in payload + [DataRow(150, 50, 200)] // When operation, cacherefresh and request info is there in payload [DataRow(0, 50, 0)] // When only cacherefresh info is there in payload - [DataRow(100, 50, 0)] // When only operation and cacherefresh info is there in payload - [DataRow(100, 0, 0)] // When only operation info is there in payload + [DataRow(150, 50, 0)] // When only operation and cacherefresh info is there in payload + [DataRow(150, 0, 0)] // When only operation info is there in payload public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInfoSize, int expectedCacheRefreshInfoSize, int expectedRequestInfoSize) { Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); @@ -147,6 +147,7 @@ public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInf string payloadJson = request.Content.ReadAsStringAsync().Result; Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); + Console.WriteLine(payloadJson); ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); Assert.AreEqual(7, propertiesToSend.SystemInfo.Count, "System Info is not correct"); @@ -162,9 +163,10 @@ public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInf Mock.Of()); ConcurrentDictionary operationInfoSnapshot - = new ConcurrentDictionary(); + = new ConcurrentDictionary (); - for (int i = 0; i < (expectedOperationInfoSize/2); i++) + int numberOfMetricsInOperationSection = 2; + for (int i = 0; i < (expectedOperationInfoSize/ numberOfMetricsInOperationSection); i++) { OperationInfo opeInfo = new OperationInfo(Regions.WestUS, 0, @@ -179,12 +181,12 @@ public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInf LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, ClientTelemetryOptions.RequestLatencyMax, ClientTelemetryOptions.RequestLatencyPrecision); - latency.RecordValue(10l); + latency.RecordValue(10); LongConcurrentHistogram requestcharge = new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, ClientTelemetryOptions.RequestChargeMax, ClientTelemetryOptions.RequestChargePrecision); - requestcharge.RecordValue(11l); + requestcharge.RecordValue(11); operationInfoSnapshot.TryAdd(opeInfo, (latency, requestcharge)); } @@ -207,13 +209,12 @@ ConcurrentDictionary cacheRefreshInfo LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, ClientTelemetryOptions.RequestLatencyMax, ClientTelemetryOptions.RequestLatencyPrecision); - latency.RecordValue(10l); + latency.RecordValue(10); cacheRefreshInfoSnapshot.TryAdd(crInfo, latency); } - ConcurrentDictionary requestInfoInfoSnapshot - = new ConcurrentDictionary(); + List requestInfoList = new List(); for (int i = 0; i < expectedRequestInfoSize; i++) { RequestInfo reqInfo = new RequestInfo @@ -227,19 +228,24 @@ ConcurrentDictionary requestInfoInfoSnapsh SubStatusCode = 0 }; - LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, - ClientTelemetryOptions.RequestLatencyMax, - ClientTelemetryOptions.RequestLatencyPrecision); - latency.RecordValue(10l); + MetricInfo metricInfo = new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit); - requestInfoInfoSnapshot.TryAdd(reqInfo, latency); - } + LongConcurrentHistogram histogram = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + histogram.RecordValue(TimeSpan.FromMinutes(1).Ticks); + + metricInfo.SetAggregators(histogram, ClientTelemetryOptions.TicksToMsFactor); + reqInfo.Metrics.Add(metricInfo); + requestInfoList.Add(reqInfo); ; + } + await processor.ProcessAndSendAsync( clientTelemetryProperties, operationInfoSnapshot, cacheRefreshInfoSnapshot, - requestInfoInfoSnapshot, + requestInfoList, new CancellationToken()); Assert.AreEqual(expectedOperationInfoSize, actualOperationInfoSize, "Operation Info is not correct"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DataSamplerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DataSamplerTests.cs new file mode 100644 index 0000000000..d6ad3dbb8c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DataSamplerTests.cs @@ -0,0 +1,119 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Telemetry +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class DataSamplerTests + { + [TestMethod] + public void TestNetworkRequestSamplerForThreshold() + { + int numberOfElementsInEachGroup = ClientTelemetryOptions.NetworkRequestsSampleSizeThreshold; + int numberOfGroups = 5; + + List requestInfoList = new List(); + + for (int counter = 0; counter < 100; counter++) + { + RequestInfo requestInfo = new RequestInfo() + { + DatabaseName = "dbId " + (counter % numberOfGroups), // To repeat similar elements + ContainerName = "containerId", + Uri = "rntbd://host/partition/replica", + StatusCode = 429, + SubStatusCode = 1002, + Resource = ResourceType.Document.ToResourceTypeString(), + Operation = OperationType.Create.ToOperationTypeString(), + Metrics = new List() + { + new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit) + { + Percentiles = new Dictionary() + { + { ClientTelemetryOptions.Percentile50, 10 }, + { ClientTelemetryOptions.Percentile90, 20 }, + { ClientTelemetryOptions.Percentile95, 30 }, + { ClientTelemetryOptions.Percentile99, Random.Shared.Next(1, 100) }, + { ClientTelemetryOptions.Percentile999, 50 } + }, + Count = Random.Shared.Next(1, 100) + } + } + }; + requestInfoList.Add(requestInfo); + } + + List sampleDataByLatency = DataSampler.OrderAndSample(requestInfoList, DataLatencyComparer.Instance); + Assert.AreEqual(numberOfGroups * numberOfElementsInEachGroup, sampleDataByLatency.Count); + + List sampleDataBySampleCount = DataSampler.OrderAndSample(requestInfoList, DataSampleCountComparer.Instance); + Assert.AreEqual(numberOfGroups * numberOfElementsInEachGroup, sampleDataBySampleCount.Count); + } + + [TestMethod] + public void TestNetworkRequestSamplerWithoutData() + { + List requestInfoList = new List(); + + Assert.AreEqual(0, DataSampler.OrderAndSample(requestInfoList, DataSampleCountComparer.Instance).Count); + Assert.AreEqual(0, DataSampler.OrderAndSample(requestInfoList, DataLatencyComparer.Instance).Count); + } + + [TestMethod] + public void TestNetworkRequestSamplerForLessThanThresholdSize() + { + int numberOfElementsInEachGroup = ClientTelemetryOptions.NetworkRequestsSampleSizeThreshold; + int numberOfGroups = 3; + + List requestInfoList = new List(); + + for (int counter = 0; counter < 10; counter++) + { + RequestInfo requestInfo = new RequestInfo() + { + DatabaseName = "dbId " + (counter % numberOfGroups), // To repeat similar elements + ContainerName = "containerId", + Uri = "rntbd://host/partition/replica", + StatusCode = 429, + SubStatusCode = 1002, + Resource = ResourceType.Document.ToResourceTypeString(), + Operation = OperationType.Create.ToOperationTypeString(), + Metrics = new List() + { + new MetricInfo(ClientTelemetryOptions.RequestLatencyName, ClientTelemetryOptions.RequestLatencyUnit) + { + Percentiles = new Dictionary() + { + { ClientTelemetryOptions.Percentile50, 10 }, + { ClientTelemetryOptions.Percentile90, 20 }, + { ClientTelemetryOptions.Percentile95, 30 }, + { ClientTelemetryOptions.Percentile99, Random.Shared.Next(1, 100) }, + { ClientTelemetryOptions.Percentile999, 50 } + }, + Count = Random.Shared.Next(1, 100) + } + } + }; + requestInfoList.Add(requestInfo); + } + + List sampleDataByLatency = DataSampler.OrderAndSample(requestInfoList, DataLatencyComparer.Instance); + Assert.AreEqual(10, sampleDataByLatency.Count); + + List sampleDataBySampleCount = DataSampler.OrderAndSample(requestInfoList, DataSampleCountComparer.Instance); + Assert.AreEqual(10, sampleDataBySampleCount.Count); + } + + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 698b99524e..c04c0d6faf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -5,10 +5,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Telemetry { using System; - using System.Collections.Generic; - using System.Linq; using System.Net; - using System.Text; using System.Threading.Tasks; using Cosmos.Telemetry; using Cosmos.Telemetry.Diagnostics; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/NetworkDataRecorderTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/NetworkDataRecorderTest.cs new file mode 100644 index 0000000000..c08282cd0f --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/NetworkDataRecorderTest.cs @@ -0,0 +1,92 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Telemetry +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.AccessControl; + using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Telemetry.Models; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; + + [TestClass] + public class NetworkDataRecorderTest + { + [TestMethod] + public void TestRecordWithErroredAndHighLatencyRequests() + { + NetworkDataRecorder recorder = new NetworkDataRecorder(); + + List stats = new List() + { + new StoreResponseStatistics( + requestStartTime: DateTime.Now, + requestResponseTime: DateTime.Now.AddMilliseconds(10), + storeResult: StoreResult.CreateForTesting(storeResponse: new StoreResponse() + { + Status = 200 + }).Target, + resourceType: Documents.ResourceType.Document, + operationType: OperationType.Create, + requestSessionToken: default, + locationEndpoint: new Uri("https://dummy.url")), + + new StoreResponseStatistics( + requestStartTime: DateTime.Now, + requestResponseTime: DateTime.Now.AddMilliseconds(10), + storeResult: StoreResult.CreateForTesting(storeResponse: new StoreResponse() + { + Status = 401 + }).Target, + resourceType: Documents.ResourceType.Document, + operationType: OperationType.Create, + requestSessionToken: default, + locationEndpoint: new Uri("https://dummy.url")) + }; + + recorder.Record(stats, "databaseId", "containerId"); + + List highLatencyRequests = new List(); + recorder.GetHighLatencyRequests(highLatencyRequests); + Assert.AreEqual(1, highLatencyRequests.Count); + + List erroredRequests = new List(); + recorder.GetErroredRequests(erroredRequests); + Assert.AreEqual(1, erroredRequests.Count); + + // you can get the values only once + List requests = new List(); + recorder.GetHighLatencyRequests(requests); + recorder.GetErroredRequests(requests); + + Assert.AreEqual(0, requests.Count); + } + + [TestMethod] + [DataRow(200, 0, 1, false)] + [DataRow(404, 0, 1, false)] + [DataRow(404, 1002, 1, true)] + [DataRow(409, 0, 1, false)] + [DataRow(409, 1002, 1, true)] + [DataRow(503, 2001, 1, true)] + [DataRow(200, 0, 6, true)] + public void CheckEligibleStatistics(int statusCode, int subStatusCode, int latencyInMs, bool expectedFlag) + { + Assert.AreEqual(expectedFlag, NetworkDataRecorderTest.IsEligible(statusCode, subStatusCode, TimeSpan.FromMilliseconds(latencyInMs))); + } + + private static bool IsEligible(int statusCode, int subStatusCode, TimeSpan latencyInMs) + { + return + NetworkDataRecorder.IsStatusCodeNotExcluded(statusCode, subStatusCode) && + (NetworkDataRecorder.IsUserOrServerError(statusCode) || NetworkDataRecorder.IsHighLatency(latencyInMs.TotalMilliseconds)); + } + } +} From 6553a70b3ff7bf9a46486297bd115947e318ae10 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 30 Mar 2023 00:30:11 +0530 Subject: [PATCH 080/337] [Internal] Emulator Test : Fixes test when running with distributed tracing enabled. (#3751) * enable DT for everything * try1 * code refactoring * fix pipeline * try 2 * Revert "try 2" This reverts commit 61643f9b4dcd2ab1898fd68b111897bed0bc6bcf. * Revert "fix pipeline" This reverts commit 4b217f5f6a087b1dd889b804fd8b477accd46419. * Revert "code refactoring" This reverts commit d1ff0ddc17ad655360988d171bd033617752f91f. * Revert "try1" This reverts commit bf9c41b43684f59719c3673d6f9c7450bbdc5142. * lazy factory and threadsafe * scope factory in function * try non static * add flag * fix test * add consoles * more console with fix * fix tests * temporarily enable dt * fuix tests * dispose listener * fix tests * remove delay * revert flag change * dynamically get number of test in trace class --- .../EndToEndTraceWriterBaselineTests.cs | 129 +++++++++++------- .../Utils/Util.cs | 7 +- 2 files changed, 82 insertions(+), 54 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index e81eda0d01..c32c756121 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -24,7 +24,8 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; - + using AzureCore = global::Azure.Core.Pipeline; + [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] public sealed class EndToEndTraceWriterBaselineTests : BaselineTests @@ -41,10 +42,14 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests m.GetCustomAttributes(typeof(TestMethodAttribute), false).Length > 0).Count(); + + private static int MethodCount = 0; + + [ClassInitialize] public static async Task ClassInitAsync(TestContext context) { - testListener = Util.ConfigureOpenTelemetryAndCustomListeners(); + EndToEndTraceWriterBaselineTests.testListener = Util.ConfigureOpenTelemetryAndCustomListeners(); client = Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestCommon.CreateCosmosClient( useGateway: false, @@ -87,30 +92,41 @@ public static async Task ClassInitAsync(TestContext context) EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } - - [ClassCleanup()] + + [TestCleanup] + public async Task CleanUp() + { + await EndToEndTraceWriterBaselineTests.ClassCleanupAsync(); + } + public static async Task ClassCleanupAsync() { - if(database != null) - { - await EndToEndTraceWriterBaselineTests.database.DeleteStreamAsync(); - } + EndToEndTraceWriterBaselineTests.MethodCount++; - Util.DisposeOpenTelemetryAndCustomListeners(); + if (EndToEndTraceWriterBaselineTests.MethodCount == EndToEndTraceWriterBaselineTests.TotalTestMethod) + { + if (database != null) + { + await EndToEndTraceWriterBaselineTests.database.DeleteStreamAsync(); + } + + EndToEndTraceWriterBaselineTests.client?.Dispose(); + EndToEndTraceWriterBaselineTests.bulkClient?.Dispose(); + EndToEndTraceWriterBaselineTests.miscCosmosClient?.Dispose(); - EndToEndTraceWriterBaselineTests.client?.Dispose(); - EndToEndTraceWriterBaselineTests.bulkClient?.Dispose(); - EndToEndTraceWriterBaselineTests.miscCosmosClient?.Dispose(); + Util.DisposeOpenTelemetryAndCustomListeners(); - await Task.Delay(5000); + EndToEndTraceWriterBaselineTests.testListener.Dispose(); + + } } - + private static void AssertAndResetActivityInformation() { AssertActivity.AreEqualAcrossListeners(); CustomOtelExporter.CollectedActivities = new(); - testListener?.ResetAttributes(); + EndToEndTraceWriterBaselineTests.testListener?.ResetAttributes(); } [TestMethod] @@ -147,10 +163,9 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener?.GetRecordedAttributes())); + oTelActivities: EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); - } //---------------------------------------------------------------- @@ -178,7 +193,7 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener?.GetRecordedAttributes())); + oTelActivities: EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -209,7 +224,7 @@ public async Task ReadFeedAsync() trace: traceForest, startLineNumber: startLineNumber, endLineNumber: endLineNumber, - oTelActivities: testListener?.GetRecordedAttributes())); + oTelActivities: EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -235,7 +250,7 @@ public async Task ReadFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ReadFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("ReadFeed Public API Typed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -277,7 +292,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -309,7 +324,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Typed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -342,7 +357,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Public API", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Public API", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -375,7 +390,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("ChangeFeed Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("ChangeFeed Public API Typed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -436,7 +451,7 @@ public async Task ChangeFeedAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Change Feed Estimator", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Change Feed Estimator", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -472,7 +487,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -497,7 +512,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query Typed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -523,7 +538,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -549,7 +564,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API Typed", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API Typed", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -578,7 +593,7 @@ public async Task QueryAsync() Documents.ServiceInteropWrapper.AssembliesExist = currentLazy; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query - Without ServiceInterop", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query - Without ServiceInterop", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -606,7 +621,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API with FeedRanges", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -634,7 +649,7 @@ public async Task QueryAsync() ITrace traceForest = TraceJoiner.JoinTraces(traces); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Query Public API Typed with FeedRanges", traceForest, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Query Public API Typed with FeedRanges", traceForest, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -650,9 +665,17 @@ public async Task ValidateInvalidCredentialsTraceAsync() string endpoint = Utils.ConfigurationManager.AppSettings["GatewayEndpoint"]; AzureKeyCredential masterKeyCredential = new AzureKeyCredential(authKey); + + // It is not baseline test hence disable distributed tracing for this test + CosmosClientOptions clientOptions = new CosmosClientOptions() + { + IsDistributedTracingEnabled = false + }; + using (CosmosClient client = new CosmosClient( endpoint, - masterKeyCredential)) + masterKeyCredential, + clientOptions)) { try @@ -705,7 +728,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -723,7 +746,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -749,7 +772,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -791,7 +814,7 @@ public async Task TypedPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -826,7 +849,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Write", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -844,7 +867,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Read", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -870,7 +893,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Replace", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -915,7 +938,7 @@ public async Task StreamPointOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)itemResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Delete", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -964,7 +987,7 @@ public async Task PointOperationsExceptionsAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation with Request Timeout", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation with Request Timeout", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1016,7 +1039,7 @@ public async Task PointOperationsExceptionsAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation With Throttle", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation With Throttle", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1096,7 +1119,7 @@ void interceptor(Uri uri, Documents.ResourceOperation operation, Documents.Docum } endLineNumber = GetLineNumber(); - inputs.Add(new Input($"Point Operation With Forbidden + Max Count = {maxCount}", trace, startLineNumber, endLineNumber, testListener.GetRecordedAttributes())); + inputs.Add(new Input($"Point Operation With Forbidden + Max Count = {maxCount}", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1147,7 +1170,7 @@ void interceptor(Uri uri, Documents.ResourceOperation operation, Documents.Docum } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Point Operation with Service Unavailable", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Point Operation with Service Unavailable", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1198,7 +1221,7 @@ public async Task BatchOperationsAsync() ITrace trace = ((CosmosTraceDiagnostics)response.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Batch Operation", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Batch Operation", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1248,7 +1271,7 @@ public async Task BulkOperationsAsync() foreach (ITrace trace in traces) { - inputs.Add(new Input("Bulk Operation", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Bulk Operation", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); } EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); @@ -1302,7 +1325,7 @@ public async Task BulkOperationsAsync() endLineNumber = GetLineNumber(); - inputs.Add(new Input("Bulk Operation With Throttle", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Bulk Operation With Throttle", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1334,7 +1357,7 @@ public async Task MiscellanousAsync() await databaseResponse.Database.DeleteAsync(); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1353,7 +1376,7 @@ public async Task MiscellanousAsync() await databaseResponse.Database.DeleteAsync(); endLineNumber = GetLineNumber(); - inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Custom Handler", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1394,7 +1417,7 @@ public async Task ReadManyAsync() } endLineNumber = GetLineNumber(); - inputs.Add(new Input("Read Many Stream Api", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Read Many Stream Api", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } @@ -1409,7 +1432,7 @@ public async Task ReadManyAsync() ITrace trace = ((CosmosTraceDiagnostics)feedResponse.Diagnostics).Value; endLineNumber = GetLineNumber(); - inputs.Add(new Input("Read Many Typed Api", trace, startLineNumber, endLineNumber, testListener?.GetRecordedAttributes())); + inputs.Add(new Input("Read Many Typed Api", trace, startLineNumber, endLineNumber, EndToEndTraceWriterBaselineTests.testListener?.GetRecordedAttributes())); EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 8c71a6b168..96254aca79 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -22,7 +22,8 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenTelemetry; using OpenTelemetry.Trace; - + using AzureCore = global::Azure.Core.Pipeline; + internal enum DocumentClientType { Gateway, @@ -542,6 +543,8 @@ internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() { AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); + AzureCore.ActivityExtensions.ResetFeatureSwitch(); + // Open Telemetry Listener Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() // use any exporter here @@ -567,6 +570,8 @@ internal static void DisposeOpenTelemetryAndCustomListeners() Util.TestListener = null; AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", false); + + AzureCore.ActivityExtensions.ResetFeatureSwitch(); } /// From 67dc262090fc66b5b8d80c6012baa926f3fa19ca Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 30 Mar 2023 11:19:27 -0700 Subject: [PATCH 081/337] Release: Adds SDK version and changelog for 3.32.3 (#3788) * Adding contract and version bump * Adding changelog --- Directory.Build.props | 4 +- .../contracts/API_3.32.3-preview.txt | 1531 +++++++++++++++++ .../contracts/API_3.32.3.txt | 1478 ++++++++++++++++ changelog.md | 7 + 4 files changed, 3018 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.3-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.32.3.txt diff --git a/Directory.Build.props b/Directory.Build.props index 39004a08ab..e51eae5f3f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.32.2 - 3.32.2 + 3.32.3 + 3.32.3 preview 3.30.4 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.3-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.3-preview.txt new file mode 100644 index 0000000000..69b7a4b83e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.3-preview.txt @@ -0,0 +1,1531 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.32.3.txt b/Microsoft.Azure.Cosmos/contracts/API_3.32.3.txt new file mode 100644 index 0000000000..5218206b0e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.32.3.txt @@ -0,0 +1,1478 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index a8a156b922..a41dc7f438 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,13 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.32.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.3) - 2023-03-30 +### [3.32.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.3-preview) - 2023-03-30 + +#### Fixed + +- [#3787](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3787) Connectivity: Fixes ConnectionBroken and adds support for Burst Capacity + ### [3.32.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.2) - 2023-03-10 ### [3.32.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.2-preview) - 2023-03-10 From a6972422d51ea5d430238bac9f285ff1c7f2dc8a Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 3 Apr 2023 11:42:22 -0700 Subject: [PATCH 082/337] SummaryDiagnostics: Refactors Code to Remove Dependency of HttpResponseHeadersWrapper to fetch Sub Status Codes (#3792) * Code changes to fetch sub status code from http response/ content headers. * Code changes to address review comments. * Code changes to return the first element from the sub status list. * Code changes to update first or default. --- .../Tracing/TraceData/SummaryDiagnostics.cs | 25 +++++++++++--- .../SummaryDiagnosticsTests.cs | 33 +++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs index 1838cb72c5..3a50b96841 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/SummaryDiagnostics.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Tracing.TraceData using System; using System.Collections.Generic; using System.Globalization; + using System.Linq; using Microsoft.Azure.Cosmos.Json; using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; @@ -73,10 +74,7 @@ private void AggregateGatewayStatistics(IReadOnlyList + /// Gets the sub status code as a comma separated value from the http response message headers. + /// If the sub status code header is not found, then returns null. + /// + /// An instance of . + /// A string containing the sub status code. + private static string GetSubStatusCodes( + HttpResponseStatistics httpResponseStatistics) + { + return httpResponseStatistics + .HttpResponseMessage + .Headers + .TryGetValues( + name: Documents.WFConstants.BackendHeaders.SubStatus, + values: out IEnumerable httpResponseHeaderValues) ? + httpResponseHeaderValues.FirstOrDefault() : + null; + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs index ae94a7220d..1948411400 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SummaryDiagnosticsTests.cs @@ -128,5 +128,38 @@ public async Task DirectPointOperationsWithTransportErrors() Assert.AreEqual(summaryDiagnostics.DirectRequestsSummary.Value[(410, (int)SubStatusCodes.TransportGenerated410)], 3); Assert.AreEqual(summaryDiagnostics.DirectRequestsSummary.Value[(201, 0)], 1); } + + /// + /// Test to validate that when a read operation is done on a database and a container that + /// does not exists, then the should capture the sub status + /// codes successfully. + /// + [TestMethod] + [Owner("dkunda")] + public async Task SummaryDiagnostics_WhenContainerDoesNotExists_ShouldRecordSubStatusCode() + { + string partitionKey = "/pk"; + int notFoundStatusCode = 404, notFoundSubStatusCode = 1003; + using CosmosClient cosmosClient = TestCommon.CreateCosmosClient(useGateway: false); + + try + { + Container container = cosmosClient.GetContainer( + databaseId: Guid.NewGuid().ToString(), + containerId: Guid.NewGuid().ToString()); + + ItemResponse readResponse = await container.ReadItemAsync( + partitionKey, + new Cosmos.PartitionKey(partitionKey)); + } + catch (CosmosException ex) + { + ITrace trace = ((CosmosTraceDiagnostics)ex.Diagnostics).Value; + SummaryDiagnostics summaryDiagnostics = new(trace); + + Assert.IsNotNull(value: summaryDiagnostics); + Assert.IsTrue(condition: summaryDiagnostics.GatewayRequestsSummary.Value.ContainsKey((notFoundStatusCode, notFoundSubStatusCode))); + } + } } } \ No newline at end of file From e41eea5ad6db54e51e953552bfccf751c0de291f Mon Sep 17 00:00:00 2001 From: Justine Cocchi Date: Tue, 4 Apr 2023 07:50:11 -0700 Subject: [PATCH 083/337] [Internal] Documentation: Fixes API name to NoSQL (#3795) --- .../src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj | 2 +- .../src/Microsoft.Azure.Cosmos.Encryption.csproj | 2 +- Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj | 2 +- README.md | 4 ++-- changelog.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index d368f399bd..54755c89ef 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -10,7 +10,7 @@ $(CustomEncryptionVersion) Microsoft Corporation Microsoft - This is an internal library that provides an implementation for client-side encryption for Azure Cosmos DB's SQL API for multi-tenant use case. For more information, refer to https://aka.ms/CosmosCustomClientEncryption + This is an internal library that provides an implementation for client-side encryption for Azure Cosmos DB for NoSQL for multi-tenant use case. For more information, refer to https://aka.ms/CosmosCustomClientEncryption © Microsoft Corporation. All rights reserved. Microsoft Azure Cosmos DB client-side encryption library for multi-tenant Microsoft.Azure.Cosmos.Encryption.Custom diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj index 9fe41b765f..f58b171cd5 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj @@ -12,7 +12,7 @@ $([System.DateTime]::Now.ToString(yyyyMMdd)) Microsoft Corporation Microsoft - This library provides an implementation for client-side encryption for Azure Cosmos's SQL API. For more information, refer to https://aka.ms/CosmosClientEncryption + This library provides an implementation for client-side encryption for Azure Cosmos DB for NoSQL. For more information, refer to https://aka.ms/CosmosClientEncryption © Microsoft Corporation. All rights reserved. Microsoft Azure Cosmos DB client-side encryption library Microsoft.Azure.Cosmos.Encryption diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 0b21867bf7..a33142b79b 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -3,7 +3,7 @@ Microsoft Corporation Microsoft(R) Azure Cosmos - This client library enables client applications to connect to Azure Cosmos via the SQL API. Azure Cosmos is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. + This client library enables client applications to connect to Azure Cosmos DB for NoSQL. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. © Microsoft Corporation. All rights reserved. en-US $([System.DateTime]::Now.ToString(yyyyMMdd)) diff --git a/README.md b/README.md index 1d39e6e204..f1dcffa7b9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ # Microsoft Azure Cosmos DB .NET SDK Version 3 -This client library enables client applications to connect to Azure Cosmos via the SQL API. Azure Cosmos is a globally distributed, multi-model database service. For more information, refer to https://azure.microsoft.com/services/cosmos-db/. +This client library enables client applications to connect to Azure Cosmos DB for NoSQL. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to https://azure.microsoft.com/services/cosmos-db/. ```csharp CosmosClient client = new CosmosClient("https://mycosmosaccount.documents.azure.com:443/", "mysupersecretkey"); @@ -45,7 +45,7 @@ using (FeedIterator feedIterator = container.GetItemQueryIterator Date: Tue, 4 Apr 2023 13:37:19 -0700 Subject: [PATCH 084/337] [Internal] CTL: Fixes docker image pipeline (#3794) --- azure-pipelines-ctl-publishing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-ctl-publishing.yml b/azure-pipelines-ctl-publishing.yml index b3b9e10fb9..862d125aa1 100644 --- a/azure-pipelines-ctl-publishing.yml +++ b/azure-pipelines-ctl-publishing.yml @@ -1,5 +1,5 @@ variables: - VmImage: 'ubuntu-18.04' + VmImage: 'ubuntu-latest' jobs: - job: BuildDockerImage From ae6bcf313b83ff58c3bb703c1dee6a4b9b1e8820 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 5 Apr 2023 03:51:25 +0530 Subject: [PATCH 085/337] [Internal] AI Integration : Refactors useragent attribute name as per Otel conventions (#3784) Co-authored-by: Fabian Meiswinkel --- .../OpenTelemetryAttributeKeys.cs | 2 +- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 12 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Tracing/AssertActivity.cs | 2 +- 12 files changed, 195 insertions(+), 195 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index e7c4d96cc2..755e1e3a66 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -20,7 +20,7 @@ internal sealed class OpenTelemetryAttributeKeys // Cosmos Db Specific public const string ClientId = "db.cosmosdb.client_id"; public const string MachineId = "db.cosmosdb.machine_id"; - public const string UserAgent = "db.cosmosdb.user_agent"; + public const string UserAgent = "user_agent.original"; // Compliant with open telemetry conventions public const string ConnectionMode = "db.cosmosdb.connection_mode"; public const string OperationType = "db.cosmosdb.operation_type"; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index d468fe87f5..ad1a3f1288 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 041523ff8a..09d8c3ce63 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -153,16 +153,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -311,16 +311,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -469,16 +469,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -627,16 +627,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -785,16 +785,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -943,16 +943,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1101,16 +1101,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1259,16 +1259,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1417,16 +1417,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1575,16 +1575,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2324,7 +2324,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index dccb7fe5d0..2e20bceb1c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -952,11 +952,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1569,11 +1569,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2167,11 +2167,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2785,11 +2785,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3066,8 +3066,8 @@ } ] }]]> - Operation.Change Feed Estimator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Change Feed Estimator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 832dfee446..348925a1f6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -107,8 +107,8 @@ } ] }]]> - Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -207,8 +207,8 @@ } ] }]]> - Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 200ad02660..a8b686d679 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -148,7 +148,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -390,7 +390,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -615,7 +615,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -872,7 +872,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1193,7 +1193,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1347,7 +1347,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 876d37dc63..18aa6d67d8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -574,10 +574,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1180,10 +1180,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1767,10 +1767,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2374,10 +2374,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3048,10 +3048,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3644,10 +3644,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4260,10 +4260,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 44a8a04a51..1ceef081c6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -536,10 +536,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1104,10 +1104,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1653,10 +1653,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2222,10 +2222,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 9a96ef9751..7229f78197 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -542,12 +542,12 @@ } ] }]]> - Operation.ReadManyItemsStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadManyItemsStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1112,7 +1112,7 @@ } ] }]]> - Operation.ReadManyItemsAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadManyItemsAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 25a01f6b94..f0dec5b7bd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -89,7 +89,7 @@ } ] }]]> - Operation.CreateItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.CreateItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -178,7 +178,7 @@ } ] }]]> - Operation.ReadItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -275,7 +275,7 @@ } ] }]]> - Operation.ReplaceItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReplaceItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -367,7 +367,7 @@ } ] }]]> - Operation.DeleteItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.DeleteItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 4dfceee978..6b57caad95 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -109,7 +109,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -203,7 +203,7 @@ } ] }]]> - Operation.ReadItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -310,7 +310,7 @@ } ] }]]> - Operation.ReplaceItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReplaceItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -406,7 +406,7 @@ } ] }]]> - Operation.DeleteItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iddb.cosmosdb.user_agentdb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.DeleteItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index d19b330d98..c46d8b035a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -39,7 +39,7 @@ public static void IsValid(Activity activity) "net.peer.name", "db.cosmosdb.client_id", "db.cosmosdb.machine_id", - "db.cosmosdb.user_agent", + "user_agent.original", "db.cosmosdb.connection_mode", "db.cosmosdb.operation_type", "db.cosmosdb.container", From 2b693948a02a2206984a6c423c3d9a3e560026d8 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 6 Apr 2023 15:05:15 -0700 Subject: [PATCH 086/337] HttpClient: Adds Properties to the Http messages if available (#3803) * Passing properties * test --- .../src/GatewayStoreClient.cs | 8 +++ .../GatewayStoreModelTest.cs | 61 +++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs b/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs index c779dc7855..e151ffcd94 100644 --- a/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs +++ b/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs @@ -320,6 +320,14 @@ private async ValueTask PrepareRequestMessageAsync( } } + if (request.Properties != null) + { + foreach (KeyValuePair property in request.Properties) + { + requestMessage.Properties.Add(property); + } + } + // add activityId Guid activityId = System.Diagnostics.Trace.CorrelationManager.ActivityId; Debug.Assert(activityId != Guid.Empty); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index 43078d1866..36b350a751 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -161,6 +161,67 @@ public async Task TestRetries() } + /// + /// Verifies that if the DCE has Properties set, the HttpRequestMessage has them too. Used on ThinClient. + /// + [TestMethod] + public async Task PassesPropertiesFromDocumentServiceRequest() + { + IDictionary properties = new Dictionary() + { + {"property1", Guid.NewGuid() }, + {"property2", Guid.NewGuid().ToString() } + }; + + Func> sendFunc = request => + { + Assert.AreEqual(properties.Count, request.Properties.Count); + foreach (KeyValuePair item in properties) + { + Assert.AreEqual(item.Value, request.Properties[item.Key]); + } + + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) ); + }; + + Mock mockDocumentClient = new Mock(); + mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo")); + + using GlobalEndpointManager endpointManager = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy()); + ISessionContainer sessionContainer = new SessionContainer(string.Empty); + DocumentClientEventSource eventSource = DocumentClientEventSource.Instance; + HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); + using GatewayStoreModel storeModel = new GatewayStoreModel( + endpointManager, + sessionContainer, + ConsistencyLevel.Eventual, + eventSource, + null, + MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler))); + + using (new ActivityScope(Guid.NewGuid())) + { + using (DocumentServiceRequest request = + DocumentServiceRequest.Create( + Documents.OperationType.Query, + Documents.ResourceType.Document, + new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute), + new MemoryStream(Encoding.UTF8.GetBytes("content1")), + AuthorizationTokenType.PrimaryMasterKey, + null)) + { + // Add properties to the DCE + request.Properties = new Dictionary(); + foreach (KeyValuePair property in properties) + { + request.Properties.Add(property.Key, property.Value); + } + + await storeModel.ProcessMessageAsync(request); + } + } + } + [TestMethod] public async Task TestApplySessionForMasterOperation() { From 4222cefad2df3c06d13fb629ae0c1f4b3937d08c Mon Sep 17 00:00:00 2001 From: Scott Addie <10702007+scottaddie@users.noreply.github.com> Date: Thu, 6 Apr 2023 17:31:29 -0500 Subject: [PATCH 087/337] Documentation: Refactors SQL API reference to NoSQL API (#3793) Co-authored-by: Kiran Kumar Kolli --- Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index a33142b79b..7ba4e9213d 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -3,7 +3,7 @@ Microsoft Corporation Microsoft(R) Azure Cosmos - This client library enables client applications to connect to Azure Cosmos DB for NoSQL. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. + This client library enables client applications to connect to Azure Cosmos DB via the NoSQL API. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. © Microsoft Corporation. All rights reserved. en-US $([System.DateTime]::Now.ToString(yyyyMMdd)) From fce970237f1f1b5c5b7d88488761b61dd3e766d4 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 7 Apr 2023 05:45:12 +0530 Subject: [PATCH 088/337] [Internal] Perf test: Refactors code to re-enable performance tests (#3785) * enable perf tests * updated json * upgrade benchmark * update results * updated benchmark results --- .../Contracts/BenchmarkResults.json | 144 +++++++++--------- .../Contracts/PerformanceValidation.cs | 2 +- ...soft.Azure.Cosmos.Performance.Tests.csproj | 2 +- 3 files changed, 74 insertions(+), 74 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index b54d4f0624..c97e0b5b2c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -1,79 +1,79 @@ { - "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 534.0, - "MasterKeyAuthorizationBenchmark.ReadSignatureGeneration;": 532.0, - "MockedItemBenchmark.CreateItem;[Type=OfT]": 45302.0, - "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 45320.0, - "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 48140.0, - "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 83798.0, - "MockedItemBenchmark.CreateItem;[Type=Stream]": 29766.0, - "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 37154.0, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 37154.0, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 39840.0, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 74758.0, - "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 29872.0, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42786.0, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 43144.0, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 44694.0, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 80098.0, - "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 37610.0, + "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 534, + "MasterKeyAuthorizationBenchmark.ReadSignatureGeneration;": 544, + "MockedItemBenchmark.CreateItem;[Type=OfT]": 36356, + "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 36362, + "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 36359.5, + "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 57472.25, + "MockedItemBenchmark.CreateItem;[Type=Stream]": 24673.25, + "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 32308.5, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 32328, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 32321.25, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 53231.25, + "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 24696, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42172.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 42174.75, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 42166.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 56695.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 37610, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13342232, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13341058, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13355160, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13612338, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814.0, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810.0, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientTelemetryEnabled]": 2244658.0, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2310842.0, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 1005038.0, - "MockedItemBenchmark.ReadFeed;[Type=OfT]": 560692.0, - "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 571334.0, - "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 565196.0, - "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": 609704.0, - "MockedItemBenchmark.ReadFeed;[Type=Stream]": 39140.0, - "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 38622.0, - "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 37992.0, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 39918.0, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 74370.0, - "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 31018.0, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43438.0, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43860.0, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 45502.0, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 83760.0, - "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 38266.0, - "MockedItemBenchmark.UpdateItem;[Type=OfT]": 46690.0, - "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 45532.0, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 48372.0, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 84694.0, - "MockedItemBenchmark.UpdateItem;[Type=Stream]": 30026.0, - "MockedItemBenchmark.UpsertItem;[Type=OfT]": 45448.0, - "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 45458.0, - "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 48298.0, - "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 83938.0, - "MockedItemBenchmark.UpsertItem;[Type=Stream]": 29934.0, - "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168.0, - "MockedItemBulkBenchmark.CreateItem;[Type=OfTCustom]": 1195808.0, - "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 1235418.0, - "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 1231120.0, - "MockedItemBulkBenchmark.CreateItem;[Type=Stream]": 772810.0, - "MockedItemBulkBenchmark.DeleteItem;[Type=OfT]": 1187168.0, - "MockedItemBulkBenchmark.DeleteItem;[Type=OfTCustom]": 1187224.0, - "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithClientTelemetryEnabled]": 1226488.0, - "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithDiagnosticsToString]": 1222124.0, - "MockedItemBulkBenchmark.DeleteItem;[Type=Stream]": 771414.0, - "MockedItemBulkBenchmark.ReadItem;[Type=OfT]": 1186594.0, - "MockedItemBulkBenchmark.ReadItem;[Type=OfTCustom]": 1187192.0, - "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithClientTelemetryEnabled]": 1226502.0, - "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithDiagnosticsToString]": 1222342.0, - "MockedItemBulkBenchmark.ReadItem;[Type=Stream]": 770894.0, - "MockedItemBulkBenchmark.UpdateItem;[Type=OfT]": 1196464.0, - "MockedItemBulkBenchmark.UpdateItem;[Type=OfTCustom]": 1195778.0, - "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 1235738.0, - "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 1231486.0, - "MockedItemBulkBenchmark.UpdateItem;[Type=Stream]": 773284.0, - "MockedItemBulkBenchmark.UpsertItem;[Type=OfT]": 1196210.0, - "MockedItemBulkBenchmark.UpsertItem;[Type=OfTCustom]": 1195590.0, - "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 1235596.0, - "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 1231380.0, - "MockedItemBulkBenchmark.UpsertItem;[Type=Stream]": 773312.0 + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientTelemetryEnabled]": 2244658, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2310842, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 1005038, + "MockedItemBenchmark.ReadFeed;[Type=OfT]": 560692, + "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716, + "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25, + "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": 573734.5, + "MockedItemBenchmark.ReadFeed;[Type=Stream]": 33434, + "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 33630.5, + "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 33636.25, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 33627.75, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 47961.25, + "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26018.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 57420.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39044, + "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, + "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 36587.25, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 57649, + "MockedItemBenchmark.UpdateItem;[Type=Stream]": 24894.75, + "MockedItemBenchmark.UpsertItem;[Type=OfT]": 36577.25, + "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 36583.75, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 36578.5, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 57732.5, + "MockedItemBenchmark.UpsertItem;[Type=Stream]": 24878.5, + "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168, + "MockedItemBulkBenchmark.CreateItem;[Type=OfTCustom]": 1195808, + "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 1235418, + "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 1231120, + "MockedItemBulkBenchmark.CreateItem;[Type=Stream]": 772810, + "MockedItemBulkBenchmark.DeleteItem;[Type=OfT]": 1187168, + "MockedItemBulkBenchmark.DeleteItem;[Type=OfTCustom]": 1187224, + "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithClientTelemetryEnabled]": 1226488, + "MockedItemBulkBenchmark.DeleteItem;[Type=OfTWithDiagnosticsToString]": 1222124, + "MockedItemBulkBenchmark.DeleteItem;[Type=Stream]": 771414, + "MockedItemBulkBenchmark.ReadItem;[Type=OfT]": 1186594, + "MockedItemBulkBenchmark.ReadItem;[Type=OfTCustom]": 1187192, + "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithClientTelemetryEnabled]": 1226502, + "MockedItemBulkBenchmark.ReadItem;[Type=OfTWithDiagnosticsToString]": 1222342, + "MockedItemBulkBenchmark.ReadItem;[Type=Stream]": 770894, + "MockedItemBulkBenchmark.UpdateItem;[Type=OfT]": 1196464, + "MockedItemBulkBenchmark.UpdateItem;[Type=OfTCustom]": 1195778, + "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 1235738, + "MockedItemBulkBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 1231486, + "MockedItemBulkBenchmark.UpdateItem;[Type=Stream]": 773284, + "MockedItemBulkBenchmark.UpsertItem;[Type=OfT]": 1196210, + "MockedItemBulkBenchmark.UpsertItem;[Type=OfTCustom]": 1195590, + "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 1235596, + "MockedItemBulkBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 1231380, + "MockedItemBulkBenchmark.UpsertItem;[Type=Stream]": 773312 } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/PerformanceValidation.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/PerformanceValidation.cs index af3d77e5a4..ad7e43ab4a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/PerformanceValidation.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/PerformanceValidation.cs @@ -125,7 +125,7 @@ public static int ValidateSummaryResultsAgainstBaseline(SortedDictionary - + From 2f2e8fbd32fb672253413c1f237a03801810619a Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Fri, 7 Apr 2023 14:18:20 -0700 Subject: [PATCH 089/337] HttpClient: Adds detection of DNS changes through use of SocketsHttpHandler for .NET 6 and above (#3762) * initial commit * removed unneeded usings * added validation callback, still needs tests * nits + fixes * added additional test * test change * removed unneeded Dispose calls * removed unnneed dispose calls * requested changes * added pooledConnectionLifetime as client option * nit Co-authored-by: Kevin Pilch * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs Co-authored-by: Matias Quaranta * suggested changes * remove test, reorder usings * updated contracts * removed all non XXXAPI.json changes from UpdateContracts run * removed public surface, added random timespan * removed change from unrelated file * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * added thread safe random method * nit * fixed merge mistake * added reflection failsafe/error tracing * nits * added back removed if * fixed formatting * changed random method, fixed serverCertificateCustomValidation --------- Co-authored-by: Kevin Pilch Co-authored-by: Matias Quaranta --- .../src/HttpClient/CosmosHttpClientCore.cs | 97 +++++++++++++++++-- .../ClientTests.cs | 19 +++- .../CosmosClientOptionsUnitTests.cs | 2 +- .../CosmosHttpClientCoreTests.cs | 65 +++++++++++-- 4 files changed, 164 insertions(+), 19 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs index a48666f16d..0fde01afb5 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs @@ -5,17 +5,17 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Collections.Generic; - using System.Diagnostics; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.Security; + using System.Reflection; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; - using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Collections; @@ -99,7 +99,87 @@ public static CosmosHttpClient CreateWithConnectionPolicy( eventSource: eventSource); } - public static HttpMessageHandler CreateHttpClientHandler(int gatewayModeMaxConnectionLimit, IWebProxy webProxy, Func serverCertificateCustomValidationCallback) + public static HttpMessageHandler CreateHttpClientHandler( + int gatewayModeMaxConnectionLimit, + IWebProxy webProxy, + Func serverCertificateCustomValidationCallback) + { + // TODO: Remove type check and use #if NET6_0_OR_GREATER when multitargetting is possible + Type socketHandlerType = Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http"); + + if (socketHandlerType != null) + { + try + { + return CosmosHttpClientCore.CreateSocketsHttpHandlerHelper(gatewayModeMaxConnectionLimit, webProxy, serverCertificateCustomValidationCallback); + } + catch (Exception e) + { + DefaultTrace.TraceError("Failed to create SocketsHttpHandler: {0}", e); + } + } + + return CosmosHttpClientCore.CreateHttpClientHandlerHelper(gatewayModeMaxConnectionLimit, webProxy, serverCertificateCustomValidationCallback); + } + + public static HttpMessageHandler CreateSocketsHttpHandlerHelper( + int gatewayModeMaxConnectionLimit, + IWebProxy webProxy, + Func serverCertificateCustomValidationCallback) + { + // TODO: Remove Reflection when multitargetting is possible + Type socketHandlerType = Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http"); + + object socketHttpHandler = Activator.CreateInstance(socketHandlerType); + + PropertyInfo pooledConnectionLifetimeInfo = socketHandlerType.GetProperty("PooledConnectionLifetime"); + + //Sets the timeout for unused connections to a random time between 5 minutes and 5 minutes and 30 seconds. + //This is to avoid the issue where a large number of connections are closed at the same time. + TimeSpan connectionTimeSpan = TimeSpan.FromMinutes(5) + TimeSpan.FromSeconds(30 * CustomTypeExtensions.GetRandomNumber().NextDouble()); + pooledConnectionLifetimeInfo.SetValue(socketHttpHandler, connectionTimeSpan); + + // Proxy is only set by users and can cause not supported exception on some platforms + if (webProxy != null) + { + PropertyInfo webProxyInfo = socketHandlerType.GetProperty("Proxy"); + webProxyInfo.SetValue(socketHttpHandler, webProxy); + } + + // https://docs.microsoft.com/en-us/archive/blogs/timomta/controlling-the-number-of-outgoing-connections-from-httpclient-net-core-or-full-framework + try + { + PropertyInfo maxConnectionsPerServerInfo = socketHandlerType.GetProperty("MaxConnectionsPerServer"); + maxConnectionsPerServerInfo.SetValue(socketHttpHandler, gatewayModeMaxConnectionLimit); + } + // MaxConnectionsPerServer is not supported on some platforms. + catch (PlatformNotSupportedException) + { + } + + if (serverCertificateCustomValidationCallback != null) + { + //Get SslOptions Property + PropertyInfo sslOptionsInfo = socketHandlerType.GetProperty("SslOptions"); + object sslOptions = sslOptionsInfo.GetValue(socketHttpHandler); + + //Set SslOptions Property with custom certificate validation + PropertyInfo remoteCertificateValidationCallbackInfo = sslOptions.GetType().GetProperty("RemoteCertificateValidationCallback"); + remoteCertificateValidationCallbackInfo.SetValue( + sslOptions, + new RemoteCertificateValidationCallback((object _, X509Certificate certificate, X509Chain x509Chain, SslPolicyErrors sslPolicyErrors) => serverCertificateCustomValidationCallback( + certificate is { } ? new X509Certificate2(certificate) : null, + x509Chain, + sslPolicyErrors))); + } + + return (HttpMessageHandler)socketHttpHandler; + } + + public static HttpMessageHandler CreateHttpClientHandlerHelper( + int gatewayModeMaxConnectionLimit, + IWebProxy webProxy, + Func serverCertificateCustomValidationCallback) { HttpClientHandler httpClientHandler = new HttpClientHandler(); @@ -112,17 +192,18 @@ public static HttpMessageHandler CreateHttpClientHandler(int gatewayModeMaxConne // https://docs.microsoft.com/en-us/archive/blogs/timomta/controlling-the-number-of-outgoing-connections-from-httpclient-net-core-or-full-framework try { - httpClientHandler.MaxConnectionsPerServer = gatewayModeMaxConnectionLimit; - if (serverCertificateCustomValidationCallback != null) - { - httpClientHandler.ServerCertificateCustomValidationCallback = (_, certificate2, x509Chain, sslPolicyErrors) => serverCertificateCustomValidationCallback(certificate2, x509Chain, sslPolicyErrors); - } + httpClientHandler.MaxConnectionsPerServer = gatewayModeMaxConnectionLimit; } // MaxConnectionsPerServer is not supported on some platforms. catch (PlatformNotSupportedException) { } + if (serverCertificateCustomValidationCallback != null) + { + httpClientHandler.ServerCertificateCustomValidationCallback = (_, certificate2, x509Chain, sslPolicyErrors) => serverCertificateCustomValidationCallback(certificate2, x509Chain, sslPolicyErrors); + } + return httpClientHandler; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index 1f419c4eb8..c8a9a0aff7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -486,7 +486,6 @@ public async Task Verify_CertificateCallBackGetsCalled_ForTCP_HTTP() { await database?.DeleteStreamAsync(); } - } [TestMethod] @@ -878,7 +877,7 @@ public async Task HttpClientConnectionLimitTest() )) { CosmosHttpClient cosmosHttpClient = cosmosClient.DocumentClient.httpClient; - HttpClientHandler httpClientHandler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler; + SocketsHttpHandler httpClientHandler = (SocketsHttpHandler)cosmosHttpClient.HttpMessageHandler; Assert.AreEqual(gatewayConnectionLimit, httpClientHandler.MaxConnectionsPerServer); Cosmos.Database database = await cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); @@ -895,7 +894,7 @@ public async Task HttpClientConnectionLimitTest() await Task.WhenAll(creates); - // Clean up the database and container + // Clean up the database await database.DeleteAsync(); } @@ -907,6 +906,20 @@ public async Task HttpClientConnectionLimitTest() $"Before connections: {JsonConvert.SerializeObject(excludeConnections)}; After connections: {JsonConvert.SerializeObject(afterConnections)}"); } + [TestMethod] + public void PooledConnectionLifetimeTest() + { + //Create Cosmos Client + using CosmosClient cosmosClient = new CosmosClient( + accountEndpoint: "https://localhost:8081", + authKeyOrResourceToken: Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()))); + + //Assert type of message handler + Type socketHandlerType = Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http"); + Type clientMessageHandlerType = cosmosClient.ClientContext.DocumentClient.httpClient.HttpMessageHandler.GetType(); + Assert.AreEqual(socketHandlerType, clientMessageHandlerType); + } + public static IReadOnlyList GetActiveConnections() { string testPid = Process.GetCurrentProcess().Id.ToString(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 986b9cc997..efb06d7cc5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -398,7 +398,7 @@ public void VerifyHttpClientHandlerIsSet() CosmosClient cosmosClient = cosmosClientBuilder.Build(); CosmosHttpClient cosmosHttpClient = cosmosClient.DocumentClient.httpClient; - HttpClientHandler handler = (HttpClientHandler)cosmosHttpClient.HttpMessageHandler; + SocketsHttpHandler handler = (SocketsHttpHandler)cosmosHttpClient.HttpMessageHandler; Assert.IsTrue(object.ReferenceEquals(webProxy, handler.Proxy)); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 3ac919bf83..0d475ca370 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -4,18 +4,20 @@ namespace Microsoft.Azure.Cosmos.Tests { - using System.Threading.Tasks; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Microsoft.Azure.Documents; using System; - using System.Net.Http; + using System.Collections.Generic; + using System.IO; using System.Net; + using System.Net.Http; + using System.Net.Security; + using System.Security.Cryptography; + using System.Security.Cryptography.X509Certificates; using System.Threading; - using System.IO; - using System.Net.Sockets; - using System.Collections.Generic; + using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class CosmosHttpClientCoreTests @@ -410,6 +412,55 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); } + [TestMethod] + public void CreateSocketsHttpHandlerCreatesCorrectValueType() + { + int gatewayLimit = 10; + IWebProxy webProxy = null; + Func serverCertificateCustomValidationCallback = (certificate2, x509Chain, sslPolicyErrors) => false; + + HttpMessageHandler handler = CosmosHttpClientCore.CreateSocketsHttpHandlerHelper( + gatewayLimit, + webProxy, + serverCertificateCustomValidationCallback); + + Assert.AreEqual(Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http"), handler.GetType()); + SocketsHttpHandler socketsHandler = (SocketsHttpHandler)handler; + + Assert.IsTrue(TimeSpan.FromMinutes(5.5) >= socketsHandler.PooledConnectionLifetime); + Assert.IsTrue(TimeSpan.FromMinutes(5) <= socketsHandler.PooledConnectionLifetime); + Assert.AreEqual(webProxy, socketsHandler.Proxy); + Assert.AreEqual(gatewayLimit, socketsHandler.MaxConnectionsPerServer); + + //Create cert for test + X509Certificate2 x509Certificate2 = new CertificateRequest("cn=www.test", ECDsa.Create(), HashAlgorithmName.SHA256).CreateSelfSigned(DateTime.Now, DateTime.Now.AddYears(1)); + X509Chain x509Chain = new X509Chain(); + SslPolicyErrors sslPolicyErrors = new SslPolicyErrors(); + Assert.IsFalse(socketsHandler.SslOptions.RemoteCertificateValidationCallback.Invoke(new object(), x509Certificate2, x509Chain, sslPolicyErrors)); + } + + [TestMethod] + public void CreateHttpClientHandlerCreatesCorrectValueType() + { + int gatewayLimit = 10; + IWebProxy webProxy = null; + Func serverCertificateCustomValidationCallback = (certificate2, x509Chain, sslPolicyErrors) => false; + + HttpMessageHandler handler = CosmosHttpClientCore.CreateHttpClientHandlerHelper(gatewayLimit, webProxy, serverCertificateCustomValidationCallback); + + Assert.AreEqual(Type.GetType("System.Net.Http.HttpClientHandler, System.Net.Http"), handler.GetType()); + HttpClientHandler clientHandler = (HttpClientHandler)handler; + + Assert.AreEqual(webProxy, clientHandler.Proxy); + Assert.AreEqual(gatewayLimit, clientHandler.MaxConnectionsPerServer); + + //Create cert for test + X509Certificate2 x509Certificate2 = new CertificateRequest("cn=www.test", ECDsa.Create(), HashAlgorithmName.SHA256).CreateSelfSigned(DateTime.Now, DateTime.Now.AddYears(1)); + X509Chain x509Chain = new X509Chain(); + SslPolicyErrors sslPolicyErrors = new SslPolicyErrors(); + Assert.IsFalse(clientHandler.ServerCertificateCustomValidationCallback.Invoke(new HttpRequestMessage(), x509Certificate2, x509Chain, sslPolicyErrors)); + } + private class MockMessageHandler : HttpMessageHandler { private readonly Func> sendFunc; From 789f70183a2323259d6518eb7d463aca38f4ae08 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Sat, 8 Apr 2023 11:05:59 -0700 Subject: [PATCH 090/337] [Internal] Tests: Fixes Open Telemetry attributes for ReadMany test (#3805) * Fixing test * New baseline * Undo some changes --- .../EndToEndTraceWriterBaselineTests.ReadManyAsync.xml | 10 ---------- .../Tracing/EndToEndTraceWriterBaselineTests.cs | 4 +++- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 7229f78197..a7cc47631a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -543,16 +543,6 @@ ] }]]> Operation.ReadManyItemsStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index c32c756121..e14188d92a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -92,7 +92,7 @@ public static async Task ClassInitAsync(TestContext context) EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); } - + [TestCleanup] public async Task CleanUp() { @@ -1405,6 +1405,8 @@ public async Task ReadManyAsync() itemList.Add(("id" + i, new PartitionKey(i.ToString()))); } + EndToEndTraceWriterBaselineTests.AssertAndResetActivityInformation(); + //---------------------------------------------------------------- // Read Many Stream //---------------------------------------------------------------- From 2b6fdb7d818115b88a992d0370e77d1a8aaf0e19 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 11 Apr 2023 00:42:35 +0530 Subject: [PATCH 091/337] [Internal] Client Telemetry: Refactors code to run client telemetry data processing task in background. (#3783) * first draft * remove failure count test * refactporing * code refactor * create task with timeout * fix test * code refactoring * fix timeout code * space fix * not failing if processor is taking time * fix procrsser test * code refactor * refactor and test fix --- .../src/Telemetry/ClientTelemetry.cs | 78 ++++++++----- .../src/Telemetry/ClientTelemetryOptions.cs | 6 +- .../ClientTelemetryTests.cs | 27 ----- .../Telemetry/ClientTelemetryTests.cs | 108 +++++++++++++++++- 4 files changed, 155 insertions(+), 64 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 8a83778fdb..dde7d5a7c5 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -19,7 +19,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; using Util; - using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; /// /// This class collects and send all the telemetry information. @@ -29,8 +28,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry /// internal class ClientTelemetry : IDisposable { - private const int allowedNumberOfFailures = 3; - private static readonly TimeSpan observingWindow = ClientTelemetryOptions.GetScheduledTimeSpan(); private readonly ClientTelemetryProperties clientTelemetryInfo; @@ -39,7 +36,6 @@ internal class ClientTelemetry : IDisposable private readonly NetworkDataRecorder networkDataRecorder; private readonly CancellationTokenSource cancellationTokenSource; - private readonly GlobalEndpointManager globalEndpointManager; private Task telemetryTask; @@ -50,8 +46,6 @@ internal class ClientTelemetry : IDisposable private ConcurrentDictionary cacheRefreshInfoMap = new ConcurrentDictionary(); - private int numberOfFailures = 0; - /// /// Only for Mocking in tests /// @@ -123,7 +117,6 @@ internal ClientTelemetry( aggregationIntervalInSec: (int)observingWindow.TotalSeconds); this.networkDataRecorder = new NetworkDataRecorder(); - this.cancellationTokenSource = new CancellationTokenSource(); } @@ -137,9 +130,9 @@ private void StartObserverTask() /// /// Task which does below operations , periodically - /// 1. Set Account information (one time at the time of initialization) - /// 2. Load VM metedata information (one time at the time of initialization) - /// 3. Calculate and Send telemetry Information to juno service (never ending task)/// + /// 1. Set Account information (one time during initialization) + /// 2. Load VM metedata information (one time during initialization) + /// 3. Calculate and Send telemetry Information to Client Telemetry Service (never ending task)/// /// Async Task private async Task EnrichAndSendAsync() { @@ -149,18 +142,12 @@ private async Task EnrichAndSendAsync() { while (!this.cancellationTokenSource.IsCancellationRequested) { - if (this.numberOfFailures == allowedNumberOfFailures) - { - this.Dispose(); - break; - } - if (string.IsNullOrEmpty(this.clientTelemetryInfo.GlobalDatabaseAccountName)) { AccountProperties accountProperties = await ClientTelemetryHelper.SetAccountNameAsync(this.globalEndpointManager); this.clientTelemetryInfo.GlobalDatabaseAccountName = accountProperties.Id; } - + await Task.Delay(observingWindow, this.cancellationTokenSource.Token); this.clientTelemetryInfo.DateTimeUtc = DateTime.UtcNow.ToString(ClientTelemetryOptions.DateFormat); @@ -180,24 +167,28 @@ private async Task EnrichAndSendAsync() ConcurrentDictionary cacheRefreshInfoSnapshot = Interlocked.Exchange(ref this.cacheRefreshInfoMap, new ConcurrentDictionary()); - + + List requestInfoSnapshot = this.networkDataRecorder.GetRequests(); + try { - await this.processor - .ProcessAndSendAsync( - clientTelemetryInfo: this.clientTelemetryInfo, - operationInfoSnapshot: operationInfoSnapshot, - cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, - requestInfoSnapshot: this.networkDataRecorder.GetRequests(), - cancellationToken: this.cancellationTokenSource.Token); - - this.numberOfFailures = 0; + CancellationTokenSource cancellationToken = new CancellationTokenSource(ClientTelemetryOptions.ClientTelemetryProcessorTimeOut); + Task processorTask = Task.Run(() => this.processor + .ProcessAndSendAsync( + clientTelemetryInfo: this.clientTelemetryInfo, + operationInfoSnapshot: operationInfoSnapshot, + cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, + requestInfoSnapshot: requestInfoSnapshot, + cancellationToken: cancellationToken.Token), cancellationToken.Token); + + // Initiating Telemetry Data Processor task which will serialize and send telemetry information to Client Telemetry Service + // Not disposing this task. If we dispose a client then, telemetry job(telemetryTask) should stop but processor task(processorTask) should make best effort to finish the job in background. + _ = ClientTelemetry.RunProcessorTaskAsync(this.clientTelemetryInfo.DateTimeUtc, processorTask, ClientTelemetryOptions.ClientTelemetryProcessorTimeOut); + } catch (Exception ex) { - this.numberOfFailures++; - - DefaultTrace.TraceError("Telemetry Job Processor failed with error : {0}", ex); + DefaultTrace.TraceError("Exception while initiating processing task : {0} with telemetry date as {1}", ex.Message, this.clientTelemetryInfo.DateTimeUtc); } } } @@ -209,6 +200,33 @@ await this.processor DefaultTrace.TraceInformation("Telemetry Job Stopped."); } + /// + /// This Task makes sure, processing task is timing out after 5 minute of timeout + /// + /// + /// + /// + internal static async Task RunProcessorTaskAsync(string telemetryDate, Task processingTask, TimeSpan timeout) + { + using (CancellationTokenSource tokenForDelayTask = new CancellationTokenSource()) + { + Task delayTask = Task.Delay(timeout, tokenForDelayTask.Token); + + Task resultTask = await Task.WhenAny(processingTask, delayTask); + if (resultTask == delayTask) + { + DefaultTrace.TraceVerbose($"Processor task with date as {telemetryDate} is canceled as it did not finish in {timeout}"); + // Operation cancelled + throw new OperationCanceledException($"Processor task with date as {telemetryDate} is canceled as it did not finish in {timeout}"); + } + else + { + // Cancel the timer task so that it does not fire + tokenForDelayTask.Cancel(); + } + } + } + /// /// Collects Cache Telemetry Information. /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index 47232a187e..2aeaadca63 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -79,13 +79,12 @@ internal static class ClientTelemetryOptions internal const double Percentile99 = 99.0; internal const double Percentile999 = 99.9; internal const string DateFormat = "yyyy-MM-ddTHH:mm:ssZ"; - internal const string EnvPropsClientTelemetrySchedulingInSeconds = "COSMOS.CLIENT_TELEMETRY_SCHEDULING_IN_SECONDS"; internal const string EnvPropsClientTelemetryEnabled = "COSMOS.CLIENT_TELEMETRY_ENABLED"; internal const string EnvPropsClientTelemetryVmMetadataUrl = "COSMOS.VM_METADATA_URL"; internal const string EnvPropsClientTelemetryEndpoint = "COSMOS.CLIENT_TELEMETRY_ENDPOINT"; internal const string EnvPropsClientTelemetryEnvironmentName = "COSMOS.ENVIRONMENT_NAME"; - + internal static readonly ResourceType AllowedResourceTypes = ResourceType.Document; // Why 5 sec? As of now, if any network request is taking more than 5 millisecond sec, we will consider it slow request this value can be revisited in future internal static readonly TimeSpan NetworkLatencyThreshold = TimeSpan.FromMilliseconds(5); @@ -101,7 +100,8 @@ internal static class ClientTelemetryOptions internal static readonly int NetworkTelemetrySampleSize = 200; internal static int PayloadSizeThreshold = 1024 * 1024 * 2; // 2MB - + internal static TimeSpan ClientTelemetryProcessorTimeOut = TimeSpan.FromMinutes(5); + private static Uri clientTelemetryEndpoint; private static string environmentName; private static TimeSpan scheduledTimeSpan = TimeSpan.Zero; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 7e924ffd53..30edc7ebf7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -1075,33 +1075,6 @@ private static void AssertCacheRefreshInfoInformation( } } - [TestMethod] - public async Task CheckMisconfiguredTelemetryEndpoint_should_stop_the_job() - { - int retryCounter = 0; - HttpClientHandlerHelper customHttpHandler = new HttpClientHandlerHelper - { - RequestCallBack = (request, cancellation) => - { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) - { - retryCounter++; - throw new Exception("Exception while sending telemetry"); - } - - return null; - } - }; - - Container container = await this.CreateClientAndContainer( - mode: ConnectionMode.Direct, - customHttpHandler: customHttpHandler); - - await Task.Delay(TimeSpan.FromMilliseconds(5000)); // wait for 5 sec, ideally telemetry would be sent 5 times but client telemetry endpoint is not functional (in this test), it should try 3 times maximum and after that client telemetry job should be stopped. - - Assert.AreEqual(3, retryCounter); - } - private static ItemBatchOperation CreateItem(string itemId) { var testItem = new { id = itemId, Status = itemId }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs index 4a6b077baa..9308d22806 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs @@ -30,6 +30,7 @@ public class ClientTelemetryTests public void Cleanup() { Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); } [TestMethod] @@ -147,7 +148,6 @@ public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInf string payloadJson = request.Content.ReadAsStringAsync().Result; Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); - Console.WriteLine(payloadJson); ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); Assert.AreEqual(7, propertiesToSend.SystemInfo.Count, "System Info is not correct"); @@ -245,14 +245,114 @@ await processor.ProcessAndSendAsync( clientTelemetryProperties, operationInfoSnapshot, cacheRefreshInfoSnapshot, - requestInfoList, - new CancellationToken()); + requestInfoList, + new CancellationTokenSource(ClientTelemetryOptions.ClientTelemetryProcessorTimeOut).Token); Assert.AreEqual(expectedOperationInfoSize, actualOperationInfoSize, "Operation Info is not correct"); Assert.AreEqual(expectedCacheRefreshInfoSize, actualCacheRefreshInfoSize, "Cache Refresh Info is not correct"); Assert.AreEqual(expectedRequestInfoSize, actualRequestInfoSize, "Request Info is not correct"); } - + + [TestMethod] + public async Task ClientTelmetryProcessor_should_timeout() + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); + + string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); + ClientTelemetryProperties clientTelemetryProperties = JsonConvert.DeserializeObject(data); + + int actualOperationInfoSize = 0; + int actualCacheRefreshInfoSize = 0; + + Mock mockHttpHandler = new Mock(); + _ = mockHttpHandler.Setup(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Callback( + (request, cancellationToken) => + { + string payloadJson = request.Content.ReadAsStringAsync().Result; + Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); + + ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); + + actualOperationInfoSize += propertiesToSend.OperationInfo?.Count ?? 0; + actualCacheRefreshInfoSize += propertiesToSend.CacheRefreshInfo?.Count ?? 0; + }) + .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + + ClientTelemetryProcessor processor = new ClientTelemetryProcessor( + MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object))), + Mock.Of()); + + ConcurrentDictionary operationInfoSnapshot + = new ConcurrentDictionary(); + + for (int i = 0; i < 20; i++) + { + OperationInfo opeInfo = new OperationInfo(Regions.WestUS, + 0, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + 200, + 0); + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10); + + LongConcurrentHistogram requestcharge = new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, + ClientTelemetryOptions.RequestChargeMax, + ClientTelemetryOptions.RequestChargePrecision); + requestcharge.RecordValue(11); + + operationInfoSnapshot.TryAdd(opeInfo, (latency, requestcharge)); + } + + ConcurrentDictionary cacheRefreshInfoSnapshot + = new ConcurrentDictionary(); + for (int i = 0; i < 10; i++) + { + CacheRefreshInfo crInfo = new CacheRefreshInfo(Regions.WestUS, + 10, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + 200, + 1002, + "dummycache"); + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10); + + cacheRefreshInfoSnapshot.TryAdd(crInfo, latency); + } + + Task processorTask = Task.Run(async () => + { + CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + await Task.Delay(1000, cts.Token); // Making this task wait to ensure that processir is taking more time. + await processor.ProcessAndSendAsync(clientTelemetryProperties, + operationInfoSnapshot, + cacheRefreshInfoSnapshot, + default, + cts.Token); + }); + + await Assert.ThrowsExceptionAsync(() => ClientTelemetry.RunProcessorTaskAsync( + telemetryDate: DateTime.Now.ToString(), + processingTask: processorTask, + timeout: TimeSpan.FromTicks(1))); + } + [TestMethod] [ExpectedException(typeof(FormatException))] public void CheckMisconfiguredTelemetry_should_fail() From 33dea8a333239a63be8700da1d982bde99d17da8 Mon Sep 17 00:00:00 2001 From: Amaan-Haque <54414760+Amaan-Haque@users.noreply.github.com> Date: Tue, 11 Apr 2023 21:09:22 +0530 Subject: [PATCH 092/337] Patch: Adds Move Operation (#3389) * Basic changes to introduce move operator * Added "from" object in patch spec operation. Added testcase block. * Fixed testcase. * Changes made to address comments' * Added comment regarding enum mutations * Formatted comment Co-authored-by: Matias Quaranta * Moved summary location. * Ran UpdateContracts.ps1 --------- Co-authored-by: Amaan Haque Co-authored-by: Amaan Haque Co-authored-by: Matias Quaranta --- .../src/Patch/PatchConstants.cs | 4 ++ .../src/Patch/PatchOperation.cs | 22 ++++++++++ .../src/Patch/PatchOperationCore{T}.cs | 43 +++++++++++++------ .../src/Patch/PatchOperationType.cs | 8 +++- .../src/Patch/PatchOperationsJsonConverter.cs | 7 ++- .../Batch/BatchSinglePartitionKeyTests.cs | 6 ++- .../CosmosItemTests.cs | 17 +++++++- .../Contracts/DotNetSDKAPI.json | 33 ++++++++++++++ 8 files changed, 122 insertions(+), 18 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Patch/PatchConstants.cs b/Microsoft.Azure.Cosmos/src/Patch/PatchConstants.cs index fd0cd79215..b06ad841b4 100644 --- a/Microsoft.Azure.Cosmos/src/Patch/PatchConstants.cs +++ b/Microsoft.Azure.Cosmos/src/Patch/PatchConstants.cs @@ -13,6 +13,7 @@ public static class PropertyNames public const string OperationType = "op"; public const string Path = "path"; public const string Value = "value"; + public const string From = "from"; } public static class PatchSpecAttributes @@ -28,6 +29,7 @@ public static class OperationTypeNames public const string Replace = "replace"; public const string Set = "set"; public const string Increment = "incr"; + public const string Move = "move"; } public static string ToEnumMemberString(this PatchOperationType patchOperationType) @@ -44,6 +46,8 @@ public static string ToEnumMemberString(this PatchOperationType patchOperationTy return PatchConstants.OperationTypeNames.Set; case PatchOperationType.Increment: return PatchConstants.OperationTypeNames.Increment; + case PatchOperationType.Move: + return PatchConstants.OperationTypeNames.Move; default: throw new ArgumentException($"Unknown Patch operation type '{patchOperationType}'."); } diff --git a/Microsoft.Azure.Cosmos/src/Patch/PatchOperation.cs b/Microsoft.Azure.Cosmos/src/Patch/PatchOperation.cs index 16448c7f9f..412dec2334 100644 --- a/Microsoft.Azure.Cosmos/src/Patch/PatchOperation.cs +++ b/Microsoft.Azure.Cosmos/src/Patch/PatchOperation.cs @@ -25,6 +25,12 @@ public abstract class PatchOperation [JsonProperty(PropertyName = PatchConstants.PropertyNames.Path)] public abstract string Path { get; } + /// + /// Source location reference (used in case of move) + /// + [JsonProperty(PropertyName = PatchConstants.PropertyNames.From)] + public virtual string From { get; set; } = null; + /// /// Serializes the value parameter, if specified for the PatchOperation. /// @@ -134,5 +140,21 @@ public static PatchOperation Increment( path, value); } + + /// + /// Create to move an object/value. + /// + /// The source location of the object/value. + /// Target location reference. + /// PatchOperation instance for specified input. + public static PatchOperation Move( + string from, + string path) + { + return new PatchOperationCore( + PatchOperationType.Move, + path, + from); + } } } diff --git a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationCore{T}.cs b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationCore{T}.cs index bb87570242..c560cbae7b 100644 --- a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationCore{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationCore{T}.cs @@ -10,23 +10,40 @@ namespace Microsoft.Azure.Cosmos internal sealed class PatchOperationCore : PatchOperation { /// - /// Initializes a new instance of the class. - /// - /// Specifies the type of Patch operation. - /// Specifies the path to target location. - /// Specifies the value to be used. +        /// Initializes a new instance of the class. +        /// +        /// Specifies the type of Patch operation. +        /// Specifies the path to target location. +        /// Specifies the value to be used. In case of move operations it will be a string specifying the source +        /// location. public PatchOperationCore( - PatchOperationType operationType, - string path, - T value) + PatchOperationType operationType, + string path, + T value) { this.OperationType = operationType; - this.Path = string.IsNullOrWhiteSpace(path) - ? throw new ArgumentNullException(nameof(path)) - : path; - this.Value = value; + if (operationType == PatchOperationType.Move) + { + this.Path = string.IsNullOrWhiteSpace(path) + ? throw new ArgumentNullException(nameof(path)) + : path; + if (!(value is String valueAsString)) + { + throw new ArgumentException( + $"Parameter {nameof(value)} must be of type String for patch operation type {nameof(PatchOperationType.Move)}"); + } + this.From = string.IsNullOrWhiteSpace(valueAsString) + ? throw new ArgumentNullException(nameof(value)) + : valueAsString; + } + else + { + this.Path = string.IsNullOrWhiteSpace(path) + ? throw new ArgumentNullException(nameof(path)) + : path; + this.Value = value; + } } - public override T Value { get; } public override PatchOperationType OperationType { get; } diff --git a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationType.cs b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationType.cs index 7504492126..d98d35f832 100644 --- a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationType.cs +++ b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationType.cs @@ -9,7 +9,7 @@ namespace Microsoft.Azure.Cosmos using Newtonsoft.Json.Converters; /// - /// Type of Patch operation. + /// Describes the list of Patch supported operation types. /// /// /// For more information, see Partial document update in Azure Cosmos DB: Supported operations @@ -47,5 +47,11 @@ public enum PatchOperationType /// [EnumMember(Value = PatchConstants.OperationTypeNames.Increment)] Increment, + + /// + /// Operation to move a object/value. + /// + [EnumMember(Value = PatchConstants.OperationTypeNames.Move)] + Move, } } diff --git a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationsJsonConverter.cs b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationsJsonConverter.cs index 6cb9c8fa45..04419a5765 100644 --- a/Microsoft.Azure.Cosmos/src/Patch/PatchOperationsJsonConverter.cs +++ b/Microsoft.Azure.Cosmos/src/Patch/PatchOperationsJsonConverter.cs @@ -88,7 +88,12 @@ public override void WriteJson( writer.WritePropertyName(PatchConstants.PropertyNames.Path); writer.WriteValue(operation.Path); - if (operation.TrySerializeValueParameter(this.userSerializer, out Stream valueStream)) + if (operation.OperationType == PatchOperationType.Move) + { + writer.WritePropertyName(PatchConstants.PropertyNames.From); + writer.WriteValue(operation.From); + } + else if (operation.TrySerializeValueParameter(this.userSerializer, out Stream valueStream)) { string valueParam; using (valueStream) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs index 675ed6b20e..b2b1ffb217 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchSinglePartitionKeyTests.cs @@ -693,7 +693,8 @@ public async Task BatchCustomSerializerUsedForPatchAsync() DateTime patchDate = new DateTime(2020, 07, 01, 01, 02, 03); List patchOperations = new List() { - PatchOperation.Add("/date", patchDate) + PatchOperation.Add("/date", patchDate), + PatchOperation.Move("/date", "/TodayDate") }; BatchCore batch = (BatchCore)new BatchCore((ContainerInlineCore)customSerializationContainer, BatchTestBase.GetPartitionKey(this.PartitionKey1)) @@ -719,7 +720,8 @@ public async Task BatchCustomSerializerUsedForPatchAsync() Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Resource); - Assert.IsTrue(dateJson.Contains(response.Resource["date"].ToString())); + Assert.IsNull(response.Resource["date"]); + Assert.IsTrue(dateJson.Contains(response.Resource["TodayDate"].ToString())); } private async Task RunCrudAsync(bool isStream, bool isSchematized, bool useEpk, Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index c5d6347dd1..b237c68c2a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -1984,7 +1984,6 @@ public async Task ItemPatchSuccessTest() patchOperations.Clear(); patchOperations.Add(PatchOperation.Add("/children/0/cost", 1)); - //patchOperations.Add(PatchOperation.Set("/random", value)); // with content response response = await containerInternal.PatchItemAsync( id: testItem.id, @@ -2006,6 +2005,22 @@ public async Task ItemPatchSuccessTest() Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Resource); Assert.AreEqual(null, response.Resource.children[0].id); + + patchOperations.Clear(); + patchOperations.Add(PatchOperation.Add("/children/1/description","Child#1")); + patchOperations.Add(PatchOperation.Move("/children/0/description", "/description")); + patchOperations.Add(PatchOperation.Move("/children/1/description", "/children/0/description")); + // with content response + response = await containerInternal.PatchItemAsync( + id: testItem.id, + partitionKey: new Cosmos.PartitionKey(testItem.pk), + patchOperations: patchOperations); + + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.IsNotNull(response.Resource); + Assert.AreEqual("testSet", response.Resource.description); + Assert.AreEqual("Child#1", response.Resource.children[0].description); + Assert.IsNull(response.Resource.children[1].description); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 3cf5c017c2..3eee7f406b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -5745,6 +5745,11 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.PatchOperation Increment(System.String, Int64);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.PatchOperation Move(System.String, System.String)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PatchOperation Move(System.String, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.PatchOperation Remove(System.String)": { "Type": "Method", "Attributes": [], @@ -5772,6 +5777,20 @@ ], "MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType OperationType;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.PatchOperationType get_OperationType();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.String From[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"from\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String From;CanRead:True;CanWrite:True;System.String get_From();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_From(System.String);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_From()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_From();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String get_Path()": { "Type": "Method", "Attributes": [], @@ -5783,6 +5802,13 @@ "JsonPropertyAttribute" ], "MethodInfo": "System.String Path;CanRead:True;CanWrite:False;System.String get_Path();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_From(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_From(System.String);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} @@ -5827,6 +5853,13 @@ ], "MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType Increment;IsInitOnly:False;IsStatic:True;" }, + "Microsoft.Azure.Cosmos.PatchOperationType Move[System.Runtime.Serialization.EnumMemberAttribute(Value = \"move\")]": { + "Type": "Field", + "Attributes": [ + "EnumMemberAttribute" + ], + "MethodInfo": "Microsoft.Azure.Cosmos.PatchOperationType Move;IsInitOnly:False;IsStatic:True;" + }, "Microsoft.Azure.Cosmos.PatchOperationType Remove[System.Runtime.Serialization.EnumMemberAttribute(Value = \"remove\")]": { "Type": "Field", "Attributes": [ From 31b1ff330a4b0983f8e29a1156faaa0c702584d5 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 11 Apr 2023 11:48:29 -0700 Subject: [PATCH 093/337] [Internal] Pipelines: Adds nightly build to produce packages (#3802) * Support cleaning * wire previous content delete * as text * with variable * another test * param with types * as string * no delete * no quotes * undoing * re-adding quotes * testing empty * trying another test * readding version * fixing publishing artifacts * fixing parameter * Fixing official pipeline * version 5 * fixing main pipeline * test with true * using start time * nightly preview * passing parameters to pack * Fixing nuget version * arguments on the nuget pack * folder structure * testing v5 * Using only content * Removing currentDate --- .../src/Microsoft.Azure.Cosmos.csproj | 3 +- azure-pipelines-nightly.yml | 72 ++++++------------- azure-pipelines-official.yml | 3 +- azure-pipelines.yml | 1 - templates/nuget-pack.yml | 67 ++++++++++------- 5 files changed, 63 insertions(+), 83 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 7ba4e9213d..6a5be8ccbb 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -9,8 +9,9 @@ $([System.DateTime]::Now.ToString(yyyyMMdd)) $(ClientOfficialVersion) $(ClientPreviewVersion) - nightly-$(CurrentDate) $(ClientPreviewSuffixVersion) + nightly-$(CurrentDate) + $(VersionSuffix)-nightly-$(CurrentDate) $(ClientVersion) $(ClientVersion)-$(VersionSuffix) $(ClientVersion) diff --git a/azure-pipelines-nightly.yml b/azure-pipelines-nightly.yml index 8db3ff01e6..04a53968aa 100644 --- a/azure-pipelines-nightly.yml +++ b/azure-pipelines-nightly.yml @@ -13,64 +13,32 @@ schedules: variables: - ReleaseArguments: ' --filter "TestCategory!=Quarantine" --verbosity normal ' VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops - BuildConfiguration: Release - IsNightly: true - + BuildConfiguration: Release + Packaging.EnableSBOMSigning: true stages: - stage: - displayName: Gate + displayName: Generate nightly GA jobs: - - template: templates/static-tools.yml - parameters: - BuildConfiguration: $(BuildConfiguration) - VmImage: $(VmImage) - - - - template: templates/build-test.yml + - template: templates/nuget-pack.yml parameters: - BuildConfiguration: $(BuildConfiguration) - Arguments: $(ReleaseArguments) /p:IsNightly=true /p:GeneratePackageOnBuild=true + BuildConfiguration: Release + Arguments: /p:IsNightly=true VmImage: $(VmImage) - - + ReleasePackage: true + OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' + BlobVersion: 'nightly' + CleanupFolder: true - stage: - displayName: Publish + displayName: Generate nightly preview jobs: - - job: - pool: - vmImage: $(VmImage) - - steps: - - task: DotNetCoreCLI@2 - displayName: Build Microsoft.Azure.Cosmos - inputs: - command: build - configuration: $(BuildConfiguration) - nugetConfigPath: NuGet.config - projects: Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj - arguments: --configuration $(BuildConfiguration) - versioningScheme: OFF - - - task: DotNetCoreCLI@2 - displayName: Pack Microsoft.Azure.Cosmos - inputs: - command: pack - configuration: $(BuildConfiguration) - searchPatternPack: Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj - arguments: --configuration $(BuildConfiguration) - versioningScheme: OFF - - - task: DotNetCoreCLI@2 - displayName: Push Microsoft.Azure.Cosmos - inputs: - command: push - configuration: $(BuildConfiguration) - searchPatternPack: Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj - arguments: --configuration $(BuildConfiguration) - packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg' - nuGetFeedType: 'internal' - publishVstsFeed: '4000bd49-81c3-47f2-94d8-d1392b95c228/04efb628-f46d-4b48-ac4d-5af5b1c75043' #azure-cosmos-dotnet - versioningScheme: OFF + - template: templates/nuget-pack.yml + parameters: + BuildConfiguration: Release + Arguments: /p:IsNightly=true /p:IsPreview=true + VmImage: $(VmImage) + ReleasePackage: true + OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' + BlobVersion: 'nightly-preview' + CleanupFolder: true \ No newline at end of file diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 1aff6dbfd2..510bf5f6f8 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -29,8 +29,7 @@ stages: - template: templates/nuget-pack.yml parameters: BuildConfiguration: Release - Arguments: $(ReleaseArguments) VmImage: $(VmImage) ReleasePackage: true OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' - BlobVersion: variables['BlobVersion'] + BlobVersion: $(BlobVersion) \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 98490f0a62..aae5115a5e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -29,7 +29,6 @@ jobs: - template: templates/nuget-pack.yml parameters: BuildConfiguration: Release - Arguments: $(ReleaseArguments) VmImage: $(VmImage) ReleasePackage: false OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/Release/Microsoft.Azure.Cosmos' diff --git a/templates/nuget-pack.yml b/templates/nuget-pack.yml index 874676d3e1..095b1b52ff 100644 --- a/templates/nuget-pack.yml +++ b/templates/nuget-pack.yml @@ -1,13 +1,27 @@ # File: templates/nuget-pack.yml parameters: - BuildConfiguration: '' - Arguments: '' - VmImage: '' # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops - OS: 'Windows' - OutputPath: '' - ReleasePackage: false - BlobVersion: '' + - name: BuildConfiguration + type: string + default: '' + - name: Arguments + type: string + default: '' + - name: VmImage + type: string + default: '' + - name: OutputPath + type: string + default: '' + - name: BlobVersion + type: string + default: '' + - name: ReleasePackage + type: boolean + default: false + - name: CleanupFolder + type: boolean + default: false jobs: - job: GenerateNugetPackages @@ -23,7 +37,7 @@ jobs: configuration: $(BuildConfiguration) nugetConfigPath: NuGet.config projects: Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj - arguments: --configuration ${{ parameters.BuildConfiguration }} -p:Optimize=true + arguments: --configuration ${{ parameters.BuildConfiguration }} -p:Optimize=true ${{ parameters.Arguments }} versioningScheme: OFF - task: DotNetCoreCLI@2 @@ -32,7 +46,7 @@ jobs: command: custom projects: 'Microsoft.Azure.Cosmos\src\Microsoft.Azure.Cosmos.csproj' custom: pack - arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build --no-restore -o "${{ parameters.OutputPath }}"' + arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build ${{ parameters.Arguments }} --no-restore -o "${{ parameters.OutputPath }}"' - ${{ if eq(parameters.ReleasePackage, true) }}: - task: DotNetCoreCLI@2 @@ -41,26 +55,25 @@ jobs: command: custom projects: 'Microsoft.Azure.Cosmos\src\Microsoft.Azure.Cosmos.csproj' custom: pack - arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build --include-symbols /p:SymbolPackageFormat=snupkg --no-restore -o "${{ parameters.OutputPath }}"' + arguments: '-v detailed -c ${{ parameters.BuildConfiguration }} --no-build --include-symbols /p:SymbolPackageFormat=snupkg ${{ parameters.Arguments }} --no-restore -o "${{ parameters.OutputPath }}"' - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 inputs: BuildDropPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' - - task: AzureFileCopy@2 - displayName: ' Copy Artifacts to Azure SDK Release blob storage' - condition: and(succeeded(),ne(${{ parameters.BlobVersion }}, '')) - inputs: - SourcePath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' - azureSubscription: azuresdkpartnerdrops - Destination: AzureBlob - storage: azuresdkpartnerdrops - ContainerName: 'drops' - BlobPrefix: 'cosmosdb/csharp/$(BlobVersion)' - - - task: PublishBuildArtifacts@1 - displayName: 'Publish Artifacts: Microsoft.Azure.Cosmos' - inputs: - artifactName: Microsoft.Azure.Cosmos + - ${{ if ne(parameters.BlobVersion, '') }}: + - task: AzureFileCopy@5 + displayName: 'Copy Artifacts to Azure SDK Release blob storage' + condition: succeeded() + inputs: + SourcePath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos/**' + azureSubscription: azuresdkpartnerdrops + Destination: AzureBlob + storage: azuresdkpartnerdrops + ContainerName: 'drops' + BlobPrefix: 'cosmosdb/csharp/${{ parameters.BlobVersion }}' + CleanTargetBeforeCopy: ${{ parameters.CleanupFolder }} - - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 - displayName: 'Component Detection' + - task: PublishBuildArtifacts@1 + displayName: 'Publish Artifacts: Microsoft.Azure.Cosmos' + inputs: + artifactName: Microsoft.Azure.Cosmos From bfbb43e6b835f921cb17fec0c1f25a84b0430065 Mon Sep 17 00:00:00 2001 From: aavasthy <113193425+aavasthy@users.noreply.github.com> Date: Tue, 18 Apr 2023 07:33:59 -0700 Subject: [PATCH 094/337] [Internal] OpenTelemetry: Direct Package update and replacing diagnostic files (#3797) * Direct Package update and replacing dagnostic files * Resolve merge conflicts * Running updateCOnstracts script * Removed LinqTranslationWithCustomSerializerBaseline file * Adding isDistributedTracingEnabled flag * Running update contracts * Running update contracts * Running update contracts * fix test * Code cleanup for test fix * Code cleanup for test fix * Making regex expression readable * Adding comment for regex expression --------- Co-authored-by: Sourabh Jain --- Directory.Build.props | 2 +- .../ChangeFeedProcessorUserException.cs | 2 +- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 17 +- .../OSS/Azure.Core/AppContextSwitchHelper.cs | 44 -- .../src/OSS/Azure.Core/DiagnosticScope.cs | 664 ------------------ .../OSS/Azure.Core/DiagnosticScopeFactory.cs | 61 -- .../src/Resource/ClientContextCore.cs | 3 +- .../CosmosExceptions/CosmosException.cs | 2 +- .../CosmosNullReferenceException.cs | 2 +- .../CosmosObjectDisposedException.cs | 2 +- .../CosmosOperationCanceledException.cs | 2 +- .../OpenTelemetryCoreRecorder.cs | 2 +- .../OpenTelemetryRecorderFactory.cs | 5 +- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- ...riterBaselineTests.BulkOperationsAsync.xml | 202 +++--- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 44 +- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...neTests.PointOperationsExceptionsAsync.xml | 12 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 +- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +- ...TraceWriterBaselineTests.ReadManyAsync.xml | 4 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Tracing/AssertActivity.cs | 1 + .../Tracing/CustomListener.cs | 24 +- .../EndToEndTraceWriterBaselineTests.cs | 1 - .../Utils/Util.cs | 6 +- 27 files changed, 235 insertions(+), 981 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos/src/OSS/Azure.Core/AppContextSwitchHelper.cs delete mode 100644 Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScope.cs delete mode 100644 Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScopeFactory.cs diff --git a/Directory.Build.props b/Directory.Build.props index e51eae5f3f..40b25a6e73 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.32.3 3.32.3 preview - 3.30.4 + 3.30.6 2.0.1 2.0.1 preview diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Exceptions/ChangeFeedProcessorUserException.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Exceptions/ChangeFeedProcessorUserException.cs index b62eba6ec7..b3b4f51932 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Exceptions/ChangeFeedProcessorUserException.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Exceptions/ChangeFeedProcessorUserException.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Runtime.Serialization; - using global::Azure.Core.Pipeline; + using global::Azure.Core; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index cbd4e06674..451166618d 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -167,6 +167,9 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider //RemoteCertificateValidationCallback internal RemoteCertificateValidationCallback remoteCertificateValidationCallback; + //Distributed Tracing Flag + internal bool isDistributedTracingEnabled; + //SessionContainer. internal ISessionContainer sessionContainer; @@ -426,6 +429,7 @@ internal DocumentClient(Uri serviceEndpoint, /// Flag to allow Quorum Read with Eventual Consistency Account /// /// This delegate responsible for validating the third party certificate. + /// This is distributed tracing flag /// /// The service endpoint can be obtained from the Azure Management Portal. /// If you are connecting using one of the Master Keys, these can be obtained along with the endpoint from the Azure Management Portal @@ -452,7 +456,8 @@ internal DocumentClient(Uri serviceEndpoint, IStoreClientFactory storeClientFactory = null, bool isLocalQuorumConsistency = false, string cosmosClientId = null, - RemoteCertificateValidationCallback remoteCertificateValidationCallback = null) + RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, + bool isDistributedTracingEnabled = false) { if (sendingRequestEventArgs != null) { @@ -485,7 +490,8 @@ internal DocumentClient(Uri serviceEndpoint, enableCpuMonitor: enableCpuMonitor, storeClientFactory: storeClientFactory, cosmosClientId: cosmosClientId, - remoteCertificateValidationCallback: remoteCertificateValidationCallback); + remoteCertificateValidationCallback: remoteCertificateValidationCallback, + isDistributedTracingEnabled: isDistributedTracingEnabled); } /// @@ -668,7 +674,8 @@ internal virtual void Initialize(Uri serviceEndpoint, IStoreClientFactory storeClientFactory = null, TokenCredential tokenCredential = null, string cosmosClientId = null, - RemoteCertificateValidationCallback remoteCertificateValidationCallback = null) + RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, + bool isDistributedTracingEnabled = false) { if (serviceEndpoint == null) { @@ -677,6 +684,7 @@ internal virtual void Initialize(Uri serviceEndpoint, this.clientId = cosmosClientId; this.remoteCertificateValidationCallback = remoteCertificateValidationCallback; + this.isDistributedTracingEnabled = isDistributedTracingEnabled; this.queryPartitionProvider = new AsyncLazy(async () => { @@ -6658,7 +6666,8 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory enableTcpConnectionEndpointRediscovery: this.ConnectionPolicy.EnableTcpConnectionEndpointRediscovery, addressResolver: this.AddressResolver, rntbdMaxConcurrentOpeningConnectionCount: this.rntbdMaxConcurrentOpeningConnectionCount, - remoteCertificateValidationCallback: this.remoteCertificateValidationCallback ); + remoteCertificateValidationCallback: this.remoteCertificateValidationCallback, + isDistributedTracingEnabled: this.isDistributedTracingEnabled); if (this.transportClientHandlerFactory != null) { diff --git a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/AppContextSwitchHelper.cs b/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/AppContextSwitchHelper.cs deleted file mode 100644 index d7e25b35c3..0000000000 --- a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/AppContextSwitchHelper.cs +++ /dev/null @@ -1,44 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// This File is copied from Azure.Core repo i.e. https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/AppContextSwitchHelper.cs - -#nullable enable - -namespace Azure.Core -{ - using System; - /// - /// Helper for interacting with AppConfig settings and their related Environment variable settings. - /// - internal static class AppContextSwitchHelper - { - /// - /// Determines if either an AppContext switch or its corresponding Environment Variable is set - /// - /// Name of the AppContext switch. - /// Name of the Environment variable. - /// If the AppContext switch has been set, returns the value of the switch. - /// If the AppContext switch has not been set, returns the value of the environment variable. - /// False if neither is set. - /// - public static bool GetConfigValue(string appContexSwitchName, string environmentVariableName) - { - // First check for the AppContext switch, giving it priority over the environment variable. - if (AppContext.TryGetSwitch(appContexSwitchName, out bool value)) - { - return value; - } - // AppContext switch wasn't used. Check the environment variable. - string? envVar = Environment.GetEnvironmentVariable(environmentVariableName); - if (envVar != null && (envVar.Equals("true", StringComparison.OrdinalIgnoreCase) || envVar.Equals("1"))) - { - return true; - } - - // Default to false. - return false; - } - } -} diff --git a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScope.cs b/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScope.cs deleted file mode 100644 index ca05f6cabb..0000000000 --- a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScope.cs +++ /dev/null @@ -1,664 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// This File is copied from Azure.Core repo. i.e. https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/DiagnosticScope.cs - -#nullable enable - -namespace Azure.Core.Pipeline -{ - using System; - using System.Collections; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Linq.Expressions; - using System.Reflection; - - internal readonly struct DiagnosticScope : IDisposable - { - private static readonly ConcurrentDictionary ActivitySources = new (); - - private readonly ActivityAdapter? activityAdapter; - - internal DiagnosticScope(string ns, string scopeName, DiagnosticListener source, ActivityKind kind) - { - object? activitySource = GetActivitySource(ns, scopeName); - - this.IsEnabled = source.IsEnabled() || ActivityExtensions.ActivitySourceHasListeners(activitySource); - - this.activityAdapter = this.IsEnabled ? new ActivityAdapter(activitySource, source, scopeName, kind, null) : null; - } - - internal DiagnosticScope(string scopeName, DiagnosticListener source, object? diagnosticSourceArgs, object? activitySource, ActivityKind kind) - { - this.IsEnabled = source.IsEnabled() || ActivityExtensions.ActivitySourceHasListeners(activitySource); - - this.activityAdapter = this.IsEnabled ? new ActivityAdapter(activitySource, source, scopeName, kind, diagnosticSourceArgs) : null; - } - - public bool IsEnabled { get; } - - /// - /// This method combines client namespace and operation name into an ActivitySource name and creates the activity source. - /// For example: - /// ns: Azure.Storage.Blobs - /// name: BlobClient.DownloadTo - /// result Azure.Storage.Blobs.BlobClient - /// - private static object? GetActivitySource(string ns, string name) - { - if (!ActivityExtensions.SupportsActivitySource()) - { - return null; - } - - int indexOfDot = name.IndexOf(".", StringComparison.OrdinalIgnoreCase); - if (indexOfDot == -1) - { - return null; - } - - string clientName = ns + "." + name.Substring(0, indexOfDot); - - return ActivitySources.GetOrAdd(clientName, static n => ActivityExtensions.CreateActivitySource(n)); - } - - public void AddAttribute(string name, string? value) - { - this.activityAdapter?.AddTag(name, value); - } - - public void AddAttribute(string name, -#if AZURE_NULLABLE - [AllowNull] -#endif - T value) - { - this.AddAttribute(name, value, static v => Convert.ToString(v, CultureInfo.InvariantCulture) ?? string.Empty); - } - - public void AddAttribute(string name, T value, Func format) - { - if (this.activityAdapter != null) - { - var formattedValue = format(value); - this.activityAdapter.AddTag(name, formattedValue); - } - } - - public void AddLink(string traceparent, string tracestate, IDictionary? attributes = null) - { - this.activityAdapter?.AddLink(traceparent, tracestate, attributes); - } - - public void Start() - { - this.activityAdapter?.Start(); - } - - public void SetStartTime(DateTime dateTime) - { - this.activityAdapter?.SetStartTime(dateTime); - } - - public void Dispose() - { - // Reverse the Start order - this.activityAdapter?.Dispose(); - } - - public void Failed(Exception e) - { - this.activityAdapter?.MarkFailed(e); - } - - /// - /// Kind describes the relationship between the Activity, its parents, and its children in a Trace. - /// - public enum ActivityKind - { - /// - /// Default value. - /// Indicates that the Activity represents an internal operation within an application, as opposed to an operations with remote parents or children. - /// - Internal = 0, - - /// - /// Server activity represents request incoming from external component. - /// - Server = 1, - - /// - /// Client activity represents outgoing request to the external component. - /// - Client = 2, - - /// - /// Producer activity represents output provided to external components. - /// - Producer = 3, - - /// - /// Consumer activity represents output received from an external component. - /// - Consumer = 4, - } - - private class DiagnosticActivity : Activity - { -#pragma warning disable 109 // extra new modifier - public new IEnumerable Links { get; set; } = Array.Empty(); -#pragma warning restore 109 - - public DiagnosticActivity(string operationName) - : base(operationName) - { - } - } - - private class ActivityAdapter : IDisposable - { - private readonly DiagnosticSource diagnosticSource; - private readonly object? activitySource; - private readonly string activityName; - private readonly ActivityKind kind; - private object? diagnosticSourceArgs; - - private Activity? currentActivity; - private ICollection>? tagCollection; - private DateTimeOffset startTime; - private List? links; - - public ActivityAdapter(object? activitySource, DiagnosticSource diagnosticSource, string activityName, ActivityKind kind, object? diagnosticSourceArgs) - { - this.activitySource = activitySource; - this.diagnosticSource = diagnosticSource; - this.activityName = activityName; - this.kind = kind; - this.diagnosticSourceArgs = diagnosticSourceArgs; - - switch (this.kind) - { - case ActivityKind.Internal: - this.AddTag("kind", "internal"); - break; - case ActivityKind.Server: - this.AddTag("kind", "server"); - break; - case ActivityKind.Client: - this.AddTag("kind", "client"); - break; - case ActivityKind.Producer: - this.AddTag("kind", "producer"); - break; - case ActivityKind.Consumer: - this.AddTag("kind", "consumer"); - break; - } - } - - public void AddTag(string name, string? value) - { - if (this.currentActivity == null) - { - // Activity is not started yet, add the value to the collection - // that is going to be passed to StartActivity - this.tagCollection ??= ActivityExtensions.CreateTagsCollection() ?? new List>(); - this.tagCollection?.Add(new KeyValuePair(name, value!)); - } - else - { - this.currentActivity?.AddTag(name, value!); - } - } - - private IList? GetActivitySourceLinkCollection() - { - if (this.links == null) - { - return null; - } - - var linkCollection = ActivityExtensions.CreateLinkCollection(); - if (linkCollection == null) - { - return null; - } - - foreach (var activity in this.links) - { - ICollection>? linkTagsCollection = ActivityExtensions.CreateTagsCollection(); - if (linkTagsCollection != null) - { - foreach (var tag in activity.Tags) - { - linkTagsCollection.Add(new KeyValuePair(tag.Key, tag.Value!)); - } - } - - var link = ActivityExtensions.CreateActivityLink(activity.ParentId!, activity.TraceStateString, linkTagsCollection); - if (link != null) - { - linkCollection.Add(link); - } - } - - return linkCollection; - } - - public void AddLink(string traceparent, string tracestate, IDictionary? attributes) - { - var linkedActivity = new Activity("LinkedActivity"); - linkedActivity.SetW3CFormat(); - linkedActivity.SetParentId(traceparent); - linkedActivity.TraceStateString = tracestate; - - if (attributes != null) - { - foreach (var kvp in attributes) - { - linkedActivity.AddTag(kvp.Key, kvp.Value); - } - } - - this.links ??= new List(); - this.links.Add(linkedActivity); - } - - public void Start() - { - this.currentActivity = this.StartActivitySourceActivity(); - - if (this.currentActivity == null) - { - if (!this.diagnosticSource.IsEnabled(this.activityName, this.diagnosticSourceArgs)) - { - return; - } - - this.currentActivity = new DiagnosticActivity(this.activityName) - { - Links = (IEnumerable?)this.links ?? Array.Empty(), - }; - this.currentActivity.SetW3CFormat(); - - if (this.startTime != default) - { - this.currentActivity.SetStartTime(this.startTime.DateTime); - } - - if (this.tagCollection != null) - { - foreach (var tag in this.tagCollection) - { - this.currentActivity.AddTag(tag.Key, (string)tag.Value); - } - } - - this.currentActivity.Start(); - } - - this.diagnosticSource.Write(this.activityName + ".Start", this.diagnosticSourceArgs ?? this.currentActivity); - } - - private Activity? StartActivitySourceActivity() - { - return ActivityExtensions.ActivitySourceStartActivity( - this.activitySource, - this.activityName, - (int)this.kind, - startTime: this.startTime, - tags: this.tagCollection, - links: this.GetActivitySourceLinkCollection()); - } - - public void SetStartTime(DateTime startTime) - { - this.startTime = startTime; - this.currentActivity?.SetStartTime(startTime); - } - - public void MarkFailed(Exception exception) - { - this.diagnosticSource?.Write(this.activityName + ".Exception", exception); - } - - public void Dispose() - { - if (this.currentActivity == null) - { - return; - } - - if (this.currentActivity.Duration == TimeSpan.Zero) - this.currentActivity.SetEndTime(DateTime.UtcNow); - - this.diagnosticSource.Write(this.activityName + ".Stop", this.diagnosticSourceArgs); - - if (!this.currentActivity.TryDispose()) - { - this.currentActivity.Stop(); - } - } - } - } - -#pragma warning disable SA1507 // File can not contain multiple types - /// - /// Until we can reference the 5.0 of System.Diagnostics.DiagnosticSource - /// - internal static class ActivityExtensions - { - static ActivityExtensions() - { - ResetFeatureSwitch(); - } - - private static readonly Type? ActivitySourceType = Type.GetType("System.Diagnostics.ActivitySource, System.Diagnostics.DiagnosticSource"); - private static readonly Type? ActivityKindType = Type.GetType("System.Diagnostics.ActivityKind, System.Diagnostics.DiagnosticSource"); - private static readonly Type? ActivityTagsCollectionType = Type.GetType("System.Diagnostics.ActivityTagsCollection, System.Diagnostics.DiagnosticSource"); - private static readonly Type? ActivityLinkType = Type.GetType("System.Diagnostics.ActivityLink, System.Diagnostics.DiagnosticSource"); - private static readonly Type? ActivityContextType = Type.GetType("System.Diagnostics.ActivityContext, System.Diagnostics.DiagnosticSource"); - - private static readonly ParameterExpression ActivityParameter = Expression.Parameter(typeof(Activity)); - - private static bool SupportsActivitySourceSwitch; - - private static Action? SetIdFormatMethod; - private static Func? GetTraceStateStringMethod; - private static Func? GetIdFormatMethod; - private static Action? ActivityAddTagMethod; - private static Func>?, IList?, DateTimeOffset, Activity?>? ActivitySourceStartActivityMethod; - private static Func? ActivitySourceHasListenersMethod; - private static Func>?, object?>? CreateActivityLinkMethod; - private static Func>?>? CreateTagsCollectionMethod; - - public static void SetW3CFormat(this Activity activity) - { - if (SetIdFormatMethod == null) - { - var method = typeof(Activity).GetMethod("SetIdFormat"); - if (method == null) - { - SetIdFormatMethod = (_, _) => { }; - } - else - { - var idParameter = Expression.Parameter(typeof(int)); - var convertedId = Expression.Convert(idParameter, method.GetParameters()[0].ParameterType); - - SetIdFormatMethod = Expression.Lambda>( - Expression.Call(ActivityParameter, method, convertedId), - ActivityParameter, idParameter).Compile(); - } - } - - SetIdFormatMethod(activity, 2 /* ActivityIdFormat.W3C */); - } - - public static bool IsW3CFormat(this Activity activity) - { - if (GetIdFormatMethod == null) - { - var method = typeof(Activity).GetProperty("IdFormat")?.GetMethod; - if (method == null) - { - GetIdFormatMethod = _ => -1; - } - else - { - GetIdFormatMethod = Expression.Lambda>( - Expression.Convert(Expression.Call(ActivityParameter, method), typeof(int)), - ActivityParameter).Compile(); - } - } - - - int result = GetIdFormatMethod(activity); - - return result == 2 /* ActivityIdFormat.W3C */; - } - - public static string? GetTraceState(this Activity activity) - { - if (GetTraceStateStringMethod == null) - { - var method = typeof(Activity).GetProperty("TraceStateString")?.GetMethod; - if (method == null) - { - GetTraceStateStringMethod = _ => null; - } - else - { - GetTraceStateStringMethod = Expression.Lambda>( - Expression.Call(ActivityParameter, method), - ActivityParameter).Compile(); - } - } - - return GetTraceStateStringMethod(activity); - } - - public static void AddObjectTag(this Activity activity, string name, object value) - { - if (ActivityAddTagMethod == null) - { - var method = typeof(Activity).GetMethod("AddTag", BindingFlags.Instance | BindingFlags.Public, null, new Type[] - { - typeof(string), - typeof(object) - }, null); - - if (method == null) - { - ActivityAddTagMethod = (_, _, _) => { }; - } - else - { - var nameParameter = Expression.Parameter(typeof(string)); - var valueParameter = Expression.Parameter(typeof(object)); - - ActivityAddTagMethod = Expression.Lambda>( - Expression.Call(ActivityParameter, method, nameParameter, valueParameter), - ActivityParameter, nameParameter, valueParameter).Compile(); - } - } - - ActivityAddTagMethod(activity, name, value); - } - - public static bool SupportsActivitySource() - { - return SupportsActivitySourceSwitch && ActivitySourceType != null; - } - - public static ICollection>? CreateTagsCollection() - { - if (CreateTagsCollectionMethod == null) - { - var ctor = ActivityTagsCollectionType?.GetConstructor(Array.Empty()); - if (ctor == null) - { - CreateTagsCollectionMethod = () => null; - } - else - { - CreateTagsCollectionMethod = Expression.Lambda>?>>( - Expression.New(ctor)).Compile(); - } - } - - return CreateTagsCollectionMethod(); - } - - public static object? CreateActivityLink(string traceparent, string? tracestate, ICollection>? tags) - { - if (ActivityLinkType == null) - { - return null; - } - - if (CreateActivityLinkMethod == null) - { - var parseMethod = ActivityContextType?.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public); - var ctor = ActivityLinkType?.GetConstructor(new[] { ActivityContextType!, ActivityTagsCollectionType! }); - - if (parseMethod == null || - ctor == null || - ActivityTagsCollectionType == null || - ActivityContextType == null) - { - CreateActivityLinkMethod = (_, _, _) => null; - } - else - { - var traceparentParameter = Expression.Parameter(typeof(string)); - var tracestateParameter = Expression.Parameter(typeof(string)); - var tagsParameter = Expression.Parameter(typeof(ICollection>)); - - CreateActivityLinkMethod = Expression.Lambda>?, object?>>( - Expression.TryCatch( - Expression.Convert(Expression.New(ctor, - Expression.Call(parseMethod, traceparentParameter, tracestateParameter), - Expression.Convert(tagsParameter, ActivityTagsCollectionType)), typeof(object)), - Expression.Catch(typeof(Exception), Expression.Default(typeof(object)))), - traceparentParameter, tracestateParameter, tagsParameter).Compile(); - } - } - - return CreateActivityLinkMethod(traceparent, tracestate, tags); - } - - public static bool ActivitySourceHasListeners(object? activitySource) - { - if (!SupportsActivitySource()) - { - return false; - } - - if (activitySource == null) - { - return false; - } - - if (ActivitySourceHasListenersMethod == null) - { - var method = ActivitySourceType?.GetMethod("HasListeners", BindingFlags.Instance | BindingFlags.Public); - if (method == null || - ActivitySourceType == null) - { - ActivitySourceHasListenersMethod = _ => false; - } - else - { - var sourceParameter = Expression.Parameter(typeof(object)); - ActivitySourceHasListenersMethod = Expression.Lambda>( - Expression.Call(Expression.Convert(sourceParameter, ActivitySourceType), method), - sourceParameter).Compile(); - } - } - - return ActivitySourceHasListenersMethod.Invoke(activitySource); - } - - public static Activity? ActivitySourceStartActivity(object? activitySource, string activityName, int kind, DateTimeOffset startTime, ICollection>? tags, IList? links) - { - if (activitySource == null) - { - return null; - } - - if (ActivitySourceStartActivityMethod == null) - { - if (ActivityLinkType == null || - ActivitySourceType == null || - ActivityContextType == null || - ActivityKindType == null) - { - ActivitySourceStartActivityMethod = (_, _, _, _, _, _) => null; - } - else - { - var method = ActivitySourceType?.GetMethod("StartActivity", BindingFlags.Instance | BindingFlags.Public, null, new[] - { - typeof(string), - ActivityKindType, - ActivityContextType, - typeof(IEnumerable>), - typeof(IEnumerable<>).MakeGenericType(ActivityLinkType), - typeof(DateTimeOffset) - }, null); - - if (method == null) - { - ActivitySourceStartActivityMethod = (_, _, _, _, _, _) => null; - } - else - { - var sourceParameter = Expression.Parameter(typeof(object)); - var nameParameter = Expression.Parameter(typeof(string)); - var kindParameter = Expression.Parameter(typeof(int)); - var startTimeParameter = Expression.Parameter(typeof(DateTimeOffset)); - var tagsParameter = Expression.Parameter(typeof(ICollection>)); - var linksParameter = Expression.Parameter(typeof(IList)); - var methodParameter = method.GetParameters(); - ActivitySourceStartActivityMethod = Expression.Lambda>?, IList?, DateTimeOffset, Activity?>>( - Expression.Call( - Expression.Convert(sourceParameter, method.DeclaringType!), - method, - nameParameter, - Expression.Convert(kindParameter, methodParameter[1].ParameterType), - Expression.Default(ActivityContextType), - Expression.Convert(tagsParameter, methodParameter[3].ParameterType), - Expression.Convert(linksParameter, methodParameter[4].ParameterType), - Expression.Convert(startTimeParameter, methodParameter[5].ParameterType)), - sourceParameter, nameParameter, kindParameter, tagsParameter, linksParameter, startTimeParameter).Compile(); - } - } - } - - return ActivitySourceStartActivityMethod.Invoke(activitySource, activityName, kind, tags, links, startTime); - } - - public static object? CreateActivitySource(string name) - { - if (ActivitySourceType == null) - { - return null; - } - return Activator.CreateInstance(ActivitySourceType, - name, // name - null); // version - } - - public static IList? CreateLinkCollection() - { - if (ActivityLinkType == null) - { - return null; - } - return Activator.CreateInstance(typeof(List<>).MakeGenericType(ActivityLinkType)) as IList; - } - - public static bool TryDispose(this Activity activity) - { - if (activity is IDisposable disposable) - { - disposable.Dispose(); - return true; - } - - return false; - } - - public static void ResetFeatureSwitch() - { - SupportsActivitySourceSwitch = AppContextSwitchHelper.GetConfigValue( - "Azure.Experimental.EnableActivitySource", - "AZURE_EXPERIMENTAL_ENABLE_ACTIVITY_SOURCE"); - } - } -} diff --git a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScopeFactory.cs b/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScopeFactory.cs deleted file mode 100644 index 2cddf70d21..0000000000 --- a/Microsoft.Azure.Cosmos/src/OSS/Azure.Core/DiagnosticScopeFactory.cs +++ /dev/null @@ -1,61 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// This File is copied from Azure.Core repo. i.e. https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/DiagnosticScopeFactory.cs - -#nullable enable - -namespace Azure.Core.Pipeline -{ - using System.Collections.Generic; - using System.Diagnostics; - using System.Threading; - -#pragma warning disable CA1001 // Types that own disposable fields should be disposable - internal class DiagnosticScopeFactory -#pragma warning restore CA1001 // Types that own disposable fields should be disposable - { - private static Dictionary? listeners; - private readonly string? resourceProviderNamespace; - private readonly DiagnosticListener? source; - - public DiagnosticScopeFactory(string clientNamespace, string? resourceProviderNamespace, bool isActivityEnabled) - { - this.resourceProviderNamespace = resourceProviderNamespace; - this.IsActivityEnabled = isActivityEnabled; - if (this.IsActivityEnabled) - { -#pragma warning disable CS8601 // Possible null reference assignment. - var listeners = LazyInitializer.EnsureInitialized>(ref DiagnosticScopeFactory.listeners); -#pragma warning restore CS8601 // Possible null reference assignment. - - lock (listeners!) - { - if (!listeners.TryGetValue(clientNamespace, out this.source)) - { - this.source = new DiagnosticListener(clientNamespace); - listeners[clientNamespace] = this.source; - } - } - } - } - - public bool IsActivityEnabled { get; } - - public DiagnosticScope CreateScope(string name, DiagnosticScope.ActivityKind kind = DiagnosticScope.ActivityKind.Client) - { - if (this.source == null) - { - return default; - } - var scope = new DiagnosticScope(this.source.Name, name, this.source, kind); - - if (this.resourceProviderNamespace != null) - { - scope.AddAttribute("az.namespace", this.resourceProviderNamespace); - } - return scope; - } - } -} diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index a9c475615a..d16d1c8bcc 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -83,7 +83,8 @@ internal static CosmosClientContext Create( handler: httpMessageHandler, sessionContainer: clientOptions.SessionContainer, cosmosClientId: cosmosClient.Id, - remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback)); + remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback), + isDistributedTracingEnabled: clientOptions.IsDistributedTracingEnabled); return ClientContextCore.Create( cosmosClient, diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs index 12db379f0c..9d0856507e 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos using System; using System.Net; using System.Text; - using global::Azure.Core.Pipeline; + using global::Azure.Core; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs index 4e7aa73f54..cbee4c59ec 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosNullReferenceException.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Collections; - using global::Azure.Core.Pipeline; + using global::Azure.Core; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosObjectDisposedException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosObjectDisposedException.cs index 64d5018f60..c6f097355d 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosObjectDisposedException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosObjectDisposedException.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos using System; using System.Collections; using System.Globalization; - using global::Azure.Core.Pipeline; + using global::Azure.Core; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs index e21843656a..010d968bd0 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosOperationCanceledException.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos using System; using System.Collections; using System.Runtime.Serialization; - using global::Azure.Core.Pipeline; + using global::Azure.Core; using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 51aa1ee794..c199c0727c 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; using System.Collections.Generic; - using global::Azure.Core.Pipeline; + using global::Azure.Core; /// /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 6c88b3d5db..51b4666b6f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -5,7 +5,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; - using global::Azure.Core.Pipeline; + using global::Azure.Core; /// /// This class is used to generate Activities with Azure.Cosmos.Operation Source Name @@ -28,7 +28,8 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, { OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true); + isActivityEnabled: true, + suppressNestedClientActivities: true); // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = OpenTelemetryRecorderFactory diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index ad1a3f1288..90f32b89c9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -129,7 +129,7 @@ } ] }]]> - Operation.ExecuteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ExecuteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 09d8c3ce63..b776a8eaae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -153,16 +153,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -311,16 +311,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -469,16 +469,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -627,16 +627,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -785,16 +785,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -943,16 +943,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1101,16 +1101,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1259,16 +1259,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1417,16 +1417,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1575,16 +1575,16 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2324,7 +2324,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 2e20bceb1c..4189b4bab8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -952,11 +952,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1569,11 +1569,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2167,11 +2167,11 @@ } ] }]]> - Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2785,11 +2785,11 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3066,9 +3066,7 @@ } ] }]]> - Operation.Change Feed Estimator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. + Operation.Change Feed Estimator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 348925a1f6..591a6af4ac 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -107,8 +107,8 @@ } ] }]]> - Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.DeleteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -207,8 +207,8 @@ } ] }]]> - Operation.DeleteAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted + Operation.DeleteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted +Operation.CreateDatabaseAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index a8b686d679..64e7e0c3ed 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -148,7 +148,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -390,7 +390,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -615,7 +615,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -872,7 +872,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1193,7 +1193,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1347,7 +1347,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 18aa6d67d8..d2abebc194 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -574,10 +574,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1180,10 +1180,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1767,10 +1767,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2374,10 +2374,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3048,10 +3048,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -3644,10 +3644,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -4260,10 +4260,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 1ceef081c6..dc6df3eacf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -536,10 +536,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1104,10 +1104,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1653,10 +1653,10 @@ } ] }]]> - Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -2222,10 +2222,10 @@ } ] }]]> - Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US +Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index a7cc47631a..29b36304ec 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -542,7 +542,7 @@ } ] }]]> - Operation.ReadManyItemsStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadManyItemsStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -1102,7 +1102,7 @@ } ] }]]> - Operation.ReadManyItemsAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadManyItemsAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index f0dec5b7bd..18f11acd62 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -89,7 +89,7 @@ } ] }]]> - Operation.CreateItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.CreateItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -178,7 +178,7 @@ } ] }]]> - Operation.ReadItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -275,7 +275,7 @@ } ] }]]> - Operation.ReplaceItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReplaceItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -367,7 +367,7 @@ } ] }]]> - Operation.DeleteItemStreamAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.DeleteItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 6b57caad95..abeaa41de8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -109,7 +109,7 @@ } ] }]]> - Operation.CreateItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -203,7 +203,7 @@ } ] }]]> - Operation.ReadItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReadItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -310,7 +310,7 @@ } ] }]]> - Operation.ReplaceItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.ReplaceItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. @@ -406,7 +406,7 @@ } ] }]]> - Operation.DeleteItemAsynckindclientaz.namespaceMicrosoft.DocumentDBdb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US + Operation.DeleteItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index c46d8b035a..f4983c10a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -32,6 +32,7 @@ public static void IsValid(Activity activity) IList expectedTags = new List { "az.namespace", + "az.schema_url", "kind", "db.system", "db.name", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 1f192bb086..5f98a6191a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -33,15 +33,27 @@ internal class CustomListener : public static ConcurrentBag CollectedActivities { private set; get; } = new(); private static ConcurrentBag CollectedEvents { set; get; } = new(); + private string SourceType { set; get; } + + // Regex is used to match string 'n' against diagnosticNameSpace string + // which is constructed by combining first two parts of name. + // Eg: Azure.Cosmos.Operation where diagnosticNameSpace is Azure.Cosmos and Operation is the sourceType public CustomListener(string name, string eventName) - : this(n => Regex.Match(n, name).Success, eventName) + : this(n => + { + string[] nameParts = name.Split("."); + string diagnosticNameSpace = $"{nameParts[0]}.{nameParts[1]}"; + return Regex.Match(n, diagnosticNameSpace).Success; + }, name.Split(".")[2], eventName) + { } - public CustomListener(Func filter, string eventName) + public CustomListener(Func filter, string sourceType, string eventName) { this.sourceNameFilter = filter; this.eventName = eventName; + this.SourceType = sourceType; DiagnosticListener.AllListeners.Subscribe(this); } @@ -76,6 +88,11 @@ public void OnNext(KeyValuePair value) string stopSuffix = ".Stop"; string exceptionSuffix = ".Exception"; + if(!this.SourceType.Contains("*") && !Activity.Current.OperationName.Contains(this.SourceType)) + { + return; + } + if (value.Key.EndsWith(startSuffix)) { string name = value.Key[..^startSuffix.Length]; @@ -89,7 +106,6 @@ public void OnNext(KeyValuePair value) Links = links.Select(a => new ProducedLink(a.ParentId, a.TraceStateString)).ToList(), LinkedActivities = links.ToList() }; - this.Scopes.Add(scope); } else if (value.Key.EndsWith(stopSuffix)) @@ -100,7 +116,6 @@ public void OnNext(KeyValuePair value) if (producedDiagnosticScope.Activity.Id == Activity.Current.Id) { AssertActivity.IsValid(producedDiagnosticScope.Activity); - CustomListener.CollectedActivities.Add(producedDiagnosticScope.Activity); producedDiagnosticScope.IsCompleted = true; @@ -120,7 +135,6 @@ public void OnNext(KeyValuePair value) { throw new InvalidOperationException("Scope should not be stopped when calling Failed"); } - producedDiagnosticScope.Exception = (Exception)value.Value; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index e14188d92a..ba7e828edf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -24,7 +24,6 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; - using AzureCore = global::Azure.Core.Pipeline; [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 96254aca79..59172beb33 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -22,7 +22,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; using OpenTelemetry; using OpenTelemetry.Trace; - using AzureCore = global::Azure.Core.Pipeline; + using AzureCore = global::Azure.Core; internal enum DocumentClientType { @@ -548,11 +548,11 @@ internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() // Open Telemetry Listener Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() // use any exporter here - .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") // Right now, it will capture only "Azure.Cosmos.Operation" + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") // Right now, it will capture only "Azure.Cosmos.Operation" .Build(); // Custom Listener - Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", "Azure-Cosmos-Operation-Request-Diagnostics"); return Util.TestListener; From f94869a83016dac97adb315d3ec23bca874e60bc Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 18 Apr 2023 11:29:19 -0700 Subject: [PATCH 095/337] [Internal] MerlinBot: Adds auto-merge and cleanup automation (#3813) * Add config changes * Polishing automerge config --- .github/fabricbot.json | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/.github/fabricbot.json b/.github/fabricbot.json index 90924da0c3..67aa59fa46 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -102,6 +102,81 @@ } ] } + }, + { + "taskType": "trigger", + "capabilityId": "AutoMerge", + "subCapability": "AutoMerge", + "version": "1.0", + "config": { + "taskName": "PR Automerge", + "allowAutoMergeInstructionsWithoutLabel": false, + "mergeType": "squash", + "deleteBranches": true, + "removeLabelOnPush": true, + "label": "auto-merge", + "requireAllStatuses": false, + "requireSpecificCheckRuns": false, + "usePrDescriptionAsCommitMessage": false, + "minMinutesOpen": "60", + "enforceDMPAsStatus": true + } + }, + { + "taskType": "scheduled", + "capabilityId": "ScheduledSearch", + "subCapability": "ScheduledSearch", + "version": "1.1", + "config": { + "frequency": [ + { + "weekDay": 1, + "hours": [ + 9 + ], + "timezoneOffset": -7 + } + ], + "searchTerms": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "name": "isIssue", + "parameters": {} + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs-more-information" + } + }, + { + "name": "noActivitySince", + "parameters": { + "days": 14 + } + }, + { + "name": "noAssignees", + "parameters": {} + } + ], + "taskName": "Close inactive needs-information", + "actions": [ + { + "name": "addReply", + "parameters": { + "comment": "${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue." + } + }, + { + "name": "closeIssue", + "parameters": {} + } + ] + } } ], "userGroups": [] From afd5904eef28e9d9c3d8d2615192b3a43a4ee5da Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 24 Apr 2023 13:54:19 -0700 Subject: [PATCH 096/337] Update fabricbot.json (#3824) --- .github/fabricbot.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/fabricbot.json b/.github/fabricbot.json index 67aa59fa46..e400139553 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -168,7 +168,7 @@ { "name": "addReply", "parameters": { - "comment": "${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue." + "comment": "@${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue." } }, { @@ -180,4 +180,4 @@ } ], "userGroups": [] -} \ No newline at end of file +} From fb80ba8eb2a219fb6c8ce14b601d4153d0f71457 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Tue, 25 Apr 2023 04:42:16 +0530 Subject: [PATCH 097/337] [Internal] Upgrade Resiliency: Adds Logic to Validate `Unknown` Replicas along with `Unhealthy`. (#3820) * Code changes to add aggressive validation logic. * Code changes to enable aggressive validation for all regions. * Code changes to pull in msdata cosmos.direct changes related to aggresive validation logic. * Code changes to make minor cosmetic changes. * Code changes to address review comments. --- Directory.Build.props | 2 +- .../src/Routing/GatewayAddressCache.cs | 37 +++- .../GatewayAddressCacheTests.cs | 200 ++++++++++-------- 3 files changed, 134 insertions(+), 105 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 40b25a6e73..695ad7c92c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.32.3 3.32.3 preview - 3.30.6 + 3.30.8 2.0.1 2.0.1 preview diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index eba425fb0d..d99be609ea 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -549,7 +549,7 @@ await this.GetServerAddressesViaGatewayAsync(request, collectionRid, new[] { par } } - this.ValidateUnhealthyPendingReplicas(transportAddressUris); + this.ValidateReplicaAddresses(transportAddressUris); return mergedAddresses; } @@ -840,12 +840,12 @@ await this.GetServerAddressesViaGatewayAsync( } /// - /// Validates the unhealthy pending replicas by attempting to open the Rntbd connection. This operation - /// will eventually marks the unhealthy pending replicas to healthy, if the rntbd connection attempt made was + /// Validates the unknown or unhealthy-pending replicas by attempting to open the Rntbd connection. This operation + /// will eventually marks the unknown or unhealthy-pending replicas to healthy, if the rntbd connection attempt made was /// successful or unhealthy otherwise. /// /// A read-only list of needs to be validated. - private void ValidateUnhealthyPendingReplicas( + private void ValidateReplicaAddresses( IReadOnlyList addresses) { if (addresses == null) @@ -853,15 +853,13 @@ private void ValidateUnhealthyPendingReplicas( throw new ArgumentNullException(nameof(addresses)); } - IEnumerable addressesNeedToValidation = addresses - .Where(address => address - .GetCurrentHealthState() - .GetHealthStatus() == TransportAddressHealthState.HealthStatus.UnhealthyPending); + IEnumerable addressesNeedToValidateStatus = this.GetAddressesNeededToValidateStatus( + transportAddresses: addresses); - if (addressesNeedToValidation.Any()) + if (addressesNeedToValidateStatus.Any()) { Task openConnectionsInBackgroundTask = Task.Run(async () => await this.openConnectionsHandler.TryOpenRntbdChannelsAsync( - addresses: addressesNeedToValidation.ToList())); + addresses: addressesNeedToValidateStatus)); } } @@ -919,6 +917,25 @@ private static PartitionAddressInformation MergeAddresses( return newAddresses; } + /// + /// Returns a list of needed to validate their health status. Validating + /// a uri is done by opening Rntbd connection to the backend replica, which is a costly operation by nature. Therefore + /// vaidating both Unhealthy and Unknown replicas at the same time could impose a high CPU utilization. To avoid this + /// situation, the RntbdOpenConnectionHandler has good concurrency control mechanism to open the connections gracefully/>. + /// + /// A read only list of s. + /// A list of that needs to validate their status. + private IEnumerable GetAddressesNeededToValidateStatus( + IReadOnlyList transportAddresses) + { + return transportAddresses + .Where(address => address + .GetCurrentHealthState() + .GetHealthStatus() is + TransportAddressHealthState.HealthStatus.Unknown or + TransportAddressHealthState.HealthStatus.UnhealthyPending); + } + protected virtual void Dispose(bool disposing) { if (this.disposedValue) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 809814aef1..2d0d0a5c6a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -379,10 +379,10 @@ await cache.OpenConnectionsAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 3, - expectedSuccessCount: 3); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 3, + expectedTotalSuccessAddressesToOpenCount: 3); } /// @@ -425,10 +425,10 @@ await cache.OpenConnectionsAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 3, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 3, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 3, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 3, + expectedTotalSuccessAddressesToOpenCount: 0); } /// @@ -474,10 +474,10 @@ await cache.OpenConnectionsAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 0, - expectedReceivedAddressesCount: 0, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); } /// @@ -552,10 +552,10 @@ await globalAddressResolver.OpenConnectionsToAllReplicasAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 3, - expectedSuccessCount: 3); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 3, + expectedTotalSuccessAddressesToOpenCount: 3); } /// @@ -630,10 +630,10 @@ await globalAddressResolver.OpenConnectionsToAllReplicasAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 2, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 3, - expectedSuccessCount: 1); + expectedTotalFailedAddressesToOpenCount: 2, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 3, + expectedTotalSuccessAddressesToOpenCount: 1); } /// @@ -721,10 +721,10 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenIn Assert.AreEqual(exceptionMessage, ex.Message); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 0, - expectedReceivedAddressesCount: 0, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); } /// @@ -797,10 +797,10 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenNu Assert.IsTrue(ce.Message.Contains("Could not resolve the collection")); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 0, - expectedReceivedAddressesCount: 0, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); } /// @@ -879,10 +879,10 @@ await cache.OpenConnectionsAsync( // Assert. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: addresses.Count, - expectedSuccessCount: addresses.Count); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: addresses.Count, + expectedTotalSuccessAddressesToOpenCount: addresses.Count); } /// @@ -960,9 +960,15 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat .ReplicaTransportAddressUris .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: true); + + // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Unknown, + expected: TransportAddressHealthState.HealthStatus.Connected, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); Assert.AreEqual(4, addressInfo.AllAddresses.Count); @@ -1004,10 +1010,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat mockHttpHandler.VerifyAll(); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 1, - expectedSuccessCount: 1); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 6, + expectedTotalSuccessAddressesToOpenCount: 6); } /// @@ -1053,7 +1059,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( failIndexesByAttempts: new Dictionary>() { - { 0, new HashSet() { 0 } } + { 0, new HashSet() { 1 } } }, manualResetEvent: manualResetEvent); @@ -1095,9 +1101,22 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr .ReplicaTransportAddressUris .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: true); + + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 4, + expectedTotalSuccessAddressesToOpenCount: 4); + + // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Unknown, + expected: TransportAddressHealthState.HealthStatus.Connected, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); Assert.AreEqual(4, addressInfo.AllAddresses.Count); @@ -1140,10 +1159,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 1, - expectedMethodInvocationCount: 1, - expectedReceivedAddressesCount: 1, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 1, + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 6, + expectedTotalSuccessAddressesToOpenCount: 5); // A delay of 2 minute was added to make the replica unhealthy for more than one minute. This // will make sure the unhealthy replica gets a chance to re-validate it's health status. @@ -1167,10 +1186,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr Assert.AreEqual(4, addressInfo.AllAddresses.Count); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 1, - expectedMethodInvocationCount: 2, - expectedReceivedAddressesCount: 1, - expectedSuccessCount: 1); + expectedTotalFailedAddressesToOpenCount: 1, + expectedTotalHandlerInvocationCount: 3, + expectedTotalReceivedAddressesCount: 7, + expectedTotalSuccessAddressesToOpenCount: 6); addressInfo = await cache.TryGetAddressesAsync( request: request, @@ -1194,13 +1213,13 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); // This assertion makes sure that no additional calls were made to the open connection handler after - // since the last address refresh, because all the replicas are now either Unknown or Connected. + // since the last address refresh, because all the replicas at this point should be Connected. GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 1, - expectedMethodInvocationCount: 2, - expectedReceivedAddressesCount: 1, - expectedSuccessCount: 1); + expectedTotalFailedAddressesToOpenCount: 1, + expectedTotalHandlerInvocationCount: 3, + expectedTotalReceivedAddressesCount: 7, + expectedTotalSuccessAddressesToOpenCount: 6); } /// @@ -1290,10 +1309,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationDisabled_ShouldNotVal mockHttpHandler.VerifyAll(); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, - expectedExceptionCount: 0, - expectedMethodInvocationCount: 0, - expectedReceivedAddressesCount: 0, - expectedSuccessCount: 0); + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); } /// @@ -1320,21 +1339,21 @@ private static void WaitForManualResetEventSignal( /// to match with that of the expected ones. /// /// An instance of the . - /// The expected exception count for the test. - /// The expected method invocation count for the test. - /// The expected received addresses count for the test. - /// The expected successful messages count for the test. + /// The expected total addresses count that are supposed to fail while opening connection for the scenario. + /// The expected total open connection handler method invocation count for the scenario. + /// The expected total received addresses count for the scenario. + /// The expected total addresses count that are supposed to succeed while opening connection for the scenario. private static void AssertOpenConnectionHandlerAttributes( FakeOpenConnectionHandler fakeOpenConnectionHandler, - int expectedExceptionCount, - int expectedMethodInvocationCount, - int expectedReceivedAddressesCount, - int expectedSuccessCount) + int expectedTotalFailedAddressesToOpenCount, + int expectedTotalHandlerInvocationCount, + int expectedTotalReceivedAddressesCount, + int expectedTotalSuccessAddressesToOpenCount) { - Assert.AreEqual(expectedExceptionCount, fakeOpenConnectionHandler.GetExceptionCount()); - Assert.AreEqual(expectedMethodInvocationCount, fakeOpenConnectionHandler.GetMethodInvocationCount()); - Assert.AreEqual(expectedReceivedAddressesCount, fakeOpenConnectionHandler.GetReceivedAddressesCount()); - Assert.AreEqual(expectedSuccessCount, fakeOpenConnectionHandler.GetSuccessfulInvocationCount()); + Assert.AreEqual(expectedTotalFailedAddressesToOpenCount, fakeOpenConnectionHandler.GetTotalExceptionCount()); + Assert.AreEqual(expectedTotalHandlerInvocationCount, fakeOpenConnectionHandler.GetTotalMethodInvocationCount()); + Assert.AreEqual(expectedTotalReceivedAddressesCount, fakeOpenConnectionHandler.GetTotalReceivedAddressesCount()); + Assert.AreEqual(expectedTotalSuccessAddressesToOpenCount, fakeOpenConnectionHandler.GetTotalSuccessfulInvocationCount()); } private class FakeMessageHandler : HttpMessageHandler @@ -1451,22 +1470,22 @@ public FakeOpenConnectionHandler( this.manualResetEvent = manualResetEvent; } - public int GetSuccessfulInvocationCount() + public int GetTotalSuccessfulInvocationCount() { return this.successInvocationCounter; } - public int GetExceptionCount() + public int GetTotalExceptionCount() { return this.exceptionCounter; } - public int GetReceivedAddressesCount() + public int GetTotalReceivedAddressesCount() { return this.totalReceivedAddressesCounter; } - public int GetMethodInvocationCount() + public int GetTotalMethodInvocationCount() { return this.methodInvocationCounter; } @@ -1474,39 +1493,34 @@ public int GetMethodInvocationCount() Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( IEnumerable addresses) { - this.totalReceivedAddressesCounter = addresses.Count(); - for (int i = 0; i < addresses.Count(); i++) + int idx = 0; + this.totalReceivedAddressesCounter += addresses.Count(); + foreach (TransportAddressUri transportAddress in addresses) { if (this.useAttemptBasedFailingIndexs) { - if (this.failIndexesByAttempts.ContainsKey(i) && this.failIndexesByAttempts[i].Contains(this.methodInvocationCounter)) + if (this.failIndexesByAttempts.ContainsKey(idx) && this.failIndexesByAttempts[idx].Contains(this.methodInvocationCounter)) { - this.ExecuteFailureCondition( - addresses: addresses.ToList(), - index: i); + this.ExecuteFailureCondition(transportAddress); } else { - this.ExecuteSuccessCondition( - addresses: addresses.ToList(), - index: i); + this.ExecuteSuccessCondition(transportAddress); } } else { - if (this.failingIndexes.Contains(i)) + if (this.failingIndexes.Contains(idx)) { - this.ExecuteFailureCondition( - addresses: addresses.ToList(), - index: i); + this.ExecuteFailureCondition(transportAddress); } else { - this.ExecuteSuccessCondition( - addresses: addresses.ToList(), - index: i); + this.ExecuteSuccessCondition(transportAddress); } } + + idx++; } this.methodInvocationCounter++; @@ -1515,18 +1529,16 @@ Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( } private void ExecuteSuccessCondition( - IReadOnlyList addresses, - int index) + TransportAddressUri address) { - addresses[index].SetConnected(); + address.SetConnected(); this.successInvocationCounter++; } private void ExecuteFailureCondition( - IReadOnlyList addresses, - int index) + TransportAddressUri address) { - addresses[index].SetUnhealthy(); + address.SetUnhealthy(); this.exceptionCounter++; } } From 5d4f7c152edcc5671ca5da71818eeb73c84f6ca3 Mon Sep 17 00:00:00 2001 From: Baltima <130716409+Baltima@users.noreply.github.com> Date: Tue, 25 Apr 2023 21:19:33 +0300 Subject: [PATCH 098/337] Serialization: Fixes call to CosmosSerializer.FromStream on Gateway mode when EnableContentResponseOnWrite is false (#3814) * Do not call serializer if ResponseMessage.Content is empty. * Add unit test * Update unit tests * Remove unused usings --------- Co-authored-by: Matias Quaranta --- .../src/Resource/CosmosResponseFactoryCore.cs | 6 ++ ...ts.cs => CosmosJsonSerializerUnitTests.cs} | 90 ++++++++++++------- 2 files changed, 66 insertions(+), 30 deletions(-) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/{CosmosJsonSeriliazerUnitTests.cs => CosmosJsonSerializerUnitTests.cs} (84%) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosResponseFactoryCore.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosResponseFactoryCore.cs index 7d9e609ba3..14d405ffc6 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosResponseFactoryCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosResponseFactoryCore.cs @@ -276,6 +276,12 @@ public T ToObjectpublic(ResponseMessage responseMessage) return default; } + if (responseMessage.Content.Length == 0) + { + responseMessage.Content.Dispose(); + return default; + } + return this.serializerCore.FromStream(responseMessage.Content); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSeriliazerUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs similarity index 84% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSeriliazerUnitTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs index 3ff401269b..8b318ad09e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSeriliazerUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.Core.Tests using System; using System.Collections.Generic; using System.IO; - using System.Linq; using System.Net; using System.Text; using Microsoft.Azure.Cosmos.CosmosElements; @@ -19,15 +18,15 @@ namespace Microsoft.Azure.Cosmos.Core.Tests using Newtonsoft.Json; [TestClass] - public class CosmosJsonSeriliazerUnitTests + public class CosmosJsonSerializerUnitTests { private readonly ToDoActivity toDoActivity = new ToDoActivity() { - id = "c1d433c1-369d-430e-91e5-14e3ce588f71", - taskNum = 42, - cost = double.MaxValue, - description = "cosmos json serializer", - status = "TBD" + Id = "c1d433c1-369d-430e-91e5-14e3ce588f71", + TaskNum = 42, + Cost = double.MaxValue, + Description = "cosmos json serializer", + Status = "TBD" }; private readonly string toDoActivityJson = @"{""id"":""c1d433c1-369d-430e-91e5-14e3ce588f71"",""taskNum"":42,""cost"":1.7976931348623157E+308,""description"":""cosmos json serializer"",""status"":""TBD""}"; @@ -41,11 +40,11 @@ public void ValidateSerializer() Assert.IsNotNull(stream); ToDoActivity result = cosmosDefaultJsonSerializer.FromStream(stream); Assert.IsNotNull(result); - Assert.AreEqual(this.toDoActivity.id, result.id); - Assert.AreEqual(this.toDoActivity.taskNum, result.taskNum); - Assert.AreEqual(this.toDoActivity.cost, result.cost); - Assert.AreEqual(this.toDoActivity.description, result.description); - Assert.AreEqual(this.toDoActivity.status, result.status); + Assert.AreEqual(this.toDoActivity.Id, result.Id); + Assert.AreEqual(this.toDoActivity.TaskNum, result.TaskNum); + Assert.AreEqual(this.toDoActivity.Cost, result.Cost); + Assert.AreEqual(this.toDoActivity.Description, result.Description); + Assert.AreEqual(this.toDoActivity.Status, result.Status); } } @@ -143,11 +142,11 @@ public void ValidateCustomSerializerSettings() ToDoActivity toDoActivityNoDescription = new ToDoActivity() { - id = "c1d433c1-369d-430e-91e5-14e3ce588f71", - taskNum = 42, - cost = double.MaxValue, - description = null, - status = "TBD" + Id = "c1d433c1-369d-430e-91e5-14e3ce588f71", + TaskNum = 42, + Cost = double.MaxValue, + Description = null, + Status = "TBD" }; string toDoActivityJson = @"{""id"":""c1d433c1-369d-430e-91e5-14e3ce588f71"",""taskNum"":42,""cost"":1.7976931348623157E+308,""status"":""TBD""}"; @@ -175,19 +174,15 @@ public void ValidateResponseFactoryJsonSerializer() ResponseMessage udfResponse = this.CreateResponse(); ResponseMessage itemResponse = this.CreateResponse(); - Mock mockUserJsonSerializer = new Mock(); CosmosSerializerCore serializerCore = new CosmosSerializerCore(mockUserJsonSerializer.Object); - CosmosResponseFactoryInternal cosmosResponseFactory = new CosmosResponseFactoryCore( - serializerCore); - - // Test the user specified response - mockUserJsonSerializer.Setup(x => x.FromStream(itemResponse.Content)).Callback(input => input.Dispose()).Returns(new ToDoActivity()); - mockUserJsonSerializer.Setup(x => x.FromStream(storedProcedureExecuteResponse.Content)).Callback(input => input.Dispose()).Returns(new ToDoActivity()); + CosmosResponseFactoryInternal cosmosResponseFactory = new CosmosResponseFactoryCore(serializerCore); // Verify all the user types use the user specified version ItemResponse itemResponseFromFactory = cosmosResponseFactory.CreateItemResponse(itemResponse); Assert.IsNotNull(itemResponseFromFactory.Diagnostics); + // Verify that FromStream is not called as the stream is empty + mockUserJsonSerializer.Verify(x => x.FromStream(itemResponse.Content), Times.Never); cosmosResponseFactory.CreateStoredProcedureExecuteResponse(storedProcedureExecuteResponse); // Throw if the setups were not called @@ -253,6 +248,27 @@ public void ValidateResponseFactoryJsonSerializer() cosmosResponseFactory.CreateUserDefinedFunctionResponse(udfResponse); } + [TestMethod] + public void ValidateResponseFactoryJsonSerializerWithContent() + { + ResponseMessage itemResponse = this.CreateResponseWithContent(); + + Mock mockUserJsonSerializer = new Mock(); + CosmosSerializerCore serializerCore = new CosmosSerializerCore(mockUserJsonSerializer.Object); + CosmosResponseFactoryInternal cosmosResponseFactory = new CosmosResponseFactoryCore(serializerCore); + + mockUserJsonSerializer.Setup(x => x.FromStream(itemResponse.Content)).Callback(input => input.Dispose()).Returns(new ToDoActivity()); + + // Verify all the user types use the user specified version + ItemResponse itemResponseFromFactory = cosmosResponseFactory.CreateItemResponse(itemResponse); + Assert.IsNotNull(itemResponseFromFactory.Diagnostics); + Assert.IsNotNull(itemResponseFromFactory.Resource); + Assert.AreEqual(HttpStatusCode.OK, itemResponseFromFactory.StatusCode); + + // Throw if the setups were not called + mockUserJsonSerializer.VerifyAll(); + } + [TestMethod] public void ValidateSqlQuerySpecSerializer() { @@ -339,6 +355,15 @@ private ResponseMessage CreateResponse() return cosmosResponse; } + private ResponseMessage CreateResponseWithContent() + { + ResponseMessage cosmosResponse = new ResponseMessage(statusCode: HttpStatusCode.OK) + { + Content = new MemoryStream(Encoding.UTF8.GetBytes(this.toDoActivityJson)) + }; + return cosmosResponse; + } + private ResponseMessage CreateQueryResponse() { List cosmosElements = new List(); @@ -387,13 +412,18 @@ private string GetSerializedToDoActivity() return @"{""id"":""c1d433c1-369d-430e-91e5-14e3ce588f71"",""taskNum"":42,""cost"":1.7976931348623157E+308,""status"":""TBD""}"; } - public class ToDoActivity + private class ToDoActivity { - public string id { get; set; } - public int taskNum { get; set; } - public double cost { get; set; } - public string description { get; set; } - public string status { get; set; } + [JsonProperty("id")] + public string Id { get; set; } + [JsonProperty("taskNum")] + public int TaskNum { get; set; } + [JsonProperty("cost")] + public double Cost { get; set; } + [JsonProperty("description")] + public string Description { get; set; } + [JsonProperty("status")] + public string Status { get; set; } } } } From 0d0ffe07919094d4304443540653fb6aa7c1141b Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 26 Apr 2023 17:28:58 -0700 Subject: [PATCH 099/337] [Internal] Documentation: Adds documentation covering build pipelines (#3822) * Add doc * Move benchmark * Fixing texts --- docs/builds-and-pipelines.md | 73 +++++++++++++++++++++++++++++++++++ templates/build-benchmark.yml | 25 ++++++++++++ templates/build-preview.yml | 28 +------------- 3 files changed, 99 insertions(+), 27 deletions(-) create mode 100644 docs/builds-and-pipelines.md diff --git a/docs/builds-and-pipelines.md b/docs/builds-and-pipelines.md new file mode 100644 index 0000000000..0747982783 --- /dev/null +++ b/docs/builds-and-pipelines.md @@ -0,0 +1,73 @@ +# Build pipelines for the Azure Cosmos DB .NET SDK + +This repository contains 6 pipelines that are used on different scenarios. + +## PR Validation + +[azure-pipelines.yml](../azure-pipelines.yml) defines the checks that are performed during a PR validation, it covers: + +* [Static analysis](../templates/static-tools.yml) +* [Verifying if the state of the SDK package is valid / can we generate a Nuget package](../templates/nuget-pack.yml) +* [Verify if the CTL runner builds](../templates/build-ctl.yml) -> [CTL Runner source](../Microsoft.Azure.Cosmos.Samples/Tools/CTL). +* [Verify if the Samples build](../templates/build-samples.yml) -> [Samples folder source](../Microsoft.Azure.Cosmos.Samples/Usage). +* [Run the Unit and Emulator tests](../templates/build-test.yml) -> For more information about tests, see the [CONTRIBUTING guide](../CONTRIBUTING.md#tests). +* [Verify the project builds with INTERNAL flag](../templates/build-internal.yml) -> INTERNAL is used for service dogfooding and for friends assembly access. +* [Verify the project builds with the PREVIEW flag, Unit tests for PREVIEW pass, Encryption and Benchmark projects for PREVIEW build](../templates/build-preview.yml) -> PREVIEW is used to ship the `-preview` SDK package. +* [Verify the Benchmark project builds, including PREVIEW flag build](../templates/build-benchmark.yml) -> [Benchmark project](../Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md) enables users to execute benchmark runs on their accounts. + +This pipeline executes on Azure Pipelines as [dotnet-v3-ci](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=63). + +## SDK release + +[azure-pipelines-official.yml](../azure-pipelines-official.yml) is used during the release process of a new version: + +* [Static analysis](../templates/static-tools.yml) +* [Run the Unit and Emulator tests](../templates/build-test.yml) -> For more information about tests, see the [CONTRIBUTING guide](../CONTRIBUTING.md#tests). +* [Generate a Nuget package, and a Symbols package, and publish it on the `cosmosdb/csharp/` storage container](../templates/nuget-pack.yml) the Nuget version will be what is defined on [Directory.Build.Props](../Directory.Build.props). Template parameters: ReleasePackage = true, CleanupFolder = false, BlobVersion = `` + +This pipeline executes on Azure Pipelines as [dotnet-v3-release](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=65). + +## Nightly release + +[azure-pipelines-nightly.yml](../azure-pipelines-nightly.yml) is a scheduled run that executes every day at 0:00 UTC and produces two Nuget packages with the content on the `master` branch: + +* A non-preview package with versioning `Microsoft.Azure.Cosmos.X.Y.Z-nightly-DATE` where `X.Y.Z` is the current version from [Directory.Build.Props](../Directory.Build.props) and `DATE` is the current date in `MMDDYYYY` format. +* A preview package with versioning `Microsoft.Azure.Cosmos.X.Y.Z-preview-nightly-DATE` where `X.Y.Z` is the current version from [Directory.Build.Props](../Directory.Build.props) and `DATE` is the current date in `MMDDYYYY` format. + +The pipeline will: + +* [Generate a nightly Nuget package and publish it on the `cosmosdb/csharp/nightly` storage container and delete previous contents](../templates/nuget-pack.yml). Template parameters: ReleasePackage = true, CleanupFolder = true, BlobVersion = nightly. +* [Generate a preview nightly Nuget package and publish it on the `cosmosdb/csharp/nightly-preview` storage container and delete previous contents](../templates/nuget-pack.yml). Template parameters: ReleasePackage = true, CleanupFolder = true, BlobVersion = nightly-preview. + +This pipeline executes on Azure Pipelines as [dotnet-v3-nightly](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=75). + +## Docker image for CTL workloads + +[azure-pipelines-ctl-publishing.yml](../azure-pipelines-ctl-publishing.yml) executes every time a change is merged into `master` and it will: + +* Generate [docker config files](../Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile). +* Copy the [executable shell file](../Microsoft.Azure.Cosmos.Samples/Tools/CTL/run_ctl.sh). +* Build and publish as a binary [the CTL project](../Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj). +* Execute docker build and publish the image to the team's Azure Container Instances container. + +This pipeline executes on Azure Pipelines as [dotnet-v3-ctl-image-publish](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=64). + +## Encryption packages release + +This repository also includes the [Microsoft.Azure.Cosmos.Encryption](../Microsoft.Azure.Cosmos.Encryption/) and [Microsoft.Azure.Cosmos.Encryption.Custom](../Microsoft.Azure.Cosmos.Encryption.Custom/) projects as satellite packages for client side encryption. + +[azure-pipelines-encryption](../azure-pipelines-encryption.yml) is used during the release process for a new `Microsoft.Azure.Cosmos.Encryption` release: + +* Builds the [Microsoft.Azure.Cosmos.Encryption](../Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj) +* Generate a Nuget package and a Symbols package +* Publish the package on the `cosmosdb/csharp/encryption/` storage container. + +This pipeline executes on Azure Pipelines as [dotnet-v3-encryption-release](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=66). + +[azure-pipelines-encryption-custom](../azure-pipelines-encryption-custom.yml) is used during the release process for a new `Microsoft.Azure.Cosmos.Encryption.Custom` release: + +* Builds the [Microsoft.Azure.Cosmos.Encryption.Custom](../Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj) +* Generate a Nuget package and a Symbols package +* Publish the package on the `cosmosdb/csharp/encryption.custom/` storage container. + +This pipeline executes on Azure Pipelines as [dotnet-v3-encryption-custom-release](https://cosmos-db-sdk-public.visualstudio.com/cosmos-db-sdk-public/_build?definitionId=67). diff --git a/templates/build-benchmark.yml b/templates/build-benchmark.yml index 7e73842ee1..b542231b8c 100644 --- a/templates/build-benchmark.yml +++ b/templates/build-benchmark.yml @@ -31,4 +31,29 @@ jobs: nugetConfigPath: NuGet.config projects: 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.sln' arguments: -p:Optimize=true -p:OSSProjectRef=true + versioningScheme: OFF +- job: + displayName: Preview CosmosBenchmark ${{ parameters.BuildConfiguration }} + pool: + vmImage: ${{ parameters.VmImage }} + + steps: + - checkout: self # self represents the repo where the initial Pipelines YAML file was found + clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching + + # Add this Command to Include the .NET 6 SDK + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.x' + + - task: DotNetCoreCLI@2 + displayName: Build Microsoft.Azure.CosmosBenchmark + inputs: + command: build + configuration: $(parameters.BuildConfiguration) + nugetConfigPath: NuGet.config + projects: 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.sln' + arguments: -p:Optimize=true -p:IsPreview=true -p:OSSProjectRef=true versioningScheme: OFF \ No newline at end of file diff --git a/templates/build-preview.yml b/templates/build-preview.yml index e9919878ff..5ce991a148 100644 --- a/templates/build-preview.yml +++ b/templates/build-preview.yml @@ -142,30 +142,4 @@ jobs: arguments: ${{ parameters.Arguments }} --configuration ${{ parameters.BuildConfiguration }} /p:IsPreview=true /p:OS=${{ parameters.OS }} publishTestResults: true nugetConfigPath: NuGet.config - testRunTitle: Microsoft.Azure.Cosmos.Tests - -- job: - displayName: Preview CosmosBenchmark ${{ parameters.BuildConfiguration }} - pool: - vmImage: ${{ parameters.VmImage }} - - steps: - - checkout: self # self represents the repo where the initial Pipelines YAML file was found - clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching - - # Add this Command to Include the .NET 6 SDK - - task: UseDotNet@2 - displayName: Use .NET 6.0 - inputs: - packageType: 'sdk' - version: '6.x' - - - task: DotNetCoreCLI@2 - displayName: Build Microsoft.Azure.CosmosBenchmark - inputs: - command: build - configuration: $(parameters.BuildConfiguration) - nugetConfigPath: NuGet.config - projects: 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.sln' - arguments: -p:Optimize=true -p:IsPreview=true -p:OSSProjectRef=true - versioningScheme: OFF \ No newline at end of file + testRunTitle: Microsoft.Azure.Cosmos.Tests \ No newline at end of file From e872f936caf2f653f7e8fd01e71f3e0ad85691ef Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Thu, 27 Apr 2023 16:32:17 +0530 Subject: [PATCH 100/337] Client Encryption: Adds release version of Microsoft.Azure.Cosmos to Microsoft.Azure.Cosmos.Encryption.Custom (#3799) * cosmos version change * changing preview to release * resolving code review comments --------- Co-authored-by: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> --- .../src/EncryptionContainer.cs | 16 +++++++++------- ...crosoft.Azure.Cosmos.Encryption.Custom.csproj | 10 ++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs index ae0ec2aead..eebf5900cf 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs @@ -791,13 +791,6 @@ public override Task> GetFeedRangesAsync( return this.container.GetFeedRangesAsync(cancellationToken); } - public override Task> GetPartitionKeyRangesAsync( - FeedRange feedRange, - CancellationToken cancellationToken = default) - { - return this.container.GetPartitionKeyRangesAsync(feedRange, cancellationToken); - } - public override FeedIterator GetItemQueryStreamIterator( FeedRange feedRange, QueryDefinition queryDefinition, @@ -1010,6 +1003,14 @@ public override async Task> ReadManyItemsAsync( return this.ResponseFactory.CreateItemFeedResponse(responseMessage); } +#if ENCRYPTIONPREVIEW + public override Task> GetPartitionKeyRangesAsync( + FeedRange feedRange, + CancellationToken cancellationToken = default) + { + return this.container.GetPartitionKeyRangesAsync(feedRange, cancellationToken); + } + public override Task DeleteAllItemsByPartitionKeyStreamAsync( Cosmos.PartitionKey partitionKey, RequestOptions requestOptions = null, @@ -1020,6 +1021,7 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( requestOptions, cancellationToken); } +#endif private async Task ReadManyItemsHelperAsync( IReadOnlyList<(string id, PartitionKey partitionKey)> items, diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index 54755c89ef..09b92aa37e 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -4,8 +4,6 @@ Microsoft.Azure.Cosmos.Encryption.Custom Microsoft.Azure.Cosmos.Encryption.Custom $(LangVersion) - true - $([System.DateTime]::Now.ToString(yyyyMMdd)) $(CustomEncryptionVersion) Microsoft Corporation @@ -24,8 +22,12 @@ - - + + + + + + From e5972ac0ffd53595b2f1f0f10a3faf913ff882e1 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 27 Apr 2023 10:16:32 -0700 Subject: [PATCH 101/337] SDK 3.33.0 : Adds version bump and changelog (#3823) * release 3.30.0 * added changelog * updated changelog * updated changelog * suggested change to changelog * updated changelog --------- Co-authored-by: Matias Quaranta --- Directory.Build.props | 4 +- .../contracts/API_3.33.0-preview.txt | 1540 +++++++++++++++++ .../contracts/API_3.33.0.txt | 1493 ++++++++++++++++ changelog.md | 25 +- 4 files changed, 3059 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.33.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.33.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 695ad7c92c..0a0d59a5b4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.32.3 - 3.32.3 + 3.33.0 + 3.33.0 preview 3.30.8 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.33.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.33.0-preview.txt new file mode 100644 index 0000000000..4b3c5c951e --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.33.0-preview.txt @@ -0,0 +1,1540 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.33.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.33.0.txt new file mode 100644 index 0000000000..af7ab6eef4 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.33.0.txt @@ -0,0 +1,1493 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsPrimitive(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 7188399b52..709a4bfccf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ ## Recommended version -The **minimum recommended version is [3.31.0](#3.31.0)**. +The **minimum recommended version is [3.33.0](#3.33.0)**. Make sure that your applications, when using the .NET V3 SDK, are using at least the version described here to have all the critical fixes. @@ -13,6 +13,29 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.33.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.33.0-preview) - 2023-04-21 + +### Added + +- [3672](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3672) PriorityBasedExecution: Added PriorityLevel as a RequestOption + +### [3.33.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.33.0) - 2023-04-21 + +#### Fixed +- [3762](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3762) HttpClient: Adds detection of DNS changes through use of SocketsHttpHandler for .NET 6 and above +- [3707](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3707) Diagnostics: Adds startDate in Summary +- [3457](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3457) Documentation: Update Database.ReadAsync description +- [3730](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3730) Query: Fixes System.ArgumentException when using PartitionKey.None on x86, Linux or in Optimistic Direct Execution +- [3775](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3775) Change Feed Processor: Fixes LeaseLostException leaks on notification APIs for Renew scenarios +- [3792](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3792) Diagnostics: Refactors Code to Remove Dependency of HttpResponseHeadersWrapper to fetch Sub Status Codes +- [3793](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3793) Documentation: Refactors SQL API reference to NoSQL API +- [3814](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3814) Serialization: Fixes call to CosmosSerializer.FromStream on Gateway mode when EnableContentResponseOnWrite is false. (Thanks @Baltima) + +#### Added +- [3109](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3109), [3763](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3763) Subpartitioning: Adds support for Prefix Partition Key searches for sub partitioned containers, and APIs for public release and increase REST API version +- [3803](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3803) HttpClient: Adds Properties to the Http messages if available +- [3389](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3389) Patch: Adds Move Operation + ### [3.32.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.3) - 2023-03-30 ### [3.32.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.32.3-preview) - 2023-03-30 From 7465da2dcf92dc14769149ae7492c3db77024405 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 1 May 2023 23:59:38 +0530 Subject: [PATCH 102/337] [Internal] Documentation: Adds msdata/direct Sync-up Guide. (#3828) * Code changes to add msdata/direct sync-up documentation. * Code changes to address review comments. * Code changes to address further review comments. * Code changes to address minor review comments. * Removed internal links. --- docs/sync_up_msdata_direct.md | 93 +++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 docs/sync_up_msdata_direct.md diff --git a/docs/sync_up_msdata_direct.md b/docs/sync_up_msdata_direct.md new file mode 100644 index 0000000000..9c416aa65b --- /dev/null +++ b/docs/sync_up_msdata_direct.md @@ -0,0 +1,93 @@ +# Update msdata/direct Repo with Cosmos v3 and Direct Codebase + +## Table of Contents + +* [Background.](#background) +* [Prerequisites.](#prerequisites) +* [Steps Required to Update msdata direct Repo.](#steps-required-to-update-msdata-direct-repo) +* [Validating the sync-up.](#validating-the-sync-up) +* [Submit Pull Request to msdata direct.](#submit-pull-request-to-msdata-direct) +* [Sample Pull Requests to Sync-up msdata direct.](#sample-pull-requests-to-sync-up-msdata-direct) + +## Background + +As a developer on the Cosmos SDK team, we often engage in a task, that requires code changes in both cosmos dotnet sdk v3 repository, as well as in the `msdata` cosmosdb direct codebase (aka `Microsoft.Azure.Cosmos.Direct` namespace). Therefore, sometimes it's utterly challenging to visualize the code changes as a whole, and analyze the impacts. To overcome this, we have created a branch called `msdata/direct` within our cosmos dotnet sdk v3 codebase, that basically mimics the code present in `msdata` repository mentioned above. This simplifies the code changes required to be done in both, provides much better understanding on the overall impacts of the code changes and gives transparency to users in terms of what is the source code for the `Microsoft.Azure.Cosmos.Direct` package. + +## Prerequisites + +Before covering the sync-up process in detail, please follow the below steps to make sure all the required pre-requisites are met. + +### Clone the Azure Cosmos DB .NET SDK Version 3 Repo + +- Clone the azure `cosmos-db dotnet sdk` repo in the local environment, using the below git command: + - git clone https://github.com/Azure/azure-cosmos-dotnet-v3.git + +- Navigate to the directory `azure-cosmos-dotnet-v3` and check out the following branch, `msdata/direct` using the below git commands: + - git pull && git checkout msdata/direct + +### Clone the `CosmosDB` Repo hosted in msdata + +- Clone the CosmosDB repository in the local environment, using the CosmosDB onboarding guide. Please note, building the entire repository is not required for the sync-up process. + +- Navigate to the cloned `CosmosDB` directory and check out the following branch, `master` using the below git commands: + - git pull && git checkout master + +## Steps Required to Update msdata direct Repo + +### Create a Feature Branch for Local Changes. + +The first step to sync up the `msdata/direct` repo is to create a feature branch out of it, where all the required changes could be made. Later on, we will use the feature branch to submit pull request to `msdata/direct`. Please use the following git command to create the feature branch: + +- Stay on the `msdata/direct` branch and run `git checkout -b users//update_msdata_direct_` to create the feature branch. + +### Merging the cosmos db v3 Code into Feature Branch. + +The next step is to port the latest `master` branch code into the newly created feature branch. Please see the below git commands to perform this action: + +- Make sure the `master` branch is up-to-date. +- Stay on the newly created feature branch `users//update_msdata_direct_` and run `git merge master`. +- There are likely to be conflicts during the merge. If that happens, we will need to resolve the conflicts gracefully by accepting the incoming `master` branch changes. + +### Pick the Required Microsoft Azure Cosmos.Direct files into `msdata/direct` repo. + +This is the last part for the sync-up process. Please follow the below steps to copy the required `Microsoft.Cosmos.Direct` files from msdata CosmosDB repo. + +- Open command prompt/windows terminal and navigate to the following directory `Microsoft.Azure.Cosmos\src\direct` inside the cloned cosmos v3 repo. +- Locate and edit the following line in the `msdata_sync.ps1` script with the respective location of the msdata repo: `$baseDir = "\CosmosDB"` +- Run the powershell script using: `.\msdata_sync.ps1`. You will notice the script started copying the required files from the msdata repo, and generating the console logs, like the below: + + ``` + Copying Files: rntbd2 + Copying Files: AccessCondition.cs + Copying Files: AccessConditionType.cs + Copying Files: Address.cs + Copying Files: AddressCacheToken.cs + Copying Files: AddressEnumerator.cs + Copying Files: AddressInformation.cs + Copying Files: AddressSelector.cs + Copying Files: ApiType.cs + Copying Files: Attachment.cs + Copying Files: AuthorizationTokenType.cs + Copying Files: BackoffRetryUtility.cs + Copying Files: BadRequestException.cs + Copying Files: BarrierRequestHelper.cs + ``` + +- Note: There may be instances where some of the files could be missing in the v3 `msdata/direct` repo and the copy may fail with the following error: `Write-Error: SystemSynchronizationScope.cs False`. If that happens, please copy the file manually from the `msdata/CosmosDB` repo and continue running the script all over again. + +## Validating the sync-up + +One of the most important part in the whole `msdata/direct` sync up process is to validate whether the code merges, conflict resolutions and file updates went successfully. To comply with this, please make sure to follow the below steps: + +- Open command prompt/ windows terminal and navigate to the directory where the cosmos v3 code is located, for instance `C:\stash\azure-cosmos-dotnet-v3`. +- Make sure to stay on the newly created feature branch. +- Stay on the same directory mentioned above, and run the following command for a clean build: `dotnet build`. Make sure, the build passes successfully. + +## Submit Pull Request to msdata direct + +Once the feature branch builds successfully, it's time to submit the PR to `msdata/direct` to complete the sync-up process. To do this, please follow `git add`, `git commit` and `git push` commands to push the newly created branch upstream. Once the branch is pushed, please submit the pull request to the `msdata/direct` branch and seek for approvals. + +## Sample Pull Requests to Sync-up msdata direct + +- [[Internal] Msdata/Direct: Refactors msdata branch with latest v3 and direct release](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3726) +- [[Internal] Msdata/Direct: Refactors msdata/direct branch with latest v3 master and Cosmos.Direct v3.30.4](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3776) \ No newline at end of file From 20121c85a1c49f46e5194007de055e5ff79ca297 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Tue, 2 May 2023 08:48:44 -0700 Subject: [PATCH 103/337] Query: Adds TRIM string system function support in LINQ (#3833) * add trim support * Added some test coverage * address reviews --------- Co-authored-by: Minh Le --- .../StringBuiltinFunctions.cs | 43 ++++++ ...ationBaselineTests.TestStringFunctions.xml | 128 ++++++++++++++++-- .../LinqTranslationBaselineTests.cs | 19 ++- 3 files changed, 177 insertions(+), 13 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs index 781eb8d20a..b04bd58c3c 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs @@ -348,6 +348,45 @@ protected override SqlScalarExpression VisitImplicit(MethodCallExpression method } } + private class StringVisitTrim : SqlBuiltinFunctionVisitor + { + public StringVisitTrim() + : base("TRIM", + false, + null) + { + } + + protected override SqlScalarExpression VisitImplicit(MethodCallExpression methodCallExpression, TranslationContext context) + { + bool validInNet = false; + bool validInNetCore = false; + + if (methodCallExpression.Arguments.Count == 1 && + methodCallExpression.Arguments[0].NodeType == ExpressionType.Constant && + methodCallExpression.Arguments[0].Type == typeof(char[])) + { + char[] argumentsExpressions = (char[])((ConstantExpression)methodCallExpression.Arguments[0]).Value; + if (argumentsExpressions.Length == 0) + { + validInNet = true; + } + } + else if (methodCallExpression.Arguments.Count == 0) + { + validInNetCore = true; + } + + if (validInNet || validInNetCore) + { + SqlScalarExpression str = ExpressionToSql.VisitScalarExpression(methodCallExpression.Object, context); + return SqlFunctionCallScalarExpression.CreateBuiltin(SqlFunctionCallScalarExpression.Names.Trim, str); + } + + return null; + } + } + static StringBuiltinFunctions() { StringBuiltinFunctionDefinitions = new Dictionary @@ -415,6 +454,10 @@ static StringBuiltinFunctions() "TrimEnd", new StringVisitTrimEnd() }, + { + "Trim", + new StringVisitTrim() + }, { "StartsWith", new SqlStringWithComparisonVisitor(SqlFunctionCallScalarExpression.Names.Startswith) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringFunctions.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringFunctions.xml index a9fc581461..4ccc9d34ca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringFunctions.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringFunctions.xml @@ -363,6 +363,28 @@ FROM root]]> + + + + + + doc.StringField.Replace(c, a))]]> + + + + + + + + + doc.StringField.Replace("str", "str2"))]]> + + + @@ -379,34 +401,45 @@ FROM root]]> - - doc.StringField.TrimStart())]]> + + doc.StringField.Trim())]]> - - doc.StringField.Replace(c, a))]]> + + " abc ".Trim())]]> - - doc.StringField.Replace("str", "str2"))]]> + + doc.StringField.Trim(new [] {}))]]> + + + + + + " abc ".Trim(new [] {}))]]> + + + @@ -418,6 +451,83 @@ FROM root]]> + + + + + + " abc ".TrimEnd())]]> + + + + + + + + + doc.StringField.TrimEnd(new [] {}))]]> + + + + + + + + + " abc ".TrimEnd(new [] {}))]]> + + + + + + + + + doc.StringField.TrimStart())]]> + + + + + + + + + " abc ".TrimStart())]]> + + + + + + + + + doc.StringField.TrimStart(new [] {}))]]> + + + + + + + + + " abc ".TrimStart(new [] {}))]]> + + + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 14aadd354f..76bd0ffc81 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -744,15 +744,26 @@ public void TestStringFunctions() new LinqTestInput("IndexOf string w/ startIndex", b => getQuery(b).Select(doc => doc.StringField.IndexOf("str", 0))), // Count new LinqTestInput("Count", b => getQuery(b).Select(doc => doc.StringField.Count())), - // ToLower - new LinqTestInput("ToLower", b => getQuery(b).Select(doc => doc.StringField.ToLower())), - // TrimStart - new LinqTestInput("TrimStart", b => getQuery(b).Select(doc => doc.StringField.TrimStart())), // Replace new LinqTestInput("Replace char", b => getQuery(b).Select(doc => doc.StringField.Replace('c', 'a'))), new LinqTestInput("Replace string", b => getQuery(b).Select(doc => doc.StringField.Replace("str", "str2"))), + // ToLower + new LinqTestInput("ToLower", b => getQuery(b).Select(doc => doc.StringField.ToLower())), + // Trim + new LinqTestInput("Trim", b => getQuery(b).Select(doc => doc.StringField.Trim())), + new LinqTestInput("Trim with Literal", b => getQuery(b).Select(doc => " abc ".Trim())), + new LinqTestInput("Trim with EmptyCharArray", b => getQuery(b).Select(doc => doc.StringField.Trim(new char[]{ }))), + new LinqTestInput("Trim with Literal and EmptyCharArray", b => getQuery(b).Select(doc => " abc ".Trim(new char[]{ }))), // TrimEnd new LinqTestInput("TrimEnd", b => getQuery(b).Select(doc => doc.StringField.TrimEnd())), + new LinqTestInput("TrimEnd with Literal", b => getQuery(b).Select(doc => " abc ".TrimEnd())), + new LinqTestInput("TrimEnd with EmptyCharArray", b => getQuery(b).Select(doc => doc.StringField.TrimEnd(new char[]{ }))), + new LinqTestInput("TrimEnd with Literal and EmptyCharArray", b => getQuery(b).Select(doc => " abc ".TrimEnd(new char[]{ }))), + // TrimStart + new LinqTestInput("TrimStart", b => getQuery(b).Select(doc => doc.StringField.TrimStart())), + new LinqTestInput("TrimStart with Literal", b => getQuery(b).Select(doc => " abc ".TrimStart())), + new LinqTestInput("TrimStart with EmptyCharArray", b => getQuery(b).Select(doc => doc.StringField.TrimStart(new char[]{ }))), + new LinqTestInput("TrimStart with Literal and EmptyCharArray", b => getQuery(b).Select(doc => " abc ".TrimStart(new char[]{ }))), //StartsWith new LinqTestInput("StartsWith", b => getQuery(b).Select(doc => doc.StringField.StartsWith("str"))), new LinqTestInput("String constant StartsWith", b => getQuery(b).Select(doc => "str".StartsWith(doc.StringField))), From 15616d38a619de70a35c99b6de7f6b30b504d17a Mon Sep 17 00:00:00 2001 From: leminh98 Date: Tue, 2 May 2023 10:34:44 -0700 Subject: [PATCH 104/337] Query: Fixes Parsing Error in SQL DOM when CultureInfo is available (#3832) * add fix * Add cultural info to test to verify correct behavior * address pr review to restore to restore culture * fix comment --------- Co-authored-by: Minh Le --- .../src/Query/Core/Parser/CstToAstVisitor.cs | 3 ++- .../Query/Parser/SqlParserBaselineTests.cs | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs index 8ba6c4fc45..7ca3a60a71 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Parser using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics.Contracts; + using System.Globalization; using Antlr4.Runtime.Misc; using Antlr4.Runtime.Tree; using Microsoft.Azure.Cosmos.SqlObjects; @@ -963,7 +964,7 @@ private static Number64 GetNumber64ValueFromNode(IParseTree parseTree) } else { - number64 = double.Parse(text); + number64 = double.Parse(text, CultureInfo.InvariantCulture); } return number64; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/SqlParserBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/SqlParserBaselineTests.cs index fbbca5abbc..11f23fab83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/SqlParserBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/SqlParserBaselineTests.cs @@ -5,6 +5,9 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Parser { using System; + using System.Collections.Generic; + using System.Globalization; + using System.Threading; using System.Xml; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Parser; @@ -17,6 +20,8 @@ public abstract class SqlParserBaselineTests : BaselineTests parseQueryMonad = SqlQueryParser.Monadic.Parse(input.Query); if (parseQueryMonad.Succeeded) { @@ -26,6 +31,22 @@ public override SqlParserBaselineTestOutput ExecuteTest(SqlParserBaselineTestInp Assert.AreEqual(parseQueryMonad.Result, parseQueryMonad2.Result); } + // Set culture to non-standard (US) to catch any parsing error + foreach (string culture in new List { "en-US", "fr-FR", "jp-JP" }) + { + Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture); + TryCatch parseQueryMonadCulture = SqlQueryParser.Monadic.Parse(input.Query); + if (parseQueryMonadCulture.Succeeded) + { + // Addtional round trip for extra validation + TryCatch parseQueryMonadCulture2 = SqlQueryParser.Monadic.Parse(parseQueryMonad.Result.ToString()); + Assert.IsTrue(parseQueryMonadCulture2.Succeeded); + Assert.AreEqual(parseQueryMonadCulture2.Result, parseQueryMonadCulture2.Result); + } + } + + // return thread to default culture + Thread.CurrentThread.CurrentCulture = defaultCulture; return new SqlParserBaselineTestOutput(parseQueryMonad); } } From 1dcba536ecaed62b559ed6f5cf0bec62d4b63374 Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Wed, 3 May 2023 19:10:54 +0530 Subject: [PATCH 105/337] Client Encryption: Adds api FetchDataEncryptionKeyWithoutRawKeyAsync and FetchDataEncryptionKeyAsync to get DEK without and with raw key respectively. (#3809) * added raw key to MdeEncryption * adding ray key to Mde Algo * test case changes * resolving code review comments * code optimization to reduce keyvault calls * removed Microsoft.Data.Encryption.Cryptography nuget package * added api for dek with raw key * resolved code review comments * adding change log * code review changes --- Directory.Build.props | 2 +- .../changelog.md | 5 ++ .../src/CosmosDataEncryptionKeyProvider.cs | 17 +++++- .../src/CosmosEncryptor.cs | 8 +-- .../src/DataEncryptionKeyContainerCore.cs | 11 ++-- .../src/DataEncryptionKeyProvider.cs | 14 ++++- .../src/MdeServices/MdeEncryptionAlgorithm.cs | 54 +++++++++++-------- .../EmulatorTests/LegacyEncryptionTests.cs | 6 +-- .../EmulatorTests/MdeCustomEncryptionTests.cs | 48 +++++++++++++++-- .../CosmosEncryptorTests.cs | 4 +- 10 files changed, 127 insertions(+), 42 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 0a0d59a5b4..a24f0ab2ac 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,7 +7,7 @@ 2.0.1 2.0.1 preview - 1.0.0-preview04 + 1.0.0-preview05 1.1.0-preview3 10.0 $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md index a17680a9f8..58fcf1d790 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md @@ -3,6 +3,11 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [1.0.0-preview05](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview05) - 2023-04-27 + +#### Fixes +- [#3809](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3809) Adds api FetchDataEncryptionKeyWithoutRawKeyAsync and FetchDataEncryptionKey to get DEK without and with raw key respectively. + ### [1.0.0-preview04](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview04) - 2022-08-16 #### Fixes diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs index 1c8cffce8e..773845aa9e 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosDataEncryptionKeyProvider.cs @@ -166,11 +166,25 @@ public async Task InitializeAsync( this.container = containerResponse.Container; } + /// + public override async Task FetchDataEncryptionKeyWithoutRawKeyAsync( + string id, + string encryptionAlgorithm, + CancellationToken cancellationToken) + { + return await this.FetchDekAsync(id, encryptionAlgorithm, cancellationToken); + } + /// public override async Task FetchDataEncryptionKeyAsync( string id, string encryptionAlgorithm, CancellationToken cancellationToken) + { + return await this.FetchDekAsync(id, encryptionAlgorithm, cancellationToken, true); + } + + private async Task FetchDekAsync(string id, string encryptionAlgorithm, CancellationToken cancellationToken, bool withRawKey = false) { DataEncryptionKeyProperties dataEncryptionKeyProperties = await this.dataEncryptionKeyContainerCore.FetchDataEncryptionKeyPropertiesAsync( id, @@ -200,7 +214,8 @@ public override async Task FetchDataEncryptionKeyAsync( InMemoryRawDek inMemoryRawDek = await this.dataEncryptionKeyContainerCore.FetchUnwrappedAsync( dataEncryptionKeyProperties, diagnosticsContext: CosmosDiagnosticsContext.Create(null), - cancellationToken: cancellationToken); + cancellationToken: cancellationToken, + withRawKey); return inMemoryRawDek.DataEncryptionKey; } diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs index 3a325e77b2..462bd56a1f 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/CosmosEncryptor.cs @@ -35,14 +35,14 @@ public override async Task DecryptAsync( string encryptionAlgorithm, CancellationToken cancellationToken = default) { - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); if (dek == null) { - throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}."); + throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}."); } return dek.DecryptData(cipherText); @@ -55,14 +55,14 @@ public override async Task EncryptAsync( string encryptionAlgorithm, CancellationToken cancellationToken = default) { - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); if (dek == null) { - throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}."); + throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}."); } return dek.EncryptData(plainText); diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs index b5f5d340c9..68e5414275 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyContainerCore.cs @@ -335,6 +335,7 @@ internal async Task FetchUnWrappedMdeSupportedLegacyDekAsync( unwrapResult.DataEncryptionKey); return new MdeEncryptionAlgorithm( + unwrapResult.DataEncryptionKey, plaintextDataEncryptionKey, Data.Encryption.Cryptography.EncryptionType.Randomized); } @@ -378,13 +379,14 @@ internal async Task FetchUnWrappedLegacySupportedMdeDekAsync( internal async Task FetchUnwrappedAsync( DataEncryptionKeyProperties dekProperties, CosmosDiagnosticsContext diagnosticsContext, - CancellationToken cancellationToken) + CancellationToken cancellationToken, + bool withRawKey = false) { try { if (string.Equals(dekProperties.EncryptionAlgorithm, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized)) { - DataEncryptionKey dek = this.InitMdeEncryptionAlgorithm(dekProperties); + DataEncryptionKey dek = this.InitMdeEncryptionAlgorithm(dekProperties, withRawKey); // TTL is not used since DEK is not cached. return new InMemoryRawDek(dek, TimeSpan.FromMilliseconds(0)); @@ -564,7 +566,7 @@ private async Task UnWrapDekMdeEncAlgoAsync( return unwrapResult; } - internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyProperties dekProperties) + internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyProperties dekProperties, bool withRawKey = false) { if (this.DekProvider.MdeKeyWrapProvider == null) { @@ -576,7 +578,8 @@ internal DataEncryptionKey InitMdeEncryptionAlgorithm(DataEncryptionKeyPropertie dekProperties, Data.Encryption.Cryptography.EncryptionType.Randomized, this.DekProvider.MdeKeyWrapProvider.EncryptionKeyStoreProvider, - this.DekProvider.PdekCacheTimeToLive); + this.DekProvider.PdekCacheTimeToLive, + withRawKey); } private async Task ReadResourceAsync( diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs index 502e14897b..c92df3fa60 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/DataEncryptionKeyProvider.cs @@ -14,7 +14,19 @@ namespace Microsoft.Azure.Cosmos.Encryption.Custom public abstract class DataEncryptionKeyProvider { /// - /// Retrieves the data encryption key for the given id. + /// Retrieves the data encryption key for the given id without rawkey. RawKey will be set to null. + /// + /// Identifier of the data encryption key. + /// Encryption algorithm that the retrieved key will be used with. + /// Token for request cancellation. + /// Data encryption key bytes. + public abstract Task FetchDataEncryptionKeyWithoutRawKeyAsync( + string id, + string encryptionAlgorithm, + CancellationToken cancellationToken); + + /// + /// Retrieves the data encryption key for the given id with RawKey value. /// /// Identifier of the data encryption key. /// Encryption algorithm that the retrieved key will be used with. diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs index d9144a5c4f..68d863114e 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/MdeServices/MdeEncryptionAlgorithm.cs @@ -14,8 +14,10 @@ internal sealed class MdeEncryptionAlgorithm : DataEncryptionKey { private readonly AeadAes256CbcHmac256EncryptionAlgorithm mdeAeadAes256CbcHmac256EncryptionAlgorithm; + private readonly byte[] unwrapKey; + // unused for MDE Algorithm. - public override byte[] RawKey => null; + public override byte[] RawKey { get; } public override string EncryptionAlgorithm => CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized; @@ -32,7 +34,8 @@ public MdeEncryptionAlgorithm( DataEncryptionKeyProperties dekProperties, Data.Encryption.Cryptography.EncryptionType encryptionType, EncryptionKeyStoreProvider encryptionKeyStoreProvider, - TimeSpan? cacheTimeToLive) + TimeSpan? cacheTimeToLive, + bool withRawKey=false) { if (dekProperties == null) { @@ -49,36 +52,39 @@ public MdeEncryptionAlgorithm( dekProperties.EncryptionKeyWrapMetadata.Value, encryptionKeyStoreProvider); - ProtectedDataEncryptionKey protectedDataEncryptionKey; - if (cacheTimeToLive.HasValue) + if (!withRawKey) { - // no caching - if (cacheTimeToLive.Value == TimeSpan.Zero) - { - protectedDataEncryptionKey = new ProtectedDataEncryptionKey( + ProtectedDataEncryptionKey protectedDataEncryptionKey = cacheTimeToLive.HasValue && cacheTimeToLive.Value == TimeSpan.Zero + ? new ProtectedDataEncryptionKey( + dekProperties.Id, + keyEncryptionKey, + dekProperties.WrappedDataEncryptionKey) + : ProtectedDataEncryptionKey.GetOrCreate( dekProperties.Id, keyEncryptionKey, dekProperties.WrappedDataEncryptionKey); - } - else - { - protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate( - dekProperties.Id, - keyEncryptionKey, - dekProperties.WrappedDataEncryptionKey); - } + this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate( + protectedDataEncryptionKey, + encryptionType); } else { - protectedDataEncryptionKey = ProtectedDataEncryptionKey.GetOrCreate( - dekProperties.Id, - keyEncryptionKey, - dekProperties.WrappedDataEncryptionKey); + byte[] rawKey = keyEncryptionKey.DecryptEncryptionKey(dekProperties.WrappedDataEncryptionKey); + PlaintextDataEncryptionKey plaintextDataEncryptionKey = cacheTimeToLive.HasValue && (cacheTimeToLive.Value == TimeSpan.Zero) + ? new PlaintextDataEncryptionKey( + dekProperties.Id, + rawKey) + : PlaintextDataEncryptionKey.GetOrCreate( + dekProperties.Id, + rawKey); + this.RawKey = rawKey; + this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate( + plaintextDataEncryptionKey, + encryptionType); + } - this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate( - protectedDataEncryptionKey, - encryptionType); + } /// @@ -90,9 +96,11 @@ public MdeEncryptionAlgorithm( /// Data Encryption Key /// Encryption type public MdeEncryptionAlgorithm( + byte[] rawkey, Data.Encryption.Cryptography.DataEncryptionKey dataEncryptionKey, Data.Encryption.Cryptography.EncryptionType encryptionType) { + this.RawKey = rawkey; this.mdeAeadAes256CbcHmac256EncryptionAlgorithm = AeadAes256CbcHmac256EncryptionAlgorithm.GetOrCreate( dataEncryptionKey, encryptionType); diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs index 27f4567732..2785f04815 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/LegacyEncryptionTests.cs @@ -1747,14 +1747,14 @@ public override async Task DecryptAsync( throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned."); } - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); if (dek == null) { - throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}."); + throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}."); } return dek.DecryptData(cipherText); @@ -1766,7 +1766,7 @@ public override async Task EncryptAsync( string encryptionAlgorithm, CancellationToken cancellationToken = default) { - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs index 3b2b8f8d97..e100268ea0 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/MdeCustomEncryptionTests.cs @@ -20,6 +20,7 @@ namespace Microsoft.Azure.Cosmos.Encryption.EmulatorTests using EncryptionKeyWrapMetadata = Custom.EncryptionKeyWrapMetadata; using DataEncryptionKey = Custom.DataEncryptionKey; using Newtonsoft.Json.Linq; + using System.Buffers.Text; [TestClass] public class MdeCustomEncryptionTests @@ -103,6 +104,47 @@ public async Task EncryptionCreateDek() Assert.AreEqual(dekProperties, readProperties); } + [TestMethod] + public async Task FetchDataEncryptionKeyWithRawKey() + { + CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider()); + await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id); + DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, dekProperties.EncryptionAlgorithm, CancellationToken.None); + Assert.IsNotNull(k.RawKey); + } + + [TestMethod] + public async Task FetchDataEncryptionKeyWithoutRawKey() + { + CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider()); + await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id); + DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyWithoutRawKeyAsync(dekProperties.Id, dekProperties.EncryptionAlgorithm, CancellationToken.None); + Assert.IsNull(k.RawKey); + } + + [TestMethod] + [Obsolete] + public async Task FetchDataEncryptionKeyMdeDEKAndLegacyBasedAlgorithm() + { + CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestEncryptionKeyStoreProvider()); + await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id); + DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized, CancellationToken.None); + Assert.IsNotNull(k.RawKey); + } + + [TestMethod] + [Obsolete] + public async Task FetchDataEncryptionKeyLegacyDEKAndMdeBasedAlgorithm() + { + string dekId = "legacyDEK"; + DataEncryptionKeyProperties dekProperties = await MdeCustomEncryptionTests.CreateDekAsync(MdeCustomEncryptionTests.dekProvider, dekId, CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized); + // Use different DEK provider to avoid (unintentional) cache impact + CosmosDataEncryptionKeyProvider dekProvider = new CosmosDataEncryptionKeyProvider(new TestKeyWrapProvider(), new TestEncryptionKeyStoreProvider()); + await dekProvider.InitializeAsync(MdeCustomEncryptionTests.database, MdeCustomEncryptionTests.keyContainer.Id); + DataEncryptionKey k = await dekProvider.FetchDataEncryptionKeyAsync(dekProperties.Id, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized, CancellationToken.None); + Assert.IsNotNull(k.RawKey); + } + [TestMethod] public async Task EncryptionRewrapDek() { @@ -2190,14 +2232,14 @@ public override async Task DecryptAsync( throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned."); } - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); if (dek == null) { - throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync)}."); + throw new InvalidOperationException($"Null {nameof(DataEncryptionKey)} returned from {nameof(this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync)}."); } return dek.DecryptData(cipherText); @@ -2209,7 +2251,7 @@ public override async Task EncryptAsync( string encryptionAlgorithm, CancellationToken cancellationToken = default) { - DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyAsync( + DataEncryptionKey dek = await this.DataEncryptionKeyProvider.FetchDataEncryptionKeyWithoutRawKeyAsync( dataEncryptionKeyId, encryptionAlgorithm, cancellationToken); diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs index 747bf3e295..63c5b370d1 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/CosmosEncryptorTests.cs @@ -34,7 +34,7 @@ public static void ClassInitialize(TestContext testContext) CosmosEncryptorTests.mockDataEncryptionKeyProvider = new Mock(); CosmosEncryptorTests.mockDataEncryptionKeyProvider - .Setup(m => m.FetchDataEncryptionKeyAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(m => m.FetchDataEncryptionKeyWithoutRawKeyAsync(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync((string dekId, string algo, CancellationToken cancellationToken) => dekId == CosmosEncryptorTests.dekId ? CosmosEncryptorTests.mockDataEncryptionKey.Object : null); @@ -82,7 +82,7 @@ public async Task ValidateEncryptDecrypt() Times.Once); CosmosEncryptorTests.mockDataEncryptionKeyProvider.Verify( - m => m.FetchDataEncryptionKeyAsync( + m => m.FetchDataEncryptionKeyWithoutRawKeyAsync( CosmosEncryptorTests.dekId, CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized, It.IsAny()), Times.Exactly(2)); From 9ba3f7539ee0b4dadb937dd47069f7c9a935ea4c Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 3 May 2023 23:00:55 +0000 Subject: [PATCH 106/337] Initial commit (#3826) --- .../src/Linq/TranslationContext.cs | 6 +++ .../BaselineTest/BaselineTests.cs | 4 +- ...nqGeneralBaselineTests.TestLambdaReuse.xml | 38 +++++++++++++++++++ .../LinqGeneralBaselineTests.cs | 21 +++++++++- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 6 +++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestLambdaReuse.xml diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index 9205052604..8fc95d8701 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -119,6 +119,7 @@ public void PopParameter() { ParameterExpression last = this.lambdaParametersStack[this.lambdaParametersStack.Count - 1]; this.lambdaParametersStack.RemoveAt(this.lambdaParametersStack.Count - 1); + this.substitutions.Remove(last); } /// @@ -337,6 +338,11 @@ public Expression Lookup(ParameterExpression parameter) return null; } + internal void Remove(ParameterExpression parameter) + { + this.substitutionTable.Remove(parameter); + } + public const string InputParameterName = "root"; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs index e9fbc54267..62f20f1fe4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/BaselineTests.cs @@ -153,8 +153,8 @@ public void ExecuteTestSuite(IEnumerable inputs, [CallerMemberName] stri Please run the ..\azure-cosmos-dotnet-v3\UpdateContracts.ps1 script to update the baselines. Expected: {baselineTextSuffix}, Actual: {outputTextSuffix}, - OutputPath: {outputPath}, - BaselinePath: {baselinePath}"); + OutputPath: {Path.GetFullPath(outputPath)}, + BaselinePath: {Path.GetFullPath(baselinePath)}"); } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestLambdaReuse.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestLambdaReuse.xml new file mode 100644 index 0000000000..bd2e168e76 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestLambdaReuse.xml @@ -0,0 +1,38 @@ + + + + Where with same predicate instance]]> + + + + + + + + + Select with same predicate instance]]> + + + + + + + + + Select -> Where with same predicate instance]]> + new AnonymousType(Int = 10, Result = c)).Where(DisplayClass.predicate2)]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs index a9782bb26b..3fc3aff900 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs @@ -1272,6 +1272,25 @@ orderby f.FamilyId descending this.ExecuteTestSuite(inputs); } + [TestMethod] + public void TestLambdaReuse() + { + List inputs = new List(); + + System.Linq.Expressions.Expression> predicate = f => f.Int == 5; + inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); + inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); + + System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; + inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", + b => getQuery(b) + .Where(predicate2) + .Select(c => new { Int = 10, Result = c }) + .Where(predicate2))); + + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void TestThenByTranslation() { @@ -1922,7 +1941,7 @@ public async Task ValidateLinqQueries() Gender = "female", Grade = 1, Pets = new List() { pet, new Pet() { GivenName = "koko" } }, - Things = new Dictionary() { { "A", "B" }, { "C", "D" } }, + Things = new Dictionary() { { "A", "B" }, { "C", "D" } } }; Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index a504adc855..51891d7e3f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -35,6 +35,7 @@ + @@ -283,6 +284,11 @@ + + + PreserveNewest + + PreserveNewest From 17203a5966e906e0d66d52a95cf4d482add3c51e Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 4 May 2023 03:54:27 +0000 Subject: [PATCH 107/337] Query: Adds Computed Property SDK Support (#3761) * Initial commit * Restored settings.json changes. * Update * Addressed comments; still need to be tested using Emulator. * Fixes after test run. * Ignored the computed property tests based on the sync this morning (to allow for preview release). * Suite0 fixes. * Test update. * Suite0 fixes --- .../Settings/ComputedPropertiesDefinition.cs | 60 ++ .../Fluent/Settings/ContainerDefinition.cs | 35 ++ .../src/Resource/Settings/ComputedProperty.cs | 53 ++ .../Resource/Settings/ContainerProperties.cs | 45 ++ .../ComputedPropertyComparer.cs | 45 ++ .../ComputedPropertyTests.cs | 549 ++++++++++++++++++ .../Fluent/ContainerSettingsTests.cs | 188 ++++++ .../Contracts/DotNetPreviewSDKAPI.json | 97 ++++ .../CosmosContainerSettingsTests.cs | 3 + .../ContainerDefinitionForCreateTests.cs | 50 ++ .../SettingsContractTests.cs | 63 +- 11 files changed, 1162 insertions(+), 26 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Fluent/Settings/ComputedPropertiesDefinition.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/ComputedProperty.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyComparer.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/ComputedPropertiesDefinition.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ComputedPropertiesDefinition.cs new file mode 100644 index 0000000000..41a6db5168 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ComputedPropertiesDefinition.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Fluent +{ + using System; + using System.Collections.ObjectModel; + + /// + /// Computed Properties fluent definition. + /// + /// +#if PREVIEW + public +#else + internal +#endif + class ComputedPropertiesDefinition + { + private readonly Collection computedProperties = new Collection(); + private readonly T parent; + private readonly Action> attachCallback; + + internal ComputedPropertiesDefinition( + T parent, + Action> attachCallback) + { + this.parent = parent; + this.attachCallback = attachCallback; + } + + /// + /// Adds a computed property to the current + /// + /// Name of the computed property + /// Query for the computed property values + /// An instance of the current + public ComputedPropertiesDefinition WithComputedProperty(string name, string query) + { + this.computedProperties.Add( + new ComputedProperty + { + Name = name, + Query = query + }); + + return this; + } + + /// + /// Applies the current definition to the parent. + /// + /// An instance of the parent. + public T Attach() + { + this.attachCallback(this.computedProperties); + return this.parent; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerDefinition.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerDefinition.cs index a1141fc3f0..1678688c41 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerDefinition.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerDefinition.cs @@ -4,6 +4,8 @@ namespace Microsoft.Azure.Cosmos.Fluent { using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; /// /// Azure Cosmos container fluent definition. @@ -18,6 +20,7 @@ public abstract class ContainerDefinition private IndexingPolicy indexingPolicy; private string timeToLivePropertyPath; private PartitionKeyDefinitionVersion? partitionKeyDefinitionVersion = null; + private Collection computedProperties; /// /// Creates an instance for unit-testing @@ -123,6 +126,28 @@ public IndexingPolicyDefinition WithIndexingPolicy() (indexingPolicy) => this.WithIndexingPolicy(indexingPolicy)); } + /// + /// definition for Azure Cosmos container. + /// + /// An instance of . +#if PREVIEW + public +#else + internal +#endif + ComputedPropertiesDefinition WithComputedProperties() + { + if (this.computedProperties != null) + { + // Overwrite + throw new NotSupportedException(); + } + + return new ComputedPropertiesDefinition( + (T)this, + (computedProperties) => this.WithComputedProperties(computedProperties)); + } + /// /// Applies the current Fluent definition and creates a container configuration. /// @@ -152,6 +177,11 @@ public ContainerProperties Build() containerProperties.PartitionKeyDefinitionVersion = this.partitionKeyDefinitionVersion.Value; } + if (this.computedProperties != null) + { + containerProperties.ComputedProperties = this.computedProperties; + } + containerProperties.ValidateRequiredProperties(); return containerProperties; @@ -161,5 +191,10 @@ private void WithIndexingPolicy(IndexingPolicy indexingPolicy) { this.indexingPolicy = indexingPolicy; } + + private void WithComputedProperties(Collection computedProperties) + { + this.computedProperties = computedProperties; + } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ComputedProperty.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ComputedProperty.cs new file mode 100644 index 0000000000..9eaf5f806b --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ComputedProperty.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents a computed property definition in a Cosmos DB collection. + /// +#if PREVIEW + public +#else + internal +#endif + sealed class ComputedProperty + { + /// + /// Gets or sets the name of the computed property. + /// + /// + /// The name of the computed property. + /// + /// + /// Name of the computed property should be chosen such that it does not collide with any existing or future document properties. + /// + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + + /// + /// Gets or sets the query for the computed property. + /// + /// + /// The query used to evaluate the value for the computed property. + /// + /// + /// For example: + /// SELECT VALUE LOWER(c.firstName) FROM c + /// + [JsonProperty(PropertyName = "query")] + public string Query { get; set; } + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs index 94cb93cff5..534f4f033d 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs @@ -78,6 +78,9 @@ public class ContainerProperties [JsonProperty(PropertyName = "clientEncryptionPolicy", NullValueHandling = NullValueHandling.Ignore)] private ClientEncryptionPolicy clientEncryptionPolicyInternal; + [JsonProperty(PropertyName = "computedProperties", NullValueHandling = NullValueHandling.Ignore)] + private Collection computedProperties; + /// /// This contains additional values for scenarios where the SDK is not aware of new fields. /// This ensures that if resource is read and updated none of the fields will be lost in the process. @@ -286,6 +289,48 @@ public IndexingPolicy IndexingPolicy } } + /// + /// Gets or sets the collection containing objects in the container. + /// + /// + /// The collection containing objects associated with the container. + /// + + /// + /// Gets or sets the collection containing objects in the container. + /// + /// + /// The collection containing objects associated with the container. + /// + [JsonIgnore] +#if PREVIEW + public +#else + internal +#endif + Collection ComputedProperties + { + get + { + if (this.computedProperties == null) + { + this.computedProperties = new Collection(); + } + + return this.computedProperties; + } + + set + { + if (value == null) + { + throw new ArgumentException($"{nameof(value)}"); + } + + this.computedProperties = value; + } + } + /// /// Gets the associated with the container from the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyComparer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyComparer.cs new file mode 100644 index 0000000000..486e785978 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyComparer.cs @@ -0,0 +1,45 @@ +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics.CodeAnalysis; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + class ComputedPropertyComparer : IEqualityComparer + { + public static void AssertAreEqual(Collection expected, Collection actual) + { + int expectedCount = expected?.Count ?? 0; + int actualCount = actual?.Count ?? 0; + Assert.AreEqual(expectedCount, actualCount); + + for (int i = 0; i < expectedCount; i++) + { + AssertAreEqual(expected[i], actual[i]); + } + } + + public static void AssertAreEqual(ComputedProperty expected, ComputedProperty actual) + { + ComputedPropertyComparer comparer = new ComputedPropertyComparer(); + Assert.IsTrue(comparer.Equals(expected, actual), $"Expected: {ToString(expected)}{Environment.NewLine}Actual:{ToString(actual)}"); + } + + private static string ToString(ComputedProperty computedProperty) => $@"""Name"":""{computedProperty.Name}"", ""Query"":""{computedProperty.Query}"""; + + public bool Equals(ComputedProperty x, ComputedProperty y) + { + if (x == null) return y == null; + if (y == null) return false; + + return (x.Name?.Equals(y.Name) == true) && + (x.Query?.Equals(y.Query) == true); + } + + public int GetHashCode([DisallowNull] ComputedProperty obj) + { + return obj.GetHashCode(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyTests.cs new file mode 100644 index 0000000000..a2c7f552ee --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ComputedPropertyTests.cs @@ -0,0 +1,549 @@ +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using global::Azure; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ComputedPropertyTests + { + private static readonly CosmosClient cosmosClient; + private static readonly Database database; + + private static readonly ComputedProperty LowerName; + private static readonly ComputedProperty ParentsFullName; + private static readonly Collection AllComputedProperties; + + private static readonly IndexingPolicy IndexAllComputedProperties_IncludeAll; + private static readonly IndexingPolicy IndexAllComputedProperties_ExcludeAll; + private static readonly IndexingPolicy IndexDefault_IncludeAll; + private static readonly IndexingPolicy IndexDefault_ExcludeAll; + + private static readonly string SelectAllComputedPropertiesQuery; + private static readonly List AllComputedPropertiesResult; + private static readonly List EmptyResult; + + static ComputedPropertyTests() + { + cosmosClient = TestCommon.CreateCosmosClient(); + database = cosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()).Result; + + LowerName = new ComputedProperty + { + Name = "lowerLastName", + Query = "SELECT VALUE LOWER(IS_DEFINED(c.lastName) ? c.lastName : c.parents[0].familyName) FROM c" + }; + ParentsFullName = new ComputedProperty + { + Name = "parentsFullName", + Query = "SELECT VALUE CONCAT(CONCAT(c.parents[0].firstName, ' ', c.lastName), ' & ', CONCAT(c.parents[1].firstName, ' ', c.lastName)) FROM c" + }; + AllComputedProperties = new Collection { { LowerName }, { ParentsFullName } }; + + IndexAllComputedProperties_IncludeAll = new IndexingPolicy + { + IncludedPaths = new Collection + { + { new IncludedPath { Path = $"/{LowerName.Name}/*" } }, + { new IncludedPath { Path = $"/{ParentsFullName.Name}/*" } }, + { new IncludedPath { Path = $"/*" } }, + } + }; + IndexAllComputedProperties_ExcludeAll = new IndexingPolicy + { + IncludedPaths = new Collection + { + { new IncludedPath { Path = $"/{LowerName.Name}/*" } }, + { new IncludedPath { Path = $"/{ParentsFullName.Name}/*" } }, + }, + ExcludedPaths = new Collection + { + { new ExcludedPath { Path = $"/*" } } + } + }; + IndexDefault_IncludeAll = new IndexingPolicy + { + IncludedPaths = new Collection + { + { new IncludedPath { Path = $"/*" } }, + } + }; + IndexDefault_ExcludeAll = new IndexingPolicy + { + ExcludedPaths = new Collection + { + { new ExcludedPath { Path = $"/*" } } + } + }; + + SelectAllComputedPropertiesQuery = @"SELECT c.lowerLastName, c.parentsFullName FROM c"; + AllComputedPropertiesResult = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen"",{Environment.NewLine} ""parentsFullName"": ""Thomas Andersen & Mary Kay Andersen""{Environment.NewLine}}}", + $@"{{{Environment.NewLine} ""lowerLastName"": ""wakefield""{Environment.NewLine}}}" + }; + EmptyResult = new List + { + @"{}", + @"{}" + }; + } + + [ClassCleanup] + public static async Task Cleanup() + { + await database?.DeleteAsync(); + } + + [Ignore] + [TestMethod] + public async Task TestComputedProperties() + { + TestVariation[] variations = new TestVariation[] + { + ///////////////// + // Create tests + ///////////////// + new TestVariation + { + Description = "V1: null; V2: Empty", + V1 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + }, + V2 = new ContainerState + { + ComputedProperties = new Collection(), + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + }, + new TestVariation + { + Description = "V1: default; V2: All computed properties, no indexing", + V1 = new ContainerState(), + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + } + }, + new TestVariation + { + Description = "V1: default; V2: All computed properties, indexed, exclude /*", + V1 = new ContainerState(), + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexAllComputedProperties_ExcludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + } + }, + new TestVariation + { + Description = "V1: default; V2: All computed properties, indexed, include /*", + V1 = new ContainerState(), + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexAllComputedProperties_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + }, + new TestVariation + { + Description = "V1: default; V2: All computed properties, not indexed, exclude /*", + V1 = new ContainerState(), + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexDefault_ExcludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + }, + new TestVariation + { + Description = "V1: default; V2: All computed properties, not indexed, include /*", + V1 = new ContainerState(), + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + } + }, + new TestVariation + { + Description = "V1: one computed property; V2: All computed properties, not indexed, include /*", + V1 = new ContainerState() + { + ComputedProperties = new Collection{ LowerName }, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen""{Environment.NewLine}}}", + $@"{{{Environment.NewLine} ""lowerLastName"": ""wakefield""{Environment.NewLine}}}" + } + }, + V2 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + } + }, + + ///////////////// + // Replace tests + ///////////////// + new TestVariation + { + Description = "V1: one computed property; V2: other computed property, not indexed, include /*", + V1 = new ContainerState() + { + ComputedProperties = new Collection{ LowerName }, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen""{Environment.NewLine}}}", + $@"{{{Environment.NewLine} ""lowerLastName"": ""wakefield""{Environment.NewLine}}}" + } + }, + V2 = new ContainerState + { + ComputedProperties = new Collection{ ParentsFullName }, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""parentsFullName"": ""Thomas Andersen & Mary Kay Andersen""{Environment.NewLine}}}", + @"{}" + } + } + }, + new TestVariation + { + Description = "V1: one computed property; V2: updated computed property definition, not indexed, include /*", + V1 = new ContainerState() + { + ComputedProperties = new Collection{ LowerName }, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen""{Environment.NewLine}}}", + $@"{{{Environment.NewLine} ""lowerLastName"": ""wakefield""{Environment.NewLine}}}" + } + }, + V2 = new ContainerState + { + ComputedProperties = new Collection + { + new ComputedProperty + { + Name = "lowerLastName", + Query = "SELECT VALUE LOWER(c.lastName) FROM c" + } + }, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen""{Environment.NewLine}}}", + @"{}" + } + } + }, + + ///////////////// + // Drop tests + ///////////////// + new TestVariation + { + Description = "V1: All computed properties; V2: null", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + }, + new TestVariation + { + Description = "V1: All computed properties; V2: only 1 computed property", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = new Collection{ LowerName }, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = new List + { + $@"{{{Environment.NewLine} ""lowerLastName"": ""andersen""{Environment.NewLine}}}", + $@"{{{Environment.NewLine} ""lowerLastName"": ""wakefield""{Environment.NewLine}}}" + } + } + }, + new TestVariation + { + Description = "V1: All computed properties, indexed, exclude /*; V2: null", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexAllComputedProperties_ExcludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + }, + new TestVariation + { + Description = "V1: All computed properties, indexed, include /*; V2: null", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexAllComputedProperties_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + }, + new TestVariation + { + Description = "V1: All computed properties, not indexed, exclude /*; V2: null", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexDefault_ExcludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + }, + new TestVariation + { + Description = "V1: All computed properties, not indexed, include /*; V2: null", + V1 = new ContainerState + { + ComputedProperties = AllComputedProperties, + IndexingPolicy = IndexDefault_IncludeAll, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = AllComputedPropertiesResult + }, + V2 = new ContainerState + { + ComputedProperties = null, + Query = SelectAllComputedPropertiesQuery, + ExpectedDocuments = EmptyResult + } + } + }; + + int i = 0; + foreach (TestVariation variation in variations) + { + Console.WriteLine($"Variation {i++} : {variation.Description}"); + await this.RunTest(variation); + } + } + + private async Task RunTest(TestVariation variation) + { + Container container = await this.CreateOrReplace(container: null, containerState: variation.V1); + return await this.CreateOrReplace(container, containerState: variation.V2); + } + + private async Task CreateOrReplace(Container container, ContainerState containerState) + { + ContainerProperties containerProperties = new ContainerProperties(container?.Id ?? Guid.NewGuid().ToString(), "/id") + { + IndexingPolicy = containerState.IndexingPolicy ?? new IndexingPolicy(), + ComputedProperties = containerState.ComputedProperties ?? new Collection(), + }; + + ContainerResponse response = container == null ? + await database.CreateContainerAsync(containerProperties) : + await container.ReplaceContainerAsync(containerProperties); + + this.ValidateComputedProperties(containerState.ComputedProperties, response.Resource.ComputedProperties); + + if (container == null) + { + await this.InsertDocuments(response.Container); + } + else + { + // Sometimes the container changes are not immediately reflected in the query. + // We force a insert-delete after container replacement, which seems to help with this problem. + // If this still doesn't help with the flakiness, we need to find other ways of running the query scenario. + // One alternative is to wait for V2 for all test variations to take effect + // and then run queries separately on each container. + await this.DeleteReinsertDocuments(response.Container); + } + + if (!string.IsNullOrEmpty(containerState.Query)) + { + List results = await this.QueryItems(response.Container, containerState.Query); + + Assert.AreEqual(containerState.ExpectedDocuments.Count, results.Count); + for (int i = 0; i < containerState.ExpectedDocuments.Count; i++) + { + Assert.AreEqual(containerState.ExpectedDocuments[i], results[i]); + } + } + + return response.Container; + } + + private async Task DeleteReinsertDocuments(Container container) + { + foreach (CosmosObject document in Documents) + { + string id = ((CosmosString)document["id"]).Value; + await container.DeleteItemAsync(id, new PartitionKey(id)); + } + + await this.InsertDocuments(container); + } + + private async Task InsertDocuments(Container container) + { + foreach(CosmosObject document in Documents) + { + await container.CreateItemAsync(document); + } + } + + private async Task> QueryItems(Container container, string query) + { + List results = new List(); + FeedIterator iterator = container.GetItemQueryIterator(query); + do + { + FeedResponse page = await iterator.ReadNextAsync(); + results.AddRange(page.Select(item => item.ToString())); + } while (iterator.HasMoreResults); + + return results; + } + + private void ValidateComputedProperties(Collection expected, Collection actual) + { + ComputedPropertyComparer.AssertAreEqual(expected, actual); + } + + private class TestVariation + { + public string Description { get; set; } + public ContainerState V1 { get; set; } + public ContainerState V2 { get; set; } + } + + private class ContainerState + { + public Collection ComputedProperties { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public List ExpectedDocuments { get; set; } + public string Query { get; set; } + } + + private static readonly CosmosObject AndersenFamily = CosmosObject.Parse(@" + { + ""id"": ""AndersenFamily"", + ""lastName"": ""Andersen"", + ""parents"": [ + { ""firstName"": ""Thomas"" }, + { ""firstName"": ""Mary Kay""} + ], + ""children"": [ + { + ""firstName"": ""Henriette Thaulow"", + ""gender"": ""female"", + ""grade"": 5, + ""pets"": [{ ""givenName"": ""Fluffy"" }] + } + ], + ""address"": { ""state"": ""WA"", ""county"": ""King"", ""city"": ""seattle"" }, + ""creationDate"": 1431620472, + ""isRegistered"": true, + ""_rid"": ""0fomAIxnukU1AQAAAAAAAA=="" + }"); + + private static readonly CosmosObject WakefieldFamily = CosmosObject.Parse(@" + { + ""id"": ""WakefieldFamily"", + ""parents"": [ + { ""familyName"": ""Wakefield"", ""givenName"": ""Robin"" }, + { ""familyName"": ""Miller"", ""givenName"": ""Ben"" } + ], + ""children"": [ + { + ""familyName"": ""Merriam"", + ""givenName"": ""Jesse"", + ""gender"": ""female"", ""grade"": 1, + ""pets"": [ + { ""givenName"": ""Goofy"" }, + { ""givenName"": ""Shadow"" } + ] + }, + { + ""familyName"": ""Miller"", + ""givenName"": ""Lisa"", + ""gender"": ""female"", + ""grade"": 8 } + ], + ""address"": { ""state"": ""NY"", ""county"": ""Manhattan"", ""city"": ""NY"" }, + ""creationDate"": 1431620462, + ""isRegistered"": false, + ""_rid"": ""0fomAIxnukU1AQAAAAAAAB=="" + }"); + + private static readonly CosmosElement[] Documents = new CosmosElement[] + { + AndersenFamily, + WakefieldFamily, + }; + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs index 9de85f9f7e..8eb72cac25 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using System; + using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; @@ -98,6 +99,11 @@ public async Task ContainerContractTest() } } }, + // ComputedProperties = new Collection + // { + // { new ComputedProperty{ Name = "lowerName", Query = "SELECT VALUE LOWER(c.Name) FROM c" } }, + // { new ComputedProperty{ Name = "fullName", Query = "SELECT VALUE CONCAT(c.Name, ' ', c.LastName) FROM c" } } + // }, ClientEncryptionPolicy = new ClientEncryptionPolicy(paths) }; @@ -140,6 +146,129 @@ public async Task ContainerContractTest() Assert.IsTrue(responseProperties.ClientEncryptionPolicy.PolicyFormatVersion <= 2); ClientEncryptionIncludedPath clientEncryptionIncludedPath = responseProperties.ClientEncryptionPolicy.IncludedPaths.First(); Assert.IsTrue(this.VerifyClientEncryptionIncludedPath(clientEncryptionIncludedPath1, clientEncryptionIncludedPath)); + + ComputedPropertyComparer.AssertAreEqual(containerProperties.ComputedProperties, responseProperties.ComputedProperties); + ComputedPropertyComparer.AssertAreEqual(containerProperties.ComputedProperties, deserialziedTest.ComputedProperties); + } + + [Ignore] + [TestMethod] + public async Task ContainerNegativeComputedPropertyTest() + { + string query = "SELECT VALUE LOWER(c.name) FROM c"; + var variations = new[] + { + new + { + ComputedProperties = new Collection + { + new ComputedProperty {Name = "lowerName", Query = @"SELECT VALUE LOWER(c.name) FROM c"}, + new ComputedProperty {Name = "lowerName", Query = @"SELECT VALUE LOWER(c.lastName) FROM c"} + }, + Error = @"""Errors"":[""Computed property name 'lowerName' cannot be used in multiple definitions.""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Query = query } }, + Error = @"""Errors"":[""One of the specified inputs is invalid""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Name = "", Query = query } }, + Error = @"""Errors"":[""Computed property 'name' is either empty or unspecified.""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Name = "lowerName" } }, + Error = @"""Errors"":[""One of the specified inputs is invalid""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Name = "lowerName", Query = "" } }, + Error = @"""Errors"":[""Computed property 'query' is either empty or unspecified.""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Name = "id", Query = query } }, + Error = @"""Errors"":[""The system property name 'id' cannot be used as a computed property name.""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty { Name = "spatial", Query = query } }, + Error = @"""Errors"":[""Computed property 'spatial' at index (0) has a spatial index. Remove the spatial index on this path.""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty {Name = "lowerName", Query = @"SELECT LOWER(c.name) FROM c"} }, + Error = @"""Errors"":[""Required VALUE expression missing from computed property query 'SELECT LOWER(c.name) FROM c' at index (0).""]" + }, + new + { + ComputedProperties = new Collection{ new ComputedProperty {Name = "lowerName", Query = @"SELECT LOWER(c.name) FROM r"} }, + Error = @"""Errors"":[""Computed property at index (0) has a malformed query: 'SELECT LOWER(c.name) FROM r' Error details: '{\""errors\"":[{\""severity\"":\""Error\"",\""code\"":2001,\""message\"":\""Identifier 'c' could not be resolved.\""}]}'""]" + }, + }; + + IndexingPolicy indexingPolicy = new IndexingPolicy + { + SpatialIndexes = new Collection + { + new SpatialPath + { + Path = "/spatial/*", + SpatialTypes = new Collection() + { + Cosmos.SpatialType.LineString, + Cosmos.SpatialType.MultiPolygon, + Cosmos.SpatialType.Point, + Cosmos.SpatialType.Polygon, + } + } + } + }; + + // Create + foreach (var variation in variations) + { + ContainerProperties containerProperties = new ContainerProperties(Guid.NewGuid().ToString(), "/users") + { + IndexingPolicy = indexingPolicy, + GeospatialConfig = new GeospatialConfig(GeospatialType.Geography), + ComputedProperties = variation.ComputedProperties + }; + + try + { + ContainerResponse response = await this.database.CreateContainerAsync(containerProperties); + Assert.Fail($@"Computed Property '{variation.ComputedProperties.Last().Name}' Query '{variation.ComputedProperties.Last().Query}' was expected to fail with error '{variation.Error}'."); + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.BadRequest) + { + Assert.IsTrue(ce.Message.Contains(variation.Error), $"Message expected to contain:'{variation.Error}'{Environment.NewLine}Actual Message: '{ce.Message}'"); + } + } + + // Replace + Container containerToReplace = await this.database.CreateContainerAsync(new ContainerProperties(Guid.NewGuid().ToString(), "/users")); + foreach (var variation in variations) + { + ContainerProperties containerProperties = new ContainerProperties(Guid.NewGuid().ToString(), "/users") + { + IndexingPolicy = indexingPolicy, + GeospatialConfig = new GeospatialConfig(GeospatialType.Geography), + ComputedProperties = variation.ComputedProperties + }; + + try + { + ContainerResponse response = await containerToReplace.ReplaceContainerAsync(containerProperties); + Assert.Fail($@"Computed Property '{variation.ComputedProperties.Last().Name}' Query '{variation.ComputedProperties.Last().Query}' was expected to fail with error '{variation.Error}'."); + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.BadRequest) + { + Assert.IsTrue(ce.Message.Contains(variation.Error), $"Message expected to contain:'{variation.Error}'{Environment.NewLine}Actual Message: '{ce.Message}'"); + } + } } [TestMethod] @@ -230,6 +359,17 @@ public async Task ContainerMigrationTest() SpatialTypes = new Collection() { SpatialType.Point } }); + // List computedProperties = new List + // { + // new ComputedProperty() { Name = "lowerName", Query = "SELECT VALUE LOWER(c.name) FROM c" }, + // new ComputedProperty() { Name = "estimatedTax", Query = "SELECT VALUE c.salary * 0.2 FROM c" } + // }; + + // foreach (ComputedProperty computedProperty in computedProperties) + // { + // containerProperties.ComputedProperties.Add(computedProperty); + // } + ContainerProperties propertiesAfterReplace = await container.ReplaceContainerAsync(containerProperties); Assert.AreEqual(0, propertiesAfterReplace.IndexingPolicy.IncludedPaths.First().Indexes.Count); Assert.AreEqual(1, propertiesAfterReplace.IndexingPolicy.CompositeIndexes.Count); @@ -242,6 +382,8 @@ public async Task ContainerMigrationTest() Assert.AreEqual(1, propertiesAfterReplace.IndexingPolicy.SpatialIndexes.Count); Assert.AreEqual("/address/test/*", propertiesAfterReplace.IndexingPolicy.SpatialIndexes.First().Path); + + ComputedPropertyComparer.AssertAreEqual(containerProperties.ComputedProperties, propertiesAfterReplace.ComputedProperties); } [TestMethod] @@ -449,6 +591,52 @@ await this.database.DefineContainer(containerName, partitionKeyPath) Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode); } + [Ignore] + [TestMethod] + public async Task WithComputedProperties() + { + string containerName = Guid.NewGuid().ToString(); + string partitionKeyPath = "/users"; + + var definitions = new[] + { + new { Name = "lowerName", Query = "SELECT VALUE LOWER(c.name) FROM c" }, + new { Name = "estimatedTax", Query = "SELECT VALUE c.salary * 0.2 FROM c" } + }; + ContainerResponse containerResponse = + await this.database.DefineContainer(containerName, partitionKeyPath) + .WithComputedProperties() + .WithComputedProperty(definitions[0].Name, definitions[0].Query) + .WithComputedProperty(definitions[1].Name, definitions[1].Query) + .Attach() + .CreateAsync(); + + Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); + Assert.AreEqual(containerName, containerResponse.Resource.Id); + Assert.AreEqual(partitionKeyPath, containerResponse.Resource.PartitionKey.Paths.First()); + + Assert.AreEqual(2, containerResponse.Resource.ComputedProperties.Count); + Assert.AreEqual(definitions[0].Name, containerResponse.Resource.ComputedProperties[0].Name); + Assert.AreEqual(definitions[0].Query, containerResponse.Resource.ComputedProperties[0].Query); + Assert.AreEqual(definitions[1].Name, containerResponse.Resource.ComputedProperties[1].Name); + Assert.AreEqual(definitions[1].Query, containerResponse.Resource.ComputedProperties[1].Query); + + Container container = containerResponse; + containerResponse = await container.ReadContainerAsync(); + Assert.AreEqual(HttpStatusCode.OK, containerResponse.StatusCode); + Assert.AreEqual(containerName, containerResponse.Resource.Id); + Assert.AreEqual(partitionKeyPath, containerResponse.Resource.PartitionKey.Paths.First()); + + Assert.AreEqual(2, containerResponse.Resource.ComputedProperties.Count); + Assert.AreEqual(definitions[0].Name, containerResponse.Resource.ComputedProperties[0].Name); + Assert.AreEqual(definitions[0].Query, containerResponse.Resource.ComputedProperties[0].Query); + Assert.AreEqual(definitions[1].Name, containerResponse.Resource.ComputedProperties[1].Name); + Assert.AreEqual(definitions[1].Query, containerResponse.Resource.ComputedProperties[1].Query); + + containerResponse = await containerResponse.Container.DeleteContainerAsync(); + Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode); + } + [TestMethod] public async Task ThroughputTest() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 8a3d326d50..ab29c95bf0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -253,6 +253,59 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.ComputedProperty;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.String get_Name()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Name();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Query()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Query();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Name[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"name\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Name;CanRead:True;CanWrite:True;System.String get_Name();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Name(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Query[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"query\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Query;CanRead:True;CanWrite:True;System.String get_Query();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Query(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_Name(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Name(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Query(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Query(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Container;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -284,10 +337,27 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedPolicy get_ChangeFeedPolicy();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty] ComputedProperties[Newtonsoft.Json.JsonIgnoreAttribute()]": { + "Type": "Property", + "Attributes": [ + "JsonIgnoreAttribute" + ], + "MethodInfo": "System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty] ComputedProperties;CanRead:True;CanWrite:True;System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty] get_ComputedProperties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ComputedProperties(System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty] get_ComputedProperties()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty] get_ComputedProperties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_ChangeFeedPolicy(Microsoft.Azure.Cosmos.ChangeFeedPolicy)": { "Type": "Method", "Attributes": [], "MethodInfo": "Void set_ChangeFeedPolicy(Microsoft.Azure.Cosmos.ChangeFeedPolicy);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_ComputedProperties(System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty])": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void set_ComputedProperties(System.Collections.ObjectModel.Collection`1[Microsoft.Azure.Cosmos.ComputedProperty]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} @@ -328,6 +398,22 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.Fluent.ComputedPropertiesDefinition`1;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:True;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.Fluent.ComputedPropertiesDefinition`1[T] WithComputedProperty(System.String, System.String)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.ComputedPropertiesDefinition`1[T] WithComputedProperty(System.String, System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "T Attach()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "T Attach();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Fluent.ContainerBuilder;Microsoft.Azure.Cosmos.Fluent.ContainerDefinition`1[[Microsoft.Azure.Cosmos.Fluent.ContainerBuilder, ]];IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -339,6 +425,17 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.Fluent.ContainerDefinition`1;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:True;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.Fluent.ComputedPropertiesDefinition`1[T] WithComputedProperties()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.ComputedPropertiesDefinition`1[T] WithComputedProperties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs index 865bb71d18..bda132d6a3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs @@ -33,6 +33,9 @@ public void DefaultIncludesPopulated() Cosmos.IncludedPath defaultEntry = containerSettings.IndexingPolicy.IncludedPaths[0]; Assert.AreEqual(Cosmos.IndexingPolicy.DefaultPath, defaultEntry.Path); Assert.AreEqual(0, defaultEntry.Indexes.Count); + + Assert.IsNotNull(containerSettings.ComputedProperties); + Assert.AreEqual(0, containerSettings.ComputedProperties.Count); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs index 58361f89bb..d94aed92a4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Fluent/ContainerDefinitionForCreateTests.cs @@ -251,6 +251,56 @@ await containerFluentDefinitionForCreate It.IsAny()), Times.Once); } + [Ignore] + [TestMethod] + public async Task WithComputedProperties() + { + Mock mockContainerResponse = new Mock(MockBehavior.Strict); + Mock mockDatabase = new Mock(MockBehavior.Strict); + Mock mockClient = new Mock(MockBehavior.Strict); + mockDatabase.Setup(m => m.Client).Returns(mockClient.Object); + mockDatabase + .Setup(c => c.CreateContainerAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(mockContainerResponse.Object); + mockDatabase + .Setup(c => c.Id) + .Returns(Guid.NewGuid().ToString()); + + ContainerBuilder containerFluentDefinitionForCreate = new ContainerBuilder( + mockDatabase.Object, + containerName, + partitionKey); + + var definitions = new[] + { + new { Name = "lowerName", Query = "SELECT VALUE LOWER(c.name) FROM c" }, + new { Name = "estimatedTax", Query = "SELECT VALUE c.salary * 0.2 FROM c" } + }; + await containerFluentDefinitionForCreate + .WithComputedProperties() + .WithComputedProperty(definitions[0].Name, definitions[0].Query) + .WithComputedProperty(definitions[1].Name, definitions[1].Query) + .Attach() + .CreateAsync(); + + mockDatabase.Verify(c => c.CreateContainerAsync( + It.Is((settings) => + settings.ComputedProperties.Count == 2 && + definitions[0].Name.Equals(settings.ComputedProperties[0].Name) && + definitions[0].Query.Equals(settings.ComputedProperties[0].Query) && + definitions[1].Name.Equals(settings.ComputedProperties[1].Name) && + definitions[1].Query.Equals(settings.ComputedProperties[1].Query) + ), + It.IsAny(), + It.IsAny(), + It.IsAny()), + Times.Once); + } + [TestMethod] public async Task WithUniqueKey() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs index 239de170de..2e8df92318 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs @@ -339,7 +339,7 @@ public void AccountPropertiesDeserializeWithAdditionalDataTest() [TestMethod] public void ContainerPropertiesDeserializeWithAdditionalDataTest() { - string cosmosSerialized = "{\"indexingPolicy\":{\"automatic\":true,\"indexingMode\":\"Consistent\",\"additionalIndexPolicy\":\"indexpolicyvalue\",\"includedPaths\":[{\"path\":\"/included/path\",\"additionalIncludedPath\":\"includedPathValue\",\"indexes\":[]}],\"excludedPaths\":[{\"path\":\"/excluded/path\",\"additionalExcludedPath\":\"excludedPathValue\"}],\"compositeIndexes\":[[{\"path\":\"/composite/path\",\"additionalCompositeIndex\":\"compositeIndexValue\",\"order\":\"ascending\"}]],\"spatialIndexes\":[{\"path\":\"/spatial/path\",\"additionalSpatialIndexes\":\"spatialIndexValue\",\"types\":[]}]},\"geospatialConfig\":{\"type\":\"Geography\",\"additionalGeospatialConfig\":\"geospatialConfigValue\"},\"uniqueKeyPolicy\":{\"additionalUniqueKeyPolicy\":\"uniqueKeyPolicyValue\",\"uniqueKeys\":[{\"paths\":[\"/unique/key/path/1\",\"/unique/key/path/2\"]}]},\"conflictResolutionPolicy\":{\"mode\":\"LastWriterWins\",\"additionalConflictResolutionPolicy\":\"conflictResolutionValue\"},\"clientEncryptionPolicy\":{\"includedPaths\":[{\"path\":\"/path\",\"clientEncryptionKeyId\":\"clientEncryptionKeyId\",\"encryptionType\":\"Randomized\",\"additionalIncludedPath\":\"includedPathValue\",\"encryptionAlgorithm\":\"AEAD_AES_256_CBC_HMAC_SHA256\"}],\"policyFormatVersion\":1,\"additionalEncryptionPolicy\":\"clientEncryptionpolicyValue\"},\"id\":\"2a9f501b-6948-4795-8fd1-797defb5c466\",\"partitionKey\":{\"paths\":[],\"kind\":\"Hash\"}}"; + string cosmosSerialized = "{\"indexingPolicy\":{\"automatic\":true,\"indexingMode\":\"Consistent\",\"additionalIndexPolicy\":\"indexpolicyvalue\",\"includedPaths\":[{\"path\":\"/included/path\",\"additionalIncludedPath\":\"includedPathValue\",\"indexes\":[]}],\"excludedPaths\":[{\"path\":\"/excluded/path\",\"additionalExcludedPath\":\"excludedPathValue\"}],\"compositeIndexes\":[[{\"path\":\"/composite/path\",\"additionalCompositeIndex\":\"compositeIndexValue\",\"order\":\"ascending\"}]],\"spatialIndexes\":[{\"path\":\"/spatial/path\",\"additionalSpatialIndexes\":\"spatialIndexValue\",\"types\":[]}]},\"computedProperties\":[{\"name\":\"lowerName\",\"query\":\"SELECT VALUE LOWER(c.name) FROM c\"},{\"name\":\"estimatedTax\",\"query\":\"SELECT VALUE c.salary * 0.2 FROM c\"}],\"geospatialConfig\":{\"type\":\"Geography\",\"additionalGeospatialConfig\":\"geospatialConfigValue\"},\"uniqueKeyPolicy\":{\"additionalUniqueKeyPolicy\":\"uniqueKeyPolicyValue\",\"uniqueKeys\":[{\"paths\":[\"/unique/key/path/1\",\"/unique/key/path/2\"]}]},\"conflictResolutionPolicy\":{\"mode\":\"LastWriterWins\",\"additionalConflictResolutionPolicy\":\"conflictResolutionValue\"},\"clientEncryptionPolicy\":{\"includedPaths\":[{\"path\":\"/path\",\"clientEncryptionKeyId\":\"clientEncryptionKeyId\",\"encryptionType\":\"Randomized\",\"additionalIncludedPath\":\"includedPathValue\",\"encryptionAlgorithm\":\"AEAD_AES_256_CBC_HMAC_SHA256\"}],\"policyFormatVersion\":1,\"additionalEncryptionPolicy\":\"clientEncryptionpolicyValue\"},\"id\":\"2a9f501b-6948-4795-8fd1-797defb5c466\",\"partitionKey\":{\"paths\":[],\"kind\":\"Hash\"}}"; JObject complexObject = JObject.FromObject(new { id = 1, name = new { fname = "fname", lname = "lname" } }); @@ -351,43 +351,49 @@ public void ContainerPropertiesDeserializeWithAdditionalDataTest() // Serialized string cosmosSerialized = SettingsContractTests.CosmosSerialize(jobject); - ContainerProperties containerDeserSettings = SettingsContractTests.CosmosDeserialize(cosmosSerialized); + ContainerProperties containerProperties = SettingsContractTests.CosmosDeserialize(cosmosSerialized); - Assert.AreEqual("2a9f501b-6948-4795-8fd1-797defb5c466", containerDeserSettings.Id); + Assert.AreEqual("2a9f501b-6948-4795-8fd1-797defb5c466", containerProperties.Id); - Assert.AreEqual(2, containerDeserSettings.AdditionalProperties.Count); - Assert.AreEqual("policy value", (string)containerDeserSettings.AdditionalProperties["simple string"]); - Assert.AreEqual(complexObject.ToString(), JObject.FromObject(containerDeserSettings.AdditionalProperties["complex object"]).ToString()); + Assert.AreEqual(2, containerProperties.AdditionalProperties.Count); + Assert.AreEqual("policy value", (string)containerProperties.AdditionalProperties["simple string"]); + Assert.AreEqual(complexObject.ToString(), JObject.FromObject(containerProperties.AdditionalProperties["complex object"]).ToString()); + + Assert.AreEqual(1, containerProperties.IndexingPolicy.AdditionalProperties.Count); + Assert.AreEqual("indexpolicyvalue", containerProperties.IndexingPolicy.AdditionalProperties["additionalIndexPolicy"]); - Assert.AreEqual(1, containerDeserSettings.IndexingPolicy.AdditionalProperties.Count); - Assert.AreEqual("indexpolicyvalue", containerDeserSettings.IndexingPolicy.AdditionalProperties["additionalIndexPolicy"]); + Assert.AreEqual(1, containerProperties.IndexingPolicy.SpatialIndexes[0].AdditionalProperties.Count); + Assert.AreEqual("spatialIndexValue", containerProperties.IndexingPolicy.SpatialIndexes[0].AdditionalProperties["additionalSpatialIndexes"]); - Assert.AreEqual(1, containerDeserSettings.IndexingPolicy.SpatialIndexes[0].AdditionalProperties.Count); - Assert.AreEqual("spatialIndexValue", containerDeserSettings.IndexingPolicy.SpatialIndexes[0].AdditionalProperties["additionalSpatialIndexes"]); + Assert.AreEqual(1, containerProperties.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties.Count); + Assert.AreEqual("compositeIndexValue", containerProperties.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties["additionalCompositeIndex"]); - Assert.AreEqual(1, containerDeserSettings.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties.Count); - Assert.AreEqual("compositeIndexValue", containerDeserSettings.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties["additionalCompositeIndex"]); + Assert.AreEqual(1, containerProperties.IndexingPolicy.IncludedPaths[0].AdditionalProperties.Count); + Assert.AreEqual("includedPathValue", containerProperties.IndexingPolicy.IncludedPaths[0].AdditionalProperties["additionalIncludedPath"]); - Assert.AreEqual(1, containerDeserSettings.IndexingPolicy.IncludedPaths[0].AdditionalProperties.Count); - Assert.AreEqual("includedPathValue", containerDeserSettings.IndexingPolicy.IncludedPaths[0].AdditionalProperties["additionalIncludedPath"]); + Assert.AreEqual(1, containerProperties.IndexingPolicy.ExcludedPaths[0].AdditionalProperties.Count); + Assert.AreEqual("excludedPathValue", containerProperties.IndexingPolicy.ExcludedPaths[0].AdditionalProperties["additionalExcludedPath"]); - Assert.AreEqual(1, containerDeserSettings.IndexingPolicy.ExcludedPaths[0].AdditionalProperties.Count); - Assert.AreEqual("excludedPathValue", containerDeserSettings.IndexingPolicy.ExcludedPaths[0].AdditionalProperties["additionalExcludedPath"]); + Assert.AreEqual(1, containerProperties.GeospatialConfig.AdditionalProperties.Count); + Assert.AreEqual("geospatialConfigValue", containerProperties.GeospatialConfig.AdditionalProperties["additionalGeospatialConfig"]); - Assert.AreEqual(1, containerDeserSettings.GeospatialConfig.AdditionalProperties.Count); - Assert.AreEqual("geospatialConfigValue", containerDeserSettings.GeospatialConfig.AdditionalProperties["additionalGeospatialConfig"]); + Assert.AreEqual(1, containerProperties.UniqueKeyPolicy.AdditionalProperties.Count); + Assert.AreEqual("uniqueKeyPolicyValue", containerProperties.UniqueKeyPolicy.AdditionalProperties["additionalUniqueKeyPolicy"]); - Assert.AreEqual(1, containerDeserSettings.UniqueKeyPolicy.AdditionalProperties.Count); - Assert.AreEqual("uniqueKeyPolicyValue", containerDeserSettings.UniqueKeyPolicy.AdditionalProperties["additionalUniqueKeyPolicy"]); + Assert.AreEqual(1, containerProperties.ConflictResolutionPolicy.AdditionalProperties.Count); + Assert.AreEqual("conflictResolutionValue", containerProperties.ConflictResolutionPolicy.AdditionalProperties["additionalConflictResolutionPolicy"]); - Assert.AreEqual(1, containerDeserSettings.ConflictResolutionPolicy.AdditionalProperties.Count); - Assert.AreEqual("conflictResolutionValue", containerDeserSettings.ConflictResolutionPolicy.AdditionalProperties["additionalConflictResolutionPolicy"]); + Assert.AreEqual(1, containerProperties.ClientEncryptionPolicy.AdditionalProperties.Count); + Assert.AreEqual("clientEncryptionpolicyValue", containerProperties.ClientEncryptionPolicy.AdditionalProperties["additionalEncryptionPolicy"]); - Assert.AreEqual(1, containerDeserSettings.ClientEncryptionPolicy.AdditionalProperties.Count); - Assert.AreEqual("clientEncryptionpolicyValue", containerDeserSettings.ClientEncryptionPolicy.AdditionalProperties["additionalEncryptionPolicy"]); + Assert.AreEqual(1, containerProperties.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties.Count); + Assert.AreEqual("includedPathValue", containerProperties.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties["additionalIncludedPath"]); - Assert.AreEqual(1, containerDeserSettings.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties.Count); - Assert.AreEqual("includedPathValue", containerDeserSettings.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties["additionalIncludedPath"]); + Assert.AreEqual(2, containerProperties.ComputedProperties.Count); + Assert.AreEqual("lowerName", containerProperties.ComputedProperties[0].Name); + Assert.AreEqual("SELECT VALUE LOWER(c.name) FROM c", containerProperties.ComputedProperties[0].Query); + Assert.AreEqual("estimatedTax", containerProperties.ComputedProperties[1].Name); + Assert.AreEqual("SELECT VALUE c.salary * 0.2 FROM c", containerProperties.ComputedProperties[1].Query); } [TestMethod] @@ -724,6 +730,7 @@ public void ContainerSettingsDefaults() "TimeToLivePropertyPath", "PartitionKeyPath", "PartitionKeyDefinitionVersion", + "ComputedProperties", "ConflictResolutionPolicy", "ChangeFeedPolicy", "ClientEncryptionPolicy", @@ -762,6 +769,10 @@ public void ContainerSettingsDefaults() Assert.IsNotNull(cosmosContainerSettings.IndexingPolicy.IncludedPaths); Assert.IsTrue(object.ReferenceEquals(cosmosContainerSettings.IndexingPolicy.IncludedPaths, cosmosContainerSettings.IndexingPolicy.IncludedPaths)); + Assert.IsNotNull(cosmosContainerSettings.ComputedProperties); + Assert.AreEqual(0, cosmosContainerSettings.ComputedProperties.Count); + Assert.IsTrue(object.ReferenceEquals(cosmosContainerSettings.ComputedProperties, cosmosContainerSettings.ComputedProperties)); + Cosmos.IncludedPath ip = new Cosmos.IncludedPath(); Assert.IsNotNull(ip.Indexes); From 033e883d2f0ae6187e7227d9b86fe6539ca3ee58 Mon Sep 17 00:00:00 2001 From: Justine Cocchi Date: Fri, 5 May 2023 07:47:06 -0700 Subject: [PATCH 108/337] [Internal] Samples: Adds OpenTelemetry and Application Insights samples (#3818) * add opentelemetry and application insights samples * address pr comments --- .../ApplicationInsights/AppSettings.json | 5 + .../ApplicationInsights.csproj | 25 ++++ .../Usage/ApplicationInsights/Program.cs | 118 +++++++++++++++ .../Usage/Cosmos.Samples.Usage.sln | 12 ++ .../Usage/OpenTelemetry/AppSettings.json | 10 ++ .../Usage/OpenTelemetry/OpenTelemetry.csproj | 28 ++++ .../Usage/OpenTelemetry/Program.cs | 138 ++++++++++++++++++ 7 files changed, 336 insertions(+) create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/AppSettings.json create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/AppSettings.json b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/AppSettings.json new file mode 100644 index 0000000000..028030099b --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/AppSettings.json @@ -0,0 +1,5 @@ +{ + "CosmosDBEndPointUrl": "https://localhost:8081", + "CosmosDBAuthorizationKey": "Super secret key", + "ApplicationInsightsConnectionString": "Super secret connection string" +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj new file mode 100644 index 0000000000..cee6d0a6e3 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj @@ -0,0 +1,25 @@ + + + + Exe + net6.0 + Cosmos.Samples.ApplicationInsights + Cosmos.Samples.ApplicationInsights + latest + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs new file mode 100644 index 0000000000..b4f55cd65f --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs @@ -0,0 +1,118 @@ +namespace Cosmos.Samples.ApplicationInsights +{ + using System; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.ApplicationInsights; + using Microsoft.ApplicationInsights.WorkerService; + using Microsoft.Extensions.Logging.ApplicationInsights; + + internal class Program + { + private static readonly string databaseName = "samples"; + private static readonly string containerName = "ai-sample"; + + private static TelemetryClient? _telemetryClient; + + static async Task Main() + { + try + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddJsonFile("AppSettings.json") + .Build(); + + string endpoint = configuration["CosmosDBEndPointUrl"]; + if (string.IsNullOrEmpty(endpoint)) + { + throw new ArgumentNullException("Please specify a valid CosmosDBEndPointUrl in the appSettings.json"); + } + + string authKey = configuration["CosmosDBAuthorizationKey"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) + { + throw new ArgumentException("Please specify a valid CosmosDBAuthorizationKey in the appSettings.json"); + } + + string aiConnectionString = configuration["ApplicationInsightsConnectionString"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret connection string")) + { + throw new ArgumentException("Please specify a valid ApplicationInsightsConnectionString in the appSettings.json"); + } + + // + IServiceCollection services = new ServiceCollection(); + services.AddApplicationInsightsTelemetryWorkerService((ApplicationInsightsServiceOptions options) => options.ConnectionString = aiConnectionString); + + IServiceProvider serviceProvider = services.BuildServiceProvider(); + _telemetryClient = serviceProvider.GetRequiredService(); + // + + CosmosClientOptions options = new CosmosClientOptions() + { + IsDistributedTracingEnabled = true // Defaults to true, set to false to disable + }; + using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + await Program.RunCrudDemo(container); + } + } + finally + { + // Explicitly calling Flush() followed by sleep is required for Application Insights logging in console apps to ensure that telemetry is sent to the back-end even if application terminates. + _telemetryClient?.Flush(); + await Task.Delay(5000); + + Console.WriteLine("End of demo."); + } + } + + public static async Task RunCrudDemo(Container container) + { + // Any operations will automatically generate telemetry + + for (int i = 1; i <= 5; i++) + { + await container.CreateItemAsync(new Item { Id = $"{i}", Status = "new" }, new PartitionKey($"{i}")); + Console.WriteLine($"Created document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReadItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Read document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReplaceItemAsync(new Item { Id = $"{i}", Status = "updated" }, $"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Updated document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.DeleteItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Deleted document with id: {i}"); + } + } + } + + internal class Item + { + [JsonProperty("id")] + public string Id { get; set; } + + public string Status { get; set; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln index de1e1f4731..999b48d928 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln @@ -51,6 +51,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFPullModelAllVersionsAndDe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFPullModelLatestVersionMode", "CFPullModelLatestVersionMode\CFPullModelLatestVersionMode.csproj", "{985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry", "OpenTelemetry\OpenTelemetry.csproj", "{C6EF6948-C085-4013-A21F-99303ECBA7A9}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationInsights", "ApplicationInsights\ApplicationInsights.csproj", "{55149A3C-A263-4EE5-AD2D-02FE9AC4D291}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -153,6 +157,14 @@ Global {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Debug|Any CPU.Build.0 = Debug|Any CPU {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Release|Any CPU.ActiveCfg = Release|Any CPU {985B0E0A-D480-4C3C-A1FC-589F2EC4BBF6}.Release|Any CPU.Build.0 = Release|Any CPU + {C6EF6948-C085-4013-A21F-99303ECBA7A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C6EF6948-C085-4013-A21F-99303ECBA7A9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C6EF6948-C085-4013-A21F-99303ECBA7A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C6EF6948-C085-4013-A21F-99303ECBA7A9}.Release|Any CPU.Build.0 = Release|Any CPU + {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json new file mode 100644 index 0000000000..1ea1245434 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Azure-Cosmos-Operation-Request-Diagnostics": "Information" + } + }, + "CosmosDBEndPointUrl": "https://localhost:8081", + "CosmosDBAuthorizationKey": "Super secret key", + "ApplicationInsightsConnectionString": "Super secret connection string" +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj new file mode 100644 index 0000000000..4dd1171328 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj @@ -0,0 +1,28 @@ + + + + Exe + net6.0 + Cosmos.Samples.OpenTelemetry + Cosmos.Samples.OpenTelemetry + latest + + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs new file mode 100644 index 0000000000..d799731f1e --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs @@ -0,0 +1,138 @@ +namespace Cosmos.Samples.OpenTelemetry +{ + using global::OpenTelemetry; + using global::OpenTelemetry.Trace; + using global::OpenTelemetry.Resources; + using System; + using System.Threading.Tasks; + using Newtonsoft.Json; + using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Azure; + using Microsoft.Extensions.Logging; + using Microsoft.Extensions.Configuration; + using Azure.Monitor.OpenTelemetry.Exporter; + + internal class Program + { + private static readonly string databaseName = "samples"; + private static readonly string containerName = "otel-sample"; + private static readonly string serviceName = "MySampleService"; + + private static TracerProvider? _traceProvider; + + static async Task Main() + { + try + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddJsonFile("AppSettings.json") + .Build(); + + string endpoint = configuration["CosmosDBEndPointUrl"]; + if (string.IsNullOrEmpty(endpoint)) + { + throw new ArgumentNullException("Please specify a valid CosmosDBEndPointUrl in the appSettings.json"); + } + + string authKey = configuration["CosmosDBAuthorizationKey"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) + { + throw new ArgumentException("Please specify a valid CosmosDBAuthorizationKey in the appSettings.json"); + } + + string aiConnectionString = configuration["ApplicationInsightsConnectionString"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret connection string")) + { + throw new ArgumentException("Please specify a valid ApplicationInsightsConnectionString in the appSettings.json"); + } + + // + ResourceBuilder resource = ResourceBuilder.CreateDefault().AddService( + serviceName: serviceName, + serviceVersion: "1.0.0"); + + // Set up logging to forward logs to chosen exporter + using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddOpenTelemetry(options => + { + options.IncludeFormattedMessage = true; + options.SetResourceBuilder(resource); + options.AddAzureMonitorLogExporter(o => o.ConnectionString = aiConnectionString); // Set up exporter of your choice + })); + + AzureEventSourceLogForwarder logforwader = new AzureEventSourceLogForwarder(loggerFactory); + logforwader.Start(); + + // Configure OpenTelemetry trace provider + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); + _traceProvider = Sdk.CreateTracerProviderBuilder() + .AddSource("Azure.Cosmos.Operation") // Cosmos DB source for operation level telemetry + .AddAzureMonitorTraceExporter(o => o.ConnectionString = aiConnectionString) // Set up exporter of your choice + .SetResourceBuilder(resource) + .Build(); + // + + CosmosClientOptions options = new CosmosClientOptions() + { + IsDistributedTracingEnabled = true // Defaults to true, set to false to disable + }; + using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + await Program.RunCrudDemo(container); + } + + } + finally + { + _traceProvider?.Dispose(); + // Sleep is required for logging in console apps to ensure that telemetry is sent to the back-end even if application terminates. + await Task.Delay(5000); + + Console.WriteLine("End of demo."); + } + } + + public static async Task RunCrudDemo(Container container) + { + // Any operations will automatically generate telemetry + + for(int i = 1; i <= 5; i++) + { + await container.CreateItemAsync(new Item { Id = $"{i}", Status = "new" }, new PartitionKey($"{i}")); + Console.WriteLine($"Created document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReadItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Read document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReplaceItemAsync(new Item { Id = $"{i}", Status = "updated" }, $"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Updated document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.DeleteItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Deleted document with id: {i}"); + } + } + } + + internal class Item + { + [JsonProperty("id")] + public string Id { get; set; } + + public string Status { get; set; } + } +} \ No newline at end of file From 0c158656a8a9a42fafeda52757360698fbfa04ea Mon Sep 17 00:00:00 2001 From: Erik O'Leary <969938+onionhammer@users.noreply.github.com> Date: Tue, 9 May 2023 10:45:01 -0500 Subject: [PATCH 109/337] [Internal] Query: Added custom serializer coverage tests to ExpressionToSQL.cs (#3722) * Ensure enum as string is preserved for custom serializer * Failing test * Added failing tests * Updated requested names * Ignore result of test for now * Added additional comment on why the test is ignored * Replaced with sample code * Remove ignore attribute from tests, documented misbehavior for future use * Updated comment --------- Co-authored-by: leminh98 --- .../Linq/CosmosLinqJsonConverterTests.cs | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs index e4f90f1957..ca2e12c8da 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs @@ -6,7 +6,10 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; using System.Globalization; + using System.IO; + using System.Linq; using System.Linq.Expressions; + using global::Azure.Core.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -30,6 +33,104 @@ public void DateTimeKindIsPreservedTest() Assert.AreEqual("(a[\"StartDate\"] <= \"2022-05-26\")", sql); } + [TestMethod] + public void EnumIsPreservedAsINTest() + { + // Arrange + CosmosLinqSerializerOptions options = new() + { + //CustomCosmosSerializer = new TestCustomJsonSerializer() + }; + + // Act + TestEnum[] values = new[] { TestEnum.One, TestEnum.Two }; + Expression> expr = a => values.Contains(a.Value); + + string sql = SqlTranslator.TranslateExpression(expr.Body, options); + + // Assert + // Assert.AreEqual("(a[\"Value\"] IN (\"One\", \"Two\"))", sql); // <- TODO - Desired Behavior with CustomSerializer + Assert.AreEqual("(a[\"Value\"] IN (0, 1))", sql); // <- Actual behavior, with ability to set custom serializor reverted + } + + [TestMethod] + public void EnumIsPreservedAsEQUALSTest() + { + // Arrange + CosmosLinqSerializerOptions options = new() + { + // CustomCosmosSerializer = new TestCustomJsonSerializer() + }; + + // Act + TestEnum statusValue = TestEnum.One; + Expression> expr = a => a.Value == statusValue; + + string sql = SqlTranslator.TranslateExpression(expr.Body, options); + + // Assert + // Assert.AreEqual("(a[\"Value\"] = \"One\")", sql); // <- THIS is the correct value, if we are able to use the custom serializer + Assert.AreEqual("(a[\"Value\"] = 0)", sql); // <- THIS is the current mis-behavior of the SDK + } + + [TestMethod] + public void EnumIsPreservedAsEXPRESSIONTest() + { + // Arrange + CosmosLinqSerializerOptions options = new() + { + // CustomCosmosSerializer = new TestCustomJsonSerializer() + }; + + // Act + + // Get status constant + ConstantExpression status = Expression.Constant(TestEnum.One); + + // Get member access expression + ParameterExpression arg = Expression.Parameter(typeof(TestEnumNewtonsoftDocument), "a"); + + // Access the value property + MemberExpression docValueExpression = Expression.MakeMemberAccess( + arg, + typeof(TestEnumNewtonsoftDocument).GetProperty(nameof(TestEnumNewtonsoftDocument.Value))! + ); + + // Create comparison expression + BinaryExpression expression = Expression.Equal( + docValueExpression, + status + ); + + // Create lambda expression + Expression> lambda = + Expression.Lambda>(expression, arg); + + string sql = SqlTranslator.TranslateExpression(lambda.Body, options); + + // Assert + Assert.AreEqual("(a[\"Value\"] = \"One\")", sql); + } + + enum TestEnum + { + One, + Two, + Three, + } + + class TestEnumDocument + { + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] // TODO: Remove this once we have the ability to use custom serializer for LINQ queries + public TestEnum Value { get; set; } + } + + class TestEnumNewtonsoftDocument + { + [JsonConverter(typeof(StringEnumConverter))] + public TestEnum Value { get; set; } + } + class TestDocument { [JsonConverter(typeof(DateJsonConverter))] @@ -50,5 +151,54 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } } + + /// + // See: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs + /// + class TestCustomJsonSerializer : CosmosSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public static readonly System.Text.Json.JsonSerializerOptions JsonOptions = new() + { + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, + PropertyNameCaseInsensitive = true, + Converters = { + new System.Text.Json.Serialization.JsonStringEnumConverter(), + } + }; + + public TestCustomJsonSerializer() + { + this.systemTextJsonSerializer = new JsonObjectSerializer(JsonOptions); + } + + public override T FromStream(Stream stream) + { + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream stream = new (); + + this.systemTextJsonSerializer.Serialize(stream, input, typeof(T), default); + stream.Position = 0; + return stream; + } + } } } From ade7e3410c0ffb78e2af815f5fe355c2047f3436 Mon Sep 17 00:00:00 2001 From: Erik O'Leary <969938+onionhammer@users.noreply.github.com> Date: Tue, 9 May 2023 12:30:29 -0500 Subject: [PATCH 110/337] Query: Added remaining Cosmos Type checking functions to CosmosLinqExtensions (#3724) * Added the remaining Cosmos Type checking functions to the CosmosLinqExtensions * Added comments requested * Updated comment * Updated baseline * Improve readability of dictionary initialization * Aligned with code style guide * Revert change to baseline * Executed update baseline script --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: leminh98 --- .../BuiltinFunctions/TypeCheckFunctions.cs | 59 ++++++--- .../src/Linq/CosmosLinqExtensions.cs | 99 ++++++++++++++- ...onBaselineTests.TestTypeCheckFunctions.xml | 117 ++++++++++++++++++ .../LinqTranslationBaselineTests.cs | 20 ++- .../Contracts/DotNetSDKAPI.json | 35 ++++++ 5 files changed, 311 insertions(+), 19 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/TypeCheckFunctions.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/TypeCheckFunctions.cs index 93c09d65ab..db875f3ae0 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/TypeCheckFunctions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/TypeCheckFunctions.cs @@ -18,33 +18,62 @@ static TypeCheckFunctions() { TypeCheckFunctionsDefinitions = new Dictionary { - { - "IsDefined", - new SqlBuiltinFunctionVisitor("IS_DEFINED", + [nameof(CosmosLinqExtensions.IsArray)] = new SqlBuiltinFunctionVisitor( + "IS_ARRAY", true, new List() { new Type[]{typeof(object)}, - }) - }, - { - "IsNull", - new SqlBuiltinFunctionVisitor("IS_NULL", + }), + [nameof(CosmosLinqExtensions.IsBool)] = new SqlBuiltinFunctionVisitor( + "IS_BOOL", true, new List() { new Type[]{typeof(object)}, - }) - }, - { - "IsPrimitive", - new SqlBuiltinFunctionVisitor("IS_PRIMITIVE", + }), + [nameof(CosmosLinqExtensions.IsDefined)] = new SqlBuiltinFunctionVisitor( + "IS_DEFINED", true, new List() { new Type[]{typeof(object)}, - }) - } + }), + [nameof(CosmosLinqExtensions.IsNull)] = new SqlBuiltinFunctionVisitor( + "IS_NULL", + true, + new List() + { + new Type[]{typeof(object)}, + }), + [nameof(CosmosLinqExtensions.IsNumber)] = new SqlBuiltinFunctionVisitor( + "IS_NUMBER", + true, + new List() + { + new Type[]{typeof(object)}, + }), + [nameof(CosmosLinqExtensions.IsObject)] = new SqlBuiltinFunctionVisitor( + "IS_OBJECT", + true, + new List() + { + new Type[]{typeof(object)}, + }), + [nameof(CosmosLinqExtensions.IsPrimitive)] = new SqlBuiltinFunctionVisitor( + "IS_PRIMITIVE", + true, + new List() + { + new Type[]{typeof(object)}, + }), + [nameof(CosmosLinqExtensions.IsString)] = new SqlBuiltinFunctionVisitor( + "IS_STRING", + true, + new List() + { + new Type[]{typeof(object)}, + }), }; } diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs index dc86de0cb6..6663f52673 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs @@ -20,6 +20,44 @@ namespace Microsoft.Azure.Cosmos.Linq /// public static class CosmosLinqExtensions { + /// + /// Returns a Boolean value indicating if the type of the specified expression is an array. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// Returns true if the type of the specified expression is an array; otherwise, false. + /// + /// + /// document.Names.IsArray()); + /// ]]> + /// + /// + public static bool IsArray(this object obj) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + + /// + /// Returns a Boolean value indicating if the type of the specified expression is a boolean. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// Returns true if the type of the specified expression is a boolean; otherwise, false. + /// + /// + /// document.IsRegistered.IsBool()); + /// ]]> + /// + /// + public static bool IsBool(this object obj) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + /// /// Determines if a certain property is defined or not. /// This method is to be used in LINQ expressions only and will be evaluated on server. @@ -52,12 +90,50 @@ public static bool IsDefined(this object obj) /// var isNullQuery = documents.Where(document => document.Name.IsNull()); /// ]]> /// - /// s> + /// public static bool IsNull(this object obj) { throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); } + /// + /// Returns a Boolean value indicating if the type of the specified expression is a number. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// Returns true if the type of the specified expression is a number; otherwise, false. + /// + /// + /// document.Age.IsNumber()); + /// ]]> + /// + /// + public static bool IsNumber(this object obj) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + + /// + /// Returns a Boolean value indicating if the type of the specified expression is an object. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// Returns true if the type of the specified expression is an object; otherwise, false. + /// + /// + /// document.Address.IsObject()); + /// ]]> + /// + /// + public static bool IsObject(this object obj) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + /// /// Determines if a certain property is of primitive JSON type. /// This method is to be used in LINQ expressions only and will be evaluated on server. @@ -74,12 +150,31 @@ public static bool IsNull(this object obj) /// var isPrimitiveQuery = documents.Where(document => document.Name.IsPrimitive()); /// ]]> /// - /// s> + /// public static bool IsPrimitive(this object obj) { throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); } + /// + /// Returns a Boolean value indicating if the type of the specified expression is a string. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// Returns true if the type of the specified expression is a string; otherwise, false. + /// + /// + /// document.Name.IsString()); + /// ]]> + /// + /// + public static bool IsString(this object obj) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + /// /// This method generate query definition from LINQ query. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestTypeCheckFunctions.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestTypeCheckFunctions.xml index 90a463defa..97aac9ef55 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestTypeCheckFunctions.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestTypeCheckFunctions.xml @@ -1,4 +1,52 @@  + + + + doc.ArrayField.IsArray())]]> + + + + + + + + + doc.StringField.IsArray())]]> + + + + + + + + + Convert(doc.BooleanField, Object).IsBool())]]> + + + + + + + + + doc.StringField.IsBool())]]> + + + + + @@ -45,6 +93,52 @@ FROM root WHERE IS_NULL(root["StringField"])]]> + + + + Convert(doc.NumericField, Object).IsNumber())]]> + + + + + + + + + doc.StringField.IsNumber())]]> + + + + + + + + + doc.ObjectField.IsObject())]]> + + + + + + + + + doc.StringField.IsObject())]]> + + + + + @@ -68,4 +162,27 @@ FROM root WHERE IS_PRIMITIVE(root["StringField"])]]> + + + + doc.StringField.IsString())]]> + + + + + + + + + Convert(doc.NumericField, Object).IsString())]]> + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 76bd0ffc81..5a46a2d118 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -116,6 +116,7 @@ internal class DataObject : LinqTestObject public int? NullableField; #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value false public bool BooleanField; + public SimpleObject ObjectField = new SimpleObject(); public Guid GuidField; #pragma warning restore // Field is never assigned to, and will always have its default value false @@ -155,6 +156,11 @@ internal class DataObject : LinqTestObject public string Pk; } + internal class SimpleObject + { + public string Field { get; set; } + } + class DateJsonConverter : IsoDateTimeConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) @@ -257,7 +263,7 @@ public void TestLiteralSerialization() [TestMethod] public void TestTypeCheckFunctions() { - // IsDefined, IsNull, and IsPrimitive are not supported on the client side. + // IsArray, IsBool, IsDefined, IsNull, IsNumber, IsObject, IsPrimitive, and IsString are not supported on the client side. // Partly because IsPrimitive is not trivial to implement. // Therefore these methods are verified with baseline only. List data = new List(); @@ -266,12 +272,22 @@ public void TestTypeCheckFunctions() List inputs = new List { + new LinqTestInput("IsArray array", b => getQuery(b).Where(doc => doc.ArrayField.IsArray())), + new LinqTestInput("IsArray string", b => getQuery(b).Where(doc => doc.StringField.IsArray())), + new LinqTestInput("IsBool bool", b => getQuery(b).Where(doc => doc.BooleanField.IsBool())), + new LinqTestInput("IsBool string", b => getQuery(b).Where(doc => doc.StringField.IsBool())), new LinqTestInput("IsDefined array", b => getQuery(b).Select(doc => doc.ArrayField.IsDefined())), new LinqTestInput("IsDefined string", b => getQuery(b).Where(doc => doc.StringField.IsDefined())), new LinqTestInput("IsNull array", b => getQuery(b).Select(doc => doc.ArrayField.IsNull())), new LinqTestInput("IsNull string", b => getQuery(b).Where(doc => doc.StringField.IsNull())), + new LinqTestInput("IsNumber number", b => getQuery(b).Select(doc => doc.NumericField.IsNumber())), + new LinqTestInput("IsNumber string", b => getQuery(b).Where(doc => doc.StringField.IsNumber())), + new LinqTestInput("IsObject object", b => getQuery(b).Select(doc => doc.ObjectField.IsObject())), + new LinqTestInput("IsObject string", b => getQuery(b).Where(doc => doc.StringField.IsObject())), new LinqTestInput("IsPrimitive array", b => getQuery(b).Select(doc => doc.ArrayField.IsPrimitive())), - new LinqTestInput("IsPrimitive string", b => getQuery(b).Where(doc => doc.StringField.IsPrimitive())) + new LinqTestInput("IsPrimitive string", b => getQuery(b).Where(doc => doc.StringField.IsPrimitive())), + new LinqTestInput("IsString string", b => getQuery(b).Where(doc => doc.StringField.IsString())), + new LinqTestInput("IsString number", b => getQuery(b).Select(doc => doc.NumericField.IsString())), }; this.ExecuteTestSuite(inputs); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 3eee7f406b..5b2e38772a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -5296,6 +5296,20 @@ "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean IsArray(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean IsArray(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean IsBool(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean IsBool(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Boolean IsDefined(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ @@ -5310,6 +5324,20 @@ ], "MethodInfo": "Boolean IsNull(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Boolean IsNumber(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean IsNumber(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean IsObject(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean IsObject(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Boolean IsPrimitive(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ @@ -5317,6 +5345,13 @@ ], "MethodInfo": "Boolean IsPrimitive(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Boolean IsString(System.Object)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean IsString(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.FeedIterator ToStreamIterator[T](System.Linq.IQueryable`1[T])[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ From aff7349cb80da9eab40f2e792b71390268e18169 Mon Sep 17 00:00:00 2001 From: Justine Cocchi Date: Wed, 10 May 2023 08:21:05 -0700 Subject: [PATCH 111/337] update sdk version and section tags (#3841) --- .../Usage/ApplicationInsights/ApplicationInsights.csproj | 2 +- .../Usage/ApplicationInsights/Program.cs | 2 +- .../Usage/OpenTelemetry/OpenTelemetry.csproj | 2 +- .../Usage/OpenTelemetry/Program.cs | 6 ++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj index cee6d0a6e3..59162abaca 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj @@ -10,7 +10,7 @@ - + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs index b4f55cd65f..288ce80c64 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs @@ -50,7 +50,7 @@ static async Task Main() IServiceProvider serviceProvider = services.BuildServiceProvider(); _telemetryClient = serviceProvider.GetRequiredService(); - // + // CosmosClientOptions options = new CosmosClientOptions() { diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj index 4dd1171328..46fe296b80 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj @@ -10,7 +10,7 @@ - + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs index d799731f1e..4d6431823e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs @@ -46,7 +46,7 @@ static async Task Main() throw new ArgumentException("Please specify a valid ApplicationInsightsConnectionString in the appSettings.json"); } - // + // ResourceBuilder resource = ResourceBuilder.CreateDefault().AddService( serviceName: serviceName, serviceVersion: "1.0.0"); @@ -69,12 +69,14 @@ static async Task Main() .AddAzureMonitorTraceExporter(o => o.ConnectionString = aiConnectionString) // Set up exporter of your choice .SetResourceBuilder(resource) .Build(); - // + // + // CosmosClientOptions options = new CosmosClientOptions() { IsDistributedTracingEnabled = true // Defaults to true, set to false to disable }; + // using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) { Console.WriteLine($"Getting container reference for {containerName}."); From 1a8b7f0d0bad48d7517f8871cb5174a4f929118f Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Tue, 16 May 2023 10:44:26 -0400 Subject: [PATCH 112/337] PackageLicense: Removes PackageLicenseUrl and Adds PackageLicenseFile since PackageLicenseUrl is deprecated (#3847) * proposal to add PackageLicenseFile since PackageLicenseUrl is deprecated. https://github.com/NuGet/Home/issues/4628 * adding attribute Visible=false --- Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 6a5be8ccbb..886a84d586 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -24,7 +24,6 @@ Microsoft.Azure.Cosmos microsoft;azure;cosmos;cosmosdb;documentdb;docdb;nosql;azureofficial;dotnetcore;netcore;netstandard The change log for this SDK is made available at https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/changelog.md at the time of release. - https://aka.ms/netcoregaeula https://github.com/Azure/azure-cosmos-dotnet-v3 true http://go.microsoft.com/fwlink/?LinkID=288890 @@ -43,8 +42,13 @@ NU5125 true $(LangVersion) + LICENSE + + + + From b06d6c3cb4bee845406ba0631228ca70e82ce70d Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 17 May 2023 13:48:21 -0400 Subject: [PATCH 113/337] making ChangeFeedMode.LatestVersion accessible to the public (#3854) --- .../src/ChangeFeed/ChangeFeedMode.cs | 7 +------ .../Contracts/DotNetPreviewSDKAPI.json | 10 ---------- .../Contracts/DotNetSDKAPI.json | 10 ++++++++++ 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs index 7df0871d74..50098a8057 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedMode.cs @@ -38,12 +38,7 @@ internal ChangeFeedMode() /// Latest version mode includes item creations and updates, not deletions. /// /// A to receive latest version item changes. -#if PREVIEW - public -#else - internal -#endif - static ChangeFeedMode LatestVersion => ChangeFeedModeIncremental.Instance; + public static ChangeFeedMode LatestVersion => ChangeFeedModeIncremental.Instance; /// /// Creates a to receive notifications for creations, deletes, as well as all intermediary snapshots for updates. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index ab29c95bf0..08d0d65a7e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -169,16 +169,6 @@ "Type": "Method", "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_AllVersionsAndDeletes();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion()": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 5b2e38772a..074be1ee37 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -307,10 +307,20 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_Incremental();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.ChangeFeedMode Incremental": { "Type": "Property", "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode Incremental;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_Incremental();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedMode LatestVersion;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ChangeFeedMode get_LatestVersion();IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} From c66e4884dcaf05657ef35f4452844fdc14447e4e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 18 May 2023 02:29:57 +0530 Subject: [PATCH 114/337] AI Integration: Fixes Operation Name in the activity and end to end Tests. (#3845) * first draft * second draft * 3rd draft * remove untouched file * test fix * fix order * change order * refactor * skip network activities in test * remove network attributes --- .../OpenTelemetryRecorderFactory.cs | 4 +- ...iterBaselineTests.BatchOperationsAsync.xml | 31 +- ...riterBaselineTests.BulkOperationsAsync.xml | 2679 +++++++++++++++-- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 571 +++- ...eWriterBaselineTests.MiscellanousAsync.xml | 114 +- ...neTests.PointOperationsExceptionsAsync.xml | 174 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 763 ++++- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 436 ++- ...TraceWriterBaselineTests.ReadManyAsync.xml | 62 +- ...selineTests.StreamPointOperationsAsync.xml | 124 +- ...aselineTests.TypedPointOperationsAsync.xml | 124 +- .../Tracing/AssertActivity.cs | 14 +- .../Tracing/CustomListener.cs | 93 +- .../Tracing/CustomOtelExporter.cs | 2 +- .../EndToEndTraceWriterBaselineTests.cs | 21 +- .../Utils/Util.cs | 4 +- 16 files changed, 4639 insertions(+), 577 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 51b4666b6f..fe10e7b22c 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -26,7 +26,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, { if (clientContext is { ClientOptions.IsDistributedTracingEnabled: true }) { - OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: OpenTelemetryAttributeKeys.DiagnosticNamespace, + OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.OperationPrefix}", resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, isActivityEnabled: true, suppressNestedClientActivities: true); @@ -34,7 +34,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = OpenTelemetryRecorderFactory .ScopeFactory - .CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", + .CreateScope(name: operationName, kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); // Record values only when we have a valid Diagnostic Scope diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 90f32b89c9..09579f83b7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -128,10 +128,31 @@ ] } ] -}]]> - Operation.ExecuteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationExecuteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeBatchdb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ExecuteAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Batch + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index b776a8eaae..be3a8c7910 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -152,29 +152,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -310,29 +529,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -468,29 +906,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -626,29 +1283,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -784,29 +1660,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -942,29 +2037,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -1100,29 +2414,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -1258,29 +2791,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -1416,29 +3168,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -1574,29 +3545,248 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + + + + + + + + + @@ -2323,10 +4513,29 @@ ] } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + + Some Value + Create + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 4189b4bab8..43d95de95d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -951,19 +951,128 @@ ] } ] -}]]> - Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + + @@ -1568,19 +1677,128 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + + @@ -2166,19 +2384,128 @@ ] } ] -}]]> - Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Change Feed Iterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Iterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Iterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + + @@ -2784,19 +3111,128 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + + @@ -3065,10 +3501,31 @@ ] } ] -}]]> - Operation.Change Feed Estimator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationChange Feed Estimator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Change Feed Estimator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 591a6af4ac..29fc40f674 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -106,13 +106,56 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.DeleteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + DeleteAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Delete + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateDatabaseAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + @@ -206,12 +249,55 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.DeleteAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -Operation.CreateDatabaseAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateDatabaseAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contacted -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + DeleteAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Delete + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateDatabaseAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 64e7e0c3ed..9ee0b6e650 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -147,11 +147,30 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + @@ -389,11 +408,30 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + @@ -614,11 +652,30 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + @@ -871,11 +928,30 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + @@ -1192,11 +1268,30 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + @@ -1346,10 +1441,29 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectexception.stacktraceexception.typedb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.regions_contactedSouth Central USexception.messagedb.cosmosdb.operation_typeCreate -ExceptionIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + Some Value + Create + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index d2abebc194..e9b0f96a00 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -573,17 +573,104 @@ ] } ] -}]]> - Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -1179,17 +1266,104 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -1766,17 +1940,104 @@ ] } ] -}]]> - Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -2373,17 +2634,104 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -3047,17 +3395,104 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -3643,17 +4078,104 @@ ] } ] -}]]> - Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -4259,16 +4781,103 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeQuerydb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Query + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index dc6df3eacf..501a8b187e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -535,17 +535,104 @@ ] } ] -}]]> - Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -1103,17 +1190,104 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -1652,17 +1826,104 @@ ] } ] -}]]> - Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.FeedIterator Read Next Asyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationFeedIterator Read Next Asyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + FeedIterator Read Next Async + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + @@ -2221,16 +2482,103 @@ ] } ] -}]]> - Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -Operation.Typed FeedIterator ReadNextAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationTyped FeedIterator ReadNextAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReadFeeddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Typed FeedIterator ReadNextAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + ReadFeed + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 29b36304ec..627a8ea66f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -541,11 +541,32 @@ ] } ] -}]]> - Operation.ReadManyItemsStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadManyItemsStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReadManyItemsStreamAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Read + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -1101,10 +1122,31 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.ReadManyItemsAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadManyItemsAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReadManyItemsAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Read + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 18f11acd62..016a37aaaf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -88,11 +88,32 @@ ] } ] -}]]> - Operation.CreateItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemStreamAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -177,11 +198,32 @@ ] } ] -}]]> - Operation.ReadItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReadItemStreamAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Read + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -274,11 +316,32 @@ ] } ] -}]]> - Operation.ReplaceItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReplaceItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReplaceItemStreamAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Replace + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -366,10 +429,31 @@ ] } ] -}]]> - Operation.DeleteItemStreamAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteItemStreamAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + DeleteItemStreamAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Delete + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index abeaa41de8..add1fcc343 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -108,11 +108,32 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.CreateItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationCreateItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeCreatedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + CreateItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Create + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -202,11 +223,32 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.ReadItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReadItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReaddb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReadItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Read + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -309,11 +351,32 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.ReplaceItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationReplaceItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeReplacedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + ReplaceItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Replace + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + @@ -405,10 +468,31 @@ "duration in milliseconds": 0 } ] -}]]> - Operation.DeleteItemAsyncaz.namespaceMicrosoft.DocumentDBaz.schema_urldb.operationDeleteItemAsyncdb.namedb.cosmosdb.containerdb.systemcosmosdbdb.cosmosdb.machine_idnet.peer.name127.0.0.1db.cosmosdb.client_iduser_agent.originaldb.cosmosdb.connection_modeDirectdb.cosmosdb.operation_typeDeletedb.cosmosdb.request_content_length_bytesdb.cosmosdb.response_content_length_bytesdb.cosmosdb.status_codedb.cosmosdb.sub_status_codedb.cosmosdb.request_chargedb.cosmosdb.item_countdb.cosmosdb.activity_iddb.cosmosdb.correlated_activity_iddb.cosmosdb.regions_contactedSouth Central US -LatencyOverThresholdIdeally, this should contain request diagnostics but request diagnostics is subject to change with each request as it contains few unique id. So just putting this tag with this static text to make sure event is getting generated for each test. - - +}]]> + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + DeleteItemAsync + Some Value + Some Value + cosmosdb + Some Value + 127.0.0.1 + Some Value + Some Value + Direct + Delete + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + Some Value + South Central US + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index f4983c10a7..e25a46e44c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -14,7 +14,7 @@ namespace Microsoft.Azure.Cosmos.Tracing internal static class AssertActivity { - public static void IsValid(Activity activity) + public static void IsValidOperationActivity(Activity activity) { Assert.IsTrue(activity.OperationName == activity.DisplayName); @@ -71,7 +71,7 @@ public static void IsValid(Activity activity) public static void AreEqualAcrossListeners() { Assert.AreEqual( - JsonConvert.SerializeObject(CustomListener.CollectedActivities.OrderBy(x => x.Id)), + JsonConvert.SerializeObject(CustomListener.CollectedOperationActivities.OrderBy(x => x.Id)), JsonConvert.SerializeObject(CustomOtelExporter.CollectedActivities.OrderBy(x => x.Id))); } @@ -79,11 +79,11 @@ private static void AssertDatabaseAndContainerName(string name, KeyValuePair exceptionsForContainerAttribute = new List { - "Operation.CreateDatabaseAsync", - "Operation.CreateDatabaseIfNotExistsAsync", - "Operation.ReadAsync", - "Operation.DeleteAsync", - "Operation.DeleteStreamAsync" + "CreateDatabaseAsync", + "CreateDatabaseIfNotExistsAsync", + "ReadAsync", + "DeleteAsync", + "DeleteStreamAsync" }; if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 5f98a6191a..b0df15c3f2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -30,30 +30,19 @@ internal class CustomListener : private ConcurrentBag subscriptions = new(); private ConcurrentBag Scopes { get; } = new(); - public static ConcurrentBag CollectedActivities { private set; get; } = new(); + public static ConcurrentBag CollectedOperationActivities { private set; get; } = new(); + public static ConcurrentBag CollectedNetworkActivities { private set; get; } = new(); private static ConcurrentBag CollectedEvents { set; get; } = new(); - private string SourceType { set; get; } - - // Regex is used to match string 'n' against diagnosticNameSpace string - // which is constructed by combining first two parts of name. - // Eg: Azure.Cosmos.Operation where diagnosticNameSpace is Azure.Cosmos and Operation is the sourceType public CustomListener(string name, string eventName) - : this(n => - { - string[] nameParts = name.Split("."); - string diagnosticNameSpace = $"{nameParts[0]}.{nameParts[1]}"; - return Regex.Match(n, diagnosticNameSpace).Success; - }, name.Split(".")[2], eventName) - + : this(n => Regex.Match(n, name).Success, eventName) { } - public CustomListener(Func filter, string sourceType, string eventName) + public CustomListener(Func filter, string eventName) { this.sourceNameFilter = filter; this.eventName = eventName; - this.SourceType = sourceType; DiagnosticListener.AllListeners.Subscribe(this); } @@ -87,12 +76,7 @@ public void OnNext(KeyValuePair value) string startSuffix = ".Start"; string stopSuffix = ".Stop"; string exceptionSuffix = ".Exception"; - - if(!this.SourceType.Contains("*") && !Activity.Current.OperationName.Contains(this.SourceType)) - { - return; - } - + if (value.Key.EndsWith(startSuffix)) { string name = value.Key[..^startSuffix.Length]; @@ -115,9 +99,16 @@ public void OnNext(KeyValuePair value) { if (producedDiagnosticScope.Activity.Id == Activity.Current.Id) { - AssertActivity.IsValid(producedDiagnosticScope.Activity); - CustomListener.CollectedActivities.Add(producedDiagnosticScope.Activity); - + if (producedDiagnosticScope.Activity.Source.Name.EndsWith("Operation")) + { + AssertActivity.IsValidOperationActivity(producedDiagnosticScope.Activity); + CustomListener.CollectedOperationActivities.Add(producedDiagnosticScope.Activity); + } + else if (producedDiagnosticScope.Activity.Source.Name.EndsWith("Request")) + { + CustomListener.CollectedNetworkActivities.Add(producedDiagnosticScope.Activity); + } + producedDiagnosticScope.IsCompleted = true; return; } @@ -173,13 +164,8 @@ protected override void OnEventSourceCreated(EventSource eventSource) protected override void OnEventWritten(EventWrittenEventArgs eventData) { StringBuilder builder = new StringBuilder(); - builder.Append("") - .Append("").Append(eventData.EventName).Append("") - .Append("Ideally, this should contain request diagnostics but request diagnostics is " + - "subject to change with each request as it contains few unique id. " + - "So just putting this tag with this static text to make sure event is getting generated" + - " for each test.") - .Append(""); + builder.Append($""); + CustomListener.CollectedEvents.Add(builder.ToString()); } @@ -238,6 +224,7 @@ private string GenerateTagForBaselineTest(Activity activity) { List tagsWithStaticValue = new List { + "az.schema_url", "kind", "az.namespace", "db.operation", @@ -249,24 +236,18 @@ private string GenerateTagForBaselineTest(Activity activity) }; StringBuilder builder = new StringBuilder(); - builder.Append("") - .Append("") - .Append(activity.OperationName) - .Append(""); - + builder.Append($""); foreach (KeyValuePair tag in activity.Tags) { - builder - .Append("") - .Append(tag.Key) - .Append(""); - if (tagsWithStaticValue.Contains(tag.Key)) { builder - .Append("") - .Append(tag.Value) - .Append(""); + .Append($"{tag.Value}"); + } + else + { + builder + .Append($"Some Value"); } } @@ -278,15 +259,26 @@ private string GenerateTagForBaselineTest(Activity activity) public List GetRecordedAttributes() { List generatedActivityTagsForBaselineXmls = new(); - List collectedActivities = new List(CustomListener.CollectedActivities); - - collectedActivities.OrderBy(act => act.OperationName); - foreach (Activity activity in collectedActivities) + List collectedOperationActivities = new List(CustomListener.CollectedOperationActivities); + foreach (Activity activity in collectedOperationActivities) { generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); } - + + /* List collectedNetworkActivities = new List(CustomListener.CollectedNetworkActivities); + collectedNetworkActivities = collectedNetworkActivities + .OrderBy(act => + act.Source.Name + + act.OperationName + + act.GetTagItem("rntbd.status_code") + + act.GetTagItem("rntbd.sub_status_code")) + .ToList(); + foreach (Activity activity in collectedNetworkActivities) + { + generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); + }*/ + List outputList = new List(); if(generatedActivityTagsForBaselineXmls != null && generatedActivityTagsForBaselineXmls.Count > 0) { @@ -304,7 +296,8 @@ public List GetRecordedAttributes() public void ResetAttributes() { CustomListener.CollectedEvents = new(); - CustomListener.CollectedActivities = new(); + CustomListener.CollectedOperationActivities = new(); + CustomListener.CollectedNetworkActivities = new(); } public class ProducedDiagnosticScope diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs index 1f6c335fdd..de819ee021 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -33,7 +33,7 @@ public override ExportResult Export(in Batch batch) foreach (Activity activity in batch) { - AssertActivity.IsValid(activity); + AssertActivity.IsValidOperationActivity(activity); CollectedActivities.Add(activity); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index ba7e828edf..63d883ef21 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -14,6 +14,7 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing using System.Threading; using System.Threading.Tasks; using System.Xml; + using System.Xml.Linq; using global::Azure; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Diagnostics; @@ -1452,10 +1453,12 @@ public override Output ExecuteTest(Input input) StringBuilder oTelActivitiesString = new StringBuilder(); if (input.OTelActivities != null && input.OTelActivities.Count > 0) { + oTelActivitiesString.Append(""); foreach (string attributes in input.OTelActivities) { oTelActivitiesString.AppendLine(attributes); } + oTelActivitiesString.Append(""); } AssertTraceProperites(input.Trace); @@ -1464,9 +1467,23 @@ public override Output ExecuteTest(Input input) Assert.IsTrue(text.Contains("Client Configuration"), $"All diagnostics should have Client Configuration: {text}"); Assert.IsTrue(json.Contains("Client Configuration"), $"All diagnostics should have Client Configuration: {json}"); - return new Output(text, JToken.Parse(json).ToString(Newtonsoft.Json.Formatting.Indented), oTelActivitiesString.ToString()); + return new Output(text, JToken.Parse(json).ToString(Newtonsoft.Json.Formatting.Indented), this.FormatXml(oTelActivitiesString.ToString())); } + private string FormatXml(string xml) + { + try + { + XDocument doc = XDocument.Parse(xml); + return doc.ToString(); + } + catch (Exception) + { + // Handle and throw if fatal exception here; don't just ignore them + return xml; + } + } + private static TraceForBaselineTesting CreateTraceForBaslineTesting(ITrace trace, TraceForBaselineTesting parent) { TraceForBaselineTesting convertedTrace = new TraceForBaselineTesting(trace.Name, trace.Level, trace.Component, parent); @@ -1650,9 +1667,7 @@ public override void SerializeAsXml(XmlWriter xmlWriter) if (!string.IsNullOrWhiteSpace(this.OTelActivities)) { - xmlWriter.WriteStartElement(nameof(this.OTelActivities)); xmlWriter.WriteRaw(this.OTelActivities); - xmlWriter.WriteEndElement(); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 59172beb33..366cc68811 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -548,11 +548,11 @@ internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() // Open Telemetry Listener Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() // use any exporter here - .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") // Right now, it will capture only "Azure.Cosmos.Operation" + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") .Build(); // Custom Listener - Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", "Azure-Cosmos-Operation-Request-Diagnostics"); + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); return Util.TestListener; From 7b32e8eb094caf9d9c2e6e905775c025e5d166f1 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Thu, 18 May 2023 10:47:27 -0400 Subject: [PATCH 115/337] SDK 3.34.0 : Adds version bump and changelog (#3855) * SDK 3.34.0: Adds version bump and changelog * adding changelog changes * added a missing PREVIEW PR * Update changelog.md Co-authored-by: Justine Cocchi * Update changelog.md Co-authored-by: Kiran Kumar Kolli * removed 3840 as it was not committed * change text for 3832 * fix merge issue * add 3724 * Update changelog.md Co-authored-by: Matias Quaranta * Update changelog.md Co-authored-by: Matias Quaranta * including 3845 --------- Co-authored-by: Justine Cocchi Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- Directory.Build.props | 4 +- .../contracts/API_3.34.0-preview.txt | 1558 +++++++++++++++++ .../contracts/API_3.34.0.txt | 1499 ++++++++++++++++ changelog.md | 17 + 4 files changed, 3076 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.34.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.34.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index a24f0ab2ac..ef1ffd2e01 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.33.0 - 3.33.0 + 3.34.0 + 3.34.0 preview 3.30.8 2.0.1 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.34.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.34.0-preview.txt new file mode 100644 index 0000000000..4087f63f84 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.34.0-preview.txt @@ -0,0 +1,1558 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.34.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.34.0.txt new file mode 100644 index 0000000000..a365c00c6a --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.34.0.txt @@ -0,0 +1,1499 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 709a4bfccf..906c0746ef 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,23 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.34.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.34.0-preview) - 2023-05-17 + +### Added +- [3761](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3761) Query: Adds Computed Property SDK Support + +### [3.34.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.34.0) - 2023-05-17 + +#### Fixed +- [3847](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3847) PackageLicense: Replaces PackageLicenseUrl with PackageLicenseFile since PackageLicenseUrl is deprecated +- [3845](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3845) AI Integration: Fixes Operation Name in the activity and end to end Tests. +- [3832](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3832) Query: Fixes format exception when using culture and partitionKey, difference between Windows and Linux + +#### Added +- [3854](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3854) Change Feed: Adds LatestVersion to ChangeFeedMode +- [3833](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3833) Query: Adds TRIM string system function support in LINQ +- [3826](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3826) Query: Adds support for Lambda expression reuse in LINQ +- [3724](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3724) Query: Added remaining Cosmos Type checking functions to CosmosLinqExtensions. Thanks @onionhammer. ### [3.33.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.33.0-preview) - 2023-04-21 From 2b7d709b9fab04a09f373d4d64e2a1ff7c16f849 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Thu, 18 May 2023 12:10:49 -0400 Subject: [PATCH 116/337] Release: Fixes changelog.md change for 3845 to preview (#3859) --- changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 906c0746ef..b1b3139828 100644 --- a/changelog.md +++ b/changelog.md @@ -17,11 +17,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [3761](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3761) Query: Adds Computed Property SDK Support +#### Fixed +- [3845](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3845) AI Integration: Fixes Operation Name in the activity and end to end Tests. + ### [3.34.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.34.0) - 2023-05-17 #### Fixed - [3847](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3847) PackageLicense: Replaces PackageLicenseUrl with PackageLicenseFile since PackageLicenseUrl is deprecated -- [3845](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3845) AI Integration: Fixes Operation Name in the activity and end to end Tests. - [3832](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3832) Query: Fixes format exception when using culture and partitionKey, difference between Windows and Linux #### Added From 3727d4d738cfc24aa372b578fd8ca482a5bc2f3f Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Fri, 19 May 2023 11:12:10 -0400 Subject: [PATCH 117/337] removing ThirdPartyNotice.txt from content and contentfiles folders (#3864) --- Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 886a84d586..f8afb4af6c 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -59,7 +59,7 @@ - + From 69cda11e4c7537cc8c864e358a4f7d47828c36d7 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Mon, 22 May 2023 06:19:42 -0700 Subject: [PATCH 118/337] Documentation: Adds see also link to Container.CreateTransactionalBatch (#3860) * Linking limit documentation to Container.CreateTransactionalBatch(PartitionKey) method * Resolved PR comments * Links update * Using learn.microsoft instead of docs.microsoft in the links --------- Co-authored-by: Matias Quaranta --- Microsoft.Azure.Cosmos/src/Batch/TransactionalBatch.cs | 6 +++++- Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatch.cs b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatch.cs index aa8ff6af62..a479f3d8b0 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatch.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatch.cs @@ -107,7 +107,9 @@ namespace Microsoft.Azure.Cosmos /// ]]> /// /// - /// Limits on TransactionalBatch requests + /// + /// Limits on TransactionalBatch requests + /// public abstract class TransactionalBatch { /// @@ -244,6 +246,7 @@ public abstract TransactionalBatch PatchItem( /// /// This API only throws on client side exceptions. This is to increase performance and prevent the overhead of throwing exceptions. /// Use on the response returned to ensure that the transactional batch succeeded. + /// Limits on TransactionalBatch requests /// public abstract Task ExecuteAsync( CancellationToken cancellationToken = default); @@ -275,6 +278,7 @@ public abstract Task ExecuteAsync( /// /// This API only throws on client side exceptions. This is to increase performance and prevent the overhead of throwing exceptions. /// Use on the response returned to ensure that the transactional batch succeeded. + /// Limits on TransactionalBatch requests /// public abstract Task ExecuteAsync( TransactionalBatchRequestOptions requestOptions, diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 1defe1f3cc..106262a13f 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -1342,6 +1342,9 @@ public abstract ChangeFeedEstimator GetChangeFeedEstimator( /// /// The partition key for all items in the batch. /// A new instance of . + /// + /// Limits on TransactionalBatch requests + /// public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); /// From d4f48f4258d2e2769a8beee69034e155f4028934 Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Tue, 23 May 2023 15:33:44 -0700 Subject: [PATCH 119/337] Query: Adds type-markers with count and length for large arrays (#3852) * initial commit * cleanup * update test output * cleanup * typo * Pr comments --- .../src/Json/JsonWriter.JsonBinaryWriter.cs | 51 +-- Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs | 1 - .../Json/JsonWriterTests.cs | 409 ++++++++++++------ 3 files changed, 306 insertions(+), 155 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs index b9d6d2047a..0df6582cf6 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs @@ -33,7 +33,7 @@ abstract partial class JsonWriter : IJsonWriter /// Blitted bytes. public static PreblittedBinaryJsonScope CapturePreblittedBinaryJsonScope(Action scopeWriter) { - JsonBinaryWriter jsonBinaryWriter = new JsonBinaryWriter(initialCapacity: 256, serializeCount: false, enableEncodedStrings: false); + JsonBinaryWriter jsonBinaryWriter = new JsonBinaryWriter(initialCapacity: 256, enableEncodedStrings: false); Contract.Requires(!jsonBinaryWriter.JsonObjectState.InArrayContext); Contract.Requires(!jsonBinaryWriter.JsonObjectState.InObjectContext); Contract.Requires(!jsonBinaryWriter.JsonObjectState.IsPropertyExpected); @@ -243,13 +243,6 @@ private enum RawValueType : byte /// private readonly Stack bufferedContexts; - /// - /// With binary encoding json elements like arrays and object are prefixed with a length in bytes and optionally a count. - /// This flag just determines whether you want to serialize the count, since it's optional and up to the user to make the - /// tradeoff between O(1) .Count() operation as the cost of additional storage. - /// - private readonly bool serializeCount; - /// /// When a user writes an open array or object we reserve this much space for the type marker + length + count /// And correct it later when they write a close array or object. @@ -269,18 +262,15 @@ private enum RawValueType : byte /// Initializes a new instance of the JsonBinaryWriter class. /// /// The initial capacity to avoid intermediary allocations. - /// Whether to serialize the count for object and array typemarkers. /// enable reference string encoding public JsonBinaryWriter( int initialCapacity, - bool serializeCount, bool enableEncodedStrings) { this.EnableEncodedStrings = enableEncodedStrings; this.binaryWriter = new JsonBinaryMemoryWriter(initialCapacity); this.bufferedContexts = new Stack(); - this.serializeCount = serializeCount; - this.reservationSize = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength + (this.serializeCount ? JsonBinaryEncoding.OneByteCount : 0); + this.reservationSize = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength; this.sharedStrings = new List(); this.sharedStringIndexes = new ReferenceStringDictionary(); this.stringReferenceOffsets = new List(); @@ -300,13 +290,13 @@ public JsonBinaryWriter( public override long CurrentLength => this.binaryWriter.Position; /// - public override void WriteObjectStart() => this.WriterArrayOrObjectStart(isArray: false); + public override void WriteObjectStart() => this.WriteArrayOrObjectStart(isArray: false); /// public override void WriteObjectEnd() => this.WriteArrayOrObjectEnd(isArray: false); /// - public override void WriteArrayStart() => this.WriterArrayOrObjectStart(isArray: true); + public override void WriteArrayStart() => this.WriteArrayOrObjectStart(isArray: true); /// public override void WriteArrayEnd() => this.WriteArrayOrObjectEnd(isArray: true); @@ -536,7 +526,7 @@ internal PreblittedBinaryJsonScope CapturePreblittedBinaryJsonScope(int startPos this.binaryWriter.BufferAsSpan.Slice(startPosition, this.binaryWriter.Position - startPosition).ToArray()); } - private void WriterArrayOrObjectStart(bool isArray) + private void WriteArrayOrObjectStart(bool isArray) { this.RegisterArrayOrObjectStart(isArray, this.binaryWriter.Position, valueCount: 0); @@ -544,10 +534,6 @@ private void WriterArrayOrObjectStart(bool isArray) // We'll adjust this as needed when writing the end of the array/object. this.binaryWriter.Write((byte)0); this.binaryWriter.Write((byte)0); - if (this.serializeCount) - { - this.binaryWriter.Write((byte)0); - } } private void RegisterArrayOrObjectStart(bool isArray, long offset, int valueCount) @@ -611,16 +597,20 @@ private void WriteArrayOrObjectEnd(bool isArray) // Need to figure out how many bytes to encode the length and the count if (payloadLength <= byte.MaxValue) { - // 1 byte length - don't need to move the buffer + bool serializeCount = isArray && (count > 16); + + // 1 byte length - move the buffer forward + Span buffer = this.binaryWriter.BufferAsSpan; int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.OneByteLength - + (this.serializeCount ? JsonBinaryEncoding.OneByteCount : 0); + + (serializeCount ? JsonBinaryEncoding.OneByteCount : 0); + this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker - if (this.serializeCount) + if (serializeCount) { this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object1ByteLengthAndCount); this.binaryWriter.Write((byte)payloadLength); @@ -637,9 +627,11 @@ private void WriteArrayOrObjectEnd(bool isArray) } else if (payloadLength <= ushort.MaxValue) { + bool serializeCount = isArray && ((count > 16) || (payloadLength > 0x1000)); + // 2 byte length - make space for the extra byte length (and extra byte count) this.binaryWriter.Write((byte)0); - if (this.serializeCount) + if (serializeCount) { this.binaryWriter.Write((byte)0); } @@ -648,14 +640,14 @@ private void WriteArrayOrObjectEnd(bool isArray) Span buffer = this.binaryWriter.BufferAsSpan; int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.TwoByteLength - + (this.serializeCount ? JsonBinaryEncoding.TwoByteCount : 0); + + (serializeCount ? JsonBinaryEncoding.TwoByteCount : 0); this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker - if (this.serializeCount) + if (serializeCount) { this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object2ByteLengthAndCount); this.binaryWriter.Write((ushort)payloadLength); @@ -673,11 +665,12 @@ private void WriteArrayOrObjectEnd(bool isArray) else { // (payloadLength <= uint.MaxValue) + bool serializeCount = isArray; // 4 byte length - make space for an extra 3 byte length (and 3 byte count) this.binaryWriter.Write((byte)0); this.binaryWriter.Write((ushort)0); - if (this.serializeCount) + if (serializeCount) { this.binaryWriter.Write((byte)0); this.binaryWriter.Write((ushort)0); @@ -687,14 +680,14 @@ private void WriteArrayOrObjectEnd(bool isArray) Span buffer = this.binaryWriter.BufferAsSpan; int bytesToWrite = JsonBinaryEncoding.TypeMarkerLength + JsonBinaryEncoding.FourByteLength - + (this.serializeCount ? JsonBinaryEncoding.FourByteCount : 0); + + (serializeCount ? JsonBinaryEncoding.FourByteCount : 0); this.MoveBuffer(buffer, payloadIndex, payloadLength, typeMarkerIndex, bytesToWrite, stringStartIndex, stringReferenceStartIndex); // Move the cursor back this.binaryWriter.Position = typeMarkerIndex; // Write the type marker - if (this.serializeCount) + if (serializeCount) { this.binaryWriter.Write(isArray ? JsonBinaryEncoding.TypeMarker.Array4ByteLengthAndCount : JsonBinaryEncoding.TypeMarker.Object4ByteLengthAndCount); this.binaryWriter.Write((uint)payloadLength); @@ -915,7 +908,7 @@ private bool TryRegisterStringValue(Utf8Span utf8Span) // In order to avoid having to change the typer marker later on, we need to account for the case // where the buffer might shift as a result of adjusting array/object length. - int maxOffset = (this.JsonObjectState.CurrentDepth * 3) + (int)this.CurrentLength; + int maxOffset = (this.JsonObjectState.CurrentDepth * 7) + (int)this.CurrentLength; bool shouldAddValue = (utf8Span.Length >= 5) || ((maxOffset <= byte.MaxValue) && (utf8Span.Length >= 2)) || diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs index 8e75c0c116..9ea7b42325 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.cs @@ -58,7 +58,6 @@ public static IJsonWriter Create( JsonSerializationFormat.Text => new JsonTextWriter(initalCapacity), JsonSerializationFormat.Binary => new JsonBinaryWriter( initialCapacity: initalCapacity, - serializeCount: false, enableEncodedStrings: enableEncodedStrings), _ => throw new ArgumentException( string.Format( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs index e60ab573e8..b44cb49b1f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs @@ -16,7 +16,7 @@ public class JsonWriterTests #region Literals [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TrueTest() { string expectedString = "true"; @@ -37,7 +37,7 @@ public void TrueTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void FalseTest() { string expectedString = "false"; @@ -58,7 +58,7 @@ public void FalseTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NullTest() { string expectedString = "null"; @@ -80,7 +80,7 @@ public void NullTest() #endregion #region Numbers [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntegerTest() { string expectedString = "1337"; @@ -103,7 +103,7 @@ public void IntegerTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DoubleTest() { string expectedString = "1337.1337"; @@ -126,7 +126,7 @@ public void DoubleTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NaNTest() { string expectedString = "\"NaN\""; @@ -149,7 +149,7 @@ public void NaNTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void PositiveInfinityTest() { string expectedString = "\"Infinity\""; @@ -172,7 +172,7 @@ public void PositiveInfinityTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NegativeInfinityTest() { string expectedString = "\"-Infinity\""; @@ -195,7 +195,7 @@ public void NegativeInfinityTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NegativeNumberTest() { string expectedString = "-1337.1337"; @@ -218,7 +218,7 @@ public void NegativeNumberTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberWithScientificNotationTest() { string expectedString = "6.02252E+23"; @@ -241,7 +241,7 @@ public void NumberWithScientificNotationTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberRegressionTest() { // regression test - the value 0.00085647800000000004 was being incorrectly rejected @@ -267,7 +267,7 @@ public void NumberRegressionTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberPrecisionTest() { string expectedString = "[2.7620553993338772e+018,2.7620553993338778e+018]"; @@ -303,7 +303,7 @@ public void NumberPrecisionTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void LargeNumbersTest() { string expectedString = @"[1,-1,10,-10,14997460357411200,14997460357411000,1499746035741101,1499746035741109,-14997460357411200,-14997460357411000,-1499746035741101,-1499746035741109,1499746035741128,1499752659822592,1499752939110661,1499753827614475,1499970126403840,1499970590815128,1499970842400644,1499971371510025,1499972760675685,1499972969962006,1499973086735836,1499973302072392,1499976826748983]"; @@ -343,7 +343,7 @@ public void LargeNumbersTest() #endregion #region String [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyStringTest() { string expectedString = "\"\""; @@ -364,7 +364,7 @@ public void EmptyStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StringTest() { string expectedString = "\"Hello World\""; @@ -387,7 +387,7 @@ public void StringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SystemStringTest() { int systemStringId = 0; @@ -418,7 +418,7 @@ public void SystemStringTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void DateTimeStringsTest() { { @@ -633,7 +633,7 @@ public void DateTimeStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void HexStringsTest() { { @@ -719,7 +719,7 @@ public void HexStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void CompressedStringsTest() { { @@ -933,7 +933,7 @@ public void CompressedStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void GuidStringsTest() { { @@ -1325,7 +1325,7 @@ public void GuidStringsTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ReferenceStringsTest() { { @@ -1501,97 +1501,97 @@ public void ReferenceStringsTest() }; byte[] binaryPayload = new byte[] { - 0x80, 0xEB, 0xCE, 0x02, 0x89, 0x70, 0x72, 0x6F, + 0x80, 0xEB, 0xD2, 0x02, 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x31, 0x86, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x31, 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x32, 0xC3, 0x0E, 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x33, 0xE2, 0x64, 0x89, 0x70, 0x72, - 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x30, 0xC3, - 0x04, 0xC3, 0x15, 0xC3, 0x21, 0x89, 0x70, 0x72, - 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x34, 0x89, - 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x35, 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, - 0x74, 0x79, 0x36, 0x89, 0x70, 0x72, 0x6F, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x37, 0x89, 0x70, 0x72, - 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x38, 0x89, - 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, - 0x39, 0xC3, 0x0E, 0xC3, 0x0E, 0xC3, 0x0E, 0xC3, - 0x6F, 0xC3, 0x65, 0xC3, 0x5B, 0xC3, 0x47, 0xC3, - 0x3D, 0xC3, 0x21, 0xC3, 0x15, 0xC3, 0x04, 0xC3, - 0x2D, 0xC3, 0x21, 0xC3, 0x0E, 0xC3, 0x3D, 0xC3, - 0x0E, 0xC3, 0x47, 0xE2, 0xB8, 0x8E, 0x53, 0x74, + 0x74, 0x79, 0x33, 0xE5, 0x64, 0x16, 0x89, 0x70, + 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x30, + 0xC3, 0x04, 0xC3, 0x15, 0xC3, 0x21, 0x89, 0x70, + 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x34, + 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x35, 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, + 0x72, 0x74, 0x79, 0x36, 0x89, 0x70, 0x72, 0x6F, + 0x70, 0x65, 0x72, 0x74, 0x79, 0x37, 0x89, 0x70, + 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, 0x38, + 0x89, 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, + 0x79, 0x39, 0xC3, 0x0E, 0xC3, 0x0E, 0xC3, 0x0E, + 0xC3, 0x70, 0xC3, 0x66, 0xC3, 0x5C, 0xC3, 0x48, + 0xC3, 0x3E, 0xC3, 0x21, 0xC3, 0x15, 0xC3, 0x04, + 0xC3, 0x2E, 0xC3, 0x21, 0xC3, 0x0E, 0xC3, 0x3E, + 0xC3, 0x0E, 0xC3, 0x48, 0xE5, 0xB8, 0x16, 0x8E, + 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, + 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x30, 0x8E, 0x53, + 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, + 0x75, 0x65, 0x5F, 0x5F, 0x31, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x5F, 0x5F, 0x30, 0x8E, 0x53, 0x74, 0x72, + 0x65, 0x5F, 0x5F, 0x32, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, - 0x5F, 0x5F, 0x31, 0x8E, 0x53, 0x74, 0x72, 0x69, + 0x5F, 0x5F, 0x33, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, - 0x5F, 0x32, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, + 0x5F, 0x34, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, - 0x33, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x34, + 0x35, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, + 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x36, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x35, 0x8E, + 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x37, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, - 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x36, 0x8E, 0x53, + 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x38, 0x8E, 0x53, 0x74, 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x5F, 0x5F, 0x37, 0x8E, 0x53, 0x74, - 0x72, 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x5F, 0x5F, 0x38, 0x8E, 0x53, 0x74, 0x72, - 0x69, 0x6E, 0x67, 0x56, 0x61, 0x6C, 0x75, 0x65, - 0x5F, 0x5F, 0x39, 0x86, 0x76, 0x61, 0x6C, 0x75, - 0x65, 0x32, 0xC4, 0x33, 0x01, 0xC4, 0x33, 0x01, - 0xC4, 0x24, 0x01, 0xC4, 0x15, 0x01, 0xC4, 0x06, - 0x01, 0xC3, 0xE8, 0xC3, 0xD9, 0xC3, 0xCA, 0xC3, - 0xBB, 0xC3, 0xAC, 0xC3, 0x9D, 0xC3, 0x47, 0xC4, - 0x33, 0x01, 0xC3, 0x51, 0xC4, 0x33, 0x01, 0xC3, - 0x5B, 0xE2, 0xAA, 0x8C, 0x54, 0x65, 0x78, 0x74, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x30, + 0x75, 0x65, 0x5F, 0x5F, 0x39, 0x86, 0x76, 0x61, + 0x6C, 0x75, 0x65, 0x32, 0xC4, 0x35, 0x01, 0xC4, + 0x35, 0x01, 0xC4, 0x26, 0x01, 0xC4, 0x17, 0x01, + 0xC4, 0x08, 0x01, 0xC3, 0xEA, 0xC3, 0xDB, 0xC3, + 0xCC, 0xC3, 0xBD, 0xC3, 0xAE, 0xC3, 0x9F, 0xC3, + 0x48, 0xC4, 0x35, 0x01, 0xC3, 0x52, 0xC4, 0x35, + 0x01, 0xC3, 0x5C, 0xE5, 0xAA, 0x16, 0x8C, 0x54, + 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, + 0x5F, 0x5F, 0x30, 0x8C, 0x54, 0x65, 0x78, 0x74, + 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x31, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x5F, 0x5F, 0x31, 0x8C, 0x54, 0x65, + 0x75, 0x65, 0x5F, 0x5F, 0x32, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, - 0x5F, 0x32, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, - 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x33, 0x8C, + 0x5F, 0x33, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, + 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x34, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, 0x75, - 0x65, 0x5F, 0x5F, 0x34, 0x8C, 0x54, 0x65, 0x78, + 0x65, 0x5F, 0x5F, 0x35, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, - 0x35, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, - 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x36, 0x8C, 0x54, + 0x36, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, + 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x37, 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, 0x75, 0x65, - 0x5F, 0x5F, 0x37, 0x8C, 0x54, 0x65, 0x78, 0x74, - 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x38, - 0x8C, 0x54, 0x65, 0x78, 0x74, 0x56, 0x61, 0x6C, - 0x75, 0x65, 0x5F, 0x5F, 0x39, 0x86, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x33, 0xC4, 0xE5, 0x01, 0xC4, - 0xE5, 0x01, 0xC4, 0xD8, 0x01, 0xC4, 0xCB, 0x01, - 0xC4, 0xBE, 0x01, 0xC4, 0xA4, 0x01, 0xC4, 0x97, - 0x01, 0xC4, 0x8A, 0x01, 0xC4, 0x7D, 0x01, 0xC4, - 0x70, 0x01, 0xC4, 0x63, 0x01, 0xC3, 0x65, 0xC4, - 0xE5, 0x01, 0xC3, 0x6F, 0xC4, 0xE5, 0x01, 0xC3, - 0x2D, 0xE2, 0xA0, 0x8B, 0x42, 0x72, 0x6F, 0x77, - 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x30, 0x8B, + 0x5F, 0x5F, 0x38, 0x8C, 0x54, 0x65, 0x78, 0x74, + 0x56, 0x61, 0x6C, 0x75, 0x65, 0x5F, 0x5F, 0x39, + 0x86, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x33, 0xC4, + 0xE8, 0x01, 0xC4, 0xE8, 0x01, 0xC4, 0xDB, 0x01, + 0xC4, 0xCE, 0x01, 0xC4, 0xC1, 0x01, 0xC4, 0xA7, + 0x01, 0xC4, 0x9A, 0x01, 0xC4, 0x8D, 0x01, 0xC4, + 0x80, 0x01, 0xC4, 0x73, 0x01, 0xC4, 0x66, 0x01, + 0xC3, 0x66, 0xC4, 0xE8, 0x01, 0xC3, 0x70, 0xC4, + 0xE8, 0x01, 0xC3, 0x2E, 0xE5, 0xA0, 0x16, 0x8B, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x44, 0x6F, 0x67, - 0x5F, 0x5F, 0x31, 0x8B, 0x42, 0x72, 0x6F, 0x77, - 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x32, 0x8B, + 0x5F, 0x5F, 0x30, 0x8B, 0x42, 0x72, 0x6F, 0x77, + 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x31, 0x8B, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x44, 0x6F, 0x67, - 0x5F, 0x5F, 0x33, 0x8B, 0x42, 0x72, 0x6F, 0x77, - 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x34, 0x8B, + 0x5F, 0x5F, 0x32, 0x8B, 0x42, 0x72, 0x6F, 0x77, + 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x33, 0x8B, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x44, 0x6F, 0x67, - 0x5F, 0x5F, 0x35, 0x8B, 0x42, 0x72, 0x6F, 0x77, - 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x36, 0x8B, + 0x5F, 0x5F, 0x34, 0x8B, 0x42, 0x72, 0x6F, 0x77, + 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x35, 0x8B, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x44, 0x6F, 0x67, - 0x5F, 0x5F, 0x37, 0x8B, 0x42, 0x72, 0x6F, 0x77, - 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x38, 0x8B, + 0x5F, 0x5F, 0x36, 0x8B, 0x42, 0x72, 0x6F, 0x77, + 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x37, 0x8B, 0x42, 0x72, 0x6F, 0x77, 0x6E, 0x44, 0x6F, 0x67, - 0x5F, 0x5F, 0x39, 0x86, 0x76, 0x61, 0x6C, 0x75, - 0x65, 0x34, 0xC4, 0x93, 0x02, 0xC4, 0x93, 0x02, - 0xC4, 0x87, 0x02, 0xC4, 0x7B, 0x02, 0xC4, 0x6F, - 0x02, 0xC4, 0x57, 0x02, 0xC4, 0x4B, 0x02, 0xC4, - 0x3F, 0x02, 0xC4, 0x33, 0x02, 0xC4, 0x27, 0x02, - 0xC4, 0x1B, 0x02, 0x89, 0x70, 0x72, 0x6F, 0x70, - 0x65, 0x72, 0x74, 0x79, 0x41, 0x86, 0x76, 0x61, - 0x6C, 0x75, 0x65, 0x41, 0xC4, 0xBB, 0x02, 0xC4, - 0xC5, 0x02 + 0x5F, 0x5F, 0x38, 0x8B, 0x42, 0x72, 0x6F, 0x77, + 0x6E, 0x44, 0x6F, 0x67, 0x5F, 0x5F, 0x39, 0x86, + 0x76, 0x61, 0x6C, 0x75, 0x65, 0x34, 0xC4, 0x97, + 0x02, 0xC4, 0x97, 0x02, 0xC4, 0x8B, 0x02, 0xC4, + 0x7F, 0x02, 0xC4, 0x73, 0x02, 0xC4, 0x5B, 0x02, + 0xC4, 0x4F, 0x02, 0xC4, 0x43, 0x02, 0xC4, 0x37, + 0x02, 0xC4, 0x2B, 0x02, 0xC4, 0x1F, 0x02, 0x89, + 0x70, 0x72, 0x6F, 0x70, 0x65, 0x72, 0x74, 0x79, + 0x41, 0x86, 0x76, 0x61, 0x6C, 0x75, 0x65, 0x41, + 0xC4, 0xBF, 0x02, 0xC4, 0xC9, 0x02 }; this.VerifyWriter(tokensToWrite, binaryPayload); @@ -1600,7 +1600,7 @@ public void ReferenceStringsTest() #endregion #region Array [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyArrayTest() { string expectedString = "[]"; @@ -1622,7 +1622,7 @@ public void EmptyArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SingleItemArrayTest() { string expectedString = "[true]"; @@ -1646,7 +1646,7 @@ public void SingleItemArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void IntArrayTest() { string expectedString = "[-2,-1,0,1,2]"; @@ -1686,7 +1686,7 @@ public void IntArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NumberArrayTest() { string expectedString = "[15,22,0.1,-0.073,7.70001E+91]"; @@ -1726,7 +1726,7 @@ public void NumberArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BooleanArrayTest() { string expectedString = "[true,false]"; @@ -1754,7 +1754,67 @@ public void BooleanArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] + public void BooleanLargeArrayTest() + { + string expectedString = "[true,false,true,false,true,false,false,false,true,false,true,false,true,true,true,false,true]"; + byte[] binaryOutput = + { + BinaryFormat, + JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount, + // length + 17, + // count + 17, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.True, + JsonBinaryEncoding.TypeMarker.False, + JsonBinaryEncoding.TypeMarker.True, + }; + + JsonToken[] tokensToWrite = + { + JsonToken.ArrayStart(), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(false), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.Boolean(true), + JsonToken.Boolean(true), + JsonToken.Boolean(false), + JsonToken.Boolean(true), + JsonToken.ArrayEnd(), + }; + + this.VerifyWriter(tokensToWrite, expectedString); + this.VerifyWriter(tokensToWrite, binaryOutput); + this.VerifyWriter(tokensToWrite, binaryOutput, null, false); + } + + [TestMethod] + [Owner("mayapainter")] public void StringArrayTest() { string expectedString = @"[""Hello"",""World"",""Bye""]"; @@ -1794,7 +1854,61 @@ public void StringArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] + public void StringLargeArrayTest() + { + int stringCount = 20; + + string expectedString = @"["; + for (int index = 0; index < stringCount; index++) + { + if (index == 0) + { + expectedString += @"""Hello0"""; + } + else + { + expectedString += @",""Hello" + index + @""""; + } + + } + expectedString += "]"; + + List binaryOutputBuilder = new List + { + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array1ByteLengthAndCount } + }; + + List strings = new List(); + + for (int index = 0; index < stringCount; index++) + { + string value = "Hello" + index; + strings.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + value.Length) }); + strings.Add(Encoding.UTF8.GetBytes(value)); + } + byte[] stringBytes = strings.SelectMany(x => x).ToArray(); + + binaryOutputBuilder.Add(new byte[] { (byte)stringBytes.Length }); + binaryOutputBuilder.Add(new byte[] { (byte)stringCount }); + binaryOutputBuilder.Add(stringBytes); + byte[] binaryOutput = binaryOutputBuilder.SelectMany(x => x).ToArray(); + + JsonToken[] tokensToWrite = new JsonToken[stringCount + 2]; + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int index = 1; index < stringCount + 1; index++) + { + tokensToWrite[index] = JsonToken.String("Hello" + (index - 1)); + } + tokensToWrite[stringCount + 1] = JsonToken.ArrayEnd(); + + this.VerifyWriter(tokensToWrite, expectedString); + this.VerifyWriter(tokensToWrite, binaryOutput); + this.VerifyWriter(tokensToWrite, binaryOutput, null, false); + } + + [TestMethod] + [Owner("mayapainter")] public void NullArrayTest() { string expectedString = "[null,null,null]"; @@ -1824,7 +1938,52 @@ public void NullArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] + public void NullLargeArrayTest() + { + int nullCount = 300; + + string expectedString = "["; + for (int index = 0; index < nullCount; index++) + { + expectedString += (index == 0) ? "null" : ",null"; + } + expectedString += "]"; + + List binaryOutputBuilder = new List + { + new byte[] { BinaryFormat, JsonBinaryEncoding.TypeMarker.Array2ByteLengthAndCount }, + // length + BitConverter.GetBytes((ushort)nullCount), + // count + BitConverter.GetBytes((ushort)nullCount), + }; + + byte[] elementsBytes = new byte[nullCount]; + + for (int index = 0; index < nullCount; index++) + { + elementsBytes[index] = JsonBinaryEncoding.TypeMarker.Null; + } + + binaryOutputBuilder.Add(elementsBytes); + byte[] binaryOutput = binaryOutputBuilder.SelectMany(x => x).ToArray(); + + JsonToken[] tokensToWrite = new JsonToken[nullCount + 2]; + tokensToWrite[0] = JsonToken.ArrayStart(); + for (int index = 1; index < nullCount + 1; index++) + { + tokensToWrite[index] = JsonToken.Null(); + } + tokensToWrite[nullCount + 1] = JsonToken.ArrayEnd(); + + this.VerifyWriter(tokensToWrite, expectedString); + this.VerifyWriter(tokensToWrite, binaryOutput); + this.VerifyWriter(tokensToWrite, binaryOutput, null, false); + } + + [TestMethod] + [Owner("mayapainter")] public void ObjectArrayTest() { string expectedString = "[{},{}]"; @@ -1854,7 +2013,7 @@ public void ObjectArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitiveArrayTest() { string expectedString = "[0,0,-1,-1.1,1,2,\"hello\",null,true,false]"; @@ -1905,7 +2064,7 @@ public void AllPrimitiveArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void NestedArrayTest() { string expectedString = "[[],[]]"; @@ -1935,7 +2094,7 @@ public void NestedArrayTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void StrangeNumberArrayTest() { string expectedString = @"[ @@ -1994,7 +2153,7 @@ public void StrangeNumberArrayTest() #endregion Array #region Escaping [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EscapeCharacterTest() { /// @@ -2026,7 +2185,7 @@ public void EscapeCharacterTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnicodeEscapeTest() { // You don't have to escape a regular unicode character @@ -2042,7 +2201,7 @@ public void UnicodeEscapeTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void TwoAdjacentUnicodeCharactersTest() { // 2 unicode escape characters that are not surrogate pairs @@ -2059,7 +2218,7 @@ public void TwoAdjacentUnicodeCharactersTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UnicodeTest() { // You don't have to escape a regular unicode character @@ -2083,7 +2242,7 @@ public void UnicodeTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmojiUTF32Test() { // You don't have to escape a regular unicode character @@ -2107,7 +2266,7 @@ public void EmojiUTF32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ControlCharacterTests() { HashSet escapeCharacters = new HashSet { '\b', '\f', '\n', '\r', '\t', '\\', '"', '/' }; @@ -2132,7 +2291,7 @@ public void ControlCharacterTests() #endregion #region Objects [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void EmptyObjectTest() { string expectedString = "{}"; @@ -2154,7 +2313,7 @@ public void EmptyObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void SimpleObjectTest() { string expectedString = "{\"GlossDiv\":10,\"title\": \"example glossary\" }"; @@ -2222,7 +2381,7 @@ public void SimpleObjectTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void AllPrimitivesObjectTest() { string expectedString = @"{ @@ -2425,7 +2584,7 @@ public void AllPrimitivesObjectTest() #endregion #region Exceptions [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ArrayNotStartedTest() { JsonToken[] tokensToWrite = @@ -2438,7 +2597,7 @@ public void ArrayNotStartedTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void ObjectNotStartedTest() { JsonToken[] tokensToWrite = @@ -2451,7 +2610,7 @@ public void ObjectNotStartedTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void PropertyArrayOrObjectNotStartedTest() { JsonToken[] tokensToWrite = @@ -2466,7 +2625,7 @@ public void PropertyArrayOrObjectNotStartedTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void MissingPropertyTest() { JsonToken[] tokensToWrite = @@ -2481,7 +2640,7 @@ public void MissingPropertyTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void PropertyAlreadyAddedTest() { string duplicateFieldName = "This property is added twice"; @@ -2501,7 +2660,7 @@ public void PropertyAlreadyAddedTest() #endregion #region ExtendedTypes [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int8Test() { sbyte[] values = new sbyte[] { sbyte.MinValue, sbyte.MinValue + 1, -1, 0, 1, sbyte.MaxValue, sbyte.MaxValue - 1 }; @@ -2531,7 +2690,7 @@ public void Int8Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int16Test() { short[] values = new short[] { short.MinValue, short.MinValue + 1, -1, 0, 1, short.MaxValue, short.MaxValue - 1 }; @@ -2561,7 +2720,7 @@ public void Int16Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int32Test() { int[] values = new int[] { int.MinValue, int.MinValue + 1, -1, 0, 1, int.MaxValue, int.MaxValue - 1 }; @@ -2591,7 +2750,7 @@ public void Int32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Int64Test() { long[] values = new long[] { long.MinValue, long.MinValue + 1, -1, 0, 1, long.MaxValue, long.MaxValue - 1 }; @@ -2621,7 +2780,7 @@ public void Int64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void UInt32Test() { uint[] values = new uint[] { uint.MinValue, uint.MinValue + 1, 0, 1, uint.MaxValue, uint.MaxValue - 1 }; @@ -2651,7 +2810,7 @@ public void UInt32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float32Test() { float[] values = new float[] { float.MinValue, float.MinValue + 1, 0, 1, float.MaxValue, float.MaxValue - 1 }; @@ -2681,7 +2840,7 @@ public void Float32Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void Float64Test() { double[] values = new double[] { double.MinValue, double.MinValue + 1, 0, 1, double.MaxValue, double.MaxValue - 1 }; @@ -2711,7 +2870,7 @@ public void Float64Test() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void GuidTest() { Guid[] values = new Guid[] { Guid.Empty, Guid.NewGuid() }; @@ -2741,7 +2900,7 @@ public void GuidTest() } [TestMethod] - [Owner("brchon")] + [Owner("mayapainter")] public void BinaryTest() { { From 459a865d323ce0009520420b4d802a1d0e3bf775 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 24 May 2023 14:23:56 +0530 Subject: [PATCH 120/337] [Internal] AI Integration or Open Telemetry: Design Document (#3858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * first draft * redesign * ädd link * updated observability url --- docs/SdkDesign.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/SdkDesign.md b/docs/SdkDesign.md index f3f2ec1581..62d4a751f7 100644 --- a/docs/SdkDesign.md +++ b/docs/SdkDesign.md @@ -186,3 +186,32 @@ flowchart LR ConsistencyWriter --> TCPClient ``` +## Distributed Tracing (Preview) + +For detail about usage of this feature, please see the [Azure Cosmos DB SDK observability](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/sdk-observability?tabs=dotnet) + +```mermaid +flowchart TD + classDef orange fill:#f96 + classDef blue fill:#6fa8dc + subgraph ClientContextCore + OpenTelemetryRecorderFactory --> CheckFeatureFlag{isDistributedTracing Enabled?} + CheckFeatureFlag --> |Yes| CreateActivity(Start an Activity or Child activity with specific kind Using DiagnosticScope
and preloaded attributes like containerName, databaseName, operationType) + CreateActivity --> HandlerPipeline + GetResponse --> TriggerDispose(Trigger Dispose of Disagnostic Scope) + TriggerDispose --> CheckLatencyThreshold{Is high latency/errored response?} + CheckLatencyThreshold -- Yes --> GenerateTraceEvent(Generate Warning or Error Trace Event With Request Diagnostics) --> StopActivity + CheckLatencyThreshold -- No --> StopActivity + StopActivity --> SendResponse(Send Response to Caller):::blue + end + OperationRequest[Operation Request]:::blue --> ClientContextCore + subgraph Application + OperationCall(User Application):::orange + end + OperationCall(User Application):::orange --> OperationRequest + CheckFeatureFlag --> |No| HandlerPipeline + HandlerPipeline --> OtherLogic(Goes through TCP/HTTP calls
based on Connection Mode):::blue + OtherLogic --> GetResponse(Get Response for the request) + SendResponse --> OperationCall + +``` \ No newline at end of file From 09e6facad468954b9ac9d51452a39fc207b5035f Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 25 May 2023 11:55:41 -0400 Subject: [PATCH 121/337] Benchmarking: Adds use of ARM Templates for benchmarking (#3838) * initial commit DONT REVIEW * fixes and documentation * Apply suggestions from code review Co-authored-by: Matias Quaranta * requested changes * Apply suggestions from code review Co-authored-by: Matias Quaranta * name changes * readme changes * nits + changing case of parameters file --------- Co-authored-by: Matias Quaranta --- .../Tools/Benchmark/ARMTemplate/README.md | 73 +++++++++ .../Tools/Benchmark/ARMTemplate/arm1.png | Bin 0 -> 73958 bytes .../Tools/Benchmark/ARMTemplate/arm2.png | Bin 0 -> 85941 bytes .../Tools/Benchmark/ARMTemplate/arm3.png | Bin 0 -> 15913 bytes .../ARMTemplate/benchmarkTemplate.json | 154 ++++++++++++++++++ .../Benchmark/ARMTemplate/parameters.json | 39 +++++ .../Tools/Benchmark/ARMTemplate/run.sh | 2 + 7 files changed, 268 insertions(+) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm2.png create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm3.png create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md new file mode 100644 index 0000000000..f829b79bc6 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md @@ -0,0 +1,73 @@ +# Running benchmarks on ARM Tempaltes + +[ARM Templates](https://learn.microsoft.com/azure/azure-resource-manager/templates/) makes executing the Azure Cosmos DB SDK Benchmark extremely easy, with very few steps involved. Plus, it lets you test and evaluate performance quickly on multiple resource (CPU/RAM) configurations and across multiple Azure regions seamlessly. + +For the below steps, you will **need an Azure Subscription**. + +## Steps + +### Deploy with one click + +Just click in the **Deploy to Azure button** and it will guide you into automatically configuring, deploying, and running the benchmark. + +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-cosmos-dotnet-v3%2Fmaster%2FARMBenchmarking%2FMicrosoft.Azure.Cosmos.Samples%2FTools%2FBenchmark%2FARMTemplate%2FbenchmarkTemplate.json) + +Please populate the `endpoint` and `key` for your Azure Cosmos DB account. You can [obtain these from the Azure Portal or through CLI](https://learn.microsoft.com/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key#primary-keys). + +Optionally you can modify the other parameters, such as the `throughput` for the container that will get created, the amount of `documents` to insert, the degree of `parallelism`, and if you want the container to be deleted after the benchmark is run (`cleanUpOnFinish` `true/false`). + +Additionally, the template lets you customize the size of the container instance that will be deployed, which you can make as similar as possible to the instance you will be running in production to simulate results. + +### Deploy with Azure CLI + +First open the `parameters.json` file and populate the `endpoint` and `key` for your Azure Cosmos DB account. You can [obtain these from the Azure Portal or through CLI](https://learn.microsoft.com/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key#primary-keys). + + Next, modify the other parameters, such as the `throughput` for the container that will get created, the amount of `documents` to insert, the degree of `parallelism`, and if you want the container to be deleted after the benchmark is run (`cleanUpOnFinish` `true/false`). + + If you're deploying the template to a resource group that does not exist you must create one first. Please note that the name of the resource group can only include alphanumeric characters, periods, underscores, hyphens, and parenthesis. It can be up to 90 characters. The name can't end in a period. To create a resource group use the following command: + ```bash + az group create --name $resourceGroupName --location $location + ``` + + To run the benchmark first navigate to the directory the `benchmarkTemplate.json` and `parameters.json` files are stored and use the Azure CLI with the following command: + ```bash + az deployment group create --resource-group $resourceGroupName --template-file benchmarkTemplate.json --parameters @parameters.json + ``` + +### The Benchmark + +Once you create the benchmark, it will do the following: + +1. It will create a Linux container named `cosmosdbsdkperf` and provision an image with NET 6 inside an instance with the configured CPU and RAM. +![Provisioned Container Instance](./arm1.png) +2. Clone the Azure Cosmos DB SDK repository with the required files +3. Execute the benchmark and provide output logs +4. Stop the instance + +While the container instance is running (or after), you can either use the Azure Portal or the Azure CLI to check the benchmark results with: + +```bash +az container logs -g $resourceGroupName -n cosmosdbsdkperf +``` + +Additionally you can check the logs in the Azure Portal by navigating to the container instance and clicking on the **Logs** tab. + +The logs will show the information, including the initial parameters: + +![Initial benchmark parameters](./arm2.png) + +And the results: + +![Benchmark results](./arm3.png) + +### Clean up + +If you want to remove the Benchmark instance, ypu can delete the container from the Azure Portal. You can also do so from the Azure CLI: + +```bash +az container delete -g $resourceGroupName -n cosmosdbsdkperf +``` + +You can also delete the Benchmark instance from the Azure Portal by navigating to the container instance and clicking on the **Delete** button. + +**Remember to delete the Database and Container** that were created for the Benchmark in your CosmosDB account if you did not use the `CLEANUPFINISH` parameter as `true`. diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png new file mode 100644 index 0000000000000000000000000000000000000000..c740b8b3d7528c4f7232b24da55fee45cdb4f6c1 GIT binary patch literal 73958 zcmdqJhgVZw+r|mfL_}3OQlnBs=mA0qfjPe4yz|YPe_&=!)?%>^hb+xLd*9`ET{o{DnHg}O5;(=g#Kdj* z@SX(|6Gtx-(+Q80?7&ZMtxQ$|-q_vq?vx*4_@f!rR`0bTYPvB+?S!4K;s@hCPvP2 z+oOVB6`W%FCXc22W3y)S(6~?U2MblPte%J$rN)`P<%Q8#Xa2PCOgX zJ?`}^jFP@)kd*T3g5;znbLULH=O<>D7pE?zs30Bsh6*&-(wWZMeR-xAO~%XeD~7+# zR}bt)oB$U5AKe5V(acZ*m6YGa$ZH%tLYrJ-q~q4mjZ|UHkZkNRgIZ{kr((K-ueipw zh*iaj^km99lmsrBjh2VPB2F>=Biyb^{Nf)Ux&NDE6zzic9DS|{e|<4k$zGu^U8>$~ zD1QQR5UCL`|8E~!vjOHQEv|LO$Nad9$F<~1{6QU@;sLBi4^A#mdvNaNwU3ck4M$5- zzYXzFmav{6Hl~jc-(5BAPnQx8&Q&@uV{;RSdudZ0S!-`;-{_rDARYALLCd;1qFVtW zj)48L=W2GUhQ7CMHK%NCeJ=mIoqi|i?2IMU(y1G&s(*k5O7)ov?HzJzb;m8nlpM!0 zpO*{~O0$VKQ7k)_a%lE_2mE3lB-s^sHf5QI$f@R4DWK(`edEXLOYhEgCFEi2J%*G>LAlZ84NKy} zl6C`~2b#t5p4Fz|?k6_C{Q3Usnqitmqb_YU64TeyV9~nhlDl-%?o(&v@yCFLF)2%v zgHsCwIdUo5>a>DBRYLU^eKm(Dg(28f+db)i7`i=F)SVa9{~I-nFe}gyx301}lb*$% zU%S{BuR~vbk4(<53vH~lKHPpBr5myL487oWRJ%jH(+pZdB0a495Rm1NWu5VLm0fki zu9w^<;DU9v(DnQsGJ#NCA6-tLpNnI`WDj<}S%+j|(mjt#2;Q{_?ZL*XV_k24W^L(0 zzm8BH87w5cu$D>>C)SdS+&j4i@p)RNt#F=wN3mZi{8~Iro5d~g0jjDPWYq1vOvp2e zGh2D}j#7UxGsO=Rue{-dZ>SLZ)Zdc~e(xzB7 zN1AD#O3qzUm)F;T;UaAHY46PM|DMx7#V7a7_fIp7=qvXKo9ETD=QCAeTZ>pMQwZN# z4mdi5^Q)|K(L%;l2b7S#I)XPq{RCJlGAN7C1BD4Ie`B#hE~ zOQ2ItiToQUnVxT7r(s9MjZLnY#V_V4c&gA!Lh2Qtd}F1p;y{O^B+R;GVdTxi7@e_; zI_D+LZoa!_@DBLu-RGP$6#&gcna&1G&b`AakZRFKsb!`D1E^r~3APWxryIs9Eb|hY zj3{nvdx{+y1cSGiZ`;8m#y*;h!?!P<*Nu);_F55zN_9zy>57(f}Z>HRXnWWUYIDy(hLGt9$I$ zPhgJ!eWjHAe!#9d1o{2V68*I6)}J4v!~>sk2IbR|V5g z-wLUJGs#o*Yy!>NZtthxG@tgwm6>`>c5@3xzP=>&%=y5XL|h>XX$O3dw6S@)VA*Wu zqlmtu&pu@t6^RO>4V&O-L)khrCasT4qspJ?D>}JoM+8w@{O4X`8FXsYgVUnEWf?#y zTA>+V~uOX*rZK^p66};wMMqQigF=6>-7PvHc8?KkppAl(>(1L)X zwhs+t9Z+MQ+w+Dxp&PTxh2x?zhwEvI1|cz|qXTFh2r=CIP+Lvq2iZg>hW2off5tFBb1UD%`IHLA)Ty$zE z1kdva?W&rg>zh(el_j9KLt12}oYPa#u9N6Y!kHzVuTlw`cehQh{nF43A~r&1`b&-@ zmmk$*GuGoniCgVNzdfnVs}Z^Gijpy-@a6h}3>jPY2!1_IAe7cbVc~GID*F#8?0fx$ z!5!-=n*(IlI>%B@tY`Fa#|&L!gWI=*o9XwvG*9m%$M=!yg+{zG`wPcxT=Uew(F(0# z?l)irs&ZV)Ng!)*9L|{Q$#w~1aE*>g((Xj94ok=~y~46=e}K|n>W|>(q5t7h#LxrvO&4gM2Pc(M0zBRl1H8Nd2mPEI5S<^I;!XW!^fpayU)e&TIK8HaoA(; zBB=4+c^eJJZ2uk8H36AxXRC^&fMb#Nl3O5mQq~CCo-SqC-9~JOHq%6z+ThcN1{pW4 zjl9Rh2gYK9=CN7Cpa@cq?^f~svToOjx`pbGI!454)@!sxdSjX z1Js{Y`&b9q2ZXWAqa7UR`Au~ADc@OerMh=Fz-R05H)>*zrVPza`K!2{I& z|NJAQwyY^3$)xo*B>1C~P;QMF6zv0U@lxMnP>ESeBGhRkhrFHT30y7L9F#5c}qkwaI8&c~gn+*q2vQwoqrGPgT1HBeZ*o z0zcY_ErAI_x*>yY1QMLGxC`YJc+~K5rjiBXf{fI(e%@HQd%TzgtU8bv)?0}n@`4OaATGZiD)*z7Rab-gHsF< zTD93!wo{jY$5ENRJ9=0Y_A1rmV7$uK6!GJ406ekQuD=0qyx*|sGr1kUzj^L&(e^*P z=-t%^;VTO$jo_93JQ#kP+IqnPh=q#UGNkQ@omF=Pv*r#%5Y|D;S|SJJs`y;Gkw_V| zYYieGibb;aJZx*Dqw0kyZ(GAS4Kt)O4(S`{fQ%DR#TacQ>!dalE8V+8hi^y47dx3R9}1g=@=95hG&u910*2-0pH98d z4_@4XSf0gaDb8k50=obC67a%zfQfa@pCVey!y25w{lq2m2}+~Nv7)%meE|;c^!Kt= z9$K<>hW{YerL!Ap{oO5T1F6bYr$ukyEyHF*M7k?E=XwS{zPn~R%eV!UaH0W>TbK$<_mjH)4N{)|}amLv$#(_q(n4m75euWK>yww$$3(9)Mi8uXEcg|CJ>J zBX-Ebx94xqTq4I0A|0BuH}JI%p3=QgKS?K4kO%k<0*+{|t6|>)qC3@&h8QxAH!(!| zjD8-kvaXWeUBTaWRauEA6qOhkI(rjpTxX9ryDlr1xno6UOhYrj@{W26Fhj&yW;P}Z zJbs*7V5~(jd>#p$Wtsj1WJIMesp^3qbX@&8nZ+0)JiU{e8_t z(6YpYe;$^awgm0eaoBsdH^vdLFyt`A=+w0kGwi2EPO-x_yn8Xkbs z$}lEAX(Pm#jo@iPVQjMvQnl28x?blsa@Ue>0F4O8$8y%h^1&Vjy*=f_eBglu$2o)F z2s7PXF{dRbv8lLiK86qUZ$uyZ=L>21-KksZeKNC}rP|2S{z_!-YvSgIl)sPAxKO7( za(9=o-7N^q#RAPzYQ5)BHg#6ZZ1(7uMn_I_q@zpt2Og&6(V{2%Il3`%aL8j)7f&l| z09x;IZis_$|m--O7+d)At-MoZZ{`SeKgF_070t-QNrQ zAlds>jqJR#@UM{HI(KR+ZENMME3K4g+)NN!Qp0RI!IM_%Av+)24pyLbVSN@kx3*Mi z`*Wa@J8>sMUJs{ThghIbY&pQ%eKId>jyF1}QnZ==kyw-V1OS2rkAUX7L5?P@Ba*gY zJBkVxj8R{6BAxcHN$wUG@}9Tu&3$rw;Dw?ROf0YZ(wTKqt|syGA#TkdkG^6 zOyOy@JIpnImv?gXJkvJ|zk!TNBc}{Gr^$x4F|mdacuOc&MA774+zB=ebvA4fKHHB1 zj?=rjp5(m8p!_fXYZVx^3rMZ8@Wn5d?P=og2`34w5f4~ly90j zRG;Bju(GKE%kHj>t2zZH(fy~dwLauY^b~k?UQ&UKnA z|8yK9b&n{EvL?xQ$arK1zhYS)>8q@ay8epRK)}r0a6oNl43DtJ4f@`CVg}P?)EM+ zozzx^O)DX7l=j!Oti~ce@vHVnsBqkK$M<(%4ASp&@#Rjw9*Wn;6qebuDgW&XHp3bs z>YTMBdV$XWuu*y}V0qp!4HMyWg*1UIo&4;Y;L;&9-KH&usVY$T+~jx@+>j05uTq}; zTbH|ZdQIVx3Ws^HRS?tJkh|cT!A$K|{sHrz1B4cd2Pa#?-lOa#auGwx-x}~VDf9*J zsKF6BZGsF&Xu!da6jVFFNG>A(p{L_4CQqereWoMh{;v8r;L~7;YCB)cYYG+dC2}&M z>slUBL5xQC3RP6WOJ zf%{irJf#RZYCnl%SJV&V6Z9u){inGZNB`8y7SbZnZroTuL@fJ4nLOaUk7X zg{mY7zxIQ-kC)brDBiL>7?crS=$wso>Xz8+|IXUgv{T(GS+oyZg6RThG~@$w;l9W^}Vg9i|ThK6iVIqRwq0T zcg_fF(i&fn#iDe6;hae;g!*l;405qCOWtWOi?DJSO`}Psg?b~ZX%PjJusr`!=AhLPLPGr0Yb5=N+QFK0hsMOfpKn{)%S0>6DD}Al}T@)xC#R+M(X- zi6U^Mvm8)WDa*Ll<{a1*bt>mLSai8#n6_-(Gc@KezcJGe#j=In)_zkr(Z$+$n%kLG z96)>3n}4&~LmBlBr`9I7-jtE~a$TS^1lw}_B@F|?$>&pvtg_S&VoiY*Wd(-Nk-uTv zR1F_*j>ekVqoKJ=s<07@IuDG;^Ep`CQ7&3ZV<=p_>ZUU~nne+NQOe@s=chj~bfD!K zITZ1p)QO^J8MaQw2<|<`ek_Bf!FTeD7SEAJgeI%iF z@lu^z-&JB1wY}|$dy@a3@3;BK49OYN*538gqwf7brI^Kby!5O;h&m&f?!}VKIf`2Oz6%NhIx*2Wqy6jPd?`wPOyA&P?`VKK5W_HC zsu-M-?l?N;qL21$vx_eO{+8q-Gx2X}dDemQ07HpBAbG}g8F@9Yu^_c9aNZpiJUYsq zvmZP`F>qvN9%W$wCUVbr1~uMrcN~%^pqzQzHTstOGgztvxz;s{*dAeVqY$UD3y~?KSYHX9-sI3XKK!4jrUo_f#)1~=-fld_oY0nn&LL1Q0n#KP3`SSO(Cmeh5|}nkDCmr)dW-2sRD{)YK#ukO7%Kk@cLAOP+a_srT4b}?#=8qwGO`>t4rvtq!TQkpIu z?`FBUbr13f%x^wv3Ee<^f6Z$Q92N;#a8o*fkBt90d2V&=zi(q&|9|K$Z}ranU-y{& z*iOvh2?)Q z9pjk(e{_=;=+@a8XVL5&r5?CgO{+d8FNww+^hKUAM!j88_U^?a9WYB|Laj0VjPRhw z3j`N>TBd%xx=nEguS) z>*l5lQaQ7+*KWt!E+YUbNLFeMKX13ijT@$3v;+P-Cr-&S!$1RD95 zuN^J^sCzb{P_YFR(U3Wbh}ZPPy{Y38vjP;*g`bNs+V|gGQRdf){HN_;l5A1zCMD(a zzBp)Y(n-#xF24!&y&8EnLP$4&2b|Vm}7gHe*}sRt$ z8V^P9L~2*x#w{3Um3Y=Bx2ZIZ_Ses#f)&YC6#sQo;3GlHH+l2tDq~tbFamV>*iWT| zH_oczjAfcFGCVjf84}IT#B-sd@JF<0rSGg5%PAk@EZMZcr6J>SY3u7Y)!7nhg{m-w z+hDfdcE|SX0_kS}SJtfq^udZp9c|Z5bFJ2=TU<{i+0ofxAn94m1-s5jof2Q5 z*LUqc6qB*3Nh!Yn`ln@A5_<~zvWiKPsHR*?z(QR)d&ok+HNR#^^?YxRK2VTJpSybR z6PmL{(Q~L5=p8UEe-77IqBZ?~#S&qG4*`yB0sw!xsU}#KtqW4B7GHe@U2)SEP!U=rIl~ zio^aB=<_wAjE)Y-u$Hjj#p(~sMJ@j!*;uqEd***=`72JHUR+9B=%&R=+g( zu04YK(4QRWw^6>UQx;m-Q5P};u7J!)j(v2-pwM(snOUB9#?n>VR1&wKN`I2DW{LlY z2Np=MH9%6+;k@;kS+Y_NxgV; zQ3ZPzP|jr7wwEXlg;3jC!?%}5N&$>!QS;1R5&1aoM5;!xfPKf)`yWM{W994?w)-q4 z^629$_-JWx!$-%qFmsQgTwb>vCmDMl5e2L6P!3vt)B*|Drrqtg zqu&G?I(%EbA#f6&pH3nZ6NPTyU7tbA>$CHuK4;^~Mvrg^9Xula`l`S9^?R4JzF3g@ z(*2RAKjvl09$J<_czo|*Dg#rGI(SPz@8aE=`fXQP&c`%=~G z;Tf`)56-L-x}>{Ks>n8O2M`J^ee~=ABmC54k-v8A-qf! zobPBvH#Qrzmybd!s?j4wLH`NI(a3;>{#3%`8K)-um%$ss`P&Sr{=?HPwd z#DD7^?d$*fkt_*lVMU+MBVH?45qd$o$2T##DjAnBd3k~6GH5UCg&4CukEkIrdGujj zfk5Y*MMIYPpwCHsLj_aKA``slm>iF(KlqKcZ-lc5shSC)1?`(hF6{uRNI`XfB2cUC zc_*&PcSd8PBQUGs*~nds>mXlHl+xO)nM1y9jg?{QPvw2zX#q9hvkB~-` zel#xzf>E}Y>Pvt-HI)OYSL`MvWg|oDh$UunTh$m}9k9E?tL_=fERy;+?~)RmiZH3- z^$`2WwMpxUl`aT%LdK^07PAF+lV(GteQALEh3m6TKCRl;ciq(*Qf^u{+csG_O5su4Lby#cY+4knMQ&ec>qwc=rK#e`i9T7Qn4-~&-f zF7I8(Sx= zCZHd2EA1sUsS&nRz1w$fQs^qb>^`F8%S>{f@}izQH|bNe@IOZfEsdd`YBSxz9cE@hOXxuQbd! zrOIgByAFc$u>bT+KF!P}TsF)%>!<^g6*UC2rY8wAqSLgsS3>VBmG&4Ur-{frWiG)N z)chW!cj@)xK|D)ZMZ=VpC+;k~ep=dqTC7_GUNZLc%8Eh70AO2O5>%kT1}2|zNH2U&XF!5RHW6yoy%uhLsiic8ZHGqOiXve zE?jwf{nf=jRkh3D1#c{z{r-UCL4iY1XAFnS&CTP>SX%> z;%dO3c}|>z`C#_#RjDg{sqQO`(vW&2y|?}?oHTmh@|;-k%Gh4|@RnMSDekn0*1g$J z>!HEV){2%7$V4x)=bFg$J0-~Zzm~bOR%$H0D{Zf)g4#PLY4WLD%h4@Db4N$7Frfra zb4M2;^y9<(QYErJ7$ogap%Fucnx4`O^fTc+1Nc(G%Wc~5mA?W^gwdvYkCFpEf!OTL z6NU2}OqqlMLgFq9D85^%Vf57^a_f)er}6`%>>KY%_a7w~o($XIW=ito6(ex;Bc~cN z0FE*Mtwl?;>#m6VfSXm~ejl&iiPs5(5jx_n#WW-~I_OD;6ud*D+fvQUXbXkIL&S*d ztiWk}EHXqDS8oss87Xcd2^<2&hD4$(wZ>^1Acn@fE7qkmbRY5Xx62-mxMRjqLL>v@ zCuLhx9YmhIAF$XfuKQLP&^&16jI0i)Ht)wP^pOw9Z+9=Ht#|S0-kQNgQW;c_)2AhS zKe)C9ktQ*2vl|WrBf-*-#Lz;z(cdC#l`J=AKO{_Wpqx-qlWQxRzq>H;4`B`TA-#AG z<54%m5@;3=CIq1!YQui|@Fy(B>pk>WXPiRJ*As9?BLNc`tToAHbLA2AzVu8cK-v1M zC+bUsNEQ-_Ar(sSek;pf_~jX5%#r#GE2`3}<|+_9_H5q-^`(~DJn?TM^*?NGefr~6 zS%d`lSyF(o!1on=d&0d}0^_R&Q4r+Ag0i{G@X-^wBFX(3(*3DF-jskgW=DZup~AAY ziROGv@cC%}p^SD~%QW27Bv;{n$m*mNp#7&zHWF24j(LO+S`Ih6c^3YLM*t_gbq z1N}sHZhr6WlL^jzGZ8yGSwQro4{Gf(&Ds<hbFE`wx9xN;j&>qa99~uP&;mW)LDhP;>aX)NYhL!M{hw<_7G9Ehbl483Gs@ zH&mTqN1DN_o4s1|=2Nu;xX=A4Fgcn&SM};=z-r8;4CRT`F4-CgTr30YOD>S4`j;9;L1VGd&JB2`LTGUi@a@(vofvaS_v)E zFD4Ms-aLF<`6##Uw?c412mOm9$W~ul;t@mKzOH1kx$>`nFKJD4zP@K)c-Xc0zwt;! zQ@aUqqN#|$0OYT@vXR$(`Y+Gi=J^~%o7B!fsyTy~8v%q8((}4dqBHG~B7gnK^M5?r z+ZxY=`u^F`!vU2QgYA#KUAtT2vAC87!m?m3MULv$3atdmv@g@Gs{>fRpHY&p+&YcP*ja%4M>+4oax;7`zk}OdkDVLJ+h05K2^5UaPdO zl5o;ly$NxNwg)T_%LE0#m4*tB>Pdul_`^b-C=(Q5Iql^ujFAH%dnV8hI^e6FeSjLh z+1Zzfk^;1L1&9)oy)K4KOiPMD^AS~QpvE6rs$iIT(KzGsV1L#e0drg9>o~X zN?sK(5KT||w1;GWrV+e8FRxZJRUbo)=6}LFRN%Vzn?v+r!kINphr_4GafanRw(;iy z`|LZw&yyWhQhOyn;b90l8&r532SdxOC4Kbzebu7Q&CqgxRGT6{!}#yL!K_X69%S44W!TtVl0rzK>+W5m0-(hj^`WpFDiP57hggsNg)BLwgRt zrf+_Wh&JVtBz8D(_S~jM*kvDNzMK;nXm9dbR8W!o?@5`@;({%!X50Ze6?apg@-JY$ z0jqvVa0mLtJr|BLJ@UqbWEH1R@WsA^7%W2Db$sUZUU<(efRRw z2K6{+fgHYk;3eRs>jc7x9#iQXN4}4FgmrEv3Mwn~=rvn6E8g!rC(iUJl{ETxYZ{nZpsJXMu=%z`S zrW$2PJM?&^5H(H?mlXg=v_1Tpbz`;_itfUd@H8)C3*`eB2XALM z<|_F}XH`S%EtirO!{Ls(q2w+NpA00t@W^+0x9XC-)6=8Sf371{ue6vcZ{QBW6lEtH zm`v>`HFP83h?yyNQ-7mz2Vp!w11zE_mzGt-{&78wrMfmnt=$pgcX*BL?69%%Tu^OH z?9;4Fcf)$<^MK^)88PK#z0(rA46Rw;P<2cJHY zj(#2TI%UK+e+io>!!4-vshqWpthJaRYC^N$aLusU!@utgirkH9dUhL^?%T}13W)D+ zpe?fv|Hk6V!0BChZHR0wHTB@_o<9U+iGuZK$jCdPLX>ClF$W|`y;!N z7iF&|R7bs6KI8i1wbX6ow-4){Yi1Mghpeaa zaHed84gJE|qjYKeQDRHJqJf#EmyAWpzv##z{x|*nlH{En#lIeZU}|9d8f^4#fUwtO z@sHR0GwEb*S2;}=DVL6XG}LN|X0eksKh{?Sb*=@sgVzBy7A&Q+BJq%7hS3*(Ul6kb z>jGB2ZLu)?G=Lwx88c3}HCr#vp*?w*&)Nc^gu8B-+CLy){(0!#J&UFwe)L><#&adFYT3fZr?KS)njyJFeeD`E*-4=LxkAHm zpIJ*ah1Ce7gj)jWcm(gP#u{vPP~P=MMXyPZKwmARx)$fk#OxCA$)81k$>8#5~~9j@xE8t&%lv zxPR_%J5!VaM;}Kw9BxzOC5q@@^d5ndb3K*F2z`fZnqOB;aukh|MYK)Tx6F}oq6xDb zBt`c2!r?3%yTgM4dDGHBWJ*njs(zl00N%OY!+{drC4E6-N!N_|M}q` z=tZ-RC>#sM&yt?rOMWtgYgS=iO|X6$?bsT!uF%f%AnD={6p=h{8;zgaLp5$#)jGGE z)J7|MVp3<@>Aiqi(gWO!z9@^z7&;DQO|W?on$*%U*%(2zas$1)+QQE@&0nuw(h#aP zqY935i15u*Spz|ioC9%|xvEt*HK_o0?aPC8oLja(4GhINec?G?w_CjeafgDCWnHI1@2wrelDf4>z? zQ-<2akU!+RN2KXEg`=7Nl|&|fq~K`Ye1*dJFX>O9k$e5S$~4pDY_lLKnT0zXGL^5x=p_E(};##-ttkju1D zfwuxC!$r@pg;f8P@MHbQAeRHe*N6ayWxQ*~W0eK3-GA#=16%U2hq=`_xBpR=KY8Oi zAuj1$rk4FFdYXKBNLVNM&$(;&lm_rx*KY`X#}ye{B-?z`1B{Z5XdlkCLmcUh+{dU) zC5VC|`=^?~zo!Q}a0o16c$rbgD62mfp$P-=8m20JZmi*X{waLOE1HDNY+J+}GeQk~ zXWHCBTgb2Nep^>@+)fBB9xysVsgS1+=Ih5gEypVva#OMTRZ>p*-2=_D7a0Y6|C0ip zvWk*&0-ab($jUztWVNCW8iGipKddYwE+Zq)iyK+>70Sbk5>DQKb4fYFqv21SXRXv3 zAK}%&;|@}Y&W+Dcb(Y(iLCI$bpPtebaL-FTFt+a9J0t}t{w95@XGwPBjNQwCze(+D zi1yJ&sj+_OsK){>Z<7JUO>~ z`?MYOQ}}Rsp%I|@86SleZC+fi_SxxGq9b=Wgm4{o<XbgQ13{wsCzPlDb6QEu6NzE6r z<81f$EY&!aC!H2OYHXWYcA^oFqqD^E+HPJW5rdo;B#oAMbQ_ZNJ!l8y+7s5r_}_gm zx#@T7Jh4w+f^bG08YQy^qPwZ{QmMvmVg9D}I$wg08leOgtn}XM6b!`8kDRWeKZy8u zWx6Ge6Gf!9z+Ot@0&!`3?DVdm{`dpWELG>2E^@oV*~~v+DjJZlvgp+HDa#W$s7`>} zaiTbL=eZihW0HR3jgjKXLPY+hup{c!J;-=n>0gycBWTsF`&QKS-O0334hn<5o3ZgA zQNgLjJGArQ?A6Bv)sbR$^yY`>r<`S?m}+_cG^P}@>CT7(0z)R`^Ut>X#<)pL{mXe{ zy`VXfi^8tfESw2E!eocOPkS?N0uH(f4>zC$}Tngj{SyJ6F_M+CDx{^t2q=pu-Fdx6c1y$!OIF*PI#BiZ9mQ@d9Z(G(A)1eV(C{ z$CbUbN1h_2iz`18Rt788Vkd%bItg2-mEAXv#1*{N=gI^+gbbJH14E4v zFBor=O73ktef=>nbL0s#q52{4KIih}E*Y;~CF&i)K|~95LvauulTtLza(5YW|ThyDSd?x=i)J zrG9`{nVL!?&4V|G^(f8E>TLV54W;kcWdX(ZYJ9@!OnsX;sUkArI3sXLv>_?TQ7z`{ z#r^!d?FbfBqJZ1*9!W8zHf;(N1itek@=){^$?UR6o1JxNoRB0mB1rh1`8xe)~PwZ51Dj(^FG zxpg|mBvw~Dyk30gvKaCB;_Ld>pc3N0tNX%uC1KQ?RFLjli`p0b^Q}^mgNkQjEO56VJ~^yX@N z1>@W?h>5KVg6CQz6Sz9epF-u6XOCWHsQu}ABT1tyqycQx;IGUD+AU=(2Do+J3AcB5 zUtk)5d7k}<#|XgHTR$@?`$^}l={v0#C5CB}tf~!cMdiDK_`dGMyj9SV&rIF@J<&~K za8iK06i1TxHPrn+>r zO#GVA0A28yDQBo_KN4^P2}5W5%Jt)qROB3*Oio?A`S>M%^Wtcv&UJJPqT!|Qql`+C z1^;LcGkev$2$BCO3WUjyGM>wrjwSW-o&zi?hP}nd{KJDZz|Uzs+Xi2FBmYvnA(W+E z9hibCS)FY+08HENpxwssU2k>3(4dZP*M8WSuU_x=uy8hLW=(xC*0(uRv`sidOHe&< zKBW?vNm*BFR4CRTXw5|nZ(rtc!76L>J(p%lkW{bp%mTV@c9hxfL9TK{X1?JvL8;wHaa{QLw#1i#v0XxJ+H8HbL+g;)g7H8d*P{F_ zs_hj{iv&Q;lXKbwwCedbYaMy7nRsm}?j0!2C1PtZM=?QLd4Fd^((KUGDD%dZ9EF$F z&(X8x*c{ECRnZyHd%dL=H_~~^&95y~UHD2mzo>IFsHcbn!HbzvN(PMfwde@n_L|)s zV21wK5O74TRse(aCDH%!o5AOPy9%+Fxbk-=3fh*L=1IJ{B%e7I>N`-8Ch6YQov0A~ z=U!i$OcrOX*PE_b$R!81oC?jn`c<=Gjnu(5=x0*&BIz-FEMIWo9y?XOOoB&;iu zIP2r~Tt?%}955Vo9gwMyyjvl+^cBsmJ0jsYg~8836AFs3s9*dtHYPX$|D_ry1<2@i zbr0U|AVe$j+aUFWK^`3K%Dd`~uYMvDkSwaJ*TGoVRNPy?U6q0g-xbJF2(IKzTK;)w z^1!@RF;_Db!RhBEqcGD!QuOF`i8=NGr;%8~Jtu|^pl@0y>OJ#l2%RXSMF+N4fRsA} z1F1LHrrKe9RqXmGd-?;eNDT>E%}guu1mRvwC>5dPJ=WWBV(eERfK}aoe?yzTY2pHS zLlm8YMfVRtEb>0bHtsr)mKZYj-r)%;}pS_h0lLsbKiD%E?*kMn}to4rOXl0k>(unDrLRZn(MMd{LcO#S1=JpgcW0gU%#Dd;?5YAHpv2#q zO6KFbf;&d|W#fhIla_dWWwLm>Ztxa82;de>R1}pj3*p z=SsCXm3$_@KZ`H_mCl`NM|iK3K5X;r@1KbPDHv*h6x9=a#&)QkJFZyLjc#K2sr5&TZKw z-a7*kKrB`!G-h_0<*UhEkT6M)$HOZcv=-J5x7+p#4)3bFk4qZTKOIW`+7qvL>RayYoEMu%yC+^DDKqp$M~zdf98l14 zg|uk=AMCwnSd(e@_KTu87QhOE6crEw0cj!~E7C+oX`v`cZ_*)DyP^WpJE(*X0qHeX zdXEr#kPe}j!~jY5$~-g9><|0>`0n?=_mdBE96E+0xw-G_TGv|V`8)Yne|(xgOGv)? z+*BTnhZWE1BHLDjAFwIKkm6;enweP~J8SAH7rU+fkm%f+a0=KMKf;L@DvhV(ZDYP> z?roJZ(*tNs1+HUrk4gHlE_9Xjh4u4Cz03}9eKtuy7ui?onB&pDn!(i@s7kGIxkOh_ znFX%C;R65n8SKD*ZX;^K-%1!6LT!&V zDk4Kmrd?^R@AYb;s!vtQkIg#uh>V8yKy>rH&5DrW412V7{|j|QH}cSrnpdTYxT`vw zc^=j7%kK^K{qvVwmkzj+hW%$c-X*1J#5LWH{Y4yDyx-iDcdORer%0U9=|inz*`Yr) zH|8``wzVcJ)i3r16Gw^Q$k7-=dT0lHzzGJi>#iMT4T#`XgJM@C?_sPALa(pPD`j{3 zETfO8K~1<|C?ue&fM(f!5$C5$zxY-dXz-Bb3rbnB3OR#_YzI zlhL_mWuJFEi#cOrS4qyiS@Y~pn4Li9{KZgDj$BbUqS2=6R7roleqygn-lJ>2tEt0o zur$Vq>R-(^z*1wS)va1$ZMU0l-1w+Qa^l$*{)gT}mzX<$81V-pcAoG*n=Nyo3SkS{ zNBdhgjvbHS>{Ixme!|(FroigtL0Q=R^=t1JZ{M)^!G03w;IGZaryuWqy_&O>(!L|U zCm&%S@`mn#F4?*=d2beazZylPcyjl?Zc3zxzF5wughAmnsznHTAp<;3ad+>wa&}W5 zabHl{p|_)9IakRx$asd?PD+1RGF>`?{Vqe_-y)pDCob6tC* z)wY5?VZNqC17(h~J_9R9L~{LR6KCF?)NeCRf9iE(+e$~9ibsmAmjh?7=Sn~xIr)S? z(@fXIV^!JdN}cMR4Z0`|fimZz;(+ID@oY0218J;MYq2~kE*G1kMD3mO9~V)OZb|hU z%-957=CIZz1zaxe4xzjUxvDM26X)rZ!NZoiXVz-a?bt#7Yo}G9<+$4pmxrj|vSK_bwG&cHMMiws!tvWEj-Y>hleLw~`k>8V%Kzud zrb%vELlb+*?98mrw`3c@_1;G#EuoZb_+)=WZq%RvT8-UH{O~=E>}NeG({jy zryAZ4DIV>_Xvgzs$<=K`t50p=c3s{Wf+%xR007HysTV1$CS-P1}t0 zIu@9d>@UWk@E(gjt%(@#%12EDQ9PU1-ts|B<)&q-pQ;+*=8w`zX)80fGC8*KNg~E$ zD_+LYuFb1`OER;10AaYU-lcqow!7RPNo5l@Zn)j?!}P55BHY3;ha1dPXK`rf($A|T zXxok0R``*FIpozv7Hz*NrH*&0kY;-KhMi48Rw zBiaAKM(&n~0gn>0Wry(ku(VyI&C2IpNx7S6>)7m+?JZxdIx*h>XPz`qlER=T*cYkgA~t%3;?u%ap)_) z%32#y(trC|k1s;B`P9dS4<&*H$n{wzce9-yIy_4O+KiW{cn`27nHJo=;HLB7 zdnFBVmL?wOI3zOdMKi@XE$kYAh9+LJT4_wqe==9-1EChTLVEl4Im)2Wyer2#^m!={ z>+JBA=l8LxrNqOs_433@<&5h|k|e5;gef9SWXM`&>uk@yH|a_|NT-CUW;cb01>=fe zJFOogm28wVakp}M@><+vYgl(JjUu}ke0K28yPe!;tQgo6uuB&EsGA-1>DDO$v!uJc z4Er~V>l{ctN+_~#YZ`nL;%%?aVf|-*)TjHV2lQ7aNX*`h-pJyr@7K8%;({-LsJVbH zU!%X?iClQkPpqoHbOdyerVR4YzJupoc;wlJUTIZzU`=6^*mkDR?S5ItcJFxN;(#@> zvtyY5KW`0M3Z~l;#2Mx&*Xo;}ezt@V0hn7Tbse$7tsMK*&54A!ZGqLRH@4X}>O+UXL(R=9Rx~hoO`v z9sJL`{zw7F*Bt5H>?pa2sPLb^`}4oa#*Z%RocnQF^#3%%*8#sXMBjgXP*a0quzyBPx^n~qylE?Uen{%tLsQPoea_LMW~X4H6rQ7x?$D)G&;@J^KI+s9kZdQCJ(MFFQPVKGJaWd#3Q zI)t)krGG_tMj1;fa2aDN3WV8*m`t{Qgj9x3!lFmuOh5p@2ODEZM~Yb86DI;F8%@CA z)8c$CMXdwh+ISTT!2LyZ7tPmdf8D(y2tE?+!!$YB)F+Kp`w$uCNlUcZW#km!VNeZ%Sew=H4)&W!Zy^8^7WLWL}Hd5F`{+sBxb;X75oD978L}ehS zED~qzmb^WA3|x)T@2~7h!0e6<%nD2QI!_pz3vA_+LA$RYbdcPvJkkw|@m+AtuBn_n zsytiy8x`=!-gc895J4oZy_j!O`?(QRsc~%a@%dn!u$=BV0YDzx z)w10O`NIHgs=n#D*qj?DrH#}9mg!sYSTur|Wy?r|S0%uhiDg<`lTG|wO34+Em2n~d zfURGXtD539_aD_~Vbk8)^!PH52dp&KpPF`G8o8jJ*ehG^H`681SLU2TPMCVbbX?r5 z;v}6_GC;8Xy1^_tU8FMsPRdgwKKT0jxvHOEF>is0(}Ze{(JJd=WMYYgDH&YL2$UiA zlq)zHeOXwIF`n9Vz72Tx#kl1?!}EtK)pHFBTP1#^R#+1}tW`pfN(?3*OYvLDf*T8G zl(ODc>X@LqiV39EzUEOf0%41@l@hJWSHB6|2b5j=!nEQf)!$!!39#1C+%Xk{VI;wE z6TKb#>F0DOUK3O6&u_Rg-UT=k+wSZVxm}17hZBUn357a?W^Afii$P(UZ)oxgI3A2P z#Vfhw4tfuycyaR2cYdf^qh`ije#O@9;EWDMYR1Qyo!iX0v`M7a72w8jxc=vy`*9Yz z^_Bk5Sx%iF&O_)Qy1QNs##vjSPR@a+7wqzLUdl5vN0NPIdQ1HiS*ZrpE<|4ztp`QYUbg0xvT8r46=$)qaY7R)Vc6+Wx!6r8d$ zXp@PJaeP%esNf@hEL`XBro))vOPV8{tNC{DqB^p z)`r(-0Hv3jp5x;-wQ*S3;1ize9-X(jN)Dtt-#arwZV{)q)r=A<*-8lbbjOonln zUogA)WRYFBhHo$$q*xn=MQ`N1(%r{_Y|NZ)eMd^ICzp^sx zIVYGlWlSkAT@6)RFqUgwpQtcfqlBu2NZ|$x#A^#OnEXSgeUs8RhgOZbB<~l<;d{_# z);i0m&A!#jea>r&X8I0L*8>PwjEJ2ycUC# zn<`i+3fgr09(?3sepy&L&b~mKpf_pkxpE6t@A+-%=P74{Vw<;d=~JFV@+JPTNG}vQ zCDAM)37uV?K?SzT=`cq!N+9tL4Z0$UGwY6kEQ*hcyY+zF95BBp0Hl_{lGCz1lf)- zzroD;t0bh`F-68cn*VyD0i7?I+3irVGJ(4MGW?@uvkJBHqCQLjqvcBo*V3-B5)+6_ zH!_@*u-gZ1lk!C0mJn7Be%A!9=ap7zHRxgr=p^gkr`1x@HNETMZMkkgm3$_m^jmzE z&L=w3Yf7L(^x^&1szq*>7jP+htG1=6fW)%GV>24lQ&I_{%+=*9Keyy9QwxtGk3S*U>Gp#95`DMFJ^*7ll329orgYt zU#q@}4p72W-<~NH)vryI(^DvQmc`OXvjce~?Od|m-rorbK}#o%nHubWQ zk;8rZ^4AMOIH(^>beLE<>>jyoJ0fKK%}n+7W7IBIZfW2kJlJM?Rtmh=r(XE+s|Fdz zjBy0H*(@1`e(kiVozY2>7ZSXl7zWf0&5*giEp9XJ3@~sCJPgqX7QTR5NFp(#e#{|( z3F(3N7SlKD_pj0u?r^(RH6jl9=DCj{{!oFocuyujTw#Cdrnpv)-0MJ)u5t3HCP-Od zPw-Ehfnky;9k;Hl6gDXDTzv6mhNNXvys8^i7ZU@{YH?ze6n3MEOCn1PfTD+8D1zQ(cb9$8AZBNvq%l!;aUt zm1KQ(F)5=HaohiX*cg6(cf&n07Eq7>QEZ?m&z4_$xm$0fpHtBUAp8>r@_`H0yQghB zj1gxrhB?u=n2;0P{n8_(zSIjnmE#f?UiP0VuFsdDU=^n`?mV-XG#_`iQEhRxHLpR3 zQKu7o8VIBSBTaqS4nq3g6hB)LJRoB==FS%~zR_Q}79n4P+p|ahnePK5MtrpkcB`he z0ay5{rbga_`pK-|9K4$zgRqGmb1BtE)FBb+waT+Y13MmVldb7B{&IrdYTXHmW=dyKf5)plnnZY535<(zjJ ziw_E6isO`ZIs?$Qm$(?uGHy2MSjFWsTI0Bou6B+$^M)O1gm-<`*674@YpD9y22`N7 zmk_<6RHYag`JzXnYYp`3Qb%@FcOH-D;Z?f+*@e6!fE{v+Y&4cwUV+IOTviK zIjdv(Xrm)@7Wq>Z$&1Kg-!Ws>>jCUNYkoL;Ig2_i({>;KBf_^E()@q?QwAuCv|9!l z+cwVuqasei8<%S+s^B#zZBjr7246oB4o*bum7>y<_)?DqB^igoDlfeKh~{H5XU8$g z`&|;=0L7bK3J@lSH;KwuPxEW+lg_U)1cMtIL1~+c_vidb?ci;<7$&gxPlIk z!qaQB(zaWb2wo|x;+7SxVVU%+CI@enOD7d|nV_uiQFR&V0RW zt36n6*cMClU#+#riJe+p9%MoJbo~W5ophU#v}~bY_GDTzUD!l)fzvdqyo5D{DQ`Lg zwvISCi)S;tzebd@;R;Df%S|3h#b2J}Z_;(a(#{uMhkmE`Jb8AFa)!8Ry+Dsc0KQN> z4h}fmYffH%eSGKM4bPuBC)I-aVRecGF>O49HgqjesYBnUjejUi|#3{YeZ$WNsCj3q+VcRt7k%)aNQ3lvz7UxGwm60q&+n-bPhtiUgr3 z*RmtCv{Ezut2_gmu@V{9?eVsC=zOD+`0C}l1S`rH;2IksD(pnetTBqO7ucC!*u{)i ziYuYCW7>AS^}w{05o>t(9B(RHwH)P8AnwxjdFPd)9AJ{F(A={eU*Y= z(jD1H_-}XHb@Lk)+f3GEjMaxA2y!|gToR%g5k8ueU4?EGr0!mt*)!PyL< z564i)Qod?z^dKA*-fH&vbdBKD9f@H$!p;^ZxZIfx^~d4-Ry^3j!M zKr!P-*AnB49XD(773e5FPY3+HwztsZh#M>R?lk9E>&pl~iCT2QlI5q&X;jKM7>S}a z*~Q~r>S6jWtU_Ch7;j60kIuoVHXKw`&97&$mIFk`N#j^Kw{(xT z0J}ESY)?s=MXvoKyGyR06|`)6Jg?J5TFnz8ddgDsI%GicL+dGf-`1}~bY*HB?Q5IM zltN8i;+9C-jK^F6vyHfM`He{ff;&j}D_qIJeIeTznHoTpm8Q|1ZKVvprkG#LqX`~3 zi=3K^HauBAg{HKuT*}BA*MT4Z^m+EPeX$HuJe|Bv1GOzd23QV|OrUN59eD8STRV2o zIr{^%#b|xjm4vBs9sTBlJyOPWueij%Ro^TMaCjR#t9S)f^Dm$;_f!|Z@?tiy73mSa zlcNrRQSBR4Ff_VS2jvcN^^Dw`VpWc06Gdp;_vM;jIwcJY*ACG;mBqXFIN?i&c61j{ zl!wR-728V9^wd;g{O8Uf7@JM1JR>k{XU^u`Dv=2QX(D}Jzg2s2r$ULi5)Wr2_EULj zKgcL*9g4dk0puc`yV=IUtg3S6=yZoznul`#iXTk(!$p11fo858$56p!E@D7fxm6sa zrE1DJ0gkXpfQV{jv?aAl7H`@pwQ=&}@6Klc6r&jm_gpvrYf)Zd>>X6mf4mXB$lnHQ< zovFjC#?@|9Dt(ofujJa00f|LKMZlD9xDs@bl^iBd*KY%ABwDUOpM2SM^yZNw}oKD#?e*<6r9*fFrkUl6NK_ zVE%H>vC9B(>5g>{&#R!Lt!q?fCos_z6Qk_E0fAb7*EB)(q`{C2EF<56Pa{?V2TYDl z(0Kgy`hyun6i*cT^C&thl+$p|iU6m}z`x!s2%91`S{HwG5 z6PL2g(D{jgMl~vR5VGw`E7bkncVf_a#vm7DeF`XD;pa?@pubhPHZwF(4Ki+_iKeI+ zvp{Zf8M~fh-M`c)@L_bs9)*4n03r6@uTOhl{lDLAe=%ZFh*!})fSfD9S3GaGmYehX z`}0APTEW%5{|o8G#qt^R-v?s)zrOsx`q%&8RdHNiD(qd{_T*tny;D<*3GV*)pT|CK z4m!#OjwQz>pT5f97=J!K^4hUWc2=)MpX#c~Vjl(plSBsY%VFt?$r#QkJev_LeO#{gD<*OZ^TG zJhN{0(q6~E{3Xr!?Y38K>Tzol6IHl~0o|W^bo-nKAesp098o|OCH{Dx038WG1-rDv z!ndz&5DCtIlStvlc`VWJ@P_-$q>_--M!_IvkxxP1>JQHc#Q%BE8x%)$}&QI1R`Ts@~4mM(!5Z62B_iVCF(cV=IwQST>pH> zvESbae&shL?$7wl=!z9y4nF!h`CxB{eFa>4(!*0Fl!3-a zZJ@uEWc>0P`NDl@-=aL}wS%GyXy8^Q#Qo9OH3jXlH*LC8dCd1r;uyFEL{S)-(+*@D@F*mw&Cni|UoV>t2Cx;w=F-U@}!s_#E;-+Wlkav}* z%1LEnW44XaqE+(BLXqbHRc%K;?%BL_-^;+CtDLFo#qU(^h$y`7>&#}OzWT4x(PmDUxLw3Bv_N; zB;F?#zNg1E4OUJdPK@++e(1{4*AX(!oqk-Hrov-W7tgYrd2aR>jy`XL;KplYSIgEd z_ZEAU33?Y7FQWcak3>G?U|C0JHTTSuQ{AiqoBGIbSNja}u^%xY$LtNHe1iI;#jB0l zL6R3O=2rB+M$a+`+~Y6rY;x7R2o4_f6KVD8LRI)VN25P;6aTzes=X&vSrp%`$}Z3s zJGz}rfqUzd=M7u>T~go6Q;54Mn@75~6h`H&-S^8fa9K3Ws?OPWm(IAr@H7 zEYczC^h}V9r3EO_CFfp=kJq&(OfH)F&&wD>$+wSlEsh>!04T4EFnbh&VkHKe-Ws6` zLl9*lMKs%VvKTn$$Zz+<#>#A(0I8)`{i9c2&E0+nlnKr7;}^DX>P};Q2$EkCpu|t` zXigEwDE))SlQ=`Sb~va~(!M#7OJ<`g%2G^0g55hQr%OXx(Qi+j;&f1PtwNUbf{$fWFH>>t&`l3^;;5ip|&x|Dk98HbR zv`rImi?zQN%A*CEQ~c+8YsU&>#B{Ho(oP;F`2*IzMcPqjj^jl@Yb|(&2`$Pq=>&nNZ8yu`(MT-Jsmd$l(WE)o4 zlv@dTo6c_sihuNCEp2#iufPB15GfqQ^W?Eml`W&DvE><;Ymui5zrEtc|FbghFa2^S z$hbK?re@9iA639EJ)J9SW`=W$`*2UuUgdIi;P`?KS!)bi1~HzKI!$a4d!uwkC0_iYw) z^m1mMhukLG1nBm2I9SHD!$DbQo2R2kK4HECLr)dtQuezhX0oS-tq*9{vh^o&=_}9A zn`_hJaTdRyFT_P!O=;V~@sF0|#| zIJwiX*kcy(PEK{|#I%9Tf$V|Yfe>qP`%#;ZW3NdIorLia`+pXK3789k^T!ghU?X-P z1bg^(F71_IXN>vjKu>6mI?d;^nP-%adkmy}2)*#- zY`GpM8AWN-&yB6!<~tRr_U(@Y+Q%vV>-LkYaFJR|YjL@@sTvCXAHG2>41iA}PC42D ziz*2cNZP4~H{9X5T{;Ee3fHdw&`OoxyJ+&W2kgg5a~BN}sR0{($K&K3%pF#2f5mD$%cE#56kJe^0Z>2wCYTpa+D$V4lE@4dQYw%cLN2ZmeE7ZI~uZeAbk_{^(((G8zGnnK+3U}4U1Q+LU-HNMro4C6}@gY4bE zUaGxFr@G@hu&!_%lhaLap{Ewhxos3vn3o*7Ti6ikb4!jsbFGW(w^XFB<^R3^+!KI~ z#6ejnMfxmxu-XTkyz%MJV2IU;V)2AMXZjsC;JzCF_HxW~4^28u9-3?irLOKH4{ZcO z|FnzznANY!PA9(Q`jJ{&RRdp_hFFOR!$tTyhfL^S2Oj$&`G8w+nB%eX`QVt-_mG0W97mm9VP*aID(nN99U6>6GWI>vCW?!L69c0+ z>IKkH-OLbsU8dT&$u5KE=^G5-p1xMYgkPTpa7DGGtpr&8=?PFR22=6*bb$qO9ULF` zLb#QLVJrk$2*L4AF?)}kxm$S&=Y;B}i#4_aC==|feGyELIDeo8MUA9MoMAuKg+Xj# zyDn!xsfEc;nrclVkZSTVQm3j)haI2;!|~OmETa?L5|->Rs+`+3A3p3>=|re!3zFD zG(96pHH2lWYoArLOZ$Ufs6mRYZFQ&5pBu5jg-1JXl|Q)GcXytEp=~rL&uX^Qf$0eh zHjQw|E`}W_c2zGl$JBn?P`S(3G@Y>H?`)sWm&4H(K-XWWYu@>W^}1CmtoHJH6`ryx z78~y9fusE}J+ych6ALTv@A9c0Wl;~y^Jn8%MsL4FETp)M)om!KJ<=3W?uN`{j@23v z6}fiGtNne~LLL>}MoW<*;miUX`=qS3WLqwjTwJRN#HV4GLjgTBF5Bh;44D>d=4s}Q zIVreu)wj_%FWKR;_&}@@?e9y{fOIVWigm9x{IujLon(Fv$@^iI>$7q0_Il`O^6I2| zn{fp{kln1}IMX0)G8B)rRW*9t$$8qYqu^aNvEQB!O^K8D$TqHia8o1ljL^$N0^zWP z#NYLPy64E2hgwa)(X)IrYpBx4s_rJU<{*dYkV^03Fhdwe_7;HGI~0`B!L?g#$T zsxn>+ToryZ;b6Mc(uh6-A-{Su7X0=P&fNM&uRCmtD3vOZR;3O;VPPEFBqkiC5my-F zf$@hFSjqbhcZF`Grh<32cLNiYYgE&eCTdWS3L~O#rk7~%>tEdK(Z_ZAOteHHz%+WI zJ6k^nT2L@leXCV~(ai|4Y9V+5n{89HwOPCwidD{!mQN2za025((O;jl#M$46VZlmw48YPYE2W(~ zzsw<&^lxQc7xh{kidx1{g_|L7K!HXP1pjF`+`$Ms*sXYvvQttO@;Z--r?J!4CfZ@J z-~tmX4}YgAQeDh&Dy#Gpv6>AY*L(B{aofA*81crugtGhV*>_HbL8v#dN-;j!LAV!R z``F>P{T7<4eY*Z4tx!IxxlT1&^zgwvV^T5c{JlpQ$H9VoAGXd~y-qyu^QAJG2h;58 zTrBxnAH2D6=!}4v;*5oGJ$@)a1?f}1>aCSAuia>$a3W9Y<~0!-814tSSo3a3IP{){ z$a2&VG+uS~N1lEDde9?z9*uUT)4TF;A=e(X0LnmbIiOH{1&fZ+9hWv#l-210{wd0{{wSn4P z*z8Pio^i3Lj~9!6e5+E6BTm{Un0$;fKxJf#wFSDP#L!Ja?dTSx=aQ!yG9U6hXLKdJFf^fG!1w?p3$5Zgm&Wb(7Bz$t!#wOPzK#Ds$o!m5wF%3`lx6+)xMO9ZbfI zoAfh}^LozMO=2^g&4i3{V;u&IJ9kt>GQBG)@rB<1#Hx60*q_xQ3VxIKDw}#n?%Z&% zN%Z&;lV8P@E|W@yBU-C>w^}Gq6iiP{p=c1rP!_!~l%87uU1X1~9WU9%lXs8$mS$pH zCxUlB3E^7L>*MjCiCt^V^?x75pExE3!NWjR&w#8!*{(thK`FdgPbqP_uX)ELNLehp zo}%mw&FP&3)Ot#7-o~ZJZJJYAt1QgmH;ixx`yQUqe9tU)4^t%#L!CV4wk7K{XoFOn z#-mf@c;Hu}WmID4_-IUnhI40Bp|go>=&!&?AlL>F#tpN0D(YN9zN z&WA#0DY_K_X3mNy^b#T;v$;^!qZot0IXG85keD+%=Iiu$Fh~I=rL)#6M>Y$u1D>fC=`Bg zLrogBT2H(rkfFHsI}wux_7biEbZmlm9}kzu7=QyVqspfk^RSs(KNO^a%{gQ$-tUGt;g-yI$*BzsFWoSe-z1~Y7zQsqc!jCs7 zb&tbYWMN0^L!BQ@>3sD<3&zw;EnY*DYwKz1)6me7Zx^&A&gT!Anz>E2%1*uPS~Wy) ziW?XA`jt6uvgj73nST$aw(UmYxf1x4&?5Kz}mYm{e22|dndSL0>u zOF^BY-e2l(rk7{RM_$=1t?jWS$irl?$1mV0Sj64uL6J+dh|Y*Q9_f@ar5M%L?l!>H zR@*^Sg2ZS=McmiEIsh=lPt4#&O-hZKn0d~?c2=zWG@l-I5j|_>zm8IxSf2UwQ+K@g z8O(IXtSaOq&jfI*mjh0N5^JR|xRG(6E=#Ba4+HD7rh?xK!#(uc^Y0~dvaimev zYugGK=o3b4ZVdU`pDnpLb}IeY6o{C#q4|8zC~_B9krC{fefF=^xY0PNj`=rO8TY>u zU!f%)9rb5bzK${pvM>7yE5!O-pR%LGNe>t>l=y&H=tF z(%U8zWc?5h_Azyw)##faD)GO5ZZy4BN@z(|LR?Q#b}S{|Jm=7RoVGbHi+zfO5VyH3 z^SU=Zlz3po`348dQ<^54)7NV*g`zxZ^Xdq}`jA5dM);yh#g3+f`uWD^M4MK}+a{cc zJO)=_!Wbt(NQt&xOpA_EbJBo@nl}5)2~^;Rz?{_%pU?i!LXX-a-KPgKLUDeCn`^+q z_27{g|NUqvF2SQA^C?#}wFq+NbarbYvh8xdwk4^A9TL2L4SPx(R8T$XBDOl5{4Bwx zdT)66Dk+Va|A%Vd%FjfnG8wdU5@YKNgN2up?a=lG7t)Uma?PTAwZ&;I@u|mM}0%hYx`RC1w6!my^@O< zDnbO69Q$tz0r{Ek1Wlez@?0KFv(=4L_J6iE2a9HpN3NZYS}2!{$s^ycDKYU08HUGB{QR$k$Z&Pyw2yWw7Lyi>Dt`-%~Y4slJ6K#!$4?@(SPYm z_r5%VfEZz*v|kS4GBo|z(>z7>2S0Z_&I2bAn{sZR)8AnIz9e!;pi$ldGb2e^q|lnO z?7g%_T>NK1zlXO4txMn`&Y|ova)!wVFT(IplXF1KYP+8BFSrG zu+s5*v{TYmcYZg)z27RbZ*yhVux}=WD$iOPNkH~smpyJ;Y;4(A^%^Uq)@qlQO|BGfD0XXdh4 z$BT#=Jdg3GsBD=67|(~w?M6;;+~jxc{}i}+7Wo?FR~EuL4#U-b$(+i!n-4Y@@1T+A zBhzIl_0TaNc4oO&JX{6bMgpidur|=}{&X|@wk`JH76jt8_|O&n5F%ZD0zKa72r>2< zGhXpmq4WLsEyM7s3Qo(oyGu}DSk}Fsp|k2WU?!O6iVE(kydwfpb%k_Ly?VmAyd?Rv z+=NPyP_Hb1dT7OiO}`%1u1vWMx>jLG(<#s;2Okp5FLuOUh2D%~7aZFz%X`e--Cn_r zUmm{V4ZThQ>$XJ5yg4-kn{OQLmswyGY1sbM+mmXgx=N|5nMSDWL`9!3XFj;kNP^m7 zBzkh2?W+Y)>c>sIKBk}-u(hm)-J_Iib0hC+Yy8TP7hdDlR)%??~CkRPQS={Eugk8gqlSA**=~#kaQbX zJk!+(C9?q3Dz9)ojmgplx!dO86cp>TkL&!W9Ybobxi~T>JVAV!h9L2rip{naq%1$D zPhYNva;$b7_giHXO#?JAz^Ei=Kot-DVwyT&Skj<4f%837y?l^OC6zZ&g7SP|GeV+x z&hx|4Dv4YpNp5T|^5j^0J(!6l)FA!&LB0`9Z^)($*P!&^StREkQgbsSATB zbBeoL##078e|kf*wRX+VaiFq0Ess2#BS{Ah?|cGDh_Q>ObmIB%Wa~v0js^HlD+eB> zD9q2Ah9;GE;mE-9(+63wg?7#y8m034!Z476M-D~b#68eJ9F}$L>fPZ0gcExmW(A13 zie%yLPav5EQnbsD1^&x(G&oXm^zoKYnMX4lHn>t_LU>30@7@o?2*(Lkp1R_P)IlFN z?XuBrRo=g!eFg?ar5z1l8^8*4AC%53ooY4rp`+WC>2gRt{!AQ2^q)^PV#}w>bCn*K zG#0=mNLL9Fx#c0<731_zubhFwo9*N;8{UzB-o{WpV)H*ZaPfbe8S0-a_J3L=_PM>5u{$@{)+0ICoBbURX^>%z? zTD2}CrI1KgAvHBMRZ1*N<^D=ObB}BK`ugJflG^lfv%H_7g-YFYX5SS^o?s8$&G7A1 z*E5Fw;!@wf9vW4ox-q=4g&zLL`GK;5KI;@m@BtLTsA?0{U(o0YMFzQ2!t5)zG7!NbhrP*tAxF@>?$Qd{~ATzk`4X}&4Q?v(^)GJU8 z5V=_$D{5T+DNvvg7CfV;D-(m4+P58lP|xjEPTPA#_&%fp$~hragldJ@($|hNZNH{& z_44_#v56Rc zgSufBbFi;hjYmD)X~+HnNzMMVk(}nNywsrX{5#k^?3H!jt0hsIhRtkcy^!j#Rl;z* zu;n1D)X;ut6;i9TlcoDucoe6_w*^HCrHTZ#r>Njdyum~h*^M?+(dBpFc3jk4f@iXF z`egH4sSFd3?rzWZZv9P7tTUVnJlmC&97ZUlP0d@x<$B&KkHy*?#QW{Nd)>whUTygU z`1c7$dhDi--<`W9c70#gB^g7!(pa&A6|vEY80to|ReQ2yt8;B%^cmAR@i!U0xt&U& z(YKwlYF`j<_3q*%Jsf)|To318YaHLTntBlKx+*MIgJVN6`8k3H8I+DcA3YT#UVdM9 zUPSMH^|J^DszRKoW9HkY$iOOUW!*XG>Tb>zwGT?(9Mn&Cf`RbD;%ojqTP+4PQ>)B*?pL9?_b7PSq$U9Dy=he$W=aOCS-ZQyZG2CVtD`i7O)LO8NzhgbN0oW9rniY&`Vr zzf(5Rn8W9lEhoLbbNSh^;UAtYpj(s1_L$R{U!8#5!va#NL&>|Z&n(Mr&t62yEHHAI zcu#nbWas1uXNN0(sQVIeUB2GLjX*SBGxDei$PFEru6P6qnrl8*o- ze!m5jz+HEn4uR$JP^sq-a-h&HMifDPw!VPHwaKrZp>cDl8DV1?LULQ!SfxyMR!s8i z-kSpa{+xg(Zc}sHaiN{=J6D&2cwU?;paEl3h{>PfJkS2W9{f>}dJKg)z#ldC&_=jX z%I-`HB#YAq!vouIwfS+9`X} z{0X=+^qst0eXT|B$mg6YmzfaI1Eq2-JCo8oB5yeu!q&Pq7KeVoCjS0n@*r3`!8 z+m{)yz9UU{4zY0k>cU@CEcxU=x?G=kb=}U%_cJmjVC5x-Dahg-v_Be|)`GTIJ)#N3 z7>|m}QEN7uM8vLk=iVG5&JPj9-;f|G-1p@e;n3uLtnoyAk#T6rVlBbkWZiDLP_uAR zXmQKNVCcrT^CQ0w>f&92XB1(Nq+J8PD=!5HODAinl?Xxi&3BL5y9%lSOlKs5NH6vcMV@@N@QTX9)$E>yJZeL& z0FPh=uEg~Fo(abv4R7=J8*ZkO?8_BUHHZ?sxB}<*t1|b#c#B8;_%#2@6uS{|>bm=- zL?&t3kEU3~6nXv6we~F4ovcdJ3$p!z^C`qjXxpTYVYAO<9AEz?+kWBbv3L1zVod!y z0elrdZNy9cbe3IYyU_P10FTNziaps`g7zrRpRT!ZrlTY7UEztN8d7UU`ulz;3+tU0 zgMFe-d1IQ7-R!Wn`#gaXkI?;E{ybC~a%-6E-3Ib@*S}x?F`|6b>UP&5(z*|fK#Rn@ z+&!n%(KAJBaqpHzwuTSQ`7RkAJD2M<&?RBRTas+b8j5;H+T}>^oI4%6&;kdp49ux8 z#qXcSh3gr!`Sk^YCk0fJGfCbQCg#BxhnrTP#T+$AT#r$;9;bTYmj)WeD55K*i2y=L2vh{wx zwLVTGWyR~;3(pjxm_7VOlHN(*0oTS{epMBunEy@UngHFJ|ZdJIebH$7wC?K_BiR|-OBILmmwv>8(U zF}wCwt*-aU@>rf1I$2C2368h=cQe0DPCvgY*kYeX8uZ7RMorp*{sx3+Yvti!}TieI@RIoz$jwc_T`zt$F7Mrk-(#8Bcdq z+}yqqXPr`5&*S^!y8O=66K$(--ja=pX&ivw`mpJ&fmKFbL|)BS6^kO>JId*$0( zeUWPg87av>yWR%7$$M>*0`Eg>EK00Fh+?&9|Osa?F)i^CcC%V0$t3PT~s zTjHAM1D6n>FGv@;Or5Fc%`+$*UEulPwm$vAVyN2dr!>uEakyr1O2j1p;xwpk2Bte% z`+}&9b4hn{U_%&fM_+x-3C=l%=o_8GWkC-LxmfjK(`V*UY>>HJF*}=Ml5F%!rp`t4?;{r;8_(&Vx#_2_GpGW< zUuI5kObuaPpEx&FF(Y|lx0gBsgR;_Z27{;+lWHD`t!;zb@ddkp^5el9or|I-AHSI(z=Gp3@#N=wZIzw40febTcd@m{Y>x+_24f$i8G~X& z@b~|EXMl?Jp!qWzF9xDg+(VH+pRyaj-ls#dp=2b-->umyHlOLToQt>L;aAgZtHS+FzjT!`~s-Jw?soOk$Sg7r-ntFb%*-o^eKGZ|ue8Hy?9QRcneNeTjX zL2l;{XYe4GF0eO8I$B9{+pGBcN*~KD%+?YhD>~F;` z_XJ0oekspEm>s!pcO`pArcqRm%xw^iIeh+d<($)?cY-=pWvkxpaci$SPa0em z?;Wf_8&bFL%ngfS^PA|_&jUEz0tKg+V+FDmm*zF2^C(1$57DrSG)!G^MqQAZDj(Ku z^>wxj@vOY9w3F?O!N?w0*dQF;s>gn8xobv?xz#X74)dHHQC>W1RY~rWIfDnD_8ify z`O4F|L&?ad`T8O$>wZ7+p`mnb1gT%cxz7vlKb5@8T}yV*`vbyk6QAi~QMUDTD#dFv zZ|ui13pX(+N3p-g*DIXoZRcPa1Alr`!97;Rk^C5TGrvaDB&7i+7S8efW9wZv=Wd+2 zCUh#ZP|L`oKd)?fvZu51J;{!u#>0_dw{r+;s!`!LYvg9U_t)?C-=D$?*jw#`2Fpo= zF_+Iocb_MDBBn|sGs+q5zIf+*FP{ak%g)?TC1QEa(&(#mjvMa2O}?S#eXH$CQ$06* zE+R*%F9j3n=a`SOc%ysh_Jpa?)M2z+iPs_zqHN*DQ~!}Nvp|o{T>lhlpN~1lx)0Y5 zFZu+Em(Ch^w4gNW>;2Y$?L#vR0Oe7pc0r!xFU%s$V+wZH{JVY&gK}w&2e3a*ZXufzQA)pHh*}D&Lh;>exL4rj+6lkif%D=+wN5YL9 z-r9^khnqe6bj=}Sk}%=6WrewAW?8lSk8$+~(FXYqlw5-^IDyKOtZ zN`^kyysruk<$l5L;#hLmt#+Sf4Ic@mHRI-C-$kVueNEQyS#IsEPR-T5DCxFW;*^wu z($UPTo7bFcIT%hhMjjb|uQ#W0S@^~EI7OkpcZZ{v=es7Zm{#TMq zxQ*S5B(Iv3vp)_pa4`q#Kmp{otiv&L_h>nqg{PQQtyO7mnAcx2^f74k_9n}`$wXyl z>RL4HMIvtB`&tvu9T;P{uOW*c90Zf{ts$8b!yo(mD4fyplkO(rg@`-Ij z2>0QVWFjWttGz2=rt`h!UN5d&@BDo93v#|h@?Ltj9$~Y9U^tj#j0%>q_q=qmIwD*^ zqjG!WanI?JwYn#K>Mm&}n?$i_A*;;#Da#nM1yfzr?YNJYLvG(6rEXVl7|S`Rbwm{z zigaSy18jZr%7k0tMWr(AF;e&RT3f!!q4oC-;HNuQYxpSn{X3_c`O+tj?Bb?h21w=$ zK3QF;npguIcTPx!IjYI2!n}l2^hsBxXw5GkzZBseIL|B0f4KXpp3zO#pFx2ju)>yO zJjrXg5aw!??iyjw{)mcJM0cJ2h#x3T_dIM;1-b4nKFc=dn#IePR(BKP#YP=~<*q9|$?wRci`1W~hQ>>xx@Ga`0MMD8=6@ArHCe%HMokL$1dzWn1KJR*6&&-ZyA z$MZN|zO74@S}8D4;&9ea_WAs!bng>yxCMs|z6iwl`6IlAKvl|uDjF&y$yTi`SU^A$ zb-HVq`@V)oOvpCP%F>uWAa-tu+bPS{N|dneK?~+Yg!4yWX((v4(|4v0}uAqmkJf0 z(pIwZR|2TVTWvelyj@4@ODbDw{yWP)%@V&Ur_mCtG%4?AL#cPZh&j#KNRdh^rY`35 zw>2G>{|y)J@;+EO+sQ7JLb~#%P0t}~keQS9L5HZiYuaSh+9~1Sk{#VUv&{EUGqXUMMt=ExzlV*s#7jHjYy(-03&z}+XWC~r+R%9_; z>k#zYso0tJHE4>wSq0xp`ZdxmRiGRB0<<*Lw&E52k2i@HbcVIhtP-oAx%gT7rf9SbJA+Trc9PCrdl8Puu;@;=wjoFJZ~3d&|U|7k9o0b)i(wRJ#*UD+m8tDOy_ zvTw%cp?^jTadY!2qfTagf$gROQ%)wF7D;(^LGKKfkL~gttRr$7e}=iyh&;$;4n5D| z2y9><2PI|^M{E@z+H#3MLL{6!S!gsM5rpoloPDMj76Wxrt@N-G1lKX4K4ii>*tTa7?u+4)>E+K>f71i=AwmlLUXW% zh1$JQV_~;=1=qFDj~t!&q-i)(%q6ed2X=$6d;AF#Q5+caXvfG;F|qbTn*4F!cBeeV zeK#&54#Ne^%sB3SM@A$Ty$``;n9BO8yX8iop8w?!Jch~2`-gVsTVtB@wc%} zfvN1V&lP(LmwZ8u23hQa_NgNv?`%`TeLy1)kZ?53&Gct)+`sUN11K(e@zBfhcXT`Y zAYjI@s>D)qNYyuSFUQy$&JT(}p)YgJl$$b(1OeY_(@{(8_a}QvTy{_e=JW5xx{*V- z6ivfzJGq?!dnd4p>oNZg6##diE6>XW-vVrCim)NNn&0V)kjdI&&!`tyTewyzJCjJP z+E$xpMP6ONX?nJ6_b-g?<#R|))xyyhN618T^`VAl7e7K8AWKON_KRfo=;%GXNA~d# zlVyPj+zMPc}0ZSx;T9HO4k0Jz2%+|(NcdBB*Yc*;eRX=s*IOnP(5k+q`?4y~8+sRsms9rwzk05Il;v7?>kQbNSgI}LR`>{q zYlmGPrfCbAzY&7r@I}blYCGw9QHDS^mk~5JRaU(GeSve4f^N z%9N4vzwG5UVG|&ZX$tzc4tZ7Xe3y7VK7b7(L4s8}at)SJ zOrM|C6T3b{;Z;rWRD2aOOb-Fp_j<5)p8x9CF6W0*`bB`P{BZSj+ZP}#4O^pOX|Ri8 z-zA6WE`Q26ts{G@HT0^%UG<)O4H+OwQ2a}FGAnYTXlju1*s7S$J>v46Rl2CEbZAl4q1reT%LTk)x{Tk{ zZHX=wuy#f+^e_$Gh?Nfx>WLReA z5vJVMaF7Ous%yMWQGucG?m!X(f-~?3S`-;clQX(`kzrK(hkA0kkoadViT--*L^}wB z%~?m!y&Vc-;`>~ajFQ96rAslcR&{du_ktkqybG_KMen!$5`T+aM`jk?(KENe1ae`0PYp$jag`zpMZ zmo&V)csEPCqIvY2o#gfIttgB`E+*JZYM&KCpjxazfA zM5>}$Cp>)dIPJN5$;qd*HzXVV-_jX}TwtB67TY)?F-55jvpHbZA;<*KvGh!=ZU+6& z_4UaBh|06ueXH7VXAa%bUtkVBflk<~6jxtpfj7Z41tNSPTx_o-CX>F5C0#K|DoR)H zP8H|~*@Maqb$=CfqV8Qe;zERBI(4zZQ=?|;Q`L}SQ(;**3Q(RjuXcF;-8envH=x)$ z;Y7|Zr8JVK>PGCUU1s`sk969N;_{x8#ojEh)WB|db4#WVhg3PDHI}tYyIu5SZ`~5~ z!#<5*F|KkdHhDmR;@p+(B=qX}YnYk%{Wtll#BPiX7FAi`g2cMUcvQlOI$Qwk^` zAw^gV4SjIV{#!afOYGnmVM{sx)xt0##iAR1mwS;LoGg~#Is=_m1@(_z3uN0<{3$Kj zMe9xLS>?^IS1{nF&#ISWuPw03kd{Z;_2DU!;SygvCLCjmZaP{OAOSPO#FoVoZ2H2T@_m!L5-bI2eW{|6rXPy{Atf$g<~LWmItJBh*0D{ zRV}2u+CKEh-eO%NO&W3BM4uDqR!_uc-$_X-eMe6(U!?E};3V}{kE_z6;Iq1j9r61+ND7>qJTM@hfhus&Q`IK>HU$|y-rfPL zRx{cfXehYQ^oy%^*QYx*r15&ef)P@DKxw+e>4_if>rN0@IywTA67Tjn7@K9T4Q8Pl z5dJ>wd(EyaT$gW+uoSrJT(f@XOsY zpp4R=t=QNW3K**i4bQ<`yO&dUnT>V_JFKvLU&peiB=D3Q*p;>Z^UMj9R|(`8oR(M~LtErp)v))*PtZLddpv3!vvXM%dIl&W^5#auf{T&C5f^CBDr{1@uD@ST= ziZ4$F9_)B;|17>gpvVxpmw3GMLfJhVQ27(K+mIhxT#zCj7_!jqWv_RUMwtaTrgOF< zzE>Z}{yO&i8J&rIAka;Pnw_pz&)Ck+#0KOy57mGGUn(J3y z@vJg|>0i>$XBHxay7AD46A!&Vg#xcNyF(GU&%f`{zHJ29W2fzL!`6#^-^7OLR}2u| zX*MDZH{bNG_(q3fw7C!tybylUc1TF zJos4V{5q1Q}e2C z^#f`o8(3H>at|gUj-bcoThfp8{>OL|G05ad;d)gobDvzuxqdZA`fr~7KwGqRn#@sY zkuxkb>*56S$$^4(I=J+g_-i8<2~j6D{S!r%0m4*Z0+av3d_kJp=z97>j>W}Ne|L;{ z4etTRshL(?Ccbf$JY@~;w_IZi9^_yMYavq956sE)S>j7kvbkf-Mtbv$@73#^oY0F54{n(YM}KCGTRuQ5qQ`!| zKTWRs5<>k~tN!fQ(V~wF&0Pj!JS5lp8$FZUXUguO3ScLn; z%7jKugm6EESM{qWj^F0N!R(;LVrgZXTL-K2M9daAxl9CFgxn+KCYtnrlO*RVhlsoa z38No3pGKGfI{|#QUq(Qp0z81G_u5%3jrO+7O+jSu(C~tG<}k1a??C?Iboyq2zOHudph(Q`Lipt?BEnvmTc%G_D7~7WGhF-zygPbrkckR8B^t5(i_3iQ@ZBPg7D7K$8#*8 zBw}K1eSNwVK#ATfxrue#aL=RaQcOt^u@NlMyf^Uh#AnLr{ zSjge=0}p(BBg7t_$()+saqBE5C=tg&#Uln%Q&nbaGBp?U;2%56wdHKJ6&XrZT_D8M zh*CfhB#cVuRiNZLr9&4Ot8-O9f&Wo<)~KpPVV}->#Wpc_zb0gdo0E|tEL7zZgG~=e zP?g$*?!jU-XInnvL)cv^0p3wh*aA&gm26^8lgW1J4&ZUrNF;GugAThgW?}7?U}DTB ziGaiaYQoW_scg#pmU2q>@g^zX0T|*4>T{P>AKLxOtIy0IA_kbGRBnqsy0(;76#<$@ zd2_bcqx`{z3UiF_b_0HFG>Mv0&W(v=C%!ZT6`}J@f9K8xcg0k={(M&p4pAK-p7hhw z{f~X>Wc3~wjm{82H)=u7qC*Ta!~+AJq;6b6e={lFH^SeBe>5TbdW+5ry_uhxZTkeC zj}p!U-`~0kIy-Pu?dwkR-}z`ah%-VA2CkU)!0kSXBNI0_Of|%#tlA|*Ze4b^rG{HA z;cghX+cW$@VchRWW^p*UPevw+&U~y+H~)hz6)^CTnRMPr9&~=dn41dbMZ#*?MvL3= z(-obTY-yEiHn$t$pnBL15EW7-e@h{9GEh&m!dTupDtHp?U^eA~Bwz8N1QOes>+@a! z#hiK0q`H=O6|d}nVaBLwDscVp<~$<@2JlLAVD*i6lrqN*?zJFUAZnPqI<;C;fC5`f zpmm^3Ryo$sBnP>4O@Oz=RC7rz#pXhF+T_vd!JRMi86^2B(9!d!>2#V4IppTT&#xWN z@DiVFLVcgfe11i0YyI^pG`STt6HU9=PuF`L#r}HNur+u)_*@W4S%3?M=PVULajPut z`HpK|uTa%AIYuKAr+&ZfppztD4R1Q=2F2Yk^V6Y4$jda=iO}1iD}C_j?>vM5R@W^v zH7%M?Vr=j3mr|hyQ*cj=mKgW!{vH0r4l0L#$RwIsFQxgUBNL3l@K$`d0PF_{_t$#0 zd~{KE94!Lgpm(xA=fE?d0ea<6n(7Hlhk2*Q z+@1~qcPt`3j6#~B9Oe$H^vIoRXb8nkp zGhm;!B^8m_mXkJG5mec?5^-YZnh3|5^BDPkD` zU7X}x;214|dGaMNyW)OJ9sw*A+(AT3#8!9lA+K@<)PH)oB7Zu-!vn484NAt31b!8K z3Tqq<^2>0#Ef16|+V+Xh+IY-sB^AYb z2j{|D8NMy_aeCQMF$t8`Jqm0Ql>#j3mTwl&<^7_X8E^RMj%co>#jHudKX?&>YE0p# zH8AJo#dMul_4>sLDvMu-f*i)HaBLFp1Qlmk^$U3gG=kDZ8v3Sk`i%nU!4MQQsh#Cm zLS+zypC>Oq9yyH2+`h27zXOnY{c?foI~{jI_%$qo&23nSqIxMI{Ceto4I@sE%|@>U zLd`etdHR9MifNfInHV2jiHU8gX_dR17G~_*2cZ6Fi1(j(RI4dRZtIsLt%=ez<+peh zLh)7W!OQ{0-z^;OxBqH}1IsexH(;Uc+A?pn*2J;Vv-o9Mc75O1)!%g8w@pMKPp~bD zSsopFZ!{kx?Zjyw=60Q%e#H}>@AxvMRa#EpH@AIuEj#3u#ZiYlqQXf+dcHSjNxc>C zcmZ=qmye`&b2w0`HFL316pm~&vv@J}_v{!b*fLSybIv% zf7PPt^E@{%-smIXWE6}7e-m99zG88ovOWMex$$u0y2L@I%PB=k~@8wCj1yQ z_)F*o`wPJkOAP&1^Q@oS**$I}IG8m6hMY0dJ_wE+dD=}XzAN(3V9@LEcY*d<+X55i zecyPOki{Oa^HLo^Yr;@zwLMcDb$5hEc1tZhOYB=UQ?uXy(EmJ|bJ|?;9d-uPo`1S; z)0Z+jR%9FT0X66$crHh8@z^y&)^o6Uze>Er|4Zza7Vsex>2rmyz6M4^D=o0Kn_Tn=n3PRzpA^SJ% z%9Gc0aiIUTc$}qF!eQtMyXZzxVi$*~?~h%sd(FIGfKI(^QgPx@rQQ$E9zlx`xT{sF zl&yQ4y47uF@1j}Mcv-X&kaW#Tbgp%$N!Q43{klpZ+)xo&M1Wn+?wl`RY9LE6VySZ@ z^hn?pm>5}cmZ`%O%qcKe@AHO=*F=J@r*TjKId$lN@EIH=5lIIv=TIbqCoWzvuMim$9F$OpZ_k zMMgd!!%~Xzv!TiuDl@S7PXDKG!843X6x|N9+V(<^%LJJ-8AJf85-l2=`z48HM4#LG z%>~Wt>@HlfOb)5DmHjr+QB?~)3C7aGebAq@EPvroZk3V>{NzDbowdZYXB+_FVR|3Q?;*gz*0=7>cIM0&%qvAsSHD;7 z&;smfl)y6Fu*M>GX146&&NTzL44zv=eD22PhU-O!Y#^16kN9Tq3)a+L8k6$0C-4`% zSH)=YbL;tKcGK$z6_m@y^A@RV&)}Nh5)rCc45rEhK3bqX+|$|gg24~f%ANw6VLQf3 z&7CTiddo(gu;3M%PJYQ$#Dh(xJGu!ASDwB3bn0N!Bgf|lzzChvqeB8xW+ zPTUIAK>Cv~z~}kXt*YP8YN7&L;!gy)m0^iZzJ?G3TuFbDQiqlN!fhS#wjkPK1Gm z#xp{3(v#&dBuT!{gQqaUGek%DZZlHhDxv?@+t2LDxtBq3buap9q76n&3{TN zP}QA{ZT*VbT-AKfQ|q5BzBzWnERT}*<78flaymMZ_IIC74rZ-6SSJ>qOKCmlDn7L!l=2uPwbbQvjkPZ^>tT&58TLv!V3Rl!3 zxwVgBk(cPac!$JKsInK=MDlkQ=_AINvoumpO)}n&d=B=fF`c;74 z4VgZmr$(}ayE3uTlXklgb!-Pf1aL~0C)XqOTA-zXK@)!3KZFNC=t@(}-4tuvz`<{= zi|rnf5Nr5&0Wxw(i731Kl}#?7);wsR*#M!zL5Ww?bF}~jzA5O&F8+LedCK0Bs!6h) z&(|M#AheUoY3z`RZQ=i|)S)cH!x_TO$*CaonLgY<`ZEWv`{bxVE!a{5JS)H_@|2!Z z!Ina4_LgEizVPmS`)gU@a}@u5W)OC7^ncEbHL3Q-BUGSylr^#t!iSJPAYJk3?K=Z> z#78zag>3z0GPK}v{niR-Kk(E&sh%z(W<_F!~z>N&=rquCDTlXP|$9x>u;iHj--bds{~?6Xo$3)c1E} zCPKO>81!Cjj);;KbF*$~((rZ6!kKLhsR{FbRr@q&>2AwOL-YG@0(cBPjUORmF*9mY zLY`sYfL+{9Prox1A*`eyqm!vXD{N!dM-fO5Ii-6_xpnZP&Rn%?Ov{mF;qZV1XvEqU zsS7(tJK|pc=GYxPnA)~%Dxvs#beh%C!>Wv!gW00>J{!}w*eEf9c zV8#iw(N=>}gnFYii$aKQWS;114F4~x`<$z(S!0?aQ3J?>Uj291=qF*snAy9qa zp510pR?EKcpvQ;benVQXIga(iPwr~qmhhCpT9zEo3;LgmRXaB4JLLc+SnT=k5RP)%DzFj#a6?J+bHDU;2Yf3v*>U*IG6N(-a({E6U7YOiU}nkcLzgP zD>_N(SN&>i40c-NjUWy?N$#^8W-yR(Y*lVwunkacu3wtCuhS&f$ z_fH=ES?V5%h9=4-Iq#j!_bY+jy}f~WFX3#9wh(%DN0c1tGsSW1>x3a6F6O=sxF)2$ z91(Qh^olGR+p3_^tcN1t#peF}tXALI%ab?vQ{K@|H8eZ=m7XtU^k*^uilL{yyxzv7 zp{}QWl4ek6O)EM&V1H`@fNtFVb$REBAZ>)Qog4jq``cVPT_Lz1mqlvcUXv8^q@|51 z(D${U(s`QzMSmdv7?is8%{PmDgmDpy<8T#3+|uye4i$T?HM0tJGfwuTdB#8=0S-O3 z7|7A1wLw=X!__X6?HxW?IM;ypv8##M90MjOCJuZKiVful0gdkb?m zmopw9hpyZZ^)x9#?b#guN0&V)`%5!Vm<=-Zl31{cw{sz<-f2hcJc*D%lRn6{CmZG^0R;9woC~i5!cG znUvJ~xndJ7?_6p+<7nDAgK8!bYCs)@u_2*GyHUx@@I^X#YVByUYq-%sw*Q@K(uBt% zbU!}%&INh%>erGICZk#H5oW?g-{-V3I#!g~GtiEYaw7;qK~dVTbTPaB1BBz9EMQl2 zPqIyM&gxa3#%-WrHVR1S*~EcFmr0^@{gd8Xp}G@ki}grwnp*2%PpR8)7h8D3U^c_$}4B!2wo5l@W< zEJDaV%~uW^Y|kdq{&8bV-Ta(gx>ugl)ypPPU%pj-?Nf?i)W+B$=|UwNe(&EC6yor2+oA0`|rF2=6T4e9_d9Pa|ipNh^jVsyj<({moO*@7pin zlw->hN%9f-PS$O20Xpd#Sh02zIk&po8PLn%jO| zl-DP~rMz%_f4Gm%ajjz^T!ED+@UN{0u{>qELmCMv3pReQPn?W&L zs^k1svA+%@1)220zmG|vn?gtgY&L@3StgcAQ`JAl3AlKS@hl;73jPLml7i&Odr@uT zQ8|?feR-kX$_LZ_E^XV_dL_9YvQeLW*KK}P0vMq;W^t4bwGoPGf~2y08+m*{C6iL< zw;2(tJcb)0Tiw6%5=EjWPut#m|Jia`Q4l@)&KwuG*}k;*{6qI4m~`D*_4(AB*4)`{ zy`-G|{V||mAw{tc`Dw4fIW-E$o0WcbR_}NIm0jTV;uh(oQ$*)FKu3A$v??8m)f)aG#D)2t3| z3UP=61orZY2rOm3BeKRHy60&NmGt0=baTkPbJmjscgf<_RT*KA3p;b_mC6r~eWo(c#;iW{+bebN?R9l2T&R5Jtd(!e74j~roQ{~7iW3$VFkO+t&P5#nfe>yTL2a*(En}{ zRh-2K`aL1SUqwRM%AJ8wdx!6UBSk#-o?$ib11HuE3-g~n==K87(t))2na~o zSeW%LA{l4=vwSys_;{1{AkG>KI|j`;#A}WP`t+TCi^+Dzcq!!? zccu8xXmg)NL8E&!pi%bg>-PDw?{z9-5}V-7D#=c)e&O6d&$PL5@tM^oU6A|Y+N>Fibxl&1 zaz4+4cLp=9dRol`+&Cp@ALs0f#07_d59FTR+?^l__^5Az(Dw7()lr@L` zZLM$*cz@8S7@tnVLo?-y*W$d6BRLO?Ne1@4r)X%(mj31SIHCK~#y}ygKe-D1n(E3_ zB{mQJcws}991vAbSu9}Wg)V_?TcR-q8$`kTP<2$bfl{-w7T)@!1ClTm3&aC$-i?`1 z#*Ip&rGljsd0V+6s$$=&LM_SMc*B$ z40*d5>BLI;o&=%o zpwq2u^JEeviRgcZ|5RKYm`C|7#K-{t>!y`Ma38U-WtFLs@U#=o>GJkZl%&}YNbaSb zz)&s%tKGMikijuo?=m8Xy^*fDq7((-uI10K%KzjH^en+iiog7&RXp?kaa*|PG$uYn z1#jfGbBTe;CC>M1G}U3?J?I1B>cNiBe&b^>b0^Dy{f|AkRVgU6<2=hb=@~cW7O$L! zWq<7MT41Kd+SDItlt4!D4BjpyXt4#jc0T_mCYS{ojnJ6IkHd6i`=>sg z3vW!}(?JTiXHLMIR;x2>^L)u$6mkZ;)pPD!%QZza15=V7X0$$9A^TY@i9p$QVe$2I zfC%dtKYCQAUbX_9Lf1{Rh4=${oR6&E)=RXhX=8B}WfphaBI?@xskBxQJgZTSpJyM) z|0*12E>9<9B98_opt}fn#W^7jNR3bMX%hh0t539;J7-J^KN_dSzR+!O{7q zzWSX@CE>aU3qymvt+}IdwK! zf#yu24sD&iTl>OcBz)8<(ME~p&Ql}LbFp-rm)ZTNJff>0m@y5|UZ7V~ zvDC_7KAT6!1;o)So0%=->(2a<1(mrWDS9#n43D47-gh1N{$bW=XeZ%Wp`LnvzU!=P!c>hG&z{AsDJg2Af>xU7(u2M z?+IMxl(f!azHKx>`S2&#lk0q<*~c&aI6&S`Hy$b>2TiU|zAJr!>EiI%v~I_%5+tta zoq&Q^lMVNwp`W(tMft_S-fgj%%CBDE-R$dY%(Zs0^(2 zuZd)rzcH%%`OmdN{L7PIOmelAVkk(lb=KDj9cw!^XQcz!FY2!}h_qj$vPq9j9M+X~ zgU&DhkTp|wlxF>jmGz&hluwywe6)6*lkX`Yu)w&4-Uv?W57U^TP;!m_6Cj-AY+gUL zB24>cT=CyO5&1t?l)U)lMg4_;ef{sySTg(JVKn7XzRGQ0iSj?n^1;hjiN9++6zuIQ zqW<6EEgEGe#ghNukzW6c9Mpe49`FJGU(vMmcNswkU6a*yebf#F;rk@u43}C=OHnyL zKpte`^>17Di$kVBF9=P}tHG9!Z5sdly`kUl8RUK#2$~wrDxi%J7?&ErQMCv2dc|}r zMJG1+<&a0*mVG_Vlw-T&bTRAT1dGp0b*}7Bld5yKe<_6U##aK*e)9Lv_iF&I09Xx; zNVvN0W7rerpU3x^WQ+7*FIz+9Ur;R`^VoJ_JEkeT5s=VRP+kQT=J=Kdn_;YPLaoeexVi z-engz>V+Ac&trG_!7PAv&$#3aT)wjzh06IF9B~1!DlsEX>M0NJTgj%KU>;LXl^SjI zuFab0bp7cUmUmHq#h3ZEeu)+q?~y!|JGFmE^?>;w6K?X6WSCcXfj99%jzxZxE3&LqrXrlk?rm zB~#_YXytlwkR9V2+=VNH21B!_wj~2)SPVQPklZIRR^uWMo{RMqx+t+}Cd%%d!(FYr z^wv%ngLPHkzdQxDnu%nxPX{GP;$NIt%4#4JjYz8c==;ONZ4^=DC2^wQG*=~vJ=q$X zxqa-pUV~^X#m^vTEYHzcw}MTlQ-vLJ6`YyMmO{CLE2-$_BsK`4#uXw*$8u*59zOye zjsPi2GXRrQr5C>HzQ%%zbo1%@`tCQ6-=D^$nIk4cxz@euW5ivsYe<2@4LsrRR|9J($MKFemLSW2Xa^3P7Po-}>56yN2wpC^323f9FS||DF-SLY67lDSLX6 zI&FbkcOqs#FaW9`!6Hdt0frJx0@HK+8Nr3QKUcq!bk%vk+_u^oZ$g3pDZHf%CRRfh z!sER?winm^od(Nui$BzF_X~x|DWWjd4mKbx?T)*^CD#Jx+*n7;NsTE*2i>;*XzCt| zk=MUVzZvB*K9Feu<`?)hRmr(7?UNG=Y{w}}co7`L{W_#_{M$--b~WvLD@Ub6t>>@;sN?6TOA>RjFX&|*5)P%^DlW+S+-*Cm1_4xGJgrW^l`7kN23fms&+B>amXCI~hC zwf5hSH^di)F*VN2CLig%yaKixRn!nXXkwlll4tF!!3H}0`tnm~dIKPJe?bdOh%f6W z^-M5`)y)ex61DxV4#|Uc@>uF%7B&!F2jcG`?;sVepKtgah4FrbK`;3xi~qCa#0wjW zJI{yE17`D~Ot^8pfc|GH%V^feHabtOKmrERJEJRXGf~RtSngi;KK^X%|Bi6Fm2*0E zCO~&eVkTf7&dfqhnz1+m-)$btBorVGnyO=KL2j{b2@F=e&?Z)Q1SPT_lnmIWfozKr zA25)-Iid$em;Nzx= zWzN%5HR_dzvxC{gJM3U-*r@}9Q9rTE2bpErP**E6u$t)fah*iwZV;YghQuQ-3tc8s zH(Ry`W`RKf^PF~DAtrpICUti!X9ll1{lJgx8KO1c9_~+3W-9In>Bz)pkc-M-Vc zEI-YxeCAlRW>6!m@4@_ZUX8`ZjWSMS*S#lGP~D4W5?0gerkl=qO0&2Bek(c|3W z@-U8nfX>{a$;?=S;pOt)v{bQyG0vcLYARu}dXeWFXp$+XwWhha9;Yc^1~5#FySZl! zlE;hRj76;c@;~eoGhe31Fem^M-UCpgDd;zymIB~mTnZKW)z}eW6%8)p=M+M&xf6XJ zwSow2#taxN* zlSg;VgJX!MLoWPZqxJ!E;oZu}UmE;y%Et>ZP|8N{Ednj}>6pzHviMnBS7cCN>?|0T z{wFZh?=ZJBqD$=FN0i8-)wVB()r#&N` zE*!nU1}|74e2|#-jz^+6`^gVrd&Tpoeb=l}$8= z_KVruG)gSwF*J}}@4CgE5U1>K(K1?Uhyoee*MJW!2dwNQXi2NLWrT9>upe6}-h zrlNaCF%g%d9Sl)&mMc_>WJe_Q1vaMIYx#cPU0)e&rNZvTU_Q4g zJU8)b8tCrdgHcU`4X>!i{-lXqOnd5y;V) zbHXwNB1Mi^$bcv!9`KDtbnY z7TTAzuIW8a1Kg9vr~l49tw{Ba?rpSYQx!aqZA6Hn!jnl2cfId$qZDDwpq_Q&FTKZe z`%9KDmcIGJNYY>VU+5WaN6Modcw(wqHE=R}%SIB&*9Z(|0yH80Mlz;Vu4h9fG}5Hn zo$FWl(AgrgRGx{hMlC^RL|W&aYK9h@%G1W2kzx^@W8lP2R)Y;KAqYs1&O`mL+v_32 z_X}wRgO83M#rhsV#GFUQA<_je&+qn26KXv`xUrE3*=loRS+c|f9{8j~>0e73=bTkX zUI%-hOI^G9X%4AMpU6jgbzVFrmPi0(e0E8KJuE11N^gWBx(DSOQ4!u8`UlvF+=w*j zs)G<0EObx1M-+)%8!u~>@>&1Ge*k=Yr`FKuA3*Ix{1vKSA2n9q-*6l)#%x^TE&)T( z)@zZ(xt-iZ3rFH~Ff!H0(l&>R%aL?SO~i;t+)w>{BH6NVk0U=RIC!E!0fNa}P=cdZ z_|@h&3R@*QfSExa9S&1dTf5twx6(Yz!JxN+z))pf(V5WOudslkB2GKX`J|!#15wef z?mWC=%U`dVpIag|x$RynM_GHoF8;bezeH~WVv3xg7F^}2r@say0lN5wIkf%9Y``zLFD< zptn!tq;mm)=^T0kdn5C5w&*|n51bfXGxs+qj-Rl(GMRU;KKX`8!1OZ{{9Q96nN!epbH3? zU|k&kJKO{gI@Z+QYhJZ0i0)r+noi@@K%%3>H;nOUXt|J>6m%{#x^mB1+r=s^_+`Mq zc4&TJfA+nW2(ptfYa>~OR56J4xhuUs=;c|R?9ZS>xi)|Zx|Al&eWvl<2cWorrTdH+ z|5H(1z+8J5*sd7kC%x9d-kfQxnJGPGnXLf{+9uc8v=uK#G7eT43KQ$MhN(R1Is%Z< z@{UPc>jMh48_>Gr1zYBC9>TuDtVLm%Ub-&vP1QGA2ch%n{^cMIAroy#ZBd zrBB?fK^O*hLw&iDy=(B(`P~LGefKTTem>1)YtT{yc4zrd*V2M`o{$0y0&KT(!i2o# zMD_+h5DX|d!f^S^%^F|dsHe%Q?zW@zw`AgT?A$7scx87;wewLz&fSk7q{jq6Bcpho zSDQiB!UT>DoRYh6P4t&o({Sa@pQ3!=zIpq#ySydWE`x@K)ikf@Is@dAC5R;vI!1pU z?J?GaiNMuPu(}RQ+^->eFK~tv%H*)P{@s>pQWVQjz*z%74IWQ^6(cu=_4>cnHISoF z1IL?V@{C5nOyg7u!tTq^d*`f;bFSvTyU)8Pmh;Lt;x_<#dxcc^6t#PM-U!59sofDN zO+~|+q%znK?zv_rIy8ZE-CFa{6EIgbQJDs%xif-ahnJT6{8fq?EoiQPuhU`%Sd&!< zozlpeXRS`4_DfdVDvhr8ija{#=oYL53gdy=ya2N(11{-4gDGg+Hsk%mpQv{x$AUG2 zMQ{uKIdRInr4XG4y>{2QVH}7wIBPFxZuN8KE4#J%`Nh|D;lR<<_%Eo5hvR>OnhLLc z$a{$yD;?YI7xD)50MBFsov;2rua6gQHAGx5`U~eYp&Agd^(195e2Lq@BG;CpcP#f` zoDfRf zdK4&1(;IfS=Q*pt7b=B<|B>HVNCdUDD(t=-X9t70ioWRESpA7pQ;AP7$9_BxEH=%r7I<>v&CbAvA4peK18#}OaRUCXEs|Zrw=B;&>tStwg!FK}CV2DL z-5Y7&4T_1{rG~&pE?))~|2A49NIG*QTSt*nX!vWSaF}t|Nbgv_^*T_sQVUx6ztZKj z_~+zQ_PyCtR+KAxSMofydT-|e$_NZWgmmnzz!>kC46e@?=BF)&tmwP6kWODvt@_R{ z$xk!pEz0Bg(+LDEAH3q3NZ?0;WoDIsR^W#AP}=}$R`S0zA|r|QQBo2H7ERBTY5zVnBIDoV#tN(zbbmuAE46% zy3Y@tkC`Ojrbx8jw)>wiWb`Rgw=z(PX}G^*)o z2atEsm?^YH%`xIMa48^Fpo%msNmC;-?|x6ZEFx9ohU8$$HaL^k1$dLZYi{uyjwoic z77U`Oh!Vf`sLgI+KA({wA($S?A(iqD)`w|G%A2tUF{=u&VXNm{SXto>uKkLF8yDyG zpn-|iC8(>3^D!uOXI?6Nj=15sWws{8`Egk9s?@ESfIv^^iV|3R=PcuU*{r22*A(Bm zN9{bEwB;}2LEB&Nia+r&Q6KEthq&!v--M!0d48)$A#6|yeU@yRr2GzZB$-XV%HjVg z@65xg-rs(&+G?jX$u2`wLJ>BZGFCDtgk-KH^D-_Ot=bY<0{aZ;a-}U+2_v`(73*vOorW9n`PWN+CUHcrF zVPPV4EBwUs>wc*>8^as2eUtqtGy+Z|N9h@VDR>;H|2q|x{3~6ZtiOmTWR^sEy`s)> zS%U42A=i5i4$So(G)5#y;0z-DTZO6-6Nx=%C4Ke=FYHZDQI0IT0iK_~p{QdSe?n0- zM^_Cy0E%*%U5MhSIiv3JR@^1TscQK)F6m~yfkj!L+5k-3m?d041YbLeTrZvQZP8b% zO$`L`w?abF)RR7AUfRJ>cek@!78{!O&c1-DPN&`oY`(;szGeVe_$L1eMOl`ODQIpa zG{u^0q*aukV)a-^xKJ;-zx$Zg=to7wq)2uJX(_=gz1Ct~za(*QZP9#uh+dTnt`ghZ zqFwfAS^#IPzI@su{ZnC8n{qJC{7i37)JxM2uQX>qtvzwo+^dXQCf%vQOxCM2F4?yU z74xSl+t&Ev)yjDm7Vnc-!Igqkc_0aGVi+5q-6>CEtWCZU;}l^^ zav@a(HqkxxpP<#Qr{DS9@WSn5ocp{Rw{CWNGoDy+I5t!-*c-Wvkzr=oOz}pQmReiF z{$>O-W~>r?R}i-@z$cZ?-we_r1NKy|Rt;<~d&-iZ0&Q|gvRQTLwa6}kyGd_~A~TZV zT+1^#UURIam_t74@*yhQ?ZAFibG-LjG-dXsr{QCc99U95Y7Q65LafwpIWK?d^OX{O zXOK69%x(kgY!f5}_Ixu-S4;5WzSX(yVL9xHGh!qO^6j%jtV40aTpowg_DUD0x4D}e z;!aPSZ6eOt)_48A@2|@sj?A|jDw6Jk-=qAV{qo0(+6#?62@m5Q#xqOUerO532Wrf~ ziB!6rTtgA>-9`VJ3zt?q!y-!9Y^pX=nS4q#(prVh7LI9`AN!N5LVG^D!)V_C49$AK zemSpwb0XofMW^nE(=AelATd8EbJ|~8@LkS4Cvs^Z-puS)8yR}z&stJU?5$wQoXLsl z^|{=#XFW9PHlLQ*VqR2Y+pV@;YQdIQG#*azk}*~LwHnhq^btKKOKn~Vh2B6u#($~q zkVDy!mFVuVqk#0LdQ$eno88D_`ZE_=qkqv>G8zZEKd?t&>Q$v~d&B|)8qFJ@?cr#j zXdv$(V&pcib-bCr=U2sL|K}J_p?HFXh-R5T@%jNz)^7vybiQ$wg4s-aLtQE>WQ z9RU+%Nhz)g<)2I4^A|Mux>B)G5qmyda zugdAlZh4w<9n|V3p}nIhtul^B*V$s1?N~8p&6>AYyp%K5LQ3G3P}4=ZA&6t7qDpv( z@sUXXrL)~8q5jx(xgVV}H!Tq}f*8_m0N+}R;z(ItGKl3HMU&hQX4G3}&;X( zw0knXKE4kR)wS9Kq%H3~A4b$)Xk=@A)tG$+^TGytRF?LmvKzRQ_KP-);h%U}_6s`3 zq4BYhS38@48MfJ`(Je=pIq&VLTCU=H&nQ126|A)fL z{HpNWY)yTcdH;`>#G_<%VFVoebLhF&h>V8EG{T`A7+s-aR%PaOwL_=5}R?t`IKZf+JTjDCY*v)u9ydRMIJsF{jS_ zI_fOg{Y`FJ$sgPE1t=;mEw0$_ZprVvkwT+YdyB~nlo$8Op@fIyf(uKQBmFaq)%NgfPr$^Qs{5c!+|S0 z;jyNAcfO4Ovl~x})IRIwENJe*%)u__qt=CKe)Nh=Z-S?|$S={o*m5@q+^fnhf=ho= zXowS0Vt3sbf^{~yQ97y+VUri)jnm85xQ?IdGmI6NX5vWdRE)WiN64H+iTs= z4mu;&NC(fN@s_u^B{YL)vF*`^DWlUeM?>tR&rk*U(cEw+&rGA~xI!+bUP4lxy_Y5e zX=VjO%^Sm02HPfcvF?P!VdHT8P@W_{L(`; z!v&8U9|9q9OM%Z%3hv(1y;a*w%{e-SOyENs$`i*9jy%jqry??!w{%*P2iSS=@1X6K z(3A5P@6Cgwh_QSk1FE6}7z_bDLvJrX+3HL-Ae>*jaPTHJ)I8sIWG}ZyMFd{EpVA>e zU+G2OaZwCWKC1P?V^YMmXRtKJNPR1Tv{?_6EV6d zo5+%HfE}8y_V(N@Ta0YKGzH zQ}Tp7Jozvo)#{{{n0C5aM!(@aoRl(BDSw!CzGFJ@1MROBU)E}v=tFKMVg#{e8s8hWYk&F!LKhSv>8ND zmE6C#S4!_}t`$QNt{-bTv>MrCcTnuoJo`OP)o2S?xD}elc@6A$Wson9o0WcFL(iq( zm$Q#b{;jT6)&k!AqFs3SYT~NqgTZ=Zmi*ROlEOtb@t7jkeFtcr zqxnCXeo~^Rfi|>qZLY-&;pCy30!dnpTJIWOYk~B zl!l7v=X7RiaHtl5+iL(I6^>bV-4dN-1$B{?#W())*m1ECWCTZBF8by9>UGiy?Z%Zw zFOe0K97KIAYrw!@0uikvr6GA35jZyKaU zOqthijdN{n_~f&Zs6$SzI%zp;6x%qG@4h> zv_(te>H9A6rJNHd_GY=<>fEouI{IML8lpG|z$YHrrP*8>{f%H;?WGq7UfRY}NScy9JtxrMEA>W|!Li_{teNJIg+w-wZ|qh?wvt zNHK<3oY`@XII4YFYdm)}yf<2K@e(cz8#Am{b**;q5Yd~Xau*ZmKJODH3u zN2sBQYjb5Y?}5yivA>H)Ow3t!bIEx#b8H2xnRK__Rn<6&UG5AGooU$47pQQ>PYn;p z#r!@bUR{T=5)$l9Pg{9vco^p~dEG5*bo+~X(h=+xO_*<*RkYZRHDJSTu&h3;Zh8t4 zbY;?@^!@UxolU-}QfBLDCEcdXE_=gW?hgG>hJGV&%AEA`v<&s#?JL&7eN49n7G3|_`xKOHx`xbw{G=0v7H=7>zfnr>LpU76vx{ppyQWpwTZx zJH<@gc=27qnv<;$8lH)JlCIM4`FP|{;7LI`xG2xI_6F{)4x9bA_4i@Fl%nu6=yyhr z9kQUsq7pduqi*TgD?!eYQFdjziQykG6h&xtd$7XkITD_wm8CiB3=kSPrapu%)*fK( z+gv3I$ku1vE3lfrgU|D-dVN{FvsIen;eCmUD*DhrbWlhD+#m)5Ib+QbIy5#)5-Yj3 zPN%N@^2*1}{6gqqdn@D+3I7CArfm(JMOqGe%i3nco?E{xFWBu-_IT6lW>8W6@zwWF z1`EEXf3Q6y4M_@5jQAUjufwo=S~Bjs`8wbxSNk7JZDp?#@i-`qvw~n_39rkLIZXZ( z#zm>lYWyd4Rr^!se-NPmTQyR*1D4m@C>l_uw-W!8XX~XV$Y1_{lv7<=pH7Ru*BWYGRR6r8YjT-#|Qc%9$wy7q+6*6*hnAhB|MZSLLnBFsDOY9b@_?J z3LQVG|A1Qcb}ZsaH5+YI-)c^MtUoe`XMej$D=?c7?Fuk&x2s&RSzT8EI$2Y6<7eV( zF9&^VHdKJ>7F#_4$CmN`gxKl{O-HIq?2Mtfe#fkF*|*A@T^|&IyjuC+A+OA)-yua^ zD6`&f0yo=1isV$Gg=X#q&BC1%C*ND{wEM3uXB?!Ph3WqqPGSYmbGIk}#$Me8nou17zzrdns#WZDD0o=fz-f5 zm%@Yowq_KZCzg$_UI;LOo_mD=n}#Gw_chRsac4vNK9ZRD95h+SNIO9JQ7=#G5%p|} zAycB)qFa1|w;rZ)uCKb@&|`$U*;5@AReiYf->a@P)lSA>f}Mft zSq^TA*~r#{uJRZ`YYV8BbZR#A+MoPdchN;@&pew=GwB8wH^xN`LX8 z>=iY(Db}~me<+g!AvI7Ou3rjoYFfOB#XdeRMfP^36XSo0;Du*yt(w!{brf|ue>=5PyW^q55;WK@PM zDvVB$K=@#=DWwofbnv4+GgBQ3&z5qN#POq{EU`0_9`MoZ=I{g-?Wq_aJKBxT2`KbF z+oX8&x+Y_HsAYHF^^YFDQ-#fum(GZ|EhPsuM1_AVJ-J(DCJt{O&$<5=W0`vw4;NeZ zI5wmV>)Ef(6NtTCZYp#4*!!F0`dk zk4^q7ni3U>o9JI^Oq-5eIbx7?eU=8ZtbpSazzlnBwGg!HjZKq@wB~8c?x650ch~;Q z-<7$=LG?)ZCqm4*>QYbBVXB8ubaTP!)Uo=T+uv?1#N0`_jAr#*34^8bfJJZiIC?At zR|i<$-HKDd}n=9*wi2jSND0IKP2iO&uVhjeFZ0R}lMK$dtPCV{D(Q6e+cItyD5 zm>~sGEhw|d^oBU}1$c}OAlVFbzhV*o#rJLv)ned<29Ur%2(or3`GRljuJL~xm(*{Q zA|!#$eu_^et``gMod%>&YDiq5A>A-Mv8{hfoHV6wd9g~vri!PBRSyG`w0%ivJ^1pA7WsFYc^ay#6Z?+``x_z<#2T8N_xizROi`b zYi0E!@zX4|{6q>3)yK$NMvzMBRpgAF;_^q3W07Z(6A28`Uhir?pNk3Qh;hrT^R3}~ zqpG}o+gvJ-MX~~0-Y+Px1=BVCJ=aBZMDAbn772Ybkz~=A_k@Y1T9srNI8hCGR^)<- zGViFPC5iq?hH3VtY@CvrM0GDOTs7n zyxhW-VwU;JJ|JZxo<%nC;zQ7nqSwRqnjlflb@~MDK}llyN)3!rqLA#Sn_bpuPTP;uLDYUTL+i{dA(jp7S!NQNSm>WQ|aOV!th zu4s%8JTZ=S!8z_b8p8P6_TAmh$oQN`~Dm8_<`!wg7ta4jlt8*_VLZZA1+ezxmvP%{tY)5 z39;RI0?C>DF{0@fNKdoc$`Pn*QqP2+tL=yZrp@hsU*1jHn((cbnJTEmP+ULql*D(dWwFb^EKQx2Tswm?`m3K$t_bbv=$8MX~zR#2K)#m!Bgb|Rn zvxSfVhDvJ6H@)sD)B=>32|n0%)&7!LKJcUd4Bk5sc3qL{+<9xxt6c5cms_IvYD~!P zkKnn7L&gz(S103$yGK%JPSfA>9GjD|KW}~IU9a10M}CP%zksESyEyin&!KJY#8w{(}}UtUWk2!=PQO1p0@wTN6=V+sCT9lF-v z$Qk=6M$Z}AU^!3DW-O3iYa2RKzw}pbNWM|Jy+KFr?Y7CXOZq(TvH$gp1SC=I!V5Q_ zsP8VWmw%D;cbb3dqxnex$8ls~>KqG;v}Qu~#wwGMODrube;uQsl^Iaqd3$yal)Z7v zh7e->+Bcb_1JM6Tn4;aO+7Yd7ZaxYG7pSv{xlWGFM?z(X3?|p&SS0mdv`cIcP$F}5 z2eNgp5F~a-G_SguM)4x;!R7V`B~R)VA%oimoS26g2_&_~HE43dR;6g_aD6!YbL$8f zDJ}JFaHis`AQlPB@B+^vCr=<3c|ZSxY(RMQKD#Ki@2EC(6>8fQpU#u6a%ED;_c|b!|MPc2;lM|*Yj{)6CC3sV=k;U8B9B=K>vM7bvfVOZ?hJ$ITN&&l`?An`;NG=`*rv&hpYt5z9>*2xByk$t;tFvM6F4z96InP6NsWtfbL zEn+r4D~US<2eL+>*pz-r?}_9}QWe{Hgs9>vuZ>M{7=zvlElY%3Lu&6<|MVM0jo?Rg zEuZUJs6s53P{hixl}>QN5l{v@(lfRGl}z>?%C=OZ%uR1HO@nB7dX_||&YWn3DzbuA zVsAf4xc&vP<$M1Hu|1EW-zY(_8 zo74ET+%2oQrz}6oxHP{0viI71%?uf8POfD2>rIebsHl^r_j`uVdr;-M-N>m(gJS}% zH~~vW+9`jA*c@O~gZhBF)Q1em(66A6q?U({z^yq_+<;}JUh&Miw^8CkVhEqD z=9I5e7IGvZyG_vWd_}Ozee>91g5`mujE^+ZZY|A7(sZp1w;9a{{plnST5`sU}vLE zO?4sfWw3#NfBos)(C&^kp`sXbXYHOwo0HI2hOH@MUhnM6K(iQDo-xt}VVe6W2(wlS$aAqkH4xK*#;v?4;8`RhJanwqvM ztxEw?XC5lGR>l;3;pLrZ#WLh7e8$Dmu4{bSmDR(nXuQ!O@U3vJTuTf_Unl-b`}0Bz z*VIcwb!iK~rUdEiq-w>{c}SycxZc`ebAoH`dK|Tgh0Ty|nYzS<^_GnD29m)~Nw*qA z9eN#{3BZgXy@E|;vcV&QF-=uF2QEagOOAUQl@k6G0P>0|3@fhVyJXskIGg)0GE}{XamXeU6KrN&h{8XY@He&nWvvvA$tLIY(HuIwOs3mS@Ccwj>-+Up4U(Dhk~mE$zGe z`OfR{rgp#9;~blM4*q+tq0^}}gB>PX+zBSS=hah@bQB6DT|99lr7z`{k6-s;n+#8Q zu=TSyK3akK!GyrRC(3+X6>f7gS*pPyf6Er0N}OJ=eP zN*n0b^cLC8?k9=TZ8BZbPtJSmJX#1SjknD}QO8`pfy?mRnl$^R*U`_q%s4C3_6y$J z9*;7b7=3Vt#7w=F>3Qi+SpXu!z}SnNh;?{9oIaukUnM$E>97bc9j*>B#s_lzVx2a( zhZW(XPAFojEjj_LIqjkDLlR|vMOEMwZ;`~g!0al%kB0}PXumVfoM~Fccy@NE3U3r6 zW#qBwTWUip8&Q*&-*49YP;0(l zM$o%JvcfVgSL7uPXF#d9#-n7YrLWrSPx%c6UGSKfF%j*-a#Z@O93u)EB?_?a!C82W z-XwM;VSgCIdNbw(_^4j8aCv0tmls&~7kr{0pw{feT)jl>{Zkm$48pMT5&E9zY*WV* z4EOhBYP)EtJ-fU2LTRkpjC#g7hMukaGu`HaG}e$y8~u}>v)YqGV|9DE_t0w)HV&}T ze#)Q`ppTH;`FaKATF=mxhE+;7L)fM`=NKlrb#N`t?LK*Whv(X@5VVnnIAHgsJ~(~j zF4M0H1w2|_DscimT6N}M8qYmFfc5E8Phu&0&R5+B$`{<63p(B9e)0_~`lXEf_sH5p zeJa88#f&Th{~aQSE96Lb?JhYYlAE;UsP=$SqT8602f0+c03@eC+W3@@cpF)Gk*!Sq z*i*04FpRXP>7;8eHGM@xIOgqOIo}#3=v1||Ja%@$Y?9z~_&}wx0;Y20 z(9(CkTF_cGZ#Td741Pov|XhU`8Yz96zPo>5^%`^}RJZlJd>-aq?1TeORXuodS`6f2VsDtdT-) zX>Da*{oFId{iQv<)cJS8TXIq3f&yw(A#uyC;%ybq*k&op_7&W+yv%u)gG#fUQT?L& zT>6?56$lE~@Lb^Z-zc0u6`*iFsS7?q2ny#@@DmD`4t7q&4@R?xb~Wv|sI%W;ETF(Q z7p~mH>`BBBCYSt=A#6s)9-os#M~|}j zB15lKY|+z6>ySMX!lpj%&*g$l-Y3@G7i#_WuWMbf_*K|$^a8%b)8AcU=W8KKT55HT z(}NdZ52et&F0GmhjJK&XxRSTof=1|`CY*mN@qA6Z*gb>h?y5lsZmJgozg?e$G1|9c zE1U@YyV_ENRd}gQv-r2h{6*J}H5?cnIrp)?2*?6i2??nSWGpRn;PKx=QeWJ4e$!j& zewVZ@r)+Y1XTAz26nD_uEMTGD+RQOIy;3JQ{*HrS)2+_)F%EG9PRD75KA<LQW{84;V^wnNL>CHgHL<`&&cAMQl zo!wC|T8Sz^4)Top55gxV^|t0A{pZTKHZxn;W+!Q_x&GU2YA=h%x8%-B41Z@wazY-I z*IB~@yvS|&RM|#CccHvYe#VErRGl*Xx9N`uxz)b(o_PSkg5KR9#MX@5sRBFy|3e1-0Inj$s^i8Z@W%xOp zvUc^E?_aO9I`U66apx+TU8CDnOUj-_MtGjH<`hk-#HCj+l$JY98)JG@r0qnPjfjTH z$JI)0hUe$6k90pZlH8DCGMEEpWAa}oFp0{%0hRFFF_PEf_v@XusKTse;`@px-$}%g@ z?r=}J)N|!ieY4FtmIG`W>U2KR*U_8p?>BXaMBAeGj~%S(V&$5yM`#qpQ?`^tSxjQQ zRs_^6o-m6&8Y{8J&ptgmM5gThqdw_$+P$hOtk8p?6#7XIM*l9|@yvVZUEfK#<8=YMZrsAUN8>dc0Vu8CqpMlm8I5Qy)COzchNOy-QIM=v4E3S z^n8YcNPRFLWw?3X{m9e?F}Lb*lzT(6&tQ`5zaiAFG6_AK_?I*+z!|0T=<*LL)m%nG z;u)y=)!E{qys6^N@%B||_cbeAJNp;X9p}@r@cqyH+Pggv6c`koFy!s69iG9{y`Ye< zMviPRi&2jt&(ks5JpyQrBj^c3px>2T&HV5jgDnhG2Yb$vYfWjQ?DKv|4B`D~1Kpnx z#oe6NvM|@9=dmXY4;m#a92W`tK=E3ytx9!IVZ0(q8C+Iu?T3yIf|DB@UEfStg?=s_ z_IR88KsKElQ`Q;eM&?R!TERZQkb}G!JmAHk&w!ih$-?$NFd)s2`cd7HRc|41Y&Q}rFHLRSnu3t|g053&xj z3vvo_OWb>>#aOrC(It^0OHr+PGZbObuwr%%kFRhXd%@6^1I--x?TzJZ&>>;kFBH$E zUt0x(6^~`)Olvp$1sz3MZ}n_UwMzwFxGhzF32K+x&ZyUFe~%`j)`VxToQf z)=2ynu;iAxnnAmNUs#mTiNp_6!$b zk=#GzU4vM+y<5Jl#5!S#ykvY=l}b(VH}Q6tg8RE3*oNn;o0yv#e>l!`cNlQ%k`Q%0 zyqoK@SG{!~#A*W{$kPZrmiJCsktn9Bt(D+Dh076g{*7U5Y4{LEFO_&H!rffM*za+v z`pin>=kS4G><=!Ilvm7jZ+*$`7?@GoW$SkQaU@X9wq^Stz&qtmqKc zx2b@}bG`T?YfHkQeq}tCskQr(hW-ucHu&0|r9J#Pn3bgaT3XCGo0diJ3mmAFnV{jY z*>f?BL3cmZ-kDE{bv3q4CnbL7$4<8oo7iifCNI2^M`kCTgG`gQX43nQFwP1z2DRLFGV};R@@_aw=9;gEP9wnGVgyJc3zgy-eAnaG8ajN66|GFk&_c=`FamjdFiuv zHEiW*W^^78Wzz(^B1^o-W+0IvF@d2zR5=u32PJQRA9QFfMnuW;dKKO|de~k<>5Up9 zTY~!7XI=tknVzC|dd|xf1`Us3p}vL_LnAvUoMi??=kDg+zwSLfqB!r8TQ1Zfl91g z+#3m#Ok)1l*Dh786Mg)q`|$OII^Uh*(P`Z~<o_9AY+fVg<#uO zxA|hQ{BL}^-$VEVR$o<-^vF;CkQ3<$V4NQs^DMOxOeHGOw_msF-bBZXp?;a19j9zb zpORj^+VPb;*E%C#`vFPh3RF&z-~M{0ha;jy1U2Z2`@q*n@n`X9S5dT$9@dcLX>cvt zStSqe7P`j#Hr^)P)%yo6)k_dDiiCY}Ileu)(v$8x4Bjy-xc*T3Up@f3B|5BASH|yf z$x#=QvqJ?7>Qimlz-_trET`-Jj@bE{cbt5;=L>THQrPt5tE{AOkIYIVXM;)RxmQjzN~lD9 zE8f)bapip`>hvlfnb&P&k&ioBle#hq`p0a?XaUqk6RP~Du5V5+9{aF(_DaMVUcHKL z;cO!tcI6012QBbSF>@czkK2P7hlEiBQxnrokRpQC#Wuj@J@)3q^a&+(PGI~80Yr6e z;0#G7o0VkZ50B+S*#GEE3#5SUbZ`yP9Km94Et1b=Suyk*a3^?$jIbB`5>5h)LWz8$b<0HD%Ym zl;XDZ-EM0L3~u6J-`o*Gl;5;J@VY<$CKVO`ldE5TBE9&Z{6}*bJU0INlT=jy$EY;X zbFFYJR<#~1>+lBu=wH9C-GPPwO8l9)!x}&LJbvi-c#QbhpZT}?tRw&Y?*EgekpGja hu>Ya|>z>Dyqq}Uo4JXr0`_DPg!fOx#r@_I~4^IA{wGASFVsKDaxu{xpLhV z|M0y#hv+u&Pi|PrD9c>AQWZmdW^xn%{I;{AuG^I>57{mr zSC!Nr?OeHn%Ttn-(eO6f#J;y?Rmzff2HK$*1e_d2z7nmHW(9X6qzU6_37V5}*`o&% zI;}j_B{7Ljq4JKFKPLv~rn53%IZg%pQdQD6X>Y@HH$&2&rswr?H`o?2SZ;sOVy zAL457SdlXE$aV99vaxf7hX>7S{$|M3BR5}NQHo&UxGuS(>3-uO z7HStUIp?b*(dtCViF@34b6k~#QLQ)Bf;kY;NM#oGv2hH~meIH3eGQk`TR&-~Wxm_C z>hm+^TQKy@S1U zI6J9=`t`aSf0#7(J|V2;<5Af?6&JHK*^s*Umyz!ZQQ^~SDcqGq?& zA4Ouvy3s-2e!Ja;vY57?pn!7W7(vbUfYViow<@aQV!_-w%{$-LJLEcay1#fq_h39O zPDIxxkB7}I$80VlzkZAtJXVhg4s@1Kugs#j?PS+l&Bm$nx^>dvVYMN&ZB9)^#L}r8 zB9d2?2JTn=px!`MeceLcHtCnx*x>sOS=rKR77p{!7i{77T0*__<2ASWD>{o3_iAV= zl26h+Rvp>`(Dt4F4(&SknkDD-<583#gx4Pja%E8-)FX&P!mr{`&uVEiZji!@%~f9q zc+xh+kZ}p>$lY&8@pIvU95i+;B64W}DMZ;8%Yu&x#R#!YriGGYn>@1qb2SyWV;bO9C ztRqS$kI`9GPC+J`2zpO64ad2V|H&k4-0sWwP5^(2kB-jx&f!Wp!hjSMe;1Az=durv zu#9M6Vwlyp_PkQcx7kk``-V;K%;<%;N7|`^mDRWPK>#Ztd@XhVTrQE&|lB8Wh2jm z9El-^~<;^gsakE`jVB6FVr!d}5gFdD7Nuev20N?o{j;0hGPhyQQwR=le{V zx2nVlO7mem9QcL{2v-ci24FS(_f|lQFnASf?}axY2y(IePU~if$Z@ad+}6z%!~N$Q=o~rV;Kh(Em{NN{1|dMlVw`d_Lst z@!&fYA$n!_dTqBbRm^^`Kt~*CBK2H=rsp#~19Gu>iZ2imSZYcmPVeIvhXi2u4{wV! zO_q#vyBwqfGUa|SN(nJ~?Z{WA_j?%L_js_~pjcTHHh9Q5Vzk(+(_HfSiLOAlzJ!iS zUKN|PHEVl}vo~!3-A=A2F>B!(^V3CtOruJb->xo=k0ynbS#?~#OnrBQfzfvs++eWh z*Vm;~5D5f~Ym>=bW!n{MR%2jC2Xn|+p?A)vgYB;N7aW6Ai*GZYZ-dwp+*EgvTNs_Q zwyJ~+zvrlWRGQevqy>upT0u<$9g7be5)s;W^EHi{o?vTgW)pryTP4pw$&xMJ`b9We z!^rcIcF>NY-&ifPcVO7Y#uK{+2?_W0E=`U1d7^_JwczH|BaadTnPG*oyuh@!0@wqe zmQeTi=jcH*4-}o;1a;A}%K=lN_@l&qfPX1}lR){FQ28E5(007~qE|qBm{%P9o5uc6 z%9faH9P+;8u9E1$ZoQ4NTW$^d{%%UWQWtSX|`_RQ5600Hwa- z^*8K=ZW0`?E*O|e4U+I5^QnB&dTz0KSpG_x}~RS!$)N6t}2 z3qv@L_b8=%jN3gaon~-s=aPx>p{1MS&v10c1`@ygEV)_mS6V4Uf!1p`21zx`-`X0W zq0p5H@|Zs>QDaj~;*m;7iJ{y3n8+;EXEmXu(b?ZUMpv(`DvWd5(p8vvaI#95kd}ld zi`XCs0l{N$a+enL0p7}z=I>h60|2pcf1O39hUc_9pfBkH} z4kakg0&i{(^OD|{0J}IZO*@wN+hv6mg(zJY`&FCJ70nP#KQt9BOgQTo8&Bj~q`FIb z1phhPenNfzO{x~+C<(s#N85NH2mgX#hG2Cl8yN7 zQ`zG2bYB-;_c2kHD48^QC5~WkLo!i>V)ei##_d))JDH*Guh#cl;`#5Lgtb@7QVU+6 zYFB~CzxtKUI4#9|9k8c{0Pot^_ojCvKK3_>J8Zwo1O`{UFGYu2n&QqKkt@_vXaH^tKql1*hiZWH7*sb*~l z0W)G7?-PaXO1Heg;G~UJa-WGT8X+P`O7@H>B)o0o3FOwmn7!g4>&-QDE38t zey|c&I)LpVZ1VSC&-*JyLnK2F`l2jO!B;wDo^(#m?p_O}h!L@=2TxRsk0Gp20@h>7 z8`3$LNHcG3J6`@(bf#mdfk(-=RK@RY?z*#N0!}fzSL9_egLYL#2>jrQ`Q+Q=H_;Gh z2oG|hB`jPN_HD9ofy3=Hq5kR zd6w|Loez#upUcMF_8W=KrX9EYF%M8Z^1rI$ zINnxLhq=*y)(f9c=RAR)!`{Zx1Uy|x55U}>J6@1xwaO>QUn9$+hdWe}BcBELa<}32 z<8}TfY<Wm2-8Qo~D!i1OLp1H%0D|IlC+?d0-n`+H&eX$k1t(WTw;An|l8=kkjqf z<|J6p=L_DItZTX}gdj%9qm-@?HcBuUxOshf?Mv?ki3VGNY$p5PTwt7v99&RjXwR!0 z7w=E-0{+6Y?A6_XENx+aob)2jn)^MamF77d$8#o)JFz-$KZ9p2;_M#7%XK+h z7hzGj7)DmW%sYzi;wAEtNE3zV3r7}a-BZc>uXm?nSuZvlOWO0zzRQo1gQ+~1FFzJ$ zc}Lv!au8Ym)r$U?FAgI4vRa&0-5suum=iU+(tFqeF3|RaxRIOu!<-#{q+jB>UQhUz zIC>anFjbAdr<}X8NJu&4gYp5tH6v60j%)iM2lc;t`8BgNP;XQ&m$`z@~s0M|BquSvV-aDED6wZAF(Vu@%YQ}YI3_4I5&2d>I$Y?C5t?E1+t zBU|cYF_A!cHMc1qntLn|hnO2?W#o6-Pk#Z{<AdRb-N6P*=P4Vk4f2ncw+3wgZ$DPX+CNC>*q~#I=y+6{FLdo>;}R zEGC|4smLl7P;|-sJon`k>eAJG=EP`7V?%8|N3x{sKG%>s$=TAZTcbj}I3ihL#!#@+ zqn`7_NGCa4a52NGL6OLee^qwWTmwdq6mU^`$N$4 zr_nQ5__@-Wv)cJytEE(li+`P_$~n3VH8YKl(P)&XQ9pdp=mb0ej8zmzpK!MU{i@n}U0aOLk*kK%&-#@MYyS+FP zwQEEphyDo)&o#Zu{)OToWA2gj$J{a|iBo|=-m}vKNyb1VrlIso*8KHNl&8wx^O%(t z(eXWnDI$!=`5zVeq_-=^i8!g=&I2}$*t741w+fS|>`S@LRL-B}A4Pt4Nnmb@^Z~rK zVAzN;TGu{!40kiaIxq#CH>yx;$OBc-S%`7){#dV=Lv=aqAva0gv&*AlBxzZ(-9+9P zaL*W*tY`GF9rtssvPH5b_J=iNVNrO8u3Fditz30ZcEqE;riLkZs=9DmRx5C9=IWDo zhRbnBpY4ZWd-@lc(oVK?|KK&Uwm(BLEjQTgX^mwDdO=L5e z%3ap+qr-x!?9goeKknuOuMyb!Im^*gpj&>AuK#f}Jn7w#acNICNc3hk2JR*Mqz{C>Lb3N0GhW^8ho#!Wsn}2-fW9Szp8qHU!vxiBC(NBSgW1LZA z9Cm$lfbo$Ns;ZJSsk-}aZq-OTXitum=DT1)&L1q|P4bq5RWUCwof5=(B37L~nkQh_ z>6w7*Ubt1O;~=S}y-Vye3e3`SkCDq{EWj;uA`TQ7 zleBwBKAjNxt=Udf;8%OUw!i;`c@x`Em9TK~9WkIJRVwv12Y0-rEuzWqqu4ePn)36* zin*cDZ%O$$Sc}7AYThHygQ$JIo@VL4Q%+~#zWiVCLzL46eh3<2E6LrZL<@(CMI=yc_1k+83f5Iv@MZh(_iF@7mLYgX{&$Gxx{X%$po)=0-1?5PU09Ycar zIw|-RRKa;6y9o=T3=EbBzLLM5nG;zl_9Um(cyV)qQ_+^*O z`|08st>=9hq@H@CE8zoAqwY?d7}dSR7ame}Jsnch+dOL&yKOvAA~eSPVQC~IK9A)J zcESxM0T#Lm6L!ReEc0KjBrJBq`($Jen%L9wt;z)UO49v~IOW=P853cRF*8hPGIC$O zer}KVPpF9XEWB!-{lnZ)MQZaKMD_s!jn9{ycB0a{mfFFOiguIlwVi;n=c5?U`CY|U zo_kJ$oZXFN^YVL5-ja-S$Yn4}zIf6Qvb6e^mB+c|VHd)P<|JIym0yi#XC#(}djHp& z-8>(bY#7Y;Y>A_jSOUA_al@=&Wyq_vlvJeTGeFWrtMoSwQ^;cw`cptPUZT=A^0jc5{TE!BiDixq{fk5di2s9Z{+rn4ziZq7@o-~vvHS90Tb_K^ zqa=GN&uznf=^9vaY)p`Sa?Y-)JzCZbZVdbvkPm<5tCX-(8isCmDp8nwcI?0#gTy0X zzJDp00$Elv1FsE#q_&T!<7%cW;Yds(l}DY>(A z?(%mibyUUn%r0|7Q_$P)ppzYjLm@ERKVOn~PUQV*O;uWcQ-CMicb-%(>fi6A6==2b z;_h93*NFSl7U5qL|0nSHp9L60^ch}K1}CdgYyTP=e}ASo1y6cwT7o0Gh#p32{9_$o zS@g{Qs~`I$CqF~~%!!7-e6bwY!}rgdH1&4NSxdRjRN@;fw#Cx_oC)=f=sPA7k1jux zqx(~r^Y7gMKicyDy6*)d^Bz@eUS%%s+a?&4#UGL1RK^P2sqxZ|2*UD64Gngtf^6c1 zsLxMLlgctW&}w<}F2+qv9TWJzn| zL84rt5RcKW9r5t6^+e%MGv)_R z&9Lj=IghtPG(@ta(tWHZdRQOydyMOonr1+A5Lq>cwcLR%rU6<9YzUH1{l13` z?6YPH_>ApHD#^-%O#JB^2RJnjf@nC5i`w^k^S|GJSMngL-7?UrZ5YQeZBvoIq0NqyxBdvQ+RXocXRL$qGaP~ukpNQ(Qry|`vP({;$-N8%iwW;GQ0!Jc$&P08IIYi-{WRH;EJQVCHQG8BhU_KK34aM;Vlzu#Q<%NqZabwv+ZEcWJiM=v7z` zVQ(5QB#Ox^<{U{yV=u-!%W^1S#X#Fsot=YUbc&)e4<$f8Gk?YxI&u3 z8qdeC+L&F>wjHzhv)7;TNhGeQv@CRlxn6 zkJo#z#*$=gM4W>0#JKw0cpcT8Vs#lE+V!DQ=(UnPO9%8jZM1VWR5FLJt8FQ&;GJ5* z#)QQQtL36{q%E$_t+2+@P-HTd)Cq8K6QA5*Z0s+&_+cl@D(X@op#=A4fq>)9sAK|= zo{iL1ezd*AZTxXrj7ve8wIj?2U^Cr< z!<|`vx&W%4*g0MXL8fubZ@$j0&k}CRl5V2e_O;$Lh=ldC&9)rfQ>5^vr|dz$MPQRX zdEQO<6gMc|SZ?zV43wH2-)l&PgO55z+Au6rx}^Qnj!f;0J&U2e-sdkZ&h8om4!K{F z4x#J!xq3AgsoEK50QH{`gW$IE##R;IpYSUn%(6&ZE`p7@@qJN)ojT18s4 z8L0L3d`<;P=2$*HVco8rQTAaTj6syTvzX(4qlM@nC0o%j4X zrCjtJCv{ujt-rU@jjh}wJqp0EyUAQs5$ekPc24Pc8h8hM=}XF4*?ZWFt-ONm9fbz+ zSUzm)Ow>fxA8b2MNrPS8oz(3Do_&c=)H?l%o_EzRL&dlb7{rTfuui(m~hgjYaR9oWx+>8nSDw7pEVmrU_s5MIy1sryMwT48; z3cz1idni+KXUp-7_Cu1{JRt6}dKdcnw_FWtvcTA2&&SrP59bXqgYXH`5A5wfy3 z4q~PQb(DUjMdj})bs1=5VjKjI6z$8o`rIoTk{fvEw9k2Ie8g$^=lrU#ekk2(Qju?u z&S>6yc|M;k$DR0K*Y9f0^G%9R$E@%F_&7v$hd~SD?1m-7Bl2#t0!*HA#Oa!KZ;QKD zw=`S&SXe##Q)R#Z@>x;DW;sOB&hAV@?vSZmI$OAsd1%nrNyz^iVTbinqAW)h%fkb) z39C0mC$STOlfI#MoMvW{5jS`HiVME3AC^NIbSCJzFX^IxLPbafg#`AHshj z2k|yw57E(7P^XUr|Evym^q2VCNWz)Zk=iU6@Iw^i?`r>~sC+(+GoTNoi zmtqZYNAui|KKI6Cb;ileT#Bx(UEhqIU4o|qiqQqMvPHkkzZBqJc2qexHg~%=$2fPf zDVmOnR`;}QT0!*V=Req2p?B*MBJ{FiVkTNaE$%tl6&Zz&R)z-lV(ycRR!t0>xCp7{ z=hg};+wk4PrpkJk4fF1|81`Ls0JTp5?o-7xC#!}MW8vOl>g$4ztayKew6@plbsvtU z<6K6faVqX~JPuL%%}q}-x9aJ$%Mri8^*h@%nD#-x$ygAlJyH_(jy`g-`Vg(xYdXQ@ zR1#$B;aqA4ZM$2reg>o(@X9`E+@wd8^X^YE#++kJ!mtqLrppOq-RNsPBdOdHhXhDp zvQSr_|N5;$C*edj#(2E?yJ~vbP$WFC4Pj(2Pn*Z@h%*?N1_ z5M(eG!S9RD^J@Xz^a>^bk{`YN%XNU7CjsGgONU~1DK!tg(A2AtNDZRdK-7FrBu;vcq)4L)3VSZ?+XB@a%Uzmf3XAOkgk6 zd)~RlegA_IIKjIK))Hb{=u2g;-<50sLs%P1*hdW`s; z1MCMceK%2eF5xWO4ln8R+b!6*4zSg3u~(@X&_)zCHxT8)Fv6+E*wH z(AKEgt|eA8f|tfm2y!{sy34uZ6$E*Y3_R(e>kYARES6y?mfTf#>2;%&U5H8Y zy}jd9;;s3EuEXrROT5zTM*$~g&K_T4hi^WiUEhKS?lq33-#Nqb{GTi}YDOI!S(AGcZBJ}&ml9ZbEx0oJQJ>VT>4(rH5DU=~TDmC+ zJsR}s7CYwk8uOG{x+hLLKIr3ii{A2U(};5HOrr3PGoh~~N}gQ7)_l~qw%@r;JCjre z1mB;j{k7*#YJ-Naw2@7sc{d)uLE*g!bRRxoLd9 z*n5nGY%fM(+Pm5dTnh!v3mi|@ju#hi&+)ra=YIp1K{+i7UXb?RWcaz>Yq&VRD@~vD zbe!m+7#IlXf3SH@P7xXTZ?DddUwiwL$LsW|sSEf1kP@2ZRKs!V@y+Bio zPr+eqn3&A;)rT57?|Ew8dx10&4PBZ_PzzY93D7iNwqv=>W5fDol*2 z^lyivYQTW51JPP)*6%S&0O^_9p;HtxC}r?+k2GEEk>?7_64hgscT}GTy%I$1FWyQ< z9Q5xbxkwkK^&e2E@Jv+X3^sdw(O?Puc8-;6Y4{3n2WYlthpgs8wGU>kW-nAU* zuY`{lS(m0sG;tf1TvjV|p{+xa>FEk*MnA0&QdUF)zUjMH?_2rTn?awCE7wguB`UhX zA}<#?-iKoKLjD)-N`E4>oAGoRm^(gl90BA#KNVCkV>$wltpYboeSBB;I1ZD+V;rjD zD!i(Um!^+_q%RC>s8DD;kWK604-~4iwH)K9%U-ovV&!?q2&CQbUPqEUwy8N>@g;xNjDt51Pb!t{hmR*|e2jcq9 z&XOpz7Zhx3OAF5#^=-bzNq1{mlf$$|NdQ1^$Ft#Dd?rU4e>Z1@%guRf%9A6%cz{Xk zXtXaKLK~&`7+{kCdf(N!e^Zx#_5Rr&V?dBoxvljXDD{!xxmt%X?(lxgZfAh}&|BI7 ztWDEEE^0`X{mliN zWtWCA%(gK;MPwaB9eTJCfjJA5@JxzzKAzeOF&}Esb=gJj_^4NM=cnBXO zmBRD;>rtNTFo3;7)cFr9d>xO=bGh)<^}3Qfcg>hvu+)BdZik0(iAE0Kuz`FvvmJyd zqK4?H5p-|h z)by+N2`k0K?Y@n*YZj~vlk4fZ{jSS#mK~3}Ug~IhnRe49bt1)VO!H0j@8}V5!exbr zxOPp2^^-j`x}hPd?$WYk$4#v^$d~n`gJVGYVmw?zUhdBEHf5bc5FOd_ih#{_n4Ddyq zc-|1ch9W|UhmgfJ(yFG-tK~y3$Bn6z5$P@1$eN)Z7lS7?^>Z#MAppQ+3@G_F=;myK zu%lgt;h0eKW7NxoD^|gL2(XYg{lw_ay95r-h8Tq9x6=bZ3@O5BQz;h-vH>FA) zxBALINIL@IQD_EpLnis>1Ys$asy+^82fI#9!cKfqtHCGJ8P8@pS(=~5a)Kr~ zh?!iA49Rz=jhz7Xo?F@QNEzvL%`XsZ4A*t12rciWr|;DmD~!kp$=4*xP5%t6>)vZ0Khza5}2lJuQgYIjn>ILryhb@YrsyHLA3yX~aTd)R3h5^jQkG^bA> zd9r2cl3}@4Mxn!&jZmQFHgY8)tayplhxzq{W!V>3AscZaM^6I*$aLK^gHjMRF^lg9 zo|0*IHWwE%3SzLt_9T*|3(wX$=od^gzNS1B`}%yn-uZqxD4iVP$7hF;Dk(wL#4A^s z514gb!JK}zaK3*XP=Ta6Xr2zgdPs=e|BWgff+&FLyN~UaPD)H9jHX-3dM3-lBV=DN z;MiXR>ugpuS{&%FJ4DDFWqz*@#-M6sOy`$6N3@$$77yXOS%xeu#$T`MgU)}FD( zFLo`d4Fs+bV(lk|M+NDmBO)q+Hxkp!2Q+oi@A|2wc{4+b2tgi}s}-xRlJ&te+R1tr zZ8(^8DsfX{yMF~5YQNA1WL=bPmpz{+$Vh_asv4C5722|OF}_OXesqjz`y5uMW?*mk z2Uth9uVx=X@0TT&{3%+7?MWC2@tU2*bcNnse`*ro&@ktSZD&VTf3kO~y<1yB`kp}e z`OZ;O3Cfl_Xq$9$jkc0i8{9t>p(04Z-6aPj;1M*I-l^vu;Ejeyn6wQOd}))bVx)w4 zEH6KAw*yp={4=3my}>0^$9`6Sun;WJvin2(Dn#2PAE6<+(`UmY007g)U z1ma&m1Q9t4n-v(xjc<%j;`IVd#y@kz>wOEuGft!vSW7}>_B<1q{m39NDD4!PRnOzv zEl$)IcCoU55g1j`5FA9co81`5*@n$@>+JQwI%aI(Y&1!t=A@l14+da|Q2EB}Ixo-S zMg>zh3z>Ys?$)m06Wtp6isz;~ON&hoBMbnDojx~$%_T`-vZS9j>>u``%CKA?<*0>? z@loqS-5fkkMn+2CyJ^^dm;Rc=Pltua1W?CGoY8=oVk*ihLHOx%?>k~yPY4Y)ovAUS zHQa@qyA3i6)Fy3_J~(+hDHaJBon(F=wH>VNV$xP&`&p_9^k;Ks9nuVa*tsc=KMo5Q zOZO>;xVKX5mZnRU4Q&yFw|=1jCH#GPG_lw7b)eAkInq_Srkkn#6<8wpdd>cHv)k%p zCqJ&RyoMPsk9N(~sG}l%;r8G=JtgGPU+za9@<1Hx?;7p*mSA4QWK-kZG{tmBhSQA~ z?`Cq?>DDk?mV?S<8Y&+x{;pZ2%-?N)bJgX8fAau@K+gyKuE2x_{z|@}g1>1F!oV%1 z&wqLr2DYCDfLrd@4vo zmxJ=feAaBwgo~Hg2d7hgXfDIkFYjAhUF_vrCO+_uhD<>Sr@aVBOSUU;MqVd|Tb2Rq z`>AOwcE~>6%$P~1Otik)igt{lLxjm;=BN7ZM{UE?xyT0RTXybmGa051XZd#O-`NBO zC^U+58+84|q^4u>3$@CTR-n|6f|v6%F1J~sG8%u|g=m&Pp8dY5&GYv(uv+ei%%7;2 z(u0iWr+F(Z(ca_AS=Vlz0QQ`2CU5*&L++PlrH#$^KQUUg=8W`-G4KL1R(VbMcH9~& z$&kx%@-h~{EY=9@o$488+K51a_1d3HLqXEGA%D{pZ^;M4y9;B{#6{8r17$oX*X7Qy@|xY2u%4^hvXV2e$AujVO7~0~ddOgMPW*3OcOa%T9k^Az zF={TkjM4{{#JFJ2N3U zs&<0O|8!t+g>M_sDlH60a<`ZC)=599HnVUq0DPcBMi4Tbe47iX0?_;%y-U^IlN9|o(#C( z&p4Gt)OOY#vkR%1?WR2n_!6MH^3JAD{?Fd;*<}E= zh-1W6%}Dv-jNubS2CeypXcyEEJjsF_*b#15-DXN^vmDw+N*Hw-!cI4<*3Sc)?Ku>C zGax0o4l8Ce5JI88qox5A;`tWob|duR65pwV#EeVT=jD^{{)XhCC3aNk7aQoF%4Y;~ z!;bA`^L z2dAYr)5E7u5q8Vq^q$jK!tK!ZC^!{goI{kPzw_ChviKlM-hc?)z?fb03MZl+ZINpu zX!_{RAhr#-59kG7OoFX2Cdi}H1nP2U{l=KuJ#oaG)+-vIeuMB-J=N?{DrTu8!kdF+ zDY9Rx00Ew^r}CCgpR4a_pzxR-D7ViA^ts$?cap7H&!dkOZxv{p4@BBL(tfxsYvG#LWzVU9S+c^0-82(%NU{*n z=q%KrBtu`j+XF9epcY2YKSs?+EFN8x&+VNF7-B4Ri?HpZ(}f*tA2%HcwjC#DFP43) zvpT6few8g1Oi+l|++e?fKcH!U4Hf&h_pqse%A1*fDjOyDG-Q+5e{)#qxZov>$+MX1 zhupktZ2;Un*J70=`d6J7c@g}DqPp6&zQO;ND4TDR-{=47DXwDNPm|zhzxg0o<63MR ztydUecBQQ*VKAo{$KD(8M)6JpYV$ z&(3fwh=cIJx882GJ-W~mDUDH5vTd*8xdev@JEX}x)}GHH3fTVYaEt-QN?=A-Cuq9y z*olYu&3k*PewN&JNQ4L+*RS&}YWGN)Xfq8~X7rLnYO4Nm+G9ihZ*PV4__;)Dz@E#N zAsnduhCgFs9`BAaea%Y?+zuNiH?;scqWtkS^_T&jBiW7IldN(}cr^>l!Lr_6f>SO) zhgABwGGv9L$B6X$a$WzQSC~PY>@X*=J3AV8mZ)RD>d^fHZKqOWAPI9ea*UDLk1hl1 z*R&b>(Z-rYM=(s|!xy?(=XIKTop==h)u8K?-7-7>B8M%99_!RQI?ezhbzo4PiU^12^-JC<4iY~- z-P{ZgX77e*`4G-N1J<;wBrno*H6fSdA^XbSKgwf?JbH)BXW3w4<_#y$=veOcXyk;9e$jF1>-_N6uB8Ri*Lr+Mn#hUSur_3kws2XsibAi; z6BE`d&J$hr@Q%rvKuox(c*4yacBbPw443J9jt^@V4yGS+OXB6)?||iliKj8x$4feM9Yeg$*d@VI$GrEo zWq&wI@M>*NL75Z!glB;cp?cCBFkhF9DB zl5gI?&xFj%nWqgBWrl#(Q9*UIqrdgjGHpx0R(Ms}hO(#Z4FX zam>{Z@15+PlfVKmI4jWo`=DXDwSy+zO#l_YKkKUokHuVn(|so6>sOTX zxaNA=_yVe!qCC0Q&j$WX%}W9^ydF`3bY7BMB9JmWPF^%pa3>;{_gTpL+dIUpM`(r=s}#=ho(z zLJX+2qd*odY1-aYyBndG`*9T=tYakaxyB+fYH595-cS@V>ZJdcXyC<#`bVI2*JC-H z0{S+|mIA7*-bS+{P>T;YnNPn|7;go30_uffk7=L`z^F?c<8 z)X|yc!}Q?wtJN!$zDP8mEBjs6lvnn|m!ieifUAV${JW10l4Jn&5o#rl!G%jtHu;l1 zY3%jyw5wh!oRk?|{KzSas_i`^G8Dz0kT&ghYt2>IML08WLD$HtS*;!)u#3BH zPul5w2_{oi=Z=+eOAo}QLcqQjGq|nn!JD)F#%++n0#l{(sg12fU+$;oR^`vyVPQ11 z@->jLM>%jSbyp?+iUEhqiur|Hx`pfcFLln)9f@3m_dg~T-{!uTk!p=Wzax_ZaO9Kz zLbE=Yc(Tv{Siza_UXfX^~}rik}2Wdi)$<&r{4O4rLEmfQ`IKB^?ip~zdO+dnD& zuSkAezs*uV)-Q4F3-45&JO6a1|BDg0Yu2(W9m#k8ZwYqRwZfZsoogvR7q|o;s8F4+ z`X0GF9hi@`fWkfKc6*;J9koyYefk$t}__K#V-H%NrU0XP08RFI;@{o;uVK2 za_1iYyIZ)l+dZaFbXUHzM7|JFZ#QI47rZuj=ap;o+@h$I|7nN6=_wbfQjy4-U;#Yiy%m5S`0Ao+g=P1c_I!x$+XI zxlP19rW*A_=1$W;;_!RwbFmS4>Z}v2j%acDv1hYcO0cjWxf60N*Qla*^GBlr3Uv-7 zM?GqnDO&x+{aakQCQ37H?vaec2{rr8EzDO z3KiGU9Hy0{E8|Irgiw>eL2@>Q@KvMrlJhh}o;m&RYIb-)s)s~|cRTRIx%N!v7Dk0) z(p5Zr|FuAGT@)N|{|+tb5n%6*RN1BN6fCqj-1)W3?_ZGplsF~38MvGWIbakvtgzTH zp+Z;^MwPt5`X8gU{ws6@^sK-aGmoP3d?c;fNC!%C8+d*S_{?O?SOOaXc11Ae%|;PG zz1u(c_cp(Rb&Z6n`s5bn%ANW^+Z*|T2S!LK*M5BSR@6t^b)FATv$}MdV_M(EjHC^4 zHWDbctqPET0_u{MPl^l29JhWP5jD_xdBzmFPl!0{rQueM(Xbu+fW%U?aRZ`w&Q}V& zISZRB;z%Q;4}SIODlGAwUX310J_TC0{VhykrN+O?0~s5yW*Q+lVPpoXtc}&*jtDhD z-K;h0sIKmMXU@uWIZZ=99Uf*1Mu6n~3*SyM;PNox_h&&n3m!b1&^+GHsQkqUS~9^< zqlE`Jk7Dko9Vxig7}@1_G4vNTd<6rJklpw;s?5dG^X&F}5tF_PczrX4_QRsWM6ZU1 zI!vFBaCh)~!L4!01qNyl>G66hzI(bb5r;)N8E@6L$63At9idr%EE zS;{8kn%dNR!L}tXhCFLsN{d-LX;G*6&bi3oLXo~Cxz?rpk;A+FKaqyhWQ0YfPky)5 z&y<}_`ZXEy_%D{>khoX=hQ;BhI8~le1TI_pO9c*v`T`N3ED>{yolWRV+*+xeX<=Q9 zO3(b`D1$_-Y;d@Bsa(cM<(v4ZDvA$lA`?f^ zyaM5&VZlE9{3qkoY_xH?fIuB zv1EFvsKa#)c#Mcz!9JNC}HE~AaO6F&U8je z;rj(&)3=1U$KDZG&|x}j{e>=8BF*N0i+uT{eWei1Vf5g=f7+j-I5SWcX3z>T2`_VY z?$2nf+XK5*;*Ey~(~j{1Bo{;e zjjs3J)J{(L)^{&oaw7>GYcvSngOon)Q~YzGcKpf-Q~kxonmjGn1tiG#c^22S-AAjm zn4{saT9I6%sF#`!;rgFLd~(Z$+R?t(=9^{$cifi6iw8xn7+(#MtRi7+ABTrIgniS9 z@8yUEb9K+CtwFv7^}X2A<{#LD349YuG#_ch>}JdEgV!F7ZNC4G@)JSD6-~ON2sio- z9JRIZA5U83ITOkI_RAfh(zO+={m88v%6U=8OY-W8n*wV^QHtPu)Mo5f1+@)$9?0rS zBi;>%f5tcV&(l;d%yB8elM_@vZw{pRv4!ai9U3RiFEIH#emC5HRr3=d#(x-&V zVouX5V(GuvA4E@qll~FOElk)Lk%!@_*4DXdMY(3<+z!Of0kV&}{HfFYiwEv%N{Y}!>}wVDgf)!#J;;kstUr*U-EQsBt1weg?)gC9h#Y8k&1vE( z-iKwWDxAHAys}FGBl?Pbo2@(rN-L9A>}_i9YXOABQFjM?9fGxVC1xZ4BzYrcnuW1cy??jW4?@`_7yxF%M=j)=`L0hO4iMSjB1EK(Qq5QU zX%9<=*JZ5RM-R`%qC4I-N@NY$b%poY8c6%-=Q+x*1o6a?_zH;n2qI#;0P(;w35;dA_yo5BHhy6-IpSzFf>RjNH<6iAR! z-NJrd(I+)Y4%OEtByM-)ta@|DCosCy`!?9zzV_F^z90wC)kFbh=g7 zo3@r8AdXU$LkDEfB39a1Dr{Js1mD#{`bcc5$1~i1{j%&g7%jFVTJ@#;aVFv>YQLQ;pMNB3xFpu~ z?^ADoms60Y!(CGCxk+^BHHYTtZss`RixQ0HTYTbObJgXM89nVg>f{?rTrEN-o8WzBc<0#D zNxG^%XkKOz(hKd2w=ZXSh3kDOWLIfC5@S{{7SE9x8aJFt7&%E zqI|#b(sd!7a?F3_PloAvQ?>iXpyAKhmNwV~jO^W;33cqa5e;Gmj?F{3SPWi+ciGN4!;CP`4%b z8+H;9(;V&{ZkMG~qPK;={tMdWGdCWHDgXW5{}5RIr(NN{pTEI9E4EV%gDUOsILGz< zJSPOOD99Mz6CLF%XGgs*JZ+1sH1=3r=F2t|1gCKN_$R}b2dHGm)%d^=sRvQWES$0I zmC_J~2GYkuZvIaOhIHLssB0@@`NZVBc`PP#R8jtQ{f5q74vSyO?=))+k)yzjcPn3> z@l(}Y<6vQYCHeLN*>!;}txU@~c|>q#l_AngC+1^DH;<`0+HlKkupdD<-;W^saaVZ| zL*z&3Mx^A@SVXRTeVEFLofbmBfZq?4!dT%NLk9<;aAAL-K$k-(Z++pGg-NL>tu2zu|lS zb^6YQXB+k4+spK$IKX8V13d4N2xKJ(RmR0wV(&Q4SxLSkQqRLnhM49*c3r2F$a!f6 zQM+8*TOGoBKifZ-m?j9H^LwD2Q1z5Q;VxdG)i`6f_4B!vCc)j3wshyw?cw$w_k27B z2fiFH3DakmLhbMEYvDuhA8l0~S{m!@icCnq(uykR_ONox_XOK~OL0pB8zH*qIYql~ z`2zVCi23G@7v>g(16darx^``vThx`=a&;_k4WF86-s69`WTZk4)6n@1S78DU=Zd?& zPIJrYiM_;&O5N`zO8bnG5UO{E^LihwDRt9#LS^(Tq$plEqs7EoY5wa^vR$UFx``A9i|kxZcbB<5ug}bK0s^5E9yK$KBRjhv zh&xB?5`WFao94~36W-rADVw30{wI33&jekja44w@<(9Uu7gt-)nZ>nkZIPKD(pdVP zRywo>^vIzt(+bJkDlcr%?-kQ+Kh7|AR>9jD4?jG?SpQ;|K8V!(KH)8~;6!(Xixk7@ zseIzjkk?@@DvTY?rOyHDf|(>>qD@CyR10arjrML(K2Fhou-)RU)kRWOJ0uY8G|AUM zaCizN6c;!JX@`H*Gu`ECDbzI}A>YEb8ege^ihlRWpvRVnpF(+bHVlHv%G($cApX{ZheMZcNoW{c5wYVA)`4G$g55sPMm4Ee26DO zFq0-1D7>fU81;!7=dD3;aU?(9o1cC3cAGIDH7nc{0J8#*WV5G0q+qOSHI)eAh!|t> zRbeA&JmdLmbgBU~8?EV*QqEaKDFJHTxF_%5y|oo7EyA-^<5qO?Ab@GO7&~`4+o*^z zzI6sYw#1{~Y;f!149hi?l$w+LVRE}uxuBDnQ&748TbnJ#I#s^AazoWQl{Rpq~=@=i`(g79?cY_x^ClI8%I-ks9MLMZpq8YD^;fB zv+ppgq)LbTRyV|TsV2T#12}%bRhgieCgAq_>h4)7Q~2_YGFN`ve_j(U_=Jg}u}%A)3F(z-Kh^6qq3=#vuc;8n8&yjOF1Ej~ zBrKX-D4-ehuL~Iz(dw&Lq$^A7k+N55R>qNnb zzpVJ_Qn5RTfBo&Hlw{$g3AiVS`~@Kg?=ei*5QYd|Tbzz*qt4uCN_>7oA?=NKz^9X! z&{wEq1bMXNQGk+Pdgp+aNW>fR7vG}K!-R|iCwsub0a|++%?g}?akueJVAjo7WLq4+ zJ`ZD2K5AZ`?oBx8)f0*Nm7E-7{nN((i8 z-i93?gt&B_9=S(l)<=8r~QfZoW`LttwT$yR*A6JtKzQ@yN(Es%G(Fn z(DF;gDn={y=O524w;Vg=ei*a%AdZ<^SdP|q*6>?7f?58)*P^AVqTGfgBv`WwX`5rN zpH5l@FNP8ntR?AV({EPGOq5zUR)p6ZH!Rvt_}ZE`5?|OYI#0STC&p~OVLE!k{30~EYA*L&fK3# zTxh}LUm|+=ZitVwV(@!L*mz3$NqA(0j`6@k-n`Lo=uN@R)@IH3z0PxJf+4WQHsw-v zJ)U$dKTNw`=Oe>sh+Q5*ZV>Q89PdDY^NyQj9n$^~uR_2ff8tfE0GLkz7;)PydpA!y zYZqI=r0Jcq$b1HJnY_h0f}r27-9$an(UGEd-}$?r^6J0OE)BLAs9!8X&hN3aw8Paz zqMj3b5sq`L2G`hU;R9I9)op7z;Y_){_p>1bjTx1uduRPwqfbh=(VG3(vtAJrCXlZ$ z;7+{bc2@;nw?K?Vxlxp3jYiG<$Ft@(Q3beRGLc9%l5IUSGHT`QMVizXSB^ez@lF&8AQ^ z4#5t!;{ztoOhw(P!%d!vF@7m5itFM?fq|Fe#_Lxg^|_xiSk)pJmjVu^LMNxUa`b8M zV@xICY`U)$?5a zt|`6%{sD~j4hBKRE&2IdZZx08E#^Yq6_P5s_QXX1MTwJeqJ`7pStMI=I}s^G2T3dD`{S^z3wgvE$6%iO_#y$LVrXTmVcABRo{hbhlJ z8EFJZzMR&gxKP=?%gUdbWc#khLoky#mG5f9OfJVz1s~4I@a=dX!Fi|LVSugf>@wHd(zXq0V{hAIY1Ll@lvBwM_VD)fv+H&*5*0x2DjvtIdlj}qSS5t9RjbI(#3TIkpf|mniV8H?(X8UUM zU!^LNF!ej5#=a|oA)MREwoX8Ekf7~BCfgt^-vWp5^1>k3X8v)sda2~{$s274W9e)i z+-wOYW)`AD=$pVHPe-cfgf&NQ+Y_(d5we-;Oi1e3+eAohes&w5mlvbV0H>vhd2KB4 zHq77W)Y4#=24@FNZD=Adt6b+pVachI~5sbe$mAn5oD|tiChW1*U38ZLcspoz_6`eZ6-&%(=KgAba?$aj|#7y z&A6+_;8rma!jBsZPPU$8 zn>+{Px7vS&kQ8u8xfYd~2>JZC!m%3Z($;-<^hvdvMNFB(k6A~ickpg0yYc?}PCSXS zM?d*kzA7{yE~%}F_V|vpP&H$7R^|*Zs}79HVKkH(#5IA(aWJT<}Q% zkAy2dHJd|DRg*JDVAB6$nXdB`rEQpFd0}Z^Ocg85s2>vk1_&V+U!4AbfA{~L#Nw{Z z^3U7__=&yDmuw0wi2-TmzatlV?rKIbU=r|7m5vVS)(d^3^PKC2J{5C!HoAivb|LbM zvtmi1{HV*1pY(F}M*Yau-5H8{8Pu5L`p;n`DUp;jzlg+!t==>zPjp+2#GW+t&49(l4KNr9Xo=FgPdKTWQ7(L+fmGP1tyog+6j5p>4~l|{`u z)i(hC002NzDf?d@K0l2PDe{+lod1f8qVvl?SrYckhrS!fLaqcO$;tebfZD_dTL{zQ zz}LNDU9ouqffxzZy>Ue8Nxe!Rr?~CQ zjAwIuZOyq5#Wogq%Vt;yDH7BJ$&`K;51!5FN?J06FqIX$y>+#1+wRv9fqTUU%eRRZ zo+IRa-i6j5$%&#gtZJ+aZbL~G-2h|BhYU}r?Y_^Qic9@Y>=V*=2-D4xj@9<}egwih zO*hbHq%%q$C?jE>sX9-WsDmJR8NZDQ`|5?7mq2HZex%Wy9FJXOL+Trmgwy_}{7>Qc z#>~^>dfk$GAJ02gvE0TCq|o{rU8Tb^J#(KiR+@?7!P3rEY_f%kp>J`?iD{N1E&!Y$ zbmofHAxK=st*pyx_$2{t^d4fVZa&I$?kTMqn*;fLUf-Dm%%qgq?6i8KWww^pV#90v zk0(NCu>b6jDWU^+l5WEF7M&B8ruLc)9;e-PG~!jq^IFaagiiD!vmOE9;K=w;{rvnM z4WnVxtM;42F^+219}MM;qO3~a_OLAhDdk;7^knB6iga*XU{yPyrP9`-TT#tC`pTkq zFObAfb^8k+t8N6+StI>bH=UoQ68E-F1*^yHo#7*6^YD-pggZKGVbz*gg`cJR2mID{ z<@P6goQ8FO@jW1V=;!+wS*BvCLu7QpN8lLhn7nQCYE9vJK^)IPdC}gFh&JO~cehM; zo?fl>*D0{TaCl+dxTTMzbUke}7QtvrjM**5^SESX~xfe}HO-{>eGbVY~FnEv07Wa1d zoAHxWe)E*oT9N0-%$Z2GdVLE_+Z5*5k$jT!>lN#GcEgz{PqeJR^rKPU5lH5QU zI1+jbH_Pl_MaZB4(Vu(oibiTnR`v6g%w{NzGgXTu5M1Nh(vF6sGWzfHh69C>ZKLER z+j+V=cNm!VcHR|3mg9zses*$vb(*^uBO&BANT$w`B;i7=f`-wBMN`RA@Z z-P)ez#RG)|*DPndh?J$ev`^0>502{l;|(+CuIYMAJPcJK5M)~?6b^mC3GAzYfv~!d zeQ`Go9uB@K=gjd0Wj?QeltM&;SV5-fs_ENm}jTEE+E#z66zt=0=?AKX^H72100&RvmW^)K;gmoO_lO&;STri|jg@QTp| zzV@u)V+5W?h4xsK+5qw*wZH0_o0)HakIn8YK?}5V6vSiq))bRWDy^G%2G$E}xekDjQhMzXk9;NEiYsg#}lEN+v%x_8Z`E&%SmK|cWm zQrZ`BZ@YOQ9I{xvDfw^zlLV+9UE*8vhXiO0s|G-DEm2C&#&;l0W+v424q^hx!Z!z73rK*8>rCjm4)Ko?aY&pT1MAa>v*Jg1A z2g}uWZNc?pT@*R3dW@RV-s}?$ci<8Bn(N^w?c@T7VRVC7p_LG8lTZ175RMu9_Ag!4 zdBg+zaz3X>%ZOuQ@Scq)$ClHW#9_7+;k|^7++hA5$;UKTOt@^<-goImrg7D~3Ea&n zJ8}$YG7x^1T|m~+6=?nHa=+C(PeiVoviftywhf+0Pi@QCKGc3ZK+!dTk?=bYy}tfC z4?SXI6hKIs9&XcC@~$Ebo2^Nazg2JHyB(`+lL_hm*`qcd3PNzK{nPL4lpllg&n)#R zy%8Ys>BaHqDL8J!Y9A=(4{JbL4xKVzIAo+$fkP%`s!JSJN>T7N=?K+?PZ$r64g3Znj17(G|K883=Zsx z9Ofs=fm)aQy$9T5tGdWN_agnK#Cdr;XkntdfBF6rv32=Vuv)XQ3Hq!*)y>m#G{F9i z$GP+zVx@a7;c1Z}kbS;T*qqwM>p2vf-mn+ikXojm7+WL2qYW@D0uKAN22UG5dJnu5 zz+)o+rAW!DLZLMFq41*WXvt#Z&W%izv-YO{dDg6ZMV~lX2Adt-_J}?2HaZ*<;p$e{HAb`MwF14j+ONTYW51MMF9|UYbMi{HRB$J8BU>xN zm*P@Euvb{i)d5SaK5EuAZ3ip43@Hxu&jHt%35Me^XIHyj19(#Hf-c-TvcKFq&3$^A zfq;>l8U*CH7gSD)>!>U;uL)s5Z z@(WXtWX!=2>+8PJF4>5S8ho9G0BDF1f0r}HYYQ!g$1Z{?O~+<3Wqj673>=+1IdR_t zwXTK4A0E^WqMEP)quB7{R-4@2F_t@6xp{e_(|t3#Ab`2sJEdBMx_N%Giw=rn;{E=N+7 zBK4Y+`?ymvZ3O?Y7xHNV@5o`iVVByV0qF}`G#1|kFZ<47R69xKuXYmu5Y_$4UvOAg zr+?cAUbDK1E_IA?JlE7h0ItMi^Sz=2GB3+nJ(`t-4;B zlo#H(s_CJo8aq_h7YkFVTVhPs0xR+BmYYjyBhfX+K&gFbJ{$+vH&}>S0!N~JjKnAh z-a+kB@-RkV%k7$7xUA9BY;)4^991wtKcwF4W!V;wQdF1@q5b|eJ12!{*ItE|ro6ky zY<(Q`Ja1;wW#Ur8_=NP5}1Q%>_2Y)6vhA*X@LL?2cBT zYY`n^0be){@(gw%{Gqv?LSo=Bw#4IWm77q2~rAb6QTtcMXW!fN8`U)EtfbL z*#z#b5=O~MG`CwA=MmmA4#*Yw72>MGjp{6q||SIH~E zmX3LSfq(J!)J9itjy-kD=g5{*npEUGR#Ev-i$AbWw|8Wfyry<%*fO`zOtqWdpRwst zZyx@VB+@*2&<#s{f6(IMk6){-1o_#ec{!BfI0g=5Z~k?7eAF7-T19Vs)b+^Xl64&S z?Fyv)?Z#r?_4(s0#p~+_xLT8~MmILDQ@-}8;AWEkV>qreo}igk`hJKzC`iw}b8x!x z`E78Owa)>rTQnTMdAT~=gvbG0?y{zT3K{)m=x}50$Q>jd4fn%1{G7YOh_gWA0g+Xx z|K@5=@&y{Y|MNi(dYv*E0VdzGyl;B$_^&;B`Q~4J_nwgMSg-imSy{6;q()zruNxQm z?^I{+tIBf&pW7b=%O1U|XFy#GCoHwCs|riSp#O=J-rW&B-|yZqV+<(KsQ5n5e)0Gn z2{;W2vb28ei!Z^9Dc5l-!ZbRM!!%?y*A|enGg(PB+>- z#_`1N&}7ds2>i7;Wcx_IjR0IB1*r9-z$82EqSjj!r@vfRQRN zkRA~O;A&}~j_){ptby%)0%NC0ND_zu_IWC@X$DwynRL1@(hB(WwR^rDi_H4Uv)r>N5U77uUEi;K*QGR?KNdAoGB z$MNEi$a){9DFe2%*0njJ52FIAzyh^nc@{zq8H|Nlya^6Wce-K|%Y9p=>MCntFtQmD zJM9^y^e?LVvqvp`2}f(}<&$Su^fQmN@wCP{erkU_I!bynn_v1r1q9{B{{#d%Zad!w zqZ?kY;kdoj8dGA9IzH{>viNPzp+1?qSCQvOMNoGy^xkz&$!hbs%WPbYJIibDHMGp) zxFl9rp%M?H(x_%go!!K1uoJ~o!cmf1vulB>Y7uD$t>Kf`CL9N5D@1FwNE3x;5|nQD zm^fy^&0-C5bCTThK<)eF!FpXhxegYfV)M7|N zDX)M}6`)p?$O5w=MHb1`e-%U&GwEYI|_b~HP2hEFOF zNpP5D68Jh6KnK#hL;ldX2W~ayo<8Iq-f3wFO#h-fABaB8lgjMPxC2>1&aGT3pGsCihn%_-44b6X zteo~sZZ5eT#j&wTmGGMWYH{3rbf3lfMfXNL^fEWL6Af}>EH8oSoE!FkGMy7O0(8%? zJ<<{8UK@=RwHg=*>YlpIqX!SsU2Ey;+=2g;gAR+I3rCTkAbDqPCe z1yT-bg--2;$L=%$Fx%*h2CPfW-mbyFHiD%tc<#0ZQV~KO?9qz_(1OZJonB?)F&*@! zCQu3T#^!v?`~4CC$#75f9V=hf^Xcqbkl3D=ZMP^s7#KJvw8dq|4*S^$Oua=GWU^c}4B4q%bSD+$ycm zU4(@FGlV8T9^Ed~ot{Tv&`bi9>+N6$FIcyK$a?giZZg*@NltIxYN3+FpHaLFJuxgP-`dKEh&9hDhpPhl2)rJ+X>EYA30*i$Ww%5Q_}#t6eODqm z#>m8f8&`gOzb>Eec*o!8PwmF9QIxA7Y$AL;O&)89sC$MTt{2g^*VM%9F^+p9tS^0MZwSP|#vcV!q*@i)7VGrrf0$hyZp}*uhzL70$o-c`p=5qRRw z1PiXwUa0CaaC5^hJHab&^o~PW`6Oe1;A?T0R8DUZq3+D7KkQegU(iQ15>Y+~iX_OK zKTVqq9BU6EsmS^8;e`#Hqq+MXNrfro)lSes9D8H0XDGt-nfjNRRb=^A3=mtltBJz# zQ65OgC^rz5BY2p^wY^Ke$qtyMI7$-~X?ic_qr$X*lsl>Q+GtiXiF@p5vz?)0bmnI2 zCugX}InAMV+w$U`@|9|iF>|$f=b-=%J*$f9PG|YHg6O7_#7$`Tk-+{B1@b?iR&Ogy zXj_Q98qO}NKZL7r)eP*Wm-h@ogUF-ixscbYAv66}@HSwSN0P=lb)@L8s_7;U_CGRd z+HiG;8smO<@I3hHReJyuck-#-DmoP{$~wG~I{xyT37p&$bN|U86^Jl$J$BfpmhEds z>RDbI?71yNY+2*G(HD*`-^HM+d5G3ip45R!{?2h@j~)R3Olj#d#}(H5eu? z$H!51-snA7!~J&She70Cv(N@+pj*m6DHN~|B0%wn?j})J&(-Tj%lh56WrKPB%G~XbiVXwKBJV@*quYAJj5t`OYWD}YA^Vhr|a;hN( z094@JcNO)lpuh$x{Upm_cukFHdw%ydtcb9dKBYe%1~f+mvu78Ii`CI%Qag~to~8%S zi}vl52ny`MKX=Oh@T5Vl2SogUHxJ59`k8ma#ra41u}2l7jfH=c#X8M`v1a8%-(0Jc zzX!di$Xcy|CR@FHDKH9Z^jc7s)CYW6MHr_zI@}(n4lf&bD{!P%5s2aZWlgiDP-M55 z|1irvw%cm!sw43|QS7Bfzb(k2`?7G~nIFU?E4)!$9V=O<4|%e)^~=kjuNCr~0!Z@* zp#_~$dH@el49xmvh-2igH3-^QksvD}%oXa8sS!I1o<_i52e({@c$?h93kj0w?T1lU z2+RA7Qwcv3R zp;QM)AR+)QibS0?l0oo4on`+QVSqLIn20u&8}G8HYe*mAqvjYocjb*C5TZ|w9lMDC zS*~QE$^Rq%SITy;v7~yN9Z^K41Aj)tUa?WgUAvpYCfj5KOxO=j)>)n)gCb41uV*gm3M;2{j_}P>1iji()5^F7YD>cm@ zhRfM=73@Odt5~W@4Q1@Z&F4B+ITlTb1}pc`D@GfmE%tVUh)Qn12~gAC`NKO2W7Z$U#%y&dgGghjN=k3l zd&1_I?j^^YDf+c$qyN6o?l8lHSiI3^v(M-E zuWwG-Mx6J_TBSbxQt@_!YimeXyJ-`X)2q|i!)LL+P~Ja*!?I28FZnuJ-?UKruWyzR z)=NW{yjaHq;0m2<1}v5OPtTfV%5H55Oy@SpH-PG73LmKdeA4aUa*sCY%e)}-bLCk_ zYVuvi=YSgkHKu2IucXe(lsQMkM*RbG)MEL83G8G~@z5~svUb=s>8D{qg@GGf{l%lx_eJ`TKvWmx}K#dXWwNE zvHhj05#O+cLysjW^r+1P1q@YGJhmAOp$`(e$;TXhK)->;Z&ZOB8PXDPT}b6WE5#!7 zI^2Uk2JzbY&Vp$c(v!F%ltP)hn)f`wD^pi^W9TcixfSsO&@jRMVy-z~l7nHCs3be= zy)zr=ASmX7%W{?qq8J49Jlm3fmY&%XsHtlPHFX`H!Ofz(HEaZjvp8cDz+tMj_5m4G4x|mVJqK@jUh=_O<*_ zE|B|vOzf)*uw_lSwvVBMMY;(w11QPc!f)4agDAqC*Rldu#I)8eCcgReaXNRGuQnTO z(~0t2I-zAX`RL_XEwQ4EM;apn8M@=KQX&R6mhe$5{RYhtrrhGJGx(8?ly9rXAjxnq z`;4SEkd<_hKD`4A%V)Zd0ElV*kylV~&?DF15n3x|JfOa0n9gEzIMZl~Q67@|wYB}( zGvh2UTLwt#KnM6A{WNUStycy)%%N@icNA*C7>mVZWqI*hFg25stg^5rE!0($V2-Xv z3o^>)>WLC$F`B#g1ryN2A*+@lgKb`4SjMSbElJq7Tj?*i=-KbV7X4?6&F)t>mVjTB zHk=;RPP@R0LfGbdO*UD()95Y(5Gs!la@dy>-S)qP09lPYyakZeV&35;s`>!n&|0$A z)OQoJxdA^zk)&)ofUJiM{;Fu`AWE(RSZ|%X~PY56C0niq{HT(+%Dq?r;a!JBp#<3 zIn2qkO_}7JW}Y#z9-rn)%ZtGW6V1niI@1JXUq}^b1E8)<;@Z1M^_3wAr<3KY=bj{j zxnc)~;)sDcMJvAH#%c}*(nTe)RsTpFu7bS_s5W?n-8Qtae@E)-8P(etbNqyz2=10?;iSH8V13;5_3eN$b;Pl+Yj- zQS0-`qi;>*c{%6O)_3i`*4_5uJST7d*)krYY&uXGl7^JLROtno;wXaY3%K$Ef?VS@h@h2C|&!5mkI=CnVcBm^wgX3IO zovRJ!u{=7iSOkP6-SZoL;>Hbm0iIOiu@wcV7dqEDHN^hV(`_(6Qa;7}kgm08>Jj#IXjg_wvp11BHuCWPcwrsb~J+bgm zW2L#_75|#%KrSj@f&nDj~6_RY%+^N=*>CA)=#fo=d-IPE(c*!QhQGmDQ2iD^q z_9|U=d~Y#9K_JfTNDFJoiHLoHL{aH7I!P?wILTChRh1jKJ_SP{z@smQy?`@^oTmum zH=pcwwcHw7xqBf?cIU>9w4-DxUX)|BxiLNjrdNGf5E!pmE|{efqCQb=($W!RxZv(C zDY1BSl8mbZo_RZFt(yZ}z-AF94ujS5QNbdmTk56j-0)EYO|JE41J09=3Iq3<-o*!X z>uH=~Iq-;l-<(i37^MUtZ_Uc=QmQ76Q2RcoD(vl;YXhZN3-c;!yFKEgJNrUBAyBsM zVtzxSeJE$NT=RQzic5pfnnAhb90jTXIz%4^z4z2yY0Lf2?elQE_i)&62-PEo5YlkG zLe*0n&&#+;IRTHkY8zP#?pJvXj;r0}O|GB1X1A^vN6W=!|1)MPu&9wjnM_J^-@K)< ziB#t=&i=DU1y(C^fFaW_j*6Xuo=uLc(jpjoa&^atFU48yH4~i3v;?h_+*=L$z8REu zv}y*lSSI~Ro{lFP;Dk01NvY9bz#(YtE%@R1297_b(R#FdO_~EYx4!d*zOYce1MIf~ z%$KdP(;~)OB>eGWm@+M8%9>)Xs8#pIno@<{tQe7qlhx=nmNoxlwpcrg1Vl9)W+qg~ zA@yhVJhBI*5GNl_2OOh*6Az;;zNFfS`dVVdv-qEB%<)RA1oObWE5##IPW`*C+=iPwZx zog(^TltL7ou!7-lHmDXdEyke5w{fA?YrrE~8+wW5rZ1e_Vlt#5w-NDQN=)zOg= zRVPnqRqj>CbU+e|p|RCtA~NKKajAjvP7yK!Y!v|sP-}f4Qkva%guZyjoEO;qOfCv3 zdB|KsvyhnbYr)n_fTCddOE$Uon+ow#aLpI{pn8Qj4EW3aXbeoR)oqACunkq$=m>{| zTc>m6MRI^*3Hj8W^g*uhKSqK&G_hGrPk?szfy+tvs5*F9iSoCHU?#;V1*_aS@DhhQx zJZ$?Qy>%7UC=B=)hVbkV-&nmcuqn(#pBB4zc>3s`s1WGoVmt-8%i$UfVZMNzo89)Z zbmeve30oSI!cDWl00WH-U(Y(Sr=ro`x=>2XyV=r!r!}<{du(8M3Q5k!J8JdFx-fHl zIzP1TTZNCcsMntS-mI~=S>P-TjJsb7 za`P@!Pll;OJ+#AiI*^5c?jZsyxdaozNg**O2Y)m^*C=q>AwZr72C>vn_b`WF@$|(+ z@b}tDswfJ_eogWx#;vK+;nxg?s_;LjPKbsXqwiWab|N!wUqfi~hp#g$cQ^a5mgQpv zUem@a85kGxTO*l|+SJ(Yf8N?R2z{o$4eXW{5CjF0nzsT`NT}9^`xz*T*%I4m#7g6pBm^u<+H4>5ExU%O0n@(C3&qEjf zOSq6NaJLD{Zm;l+hQ4nEG!OjN4r|wX3R6VNtX{r<^ziuFW_g$en*wpWIflYl4B8})%7wtZhoSkV4pakY_T|7I6os60WjM&qPTcXofhbrJp5F%Ez9T( z_emW!WbUk_Fkn2m&paR+goRh%N#ZSJhB}d;WHT6cE5(H2OgtVx@t`!s-BNZ%0YrW# z3OoZ-ZgR8slilFZRTCavY_q5}QU8*fWabnuGl5^izaBP8RA#T}|7JVhXjPC}53wX$ zv7EUO7~NM*h;n<-u`k$5f)FVa|8?2K ztZ~`IJa)_C%UAOlcux1A^Vf;Y= zmiTyM$1J6>TO^0cSHx$z?NS?T1+K5gX`WsUi09JodBWWVTSeu>gSrCLy4Ne&MgI>*9hV$@7ZVb~Q3v`J~3@-LXG+guK zRSytOqwayjxF8d(9pxjutu`(wrNI4w$ql8MNP5hBQc@y=`wY6^$4XUM3V1X>AFnRo z`QzTaWkZ&Y8d}XI8}O1__zQNsKK;M69(k4EE2i}pFLW&QabLOU5FL+LT5Ef%Qk-|p zmTytnzx#Aa4H^HXAdDQJ<-RV{@zaoYf&%k=gsr$ULJ6I|(m66b$cRJZR z3UVV+oHRUfN7ENp6_l0R!q7cm-p#evRT?v35$$n#3{>>5b(T6(#uDci^+%*|_i+ah zYE1txOXt6rI~)H5nwe9MDlvYx21-y@ZM*9-7Zc`LX%1Gdor_V>WchJa9%$jY?r;#* zVm4Lj_O+9#vUP6KD3C=S8hB&Z^nw_z>zL1Af{8UaUt<3q=>#a;={J1=%L=gDJPz(7 zv-rKW{|RJQ>jTC6tz|mAW0n%$M|bP^ufy>J3-YFPQlQqA51XdkM4LX> znIxlkc(^6fQ9mkSeN7kMIIkm}g6;0)opqskoUw-liS{pU}qE(o<_ThGZu>KD=R?KJnpNmX9+T8t?cqNGvM(NNT= zP>sTy#F@fc7V;QbontKzYpEypZ{){4s13?n^dhXP&Wd4`;LwM?9*Q?AhOfls6G3km zY`M>RAyeUAUHYJ*@P+Y=wpa zzWq5*@ZAdfL z?TjgVIra7E9tNL}6}qq(JR<5N9mH_7_R z$4g!yRL%%~BUA)d`b$ywP_{R*juLD9BDVuJrXHlNQ^B2umD1ik-z1a5>93s|3ZjX} z+Ttsi3rESS0)iJMz-&vuX{8-VI`Uu5Fz#+B1s3(iW$<^|Fj%@@e8GtRiC@{VS9?ya zNr0RBe#QEmEG-G})%lf#9cu~)%tc(V)wslfEJ^23qL5EA_|G`BghV(a>8^FC)=#aI zlE8n=p(7#16d8KDlrqFR;a(;fnm8(-Z4}l3x{{z5D2|gTS{GaGzv-*%qU>iTH6~G; zbKs_KblLq9X{{g$JNK*SX-8n{T%nn~*Oe5YqK4InjnZ6CbNw&tZ{aIQe7hIK@mME& zS*jgv=@Egf9}lw%Pn)n;brt7XnQe_l~{YkJgcYpE*4 zS@t*D=sd*L8gDe4@Xnd~xSvG4hXVd6*LvFEjdpi7n{i+r)1nT8f$N3gx!k08Lj3bT zpHi+9VNsK(P-o&h9DI#)CR{%Wkb`=K!df&r|51LsL@$8+s$5|a3S(BxZLJegIPG}( ztX0El`7-l5BV2RQoG{mRI2E)lKIZ+M#$GGmC+?V zMuEa}wLpsdngzVE@QWBzZ+yzPN@s~$YqR~U%1MQwh~!@r2RCoIU&SgDvPQVr%o#mG zKAGRY*sCkR3&T;X^CN5YS2e3fPJD>` z6G-bxR=p2O17ZwX3X*TGC^4d*t50!cm1!^N`j?@2=3zYDA<1xT3*Lv+_>Q3R?=jWP-LE|O^8(vr3aAAI zAsxpm4oebkBCSLfe(%AqeW*rG6KvYy$kO52YIho` z-hlQP`|8Z6*R%xKSGAGf5Pk~le!j->$6lGVCBr#76WPfxxZr}e5{g}|af7uf6Danq z5sE!)(osX}>=C8NbcwQKs?d3`!-puP*83GQ-^>A&HkPL;kVN6Uduf)<{H&^Ye7M!M zYHUGDAOyAOScuUaNu8_t#3_7yx1B3@lQG-B50&>WCjtE;pnCLL*|Ar_Qd>yw?Lqu} z#u9Wpys!{Ho7durzhsTW$GMT&>TcuE zIyY^A#@uLub%|+PPj(5An|vJYFgxE^GY-Ly977k3%_bVC>+_@pp{OC9LVd;cgYqMC z^GS9khtOt3``a!bHaopRm%&btzQwYXI)>!MosxsoJx%@1W67g`M4t)oBr>O?Qhzapd}P{THG(yS}4c#M^_p4Y6xm$KZ@Ge z2cWr}$U6HdCCHtwLkEI#;@vbu#Bz%*xL?-{I=leZDWf8h`jzWs5(0x(A*NAsBYiO2 zzTsl2lTIT3MfY*(3cu$THo-38Nx`NI0-d(o!$KV!&-Nuy<9E zv{9N7SOz>M-nHd$D1nEZIG(XO#n^SH?iE>$-euRapVoKscgrY`&uQz<*rGv(m-4`J zDM>FxHmAfnRMvgoE-$xjS&0|8HO0wn3NdrNWf+*OmM%4Towbish76Ged)*yA!l1B1 z1D*`brvBCQA6wJbuN!4)&n*5wqi388q|fyeF1g9U6S z?5JK1B@ge-$|ld))ym>2?7w(kE&&wJ`@&kxP6wyfYO+rN3k8-ro~(J-0$wLHl*8J? zrDyXPZNWvj8#tcxc_V%{?A&hcp#NNf6?-I>*v>j%^OCCaQnHGIXc8+W1bSq5j?$o} z4+ek{));H^cu04IFag+>(Hes~PdJGYcJ6!%>~@4@s7smEk2htRZpuV_D!%ZA1a)&D z*`$GUyK+5yr>Fh}i5N7?=Eb?^Xmn#(1y(!fzmj_APq6Q~4`{l%yyNaQuOiOV(OGt+ z^*ish#^OqD>GxVcP>_(1*u(79b6jhhjxB}fT{lf9LlG4^d;h&IL+IcwpJn=X2dw}I z@Xq(8gk~w-)nGQjuLLn~y!`PuE4)kENt^=nTHhoewb+;@Y->oGA8+)3|I@e2m>8$=>d4^a zB=tXCQU8X}n}SfEnKP*V5Ms79fbU@$aKR{00A_kvf@33H={le|a&y9WXvA6P?khWH zwc^AI*yuU;lISo0GxBdg)jNk#&- zGR1f}k&CQ>&(O$$yJL4|W7Z_pD&(qCHM|&WkZ3yvWs?f^^4j}kY&NNZsyJZd0G)>V zXU-GQyAR&qz@@&hiUYbkwbkd8%$xV_wwX`%f!I#G&;YZPodRH%ny))aHBm2RgExjr zXdSz=SVDD7ZweNw035%w2l>83?&f6@P<@h}yeo+zWSo}|C=^H!|8(sqq$P|fF{Cd; zK41mJKj9LQ!uf~OU4Kp$&ECu216MnAZwvl4d+=e3U+A|&wJ>Xv|5CD9ZXzYtda3KI zKl!aLF?C`X)sVdI=S{6Ivo0TpafZX(-*dbp=O5hW*tI@*>XF-(mrmX*EHV-C<@7J1 zDHrF}oNN@a58YC-4+3N1Y)ORLG-v5ANvlFRnPAv#Y*7dxY7mnXDQ^ItR{4Et1VXZ{5I`&=f@KBO@tu1ZGPtTL9>S^r}etje=e~$ z(E+P};0s&*-ntwI26TDqi1yU*kd+*%V+8`j2yU&Z_52EvSy8FMCB>$WcisCrpX-Gt z2kAHgs<>$o4PZ>MK5Q?s+MTece8oUPl$K)^$-w@?lf??J{l>+6Mt z55+rRDe*THWY_UsK%%-qkeB@RH)H(5Yu(F*9f9B-1kT`fE@D(s1m44?_L&x!`Y^jN z>)&xjn`J!sD9u7p{r^{5(ZIIz>c906LHB=np-kU_Ccm{1FAKZu|D}cC!Nb&dlM_m4 zw|CW{edhu zR0we20Rh5O3blROrI{%*lrx1tGG|?EvKH;wZUF~DF9-f{j}cfdi}3U@ZG*QKLJXCF zq;Zrwzlze2W+W@}+@D0xJ5J>UpG?5K7B)_-N_A$5j*kEkNv){T_q}{fQys3D^p^n{@@SM0mSN& zC;5|M_BMfHHoiSobW!<7of(O&%m8nGIz%>a-X(nKE=rED-gI%=D*P4|UM*bfLsXv1 zSu$R8gpyUb54B_6__ZPhem)r$C`7-|GzKloQ|q$1)a64RwL|6gEGaz7pLtfyTEquT zihK(OFS-u_b1j97AWMz>lb`C(BmQUy|O1?>xb2Pk(L1?%Y089o? zz1BWFNVIwWgNitbe2uN6zkX07W;?9uB%x0$n70-=8|-Fc|7IZP&ewg+A#%# zNH`Fa&@)I9yWoM5^C5Msm&)z6>!`tjaAD&T60CIy=P1CeV zGm$4_T?bVHN1Uzh-+y^-83F#V6D7W6{g`~GEiFlP7}J`cm9~qeR;kLuP0oScP0m4W zveMXq!AMn5YgL`9~+Xp?3g3a=^HQ_!QS(){3%!Aa*2jgT)Gw)0ITB_Q00q84M-$M z#GRS*S*skTz%V?xE~9gS;oghV>c4_K?b<)crpPAXi98LHD&0=$G0|NT?>R}|?zY|# zln|?2xZ>xy59{fbd)L%VNhZSa1zj2iuqCi&BN;*}u_x#(nP8yOiOA^Gyj7vfc4PnQ z0kip%l)PQl=H_Ub;tBqUAm-P*_ z8~Zk(jYHy8VIH@+`23B=Fk@HhigqJUBPA95AtN-NpWq`$h`T^Lu@gh?vh|#u^4v~M zM!nDRR!{Fv#*5H{1(`q&>cXrmrDx{CYS+EXFG??k{t7W{@4|=RBJZ7WxN#!cI*?CN zD7G6AMZ1`H8uC$SuW+iLvnMD9xcjn*J?Ky>y&a?A^|#8^sNZ7n%GXT5yJ>ZATc#fI=Au21t}W2E^&i$lp?qSZPL6N*=ZbUbxh zHOfTlR4VB9E=_N{2sUnU6fE@jrN7Ea=sc+)_A1k*NoHJbW zfjk98r*V(+j1G)?HLv5P^e{*Yp=L4N^0=OB0j{U=CnZJJ*T+$DC_G@ZY9nC3WG+N* z-0sR=aZC=n-n}E}dd5AUF47=R-_tdr(LhcqpeVhu$sOm^szX)HAMuUpogi#n{h?li zVa%J(sZ6}-le14~i=7OMK4i9FQ;|%wG+hi?YOAI#+#kwE9pB=s#P-)sr#+7lffR-I z`;<*h`mz)~q*1wO6-6v|Wlf*M@fx{zYvzo~h4SVFD^IrOC^Fq1^5cIJo+&)lVKGOM z@MceUfjET|YKz$6FhZ8{3>yqIR965`zI9*pi)P{-GnmrL6p$jbfS!$7?C z-k3pN_^M$?KGnAba2$G-NEy-I_X@X;n(SfHqs`cWu#focK~3>}n@-8$x$mdtpU%CT zNN>NbcoFmAUarSpepcG(tiSVNUI79FMq~82okaizpAZ9f_%UHUep`>QvS$Vq2 znc62~q+Y|sIu&27bkjl?sNwk^_$;yu*J>nk9JN)o)Z6Dy4Lq`5rP~8i7fRA(<1JlV zq3-??<|9Y55_7NugNMJ!$cdT1ob|B$QPd=y+s3ELH?v~r+#a+wlu~qOX9enF9vd03 z!>y+dm$s|6zVHvRH=EeGf=vp4&W*1so@S@`^gVXeV1yF;&n@5mOo83w&=jYjXLKwd zsvdV8+7NUCN#~UVGnG#mZH??SEVC_?gWX?6=}GH$PaiIeAwQVknUQg75jX#)DA*-o zM36k0CECQ>Ce8bKXN8I$YL<$MRGk+kU4s6285LhuBGi7ebzd%@l0!BATLgLt|Wl}B2 zGJX6_EJI)qO&TDe)*|eWu`5CoW#eSV!HqzY4x`oMqaN4|nhp+oaYsqw3-X3-5b2WI zpQgIQ&!)c}aWAlje^dGI{-*L@UAuI5DaZ0A=xk~N!%*P|&y zn_b0egT>T3FM(VJ7Tdku^P5D}43c_(j+@l=YbyE+pJes>YvErC9AXA>WQo_iTp5an zy0J;uKa})We>ob9NjtXRQX00AF+=m8CtqIr!&BJdW*a?%9$G@};_V;otsu7M00&!{ z@f_bBr;qQ#Y^X2gKDc1O+5gqb;CczM9SCwBE<1cb$U~LJRnynZCIPpy69_Nc`k`V! z4SK-cukG)0>e-0;07k;*mxX{lu{(_;tOBINs{21Dr@i*|aNY=I1~%7h;=spyC+dZZ z;hJtHFTPXS<(bw#f1EOTO&H-5cq)8d>HQ8h1#v#e1VYeMjiNORR0f7-*2U^p2b+}3 zQzA=|fiH&N7fcTJ1%b?uB5#w>9y2=)}-o zt}$_1_|RCZ!JWwem>)WD?)xEq@exGC7-9=8`=*{#v|ha{a8$#De`-wdgJjS9bLq9B zBt*8bZ)pz5cUbwB*unlv=!lm6WxmJs7U6V65?;WM!HJj!Se6!fpDgj4%bQ_oE?dIj zX|z=EXDgKl=cU`yyaN#!Gj3m{snScgVp6xxi%l-F%2`dbtG-&FO;%iDM8*|+m>N?e zSO%*c>|2`^Co$hrlC+y>GJu;WbA{&Dr!;K@X09!?(v*50YV1|1-e2W+9I6xsD$}5x zwsUP>iK2oRkXmSp&DtsU%ZtwNkEIEG z=80^Vu}4L-_lbkZwyA`7qA42MHW%pIZgE^5-d9|IlAs2=_1!CryKTSMab}0+ZgM}w zSN6sA72fs^ma|2tmv{H(6&>MRn^K}sSHvQ+1quEva&;)_x?>yaghX5)ad>{E`!+w1 z>)UTU9ER8ebb>-H5KFD*@wcafF*E3}8z(7*8Bk0>{N_09fwV|w^qG0b1hukv4&fa^ zcK7q$oZG?FhZp#7G*X@;bvAd(6PSA)o$P9MzcSlVjYnyjW~2u0nXZ;B5-jv>t1X9IE2J}ph&17u$qPV7=!MtMFPBZ`ro9r~=Kd;33$+Ww z5TbSonun(Ew|SbD4Ji&L?a}z)3v7joL!3pTLdT=L_cdia7oJ-0vxn?to@6^~j^5Ec z!<{LtVp5W{z_92Q)_s)=AF%fB?t{;@X(f7nTujS5GQNcz+mn7tDBLNT9KnhZGTiMT z>E(9THK8uP>DO_zd{ITc{#oRctb+4ETsyk<>HE@6I-&P(cD6_}iPp=y^I~z-jN-dj zX~3uRd)ICRwlrYze5lwnBs%ykLLUB%e68u|2N|BB-`v?k94bHQ5nn?sS^dv3YsNx6 z%rKcO)%8J-PoWzPxkaNtPk+3-*VcuwRQVbPlyauBHJax*3@drlM#Zxi{;JfyLia)R zi8Y;UOr4d=irP@kh$dd&6XrwUM+_=Qn^etB%OqlhuWrmJJE$L`_oGg^IBu>}KvMTR zT)C7;R^CawOO=y?o-Fj4+u#}OjZlr(A4mOSq_v>Km_>zh@{*k+$}HLhXw)=_7-`?w z+F$hfHS`X$KXYn-e-ChD6%5?Fx@CLWksx4h1LQBUR4Pp9qK?!Cozv4%=`jEvRDUJ* zxBVL+IBHLxoHNU@tX;RTa?4@zYDc{Gx$Eth0plGY{K_qfC)k$;TaUZ9++EjWMQQPz zlvwSYEH=r`nw!|RanA~W=n0E#7AYDW77KYI_L2|1#3fjW2muKl|ld0$%*&U zA)Vppf9@-uhR%f{JS28!9>nof)D=~eXH4Yb+clAivN{>dm7iPSRW9*9v{&2eP*y_S z->vs+k~5>4evC*z?Qhh;AM}8IX|wc}T;^K{w|(ZJVObJC)Gl$iG_Bx>*Y{A-WN&5a z`a;Xojpk?{41Jz|F!i_vIZUxqO@SnN0Id>*%s8w{)Pyz1%;>>So5Swl7k7+_GA6R1 z5a@=D;8(yG1rYr-n72tR1iwiW*dYQ7QFnkNZ1++KxRk{>9Hh1h%PbylxyQNQ5pRtjF`|Sr8 z&97z>ST!dXS)LDKTy_B0xLaj+HAR>tt4KCTR^QuPMV>ez7b%x?tKVgMw?WQ1NlUWf zy+rc@hPKVrn&hLA6D9IoGSm($^J^PR9Ie}H&`4jq!H`uYm z6W0|7^FQ(47itr;T**aDc6EZ@f4QjlwDlv7*v`s)ncTy%WoJ_TYWrByn)uIy6$(p`kMNto zo;9eGdmo9Z)uXMfP|GaJxE>jLF?bGgYo?(4$g^;HSNA%5 z0g1=}b=K;7`*n+QybTaNL@Xz-yV|bN**ApVNl2TDPBt+>^u)skk&`fE{889L(_L+- z%QtH~Y=m(QiN2wxYbMuV=*gP<%f(w;St605Zz1if;2+-ODZF=WhBz<8FrIU`#S|3p z)cRg;j9mI$9r3=|)a~)~1JaJ#; zVW~ly%&JRlFgnJHy-rbfGKgHXc$XgC@2r`n7~lUD`_M$Q^xUbM$$emtp2IS6s*GjI z$r}xep;WpQZuex8yHSpB3@N*~{4(2rTdn3Ao8w|i*VY)Cz56?&nAL{G=3rEM4@q+L zlNKG2R9-&IX*)_dnfTyc7X0Cr&gZkcxmyHOx=#;2m53bMi;Nl~&j$DUuNlr(SbY4Z zuDZ?!7O&IOmwaV!86Q;$3oJUSuh+WbO1{s*W+wY)1~O=vH`N7lNeX*M}z zXBF1`cvjMa8cTQO0f04{2hebCqnGY3X`4W3`weZo`I`Zaf><@*9OD$4M;9LlVl7iu zP}|L9pwS-*tyu5!atf14A=mObb><{~f?w&O9_IJxC#p{Fla}KpS*~Xy;jxjWU z7iI7rv3A&Af@mh>lFbe|4-5o}A7;6k6vTwrWIH(#^hj%gaS;kW9v5(q6-F^Sh%h7+ zHe@!P=`*Vv#BwD$c!MTBB-n;PH{&aKHImJf<5}e@d$*a1$1YMKk+5XBs!10%9Yws( z8FxvdJgF4)>Q#5|{uJ(4-T`hBL*!m@iw|(l$tul?(~gkd`V#@5bTZY{V^x>G7^hky zLk9`wGSB%2oQ*@${4g3>#77A`oP*l*|+=A0ZeDqt`ywv^3Gg)ze+Dfk9L7s@G z4rBaE_f~sdzfUJT>*+VMN8~{EB;o+tz2mFPIq-+7Nbm-#uohoUo_Uq-bSLQPAZE#LUC4?s(W0yl?ta@X-_ z-@j>=M5Tb;hVT(woa8>c7>r+^6d_;qY5#n`i*kpWe0bn zd~M=8I(DYS=H8Neqld600R6Cq?5wfg7W4i&-^|1TJTw{cJ=1{vfm~$&SEK71qI6~F z^vW;X!Mt4`GU?#!u{ZzU@XD>&FIKOHuWzTPcm;Qx6ePPI40gME%rwO_<93f-er3zd z|7>{0w46XyNU%FgO}<^{fs z2gM=QrmR9-MI61C{Z{)8sN_iTOl}RbdQCAAHMtYzvPOa^Y)_HbL1Os!BBlIRyY;QiRfxeayb0M@lC;HSZ+ z@)3iT_Wjep;gMjF;hSv<8^s^H{R3JMbBvu;1(nm037MYf^IkU|{w4>~dux+zq%Fe`j)siaI9XHK z%*@Q8L^_$OC+~-z`&k(fo9hU!08tw(<_9fjvnkN5t3~jmN>%cv(AzTr5rb<94g9if zu$TfR#5g(vJn49q!h4ipP>p{sd!x(*#HjA~qt*qRJ zvEbsSonD9RD)sGz;oli=b#AhgM0|qXa|hT)ES6m}&+--MmR+eotI1E)-$`D%Luxc^ zXPnA6x@sBgE%152Z^UdDY_Zpsd-PyHRDdkB#dB|)&wg07tSPcH zy9i8BxO-oTr@nSfCebZlfN9S<;nb4;Z>(hI`kVIn{+8e__jp)dEaNhc+K0vnMOxHN za{XdEl=M*;*OBnJ%0y6fi9Ow)&94$40W@Ux(jbvN9L|A<71n>JgIYv#{pjole?d`5 z>Pt@@4p$?gx)tFr3y8Y-UQ5$KePf@S;w*$~gz^Cj29 zGcGb{6XWH^>1|`fw!seSgmgug99D2u0WIW#W%Gl#4zESnjDVb=x%LUk{1EqFjvnWU zP6a8EG+q%96&*E+W(p6k+HlA3q3+GqBKiB_h!?=2{jNrfm-?nsmL((Oy4Jx)HV7zm z55e1}eZ8Md*N9?6;?>&E&86ktH_ybRw$r~W7ti&Tgxgbw75k^rxJa7d%9x;%+im+T z@ApoJCYn?=2zsiMj`-%zQfyAaHxF4z??EXSqS^E zh$5L9?$x?RXcy1?Va3T$lKEzvi^N!Tpqu9_yPW8=vZ{db7DK?I!yRxrP9Asr(0JuR zu18@44)Gcxx@1{{OK^XZ#U6~tshQNBoGf|PXEoJw29@WX^~5W^+Sf7s43%{3t}809wz02IObvJ9 z=vP~Gcp(y9rCXyR$+xIOU~@>4&hwzrz9B63G;JlB@S=ErT(`HWM9=xeT9AWQW88jN zy0}8cM| zg=GaGAC^%d@Q7l@g{x=AxHn4v-zRZKpMB)S9xC6+=)VWRb;%cY_EE zAzSu3P|f~o$pN5T06ElaEWo4~N%okMVN5=rCK?%Qie6Rb-R8i5>F;HdA)LGE8M=LJH9d-Gg%gz8=t+rBa z>s>5o+5DVcE5txTUd>JFK_VBI*s2TCUh{RzhOmTAO0f%LJ0()ftx`dQz*I{iRZUNV z(Z)E5Y{Z`5BFA=5P#H78z{^fT?li=|m?KkxN#GuTF$~$a>7W{*T>uJnPZ(ufS42wtKonvbw)32J0J3aVwr?l3`cC zIWq6Om#&rP$<*~G94kO%@S8piYw8HHF(NT-9~cVR-pwKu7nXg>IqsmVRX)9XEEUueWB#MWOPn%TFX9VmW ztW)d!p+tGA$E7T)u8bU&!j9==)qRBs$v@P92g7zDnT+rJT-?J=6J8qwvXT*yBH!gN zn%D+kres=*>;_&rwO^KZz`Xy;?lhZU)}yW6K_OL$A>j{^%Mw5PB_+?Qb9CU_0d+o* zERUvhgz&^@j^gZZIioOct<4EL3gdRO{5k|NC({Uh^~H&7mY!Rjiq!nv=RdseR4;=L zJD_B?1J;nNoi}U9PYk!ao;_xY@3FqZ*s(MXJLD-`bQ|0YS+`j2{G+YVqlbXOtOvg} z8#^mltxk$|pj*}t7o%WU`9qplNp9UryXT8SG-Y%A)3U0nAQ2}k;#0x6M81L*Wh0Wr z;x_|%<`?C-bAfp(=Gsg14Yz<`_Z#_I2NbC*QWpulIXQImlEi17eys4vzVrgJa-@=)?@PK|uIS`ysl zWBeeG(@4zfituc8TS<^x$sdKKFH^f{6bp~gxhedA9h@sp=DAkju_ipIIG9}A4W4L!#LlDTWStK8rUp~LT#0+QWxkNniEgcMoK zC5-{m9+lW!1X;a6+*6w}UDU)^&)G#*&-Xl?x!wsAt%*_|-MU&Ev2;Ci5oxD@ zt0-Q7to1e+z$VW9^uB)wwHf{C{(1r{N9foQn#R1@<+HLipYTgmA!3vK2lCJ{n%cnqn%yiRrA&xS1vSrN znl4w?rA>PO3b7=E`a(}H6WNc$R=&|YF3_gf#DlL}#P)NG-KVy&l^^F)}o2xaG;~(UQ!*J9g+_9@+THgy9RHS7kJP z%gafe;rIM=k$cLy@^ER-ghk%?%?wro0pHGItfBOwem-pc%0`O}+T9}(v5O49%66xY zqC>@1XOPr(W|>9GX~7c!I&`l~pwTrYy|Gs)iD~gE{Ma8elfSo8h~pEu)=Wj*V%~ux zSGu`+vRpinm!~3jP^_7Ps9s0+-w}TOeLGhQ<%vI5nD!}#0 z0@)8`2i~k^SyD;S`qVOsK3F#WkTX!6x%@a-kohuTDku~u{E=}rmX z>u;6zFGh%WMwGlSsYYs9XC?8h9s(*6O7pC0A+^D`2-eHuNIH)&s@Vs%=gl@GGRAWb zGf3F-z{^ADt#i)+iJ4jn0!LTCJfKT9d|WBB#&>|K z>!C`IKs4P}oW;w&l-&u$8612?pbMJ#d8X?SHGXD^p?kF+aWIQ>g?-O~I4!^bu%gbf z&h%x%R^8&x*&k>#4qiTyOw~K&nVGj(&xCZY8UK3Sw?4ALa&JkvEEcBT7S5VK5S!9_SiXj(R3OFc_qCzrrJ_40Knvw zoU~_;L81<2orDz20Wu^#pn@Y}X`pP9jhm`+y6Ocy`>;Ax$f-{;wOnv8c}!^ky$Oqb zH*2Zm8?iXAVrw$5grso2m1*9&4Vs<2c?oiR`|F=R8I-kq2TThN>&7A{9qr{EE8bRa zwktn)`%C`b9dDtUH}zOcLh^n_VB>8iI@EA){AbD|~^V#||`CJS$K{u(pswGG|HT^KkS-Fc6XS}nid$LJK zIb9)rzFZ6#uQs^(fc{OaE~iJ25tAA*!sA}i3#0s(#rhq<&(Mz;LU6+f5mXismcBnx z(ufEtEl|eEv!sh_8DN^BTpUs(D!v7@=%v@Z*Q*^gGm(~ z8blPp`J3dIJNV&=O6><;c%Oka_|5D8Kxh9h75Fdv>YJ*rK(n@+Iqemy`TL&*byq;_ z6tIr|DUX#{QBHpH0X`zYW`0hFx1#E^J{idzqflCFE4immfg1F7eg8d)?XAw2S@}fo@v{)B&Rw_=vpA34TiOpTpINj5V+(KVncm4k4ybFT6JPt@{on zv(|HhWV1}w-Om2NA%6-?PnLWw08^85!$7-C+7e}6G}e(xsy`8@3E0WjbI>Z-w|Nb_ zgL)gP>pMMwpsg<-G7rKIGTuG%sJU;!KyI*>n7G>FUh_G?8rDQBBeuyH9pFw6@rP~g zZHRv!ySQFHz&Ti0_n9ocnU&YL0sh?h4YyY|AnlCt^gfaq8$iU33rSy@JvPm@II3uO z=Zi2Jw|&8R_M7vCoA9Hy(sAOFib{8`{F#iH3-V4iO4K;Yy;l2+1%ZYufKN`~SjXAg zjkBC*$*F0dA0jH?*Lh;9MR|s2uB{w49Ls^h(Y!Rf#=R#KUH*tW$Dc=YY`_eXX#$GV z8tPH=7LPWqvDT5~v$a|8}wkMLSo#B)&f5yt(xUd@8-?Th^|AVLup;i}vBC zDH|opilXRqvh_JC zx<(wu%jMS_5sn4xopIpU1=-yqU=}Hc)XZB@vKWaqY3V?%ORBX!Izk5u?G#DZhi`_F ze8Q;L+#kq<<72YFA2Ua{#t9T5iO&n6#%@HFScIm_Mb_;xO-xhs52qr@_#En0A#_2W zAZJ>#@gpsE9jR^Ir+X|XVuONQhL;09bDiF&f;jrI#iM;Ie?02vo!XOIlRe__3K;@T z0n^6C{)Wrq*0~&t2bU2rOEvn9pRw@6@od?eTvoA+?P{uDnyeltc6urNWa???v8^86 zTkX&I`Zl=ZwbU7$6O2ytu+v{oiy$#!%)XEcoQ_L5LwOu9*%368u{*)KH;4Oh2NU9x z7cbs5P#77I^;JWOL)^Q2@vD){sGnCK()JFC8<^;%aB1xmE`QL^nJM3|(dM9_ zFS^(B@YURLP1#oXcTHY=SO|xGgD#_0Dp4xsOud@3U{r8MZjbZ_kq# z{nxthQ=8o~lZ1z1Q*trK*!G9sFXkD|3JJVyLp?F0A=YE5ZPIgAO`83&*!!1el7?ga zT1tP;3}UWq#Y1Wnoihz$cew4S8bj?%gbl~p_L9QqfAy28dKV*A2CIs#&753|!I>bO z7+ra?`Ucq=J!d`s^(O zjG+q({oCp?3p2isPIQ43<+6s7kJ+*X;rY6%~Itjz4$f&sGGAb; zd(Pg|T7hqww8M&gmr|czJ%5%8}MCF&%b^RLNDl^Qfrc6U!w@pr4mnis^x4sKB==B266^6<@~CCFng65yUW%>Lq@b8QFp-1{zPs_S!Q-rrf` zDH#gGAjgNh!U5VE$Bxl`(^zXaOk&vf2s_PWc;vlXP`8l?^XIbCFWOs>@P2mM{<1B1 zpC|b26u)%Io4*A3oN^!)(r1xqO>jKJ-Mp=br~{g>v6hUl|7MB5^eSQYh$HjmI4GVkGUHOyl^NSMgQvIb;H{{3oweaU)ldC?WM`P)hVYudN zQ^FQ&dTY2(+@Fb~6(gOmb$H56!dLTnh1G0+luc@wuN^?`cJg9DTMfAv`~M=s2R*S= zr)rPCe$P?VWON?*Gq0&tkGK0$i2Bs(UO$P3_M~RJ9Vh)8Qd>z}S*Q6uXU~tm+k7QP znp#^X7XX9(F@B->uf;w?>K)(tj{dUwbyp7*DIH9#WSl1~%*!=&l0U+X^TowMTW*rF zdA^HAE}~I#kCceT2@-vJ0Q0$IYH2F?e(=BB_QQreNYE~@^0~=6qRvrP>A(w*XQ+yB z5V1q=ZF>@ZPPz17u{^XF-|w8hu6Xv02T)s5U46J$JADu3XG>B)y&~t!cmZpXoUz>J z3g(?Qq1}~BoHJB$TFxre4n~zCQBlPMto1I~=+^7>!*XRKQyUChZ{F5n(u5D?vP9h% zi5OqH)^06Fre_|xAyH54Dj*2hpaHTz=mUIR{Zi}7fBrl@G(KHM2lvU50-tRp;Xi@^ z6d#UynYESuUyB5yZJ2{RQQ1<50+bHRPm`;VQJ?0*Q2$90fTeQD+ZdJGOaDhOr4aaU zg@EPM+SFLhQ`@cYQ!bi3UpARxGj(J#(BC-g#0Q{yXUhG6|NliFQ_4**`Zb}#$hC{T z%|KO~MH9qSsP7x-&H3_OL=Z00q>s6qF9l{_yoBV;riDz;QZn~BjZ2PXkiPM5e!A8G z$Ls$#U++bhY2~dqFb{VgD-npB|NQgegL$_%LsOm*9qHaNPS-O?cBzicU~&ifSjN zR832KyDQ{DbeD}{@l_u$_U9j?2q)v;JSAt0-Hj8C0z6YfY~2xW%IT=ct-CM35^#^JnhRv7$8TU4@plzY0TmF7M%UTCb{W!(p6|_ znpdC;2*&_EewHo#)TiM3)Z6ymAGS>hjFu~z=6X;8Y0Kpywcx{~w@Igzz0>FC-+?5|Yhd0^WXPJAKtpYFCXsN(bl)2@w z`>ZKu@0pX=jp}jjLPdsmE~1x@0B3G+r3FJH*fPK^23CV~79abg`>_v|Z&X7-vG=FT zJU%=0`IKIG3)8%PImH~7^E|2%@ok2t><#Vli z*NElUKCf#E;G7IzjUcyw^a|XgaHb-HnfE;LmTTXiAD$PaP35O8Zb{7zv7r`vv8Ec~ zsr}_OAw#9>P7aNb68S=2+xV>cS$CTV_q}XSp>d}tSAJ3g1SN_D6)Yw>@D|AYPBLY= z(uSJBmlE(2WzkOQbZy~!pmEAnt`Z<<2+g(D4}pc#l$;oHG>z;2ndKKvRO@QKwtx0n z^zM668xM?DG#p%Q{#Ob*7HgP>Gu+=m|58QHXx^wIRc1HQRR!)VBt956oCP*Yt@Lf5 z(9r$TU!`M3_lMcyur5oRQRIiQdWJC=4K@+GO}E!;m&h~w*mifyA1|(szs2a~Z(mtk zNa{X2NM4M;R@?6e)ODqoVF!ueYY~xlw8YzeP#TNr6l>@##wgQ&UND{0_mp74_^lcRI)Ep}t)epN{|& zgO87XHhMhL~Easg7l@#`;+vL;3Oo8_vpj+h?H@z8QAV;;1*; za*aXSC))9kek(I8o5@|~?dmBQ+WAp3iIHiPN&>`ty|ri{U^s%zZ)9Z0@R_rJOxvXq zqUc_3-Jqmyo(%TX>Mzy}yfj1DmwTHaD|Bvv=3?na$YxZE5}_%KtY0~j_Ypl|m&TJq zEcet@^UJCbUx(@Gwy=DxF4)@w<_)ra* z-%d7}1=b^44U_IO!wYsxNH7`P(y7~vH=jm}xUpXeiF8BQALu`F*KYcFib#z+{(&wmenM~UqYKDC z=?R4w-|c4FuiWS`lF|QDhhe+>xPDONd-He^2VW%=aSO{$%XP`S(I23muNioUh2yUy zKKCCwX-%yhb>)S`YgoB#i-|3nEOJVIPYJf7uBHy0n{2 zZGNwN#qQ?8Rv^g?*Dh6HFfBLF+3x_{F)v99`}OaBIru^Afp#$2$yz+8a{|kqNBm7d zd!qYMED>HG(J zs0i`U{o|$=Fx9C4f@*afl`{JirpW4BkM?H(-4NJojS}Q>Y>8CM`6w;MeSh8Oll+iy zryFM_t^jkrJ(6DM0@+Hod{+r-k9>dDXolhT0^k}#{v1+ZIN`fc& za*J*BPJ(Vr@7cP8l(0^mOeC{|d*3hmmqx-rz=H1BIM=(TXPGUEFpB+2`Otc~E^{fr z5^H^-mzvHAuiZbJGY44{id~;-@|@1?XgJ^|ZJwWG=P&KK*gDdsdZcZ+k1$s1-R%`1 z4p?x_bH=XU*;_%Bde+X=pY675G+lz$jkBVS)w@%#F7~?H`EH)Wx__{IXcR0Vd9!oe?PG+dGWUP0I|`1LqD1^QE+~ik_^dXPljwVP zHHRaQmU+%Hj_(PdpQbN|l}*%Rpa8O05ZQalmC}nhArqoe#x6}y{Nt@~!ji2OIEI)h z>p~%1v6B(+mvQ~)zt~YE;1R;0#*Jj@u*MTy&>&SkZ)RDLDc{T&VG5hqe8rW6imL57FYh3r}kVpk^rn{_L}h)dU> zD{^ME5d{qc)u7ie*pSw!oQU>yKw-P%&!wotQuAoLDO7QK{ahYsP~ET_d~});%Mmo0 z_lY@;VS<=$gypf9+K^@~tnV9&<{dD0A8bb~TRJ2~U-(>03~2USODJ!A+9R!sng>_naeO0hTSM}`}UmD%X6I?Ax39Yorwymv-#@~GGf@W;DhggzSmZ@MaM~} zGX*&(M6qI`RV!MP9O5+wj^&Y{a8f3m7)_LN4p-k|D+1>`PJO!3s5D!JMDBExZHuzG*_@%0rSb>#0!)53M@c8oMjSSU|a8t zZ544wP)%5Gcqzzn6F4?}*Yk#~JsbBFNf7V|Pnoh_N{YX9En5Lb1t`aL%;vMWfq39U z1A1E!$jKg! zFrn*%-*-e?rg^{bEm>abi#!jPpo^nhQ5WH8{aGjYO7PIZQ8)r6C+@-otUn`67xzVU zgMYoHpR%LK8aMl9?-o3cw*r!Cc-Q5XH`C19R$76QCUau^Ge7JDavaoa1h4}AKh6{b zfS989wjVBgUr)#JUHoH@PZezX9R@uyVPI2~E9hNqcL8Rt`q>s`x38`3Wa_8+b76Vl z9Xvj)`wv@?apm_Zk$*F;m7sPkgI=r$^f;>LQ?QqW>{4AO1Du>+(>>kad9kdFr6-sR zk>u`7nx<3mi4fF`HjozC7pvW%%EzeDt3l*HbT7Naf9hU3rG(o1+Rt`W?w4KQ8eOpVN*aX|c=&%HZkeJeNizOa2~T=SK!vo|LOs_cIo-Y} zPH1|Qt$99Hm;mX>W@hE;=!qD4RzQg59Mi&N)K-o}FMZY=Nf`Eox_MZRwSEojE}1#p ztE{wLN#x7Fu{ka7`Oqc%=wl{^SR5UK0roj-$Vz}^PCZ+Qp*k+V?^!iI>w40~e6A@( z-X$7Q_XR{dh%691&wShLJ!tF_GxKb2P|I7#X64q28!#Iv>M&O_!^{BP^0#VQnS{9O zDf_v=CI`RLE5^m9v-^@F>782#v7W#h+*6AN<$G!%>^Kuw>v`8(QSJkte7i25iWJK=drN@4%8^NvKCj?=IR2~=Yw zrgG7s8&;@T|8T`5F(GXXJqqFcRmMMbL#%y2upqF>-@m0S&?ouG3Lrd?qa<2q(Tx{Gil z!ooinYt1XPzo_mjfq5!94GzZ*m^5o1ixhV*bo(Y$-a5x4c%c@t)l({UYibv{;Se6mVDSzvdG5aaiY?0T2nbYgH z+{z&~%? zMr2&mmyj&Y-tDPUS)EHmz=+=6r*$=cR>dEEVa7mIHhb;~Q~zC#P1u(nM9=(XG>mvp zS)etJESD%slMrr(FO)=w!EB5xLX~x1_)FkK``nvbq5*6ilkfP=)->k%Gp2wN54hq z?h?W&d8Zf734AY^x4QbMRZYm|YJc(^$Q3RS{x*h~QpF^GReH;h1kUoMt1oXk3TJ%G z-4NQ7?rd?|o$IdLzIH=;RGm|@K)~zcFM8qTTJI8P5t;>7D&Q}U*hut`VC~yuRlIdI zN-&$)mAcrnMYk;vJdJ()!WXx4E%YTW?ob$v4GQ+mt$-N!fcX|4HzRqf&iURGo!J(D zfL_AXiB3PbgjZR&li|I&-%n~!p`qK=j7CLZ{{3;ASmS9@M+5%v3VY*YE{#itbS>w6)6=f64Qk1RT2bqZ(MZgJ!?F^2!U813$^%i8l+ zo#cBea%)NdmQVcJN{eUAU+xQCMO3yuec0G9cE89X=Awdz751!n3Ym2SOG3rjH{GGu zwR6+IV%vPK+&kKI;1*uvLhF!$#Z&thtv@LISC-NmJanV52 zJguCGCTd&>S^Gs}kRw_>Xr;MOdtMGpMThSlx{I24czCTrCZrOI&Tmf_1}r1BaFfoP zWe_#6Ivef~P(SMPI}fCwY0PJ~r&kGhGFTgPv9;i7bY*}(&iCEmY72;88C~SQ@b^La zjK7Ih4(b_P88yelQ<%l7;=4NUqcm@oM7X|_ybG_o^eU|GJ&K4u!{P=KQga;px5BpW zjo)ED1)_2WF(Z=^e6vG?Svnnyw)*bLFJA$1)j+ImQIPMpVuGInVHRNf!j5Ul;LMf+ z*1E4O8B71z%4;9Fv*gswM~dL#pSyUxw5 zx7glQ6t!)rr)nM?LgqpMgRQu?$r(!zjnK~N#{mL**CaPg>#p6OG#$lb-QqSs69j-(mT`Gk5=+eBD0`3E;wNsvVW<ZeF4d}csKm=H{dNc zHdevwx6gEwtz@F#pj_f^qiLZWrUP65w2_0;?XnPuPTpzMHb%hzxa40Gb;S=lO^ljJ z_bu+4`dLP^hs&0gi)w#EWMS1-qGS|rU&Zoix>`4qMG-=+`(EsQ{$Pu#Z}Y_6poHv8 z4INx*xq6(B?*`MZUdx-EtE*C%Ap}x_yZc zi*7>oKaC4xYAiweKhTnpPPFi0J4FVHeX5Tu&nLcm0^u0DwGHby90{w(2ooTgSqMq( zL_VoI-{6KfvpP1_2tA$;MI&VVeO;HX1_{Zu*)w=JM03y8~QV(Gi-%G<;StW)aQ=*X!TMk%~1)P6R{k_p_ZLzD{JY0M?t4vw#P$LDhA~ zw-3_b&2jG%(69h`0*H;=pg3wQ8(tSMlVlaYE~7QVz*3c^4VWEp6{Y z`WckDB6jjTc>X94@KylCwJ4i+GQc4?^+amYyqPVPL5sH}Wtf$j{H>@&PT;Ak<*|0j z(@dURsB!xpSN3(3mAiWdW#wj1uwo#@sol9oP88@CX|)IHD(#6{haI>MvlSZX71W*{ ze=c7J#L3;#dX#q?^b%MriZ$A1aN=o0s#q$dG6C~-cG=B5t(lN-{UQg(urgKyT=Tes z9hF%wh>6=FsI5~}YQg=Rjv!=6d*i9W5K+3?6rrq(I=5w7^%%2&P2lWioK%XU>aJ_G z2^Y$R!6^DH#2gGUHf{U;m_b_)b?L%0TGnbnyP}(ZA>as`j=vFM4{mUS_=C$to0> zjJMXMJJ#Q^eI}*4 zbz|8krGMUo0 z4#eJwQ`+5)E_ho^IQc@3kp}-I)w=*?D)h9R)dWcZ$l`fcuC3NE^D8^=W^0n?$L?@@ z1ax<+qk3s96aE#cLXvY~f&hA^#x zEp!qL#AcFoQW()YKe;=ju9yy#U{F--fCvsfI2=B zH9>64F7w|;lXcce(}l8J2Gyp*x%D(W_$_^@q%S)_Y>;)6w^-cb?rL3lPo~5*1(c-% zxW4}aJUAi{_lkNrO!MT@rH$VRxU^fxzP>=fd{hNmzvNFw`10m_?8zisgC_uzJE$Vv zrnc>s#OoxddU8C})i7LHxuq+*@w;O;X@>lVyHutKW*ap4C09jH0Py*Nc?dhekZ~)3 z*mNEmeYejc9z?IND4o-SqMy7+Sw2vPxdkf^K6`k&>xV5I;#|w~j3{GD8gK!9q`=W% zdiY@I>2E`J0m_h_#X>!~SV=+Dx_a?k26Vt*bL;KA#<^NG8=54l;f(8!^cGF%bCcqF zVu=@~{<=<-6Woj42989GJD!EtNv1ML49+|w*_bLHh|RIo*n6$DL*|tdI;WQ0?g8h= zu<&Aj%EP(1knMvKS3TLM!I?UuH2{`@=x~sybuA-CF8kkk45)k~PxoK>#_d^Zh`4rk zWYSvu=cw^bYlI1x(#-*uw#c=IKL#Jl`RmYJ%I^wyqh95A#~o%8%&zi!h|Z^P^qR?b zH}Li!pPIZD<&$R2R?MyH+NP*rfQ_-_Du=f;wzZMPY=b996l=(%Tlj>MiQb% z^Vjg^OKlI>#*ZyA+$azx0@NpV*q=N(7Zf+0v?EbRra>F4%`o?ay-@-B${_1f9D6Dv zff`;?;Z|{z`+aX9HhupRiTsI&ibS$71?QlgAR-mLFzLLH&{3WH9hd=RDb3{fsxdqZ zJHZ;@zIViJS_(X-6P{j4n;Ef`*KHPv1$$)jdFIe8HJ!Fr z%b1?669A!;cjtrn1clL4DmZBK7E=$D*t%lnSpEu6`nqRpGEc8|FJqkX+NZIUoEZik z$O5y6w_cs)WG*QlwFV~Pu$)#F@fyt3}9x#-6OW&WR=+0%b}H-`(O3Y$FP@^uyO^?0^t50 za^s0faN}={CROT{LdL53PC>^@z`k{HM0&~`%oJV5=n!qND8Irqpx_$?+AY#^8OKc< zBa4Y>9)d){mP@A9N*T9SX8fs^wEy6chHE}mMv}c!22Z^ev~>bV<~5@{Do)Q z|JTrfLC_tFD9GcspVgdi0&tj-5zp+(KKi|^h7Cw7uidu>DuShFJA7Ru*ITev8?mj( z@Fw~>fgU!JX6(eNW;J-(Pv9C&QAYc@5|fjY9FIy$^o+goq{<)CQv~(3-of!iY2(bT z<};47xT~9OXqgh8Z_;!~uWo+L^i7~|0#JRO-!f^uu%QfUUBRi_p)Sltp=J@_eF9#J zRCj9=%z(2Sa>g{>e~#b4v*w4&SK4TmTqEbVWqdLgqtzHkwo~#N^@Lu2YeNPoQzXWm z!@kU8w&VPLivHWE@;@Y3!1)1Bj0n2_<#86_04D~13GhWIozHGBM0R7A=b(h38Fp#= z1diEW4ZBv0ry$^UT!eiZsSs!%(0=`nW z2e?K%mLg)2Ur>?+pqW3B%)jJa0j!N+lIrXqsegS()?ISr^xhNX%-#+uCJy-#I2(A2 z0$&^wr0ow|rCUP8`26Z!9xB1V%}w6~1O?lxM_ld(>1b-?4)(qYA%A-HON$4m!?Y%w zrdtJWlmoztCUk*cW0&qAid4G+;9K_$HP4+RCR*HkAV2RL(V?VxV8@5ura*5Q(bJ{& z``6kK|DkwsH2jBK8eI{r&GC>$@9L-fs@VAL*#Q)+p|b{P0id1}D50FefKq%a;BVYH zr|$eqMy*Z#{CvX2rs2=M>8~j(>3gwwdTsmJRlF9sKVvru8eM+h*6{afswnUWARPS9 z*<$~P3x)q3s_f6hd7uHqk;n@kF>>>a5|;cA<`^=T`kFTf2&0F8l-P zO$~B$x#X~be|Xf~p6h5~0^|28v|KPgH!G@4Ot4Pu#DqbKbWW(m-(1Beg8ni1E=RC# z$tJQoK|qeX5&c#McJB#@IS;~dL-&x|`{BTcYmM^3cCqp7H2u&GepR0e=Wku#2Tj%= z;w|#6rX4l%chA;k=nlT~itP{Aea(PoE1^NNNndE}Gy<|ut=N8GctRuL)$)99z+O=w zu>HBGzdzu7V~)bZY0U`k^L2jasKC8*vF=J;5fUC)a(Xg+s6jH+PXO3|OupbUo3D`i zXV}#VhGa`%yF+c~=7r-1;s9TekGBDa9}OPu1j3HjCz^NWS6ibh;q7W|df9r-#xXCM z^A@?Z*V2^SUySwxDf1XMQ$_*!W|%nj&s}?}j)XHpcJ5=t2-K+T`3 z?_qX|aDBWZ;~p}f&g-i_QOh6~Uy+}AoZHC!XyyLwQGmTfd$2b9dOX9tu5={Wi`DtQ zIYH$^n}hW0z}=k_8`jQtqaHr%Hpgd{_gMPrgT^9qu(SBM-TN?hKv`fA^}#i%KI!@8 zs0=IXiCq!lOMs;LCEm;RAs0l=q}ZJ5_Hd#hC&Pd$5HH81)b~2PwWJnSV|5J}uDEf# znx_Ga>Dxn9RKpbk6V`_@E>hCrjAa*(q1UUsdJc=+_8Q~I=d#aVqnMh_K3gdt zpi0%Sbk|#5Zl}Ly?}mV}7lkny50}5d&qWi@!Z~Z$!dbJ9;j~sZH=nEL(QL7i zvl+`q=Q>D*E4#(S)Yp7x@giD2P49Rx!HfpPDZ+q!xc6Ch)Gh_V`nifFbp`Xz;;^mQ zzMBRRs}MahHj`*R=n>1d&~hrL0$_lK8H@>fV$N)-`cNNO9_?EvvB7hC-)fsh8JVLr zDLd7i)x*~lH5$h6Fv^K7$Ijn~0NO%DT_@~Izeb55mY^55(<$eqwU_m*jaIa4FXU-w ziS#(Mim4OXEucr%rMK@Kzl88N-Yb-Db;nxl#dda=uxSS=O1?m4E#?rAK`lsGXU#4U zwg><~LtWQE{nAwhkeh>2%(Flo^b4DV77f@a>v(dqJBH;oU{0tIX-s-`-?e?PGe&He zy`aZwTU$208!zcG08jzy|o_v0jI%FK%4=TSw39o)=!5=e_G)-#B2LY zT_*5rac>3tv*6ih`AVZZw(EGR1R)c}nttW8+TK0xC&4OE>kAKr`eZo-!+k2Ym|AYH z!G-+5J$|LU1d(&j73F*uGr>ujl9iZ$e=Of34o?;lJIs)#kiP#IN5#9I%zLvAY&O9> zS&NSR*dAG;y|(g$W;8K3}A-IX@LBcvo3l~@Pi zsEV!`3NP^J`JI1_{}nt*yZSvy5^^#e-U>RqP!eLb2!5vNZK=Rby?*kMakwW4Qpl8|UBsz< zdVlUsrE&qUmkY+OA7!+A4yn6(IBu*Rl*tH(7y^R0NyL$D>@Jl_$6RMbpyRT*1dR>N8eSF7WCmLMVKyuf?Gae4kaezNt z2eE$T3uv2Dsvj*mYJw9P9=Nx%>7KPEeK{09(eyZTFI6(cin@CF`>cuDG%B6dC$J%O zob!ybz7t+&2Xc~=1tpy1n0O|!B-{x0#1H_`j#_WR321op-$g%kU~gqJfg4hobD5xx zOXgvQDs~03>)dtosC-I?8OK^eH@qgMEbv?71vJ;w5zl-=>jst}G=>x+#ckOSoKZ2W|DY_{@xV`FgP^(pD$fs?~ z(HD>`r1Ph~ie)<=dv+1S8J^U3&#V*u^{9mV^C!GUGNt)iOL$I8HJnXda^p04iw71| z`!)=nTcLUY8D=3xK_%SWKJp} zERehaQ|YKv)yrz*y9N=rwdWjni3D3VTKqH~?+dQ+DFkX)Mg%W96~vjI(>k%;229nn z{>I-U?`S6`1fF76FfxTroZ^f}oj#z)8tR%Tg}X-yLHfD1pu#uKjuv`Limg2i81l34 z+Ox}KYiDV7(Db&iE}$K)2hfFIJ6~~r_U(SsTw0f8^jRY7;V=-c5}o#|8=7H#UOLXJ zNHz}r^=K@!YZh}H{Ojmf15CvK*3iY1c+({4g&(42SGMl_HQ-FXnPvlp5Nl7r$Z`1` zxTo0`y3DCe_XM9a-I$Iiq`l56^+7nZ|Ioa2{5pfS@cV$MvNP?(xuqWdU@S6RDl--%9*b4^kk*~=nr-^L(i82vDv()Qu@mJ$wC7S??s*7PzGS$vw+@MSTNXG=yB4zlPJ?w^jV%dV@Pn?zG{3#G zx!Y?p4okJA<>~#k8zno?3pb%UB~>q-6G_;mGxf-ViYp-{N&#DK^}Yk$`{YyRJ*toT z^NOV203*n1Zy_UdPj#q}rW+lxu<62{{q5Q{`4}m&m&*SIfV#b}w@SMt+-Rf{oyPTH z|F9b>6Q=iL9fJlroozqqioDb1_f+lOP+F3!1F#wo%Nw=dC#)8;U!k-oI)?@m@!Y2$#z4E%z z`e-wX)bcvG#@U98%s8kQuY)MSWpb+j?y!A&5x~X&Rh@CJ zx)*~}jm7(!O%~PIc*rfYuewo|GD(*}t5A6Ce@c2c6g-ptIs(57^uidz7S;r!VMv>-$*UU?qEWh8(CIA+5@#ZecZ8AT(kN`RYArC1KvWm{78sl(`k*W$gMP&1jxieM4(%Lpzpn#y7Av zKdMX@CaA+k7zQu4B@Q0ia1}^Qh-;H_EgFd$)dKLj!z0(HN#{@6X%KZ#Qyg6-Z}~;% z_mATBHm7OQT1~E|(L0NQESB7fXh^I^x2e}N`agCC`F zmsrof?B;pq_oKB$U<)ryx}%cJ#BMse(c|=P#$wnj5`XG`;FI%TB-@lriXB^m;*~Sm zk8h=AVQ^;qIXkmJL}B2m+w;n5O7uW%Ho3&F90cLMRV9DdhuT@AGv(4gA zfV9T~9+Ulx&1poLw|zYhP+BStCXGA-6Bh>;!+torRM#twE##kjIXvaRz2mL-7O%SL z7Toc+Dxxw(gs$K)EqB+56C35&Ad+uWqFtj2VpH0mEqeb=NKh|qe@!sL@vS-9PRYp3 z%b?TRmJqP(lz5x*MtigvGo!--j%9O_r9{3X=jt~-s=V2c#2RTl7!MuTlH9VWXet(u zak{Vr``smD$?MC1 zJhA*5kzf2lOZ27tb3b4*AWX{&2mE%{a?Xkun=}4n0MuL?HR7b7W0ql6-(}u+7Bhy| zY?OtNE|m$FOUNQ1lLb50zH!!TDX>#S{*ugC_L3+G;l$ucRz!Z^oLh;oH=Wz)`D7*& z8$^e)(diV!&uxSdyITsN%fatRBc2^IsacnPvM#G;MpM{{u&a_&M8**}b3AJ)Y@8*t0U^2ywP2+S~oq~2{QV4hz4t|HRIH^62~ZkK>r zHfWi&8jnZwu8}Ku;9QYyE6Vk81xS``$dFjShcY>9aj!#u7athz;_0=#!jp7yDxGH| zEliwWe-;z6`=zFG_;-(jIn*pov3c9+*3WN3h2Hlisu(A0^6()tQZ17V?ALTmQbXb`CqEwnyA}JU2q=!GRBql4YH=A(2vc1o7}6a43Nf;8Fl`yW}xax zG;jyq%pQ=|=;@M*g$3pyvT6Kfpo>}&XGs3&5G#aU`}#?UOi-@&J$Z`Rg0Q*4nNdNm z?rY1XH!@oZLJ%AlPqY(rjPGn8*PcPH*L~lYi1evWXrhU=RjC-uMgoGWOTB~jQCh7U8C;}@!t$vD`>K*nXz*fkzr;h~LO~Sk zvh_jx&JWX0ZMG?kEw$O)L2geiIqKK0Jm5d|CmCQ%5|Kb#h26Peh!CWTeS%H7!}OQ43Qewr>JT^2?8{Mi~}QCVyeFr;@w-(oAS5 z4+<*E%bz?@ZaJ1VGBLr()&XHT+#Xw}Sw1<^bbEd&08+AH>_@kE4pk!)%>?RrG=J{s zVq*xtQ6cS~Uo1NB$5-f?gpue!?|orsJ2v|jAeCMgK2w$ijGoh1wVk>QYmd?5}_ed=wcCDGwAR81;UB3X>cSh8&)%FrD{vohjP#a zRZBrPvs@Vc0BeiosyN0{=5xVIHQVelaZfuk;|Ac*`&Fg>!oEBHmCqkHcX0jhANqHw z;ib~rl*w-&VWrI_q;gYP;vMPsIzs`Wy)SbR4H`32gW&2??I^$7Q&SI0yC048i0O1a zzU`nX^R|<(*#9SUY6rVQ4&n1pG8)}9;)62{K{2BZ?NRw0Y%28(_f|lxrqV`Yf2k>5 zkmp0Wb3jYOqYxi%DFmbTBDY5Gu5t|EZoZOo>f`Y`vLK98AU^1{PK@ge?nvtkWQ4an z4duOx(@v3xpJBm=keMg!6cx65%+<>lQt|6;%`#eiQLgx7PVAN9ej@z`mHF@D(6ltG zlMjsB{bRh}71cET0oviE5PBqFh>)CrUu%3$Lc*)?20YFWisCf4z zahIRQ$?eoy)`<nWYBNv+JMoEGZVY=1A}0nH^R zWoa;McXI*kn_~5VXkeTuZ>TXvT`xXt;LOkf0W*v4^v#kZ0x*Neo>FfsaJ$%Py|7?#+EO+lt!Q~VO944&EcIGu^ZydM@g4?f4M9c6`iqWb2nUjsHcXIqiDC9sb?TnJTb8+gkJ)_6 z4=^GU%^QbFm1WAuRgPeLgk-5^TNXqwq zTburM1@6Xn{R$21v#eN@<2DJi1(Zt^Sf1xjrjp%SQ@`DX`jdXWJ_)xXL-vi(9JLcE z%Zopmll9VWke?qoL^Q)u*}mD&$nGuFWT^kV^mt0~o#y%F460dxLMuyJBR#Gs;2vFr z2xhlm+&s#hiFm{0@g;SR!^8*Q(C{V< zIU-SATizFrrS6Wccw{CD%Hr6)0d)aAlzF}Zbuh!)G>-|4Xg_k>$`3)}Q$WfWi21^| zjz0V=qgit0@IoN4@~d8|@-F#9uTOfXZJ7Wb2J~(Bk__{9=WC?Iv#0!bb|9TkzO;VA zd@{JVJ9vjhFx~G&4ODb-?VJ*J$=T_PMtGh6@Y$S;*n|XE&L9K^=2ZZ5aJdYCR&I{G zCv>tHvQ=3q&}EMVk&R`#SY@!eNFhE)od$REEd0cnUkl@#cyft= zv*-=iityDvR{r7I!AJ>f5{vzIML=%)b@XB@j!tzjJM z^zG<15?FB`(O}z zI69M&Gb7cAZh`kz{0=Ln%X%=O`Yox7=M2CT;`ekPrIeONeM)nQ*t?y+a4wS&mEr5I z^wXn)h3&_WCEY&wr(0mrO$zZ$U}2=m>|?(FJ;9=6A5~3eRJp{1M@%~i`DoX7PHCo5 zUC+8^j}k^Ze@c@|lusEF#H5|anhP$bjLZ}S2HrQ4pwEx0VSlB*-?b2Wp&CTT`1@Vm zL`um^iT00vi9|PdGRXPJ%p5eAknlf1m3JeD?=vGwnjPxufmOfjZTPQGm=XzS%-Rcw zfA;zc#m_7T3qtw*DLukJ*f)$fTdAL)0X|*Up|=d~Hz#^vchg`#aFbf_m(xqyv#}0$ z<|QUWY-=@}@4|$8wPyE0ZCk5`aJ#odX4`Q@sY3eY2DcWCO*!OhRp?LM?BCt~dlj7Z z-~4(0zun{pHBfR#i8atY6?=kA2;~jixK-J5)`s$BitQ=ldrC5q{yhEW#`+nVt|Az) z(Jo!aXc$wn219@R75*uzg{9K2BpLdq&hhiB_hkIYn)8>x-gd>Ko^GQ>ev!w&CS{~k zlL_tY&%po)SyzeKf=5_(MQX6^4-LWvUa@8JZNgA_(q`UHo!c8dVBs#)9)Z{gduo&J z<%P=~Sd89OF#!6Cd{;r%6cm$c+}~gG7@BOw1SNH=zBJNyd}{wTR7XTQA}U`juz9mU z&Tgxi7sbJ74LlXW+qtio6}2Ar&Eea}CV|#=3iEF@v{VU8?Aqco6((Rq$HYy#jopfO zr8a4r7ct_+5lsH}Q|fi%P7A~XJslp7RMuZf6v+8mapHzS&1{WXechT+@ZGf4nYAiX z+1$^AKniD*=XW%43Jr~)JXPz-_-K=jK+t=vtOPRs%`(GoyN9y#E|d?*2&-iB4TS)V z*bRd`(#I)s0>_Q=MU{(5ureRojoF_!t7QnToU}X4*^8~kQ;1I)rj{-xk3)%Q{03{8 zVdlVn<#4JyvnP58U>yQbAgy8M?){vj187L|eDYc8aAD&*aZfN67?SD*K9mff%TpfO zjBw*+{@T~A_i3ql+(7pmqTXv4mt>{BImmxKDL}Eje9i6O)>OjjZ22`47L&#GZRYQnM`b^;q>&)WL#=|&%z;%<)Sf^DL`nwnJdfR8CrK84 zSH4qY^{fjxIXdsS@kb3P_#tf|H?KMif&}V3W`&QZD&4+>@0f;IC+$zWX6b43=F<@lZM4t7x^y((!JRJ;I^TSuJ0?JnuLd(%4qS$G3OCPEAvKw_bzM>$-drrl={_ z<(M{stII@Qy7LC$85^SxT~WX&xcIUdb$y7qEaM{US*BC?4FDh(ybD^xHxD{YTW=qd zzCBxI={V^3GR;}CTeA=de60@{6ELp%v**$c^-!}|pPX9Gj|Xe(EL0A<(_{HKEu@O* zsXS+D_R4Z^IN7{*6^f$7I@CJ~X~{I9T*QjA^#{5XR{pWxIGNU)^W0Rku+)xh85>R& zI^is>Vh$3D8+s9Dz-hAjER1#FC)uNbvyZ*j1fH#JG6>c@fgIx`DjbUML|IqXdN{`F4HZjpC2O? zoxn};92-;$x0(=H0w5g2L1kShmU*q|SKP5xs~{A2EM|hkHe>%`U)dVrDpp{lfe5S% zf4~%2sl;$|`FaWpMveJbiub4s4}f4R4^-G;b-Z1OT5vw_=Cs~Vp}Pl1s$WDm z`xkB`=G8fx_2avX&lmLDEf>*xbDOuURtm736VS$f$(HHmM6eVR&;cgaepUJ5@%}OI zyN8ozs7*G$0WvW=$)#el)-_zytpSegrlB~nl^I`GoEl1!q1X1%60#mSU%UL{7c}eV_fziD4x4=Izt~~HPf)yI zFC)*i6q|W805ze{@ayy*9hy>@HE?1Fr_>ESgr7|K-&#Nbn1`h70MeEv?1PRA=F-uP zcG22rpE8Fo014_;LcZ92+W=QQV)4D);GD@+-Od$4%@)J1fTEn^*Up;ug7fpN;XYIV zZhaH+it%Oo4suYUxK_+&SKdr-2SEBL`*6czH>d8AKT?LGqG^-SjtL48V?|LX$Ouw= zQQTy0>E~rugZz5<(s1_r8%h>qo_FpNP-~D)pC0wViJHKOLYm(jg3p9Lq8N?ESE)6( z~P#^TMggp&N-*w6^c`5@Xxr?}V>E6ZY?d9Lr z5j5Dhh@z_Ufa0dH?jpT$>_>gTs`yPV}ENezZ0##N z+5MqictbXrM4Rqx7bg0I-Oq3K(!7>nK$&}2qrAqdpJ3*XBU_iD&mpIjf?gV z{O6c}T`!e-EG!&j)_=xhVs0i3thnD;T&(`DR$)-u?$uE}tps3rj;e{;oSYn;)6ZCQ zMMF;B;o3q*Tssoc#OJ@t-lBZf4X{TR-em_;`nLy*##pzc6v#A2@L9V!OnLu&$RQ`* z!8L-aP01O0)BGUAHjU=_6Hp-Md*osk>+G;#Q~I=7$$58W)HmUB=wZ*k;HhxJH=xgpP%5n~y5_m(0(~br1`5wK^Zc@9U z^m&YlEX|tW{rTZZIi9OHBB7 zl}((h80~=@c8e<#TLQcKo5zU(?h^PptSw1jGeIDmNADNniyx>~8W5^$5@oN1YLA?C z5A_$XlkVmJa_p%}cI)rQY%0xcgKJb9TOr7zblbbXkC)hlAYMP7fR?zA@U(49Ku%;g z&-vd2CrB&U_4)V+>mIR7SVzfkSVvmc9+5%UATp0Gvu~GAveXjeZ1X!)PI~E2GDU$X z4nJjQLn4fUBo@if4#Nkh99W3qFIlW2DLy9SLW^2}ulXBKsx`S*CPg1)XH?>0y$x0U z^(M%)8&Eo-bDkjTU?qgN*sEgFg}+m=^$1Rh&QUG+7Dq>3PuNnWAMOCJvzkX)q(7_{ z2EGfM8J=0w>*)G*8PeMr5|@Ck{-Bf`(1gLq|d?`4_z-fydg<%z_4kez_H0% z2Vxd##){$!tyf-p@$C*>i;8*vWe_fT5<|ihzB@<1G!(>7n9^)?_SCNYBNZnFem6`ns!c&<( zbG`=5PUQep3aqDY`fxQhG#;pbLh(OtFP&O3qK;mUVjR}-E48C|5j8JK@E{>oC}z4!uF_FQtJT9watB9WR&^w_ChSpE#;D2 zmn!?W4OiuWHQvi4^a7v|{-|4G6pf=GbV^r(XA3|+x1)C(ftUjg)5!;V^N%35 zvnh1$BxK3SG`L$Y9mYlL_PzJTQn^yVf@`f!Koqvx$?JXnz!%=OmmJ`E0LNwq)PsLP zCg*8gqCVcxkb2J2j85#h%U`M@mCz%Fab(nqi8>@+uc?9fa?GluRk4OFjpPCd=f?^V zPb6!YLT2h7^Sl?fY~q-Z65e86%(Me3Y|)99YTbL{fy3Bp>A9I=d_>N1y(06HINR#x z5iDMv9~Nj|KT>_KFKpVfj=5o28mU>g$uZ;Lb#o4=!ofyW5c1VhRHDjos7TS)SAwDg z)&uL-_vGqzaX;_5wT(q7SaUy_-f`DyhJAT6YL{3@8QEtl20mm$1pjkv8-gG6+Hyx> zkK^4&BF{#HylnGr-D3!goeT#fR>x{Wb&4un`y8cuO1nc{r4W2~vao1_4*J&o9glGu+(q%1CgIiXnU(nYVOOof!7K3JcSis2bwt`RnvfcE>hL6xgc?d z@F^DH=>Wv+B`6WXwRngjDRgwjnKvgJVe4|wnS|FFdDT!zFohyBYgL>`uK-F>-QtMs zQI~-Bnji5JVwANXe^YWIEH~<2>Vk4R$%J(;Fj$lh=Q8vwoH%Mo+~=QzjR)z|CdUqWLzL^8OZFj6R-WsZoA4oV{5;=xqZeJ2P_~=SLOjLM8xfV(8=E)=l z$EPrK!|bCqCh;Va@|kwDOf+|4U@LH7kc#ekC{RrL$!5aoyixc~6#&>M=wK!dln41j z=YEfc1OHUfwJ15tm>oTf3gf12q{z85W61&CT_X*6Zn2OcA|S%&Fg{gW{5gg@)729Z z{KRHB-?~;s+(3BPv=)Q3p5NYNN!+R752GVWUiznzre#ChI~B4zV&HBh1P8}^zjVR} zb0QiJZEu0TUhyvGGg6qkEQM1PQ7tZgk5}ztqM)s6g|DKcEXxU7RQ-~fG8rAU8;!dV zW(=62XuvZzMk`ZRSQ#+`5d0Xe_uu9-CY(Kx$Ti?Kt6FcbZfEv-)^J2dxlRUX>*?!3 z;-1yoK!B0o>ZCaUK>3zhxs7L4#GRbh1hRB}jRyh2mq^;}#U^i+H`AzqEGHfe4uOYZch6A*g z`RMsR@^xGdjdo2(-GNI0STy2KX^Z~7ze-!45-s~&*2N@i+hS+|^Uim&&c$Ex zAt;4jffw`N@qO!&9|v~y$SB++Dy%ao%c(4VH48MQY7K0;50RktU3x(tKbXKCWxXgA z9if6@WG*Wk>TUfxUnl9Mh_94QCAaW-DYCVuF#>1I6i z3<7-cQqCQ#v%LbkBcnP*FpdXlHw?_pal9=GVg2Z?P9Dx+ zv=%$NJtHy~x;2l+Bil_NRrfoMm?zP{8-ueMU|QR*+j-$Rpgt|wl5U}_`sJ12T|}_l zRo%<{{Qq(nz#-wAG(%CK%P zN3?EY*u5BJ29%WC4rzPT1Cn%t&r4uESwcg@OyFtyzK&`$bi9Zm;f?#74$|v!Ne2-` z7o2JZ8bUzeuv9~7aN3QJl=mAs4)7G zdcVR;<+n#=jI*8+*;*GCL{D)HfWJna)@;L;+iz#EVhO7*`ItRc8l@j*;e-TnGEgMD z&#Lk5pQ(totmej=4(ocJ7;*Gq_`XF`+pMGu14?n`&(!CNH#oYB#yIX}0*#EcOu zw0!8RLxb9*+GNyHn!4$-5=nV_-QFBpxVx%aY;kc}9is^rhUshSHF62u)H~))Misd= z{9Wv#fV?Vp>6U)bCVTrc4DBdNvT$~G=Inv@U_#tgi6kxvDtI~27<`(vt~^KX&rPCC zGpTN*n!wt?{phI7zjaU`awH?jLg;(&r1gl@VQ^?IhnL6Y08@JD`(cj+&t;#ENRP)6 zofkKIPMH(u>$_6Y2xDJ1&Is~5bZ%X}x@0|;*4~j6e}0oozKCT&UL4YBp$^FhaSg)U zn;!4mlf>2YO{O#h=Wld3xwgd$IaU)_y4I-@dZ7(@MV0^OiPQO;$bU3x=gC>q zUWc7Oy=Ejm*msoc^#L`2RI&USKnmk>*Wp4C-Gv~)er3f#8AM_K9C^^h&`qQi9U}a* z>{O}zwL&IIJISyV^R)Eh9#>*;=9^J@e5CTB3n^}Be`W(6V8~&@JoxJLR8%3m(bsz=hvB$c}*2uP8y_Zr{VI29kv=C$2jcyey0@@KO9vrtuOGU zGYSK*>6if{O5ZvZZAvscJFw4i49)E!FreqL>s_%;Vnv+a)eHdvLxCCM z7En}#7GOYj`N7_XwOo{Mt22z?wLJD;rMg<8v|`Nh1I`X*t3$Wz7=v_CJhFl>fyp8G zC3gC6n)f}}hl3hHr6@XMyOnoX8Z4Ya&=Ktg12Nr&VDgK+VY9(Emh}8&85xwLJfz)= zCQaLadM!CQ&PU>@IL|d3qb`s}bq7A)qCev^?$q;MIbsacSwAY=owDL)M(+PAF^oS8 zL!JMh6#?h}K0M=k$gu>35H>X=Wjn|fe0ly4SqfX<(FZPwb`M;m~&0F~nFY8goI6MR>m!!~7K2s#(&;Qs{{=@l0owWVUs$3+x!)>>A z)6o;Z2f6!>+aSz2-c$>SuLjs{q98uNhicZ}QMTFt8>7bMqx^rL>HB|qPxXKFaFPE; za+&udsdi`fmC@jQJ&wY*;9$$@b%&_fvg$2fiil*sH z`h>8GAQ9@jnQ+YKhkNRCH5=-}lfZtB4%n{=Yq8A8C&%D_1qjX+WX-FKH~JCQ?x8B9AN@MH>qWQTr`Q5`YJ zlU0X}-JQAu*OYi*Qev{wXf^&6b5+HCb;n(bE0TqM;7b(JruDVsoTgBsTIoth?*q;@RhpGa_z4!=XNIQoXOgspq0uFtQaWcHD@J zHtA`)<&EcMO1XBEP_5ktKytVM1o*eNmWpel#Ebhw&HXn%lxM1|fa2uPP+6FO1py%S0RAwYlt5ds7V;oIz5>Gk%oVNAe8JYiZnHo5k4Gc;AGYqHxx z09~r-E`~I~ENZdh#r4Zx?KR|}{&y26W)@aOCfW;bO8kyf!-3lJXEfk6RNsW68Z?u6Ye!m1lJ)6b)ZY;q0wvv`3l<1EN} zM*D9lWeQ8{e7N-!Pz5pM5PHM^1%?uC1j70+Qn#hX=WgjPe!K5z@iwB`T5N8+a)7}* z^kp~Hv(*o;lgCU(YzDpqxW78&M@Q9k_+lc{R%UUPCMZAzB9M`Ki} zk?fAfmpdxSU?5kAU1T)nsA;u+^V)cP5i?DHM-farpra-oIZim#{a`S4+jmi6>Dz78 zcKr#JtxCg_BP+_#sQv!jBbHYVIbz~*v*y0dDSL?G%GGmyPP_)f`Z zv3x2}rMH9B_yT;sDP8w!l8Ao>G&@l@eQ1NF;ss0s|T z1tFxXV?We~Xak3v?5&qSuMxTICF&y6pL=%HhxGK+(;3qj6UcB1ZjnkHNv=h`5AffI zk41+nrgr%LeIh^tpJ0>EPx6{-1AhqB#JuC`GT1f~Zy)KkJWmN%6e)0{nh34iHnN?z zD~y)DdOrnX5kg;l88RY!VOu) zOa^i1rrLRLJJLuyUlNi>!abWEqc4iM&C1!*(|RRS_ZXESS@=FGF-PM~P}mInE3D7&T|U%D~Z2qu>w zpe5%TeyXbu&tG$vB5rz*ZXG+cw?K#Tp?)R#q3Vmf0~HP+?-_@yT*GXy4M)#%l-%uU^7Yl0oxPGyp7L1ljHGQt;f^(}L;@)n|EOq<6h~+v0#bQ{oGx zr{ua{u9z(C)z%6*R>Q9i_y3$MsvfiAEZ_^gnBW6h8-2OpFvGvPf6s-CEDdhOEuITW zRuZ8;MNxc6_Hplt7#+Jk1gZ2;67>(C$O%(@wS+Uas#Q>TvAcTsIBbDy!IO&c2Z}fc zcER`{YcK(L{{8_8<`81~LG-cUy-xD9drIPQ--XsCjBj?pO9A=~3{@P?#GQBkkw^&_ zk4Z1jP}O08RViTX?vM*r^W6I_l}jNGlICt7)3Z=sU167#;F0P0F|hqR@-IVa9=V7c`$rDA4{g#sC< z4bpaP?X}b?=4OsA8oG<82seq>nA}Ru>M*MrY#wCkGt#TacO~Z#AG5-4s!F;Ss}LB= zSs}s&*KgxKJw`IM+Sr!5SJ$TlgTy{gbN%an!?y6&kQ1;bo$~a=P{ChEKCD(6E#Jp! zyhr9-E{g&nJc*ojuevcyM-(<=$R?CNfvQ*_L@YjPIbjv%ca3OvM6Vd2>&HhL^=pAv zZq&beHRd4T@SuF-Itd&SQri+>wiZ+*BtL*I!R5fKahxSXhbp@|>l0UMp4v!-v_r}h z3)_Uf3)mXKuo3Q9px$9SMpQAtk>e0swWrTyW@Q4ly- zjxEl@aBbvr2IHKpyrsI^?NM{h&_8G+A&ka;e##}J&+bweTRTR`Hkg6q&VmI?I1gLy=eWb|b% zuiaa#ey+a8N{@#`?bFqEAZA}y6Egnh+KV!8sm1)tJwVR&NND`FSOry4?X&XNZsn_q z$e%?U6vh@}$3e;BJnnSOOSd=l_beZrJHKUTX^;AI!=y`bgY=q{+Z02r(dQCqN`4cx zXDyUZ?pqC@2|s>Q!O$c9XrcV&XysHs70L+K?Mt3A^ z)|1ZHX(M5UqVTGu*K+9`yfv9q-i1}c#re|I{4^V6$=Jhc;MdigV@pN1;gwSmyQc$3 zS92U@GcLx^8`}HdKel*cRUJ|P)8L+kFZE%Iv%Kq@iCpb=98-h?H$F$oI zuE;|4vcxN+ur}v?f?5isW7lyx3za#XsOh`Ic=}*Lc|~A9n`WK`iP1h|=w+c1ZYpN8 z=c%O#3o)v!&slfv^qBqrG)m`A@ko)mpeQrvZ~z0#LDMo9^(rPyF^u-Xo~A2E&d&{D zY@D{NXQ{%V8fz;xS-K0>cZ9*8V9f$1#e>Gmeye-jiFM<-{4;W5vA&3L@f*kf(Wq+c zarg4GmRG91u(W2OURzk*KdlkdF?vFAluh)ig|E}MOfl2@jRw^Ql7^M^;KtjgS-6M4 zU>3q=4YDSwYihtx*2SjQlj6sK0(qgd=IJ#DeGSjw zg=0TZ#Md&+KolGLV3tinJ;I5M6)E3H&tvQCXE|ifQkCT{JG#AfbG<7MbJBHB&@4iu z0-iV5k{6r9>HLr{_@ee(n6R(a{m$^9p;`@Q9z(mT+K4Mvsmm%^L#whAT}}4^`DIU} zJr7!p#M*vEw^2=#s)J|Zqa3>1FDPZa*?m$M({sVi&6MHjAO9&G@@X^&+Y7_@ottgf zp}Wg1DZj-xGf4O{*FWkT$^xIvKVfga=>JdgjpVpp@GpF0@^c}aR>M>Dt7qN|P~v!9 z{5aE6bV~XPDxiQsjd4-gzQ}U8p70CskRgc|&;MLJ?=Zb>q)0q1kY}8Fbh{=ZK;~S= zK$`S5YAhUPG>WZX&md^Hr!6+Tq}t=AB*6^%rs_Dk_>~?1$48TeMX138Ma!176di5m z`e9b*9x9FI<+6!w+Jwx$$jGfg4%T6U6&{)%U7ZG7vtl^-OXr(6dt3KF-ufO$dDUNj zI~^e9+EOQDO6EB{v*nFT$CF_P(DQw*alMRBQO5y!gvp@k+3}63pyk|Bc1ws8-KRO% zm_5owqWz;ywWbe%$0vfjBuC+dN;aWzd&*8~`e%uD->8UQ0oQu;l}0wA?5xAB|o61-dMI*y-O=>V&J-3x`505+8Ku#u)-RtcU&kYr;dd zS8~=cnQ<*g@^o-2#DL*o6EU7ydC1lK@9@jA*H7OJ|1uDzkaHsAlW8g(4KM2}S`b|{ z)Jp)Laif!<7th(_?-7vh4arRH&PqSaGEzEdgD+5Ev3!ouB7w-#z!Q`o>rcv)2i{|8 z2}fy0r&oxbbh(=%pAg?b4L82}DUv4QtK8K?B?YO$hK^Q6J$3;SQ-L~MBg6-jk(i>5 z>RFGq6heJz9^Jfr5fEAyqYvd~xV3ykHA@eNp4@MEt7!L&`Cob21KDZt>?`<1<>#?$ z2J{otuwRy~H(Q0s)B#4h*4@{1^+TpHwPDpIysir6Ol{ZHh3b?{Z zL2}Q-wacQD1Zt5~hj@DimApF{HlF~5n0eeu< zx@K9(P0!*+XM7qaBN@7go-l#GrSlGXVYOzgrM^T-^2ksuVMMZpYts~F+CkCBih3I}L!5TI%TjO6leb=OA+!&~&-Z9pS@Sd@ zC;XHPQL<52sHx-?CX#tfWNJirK<##KvVasD6Ju4dY0R7JgQN?8l;wF%#sR4KPE6P7 z{|(=9{9o`Lk6_mMm!G&>hy9sNgv$O8AP+27+i>UQ#fST8YJZ4ZuO3nI@|Mun!+SsG zzVB656yr8xW1Q{md?~8y&snydGm5X6$jn$s5z32Qd)PG)CeMM@gz8L4j`a7RUA~hW zd>2!9!3+|tA!j=>@j%=sxF35l$EJxDnO|B-6h8IULG+!@^h#{|*9%==kevL9{|5dT zW8P)5od!wAuD(3dTP7aW-B+C%M1O4lYUIIwT`?hlvC29+|359HCyNodiM9Z#lbFDZ zV^Q5nP$lM$1S(urT#2K#y916qf?ms{2B-H^;|V1!x@^g-4^B__`ngasi`QCw3M}jI zFld0D@L2I3u(3JcwY-y`)i3zvmdsE3tDi4w{LOAM_~_5CZU6F(fAiSuoYBS4Rvfo3 z)((o@sK5TjaOd_{{emx&ALS3@!mi|){!5S_&;X#wH^^5lCTJf*USbmbBM9^B59W>r z%7MMd$^}p@F78S=Bv157` z(JL?$$y%wiGKA5eS#5r|XYHa$1_bQ^xn5|U?m3%*LL;?ei1dDW?c3q8Lzj|5gdz|( znrH1S0&~maJcyvJB{~}m6NqQkg@<}6WyBBC?)ll8rl+U#1)bR-wFBO7&Af`LxgP;Z z9~8lH(&68DimNokRU_zBYwH0fvusjrQi%#cp40NDeNJdi#g|#6d#{QWcMf_04!g&9 zMThk~V0uhVqqgQ2&Sjcy-t?D+JL=uH$c9^!OoGlI#y<_F&#_#6eRc7IJOf=?fzvgo z(U)_=@5BX-oGtDbIZ1Ep(Mj(xY#P>F-Kfo0B*8izsyI`?mJ{-X@n_wijHt<unn3!q90(@miJk_p$q?GwGo&C%%(NDt1Iii(vS zlURCBg0$p>w)5_RuITK|V-*_3KKv{ts#lj80Yhg26>7CTAwW)PliYTb;(S|HRBq$k zXJwF*mtxrt(^Q()6@vtyq)uPStLz`AHEie$yj*b{&iJT{l=m{X%;I$9d<7V#d0&@H z&_wPpI3?g|aoo%$vg;2Det6BbiBxZWeU!MTx-rg%?tB%RK=Cw+6#==*2}@YTZhrK0C!;i3&%Acc9sned-{xr$TkQFM$)y^jg`)yJ>X z*4l+DP7oq2V{w495{31ylp{@g3zBSj{XbUR&fl5gE%uai+3K#LaleL;xkS>tEI(4c zd(d56yU!++za2myF6K7&BA5rfa20(qPo?Fix5dI1wI&Gsl+Z{+s7!X*c{;G;X!d?v zdfi`A&BGOKqEovPAwPnwSB0x(ljzlRU83muXV2So3%QMeGEnlmE#EWDbiN-NZOA(3 znYUVTI4}P$&UIttIoaQpx%jIx3*6pMjVVurWYWOb4FacEp9Vks=Jsck$+^J1;%2nS z@2W`fH3G;JHJbW5DM+m@nxvmBxd=N?#HM650X4j3>gz9+)s$B_Uv3Lrr~!r;pXzGD6<3+uMEgADEs{Q!@n%SI$!bpbHxld0-&*qYy*F$= zU{g)heLmVd(SOZNF*t>ZdrqV~TOnP!JBpg1!amNVC8?mk>7N>s+{lGxmP8GX1b94k z2qI(;tgwV0x65bP95OZKUrT-c3`Y=sXSwsvGH++B5iRIF+*vcI_$bomI2-iJN9TRv zhmiQ^!0T7;Ff$2EW(mJ8*JZ3^9OVy$ww>5SYE|v#gk=lny^FT^Mt~VIMJ{xny-W@V zU42^xv-Bae8t;kC#dnz?Rf(LAHM|22?03DczP?}fcS$?EQ_i$n!ZOQG)-&En<2XaV zi^!c*vi3R1xRKdOUh~AoVHgFNd|H>)bm6)f&%8lNJPG^^qUZ7TrZv>gb!;gW4Et25 zZ|~y7k4i7;)q)XurSt;RjOOf4{|Y>5x8~C9jA8HBy9Cmvsp;tt8z=U2C+cNDpPaa# zwoUR9XQD0E*RGSXJf5Akr@`Aj4cu|y(4T;9FxSjBLszVl|EAbYzmS2h+$N8p)b$4T z2LT^GsV_?FO=0%@0b1Kyb20hD{CfK|W{69jf;O)C856|S29m+{iYusMFlR9e-v8J# zz3c+P*Gx{KvBji_@@JHP*WN>C0P)kiM-#Ncxn3#QhsAO%)%UwdZCea=wzdQs>vD4Y zWb@3s!&H})CO);WSRsj@iFpcq_&u?E>q%&t+vpQ@uZGB}Y~|qBF9}gB{oz^LWmgs} znhY*hy=sYQ9qmyuixHok^FP`m!1XlBR}MZZ9Fs0pkS%IiwI?9 zCr#gQhoo0te~pq{AfzL1$aq1bxN5J&2{BtNCpBjd2Vhiu+t|f8A1mOY{nDp8axJgI|zaa?0fed?WWu{g6%U3q+fs~ z^Ay2`eLTeqM~S(VoVlE_+L$D_l*I$L6Pqe`#oQ}T_dbxow;8sO?%#zkG}7_B&#k^* z=diC?8na#CF`G67%HLeHfqtoK*esYZn6<2Hp3cht_)}c%j&~86&wKHeQV~Yx&pX}N zj3C!nqj$U=Prm6Nj&^HVJd7=~F;MW-ot`%kX16*BWpuk7{R&Z6HF=&GLrE7)D(%=U z7>?XR`d4ys$*3T5kqv^T|LU$u0JlCxNjbX611kLzC4}ul4BQnzU;5Z#=Ad*RRNgcemSZIb`fbX8xAtw)|mCZQl1oJbuUcM+(gH&b;OB$}8UJI?099N;PG7 zQ(E1*H{~~y9@QoByj_FdzZ)^sQXV~8@OE4w`HkP*k(b2JU+RGzDT`4u6kA=;0``wa z;(L)VhHq#bH_B%xC0vedo-|uXpO%AArSbSC8qMv7PGeJXb!WOd?9rkcWz;@6d5?+x zbIG%9tJ=MFO|GXK#^++#yf6La8!KJ$je32cSz|ZV7(y#la$A5%%ed-pFE2q7N~uuO zH(v_ulBlTq5X7zhN0~JunLble_~nzs45lb=p)ZEf2-eAZXiAc3vm7ejBrr{X=Gz-x zr;{nTs?*3-PT$y7>zwNX)kfKfp$}ynv_BpsXl3gOG~>-jDylx4-YTv9`2^yT0^KiC z8UjEMk55~lyxq+(*;$VzuTbXknwNx<&FIfX$E(Rr$Zze0HRPF93CpdIo_Cc#Z*G6+ zSnT`LnuFrQJV!4RP$skO#NVTf(O24Bxt3V2;|gHwa7Y#xqMIU%4kO+3ztQy9zNfG0 zm}lB;h%{v%r?vo}(rj-kb8cXGyQeKfr?fo;R7t)9+CXmTShQ z?LFvZ`5_kgVd1LE_6IZLB$3#@UD&<@&gLK-i@yn*qq?#ap(^hKIE2rgeFA7-#9m!u z8i~5O-CuHLf%lwatA~H(eK#YGCIElNM3LInK*-6(7@1!epZjWFHAGiu9;&snq`kd} zZ+Ju0_op_Qn{%O?*o(g}c`4;UQeW(ps)PDGN=I$0kC2g_dULXnX?h*pw z4ZZLFo@Zv>nKd*2yld8)vyhXs&)zxvo2{SgN`#tINUdGihp`TB{ooW2_h3K9MN?*n-a zx+4@6kxqFjaV;;C{R}Y&T6xdA#Wxe2WU^BatP>Sf{NSG%ubcpGsS`wo55NS-Ct}>b4t*q>nlwx~?e8>-0YL4Se zJ=7x2@K6&GNP*bZ+Ds|(Itt3^75lkZvxioRJvW!ERf8563JUb`fX9v=pMVMvkxA68 zas0Ods)LE(Fjc6s`t!gC$ii%g*J8vuvjqS9f1{k`3aA6hf*ZR(u zU!)Tjhn*29XxX3Jyt%j;I?&PnLHCmp;!he)5%_jKAof#UTq|Yq~Lr&J<59STZ9XWE)`q5g+RrM@z;Z>EMkSQl`zo1a= z?Y=U2Rt=K;BgOh`C;Da?tHZ}-#j(|xz@}*2r4OewD_VBSNmu&OFv&E>99UP3I2cep9pKhEIH1Y{}hl3#V`3oZgXoN^fbp3vS~kqEuO5 z_FCwu!OrEm6+%E|)q3WrUxNKiKfMrJ96zpdQAsSb9q>!B2cN}l5N}!tt8H-QMp|qV zPg%yiAs13rh787+-}RKGxgI`k{3+JCE0p|#L{Tx^L2_zX7j=FUxP8VWsTEou?K5(i zxXkP%pC=VufQ3cMG4BA$5*OM!)IUB9&l^x%vNmLPcFvHLSnRo3RN2(GJgJ~Vyf3cZ zsw$LG7!Qm1(R}R2s@}jV>?0VzI(>V@Lmp+gKGvyQF$BJ0GyKs2_M6aqZT&5+$t`|% z)O|j3H47S6mdtcKuxhoNo4@%cI*WZLaYc`YilEbkcaB~?jW5Yl*qfDbQO^!Xn^M(zu>{=AX(WAhny2vbLOJ@#U-cah7R6hMy%q>;LwQ} zMyHY$GLIraXCh(3)8D5Uhq90Rbb#OUY6RcmSr6p}M6q65vQ?YrDhC`Ua$Z61+>=%@ zy8}S*nbE7`tEObVxutjh6wVNO(ne1`KI4Lj88x1>q#ALz*HAh<%3j=Dp95!!Z9 zhhj^f)4OlZxw>y1V>`$w_<-htb>D|SUK&>Xl{egcWRQ0#i^ za4o>*+Atq`RlrT@0y5@xSLz2uP4nSM0Di>-iZ%J6Ir8{a6MYEm`{mbyWM!!WVY{xqx-;Ms5pO(UF&g&? zD0p7Yp?%B?(*~Br^Jcp&rAbrEZ`rNH&TBQFyPH*J;2wBW%#jT_^{f4cWmhuu`U3;y z!vjkmhoWK5abIEa>S3&y2bW!e2o*rI#obMfQ%Zyem6QIP>_|BV_YP}q&|`Xvm#|K1 zjJtU&8z0xnGt^oxvocnem>192yL4_AUNrv*gbIa2Hnbujah|pLPfE8Q2|6CWH_zpk zdzb#6^j+FjwH#Z2t+8d5*>?-d=OF~7mazUlL0GFO!aMv$xmcob;m!k++3#WS=A0$+fP zJaL?RM>VYiybfVSud4JSZk3vHY&UzqWyi1&l0z5@1*@Qpn&-r}H*6KEk2QT|Ga|1< z!i^PG)hqx^>s}|x1I=<1x}z%F5{PP8xC%$;l0}_^$%uJKe@eCU)zJ>US$0 z*k;GX))LKIWB|M2lmlIUr;(jX)g#)=M<4BEtL7KoC=@H_HtJ}!*h@d_ETChOCV(%x4MHQ@FFlv(d%ID%g=#7%i+5gkr-fcJ z4YxG8j*{3H5b>o8n(lD}-)V~Jv8UPsnC87s_$-Eu*0nxvDT|(yOWF>wZ;}AD6N(Er z-gH;KWCS0^!qx*7Y10FbgOw#=Sat`;$+PJ`98^Iurt^uDpP*?N#y@~xv~OAHJA$$b z&bYd(#?Uk=zp3-<4M~m6q>M`0i+Sua;57c=fo)qle>pHv7!Q4aWxhvFl(wgxKHT9w z>8&yA69st#ts>jATd0#C$#1|EL0h`z}=XeqmT`M^B^JdGHk(K=|ve+@wO%>?l!N z@QyMl@iwT_=kJhT^yO5!Ue-I4##p!qaiP zAr%1`duIAMLvmgm8)B4J9nBn4VG63lpfF9lic8l^Xc;g%^j-7-50uu#{I(jp-H2I4 zFVCy8N2_$;0D7Qu@!}i<1ty-@#TxeIFkh{T^3U6T{qb__21aOOU_^}Cmv&-h>h^Hd zQfR=GOXpTlD@3SnLCZI0A-JU_FuNMzKpc~7f;Qe~jT_*M0*sHc&3%AfD0Y<*u|er{_SCIi7(*p~Uw^tvgYvQ5^^4C>O4V{E))rpr zp?v81Fy7b-weyWozH%#TJXe`XdaG+!=Zo(TjY_G|dh&0Gtn3Yb(G(IiUO#`2C(y}r zOwCwBry26Nw97NM4XekMm*>SZKVK35dCjGPjg$1q67O)(U_7O;{TkYS@Yu?G&Fdy@ z1snqHcBUlkpv|TI2!5g$sIgtE;~#{gogWr`DblNL=W|M^ub|rfl1A){;MQh)(x7b3 zbSUu!O2#76VO|Oyg-Uxlsv)N*8(Kw0HQIeZgQ)jBf+jjE)nPqIwbo~q*d{q8JCwH! ztANCJL4$-}MY|x6CP>Wct?hf-V}kb1_rLlYwrVFdg|;5SqwNw81CJ~adz*`o4`=E@ z8+|g6XFQi)!C`qR{^%Y#*UEYU_!E6`jp{y&LiKSy&*qZ=lFEzKX)cCtMe&Towvya_ zT%Op|K^S#6zjdD)9zG}9mYe7fBkW5UB4`g}-+s$m-tX2v(n*QzYd3}FcBBwLR=s$h zW_wbW8Pu_M&IB#IfHJV3B}zFt!|ivM=^D!xKtS@&0?PZ3f(pcnXL>xDHU!Oun_r?1 zNgYgU@ZhN`NixtmO;6ksALqvlhjqQ7KFb`wEAd>qWyk$if94>EGJk<5h5qcNJOHNQ z*;7EWOMJe*pWC)5i*kL<@~u;LHX_T?e$w#8^6(t@^^Z+Z?wxaBBEj~;JS>Vq3F4Hb zSlcR=2f8_epN$;eh6ga?08eqYRS{6u4*8)zUm4;9(x-;?yPPX{YBqb5sQL|6^H!yw zEww@R@-5PguF{|AFrPuQ_oLjLaz0m}pI^aB9TJRWEq@D`u)BfBSPvfrkf73xUPk$N zU60+qf3Wi|5DYFzejzInM;Ylk>jmU-nufH zymLFEZE0=s91z*Q3EG2Hdx`6u3mwmS>mJql$r_%pDy{hLPdAUNZ;n<}MKEucHBJMc zc6;7gogZ+|i<3Pin*0^4QBQrV!nqvPfl5NVb}4vK^+++ut(X`M|1-O2rTrpdR>>61 z%gm(@gqikJ2b6F8+o|ct7u%?&76p7NqA2>^qW}c~dKFdX^oyH0Ht)%TdQccq3UYUc z!*htequi}kBHX=L(C?IP(Fo?P!iqYU91djgXwlrNWS`7nXTCc~?g}o9pH;?IzJi)Am13>^ z>EyLU#BfKet+NPMBhM7DR8K=dhghMA`uYR8STL#1(CCH;oRTtlRM=^P2fA=F1}fOT z-yPA2lKgIe#QX7%qW~+lH?c|QIJ&1pkm@qjA-0RQ=aFJKaT%0y_C#P2<6RiXOq=kt z{h1neCzl5v=FzAjE%5oZOTz*ow1UssV8XK>C)i&0%iE zh^g&^Gh^aL8#|F=GMMA_ga>-r$n3_u!>>3DS*-32DxH*afx{)psgB`(s^-@uYyoE; zp&L8NzzOYSR-Qxm)yuF|qnufba-6dZFiYl>}!3m)*~S~z!k<0or^4Nb0_{@I6bBz{bGM)z3eOR^O9hP%t& zI@{wSq{3Vi5bMnQpwkBxbF3Fg4ugX79guH@J1D*f!<}!rs{vztzfSat&uDKiI8sFv%+P|pid=sR3g7gy-ZP^6qZ-fgkV309 zw`|Z&Py}4G51iy|!~Q1;#jFK-ZLRj_eUVqzf(`x93I9!coB1~A@0+|Nekp#>#qN(d z%((1_|D2-yLX-Qi%n#}AA=~%Y%uP10-kVcSX6tK^-IpBqh_1LPnZ*Mj@F8-*uEZP# zr5P(}cdEw0^_vY_I}yC?Y^m~QnM1_us(YRQ?U)#uE+Gp z?k7~laIsx_#o{nc;5U?i&9JsloCd_(+SIEMlmT|I_RWU+u%l)D?M&fO5yzHos(CKI zs4T@6XK^!M%acL~6K8>EXv|SVw9Q2N2iEN8@H7o3^@{1d93kIN{h5R}b+yV$2`{WV z<6b1rYhRen{iRIQcBGyuA-+;b$~3I_zoSfq|4^n5K2;!hSjBs0b5kOZSHnhh2W*1D z4GkgLO_FGpC3-9G>Ru?m*gMJT7?GoRpGD>?oj0s(gWUE@R%q{)d4{B@FuJy{_zrj1 zG;3q;`&MYJ%S}eV1iMt2T`A!Wld47rbZVQ7@u4g13AH+g1S%bLX)7jqtsmF&s=36H zQAF)WXfopUr`IW$SaR9vq+?LK(o8OXsI0i^)$rZYZslHa%==jo#KM}~@_VP&$|EjY zWist|m%?MYkTjbci+f1K>Koi8QPSHdNyzt;Sb~M(A~XRTC)VDGV_-C;`FEpNc_R*K zDXKBQA%>5lR&mLLbU@AeZQSmohV3wIH<Y3?1~&cHI>e- zv*ic2Ug!FE6aBrxCdI%}Jh-Nv*89nAx zDBG7$7%}Quw71(g&!X->(y}<$4m!;xXP{i{ZYjCcZpUCGaS~^n(+u{W9BOF+TO1}q zXc&}|37ZAfcz-AKza@qApAa(F9Of&jNe1W?*Efri!V#;psE*nUyJkHBI(AVtdmkX$ zhcaDfE^k8{nd_5YXxmipCb<5V>Q}>NmpqOJKe2pUI^1f|@b)3^DQzCME)n!F?CvH5 zOxlNlSuAqk7li0uYX5<0Yw*yeR&n#zAhUh6Q?qKJITu3DH0X@>_SwuB zpFyVry`v^rFDPYy7Dj_#A0(XN!DjdwOmov-PXr{?q})dlljIIoGM=L!-KGxtv*X ztz;|VQq&n0IevuqUBozFQLQi8Dn=Jyv;TC%+GkN735ECF*%@WFr97cRuaYHaQjlxx zs?3aukehd>xEV&zN+xHyIUSCU{af8OV~XPPch>#U<& zKPDoTb>HGR_L8?&r5e8|WLwM)Q&rt=5Y|yY9F6I&W-Pnzcx+u%)vbaiecoX2N>m&kR} zh6-9ACY;k@*6Y_l1a(8Y&`TG6_7Ru47F5j5l0s1U$d z=r%xcvuggZ)#Wntia#0HxgN|D0O(P3L(>e^DkOn{uiN*J`B#-t-jv$b?ywuYv`88N~(S$5D zhisnc)9C?1>X$w&FeHyzA00Jc{XjA>;MrP9mFIkU)@unZ)>_i2=rJC=ApI28)uqBN zI!$Z)P`lWBS2MBxisgt_F@%Zd3#OhqL@|s2A@t=lC>-MND{|jCtYA_h6SG_AmEx)0CpTX$_#V?m(A&Rk84DF&O+-EY-ZvvG-jVaQ z_4=xft>WF@qRLBnhJMYG)3;sl^Dg{A=$3bOAIVT$F9r}|ekt?lpp^cj|$ZbCouz9?U z{>VQjHxZyY>l0S}>jSg0pPmbwKI-;q#-qti-HLk=gP%}Smn<-)g!i*QzI#DEX&3pI2^Gbwac{vkv;X*oQN{Ds|}d5M|0z>6efDHdDTKSadWhl>Mp zb};OBrB52zf8VHa^L_$VXDc&8{9+QVEqVj3PeGt3t|WGh+K-os+~EWF%G-En*}%=P@^bGvt#NI;@9 zH~%_=pmFoSjx_yjNxcUW_Z8VS#A+UuhcIe1C`gE=}Z`a_z0aE*<< z?>N!MO}`1_F2q?598Vv?>93!F$UD|J5f@=M3ylGCMkeytWC7a&S3-!D z+y2q#DQT!q;xyLX^WK=vblO3y=Zkf8ca=_>Ya(}6i>^=4yB{j(Pak$$ZyNtF-D#_n zs3M3^#r-z+vFRxKNEiti4&j5utnkt2pAHHu(g7SvxmeqmD-nldLUCLYqGbVlro73I zbl;rkng!ML^m**Jt#E%4q{3l4xH^yf`Mb(AENuRCbT>;Ft=(~Hc8~IZlA(rx~bUYh&M^Ly^l7|^T*ElX+V}>zE9m2B+sL`t( z@;vt3+Lu$~jw%rd2hG_In`em%qdU*8#Xx?9c_PHm*wPUbrEPw)XLPV^F zHStF6Yuh4Hw5>u!n8x((-NdpGytzB40NsT3-5jhT>S=nNvmc$m4WV#!&t;Vq zT*bYFO#gCI!DX)tz~}MP981uhhmH!kZo_Q!4MI@Yv}i{430lAhr@zi_CE&)Y5N%c~ zGM1SZGJ{_~Z%sV7KBV$}NbH1AxfHV$!hOvl4|UUw8y)(@Vm>&VC;dYr<~SCxJLvzR z4(P}Hh8602lbb(z;-*LQo?u>H+8z%V^G4CPa(!~{<-_sq^LqvRW+Hcbm>rs^f?Fod zMup@dwXdQ9*h#&>d?o*Mi@IrBslMq@x8>hqHCXH4NAbG3K{2(pSj= zLOWrGQQ@fWOpIrynG*;hs#PUA&Ovxp` z8@D3h^#bF&b@+5ef9^$s1PMp0AcK8yH*wY0S{@)__mzpUa8Xy6Q@g~!cc8E?Uo40h zu(q}e7ft5*g9B#H?C}4l@%L8*KK>6~5N+-O{ueuV@`oM#xzqIlp4Q(iEhtY|{yqO- z^x@HeGIRXDLKFXg@&8k96GZaFF21yaL%&fHo4Y1yH4flWqRq}i_V+_D6M*8HANIYn zveUl@?l}QjOD9Pei?9!!8lb-gqRjMop*Kv49w$te&A4Bm;R2i%a)f}N8Y#yT^E3rP z?Hb8{i~D{O2UMfAGuSf+metgLH5iz+>lr9DhOnPpOq$y=2XgSkg*_E}p-xH7YP&~c zke37Y%zzG%Hq&(TG{uq4o>$1fwv3P?7wtI_wzffS7UzO#9RJ>TzS(=1g2Jv%SS`j+ z15I{6_#U{-*3?Q=4AQnJ%KA0pu?N4z2>R!zkfl?dG5K{wnRJ3sum(f%>PI=6`HIMQ zS@4}v@6Q@wpFl;b(0h{t!lmSqwx8!KwbX-0BiYn@3Q$TP5DtX??(nMgQd)4AsCVGz z8lO(#g!*sMFZooCZ+GUHjek+`QH}Ta#0f@=82ql415ycR`=%6~S?Mh9*W z!=6xxLS6TPS()PnOmnjVbckDCf1m5fb}=~amo-_5DJqd{EcNT1GtCD2B_%(VgRno_ zJui)WvUYzYm=76Yej$=|dKKe6YwuE_6%HsjeXZ32OGP&5r&1fYaf=GjtI9 zp#M3JanFsQ<_~(^Ckl;l}!xZJO8(tFI^AGt4ZGU z>7E_KL5gtGR#n@Hi#$muUu-7->m*7*Bo#8$YyGHT*DUe#`oJAgtkyS+!g-pow+Dqj zF%8agZ4ff|^PMEojAT93f1g`U`Q(xI@o<5{)mg@XZdC``$L_=UkWT~bKG$mRqvz@x zwv|`?-7Y={9Kou##Gs3G(yc%sm|!t~t0#eP`$vHGT2Whl$8qS0ifHOr%4h$Ux+M4l zZ;Hhuly-+|rleK#X(lgwl1Ec&-A^q71!wa+Ej07Ztlo|Fr_PS{ zqWZi%IgOgM=GonzoR`Jf${dQ~Z`@M9x#j!Y5S}5cUbVHIh(r@E;wer)6$y;T(+4qq zs1v5<_i?t|0t0sW&x+t-?mox8rej+Qbakeb2NP|a$?@b2OJz7) zsQpFlS2#Gl&?dp%j&It=1|zCwGwe|hXm@=r2~ z9v^ZxZS^1+)Ur1`lb|ai)7?C~VNTHeH~H5?sCb6VAPtec?e_vX4XO!vU@UO(-^8~> zOV~R`m0QER+&-P4s5OFrufKlu-)2o@0sl9t{GZ(at7g_$BH|UE{qGt0e%UdTVL6DH z?LIKXnf3Yp8?}+L`usx$`ahRq%N-u*;XD7A0Kw5r+r1F`Z^co*?|i5D|IWhTgEn%b zW;WCJAAOQf%wsBf ztJnEXLX_$tW5NZ&{?@sN&mZp71SX|fW>AbHE*Jm~#el)3L2jRO8N^YjNyi%({&|ky zzo<%$Yp1zF*C`K=A4nTm4@S;;H}dJv6Qzc#w`8m38kEUOURH`G&R3KMJ<;f4;>vWm zwB^Abso~GuQ?n?_cHnU_1cIU|mYEfE)i90EYHUwfiT)8y_6GlmCY#6k^cV8}IfFE( zOtsR6H3 z*tUxM1bgD(KOS2h>*9u!FuRlvFh9P4$#KW~6+I|R*hPmO;brr9jUL@MT&W<^CS}6B zjn9m<=dT8J_L`822~eG|xey!|HcTUq^+i`egIs*}_fu*JIa7`5&LRDduParhL2fr| zY)VD&#J48>#vr+v#NPYrkQUfVwp^b7(Mc$>{!euh5u{E+{;y7g+WAK(nQs0W-7@jc z$!qKAsJVAN_r@>69uU=M2hYwSootDwF31vN~BxsnA0-tNx>O+zfrqE{sq|7dbQKP7aRCKb`9DLtetE4}`!f0@s{%3}@Sl6Rixb-Ikb{W~7jSAGHCX6F0nC8}ke_`l zqa6tB7B%xMKREu>+NScfG~K&zxde#x`G7=LW3qvcsy_amnAsO!e@^_Ppoo{>uja~G z-mZN1o^o=L)&)O=(}UM8MPWgpTUA+Jg^#m`z`JV_v4sgf65E_rcIN`-gxjNag}(P? zkaisrx>D2N1Z*EmXP}U-^{@TNxeYL0Fp&pOz)O)W@2)Q{AWHjJg#Ol&Xj>k2!?Adc z)cYx+t1|%vu@uskjc{C$doS%lQ<>4{*@8ND9f&YS1GQ{pj>^3A485|S9F^i2$HIo^ zGPAR#eNnv(su??Ax?pI_T=!*SpPPqq-(FipXyp` zuX1)p%C32twzK;#vBa-?6Sc&%&mP*2#Vhf({!~eXx3Xj)NWn6Lx+UEJIib{dOE%&#)K_xY(UdF0C-c$6F zmi`azt7U(MlqMD@m%bN+n|7~do@`qhspvzWV133E@+)_|cm{D*aOOtLRZnH$7n#PU z&}+PE08W*JFQVQlCS`|?+^+Q`eL;p~=TN91pop&6V({cbtiPLJ3VI)o!W|mn z>la8rzLuh$B<$FutJgJM`xfJn+_k92x_OW*ha~uSbsDO7N_9^Ig}-9k_X04NFE9z~ zBh7dK)#;2Q0DKb_ySNHpJZ%KQL4m)-ZedL~`**zjF-l2GUYOAzH@~iU!4U*IG>0LD zh*?JzEPsx&Yi$L=t$5vbBSq_9eeyxqG!s}ezflDV-}JmKIDinsvhxbru6})Qb!=?) zoBm_S%(Ycp1xk#B`&Oi#0GCt#p-i7{m}&s>JxrHek0`S8tD5w99_W7$F2ue@%2wtz zkM>vC9f(^KGi8~?hXoM|>nu8^iuM~g8ljeNRU+&SS<)$^4s$to%HG(LdJ(7DJzIjS zAXZ|SlSj4LWaPE4W;-ZoNlvqk*O6w{HiVh%BF6ZW={N}e?Oa?TgL(hj%yhNLvC>BS zqXs0COYhKRb2zi8Ui&=oGQwNgljPDC@`|Yh5FUN3UT5=!h8GvNV zsmH3!Wpcn7Lzd4%HqZJ8d%dCRE*TEte@M`sr%+QVn_?s<1^fIRTQzBeV&306bS(xpC_wKGzz%A8LbdPG74iSd z31jziLQ4caaz;GK{=PrFUg`J}u|ccDDT$2JWWock7v&|=GJeBPG!kQ}*Vqrb&0$K) zQR)i!aE$TrGiERT=<5-MMxM|B>&CMwlhilqIMofWH$SzP6cv9oSw3eg}UzT_C~u9mO*#6wSO>>wT>xS>zq`X zD>MGyX87+GRovX1XN6+f_ZHQvgQSkK-s6*(;ZlvrF9s--QJsAfd=sB7RYke|y(FGk z9$R8^q|2kxvC+qn5~-CBAN9;;%gm(_Jq$;Bc11s>O2u#@U4!y$E+L-r#AuFA9H5e` zwrjl(wu&6FtshyD?5?eOcSA@G#S_&c&h;M+h4gBj`QU{)Olvq&T_VSG`PsU0MuP8Z zUXkw8FHg+3M%;2H2&{et3GamqR^Jd zV>yqrGk7X{JneYlMAwGhQ+(3zMHvG5Z1z`Rp4-JbR&t)!SQ1pE>1Z1j>LI- zwXh-DA>g&AbI$ZuP}y#d>z%ihH?PyYgCxW)PvDQr^qBYBdzWsXKcoVP5%p-4=lER@ za;TxveF|ML3eY?THq`i}8b}6ym3wUTrQ6K7C+t@)!@#=<2CcGKp-l4{Xt6gJ%M0#a z{O*S{XWtx;=Z>tEPQbc0xTT*a7HOXpj)r|HS8>#f@Yi50rajnWZVT6%*nZZ&XdNwZ zPGfq}oo7>dvJ84xAmHTTgmM7k82r0H5;*o)?cJVG5!(JrZJp_RNjutK(Q)HRmV5qeqT! zYL?u;AT&*vO1KVRj;bwS!+GApja`#$f+80qGrpvGJzMiEIL)L|xL>hIb9Tr2+B_H5&R8v!tO+Y*&irGT71G&QY4ekAw z*obK3!?MDy7z^xD2v`WRe$%kX+4HB96gWr<9G~}N{nb^bO(WEb)mA71Js9VnP)Ugu zkwskb>!tFQX8$<5LP{#~l`jZ83jka0_H5M z)W$Gj#sfw2P~U1;99I?SB)XYy9f-9Nw5B7wT8mmFUp~J4F@+EMYZ))rFFR{mc+c$4 z{-dOXe(|21y*}SPs)j5L)b~J)kfTpj4_-ZHKV+8UA=)Z0($CXvTJoiPr@Y<~@rs@V z<3KOu@!i0?1o~oua3TDOfcL@(0xkv9PjP*-C1E;7RiAX&co&%el~G8GB3hAHtx(I+ zmJ9~{HpfuuuIabickLA3nhC5qXZZ4y@s=bm-i>-S$;4LJy+#gQ7{*pMf@TSE*xfEg zdO@Y1o^FCP`bX1?gG?U~uKl-F`@%&WNACYp`QI_j7%JKbS>FkRiF) zcbL4+x8vEe7_XxA|AQga4?X^~V7qm-eAS~qvNT`EpX5g=Mj&nn-oluEs!vap)@=zE zX0&ct<$eeaDb3Cw{WRWvpN@{)7fkx8(?v;Ey<8#75h`PnM2gko=+^L5=+yr&5rraHUUCe-H z=~%uJ-v4oomXu8ioo*8xpQg+>4u|jCt<4pLC+mYSv3=GEIWOH}j6wwsl6AHpBfras zT&@eh_6Lmx%uISt|Mh_0(e#QinKUfx*O*?GVV-s)l zGK5IKoKI0zRttF@@h6IQ(Kqj8UN4Dpv$8=Ki+UvTbf|y{SE+~vTZ<&W5H;)P(c3h| zr^SIo=<(LEUBULaGtyA1Uzbluzfsq%2_eH6_D7sa>`TKhIF@JDyxW;|@E{$p>Bymk zx|utq3mh$KZL()}%NxS5cX!t8pb}BAsy^2XGMmn-A{$A8%kw{y%o{QHX7+$);euPB zXm(Zm@IRmfDr!JfLr$JWHJ$;dDvL&el7k8mApd_Lk`zNx(2O;soXWqBO|uZ_z@r9m zLjV52Ws>9utCIi31Yl?w?y;T1Bc-!Yt^203K$C ADF6Tf literal 0 HcmV?d00001 diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json new file mode 100644 index 0000000000..13bb3070da --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json @@ -0,0 +1,154 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "endpoint": { + "type": "string", + "metadata": { + "description": "Your account endpoint" + } + }, + "key": { + "type": "securestring", + "metadata": { + "description": "Your account key" + } + }, + "throughput": { + "type": "string", + "metadata": { + "description": "The throughput for the container." + } + }, + "documents": { + "type": "string", + "metadata": { + "description": "The amount of items to insert." + } + }, + "parallelism": { + "type": "string", + "metadata": { + "description": "The degree of parallelism." + }, + "defaultValue": "-1" + }, + "cleanUpOnFinish": { + "type": "string", + "metadata": { + "description": "Whether to delete the container after the benchmark is run." + }, + "defaultValue": "false" + }, + "containerGroupName": { + "type": "string", + "metadata": { + "description": "Name for the container group" + }, + "defaultValue": "CosmosDBBenchmark" + }, + "containerName": { + "type": "string", + "metadata": { + "description": "Name for the container" + }, + "defaultValue": "cosmosdbsdkperf" + }, + "volumeName": { + "type": "string", + "metadata": { + "description": "Name for the gitRepo volume" + }, + "defaultValue": "cosmosdbsdk" + }, + "port": { + "type": "string", + "metadata": { + "description": "Port to open on the container and the public IP address." + }, + "defaultValue": "80" + }, + "cpuCores": { + "type": "string", + "metadata": { + "description": "The number of CPU cores to allocate to the container." + }, + "defaultValue": "4" + }, + "memoryInGb": { + "type": "string", + "metadata": { + "description": "The amount of memory to allocate to the container in gigabytes." + }, + "defaultValue": "8" + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Location for all resources." + } + } + }, + "variables": {}, + "resources": [ + { + "name": "[parameters('containerGroupName')]", + "type": "Microsoft.ContainerInstance/containerGroups", + "apiVersion": "2020-11-01", + "location": "[parameters('location')]", + "properties": { + "containers": [ + { + "name": "[parameters('containerName')]", + "properties": { + "image": "mcr.microsoft.com/dotnet/sdk:6.0", + "ports": [ + { + "port": "[parameters('port')]" + } + ], + "resources": { + "requests": { + "cpu": "[parameters('cpuCores')]", + "memoryInGB": "[parameters('memoryInGb')]" + } + }, + "volumeMounts": [ + { + "name": "[parameters('volumeName')]", + "mountPath": "/mnt/gitrepos/", + "readOnly": false + } + ], + "command": [ + "/bin/bash", + "-c", + "[concat('cd /mnt/gitrepos/azure-cosmos-dotnet-v3/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate;export ENDPOINT=\"', parameters('endpoint'),'\";export KEY=\"', parameters('key'),'\";export THROUGHPUT=\"', parameters('throughput'),'\";export DOCUMENTS=\"', parameters('documents'),'\";export PARALLELISM=\"', parameters('parallelism'),'\";export CLEANUPFINISH=\"', parameters('cleanUpOnFinish'),'\";chmod +x run.sh;./run.sh')]" + ] + } + } + ], + "osType": "Linux", + "restartPolicy": "Never", + "ipAddress": { + "type": "Public", + "ports": [ + { + "protocol": "TCP", + "port": "[parameters('port')]" + } + ] + }, + "volumes": [ + { + "name": "[parameters('volumeName')]", + "gitRepo": { + "repository": "https://github.com/Azure/azure-cosmos-dotnet-v3" + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json new file mode 100644 index 0000000000..f8b1983b33 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json @@ -0,0 +1,39 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "endpoint": { + "value": "" + }, + "key": { + "value": "" + }, + "throughput": { + "value": "" + }, + "documents": { + "value": "" + }, + "parallelism": { + "value": "-1" + }, + "cleanUpOnFinish": { + "value": "false" + }, + "containergroupname": { + "value": "CosmosDBBenchmark" + }, + "containername": { + "value": "cosmosdbsdkperf" + }, + "volumename": { + "value": "cosmosdbsdk" + }, + "cpuCores": { + "value": "4" + }, + "memoryInGb": { + "value": "8" + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh new file mode 100644 index 0000000000..3b8855a95f --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh @@ -0,0 +1,2 @@ +cd .. +dotnet run -c Release -e ${ENDPOINT} -k ${KEY} -t ${THROUGHPUT} -n ${DOCUMENTS} --pl ${PARALLELISM} --CleanupOnFinish ${CLEANUPFINISH} -w InsertV2BenchmarkOperation \ No newline at end of file From 83bad122481303a66e7a1ae9a84ec9fbdb561aee Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Fri, 26 May 2023 13:51:46 -0400 Subject: [PATCH 122/337] Update README.md (#3875) URL typo. --- .../Tools/Benchmark/ARMTemplate/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md index f829b79bc6..7821e1eefd 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md @@ -10,7 +10,7 @@ For the below steps, you will **need an Azure Subscription**. Just click in the **Deploy to Azure button** and it will guide you into automatically configuring, deploying, and running the benchmark. -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-cosmos-dotnet-v3%2Fmaster%2FARMBenchmarking%2FMicrosoft.Azure.Cosmos.Samples%2FTools%2FBenchmark%2FARMTemplate%2FbenchmarkTemplate.json) +[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-cosmos-dotnet-v3%2Fmaster%2FMicrosoft.Azure.Cosmos.Samples%2FTools%2FBenchmark%2FARMTemplate%2FbenchmarkTemplate.json) Please populate the `endpoint` and `key` for your Azure Cosmos DB account. You can [obtain these from the Azure Portal or through CLI](https://learn.microsoft.com/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key#primary-keys). From c5ef47e1e70fab32ff1aa81b370607d8b9b7fbb8 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Sat, 27 May 2023 23:40:23 +0530 Subject: [PATCH 123/337] moved to new file (#3876) --- docs/SdkDesign.md | 29 ----------------------------- docs/observability.md | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 29 deletions(-) create mode 100644 docs/observability.md diff --git a/docs/SdkDesign.md b/docs/SdkDesign.md index 62d4a751f7..f3f2ec1581 100644 --- a/docs/SdkDesign.md +++ b/docs/SdkDesign.md @@ -186,32 +186,3 @@ flowchart LR ConsistencyWriter --> TCPClient ``` -## Distributed Tracing (Preview) - -For detail about usage of this feature, please see the [Azure Cosmos DB SDK observability](https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/sdk-observability?tabs=dotnet) - -```mermaid -flowchart TD - classDef orange fill:#f96 - classDef blue fill:#6fa8dc - subgraph ClientContextCore - OpenTelemetryRecorderFactory --> CheckFeatureFlag{isDistributedTracing Enabled?} - CheckFeatureFlag --> |Yes| CreateActivity(Start an Activity or Child activity with specific kind Using DiagnosticScope
and preloaded attributes like containerName, databaseName, operationType) - CreateActivity --> HandlerPipeline - GetResponse --> TriggerDispose(Trigger Dispose of Disagnostic Scope) - TriggerDispose --> CheckLatencyThreshold{Is high latency/errored response?} - CheckLatencyThreshold -- Yes --> GenerateTraceEvent(Generate Warning or Error Trace Event With Request Diagnostics) --> StopActivity - CheckLatencyThreshold -- No --> StopActivity - StopActivity --> SendResponse(Send Response to Caller):::blue - end - OperationRequest[Operation Request]:::blue --> ClientContextCore - subgraph Application - OperationCall(User Application):::orange - end - OperationCall(User Application):::orange --> OperationRequest - CheckFeatureFlag --> |No| HandlerPipeline - HandlerPipeline --> OtherLogic(Goes through TCP/HTTP calls
based on Connection Mode):::blue - OtherLogic --> GetResponse(Get Response for the request) - SendResponse --> OperationCall - -``` \ No newline at end of file diff --git a/docs/observability.md b/docs/observability.md new file mode 100644 index 0000000000..b74b55cd21 --- /dev/null +++ b/docs/observability.md @@ -0,0 +1,36 @@ +# .NET SDK Observability Feature Design + +## Distributed Tracing (Preview) + +**Source to capture operation level activities**: _Azure.Cosmos.Operation_\ +**Source to capture event with request diagnostics** : _Azure-Cosmos-Operation-Request-Diagnostics_ + +For detail about usage of this feature, please see the [Azure Cosmos DB SDK observability](https://learn.microsoft.com/azure/cosmos-db/nosql/sdk-observability?tabs=dotnet) + +```mermaid +flowchart TD + classDef orange fill:#f96 + classDef blue fill:#6fa8dc + subgraph ClientContextCore + OpenTelemetryRecorderFactory --> CheckFeatureFlag{isDistributedTracing Enabled?} + CheckFeatureFlag --> |Yes| CreateActivity(Start an Activity or Child activity
with preloaded attributes) + CreateActivity --> HandlerPipeline{Handler Pipeline} + GetResponse --> TriggerDispose(Trigger Dispose of Diagnostic Scope) + subgraph Dispose + TriggerDispose --> CheckLatencyThreshold{Is high latency/errored response?} + CheckLatencyThreshold -- Yes --> GenerateEvent(Generate Warning or Error Event With Request Diagnostics) --> StopActivity + CheckLatencyThreshold -- No --> StopActivity + end + StopActivity --> SendResponse(Send Response to Caller):::blue + end + OperationRequest[Operation Request]:::blue --> ClientContextCore + subgraph Application + OperationCall(User Application):::orange + end + OperationCall(User Application):::orange --> OperationRequest + CheckFeatureFlag --> |No| HandlerPipeline + HandlerPipeline --> OtherLogic(Goes through TCP/HTTP calls
based on Connection Mode):::blue + OtherLogic --> GetResponse(Get Response for the request) + SendResponse --> OperationCall + +``` \ No newline at end of file From ee7f86ddd2ea141103c0d57c82e8ff429cd1f6ed Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 30 May 2023 20:16:32 +0530 Subject: [PATCH 124/337] Direct Package Upgrade 3.31.0: Refactors code to make compatible with latest direct (#3877) * upgrade to 3.31.0 * add more regions * enable dt for operations * updated contract file --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 7 ++++++- Microsoft.Azure.Cosmos/src/Regions.cs | 10 ++++++++++ .../src/Routing/GatewayAddressCache.cs | 2 +- .../Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs | 4 ++-- .../Contracts/DotNetSDKAPI.json | 10 ++++++++++ 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ef1ffd2e01..52e815227a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.34.0 3.34.0 preview - 3.30.8 + 3.31.0 2.0.1 2.0.1 preview diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 451166618d..068bb5b857 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -6644,6 +6644,11 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory } else { + Documents.Telemetry.DistributedTracingOptions distributedTracingOptions = new () + { + IsDistributedTracingEnabled = this.isDistributedTracingEnabled + }; + StoreClientFactory newClientFactory = new StoreClientFactory( this.ConnectionPolicy.ConnectionProtocol, (int)this.ConnectionPolicy.RequestTimeout.TotalSeconds, @@ -6667,7 +6672,7 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory addressResolver: this.AddressResolver, rntbdMaxConcurrentOpeningConnectionCount: this.rntbdMaxConcurrentOpeningConnectionCount, remoteCertificateValidationCallback: this.remoteCertificateValidationCallback, - isDistributedTracingEnabled: this.isDistributedTracingEnabled); + distributedTracingOptions: distributedTracingOptions); if (this.transportClientHandlerFactory != null) { diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index 853bc48267..666ec0435b 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -349,5 +349,15 @@ public static class Regions /// Name of the Azure Poland Central region in the Azure Cosmos DB service. ///
public const string PolandCentral = "Poland Central"; + + /// + /// Name of the Azure Malaysia South region in the Azure Cosmos DB service. + /// + public const string MalaysiaSouth = "Malaysia South"; + + /// + /// Name of the Azure Italy North region in the Azure Cosmos DB service. + /// + public const string ItalyNorth = "Italy North"; } } diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index d99be609ea..182243ec40 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -85,7 +85,7 @@ public GatewayAddressCache( GatewayAddressCache.ProtocolString(this.protocol)); this.openConnectionsHandler = openConnectionsHandler; - this.isReplicaAddressValidationEnabled = Helpers.GetEnvironmentVariableAsBool( + this.isReplicaAddressValidationEnabled = Helpers.GetEnvironmentVariable( name: Constants.EnvironmentVariables.ReplicaConnectivityValidationEnabled, defaultValue: false); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 366cc68811..4773c7de96 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -548,11 +548,11 @@ internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() // Open Telemetry Listener Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() // use any exporter here - .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") .Build(); // Custom Listener - Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", "Azure-Cosmos-Operation-Request-Diagnostics"); return Util.TestListener; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 074be1ee37..e5b95a7ed9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6680,6 +6680,11 @@ "Attributes": [], "MethodInfo": "System.String GermanyWestCentral;IsInitOnly:False;IsStatic:True;" }, + "System.String ItalyNorth": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String ItalyNorth;IsInitOnly:False;IsStatic:True;" + }, "System.String JapanEast": { "Type": "Field", "Attributes": [], @@ -6710,6 +6715,11 @@ "Attributes": [], "MethodInfo": "System.String KoreaSouth;IsInitOnly:False;IsStatic:True;" }, + "System.String MalaysiaSouth": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String MalaysiaSouth;IsInitOnly:False;IsStatic:True;" + }, "System.String NorthCentralUS": { "Type": "Field", "Attributes": [], From 89cc257324d8caf8fe9826c7dfebf88add7ad42c Mon Sep 17 00:00:00 2001 From: jiajunpeng-msft <32749342+jiajunpeng-msft@users.noreply.github.com> Date: Wed, 31 May 2023 09:12:59 -0700 Subject: [PATCH 125/337] [Preview] Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions (#3836) * Integrated cache: Add BypassIntegratedCache to DedicatedGatewayRequestOptions Currently, integrated cache is used by default for Dedicated Gateway. Customers cannot skip cache for particular requests or data unless they shift to multi-tenant Gateway,which will lose the benefits of Dedicated Gateway. For customers to have more control over integrated cache, we're introducing a new "RequestOption" called "BypassIntegratedCache". This option will allow the customer to decide whether to use integrated cache for each request or not. If this value is set to true, the item/query will be served from backend and won't be cached in Dedicated Gateway. * Move this feature to public preview * Address comments 1. Add more tests 2. Add more detail and example code for BypassIntegratedCache * Revert changes in EncryptionCustomAPI --------- Co-authored-by: Jiajun Peng Co-authored-by: Matias Quaranta --- .../src/RequestOptions/ItemRequestOptions.cs | 1 + .../src/RequestOptions/QueryRequestOptions.cs | 1 + .../DedicatedGatewayRequestOptions.cs | 42 +++++++++ .../Contracts/DotNetPreviewSDKAPI.json | 25 +++++ .../DedicatedGatewayRequestOptionsTests.cs | 94 +++++++++++++++++++ 5 files changed, 163 insertions(+) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Resource/Settings/DedicatedGatewayRequestOptionsTests.cs diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/ItemRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/ItemRequestOptions.cs index 59b5b245f7..d807f42f57 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/ItemRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/ItemRequestOptions.cs @@ -151,6 +151,7 @@ internal override void PopulateRequestOptions(RequestMessage request) } DedicatedGatewayRequestOptions.PopulateMaxIntegratedCacheStalenessOption(this.DedicatedGatewayRequestOptions, request); + DedicatedGatewayRequestOptions.PopulateBypassIntegratedCacheOption(this.DedicatedGatewayRequestOptions, request); RequestOptions.SetSessionToken(request, this.SessionToken); base.PopulateRequestOptions(request); diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 8711836191..8ce4761c31 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -264,6 +264,7 @@ internal override void PopulateRequestOptions(RequestMessage request) } DedicatedGatewayRequestOptions.PopulateMaxIntegratedCacheStalenessOption(this.DedicatedGatewayRequestOptions, request); + DedicatedGatewayRequestOptions.PopulateBypassIntegratedCacheOption(this.DedicatedGatewayRequestOptions, request); request.Headers.Add(HttpConstants.HttpHeaders.PopulateQueryMetrics, bool.TrueString); diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs index e3b7dccf3f..9ca854388c 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs @@ -23,6 +23,40 @@ public class DedicatedGatewayRequestOptions /// public TimeSpan? MaxIntegratedCacheStaleness { get; set; } + /// + /// Gets or sets if bypass the integrated cache or not associated with the request in the Azure CosmosDB service. + /// When set this value to true, the request will not be served from the integrated cache, and the response will not be cached either. + /// + /// Default value is false. + /// + /// + /// + /// + /// +#if PREVIEW + public +#else + internal +#endif + bool? BypassIntegratedCache { get; set; } + internal static void PopulateMaxIntegratedCacheStalenessOption(DedicatedGatewayRequestOptions dedicatedGatewayRequestOptions, RequestMessage request) { if (dedicatedGatewayRequestOptions?.MaxIntegratedCacheStaleness != null) @@ -37,5 +71,13 @@ internal static void PopulateMaxIntegratedCacheStalenessOption(DedicatedGatewayR request.Headers.Set(HttpConstants.HttpHeaders.DedicatedGatewayPerRequestCacheStaleness, cacheStalenessInMilliseconds.ToString(CultureInfo.InvariantCulture)); } } + + internal static void PopulateBypassIntegratedCacheOption(DedicatedGatewayRequestOptions dedicatedGatewayRequestOptions, RequestMessage request) + { + if (dedicatedGatewayRequestOptions != null && dedicatedGatewayRequestOptions.BypassIntegratedCache.HasValue && dedicatedGatewayRequestOptions.BypassIntegratedCache.Value) + { + request.Headers.Set(HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache, true.ToString(CultureInfo.InvariantCulture)); + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 08d0d65a7e..de49584da2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -377,6 +377,31 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.Nullable`1[System.Boolean] BypassIntegratedCache": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Boolean] BypassIntegratedCache;CanRead:True;CanWrite:True;System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Boolean] get_BypassIntegratedCache()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Fluent.ChangeFeedPolicyDefinition;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Resource/Settings/DedicatedGatewayRequestOptionsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Resource/Settings/DedicatedGatewayRequestOptionsTests.cs new file mode 100644 index 0000000000..b0f5cd2ea0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Resource/Settings/DedicatedGatewayRequestOptionsTests.cs @@ -0,0 +1,94 @@ +namespace Microsoft.Azure.Cosmos.Tests.Resource.Settings +{ + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class DedicatedGatewayRequestOptionsTests + { + [TestMethod] + public void BypassIntegratedCacheHeaderIsSetWhenTrue() + { + DedicatedGatewayRequestOptions dedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions + { + BypassIntegratedCache = true + }; + + ItemRequestOptions itemRequestOptions = new ItemRequestOptions + { + DedicatedGatewayRequestOptions = dedicatedGatewayRequestOptions + }; + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + DedicatedGatewayRequestOptions = dedicatedGatewayRequestOptions + }; + + RequestMessage itemRequestMessage = new RequestMessage(); + RequestMessage queryRequestMessage = new RequestMessage(); + + itemRequestOptions.PopulateRequestOptions(itemRequestMessage); + queryRequestOptions.PopulateRequestOptions(queryRequestMessage); + + + Assert.IsNotNull(itemRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + Assert.IsNotNull(queryRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + + Assert.AreEqual("True", itemRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + Assert.AreEqual("True", queryRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + } + + [TestMethod] + public void BypassIntegratedCacheHeaderIsNotSetWhenFalse() + { + DedicatedGatewayRequestOptions dedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions + { + BypassIntegratedCache = false + }; + + ItemRequestOptions itemRequestOptions = new ItemRequestOptions + { + DedicatedGatewayRequestOptions = dedicatedGatewayRequestOptions + }; + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + DedicatedGatewayRequestOptions = dedicatedGatewayRequestOptions + }; + + RequestMessage itemRequestMessage = new RequestMessage(); + RequestMessage queryRequestMessage = new RequestMessage(); + + itemRequestOptions.PopulateRequestOptions(itemRequestMessage); + queryRequestOptions.PopulateRequestOptions(queryRequestMessage); + + + Assert.IsNull(itemRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + Assert.IsNull(queryRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + } + + [TestMethod] + public void BypassIntegratedCacheHeaderIsNotSetWhenNotSet() + { + ItemRequestOptions itemRequestOptions = new ItemRequestOptions + { + DedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions() + }; + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + DedicatedGatewayRequestOptions = new DedicatedGatewayRequestOptions() + }; + + RequestMessage itemRequestMessage = new RequestMessage(); + RequestMessage queryRequestMessage = new RequestMessage(); + + itemRequestOptions.PopulateRequestOptions(itemRequestMessage); + queryRequestOptions.PopulateRequestOptions(queryRequestMessage); + + + Assert.IsNull(itemRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + Assert.IsNull(queryRequestMessage.Headers[HttpConstants.HttpHeaders.DedicatedGatewayPerRequestBypassIntegratedCache]); + } + } +} From 327422b02180029899d283ee385d3f7e2abeb24b Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Thu, 1 Jun 2023 22:05:15 +0530 Subject: [PATCH 126/337] Client Encryption: Adds Microsoft.Azure.Cosmos compatibility to version 3.34.0 (#3874) * chaging Microsoft.Azure.Cosmos support version * resolved merge conflicts --- Directory.Build.props | 4 ++-- Microsoft.Azure.Cosmos.Encryption/changelog.md | 10 ++++++++++ .../src/Microsoft.Azure.Cosmos.Encryption.csproj | 4 ++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 52e815227a..7eecd3c8e2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,8 +4,8 @@ 3.34.0 preview 3.31.0 - 2.0.1 - 2.0.1 + 2.0.2 + 2.0.2 preview 1.0.0-preview05 1.1.0-preview3 diff --git a/Microsoft.Azure.Cosmos.Encryption/changelog.md b/Microsoft.Azure.Cosmos.Encryption/changelog.md index a5e7101074..a8edf3441d 100644 --- a/Microsoft.Azure.Cosmos.Encryption/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption/changelog.md @@ -3,6 +3,16 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [2.0.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.2) - 2023-06-01 + +#### Added +- [#3874](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3874) Adds support for Microsoft.Azure.Cosmos up to 3.34.0. + +### [2.0.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.2-preview) - 2023-06-01 + +#### Added +- [#3874](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3874) Adds support for Microsoft.Azure.Cosmos 3.34.0-preview. + ### [2.0.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.1) - 2023-03-11 #### Added diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj index f58b171cd5..94e93aa6fe 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj @@ -28,11 +28,11 @@ - + - + From 3e3bbe5d53bd771ead625f5aee6e55cca9dd8764 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Thu, 1 Jun 2023 15:03:04 -0700 Subject: [PATCH 127/337] CosmosClient: Fixes missing Trace when converting HTTP Timeout to 503 (#3866) * Added tracing when converting HTTP Timeout to 503 * Fixed tracing when converting HTTP Timeout to 503 * Resolved PR comments * Using ITrace as part of ClientSideRequestStatisticsTraceDatum * Refactoring * Test update * Unit tests fix --- .../src/GatewayAccountReader.cs | 2 +- .../src/Handler/TransportHandler.cs | 2 +- .../src/HttpClient/CosmosHttpClientCore.cs | 4 + .../src/Routing/ClientCollectionCache.cs | 2 +- .../src/Routing/PartitionKeyRangeCache.cs | 2 +- .../ClientSideRequestStatisticsTraceDatum.cs | 13 ++- .../RegionContactedInDiagnosticsBenchmark.cs | 2 +- .../TraceWriterBaselineTests.TraceData.xml | 6 +- .../CosmosHttpClientCoreTests.cs | 92 ++++++++++++------- .../GatewayAccountReaderTests.cs | 23 +++-- .../GatewayStoreModelTest.cs | 35 ++++--- ...entSideRequestStatisticsTraceDatumTests.cs | 6 +- .../Tracing/ContactedRegionsTests.cs | 2 +- .../Tracing/TraceTests.cs | 2 +- .../Tracing/TraceWriterBaselineTests.cs | 6 +- 15 files changed, 121 insertions(+), 78 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs b/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs index 2754dfaa40..5413103fee 100644 --- a/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs +++ b/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs @@ -49,7 +49,7 @@ await this.cosmosAuthorization.AddAuthorizationHeaderAsync( using (ITrace trace = Trace.GetRootTrace("Account Read", TraceComponent.Transport, TraceLevel.Info)) { - IClientSideRequestStatistics stats = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace.Summary); + IClientSideRequestStatistics stats = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); try { diff --git a/Microsoft.Azure.Cosmos/src/Handler/TransportHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/TransportHandler.cs index e524214976..7baf8a7254 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/TransportHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/TransportHandler.cs @@ -93,7 +93,7 @@ internal async Task ProcessMessageAsync( DocumentServiceRequest serviceRequest = request.ToDocumentServiceRequest(); - ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, request.Trace.Summary); + ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, request.Trace); serviceRequest.RequestContext.ClientRequestStatistics = clientSideRequestStatisticsTraceDatum; //TODO: extrace auth into a separate handler diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs index 0fde01afb5..c29c3a5b94 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs @@ -16,6 +16,7 @@ namespace Microsoft.Azure.Cosmos using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; + using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Collections; @@ -361,9 +362,11 @@ private async Task SendHttpHelperAsync( } catch (Exception e) { + ITrace trace = NoOpTrace.Singleton; if (clientSideRequestStatistics is ClientSideRequestStatisticsTraceDatum datum) { datum.RecordHttpException(requestMessage, e, resourceType, requestStartTime); + trace = datum.Trace; } bool isOutOfRetries = CosmosHttpClientCore.IsOutOfRetries(timeoutPolicy, startDateTimeUtc, timeoutEnumerator); @@ -394,6 +397,7 @@ private async Task SendHttpHelperAsync( ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), SubStatusCode = SubStatusCodes.TransportGenerated503 }, + trace: trace, innerException: e); } diff --git a/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs b/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs index 30ece5015b..530bbfceb5 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs @@ -186,7 +186,7 @@ private async Task ReadCollectionAsync( { headers.XDate = Rfc1123DateTimeCache.UtcNow(); - request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace.Summary); + request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); if (clientSideRequestStatistics == null) { childTrace.AddDatum( diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs index 4373d61f56..d9e2854b2b 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs @@ -316,7 +316,7 @@ private async Task ExecutePartitionKeyRangeReadChangeFe } request.Headers[HttpConstants.HttpHeaders.Authorization] = authorizationToken; - request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace.Summary); + request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); if (clientSideRequestStatistics == null) { childTrace.AddDatum("Client Side Request Stats", request.RequestContext.ClientRequestStatistics); diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs index 10845f133f..def12c8262 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs @@ -33,9 +33,8 @@ internal sealed class ClientSideRequestStatisticsTraceDatum : TraceDatum, IClien private IReadOnlyList shallowCopyOfStoreResponseStatistics = null; private IReadOnlyList shallowCopyOfHttpResponseStatistics = null; private SystemUsageHistory systemUsageHistory = null; - public TraceSummary TraceSummary = null; - public ClientSideRequestStatisticsTraceDatum(DateTime startTime, TraceSummary summary) + public ClientSideRequestStatisticsTraceDatum(DateTime startTime, ITrace trace) { this.RequestStartTimeUtc = startTime; this.RequestEndTimeUtc = null; @@ -45,7 +44,7 @@ public ClientSideRequestStatisticsTraceDatum(DateTime startTime, TraceSummary su this.FailedReplicas = new HashSet(); this.RegionsContacted = new HashSet<(string, Uri)>(); this.httpResponseStatistics = new List(); - this.TraceSummary = summary; + this.Trace = trace; } public DateTime RequestStartTimeUtc { get; } @@ -75,6 +74,10 @@ public IReadOnlyDictionary EndpointToAddres public HashSet<(string, Uri)> RegionsContacted { get; } + public ITrace Trace { get; private set; } + + public TraceSummary TraceSummary => this.Trace?.Summary; + public IReadOnlyList StoreResponseStatisticsList { get @@ -502,11 +505,11 @@ public HttpResponseStatistics( if (responseMessage != null) { Headers headers = new Headers(GatewayStoreClient.ExtractResponseHeaders(responseMessage)); - this.ActivityId = headers.ActivityId ?? Trace.CorrelationManager.ActivityId.ToString(); + this.ActivityId = headers.ActivityId ?? System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(); } else { - this.ActivityId = Trace.CorrelationManager.ActivityId.ToString(); + this.ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/RegionContactedInDiagnosticsBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/RegionContactedInDiagnosticsBenchmark.cs index bcf95ba776..0d3d2ffd81 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/RegionContactedInDiagnosticsBenchmark.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/RegionContactedInDiagnosticsBenchmark.cs @@ -42,7 +42,7 @@ private ITrace CreateTestTraceTree() private TraceDatum GetDatumObject(string regionName1, string regionName2 = null) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, Trace.GetRootTrace(nameof(RegionContactedInDiagnosticsBenchmark))); Uri uri1 = new Uri("http://someUri1.com"); datum.RegionsContacted.Add((regionName1, uri1)); if (regionName2 != null) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml index d3b996a0e9..8b6adc1c15 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml @@ -187,7 +187,7 @@ TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); TransportAddressUri uri1 = new TransportAddressUri(new Uri("http://someUri1.com")); TransportAddressUri uri2 = new TransportAddressUri(new Uri("http://someUri2.com")); @@ -405,7 +405,7 @@ TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); datum.ContactedReplicas.Add(default); TraceWriterBaselineTests.GetPrivateField>(datum, "endpointToAddressResolutionStats").Add("asdf", default); @@ -546,7 +546,7 @@ TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); TraceWriterBaselineTests.SetEndRequestTime(datum,DateTime.MaxValue); HttpResponseStatistics httpResponseStatistics = new HttpResponseStatistics( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 0d475ca370..03fdb84ead 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -42,14 +42,17 @@ static Task sendFunc(HttpRequestMessage request, Cancellati HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost")); - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => - new ValueTask(httpRequestMessage), - ResourceType.Collection, - timeoutPolicy: HttpTimeoutPolicyDefault.Instance, - new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow,new TraceSummary()), - default); - - Assert.AreEqual(httpRequestMessage, responseMessage.RequestMessage); + using (ITrace trace = Trace.GetRootTrace(nameof(ResponseMessageHasRequestMessageAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + new ValueTask(httpRequestMessage), + ResourceType.Collection, + timeoutPolicy: HttpTimeoutPolicyDefault.Instance, + new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), + default); + + Assert.AreEqual(httpRequestMessage, responseMessage.RequestMessage); + } } [TestMethod] @@ -111,15 +114,18 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); using CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)); - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(RetryTransientIssuesTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost"))), resourceType: ResourceType.Collection, timeoutPolicy: currentTimeoutPolicy.Key, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); - Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + } } } @@ -178,15 +184,18 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); using CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)); - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(RetryTransient408sTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost"))), resourceType: ResourceType.Collection, timeoutPolicy: HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); - Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + } } [TestMethod] @@ -216,15 +225,18 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); using CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)); - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(DoesNotRetryTransient408sOnDefaultPolicyTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost"))), resourceType: ResourceType.Collection, timeoutPolicy: HttpTimeoutPolicyControlPlaneRead.Instance, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); - - Assert.AreEqual(HttpStatusCode.RequestTimeout, responseMessage.StatusCode, "Should be a request timeout"); + + Assert.AreEqual(HttpStatusCode.RequestTimeout, responseMessage.StatusCode, "Should be a request timeout"); + } } [TestMethod] @@ -245,13 +257,16 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio try { - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(Retry3TimesOnDefaultPolicyTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost"))), resourceType: ResourceType.Collection, timeoutPolicy: HttpTimeoutPolicyDefault.Instance, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); + } } catch (Exception ex) { @@ -282,14 +297,16 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio try { - - HttpResponseMessage responseMessage1 = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(NoRetryOnNoRetryPolicyTestAsync))) + { + HttpResponseMessage responseMessage1 = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(method, new Uri("http://localhost"))), resourceType: resourceType, timeoutPolicy: timeoutPolicy, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); + } } catch (Exception e) { @@ -301,6 +318,9 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio CosmosException cosmosException = (CosmosException)e; Assert.AreEqual(cosmosException.StatusCode, System.Net.HttpStatusCode.ServiceUnavailable); Assert.AreEqual((int)cosmosException.SubStatusCode,(int)SubStatusCodes.TransportGenerated503); + + Assert.IsNotNull(cosmosException.Trace); + Assert.AreNotEqual(cosmosException.Trace, NoOpTrace.Singleton); } } @@ -344,13 +364,16 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio try { - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + using (ITrace trace = Trace.GetRootTrace(nameof(NoRetryOnNoRetryPolicyTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => new ValueTask( result: new HttpRequestMessage(HttpMethod.Get, new Uri("http://localhost"))), resourceType: ResourceType.Collection, timeoutPolicy: HttpTimeoutPolicyNoRetry.Instance, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), cancellationToken: default); + } } catch (Exception ex) { @@ -401,15 +424,18 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); using CosmosHttpClient cosmoshttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)); - HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => - new ValueTask( - result: new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost"))), - resourceType: ResourceType.Document, - timeoutPolicy: HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), - cancellationToken: default); + using (ITrace trace = Trace.GetRootTrace(nameof(RetryTransientIssuesForQueryPlanTestAsync))) + { + HttpResponseMessage responseMessage = await cosmoshttpClient.SendHttpAsync(() => + new ValueTask( + result: new HttpRequestMessage(HttpMethod.Post, new Uri("http://localhost"))), + resourceType: ResourceType.Document, + timeoutPolicy: HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance, + clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace), + cancellationToken: default); - Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + Assert.AreEqual(HttpStatusCode.OK, responseMessage.StatusCode); + } } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs index 2fc8359f68..cf54b12a52 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs @@ -57,15 +57,20 @@ public async Task DocumentClient_BuildHttpClientFactory_WithHandler() receivedResponseEventArgs: null); Assert.IsNotNull(httpClient); - HttpResponseMessage response = await httpClient.GetAsync( - uri: new Uri("https://localhost"), - additionalHeaders: new RequestNameValueCollection(), - resourceType: ResourceType.Document, - timeoutPolicy: HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, - clientSideRequestStatistics: new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()), - cancellationToken: default); - - Assert.AreEqual(HttpStatusCode.Conflict, response.StatusCode); + + using (ITrace trace = Trace.GetRootTrace(nameof(DocumentClient_BuildHttpClientFactory_WithHandler))) + { + IClientSideRequestStatistics stats = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); + HttpResponseMessage response = await httpClient.GetAsync( + uri: new Uri("https://localhost"), + additionalHeaders: new RequestNameValueCollection(), + resourceType: ResourceType.Document, + timeoutPolicy: HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, + clientSideRequestStatistics: stats, + cancellationToken: default); + + Assert.AreEqual(HttpStatusCode.Conflict, response.StatusCode); + } } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index 36b350a751..e16f176e61 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -865,21 +865,26 @@ public async Task GatewayStatsDurationTest() HttpMessageHandler mockMessageHandler = new MockMessageHandler(sendFunc); CosmosHttpClient cosmosHttpClient = MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(mockMessageHandler), DocumentClientEventSource.Instance); - Tracing.TraceData.ClientSideRequestStatisticsTraceDatum clientSideRequestStatistics = new Tracing.TraceData.ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); - - await cosmosHttpClient.SendHttpAsync(() => new ValueTask(new HttpRequestMessage(HttpMethod.Get, "http://someuri.com")), - ResourceType.Document, - HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, - clientSideRequestStatistics, - CancellationToken.None); - - Assert.AreEqual(clientSideRequestStatistics.HttpResponseStatisticsList.Count, 2); - // The duration is calculated using date times which can cause the duration to be slightly off. This allows for up to 15 Ms of variance. - // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision#:~:text=The%20precision%20is%20related%20to,35%2D40%20ms%20accuracy - Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[0].Duration.TotalMilliseconds >= 985, $"First request did was not delayed by at least 1 second. {JsonConvert.SerializeObject(clientSideRequestStatistics.HttpResponseStatisticsList[0])}"); - Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[1].Duration.TotalMilliseconds >= 985, $"Second request did was not delayed by at least 1 second. {JsonConvert.SerializeObject(clientSideRequestStatistics.HttpResponseStatisticsList[1])}"); - Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[0].RequestStartTime < - clientSideRequestStatistics.HttpResponseStatisticsList[1].RequestStartTime); + + using(ITrace trace = Tracing.Trace.GetRootTrace(nameof(GatewayStatsDurationTest))) + { + + Tracing.TraceData.ClientSideRequestStatisticsTraceDatum clientSideRequestStatistics = new Tracing.TraceData.ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); + + await cosmosHttpClient.SendHttpAsync(() => new ValueTask(new HttpRequestMessage(HttpMethod.Get, "http://someuri.com")), + ResourceType.Document, + HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout, + clientSideRequestStatistics, + CancellationToken.None); + + Assert.AreEqual(clientSideRequestStatistics.HttpResponseStatisticsList.Count, 2); + // The duration is calculated using date times which can cause the duration to be slightly off. This allows for up to 15 Ms of variance. + // https://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision#:~:text=The%20precision%20is%20related%20to,35%2D40%20ms%20accuracy + Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[0].Duration.TotalMilliseconds >= 985, $"First request did was not delayed by at least 1 second. {JsonConvert.SerializeObject(clientSideRequestStatistics.HttpResponseStatisticsList[0])}"); + Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[1].Duration.TotalMilliseconds >= 985, $"Second request did was not delayed by at least 1 second. {JsonConvert.SerializeObject(clientSideRequestStatistics.HttpResponseStatisticsList[1])}"); + Assert.IsTrue(clientSideRequestStatistics.HttpResponseStatisticsList[0].RequestStartTime < + clientSideRequestStatistics.HttpResponseStatisticsList[1].RequestStartTime); + } } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs index 2ec6e9db62..a28300d82f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ClientSideRequestStatisticsTraceDatumTests.cs @@ -48,7 +48,7 @@ public async Task ConcurrentUpdateHttpResponseStatisticsListTests() [TestMethod] public void DuplicateContactedReplicasTests() { - ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, Trace.GetRootTrace(nameof(DuplicateContactedReplicasTests))); clientSideRequestStatisticsTraceDatum.ContactedReplicas.Add(new TransportAddressUri(new Uri("http://storephysicaladdress1.com"))); clientSideRequestStatisticsTraceDatum.ContactedReplicas.Add(new TransportAddressUri(new Uri("http://storephysicaladdress2.com"))); clientSideRequestStatisticsTraceDatum.ContactedReplicas.Add(new TransportAddressUri(new Uri("http://storephysicaladdress2.com"))); @@ -89,7 +89,7 @@ public async Task ConcurrentUpdateStoreResponseStatisticsListTests() [TestMethod] public void VerifyIClientSideRequestStatisticsNullTests() { - IClientSideRequestStatistics clientSideRequestStatistics = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new Cosmos.Tracing.TraceSummary()); + IClientSideRequestStatistics clientSideRequestStatistics = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, Trace.GetRootTrace(nameof(VerifyIClientSideRequestStatisticsNullTests))); Assert.IsNotNull(clientSideRequestStatistics.ContactedReplicas); Assert.IsNotNull(clientSideRequestStatistics.FailedReplicas); Assert.IsNotNull(clientSideRequestStatistics.RegionsContacted); @@ -101,7 +101,7 @@ private async Task ConcurrentUpdateTestHelper( { using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new Cosmos.Tracing.TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, Trace.GetRootTrace(nameof(ConcurrentUpdateTestHelper))); Task backgroundTask = Task.Run(() => backgroundUpdater(datum, cancellationTokenSource.Token)); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ContactedRegionsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ContactedRegionsTests.cs index 6f6a84cbe2..53a04e5228 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ContactedRegionsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/ContactedRegionsTests.cs @@ -54,7 +54,7 @@ private ITrace CreateTestTraceTree() private TraceDatum GetDatumObject(string regionName1, string regionName2 = null) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, Trace.GetRootTrace(nameof(ContactedRegionsTests))); Uri uri1 = new Uri("http://someUri1.com"); datum.RegionsContacted.Add((regionName1, uri1)); if (regionName2 != null) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs index ff27842308..ad21070609 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs @@ -97,7 +97,7 @@ public void ValidateStoreResultSerialization() HashSet storeResultProperties = typeof(StoreResult).GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToHashSet(); string datumKey = "ClientStats"; Trace trace = Trace.GetRootTrace("Test"); - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace); trace.AddDatum(datumKey, datum); ReferenceCountedDisposable storeResult = StoreResult.CreateForTesting(storeResponse: new StoreResponse()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index 67bafdbf56..fe3dc7054f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -336,7 +336,7 @@ public void TraceData() TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); TransportAddressUri uri1 = new TransportAddressUri(new Uri("http://someUri1.com")); TransportAddressUri uri2 = new TransportAddressUri(new Uri("http://someUri2.com")); @@ -382,7 +382,7 @@ public void TraceData() TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); datum.ContactedReplicas.Add(default); TraceWriterBaselineTests.GetPrivateField>(datum, "endpointToAddressResolutionStats").Add("asdf", default); @@ -416,7 +416,7 @@ public void TraceData() TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, new TraceSummary()); + ClientSideRequestStatisticsTraceDatum datum = new ClientSideRequestStatisticsTraceDatum(DateTime.MinValue, rootTrace); TraceWriterBaselineTests.SetEndRequestTime(datum,DateTime.MaxValue); HttpResponseStatistics httpResponseStatistics = new HttpResponseStatistics( From 387ab62dbb55bcc99491bf16b88a32ad1cd663a5 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 2 Jun 2023 22:09:59 +0530 Subject: [PATCH 128/337] AI Integration: Fixes Open Telemetry Example (#3868) * first draft * add filter * revert csproj * fix sample * changed log message * remove unused library --- .../Usage/OpenTelemetry/AppSettings.json | 6 ++-- .../Usage/OpenTelemetry/OpenTelemetry.csproj | 4 --- .../Usage/OpenTelemetry/Program.cs | 31 +++++++++++++------ 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json index 1ea1245434..e0d21e3e09 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/AppSettings.json @@ -1,7 +1,9 @@ { "Logging": { - "LogLevel": { - "Azure-Cosmos-Operation-Request-Diagnostics": "Information" + "OpenTelemetry": { + "LogLevel": { + "Azure.Cosmos.Operation.Request.Diagnostics": "Warning" + } } }, "CosmosDBEndPointUrl": "https://localhost:8081", diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj index 46fe296b80..83224d4570 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj @@ -12,10 +12,6 @@ - - - - diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs index 4d6431823e..b4729e41c7 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs @@ -25,8 +25,8 @@ static async Task Main() try { IConfigurationRoot configuration = new ConfigurationBuilder() - .AddJsonFile("AppSettings.json") - .Build(); + .AddJsonFile("AppSettings.json") + .Build(); string endpoint = configuration["CosmosDBEndPointUrl"]; if (string.IsNullOrEmpty(endpoint)) @@ -52,12 +52,16 @@ static async Task Main() serviceVersion: "1.0.0"); // Set up logging to forward logs to chosen exporter - using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder.AddOpenTelemetry(options => - { - options.IncludeFormattedMessage = true; - options.SetResourceBuilder(resource); - options.AddAzureMonitorLogExporter(o => o.ConnectionString = aiConnectionString); // Set up exporter of your choice - })); + using ILoggerFactory loggerFactory + = LoggerFactory.Create(builder => builder + .AddConfiguration(configuration.GetSection("Logging")) + .AddOpenTelemetry(options => + { + options.IncludeFormattedMessage = true; + options.SetResourceBuilder(resource); + options.AddAzureMonitorLogExporter(o => o.ConnectionString = aiConnectionString); // Set up exporter of your choice + })); + /*.AddFilter(level => level == LogLevel.Error) // Filter is irrespective of event type or event name*/ AzureEventSourceLogForwarder logforwader = new AzureEventSourceLogForwarder(loggerFactory); logforwader.Start(); @@ -76,6 +80,7 @@ static async Task Main() { IsDistributedTracingEnabled = true // Defaults to true, set to false to disable }; + // using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) { @@ -88,7 +93,6 @@ static async Task Main() await Program.RunCrudDemo(container); } - } finally { @@ -116,6 +120,15 @@ public static async Task RunCrudDemo(Container container) Console.WriteLine($"Read document with id: {i}"); } + try + { + await container.ReadItemAsync($"random key", new PartitionKey($"random partition")); + } + catch(Exception) + { + Console.WriteLine("Generate exception by reading an invalid key"); + } + for (int i = 1; i <= 5; i++) { await container.ReplaceItemAsync(new Item { Id = $"{i}", Status = "updated" }, $"{i}", new PartitionKey($"{i}")); From f19acb073173fd9cbf640044f506c45cbe478e80 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:02:17 -0700 Subject: [PATCH 129/337] [Internal] Query: Adds OptimisticDirectExecute and RequiresDistribution headers (#3882) * Adding ODE and RequiresDistribution Headers * Fixed comments * Updated parameter in SwitchToFallbackPipelineAsync * Renamed TryUnwrapContinuationToken to UnwrapContinuationToken --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> --- .../Headers/CosmosMessageHeadersInternal.cs | 12 + Microsoft.Azure.Cosmos/src/Headers/Headers.cs | 12 + .../src/Headers/StoreRequestHeaders.cs | 6 + .../NetworkAttachedDocumentContainer.cs | 5 +- .../Query/Core/AdditionalRequestHeaders.cs | 36 ++ .../CosmosQueryExecutionContextFactory.cs | 1 - ...misticDirectExecutionQueryPipelineStage.cs | 92 ++++-- .../Pagination/QueryPaginationOptions.cs | 4 + .../Core/QueryClient/CosmosQueryClient.cs | 3 +- .../Query/v3Query/CosmosQueryClientCore.cs | 8 +- .../Query/v3Query/CosmosQueryContextCore.cs | 5 +- .../src/RequestOptions/QueryRequestOptions.cs | 2 +- .../Query/MockCosmosQueryClient.cs | 8 +- .../OptimisticDirectExecutionQueryTests.cs | 312 ++++++++++++++++-- ...ositiveOptimisticDirectExecutionOutput.xml | 15 +- ...misticDirectExecutionQueryBaselineTests.cs | 246 ++++++++++++-- 16 files changed, 655 insertions(+), 112 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/AdditionalRequestHeaders.cs diff --git a/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs b/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs index e8c584d782..f12595d832 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs @@ -177,6 +177,18 @@ public virtual string EndEpk set => this.SetProperty(HttpConstants.HttpHeaders.EndEpk, value); } + public virtual string OptimisticDirectExecute + { + get => this.GetValueOrDefault(HttpConstants.HttpHeaders.OptimisticDirectExecute); + set => this.SetProperty(HttpConstants.HttpHeaders.OptimisticDirectExecute, value); + } + + public virtual string RequiresDistribution + { + get => this.GetValueOrDefault(HttpConstants.HttpHeaders.RequiresDistribution); + set => this.SetProperty(HttpConstants.HttpHeaders.RequiresDistribution, value); + } + public abstract INameValueCollection INameValueCollection { get; } public virtual string this[string headerName] diff --git a/Microsoft.Azure.Cosmos/src/Headers/Headers.cs b/Microsoft.Azure.Cosmos/src/Headers/Headers.cs index 611de5f147..40f90c423a 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/Headers.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/Headers.cs @@ -171,6 +171,18 @@ internal virtual string PartitionKey set => this.CosmosMessageHeaders.PartitionKey = value; } + internal virtual string OptimisticDirectExecute + { + get => this.CosmosMessageHeaders.OptimisticDirectExecute; + set => this.CosmosMessageHeaders.OptimisticDirectExecute = value; + } + + internal virtual string RequiresDistribution + { + get => this.CosmosMessageHeaders.RequiresDistribution; + set => this.CosmosMessageHeaders.RequiresDistribution = value; + } + internal virtual string PartitionKeyRangeId { get => this.CosmosMessageHeaders.PartitionKeyRangeId; diff --git a/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs b/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs index 9147c31026..68086095f7 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs @@ -46,6 +46,12 @@ public override string XDate set => this.requestNameValueCollection.XDate = value; } + public override string OptimisticDirectExecute + { + get => this.requestNameValueCollection.OptimisticDirectExecute; + set => this.requestNameValueCollection.OptimisticDirectExecute = value; + } + public override string ConsistencyLevel { get => this.requestNameValueCollection.ConsistencyLevel; diff --git a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs index 1132a40a35..7d8683c3fe 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs @@ -258,16 +258,17 @@ public async Task> MonadicQueryAsync( } QueryRequestOptions queryRequestOptions = this.queryRequestOptions == null ? new QueryRequestOptions() : this.queryRequestOptions; + AdditionalRequestHeaders additionalRequestHeaders = new AdditionalRequestHeaders(this.correlatedActivityId, isContinuationExpected: false, optimisticDirectExecute: queryPaginationOptions.OptimisticDirectExecute); + TryCatch monadicQueryPage = await this.cosmosQueryClient.ExecuteItemQueryAsync( this.resourceLink, this.resourceType, Documents.OperationType.Query, - this.correlatedActivityId, feedRangeState.FeedRange, queryRequestOptions, + additionalRequestHeaders, sqlQuerySpec, feedRangeState.State == null ? null : ((CosmosString)feedRangeState.State.Value).Value, - isContinuationExpected: false, queryPaginationOptions.PageSizeLimit ?? int.MaxValue, trace, cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/AdditionalRequestHeaders.cs b/Microsoft.Azure.Cosmos/src/Query/Core/AdditionalRequestHeaders.cs new file mode 100644 index 0000000000..add4e15c99 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/AdditionalRequestHeaders.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core +{ + using System; + + /// + /// Captures additional headers to be sent in the web request. + /// + internal sealed class AdditionalRequestHeaders + { + /// + /// Enable backend to link multiple activityIds that belong to the same operation. + /// + public Guid CorrelatedActivityId { get; } + + /// + /// Let the backend know if continuations are expected for a certain query. + /// + public bool IsContinuationExpected { get; } + + /// + /// Let the backend know if a query is utilizing the OptimisticDirectExecute pipeline. + /// + public bool OptimisticDirectExecute { get; } + + public AdditionalRequestHeaders(Guid correlatedActivityId, bool isContinuationExpected, bool optimisticDirectExecute) + { + this.CorrelatedActivityId = correlatedActivityId; + this.IsContinuationExpected = isContinuationExpected; + this.OptimisticDirectExecute = optimisticDirectExecute; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index e276466f9d..8f35ff821a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -477,7 +477,6 @@ private static TryCatch TryCreateOptimisticDirectExecutionC documentContainer: documentContainer, inputParameters: inputParameters, targetRange: new FeedRangeEpk(targetRange.ToRange()), - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: inputParameters.MaxItemCount), fallbackQueryPipelineStageFactory: (continuationToken) => { // In fallback scenario, the Specialized pipeline is always invoked diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index 0664603024..e62ecf41f0 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -19,6 +19,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQu using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; internal sealed class OptimisticDirectExecutionQueryPipelineStage : IQueryPipelineStage { @@ -28,11 +29,12 @@ private enum ExecutionState SpecializedDocumentQueryExecution, } - private const string optimisticDirectExecutionToken = "OptimisticDirectExecutionToken"; + private const string OptimisticDirectExecutionToken = "OptimisticDirectExecutionToken"; private readonly FallbackQueryPipelineStageFactory queryPipelineStageFactory; private TryCatch inner; private CosmosElement continuationToken; private ExecutionState executionState; + private bool? previousRequiresDistribution; private OptimisticDirectExecutionQueryPipelineStage(TryCatch inner, FallbackQueryPipelineStageFactory queryPipelineStageFactory, CosmosElement continuationToken) { @@ -40,6 +42,12 @@ private OptimisticDirectExecutionQueryPipelineStage(TryCatch> FallbackQueryPipelineStageFactory(CosmosElement continuationToken); @@ -55,22 +63,43 @@ public async ValueTask MoveNextAsync(ITrace trace) { TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace)); bool success = hasNext.Succeeded && hasNext.Result; - bool isPartitionSplitException = hasNext.Succeeded && this.Current.Failed && this.Current.InnerMostException.IsPartitionSplitException(); - - if (success && !isPartitionSplitException) - { - this.continuationToken = this.Current.Succeeded ? this.Current.Result.State?.Value : null; - } - else if (isPartitionSplitException && this.executionState == ExecutionState.OptimisticDirectExecution) + if (this.executionState == ExecutionState.OptimisticDirectExecution) { - this.inner = await this.queryPipelineStageFactory(this.TryUnwrapContinuationToken()); - this.executionState = ExecutionState.SpecializedDocumentQueryExecution; - if (this.inner.Failed) + bool isPartitionSplitException = hasNext.Succeeded && this.Current.Failed && this.Current.InnerMostException.IsPartitionSplitException(); + if (success && !isPartitionSplitException) { - return false; + this.continuationToken = this.Current.Succeeded ? this.Current.Result.State?.Value : null; + if (this.continuationToken != null) + { + bool requiresDistribution; + if (this.Current.Result.AdditionalHeaders.TryGetValue(HttpConstants.HttpHeaders.RequiresDistribution, out string requiresDistributionHeaderValue)) + { + requiresDistribution = bool.Parse(requiresDistributionHeaderValue); + } + else + { + requiresDistribution = true; + } + + if (this.previousRequiresDistribution.HasValue && this.previousRequiresDistribution != requiresDistribution) + { + // We should never enter this if statement as requiresDistribution flag can never switch mid execution. + // Hence, this exception should never be thrown. + throw new InvalidOperationException($"Unexpected switch in {HttpConstants.HttpHeaders.RequiresDistribution} value. Previous value : {this.previousRequiresDistribution} Current value : {requiresDistribution}."); + } + + if (requiresDistribution) + { + success = await this.SwitchToFallbackPipelineAsync(continuationToken: null, trace); + } + + this.previousRequiresDistribution = requiresDistribution; + } + } + else if (isPartitionSplitException) + { + success = await this.SwitchToFallbackPipelineAsync(continuationToken: UnwrapContinuationToken(this.continuationToken), trace); } - - success = await this.inner.Result.MoveNextAsync(trace); } return success; @@ -81,32 +110,46 @@ public void SetCancellationToken(CancellationToken cancellationToken) this.inner.Try(pipelineStage => pipelineStage.SetCancellationToken(cancellationToken)); } - private CosmosElement TryUnwrapContinuationToken() + private static CosmosElement UnwrapContinuationToken(CosmosElement continuationToken) { - if (this.continuationToken != null) + if (continuationToken == null) return null; + + CosmosObject cosmosObject = continuationToken as CosmosObject; + CosmosElement backendContinuationToken = cosmosObject[OptimisticDirectExecutionToken]; + Debug.Assert(backendContinuationToken != null); + + return CosmosArray.Create(backendContinuationToken); + } + + private async Task SwitchToFallbackPipelineAsync(CosmosElement continuationToken, ITrace trace) + { + Debug.Assert(this.executionState == ExecutionState.OptimisticDirectExecution, "OptimisticDirectExecuteQueryPipelineStage Assert!", "Only OptimisticDirectExecute pipeline can create this fallback pipeline"); + this.executionState = ExecutionState.SpecializedDocumentQueryExecution; + this.inner = continuationToken != null + ? await this.queryPipelineStageFactory(continuationToken) + : await this.queryPipelineStageFactory(null); + + if (this.inner.Failed) { - CosmosObject cosmosObject = this.continuationToken as CosmosObject; - CosmosElement backendContinuationToken = cosmosObject[optimisticDirectExecutionToken]; - Debug.Assert(backendContinuationToken != null); - return CosmosArray.Create(backendContinuationToken); + return false; } - return null; + return await this.inner.Result.MoveNextAsync(trace); } public static TryCatch MonadicCreate( DocumentContainer documentContainer, CosmosQueryExecutionContextFactory.InputParameters inputParameters, FeedRangeEpk targetRange, - QueryPaginationOptions queryPaginationOptions, FallbackQueryPipelineStageFactory fallbackQueryPipelineStageFactory, CancellationToken cancellationToken) { + QueryPaginationOptions paginationOptions = new QueryPaginationOptions(pageSizeHint: inputParameters.MaxItemCount, optimisticDirectExecute: true); TryCatch pipelineStage = OptimisticDirectExecutionQueryPipelineImpl.MonadicCreate( documentContainer: documentContainer, sqlQuerySpec: inputParameters.SqlQuerySpec, targetRange: targetRange, - queryPaginationOptions: queryPaginationOptions, + queryPaginationOptions: paginationOptions, partitionKey: inputParameters.PartitionKey, continuationToken: inputParameters.InitialUserContinuationToken, cancellationToken: cancellationToken); @@ -120,7 +163,7 @@ public static TryCatch MonadicCreate( return TryCatch.FromResult(odePipelineStageMonadicCreate); } - private class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage + private sealed class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage { private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; @@ -226,7 +269,6 @@ public static TryCatch MonadicCreate( } FeedRangeState feedRangeState = monadicExtractState.Result; - QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( documentContainer, sqlQuerySpec, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs index 0b692160be..c285135feb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs @@ -15,6 +15,8 @@ internal sealed class QueryPaginationOptions : PaginationOptions { public static readonly QueryPaginationOptions Default = new QueryPaginationOptions(); + public bool OptimisticDirectExecute { get; } + public static readonly ImmutableHashSet BannedHeaders = new HashSet() { HttpConstants.HttpHeaders.Continuation, @@ -29,10 +31,12 @@ internal sealed class QueryPaginationOptions : PaginationOptions public QueryPaginationOptions( int? pageSizeHint = null, + bool optimisticDirectExecute = false, JsonSerializationFormat? jsonSerializationFormat = null, Dictionary additionalHeaders = null) : base(pageSizeHint, jsonSerializationFormat, additionalHeaders) { + this.OptimisticDirectExecute = optimisticDirectExecute; } protected override ImmutableHashSet BannedAdditionalHeaders => BannedHeaders; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs index c2bcf91619..ac093cadce 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs @@ -54,12 +54,11 @@ public abstract Task> ExecuteItemQueryAsync( string resourceUri, Documents.ResourceType resourceType, Documents.OperationType operationType, - Guid clientQueryCorrelationId, FeedRange feedRange, QueryRequestOptions requestOptions, + AdditionalRequestHeaders additionalRequestHeaders, SqlQuerySpec sqlQuerySpec, string continuationToken, - bool isContinuationExpected, int pageSize, ITrace trace, CancellationToken cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index 138f32c593..daf47e151c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -119,12 +119,11 @@ public override async Task> ExecuteItemQueryAsync( string resourceUri, ResourceType resourceType, OperationType operationType, - Guid clientQueryCorrelationId, FeedRange feedRange, QueryRequestOptions requestOptions, + AdditionalRequestHeaders additionalRequestHeaders, SqlQuerySpec sqlQuerySpec, string continuationToken, - bool isContinuationExpected, int pageSize, ITrace trace, CancellationToken cancellationToken) @@ -143,13 +142,14 @@ public override async Task> ExecuteItemQueryAsync( { cosmosRequestMessage.Headers.Add( HttpConstants.HttpHeaders.IsContinuationExpected, - isContinuationExpected.ToString()); + additionalRequestHeaders.IsContinuationExpected.ToString()); QueryRequestOptions.FillContinuationToken( cosmosRequestMessage, continuationToken); cosmosRequestMessage.Headers.Add(HttpConstants.HttpHeaders.ContentType, MediaTypes.QueryJson); cosmosRequestMessage.Headers.Add(HttpConstants.HttpHeaders.IsQuery, bool.TrueString); - cosmosRequestMessage.Headers.Add(WFConstants.BackendHeaders.CorrelatedActivityId, clientQueryCorrelationId.ToString()); + cosmosRequestMessage.Headers.Add(WFConstants.BackendHeaders.CorrelatedActivityId, additionalRequestHeaders.CorrelatedActivityId.ToString()); + cosmosRequestMessage.Headers.Add(HttpConstants.HttpHeaders.OptimisticDirectExecute, additionalRequestHeaders.OptimisticDirectExecute.ToString()); }, trace: trace, cancellationToken: cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryContextCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryContextCore.cs index b1325f2652..215ca22b2c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryContextCore.cs @@ -51,16 +51,17 @@ internal override Task> ExecuteQueryAsync( ITrace trace, CancellationToken cancellationToken) { + AdditionalRequestHeaders additionalRequestHeaders = new AdditionalRequestHeaders(this.CorrelatedActivityId, isContinuationExpected, optimisticDirectExecute: false); + return this.QueryClient.ExecuteItemQueryAsync( resourceUri: this.ResourceLink, resourceType: this.ResourceTypeEnum, operationType: this.OperationTypeEnum, - clientQueryCorrelationId: this.CorrelatedActivityId, requestOptions: queryRequestOptions, + additionalRequestHeaders: additionalRequestHeaders, sqlQuerySpec: querySpecForInit, continuationToken: continuationToken, feedRange: feedRange, - isContinuationExpected: isContinuationExpected, pageSize: pageSize, trace: trace, cancellationToken: cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 8ce4761c31..cd505f1158 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -44,7 +44,7 @@ public class QueryRequestOptions : RequestOptions public bool? EnableLowPrecisionOrderBy { get; set; } /// - /// Gets or sets the option for customers to opt in for direct (optimistic) execution of the query.. + /// Gets or sets the option for customers to opt in for direct (optimistic) execution of the query. /// /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs index ee6eec3004..11d51403b1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs @@ -68,12 +68,11 @@ public override Task> ExecuteItemQueryAsync( string resourceUri, ResourceType resourceType, OperationType operationType, - Guid clientQueryCorrelationId, FeedRange feedRange, QueryRequestOptions requestOptions, + AdditionalRequestHeaders additionalRequestHeaders, SqlQuerySpec sqlQuerySpec, string continuationToken, - bool isContinuationExpected, int pageSize, ITrace trace, CancellationToken cancellationToken) @@ -82,12 +81,11 @@ public override Task> ExecuteItemQueryAsync( resourceUri: resourceUri, resourceType: resourceType, operationType: operationType, - clientQueryCorrelationId: clientQueryCorrelationId, + feedRange: feedRange, requestOptions: requestOptions, + additionalRequestHeaders: additionalRequestHeaders, sqlQuerySpec: sqlQuerySpec, continuationToken: continuationToken, - feedRange: feedRange, - isContinuationExpected: isContinuationExpected, pageSize: pageSize, trace: trace, cancellationToken: cancellationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index cc9ef91733..78d4ddb8ed 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -20,7 +20,8 @@ public sealed class OptimisticDirectExecutionQueryTests : QueryTestsBase private static class PageSizeOptions { - public static readonly int[] NonGroupByPageSizeOptions = { -1, 1, 2, 10, 100 }; + public static readonly int[] NonGroupByAndNoContinuationTokenPageSizeOptions = { -1, 10 }; + public static readonly int[] NonGroupByWithContinuationTokenPageSizeOptions = { 1, 2 }; public static readonly int[] GroupByPageSizeOptions = { -1 }; public static readonly int[] PageSize100 = { 100 }; } @@ -42,49 +43,98 @@ public async Task TestPassingOptimisticDirectExecutionQueries() expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: false, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), - // Simple query + // Simple query (requiresDist = false) CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: null, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - // DISTINCT with ORDER BY + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + // DISTINCT with ORDER BY (requiresDist = true) CreateInput( query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first7IntegersReversed, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), CreateInput( query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first7IntegersReversed, partitionKey: null, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), - // TOP with GROUP BY + // DISTINCT (requiresDist = true) + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r", + expectedResult: first7Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r", + expectedResult: first7Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + // TOP with GROUP BY (requiresDist = true) CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r GROUP BY r.{NumberField}", expectedResult: first5Integers, @@ -99,72 +149,267 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.GroupByPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - // OFFSET LIMIT with WHERE and BETWEEN + + // TOP (requiresDist = false) + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + // TOP with ORDER BY (requiresDist = false) + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + // OFFSET LIMIT with WHERE and BETWEEN (requiresDist = false) + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: partitionKeyValue, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + enableOptimisticDirectExecution: true, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: partitionKeyValue, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + enableOptimisticDirectExecution: true, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: null, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, enableOptimisticDirectExecution: true, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution) - }; - + }; + List multiPartitionContainerTestCases = new List() { - // Simple query + // Simple query (requiresDist = false) CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: null, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r", + expectedResult: first7Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), - // DISTINCT with ORDER BY + // DISTINCT with ORDER BY (requiresDist = true) CreateInput( query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first7IntegersReversed, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first7IntegersReversed, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT DISTINCT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", + expectedResult: first7IntegersReversed, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + // TOP (requiresDist = false) + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + // TOP with ORDER BY (requiresDist = false) + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, partitionKey: null, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", + expectedResult: first5Integers, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized), - // OFFSET LIMIT with WHERE and BETWEEN + // OFFSET LIMIT with WHERE and BETWEEN (requiresDist = false) CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, partitionKey: null, enableOptimisticDirectExecution: true, - pageSizeOptions: PageSizeOptions.NonGroupByPageSizeOptions, + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( + query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", + expectedResult: new List { 1 }, + partitionKey: null, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Specialized) }; @@ -222,27 +467,34 @@ public async Task TestQueriesWithPartitionKeyNone() enableOptimisticDirectExecution: false, pageSizeOptions: PageSizeOptions.PageSize100, expectedPipelineType: TestInjections.PipelineType.Passthrough), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first400Integers, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + expectedPipelineType: TestInjections.PipelineType.Specialized), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} ASC", expectedResult: first400Integers, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + expectedPipelineType: TestInjections.PipelineType.Specialized), + + //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first400IntegersReversed, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + expectedPipelineType: TestInjections.PipelineType.Specialized), + CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, @@ -279,7 +531,7 @@ public async Task TestFailingOptimisticDirectExecutionOutput() { "SELECT TOP 10 * FOM r", null }, { "this is not a valid query", null }, }; - + await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml index 5e496fc564..a5e6d97841 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/OptimisticDirectExecutionQueryBaselineTests.PositiveOptimisticDirectExecutionOutput.xml @@ -66,20 +66,7 @@ - Null Partition Key Value - SELECT * FROM c - - /pk - - Hash - - - true - - - - - None Partition Key Value + Cosmos.PartitionKey.Null Partition Key Value SELECT * FROM c /pk diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 20de3f1f03..fad65e80db 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.Collections.Immutable; using System.Collections.ObjectModel; using System.IO; using System.Linq; @@ -80,19 +81,12 @@ public void PositiveOptimisticDirectExecutionOutput() // Below cases are Ode because they have a collection with a single physical partition. // Added emulator tests (TestPassingOptimisticDirectExecutionQueries()) to verify the negation of the below cases. CreateInput( - description: @"Null Partition Key Value", + description: @"Cosmos.PartitionKey.Null Partition Key Value", query: "SELECT * FROM c", expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", partitionKeyValue: Cosmos.PartitionKey.Null), - CreateInput( - description: @"None Partition Key Value", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, - partitionKeyPath: @"/pk", - partitionKeyValue: Cosmos.PartitionKey.None), - CreateInput( description: @"C# Null Partition Key Value", query: "SELECT * FROM c", @@ -133,7 +127,7 @@ public void NegativeOptimisticDirectExecutionOutput() partitionKeyPath: @"/pk", partitionKeyValue: "a", continuationToken: CosmosArray.Create(new List() { ParallelContinuationToken.ToCosmosElement(parallelContinuationToken) })), - + CreateInput( description: @"Single Partition Key with OrderBy continuation token", query: "SELECT * FROM c ORDER BY c._ts", @@ -144,7 +138,7 @@ public void NegativeOptimisticDirectExecutionOutput() }; this.ExecuteTestSuite(testVariations); } - + // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done [TestMethod] @@ -169,7 +163,6 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() partitionKeyValue: "a"); QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: false); IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); int documentCountInSinglePartition = 0; @@ -192,6 +185,145 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() Assert.AreEqual(100, documentCountInSinglePartition); } + [TestMethod] + public async Task TestQueriesWhichNeverRequireDistribution() + { + // requiresDist = false + int numItems = 100; + List singlePartitionContainerTestCases = new List() + { + new RequiresDistributionTestCase("SELECT * FROM r", 10, 100), + new RequiresDistributionTestCase("SELECT VALUE r.id FROM r", 0, 10), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5", 0, 0), + new RequiresDistributionTestCase("SELECT r.id FROM r JOIN id IN r.id",0, 0), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r ORDER BY r.id", 0, 5), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r WHERE r.id > 5 ORDER BY r.id", 0, 0), + new RequiresDistributionTestCase("SELECT * FROM r OFFSET 5 LIMIT 3", 1, 3), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5 OFFSET 5 LIMIT 3", 0, 0) + }; + + foreach (RequiresDistributionTestCase testCase in singlePartitionContainerTestCases) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Queries which will never require distribution", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: testCase.ExpectedContinuationTokenCount, + requiresDist: false); + + Assert.AreEqual(testCase.ExpectedDocumentCount, result); + } + } + + [TestMethod] + public async Task TestQueriesWhichWillAlwaysRequireDistribution() + { + // requiresDist = true + int numItems = 100; + List singlePartitionContainerTestCases = new List() + { + new RequiresDistributionTestCase("SELECT Sum(id) as sum_id FROM r JOIN id IN r.id", 0, 1), + new RequiresDistributionTestCase("SELECT DISTINCT TOP 5 r.id FROM r ORDER BY r.id", 0, 5), + new RequiresDistributionTestCase("SELECT DISTINCT r.id FROM r GROUP BY r.id", 0, 10), + new RequiresDistributionTestCase("SELECT DISTINCT r.id, Sum(r.id) as sum_a FROM r GROUP BY r.id",0, 10), + new RequiresDistributionTestCase("SELECT Count(1) FROM (SELECT DISTINCT r.id FROM root r)", 0, 1), + new RequiresDistributionTestCase("SELECT DISTINCT id FROM r JOIN id in r.id", 0, 0), + new RequiresDistributionTestCase("SELECT r.id, Count(1) AS count_a FROM r GROUP BY r.id ORDER BY r.id", 0, 10), + new RequiresDistributionTestCase("SELECT Count(1) as count FROM root r JOIN b IN r.id", 0, 1), + new RequiresDistributionTestCase("SELECT Avg(1) AS avg FROM root r", 0, 1), + new RequiresDistributionTestCase("SELECT r.id, Count(1) as count FROM r WHERE r.id > 0 GROUP BY r.id", 0, 0), + new RequiresDistributionTestCase("SELECT r.id FROM r WHERE r.id > 0 GROUP BY r.id ORDER BY r.id", 0, 0) + }; + + foreach (RequiresDistributionTestCase testCase in singlePartitionContainerTestCases) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Queries which will always require distribution", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: testCase.ExpectedContinuationTokenCount, + requiresDist: true); + + Assert.AreEqual(testCase.ExpectedDocumentCount, result); + } + } + + [TestMethod] + public async Task TestQueriesWhichCanSwitchDistribution() + { + // requiresDist = true/false + int numItems = 100; + bool[] requiresDistSet = { true, false }; + + List singlePartitionContainerTestCases = new List() + { + new RequiresDistributionTestCase("SELECT Count(r.id) AS count_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT DISTINCT r.id FROM r", 0, 10), + new RequiresDistributionTestCase("SELECT r.id, Count(1) AS count_a FROM r GROUP BY r.id", 0, 10), + new RequiresDistributionTestCase("SELECT Count(1) AS count FROM root r WHERE r.id < 2", 0, 1), + new RequiresDistributionTestCase("SELECT r.id, Count(r.id), Avg(r.id) FROM r WHERE r.id < 2 GROUP BY r.id", 0, 0), + new RequiresDistributionTestCase("SELECT TOP 5 Count(1) as count FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT TOP 5 Count(1) as count FROM r ORDER BY r.id", 0, 1), + new RequiresDistributionTestCase("SELECT r.id FROM r GROUP BY r.id OFFSET 5 LIMIT 3", 0, 3), + new RequiresDistributionTestCase("SELECT Count(1) as count FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Sum(r.id) as sum_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Min(r.a) as min_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Max(r.a) as min_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Avg(r.a) as min_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r WHERE r.a > 0", 0, 1), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r WHERE r.a > 0 OFFSET 0 LIMIT 5", 0, 1), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r WHERE r.a > 0 OFFSET 5 LIMIT 5", 0, 0), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r ORDER BY r.a", 0, 1), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r ORDER BY r.a OFFSET 5 LIMIT 5", 0, 0), + new RequiresDistributionTestCase("SELECT Sum(r.a) as sum_a FROM r WHERE r.a > 0 ORDER BY r.a OFFSET 5 LIMIT 5", 0, 0), + new RequiresDistributionTestCase("SELECT DISTINCT VALUE r.id FROM r", 0, 10), + new RequiresDistributionTestCase("SELECT DISTINCT TOP 5 r.a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT s.id FROM (SELECT DISTINCT r.id FROM root r) as s", 0, 10), + new RequiresDistributionTestCase("SELECT DISTINCT r.a FROM r OFFSET 3 LIMIT 5", 0, 0), + new RequiresDistributionTestCase("SELECT Count(r.id) AS count_a FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT r.id, Count(1) AS count_a FROM r GROUP BY r.id", 0, 10), + new RequiresDistributionTestCase("SELECT Count(1) AS count FROM root r WHERE r.id < 2", 0, 1), + new RequiresDistributionTestCase("SELECT TOP 5 Count(1) as count FROM r", 0, 1), + new RequiresDistributionTestCase("SELECT Count(1) AS count FROM root r WHERE r.id < 2", 0, 1), + }; + + foreach (RequiresDistributionTestCase testCase in singlePartitionContainerTestCases) + { + foreach (bool requiresDist in requiresDistSet) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Queries which can require distribution in certain cases", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: testCase.ExpectedContinuationTokenCount, + requiresDist: requiresDist); + + Assert.AreEqual(testCase.ExpectedDocumentCount, result); + } + } + } + // test checks that the pipeline can take a query to the backend and returns its associated document(s) + continuation token. [TestMethod] public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() @@ -269,7 +401,7 @@ private static async Task ExecuteGoneExceptionOnODEPipeline(bool isMultiPa { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - else + else { Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } @@ -345,18 +477,20 @@ private static async Task TestHandlingOfFailedFallbackPipeline(bool isMult return (mergeTest, queryPipelineStage); } - private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestInput input, int numItems, bool isMultiPartition, int expectedContinuationTokenCount) + private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestInput input, int numItems, bool isMultiPartition, int expectedContinuationTokenCount, bool requiresDist = false) { QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); - List documents = new List(); int continuationTokenCount = 0; while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { - Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + if (!requiresDist) + { + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); @@ -420,6 +554,7 @@ private static async Task GetOdePipelineAsync(OptimisticDir private static async Task CreateDocumentContainerAsync( int numItems, bool multiPartition, + bool requiresDist = false, FlakyDocumentContainer.FailureConfigs failureConfigs = null) { PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() @@ -432,7 +567,9 @@ private static async Task CreateDocumentContainerAsync( Version = PartitionKeyDefinitionVersion.V2, }; - IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(partitionKeyDefinition); + MockDocumentContainer mockContainer = new MockDocumentContainer(partitionKeyDefinition, requiresDist); + IMonadicDocumentContainer monadicDocumentContainer = mockContainer; + if (failureConfigs != null) { monadicDocumentContainer = new FlakyDocumentContainer(monadicDocumentContainer, failureConfigs); @@ -523,7 +660,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect NoOpTrace.Singleton); bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton).AsTask().GetAwaiter().GetResult(); - + if (input.ExpectedOptimisticDirectExecution) { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); @@ -546,11 +683,6 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect string sqlQuerySpecJsonString = streamReader.ReadToEnd(); PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = GetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, input.PartitionKeyDefinition); - if (input.PartitionKeyValue == default || input.PartitionKeyValue == Cosmos.PartitionKey.None) - { - input.PartitionKeyValue = Cosmos.PartitionKey.Null; - } - CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: new SqlQuerySpec(input.Query), initialUserContinuationToken: input.ContinuationToken, @@ -598,6 +730,68 @@ private static QueryRequestOptions GetQueryRequestOptions(bool enableOptimisticD }; } + internal readonly struct RequiresDistributionTestCase + { + public string Query { get; } + public int ExpectedContinuationTokenCount { get; } + public int ExpectedDocumentCount { get; } + + public RequiresDistributionTestCase( + string query, + int expectedContinuationTokenCount, + int expectedDocumentCount) + { + this.Query = query; + this.ExpectedContinuationTokenCount = expectedContinuationTokenCount; + this.ExpectedDocumentCount = expectedDocumentCount; + } + } + + private sealed class MockDocumentContainer : InMemoryContainer + { + private readonly bool requiresDistribution; + + public MockDocumentContainer( + PartitionKeyDefinition partitionKeyDefinition, + bool requiresDistribution) + : base(partitionKeyDefinition) + { + this.requiresDistribution = requiresDistribution; + } + + public override async Task> MonadicQueryAsync( + SqlQuerySpec sqlQuerySpec, + FeedRangeState feedRangeState, + QueryPaginationOptions queryPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + Task> queryPage = base.MonadicQueryAsync( + sqlQuerySpec, + feedRangeState, + queryPaginationOptions, + trace, + cancellationToken); + + ImmutableDictionary.Builder additionalHeaders = ImmutableDictionary.CreateBuilder(); + additionalHeaders.Add("x-ms-documentdb-partitionkeyrangeid", "0"); + additionalHeaders.Add("x-ms-test-header", "true"); + additionalHeaders.Add("x-ms-cosmos-query-requiresdistribution", this.requiresDistribution.ToString()); + + return await Task.FromResult( + TryCatch.FromResult( + new QueryPage( + queryPage.Result.Result.Documents, + requestCharge: 42, + activityId: Guid.NewGuid().ToString(), + responseLengthInBytes: 1337, + cosmosQueryExecutionInfo: default, + disallowContinuationTokenMessage: default, + additionalHeaders: additionalHeaders.ToImmutable(), + state: queryPage.Result.Result.State))); + } + } + private class MergeTestUtil { public int MoveNextCounter { get; private set; } @@ -626,7 +820,7 @@ public async Task ShouldReturnFailure() activityId: "0f8fad5b-d9cb-469f-a165-70867728950e", requestCharge: default); } - + if (this.IsFailedFallbackPipelineTest && this.GoneExceptionCreated && !this.TooManyRequestsFailureCreated) { this.TooManyRequestsFailureCreated = true; @@ -728,7 +922,7 @@ public override void SerializeAsXml(XmlWriter xmlWriter) } } } - + internal class TestCosmosQueryClient : CosmosQueryClient { public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); @@ -743,7 +937,7 @@ public override void ClearSessionTokenCache(string collectionFullName) throw new NotImplementedException(); } - public override Task> ExecuteItemQueryAsync(string resourceUri, ResourceType resourceType, OperationType operationType, Guid clientQueryCorrelationId, Cosmos.FeedRange feedRange, QueryRequestOptions requestOptions, SqlQuerySpec sqlQuerySpec, string continuationToken, bool isContinuationExpected, int pageSize, ITrace trace, CancellationToken cancellationToken) + public override Task> ExecuteItemQueryAsync(string resourceUri, ResourceType resourceType, OperationType operationType, Cosmos.FeedRange feedRange, QueryRequestOptions requestOptions, AdditionalRequestHeaders additionalRequestHeaders, SqlQuerySpec sqlQuerySpec, string continuationToken, int pageSize, ITrace trace, CancellationToken cancellationToken) { throw new NotImplementedException(); } From c095bc1119684078737282dbe80ebbba100bab74 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 6 Jun 2023 17:26:50 -0700 Subject: [PATCH 130/337] Query: Refactors the EnableOptimisticDirectExecution flag to be public (#3883) * Made EnableOptimisticDirectExecution a public flag * Updated contract --- .../DotNetSDKEncryptionCustomAPI.json | 19 ++++++++++ .../src/RequestOptions/QueryRequestOptions.cs | 2 +- .../Contracts/DotNetSDKAPI.json | 38 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/Contracts/DotNetSDKEncryptionCustomAPI.json b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/Contracts/DotNetSDKEncryptionCustomAPI.json index 8f858ddb94..1912d16407 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/Contracts/DotNetSDKEncryptionCustomAPI.json +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/Microsoft.Azure.Cosmos.Encryption.Custom.Tests/Contracts/DotNetSDKEncryptionCustomAPI.json @@ -51,6 +51,13 @@ ], "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken)[System.Runtime.CompilerServices.AsyncStateMachineAttribute(typeof(Microsoft.Azure.Cosmos.Encryption.Custom.CosmosDataEncryptionKeyProvider+))]": { + "Type": "Method", + "Attributes": [ + "AsyncStateMachineAttribute" + ], + "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void .ctor(Microsoft.Azure.Cosmos.Encryption.Custom.EncryptionKeyWrapProvider, Microsoft.Data.Encryption.Cryptography.EncryptionKeyStoreProvider, System.Nullable`1[System.TimeSpan])[System.ObsoleteAttribute(\"Please use the constructor with EncryptionKeyStoreProvider only.\")]": { "Type": "Constructor", "Attributes": [ @@ -398,6 +405,13 @@ ], "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken)[System.Runtime.CompilerServices.AsyncStateMachineAttribute(typeof(Microsoft.Azure.Cosmos.Encryption.Custom.CosmosDataEncryptionKeyProvider+))]": { + "Type": "Method", + "Attributes": [ + "AsyncStateMachineAttribute" + ], + "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void .ctor(Microsoft.Azure.Cosmos.Encryption.Custom.EncryptionKeyWrapProvider, Microsoft.Data.Encryption.Cryptography.EncryptionKeyStoreProvider, System.Nullable`1[System.TimeSpan])[System.ObsoleteAttribute(\"Please use the constructor with EncryptionKeyStoreProvider only.\")]": { "Type": "Constructor", "Attributes": [ @@ -426,6 +440,11 @@ "Type": "Method", "Attributes": [], "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.Encryption.Custom.DataEncryptionKey] FetchDataEncryptionKeyWithoutRawKeyAsync(System.String, System.String, System.Threading.CancellationToken);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index cd505f1158..4cca513013 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -49,7 +49,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - internal bool EnableOptimisticDirectExecution { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index e5b95a7ed9..8a3bc7b462 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6279,6 +6279,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -6433,6 +6445,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -7301,6 +7320,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -7455,6 +7486,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ From 6024f2433b342f58d738b0339492850a09018309 Mon Sep 17 00:00:00 2001 From: Arooshi Avasthy <113193425+aavasthy@users.noreply.github.com> Date: Wed, 7 Jun 2023 09:15:05 -0700 Subject: [PATCH 131/337] [Internal] OpenTelemetry : Adds Telemetry Distributed Tracing functionality (#3801) * Direct Package update and replacing dagnostic files * Resolve merge conflicts * Running updateCOnstracts script * Add code changes for distributed tracing open telemetry changes * Add distributed tracing tests * Updated tests for distributed tracing * Addin traceID for diagnostics * Running update contract script * Removed LinqTranslationWithCustomSerializerBaseline file * Adding isDistributedTracingEnabled flag * Running update contracts * Running update contracts * Updates based on differnt code review comments * Running update contracts * Running update contracts * Running update contracts * fix test * Code cleanup for test fix * Running Update contracts * resolving merge conflicts * resolving merge conflicts * Set EnableDistributedTracing to true for performance tests * Benchmark project change for distributed tracing * Updating tests * Updated unit tests * Updated unit tests * Updated tests and constructors based on review comments * Updated scope name in recorder * Updated distributedOtel tests to cover more scenarios * Updated distributedOtel tests * Reverting benchmark performance test changes * Update DistributedOpentelemetry tests * Update test cleanup * Update distributed tests with custom builder * Update distributed open telemetry tests * Update contracts * Cleanup files * Update distributed Otel tests * Update distributed Otel tests * code refactoring * fix custom listener * Update direct package to 3.31.1 * Code clean up * Update tests with display name --------- Co-authored-by: Sourabh Jain --- Directory.Build.props | 2 +- .../src/Resource/ClientContextCore.cs | 1 + .../OpenTelemetryAttributeKeys.cs | 1 + .../OpenTelemetryCoreRecorder.cs | 67 +++++- .../OpenTelemetryRecorderFactory.cs | 47 ++-- ...iterBaselineTests.BatchOperationsAsync.xml | 5 +- ...riterBaselineTests.BulkOperationsAsync.xml | 55 ++++- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 90 +++++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 10 +- ...neTests.PointOperationsExceptionsAsync.xml | 30 ++- ...EndTraceWriterBaselineTests.QueryAsync.xml | 84 +++++++ ...TraceWriterBaselineTests.ReadFeedAsync.xml | 80 +++++-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 10 +- ...selineTests.StreamPointOperationsAsync.xml | 20 +- ...aselineTests.TypedPointOperationsAsync.xml | 20 +- .../DistributedTracingOTelTests.cs | 222 ++++++++++++++++++ .../Tracing/AssertActivity.cs | 37 +-- .../Tracing/CustomListener.cs | 12 + .../Tracing/CustomOtelExporter.cs | 3 +- 19 files changed, 695 insertions(+), 101 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs diff --git a/Directory.Build.props b/Directory.Build.props index 7eecd3c8e2..c8b86ceed2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.34.0 3.34.0 preview - 3.31.0 + 3.31.1 2.0.2 2.0.2 preview diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index d16d1c8bcc..42e128ac2e 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -497,6 +497,7 @@ private async Task RunWithDiagnosticsHelperAsync( databaseName: databaseName, operationType: operationType, requestOptions: requestOptions, + trace: trace, clientContext: this.isDisposed ? null : this)) using (new ActivityScope(Guid.NewGuid())) { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 755e1e3a66..1bb66170b5 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -10,6 +10,7 @@ internal sealed class OpenTelemetryAttributeKeys public const string DiagnosticNamespace = "Azure.Cosmos"; public const string ResourceProviderNamespace = "Microsoft.DocumentDB"; public const string OperationPrefix = "Operation"; + public const string NetworkLevelPrefix = "Request"; // Common database attributes public const string DbSystemName = "db.system"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index c199c0727c..2ef929ca8c 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; using System.Collections.Generic; + using System.Diagnostics; using global::Azure.Core; /// @@ -14,11 +15,12 @@ namespace Microsoft.Azure.Cosmos.Telemetry internal struct OpenTelemetryCoreRecorder : IDisposable { private const string CosmosDb = "cosmosdb"; - - private readonly DiagnosticScope scope; - private readonly DistributedTracingOptions config; - private readonly Documents.OperationType operationType; + private readonly DiagnosticScope scope = default; + private readonly DistributedTracingOptions config = null; + private readonly Activity activity = null; + + private readonly Documents.OperationType operationType = Documents.OperationType.Invalid; private OpenTelemetryAttributes response = null; internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() @@ -30,7 +32,19 @@ internal struct OpenTelemetryCoreRecorder : IDisposable { typeof(ChangeFeedProcessorUserException), (exception, scope) => ChangeFeedProcessorUserException.RecordOtelAttributes((ChangeFeedProcessorUserException)exception, scope)} }; - public OpenTelemetryCoreRecorder( + private OpenTelemetryCoreRecorder(DiagnosticScope scope) + { + this.scope = scope; + this.scope.Start(); + } + + private OpenTelemetryCoreRecorder(string operationName) + { + this.activity = new Activity(operationName); + this.activity.Start(); + } + + private OpenTelemetryCoreRecorder( DiagnosticScope scope, string operationName, string containerName, @@ -54,6 +68,45 @@ public OpenTelemetryCoreRecorder( } } + /// + /// Used for creating parent activity in scenario where there are no listeners at operation level + /// but they are present at network level + /// + public static OpenTelemetryCoreRecorder CreateNetworkLevelParentActivity(DiagnosticScope networkScope) + { + return new OpenTelemetryCoreRecorder(networkScope); + } + + /// + /// Used for creating parent activity in scenario where there are no listeners at operation level and network level + /// + public static OpenTelemetryCoreRecorder CreateParentActivity(string operationName) + { + return new OpenTelemetryCoreRecorder(operationName); + } + + /// + /// Used for creating parent activity in scenario where there are listeners at operation level + /// + public static OpenTelemetryCoreRecorder CreateOperationLevelParentActivity( + DiagnosticScope operationScope, + string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, + CosmosClientContext clientContext, + DistributedTracingOptions config) + { + return new OpenTelemetryCoreRecorder( + operationScope, + operationName, + containerName, + databaseName, + operationType, + clientContext, + config); + } + public bool IsEnabled => this.scope.IsEnabled; public void Record(string key, string value) @@ -179,6 +232,10 @@ Documents.OperationType operationType this.scope.Dispose(); } + else + { + this.activity?.Stop(); + } } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index fe10e7b22c..fee3282c1a 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -5,7 +5,9 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; + using System.Diagnostics; using global::Azure.Core; + using Microsoft.Azure.Cosmos.Tracing; /// /// This class is used to generate Activities with Azure.Cosmos.Operation Source Name @@ -15,33 +17,42 @@ internal static class OpenTelemetryRecorderFactory /// /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once /// - private static DiagnosticScopeFactory ScopeFactory { get; set; } - + private static readonly Lazy LazyOperationScopeFactory = new Lazy( + valueFactory: () => new DiagnosticScopeFactory( + clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.OperationPrefix}", + resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, + isActivityEnabled: true, + suppressNestedClientActivities: true), + isThreadSafe: true); + + private static readonly Lazy LazyNetworkScopeFactory = new Lazy( + valueFactory: () => new DiagnosticScopeFactory( + clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.NetworkLevelPrefix}", + resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, + isActivityEnabled: true, + suppressNestedClientActivities: true), + isThreadSafe: true); + public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, string containerName, string databaseName, Documents.OperationType operationType, RequestOptions requestOptions, + ITrace trace, CosmosClientContext clientContext) { + OpenTelemetryCoreRecorder openTelemetryRecorder = default; if (clientContext is { ClientOptions.IsDistributedTracingEnabled: true }) { - OpenTelemetryRecorderFactory.ScopeFactory ??= new DiagnosticScopeFactory(clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.OperationPrefix}", - resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true, - suppressNestedClientActivities: true); - // If there is no source then it will return default otherwise a valid diagnostic scope - DiagnosticScope scope = OpenTelemetryRecorderFactory - .ScopeFactory - .CreateScope(name: operationName, + DiagnosticScope scope = LazyOperationScopeFactory.Value.CreateScope(name: operationName, kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); // Record values only when we have a valid Diagnostic Scope if (scope.IsEnabled) { - return new OpenTelemetryCoreRecorder( - scope: scope, + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateOperationLevelParentActivity( + operationScope: scope, operationName: operationName, containerName: containerName, databaseName: databaseName, @@ -49,9 +60,17 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, clientContext: clientContext, config: requestOptions?.DistributedTracingOptions ?? clientContext.ClientOptions?.DistributedTracingOptions); } - } +#if !INTERNAL + else if (Activity.Current is null) + { + DiagnosticScope requestScope = LazyNetworkScopeFactory.Value.CreateScope(name: operationName); - return default; + openTelemetryRecorder = requestScope.IsEnabled ? OpenTelemetryCoreRecorder.CreateNetworkLevelParentActivity(networkScope: requestScope) : OpenTelemetryCoreRecorder.CreateParentActivity(operationName); + } +#endif + trace.AddDatum("DistributedTraceId", Activity.Current?.TraceId); + } + return openTelemetryRecorder; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 09579f83b7..66ca36f8ba 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -38,6 +38,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── Execute Next Batch(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ├── Create Batch Request(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds @@ -64,7 +66,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index be3a8c7910..b483975a57 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -35,6 +35,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -69,7 +71,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -431,6 +434,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -459,7 +464,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -808,6 +814,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -836,7 +844,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1185,6 +1194,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -1213,7 +1224,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1562,6 +1574,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -1590,7 +1604,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1939,6 +1954,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -1967,7 +1984,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2316,6 +2334,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -2344,7 +2364,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2693,6 +2714,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -2721,7 +2744,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -3070,6 +3094,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -3098,7 +3124,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -3447,6 +3474,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -3475,7 +3504,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -3840,6 +3870,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -4014,7 +4046,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 43d95de95d..ffc97ea44f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -30,6 +30,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -72,6 +74,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -99,6 +103,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -126,6 +132,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -153,6 +161,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -245,7 +255,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -408,7 +419,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -495,7 +507,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -582,7 +595,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -669,7 +683,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1106,6 +1121,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1149,6 +1166,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1177,6 +1196,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1205,6 +1226,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1240,7 +1263,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1407,7 +1431,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1498,7 +1523,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1589,7 +1615,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1833,6 +1860,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1875,6 +1904,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1902,6 +1933,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1929,6 +1962,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1963,7 +1998,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2126,7 +2162,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2213,7 +2250,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2300,7 +2338,8 @@ "name": "Change Feed Iterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2540,6 +2579,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2583,6 +2624,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2611,6 +2654,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2639,6 +2684,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ChangeFeed MoveNextAsync(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2674,7 +2721,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2841,7 +2889,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2932,7 +2981,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -3023,7 +3073,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -3262,6 +3313,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Initialize Lease Store(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -3331,7 +3384,8 @@ "name": "Change Feed Estimator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 29fc40f674..df53bd53d0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -20,6 +20,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ ├── Waiting for Initialization of client to complete(00000000-0000-0000-0000-000000000000) Unknown-Component 00:00:00:000 0.00 milliseconds @@ -47,7 +49,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -175,6 +178,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -200,7 +205,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 9ee0b6e650..902712a2a4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -37,6 +37,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -71,7 +73,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -223,6 +226,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -276,7 +281,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -510,6 +516,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -555,7 +563,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -754,6 +763,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -810,7 +821,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1030,6 +1042,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -1108,7 +1122,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1331,6 +1346,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -1365,7 +1382,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index e9b0f96a00..5075d5d3e9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -24,6 +24,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -64,6 +66,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -97,6 +101,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -130,6 +136,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -171,6 +179,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -298,6 +307,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -391,6 +401,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -484,6 +495,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -697,6 +709,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -738,6 +752,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -772,6 +788,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -806,6 +824,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -848,6 +868,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -979,6 +1000,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1076,6 +1098,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1173,6 +1196,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1391,6 +1415,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -1431,6 +1457,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -1464,6 +1492,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -1497,6 +1527,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -1538,6 +1570,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1665,6 +1698,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1758,6 +1792,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -1851,6 +1886,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -2065,6 +2101,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2106,6 +2144,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2140,6 +2180,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2174,6 +2216,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -2216,6 +2260,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -2347,6 +2392,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -2444,6 +2490,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -2541,6 +2588,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -2762,6 +2810,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2823,6 +2873,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2857,6 +2909,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -2891,6 +2945,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -2933,6 +2989,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3108,6 +3165,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3205,6 +3263,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3302,6 +3361,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3522,6 +3582,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -3563,6 +3625,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -3596,6 +3660,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -3629,6 +3695,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -3670,6 +3738,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3803,6 +3872,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3896,6 +3966,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -3989,6 +4060,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -4205,6 +4277,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -4247,6 +4321,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -4281,6 +4357,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) @@ -4315,6 +4393,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) @@ -4357,6 +4437,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -4494,6 +4575,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -4591,6 +4673,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ @@ -4688,6 +4771,7 @@ "duration in milliseconds": 0, "data": { "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run", "Query Correlated ActivityId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 501a8b187e..2dd4424cb7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -24,6 +24,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -64,6 +66,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -89,6 +93,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -114,6 +120,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -146,7 +154,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -301,7 +310,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -380,7 +390,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -459,7 +470,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -659,6 +671,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -700,6 +714,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -726,6 +742,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -752,6 +770,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -785,7 +805,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -944,7 +965,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1027,7 +1049,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1110,7 +1133,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1315,6 +1339,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1355,6 +1381,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1380,6 +1408,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1405,6 +1435,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1437,7 +1469,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1592,7 +1625,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1671,7 +1705,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1750,7 +1785,8 @@ "name": "FeedIterator Read Next Async", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -1951,6 +1987,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1992,6 +2030,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2018,6 +2058,8 @@ │ │ ( │ │ [Client Configuration] │ │ Redacted To Not Change The Baselines From Run To Run + │ │ [DistributedTraceId] + │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2044,6 +2086,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) ReadFeed-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2077,7 +2121,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2236,7 +2281,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2319,7 +2365,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -2402,7 +2449,8 @@ "name": "Typed FeedIterator ReadNextAsync", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 627a8ea66f..362afa7444 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -16,6 +16,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -141,7 +143,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -582,6 +585,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -710,7 +715,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 016a37aaaf..8816767262 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -22,6 +22,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -44,7 +46,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -132,6 +135,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -154,7 +159,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -250,6 +256,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -272,7 +280,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -363,6 +372,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) └── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -385,7 +396,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index add1fcc343..f23344b440 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -20,6 +20,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Get PkValue From Stream(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -46,7 +48,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -152,6 +155,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -175,7 +180,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -275,6 +281,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── ItemSerialize(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -299,7 +307,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { @@ -397,6 +406,8 @@ │ ( │ [Client Configuration] │ Redacted To Not Change The Baselines From Run To Run + │ [DistributedTraceId] + │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds @@ -420,7 +431,8 @@ "start datetime": "0001-01-01T00:00:00Z", "duration in milliseconds": 0, "data": { - "Client Configuration": "Redacted To Not Change The Baselines From Run To Run" + "Client Configuration": "Redacted To Not Change The Baselines From Run To Run", + "DistributedTraceId": "Redacted To Not Change The Baselines From Run To Run" }, "children": [ { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs new file mode 100644 index 0000000000..8b5825831c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs @@ -0,0 +1,222 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json.Linq; + using OpenTelemetry.Trace; + using OpenTelemetry; + using AzureCore = global::Azure.Core; + using Microsoft.Azure.Cosmos.Telemetry; + using System.Diagnostics; + using Microsoft.Azure.Cosmos.Tracing; + using System.Net.Http; + using System.ComponentModel; + + [VisualStudio.TestTools.UnitTesting.TestClass] + public sealed class DistributedTracingOTelTests : BaseCosmosClientHelper + { + [TestInitialize] + public void TestInitialize() + { + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); + AzureCore.ActivityExtensions.ResetFeatureSwitch(); + } + + [DataTestMethod] + [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] + [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] + public async Task SourceEnabled_FlagOn_DirectMode_RecordsActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) + { + string[] sources = new string[] { operationLevelSource, networkLevelSource }; + sources = sources.Where(x => x != null).ToArray(); + + using TracerProvider provider = Sdk.CreateTracerProviderBuilder() + .AddCustomOtelExporter() + .AddSource(sources) + .Build(); + + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithDistributedTracing(true) + .WithConnectionModeDirect()); + + Container containerResponse = await this.database.CreateContainerAsync( + id: Guid.NewGuid().ToString(), + partitionKeyPath: "/id", + throughput: 20000); + + CosmosObject cosmosObject = CosmosObject.Create( + new Dictionary() + { + { "id", CosmosString.Create("1") } + }); + + ItemResponse createResponse = await containerResponse.CreateItemAsync(JToken.Parse(cosmosObject.ToString())); + + //Assert traceparent header in Direct mode request + Assert.IsTrue(createResponse.RequestMessage.Headers.TryGetValue("traceparent", out string traceheader)); + Assert.IsNotNull(traceheader); + string[] traceheaderParts = traceheader.Split('-'); + string traceheaderId = traceheaderParts[1]; + + //Assert traceId in Diagnostics logs + string diagnosticsCreateItem = createResponse.Diagnostics.ToString(); + JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateItem); + string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; + Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId)); + + //Assert diagnostics log trace id is same as parent trace id of the activity + string operationName = (string)objDiagnosticsCreate["name"]; + string traceIdCreateItem = CustomOtelExporter.CollectedActivities + .Where(x => x.OperationName.Contains(operationName)) + .FirstOrDefault() + .TraceId + .ToString(); + //Assert created activity traceId and diagnosticsLog traceId + Assert.AreEqual(distributedTraceId, traceIdCreateItem); + + //Assert requestHeader trace id and and diagnosticsLog traceId + Assert.AreEqual(distributedTraceId, traceheaderId); + + //Assert activity creation + Assert.IsNotNull(CustomOtelExporter.CollectedActivities); + + if (networkLevelSource != null) + { + // Assert activity created at network level have an existing parent activity + Activity networkLevelChildActivity = CustomOtelExporter.CollectedActivities + .Where(x => x.OperationName.Contains("Request")) + .FirstOrDefault(); + Assert.IsNotNull(CustomOtelExporter.CollectedActivities + .Where(x => x.Id == networkLevelChildActivity.ParentId)); + } + } + + [DataTestMethod] + [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] + [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] + public async Task SourceEnabled_FlagOn_GatewayMode_RecordsActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) + { + string[] sources = new string[] { operationLevelSource, networkLevelSource }; + sources = sources.Where(x => x != null).ToArray(); + + HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.Headers.TryGetValues("traceparent", out IEnumerable traceparentHeaderValues)) + { + Assert.IsNotNull(traceparentHeaderValues); + } + return null; + } + }; + + using TracerProvider provider = Sdk.CreateTracerProviderBuilder() + .AddCustomOtelExporter() + .AddSource(sources) + .Build(); + + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithDistributedTracing(true) + .WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper)) + .WithConnectionModeGateway()); + + ContainerResponse containerResponse = await this.database.CreateContainerAsync( + id: Guid.NewGuid().ToString(), + partitionKeyPath: "/id", + throughput: 20000); + + List b = CustomOtelExporter.CollectedActivities.ToList(); + //Assert traceId in Diagnostics logs + string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); + JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); + string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; + Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId)); + + //Assert diagnostics log trace id is same as parent trace id of the activity + string operationName = (string)objDiagnosticsCreate["name"]; + string traceIdCreateContainer = CustomOtelExporter.CollectedActivities + .Where(x => x.OperationName.Contains(operationName)) + .FirstOrDefault() + .TraceId + .ToString(); + Assert.AreEqual(distributedTraceId, traceIdCreateContainer); + + //Assert activity creation + Assert.IsNotNull(CustomOtelExporter.CollectedActivities); + } + + [DataTestMethod] + [DataRow(false, true, "random.source.name", DisplayName = "DirectMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] + [DataRow(true, true, "random.source.name", DisplayName = "GatewayMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] + [DataRow(false, false, "random.source.name", DisplayName = "DirectMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] + [DataRow(true, false, "random.source.name", DisplayName = "GatewayMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] + [DataRow(false, false, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "DirectMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] + [DataRow(true, false, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "GatewayMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] + public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_AssertLogTraceId(bool useGateway, bool enableDistributingTracing, string source) + { + using TracerProvider provider = Sdk.CreateTracerProviderBuilder() + .AddCustomOtelExporter() + .AddSource(source) + .Build(); + + if (useGateway) + { + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithDistributedTracing(enableDistributingTracing) + .WithConnectionModeGateway()); + } + else + { + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithDistributedTracing(enableDistributingTracing)); + } + + ContainerResponse containerResponse = await this.database.CreateContainerAsync( + id: Guid.NewGuid().ToString(), + partitionKeyPath: "/id", + throughput: 20000); + + //Assert traceId in Diagnostics logs + string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); + JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); + + if (enableDistributingTracing) + { + //DistributedTraceId present in logs + string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; + Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId), "Distributed Trace Id is not there in diagnostics"); + } + else + { + //DistributedTraceId field not present in logs + Assert.IsNull(objDiagnosticsCreate["data"]["DistributedTraceId"], "Distributed Trace Id has value in diagnostics i.e. " + (string)objDiagnosticsCreate["data"]["DistributedTraceId"]); + } + + //Assert no activity with attached source is created + Assert.AreEqual(0, CustomOtelExporter.CollectedActivities.Count()); + } + + [TestCleanup] + public async Task CleanUp() + { + await base.TestCleanup(); + + AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", false); + AzureCore.ActivityExtensions.ResetFeatureSwitch(); + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index e25a46e44c..b1223656f1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -4,9 +4,11 @@ namespace Microsoft.Azure.Cosmos.Tracing { + using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using global::Azure; using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -16,20 +18,22 @@ internal static class AssertActivity { public static void IsValidOperationActivity(Activity activity) { - Assert.IsTrue(activity.OperationName == activity.DisplayName); + if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase)) + { + Assert.IsTrue(activity.OperationName == activity.DisplayName); - Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is emtpy for {activity.OperationName}"); + Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is emtpy for {activity.OperationName}"); - if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) - { - Assert.AreEqual(ActivityKind.Internal, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Internal} for {activity.OperationName}"); - } - else if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Direct.ToString()) - { - Assert.AreEqual(ActivityKind.Client, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Client} for {activity.OperationName}"); - } - - IList expectedTags = new List + if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) + { + Assert.AreEqual(ActivityKind.Internal, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Internal} for {activity.OperationName}"); + } + else if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Direct.ToString()) + { + Assert.AreEqual(ActivityKind.Client, activity.Kind, $" Actual Kind is {activity.Kind} but expected is {ActivityKind.Client} for {activity.OperationName}"); + } + + IList expectedTags = new List { "az.namespace", "az.schema_url", @@ -60,11 +64,12 @@ public static void IsValidOperationActivity(Activity activity) "db.cosmosdb.correlated_activity_id" }; - foreach (KeyValuePair actualTag in activity.Tags) - { - Assert.IsTrue(expectedTags.Contains(actualTag.Key), $"{actualTag.Key} is not allowed for {activity.OperationName}"); + foreach (KeyValuePair actualTag in activity.Tags) + { + Assert.IsTrue(expectedTags.Contains(actualTag.Key), $"{actualTag.Key} is not allowed for {activity.OperationName}"); - AssertActivity.AssertDatabaseAndContainerName(activity.OperationName, actualTag); + AssertActivity.AssertDatabaseAndContainerName(activity.OperationName, actualTag); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index b0df15c3f2..44d34abece 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -34,6 +34,8 @@ internal class CustomListener : public static ConcurrentBag CollectedNetworkActivities { private set; get; } = new(); private static ConcurrentBag CollectedEvents { set; get; } = new(); + private static List EventSources { set; get; } = new(); + public CustomListener(string name, string eventName) : this(n => Regex.Match(n, name).Success, eventName) { @@ -43,6 +45,11 @@ public CustomListener(Func filter, string eventName) { this.sourceNameFilter = filter; this.eventName = eventName; + + foreach (EventSource eventSource in EventSources) + { + this.OnEventSourceCreated(eventSource); + } DiagnosticListener.AllListeners.Subscribe(this); } @@ -152,6 +159,11 @@ public void OnNext(DiagnosticListener value) /// protected override void OnEventSourceCreated(EventSource eventSource) { + if(this.eventName == null) + { + EventSources.Add(eventSource); + } + if (eventSource != null && eventSource.Name.Equals(this.eventName)) { this.EnableEvents(eventSource, EventLevel.Informational); // Enable information level events diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs index de819ee021..9572a298a6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -18,11 +18,12 @@ internal class CustomOtelExporter : BaseExporter { private readonly string _name; - public static List CollectedActivities = new List(); + public static List CollectedActivities; public CustomOtelExporter(string name = "CustomOtelExporter") { this._name = name; + CollectedActivities = new List(); } public override ExportResult Export(in Batch batch) From e08fd5242f2129c4f0297447f35ec69881a11682 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Thu, 8 Jun 2023 07:29:04 -0700 Subject: [PATCH 132/337] Documentation: Adds additional remarks to CosmosClient (#3891) * CosmosClient documentation improvements * Cref fix * Link fix * Documentation fix * Typo fix --------- Co-authored-by: Matias Quaranta --- Microsoft.Azure.Cosmos/src/CosmosClient.cs | 20 ++++++++++++++++++- .../src/Fluent/CosmosClientBuilder.cs | 13 ++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index d4fe7dcb9b..d622e9ddcb 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -92,6 +92,9 @@ namespace Microsoft.Azure.Cosmos /// ]]> /// /// + /// + /// The returned not-initialized reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls + /// /// /// /// Performance Tips @@ -179,6 +182,9 @@ protected CosmosClient() /// ]]> /// /// + /// + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. + /// /// /// /// Performance Tips @@ -221,6 +227,9 @@ public CosmosClient( /// ]]> /// /// + /// + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. + /// /// /// /// Performance Tips @@ -274,7 +283,10 @@ public CosmosClient( /// /// Performance Tips /// Diagnose and troubleshoot issues - /// AzureKeyCredential enables changing/updating master-key/ResourceToken whle CosmosClient is still in use. + /// + /// AzureKeyCredential enables changing/updating master-key/ResourceToken whle CosmosClient is still in use. + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. + /// public CosmosClient( string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, @@ -292,6 +304,9 @@ public CosmosClient( /// of the application which enables efficient connection management and performance. Please refer to the /// performance guide. /// + /// + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. + /// /// The cosmos service endpoint to use. /// The token to provide AAD token for authorization. /// (Optional) client options @@ -368,6 +383,9 @@ internal CosmosClient( /// ]]> /// /// + /// + /// The returned reference doesn't guarantee credentials or connectivity validations because initialization doesn't make any network calls. + /// public static async Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList<(string databaseId, string containerId)> containers, diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 692d5b498a..8b72bfffa4 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -167,9 +167,13 @@ public CosmosClientBuilder( /// /// A method to create the cosmos client + /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime + /// of the application which enables efficient connection management and performance. Please refer to the + /// performance guide. /// /// /// Setting this property after sending any request won't have any effect. + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. /// /// An instance of . public CosmosClient Build() @@ -191,6 +195,11 @@ public CosmosClient Build() /// /// A method to create the cosmos client and initialize the provided containers. + /// In addition to that it initializes the client with containers provided i.e The SDK warms up the caches and + /// connections before the first call to the service is made. Use this to obtain lower latency while startup of your application. + /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime + /// of the application which enables efficient connection management and performance. Please refer to the + /// performance guide. /// /// Containers to be initialized identified by it's database name and container name. /// (Optional) Cancellation Token @@ -214,9 +223,13 @@ public Task BuildAndInitializeAsync(IReadOnlyList<(string database /// /// A method to create the cosmos client + /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime + /// of the application which enables efficient connection management and performance. Please refer to the + /// performance guide. /// /// /// Setting this property after sending any request won't have any effect. + /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. /// internal virtual CosmosClient Build(DocumentClient documentClient) { From d58b44138e07f17dcd8db5b80400a47c4561c095 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 9 Jun 2023 02:00:27 +0530 Subject: [PATCH 133/337] Open Telemetry End To End Test: Adds baseline for network level requests trace (#3887) * enable request level in end to end * made some changes * fix tests * fix display name * hardcoded containername and databasenam * fix tests * temp * fix tests * update contracts * fix tests * fixed display name --- .../OpenTelemetryRecorderFactory.cs | 2 + ...iterBaselineTests.BatchOperationsAsync.xml | 13 +- ...riterBaselineTests.BulkOperationsAsync.xml | 676 ++++++++++-------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 189 +++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 28 +- ...neTests.PointOperationsExceptionsAsync.xml | 36 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 217 +++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 124 ++-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 26 +- ...selineTests.StreamPointOperationsAsync.xml | 52 +- ...aselineTests.TypedPointOperationsAsync.xml | 52 +- .../Tracing/AssertActivity.cs | 4 +- .../Tracing/CustomListener.cs | 35 +- .../Tracing/CustomOtelExporter.cs | 10 +- .../EndToEndTraceWriterBaselineTests.cs | 10 +- .../Utils/Util.cs | 4 +- 16 files changed, 895 insertions(+), 583 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index fee3282c1a..ca0b864d2f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -51,6 +51,8 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, // Record values only when we have a valid Diagnostic Scope if (scope.IsEnabled) { + scope.SetDisplayName($"{operationName} {containerName}"); + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateOperationLevelParentActivity( operationScope: scope, operationName: operationName, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 66ca36f8ba..66edf29c06 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -132,12 +132,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ExecuteAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -155,6 +155,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 1001 + 207 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index b483975a57..053f6ecc39 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -156,12 +156,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -179,12 +179,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -202,12 +202,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -225,12 +225,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -248,12 +248,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -271,12 +271,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -294,12 +294,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -317,12 +317,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -340,12 +340,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -363,12 +363,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -386,6 +386,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -536,12 +543,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -559,12 +566,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -582,12 +589,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -605,12 +612,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -628,12 +635,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -651,12 +658,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -674,12 +681,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -697,12 +704,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -720,12 +727,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -743,12 +750,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -766,6 +773,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -916,12 +930,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -939,12 +953,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -962,12 +976,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -985,12 +999,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1008,12 +1022,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1031,12 +1045,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1054,12 +1068,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1077,12 +1091,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1100,12 +1114,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1123,12 +1137,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1146,6 +1160,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1296,12 +1317,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1319,12 +1340,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1342,12 +1363,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1365,12 +1386,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1388,12 +1409,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1411,12 +1432,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1434,12 +1455,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1457,12 +1478,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1480,12 +1501,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1503,12 +1524,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1526,6 +1547,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1676,12 +1704,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1699,12 +1727,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1722,12 +1750,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1745,12 +1773,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1768,12 +1796,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1791,12 +1819,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1814,12 +1842,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1837,12 +1865,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1860,12 +1888,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1883,12 +1911,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1906,6 +1934,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -2056,12 +2091,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2079,12 +2114,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2102,12 +2137,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2125,12 +2160,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2148,12 +2183,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2171,12 +2206,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2194,12 +2229,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2217,12 +2252,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2240,12 +2275,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2263,12 +2298,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2286,6 +2321,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -2436,12 +2478,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2459,12 +2501,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2482,12 +2524,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2505,12 +2547,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2528,12 +2570,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2551,12 +2593,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2574,12 +2616,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2597,12 +2639,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2620,12 +2662,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2643,12 +2685,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2666,6 +2708,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -2816,12 +2865,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2839,12 +2888,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2862,12 +2911,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2885,12 +2934,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2908,12 +2957,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2931,12 +2980,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2954,12 +3003,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2977,12 +3026,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3000,12 +3049,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3023,12 +3072,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3046,6 +3095,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -3196,12 +3252,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3219,12 +3275,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3242,12 +3298,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3265,12 +3321,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3288,12 +3344,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3311,12 +3367,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3334,12 +3390,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3357,12 +3413,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3380,12 +3436,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3403,12 +3459,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3426,6 +3482,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -3576,12 +3639,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3599,12 +3662,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3622,12 +3685,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3645,12 +3708,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3668,12 +3731,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3691,12 +3754,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3714,12 +3777,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3737,12 +3800,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3760,12 +3823,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3783,12 +3846,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3806,6 +3869,13 @@ Some Value + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -4547,12 +4617,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index ffc97ea44f..379c887104 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -967,12 +967,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -990,12 +990,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1013,12 +1013,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1036,12 +1036,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1059,12 +1059,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1082,6 +1082,20 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 304 + @@ -1705,12 +1719,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1728,12 +1742,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1751,12 +1765,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1774,12 +1788,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1797,12 +1811,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1820,6 +1834,20 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 304 + @@ -2424,12 +2452,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2447,12 +2475,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2470,12 +2498,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2493,12 +2521,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2516,12 +2544,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Iterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2539,6 +2567,20 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 304 + @@ -3163,12 +3205,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3186,12 +3228,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3209,12 +3251,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3232,12 +3274,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3255,12 +3297,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3278,6 +3320,20 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 304 + @@ -3556,12 +3612,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Change Feed Estimator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3579,6 +3635,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index df53bd53d0..7341e76cb9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -4,7 +4,7 @@ Custom Handler - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 DeleteAsync - Some Value - Some Value + miscdbcustonhandler + cosmosdb Some Value 127.0.0.1 @@ -133,12 +133,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateDatabaseAsync - Some Value - Some Value + miscdbcustonhandler + cosmosdb Some Value 127.0.0.1 @@ -166,7 +166,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 DeleteAsync - Some Value - Some Value + miscdbdataplane + cosmosdb Some Value 127.0.0.1 @@ -279,12 +279,12 @@ Some Value - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateDatabaseAsync - Some Value - Some Value + miscdbdataplane + cosmosdb Some Value 127.0.0.1 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 902712a2a4..4e11d5e4b7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -151,12 +151,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -415,12 +415,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -662,12 +662,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -941,12 +941,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1284,12 +1284,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1460,12 +1460,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 5075d5d3e9..8b737a419e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -586,12 +586,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -609,12 +609,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -632,12 +632,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -655,12 +655,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -678,6 +678,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1291,12 +1298,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1314,12 +1321,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1337,12 +1344,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1360,12 +1367,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1383,6 +1390,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1977,12 +1991,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2000,12 +2014,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2023,12 +2037,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2046,12 +2060,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2069,6 +2083,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -2683,12 +2704,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2706,12 +2727,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2729,12 +2750,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2752,12 +2773,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2775,6 +2796,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -3456,12 +3484,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3479,12 +3507,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3502,12 +3530,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3525,12 +3553,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -3548,6 +3576,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -4151,12 +4186,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4174,12 +4209,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4197,12 +4232,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4220,12 +4255,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4243,6 +4278,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -4866,12 +4908,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4889,12 +4931,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4912,12 +4954,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4935,12 +4977,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -4958,6 +5000,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 2dd4424cb7..86f16841b5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -548,12 +548,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -571,12 +571,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -594,12 +594,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -617,12 +617,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -640,6 +640,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1215,12 +1222,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1238,12 +1245,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1261,12 +1268,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1284,12 +1291,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1307,6 +1314,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1863,12 +1877,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1886,12 +1900,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1909,12 +1923,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1932,12 +1946,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 FeedIterator Read Next Async - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1955,6 +1969,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -2531,12 +2552,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2554,12 +2575,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2577,12 +2598,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2600,12 +2621,12 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 Typed FeedIterator ReadNextAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -2623,6 +2644,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 362afa7444..42c948a0d9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -545,12 +545,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReadManyItemsStreamAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -568,6 +568,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -1129,12 +1136,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReadManyItemsAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -1152,6 +1159,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 8816767262..ea5327040a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -92,12 +92,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemStreamAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -115,6 +115,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 201 + @@ -205,12 +212,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReadItemStreamAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -228,6 +235,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -326,12 +340,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReplaceItemStreamAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -349,6 +363,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -442,12 +463,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 DeleteItemStreamAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -465,6 +486,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 204 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index f23344b440..25b6e52364 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -112,12 +112,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 CreateItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -135,6 +135,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 201 + @@ -230,12 +237,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReadItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -253,6 +260,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -361,12 +375,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 ReplaceItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -384,6 +398,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 200 + @@ -481,12 +502,12 @@ } ] }]]> - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.17.0 DeleteItemAsync - Some Value - Some Value + databaseName + containerName cosmosdb Some Value 127.0.0.1 @@ -504,6 +525,13 @@ Some Value South Central US + + Microsoft.DocumentDB + https://opentelemetry.io/schemas/1.17.0 + Some Value + 0 + 204 + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index b1223656f1..75153d3b88 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -20,9 +20,7 @@ public static void IsValidOperationActivity(Activity activity) { if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase)) { - Assert.IsTrue(activity.OperationName == activity.DisplayName); - - Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is emtpy for {activity.OperationName}"); + Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is empty for {activity.OperationName}"); if (activity.GetTagItem("db.cosmosdb.connection_mode").ToString() == ConnectionMode.Gateway.ToString()) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 44d34abece..cae05fa94d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -242,9 +242,13 @@ private string GenerateTagForBaselineTest(Activity activity) "db.operation", "db.system", "net.peer.name", + "db.name", + "db.cosmosdb.container", "db.cosmosdb.connection_mode", "db.cosmosdb.operation_type", - "db.cosmosdb.regions_contacted" + "db.cosmosdb.regions_contacted", + "tcp.sub_status_code", + "tcp.status_code" }; StringBuilder builder = new StringBuilder(); @@ -278,18 +282,18 @@ public List GetRecordedAttributes() generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); } - /* List collectedNetworkActivities = new List(CustomListener.CollectedNetworkActivities); - collectedNetworkActivities = collectedNetworkActivities + HashSet collectedNetworkActivities = new HashSet(CustomListener.CollectedNetworkActivities, new NetworkActivityComparer()); + List orderedUniqueNetworkActivities = collectedNetworkActivities .OrderBy(act => act.Source.Name + act.OperationName + - act.GetTagItem("rntbd.status_code") + - act.GetTagItem("rntbd.sub_status_code")) + act.GetTagItem("tcp.status_code") + + act.GetTagItem("tcp.sub_status_code")) .ToList(); - foreach (Activity activity in collectedNetworkActivities) + foreach (Activity activity in orderedUniqueNetworkActivities) { generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); - }*/ + } List outputList = new List(); if(generatedActivityTagsForBaselineXmls != null && generatedActivityTagsForBaselineXmls.Count > 0) @@ -345,5 +349,22 @@ public ProducedLink(string traceparent, string tracestate) public string Traceparent { get; set; } public string Tracestate { get; set; } } + + public class NetworkActivityComparer : IEqualityComparer + { + public bool Equals(Activity x, Activity y) + { + string xData = x.Source.Name + x.OperationName + x.GetTagItem("tcp.status_code") + x.GetTagItem("tcp.sub_status_code"); + string yData = y.Source.Name + y.OperationName + y.GetTagItem("tcp.status_code") + y.GetTagItem("tcp.sub_status_code"); + + return xData.Equals(yData, StringComparison.OrdinalIgnoreCase); + } + + public int GetHashCode(Activity obj) + { + return (obj.Source.Name + obj.OperationName + obj.GetTagItem("tcp.status_code") + obj.GetTagItem("tcp.sub_status_code")).GetHashCode() ; + } + } + } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs index 9572a298a6..eb46d83e48 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Tracing using System; using System.Collections.Generic; using System.Diagnostics; + using Microsoft.Azure.Cosmos.Telemetry; using OpenTelemetry; using OpenTelemetry.Trace; @@ -34,9 +35,12 @@ public override ExportResult Export(in Batch batch) foreach (Activity activity in batch) { - AssertActivity.IsValidOperationActivity(activity); - - CollectedActivities.Add(activity); + if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase)) + { + AssertActivity.IsValidOperationActivity(activity); + + CollectedActivities.Add(activity); + } } return ExportResult.Success; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 63d883ef21..64bc7c015a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -71,11 +71,11 @@ public static async Task ClassInitAsync(TestContext context) })); EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( - Guid.NewGuid().ToString(), + "databaseName", cancellationToken: default); EndToEndTraceWriterBaselineTests.container = await EndToEndTraceWriterBaselineTests.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), + id: "containerName", partitionKeyPath: "/id", throughput: 20000); @@ -401,7 +401,7 @@ public async Task ChangeFeedAsync() //---------------------------------------------------------------- { Container leaseContainer = await EndToEndTraceWriterBaselineTests.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), + id: "changefeedleasecontainer", partitionKeyPath: "/id"); ChangeFeedProcessor processor = container @@ -1347,7 +1347,7 @@ public async Task MiscellanousAsync() { startLineNumber = GetLineNumber(); - DatabaseResponse databaseResponse = await miscCosmosClient.CreateDatabaseAsync(Guid.NewGuid().ToString()); + DatabaseResponse databaseResponse = await miscCosmosClient.CreateDatabaseAsync("miscdbcustonhandler"); EndToEndTraceWriterBaselineTests.AssertCustomHandlerTime( databaseResponse.Diagnostics.ToString(), requestHandler.FullHandlerName, @@ -1370,7 +1370,7 @@ public async Task MiscellanousAsync() startLineNumber = GetLineNumber(); RequestOptions requestOptions = new RequestOptions(); DatabaseResponse databaseResponse = await client.CreateDatabaseAsync( - id: Guid.NewGuid().ToString(), + id: "miscdbdataplane", requestOptions: requestOptions); ITrace trace = ((CosmosTraceDiagnostics)databaseResponse.Diagnostics).Value; await databaseResponse.Database.DeleteAsync(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 4773c7de96..366cc68811 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -548,11 +548,11 @@ internal static CustomListener ConfigureOpenTelemetryAndCustomListeners() // Open Telemetry Listener Util.OTelTracerProvider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() // use any exporter here - .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") + .AddSource($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*") .Build(); // Custom Listener - Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", "Azure-Cosmos-Operation-Request-Diagnostics"); + Util.TestListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics"); return Util.TestListener; From df630928ca7f421177998464fd57b31ce27cd84e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Sat, 10 Jun 2023 01:52:17 +0530 Subject: [PATCH 134/337] [Internal] Design Docs: Adds Design Document for Client Telemetry (#3590) * sdk design for client telemetry * Otel design * update optel design * added more nformation * updated ct design * remove otel design * Client Telemetry Design * update typos * fix typos * fix typos * added limitation * updated docs * updated doc * updated text * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * move stuff here and there. --------- Co-authored-by: Kiran Kumar Kolli --- docs/observability.md | 73 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/docs/observability.md b/docs/observability.md index b74b55cd21..184d609f76 100644 --- a/docs/observability.md +++ b/docs/observability.md @@ -33,4 +33,75 @@ flowchart TD OtherLogic --> GetResponse(Get Response for the request) SendResponse --> OperationCall -``` \ No newline at end of file +``` + +## Send telemetry from SDK to service (Private Preview) + +### Introduction +When opted-in CosmosDB SDK collects below aggregated telemetry data every 10 minutes to Azure CosmosDB service. +1. Operation(CRUD APIs) Latencies and Request Units (RUs). +2. Metadata caches (ex: CollectionCache) miss statistics +3. Client System Usage (during an operation) : + * CPU usage + * Memory Usage + * Thread Starvation + * Network Connections Opened (only TCP Connections) +4. TOP 10 slower network interactions + +> Note: We don't collect any PII data as part of this feature. + +### Benefits +Enabling this feature provides numerous benefits. The telemetry data collected will allow us to identify and address potential issues. This results in a superior support experience and ensures that some issues can even be resolved before they impact your application. In short, customers with this feature enabled can expect a smoother and more reliable experience. + +### Impact of this feature enabled +* _Latency_: Customer should not see any impact on latency. +* _Total RPS_: It depends on the infrastructure the application using SDK is hosted on among other factors but the impact should not exceed 10%. +* _Any other impact_: Collector needs around 18MB of in-memory storage to hold the data and this storage is always constant (it means it doesn't grow, no matter how much data we have) +* Benchmark Numbers: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json + +### Components + +**Telemetry Job:** Background task which collects the data and sends it to a Azure CosmosDB service every 10 minutes. + +**Collectors:** In-memory storage which keeps the telemetry data collected during an operation. There are 3 types of collectors including: +* _Operational Data Collector_: It keeps operation level latencies and request units. +* _Network Data Collector_: It keeps all the metrics related to network or TCP calls. It has its own Sampler which sample-in only slowest TCP calls for a particular replica. +* _Cache Data Collector_: It keeps all the cache call latencies. Right now, only collection cache is covered. + +**Get VM Information**: + +- Azure VM: [Azure Instance Metadata](https://learn.microsoft.com/azure/virtual-machines/instance-metadata-service?tabs=windows) call. +- Non-Azure VM: We don't collect any other information except VMID which will a Guid or Hashed Machine Name. + +**Processor**: Its responsibility is to get all the data and divide it into small chunks (<2MB) and send each chunk to the Azure CosmosDB service. + +```mermaid +flowchart TD + subgraph TelemetryJob[Telemetry Background Job] + subgraph Storage[In Memory Storage or Collectors] + subgraph NetworkDataCollector[Network Data Collector] + TcpDatapoint(Network Request Datapoint) --> NetworkHistogram[(Histogram)] + DataSampler(Sampler) + end + subgraph DataCollector[Operational Data Collector] + OpsDatapoint(Operation Datapoint) --> OperationHistogram[(Histogram)] + end + subgraph CacheCollector[Cache Data Collector] + CacheDatapoint(Cache Request Datapoint) --> CacheHistogram[(Histogram)] + end + end + subgraph TelemetryTask[Telemetry Task Every 10 min] + CacheAccountInfo(Cached Account Properties) --> VMInfo + VMInfo(Get VM Information) --> CollectSystemUsage + CollectSystemUsage(Record System Usage Information) --> GetDataFromCollector + end + subgraph Processor + GetDataFromCollector(Fetch Data from Collectors) --> Serializer + Serializer(Serialize and divide the Payload) --> SendCTOverHTTP(Send Data over HTTP to Service) + end + Storage --> |Get Aggregated data|GetDataFromCollector + end +``` + +### Limitations +1. AAD Support is not available. \ No newline at end of file From d1dbe94ee4e855ef90a6997ab075d7306413ff1e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Sat, 10 Jun 2023 03:06:17 +0530 Subject: [PATCH 135/337] [Internal] Design Docs: Adds Design Document for Client Telemetry Part 2 (#3903) * updated doc * Update docs/observability.md Co-authored-by: Justine Cocchi * updated text --------- Co-authored-by: Justine Cocchi --- docs/observability.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/observability.md b/docs/observability.md index 184d609f76..50ce14d33c 100644 --- a/docs/observability.md +++ b/docs/observability.md @@ -39,19 +39,19 @@ flowchart TD ### Introduction When opted-in CosmosDB SDK collects below aggregated telemetry data every 10 minutes to Azure CosmosDB service. -1. Operation(CRUD APIs) Latencies and Request Units (RUs). +1. Operation(Point, Stream, Batch and Query APIs) Latencies and Request Units (RUs). 2. Metadata caches (ex: CollectionCache) miss statistics -3. Client System Usage (during an operation) : +3. Host Resource Usage: (during an operation) : * CPU usage * Memory Usage * Thread Starvation * Network Connections Opened (only TCP Connections) -4. TOP 10 slower network interactions +4. TOP 10 slowest network interactions per endpoint > Note: We don't collect any PII data as part of this feature. ### Benefits -Enabling this feature provides numerous benefits. The telemetry data collected will allow us to identify and address potential issues. This results in a superior support experience and ensures that some issues can even be resolved before they impact your application. In short, customers with this feature enabled can expect a smoother and more reliable experience. +Enabling this feature provides numerous benefits. The telemetry data collected will allow us to identify and address potential issues. This results in a superior support experience and ensures that some issues can even be resolved before they impact your application. In short, customers with this feature enabled can expect a smoother and more reliable support experience. ### Impact of this feature enabled * _Latency_: Customer should not see any impact on latency. From 28e03c8bd490a2f3c955dea02eb1bd78b0eda61a Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 9 Jun 2023 19:07:04 -0700 Subject: [PATCH 136/337] ConnectionPolicy: Refactors Code to Reduce Default Request Timeout to 6 Seconds. (#3902) * Code changes to reduce default request timeout to 6 seconds. * Code changes to update API doc default request timeout to 6 seconds. --- Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs | 2 +- Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index 172aac4fbb..7abfd76deb 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -19,7 +19,7 @@ namespace Microsoft.Azure.Cosmos /// internal sealed class ConnectionPolicy { - private const int defaultRequestTimeout = 10; + private const int defaultRequestTimeout = 6; // defaultMediaRequestTimeout is based upon the blob client timeout and the retry policy. private const int defaultMediaRequestTimeout = 300; private const int defaultMaxConcurrentFanoutRequests = 32; diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index c826bb90d1..1fce195915 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -223,7 +223,7 @@ public int GatewayModeMaxConnectionLimit /// Gets the request timeout in seconds when connecting to the Azure Cosmos DB service. /// The number specifies the time to wait for response to come back from network peer. ///
- /// Default value is 1 minute. + /// Default value is 6 seconds. /// public TimeSpan RequestTimeout { get; set; } From b9242094bada0cb5b05851ff077f068019b57d7b Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 9 Jun 2023 21:39:37 -0700 Subject: [PATCH 137/337] [Internal] Upgrade Resiliency: Adds Replica Health State Diagnostics. (#3835) * Code changes to add replica health status in diagnostics. * Code changes to fix performance test build failure. * Code changes to add health state capture logic in address cache. * Code changes to fix benchmark test execution. * Code changes to add tests to validate health state cache. * Code changes to reduce default request timeout to 5 seconds. * Revert "Code changes to reduce default request timeout to 5 seconds." This reverts commit 139f37e588fc9dfed608431f4186c567a080e622. --- .../src/Routing/GatewayAddressCache.cs | 23 +++++++ .../Tracing/TraceWriter.TraceJsonWriter.cs | 18 ++++++ .../Contracts/BenchmarkResults.json | 6 +- .../TraceWriterBaselineTests.TraceData.xml | 7 ++ .../GatewayAddressCacheTests.cs | 64 +++++++++++++++++++ .../Tracing/TraceTests.cs | 2 - 6 files changed, 115 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 182243ec40..14b641959a 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -550,10 +550,17 @@ await this.GetServerAddressesViaGatewayAsync(request, collectionRid, new[] { par } this.ValidateReplicaAddresses(transportAddressUris); + this.CaptureTransportAddressUriHealthStates( + partitionAddressInformation: mergedAddresses, + transportAddressUris: transportAddressUris); return mergedAddresses; } + this.CaptureTransportAddressUriHealthStates( + partitionAddressInformation: result.Item2, + transportAddressUris: result.Item2.Get(Protocol.Tcp)?.ReplicaTransportAddressUris); + return result.Item2; } } @@ -936,6 +943,22 @@ TransportAddressHealthState.HealthStatus.Unknown or TransportAddressHealthState.HealthStatus.UnhealthyPending); } + /// + /// The replica health status of the transport address uri will change eventually with the motonically increasing time. + /// However, the purpose of this method is to capture the health status snapshot at this moment. + /// + /// An instance of . + /// A read-only list of . + private void CaptureTransportAddressUriHealthStates( + PartitionAddressInformation partitionAddressInformation, + IReadOnlyList transportAddressUris) + { + partitionAddressInformation + .Get(Protocol.Tcp)? + .SetTransportAddressUrisHealthState( + replicaHealthStates: transportAddressUris.Select(x => x.GetCurrentHealthState().GetHealthStatusDiagnosticString()).ToList()); + } + protected virtual void Dispose(bool disposing) { if (this.disposedValue) diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs index 74363c8ca1..247c9f2587 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceWriter.TraceJsonWriter.cs @@ -430,6 +430,8 @@ public void Visit(StoreResult storeResult) this.jsonWriter.WriteFieldName("BELatencyInMs"); this.WriteStringValueOrNull(storeResult.BackendRequestDurationInMs); + this.WriteJsonUriArray("ReplicaHealthStatuses", storeResult.ReplicaHealthStatuses); + this.VisitTransportRequestStats(storeResult.TransportRequestStats); this.jsonWriter.WriteFieldName("TransportException"); @@ -468,6 +470,22 @@ private void WriteJsonUriArray(string propertyName, IEnumerable replicaHealthStatuses) + { + this.jsonWriter.WriteFieldName(propertyName); + this.jsonWriter.WriteArrayStart(); + + if (replicaHealthStatuses != null) + { + foreach (string replicaHealthStatus in replicaHealthStatuses) + { + this.WriteStringValueOrNull(replicaHealthStatus); + } + } + + this.jsonWriter.WriteArrayEnd(); + } + private void WriteRegionsContactedArray(string propertyName, IEnumerable<(string, Uri)> uris) { this.jsonWriter.WriteFieldName(propertyName); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index c97e0b5b2c..a06dabf09c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -14,7 +14,7 @@ "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42172.5, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 42174.75, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 42166.5, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 56695.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338, "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 37610, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13342232, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13341058, @@ -34,12 +34,12 @@ "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 33630.5, "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 33636.25, "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 33627.75, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 47961.25, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 55044, "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26018.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 57420.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 58054, "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39044, "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml index 8b6adc1c15..885699cb43 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml @@ -340,6 +340,12 @@ "RequestCharge": 3.14, "RetryAfterInMs": "9000", "BELatencyInMs": "4.2", + "ReplicaHealthStatuses": [ + "http://storephysicaladdress-1p.com:Connected", + "http://storephysicaladdress-2s.com:Unknown", + "http://storephysicaladdress-3s.com:Unhealthy", + "http://storephysicaladdress-4s.com:Unknown" + ], "transportRequestTimeline": { "requestTimeline": [ { @@ -529,6 +535,7 @@ "RequestCharge": 0, "RetryAfterInMs": null, "BELatencyInMs": null, + "ReplicaHealthStatuses":[], "transportRequestTimeline": null, "TransportException": null } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 2d0d0a5c6a..5116eb22de 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -971,6 +971,13 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat expected: TransportAddressHealthState.HealthStatus.Connected, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( + addressInfo: addressInfo, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 4, + numberOfUnhealthyPendingReplicas: 0, + numberOfUnhealthyReplicas: 0); + Assert.AreEqual(4, addressInfo.AllAddresses.Count); Assert.AreEqual(1, addressInfo.AllAddresses.Count(x => x.PhysicalUri == oldAddress)); Assert.AreEqual(0, addressInfo.AllAddresses.Count(x => x.PhysicalUri == newAddress)); @@ -1008,6 +1015,14 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); mockHttpHandler.VerifyAll(); + + GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( + addressInfo: addressInfo, + numberOfConnectedReplicas: 2, + numberOfUnknownReplicas: 1, + numberOfUnhealthyPendingReplicas: 1, + numberOfUnhealthyReplicas: 0); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, @@ -1106,6 +1121,13 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr manualResetEvent: manualResetEvent, shouldReset: true); + GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( + addressInfo: addressInfo, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 4, + numberOfUnhealthyPendingReplicas: 0, + numberOfUnhealthyReplicas: 0); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, @@ -1157,6 +1179,13 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr expected: TransportAddressHealthState.HealthStatus.Unhealthy, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); + GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( + addressInfo: addressInfo, + numberOfConnectedReplicas: 2, + numberOfUnknownReplicas: 1, + numberOfUnhealthyPendingReplicas: 1, + numberOfUnhealthyReplicas: 0); + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, @@ -1356,6 +1385,41 @@ private static void AssertOpenConnectionHandlerAttributes( Assert.AreEqual(expectedTotalSuccessAddressesToOpenCount, fakeOpenConnectionHandler.GetTotalSuccessfulInvocationCount()); } + /// + /// Helper method to validate and assert on the cached health states for diagnostics. + /// + /// An instance of containing the partition address information. + /// An integer containing the number of connected replicas to be validated inthe cached health status list. + /// An integer containing the number of unknown replicas to be validated inthe cached health status list. + /// An integer containing the number of unhealthy pending replicas to be validated inthe cached health status list. + /// An integer containing the number of unhealthy replicas to be validated inthe cached health status list. + private static void ValidateHealthStatesInDiagnostics( + PartitionAddressInformation addressInfo, + int numberOfConnectedReplicas, + int numberOfUnknownReplicas, + int numberOfUnhealthyPendingReplicas, + int numberOfUnhealthyReplicas) + { + IReadOnlyList replicaHealthStatuses = addressInfo.Get(Protocol.Tcp)?.ReplicaTransportAddressUrisHealthState; + + Assert.IsNotNull(replicaHealthStatuses); + Assert.AreEqual( + expected: numberOfConnectedReplicas, + actual: replicaHealthStatuses.Where(x => x.Contains("| status: Connected |")).Count()); + + Assert.AreEqual( + expected: numberOfUnknownReplicas, + actual: replicaHealthStatuses.Where(x => x.Contains("| status: Unknown |")).Count()); + + Assert.AreEqual( + expected: numberOfUnhealthyPendingReplicas, + actual: replicaHealthStatuses.Where(x => x.Contains("| status: UnhealthyPending |")).Count()); + + Assert.AreEqual( + expected: numberOfUnhealthyReplicas, + actual: replicaHealthStatuses.Where(x => x.Contains("| status: Unhealthy |")).Count()); + } + private class FakeMessageHandler : HttpMessageHandler { private bool returnFullReplicaSet; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs index ad21070609..7c0cca1f95 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceTests.cs @@ -125,8 +125,6 @@ public void ValidateStoreResultSerialization() storeResultProperties.Remove(nameof(storeResult.Target.Exception)); storeResultProperties.Add("transportRequestTimeline"); storeResultProperties.Remove(nameof(storeResult.Target.TransportRequestStats)); - storeResultProperties.Add("ReplicaHealthStatuses"); - storeResultProperties.Remove(nameof(storeResult.Target.ReplicaHealthStatuses)); foreach (string key in jsonPropertyNames) { From ea10439d2b3b1658b8dee97186b362d5b60ae537 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:54:00 -0700 Subject: [PATCH 138/337] Subpartitioning: Fixes handling of split physical partitions (#3879) * Initial Commit DO NOT REVIEW * bug fix, needs Direct Package Changes * fix for change feed and query plus tests * clean up * query + clean up --------- Co-authored-by: Kiran Kumar Kolli --- .../FeedRanges/FeedRangePartitionKey.cs | 11 +- .../Core/QueryPlan/QueryPartitionProvider.cs | 6 +- .../Routing/PartitionRoutingHelperTest.cs | 517 ++++++++++++++++++ 3 files changed, 527 insertions(+), 7 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/FeedRange/FeedRanges/FeedRangePartitionKey.cs b/Microsoft.Azure.Cosmos/src/FeedRange/FeedRanges/FeedRangePartitionKey.cs index 47f84fd280..1a04800b50 100644 --- a/Microsoft.Azure.Cosmos/src/FeedRange/FeedRanges/FeedRangePartitionKey.cs +++ b/Microsoft.Azure.Cosmos/src/FeedRange/FeedRanges/FeedRangePartitionKey.cs @@ -4,11 +4,13 @@ namespace Microsoft.Azure.Cosmos { + using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; /// /// FeedRange that represents an exact Partition Key value. @@ -31,8 +33,13 @@ public FeedRangePartitionKey(PartitionKey partitionKey) return Task.FromResult( new List> { - Documents.Routing.Range.GetPointRange( - this.PartitionKey.InternalKey.GetEffectivePartitionKeyString(partitionKeyDefinition)) + Documents.Routing.PartitionKeyInternal.GetEffectivePartitionKeyRange( + partitionKeyDefinition, + new Documents.Routing.Range( + min: this.PartitionKey.InternalKey, + max: this.PartitionKey.InternalKey, + isMinInclusive: true, + isMaxInclusive: true)) }); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs index 6e7b0b4a8f..c62a65b27a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs @@ -147,11 +147,7 @@ internal PartitionedQueryExecutionInfo ConvertPartitionedQueryExecutionInfo( List> effectiveRanges = new List>(queryInfoInternal.QueryRanges.Count); foreach (Documents.Routing.Range internalRange in queryInfoInternal.QueryRanges) { - effectiveRanges.Add(new Documents.Routing.Range( - internalRange.Min.GetEffectivePartitionKeyString(partitionKeyDefinition, false), - internalRange.Max.GetEffectivePartitionKeyString(partitionKeyDefinition, false), - internalRange.IsMinInclusive, - internalRange.IsMaxInclusive)); + effectiveRanges.Add(PartitionKeyInternal.GetEffectivePartitionKeyRange(partitionKeyDefinition, internalRange)); } effectiveRanges.Sort(Documents.Routing.Range.MinComparer.Instance); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs index 35ffaa65bb..792621f54a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionRoutingHelperTest.cs @@ -19,6 +19,8 @@ namespace Microsoft.Azure.Cosmos.Tests.Routing using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using System.Collections.ObjectModel; using System.Net; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.Monads; /// /// Tests for class. @@ -246,6 +248,521 @@ public async Task TestGetPartitionRoutingInfo() } } } + [TestMethod] + public async Task TestRoutingForPrefixedPartitionKeyQueriesAsync() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() + { + Kind = PartitionKind.MultiHash, + Paths = new Collection() { "/path1", "/path2", "/path3" }, + Version = PartitionKeyDefinitionVersion.V2 + }; + + // Case 1: Query with 1 prefix path, split at 1st level. Should route to only one partition. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F856" //Seattle + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F856", //Seattle + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"Microsoft\"", + epkRanges => + { + return epkRanges.Count == 1; //Routes to only one pkRange. + }, + partitionKeyRanges); + } + + //Case 2: Query with 1 prefix path value which is split at 2nd level. Should route to two partitions. + //Case 3: Query with 2 prefix path values which is split at 2nd level. Should route to one partition. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963" //[Seattle, Redmond] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963",//[Seattle, Redmond] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" or (r.path1 = \"seattle\" and r.path2 = \"bellevue\")", + epkRanges => + { + return epkRanges.Count == 2; //Since data is split at pkey [seattle, redmond], it should route to two pkRange. + }, + partitionKeyRanges); + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" and r.path2 =\"redmond\"", + epkRanges => + { + return epkRanges.Count == 1; //Since data is split at pkey [seattle, redmond], this query should route to one pkRange + }, + partitionKeyRanges); + } + + //Case 4: Query with 2 prefix path values split at the 3rd level. Should route to 2 paritions. + //Case 5: Query with 1 prefix path value split at 3rd level. Should route to 2 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8"//[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8",//[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" and r.path2 =\"redmond\"", + epkRanges => + { + return epkRanges.Count == 2; //Since data is split at pkey [seattle, redmond, 5.12312419050912359123], it should route to two pkRange. + }, + partitionKeyRanges); + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" and r.path2 =\"redmond\" and r.path3=5.12312419050912359123", + epkRanges => + { + return epkRanges.Count == 1; + }, + partitionKeyRanges); + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\"", + epkRanges => + { + return epkRanges.Count == 2; + }, + partitionKeyRanges); + } + + //Case 6: Query with 1 prefix path value split succesively at 2nd and then at the 3rd level. Should route to 3 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963"//[seattle, redmond] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963",//[seattle, redmond] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8"//[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "2", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8",//[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\"", + epkRanges => + { + return epkRanges.Count == 3; + }, + partitionKeyRanges); + } + + //Case 7: Query with 1 prefix path value split succesively at 1st, 2nd and then at the 3rd level. Should route to 3 partitions. + //Case 8: Query with 2 prefix path value split succesively at 1st, 2nd and then at the 3rd level. Should route to 2 partitions. + //Case 9: Query with fully specfied pkey, split succesively at 1st, 2nd and then at the 3rd level. Should route to 1 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F856" //[seattle] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F856", //[seattle] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963" //[seattle, redmond] + }, + new PartitionKeyRange() + { + Id = "2", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963", //[seattle, redmond] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8"//[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "3", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8",//[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\"", + epkRanges => + { + return epkRanges.Count == 3; //Routes tp three pkRanges + }, + partitionKeyRanges); + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" and r.path2 = \"redmond\"", + epkRanges => + { + return epkRanges.Count == 2; //Routes to two pkRanges. + }, + partitionKeyRanges); + await PrefixPartitionKeyTestRunnerAsync( + partitionKeyDefinition, + $"SELECT VALUE r.id from r where r.path1 = \"seattle\" and r.path2 = \"redmond\" and r.path3 = \"98052\"", + epkRanges => + { + Assert.AreEqual(epkRanges.Count, 1); + + return epkRanges.Count == 1; //Routes to only one pkRanges. + }, + partitionKeyRanges); + } + } + + [TestMethod] + public async Task TestRoutingForPrefixedPartitionKeyChangeFeedAsync() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() + { + Kind = PartitionKind.MultiHash, + Paths = new Collection() { "/path1", "/path2", "/path3" }, + Version = PartitionKeyDefinitionVersion.V2 + }; + + // Case 1: ChangeFeed with 1 prefix path, split at 1st level. Should route to only one partition. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F856" //Seattle + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F856", //Seattle + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("Microsoft").Build(), + epkRanges => + { + return epkRanges.Count == 1; //Routes to only one pkRange. + }, + partitionKeyRanges); + } + + //Case 2: ChangeFeed with 1 prefix path value which is split at 2nd level. Should route to two partitions. + //Case 3: ChangeFeed with 2 prefix path values which is split at 2nd level. Should route to one partition. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963" //[Seattle, Redmond] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963", //[Seattle, Redmond] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Build(), + epkRanges => + { + return epkRanges.Count == 2; //Since data is split at pkey [seattle, redmond], it should route to two pkRange. + }, + partitionKeyRanges); + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Add("redmond").Build(), + epkRanges => + { + return epkRanges.Count == 1; //Since data is split at pkey [seattle, redmond], this query should route to one pkRange + }, + partitionKeyRanges); + } + + //Case 4: ChangeFeed with 2 prefix path values split at the 3rd level. Should route to 2 paritions. + //Case 5: ChangeFeed with 1 prefix path value split at 3rd level. Should route to 2 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8"//[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8", //[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Add("redmond").Build(), + epkRanges => + { + return epkRanges.Count == 2; //Since data is split at pkey [seattle, redmond, 5.12312419050912359123], it should route to two pkRange. + }, + partitionKeyRanges); + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Add("redmond").Add(5.12312419050912359123).Build(), + epkRanges => + { + return epkRanges.Count == 1; + }, + partitionKeyRanges); + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Build(), + epkRanges => + { + return epkRanges.Count == 2; + }, + partitionKeyRanges); + } + + //Case 6: ChangeFeed with 1 prefix path value split succesively at 2nd and then at the 3rd level. Should route to 3 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963" //[seattle, redmond] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963", //[seattle, redmond] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8" //[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "2", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8", //[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Build(), + epkRanges => + { + return epkRanges.Count == 3; + }, + partitionKeyRanges); + } + + //Case 7: ChangeFeed with 1 prefix path value split succesively at 1st, 2nd and then at the 3rd level. Should route to 3 partitions. + //Case 8: ChangeFeed with 2 prefix path value split succesively at 1st, 2nd and then at the 3rd level. Should route to 2 partitions. + //Case 9: ChangeFeed with fully specfied pkey, split succesively at 1st, 2nd and then at the 3rd level. Should route to 1 partitions. + { + List partitionKeyRanges = new List() + { + new PartitionKeyRange() + { + Id = "0", + MinInclusive = string.Empty, + MaxExclusive = "07E4D14180A45153F00B44907886F856" //[seattle] + }, + new PartitionKeyRange() + { + Id = "1", + MinInclusive = "07E4D14180A45153F00B44907886F856", //[seattle] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963" //[seattle, redmond] + }, + new PartitionKeyRange() + { + Id = "2", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A5963", //[seattle, redmond] + MaxExclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8"//[seattle, redmond, 5.12312419050912359123] + }, + new PartitionKeyRange() + { + Id = "3", + MinInclusive = "07E4D14180A45153F00B44907886F85622E342F38A486A088463DFF7838A59630EF2E2D82460884AF0F6440BE4F726A8", //[seattle, redmond, 5.12312419050912359123] + MaxExclusive = "FF" + }, + }; + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Build(), + epkRanges => + { + return epkRanges.Count == 3; //Routes tp three pkRanges + }, + partitionKeyRanges); + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Add("redmond").Build(), + epkRanges => + { + return epkRanges.Count == 2; //Routes to two pkRanges. + }, + partitionKeyRanges); + await PrefixPartitionKeyChangeFeedTestRunnerAsync( + partitionKeyDefinition, + new PartitionKeyBuilder().Add("seattle").Add("redmond").Add("98052").Build(), + epkRanges => + { + Assert.AreEqual(epkRanges.Count, 1); + + return epkRanges.Count == 1; //Routes to only one pkRanges. + }, + partitionKeyRanges); + } + } + + private static async Task PrefixPartitionKeyTestRunnerAsync( + PartitionKeyDefinition partitionKeyDefinition, + string queryText, + Predicate> validator, + List partitionKeyRanges) + { + IDictionary DefaultQueryengineConfiguration = new Dictionary() + { + {"maxSqlQueryInputLength", 30720}, + {"maxJoinsPerSqlQuery", 5}, + {"maxLogicalAndPerSqlQuery", 200}, + {"maxLogicalOrPerSqlQuery", 200}, + {"maxUdfRefPerSqlQuery", 2}, + {"maxInExpressionItemsCount", 8000}, + {"queryMaxInMemorySortDocumentCount", 500}, + {"maxQueryRequestTimeoutFraction", 0.90}, + {"sqlAllowNonFiniteNumbers", false}, + {"sqlAllowAggregateFunctions", true}, + {"sqlAllowSubQuery", true}, + {"sqlAllowScalarSubQuery", false}, + {"allowNewKeywords", true}, + {"sqlAllowLike", true}, + {"sqlAllowGroupByClause", false}, + {"queryEnableMongoNativeRegex", true}, + {"maxSpatialQueryCells", 12}, + {"spatialMaxGeometryPointCount", 256}, + {"sqlDisableOptimizationFlags", 0}, + {"sqlEnableParameterExpansionCheck", true} + }; + + QueryPartitionProvider QueryPartitionProvider = new QueryPartitionProvider(DefaultQueryengineConfiguration); + + IEnumerable> rangesAndServiceIdentity = partitionKeyRanges + .Select(range => Tuple.Create(range, (ServiceIdentity)null)); + string collectionRid = string.Empty; + CollectionRoutingMap routingMap = + CollectionRoutingMap.TryCreateCompleteRoutingMap( + rangesAndServiceIdentity, + collectionRid); + + RoutingMapProvider routingMapProvider = new RoutingMapProvider(routingMap); + TryCatch tryGetQueryPlan = + QueryPartitionProvider.TryGetPartitionedQueryExecutionInfo( + querySpecJsonString: JsonConvert.SerializeObject(new SqlQuerySpec(queryText)), + partitionKeyDefinition: partitionKeyDefinition, + requireFormattableOrderByQuery: true, + isContinuationExpected: true, + allowNonValueAggregateQuery: false, + hasLogicalPartitionKey: false, + allowDCount: true, + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); + + HashSet resolvedPKRanges = new HashSet(); + foreach (Range range in tryGetQueryPlan.Result.QueryRanges) + { + resolvedPKRanges.UnionWith(await routingMapProvider.TryGetOverlappingRangesAsync( + collectionRid, + range, + NoOpTrace.Singleton)); + } + + Assert.IsTrue(validator(resolvedPKRanges)); + } + + private static async Task PrefixPartitionKeyChangeFeedTestRunnerAsync( + PartitionKeyDefinition partitionKeyDefinition, + Cosmos.PartitionKey partitionKey, + Predicate> validator, + List partitionKeyRanges) + { + IEnumerable> rangesAndServiceIdentity = partitionKeyRanges + .Select(range => Tuple.Create(range, (ServiceIdentity)null)); + string collectionRid = string.Empty; + CollectionRoutingMap routingMap = + CollectionRoutingMap.TryCreateCompleteRoutingMap( + rangesAndServiceIdentity, + collectionRid); + + RoutingMapProvider routingMapProvider = new RoutingMapProvider(routingMap); + + HashSet resolvedPKRanges = new HashSet(); + FeedRangePartitionKey feedRangePartitionKey = new FeedRangePartitionKey(partitionKey); + List> effectiveRanges = await feedRangePartitionKey.GetEffectiveRangesAsync(routingMapProvider, null, partitionKeyDefinition, null); + foreach (Range range in effectiveRanges) + { + resolvedPKRanges.UnionWith(await routingMapProvider.TryGetOverlappingRangesAsync( + collectionRid, + range, + NoOpTrace.Singleton)); + + } + + Assert.IsTrue(validator(resolvedPKRanges)); + } [TestMethod] public void TestCrossPartitionAggregateQueries() From 8137c7758eac966e75df7ea3aa8109c7170c5dba Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Tue, 13 Jun 2023 18:26:55 -0700 Subject: [PATCH 139/337] [Query] Fixes empty property name parsing exception (#3907) * inital commit * cleanup * test cleanup * PR comments * PR comment --- .../CosmosQueryExecutionContextFactory.cs | 4 +-- .../Core/QueryClient/CosmosQueryClient.cs | 2 +- .../Query/v3Query/CosmosQueryClientCore.cs | 2 +- .../src/SqlObjects/SqlPropertyName.cs | 7 +---- .../CosmosGatewayTimeoutTests.cs | 2 +- .../Query/BypassQueryParsingTests.cs | 28 ++++++++++++++++--- .../Query/MockCosmosQueryClient.cs | 2 +- ...misticDirectExecutionQueryBaselineTests.cs | 2 +- 8 files changed, 32 insertions(+), 17 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 8f35ff821a..47aa1c4490 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -188,7 +188,7 @@ private static async Task> TryCreateCoreContextAsy // If the query would go to gateway, but we have a partition key, // then try seeing if we can execute as a passthrough using client side only logic. // This is to short circuit the need to go to the gateway to get the query plan. - if (cosmosQueryContext.QueryClient.ByPassQueryParsing() + if (cosmosQueryContext.QueryClient.BypassQueryParsing() && inputParameters.PartitionKey.HasValue) { bool parsed; @@ -586,7 +586,7 @@ private static async Task GetPartitionedQueryExec CancellationToken cancellationToken) { PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; - if (cosmosQueryContext.QueryClient.ByPassQueryParsing()) + if (cosmosQueryContext.QueryClient.BypassQueryParsing()) { // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs index ac093cadce..3fa4cb90e7 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs @@ -98,7 +98,7 @@ public abstract Task ExecuteQueryPlanRequestAsync bool forceRefresh, ITrace trace); - public abstract bool ByPassQueryParsing(); + public abstract bool BypassQueryParsing(); public abstract Task ForceRefreshCollectionCacheAsync( string collectionLink, diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index daf47e151c..1c5a9ef21f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -285,7 +285,7 @@ public override async Task> GetTargetPartitionKeyRangesA } } - public override bool ByPassQueryParsing() + public override bool BypassQueryParsing() { return CustomTypeExtensions.ByPassQueryParsing(); } diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlPropertyName.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlPropertyName.cs index 059e799d99..e7f859ff18 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlPropertyName.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlPropertyName.cs @@ -68,12 +68,7 @@ sealed class SqlPropertyName : SqlObject private SqlPropertyName(string value) { - if (string.IsNullOrWhiteSpace(value)) - { - throw new ArgumentException($"{nameof(value)} must not be null, empty, or whitespace."); - } - - this.Value = value; + this.Value = value ?? throw new ArgumentNullException(nameof(value)); } public string Value { get; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs index 8b4728c122..f50319f65f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs @@ -163,7 +163,7 @@ public DisableServiceInterop( { } - public override bool ByPassQueryParsing() + public override bool BypassQueryParsing() { return true; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs index a0c821c72d..4db276f4ce 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/BypassQueryParsingTests.cs @@ -1,5 +1,6 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Query { + using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -14,9 +15,28 @@ public sealed class BypassQueryParsingTests : QueryTestsBase public async Task TestBypassQueryParsingWithNonePartitionKey() { int documentCount = 400; - QueryRequestOptions feedOptions = new QueryRequestOptions { PartitionKey = PartitionKey.None }; + string query = "SELECT VALUE r.numberField FROM r"; - IReadOnlyList expected = Enumerable.Range(0, documentCount).ToList(); + IReadOnlyList expectedOutput = Enumerable.Range(0, documentCount).Select(i => i.ToString()).ToList(); + + await this.ValidateQueryBypassWithNonePartitionKey(documentCount, query, expectedOutput); + } + + [TestMethod] + [TestCategory("Query")] + public async Task TestBypassQueryParsingWithNonePartitionKeyEmptyPropertyName() + { + int documentCount = 400; + + string query = @"SELECT VALUE { """" : r.numberField } FROM r"; + IReadOnlyList expectedOutput = Enumerable.Range(0, documentCount).Select(i => String.Format("{{\"\":{0}}}", i)).ToList(); + + await this.ValidateQueryBypassWithNonePartitionKey(documentCount, query, expectedOutput); + } + + private async Task ValidateQueryBypassWithNonePartitionKey(int documentCount, string query, IReadOnlyList expectedOutput) + { + QueryRequestOptions feedOptions = new QueryRequestOptions { PartitionKey = PartitionKey.None }; async Task ImplementationAsync(Container container, IReadOnlyList documents) { @@ -34,9 +54,9 @@ async Task ImplementationAsync(Container container, IReadOnlyList cosmosQueryClientCore); List items = await RunQueryAsync(containerWithBypassParsing, query, feedOptions); - int[] actual = items.Cast().Select(x => (int)Number64.ToLong(x.Value)).ToArray(); + string[] actualOutput = items.Select(x => x.ToString()).ToArray(); - Assert.IsTrue(expected.SequenceEqual(actual)); + Assert.IsTrue(expectedOutput.SequenceEqual(actualOutput)); } IReadOnlyList documents = CreateDocuments(documentCount); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs index 11d51403b1..6dd861ec88 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/MockCosmosQueryClient.cs @@ -35,7 +35,7 @@ public MockCosmosQueryClient( public int QueryPlanCalls { get; private set; } - public override bool ByPassQueryParsing() + public override bool BypassQueryParsing() { return this.forceQueryPlanGatewayElseServiceInterop; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index fad65e80db..1e7d4e1e40 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -927,7 +927,7 @@ internal class TestCosmosQueryClient : CosmosQueryClient { public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); - public override bool ByPassQueryParsing() + public override bool BypassQueryParsing() { return false; } From b200491ec789e81443990069cf2164a3e5e47ef8 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Wed, 14 Jun 2023 11:54:09 -0700 Subject: [PATCH 140/337] [Preview] Query: Refactors EnableOptimisticDirectExecution to true by default in Preview mode (#3909) * Setting EnableODE to true by default in Preview Mode. * Added seperate if block for default value * Updated property * Removed unused Usings * Updated contracts * Updated test * Updated directive indentation --- .../src/RequestOptions/QueryRequestOptions.cs | 10 +++- .../TraceWriterBaselineTests.TraceData.xml | 10 ++-- .../Contracts/DotNetPreviewSDKAPI.json | 53 ++++++++++++++++++- .../Contracts/DotNetSDKAPI.json | 38 ------------- ...misticDirectExecutionQueryBaselineTests.cs | 11 ++-- 5 files changed, 74 insertions(+), 48 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 4cca513013..60cea5b48c 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -49,7 +49,15 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - public bool EnableOptimisticDirectExecution { get; set; } +#if PREVIEW + public +#else + internal +#endif + bool EnableOptimisticDirectExecution { get; set; } +#if PREVIEW + = true; +#endif /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml index 885699cb43..d1dee72a0f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml @@ -341,10 +341,10 @@ "RetryAfterInMs": "9000", "BELatencyInMs": "4.2", "ReplicaHealthStatuses": [ - "http://storephysicaladdress-1p.com:Connected", - "http://storephysicaladdress-2s.com:Unknown", - "http://storephysicaladdress-3s.com:Unhealthy", - "http://storephysicaladdress-4s.com:Unknown" + "http://storephysicaladdress-1p.com:Connected", + "http://storephysicaladdress-2s.com:Unknown", + "http://storephysicaladdress-3s.com:Unhealthy", + "http://storephysicaladdress-4s.com:Unknown" ], "transportRequestTimeline": { "requestTimeline": [ @@ -535,7 +535,7 @@ "RequestCharge": 0, "RetryAfterInMs": null, "BELatencyInMs": null, - "ReplicaHealthStatuses":[], + "ReplicaHealthStatuses": [], "transportRequestTimeline": null, "TransportException": null } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index de49584da2..8546a93b2f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -496,8 +496,59 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, + "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": { + "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + }, "Members": { "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 8a3bc7b462..e5b95a7ed9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6279,18 +6279,6 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -6445,13 +6433,6 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -7320,18 +7301,6 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -7486,13 +7455,6 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 1e7d4e1e40..81c765adc4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -144,10 +144,15 @@ public void NegativeOptimisticDirectExecutionOutput() [TestMethod] public async Task TestDefaultQueryRequestOptionsSettings() { - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - Assert.AreEqual(requestOptions.EnableOptimisticDirectExecution, false); + bool odeExpectedValue = +#if PREVIEW + true; +#else + false; +#endif + + Assert.AreEqual(odeExpectedValue, requestOptions.EnableOptimisticDirectExecution); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). From 8684535d233ea6a7147d857fae9a6c69e467c827 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Thu, 15 Jun 2023 07:53:21 -0700 Subject: [PATCH 141/337] Documentations: Adds links to PatchItems docs (#3910) * Added links to PatchItems docs * Undo changes from internal file --- Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 106262a13f..2978d741bf 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -751,6 +751,7 @@ public abstract Task> ReadManyItemsAsync( /// ]]> /// /// + /// Supported partial document update modes public abstract Task> PatchItemAsync( string id, PartitionKey partitionKey, @@ -783,6 +784,7 @@ public abstract Task> PatchItemAsync( /// /// /// + /// Supported partial document update modes public abstract Task PatchItemStreamAsync( string id, PartitionKey partitionKey, From 69702227d91de27a8257683d4984a750057406c5 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 16 Jun 2023 17:29:42 -0700 Subject: [PATCH 142/337] [Internal] Direct Package Upgrade: Refactors Code to Bump Up `Cosmos.Direct` Package to `3.31.2` (#3918) * Code changes to bump up the direct version. * Code changes to mark the Israel Central region as public. * Code changes to update contracts. * Code changes to fix test failure. Some clean ups. * Code changes to add detailed message for open channels count. --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/Regions.cs | 5 +++++ .../ClientCreateAndInitializeTest.cs | 10 +++++++--- .../Contracts/DotNetSDKAPI.json | 5 +++++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c8b86ceed2..6e15dbd850 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.34.0 3.34.0 preview - 3.31.1 + 3.31.2 2.0.2 2.0.2 preview diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index 666ec0435b..33c258aaf7 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -359,5 +359,10 @@ public static class Regions /// Name of the Azure Italy North region in the Azure Cosmos DB service. /// public const string ItalyNorth = "Italy North"; + + /// + /// Name of the Azure Israel Central region in the Azure Cosmos DB service. + /// + public const string IsraelCentral = "Israel Central"; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs index e977a8b459..e07fe85a7e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs @@ -205,7 +205,7 @@ public async Task InitializeContainersAsync_WhenThrowsException_ShouldDisposeCos public async Task CreateAndInitializeAsync_WithValidDatabaseAndContainer_ShouldOpenRntbdConnectionsToBackendReplicas() { // Arrange. - int httpCallsMade = 0; + int httpCallsMade = 0, maxRequestsPerConnection = 6; HttpClientHandlerHelper httpClientHandlerHelper = new () { RequestCallBack = (request, cancellationToken) => @@ -227,6 +227,7 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndContainer_ShouldO { HttpClientFactory = () => new HttpClient(httpClientHandlerHelper), ConnectionMode = ConnectionMode.Direct, + MaxRequestsPerTcpConnection = maxRequestsPerConnection, }; // Act. @@ -275,8 +276,11 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndContainer_ShouldO .GetValue(loadBalancingPartition); Assert.IsNotNull(openChannels); - Assert.AreEqual(30, channelCapacity); - Assert.AreEqual(1, openChannels.Count); + Assert.AreEqual(48, openChannels.Count, "Here the expected value 48 rather explains how many time we call the" + + "LoadBalancingPartition.OpenChannelAsync(). The emulator by default returns 12 partitions, and each partition has 4 replicas," + + "and by behavior the emulator uses the same URI for eac of these replica, hence 12 * 4 = 48 times we call the OpenChannelAsync()." + + "In ideal world, the value should be 1, because for each unique URI, the OpenChannelAsync() call will just be 1."); + Assert.AreEqual(openChannels.Count * maxRequestsPerConnection, channelCapacity); Documents.Rntbd.LbChannelState channelState = openChannels.First(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index e5b95a7ed9..7fde376d49 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6680,6 +6680,11 @@ "Attributes": [], "MethodInfo": "System.String GermanyWestCentral;IsInitOnly:False;IsStatic:True;" }, + "System.String IsraelCentral": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String IsraelCentral;IsInitOnly:False;IsStatic:True;" + }, "System.String ItalyNorth": { "Type": "Field", "Attributes": [], From b97906191c98f80e0dc9cba85545dc163b7df9dc Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Mon, 19 Jun 2023 14:34:32 -0400 Subject: [PATCH 143/337] SDK 3.35.0 : Adds version bump and changelog (#3920) * release PR * updated changelog.md * more changelog updates --- Directory.Build.props | 4 +- .../contracts/API_3.35.0-preview.txt | 1563 +++++++++++++++++ .../contracts/API_3.35.0.txt | 1502 ++++++++++++++++ changelog.md | 27 + 4 files changed, 3094 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 6e15dbd850..eb4940bf4b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.34.0 - 3.34.0 + 3.35.0 + 3.35.0 preview 3.31.2 2.0.2 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.0-preview.txt new file mode 100644 index 0000000000..6c989053fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.0-preview.txt @@ -0,0 +1,1563 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.0.txt new file mode 100644 index 0000000000..c0dc3e280f --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.0.txt @@ -0,0 +1,1502 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index b1b3139828..01e3703c89 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,33 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.35.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0-preview) - 2023-06-19 + +### Added +- [3836](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3836) Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions +- [3909](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3909) Query: Adds EnableOptimisticDirectExecution in QueryRequestOptions enabled by default + +### [3.35.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0) - 2023-06-19 + +#### Fixed +- [3864](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3864) NugetPackage: Removes ThirdPartyNotice.txt from content and contentFiles folders +- [3866](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3866) CosmosClient: Fixes missing Trace when converting HTTP Timeout to 503 +- [3879](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3879) Subpartitioning: Fixes handling of split physical partitions +- [3907](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3907) Query: Fixes empty property name parsing exception + +#### Added +- [3860](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3860) Documentation: Adds see also link to Container.CreateTransactionalBatch +- [3852](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3852) Query: Adds type-markers with count and length for large arrays +- [3838](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3838) Benchmarking: Adds use of ARM Templates for benchmarking +- [3877](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3877) Regions: Adds Malaysia South, Isreal Central, and Italy North +- [3877](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3877) Distributed Tracing: Enables Distributing Tracing for Operations +- [3874](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3874) Client Encryption: Adds Microsoft.Azure.Cosmos compatibility to version 3.34.0 +- [3891](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3891) Documentation: Adds additional remarks to CosmosClient +- [3902](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3902) ConnectionPolicy: Refactors Code to Reduce Default Request Timeout to 6 Seconds +- [3910](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3910) Documentations: Adds links to PatchItems docs +- [3918](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3918) Regions: Adds Israel Central +- [3918](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3918) CosmosClient: Fixes SynchronizationLockException when disposing client with requests in-flight. + ### [3.34.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.34.0-preview) - 2023-05-17 ### Added From b1d313452cdb4318b9239fe9b39668667f6cf034 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Mon, 19 Jun 2023 15:35:53 -0400 Subject: [PATCH 144/337] [Internal] Last minute fix to changelog for 3.35.0 (#3921) * release PR * updated changelog.md * more changelog updates * changelog fix * Update changelog.md * Update changelog.md --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 01e3703c89..bd5c29c32c 100644 --- a/changelog.md +++ b/changelog.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [3852](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3852) Query: Adds type-markers with count and length for large arrays - [3838](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3838) Benchmarking: Adds use of ARM Templates for benchmarking - [3877](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3877) Regions: Adds Malaysia South, Isreal Central, and Italy North -- [3877](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3877) Distributed Tracing: Enables Distributing Tracing for Operations +- [3887](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3887) Distributed Tracing: Setting DisplayName for an operation level activity as `` - [3874](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3874) Client Encryption: Adds Microsoft.Azure.Cosmos compatibility to version 3.34.0 - [3891](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3891) Documentation: Adds additional remarks to CosmosClient - [3902](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3902) ConnectionPolicy: Refactors Code to Reduce Default Request Timeout to 6 Seconds From 92319a0528b5e257da71dd6ec0c8bc50375d05c3 Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Thu, 22 Jun 2023 15:19:55 -0700 Subject: [PATCH 145/337] [Internal] Query: Adds new header SupportedSerializationFormats (#3911) * Binary Serilaization Response test * Added new header SupportedSerializationFormats * Modified existing use of CosmosSerializationFormatOptions * Modified tests and removed unused code * Addressed comments * Added more negative cases * Revert changes * Added spaces * Addressed comments * Addressed comments * Removed SupportedSerializationFormats from Headers file * Removed unused JsonSerilazationFormats option * Addressed comments * Addressed comments * Addressed comments * Addressed comments * Added new enum TransportSerializationFormat * Added new enum TransportSerializationFormat * Addressed comments * Removed unused parameter * Addressed comments * updating API * remove tests * Text fixes * fix typo * remove TransportSerializationFormat header * text reverts * revert * test update * PR comments * remove test owner headers HeadersValidationTests.cs * PR comments - remove unsupported tests and scope client --------- Co-authored-by: Heet Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../Pagination/ChangeFeedPaginationOptions.cs | 5 +- Microsoft.Azure.Cosmos/src/FeedOptions.cs | 37 ++-- .../Headers/CosmosMessageHeadersInternal.cs | 6 + .../src/Headers/StoreRequestHeaders.cs | 6 + .../NetworkAttachedDocumentContainer.cs | 5 - .../src/Pagination/PaginationOptions.cs | 4 - .../Pagination/QueryPaginationOptions.cs | 3 +- .../DocumentQueryExecutionContextBase.cs | 30 +-- .../Query/v3Query/CosmosQueryClientCore.cs | 24 +-- .../Pagination/ReadFeedPaginationOptions.cs | 3 +- .../ReadFeedCrossFeedRangeAsyncEnumerator.cs | 3 +- .../src/RequestOptions/QueryRequestOptions.cs | 11 +- .../CosmosSerializationFormatOptions.cs | 2 +- .../HeadersValidationTests.cs | 192 +++++++++++++++++- .../SupportedSerializationFormatsTest.cs | 102 ++++++++++ .../ContentSerializationPerformanceTests.cs | 4 - .../BinaryEncodingOverTheWireTests.cs | 42 ++-- .../OrderByQueryResultTests.cs | 6 +- .../Query/FeedOptionTests.cs | 25 +++ 19 files changed, 383 insertions(+), 127 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SupportedSerializationFormatsTest.cs diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPaginationOptions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPaginationOptions.cs index 8579c6de42..85a2895774 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPaginationOptions.cs @@ -33,16 +33,19 @@ public ChangeFeedPaginationOptions( JsonSerializationFormat? jsonSerializationFormat = null, Dictionary additionalHeaders = null, ChangeFeedQuerySpec changeFeedQuerySpec = null) - : base(pageSizeHint, jsonSerializationFormat, additionalHeaders) + : base(pageSizeHint, additionalHeaders) { this.Mode = mode ?? throw new ArgumentNullException(nameof(mode)); this.ChangeFeedQuerySpec = changeFeedQuerySpec; + this.JsonSerializationFormat = jsonSerializationFormat; } public ChangeFeedMode Mode { get; } public ChangeFeedQuerySpec ChangeFeedQuerySpec { get; } + public JsonSerializationFormat? JsonSerializationFormat { get; } + protected override ImmutableHashSet BannedAdditionalHeaders => BannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/FeedOptions.cs b/Microsoft.Azure.Cosmos/src/FeedOptions.cs index 6f4cae7e0d..4d6ce52f41 100644 --- a/Microsoft.Azure.Cosmos/src/FeedOptions.cs +++ b/Microsoft.Azure.Cosmos/src/FeedOptions.cs @@ -24,7 +24,7 @@ public FeedOptions() { } - internal FeedOptions(FeedOptions options) + public FeedOptions(FeedOptions options) { if (options == null) { @@ -65,10 +65,10 @@ internal FeedOptions(FeedOptions options) this.EndId = options.EndId; this.StartEpk = options.StartEpk; this.EndEpk = options.EndEpk; - this.ContentSerializationFormat = options.ContentSerializationFormat; this.EnableGroupBy = options.EnableGroupBy; this.MergeStaticId = options.MergeStaticId; this.Properties = options.Properties; + this.SupportedSerializationFormats = options.SupportedSerializationFormats; } /// @@ -282,7 +282,7 @@ internal FeedOptions(FeedOptions options) /// /// Option is true if query tracing is enabled; otherwise, false. /// - internal bool? EmitVerboseTracesInQuery { get; set; } + public bool? EmitVerboseTracesInQuery { get; set; } /// /// Gets or sets the schema rid which could be used to filter the document feed response @@ -292,7 +292,7 @@ internal FeedOptions(FeedOptions options) /// By default, it is null which means no filtering will be applied. /// Otherwise, it must be a valid resource id of Schema resource. /// - internal string FilterBySchemaResourceId { get; set; } + public string FilterBySchemaResourceId { get; set; } /// /// Gets or sets the request option for document query requests in the Azure Cosmos DB service. @@ -359,65 +359,62 @@ internal FeedOptions(FeedOptions options) /// /// Gets or sets the flag that tells the backend to forces the query to perform a scan (at a request level). /// - internal bool ForceQueryScan { get; set; } + public bool ForceQueryScan { get; set; } /// /// Gets or sets the EnumerationDirection /// To be used along with Read feed operation /// - internal EnumerationDirection? EnumerationDirection { get; set; } + public EnumerationDirection? EnumerationDirection { get; set; } /// /// Gets or sets the ReadFeedKeyType /// To be used along with Read feed operation /// - internal ReadFeedKeyType? ReadFeedKeyType { get; set; } + public ReadFeedKeyType? ReadFeedKeyType { get; set; } /// /// Gets or sets the StartId /// To be used along with Read feed operation /// - internal string StartId { get; set; } + public string StartId { get; set; } /// /// Gets or sets the EndId /// To be used along with Read feed operation /// - internal string EndId { get; set; } + public string EndId { get; set; } /// /// Gets or sets the StartEpk /// To be used along with Read feed operation /// - internal string StartEpk { get; set; } + public string StartEpk { get; set; } /// /// Gets or sets the EndEpk /// To be used along with Read feed operation /// - internal string EndEpk { get; set; } + public string EndEpk { get; set; } /// - /// Gets or sets the ContentSerializationFormat for the feed (query/read feed) operation in the Azure Cosmos DB service. + /// Gets or sets the SupportedSerializationFormats for the query response from the service. /// - /// - /// If the document is stored in a different serialization format then the one requested, then there will be a rewrite over the wire, but the source document will be untouched. - /// - internal ContentSerializationFormat? ContentSerializationFormat { get; set; } + public SupportedSerializationFormats? SupportedSerializationFormats { get; set; } - internal bool EnableGroupBy { get; set; } + public bool EnableGroupBy { get; set; } /// /// Gets or sets the MergeStaticId. /// To be used along with Read feed operation when Static Column merge is desired. /// - internal string MergeStaticId { get; set; } + public string MergeStaticId { get; set; } /// /// Gets or sets the custom serialization options for query /// - internal CosmosSerializationFormatOptions CosmosSerializationFormatOptions { get; set; } + public CosmosSerializationFormatOptions CosmosSerializationFormatOptions { get; set; } - internal IDictionary Properties { get; set; } + public IDictionary Properties { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs b/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs index f12595d832..1cbf9b54e6 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/CosmosMessageHeadersInternal.cs @@ -159,6 +159,12 @@ public virtual string ContentSerializationFormat set => this.SetProperty(HttpConstants.HttpHeaders.ContentSerializationFormat, value); } + public virtual string SupportedSerializationFormats + { + get => this.GetValueOrDefault(HttpConstants.HttpHeaders.SupportedSerializationFormats); + set => this.SetProperty(HttpConstants.HttpHeaders.SupportedSerializationFormats, value); + } + public virtual string ReadFeedKeyType { get => this.GetValueOrDefault(HttpConstants.HttpHeaders.ReadFeedKeyType); diff --git a/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs b/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs index 68086095f7..b907363685 100644 --- a/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs +++ b/Microsoft.Azure.Cosmos/src/Headers/StoreRequestHeaders.cs @@ -76,6 +76,12 @@ public override string ContentSerializationFormat set => this.requestNameValueCollection.ContentSerializationFormat = value; } + public override string SupportedSerializationFormats + { + get => this.requestNameValueCollection.SupportedSerializationFormats; + set => this.requestNameValueCollection.SupportedSerializationFormats = value; + } + public override string ReadFeedKeyType { get => this.requestNameValueCollection.ReadFeedKeyType; diff --git a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs index 7d8683c3fe..8420cb0540 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs @@ -192,11 +192,6 @@ public async Task> MonadicReadFeedAsync( request.Headers.ContinuationToken = ((CosmosString)readFeedContinuationState.ContinuationToken).Value; } - if (readFeedPaginationOptions.JsonSerializationFormat.HasValue) - { - request.Headers.ContentSerializationFormat = readFeedPaginationOptions.JsonSerializationFormat.Value.ToContentSerializationFormatString(); - } - foreach (KeyValuePair kvp in readFeedPaginationOptions.AdditionalHeaders) { request.Headers[kvp.Key] = kvp.Value; diff --git a/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs b/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs index 5558f2be24..593d761ec0 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs @@ -23,11 +23,9 @@ internal abstract class PaginationOptions protected PaginationOptions( int? pageSizeLimit = null, - JsonSerializationFormat? jsonSerializationFormat = null, Dictionary additionalHeaders = null) { this.PageSizeLimit = pageSizeLimit; - this.JsonSerializationFormat = jsonSerializationFormat; this.AdditionalHeaders = additionalHeaders != null ? additionalHeaders.ToImmutableDictionary() : EmptyDictionary; foreach (string key in this.AdditionalHeaders.Keys) @@ -41,8 +39,6 @@ protected PaginationOptions( public int? PageSizeLimit { get; } - public JsonSerializationFormat? JsonSerializationFormat { get; } - public ImmutableDictionary AdditionalHeaders { get; } protected abstract ImmutableHashSet BannedAdditionalHeaders { get; } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs index c285135feb..c985158828 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs @@ -32,9 +32,8 @@ internal sealed class QueryPaginationOptions : PaginationOptions public QueryPaginationOptions( int? pageSizeHint = null, bool optimisticDirectExecute = false, - JsonSerializationFormat? jsonSerializationFormat = null, Dictionary additionalHeaders = null) - : base(pageSizeHint, jsonSerializationFormat, additionalHeaders) + : base(pageSizeHint, additionalHeaders) { this.OptimisticDirectExecute = optimisticDirectExecute; } diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs index ec4e6d9185..053c951f6c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query { using System; using System.Collections.Generic; + using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; @@ -31,6 +32,8 @@ namespace Microsoft.Azure.Cosmos.Query internal abstract class DocumentQueryExecutionContextBase : IDocumentQueryExecutionContext { + public static readonly string DefaultSupportedSerializationFormats = string.Join(",", SupportedSerializationFormats.JsonText, SupportedSerializationFormats.CosmosBinary); + public readonly struct InitParams { public IDocumentQueryClient Client { get; } @@ -326,14 +329,7 @@ await this.Client.EnsureValidOverwriteAsync( requestHeaders.Set(HttpConstants.HttpHeaders.MergeStaticId, this.feedOptions.MergeStaticId); } - if (this.feedOptions.CosmosSerializationFormatOptions != null) - { - requestHeaders[HttpConstants.HttpHeaders.ContentSerializationFormat] = this.feedOptions.CosmosSerializationFormatOptions.ContentSerializationFormat; - } - else if (this.feedOptions.ContentSerializationFormat.HasValue) - { - requestHeaders[HttpConstants.HttpHeaders.ContentSerializationFormat] = this.feedOptions.ContentSerializationFormat.Value.ToString(); - } + requestHeaders[HttpConstants.HttpHeaders.SupportedSerializationFormats] = this.feedOptions.SupportedSerializationFormats?.ToString() ?? DefaultSupportedSerializationFormats; return requestHeaders; } @@ -688,23 +684,7 @@ private DocumentFeedResponse GetFeedResponse( { content = memoryStream.ToArray(); } - - IJsonNavigator jsonNavigator = null; - - // Use the users custom navigator first. If it returns null back try the - // internal navigator. - if (this.feedOptions.CosmosSerializationFormatOptions != null) - { - jsonNavigator = this.feedOptions.CosmosSerializationFormatOptions.CreateCustomNavigatorCallback(content); - if (jsonNavigator == null) - { - throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); - } - } - else - { - jsonNavigator = JsonNavigator.Create(content); - } + IJsonNavigator jsonNavigator = JsonNavigator.Create(content); string resourceName = this.GetRootNodeName(documentServiceRequest.ResourceType); diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index 1c5a9ef21f..cce1a5268a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -155,7 +155,6 @@ public override async Task> ExecuteItemQueryAsync( cancellationToken: cancellationToken); return CosmosQueryClientCore.GetCosmosElementResponse( - requestOptions, resourceType, message, trace); @@ -297,7 +296,6 @@ public override void ClearSessionTokenCache(string collectionFullName) } private static TryCatch GetCosmosElementResponse( - QueryRequestOptions requestOptions, ResourceType resourceType, ResponseMessage cosmosResponseMessage, ITrace trace) @@ -336,8 +334,7 @@ private static TryCatch GetCosmosElementResponse( long responseLengthBytes = memoryStream.Length; CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( memoryStream, - resourceType, - requestOptions.CosmosSerializationFormatOptions); + resourceType); QueryState queryState; if (cosmosResponseMessage.Headers.ContinuationToken != null) @@ -444,12 +441,10 @@ private Task GetRoutingMapProviderAsync() /// /// The memory stream response for the query REST response Azure Cosmos /// The resource type - /// The custom serialization options. This allows custom serialization types like BSON, JSON, or other formats /// An array of CosmosElements parsed from the response body. public static CosmosArray ParseElementsFromRestStream( Stream stream, - ResourceType resourceType, - CosmosSerializationFormatOptions cosmosSerializationOptions) + ResourceType resourceType) { if (!(stream is MemoryStream memoryStream)) { @@ -478,20 +473,7 @@ public static CosmosArray ParseElementsFromRestStream( // You want to create a CosmosElement for each document in "Documents". ReadOnlyMemory content = memoryStream.TryGetBuffer(out ArraySegment buffer) ? buffer : (ReadOnlyMemory)memoryStream.ToArray(); - IJsonNavigator jsonNavigator; - if (cosmosSerializationOptions != null) - { - // Use the users custom navigator - jsonNavigator = cosmosSerializationOptions.CreateCustomNavigatorCallback(content); - if (jsonNavigator == null) - { - throw new InvalidOperationException("The CosmosSerializationOptions did not return a JSON navigator."); - } - } - else - { - jsonNavigator = JsonNavigator.Create(content); - } + IJsonNavigator jsonNavigator = JsonNavigator.Create(content); string resourceName = resourceType switch { diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPaginationOptions.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPaginationOptions.cs index 757473c02c..ad219dfd99 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPaginationOptions.cs @@ -27,9 +27,8 @@ internal sealed class ReadFeedPaginationOptions : PaginationOptions public ReadFeedPaginationOptions( PaginationDirection? paginationDirection = null, int? pageSizeHint = null, - JsonSerializationFormat? jsonSerializationFormat = null, Dictionary additionalHeaders = null) - : base(pageSizeHint, jsonSerializationFormat, additionalHeaders) + : base(pageSizeHint, additionalHeaders) { this.Direction = paginationDirection; } diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs index 2f611840f7..95fb8b23cf 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs @@ -45,8 +45,7 @@ public async ValueTask MoveNextAsync() CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( innerReadFeedPage.Page.Content, - Documents.ResourceType.Document, - cosmosSerializationOptions: null); + Documents.ResourceType.Document); ReadFeedPage page = new ReadFeedPage( documents, innerReadFeedPage.Page.RequestCharge, diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 60cea5b48c..f723107ede 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -5,8 +5,10 @@ namespace Microsoft.Azure.Cosmos { using System; + using System.ComponentModel; using System.Text; using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Query; using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Documents; @@ -188,6 +190,8 @@ public ConsistencyLevel? ConsistencyLevel internal CosmosSerializationFormatOptions CosmosSerializationFormatOptions { get; set; } + internal SupportedSerializationFormats? SupportedSerializationFormats { get; set; } + internal ExecutionEnvironment? ExecutionEnvironment { get; set; } internal bool? ReturnResultsInDeterministicOrder { get; set; } @@ -240,11 +244,8 @@ internal override void PopulateRequestOptions(RequestMessage request) { request.Headers.Add(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, this.ResponseContinuationTokenLimitInKb.ToString()); } - - if (this.CosmosSerializationFormatOptions != null) - { - request.Headers.CosmosMessageHeaders.ContentSerializationFormat = this.CosmosSerializationFormatOptions.ContentSerializationFormat; - } + + request.Headers.CosmosMessageHeaders.SupportedSerializationFormats = this.SupportedSerializationFormats?.ToString() ?? DocumentQueryExecutionContextBase.DefaultSupportedSerializationFormats; if (this.StartId != null) { diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationFormatOptions.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationFormatOptions.cs index 81ab5fd1e4..8ebefa502a 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationFormatOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationFormatOptions.cs @@ -52,4 +52,4 @@ public CosmosSerializationFormatOptions( this.CreateCustomWriterCallback = createCustomWriter; } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs index b24ce5f03b..f9ca3f8ecc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/HeadersValidationTests.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Net; using System.Text; using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Tracing; @@ -164,17 +165,17 @@ private void ValidatePageSize(DocumentClient client) public async Task ValidateConsistencyLevelGateway() { DocumentClient client = TestCommon.CreateClient(true); - await ValidateCosistencyLevel(client); + await ValidateConsistencyLevel(client); } [TestMethod] public async Task ValidateConsistencyLevelRntbd() { DocumentClient client = TestCommon.CreateClient(false, Protocol.Tcp); - await ValidateCosistencyLevel(client); + await ValidateConsistencyLevel(client); } - private async Task ValidateCosistencyLevel(DocumentClient client) + private async Task ValidateConsistencyLevel(DocumentClient client) { DocumentCollection collection = TestCommon.CreateOrGetDocumentCollection(client); @@ -203,17 +204,16 @@ private async Task ValidateCosistencyLevel(DocumentClient client) } [TestMethod] - [Owner("brchon")] public void ValidateJsonSerializationFormatGateway() { - var client = TestCommon.CreateClient(true); + using var client = TestCommon.CreateClient(true); ValidateJsonSerializationFormat(client); } [TestMethod] public void ValidateJsonSerializationFormatRntbd() { - var client = TestCommon.CreateClient(false, Protocol.Tcp); + using var client = TestCommon.CreateClient(false, Protocol.Tcp); ValidateJsonSerializationFormat(client); } @@ -306,6 +306,184 @@ private void ValidateJsonSerializationFormatQuery(DocumentClient client, Documen Assert.IsTrue(response.ResponseBody.ReadByte() == HeadersValidationTests.BinarySerializationByteMarkValue); } + [TestMethod] + public void ValidateSupportedSerializationFormatsGateway() + { + using var client = TestCommon.CreateClient(true); + this.ValidateSupportedSerializationFormats(client, true); + } + + [TestMethod] + public void ValidateSupportedSerializationFormatsRntbd() + { + using var client = TestCommon.CreateClient(false, Protocol.Tcp); + this.ValidateSupportedSerializationFormats(client, false); + } + + private void ValidateSupportedSerializationFormats(DocumentClient client, bool isHttps) + { + DocumentCollection collection = TestCommon.CreateOrGetDocumentCollection(client); + this.ValidateSupportedSerializationFormatsReadFeed(client, collection, isHttps); + + List sqlQueryList = new List() + { + new SqlQuerySpec("SELECT * FROM c"), + new SqlQuerySpec("SELECT c.id FROM c ORDER BY c.partitionKey"), + new SqlQuerySpec("SELECT c.name FROM c GROUP BY c.name") + }; + + foreach(SqlQuerySpec sqlQuery in sqlQueryList) + { + this.ValidateSupportedSerializationFormatsQuery(client, collection, sqlQuery, isHttps); + } + } + + private void SupportedSerializationFormatsNegativeCases( + DocumentClient client, + DocumentCollection collection, + string invalidValue, + bool isHttps, + SqlQuerySpec sqlQuerySpec = null) + { + INameValueCollection headers = new RequestNameValueCollection(); + headers.Add(HttpConstants.HttpHeaders.SupportedSerializationFormats, invalidValue); + + try + { + DocumentServiceResponse response; + if (sqlQuerySpec != null) + { + response = this.QueryRequest(client, collection.ResourceId, sqlQuerySpec, headers); + } + else + { + headers.Set(HttpConstants.HttpHeaders.PartitionKey, "[\"test\"]"); + response = this.ReadDocumentFeedRequestSinglePartition(client, collection.ResourceId, headers); + } + + if (isHttps) + { + // Invalid value is treated as default JsonText if HTTPS + Assert.IsTrue(response.StatusCode == HttpStatusCode.OK, "Invalid status code"); + Assert.IsTrue(this.CheckSerializationFormat(response) == JsonSerializationFormat.Text); + } + else + { + Assert.Fail("Should throw an exception"); + } + } + catch (Exception ex) + { + DocumentClientException innerException = ex.InnerException as DocumentClientException; + Assert.IsTrue(innerException.StatusCode == HttpStatusCode.BadRequest, "invalid status code"); + } + } + + private void SupportedSerializationFormatsPositiveCases( + DocumentClient client, + DocumentCollection collection, + SupportedSerializationFormats expectedFormat, + string supportedSerializationFormats, + SqlQuerySpec sqlQuerySpec = null) + { + INameValueCollection headers = new RequestNameValueCollection(); + + headers.Add(HttpConstants.HttpHeaders.SupportedSerializationFormats, supportedSerializationFormats); + DocumentServiceResponse response; + if(sqlQuerySpec!=null) + { + response = this.QueryRequest(client, collection.ResourceId, sqlQuerySpec, headers); + } + else + { + Assert.IsTrue(expectedFormat == SupportedSerializationFormats.JsonText, "ReadFeed response should be in Text"); + response = this.ReadDocumentFeedRequestAsync(client, collection.ResourceId, headers).Result; + } + + Assert.IsTrue(response.StatusCode == HttpStatusCode.OK, "Invalid status code"); + + if(expectedFormat == SupportedSerializationFormats.JsonText) + { + Assert.IsTrue(this.CheckSerializationFormat(response) == JsonSerializationFormat.Text); + } + else + { + Assert.IsTrue(this.CheckSerializationFormat(response) == JsonSerializationFormat.Binary); + } + } + + private void ValidateSupportedSerializationFormatsReadFeed(DocumentClient client, DocumentCollection collection, bool isHttps) + { + // Value not supported + this.SupportedSerializationFormatsNegativeCases(client, collection, "Invalid value", isHttps); + + // Supported values + this.SupportedSerializationFormatsPositiveCases(client, collection, expectedFormat: SupportedSerializationFormats.JsonText, supportedSerializationFormats: "JSONText"); + this.SupportedSerializationFormatsPositiveCases(client, collection, expectedFormat: SupportedSerializationFormats.JsonText, supportedSerializationFormats: "COSMOSbinary"); + this.SupportedSerializationFormatsPositiveCases(client, collection, expectedFormat: SupportedSerializationFormats.JsonText, supportedSerializationFormats: "JsonText, CosmosBinary"); + } + + private void ValidateSupportedSerializationFormatsQuery(DocumentClient client, DocumentCollection collection, SqlQuerySpec sqlQuerySpec, bool isHttps) + { + // Values not supported + this.SupportedSerializationFormatsNegativeCases(client, collection, "Invalid value", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, ", ,", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, ",,", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, "JsonText CosmosBinary", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, ",JsonText|CosmosBinary", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, "Json Text", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, "Json,Text", isHttps, sqlQuerySpec: sqlQuerySpec); + this.SupportedSerializationFormatsNegativeCases(client, collection, "JsonText, ", isHttps, sqlQuerySpec: sqlQuerySpec); + + // Supported values + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.JsonText, + supportedSerializationFormats: "jsontext", + sqlQuerySpec: sqlQuerySpec); + /* + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.CosmosBinary, + supportedSerializationFormats: "COSMOSBINARY", + sqlQuerySpec: sqlQuerySpec); + */ + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.JsonText, + supportedSerializationFormats: "JsonText, CosmosBinary", + sqlQuerySpec: sqlQuerySpec); + /* + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.CosmosBinary, + supportedSerializationFormats: "CosmosBinary, HybridRow", + sqlQuerySpec: sqlQuerySpec); + */ + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.JsonText, + supportedSerializationFormats: "JsonText, CosmosBinary, HybridRow", + sqlQuerySpec: sqlQuerySpec); + /* + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.CosmosBinary, + supportedSerializationFormats: "JsonText, CosmosBinary, HybridRow", + sqlQuerySpec: sqlQuerySpec); + */ + this.SupportedSerializationFormatsPositiveCases(client, collection, + expectedFormat: SupportedSerializationFormats.JsonText, + supportedSerializationFormats: "JsonText, CosmosBinary, HybridRow", + sqlQuerySpec: sqlQuerySpec); + } + + private JsonSerializationFormat CheckSerializationFormat(DocumentServiceResponse response) + { + if(response.ResponseBody.ReadByte() < BinarySerializationByteMarkValue) + { + return JsonSerializationFormat.Text; + } + else + { + return JsonSerializationFormat.Binary; + } + } + [TestMethod] public void ValidateIndexingDirectiveGateway() { @@ -1105,4 +1283,4 @@ internal override string BaseUserAgent } } } -} \ No newline at end of file +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SupportedSerializationFormatsTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SupportedSerializationFormatsTest.cs new file mode 100644 index 0000000000..f4cdab6e51 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SupportedSerializationFormatsTest.cs @@ -0,0 +1,102 @@ +namespace Microsoft.Azure.Cosmos.Query +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.EmulatorTests.Query; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests.QueryOracle; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + [TestCategory("Query")] + public sealed class SupportedSerializationFormatsTest : QueryTestsBase + { + [TestMethod] + public async Task TestSupportedSerializationFormats() + { + string[] inputDocuments = new[] + { + @"{""id"":""0"",""name"":""document_0""}", + @"{""id"":""1"",""name"":""document_1""}", + @"{""id"":""2"",""name"":""document_2""}", + @"{""id"":""3"",""name"":""document_3""}", + @"{""id"":""4"",""name"":""document_4""}", + @"{""id"":""5"",""name"":""document_5""}", + @"{""id"":""6"",""name"":""document_6""}", + @"{""id"":""7"",""name"":""document_7""}", + @"{""id"":""8"",""name"":""document_8""}", + @"{""id"":""9"",""name"":""document_9""}", + }; + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct, + CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + inputDocuments, + this.TestSupportedSerializationFormatsHelper, + "/id"); + } + + private async Task TestSupportedSerializationFormatsHelper(Container container, IReadOnlyList documents) + { + string[] expectedResults = new[] { "document_0", "document_1", "document_2", "document_3", "document_4", "document_5", "document_6", "document_7", "document_8", "document_9" }; + string query = string.Format("SELECT c.name FROM c"); + List queryRequestOptionsList = new List() + { + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.CosmosBinary | SupportedSerializationFormats.HybridRow + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.JsonText | SupportedSerializationFormats.CosmosBinary + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.JsonText | SupportedSerializationFormats.HybridRow + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.JsonText | SupportedSerializationFormats.CosmosBinary | SupportedSerializationFormats.HybridRow + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.JsonText + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.CosmosBinary + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.CosmosBinary + }, + new QueryRequestOptions() + { + SupportedSerializationFormats = SupportedSerializationFormats.JsonText + } + }; + + foreach (QueryRequestOptions requestOptions in queryRequestOptionsList) + { + List results = new List(); + using (FeedIterator feedIterator = container.GetItemQueryIterator(new QueryDefinition(query), requestOptions: requestOptions)) + { + while (feedIterator.HasMoreResults) + { + FeedResponse response = await feedIterator.ReadNextAsync(); + results.AddRange(response.ToList()); + } + } + + string[] actualResults = results + .Select(doc => ((CosmosString)(doc as CosmosObject)["name"]).Value.ToString()) + .ToArray(); + + CollectionAssert.AreEquivalent(expectedResults, actualResults); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs index c18ac5e420..759e63b345 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs @@ -83,10 +83,6 @@ private async Task RunQueryAsync(Container container) { MaxConcurrency = this.MaxConcurrency, MaxItemCount = this.MaxItemCount, - CosmosSerializationFormatOptions = new CosmosSerializationFormatOptions( - contentSerializationFormat: this.contentSerialization, - createCustomNavigator: (content) => JsonNavigator.Create(content), - createCustomWriter: () => JsonWriter.Create(this.contentSerialization == "JsonText" ? JsonSerializationFormat.Text : JsonSerializationFormat.Binary)) }; if (this.useStronglyTypedIterator) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BinaryEncodingOverTheWireTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BinaryEncodingOverTheWireTests.cs index b55e837844..7d570d65d0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BinaryEncodingOverTheWireTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BinaryEncodingOverTheWireTests.cs @@ -28,15 +28,11 @@ public class BinaryEncodingOverTheWireTests ConfigurationManager.AppSettings["GatewayEndpoint"], ConfigurationManager.AppSettings["MasterKey"], new CosmosClientOptions() { ConnectionMode = ConnectionMode.Gateway }); - private static readonly CosmosClient DirectHttpsClient = new CosmosClient( - ConfigurationManager.AppSettings["GatewayEndpoint"], - ConfigurationManager.AppSettings["MasterKey"], - new CosmosClientOptions() { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Documents.Client.Protocol.Https }); private static readonly CosmosClient RntbdClient = new CosmosClient( ConfigurationManager.AppSettings["GatewayEndpoint"], ConfigurationManager.AppSettings["MasterKey"], new CosmosClientOptions() { ConnectionMode = ConnectionMode.Direct, ConnectionProtocol = Documents.Client.Protocol.Tcp }); - private static readonly CosmosClient[] Clients = new CosmosClient[] { GatewayClient, DirectHttpsClient, RntbdClient }; + private static readonly CosmosClient[] Clients = new CosmosClient[] { GatewayClient, RntbdClient }; private static readonly CosmosClient Client = RntbdClient; private static readonly AsyncLazy Database = new AsyncLazy(async () => { @@ -124,7 +120,7 @@ public void CheckThatAllTestsAreRunning() [TestMethod] public async Task CombinedScriptsDataTest() { - await this.TestCurratedDocs("CombinedScriptsData.json"); + await this.TestCuratedDocs("CombinedScriptsData.json"); } // For now we are skipping this test since the documents are too large to ingest and we get a rate size too large (HTTP 413). @@ -139,96 +135,96 @@ public async Task CountriesTest() [TestMethod] public async Task DevTestCollTest() { - await this.TestCurratedDocs("devtestcoll.json"); + await this.TestCuratedDocs("devtestcoll.json"); } [TestMethod] public async Task LastFMTest() { - await this.TestCurratedDocs("lastfm"); + await this.TestCuratedDocs("lastfm"); } [TestMethod] public async Task LogDataTest() { - await this.TestCurratedDocs("LogData.json"); + await this.TestCuratedDocs("LogData.json"); } [TestMethod] public async Task MillionSong1KDocumentsTest() { - await this.TestCurratedDocs("MillionSong1KDocuments.json"); + await this.TestCuratedDocs("MillionSong1KDocuments.json"); } [TestMethod] public async Task MsnCollectionTest() { - await this.TestCurratedDocs("MsnCollection.json"); + await this.TestCuratedDocs("MsnCollection.json"); } [TestMethod] public async Task NutritionDataTest() { - await this.TestCurratedDocs("NutritionData"); + await this.TestCuratedDocs("NutritionData"); } [TestMethod] public async Task RunsCollectionTest() { - await this.TestCurratedDocs("runsCollection"); + await this.TestCuratedDocs("runsCollection"); } [TestMethod] public async Task StatesCommitteesTest() { - await this.TestCurratedDocs("states_committees.json"); + await this.TestCuratedDocs("states_committees.json"); } [TestMethod] public async Task StatesLegislatorsTest() { - await this.TestCurratedDocs("states_legislators"); + await this.TestCuratedDocs("states_legislators"); } [TestMethod] public async Task Store01Test() { - await this.TestCurratedDocs("store01C.json"); + await this.TestCuratedDocs("store01C.json"); } [TestMethod] public async Task TicinoErrorBucketsTest() { - await this.TestCurratedDocs("TicinoErrorBuckets"); + await this.TestCuratedDocs("TicinoErrorBuckets"); } [TestMethod] public async Task TwitterDataTest() { - await this.TestCurratedDocs("twitter_data"); + await this.TestCuratedDocs("twitter_data"); } [TestMethod] public async Task Ups1Test() { - await this.TestCurratedDocs("ups1"); + await this.TestCuratedDocs("ups1"); } [TestMethod] public async Task XpertEventsTest() { - await this.TestCurratedDocs("XpertEvents"); + await this.TestCuratedDocs("XpertEvents"); } - private async Task TestCurratedDocs(string path) + private async Task TestCuratedDocs(string path) { IEnumerable documents = BinaryEncodingOverTheWireTests.GetDocumentsFromCurratedDoc(path); await BinaryEncodingOverTheWireTests.CreateIngestQueryDelete( documents.Select(x => x.ToString()), - this.TestCurratedDocs); + this.TestCuratedDocs); } - private async Task TestCurratedDocs(CosmosClient cosmosClient, Container container, List items) + private async Task TestCuratedDocs(CosmosClient cosmosClient, Container container, List items) { HashSet inputItems = new HashSet(items, JsonTokenEqualityComparer.Value); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs index 86093aa296..7207f897be 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs @@ -31,11 +31,7 @@ public void TestOrderByUndefined() CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( memoryStream, - Documents.ResourceType.Document, - new CosmosSerializationFormatOptions( - "JsonText", - (content) => JsonNavigator.Create(content), - () => JsonWriter.Create(JsonSerializationFormat.Text))); + Documents.ResourceType.Document); List orderByQueryResults = documents.Select(x => new OrderByQueryResult(x)).ToList(); Assert.AreEqual(14, orderByQueryResults.Count); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/FeedOptionTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/FeedOptionTests.cs index 54c965cce8..703636ca81 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/FeedOptionTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/FeedOptionTests.cs @@ -50,6 +50,31 @@ public void TestCopyConstructor() _ = new FeedOptions(fo); } + [TestMethod] + public async Task TestSupportedSerializationFormats() + { + FeedOptions feedOptions = new FeedOptions(); + Mock client = new Mock(MockBehavior.Strict); + client.Setup(x => x.GetDefaultConsistencyLevelAsync()).Returns(Task.FromResult(ConsistencyLevel.BoundedStaleness)); + client.Setup(x => x.GetDesiredConsistencyLevelAsync()).Returns(Task.FromResult(ConsistencyLevel.BoundedStaleness)); + Expression> randomFunc = x => x * 2; + + TestQueryExecutionContext testQueryExecutionContext = new TestQueryExecutionContext( + client.Object, + ResourceType.Document, + typeof(TestQueryExecutionContext), + randomFunc, + feedOptions, + string.Empty, + true, Guid.NewGuid()); + INameValueCollection headers = await testQueryExecutionContext.CreateCommonHeadersAsync(feedOptions); + Assert.AreEqual("JsonText,CosmosBinary", headers[HttpConstants.HttpHeaders.SupportedSerializationFormats]); + + feedOptions.SupportedSerializationFormats = SupportedSerializationFormats.CosmosBinary | SupportedSerializationFormats.HybridRow; + headers = await testQueryExecutionContext.CreateCommonHeadersAsync(feedOptions); + Assert.AreEqual("CosmosBinary, HybridRow", headers[HttpConstants.HttpHeaders.SupportedSerializationFormats]); + } + internal class TestQueryExecutionContext : DocumentQueryExecutionContextBase { public TestQueryExecutionContext( From 3f4b7bd04dd9b456ceca20f269ed585599d9b4ca Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 26 Jun 2023 07:47:45 -0700 Subject: [PATCH 146/337] Code changes to optimize the rntbd open connection logic to open connections in parallel. (#3939) --- .../src/Routing/GatewayAddressCache.cs | 143 +++++++++++++----- .../GatewayAddressCacheTests.cs | 87 ++++++++++- 2 files changed, 185 insertions(+), 45 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 14b641959a..f864256df9 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -31,6 +31,11 @@ internal class GatewayAddressCache : IAddressCache, IDisposable private const string AddressResolutionBatchSize = "AddressResolutionBatchSize"; private const int DefaultBatchSize = 50; + // This warmup cache and connection timeout is meant to mimic an indefinite timeframe till which + // a delay task will run, until a cancellation token is requested to cancel the task. The default + // value for this timeout is 45 minutes at the moment. + private static readonly TimeSpan WarmupCacheAndOpenConnectionTimeout = TimeSpan.FromMinutes(45); + private readonly Uri serviceEndpoint; private readonly Uri addressEndpoint; @@ -113,7 +118,7 @@ public async Task OpenConnectionsAsync( bool shouldOpenRntbdChannels, CancellationToken cancellationToken) { - List>> tasks = new (); + List tasks = new (); int batchSize = GatewayAddressCache.DefaultBatchSize; #if !(NETSTANDARD15 || NETSTANDARD16) @@ -147,50 +152,33 @@ public async Task OpenConnectionsAsync( { for (int i = 0; i < partitionKeyRangeIdentities.Count; i += batchSize) { - tasks - .Add(this.GetAddressesAsync( - request: request, - collectionRid: collection.ResourceId, - partitionKeyRangeIds: partitionKeyRangeIdentities.Skip(i).Take(batchSize).Select(range => range.PartitionKeyRangeId))); + tasks.Add( + this.WarmupCachesAndOpenConnectionsAsync( + request: request, + collectionRid: collection.ResourceId, + partitionKeyRangeIds: partitionKeyRangeIdentities.Skip(i).Take(batchSize).Select(range => range.PartitionKeyRangeId), + containerProperties: collection, + shouldOpenRntbdChannels: shouldOpenRntbdChannels)); } } - foreach (TryCatch task in await Task.WhenAll(tasks)) - { - if (task.Failed) - { - continue; - } + using CancellationTokenSource linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - using (DocumentServiceResponse response = task.Result) - { - FeedResource
addressFeed = response.GetResource>(); - - bool inNetworkRequest = this.IsInNetworkRequest(response); + // The `timeoutTask` is a background task which adds a delay for a period of WarmupCacheAndOpenConnectionTimeout. The task will + // be cancelled either by - a) when `linkedTokenSource` expires, which means the original `cancellationToken` expires or + // b) the the `linkedTokenSource.Cancel()` is called. + Task timeoutTask = Task.Delay(GatewayAddressCache.WarmupCacheAndOpenConnectionTimeout, linkedTokenSource.Token); + Task resultTask = await Task.WhenAny(Task.WhenAll(tasks), timeoutTask); - IEnumerable> addressInfos = - addressFeed.Where(addressInfo => ProtocolFromString(addressInfo.Protocol) == this.protocol) - .GroupBy(address => address.PartitionKeyRangeId, StringComparer.Ordinal) - .Select(group => this.ToPartitionAddressAndRange(collection.ResourceId, @group.ToList(), inNetworkRequest)); - - foreach (Tuple addressInfo in addressInfos) - { - this.serverPartitionAddressCache.Set( - new PartitionKeyRangeIdentity(collection.ResourceId, addressInfo.Item1.PartitionKeyRangeId), - addressInfo.Item2); - - // The `shouldOpenRntbdChannels` boolean flag indicates whether the SDK should establish Rntbd connections to the - // backend replica nodes. For the `CosmosClient.CreateAndInitializeAsync()` flow, the flag should be passed as - // `true` so that the Rntbd connections to the backend replicas could be established deterministically. For any - // other flow, the flag should be passed as `false`. - if (this.openConnectionsHandler != null && shouldOpenRntbdChannels) - { - await this.openConnectionsHandler - .TryOpenRntbdChannelsAsync( - addresses: addressInfo.Item2.Get(Protocol.Tcp)?.ReplicaTransportAddressUris); - } - } - } + if (resultTask == timeoutTask) + { + // Operation has been cancelled. + DefaultTrace.TraceWarning("The open connection task was cancelled because the cancellation token was expired. '{0}'", + System.Diagnostics.Trace.CorrelationManager.ActivityId); + } + else + { + linkedTokenSource.Cancel(); } } @@ -350,6 +338,81 @@ public async Task TryGetAddressesAsync( } } + /// + /// Gets the address information from the gateway using the partition key range ids, and warms up the async non blocking cache + /// by inserting them as a key value pair for later lookup. Additionally attempts to establish Rntbd connections to the backend + /// replicas based on `shouldOpenRntbdChannels` boolean flag. + /// + /// An instance of containing the request payload. + /// A string containing the collection ids. + /// An instance of containing the list of partition key range ids. + /// An instance of containing the collection properties. + /// A boolean flag indicating whether Rntbd connections are required to be established to the backend replica nodes. + private async Task WarmupCachesAndOpenConnectionsAsync( + DocumentServiceRequest request, + string collectionRid, + IEnumerable partitionKeyRangeIds, + ContainerProperties containerProperties, + bool shouldOpenRntbdChannels) + { + TryCatch documentServiceResponseWrapper = await this.GetAddressesAsync( + request: request, + collectionRid: collectionRid, + partitionKeyRangeIds: partitionKeyRangeIds); + + if (documentServiceResponseWrapper.Failed) + { + return; + } + + try + { + using (DocumentServiceResponse response = documentServiceResponseWrapper.Result) + { + FeedResource
addressFeed = response.GetResource>(); + + bool inNetworkRequest = this.IsInNetworkRequest(response); + + IEnumerable> addressInfos = + addressFeed.Where(addressInfo => ProtocolFromString(addressInfo.Protocol) == this.protocol) + .GroupBy(address => address.PartitionKeyRangeId, StringComparer.Ordinal) + .Select(group => this.ToPartitionAddressAndRange(containerProperties.ResourceId, @group.ToList(), inNetworkRequest)); + + List openConnectionTasks = new (); + foreach (Tuple addressInfo in addressInfos) + { + this.serverPartitionAddressCache.Set( + new PartitionKeyRangeIdentity(containerProperties.ResourceId, addressInfo.Item1.PartitionKeyRangeId), + addressInfo.Item2); + + // The `shouldOpenRntbdChannels` boolean flag indicates whether the SDK should establish Rntbd connections to the + // backend replica nodes. For the `CosmosClient.CreateAndInitializeAsync()` flow, the flag should be passed as + // `true` so that the Rntbd connections to the backend replicas could be established deterministically. For any + // other flow, the flag should be passed as `false`. + if (this.openConnectionsHandler != null && shouldOpenRntbdChannels) + { + openConnectionTasks + .Add(this.openConnectionsHandler + .TryOpenRntbdChannelsAsync( + addresses: addressInfo.Item2.Get(Protocol.Tcp)?.ReplicaTransportAddressUris)); + } + } + + if (openConnectionTasks.Any()) + { + await Task.WhenAll(openConnectionTasks); + } + } + } + catch (Exception ex) + { + DefaultTrace.TraceWarning("Failed to warm-up caches and open connections for the server addresses: {0} with exception: {1}. '{2}'", + collectionRid, + ex, + System.Diagnostics.Trace.CorrelationManager.ActivityId); + } + } + private static void SetTransportAddressUrisToUnhealthy( PartitionAddressInformation stalePartitionAddressInformation, Lazy> failedEndpoints) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 5116eb22de..296c131fbf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -480,6 +480,75 @@ await cache.OpenConnectionsAsync( expectedTotalSuccessAddressesToOpenCount: 0); } + /// + /// Test to validate that when is called with a valid open connection handler + /// and a cancellation token that will expire with a pre-configured time, the handler method is indeed invoked and the open connection + /// operation gets cancelled successfully, if the cancellation token expires. The open connection operation succeeds if the operation + /// is finished before the cancellation token expiry time. + /// + [TestMethod] + [Owner("dkunda")] + [DataRow(1, 2, 1, 0, 3, 0, true, DisplayName = "Validate that when the cancellation token expiry time (i.e. 1 sec) is smaller than the open connection opperation duration (i.e. 2 sec)," + + "the open connection operation gets cancelled and the cancellation token is indeed respected and eventually cancelled.")] + [DataRow(3, 1, 1, 0, 3, 3, false, DisplayName = "Validate that when the cancellation token expiry time (i.e. 3 sec) is larger than the open connection opperation duration (i.e. 1 sec)," + + "the open connection operation completes successfully and the cancellation token is not cancelled.")] + public async Task OpenConnectionsAsync_WithValidOpenConnectionHandlerAndCancellationTokenExpires_ShouldInvokeHandlerMethodAndCancelToken( + int cancellationTokenTimeoutInSeconds, + int openConnectionDelayInSeconds, + int expectedTotalHandlerInvocationCount, + int expectedTotalFailedAddressesToOpenCount, + int expectedTotalReceivedAddressesCount, + int expectedTotalSuccessAddressesToOpenCount, + bool shouldCancelToken) + { + // Arrange. + FakeMessageHandler messageHandler = new (); + FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + failingIndexes: new HashSet(), + openConnectionDelayInSeconds: openConnectionDelayInSeconds); + + ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk="); + containerProperties.Id = "TestId"; + containerProperties.PartitionKeyPath = "/pk"; + HttpClient httpClient = new(messageHandler) + { + Timeout = TimeSpan.FromSeconds(120) + }; + + CancellationTokenSource cts = new (TimeSpan.FromSeconds(cancellationTokenTimeoutInSeconds)); + CancellationToken token = cts.Token; + + GatewayAddressCache cache = new ( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2); + + // Act. + await cache.OpenConnectionsAsync( + databaseName: "test-database", + collection: containerProperties, + partitionKeyRangeIdentities: new List() + { + this.testPartitionKeyRangeIdentity + }, + shouldOpenRntbdChannels: true, + cancellationToken: token); + + // Assert. + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedTotalFailedAddressesToOpenCount: expectedTotalFailedAddressesToOpenCount, + expectedTotalHandlerInvocationCount: expectedTotalHandlerInvocationCount, + expectedTotalReceivedAddressesCount: expectedTotalReceivedAddressesCount, + expectedTotalSuccessAddressesToOpenCount: expectedTotalSuccessAddressesToOpenCount); + + Assert.AreEqual(shouldCancelToken, token.IsCancellationRequested); + } + /// /// Test to validate that when is called with a /// valid open connection handler, the handler method is indeed invoked and an attempt is made to open @@ -1074,7 +1143,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( failIndexesByAttempts: new Dictionary>() { - { 0, new HashSet() { 1 } } + { 0, new HashSet() { 2 } } }, manualResetEvent: manualResetEvent); @@ -1513,16 +1582,19 @@ public class FakeOpenConnectionHandler : IOpenConnectionsHandler private int successInvocationCounter = 0; private int totalReceivedAddressesCounter = 0; private readonly HashSet failingIndexes; + private readonly int openConnectionDelayInSeconds; private readonly bool useAttemptBasedFailingIndexs; private readonly ManualResetEvent manualResetEvent; private readonly Dictionary> failIndexesByAttempts; public FakeOpenConnectionHandler( HashSet failingIndexes, - ManualResetEvent manualResetEvent = null) + ManualResetEvent manualResetEvent = null, + int openConnectionDelayInSeconds = 0) { this.failingIndexes = failingIndexes; this.manualResetEvent = manualResetEvent; + this.openConnectionDelayInSeconds = openConnectionDelayInSeconds; } public FakeOpenConnectionHandler( @@ -1554,11 +1626,18 @@ public int GetTotalMethodInvocationCount() return this.methodInvocationCounter; } - Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( + async Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( IEnumerable addresses) { int idx = 0; + this.methodInvocationCounter++; this.totalReceivedAddressesCounter += addresses.Count(); + + if (this.openConnectionDelayInSeconds > 0) + { + await Task.Delay(TimeSpan.FromSeconds(this.openConnectionDelayInSeconds)); + } + foreach (TransportAddressUri transportAddress in addresses) { if (this.useAttemptBasedFailingIndexs) @@ -1587,9 +1666,7 @@ Task IOpenConnectionsHandler.TryOpenRntbdChannelsAsync( idx++; } - this.methodInvocationCounter++; this.manualResetEvent?.Set(); - return Task.CompletedTask; } private void ExecuteSuccessCondition( From abab80e23858961a0f67db576ee51aac9255c094 Mon Sep 17 00:00:00 2001 From: Erik O'Leary <969938+onionhammer@users.noreply.github.com> Date: Mon, 26 Jun 2023 17:52:44 -0500 Subject: [PATCH 147/337] Query : Adds support for newtonsoft member access via ExtensionData (#3834) * Support newtonsoft member access via ExtensionData * Return null instead of empty string * Added tests for select & where * Updated baseline with note --------- Co-authored-by: leminh98 --- .../src/Linq/ExpressionToSQL.cs | 6 ++++ Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs | 8 +++++ ...ionBaselineTest.ValidateSQLTranslation.xml | 11 ++++++ ...Test.ValidateSQLTranslationComplexData.xml | 34 +++++++++++++++++++ .../LinqSQLTranslationBaselineTests.cs | 30 +++++++++++++++- .../Linq/CosmosLinqJsonConverterTests.cs | 30 ++++++++++++++++ 6 files changed, 118 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index 476774e137..b259234336 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -742,6 +742,12 @@ private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpre SqlScalarExpression memberExpression = ExpressionToSql.VisitScalarExpression(inputExpression.Expression, context); string memberName = inputExpression.Member.GetMemberName(context.linqSerializerOptions); + // If the resulting memberName is null, then the indexer should be on the root of the object. + if (memberName == null) + { + return memberExpression; + } + // if expression is nullable if (inputExpression.Expression.Type.IsNullable()) { diff --git a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs index 34d771bf56..7c8e62d69c 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs @@ -25,6 +25,14 @@ public static Type GetElementType(Type type) public static string GetMemberName(this MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) { string memberName = null; + + // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. + JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null && jsonExtensionDataAttribute.ReadData) + { + return null; + } + // Json.Net honors JsonPropertyAttribute more than DataMemberAttribute // So we check for JsonPropertyAttribute first. JsonPropertyAttribute jsonPropertyAttribute = memberInfo.GetCustomAttribute(true); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslation.xml index 877754ac74..d22afb37f9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslation.xml @@ -268,6 +268,17 @@ FROM root]]> + + + + + + new complex() {NewtonsoftExtensionData = new Dictionary`2() {Void Add(System.String, System.Object)("test", Convert(1.5, Object))}, NetExtensionData = new Dictionary`2() {Void Add(System.String, System.Object)("OtherTest", Convert(1.5, Object))}})]]> + + + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslationComplexData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslationComplexData.xml index 04e8ab30fe..a557298543 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslationComplexData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqSQLTranslationBaselineTest.ValidateSQLTranslationComplexData.xml @@ -166,4 +166,38 @@ FROM root JOIN x0 IN root["dblArray"]]]> + + + + (Convert(p.NewtonsoftExtensionData.get_Item("age"), Int32) > 18)).Select(x => new AnonymousType(Age = Convert(x.NewtonsoftExtensionData.get_Item("age"), Int32)))]]> + + + 18)]]> + + + + + + Convert(p.NewtonsoftExtensionData.get_Item("tags"), String[]).Contains("item-1")).Select(x => Convert(x.NewtonsoftExtensionData.get_Item("tags"), String[]))]]> + + + + + + + + + Convert(p.NewtonsoftExtensionData.get_Item("tags"), String[]).Contains("item-1")).SelectMany(x => Convert(x.NewtonsoftExtensionData.get_Item("tags"), Object[]))]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs index f3c27a2230..230e2599a3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs @@ -103,6 +103,12 @@ struct complex public string id; public string pk; + [Newtonsoft.Json.JsonExtensionData(ReadData = true, WriteData = true)] + public Dictionary NewtonsoftExtensionData { get; set; } + + [System.Text.Json.Serialization.JsonExtensionData()] + public Dictionary NetExtensionData { get; set; } + public complex(double d, string str, bool b, double[] da, simple s) { this.dbl = d; @@ -113,6 +119,8 @@ public complex(double d, string str, bool b, double[] da, simple s) this.json = null; this.id = Guid.NewGuid().ToString(); this.pk = "Test"; + this.NetExtensionData = new Dictionary(); + this.NewtonsoftExtensionData = new Dictionary(); } public override string ToString() @@ -236,7 +244,15 @@ public void ValidateSQLTranslation() inputs.Add(new LinqTestInput("Select new constructor", b => dataQuery(b).Select(x => new TimeSpan(x.x)))); inputs.Add(new LinqTestInput("Select method id", b => dataQuery(b).Select(x => id(x)))); inputs.Add(new LinqTestInput("Select identity", b => dataQuery(b).Select(x => x))); - inputs.Add(new LinqTestInput("Select simple property", b => dataQuery(b).Select(x => x.x))); + inputs.Add(new LinqTestInput("Select simple property", b => dataQuery(b).Select(x => x.x))); + inputs.Add(new LinqTestInput("Select extension data", b => dataQuery(b).Select(x => new complex() { + NewtonsoftExtensionData = new() { + { "test", 1.5 } + }, + NetExtensionData = new() { + { "OtherTest", 1.5 } + } + } ))); this.ExecuteTestSuite(inputs); } @@ -264,6 +280,10 @@ public void ValidateSQLTranslationComplexData() obj.str = random.NextDouble() < 0.1 ? "5" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)); obj.id = Guid.NewGuid().ToString(); obj.pk = "Test"; + obj.NewtonsoftExtensionData = new Dictionary() { + ["age"] = 32, + ["tags"] = new [] { "item-1", "item-2" } + }; return obj; }; Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, testContainer); @@ -285,6 +305,14 @@ public void ValidateSQLTranslationComplexData() inputs.Add(new LinqTestInput("SelectMany x -> Select y", b => getQuery(b).SelectMany(x => x.dblArray.Select(y => y)))); inputs.Add(new LinqTestInput("SelectMany x -> Select x.y", b => getQuery(b).SelectMany(x => x.dblArray.Select(y => y)))); inputs.Add(new LinqTestInput("SelectMany array", b => getQuery(b).SelectMany(x => x.dblArray))); + + inputs.Add(new LinqTestInput("Select where extensiondata", b => getQuery(b).Where(p => (int)p.NewtonsoftExtensionData["age"] > 18).Select(x => new { Age = (int)x.NewtonsoftExtensionData["age"] }))); + inputs.Add(new LinqTestInput("Select where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).Select(x => (string[])x.NewtonsoftExtensionData["tags"] ))); + + // TODO: SelectMany does not currently work with Dictionary objects, the snapshot represents + // the current (broken) behavior + inputs.Add(new LinqTestInput("SelectMany where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).SelectMany(x => (object[])x.NewtonsoftExtensionData["tags"] ))); + this.ExecuteTestSuite(inputs); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs index ca2e12c8da..8e50a21dd0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; + using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; @@ -152,6 +153,35 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s } } + [TestMethod] + public void TestNewtonsoftExtensionDataQuery() + { + Expression> expr = a => (string)a.NewtonsoftExtensionData["foo"] == "bar"; + string sql = SqlTranslator.TranslateExpression(expr.Body); + + Assert.AreEqual("(a[\"foo\"] = \"bar\")", sql); + } + + [TestMethod] + public void TestSystemTextJsonExtensionDataQuery() + { + Expression> expr = a => ((object)a.NetExtensionData["foo"]) == "bar"; + string sql = SqlTranslator.TranslateExpression(expr.Body); + + // TODO: This is a limitation in the translator. It should be able to handle STJ extension data, if a custom + // JSON serializer is specified. + Assert.AreEqual("(a[\"NetExtensionData\"][\"foo\"] = \"bar\")", sql); + } + + class DocumentWithExtensionData + { + [Newtonsoft.Json.JsonExtensionData(ReadData = true, WriteData = true)] + public Dictionary NewtonsoftExtensionData { get; set; } + + [System.Text.Json.Serialization.JsonExtensionData()] + public Dictionary NetExtensionData { get; set; } + } + /// // See: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs /// From 3a1f46ba42ed08a65c1fc7eb47cea4020c469975 Mon Sep 17 00:00:00 2001 From: Fabian Meiswinkel Date: Tue, 27 Jun 2023 17:47:49 +0200 Subject: [PATCH 148/337] HttpTransport: Fixes HttpTimeoutPolicies to not accidentally suppress retries (#3944) * Fix HttpTimeoutPolicies to not accidentally suppress retries * Removing HttpTimeoutPolicy.MaxRetryTimeLimit altogether --- Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs | 3 +-- Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs | 1 - .../src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs | 2 -- .../HttpTimeoutPolicyControlPlaneRetriableHotPath.cs | 2 -- .../src/HttpClient/HttpTimeoutPolicyDefault.cs | 2 -- .../src/HttpClient/HttpTimeoutPolicyNoRetry.cs | 2 -- 6 files changed, 1 insertion(+), 11 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs index c29c3a5b94..0e7cc30c9e 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs @@ -438,8 +438,7 @@ private static bool IsOutOfRetries( DateTime startDateTimeUtc, IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> timeoutEnumerator) { - return (DateTime.UtcNow - startDateTimeUtc) > timeoutPolicy.MaximumRetryTimeLimit || // Maximum of time for all retries - !timeoutEnumerator.MoveNext(); // No more retries are configured + return !timeoutEnumerator.MoveNext(); // No more retries are configured } private async Task ExecuteHttpHelperAsync( diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs index fa2fc25bf7..42742f86c1 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos internal abstract class HttpTimeoutPolicy { public abstract string TimeoutPolicyName { get; } - public abstract TimeSpan MaximumRetryTimeLimit { get; } public abstract int TotalRetryCount { get; } public abstract IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator(); public abstract bool IsSafeToRetry(HttpMethod httpMethod); diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs index 757134a576..9f85ba33ab 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRead.cs @@ -25,8 +25,6 @@ private HttpTimeoutPolicyControlPlaneRead() public override string TimeoutPolicyName => HttpTimeoutPolicyControlPlaneRead.Name; - public override TimeSpan MaximumRetryTimeLimit => CosmosHttpClient.GatewayRequestTimeout; - public override int TotalRetryCount => this.TimeoutsAndDelays.Count; public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator() diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs index 8dbb8a2a44..53a7c78e9e 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyControlPlaneRetriableHotPath.cs @@ -29,8 +29,6 @@ private HttpTimeoutPolicyControlPlaneRetriableHotPath(bool shouldThrow503OnTimeo public override string TimeoutPolicyName => HttpTimeoutPolicyControlPlaneRetriableHotPath.Name; - public override TimeSpan MaximumRetryTimeLimit => CosmosHttpClient.GatewayRequestTimeout; - public override int TotalRetryCount => this.TimeoutsAndDelays.Count; public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator() diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs index 974509c70c..69a83707a1 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyDefault.cs @@ -29,8 +29,6 @@ private HttpTimeoutPolicyDefault(bool shouldThrow503OnTimeout) public override string TimeoutPolicyName => HttpTimeoutPolicyDefault.Name; - public override TimeSpan MaximumRetryTimeLimit => CosmosHttpClient.GatewayRequestTimeout; - public override int TotalRetryCount => this.TimeoutsAndDelays.Count; public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator() diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyNoRetry.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyNoRetry.cs index 595498aec2..65ea12144b 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyNoRetry.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicyNoRetry.cs @@ -24,8 +24,6 @@ private HttpTimeoutPolicyNoRetry() public override string TimeoutPolicyName => HttpTimeoutPolicyNoRetry.Name; - public override TimeSpan MaximumRetryTimeLimit => TimeSpan.Zero; - public override int TotalRetryCount => 0; public override IEnumerator<(TimeSpan requestTimeout, TimeSpan delayForNextRequest)> GetTimeoutEnumerator() From cf71ddd9103e2a375e46c93c5a3f1b35144e2038 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 27 Jun 2023 09:56:29 -0700 Subject: [PATCH 149/337] SDK 3.35.1 : Adds version bump and changelog (#3945) * version bump * changelog * contract --- Directory.Build.props | 4 +- .../contracts/API_3.35.1-preview.txt | 1563 +++++++++++++++++ .../contracts/API_3.35.1.txt | 1502 ++++++++++++++++ changelog.md | 9 +- 4 files changed, 3075 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.1-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.1.txt diff --git a/Directory.Build.props b/Directory.Build.props index eb4940bf4b..55a67ffec4 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.35.0 - 3.35.0 + 3.35.1 + 3.35.1 preview 3.31.2 2.0.2 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.1-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.1-preview.txt new file mode 100644 index 0000000000..6c989053fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.1-preview.txt @@ -0,0 +1,1563 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.1.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.1.txt new file mode 100644 index 0000000000..c0dc3e280f --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.1.txt @@ -0,0 +1,1502 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index bd5c29c32c..80a2d967c2 100644 --- a/changelog.md +++ b/changelog.md @@ -12,7 +12,14 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -### [3.35.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0-preview) - 2023-06-19 + +### [3.35.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1-preview) - 2023-06-27 +### [3.35.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1) - 2023-06-27 + +#### Fixed +- [3944](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3944) Availability: Fixes HttpTimeoutPolicies to not accidentally suppress retries + +### [3.35.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0-preview) - 2023-06-19 ### Added - [3836](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3836) Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions From c2bf6409c923831171afc1c8790a18e66b8e2df0 Mon Sep 17 00:00:00 2001 From: Fabian Meiswinkel Date: Tue, 27 Jun 2023 19:11:01 +0200 Subject: [PATCH 150/337] [Internal] Changelog: Fixes recommended version and title (#3948) * SDK 3.35.1: Adds version bump and changelog * Update changelog.md * Update changelog.md * Update changelog.md * Update changelog.md * Update changelog.md --- changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 80a2d967c2..f72c7fd59f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ ## Recommended version -The **minimum recommended version is [3.33.0](#3.33.0)**. +The **minimum recommended version is [3.33.0](#3.33.0) when using Direct mode and [3.35.1](#3.35.1) for Gateway mode**. Make sure that your applications, when using the .NET V3 SDK, are using at least the version described here to have all the critical fixes. @@ -21,7 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### [3.35.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0-preview) - 2023-06-19 -### Added +#### Added - [3836](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3836) Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions - [3909](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3909) Query: Adds EnableOptimisticDirectExecution in QueryRequestOptions enabled by default From a25730a77ab43a8e460ddc292f1a6d8eb193395a Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 28 Jun 2023 09:45:30 -0700 Subject: [PATCH 151/337] [Internal] Dependencies: Fixes dependabot alert for System.Linq.Dynamic.Core (#3957) * Removing 1 * Removing 2 * Removing 3 --- ...Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests.csproj | 1 - .../Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj | 1 - .../Microsoft.Azure.Cosmos.EmulatorTests.csproj | 1 - 3 files changed, 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests.csproj index d8dc8fb6a7..c5dfa8db0c 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests.csproj @@ -26,7 +26,6 @@ - diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj index 458cfb6849..0b7c24dbdd 100644 --- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/Microsoft.Azure.Cosmos.Encryption.EmulatorTests.csproj @@ -26,7 +26,6 @@ - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 51891d7e3f..8b1aa3b149 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -54,7 +54,6 @@ - From 17f1b4eef8d6776b40a14fd3acf22c4ca64fb6a2 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 29 Jun 2023 19:06:53 -0700 Subject: [PATCH 152/337] [Internal] Upgrade Resiliency: Adds Code to Enable Replica Validation Feature for Preview (#3951) * Code changes to add replica validation feature in cosmos client options. * Code changes to upgrade the cosmos direct version to 3.31.3. * Adding emulator test to cover replica validation. * Code changes to address cosmetic clean ups. * Code changes to address review comments. Fixed preview build failures. * Code changes to enable replica validation for preview package by default. * Code changes to address review comments. * Code changes to fix preview unit tests. * Code changes to disable environment variable at the end of the test. --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 7 +- .../src/Routing/GatewayAddressCache.cs | 24 +- .../src/Routing/GlobalAddressResolver.cs | 7 +- .../src/Util/ConfigurationManager.cs | 30 +- .../ClientRetryPolicyTests.cs | 3 +- .../CosmosBadReplicaTests.cs | 291 ++++++++++-------- .../GatewayAddressCacheTests.cs | 30 +- .../RequestEventHandlerTests.cs | 2 +- .../StoreReaderTest.cs | 24 +- 10 files changed, 231 insertions(+), 189 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 55a67ffec4..71b854a5c7 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.35.1 3.35.1 preview - 3.31.2 + 3.31.3 2.0.2 2.0.2 preview diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 068bb5b857..752ec8f5a5 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -113,6 +113,8 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider private const string DefaultInitTaskKey = "InitTaskKey"; private readonly bool IsLocalQuorumConsistency = false; + private readonly bool isReplicaAddressValidationEnabled; + //Auth internal readonly AuthorizationTokenProvider cosmosAuthorization; @@ -231,7 +233,7 @@ public DocumentClient(Uri serviceEndpoint, this.Initialize(serviceEndpoint, connectionPolicy, desiredConsistencyLevel); this.initTaskCache = new AsyncCacheNonBlocking(cancellationToken: this.cancellationTokenSource.Token); - + this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(); } /// @@ -6700,7 +6702,8 @@ private void CreateStoreModel(bool subscribeRntbdStatus) this.ConnectionPolicy.EnableReadRequestsFallback ?? (this.accountServiceConfiguration.DefaultConsistencyLevel != Documents.ConsistencyLevel.BoundedStaleness), !this.enableRntbdChannel, this.UseMultipleWriteLocations && (this.accountServiceConfiguration.DefaultConsistencyLevel != Documents.ConsistencyLevel.Strong), - true); + true, + enableReplicaValidation: this.isReplicaAddressValidationEnabled); if (subscribeRntbdStatus) { diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index f864256df9..a4dbb1d8a3 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -66,7 +66,8 @@ public GatewayAddressCache( CosmosHttpClient httpClient, IOpenConnectionsHandler openConnectionsHandler, long suboptimalPartitionForceRefreshIntervalInSeconds = 600, - bool enableTcpConnectionEndpointRediscovery = false) + bool enableTcpConnectionEndpointRediscovery = false, + bool replicaAddressValidationEnabled = false) { this.addressEndpoint = new Uri(serviceEndpoint + "/" + Paths.AddressPathSegment); this.protocol = protocol; @@ -90,9 +91,7 @@ public GatewayAddressCache( GatewayAddressCache.ProtocolString(this.protocol)); this.openConnectionsHandler = openConnectionsHandler; - this.isReplicaAddressValidationEnabled = Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.ReplicaConnectivityValidationEnabled, - defaultValue: false); + this.isReplicaAddressValidationEnabled = replicaAddressValidationEnabled; } public Uri ServiceEndpoint => this.serviceEndpoint; @@ -158,7 +157,8 @@ public async Task OpenConnectionsAsync( collectionRid: collection.ResourceId, partitionKeyRangeIds: partitionKeyRangeIdentities.Skip(i).Take(batchSize).Select(range => range.PartitionKeyRangeId), containerProperties: collection, - shouldOpenRntbdChannels: shouldOpenRntbdChannels)); + shouldOpenRntbdChannels: shouldOpenRntbdChannels, + cancellationToken: cancellationToken)); } } @@ -348,12 +348,14 @@ public async Task TryGetAddressesAsync( /// An instance of containing the list of partition key range ids. /// An instance of containing the collection properties. /// A boolean flag indicating whether Rntbd connections are required to be established to the backend replica nodes. + /// An instance of . private async Task WarmupCachesAndOpenConnectionsAsync( DocumentServiceRequest request, string collectionRid, IEnumerable partitionKeyRangeIds, ContainerProperties containerProperties, - bool shouldOpenRntbdChannels) + bool shouldOpenRntbdChannels, + CancellationToken cancellationToken) { TryCatch documentServiceResponseWrapper = await this.GetAddressesAsync( request: request, @@ -381,6 +383,11 @@ private async Task WarmupCachesAndOpenConnectionsAsync( List openConnectionTasks = new (); foreach (Tuple addressInfo in addressInfos) { + if (cancellationToken.IsCancellationRequested) + { + break; + } + this.serverPartitionAddressCache.Set( new PartitionKeyRangeIdentity(containerProperties.ResourceId, addressInfo.Item1.PartitionKeyRangeId), addressInfo.Item2); @@ -398,10 +405,7 @@ private async Task WarmupCachesAndOpenConnectionsAsync( } } - if (openConnectionTasks.Any()) - { - await Task.WhenAll(openConnectionTasks); - } + await Task.WhenAll(openConnectionTasks); } } catch (Exception ex) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs index 344f994395..8ac0719dcd 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs @@ -27,7 +27,6 @@ namespace Microsoft.Azure.Cosmos.Routing internal sealed class GlobalAddressResolver : IAddressResolverExtension, IDisposable { private const int MaxBackupReadRegions = 3; - private readonly GlobalEndpointManager endpointManager; private readonly GlobalPartitionEndpointManager partitionKeyRangeLocationCache; private readonly Protocol protocol; @@ -39,6 +38,7 @@ internal sealed class GlobalAddressResolver : IAddressResolverExtension, IDispos private readonly CosmosHttpClient httpClient; private readonly ConcurrentDictionary addressCacheByEndpoint; private readonly bool enableTcpConnectionEndpointRediscovery; + private readonly bool isReplicaAddressValidationEnabled; private IOpenConnectionsHandler openConnectionsHandler; public GlobalAddressResolver( @@ -67,6 +67,8 @@ public GlobalAddressResolver( this.enableTcpConnectionEndpointRediscovery = connectionPolicy.EnableTcpConnectionEndpointRediscovery; + this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(); + this.maxEndpoints = maxBackupReadEndpoints + 2; // for write and alternate write endpoint (during failover) this.addressCacheByEndpoint = new ConcurrentDictionary(); @@ -281,7 +283,8 @@ private EndpointCache GetOrAddEndpoint(Uri endpoint) this.serviceConfigReader, this.httpClient, this.openConnectionsHandler, - enableTcpConnectionEndpointRediscovery: this.enableTcpConnectionEndpointRediscovery); + enableTcpConnectionEndpointRediscovery: this.enableTcpConnectionEndpointRediscovery, + replicaAddressValidationEnabled: this.isReplicaAddressValidationEnabled); string location = this.endpointManager.GetLocation(endpoint); AddressResolver addressResolver = new AddressResolver(null, new NullRequestSigner(), location); diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 4e9e8fde84..ed0f5a47a6 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -7,7 +7,14 @@ namespace Microsoft.Azure.Cosmos using System; internal static class ConfigurationManager - { + { + /// + /// A read-only string containing the environment variablename for enabling replica validation. + /// This will eventually be removed oncereplica valdiatin is enabled by default for both preview + /// and GA. + /// + internal static readonly string ReplicaConnectivityValidationEnabled = "AZURE_COSMOS_REPLICA_VALIDATION_ENABLED"; + public static T GetEnvironmentVariable(string variable, T defaultValue) { string value = Environment.GetEnvironmentVariable(variable); @@ -17,5 +24,26 @@ public static T GetEnvironmentVariable(string variable, T defaultValue) } return (T)Convert.ChangeType(value, typeof(T)); } + + /// + /// Gets the boolean value of the replica validation environment variable. Note that, replica validation + /// is enabled by default for the preview package and disabled for GA at the moment. The user can set the + /// respective environment variable 'AZURE_COSMOS_REPLICA_VALIDATION_ENABLED' to override the value for + /// both preview and GA. The method will eventually be removed, once replica valdiatin is enabled by default + /// for both preview and GA. + /// + /// A boolean flag indicating if replica validation is enabled. + public static bool IsReplicaAddressValidationEnabled() + { + bool replicaValidationDefaultValue = false; +#if PREVIEW + replicaValidationDefaultValue = true; +#endif + + return ConfigurationManager + .GetEnvironmentVariable( + variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, + defaultValue: replicaValidationDefaultValue); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs index a41f08afa1..0851952f40 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs @@ -209,7 +209,8 @@ private async Task ValidateConnectTimeoutTriggersClientRetryPolicy( enableReadRequestsFallback: false, useMultipleWriteLocations: useMultipleWriteLocations, detectClientConnectivityIssues: true, - disableRetryWithRetryPolicy: false); + disableRetryWithRetryPolicy: false, + enableReplicaValidation: false); // Reducing retry timeout to avoid long-running tests replicatedResourceClient.GoneAndRetryWithRetryTimeoutInSecondsOverride = 1; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs index 3ef86568b8..7a5b387e8e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs @@ -6,7 +6,6 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; using System.Collections.Generic; - using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -14,44 +13,50 @@ namespace Microsoft.Azure.Cosmos.Tests using System.Text; using System.Threading; using System.Threading.Tasks; - using global::Azure.Core; - using Microsoft.Azure.Cosmos.Fluent; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; - using Newtonsoft.Json.Linq; [TestClass] public class CosmosBadReplicaTests { [TestMethod] [Timeout(30000)] - public async Task TestGoneFromServiceScenarioAsync() + [DataRow(true, DisplayName = "Validate when replica validation is enabled.")] + [DataRow(false, DisplayName = "Validate when replica validation is disabled.")] + public async Task TestGoneFromServiceScenarioAsync( + bool enableReplicaValidation) { - Mock mockHttpHandler = new Mock(MockBehavior.Strict); - Uri endpoint = MockSetupsHelper.SetupSingleRegionAccount( - "mockAccountInfo", - consistencyLevel: ConsistencyLevel.Session, - mockHttpHandler, - out string primaryRegionEndpoint); - - string databaseName = "mockDbName"; - string containerName = "mockContainerName"; - string containerRid = "ccZ1ANCszwk="; - Documents.ResourceId cRid = Documents.ResourceId.Parse(containerRid); - MockSetupsHelper.SetupContainerProperties( - mockHttpHandler: mockHttpHandler, - regionEndpoint: primaryRegionEndpoint, - databaseName: databaseName, - containerName: containerName, - containerRid: containerRid); - - MockSetupsHelper.SetupSinglePartitionKeyRange( - mockHttpHandler, - primaryRegionEndpoint, - cRid, - out IReadOnlyList partitionKeyRanges); - - List replicaIds1 = new List() + try + { + Environment.SetEnvironmentVariable( + variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, + value: enableReplicaValidation.ToString()); + + Mock mockHttpHandler = new Mock(MockBehavior.Strict); + Uri endpoint = MockSetupsHelper.SetupSingleRegionAccount( + "mockAccountInfo", + consistencyLevel: ConsistencyLevel.Session, + mockHttpHandler, + out string primaryRegionEndpoint); + + string databaseName = "mockDbName"; + string containerName = "mockContainerName"; + string containerRid = "ccZ1ANCszwk="; + Documents.ResourceId cRid = Documents.ResourceId.Parse(containerRid); + MockSetupsHelper.SetupContainerProperties( + mockHttpHandler: mockHttpHandler, + regionEndpoint: primaryRegionEndpoint, + databaseName: databaseName, + containerName: containerName, + containerRid: containerRid); + + MockSetupsHelper.SetupSinglePartitionKeyRange( + mockHttpHandler, + primaryRegionEndpoint, + cRid, + out IReadOnlyList partitionKeyRanges); + + List replicaIds1 = new List() { "11111111111111111", "22222222222222222", @@ -59,14 +64,14 @@ public async Task TestGoneFromServiceScenarioAsync() "44444444444444444", }; - HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( - replicaIds1, - partitionKeyRanges.First(), - "eastus", - cRid); + HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( + replicaIds1, + partitionKeyRanges.First(), + "eastus", + cRid); - // One replica changed on the refresh - List replicaIds2 = new List() + // One replica changed on the refresh + List replicaIds2 = new List() { "11111111111111111", "22222222222222222", @@ -74,118 +79,134 @@ public async Task TestGoneFromServiceScenarioAsync() "55555555555555555", }; - HttpResponseMessage replicaSet2 = MockSetupsHelper.CreateAddresses( - replicaIds2, - partitionKeyRanges.First(), - "eastus", - cRid); - - bool delayCacheRefresh = true; - bool delayRefreshUnblocked = false; - mockHttpHandler.SetupSequence(x => x.SendAsync( - It.Is(r => r.RequestUri.ToString().Contains("addresses")), It.IsAny())) - .Returns(Task.FromResult(replicaSet1)) - .Returns(async ()=> + HttpResponseMessage replicaSet2 = MockSetupsHelper.CreateAddresses( + replicaIds2, + partitionKeyRanges.First(), + "eastus", + cRid); + + bool delayCacheRefresh = true; + bool delayRefreshUnblocked = false; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.Is(r => r.RequestUri.ToString().Contains("addresses")), It.IsAny())) + .Returns(Task.FromResult(replicaSet1)) + .Returns(async ()=> + { + //block cache refresh to verify bad replica is not visited during refresh + while (delayCacheRefresh) + { + await Task.Delay(TimeSpan.FromMilliseconds(20)); + } + + delayRefreshUnblocked = true; + return replicaSet2; + }); + + int callBack = 0; + List urisVisited = new List(); + Mock mockTransportClient = new Mock(MockBehavior.Strict); + mockTransportClient.Setup(x => x.InvokeResourceOperationAsync(It.IsAny(), It.IsAny())) + .Callback((t, _) => urisVisited.Add(t)) + .Returns(() => { - //block cache refresh to verify bad replica is not visited during refresh - while (delayCacheRefresh) + callBack++; + if (callBack == 1) { - await Task.Delay(TimeSpan.FromMilliseconds(20)); + throw Documents.Rntbd.TransportExceptions.GetGoneException( + new Uri("https://localhost:8081"), + Guid.NewGuid(), + new Documents.TransportException(Documents.TransportErrorCode.ConnectionBroken, + null, + Guid.NewGuid(), + new Uri("https://localhost:8081"), + "Mock", + userPayload: true, + payloadSent: false)); } - delayRefreshUnblocked = true; - return replicaSet2; - }); - - int callBack = 0; - List urisVisited = new List(); - Mock mockTransportClient = new Mock(MockBehavior.Strict); - mockTransportClient.Setup(x => x.InvokeResourceOperationAsync(It.IsAny(), It.IsAny())) - .Callback((t, _) => urisVisited.Add(t)) - .Returns(() => - { - callBack++; - if (callBack == 1) - { - throw Documents.Rntbd.TransportExceptions.GetGoneException( - new Uri("https://localhost:8081"), - Guid.NewGuid(), - new Documents.TransportException(Documents.TransportErrorCode.ConnectionBroken, - null, - Guid.NewGuid(), - new Uri("https://localhost:8081"), - "Mock", - userPayload: true, - payloadSent: false)); - } - - return Task.FromResult(new Documents.StoreResponse() - { - Status = 200, - Headers = new Documents.Collections.StoreResponseNameValueCollection() + return Task.FromResult(new Documents.StoreResponse() { - ActivityId = Guid.NewGuid().ToString(), - LSN = "12345", - PartitionKeyRangeId = "0", - GlobalCommittedLSN = "12345", - SessionToken = "1#12345#1=12345" - }, - ResponseBody = new MemoryStream() + Status = 200, + Headers = new Documents.Collections.StoreResponseNameValueCollection() + { + ActivityId = Guid.NewGuid().ToString(), + LSN = "12345", + PartitionKeyRangeId = "0", + GlobalCommittedLSN = "12345", + SessionToken = "1#12345#1=12345" + }, + ResponseBody = new MemoryStream() + }); }); - }); - - CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() - { - ConsistencyLevel = Cosmos.ConsistencyLevel.Session, - HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)), - TransportClientHandlerFactory = (original) => mockTransportClient.Object, - }; - using (CosmosClient customClient = new CosmosClient( - endpoint.ToString(), - Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())), - cosmosClientOptions)) - { - try + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() { - Container container = customClient.GetContainer(databaseName, containerName); - - for (int i = 0; i < 20; i++) + ConsistencyLevel = Cosmos.ConsistencyLevel.Session, + HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)), + TransportClientHandlerFactory = (original) => mockTransportClient.Object, + }; + + using (CosmosClient customClient = new CosmosClient( + endpoint.ToString(), + Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())), + cosmosClientOptions)) + { + try { - ResponseMessage response = await container.ReadItemStreamAsync(Guid.NewGuid().ToString(), new Cosmos.PartitionKey(Guid.NewGuid().ToString())); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Container container = customClient.GetContainer(databaseName, containerName); + + for (int i = 0; i < 20; i++) + { + ResponseMessage response = await container.ReadItemStreamAsync(Guid.NewGuid().ToString(), new Cosmos.PartitionKey(Guid.NewGuid().ToString())); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + } + + mockTransportClient.VerifyAll(); + mockHttpHandler.VerifyAll(); + + Documents.TransportAddressUri failedReplica = urisVisited.First(); + + // With replica validation enabled in preview mode, the failed replica will be validated as a part of the flow, + // and because any subsequent validation/ connection will be successful, the failed replica will now be marked + // as connected, thus it will be visited more than once. However, note that when replice validation is disabled, + // no validation is done thus the URI will be marked as unhealthy as expected. Therefore the uri will be visited + // just once. + Assert.IsTrue( + enableReplicaValidation + ? urisVisited.Any(x => x.Equals(failedReplica)) + : urisVisited.Count(x => x.Equals(failedReplica)) == 1); + + urisVisited.Clear(); + delayCacheRefresh = false; + do + { + await Task.Delay(TimeSpan.FromMilliseconds(100)); + }while (!delayRefreshUnblocked); + + for (int i = 0; i < 20; i++) + { + ResponseMessage response = await container.ReadItemStreamAsync(Guid.NewGuid().ToString(), new Cosmos.PartitionKey(Guid.NewGuid().ToString())); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + } + + Assert.AreEqual(4, urisVisited.ToHashSet().Count()); + + // Clears all the setups. No network calls should be done on the next operation. + mockHttpHandler.Reset(); + mockTransportClient.Reset(); } - - mockTransportClient.VerifyAll(); - mockHttpHandler.VerifyAll(); - - Documents.TransportAddressUri failedReplica = urisVisited.First(); - Assert.AreEqual(1, urisVisited.Count(x => x.Equals(failedReplica))); - - urisVisited.Clear(); - delayCacheRefresh = false; - do - { - await Task.Delay(TimeSpan.FromMilliseconds(100)); - }while (!delayRefreshUnblocked); - - for (int i = 0; i < 20; i++) + finally { - ResponseMessage response = await container.ReadItemStreamAsync(Guid.NewGuid().ToString(), new Cosmos.PartitionKey(Guid.NewGuid().ToString())); - Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + mockTransportClient.Setup(x => x.Dispose()); } - - Assert.AreEqual(4, urisVisited.ToHashSet().Count()); - - // Clears all the setups. No network calls should be done on the next operation. - mockHttpHandler.Reset(); - mockTransportClient.Reset(); - } - finally - { - mockTransportClient.Setup(x => x.Dispose()); } } + finally + { + Environment.SetEnvironmentVariable( + variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, + value: null); + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 296c131fbf..c855599465 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -1000,19 +1000,8 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), openConnectionsHandler: fakeOpenConnectionHandler, suboptimalPartitionForceRefreshIntervalInSeconds: 2, - enableTcpConnectionEndpointRediscovery: true); - - // By default, the replica validation feature is disabled in GatewayAddressCache. Reflection is used to enable the feature - // for the purpose of this test. - FieldInfo fieldInfo = cache - .GetType() - .GetField( - name: "isReplicaAddressValidationEnabled", - bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); - - fieldInfo.SetValue( - obj: cache, - value: true); + enableTcpConnectionEndpointRediscovery: true, + replicaAddressValidationEnabled: true); DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); @@ -1156,19 +1145,8 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), openConnectionsHandler: fakeOpenConnectionHandler, suboptimalPartitionForceRefreshIntervalInSeconds: 2, - enableTcpConnectionEndpointRediscovery: true); - - // By default, the replica validation feature is disabled in GatewayAddressCache. Reflection is used to enable the feature - // for the purpose of this test. - FieldInfo fieldInfo = cache - .GetType() - .GetField( - name: "isReplicaAddressValidationEnabled", - bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); - - fieldInfo.SetValue( - obj: cache, - value: true); + enableTcpConnectionEndpointRediscovery: true, + replicaAddressValidationEnabled: true); DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RequestEventHandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RequestEventHandlerTests.cs index f5602a1f29..9a19fb4a90 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RequestEventHandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RequestEventHandlerTests.cs @@ -82,7 +82,7 @@ private StoreClient GetMockStoreClient() TransportClient mockTransportClient = this.GetMockTransportClient(); ISessionContainer sessionContainer = new SessionContainer(string.Empty); - StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer); + StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer, false); Mock mockAuthorizationTokenProvider = new Mock(); mockAuthorizationTokenProvider.Setup(provider => provider.AddSystemAuthorizationHeaderAsync( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs index b92ca3c804..831e32041a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/StoreReaderTest.cs @@ -536,7 +536,8 @@ public void StoreReaderBarrierTest() new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), - sessionContainer); + sessionContainer, + enableReplicaValidation: false); // reads always go to read quorum (2) replicas int replicaCountToRead = 2; @@ -611,14 +612,14 @@ public void GlobalStrongConsistentWriteMockTest() for (int i = 0; i < addressInformation.Length; i++) { TransportClient mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, false, false); - StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer); - ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false); + StoreReader storeReader = new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), sessionContainer, false); + ConsistencyWriter consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false); StoreResponse response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result; Assert.AreEqual(100, response.LSN); //globalCommittedLsn never catches up in this case mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, true, false, false); - consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false); + consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false); try { response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result; @@ -629,17 +630,17 @@ public void GlobalStrongConsistentWriteMockTest() } mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, true, false); - consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false); + consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false); response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result; Assert.AreEqual(100, response.LSN); mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, true, true); - consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false); + consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false); response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result; Assert.AreEqual(100, response.LSN); mockTransportClient = this.GetMockTransportClientForGlobalStrongWrites(addressInformation, i, false, false, true); - consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false); + consistencyWriter = new ConsistencyWriter(addressSelector, sessionContainer, mockTransportClient, mockServiceConfigReader.Object, mockAuthorizationTokenProvider.Object, false, false); response = consistencyWriter.WriteAsync(entity, new TimeoutHelper(TimeSpan.FromSeconds(30)), false).Result; Assert.AreEqual(100, response.LSN); } @@ -703,7 +704,8 @@ public void GlobalStrongConsistencyMockTest() new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), - sessionContainer); + sessionContainer, + false); Mock mockAuthorizationTokenProvider = new Mock(); mockAuthorizationTokenProvider.Setup(provider => provider.AddSystemAuthorizationHeaderAsync( @@ -746,7 +748,8 @@ public void GlobalStrongConsistencyMockTest() new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), - sessionContainer); + sessionContainer, + false); Mock mockAuthorizationTokenProvider = new Mock(); mockAuthorizationTokenProvider.Setup(provider => provider.AddSystemAuthorizationHeaderAsync( @@ -798,7 +801,8 @@ public void GlobalStrongConsistencyMockTest() new StoreReader(mockTransportClient, addressSelector, new AddressEnumerator(), - sessionContainer); + sessionContainer, + false); Mock mockAuthorizationTokenProvider = new Mock(); mockAuthorizationTokenProvider.Setup(provider => provider.AddSystemAuthorizationHeaderAsync( From 077acf3e1a172406fb660af6dea6372e0f5a54c0 Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Tue, 4 Jul 2023 15:31:20 +0530 Subject: [PATCH 153/337] Client Encryption: Adds package reference Microsoft.Azure.Cosmos version 3.35.1-preview (#3956) * changing cosmos preview version * updating build file --------- Co-authored-by: Matias Quaranta --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md | 5 +++++ .../src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 71b854a5c7..51d6237854 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,7 +7,7 @@ 2.0.2 2.0.2 preview - 1.0.0-preview05 + 1.0.0-preview06 1.1.0-preview3 10.0 $([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../')) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md index 58fcf1d790..a96c9c325b 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/changelog.md @@ -3,6 +3,11 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [1.0.0-preview06](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview06) - 2023-06-28 + +#### Fixes +- [#3956](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3956) Updates package reference Microsoft.Azure.Cosmos to version 3.35.1-preview. + ### [1.0.0-preview05](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption.Custom/1.0.0-preview05) - 2023-04-27 #### Fixes diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index 09b92aa37e..a9f729c9ab 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -27,7 +27,7 @@ - + From 0d4e93f932064b1287e64b091687eabb615f7eec Mon Sep 17 00:00:00 2001 From: "microsoft-github-policy-service[bot]" <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Date: Thu, 6 Jul 2023 09:36:56 -0700 Subject: [PATCH 154/337] [Internal] FabricBot: Adds GitOps.ResourceManagement because of FabricBot decommissioning (#3966) * Add prIssueManagement.yml to onboard repo to GitOps.ResourceManagement as FabricBot replacement Owners of the FabricBot configuration should have received email notification. The same information contained in the email is published internally at: https://aka.ms/gim/fabricbot. Details on the replacement service and the syntax of the new yaml configuration file is available publicly at: https://microsoft.github.io/GitOps/policies/resource-management.html Please review and merge this PR to complete the process of onboarding to the new service. * Deleting fabricbot.json --------- Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> --- .github/fabricbot.json | 183 ------------------------ .github/policies/resourceManagement.yml | 57 ++++++++ 2 files changed, 57 insertions(+), 183 deletions(-) delete mode 100644 .github/fabricbot.json create mode 100644 .github/policies/resourceManagement.yml diff --git a/.github/fabricbot.json b/.github/fabricbot.json deleted file mode 100644 index e400139553..0000000000 --- a/.github/fabricbot.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "version": "1.0", - "tasks": [ - { - "taskType": "scheduled", - "capabilityId": "ScheduledSearch", - "subCapability": "ScheduledSearch", - "version": "1.1", - "config": { - "frequency": [ - { - "weekDay": 0, - "hours": [], - "timezoneOffset": -8 - } - ], - "searchTerms": [ - { - "name": "noActivitySince", - "parameters": { - "days": 180 - } - }, - { - "name": "noLabel", - "parameters": { - "label": "VNext" - } - }, - { - "name": "noLabel", - "parameters": { - "label": "feature-request" - } - } - ], - "taskName": "CosmosV3-InactivePruge", - "actions": [ - { - "name": "addReply", - "parameters": { - "comment": "Closing due to in-activity, pease feel free to re-open." - } - }, - { - "name": "closeIssue", - "parameters": {} - } - ] - }, - "disabled": true - }, - { - "taskType": "trigger", - "capabilityId": "IssueResponder", - "subCapability": "IssuesOnlyResponder", - "version": "1.0", - "config": { - "conditions": { - "operator": "and", - "operands": [ - { - "operator": "not", - "operands": [ - { - "name": "isAssignedToSomeone", - "parameters": {} - } - ] - }, - { - "name": "isAction", - "parameters": { - "action": "opened" - } - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "needs-investigation" - } - } - ] - } - ] - }, - "eventType": "issue", - "eventNames": [ - "issues", - "project_card" - ], - "taskName": "Add needs-investigation", - "actions": [ - { - "name": "addLabel", - "parameters": { - "label": "needs-investigation" - } - } - ] - } - }, - { - "taskType": "trigger", - "capabilityId": "AutoMerge", - "subCapability": "AutoMerge", - "version": "1.0", - "config": { - "taskName": "PR Automerge", - "allowAutoMergeInstructionsWithoutLabel": false, - "mergeType": "squash", - "deleteBranches": true, - "removeLabelOnPush": true, - "label": "auto-merge", - "requireAllStatuses": false, - "requireSpecificCheckRuns": false, - "usePrDescriptionAsCommitMessage": false, - "minMinutesOpen": "60", - "enforceDMPAsStatus": true - } - }, - { - "taskType": "scheduled", - "capabilityId": "ScheduledSearch", - "subCapability": "ScheduledSearch", - "version": "1.1", - "config": { - "frequency": [ - { - "weekDay": 1, - "hours": [ - 9 - ], - "timezoneOffset": -7 - } - ], - "searchTerms": [ - { - "name": "isOpen", - "parameters": {} - }, - { - "name": "isIssue", - "parameters": {} - }, - { - "name": "hasLabel", - "parameters": { - "label": "needs-more-information" - } - }, - { - "name": "noActivitySince", - "parameters": { - "days": 14 - } - }, - { - "name": "noAssignees", - "parameters": {} - } - ], - "taskName": "Close inactive needs-information", - "actions": [ - { - "name": "addReply", - "parameters": { - "comment": "@${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue." - } - }, - { - "name": "closeIssue", - "parameters": {} - } - ] - } - } - ], - "userGroups": [] -} diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml new file mode 100644 index 0000000000..8207a0708a --- /dev/null +++ b/.github/policies/resourceManagement.yml @@ -0,0 +1,57 @@ +id: +name: GitOps.PullRequestIssueManagement +description: GitOps.PullRequestIssueManagement primitive +owner: +resource: repository +disabled: false +where: +configuration: + resourceManagementConfiguration: + scheduledSearches: + - description: + frequencies: + - weekday: + day: Monday + time: 9:0 + filters: + - isOpen + - isIssue + - hasLabel: + label: needs-more-information + - noActivitySince: + days: 14 + - isNotAssigned + actions: + - addReply: + reply: '@${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue.' + - closeIssue + eventResponderTasks: + - if: + - payloadType: Issues + - not: isAssignedToSomeone + - isAction: + action: Opened + - not: + hasLabel: + label: needs-investigation + then: + - addLabel: + label: needs-investigation + description: + - if: + - payloadType: Pull_Request + - hasLabel: + label: auto-merge + then: + - enableAutoMerge: + mergeMethod: Squash + description: + - if: + - payloadType: Pull_Request + - labelRemoved: + label: auto-merge + then: + - disableAutoMerge + description: +onFailure: +onSuccess: From 1981fc121408deff3204d50e941dbf4825e035f6 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Fri, 7 Jul 2023 13:59:49 -0700 Subject: [PATCH 155/337] [Internal] Query: Refactors certain tests to not fail when EnableOptimisticDirectExecution is set to true in 3.35.0-preview package (#3955) * Updated emulator and baseline tests to not fail when ODE is set to default true in PREVIEW mode * Fixed QueryAsync() test * Fixed QueryAsync() in EndToEndTraceBaselineTests * Undid changes to IndexMetrics baseline file * Updated EndToEndTraceWriterBaselineTests.QueryAsync xml * Updated xml * Updated xml to have request options tag --- ...EndTraceWriterBaselineTests.QueryAsync.xml | 21 +++++++++----- .../CosmosBasicQueryTests.cs | 10 +++++-- .../CosmosGatewayTimeoutTests.cs | 9 +++++- .../CosmosItemSessionTokenTests.cs | 5 +++- .../CosmosJsonSerializerTests.cs | 12 ++++++-- .../FeedToken/QueryFeedTokenTests.cs | 7 ++++- .../LinqTestsCommon.cs | 18 ++++++++++-- .../LinqTranslationBaselineTests.cs | 8 ++++- .../Query/AggregateQueryTests.cs | 3 ++ .../Query/SanityQueryTests.cs | 6 ++++ .../EndToEndTraceWriterBaselineTests.cs | 29 ++++++++++++++----- 11 files changed, 103 insertions(+), 25 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 8b737a419e..d6d638fd47 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -4,7 +4,8 @@ Query traces = new List(); while (feedIterator.HasMoreResults) @@ -696,7 +697,8 @@ Query Typed feedIterator = (FeedIteratorInternal)container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); while (feedIterator.HasMoreResults) @@ -1408,7 +1410,8 @@ Query Public API traces = new List(); @@ -2101,7 +2104,8 @@ Query Public API Typed feedIterator = container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); @@ -2816,7 +2820,8 @@ Lazy currentLazy = Documents.ServiceInteropWrapper.AssembliesExist; Documents.ServiceInteropWrapper.AssembliesExist = new Lazy(() => false); FeedIterator feedIterator = container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); @@ -3596,7 +3601,8 @@ FeedIterator feedIterator = container.GetItemQueryStreamIterator( feedRange: FeedRangeEpk.FullRange, queryDefinition: new QueryDefinition("SELECT * FROM c"), - continuationToken: null); + continuationToken: null, + requestOptions: requestOptions); List traces = new List(); @@ -4298,7 +4304,8 @@ FeedIterator feedIterator = container.GetItemQueryIterator( feedRange: FeedRangeEpk.FullRange, queryDefinition: new QueryDefinition("SELECT * FROM c"), - continuationToken: null); + continuationToken: null, + requestOptions: requestOptions); List traces = new List(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs index 7ae2b28cc6..25ac9a705f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs @@ -240,7 +240,10 @@ public async Task QueryRequestRateTest(bool directMode) requestOptions: new QueryRequestOptions() { MaxItemCount = 1, - MaxConcurrency = 1 + MaxConcurrency = 1, +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif })) { while (feedIterator.HasMoreResults) @@ -268,7 +271,10 @@ public async Task QueryRequestRateTest(bool directMode) requestOptions: new QueryRequestOptions() { MaxItemCount = 1, - MaxConcurrency = 1 + MaxConcurrency = 1, +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif }); // First request should be a success diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs index f50319f65f..241b60fb7f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs @@ -81,7 +81,14 @@ public async Task QueryPlanRetryTimeoutTestAsync() } }; - using FeedIterator iterator = gatewayQueryPlanContainer.GetItemQueryIterator("select * From T order by T.status"); + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; + + using FeedIterator iterator = gatewayQueryPlanContainer.GetItemQueryIterator("select * From T order by T.status", requestOptions: requestOptions); FeedResponse response = await iterator.ReadNextAsync(); Assert.IsTrue(isQueryRequestFound, "Query plan call back was not called."); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs index f815eba08e..c76110f1fb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs @@ -366,7 +366,10 @@ public async Task InvalidSessionTokenAfterContainerRecreationAndCollectionCacheR new QueryRequestOptions { ConsistencyLevel = Cosmos.ConsistencyLevel.Session, - PartitionKey = new Cosmos.PartitionKey(pk) + PartitionKey = new Cosmos.PartitionKey(pk), +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif }); int itemCountOldContainer = 0; while (queryIteratorOldContainer.HasMoreResults) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs index 0be44fbc1c..eadb62da7c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs @@ -98,7 +98,11 @@ public async Task TestQueryWithCustomJsonSerializer() fromStreamCount = 0; FeedIterator itemIterator = container.GetItemQueryIterator( - query); + query +#if PREVIEW + , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } +#endif + ); List items = new List(); while (itemIterator.HasMoreResults) { @@ -113,7 +117,11 @@ public async Task TestQueryWithCustomJsonSerializer() // Verify that the custom serializer is actually being used via stream FeedIterator itemStreamIterator = container.GetItemQueryStreamIterator( - query); + query +#if PREVIEW + , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } +#endif + ); while (itemStreamIterator.HasMoreResults) { ResponseMessage response = await itemStreamIterator.ReadNextAsync(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs index df61615fe6..ce9723e7ee 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs @@ -101,7 +101,12 @@ public async Task InexistentPKRangeId() FeedIterator feedIterator = container.GetItemQueryIterator( queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedRange, - continuationToken: null); + continuationToken: null + +#if PREVIEW + , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } +#endif + ); CosmosException exception = await Assert.ThrowsExceptionAsync(() => feedIterator.ReadNextAsync()); Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs index 5907d861fc..87b33110e2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs @@ -296,7 +296,14 @@ public static Func> GenerateTestCosmosData(Func query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); // To cover both query against backend and queries on the original data using LINQ nicely, // the LINQ expression should be written once and they should be compiled and executed against the two sources. @@ -483,7 +490,14 @@ Cosmos.Database cosmosDatabase } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); // To cover both query against backend and queries on the original data using LINQ nicely, // the LINQ expression should be written once and they should be compiled and executed against the two sources. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 5a46a2d118..51da69c98f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -1136,8 +1136,14 @@ public void TestSelectTop() Tuple> generatedData = this.CreateDataTestSelectTop(); int seed = generatedData.Item1; List data = generatedData.Item2; + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; - IOrderedQueryable query = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + IOrderedQueryable query = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); Func> getQuery = useQuery => useQuery ? query : data.AsQueryable(); List inputs = new List diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs index 0bcfcea030..d60f76f92c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs @@ -152,6 +152,9 @@ async Task ImplementationAsync( new QueryRequestOptions() { MaxConcurrency = maxDoP, +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif }); if (argument.ExpectedValue == null) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 60ab6f9fe4..9eecd81e30 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -538,6 +538,9 @@ static async Task ImplementationAsync(Container container, IReadOnlyList MaxBufferedItemCount = 7000, MaxConcurrency = maxDegreeOfParallelism, MaxItemCount = maxItemCount, +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif }; async Task> AssertPassthroughAsync(string query, Cosmos.PartitionKey? pk = default) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 64bc7c015a..79e947d41b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -25,7 +25,7 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Tracing using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using static Microsoft.Azure.Cosmos.SDK.EmulatorTests.TransportClientHelper; - + [VisualStudio.TestTools.UnitTesting.TestClass] [TestCategory("UpdateContract")] public sealed class EndToEndTraceWriterBaselineTests : BaselineTests @@ -464,6 +464,12 @@ public async Task ChangeFeedAsync() public async Task QueryAsync() { List inputs = new List(); + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; int startLineNumber; int endLineNumber; @@ -474,7 +480,8 @@ public async Task QueryAsync() { startLineNumber = GetLineNumber(); FeedIteratorInternal feedIterator = (FeedIteratorInternal)container.GetItemQueryStreamIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); while (feedIterator.HasMoreResults) @@ -499,7 +506,8 @@ public async Task QueryAsync() { startLineNumber = GetLineNumber(); FeedIteratorInternal feedIterator = (FeedIteratorInternal)container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); while (feedIterator.HasMoreResults) @@ -524,7 +532,8 @@ public async Task QueryAsync() { startLineNumber = GetLineNumber(); FeedIterator feedIterator = container.GetItemQueryStreamIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); @@ -550,7 +559,8 @@ public async Task QueryAsync() { startLineNumber = GetLineNumber(); FeedIterator feedIterator = container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); @@ -578,7 +588,8 @@ public async Task QueryAsync() Lazy currentLazy = Documents.ServiceInteropWrapper.AssembliesExist; Documents.ServiceInteropWrapper.AssembliesExist = new Lazy(() => false); FeedIterator feedIterator = container.GetItemQueryIterator( - queryText: "SELECT * FROM c"); + queryText: "SELECT * FROM c", + requestOptions: requestOptions); List traces = new List(); @@ -607,7 +618,8 @@ public async Task QueryAsync() FeedIterator feedIterator = container.GetItemQueryStreamIterator( feedRange: FeedRangeEpk.FullRange, queryDefinition: new QueryDefinition("SELECT * FROM c"), - continuationToken: null); + continuationToken: null, + requestOptions: requestOptions); List traces = new List(); @@ -635,7 +647,8 @@ public async Task QueryAsync() FeedIterator feedIterator = container.GetItemQueryIterator( feedRange: FeedRangeEpk.FullRange, queryDefinition: new QueryDefinition("SELECT * FROM c"), - continuationToken: null); + continuationToken: null, + requestOptions: requestOptions); List traces = new List(); From d3fa6a88142d7373c8ee9f96e1a54e08f63a6027 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Mon, 10 Jul 2023 08:07:18 -0700 Subject: [PATCH 156/337] Diagnostics: Fixes verbose levels for "Operation will NOT be retried" (#3969) --- Microsoft.Azure.Cosmos/src/ResourceThrottleRetryPolicy.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ResourceThrottleRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/ResourceThrottleRetryPolicy.cs index c6187f3e51..a99bc594f7 100644 --- a/Microsoft.Azure.Cosmos/src/ResourceThrottleRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ResourceThrottleRetryPolicy.cs @@ -52,7 +52,7 @@ public Task ShouldRetryAsync( { if (!this.IsValidThrottleStatusCode(dce.StatusCode)) { - DefaultTrace.TraceError( + DefaultTrace.TraceVerbose( "Operation will NOT be retried. Current attempt {0}, Status Code: {1} ", this.currentAttemptCount, dce.StatusCode); @@ -81,7 +81,7 @@ public Task ShouldRetryAsync( { if (!this.IsValidThrottleStatusCode(cosmosResponseMessage?.StatusCode)) { - DefaultTrace.TraceError( + DefaultTrace.TraceVerbose( "Operation will NOT be retried. Current attempt {0}, Status Code: {1} ", this.currentAttemptCount, cosmosResponseMessage?.StatusCode); From 51c9d9c6fda1656cb1d3a28d2bb23df3e1ce43ad Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Mon, 10 Jul 2023 12:37:50 -0700 Subject: [PATCH 157/337] Query: Fixes malformed continuation token exception type and message (#3917) * Fixed malformed continuation token issue where Exception was not CosmosExceptionan and did not have the correct Status and Sub Status codes. * Fixed incorrect indentation * Added type check for incoming exception * Replaced if/else with extra catch block * Moved fix to a higher point in the call stack * Removed unused Usings * Updated test code --------- Co-authored-by: Matias Quaranta --- .../src/ReadFeed/ReadFeedIteratorCore.cs | 25 ++++++++++++++++-- .../CosmosItemLinqTests.cs | 26 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs index d9b935e758..8a46196a56 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs @@ -9,13 +9,16 @@ namespace Microsoft.Azure.Cosmos.ReadFeed using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Diagnostics; + using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.Exceptions; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; /// /// Cosmos feed stream iterator. This is used to get the query responses with a Stream content @@ -113,7 +116,25 @@ public ReadFeedIteratorCore( else { CosmosString tokenAsString = (CosmosString)token; - state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); + try + { + state = ReadFeedState.Continuation(CosmosElement.Parse(tokenAsString.Value)); + } + catch (Exception exception) when (exception.InnerException is JsonParseException) + { + MalformedContinuationTokenException malformedContinuationTokenException = new MalformedContinuationTokenException(exception.Message); + throw CosmosExceptionFactory.CreateBadRequestException( + message: $"Malformed Continuation Token: {tokenAsString}.", + headers: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders( + new Headers(), + default, + default, + (int)SubStatusCodes.MalformedContinuationToken, + default), + stackTrace: exception.StackTrace, + innerException: malformedContinuationTokenException, + trace: null); + } } FeedRangeState feedRangeState = new FeedRangeState(feedRange, state); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs index 28fc3ec61c..b3dc7afa41 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs @@ -211,6 +211,32 @@ public async Task ItemLINQQueryTest() Assert.AreEqual(itemList[1].id, queriable.ToList()[0].id); } + [TestMethod] + public void ItemLINQQueryWithInvalidContinuationTokenTest() + { + string malformedString = "Malformed String"; + FeedIterator feedIterator = this.Container.GetItemLinqQueryable().ToFeedIterator(); + + while (feedIterator.HasMoreResults) + { + IOrderedQueryable querable = this.Container.GetItemLinqQueryable( + continuationToken: malformedString); + try + { + FeedIterator iterator = querable.ToFeedIterator(); + } + catch (CosmosException exception) + { + Assert.IsTrue(exception.StatusCode == System.Net.HttpStatusCode.BadRequest); + Assert.IsTrue(exception.SubStatusCode == (int)Documents.SubStatusCodes.MalformedContinuationToken); + Assert.IsTrue(exception.Message.Contains(malformedString)); + return; + } + + Assert.Fail("Should never reach till here, hence ensuring that an exception is always recieved"); + } + } + [TestMethod] public async Task ItemLINQQueryWithContinuationTokenTest() { From 4bb62d378c2960088efa44c76f96ca4bdac8fae6 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:38:22 -0700 Subject: [PATCH 158/337] [Internal] Upgrade Resiliency: Refactors Code to Enable Replica Validation Feature Through `CosmosClientOptions` And Environment Variable (#3974) * Code changes to use client options to enable or disable replica validation. * Code changes to fix preview build failures. --- .../src/ConnectionPolicy.cs | 12 +++ .../src/CosmosClientOptions.cs | 12 +++ Microsoft.Azure.Cosmos/src/DocumentClient.cs | 2 +- .../src/Routing/GlobalAddressResolver.cs | 2 +- .../src/Util/ConfigurationManager.cs | 9 ++- .../CosmosReadManyItemsTests.cs | 61 +++++++++++---- .../CosmosBadReplicaTests.cs | 75 +++++++++++-------- .../CosmosClientOptionsUnitTests.cs | 7 +- 8 files changed, 131 insertions(+), 49 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index 7abfd76deb..9193abedef 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -459,6 +459,18 @@ public Func HttpClientFactory set; } + /// + /// Gets or sets the boolean flag to enable replica validation. + /// + /// + /// The default value for this parameter is false. + /// + public bool? EnableAdvancedReplicaSelectionForTcp + { + get; + set; + } + /// /// (Direct/TCP) This is an advanced setting that controls the number of TCP connections that will be opened eagerly to each Cosmos DB back-end. /// diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 1fce195915..330738c00b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -346,6 +346,17 @@ public ConnectionMode ConnectionMode /// public bool? EnableContentResponseOnWrite { get; set; } + /// + /// Gets or sets the advanced replica selection flag. The advanced replica selection logic keeps track of the replica connection + /// status, and based on status, it prioritizes the replicas which show healthy stable connections, so that the requests can be sent + /// confidently to the particular replica. This helps the cosmos client to become more resilient and effective to any connectivity issues. + /// The default value for this parameter is 'false'. + /// + /// + /// This is optimal for latency-sensitive workloads. Does not apply if is used. + /// + internal bool? EnableAdvancedReplicaSelectionForTcp { get; set; } + /// /// (Direct/TCP) Controls the amount of idle time after which unused connections are closed. /// @@ -758,6 +769,7 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) EnablePartitionLevelFailover = this.EnablePartitionLevelFailover, PortReuseMode = this.portReuseMode, EnableTcpConnectionEndpointRediscovery = this.EnableTcpConnectionEndpointRediscovery, + EnableAdvancedReplicaSelectionForTcp = this.EnableAdvancedReplicaSelectionForTcp, HttpClientFactory = this.httpClientFactory, ServerCertificateCustomValidationCallback = this.ServerCertificateCustomValidationCallback }; diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 752ec8f5a5..c7aeb07a6f 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -233,7 +233,7 @@ public DocumentClient(Uri serviceEndpoint, this.Initialize(serviceEndpoint, connectionPolicy, desiredConsistencyLevel); this.initTaskCache = new AsyncCacheNonBlocking(cancellationToken: this.cancellationTokenSource.Token); - this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(); + this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(connectionPolicy); } /// diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs index 8ac0719dcd..058e9c3ce4 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalAddressResolver.cs @@ -67,7 +67,7 @@ public GlobalAddressResolver( this.enableTcpConnectionEndpointRediscovery = connectionPolicy.EnableTcpConnectionEndpointRediscovery; - this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(); + this.isReplicaAddressValidationEnabled = ConfigurationManager.IsReplicaAddressValidationEnabled(connectionPolicy); this.maxEndpoints = maxBackupReadEndpoints + 2; // for write and alternate write endpoint (during failover) diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index ed0f5a47a6..216e1295b5 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -32,13 +32,20 @@ public static T GetEnvironmentVariable(string variable, T defaultValue) /// both preview and GA. The method will eventually be removed, once replica valdiatin is enabled by default /// for both preview and GA. /// + /// An instance of containing the client options. /// A boolean flag indicating if replica validation is enabled. - public static bool IsReplicaAddressValidationEnabled() + public static bool IsReplicaAddressValidationEnabled( + ConnectionPolicy connectionPolicy) { bool replicaValidationDefaultValue = false; #if PREVIEW replicaValidationDefaultValue = true; #endif + if (connectionPolicy != null + && connectionPolicy.EnableAdvancedReplicaSelectionForTcp.HasValue) + { + return connectionPolicy.EnableAdvancedReplicaSelectionForTcp.Value; + } return ConfigurationManager .GetEnvironmentVariable( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs index d215b6b18b..05184d7826 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosReadManyItemsTests.cs @@ -51,27 +51,58 @@ public async Task Cleanup() } [TestMethod] - public async Task ReadManyTypedTest() + [DataRow(true, DisplayName = "Validates Read Many scenario with advanced replica selection enabled.")] + [DataRow(false, DisplayName = "Validates Read Many scenario with advanced replica selection disabled.")] + public async Task ReadManyTypedTestWithAdvancedReplicaSelection( + bool advancedReplicaSelectionEnabled) { - List<(string, PartitionKey)> itemList = new List<(string, PartitionKey)>(); - for (int i=0; i<10; i++) + CosmosClientOptions clientOptions = new () { - itemList.Add((i.ToString(), new PartitionKey("pk" + i.ToString()))); - } + EnableAdvancedReplicaSelectionForTcp = advancedReplicaSelectionEnabled, + }; - FeedResponse feedResponse= await this.Container.ReadManyItemsAsync(itemList); - Assert.IsNotNull(feedResponse); - Assert.AreEqual(feedResponse.Count, 10); - Assert.IsTrue(feedResponse.Headers.RequestCharge > 0); - Assert.IsNotNull(feedResponse.Diagnostics); + Database database = null; + CosmosClient cosmosClient = TestCommon.CreateCosmosClient(clientOptions); + try + { + database = await cosmosClient.CreateDatabaseAsync("ReadManyTypedTestScenarioDb"); + Container container = await database.CreateContainerAsync("ReadManyTypedTestContainer", "/pk"); - int count = 0; - foreach (ToDoActivity item in feedResponse) + // Create items with different pk values + for (int i = 0; i < 500; i++) + { + ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); + item.pk = "pk" + i.ToString(); + item.id = i.ToString(); + ItemResponse itemResponse = await container.CreateItemAsync(item); + Assert.AreEqual(HttpStatusCode.Created, itemResponse.StatusCode); + } + + List<(string, PartitionKey)> itemList = new List<(string, PartitionKey)>(); + for (int i = 0; i < 20; i++) + { + itemList.Add((i.ToString(), new PartitionKey("pk" + i.ToString()))); + } + + FeedResponse feedResponse = await container.ReadManyItemsAsync(itemList); + Assert.IsNotNull(feedResponse); + Assert.AreEqual(20, feedResponse.Count); + Assert.IsTrue(feedResponse.Headers.RequestCharge > 0); + Assert.IsNotNull(feedResponse.Diagnostics); + + int count = 0; + foreach (ToDoActivity item in feedResponse) + { + count++; + Assert.IsNotNull(item); + } + Assert.AreEqual(20, count); + } + finally { - count++; - Assert.IsNotNull(item); + await database.DeleteAsync(); + cosmosClient.Dispose(); } - Assert.AreEqual(count, 10); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs index 7a5b387e8e..151e0690a8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs @@ -21,16 +21,23 @@ public class CosmosBadReplicaTests { [TestMethod] [Timeout(30000)] - [DataRow(true, DisplayName = "Validate when replica validation is enabled.")] - [DataRow(false, DisplayName = "Validate when replica validation is disabled.")] + [DataRow(true, true, false, DisplayName = "Validate when replica validation is enabled using environment variable.")] + [DataRow(false, true, false, DisplayName = "Validate when replica validation is disabled using environment variable.")] + [DataRow(true, false, true, DisplayName = "Validate when replica validation is enabled using cosmos client options.")] + [DataRow(false, false, true, DisplayName = "Validate when replica validation is disabled using cosmos client options.")] public async Task TestGoneFromServiceScenarioAsync( - bool enableReplicaValidation) + bool enableReplicaValidation, + bool useEnvironmentVariable, + bool useCosmosClientOptions) { try { - Environment.SetEnvironmentVariable( - variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, - value: enableReplicaValidation.ToString()); + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable( + variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, + value: enableReplicaValidation.ToString()); + } Mock mockHttpHandler = new Mock(MockBehavior.Strict); Uri endpoint = MockSetupsHelper.SetupSingleRegionAccount( @@ -56,28 +63,28 @@ public async Task TestGoneFromServiceScenarioAsync( cRid, out IReadOnlyList partitionKeyRanges); - List replicaIds1 = new List() - { - "11111111111111111", - "22222222222222222", - "33333333333333333", - "44444444444444444", - }; - - HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( - replicaIds1, - partitionKeyRanges.First(), - "eastus", - cRid); + List replicaIds1 = new List() + { + "11111111111111111", + "22222222222222222", + "33333333333333333", + "44444444444444444", + }; - // One replica changed on the refresh - List replicaIds2 = new List() - { - "11111111111111111", - "22222222222222222", - "33333333333333333", - "55555555555555555", - }; + HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( + replicaIds1, + partitionKeyRanges.First(), + "eastus", + cRid); + + // One replica changed on the refresh + List replicaIds2 = new List() + { + "11111111111111111", + "22222222222222222", + "33333333333333333", + "55555555555555555", + }; HttpResponseMessage replicaSet2 = MockSetupsHelper.CreateAddresses( replicaIds2, @@ -146,6 +153,11 @@ public async Task TestGoneFromServiceScenarioAsync( TransportClientHandlerFactory = (original) => mockTransportClient.Object, }; + if (useCosmosClientOptions) + { + cosmosClientOptions.EnableAdvancedReplicaSelectionForTcp = enableReplicaValidation; + } + using (CosmosClient customClient = new CosmosClient( endpoint.ToString(), Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())), @@ -203,9 +215,12 @@ public async Task TestGoneFromServiceScenarioAsync( } finally { - Environment.SetEnvironmentVariable( - variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, - value: null); + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable( + variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, + value: null); + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index efb06d7cc5..37d89c389a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -81,6 +81,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsNull(clientOptions.HttpClientFactory); Assert.AreNotEqual(consistencyLevel, clientOptions.ConsistencyLevel); Assert.IsFalse(clientOptions.EnablePartitionLevelFailover); + Assert.IsFalse(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue); //Verify GetConnectionPolicy returns the correct values for default ConnectionPolicy policy = clientOptions.GetConnectionPolicy(clientId: 0); @@ -97,6 +98,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsNull(policy.HttpClientFactory); Assert.AreNotEqual(Cosmos.ConsistencyLevel.Session, clientOptions.ConsistencyLevel); Assert.IsFalse(policy.EnablePartitionLevelFailover); + Assert.IsFalse(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue); cosmosClientBuilder.WithApplicationRegion(region) .WithConnectionModeGateway(maxConnections, webProxy) @@ -112,6 +114,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); clientOptions = cosmosClient.ClientOptions; + clientOptions.EnableAdvancedReplicaSelectionForTcp = true; //Verify all the values are updated Assert.AreEqual(region, clientOptions.ApplicationRegion); @@ -131,6 +134,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(clientOptions.AllowBulkExecution); Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); + Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue && clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); //Verify GetConnectionPolicy returns the correct values policy = clientOptions.GetConnectionPolicy(clientId: 0); @@ -145,7 +149,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds); Assert.AreEqual((Documents.ConsistencyLevel)consistencyLevel, clientOptions.GetDocumentsConsistencyLevel()); Assert.IsTrue(policy.EnablePartitionLevelFailover); - + Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); + IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; //Verify Direct Mode settings cosmosClientBuilder = new CosmosClientBuilder( From d0aac27bfdd5fb90a7ab0523491897454f69ba6b Mon Sep 17 00:00:00 2001 From: ernesto1596 Date: Tue, 11 Jul 2023 11:43:55 -0700 Subject: [PATCH 159/337] Query : Adds string comparison alternative when converting LINQ to SQL (#3668) * string.Compare supported with LINQ to SQL * Update tests * Update test name * Update tests * Add test * Create helper ReverseExpressionTypeForStrings * PR feedback * Update tests * Update base line --------- Co-authored-by: Aditya Co-authored-by: Matias Quaranta --- .../src/ClientResources.Designer.cs | 18 ++ .../src/ClientResources.resx | 8 +- .../src/Linq/ExpressionToSQL.cs | 87 +++++- ...slationBaselineTests.TestStringCompare.xml | 267 ++++++++++++++++++ ...ationBaselineTests.TestStringCompareTo.xml | 6 +- .../LinqTranslationBaselineTests.cs | 52 ++++ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 8 +- 7 files changed, 429 insertions(+), 17 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml diff --git a/Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs b/Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs index 7ea2672d6c..3736d0fbbd 100644 --- a/Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs +++ b/Microsoft.Azure.Cosmos/src/ClientResources.Designer.cs @@ -582,6 +582,24 @@ internal static string StringCompareToInvalidOperator { } } + /// + /// Looks up a localized string similar to Invalid operator for string.Compare(). Valid operators are ('==', '<', '<=', '>' or '>='). + /// + internal static string StringCompareInvalidOperator { + get { + return ResourceManager.GetString("StringCompareInvalidOperator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The right hand side of string.Compare() comparison must be constant '0'. + /// + internal static string StringCompareInvalidConstant { + get { + return ResourceManager.GetString("StringCompareInvalidConstant", resourceCulture); + } + } + /// /// Looks up a localized string similar to Token refresh in progress.. /// diff --git a/Microsoft.Azure.Cosmos/src/ClientResources.resx b/Microsoft.Azure.Cosmos/src/ClientResources.resx index ae00e80a78..7a3e336e2a 100644 --- a/Microsoft.Azure.Cosmos/src/ClientResources.resx +++ b/Microsoft.Azure.Cosmos/src/ClientResources.resx @@ -268,11 +268,17 @@ Failed to deserialize response returned by server. - The right hand side of string.CompareTo() comparison must be constant '0' + The right-hand side of String.CompareTo() comparison must be constant '0'. + + + The right-hand side of String.Compare() comparison must be constant '0'. Invalid operator for string.CompareTo(). Vaid operators are ('==', '<', '<=', '>' or '>=') + + Invalid operator for string.Compare(). Vaid operators are ('==', '<', '<=', '>' or '>=') + Token refresh in progress. diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index b259234336..2ada0738da 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -457,6 +457,11 @@ private static SqlScalarExpression VisitBinary(BinaryExpression inputExpression, { return ExpressionToSql.VisitStringCompareTo(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context); } + + if (TryMatchStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType)) + { + return ExpressionToSql.VisitStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context); + } } SqlScalarExpression left = ExpressionToSql.VisitScalarExpression(inputExpression.Left, context); @@ -615,32 +620,90 @@ private static SqlScalarExpression VisitStringCompareTo( { if (reverseNodeType) { + compareOperator = ReverseExpressionTypeForStrings(compareOperator, ClientResources.StringCompareToInvalidOperator); + } + + SqlBinaryScalarOperatorKind op = GetBinaryOperatorKind(compareOperator, null); + + SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Object, context); + SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context); + + return SqlBinaryScalarExpression.Create(op, leftExpression, rightExpression); + } + + private static ExpressionType ReverseExpressionTypeForStrings(ExpressionType compareOperator, string errorMessage) + { + switch (compareOperator) + { + case ExpressionType.Equal: + // do nothing + break; + case ExpressionType.GreaterThan: + compareOperator = ExpressionType.LessThan; + break; + case ExpressionType.GreaterThanOrEqual: + compareOperator = ExpressionType.LessThanOrEqual; + break; + case ExpressionType.LessThan: + compareOperator = ExpressionType.GreaterThan; + break; + case ExpressionType.LessThanOrEqual: + compareOperator = ExpressionType.GreaterThanOrEqual; + break; + default: + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, errorMessage)); + } + + return compareOperator; + } + + private static bool TryMatchStringCompare(MethodCallExpression left, ConstantExpression right, ExpressionType compareOperator) + { + if (left.Method.Equals(typeof(string).GetMethod("Compare", new Type[] { typeof(string), typeof(string) })) && left.Arguments.Count == 2) + { + // operator can only be =, >, >=, <, <= switch (compareOperator) { case ExpressionType.Equal: - // do nothing - break; case ExpressionType.GreaterThan: - compareOperator = ExpressionType.LessThan; - break; case ExpressionType.GreaterThanOrEqual: - compareOperator = ExpressionType.LessThanOrEqual; - break; case ExpressionType.LessThan: - compareOperator = ExpressionType.GreaterThan; - break; case ExpressionType.LessThanOrEqual: - compareOperator = ExpressionType.GreaterThanOrEqual; break; default: - throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareToInvalidOperator)); + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareInvalidOperator)); + } + + // the constant value should be zero, otherwise we can't determine how to translate the expression + // it could be either integer or nullable integer + if (!(right.Type == typeof(int) && (int)right.Value == 0) && + !(right.Type == typeof(int?) && ((int?)right.Value).HasValue && ((int?)right.Value).Value == 0)) + { + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.StringCompareInvalidConstant)); } + + return true; + } + + return false; + } + + private static SqlScalarExpression VisitStringCompare( + MethodCallExpression left, + ConstantExpression right, + ExpressionType compareOperator, + bool reverseNodeType, + TranslationContext context) + { + if (reverseNodeType) + { + compareOperator = ReverseExpressionTypeForStrings(compareOperator, ClientResources.StringCompareInvalidOperator); } SqlBinaryScalarOperatorKind op = GetBinaryOperatorKind(compareOperator, null); - SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Object, context); - SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context); + SqlScalarExpression leftExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[0], context); + SqlScalarExpression rightExpression = ExpressionToSql.VisitNonSubqueryScalarExpression(left.Arguments[1], context); return SqlBinaryScalarExpression.Create(op, leftExpression, rightExpression); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml new file mode 100644 index 0000000000..17538ff1d8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml @@ -0,0 +1,267 @@ + + + + + (Compare(doc.StringField, doc.StringField2) == 0))]]> + + + + + + + + + + ]]> + (Compare(doc.StringField, doc.StringField2) > 0))]]> + + + + root["StringField2"]) +FROM root]]> + + + + + + =]]> + (Compare(doc.StringField, doc.StringField2) >= 0))]]> + + + + = root["StringField2"]) +FROM root]]> + + + + + + + (Compare(doc.StringField, doc.StringField2) < 0))]]> + + + + + + + + + + + (Compare(doc.StringField, doc.StringField2) <= 0))]]> + + + + + + + + + + + (Compare(doc.StringField, "str") == 0))]]> + + + + + + + + + + ]]> + (Compare(doc.StringField, "str") > 0))]]> + + + + "str") +FROM root]]> + + + + + + =]]> + (Compare(doc.StringField, "str") >= 0))]]> + + + + = "str") +FROM root]]> + + + + + + + (Compare(doc.StringField, "str") < 0))]]> + + + + + + + + + + + (Compare(doc.StringField, "str") <= 0))]]> + + + + + + + + + + + (0 == Compare(doc.StringField, doc.StringField2)))]]> + + + + + + + + + + + (0 < Compare(doc.StringField, doc.StringField2)))]]> + + + + root["StringField2"]) +FROM root]]> + + + + + + + (0 <= Compare(doc.StringField, doc.StringField2)))]]> + + + + = root["StringField2"]) +FROM root]]> + + + + + + reverse operands]]> + (0 > Compare(doc.StringField, doc.StringField2)))]]> + + + + + + + + + + = reverse operands]]> + (0 >= Compare(doc.StringField, doc.StringField2)))]]> + + + + + + + + + + 1]]> + (Compare(doc.StringField, "str") > 1))]]> + + + + + + + + + + (Compare(doc.StringField, "str") == 1))]]> + + + + + + + + + + (Compare(doc.StringField, "str") == -1))]]> + + + + + + + + + + (Compare(doc.StringField, "str") | 0))]]> + + + + ' or '>=')]]> + + + + + + (Compare(doc.StringField, "str") & 0))]]> + + + + ' or '>=')]]> + + + + + + (Compare(doc.StringField, "str") ^ 0))]]> + + + + ' or '>=')]]> + + + + + + (Compare(doc.StringField, 0, "str", 0, 3) == 0))]]> + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompareTo.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompareTo.xml index 979d6f6191..c730415fb6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompareTo.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompareTo.xml @@ -171,7 +171,7 @@ FROM root]]> - + @@ -181,7 +181,7 @@ FROM root]]> - + @@ -191,7 +191,7 @@ FROM root]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs index 51da69c98f..4c8d6c423f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs @@ -1044,6 +1044,58 @@ public void TestStringCompareTo() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void TestStringCompare() + { + IOrderedQueryable testQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + const int Records = 100; + const int MaxStringLength = 20; + Func createDataObj = (random) => + { + DataObject obj = new DataObject(); + obj.StringField = LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)); + obj.StringField2 = random.NextDouble() < 0.5 ? obj.StringField : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)); + obj.Id = Guid.NewGuid().ToString(); + obj.Pk = "Test"; + return obj; + }; + Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, testContainer); + + List inputs = new List + { + // projected compare + new LinqTestInput("Projected Compare ==", b => getQuery(b).Select(doc => String.Compare(doc.StringField, doc.StringField2) == 0)), + new LinqTestInput("Projected Compare >", b => getQuery(b).Select(doc => String.Compare(doc.StringField, doc.StringField2) > 0)), + new LinqTestInput("Projected Compare >=", b => getQuery(b).Select(doc => String.Compare(doc.StringField, doc.StringField2) >= 0)), + new LinqTestInput("Projected Compare <", b => getQuery(b).Select(doc => String.Compare(doc.StringField, doc.StringField2) < 0)), + new LinqTestInput("Projected Compare <=", b => getQuery(b).Select(doc => String.Compare(doc.StringField, doc.StringField2) <= 0)), + // static strings + new LinqTestInput("String.Compare static string ==", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") == 0)), + new LinqTestInput("String.Compare static string >", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") > 0)), + new LinqTestInput("String.Compare static string >=", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") >= 0)), + new LinqTestInput("String.Compare static string <", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") < 0)), + new LinqTestInput("String.Compare static string <=", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") <= 0)), + // reverse operands + new LinqTestInput("Projected Compare == reverse operands", b => getQuery(b).Select(doc => 0 == String.Compare(doc.StringField, doc.StringField2))), + new LinqTestInput("Projected Compare < reverse operands", b => getQuery(b).Select(doc => 0 < String.Compare(doc.StringField, doc.StringField2))), + new LinqTestInput("Projected Compare <= reverse operands", b => getQuery(b).Select(doc => 0 <= String.Compare(doc.StringField, doc.StringField2))), + new LinqTestInput("Projected Compare > reverse operands", b => getQuery(b).Select(doc => 0 > String.Compare(doc.StringField, doc.StringField2))), + new LinqTestInput("Projected Compare >= reverse operands", b => getQuery(b).Select(doc => 0 >= String.Compare(doc.StringField, doc.StringField2))), + // errors Invalid compare value + new LinqTestInput("String.Compare > 1", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") > 1)), + new LinqTestInput("String.Compare == 1", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") == 1)), + new LinqTestInput("String.Compare == -1", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") == -1)), + // errors Invalid operator + new LinqTestInput("String.Compare | 0", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") | 0)), + new LinqTestInput("String.Compare & 0", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") & 0)), + new LinqTestInput("String.Compare ^ 0", b => getQuery(b).Select(doc => String.Compare(doc.StringField, "str") ^ 0)), + // errors Unexpected number of arguments to string.Compare + new LinqTestInput("Unexpected number of arguments to string.Compare", b => getQuery(b).Select(doc => String.Compare(doc.StringField, 0, "str", 0, 3) == 0)) + }; + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void TestUDFs() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 8b1aa3b149..8011b07351 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -1,4 +1,4 @@ - + true true @@ -214,6 +214,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -300,6 +303,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From d7fc28225057ac402a7c862daf7707d08a2f70d3 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 13 Jul 2023 00:41:10 +0530 Subject: [PATCH 160/337] AI Integration: Fixes event generation for failed requests (#3973) * first draft * fix code * included feedback * flip condition * updated docs * Update docs/observability.md Co-authored-by: Matias Quaranta * Update observability.md * updated contract --------- Co-authored-by: Matias Quaranta --- .../OpenTelemetry/CosmosDbEventSource.cs | 13 +++++++++++- .../Filters/DiagnosticsFilterHelper.cs | 21 ++++++++++++++----- ...iterBaselineTests.BatchOperationsAsync.xml | 2 +- .../Telemetry/DiagnosticsFilterHelperTest.cs | 6 +++--- docs/observability.md | 7 ++++++- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index 091373b0de..9e8028c0d8 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -35,7 +35,12 @@ public static void RecordDiagnosticsForRequests( Documents.OperationType operationType, OpenTelemetryAttributes response) { - if (DiagnosticsFilterHelper.IsTracingNeeded( + if (!DiagnosticsFilterHelper.IsSuccessfulResponse( + response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) + { + CosmosDbEventSource.Singleton.FailedRequest(response.Diagnostics.ToString()); + } + else if (DiagnosticsFilterHelper.IsLatencyThresholdCrossed( config: config, operationType: operationType, response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) @@ -64,5 +69,11 @@ private void LatencyOverThreshold(string message) { this.WriteEvent(2, message); } + + [Event(3, Level = EventLevel.Error)] + private void FailedRequest(string message) + { + this.WriteEvent(3, message); + } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index 7649977fa0..60fb86fa5c 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -10,12 +10,10 @@ namespace Microsoft.Azure.Cosmos.Telemetry.Diagnostics internal static class DiagnosticsFilterHelper { /// - /// Allow only when either of below is True

- /// 1) Latency is not more than 100/250 (query) ms

- /// 3) HTTP status code is not Success

+ /// Allow only when Latency is not more than 100 (non-query) /250 (query) ms ///
/// true or false - public static bool IsTracingNeeded( + public static bool IsLatencyThresholdCrossed( DistributedTracingOptions config, OperationType operationType, OpenTelemetryAttributes response) @@ -31,7 +29,20 @@ public static bool IsTracingNeeded( latencyThreshold = operationType == OperationType.Query ? DistributedTracingOptions.DefaultQueryTimeoutThreshold : DistributedTracingOptions.DefaultCrudLatencyThreshold; } - return response.Diagnostics.GetClientElapsedTime() > latencyThreshold || !response.StatusCode.IsSuccess(); + return response.Diagnostics.GetClientElapsedTime() > latencyThreshold; + } + + /// + /// Check if response HTTP status code is returning successful + /// + /// true or false + public static bool IsSuccessfulResponse(OpenTelemetryAttributes response) + { + return response.StatusCode.IsSuccess() + || (response.StatusCode == System.Net.HttpStatusCode.NotFound && response.SubStatusCode == 0) + || (response.StatusCode == System.Net.HttpStatusCode.NotModified && response.SubStatusCode == 0) + || (response.StatusCode == System.Net.HttpStatusCode.Conflict && response.SubStatusCode == 0) + || (response.StatusCode == System.Net.HttpStatusCode.PreconditionFailed && response.SubStatusCode == 0); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index 66edf29c06..fd097032d9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -162,7 +162,7 @@ 1001 207 - +
\ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index c04c0d6faf..e345394265 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -46,7 +46,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() Assert.IsFalse( DiagnosticsFilterHelper - .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), + .IsLatencyThresholdCrossed(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}" ); @@ -70,8 +70,8 @@ public void CheckReturnTrueOnFailedStatusCode() }; Assert.IsTrue( - DiagnosticsFilterHelper - .IsTracingNeeded(distributedTracingOptions, OperationType.Read, response), + !DiagnosticsFilterHelper + .IsSuccessfulResponse(response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); diff --git a/docs/observability.md b/docs/observability.md index 50ce14d33c..1da6f02e44 100644 --- a/docs/observability.md +++ b/docs/observability.md @@ -5,6 +5,11 @@ **Source to capture operation level activities**: _Azure.Cosmos.Operation_\ **Source to capture event with request diagnostics** : _Azure-Cosmos-Operation-Request-Diagnostics_ +There are 3 kind of events generated: +1. LatencyOverThrehold: If particular operation latency is more than threshold. +2. FailedRequest: If particular reequest failed. Status codes not considered as failed, are anything below 300, 404/0, 304/0, 409/0, and 412/0 +3. Exception: If any exception occured. + For detail about usage of this feature, please see the [Azure Cosmos DB SDK observability](https://learn.microsoft.com/azure/cosmos-db/nosql/sdk-observability?tabs=dotnet) ```mermaid @@ -104,4 +109,4 @@ flowchart TD ``` ### Limitations -1. AAD Support is not available. \ No newline at end of file +1. AAD Support is not available. From 8d2691b984dac9a1c668d37f74cbfe306dd03671 Mon Sep 17 00:00:00 2001 From: Mikhail Lipin Date: Fri, 14 Jul 2023 22:10:39 +0300 Subject: [PATCH 161/337] [Internal] Category: Refactors Cosmos benchmark operations (#3961) * Refactoring: base classes for operations. * Updating comments. * Adding new line at the end of the file. * Fixing code review points. * Restore PrepareAsync to be virtual. --- .../Tools/Benchmark/BenchmarkOperationType.cs | 16 ++++++++++++++++ .../Benchmark/Fx/CosmosDiagnosticsLogger.cs | 3 --- .../Tools/Benchmark/IBenchmarkOperation.cs | 18 +++++++++++++++++- .../Benchmark/v2/InsertV2BenchmarkOperation.cs | 2 ++ .../QueryStreamSinglePkV2BenchmarkOperation.cs | 2 ++ .../v2/QueryTSinglePkV2BenchmarkOperation.cs | 4 +++- .../v2/ReadFeedStreamV2BenchmarkOperation.cs | 4 +++- .../v2/ReadNotExistsV2BenchmarkOperation.cs | 4 +++- .../v2/ReadStreamExistsV2BenchmarkOperation.cs | 4 +++- .../v2/ReadTExistsV2BenchmarkOperation.cs | 4 +++- .../Benchmark/v3/InsertV3BenchmarkOperation.cs | 2 ++ .../Benchmark/v3/QueryTV3BenchmarkOperation.cs | 4 +++- .../v3/ReadFeedStreamV3BenchmarkOperation.cs | 6 ++++-- .../v3/ReadNotExistsV3BenchmarkOperation.cs | 4 +++- .../v3/ReadStreamExistsV3BenchmarkOperation.cs | 2 ++ ...xistsWithDiagnosticsV3BenchmarkOperation.cs | 4 +++- .../v3/ReadTExistsV3BenchmarkOperation.cs | 7 ++++--- 17 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkOperationType.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkOperationType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkOperationType.cs new file mode 100644 index 0000000000..b18fb1c318 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkOperationType.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark +{ + /// + /// Benchmark operation type. + /// + public enum BenchmarkOperationType + { + Read, + Insert, + Query + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/CosmosDiagnosticsLogger.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/CosmosDiagnosticsLogger.cs index 9a399c5dc8..e08b2dd6da 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/CosmosDiagnosticsLogger.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/CosmosDiagnosticsLogger.cs @@ -6,11 +6,8 @@ namespace CosmosBenchmark { using System; using System.Collections.Concurrent; - using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using System.Runtime.CompilerServices; - using System.Text; using Microsoft.Azure.Cosmos; using Newtonsoft.Json.Linq; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/IBenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/IBenchmarkOperation.cs index d6933fcce5..3580a8a6fc 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/IBenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/IBenchmarkOperation.cs @@ -6,10 +6,26 @@ namespace CosmosBenchmark { using System.Threading.Tasks; + /// + /// Represents the Benchmark operation. + /// internal interface IBenchmarkOperation { - Task PrepareAsync(); + /// + /// Benchmark operation type. + /// + BenchmarkOperationType OperationType { get; } + /// + /// Executes Benchmark operation once asynchronously. + /// + /// The operation result wrapped by task. Task ExecuteOnceAsync(); + + /// + /// Prepares Benchmark operation asynchronously. + /// + /// The task related to method's work. + Task PrepareAsync(); } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs index 744bb9f577..124c841085 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs @@ -38,6 +38,8 @@ public InsertV2BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Insert; + public async Task ExecuteOnceAsync() { ResourceResponse itemResponse = await this.documentClient.CreateDocumentAsync( diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs index 1bf3bf245e..b0f071f6de 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs @@ -47,6 +47,8 @@ public QueryStreamSinglePkV2BenchmarkOperation( this.containerUri = UriFactory.CreateDocumentCollectionUri(this.databsaeName, this.containerName); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Query; + public async Task ExecuteOnceAsync() { IDocumentQuery query = this.documentClient.CreateDocumentQuery( diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs index 7d58447859..cd50a789b8 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs @@ -46,6 +46,8 @@ public QueryTSinglePkV2BenchmarkOperation( this.sampleJObject[this.partitionKeyPath] = this.executionItemPartitionKey; } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Query; + public async Task ExecuteOnceAsync() { IDocumentQuery> query = this.documentClient.CreateDocumentQuery>( @@ -107,7 +109,7 @@ public async Task PrepareAsync() new RequestOptions() { PartitionKey = new PartitionKey(this.executionItemPartitionKey) }); if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } this.initialized = true; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs index 379cd363e6..0a9b9e3d7f 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs @@ -40,6 +40,8 @@ public ReadFeedStreamV2BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { Uri containerUri = UriFactory.CreateDocumentCollectionUri(this.databsaeName, this.containerName); @@ -75,7 +77,7 @@ public async Task PrepareAsync() new RequestOptions() { PartitionKey = new PartitionKey(this.nextExecutionItemPartitionKey) }); if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs index f5e8f94c68..1d8b99449e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs @@ -22,6 +22,8 @@ internal class ReadNotExistsV2BenchmarkOperation : IBenchmarkOperation private readonly DocumentClient documentClient; + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public ReadNotExistsV2BenchmarkOperation( DocumentClient documentClient, string dbName, @@ -52,7 +54,7 @@ public async Task ExecuteOnceAsync() { if (dce.StatusCode != HttpStatusCode.NotFound) { - throw new Exception($"ReadItem failed wth {dce?.StatusCode} {dce?.ToString()}"); + throw new Exception($"ReadItem failed with {dce?.StatusCode} {dce?.ToString()}"); } return new OperationResult() diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs index 7afd4cdf71..c7419db811 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs @@ -25,6 +25,8 @@ internal class ReadStreamExistsV2BenchmarkOperation : IBenchmarkOperation private readonly DocumentClient documentClient; + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public ReadStreamExistsV2BenchmarkOperation( DocumentClient documentClient, string dbName, @@ -84,7 +86,7 @@ public async Task PrepareAsync() if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs index 061183c575..7e161f8ffc 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs @@ -26,6 +26,8 @@ internal class ReadTExistsV2BenchmarkOperation : IBenchmarkOperation private readonly DocumentClient documentClient; + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public ReadTExistsV2BenchmarkOperation( DocumentClient documentClient, string dbName, @@ -85,7 +87,7 @@ public async Task PrepareAsync() if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs index 1ab5861242..504148bfda 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs @@ -37,6 +37,8 @@ public InsertV3BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Insert; + public async Task ExecuteOnceAsync() { using (MemoryStream input = JsonHelper.ToStream(this.sampleJObject)) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs index bdb0b38cf8..f78153034b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs @@ -31,6 +31,8 @@ internal abstract class QueryTV3BenchmarkOperation : IBenchmarkOperation public abstract bool IsPaginationEnabled { get; } public abstract bool IsQueryStream { get; } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Query; + protected string executionItemId = null; protected string executionPartitionKey = null; @@ -291,7 +293,7 @@ public virtual async Task PrepareAsync() if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs index 99789040b0..3b9c5cd800 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs @@ -39,6 +39,8 @@ public ReadFeedStreamV3BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { FeedIterator feedIterator = this.container @@ -50,7 +52,7 @@ public async Task ExecuteOnceAsync() ResponseMessage feedResponse = await feedIterator.ReadNextAsync(); if (feedResponse.StatusCode != HttpStatusCode.OK) { - throw new Exception($"ReadItem failed wth {feedResponse.StatusCode}"); + throw new Exception($"ReadItem failed with {feedResponse.StatusCode}"); } return new OperationResult() @@ -84,7 +86,7 @@ public async Task PrepareAsync() if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs index c97d1af4b7..1804ea9852 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs @@ -32,6 +32,8 @@ public ReadNotExistsV3BenchmarkOperation( this.container = cosmosClient.GetContainer(this.databsaeName, this.containerName); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { using (ResponseMessage itemResponse = await this.container.ReadItemStreamAsync( @@ -40,7 +42,7 @@ public async Task ExecuteOnceAsync() { if (itemResponse.StatusCode != HttpStatusCode.NotFound) { - throw new Exception($"ReadItem failed wth {itemResponse.StatusCode}"); + throw new Exception($"ReadItem failed with {itemResponse.StatusCode}"); } return new OperationResult() diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs index aba0a4ea7a..fabe8f20bd 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs @@ -39,6 +39,8 @@ public ReadStreamExistsV3BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { using (ResponseMessage itemResponse = await this.container.ReadItemStreamAsync( diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs index ebdc14924b..74f2ac67f7 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs @@ -39,6 +39,8 @@ public ReadStreamExistsWithDiagnosticsV3BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { using (ResponseMessage itemResponse = await this.container.ReadItemStreamAsync( @@ -47,7 +49,7 @@ public async Task ExecuteOnceAsync() { if (itemResponse.StatusCode != HttpStatusCode.OK) { - throw new Exception($"ReadItem failed wth {itemResponse.StatusCode}"); + throw new Exception($"ReadItem failed with {itemResponse.StatusCode}"); } string diagnostics = itemResponse.Diagnostics.ToString(); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs index 7fd40397be..bb6295356e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs @@ -10,7 +10,6 @@ namespace CosmosBenchmark using System.Net; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; - using Newtonsoft.Json.Linq; internal class ReadTExistsV3BenchmarkOperation : IBenchmarkOperation { @@ -40,6 +39,8 @@ public ReadTExistsV3BenchmarkOperation( this.sampleJObject = JsonHelper.Deserialize>(sampleJson); } + public BenchmarkOperationType OperationType => BenchmarkOperationType.Read; + public async Task ExecuteOnceAsync() { ItemResponse> itemResponse = await this.container.ReadItemAsync>( @@ -47,7 +48,7 @@ public async Task ExecuteOnceAsync() new PartitionKey(this.nextExecutionItemPartitionKey)); if (itemResponse.StatusCode != HttpStatusCode.OK) { - throw new Exception($"ReadItem failed wth {itemResponse.StatusCode}"); + throw new Exception($"ReadItem failed with {itemResponse.StatusCode}"); } return new OperationResult() @@ -81,7 +82,7 @@ public async Task PrepareAsync() if (itemResponse.StatusCode != HttpStatusCode.Created) { - throw new Exception($"Create failed with statuscode: {itemResponse.StatusCode}"); + throw new Exception($"Create failed with status code: {itemResponse.StatusCode}"); } } } From 38b556b60ed921c74bb6fdc44361cf5ec6c503d8 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:07:24 -0700 Subject: [PATCH 162/337] 3.35.2: Adds new SDK versions and contract files (#3985) * Updated change log and bumped up the version. * Changing the version to 3.35.2 * Code changes to address review comments. * Code changes to make minor fixes. * Code changes to move some fixes into preview. --- Directory.Build.props | 4 +- .../contracts/API_3.35.2-preview.txt | 1563 +++++++++++++++++ .../contracts/API_3.35.2.txt | 1502 ++++++++++++++++ changelog.md | 18 + 4 files changed, 3085 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.2-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.2.txt diff --git a/Directory.Build.props b/Directory.Build.props index 51d6237854..b9171d6307 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.35.1 - 3.35.1 + 3.35.2 + 3.35.2 preview 3.31.3 2.0.2 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.2-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.2-preview.txt new file mode 100644 index 0000000000..6c989053fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.2-preview.txt @@ -0,0 +1,1563 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.2.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.2.txt new file mode 100644 index 0000000000..c0dc3e280f --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.2.txt @@ -0,0 +1,1502 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index f72c7fd59f..481cde52db 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,24 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +###
[3.35.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.2-preview) - 2023-07-17 + +#### Fixed +- [3973](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3973) Application Insights Integration: Fixes event generation for failed requests + +#### Added +- [3951](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3951) Upgrade Resiliency: Adds Code to Enable Replica Validation Feature By Default for Preview + +### [3.35.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.2) - 2023-07-17 + +#### Fixed +- [3917](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3917) Query: Fixes malformed continuation token exception type and message +- [3969](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3969) Diagnostics: Fixes verbose levels for "Operation will NOT be retried" + +#### Added +- [3668](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3668) Query : Adds string comparison alternative when converting LINQ to SQL (Thanks [@ernesto1596](https://github.com/ernesto1596)) +- [3834](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3834) Query : Adds support for newtonsoft member access via ExtensionData (Thanks [@onionhammer](https://github.com/onionhammer)) + ### [3.35.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1-preview) - 2023-06-27 ### [3.35.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1) - 2023-06-27 From d71dcb2def59cfd07ad84eadc0a5793f8ae5b5a4 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Wed, 19 Jul 2023 14:02:05 -0700 Subject: [PATCH 163/337] [INTERNAL] LocalQuorum: Adds documentation for LocalQuorum (#3993) * Draft of local-quorum documentation * Adding experimental to header * Adding cross-region read guarantees * Reads Bounded clarification * Adding account consistency step also * Non-Prod usage note at top * Addressing review comments * Some more refinement --- docs/LocalQuorum.md | 59 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/LocalQuorum.md diff --git a/docs/LocalQuorum.md b/docs/LocalQuorum.md new file mode 100644 index 0000000000..5ca45e9055 --- /dev/null +++ b/docs/LocalQuorum.md @@ -0,0 +1,59 @@ +> # NOT SUPPORTED FOR PRODUCTION USAGE +> # ONLY INTERNAL, DEVELOPMENT OR EXPERIMENTAL USAGE ONLY + + +## Context +Distributed databases that rely on replication for high availability, low latency, or both, must make a fundamental tradeoff between the read consistency, availability, latency, and throughput. + +The linearizability of the strong consistency model is the gold standard of data programmability. But it adds a steep price from higher write latencies due to data having to replicate and commit across large distances. Strong consistency may also suffer from reduced availability (during failures) because data can't replicate and commit in every region. Eventual consistency offers higher availability and better performance, but it's more difficult to program applications because data may not be consistent across all regions (eventual reads are not guaranteed to be monotonic). + + +Please refer to [public documentation](https://learn.microsoft.com/en-us/azure/cosmos-db/consistency-levels) for more details. + + +Many applications can benefit from having a read-write model like below + +| Operation | Write-Region | Replicated-Regions | +|---|---|---| +|Write | Write high availabillity in write region
vs BoundedStaleness: write un-availability when bounds are violated | Eventual replication: Asynchronous non-blocking, possibly unbounded staleness
vs BoundedStaleness: staleness limited by bounds | +|Read |**Single write region**: Read my writes
**Multiple write regions**: read-my-writes from the region of writes, otherwise eventual
Monotonic reads
No sessionToken management| **Single write region**: Eventual read
**Multiple write regions**: read-my-writes from the region of writes, otherwise eventual
Monotonic reads
No sessionToken management | + +> ### NOTE: cross-region reads will violate the monotonic reads guarantee + + +## How-TO +It involves three stages + +#### Create CosmosDB account with Eventual/ConsistentPrefix/Session consistency + +#### Enabling/opt-in ability to upgrade consistency level +SDK version: MA [3.35.1](https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/changelog.md#-3351---2023-06-27) or [minimum recommended version](https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/changelog.md#-recommended-version) + +```C# +CosmosClientOptions clientOptions = new CosmosClientOptions(); +var upgradeConsistencyProperty = clientOptions.GetType().GetProperty("EnableUpgradeConsistencyToLocalQuorum", BindingFlags.NonPublic | BindingFlags.Instance); +upgradeConsistencyProperty.SetValue(clientOptions, true); + +CosmosClient cosmosClient = new CosmosClient(..., clientOptions); +``` + +#### Per request upgrade consistency to Bounded +> ###### Please note that Bounded here is only used as HINT for SDK to do quorum reads +> ###### It will not impact CosmosDB account or write consistency levels + +```C# +ItemRequestOptions requestOption = new ItemRequestOptions(); +requestOption.ConsistencyLevel = ConsistencyLevel.Bounded; + +T item = await container.ReadItemAsync(docId, new PartitionKey(docPartitionKey), requestOption); +``` + +```C# +QueryRequestOptions requestOption = new QueryRequestOptions(); +requestOption.ConsistencyLevel = ConsistencyLevel.Bounded; + +await container.GetItemQueryIterator(queryText, continuationToken, requestOption); +``` + +> #### Please use Bounded only for per request options as pattern +> #### Single master account possibly Strong == Bounded (**TBD**) \ No newline at end of file From 5ec7b4bcd7e2e0698736cd374f2196682227c913 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 19 Jul 2023 16:26:04 -0700 Subject: [PATCH 164/337] Code changes to update release note. (#3996) --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 481cde52db..ab733a4137 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 #### Added - [3668](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3668) Query : Adds string comparison alternative when converting LINQ to SQL (Thanks [@ernesto1596](https://github.com/ernesto1596)) - [3834](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3834) Query : Adds support for newtonsoft member access via ExtensionData (Thanks [@onionhammer](https://github.com/onionhammer)) +- [3939](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3939) CreateAndInitializeAsync: Adds Code to Optimize Rntbd Open Connection Logic to Open Connections in Parallel ###
[3.35.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1-preview) - 2023-06-27 ### [3.35.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.1) - 2023-06-27 From 08981bf2fd87f110ca4a1e2af5f82974857c1aaf Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Sat, 29 Jul 2023 02:33:38 +0530 Subject: [PATCH 165/337] Client Encryption: Adds fix for supporting Prefix Partition Key (Hierarchical partitioning) (#3979) * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * testing new version * adding more tests * adding more tests * adding more tests * code review changes * test fix * test fix * test fix * test fix --------- Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> --- Directory.Build.props | 4 +- .../changelog.md | 10 + .../src/EncryptionContainer.cs | 17 +- .../Microsoft.Azure.Cosmos.Encryption.csproj | 4 +- .../tests/EmulatorTests/MdeEncryptionTests.cs | 388 +++++++++++++++++- 5 files changed, 413 insertions(+), 10 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b9171d6307..9daa1e7e9f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,8 +4,8 @@ 3.35.2 preview 3.31.3 - 2.0.2 - 2.0.2 + 2.0.3 + 2.0.3 preview 1.0.0-preview06 1.1.0-preview3 diff --git a/Microsoft.Azure.Cosmos.Encryption/changelog.md b/Microsoft.Azure.Cosmos.Encryption/changelog.md index a8edf3441d..2f50fcbdf3 100644 --- a/Microsoft.Azure.Cosmos.Encryption/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption/changelog.md @@ -3,6 +3,16 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [2.0.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.3) - 2023-07-12 + +#### Added +- [#3979](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3979) Adds fix for supporting Prefix Partition Key (Hierarchical partitioning). + +### [2.0.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.3-preview) - 2023-07-12 + +#### Added +- [#3979](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3979) Adds fix for supporting Prefix Partition Key (Hierarchical partitioning). + ### [2.0.2](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.2) - 2023-06-01 #### Added diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs index d32bfa1c94..0bd342f0ef 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs @@ -957,15 +957,22 @@ internal async Task CheckIfIdIsEncryptedAndGetEncryptedIdAsync( JArray jArray = JArray.Parse(partitionKey.ToString()); #if ENCRYPTIONPREVIEW - if (jArray.Count > 1) + if (encryptionSettings.PartitionKeyPaths.Count > 1) { - int i = 0; + int counter = 0; PartitionKeyBuilder partitionKeyBuilder = new PartitionKeyBuilder(); + if (jArray.Count() > encryptionSettings.PartitionKeyPaths.Count()) + { + throw new NotSupportedException($"The number of partition keys passed in the query exceeds the number of keys initialized on the container. Container Id : {this.Id}"); + } bool isPkEncrypted = false; + // partitionKeyBuilder expects the paths and values to be in same order. - foreach (string path in encryptionSettings.PartitionKeyPaths) + for(counter = 0; counter < jArray.Count(); counter++) { + string path = encryptionSettings.PartitionKeyPaths[counter]; + // case: partition key path is /a/b/c and the client encryption policy has /a in path. // hence encrypt the partition key value with using its top level path /a since /c would have been encrypted in the document using /a's policy. string partitionKeyPath = path.Split('/')[1]; @@ -975,12 +982,12 @@ internal async Task CheckIfIdIsEncryptedAndGetEncryptedIdAsync( if (encryptionSettingForProperty == null) { - partitionKeyBuilder.Add(jArray[i++].ToString()); + partitionKeyBuilder.Add(jArray[counter].ToString()); continue; } isPkEncrypted = true; - Stream valueStream = EncryptionProcessor.BaseSerializer.ToStream(jArray[i++]); + Stream valueStream = EncryptionProcessor.BaseSerializer.ToStream(jArray[counter]); Stream encryptedPartitionKey = await EncryptionProcessor.EncryptValueStreamAsync( valueStreamToEncrypt: valueStream, diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj index 94e93aa6fe..f7baa75f60 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj @@ -28,11 +28,11 @@ - + - + diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs index 65efd425aa..3489cdf02e 100644 --- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs @@ -189,6 +189,9 @@ public void TestInitialize() { // Reset static cache TTL Microsoft.Data.Encryption.Cryptography.ProtectedDataEncryptionKey.TimeToLive = TimeSpan.FromHours(2); + // flag to disable https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3951 + // need to be removed after the fix + Environment.SetEnvironmentVariable("AZURE_COSMOS_REPLICA_VALIDATION_ENABLED", "False"); } private static async Task CreateClientEncryptionKeyAsync(string cekId, Cosmos.EncryptionKeyWrapMetadata encryptionKeyWrapMetadata) @@ -2303,7 +2306,7 @@ public async Task ValidatePkAndIdEncryptionSupport() VerifyExpectedDocResponse(testDoc, readResponse.Resource); #if ENCRYPTIONTESTPREVIEW - // hierarchical + // hierarchical pk container test cepWithPKIdPath1 = new ClientEncryptionIncludedPath() { Path = "/Sensitive_LongFormat", @@ -2352,9 +2355,320 @@ public async Task ValidatePkAndIdEncryptionSupport() Assert.AreEqual(HttpStatusCode.OK, readResponse.StatusCode); VerifyExpectedDocResponse(testDoc, readResponse.Resource); + + // test to validate query with one partition key (topmost) in hierarchical pk container of 3 keys + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + PartitionKey = new PartitionKeyBuilder().Add(testDoc.Sensitive_StringFormat).Build() + }; + + using FeedIterator setIterator = encryptionContainer.GetItemQueryIterator("select * from c", requestOptions: queryRequestOptions); + + while (setIterator.HasMoreResults) + { + FeedResponse response = await setIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + // test to validate query with one partition key (topmost) in hierarchical pk container of 3 keys with where clause on topmost pk + QueryDefinition queryDefinition = encryptionContainer.CreateQueryDefinition("SELECT * FROM c WHERE c.Sensitive_StringFormat = @Sensitive_StringFormat"); + + await queryDefinition.AddParameterAsync("@Sensitive_StringFormat", testDoc.Sensitive_StringFormat, "/Sensitive_StringFormat"); + + FeedIterator setIteratorWithFilter = encryptionContainer.GetItemQueryIterator(queryDefinition, requestOptions: queryRequestOptions); + + while (setIteratorWithFilter.HasMoreResults) + { + FeedResponse response = await setIteratorWithFilter.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + // test to validate query with one partition key (2nd topmost) in hierarchical pk container of 3 keys with where clause on topmost pk + // this shold give 0 items as PK is set wrongly + queryRequestOptions = new QueryRequestOptions + { + PartitionKey = new PartitionKeyBuilder().Add(testDoc.Sensitive_NestedObjectFormatL1.Sensitive_NestedObjectFormatL2.Sensitive_StringFormatL2).Build() + }; + + setIteratorWithFilter = encryptionContainer.GetItemQueryIterator(queryDefinition, requestOptions: queryRequestOptions); + + while (setIteratorWithFilter.HasMoreResults) + { + FeedResponse response = await setIteratorWithFilter.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual(0, response.Count()); + } #endif } +#if ENCRYPTIONTESTPREVIEW + [TestMethod] + public async Task TestHirarchicalPkWithFullAndPartialKey() + { + HirarchicalPkTestDoc testDoc = HirarchicalPkTestDoc.Create(); + + ClientEncryptionIncludedPath cepWithPKIdPath1 = new ClientEncryptionIncludedPath() + { + Path = "/State", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + ClientEncryptionIncludedPath cepWithPKIdPath2 = new ClientEncryptionIncludedPath() + { + Path = "/City", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + ClientEncryptionIncludedPath cepWithPKIdPath3 = new ClientEncryptionIncludedPath() + { + Path = "/ZipCode", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + Collection paths = new Collection { cepWithPKIdPath1, cepWithPKIdPath2, cepWithPKIdPath3 }; + + ClientEncryptionPolicy clientEncryptionPolicy= new ClientEncryptionPolicy(paths, 2); + + ContainerProperties containerProperties = new ContainerProperties() + { + Id = "HierarchicalPkContainerWith3Pk", + PartitionKeyPaths = new List { "/State", "/City", "/ZipCode" }, + ClientEncryptionPolicy = clientEncryptionPolicy + }; + + Container encryptionContainer = await database.CreateContainerAsync(containerProperties, 400); + await encryptionContainer.InitializeEncryptionAsync(); + + PartitionKey hirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Add(testDoc.City) + .Add(testDoc.ZipCode) + .Build(); + + ItemResponse createResponse = await encryptionContainer.CreateItemAsync( + testDoc, + partitionKey: hirarchicalPk); + Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode); + VerifyExpectedDocResponse(testDoc, createResponse.Resource); + + // read back + ItemResponse readResponse = await encryptionContainer.ReadItemAsync( + testDoc.Id, + hirarchicalPk); + + Assert.AreEqual(HttpStatusCode.OK, readResponse.StatusCode); + VerifyExpectedDocResponse(testDoc, readResponse.Resource); + + PartitionKey partialHirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Add(testDoc.City) + .Build(); + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + PartitionKey = partialHirarchicalPk + }; + + using FeedIterator setIterator = encryptionContainer.GetItemQueryIterator("select * from c", requestOptions: queryRequestOptions); + + while (setIterator.HasMoreResults) + { + FeedResponse response = await setIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + QueryDefinition withEncryptedParameter = encryptionContainer.CreateQueryDefinition( + "SELECT * FROM c WHERE c.City = @cityInput AND c.State = @stateInput"); + + await withEncryptedParameter.AddParameterAsync( + "@cityInput", + testDoc.City, + "/City"); + + await withEncryptedParameter.AddParameterAsync( + "@stateInput", + testDoc.State, + "/State"); + + // query with partial HirarchicalPk state and city + FeedIterator queryResponseIterator; + queryResponseIterator = encryptionContainer.GetItemQueryIterator(withEncryptedParameter, requestOptions: queryRequestOptions); + + while (queryResponseIterator.HasMoreResults) + { + FeedResponse response = await queryResponseIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + partialHirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Build(); + + queryRequestOptions = new QueryRequestOptions + { + PartitionKey = partialHirarchicalPk + }; + + // query with partial HirarchicalPk state + queryResponseIterator = encryptionContainer.GetItemQueryIterator(withEncryptedParameter, requestOptions: queryRequestOptions); + + while (queryResponseIterator.HasMoreResults) + { + FeedResponse response = await queryResponseIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + partialHirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.ZipCode) + .Build(); + + queryRequestOptions = new QueryRequestOptions + { + PartitionKey = partialHirarchicalPk + }; + + // query with partial HirarchicalPk zipCode. + // Since zipCode is 3rd in HirarchicalPk set. Query will get 0 response. + queryResponseIterator = encryptionContainer.GetItemQueryIterator(withEncryptedParameter, requestOptions: queryRequestOptions); + + while (queryResponseIterator.HasMoreResults) + { + FeedResponse response = await queryResponseIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual(0, response.Count()); + } + + // query with no HirarchicalPk set. + queryResponseIterator = encryptionContainer.GetItemQueryIterator(withEncryptedParameter); + + while (queryResponseIterator.HasMoreResults) + { + FeedResponse response = await queryResponseIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + + partialHirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Add(testDoc.City) + .Add(testDoc.ZipCode) + .Add("Extra Value") + .Build(); + + queryRequestOptions = new QueryRequestOptions + { + PartitionKey = partialHirarchicalPk + }; + // query with more PKs greater than number of PK feilds set in the container settings. + try + { + queryResponseIterator = encryptionContainer.GetItemQueryIterator(withEncryptedParameter, requestOptions: queryRequestOptions); + while (queryResponseIterator.HasMoreResults) + { + FeedResponse response = await queryResponseIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + Assert.AreEqual(0, response.Count()); + } + } + catch (Exception ex) + { + Assert.IsTrue(ex is NotSupportedException); + if (ex is NotSupportedException notSupportedException) + Assert.IsTrue(notSupportedException.Message.Contains("The number of partition keys passed in the query exceeds the number of keys initialized on the container")); + } + } + + [TestMethod] + public async Task TestHirarchicalPkWithOnlyOneKey() + { + HirarchicalPkTestDoc testDoc = HirarchicalPkTestDoc.Create(); + + ClientEncryptionIncludedPath cepWithPKIdPath1 = new ClientEncryptionIncludedPath() + { + Path = "/State", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + ClientEncryptionIncludedPath cepWithPKIdPath2 = new ClientEncryptionIncludedPath() + { + Path = "/City", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + ClientEncryptionIncludedPath cepWithPKIdPath3 = new ClientEncryptionIncludedPath() + { + Path = "/ZipCode", + ClientEncryptionKeyId = "key1", + EncryptionType = "Deterministic", + EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", + }; + + Collection paths = new Collection { cepWithPKIdPath1, cepWithPKIdPath2, cepWithPKIdPath3 }; + + ClientEncryptionPolicy clientEncryptionPolicy = new ClientEncryptionPolicy(paths, 2); + + ContainerProperties containerProperties = new ContainerProperties() + { + Id = "HierarchicalPkContainerWithOnePk", + PartitionKeyPaths = new List { "/State" }, + ClientEncryptionPolicy = clientEncryptionPolicy + }; + + Container encryptionContainer = await database.CreateContainerAsync(containerProperties, 400); + await encryptionContainer.InitializeEncryptionAsync(); + + PartitionKey hirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Build(); + + ItemResponse createResponse = await encryptionContainer.CreateItemAsync( + testDoc, + partitionKey: hirarchicalPk); + Assert.AreEqual(HttpStatusCode.Created, createResponse.StatusCode); + VerifyExpectedDocResponse(testDoc, createResponse.Resource); + + // read back + ItemResponse readResponse = await encryptionContainer.ReadItemAsync( + testDoc.Id, + hirarchicalPk); + + Assert.AreEqual(HttpStatusCode.OK, readResponse.StatusCode); + VerifyExpectedDocResponse(testDoc, readResponse.Resource); + + PartitionKey fullHirarchicalPk = new PartitionKeyBuilder() + .Add(testDoc.State) + .Build(); + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + PartitionKey = fullHirarchicalPk + }; + + using FeedIterator setIterator = encryptionContainer.GetItemQueryIterator("select * from c", requestOptions: queryRequestOptions); + + while (setIterator.HasMoreResults) + { + FeedResponse response = await setIterator.ReadNextAsync().ConfigureAwait(false); + Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); + VerifyExpectedDocResponse(testDoc, response.First()); + } + } +#endif [TestMethod] public async Task EncryptionStreamIteratorValidation() { @@ -3204,6 +3518,14 @@ private static async Task> MdeDeleteItemAsync( return deleteResponse; } + private static void VerifyExpectedDocResponse(HirarchicalPkTestDoc expectedDoc, HirarchicalPkTestDoc verifyDoc) + { + Assert.AreEqual(expectedDoc.Id, verifyDoc.Id); + Assert.AreEqual(expectedDoc.State, verifyDoc.State); + Assert.AreEqual(expectedDoc.City, verifyDoc.City); + Assert.AreEqual(expectedDoc.ZipCode, verifyDoc.ZipCode); + } + private static void VerifyExpectedDocResponse(TestDoc expectedDoc, TestDoc verifyDoc) { Assert.AreEqual(expectedDoc.Id, verifyDoc.Id); @@ -3716,6 +4038,70 @@ public Stream ToStream() } } + public class HirarchicalPkTestDoc + { + [JsonProperty("id")] + public string Id { get; set; } + + public string PK { get; set; } + + public string State { get; set; } + + public string City { get; set; } + + public string ZipCode { get; set; } + + public HirarchicalPkTestDoc() + { + } + public HirarchicalPkTestDoc(HirarchicalPkTestDoc other) + { + this.Id = other.Id; + this.PK = other.PK; + this.State = other.State; + this.City = other.City; + this.ZipCode = other.ZipCode; + } + + public override bool Equals(object obj) + { + return obj is HirarchicalPkTestDoc doc + && this.Id == doc.Id + && this.PK == doc.PK + && this.State == doc.State + && this.City == doc.City + && this.ZipCode == doc.ZipCode; + } + + public override int GetHashCode() + { + int hashCode = 1652434776; + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.Id); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.PK); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.State); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.City); + hashCode = (hashCode * -1521134295) + EqualityComparer.Default.GetHashCode(this.ZipCode); + return hashCode; + } + + public static HirarchicalPkTestDoc Create(string partitionKey = null) + { + return new HirarchicalPkTestDoc() + { + Id = Guid.NewGuid().ToString(), + PK = partitionKey ?? Guid.NewGuid().ToString(), + State = Guid.NewGuid().ToString(), + City = Guid.NewGuid().ToString(), + ZipCode = Guid.NewGuid().ToString() + }; + } + + public Stream ToStream() + { + return TestCommon.ToStream(this); + } + } + internal class TestKeyEncryptionKey : IKeyEncryptionKey { private static readonly Dictionary keyinfo = new Dictionary From ebd1b91a26547721ef232ef597d878144889b80b Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 1 Aug 2023 08:28:49 -0700 Subject: [PATCH 166/337] Query: Refactors changelog.md with Optimistic Direct Execution recommendation (#4004) * Update changelog.md This is a recommendation for customers if they would like to use the ODE features. * Updated release notes for ODE --- changelog.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog.md b/changelog.md index ab733a4137..a6f9e65864 100644 --- a/changelog.md +++ b/changelog.md @@ -44,6 +44,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [3836](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3836) Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions - [3909](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3909) Query: Adds EnableOptimisticDirectExecution in QueryRequestOptions enabled by default +Recommendation for customers regarding Optimistic Direct Execution: + +Starting Version 3.35.0, the Preview SDK enables the ODE feature by default. This can potentially cause a new type of continuation token to be generated. Such a token is not recognized by the older SDKs by design and this could result in a Malformed Continuation Token Exception. +If you have a scenario where tokens generated from the newer SDKs are used by an older SDK, we recommend a 2 step approach to upgrade: + +- Upgrade to the new SDK and disable ODE, both together as part of a single deployment. Wait for all nodes to upgrade. + - In order to disable ODE, set EnableOptimisticDirectExecution to false in the QueryRequestOptions. +- Enable ODE as part of second deployment for all nodes. + ### [3.35.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.0) - 2023-06-19 #### Fixed From 8c4f99f35e326b61ecca210988334d00629b6ee7 Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Sat, 5 Aug 2023 13:01:59 -0700 Subject: [PATCH 167/337] [Internal] Query: Adds performance testing for OptimisticDirectExecution pipeline (#3839) * Infrastructure for performance testing with ODE pipeline. * Resolve comments * Removed randomization from data creation process * Fixed comments * Removed Query and EnableODE from QueryStatisticsMetrics, as they do not relate to query statistics. * Removed try catch to make CreateItemAsync call always succeed * Removed one liner functions * Removed code from MetricsSerializer and QueryStatisticsDatumVisitor files * Fixed comments * Removed request Charge check * Bug in Debug Assert * Test * Bug in debug assert fix * Fixed second bug in Metrics Accumalator class * Added ignore flag to ode perf tests so that they do not run on every loop build * Added comment explaining the Ignore flag. --- .../ContentSerializationPerformanceTests.cs | 18 +- .../QueryPerfTest/MetricsAccumulator.cs | 8 +- ...timisticDirectExecutionPerformanceTests.cs | 469 ++++++++++++++++++ .../QueryPerfTest/QueryStatisticsMetrics.cs | 6 + .../settings.json | 18 +- 5 files changed, 496 insertions(+), 23 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/OptimisticDirectExecutionPerformanceTests.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs index 759e63b345..8ff5660c6f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/ContentSerializationPerformanceTests.cs @@ -33,15 +33,15 @@ public ContentSerializationPerformanceTests() this.queryStatisticsDatumVisitor = new(); this.endpoint = Utils.ConfigurationManager.AppSettings["GatewayEndpoint"]; this.authKey = Utils.ConfigurationManager.AppSettings["MasterKey"]; - this.cosmosDatabaseId = Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.CosmosDatabaseId"]; - this.containerId = Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.ContainerId"]; - this.contentSerialization = Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.ContentSerialization"]; - this.query = Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.Query"]; - this.numberOfIterations = int.Parse(Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.NumberOfIterations"]); - this.warmupIterations = int.Parse(Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.WarmupIterations"]); - this.MaxConcurrency = int.Parse(Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.MaxConcurrency"]); - this.MaxItemCount = int.Parse(Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.MaxItemCount"]); - this.useStronglyTypedIterator = bool.Parse(Utils.ConfigurationManager.AppSettings["ContentSerializationPerformanceTests.UseStronglyTypedIterator"]); + this.cosmosDatabaseId = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.CosmosDatabaseId"]; + this.containerId = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.ContainerId"]; + this.contentSerialization = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.ContentSerialization"]; + this.query = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.Query"]; + this.numberOfIterations = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.NumberOfIterations"]); + this.warmupIterations = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.WarmupIterations"]); + this.MaxConcurrency = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.MaxConcurrency"]); + this.MaxItemCount = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.MaxItemCount"]); + this.useStronglyTypedIterator = bool.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.UseStronglyTypedIterator"]); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/MetricsAccumulator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/MetricsAccumulator.cs index 56fc16b683..a7e6032001 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/MetricsAccumulator.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/MetricsAccumulator.cs @@ -53,18 +53,16 @@ public void ReadFromTrace(FeedResponse Response, QueryStatisticsDatumVisit { if (storeResponse.StoreResult.StatusCode == StatusCodes.Ok) { - backendAndClientMetrics.Add(Tuple.Create(retrieveCosmosElementTraces[k], backendMetrics[j], transitMetrics[i])); + backendAndClientMetrics.Add(Tuple.Create(retrieveCosmosElementTraces[k], backendMetrics[j], node)); j++; k++; } else { //We add null values to the tuple since status codes other than Ok will not have data for 'Query Metrics' and 'Get Cosmos Element Response' - backendAndClientMetrics.Add(Tuple.Create(null, null, transitMetrics[i])); + backendAndClientMetrics.Add(Tuple.Create(null, null, node)); } } - - i++; } Debug.Assert(i == transitMetrics.Count, "All 'transit metrics' must be grouped."); @@ -76,7 +74,7 @@ public void ReadFromTrace(FeedResponse Response, QueryStatisticsDatumVisit { if (metrics.Item2 != null) { - Debug.Assert(metrics.Item1 == null, "'Get Cosmos Element Response' is null"); + Debug.Assert(metrics.Item1 != null, "'Get Cosmos Element Response' is null"); queryStatisticsDatumVisitor.AddGetCosmosElementResponseTime(metrics.Item1.Duration.TotalMilliseconds); foreach (KeyValuePair kvp in metrics.Item2.Data) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/OptimisticDirectExecutionPerformanceTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/OptimisticDirectExecutionPerformanceTests.cs new file mode 100644 index 0000000000..756357e611 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/OptimisticDirectExecutionPerformanceTests.cs @@ -0,0 +1,469 @@ +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class OptimisticDirectExecutionPerformanceTests + { + private Container Container; + private const string RawDataFileName = "OptimisticDirectExecutionPerformanceTestsRawData.csv"; + private const string AggregateDataFileName = "OptimisticDirectExecutionPerformanceTestsAggregatedData.csv"; + private const string PrintQueryMetrics = "QueryMetrics"; + private static readonly string RawDataPath = Path.GetFullPath(RawDataFileName); + private static readonly string AggregateDataPath = Path.GetFullPath(AggregateDataFileName); + private static readonly string Endpoint = Utils.ConfigurationManager.AppSettings["GatewayEndpoint"]; + private static readonly string AuthKey = Utils.ConfigurationManager.AppSettings["MasterKey"]; + private static readonly string CosmosDatabaseId = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.CosmosDatabaseId"]; + private static readonly string ContainerId = Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.ContainerId"]; + private static readonly PartitionKey PartitionKeyValue = new PartitionKey("Andersen"); + private static readonly int NumberOfIterations = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.NumberOfIterations"]); + private static readonly int WarmupIterations = int.Parse(Utils.ConfigurationManager.AppSettings["QueryPerformanceTests.WarmupIterations"]); + + [TestInitialize] + public async Task InitializeTest() + { + CosmosClientOptions clientOptions = new CosmosClientOptions() + { + ConnectionMode = ConnectionMode.Direct, + }; + + CosmosClient cosmosClient = new CosmosClient(Endpoint, AuthKey, clientOptions); + Database database = await cosmosClient.CreateDatabaseAsync(CosmosDatabaseId); + this.Container = await database.CreateContainerAsync(ContainerId, partitionKeyPath: "/name"); + await this.AddItemsToContainerAsync(this.Container); + + if (File.Exists(RawDataPath)) + { + File.Delete(RawDataPath); + } + + if (File.Exists(AggregateDataPath)) + { + File.Delete(AggregateDataPath); + } + } + + [TestCleanup] + public async Task CleanupAsync() + { + if (this.Container != null) + { + await this.Container.Database.DeleteAsync(); + this.Container = null; + } + } + + private async Task AddItemsToContainerAsync(Container container) + { + int totalItems = 5000; + string[] cityOptions = new string[] { "Seattle", "Chicago", "NYC", "SF" }; + int numberOfRecipeints = cityOptions.Length; + List recipientList = new List(numberOfRecipeints); + + for (int j = 0; j < numberOfRecipeints; j++) + { + RecipientList recipient = new RecipientList() + { + Name = "John", + City = cityOptions[j], + }; + + recipientList.Add(recipient); + } + + // Create a family object for the Andersen family + foreach (int i in Enumerable.Range(0, totalItems)) + { + States andersenFamily = new States + { + Id = i.ToString(), + Name = i < (totalItems/2) ? "Andersen" : "Smith", + City = cityOptions[i%cityOptions.Length], + PostalCode = (i * 10).ToString(), + Region = "Northwest", + UserDefinedID = i % 10, + RecipientList = recipientList + }; + + ItemResponse andersenFamilyResponse = await container.CreateItemAsync(andersenFamily, new PartitionKey(andersenFamily.Name)); + Console.WriteLine("Created item in database with id: {0} Operation consumed {1} RUs.\n", andersenFamilyResponse.Resource.Id, andersenFamilyResponse.RequestCharge); + } + } + + //Set Ode perf tests to ignore so that they dont run on every loop build. + //Ignore flag can be removed when checking for Ode performance. + [Ignore] + [TestMethod] + [Owner("akotalwar")] + public async Task RunAsync() + { + string highPrepTimeSumQuery = CreateHighPrepTimeSumQuery(); + string highPrepTimeConditionalQuery = CreateHighPrepTimeConditionalQuery(); + List> globalCustomOdeStatisticsList = new List>(); + + List odeTestCases = new List() + { + //Simple Query + CreateInput("SELECT * FROM c", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT * FROM c", PartitionKeyValue, true, -1, 2500), + + //TOP + CreateInput("SELECT TOP 1000 c.id FROM c", PartitionKeyValue, false, -1, 1000), + CreateInput("SELECT TOP 1000 c.id FROM c", PartitionKeyValue, true, -1, 1000), + + //Filter + CreateInput("SELECT c.id FROM c WHERE c.city IN ('Seattle', 'NYC')", PartitionKeyValue, false, -1, 1250), + CreateInput("SELECT c.id FROM c WHERE c.city IN ('Seattle', 'NYC')", PartitionKeyValue, true, -1, 1250), + + //DISTINCT + Filter + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId BETWEEN 0 AND 5 OFFSET 1 LIMIT 3", PartitionKeyValue, false, -1, 3), + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId BETWEEN 0 AND 5 OFFSET 1 LIMIT 3", PartitionKeyValue, true, -1, 3), + + CreateInput("SELECT DISTINCT c.city FROM c WHERE STARTSWITH(c.city, 'S')", PartitionKeyValue, false, -1, 2), + CreateInput("SELECT DISTINCT c.city FROM c WHERE STARTSWITH(c.city, 'S')", PartitionKeyValue, true, -1, 2), + + //JOIN + CreateInput("SELECT root.id " + + "FROM root " + + "JOIN root.id a " + + "JOIN root.id b " + + "JOIN root.id c " + + "WHERE root.id = '1' OR a.id in (1,2,3,4,5,6,7,8,9,10) " + + "OR b.id in (1,2,3,4,5,6,7,8,9,10) " + + "OR c.id in (1,2,3,4,5,6,7,8,9,10)", PartitionKeyValue, false, -1, 1), + CreateInput("SELECT root.id " + + "FROM root " + + "JOIN root.id a " + + "JOIN root.id b " + + "JOIN root.id c " + + "WHERE root.id = '1' OR a.id in (1,2,3,4,5,6,7,8,9,10) " + + "OR b.id in (1,2,3,4,5,6,7,8,9,10) " + + "OR c.id in (1,2,3,4,5,6,7,8,9,10)", PartitionKeyValue, true, -1, 1), + + //High Prep Time + CreateInput(highPrepTimeSumQuery, PartitionKeyValue, false, -1, 2500), + CreateInput(highPrepTimeSumQuery, PartitionKeyValue, true, -1, 2500), + + CreateInput(highPrepTimeConditionalQuery, PartitionKeyValue, false, -1, 1750), + CreateInput(highPrepTimeConditionalQuery, PartitionKeyValue, true, -1, 1750), + + //Order By + CreateInput("SELECT * FROM c ORDER BY c.userDefinedId DESC", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT * FROM c ORDER BY c.userDefinedId DESC", PartitionKeyValue, true, -1, 2500), + + CreateInput("SELECT c.id FROM c ORDER BY c.postalcode DESC", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT c.id FROM c ORDER BY c.postalcode DESC", PartitionKeyValue, true, -1, 2500), + + //Order By + TOP + CreateInput("SELECT TOP 5 c.id FROM c ORDER BY c.userDefinedId", PartitionKeyValue, false, -1, 5), + CreateInput("SELECT TOP 5 c.id FROM c ORDER BY c.userDefinedId", PartitionKeyValue, true, -1, 5), + + //Order By + DISTINCT + CreateInput("SELECT DISTINCT c.id FROM c ORDER BY c.city DESC", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT DISTINCT c.id FROM c ORDER BY c.city DESC", PartitionKeyValue, true, -1, 2500), + + //Order By + DISTINCT + Filter + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId > 5 ORDER BY c.userDefinedId", PartitionKeyValue, false, -1, 4), + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId > 5 ORDER BY c.userDefinedId", PartitionKeyValue, true, -1, 4), + + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId BETWEEN 0 AND 5 ORDER BY c.id DESC", PartitionKeyValue, false, -1, 6), + CreateInput("SELECT DISTINCT c.userDefinedId FROM c WHERE c.userDefinedId BETWEEN 0 AND 5 ORDER BY c.id DESC", PartitionKeyValue, true, -1, 6), + + //Group By + CreateInput("SELECT c.postalcode FROM c GROUP BY c.postalcode", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT c.postalcode FROM c GROUP BY c.postalcode", PartitionKeyValue, true, -1, 2500), + + CreateInput("SELECT Count(1) AS count, Sum(ARRAY_LENGTH(c.recipientList)) AS sum FROM c WHERE c.city IN ('Seattle', 'SF') GROUP BY c.city", PartitionKeyValue, false, -1, 2), + CreateInput("SELECT Count(1) AS count, Sum(ARRAY_LENGTH(c.recipientList)) AS sum FROM c WHERE c.city IN ('Seattle', 'SF') GROUP BY c.city", PartitionKeyValue, true, -1, 2), + + CreateInput("SELECT c.city, AVG(ARRAY_LENGTH(c.recipientList)) FROM c GROUP BY c.city", PartitionKeyValue, false, -1, 4), + CreateInput("SELECT c.city, AVG(ARRAY_LENGTH(c.recipientList)) FROM c GROUP BY c.city", PartitionKeyValue, true, -1, 4), + + //Group By + OFFSET + CreateInput("SELECT c.id FROM c GROUP BY c.id OFFSET 5 LIMIT 3", PartitionKeyValue, false, -1, 3), + CreateInput("SELECT c.id FROM c GROUP BY c.id OFFSET 5 LIMIT 3", PartitionKeyValue, true, -1, 3), + + //Group By + TOP + CreateInput("SELECT TOP 25 c.id FROM c GROUP BY c.id", PartitionKeyValue, false, -1, 25), + CreateInput("SELECT TOP 25 c.id FROM c GROUP BY c.id", PartitionKeyValue, true, -1, 25), + + //Group By + DISTINCT + CreateInput("SELECT DISTINCT c.id FROM c GROUP BY c.id", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT DISTINCT c.id FROM c GROUP BY c.id", PartitionKeyValue, true, -1, 2500), + + CreateInput("SELECT DISTINCT c.postalcode FROM c GROUP BY c.postalcode", PartitionKeyValue, false, -1, 2500), + CreateInput("SELECT DISTINCT c.postalcode FROM c GROUP BY c.postalcode", PartitionKeyValue, true, -1, 2500), + }; + + foreach (DirectExecutionTestCase testCase in odeTestCases) + { + globalCustomOdeStatisticsList.AddRange(await this.RunQueryAsync(testCase)); + } + + using (StreamWriter writer = new StreamWriter(new FileStream(RawDataPath, FileMode.Append, FileAccess.Write))) + { + SerializeODEQueryMetrics(writer, globalCustomOdeStatisticsList, NumberOfIterations, rawData: true); + } + + using (StreamWriter writer = new StreamWriter(new FileStream(AggregateDataPath, FileMode.Append, FileAccess.Write))) + { + SerializeODEQueryMetrics(writer, globalCustomOdeStatisticsList, NumberOfIterations, rawData: false); + } + } + + private async Task>> RunQueryAsync(DirectExecutionTestCase queryInput) + { + List> odeQueryStatisticsList = new List>(); + QueryRequestOptions requestOptions = new QueryRequestOptions() + { + MaxItemCount = queryInput.PageSizeOption, + EnableOptimisticDirectExecution = queryInput.EnableOptimisticDirectExecution, + PartitionKey = queryInput.PartitionKey, + }; + + for (int i = 0; i < NumberOfIterations + WarmupIterations; i++) + { + bool isWarmUpIteration = i < WarmupIterations; + using (FeedIterator iterator = this.Container.GetItemQueryIterator( + queryText: queryInput.Query, + requestOptions: requestOptions)) + { + if (isWarmUpIteration) + { + while (iterator.HasMoreResults) + { + await iterator.ReadNextAsync(); + } + } + else + { + odeQueryStatisticsList.Add(await this.GetIteratorStatistics(iterator, queryInput)); + } + } + } + + return odeQueryStatisticsList; + } + + private async Task> GetIteratorStatistics(FeedIterator feedIterator, DirectExecutionTestCase queryInput) + { + MetricsAccumulator metricsAccumulator = new MetricsAccumulator(); + Guid correlatedActivityId = Guid.NewGuid(); + FeedResponse response; + int totalDocumentCount = 0; + string query; + bool enableOde; + List odeQueryStatisticsList = new List(); + + while (feedIterator.HasMoreResults) + { + QueryStatisticsDatumVisitor queryStatisticsDatumVisitor = new QueryStatisticsDatumVisitor(); + System.Diagnostics.Stopwatch totalTime = new System.Diagnostics.Stopwatch(); + System.Diagnostics.Stopwatch traceTime = new System.Diagnostics.Stopwatch(); + + totalTime.Start(); + response = await feedIterator.ReadNextAsync(); + traceTime.Start(); + if (response.RequestCharge != 0) + { + metricsAccumulator.ReadFromTrace(response, queryStatisticsDatumVisitor); + } + + traceTime.Stop(); + totalTime.Stop(); + + query = queryInput.Query; + enableOde = queryInput.EnableOptimisticDirectExecution; + queryStatisticsDatumVisitor.AddEndToEndTime(totalTime.ElapsedMilliseconds - traceTime.ElapsedMilliseconds); + queryStatisticsDatumVisitor.PopulateMetrics(); + + QueryStatisticsMetrics queryStatistics = queryStatisticsDatumVisitor.QueryMetricsList[0]; + queryStatistics.RUCharge = response.RequestCharge; + queryStatistics.CorrelatedActivityId = correlatedActivityId; + + // Each roundtrip is a new item in the list + odeQueryStatisticsList.Add(new OdeQueryStatistics + { + Query = query, + EnableOde = enableOde, + QueryStatisticsMetrics = queryStatistics + }); + + totalDocumentCount += response.Count; + } + + Assert.AreEqual(queryInput.ExpectedResultCount, totalDocumentCount); + + return odeQueryStatisticsList; + } + + private static string CreateHighPrepTimeSumQuery() + { + int exprCount = 9999; + StringBuilder sb = new StringBuilder(); + sb.Append("SELECT r.id FROM root r WHERE "); + for (int i = 0; i < exprCount; i++) + { + sb.Append(i == 0 ? "1" : "+1"); + } + + return sb.Append(" = " + exprCount + " ORDER BY r.id ASC").ToString(); + } + + private static string CreateHighPrepTimeConditionalQuery() + { + int exprCount = 999; + StringBuilder sb = new StringBuilder(); + string[] cityOptions = new string[] { "Seattle", "Chicago", "NYC", "SF" }; + + sb.Append("SELECT * FROM root r WHERE "); + for (int nIdx = 0; nIdx < exprCount; nIdx++) + { + if (nIdx > 0) + { + sb.Append(" OR "); + } + + sb.Append($"r.userDefinedId > {nIdx} AND r.city = '{cityOptions[nIdx % cityOptions.Length]}'"); + } + + return sb.ToString(); + } + + private static void SerializeODEQueryMetrics(TextWriter textWriter, List> customOdeStatisticsList, int numberOfIterations, bool rawData) + { + if (rawData) + { + SerializeODERawDataQueryMetrics(textWriter, customOdeStatisticsList); + } + else + { + SerializeODEProcessedDataQueryMetrics(textWriter, customOdeStatisticsList, numberOfIterations); + } + } + + private static void SerializeODERawDataQueryMetrics(TextWriter textWriter, List> globalOdeQueryStatisticsList) + { + textWriter.WriteLine(); + textWriter.WriteLine(PrintQueryMetrics); + textWriter.Write("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\"", "Query", "ODE", "RUCharge", "BackendTime", "TransitTime", "ClientTime", "EndToEndTime"); + textWriter.WriteLine(); + + foreach (List queryStatisticsList in globalOdeQueryStatisticsList) + { + double totalClientTime = 0; + double totalBackendTime = 0; + double totalEndToEndTime = 0; + double totalTransitTime = 0; + double totalRU = 0; + string query = ""; + bool ode = false; + + foreach (OdeQueryStatistics queryStatistics in queryStatisticsList) + { + QueryStatisticsMetrics metrics = queryStatistics.QueryStatisticsMetrics; + double transitTime = metrics.Created + metrics.ChannelAcquisitionStarted + metrics.Pipelined + metrics.Received + metrics.Completed; + double backendTime = metrics.TotalQueryExecutionTime; + + totalClientTime += metrics.EndToEndTime - (backendTime + transitTime); + totalBackendTime += backendTime; + totalEndToEndTime += metrics.EndToEndTime; + totalTransitTime += transitTime; + totalRU += metrics.RUCharge; + query = queryStatistics.Query; + ode = queryStatistics.EnableOde; + } + + textWriter.WriteLine($"{query},{ode},{totalRU},{totalBackendTime},{totalTransitTime},{totalClientTime},{totalEndToEndTime}"); + } + } + + private static void SerializeODEProcessedDataQueryMetrics(TextWriter textWriter, List> globalOdeQueryStatisticsList, int numberOfIterations) + { + textWriter.WriteLine(); + textWriter.WriteLine(PrintQueryMetrics); + textWriter.Write("\"{0}\",\"{1}\",\"{2}\",\"{3}\"", "Query", "ODE", "RUCharge", "EndToEndTime"); + textWriter.WriteLine(); + + string prevQuery = globalOdeQueryStatisticsList[0][0].Query; + bool prevOde = globalOdeQueryStatisticsList[0][0].EnableOde; + double totalEndToEndTime = 0; + double totalRU = 0; + + foreach (List odeQueryStatisticsList in globalOdeQueryStatisticsList) + { + if (odeQueryStatisticsList[0].Query == prevQuery && odeQueryStatisticsList[0].EnableOde == prevOde) + { + foreach (OdeQueryStatistics odeQueryStatistics in odeQueryStatisticsList) + { + QueryStatisticsMetrics metrics = odeQueryStatistics.QueryStatisticsMetrics; + totalEndToEndTime += metrics.EndToEndTime; + totalRU += metrics.RUCharge; + } + } + else + { + textWriter.WriteLine($"{prevQuery},{prevOde},{totalRU / numberOfIterations},{totalEndToEndTime / numberOfIterations}"); + + foreach (OdeQueryStatistics odeQueryStatistics in odeQueryStatisticsList) + { + QueryStatisticsMetrics metrics = odeQueryStatistics.QueryStatisticsMetrics; + totalEndToEndTime = metrics.EndToEndTime; + totalRU = metrics.RUCharge; + prevQuery = odeQueryStatistics.Query; + prevOde = odeQueryStatistics.EnableOde; + } + } + } + + textWriter.WriteLine($"{prevQuery},{prevOde},{totalRU / numberOfIterations},{totalEndToEndTime / numberOfIterations}"); + } + + private class OdeQueryStatistics + { + public string Query { get; set; } + public bool EnableOde { get; set; } + public QueryStatisticsMetrics QueryStatisticsMetrics { get; set; } + } + + private static DirectExecutionTestCase CreateInput( + string query, + PartitionKey? partitionKey, + bool enableOptimisticDirectExecution, + int pageSizeOption, + int expectedResultCount) + { + return new DirectExecutionTestCase(query, partitionKey, enableOptimisticDirectExecution, pageSizeOption, expectedResultCount); + } + + private readonly struct DirectExecutionTestCase + { + public string Query { get; } + public PartitionKey? PartitionKey { get; } + public bool EnableOptimisticDirectExecution { get; } + public int PageSizeOption { get; } + public int ExpectedResultCount { get; } + + public DirectExecutionTestCase( + string query, + PartitionKey? partitionKey, + bool enableOptimisticDirectExecution, + int pageSizeOption, + int expectedResultCount) + { + this.Query = query; + this.PartitionKey = partitionKey; + this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; + this.PageSizeOption = pageSizeOption; + this.ExpectedResultCount = expectedResultCount; + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsMetrics.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsMetrics.cs index 70ed146f4c..d72193fc43 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsMetrics.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsMetrics.cs @@ -1,7 +1,11 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { + using System; + internal class QueryStatisticsMetrics { + public Guid CorrelatedActivityId { get; set; } + public double EndToEndTime { get; set; } public double PocoTime { get; set; } @@ -32,6 +36,8 @@ internal class QueryStatisticsMetrics public double Received { get; set; } + public double RUCharge { get; set; } + public double Completed { get; set; } public double BadRequestCreated { get; set; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json index 51ecc8a707..611ba8c677 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/settings.json @@ -11,14 +11,14 @@ "MasterKey": "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", "ServerStalenessIntervalInSeconds": "5", "MasterStalenessIntervalInSeconds": "1", - "ContentSerializationPerformanceTests.CosmosDatabaseId": "db", - "ContentSerializationPerformanceTests.ContainerId": "container", - "ContentSerializationPerformanceTests.ContentSerialization": "JsonText", - "ContentSerializationPerformanceTests.Query": "SELECT TOP 1 c.region FROM c", - "ContentSerializationPerformanceTests.MaxConcurrency": "-1", - "ContentSerializationPerformanceTests.MaxItemCount": "-1", - "ContentSerializationPerformanceTests.NumberOfIterations": "1", - "ContentSerializationPerformanceTests.WarmupIterations": "0", - "ContentSerializationPerformanceTests.UseStronglyTypedIterator": "true" + "QueryPerformanceTests.CosmosDatabaseId": "db", + "QueryPerformanceTests.ContainerId": "container", + "QueryPerformanceTests.ContentSerialization": "JsonText", + "QueryPerformanceTests.Query": "SELECT TOP 1 c.region FROM c", + "QueryPerformanceTests.MaxConcurrency": "-1", + "QueryPerformanceTests.MaxItemCount": "-1", + "QueryPerformanceTests.NumberOfIterations": "1", + "QueryPerformanceTests.WarmupIterations": "0", + "QueryPerformanceTests.UseStronglyTypedIterator": "true" } } \ No newline at end of file From c46614b9311365f203d489394cf475e212ca202f Mon Sep 17 00:00:00 2001 From: akotalwar <94020786+akotalwar@users.noreply.github.com> Date: Sat, 5 Aug 2023 13:44:45 -0700 Subject: [PATCH 168/337] Query: Adds ODE continuation token support for non-ODE pipelines (#4009) * Added code to throw exception if ODE continuation token goes into non ODE pipeline * Removed count variable * Updated test name * Removed ODE continuation token logic from caller class * Simplified code * Fixed comments * Updated continuation token cast * Removed const string for continuation token * Added Ignore flag for test * Added baseline test * Updated baseline test --- .../CosmosQueryExecutionContextFactory.cs | 12 ++++- ...imisticDirectExecutionContinuationToken.cs | 16 +++--- .../CosmosBasicQueryTests.cs | 53 ++++++++++++++++++- ...misticDirectExecutionQueryBaselineTests.cs | 44 +++++++++++++++ 4 files changed, 117 insertions(+), 8 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 47aa1c4490..43ebf6a2d8 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -752,7 +752,17 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ContainerQueryProperties containerQueryProperties, ITrace trace) { - if (!inputParameters.EnableOptimisticDirectExecution) return null; + if (!inputParameters.EnableOptimisticDirectExecution) + { + if (inputParameters.InitialUserContinuationToken != null + && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) + { + throw new MalformedContinuationTokenException($"The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. " + + $"{inputParameters.InitialUserContinuationToken}"); + } + + return null; + } Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs index 59f87295f3..76b2531f01 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionContinuationToken.cs @@ -4,9 +4,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery { - using System; using System.Collections.Generic; - using Microsoft.Azure.Cosmos.ChangeFeed; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; using Microsoft.Azure.Cosmos.Query.Core.Monads; @@ -30,6 +28,12 @@ public OptimisticDirectExecutionContinuationToken(ParallelContinuationToken toke public Range Range => this.Token.Range; + public static bool IsOptimisticDirectExecutionContinuationToken(CosmosElement continuationToken) + { + CosmosObject cosmosObjectContinuationToken = continuationToken as CosmosObject; + return !(cosmosObjectContinuationToken == null || !cosmosObjectContinuationToken.ContainsKey(OptimisticDirectExecutionToken)); + } + public static CosmosElement ToCosmosElement(OptimisticDirectExecutionContinuationToken continuationToken) { CosmosElement inner = ParallelContinuationToken.ToCosmosElement(continuationToken.Token); @@ -42,14 +46,14 @@ public static CosmosElement ToCosmosElement(OptimisticDirectExecutionContinuatio public static TryCatch TryCreateFromCosmosElement(CosmosElement cosmosElement) { - CosmosObject cosmosObjectContinuationToken = cosmosElement as CosmosObject; - if (cosmosObjectContinuationToken == null || !cosmosObjectContinuationToken.ContainsKey(OptimisticDirectExecutionToken)) + if (!IsOptimisticDirectExecutionContinuationToken(cosmosElement)) { return TryCatch.FromException( - new MalformedContinuationTokenException( - message: $"Malformed Continuation Token: Expected OptimisticDirectExecutionToken\r\n")); + new MalformedContinuationTokenException( + message: $"Malformed Continuation Token: Expected OptimisticDirectExecutionToken\r\n")); } + CosmosObject cosmosObjectContinuationToken = (CosmosObject)cosmosElement; TryCatch inner = ParallelContinuationToken.TryCreateFromCosmosElement(cosmosObjectContinuationToken[OptimisticDirectExecutionToken]); return inner.Succeeded ? diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs index 25ac9a705f..bfd6366104 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs @@ -15,7 +15,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Cosmos.Scripts; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Cosmos.Linq; - using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents.Collections; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -786,6 +785,58 @@ public async Task QueryActivityIdWithContinuationTokenAndTraceTest() } + //TODO: Remove Ignore flag once emulator is updated to 0415 + [Ignore] + [TestMethod] + public async Task TesOdeTokenCompatibilityWithNonOdePipeline() + { + string query = "select top 200 * from c"; + CosmosClient client = DirectCosmosClient; + Container container = client.GetContainer(DatabaseId, ContainerId); + + // Create items + for (int i = 0; i < 500; i++) + { + await container.CreateItemAsync(ToDoActivity.CreateRandomToDoActivity()); + } + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions + { + MaxItemCount = 50, + EnableOptimisticDirectExecution = true + }; + + FeedIteratorInternal feedIterator = + (FeedIteratorInternal)container.GetItemQueryStreamIterator( + query, + null, + queryRequestOptions); + + ResponseMessage responseMessage = await feedIterator.ReadNextAsync(CancellationToken.None); + string continuationToken = responseMessage.ContinuationToken; + + QueryRequestOptions newQueryRequestOptions = new QueryRequestOptions + { + MaxItemCount = 50, + EnableOptimisticDirectExecution = false + }; + + // use Continuation Token to create new iterator and use same trace + FeedIterator feedIteratorNew = + container.GetItemQueryStreamIterator( + query, + continuationToken, + newQueryRequestOptions); + + while (feedIteratorNew.HasMoreResults) + { + responseMessage = await feedIteratorNew.ReadNextAsync(CancellationToken.None); + } + + string expectedErrorMessage = "The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. "; + Assert.IsTrue(responseMessage.CosmosException.ToString().Contains(expectedErrorMessage)); + } + private class CustomHandler : RequestHandler { string correlatedActivityId; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 81c765adc4..5c0e66f1a6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -19,6 +19,7 @@ using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; @@ -190,6 +191,49 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() Assert.AreEqual(100, documentCountInSinglePartition); } + [TestMethod] + public async Task TestOdeTokenWithSpecializedPipeline() + { + int numItems = 100; + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: Guid.NewGuid().ToString(), + range: new Documents.Routing.Range("A", "B", true, false)); + + OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); + CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); + + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT VALUE COUNT(1) FROM c", + expectedOptimisticDirectExecution: false, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: cosmosElementContinuationToken); + + DocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems, multiPartition: false); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: input.ExpectedOptimisticDirectExecution); + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); + + string expectedErrorMessage = "The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. "; + + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + { + if (queryPipelineStage.Current.Failed) + { + Assert.IsTrue(queryPipelineStage.Current.InnerMostException.ToString().Contains(expectedErrorMessage)); + return; + } + + Assert.IsFalse(true); + break; + } + } + [TestMethod] public async Task TestQueriesWhichNeverRequireDistribution() { From e05e3eb23c4afd241dc24f3a8872f3ab5b9f431f Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:39:37 -0700 Subject: [PATCH 169/337] Code changes to disable replica validation in preview package. (#4019) --- Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 216e1295b5..748f81833a 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -38,9 +38,7 @@ public static bool IsReplicaAddressValidationEnabled( ConnectionPolicy connectionPolicy) { bool replicaValidationDefaultValue = false; -#if PREVIEW - replicaValidationDefaultValue = true; -#endif + if (connectionPolicy != null && connectionPolicy.EnableAdvancedReplicaSelectionForTcp.HasValue) { From 27b935072764a901b3eed4b038aff7956f2d297e Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Tue, 8 Aug 2023 21:08:02 -0700 Subject: [PATCH 170/337] 3.35.3: Adds new SDK versions and contract files (#4024) * Updated change log and bumped up the patch version. * Code changes to update the change log message. --- Directory.Build.props | 4 +- .../contracts/API_3.35.3-preview.txt | 1563 +++++++++++++++++ .../contracts/API_3.35.3.txt | 1502 ++++++++++++++++ changelog.md | 9 + 4 files changed, 3076 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.3-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.3.txt diff --git a/Directory.Build.props b/Directory.Build.props index 9daa1e7e9f..d3ceab0046 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.35.2 - 3.35.2 + 3.35.3 + 3.35.3 preview 3.31.3 2.0.3 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.3-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.3-preview.txt new file mode 100644 index 0000000000..6c989053fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.3-preview.txt @@ -0,0 +1,1563 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.3.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.3.txt new file mode 100644 index 0000000000..c0dc3e280f --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.3.txt @@ -0,0 +1,1502 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index a6f9e65864..f7a46f39a3 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,15 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.35.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3-preview) - 2023-08-09 +### [3.35.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3) - 2023-08-09 + +#### Fixed +- [3979](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3979) Client Encryption: Adds fix for supporting Prefix Partition Key (Hierarchical partitioning) + +#### Added +- [4019](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4019) Upgrade Resiliency: Disables Replica Validation Feature By Default in Preview (The feature was previously enabled by default in the [`3.35.2-preview`](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.2-preview) release) + ### [3.35.2-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.2-preview) - 2023-07-17 #### Fixed From f8f38017f091bf9691db52724f153e3f338d72d5 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 10 Aug 2023 03:05:06 +0530 Subject: [PATCH 171/337] [Internal] Distributed tracing: Adds a sample to collect activities and events using custom listener (#4021) * custom listener example * removed unwanted code * add comments * fix appsettings * revert changes --- .../Usage/Cosmos.Samples.Usage.sln | 8 +- .../CustomDiagnosticAndEventListener.cs | 167 ++++++++++++++++++ .../CustomDiagnosticAndEventListener.csproj | 20 +++ .../Program.cs | 90 ++++++++++ 4 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln index 999b48d928..5e23b5c075 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Cosmos.Samples.Usage.sln @@ -53,7 +53,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CFPullModelLatestVersionMod EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry", "OpenTelemetry\OpenTelemetry.csproj", "{C6EF6948-C085-4013-A21F-99303ECBA7A9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApplicationInsights", "ApplicationInsights\ApplicationInsights.csproj", "{55149A3C-A263-4EE5-AD2D-02FE9AC4D291}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ApplicationInsights", "ApplicationInsights\ApplicationInsights.csproj", "{55149A3C-A263-4EE5-AD2D-02FE9AC4D291}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomDiagnosticAndEventListener", "CustomDiagnosticAndEventListener\CustomDiagnosticAndEventListener.csproj", "{9BE3551E-31A1-4186-9D2F-DC325411A39D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -165,6 +167,10 @@ Global {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Debug|Any CPU.Build.0 = Debug|Any CPU {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Release|Any CPU.ActiveCfg = Release|Any CPU {55149A3C-A263-4EE5-AD2D-02FE9AC4D291}.Release|Any CPU.Build.0 = Release|Any CPU + {9BE3551E-31A1-4186-9D2F-DC325411A39D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9BE3551E-31A1-4186-9D2F-DC325411A39D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BE3551E-31A1-4186-9D2F-DC325411A39D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9BE3551E-31A1-4186-9D2F-DC325411A39D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.cs new file mode 100644 index 0000000000..17348d9a22 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.cs @@ -0,0 +1,167 @@ +namespace Sample.Listeners +{ + using System.Diagnostics.Tracing; + using System.Diagnostics; + using System.Collections.Concurrent; + + /// + /// This listener can cover following aspects: + /// 1. Write its own monitoring library with the custom implementation of aggregation or whatever you want to do with this data. + /// 2. Support an APM tool which is not open telemetry compliant. + /// + /// It is a simple sample. Anybody can get as creative as they want to make it better in terms of usability and performance. + internal class CustomDiagnosticAndEventListener : + EventListener, // Override Event Listener to capture Event source events + IObserver>, // Override IObserver to capture Activity events + IObserver, + IDisposable + { + private readonly string diagnosticSourceName; + private readonly string eventSourceName; + + private ConcurrentBag? Subscriptions = new(); + private ConcurrentBag Activities { get; } = new(); + + public CustomDiagnosticAndEventListener(string diagnosticSourceName, string eventSourceName) + { + this.diagnosticSourceName = diagnosticSourceName; + this.eventSourceName = eventSourceName; + + DiagnosticListener.AllListeners.Subscribe(this); + } + + /// + /// IObserver Override + /// + public void OnCompleted() { + Console.WriteLine("OnCompleted"); + } + + /// + /// IObserver Override + /// + public void OnError(Exception error) { + Console.WriteLine($"OnError : {error}"); + } + + /// + /// IObserver Override + /// + public void OnNext(KeyValuePair value) + { + lock (this.Activities) + { + // Check for disposal + if (this.Subscriptions == null) return; + + string startSuffix = ".Start"; + string stopSuffix = ".Stop"; + string exceptionSuffix = ".Exception"; + + if (Activity.Current == null) + { + return; + } + + if (value.Key.EndsWith(startSuffix)) + { + this.Activities.Add(Activity.Current); + } + else if (value.Key.EndsWith(stopSuffix) || value.Key.EndsWith(exceptionSuffix)) + { + foreach (Activity activity in this.Activities) + { + if (activity.Id == Activity.Current.Id) + { + Console.WriteLine($" Activity Name: {activity.DisplayName}"); + Console.WriteLine($" Activity Operation Name: {activity.OperationName}"); + foreach (KeyValuePair actualTag in activity.Tags) + { + Console.WriteLine($" {actualTag.Key} ==> {actualTag.Value}"); + } + Console.WriteLine(); + return; + } + } + } + } + } + + /// + /// IObserver Override + /// + public void OnNext(DiagnosticListener value) + { + if (value.Name == this.diagnosticSourceName && this.Subscriptions != null) + { + Console.WriteLine($"CustomDiagnosticAndEventListener : OnNext : {value.Name}"); + lock (this.Activities) + { + this.Subscriptions?.Add(value.Subscribe(this)); + } + } + } + + /// + /// EventListener Override + /// + protected override void OnEventSourceCreated(EventSource eventSource) + { + if (eventSource != null && eventSource.Name.Equals(this.eventSourceName)) + { + Console.WriteLine($"CustomDiagnosticAndEventListener : OnEventSourceCreated : {eventSource.Name}"); + this.EnableEvents(eventSource, EventLevel.Informational); // Enable information level events + } + } + + /// + /// EventListener Override + /// + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + Console.WriteLine($" Event Name: {eventData.EventName}"); + Console.WriteLine($" Event Level: {eventData.Level}"); + if(eventData.Payload != null) + { + int counter = 0; + foreach (object? payload in eventData.Payload) + { + Console.WriteLine($" Event Payload {counter++}: {payload}"); + } + } + else + { + Console.WriteLine($" Event Payload: NULL"); + } + Console.WriteLine(); + } + + public override void Dispose() + { + Console.WriteLine("CustomDiagnosticAndEventListener : Dispose"); + base.Dispose(); + + if (this.Subscriptions == null) + { + return; + } + + ConcurrentBag subscriptions; + lock (this.Activities) + { + subscriptions = this.Subscriptions; + this.Subscriptions = null; + } + + foreach (IDisposable subscription in subscriptions) + { + subscription.Dispose(); // Dispose of DiagnosticListener subscription + } + + foreach (Activity activity in this.Activities) + { + activity.Dispose(); // Dispose of Activity + } + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.csproj new file mode 100644 index 0000000000..eeb17eb145 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/CustomDiagnosticAndEventListener.csproj @@ -0,0 +1,20 @@ + + + + Exe + net6.0 + enable + enable + + + + + + + + + + PreserveNewest + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs new file mode 100644 index 0000000000..77580936f7 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs @@ -0,0 +1,90 @@ +namespace Cosmos.Samples.ApplicationInsights +{ + using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Configuration; + using Newtonsoft.Json; + using Sample.Listeners; + + internal class Program + { + private static readonly string databaseName = "samples"; + private static readonly string containerName = "custom-listener-sample"; + + static async Task Main() + { + IConfigurationRoot configuration = new ConfigurationBuilder() + .AddJsonFile("AppSettings.json") + .Build(); + + string endpoint = configuration["EndPointUrl"]; + if (string.IsNullOrEmpty(endpoint)) + { + throw new ArgumentNullException("Please specify a valid CosmosDBEndPointUrl in the appSettings.json"); + } + + string authKey = configuration["AuthorizationKey"]; + if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key")) + { + throw new ArgumentException("Please specify a valid CosmosDBAuthorizationKey in the appSettings.json"); + } + + using CustomDiagnosticAndEventListener listener + = new CustomDiagnosticAndEventListener( + diagnosticSourceName: "Azure.Cosmos.Operation", + eventSourceName: "Azure-Cosmos-Operation-Request-Diagnostics"); + + CosmosClientOptions options = new CosmosClientOptions() + { + IsDistributedTracingEnabled = true // Defaults to true, set to false to disable + }; + using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + await Program.RunCrudDemo(container); + } + } + + public static async Task RunCrudDemo(Container container) + { + // Any operations will automatically generate telemetry + + for (int i = 1; i <= 5; i++) + { + await container.CreateItemAsync(new Item { Id = $"{i}", Status = "new" }, new PartitionKey($"{i}")); + Console.WriteLine($"Created document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReadItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Read document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.ReplaceItemAsync(new Item { Id = $"{i}", Status = "updated" }, $"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Updated document with id: {i}"); + } + + for (int i = 1; i <= 5; i++) + { + await container.DeleteItemAsync($"{i}", new PartitionKey($"{i}")); + Console.WriteLine($"Deleted document with id: {i}"); + } + } + } + + internal class Item + { + [JsonProperty("id")] + public string Id { get; set; } + + public string Status { get; set; } + } +} \ No newline at end of file From 32827f7846efdfa58be1a72cfe5e0e13cc3fe485 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 10 Aug 2023 12:59:38 -0700 Subject: [PATCH 172/337] Code changes to fix race condition by calling dispose too early. (#4030) --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index d3ceab0046..044a7ec7d9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.35.3 3.35.3 preview - 3.31.3 + 3.31.4 2.0.3 2.0.3 preview From efb90f094166ab1c9ab8cd8ef84b556ec6c887e0 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 10 Aug 2023 13:25:15 -0700 Subject: [PATCH 173/337] Code changes to update change log for release 3.35.3 (#4032) --- changelog.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/changelog.md b/changelog.md index f7a46f39a3..27ec98fae0 100644 --- a/changelog.md +++ b/changelog.md @@ -13,11 +13,11 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -### [3.35.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3-preview) - 2023-08-09 -### [3.35.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3) - 2023-08-09 +### [3.35.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3-preview) - 2023-08-10 +### [3.35.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3) - 2023-08-10 #### Fixed -- [3979](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3979) Client Encryption: Adds fix for supporting Prefix Partition Key (Hierarchical partitioning) +- [4030](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4030) Upgrade Resiliency: Fixes Race Condition by Calling Dispose Too Early #### Added - [4019](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4019) Upgrade Resiliency: Disables Replica Validation Feature By Default in Preview (The feature was previously enabled by default in the [`3.35.2-preview`](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.2-preview) release) From e708ec9025626121ef9e07cf9146a71daefc296e Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:14:47 -0700 Subject: [PATCH 174/337] Documentation: Fixes article links (replaced links V2 to V3 SDK version) + Azure Cosmos DB typo (#4031) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Documentation link fix * Fixed Typo "Azure CosmosDB"→"Azure Cosmos DB" --- .../src/ConnectionPolicy.cs | 6 ++--- Microsoft.Azure.Cosmos/src/CosmosClient.cs | 26 +++++++++---------- .../src/CosmosClientOptions.cs | 6 ++--- .../src/Diagnostics/CosmosDiagnostics.cs | 4 +-- .../src/Fluent/CosmosClientBuilder.cs | 8 +++--- .../DedicatedGatewayRequestOptions.cs | 4 +-- Microsoft.Azure.Cosmos/src/RetryOptions.cs | 4 +-- 7 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index 9193abedef..c8c1d9db93 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -131,7 +131,7 @@ public TimeSpan MediaRequestTimeout /// Default value is /// /// - /// For more information, see Connection policy: Use direct connection mode. + /// For more information, see Connection policy: Use direct connection mode. /// public ConnectionMode ConnectionMode { @@ -160,7 +160,7 @@ public MediaReadMode MediaReadMode /// /// This setting is not used when is set to . /// Gateway mode only supports HTTPS. - /// For more information, see Connection policy: Use the TCP protocol. + /// For more information, see Connection policy: Use the HTTPS protocol. /// public Protocol ConnectionProtocol { @@ -369,7 +369,7 @@ public int MaxConnectionLimit /// set to 9 and set to 30 seconds. /// /// - /// For more information, see Handle rate limiting/request rate too large. + /// For more information, see Handle rate limiting/request rate too large. /// public RetryOptions RetryOptions { diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index d622e9ddcb..7b143196fe 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -28,7 +28,7 @@ namespace Microsoft.Azure.Cosmos /// /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. ///
/// /// This example create a , , and a . @@ -97,7 +97,7 @@ namespace Microsoft.Azure.Cosmos /// /// /// - /// Performance Tips + /// Performance Tips /// Diagnose and troubleshoot issues /// Global data distribution /// Partitioning and horizontal scaling @@ -160,7 +160,7 @@ protected CosmosClient() /// /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. ///
/// The connection string to the cosmos account. ex: AccountEndpoint=https://XXXXX.documents.azure.com:443/;AccountKey=SuperSecretKey; /// (Optional) client options @@ -187,7 +187,7 @@ protected CosmosClient() /// /// /// - /// Performance Tips + /// Performance Tips /// Diagnose and troubleshoot issues public CosmosClient( string connectionString, @@ -204,7 +204,7 @@ public CosmosClient( /// /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. ///
/// The cosmos service endpoint to use /// The cosmos account key or resource token to use to create the client. @@ -232,7 +232,7 @@ public CosmosClient( /// /// /// - /// Performance Tips + /// Performance Tips /// Diagnose and troubleshoot issues public CosmosClient( string accountEndpoint, @@ -250,7 +250,7 @@ public CosmosClient( /// /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// The cosmos service endpoint to use /// AzureKeyCredential with master-key or resource token.. @@ -281,7 +281,7 @@ public CosmosClient( /// /// /// - /// Performance Tips + /// Performance Tips /// Diagnose and troubleshoot issues /// /// AzureKeyCredential enables changing/updating master-key/ResourceToken whle CosmosClient is still in use. @@ -302,7 +302,7 @@ public CosmosClient( /// /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. @@ -357,7 +357,7 @@ internal CosmosClient( /// connections before the first call to the service is made. Use this to obtain lower latency while startup of your application. /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// The cosmos service endpoint to use /// The cosmos account key or resource token to use to create the client. @@ -413,7 +413,7 @@ public static async Task CreateAndInitializeAsync(string accountEn /// connections before the first call to the service is made. Use this to obtain lower latency while startup of your application. /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// The cosmos service endpoint to use /// AzureKeyCredential with master-key or resource token. @@ -471,7 +471,7 @@ public static async Task CreateAndInitializeAsync(string accountEn /// connections before the first call to the service is made. Use this to obtain lower latency while startup of your application. /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// The connection string to the cosmos account. ex: AccountEndpoint=https://XXXXX.documents.azure.com:443/;AccountKey=SuperSecretKey; /// Containers to be initialized identified by it's database name and container name. @@ -518,7 +518,7 @@ public static async Task CreateAndInitializeAsync(string connectio /// connections before the first call to the service is made. Use this to obtain lower latency while startup of your application. /// CosmosClient is thread-safe. Its recommended to maintain a single instance of CosmosClient per lifetime /// of the application which enables efficient connection management and performance. Please refer to the - /// performance guide. + /// performance guide. /// /// The cosmos service endpoint to use. /// The token to provide AAD token for authorization. diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 330738c00b..2c07f060f8 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -250,7 +250,7 @@ public int GatewayModeMaxConnectionLimit /// Default value is /// /// - /// For more information, see Connection policy: Use direct connection mode. + /// For more information, see Connection policy: Use direct connection mode. /// /// /// @@ -614,7 +614,7 @@ public Func HttpClientFactory /// Quorum Read allowed with eventual consistency account or consistent prefix account. /// internal bool EnableUpgradeConsistencyToLocalQuorum { get; set; } = false; - + /// /// Gets or sets the connection protocol when connecting to the Azure Cosmos service. /// @@ -624,7 +624,7 @@ public Func HttpClientFactory /// /// This setting is not used when is set to . /// Gateway mode only supports HTTPS. - /// For more information, see Connection policy: Use the TCP protocol. + /// For more information, see Connection policy: Use the HTTPS protocol. /// internal Protocol ConnectionProtocol { diff --git a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs index cb3ffe6c04..ad568475df 100644 --- a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs @@ -44,9 +44,9 @@ public virtual int GetFailedRequestCount() } /// - /// Gets the string field instance in the Azure CosmosDB database service. + /// Gets the string field instance in the Azure Cosmos DB database service. /// - /// The string field instance in the Azure CosmosDB database service. + /// The string field instance in the Azure Cosmos DB database service. /// /// implements lazy materialization and is only materialized when is called. /// diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 8b72bfffa4..9c8c2fbb4e 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -349,7 +349,7 @@ public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout) /// Sets the connection mode to Direct. This is used by the client when connecting to the Azure Cosmos DB service. /// /// - /// For more information, see Connection policy: Use direct connection mode. + /// For more information, see Connection policy: Use direct connection mode. /// /// The current . /// @@ -396,7 +396,7 @@ public CosmosClientBuilder WithConnectionModeDirect() /// The default value is false. /// /// - /// For more information, see Connection policy: Use direct connection mode. + /// For more information, see Connection policy: Use direct connection mode. /// /// The current . /// @@ -472,7 +472,7 @@ internal CosmosClientBuilder WithDistributedTracingOptions(DistributedTracingOpt /// The number specifies the number of connections that may be opened simultaneously. Default is 50 connections /// Get or set the proxy information used for web requests. /// - /// For more information, see Connection policy: Use direct connection mode. + /// For more information, see Connection policy: Use direct connection mode. /// /// The current . /// @@ -529,7 +529,7 @@ public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandl /// If the cumulative wait time exceeds the this value, the client will stop retrying and return the error to the application. /// /// - /// For more information, see Handle rate limiting/request rate too large. + /// For more information, see Handle rate limiting/request rate too large. /// /// The current . /// diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs index 9ca854388c..31f82644a9 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs @@ -14,7 +14,7 @@ namespace Microsoft.Azure.Cosmos public class DedicatedGatewayRequestOptions { /// - /// Gets or sets the staleness value associated with the request in the Azure CosmosDB service. + /// Gets or sets the staleness value associated with the request in the Azure Cosmos DB service. /// /// Default value is null. /// @@ -24,7 +24,7 @@ public class DedicatedGatewayRequestOptions public TimeSpan? MaxIntegratedCacheStaleness { get; set; } /// - /// Gets or sets if bypass the integrated cache or not associated with the request in the Azure CosmosDB service. + /// Gets or sets if bypass the integrated cache or not associated with the request in the Azure Cosmos DB service. /// When set this value to true, the request will not be served from the integrated cache, and the response will not be cached either. /// /// Default value is false. diff --git a/Microsoft.Azure.Cosmos/src/RetryOptions.cs b/Microsoft.Azure.Cosmos/src/RetryOptions.cs index 8384df8105..5577b4b0d6 100644 --- a/Microsoft.Azure.Cosmos/src/RetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RetryOptions.cs @@ -56,7 +56,7 @@ public RetryOptions() /// retry after the time has elapsed. /// /// - /// For more information, see Handle rate limiting/request rate too large. + /// For more information, see Handle rate limiting/request rate too large. /// /// public int MaxRetryAttemptsOnThrottledRequests @@ -91,7 +91,7 @@ public int MaxRetryAttemptsOnThrottledRequests /// If the cumulative wait time exceeds the this value, the client will stop retrying and return the error to the application. /// /// - /// For more information, see Handle rate limiting/request rate too large. + /// For more information, see Handle rate limiting/request rate too large. /// /// public int MaxRetryWaitTimeInSeconds From 946dd4a95f27da4bc82ead3558d67afcd423c8c0 Mon Sep 17 00:00:00 2001 From: Mikhail Lipin Date: Wed, 16 Aug 2023 01:06:04 +0300 Subject: [PATCH 175/337] [Internal] Benchmark tool: Adds Cosmos Benchmark Metrics (#3950) * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Fixing code review points. * make MetrcisCollectorProvider non static and remove locks * fix * fixes * use static class name TelemetrySpan.IncludePercentile * use app insights connection string * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * rename AppInsightsConnectionString * fix * fix comments * fix if AppInsights c string is not set * summary * fix * remove unnecessary collector types * remove unnecesary metere provicer * add event source * remove folder * fix * split success and failed latencies * fix * fix --------- Co-authored-by: David Chaava Co-authored-by: David Chaava --- .../Tools/Benchmark/BenchmarkConfig.cs | 14 +- .../Tools/Benchmark/CosmosBenchmark.csproj | 1 + .../Tools/Benchmark/Fx/IExecutionStrategy.cs | 5 +- .../Tools/Benchmark/Fx/IExecutor.cs | 4 +- .../Tools/Benchmark/Fx/IMetricsCollector.cs | 36 ++++ .../Tools/Benchmark/Fx/MetricsCollector.cs | 166 ++++++++++++++++++ .../Benchmark/Fx/MetricsCollectorProvider.cs | 68 +++++++ .../Benchmark/Fx/ParallelExecutionStrategy.cs | 16 +- .../Benchmark/Fx/SerialOperationExecutor.cs | 31 +++- .../Tools/Benchmark/Fx/TelemetrySpan.cs | 53 +++++- .../Tools/Benchmark/MetricCollectionWindow.cs | 48 +++++ .../Tools/Benchmark/Program.cs | 67 +++++-- 12 files changed, 475 insertions(+), 34 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index 6f89776370..f5ff091b28 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -6,12 +6,16 @@ namespace CosmosBenchmark { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Runtime; using CommandLine; using Microsoft.Azure.Documents.Client; using Newtonsoft.Json; + /// + /// Represents Benchmark Configuration + /// public class BenchmarkConfig { private static readonly string UserAgentSuffix = "cosmosdbdotnetbenchmark"; @@ -123,6 +127,12 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Container to publish results to")] public string ResultsContainer { get; set; } = "runsummary"; + [Option(Required = false, HelpText = "Metrics reporting interval in seconds")] + public int MetricsReportingIntervalInSec { get; set; } = 5; + + [Option(Required = false, HelpText = "Application Insights connection string")] + public string AppInsightsConnectionString { get; set; } + internal int GetTaskCount(int containerThroughput) { int taskCount = this.DegreeOfParallelism; @@ -263,11 +273,11 @@ private static void HandleParseError(IEnumerable errors) { foreach (Error e in errors) { - Console.WriteLine(e.ToString()); + Trace.TraceInformation(e.ToString()); } } Environment.Exit(errors.Count()); } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj index c8ac26f5aa..2506e48102 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj @@ -17,6 +17,7 @@ + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs index b18fc34dc7..ed1400026b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs @@ -6,6 +6,7 @@ namespace CosmosBenchmark { using System; using System.Threading.Tasks; + using OpenTelemetry.Metrics; internal interface IExecutionStrategy { @@ -19,7 +20,7 @@ public Task ExecuteAsync( BenchmarkConfig benchmarkConfig, int serialExecutorConcurrency, int serialExecutorIterationCount, - double warmupFraction); - + double warmupFraction, + MetricsCollectorProvider metricsCollectorProvider); } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs index be2ee2e761..235a54199b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs @@ -17,6 +17,8 @@ public Task ExecuteAsync( int iterationCount, bool isWarmup, bool traceFailures, - Action completionCallback); + Action completionCallback, + BenchmarkConfig benchmarkConfig, + MetricsCollectorProvider metricsCollectorProvider); } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs new file mode 100644 index 0000000000..58af9d0b19 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs @@ -0,0 +1,36 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark +{ + using System; + + /// + /// Represents the metrics collector. + /// + public interface IMetricsCollector + { + /// + /// Collects the number of successful operations. + /// + void CollectMetricsOnSuccess(); + + /// + /// Collects the number of failed operations. + /// + void CollectMetricsOnFailure(); + + /// + /// Records latency for success operations in milliseconda. + /// + /// The number of milliseconds to record. + void RecordSuccessOpLatencyAndRps(TimeSpan timeSpan); + + /// + /// Records latency for failed operations in milliseconda. + /// + /// The number of milliseconds to record. + void RecordFailedOpLatencyAndRps(TimeSpan timeSpan); + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs new file mode 100644 index 0000000000..866e400870 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs @@ -0,0 +1,166 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark +{ + using System; + using System.Diagnostics.Metrics; + + /// + /// Represents the metrics collector. + /// + internal class MetricsCollector : IMetricsCollector + { + /// + /// Represents the meter to collect metrics. + /// + private readonly Meter meter; + + /// + /// Represents the histogram for operation latency. + /// + private readonly Histogram operationLatencyHistogram; + + /// + /// Represents the histogram for records per second metric. + /// + private readonly Histogram rpsMetricNameHistogram; + + /// + /// Represents the histogram for failed operation latency. + /// + private readonly Histogram operationFailedLatencyHistogram; + + /// + /// Represents the histogram failed operations for records per second metric. + /// + private readonly Histogram rpsFailedMetricNameHistogram; + + /// + /// Represents the success operation counter. + /// + private readonly Counter successOperationCounter; + + /// + /// Represents the failure operation counter. + /// + private readonly Counter failureOperationCounter; + + /// + /// Represents latency in milliseconds metric gauge. + /// + /// Please do not remove this as it used when collecting metrics.. + private readonly ObservableGauge latencyInMsMetricNameGauge; + + /// + /// Represents records per second metric gauge. + /// + /// Please do not remove this as it used when collecting metrics.. + private readonly ObservableGauge rpsNameGauge; + + + /// + /// Represents latency in milliseconds metric gauge for failed operations. + /// + /// Please do not remove this as it used when collecting metrics.. + private readonly ObservableGauge latencyInMsFailedMetricNameGauge; + + /// + /// Represents records per second metric gauge for failed operations. + /// + /// Please do not remove this as it used when collecting metrics.. + private readonly ObservableGauge rpsFailedNameGauge; + + /// + /// Latency in milliseconds. + /// + private double latencyInMs; + + /// + /// Records per second. + /// + private double rps; + + /// + /// Latency in milliseconds. + /// + private double latencyFailedInMs; + + /// + /// Records per second. + /// + private double rpsFailed; + + /// + /// Initialize new instance of . + /// + /// OpenTelemetry meter. + public MetricsCollector(Meter meter, string prefix) + { + this.meter = meter; + this.rpsMetricNameHistogram = meter.CreateHistogram($"{prefix}OperationRpsHistogram"); + this.operationLatencyHistogram = meter.CreateHistogram($"{prefix}OperationLatencyInMsHistogram"); + + this.rpsFailedMetricNameHistogram = meter.CreateHistogram($"{prefix}FailedOperationRpsHistogram"); + this.operationFailedLatencyHistogram = meter.CreateHistogram($"{prefix}FailedOperationLatencyInMsHistogram"); + + this.successOperationCounter = meter.CreateCounter($"{prefix}OperationSuccess"); + this.failureOperationCounter = meter.CreateCounter($"{prefix}OperationFailure"); + + this.latencyInMsMetricNameGauge = this.meter.CreateObservableGauge($"{prefix}OperationLatencyInMs", + () => new Measurement(this.latencyInMs)); + + this.rpsNameGauge = this.meter.CreateObservableGauge($"{prefix}OperationRps", + () => new Measurement(this.rps)); + + this.latencyInMsFailedMetricNameGauge = this.meter.CreateObservableGauge($"{prefix}FailedOperationLatencyInMs", + () => new Measurement(this.latencyInMs)); + + this.rpsFailedNameGauge = this.meter.CreateObservableGauge($"{prefix}FailedOperationRps", + () => new Measurement(this.rps)); + } + + /// + /// Collects the number of successful operations. + /// + public void CollectMetricsOnSuccess() + { + this.successOperationCounter.Add(1); + } + + /// + /// Collects the number of failed operations. + /// + public void CollectMetricsOnFailure() + { + this.failureOperationCounter.Add(1); + } + + /// + /// Records success operation latency in milliseconds. + /// + /// The number of milliseconds to record. + public void RecordSuccessOpLatencyAndRps( + TimeSpan timeSpan) + { + this.rps = 1000 / timeSpan.Milliseconds; + this.latencyInMs = timeSpan.Milliseconds; + this.rpsMetricNameHistogram.Record(this.rps); + this.operationLatencyHistogram.Record(this.latencyInMs); + } + + /// + /// Records failed operation latency in milliseconds. + /// + /// The number of milliseconds to record. + public void RecordFailedOpLatencyAndRps( + TimeSpan timeSpan) + { + this.rpsFailed = 1000 / timeSpan.Milliseconds; + this.latencyFailedInMs = timeSpan.Milliseconds; + this.rpsFailedMetricNameHistogram.Record(this.rpsFailed); + this.operationFailedLatencyHistogram.Record(this.latencyFailedInMs); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs new file mode 100644 index 0000000000..4de7009be1 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs @@ -0,0 +1,68 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark +{ + using System; + using System.Diagnostics.Metrics; + using OpenTelemetry.Metrics; + + /// + /// Represents the metrics collector provider. + /// + internal class MetricsCollectorProvider + { + private readonly MetricCollectionWindow metricCollectionWindow; + + private readonly MetricsCollector insertOperationMetricsCollector; + + private readonly MetricsCollector queryOperationMetricsCollector; + + private readonly MetricsCollector readOperationMetricsCollector; + + private readonly Meter insertOperationMeter = new("CosmosBenchmarkInsertOperationMeter"); + + private readonly Meter queryOperationMeter = new("CosmosBenchmarkQueryOperationMeter"); + + private readonly Meter readOperationMeter = new("CosmosBenchmarkReadOperationMeter"); + + private readonly MeterProvider meterProvider; + + public MetricsCollectorProvider(BenchmarkConfig config, MeterProvider meterProvider) + { + this.meterProvider = meterProvider; + this.insertOperationMetricsCollector ??= new MetricsCollector(this.insertOperationMeter, "Insert"); + this.queryOperationMetricsCollector ??= new MetricsCollector(this.queryOperationMeter, "Query"); + this.readOperationMetricsCollector ??= new MetricsCollector(this.readOperationMeter, "Read"); + this.metricCollectionWindow ??= new MetricCollectionWindow(config); + } + + /// + /// Gets the metric collector. + /// + /// Benchmark operation. + /// Benchmark configuration. + /// Metrics collector. + /// Thrown if provided benchmark operation is not covered supported to collect metrics. + public IMetricsCollector GetMetricsCollector(IBenchmarkOperation benchmarkOperation, BenchmarkConfig config) + { + MetricCollectionWindow metricCollectionWindow = this.metricCollectionWindow; + + // Reset metricCollectionWindow and flush. + if (!metricCollectionWindow.IsValid) + { + this.meterProvider.ForceFlush(); + metricCollectionWindow.Reset(config); + } + + return benchmarkOperation.OperationType switch + { + BenchmarkOperationType.Insert => this.insertOperationMetricsCollector, + BenchmarkOperationType.Query => this.queryOperationMetricsCollector, + BenchmarkOperationType.Read => this.readOperationMetricsCollector, + _ => throw new NotSupportedException($"The type of {nameof(benchmarkOperation)} is not supported for collecting metrics."), + }; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs index e5dc7bb58d..2348d4a995 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs @@ -11,6 +11,7 @@ namespace CosmosBenchmark using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; + using OpenTelemetry.Metrics; internal class ParallelExecutionStrategy : IExecutionStrategy { @@ -28,7 +29,8 @@ public async Task ExecuteAsync( BenchmarkConfig benchmarkConfig, int serialExecutorConcurrency, int serialExecutorIterationCount, - double warmupFraction) + double warmupFraction, + MetricsCollectorProvider metricsCollectorProvider) { IExecutor warmupExecutor = new SerialOperationExecutor( executorId: "Warmup", @@ -37,7 +39,9 @@ await warmupExecutor.ExecuteAsync( (int)(serialExecutorIterationCount * warmupFraction), isWarmup: true, traceFailures: benchmarkConfig.TraceFailures, - completionCallback: () => { }); + completionCallback: () => { }, + benchmarkConfig, + metricsCollectorProvider); IExecutor[] executors = new IExecutor[serialExecutorConcurrency]; for (int i = 0; i < serialExecutorConcurrency; i++) @@ -54,11 +58,13 @@ await warmupExecutor.ExecuteAsync( iterationCount: serialExecutorIterationCount, isWarmup: false, traceFailures: benchmarkConfig.TraceFailures, - completionCallback: () => Interlocked.Decrement(ref this.pendingExecutorCount)); + completionCallback: () => Interlocked.Decrement(ref this.pendingExecutorCount), + benchmarkConfig, + metricsCollectorProvider); } return await this.LogOutputStats( - benchmarkConfig, + benchmarkConfig, executors); } @@ -160,4 +166,4 @@ private async Task LogOutputStats( } } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs index 1086c31bd5..b33218f65b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs @@ -8,10 +8,12 @@ namespace CosmosBenchmark using System.Diagnostics; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; + using static CosmosBenchmark.TelemetrySpan; internal class SerialOperationExecutor : IExecutor { private readonly IBenchmarkOperation operation; + private readonly string executorId; public SerialOperationExecutor( @@ -26,6 +28,7 @@ public SerialOperationExecutor( } public int SuccessOperationCount { get; private set; } + public int FailedOperationCount { get; private set; } public double TotalRuCharges { get; private set; } @@ -34,27 +37,38 @@ public async Task ExecuteAsync( int iterationCount, bool isWarmup, bool traceFailures, - Action completionCallback) + Action completionCallback, + BenchmarkConfig benchmarkConfig, + MetricsCollectorProvider metricsCollectorProvider) { Trace.TraceInformation($"Executor {this.executorId} started"); + Trace.TraceInformation("Initializing counters and metrics."); + try { int currentIterationCount = 0; do { + IMetricsCollector metricsCollector = metricsCollectorProvider.GetMetricsCollector(this.operation, benchmarkConfig); + OperationResult? operationResult = null; await this.operation.PrepareAsync(); - using (IDisposable telemetrySpan = TelemetrySpan.StartNew( + using (ITelemetrySpan telemetrySpan = TelemetrySpan.StartNew( + benchmarkConfig, () => operationResult.Value, - disableTelemetry: isWarmup)) + disableTelemetry: isWarmup, + metricsCollector.RecordSuccessOpLatencyAndRps, + metricsCollector.RecordFailedOpLatencyAndRps)) { try { operationResult = await this.operation.ExecuteOnceAsync(); + metricsCollector.CollectMetricsOnSuccess(); + // Success case this.SuccessOperationCount++; this.TotalRuCharges += operationResult.Value.RuCharges; @@ -68,8 +82,11 @@ public async Task ExecuteAsync( { if (traceFailures) { - Console.WriteLine(ex.ToString()); + Trace.TraceInformation(ex.ToString()); } + telemetrySpan.MarkFailed(); + + metricsCollector.CollectMetricsOnFailure(); // failure case this.FailedOperationCount++; @@ -96,10 +113,14 @@ public async Task ExecuteAsync( Trace.TraceInformation($"Executor {this.executorId} completed"); } + catch (Exception e) + { + Trace.TraceInformation($"Error: {e.Message}"); + } finally { completionCallback(); } } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs index 13d971aa2a..fff2acac3e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs @@ -8,8 +8,9 @@ namespace CosmosBenchmark using System.Diagnostics; using System.Linq; using System.Threading; + using static CosmosBenchmark.TelemetrySpan; - internal struct TelemetrySpan : IDisposable + internal class TelemetrySpan : ITelemetrySpan { private static double[] latencyHistogram; private static int latencyIndex = -1; @@ -18,11 +19,18 @@ internal struct TelemetrySpan : IDisposable private Stopwatch stopwatch; private Func lazyOperationResult; + private Action recordFailedOpLatencyAction; + private Action recordSuccessOpLatencyAction; private bool disableTelemetry; + private bool isFailed = false; + private BenchmarkConfig benchmarkConfig; - public static IDisposable StartNew( + public static ITelemetrySpan StartNew( + BenchmarkConfig benchmarkConfig, Func lazyOperationResult, - bool disableTelemetry) + bool disableTelemetry, + Action recordSuccessOpLatencyAction, + Action recordFailedOpLatencyAction) { if (disableTelemetry || !TelemetrySpan.IncludePercentile) { @@ -31,12 +39,17 @@ public static IDisposable StartNew( return new TelemetrySpan { + benchmarkConfig = benchmarkConfig, stopwatch = Stopwatch.StartNew(), lazyOperationResult = lazyOperationResult, + recordSuccessOpLatencyAction = recordSuccessOpLatencyAction, + recordFailedOpLatencyAction = recordFailedOpLatencyAction, disableTelemetry = disableTelemetry }; } + public void MarkFailed() { this.isFailed = true; } + public void Dispose() { this.stopwatch.Stop(); @@ -47,6 +60,16 @@ public void Dispose() if (TelemetrySpan.IncludePercentile) { RecordLatency(this.stopwatch.Elapsed.TotalMilliseconds); + + if(this.isFailed) + { + this.recordSuccessOpLatencyAction?.Invoke(TimeSpan.FromMilliseconds(this.stopwatch.Elapsed.TotalMilliseconds)); + } + else + { + this.recordSuccessOpLatencyAction?.Invoke(TimeSpan.FromMilliseconds(this.stopwatch.Elapsed.TotalMilliseconds)); + + } } BenchmarkLatencyEventSource.Instance.LatencyDiagnostics( @@ -65,13 +88,13 @@ private static void RecordLatency(double elapsedMilliseoncds) internal static void ResetLatencyHistogram(int totalNumberOfIterations) { - latencyHistogram = new double[totalNumberOfIterations]; + TelemetrySpan.latencyHistogram = new double[totalNumberOfIterations]; latencyIndex = -1; } internal static double? GetLatencyPercentile(int percentile) { - if (latencyHistogram == null) + if (TelemetrySpan.latencyHistogram == null) { return null; } @@ -79,13 +102,31 @@ internal static void ResetLatencyHistogram(int totalNumberOfIterations) return MathNet.Numerics.Statistics.Statistics.Percentile(latencyHistogram.Take(latencyIndex + 1), percentile); } - private class NoOpDisposable : IDisposable + internal static double? GetLatencyQuantile(double quantile) + { + if (TelemetrySpan.latencyHistogram == null) + { + return null; + } + + return MathNet.Numerics.Statistics.Statistics.Quantile(latencyHistogram.Take(latencyIndex + 1), quantile); + } + + private class NoOpDisposable : ITelemetrySpan { public static readonly NoOpDisposable Instance = new NoOpDisposable(); public void Dispose() { } + + public void MarkFailed() + { + } + } + + public interface ITelemetrySpan : IDisposable { + void MarkFailed(); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs new file mode 100644 index 0000000000..948ade075e --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark +{ + using System; + + /// + /// Represents the metric collection window (time span while accumulating and granulating the data) + /// + internal class MetricCollectionWindow + { + /// + /// The timestamp when window span is started. + /// + public DateTime Started { get; private set; } + + /// + /// The timestamp until which the current window span is not elapsed. + /// + public DateTime ValidTill { get; private set; } + + /// + /// Creates the instance of . + /// + /// Cosmos Benchmark configuration. + public MetricCollectionWindow(BenchmarkConfig config) + { + this.Reset(config); + } + + /// + /// Indicates whether the current window is valid. + /// + public bool IsValid => DateTime.UtcNow > this.ValidTill; + + /// + /// Resets the started timestamp and valid till timespan. + /// + /// + public void Reset(BenchmarkConfig config) + { + this.Started = DateTime.UtcNow; + this.ValidTill = this.Started.AddSeconds(config.MetricsReportingIntervalInSec); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs index 99131262d7..2e7687932f 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs @@ -14,8 +14,13 @@ namespace CosmosBenchmark using System.Reflection; using System.Threading; using System.Threading.Tasks; + using Azure.Monitor.OpenTelemetry.Exporter; using Microsoft.Azure.Cosmos; + using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; + using OpenTelemetry; + using OpenTelemetry.Metrics; + using Container = Microsoft.Azure.Cosmos.Container; /// /// This sample demonstrates how to achieve high performance writes using Azure Comsos DB. @@ -31,8 +36,12 @@ public static async Task Main(string[] args) try { BenchmarkConfig config = BenchmarkConfig.From(args); - await Program.AddAzureInfoToRunSummary(); - + await AddAzureInfoToRunSummary(); + + MeterProvider meterProvider = BuildMeterProvider(config); + + MetricsCollectorProvider metricsCollectorProvider = new MetricsCollectorProvider(config, meterProvider); + ThreadPool.SetMinThreads(config.MinThreadPoolSize, config.MinThreadPoolSize); if (config.EnableLatencyPercentiles) @@ -45,7 +54,7 @@ public static async Task Main(string[] args) Program program = new Program(); - RunSummary runSummary = await program.ExecuteAsync(config); + RunSummary runSummary = await program.ExecuteAsync(config, metricsCollectorProvider); } finally { @@ -58,6 +67,37 @@ public static async Task Main(string[] args) } } + /// + /// Create a MeterProvider. If the App Insights connection string is not set, do not create an AppInsights Exporter. + /// + /// + private static MeterProvider BuildMeterProvider(BenchmarkConfig config) + { + if (string.IsNullOrWhiteSpace(config.AppInsightsConnectionString)) + { + return Sdk.CreateMeterProviderBuilder() + .AddMeter("CosmosBenchmarkInsertOperationMeter") + .AddMeter("CosmosBenchmarkQueryOperationMeter") + .AddMeter("CosmosBenchmarkReadOperationMeter") + .Build(); + } + + OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder = Sdk.CreateTracerProviderBuilder() + .AddAzureMonitorTraceExporter(); + + return Sdk.CreateMeterProviderBuilder() + .AddAzureMonitorMetricExporter(configure: new Action( + (options) => options.ConnectionString = config.AppInsightsConnectionString)) + .AddMeter("CosmosBenchmarkInsertOperationMeter") + .AddMeter("CosmosBenchmarkQueryOperationMeter") + .AddMeter("CosmosBenchmarkReadOperationMeter") + .Build(); + } + + /// + /// Adds Azure VM information to run summary. + /// + /// private static async Task AddAzureInfoToRunSummary() { using HttpClient httpClient = new HttpClient(); @@ -81,11 +121,13 @@ private static async Task AddAzureInfoToRunSummary() } } + /// /// Executing benchmarks for V2/V3 cosmosdb SDK. /// /// a Task object. - private async Task ExecuteAsync(BenchmarkConfig config) + private async Task ExecuteAsync(BenchmarkConfig config, + MetricsCollectorProvider metricsCollectorProvider) { // V3 SDK client initialization using (CosmosClient cosmosClient = config.CreateCosmosClient(config.Key)) @@ -137,7 +179,7 @@ private async Task ExecuteAsync(BenchmarkConfig config) } IExecutionStrategy execution = IExecutionStrategy.StartNew(benchmarkOperationFactory); - runSummary = await execution.ExecuteAsync(config, taskCount, opsPerTask, 0.01); + runSummary = await execution.ExecuteAsync(config, taskCount, opsPerTask, 0.01, metricsCollectorProvider); } if (config.CleanupOnFinish) @@ -154,13 +196,12 @@ private async Task ExecuteAsync(BenchmarkConfig config) } runSummary.ConsistencyLevel = consistencyLevel; - if (config.PublishResults) { runSummary.Diagnostics = CosmosDiagnosticsLogger.GetDiagnostics(); await this.PublishResults( - config, - runSummary, + config, + runSummary, cosmosClient); } @@ -169,8 +210,8 @@ await this.PublishResults( } private async Task PublishResults( - BenchmarkConfig config, - RunSummary runSummary, + BenchmarkConfig config, + RunSummary runSummary, CosmosClient benchmarkClient) { if (string.IsNullOrEmpty(config.ResultsEndpoint)) @@ -266,8 +307,8 @@ private static async Task CreatePartitionedContainerAsync(Ben { return await container.ReadContainerAsync(); } - catch(CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound) - { + catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound) + { // Show user cost of running this test double estimatedCostPerMonth = 0.06 * options.Throughput; double estimatedCostPerHour = estimatedCostPerMonth / (24 * 30); @@ -288,4 +329,4 @@ private static void ClearCoreSdkListeners() traceSource.Listeners.Clear(); } } -} +} \ No newline at end of file From 48af69ecab18066a6b4faef924cdc8fe7c828401 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 16 Aug 2023 16:24:03 -0700 Subject: [PATCH 176/337] GatewayAddressCache: Fixes Unobserved Exception During Background Address Refresh (#4039) * Code changes to fix unobserved exception during background address refresh. * Code changes to add exception handler in task. * Code changes to fix null ref exception. * Revert "Code changes to fix null ref exception." This reverts commit 83f90d578bd301339f6fa13981a0fe2fc3d65fa6. * Revert "Code changes to add exception handler in task." This reverts commit c49ed8162758217a09df28417a6f76649eab6a26. * Code changes to address review comments. * Revert "Code changes to address review comments." This reverts commit d2b9f6b501f64f1a50b8a49de3ea76fbb9b5c853. --- .../src/Routing/GatewayAddressCache.cs | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index a4dbb1d8a3..8bc429070e 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -302,14 +302,27 @@ public async Task TryGetAddressesAsync( .ReplicaTransportAddressUris .Any(x => x.ShouldRefreshHealthStatus())) { - Task refreshAddressesInBackgroundTask = Task.Run(async () => await this.serverPartitionAddressCache.RefreshAsync( - key: partitionKeyRangeIdentity, - singleValueInitFunc: (currentCachedValue) => this.GetAddressesForRangeIdAsync( - request, - cachedAddresses: currentCachedValue, + Task refreshAddressesInBackgroundTask = Task.Run(async () => + { + try + { + await this.serverPartitionAddressCache.RefreshAsync( + key: partitionKeyRangeIdentity, + singleValueInitFunc: (currentCachedValue) => this.GetAddressesForRangeIdAsync( + request, + cachedAddresses: currentCachedValue, + partitionKeyRangeIdentity.CollectionRid, + partitionKeyRangeIdentity.PartitionKeyRangeId, + forceRefresh: true)); + } + catch (Exception ex) + { + DefaultTrace.TraceWarning("Failed to refresh addresses in the background for the collection rid: {0} with exception: {1}. '{2}'", partitionKeyRangeIdentity.CollectionRid, - partitionKeyRangeIdentity.PartitionKeyRangeId, - forceRefresh: true))); + ex, + System.Diagnostics.Trace.CorrelationManager.ActivityId); + } + }); } return addresses; From ce38cc1b2213cb04972f3c64dea9bb19e14d5334 Mon Sep 17 00:00:00 2001 From: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:12:46 -0700 Subject: [PATCH 177/337] Documentation: Adds additional note for GetContactedRegions method (#4042) * Added small remark for GetContactedRegions method documentation * Moved to remarks --- Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs index ad568475df..a82ef2ecc2 100644 --- a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs @@ -80,6 +80,9 @@ public virtual int GetFailedRequestCount() /// Gets the list of all regions that were contacted for a request /// /// The list of tuples containing the Region name and the URI + /// + /// The returned list contains unique regions and doesn't guarantee ordering of the regions contacted from the first to the last + /// public abstract IReadOnlyList<(string regionName, Uri uri)> GetContactedRegions(); } } From 2257ca2fbe1f3bb5b4ca87ce9c93955c1ab480a1 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 22 Aug 2023 16:26:27 +0530 Subject: [PATCH 178/337] [Internal] Client Telemetry: Adds Client Telemetry pipeline sending data to service (#3900) * first draft * comment other pipelines * pint variables * commnet other pipelines * added env variable * minor changes * update env variable * print env variable * add space in end * fix test * fix tests * fix test * fix tests * remove response interceptor * logs * debuug mode * 3failing test to print llgs * minor refactoring * 2nd windows-2019 * fix ct tests * 2remove debugging * fix tests * revert * ncomment pipelines * fix test * minor changes * release and emulator pipeline * update pipelines * ignore abstract class test * fixing pipeline * refactor code * change it to class name to run tests * added emulator setup * 1 temp commit * env variable * renames env variable * fix tests * add condition * fix tests * reorder env variable * revert pipeline * did some clean up * change to revert * Revert "change to revert" This reverts commit 03db3c104505dc7b8f3cea267835c92ca530f8f4. * fix typos * throw if exception intercepter is null * remove modelling changes * removed virtaul * Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs Co-authored-by: Matias Quaranta * added condition for pipelines * Revert "added condition for pipelines" This reverts commit f9a208cd28e01badee97a2eb770a486cea67c1f0. * changed cond * fix codn * more enhancement * testing for release pipeline * refactore code and using test category * added comments on test * refactor pipeline code * fix variables * fix pipeline --------- Co-authored-by: Matias Quaranta --- .../ClientTelemetryReleaseTests.cs | 164 +++ .../ClientTelemetryTests.cs | 1078 +--------------- .../ClientTelemetryTestsBase.cs | 1087 +++++++++++++++++ .../Utils/HttpHandlerHelper.cs | 16 +- azure-pipelines-official.yml | 37 +- templates/build-test.yml | 6 +- 6 files changed, 1360 insertions(+), 1028 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs new file mode 100644 index 0000000000..d31c95bfe8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs @@ -0,0 +1,164 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Net.Http; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Fluent; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + /// + /// In Release pipeline, no need to mock Client Telemetry Service Call and Test will talk to the real database account. + /// If you are making changes in this file please make sure you are adding similar test in also. + /// + [TestClass] + [TestCategory("ClientTelemetryRelease")] + public class ClientTelemetryReleaseTests : ClientTelemetryTestsBase + { + public override CosmosClientBuilder GetBuilder() + { + string connectionString = ConfigurationManager.GetEnvironmentVariable("COSMOSDB_ACCOUNT_CONNECTION_STRING", null); + return new CosmosClientBuilder(connectionString: connectionString); + } + + /// + /// Returing null means do not return any hard codd response for any HTTP call. + /// + /// + /// + public override Task HttpHandlerRequestCallbackChecks(HttpRequestMessage request) + { + return null; + } + + [ClassInitialize] + public static new void ClassInitialize(TestContext context) + { + ClientTelemetryTestsBase.ClassInitialize(context); + + // It will go away in next PR + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "true"); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1"); + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "https://tools.cosmos.azure.com/api/clienttelemetry/trace"); + } + + [ClassCleanup] + public static new void FinalCleanup() + { + ClientTelemetryTestsBase.FinalCleanup(); + } + + [TestInitialize] + public override void TestInitialize() + { + base.TestInitialize(); + } + + [TestCleanup] + public override async Task Cleanup() + { + await base.Cleanup(); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct, true)] + [DataRow(ConnectionMode.Gateway, true)] + [DataRow(ConnectionMode.Direct, false)] + [DataRow(ConnectionMode.Gateway, false)] + public override async Task PointSuccessOperationsTest(ConnectionMode mode, bool isAzureInstance) + { + await base.PointSuccessOperationsTest(mode, isAzureInstance); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task PointReadFailureOperationsTest(ConnectionMode mode) + { + await base.PointReadFailureOperationsTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task StreamReadFailureOperationsTest(ConnectionMode mode) + { + await base.StreamReadFailureOperationsTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task StreamOperationsTest(ConnectionMode mode) + { + await base.StreamOperationsTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task BatchOperationsTest(ConnectionMode mode) + { + await base.BatchOperationsTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task SingleOperationMultipleTimesTest(ConnectionMode mode) + { + await base.SingleOperationMultipleTimesTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task QueryOperationSinglePartitionTest(ConnectionMode mode) + { + await base.QueryOperationSinglePartitionTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task QueryMultiPageSinglePartitionOperationTest(ConnectionMode mode) + { + await base.QueryMultiPageSinglePartitionOperationTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task QueryOperationCrossPartitionTest(ConnectionMode mode) + { + await base.QueryOperationCrossPartitionTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task QueryOperationMutiplePageCrossPartitionTest(ConnectionMode mode) + { + await base.QueryOperationMutiplePageCrossPartitionTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + [DataRow(ConnectionMode.Gateway)] + public override async Task QueryOperationInvalidContinuationTokenTest(ConnectionMode mode) + { + await base.QueryOperationInvalidContinuationTokenTest(mode); + } + + [TestMethod] + [DataRow(ConnectionMode.Direct)] + public override async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) + { + await base.CreateItemWithSubStatusCodeTest(mode); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 30edc7ebf7..2ffc60f5f4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -4,1121 +4,155 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { - using System; - using System.Collections.Generic; - using System.Text; - using System.Threading.Tasks; - using System.Net; - using System.Net.Http; - using System.Reflection; using Microsoft.Azure.Cosmos.Fluent; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Telemetry; - using Microsoft.Azure.Cosmos.Handler; - using Microsoft.Azure.Documents; - using Newtonsoft.Json.Linq; - using Newtonsoft.Json; - using Documents.Rntbd; - using System.Globalization; - using System.Linq; - using Cosmos.Util; - using Microsoft.Azure.Cosmos.Telemetry.Models; + using System.Net.Http; + using System.Net; + using System.Threading.Tasks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + /// + /// In Emulator Mode, Run test against emulator and mock client telemetry service calls. + /// If you are making changes in this file please make sure you are adding similar test in also. + /// [TestClass] - public class ClientTelemetryTests : BaseCosmosClientHelper + [TestCategory("ClientTelemetryEmulator")] + public class ClientTelemetryTests : ClientTelemetryTestsBase { - private const int scheduledInSeconds = 1; - private static readonly object jsonObject = JsonConvert.DeserializeObject("{\"compute\":{\"azEnvironment\":\"AzurePublicCloud\",\"customData\":\"\",\"isHostCompatibilityLayerVm\":\"false\",\"licenseType\":\"\",\"location\":\"eastus\",\"name\":\"sourabh-testing\",\"offer\":\"UbuntuServer\",\"osProfile\":{\"adminUsername\":\"azureuser\",\"computerName\":\"sourabh-testing\"},\"osType\":\"Linux\",\"placementGroupId\":\"\",\"plan\":{\"name\":\"\",\"product\":\"\",\"publisher\":\"\"},\"platformFaultDomain\":\"0\",\"platformUpdateDomain\":\"0\",\"provider\":\"Microsoft.Compute\",\"publicKeys\":[{\"keyData\":\"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC5uCeOAm3ehmhI+2PbMoMl17Eo\r\nqfHKCycSaBJsv9qxlmBOuFheSJc1XknJleXUSsuTO016/d1PyWpevnqOZNRksWoa\r\nJvQ23sDTxcK+X2OP3QlCUeX4cMjPXqlL8z1UYzU4Bx3fFvf8fs67G3N72sxWBw5P\r\nZyuXyhBm0NCe/2NYMKgEDT4ma8XszO0ikbhoPKbMbgHAQk/ktWQHNcqYOPQKEWqp\r\nEK1R0rjS2nmtovfScP/ZGXcvOpJ1/NDBo4dh1K+OxOGM/4PSH/F448J5Zy4eAyEk\r\nscys+IpeIOTOlRUy/703SNIX0LEWlnYqbyL9c1ypcYLQqF76fKkDfzzFI/OWVlGw\r\nhj/S9uP8iMsR+fhGIbn6MAa7O4DWPWLuedSp7KDYyjY09gqNJsfuaAJN4LiC6bPy\r\nhknm0PVLK3ux7EUOt+cZrHCdIFWbdOtxiPNIl1tkv9kV5aE5Aj2gJm4MeB9uXYhS\r\nOuksboBc0wyUGrl9+XZJ1+NlZOf7IjVi86CieK8= generated-by-azure\r\n\",\"path\":\"/home/azureuser/.ssh/authorized_keys\"}],\"publisher\":\"Canonical\",\"resourceGroupName\":\"sourabh-telemetry-sdk\",\"resourceId\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/virtualMachines/sourabh-testing\",\"securityProfile\":{\"secureBootEnabled\":\"false\",\"virtualTpmEnabled\":\"false\"},\"sku\":\"18.04-LTS\",\"storageProfile\":{\"dataDisks\":[],\"imageReference\":{\"id\":\"\",\"offer\":\"UbuntuServer\",\"publisher\":\"Canonical\",\"sku\":\"18.04-LTS\",\"version\":\"latest\"},\"osDisk\":{\"caching\":\"ReadWrite\",\"createOption\":\"FromImage\",\"diffDiskSettings\":{\"option\":\"\"},\"diskSizeGB\":\"30\",\"encryptionSettings\":{\"enabled\":\"false\"},\"image\":{\"uri\":\"\"},\"managedDisk\":{\"id\":\"/subscriptions/8fba6d4f-7c37-4d13-9063-fd58ad2b86e2/resourceGroups/sourabh-telemetry-sdk/providers/Microsoft.Compute/disks/sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"storageAccountType\":\"Premium_LRS\"},\"name\":\"sourabh-testing_OsDisk_1_9a54abfc5ba149c6a106bd9e5b558c2a\",\"osType\":\"Linux\",\"vhd\":{\"uri\":\"\"},\"writeAcceleratorEnabled\":\"false\"}},\"subscriptionId\":\"8fba6d4f-7c37-4d13-9063-fd58ad2b86e2\",\"tags\":\"azsecpack:nonprod;platformsettings.host_environment.service.platform_optedin_for_rootcerts:true\",\"tagsList\":[{\"name\":\"azsecpack\",\"value\":\"nonprod\"},{\"name\":\"platformsettings.host_environment.service.platform_optedin_for_rootcerts\",\"value\":\"true\"}],\"version\":\"18.04.202103250\",\"vmId\":\"d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd\",\"vmScaleSetName\":\"\",\"vmSize\":\"Standard_D2s_v3\",\"zone\":\"1\"},\"network\":{\"interface\":[{\"ipv4\":{\"ipAddress\":[{\"privateIpAddress\":\"10.0.7.5\",\"publicIpAddress\":\"\"}],\"subnet\":[{\"address\":\"10.0.7.0\",\"prefix\":\"24\"}]},\"ipv6\":{\"ipAddress\":[]},\"macAddress\":\"000D3A8F8BA0\"}]}}"); - - private CosmosClientBuilder cosmosClientBuilder; - private static SystemUsageMonitor systemUsageMonitor; - - private List actualInfo; - private List preferredRegionList; + public override Task HttpHandlerRequestCallbackChecks(HttpRequestMessage request) + { + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NoContent)); // In Emulator test, send hardcoded response status code as there is no real communication happens with client telemetry service + } - private IDictionary expectedMetricNameUnitMap; + return null; + } - private HttpClientHandlerHelper httpHandler; - private HttpClientHandlerHelper httpHandlerForNonAzureInstance; + public override CosmosClientBuilder GetBuilder() + { + return TestCommon.GetDefaultConfiguration(); + } [ClassInitialize] - public static void ClassInitialize(TestContext _) + public static new void ClassInitialize(TestContext context) { - SystemUsageMonitor oldSystemUsageMonitor = (SystemUsageMonitor)typeof(DiagnosticsHandlerHelper) - .GetField("systemUsageMonitor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DiagnosticsHandlerHelper.Instance); - oldSystemUsageMonitor.Stop(); - - ClientTelemetryTests.ResetSystemUsageMonitor(true); + ClientTelemetryTestsBase.ClassInitialize(context); } - [TestInitialize] - public void TestInitialize() + [ClassCleanup] + public static new void FinalCleanup() { - Util.EnableClientTelemetryEnvironmentVariables(); - - this.actualInfo = new List(); - - this.httpHandler = new HttpClientHandlerHelper - { - RequestCallBack = (request, cancellation) => - { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); - - string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - - lock (this.actualInfo) - { - this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); - } - - return Task.FromResult(result); - } - else if (request.RequestUri.AbsoluteUri.Equals(VmMetadataApiHandler.vmMetadataEndpointUrl.AbsoluteUri)) - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); - - string payload = JsonConvert.SerializeObject(ClientTelemetryTests.jsonObject); - result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); - - return Task.FromResult(result); - } - return null; - } - }; - - this.httpHandlerForNonAzureInstance = new HttpClientHandlerHelper - { - RequestCallBack = (request, cancellation) => - { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); - - string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - - lock (this.actualInfo) - { - this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); - } - - return Task.FromResult(result); - } - return null; - } - }; - - this.preferredRegionList = new List - { - "region1", - "region2" - }; - - this.expectedMetricNameUnitMap = new Dictionary() - { - { ClientTelemetryOptions.CpuName, ClientTelemetryOptions.CpuUnit }, - { ClientTelemetryOptions.MemoryName, ClientTelemetryOptions.MemoryUnit }, - { ClientTelemetryOptions.AvailableThreadsName, ClientTelemetryOptions.AvailableThreadsUnit }, - { ClientTelemetryOptions.IsThreadStarvingName, ClientTelemetryOptions.IsThreadStarvingUnit }, - { ClientTelemetryOptions.ThreadWaitIntervalInMsName, ClientTelemetryOptions.ThreadWaitIntervalInMsUnit } - }; - - this.cosmosClientBuilder = TestCommon.GetDefaultConfiguration() - .WithApplicationPreferredRegions(this.preferredRegionList); + ClientTelemetryTestsBase.FinalCleanup(); } - private static void ResetSystemUsageMonitor(bool isTelemetryEnabled) + [TestInitialize] + public override void TestInitialize() { - ClientTelemetryTests.systemUsageMonitor?.Stop(); - - FieldInfo diagnosticsHandlerHelperInstance = typeof(DiagnosticsHandlerHelper) - .GetField("isTelemetryMonitoringEnabled", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); - diagnosticsHandlerHelperInstance.SetValue(null, isTelemetryEnabled); - - List recorders = new List() - { - (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) - .GetField("diagnosticSystemUsageRecorder", - BindingFlags.Instance | BindingFlags.NonPublic) - .GetValue(DiagnosticsHandlerHelper.Instance) - }; - - if (isTelemetryEnabled) - { - recorders.Add( - (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) - .GetField("telemetrySystemUsageRecorder", - BindingFlags.Instance | BindingFlags.NonPublic) - .GetValue(DiagnosticsHandlerHelper.Instance)); - } - - ClientTelemetryTests.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(recorders); + base.TestInitialize(); } [TestCleanup] - public async Task Cleanup() + public override async Task Cleanup() { - FieldInfo isInitializedField = typeof(VmMetadataApiHandler).GetField("isInitialized", - BindingFlags.Static | - BindingFlags.NonPublic); - isInitializedField.SetValue(null, false); - - FieldInfo azMetadataField = typeof(VmMetadataApiHandler).GetField("azMetadata", - BindingFlags.Static | - BindingFlags.NonPublic); - azMetadataField.SetValue(null, null); - - await base.TestCleanup(); - - Util.DisableClientTelemetryEnvironmentVariables(); + await base.Cleanup(); } - [ClassCleanup] - public static void FinalCleanup() - { - ClientTelemetryTests.ResetSystemUsageMonitor(false); - } - [TestMethod] [DataRow(ConnectionMode.Direct, true)] [DataRow(ConnectionMode.Gateway, true)] [DataRow(ConnectionMode.Direct, false)] [DataRow(ConnectionMode.Gateway, false)] - public async Task PointSuccessOperationsTest(ConnectionMode mode, bool isAzureInstance) + public override async Task PointSuccessOperationsTest(ConnectionMode mode, bool isAzureInstance) { - Container container = await this.CreateClientAndContainer( - mode: mode, - isAzureInstance: isAzureInstance); - - // Create an item - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); - ItemResponse createResponse = await container.CreateItemAsync(testItem); - ToDoActivity testItemCreated = createResponse.Resource; - - // Read an Item - await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - // Upsert an Item - await container.UpsertItemAsync(testItem); - - // Replace an Item - await container.ReplaceItemAsync(testItemCreated, testItemCreated.id.ToString()); - - // Patch an Item - List patch = new List() - { - PatchOperation.Add("/new", "patched") - }; - await ((ContainerInternal)container).PatchItemAsync( - testItem.id, - new Cosmos.PartitionKey(testItem.id), - patch); - - // Delete an Item - await container.DeleteItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Create.ToString(), 1}, - { Documents.OperationType.Upsert.ToString(), 1}, - { Documents.OperationType.Read.ToString(), 1}, - { Documents.OperationType.Replace.ToString(), 1}, - { Documents.OperationType.Patch.ToString(), 1}, - { Documents.OperationType.Delete.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 12, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - isAzureInstance: isAzureInstance); + await base.PointSuccessOperationsTest(mode, isAzureInstance); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task PointReadFailureOperationsTest(ConnectionMode mode) + public override async Task PointReadFailureOperationsTest(ConnectionMode mode) { - // Fail Read - try - { - Container container = await this.CreateClientAndContainer(mode, Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); - - await container.ReadItemAsync( - new Guid().ToString(), - new Cosmos.PartitionKey(new Guid().ToString()), - new ItemRequestOptions() - { - BaseConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual // overriding client level consistency - }); - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.NotFound) - { - string message = ce.ToString(); - Assert.IsNotNull(message); - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Read.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 2, - expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedCacheSource: null, - isExpectedNetworkTelemetry: false); + await base.PointReadFailureOperationsTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task StreamReadFailureOperationsTest(ConnectionMode mode) + public override async Task StreamReadFailureOperationsTest(ConnectionMode mode) { - Container container = await this.CreateClientAndContainer(mode); - - // Fail Read - try - { - await container.ReadItemStreamAsync( - new Guid().ToString(), - new Cosmos.PartitionKey(new Guid().ToString()), - new ItemRequestOptions() - { - BaseConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix // Request level consistency - }); - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.NotFound) - { - string message = ce.ToString(); - Assert.IsNotNull(message); - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Read.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 2, - expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedCacheSource: null, - isExpectedNetworkTelemetry: false); + await base.StreamReadFailureOperationsTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task StreamOperationsTest(ConnectionMode mode) + public override async Task StreamOperationsTest(ConnectionMode mode) { - Container container = await this.CreateClientAndContainer(mode); - - // Create an item - var testItem = new { id = "MyTestItemId", partitionKeyPath = "MyTestPkValue", details = "it's working", status = "done" }; - await container - .CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), - new Cosmos.PartitionKey(testItem.id)); - - //Upsert an Item - await container.UpsertItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), new Cosmos.PartitionKey(testItem.id)); - - //Read an Item - await container.ReadItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - //Replace an Item - await container.ReplaceItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), testItem.id, new Cosmos.PartitionKey(testItem.id)); - - // Patch an Item - List patch = new List() - { - PatchOperation.Add("/new", "patched") - }; - await ((ContainerInternal)container).PatchItemStreamAsync( - partitionKey: new Cosmos.PartitionKey(testItem.id), - id: testItem.id, - patchOperations: patch); - - //Delete an Item - await container.DeleteItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Create.ToString(), 1}, - { Documents.OperationType.Upsert.ToString(), 1}, - { Documents.OperationType.Read.ToString(), 1}, - { Documents.OperationType.Replace.ToString(), 1}, - { Documents.OperationType.Patch.ToString(), 1}, - { Documents.OperationType.Delete.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 12, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedCacheSource: null); + await base.StreamOperationsTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task BatchOperationsTest(ConnectionMode mode) + public override async Task BatchOperationsTest(ConnectionMode mode) { - Container container = await this.CreateClientAndContainer(mode, Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual); // Client level consistency - using (BatchAsyncContainerExecutor executor = - new BatchAsyncContainerExecutor( - (ContainerInlineCore)container, - ((ContainerInlineCore)container).ClientContext, - 20, - Documents.Constants.MaxDirectModeBatchRequestBodySizeInBytes) - ) - { - List> tasks = new List>(); - for (int i = 0; i < 10; i++) - { - tasks.Add(executor.AddAsync(CreateItem(i.ToString()), NoOpTrace.Singleton, default)); - } - - await Task.WhenAll(tasks); - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Batch.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 2, - expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual, - expectedOperationRecordCountMap: expectedRecordCountInOperation); + await base.BatchOperationsTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task SingleOperationMultipleTimesTest(ConnectionMode mode) + public override async Task SingleOperationMultipleTimesTest(ConnectionMode mode) { - Container container = await this.CreateClientAndContainer(mode); - - // Create an item - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); - - await container.CreateItemAsync(testItem, requestOptions: new ItemRequestOptions()); - - for (int count = 0; count < 50; count++) - { - // Read an Item - await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Read.ToString(), 50}, - { Documents.OperationType.Create.ToString(), 1} - }; - - await this.WaitAndAssert( - expectedOperationCount: 4,// 2 (read, requetLatency + requestCharge) + 2 (create, requestLatency + requestCharge) - expectedOperationRecordCountMap: expectedRecordCountInOperation); + await base.SingleOperationMultipleTimesTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task QueryOperationSinglePartitionTest(ConnectionMode mode) + public override async Task QueryOperationSinglePartitionTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - - Container container = await this.CreateClientAndContainer(mode); - - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue", "MyTestItemId"); - ItemRequestOptions requestOptions = new ItemRequestOptions() - { - ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix - }; - - ItemResponse createResponse = await container.CreateItemAsync( - item: testItem, - requestOptions: requestOptions); - - QueryRequestOptions queryRequestOptions = new QueryRequestOptions() - { - ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, - }; - - List families = new List(); - if (createResponse.StatusCode == HttpStatusCode.Created) - { - string sqlQueryText = "SELECT * FROM c"; - - QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); - using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( - queryDefinition: queryDefinition, - requestOptions: queryRequestOptions)) - { - while (queryResultSetIterator.HasMoreResults) - { - FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); - foreach (object family in currentResultSet) - { - families.Add(family); - } - } - } - - Assert.AreEqual(1, families.Count); - - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Query.ToString(), 1}, - { Documents.OperationType.Create.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 4, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); + await base.QueryOperationSinglePartitionTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task QueryMultiPageSinglePartitionOperationTest(ConnectionMode mode) + public override async Task QueryMultiPageSinglePartitionOperationTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - Container container = await this.CreateClientAndContainer(mode: mode); - - ItemRequestOptions requestOptions = new ItemRequestOptions() - { - ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix - }; - - ToDoActivity testItem1 = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue1", "MyTestItemId1"); - ItemResponse createResponse1 = await container.CreateItemAsync( - item: testItem1, - requestOptions: requestOptions); - ToDoActivity testItem2 = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue2", "MyTestItemId2"); - ItemResponse createResponse2 = await container.CreateItemAsync( - item: testItem2, - requestOptions: requestOptions); - - if (createResponse1.StatusCode == HttpStatusCode.Created && - createResponse2.StatusCode == HttpStatusCode.Created) - { - string sqlQueryText = "SELECT * FROM c"; - - List families = new List(); - QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); - using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( - queryDefinition: queryDefinition, - requestOptions: new QueryRequestOptions() - { - ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, - MaxItemCount = 1 - })) - { - while (queryResultSetIterator.HasMoreResults) - { - FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); - foreach (object family in currentResultSet) - { - families.Add(family); - } - } - } - - Assert.AreEqual(2, families.Count); - - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Query.ToString(), 3}, - { Documents.OperationType.Create.ToString(), 2} - }; - - await this.WaitAndAssert( - expectedOperationCount: 4, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); + await base.QueryMultiPageSinglePartitionOperationTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task QueryOperationCrossPartitionTest(ConnectionMode mode) + public override async Task QueryOperationCrossPartitionTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - - ContainerInternal itemsCore = (ContainerInternal)await this.CreateClientAndContainer( - mode: mode, - isLargeContainer: true); - - // Verify container has multiple partitions - int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; - Assert.IsTrue(pkRangesCount > 1, "Should have created a multi partition container."); - - Container container = (Container)itemsCore; - - await ToDoActivity.CreateRandomItems( - container: container, - pkCount: 2, - perPKItemCount: 5); - - string sqlQueryText = "SELECT * FROM c"; - - List families = new List(); - - QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); - using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator(queryDefinition)) - { - while (queryResultSetIterator.HasMoreResults) - { - FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); - foreach (object family in currentResultSet) - { - families.Add(family); - } - } - } - - Assert.AreEqual(10, families.Count); - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Query.ToString(), pkRangesCount}, - { Documents.OperationType.Create.ToString(), 10} - }; - - await this.WaitAndAssert( - expectedOperationCount: 4, - expectedOperationRecordCountMap: expectedRecordCountInOperation); + await base.QueryOperationCrossPartitionTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task QueryOperationMutiplePageCrossPartitionTest(ConnectionMode mode) + public override async Task QueryOperationMutiplePageCrossPartitionTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - - ContainerInternal itemsCore = (ContainerInternal)await this.CreateClientAndContainer( - mode: mode, - isLargeContainer: true); - - // Verify container has multiple partitions - int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; - Assert.IsTrue(pkRangesCount > 1, "Should have created a multi partition container."); - - Container container = (Container)itemsCore; - - await ToDoActivity.CreateRandomItems( - container: container, - pkCount: 2, - perPKItemCount: 5); - - string sqlQueryText = "SELECT * FROM c"; - - List families = new List(); - QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); - using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( - queryDefinition: queryDefinition, - requestOptions: new QueryRequestOptions() - { - MaxItemCount = 1 - })) - { - while (queryResultSetIterator.HasMoreResults) - { - FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); - foreach (object family in currentResultSet) - { - families.Add(family); - } - } - } - - Assert.AreEqual(10, families.Count); - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Query.ToString(), pkRangesCount + 10}, // 10 is number of items - { Documents.OperationType.Create.ToString(), 10} - }; - - await this.WaitAndAssert( - expectedOperationCount: 4, - expectedOperationRecordCountMap: expectedRecordCountInOperation); + await base.QueryOperationMutiplePageCrossPartitionTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] [DataRow(ConnectionMode.Gateway)] - public async Task QueryOperationInvalidContinuationTokenTest(ConnectionMode mode) + public override async Task QueryOperationInvalidContinuationTokenTest(ConnectionMode mode) { - Container container = await this.CreateClientAndContainer(mode); - - // Create an item : First successful request to load Cache - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); - await container.CreateItemAsync(testItem); - - List results = new List(); - using (FeedIterator resultSetIterator = container.GetItemQueryIterator( - "SELECT * FROM c", - continuationToken: "dummy token")) - { - try - { - while (resultSetIterator.HasMoreResults) - { - FeedResponse response = await resultSetIterator.ReadNextAsync(); - results.AddRange(response); - } - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.BadRequest) - { - string message = ce.ToString(); - Assert.IsNotNull(message); - } - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Create.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 2, - expectedOperationRecordCountMap: expectedRecordCountInOperation); + await base.QueryOperationInvalidContinuationTokenTest(mode); } [TestMethod] [DataRow(ConnectionMode.Direct)] - public async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) + public override async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) { - HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper(); - HttpClient httpClient = new HttpClient(httpHandler); - - httpHandler.RequestCallBack = (request, cancellation) => - { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); - - string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - - lock (this.actualInfo) - { - this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); - } - - return Task.FromResult(result); - } - else if (request.RequestUri.AbsoluteUri.Equals(VmMetadataApiHandler.vmMetadataEndpointUrl.AbsoluteUri)) - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); - - string payload = JsonConvert.SerializeObject(ClientTelemetryTests.jsonObject); - result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); - - return Task.FromResult(result); - } - else if (request.Method == HttpMethod.Get && request.RequestUri.AbsolutePath == "//addresses/") - { - HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Forbidden); - - // Add a substatus code that is not part of the enum. - // This ensures that if the backend adds a enum the status code is not lost. - result.Headers.Add(WFConstants.BackendHeaders.SubStatus, 999999.ToString(CultureInfo.InvariantCulture)); - - string payload = JsonConvert.SerializeObject(new Error() { Message = "test message" }); - result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); - - return Task.FromResult(result); - } - - return null; - }; - - // Replacing originally initialized cosmos Builder with this one with new handler - this.cosmosClientBuilder = this.cosmosClientBuilder - .WithHttpClientFactory(() => new HttpClient(httpHandler)); - - Container container = await this.CreateClientAndContainer( - mode: mode, - customHttpHandler: httpHandler); - try - { - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); - ItemResponse createResponse = await container.CreateItemAsync(testItem); - Assert.Fail("Request should throw exception."); - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.Forbidden) - { - Assert.AreEqual(999999, ce.SubStatusCode); - } - - IDictionary expectedRecordCountInOperation = new Dictionary - { - { Documents.OperationType.Create.ToString(), 1} - }; - - await this.WaitAndAssert(expectedOperationCount: 2, - expectedOperationRecordCountMap: expectedRecordCountInOperation, - expectedSubstatuscode: 999999, - isExpectedNetworkTelemetry: false); - + await base.CreateItemWithSubStatusCodeTest(mode); } - - /// - /// This method wait for the expected operations to get recorded by telemetry and assert the values - /// - /// Expected number of unique OperationInfo irrespective of response size. - /// Expected Consistency level of the operation recorded by telemetry - /// Expected number of requests recorded for each operation - /// - private async Task WaitAndAssert( - int expectedOperationCount = 0, - Microsoft.Azure.Cosmos.ConsistencyLevel? expectedConsistencyLevel = null, - IDictionary expectedOperationRecordCountMap = null, - int expectedSubstatuscode = 0, - bool? isAzureInstance = null, - string expectedCacheSource = "ClientCollectionCache", - bool isExpectedNetworkTelemetry = true) - { - Assert.IsNotNull(this.actualInfo, "Telemetry Information not available"); - - // As this feature is thread based execution so wait for the results to avoid test flakiness - List localCopyOfActualInfo = null; - ValueStopwatch stopwatch = ValueStopwatch.StartNew(); - - HashSet cacheRefreshInfoSet = new HashSet(); - do - { - await Task.Delay(TimeSpan.FromMilliseconds(1500)); // wait at least for 1 round of telemetry - - HashSet actualOperationSet = new HashSet(); - HashSet requestInfoSet = new HashSet(); - - lock (this.actualInfo) - { - // Setting the number of unique OperationInfo irrespective of response size as response size is varying in case of queries. - this.actualInfo - .ForEach(x => - { - if (x.CacheRefreshInfo != null && x.CacheRefreshInfo.Count > 0) - { - x.CacheRefreshInfo - .ForEach(y => - { - y.GreaterThan1Kb = false; - cacheRefreshInfoSet.Add(y); - }); - - } - - x.OperationInfo - .ForEach(y => - { - y.GreaterThan1Kb = false; - actualOperationSet.Add(y); - }); - }); - - if (actualOperationSet.Count == expectedOperationCount / 2) - { - // Copy the list to avoid it being modified while validating - localCopyOfActualInfo = new List(this.actualInfo); - break; - } - - Assert.IsTrue(stopwatch.Elapsed.TotalMinutes < 1, $"The expected operation count({expectedOperationCount}) was never hit, Actual Operation Count is {actualOperationSet.Count}. ActualInfo:{JsonConvert.SerializeObject(this.actualInfo)}"); - } - } - while (localCopyOfActualInfo == null); - - List actualOperationList = new List(); - List actualSystemInformation = new List(); - List actualRequestInformation = new List(); - - if (localCopyOfActualInfo[0].ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) - { - this.expectedMetricNameUnitMap.Add(ClientTelemetryOptions.NumberOfTcpConnectionName, ClientTelemetryOptions.NumberOfTcpConnectionUnit); - } - - ClientTelemetryTests.AssertAccountLevelInformation( - localCopyOfActualInfo: localCopyOfActualInfo, - actualOperationList: actualOperationList, - actualSystemInformation: actualSystemInformation, - actualRequestInformation: actualRequestInformation, - isAzureInstance: isAzureInstance); - - ClientTelemetryTests.AssertOperationLevelInformation( - expectedConsistencyLevel: expectedConsistencyLevel, - expectedOperationRecordCountMap: expectedOperationRecordCountMap, - actualOperationList: actualOperationList, - expectedSubstatuscode: expectedSubstatuscode); - - if(!string.IsNullOrEmpty(expectedCacheSource)) - { - Assert.IsTrue(cacheRefreshInfoSet.Count > 0, "Cache Refresh Information is not there"); - - ClientTelemetryTests.AssertCacheRefreshInfoInformation( - cacheRefreshInfoSet: cacheRefreshInfoSet, - expectedCacheSource: expectedCacheSource); - } - - ClientTelemetryTests.AssertSystemLevelInformation(actualSystemInformation, this.expectedMetricNameUnitMap); - if (localCopyOfActualInfo.First().ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant() - && isExpectedNetworkTelemetry) - { - ClientTelemetryTests.AssertNetworkLevelInformation(actualRequestInformation); - } - else - { - Assert.IsTrue(actualRequestInformation == null || actualRequestInformation.Count == 0, "Request Information is not expected in Gateway mode"); - } - } - - private static void AssertNetworkLevelInformation(List actualRequestInformation) - { - Assert.IsNotNull(actualRequestInformation); - Assert.IsTrue(actualRequestInformation.Count > 0); - - foreach(RequestInfo requestInfo in actualRequestInformation) - { - Assert.IsNotNull(requestInfo.Uri); - Assert.IsNotNull(requestInfo.DatabaseName); - Assert.IsNotNull(requestInfo.ContainerName); - Assert.IsNotNull(requestInfo.Operation); - Assert.IsNotNull(requestInfo.Resource); - Assert.IsNotNull(requestInfo.StatusCode); - Assert.AreNotEqual(0, requestInfo.StatusCode); - Assert.IsNotNull(requestInfo.SubStatusCode); - - Assert.IsNotNull(requestInfo.Metrics, "MetricInfo is null"); - } - } - - private static void AssertSystemLevelInformation(List actualSystemInformation, IDictionary expectedMetricNameUnitMap) - { - IDictionary actualMetricNameUnitMap = new Dictionary(); - - // Asserting If system information list is as expected - foreach (SystemInfo systemInfo in actualSystemInformation) - { - Assert.AreEqual("HostMachine", systemInfo.Resource); - Assert.IsNotNull(systemInfo.MetricInfo, "MetricInfo is null"); - - if(!actualMetricNameUnitMap.TryAdd(systemInfo.MetricInfo.MetricsName, systemInfo.MetricInfo.UnitName)) - { - Assert.AreEqual(systemInfo.MetricInfo.UnitName, actualMetricNameUnitMap[systemInfo.MetricInfo.MetricsName]); - } - - if(!systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.IsThreadStarvingName) && - !systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.ThreadWaitIntervalInMsName)) - { - Assert.IsTrue(systemInfo.MetricInfo.Count > 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Count is not greater than 0"); - Assert.IsNotNull(systemInfo.MetricInfo.Percentiles, $"Percentiles is null for metrics ({systemInfo.MetricInfo.MetricsName})"); - } - Assert.IsTrue(systemInfo.MetricInfo.Mean >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Mean is not greater than or equal to 0"); - Assert.IsTrue(systemInfo.MetricInfo.Max >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Max is not greater than or equal to 0"); - Assert.IsTrue(systemInfo.MetricInfo.Min >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Min is not greater than or equal to 0"); - if (systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.CpuName)) - { - Assert.IsTrue(systemInfo.MetricInfo.Mean <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Mean is not greater than 100 for CPU Usage"); - Assert.IsTrue(systemInfo.MetricInfo.Max <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Max is not greater than 100 for CPU Usage"); - Assert.IsTrue(systemInfo.MetricInfo.Min <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Min is not greater than 100 for CPU Usage"); - }; - } - - Assert.IsTrue(expectedMetricNameUnitMap.EqualsTo(actualMetricNameUnitMap), $"Actual System Information metric i.e {string.Join(", ", actualMetricNameUnitMap)} is not matching with expected System Information Metric i.e. {string.Join(", ", expectedMetricNameUnitMap)}"); - - } - - private static void AssertOperationLevelInformation( - Microsoft.Azure.Cosmos.ConsistencyLevel? expectedConsistencyLevel, - IDictionary expectedOperationRecordCountMap, - List actualOperationList, - int expectedSubstatuscode = 0) - { - IDictionary actualOperationRecordCountMap = new Dictionary(); - // Asserting If operation list is as expected - foreach (OperationInfo operation in actualOperationList) - { - Assert.IsNotNull(operation.Operation, "Operation Type is null"); - Assert.IsNotNull(operation.Resource, "Resource Type is null"); - - Assert.AreEqual(expectedSubstatuscode, operation.SubStatusCode); - Assert.AreEqual(expectedConsistencyLevel?.ToString(), operation.Consistency, $"Consistency is not {expectedConsistencyLevel}"); - - Assert.IsNotNull(operation.MetricInfo, "MetricInfo is null"); - Assert.IsNotNull(operation.MetricInfo.MetricsName, "MetricsName is null"); - Assert.IsNotNull(operation.MetricInfo.UnitName, "UnitName is null"); - Assert.IsNotNull(operation.MetricInfo.Percentiles, "Percentiles is null"); - Assert.IsTrue(operation.MetricInfo.Count > 0, "MetricInfo Count is not greater than 0"); - Assert.IsTrue(operation.MetricInfo.Mean >= 0, "MetricInfo Mean is not greater than or equal to 0"); - Assert.IsTrue(operation.MetricInfo.Max >= 0, "MetricInfo Max is not greater than or equal to 0"); - Assert.IsTrue(operation.MetricInfo.Min >= 0, "MetricInfo Min is not greater than or equal to 0"); - if (operation.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.RequestLatencyName)) // putting this condition to avoid doubling of count as we have same information for each metrics - { - if (!actualOperationRecordCountMap.TryGetValue(operation.Operation.ToString(), out long recordCount)) - { - actualOperationRecordCountMap.Add(operation.Operation.ToString(), operation.MetricInfo.Count); - } - else - { - actualOperationRecordCountMap.Remove(operation.Operation.ToString()); - actualOperationRecordCountMap.Add(operation.Operation.ToString(), recordCount + operation.MetricInfo.Count); - } - } - } - - if (expectedOperationRecordCountMap != null) - { - Assert.IsTrue(expectedOperationRecordCountMap.EqualsTo(actualOperationRecordCountMap), $"actual record i.e. ({actualOperationRecordCountMap}) for operation does not match with expected record i.e. ({expectedOperationRecordCountMap})"); - } - } - - private static void AssertAccountLevelInformation( - List localCopyOfActualInfo, - List actualOperationList, - List actualSystemInformation, - List actualRequestInformation, - bool? isAzureInstance) - { - ISet machineId = new HashSet(); - - // Asserting If basic client telemetry object is as expected - foreach (ClientTelemetryProperties telemetryInfo in localCopyOfActualInfo) - { - if (telemetryInfo.OperationInfo != null) - { - actualOperationList.AddRange(telemetryInfo.OperationInfo); - } - - if (telemetryInfo.SystemInfo != null) - { - foreach (SystemInfo sysInfo in telemetryInfo.SystemInfo) - { - actualSystemInformation.Add(sysInfo); - } - } - - if (telemetryInfo.RequestInfo != null) - { - actualRequestInformation.AddRange(telemetryInfo.RequestInfo); - } - - if (telemetryInfo.ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) - { - Assert.AreEqual(6, telemetryInfo.SystemInfo.Count, $"System Information Count doesn't Match; {JsonConvert.SerializeObject(telemetryInfo.SystemInfo)}"); - } - else - { - Assert.AreEqual(5, telemetryInfo.SystemInfo.Count, $"System Information Count doesn't Match; {JsonConvert.SerializeObject(telemetryInfo.SystemInfo)}"); - } - - Assert.IsNotNull(telemetryInfo.GlobalDatabaseAccountName, "GlobalDatabaseAccountName is null"); - Assert.IsNotNull(telemetryInfo.DateTimeUtc, "Timestamp is null"); - Assert.AreEqual(2, telemetryInfo.PreferredRegions.Count); - Assert.AreEqual("region1", telemetryInfo.PreferredRegions[0]); - Assert.AreEqual("region2", telemetryInfo.PreferredRegions[1]); - Assert.AreEqual(1, telemetryInfo.AggregationIntervalInSec); - Assert.IsNull(telemetryInfo.AcceleratedNetworking); - Assert.IsNotNull(telemetryInfo.ClientId); - Assert.IsNotNull(telemetryInfo.ProcessId); - Assert.AreEqual(HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), telemetryInfo.ProcessId); - Assert.IsNotNull(telemetryInfo.UserAgent); - Assert.IsFalse(telemetryInfo.UserAgent.Contains("userAgentSuffix"), "Useragent should not have suffix appended"); // Useragent should not contain useragentsuffix as it can have PII - Assert.IsNotNull(telemetryInfo.ConnectionMode); - - if(!string.IsNullOrEmpty(telemetryInfo.MachineId)) - { - machineId.Add(telemetryInfo.MachineId); - } - } - - if(isAzureInstance.HasValue) - { - if (isAzureInstance.Value) - { - Assert.AreEqual($"{VmMetadataApiHandler.VmIdPrefix}{"d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd"}", machineId.First(), $"Generated Machine id is : {machineId.First()}"); - } - else - { - Assert.AreNotEqual($"{VmMetadataApiHandler.VmIdPrefix}{"d0cb93eb-214b-4c2b-bd3d-cc93e90d9efd"}", machineId.First(), $"Generated Machine id is : {machineId.First()}"); - Assert.AreEqual(1, machineId.Count, $"Multiple Machine Id has been generated i.e {JsonConvert.SerializeObject(machineId)}"); - } - } - } - - - private static void AssertCacheRefreshInfoInformation( - HashSet cacheRefreshInfoSet, - string expectedCacheSource) - { - foreach(CacheRefreshInfo cacheRefreshInfo in cacheRefreshInfoSet) - { - Assert.IsNotNull(cacheRefreshInfo.CacheRefreshSource); - Assert.IsTrue(expectedCacheSource.Contains(cacheRefreshInfo.CacheRefreshSource)); - Assert.IsNotNull(cacheRefreshInfo.Operation, "Operation Type is null"); - Assert.IsNotNull(cacheRefreshInfo.Resource, "Resource Type is null"); - Assert.IsNotNull(cacheRefreshInfo.StatusCode, "StatusCode is null"); - Assert.IsNotNull(cacheRefreshInfo.SubStatusCode); - Assert.IsNull(cacheRefreshInfo.Consistency); - Assert.IsNotNull(cacheRefreshInfo.ContainerName, "ContainerName is null"); - Assert.IsNotNull(cacheRefreshInfo.MetricInfo, "MetricInfo is null"); - Assert.IsNotNull(cacheRefreshInfo.MetricInfo.MetricsName, "MetricsName is null"); - Assert.IsNotNull(cacheRefreshInfo.MetricInfo.UnitName, "UnitName is null"); - Assert.IsNotNull(cacheRefreshInfo.MetricInfo.Percentiles, "Percentiles is null"); - Assert.IsTrue(cacheRefreshInfo.MetricInfo.Count >= 0, "MetricInfo Count is not greater than 0"); - Assert.IsTrue(cacheRefreshInfo.MetricInfo.Mean >= 0, "MetricInfo Mean is not greater than or equal to 0"); - Assert.IsTrue(cacheRefreshInfo.MetricInfo.Max >= 0, "MetricInfo Max is not greater than or equal to 0"); - Assert.IsTrue(cacheRefreshInfo.MetricInfo.Min >= 0, "MetricInfo Min is not greater than or equal to 0"); - } - } - - private static ItemBatchOperation CreateItem(string itemId) - { - var testItem = new { id = itemId, Status = itemId }; - return new ItemBatchOperation(Documents.OperationType.Create, 0, new Cosmos.PartitionKey(itemId), itemId, TestCommon.SerializerCore.ToStream(testItem)); - } - - private async Task CreateClientAndContainer(ConnectionMode mode, - Microsoft.Azure.Cosmos.ConsistencyLevel? consistency = null, - bool isLargeContainer = false, - bool isAzureInstance = false, - HttpClientHandlerHelper customHttpHandler = null) - { - if (consistency.HasValue) - { - this.cosmosClientBuilder = this.cosmosClientBuilder - .WithConsistencyLevel(consistency.Value); - } - - HttpClientHandlerHelper handlerHelper; - if (customHttpHandler == null) - { - handlerHelper = isAzureInstance ? this.httpHandler : this.httpHandlerForNonAzureInstance; - } - else - { - handlerHelper = customHttpHandler; - } - - this.cosmosClientBuilder = this.cosmosClientBuilder - .WithHttpClientFactory(() => new HttpClient(handlerHelper)) - .WithApplicationName("userAgentSuffix"); - - this.SetClient(mode == ConnectionMode.Gateway - ? this.cosmosClientBuilder.WithConnectionModeGateway().Build() - : this.cosmosClientBuilder.Build()); - - this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); - - return await this.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), - partitionKeyPath: "/id", - throughput: isLargeContainer? 15000 : 400); - - } - } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs new file mode 100644 index 0000000000..259a5346df --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs @@ -0,0 +1,1087 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System; + using System.Collections.Generic; + using System.Text; + using System.Threading.Tasks; + using System.Net; + using System.Net.Http; + using System.Reflection; + using Microsoft.Azure.Cosmos.Fluent; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Handler; + using Microsoft.Azure.Documents; + using Newtonsoft.Json.Linq; + using Newtonsoft.Json; + using Documents.Rntbd; + using System.Globalization; + using System.Linq; + using Cosmos.Util; + using Microsoft.Azure.Cosmos.Telemetry.Models; + + public abstract class ClientTelemetryTestsBase : BaseCosmosClientHelper + { + private static SystemUsageMonitor systemUsageMonitor; + private static readonly List preferredRegionList = new List + { + Regions.EastUS, + Regions.WestUS2 + }; + + private static readonly IDictionary expectedMetricNameUnitMap = new Dictionary() + { + { ClientTelemetryOptions.CpuName, ClientTelemetryOptions.CpuUnit }, + { ClientTelemetryOptions.MemoryName, ClientTelemetryOptions.MemoryUnit }, + { ClientTelemetryOptions.AvailableThreadsName, ClientTelemetryOptions.AvailableThreadsUnit }, + { ClientTelemetryOptions.IsThreadStarvingName, ClientTelemetryOptions.IsThreadStarvingUnit }, + { ClientTelemetryOptions.ThreadWaitIntervalInMsName, ClientTelemetryOptions.ThreadWaitIntervalInMsUnit } + }; + + private List actualInfo; + protected CosmosClientBuilder cosmosClientBuilder; + + protected HttpClientHandlerHelper httpHandler; + protected HttpClientHandlerHelper httpHandlerForNonAzureInstance; + + private bool isClientTelemetryAPICallFailed = false; + + public static void ClassInitialize(TestContext _) + { + Util.EnableClientTelemetryEnvironmentVariables(); + + SystemUsageMonitor oldSystemUsageMonitor = (SystemUsageMonitor)typeof(DiagnosticsHandlerHelper) + .GetField("systemUsageMonitor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DiagnosticsHandlerHelper.Instance); + oldSystemUsageMonitor.Stop(); + + ClientTelemetryTestsBase.ResetSystemUsageMonitor(true); + } + + public virtual void TestInitialize() + { + this.actualInfo = new List(); + + this.httpHandler = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + + lock (this.actualInfo) + { + this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); + } + } + return this.HttpHandlerRequestCallbackChecks(request); + }, + ResponseIntercepter = (response) => + { + if (response.RequestMessage.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); + } + + return Task.FromResult(response); + }, + ExceptionIntercepter = (request, exception) => + { + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + this.isClientTelemetryAPICallFailed = true; + } + } + }; + + this.httpHandlerForNonAzureInstance = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(VmMetadataApiHandler.vmMetadataEndpointUrl.AbsoluteUri)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.NotFound); + return Task.FromResult(result); + } + + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + + lock(this.actualInfo) + { + this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); + } + } + + return this.HttpHandlerRequestCallbackChecks(request); + }, + ResponseIntercepter = (response) => + { + if (response.RequestMessage.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); + } + return Task.FromResult(response); + }, + ExceptionIntercepter = (request, exception) => + { + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + this.isClientTelemetryAPICallFailed = true; + } + } + }; + + this.cosmosClientBuilder = this.GetBuilder() + .WithApplicationPreferredRegions(ClientTelemetryTestsBase.preferredRegionList); + } + + public abstract Task HttpHandlerRequestCallbackChecks(HttpRequestMessage request); + + public abstract CosmosClientBuilder GetBuilder(); + + private static void ResetSystemUsageMonitor(bool isTelemetryEnabled) + { + ClientTelemetryTestsBase.systemUsageMonitor?.Stop(); + + FieldInfo diagnosticsHandlerHelperInstance = typeof(DiagnosticsHandlerHelper) + .GetField("isTelemetryMonitoringEnabled", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); + diagnosticsHandlerHelperInstance.SetValue(null, isTelemetryEnabled); + + List recorders = new List() + { + (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) + .GetField("diagnosticSystemUsageRecorder", + BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(DiagnosticsHandlerHelper.Instance) + }; + + if (isTelemetryEnabled) + { + recorders.Add( + (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) + .GetField("telemetrySystemUsageRecorder", + BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(DiagnosticsHandlerHelper.Instance)); + } + + ClientTelemetryTestsBase.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(recorders); + } + + public virtual async Task Cleanup() + { + FieldInfo isInitializedField = typeof(VmMetadataApiHandler).GetField("isInitialized", + BindingFlags.Static | + BindingFlags.NonPublic); + isInitializedField.SetValue(null, false); + + FieldInfo azMetadataField = typeof(VmMetadataApiHandler).GetField("azMetadata", + BindingFlags.Static | + BindingFlags.NonPublic); + azMetadataField.SetValue(null, null); + await base.TestCleanup(); + + Assert.IsFalse(this.isClientTelemetryAPICallFailed, $"Call to client telemetry service endpoint (i.e. {ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri}) failed"); + } + + public static void FinalCleanup() + { + ClientTelemetryTestsBase.ResetSystemUsageMonitor(false); + } + + public virtual async Task PointSuccessOperationsTest(ConnectionMode mode, bool isAzureInstance) + { + Container container = await this.CreateClientAndContainer( + mode: mode, + isAzureInstance: isAzureInstance); + + // Create an item + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); + ItemResponse createResponse = await container.CreateItemAsync(testItem); + ToDoActivity testItemCreated = createResponse.Resource; + + // Read an Item + await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + + // Upsert an Item + await container.UpsertItemAsync(testItem); + + // Replace an Item + await container.ReplaceItemAsync(testItemCreated, testItemCreated.id.ToString()); + + // Patch an Item + List patch = new List() + { + PatchOperation.Add("/new", "patched") + }; + await ((ContainerInternal)container).PatchItemAsync( + testItem.id, + new Cosmos.PartitionKey(testItem.id), + patch); + + // Delete an Item + await container.DeleteItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Create.ToString(), 1}, + { Documents.OperationType.Upsert.ToString(), 1}, + { Documents.OperationType.Read.ToString(), 1}, + { Documents.OperationType.Replace.ToString(), 1}, + { Documents.OperationType.Patch.ToString(), 1}, + { Documents.OperationType.Delete.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 12, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + isAzureInstance: isAzureInstance); + } + + public virtual async Task PointReadFailureOperationsTest(ConnectionMode mode) + { + // Fail Read + try + { + Container container = await this.CreateClientAndContainer(mode, Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); + + await container.ReadItemAsync( + new Guid().ToString(), + new Cosmos.PartitionKey(new Guid().ToString()), + new ItemRequestOptions() + { + BaseConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual // overriding client level consistency + }); + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.NotFound) + { + string message = ce.ToString(); + Assert.IsNotNull(message); + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Read.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 2, + expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedCacheSource: null, + isExpectedNetworkTelemetry: false); + } + + public virtual async Task StreamReadFailureOperationsTest(ConnectionMode mode) + { + Container container = await this.CreateClientAndContainer(mode); + + // Fail Read + try + { + await container.ReadItemStreamAsync( + new Guid().ToString(), + new Cosmos.PartitionKey(new Guid().ToString()), + new ItemRequestOptions() + { + BaseConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix // Request level consistency + }); + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.NotFound) + { + string message = ce.ToString(); + Assert.IsNotNull(message); + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Read.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 2, + expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedCacheSource: null, + isExpectedNetworkTelemetry: false); + } + + public virtual async Task StreamOperationsTest(ConnectionMode mode) + { + Container container = await this.CreateClientAndContainer(mode); + + // Create an item + var testItem = new { id = "MyTestItemId", partitionKeyPath = "MyTestPkValue", details = "it's working", status = "done" }; + await container + .CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), + new Cosmos.PartitionKey(testItem.id)); + + //Upsert an Item + await container.UpsertItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), new Cosmos.PartitionKey(testItem.id)); + + //Read an Item + await container.ReadItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + + //Replace an Item + await container.ReplaceItemStreamAsync(TestCommon.SerializerCore.ToStream(testItem), testItem.id, new Cosmos.PartitionKey(testItem.id)); + + // Patch an Item + List patch = new List() + { + PatchOperation.Add("/new", "patched") + }; + await ((ContainerInternal)container).PatchItemStreamAsync( + partitionKey: new Cosmos.PartitionKey(testItem.id), + id: testItem.id, + patchOperations: patch); + + //Delete an Item + await container.DeleteItemStreamAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Create.ToString(), 1}, + { Documents.OperationType.Upsert.ToString(), 1}, + { Documents.OperationType.Read.ToString(), 1}, + { Documents.OperationType.Replace.ToString(), 1}, + { Documents.OperationType.Patch.ToString(), 1}, + { Documents.OperationType.Delete.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 12, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedCacheSource: null); + } + + public virtual async Task BatchOperationsTest(ConnectionMode mode) + { + Container container = await this.CreateClientAndContainer(mode, Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual); // Client level consistency + using (BatchAsyncContainerExecutor executor = + new BatchAsyncContainerExecutor( + (ContainerInlineCore)container, + ((ContainerInlineCore)container).ClientContext, + 20, + Documents.Constants.MaxDirectModeBatchRequestBodySizeInBytes) + ) + { + List> tasks = new List>(); + for (int i = 0; i < 10; i++) + { + tasks.Add(executor.AddAsync(CreateItem(i.ToString()), NoOpTrace.Singleton, default)); + } + + await Task.WhenAll(tasks); + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Batch.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 2, + expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.Eventual, + expectedOperationRecordCountMap: expectedRecordCountInOperation); + } + + public virtual async Task SingleOperationMultipleTimesTest(ConnectionMode mode) + { + Container container = await this.CreateClientAndContainer(mode); + + // Create an item + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); + + await container.CreateItemAsync(testItem, requestOptions: new ItemRequestOptions()); + + for (int count = 0; count < 50; count++) + { + // Read an Item + await container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.id)); + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Read.ToString(), 50}, + { Documents.OperationType.Create.ToString(), 1} + }; + + await this.WaitAndAssert( + expectedOperationCount: 4,// 2 (read, requestLatency + requestCharge) + 2 (create, requestLatency + requestCharge) + expectedOperationRecordCountMap: expectedRecordCountInOperation); + } + + public virtual async Task QueryOperationSinglePartitionTest(ConnectionMode mode) + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); + + Container container = await this.CreateClientAndContainer(mode); + + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue", "MyTestItemId"); + ItemRequestOptions requestOptions = new ItemRequestOptions() + { + ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix + }; + + ItemResponse createResponse = await container.CreateItemAsync( + item: testItem, + requestOptions: requestOptions); + + QueryRequestOptions queryRequestOptions = new QueryRequestOptions() + { + EnableOptimisticDirectExecution = false, + ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, + }; + + List families = new List(); + if (createResponse.StatusCode == HttpStatusCode.Created) + { + string sqlQueryText = "SELECT * FROM c"; + + QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); + using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( + queryDefinition: queryDefinition, + requestOptions: queryRequestOptions)) + { + while (queryResultSetIterator.HasMoreResults) + { + FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); + foreach (object family in currentResultSet) + { + families.Add(family); + } + } + } + + Assert.AreEqual(1, families.Count); + + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Query.ToString(), 1}, + { Documents.OperationType.Create.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 4, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); + } + + public virtual async Task QueryMultiPageSinglePartitionOperationTest(ConnectionMode mode) + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); + Container container = await this.CreateClientAndContainer(mode: mode); + + ItemRequestOptions requestOptions = new ItemRequestOptions() + { + ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix + }; + + ToDoActivity testItem1 = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue1", "MyTestItemId1"); + ItemResponse createResponse1 = await container.CreateItemAsync( + item: testItem1, + requestOptions: requestOptions); + ToDoActivity testItem2 = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue2", "MyTestItemId2"); + ItemResponse createResponse2 = await container.CreateItemAsync( + item: testItem2, + requestOptions: requestOptions); + + if (createResponse1.StatusCode == HttpStatusCode.Created && + createResponse2.StatusCode == HttpStatusCode.Created) + { + string sqlQueryText = "SELECT * FROM c"; + + List families = new List(); + QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); + using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( + queryDefinition: queryDefinition, + requestOptions: new QueryRequestOptions() + { + EnableOptimisticDirectExecution = false, + ConsistencyLevel = Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix, + MaxItemCount = 1 + })) + { + while (queryResultSetIterator.HasMoreResults) + { + FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); + foreach (object family in currentResultSet) + { + families.Add(family); + } + } + } + + Assert.AreEqual(2, families.Count); + + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Query.ToString(), 3}, + { Documents.OperationType.Create.ToString(), 2} + }; + + await this.WaitAndAssert( + expectedOperationCount: 4, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedConsistencyLevel: Microsoft.Azure.Cosmos.ConsistencyLevel.ConsistentPrefix); + } + + public virtual async Task QueryOperationCrossPartitionTest(ConnectionMode mode) + { + Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); + + ContainerInternal itemsCore = (ContainerInternal)await this.CreateClientAndContainer( + mode: mode, + isLargeContainer: true); + + // Verify container has multiple partitions + int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; + Assert.IsTrue(pkRangesCount > 1, "Should have created a multi partition container."); + + Container container = (Container)itemsCore; + + await ToDoActivity.CreateRandomItems( + container: container, + pkCount: 2, + perPKItemCount: 5); + + string sqlQueryText = "SELECT * FROM c"; + + List families = new List(); + + QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); + using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator(queryDefinition)) + { + while (queryResultSetIterator.HasMoreResults) + { + FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); + foreach (object family in currentResultSet) + { + families.Add(family); + } + } + } + + Assert.AreEqual(10, families.Count); + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Query.ToString(), pkRangesCount}, + { Documents.OperationType.Create.ToString(), 10} + }; + + await this.WaitAndAssert( + expectedOperationCount: 4, + expectedOperationRecordCountMap: expectedRecordCountInOperation); + } + + public virtual async Task QueryOperationMutiplePageCrossPartitionTest(ConnectionMode mode) + { + ContainerInternal itemsCore = (ContainerInternal)await this.CreateClientAndContainer( + mode: mode, + isLargeContainer: true); + + // Verify container has multiple partitions + int pkRangesCount = (await itemsCore.ClientContext.DocumentClient.ReadPartitionKeyRangeFeedAsync(itemsCore.LinkUri)).Count; + Assert.IsTrue(pkRangesCount > 1, "Should have created a multi partition container."); + + Container container = (Container)itemsCore; + + await ToDoActivity.CreateRandomItems( + container: container, + pkCount: 2, + perPKItemCount: 5); + + string sqlQueryText = "SELECT * FROM c"; + + List families = new List(); + QueryDefinition queryDefinition = new QueryDefinition(sqlQueryText); + using (FeedIterator queryResultSetIterator = container.GetItemQueryIterator( + queryDefinition: queryDefinition, + requestOptions: new QueryRequestOptions() + { + MaxItemCount = 1 + })) + { + while (queryResultSetIterator.HasMoreResults) + { + FeedResponse currentResultSet = await queryResultSetIterator.ReadNextAsync(); + foreach (object family in currentResultSet) + { + families.Add(family); + } + } + } + + Assert.AreEqual(10, families.Count); + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Query.ToString(), pkRangesCount + 10}, // 10 is number of items + { Documents.OperationType.Create.ToString(), 10} + }; + + await this.WaitAndAssert( + expectedOperationCount: 4, + expectedOperationRecordCountMap: expectedRecordCountInOperation); + } + + public virtual async Task QueryOperationInvalidContinuationTokenTest(ConnectionMode mode) + { + Container container = await this.CreateClientAndContainer(mode); + + // Create an item : First successful request to load Cache + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); + await container.CreateItemAsync(testItem); + + List results = new List(); + using (FeedIterator resultSetIterator = container.GetItemQueryIterator( + "SELECT * FROM c", + continuationToken: "dummy token")) + { + try + { + while (resultSetIterator.HasMoreResults) + { + FeedResponse response = await resultSetIterator.ReadNextAsync(); + results.AddRange(response); + } + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.BadRequest) + { + string message = ce.ToString(); + Assert.IsNotNull(message); + } + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Create.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 2, + expectedOperationRecordCountMap: expectedRecordCountInOperation); + } + + public virtual async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) + { + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper(); + HttpClient httpClient = new HttpClient(httpHandler); + + httpHandler.RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + { + string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + + lock (this.actualInfo) + { + this.actualInfo.Add(JsonConvert.DeserializeObject(jsonObject)); + } + } + else if (request.Method == HttpMethod.Get && request.RequestUri.AbsolutePath == "//addresses/") + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.Forbidden); + + // Add a substatus code that is not part of the enum. + // This ensures that if the backend adds a enum the status code is not lost. + result.Headers.Add(WFConstants.BackendHeaders.SubStatus, 999999.ToString(CultureInfo.InvariantCulture)); + + string payload = JsonConvert.SerializeObject(new Error() { Message = "test message" }); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + + return Task.FromResult(result); + } + return null; + }; + + // Replacing originally initialized cosmos Builder with this one with new handler + this.cosmosClientBuilder = this.cosmosClientBuilder + .WithHttpClientFactory(() => new HttpClient(httpHandler)); + + Container container = await this.CreateClientAndContainer( + mode: mode, + customHttpHandler: httpHandler); + try + { + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue"); + ItemResponse createResponse = await container.CreateItemAsync(testItem); + Assert.Fail("Request should throw exception."); + } + catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.Forbidden) + { + Assert.AreEqual(999999, ce.SubStatusCode); + } + + IDictionary expectedRecordCountInOperation = new Dictionary + { + { Documents.OperationType.Create.ToString(), 1} + }; + + await this.WaitAndAssert(expectedOperationCount: 2, + expectedOperationRecordCountMap: expectedRecordCountInOperation, + expectedSubstatuscode: 999999, + isExpectedNetworkTelemetry: false); + + } + + /// + /// This method wait for the expected operations to get recorded by telemetry and assert the values + /// + /// Expected number of unique OperationInfo irrespective of response size. + /// Expected Consistency level of the operation recorded by telemetry + /// Expected number of requests recorded for each operation + /// + private async Task WaitAndAssert( + int expectedOperationCount = 0, + Microsoft.Azure.Cosmos.ConsistencyLevel? expectedConsistencyLevel = null, + IDictionary expectedOperationRecordCountMap = null, + int expectedSubstatuscode = 0, + bool? isAzureInstance = null, + string expectedCacheSource = "ClientCollectionCache", + bool isExpectedNetworkTelemetry = true) + { + Assert.IsNotNull(this.actualInfo, "Telemetry Information not available"); + + // As this feature is thread based execution so wait for the results to avoid test flakiness + List localCopyOfActualInfo = null; + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + + HashSet cacheRefreshInfoSet = new HashSet(); + do + { + await Task.Delay(TimeSpan.FromMilliseconds(1500)); // wait at least for 1 round of telemetry + + HashSet actualOperationSet = new HashSet(); + HashSet requestInfoSet = new HashSet(); + + lock (this.actualInfo) + { + // Setting the number of unique OperationInfo irrespective of response size as response size is varying in case of queries. + this.actualInfo + .ForEach(x => + { + if (x.CacheRefreshInfo != null && x.CacheRefreshInfo.Count > 0) + { + x.CacheRefreshInfo + .ForEach(y => + { + y.GreaterThan1Kb = false; + cacheRefreshInfoSet.Add(y); + }); + + } + + x.OperationInfo + .ForEach(y => + { + y.GreaterThan1Kb = false; + actualOperationSet.Add(y); + }); + }); + + if (actualOperationSet.Count == expectedOperationCount / 2) + { + // Copy the list to avoid it being modified while validating + localCopyOfActualInfo = new List(this.actualInfo); + break; + } + + Assert.IsTrue(stopwatch.Elapsed.TotalMinutes < 1, $"The expected operation count({expectedOperationCount}) was never hit, Actual Operation Count is {actualOperationSet.Count}. ActualInfo:{JsonConvert.SerializeObject(this.actualInfo)}"); + } + } + while (localCopyOfActualInfo == null); + + List actualOperationList = new List(); + List actualSystemInformation = new List(); + List actualRequestInformation = new List(); + + if (localCopyOfActualInfo[0].ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) + { + ClientTelemetryTestsBase.expectedMetricNameUnitMap.TryAdd(ClientTelemetryOptions.NumberOfTcpConnectionName, ClientTelemetryOptions.NumberOfTcpConnectionUnit); + } + else + { + ClientTelemetryTestsBase.expectedMetricNameUnitMap.Remove(ClientTelemetryOptions.NumberOfTcpConnectionName); + } + + ClientTelemetryTestsBase.AssertAccountLevelInformation( + localCopyOfActualInfo: localCopyOfActualInfo, + actualOperationList: actualOperationList, + actualSystemInformation: actualSystemInformation, + actualRequestInformation: actualRequestInformation, + isAzureInstance: isAzureInstance); + + ClientTelemetryTestsBase.AssertOperationLevelInformation( + expectedConsistencyLevel: expectedConsistencyLevel, + expectedOperationRecordCountMap: expectedOperationRecordCountMap, + actualOperationList: actualOperationList, + expectedSubstatuscode: expectedSubstatuscode); + + if(!string.IsNullOrEmpty(expectedCacheSource)) + { + Assert.IsTrue(cacheRefreshInfoSet.Count > 0, "Cache Refresh Information is not there"); + + ClientTelemetryTestsBase.AssertCacheRefreshInfoInformation( + cacheRefreshInfoSet: cacheRefreshInfoSet, + expectedCacheSource: expectedCacheSource); + } + + ClientTelemetryTestsBase.AssertSystemLevelInformation(actualSystemInformation, ClientTelemetryTestsBase.expectedMetricNameUnitMap); + if (localCopyOfActualInfo.First().ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) + { + if (isExpectedNetworkTelemetry) + { + ClientTelemetryTestsBase.AssertNetworkLevelInformation(actualRequestInformation); + } + } + else + { + Assert.IsTrue(actualRequestInformation == null || actualRequestInformation.Count == 0, $"Request Information is not expected in {localCopyOfActualInfo.First().ConnectionMode} mode"); + } + } + + private static void AssertNetworkLevelInformation(List actualRequestInformation) + { + Assert.IsNotNull(actualRequestInformation); + Assert.IsTrue(actualRequestInformation.Count > 0); + + foreach(RequestInfo requestInfo in actualRequestInformation) + { + Assert.IsNotNull(requestInfo.Uri); + Assert.IsNotNull(requestInfo.DatabaseName); + Assert.IsNotNull(requestInfo.ContainerName); + Assert.IsNotNull(requestInfo.Operation); + Assert.IsNotNull(requestInfo.Resource); + Assert.IsNotNull(requestInfo.StatusCode); + Assert.AreNotEqual(0, requestInfo.StatusCode); + Assert.IsNotNull(requestInfo.SubStatusCode); + + Assert.IsNotNull(requestInfo.Metrics, "MetricInfo is null"); + } + } + + private static void AssertSystemLevelInformation(List actualSystemInformation, IDictionary expectedMetricNameUnitMap) + { + IDictionary actualMetricNameUnitMap = new Dictionary(); + + // Asserting If system information list is as expected + foreach (SystemInfo systemInfo in actualSystemInformation) + { + Assert.AreEqual("HostMachine", systemInfo.Resource); + Assert.IsNotNull(systemInfo.MetricInfo, "MetricInfo is null"); + + if(!actualMetricNameUnitMap.TryAdd(systemInfo.MetricInfo.MetricsName, systemInfo.MetricInfo.UnitName)) + { + Assert.AreEqual(systemInfo.MetricInfo.UnitName, actualMetricNameUnitMap[systemInfo.MetricInfo.MetricsName]); + } + + if(!systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.IsThreadStarvingName) && + !systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.ThreadWaitIntervalInMsName)) + { + Assert.IsTrue(systemInfo.MetricInfo.Count > 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Count is not greater than 0"); + Assert.IsNotNull(systemInfo.MetricInfo.Percentiles, $"Percentiles is null for metrics ({systemInfo.MetricInfo.MetricsName})"); + } + Assert.IsTrue(systemInfo.MetricInfo.Mean >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Mean is not greater than or equal to 0"); + Assert.IsTrue(systemInfo.MetricInfo.Max >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Max is not greater than or equal to 0"); + Assert.IsTrue(systemInfo.MetricInfo.Min >= 0, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Min is not greater than or equal to 0"); + if (systemInfo.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.CpuName)) + { + Assert.IsTrue(systemInfo.MetricInfo.Mean <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Mean is not greater than 100 for CPU Usage"); + Assert.IsTrue(systemInfo.MetricInfo.Max <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Max is not greater than 100 for CPU Usage"); + Assert.IsTrue(systemInfo.MetricInfo.Min <= 100, $"MetricInfo ({systemInfo.MetricInfo.MetricsName}) Min is not greater than 100 for CPU Usage"); + }; + } + + Assert.IsTrue(expectedMetricNameUnitMap.EqualsTo(actualMetricNameUnitMap), $"Actual System Information metric i.e {string.Join(", ", actualMetricNameUnitMap)} is not matching with expected System Information Metric i.e. {string.Join(", ", expectedMetricNameUnitMap)}"); + + } + + private static void AssertOperationLevelInformation( + Microsoft.Azure.Cosmos.ConsistencyLevel? expectedConsistencyLevel, + IDictionary expectedOperationRecordCountMap, + List actualOperationList, + int expectedSubstatuscode = 0) + { + IDictionary actualOperationRecordCountMap = new Dictionary(); + // Asserting If operation list is as expected + foreach (OperationInfo operation in actualOperationList) + { + Assert.IsNotNull(operation.Operation, "Operation Type is null"); + Assert.IsNotNull(operation.Resource, "Resource Type is null"); + + Assert.AreEqual(expectedSubstatuscode, operation.SubStatusCode); + Assert.AreEqual(expectedConsistencyLevel?.ToString(), operation.Consistency, $"Consistency is not {expectedConsistencyLevel}"); + + Assert.IsNotNull(operation.MetricInfo, "MetricInfo is null"); + Assert.IsNotNull(operation.MetricInfo.MetricsName, "MetricsName is null"); + Assert.IsNotNull(operation.MetricInfo.UnitName, "UnitName is null"); + Assert.IsNotNull(operation.MetricInfo.Percentiles, "Percentiles is null"); + Assert.IsTrue(operation.MetricInfo.Count > 0, "MetricInfo Count is not greater than 0"); + Assert.IsTrue(operation.MetricInfo.Mean >= 0, "MetricInfo Mean is not greater than or equal to 0"); + Assert.IsTrue(operation.MetricInfo.Max >= 0, "MetricInfo Max is not greater than or equal to 0"); + Assert.IsTrue(operation.MetricInfo.Min >= 0, "MetricInfo Min is not greater than or equal to 0"); + + if (operation.MetricInfo.MetricsName.Equals(ClientTelemetryOptions.RequestLatencyName)) // putting this condition to avoid doubling of count as we have same information for each metrics + { + if (!actualOperationRecordCountMap.TryGetValue(operation.Operation, out long recordCount)) + { + actualOperationRecordCountMap.Add(operation.Operation, operation.MetricInfo.Count); + } + else + { + actualOperationRecordCountMap.Remove(operation.Operation); + actualOperationRecordCountMap.Add(operation.Operation, recordCount + operation.MetricInfo.Count); + } + } + } + + if (expectedOperationRecordCountMap != null) + { + Assert.IsTrue(expectedOperationRecordCountMap.EqualsTo(actualOperationRecordCountMap), $"actual record i.e. ({string.Join(", ", actualOperationRecordCountMap)}) for operation does not match with expected record i.e. ({string.Join(", ", expectedOperationRecordCountMap)})"); + } + } + + private static void AssertAccountLevelInformation( + List localCopyOfActualInfo, + List actualOperationList, + List actualSystemInformation, + List actualRequestInformation, + bool? isAzureInstance) + { + ISet machineId = new HashSet(); + + // Asserting If basic client telemetry object is as expected + foreach (ClientTelemetryProperties telemetryInfo in localCopyOfActualInfo) + { + if (telemetryInfo.OperationInfo != null) + { + actualOperationList.AddRange(telemetryInfo.OperationInfo); + } + + if (telemetryInfo.SystemInfo != null) + { + foreach (SystemInfo sysInfo in telemetryInfo.SystemInfo) + { + actualSystemInformation.Add(sysInfo); + } + } + + if (telemetryInfo.RequestInfo != null) + { + actualRequestInformation.AddRange(telemetryInfo.RequestInfo); + } + + if (telemetryInfo.ConnectionMode == ConnectionMode.Direct.ToString().ToUpperInvariant()) + { + Assert.AreEqual(6, telemetryInfo.SystemInfo.Count, $"System Information Count doesn't Match; {JsonConvert.SerializeObject(telemetryInfo.SystemInfo)}"); + } + else + { + Assert.AreEqual(5, telemetryInfo.SystemInfo.Count, $"System Information Count doesn't Match; {JsonConvert.SerializeObject(telemetryInfo.SystemInfo)}"); + } + + Assert.IsNotNull(telemetryInfo.GlobalDatabaseAccountName, "GlobalDatabaseAccountName is null"); + Assert.IsNotNull(telemetryInfo.DateTimeUtc, "Timestamp is null"); + Assert.AreEqual(2, telemetryInfo.PreferredRegions.Count); + Assert.AreEqual(Regions.EastUS, telemetryInfo.PreferredRegions[0]); + Assert.AreEqual(Regions.WestUS2, telemetryInfo.PreferredRegions[1]); + Assert.AreEqual(1, telemetryInfo.AggregationIntervalInSec); + Assert.IsNull(telemetryInfo.AcceleratedNetworking); + Assert.IsNotNull(telemetryInfo.ClientId); + Assert.IsNotNull(telemetryInfo.ProcessId); + Assert.AreEqual(HashingExtension.ComputeHash(System.Diagnostics.Process.GetCurrentProcess().ProcessName), telemetryInfo.ProcessId); + Assert.IsNotNull(telemetryInfo.UserAgent); + Assert.IsFalse(telemetryInfo.UserAgent.Contains("userAgentSuffix"), "Useragent should not have suffix appended"); // Useragent should not contain useragentsuffix as it can have PII + Assert.IsNotNull(telemetryInfo.ConnectionMode); + + if (!string.IsNullOrEmpty(telemetryInfo.MachineId)) + { + machineId.Add(telemetryInfo.MachineId); + } + } + + if (isAzureInstance.HasValue) + { + if (isAzureInstance.Value) + { + Assert.IsTrue(machineId.First().StartsWith(VmMetadataApiHandler.VmIdPrefix), $"Generated Machine id is : {machineId.First()}"); + } + else + { + Assert.IsTrue(machineId.First().StartsWith(VmMetadataApiHandler.HashedMachineNamePrefix), $"Generated Machine id is : {machineId.First()}"); + } + } + + Assert.AreEqual(1, machineId.Count, $"Multiple Machine Id has been generated i.e {JsonConvert.SerializeObject(machineId)}"); + } + + private static void AssertCacheRefreshInfoInformation( + HashSet cacheRefreshInfoSet, + string expectedCacheSource) + { + foreach(CacheRefreshInfo cacheRefreshInfo in cacheRefreshInfoSet) + { + Assert.IsNotNull(cacheRefreshInfo.CacheRefreshSource); + Assert.IsTrue(expectedCacheSource.Contains(cacheRefreshInfo.CacheRefreshSource)); + Assert.IsNotNull(cacheRefreshInfo.Operation, "Operation Type is null"); + Assert.IsNotNull(cacheRefreshInfo.Resource, "Resource Type is null"); + Assert.IsNotNull(cacheRefreshInfo.StatusCode, "StatusCode is null"); + Assert.IsNotNull(cacheRefreshInfo.SubStatusCode); + Assert.IsNull(cacheRefreshInfo.Consistency); + Assert.IsNotNull(cacheRefreshInfo.ContainerName, "ContainerName is null"); + Assert.IsNotNull(cacheRefreshInfo.MetricInfo, "MetricInfo is null"); + Assert.IsNotNull(cacheRefreshInfo.MetricInfo.MetricsName, "MetricsName is null"); + Assert.IsNotNull(cacheRefreshInfo.MetricInfo.UnitName, "UnitName is null"); + Assert.IsNotNull(cacheRefreshInfo.MetricInfo.Percentiles, "Percentiles is null"); + Assert.IsTrue(cacheRefreshInfo.MetricInfo.Count >= 0, "MetricInfo Count is not greater than 0"); + Assert.IsTrue(cacheRefreshInfo.MetricInfo.Mean >= 0, "MetricInfo Mean is not greater than or equal to 0"); + Assert.IsTrue(cacheRefreshInfo.MetricInfo.Max >= 0, "MetricInfo Max is not greater than or equal to 0"); + Assert.IsTrue(cacheRefreshInfo.MetricInfo.Min >= 0, "MetricInfo Min is not greater than or equal to 0"); + } + } + + private static ItemBatchOperation CreateItem(string itemId) + { + var testItem = new { id = itemId, Status = itemId }; + return new ItemBatchOperation(Documents.OperationType.Create, 0, new Cosmos.PartitionKey(itemId), itemId, TestCommon.SerializerCore.ToStream(testItem)); + } + + private async Task CreateClientAndContainer(ConnectionMode mode, + Microsoft.Azure.Cosmos.ConsistencyLevel? consistency = null, + bool isLargeContainer = false, + bool isAzureInstance = true, + HttpClientHandlerHelper customHttpHandler = null) + { + if (consistency.HasValue) + { + this.cosmosClientBuilder = this.cosmosClientBuilder + .WithConsistencyLevel(consistency.Value); + } + + HttpClientHandlerHelper handlerHelper = customHttpHandler ?? (isAzureInstance ? this.httpHandler : this.httpHandlerForNonAzureInstance); + this.cosmosClientBuilder = this.cosmosClientBuilder + .WithHttpClientFactory(() => new HttpClient(handlerHelper)) + .WithApplicationName("userAgentSuffix"); + + this.SetClient(mode == ConnectionMode.Gateway + ? this.cosmosClientBuilder.WithConnectionModeGateway().Build() + : this.cosmosClientBuilder.Build()); + + // Making sure client telemetry is enabled + Assert.IsNotNull(this.GetClient().DocumentClient.clientTelemetry); + + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); + + return await this.database.CreateContainerAsync( + id: Guid.NewGuid().ToString(), + partitionKeyPath: "/id", + throughput: isLargeContainer? 15000 : 400); + + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs index cedef0658a..9b78eb573c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs @@ -19,6 +19,8 @@ public HttpClientHandlerHelper() : base(new HttpClientHandler()) public Func> ResponseIntercepter { get; set; } + public Action ExceptionIntercepter { get; set; } + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { HttpResponseMessage httpResponse = null; @@ -39,7 +41,19 @@ protected override async Task SendAsync(HttpRequestMessage } } - httpResponse = await base.SendAsync(request, cancellationToken); + try + { + httpResponse = await base.SendAsync(request, cancellationToken); + } + catch (Exception ex) { + + if (this.ExceptionIntercepter == null) + { + throw; + } + this.ExceptionIntercepter.Invoke(request, ex); + } + if (this.ResponseIntercepter != null) { httpResponse = await this.ResponseIntercepter(httpResponse); diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 510bf5f6f8..81cd3d3d91 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -7,6 +7,8 @@ variables: VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops BuildConfiguration: Release Packaging.EnableSBOMSigning: true + ReleasePackage: true + OS: 'Windows' stages: - stage: @@ -22,14 +24,45 @@ stages: BuildConfiguration: $(BuildConfiguration) Arguments: $(ReleaseArguments) VmImage: $(VmImage) + + - job: + displayName: TelemetryToService $(BuildConfiguration) + timeoutInMinutes: 120 + condition: and(succeeded(), eq('$(OS)', 'Windows')) + pool: + vmImage: windows-2019 + + steps: + - checkout: self # self represents the repo where the initial Pipelines YAML file was found + clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching + + # Add this Command to Include the .NET 6 SDK + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.x' + + - task: DotNetCoreCLI@2 + displayName: Integration Test With Client Telemetry Service + condition: succeeded() + inputs: + command: test + projects: 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/*.csproj' + arguments: --filter "TestCategory=ClientTelemetryRelease" --verbosity normal --configuration $(BuildConfiguration) /p:OS=$(OS) + nugetConfigPath: NuGet.config + publishTestResults: true + testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests + env: + COSMOSDB_ACCOUNT_CONNECTION_STRING: $(COSMOSDB_ACCOUNT_CONNECTION_STRING) # Real Account Connection String used by Integration Tests while running as part of release pipeline - stage: displayName: Publish jobs: - template: templates/nuget-pack.yml parameters: - BuildConfiguration: Release + BuildConfiguration: $(BuildConfiguration) VmImage: $(VmImage) - ReleasePackage: true + ReleasePackage: $(ReleasePackage) OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' BlobVersion: $(BlobVersion) \ No newline at end of file diff --git a/templates/build-test.yml b/templates/build-test.yml index 3a016080e1..8d22aeb758 100644 --- a/templates/build-test.yml +++ b/templates/build-test.yml @@ -5,9 +5,9 @@ parameters: Arguments: '' VmImage: '' # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops OS: 'Windows' - EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & (TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' - EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed" --verbosity normal ' - EmulatorPipeline1CategoryListName: ' Query, ChangeFeed, ReadFeed, Batch ' # Divided in 2 categories to run them in parallel and reduce the PR feedback time + EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' + EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed" --verbosity normal ' + EmulatorPipeline1CategoryListName: ' Client Telemetry, Query, ChangeFeed, ReadFeed, Batch ' # Divided in 2 categories to run them in parallel and reduce the PR feedback time EmulatorPipeline2CategoryListName: ' Others ' jobs: From e2311a9fdcca392ec7d49c13939aaff3404deb85 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 22 Aug 2023 22:55:01 +0530 Subject: [PATCH 179/337] [Internal] Client Telemetry: Refactors code for collectors (#4037) * refactored code * implemented review comments * test fix * fix tests * fix test * fix test * logger fix * update contract * fic test * updated benchmarks --- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 67 +- .../src/Fluent/CosmosClientBuilder.cs | 1 - .../src/Handler/ClientPipelineBuilder.cs | 9 +- .../src/Handler/TelemetryHandler.cs | 38 +- .../src/Resource/ClientContextCore.cs | 4 +- .../src/Routing/ClientCollectionCache.cs | 42 +- .../src/Telemetry/ClientTelemetry.cs | 143 +-- .../Collector/ITelemetryCollector.cs | 25 + .../Telemetry/Collector/TelemetryCollector.cs | 77 ++ .../Collector/TelemetryCollectorNoOp.cs | 21 + .../Collector/TelemetryInformation.cs | 30 + .../src/Telemetry/TelemetryToServiceHelper.cs | 134 ++ .../src/Telemetry/VmMetadataApiHandler.cs | 6 +- ...iterBaselineTests.BatchOperationsAsync.xml | 37 +- ...riterBaselineTests.BulkOperationsAsync.xml | 974 ++++++++------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 888 ++++++++------ ...eWriterBaselineTests.MiscellanousAsync.xml | 86 +- ...neTests.PointOperationsExceptionsAsync.xml | 716 ++++++----- ...EndTraceWriterBaselineTests.QueryAsync.xml | 1079 ++++++++++------- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 592 +++++---- ...TraceWriterBaselineTests.ReadManyAsync.xml | 222 ++-- ...selineTests.StreamPointOperationsAsync.xml | 148 ++- ...aselineTests.TypedPointOperationsAsync.xml | 148 ++- .../ClientTelemetryTestsBase.cs | 2 +- .../Contracts/BenchmarkResults.json | 2 +- .../Mocks/MockDocumentClient.cs | 33 +- .../HandlerTests.cs | 24 +- .../Utils/MockCosmosUtil.cs | 15 +- .../Utils/MockDocumentClient.cs | 17 +- 29 files changed, 3280 insertions(+), 2300 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Collector/ITelemetryCollector.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollector.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollectorNoOp.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryInformation.cs create mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index c7aeb07a6f..9dee309028 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -142,7 +142,8 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider private Documents.ConsistencyLevel? desiredConsistencyLevel; internal CosmosAccountServiceConfiguration accountServiceConfiguration { get; private set; } - internal ClientTelemetry clientTelemetry { get; set; } + + internal TelemetryToServiceHelper telemetryToServiceHelper { get; set; } private ClientCollectionCache collectionCache; @@ -564,11 +565,11 @@ public DocumentClient(Uri serviceEndpoint, /// /// Internal constructor purely for unit-testing /// - internal DocumentClient(Uri serviceEndpoint, string authKey) + internal DocumentClient(Uri serviceEndpoint, ConnectionPolicy connectionPolicy) { // do nothing this.ServiceEndpoint = serviceEndpoint; - this.ConnectionPolicy = new ConnectionPolicy(); + this.ConnectionPolicy = connectionPolicy ?? new ConnectionPolicy(); } internal virtual async Task GetCollectionCacheAsync(ITrace trace) @@ -660,7 +661,7 @@ private async Task OpenPrivateAsync(CancellationToken cancellationToken) storeModel: this.GatewayStoreModel, tokenProvider: this, retryPolicy: this.retryPolicy, - clientTelemetry: this.clientTelemetry); + telemetryToServiceHelper: this.telemetryToServiceHelper); this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache); DefaultTrace.TraceWarning("{0} occurred while OpenAsync. Exception Message: {1}", ex.ToString(), ex.Message); @@ -939,6 +940,15 @@ internal virtual void Initialize(Uri serviceEndpoint, // Loading VM Information (non blocking call and initialization won't fail if this call fails) VmMetadataApiHandler.TryInitialize(this.httpClient); + // Starting ClientTelemetry Job + this.telemetryToServiceHelper = TelemetryToServiceHelper.CreateAndInitializeClientConfigAndTelemetryJob(this.clientId, + this.ConnectionPolicy, + this.cosmosAuthorization, + this.httpClient, + this.ServiceEndpoint, + this.GlobalEndpointManager, + this.cancellationTokenSource); + if (sessionContainer != null) { this.sessionContainer = sessionContainer; @@ -961,12 +971,6 @@ internal virtual void Initialize(Uri serviceEndpoint, // For direct: WFStoreProxy [set in OpenAsync()]. this.eventSource = DocumentClientEventSource.Instance; - // Disable system usage for internal builds. Cosmos DB owns the VMs and already logs - // the system information so no need to track it. -#if !INTERNAL - this.InitializeClientTelemetry(); -#endif - this.initializeTaskFactory = (_) => TaskHelper.InlineIfPossible( () => this.GetInitializationTaskAsync(storeClientFactory: storeClientFactory), new ResourceThrottleRetryPolicy( @@ -1028,7 +1032,7 @@ private async Task GetInitializationTaskAsync(IStoreClientFactory storeCli storeModel: this.GatewayStoreModel, tokenProvider: this, retryPolicy: this.retryPolicy, - clientTelemetry: this.clientTelemetry); + telemetryToServiceHelper: this.telemetryToServiceHelper); this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache); this.ResetSessionTokenRetryPolicy = new ResetSessionTokenRetryPolicyFactory(this.sessionContainer, this.collectionCache, this.retryPolicy); @@ -1046,36 +1050,6 @@ private async Task GetInitializationTaskAsync(IStoreClientFactory storeCli return true; } - private void InitializeClientTelemetry() - { - if (this.ConnectionPolicy.EnableClientTelemetry) - { - try - { - this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( - clientId: this.clientId, - httpClient: this.httpClient, - userAgent: this.ConnectionPolicy.UserAgentContainer.BaseUserAgent, - connectionMode: this.ConnectionPolicy.ConnectionMode, - authorizationTokenProvider: this.cosmosAuthorization, - diagnosticsHelper: DiagnosticsHandlerHelper.Instance, - preferredRegions: this.ConnectionPolicy.PreferredLocations, - globalEndpointManager: this.GlobalEndpointManager); - - DefaultTrace.TraceInformation("Client Telemetry Enabled."); - } - catch (Exception ex) - { - DefaultTrace.TraceInformation($"Error While starting Telemetry Job : {ex.Message}. Hence disabling Client Telemetry"); - this.ConnectionPolicy.EnableClientTelemetry = false; - } - } - else - { - DefaultTrace.TraceInformation("Client Telemetry Disabled."); - } - } - private async Task InitializeCachesAsync(string databaseName, DocumentCollection collection, CancellationToken cancellationToken) { if (databaseName == null) @@ -1279,6 +1253,12 @@ public void Dispose() return; } + if (this.telemetryToServiceHelper != null) + { + this.telemetryToServiceHelper.Dispose(); + this.telemetryToServiceHelper = null; + } + if (!this.cancellationTokenSource.IsCancellationRequested) { this.cancellationTokenSource.Cancel(); @@ -1346,11 +1326,6 @@ public void Dispose() this.initTaskCache = null; } - if (this.clientTelemetry != null) - { - this.clientTelemetry.Dispose(); - } - DefaultTrace.TraceInformation("DocumentClient with id {0} disposed.", this.traceId); DefaultTrace.Flush(); diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 9c8c2fbb4e..bf04d103bb 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -15,7 +15,6 @@ namespace Microsoft.Azure.Cosmos.Fluent using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; - using Telemetry; /// /// This is a Builder class that creates a cosmos client diff --git a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs index d4c260f904..aa69b770e1 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs @@ -27,7 +27,7 @@ public ClientPipelineBuilder( CosmosClient client, ConsistencyLevel? requestedClientConsistencyLevel, IReadOnlyCollection customHandlers, - ClientTelemetry telemetry) + TelemetryToServiceHelper telemetryToServiceHelper) { this.client = client ?? throw new ArgumentNullException(nameof(client)); this.requestedClientConsistencyLevel = requestedClientConsistencyLevel; @@ -48,11 +48,8 @@ public ClientPipelineBuilder( #else this.diagnosticsHandler = null; #endif - if (telemetry != null) - { - this.telemetryHandler = new TelemetryHandler(telemetry); - Debug.Assert(this.telemetryHandler.InnerHandler == null, nameof(this.telemetryHandler)); - } + this.telemetryHandler = new TelemetryHandler(telemetryToServiceHelper); + Debug.Assert(this.telemetryHandler.InnerHandler == null, nameof(this.telemetryHandler)); this.UseRetryPolicy(); this.AddCustomHandlers(customHandlers); diff --git a/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs index 9d7e504eba..039373718f 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/TelemetryHandler.cs @@ -10,14 +10,15 @@ namespace Microsoft.Azure.Cosmos.Handlers using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Telemetry.Collector; internal class TelemetryHandler : RequestHandler { - private readonly ClientTelemetry telemetry; + private readonly TelemetryToServiceHelper telemetryToServiceHelper; - public TelemetryHandler(ClientTelemetry telemetry) + public TelemetryHandler(TelemetryToServiceHelper telemetryToServiceHelper) { - this.telemetry = telemetry ?? throw new ArgumentNullException(nameof(telemetry)); + this.telemetryToServiceHelper = telemetryToServiceHelper ?? throw new ArgumentNullException(nameof(telemetryToServiceHelper)); } public override async Task SendAsync( @@ -29,19 +30,22 @@ public override async Task SendAsync( { try { - this.telemetry - .CollectOperationInfo( - cosmosDiagnostics: response.Diagnostics, - statusCode: response.StatusCode, - responseSizeInBytes: this.GetPayloadSize(response), - containerId: request.ContainerId, - databaseId: request.DatabaseId, - operationType: request.OperationType, - resourceType: request.ResourceType, - consistencyLevel: request.Headers?[Documents.HttpConstants.HttpHeaders.ConsistencyLevel], - requestCharge: response.Headers.RequestCharge, - subStatusCode: response.Headers.SubStatusCode, - trace: response.Trace); + this.telemetryToServiceHelper.GetCollector().CollectOperationAndNetworkInfo( + () => new TelemetryInformation + { + RegionsContactedList = response.Diagnostics.GetContactedRegions(), + RequestLatency = response.Diagnostics.GetClientElapsedTime(), + StatusCode = response.StatusCode, + ResponseSizeInBytes = TelemetryHandler.GetPayloadSize(response), + ContainerId = request.ContainerId, + DatabaseId = request.DatabaseId, + OperationType = request.OperationType, + ResourceType = request.ResourceType, + ConsistencyLevel = request.Headers?[Documents.HttpConstants.HttpHeaders.ConsistencyLevel], + RequestCharge = response.Headers.RequestCharge, + SubStatusCode = response.Headers.SubStatusCode, + Trace = response.Trace + }); } catch (Exception ex) { @@ -63,7 +67,7 @@ private bool IsAllowed(RequestMessage request) /// /// /// Size of Payload - private long GetPayloadSize(ResponseMessage response) + private static long GetPayloadSize(ResponseMessage response) { if (response != null) { diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index 42e128ac2e..a128e178d0 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -13,8 +13,6 @@ namespace Microsoft.Azure.Cosmos using System.Text; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.Handler; using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; using Microsoft.Azure.Cosmos.Routing; @@ -122,7 +120,7 @@ internal static CosmosClientContext Create( cosmosClient, clientOptions.ConsistencyLevel, clientOptions.CustomHandlers, - telemetry: documentClient.clientTelemetry); + telemetryToServiceHelper: documentClient.telemetryToServiceHelper); requestInvokerHandler = clientPipelineBuilder.Build(); } diff --git a/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs b/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs index 530bbfceb5..534a0b8a22 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/ClientCollectionCache.cs @@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Routing using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Common; using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Telemetry.Collector; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; @@ -25,20 +26,20 @@ internal class ClientCollectionCache : CollectionCache private readonly ICosmosAuthorizationTokenProvider tokenProvider; private readonly IRetryPolicyFactory retryPolicy; private readonly ISessionContainer sessionContainer; - private readonly ClientTelemetry clientTelemetry; + private readonly TelemetryToServiceHelper telemetryToServiceHelper; public ClientCollectionCache( ISessionContainer sessionContainer, IStoreModel storeModel, ICosmosAuthorizationTokenProvider tokenProvider, IRetryPolicyFactory retryPolicy, - ClientTelemetry clientTelemetry) + TelemetryToServiceHelper telemetryToServiceHelper) { this.storeModel = storeModel ?? throw new ArgumentNullException("storeModel"); this.tokenProvider = tokenProvider; this.retryPolicy = retryPolicy; this.sessionContainer = sessionContainer; - this.clientTelemetry = clientTelemetry; + this.telemetryToServiceHelper = telemetryToServiceHelper; } protected override Task GetByRidAsync(string apiVersion, @@ -214,21 +215,19 @@ private async Task ReadCollectionAsync( await this.storeModel.ProcessMessageAsync(request)) { ContainerProperties containerProperties = CosmosResource.FromStream(response); - - if (this.clientTelemetry != null) - { - ClientCollectionCache.GetDatabaseAndCollectionName(collectionLink, out string databaseName, out string collectionName); - this.clientTelemetry.CollectCacheInfo( - cacheRefreshSource: ClientCollectionCache.TelemetrySourceName, - regionsContactedList: response.RequestStats.RegionsContacted, - requestLatency: response.RequestStats.RequestLatency, - statusCode: response.StatusCode, - containerId: collectionName, - operationType: request.OperationType, - resourceType: request.ResourceType, - subStatusCode: response.SubStatusCode, - databaseId: databaseName); - } + + this.telemetryToServiceHelper.GetCollector().CollectCacheInfo( + ClientCollectionCache.TelemetrySourceName, + () => new TelemetryInformation + { + RegionsContactedList = response.RequestStats.RegionsContacted, + RequestLatency = response.RequestStats.RequestLatency, + StatusCode = response.StatusCode, + OperationType = request.OperationType, + ResourceType = request.ResourceType, + SubStatusCode = response.SubStatusCode, + CollectionLink = collectionLink + }); return containerProperties; } @@ -242,12 +241,5 @@ await this.storeModel.ProcessMessageAsync(request)) } } } - - private static void GetDatabaseAndCollectionName(string path, out string databaseName, out string collectionName) - { - string[] segments = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - - PathsHelper.ParseDatabaseNameAndCollectionNameFromUrlSegments(segments, out databaseName, out collectionName); - } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index dde7d5a7c5..2dfcbab496 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -7,18 +7,16 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System; using System.Collections.Concurrent; using System.Collections.Generic; - using System.Net; using System.Threading; using System.Threading.Tasks; using Handler; using HdrHistogram; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Telemetry.Collector; using Microsoft.Azure.Cosmos.Telemetry.Models; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Cosmos.Tracing.TraceData; - using Microsoft.Azure.Documents; using Util; + using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; /// /// This class collects and send all the telemetry information. @@ -215,9 +213,9 @@ internal static async Task RunProcessorTaskAsync(string telemetryDate, Task proc Task resultTask = await Task.WhenAny(processingTask, delayTask); if (resultTask == delayTask) { - DefaultTrace.TraceVerbose($"Processor task with date as {telemetryDate} is canceled as it did not finish in {timeout}"); + DefaultTrace.TraceVerbose($"Processor task with date as {0} is canceled as it did not finish in {1}", telemetryDate, timeout); // Operation cancelled - throw new OperationCanceledException($"Processor task with date as {telemetryDate} is canceled as it did not finish in {timeout}"); + throw new OperationCanceledException(string.Format($"Processor task with date as {0} is canceled as it did not finish in {1}", telemetryDate, timeout)); } else { @@ -230,38 +228,36 @@ internal static async Task RunProcessorTaskAsync(string telemetryDate, Task proc /// /// Collects Cache Telemetry Information. /// - internal void CollectCacheInfo(string cacheRefreshSource, - HashSet<(string regionName, Uri uri)> regionsContactedList, - TimeSpan? requestLatency, - HttpStatusCode statusCode, - string containerId, - OperationType operationType, - ResourceType resourceType, - SubStatusCodes subStatusCode, - string databaseId, - long responseSizeInBytes = 0, - string consistencyLevel = null ) + internal void PushCacheDatapoint(string cacheName, TelemetryInformation data) { - if (string.IsNullOrEmpty(cacheRefreshSource)) + if (string.IsNullOrEmpty(cacheName)) { - throw new ArgumentNullException(nameof(cacheRefreshSource)); + throw new ArgumentNullException(nameof(cacheName)); } - DefaultTrace.TraceVerbose($"Collecting cacheRefreshSource {0} data for Telemetry.", cacheRefreshSource); + // If latency information is not available. Ignore this datapoint. It is not expected but putting this safety check + if (!data.RequestLatency.HasValue) + { + DefaultTrace.TraceWarning($"Latency data point is not available for {0} cache call", cacheName); + + return; + } + + DefaultTrace.TraceVerbose($"Collecting cacheRefreshSource {0} data for Telemetry.", cacheName); - string regionsContacted = ClientTelemetryHelper.GetContactedRegions(regionsContactedList); + string regionsContacted = ClientTelemetryHelper.GetContactedRegions(data.RegionsContactedList); // Recording Request Latency - CacheRefreshInfo payloadKey = new CacheRefreshInfo(cacheRefreshSource: cacheRefreshSource, + CacheRefreshInfo payloadKey = new CacheRefreshInfo(cacheRefreshSource: cacheName, regionsContacted: regionsContacted?.ToString(), - responseSizeInBytes: responseSizeInBytes, - consistency: consistencyLevel, - databaseName: databaseId, - containerName: containerId, - operation: operationType, - resource: resourceType, - statusCode: (int)statusCode, - subStatusCode: (int)subStatusCode); + responseSizeInBytes: data.ResponseSizeInBytes, + consistency: data.ConsistencyLevel, + databaseName: data.DatabaseId, + containerName: data.ContainerId, + operation: data.OperationType, + resource: data.ResourceType, + statusCode: (int)data.StatusCode, + subStatusCode: (int)data.SubStatusCode); LongConcurrentHistogram latency = this.cacheRefreshInfoMap .GetOrAdd(payloadKey, new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, @@ -269,7 +265,7 @@ internal void CollectCacheInfo(string cacheRefreshSource, ClientTelemetryOptions.RequestLatencyPrecision)); try { - latency.RecordValue(requestLatency.Value.Ticks); + latency.RecordValue(data.RequestLatency.Value.Ticks); } catch (Exception ex) { @@ -280,52 +276,22 @@ internal void CollectCacheInfo(string cacheRefreshSource, /// /// Collects Telemetry Information. /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, - HttpStatusCode statusCode, - long responseSizeInBytes, - string containerId, - string databaseId, - OperationType operationType, - ResourceType resourceType, - string consistencyLevel, - double requestCharge, - SubStatusCodes subStatusCode, - ITrace trace) + internal void PushOperationDatapoint(TelemetryInformation data) { DefaultTrace.TraceVerbose("Collecting Operation data for Telemetry."); - if (cosmosDiagnostics == null) - { - throw new ArgumentNullException(nameof(cosmosDiagnostics)); - } - - // Record Network/Replica Information - SummaryDiagnostics summaryDiagnostics = new SummaryDiagnostics(trace); - this.networkDataRecorder.Record(summaryDiagnostics.StoreResponseStatistics.Value, databaseId, containerId); - - string regionsContacted = ClientTelemetryHelper.GetContactedRegions(cosmosDiagnostics.GetContactedRegions()); + string regionsContacted = ClientTelemetryHelper.GetContactedRegions(data.RegionsContactedList); // Recording Request Latency and Request Charge OperationInfo payloadKey = new OperationInfo(regionsContacted: regionsContacted?.ToString(), - responseSizeInBytes: responseSizeInBytes, - consistency: consistencyLevel, - databaseName: databaseId, - containerName: containerId, - operation: operationType, - resource: resourceType, - statusCode: (int)statusCode, - subStatusCode: (int)subStatusCode); + responseSizeInBytes: data.ResponseSizeInBytes, + consistency: data.ConsistencyLevel, + databaseName: data.DatabaseId, + containerName: data.ContainerId, + operation: data.OperationType, + resource: data.ResourceType, + statusCode: (int)data.StatusCode, + subStatusCode: (int)data.SubStatusCode); (LongConcurrentHistogram latency, LongConcurrentHistogram requestcharge) = this.operationInfoMap .GetOrAdd(payloadKey, x => (latency: new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, @@ -334,16 +300,26 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, requestcharge: new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, ClientTelemetryOptions.RequestChargeMax, ClientTelemetryOptions.RequestChargePrecision))); - try + + // If latency information is not available. Ignore this datapoint. It is not expected but putting this safety check + if (data.RequestLatency.HasValue) { - latency.RecordValue(cosmosDiagnostics.GetClientElapsedTime().Ticks); + try + { + latency.RecordValue(data.RequestLatency.Value.Ticks); + } + catch (Exception ex) + { + DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex); + } + } - catch (Exception ex) + else { - DefaultTrace.TraceError("Latency Recording Failed by Telemetry. Exception : {0}", ex); + DefaultTrace.TraceWarning($"Latency data point is not available for an operation"); } - - long requestChargeToRecord = (long)(requestCharge * ClientTelemetryOptions.HistogramPrecisionFactor); + + long requestChargeToRecord = (long)(data.RequestCharge * ClientTelemetryOptions.HistogramPrecisionFactor); try { requestcharge.RecordValue(requestChargeToRecord); @@ -354,6 +330,19 @@ internal void CollectOperationInfo(CosmosDiagnostics cosmosDiagnostics, } } + /// + /// Record Network Request Telemetry Information + /// + /// + /// + /// + public void PushNetworkDataPoint(List storeResponseStatistics, string databaseId, string containerId) + { + // Record Network/Replica Information + this.networkDataRecorder.Record(storeResponseStatistics, databaseId, containerId); + + } + /// /// Dispose of cosmos client.It will get disposed with client so not making it thread safe. /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Collector/ITelemetryCollector.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/ITelemetryCollector.cs new file mode 100644 index 0000000000..aef7a5efc4 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/ITelemetryCollector.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using Microsoft.Azure.Cosmos.Telemetry.Collector; + + internal interface ITelemetryCollector + { + /// + /// Collect information required to collect the telemetry information for the cache. + /// + /// Cache Name + /// delegate that encapsulates a method that returns a CacheTelemetryInformation object + public void CollectCacheInfo(string cacheName, Func functionFordata); + + /// + /// Collect information required to collect the telemetry information for the operation. + /// + /// delegate that encapsulates a method that returns a OperationTelemetryInformation object + public void CollectOperationAndNetworkInfo(Func functionFordata); + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollector.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollector.cs new file mode 100644 index 0000000000..9570fcd56a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollector.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry.Collector +{ + using System; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Tracing.TraceData; + using Microsoft.Azure.Documents; + + internal class TelemetryCollector : ITelemetryCollector + { + private readonly ClientTelemetry clientTelemetry = null; + private readonly ConnectionPolicy connectionPolicy = null; + + internal TelemetryCollector( + ClientTelemetry clientTelemetry, + ConnectionPolicy connectionPolicy) + { + this.clientTelemetry = clientTelemetry; + this.connectionPolicy = connectionPolicy; + } + + public void CollectCacheInfo(string cacheName, Func functionFordata) + { + try + { + TelemetryInformation data = functionFordata(); + + if (data.CollectionLink != null) + { + GetDatabaseAndCollectionName(data.CollectionLink, out string databaseName, out string collectionName); + + data.DatabaseId = databaseName; + data.ContainerId = collectionName; + } + + this.clientTelemetry?.PushCacheDatapoint(cacheName, data); + } + catch (Exception ex) + { + DefaultTrace.TraceError($"Error while collecting cache {0} telemetry. Exception : {1}", cacheName, ex); + } + } + + public void CollectOperationAndNetworkInfo(Func functionFordata) + { + try + { + TelemetryInformation data = functionFordata(); + + this.clientTelemetry?.PushOperationDatapoint(data); + + // Collect network level telemetry only in Direct Mode + if (this.connectionPolicy.ConnectionMode == ConnectionMode.Direct) + { + SummaryDiagnostics summaryDiagnostics = new SummaryDiagnostics(data.Trace); + this.clientTelemetry?.PushNetworkDataPoint(summaryDiagnostics.StoreResponseStatistics.Value, data.DatabaseId, data.ContainerId); + } + } + catch (Exception ex) + { + DefaultTrace.TraceError($"Error while collecting operation telemetry. Exception : {1}", ex); + } + } + + private static void GetDatabaseAndCollectionName(string path, out string databaseName, out string collectionName) + { + string[] segments = path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + + PathsHelper.ParseDatabaseNameAndCollectionNameFromUrlSegments(segments, out databaseName, out collectionName); + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollectorNoOp.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollectorNoOp.cs new file mode 100644 index 0000000000..a1d286fe94 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryCollectorNoOp.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry.Collector +{ + using System; + + internal class TelemetryCollectorNoOp : ITelemetryCollector + { + public void CollectCacheInfo(string cacheName, Func functionFordata) + { + //NoOps + } + + public void CollectOperationAndNetworkInfo(Func functionFordata) + { + //NoOps + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryInformation.cs b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryInformation.cs new file mode 100644 index 0000000000..a8210fb0a4 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/Collector/TelemetryInformation.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry.Collector +{ + using System; + using System.Collections.Generic; + using System.Net; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + + internal class TelemetryInformation + { + internal HttpStatusCode StatusCode { get; set; } + internal SubStatusCodes SubStatusCode { get; set; } + internal OperationType OperationType { get; set; } + internal ResourceType ResourceType { get; set; } + internal string ContainerId { get; set; } + internal string DatabaseId { get; set; } + internal long ResponseSizeInBytes { get; set; } = 0; + internal string ConsistencyLevel { get; set; } = null; + internal IReadOnlyCollection<(string regionName, Uri uri)> RegionsContactedList { get; set; } + internal TimeSpan? RequestLatency { get; set; } + + internal double RequestCharge { get; set; } // Required only for operation level telemetry + internal string CollectionLink { get; set; } = null; // Required only for collection cache telemetry + internal ITrace Trace { get; set; } // Required to fetch network level telemetry out of the trace object + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs new file mode 100644 index 0000000000..2f78df0913 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs @@ -0,0 +1,134 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Cosmos.Handler; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Telemetry.Collector; + + internal class TelemetryToServiceHelper : IDisposable + { + private ITelemetryCollector collector = new TelemetryCollectorNoOp(); + + internal static int DefaultBackgroundRefreshClientConfigTimeIntervalInMS = (int)TimeSpan.FromMinutes(10).TotalMilliseconds; + + private readonly AuthorizationTokenProvider cosmosAuthorization; + private readonly CosmosHttpClient httpClient; + private readonly Uri serviceEnpoint; + private readonly ConnectionPolicy connectionPolicy; + private readonly string clientId; + private readonly GlobalEndpointManager globalEndpointManager; + private readonly CancellationTokenSource cancellationTokenSource; + + private ClientTelemetry clientTelemetry = null; + + private TelemetryToServiceHelper() + { + //NoOpConstructor + } + + private TelemetryToServiceHelper( + string clientId, + ConnectionPolicy connectionPolicy, + AuthorizationTokenProvider cosmosAuthorization, + CosmosHttpClient httpClient, + Uri serviceEndpoint, + GlobalEndpointManager globalEndpointManager, + CancellationTokenSource cancellationTokenSource) + { + this.clientId = clientId; + this.cosmosAuthorization = cosmosAuthorization; + this.httpClient = httpClient; + this.connectionPolicy = connectionPolicy; + this.serviceEnpoint = serviceEndpoint; + this.globalEndpointManager = globalEndpointManager; + this.cancellationTokenSource = cancellationTokenSource; + } + + public static TelemetryToServiceHelper CreateAndInitializeClientConfigAndTelemetryJob(string clientId, + ConnectionPolicy connectionPolicy, + AuthorizationTokenProvider cosmosAuthorization, + CosmosHttpClient httpClient, + Uri serviceEndpoint, + GlobalEndpointManager globalEndpointManager, + CancellationTokenSource cancellationTokenSource) + { +#if INTERNAL + return new TelemetryToServiceHelper(); +#else + if (!connectionPolicy.EnableClientTelemetry) + { + return new TelemetryToServiceHelper(); + } + + TelemetryToServiceHelper helper = new TelemetryToServiceHelper( + clientId, connectionPolicy, cosmosAuthorization, httpClient, serviceEndpoint, globalEndpointManager, cancellationTokenSource); + + helper.InitializeClientTelemetry(); + + return helper; +#endif + } + + public ITelemetryCollector GetCollector() + { + return this.collector; + } + + public bool IsClientTelemetryJobRunning() + { + return this.clientTelemetry != null; + } + + /// + /// Trigger Client Telemetry job when it is enabled and not already running. + /// + private void InitializeClientTelemetry() + { + try + { + this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( + clientId: this.clientId, + httpClient: this.httpClient, + userAgent: this.connectionPolicy.UserAgentContainer.BaseUserAgent, + connectionMode: this.connectionPolicy.ConnectionMode, + authorizationTokenProvider: this.cosmosAuthorization, + diagnosticsHelper: DiagnosticsHandlerHelper.Instance, + preferredRegions: this.connectionPolicy.PreferredLocations, + globalEndpointManager: this.globalEndpointManager); + + this.collector = new TelemetryCollector(this.clientTelemetry, this.connectionPolicy); + + DefaultTrace.TraceVerbose("Client Telemetry Enabled."); + } + catch (Exception ex) + { + DefaultTrace.TraceWarning($"Error While starting Telemetry Job : {0}. Hence disabling Client Telemetry", ex.Message); + this.connectionPolicy.EnableClientTelemetry = false; + } + } + + public void Dispose() + { + this.StopClientTelemetry(); + } + + /// + /// Stopping a client telemetry job means now there shouldn't be any valid collector available, Hence switch it to NoOp collector. + /// Along with it, send a signal to stop client telemetry job. + /// + private void StopClientTelemetry() + { + this.collector = new TelemetryCollectorNoOp(); + + this.clientTelemetry?.Dispose(); + this.clientTelemetry = null; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs b/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs index ed5ad111d7..b9d9c60d36 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/VmMetadataApiHandler.cs @@ -85,11 +85,11 @@ static ValueTask CreateRequestMessage() azMetadata = await VmMetadataApiHandler.ProcessResponseAsync(response); - DefaultTrace.TraceInformation($"Succesfully get Instance Metadata Response : {azMetadata.Compute.VMId}"); + DefaultTrace.TraceInformation($"Succesfully get Instance Metadata Response : {0}", azMetadata.Compute.VMId); } catch (Exception e) { - DefaultTrace.TraceInformation($"Azure Environment metadata information not available. {e.Message}"); + DefaultTrace.TraceInformation($"Azure Environment metadata information not available. {0}", e.Message); } } @@ -154,7 +154,7 @@ internal static string GetCloudInformation() } catch (Exception ex) { - DefaultTrace.TraceWarning("Error while generating hashed machine name " + ex.Message); + DefaultTrace.TraceWarning($"Error while generating hashed machine name {0}", ex.Message); } return $"{VmMetadataApiHandler.UuidPrefix}{Guid.NewGuid()}"; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index fd097032d9..fb6a5fb720 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -50,14 +50,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ]]> @@ -116,23 +117,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -454,14 +461,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -503,23 +511,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -841,14 +855,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -890,23 +905,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1228,14 +1249,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -1277,23 +1299,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1615,14 +1643,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -1664,23 +1693,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2002,14 +2037,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -2051,23 +2087,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2389,14 +2431,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -2438,23 +2481,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2776,14 +2825,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -2825,23 +2875,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3163,14 +3219,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -3212,23 +3269,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3550,14 +3613,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds └── Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -3599,23 +3663,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3959,35 +4029,36 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ├── Batch Retry Async(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -3999,35 +4070,36 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ├── Batch Retry Async(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -4039,35 +4111,36 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ├── Batch Retry Async(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds @@ -4079,35 +4152,36 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── Create Trace(00000000-0000-0000-0000-000000000000) Batch-Component 00:00:00:000 0.00 milliseconds ]]> @@ -369,23 +377,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -459,23 +473,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -547,23 +567,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -635,23 +661,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -723,23 +755,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -791,23 +829,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -855,23 +899,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -919,23 +969,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1165,14 +1221,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -1195,14 +1252,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -1225,14 +1283,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -1255,14 +1314,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -1391,23 +1451,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1485,23 +1551,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1577,23 +1649,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1669,23 +1747,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1918,14 +2002,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds ├── Change Feed Iterator Read Next Async(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds @@ -1947,14 +2032,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds ├── Change Feed Iterator Read Next Async(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds @@ -1976,14 +2062,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds └── Change Feed Iterator Read Next Async(00000000-0000-0000-0000-000000000000) ChangeFeed-Component 00:00:00:000 0.00 milliseconds @@ -2005,14 +2092,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds ]]> @@ -2140,23 +2228,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2230,23 +2324,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2318,23 +2418,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2406,23 +2512,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2651,14 +2763,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2681,14 +2794,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2711,14 +2825,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2741,14 +2856,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Get RID(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds └── ChangeFeed Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2877,23 +2993,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2971,23 +3093,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3063,23 +3191,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3155,23 +3289,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3379,56 +3519,60 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds │ ( │ [System Info] │ Redacted To Not Change The Baselines From Run To Run │ ) - └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - ( - [Client Side Request Stats] - Redacted To Not Change The Baselines From Run To Run - ) + └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + ( + [Client Side Request Stats] + Redacted To Not Change The Baselines From Run To Run + ) ]]> @@ -958,23 +990,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1056,23 +1094,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1154,23 +1198,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1252,23 +1302,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -1461,14 +1517,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -1496,14 +1553,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -1531,14 +1589,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ ( @@ -1566,14 +1625,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ]]> @@ -2366,23 +2454,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2464,23 +2558,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2562,23 +2662,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2660,23 +2766,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -2862,16 +2974,17 @@ │ │ │ │ [System Info] │ │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ │ ) - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.GatewayStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ [PointOperationStatisticsTraceDatum] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.GatewayStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ [PointOperationStatisticsTraceDatum] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2892,14 +3005,15 @@ │ │ │ │ [System Info] │ │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ │ ) - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) │ │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds │ └── Query Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Typed FeedIterator ReadNextAsync(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2928,14 +3042,15 @@ │ │ │ │ [System Info] │ │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ │ ) - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) │ │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds │ └── Query Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ├── Typed FeedIterator ReadNextAsync(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -2964,14 +3079,15 @@ │ │ │ │ [System Info] │ │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ │ ) - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [Client Side Request Stats] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [Client Side Request Stats] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) │ │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds │ └── Query Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds └── Typed FeedIterator ReadNextAsync(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds @@ -3000,14 +3116,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── Query Response Serialization(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds ]]> @@ -3059,24 +3176,30 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.GatewayStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run", - "PointOperationStatisticsTraceDatum": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Cosmos.GatewayStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run", + "PointOperationStatisticsTraceDatum": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3147,23 +3270,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3245,23 +3374,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3343,23 +3478,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3441,23 +3582,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -3653,14 +3800,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -3688,14 +3836,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( @@ -3723,14 +3872,15 @@ │ │ │ [System Info] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ ( @@ -3758,14 +3908,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ]]> @@ -4573,23 +4752,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -4671,23 +4856,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -4769,23 +4960,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } @@ -4867,23 +5064,29 @@ }, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.TelemetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RetryHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", + "name": "Microsoft.Azure.Cosmos.Handlers.RouterHandler", "duration in milliseconds": 0, "children": [ { - "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "name": "Microsoft.Azure.Cosmos.Handlers.TransportHandler", "duration in milliseconds": 0, - "data": { - "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" - } + "children": [ + { + "name": "Microsoft.Azure.Documents.ServerStoreModel Transport Request", + "duration in milliseconds": 0, + "data": { + "Client Side Request Stats": "Redacted To Not Change The Baselines From Run To Run" + } + } + ] } ] } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 86f16841b5..60f1b42df3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -54,14 +54,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [Client Configuration] @@ -81,14 +82,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) ├── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [Client Configuration] @@ -108,14 +110,15 @@ │ │ [System Info] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) └── FeedIterator Read Next Async(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ ( │ [Client Configuration] @@ -135,14 +138,15 @@ │ [System Info] │ Redacted To Not Change The Baselines From Run To Run │ ) - └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - ( - [Client Side Request Stats] - Redacted To Not Change The Baselines From Run To Run - ) + └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + ( + [Client Side Request Stats] + Redacted To Not Change The Baselines From Run To Run + ) ]]> CreateClientAndContainer(ConnectionMode mode, : this.cosmosClientBuilder.Build()); // Making sure client telemetry is enabled - Assert.IsNotNull(this.GetClient().DocumentClient.clientTelemetry); + Assert.IsNotNull(this.GetClient().DocumentClient.telemetryToServiceHelper); this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index a06dabf09c..8e45a72922 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -39,7 +39,7 @@ "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25, - "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 58054, + "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 64764.75, "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39044, "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs index 2baee14bd8..3403269950 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs @@ -6,7 +6,6 @@ namespace Microsoft.Azure.Cosmos.Performance.Tests { using System; using System.Globalization; - using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; @@ -19,11 +18,10 @@ namespace Microsoft.Azure.Cosmos.Performance.Tests using Moq; using System.Collections.ObjectModel; using System.Collections.Generic; - using Microsoft.CodeAnalysis.CSharp.Syntax; - using System.IO; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Newtonsoft.Json; + using Microsoft.Azure.Cosmos.Telemetry; internal class MockDocumentClient : DocumentClient, ICosmosAuthorizationTokenProvider { @@ -47,7 +45,18 @@ public static CosmosClient CreateMockCosmosClient( bool? isClientTelemetryEnabled = null, Action < CosmosClientBuilder> customizeClientBuilder = null) { - MockDocumentClient documentClient = new MockDocumentClient(); + ConnectionPolicy policy = new ConnectionPolicy(); + + if (isClientTelemetryEnabled.HasValue) + { + policy = new ConnectionPolicy + { + EnableClientTelemetry = isClientTelemetryEnabled.Value + }; + + } + + MockDocumentClient documentClient = new MockDocumentClient(policy); CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", Convert.ToBase64String(Guid.NewGuid().ToByteArray())); cosmosClientBuilder.WithConnectionModeDirect(); customizeClientBuilder?.Invoke(cosmosClientBuilder); @@ -61,11 +70,6 @@ public static CosmosClient CreateMockCosmosClient( }); } - if (isClientTelemetryEnabled.HasValue && isClientTelemetryEnabled.Value) - { - cosmosClientBuilder.WithTelemetryEnabled(); - } - documentClient.dummyHeaderNames = new string[100]; for (int i = 0; i < documentClient.dummyHeaderNames.Length; i++) { @@ -79,8 +83,8 @@ public static CosmosClient CreateMockCosmosClient( return cosmosClientBuilder.Build(documentClient); } - public MockDocumentClient() - : base(new Uri("http://localhost"), null) + public MockDocumentClient(ConnectionPolicy policy = null) + : base(new Uri("http://localhost"), connectionPolicy: policy) { this.authKeyHashFunction = new StringHMACSHA256Hash(MockDocumentClient.GenerateRandomKey()); @@ -212,6 +216,13 @@ private void Init() this.globalEndpointManager = new Mock(this, new ConnectionPolicy()); + this.telemetryToServiceHelper = TelemetryToServiceHelper.CreateAndInitializeClientConfigAndTelemetryJob("perf-test-client", + this.ConnectionPolicy, + new Mock().Object, + new Mock().Object, + this.ServiceEndpoint, + this.GlobalEndpointManager, + default); this.InitStoreModels(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs index ae5dccd2c8..d3d0e45653 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs @@ -36,6 +36,7 @@ public void HandlerOrder() { typeof(RequestInvokerHandler), typeof(DiagnosticsHandler), + typeof(TelemetryHandler), typeof(RetryHandler), typeof(RouterHandler) }; @@ -50,29 +51,6 @@ public void HandlerOrder() Assert.IsNull(handler); } - [TestMethod] - public void HandlerOrderIfTelemetryIsEnabled() - { - using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(enableTelemetry: true); - - Type[] types = new Type[] - { - typeof(RequestInvokerHandler), - typeof(DiagnosticsHandler), - typeof(TelemetryHandler), - typeof(RetryHandler), - typeof(RouterHandler) - }; - - RequestHandler handler = client.RequestHandler; - foreach (Type type in types) - { - Assert.IsTrue(type.Equals(handler.GetType()), $"{type} is not equal to {handler.GetType()}"); - handler = handler.InnerHandler; - } - Assert.IsNull(handler); - } - [TestMethod] public async Task TestPreProcessingHandler() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs index 8ea04f99a5..92a6e60038 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs @@ -34,16 +34,15 @@ public static CosmosClient CreateMockCosmosClient( Cosmos.ConsistencyLevel? accountConsistencyLevel = null, bool enableTelemetry = false) { - DocumentClient documentClient = accountConsistencyLevel.HasValue ? new MockDocumentClient(accountConsistencyLevel.Value) : new MockDocumentClient(); - CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey); - customizeClientBuilder?.Invoke(cosmosClientBuilder); - if(enableTelemetry) + ConnectionPolicy policy = new ConnectionPolicy { - documentClient.clientTelemetry = new Mock().Object; - - cosmosClientBuilder.WithTelemetryEnabled(); - } + EnableClientTelemetry = enableTelemetry + }; + DocumentClient documentClient = accountConsistencyLevel.HasValue ? new MockDocumentClient(accountConsistencyLevel.Value, policy) : new MockDocumentClient(policy); + CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey); + + customizeClientBuilder?.Invoke(cosmosClientBuilder); return cosmosClientBuilder.Build(documentClient); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs index 12d776fb38..b0c29eb016 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs @@ -15,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.Tests using Microsoft.Azure.Cosmos.Common; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Collections; @@ -27,14 +28,14 @@ internal class MockDocumentClient : DocumentClient, IAuthorizationTokenProvider, Mock partitionKeyRangeCache; private readonly Cosmos.ConsistencyLevel accountConsistencyLevel; - public MockDocumentClient() - : base(new Uri("http://localhost"), MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey) + public MockDocumentClient(ConnectionPolicy connectionPolicy = null) + : base(new Uri("http://localhost"), MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey, connectionPolicy) { this.Init(); } - public MockDocumentClient(Cosmos.ConsistencyLevel accountConsistencyLevel) - : base(new Uri("http://localhost"), null) + public MockDocumentClient(Cosmos.ConsistencyLevel accountConsistencyLevel, ConnectionPolicy connectionPolicy = null) + : base(new Uri("http://localhost"), connectionPolicy) { this.accountConsistencyLevel = accountConsistencyLevel; this.Init(); @@ -261,6 +262,14 @@ private void Init() this.MockGlobalEndpointManager.Setup(gep => gep.ResolveServiceEndpoint(It.IsAny())).Returns(new Uri("http://localhost")); this.MockGlobalEndpointManager.Setup(gep => gep.InitializeAccountPropertiesAndStartBackgroundRefresh(It.IsAny())); SessionContainer sessionContainer = new SessionContainer(this.ServiceEndpoint.Host); + + this.telemetryToServiceHelper = TelemetryToServiceHelper.CreateAndInitializeClientConfigAndTelemetryJob("test-client", + this.ConnectionPolicy, + new Mock().Object, + new Mock().Object, + this.ServiceEndpoint, + this.GlobalEndpointManager, + default); this.sessionContainer = sessionContainer; } From f56944ef55fef63549067823d6274d867a44c065 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Wed, 23 Aug 2023 08:30:36 -0700 Subject: [PATCH 180/337] [Internal] Automation: Adds logic to tag customer-reported issues (#4047) * Added customer-reported label * Changing condition * padding * more padding * permission name * padding --- .github/policies/resourceManagement.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml index 8207a0708a..7d78118b0e 100644 --- a/.github/policies/resourceManagement.yml +++ b/.github/policies/resourceManagement.yml @@ -38,6 +38,20 @@ configuration: - addLabel: label: needs-investigation description: + - if: + - payloadType: Issues + - isAction: + action: Opened + - not: + or: + - activitySenderHasPermission: + permission: Write + - activitySenderHasPermission: + permission: Admin + then: + - addLabel: + label: customer-reported + description: Identifies issues created by users without write access as customers - if: - payloadType: Pull_Request - hasLabel: From 83dd4b54348a4b2d172d1bbcfd830134363e212b Mon Sep 17 00:00:00 2001 From: David Chaava Date: Wed, 23 Aug 2023 21:57:27 +0200 Subject: [PATCH 181/337] [Internal] Benchmark tool: Adds requests diagnostic data capture and upload to storage (#3926) * azure-cosmos-dotnet-v3/issues/3889 add diagnostics data capturing during bechmark and storing into blob storage after finish * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh * fix bug * fix review comments * fix comments * fix comments * fix case * add tests and refactoring * fix * unify logging * add summaries * fix method summary * fix BOM * fix review comments * fix comment * fix line breaks * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * catch exceptions * add container prefix * ResultStorageContainerPrefix * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs Co-authored-by: Kiran Kumar Kolli * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs Co-authored-by: Kiran Kumar Kolli * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs Co-authored-by: Matias Quaranta * fix comments * fix comments * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * make BlobCLient Lazy singleton * new file: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * check on diagnostic colletiong * remove locks and improve logs appending * removed unnecesary directory * removed unnecesary directory * removed unnecesary directory * new file: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md * add dashboard * fix arm template * change branch * fix * add dashboard name * fix dashboard * add logging * fix * trace error * fix devide zero * add trace errors * fix * fix * fix * fix * fix * migrate to text writer * fixes * diagnostic logs * add diagnostic logs * remove flush and reset * metric collection window lock * collection window * force flush every n seconds * fix bug * fix * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md Co-authored-by: Matias Quaranta * change deafult metric interval * constant * fix container creating conflict issue * change azuredeply branch name * remove ArmTemplate folder * fix DiagnosticLatencyThresholdInMs default value --------- Co-authored-by: David Chaava Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- .../Tools/Benchmark/ARMTemplate/README.md | 73 -- .../Tools/Benchmark/ARMTemplate/arm1.png | Bin 73958 -> 0 bytes .../Tools/Benchmark/ARMTemplate/arm2.png | Bin 85941 -> 0 bytes .../Tools/Benchmark/ARMTemplate/arm3.png | Bin 15913 -> 0 bytes .../ARMTemplate/benchmarkTemplate.json | 154 --- .../Benchmark/ARMTemplate/parameters.json | 39 - .../Tools/Benchmark/ARMTemplate/run.sh | 2 - .../Benchmark/AzureVmBenchmark/README.md | 111 ++ .../AzureVmBenchmark/azuredeploy.json | 1160 +++++++++++++++++ .../AzureVmBenchmark/scripts/custom-script.sh | 28 + .../AzureVmBenchmark/scripts/execute.sh | 9 + .../AzureVmBenchmark/system/cloud-init.txt | 16 + .../Tools/Benchmark/BenchmarkConfig.cs | 10 + .../Benchmark/BenchmarkLatencyEventSource.cs | 5 +- .../Tools/Benchmark/BenchmarkProgress.cs | 50 + .../Tools/Benchmark/CosmosBenchmark.csproj | 1 + .../Benchmark/Fx/DiagnosticDataListener.cs | 224 ++++ .../Tools/Benchmark/Fx/MetricsCollector.cs | 16 +- .../Benchmark/Fx/MetricsCollectorProvider.cs | 50 +- .../Benchmark/Fx/ParallelExecutionStrategy.cs | 9 +- .../Benchmark/Fx/SerialOperationExecutor.cs | 6 +- .../Tools/Benchmark/Fx/TelemetrySpan.cs | 8 +- .../Tools/Benchmark/Program.cs | 111 +- .../Tools/Benchmark/README.md | 5 + .../Tools/Benchmark/Utility.cs | 6 + .../CosmosBenchmarkTests.csproj | 23 + .../Fx/DiagnosticDataListenerTests.cs | 54 + 27 files changed, 1845 insertions(+), 325 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm2.png delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm3.png delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/CosmosBenchmarkTests.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/Fx/DiagnosticDataListenerTests.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md deleted file mode 100644 index 7821e1eefd..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Running benchmarks on ARM Tempaltes - -[ARM Templates](https://learn.microsoft.com/azure/azure-resource-manager/templates/) makes executing the Azure Cosmos DB SDK Benchmark extremely easy, with very few steps involved. Plus, it lets you test and evaluate performance quickly on multiple resource (CPU/RAM) configurations and across multiple Azure regions seamlessly. - -For the below steps, you will **need an Azure Subscription**. - -## Steps - -### Deploy with one click - -Just click in the **Deploy to Azure button** and it will guide you into automatically configuring, deploying, and running the benchmark. - -[![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-cosmos-dotnet-v3%2Fmaster%2FMicrosoft.Azure.Cosmos.Samples%2FTools%2FBenchmark%2FARMTemplate%2FbenchmarkTemplate.json) - -Please populate the `endpoint` and `key` for your Azure Cosmos DB account. You can [obtain these from the Azure Portal or through CLI](https://learn.microsoft.com/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key#primary-keys). - -Optionally you can modify the other parameters, such as the `throughput` for the container that will get created, the amount of `documents` to insert, the degree of `parallelism`, and if you want the container to be deleted after the benchmark is run (`cleanUpOnFinish` `true/false`). - -Additionally, the template lets you customize the size of the container instance that will be deployed, which you can make as similar as possible to the instance you will be running in production to simulate results. - -### Deploy with Azure CLI - -First open the `parameters.json` file and populate the `endpoint` and `key` for your Azure Cosmos DB account. You can [obtain these from the Azure Portal or through CLI](https://learn.microsoft.com/azure/cosmos-db/secure-access-to-data?tabs=using-primary-key#primary-keys). - - Next, modify the other parameters, such as the `throughput` for the container that will get created, the amount of `documents` to insert, the degree of `parallelism`, and if you want the container to be deleted after the benchmark is run (`cleanUpOnFinish` `true/false`). - - If you're deploying the template to a resource group that does not exist you must create one first. Please note that the name of the resource group can only include alphanumeric characters, periods, underscores, hyphens, and parenthesis. It can be up to 90 characters. The name can't end in a period. To create a resource group use the following command: - ```bash - az group create --name $resourceGroupName --location $location - ``` - - To run the benchmark first navigate to the directory the `benchmarkTemplate.json` and `parameters.json` files are stored and use the Azure CLI with the following command: - ```bash - az deployment group create --resource-group $resourceGroupName --template-file benchmarkTemplate.json --parameters @parameters.json - ``` - -### The Benchmark - -Once you create the benchmark, it will do the following: - -1. It will create a Linux container named `cosmosdbsdkperf` and provision an image with NET 6 inside an instance with the configured CPU and RAM. -![Provisioned Container Instance](./arm1.png) -2. Clone the Azure Cosmos DB SDK repository with the required files -3. Execute the benchmark and provide output logs -4. Stop the instance - -While the container instance is running (or after), you can either use the Azure Portal or the Azure CLI to check the benchmark results with: - -```bash -az container logs -g $resourceGroupName -n cosmosdbsdkperf -``` - -Additionally you can check the logs in the Azure Portal by navigating to the container instance and clicking on the **Logs** tab. - -The logs will show the information, including the initial parameters: - -![Initial benchmark parameters](./arm2.png) - -And the results: - -![Benchmark results](./arm3.png) - -### Clean up - -If you want to remove the Benchmark instance, ypu can delete the container from the Azure Portal. You can also do so from the Azure CLI: - -```bash -az container delete -g $resourceGroupName -n cosmosdbsdkperf -``` - -You can also delete the Benchmark instance from the Azure Portal by navigating to the container instance and clicking on the **Delete** button. - -**Remember to delete the Database and Container** that were created for the Benchmark in your CosmosDB account if you did not use the `CLEANUPFINISH` parameter as `true`. diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/arm1.png deleted file mode 100644 index c740b8b3d7528c4f7232b24da55fee45cdb4f6c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73958 zcmdqJhgVZw+r|mfL_}3OQlnBs=mA0qfjPe4yz|YPe_&=!)?%>^hb+xLd*9`ET{o{DnHg}O5;(=g#Kdj* z@SX(|6Gtx-(+Q80?7&ZMtxQ$|-q_vq?vx*4_@f!rR`0bTYPvB+?S!4K;s@hCPvP2 z+oOVB6`W%FCXc22W3y)S(6~?U2MblPte%J$rN)`P<%Q8#Xa2PCOgX zJ?`}^jFP@)kd*T3g5;znbLULH=O<>D7pE?zs30Bsh6*&-(wWZMeR-xAO~%XeD~7+# zR}bt)oB$U5AKe5V(acZ*m6YGa$ZH%tLYrJ-q~q4mjZ|UHkZkNRgIZ{kr((K-ueipw zh*iaj^km99lmsrBjh2VPB2F>=Biyb^{Nf)Ux&NDE6zzic9DS|{e|<4k$zGu^U8>$~ zD1QQR5UCL`|8E~!vjOHQEv|LO$Nad9$F<~1{6QU@;sLBi4^A#mdvNaNwU3ck4M$5- zzYXzFmav{6Hl~jc-(5BAPnQx8&Q&@uV{;RSdudZ0S!-`;-{_rDARYALLCd;1qFVtW zj)48L=W2GUhQ7CMHK%NCeJ=mIoqi|i?2IMU(y1G&s(*k5O7)ov?HzJzb;m8nlpM!0 zpO*{~O0$VKQ7k)_a%lE_2mE3lB-s^sHf5QI$f@R4DWK(`edEXLOYhEgCFEi2J%*G>LAlZ84NKy} zl6C`~2b#t5p4Fz|?k6_C{Q3Usnqitmqb_YU64TeyV9~nhlDl-%?o(&v@yCFLF)2%v zgHsCwIdUo5>a>DBRYLU^eKm(Dg(28f+db)i7`i=F)SVa9{~I-nFe}gyx301}lb*$% zU%S{BuR~vbk4(<53vH~lKHPpBr5myL487oWRJ%jH(+pZdB0a495Rm1NWu5VLm0fki zu9w^<;DU9v(DnQsGJ#NCA6-tLpNnI`WDj<}S%+j|(mjt#2;Q{_?ZL*XV_k24W^L(0 zzm8BH87w5cu$D>>C)SdS+&j4i@p)RNt#F=wN3mZi{8~Iro5d~g0jjDPWYq1vOvp2e zGh2D}j#7UxGsO=Rue{-dZ>SLZ)Zdc~e(xzB7 zN1AD#O3qzUm)F;T;UaAHY46PM|DMx7#V7a7_fIp7=qvXKo9ETD=QCAeTZ>pMQwZN# z4mdi5^Q)|K(L%;l2b7S#I)XPq{RCJlGAN7C1BD4Ie`B#hE~ zOQ2ItiToQUnVxT7r(s9MjZLnY#V_V4c&gA!Lh2Qtd}F1p;y{O^B+R;GVdTxi7@e_; zI_D+LZoa!_@DBLu-RGP$6#&gcna&1G&b`AakZRFKsb!`D1E^r~3APWxryIs9Eb|hY zj3{nvdx{+y1cSGiZ`;8m#y*;h!?!P<*Nu);_F55zN_9zy>57(f}Z>HRXnWWUYIDy(hLGt9$I$ zPhgJ!eWjHAe!#9d1o{2V68*I6)}J4v!~>sk2IbR|V5g z-wLUJGs#o*Yy!>NZtthxG@tgwm6>`>c5@3xzP=>&%=y5XL|h>XX$O3dw6S@)VA*Wu zqlmtu&pu@t6^RO>4V&O-L)khrCasT4qspJ?D>}JoM+8w@{O4X`8FXsYgVUnEWf?#y zTA>+V~uOX*rZK^p66};wMMqQigF=6>-7PvHc8?KkppAl(>(1L)X zwhs+t9Z+MQ+w+Dxp&PTxh2x?zhwEvI1|cz|qXTFh2r=CIP+Lvq2iZg>hW2off5tFBb1UD%`IHLA)Ty$zE z1kdva?W&rg>zh(el_j9KLt12}oYPa#u9N6Y!kHzVuTlw`cehQh{nF43A~r&1`b&-@ zmmk$*GuGoniCgVNzdfnVs}Z^Gijpy-@a6h}3>jPY2!1_IAe7cbVc~GID*F#8?0fx$ z!5!-=n*(IlI>%B@tY`Fa#|&L!gWI=*o9XwvG*9m%$M=!yg+{zG`wPcxT=Uew(F(0# z?l)irs&ZV)Ng!)*9L|{Q$#w~1aE*>g((Xj94ok=~y~46=e}K|n>W|>(q5t7h#LxrvO&4gM2Pc(M0zBRl1H8Nd2mPEI5S<^I;!XW!^fpayU)e&TIK8HaoA(; zBB=4+c^eJJZ2uk8H36AxXRC^&fMb#Nl3O5mQq~CCo-SqC-9~JOHq%6z+ThcN1{pW4 zjl9Rh2gYK9=CN7Cpa@cq?^f~svToOjx`pbGI!454)@!sxdSjX z1Js{Y`&b9q2ZXWAqa7UR`Au~ADc@OerMh=Fz-R05H)>*zrVPza`K!2{I& z|NJAQwyY^3$)xo*B>1C~P;QMF6zv0U@lxMnP>ESeBGhRkhrFHT30y7L9F#5c}qkwaI8&c~gn+*q2vQwoqrGPgT1HBeZ*o z0zcY_ErAI_x*>yY1QMLGxC`YJc+~K5rjiBXf{fI(e%@HQd%TzgtU8bv)?0}n@`4OaATGZiD)*z7Rab-gHsF< zTD93!wo{jY$5ENRJ9=0Y_A1rmV7$uK6!GJ406ekQuD=0qyx*|sGr1kUzj^L&(e^*P z=-t%^;VTO$jo_93JQ#kP+IqnPh=q#UGNkQ@omF=Pv*r#%5Y|D;S|SJJs`y;Gkw_V| zYYieGibb;aJZx*Dqw0kyZ(GAS4Kt)O4(S`{fQ%DR#TacQ>!dalE8V+8hi^y47dx3R9}1g=@=95hG&u910*2-0pH98d z4_@4XSf0gaDb8k50=obC67a%zfQfa@pCVey!y25w{lq2m2}+~Nv7)%meE|;c^!Kt= z9$K<>hW{YerL!Ap{oO5T1F6bYr$ukyEyHF*M7k?E=XwS{zPn~R%eV!UaH0W>TbK$<_mjH)4N{)|}amLv$#(_q(n4m75euWK>yww$$3(9)Mi8uXEcg|CJ>J zBX-Ebx94xqTq4I0A|0BuH}JI%p3=QgKS?K4kO%k<0*+{|t6|>)qC3@&h8QxAH!(!| zjD8-kvaXWeUBTaWRauEA6qOhkI(rjpTxX9ryDlr1xno6UOhYrj@{W26Fhj&yW;P}Z zJbs*7V5~(jd>#p$Wtsj1WJIMesp^3qbX@&8nZ+0)JiU{e8_t z(6YpYe;$^awgm0eaoBsdH^vdLFyt`A=+w0kGwi2EPO-x_yn8Xkbs z$}lEAX(Pm#jo@iPVQjMvQnl28x?blsa@Ue>0F4O8$8y%h^1&Vjy*=f_eBglu$2o)F z2s7PXF{dRbv8lLiK86qUZ$uyZ=L>21-KksZeKNC}rP|2S{z_!-YvSgIl)sPAxKO7( za(9=o-7N^q#RAPzYQ5)BHg#6ZZ1(7uMn_I_q@zpt2Og&6(V{2%Il3`%aL8j)7f&l| z09x;IZis_$|m--O7+d)At-MoZZ{`SeKgF_070t-QNrQ zAlds>jqJR#@UM{HI(KR+ZENMME3K4g+)NN!Qp0RI!IM_%Av+)24pyLbVSN@kx3*Mi z`*Wa@J8>sMUJs{ThghIbY&pQ%eKId>jyF1}QnZ==kyw-V1OS2rkAUX7L5?P@Ba*gY zJBkVxj8R{6BAxcHN$wUG@}9Tu&3$rw;Dw?ROf0YZ(wTKqt|syGA#TkdkG^6 zOyOy@JIpnImv?gXJkvJ|zk!TNBc}{Gr^$x4F|mdacuOc&MA774+zB=ebvA4fKHHB1 zj?=rjp5(m8p!_fXYZVx^3rMZ8@Wn5d?P=og2`34w5f4~ly90j zRG;Bju(GKE%kHj>t2zZH(fy~dwLauY^b~k?UQ&UKnA z|8yK9b&n{EvL?xQ$arK1zhYS)>8q@ay8epRK)}r0a6oNl43DtJ4f@`CVg}P?)EM+ zozzx^O)DX7l=j!Oti~ce@vHVnsBqkK$M<(%4ASp&@#Rjw9*Wn;6qebuDgW&XHp3bs z>YTMBdV$XWuu*y}V0qp!4HMyWg*1UIo&4;Y;L;&9-KH&usVY$T+~jx@+>j05uTq}; zTbH|ZdQIVx3Ws^HRS?tJkh|cT!A$K|{sHrz1B4cd2Pa#?-lOa#auGwx-x}~VDf9*J zsKF6BZGsF&Xu!da6jVFFNG>A(p{L_4CQqereWoMh{;v8r;L~7;YCB)cYYG+dC2}&M z>slUBL5xQC3RP6WOJ zf%{irJf#RZYCnl%SJV&V6Z9u){inGZNB`8y7SbZnZroTuL@fJ4nLOaUk7X zg{mY7zxIQ-kC)brDBiL>7?crS=$wso>Xz8+|IXUgv{T(GS+oyZg6RThG~@$w;l9W^}Vg9i|ThK6iVIqRwq0T zcg_fF(i&fn#iDe6;hae;g!*l;405qCOWtWOi?DJSO`}Psg?b~ZX%PjJusr`!=AhLPLPGr0Yb5=N+QFK0hsMOfpKn{)%S0>6DD}Al}T@)xC#R+M(X- zi6U^Mvm8)WDa*Ll<{a1*bt>mLSai8#n6_-(Gc@KezcJGe#j=In)_zkr(Z$+$n%kLG z96)>3n}4&~LmBlBr`9I7-jtE~a$TS^1lw}_B@F|?$>&pvtg_S&VoiY*Wd(-Nk-uTv zR1F_*j>ekVqoKJ=s<07@IuDG;^Ep`CQ7&3ZV<=p_>ZUU~nne+NQOe@s=chj~bfD!K zITZ1p)QO^J8MaQw2<|<`ek_Bf!FTeD7SEAJgeI%iF z@lu^z-&JB1wY}|$dy@a3@3;BK49OYN*538gqwf7brI^Kby!5O;h&m&f?!}VKIf`2Oz6%NhIx*2Wqy6jPd?`wPOyA&P?`VKK5W_HC zsu-M-?l?N;qL21$vx_eO{+8q-Gx2X}dDemQ07HpBAbG}g8F@9Yu^_c9aNZpiJUYsq zvmZP`F>qvN9%W$wCUVbr1~uMrcN~%^pqzQzHTstOGgztvxz;s{*dAeVqY$UD3y~?KSYHX9-sI3XKK!4jrUo_f#)1~=-fld_oY0nn&LL1Q0n#KP3`SSO(Cmeh5|}nkDCmr)dW-2sRD{)YK#ukO7%Kk@cLAOP+a_srT4b}?#=8qwGO`>t4rvtq!TQkpIu z?`FBUbr13f%x^wv3Ee<^f6Z$Q92N;#a8o*fkBt90d2V&=zi(q&|9|K$Z}ranU-y{& z*iOvh2?)Q z9pjk(e{_=;=+@a8XVL5&r5?CgO{+d8FNww+^hKUAM!j88_U^?a9WYB|Laj0VjPRhw z3j`N>TBd%xx=nEguS) z>*l5lQaQ7+*KWt!E+YUbNLFeMKX13ijT@$3v;+P-Cr-&S!$1RD95 zuN^J^sCzb{P_YFR(U3Wbh}ZPPy{Y38vjP;*g`bNs+V|gGQRdf){HN_;l5A1zCMD(a zzBp)Y(n-#xF24!&y&8EnLP$4&2b|Vm}7gHe*}sRt$ z8V^P9L~2*x#w{3Um3Y=Bx2ZIZ_Ses#f)&YC6#sQo;3GlHH+l2tDq~tbFamV>*iWT| zH_oczjAfcFGCVjf84}IT#B-sd@JF<0rSGg5%PAk@EZMZcr6J>SY3u7Y)!7nhg{m-w z+hDfdcE|SX0_kS}SJtfq^udZp9c|Z5bFJ2=TU<{i+0ofxAn94m1-s5jof2Q5 z*LUqc6qB*3Nh!Yn`ln@A5_<~zvWiKPsHR*?z(QR)d&ok+HNR#^^?YxRK2VTJpSybR z6PmL{(Q~L5=p8UEe-77IqBZ?~#S&qG4*`yB0sw!xsU}#KtqW4B7GHe@U2)SEP!U=rIl~ zio^aB=<_wAjE)Y-u$Hjj#p(~sMJ@j!*;uqEd***=`72JHUR+9B=%&R=+g( zu04YK(4QRWw^6>UQx;m-Q5P};u7J!)j(v2-pwM(snOUB9#?n>VR1&wKN`I2DW{LlY z2Np=MH9%6+;k@;kS+Y_NxgV; zQ3ZPzP|jr7wwEXlg;3jC!?%}5N&$>!QS;1R5&1aoM5;!xfPKf)`yWM{W994?w)-q4 z^629$_-JWx!$-%qFmsQgTwb>vCmDMl5e2L6P!3vt)B*|Drrqtg zqu&G?I(%EbA#f6&pH3nZ6NPTyU7tbA>$CHuK4;^~Mvrg^9Xula`l`S9^?R4JzF3g@ z(*2RAKjvl09$J<_czo|*Dg#rGI(SPz@8aE=`fXQP&c`%=~G z;Tf`)56-L-x}>{Ks>n8O2M`J^ee~=ABmC54k-v8A-qf! zobPBvH#Qrzmybd!s?j4wLH`NI(a3;>{#3%`8K)-um%$ss`P&Sr{=?HPwd z#DD7^?d$*fkt_*lVMU+MBVH?45qd$o$2T##DjAnBd3k~6GH5UCg&4CukEkIrdGujj zfk5Y*MMIYPpwCHsLj_aKA``slm>iF(KlqKcZ-lc5shSC)1?`(hF6{uRNI`XfB2cUC zc_*&PcSd8PBQUGs*~nds>mXlHl+xO)nM1y9jg?{QPvw2zX#q9hvkB~-` zel#xzf>E}Y>Pvt-HI)OYSL`MvWg|oDh$UunTh$m}9k9E?tL_=fERy;+?~)RmiZH3- z^$`2WwMpxUl`aT%LdK^07PAF+lV(GteQALEh3m6TKCRl;ciq(*Qf^u{+csG_O5su4Lby#cY+4knMQ&ec>qwc=rK#e`i9T7Qn4-~&-f zF7I8(Sx= zCZHd2EA1sUsS&nRz1w$fQs^qb>^`F8%S>{f@}izQH|bNe@IOZfEsdd`YBSxz9cE@hOXxuQbd! zrOIgByAFc$u>bT+KF!P}TsF)%>!<^g6*UC2rY8wAqSLgsS3>VBmG&4Ur-{frWiG)N z)chW!cj@)xK|D)ZMZ=VpC+;k~ep=dqTC7_GUNZLc%8Eh70AO2O5>%kT1}2|zNH2U&XF!5RHW6yoy%uhLsiic8ZHGqOiXve zE?jwf{nf=jRkh3D1#c{z{r-UCL4iY1XAFnS&CTP>SX%> z;%dO3c}|>z`C#_#RjDg{sqQO`(vW&2y|?}?oHTmh@|;-k%Gh4|@RnMSDekn0*1g$J z>!HEV){2%7$V4x)=bFg$J0-~Zzm~bOR%$H0D{Zf)g4#PLY4WLD%h4@Db4N$7Frfra zb4M2;^y9<(QYErJ7$ogap%Fucnx4`O^fTc+1Nc(G%Wc~5mA?W^gwdvYkCFpEf!OTL z6NU2}OqqlMLgFq9D85^%Vf57^a_f)er}6`%>>KY%_a7w~o($XIW=ito6(ex;Bc~cN z0FE*Mtwl?;>#m6VfSXm~ejl&iiPs5(5jx_n#WW-~I_OD;6ud*D+fvQUXbXkIL&S*d ztiWk}EHXqDS8oss87Xcd2^<2&hD4$(wZ>^1Acn@fE7qkmbRY5Xx62-mxMRjqLL>v@ zCuLhx9YmhIAF$XfuKQLP&^&16jI0i)Ht)wP^pOw9Z+9=Ht#|S0-kQNgQW;c_)2AhS zKe)C9ktQ*2vl|WrBf-*-#Lz;z(cdC#l`J=AKO{_Wpqx-qlWQxRzq>H;4`B`TA-#AG z<54%m5@;3=CIq1!YQui|@Fy(B>pk>WXPiRJ*As9?BLNc`tToAHbLA2AzVu8cK-v1M zC+bUsNEQ-_Ar(sSek;pf_~jX5%#r#GE2`3}<|+_9_H5q-^`(~DJn?TM^*?NGefr~6 zS%d`lSyF(o!1on=d&0d}0^_R&Q4r+Ag0i{G@X-^wBFX(3(*3DF-jskgW=DZup~AAY ziROGv@cC%}p^SD~%QW27Bv;{n$m*mNp#7&zHWF24j(LO+S`Ih6c^3YLM*t_gbq z1N}sHZhr6WlL^jzGZ8yGSwQro4{Gf(&Ds<hbFE`wx9xN;j&>qa99~uP&;mW)LDhP;>aX)NYhL!M{hw<_7G9Ehbl483Gs@ zH&mTqN1DN_o4s1|=2Nu;xX=A4Fgcn&SM};=z-r8;4CRT`F4-CgTr30YOD>S4`j;9;L1VGd&JB2`LTGUi@a@(vofvaS_v)E zFD4Ms-aLF<`6##Uw?c412mOm9$W~ul;t@mKzOH1kx$>`nFKJD4zP@K)c-Xc0zwt;! zQ@aUqqN#|$0OYT@vXR$(`Y+Gi=J^~%o7B!fsyTy~8v%q8((}4dqBHG~B7gnK^M5?r z+ZxY=`u^F`!vU2QgYA#KUAtT2vAC87!m?m3MULv$3atdmv@g@Gs{>fRpHY&p+&YcP*ja%4M>+4oax;7`zk}OdkDVLJ+h05K2^5UaPdO zl5o;ly$NxNwg)T_%LE0#m4*tB>Pdul_`^b-C=(Q5Iql^ujFAH%dnV8hI^e6FeSjLh z+1Zzfk^;1L1&9)oy)K4KOiPMD^AS~QpvE6rs$iIT(KzGsV1L#e0drg9>o~X zN?sK(5KT||w1;GWrV+e8FRxZJRUbo)=6}LFRN%Vzn?v+r!kINphr_4GafanRw(;iy z`|LZw&yyWhQhOyn;b90l8&r532SdxOC4Kbzebu7Q&CqgxRGT6{!}#yL!K_X69%S44W!TtVl0rzK>+W5m0-(hj^`WpFDiP57hggsNg)BLwgRt zrf+_Wh&JVtBz8D(_S~jM*kvDNzMK;nXm9dbR8W!o?@5`@;({%!X50Ze6?apg@-JY$ z0jqvVa0mLtJr|BLJ@UqbWEH1R@WsA^7%W2Db$sUZUU<(efRRw z2K6{+fgHYk;3eRs>jc7x9#iQXN4}4FgmrEv3Mwn~=rvn6E8g!rC(iUJl{ETxYZ{nZpsJXMu=%z`S zrW$2PJM?&^5H(H?mlXg=v_1Tpbz`;_itfUd@H8)C3*`eB2XALM z<|_F}XH`S%EtirO!{Ls(q2w+NpA00t@W^+0x9XC-)6=8Sf371{ue6vcZ{QBW6lEtH zm`v>`HFP83h?yyNQ-7mz2Vp!w11zE_mzGt-{&78wrMfmnt=$pgcX*BL?69%%Tu^OH z?9;4Fcf)$<^MK^)88PK#z0(rA46Rw;P<2cJHY zj(#2TI%UK+e+io>!!4-vshqWpthJaRYC^N$aLusU!@utgirkH9dUhL^?%T}13W)D+ zpe?fv|Hk6V!0BChZHR0wHTB@_o<9U+iGuZK$jCdPLX>ClF$W|`y;!N z7iF&|R7bs6KI8i1wbX6ow-4){Yi1Mghpeaa zaHed84gJE|qjYKeQDRHJqJf#EmyAWpzv##z{x|*nlH{En#lIeZU}|9d8f^4#fUwtO z@sHR0GwEb*S2;}=DVL6XG}LN|X0eksKh{?Sb*=@sgVzBy7A&Q+BJq%7hS3*(Ul6kb z>jGB2ZLu)?G=Lwx88c3}HCr#vp*?w*&)Nc^gu8B-+CLy){(0!#J&UFwe)L><#&adFYT3fZr?KS)njyJFeeD`E*-4=LxkAHm zpIJ*ah1Ce7gj)jWcm(gP#u{vPP~P=MMXyPZKwmARx)$fk#OxCA$)81k$>8#5~~9j@xE8t&%lv zxPR_%J5!VaM;}Kw9BxzOC5q@@^d5ndb3K*F2z`fZnqOB;aukh|MYK)Tx6F}oq6xDb zBt`c2!r?3%yTgM4dDGHBWJ*njs(zl00N%OY!+{drC4E6-N!N_|M}q` z=tZ-RC>#sM&yt?rOMWtgYgS=iO|X6$?bsT!uF%f%AnD={6p=h{8;zgaLp5$#)jGGE z)J7|MVp3<@>Aiqi(gWO!z9@^z7&;DQO|W?on$*%U*%(2zas$1)+QQE@&0nuw(h#aP zqY935i15u*Spz|ioC9%|xvEt*HK_o0?aPC8oLja(4GhINec?G?w_CjeafgDCWnHI1@2wrelDf4>z? zQ-<2akU!+RN2KXEg`=7Nl|&|fq~K`Ye1*dJFX>O9k$e5S$~4pDY_lLKnT0zXGL^5x=p_E(};##-ttkju1D zfwuxC!$r@pg;f8P@MHbQAeRHe*N6ayWxQ*~W0eK3-GA#=16%U2hq=`_xBpR=KY8Oi zAuj1$rk4FFdYXKBNLVNM&$(;&lm_rx*KY`X#}ye{B-?z`1B{Z5XdlkCLmcUh+{dU) zC5VC|`=^?~zo!Q}a0o16c$rbgD62mfp$P-=8m20JZmi*X{waLOE1HDNY+J+}GeQk~ zXWHCBTgb2Nep^>@+)fBB9xysVsgS1+=Ih5gEypVva#OMTRZ>p*-2=_D7a0Y6|C0ip zvWk*&0-ab($jUztWVNCW8iGipKddYwE+Zq)iyK+>70Sbk5>DQKb4fYFqv21SXRXv3 zAK}%&;|@}Y&W+Dcb(Y(iLCI$bpPtebaL-FTFt+a9J0t}t{w95@XGwPBjNQwCze(+D zi1yJ&sj+_OsK){>Z<7JUO>~ z`?MYOQ}}Rsp%I|@86SleZC+fi_SxxGq9b=Wgm4{o<XbgQ13{wsCzPlDb6QEu6NzE6r z<81f$EY&!aC!H2OYHXWYcA^oFqqD^E+HPJW5rdo;B#oAMbQ_ZNJ!l8y+7s5r_}_gm zx#@T7Jh4w+f^bG08YQy^qPwZ{QmMvmVg9D}I$wg08leOgtn}XM6b!`8kDRWeKZy8u zWx6Ge6Gf!9z+Ot@0&!`3?DVdm{`dpWELG>2E^@oV*~~v+DjJZlvgp+HDa#W$s7`>} zaiTbL=eZihW0HR3jgjKXLPY+hup{c!J;-=n>0gycBWTsF`&QKS-O0334hn<5o3ZgA zQNgLjJGArQ?A6Bv)sbR$^yY`>r<`S?m}+_cG^P}@>CT7(0z)R`^Ut>X#<)pL{mXe{ zy`VXfi^8tfESw2E!eocOPkS?N0uH(f4>zC$}Tngj{SyJ6F_M+CDx{^t2q=pu-Fdx6c1y$!OIF*PI#BiZ9mQ@d9Z(G(A)1eV(C{ z$CbUbN1h_2iz`18Rt788Vkd%bItg2-mEAXv#1*{N=gI^+gbbJH14E4v zFBor=O73ktef=>nbL0s#q52{4KIih}E*Y;~CF&i)K|~95LvauulTtLza(5YW|ThyDSd?x=i)J zrG9`{nVL!?&4V|G^(f8E>TLV54W;kcWdX(ZYJ9@!OnsX;sUkArI3sXLv>_?TQ7z`{ z#r^!d?FbfBqJZ1*9!W8zHf;(N1itek@=){^$?UR6o1JxNoRB0mB1rh1`8xe)~PwZ51Dj(^FG zxpg|mBvw~Dyk30gvKaCB;_Ld>pc3N0tNX%uC1KQ?RFLjli`p0b^Q}^mgNkQjEO56VJ~^yX@N z1>@W?h>5KVg6CQz6Sz9epF-u6XOCWHsQu}ABT1tyqycQx;IGUD+AU=(2Do+J3AcB5 zUtk)5d7k}<#|XgHTR$@?`$^}l={v0#C5CB}tf~!cMdiDK_`dGMyj9SV&rIF@J<&~K za8iK06i1TxHPrn+>r zO#GVA0A28yDQBo_KN4^P2}5W5%Jt)qROB3*Oio?A`S>M%^Wtcv&UJJPqT!|Qql`+C z1^;LcGkev$2$BCO3WUjyGM>wrjwSW-o&zi?hP}nd{KJDZz|Uzs+Xi2FBmYvnA(W+E z9hibCS)FY+08HENpxwssU2k>3(4dZP*M8WSuU_x=uy8hLW=(xC*0(uRv`sidOHe&< zKBW?vNm*BFR4CRTXw5|nZ(rtc!76L>J(p%lkW{bp%mTV@c9hxfL9TK{X1?JvL8;wHaa{QLw#1i#v0XxJ+H8HbL+g;)g7H8d*P{F_ zs_hj{iv&Q;lXKbwwCedbYaMy7nRsm}?j0!2C1PtZM=?QLd4Fd^((KUGDD%dZ9EF$F z&(X8x*c{ECRnZyHd%dL=H_~~^&95y~UHD2mzo>IFsHcbn!HbzvN(PMfwde@n_L|)s zV21wK5O74TRse(aCDH%!o5AOPy9%+Fxbk-=3fh*L=1IJ{B%e7I>N`-8Ch6YQov0A~ z=U!i$OcrOX*PE_b$R!81oC?jn`c<=Gjnu(5=x0*&BIz-FEMIWo9y?XOOoB&;iu zIP2r~Tt?%}955Vo9gwMyyjvl+^cBsmJ0jsYg~8836AFs3s9*dtHYPX$|D_ry1<2@i zbr0U|AVe$j+aUFWK^`3K%Dd`~uYMvDkSwaJ*TGoVRNPy?U6q0g-xbJF2(IKzTK;)w z^1!@RF;_Db!RhBEqcGD!QuOF`i8=NGr;%8~Jtu|^pl@0y>OJ#l2%RXSMF+N4fRsA} z1F1LHrrKe9RqXmGd-?;eNDT>E%}guu1mRvwC>5dPJ=WWBV(eERfK}aoe?yzTY2pHS zLlm8YMfVRtEb>0bHtsr)mKZYj-r)%;}pS_h0lLsbKiD%E?*kMn}to4rOXl0k>(unDrLRZn(MMd{LcO#S1=JpgcW0gU%#Dd;?5YAHpv2#q zO6KFbf;&d|W#fhIla_dWWwLm>Ztxa82;de>R1}pj3*p z=SsCXm3$_@KZ`H_mCl`NM|iK3K5X;r@1KbPDHv*h6x9=a#&)QkJFZyLjc#K2sr5&TZKw z-a7*kKrB`!G-h_0<*UhEkT6M)$HOZcv=-J5x7+p#4)3bFk4qZTKOIW`+7qvL>RayYoEMu%yC+^DDKqp$M~zdf98l14 zg|uk=AMCwnSd(e@_KTu87QhOE6crEw0cj!~E7C+oX`v`cZ_*)DyP^WpJE(*X0qHeX zdXEr#kPe}j!~jY5$~-g9><|0>`0n?=_mdBE96E+0xw-G_TGv|V`8)Yne|(xgOGv)? z+*BTnhZWE1BHLDjAFwIKkm6;enweP~J8SAH7rU+fkm%f+a0=KMKf;L@DvhV(ZDYP> z?roJZ(*tNs1+HUrk4gHlE_9Xjh4u4Cz03}9eKtuy7ui?onB&pDn!(i@s7kGIxkOh_ znFX%C;R65n8SKD*ZX;^K-%1!6LT!&V zDk4Kmrd?^R@AYb;s!vtQkIg#uh>V8yKy>rH&5DrW412V7{|j|QH}cSrnpdTYxT`vw zc^=j7%kK^K{qvVwmkzj+hW%$c-X*1J#5LWH{Y4yDyx-iDcdORer%0U9=|inz*`Yr) zH|8``wzVcJ)i3r16Gw^Q$k7-=dT0lHzzGJi>#iMT4T#`XgJM@C?_sPALa(pPD`j{3 zETfO8K~1<|C?ue&fM(f!5$C5$zxY-dXz-Bb3rbnB3OR#_YzI zlhL_mWuJFEi#cOrS4qyiS@Y~pn4Li9{KZgDj$BbUqS2=6R7roleqygn-lJ>2tEt0o zur$Vq>R-(^z*1wS)va1$ZMU0l-1w+Qa^l$*{)gT}mzX<$81V-pcAoG*n=Nyo3SkS{ zNBdhgjvbHS>{Ixme!|(FroigtL0Q=R^=t1JZ{M)^!G03w;IGZaryuWqy_&O>(!L|U zCm&%S@`mn#F4?*=d2beazZylPcyjl?Zc3zxzF5wughAmnsznHTAp<;3ad+>wa&}W5 zabHl{p|_)9IakRx$asd?PD+1RGF>`?{Vqe_-y)pDCob6tC* z)wY5?VZNqC17(h~J_9R9L~{LR6KCF?)NeCRf9iE(+e$~9ibsmAmjh?7=Sn~xIr)S? z(@fXIV^!JdN}cMR4Z0`|fimZz;(+ID@oY0218J;MYq2~kE*G1kMD3mO9~V)OZb|hU z%-957=CIZz1zaxe4xzjUxvDM26X)rZ!NZoiXVz-a?bt#7Yo}G9<+$4pmxrj|vSK_bwG&cHMMiws!tvWEj-Y>hleLw~`k>8V%Kzud zrb%vELlb+*?98mrw`3c@_1;G#EuoZb_+)=WZq%RvT8-UH{O~=E>}NeG({jy zryAZ4DIV>_Xvgzs$<=K`t50p=c3s{Wf+%xR007HysTV1$CS-P1}t0 zIu@9d>@UWk@E(gjt%(@#%12EDQ9PU1-ts|B<)&q-pQ;+*=8w`zX)80fGC8*KNg~E$ zD_+LYuFb1`OER;10AaYU-lcqow!7RPNo5l@Zn)j?!}P55BHY3;ha1dPXK`rf($A|T zXxok0R``*FIpozv7Hz*NrH*&0kY;-KhMi48Rw zBiaAKM(&n~0gn>0Wry(ku(VyI&C2IpNx7S6>)7m+?JZxdIx*h>XPz`qlER=T*cYkgA~t%3;?u%ap)_) z%32#y(trC|k1s;B`P9dS4<&*H$n{wzce9-yIy_4O+KiW{cn`27nHJo=;HLB7 zdnFBVmL?wOI3zOdMKi@XE$kYAh9+LJT4_wqe==9-1EChTLVEl4Im)2Wyer2#^m!={ z>+JBA=l8LxrNqOs_433@<&5h|k|e5;gef9SWXM`&>uk@yH|a_|NT-CUW;cb01>=fe zJFOogm28wVakp}M@><+vYgl(JjUu}ke0K28yPe!;tQgo6uuB&EsGA-1>DDO$v!uJc z4Er~V>l{ctN+_~#YZ`nL;%%?aVf|-*)TjHV2lQ7aNX*`h-pJyr@7K8%;({-LsJVbH zU!%X?iClQkPpqoHbOdyerVR4YzJupoc;wlJUTIZzU`=6^*mkDR?S5ItcJFxN;(#@> zvtyY5KW`0M3Z~l;#2Mx&*Xo;}ezt@V0hn7Tbse$7tsMK*&54A!ZGqLRH@4X}>O+UXL(R=9Rx~hoO`v z9sJL`{zw7F*Bt5H>?pa2sPLb^`}4oa#*Z%RocnQF^#3%%*8#sXMBjgXP*a0quzyBPx^n~qylE?Uen{%tLsQPoea_LMW~X4H6rQ7x?$D)G&;@J^KI+s9kZdQCJ(MFFQPVKGJaWd#3Q zI)t)krGG_tMj1;fa2aDN3WV8*m`t{Qgj9x3!lFmuOh5p@2ODEZM~Yb86DI;F8%@CA z)8c$CMXdwh+ISTT!2LyZ7tPmdf8D(y2tE?+!!$YB)F+Kp`w$uCNlUcZW#km!VNeZ%Sew=H4)&W!Zy^8^7WLWL}Hd5F`{+sBxb;X75oD978L}ehS zED~qzmb^WA3|x)T@2~7h!0e6<%nD2QI!_pz3vA_+LA$RYbdcPvJkkw|@m+AtuBn_n zsytiy8x`=!-gc895J4oZy_j!O`?(QRsc~%a@%dn!u$=BV0YDzx z)w10O`NIHgs=n#D*qj?DrH#}9mg!sYSTur|Wy?r|S0%uhiDg<`lTG|wO34+Em2n~d zfURGXtD539_aD_~Vbk8)^!PH52dp&KpPF`G8o8jJ*ehG^H`681SLU2TPMCVbbX?r5 z;v}6_GC;8Xy1^_tU8FMsPRdgwKKT0jxvHOEF>is0(}Ze{(JJd=WMYYgDH&YL2$UiA zlq)zHeOXwIF`n9Vz72Tx#kl1?!}EtK)pHFBTP1#^R#+1}tW`pfN(?3*OYvLDf*T8G zl(ODc>X@LqiV39EzUEOf0%41@l@hJWSHB6|2b5j=!nEQf)!$!!39#1C+%Xk{VI;wE z6TKb#>F0DOUK3O6&u_Rg-UT=k+wSZVxm}17hZBUn357a?W^Afii$P(UZ)oxgI3A2P z#Vfhw4tfuycyaR2cYdf^qh`ije#O@9;EWDMYR1Qyo!iX0v`M7a72w8jxc=vy`*9Yz z^_Bk5Sx%iF&O_)Qy1QNs##vjSPR@a+7wqzLUdl5vN0NPIdQ1HiS*ZrpE<|4ztp`QYUbg0xvT8r46=$)qaY7R)Vc6+Wx!6r8d$ zXp@PJaeP%esNf@hEL`XBro))vOPV8{tNC{DqB^p z)`r(-0Hv3jp5x;-wQ*S3;1ize9-X(jN)Dtt-#arwZV{)q)r=A<*-8lbbjOonln zUogA)WRYFBhHo$$q*xn=MQ`N1(%r{_Y|NZ)eMd^ICzp^sx zIVYGlWlSkAT@6)RFqUgwpQtcfqlBu2NZ|$x#A^#OnEXSgeUs8RhgOZbB<~l<;d{_# z);i0m&A!#jea>r&X8I0L*8>PwjEJ2ycUC# zn<`i+3fgr09(?3sepy&L&b~mKpf_pkxpE6t@A+-%=P74{Vw<;d=~JFV@+JPTNG}vQ zCDAM)37uV?K?SzT=`cq!N+9tL4Z0$UGwY6kEQ*hcyY+zF95BBp0Hl_{lGCz1lf)- zzroD;t0bh`F-68cn*VyD0i7?I+3irVGJ(4MGW?@uvkJBHqCQLjqvcBo*V3-B5)+6_ zH!_@*u-gZ1lk!C0mJn7Be%A!9=ap7zHRxgr=p^gkr`1x@HNETMZMkkgm3$_m^jmzE z&L=w3Yf7L(^x^&1szq*>7jP+htG1=6fW)%GV>24lQ&I_{%+=*9Keyy9QwxtGk3S*U>Gp#95`DMFJ^*7ll329orgYt zU#q@}4p72W-<~NH)vryI(^DvQmc`OXvjce~?Od|m-rorbK}#o%nHubWQ zk;8rZ^4AMOIH(^>beLE<>>jyoJ0fKK%}n+7W7IBIZfW2kJlJM?Rtmh=r(XE+s|Fdz zjBy0H*(@1`e(kiVozY2>7ZSXl7zWf0&5*giEp9XJ3@~sCJPgqX7QTR5NFp(#e#{|( z3F(3N7SlKD_pj0u?r^(RH6jl9=DCj{{!oFocuyujTw#Cdrnpv)-0MJ)u5t3HCP-Od zPw-Ehfnky;9k;Hl6gDXDTzv6mhNNXvys8^i7ZU@{YH?ze6n3MEOCn1PfTD+8D1zQ(cb9$8AZBNvq%l!;aUt zm1KQ(F)5=HaohiX*cg6(cf&n07Eq7>QEZ?m&z4_$xm$0fpHtBUAp8>r@_`H0yQghB zj1gxrhB?u=n2;0P{n8_(zSIjnmE#f?UiP0VuFsdDU=^n`?mV-XG#_`iQEhRxHLpR3 zQKu7o8VIBSBTaqS4nq3g6hB)LJRoB==FS%~zR_Q}79n4P+p|ahnePK5MtrpkcB`he z0ay5{rbga_`pK-|9K4$zgRqGmb1BtE)FBb+waT+Y13MmVldb7B{&IrdYTXHmW=dyKf5)plnnZY535<(zjJ ziw_E6isO`ZIs?$Qm$(?uGHy2MSjFWsTI0Bou6B+$^M)O1gm-<`*674@YpD9y22`N7 zmk_<6RHYag`JzXnYYp`3Qb%@FcOH-D;Z?f+*@e6!fE{v+Y&4cwUV+IOTviK zIjdv(Xrm)@7Wq>Z$&1Kg-!Ws>>jCUNYkoL;Ig2_i({>;KBf_^E()@q?QwAuCv|9!l z+cwVuqasei8<%S+s^B#zZBjr7246oB4o*bum7>y<_)?DqB^igoDlfeKh~{H5XU8$g z`&|;=0L7bK3J@lSH;KwuPxEW+lg_U)1cMtIL1~+c_vidb?ci;<7$&gxPlIk z!qaQB(zaWb2wo|x;+7SxVVU%+CI@enOD7d|nV_uiQFR&V0RW zt36n6*cMClU#+#riJe+p9%MoJbo~W5ophU#v}~bY_GDTzUD!l)fzvdqyo5D{DQ`Lg zwvISCi)S;tzebd@;R;Df%S|3h#b2J}Z_;(a(#{uMhkmE`Jb8AFa)!8Ry+Dsc0KQN> z4h}fmYffH%eSGKM4bPuBC)I-aVRecGF>O49HgqjesYBnUjejUi|#3{YeZ$WNsCj3q+VcRt7k%)aNQ3lvz7UxGwm60q&+n-bPhtiUgr3 z*RmtCv{Ezut2_gmu@V{9?eVsC=zOD+`0C}l1S`rH;2IksD(pnetTBqO7ucC!*u{)i ziYuYCW7>AS^}w{05o>t(9B(RHwH)P8AnwxjdFPd)9AJ{F(A={eU*Y= z(jD1H_-}XHb@Lk)+f3GEjMaxA2y!|gToR%g5k8ueU4?EGr0!mt*)!PyL< z564i)Qod?z^dKA*-fH&vbdBKD9f@H$!p;^ZxZIfx^~d4-Ry^3j!M zKr!P-*AnB49XD(773e5FPY3+HwztsZh#M>R?lk9E>&pl~iCT2QlI5q&X;jKM7>S}a z*~Q~r>S6jWtU_Ch7;j60kIuoVHXKw`&97&$mIFk`N#j^Kw{(xT z0J}ESY)?s=MXvoKyGyR06|`)6Jg?J5TFnz8ddgDsI%GicL+dGf-`1}~bY*HB?Q5IM zltN8i;+9C-jK^F6vyHfM`He{ff;&j}D_qIJeIeTznHoTpm8Q|1ZKVvprkG#LqX`~3 zi=3K^HauBAg{HKuT*}BA*MT4Z^m+EPeX$HuJe|Bv1GOzd23QV|OrUN59eD8STRV2o zIr{^%#b|xjm4vBs9sTBlJyOPWueij%Ro^TMaCjR#t9S)f^Dm$;_f!|Z@?tiy73mSa zlcNrRQSBR4Ff_VS2jvcN^^Dw`VpWc06Gdp;_vM;jIwcJY*ACG;mBqXFIN?i&c61j{ zl!wR-728V9^wd;g{O8Uf7@JM1JR>k{XU^u`Dv=2QX(D}Jzg2s2r$ULi5)Wr2_EULj zKgcL*9g4dk0puc`yV=IUtg3S6=yZoznul`#iXTk(!$p11fo858$56p!E@D7fxm6sa zrE1DJ0gkXpfQV{jv?aAl7H`@pwQ=&}@6Klc6r&jm_gpvrYf)Zd>>X6mf4mXB$lnHQ< zovFjC#?@|9Dt(ofujJa00f|LKMZlD9xDs@bl^iBd*KY%ABwDUOpM2SM^yZNw}oKD#?e*<6r9*fFrkUl6NK_ zVE%H>vC9B(>5g>{&#R!Lt!q?fCos_z6Qk_E0fAb7*EB)(q`{C2EF<56Pa{?V2TYDl z(0Kgy`hyun6i*cT^C&thl+$p|iU6m}z`x!s2%91`S{HwG5 z6PL2g(D{jgMl~vR5VGw`E7bkncVf_a#vm7DeF`XD;pa?@pubhPHZwF(4Ki+_iKeI+ zvp{Zf8M~fh-M`c)@L_bs9)*4n03r6@uTOhl{lDLAe=%ZFh*!})fSfD9S3GaGmYehX z`}0APTEW%5{|o8G#qt^R-v?s)zrOsx`q%&8RdHNiD(qd{_T*tny;D<*3GV*)pT|CK z4m!#OjwQz>pT5f97=J!K^4hUWc2=)MpX#c~Vjl(plSBsY%VFt?$r#QkJev_LeO#{gD<*OZ^TG zJhN{0(q6~E{3Xr!?Y38K>Tzol6IHl~0o|W^bo-nKAesp098o|OCH{Dx038WG1-rDv z!ndz&5DCtIlStvlc`VWJ@P_-$q>_--M!_IvkxxP1>JQHc#Q%BE8x%)$}&QI1R`Ts@~4mM(!5Z62B_iVCF(cV=IwQST>pH> zvESbae&shL?$7wl=!z9y4nF!h`CxB{eFa>4(!*0Fl!3-a zZJ@uEWc>0P`NDl@-=aL}wS%GyXy8^Q#Qo9OH3jXlH*LC8dCd1r;uyFEL{S)-(+*@D@F*mw&Cni|UoV>t2Cx;w=F-U@}!s_#E;-+Wlkav}* z%1LEnW44XaqE+(BLXqbHRc%K;?%BL_-^;+CtDLFo#qU(^h$y`7>&#}OzWT4x(PmDUxLw3Bv_N; zB;F?#zNg1E4OUJdPK@++e(1{4*AX(!oqk-Hrov-W7tgYrd2aR>jy`XL;KplYSIgEd z_ZEAU33?Y7FQWcak3>G?U|C0JHTTSuQ{AiqoBGIbSNja}u^%xY$LtNHe1iI;#jB0l zL6R3O=2rB+M$a+`+~Y6rY;x7R2o4_f6KVD8LRI)VN25P;6aTzes=X&vSrp%`$}Z3s zJGz}rfqUzd=M7u>T~go6Q;54Mn@75~6h`H&-S^8fa9K3Ws?OPWm(IAr@H7 zEYczC^h}V9r3EO_CFfp=kJq&(OfH)F&&wD>$+wSlEsh>!04T4EFnbh&VkHKe-Ws6` zLl9*lMKs%VvKTn$$Zz+<#>#A(0I8)`{i9c2&E0+nlnKr7;}^DX>P};Q2$EkCpu|t` zXigEwDE))SlQ=`Sb~va~(!M#7OJ<`g%2G^0g55hQr%OXx(Qi+j;&f1PtwNUbf{$fWFH>>t&`l3^;;5ip|&x|Dk98HbR zv`rImi?zQN%A*CEQ~c+8YsU&>#B{Ho(oP;F`2*IzMcPqjj^jl@Yb|(&2`$Pq=>&nNZ8yu`(MT-Jsmd$l(WE)o4 zlv@dTo6c_sihuNCEp2#iufPB15GfqQ^W?Eml`W&DvE><;Ymui5zrEtc|FbghFa2^S z$hbK?re@9iA639EJ)J9SW`=W$`*2UuUgdIi;P`?KS!)bi1~HzKI!$a4d!uwkC0_iYw) z^m1mMhukLG1nBm2I9SHD!$DbQo2R2kK4HECLr)dtQuezhX0oS-tq*9{vh^o&=_}9A zn`_hJaTdRyFT_P!O=;V~@sF0|#| zIJwiX*kcy(PEK{|#I%9Tf$V|Yfe>qP`%#;ZW3NdIorLia`+pXK3789k^T!ghU?X-P z1bg^(F71_IXN>vjKu>6mI?d;^nP-%adkmy}2)*#- zY`GpM8AWN-&yB6!<~tRr_U(@Y+Q%vV>-LkYaFJR|YjL@@sTvCXAHG2>41iA}PC42D ziz*2cNZP4~H{9X5T{;Ee3fHdw&`OoxyJ+&W2kgg5a~BN}sR0{($K&K3%pF#2f5mD$%cE#56kJe^0Z>2wCYTpa+D$V4lE@4dQYw%cLN2ZmeE7ZI~uZeAbk_{^(((G8zGnnK+3U}4U1Q+LU-HNMro4C6}@gY4bE zUaGxFr@G@hu&!_%lhaLap{Ewhxos3vn3o*7Ti6ikb4!jsbFGW(w^XFB<^R3^+!KI~ z#6ejnMfxmxu-XTkyz%MJV2IU;V)2AMXZjsC;JzCF_HxW~4^28u9-3?irLOKH4{ZcO z|FnzznANY!PA9(Q`jJ{&RRdp_hFFOR!$tTyhfL^S2Oj$&`G8w+nB%eX`QVt-_mG0W97mm9VP*aID(nN99U6>6GWI>vCW?!L69c0+ z>IKkH-OLbsU8dT&$u5KE=^G5-p1xMYgkPTpa7DGGtpr&8=?PFR22=6*bb$qO9ULF` zLb#QLVJrk$2*L4AF?)}kxm$S&=Y;B}i#4_aC==|feGyELIDeo8MUA9MoMAuKg+Xj# zyDn!xsfEc;nrclVkZSTVQm3j)haI2;!|~OmETa?L5|->Rs+`+3A3p3>=|re!3zFD zG(96pHH2lWYoArLOZ$Ufs6mRYZFQ&5pBu5jg-1JXl|Q)GcXytEp=~rL&uX^Qf$0eh zHjQw|E`}W_c2zGl$JBn?P`S(3G@Y>H?`)sWm&4H(K-XWWYu@>W^}1CmtoHJH6`ryx z78~y9fusE}J+ych6ALTv@A9c0Wl;~y^Jn8%MsL4FETp)M)om!KJ<=3W?uN`{j@23v z6}fiGtNne~LLL>}MoW<*;miUX`=qS3WLqwjTwJRN#HV4GLjgTBF5Bh;44D>d=4s}Q zIVreu)wj_%FWKR;_&}@@?e9y{fOIVWigm9x{IujLon(Fv$@^iI>$7q0_Il`O^6I2| zn{fp{kln1}IMX0)G8B)rRW*9t$$8qYqu^aNvEQB!O^K8D$TqHia8o1ljL^$N0^zWP z#NYLPy64E2hgwa)(X)IrYpBx4s_rJU<{*dYkV^03Fhdwe_7;HGI~0`B!L?g#$T zsxn>+ToryZ;b6Mc(uh6-A-{Su7X0=P&fNM&uRCmtD3vOZR;3O;VPPEFBqkiC5my-F zf$@hFSjqbhcZF`Grh<32cLNiYYgE&eCTdWS3L~O#rk7~%>tEdK(Z_ZAOteHHz%+WI zJ6k^nT2L@leXCV~(ai|4Y9V+5n{89HwOPCwidD{!mQN2za025((O;jl#M$46VZlmw48YPYE2W(~ zzsw<&^lxQc7xh{kidx1{g_|L7K!HXP1pjF`+`$Ms*sXYvvQttO@;Z--r?J!4CfZ@J z-~tmX4}YgAQeDh&Dy#Gpv6>AY*L(B{aofA*81crugtGhV*>_HbL8v#dN-;j!LAV!R z``F>P{T7<4eY*Z4tx!IxxlT1&^zgwvV^T5c{JlpQ$H9VoAGXd~y-qyu^QAJG2h;58 zTrBxnAH2D6=!}4v;*5oGJ$@)a1?f}1>aCSAuia>$a3W9Y<~0!-814tSSo3a3IP{){ z$a2&VG+uS~N1lEDde9?z9*uUT)4TF;A=e(X0LnmbIiOH{1&fZ+9hWv#l-210{wd0{{wSn4P z*z8Pio^i3Lj~9!6e5+E6BTm{Un0$;fKxJf#wFSDP#L!Ja?dTSx=aQ!yG9U6hXLKdJFf^fG!1w?p3$5Zgm&Wb(7Bz$t!#wOPzK#Ds$o!m5wF%3`lx6+)xMO9ZbfI zoAfh}^LozMO=2^g&4i3{V;u&IJ9kt>GQBG)@rB<1#Hx60*q_xQ3VxIKDw}#n?%Z&% zN%Z&;lV8P@E|W@yBU-C>w^}Gq6iiP{p=c1rP!_!~l%87uU1X1~9WU9%lXs8$mS$pH zCxUlB3E^7L>*MjCiCt^V^?x75pExE3!NWjR&w#8!*{(thK`FdgPbqP_uX)ELNLehp zo}%mw&FP&3)Ot#7-o~ZJZJJYAt1QgmH;ixx`yQUqe9tU)4^t%#L!CV4wk7K{XoFOn z#-mf@c;Hu}WmID4_-IUnhI40Bp|go>=&!&?AlL>F#tpN0D(YN9zN z&WA#0DY_K_X3mNy^b#T;v$;^!qZot0IXG85keD+%=Iiu$Fh~I=rL)#6M>Y$u1D>fC=`Bg zLrogBT2H(rkfFHsI}wux_7biEbZmlm9}kzu7=QyVqspfk^RSs(KNO^a%{gQ$-tUGt;g-yI$*BzsFWoSe-z1~Y7zQsqc!jCs7 zb&tbYWMN0^L!BQ@>3sD<3&zw;EnY*DYwKz1)6me7Zx^&A&gT!Anz>E2%1*uPS~Wy) ziW?XA`jt6uvgj73nST$aw(UmYxf1x4&?5Kz}mYm{e22|dndSL0>u zOF^BY-e2l(rk7{RM_$=1t?jWS$irl?$1mV0Sj64uL6J+dh|Y*Q9_f@ar5M%L?l!>H zR@*^Sg2ZS=McmiEIsh=lPt4#&O-hZKn0d~?c2=zWG@l-I5j|_>zm8IxSf2UwQ+K@g z8O(IXtSaOq&jfI*mjh0N5^JR|xRG(6E=#Ba4+HD7rh?xK!#(uc^Y0~dvaimev zYugGK=o3b4ZVdU`pDnpLb}IeY6o{C#q4|8zC~_B9krC{fefF=^xY0PNj`=rO8TY>u zU!f%)9rb5bzK${pvM>7yE5!O-pR%LGNe>t>l=y&H=tF z(%U8zWc?5h_Azyw)##faD)GO5ZZy4BN@z(|LR?Q#b}S{|Jm=7RoVGbHi+zfO5VyH3 z^SU=Zlz3po`348dQ<^54)7NV*g`zxZ^Xdq}`jA5dM);yh#g3+f`uWD^M4MK}+a{cc zJO)=_!Wbt(NQt&xOpA_EbJBo@nl}5)2~^;Rz?{_%pU?i!LXX-a-KPgKLUDeCn`^+q z_27{g|NUqvF2SQA^C?#}wFq+NbarbYvh8xdwk4^A9TL2L4SPx(R8T$XBDOl5{4Bwx zdT)66Dk+Va|A%Vd%FjfnG8wdU5@YKNgN2up?a=lG7t)Uma?PTAwZ&;I@u|mM}0%hYx`RC1w6!my^@O< zDnbO69Q$tz0r{Ek1Wlez@?0KFv(=4L_J6iE2a9HpN3NZYS}2!{$s^ycDKYU08HUGB{QR$k$Z&Pyw2yWw7Lyi>Dt`-%~Y4slJ6K#!$4?@(SPYm z_r5%VfEZz*v|kS4GBo|z(>z7>2S0Z_&I2bAn{sZR)8AnIz9e!;pi$ldGb2e^q|lnO z?7g%_T>NK1zlXO4txMn`&Y|ova)!wVFT(IplXF1KYP+8BFSrG zu+s5*v{TYmcYZg)z27RbZ*yhVux}=WD$iOPNkH~smpyJ;Y;4(A^%^Uq)@qlQO|BGfD0XXdh4 z$BT#=Jdg3GsBD=67|(~w?M6;;+~jxc{}i}+7Wo?FR~EuL4#U-b$(+i!n-4Y@@1T+A zBhzIl_0TaNc4oO&JX{6bMgpidur|=}{&X|@wk`JH76jt8_|O&n5F%ZD0zKa72r>2< zGhXpmq4WLsEyM7s3Qo(oyGu}DSk}Fsp|k2WU?!O6iVE(kydwfpb%k_Ly?VmAyd?Rv z+=NPyP_Hb1dT7OiO}`%1u1vWMx>jLG(<#s;2Okp5FLuOUh2D%~7aZFz%X`e--Cn_r zUmm{V4ZThQ>$XJ5yg4-kn{OQLmswyGY1sbM+mmXgx=N|5nMSDWL`9!3XFj;kNP^m7 zBzkh2?W+Y)>c>sIKBk}-u(hm)-J_Iib0hC+Yy8TP7hdDlR)%??~CkRPQS={Eugk8gqlSA**=~#kaQbX zJk!+(C9?q3Dz9)ojmgplx!dO86cp>TkL&!W9Ybobxi~T>JVAV!h9L2rip{naq%1$D zPhYNva;$b7_giHXO#?JAz^Ei=Kot-DVwyT&Skj<4f%837y?l^OC6zZ&g7SP|GeV+x z&hx|4Dv4YpNp5T|^5j^0J(!6l)FA!&LB0`9Z^)($*P!&^StREkQgbsSATB zbBeoL##078e|kf*wRX+VaiFq0Ess2#BS{Ah?|cGDh_Q>ObmIB%Wa~v0js^HlD+eB> zD9q2Ah9;GE;mE-9(+63wg?7#y8m034!Z476M-D~b#68eJ9F}$L>fPZ0gcExmW(A13 zie%yLPav5EQnbsD1^&x(G&oXm^zoKYnMX4lHn>t_LU>30@7@o?2*(Lkp1R_P)IlFN z?XuBrRo=g!eFg?ar5z1l8^8*4AC%53ooY4rp`+WC>2gRt{!AQ2^q)^PV#}w>bCn*K zG#0=mNLL9Fx#c0<731_zubhFwo9*N;8{UzB-o{WpV)H*ZaPfbe8S0-a_J3L=_PM>5u{$@{)+0ICoBbURX^>%z? zTD2}CrI1KgAvHBMRZ1*N<^D=ObB}BK`ugJflG^lfv%H_7g-YFYX5SS^o?s8$&G7A1 z*E5Fw;!@wf9vW4ox-q=4g&zLL`GK;5KI;@m@BtLTsA?0{U(o0YMFzQ2!t5)zG7!NbhrP*tAxF@>?$Qd{~ATzk`4X}&4Q?v(^)GJU8 z5V=_$D{5T+DNvvg7CfV;D-(m4+P58lP|xjEPTPA#_&%fp$~hragldJ@($|hNZNH{& z_44_#v56Rc zgSufBbFi;hjYmD)X~+HnNzMMVk(}nNywsrX{5#k^?3H!jt0hsIhRtkcy^!j#Rl;z* zu;n1D)X;ut6;i9TlcoDucoe6_w*^HCrHTZ#r>Njdyum~h*^M?+(dBpFc3jk4f@iXF z`egH4sSFd3?rzWZZv9P7tTUVnJlmC&97ZUlP0d@x<$B&KkHy*?#QW{Nd)>whUTygU z`1c7$dhDi--<`W9c70#gB^g7!(pa&A6|vEY80to|ReQ2yt8;B%^cmAR@i!U0xt&U& z(YKwlYF`j<_3q*%Jsf)|To318YaHLTntBlKx+*MIgJVN6`8k3H8I+DcA3YT#UVdM9 zUPSMH^|J^DszRKoW9HkY$iOOUW!*XG>Tb>zwGT?(9Mn&Cf`RbD;%ojqTP+4PQ>)B*?pL9?_b7PSq$U9Dy=he$W=aOCS-ZQyZG2CVtD`i7O)LO8NzhgbN0oW9rniY&`Vr zzf(5Rn8W9lEhoLbbNSh^;UAtYpj(s1_L$R{U!8#5!va#NL&>|Z&n(Mr&t62yEHHAI zcu#nbWas1uXNN0(sQVIeUB2GLjX*SBGxDei$PFEru6P6qnrl8*o- ze!m5jz+HEn4uR$JP^sq-a-h&HMifDPw!VPHwaKrZp>cDl8DV1?LULQ!SfxyMR!s8i z-kSpa{+xg(Zc}sHaiN{=J6D&2cwU?;paEl3h{>PfJkS2W9{f>}dJKg)z#ldC&_=jX z%I-`HB#YAq!vouIwfS+9`X} z{0X=+^qst0eXT|B$mg6YmzfaI1Eq2-JCo8oB5yeu!q&Pq7KeVoCjS0n@*r3`!8 z+m{)yz9UU{4zY0k>cU@CEcxU=x?G=kb=}U%_cJmjVC5x-Dahg-v_Be|)`GTIJ)#N3 z7>|m}QEN7uM8vLk=iVG5&JPj9-;f|G-1p@e;n3uLtnoyAk#T6rVlBbkWZiDLP_uAR zXmQKNVCcrT^CQ0w>f&92XB1(Nq+J8PD=!5HODAinl?Xxi&3BL5y9%lSOlKs5NH6vcMV@@N@QTX9)$E>yJZeL& z0FPh=uEg~Fo(abv4R7=J8*ZkO?8_BUHHZ?sxB}<*t1|b#c#B8;_%#2@6uS{|>bm=- zL?&t3kEU3~6nXv6we~F4ovcdJ3$p!z^C`qjXxpTYVYAO<9AEz?+kWBbv3L1zVod!y z0elrdZNy9cbe3IYyU_P10FTNziaps`g7zrRpRT!ZrlTY7UEztN8d7UU`ulz;3+tU0 zgMFe-d1IQ7-R!Wn`#gaXkI?;E{ybC~a%-6E-3Ib@*S}x?F`|6b>UP&5(z*|fK#Rn@ z+&!n%(KAJBaqpHzwuTSQ`7RkAJD2M<&?RBRTas+b8j5;H+T}>^oI4%6&;kdp49ux8 z#qXcSh3gr!`Sk^YCk0fJGfCbQCg#BxhnrTP#T+$AT#r$;9;bTYmj)WeD55K*i2y=L2vh{wx zwLVTGWyR~;3(pjxm_7VOlHN(*0oTS{epMBunEy@UngHFJ|ZdJIebH$7wC?K_BiR|-OBILmmwv>8(U zF}wCwt*-aU@>rf1I$2C2368h=cQe0DPCvgY*kYeX8uZ7RMorp*{sx3+Yvti!}TieI@RIoz$jwc_T`zt$F7Mrk-(#8Bcdq z+}yqqXPr`5&*S^!y8O=66K$(--ja=pX&ivw`mpJ&fmKFbL|)BS6^kO>JId*$0( zeUWPg87av>yWR%7$$M>*0`Eg>EK00Fh+?&9|Osa?F)i^CcC%V0$t3PT~s zTjHAM1D6n>FGv@;Or5Fc%`+$*UEulPwm$vAVyN2dr!>uEakyr1O2j1p;xwpk2Bte% z`+}&9b4hn{U_%&fM_+x-3C=l%=o_8GWkC-LxmfjK(`V*UY>>HJF*}=Ml5F%!rp`t4?;{r;8_(&Vx#_2_GpGW< zUuI5kObuaPpEx&FF(Y|lx0gBsgR;_Z27{;+lWHD`t!;zb@ddkp^5el9or|I-AHSI(z=Gp3@#N=wZIzw40febTcd@m{Y>x+_24f$i8G~X& z@b~|EXMl?Jp!qWzF9xDg+(VH+pRyaj-ls#dp=2b-->umyHlOLToQt>L;aAgZtHS+FzjT!`~s-Jw?soOk$Sg7r-ntFb%*-o^eKGZ|ue8Hy?9QRcneNeTjX zL2l;{XYe4GF0eO8I$B9{+pGBcN*~KD%+?YhD>~F;` z_XJ0oekspEm>s!pcO`pArcqRm%xw^iIeh+d<($)?cY-=pWvkxpaci$SPa0em z?;Wf_8&bFL%ngfS^PA|_&jUEz0tKg+V+FDmm*zF2^C(1$57DrSG)!G^MqQAZDj(Ku z^>wxj@vOY9w3F?O!N?w0*dQF;s>gn8xobv?xz#X74)dHHQC>W1RY~rWIfDnD_8ify z`O4F|L&?ad`T8O$>wZ7+p`mnb1gT%cxz7vlKb5@8T}yV*`vbyk6QAi~QMUDTD#dFv zZ|ui13pX(+N3p-g*DIXoZRcPa1Alr`!97;Rk^C5TGrvaDB&7i+7S8efW9wZv=Wd+2 zCUh#ZP|L`oKd)?fvZu51J;{!u#>0_dw{r+;s!`!LYvg9U_t)?C-=D$?*jw#`2Fpo= zF_+Iocb_MDBBn|sGs+q5zIf+*FP{ak%g)?TC1QEa(&(#mjvMa2O}?S#eXH$CQ$06* zE+R*%F9j3n=a`SOc%ysh_Jpa?)M2z+iPs_zqHN*DQ~!}Nvp|o{T>lhlpN~1lx)0Y5 zFZu+Em(Ch^w4gNW>;2Y$?L#vR0Oe7pc0r!xFU%s$V+wZH{JVY&gK}w&2e3a*ZXufzQA)pHh*}D&Lh;>exL4rj+6lkif%D=+wN5YL9 z-r9^khnqe6bj=}Sk}%=6WrewAW?8lSk8$+~(FXYqlw5-^IDyKOtZ zN`^kyysruk<$l5L;#hLmt#+Sf4Ic@mHRI-C-$kVueNEQyS#IsEPR-T5DCxFW;*^wu z($UPTo7bFcIT%hhMjjb|uQ#W0S@^~EI7OkpcZZ{v=es7Zm{#TMq zxQ*S5B(Iv3vp)_pa4`q#Kmp{otiv&L_h>nqg{PQQtyO7mnAcx2^f74k_9n}`$wXyl z>RL4HMIvtB`&tvu9T;P{uOW*c90Zf{ts$8b!yo(mD4fyplkO(rg@`-Ij z2>0QVWFjWttGz2=rt`h!UN5d&@BDo93v#|h@?Ltj9$~Y9U^tj#j0%>q_q=qmIwD*^ zqjG!WanI?JwYn#K>Mm&}n?$i_A*;;#Da#nM1yfzr?YNJYLvG(6rEXVl7|S`Rbwm{z zigaSy18jZr%7k0tMWr(AF;e&RT3f!!q4oC-;HNuQYxpSn{X3_c`O+tj?Bb?h21w=$ zK3QF;npguIcTPx!IjYI2!n}l2^hsBxXw5GkzZBseIL|B0f4KXpp3zO#pFx2ju)>yO zJjrXg5aw!??iyjw{)mcJM0cJ2h#x3T_dIM;1-b4nKFc=dn#IePR(BKP#YP=~<*q9|$?wRci`1W~hQ>>xx@Ga`0MMD8=6@ArHCe%HMokL$1dzWn1KJR*6&&-ZyA z$MZN|zO74@S}8D4;&9ea_WAs!bng>yxCMs|z6iwl`6IlAKvl|uDjF&y$yTi`SU^A$ zb-HVq`@V)oOvpCP%F>uWAa-tu+bPS{N|dneK?~+Yg!4yWX((v4(|4v0}uAqmkJf0 z(pIwZR|2TVTWvelyj@4@ODbDw{yWP)%@V&Ur_mCtG%4?AL#cPZh&j#KNRdh^rY`35 zw>2G>{|y)J@;+EO+sQ7JLb~#%P0t}~keQS9L5HZiYuaSh+9~1Sk{#VUv&{EUGqXUMMt=ExzlV*s#7jHjYy(-03&z}+XWC~r+R%9_; z>k#zYso0tJHE4>wSq0xp`ZdxmRiGRB0<<*Lw&E52k2i@HbcVIhtP-oAx%gT7rf9SbJA+Trc9PCrdl8Puu;@;=wjoFJZ~3d&|U|7k9o0b)i(wRJ#*UD+m8tDOy_ zvTw%cp?^jTadY!2qfTagf$gROQ%)wF7D;(^LGKKfkL~gttRr$7e}=iyh&;$;4n5D| z2y9><2PI|^M{E@z+H#3MLL{6!S!gsM5rpoloPDMj76Wxrt@N-G1lKX4K4ii>*tTa7?u+4)>E+K>f71i=AwmlLUXW% zh1$JQV_~;=1=qFDj~t!&q-i)(%q6ed2X=$6d;AF#Q5+caXvfG;F|qbTn*4F!cBeeV zeK#&54#Ne^%sB3SM@A$Ty$``;n9BO8yX8iop8w?!Jch~2`-gVsTVtB@wc%} zfvN1V&lP(LmwZ8u23hQa_NgNv?`%`TeLy1)kZ?53&Gct)+`sUN11K(e@zBfhcXT`Y zAYjI@s>D)qNYyuSFUQy$&JT(}p)YgJl$$b(1OeY_(@{(8_a}QvTy{_e=JW5xx{*V- z6ivfzJGq?!dnd4p>oNZg6##diE6>XW-vVrCim)NNn&0V)kjdI&&!`tyTewyzJCjJP z+E$xpMP6ONX?nJ6_b-g?<#R|))xyyhN618T^`VAl7e7K8AWKON_KRfo=;%GXNA~d# zlVyPj+zMPc}0ZSx;T9HO4k0Jz2%+|(NcdBB*Yc*;eRX=s*IOnP(5k+q`?4y~8+sRsms9rwzk05Il;v7?>kQbNSgI}LR`>{q zYlmGPrfCbAzY&7r@I}blYCGw9QHDS^mk~5JRaU(GeSve4f^N z%9N4vzwG5UVG|&ZX$tzc4tZ7Xe3y7VK7b7(L4s8}at)SJ zOrM|C6T3b{;Z;rWRD2aOOb-Fp_j<5)p8x9CF6W0*`bB`P{BZSj+ZP}#4O^pOX|Ri8 z-zA6WE`Q26ts{G@HT0^%UG<)O4H+OwQ2a}FGAnYTXlju1*s7S$J>v46Rl2CEbZAl4q1reT%LTk)x{Tk{ zZHX=wuy#f+^e_$Gh?Nfx>WLReA z5vJVMaF7Ous%yMWQGucG?m!X(f-~?3S`-;clQX(`kzrK(hkA0kkoadViT--*L^}wB z%~?m!y&Vc-;`>~ajFQ96rAslcR&{du_ktkqybG_KMen!$5`T+aM`jk?(KENe1ae`0PYp$jag`zpMZ zmo&V)csEPCqIvY2o#gfIttgB`E+*JZYM&KCpjxazfA zM5>}$Cp>)dIPJN5$;qd*HzXVV-_jX}TwtB67TY)?F-55jvpHbZA;<*KvGh!=ZU+6& z_4UaBh|06ueXH7VXAa%bUtkVBflk<~6jxtpfj7Z41tNSPTx_o-CX>F5C0#K|DoR)H zP8H|~*@Maqb$=CfqV8Qe;zERBI(4zZQ=?|;Q`L}SQ(;**3Q(RjuXcF;-8envH=x)$ z;Y7|Zr8JVK>PGCUU1s`sk969N;_{x8#ojEh)WB|db4#WVhg3PDHI}tYyIu5SZ`~5~ z!#<5*F|KkdHhDmR;@p+(B=qX}YnYk%{Wtll#BPiX7FAi`g2cMUcvQlOI$Qwk^` zAw^gV4SjIV{#!afOYGnmVM{sx)xt0##iAR1mwS;LoGg~#Is=_m1@(_z3uN0<{3$Kj zMe9xLS>?^IS1{nF&#ISWuPw03kd{Z;_2DU!;SygvCLCjmZaP{OAOSPO#FoVoZ2H2T@_m!L5-bI2eW{|6rXPy{Atf$g<~LWmItJBh*0D{ zRV}2u+CKEh-eO%NO&W3BM4uDqR!_uc-$_X-eMe6(U!?E};3V}{kE_z6;Iq1j9r61+ND7>qJTM@hfhus&Q`IK>HU$|y-rfPL zRx{cfXehYQ^oy%^*QYx*r15&ef)P@DKxw+e>4_if>rN0@IywTA67Tjn7@K9T4Q8Pl z5dJ>wd(EyaT$gW+uoSrJT(f@XOsY zpp4R=t=QNW3K**i4bQ<`yO&dUnT>V_JFKvLU&peiB=D3Q*p;>Z^UMj9R|(`8oR(M~LtErp)v))*PtZLddpv3!vvXM%dIl&W^5#auf{T&C5f^CBDr{1@uD@ST= ziZ4$F9_)B;|17>gpvVxpmw3GMLfJhVQ27(K+mIhxT#zCj7_!jqWv_RUMwtaTrgOF< zzE>Z}{yO&i8J&rIAka;Pnw_pz&)Ck+#0KOy57mGGUn(J3y z@vJg|>0i>$XBHxay7AD46A!&Vg#xcNyF(GU&%f`{zHJ29W2fzL!`6#^-^7OLR}2u| zX*MDZH{bNG_(q3fw7C!tybylUc1TF zJos4V{5q1Q}e2C z^#f`o8(3H>at|gUj-bcoThfp8{>OL|G05ad;d)gobDvzuxqdZA`fr~7KwGqRn#@sY zkuxkb>*56S$$^4(I=J+g_-i8<2~j6D{S!r%0m4*Z0+av3d_kJp=z97>j>W}Ne|L;{ z4etTRshL(?Ccbf$JY@~;w_IZi9^_yMYavq956sE)S>j7kvbkf-Mtbv$@73#^oY0F54{n(YM}KCGTRuQ5qQ`!| zKTWRs5<>k~tN!fQ(V~wF&0Pj!JS5lp8$FZUXUguO3ScLn; z%7jKugm6EESM{qWj^F0N!R(;LVrgZXTL-K2M9daAxl9CFgxn+KCYtnrlO*RVhlsoa z38No3pGKGfI{|#QUq(Qp0z81G_u5%3jrO+7O+jSu(C~tG<}k1a??C?Iboyq2zOHudph(Q`Lipt?BEnvmTc%G_D7~7WGhF-zygPbrkckR8B^t5(i_3iQ@ZBPg7D7K$8#*8 zBw}K1eSNwVK#ATfxrue#aL=RaQcOt^u@NlMyf^Uh#AnLr{ zSjge=0}p(BBg7t_$()+saqBE5C=tg&#Uln%Q&nbaGBp?U;2%56wdHKJ6&XrZT_D8M zh*CfhB#cVuRiNZLr9&4Ot8-O9f&Wo<)~KpPVV}->#Wpc_zb0gdo0E|tEL7zZgG~=e zP?g$*?!jU-XInnvL)cv^0p3wh*aA&gm26^8lgW1J4&ZUrNF;GugAThgW?}7?U}DTB ziGaiaYQoW_scg#pmU2q>@g^zX0T|*4>T{P>AKLxOtIy0IA_kbGRBnqsy0(;76#<$@ zd2_bcqx`{z3UiF_b_0HFG>Mv0&W(v=C%!ZT6`}J@f9K8xcg0k={(M&p4pAK-p7hhw z{f~X>Wc3~wjm{82H)=u7qC*Ta!~+AJq;6b6e={lFH^SeBe>5TbdW+5ry_uhxZTkeC zj}p!U-`~0kIy-Pu?dwkR-}z`ah%-VA2CkU)!0kSXBNI0_Of|%#tlA|*Ze4b^rG{HA z;cghX+cW$@VchRWW^p*UPevw+&U~y+H~)hz6)^CTnRMPr9&~=dn41dbMZ#*?MvL3= z(-obTY-yEiHn$t$pnBL15EW7-e@h{9GEh&m!dTupDtHp?U^eA~Bwz8N1QOes>+@a! z#hiK0q`H=O6|d}nVaBLwDscVp<~$<@2JlLAVD*i6lrqN*?zJFUAZnPqI<;C;fC5`f zpmm^3Ryo$sBnP>4O@Oz=RC7rz#pXhF+T_vd!JRMi86^2B(9!d!>2#V4IppTT&#xWN z@DiVFLVcgfe11i0YyI^pG`STt6HU9=PuF`L#r}HNur+u)_*@W4S%3?M=PVULajPut z`HpK|uTa%AIYuKAr+&ZfppztD4R1Q=2F2Yk^V6Y4$jda=iO}1iD}C_j?>vM5R@W^v zH7%M?Vr=j3mr|hyQ*cj=mKgW!{vH0r4l0L#$RwIsFQxgUBNL3l@K$`d0PF_{_t$#0 zd~{KE94!Lgpm(xA=fE?d0ea<6n(7Hlhk2*Q z+@1~qcPt`3j6#~B9Oe$H^vIoRXb8nkp zGhm;!B^8m_mXkJG5mec?5^-YZnh3|5^BDPkD` zU7X}x;214|dGaMNyW)OJ9sw*A+(AT3#8!9lA+K@<)PH)oB7Zu-!vn484NAt31b!8K z3Tqq<^2>0#Ef16|+V+Xh+IY-sB^AYb z2j{|D8NMy_aeCQMF$t8`Jqm0Ql>#j3mTwl&<^7_X8E^RMj%co>#jHudKX?&>YE0p# zH8AJo#dMul_4>sLDvMu-f*i)HaBLFp1Qlmk^$U3gG=kDZ8v3Sk`i%nU!4MQQsh#Cm zLS+zypC>Oq9yyH2+`h27zXOnY{c?foI~{jI_%$qo&23nSqIxMI{Ceto4I@sE%|@>U zLd`etdHR9MifNfInHV2jiHU8gX_dR17G~_*2cZ6Fi1(j(RI4dRZtIsLt%=ez<+peh zLh)7W!OQ{0-z^;OxBqH}1IsexH(;Uc+A?pn*2J;Vv-o9Mc75O1)!%g8w@pMKPp~bD zSsopFZ!{kx?Zjyw=60Q%e#H}>@AxvMRa#EpH@AIuEj#3u#ZiYlqQXf+dcHSjNxc>C zcmZ=qmye`&b2w0`HFL316pm~&vv@J}_v{!b*fLSybIv% zf7PPt^E@{%-smIXWE6}7e-m99zG88ovOWMex$$u0y2L@I%PB=k~@8wCj1yQ z_)F*o`wPJkOAP&1^Q@oS**$I}IG8m6hMY0dJ_wE+dD=}XzAN(3V9@LEcY*d<+X55i zecyPOki{Oa^HLo^Yr;@zwLMcDb$5hEc1tZhOYB=UQ?uXy(EmJ|bJ|?;9d-uPo`1S; z)0Z+jR%9FT0X66$crHh8@z^y&)^o6Uze>Er|4Zza7Vsex>2rmyz6M4^D=o0Kn_Tn=n3PRzpA^SJ% z%9Gc0aiIUTc$}qF!eQtMyXZzxVi$*~?~h%sd(FIGfKI(^QgPx@rQQ$E9zlx`xT{sF zl&yQ4y47uF@1j}Mcv-X&kaW#Tbgp%$N!Q43{klpZ+)xo&M1Wn+?wl`RY9LE6VySZ@ z^hn?pm>5}cmZ`%O%qcKe@AHO=*F=J@r*TjKId$lN@EIH=5lIIv=TIbqCoWzvuMim$9F$OpZ_k zMMgd!!%~Xzv!TiuDl@S7PXDKG!843X6x|N9+V(<^%LJJ-8AJf85-l2=`z48HM4#LG z%>~Wt>@HlfOb)5DmHjr+QB?~)3C7aGebAq@EPvroZk3V>{NzDbowdZYXB+_FVR|3Q?;*gz*0=7>cIM0&%qvAsSHD;7 z&;smfl)y6Fu*M>GX146&&NTzL44zv=eD22PhU-O!Y#^16kN9Tq3)a+L8k6$0C-4`% zSH)=YbL;tKcGK$z6_m@y^A@RV&)}Nh5)rCc45rEhK3bqX+|$|gg24~f%ANw6VLQf3 z&7CTiddo(gu;3M%PJYQ$#Dh(xJGu!ASDwB3bn0N!Bgf|lzzChvqeB8xW+ zPTUIAK>Cv~z~}kXt*YP8YN7&L;!gy)m0^iZzJ?G3TuFbDQiqlN!fhS#wjkPK1Gm z#xp{3(v#&dBuT!{gQqaUGek%DZZlHhDxv?@+t2LDxtBq3buap9q76n&3{TN zP}QA{ZT*VbT-AKfQ|q5BzBzWnERT}*<78flaymMZ_IIC74rZ-6SSJ>qOKCmlDn7L!l=2uPwbbQvjkPZ^>tT&58TLv!V3Rl!3 zxwVgBk(cPac!$JKsInK=MDlkQ=_AINvoumpO)}n&d=B=fF`c;74 z4VgZmr$(}ayE3uTlXklgb!-Pf1aL~0C)XqOTA-zXK@)!3KZFNC=t@(}-4tuvz`<{= zi|rnf5Nr5&0Wxw(i731Kl}#?7);wsR*#M!zL5Ww?bF}~jzA5O&F8+LedCK0Bs!6h) z&(|M#AheUoY3z`RZQ=i|)S)cH!x_TO$*CaonLgY<`ZEWv`{bxVE!a{5JS)H_@|2!Z z!Ina4_LgEizVPmS`)gU@a}@u5W)OC7^ncEbHL3Q-BUGSylr^#t!iSJPAYJk3?K=Z> z#78zag>3z0GPK}v{niR-Kk(E&sh%z(W<_F!~z>N&=rquCDTlXP|$9x>u;iHj--bds{~?6Xo$3)c1E} zCPKO>81!Cjj);;KbF*$~((rZ6!kKLhsR{FbRr@q&>2AwOL-YG@0(cBPjUORmF*9mY zLY`sYfL+{9Prox1A*`eyqm!vXD{N!dM-fO5Ii-6_xpnZP&Rn%?Ov{mF;qZV1XvEqU zsS7(tJK|pc=GYxPnA)~%Dxvs#beh%C!>Wv!gW00>J{!}w*eEf9c zV8#iw(N=>}gnFYii$aKQWS;114F4~x`<$z(S!0?aQ3J?>Uj291=qF*snAy9qa zp510pR?EKcpvQ;benVQXIga(iPwr~qmhhCpT9zEo3;LgmRXaB4JLLc+SnT=k5RP)%DzFj#a6?J+bHDU;2Yf3v*>U*IG6N(-a({E6U7YOiU}nkcLzgP zD>_N(SN&>i40c-NjUWy?N$#^8W-yR(Y*lVwunkacu3wtCuhS&f$ z_fH=ES?V5%h9=4-Iq#j!_bY+jy}f~WFX3#9wh(%DN0c1tGsSW1>x3a6F6O=sxF)2$ z91(Qh^olGR+p3_^tcN1t#peF}tXALI%ab?vQ{K@|H8eZ=m7XtU^k*^uilL{yyxzv7 zp{}QWl4ek6O)EM&V1H`@fNtFVb$REBAZ>)Qog4jq``cVPT_Lz1mqlvcUXv8^q@|51 z(D${U(s`QzMSmdv7?is8%{PmDgmDpy<8T#3+|uye4i$T?HM0tJGfwuTdB#8=0S-O3 z7|7A1wLw=X!__X6?HxW?IM;ypv8##M90MjOCJuZKiVful0gdkb?m zmopw9hpyZZ^)x9#?b#guN0&V)`%5!Vm<=-Zl31{cw{sz<-f2hcJc*D%lRn6{CmZG^0R;9woC~i5!cG znUvJ~xndJ7?_6p+<7nDAgK8!bYCs)@u_2*GyHUx@@I^X#YVByUYq-%sw*Q@K(uBt% zbU!}%&INh%>erGICZk#H5oW?g-{-V3I#!g~GtiEYaw7;qK~dVTbTPaB1BBz9EMQl2 zPqIyM&gxa3#%-WrHVR1S*~EcFmr0^@{gd8Xp}G@ki}grwnp*2%PpR8)7h8D3U^c_$}4B!2wo5l@W< zEJDaV%~uW^Y|kdq{&8bV-Ta(gx>ugl)ypPPU%pj-?Nf?i)W+B$=|UwNe(&EC6yor2+oA0`|rF2=6T4e9_d9Pa|ipNh^jVsyj<({moO*@7pin zlw->hN%9f-PS$O20Xpd#Sh02zIk&po8PLn%jO| zl-DP~rMz%_f4Gm%ajjz^T!ED+@UN{0u{>qELmCMv3pReQPn?W&L zs^k1svA+%@1)220zmG|vn?gtgY&L@3StgcAQ`JAl3AlKS@hl;73jPLml7i&Odr@uT zQ8|?feR-kX$_LZ_E^XV_dL_9YvQeLW*KK}P0vMq;W^t4bwGoPGf~2y08+m*{C6iL< zw;2(tJcb)0Tiw6%5=EjWPut#m|Jia`Q4l@)&KwuG*}k;*{6qI4m~`D*_4(AB*4)`{ zy`-G|{V||mAw{tc`Dw4fIW-E$o0WcbR_}NIm0jTV;uh(oQ$*)FKu3A$v??8m)f)aG#D)2t3| z3UP=61orZY2rOm3BeKRHy60&NmGt0=baTkPbJmjscgf<_RT*KA3p;b_mC6r~eWo(c#;iW{+bebN?R9l2T&R5Jtd(!e74j~roQ{~7iW3$VFkO+t&P5#nfe>yTL2a*(En}{ zRh-2K`aL1SUqwRM%AJ8wdx!6UBSk#-o?$ib11HuE3-g~n==K87(t))2na~o zSeW%LA{l4=vwSys_;{1{AkG>KI|j`;#A}WP`t+TCi^+Dzcq!!? zccu8xXmg)NL8E&!pi%bg>-PDw?{z9-5}V-7D#=c)e&O6d&$PL5@tM^oU6A|Y+N>Fibxl&1 zaz4+4cLp=9dRol`+&Cp@ALs0f#07_d59FTR+?^l__^5Az(Dw7()lr@L` zZLM$*cz@8S7@tnVLo?-y*W$d6BRLO?Ne1@4r)X%(mj31SIHCK~#y}ygKe-D1n(E3_ zB{mQJcws}991vAbSu9}Wg)V_?TcR-q8$`kTP<2$bfl{-w7T)@!1ClTm3&aC$-i?`1 z#*Ip&rGljsd0V+6s$$=&LM_SMc*B$ z40*d5>BLI;o&=%o zpwq2u^JEeviRgcZ|5RKYm`C|7#K-{t>!y`Ma38U-WtFLs@U#=o>GJkZl%&}YNbaSb zz)&s%tKGMikijuo?=m8Xy^*fDq7((-uI10K%KzjH^en+iiog7&RXp?kaa*|PG$uYn z1#jfGbBTe;CC>M1G}U3?J?I1B>cNiBe&b^>b0^Dy{f|AkRVgU6<2=hb=@~cW7O$L! zWq<7MT41Kd+SDItlt4!D4BjpyXt4#jc0T_mCYS{ojnJ6IkHd6i`=>sg z3vW!}(?JTiXHLMIR;x2>^L)u$6mkZ;)pPD!%QZza15=V7X0$$9A^TY@i9p$QVe$2I zfC%dtKYCQAUbX_9Lf1{Rh4=${oR6&E)=RXhX=8B}WfphaBI?@xskBxQJgZTSpJyM) z|0*12E>9<9B98_opt}fn#W^7jNR3bMX%hh0t539;J7-J^KN_dSzR+!O{7q zzWSX@CE>aU3qymvt+}IdwK! zf#yu24sD&iTl>OcBz)8<(ME~p&Ql}LbFp-rm)ZTNJff>0m@y5|UZ7V~ zvDC_7KAT6!1;o)So0%=->(2a<1(mrWDS9#n43D47-gh1N{$bW=XeZ%Wp`LnvzU!=P!c>hG&z{AsDJg2Af>xU7(u2M z?+IMxl(f!azHKx>`S2&#lk0q<*~c&aI6&S`Hy$b>2TiU|zAJr!>EiI%v~I_%5+tta zoq&Q^lMVNwp`W(tMft_S-fgj%%CBDE-R$dY%(Zs0^(2 zuZd)rzcH%%`OmdN{L7PIOmelAVkk(lb=KDj9cw!^XQcz!FY2!}h_qj$vPq9j9M+X~ zgU&DhkTp|wlxF>jmGz&hluwywe6)6*lkX`Yu)w&4-Uv?W57U^TP;!m_6Cj-AY+gUL zB24>cT=CyO5&1t?l)U)lMg4_;ef{sySTg(JVKn7XzRGQ0iSj?n^1;hjiN9++6zuIQ zqW<6EEgEGe#ghNukzW6c9Mpe49`FJGU(vMmcNswkU6a*yebf#F;rk@u43}C=OHnyL zKpte`^>17Di$kVBF9=P}tHG9!Z5sdly`kUl8RUK#2$~wrDxi%J7?&ErQMCv2dc|}r zMJG1+<&a0*mVG_Vlw-T&bTRAT1dGp0b*}7Bld5yKe<_6U##aK*e)9Lv_iF&I09Xx; zNVvN0W7rerpU3x^WQ+7*FIz+9Ur;R`^VoJ_JEkeT5s=VRP+kQT=J=Kdn_;YPLaoeexVi z-engz>V+Ac&trG_!7PAv&$#3aT)wjzh06IF9B~1!DlsEX>M0NJTgj%KU>;LXl^SjI zuFab0bp7cUmUmHq#h3ZEeu)+q?~y!|JGFmE^?>;w6K?X6WSCcXfj99%jzxZxE3&LqrXrlk?rm zB~#_YXytlwkR9V2+=VNH21B!_wj~2)SPVQPklZIRR^uWMo{RMqx+t+}Cd%%d!(FYr z^wv%ngLPHkzdQxDnu%nxPX{GP;$NIt%4#4JjYz8c==;ONZ4^=DC2^wQG*=~vJ=q$X zxqa-pUV~^X#m^vTEYHzcw}MTlQ-vLJ6`YyMmO{CLE2-$_BsK`4#uXw*$8u*59zOye zjsPi2GXRrQr5C>HzQ%%zbo1%@`tCQ6-=D^$nIk4cxz@euW5ivsYe<2@4LsrRR|9J($MKFemLSW2Xa^3P7Po-}>56yN2wpC^323f9FS||DF-SLY67lDSLX6 zI&FbkcOqs#FaW9`!6Hdt0frJx0@HK+8Nr3QKUcq!bk%vk+_u^oZ$g3pDZHf%CRRfh z!sER?winm^od(Nui$BzF_X~x|DWWjd4mKbx?T)*^CD#Jx+*n7;NsTE*2i>;*XzCt| zk=MUVzZvB*K9Feu<`?)hRmr(7?UNG=Y{w}}co7`L{W_#_{M$--b~WvLD@Ub6t>>@;sN?6TOA>RjFX&|*5)P%^DlW+S+-*Cm1_4xGJgrW^l`7kN23fms&+B>amXCI~hC zwf5hSH^di)F*VN2CLig%yaKixRn!nXXkwlll4tF!!3H}0`tnm~dIKPJe?bdOh%f6W z^-M5`)y)ex61DxV4#|Uc@>uF%7B&!F2jcG`?;sVepKtgah4FrbK`;3xi~qCa#0wjW zJI{yE17`D~Ot^8pfc|GH%V^feHabtOKmrERJEJRXGf~RtSngi;KK^X%|Bi6Fm2*0E zCO~&eVkTf7&dfqhnz1+m-)$btBorVGnyO=KL2j{b2@F=e&?Z)Q1SPT_lnmIWfozKr zA25)-Iid$em;Nzx= zWzN%5HR_dzvxC{gJM3U-*r@}9Q9rTE2bpErP**E6u$t)fah*iwZV;YghQuQ-3tc8s zH(Ry`W`RKf^PF~DAtrpICUti!X9ll1{lJgx8KO1c9_~+3W-9In>Bz)pkc-M-Vc zEI-YxeCAlRW>6!m@4@_ZUX8`ZjWSMS*S#lGP~D4W5?0gerkl=qO0&2Bek(c|3W z@-U8nfX>{a$;?=S;pOt)v{bQyG0vcLYARu}dXeWFXp$+XwWhha9;Yc^1~5#FySZl! zlE;hRj76;c@;~eoGhe31Fem^M-UCpgDd;zymIB~mTnZKW)z}eW6%8)p=M+M&xf6XJ zwSow2#taxN* zlSg;VgJX!MLoWPZqxJ!E;oZu}UmE;y%Et>ZP|8N{Ednj}>6pzHviMnBS7cCN>?|0T z{wFZh?=ZJBqD$=FN0i8-)wVB()r#&N` zE*!nU1}|74e2|#-jz^+6`^gVrd&Tpoeb=l}$8= z_KVruG)gSwF*J}}@4CgE5U1>K(K1?Uhyoee*MJW!2dwNQXi2NLWrT9>upe6}-h zrlNaCF%g%d9Sl)&mMc_>WJe_Q1vaMIYx#cPU0)e&rNZvTU_Q4g zJU8)b8tCrdgHcU`4X>!i{-lXqOnd5y;V) zbHXwNB1Mi^$bcv!9`KDtbnY z7TTAzuIW8a1Kg9vr~l49tw{Ba?rpSYQx!aqZA6Hn!jnl2cfId$qZDDwpq_Q&FTKZe z`%9KDmcIGJNYY>VU+5WaN6Modcw(wqHE=R}%SIB&*9Z(|0yH80Mlz;Vu4h9fG}5Hn zo$FWl(AgrgRGx{hMlC^RL|W&aYK9h@%G1W2kzx^@W8lP2R)Y;KAqYs1&O`mL+v_32 z_X}wRgO83M#rhsV#GFUQA<_je&+qn26KXv`xUrE3*=loRS+c|f9{8j~>0e73=bTkX zUI%-hOI^G9X%4AMpU6jgbzVFrmPi0(e0E8KJuE11N^gWBx(DSOQ4!u8`UlvF+=w*j zs)G<0EObx1M-+)%8!u~>@>&1Ge*k=Yr`FKuA3*Ix{1vKSA2n9q-*6l)#%x^TE&)T( z)@zZ(xt-iZ3rFH~Ff!H0(l&>R%aL?SO~i;t+)w>{BH6NVk0U=RIC!E!0fNa}P=cdZ z_|@h&3R@*QfSExa9S&1dTf5twx6(Yz!JxN+z))pf(V5WOudslkB2GKX`J|!#15wef z?mWC=%U`dVpIag|x$RynM_GHoF8;bezeH~WVv3xg7F^}2r@say0lN5wIkf%9Y``zLFD< zptn!tq;mm)=^T0kdn5C5w&*|n51bfXGxs+qj-Rl(GMRU;KKX`8!1OZ{{9Q96nN!epbH3? zU|k&kJKO{gI@Z+QYhJZ0i0)r+noi@@K%%3>H;nOUXt|J>6m%{#x^mB1+r=s^_+`Mq zc4&TJfA+nW2(ptfYa>~OR56J4xhuUs=;c|R?9ZS>xi)|Zx|Al&eWvl<2cWorrTdH+ z|5H(1z+8J5*sd7kC%x9d-kfQxnJGPGnXLf{+9uc8v=uK#G7eT43KQ$MhN(R1Is%Z< z@{UPc>jMh48_>Gr1zYBC9>TuDtVLm%Ub-&vP1QGA2ch%n{^cMIAroy#ZBd zrBB?fK^O*hLw&iDy=(B(`P~LGefKTTem>1)YtT{yc4zrd*V2M`o{$0y0&KT(!i2o# zMD_+h5DX|d!f^S^%^F|dsHe%Q?zW@zw`AgT?A$7scx87;wewLz&fSk7q{jq6Bcpho zSDQiB!UT>DoRYh6P4t&o({Sa@pQ3!=zIpq#ySydWE`x@K)ikf@Is@dAC5R;vI!1pU z?J?GaiNMuPu(}RQ+^->eFK~tv%H*)P{@s>pQWVQjz*z%74IWQ^6(cu=_4>cnHISoF z1IL?V@{C5nOyg7u!tTq^d*`f;bFSvTyU)8Pmh;Lt;x_<#dxcc^6t#PM-U!59sofDN zO+~|+q%znK?zv_rIy8ZE-CFa{6EIgbQJDs%xif-ahnJT6{8fq?EoiQPuhU`%Sd&!< zozlpeXRS`4_DfdVDvhr8ija{#=oYL53gdy=ya2N(11{-4gDGg+Hsk%mpQv{x$AUG2 zMQ{uKIdRInr4XG4y>{2QVH}7wIBPFxZuN8KE4#J%`Nh|D;lR<<_%Eo5hvR>OnhLLc z$a{$yD;?YI7xD)50MBFsov;2rua6gQHAGx5`U~eYp&Agd^(195e2Lq@BG;CpcP#f` zoDfRf zdK4&1(;IfS=Q*pt7b=B<|B>HVNCdUDD(t=-X9t70ioWRESpA7pQ;AP7$9_BxEH=%r7I<>v&CbAvA4peK18#}OaRUCXEs|Zrw=B;&>tStwg!FK}CV2DL z-5Y7&4T_1{rG~&pE?))~|2A49NIG*QTSt*nX!vWSaF}t|Nbgv_^*T_sQVUx6ztZKj z_~+zQ_PyCtR+KAxSMofydT-|e$_NZWgmmnzz!>kC46e@?=BF)&tmwP6kWODvt@_R{ z$xk!pEz0Bg(+LDEAH3q3NZ?0;WoDIsR^W#AP}=}$R`S0zA|r|QQBo2H7ERBTY5zVnBIDoV#tN(zbbmuAE46% zy3Y@tkC`Ojrbx8jw)>wiWb`Rgw=z(PX}G^*)o z2atEsm?^YH%`xIMa48^Fpo%msNmC;-?|x6ZEFx9ohU8$$HaL^k1$dLZYi{uyjwoic z77U`Oh!Vf`sLgI+KA({wA($S?A(iqD)`w|G%A2tUF{=u&VXNm{SXto>uKkLF8yDyG zpn-|iC8(>3^D!uOXI?6Nj=15sWws{8`Egk9s?@ESfIv^^iV|3R=PcuU*{r22*A(Bm zN9{bEwB;}2LEB&Nia+r&Q6KEthq&!v--M!0d48)$A#6|yeU@yRr2GzZB$-XV%HjVg z@65xg-rs(&+G?jX$u2`wLJ>BZGFCDtgk-KH^D-_Ot=bY<0{aZ;a-}U+2_v`(73*vOorW9n`PWN+CUHcrF zVPPV4EBwUs>wc*>8^as2eUtqtGy+Z|N9h@VDR>;H|2q|x{3~6ZtiOmTWR^sEy`s)> zS%U42A=i5i4$So(G)5#y;0z-DTZO6-6Nx=%C4Ke=FYHZDQI0IT0iK_~p{QdSe?n0- zM^_Cy0E%*%U5MhSIiv3JR@^1TscQK)F6m~yfkj!L+5k-3m?d041YbLeTrZvQZP8b% zO$`L`w?abF)RR7AUfRJ>cek@!78{!O&c1-DPN&`oY`(;szGeVe_$L1eMOl`ODQIpa zG{u^0q*aukV)a-^xKJ;-zx$Zg=to7wq)2uJX(_=gz1Ct~za(*QZP9#uh+dTnt`ghZ zqFwfAS^#IPzI@su{ZnC8n{qJC{7i37)JxM2uQX>qtvzwo+^dXQCf%vQOxCM2F4?yU z74xSl+t&Ev)yjDm7Vnc-!Igqkc_0aGVi+5q-6>CEtWCZU;}l^^ zav@a(HqkxxpP<#Qr{DS9@WSn5ocp{Rw{CWNGoDy+I5t!-*c-Wvkzr=oOz}pQmReiF z{$>O-W~>r?R}i-@z$cZ?-we_r1NKy|Rt;<~d&-iZ0&Q|gvRQTLwa6}kyGd_~A~TZV zT+1^#UURIam_t74@*yhQ?ZAFibG-LjG-dXsr{QCc99U95Y7Q65LafwpIWK?d^OX{O zXOK69%x(kgY!f5}_Ixu-S4;5WzSX(yVL9xHGh!qO^6j%jtV40aTpowg_DUD0x4D}e z;!aPSZ6eOt)_48A@2|@sj?A|jDw6Jk-=qAV{qo0(+6#?62@m5Q#xqOUerO532Wrf~ ziB!6rTtgA>-9`VJ3zt?q!y-!9Y^pX=nS4q#(prVh7LI9`AN!N5LVG^D!)V_C49$AK zemSpwb0XofMW^nE(=AelATd8EbJ|~8@LkS4Cvs^Z-puS)8yR}z&stJU?5$wQoXLsl z^|{=#XFW9PHlLQ*VqR2Y+pV@;YQdIQG#*azk}*~LwHnhq^btKKOKn~Vh2B6u#($~q zkVDy!mFVuVqk#0LdQ$eno88D_`ZE_=qkqv>G8zZEKd?t&>Q$v~d&B|)8qFJ@?cr#j zXdv$(V&pcib-bCr=U2sL|K}J_p?HFXh-R5T@%jNz)^7vybiQ$wg4s-aLtQE>WQ z9RU+%Nhz)g<)2I4^A|Mux>B)G5qmyda zugdAlZh4w<9n|V3p}nIhtul^B*V$s1?N~8p&6>AYyp%K5LQ3G3P}4=ZA&6t7qDpv( z@sUXXrL)~8q5jx(xgVV}H!Tq}f*8_m0N+}R;z(ItGKl3HMU&hQX4G3}&;X( zw0knXKE4kR)wS9Kq%H3~A4b$)Xk=@A)tG$+^TGytRF?LmvKzRQ_KP-);h%U}_6s`3 zq4BYhS38@48MfJ`(Je=pIq&VLTCU=H&nQ126|A)fL z{HpNWY)yTcdH;`>#G_<%VFVoebLhF&h>V8EG{T`A7+s-aR%PaOwL_=5}R?t`IKZf+JTjDCY*v)u9ydRMIJsF{jS_ zI_fOg{Y`FJ$sgPE1t=;mEw0$_ZprVvkwT+YdyB~nlo$8Op@fIyf(uKQBmFaq)%NgfPr$^Qs{5c!+|S0 z;jyNAcfO4Ovl~x})IRIwENJe*%)u__qt=CKe)Nh=Z-S?|$S={o*m5@q+^fnhf=ho= zXowS0Vt3sbf^{~yQ97y+VUri)jnm85xQ?IdGmI6NX5vWdRE)WiN64H+iTs= z4mu;&NC(fN@s_u^B{YL)vF*`^DWlUeM?>tR&rk*U(cEw+&rGA~xI!+bUP4lxy_Y5e zX=VjO%^Sm02HPfcvF?P!VdHT8P@W_{L(`; z!v&8U9|9q9OM%Z%3hv(1y;a*w%{e-SOyENs$`i*9jy%jqry??!w{%*P2iSS=@1X6K z(3A5P@6Cgwh_QSk1FE6}7z_bDLvJrX+3HL-Ae>*jaPTHJ)I8sIWG}ZyMFd{EpVA>e zU+G2OaZwCWKC1P?V^YMmXRtKJNPR1Tv{?_6EV6d zo5+%HfE}8y_V(N@Ta0YKGzH zQ}Tp7Jozvo)#{{{n0C5aM!(@aoRl(BDSw!CzGFJ@1MROBU)E}v=tFKMVg#{e8s8hWYk&F!LKhSv>8ND zmE6C#S4!_}t`$QNt{-bTv>MrCcTnuoJo`OP)o2S?xD}elc@6A$Wson9o0WcFL(iq( zm$Q#b{;jT6)&k!AqFs3SYT~NqgTZ=Zmi*ROlEOtb@t7jkeFtcr zqxnCXeo~^Rfi|>qZLY-&;pCy30!dnpTJIWOYk~B zl!l7v=X7RiaHtl5+iL(I6^>bV-4dN-1$B{?#W())*m1ECWCTZBF8by9>UGiy?Z%Zw zFOe0K97KIAYrw!@0uikvr6GA35jZyKaU zOqthijdN{n_~f&Zs6$SzI%zp;6x%qG@4h> zv_(te>H9A6rJNHd_GY=<>fEouI{IML8lpG|z$YHrrP*8>{f%H;?WGq7UfRY}NScy9JtxrMEA>W|!Li_{teNJIg+w-wZ|qh?wvt zNHK<3oY`@XII4YFYdm)}yf<2K@e(cz8#Am{b**;q5Yd~Xau*ZmKJODH3u zN2sBQYjb5Y?}5yivA>H)Ow3t!bIEx#b8H2xnRK__Rn<6&UG5AGooU$47pQQ>PYn;p z#r!@bUR{T=5)$l9Pg{9vco^p~dEG5*bo+~X(h=+xO_*<*RkYZRHDJSTu&h3;Zh8t4 zbY;?@^!@UxolU-}QfBLDCEcdXE_=gW?hgG>hJGV&%AEA`v<&s#?JL&7eN49n7G3|_`xKOHx`xbw{G=0v7H=7>zfnr>LpU76vx{ppyQWpwTZx zJH<@gc=27qnv<;$8lH)JlCIM4`FP|{;7LI`xG2xI_6F{)4x9bA_4i@Fl%nu6=yyhr z9kQUsq7pduqi*TgD?!eYQFdjziQykG6h&xtd$7XkITD_wm8CiB3=kSPrapu%)*fK( z+gv3I$ku1vE3lfrgU|D-dVN{FvsIen;eCmUD*DhrbWlhD+#m)5Ib+QbIy5#)5-Yj3 zPN%N@^2*1}{6gqqdn@D+3I7CArfm(JMOqGe%i3nco?E{xFWBu-_IT6lW>8W6@zwWF z1`EEXf3Q6y4M_@5jQAUjufwo=S~Bjs`8wbxSNk7JZDp?#@i-`qvw~n_39rkLIZXZ( z#zm>lYWyd4Rr^!se-NPmTQyR*1D4m@C>l_uw-W!8XX~XV$Y1_{lv7<=pH7Ru*BWYGRR6r8YjT-#|Qc%9$wy7q+6*6*hnAhB|MZSLLnBFsDOY9b@_?J z3LQVG|A1Qcb}ZsaH5+YI-)c^MtUoe`XMej$D=?c7?Fuk&x2s&RSzT8EI$2Y6<7eV( zF9&^VHdKJ>7F#_4$CmN`gxKl{O-HIq?2Mtfe#fkF*|*A@T^|&IyjuC+A+OA)-yua^ zD6`&f0yo=1isV$Gg=X#q&BC1%C*ND{wEM3uXB?!Ph3WqqPGSYmbGIk}#$Me8nou17zzrdns#WZDD0o=fz-f5 zm%@Yowq_KZCzg$_UI;LOo_mD=n}#Gw_chRsac4vNK9ZRD95h+SNIO9JQ7=#G5%p|} zAycB)qFa1|w;rZ)uCKb@&|`$U*;5@AReiYf->a@P)lSA>f}Mft zSq^TA*~r#{uJRZ`YYV8BbZR#A+MoPdchN;@&pew=GwB8wH^xN`LX8 z>=iY(Db}~me<+g!AvI7Ou3rjoYFfOB#XdeRMfP^36XSo0;Du*yt(w!{brf|ue>=5PyW^q55;WK@PM zDvVB$K=@#=DWwofbnv4+GgBQ3&z5qN#POq{EU`0_9`MoZ=I{g-?Wq_aJKBxT2`KbF z+oX8&x+Y_HsAYHF^^YFDQ-#fum(GZ|EhPsuM1_AVJ-J(DCJt{O&$<5=W0`vw4;NeZ zI5wmV>)Ef(6NtTCZYp#4*!!F0`dk zk4^q7ni3U>o9JI^Oq-5eIbx7?eU=8ZtbpSazzlnBwGg!HjZKq@wB~8c?x650ch~;Q z-<7$=LG?)ZCqm4*>QYbBVXB8ubaTP!)Uo=T+uv?1#N0`_jAr#*34^8bfJJZiIC?At zR|i<$-HKDd}n=9*wi2jSND0IKP2iO&uVhjeFZ0R}lMK$dtPCV{D(Q6e+cItyD5 zm>~sGEhw|d^oBU}1$c}OAlVFbzhV*o#rJLv)ned<29Ur%2(or3`GRljuJL~xm(*{Q zA|!#$eu_^et``gMod%>&YDiq5A>A-Mv8{hfoHV6wd9g~vri!PBRSyG`w0%ivJ^1pA7WsFYc^ay#6Z?+``x_z<#2T8N_xizROi`b zYi0E!@zX4|{6q>3)yK$NMvzMBRpgAF;_^q3W07Z(6A28`Uhir?pNk3Qh;hrT^R3}~ zqpG}o+gvJ-MX~~0-Y+Px1=BVCJ=aBZMDAbn772Ybkz~=A_k@Y1T9srNI8hCGR^)<- zGViFPC5iq?hH3VtY@CvrM0GDOTs7n zyxhW-VwU;JJ|JZxo<%nC;zQ7nqSwRqnjlflb@~MDK}llyN)3!rqLA#Sn_bpuPTP;uLDYUTL+i{dA(jp7S!NQNSm>WQ|aOV!th zu4s%8JTZ=S!8z_b8p8P6_TAmh$oQN`~Dm8_<`!wg7ta4jlt8*_VLZZA1+ezxmvP%{tY)5 z39;RI0?C>DF{0@fNKdoc$`Pn*QqP2+tL=yZrp@hsU*1jHn((cbnJTEmP+ULql*D(dWwFb^EKQx2Tswm?`m3K$t_bbv=$8MX~zR#2K)#m!Bgb|Rn zvxSfVhDvJ6H@)sD)B=>32|n0%)&7!LKJcUd4Bk5sc3qL{+<9xxt6c5cms_IvYD~!P zkKnn7L&gz(S103$yGK%JPSfA>9GjD|KW}~IU9a10M}CP%zksESyEyin&!KJY#8w{(}}UtUWk2!=PQO1p0@wTN6=V+sCT9lF-v z$Qk=6M$Z}AU^!3DW-O3iYa2RKzw}pbNWM|Jy+KFr?Y7CXOZq(TvH$gp1SC=I!V5Q_ zsP8VWmw%D;cbb3dqxnex$8ls~>KqG;v}Qu~#wwGMODrube;uQsl^Iaqd3$yal)Z7v zh7e->+Bcb_1JM6Tn4;aO+7Yd7ZaxYG7pSv{xlWGFM?z(X3?|p&SS0mdv`cIcP$F}5 z2eNgp5F~a-G_SguM)4x;!R7V`B~R)VA%oimoS26g2_&_~HE43dR;6g_aD6!YbL$8f zDJ}JFaHis`AQlPB@B+^vCr=<3c|ZSxY(RMQKD#Ki@2EC(6>8fQpU#u6a%ED;_c|b!|MPc2;lM|*Yj{)6CC3sV=k;U8B9B=K>vM7bvfVOZ?hJ$ITN&&l`?An`;NG=`*rv&hpYt5z9>*2xByk$t;tFvM6F4z96InP6NsWtfbL zEn+r4D~US<2eL+>*pz-r?}_9}QWe{Hgs9>vuZ>M{7=zvlElY%3Lu&6<|MVM0jo?Rg zEuZUJs6s53P{hixl}>QN5l{v@(lfRGl}z>?%C=OZ%uR1HO@nB7dX_||&YWn3DzbuA zVsAf4xc&vP<$M1Hu|1EW-zY(_8 zo74ET+%2oQrz}6oxHP{0viI71%?uf8POfD2>rIebsHl^r_j`uVdr;-M-N>m(gJS}% zH~~vW+9`jA*c@O~gZhBF)Q1em(66A6q?U({z^yq_+<;}JUh&Miw^8CkVhEqD z=9I5e7IGvZyG_vWd_}Ozee>91g5`mujE^+ZZY|A7(sZp1w;9a{{plnST5`sU}vLE zO?4sfWw3#NfBos)(C&^kp`sXbXYHOwo0HI2hOH@MUhnM6K(iQDo-xt}VVe6W2(wlS$aAqkH4xK*#;v?4;8`RhJanwqvM ztxEw?XC5lGR>l;3;pLrZ#WLh7e8$Dmu4{bSmDR(nXuQ!O@U3vJTuTf_Unl-b`}0Bz z*VIcwb!iK~rUdEiq-w>{c}SycxZc`ebAoH`dK|Tgh0Ty|nYzS<^_GnD29m)~Nw*qA z9eN#{3BZgXy@E|;vcV&QF-=uF2QEagOOAUQl@k6G0P>0|3@fhVyJXskIGg)0GE}{XamXeU6KrN&h{8XY@He&nWvvvA$tLIY(HuIwOs3mS@Ccwj>-+Up4U(Dhk~mE$zGe z`OfR{rgp#9;~blM4*q+tq0^}}gB>PX+zBSS=hah@bQB6DT|99lr7z`{k6-s;n+#8Q zu=TSyK3akK!GyrRC(3+X6>f7gS*pPyf6Er0N}OJ=eP zN*n0b^cLC8?k9=TZ8BZbPtJSmJX#1SjknD}QO8`pfy?mRnl$^R*U`_q%s4C3_6y$J z9*;7b7=3Vt#7w=F>3Qi+SpXu!z}SnNh;?{9oIaukUnM$E>97bc9j*>B#s_lzVx2a( zhZW(XPAFojEjj_LIqjkDLlR|vMOEMwZ;`~g!0al%kB0}PXumVfoM~Fccy@NE3U3r6 zW#qBwTWUip8&Q*&-*49YP;0(l zM$o%JvcfVgSL7uPXF#d9#-n7YrLWrSPx%c6UGSKfF%j*-a#Z@O93u)EB?_?a!C82W z-XwM;VSgCIdNbw(_^4j8aCv0tmls&~7kr{0pw{feT)jl>{Zkm$48pMT5&E9zY*WV* z4EOhBYP)EtJ-fU2LTRkpjC#g7hMukaGu`HaG}e$y8~u}>v)YqGV|9DE_t0w)HV&}T ze#)Q`ppTH;`FaKATF=mxhE+;7L)fM`=NKlrb#N`t?LK*Whv(X@5VVnnIAHgsJ~(~j zF4M0H1w2|_DscimT6N}M8qYmFfc5E8Phu&0&R5+B$`{<63p(B9e)0_~`lXEf_sH5p zeJa88#f&Th{~aQSE96Lb?JhYYlAE;UsP=$SqT8602f0+c03@eC+W3@@cpF)Gk*!Sq z*i*04FpRXP>7;8eHGM@xIOgqOIo}#3=v1||Ja%@$Y?9z~_&}wx0;Y20 z(9(CkTF_cGZ#Td741Pov|XhU`8Yz96zPo>5^%`^}RJZlJd>-aq?1TeORXuodS`6f2VsDtdT-) zX>Da*{oFId{iQv<)cJS8TXIq3f&yw(A#uyC;%ybq*k&op_7&W+yv%u)gG#fUQT?L& zT>6?56$lE~@Lb^Z-zc0u6`*iFsS7?q2ny#@@DmD`4t7q&4@R?xb~Wv|sI%W;ETF(Q z7p~mH>`BBBCYSt=A#6s)9-os#M~|}j zB15lKY|+z6>ySMX!lpj%&*g$l-Y3@G7i#_WuWMbf_*K|$^a8%b)8AcU=W8KKT55HT z(}NdZ52et&F0GmhjJK&XxRSTof=1|`CY*mN@qA6Z*gb>h?y5lsZmJgozg?e$G1|9c zE1U@YyV_ENRd}gQv-r2h{6*J}H5?cnIrp)?2*?6i2??nSWGpRn;PKx=QeWJ4e$!j& zewVZ@r)+Y1XTAz26nD_uEMTGD+RQOIy;3JQ{*HrS)2+_)F%EG9PRD75KA<LQW{84;V^wnNL>CHgHL<`&&cAMQl zo!wC|T8Sz^4)Top55gxV^|t0A{pZTKHZxn;W+!Q_x&GU2YA=h%x8%-B41Z@wazY-I z*IB~@yvS|&RM|#CccHvYe#VErRGl*Xx9N`uxz)b(o_PSkg5KR9#MX@5sRBFy|3e1-0Inj$s^i8Z@W%xOp zvUc^E?_aO9I`U66apx+TU8CDnOUj-_MtGjH<`hk-#HCj+l$JY98)JG@r0qnPjfjTH z$JI)0hUe$6k90pZlH8DCGMEEpWAa}oFp0{%0hRFFF_PEf_v@XusKTse;`@px-$}%g@ z?r=}J)N|!ieY4FtmIG`W>U2KR*U_8p?>BXaMBAeGj~%S(V&$5yM`#qpQ?`^tSxjQQ zRs_^6o-m6&8Y{8J&ptgmM5gThqdw_$+P$hOtk8p?6#7XIM*l9|@yvVZUEfK#<8=YMZrsAUN8>dc0Vu8CqpMlm8I5Qy)COzchNOy-QIM=v4E3S z^n8YcNPRFLWw?3X{m9e?F}Lb*lzT(6&tQ`5zaiAFG6_AK_?I*+z!|0T=<*LL)m%nG z;u)y=)!E{qys6^N@%B||_cbeAJNp;X9p}@r@cqyH+Pggv6c`koFy!s69iG9{y`Ye< zMviPRi&2jt&(ks5JpyQrBj^c3px>2T&HV5jgDnhG2Yb$vYfWjQ?DKv|4B`D~1Kpnx z#oe6NvM|@9=dmXY4;m#a92W`tK=E3ytx9!IVZ0(q8C+Iu?T3yIf|DB@UEfStg?=s_ z_IR88KsKElQ`Q;eM&?R!TERZQkb}G!JmAHk&w!ih$-?$NFd)s2`cd7HRc|41Y&Q}rFHLRSnu3t|g053&xj z3vvo_OWb>>#aOrC(It^0OHr+PGZbObuwr%%kFRhXd%@6^1I--x?TzJZ&>>;kFBH$E zUt0x(6^~`)Olvp$1sz3MZ}n_UwMzwFxGhzF32K+x&ZyUFe~%`j)`VxToQf z)=2ynu;iAxnnAmNUs#mTiNp_6!$b zk=#GzU4vM+y<5Jl#5!S#ykvY=l}b(VH}Q6tg8RE3*oNn;o0yv#e>l!`cNlQ%k`Q%0 zyqoK@SG{!~#A*W{$kPZrmiJCsktn9Bt(D+Dh076g{*7U5Y4{LEFO_&H!rffM*za+v z`pin>=kS4G><=!Ilvm7jZ+*$`7?@GoW$SkQaU@X9wq^Stz&qtmqKc zx2b@}bG`T?YfHkQeq}tCskQr(hW-ucHu&0|r9J#Pn3bgaT3XCGo0diJ3mmAFnV{jY z*>f?BL3cmZ-kDE{bv3q4CnbL7$4<8oo7iifCNI2^M`kCTgG`gQX43nQFwP1z2DRLFGV};R@@_aw=9;gEP9wnGVgyJc3zgy-eAnaG8ajN66|GFk&_c=`FamjdFiuv zHEiW*W^^78Wzz(^B1^o-W+0IvF@d2zR5=u32PJQRA9QFfMnuW;dKKO|de~k<>5Up9 zTY~!7XI=tknVzC|dd|xf1`Us3p}vL_LnAvUoMi??=kDg+zwSLfqB!r8TQ1Zfl91g z+#3m#Ok)1l*Dh786Mg)q`|$OII^Uh*(P`Z~<o_9AY+fVg<#uO zxA|hQ{BL}^-$VEVR$o<-^vF;CkQ3<$V4NQs^DMOxOeHGOw_msF-bBZXp?;a19j9zb zpORj^+VPb;*E%C#`vFPh3RF&z-~M{0ha;jy1U2Z2`@q*n@n`X9S5dT$9@dcLX>cvt zStSqe7P`j#Hr^)P)%yo6)k_dDiiCY}Ileu)(v$8x4Bjy-xc*T3Up@f3B|5BASH|yf z$x#=QvqJ?7>Qimlz-_trET`-Jj@bE{cbt5;=L>THQrPt5tE{AOkIYIVXM;)RxmQjzN~lD9 zE8f)bapip`>hvlfnb&P&k&ioBle#hq`p0a?XaUqk6RP~Du5V5+9{aF(_DaMVUcHKL z;cO!tcI6012QBbSF>@czkK2P7hlEiBQxnrokRpQC#Wuj@J@)3q^a&+(PGI~80Yr6e z;0#G7o0VkZ50B+S*#GEE3#5SUbZ`yP9Km94Et1b=Suyk*a3^?$jIbB`5>5h)LWz8$b<0HD%Ym zl;XDZ-EM0L3~u6J-`o*Gl;5;J@VY<$CKVO`ldE5TBE9&Z{6}*bJU0INlT=jy$EY;X zbFFYJR<#~1>+lBu=wH9C-GPPwO8l9)!x}&LJbvi-c#QbhpZT}?tRw&Y?*EgekpGja hu>Ya|>z>Dyqq}Uo4JXr0`_DPg!fOx#r@_I~4^IA{wGASFVsKDaxu{xpLhV z|M0y#hv+u&Pi|PrD9c>AQWZmdW^xn%{I;{AuG^I>57{mr zSC!Nr?OeHn%Ttn-(eO6f#J;y?Rmzff2HK$*1e_d2z7nmHW(9X6qzU6_37V5}*`o&% zI;}j_B{7Ljq4JKFKPLv~rn53%IZg%pQdQD6X>Y@HH$&2&rswr?H`o?2SZ;sOVy zAL457SdlXE$aV99vaxf7hX>7S{$|M3BR5}NQHo&UxGuS(>3-uO z7HStUIp?b*(dtCViF@34b6k~#QLQ)Bf;kY;NM#oGv2hH~meIH3eGQk`TR&-~Wxm_C z>hm+^TQKy@S1U zI6J9=`t`aSf0#7(J|V2;<5Af?6&JHK*^s*Umyz!ZQQ^~SDcqGq?& zA4Ouvy3s-2e!Ja;vY57?pn!7W7(vbUfYViow<@aQV!_-w%{$-LJLEcay1#fq_h39O zPDIxxkB7}I$80VlzkZAtJXVhg4s@1Kugs#j?PS+l&Bm$nx^>dvVYMN&ZB9)^#L}r8 zB9d2?2JTn=px!`MeceLcHtCnx*x>sOS=rKR77p{!7i{77T0*__<2ASWD>{o3_iAV= zl26h+Rvp>`(Dt4F4(&SknkDD-<583#gx4Pja%E8-)FX&P!mr{`&uVEiZji!@%~f9q zc+xh+kZ}p>$lY&8@pIvU95i+;B64W}DMZ;8%Yu&x#R#!YriGGYn>@1qb2SyWV;bO9C ztRqS$kI`9GPC+J`2zpO64ad2V|H&k4-0sWwP5^(2kB-jx&f!Wp!hjSMe;1Az=durv zu#9M6Vwlyp_PkQcx7kk``-V;K%;<%;N7|`^mDRWPK>#Ztd@XhVTrQE&|lB8Wh2jm z9El-^~<;^gsakE`jVB6FVr!d}5gFdD7Nuev20N?o{j;0hGPhyQQwR=le{V zx2nVlO7mem9QcL{2v-ci24FS(_f|lQFnASf?}axY2y(IePU~if$Z@ad+}6z%!~N$Q=o~rV;Kh(Em{NN{1|dMlVw`d_Lst z@!&fYA$n!_dTqBbRm^^`Kt~*CBK2H=rsp#~19Gu>iZ2imSZYcmPVeIvhXi2u4{wV! zO_q#vyBwqfGUa|SN(nJ~?Z{WA_j?%L_js_~pjcTHHh9Q5Vzk(+(_HfSiLOAlzJ!iS zUKN|PHEVl}vo~!3-A=A2F>B!(^V3CtOruJb->xo=k0ynbS#?~#OnrBQfzfvs++eWh z*Vm;~5D5f~Ym>=bW!n{MR%2jC2Xn|+p?A)vgYB;N7aW6Ai*GZYZ-dwp+*EgvTNs_Q zwyJ~+zvrlWRGQevqy>upT0u<$9g7be5)s;W^EHi{o?vTgW)pryTP4pw$&xMJ`b9We z!^rcIcF>NY-&ifPcVO7Y#uK{+2?_W0E=`U1d7^_JwczH|BaadTnPG*oyuh@!0@wqe zmQeTi=jcH*4-}o;1a;A}%K=lN_@l&qfPX1}lR){FQ28E5(007~qE|qBm{%P9o5uc6 z%9faH9P+;8u9E1$ZoQ4NTW$^d{%%UWQWtSX|`_RQ5600Hwa- z^*8K=ZW0`?E*O|e4U+I5^QnB&dTz0KSpG_x}~RS!$)N6t}2 z3qv@L_b8=%jN3gaon~-s=aPx>p{1MS&v10c1`@ygEV)_mS6V4Uf!1p`21zx`-`X0W zq0p5H@|Zs>QDaj~;*m;7iJ{y3n8+;EXEmXu(b?ZUMpv(`DvWd5(p8vvaI#95kd}ld zi`XCs0l{N$a+enL0p7}z=I>h60|2pcf1O39hUc_9pfBkH} z4kakg0&i{(^OD|{0J}IZO*@wN+hv6mg(zJY`&FCJ70nP#KQt9BOgQTo8&Bj~q`FIb z1phhPenNfzO{x~+C<(s#N85NH2mgX#hG2Cl8yN7 zQ`zG2bYB-;_c2kHD48^QC5~WkLo!i>V)ei##_d))JDH*Guh#cl;`#5Lgtb@7QVU+6 zYFB~CzxtKUI4#9|9k8c{0Pot^_ojCvKK3_>J8Zwo1O`{UFGYu2n&QqKkt@_vXaH^tKql1*hiZWH7*sb*~l z0W)G7?-PaXO1Heg;G~UJa-WGT8X+P`O7@H>B)o0o3FOwmn7!g4>&-QDE38t zey|c&I)LpVZ1VSC&-*JyLnK2F`l2jO!B;wDo^(#m?p_O}h!L@=2TxRsk0Gp20@h>7 z8`3$LNHcG3J6`@(bf#mdfk(-=RK@RY?z*#N0!}fzSL9_egLYL#2>jrQ`Q+Q=H_;Gh z2oG|hB`jPN_HD9ofy3=Hq5kR zd6w|Loez#upUcMF_8W=KrX9EYF%M8Z^1rI$ zINnxLhq=*y)(f9c=RAR)!`{Zx1Uy|x55U}>J6@1xwaO>QUn9$+hdWe}BcBELa<}32 z<8}TfY<Wm2-8Qo~D!i1OLp1H%0D|IlC+?d0-n`+H&eX$k1t(WTw;An|l8=kkjqf z<|J6p=L_DItZTX}gdj%9qm-@?HcBuUxOshf?Mv?ki3VGNY$p5PTwt7v99&RjXwR!0 z7w=E-0{+6Y?A6_XENx+aob)2jn)^MamF77d$8#o)JFz-$KZ9p2;_M#7%XK+h z7hzGj7)DmW%sYzi;wAEtNE3zV3r7}a-BZc>uXm?nSuZvlOWO0zzRQo1gQ+~1FFzJ$ zc}Lv!au8Ym)r$U?FAgI4vRa&0-5suum=iU+(tFqeF3|RaxRIOu!<-#{q+jB>UQhUz zIC>anFjbAdr<}X8NJu&4gYp5tH6v60j%)iM2lc;t`8BgNP;XQ&m$`z@~s0M|BquSvV-aDED6wZAF(Vu@%YQ}YI3_4I5&2d>I$Y?C5t?E1+t zBU|cYF_A!cHMc1qntLn|hnO2?W#o6-Pk#Z{<AdRb-N6P*=P4Vk4f2ncw+3wgZ$DPX+CNC>*q~#I=y+6{FLdo>;}R zEGC|4smLl7P;|-sJon`k>eAJG=EP`7V?%8|N3x{sKG%>s$=TAZTcbj}I3ihL#!#@+ zqn`7_NGCa4a52NGL6OLee^qwWTmwdq6mU^`$N$4 zr_nQ5__@-Wv)cJytEE(li+`P_$~n3VH8YKl(P)&XQ9pdp=mb0ej8zmzpK!MU{i@n}U0aOLk*kK%&-#@MYyS+FP zwQEEphyDo)&o#Zu{)OToWA2gj$J{a|iBo|=-m}vKNyb1VrlIso*8KHNl&8wx^O%(t z(eXWnDI$!=`5zVeq_-=^i8!g=&I2}$*t741w+fS|>`S@LRL-B}A4Pt4Nnmb@^Z~rK zVAzN;TGu{!40kiaIxq#CH>yx;$OBc-S%`7){#dV=Lv=aqAva0gv&*AlBxzZ(-9+9P zaL*W*tY`GF9rtssvPH5b_J=iNVNrO8u3Fditz30ZcEqE;riLkZs=9DmRx5C9=IWDo zhRbnBpY4ZWd-@lc(oVK?|KK&Uwm(BLEjQTgX^mwDdO=L5e z%3ap+qr-x!?9goeKknuOuMyb!Im^*gpj&>AuK#f}Jn7w#acNICNc3hk2JR*Mqz{C>Lb3N0GhW^8ho#!Wsn}2-fW9Szp8qHU!vxiBC(NBSgW1LZA z9Cm$lfbo$Ns;ZJSsk-}aZq-OTXitum=DT1)&L1q|P4bq5RWUCwof5=(B37L~nkQh_ z>6w7*Ubt1O;~=S}y-Vye3e3`SkCDq{EWj;uA`TQ7 zleBwBKAjNxt=Udf;8%OUw!i;`c@x`Em9TK~9WkIJRVwv12Y0-rEuzWqqu4ePn)36* zin*cDZ%O$$Sc}7AYThHygQ$JIo@VL4Q%+~#zWiVCLzL46eh3<2E6LrZL<@(CMI=yc_1k+83f5Iv@MZh(_iF@7mLYgX{&$Gxx{X%$po)=0-1?5PU09Ycar zIw|-RRKa;6y9o=T3=EbBzLLM5nG;zl_9Um(cyV)qQ_+^*O z`|08st>=9hq@H@CE8zoAqwY?d7}dSR7ame}Jsnch+dOL&yKOvAA~eSPVQC~IK9A)J zcESxM0T#Lm6L!ReEc0KjBrJBq`($Jen%L9wt;z)UO49v~IOW=P853cRF*8hPGIC$O zer}KVPpF9XEWB!-{lnZ)MQZaKMD_s!jn9{ycB0a{mfFFOiguIlwVi;n=c5?U`CY|U zo_kJ$oZXFN^YVL5-ja-S$Yn4}zIf6Qvb6e^mB+c|VHd)P<|JIym0yi#XC#(}djHp& z-8>(bY#7Y;Y>A_jSOUA_al@=&Wyq_vlvJeTGeFWrtMoSwQ^;cw`cptPUZT=A^0jc5{TE!BiDixq{fk5di2s9Z{+rn4ziZq7@o-~vvHS90Tb_K^ zqa=GN&uznf=^9vaY)p`Sa?Y-)JzCZbZVdbvkPm<5tCX-(8isCmDp8nwcI?0#gTy0X zzJDp00$Elv1FsE#q_&T!<7%cW;Yds(l}DY>(A z?(%mibyUUn%r0|7Q_$P)ppzYjLm@ERKVOn~PUQV*O;uWcQ-CMicb-%(>fi6A6==2b z;_h93*NFSl7U5qL|0nSHp9L60^ch}K1}CdgYyTP=e}ASo1y6cwT7o0Gh#p32{9_$o zS@g{Qs~`I$CqF~~%!!7-e6bwY!}rgdH1&4NSxdRjRN@;fw#Cx_oC)=f=sPA7k1jux zqx(~r^Y7gMKicyDy6*)d^Bz@eUS%%s+a?&4#UGL1RK^P2sqxZ|2*UD64Gngtf^6c1 zsLxMLlgctW&}w<}F2+qv9TWJzn| zL84rt5RcKW9r5t6^+e%MGv)_R z&9Lj=IghtPG(@ta(tWHZdRQOydyMOonr1+A5Lq>cwcLR%rU6<9YzUH1{l13` z?6YPH_>ApHD#^-%O#JB^2RJnjf@nC5i`w^k^S|GJSMngL-7?UrZ5YQeZBvoIq0NqyxBdvQ+RXocXRL$qGaP~ukpNQ(Qry|`vP({;$-N8%iwW;GQ0!Jc$&P08IIYi-{WRH;EJQVCHQG8BhU_KK34aM;Vlzu#Q<%NqZabwv+ZEcWJiM=v7z` zVQ(5QB#Ox^<{U{yV=u-!%W^1S#X#Fsot=YUbc&)e4<$f8Gk?YxI&u3 z8qdeC+L&F>wjHzhv)7;TNhGeQv@CRlxn6 zkJo#z#*$=gM4W>0#JKw0cpcT8Vs#lE+V!DQ=(UnPO9%8jZM1VWR5FLJt8FQ&;GJ5* z#)QQQtL36{q%E$_t+2+@P-HTd)Cq8K6QA5*Z0s+&_+cl@D(X@op#=A4fq>)9sAK|= zo{iL1ezd*AZTxXrj7ve8wIj?2U^Cr< z!<|`vx&W%4*g0MXL8fubZ@$j0&k}CRl5V2e_O;$Lh=ldC&9)rfQ>5^vr|dz$MPQRX zdEQO<6gMc|SZ?zV43wH2-)l&PgO55z+Au6rx}^Qnj!f;0J&U2e-sdkZ&h8om4!K{F z4x#J!xq3AgsoEK50QH{`gW$IE##R;IpYSUn%(6&ZE`p7@@qJN)ojT18s4 z8L0L3d`<;P=2$*HVco8rQTAaTj6syTvzX(4qlM@nC0o%j4X zrCjtJCv{ujt-rU@jjh}wJqp0EyUAQs5$ekPc24Pc8h8hM=}XF4*?ZWFt-ONm9fbz+ zSUzm)Ow>fxA8b2MNrPS8oz(3Do_&c=)H?l%o_EzRL&dlb7{rTfuui(m~hgjYaR9oWx+>8nSDw7pEVmrU_s5MIy1sryMwT48; z3cz1idni+KXUp-7_Cu1{JRt6}dKdcnw_FWtvcTA2&&SrP59bXqgYXH`5A5wfy3 z4q~PQb(DUjMdj})bs1=5VjKjI6z$8o`rIoTk{fvEw9k2Ie8g$^=lrU#ekk2(Qju?u z&S>6yc|M;k$DR0K*Y9f0^G%9R$E@%F_&7v$hd~SD?1m-7Bl2#t0!*HA#Oa!KZ;QKD zw=`S&SXe##Q)R#Z@>x;DW;sOB&hAV@?vSZmI$OAsd1%nrNyz^iVTbinqAW)h%fkb) z39C0mC$STOlfI#MoMvW{5jS`HiVME3AC^NIbSCJzFX^IxLPbafg#`AHshj z2k|yw57E(7P^XUr|Evym^q2VCNWz)Zk=iU6@Iw^i?`r>~sC+(+GoTNoi zmtqZYNAui|KKI6Cb;ileT#Bx(UEhqIU4o|qiqQqMvPHkkzZBqJc2qexHg~%=$2fPf zDVmOnR`;}QT0!*V=Req2p?B*MBJ{FiVkTNaE$%tl6&Zz&R)z-lV(ycRR!t0>xCp7{ z=hg};+wk4PrpkJk4fF1|81`Ls0JTp5?o-7xC#!}MW8vOl>g$4ztayKew6@plbsvtU z<6K6faVqX~JPuL%%}q}-x9aJ$%Mri8^*h@%nD#-x$ygAlJyH_(jy`g-`Vg(xYdXQ@ zR1#$B;aqA4ZM$2reg>o(@X9`E+@wd8^X^YE#++kJ!mtqLrppOq-RNsPBdOdHhXhDp zvQSr_|N5;$C*edj#(2E?yJ~vbP$WFC4Pj(2Pn*Z@h%*?N1_ z5M(eG!S9RD^J@Xz^a>^bk{`YN%XNU7CjsGgONU~1DK!tg(A2AtNDZRdK-7FrBu;vcq)4L)3VSZ?+XB@a%Uzmf3XAOkgk6 zd)~RlegA_IIKjIK))Hb{=u2g;-<50sLs%P1*hdW`s; z1MCMceK%2eF5xWO4ln8R+b!6*4zSg3u~(@X&_)zCHxT8)Fv6+E*wH z(AKEgt|eA8f|tfm2y!{sy34uZ6$E*Y3_R(e>kYARES6y?mfTf#>2;%&U5H8Y zy}jd9;;s3EuEXrROT5zTM*$~g&K_T4hi^WiUEhKS?lq33-#Nqb{GTi}YDOI!S(AGcZBJ}&ml9ZbEx0oJQJ>VT>4(rH5DU=~TDmC+ zJsR}s7CYwk8uOG{x+hLLKIr3ii{A2U(};5HOrr3PGoh~~N}gQ7)_l~qw%@r;JCjre z1mB;j{k7*#YJ-Naw2@7sc{d)uLE*g!bRRxoLd9 z*n5nGY%fM(+Pm5dTnh!v3mi|@ju#hi&+)ra=YIp1K{+i7UXb?RWcaz>Yq&VRD@~vD zbe!m+7#IlXf3SH@P7xXTZ?DddUwiwL$LsW|sSEf1kP@2ZRKs!V@y+Bio zPr+eqn3&A;)rT57?|Ew8dx10&4PBZ_PzzY93D7iNwqv=>W5fDol*2 z^lyivYQTW51JPP)*6%S&0O^_9p;HtxC}r?+k2GEEk>?7_64hgscT}GTy%I$1FWyQ< z9Q5xbxkwkK^&e2E@Jv+X3^sdw(O?Puc8-;6Y4{3n2WYlthpgs8wGU>kW-nAU* zuY`{lS(m0sG;tf1TvjV|p{+xa>FEk*MnA0&QdUF)zUjMH?_2rTn?awCE7wguB`UhX zA}<#?-iKoKLjD)-N`E4>oAGoRm^(gl90BA#KNVCkV>$wltpYboeSBB;I1ZD+V;rjD zD!i(Um!^+_q%RC>s8DD;kWK604-~4iwH)K9%U-ovV&!?q2&CQbUPqEUwy8N>@g;xNjDt51Pb!t{hmR*|e2jcq9 z&XOpz7Zhx3OAF5#^=-bzNq1{mlf$$|NdQ1^$Ft#Dd?rU4e>Z1@%guRf%9A6%cz{Xk zXtXaKLK~&`7+{kCdf(N!e^Zx#_5Rr&V?dBoxvljXDD{!xxmt%X?(lxgZfAh}&|BI7 ztWDEEE^0`X{mliN zWtWCA%(gK;MPwaB9eTJCfjJA5@JxzzKAzeOF&}Esb=gJj_^4NM=cnBXO zmBRD;>rtNTFo3;7)cFr9d>xO=bGh)<^}3Qfcg>hvu+)BdZik0(iAE0Kuz`FvvmJyd zqK4?H5p-|h z)by+N2`k0K?Y@n*YZj~vlk4fZ{jSS#mK~3}Ug~IhnRe49bt1)VO!H0j@8}V5!exbr zxOPp2^^-j`x}hPd?$WYk$4#v^$d~n`gJVGYVmw?zUhdBEHf5bc5FOd_ih#{_n4Ddyq zc-|1ch9W|UhmgfJ(yFG-tK~y3$Bn6z5$P@1$eN)Z7lS7?^>Z#MAppQ+3@G_F=;myK zu%lgt;h0eKW7NxoD^|gL2(XYg{lw_ay95r-h8Tq9x6=bZ3@O5BQz;h-vH>FA) zxBALINIL@IQD_EpLnis>1Ys$asy+^82fI#9!cKfqtHCGJ8P8@pS(=~5a)Kr~ zh?!iA49Rz=jhz7Xo?F@QNEzvL%`XsZ4A*t12rciWr|;DmD~!kp$=4*xP5%t6>)vZ0Khza5}2lJuQgYIjn>ILryhb@YrsyHLA3yX~aTd)R3h5^jQkG^bA> zd9r2cl3}@4Mxn!&jZmQFHgY8)tayplhxzq{W!V>3AscZaM^6I*$aLK^gHjMRF^lg9 zo|0*IHWwE%3SzLt_9T*|3(wX$=od^gzNS1B`}%yn-uZqxD4iVP$7hF;Dk(wL#4A^s z514gb!JK}zaK3*XP=Ta6Xr2zgdPs=e|BWgff+&FLyN~UaPD)H9jHX-3dM3-lBV=DN z;MiXR>ugpuS{&%FJ4DDFWqz*@#-M6sOy`$6N3@$$77yXOS%xeu#$T`MgU)}FD( zFLo`d4Fs+bV(lk|M+NDmBO)q+Hxkp!2Q+oi@A|2wc{4+b2tgi}s}-xRlJ&te+R1tr zZ8(^8DsfX{yMF~5YQNA1WL=bPmpz{+$Vh_asv4C5722|OF}_OXesqjz`y5uMW?*mk z2Uth9uVx=X@0TT&{3%+7?MWC2@tU2*bcNnse`*ro&@ktSZD&VTf3kO~y<1yB`kp}e z`OZ;O3Cfl_Xq$9$jkc0i8{9t>p(04Z-6aPj;1M*I-l^vu;Ejeyn6wQOd}))bVx)w4 zEH6KAw*yp={4=3my}>0^$9`6Sun;WJvin2(Dn#2PAE6<+(`UmY007g)U z1ma&m1Q9t4n-v(xjc<%j;`IVd#y@kz>wOEuGft!vSW7}>_B<1q{m39NDD4!PRnOzv zEl$)IcCoU55g1j`5FA9co81`5*@n$@>+JQwI%aI(Y&1!t=A@l14+da|Q2EB}Ixo-S zMg>zh3z>Ys?$)m06Wtp6isz;~ON&hoBMbnDojx~$%_T`-vZS9j>>u``%CKA?<*0>? z@loqS-5fkkMn+2CyJ^^dm;Rc=Pltua1W?CGoY8=oVk*ihLHOx%?>k~yPY4Y)ovAUS zHQa@qyA3i6)Fy3_J~(+hDHaJBon(F=wH>VNV$xP&`&p_9^k;Ks9nuVa*tsc=KMo5Q zOZO>;xVKX5mZnRU4Q&yFw|=1jCH#GPG_lw7b)eAkInq_Srkkn#6<8wpdd>cHv)k%p zCqJ&RyoMPsk9N(~sG}l%;r8G=JtgGPU+za9@<1Hx?;7p*mSA4QWK-kZG{tmBhSQA~ z?`Cq?>DDk?mV?S<8Y&+x{;pZ2%-?N)bJgX8fAau@K+gyKuE2x_{z|@}g1>1F!oV%1 z&wqLr2DYCDfLrd@4vo zmxJ=feAaBwgo~Hg2d7hgXfDIkFYjAhUF_vrCO+_uhD<>Sr@aVBOSUU;MqVd|Tb2Rq z`>AOwcE~>6%$P~1Otik)igt{lLxjm;=BN7ZM{UE?xyT0RTXybmGa051XZd#O-`NBO zC^U+58+84|q^4u>3$@CTR-n|6f|v6%F1J~sG8%u|g=m&Pp8dY5&GYv(uv+ei%%7;2 z(u0iWr+F(Z(ca_AS=Vlz0QQ`2CU5*&L++PlrH#$^KQUUg=8W`-G4KL1R(VbMcH9~& z$&kx%@-h~{EY=9@o$488+K51a_1d3HLqXEGA%D{pZ^;M4y9;B{#6{8r17$oX*X7Qy@|xY2u%4^hvXV2e$AujVO7~0~ddOgMPW*3OcOa%T9k^Az zF={TkjM4{{#JFJ2N3U zs&<0O|8!t+g>M_sDlH60a<`ZC)=599HnVUq0DPcBMi4Tbe47iX0?_;%y-U^IlN9|o(#C( z&p4Gt)OOY#vkR%1?WR2n_!6MH^3JAD{?Fd;*<}E= zh-1W6%}Dv-jNubS2CeypXcyEEJjsF_*b#15-DXN^vmDw+N*Hw-!cI4<*3Sc)?Ku>C zGax0o4l8Ce5JI88qox5A;`tWob|duR65pwV#EeVT=jD^{{)XhCC3aNk7aQoF%4Y;~ z!;bA`^L z2dAYr)5E7u5q8Vq^q$jK!tK!ZC^!{goI{kPzw_ChviKlM-hc?)z?fb03MZl+ZINpu zX!_{RAhr#-59kG7OoFX2Cdi}H1nP2U{l=KuJ#oaG)+-vIeuMB-J=N?{DrTu8!kdF+ zDY9Rx00Ew^r}CCgpR4a_pzxR-D7ViA^ts$?cap7H&!dkOZxv{p4@BBL(tfxsYvG#LWzVU9S+c^0-82(%NU{*n z=q%KrBtu`j+XF9epcY2YKSs?+EFN8x&+VNF7-B4Ri?HpZ(}f*tA2%HcwjC#DFP43) zvpT6few8g1Oi+l|++e?fKcH!U4Hf&h_pqse%A1*fDjOyDG-Q+5e{)#qxZov>$+MX1 zhupktZ2;Un*J70=`d6J7c@g}DqPp6&zQO;ND4TDR-{=47DXwDNPm|zhzxg0o<63MR ztydUecBQQ*VKAo{$KD(8M)6JpYV$ z&(3fwh=cIJx882GJ-W~mDUDH5vTd*8xdev@JEX}x)}GHH3fTVYaEt-QN?=A-Cuq9y z*olYu&3k*PewN&JNQ4L+*RS&}YWGN)Xfq8~X7rLnYO4Nm+G9ihZ*PV4__;)Dz@E#N zAsnduhCgFs9`BAaea%Y?+zuNiH?;scqWtkS^_T&jBiW7IldN(}cr^>l!Lr_6f>SO) zhgABwGGv9L$B6X$a$WzQSC~PY>@X*=J3AV8mZ)RD>d^fHZKqOWAPI9ea*UDLk1hl1 z*R&b>(Z-rYM=(s|!xy?(=XIKTop==h)u8K?-7-7>B8M%99_!RQI?ezhbzo4PiU^12^-JC<4iY~- z-P{ZgX77e*`4G-N1J<;wBrno*H6fSdA^XbSKgwf?JbH)BXW3w4<_#y$=veOcXyk;9e$jF1>-_N6uB8Ri*Lr+Mn#hUSur_3kws2XsibAi; z6BE`d&J$hr@Q%rvKuox(c*4yacBbPw443J9jt^@V4yGS+OXB6)?||iliKj8x$4feM9Yeg$*d@VI$GrEo zWq&wI@M>*NL75Z!glB;cp?cCBFkhF9DB zl5gI?&xFj%nWqgBWrl#(Q9*UIqrdgjGHpx0R(Ms}hO(#Z4FX zam>{Z@15+PlfVKmI4jWo`=DXDwSy+zO#l_YKkKUokHuVn(|so6>sOTX zxaNA=_yVe!qCC0Q&j$WX%}W9^ydF`3bY7BMB9JmWPF^%pa3>;{_gTpL+dIUpM`(r=s}#=ho(z zLJX+2qd*odY1-aYyBndG`*9T=tYakaxyB+fYH595-cS@V>ZJdcXyC<#`bVI2*JC-H z0{S+|mIA7*-bS+{P>T;YnNPn|7;go30_uffk7=L`z^F?c<8 z)X|yc!}Q?wtJN!$zDP8mEBjs6lvnn|m!ieifUAV${JW10l4Jn&5o#rl!G%jtHu;l1 zY3%jyw5wh!oRk?|{KzSas_i`^G8Dz0kT&ghYt2>IML08WLD$HtS*;!)u#3BH zPul5w2_{oi=Z=+eOAo}QLcqQjGq|nn!JD)F#%++n0#l{(sg12fU+$;oR^`vyVPQ11 z@->jLM>%jSbyp?+iUEhqiur|Hx`pfcFLln)9f@3m_dg~T-{!uTk!p=Wzax_ZaO9Kz zLbE=Yc(Tv{Siza_UXfX^~}rik}2Wdi)$<&r{4O4rLEmfQ`IKB^?ip~zdO+dnD& zuSkAezs*uV)-Q4F3-45&JO6a1|BDg0Yu2(W9m#k8ZwYqRwZfZsoogvR7q|o;s8F4+ z`X0GF9hi@`fWkfKc6*;J9koyYefk$t}__K#V-H%NrU0XP08RFI;@{o;uVK2 za_1iYyIZ)l+dZaFbXUHzM7|JFZ#QI47rZuj=ap;o+@h$I|7nN6=_wbfQjy4-U;#Yiy%m5S`0Ao+g=P1c_I!x$+XI zxlP19rW*A_=1$W;;_!RwbFmS4>Z}v2j%acDv1hYcO0cjWxf60N*Qla*^GBlr3Uv-7 zM?GqnDO&x+{aakQCQ37H?vaec2{rr8EzDO z3KiGU9Hy0{E8|Irgiw>eL2@>Q@KvMrlJhh}o;m&RYIb-)s)s~|cRTRIx%N!v7Dk0) z(p5Zr|FuAGT@)N|{|+tb5n%6*RN1BN6fCqj-1)W3?_ZGplsF~38MvGWIbakvtgzTH zp+Z;^MwPt5`X8gU{ws6@^sK-aGmoP3d?c;fNC!%C8+d*S_{?O?SOOaXc11Ae%|;PG zz1u(c_cp(Rb&Z6n`s5bn%ANW^+Z*|T2S!LK*M5BSR@6t^b)FATv$}MdV_M(EjHC^4 zHWDbctqPET0_u{MPl^l29JhWP5jD_xdBzmFPl!0{rQueM(Xbu+fW%U?aRZ`w&Q}V& zISZRB;z%Q;4}SIODlGAwUX310J_TC0{VhykrN+O?0~s5yW*Q+lVPpoXtc}&*jtDhD z-K;h0sIKmMXU@uWIZZ=99Uf*1Mu6n~3*SyM;PNox_h&&n3m!b1&^+GHsQkqUS~9^< zqlE`Jk7Dko9Vxig7}@1_G4vNTd<6rJklpw;s?5dG^X&F}5tF_PczrX4_QRsWM6ZU1 zI!vFBaCh)~!L4!01qNyl>G66hzI(bb5r;)N8E@6L$63At9idr%EE zS;{8kn%dNR!L}tXhCFLsN{d-LX;G*6&bi3oLXo~Cxz?rpk;A+FKaqyhWQ0YfPky)5 z&y<}_`ZXEy_%D{>khoX=hQ;BhI8~le1TI_pO9c*v`T`N3ED>{yolWRV+*+xeX<=Q9 zO3(b`D1$_-Y;d@Bsa(cM<(v4ZDvA$lA`?f^ zyaM5&VZlE9{3qkoY_xH?fIuB zv1EFvsKa#)c#Mcz!9JNC}HE~AaO6F&U8je z;rj(&)3=1U$KDZG&|x}j{e>=8BF*N0i+uT{eWei1Vf5g=f7+j-I5SWcX3z>T2`_VY z?$2nf+XK5*;*Ey~(~j{1Bo{;e zjjs3J)J{(L)^{&oaw7>GYcvSngOon)Q~YzGcKpf-Q~kxonmjGn1tiG#c^22S-AAjm zn4{saT9I6%sF#`!;rgFLd~(Z$+R?t(=9^{$cifi6iw8xn7+(#MtRi7+ABTrIgniS9 z@8yUEb9K+CtwFv7^}X2A<{#LD349YuG#_ch>}JdEgV!F7ZNC4G@)JSD6-~ON2sio- z9JRIZA5U83ITOkI_RAfh(zO+={m88v%6U=8OY-W8n*wV^QHtPu)Mo5f1+@)$9?0rS zBi;>%f5tcV&(l;d%yB8elM_@vZw{pRv4!ai9U3RiFEIH#emC5HRr3=d#(x-&V zVouX5V(GuvA4E@qll~FOElk)Lk%!@_*4DXdMY(3<+z!Of0kV&}{HfFYiwEv%N{Y}!>}wVDgf)!#J;;kstUr*U-EQsBt1weg?)gC9h#Y8k&1vE( z-iKwWDxAHAys}FGBl?Pbo2@(rN-L9A>}_i9YXOABQFjM?9fGxVC1xZ4BzYrcnuW1cy??jW4?@`_7yxF%M=j)=`L0hO4iMSjB1EK(Qq5QU zX%9<=*JZ5RM-R`%qC4I-N@NY$b%poY8c6%-=Q+x*1o6a?_zH;n2qI#;0P(;w35;dA_yo5BHhy6-IpSzFf>RjNH<6iAR! z-NJrd(I+)Y4%OEtByM-)ta@|DCosCy`!?9zzV_F^z90wC)kFbh=g7 zo3@r8AdXU$LkDEfB39a1Dr{Js1mD#{`bcc5$1~i1{j%&g7%jFVTJ@#;aVFv>YQLQ;pMNB3xFpu~ z?^ADoms60Y!(CGCxk+^BHHYTtZss`RixQ0HTYTbObJgXM89nVg>f{?rTrEN-o8WzBc<0#D zNxG^%XkKOz(hKd2w=ZXSh3kDOWLIfC5@S{{7SE9x8aJFt7&%E zqI|#b(sd!7a?F3_PloAvQ?>iXpyAKhmNwV~jO^W;33cqa5e;Gmj?F{3SPWi+ciGN4!;CP`4%b z8+H;9(;V&{ZkMG~qPK;={tMdWGdCWHDgXW5{}5RIr(NN{pTEI9E4EV%gDUOsILGz< zJSPOOD99Mz6CLF%XGgs*JZ+1sH1=3r=F2t|1gCKN_$R}b2dHGm)%d^=sRvQWES$0I zmC_J~2GYkuZvIaOhIHLssB0@@`NZVBc`PP#R8jtQ{f5q74vSyO?=))+k)yzjcPn3> z@l(}Y<6vQYCHeLN*>!;}txU@~c|>q#l_AngC+1^DH;<`0+HlKkupdD<-;W^saaVZ| zL*z&3Mx^A@SVXRTeVEFLofbmBfZq?4!dT%NLk9<;aAAL-K$k-(Z++pGg-NL>tu2zu|lS zb^6YQXB+k4+spK$IKX8V13d4N2xKJ(RmR0wV(&Q4SxLSkQqRLnhM49*c3r2F$a!f6 zQM+8*TOGoBKifZ-m?j9H^LwD2Q1z5Q;VxdG)i`6f_4B!vCc)j3wshyw?cw$w_k27B z2fiFH3DakmLhbMEYvDuhA8l0~S{m!@icCnq(uykR_ONox_XOK~OL0pB8zH*qIYql~ z`2zVCi23G@7v>g(16darx^``vThx`=a&;_k4WF86-s69`WTZk4)6n@1S78DU=Zd?& zPIJrYiM_;&O5N`zO8bnG5UO{E^LihwDRt9#LS^(Tq$plEqs7EoY5wa^vR$UFx``A9i|kxZcbB<5ug}bK0s^5E9yK$KBRjhv zh&xB?5`WFao94~36W-rADVw30{wI33&jekja44w@<(9Uu7gt-)nZ>nkZIPKD(pdVP zRywo>^vIzt(+bJkDlcr%?-kQ+Kh7|AR>9jD4?jG?SpQ;|K8V!(KH)8~;6!(Xixk7@ zseIzjkk?@@DvTY?rOyHDf|(>>qD@CyR10arjrML(K2Fhou-)RU)kRWOJ0uY8G|AUM zaCizN6c;!JX@`H*Gu`ECDbzI}A>YEb8ege^ihlRWpvRVnpF(+bHVlHv%G($cApX{ZheMZcNoW{c5wYVA)`4G$g55sPMm4Ee26DO zFq0-1D7>fU81;!7=dD3;aU?(9o1cC3cAGIDH7nc{0J8#*WV5G0q+qOSHI)eAh!|t> zRbeA&JmdLmbgBU~8?EV*QqEaKDFJHTxF_%5y|oo7EyA-^<5qO?Ab@GO7&~`4+o*^z zzI6sYw#1{~Y;f!149hi?l$w+LVRE}uxuBDnQ&748TbnJ#I#s^AazoWQl{Rpq~=@=i`(g79?cY_x^ClI8%I-ks9MLMZpq8YD^;fB zv+ppgq)LbTRyV|TsV2T#12}%bRhgieCgAq_>h4)7Q~2_YGFN`ve_j(U_=Jg}u}%A)3F(z-Kh^6qq3=#vuc;8n8&yjOF1Ej~ zBrKX-D4-ehuL~Iz(dw&Lq$^A7k+N55R>qNnb zzpVJ_Qn5RTfBo&Hlw{$g3AiVS`~@Kg?=ei*5QYd|Tbzz*qt4uCN_>7oA?=NKz^9X! z&{wEq1bMXNQGk+Pdgp+aNW>fR7vG}K!-R|iCwsub0a|++%?g}?akueJVAjo7WLq4+ zJ`ZD2K5AZ`?oBx8)f0*Nm7E-7{nN((i8 z-i93?gt&B_9=S(l)<=8r~QfZoW`LttwT$yR*A6JtKzQ@yN(Es%G(Fn z(DF;gDn={y=O524w;Vg=ei*a%AdZ<^SdP|q*6>?7f?58)*P^AVqTGfgBv`WwX`5rN zpH5l@FNP8ntR?AV({EPGOq5zUR)p6ZH!Rvt_}ZE`5?|OYI#0STC&p~OVLE!k{30~EYA*L&fK3# zTxh}LUm|+=ZitVwV(@!L*mz3$NqA(0j`6@k-n`Lo=uN@R)@IH3z0PxJf+4WQHsw-v zJ)U$dKTNw`=Oe>sh+Q5*ZV>Q89PdDY^NyQj9n$^~uR_2ff8tfE0GLkz7;)PydpA!y zYZqI=r0Jcq$b1HJnY_h0f}r27-9$an(UGEd-}$?r^6J0OE)BLAs9!8X&hN3aw8Paz zqMj3b5sq`L2G`hU;R9I9)op7z;Y_){_p>1bjTx1uduRPwqfbh=(VG3(vtAJrCXlZ$ z;7+{bc2@;nw?K?Vxlxp3jYiG<$Ft@(Q3beRGLc9%l5IUSGHT`QMVizXSB^ez@lF&8AQ^ z4#5t!;{ztoOhw(P!%d!vF@7m5itFM?fq|Fe#_Lxg^|_xiSk)pJmjVu^LMNxUa`b8M zV@xICY`U)$?5a zt|`6%{sD~j4hBKRE&2IdZZx08E#^Yq6_P5s_QXX1MTwJeqJ`7pStMI=I}s^G2T3dD`{S^z3wgvE$6%iO_#y$LVrXTmVcABRo{hbhlJ z8EFJZzMR&gxKP=?%gUdbWc#khLoky#mG5f9OfJVz1s~4I@a=dX!Fi|LVSugf>@wHd(zXq0V{hAIY1Ll@lvBwM_VD)fv+H&*5*0x2DjvtIdlj}qSS5t9RjbI(#3TIkpf|mniV8H?(X8UUM zU!^LNF!ej5#=a|oA)MREwoX8Ekf7~BCfgt^-vWp5^1>k3X8v)sda2~{$s274W9e)i z+-wOYW)`AD=$pVHPe-cfgf&NQ+Y_(d5we-;Oi1e3+eAohes&w5mlvbV0H>vhd2KB4 zHq77W)Y4#=24@FNZD=Adt6b+pVachI~5sbe$mAn5oD|tiChW1*U38ZLcspoz_6`eZ6-&%(=KgAba?$aj|#7y z&A6+_;8rma!jBsZPPU$8 zn>+{Px7vS&kQ8u8xfYd~2>JZC!m%3Z($;-<^hvdvMNFB(k6A~ickpg0yYc?}PCSXS zM?d*kzA7{yE~%}F_V|vpP&H$7R^|*Zs}79HVKkH(#5IA(aWJT<}Q% zkAy2dHJd|DRg*JDVAB6$nXdB`rEQpFd0}Z^Ocg85s2>vk1_&V+U!4AbfA{~L#Nw{Z z^3U7__=&yDmuw0wi2-TmzatlV?rKIbU=r|7m5vVS)(d^3^PKC2J{5C!HoAivb|LbM zvtmi1{HV*1pY(F}M*Yau-5H8{8Pu5L`p;n`DUp;jzlg+!t==>zPjp+2#GW+t&49(l4KNr9Xo=FgPdKTWQ7(L+fmGP1tyog+6j5p>4~l|{`u z)i(hC002NzDf?d@K0l2PDe{+lod1f8qVvl?SrYckhrS!fLaqcO$;tebfZD_dTL{zQ zz}LNDU9ouqffxzZy>Ue8Nxe!Rr?~CQ zjAwIuZOyq5#Wogq%Vt;yDH7BJ$&`K;51!5FN?J06FqIX$y>+#1+wRv9fqTUU%eRRZ zo+IRa-i6j5$%&#gtZJ+aZbL~G-2h|BhYU}r?Y_^Qic9@Y>=V*=2-D4xj@9<}egwih zO*hbHq%%q$C?jE>sX9-WsDmJR8NZDQ`|5?7mq2HZex%Wy9FJXOL+Trmgwy_}{7>Qc z#>~^>dfk$GAJ02gvE0TCq|o{rU8Tb^J#(KiR+@?7!P3rEY_f%kp>J`?iD{N1E&!Y$ zbmofHAxK=st*pyx_$2{t^d4fVZa&I$?kTMqn*;fLUf-Dm%%qgq?6i8KWww^pV#90v zk0(NCu>b6jDWU^+l5WEF7M&B8ruLc)9;e-PG~!jq^IFaagiiD!vmOE9;K=w;{rvnM z4WnVxtM;42F^+219}MM;qO3~a_OLAhDdk;7^knB6iga*XU{yPyrP9`-TT#tC`pTkq zFObAfb^8k+t8N6+StI>bH=UoQ68E-F1*^yHo#7*6^YD-pggZKGVbz*gg`cJR2mID{ z<@P6goQ8FO@jW1V=;!+wS*BvCLu7QpN8lLhn7nQCYE9vJK^)IPdC}gFh&JO~cehM; zo?fl>*D0{TaCl+dxTTMzbUke}7QtvrjM**5^SESX~xfe}HO-{>eGbVY~FnEv07Wa1d zoAHxWe)E*oT9N0-%$Z2GdVLE_+Z5*5k$jT!>lN#GcEgz{PqeJR^rKPU5lH5QU zI1+jbH_Pl_MaZB4(Vu(oibiTnR`v6g%w{NzGgXTu5M1Nh(vF6sGWzfHh69C>ZKLER z+j+V=cNm!VcHR|3mg9zses*$vb(*^uBO&BANT$w`B;i7=f`-wBMN`RA@Z z-P)ez#RG)|*DPndh?J$ev`^0>502{l;|(+CuIYMAJPcJK5M)~?6b^mC3GAzYfv~!d zeQ`Go9uB@K=gjd0Wj?QeltM&;SV5-fs_ENm}jTEE+E#z66zt=0=?AKX^H72100&RvmW^)K;gmoO_lO&;STri|jg@QTp| zzV@u)V+5W?h4xsK+5qw*wZH0_o0)HakIn8YK?}5V6vSiq))bRWDy^G%2G$E}xekDjQhMzXk9;NEiYsg#}lEN+v%x_8Z`E&%SmK|cWm zQrZ`BZ@YOQ9I{xvDfw^zlLV+9UE*8vhXiO0s|G-DEm2C&#&;l0W+v424q^hx!Z!z73rK*8>rCjm4)Ko?aY&pT1MAa>v*Jg1A z2g}uWZNc?pT@*R3dW@RV-s}?$ci<8Bn(N^w?c@T7VRVC7p_LG8lTZ175RMu9_Ag!4 zdBg+zaz3X>%ZOuQ@Scq)$ClHW#9_7+;k|^7++hA5$;UKTOt@^<-goImrg7D~3Ea&n zJ8}$YG7x^1T|m~+6=?nHa=+C(PeiVoviftywhf+0Pi@QCKGc3ZK+!dTk?=bYy}tfC z4?SXI6hKIs9&XcC@~$Ebo2^Nazg2JHyB(`+lL_hm*`qcd3PNzK{nPL4lpllg&n)#R zy%8Ys>BaHqDL8J!Y9A=(4{JbL4xKVzIAo+$fkP%`s!JSJN>T7N=?K+?PZ$r64g3Znj17(G|K883=Zsx z9Ofs=fm)aQy$9T5tGdWN_agnK#Cdr;XkntdfBF6rv32=Vuv)XQ3Hq!*)y>m#G{F9i z$GP+zVx@a7;c1Z}kbS;T*qqwM>p2vf-mn+ikXojm7+WL2qYW@D0uKAN22UG5dJnu5 zz+)o+rAW!DLZLMFq41*WXvt#Z&W%izv-YO{dDg6ZMV~lX2Adt-_J}?2HaZ*<;p$e{HAb`MwF14j+ONTYW51MMF9|UYbMi{HRB$J8BU>xN zm*P@Euvb{i)d5SaK5EuAZ3ip43@Hxu&jHt%35Me^XIHyj19(#Hf-c-TvcKFq&3$^A zfq;>l8U*CH7gSD)>!>U;uL)s5Z z@(WXtWX!=2>+8PJF4>5S8ho9G0BDF1f0r}HYYQ!g$1Z{?O~+<3Wqj673>=+1IdR_t zwXTK4A0E^WqMEP)quB7{R-4@2F_t@6xp{e_(|t3#Ab`2sJEdBMx_N%Giw=rn;{E=N+7 zBK4Y+`?ymvZ3O?Y7xHNV@5o`iVVByV0qF}`G#1|kFZ<47R69xKuXYmu5Y_$4UvOAg zr+?cAUbDK1E_IA?JlE7h0ItMi^Sz=2GB3+nJ(`t-4;B zlo#H(s_CJo8aq_h7YkFVTVhPs0xR+BmYYjyBhfX+K&gFbJ{$+vH&}>S0!N~JjKnAh z-a+kB@-RkV%k7$7xUA9BY;)4^991wtKcwF4W!V;wQdF1@q5b|eJ12!{*ItE|ro6ky zY<(Q`Ja1;wW#Ur8_=NP5}1Q%>_2Y)6vhA*X@LL?2cBT zYY`n^0be){@(gw%{Gqv?LSo=Bw#4IWm77q2~rAb6QTtcMXW!fN8`U)EtfbL z*#z#b5=O~MG`CwA=MmmA4#*Yw72>MGjp{6q||SIH~E zmX3LSfq(J!)J9itjy-kD=g5{*npEUGR#Ev-i$AbWw|8Wfyry<%*fO`zOtqWdpRwst zZyx@VB+@*2&<#s{f6(IMk6){-1o_#ec{!BfI0g=5Z~k?7eAF7-T19Vs)b+^Xl64&S z?Fyv)?Z#r?_4(s0#p~+_xLT8~MmILDQ@-}8;AWEkV>qreo}igk`hJKzC`iw}b8x!x z`E78Owa)>rTQnTMdAT~=gvbG0?y{zT3K{)m=x}50$Q>jd4fn%1{G7YOh_gWA0g+Xx z|K@5=@&y{Y|MNi(dYv*E0VdzGyl;B$_^&;B`Q~4J_nwgMSg-imSy{6;q()zruNxQm z?^I{+tIBf&pW7b=%O1U|XFy#GCoHwCs|riSp#O=J-rW&B-|yZqV+<(KsQ5n5e)0Gn z2{;W2vb28ei!Z^9Dc5l-!ZbRM!!%?y*A|enGg(PB+>- z#_`1N&}7ds2>i7;Wcx_IjR0IB1*r9-z$82EqSjj!r@vfRQRN zkRA~O;A&}~j_){ptby%)0%NC0ND_zu_IWC@X$DwynRL1@(hB(WwR^rDi_H4Uv)r>N5U77uUEi;K*QGR?KNdAoGB z$MNEi$a){9DFe2%*0njJ52FIAzyh^nc@{zq8H|Nlya^6Wce-K|%Y9p=>MCntFtQmD zJM9^y^e?LVvqvp`2}f(}<&$Su^fQmN@wCP{erkU_I!bynn_v1r1q9{B{{#d%Zad!w zqZ?kY;kdoj8dGA9IzH{>viNPzp+1?qSCQvOMNoGy^xkz&$!hbs%WPbYJIibDHMGp) zxFl9rp%M?H(x_%go!!K1uoJ~o!cmf1vulB>Y7uD$t>Kf`CL9N5D@1FwNE3x;5|nQD zm^fy^&0-C5bCTThK<)eF!FpXhxegYfV)M7|N zDX)M}6`)p?$O5w=MHb1`e-%U&GwEYI|_b~HP2hEFOF zNpP5D68Jh6KnK#hL;ldX2W~ayo<8Iq-f3wFO#h-fABaB8lgjMPxC2>1&aGT3pGsCihn%_-44b6X zteo~sZZ5eT#j&wTmGGMWYH{3rbf3lfMfXNL^fEWL6Af}>EH8oSoE!FkGMy7O0(8%? zJ<<{8UK@=RwHg=*>YlpIqX!SsU2Ey;+=2g;gAR+I3rCTkAbDqPCe z1yT-bg--2;$L=%$Fx%*h2CPfW-mbyFHiD%tc<#0ZQV~KO?9qz_(1OZJonB?)F&*@! zCQu3T#^!v?`~4CC$#75f9V=hf^Xcqbkl3D=ZMP^s7#KJvw8dq|4*S^$Oua=GWU^c}4B4q%bSD+$ycm zU4(@FGlV8T9^Ed~ot{Tv&`bi9>+N6$FIcyK$a?giZZg*@NltIxYN3+FpHaLFJuxgP-`dKEh&9hDhpPhl2)rJ+X>EYA30*i$Ww%5Q_}#t6eODqm z#>m8f8&`gOzb>Eec*o!8PwmF9QIxA7Y$AL;O&)89sC$MTt{2g^*VM%9F^+p9tS^0MZwSP|#vcV!q*@i)7VGrrf0$hyZp}*uhzL70$o-c`p=5qRRw z1PiXwUa0CaaC5^hJHab&^o~PW`6Oe1;A?T0R8DUZq3+D7KkQegU(iQ15>Y+~iX_OK zKTVqq9BU6EsmS^8;e`#Hqq+MXNrfro)lSes9D8H0XDGt-nfjNRRb=^A3=mtltBJz# zQ65OgC^rz5BY2p^wY^Ke$qtyMI7$-~X?ic_qr$X*lsl>Q+GtiXiF@p5vz?)0bmnI2 zCugX}InAMV+w$U`@|9|iF>|$f=b-=%J*$f9PG|YHg6O7_#7$`Tk-+{B1@b?iR&Ogy zXj_Q98qO}NKZL7r)eP*Wm-h@ogUF-ixscbYAv66}@HSwSN0P=lb)@L8s_7;U_CGRd z+HiG;8smO<@I3hHReJyuck-#-DmoP{$~wG~I{xyT37p&$bN|U86^Jl$J$BfpmhEds z>RDbI?71yNY+2*G(HD*`-^HM+d5G3ip45R!{?2h@j~)R3Olj#d#}(H5eu? z$H!51-snA7!~J&She70Cv(N@+pj*m6DHN~|B0%wn?j})J&(-Tj%lh56WrKPB%G~XbiVXwKBJV@*quYAJj5t`OYWD}YA^Vhr|a;hN( z094@JcNO)lpuh$x{Upm_cukFHdw%ydtcb9dKBYe%1~f+mvu78Ii`CI%Qag~to~8%S zi}vl52ny`MKX=Oh@T5Vl2SogUHxJ59`k8ma#ra41u}2l7jfH=c#X8M`v1a8%-(0Jc zzX!di$Xcy|CR@FHDKH9Z^jc7s)CYW6MHr_zI@}(n4lf&bD{!P%5s2aZWlgiDP-M55 z|1irvw%cm!sw43|QS7Bfzb(k2`?7G~nIFU?E4)!$9V=O<4|%e)^~=kjuNCr~0!Z@* zp#_~$dH@el49xmvh-2igH3-^QksvD}%oXa8sS!I1o<_i52e({@c$?h93kj0w?T1lU z2+RA7Qwcv3R zp;QM)AR+)QibS0?l0oo4on`+QVSqLIn20u&8}G8HYe*mAqvjYocjb*C5TZ|w9lMDC zS*~QE$^Rq%SITy;v7~yN9Z^K41Aj)tUa?WgUAvpYCfj5KOxO=j)>)n)gCb41uV*gm3M;2{j_}P>1iji()5^F7YD>cm@ zhRfM=73@Odt5~W@4Q1@Z&F4B+ITlTb1}pc`D@GfmE%tVUh)Qn12~gAC`NKO2W7Z$U#%y&dgGghjN=k3l zd&1_I?j^^YDf+c$qyN6o?l8lHSiI3^v(M-E zuWwG-Mx6J_TBSbxQt@_!YimeXyJ-`X)2q|i!)LL+P~Ja*!?I28FZnuJ-?UKruWyzR z)=NW{yjaHq;0m2<1}v5OPtTfV%5H55Oy@SpH-PG73LmKdeA4aUa*sCY%e)}-bLCk_ zYVuvi=YSgkHKu2IucXe(lsQMkM*RbG)MEL83G8G~@z5~svUb=s>8D{qg@GGf{l%lx_eJ`TKvWmx}K#dXWwNE zvHhj05#O+cLysjW^r+1P1q@YGJhmAOp$`(e$;TXhK)->;Z&ZOB8PXDPT}b6WE5#!7 zI^2Uk2JzbY&Vp$c(v!F%ltP)hn)f`wD^pi^W9TcixfSsO&@jRMVy-z~l7nHCs3be= zy)zr=ASmX7%W{?qq8J49Jlm3fmY&%XsHtlPHFX`H!Ofz(HEaZjvp8cDz+tMj_5m4G4x|mVJqK@jUh=_O<*_ zE|B|vOzf)*uw_lSwvVBMMY;(w11QPc!f)4agDAqC*Rldu#I)8eCcgReaXNRGuQnTO z(~0t2I-zAX`RL_XEwQ4EM;apn8M@=KQX&R6mhe$5{RYhtrrhGJGx(8?ly9rXAjxnq z`;4SEkd<_hKD`4A%V)Zd0ElV*kylV~&?DF15n3x|JfOa0n9gEzIMZl~Q67@|wYB}( zGvh2UTLwt#KnM6A{WNUStycy)%%N@icNA*C7>mVZWqI*hFg25stg^5rE!0($V2-Xv z3o^>)>WLC$F`B#g1ryN2A*+@lgKb`4SjMSbElJq7Tj?*i=-KbV7X4?6&F)t>mVjTB zHk=;RPP@R0LfGbdO*UD()95Y(5Gs!la@dy>-S)qP09lPYyakZeV&35;s`>!n&|0$A z)OQoJxdA^zk)&)ofUJiM{;Fu`AWE(RSZ|%X~PY56C0niq{HT(+%Dq?r;a!JBp#<3 zIn2qkO_}7JW}Y#z9-rn)%ZtGW6V1niI@1JXUq}^b1E8)<;@Z1M^_3wAr<3KY=bj{j zxnc)~;)sDcMJvAH#%c}*(nTe)RsTpFu7bS_s5W?n-8Qtae@E)-8P(etbNqyz2=10?;iSH8V13;5_3eN$b;Pl+Yj- zQS0-`qi;>*c{%6O)_3i`*4_5uJST7d*)krYY&uXGl7^JLROtno;wXaY3%K$Ef?VS@h@h2C|&!5mkI=CnVcBm^wgX3IO zovRJ!u{=7iSOkP6-SZoL;>Hbm0iIOiu@wcV7dqEDHN^hV(`_(6Qa;7}kgm08>Jj#IXjg_wvp11BHuCWPcwrsb~J+bgm zW2L#_75|#%KrSj@f&nDj~6_RY%+^N=*>CA)=#fo=d-IPE(c*!QhQGmDQ2iD^q z_9|U=d~Y#9K_JfTNDFJoiHLoHL{aH7I!P?wILTChRh1jKJ_SP{z@smQy?`@^oTmum zH=pcwwcHw7xqBf?cIU>9w4-DxUX)|BxiLNjrdNGf5E!pmE|{efqCQb=($W!RxZv(C zDY1BSl8mbZo_RZFt(yZ}z-AF94ujS5QNbdmTk56j-0)EYO|JE41J09=3Iq3<-o*!X z>uH=~Iq-;l-<(i37^MUtZ_Uc=QmQ76Q2RcoD(vl;YXhZN3-c;!yFKEgJNrUBAyBsM zVtzxSeJE$NT=RQzic5pfnnAhb90jTXIz%4^z4z2yY0Lf2?elQE_i)&62-PEo5YlkG zLe*0n&&#+;IRTHkY8zP#?pJvXj;r0}O|GB1X1A^vN6W=!|1)MPu&9wjnM_J^-@K)< ziB#t=&i=DU1y(C^fFaW_j*6Xuo=uLc(jpjoa&^atFU48yH4~i3v;?h_+*=L$z8REu zv}y*lSSI~Ro{lFP;Dk01NvY9bz#(YtE%@R1297_b(R#FdO_~EYx4!d*zOYce1MIf~ z%$KdP(;~)OB>eGWm@+M8%9>)Xs8#pIno@<{tQe7qlhx=nmNoxlwpcrg1Vl9)W+qg~ zA@yhVJhBI*5GNl_2OOh*6Az;;zNFfS`dVVdv-qEB%<)RA1oObWE5##IPW`*C+=iPwZx zog(^TltL7ou!7-lHmDXdEyke5w{fA?YrrE~8+wW5rZ1e_Vlt#5w-NDQN=)zOg= zRVPnqRqj>CbU+e|p|RCtA~NKKajAjvP7yK!Y!v|sP-}f4Qkva%guZyjoEO;qOfCv3 zdB|KsvyhnbYr)n_fTCddOE$Uon+ow#aLpI{pn8Qj4EW3aXbeoR)oqACunkq$=m>{| zTc>m6MRI^*3Hj8W^g*uhKSqK&G_hGrPk?szfy+tvs5*F9iSoCHU?#;V1*_aS@DhhQx zJZ$?Qy>%7UC=B=)hVbkV-&nmcuqn(#pBB4zc>3s`s1WGoVmt-8%i$UfVZMNzo89)Z zbmeve30oSI!cDWl00WH-U(Y(Sr=ro`x=>2XyV=r!r!}<{du(8M3Q5k!J8JdFx-fHl zIzP1TTZNCcsMntS-mI~=S>P-TjJsb7 za`P@!Pll;OJ+#AiI*^5c?jZsyxdaozNg**O2Y)m^*C=q>AwZr72C>vn_b`WF@$|(+ z@b}tDswfJ_eogWx#;vK+;nxg?s_;LjPKbsXqwiWab|N!wUqfi~hp#g$cQ^a5mgQpv zUem@a85kGxTO*l|+SJ(Yf8N?R2z{o$4eXW{5CjF0nzsT`NT}9^`xz*T*%I4m#7g6pBm^u<+H4>5ExU%O0n@(C3&qEjf zOSq6NaJLD{Zm;l+hQ4nEG!OjN4r|wX3R6VNtX{r<^ziuFW_g$en*wpWIflYl4B8})%7wtZhoSkV4pakY_T|7I6os60WjM&qPTcXofhbrJp5F%Ez9T( z_emW!WbUk_Fkn2m&paR+goRh%N#ZSJhB}d;WHT6cE5(H2OgtVx@t`!s-BNZ%0YrW# z3OoZ-ZgR8slilFZRTCavY_q5}QU8*fWabnuGl5^izaBP8RA#T}|7JVhXjPC}53wX$ zv7EUO7~NM*h;n<-u`k$5f)FVa|8?2K ztZ~`IJa)_C%UAOlcux1A^Vf;Y= zmiTyM$1J6>TO^0cSHx$z?NS?T1+K5gX`WsUi09JodBWWVTSeu>gSrCLy4Ne&MgI>*9hV$@7ZVb~Q3v`J~3@-LXG+guK zRSytOqwayjxF8d(9pxjutu`(wrNI4w$ql8MNP5hBQc@y=`wY6^$4XUM3V1X>AFnRo z`QzTaWkZ&Y8d}XI8}O1__zQNsKK;M69(k4EE2i}pFLW&QabLOU5FL+LT5Ef%Qk-|p zmTytnzx#Aa4H^HXAdDQJ<-RV{@zaoYf&%k=gsr$ULJ6I|(m66b$cRJZR z3UVV+oHRUfN7ENp6_l0R!q7cm-p#evRT?v35$$n#3{>>5b(T6(#uDci^+%*|_i+ah zYE1txOXt6rI~)H5nwe9MDlvYx21-y@ZM*9-7Zc`LX%1Gdor_V>WchJa9%$jY?r;#* zVm4Lj_O+9#vUP6KD3C=S8hB&Z^nw_z>zL1Af{8UaUt<3q=>#a;={J1=%L=gDJPz(7 zv-rKW{|RJQ>jTC6tz|mAW0n%$M|bP^ufy>J3-YFPQlQqA51XdkM4LX> znIxlkc(^6fQ9mkSeN7kMIIkm}g6;0)opqskoUw-liS{pU}qE(o<_ThGZu>KD=R?KJnpNmX9+T8t?cqNGvM(NNT= zP>sTy#F@fc7V;QbontKzYpEypZ{){4s13?n^dhXP&Wd4`;LwM?9*Q?AhOfls6G3km zY`M>RAyeUAUHYJ*@P+Y=wpa zzWq5*@ZAdfL z?TjgVIra7E9tNL}6}qq(JR<5N9mH_7_R z$4g!yRL%%~BUA)d`b$ywP_{R*juLD9BDVuJrXHlNQ^B2umD1ik-z1a5>93s|3ZjX} z+Ttsi3rESS0)iJMz-&vuX{8-VI`Uu5Fz#+B1s3(iW$<^|Fj%@@e8GtRiC@{VS9?ya zNr0RBe#QEmEG-G})%lf#9cu~)%tc(V)wslfEJ^23qL5EA_|G`BghV(a>8^FC)=#aI zlE8n=p(7#16d8KDlrqFR;a(;fnm8(-Z4}l3x{{z5D2|gTS{GaGzv-*%qU>iTH6~G; zbKs_KblLq9X{{g$JNK*SX-8n{T%nn~*Oe5YqK4InjnZ6CbNw&tZ{aIQe7hIK@mME& zS*jgv=@Egf9}lw%Pn)n;brt7XnQe_l~{YkJgcYpE*4 zS@t*D=sd*L8gDe4@Xnd~xSvG4hXVd6*LvFEjdpi7n{i+r)1nT8f$N3gx!k08Lj3bT zpHi+9VNsK(P-o&h9DI#)CR{%Wkb`=K!df&r|51LsL@$8+s$5|a3S(BxZLJegIPG}( ztX0El`7-l5BV2RQoG{mRI2E)lKIZ+M#$GGmC+?V zMuEa}wLpsdngzVE@QWBzZ+yzPN@s~$YqR~U%1MQwh~!@r2RCoIU&SgDvPQVr%o#mG zKAGRY*sCkR3&T;X^CN5YS2e3fPJD>` z6G-bxR=p2O17ZwX3X*TGC^4d*t50!cm1!^N`j?@2=3zYDA<1xT3*Lv+_>Q3R?=jWP-LE|O^8(vr3aAAI zAsxpm4oebkBCSLfe(%AqeW*rG6KvYy$kO52YIho` z-hlQP`|8Z6*R%xKSGAGf5Pk~le!j->$6lGVCBr#76WPfxxZr}e5{g}|af7uf6Danq z5sE!)(osX}>=C8NbcwQKs?d3`!-puP*83GQ-^>A&HkPL;kVN6Uduf)<{H&^Ye7M!M zYHUGDAOyAOScuUaNu8_t#3_7yx1B3@lQG-B50&>WCjtE;pnCLL*|Ar_Qd>yw?Lqu} z#u9Wpys!{Ho7durzhsTW$GMT&>TcuE zIyY^A#@uLub%|+PPj(5An|vJYFgxE^GY-Ly977k3%_bVC>+_@pp{OC9LVd;cgYqMC z^GS9khtOt3``a!bHaopRm%&btzQwYXI)>!MosxsoJx%@1W67g`M4t)oBr>O?Qhzapd}P{THG(yS}4c#M^_p4Y6xm$KZ@Ge z2cWr}$U6HdCCHtwLkEI#;@vbu#Bz%*xL?-{I=leZDWf8h`jzWs5(0x(A*NAsBYiO2 zzTsl2lTIT3MfY*(3cu$THo-38Nx`NI0-d(o!$KV!&-Nuy<9E zv{9N7SOz>M-nHd$D1nEZIG(XO#n^SH?iE>$-euRapVoKscgrY`&uQz<*rGv(m-4`J zDM>FxHmAfnRMvgoE-$xjS&0|8HO0wn3NdrNWf+*OmM%4Towbish76Ged)*yA!l1B1 z1D*`brvBCQA6wJbuN!4)&n*5wqi388q|fyeF1g9U6S z?5JK1B@ge-$|ld))ym>2?7w(kE&&wJ`@&kxP6wyfYO+rN3k8-ro~(J-0$wLHl*8J? zrDyXPZNWvj8#tcxc_V%{?A&hcp#NNf6?-I>*v>j%^OCCaQnHGIXc8+W1bSq5j?$o} z4+ek{));H^cu04IFag+>(Hes~PdJGYcJ6!%>~@4@s7smEk2htRZpuV_D!%ZA1a)&D z*`$GUyK+5yr>Fh}i5N7?=Eb?^Xmn#(1y(!fzmj_APq6Q~4`{l%yyNaQuOiOV(OGt+ z^*ish#^OqD>GxVcP>_(1*u(79b6jhhjxB}fT{lf9LlG4^d;h&IL+IcwpJn=X2dw}I z@Xq(8gk~w-)nGQjuLLn~y!`PuE4)kENt^=nTHhoewb+;@Y->oGA8+)3|I@e2m>8$=>d4^a zB=tXCQU8X}n}SfEnKP*V5Ms79fbU@$aKR{00A_kvf@33H={le|a&y9WXvA6P?khWH zwc^AI*yuU;lISo0GxBdg)jNk#&- zGR1f}k&CQ>&(O$$yJL4|W7Z_pD&(qCHM|&WkZ3yvWs?f^^4j}kY&NNZsyJZd0G)>V zXU-GQyAR&qz@@&hiUYbkwbkd8%$xV_wwX`%f!I#G&;YZPodRH%ny))aHBm2RgExjr zXdSz=SVDD7ZweNw035%w2l>83?&f6@P<@h}yeo+zWSo}|C=^H!|8(sqq$P|fF{Cd; zK41mJKj9LQ!uf~OU4Kp$&ECu216MnAZwvl4d+=e3U+A|&wJ>Xv|5CD9ZXzYtda3KI zKl!aLF?C`X)sVdI=S{6Ivo0TpafZX(-*dbp=O5hW*tI@*>XF-(mrmX*EHV-C<@7J1 zDHrF}oNN@a58YC-4+3N1Y)ORLG-v5ANvlFRnPAv#Y*7dxY7mnXDQ^ItR{4Et1VXZ{5I`&=f@KBO@tu1ZGPtTL9>S^r}etje=e~$ z(E+P};0s&*-ntwI26TDqi1yU*kd+*%V+8`j2yU&Z_52EvSy8FMCB>$WcisCrpX-Gt z2kAHgs<>$o4PZ>MK5Q?s+MTece8oUPl$K)^$-w@?lf??J{l>+6Mt z55+rRDe*THWY_UsK%%-qkeB@RH)H(5Yu(F*9f9B-1kT`fE@D(s1m44?_L&x!`Y^jN z>)&xjn`J!sD9u7p{r^{5(ZIIz>c906LHB=np-kU_Ccm{1FAKZu|D}cC!Nb&dlM_m4 zw|CW{edhu zR0we20Rh5O3blROrI{%*lrx1tGG|?EvKH;wZUF~DF9-f{j}cfdi}3U@ZG*QKLJXCF zq;Zrwzlze2W+W@}+@D0xJ5J>UpG?5K7B)_-N_A$5j*kEkNv){T_q}{fQys3D^p^n{@@SM0mSN& zC;5|M_BMfHHoiSobW!<7of(O&%m8nGIz%>a-X(nKE=rED-gI%=D*P4|UM*bfLsXv1 zSu$R8gpyUb54B_6__ZPhem)r$C`7-|GzKloQ|q$1)a64RwL|6gEGaz7pLtfyTEquT zihK(OFS-u_b1j97AWMz>lb`C(BmQUy|O1?>xb2Pk(L1?%Y089o? zz1BWFNVIwWgNitbe2uN6zkX07W;?9uB%x0$n70-=8|-Fc|7IZP&ewg+A#%# zNH`Fa&@)I9yWoM5^C5Msm&)z6>!`tjaAD&T60CIy=P1CeV zGm$4_T?bVHN1Uzh-+y^-83F#V6D7W6{g`~GEiFlP7}J`cm9~qeR;kLuP0oScP0m4W zveMXq!AMn5YgL`9~+Xp?3g3a=^HQ_!QS(){3%!Aa*2jgT)Gw)0ITB_Q00q84M-$M z#GRS*S*skTz%V?xE~9gS;oghV>c4_K?b<)crpPAXi98LHD&0=$G0|NT?>R}|?zY|# zln|?2xZ>xy59{fbd)L%VNhZSa1zj2iuqCi&BN;*}u_x#(nP8yOiOA^Gyj7vfc4PnQ z0kip%l)PQl=H_Ub;tBqUAm-P*_ z8~Zk(jYHy8VIH@+`23B=Fk@HhigqJUBPA95AtN-NpWq`$h`T^Lu@gh?vh|#u^4v~M zM!nDRR!{Fv#*5H{1(`q&>cXrmrDx{CYS+EXFG??k{t7W{@4|=RBJZ7WxN#!cI*?CN zD7G6AMZ1`H8uC$SuW+iLvnMD9xcjn*J?Ky>y&a?A^|#8^sNZ7n%GXT5yJ>ZATc#fI=Au21t}W2E^&i$lp?qSZPL6N*=ZbUbxh zHOfTlR4VB9E=_N{2sUnU6fE@jrN7Ea=sc+)_A1k*NoHJbW zfjk98r*V(+j1G)?HLv5P^e{*Yp=L4N^0=OB0j{U=CnZJJ*T+$DC_G@ZY9nC3WG+N* z-0sR=aZC=n-n}E}dd5AUF47=R-_tdr(LhcqpeVhu$sOm^szX)HAMuUpogi#n{h?li zVa%J(sZ6}-le14~i=7OMK4i9FQ;|%wG+hi?YOAI#+#kwE9pB=s#P-)sr#+7lffR-I z`;<*h`mz)~q*1wO6-6v|Wlf*M@fx{zYvzo~h4SVFD^IrOC^Fq1^5cIJo+&)lVKGOM z@MceUfjET|YKz$6FhZ8{3>yqIR965`zI9*pi)P{-GnmrL6p$jbfS!$7?C z-k3pN_^M$?KGnAba2$G-NEy-I_X@X;n(SfHqs`cWu#focK~3>}n@-8$x$mdtpU%CT zNN>NbcoFmAUarSpepcG(tiSVNUI79FMq~82okaizpAZ9f_%UHUep`>QvS$Vq2 znc62~q+Y|sIu&27bkjl?sNwk^_$;yu*J>nk9JN)o)Z6Dy4Lq`5rP~8i7fRA(<1JlV zq3-??<|9Y55_7NugNMJ!$cdT1ob|B$QPd=y+s3ELH?v~r+#a+wlu~qOX9enF9vd03 z!>y+dm$s|6zVHvRH=EeGf=vp4&W*1so@S@`^gVXeV1yF;&n@5mOo83w&=jYjXLKwd zsvdV8+7NUCN#~UVGnG#mZH??SEVC_?gWX?6=}GH$PaiIeAwQVknUQg75jX#)DA*-o zM36k0CECQ>Ce8bKXN8I$YL<$MRGk+kU4s6285LhuBGi7ebzd%@l0!BATLgLt|Wl}B2 zGJX6_EJI)qO&TDe)*|eWu`5CoW#eSV!HqzY4x`oMqaN4|nhp+oaYsqw3-X3-5b2WI zpQgIQ&!)c}aWAlje^dGI{-*L@UAuI5DaZ0A=xk~N!%*P|&y zn_b0egT>T3FM(VJ7Tdku^P5D}43c_(j+@l=YbyE+pJes>YvErC9AXA>WQo_iTp5an zy0J;uKa})We>ob9NjtXRQX00AF+=m8CtqIr!&BJdW*a?%9$G@};_V;otsu7M00&!{ z@f_bBr;qQ#Y^X2gKDc1O+5gqb;CczM9SCwBE<1cb$U~LJRnynZCIPpy69_Nc`k`V! z4SK-cukG)0>e-0;07k;*mxX{lu{(_;tOBINs{21Dr@i*|aNY=I1~%7h;=spyC+dZZ z;hJtHFTPXS<(bw#f1EOTO&H-5cq)8d>HQ8h1#v#e1VYeMjiNORR0f7-*2U^p2b+}3 zQzA=|fiH&N7fcTJ1%b?uB5#w>9y2=)}-o zt}$_1_|RCZ!JWwem>)WD?)xEq@exGC7-9=8`=*{#v|ha{a8$#De`-wdgJjS9bLq9B zBt*8bZ)pz5cUbwB*unlv=!lm6WxmJs7U6V65?;WM!HJj!Se6!fpDgj4%bQ_oE?dIj zX|z=EXDgKl=cU`yyaN#!Gj3m{snScgVp6xxi%l-F%2`dbtG-&FO;%iDM8*|+m>N?e zSO%*c>|2`^Co$hrlC+y>GJu;WbA{&Dr!;K@X09!?(v*50YV1|1-e2W+9I6xsD$}5x zwsUP>iK2oRkXmSp&DtsU%ZtwNkEIEG z=80^Vu}4L-_lbkZwyA`7qA42MHW%pIZgE^5-d9|IlAs2=_1!CryKTSMab}0+ZgM}w zSN6sA72fs^ma|2tmv{H(6&>MRn^K}sSHvQ+1quEva&;)_x?>yaghX5)ad>{E`!+w1 z>)UTU9ER8ebb>-H5KFD*@wcafF*E3}8z(7*8Bk0>{N_09fwV|w^qG0b1hukv4&fa^ zcK7q$oZG?FhZp#7G*X@;bvAd(6PSA)o$P9MzcSlVjYnyjW~2u0nXZ;B5-jv>t1X9IE2J}ph&17u$qPV7=!MtMFPBZ`ro9r~=Kd;33$+Ww z5TbSonun(Ew|SbD4Ji&L?a}z)3v7joL!3pTLdT=L_cdia7oJ-0vxn?to@6^~j^5Ec z!<{LtVp5W{z_92Q)_s)=AF%fB?t{;@X(f7nTujS5GQNcz+mn7tDBLNT9KnhZGTiMT z>E(9THK8uP>DO_zd{ITc{#oRctb+4ETsyk<>HE@6I-&P(cD6_}iPp=y^I~z-jN-dj zX~3uRd)ICRwlrYze5lwnBs%ykLLUB%e68u|2N|BB-`v?k94bHQ5nn?sS^dv3YsNx6 z%rKcO)%8J-PoWzPxkaNtPk+3-*VcuwRQVbPlyauBHJax*3@drlM#Zxi{;JfyLia)R zi8Y;UOr4d=irP@kh$dd&6XrwUM+_=Qn^etB%OqlhuWrmJJE$L`_oGg^IBu>}KvMTR zT)C7;R^CawOO=y?o-Fj4+u#}OjZlr(A4mOSq_v>Km_>zh@{*k+$}HLhXw)=_7-`?w z+F$hfHS`X$KXYn-e-ChD6%5?Fx@CLWksx4h1LQBUR4Pp9qK?!Cozv4%=`jEvRDUJ* zxBVL+IBHLxoHNU@tX;RTa?4@zYDc{Gx$Eth0plGY{K_qfC)k$;TaUZ9++EjWMQQPz zlvwSYEH=r`nw!|RanA~W=n0E#7AYDW77KYI_L2|1#3fjW2muKl|ld0$%*&U zA)Vppf9@-uhR%f{JS28!9>nof)D=~eXH4Yb+clAivN{>dm7iPSRW9*9v{&2eP*y_S z->vs+k~5>4evC*z?Qhh;AM}8IX|wc}T;^K{w|(ZJVObJC)Gl$iG_Bx>*Y{A-WN&5a z`a;Xojpk?{41Jz|F!i_vIZUxqO@SnN0Id>*%s8w{)Pyz1%;>>So5Swl7k7+_GA6R1 z5a@=D;8(yG1rYr-n72tR1iwiW*dYQ7QFnkNZ1++KxRk{>9Hh1h%PbylxyQNQ5pRtjF`|Sr8 z&97z>ST!dXS)LDKTy_B0xLaj+HAR>tt4KCTR^QuPMV>ez7b%x?tKVgMw?WQ1NlUWf zy+rc@hPKVrn&hLA6D9IoGSm($^J^PR9Ie}H&`4jq!H`uYm z6W0|7^FQ(47itr;T**aDc6EZ@f4QjlwDlv7*v`s)ncTy%WoJ_TYWrByn)uIy6$(p`kMNto zo;9eGdmo9Z)uXMfP|GaJxE>jLF?bGgYo?(4$g^;HSNA%5 z0g1=}b=K;7`*n+QybTaNL@Xz-yV|bN**ApVNl2TDPBt+>^u)skk&`fE{889L(_L+- z%QtH~Y=m(QiN2wxYbMuV=*gP<%f(w;St605Zz1if;2+-ODZF=WhBz<8FrIU`#S|3p z)cRg;j9mI$9r3=|)a~)~1JaJ#; zVW~ly%&JRlFgnJHy-rbfGKgHXc$XgC@2r`n7~lUD`_M$Q^xUbM$$emtp2IS6s*GjI z$r}xep;WpQZuex8yHSpB3@N*~{4(2rTdn3Ao8w|i*VY)Cz56?&nAL{G=3rEM4@q+L zlNKG2R9-&IX*)_dnfTyc7X0Cr&gZkcxmyHOx=#;2m53bMi;Nl~&j$DUuNlr(SbY4Z zuDZ?!7O&IOmwaV!86Q;$3oJUSuh+WbO1{s*W+wY)1~O=vH`N7lNeX*M}z zXBF1`cvjMa8cTQO0f04{2hebCqnGY3X`4W3`weZo`I`Zaf><@*9OD$4M;9LlVl7iu zP}|L9pwS-*tyu5!atf14A=mObb><{~f?w&O9_IJxC#p{Fla}KpS*~Xy;jxjWU z7iI7rv3A&Af@mh>lFbe|4-5o}A7;6k6vTwrWIH(#^hj%gaS;kW9v5(q6-F^Sh%h7+ zHe@!P=`*Vv#BwD$c!MTBB-n;PH{&aKHImJf<5}e@d$*a1$1YMKk+5XBs!10%9Yws( z8FxvdJgF4)>Q#5|{uJ(4-T`hBL*!m@iw|(l$tul?(~gkd`V#@5bTZY{V^x>G7^hky zLk9`wGSB%2oQ*@${4g3>#77A`oP*l*|+=A0ZeDqt`ywv^3Gg)ze+Dfk9L7s@G z4rBaE_f~sdzfUJT>*+VMN8~{EB;o+tz2mFPIq-+7Nbm-#uohoUo_Uq-bSLQPAZE#LUC4?s(W0yl?ta@X-_ z-@j>=M5Tb;hVT(woa8>c7>r+^6d_;qY5#n`i*kpWe0bn zd~M=8I(DYS=H8Neqld600R6Cq?5wfg7W4i&-^|1TJTw{cJ=1{vfm~$&SEK71qI6~F z^vW;X!Mt4`GU?#!u{ZzU@XD>&FIKOHuWzTPcm;Qx6ePPI40gME%rwO_<93f-er3zd z|7>{0w46XyNU%FgO}<^{fs z2gM=QrmR9-MI61C{Z{)8sN_iTOl}RbdQCAAHMtYzvPOa^Y)_HbL1Os!BBlIRyY;QiRfxeayb0M@lC;HSZ+ z@)3iT_Wjep;gMjF;hSv<8^s^H{R3JMbBvu;1(nm037MYf^IkU|{w4>~dux+zq%Fe`j)siaI9XHK z%*@Q8L^_$OC+~-z`&k(fo9hU!08tw(<_9fjvnkN5t3~jmN>%cv(AzTr5rb<94g9if zu$TfR#5g(vJn49q!h4ipP>p{sd!x(*#HjA~qt*qRJ zvEbsSonD9RD)sGz;oli=b#AhgM0|qXa|hT)ES6m}&+--MmR+eotI1E)-$`D%Luxc^ zXPnA6x@sBgE%152Z^UdDY_Zpsd-PyHRDdkB#dB|)&wg07tSPcH zy9i8BxO-oTr@nSfCebZlfN9S<;nb4;Z>(hI`kVIn{+8e__jp)dEaNhc+K0vnMOxHN za{XdEl=M*;*OBnJ%0y6fi9Ow)&94$40W@Ux(jbvN9L|A<71n>JgIYv#{pjole?d`5 z>Pt@@4p$?gx)tFr3y8Y-UQ5$KePf@S;w*$~gz^Cj29 zGcGb{6XWH^>1|`fw!seSgmgug99D2u0WIW#W%Gl#4zESnjDVb=x%LUk{1EqFjvnWU zP6a8EG+q%96&*E+W(p6k+HlA3q3+GqBKiB_h!?=2{jNrfm-?nsmL((Oy4Jx)HV7zm z55e1}eZ8Md*N9?6;?>&E&86ktH_ybRw$r~W7ti&Tgxgbw75k^rxJa7d%9x;%+im+T z@ApoJCYn?=2zsiMj`-%zQfyAaHxF4z??EXSqS^E zh$5L9?$x?RXcy1?Va3T$lKEzvi^N!Tpqu9_yPW8=vZ{db7DK?I!yRxrP9Asr(0JuR zu18@44)Gcxx@1{{OK^XZ#U6~tshQNBoGf|PXEoJw29@WX^~5W^+Sf7s43%{3t}809wz02IObvJ9 z=vP~Gcp(y9rCXyR$+xIOU~@>4&hwzrz9B63G;JlB@S=ErT(`HWM9=xeT9AWQW88jN zy0}8cM| zg=GaGAC^%d@Q7l@g{x=AxHn4v-zRZKpMB)S9xC6+=)VWRb;%cY_EE zAzSu3P|f~o$pN5T06ElaEWo4~N%okMVN5=rCK?%Qie6Rb-R8i5>F;HdA)LGE8M=LJH9d-Gg%gz8=t+rBa z>s>5o+5DVcE5txTUd>JFK_VBI*s2TCUh{RzhOmTAO0f%LJ0()ftx`dQz*I{iRZUNV z(Z)E5Y{Z`5BFA=5P#H78z{^fT?li=|m?KkxN#GuTF$~$a>7W{*T>uJnPZ(ufS42wtKonvbw)32J0J3aVwr?l3`cC zIWq6Om#&rP$<*~G94kO%@S8piYw8HHF(NT-9~cVR-pwKu7nXg>IqsmVRX)9XEEUueWB#MWOPn%TFX9VmW ztW)d!p+tGA$E7T)u8bU&!j9==)qRBs$v@P92g7zDnT+rJT-?J=6J8qwvXT*yBH!gN zn%D+kres=*>;_&rwO^KZz`Xy;?lhZU)}yW6K_OL$A>j{^%Mw5PB_+?Qb9CU_0d+o* zERUvhgz&^@j^gZZIioOct<4EL3gdRO{5k|NC({Uh^~H&7mY!Rjiq!nv=RdseR4;=L zJD_B?1J;nNoi}U9PYk!ao;_xY@3FqZ*s(MXJLD-`bQ|0YS+`j2{G+YVqlbXOtOvg} z8#^mltxk$|pj*}t7o%WU`9qplNp9UryXT8SG-Y%A)3U0nAQ2}k;#0x6M81L*Wh0Wr z;x_|%<`?C-bAfp(=Gsg14Yz<`_Z#_I2NbC*QWpulIXQImlEi17eys4vzVrgJa-@=)?@PK|uIS`ysl zWBeeG(@4zfituc8TS<^x$sdKKFH^f{6bp~gxhedA9h@sp=DAkju_ipIIG9}A4W4L!#LlDTWStK8rUp~LT#0+QWxkNniEgcMoK zC5-{m9+lW!1X;a6+*6w}UDU)^&)G#*&-Xl?x!wsAt%*_|-MU&Ev2;Ci5oxD@ zt0-Q7to1e+z$VW9^uB)wwHf{C{(1r{N9foQn#R1@<+HLipYTgmA!3vK2lCJ{n%cnqn%yiRrA&xS1vSrN znl4w?rA>PO3b7=E`a(}H6WNc$R=&|YF3_gf#DlL}#P)NG-KVy&l^^F)}o2xaG;~(UQ!*J9g+_9@+THgy9RHS7kJP z%gafe;rIM=k$cLy@^ER-ghk%?%?wro0pHGItfBOwem-pc%0`O}+T9}(v5O49%66xY zqC>@1XOPr(W|>9GX~7c!I&`l~pwTrYy|Gs)iD~gE{Ma8elfSo8h~pEu)=Wj*V%~ux zSGu`+vRpinm!~3jP^_7Ps9s0+-w}TOeLGhQ<%vI5nD!}#0 z0@)8`2i~k^SyD;S`qVOsK3F#WkTX!6x%@a-kohuTDku~u{E=}rmX z>u;6zFGh%WMwGlSsYYs9XC?8h9s(*6O7pC0A+^D`2-eHuNIH)&s@Vs%=gl@GGRAWb zGf3F-z{^ADt#i)+iJ4jn0!LTCJfKT9d|WBB#&>|K z>!C`IKs4P}oW;w&l-&u$8612?pbMJ#d8X?SHGXD^p?kF+aWIQ>g?-O~I4!^bu%gbf z&h%x%R^8&x*&k>#4qiTyOw~K&nVGj(&xCZY8UK3Sw?4ALa&JkvEEcBT7S5VK5S!9_SiXj(R3OFc_qCzrrJ_40Knvw zoU~_;L81<2orDz20Wu^#pn@Y}X`pP9jhm`+y6Ocy`>;Ax$f-{;wOnv8c}!^ky$Oqb zH*2Zm8?iXAVrw$5grso2m1*9&4Vs<2c?oiR`|F=R8I-kq2TThN>&7A{9qr{EE8bRa zwktn)`%C`b9dDtUH}zOcLh^n_VB>8iI@EA){AbD|~^V#||`CJS$K{u(pswGG|HT^KkS-Fc6XS}nid$LJK zIb9)rzFZ6#uQs^(fc{OaE~iJ25tAA*!sA}i3#0s(#rhq<&(Mz;LU6+f5mXismcBnx z(ufEtEl|eEv!sh_8DN^BTpUs(D!v7@=%v@Z*Q*^gGm(~ z8blPp`J3dIJNV&=O6><;c%Oka_|5D8Kxh9h75Fdv>YJ*rK(n@+Iqemy`TL&*byq;_ z6tIr|DUX#{QBHpH0X`zYW`0hFx1#E^J{idzqflCFE4immfg1F7eg8d)?XAw2S@}fo@v{)B&Rw_=vpA34TiOpTpINj5V+(KVncm4k4ybFT6JPt@{on zv(|HhWV1}w-Om2NA%6-?PnLWw08^85!$7-C+7e}6G}e(xsy`8@3E0WjbI>Z-w|Nb_ zgL)gP>pMMwpsg<-G7rKIGTuG%sJU;!KyI*>n7G>FUh_G?8rDQBBeuyH9pFw6@rP~g zZHRv!ySQFHz&Ti0_n9ocnU&YL0sh?h4YyY|AnlCt^gfaq8$iU33rSy@JvPm@II3uO z=Zi2Jw|&8R_M7vCoA9Hy(sAOFib{8`{F#iH3-V4iO4K;Yy;l2+1%ZYufKN`~SjXAg zjkBC*$*F0dA0jH?*Lh;9MR|s2uB{w49Ls^h(Y!Rf#=R#KUH*tW$Dc=YY`_eXX#$GV z8tPH=7LPWqvDT5~v$a|8}wkMLSo#B)&f5yt(xUd@8-?Th^|AVLup;i}vBC zDH|opilXRqvh_JC zx<(wu%jMS_5sn4xopIpU1=-yqU=}Hc)XZB@vKWaqY3V?%ORBX!Izk5u?G#DZhi`_F ze8Q;L+#kq<<72YFA2Ua{#t9T5iO&n6#%@HFScIm_Mb_;xO-xhs52qr@_#En0A#_2W zAZJ>#@gpsE9jR^Ir+X|XVuONQhL;09bDiF&f;jrI#iM;Ie?02vo!XOIlRe__3K;@T z0n^6C{)Wrq*0~&t2bU2rOEvn9pRw@6@od?eTvoA+?P{uDnyeltc6urNWa???v8^86 zTkX&I`Zl=ZwbU7$6O2ytu+v{oiy$#!%)XEcoQ_L5LwOu9*%368u{*)KH;4Oh2NU9x z7cbs5P#77I^;JWOL)^Q2@vD){sGnCK()JFC8<^;%aB1xmE`QL^nJM3|(dM9_ zFS^(B@YURLP1#oXcTHY=SO|xGgD#_0Dp4xsOud@3U{r8MZjbZ_kq# z{nxthQ=8o~lZ1z1Q*trK*!G9sFXkD|3JJVyLp?F0A=YE5ZPIgAO`83&*!!1el7?ga zT1tP;3}UWq#Y1Wnoihz$cew4S8bj?%gbl~p_L9QqfAy28dKV*A2CIs#&753|!I>bO z7+ra?`Ucq=J!d`s^(O zjG+q({oCp?3p2isPIQ43<+6s7kJ+*X;rY6%~Itjz4$f&sGGAb; zd(Pg|T7hqww8M&gmr|czJ%5%8}MCF&%b^RLNDl^Qfrc6U!w@pr4mnis^x4sKB==B266^6<@~CCFng65yUW%>Lq@b8QFp-1{zPs_S!Q-rrf` zDH#gGAjgNh!U5VE$Bxl`(^zXaOk&vf2s_PWc;vlXP`8l?^XIbCFWOs>@P2mM{<1B1 zpC|b26u)%Io4*A3oN^!)(r1xqO>jKJ-Mp=br~{g>v6hUl|7MB5^eSQYh$HjmI4GVkGUHOyl^NSMgQvIb;H{{3oweaU)ldC?WM`P)hVYudN zQ^FQ&dTY2(+@Fb~6(gOmb$H56!dLTnh1G0+luc@wuN^?`cJg9DTMfAv`~M=s2R*S= zr)rPCe$P?VWON?*Gq0&tkGK0$i2Bs(UO$P3_M~RJ9Vh)8Qd>z}S*Q6uXU~tm+k7QP znp#^X7XX9(F@B->uf;w?>K)(tj{dUwbyp7*DIH9#WSl1~%*!=&l0U+X^TowMTW*rF zdA^HAE}~I#kCceT2@-vJ0Q0$IYH2F?e(=BB_QQreNYE~@^0~=6qRvrP>A(w*XQ+yB z5V1q=ZF>@ZPPz17u{^XF-|w8hu6Xv02T)s5U46J$JADu3XG>B)y&~t!cmZpXoUz>J z3g(?Qq1}~BoHJB$TFxre4n~zCQBlPMto1I~=+^7>!*XRKQyUChZ{F5n(u5D?vP9h% zi5OqH)^06Fre_|xAyH54Dj*2hpaHTz=mUIR{Zi}7fBrl@G(KHM2lvU50-tRp;Xi@^ z6d#UynYESuUyB5yZJ2{RQQ1<50+bHRPm`;VQJ?0*Q2$90fTeQD+ZdJGOaDhOr4aaU zg@EPM+SFLhQ`@cYQ!bi3UpARxGj(J#(BC-g#0Q{yXUhG6|NliFQ_4**`Zb}#$hC{T z%|KO~MH9qSsP7x-&H3_OL=Z00q>s6qF9l{_yoBV;riDz;QZn~BjZ2PXkiPM5e!A8G z$Ls$#U++bhY2~dqFb{VgD-npB|NQgegL$_%LsOm*9qHaNPS-O?cBzicU~&ifSjN zR832KyDQ{DbeD}{@l_u$_U9j?2q)v;JSAt0-Hj8C0z6YfY~2xW%IT=ct-CM35^#^JnhRv7$8TU4@plzY0TmF7M%UTCb{W!(p6|_ znpdC;2*&_EewHo#)TiM3)Z6ymAGS>hjFu~z=6X;8Y0Kpywcx{~w@Igzz0>FC-+?5|Yhd0^WXPJAKtpYFCXsN(bl)2@w z`>ZKu@0pX=jp}jjLPdsmE~1x@0B3G+r3FJH*fPK^23CV~79abg`>_v|Z&X7-vG=FT zJU%=0`IKIG3)8%PImH~7^E|2%@ok2t><#Vli z*NElUKCf#E;G7IzjUcyw^a|XgaHb-HnfE;LmTTXiAD$PaP35O8Zb{7zv7r`vv8Ec~ zsr}_OAw#9>P7aNb68S=2+xV>cS$CTV_q}XSp>d}tSAJ3g1SN_D6)Yw>@D|AYPBLY= z(uSJBmlE(2WzkOQbZy~!pmEAnt`Z<<2+g(D4}pc#l$;oHG>z;2ndKKvRO@QKwtx0n z^zM668xM?DG#p%Q{#Ob*7HgP>Gu+=m|58QHXx^wIRc1HQRR!)VBt956oCP*Yt@Lf5 z(9r$TU!`M3_lMcyur5oRQRIiQdWJC=4K@+GO}E!;m&h~w*mifyA1|(szs2a~Z(mtk zNa{X2NM4M;R@?6e)ODqoVF!ueYY~xlw8YzeP#TNr6l>@##wgQ&UND{0_mp74_^lcRI)Ep}t)epN{|& zgO87XHhMhL~Easg7l@#`;+vL;3Oo8_vpj+h?H@z8QAV;;1*; za*aXSC))9kek(I8o5@|~?dmBQ+WAp3iIHiPN&>`ty|ri{U^s%zZ)9Z0@R_rJOxvXq zqUc_3-Jqmyo(%TX>Mzy}yfj1DmwTHaD|Bvv=3?na$YxZE5}_%KtY0~j_Ypl|m&TJq zEcet@^UJCbUx(@Gwy=DxF4)@w<_)ra* z-%d7}1=b^44U_IO!wYsxNH7`P(y7~vH=jm}xUpXeiF8BQALu`F*KYcFib#z+{(&wmenM~UqYKDC z=?R4w-|c4FuiWS`lF|QDhhe+>xPDONd-He^2VW%=aSO{$%XP`S(I23muNioUh2yUy zKKCCwX-%yhb>)S`YgoB#i-|3nEOJVIPYJf7uBHy0n{2 zZGNwN#qQ?8Rv^g?*Dh6HFfBLF+3x_{F)v99`}OaBIru^Afp#$2$yz+8a{|kqNBm7d zd!qYMED>HG(J zs0i`U{o|$=Fx9C4f@*afl`{JirpW4BkM?H(-4NJojS}Q>Y>8CM`6w;MeSh8Oll+iy zryFM_t^jkrJ(6DM0@+Hod{+r-k9>dDXolhT0^k}#{v1+ZIN`fc& za*J*BPJ(Vr@7cP8l(0^mOeC{|d*3hmmqx-rz=H1BIM=(TXPGUEFpB+2`Otc~E^{fr z5^H^-mzvHAuiZbJGY44{id~;-@|@1?XgJ^|ZJwWG=P&KK*gDdsdZcZ+k1$s1-R%`1 z4p?x_bH=XU*;_%Bde+X=pY675G+lz$jkBVS)w@%#F7~?H`EH)Wx__{IXcR0Vd9!oe?PG+dGWUP0I|`1LqD1^QE+~ik_^dXPljwVP zHHRaQmU+%Hj_(PdpQbN|l}*%Rpa8O05ZQalmC}nhArqoe#x6}y{Nt@~!ji2OIEI)h z>p~%1v6B(+mvQ~)zt~YE;1R;0#*Jj@u*MTy&>&SkZ)RDLDc{T&VG5hqe8rW6imL57FYh3r}kVpk^rn{_L}h)dU> zD{^ME5d{qc)u7ie*pSw!oQU>yKw-P%&!wotQuAoLDO7QK{ahYsP~ET_d~});%Mmo0 z_lY@;VS<=$gypf9+K^@~tnV9&<{dD0A8bb~TRJ2~U-(>03~2USODJ!A+9R!sng>_naeO0hTSM}`}UmD%X6I?Ax39Yorwymv-#@~GGf@W;DhggzSmZ@MaM~} zGX*&(M6qI`RV!MP9O5+wj^&Y{a8f3m7)_LN4p-k|D+1>`PJO!3s5D!JMDBExZHuzG*_@%0rSb>#0!)53M@c8oMjSSU|a8t zZ544wP)%5Gcqzzn6F4?}*Yk#~JsbBFNf7V|Pnoh_N{YX9En5Lb1t`aL%;vMWfq39U z1A1E!$jKg! zFrn*%-*-e?rg^{bEm>abi#!jPpo^nhQ5WH8{aGjYO7PIZQ8)r6C+@-otUn`67xzVU zgMYoHpR%LK8aMl9?-o3cw*r!Cc-Q5XH`C19R$76QCUau^Ge7JDavaoa1h4}AKh6{b zfS989wjVBgUr)#JUHoH@PZezX9R@uyVPI2~E9hNqcL8Rt`q>s`x38`3Wa_8+b76Vl z9Xvj)`wv@?apm_Zk$*F;m7sPkgI=r$^f;>LQ?QqW>{4AO1Du>+(>>kad9kdFr6-sR zk>u`7nx<3mi4fF`HjozC7pvW%%EzeDt3l*HbT7Naf9hU3rG(o1+Rt`W?w4KQ8eOpVN*aX|c=&%HZkeJeNizOa2~T=SK!vo|LOs_cIo-Y} zPH1|Qt$99Hm;mX>W@hE;=!qD4RzQg59Mi&N)K-o}FMZY=Nf`Eox_MZRwSEojE}1#p ztE{wLN#x7Fu{ka7`Oqc%=wl{^SR5UK0roj-$Vz}^PCZ+Qp*k+V?^!iI>w40~e6A@( z-X$7Q_XR{dh%691&wShLJ!tF_GxKb2P|I7#X64q28!#Iv>M&O_!^{BP^0#VQnS{9O zDf_v=CI`RLE5^m9v-^@F>782#v7W#h+*6AN<$G!%>^Kuw>v`8(QSJkte7i25iWJK=drN@4%8^NvKCj?=IR2~=Yw zrgG7s8&;@T|8T`5F(GXXJqqFcRmMMbL#%y2upqF>-@m0S&?ouG3Lrd?qa<2q(Tx{Gil z!ooinYt1XPzo_mjfq5!94GzZ*m^5o1ixhV*bo(Y$-a5x4c%c@t)l({UYibv{;Se6mVDSzvdG5aaiY?0T2nbYgH z+{z&~%? zMr2&mmyj&Y-tDPUS)EHmz=+=6r*$=cR>dEEVa7mIHhb;~Q~zC#P1u(nM9=(XG>mvp zS)etJESD%slMrr(FO)=w!EB5xLX~x1_)FkK``nvbq5*6ilkfP=)->k%Gp2wN54hq z?h?W&d8Zf734AY^x4QbMRZYm|YJc(^$Q3RS{x*h~QpF^GReH;h1kUoMt1oXk3TJ%G z-4NQ7?rd?|o$IdLzIH=;RGm|@K)~zcFM8qTTJI8P5t;>7D&Q}U*hut`VC~yuRlIdI zN-&$)mAcrnMYk;vJdJ()!WXx4E%YTW?ob$v4GQ+mt$-N!fcX|4HzRqf&iURGo!J(D zfL_AXiB3PbgjZR&li|I&-%n~!p`qK=j7CLZ{{3;ASmS9@M+5%v3VY*YE{#itbS>w6)6=f64Qk1RT2bqZ(MZgJ!?F^2!U813$^%i8l+ zo#cBea%)NdmQVcJN{eUAU+xQCMO3yuec0G9cE89X=Awdz751!n3Ym2SOG3rjH{GGu zwR6+IV%vPK+&kKI;1*uvLhF!$#Z&thtv@LISC-NmJanV52 zJguCGCTd&>S^Gs}kRw_>Xr;MOdtMGpMThSlx{I24czCTrCZrOI&Tmf_1}r1BaFfoP zWe_#6Ivef~P(SMPI}fCwY0PJ~r&kGhGFTgPv9;i7bY*}(&iCEmY72;88C~SQ@b^La zjK7Ih4(b_P88yelQ<%l7;=4NUqcm@oM7X|_ybG_o^eU|GJ&K4u!{P=KQga;px5BpW zjo)ED1)_2WF(Z=^e6vG?Svnnyw)*bLFJA$1)j+ImQIPMpVuGInVHRNf!j5Ul;LMf+ z*1E4O8B71z%4;9Fv*gswM~dL#pSyUxw5 zx7glQ6t!)rr)nM?LgqpMgRQu?$r(!zjnK~N#{mL**CaPg>#p6OG#$lb-QqSs69j-(mT`Gk5=+eBD0`3E;wNsvVW<ZeF4d}csKm=H{dNc zHdevwx6gEwtz@F#pj_f^qiLZWrUP65w2_0;?XnPuPTpzMHb%hzxa40Gb;S=lO^ljJ z_bu+4`dLP^hs&0gi)w#EWMS1-qGS|rU&Zoix>`4qMG-=+`(EsQ{$Pu#Z}Y_6poHv8 z4INx*xq6(B?*`MZUdx-EtE*C%Ap}x_yZc zi*7>oKaC4xYAiweKhTnpPPFi0J4FVHeX5Tu&nLcm0^u0DwGHby90{w(2ooTgSqMq( zL_VoI-{6KfvpP1_2tA$;MI&VVeO;HX1_{Zu*)w=JM03y8~QV(Gi-%G<;StW)aQ=*X!TMk%~1)P6R{k_p_ZLzD{JY0M?t4vw#P$LDhA~ zw-3_b&2jG%(69h`0*H;=pg3wQ8(tSMlVlaYE~7QVz*3c^4VWEp6{Y z`WckDB6jjTc>X94@KylCwJ4i+GQc4?^+amYyqPVPL5sH}Wtf$j{H>@&PT;Ak<*|0j z(@dURsB!xpSN3(3mAiWdW#wj1uwo#@sol9oP88@CX|)IHD(#6{haI>MvlSZX71W*{ ze=c7J#L3;#dX#q?^b%MriZ$A1aN=o0s#q$dG6C~-cG=B5t(lN-{UQg(urgKyT=Tes z9hF%wh>6=FsI5~}YQg=Rjv!=6d*i9W5K+3?6rrq(I=5w7^%%2&P2lWioK%XU>aJ_G z2^Y$R!6^DH#2gGUHf{U;m_b_)b?L%0TGnbnyP}(ZA>as`j=vFM4{mUS_=C$to0> zjJMXMJJ#Q^eI}*4 zbz|8krGMUo0 z4#eJwQ`+5)E_ho^IQc@3kp}-I)w=*?D)h9R)dWcZ$l`fcuC3NE^D8^=W^0n?$L?@@ z1ax<+qk3s96aE#cLXvY~f&hA^#x zEp!qL#AcFoQW()YKe;=ju9yy#U{F--fCvsfI2=B zH9>64F7w|;lXcce(}l8J2Gyp*x%D(W_$_^@q%S)_Y>;)6w^-cb?rL3lPo~5*1(c-% zxW4}aJUAi{_lkNrO!MT@rH$VRxU^fxzP>=fd{hNmzvNFw`10m_?8zisgC_uzJE$Vv zrnc>s#OoxddU8C})i7LHxuq+*@w;O;X@>lVyHutKW*ap4C09jH0Py*Nc?dhekZ~)3 z*mNEmeYejc9z?IND4o-SqMy7+Sw2vPxdkf^K6`k&>xV5I;#|w~j3{GD8gK!9q`=W% zdiY@I>2E`J0m_h_#X>!~SV=+Dx_a?k26Vt*bL;KA#<^NG8=54l;f(8!^cGF%bCcqF zVu=@~{<=<-6Woj42989GJD!EtNv1ML49+|w*_bLHh|RIo*n6$DL*|tdI;WQ0?g8h= zu<&Aj%EP(1knMvKS3TLM!I?UuH2{`@=x~sybuA-CF8kkk45)k~PxoK>#_d^Zh`4rk zWYSvu=cw^bYlI1x(#-*uw#c=IKL#Jl`RmYJ%I^wyqh95A#~o%8%&zi!h|Z^P^qR?b zH}Li!pPIZD<&$R2R?MyH+NP*rfQ_-_Du=f;wzZMPY=b996l=(%Tlj>MiQb% z^Vjg^OKlI>#*ZyA+$azx0@NpV*q=N(7Zf+0v?EbRra>F4%`o?ay-@-B${_1f9D6Dv zff`;?;Z|{z`+aX9HhupRiTsI&ibS$71?QlgAR-mLFzLLH&{3WH9hd=RDb3{fsxdqZ zJHZ;@zIViJS_(X-6P{j4n;Ef`*KHPv1$$)jdFIe8HJ!Fr z%b1?669A!;cjtrn1clL4DmZBK7E=$D*t%lnSpEu6`nqRpGEc8|FJqkX+NZIUoEZik z$O5y6w_cs)WG*QlwFV~Pu$)#F@fyt3}9x#-6OW&WR=+0%b}H-`(O3Y$FP@^uyO^?0^t50 za^s0faN}={CROT{LdL53PC>^@z`k{HM0&~`%oJV5=n!qND8Irqpx_$?+AY#^8OKc< zBa4Y>9)d){mP@A9N*T9SX8fs^wEy6chHE}mMv}c!22Z^ev~>bV<~5@{Do)Q z|JTrfLC_tFD9GcspVgdi0&tj-5zp+(KKi|^h7Cw7uidu>DuShFJA7Ru*ITev8?mj( z@Fw~>fgU!JX6(eNW;J-(Pv9C&QAYc@5|fjY9FIy$^o+goq{<)CQv~(3-of!iY2(bT z<};47xT~9OXqgh8Z_;!~uWo+L^i7~|0#JRO-!f^uu%QfUUBRi_p)Sltp=J@_eF9#J zRCj9=%z(2Sa>g{>e~#b4v*w4&SK4TmTqEbVWqdLgqtzHkwo~#N^@Lu2YeNPoQzXWm z!@kU8w&VPLivHWE@;@Y3!1)1Bj0n2_<#86_04D~13GhWIozHGBM0R7A=b(h38Fp#= z1diEW4ZBv0ry$^UT!eiZsSs!%(0=`nW z2e?K%mLg)2Ur>?+pqW3B%)jJa0j!N+lIrXqsegS()?ISr^xhNX%-#+uCJy-#I2(A2 z0$&^wr0ow|rCUP8`26Z!9xB1V%}w6~1O?lxM_ld(>1b-?4)(qYA%A-HON$4m!?Y%w zrdtJWlmoztCUk*cW0&qAid4G+;9K_$HP4+RCR*HkAV2RL(V?VxV8@5ura*5Q(bJ{& z``6kK|DkwsH2jBK8eI{r&GC>$@9L-fs@VAL*#Q)+p|b{P0id1}D50FefKq%a;BVYH zr|$eqMy*Z#{CvX2rs2=M>8~j(>3gwwdTsmJRlF9sKVvru8eM+h*6{afswnUWARPS9 z*<$~P3x)q3s_f6hd7uHqk;n@kF>>>a5|;cA<`^=T`kFTf2&0F8l-P zO$~B$x#X~be|Xf~p6h5~0^|28v|KPgH!G@4Ot4Pu#DqbKbWW(m-(1Beg8ni1E=RC# z$tJQoK|qeX5&c#McJB#@IS;~dL-&x|`{BTcYmM^3cCqp7H2u&GepR0e=Wku#2Tj%= z;w|#6rX4l%chA;k=nlT~itP{Aea(PoE1^NNNndE}Gy<|ut=N8GctRuL)$)99z+O=w zu>HBGzdzu7V~)bZY0U`k^L2jasKC8*vF=J;5fUC)a(Xg+s6jH+PXO3|OupbUo3D`i zXV}#VhGa`%yF+c~=7r-1;s9TekGBDa9}OPu1j3HjCz^NWS6ibh;q7W|df9r-#xXCM z^A@?Z*V2^SUySwxDf1XMQ$_*!W|%nj&s}?}j)XHpcJ5=t2-K+T`3 z?_qX|aDBWZ;~p}f&g-i_QOh6~Uy+}AoZHC!XyyLwQGmTfd$2b9dOX9tu5={Wi`DtQ zIYH$^n}hW0z}=k_8`jQtqaHr%Hpgd{_gMPrgT^9qu(SBM-TN?hKv`fA^}#i%KI!@8 zs0=IXiCq!lOMs;LCEm;RAs0l=q}ZJ5_Hd#hC&Pd$5HH81)b~2PwWJnSV|5J}uDEf# znx_Ga>Dxn9RKpbk6V`_@E>hCrjAa*(q1UUsdJc=+_8Q~I=d#aVqnMh_K3gdt zpi0%Sbk|#5Zl}Ly?}mV}7lkny50}5d&qWi@!Z~Z$!dbJ9;j~sZH=nEL(QL7i zvl+`q=Q>D*E4#(S)Yp7x@giD2P49Rx!HfpPDZ+q!xc6Ch)Gh_V`nifFbp`Xz;;^mQ zzMBRRs}MahHj`*R=n>1d&~hrL0$_lK8H@>fV$N)-`cNNO9_?EvvB7hC-)fsh8JVLr zDLd7i)x*~lH5$h6Fv^K7$Ijn~0NO%DT_@~Izeb55mY^55(<$eqwU_m*jaIa4FXU-w ziS#(Mim4OXEucr%rMK@Kzl88N-Yb-Db;nxl#dda=uxSS=O1?m4E#?rAK`lsGXU#4U zwg><~LtWQE{nAwhkeh>2%(Flo^b4DV77f@a>v(dqJBH;oU{0tIX-s-`-?e?PGe&He zy`aZwTU$208!zcG08jzy|o_v0jI%FK%4=TSw39o)=!5=e_G)-#B2LY zT_*5rac>3tv*6ih`AVZZw(EGR1R)c}nttW8+TK0xC&4OE>kAKr`eZo-!+k2Ym|AYH z!G-+5J$|LU1d(&j73F*uGr>ujl9iZ$e=Of34o?;lJIs)#kiP#IN5#9I%zLvAY&O9> zS&NSR*dAG;y|(g$W;8K3}A-IX@LBcvo3l~@Pi zsEV!`3NP^J`JI1_{}nt*yZSvy5^^#e-U>RqP!eLb2!5vNZK=Rby?*kMakwW4Qpl8|UBsz< zdVlUsrE&qUmkY+OA7!+A4yn6(IBu*Rl*tH(7y^R0NyL$D>@Jl_$6RMbpyRT*1dR>N8eSF7WCmLMVKyuf?Gae4kaezNt z2eE$T3uv2Dsvj*mYJw9P9=Nx%>7KPEeK{09(eyZTFI6(cin@CF`>cuDG%B6dC$J%O zob!ybz7t+&2Xc~=1tpy1n0O|!B-{x0#1H_`j#_WR321op-$g%kU~gqJfg4hobD5xx zOXgvQDs~03>)dtosC-I?8OK^eH@qgMEbv?71vJ;w5zl-=>jst}G=>x+#ckOSoKZ2W|DY_{@xV`FgP^(pD$fs?~ z(HD>`r1Ph~ie)<=dv+1S8J^U3&#V*u^{9mV^C!GUGNt)iOL$I8HJnXda^p04iw71| z`!)=nTcLUY8D=3xK_%SWKJp} zERehaQ|YKv)yrz*y9N=rwdWjni3D3VTKqH~?+dQ+DFkX)Mg%W96~vjI(>k%;229nn z{>I-U?`S6`1fF76FfxTroZ^f}oj#z)8tR%Tg}X-yLHfD1pu#uKjuv`Limg2i81l34 z+Ox}KYiDV7(Db&iE}$K)2hfFIJ6~~r_U(SsTw0f8^jRY7;V=-c5}o#|8=7H#UOLXJ zNHz}r^=K@!YZh}H{Ojmf15CvK*3iY1c+({4g&(42SGMl_HQ-FXnPvlp5Nl7r$Z`1` zxTo0`y3DCe_XM9a-I$Iiq`l56^+7nZ|Ioa2{5pfS@cV$MvNP?(xuqWdU@S6RDl--%9*b4^kk*~=nr-^L(i82vDv()Qu@mJ$wC7S??s*7PzGS$vw+@MSTNXG=yB4zlPJ?w^jV%dV@Pn?zG{3#G zx!Y?p4okJA<>~#k8zno?3pb%UB~>q-6G_;mGxf-ViYp-{N&#DK^}Yk$`{YyRJ*toT z^NOV203*n1Zy_UdPj#q}rW+lxu<62{{q5Q{`4}m&m&*SIfV#b}w@SMt+-Rf{oyPTH z|F9b>6Q=iL9fJlroozqqioDb1_f+lOP+F3!1F#wo%Nw=dC#)8;U!k-oI)?@m@!Y2$#z4E%z z`e-wX)bcvG#@U98%s8kQuY)MSWpb+j?y!A&5x~X&Rh@CJ zx)*~}jm7(!O%~PIc*rfYuewo|GD(*}t5A6Ce@c2c6g-ptIs(57^uidz7S;r!VMv>-$*UU?qEWh8(CIA+5@#ZecZ8AT(kN`RYArC1KvWm{78sl(`k*W$gMP&1jxieM4(%Lpzpn#y7Av zKdMX@CaA+k7zQu4B@Q0ia1}^Qh-;H_EgFd$)dKLj!z0(HN#{@6X%KZ#Qyg6-Z}~;% z_mATBHm7OQT1~E|(L0NQESB7fXh^I^x2e}N`agCC`F zmsrof?B;pq_oKB$U<)ryx}%cJ#BMse(c|=P#$wnj5`XG`;FI%TB-@lriXB^m;*~Sm zk8h=AVQ^;qIXkmJL}B2m+w;n5O7uW%Ho3&F90cLMRV9DdhuT@AGv(4gA zfV9T~9+Ulx&1poLw|zYhP+BStCXGA-6Bh>;!+torRM#twE##kjIXvaRz2mL-7O%SL z7Toc+Dxxw(gs$K)EqB+56C35&Ad+uWqFtj2VpH0mEqeb=NKh|qe@!sL@vS-9PRYp3 z%b?TRmJqP(lz5x*MtigvGo!--j%9O_r9{3X=jt~-s=V2c#2RTl7!MuTlH9VWXet(u zak{Vr``smD$?MC1 zJhA*5kzf2lOZ27tb3b4*AWX{&2mE%{a?Xkun=}4n0MuL?HR7b7W0ql6-(}u+7Bhy| zY?OtNE|m$FOUNQ1lLb50zH!!TDX>#S{*ugC_L3+G;l$ucRz!Z^oLh;oH=Wz)`D7*& z8$^e)(diV!&uxSdyITsN%fatRBc2^IsacnPvM#G;MpM{{u&a_&M8**}b3AJ)Y@8*t0U^2ywP2+S~oq~2{QV4hz4t|HRIH^62~ZkK>r zHfWi&8jnZwu8}Ku;9QYyE6Vk81xS``$dFjShcY>9aj!#u7athz;_0=#!jp7yDxGH| zEliwWe-;z6`=zFG_;-(jIn*pov3c9+*3WN3h2Hlisu(A0^6()tQZ17V?ALTmQbXb`CqEwnyA}JU2q=!GRBql4YH=A(2vc1o7}6a43Nf;8Fl`yW}xax zG;jyq%pQ=|=;@M*g$3pyvT6Kfpo>}&XGs3&5G#aU`}#?UOi-@&J$Z`Rg0Q*4nNdNm z?rY1XH!@oZLJ%AlPqY(rjPGn8*PcPH*L~lYi1evWXrhU=RjC-uMgoGWOTB~jQCh7U8C;}@!t$vD`>K*nXz*fkzr;h~LO~Sk zvh_jx&JWX0ZMG?kEw$O)L2geiIqKK0Jm5d|CmCQ%5|Kb#h26Peh!CWTeS%H7!}OQ43Qewr>JT^2?8{Mi~}QCVyeFr;@w-(oAS5 z4+<*E%bz?@ZaJ1VGBLr()&XHT+#Xw}Sw1<^bbEd&08+AH>_@kE4pk!)%>?RrG=J{s zVq*xtQ6cS~Uo1NB$5-f?gpue!?|orsJ2v|jAeCMgK2w$ijGoh1wVk>QYmd?5}_ed=wcCDGwAR81;UB3X>cSh8&)%FrD{vohjP#a zRZBrPvs@Vc0BeiosyN0{=5xVIHQVelaZfuk;|Ac*`&Fg>!oEBHmCqkHcX0jhANqHw z;ib~rl*w-&VWrI_q;gYP;vMPsIzs`Wy)SbR4H`32gW&2??I^$7Q&SI0yC048i0O1a zzU`nX^R|<(*#9SUY6rVQ4&n1pG8)}9;)62{K{2BZ?NRw0Y%28(_f|lxrqV`Yf2k>5 zkmp0Wb3jYOqYxi%DFmbTBDY5Gu5t|EZoZOo>f`Y`vLK98AU^1{PK@ge?nvtkWQ4an z4duOx(@v3xpJBm=keMg!6cx65%+<>lQt|6;%`#eiQLgx7PVAN9ej@z`mHF@D(6ltG zlMjsB{bRh}71cET0oviE5PBqFh>)CrUu%3$Lc*)?20YFWisCf4z zahIRQ$?eoy)`<nWYBNv+JMoEGZVY=1A}0nH^R zWoa;McXI*kn_~5VXkeTuZ>TXvT`xXt;LOkf0W*v4^v#kZ0x*Neo>FfsaJ$%Py|7?#+EO+lt!Q~VO944&EcIGu^ZydM@g4?f4M9c6`iqWb2nUjsHcXIqiDC9sb?TnJTb8+gkJ)_6 z4=^GU%^QbFm1WAuRgPeLgk-5^TNXqwq zTburM1@6Xn{R$21v#eN@<2DJi1(Zt^Sf1xjrjp%SQ@`DX`jdXWJ_)xXL-vi(9JLcE z%Zopmll9VWke?qoL^Q)u*}mD&$nGuFWT^kV^mt0~o#y%F460dxLMuyJBR#Gs;2vFr z2xhlm+&s#hiFm{0@g;SR!^8*Q(C{V< zIU-SATizFrrS6Wccw{CD%Hr6)0d)aAlzF}Zbuh!)G>-|4Xg_k>$`3)}Q$WfWi21^| zjz0V=qgit0@IoN4@~d8|@-F#9uTOfXZJ7Wb2J~(Bk__{9=WC?Iv#0!bb|9TkzO;VA zd@{JVJ9vjhFx~G&4ODb-?VJ*J$=T_PMtGh6@Y$S;*n|XE&L9K^=2ZZ5aJdYCR&I{G zCv>tHvQ=3q&}EMVk&R`#SY@!eNFhE)od$REEd0cnUkl@#cyft= zv*-=iityDvR{r7I!AJ>f5{vzIML=%)b@XB@j!tzjJM z^zG<15?FB`(O}z zI69M&Gb7cAZh`kz{0=Ln%X%=O`Yox7=M2CT;`ekPrIeONeM)nQ*t?y+a4wS&mEr5I z^wXn)h3&_WCEY&wr(0mrO$zZ$U}2=m>|?(FJ;9=6A5~3eRJp{1M@%~i`DoX7PHCo5 zUC+8^j}k^Ze@c@|lusEF#H5|anhP$bjLZ}S2HrQ4pwEx0VSlB*-?b2Wp&CTT`1@Vm zL`um^iT00vi9|PdGRXPJ%p5eAknlf1m3JeD?=vGwnjPxufmOfjZTPQGm=XzS%-Rcw zfA;zc#m_7T3qtw*DLukJ*f)$fTdAL)0X|*Up|=d~Hz#^vchg`#aFbf_m(xqyv#}0$ z<|QUWY-=@}@4|$8wPyE0ZCk5`aJ#odX4`Q@sY3eY2DcWCO*!OhRp?LM?BCt~dlj7Z z-~4(0zun{pHBfR#i8atY6?=kA2;~jixK-J5)`s$BitQ=ldrC5q{yhEW#`+nVt|Az) z(Jo!aXc$wn219@R75*uzg{9K2BpLdq&hhiB_hkIYn)8>x-gd>Ko^GQ>ev!w&CS{~k zlL_tY&%po)SyzeKf=5_(MQX6^4-LWvUa@8JZNgA_(q`UHo!c8dVBs#)9)Z{gduo&J z<%P=~Sd89OF#!6Cd{;r%6cm$c+}~gG7@BOw1SNH=zBJNyd}{wTR7XTQA}U`juz9mU z&Tgxi7sbJ74LlXW+qtio6}2Ar&Eea}CV|#=3iEF@v{VU8?Aqco6((Rq$HYy#jopfO zr8a4r7ct_+5lsH}Q|fi%P7A~XJslp7RMuZf6v+8mapHzS&1{WXechT+@ZGf4nYAiX z+1$^AKniD*=XW%43Jr~)JXPz-_-K=jK+t=vtOPRs%`(GoyN9y#E|d?*2&-iB4TS)V z*bRd`(#I)s0>_Q=MU{(5ureRojoF_!t7QnToU}X4*^8~kQ;1I)rj{-xk3)%Q{03{8 zVdlVn<#4JyvnP58U>yQbAgy8M?){vj187L|eDYc8aAD&*aZfN67?SD*K9mff%TpfO zjBw*+{@T~A_i3ql+(7pmqTXv4mt>{BImmxKDL}Eje9i6O)>OjjZ22`47L&#GZRYQnM`b^;q>&)WL#=|&%z;%<)Sf^DL`nwnJdfR8CrK84 zSH4qY^{fjxIXdsS@kb3P_#tf|H?KMif&}V3W`&QZD&4+>@0f;IC+$zWX6b43=F<@lZM4t7x^y((!JRJ;I^TSuJ0?JnuLd(%4qS$G3OCPEAvKw_bzM>$-drrl={_ z<(M{stII@Qy7LC$85^SxT~WX&xcIUdb$y7qEaM{US*BC?4FDh(ybD^xHxD{YTW=qd zzCBxI={V^3GR;}CTeA=de60@{6ELp%v**$c^-!}|pPX9Gj|Xe(EL0A<(_{HKEu@O* zsXS+D_R4Z^IN7{*6^f$7I@CJ~X~{I9T*QjA^#{5XR{pWxIGNU)^W0Rku+)xh85>R& zI^is>Vh$3D8+s9Dz-hAjER1#FC)uNbvyZ*j1fH#JG6>c@fgIx`DjbUML|IqXdN{`F4HZjpC2O? zoxn};92-;$x0(=H0w5g2L1kShmU*q|SKP5xs~{A2EM|hkHe>%`U)dVrDpp{lfe5S% zf4~%2sl;$|`FaWpMveJbiub4s4}f4R4^-G;b-Z1OT5vw_=Cs~Vp}Pl1s$WDm z`xkB`=G8fx_2avX&lmLDEf>*xbDOuURtm736VS$f$(HHmM6eVR&;cgaepUJ5@%}OI zyN8ozs7*G$0WvW=$)#el)-_zytpSegrlB~nl^I`GoEl1!q1X1%60#mSU%UL{7c}eV_fziD4x4=Izt~~HPf)yI zFC)*i6q|W805ze{@ayy*9hy>@HE?1Fr_>ESgr7|K-&#Nbn1`h70MeEv?1PRA=F-uP zcG22rpE8Fo014_;LcZ92+W=QQV)4D);GD@+-Od$4%@)J1fTEn^*Up;ug7fpN;XYIV zZhaH+it%Oo4suYUxK_+&SKdr-2SEBL`*6czH>d8AKT?LGqG^-SjtL48V?|LX$Ouw= zQQTy0>E~rugZz5<(s1_r8%h>qo_FpNP-~D)pC0wViJHKOLYm(jg3p9Lq8N?ESE)6( z~P#^TMggp&N-*w6^c`5@Xxr?}V>E6ZY?d9Lr z5j5Dhh@z_Ufa0dH?jpT$>_>gTs`yPV}ENezZ0##N z+5MqictbXrM4Rqx7bg0I-Oq3K(!7>nK$&}2qrAqdpJ3*XBU_iD&mpIjf?gV z{O6c}T`!e-EG!&j)_=xhVs0i3thnD;T&(`DR$)-u?$uE}tps3rj;e{;oSYn;)6ZCQ zMMF;B;o3q*Tssoc#OJ@t-lBZf4X{TR-em_;`nLy*##pzc6v#A2@L9V!OnLu&$RQ`* z!8L-aP01O0)BGUAHjU=_6Hp-Md*osk>+G;#Q~I=7$$58W)HmUB=wZ*k;HhxJH=xgpP%5n~y5_m(0(~br1`5wK^Zc@9U z^m&YlEX|tW{rTZZIi9OHBB7 zl}((h80~=@c8e<#TLQcKo5zU(?h^PptSw1jGeIDmNADNniyx>~8W5^$5@oN1YLA?C z5A_$XlkVmJa_p%}cI)rQY%0xcgKJb9TOr7zblbbXkC)hlAYMP7fR?zA@U(49Ku%;g z&-vd2CrB&U_4)V+>mIR7SVzfkSVvmc9+5%UATp0Gvu~GAveXjeZ1X!)PI~E2GDU$X z4nJjQLn4fUBo@if4#Nkh99W3qFIlW2DLy9SLW^2}ulXBKsx`S*CPg1)XH?>0y$x0U z^(M%)8&Eo-bDkjTU?qgN*sEgFg}+m=^$1Rh&QUG+7Dq>3PuNnWAMOCJvzkX)q(7_{ z2EGfM8J=0w>*)G*8PeMr5|@Ck{-Bf`(1gLq|d?`4_z-fydg<%z_4kez_H0% z2Vxd##){$!tyf-p@$C*>i;8*vWe_fT5<|ihzB@<1G!(>7n9^)?_SCNYBNZnFem6`ns!c&<( zbG`=5PUQep3aqDY`fxQhG#;pbLh(OtFP&O3qK;mUVjR}-E48C|5j8JK@E{>oC}z4!uF_FQtJT9watB9WR&^w_ChSpE#;D2 zmn!?W4OiuWHQvi4^a7v|{-|4G6pf=GbV^r(XA3|+x1)C(ftUjg)5!;V^N%35 zvnh1$BxK3SG`L$Y9mYlL_PzJTQn^yVf@`f!Koqvx$?JXnz!%=OmmJ`E0LNwq)PsLP zCg*8gqCVcxkb2J2j85#h%U`M@mCz%Fab(nqi8>@+uc?9fa?GluRk4OFjpPCd=f?^V zPb6!YLT2h7^Sl?fY~q-Z65e86%(Me3Y|)99YTbL{fy3Bp>A9I=d_>N1y(06HINR#x z5iDMv9~Nj|KT>_KFKpVfj=5o28mU>g$uZ;Lb#o4=!ofyW5c1VhRHDjos7TS)SAwDg z)&uL-_vGqzaX;_5wT(q7SaUy_-f`DyhJAT6YL{3@8QEtl20mm$1pjkv8-gG6+Hyx> zkK^4&BF{#HylnGr-D3!goeT#fR>x{Wb&4un`y8cuO1nc{r4W2~vao1_4*J&o9glGu+(q%1CgIiXnU(nYVOOof!7K3JcSis2bwt`RnvfcE>hL6xgc?d z@F^DH=>Wv+B`6WXwRngjDRgwjnKvgJVe4|wnS|FFdDT!zFohyBYgL>`uK-F>-QtMs zQI~-Bnji5JVwANXe^YWIEH~<2>Vk4R$%J(;Fj$lh=Q8vwoH%Mo+~=QzjR)z|CdUqWLzL^8OZFj6R-WsZoA4oV{5;=xqZeJ2P_~=SLOjLM8xfV(8=E)=l z$EPrK!|bCqCh;Va@|kwDOf+|4U@LH7kc#ekC{RrL$!5aoyixc~6#&>M=wK!dln41j z=YEfc1OHUfwJ15tm>oTf3gf12q{z85W61&CT_X*6Zn2OcA|S%&Fg{gW{5gg@)729Z z{KRHB-?~;s+(3BPv=)Q3p5NYNN!+R752GVWUiznzre#ChI~B4zV&HBh1P8}^zjVR} zb0QiJZEu0TUhyvGGg6qkEQM1PQ7tZgk5}ztqM)s6g|DKcEXxU7RQ-~fG8rAU8;!dV zW(=62XuvZzMk`ZRSQ#+`5d0Xe_uu9-CY(Kx$Ti?Kt6FcbZfEv-)^J2dxlRUX>*?!3 z;-1yoK!B0o>ZCaUK>3zhxs7L4#GRbh1hRB}jRyh2mq^;}#U^i+H`AzqEGHfe4uOYZch6A*g z`RMsR@^xGdjdo2(-GNI0STy2KX^Z~7ze-!45-s~&*2N@i+hS+|^Uim&&c$Ex zAt;4jffw`N@qO!&9|v~y$SB++Dy%ao%c(4VH48MQY7K0;50RktU3x(tKbXKCWxXgA z9if6@WG*Wk>TUfxUnl9Mh_94QCAaW-DYCVuF#>1I6i z3<7-cQqCQ#v%LbkBcnP*FpdXlHw?_pal9=GVg2Z?P9Dx+ zv=%$NJtHy~x;2l+Bil_NRrfoMm?zP{8-ueMU|QR*+j-$Rpgt|wl5U}_`sJ12T|}_l zRo%<{{Qq(nz#-wAG(%CK%P zN3?EY*u5BJ29%WC4rzPT1Cn%t&r4uESwcg@OyFtyzK&`$bi9Zm;f?#74$|v!Ne2-` z7o2JZ8bUzeuv9~7aN3QJl=mAs4)7G zdcVR;<+n#=jI*8+*;*GCL{D)HfWJna)@;L;+iz#EVhO7*`ItRc8l@j*;e-TnGEgMD z&#Lk5pQ(totmej=4(ocJ7;*Gq_`XF`+pMGu14?n`&(!CNH#oYB#yIX}0*#EcOu zw0!8RLxb9*+GNyHn!4$-5=nV_-QFBpxVx%aY;kc}9is^rhUshSHF62u)H~))Misd= z{9Wv#fV?Vp>6U)bCVTrc4DBdNvT$~G=Inv@U_#tgi6kxvDtI~27<`(vt~^KX&rPCC zGpTN*n!wt?{phI7zjaU`awH?jLg;(&r1gl@VQ^?IhnL6Y08@JD`(cj+&t;#ENRP)6 zofkKIPMH(u>$_6Y2xDJ1&Is~5bZ%X}x@0|;*4~j6e}0oozKCT&UL4YBp$^FhaSg)U zn;!4mlf>2YO{O#h=Wld3xwgd$IaU)_y4I-@dZ7(@MV0^OiPQO;$bU3x=gC>q zUWc7Oy=Ejm*msoc^#L`2RI&USKnmk>*Wp4C-Gv~)er3f#8AM_K9C^^h&`qQi9U}a* z>{O}zwL&IIJISyV^R)Eh9#>*;=9^J@e5CTB3n^}Be`W(6V8~&@JoxJLR8%3m(bsz=hvB$c}*2uP8y_Zr{VI29kv=C$2jcyey0@@KO9vrtuOGU zGYSK*>6if{O5ZvZZAvscJFw4i49)E!FreqL>s_%;Vnv+a)eHdvLxCCM z7En}#7GOYj`N7_XwOo{Mt22z?wLJD;rMg<8v|`Nh1I`X*t3$Wz7=v_CJhFl>fyp8G zC3gC6n)f}}hl3hHr6@XMyOnoX8Z4Ya&=Ktg12Nr&VDgK+VY9(Emh}8&85xwLJfz)= zCQaLadM!CQ&PU>@IL|d3qb`s}bq7A)qCev^?$q;MIbsacSwAY=owDL)M(+PAF^oS8 zL!JMh6#?h}K0M=k$gu>35H>X=Wjn|fe0ly4SqfX<(FZPwb`M;m~&0F~nFY8goI6MR>m!!~7K2s#(&;Qs{{=@l0owWVUs$3+x!)>>A z)6o;Z2f6!>+aSz2-c$>SuLjs{q98uNhicZ}QMTFt8>7bMqx^rL>HB|qPxXKFaFPE; za+&udsdi`fmC@jQJ&wY*;9$$@b%&_fvg$2fiil*sH z`h>8GAQ9@jnQ+YKhkNRCH5=-}lfZtB4%n{=Yq8A8C&%D_1qjX+WX-FKH~JCQ?x8B9AN@MH>qWQTr`Q5`YJ zlU0X}-JQAu*OYi*Qev{wXf^&6b5+HCb;n(bE0TqM;7b(JruDVsoTgBsTIoth?*q;@RhpGa_z4!=XNIQoXOgspq0uFtQaWcHD@J zHtA`)<&EcMO1XBEP_5ktKytVM1o*eNmWpel#Ebhw&HXn%lxM1|fa2uPP+6FO1py%S0RAwYlt5ds7V;oIz5>Gk%oVNAe8JYiZnHo5k4Gc;AGYqHxx z09~r-E`~I~ENZdh#r4Zx?KR|}{&y26W)@aOCfW;bO8kyf!-3lJXEfk6RNsW68Z?u6Ye!m1lJ)6b)ZY;q0wvv`3l<1EN} zM*D9lWeQ8{e7N-!Pz5pM5PHM^1%?uC1j70+Qn#hX=WgjPe!K5z@iwB`T5N8+a)7}* z^kp~Hv(*o;lgCU(YzDpqxW78&M@Q9k_+lc{R%UUPCMZAzB9M`Ki} zk?fAfmpdxSU?5kAU1T)nsA;u+^V)cP5i?DHM-farpra-oIZim#{a`S4+jmi6>Dz78 zcKr#JtxCg_BP+_#sQv!jBbHYVIbz~*v*y0dDSL?G%GGmyPP_)f`Z zv3x2}rMH9B_yT;sDP8w!l8Ao>G&@l@eQ1NF;ss0s|T z1tFxXV?We~Xak3v?5&qSuMxTICF&y6pL=%HhxGK+(;3qj6UcB1ZjnkHNv=h`5AffI zk41+nrgr%LeIh^tpJ0>EPx6{-1AhqB#JuC`GT1f~Zy)KkJWmN%6e)0{nh34iHnN?z zD~y)DdOrnX5kg;l88RY!VOu) zOa^i1rrLRLJJLuyUlNi>!abWEqc4iM&C1!*(|RRS_ZXESS@=FGF-PM~P}mInE3D7&T|U%D~Z2qu>w zpe5%TeyXbu&tG$vB5rz*ZXG+cw?K#Tp?)R#q3Vmf0~HP+?-_@yT*GXy4M)#%l-%uU^7Yl0oxPGyp7L1ljHGQt;f^(}L;@)n|EOq<6h~+v0#bQ{oGx zr{ua{u9z(C)z%6*R>Q9i_y3$MsvfiAEZ_^gnBW6h8-2OpFvGvPf6s-CEDdhOEuITW zRuZ8;MNxc6_Hplt7#+Jk1gZ2;67>(C$O%(@wS+Uas#Q>TvAcTsIBbDy!IO&c2Z}fc zcER`{YcK(L{{8_8<`81~LG-cUy-xD9drIPQ--XsCjBj?pO9A=~3{@P?#GQBkkw^&_ zk4Z1jP}O08RViTX?vM*r^W6I_l}jNGlICt7)3Z=sU167#;F0P0F|hqR@-IVa9=V7c`$rDA4{g#sC< z4bpaP?X}b?=4OsA8oG<82seq>nA}Ru>M*MrY#wCkGt#TacO~Z#AG5-4s!F;Ss}LB= zSs}s&*KgxKJw`IM+Sr!5SJ$TlgTy{gbN%an!?y6&kQ1;bo$~a=P{ChEKCD(6E#Jp! zyhr9-E{g&nJc*ojuevcyM-(<=$R?CNfvQ*_L@YjPIbjv%ca3OvM6Vd2>&HhL^=pAv zZq&beHRd4T@SuF-Itd&SQri+>wiZ+*BtL*I!R5fKahxSXhbp@|>l0UMp4v!-v_r}h z3)_Uf3)mXKuo3Q9px$9SMpQAtk>e0swWrTyW@Q4ly- zjxEl@aBbvr2IHKpyrsI^?NM{h&_8G+A&ka;e##}J&+bweTRTR`Hkg6q&VmI?I1gLy=eWb|b% zuiaa#ey+a8N{@#`?bFqEAZA}y6Egnh+KV!8sm1)tJwVR&NND`FSOry4?X&XNZsn_q z$e%?U6vh@}$3e;BJnnSOOSd=l_beZrJHKUTX^;AI!=y`bgY=q{+Z02r(dQCqN`4cx zXDyUZ?pqC@2|s>Q!O$c9XrcV&XysHs70L+K?Mt3A^ z)|1ZHX(M5UqVTGu*K+9`yfv9q-i1}c#re|I{4^V6$=Jhc;MdigV@pN1;gwSmyQc$3 zS92U@GcLx^8`}HdKel*cRUJ|P)8L+kFZE%Iv%Kq@iCpb=98-h?H$F$oI zuE;|4vcxN+ur}v?f?5isW7lyx3za#XsOh`Ic=}*Lc|~A9n`WK`iP1h|=w+c1ZYpN8 z=c%O#3o)v!&slfv^qBqrG)m`A@ko)mpeQrvZ~z0#LDMo9^(rPyF^u-Xo~A2E&d&{D zY@D{NXQ{%V8fz;xS-K0>cZ9*8V9f$1#e>Gmeye-jiFM<-{4;W5vA&3L@f*kf(Wq+c zarg4GmRG91u(W2OURzk*KdlkdF?vFAluh)ig|E}MOfl2@jRw^Ql7^M^;KtjgS-6M4 zU>3q=4YDSwYihtx*2SjQlj6sK0(qgd=IJ#DeGSjw zg=0TZ#Md&+KolGLV3tinJ;I5M6)E3H&tvQCXE|ifQkCT{JG#AfbG<7MbJBHB&@4iu z0-iV5k{6r9>HLr{_@ee(n6R(a{m$^9p;`@Q9z(mT+K4Mvsmm%^L#whAT}}4^`DIU} zJr7!p#M*vEw^2=#s)J|Zqa3>1FDPZa*?m$M({sVi&6MHjAO9&G@@X^&+Y7_@ottgf zp}Wg1DZj-xGf4O{*FWkT$^xIvKVfga=>JdgjpVpp@GpF0@^c}aR>M>Dt7qN|P~v!9 z{5aE6bV~XPDxiQsjd4-gzQ}U8p70CskRgc|&;MLJ?=Zb>q)0q1kY}8Fbh{=ZK;~S= zK$`S5YAhUPG>WZX&md^Hr!6+Tq}t=AB*6^%rs_Dk_>~?1$48TeMX138Ma!176di5m z`e9b*9x9FI<+6!w+Jwx$$jGfg4%T6U6&{)%U7ZG7vtl^-OXr(6dt3KF-ufO$dDUNj zI~^e9+EOQDO6EB{v*nFT$CF_P(DQw*alMRBQO5y!gvp@k+3}63pyk|Bc1ws8-KRO% zm_5owqWz;ywWbe%$0vfjBuC+dN;aWzd&*8~`e%uD->8UQ0oQu;l}0wA?5xAB|o61-dMI*y-O=>V&J-3x`505+8Ku#u)-RtcU&kYr;dd zS8~=cnQ<*g@^o-2#DL*o6EU7ydC1lK@9@jA*H7OJ|1uDzkaHsAlW8g(4KM2}S`b|{ z)Jp)Laif!<7th(_?-7vh4arRH&PqSaGEzEdgD+5Ev3!ouB7w-#z!Q`o>rcv)2i{|8 z2}fy0r&oxbbh(=%pAg?b4L82}DUv4QtK8K?B?YO$hK^Q6J$3;SQ-L~MBg6-jk(i>5 z>RFGq6heJz9^Jfr5fEAyqYvd~xV3ykHA@eNp4@MEt7!L&`Cob21KDZt>?`<1<>#?$ z2J{otuwRy~H(Q0s)B#4h*4@{1^+TpHwPDpIysir6Ol{ZHh3b?{Z zL2}Q-wacQD1Zt5~hj@DimApF{HlF~5n0eeu< zx@K9(P0!*+XM7qaBN@7go-l#GrSlGXVYOzgrM^T-^2ksuVMMZpYts~F+CkCBih3I}L!5TI%TjO6leb=OA+!&~&-Z9pS@Sd@ zC;XHPQL<52sHx-?CX#tfWNJirK<##KvVasD6Ju4dY0R7JgQN?8l;wF%#sR4KPE6P7 z{|(=9{9o`Lk6_mMm!G&>hy9sNgv$O8AP+27+i>UQ#fST8YJZ4ZuO3nI@|Mun!+SsG zzVB656yr8xW1Q{md?~8y&snydGm5X6$jn$s5z32Qd)PG)CeMM@gz8L4j`a7RUA~hW zd>2!9!3+|tA!j=>@j%=sxF35l$EJxDnO|B-6h8IULG+!@^h#{|*9%==kevL9{|5dT zW8P)5od!wAuD(3dTP7aW-B+C%M1O4lYUIIwT`?hlvC29+|359HCyNodiM9Z#lbFDZ zV^Q5nP$lM$1S(urT#2K#y916qf?ms{2B-H^;|V1!x@^g-4^B__`ngasi`QCw3M}jI zFld0D@L2I3u(3JcwY-y`)i3zvmdsE3tDi4w{LOAM_~_5CZU6F(fAiSuoYBS4Rvfo3 z)((o@sK5TjaOd_{{emx&ALS3@!mi|){!5S_&;X#wH^^5lCTJf*USbmbBM9^B59W>r z%7MMd$^}p@F78S=Bv157` z(JL?$$y%wiGKA5eS#5r|XYHa$1_bQ^xn5|U?m3%*LL;?ei1dDW?c3q8Lzj|5gdz|( znrH1S0&~maJcyvJB{~}m6NqQkg@<}6WyBBC?)ll8rl+U#1)bR-wFBO7&Af`LxgP;Z z9~8lH(&68DimNokRU_zBYwH0fvusjrQi%#cp40NDeNJdi#g|#6d#{QWcMf_04!g&9 zMThk~V0uhVqqgQ2&Sjcy-t?D+JL=uH$c9^!OoGlI#y<_F&#_#6eRc7IJOf=?fzvgo z(U)_=@5BX-oGtDbIZ1Ep(Mj(xY#P>F-Kfo0B*8izsyI`?mJ{-X@n_wijHt<unn3!q90(@miJk_p$q?GwGo&C%%(NDt1Iii(vS zlURCBg0$p>w)5_RuITK|V-*_3KKv{ts#lj80Yhg26>7CTAwW)PliYTb;(S|HRBq$k zXJwF*mtxrt(^Q()6@vtyq)uPStLz`AHEie$yj*b{&iJT{l=m{X%;I$9d<7V#d0&@H z&_wPpI3?g|aoo%$vg;2Det6BbiBxZWeU!MTx-rg%?tB%RK=Cw+6#==*2}@YTZhrK0C!;i3&%Acc9sned-{xr$TkQFM$)y^jg`)yJ>X z*4l+DP7oq2V{w495{31ylp{@g3zBSj{XbUR&fl5gE%uai+3K#LaleL;xkS>tEI(4c zd(d56yU!++za2myF6K7&BA5rfa20(qPo?Fix5dI1wI&Gsl+Z{+s7!X*c{;G;X!d?v zdfi`A&BGOKqEovPAwPnwSB0x(ljzlRU83muXV2So3%QMeGEnlmE#EWDbiN-NZOA(3 znYUVTI4}P$&UIttIoaQpx%jIx3*6pMjVVurWYWOb4FacEp9Vks=Jsck$+^J1;%2nS z@2W`fH3G;JHJbW5DM+m@nxvmBxd=N?#HM650X4j3>gz9+)s$B_Uv3Lrr~!r;pXzGD6<3+uMEgADEs{Q!@n%SI$!bpbHxld0-&*qYy*F$= zU{g)heLmVd(SOZNF*t>ZdrqV~TOnP!JBpg1!amNVC8?mk>7N>s+{lGxmP8GX1b94k z2qI(;tgwV0x65bP95OZKUrT-c3`Y=sXSwsvGH++B5iRIF+*vcI_$bomI2-iJN9TRv zhmiQ^!0T7;Ff$2EW(mJ8*JZ3^9OVy$ww>5SYE|v#gk=lny^FT^Mt~VIMJ{xny-W@V zU42^xv-Bae8t;kC#dnz?Rf(LAHM|22?03DczP?}fcS$?EQ_i$n!ZOQG)-&En<2XaV zi^!c*vi3R1xRKdOUh~AoVHgFNd|H>)bm6)f&%8lNJPG^^qUZ7TrZv>gb!;gW4Et25 zZ|~y7k4i7;)q)XurSt;RjOOf4{|Y>5x8~C9jA8HBy9Cmvsp;tt8z=U2C+cNDpPaa# zwoUR9XQD0E*RGSXJf5Akr@`Aj4cu|y(4T;9FxSjBLszVl|EAbYzmS2h+$N8p)b$4T z2LT^GsV_?FO=0%@0b1Kyb20hD{CfK|W{69jf;O)C856|S29m+{iYusMFlR9e-v8J# zz3c+P*Gx{KvBji_@@JHP*WN>C0P)kiM-#Ncxn3#QhsAO%)%UwdZCea=wzdQs>vD4Y zWb@3s!&H})CO);WSRsj@iFpcq_&u?E>q%&t+vpQ@uZGB}Y~|qBF9}gB{oz^LWmgs} znhY*hy=sYQ9qmyuixHok^FP`m!1XlBR}MZZ9Fs0pkS%IiwI?9 zCr#gQhoo0te~pq{AfzL1$aq1bxN5J&2{BtNCpBjd2Vhiu+t|f8A1mOY{nDp8axJgI|zaa?0fed?WWu{g6%U3q+fs~ z^Ay2`eLTeqM~S(VoVlE_+L$D_l*I$L6Pqe`#oQ}T_dbxow;8sO?%#zkG}7_B&#k^* z=diC?8na#CF`G67%HLeHfqtoK*esYZn6<2Hp3cht_)}c%j&~86&wKHeQV~Yx&pX}N zj3C!nqj$U=Prm6Nj&^HVJd7=~F;MW-ot`%kX16*BWpuk7{R&Z6HF=&GLrE7)D(%=U z7>?XR`d4ys$*3T5kqv^T|LU$u0JlCxNjbX611kLzC4}ul4BQnzU;5Z#=Ad*RRNgcemSZIb`fbX8xAtw)|mCZQl1oJbuUcM+(gH&b;OB$}8UJI?099N;PG7 zQ(E1*H{~~y9@QoByj_FdzZ)^sQXV~8@OE4w`HkP*k(b2JU+RGzDT`4u6kA=;0``wa z;(L)VhHq#bH_B%xC0vedo-|uXpO%AArSbSC8qMv7PGeJXb!WOd?9rkcWz;@6d5?+x zbIG%9tJ=MFO|GXK#^++#yf6La8!KJ$je32cSz|ZV7(y#la$A5%%ed-pFE2q7N~uuO zH(v_ulBlTq5X7zhN0~JunLble_~nzs45lb=p)ZEf2-eAZXiAc3vm7ejBrr{X=Gz-x zr;{nTs?*3-PT$y7>zwNX)kfKfp$}ynv_BpsXl3gOG~>-jDylx4-YTv9`2^yT0^KiC z8UjEMk55~lyxq+(*;$VzuTbXknwNx<&FIfX$E(Rr$Zze0HRPF93CpdIo_Cc#Z*G6+ zSnT`LnuFrQJV!4RP$skO#NVTf(O24Bxt3V2;|gHwa7Y#xqMIU%4kO+3ztQy9zNfG0 zm}lB;h%{v%r?vo}(rj-kb8cXGyQeKfr?fo;R7t)9+CXmTShQ z?LFvZ`5_kgVd1LE_6IZLB$3#@UD&<@&gLK-i@yn*qq?#ap(^hKIE2rgeFA7-#9m!u z8i~5O-CuHLf%lwatA~H(eK#YGCIElNM3LInK*-6(7@1!epZjWFHAGiu9;&snq`kd} zZ+Ju0_op_Qn{%O?*o(g}c`4;UQeW(ps)PDGN=I$0kC2g_dULXnX?h*pw z4ZZLFo@Zv>nKd*2yld8)vyhXs&)zxvo2{SgN`#tINUdGihp`TB{ooW2_h3K9MN?*n-a zx+4@6kxqFjaV;;C{R}Y&T6xdA#Wxe2WU^BatP>Sf{NSG%ubcpGsS`wo55NS-Ct}>b4t*q>nlwx~?e8>-0YL4Se zJ=7x2@K6&GNP*bZ+Ds|(Itt3^75lkZvxioRJvW!ERf8563JUb`fX9v=pMVMvkxA68 zas0Ods)LE(Fjc6s`t!gC$ii%g*J8vuvjqS9f1{k`3aA6hf*ZR(u zU!)Tjhn*29XxX3Jyt%j;I?&PnLHCmp;!he)5%_jKAof#UTq|Yq~Lr&J<59STZ9XWE)`q5g+RrM@z;Z>EMkSQl`zo1a= z?Y=U2Rt=K;BgOh`C;Da?tHZ}-#j(|xz@}*2r4OewD_VBSNmu&OFv&E>99UP3I2cep9pKhEIH1Y{}hl3#V`3oZgXoN^fbp3vS~kqEuO5 z_FCwu!OrEm6+%E|)q3WrUxNKiKfMrJ96zpdQAsSb9q>!B2cN}l5N}!tt8H-QMp|qV zPg%yiAs13rh787+-}RKGxgI`k{3+JCE0p|#L{Tx^L2_zX7j=FUxP8VWsTEou?K5(i zxXkP%pC=VufQ3cMG4BA$5*OM!)IUB9&l^x%vNmLPcFvHLSnRo3RN2(GJgJ~Vyf3cZ zsw$LG7!Qm1(R}R2s@}jV>?0VzI(>V@Lmp+gKGvyQF$BJ0GyKs2_M6aqZT&5+$t`|% z)O|j3H47S6mdtcKuxhoNo4@%cI*WZLaYc`YilEbkcaB~?jW5Yl*qfDbQO^!Xn^M(zu>{=AX(WAhny2vbLOJ@#U-cah7R6hMy%q>;LwQ} zMyHY$GLIraXCh(3)8D5Uhq90Rbb#OUY6RcmSr6p}M6q65vQ?YrDhC`Ua$Z61+>=%@ zy8}S*nbE7`tEObVxutjh6wVNO(ne1`KI4Lj88x1>q#ALz*HAh<%3j=Dp95!!Z9 zhhj^f)4OlZxw>y1V>`$w_<-htb>D|SUK&>Xl{egcWRQ0#i^ za4o>*+Atq`RlrT@0y5@xSLz2uP4nSM0Di>-iZ%J6Ir8{a6MYEm`{mbyWM!!WVY{xqx-;Ms5pO(UF&g&? zD0p7Yp?%B?(*~Br^Jcp&rAbrEZ`rNH&TBQFyPH*J;2wBW%#jT_^{f4cWmhuu`U3;y z!vjkmhoWK5abIEa>S3&y2bW!e2o*rI#obMfQ%Zyem6QIP>_|BV_YP}q&|`Xvm#|K1 zjJtU&8z0xnGt^oxvocnem>192yL4_AUNrv*gbIa2Hnbujah|pLPfE8Q2|6CWH_zpk zdzb#6^j+FjwH#Z2t+8d5*>?-d=OF~7mazUlL0GFO!aMv$xmcob;m!k++3#WS=A0$+fP zJaL?RM>VYiybfVSud4JSZk3vHY&UzqWyi1&l0z5@1*@Qpn&-r}H*6KEk2QT|Ga|1< z!i^PG)hqx^>s}|x1I=<1x}z%F5{PP8xC%$;l0}_^$%uJKe@eCU)zJ>US$0 z*k;GX))LKIWB|M2lmlIUr;(jX)g#)=M<4BEtL7KoC=@H_HtJ}!*h@d_ETChOCV(%x4MHQ@FFlv(d%ID%g=#7%i+5gkr-fcJ z4YxG8j*{3H5b>o8n(lD}-)V~Jv8UPsnC87s_$-Eu*0nxvDT|(yOWF>wZ;}AD6N(Er z-gH;KWCS0^!qx*7Y10FbgOw#=Sat`;$+PJ`98^Iurt^uDpP*?N#y@~xv~OAHJA$$b z&bYd(#?Uk=zp3-<4M~m6q>M`0i+Sua;57c=fo)qle>pHv7!Q4aWxhvFl(wgxKHT9w z>8&yA69st#ts>jATd0#C$#1|EL0h`z}=XeqmT`M^B^JdGHk(K=|ve+@wO%>?l!N z@QyMl@iwT_=kJhT^yO5!Ue-I4##p!qaiP zAr%1`duIAMLvmgm8)B4J9nBn4VG63lpfF9lic8l^Xc;g%^j-7-50uu#{I(jp-H2I4 zFVCy8N2_$;0D7Qu@!}i<1ty-@#TxeIFkh{T^3U6T{qb__21aOOU_^}Cmv&-h>h^Hd zQfR=GOXpTlD@3SnLCZI0A-JU_FuNMzKpc~7f;Qe~jT_*M0*sHc&3%AfD0Y<*u|er{_SCIi7(*p~Uw^tvgYvQ5^^4C>O4V{E))rpr zp?v81Fy7b-weyWozH%#TJXe`XdaG+!=Zo(TjY_G|dh&0Gtn3Yb(G(IiUO#`2C(y}r zOwCwBry26Nw97NM4XekMm*>SZKVK35dCjGPjg$1q67O)(U_7O;{TkYS@Yu?G&Fdy@ z1snqHcBUlkpv|TI2!5g$sIgtE;~#{gogWr`DblNL=W|M^ub|rfl1A){;MQh)(x7b3 zbSUu!O2#76VO|Oyg-Uxlsv)N*8(Kw0HQIeZgQ)jBf+jjE)nPqIwbo~q*d{q8JCwH! ztANCJL4$-}MY|x6CP>Wct?hf-V}kb1_rLlYwrVFdg|;5SqwNw81CJ~adz*`o4`=E@ z8+|g6XFQi)!C`qR{^%Y#*UEYU_!E6`jp{y&LiKSy&*qZ=lFEzKX)cCtMe&Towvya_ zT%Op|K^S#6zjdD)9zG}9mYe7fBkW5UB4`g}-+s$m-tX2v(n*QzYd3}FcBBwLR=s$h zW_wbW8Pu_M&IB#IfHJV3B}zFt!|ivM=^D!xKtS@&0?PZ3f(pcnXL>xDHU!Oun_r?1 zNgYgU@ZhN`NixtmO;6ksALqvlhjqQ7KFb`wEAd>qWyk$if94>EGJk<5h5qcNJOHNQ z*;7EWOMJe*pWC)5i*kL<@~u;LHX_T?e$w#8^6(t@^^Z+Z?wxaBBEj~;JS>Vq3F4Hb zSlcR=2f8_epN$;eh6ga?08eqYRS{6u4*8)zUm4;9(x-;?yPPX{YBqb5sQL|6^H!yw zEww@R@-5PguF{|AFrPuQ_oLjLaz0m}pI^aB9TJRWEq@D`u)BfBSPvfrkf73xUPk$N zU60+qf3Wi|5DYFzejzInM;Ylk>jmU-nufH zymLFEZE0=s91z*Q3EG2Hdx`6u3mwmS>mJql$r_%pDy{hLPdAUNZ;n<}MKEucHBJMc zc6;7gogZ+|i<3Pin*0^4QBQrV!nqvPfl5NVb}4vK^+++ut(X`M|1-O2rTrpdR>>61 z%gm(@gqikJ2b6F8+o|ct7u%?&76p7NqA2>^qW}c~dKFdX^oyH0Ht)%TdQccq3UYUc z!*htequi}kBHX=L(C?IP(Fo?P!iqYU91djgXwlrNWS`7nXTCc~?g}o9pH;?IzJi)Am13>^ z>EyLU#BfKet+NPMBhM7DR8K=dhghMA`uYR8STL#1(CCH;oRTtlRM=^P2fA=F1}fOT z-yPA2lKgIe#QX7%qW~+lH?c|QIJ&1pkm@qjA-0RQ=aFJKaT%0y_C#P2<6RiXOq=kt z{h1neCzl5v=FzAjE%5oZOTz*ow1UssV8XK>C)i&0%iE zh^g&^Gh^aL8#|F=GMMA_ga>-r$n3_u!>>3DS*-32DxH*afx{)psgB`(s^-@uYyoE; zp&L8NzzOYSR-Qxm)yuF|qnufba-6dZFiYl>}!3m)*~S~z!k<0or^4Nb0_{@I6bBz{bGM)z3eOR^O9hP%t& zI@{wSq{3Vi5bMnQpwkBxbF3Fg4ugX79guH@J1D*f!<}!rs{vztzfSat&uDKiI8sFv%+P|pid=sR3g7gy-ZP^6qZ-fgkV309 zw`|Z&Py}4G51iy|!~Q1;#jFK-ZLRj_eUVqzf(`x93I9!coB1~A@0+|Nekp#>#qN(d z%((1_|D2-yLX-Qi%n#}AA=~%Y%uP10-kVcSX6tK^-IpBqh_1LPnZ*Mj@F8-*uEZP# zr5P(}cdEw0^_vY_I}yC?Y^m~QnM1_us(YRQ?U)#uE+Gp z?k7~laIsx_#o{nc;5U?i&9JsloCd_(+SIEMlmT|I_RWU+u%l)D?M&fO5yzHos(CKI zs4T@6XK^!M%acL~6K8>EXv|SVw9Q2N2iEN8@H7o3^@{1d93kIN{h5R}b+yV$2`{WV z<6b1rYhRen{iRIQcBGyuA-+;b$~3I_zoSfq|4^n5K2;!hSjBs0b5kOZSHnhh2W*1D z4GkgLO_FGpC3-9G>Ru?m*gMJT7?GoRpGD>?oj0s(gWUE@R%q{)d4{B@FuJy{_zrj1 zG;3q;`&MYJ%S}eV1iMt2T`A!Wld47rbZVQ7@u4g13AH+g1S%bLX)7jqtsmF&s=36H zQAF)WXfopUr`IW$SaR9vq+?LK(o8OXsI0i^)$rZYZslHa%==jo#KM}~@_VP&$|EjY zWist|m%?MYkTjbci+f1K>Koi8QPSHdNyzt;Sb~M(A~XRTC)VDGV_-C;`FEpNc_R*K zDXKBQA%>5lR&mLLbU@AeZQSmohV3wIH<Y3?1~&cHI>e- zv*ic2Ug!FE6aBrxCdI%}Jh-Nv*89nAx zDBG7$7%}Quw71(g&!X->(y}<$4m!;xXP{i{ZYjCcZpUCGaS~^n(+u{W9BOF+TO1}q zXc&}|37ZAfcz-AKza@qApAa(F9Of&jNe1W?*Efri!V#;psE*nUyJkHBI(AVtdmkX$ zhcaDfE^k8{nd_5YXxmipCb<5V>Q}>NmpqOJKe2pUI^1f|@b)3^DQzCME)n!F?CvH5 zOxlNlSuAqk7li0uYX5<0Yw*yeR&n#zAhUh6Q?qKJITu3DH0X@>_SwuB zpFyVry`v^rFDPYy7Dj_#A0(XN!DjdwOmov-PXr{?q})dlljIIoGM=L!-KGxtv*X ztz;|VQq&n0IevuqUBozFQLQi8Dn=Jyv;TC%+GkN735ECF*%@WFr97cRuaYHaQjlxx zs?3aukehd>xEV&zN+xHyIUSCU{af8OV~XPPch>#U<& zKPDoTb>HGR_L8?&r5e8|WLwM)Q&rt=5Y|yY9F6I&W-Pnzcx+u%)vbaiecoX2N>m&kR} zh6-9ACY;k@*6Y_l1a(8Y&`TG6_7Ru47F5j5l0s1U$d z=r%xcvuggZ)#Wntia#0HxgN|D0O(P3L(>e^DkOn{uiN*J`B#-t-jv$b?ywuYv`88N~(S$5D zhisnc)9C?1>X$w&FeHyzA00Jc{XjA>;MrP9mFIkU)@unZ)>_i2=rJC=ApI28)uqBN zI!$Z)P`lWBS2MBxisgt_F@%Zd3#OhqL@|s2A@t=lC>-MND{|jCtYA_h6SG_AmEx)0CpTX$_#V?m(A&Rk84DF&O+-EY-ZvvG-jVaQ z_4=xft>WF@qRLBnhJMYG)3;sl^Dg{A=$3bOAIVT$F9r}|ekt?lpp^cj|$ZbCouz9?U z{>VQjHxZyY>l0S}>jSg0pPmbwKI-;q#-qti-HLk=gP%}Smn<-)g!i*QzI#DEX&3pI2^Gbwac{vkv;X*oQN{Ds|}d5M|0z>6efDHdDTKSadWhl>Mp zb};OBrB52zf8VHa^L_$VXDc&8{9+QVEqVj3PeGt3t|WGh+K-os+~EWF%G-En*}%=P@^bGvt#NI;@9 zH~%_=pmFoSjx_yjNxcUW_Z8VS#A+UuhcIe1C`gE=}Z`a_z0aE*<< z?>N!MO}`1_F2q?598Vv?>93!F$UD|J5f@=M3ylGCMkeytWC7a&S3-!D z+y2q#DQT!q;xyLX^WK=vblO3y=Zkf8ca=_>Ya(}6i>^=4yB{j(Pak$$ZyNtF-D#_n zs3M3^#r-z+vFRxKNEiti4&j5utnkt2pAHHu(g7SvxmeqmD-nldLUCLYqGbVlro73I zbl;rkng!ML^m**Jt#E%4q{3l4xH^yf`Mb(AENuRCbT>;Ft=(~Hc8~IZlA(rx~bUYh&M^Ly^l7|^T*ElX+V}>zE9m2B+sL`t( z@;vt3+Lu$~jw%rd2hG_In`em%qdU*8#Xx?9c_PHm*wPUbrEPw)XLPV^F zHStF6Yuh4Hw5>u!n8x((-NdpGytzB40NsT3-5jhT>S=nNvmc$m4WV#!&t;Vq zT*bYFO#gCI!DX)tz~}MP981uhhmH!kZo_Q!4MI@Yv}i{430lAhr@zi_CE&)Y5N%c~ zGM1SZGJ{_~Z%sV7KBV$}NbH1AxfHV$!hOvl4|UUw8y)(@Vm>&VC;dYr<~SCxJLvzR z4(P}Hh8602lbb(z;-*LQo?u>H+8z%V^G4CPa(!~{<-_sq^LqvRW+Hcbm>rs^f?Fod zMup@dwXdQ9*h#&>d?o*Mi@IrBslMq@x8>hqHCXH4NAbG3K{2(pSj= zLOWrGQQ@fWOpIrynG*;hs#PUA&Ovxp` z8@D3h^#bF&b@+5ef9^$s1PMp0AcK8yH*wY0S{@)__mzpUa8Xy6Q@g~!cc8E?Uo40h zu(q}e7ft5*g9B#H?C}4l@%L8*KK>6~5N+-O{ueuV@`oM#xzqIlp4Q(iEhtY|{yqO- z^x@HeGIRXDLKFXg@&8k96GZaFF21yaL%&fHo4Y1yH4flWqRq}i_V+_D6M*8HANIYn zveUl@?l}QjOD9Pei?9!!8lb-gqRjMop*Kv49w$te&A4Bm;R2i%a)f}N8Y#yT^E3rP z?Hb8{i~D{O2UMfAGuSf+metgLH5iz+>lr9DhOnPpOq$y=2XgSkg*_E}p-xH7YP&~c zke37Y%zzG%Hq&(TG{uq4o>$1fwv3P?7wtI_wzffS7UzO#9RJ>TzS(=1g2Jv%SS`j+ z15I{6_#U{-*3?Q=4AQnJ%KA0pu?N4z2>R!zkfl?dG5K{wnRJ3sum(f%>PI=6`HIMQ zS@4}v@6Q@wpFl;b(0h{t!lmSqwx8!KwbX-0BiYn@3Q$TP5DtX??(nMgQd)4AsCVGz z8lO(#g!*sMFZooCZ+GUHjek+`QH}Ta#0f@=82ql415ycR`=%6~S?Mh9*W z!=6xxLS6TPS()PnOmnjVbckDCf1m5fb}=~amo-_5DJqd{EcNT1GtCD2B_%(VgRno_ zJui)WvUYzYm=76Yej$=|dKKe6YwuE_6%HsjeXZ32OGP&5r&1fYaf=GjtI9 zp#M3JanFsQ<_~(^Ckl;l}!xZJO8(tFI^AGt4ZGU z>7E_KL5gtGR#n@Hi#$muUu-7->m*7*Bo#8$YyGHT*DUe#`oJAgtkyS+!g-pow+Dqj zF%8agZ4ff|^PMEojAT93f1g`U`Q(xI@o<5{)mg@XZdC``$L_=UkWT~bKG$mRqvz@x zwv|`?-7Y={9Kou##Gs3G(yc%sm|!t~t0#eP`$vHGT2Whl$8qS0ifHOr%4h$Ux+M4l zZ;Hhuly-+|rleK#X(lgwl1Ec&-A^q71!wa+Ej07Ztlo|Fr_PS{ zqWZi%IgOgM=GonzoR`Jf${dQ~Z`@M9x#j!Y5S}5cUbVHIh(r@E;wer)6$y;T(+4qq zs1v5<_i?t|0t0sW&x+t-?mox8rej+Qbakeb2NP|a$?@b2OJz7) zsQpFlS2#Gl&?dp%j&It=1|zCwGwe|hXm@=r2~ z9v^ZxZS^1+)Ur1`lb|ai)7?C~VNTHeH~H5?sCb6VAPtec?e_vX4XO!vU@UO(-^8~> zOV~R`m0QER+&-P4s5OFrufKlu-)2o@0sl9t{GZ(at7g_$BH|UE{qGt0e%UdTVL6DH z?LIKXnf3Yp8?}+L`usx$`ahRq%N-u*;XD7A0Kw5r+r1F`Z^co*?|i5D|IWhTgEn%b zW;WCJAAOQf%wsBf ztJnEXLX_$tW5NZ&{?@sN&mZp71SX|fW>AbHE*Jm~#el)3L2jRO8N^YjNyi%({&|ky zzo<%$Yp1zF*C`K=A4nTm4@S;;H}dJv6Qzc#w`8m38kEUOURH`G&R3KMJ<;f4;>vWm zwB^Abso~GuQ?n?_cHnU_1cIU|mYEfE)i90EYHUwfiT)8y_6GlmCY#6k^cV8}IfFE( zOtsR6H3 z*tUxM1bgD(KOS2h>*9u!FuRlvFh9P4$#KW~6+I|R*hPmO;brr9jUL@MT&W<^CS}6B zjn9m<=dT8J_L`822~eG|xey!|HcTUq^+i`egIs*}_fu*JIa7`5&LRDduParhL2fr| zY)VD&#J48>#vr+v#NPYrkQUfVwp^b7(Mc$>{!euh5u{E+{;y7g+WAK(nQs0W-7@jc z$!qKAsJVAN_r@>69uU=M2hYwSootDwF31vN~BxsnA0-tNx>O+zfrqE{sq|7dbQKP7aRCKb`9DLtetE4}`!f0@s{%3}@Sl6Rixb-Ikb{W~7jSAGHCX6F0nC8}ke_`l zqa6tB7B%xMKREu>+NScfG~K&zxde#x`G7=LW3qvcsy_amnAsO!e@^_Ppoo{>uja~G z-mZN1o^o=L)&)O=(}UM8MPWgpTUA+Jg^#m`z`JV_v4sgf65E_rcIN`-gxjNag}(P? zkaisrx>D2N1Z*EmXP}U-^{@TNxeYL0Fp&pOz)O)W@2)Q{AWHjJg#Ol&Xj>k2!?Adc z)cYx+t1|%vu@uskjc{C$doS%lQ<>4{*@8ND9f&YS1GQ{pj>^3A485|S9F^i2$HIo^ zGPAR#eNnv(su??Ax?pI_T=!*SpPPqq-(FipXyp` zuX1)p%C32twzK;#vBa-?6Sc&%&mP*2#Vhf({!~eXx3Xj)NWn6Lx+UEJIib{dOE%&#)K_xY(UdF0C-c$6F zmi`azt7U(MlqMD@m%bN+n|7~do@`qhspvzWV133E@+)_|cm{D*aOOtLRZnH$7n#PU z&}+PE08W*JFQVQlCS`|?+^+Q`eL;p~=TN91pop&6V({cbtiPLJ3VI)o!W|mn z>la8rzLuh$B<$FutJgJM`xfJn+_k92x_OW*ha~uSbsDO7N_9^Ig}-9k_X04NFE9z~ zBh7dK)#;2Q0DKb_ySNHpJZ%KQL4m)-ZedL~`**zjF-l2GUYOAzH@~iU!4U*IG>0LD zh*?JzEPsx&Yi$L=t$5vbBSq_9eeyxqG!s}ezflDV-}JmKIDinsvhxbru6})Qb!=?) zoBm_S%(Ycp1xk#B`&Oi#0GCt#p-i7{m}&s>JxrHek0`S8tD5w99_W7$F2ue@%2wtz zkM>vC9f(^KGi8~?hXoM|>nu8^iuM~g8ljeNRU+&SS<)$^4s$to%HG(LdJ(7DJzIjS zAXZ|SlSj4LWaPE4W;-ZoNlvqk*O6w{HiVh%BF6ZW={N}e?Oa?TgL(hj%yhNLvC>BS zqXs0COYhKRb2zi8Ui&=oGQwNgljPDC@`|Yh5FUN3UT5=!h8GvNV zsmH3!Wpcn7Lzd4%HqZJ8d%dCRE*TEte@M`sr%+QVn_?s<1^fIRTQzBeV&306bS(xpC_wKGzz%A8LbdPG74iSd z31jziLQ4caaz;GK{=PrFUg`J}u|ccDDT$2JWWock7v&|=GJeBPG!kQ}*Vqrb&0$K) zQR)i!aE$TrGiERT=<5-MMxM|B>&CMwlhilqIMofWH$SzP6cv9oSw3eg}UzT_C~u9mO*#6wSO>>wT>xS>zq`X zD>MGyX87+GRovX1XN6+f_ZHQvgQSkK-s6*(;ZlvrF9s--QJsAfd=sB7RYke|y(FGk z9$R8^q|2kxvC+qn5~-CBAN9;;%gm(_Jq$;Bc11s>O2u#@U4!y$E+L-r#AuFA9H5e` zwrjl(wu&6FtshyD?5?eOcSA@G#S_&c&h;M+h4gBj`QU{)Olvq&T_VSG`PsU0MuP8Z zUXkw8FHg+3M%;2H2&{et3GamqR^Jd zV>yqrGk7X{JneYlMAwGhQ+(3zMHvG5Z1z`Rp4-JbR&t)!SQ1pE>1Z1j>LI- zwXh-DA>g&AbI$ZuP}y#d>z%ihH?PyYgCxW)PvDQr^qBYBdzWsXKcoVP5%p-4=lER@ za;TxveF|ML3eY?THq`i}8b}6ym3wUTrQ6K7C+t@)!@#=<2CcGKp-l4{Xt6gJ%M0#a z{O*S{XWtx;=Z>tEPQbc0xTT*a7HOXpj)r|HS8>#f@Yi50rajnWZVT6%*nZZ&XdNwZ zPGfq}oo7>dvJ84xAmHTTgmM7k82r0H5;*o)?cJVG5!(JrZJp_RNjutK(Q)HRmV5qeqT! zYL?u;AT&*vO1KVRj;bwS!+GApja`#$f+80qGrpvGJzMiEIL)L|xL>hIb9Tr2+B_H5&R8v!tO+Y*&irGT71G&QY4ekAw z*obK3!?MDy7z^xD2v`WRe$%kX+4HB96gWr<9G~}N{nb^bO(WEb)mA71Js9VnP)Ugu zkwskb>!tFQX8$<5LP{#~l`jZ83jka0_H5M z)W$Gj#sfw2P~U1;99I?SB)XYy9f-9Nw5B7wT8mmFUp~J4F@+EMYZ))rFFR{mc+c$4 z{-dOXe(|21y*}SPs)j5L)b~J)kfTpj4_-ZHKV+8UA=)Z0($CXvTJoiPr@Y<~@rs@V z<3KOu@!i0?1o~oua3TDOfcL@(0xkv9PjP*-C1E;7RiAX&co&%el~G8GB3hAHtx(I+ zmJ9~{HpfuuuIabickLA3nhC5qXZZ4y@s=bm-i>-S$;4LJy+#gQ7{*pMf@TSE*xfEg zdO@Y1o^FCP`bX1?gG?U~uKl-F`@%&WNACYp`QI_j7%JKbS>FkRiF) zcbL4+x8vEe7_XxA|AQga4?X^~V7qm-eAS~qvNT`EpX5g=Mj&nn-oluEs!vap)@=zE zX0&ct<$eeaDb3Cw{WRWvpN@{)7fkx8(?v;Ey<8#75h`PnM2gko=+^L5=+yr&5rraHUUCe-H z=~%uJ-v4oomXu8ioo*8xpQg+>4u|jCt<4pLC+mYSv3=GEIWOH}j6wwsl6AHpBfras zT&@eh_6Lmx%uISt|Mh_0(e#QinKUfx*O*?GVV-s)l zGK5IKoKI0zRttF@@h6IQ(Kqj8UN4Dpv$8=Ki+UvTbf|y{SE+~vTZ<&W5H;)P(c3h| zr^SIo=<(LEUBULaGtyA1Uzbluzfsq%2_eH6_D7sa>`TKhIF@JDyxW;|@E{$p>Bymk zx|utq3mh$KZL()}%NxS5cX!t8pb}BAsy^2XGMmn-A{$A8%kw{y%o{QHX7+$);euPB zXm(Zm@IRmfDr!JfLr$JWHJ$;dDvL&el7k8mApd_Lk`zNx(2O;soXWqBO|uZ_z@r9m zLjV52Ws>9utCIi31Yl?w?y;T1Bc-!Yt^203K$C ADF6Tf diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json deleted file mode 100644 index 13bb3070da..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/benchmarkTemplate.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "endpoint": { - "type": "string", - "metadata": { - "description": "Your account endpoint" - } - }, - "key": { - "type": "securestring", - "metadata": { - "description": "Your account key" - } - }, - "throughput": { - "type": "string", - "metadata": { - "description": "The throughput for the container." - } - }, - "documents": { - "type": "string", - "metadata": { - "description": "The amount of items to insert." - } - }, - "parallelism": { - "type": "string", - "metadata": { - "description": "The degree of parallelism." - }, - "defaultValue": "-1" - }, - "cleanUpOnFinish": { - "type": "string", - "metadata": { - "description": "Whether to delete the container after the benchmark is run." - }, - "defaultValue": "false" - }, - "containerGroupName": { - "type": "string", - "metadata": { - "description": "Name for the container group" - }, - "defaultValue": "CosmosDBBenchmark" - }, - "containerName": { - "type": "string", - "metadata": { - "description": "Name for the container" - }, - "defaultValue": "cosmosdbsdkperf" - }, - "volumeName": { - "type": "string", - "metadata": { - "description": "Name for the gitRepo volume" - }, - "defaultValue": "cosmosdbsdk" - }, - "port": { - "type": "string", - "metadata": { - "description": "Port to open on the container and the public IP address." - }, - "defaultValue": "80" - }, - "cpuCores": { - "type": "string", - "metadata": { - "description": "The number of CPU cores to allocate to the container." - }, - "defaultValue": "4" - }, - "memoryInGb": { - "type": "string", - "metadata": { - "description": "The amount of memory to allocate to the container in gigabytes." - }, - "defaultValue": "8" - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Location for all resources." - } - } - }, - "variables": {}, - "resources": [ - { - "name": "[parameters('containerGroupName')]", - "type": "Microsoft.ContainerInstance/containerGroups", - "apiVersion": "2020-11-01", - "location": "[parameters('location')]", - "properties": { - "containers": [ - { - "name": "[parameters('containerName')]", - "properties": { - "image": "mcr.microsoft.com/dotnet/sdk:6.0", - "ports": [ - { - "port": "[parameters('port')]" - } - ], - "resources": { - "requests": { - "cpu": "[parameters('cpuCores')]", - "memoryInGB": "[parameters('memoryInGb')]" - } - }, - "volumeMounts": [ - { - "name": "[parameters('volumeName')]", - "mountPath": "/mnt/gitrepos/", - "readOnly": false - } - ], - "command": [ - "/bin/bash", - "-c", - "[concat('cd /mnt/gitrepos/azure-cosmos-dotnet-v3/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate;export ENDPOINT=\"', parameters('endpoint'),'\";export KEY=\"', parameters('key'),'\";export THROUGHPUT=\"', parameters('throughput'),'\";export DOCUMENTS=\"', parameters('documents'),'\";export PARALLELISM=\"', parameters('parallelism'),'\";export CLEANUPFINISH=\"', parameters('cleanUpOnFinish'),'\";chmod +x run.sh;./run.sh')]" - ] - } - } - ], - "osType": "Linux", - "restartPolicy": "Never", - "ipAddress": { - "type": "Public", - "ports": [ - { - "protocol": "TCP", - "port": "[parameters('port')]" - } - ] - }, - "volumes": [ - { - "name": "[parameters('volumeName')]", - "gitRepo": { - "repository": "https://github.com/Azure/azure-cosmos-dotnet-v3" - } - } - ] - } - } - ] -} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json deleted file mode 100644 index f8b1983b33..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/parameters.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "endpoint": { - "value": "" - }, - "key": { - "value": "" - }, - "throughput": { - "value": "" - }, - "documents": { - "value": "" - }, - "parallelism": { - "value": "-1" - }, - "cleanUpOnFinish": { - "value": "false" - }, - "containergroupname": { - "value": "CosmosDBBenchmark" - }, - "containername": { - "value": "cosmosdbsdkperf" - }, - "volumename": { - "value": "cosmosdbsdk" - }, - "cpuCores": { - "value": "4" - }, - "memoryInGb": { - "value": "8" - } - } -} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh deleted file mode 100644 index 3b8855a95f..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/run.sh +++ /dev/null @@ -1,2 +0,0 @@ -cd .. -dotnet run -c Release -e ${ENDPOINT} -k ${KEY} -t ${THROUGHPUT} -n ${DOCUMENTS} --pl ${PARALLELISM} --CleanupOnFinish ${CLEANUPFINISH} -w InsertV2BenchmarkOperation \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md new file mode 100644 index 0000000000..cd9ad834fc --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md @@ -0,0 +1,111 @@ +# Running benchmarks on Azure Virtual Machines + +[Azure Arm Template](https://azure.microsoft.com/products/arm-templates/) makes executing the Azure Cosmos DB SDK Benchmark extremely easy. And reaching following abilities: + +- Ability to execute benchmarking on multiple machines with one ARM Template +- Capturing diagnostics data for requests that exceed the latency threshold +- AppInsights: Live metrics (10s) + - Success rate + - Error + - P90, P99, P999, P9999 + +| Parameter name | Description | +| ------------------------------------------------------ | ------------------------------------------------------ | +| projectName | Specifies a name for generating resource names. | +| location | Specifies the location for all resources. | +| adminUsername | Specifies a username for the Virtual Machine. | +| adminPassword | Specifies a password for the Virtual Machine. | +| vmSize | Specifies a Virtual Machine size | +| vNetName | Specifies a Virtual Network name | +| vNetAddressPrefixes | Specifies a Virtual Network Address Prefix | +| vNetSubnetName | Specifies a Virtual Network Subnet name | +| vNetSubnetAddressPrefix | Specifies a Virtual Network Subnet Address Prefix | +| cosmosURI | Specifies the URI of the Cosmos DB account | +| cosmosKey | Specifies the key for the Cosmos DB account | +| throughput | Specifies Collection throughput use | +| operationsCount | Specifies the number of operations to execute | +| parallelism | Specifies the degree of parallelism | +| resultsContainer | Specifies the name of the container to which the results to be saved | +| vmCount | Specifies the number of Virtual Machines that will part of the test bench | +| workloadType | Specifies the workload | +| benchmarkingToolsBranchName | Specifies the GitHub branch for the benchmark tool source code repository | +| diagnosticsLatencyThresholdInMS | Specifies request latency threshold for capturing diagnostic data | +| storageAccountName | Specifies Storage Account Nmae | +| metricsReportingIntervalInSec | Specifies metrics reporting interval in seconds | +| applicationInsightsName | Specifies Application Insights Account Name | +| startDate | Specifies Diagnostic Blob storage container folder prefix | + + [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fazure-cosmos-dotnet-v3%2Fmaster%2FMicrosoft.Azure.Cosmos.Samples%2FTools%2FBenchmark%2FAzureVmBenchmark%2Fazuredeploy.json) + +After benchmark was launched use Shared Dashboard for viewing charts with + +## Workload types + +| Workload Type | Description | +| ------------------------------------------------------ | ------------------------------------------------------ | +| InsertV3BenchmarkOperation | Inserts single document | +| QueryStreamCrossPkDistinctFullDrainV3BenchmarkOperation | Execute a `DISTINCT` query cross partitions and access data using a steram | +| QueryStreamCrossPkDistinctWithPaginationV3BenchmarkOperation | Execute a `DISTINCT` query cross partitions and access data using a steram and pagination | +| QueryStreamCrossPkGroupByFullDrainV3BenchmarkOperation | Execute a `GROUP BY` query cross partitions and access data using a steram | +| QueryStreamCrossPkGroupByWithPaginationV3BenchmarkOperation | Execute a `GROUP BY` query cross partitions and access data using a steram and pagination | +| QueryStreamCrossPkOrderByFullDrainV3BenchmarkOperation | Execute a `ORDER BY` query cross partitions and access data using a steram | +| QueryStreamCrossPkOrderByWithPaginationV3BenchmarkOperation | Execute a `ORDER BY` query cross partitions and access data using a steram and pagination | +| QueryStreamCrossPkV3BenchmarkOperation | Execute `select * from T where T.id = @id` query cross partitions and access data using a steram | +| QueryStreamCrossPkWithPaginationV3BenchmarkOperation | Execute `select * from T where T.id = @id` query cross partitions and access data using a steram and pagination | +| QueryStreamSinglePkDistinctFullDrainV3BenchmarkOperation | Execute a `DISTINCT` query on a single partition and access data using a steram | +| QueryStreamSinglePkDistinctWithPaginationV3BenchmarkOperation | Execute a `DISTINCT` query on a single partition and access data using a steram and pagination | +| QueryStreamSinglePkGroupByFullDrainV3BenchmarkOperation | Execute a `GROUP BY` query on a single partition and access data using a steram | +| QueryStreamSinglePkGroupByWithPaginationV3BenchmarkOperation | Execute a `GROUP BY` query on a single partition and access data using a steram and pagination | +| QueryStreamSinglePkOrderByFullDrainV3BenchmarkOperation | Execute a `ORDER BY` query on a single partition and access data using a stream | +| QueryStreamSinglePkOrderByWithPaginationV3BenchmarkOperation | Execute a `ORDER BY` query on a single partition and access data using a steram and pagination | +| QueryStreamSinglePkV3BenchmarkOperation | Execute `select * from T where T.id = @id` query on a single partition and access data using a steram | +| QueryStreamSinglePkWithPaginationV3BenchmarkOperation | Execute `select * from T where T.id = @id` query on a single partition and access data using a steram and pagination | +| QueryTCrossPkDistinctFullDrainV3BenchmarkOperation | Execute a `DISTINCT` query cross partitions and access data | +| QueryTCrossPkDistinctWithPaginationV3BenchmarkOperation | Execute a `DISTINCT` query cross partitions and access data using a pagination | +| QueryTCrossPkGroupByFullDrainV3BenchmarkOperation | Execute a `GROUP BY` query cross partitions and access data | +| QueryTCrossPkGroupByWithPaginationV3BenchmarkOperation | Execute a `GROUP BY` query cross partitions and access data using a pagination | +| QueryTCrossPkOrderByFullDrainV3BenchmarkOperation | Execute a `ORDER BY` query cross partitions and access data | +| QueryTCrossPkOrderByWithPaginationV3BenchmarkOperation | Execute a `ORDER BY` query cross partitions and access data using a pagination | +| QueryTCrossPkV3BenchmarkOperation | Execute `select * from T where T.id = @id` query cross partitions partition and access data | +| QueryTCrossPkWithPaginationV3BenchmarkOperation | Execute `select * from T where T.id = @id` query cross partitions partition and access data using a pagination | +| QueryTSinglePkDistinctFullDrainV3BenchmarkOperation | Execute a `DISTINCT` query on a single partition and access data | +| QueryTSinglePkDistinctWithPaginationV3BenchmarkOperation | Execute a `DISTINCT` query on a single partition and access data using a pagination | +| QueryTSinglePkGroupByFullDrainV3BenchmarkOperation | Execute a `GROUP BY` query on a single partition and access data | +| QueryTSinglePkGroupByWithPaginationV3BenchmarkOperation | Execute a `GROUP BY` query on a single partition and access data using a pagination | +| QueryTSinglePkOrderByFullDrainV3BenchmarkOperation | Execute a `ORDER BY` query on a single partition and access data | +| QueryTSinglePkOrderByWithPaginationV3BenchmarkOperation | Execute a `ORDER BY` query on a single partition and access data using a pagination | +| QueryTSinglePkV3BenchmarkOperation | Execute `select * from T where T.id = @id` query on a single partition and access data | +| QueryTSinglePkWithPaginationV3BenchmarkOperation | Execute `select * from T where T.id = @id` query on a single partition and access data using a pagination | +| ReadFeedStreamV3BenchmarkOperation | Execute Read Feed query | +| ReadNotExistsV3BenchmarkOperation | Execute query for not existing item | +| ReadStreamExistsV3BenchmarkOperation | Read item stream | +| ReadStreamExistsWithDiagnosticsV3BenchmarkOperation | Read item stream with diagnostics data | +| ReadTExistsV3BenchmarkOperation | Read single item | + + +## Diagnose and troubleshooting +The Benchmark tool output logs may be found on the each Virtual Machine in user home directory. + +- Connect to VM using serial console +- Enter login and password + +```bash +benchmarking@Benchmarking-dotnet-SDK-vm1:~$ ls + +agent.err agent.out +``` + +```bash +benchmarking@Benchmarking-dotnet-SDK-vm1:~$ cat agent.out + +CSC : warning CS8002: Referenced assembly 'MathNet.Numerics, Version=4.15.0.0, Culture=neutral, PublicKeyToken=null' does not have a strong name. [/var/lib/waagent/custom-script/download/2/azure-cosmos-dotnet-v3/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj] +Azure VM Location:eastus +BenchmarkConfig arguments +IsServerGC: True +--------------------------------------------------------------------- +{ + "WorkloadType": "ReadTExistsV3BenchmarkOperation", + "EndPoint": "https://cosmosdb-benchmark-dotnet-test-thr.documents.azure.com:443/", + "Database": "db", + "Container": "data", +``` diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json new file mode 100644 index 0000000000..347857cf82 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json @@ -0,0 +1,1160 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "projectName": { + "type": "string", + "defaultValue": "Benchmarking-dotnet-SDK", + "metadata": { + "description": "Specifies a name for generating resource names." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Specifies the location for all resources." + } + }, + "adminUsername": { + "type": "string", + "defaultValue": "benchmarking", + "metadata": { + "description": "Specifies a username for the Virtual Machine." + } + }, + "adminPassword": { + "type": "securestring", + "metadata": { + "description": "Specifies a password for the Virtual Machine." + } + }, + "vmSize": { + "type": "string", + "defaultValue": "Standard_D4s_v3", + "metadata": { + "description": "Specifies a Virtual Machine size" + } + }, + "vNetName": { + "type": "string", + "defaultValue": "Benchmarking-dotnet-SDK-vnet", + "metadata": { + "description": "Specifies a Virtual Network name" + } + }, + "vNetAddressPrefixes": { + "type": "string", + "defaultValue": "10.2.0.0/16", + "metadata": { + "description": "Specifies a Virtual Network Address Prefix" + } + }, + "vNetSubnetName": { + "type": "string", + "defaultValue": "default", + "metadata": { + "description": "Specifies a Virtual Network Subnet name" + } + }, + "vNetSubnetAddressPrefix": { + "type": "string", + "defaultValue": "10.2.0.0/24", + "metadata": { + "description": "Specifies a Virtual Network Subnet Address Prefix " + } + }, + "cosmosURI": { + "type": "string", + "metadata": { + "description": "Specifies the URI of the Cosmos DB account" + } + }, + "cosmosKey": { + "type": "securestring", + "metadata": { + "description": "Specifies the key for the Cosmos DB account" + } + }, + "throughput": { + "type": "int", + "defaultValue": 100000, + "metadata": { + "description": "Specifies Collection throughput use" + } + }, + "operationsCount": { + "type": "int", + "metadata": { + "description": "Specifies the number of operations to execute" + } + }, + "parallelism": { + "type": "int", + "defaultValue": -1, + "metadata": { + "description": "Specifies the degree of parallelism" + } + }, + "resultsContainer": { + "type": "string", + "defaultValue": "BenchmarkResult", + "metadata": { + "description": "Specifies the name of the container to which the results to be saved" + } + }, + "vmCount": { + "type": "int", + "defaultValue": 1, + "metadata": { + "description": "Specifies the number of Virtual Machines that will part of the test bench" + } + }, + "workloadType": { + "type": "string", + "allowedValues": [ + "InsertV3BenchmarkOperation", + "QueryStreamCrossPkDistinctFullDrainV3BenchmarkOperation", + "QueryStreamCrossPkDistinctWithPaginationV3BenchmarkOperation", + "QueryStreamCrossPkGroupByFullDrainV3BenchmarkOperation", + "QueryStreamCrossPkGroupByWithPaginationV3BenchmarkOperation", + "QueryStreamCrossPkOrderByFullDrainV3BenchmarkOperation", + "QueryStreamCrossPkOrderByWithPaginationV3BenchmarkOperation", + "QueryStreamCrossPkV3BenchmarkOperation", + "QueryStreamCrossPkWithPaginationV3BenchmarkOperation", + "QueryStreamSinglePkDistinctFullDrainV3BenchmarkOperation", + "QueryStreamSinglePkDistinctWithPaginationV3BenchmarkOperation", + "QueryStreamSinglePkGroupByFullDrainV3BenchmarkOperation", + "QueryStreamSinglePkGroupByWithPaginationV3BenchmarkOperation", + "QueryStreamSinglePkGroupByWithPaginationV3BenchmarkOperation", + "QueryStreamSinglePkOrderByWithPaginationV3BenchmarkOperation", + "QueryStreamSinglePkV3BenchmarkOperation", + "QueryStreamSinglePkWithPaginationV3BenchmarkOperation", + "QueryTCrossPkDistinctFullDrainV3BenchmarkOperation", + "QueryTCrossPkDistinctWithPaginationV3BenchmarkOperation", + "QueryTCrossPkGroupByFullDrainV3BenchmarkOperation", + "QueryTCrossPkGroupByWithPaginationV3BenchmarkOperation", + "QueryTCrossPkOrderByFullDrainV3BenchmarkOperation", + "QueryTCrossPkOrderByWithPaginationV3BenchmarkOperation", + "QueryTCrossPkV3BenchmarkOperation", + "QueryTCrossPkWithPaginationV3BenchmarkOperation", + "QueryTSinglePkDistinctFullDrainV3BenchmarkOperation", + "QueryTSinglePkDistinctWithPaginationV3BenchmarkOperation", + "QueryTSinglePkGroupByFullDrainV3BenchmarkOperation", + "QueryTSinglePkGroupByWithPaginationV3BenchmarkOperation", + "QueryTSinglePkOrderByFullDrainV3BenchmarkOperation", + "QueryTSinglePkOrderByWithPaginationV3BenchmarkOperation", + "QueryTSinglePkV3BenchmarkOperation", + "QueryTSinglePkWithPaginationV3BenchmarkOperation", + "ReadFeedStreamV3BenchmarkOperation", + "ReadNotExistsV3BenchmarkOperation", + "ReadStreamExistsV3BenchmarkOperation", + "ReadStreamExistsWithDiagnosticsV3BenchmarkOperation", + "ReadTExistsV3BenchmarkOperation" + ], + "defaultValue": "ReadTExistsV3BenchmarkOperation", + "metadata": { + "description": "Specifies the workload" + } + }, + "benchmarkingToolsBranchName": { + "type": "string", + "defaultValue": "master", + "metadata": { + "description": "Specifies the GitHub branch for the benchmark tool source code repository" + } + }, + "diagnosticsLatencyThresholdInMS": { + "type": "int", + "defaultValue": 100 + }, + "storageAccountName": { + "type": "string", + "defaultValue": "dotnetbenchmark", + "metadata": { + "description": "Specifies Storage Account Nmae" + } + }, + "metricsReportingIntervalInSec": { + "type": "int", + "defaultValue": 5 + }, + "applicationInsightsName": { + "type": "string", + "defaultValue": "CosmosDBBenchmarkTestAppInsights", + "metadata": { + "description": "Specifies Application Insights Account Name" + } + }, + "startDate": { + "type": "int", + "defaultValue": "[dateTimeToEpoch(utcNow())]" + }, + "dashboardName": { + "type": "string", + "defaultValue": "Cosmos Benchmark Statistics", + "metadata": { + "description": "Specifies Application Insights Dashboard Name" + } + } + }, + "variables": { + "vmName": "[concat(parameters('projectName'), '-vm')]", + "publicIPAddressName": "[concat(parameters('projectName'), '-ip')]", + "networkInterfaceName": "[concat(parameters('projectName'), '-nic')]", + "networkSecurityGroupName": "[concat(parameters('projectName'), '-nsg')]", + "benchmarkingToolsURL": "https://github.com/Azure/azure-cosmos-dotnet-v3.git", + "cloudInitScriptUrl": "[concat('https://raw.githubusercontent.com/Azure/azure-cosmos-dotnet-v3/',parameters('benchmarkingToolsBranchName'),'/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt')]", + "vmScriptExtensionScriptUrl": "[concat('https://raw.githubusercontent.com/Azure/azure-cosmos-dotnet-v3/',parameters('benchmarkingToolsBranchName'),'/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh')]", + "customScriptUrl": "[concat('https://raw.githubusercontent.com/Azure/azure-cosmos-dotnet-v3/',parameters('benchmarkingToolsBranchName'),'/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh')]", + "vmScriptExtensionScriptName": "execute.sh", + "convertedDatetime": "[dateTimeFromEpoch(parameters('startDate'))]", + "appInsightsResourceIds": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/microsoft.insights/components/', parameters('applicationInsightsName'))]", + "chart0Expression": "[concat('customMetrics\n| where name == \"ReadOperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 50),\n percentile(value, 75),\n percentile(value, 90),\n percentile(value, 95)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", + "chart1Expression": "[concat('customMetrics\n| where name == \"ReadOperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 99),\n percentile(value, 99.9),\n percentile(value, 99.99)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", + "chart2Expression": "[concat('customMetrics\n| where name == \"ReadOperationRps\" and timestamp > ago(1d)\n| summarize\n avg(value)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]" + + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2021-04-01", + "name": "[parameters('storageAccountName')]", + "location": "[resourceGroup().location]", + "sku": { + "name": "Standard_LRS" + }, + "kind": "StorageV2", + "properties": { + "accessTier": "Hot" + } + }, + { + "name": "[parameters('applicationInsightsName')]", + "type": "Microsoft.Insights/components", + "apiVersion": "2015-05-01", + "location": "[resourceGroup().location]", + "properties": { + "ApplicationId": "[parameters('applicationInsightsName')]", + "Application_Type": "web" + } + }, + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2020-11-01", + "name": "[variables('networkSecurityGroupName')]", + "location": "[parameters('location')]", + "properties": { + "securityRules": [] + } + }, + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2020-11-01", + "name": "[concat(variables('publicIPAddressName'),copyIndex(1))]", + "location": "[parameters('location')]", + "sku": { + "name": "Basic", + "tier": "Regional" + }, + "properties": { + "publicIPAddressVersion": "IPv4", + "publicIPAllocationMethod": "Dynamic", + "idleTimeoutInMinutes": 4 + }, + "copy": { + "name": "publicIPcopy", + "count": "[parameters('vmCount')]" + } + }, + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2020-11-01", + "name": "[parameters('vNetName')]", + "location": "[parameters('location')]", + "properties": { + "addressSpace": { + "addressPrefixes": [ + "[parameters('vNetAddressPrefixes')]" + ] + }, + "subnets": [ + { + "name": "[parameters('vNetSubnetName')]", + "properties": { + "addressPrefix": "[parameters('vNetSubnetAddressPrefix')]", + "privateEndpointNetworkPolicies": "Enabled", + "privateLinkServiceNetworkPolicies": "Enabled" + } + } + ], + "enableDdosProtection": false + } + }, + { + "type": "Microsoft.Network/virtualNetworks/subnets", + "apiVersion": "2020-11-01", + "name": "[concat(parameters('vNetName'), '/',parameters('vNetSubnetName'))]", + "dependsOn": [ + "[resourceId('Microsoft.Network/virtualNetworks', parameters('vNetName'))]", + "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + ], + "properties": { + "addressPrefix": "[parameters('vNetSubnetAddressPrefix')]", + "privateEndpointNetworkPolicies": "Enabled", + "privateLinkServiceNetworkPolicies": "Enabled", + "networkSecurityGroup": { + "id": "[resourceId('Microsoft.Network/networkSecurityGroups', variables('networkSecurityGroupName'))]" + } + } + }, + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2020-11-01", + "name": "[concat(variables('networkInterfaceName'),copyIndex(1))]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddressName'),copyIndex(1)))]", + "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), parameters('vNetSubnetName'))]" + ], + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "privateIPAddress": "10.0.0.4", + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[resourceId('Microsoft.Network/publicIPAddresses', concat(variables('publicIPAddressName'),copyIndex(1)))]" + }, + "subnet": { + "id": "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vNetName'), parameters('vNetSubnetName'))]" + }, + "primary": true, + "privateIPAddressVersion": "IPv4" + } + } + ], + "enableAcceleratedNetworking": true, + "enableIPForwarding": false + }, + "copy": { + "name": "networkInterfacecopy", + "count": "[parameters('vmCount')]" + } + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2021-11-01", + "name": "[concat(variables('vmName'),copyIndex(1))]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('networkInterfaceName'),copyIndex(1)))]", + "[concat('Microsoft.Storage/storageAccounts/', parameters('storageAccountName'))]", + "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]" + ], + "tags": { + "azsecpack": "prod", + "platformsettings.host_environment.service.platform_optedin_for_rootcerts": "true" + }, + "properties": { + "hardwareProfile": { + "vmSize": "[parameters('vmSize')]" + }, + "storageProfile": { + "imageReference": { + "publisher": "canonical", + "offer": "0001-com-ubuntu-server-focal", + "sku": "20_04-lts-gen2", + "version": "latest" + }, + "osDisk": { + "osType": "Linux", + "name": "[concat(variables('vmName'),copyIndex(1),'_OsDisk')]", + "createOption": "FromImage", + "caching": "ReadWrite", + "managedDisk": { + "storageAccountType": "Premium_LRS" + }, + "deleteOption": "Delete", + "diskSizeGB": 30 + } + }, + "osProfile": { + "computerName": "[concat(variables('vmName'),copyIndex(1))]", + "adminUsername": "[parameters('adminUsername')]", + "adminPassword": "[parameters('adminPassword')]", + "customData": "[base64(concat('#include\n',variables('cloudInitScriptUrl')))]", + "linuxConfiguration": { + "disablePasswordAuthentication": false, + "provisionVMAgent": true, + "patchSettings": { + "patchMode": "ImageDefault", + "assessmentMode": "ImageDefault" + } + }, + "allowExtensionOperations": true + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', concat(variables('networkInterfaceName'),copyIndex(1)))]", + "properties": { + "deleteOption": "Delete" + } + } + ] + }, + "diagnosticsProfile": { + "bootDiagnostics": { + "enabled": true + } + } + }, + "copy": { + "name": "vmcopy", + "count": "[parameters('vmCount')]" + } + }, + { + "type": "Microsoft.Compute/virtualMachines/extensions", + "apiVersion": "2019-03-01", + "name": "[concat(variables('vmName'),copyIndex(1),'/CustomScript')]", + "location": "[parameters('location')]", + "dependsOn": [ + "[resourceId('Microsoft.Compute/virtualMachines', concat(variables('vmName'),copyIndex(1)))]" + ], + "properties": { + "publisher": "Microsoft.Azure.Extensions", + "type": "CustomScript", + "typeHandlerVersion": "2.1", + "autoUpgradeMinorVersion": true, + "settings": { + }, + "protectedSettings": { + "commandToExecute": "[concat('ADMIN_USER_NAME=',parameters('adminUsername'),' ','BENCHMARKING_TOOLS_URL=',variables('benchmarkingToolsURL'),' ','BENCHMARKING_TOOLS_BRANCH_NAME=',parameters('benchmarkingToolsBranchName'),' ','WORKLOAD_TYPE=',parameters('workloadType'),' ','VM_NAME=',variables('vmName'),copyIndex(1), ' ','DIAGNOSTICS_STORAGE_CONNECTION_STRING=','\"',concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), ';AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')), providers('Microsoft.Storage', 'storageAccounts').apiVersions[0]).keys[0].value),'\"',' ','COSMOS_URI=','\"',parameters('cosmosURI'),'\"', ' ', 'COSMOS_KEY=',parameters('cosmosKey'), ' ', 'THROUGHPUT=',parameters('throughput'), ' ', 'DOCUMENTS=',parameters('operationsCount'), ' ','PARALLELISM=',parameters('parallelism'), ' ','RESULTS_CONTAINER=',parameters('resultsContainer'), ' ','VM_COUNT=',parameters('vmCount'), ' ','DIAGNOSTICS_LATENCY_THRESHOLD_IN_MS=',parameters('diagnosticsLatencyThresholdInMS'),' ','DIAGNOSTICS_STORAGE_CONTAINER_PREFIX=',variables('convertedDatetime'),' ','METRICS_REPORTINT_INTERVAL_SEC=',parameters('metricsReportingIntervalInSec'), ' ','CUSTOM_SCRIPT_URL=',variables('customScriptUrl'), ' ','MACHINE_INDEX=',copyIndex(1), ' ','APP_INSIGHT_CONN_STR=','\"', reference(resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))).ConnectionString,'\"',' ', 'bash ',variables('vmScriptExtensionScriptName'))]", + "fileUris": [ "[concat(variables('vmScriptExtensionScriptURL'))]" ] + } + }, + "copy": { + "name": "vmextensioncopy", + "count": "[parameters('vmCount')]" + } + }, + { + "name": "CosmosDBBenchmarkDashboard", + "type": "Microsoft.Portal/dashboards", + "location": "[resourceGroup().location]", + "apiVersion": "2015-08-01-preview", + "dependsOn": [ + "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]" + ], + "tags": { + "hidden-title": "[parameters('dashboardName')]" + }, + + "properties": { + "lenses": { + "0": { + "order": 0, + "parts": { + "0": { + "position": { + "x": 0, + "y": 0, + "colSpan": 10, + "rowSpan": 6 + }, + "metadata": { + "inputs": [ + { + "name": "resourceTypeMode", + "isOptional": true + }, + { + "name": "ComponentId", + "isOptional": true + }, + { + "name": "Scope", + "value": { + "resourceIds": [ + "[variables('appInsightsResourceIds')]" + ] + }, + "isOptional": true + }, + { + "name": "PartId", + "value": "104528fc-0216-49c6-bf70-fffe9d37f93d", + "isOptional": true + }, + { + "name": "Version", + "value": "2.0", + "isOptional": true + }, + { + "name": "TimeRange", + "isOptional": true + }, + { + "name": "DashboardId", + "isOptional": true + }, + { + "name": "DraftRequestParameters", + "isOptional": true + }, + { + "name": "Query", + "value": "[variables('chart0Expression')]", + "isOptional": true + }, + { + "name": "ControlType", + "value": "FrameControlChart", + "isOptional": true + }, + { + "name": "SpecificChart", + "value": "Line", + "isOptional": true + }, + { + "name": "PartTitle", + "value": "Request latencies P50, P75, P90, P95 in ms", + "isOptional": true + }, + { + "name": "PartSubTitle", + "value": "A Latency Percentiles dashboard provides a concise overview of the distribution of response times or latencies for a system or application. It helps monitor and analyze the performance of the system, identify bottlenecks or outliers, and ensure optimal user experience.", + "isOptional": true + }, + { + "name": "Dimensions", + "value": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "percentile_value_50", + "type": "real" + }, + { + "name": "percentile_value_75", + "type": "real" + }, + { + "name": "percentile_value_90", + "type": "real" + }, + { + "name": "percentile_value_95", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "isOptional": true + }, + { + "name": "LegendOptions", + "value": { + "isEnabled": true, + "position": "Bottom" + }, + "isOptional": true + }, + { + "name": "IsQueryContainTimeRange", + "value": true, + "isOptional": true + } + ], + "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", + "settings": { + "content": { + "Dimensions": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "percentile_value_50", + "type": "real" + }, + { + "name": "percentile_value_75", + "type": "real" + }, + { + "name": "percentile_value_90", + "type": "real" + }, + { + "name": "percentile_value_95", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "IsQueryContainTimeRange": true + } + } + } + }, + "1": { + "position": { + "x": 10, + "y": 0, + "colSpan": 10, + "rowSpan": 6 + }, + "metadata": { + "inputs": [ + { + "name": "resourceTypeMode", + "isOptional": true + }, + { + "name": "ComponentId", + "isOptional": true + }, + { + "name": "Scope", + "value": { + "resourceIds": [ + "[variables('appInsightsResourceIds')]" + ] + }, + "isOptional": true + }, + { + "name": "PartId", + "value": "104528fc-0216-49c6-bf70-fffe9d37f93e", + "isOptional": true + }, + { + "name": "Version", + "value": "2.0", + "isOptional": true + }, + { + "name": "TimeRange", + "isOptional": true + }, + { + "name": "DashboardId", + "isOptional": true + }, + { + "name": "DraftRequestParameters", + "isOptional": true + }, + { + "name": "Query", + "value": "[variables('chart1Expression')]", + "isOptional": true + }, + { + "name": "ControlType", + "value": "FrameControlChart", + "isOptional": true + }, + { + "name": "SpecificChart", + "value": "Line", + "isOptional": true + }, + { + "name": "PartTitle", + "value": "Request latencies P99, P99.9, P99.99 in ms", + "isOptional": true + }, + { + "name": "PartSubTitle", + "value": "A Latency Percentiles dashboard provides a concise overview of the distribution of response times or latencies for a system or application. It helps monitor and analyze the performance of the system, identify bottlenecks or outliers, and ensure optimal user experience.", + "isOptional": true + }, + { + "name": "Dimensions", + "value": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "percentile_value_99", + "type": "real" + }, + { + "name": "percentile_value_99_9", + "type": "real" + }, + { + "name": "percentile_value_99_99", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "isOptional": true + }, + { + "name": "LegendOptions", + "value": { + "isEnabled": true, + "position": "Bottom" + }, + "isOptional": true + }, + { + "name": "IsQueryContainTimeRange", + "value": true, + "isOptional": true + } + ], + "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", + "settings": {} + } + }, + "2": { + "position": { + "x": 0, + "y": 6, + "colSpan": 5, + "rowSpan": 6 + }, + "metadata": { + "inputs": [ + { + "name": "resourceTypeMode", + "isOptional": true + }, + { + "name": "ComponentId", + "isOptional": true + }, + { + "name": "Scope", + "value": { + "resourceIds": [ + "[variables('appInsightsResourceIds')]" + ] + }, + "isOptional": true + }, + { + "name": "PartId", + "value": "104528fc-0216-49c6-bf70-fffe9d37f93e", + "isOptional": true + }, + { + "name": "Version", + "value": "2.0", + "isOptional": true + }, + { + "name": "TimeRange", + "isOptional": true + }, + { + "name": "DashboardId", + "isOptional": true + }, + { + "name": "DraftRequestParameters", + "isOptional": true + }, + { + "name": "Query", + "value": "customMetrics\n| where name == \"ReadOperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n", + "isOptional": true + }, + { + "name": "ControlType", + "value": "FrameControlChart", + "isOptional": true + }, + { + "name": "SpecificChart", + "value": "Line", + "isOptional": true + }, + { + "name": "PartTitle", + "value": "Failed operations", + "isOptional": true + }, + { + "name": "PartSubTitle", + "value": "Provides the number of failed operations. (most likely related to some error or inavailability)", + "isOptional": true + }, + { + "name": "Dimensions", + "value": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "sum_value", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "isOptional": true + }, + { + "name": "LegendOptions", + "value": { + "isEnabled": true, + "position": "Bottom" + }, + "isOptional": true + }, + { + "name": "IsQueryContainTimeRange", + "value": true, + "isOptional": true + } + ], + "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", + "settings": { + "content": { + "Query": "customMetrics\n| where name == \"ReadOperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n", + "Dimensions": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "sum_value", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + } + } + } + } + }, + "3": { + "position": { + "x": 5, + "y": 6, + "colSpan": 5, + "rowSpan": 6 + }, + "metadata": { + "inputs": [ + { + "name": "resourceTypeMode", + "isOptional": true + }, + { + "name": "ComponentId", + "isOptional": true + }, + { + "name": "Scope", + "value": { + "resourceIds": [ + "[variables('appInsightsResourceIds')]" + ] + }, + "isOptional": true + }, + { + "name": "PartId", + "value": "104528fc-0216-49c6-bf70-fffe9d37f93e", + "isOptional": true + }, + { + "name": "Version", + "value": "2.0", + "isOptional": true + }, + { + "name": "TimeRange", + "isOptional": true + }, + { + "name": "DashboardId", + "isOptional": true + }, + { + "name": "DraftRequestParameters", + "isOptional": true + }, + { + "name": "Query", + "value": "customMetrics\n| where name == \"ReadOperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n", + "isOptional": true + }, + { + "name": "ControlType", + "value": "FrameControlChart", + "isOptional": true + }, + { + "name": "SpecificChart", + "value": "Line", + "isOptional": true + }, + { + "name": "PartTitle", + "value": "Success operations", + "isOptional": true + }, + { + "name": "PartSubTitle", + "value": "Provides the number of successful operations.", + "isOptional": true + }, + { + "name": "Dimensions", + "value": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "sum_value", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "isOptional": true + }, + { + "name": "LegendOptions", + "value": { + "isEnabled": true, + "position": "Bottom" + }, + "isOptional": true + }, + { + "name": "IsQueryContainTimeRange", + "value": true, + "isOptional": true + } + ], + "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", + "settings": { + "content": { + "Query": "customMetrics\n| where name == \"ReadOperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n", + "Dimensions": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "sum_value", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + } + } + } + } + }, + "4": { + "position": { + "x": 10, + "y": 6, + "colSpan": 10, + "rowSpan": 6 + }, + "metadata": { + "inputs": [ + { + "name": "resourceTypeMode", + "isOptional": true + }, + { + "name": "ComponentId", + "isOptional": true + }, + { + "name": "Scope", + "value": { + "resourceIds": [ + "[variables('appInsightsResourceIds')]" + ] + }, + "isOptional": true + }, + { + "name": "PartId", + "value": "104528fc-0216-49c6-bf70-fffe9d37f93e", + "isOptional": true + }, + { + "name": "Version", + "value": "2.0", + "isOptional": true + }, + { + "name": "TimeRange", + "isOptional": true + }, + { + "name": "DashboardId", + "isOptional": true + }, + { + "name": "DraftRequestParameters", + "isOptional": true + }, + { + "name": "Query", + "value": "[variables('chart2Expression')]", + "isOptional": true + }, + { + "name": "ControlType", + "value": "FrameControlChart", + "isOptional": true + }, + { + "name": "SpecificChart", + "value": "Line", + "isOptional": true + }, + { + "name": "PartTitle", + "value": "Requests per Second (RPS)", + "isOptional": true + }, + { + "name": "PartSubTitle", + "value": "A Requests per Second (RPS) dashboard provides a concise overview of the number of requests being processed by a system or application per second.", + "isOptional": true + }, + { + "name": "Dimensions", + "value": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "RPs", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "isOptional": true + }, + { + "name": "LegendOptions", + "value": { + "isEnabled": true, + "position": "Bottom" + }, + "isOptional": true + }, + { + "name": "IsQueryContainTimeRange", + "value": true, + "isOptional": true + } + ], + "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", + "settings": { + "content": { + "Dimensions": { + "xAxis": { + "name": "ts", + "type": "datetime" + }, + "yAxis": [ + { + "name": "avg_value", + "type": "real" + } + ], + "splitBy": [], + "aggregation": "Sum" + }, + "IsQueryContainTimeRange": false + } + } + } + } + } + } + }, + "metadata": { + "model": { + "timeRange": { + "value": { + "relative": { + "duration": 24, + "timeUnit": 1 + } + }, + "type": "MsPortalFx.Composition.Configuration.ValueTypes.TimeRange" + }, + "filterLocale": { + "value": "en-us" + }, + "filters": { + "value": { + "MsPortalFx_TimeRange": { + "model": { + "format": "utc", + "granularity": "auto", + "relative": "24h" + }, + "displayCache": { + "name": "UTC Time", + "value": "Past 24 hours" + }, + "filteredPartIds": [ + "StartboardPart-LogsDashboardPart-6d2eff36-636b-406d-8390-12e2135e700a", + "StartboardPart-LogsDashboardPart-6d2eff36-636b-406d-8390-12e2135e700c", + "StartboardPart-LogsDashboardPart-6d2eff36-636b-406d-8390-12e2135e700d", + "StartboardPart-LogsDashboardPart-6d2eff36-636b-406d-8390-12e2135e700e", + "StartboardPart-LogsDashboardPart-6d2eff36-636b-406d-8390-12e2135e700f" + ] + } + } + } + } + } + } + } + ], + "outputs": { + "results": { + "type": "string", + "value": "The Benchmarking job has been triggered successfully. Please check the storage account you provided for Job Status and Results. The jobs status will be available in a storage table within a few minutes and results will be available once the job finishes." + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh new file mode 100644 index 0000000000..2b41d4d0e4 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#Cloning Test Bench Repo +echo "########## Cloning Test Bench repository ##########" +git clone https://github.com/Azure/azure-cosmos-dotnet-v3.git + +# Build Benchmark Project +cd 'azure-cosmos-dotnet-v3/' +git checkout ${BENCHMARKING_TOOLS_BRANCH_NAME} + +cd 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark' + +echo "########## Build benckmark tool ##########" +dotnet build --configuration Release -p:"OSSProjectRef=true;ShouldUnsetParentConfigurationAndPlatform=false" + +echo "########## Run benchmark ##########" +nohup dotnet run -c Release -e ${COSMOS_URI} -k ${COSMOS_KEY} -t ${THROUGHPUT} -n ${DOCUMENTS} --pl ${PARALLELISM} \ +--enablelatencypercentiles true --resultscontainer ${RESULTS_CONTAINER} --resultspartitionkeyvalue "pk" \ +--DiagnosticsStorageConnectionString ${DIAGNOSTICS_STORAGE_CONNECTION_STRING} \ +--DiagnosticLatencyThresholdInMs ${DIAGNOSTICS_LATENCY_THRESHOLD_IN_MS} \ +--DiagnosticsStorageContainerPrefix ${DIAGNOSTICS_STORAGE_CONTAINER_PREFIX} \ +--MetricsReportingIntervalInSec ${METRICS_REPORTINT_INTERVAL_SEC} \ +--AppInsightsConnectionString ${APP_INSIGHT_CONN_STR} \ +-w ${WORKLOAD_TYPE} \ +> "/home/${ADMIN_USER_NAME}/agent.out" 2> "/home/${ADMIN_USER_NAME}/agent.err" & diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh new file mode 100644 index 0000000000..cf86202002 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +export DOTNET_CLI_HOME=/temp + +cloud-init status --wait +curl -o custom-script.sh $CUSTOM_SCRIPT_URL +bash -x custom-script.sh \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt new file mode 100644 index 0000000000..6821dcaa15 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt @@ -0,0 +1,16 @@ +#cloud-config +package_upgrade: true +packages: + - azure-cli + +runcmd: + - wget https://aka.ms/downloadazcopy-v10-linux + - tar -xvf downloadazcopy-v10-linux + - sudo cp ./azcopy_linux_amd64_*/azcopy /usr/bin/ + - wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb + - sudo dpkg -i packages-microsoft-prod.deb + - sudo apt update + - sudo apt install apt-transport-https -y + - sudo apt install dotnet-sdk-6.0 -y + - sudo apt install dotnet-runtime-6.0 + - sudo apt-get install git \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index f5ff091b28..f69c305096 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -126,6 +126,16 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Container to publish results to")] public string ResultsContainer { get; set; } = "runsummary"; + + [Option(Required = false, HelpText = "Request latency threshold for capturing diagnostic data")] + public int DiagnosticLatencyThresholdInMs { get; set; } = 100; + + [Option(Required = false, HelpText = "Blob storage account connection string")] + [JsonIgnore] + public string DiagnosticsStorageConnectionString { get; set; } + + [Option(Required = false, HelpText = "Blob storage container folder prefix")] + public string DiagnosticsStorageContainerPrefix { get; set; } [Option(Required = false, HelpText = "Metrics reporting interval in seconds")] public int MetricsReportingIntervalInSec { get; set; } = 5; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs index 309eb58c15..5a945d21da 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs @@ -36,9 +36,10 @@ public void LatencyDiagnostics( string dbName, string containerName, int durationInMs, - Func lazyDiagnostics) + Func lazyDiagnostics, + int latencyThreshold) { - if (durationInMs > BenchmarkLatencyEventSource.TraceLatencyThreshold + if (durationInMs > latencyThreshold && this.IsEnabled()) { this.WriteEvent(1, dbName, containerName, durationInMs, lazyDiagnostics()); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs new file mode 100644 index 0000000000..6a7650a5cd --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs @@ -0,0 +1,50 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace CosmosBenchmark +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading.Tasks; + using Newtonsoft.Json; + + /// + /// Represents a class that is used as an item in CosmosDB to track benchmark progress. + /// + public class BenchmarkProgress + { + + /// + /// Record item id + /// + [JsonProperty] + public string id { get; set; } + + /// + /// Machine name + /// + [JsonProperty] + public string MachineName { get; set; } + + /// + /// Job status STARTED|COMPLETED + /// + [JsonProperty] + public string JobStatus { get; set; } + + /// + /// Job start time . + /// + [JsonProperty] + public DateTime JobStartTime { get; set; } + + /// + /// Job end time . + /// + [JsonProperty] + public DateTime JobEndTime { get; set; } + + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj index 2506e48102..073e8daa7a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmark.csproj @@ -17,6 +17,7 @@ + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs new file mode 100644 index 0000000000..1171a05faa --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs @@ -0,0 +1,224 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace CosmosBenchmark.Fx +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.Tracing; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Azure.Storage.Blobs; + + public class DiagnosticDataListener : EventListener + { + /// + /// A constant string representing the container name in Azure Blob Storage. + /// + private const string BlobContainerName = "diagnostics"; + + /// + /// A constant string representing the diagnostics file path. + /// + public const string DiagnosticsFileName = "BenchmarkDiagnostics.out"; + + /// + /// A constant int representing the maximum file size. + /// + private readonly int MaxDIagnosticFileSize = 100_000_000; + + /// + /// A constant int representing the interval at which the file size is checked. + /// + private readonly TimeSpan FileSizeCheckInterval = TimeSpan.FromSeconds(5); + + /// + /// string representing filename prefix in blob storage + /// + private readonly string BlobPrefix = $"{Environment.MachineName}/{Environment.MachineName}"; + + /// + /// Number of files + /// + private int filesCount = 0; + + /// + /// Represents a Blob storage container client instance + /// + private readonly Lazy BlobContainerClient; + + /// + /// Represents a Benchmark Configs + /// + private readonly BenchmarkConfig config; + + /// + /// Current diagnostics optput StreamWriter + /// + private volatile TextWriter Writer; + + /// + /// Current diagnostics optput filename + /// + public volatile string WriterFileName; + + /// + /// List of all previously opened StreamWriters + /// should be stored for later closing, as they may be + /// concurrently accessed by other threads for appending to a file. + /// + private readonly List TextWriters = new List(); + + /// + /// Represents a class that performs writing diagnostic data to a file and uploading it to Azure Blob Storage + /// + public DiagnosticDataListener(BenchmarkConfig config) + { + this.config = config; + this.EnableEvents(BenchmarkLatencyEventSource.Instance, EventLevel.Informational); + this.BlobContainerClient = new Lazy(() => this.GetBlobServiceClient()); + this.Writer = TextWriter.Synchronized(File.AppendText(DiagnosticsFileName)); + this.WriterFileName = DiagnosticsFileName; + + /// + /// Checks the file size every milliseconds for diagnostics and creates a new one if the maximum limit is exceeded. + /// + ThreadPool.QueueUserWorkItem(async state => + { + while (true) + { + try + { + if (File.Exists(this.WriterFileName)) + { + FileInfo fileInfo = new FileInfo(this.WriterFileName); + long fileSize = fileInfo.Length; + + if (fileSize > this.MaxDIagnosticFileSize) + { + string newFilePath = Path.Combine(fileInfo.DirectoryName, $"{DiagnosticsFileName}-{this.filesCount}"); + + File.Create(newFilePath).Close(); + + this.TextWriters.Add(this.Writer); + + this.Writer = TextWriter.Synchronized(File.AppendText($"{newFilePath}")); + this.WriterFileName = newFilePath; + this.filesCount++; + + Utility.TeeTraceInformation("File size exceeded 100MB. Created a new one."); + } + } + + await Task.Delay(this.FileSizeCheckInterval); + + this.CloseStreamWriters(); + } + catch (Exception ex) + { + Utility.TraceError("Exception in file size check loop", ex); + } + } + }); + } + + + /// + /// Listening for events generated by BenchmarkLatencyEventSource + /// + /// An instance of containing the request latency and diagnostics. + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + try + { + this.Writer.WriteLine($"{eventData.Payload[2]} ; {eventData.Payload[3]}"); + } + catch (Exception ex) + { + Utility.TraceError("An exception ocured while writing diagnostic data to the file", ex); + } + } + + /// + /// Uploading all files with diagnostic data to blob storage + /// + public void UploadDiagnostcs() + { + Utility.TeeTraceInformation("Uploading diagnostics"); + string[] diagnosticFiles = Directory.GetFiles(".", $"{DiagnosticsFileName}*"); + string containerPrefix = this.config.DiagnosticsStorageContainerPrefix; + + this.CloseStreamWriters(); + this.SafeCloseCurrentStreamWriter(); + + BlobContainerClient blobContainerClient = this.BlobContainerClient.Value; + for (int i = 0; i < diagnosticFiles.Length; i++) + { + try + { + string diagnosticFile = diagnosticFiles[i]; + Utility.TeeTraceInformation($"Uploading {i + 1} of {diagnosticFiles.Length} file: {diagnosticFile} "); + + string blobName = string.IsNullOrEmpty(containerPrefix) ? + $"{this.BlobPrefix}-{i}.out" : $"{containerPrefix}/{this.BlobPrefix}-{i}.out"; + + BlobClient blobClient = blobContainerClient.GetBlobClient(blobName); + + blobClient.Upload(diagnosticFile, overwrite: true); + } + catch (Exception ex) + { + Utility.TraceError($"An exception ocured while uploading file {this.WriterFileName} to the blob storage", ex); + } + } + } + + /// + /// Closes all unclosed StreamWriters + /// + private void CloseStreamWriters() + { + + this.TextWriters.ForEach(t => + { + try + { + t.Close(); + } + catch (Exception ex) + { + Utility.TraceError("An exception ocured while closing StreamWriters", ex); + } + }); + } + + /// + /// Safe close current StreamWriter + /// + private void SafeCloseCurrentStreamWriter() + { + try + { + this.Writer.Close(); + } + catch (Exception ex) + { + Utility.TraceError("An exception ocured while closing StreamWriters.", ex); + } + } + + /// + /// Creating an instance of BlobClient using configs + /// + private BlobContainerClient GetBlobServiceClient() + { + BlobContainerClient blobContainerClient = new BlobContainerClient( + this.config.DiagnosticsStorageConnectionString, + BlobContainerName); + blobContainerClient.CreateIfNotExists(); + return blobContainerClient; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs index 866e400870..1676dd0052 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs @@ -107,7 +107,7 @@ public MetricsCollector(Meter meter, string prefix) this.successOperationCounter = meter.CreateCounter($"{prefix}OperationSuccess"); this.failureOperationCounter = meter.CreateCounter($"{prefix}OperationFailure"); - + this.latencyInMsMetricNameGauge = this.meter.CreateObservableGauge($"{prefix}OperationLatencyInMs", () => new Measurement(this.latencyInMs)); @@ -140,25 +140,25 @@ public void CollectMetricsOnFailure() /// /// Records success operation latency in milliseconds. /// - /// The number of milliseconds to record. + /// The number of milliseconds to record. public void RecordSuccessOpLatencyAndRps( TimeSpan timeSpan) { - this.rps = 1000 / timeSpan.Milliseconds; - this.latencyInMs = timeSpan.Milliseconds; + this.rps = timeSpan.TotalMilliseconds != 0 ? 1000 / timeSpan.TotalMilliseconds : 0; + this.latencyInMs = timeSpan.TotalMilliseconds; this.rpsMetricNameHistogram.Record(this.rps); this.operationLatencyHistogram.Record(this.latencyInMs); } - + /// /// Records failed operation latency in milliseconds. /// - /// The number of milliseconds to record. + /// The number of milliseconds to record. public void RecordFailedOpLatencyAndRps( TimeSpan timeSpan) { - this.rpsFailed = 1000 / timeSpan.Milliseconds; - this.latencyFailedInMs = timeSpan.Milliseconds; + this.rpsFailed = timeSpan.TotalMilliseconds != 0 ? 1000 / timeSpan.TotalMilliseconds : 0; + this.latencyFailedInMs = timeSpan.TotalMilliseconds; this.rpsFailedMetricNameHistogram.Record(this.rpsFailed); this.operationFailedLatencyHistogram.Record(this.latencyFailedInMs); } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs index 4de7009be1..f49d9ec571 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs @@ -6,6 +6,8 @@ namespace CosmosBenchmark { using System; using System.Diagnostics.Metrics; + using System.Threading; + using System.Threading.Tasks; using OpenTelemetry.Metrics; /// @@ -13,7 +15,10 @@ namespace CosmosBenchmark /// internal class MetricsCollectorProvider { - private readonly MetricCollectionWindow metricCollectionWindow; + private const int WindowCheckInterval = 10; + private MetricCollectionWindow metricCollectionWindow; + + private static readonly object metricCollectionWindowLock = new object(); private readonly MetricsCollector insertOperationMetricsCollector; @@ -36,6 +41,38 @@ public MetricsCollectorProvider(BenchmarkConfig config, MeterProvider meterProvi this.queryOperationMetricsCollector ??= new MetricsCollector(this.queryOperationMeter, "Query"); this.readOperationMetricsCollector ??= new MetricsCollector(this.readOperationMeter, "Read"); this.metricCollectionWindow ??= new MetricCollectionWindow(config); + + /// + /// Flush metrics every + /// + ThreadPool.QueueUserWorkItem(async state => + { + while (true) + { + MetricCollectionWindow metricCollectionWindow = this.GetCurrentMetricCollectionWindow(config); + + // Reset metricCollectionWindow and flush. + if (!metricCollectionWindow.IsValid) + { + this.meterProvider.ForceFlush(); + this.metricCollectionWindow.Reset(config); + } + await Task.Delay(TimeSpan.FromMilliseconds(MetricsCollectorProvider.WindowCheckInterval)); + } + }); + } + + private MetricCollectionWindow GetCurrentMetricCollectionWindow(BenchmarkConfig config) + { + if (this.metricCollectionWindow is null || !this.metricCollectionWindow.IsValid) + { + lock (metricCollectionWindowLock) + { + this.metricCollectionWindow ??= new MetricCollectionWindow(config); + } + } + + return this.metricCollectionWindow; } /// /// The response headers - /// The encoding of the IndexMetrics response + /// The encoding of the IndexMetrics response /// Lazy implementation of the pretty-printed IndexMetrics - static internal Lazy DecodeIndexMetrics(Headers responseMessageHeaders, bool isBse64Encoded) + static internal Lazy DecodeIndexMetrics(Headers responseMessageHeaders, bool isBase64Encoded) { if (responseMessageHeaders?.IndexUtilizationText != null) { return new Lazy(() => { - IndexUtilizationInfo parsedIndexUtilizationInfo = IndexUtilizationInfo.CreateFromString(responseMessageHeaders.IndexUtilizationText, isBse64Encoded); - - StringBuilder stringBuilder = new StringBuilder(); - IndexMetricWriter indexMetricWriter = new IndexMetricWriter(stringBuilder); - indexMetricWriter.WriteIndexMetrics(parsedIndexUtilizationInfo); + if (isBase64Encoded) + { + IndexUtilizationInfo parsedIndexUtilizationInfo = IndexUtilizationInfo.CreateFromString(responseMessageHeaders.IndexUtilizationText); - return stringBuilder.ToString(); + StringBuilder stringBuilder = new StringBuilder(); + IndexMetricsWriter indexMetricWriter = new IndexMetricsWriter(stringBuilder); + indexMetricWriter.WriteIndexMetrics(parsedIndexUtilizationInfo); + + return stringBuilder.ToString(); + } + + // Return the JSON from the response header + return responseMessageHeaders.IndexUtilizationText; }); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/CompositeIndexIndexMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/CompositeIndexIndexMetrics.cs new file mode 100644 index 0000000000..5ee147dc87 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/CompositeIndexIndexMetrics.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + + /// + /// Query index utilization data for composite indexes (sub-structure of the Index Metrics class) in the Azure Cosmos database service. + /// + #if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class CompositeIndexIndexMetrics + { + /// + /// Initialized a new instance of an Index Metrics' Composite Index class. + /// + /// The string list representation of the composite index. + /// The index impact score. + [JsonConstructor] + private CompositeIndexIndexMetrics( + IReadOnlyList indexDocumentExpressions, + string indexImpactScore) + { + this.IndexSpecs = indexDocumentExpressions; + this.IndexImpactScore = indexImpactScore; + } + + /// + /// String list representation of index paths of a composite index. + /// + [JsonProperty(PropertyName = "IndexSpecs")] + public IReadOnlyList IndexSpecs { get; } + + /// + /// The index impact score of the composite index. + /// + [JsonProperty(PropertyName = "IndexImpactScore")] + public string IndexImpactScore { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfo.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfo.cs new file mode 100644 index 0000000000..4156e520a7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfo.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Microsoft.Azure.Cosmos.Core; + using Microsoft.Azure.Cosmos.Core.Utf8; + using Newtonsoft.Json; + + /// + /// Query index utilization data for composite indexes (sub-structure of the Index Metrics class) in the Azure Cosmos database service. + /// +#if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class IndexMetricsInfo + { + /// + /// Initializes a new instance of the Index Metrics class. + /// + /// The utilized indexes + /// The potential indexes + [JsonConstructor] + public IndexMetricsInfo( + IndexMetricsInfoEntity utilizedEntity, + IndexMetricsInfoEntity potentialEntity) + { + this.UtilizedEntity = utilizedEntity; + this.PotentialEntity = potentialEntity; + } + + [JsonProperty("Utilized")] + public IndexMetricsInfoEntity UtilizedEntity { get; } + + [JsonProperty("Potential")] + public IndexMetricsInfoEntity PotentialEntity { get; } + + /// + /// Creates a new IndexMetricsInfo from the backend delimited string. + /// + /// The backend delimited string to deserialize from. + /// The parsed index utilization info + /// A new IndexMetricsInfo from the backend delimited string. + public static bool TryCreateFromString(string delimitedString, out IndexMetricsInfo result) + { + if (delimitedString == null) + { + result = null; + return false; + } + + try + { + // Decode and deserialize the response string + string decodedString = System.Web.HttpUtility.UrlDecode(delimitedString, Encoding.UTF8); + + result = JsonConvert.DeserializeObject(decodedString, new JsonSerializerSettings() + { + // Allowing null values to be resilient to Json structure change + MissingMemberHandling = MissingMemberHandling.Ignore, + NullValueHandling = NullValueHandling.Ignore, + // Ignore parsing error encountered in deserialization + Error = (sender, parsingErrorEvent) => parsingErrorEvent.ErrorContext.Handled = true + }) ?? null; + + return true; + } + catch (JsonException) + { + result = null; + return false; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfoEntity.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfoEntity.cs new file mode 100644 index 0000000000..69a0f3270a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfoEntity.cs @@ -0,0 +1,43 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using Microsoft.Azure.Cosmos.Core; + using Microsoft.Azure.Cosmos.Core.Utf8; + using Newtonsoft.Json; + + /// + /// Query index utilization metrics in the Azure Cosmos database service. + /// +#if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class IndexMetricsInfoEntity + { + /// + /// Initializes a new instance of the Index Utilization class. This is the legacy class of IndexMetricsInfoEntity. + /// + /// The utilized single indexes list + /// The potential single indexes list + [JsonConstructor] + public IndexMetricsInfoEntity( + IReadOnlyList singleIndexes, + IReadOnlyList compositeIndexes) + { + this.SingleIndexes = (singleIndexes ?? Enumerable.Empty()).Where(item => item != null).ToList(); + this.CompositeIndexes = (compositeIndexes ?? Enumerable.Empty()).Where(item => item != null).ToList(); + } + + public IReadOnlyList SingleIndexes { get; } + public IReadOnlyList CompositeIndexes { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricWriter.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsWriter.cs similarity index 65% rename from Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricWriter.cs rename to Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsWriter.cs index 7deb1f767b..138275fda9 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsWriter.cs @@ -9,7 +9,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics using System.Text; /// - /// Base class for visiting and serializing a . + /// Base class for visiting and serializing a . /// #if INTERNAL #pragma warning disable SA1600 @@ -18,7 +18,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics #else internal #endif - class IndexMetricWriter + class IndexMetricsWriter { private const string IndexUtilizationInfo = "Index Utilization Information"; private const string UtilizedSingleIndexes = "Utilized Single Indexes"; @@ -32,7 +32,7 @@ class IndexMetricWriter private readonly StringBuilder stringBuilder; - public IndexMetricWriter(StringBuilder stringBuilder) + public IndexMetricsWriter(StringBuilder stringBuilder) { this.stringBuilder = stringBuilder ?? throw new ArgumentNullException($"{nameof(stringBuilder)} must not be null."); } @@ -50,37 +50,37 @@ public void WriteIndexMetrics(IndexUtilizationInfo indexUtilizationInfo) #region IndexUtilizationInfo protected void WriteBeforeIndexUtilizationInfo() { - IndexMetricWriter.AppendNewlineToStringBuilder(this.stringBuilder); - IndexMetricWriter.AppendHeaderToStringBuilder( + IndexMetricsWriter.AppendNewlineToStringBuilder(this.stringBuilder); + IndexMetricsWriter.AppendHeaderToStringBuilder( this.stringBuilder, - IndexMetricWriter.IndexUtilizationInfo, + IndexMetricsWriter.IndexUtilizationInfo, indentLevel: 0); } protected void WriteIndexUtilizationInfo(IndexUtilizationInfo indexUtilizationInfo) { - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.UtilizedSingleIndexes, indentLevel: 1); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.UtilizedSingleIndexes, indentLevel: 1); foreach (SingleIndexUtilizationEntity indexUtilizationEntity in indexUtilizationInfo.UtilizedSingleIndexes) { WriteSingleIndexUtilizationEntity(indexUtilizationEntity); } - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.PotentialSingleIndexes, indentLevel: 1); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.PotentialSingleIndexes, indentLevel: 1); foreach (SingleIndexUtilizationEntity indexUtilizationEntity in indexUtilizationInfo.PotentialSingleIndexes) { WriteSingleIndexUtilizationEntity(indexUtilizationEntity); } - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.UtilizedCompositeIndexes, indentLevel: 1); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.UtilizedCompositeIndexes, indentLevel: 1); foreach (CompositeIndexUtilizationEntity indexUtilizationEntity in indexUtilizationInfo.UtilizedCompositeIndexes) { WriteCompositeIndexUtilizationEntity(indexUtilizationEntity); } - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.PotentialCompositeIndexes, indentLevel: 1); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.PotentialCompositeIndexes, indentLevel: 1); foreach (CompositeIndexUtilizationEntity indexUtilizationEntity in indexUtilizationInfo.PotentialCompositeIndexes) { @@ -89,16 +89,16 @@ protected void WriteIndexUtilizationInfo(IndexUtilizationInfo indexUtilizationIn void WriteSingleIndexUtilizationEntity(SingleIndexUtilizationEntity indexUtilizationEntity) { - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricWriter.IndexExpression}: {indexUtilizationEntity.IndexDocumentExpression}", indentLevel: 2); - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricWriter.IndexImpactScore}: {indexUtilizationEntity.IndexImpactScore}", indentLevel: 2); - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.IndexUtilizationSeparator, indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricsWriter.IndexExpression}: {indexUtilizationEntity.IndexDocumentExpression}", indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricsWriter.IndexImpactScore}: {indexUtilizationEntity.IndexImpactScore}", indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.IndexUtilizationSeparator, indentLevel: 2); } void WriteCompositeIndexUtilizationEntity(CompositeIndexUtilizationEntity indexUtilizationEntity) { - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricWriter.IndexExpression}: {String.Join(", ", indexUtilizationEntity.IndexDocumentExpressions)}", indentLevel: 2); - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricWriter.IndexImpactScore}: {indexUtilizationEntity.IndexImpactScore}", indentLevel: 2); - IndexMetricWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricWriter.IndexUtilizationSeparator, indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricsWriter.IndexExpression}: {String.Join(", ", indexUtilizationEntity.IndexDocumentExpressions)}", indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, $"{IndexMetricsWriter.IndexImpactScore}: {indexUtilizationEntity.IndexImpactScore}", indentLevel: 2); + IndexMetricsWriter.AppendHeaderToStringBuilder(this.stringBuilder, IndexMetricsWriter.IndexUtilizationSeparator, indentLevel: 2); } } @@ -123,7 +123,7 @@ private static void AppendHeaderToStringBuilder(StringBuilder stringBuilder, str private static void AppendNewlineToStringBuilder(StringBuilder stringBuilder) { - IndexMetricWriter.AppendHeaderToStringBuilder( + IndexMetricsWriter.AppendHeaderToStringBuilder( stringBuilder, string.Empty, indentLevel: 0); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs index e34a7902ad..a9ef4569b5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics using System.Linq; using System.Text; using Microsoft.Azure.Cosmos.Core; + using Microsoft.Azure.Cosmos.Core.Utf8; using Newtonsoft.Json; /// @@ -29,7 +30,7 @@ sealed class IndexUtilizationInfo potentialCompositeIndexes: new List()); /// - /// Initializes a new instance of the Index Utilization class. + /// Initializes a new instance of the Index Utilization class. This is the legacy class of IndexMetricsInfo. /// /// The utilized single indexes list /// The potential single indexes list @@ -60,23 +61,6 @@ public IndexUtilizationInfo( /// The parsed index utilization info /// A new IndexUtilizationInfo from the backend delimited string. internal static bool TryCreateFromDelimitedBase64String(string delimitedString, out IndexUtilizationInfo result) - { - if (delimitedString == null) - { - result = IndexUtilizationInfo.Empty; - return true; - } - - return TryCreateFromDelimitedString(System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(delimitedString)), out result); - } - - /// - /// Creates a new IndexUtilizationInfo from the backend delimited string. - /// - /// The backend delimited string to deserialize from. - /// The parsed index utilization info - /// A new IndexUtilizationInfo from the backend delimited string. - internal static bool TryCreateFromDelimitedString(string delimitedString, out IndexUtilizationInfo result) { if (delimitedString == null) { @@ -84,9 +68,15 @@ internal static bool TryCreateFromDelimitedString(string delimitedString, out In return true; } + // Even though this parsing is resilient, older version of the SDK doesn't have such lenient parsing. + // As such, it is right not not possible to remove some of the field in the IndexUtilizationInfo class. + // However, in newer version of the SDKs, the code base is going to start returning IndexMetricsInfo, + // so this class exists solely for legacy support. try { - result = JsonConvert.DeserializeObject(delimitedString, new JsonSerializerSettings() + string decodedString = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(delimitedString)); + + result = JsonConvert.DeserializeObject(decodedString, new JsonSerializerSettings() { // Allowing null values to be resilient to Json structure change MissingMemberHandling = MissingMemberHandling.Ignore, @@ -108,20 +98,10 @@ internal static bool TryCreateFromDelimitedString(string delimitedString, out In /// Materialize the Index Utilization String into Concrete objects. /// /// The index utilization response string as sent by the back end. - /// The encoding of the string. /// Cpncrete Index utilization object. - public static IndexUtilizationInfo CreateFromString(string delimitedString, bool isBse64Encoded) + public static IndexUtilizationInfo CreateFromString(string delimitedString) { - IndexUtilizationInfo indexUtilizationInfo; - - if (isBse64Encoded) - { - TryCreateFromDelimitedBase64String(delimitedString, out indexUtilizationInfo); - } - else - { - TryCreateFromDelimitedString(delimitedString, out indexUtilizationInfo); - } + TryCreateFromDelimitedBase64String(delimitedString, out IndexUtilizationInfo indexUtilizationInfo); return indexUtilizationInfo; } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/SingleIndexIndexMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/SingleIndexIndexMetrics.cs new file mode 100644 index 0000000000..2c8826c3ea --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/SingleIndexIndexMetrics.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using Newtonsoft.Json; + + /// + /// Query index utilization data for single indexes (sub-structure of the Index Metrics class) in the Azure Cosmos database service. + /// + #if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class SingleIndexIndexMetrics + { + /// + /// Initialized a new instance of an Index Metrics' Single Index class. + /// + /// The string representation of the single index. + /// The index impact score. + [JsonConstructor] + public SingleIndexIndexMetrics( + string indexDocumentExpression, + string indexImpactScore) + { + this.IndexDocumentExpression = indexDocumentExpression; + this.IndexImpactScore = indexImpactScore; + } + + /// + /// String representation of index paths of a composite index. + /// + [JsonProperty(PropertyName = "IndexSpec")] + public string IndexDocumentExpression { get; } + + /// + /// The index impact score of the single index. + /// + [JsonProperty(PropertyName = "IndexImpactScore")] + public string IndexImpactScore { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs index b53c3c5c71..9895bd5f5a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DefaultDocumentQueryExecutionContext.cs @@ -108,7 +108,7 @@ protected override async Task> ExecuteIntern partitionIdentifier, new QueryMetrics( response.ResponseHeaders[HttpConstants.HttpHeaders.QueryMetrics], - IndexUtilizationInfo.CreateFromString(response.ResponseHeaders[HttpConstants.HttpHeaders.IndexUtilization], true), + IndexUtilizationInfo.CreateFromString(response.ResponseHeaders[HttpConstants.HttpHeaders.IndexUtilization]), new ClientSideMetrics( this.retries, response.RequestCharge, diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs index 6c7777ebff..47c9136a8f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Query.Core.Metrics; using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; /// /// Represents the template class used by feed methods (enumeration operations) for the Azure Cosmos DB service. @@ -183,7 +184,13 @@ private QueryResponse( cosmosArray: cosmosElements, serializerCore: serializerCore); - this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics(responseMessageHeaders, true); + // Chose how to decode depending on which PopulateIndexMetrics request header was sent + // If none was sent, we currently default to V1 + // TODO: Switch the flag to false once V2 is deployed + this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics( + responseMessageHeaders, + isBase64Encoded: true); + this.RequestMessage = requestMessage; } diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index f723107ede..2b4aba5ac0 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -269,6 +269,7 @@ internal override void PopulateRequestOptions(RequestMessage request) if (this.PopulateIndexMetrics.HasValue) { + // TODO: Switch to V2 request.Headers.CosmosMessageHeaders.Add(HttpConstants.HttpHeaders.PopulateIndexMetrics, this.PopulateIndexMetrics.ToString()); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index 6ae91f1375..598ee51c9d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -133,6 +133,7 @@ public void IndexUtilizationParse() public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestInput input) { + // V2 QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true }; FeedIterator itemQuery = testContainer.GetItemQueryIterator( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PopulateIndexMetricsTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PopulateIndexMetricsTest.cs index 29f1944643..084e7738a5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PopulateIndexMetricsTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/PopulateIndexMetricsTest.cs @@ -35,14 +35,6 @@ static async Task ImplementationAsync(Container container, IReadOnlyList 12"); - // Build the expected string - Assert.IsTrue(IndexUtilizationInfo.TryCreateFromDelimitedBase64String("eyJVdGlsaXplZFNpbmdsZUluZGV4ZXMiOlt7IkZpbHRlckV4cHJlc3Npb24iOiIoUk9PVC5uYW1lID0gXCJBQkNcIikiLCJJbmRleFNwZWMiOiJcL25hbWVcLz8iLCJGaWx0ZXJQcmVjaXNlU2V0Ijp0cnVlLCJJbmRleFByZWNpc2VTZXQiOnRydWUsIkluZGV4SW1wYWN0U2NvcmUiOiJIaWdoIn0seyJGaWx0ZXJFeHByZXNzaW9uIjoiKFJPT1QuYWdlID4gMTIpIiwiSW5kZXhTcGVjIjoiXC9hZ2VcLz8iLCJGaWx0ZXJQcmVjaXNlU2V0Ijp0cnVlLCJJbmRleFByZWNpc2VTZXQiOnRydWUsIkluZGV4SW1wYWN0U2NvcmUiOiJIaWdoIn1dLCJQb3RlbnRpYWxTaW5nbGVJbmRleGVzIjpbXSwiVXRpbGl6ZWRDb21wb3NpdGVJbmRleGVzIjpbXSwiUG90ZW50aWFsQ29tcG9zaXRlSW5kZXhlcyI6W3siSW5kZXhTcGVjcyI6WyJcL25hbWUgQVNDIiwiXC9hZ2UgQVNDIl0sIkluZGV4UHJlY2lzZVNldCI6ZmFsc2UsIkluZGV4SW1wYWN0U2NvcmUiOiJIaWdoIn1dfQ==", - out IndexUtilizationInfo parsedInfo)); - StringBuilder stringBuilder = new StringBuilder(); - IndexMetricWriter indexMetricWriter = new IndexMetricWriter(stringBuilder); - indexMetricWriter.WriteIndexMetrics(parsedInfo); - string expectedIndexMetricsString = stringBuilder.ToString(); - // Test using GetItemQueryIterator QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true }; @@ -56,7 +48,6 @@ static async Task ImplementationAsync(Container container, IReadOnlyList 1); Assert.IsNotNull(page.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); Assert.IsNotNull(page.IndexMetrics, "Expected index metrics response for query"); - Assert.AreEqual(expectedIndexMetricsString, page.IndexMetrics); } // Test using Stream API @@ -73,7 +64,6 @@ static async Task ImplementationAsync(Container container, IReadOnlyList 1); Assert.IsNotNull(response.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); - Assert.AreEqual(expectedIndexMetricsString, response.IndexMetrics); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index d971223f09..762bbbd945 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -2292,7 +2292,7 @@ private async Task ValidateQueryMetricsHeadersOverContinuations( QueryMetrics queryMetrics = new QueryMetrics( responseQueryMetrics, - IndexUtilizationInfo.CreateFromString(indexUtilization, true), + IndexUtilizationInfo.CreateFromString(indexUtilization), ClientSideMetrics.Empty); this.ValidateQueryMetrics(queryMetrics); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs index 9fe272a6bd..b3bce119dd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs @@ -97,9 +97,7 @@ private static void TestParses(bool isBase64Encoded) } else { - Assert.IsTrue(IndexUtilizationInfo.TryCreateFromDelimitedString(testString, - out IndexUtilizationInfo parsedInfo)); - Assert.IsNotNull(parsedInfo); + Assert.IsTrue(IndexMetricsInfo.TryCreateFromString(testString, out _)); } } } From 08e7f54730f01452ebb05ed255285e91668a17e3 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 26 Sep 2023 19:38:47 +0530 Subject: [PATCH 196/337] Distributed Tracing: Fixes dependency failure on appinsights (#4098) * first draft * refactor * fix tests * fixed condition --- .../OpenTelemetry/CosmosDbEventSource.cs | 2 +- .../Filters/DiagnosticsFilterHelper.cs | 16 ++--- .../OpenTelemetryCoreRecorder.cs | 15 +++- .../Tracing/AssertActivity.cs | 68 +++++++++++-------- .../Telemetry/DiagnosticsFilterHelperTest.cs | 3 +- 5 files changed, 61 insertions(+), 43 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index 9e8028c0d8..8898cea96d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -36,7 +36,7 @@ public static void RecordDiagnosticsForRequests( OpenTelemetryAttributes response) { if (!DiagnosticsFilterHelper.IsSuccessfulResponse( - response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) + response.StatusCode, response.SubStatusCode) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) { CosmosDbEventSource.Singleton.FailedRequest(response.Diagnostics.ToString()); } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index a5ca0215cb..d48392bb3e 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -5,8 +5,8 @@ namespace Microsoft.Azure.Cosmos.Telemetry.Diagnostics { using System; + using System.Net; using Documents; - using static Antlr4.Runtime.TokenStreamRewriter; internal static class DiagnosticsFilterHelper { @@ -39,13 +39,13 @@ public static bool IsLatencyThresholdCrossed( /// Check if response HTTP status code is returning successful /// /// true or false - public static bool IsSuccessfulResponse(OpenTelemetryAttributes response) - { - return response.StatusCode.IsSuccess() - || (response.StatusCode == System.Net.HttpStatusCode.NotFound && response.SubStatusCode == 0) - || (response.StatusCode == System.Net.HttpStatusCode.NotModified && response.SubStatusCode == 0) - || (response.StatusCode == System.Net.HttpStatusCode.Conflict && response.SubStatusCode == 0) - || (response.StatusCode == System.Net.HttpStatusCode.PreconditionFailed && response.SubStatusCode == 0); + public static bool IsSuccessfulResponse(HttpStatusCode statusCode, int substatusCode) + { + return statusCode.IsSuccess() + || (statusCode == System.Net.HttpStatusCode.NotFound && substatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.NotModified && substatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.Conflict && substatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.PreconditionFailed && substatusCode == 0); } /// diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 2ef929ca8c..ced441d368 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System.Collections.Generic; using System.Diagnostics; using global::Azure.Core; + using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; /// /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 @@ -177,7 +178,12 @@ public void MarkFailed(Exception exception) this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message); } - this.scope.Failed(exception); + if (exception is not CosmosException || (exception is CosmosException cosmosException + && !DiagnosticsFilterHelper + .IsSuccessfulResponse(cosmosException.StatusCode, cosmosException.SubStatusCode))) + { + this.scope.Failed(exception); + } } } @@ -205,7 +211,7 @@ internal static bool IsExceptionRegistered(Exception exception, DiagnosticScope public void Dispose() { - if (this.scope.IsEnabled) + if (this.IsEnabled) { Documents.OperationType operationType = (this.response == null || this.response?.OperationType == Documents.OperationType.Invalid) ? this.operationType : this.response.OperationType; @@ -228,6 +234,11 @@ Documents.OperationType operationType this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(this.response.Diagnostics.GetContactedRegions())); CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, operationType, this.response); } + + if (!DiagnosticsFilterHelper.IsSuccessfulResponse(this.response.StatusCode, this.response.SubStatusCode)) + { + this.scope.Failed(); + } } this.scope.Dispose(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index 75153d3b88..9b9be4479a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -8,8 +8,9 @@ namespace Microsoft.Azure.Cosmos.Tracing using System.Collections.Generic; using System.Diagnostics; using System.Linq; - using global::Azure; + using System.Net; using Microsoft.Azure.Cosmos.Telemetry; + using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; using Microsoft.Azure.Cosmos.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; @@ -32,35 +33,35 @@ public static void IsValidOperationActivity(Activity activity) } IList expectedTags = new List - { - "az.namespace", - "az.schema_url", - "kind", - "db.system", - "db.name", - "db.operation", - "net.peer.name", - "db.cosmosdb.client_id", - "db.cosmosdb.machine_id", - "user_agent.original", - "db.cosmosdb.connection_mode", - "db.cosmosdb.operation_type", - "db.cosmosdb.container", - "db.cosmosdb.request_content_length_bytes", - "db.cosmosdb.response_content_length_bytes", - "db.cosmosdb.status_code", - "db.cosmosdb.sub_status_code", - "db.cosmosdb.request_charge", - "db.cosmosdb.regions_contacted", - "db.cosmosdb.retry_count", - "db.cosmosdb.item_count", - "db.cosmosdb.request_diagnostics", - "exception.type", - "exception.message", - "exception.stacktrace", - "db.cosmosdb.activity_id", - "db.cosmosdb.correlated_activity_id" - }; + { + "az.namespace", + "az.schema_url", + "kind", + "db.system", + "db.name", + "db.operation", + "net.peer.name", + "db.cosmosdb.client_id", + "db.cosmosdb.machine_id", + "user_agent.original", + "db.cosmosdb.connection_mode", + "db.cosmosdb.operation_type", + "db.cosmosdb.container", + "db.cosmosdb.request_content_length_bytes", + "db.cosmosdb.response_content_length_bytes", + "db.cosmosdb.status_code", + "db.cosmosdb.sub_status_code", + "db.cosmosdb.request_charge", + "db.cosmosdb.regions_contacted", + "db.cosmosdb.retry_count", + "db.cosmosdb.item_count", + "db.cosmosdb.request_diagnostics", + "exception.type", + "exception.message", + "exception.stacktrace", + "db.cosmosdb.activity_id", + "db.cosmosdb.correlated_activity_id" + }; foreach (KeyValuePair actualTag in activity.Tags) { @@ -68,6 +69,13 @@ public static void IsValidOperationActivity(Activity activity) AssertActivity.AssertDatabaseAndContainerName(activity.OperationName, actualTag); } + + HttpStatusCode statusCode = (HttpStatusCode)Convert.ToInt32(activity.GetTagItem("db.cosmosdb.status_code")); + int subStatusCode = Convert.ToInt32(activity.GetTagItem("db.cosmosdb.sub_status_code")); + if (!DiagnosticsFilterHelper.IsSuccessfulResponse(statusCode, subStatusCode)) + { + Assert.AreEqual(ActivityStatusCode.Error, activity.Status); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index e345394265..5e32b26da1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -71,11 +71,10 @@ public void CheckReturnTrueOnFailedStatusCode() Assert.IsTrue( !DiagnosticsFilterHelper - .IsSuccessfulResponse(response), + .IsSuccessfulResponse(response.StatusCode, response.SubStatusCode), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); - } } From 455656753e115d1667bbaa0ae8689a2f3686a6d2 Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:38:58 -0700 Subject: [PATCH 197/337] [Internal] Query: Adds deserializing logic for ClientQL Coordinator Distribution Plan (#3988) * First commit. * Added remaining classes for ClientQL structure * Added ClientQLDeserializing class and added CoordinatorDistributionPlan folder * Added support for all Enumerable and Scalar Expressions * Added baseline tests for testing CoordinatorDistributionPlan deserializing * Made ClientQL objects immutable * Added error and null checks for Value calls * Updated List<> with IReadOnlyList<> * Made most functions in the Deserializing class private and static * Added static constant class for Enumerable expressions * Added null checking for arrays * Removed null checks from deserializing array functions * Removed support for JavaScript * Removed support for Unwind * Function names changed * Removed few functions. * Updated constants class * Function Formatting for ClientQL Deserializing (#4062) * Adding error handling for Deserializing functions * Finished updating code to remove all dependency on Newtonsoft.Json * Removed try catch for all upper level functions * Resolved comments * Resolved comments pt2 * Updated error message * Resolved comments pt3 * Changed parameter types from int to long * Removed ClientQLDelegate * Syntax Fixes * Removed ClientQLFlattenEnumerable file. This is JS. * Fixed List helper functions * Made singleton constructors from public to private * Updated the DeserializeClientQLBinaryLiteral function * Renamed ClientQL to QL * Fixed variable names * Updated more variable names * Removed support for Type * Removed all extra newlines * Added null checks * Updated the name CoordinatorDistributionPlan to ClientDistributionPlan * Removed all support for Cassandra, Mongo and Binary Literal * Updaed ClientQL to Cql * Updated baseline test class property. --- .../ClientDistributionPlanDeserializer.cs | 561 ++++++++++++++++ .../Cql/ClientDistributionPlan.cs | 18 + .../Cql/CqlAggregate.cs | 16 + .../Cql/CqlAggregateEnumerableExpression.cs | 22 + .../Cql/CqlAggregateKind.cs | 12 + .../Cql/CqlAggregateOperatorKind.cs | 19 + .../Cql/CqlArrayCreateScalarExpression.cs | 25 + .../Cql/CqlArrayIndexerScalarExpression.cs | 22 + .../Cql/CqlArrayLiteral.cs | 20 + .../Cql/CqlBinaryScalarExpression.cs | 25 + .../Cql/CqlBinaryScalarOperatorKind.cs | 29 + .../Cql/CqlBooleanLiteral.cs | 17 + .../Cql/CqlBuiltinAggregate.cs | 17 + .../Cql/CqlBuiltinScalarFunctionKind.cs | 126 ++++ .../Cql/CqlDistinctEnumerableExpression.cs | 26 + .../Cql/CqlEnumerableExpression.cs | 16 + .../Cql/CqlEnumerableExpressionKind.cs | 20 + .../Cql/CqlEnumerationKind.cs | 14 + .../Cql/CqlFunctionIdentifier.cs | 18 + .../Cql/CqlGroupByEnumerableExpression.cs | 26 + .../Cql/CqlInputEnumerableExpression.cs | 19 + .../Cql/CqlIsOperatorKind.cs | 11 + .../Cql/CqlIsOperatorScalarExpression.cs | 23 + .../Cql/CqlLetScalarExpression.cs | 25 + .../ClientDistributionPlan/Cql/CqlLiteral.cs | 16 + .../Cql/CqlLiteralKind.cs | 17 + .../Cql/CqlLiteralScalarExpression.cs | 19 + .../Cql/CqlMuxScalarExpression.cs | 25 + .../Cql/CqlNullLiteral.cs | 16 + .../Cql/CqlNumberLiteral.cs | 19 + .../Cql/CqlObjectCreateScalarExpression.cs | 25 + .../Cql/CqlObjectLiteral.cs | 20 + .../Cql/CqlObjectLiteralProperty.cs | 21 + .../Cql/CqlObjectProperty.cs | 21 + .../Cql/CqlOrderByEnumerableExpression.cs | 26 + .../Cql/CqlOrderByItem.cs | 21 + .../Cql/CqlPropertyRefScalarExpression.cs | 23 + .../Cql/CqlScalarAsEnumerableExpression.cs | 22 + .../Cql/CqlScalarExpression.cs | 16 + .../Cql/CqlScalarExpressionKind.cs | 25 + .../Cql/CqlSelectEnumerableExpression.cs | 25 + .../Cql/CqlSelectManyEnumerableExpression.cs | 25 + .../Cql/CqlSortOrder.cs | 12 + .../Cql/CqlStringLiteral.cs | 19 + .../CqlSystemFunctionCallScalarExpression.cs | 23 + .../Cql/CqlTakeEnumerableExpression.cs | 25 + .../Cql/CqlTupleAggregate.cs | 20 + .../Cql/CqlTupleCreateScalarExpression.cs | 20 + .../Cql/CqlTupleItemRefScalarExpression.cs | 22 + .../Cql/CqlUnaryScalarExpression.cs | 22 + .../Cql/CqlUnaryScalarOperatorKind.cs | 14 + .../Cql/CqlUndefinedLiteral.cs | 16 + ...UserDefinedFunctionCallScalarExpression.cs | 26 + .../ClientDistributionPlan/Cql/CqlVariable.cs | 21 + .../Cql/CqlVariableRefScalarExpression.cs | 19 + .../Cql/CqlWhereEnumerableExpression.cs | 25 + ...tClientDistributionPlanDeserialization.xml | 606 ++++++++++++++++++ .../Microsoft.Azure.Cosmos.Tests.csproj | 3 + .../ClientDistributionPlanBaselineTests.cs | 100 +++ 59 files changed, 2502 insertions(+) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs new file mode 100644 index 0000000000..df19b88b3d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs @@ -0,0 +1,561 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan +{ + using System; + using System.Collections.Generic; + using System.Reflection; + using Cql; + using Microsoft.Azure.Cosmos.CosmosElements; + + internal static class ClientDistributionPlanDeserializer + { + private static class Constants + { + public const string Arguments = "Arguments"; + public const string ArrayKind = "ArrayKind"; + public const string Aggregate = "Aggregate"; + public const string Aggregates = "Aggregates"; + public const string Builtin = "Builtin"; + public const string Cql = "Cql"; + public const string ConditionExpression = "ConditionExpression"; + public const string ClientDistributionPlan = "clientDistributionPlan"; + public const string DeclaredVariable = "DeclaredVariable"; + public const string DeclaredVariableExpression = "DeclaredVariableExpression"; + public const string Distinct = "Distinct"; + public const string EnumerationKind = "EnumerationKind"; + public const string Expression = "Expression"; + public const string FunctionKind = "FunctionKind"; + public const string GroupBy = "GroupBy"; + public const string Identifier = "Identifier"; + public const string Index = "Index"; + public const string Input = "Input"; + public const string Items = "Items"; + public const string KeyCount = "KeyCount"; + public const string Kind = "Kind"; + public const string LeftExpression = "LeftExpression"; + public const string Literal = "Literal"; + public const string MaxDepth = "MaxDepth"; + public const string Name = "Name"; + public const string ObjectKind = "ObjectKind"; + public const string OperatorKind = "OperatorKind"; + public const string Options = "Options"; + public const string OrderBy = "OrderBy"; + public const string Pattern = "Pattern"; + public const string Properties = "Properties"; + public const string PropertyName = "PropertyName"; + public const string RightExpression = "RightExpression"; + public const string ScalarAsEnumerable = "ScalarAsEnumerable"; + public const string Select = "Select"; + public const string SelectorExpression = "SelectorExpression"; + public const string SelectMany = "SelectMany"; + public const string SingletonKind = "SingletonKind"; + public const string SkipValue = "SkipValue"; + public const string SortOrder = "SortOrder"; + public const string SourceExpression = "SourceExpression"; + public const string Take = "Take"; + public const string TakeValue = "TakeValue"; + public const string Tuple = "Tuple"; + public const string Type = "Type"; + public const string UniqueId = "UniqueId"; + public const string Value = "Value"; + public const string Variable = "Variable"; + public const string Where = "Where"; + } + + public static ClientDistributionPlan DeserializeClientDistributionPlan(string jsonString) + { + CosmosObject cosmosObject = CosmosObject.Parse(jsonString); + CosmosObject clientDistributionPlanElement = GetValue(cosmosObject, Constants.ClientDistributionPlan); + CosmosObject cqlElement = GetValue(clientDistributionPlanElement, Constants.Cql); + CqlEnumerableExpression expression = DeserializeCqlEnumerableExpression(cqlElement); + + return new ClientDistributionPlan(expression); + } + + #region Enumerable Expressions + + private static CqlEnumerableExpression DeserializeCqlEnumerableExpression(CosmosObject cosmosObject) + { + CosmosString kindProperty = GetValue(cosmosObject, Constants.Kind); + switch (kindProperty.Value) + { + case Constants.Aggregate: + return DeserializeAggregateEnumerableExpression(cosmosObject); + case Constants.Distinct: + return DeserializeDistinctEnumerableExpression(cosmosObject); + case Constants.GroupBy: + return DeserializeGroupByEnumerableExpression(cosmosObject); + case Constants.Input: + return DeserializeInputEnumerableExpression(cosmosObject); + case Constants.OrderBy: + return DeserializeOrderByEnumerableExpression(cosmosObject); + case Constants.ScalarAsEnumerable: + return DeserializeScalarAsEnumerableExpression(cosmosObject); + case Constants.Select: + return DeserializeSelectEnumerableExpression(cosmosObject); + case Constants.SelectMany: + return DeserializeSelectManyEnumerableExpression(cosmosObject); + case Constants.Take: + return DeserializeTakeEnumerableExpression(cosmosObject); + case Constants.Where: + return DeserializeWhereEnumerableExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {kindProperty.Value}"); + } + } + + private static CqlAggregateEnumerableExpression DeserializeAggregateEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlAggregate aggregate = DeserializeAggregate(GetValue(cosmosObject, Constants.Aggregate)); + return new CqlAggregateEnumerableExpression(sourceExpression, aggregate); + } + + private static CqlDistinctEnumerableExpression DeserializeDistinctEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + IReadOnlyList expressions = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Expression)); + return new CqlDistinctEnumerableExpression(sourceExpression, declaredVariable, expressions); + } + + private static CqlGroupByEnumerableExpression DeserializeGroupByEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + long keyCount = Number64.ToLong(GetValue(cosmosObject, Constants.KeyCount).Value); + IReadOnlyList aggregates = DeserializeAggregateArray(GetValue(cosmosObject, Constants.Aggregates)); + return new CqlGroupByEnumerableExpression(sourceExpression, Convert.ToUInt64(keyCount), aggregates); + } + + private static CqlInputEnumerableExpression DeserializeInputEnumerableExpression(CosmosObject cosmosObject) + { + return new CqlInputEnumerableExpression(GetValue(cosmosObject, Constants.Name).Value); + } + + private static CqlOrderByEnumerableExpression DeserializeOrderByEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + IReadOnlyList orderByItems = DeserializeOrderByItemArray(GetValue(cosmosObject, Constants.Items)); + return new CqlOrderByEnumerableExpression(sourceExpression, declaredVariable, orderByItems); + } + + private static CqlScalarAsEnumerableExpression DeserializeScalarAsEnumerableExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + CqlEnumerationKind enumerationKind = GetEnumValue(GetValue(cosmosObject, Constants.EnumerationKind).Value); + return new CqlScalarAsEnumerableExpression(expression, enumerationKind); + } + + private static CqlSelectEnumerableExpression DeserializeSelectEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlSelectEnumerableExpression(sourceExpression, declaredVariable, expression); + } + + private static CqlSelectManyEnumerableExpression DeserializeSelectManyEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlEnumerableExpression selectorExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SelectorExpression)); + return new CqlSelectManyEnumerableExpression(sourceExpression, declaredVariable, selectorExpression); + } + + private static CqlTakeEnumerableExpression DeserializeTakeEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + long skipValue = Number64.ToLong(GetValue(cosmosObject, Constants.SkipValue).Value); + long takeExpression = Number64.ToLong(GetValue(cosmosObject, Constants.TakeValue).Value); + return new CqlTakeEnumerableExpression(sourceExpression, Convert.ToUInt64(skipValue), Convert.ToUInt64(takeExpression)); + } + + private static CqlWhereEnumerableExpression DeserializeWhereEnumerableExpression(CosmosObject cosmosObject) + { + CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlWhereEnumerableExpression(sourceExpression, declaredVariable, expression); + } + + #endregion + + #region Scalar Expressions + + private static CqlScalarExpression DeserializeScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpressionKind scalarExpressionKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (scalarExpressionKind) + { + case CqlScalarExpressionKind.ArrayCreate: + return DeserializeArrayCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.ArrayIndexer: + return DeserializeArrayIndexerScalarExpression(cosmosObject); + case CqlScalarExpressionKind.BinaryOperator: + return DeserializeBinaryOperatorScalarExpression(cosmosObject); + case CqlScalarExpressionKind.IsOperator: + return DeserializeIsOperatorScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Let: + return DeserializeLetScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Literal: + return DeserializeLiteralScalarExpression(cosmosObject); + case CqlScalarExpressionKind.Mux: + return DeserializeMuxScalarExpression(cosmosObject); + case CqlScalarExpressionKind.ObjectCreate: + return DeserializeObjectCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.PropertyRef: + return DeserializePropertyRefScalarExpression(cosmosObject); + case CqlScalarExpressionKind.SystemFunctionCall: + return DeserializeSystemFunctionCallScalarExpression(cosmosObject); + case CqlScalarExpressionKind.TupleCreate: + return DeserializeTupleCreateScalarExpression(cosmosObject); + case CqlScalarExpressionKind.TupleItemRef: + return DeserializeTupleItemRefScalarExpression(cosmosObject); + case CqlScalarExpressionKind.UnaryOperator: + return DeserializeUnaryScalarExpression(cosmosObject); + case CqlScalarExpressionKind.UserDefinedFunctionCall: + return DeserializeUserDefinedFunctionCallScalarExpression(cosmosObject); + case CqlScalarExpressionKind.VariableRef: + return DeserializeVariableRefScalarExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {scalarExpressionKind}"); + } + } + + private static CqlArrayCreateScalarExpression DeserializeArrayCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList items = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Items)); + return new CqlArrayCreateScalarExpression(items); + } + + private static CqlArrayIndexerScalarExpression DeserializeArrayIndexerScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + long index = Number64.ToLong(GetValue(cosmosObject, Constants.Index).Value); + return new CqlArrayIndexerScalarExpression(expression, Convert.ToUInt64(index)); + } + + private static CqlBinaryScalarExpression DeserializeBinaryOperatorScalarExpression(CosmosObject cosmosObject) + { + CqlBinaryScalarOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression leftExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.LeftExpression)); + CqlScalarExpression rightExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.RightExpression)); + return new CqlBinaryScalarExpression(operatorKind, leftExpression, rightExpression); + } + + private static CqlIsOperatorScalarExpression DeserializeIsOperatorScalarExpression(CosmosObject cosmosObject) + { + CqlIsOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlIsOperatorScalarExpression(operatorKind, expression); + } + + private static CqlLetScalarExpression DeserializeLetScalarExpression(CosmosObject cosmosObject) + { + CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); + CqlScalarExpression declaredVariableExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.DeclaredVariableExpression)); + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlLetScalarExpression(declaredVariable, declaredVariableExpression, expression); + } + + private static CqlLiteralScalarExpression DeserializeLiteralScalarExpression(CosmosObject cosmosObject) + { + CosmosObject literalObject = GetValue(cosmosObject, Constants.Literal); + return new CqlLiteralScalarExpression(DeserializeLiteral(literalObject)); + } + + private static CqlMuxScalarExpression DeserializeMuxScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression conditionExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.ConditionExpression)); + CqlScalarExpression leftExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.LeftExpression)); + CqlScalarExpression rightExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.RightExpression)); + return new CqlMuxScalarExpression(conditionExpression, leftExpression, rightExpression); + } + + private static CqlObjectCreateScalarExpression DeserializeObjectCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList properties = DeserializeObjectProperties(GetValue(cosmosObject, Constants.Properties)); + return new CqlObjectCreateScalarExpression(properties); + } + + private static CqlPropertyRefScalarExpression DeserializePropertyRefScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + string propertyName = GetValue(cosmosObject, Constants.PropertyName).Value; + return new CqlPropertyRefScalarExpression(expression, propertyName); + } + + private static CqlSystemFunctionCallScalarExpression DeserializeSystemFunctionCallScalarExpression(CosmosObject cosmosObject) + { + CqlBuiltinScalarFunctionKind functionKind = GetEnumValue(GetValue(cosmosObject, Constants.FunctionKind).Value); + IReadOnlyList arguments = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Arguments)); + return new CqlSystemFunctionCallScalarExpression(functionKind, arguments); + } + + private static CqlTupleCreateScalarExpression DeserializeTupleCreateScalarExpression(CosmosObject cosmosObject) + { + IReadOnlyList items = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Items)); + return new CqlTupleCreateScalarExpression(items); + } + + private static CqlTupleItemRefScalarExpression DeserializeTupleItemRefScalarExpression(CosmosObject cosmosObject) + { + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + long index = Number64.ToLong(GetValue(cosmosObject, Constants.Index).Value); + return new CqlTupleItemRefScalarExpression(expression, Convert.ToUInt64(index)); + } + + private static CqlUnaryScalarExpression DeserializeUnaryScalarExpression(CosmosObject cosmosObject) + { + CqlUnaryScalarOperatorKind operatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + CqlScalarExpression scalarExpression = DeserializeScalarExpression(GetValue(cosmosObject, Constants.Expression)); + return new CqlUnaryScalarExpression(operatorKind, scalarExpression); + } + + private static CqlUserDefinedFunctionCallScalarExpression DeserializeUserDefinedFunctionCallScalarExpression(CosmosObject cosmosObject) + { + string identifierString = GetValue(cosmosObject, Constants.Identifier).Value; + CqlFunctionIdentifier functionIdentifier = new CqlFunctionIdentifier(identifierString); + IReadOnlyList arguments = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Arguments)); + bool builtin = GetValue(cosmosObject, Constants.Builtin).Value; + return new CqlUserDefinedFunctionCallScalarExpression(functionIdentifier, arguments, builtin); + } + + private static CqlVariableRefScalarExpression DeserializeVariableRefScalarExpression(CosmosObject cosmosObject) + { + CqlVariable variable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.Variable)); + return new CqlVariableRefScalarExpression(variable); + } + + #endregion + + #region Aggregate + + private static IReadOnlyList DeserializeAggregateArray(CosmosArray cosmosArray) + { + List aggregates = new List(cosmosArray.Count); + foreach (CosmosElement aggregateElement in cosmosArray) + { + CosmosObject aggregateObject = CastToCosmosObject(aggregateElement); + aggregates.Add(DeserializeAggregate(aggregateObject)); + } + + return aggregates; + } + + private static CqlAggregate DeserializeAggregate(CosmosObject cosmosObject) + { + CqlAggregateKind aggregateKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (aggregateKind) + { + case CqlAggregateKind.Builtin: + return DeserializeBuiltInAggregateExpression(cosmosObject); + case CqlAggregateKind.Tuple: + return DeserializeTupleAggregateExpression(cosmosObject); + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {aggregateKind}"); + } + } + + private static CqlBuiltinAggregate DeserializeBuiltInAggregateExpression(CosmosObject cosmosObject) + { + CqlAggregateOperatorKind aggregateOperatorKind = GetEnumValue(GetValue(cosmosObject, Constants.OperatorKind).Value); + return new CqlBuiltinAggregate(aggregateOperatorKind); + } + + private static CqlTupleAggregate DeserializeTupleAggregateExpression(CosmosObject cosmosObject) + { + CosmosArray tupleArray = GetValue(cosmosObject, Constants.Items); + List aggregates = new List(tupleArray.Count); + + foreach (CosmosElement tupleElement in tupleArray) + { + CosmosObject tupleObject = CastToCosmosObject(tupleElement); + CqlAggregate aggregate = DeserializeAggregate(tupleObject); + aggregates.Add(aggregate); + } + + return new CqlTupleAggregate(aggregates); + } + + #endregion + + #region Literal + + private static CqlLiteral DeserializeLiteral(CosmosObject cosmosObject) + { + CqlLiteralKind literalKind = GetEnumValue(GetValue(cosmosObject, Constants.Kind).Value); + switch (literalKind) + { + case CqlLiteralKind.Array: + return new CqlArrayLiteral(DeserializeLiteralArray(GetValue(cosmosObject, Constants.Items))); + case CqlLiteralKind.Boolean: + return new CqlBooleanLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Null: + return CqlNullLiteral.Singleton; + case CqlLiteralKind.Number: + return new CqlNumberLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Object: + return new CqlObjectLiteral(DeserializeObjectLiteralArray(GetValue(cosmosObject, Constants.Properties))); + case CqlLiteralKind.String: + return new CqlStringLiteral(GetValue(cosmosObject, Constants.Value).Value); + case CqlLiteralKind.Undefined: + return CqlUndefinedLiteral.Singleton; + default: + throw new NotSupportedException($"Invalid CqlExpression kind: {literalKind}"); + } + } + + private static IReadOnlyList DeserializeLiteralArray(CosmosArray cosmosArray) + { + List literals = new List(cosmosArray.Count); + foreach (CosmosElement literalElement in cosmosArray) + { + CosmosObject literalObject = CastToCosmosObject(literalElement); + literals.Add(DeserializeLiteral(literalObject)); + } + + return literals; + } + + private static IReadOnlyList DeserializeObjectLiteralArray(CosmosArray cosmosArray) + { + List objectLiterals = new List(cosmosArray.Count); + foreach (CosmosElement objectLiteralElement in cosmosArray) + { + CosmosObject propertyObject = CastToCosmosObject(objectLiteralElement); + string name = GetValue(propertyObject, Constants.Name).Value; + CqlLiteral literal = DeserializeLiteral(propertyObject); + CqlObjectLiteralProperty objectLiteralProperty = new CqlObjectLiteralProperty(name, literal); + objectLiterals.Add(objectLiteralProperty); + } + + return objectLiterals; + } + + #endregion + + #region Helper Functions + + private static CqlVariable DeserializeCqlVariable(CosmosObject cosmosObject) + { + string name = GetValue(cosmosObject, Constants.Name).Value; + long uniqueId = Number64.ToLong(GetValue(cosmosObject, Constants.UniqueId).Value); + + return new CqlVariable(name, uniqueId); + } + + private static IReadOnlyList DeserializeObjectProperties(CosmosArray cosmosArray) + { + List properties = new List(cosmosArray.Count); + foreach (CosmosElement propertyElement in cosmosArray) + { + CosmosObject propertyObject = CastToCosmosObject(propertyElement); + string objectPropertyName = GetValue(propertyObject, Constants.Name).Value; + CqlScalarExpression expression = DeserializeScalarExpression(GetValue(propertyObject, Constants.Expression)); + properties.Add(new CqlObjectProperty(objectPropertyName, expression)); + } + + return properties; + } + + private static IReadOnlyList DeserializeScalarExpressionArray(CosmosArray cosmosArray) + { + List expressions = new List(cosmosArray.Count); + foreach (CosmosElement itemElement in cosmosArray) + { + CosmosObject itemObject = CastToCosmosObject(itemElement); + CqlScalarExpression expression = DeserializeScalarExpression(itemObject); + expressions.Add(expression); + } + + return expressions; + } + + private static IReadOnlyList DeserializeOrderByItemArray(CosmosArray cosmosArray) + { + List expressions = new List(cosmosArray.Count); + foreach (CosmosElement itemElement in cosmosArray) + { + CosmosObject itemObject = CastToCosmosObject(itemElement); + CqlSortOrder sortOrder = GetEnumValue(GetValue(itemObject, Constants.SortOrder).Value); + CqlScalarExpression scalarExpression = DeserializeScalarExpression(itemObject); + expressions.Add(new CqlOrderByItem(scalarExpression, sortOrder)); + } + + return expressions; + } + + private static T GetValue(CosmosObject cosmosObject, string propertyName) + where T : CosmosElement + { + bool found = TryGetValue(cosmosObject, propertyName, out T value); + + if (!found) + { + throw new InvalidOperationException($"{GetExceptionMessage()} The required property {propertyName} was not found in {cosmosObject}"); + } + + return value; + } + + private static bool TryGetValue(CosmosObject cosmosObject, string propertyName, out T result) + where T : CosmosElement + { + bool found = cosmosObject.TryGetValue(propertyName, out CosmosElement value); + + if (found && value != null) + { + result = value as T; + if (result == null) + { + throw new InvalidOperationException($"{GetExceptionMessage()} Type mismatch for property {propertyName}. Expected {typeof(T)}, Actual {value?.GetType()}"); + } + + return found; + } + + result = default(T); + return found; + } + + private static TEnum GetEnumValue(string propertyName) + where TEnum : struct + { + bool success = Enum.TryParse(propertyName, ignoreCase: true, out TEnum result); + if (!success) + { + throw new InvalidOperationException($"{GetExceptionMessage()} The string representation of {propertyName} enumerated constant was not able to be converted to an equivalent enumerated object"); + } + + return result; + } + + private static string GetExceptionMessage() + { + Version sdkVersion = Assembly.GetAssembly(typeof(CosmosClient)).GetName().Version; + string clientSDKVersion = $"{sdkVersion.Major}.{sdkVersion.Minor}.{sdkVersion.Build}"; + + return $"Exception occurred while deserializing query plan. Version : '{clientSDKVersion}', Exception/Reason : "; + } + + private static CosmosObject CastToCosmosObject(CosmosElement cosmosElement) + { + CosmosObject propertyObject = cosmosElement as CosmosObject; + if (propertyObject != null) + { + return propertyObject; + } + else + { + throw new InvalidOperationException("Unable to cast CosmosElement to CosmosObject."); + } + } + + #endregion + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs new file mode 100644 index 0000000000..51da84c03e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/ClientDistributionPlan.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class ClientDistributionPlan + { + public ClientDistributionPlan(CqlEnumerableExpression cql) + { + this.Cql = cql ?? throw new ArgumentNullException(nameof(cql)); + } + + public CqlEnumerableExpression Cql { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs new file mode 100644 index 0000000000..3df9af326f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlAggregate + { + protected CqlAggregate(CqlAggregateKind kind) + { + this.Kind = kind; + } + + public CqlAggregateKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs new file mode 100644 index 0000000000..eb4a09a966 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlAggregateEnumerableExpression : CqlEnumerableExpression + { + public CqlAggregateEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlAggregate aggregate) + : base(CqlEnumerableExpressionKind.Aggregate) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.Aggregate = aggregate ?? throw new ArgumentNullException(nameof(aggregate)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlAggregate Aggregate { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs new file mode 100644 index 0000000000..c25ae41bb8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateKind.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlAggregateKind + { + Builtin, + Tuple, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs new file mode 100644 index 0000000000..57c1955b74 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateOperatorKind.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlAggregateOperatorKind + { + All, + Any, + Array, + Count, + First, + Last, + Max, + Min, + Sum, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs new file mode 100644 index 0000000000..84b829179c --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlArrayCreateScalarExpression : CqlScalarExpression + { + private const string Array = "Array"; + + public CqlArrayCreateScalarExpression(IReadOnlyList items) + : base(CqlScalarExpressionKind.ArrayCreate) + { + this.ArrayKind = Array; + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public string ArrayKind { get; } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs new file mode 100644 index 0000000000..65d280a02e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlArrayIndexerScalarExpression : CqlScalarExpression + { + public CqlArrayIndexerScalarExpression(CqlScalarExpression expression, ulong index) + : base(CqlScalarExpressionKind.ArrayIndexer) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.Index = index; + } + + public CqlScalarExpression Expression { get; } + + public ulong Index { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs new file mode 100644 index 0000000000..a50036123d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlArrayLiteral : CqlLiteral + { + public CqlArrayLiteral(IReadOnlyList items) + : base(CqlLiteralKind.Array) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs new file mode 100644 index 0000000000..9f3a382fd0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlBinaryScalarExpression : CqlScalarExpression + { + public CqlBinaryScalarExpression(CqlBinaryScalarOperatorKind operatorKind, CqlScalarExpression leftExpression, CqlScalarExpression rightExpression) + : base(CqlScalarExpressionKind.BinaryOperator) + { + this.OperatorKind = operatorKind; + this.LeftExpression = leftExpression ?? throw new ArgumentNullException(nameof(leftExpression)); + this.RightExpression = rightExpression ?? throw new ArgumentNullException(nameof(rightExpression)); + } + + public CqlBinaryScalarOperatorKind OperatorKind { get; } + + public CqlScalarExpression LeftExpression { get; } + + public CqlScalarExpression RightExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs new file mode 100644 index 0000000000..c41a740994 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarOperatorKind.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlBinaryScalarOperatorKind + { + Add, + And, + BitwiseAnd, + BitwiseOr, + BitwiseXor, + Divide, + Equal, + GreaterThan, + GreaterThanOrEqual, + LeftShift, + LessThan, + LessThanOrEqual, + Modulo, + Multiply, + NotEqual, + Or, + RightShift, + Subtract, + ZeroFillRightShift + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs new file mode 100644 index 0000000000..06f06b4e64 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlBooleanLiteral : CqlLiteral + { + public CqlBooleanLiteral(bool value) + : base(CqlLiteralKind.Boolean) + { + this.Value = value; + } + + public bool Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs new file mode 100644 index 0000000000..8dcebf5bb8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlBuiltinAggregate : CqlAggregate + { + public CqlBuiltinAggregate(CqlAggregateOperatorKind operatorKind) + : base(CqlAggregateKind.Builtin) + { + this.OperatorKind = operatorKind; + } + + public CqlAggregateOperatorKind OperatorKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs new file mode 100644 index 0000000000..ae59e55cf1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinScalarFunctionKind.cs @@ -0,0 +1,126 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlBuiltinScalarFunctionKind + { + Abs, + Acos, + All, + Any, + Array, + Array_Concat, + Array_Contains, + Array_Length, + Array_Slice, + Asin, + Atan, + Atn2, + Avg, + Ceiling, + Choose, + Concat, + Contains, + Cos, + Cot, + Count, + DateTimeAdd, + DateTimeBin, + DateTimeDiff, + DateTimeFromParts, + DateTimePart, + DateTimeToTicks, + DateTimeToTimestamp, + Degrees, + DocumentId, + EndsWith, + Exp, + First, + Floor, + GetCurrentDateTime, + GetCurrentDateTimeStatic, + GetCurrentTicks, + GetCurrentTicksStatic, + GetCurrentTimestamp, + GetCurrentTimestampStatic, + Iif, + Index_Of, + IntAdd, + IntBitAnd, + IntBitLeftShift, + IntBitNot, + IntBitOr, + IntBitRightShift, + IntBitXor, + IntDiv, + IntMod, + IntMul, + IntSub, + Is_Array, + Is_Bool, + Is_DateTime, + Is_Defined, + Is_Finite_Number, + Is_Integer, + Is_Null, + Is_Number, + Is_Object, + Is_Primitive, + Is_String, + Last, + LastIndexOf, + Left, + Length, + Like, + Log, + Log10, + Lower, + Ltrim, + Max, + Min, + NumberBin, + ObjectToArray, + Pi, + Power, + Radians, + Rand, + RegexMatch, + Replace, + Replicate, + Reverse, + Right, + Round, + Rtrim, + SetDifference, + SetIntersect, + SetUnion, + Sign, + Sin, + Sqrt, + Square, + ST_Area, + ST_Distance, + ST_Intersects, + ST_IsValid, + ST_IsValidDetailed, + ST_Within, + StartsWith, + StringEquals, + StringToArray, + StringToBoolean, + StringToNull, + StringToNumber, + StringToObject, + Substring, + Sum, + Tan, + TicksToDateTime, + TimestampToDateTime, + ToString, + Trim, + Trunc, + Upper + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs new file mode 100644 index 0000000000..8fa7515235 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlDistinctEnumerableExpression : CqlEnumerableExpression + { + public CqlDistinctEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, IReadOnlyList expression) + : base(CqlEnumerableExpressionKind.Distinct) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public IReadOnlyList Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs new file mode 100644 index 0000000000..7b30bdc629 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlEnumerableExpression + { + protected CqlEnumerableExpression(CqlEnumerableExpressionKind kind) + { + this.Kind = kind; + } + + public CqlEnumerableExpressionKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs new file mode 100644 index 0000000000..11b135895d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpressionKind.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlEnumerableExpressionKind + { + Aggregate, + Distinct, + GroupBy, + Input, + OrderBy, + ScalarAsEnumerable, + Select, + SelectMany, + Take, + Where, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs new file mode 100644 index 0000000000..60d96d2703 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerationKind.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlEnumerationKind + { + ArrayItems, + PropertyValues, + Children, + Descendants, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs new file mode 100644 index 0000000000..16a717bdfe --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlFunctionIdentifier.cs @@ -0,0 +1,18 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlFunctionIdentifier + { + public CqlFunctionIdentifier(string name) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + } + + public string Name { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs new file mode 100644 index 0000000000..b3efe8cb5d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlGroupByEnumerableExpression : CqlEnumerableExpression + { + public CqlGroupByEnumerableExpression(CqlEnumerableExpression sourceExpression, ulong keyCount, IReadOnlyList aggregates) + : base(CqlEnumerableExpressionKind.GroupBy) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.KeyCount = keyCount; + this.Aggregates = aggregates ?? throw new ArgumentNullException(nameof(aggregates)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public ulong KeyCount { get; } + + public IReadOnlyList Aggregates { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs new file mode 100644 index 0000000000..a9a1ba8d6f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlInputEnumerableExpression : CqlEnumerableExpression + { + public CqlInputEnumerableExpression(string name) + : base(CqlEnumerableExpressionKind.Input) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + } + + public string Name { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs new file mode 100644 index 0000000000..84a8e17601 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorKind.cs @@ -0,0 +1,11 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlIsOperatorKind + { + Defined, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs new file mode 100644 index 0000000000..c1aa03907d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlIsOperatorScalarExpression : CqlScalarExpression + { + public CqlIsOperatorScalarExpression(CqlIsOperatorKind operatorKind, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.IsOperator) + { + this.OperatorKind = operatorKind; + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlIsOperatorKind OperatorKind { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs new file mode 100644 index 0000000000..329e2f36cd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlLetScalarExpression : CqlScalarExpression + { + public CqlLetScalarExpression(CqlVariable declaredVariable, CqlScalarExpression declaredVariableExpression, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.Let) + { + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.DeclaredVariableExpression = declaredVariableExpression ?? throw new ArgumentNullException(nameof(declaredVariableExpression)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression DeclaredVariableExpression { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs new file mode 100644 index 0000000000..d5b17b06ac --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlLiteral + { + protected CqlLiteral(CqlLiteralKind kind) + { + this.Kind = kind; + } + + public CqlLiteralKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs new file mode 100644 index 0000000000..e03b18a28a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralKind.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlLiteralKind + { + Undefined, + Array, + Boolean, + Null, + Number, + Object, + String, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs new file mode 100644 index 0000000000..ebc82d9048 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlLiteralScalarExpression : CqlScalarExpression + { + public CqlLiteralScalarExpression(CqlLiteral literal) + : base(CqlScalarExpressionKind.Literal) + { + this.Literal = literal ?? throw new ArgumentNullException(nameof(literal)); + } + + public CqlLiteral Literal { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs new file mode 100644 index 0000000000..0ebb3cab53 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlMuxScalarExpression : CqlScalarExpression + { + public CqlMuxScalarExpression(CqlScalarExpression conditionExpression, CqlScalarExpression leftExpression, CqlScalarExpression rightExpression) + : base(CqlScalarExpressionKind.Mux) + { + this.ConditionExpression = conditionExpression ?? throw new ArgumentNullException(nameof(conditionExpression)); + this.LeftExpression = leftExpression ?? throw new ArgumentNullException(nameof(leftExpression)); + this.RightExpression = rightExpression ?? throw new ArgumentNullException(nameof(rightExpression)); + } + + public CqlScalarExpression ConditionExpression { get; } + + public CqlScalarExpression LeftExpression { get; } + + public CqlScalarExpression RightExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs new file mode 100644 index 0000000000..53696840b1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlNullLiteral : CqlLiteral + { + public static readonly CqlNullLiteral Singleton = new CqlNullLiteral(); + + private CqlNullLiteral() + : base(CqlLiteralKind.Null) + { + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs new file mode 100644 index 0000000000..28769462d7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System.Collections.Generic; + + internal class CqlNumberLiteral : CqlLiteral + { + public CqlNumberLiteral(Number64 value) + : base(CqlLiteralKind.Number) + { + this.Value = value; + } + + public Number64 Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs new file mode 100644 index 0000000000..1bcd44e106 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlObjectCreateScalarExpression : CqlScalarExpression + { + private const string Object = "Object"; + + public CqlObjectCreateScalarExpression(IReadOnlyList properties) + : base(CqlScalarExpressionKind.ObjectCreate) + { + this.Properties = properties ?? throw new ArgumentNullException(nameof(properties)); + this.ObjectKind = Object; + } + + public IReadOnlyList Properties { get; } + + public string ObjectKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs new file mode 100644 index 0000000000..e5ba8ff343 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlObjectLiteral : CqlLiteral + { + public CqlObjectLiteral(IReadOnlyList properties) + : base(CqlLiteralKind.Object) + { + this.Properties = properties ?? throw new ArgumentNullException(nameof(properties)); + } + + public IReadOnlyList Properties { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs new file mode 100644 index 0000000000..4a063d4449 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteralProperty.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlObjectLiteralProperty + { + public CqlObjectLiteralProperty(string name, CqlLiteral literal) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Literal = literal ?? throw new ArgumentNullException(nameof(literal)); + } + + public string Name { get; } + + public CqlLiteral Literal { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs new file mode 100644 index 0000000000..7b97de1620 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectProperty.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlObjectProperty + { + public CqlObjectProperty(string name, CqlScalarExpression expression) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public string Name { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs new file mode 100644 index 0000000000..b4b9603841 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlOrderByEnumerableExpression : CqlEnumerableExpression + { + public CqlOrderByEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, IReadOnlyList items) + : base(CqlEnumerableExpressionKind.OrderBy) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs new file mode 100644 index 0000000000..8fb4a73810 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByItem.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlOrderByItem + { + public CqlOrderByItem(CqlScalarExpression expression, CqlSortOrder sortOrder) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.SortOrder = sortOrder; + } + + public CqlScalarExpression Expression { get; } + + public CqlSortOrder SortOrder { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs new file mode 100644 index 0000000000..e93a31fe3e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlPropertyRefScalarExpression : CqlScalarExpression + { + public CqlPropertyRefScalarExpression(CqlScalarExpression expression, string propertyName) + : base(CqlScalarExpressionKind.PropertyRef) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); + } + + public CqlScalarExpression Expression { get; } + + public string PropertyName { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs new file mode 100644 index 0000000000..0d69d8b424 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlScalarAsEnumerableExpression : CqlEnumerableExpression + { + public CqlScalarAsEnumerableExpression(CqlScalarExpression expression, CqlEnumerationKind enumerationKind) + : base(CqlEnumerableExpressionKind.ScalarAsEnumerable) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.EnumerationKind = enumerationKind; + } + + public CqlScalarExpression Expression { get; } + + public CqlEnumerationKind EnumerationKind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs new file mode 100644 index 0000000000..659bdc5f58 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal abstract class CqlScalarExpression + { + protected CqlScalarExpression(CqlScalarExpressionKind kind) + { + this.Kind = kind; + } + + public CqlScalarExpressionKind Kind { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs new file mode 100644 index 0000000000..fede841576 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpressionKind.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlScalarExpressionKind + { + ArrayCreate, + ArrayIndexer, + BinaryOperator, + IsOperator, + Let, + Literal, + Mux, + ObjectCreate, + PropertyRef, + SystemFunctionCall, + TupleCreate, + TupleItemRef, + UnaryOperator, + UserDefinedFunctionCall, + VariableRef, + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs new file mode 100644 index 0000000000..0d052e980b --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlSelectEnumerableExpression : CqlEnumerableExpression + { + public CqlSelectEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlScalarExpression expression) + : base(CqlEnumerableExpressionKind.Select) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs new file mode 100644 index 0000000000..e34d4ba874 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlSelectManyEnumerableExpression : CqlEnumerableExpression + { + public CqlSelectManyEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlEnumerableExpression selectorExpression) + : base(CqlEnumerableExpressionKind.SelectMany) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.SelectorExpression = selectorExpression ?? throw new ArgumentNullException(nameof(selectorExpression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlEnumerableExpression SelectorExpression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs new file mode 100644 index 0000000000..efd5aaeb42 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSortOrder.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlSortOrder + { + Ascending, + Descending + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs new file mode 100644 index 0000000000..a20947b0dd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlStringLiteral : CqlLiteral + { + public CqlStringLiteral(string value) + : base(CqlLiteralKind.String) + { + this.Value = value ?? throw new ArgumentNullException(nameof(value)); + } + + public string Value { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs new file mode 100644 index 0000000000..d42ee09f15 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlSystemFunctionCallScalarExpression : CqlScalarExpression + { + public CqlSystemFunctionCallScalarExpression(CqlBuiltinScalarFunctionKind functionKind, IReadOnlyList arguments) + : base(CqlScalarExpressionKind.SystemFunctionCall) + { + this.FunctionKind = functionKind; + this.Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments)); + } + + public CqlBuiltinScalarFunctionKind FunctionKind { get; } + + public IReadOnlyList Arguments { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs new file mode 100644 index 0000000000..0391db64fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlTakeEnumerableExpression : CqlEnumerableExpression + { + public CqlTakeEnumerableExpression(CqlEnumerableExpression sourceExpression, ulong skipValue, ulong takeValue) + : base(CqlEnumerableExpressionKind.Take) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.SkipValue = skipValue; + this.TakeValue = takeValue; + } + + public CqlEnumerableExpression SourceExpression { get; } + + public ulong SkipValue { get; } + + public ulong TakeValue { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs new file mode 100644 index 0000000000..6f553c1ec8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlTupleAggregate : CqlAggregate + { + public CqlTupleAggregate(IReadOnlyList items) + : base(CqlAggregateKind.Tuple) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs new file mode 100644 index 0000000000..0c30e79d33 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlTupleCreateScalarExpression : CqlScalarExpression + { + public CqlTupleCreateScalarExpression(IReadOnlyList items) + : base(CqlScalarExpressionKind.TupleCreate) + { + this.Items = items ?? throw new ArgumentNullException(nameof(items)); + } + + public IReadOnlyList Items { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs new file mode 100644 index 0000000000..bc011cecf7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlTupleItemRefScalarExpression : CqlScalarExpression + { + public CqlTupleItemRefScalarExpression(CqlScalarExpression expression, ulong index) + : base(CqlScalarExpressionKind.TupleItemRef) + { + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + this.Index = index; + } + + public CqlScalarExpression Expression { get; } + + public ulong Index { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs new file mode 100644 index 0000000000..8131ea618d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlUnaryScalarExpression : CqlScalarExpression + { + public CqlUnaryScalarExpression(CqlUnaryScalarOperatorKind operatorKind, CqlScalarExpression expression) + : base(CqlScalarExpressionKind.UnaryOperator) + { + this.OperatorKind = operatorKind; + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlUnaryScalarOperatorKind OperatorKind { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs new file mode 100644 index 0000000000..30c0cedc54 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarOperatorKind.cs @@ -0,0 +1,14 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal enum CqlUnaryScalarOperatorKind + { + BitwiseNot, + Minus, + Not, + Plus + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs new file mode 100644 index 0000000000..ecc8d556b2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + internal class CqlUndefinedLiteral : CqlLiteral + { + public static readonly CqlUndefinedLiteral Singleton = new CqlUndefinedLiteral(); + + private CqlUndefinedLiteral() + : base(CqlLiteralKind.Undefined) + { + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs new file mode 100644 index 0000000000..fda301a6a1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + using System.Collections.Generic; + + internal class CqlUserDefinedFunctionCallScalarExpression : CqlScalarExpression + { + public CqlUserDefinedFunctionCallScalarExpression(CqlFunctionIdentifier identifier, IReadOnlyList arguments, bool builtin) + : base(CqlScalarExpressionKind.UserDefinedFunctionCall) + { + this.Identifier = identifier ?? throw new ArgumentNullException(nameof(identifier)); + this.Arguments = arguments ?? throw new ArgumentNullException(nameof(arguments)); + this.Builtin = builtin; + } + + public CqlFunctionIdentifier Identifier { get; } + + public IReadOnlyList Arguments { get; } + + public bool Builtin { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs new file mode 100644 index 0000000000..73cbac8324 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariable.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlVariable + { + public CqlVariable(string name, long uniqueId) + { + this.Name = name ?? throw new ArgumentNullException(nameof(name)); + this.UniqueId = uniqueId; + } + + public string Name { get; } + + public long UniqueId { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs new file mode 100644 index 0000000000..a909fb39a1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlVariableRefScalarExpression : CqlScalarExpression + { + public CqlVariableRefScalarExpression(CqlVariable variable) + : base(CqlScalarExpressionKind.VariableRef) + { + this.Variable = variable ?? throw new ArgumentNullException(nameof(variable)); + } + + public CqlVariable Variable { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs new file mode 100644 index 0000000000..3f6db64aa2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs @@ -0,0 +1,25 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql +{ + using System; + + internal class CqlWhereEnumerableExpression : CqlEnumerableExpression + { + public CqlWhereEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlVariable declaredVariable, CqlScalarExpression expression) + : base(CqlEnumerableExpressionKind.Where) + { + this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); + this.DeclaredVariable = declaredVariable ?? throw new ArgumentNullException(nameof(declaredVariable)); + this.Expression = expression ?? throw new ArgumentNullException(nameof(expression)); + } + + public CqlEnumerableExpression SourceExpression { get; } + + public CqlVariable DeclaredVariable { get; } + + public CqlScalarExpression Expression { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml new file mode 100644 index 0000000000..c59b58aef1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml @@ -0,0 +1,606 @@ + + + + Input Expression + {"clientDistributionPlan": {"Cql": {"Kind": "Input","Name": "root"}}} + + + { + "Cql": { + "Name": "root", + "Kind": 3 + } +} + + + + + Aggregate and ObjectCreate Expressions + {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a","Expression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6}}}]},"SourceExpression": {"Kind": "Aggregate","Aggregate": {"Kind": "Builtin","OperatorKind": "Sum"},"SourceExpression": {"Kind": "Input","Name": "root"}}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "Aggregate": { + "OperatorKind": 8, + "Kind": 0 + }, + "Kind": 0 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Properties": [ + { + "Name": "count_a", + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 6 + }, + "Kind": 14 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + + + Select, Aggregate and BinaryOperator Expressions + {"clientDistributionPlan": {"Cql": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 10 }, "Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [ {"Name": "F1","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "FieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "FieldSum", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 1 }},{ "Name": "FieldAvg", "Expression": {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "Equal", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }, "RightExpression": {"Kind": "Literal","Literal": { "Kind": "Number", "Value": 0} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Undefined" }},"RightExpression": { "Kind": "BinaryOperator", "OperatorKind": "Divide", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 0 }, "RightExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }}}}]}}, {"Name": "F2","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "OtherFieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "OtherFieldMax", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 3 }} ]} }] }, "SourceExpression": {"Kind": "GroupBy","KeyCount": 1,"Aggregates": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Tuple","Items": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Builtin","OperatorKind": "Sum" }] }, {"Kind": "Builtin","OperatorKind": "Max" }],"SourceExpression": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 16 }, "Expression": {"Kind": "TupleCreate","Items": [ {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 0 }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} }, {"Kind": "TupleCreate","Items": [ {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 2 }, "Index": 0} }, {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 1 }] }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16}},"Index": 3}, "Index": 0}}]}, "SourceExpression": {"Kind": "Input","Name": "root"}}}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 16 + }, + "Expression": { + "Items": [ + { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + }, + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + }, + { + "Items": [ + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + }, + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + } + ], + "Kind": 10 + }, + { + "ConditionExpression": { + "OperatorKind": 1, + "LeftExpression": { + "OperatorKind": 14, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "RightExpression": { + "OperatorKind": 2, + "Expression": { + "FunctionKind": 55, + "Arguments": [ + { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + } + ], + "Kind": 9 + }, + "Kind": 12 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Items": [], + "Kind": 1 + }, + "Kind": 5 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 16 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "Kind": 6 + } + ], + "Kind": 10 + }, + "Kind": 6 + }, + "KeyCount": 1, + "Aggregates": [ + { + "OperatorKind": 8, + "Kind": 0 + }, + { + "Items": [ + { + "OperatorKind": 8, + "Kind": 0 + }, + { + "OperatorKind": 8, + "Kind": 0 + } + ], + "Kind": 1 + }, + { + "OperatorKind": 6, + "Kind": 0 + } + ], + "Kind": 2 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 10 + }, + "Expression": { + "Properties": [ + { + "Name": "F1", + "Expression": { + "Properties": [ + { + "Name": "FieldA", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + } + }, + { + "Name": "FieldSum", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 1, + "Kind": 11 + } + }, + { + "Name": "FieldAvg", + "Expression": { + "ConditionExpression": { + "OperatorKind": 6, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "RightExpression": { + "Literal": { + "Value": 0, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + }, + "LeftExpression": { + "Literal": { + "Kind": 0 + }, + "Kind": 5 + }, + "RightExpression": { + "OperatorKind": 5, + "LeftExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 0, + "Kind": 11 + }, + "RightExpression": { + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 2, + "Kind": 11 + }, + "Index": 1, + "Kind": 11 + }, + "Kind": 2 + }, + "Kind": 6 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + } + }, + { + "Name": "F2", + "Expression": { + "Properties": [ + { + "Name": "OtherFieldA", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 0, + "Kind": 11 + } + }, + { + "Name": "OtherFieldMax", + "Expression": { + "Expression": { + "Variable": { + "Name": "v0", + "UniqueId": 10 + }, + "Kind": 14 + }, + "Index": 3, + "Kind": 11 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + + + Select, Sum and VariableRef Expressions + {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a_plus_five","Expression": {"Kind": "BinaryOperator","OperatorKind": "Add","LeftExpression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6 }}, "RightExpression": { "Kind": "Literal", "Literal": { "Kind": "Number", "Value": 5 }}}}]}, "SourceExpression": { "Kind": "Aggregate", "Aggregate": { "Kind": "Builtin", "OperatorKind": "Sum" }, "SourceExpression": { "Kind": "Input", "Name": "root" }}}}} + + + { + "Cql": { + "SourceExpression": { + "SourceExpression": { + "Name": "root", + "Kind": 3 + }, + "Aggregate": { + "OperatorKind": 8, + "Kind": 0 + }, + "Kind": 0 + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Properties": [ + { + "Name": "count_a_plus_five", + "Expression": { + "OperatorKind": 0, + "LeftExpression": { + "Variable": { + "Name": "v0", + "UniqueId": 6 + }, + "Kind": 14 + }, + "RightExpression": { + "Literal": { + "Value": 5, + "Kind": 4 + }, + "Kind": 5 + }, + "Kind": 2 + } + } + ], + "ObjectKind": "Object", + "Kind": 7 + }, + "Kind": 6 + } +} + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 88450d8984..6f1657f37c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -79,6 +79,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs new file mode 100644 index 0000000000..845f71d25e --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs @@ -0,0 +1,100 @@ +namespace Microsoft.Azure.Cosmos.Tests.Query +{ + using System.Collections.Generic; + using System.Xml; + using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan; + using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql; + using Microsoft.Azure.Cosmos.Test.BaselineTest; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + [TestClass] + public class ClientDistributionPlanBaselineTests : BaselineTests + { + [TestMethod] + [Owner("akotalwar")] + public void TestClientDistributionPlanDeserialization() + { + List testVariations = new List + { + CreateInput( + description: @"Input Expression", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}"), + + CreateInput( + description: @"Aggregate and ObjectCreate Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a\",\"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6}}}]},\"SourceExpression\": {\"Kind\": \"Aggregate\",\"Aggregate\": {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\"},\"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}"), + + CreateInput( + description: @"Select, Aggregate and BinaryOperator Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 10 }, \"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [ {\"Name\": \"F1\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"FieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"FieldSum\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 1 }},{ \"Name\": \"FieldAvg\", \"Expression\": {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Equal\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }, \"RightExpression\": {\"Kind\": \"Literal\",\"Literal\": { \"Kind\": \"Number\", \"Value\": 0} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Undefined\" }},\"RightExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Divide\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 0 }, \"RightExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }}}}]}}, {\"Name\": \"F2\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"OtherFieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"OtherFieldMax\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 3 }} ]} }] }, \"SourceExpression\": {\"Kind\": \"GroupBy\",\"KeyCount\": 1,\"Aggregates\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Tuple\",\"Items\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }] }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Max\" }],\"SourceExpression\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 16 }, \"Expression\": {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 0 }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} }, {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 2 }, \"Index\": 0} }, {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 1 }] }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16}},\"Index\": 3}, \"Index\": 0}}]}, \"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}}"), + + CreateInput( + description: @"Select, Sum and VariableRef Expressions", + clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a_plus_five\",\"Expression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"Add\",\"LeftExpression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6 }}, \"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": { \"Kind\": \"Number\", \"Value\": 5 }}}}]}, \"SourceExpression\": { \"Kind\": \"Aggregate\", \"Aggregate\": { \"Kind\": \"Builtin\", \"OperatorKind\": \"Sum\" }, \"SourceExpression\": { \"Kind\": \"Input\", \"Name\": \"root\" }}}}}"), + }; + + this.ExecuteTestSuite(testVariations); + } + + + private static ClientDistributionPlanTestInput CreateInput( + string description, + string clientPlanJson) + { + return new ClientDistributionPlanTestInput(description, clientPlanJson); + } + + public override ClientDistributionPlanTestOutput ExecuteTest(ClientDistributionPlanTestInput input) + { + JsonSerializerSettings settings = new JsonSerializerSettings + { + Formatting = Newtonsoft.Json.Formatting.Indented + }; + + ClientDistributionPlan distributionPlan = ClientDistributionPlanDeserializer.DeserializeClientDistributionPlan(input.ClientPlanJson); + string serializedDistributionPlan = JsonConvert.SerializeObject(distributionPlan, settings); + + return new ClientDistributionPlanTestOutput(serializedDistributionPlan); + } + + public sealed class ClientDistributionPlanTestOutput : BaselineTestOutput + { + public ClientDistributionPlanTestOutput(string serializedclientPlanJson) + { + this.SerializedclientPlanJson = serializedclientPlanJson; + } + + public string SerializedclientPlanJson { get; } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + JObject jObject = JObject.Parse(this.SerializedclientPlanJson); + string jsonString = jObject.ToString(); + xmlWriter.WriteStartElement("SerializedClientPlanJson"); + xmlWriter.WriteString(jsonString); + xmlWriter.WriteEndElement(); + } + } + + public sealed class ClientDistributionPlanTestInput : BaselineTestInput + { + internal string ClientPlanJson { get; set; } + + internal ClientDistributionPlanTestInput( + string description, + string clientPlanJson) + : base(description) + { + this.ClientPlanJson = clientPlanJson; + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteElementString("Description", this.Description); + xmlWriter.WriteElementString("ClientDistributionPlanJson", this.ClientPlanJson); + } + } + } +} From f312f6a4c36472ca489cd50c6cee5078a2207840 Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 28 Sep 2023 12:03:44 -0700 Subject: [PATCH 198/337] [Internal] Query: Adds check to detect unsupported queries for Optimistic Direct Execution code path (#4090) * Added query validity function on Ode code path * Fixed syntax * Updated to use string search instead of query parsing * Updated string search to now be regex * Changed location of caller for QueryValidityCheck() * Updated regex string * Added extra test coverage * Added const string to error messages * Added compile flag to Regex * Fixed comments * Added missing null reference coverage * Removed extra foreach loop in test * Removed useQueryPlan bool in test code --- .../CosmosQueryExecutionContextFactory.cs | 23 ++++-- ...misticDirectExecutionQueryBaselineTests.cs | 79 ++++++++++++++++--- 2 files changed, 87 insertions(+), 15 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 01ed10a627..adb19c303f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -7,9 +7,9 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext using System.Collections.Generic; using System.Diagnostics; using System.Linq; + using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; - using global::Azure; using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; @@ -33,10 +33,12 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext internal static class CosmosQueryExecutionContextFactory { private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; + private const string QueryInspectionPattern = @"\s+(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; private const string OptimisticDirectExecution = "OptimisticDirectExecution"; private const string Passthrough = "Passthrough"; private const string Specialized = "Specialized"; private const int PageSizeFactorForTop = 5; + private static readonly Regex QueryInspectionRegex = new Regex(QueryInspectionPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); public static IQueryPipelineStage Create( DocumentContainer documentContainer, @@ -147,14 +149,14 @@ private static async Task> TryCreateCoreContextAsy if (targetRange != null) { - return await TryCreateExecutionContextAsync( + return await TryCreateSinglePartitionExecutionContextAsync( documentContainer, partitionedQueryExecutionInfo: null, cosmosQueryContext, containerQueryProperties, inputParameters, targetRange, - trace, + createQueryPipelineTrace, cancellationToken); } @@ -297,7 +299,7 @@ private static async Task> TryCreateFromPartitione if (targetRange != null) { - tryCreatePipelineStage = await TryCreateExecutionContextAsync( + tryCreatePipelineStage = await TryCreateSinglePartitionExecutionContextAsync( documentContainer, partitionedQueryExecutionInfo, cosmosQueryContext, @@ -328,7 +330,7 @@ private static async Task> TryCreateFromPartitione return tryCreatePipelineStage; } - private static async Task> TryCreateExecutionContextAsync( + private static async Task> TryCreateSinglePartitionExecutionContextAsync( DocumentContainer documentContainer, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, CosmosQueryContext cosmosQueryContext, @@ -338,6 +340,17 @@ private static async Task> TryCreateExecutionConte ITrace trace, CancellationToken cancellationToken) { + // Retrieve the query plan in a subset of cases to ensure the query is valid before creating the Ode pipeline + if (partitionedQueryExecutionInfo == null && QueryInspectionRegex.IsMatch(inputParameters.SqlQuerySpec.QueryText)) + { + partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + trace, + cancellationToken); + } + // Test code added to confirm the correct pipeline is being utilized SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index cc4a2c7718..a09a31d0ca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -95,6 +95,7 @@ public void PositiveOptimisticDirectExecutionOutput() partitionKeyPath: @"/pk", partitionKeyValue: null), }; + this.ExecuteTestSuite(testVariations); } @@ -379,11 +380,11 @@ public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() { int numItems = 100; OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Single Partition Key and Value Field", + description: @"Single Partition Key and Value Field", query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, - partitionKeyPath: @"/pk", - partitionKeyValue: "a"); + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); int result = await this.GetPipelineAndDrainAsync( input, @@ -394,6 +395,64 @@ public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() Assert.AreEqual(numItems, result); } + // test checks that the Ode code path ensures that a query is valid before sending it to the backend + // these queries with previous ODE implementation would have succedded. However, with the new query validity check, they should all throw an exception + [TestMethod] + public async Task TestQueryValidityCheckWithODEAsync() + { + const string UnsupportedSelectStarInGroupBy = $"'SELECT *' is not allowed with GROUP BY"; + const string UnsupportedCompositeAggregate = $"Compositions of aggregates and other expressions are not allowed."; + const string UnsupportedNestedAggregateExpression = $"Cannot perform an aggregate function on an expression containing an aggregate or a subquery."; + const string UnsupportedSelectLisWithAggregateOrGroupByExpression = $"invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"; + + List<(string Query, string ExpectedMessage)> testVariations = new List<(string Query, string ExpectedMessage)> + { + ("SELECT COUNT (1) + 5 FROM c", UnsupportedCompositeAggregate), + ("SELECT MIN(c.price) + 10 FROM c", UnsupportedCompositeAggregate), + ("SELECT MAX(c.price) - 4 FROM c", UnsupportedCompositeAggregate), + ("SELECT SUM (c.price) + 20 FROM c",UnsupportedCompositeAggregate), + ("SELECT AVG(c.price) * 50 FROM c", UnsupportedCompositeAggregate), + ("SELECT * from c GROUP BY c.name", UnsupportedSelectStarInGroupBy), + ("SELECT SUM(c.sales) AS totalSales, AVG(SUM(c.salesAmount)) AS averageTotalSales\n\n\nFROM c", UnsupportedNestedAggregateExpression), + ("SELECT c.category, c.price, COUNT(c) FROM c GROUP BY c.category\r\n", UnsupportedSelectLisWithAggregateOrGroupByExpression) + }; + + List<(string, string)> testVariationsWithCaseSensitivity = new List<(string, string)>(); + foreach ((string Query, string ExpectedMessage) testCase in testVariations) + { + testVariationsWithCaseSensitivity.Add((testCase.Query, testCase.ExpectedMessage)); + testVariationsWithCaseSensitivity.Add((testCase.Query.ToLower(), testCase.ExpectedMessage)); + testVariationsWithCaseSensitivity.Add((testCase.Query.ToUpper(), testCase.ExpectedMessage)); + } + + foreach ((string Query, string ExpectedMessage) testCase in testVariationsWithCaseSensitivity) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Unsupported queries in CosmosDB that were previousely supported by Ode pipeline and returning wrong resutls", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + try + { + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 0, + requiresDist: true); + } + catch (Exception ex) + { + Assert.IsTrue(ex.InnerException.Message.Contains(testCase.ExpectedMessage)); + continue; + } + + Assert.Fail(); + } + } + // test to check if pipeline handles a 410 exception properly and returns all the documents. [TestMethod] public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync() @@ -570,7 +629,7 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn return documents.Count; } - internal static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) + internal static TryCatch TryGetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) { TryCatch tryGetQueryPlan = QueryPartitionProviderTestInstance.Object.TryGetPartitionedQueryExecutionInfo( querySpecJsonString: querySpecJsonString, @@ -583,7 +642,7 @@ internal static PartitionedQueryExecutionInfo GetPartitionedQueryExecutionInfo(s useSystemPrefix: false, geospatialType: Cosmos.GeospatialType.Geography); - return tryGetQueryPlan.Result; + return tryGetQueryPlan; } private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) @@ -731,7 +790,6 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(input.Query), Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = GetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, input.PartitionKeyDefinition); CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: new SqlQuerySpec(input.Query), initialUserContinuationToken: input.ContinuationToken, @@ -740,8 +798,8 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect maxItemCount: queryRequestOptions.MaxItemCount, maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, partitionKey: input.PartitionKeyValue, - properties: queryRequestOptions.Properties, - partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, + properties: new Dictionary() { { "x-ms-query-partitionkey-definition", input.PartitionKeyDefinition } }, + partitionedQueryExecutionInfo: null, executionEnvironment: null, returnResultsInDeterministicOrder: null, forcePassthrough: false, @@ -1043,7 +1101,8 @@ public override async Task> TryGetPartit using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); + TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; return TryCatch.FromResult(partitionedQueryExecutionInfo); } } From 101b9b1ad59d65f4687cf383afdb9b22b873b0dc Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 28 Sep 2023 15:35:21 -0700 Subject: [PATCH 199/337] [Internal] Query: Fixes minor issues with TestQueryValidityCheckWithODEAsync (#4105) * Fixed typos and made test more readable * Another typo --- ...OptimisticDirectExecutionQueryBaselineTests.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index a09a31d0ca..9076506e64 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -396,14 +396,14 @@ public async Task TestPipelineForContinuationTokenOnSinglePartitionAsync() } // test checks that the Ode code path ensures that a query is valid before sending it to the backend - // these queries with previous ODE implementation would have succedded. However, with the new query validity check, they should all throw an exception + // these queries with previous ODE implementation would have succeeded. However, with the new query validity check, they should all throw an exception [TestMethod] public async Task TestQueryValidityCheckWithODEAsync() { - const string UnsupportedSelectStarInGroupBy = $"'SELECT *' is not allowed with GROUP BY"; - const string UnsupportedCompositeAggregate = $"Compositions of aggregates and other expressions are not allowed."; - const string UnsupportedNestedAggregateExpression = $"Cannot perform an aggregate function on an expression containing an aggregate or a subquery."; - const string UnsupportedSelectLisWithAggregateOrGroupByExpression = $"invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"; + const string UnsupportedSelectStarInGroupBy = "'SELECT *' is not allowed with GROUP BY"; + const string UnsupportedCompositeAggregate = "Compositions of aggregates and other expressions are not allowed."; + const string UnsupportedNestedAggregateExpression = "Cannot perform an aggregate function on an expression containing an aggregate or a subquery."; + const string UnsupportedSelectLisWithAggregateOrGroupByExpression = "invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"; List<(string Query, string ExpectedMessage)> testVariations = new List<(string Query, string ExpectedMessage)> { @@ -428,7 +428,7 @@ public async Task TestQueryValidityCheckWithODEAsync() foreach ((string Query, string ExpectedMessage) testCase in testVariationsWithCaseSensitivity) { OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Unsupported queries in CosmosDB that were previousely supported by Ode pipeline and returning wrong resutls", + description: @"Unsupported queries in CosmosDB that were previously supported by Ode pipeline and returning wrong results", query: testCase.Query, expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", @@ -442,14 +442,13 @@ public async Task TestQueryValidityCheckWithODEAsync() isMultiPartition: false, expectedContinuationTokenCount: 0, requiresDist: true); + Assert.Fail("Invalid query being executed did not result in an exception"); } catch (Exception ex) { Assert.IsTrue(ex.InnerException.Message.Contains(testCase.ExpectedMessage)); continue; } - - Assert.Fail(); } } From 11fa17b6e91c243ce25bd57ce511bd3dfbfccad5 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Tue, 3 Oct 2023 15:37:11 -0700 Subject: [PATCH 200/337] Query: Adds LINQ RegexMatch Extension method (#4078) * Add support for translation to REgexmatch * Add test and fix some indexing issues * remove visit explicit, add some comment. Update public contract and added the baseline for the test * add the missing baseline * added test * address code review * update csproj --------- Co-authored-by: Minh Le --- .../BuiltinFunctionVisitor.cs | 7 + .../StringBuiltinFunctions.cs | 41 +++++ .../src/Linq/CosmosLinqExtensions.cs | 44 +++++ .../SqlFunctionCallScalarExpression.cs | 3 + ...onBaselineTests.TestRegexMatchFunction.xml | 170 ++++++++++++++++++ ...slationBaselineTests.TestStringCompare.xml | 120 +++++-------- .../Linq/LinqTranslationBaselineTests.cs | 32 ++++ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 3 + .../Contracts/DotNetSDKAPI.json | 14 ++ 9 files changed, 359 insertions(+), 75 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRegexMatchFunction.xml diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs index e3814ba1fd..d7e79b5c50 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/BuiltinFunctionVisitor.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; + using System.Collections.Generic; using System.Globalization; using System.Linq.Expressions; using Microsoft.Azure.Cosmos; @@ -49,6 +50,12 @@ public static SqlScalarExpression VisitBuiltinFunctionCall(MethodCallExpression if (methodCallExpression.Method.DeclaringType.GeUnderlyingSystemType() == typeof(CosmosLinqExtensions)) { + // CosmosLinq Extensions are either RegexMatch or Type check functions (IsString, IsBool, etc.) + if (methodCallExpression.Method.Name == nameof(CosmosLinqExtensions.RegexMatch)) + { + return StringBuiltinFunctions.Visit(methodCallExpression, context); + } + return TypeCheckFunctions.Visit(methodCallExpression, context); } } diff --git a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs index b04bd58c3c..7d833a03bd 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/BuiltinFunctions/StringBuiltinFunctions.cs @@ -327,6 +327,43 @@ protected override SqlScalarExpression VisitExplicit(MethodCallExpression method } } + private class RegexMatchVisitor : SqlBuiltinFunctionVisitor + { + public RegexMatchVisitor() + : base(SqlFunctionCallScalarExpression.Names.RegexMatch, + isStatic: true, + new List() + { + new Type[]{ typeof(object), typeof(string)}, // search string, regex pattern + new Type[]{ typeof(object), typeof(string), typeof(string)} // search string, regex pattern, search modifier + }) + { + } + + protected override SqlScalarExpression VisitImplicit(MethodCallExpression methodCallExpression, TranslationContext context) + { + int argumentCount = methodCallExpression.Arguments.Count; + if (argumentCount == 0 || argumentCount > 3 || (methodCallExpression.Arguments[1].NodeType != ExpressionType.Constant)) + { + return null; + } + + List arguments = new List + { + // Argument 0 and the Method object is the same, since Regex is an extension method + ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[0], context), + ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[1], context) + }; + + if (argumentCount > 2 && (methodCallExpression.Arguments[2].NodeType == ExpressionType.Constant)) + { + arguments.Add(ExpressionToSql.VisitNonSubqueryScalarExpression(methodCallExpression.Arguments[2], context)); + } + + return SqlFunctionCallScalarExpression.CreateBuiltin(SqlFunctionCallScalarExpression.Names.RegexMatch, arguments.ToArray()); + } + } + private class StringVisitToString : SqlBuiltinFunctionVisitor { public StringVisitToString() @@ -432,6 +469,10 @@ static StringBuiltinFunctions() "TrimStart", new StringVisitTrimStart() }, + { + nameof(CosmosLinqExtensions.RegexMatch), + new RegexMatchVisitor() + }, { "Replace", new SqlBuiltinFunctionVisitor(SqlFunctionCallScalarExpression.Names.Replace, diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs index 6663f52673..619c1c1ecf 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq; using System.Linq.Expressions; using System.Reflection; + using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Diagnostics; @@ -175,6 +176,49 @@ public static bool IsString(this object obj) throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); } + /// + /// Returns a Boolean value indicating if the specified expression matches the supplied regex pattern. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/regexmatch. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// A string expression with a regular expression defined to use when searching. + /// Returns true if the string matches the regex expressions; otherwise, false. + /// + /// + /// document.Name.RegexMatch()); + /// ]]> + /// + /// + public static bool RegexMatch(this object obj, string regularExpression) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + + /// + /// Returns a Boolean value indicating if the specified expression matches the supplied regex pattern. + /// For more information, see https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/regexmatch. + /// This method is to be used in LINQ expressions only and will be evaluated on server. + /// There's no implementation provided in the client library. + /// + /// + /// A string expression with a regular expression defined to use when searching. + /// An optional string expression with the selected modifiers to use with the regular expression. + /// Returns true if the string matches the regex expressions; otherwise, false. + /// + /// + /// document.Name.RegexMatch(, )); + /// ]]> + /// + /// + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier) + { + throw new NotImplementedException(ClientResources.TypeCheckExtensionFunctionsNotImplemented); + } + /// /// This method generate query definition from LINQ query. /// diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs index bcb38257c6..651ad5726d 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/SqlFunctionCallScalarExpression.cs @@ -112,6 +112,7 @@ sealed class SqlFunctionCallScalarExpression : SqlScalarExpression { Names.Power, Identifiers.Power }, { Names.Radians, Identifiers.Radians }, { Names.Rand, Identifiers.Rand }, + { Names.RegexMatch, Identifiers.RegexMatch }, { Names.Replace, Identifiers.Replace }, { Names.Replicate, Identifiers.Replicate }, { Names.Reverse, Identifiers.Reverse }, @@ -332,6 +333,7 @@ public static class Names public const string Power = "POWER"; public const string Radians = "RADIANS"; public const string Rand = "RAND"; + public const string RegexMatch = "RegexMatch"; public const string Replace = "REPLACE"; public const string Replicate = "REPLICATE"; public const string Reverse = "REVERSE"; @@ -474,6 +476,7 @@ public static class Identifiers public static readonly SqlIdentifier Power = SqlIdentifier.Create(Names.Power); public static readonly SqlIdentifier Radians = SqlIdentifier.Create(Names.Radians); public static readonly SqlIdentifier Rand = SqlIdentifier.Create(Names.Rand); + public static readonly SqlIdentifier RegexMatch = SqlIdentifier.Create(Names.RegexMatch); public static readonly SqlIdentifier Replace = SqlIdentifier.Create(Names.Replace); public static readonly SqlIdentifier Replicate = SqlIdentifier.Create(Names.Replicate); public static readonly SqlIdentifier Reverse = SqlIdentifier.Create(Names.Reverse); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRegexMatchFunction.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRegexMatchFunction.xml new file mode 100644 index 0000000000..03f808f8b5 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestRegexMatchFunction.xml @@ -0,0 +1,170 @@ + + + + + doc.StringField.RegexMatch("abcd"))]]> + + + + + + + + + doc.StringField.RegexMatch("abcd", "i"))]]> + + + + + + + + + doc.StringField.RegexMatch(doc.StringField2))]]> + + + + + + + + + doc.StringField.RegexMatch(doc.IntField.ToString()))]]> + + + + + + + + + doc.StringField.RegexMatch(doc.StringField2.ToUpper()))]]> + + + + + + + + + doc.StringField.RegexMatch(doc.StringField2.ToLower()))]]> + + + + + + + + + doc.StringField.RegexMatch(Concat(doc.StringField, "str")))]]> + + + + + + + + + doc.IntField.ToString().RegexMatch(doc.StringField))]]> + + + + + + + + + doc.IntField.ToString().RegexMatch(doc.StringField, doc.StringField2.ToString()))]]> + + + + + + + + + (doc.StringField.RegexMatch("abc") AndAlso doc.StringField2.RegexMatch("def")))]]> + + + + + + + + + (doc.StringField.RegexMatch("abc") OrElse doc.StringField2.RegexMatch("def")))]]> + + + + + + + + + doc.StringField.RegexMatch("abc")).Where(doc => doc.StringField2.RegexMatch("abc"))]]> + + + + + + + + + doc.StringField.RegexMatch("abc")).Where(doc => Not(doc.StringField2.RegexMatch("abc")))]]> + + + + + + + + + doc.StringField.RegexMatch("abcd", "this should error out on the back end"))]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml index 17538ff1d8..e737413eed 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationBaselineTests.TestStringCompare.xml @@ -5,11 +5,9 @@ (Compare(doc.StringField, doc.StringField2) == 0))]]> - - - + @@ -18,11 +16,9 @@ FROM root]]> (Compare(doc.StringField, doc.StringField2) > 0))]]> - - root["StringField2"]) -FROM root]]> - + root["StringField2"]) +FROM root]]> @@ -31,11 +27,9 @@ FROM root]]> (Compare(doc.StringField, doc.StringField2) >= 0))]]> - - = root["StringField2"]) -FROM root]]> - + = root["StringField2"]) +FROM root]]> @@ -44,11 +38,9 @@ FROM root]]> (Compare(doc.StringField, doc.StringField2) < 0))]]> - - - + @@ -57,11 +49,9 @@ FROM root]]> (Compare(doc.StringField, doc.StringField2) <= 0))]]> - - - + @@ -70,11 +60,9 @@ FROM root]]> (Compare(doc.StringField, "str") == 0))]]> - - - + @@ -83,11 +71,9 @@ FROM root]]> (Compare(doc.StringField, "str") > 0))]]> - - "str") -FROM root]]> - + "str") +FROM root]]> @@ -96,11 +82,9 @@ FROM root]]> (Compare(doc.StringField, "str") >= 0))]]> - - = "str") -FROM root]]> - + = "str") +FROM root]]> @@ -109,11 +93,9 @@ FROM root]]> (Compare(doc.StringField, "str") < 0))]]> - - - + @@ -122,11 +104,9 @@ FROM root]]> (Compare(doc.StringField, "str") <= 0))]]> - - - + @@ -135,11 +115,9 @@ FROM root]]> (0 == Compare(doc.StringField, doc.StringField2)))]]> - - - + @@ -148,11 +126,9 @@ FROM root]]> (0 < Compare(doc.StringField, doc.StringField2)))]]> - - root["StringField2"]) -FROM root]]> - + root["StringField2"]) +FROM root]]> @@ -161,11 +137,9 @@ FROM root]]> (0 <= Compare(doc.StringField, doc.StringField2)))]]> - - = root["StringField2"]) -FROM root]]> - + = root["StringField2"]) +FROM root]]> @@ -174,11 +148,9 @@ FROM root]]> (0 > Compare(doc.StringField, doc.StringField2)))]]> - - - + @@ -187,11 +159,9 @@ FROM root]]> (0 >= Compare(doc.StringField, doc.StringField2)))]]> - - - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs index d6e4ee4767..f13a92da82 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs @@ -291,6 +291,38 @@ public void TestTypeCheckFunctions() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void TestRegexMatchFunction() + { + // Similar to the type checking function, RegexMatch are not supported client side. + // Therefore this method is verified with baseline only. + List data = new List(); + IOrderedQueryable query = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Func> getQuery = useQuery => useQuery ? query : data.AsQueryable(); + + List inputs = new List + { + new LinqTestInput("RegexMatch with 1 argument", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd"))), + new LinqTestInput("RegexMatch with 2 argument", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd", "i"))), + new LinqTestInput("RegexMatch with 1st argument member expression", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2))), + new LinqTestInput("RegexMatch with ToString", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.IntField.ToString()))), + new LinqTestInput("RegexMatch with StringUpper", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToUpper()))), + new LinqTestInput("RegexMatch with StringLower", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(doc.StringField2.ToLower()))), + new LinqTestInput("RegexMatch with StringConcat", b => getQuery(b).Where(doc => doc.StringField.RegexMatch(string.Concat(doc.StringField, "str")))), + + new LinqTestInput("RegexMatch with string composition", b => getQuery(b).Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField))), + new LinqTestInput("RegexMatch with string composition 2", b => getQuery(b).Where(doc => doc.IntField.ToString().RegexMatch(doc.StringField, doc.StringField2.ToString()))), + + new LinqTestInput("RegexMatch with conditional", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc") && doc.StringField2.RegexMatch("def"))), + new LinqTestInput("RegexMatch with conditional 2", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc") || doc.StringField2.RegexMatch("def"))), + new LinqTestInput("RegexMatch with conditional 3", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => doc.StringField2.RegexMatch("abc"))), + new LinqTestInput("RegexMatch with conditional 4", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abc")).Where(doc => !doc.StringField2.RegexMatch("abc"))), + + new LinqTestInput("RegexMatch with 2nd argument invalid string options", b => getQuery(b).Where(doc => doc.StringField.RegexMatch("abcd", "this should error out on the back end"))), + }; + this.ExecuteTestSuite(inputs); + } + [TestMethod] public void TestMemberInitializer() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 8011b07351..30c29ec5db 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -202,6 +202,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 759762f21f..2ba2523435 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -5367,6 +5367,20 @@ ], "MethodInfo": "Boolean IsString(System.Object);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Boolean RegexMatch(System.Object, System.String, System.String)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean RegexMatch(System.Object, System.String, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean RegexMatch(System.Object, System.String)[System.Runtime.CompilerServices.ExtensionAttribute()]": { + "Type": "Method", + "Attributes": [ + "ExtensionAttribute" + ], + "MethodInfo": "Boolean RegexMatch(System.Object, System.String);IsAbstract:False;IsStatic:True;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.FeedIterator ToStreamIterator[T](System.Linq.IQueryable`1[T])[System.Runtime.CompilerServices.ExtensionAttribute()]": { "Type": "Method", "Attributes": [ From b03df6bb12c3214f5e4fed3c851009741662c903 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Wed, 4 Oct 2023 07:29:36 -0700 Subject: [PATCH 201/337] Chaning Bounded to Strong (#4103) --- docs/LocalQuorum.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/LocalQuorum.md b/docs/LocalQuorum.md index 5ca45e9055..a971955006 100644 --- a/docs/LocalQuorum.md +++ b/docs/LocalQuorum.md @@ -37,23 +37,23 @@ upgradeConsistencyProperty.SetValue(clientOptions, true); CosmosClient cosmosClient = new CosmosClient(..., clientOptions); ``` -#### Per request upgrade consistency to Bounded -> ###### Please note that Bounded here is only used as HINT for SDK to do quorum reads +#### Per request upgrade consistency to Strong +> ###### Please note that Strong here is only used as HINT for SDK to do quorum reads > ###### It will not impact CosmosDB account or write consistency levels ```C# ItemRequestOptions requestOption = new ItemRequestOptions(); -requestOption.ConsistencyLevel = ConsistencyLevel.Bounded; +requestOption.ConsistencyLevel = ConsistencyLevel.Strong; T item = await container.ReadItemAsync(docId, new PartitionKey(docPartitionKey), requestOption); ``` ```C# QueryRequestOptions requestOption = new QueryRequestOptions(); -requestOption.ConsistencyLevel = ConsistencyLevel.Bounded; +requestOption.ConsistencyLevel = ConsistencyLevel.Strong; await container.GetItemQueryIterator(queryText, continuationToken, requestOption); ``` -> #### Please use Bounded only for per request options as pattern +> #### Please use Strong only for per request options as pattern > #### Single master account possibly Strong == Bounded (**TBD**) \ No newline at end of file From 72e96faca5376afa1a2c9992bfb99cbeda5d11f9 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 5 Oct 2023 01:35:46 +0530 Subject: [PATCH 202/337] Client Telemetry: Adds new public APIs (#4056) * Revert "[Internal] Client Telemetry: Refactors code for collectors (#4037)" This reverts commit e2311a9fdcca392ec7d49c13939aaff3404deb85. * Revert "Revert "[Internal] Client Telemetry: Refactors code for collectors (#4037)"" This reverts commit f04234b76174180b482eadfa0f6f412c80d380c3. * firdst draft * initialize object * null handle * update contracts * compilation charges * fix tests * public API changes * add docs * contract updated * fixed tests * by default switch of te;emetry in sdk * fix tests * fix assertion * incorporate review comments * fetaure flag fix in script * switch case * add test * fix tests * fix test * fixed run.sh * minor changes * code refactor * changed default values and fix tests --- .../Tools/Benchmark/BenchmarkConfig.cs | 16 ++- .../Tools/Benchmark/run.sh | 18 ++- .../Tools/CTL/CTLConfig.cs | 14 +- .../src/ConnectionPolicy.cs | 22 +-- .../src/CosmosClientOptions.cs | 42 ++---- .../src/CosmosClientTelemetryOptions.cs | 58 ++++++++ .../src/CosmosThresholdOptions.cs | 31 ++++ Microsoft.Azure.Cosmos/src/DocumentClient.cs | 14 +- .../src/Fluent/CosmosClientBuilder.cs | 67 +++------ .../src/RequestOptions/RequestOptions.cs | 2 +- .../src/Resource/ClientContextCore.cs | 2 +- .../OpenTelemetry/CosmosDbEventSource.cs | 2 +- .../DistributedTracingOptions.cs | 30 ---- .../Filters/DiagnosticsFilterHelper.cs | 34 ++--- .../OpenTelemetryCoreRecorder.cs | 6 +- .../OpenTelemetryRecorderFactory.cs | 4 +- .../src/Telemetry/TelemetryToServiceHelper.cs | 4 +- ...riterBaselineTests.BulkOperationsAsync.xml | 9 +- ...neTests.PointOperationsExceptionsAsync.xml | 9 +- .../ClientTelemetryConfigurationTest.cs | 15 +- .../ClientTelemetryTestsBase.cs | 10 +- .../DistributedTracingOTelTests.cs | 37 +++-- .../SynchronizationContextTests.cs | 5 +- .../EndToEndTraceWriterBaselineTests.cs | 65 ++++++--- .../Utils/TestCommon.cs | 14 +- .../Utils/TransportClientHelper.cs | 9 +- .../Mocks/MockDocumentClient.cs | 6 +- .../Contracts/DotNetPreviewSDKAPI.json | 133 ++++++++++++++++-- .../CosmosClientOptionsUnitTests.cs | 20 ++- .../CosmosClientTests.cs | 34 +---- .../DiagnosticHandlerHelperTests.cs | 16 +-- .../Telemetry/DiagnosticsFilterHelperTest.cs | 35 +++-- .../Utils/MockCosmosUtil.cs | 5 +- 33 files changed, 501 insertions(+), 287 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs create mode 100644 Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs delete mode 100644 Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index e3ec5c23bb..0fde6a8926 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -103,8 +103,8 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Disable core SDK logging")] public bool DisableCoreSdkLogging { get; set; } - [Option(Required = false, HelpText = "Enable Distributed Tracing")] - public bool EnableDistributedTracing { get; set; } + [Option(Required = false, HelpText = "Disable Distributed Tracing feature from source")] + public bool DisableDistributedTracing { get; set; } = false; [Option(Required = false, HelpText = "Client Telemetry Schedule in Seconds")] public int TelemetryScheduleInSec { get; set; } @@ -138,8 +138,8 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Application Insights connection string")] public string AppInsightsConnectionString { get; set; } - [Option(Required = false, HelpText = "Enable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] - public bool EnableClientTelemetry { get; set; } = true; + [Option(Required = false, HelpText = "Disable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] + public bool DisableClientTelemetry { get; set; } = false; internal int GetTaskCount(int containerThroughput) { @@ -220,7 +220,11 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe MaxRetryAttemptsOnRateLimitedRequests = 0, MaxRequestsPerTcpConnection = this.MaxRequestsPerTcpConnection, MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint, - EnableClientTelemetry = this.EnableClientTelemetry + CosmosClientTelemetryOptions = new Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = this.DisableClientTelemetry, + DisableDistributedTracing = this.DisableDistributedTracing + } }; if (!string.IsNullOrWhiteSpace(this.ConsistencyLevel)) @@ -228,8 +232,6 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe clientOptions.ConsistencyLevel = (Microsoft.Azure.Cosmos.ConsistencyLevel)Enum.Parse(typeof(Microsoft.Azure.Cosmos.ConsistencyLevel), this.ConsistencyLevel, ignoreCase: true); } - clientOptions.IsDistributedTracingEnabled = this.EnableDistributedTracing; - return new Microsoft.Azure.Cosmos.CosmosClient( this.EndPoint, accountKey, diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh index 71b647d72d..81cafc4a4a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh @@ -24,6 +24,12 @@ then exit -1 fi +if [ -z "$TELEMETRY_ENDPOINT" ] +then + echo "Missing TELEMETRY_ENDPOINT" + exit -1 +fi + if [ -z "$INCLUDE_QUERY" ] then echo "Missing INCLUDE_QUERY" @@ -41,26 +47,26 @@ echo $COMMIT_TIME echo $BRANCH_NAME # Client telemetry disabled ReadStreamExistsV3 -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --disableClientTelemetry --disableDistributedTracing --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait # Client telemetry enabled ReadStreamExistsV3. This is needed to see the impact of client telemetry. -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithTelemetry --telemetryScheduleInSec 60 --disableDistributedTracing --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithTelemetry --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait # Open telemetry enabled ReadStreamExistsV3. This is needed to see the impact of distributed tracing (without listener) -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithDistributedTracingWOListener --disableClientTelemetry --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithDistributedTracingWOListener --enableDistributedTracing --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait #Point read operations for WORKLOAD_NAME in ReadNotExistsV3 ReadTExistsV3 ReadStreamExistsWithDiagnosticsV3 do - dotnet run -c Release -- -n 2000000 -w $WORKLOAD_NAME --pl $PL --telemetryScheduleInSec 60 --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol + dotnet run -c Release -- -n 2000000 -w $WORKLOAD_NAME --pl $PL --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait done #Insert operation -dotnet run -c Release -- -n 2000000 -w InsertV3 --pl 30 --telemetryScheduleInSec 60 --tcp 1 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol +dotnet run -c Release -- -n 2000000 -w InsertV3 --pl 30 --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 1 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 45 #Wait if [ "$INCLUDE_QUERY" = true ] @@ -70,7 +76,7 @@ then # pl is 16 because 18 was casuing a small amount of thorrtles. for WORKLOAD_NAME in ReadFeedStreamV3 QueryTSinglePkV3 QueryTSinglePkOrderByWithPaginationV3 QueryTSinglePkOrderByFullDrainV3 QueryTCrossPkV3 QueryTCrossPkOrderByWithPaginationV3 QueryTCrossPkOrderByFullDrainV3 QueryStreamSinglePkV3 QueryStreamSinglePkOrderByWithPaginationV3 QueryStreamSinglePkOrderByFullDrainV3 QueryStreamCrossPkV3 QueryStreamCrossPkOrderByWithPaginationV3 QueryStreamCrossPkOrderByFullDrainV3 do - dotnet run -c Release -- -n 200000 -w $WORKLOAD_NAME --pl 16 --telemetryScheduleInSec 60 --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol + dotnet run -c Release -- -n 200000 -w $WORKLOAD_NAME --pl 16 --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk sleep 10 #Wait done fi \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs index 98bba7b700..8d58271a22 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs @@ -103,8 +103,8 @@ public string DiagnosticsThresholdDuration [Option("ctl_reservoir_sample_size", Required = false, HelpText = "The reservoir sample size.")] public int ReservoirSampleSize { get; set; } = 1028; - [Option("ctl_enable_client_telemetry", Required = false, HelpText = "Enable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] - public bool EnableClientTelemetry { get; set; } = true; + [Option("ctl_disable_client_telemetry", Required = false, HelpText = "Disable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] + public bool DisableClientTelemetry { get; set; } = false; internal TimeSpan RunningTimeDurationAsTimespan { get; private set; } = TimeSpan.FromHours(10); internal TimeSpan DiagnosticsThresholdDurationAsTimespan { get; private set; } = TimeSpan.FromSeconds(60); @@ -130,12 +130,19 @@ internal CosmosClient CreateCosmosClient() CosmosClientOptions clientOptions = new CosmosClientOptions() { ApplicationName = CTLConfig.UserAgentSuffix, - EnableClientTelemetry = this.EnableClientTelemetry + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = this.DisableClientTelemetry, + } }; + Console.WriteLine("ApplicationName = " + CTLConfig.UserAgentSuffix); + Console.WriteLine("DisableSendingMetricsToService = " + this.DisableClientTelemetry); + if (this.UseGatewayMode) { clientOptions.ConnectionMode = ConnectionMode.Gateway; + Console.WriteLine("ConnectionMode = " + ConnectionMode.Gateway); } if (!string.IsNullOrWhiteSpace(this.ConsistencyLevel)) @@ -143,6 +150,7 @@ internal CosmosClient CreateCosmosClient() if (Enum.TryParse(this.ConsistencyLevel, out ConsistencyLevel consistencyLevel)) { clientOptions.ConsistencyLevel = consistencyLevel; + Console.WriteLine("ConsistencyLevel = " + consistencyLevel); } else { diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index 8451918e9b..bd1b23b16c 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos using System.Net.Http; using System.Net.Security; using System.Security.Cryptography.X509Certificates; - using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; @@ -48,8 +47,9 @@ public ConnectionPolicy() this.MaxConnectionLimit = defaultMaxConcurrentConnectionLimit; this.RetryOptions = new RetryOptions(); this.EnableReadRequestsFallback = null; - this.EnableClientTelemetry = false; // by default feature flag is off this.ServerCertificateCustomValidationCallback = null; + + this.CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions(); } /// @@ -211,15 +211,6 @@ public bool EnableTcpConnectionEndpointRediscovery set; } - /// - /// Gets or sets the flag to enable client telemetry feature. - /// - internal bool EnableClientTelemetry - { - get; - set; - } - /// /// Gets the default connection policy used to connect to the Azure Cosmos DB service. /// @@ -489,6 +480,15 @@ internal int? MaxTcpPartitionCount set; } + /// + /// Gets or sets Client Telemetry Options like feature flags and corresponding options + /// + internal CosmosClientTelemetryOptions CosmosClientTelemetryOptions + { + get; + set; + } + /// /// GlobalEndpointManager will subscribe to this event if user updates the preferredLocations list in the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 2c07f060f8..b3b21e4f3b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos using System.Linq; using System.Net; using System.Net.Http; - using System.Net.Http.Headers; using System.Net.Security; using System.Security.Cryptography.X509Certificates; using Microsoft.Azure.Cosmos.Fluent; @@ -85,6 +84,7 @@ public CosmosClientOptions() this.ConnectionProtocol = CosmosClientOptions.DefaultProtocol; this.ApiType = CosmosClientOptions.DefaultApiType; this.CustomHandlers = new Collection(); + this.CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions(); } /// @@ -730,9 +730,14 @@ internal Protocol ConnectionProtocol internal bool? EnableCpuMonitor { get; set; } /// - /// Flag to enable telemetry + /// Gets or sets Client Telemetry Options like feature flags and corresponding options /// - internal bool? EnableClientTelemetry { get; set; } +#if PREVIEW + public +#else + internal +#endif + CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } internal void SetSerializerIfNotConfigured(CosmosSerializer serializer) { @@ -771,12 +776,13 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) EnableTcpConnectionEndpointRediscovery = this.EnableTcpConnectionEndpointRediscovery, EnableAdvancedReplicaSelectionForTcp = this.EnableAdvancedReplicaSelectionForTcp, HttpClientFactory = this.httpClientFactory, - ServerCertificateCustomValidationCallback = this.ServerCertificateCustomValidationCallback + ServerCertificateCustomValidationCallback = this.ServerCertificateCustomValidationCallback, + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions() }; - if (this.EnableClientTelemetry.HasValue) + if (this.CosmosClientTelemetryOptions != null) { - connectionPolicy.EnableClientTelemetry = this.EnableClientTelemetry.Value; + connectionPolicy.CosmosClientTelemetryOptions = this.CosmosClientTelemetryOptions; } if (this.ApplicationRegion != null) @@ -1013,29 +1019,5 @@ public override bool CanConvert(Type objectType) return objectType == typeof(DateTime); } } - - /// - /// Distributed Tracing Options. - /// - /// Applicable only when Operation level distributed tracing is enabled through - internal DistributedTracingOptions DistributedTracingOptions { get; set; } - - /// - /// Gets or sets the flag to generate operation level for methods calls using the Source Name "Azure.Cosmos.Operation". - /// - /// - /// The default value is true (for preview package). - /// - /// This flag is there to disable it from source. Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters -#if PREVIEW - public -#else - internal -#endif - bool IsDistributedTracingEnabled { get; set; } -#if PREVIEW - = true; -#endif - } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs new file mode 100644 index 0000000000..8b2a2aa6a0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + /// + /// Telemetry Options for Cosmos Client to enable/disable telemetry and distributed tracing along with corresponding threshold values. + /// +#if PREVIEW + public +#else + internal +#endif + class CosmosClientTelemetryOptions + { + /// + /// Disable sending telemetry to service, is not applicable to this as of now. + /// + /// This option will disable sending telemetry to service.even it is opt-in from portal. + /// true +#if PREVIEW + public +#else + internal +#endif + bool DisableSendingMetricsToService { get; set; } = true; + + /// + /// This method enable/disable generation of operation level if listener is subscribed to the Source Name "Azure.Cosmos.Operation". + /// + /// false + /// Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters +#if PREVIEW + public +#else + internal +#endif + bool DisableDistributedTracing { get; set; } = +#if PREVIEW + false; +#else + true; +#endif + + /// + /// Threshold values for Distributed Tracing. + /// These values decides whether to generate operation level with request diagnostics or not. + /// +#if PREVIEW + public +#else + internal +#endif + CosmosThresholdOptions CosmosThresholdOptions { get; set; } = new CosmosThresholdOptions(); + + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs new file mode 100644 index 0000000000..5a04286f68 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs @@ -0,0 +1,31 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + + /// + /// Threshold values for Distributed Tracing + /// +#if PREVIEW + public +#else + internal +#endif + class CosmosThresholdOptions + { + /// + /// Latency Threshold for non point operations i.e. Query + /// + /// 500 ms + public TimeSpan NonPointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(3); + + /// + /// Latency Threshold for point operations i.e operation other than Query + /// + /// 100 ms + public TimeSpan PointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(1); + } +} diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 9dee309028..3c261490a7 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -171,7 +171,7 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider internal RemoteCertificateValidationCallback remoteCertificateValidationCallback; //Distributed Tracing Flag - internal bool isDistributedTracingEnabled; + internal CosmosClientTelemetryOptions cosmosClientTelemetryOptions; //SessionContainer. internal ISessionContainer sessionContainer; @@ -432,7 +432,7 @@ internal DocumentClient(Uri serviceEndpoint, /// Flag to allow Quorum Read with Eventual Consistency Account /// /// This delegate responsible for validating the third party certificate. - /// This is distributed tracing flag + /// This is distributed tracing flag /// /// The service endpoint can be obtained from the Azure Management Portal. /// If you are connecting using one of the Master Keys, these can be obtained along with the endpoint from the Azure Management Portal @@ -460,7 +460,7 @@ internal DocumentClient(Uri serviceEndpoint, bool isLocalQuorumConsistency = false, string cosmosClientId = null, RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, - bool isDistributedTracingEnabled = false) + CosmosClientTelemetryOptions cosmosClientTelemetryOptions = null) { if (sendingRequestEventArgs != null) { @@ -494,7 +494,7 @@ internal DocumentClient(Uri serviceEndpoint, storeClientFactory: storeClientFactory, cosmosClientId: cosmosClientId, remoteCertificateValidationCallback: remoteCertificateValidationCallback, - isDistributedTracingEnabled: isDistributedTracingEnabled); + cosmosClientTelemetryOptions: cosmosClientTelemetryOptions); } /// @@ -678,7 +678,7 @@ internal virtual void Initialize(Uri serviceEndpoint, TokenCredential tokenCredential = null, string cosmosClientId = null, RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, - bool isDistributedTracingEnabled = false) + CosmosClientTelemetryOptions cosmosClientTelemetryOptions = null) { if (serviceEndpoint == null) { @@ -687,7 +687,7 @@ internal virtual void Initialize(Uri serviceEndpoint, this.clientId = cosmosClientId; this.remoteCertificateValidationCallback = remoteCertificateValidationCallback; - this.isDistributedTracingEnabled = isDistributedTracingEnabled; + this.cosmosClientTelemetryOptions = cosmosClientTelemetryOptions ?? new CosmosClientTelemetryOptions(); this.queryPartitionProvider = new AsyncLazy(async () => { @@ -6623,7 +6623,7 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory { Documents.Telemetry.DistributedTracingOptions distributedTracingOptions = new () { - IsDistributedTracingEnabled = this.isDistributedTracingEnabled + IsDistributedTracingEnabled = !this.cosmosClientTelemetryOptions.DisableDistributedTracing }; StoreClientFactory newClientFactory = new StoreClientFactory( diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index bf04d103bb..8ba2ffa266 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -435,36 +435,6 @@ public CosmosClientBuilder WithConsistencyLevel(Cosmos.ConsistencyLevel consiste } - /// - /// Sets whether Distributed Tracing for "Azure.Cosmos.Operation" source is enabled. - /// - /// Whether is enabled. - /// The current . -#if PREVIEW - public -#else - internal -#endif - CosmosClientBuilder WithDistributedTracing(bool isEnabled = true) - { - this.clientOptions.IsDistributedTracingEnabled = isEnabled; - return this; - } - - /// - /// Enables Distributed Tracing with a Configuration ref. - /// - /// . - /// The current .] - /// Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters - internal CosmosClientBuilder WithDistributedTracingOptions(DistributedTracingOptions options) - { - this.clientOptions.IsDistributedTracingEnabled = true; - this.clientOptions.DistributedTracingOptions = options; - - return this; - } - /// /// Sets the connection mode to Gateway. This is used by the client when connecting to the Azure Cosmos DB service. /// @@ -679,27 +649,6 @@ internal CosmosClientBuilder WithCpuMonitorDisabled() return this; } - /// - /// Disable Telemetry if enabled using environment properties - /// - /// The object - internal CosmosClientBuilder WithTelemetryDisabled() - { - this.clientOptions.EnableClientTelemetry = false; - return this; - } - - /// - /// To enable Telemetry, set COSMOS.CLIENT_TELEMETRY_ENABLED environment property. - /// This function is used by Test only. - /// - /// The object - internal CosmosClientBuilder WithTelemetryEnabled() - { - this.clientOptions.EnableClientTelemetry = true; - return this; - } - /// /// Enabled partition level failover in the SDK /// @@ -731,5 +680,21 @@ internal CosmosClientBuilder WithRetryWithOptions( this.clientOptions.TotalWaitTimeForRetryWithMilliseconds = totalWaitTimeForRetryWithMilliseconds; return this; } + + /// + /// To enable Telemetry features with corresponding options + /// + /// + /// The object +#if PREVIEW + public +#else + internal +#endif + CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options) + { + this.clientOptions.CosmosClientTelemetryOptions = options; + return this; + } } } diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index dc02f9a248..56c152568a 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -66,7 +66,7 @@ public class RequestOptions /// /// Set Request Level Distributed Tracing Options. /// - internal DistributedTracingOptions DistributedTracingOptions { get; set; } + internal CosmosThresholdOptions CosmosThresholdOptions { get; set; } /// /// Gets or sets the boolean to use effective partition key routing in the cosmos db request. diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index a128e178d0..5d5b66ee71 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -82,7 +82,7 @@ internal static CosmosClientContext Create( sessionContainer: clientOptions.SessionContainer, cosmosClientId: cosmosClient.Id, remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback), - isDistributedTracingEnabled: clientOptions.IsDistributedTracingEnabled); + cosmosClientTelemetryOptions: clientOptions.CosmosClientTelemetryOptions); return ClientContextCore.Create( cosmosClient, diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index 8898cea96d..f7fe0c307f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -31,7 +31,7 @@ public static bool IsEnabled(EventLevel level) [NonEvent] public static void RecordDiagnosticsForRequests( - DistributedTracingOptions config, + CosmosThresholdOptions config, Documents.OperationType operationType, OpenTelemetryAttributes response) { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs deleted file mode 100644 index 6c44f06bf2..0000000000 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/DistributedTracingOptions.cs +++ /dev/null @@ -1,30 +0,0 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos -{ - using System; - - /// - /// Options for configuring the distributed tracing and event tracing - /// - internal sealed class DistributedTracingOptions - { - /// - /// Default Latency threshold for other than query Operation - /// - internal static readonly TimeSpan DefaultCrudLatencyThreshold = TimeSpan.FromMilliseconds(100); - - /// - /// Default Latency threshold for QUERY operation - /// - internal static readonly TimeSpan DefaultQueryTimeoutThreshold = TimeSpan.FromMilliseconds(500); - - /// - /// SDK generates (Event Source Name is "Azure-Cosmos-Operation-Request-Diagnostics") with Request Diagnostics String, If Operation level distributed tracing is not disabled i.e. - /// - /// If it is not set then, by default, it will generate for query operation which are taking more than 500 ms and non-query operations taking more than 100 ms. - public TimeSpan? LatencyThresholdForDiagnosticEvent { get; set; } - } -} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index d48392bb3e..3c0646f101 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -10,29 +10,18 @@ namespace Microsoft.Azure.Cosmos.Telemetry.Diagnostics internal static class DiagnosticsFilterHelper { + private static readonly CosmosThresholdOptions defaultThresholdOptions = new CosmosThresholdOptions(); + /// /// Allow only when Latency is not more than 100 (non-query) /250 (query) ms /// /// true or false public static bool IsLatencyThresholdCrossed( - DistributedTracingOptions config, + CosmosThresholdOptions config, OperationType operationType, OpenTelemetryAttributes response) { - TimeSpan latencyThreshold; - - if (config?.LatencyThresholdForDiagnosticEvent != null) - { - latencyThreshold = config.LatencyThresholdForDiagnosticEvent.Value; - } - else - { - latencyThreshold = DiagnosticsFilterHelper.IsPointOperation(operationType) ? - DistributedTracingOptions.DefaultCrudLatencyThreshold : - DistributedTracingOptions.DefaultQueryTimeoutThreshold; - } - - return response.Diagnostics.GetClientElapsedTime() > latencyThreshold; + return response.Diagnostics.GetClientElapsedTime() > DiagnosticsFilterHelper.DefaultThreshold(operationType, config); } /// @@ -48,11 +37,24 @@ public static bool IsSuccessfulResponse(HttpStatusCode statusCode, int substatus || (statusCode == System.Net.HttpStatusCode.PreconditionFailed && substatusCode == 0); } + /// + /// Get default threshold value based on operation type + /// + /// + /// + internal static TimeSpan DefaultThreshold(OperationType operationType, CosmosThresholdOptions config) + { + config ??= DiagnosticsFilterHelper.defaultThresholdOptions; + return DiagnosticsFilterHelper.IsPointOperation(operationType) ? + config.PointOperationLatencyThreshold : + config.NonPointOperationLatencyThreshold; + } + /// /// Check if passed operation type is a point operation /// /// - public static bool IsPointOperation(OperationType operationType) + internal static bool IsPointOperation(OperationType operationType) { return operationType == OperationType.Create || operationType == OperationType.Delete || diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index ced441d368..3679d7c7bd 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -18,7 +18,7 @@ internal struct OpenTelemetryCoreRecorder : IDisposable private const string CosmosDb = "cosmosdb"; private readonly DiagnosticScope scope = default; - private readonly DistributedTracingOptions config = null; + private readonly CosmosThresholdOptions config = null; private readonly Activity activity = null; private readonly Documents.OperationType operationType = Documents.OperationType.Invalid; @@ -51,7 +51,7 @@ private OpenTelemetryCoreRecorder( string containerName, string databaseName, Documents.OperationType operationType, - CosmosClientContext clientContext, DistributedTracingOptions config) + CosmosClientContext clientContext, CosmosThresholdOptions config) { this.scope = scope; this.config = config; @@ -96,7 +96,7 @@ public static OpenTelemetryCoreRecorder CreateOperationLevelParentActivity( string databaseName, Documents.OperationType operationType, CosmosClientContext clientContext, - DistributedTracingOptions config) + CosmosThresholdOptions config) { return new OpenTelemetryCoreRecorder( operationScope, diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index ca0b864d2f..61d8889aaa 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -42,7 +42,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, CosmosClientContext clientContext) { OpenTelemetryCoreRecorder openTelemetryRecorder = default; - if (clientContext is { ClientOptions.IsDistributedTracingEnabled: true }) + if (clientContext is { ClientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing: false }) { // If there is no source then it will return default otherwise a valid diagnostic scope DiagnosticScope scope = LazyOperationScopeFactory.Value.CreateScope(name: operationName, @@ -60,7 +60,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, databaseName: databaseName, operationType: operationType, clientContext: clientContext, - config: requestOptions?.DistributedTracingOptions ?? clientContext.ClientOptions?.DistributedTracingOptions); + config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); } #if !INTERNAL else if (Activity.Current is null) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs index f358076b25..2d0e79071f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs @@ -68,7 +68,7 @@ public static TelemetryToServiceHelper CreateAndInitializeClientConfigAndTelemet #if INTERNAL return new TelemetryToServiceHelper(); #else - if (!connectionPolicy.EnableClientTelemetry) + if (connectionPolicy.CosmosClientTelemetryOptions.DisableSendingMetricsToService) { return new TelemetryToServiceHelper(); } @@ -217,7 +217,7 @@ private void InitializeClientTelemetry(AccountClientConfiguration clientConfig) catch (Exception ex) { DefaultTrace.TraceWarning($"Error While starting Telemetry Job : {0}. Hence disabling Client Telemetry", ex); - this.connectionPolicy.EnableClientTelemetry = false; + this.connectionPolicy.CosmosClientTelemetryOptions.DisableSendingMetricsToService = true; } } else diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index fa758baa05..d24e0d6ac3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -3969,9 +3969,14 @@ maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) - .WithDistributedTracingOptions(new DistributedTracingOptions() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 23f61fcef1..62b8f5b2bb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -190,9 +190,14 @@ Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => builder - .WithDistributedTracingOptions(new DistributedTracingOptions() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } }) .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs index 57b5357055..9447191a90 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs @@ -80,7 +80,10 @@ public async Task Validate_ClientTelemetryJob_Status_if_Disabled_At_Instance_Lev this.cosmosClientBuilder .WithHttpClientFactory(() => new HttpClient(httpHandler)) - .WithTelemetryDisabled(); + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = true + }); this.SetClient(this.cosmosClientBuilder.Build()); @@ -144,7 +147,10 @@ public async Task Validate_ClientTelemetryJob_Status_with_Client_Config_Api_Stat this.cosmosClientBuilder .WithHttpClientFactory(() => new HttpClient(httpHandler)) - .WithTelemetryEnabled(); + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = false + }); this.SetClient(this.cosmosClientBuilder.Build()); @@ -212,7 +218,10 @@ public async Task Validate_ClientTelemetryJob_When_Flag_Is_Switched(bool flagSta this.cosmosClientBuilder .WithHttpClientFactory(() => new HttpClient(httpHandler)) - .WithTelemetryEnabled(); + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = false + }); this.SetClient(this.cosmosClientBuilder.Build()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs index 30c239a036..3bb8a53c0c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs @@ -140,7 +140,10 @@ public virtual void TestInitialize() }; this.cosmosClientBuilder = this.GetBuilder() - .WithTelemetryEnabled() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = false + }) .WithApplicationPreferredRegions(ClientTelemetryTestsBase.preferredRegionList); } @@ -666,7 +669,10 @@ public virtual async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) // Replacing originally initialized cosmos Builder with this one with new handler this.cosmosClientBuilder = this.cosmosClientBuilder - .WithTelemetryEnabled() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableSendingMetricsToService = false + }) .WithHttpClientFactory(() => new HttpClient(httpHandler)); Container container = await this.CreateClientAndContainer( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs index 8b5825831c..53b0eb6e24 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs @@ -19,7 +19,6 @@ namespace Microsoft.Azure.Cosmos using System.Diagnostics; using Microsoft.Azure.Cosmos.Tracing; using System.Net.Http; - using System.ComponentModel; [VisualStudio.TestTools.UnitTesting.TestClass] public sealed class DistributedTracingOTelTests : BaseCosmosClientHelper @@ -46,7 +45,10 @@ public async Task SourceEnabled_FlagOn_DirectMode_RecordsActivity_AssertLogTrace await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder - .WithDistributedTracing(true) + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + }) .WithConnectionModeDirect()); Container containerResponse = await this.database.CreateContainerAsync( @@ -128,7 +130,10 @@ public async Task SourceEnabled_FlagOn_GatewayMode_RecordsActivity_AssertLogTrac await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder - .WithDistributedTracing(true) + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + }) .WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper)) .WithConnectionModeGateway()); @@ -158,13 +163,13 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, } [DataTestMethod] - [DataRow(false, true, "random.source.name", DisplayName = "DirectMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] - [DataRow(true, true, "random.source.name", DisplayName = "GatewayMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] - [DataRow(false, false, "random.source.name", DisplayName = "DirectMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] - [DataRow(true, false, "random.source.name", DisplayName = "GatewayMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] - [DataRow(false, false, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "DirectMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] - [DataRow(true, false, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "GatewayMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] - public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_AssertLogTraceId(bool useGateway, bool enableDistributingTracing, string source) + [DataRow(false, false, "random.source.name", DisplayName = "DirectMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] + [DataRow(true, false, "random.source.name", DisplayName = "GatewayMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] + [DataRow(false, true, "random.source.name", DisplayName = "DirectMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] + [DataRow(true, true, "random.source.name", DisplayName = "GatewayMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] + [DataRow(false, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "DirectMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] + [DataRow(true, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "GatewayMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] + public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_AssertLogTraceId(bool useGateway, bool disableDistributingTracing, string source) { using TracerProvider provider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() @@ -175,14 +180,20 @@ public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_Assert { await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder - .WithDistributedTracing(enableDistributingTracing) + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = disableDistributingTracing + }) .WithConnectionModeGateway()); } else { await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder - .WithDistributedTracing(enableDistributingTracing)); + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = disableDistributingTracing + })); } ContainerResponse containerResponse = await this.database.CreateContainerAsync( @@ -194,7 +205,7 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); - if (enableDistributingTracing) + if (!disableDistributingTracing) { //DistributedTraceId present in logs string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs index 1c5676a46a..a51a77f14f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs @@ -59,7 +59,10 @@ public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) { using (CosmosClient client = TestCommon.CreateCosmosClient( customizeClientBuilder: (builder) => builder - .WithTelemetryEnabled() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions () + { + DisableSendingMetricsToService = !withClientTelemetry + }) .WithHttpClientFactory(() => new HttpClient(httpHandler)))) { Cosmos.Database database = client.CreateDatabaseAsync(databaseId).GetAwaiter().GetResult(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 79e947d41b..6cd8905b07 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -47,28 +47,48 @@ public sealed class EndToEndTraceWriterBaselineTests : BaselineTests builder + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } + })); + bulkClient = TestCommon.CreateCosmosClient(builder => builder .WithBulkExecution(true) - .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - })); - + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } + })); + // Set a small retry count to reduce test time miscCosmosClient = TestCommon.CreateCosmosClient(builder => builder .AddCustomHandlers(requestHandler) - .WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - })); + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } + })); EndToEndTraceWriterBaselineTests.database = await client.CreateDatabaseAsync( "databaseName", @@ -682,7 +702,10 @@ public async Task ValidateInvalidCredentialsTraceAsync() // It is not baseline test hence disable distributed tracing for this test CosmosClientOptions clientOptions = new CosmosClientOptions() { - IsDistributedTracingEnabled = false + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = true + } }; using (CosmosClient client = new CosmosClient( @@ -1015,9 +1038,14 @@ public async Task PointOperationsExceptionsAsync() Guid exceptionActivityId = Guid.NewGuid(); using CosmosClient throttleClient = TestCommon.CreateCosmosClient(builder => builder - .WithDistributedTracingOptions(new DistributedTracingOptions() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } }) .WithThrottlingRetryOptions( maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), @@ -1303,9 +1331,14 @@ public async Task BulkOperationsAsync() maxRetryWaitTimeOnThrottledRequests: TimeSpan.FromSeconds(1), maxRetryAttemptsOnThrottledRequests: 3) .WithBulkExecution(true) - .WithDistributedTracingOptions(new DistributedTracingOptions() + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } }) .WithTransportClientHandlerFactory(transportClient => new TransportClientWrapper( transportClient, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index 8cfa5be33b..48a5025289 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -130,8 +130,7 @@ internal static CosmosClient CreateCosmosClient( internal static CosmosClient CreateCosmosClient( bool useGateway, - Action customizeClientBuilder = null, - bool enableDistributingTracing = false) + Action customizeClientBuilder = null) { CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(); @@ -141,14 +140,6 @@ internal static CosmosClient CreateCosmosClient( { cosmosClientBuilder.WithConnectionModeGateway(); } - - if(enableDistributingTracing) - { - cosmosClientBuilder.WithDistributedTracingOptions(new DistributedTracingOptions() - { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }); - } return cosmosClientBuilder.Build(); } @@ -164,8 +155,7 @@ internal static DocumentClient CreateClient(bool useGateway, Protocol protocol = RetryOptions retryOptions = null, ApiType apiType = ApiType.None, EventHandler recievedResponseEventHandler = null, - bool useMultipleWriteLocations = false, - bool enableClientTelemetry = false) + bool useMultipleWriteLocations = false) { string authKey = ConfigurationManager.AppSettings["MasterKey"]; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs index f34135b695..ebeebad7ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TransportClientHelper.cs @@ -83,9 +83,14 @@ internal static Container GetContainerWithIntercepter( if (enableDistributingTracing) { - builder.WithDistributedTracingOptions(new DistributedTracingOptions() + builder.WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(.0001) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.Zero, + NonPointOperationLatencyThreshold = TimeSpan.Zero + } }); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs index 3484abb3ae..7d268407de 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs @@ -54,9 +54,11 @@ public static CosmosClient CreateMockCosmosClient( { policy = new ConnectionPolicy { - EnableClientTelemetry = true // feature flag is always true + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions + { + DisableSendingMetricsToService = !isClientTelemetryEnabled.Value + } }; - } MockDocumentClient documentClient = new MockDocumentClient(policy); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 8546a93b2f..8f25a74f08 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -355,24 +355,141 @@ "Microsoft.Azure.Cosmos.CosmosClientOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { - "Boolean get_IsDistributedTracingEnabled()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ "CompilerGeneratedAttribute" ], - "MethodInfo": "Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Boolean DisableDistributedTracing": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean DisableDistributedTracing;CanRead:True;CanWrite:True;Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Boolean IsDistributedTracingEnabled": { + "Boolean DisableSendingMetricsToService": { "Type": "Property", "Attributes": [], - "MethodInfo": "Boolean IsDistributedTracingEnabled;CanRead:True;CanWrite:True;Boolean get_IsDistributedTracingEnabled();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Boolean DisableSendingMetricsToService;CanRead:True;CanWrite:True;Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_DisableDistributedTracing()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_DisableSendingMetricsToService()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DisableDistributedTracing(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DisableSendingMetricsToService(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.TimeSpan get_NonPointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_PointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan NonPointOperationLatencyThreshold": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan NonPointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan PointOperationLatencyThreshold": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan PointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_NonPointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, - "Void set_IsDistributedTracingEnabled(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Void set_PointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ "CompilerGeneratedAttribute" ], - "MethodInfo": "Void set_IsDistributedTracingEnabled(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} @@ -454,10 +571,10 @@ "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { - "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean)": { + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)": { "Type": "Method", "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 37d89c389a..f3c45adf48 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -99,6 +99,12 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreNotEqual(Cosmos.ConsistencyLevel.Session, clientOptions.ConsistencyLevel); Assert.IsFalse(policy.EnablePartitionLevelFailover); Assert.IsFalse(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue); +#if PREVIEW + Assert.IsFalse(clientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing); +#else + Assert.IsTrue(clientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing); +#endif + Assert.IsTrue(clientOptions.CosmosClientTelemetryOptions.DisableSendingMetricsToService); cosmosClientBuilder.WithApplicationRegion(region) .WithConnectionModeGateway(maxConnections, webProxy) @@ -164,9 +170,14 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() portReuseMode, enableTcpConnectionEndpointRediscovery) .WithApplicationPreferredRegions(preferredLocations) - .WithDistributedTracingOptions(new DistributedTracingOptions + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { - LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(100) + DisableDistributedTracing = false, + CosmosThresholdOptions = new CosmosThresholdOptions() + { + PointOperationLatencyThreshold = TimeSpan.FromMilliseconds(100), + NonPointOperationLatencyThreshold = TimeSpan.FromMilliseconds(100) + } }); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); @@ -179,8 +190,9 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, clientOptions.PortReuseMode); Assert.IsTrue(clientOptions.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), clientOptions.ApplicationPreferredRegions.ToArray()); - Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.DistributedTracingOptions.LatencyThresholdForDiagnosticEvent); - Assert.IsTrue(clientOptions.IsDistributedTracingEnabled); + Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.CosmosClientTelemetryOptions.CosmosThresholdOptions.PointOperationLatencyThreshold); + Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.CosmosClientTelemetryOptions.CosmosThresholdOptions.NonPointOperationLatencyThreshold); + Assert.IsFalse(clientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing); //Verify GetConnectionPolicy returns the correct values policy = clientOptions.GetConnectionPolicy(clientId: 0); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs index 8d08704eeb..6740001f53 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.Tests using System; using System.Collections.Generic; using System.Diagnostics; - using System.Collections.Specialized; using System.Globalization; using System.Linq; using System.Net; @@ -16,7 +15,6 @@ namespace Microsoft.Azure.Cosmos.Tests using System.Threading; using System.Threading.Tasks; using System.Web; - using FluentAssertions; using global::Azure; using global::Azure.Core; using Microsoft.Azure.Cosmos.Core.Trace; @@ -248,11 +246,7 @@ public void ValidateMasterKeyAuthProvider() using (CosmosClient client = new CosmosClient( CosmosClientTests.AccountEndpoint, - masterKeyCredential, - new CosmosClientOptions() - { - EnableClientTelemetry = false, - })) + masterKeyCredential)) { Assert.AreEqual(typeof(AuthorizationTokenProviderMasterKey), client.AuthorizationTokenProvider.GetType()); } @@ -265,11 +259,7 @@ public void ValidateResourceTokenAuthProvider() using (CosmosClient client = new CosmosClient( CosmosClientTests.AccountEndpoint, - resourceToken, - new CosmosClientOptions() - { - EnableClientTelemetry = false, - })) + resourceToken)) { Assert.AreEqual(typeof(AuthorizationTokenProviderResourceToken), client.AuthorizationTokenProvider.GetType()); } @@ -283,11 +273,7 @@ public void ValidateMasterKeyAzureCredentialAuthProvider() AzureKeyCredential masterKeyCredential = new AzureKeyCredential(originalKey); using (CosmosClient client = new CosmosClient( CosmosClientTests.AccountEndpoint, - masterKeyCredential, - new CosmosClientOptions() - { - EnableClientTelemetry = false, - })) + masterKeyCredential)) { Assert.AreEqual(typeof(AzureKeyCredentialAuthorizationTokenProvider), client.AuthorizationTokenProvider.GetType()); @@ -304,11 +290,7 @@ public void ValidateResourceTokenAzureCredentialAuthProvider() AzureKeyCredential resourceTokenCredential = new AzureKeyCredential(resourceToken); using (CosmosClient client = new CosmosClient( CosmosClientTests.AccountEndpoint, - resourceTokenCredential, - new CosmosClientOptions() - { - EnableClientTelemetry = false, - })) + resourceTokenCredential)) { Assert.AreEqual(typeof(AzureKeyCredentialAuthorizationTokenProvider), client.AuthorizationTokenProvider.GetType()); @@ -377,8 +359,7 @@ public async Task ValidateAzureKeyCredentialGatewayModeUpdateAsync() masterKeyCredential, new CosmosClientOptions() { - HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)), - EnableClientTelemetry = false, + HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)) })) { Container container = client.GetContainer(Guid.NewGuid().ToString(), Guid.NewGuid().ToString()); @@ -440,10 +421,7 @@ void TraceHandler(string message) for (int z = 0; z < 100; ++z) { - using CosmosClient cosmos = new(ConnectionString, new CosmosClientOptions - { - EnableClientTelemetry = true - }); + using CosmosClient cosmos = new(ConnectionString); } string assertMsg = String.Empty; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs index c620b726e7..cd0a92ad1b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs @@ -58,8 +58,9 @@ public async Task RefreshTestAsync() { // Get default instance of DiagnosticsHandlerHelper with client telemetry disabled (default) DiagnosticsHandlerHelper diagnosticHandlerHelper1 = DiagnosticsHandlerHelper.GetInstance(); - await Task.Delay(10000); // warm up + await Task.Delay(10000); // warm up to make sure there is at least one entry in the history Assert.IsNotNull(diagnosticHandlerHelper1.GetDiagnosticsSystemHistory()); + Assert.IsNull(diagnosticHandlerHelper1.GetClientTelemetrySystemHistory()); Assert.IsTrue(diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count > 0); int countBeforeRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; @@ -69,22 +70,21 @@ public async Task RefreshTestAsync() Assert.IsNull(TelemetrySystemUsageRecorderField1.GetValue(null)); // Refresh instance of DiagnosticsHandlerHelper with client telemetry enabled - DiagnosticsHandlerHelper.Refresh(true); - await Task.Delay(5000); // warm up again to populate telemetry data + DiagnosticsHandlerHelper.Refresh(isClientTelemetryEnabled: true); DiagnosticsHandlerHelper diagnosticHandlerHelper2 = DiagnosticsHandlerHelper.GetInstance(); - int countAfterRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; - + Assert.IsNotNull(diagnosticHandlerHelper2.GetDiagnosticsSystemHistory()); + int countAfterRefresh = diagnosticHandlerHelper2.GetDiagnosticsSystemHistory().Values.Count; + Assert.IsTrue(countBeforeRefresh <= countAfterRefresh, "After Refresh count should be greater than or equal to before refresh count"); - Assert.AreNotEqual(diagnosticHandlerHelper1, diagnosticHandlerHelper2); - Assert.IsNotNull(diagnosticHandlerHelper2.GetDiagnosticsSystemHistory()); + await Task.Delay(5000); // warm up to make sure there is at least one entry in the history Assert.IsNotNull(diagnosticHandlerHelper2.GetClientTelemetrySystemHistory()); Assert.IsTrue(diagnosticHandlerHelper2.GetClientTelemetrySystemHistory().Values.Count > 0); // Refresh instance of DiagnosticsHandlerHelper with client telemetry disabled - DiagnosticsHandlerHelper.Refresh(false); + DiagnosticsHandlerHelper.Refresh(isClientTelemetryEnabled: false); DiagnosticsHandlerHelper diagnosticHandlerHelper3 = DiagnosticsHandlerHelper.GetInstance(); Assert.IsNotNull(diagnosticHandlerHelper3.GetDiagnosticsSystemHistory()); Assert.IsNull(diagnosticHandlerHelper3.GetClientTelemetrySystemHistory()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 5e32b26da1..62517239e3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos.Tests.Telemetry using Documents; using VisualStudio.TestTools.UnitTesting; - [TestClass] public class DiagnosticsFilterHelperTest { @@ -33,9 +32,9 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() { Assert.IsTrue(this.rootTrace.Duration > TimeSpan.Zero); - DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions + CosmosThresholdOptions distributedTracingOptions = new CosmosThresholdOptions { - LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) + PointOperationLatencyThreshold = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) }; OpenTelemetryAttributes response = new OpenTelemetryAttributes @@ -48,7 +47,7 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() DiagnosticsFilterHelper .IsLatencyThresholdCrossed(distributedTracingOptions, OperationType.Read, response), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + + $"and Configured threshold value is {distributedTracingOptions.PointOperationLatencyThreshold.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}" ); } @@ -56,13 +55,6 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() public void CheckReturnTrueOnFailedStatusCode() { Assert.IsTrue(this.rootTrace.Duration > TimeSpan.Zero); - - - DistributedTracingOptions distributedTracingOptions = new DistributedTracingOptions - { - LatencyThresholdForDiagnosticEvent = this.rootTrace.Duration.Add(TimeSpan.FromSeconds(1)) - }; - OpenTelemetryAttributes response = new OpenTelemetryAttributes { StatusCode = HttpStatusCode.BadRequest, @@ -73,9 +65,28 @@ public void CheckReturnTrueOnFailedStatusCode() !DiagnosticsFilterHelper .IsSuccessfulResponse(response.StatusCode, response.SubStatusCode), $" Response time is {response.Diagnostics.GetClientElapsedTime().Milliseconds}ms " + - $"and Configured threshold value is {distributedTracingOptions.LatencyThresholdForDiagnosticEvent.Value.Milliseconds}ms " + $"and Is response Success : {response.StatusCode.IsSuccess()}"); } + [TestMethod] + public void CheckedDefaultThresholdBasedOnOperationType() + { + Assert.IsTrue(this.rootTrace.Duration > TimeSpan.Zero); + + CosmosThresholdOptions config = new CosmosThresholdOptions(); + + Array values = Enum.GetValues(typeof(OperationType)); + + foreach(OperationType operationType in values) + { + TimeSpan defaultThreshold = DiagnosticsFilterHelper.DefaultThreshold(operationType, config); + + if(DiagnosticsFilterHelper.IsPointOperation(operationType)) + Assert.AreEqual(defaultThreshold, config.PointOperationLatencyThreshold); + else + Assert.AreEqual(defaultThreshold, config.NonPointOperationLatencyThreshold); + } + } + } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs index 92a6e60038..77ba6981cb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockCosmosUtil.cs @@ -36,7 +36,10 @@ public static CosmosClient CreateMockCosmosClient( { ConnectionPolicy policy = new ConnectionPolicy { - EnableClientTelemetry = enableTelemetry + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions + { + DisableSendingMetricsToService = !enableTelemetry + } }; DocumentClient documentClient = accountConsistencyLevel.HasValue ? new MockDocumentClient(accountConsistencyLevel.Value, policy) : new MockDocumentClient(policy); From 7ed22ac55b569354ea94733ea5ab4601d20dd586 Mon Sep 17 00:00:00 2001 From: Kevin Pilch Date: Fri, 6 Oct 2023 16:36:44 -0700 Subject: [PATCH 203/337] [Internal] Build: Adds CodeQL support in nightly builds (#4113) * Update azure-pipelines-nightly.yml * Newlines in variables sections --- azure-pipelines-nightly.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/azure-pipelines-nightly.yml b/azure-pipelines-nightly.yml index 04a53968aa..f0f7f3faea 100644 --- a/azure-pipelines-nightly.yml +++ b/azure-pipelines-nightly.yml @@ -16,10 +16,13 @@ variables: VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops BuildConfiguration: Release Packaging.EnableSBOMSigning: true + Codeql.Enabled: true stages: - stage: displayName: Generate nightly GA + variables: + Codeql.BuildIdentifier: ga jobs: - template: templates/nuget-pack.yml parameters: @@ -32,6 +35,8 @@ stages: CleanupFolder: true - stage: displayName: Generate nightly preview + variables: + Codeql.BuildIdentifier: preview jobs: - template: templates/nuget-pack.yml parameters: @@ -41,4 +46,4 @@ stages: ReleasePackage: true OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' BlobVersion: 'nightly-preview' - CleanupFolder: true \ No newline at end of file + CleanupFolder: true From 75eec5c33abff8fb07886af917d661f0963b452f Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Mon, 9 Oct 2023 20:29:11 +0530 Subject: [PATCH 204/337] Benchmark: Fixes to show estimated cost of a container only when new container is getting created (#4109) * Showing Estimated Cost only when new container is getting created * read container to get container response * disable client telemetry by default * removed unused imports * resolve merge conflict * fixed name * fix container not found * removed the message * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs Co-authored-by: Matias Quaranta * removed line space --------- Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- .../Tools/Benchmark/BenchmarkConfig.cs | 12 ++++++------ .../Tools/Benchmark/Program.cs | 12 +----------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index 0fde6a8926..2c523374bf 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -103,8 +103,8 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Disable core SDK logging")] public bool DisableCoreSdkLogging { get; set; } - [Option(Required = false, HelpText = "Disable Distributed Tracing feature from source")] - public bool DisableDistributedTracing { get; set; } = false; + [Option(Required = false, HelpText = "Enable Distributed Tracing")] + public bool EnableDistributedTracing { get; set; } = false; [Option(Required = false, HelpText = "Client Telemetry Schedule in Seconds")] public int TelemetryScheduleInSec { get; set; } @@ -138,8 +138,8 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Application Insights connection string")] public string AppInsightsConnectionString { get; set; } - [Option(Required = false, HelpText = "Disable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] - public bool DisableClientTelemetry { get; set; } = false; + [Option(Required = false, HelpText = "Enable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] + public bool EnableTelemetry { get; set; } = false; internal int GetTaskCount(int containerThroughput) { @@ -222,8 +222,8 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint, CosmosClientTelemetryOptions = new Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions() { - DisableSendingMetricsToService = this.DisableClientTelemetry, - DisableDistributedTracing = this.DisableDistributedTracing + DisableSendingMetricsToService = !this.EnableTelemetry, + DisableDistributedTracing = !this.EnableDistributedTracing } }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs index 9bbb33b9fd..fde9d5cd2c 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs @@ -7,10 +7,8 @@ namespace CosmosBenchmark using System; using System.Collections.Generic; using System.Diagnostics; - using System.Diagnostics.Tracing; using System.IO; using System.Linq; - using System.Net; using System.Net.Http; using System.Reflection; using System.Threading; @@ -18,7 +16,6 @@ namespace CosmosBenchmark using Azure.Monitor.OpenTelemetry.Exporter; using CosmosBenchmark.Fx; using Microsoft.Azure.Cosmos; - using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using OpenTelemetry; using OpenTelemetry.Metrics; @@ -323,14 +320,7 @@ private static Type[] AvailableBenchmarks() private static async Task CreatePartitionedContainerAsync(BenchmarkConfig options, CosmosClient cosmosClient) { Microsoft.Azure.Cosmos.Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync(options.Database); - - // Show user cost of running this test - double estimatedCostPerMonth = 0.06 * options.Throughput; - double estimatedCostPerHour = estimatedCostPerMonth / (24 * 30); - Utility.TeeTraceInformation($"The container will cost an estimated ${Math.Round(estimatedCostPerHour, 2)} per hour (${Math.Round(estimatedCostPerMonth, 2)} per month)"); - Utility.TeeTraceInformation("Press enter to continue ..."); - Console.ReadLine(); - + string partitionKeyPath = options.PartitionKeyPath; return await database.CreateContainerIfNotExistsAsync(options.Container, partitionKeyPath, options.Throughput); } From a5dec66060a63572ac09d2c4943dc9b218650a70 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 10 Oct 2023 00:08:05 +0530 Subject: [PATCH 205/337] Distributed Tracing: Fixes SDK responses compatibility with opentelemetry response (#4097) * adding tets * wip * wip2 * fix code * add tests * fix test * fix test * remove consoles * fix indent and remove unused imports * internal to private rollback * added docs * removed unused imports * added exception in message * fix exception catching --- .../OpenTelemetryCoreRecorder.cs | 2 +- .../OpenTelemetry/OpenTelemetryResponse.cs | 52 +++-- .../OpenTelemetry/OpenTelemetryResponse{T}.cs | 56 +++-- .../Telemetry/OpenTelemetryRecorderTests.cs | 201 ++++++++++++++++++ 4 files changed, 284 insertions(+), 27 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 3679d7c7bd..2928685d97 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -223,7 +223,7 @@ Documents.OperationType operationType this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, this.response.RequestContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, this.response.ResponseContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)this.response.SubStatusCode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, this.response.SubStatusCode); this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, this.response.RequestCharge); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, this.response.ItemCount); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, this.response.ActivityId); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs index c9aba10ee6..09d43c6965 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse.cs @@ -4,8 +4,10 @@ namespace Microsoft.Azure.Cosmos { + using System; using System.IO; using System.Net; + using Microsoft.Azure.Cosmos.Core.Trace; using Telemetry; internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes @@ -13,28 +15,28 @@ internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes internal OpenTelemetryResponse(TransactionalBatchResponse responseMessage) : this( statusCode: responseMessage.StatusCode, - requestCharge: responseMessage.Headers?.RequestCharge, + requestCharge: OpenTelemetryResponse.GetHeader(responseMessage)?.RequestCharge, responseContentLength: null, diagnostics: responseMessage.Diagnostics, - itemCount: responseMessage.Headers?.ItemCount, + itemCount: OpenTelemetryResponse.GetHeader(responseMessage)?.ItemCount, requestMessage: null, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode, - activityId: responseMessage.Headers?.ActivityId, - correlationId: responseMessage.Headers?.CorrelatedActivityId) + subStatusCode: OpenTelemetryResponse.GetHeader(responseMessage)?.SubStatusCode, + activityId: OpenTelemetryResponse.GetHeader(responseMessage)?.ActivityId, + correlationId: OpenTelemetryResponse.GetHeader(responseMessage)?.CorrelatedActivityId) { } internal OpenTelemetryResponse(ResponseMessage responseMessage) : this( statusCode: responseMessage.StatusCode, - requestCharge: responseMessage.Headers?.RequestCharge, + requestCharge: OpenTelemetryResponse.GetHeader(responseMessage)?.RequestCharge, responseContentLength: OpenTelemetryResponse.GetPayloadSize(responseMessage), diagnostics: responseMessage.Diagnostics, - itemCount: responseMessage.Headers?.ItemCount, + itemCount: OpenTelemetryResponse.GetHeader(responseMessage)?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode, - activityId: responseMessage.Headers?.ActivityId, - correlationId: responseMessage.Headers?.CorrelatedActivityId, + subStatusCode: OpenTelemetryResponse.GetHeader(responseMessage)?.SubStatusCode, + activityId: OpenTelemetryResponse.GetHeader(responseMessage)?.ActivityId, + correlationId: OpenTelemetryResponse.GetHeader(responseMessage)?.CorrelatedActivityId, operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid ) { @@ -47,7 +49,7 @@ private OpenTelemetryResponse( CosmosDiagnostics diagnostics, string itemCount, RequestMessage requestMessage, - int subStatusCode, + Documents.SubStatusCodes? subStatusCode, string activityId, string correlationId, Documents.OperationType operationType = Documents.OperationType.Invalid) @@ -58,7 +60,7 @@ private OpenTelemetryResponse( this.ResponseContentLength = responseContentLength; this.Diagnostics = diagnostics; this.ItemCount = itemCount; - this.SubStatusCode = subStatusCode; + this.SubStatusCode = (int)(subStatusCode ?? Documents.SubStatusCodes.Unknown); this.ActivityId = activityId; this.CorrelatedActivityId = correlationId; this.OperationType = operationType; @@ -74,5 +76,31 @@ private static string GetPayloadSize(ResponseMessage response) } return response?.Headers?.ContentLength; } + + private static Headers GetHeader(TransactionalBatchResponse responseMessage) + { + try + { + return responseMessage?.Headers; + } + catch (NotImplementedException ex) + { + DefaultTrace.TraceVerbose("Failed to get headers from TransactionalBatchResponse. Exception: {0}", ex); + return null; + } + } + + private static Headers GetHeader(ResponseMessage responseMessage) + { + try + { + return responseMessage?.Headers; + } + catch (NotImplementedException ex) + { + DefaultTrace.TraceVerbose("Failed to get headers from ResponseMessage. Exception: {0}", ex); + return null; + } + } } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs index 4c96306a30..976b68173a 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryResponse{T}.cs @@ -4,7 +4,9 @@ namespace Microsoft.Azure.Cosmos { + using System; using System.Net; + using Microsoft.Azure.Cosmos.Core.Trace; using Telemetry; internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes @@ -12,14 +14,14 @@ internal sealed class OpenTelemetryResponse : OpenTelemetryAttributes internal OpenTelemetryResponse(FeedResponse responseMessage) : this( statusCode: responseMessage.StatusCode, - requestCharge: responseMessage.Headers?.RequestCharge, - responseContentLength: responseMessage?.Headers?.ContentLength, + requestCharge: OpenTelemetryResponse.GetHeader(responseMessage)?.RequestCharge, + responseContentLength: OpenTelemetryResponse.GetHeader(responseMessage)?.ContentLength, diagnostics: responseMessage.Diagnostics, - itemCount: responseMessage.Headers?.ItemCount, + itemCount: OpenTelemetryResponse.GetHeader(responseMessage)?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode, - activityId: responseMessage.Headers?.ActivityId, - correlatedActivityId: responseMessage.Headers?.CorrelatedActivityId, + subStatusCode: OpenTelemetryResponse.GetHeader(responseMessage)?.SubStatusCode, + activityId: OpenTelemetryResponse.GetHeader(responseMessage)?.ActivityId, + correlatedActivityId: OpenTelemetryResponse.GetHeader(responseMessage)?.CorrelatedActivityId, operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid) { } @@ -27,14 +29,14 @@ internal OpenTelemetryResponse(FeedResponse responseMessage) internal OpenTelemetryResponse(Response responseMessage) : this( statusCode: responseMessage.StatusCode, - requestCharge: responseMessage.Headers?.RequestCharge, - responseContentLength: responseMessage?.Headers?.ContentLength, + requestCharge: OpenTelemetryResponse.GetHeader(responseMessage)?.RequestCharge, + responseContentLength: OpenTelemetryResponse.GetHeader(responseMessage)?.ContentLength, diagnostics: responseMessage.Diagnostics, - itemCount: responseMessage.Headers?.ItemCount, + itemCount: OpenTelemetryResponse.GetHeader(responseMessage)?.ItemCount, requestMessage: responseMessage.RequestMessage, - subStatusCode: (int)responseMessage.Headers?.SubStatusCode, - activityId: responseMessage.Headers?.ActivityId, - correlatedActivityId: responseMessage.Headers?.CorrelatedActivityId, + subStatusCode: OpenTelemetryResponse.GetHeader(responseMessage)?.SubStatusCode, + activityId: OpenTelemetryResponse.GetHeader(responseMessage)?.ActivityId, + correlatedActivityId: OpenTelemetryResponse.GetHeader(responseMessage)?.CorrelatedActivityId, operationType: responseMessage is QueryResponse ? Documents.OperationType.Query : Documents.OperationType.Invalid) { } @@ -46,7 +48,7 @@ private OpenTelemetryResponse( CosmosDiagnostics diagnostics, string itemCount, RequestMessage requestMessage, - int subStatusCode, + Documents.SubStatusCodes? subStatusCode, string activityId, string correlatedActivityId, Documents.OperationType operationType) @@ -57,10 +59,36 @@ private OpenTelemetryResponse( this.ResponseContentLength = responseContentLength; this.Diagnostics = diagnostics; this.ItemCount = itemCount; - this.SubStatusCode = subStatusCode; + this.SubStatusCode = (int)(subStatusCode ?? Documents.SubStatusCodes.Unknown); this.ActivityId = activityId; this.CorrelatedActivityId = correlatedActivityId; this.OperationType = operationType; } + + private static Headers GetHeader(FeedResponse responseMessage) + { + try + { + return responseMessage?.Headers; + } + catch (NotImplementedException ex) + { + DefaultTrace.TraceWarning("Failed to get headers from FeedResponse. Exception: {0}", ex); + return null; + } + } + + private static Headers GetHeader(Response responseMessage) + { + try + { + return responseMessage?.Headers; + } + catch (NotImplementedException ex) + { + DefaultTrace.TraceWarning("Failed to get headers from Response. Exception: {0}", ex); + return null; + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/OpenTelemetryRecorderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/OpenTelemetryRecorderTests.cs index 2095999f6c..601045cba5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/OpenTelemetryRecorderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/OpenTelemetryRecorderTests.cs @@ -6,12 +6,18 @@ namespace Microsoft.Azure.Cosmos.Tests.Telemetry { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Linq; + using System.Net; using System.Reflection; + using System.Threading; + using System.Threading.Tasks; using Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Diagnostics; + using Microsoft.Azure.Cosmos.Scripts; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; [TestClass] public class OpenTelemetryRecorderTests @@ -43,6 +49,201 @@ public void CheckExceptionsCompatibility() } } + /// + /// This test verifies whether OpenTelemetryResponse can be initialized using a specific type of response available in the SDK. + /// If any new response is added to the SDK in the future, it must be configured in either of the following dictionaries. + /// + [TestMethod] + public async Task CheckResponseCompatibility() + { + // This list contains all the response types which are not compatible with Open Telemetry Response + IReadOnlyList excludedResponses = new List() + { + "MediaResponse", // Part of dead code + "DocumentFeedResponse`1",// Part of dead code + "CosmosQuotaResponse",// Part of dead code + "StoredProcedureResponse`1" // Not supported as of now + }; + + // This dictionary contains a Key-Value pair where the Key represents the Response Type compatible with Open Telemetry Response, and the corresponding Value is a mocked instance. + // Essentially, at some point in the code, we send an instance of the response to Open Telemetry to retrieve relevant information. + IDictionary responseInstances = new Dictionary() + { + { "PartitionKeyRangeBatchResponse", await OpenTelemetryRecorderTests.GetPartitionKeyRangeBatchResponse() }, + { "TransactionalBatchResponse", await OpenTelemetryRecorderTests.GetTransactionalBatchResponse() }, + { "QueryResponse", new Mock().Object }, + { "QueryResponse`1", OpenTelemetryRecorderTests.GetQueryResponseWithGenerics()}, + { "ReadFeedResponse`1", ReadFeedResponse.CreateResponse (new ResponseMessage(HttpStatusCode.OK),MockCosmosUtil.Serializer)}, + { "ClientEncryptionKeyResponse", new Mock().Object}, + { "ContainerResponse", new Mock().Object }, + { "ItemResponse`1", new Mock>().Object }, + { "DatabaseResponse", new Mock().Object }, + { "PermissionResponse", new Mock().Object }, + { "ThroughputResponse", new Mock().Object }, + { "UserResponse", new Mock().Object }, + { "ChangeFeedEstimatorFeedResponse", ChangefeedResponseFunc}, + { "ChangeFeedEstimatorEmptyFeedResponse", ChangeFeedEstimatorEmptyFeedResponseFunc }, + { "StoredProcedureExecuteResponse`1",new Mock>().Object }, + { "StoredProcedureResponse", new Mock().Object }, + { "TriggerResponse", new Mock().Object }, + { "UserDefinedFunctionResponse", new Mock().Object } + }; + + Assembly asm = OpenTelemetryRecorderTests.GetAssemblyLocally(DllName); + + // Get all types (including internal) defined in the assembly + IEnumerable actualClasses = asm + .GetTypes() + .Where(type => + (type.Name.EndsWith("Response") || type.Name.EndsWith("Response`1")) && // Ending with Response and Response + !type.Name.Contains("OpenTelemetryResponse") && // Excluding OpenTelemetryResponse because we are testing this class + !type.IsAbstract && // Excluding abstract classes + !type.IsInterface && // Excluding interfaces + !excludedResponses.Contains(type.Name)); // Excluding all the types defined in excludedResponses list + + foreach (Type className in actualClasses) + { + Assert.IsTrue(responseInstances.TryGetValue(className.Name, out object instance), $" New Response type found i.e.{className.Name}"); + + if (instance is TransactionalBatchResponse transactionInstance) + { + _ = new OpenTelemetryResponse(transactionInstance); + } + else if (instance is ResponseMessage responseMessageInstance) + { + _ = new OpenTelemetryResponse(responseMessageInstance); + } + else if (instance is FeedResponse feedResponseInstance) + { + _ = new OpenTelemetryResponse(feedResponseInstance); + } + else if (instance is Response responseInstance) + { + _ = new OpenTelemetryResponse(responseInstance); + } + else if (instance is Response encrypResponse) + { + _ = new OpenTelemetryResponse(encrypResponse); + } + else if (instance is Response containerPropertiesResponse) + { + _ = new OpenTelemetryResponse(containerPropertiesResponse); + } + else if (instance is Response databasePropertiesResponse) + { + _ = new OpenTelemetryResponse(databasePropertiesResponse); + } + else if (instance is Response permissionPropertiesResponse) + { + _ = new OpenTelemetryResponse(permissionPropertiesResponse); + } + else if (instance is Response throughputPropertiesResponse) + { + _ = new OpenTelemetryResponse(throughputPropertiesResponse); + } + else if (instance is Response userPropertiesResponse) + { + _ = new OpenTelemetryResponse(userPropertiesResponse); + } + else if (instance is Func> fucntion) + { + _ = new OpenTelemetryResponse(fucntion(className)); + } + else if (instance is Response storedProcedureResponse) + { + _ = new OpenTelemetryResponse(storedProcedureResponse); + } + else if (instance is Response triggerResponse) + { + _ = new OpenTelemetryResponse(triggerResponse); + } + else if (instance is Response userDefinedFunctionResponse) + { + _ = new OpenTelemetryResponse(userDefinedFunctionResponse); + } + else if (instance is Response> storedProcedureExecuteResponse) + { + _ = new OpenTelemetryResponse>(storedProcedureExecuteResponse); + } + else + { + Assert.Fail("Opentelemetry does not support this response type " + className.Name); + } + } + } + + private static readonly Func> ChangefeedResponseFunc = (Type type) => + { + ConstructorInfo constructorInfo = type + .GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ITrace), typeof(ReadOnlyCollection), typeof(double) }, null); + if (constructorInfo != null) + { + return (FeedResponse)constructorInfo.Invoke( + new object[] { + NoOpTrace.Singleton, new List().AsReadOnly(), 10 }); + } + + return null; + }; + + private static readonly Func> ChangeFeedEstimatorEmptyFeedResponseFunc = (Type type) => + { + ConstructorInfo constructorInfo = type + .GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(ITrace) }, null); + if (constructorInfo != null) + { + return (FeedResponse)constructorInfo.Invoke( + new object[] { + NoOpTrace.Singleton}); + } + + return null; + }; + + private static QueryResponse GetQueryResponseWithGenerics() + { + return QueryResponse.CreateResponse( + QueryResponse.CreateFailure( + new CosmosQueryResponseMessageHeaders(null, null, Documents.ResourceType.Document, "col"), HttpStatusCode.OK, new RequestMessage(), null, NoOpTrace.Singleton), + MockCosmosUtil.Serializer); + } + + private static async Task GetTransactionalBatchResponse(ItemBatchOperation[] arrayOperations = null) + { + if(arrayOperations == null) + { + arrayOperations = new ItemBatchOperation[1]; + arrayOperations[0] = new ItemBatchOperation(Documents.OperationType.Read, 0, new PartitionKey("0")); + } + + SinglePartitionKeyServerBatchRequest batchRequest = await SinglePartitionKeyServerBatchRequest.CreateAsync( + partitionKey: null, + operations: new ArraySegment(arrayOperations), + serializerCore: MockCosmosUtil.Serializer, + trace: NoOpTrace.Singleton, + cancellationToken: default); + + return await TransactionalBatchResponse.FromResponseMessageAsync( + new ResponseMessage(HttpStatusCode.OK) { Content = new System.IO.MemoryStream() }, + batchRequest, + MockCosmosUtil.Serializer, + true, + NoOpTrace.Singleton, + CancellationToken.None); + } + + private static async Task GetPartitionKeyRangeBatchResponse() + { + ItemBatchOperation[] arrayOperations = new ItemBatchOperation[1]; + + arrayOperations[0] = new ItemBatchOperation(Documents.OperationType.Read, 0, new PartitionKey("0")); + PartitionKeyRangeBatchResponse partitionKeyRangeBatchResponse = new PartitionKeyRangeBatchResponse( + arrayOperations.Length, + await OpenTelemetryRecorderTests.GetTransactionalBatchResponse(arrayOperations), + MockCosmosUtil.Serializer); + + return partitionKeyRangeBatchResponse; + } [TestMethod] public void MarkFailedTest() From 88fd4cdb9bd9975ae663e559e967a217745d1d02 Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:48:52 -0700 Subject: [PATCH 206/337] Revert "Query: Adds new system strings in JsonBinaryEncoding, replacing 1-byte user strings (#3400)" (#4108) This reverts commit 9140890d788cd43d5668d12072be6b965995a28a. --- .../JsonBinaryEncoding.FirstValueOffsets.cs | 4 +- .../src/Json/JsonBinaryEncoding.NodeTypes.cs | 4 +- .../Json/JsonBinaryEncoding.StringLengths.cs | 24 +- .../src/Json/JsonBinaryEncoding.Strings.cs | 29 ++- .../Json/JsonBinaryEncoding.SystemStrings.cs | 214 +----------------- .../Json/JsonBinaryEncoding.SystemStrings.tt | 32 --- .../src/Json/JsonBinaryEncoding.TypeMarker.cs | 33 ++- .../Json/JsonBinaryEncoding.ValueLengths.cs | 4 +- .../src/Json/JsonReader.JsonBinaryReader.cs | 4 +- .../src/Json/JsonWriter.JsonBinaryWriter.cs | 12 +- .../Json/JsonReaderTests.cs | 20 +- .../Json/JsonWriterTests.cs | 20 +- 12 files changed, 98 insertions(+), 302 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.FirstValueOffsets.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.FirstValueOffsets.cs index 609ede82ef..36070e533c 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.FirstValueOffsets.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.FirstValueOffsets.cs @@ -21,11 +21,13 @@ private static class FirstValueOffsets 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - // Encoded 1-byte system string (64 values) + // Encoded 1-byte system string (32 values) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + // Encoded 1-byte user string (32 values) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs index e0aa15c2c5..80885d9296 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.NodeTypes.cs @@ -36,11 +36,13 @@ public static class NodeTypes Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, Number, - // Encoded 1-byte system string (64 values) + // Encoded 1-byte system string (32 values) String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, + + // Encoded 1-byte user string (32 values) String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.StringLengths.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.StringLengths.cs index 09e85f3815..ac68cfe027 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.StringLengths.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.StringLengths.cs @@ -37,7 +37,7 @@ private static class StringLengths NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, NotStr, - // Encoded 1-byte system string (64 values) + // Encoded 1-byte system string (32 values) SystemStrings.Strings[0].Utf8String.Length, SystemStrings.Strings[1].Utf8String.Length, SystemStrings.Strings[2].Utf8String.Length, SystemStrings.Strings[3].Utf8String.Length, SystemStrings.Strings[4].Utf8String.Length, SystemStrings.Strings[5].Utf8String.Length, @@ -54,22 +54,12 @@ private static class StringLengths SystemStrings.Strings[26].Utf8String.Length, SystemStrings.Strings[27].Utf8String.Length, SystemStrings.Strings[28].Utf8String.Length, SystemStrings.Strings[29].Utf8String.Length, SystemStrings.Strings[30].Utf8String.Length, SystemStrings.Strings[31].Utf8String.Length, - SystemStrings.Strings[32].Utf8String.Length, SystemStrings.Strings[33].Utf8String.Length, - SystemStrings.Strings[34].Utf8String.Length, SystemStrings.Strings[35].Utf8String.Length, - SystemStrings.Strings[36].Utf8String.Length, SystemStrings.Strings[37].Utf8String.Length, - SystemStrings.Strings[38].Utf8String.Length, SystemStrings.Strings[39].Utf8String.Length, - SystemStrings.Strings[40].Utf8String.Length, SystemStrings.Strings[41].Utf8String.Length, - SystemStrings.Strings[42].Utf8String.Length, SystemStrings.Strings[43].Utf8String.Length, - SystemStrings.Strings[44].Utf8String.Length, SystemStrings.Strings[45].Utf8String.Length, - SystemStrings.Strings[46].Utf8String.Length, SystemStrings.Strings[47].Utf8String.Length, - SystemStrings.Strings[48].Utf8String.Length, SystemStrings.Strings[49].Utf8String.Length, - SystemStrings.Strings[50].Utf8String.Length, SystemStrings.Strings[51].Utf8String.Length, - SystemStrings.Strings[52].Utf8String.Length, SystemStrings.Strings[53].Utf8String.Length, - SystemStrings.Strings[54].Utf8String.Length, SystemStrings.Strings[55].Utf8String.Length, - SystemStrings.Strings[56].Utf8String.Length, SystemStrings.Strings[57].Utf8String.Length, - SystemStrings.Strings[58].Utf8String.Length, SystemStrings.Strings[59].Utf8String.Length, - SystemStrings.Strings[60].Utf8String.Length, SystemStrings.Strings[61].Utf8String.Length, - SystemStrings.Strings[62].Utf8String.Length, SystemStrings.Strings[63].Utf8String.Length, + + // Encoded 1-byte user string (32 values) + UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, + UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, + UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, + UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, UsrStr1, // Encoded 2-byte user string (8 values) UsrStr2, UsrStr2, UsrStr2, UsrStr2, UsrStr2, UsrStr2, UsrStr2, UsrStr2, diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Strings.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Strings.cs index 5c3bf992a1..d3c866fbf0 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Strings.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.Strings.cs @@ -38,11 +38,13 @@ internal static partial class JsonBinaryEncoding false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - // Encoded 0-byte system string (64 values) + // Encoded 0-byte system string (32 values) true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, + + // Encoded true-byte user string (32 values) true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, @@ -384,14 +386,29 @@ private static bool TryGetUserStringId(ReadOnlySpan stringToken, out int u return false; } - // JsonBinaryEncoding.TypeMarker.IsTwoByteEncodedUserString(typeMarker) must be true - if (stringToken.Length < 2) + if (JsonBinaryEncoding.TypeMarker.IsOneByteEncodedUserString(typeMarker)) { - userStringId = default; - return false; + if (stringToken.Length < 1) + { + userStringId = default; + return false; + } + + userStringId = typeMarker - JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin; } + else //// JsonBinaryEncoding.TypeMarker.IsTwoByteEncodedUserString(typeMarker) + { + if (stringToken.Length < 2) + { + userStringId = default; + return false; + } - userStringId = stringToken[1] + ((stringToken[0] - JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin) * 0xFF); + const byte OneByteCount = JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMax - JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin; + userStringId = OneByteCount + + stringToken[1] + + ((stringToken[0] - JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin) * 0xFF); + } return true; } diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.cs index 87f2a24062..e9edee7854 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.cs @@ -2,7 +2,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ------------------------------------------------------------ -// This is auto-generated code. Modify: JsonBinaryEncoding.SystemStrings.tt: 86 +// This is auto-generated code. Modify: JsonBinaryEncoding.SystemStrings.tt: 54 namespace Microsoft.Azure.Cosmos.Json { @@ -51,38 +51,6 @@ public static class SystemStrings UtfAllString.Create("Feature"), UtfAllString.Create("FeatureCollection"), UtfAllString.Create("_id"), - UtfAllString.Create("$id"), - UtfAllString.Create("$pk"), - UtfAllString.Create("_isEdge"), - UtfAllString.Create("_partitionKey"), - UtfAllString.Create("_type"), - UtfAllString.Create("_value"), - UtfAllString.Create("data"), - UtfAllString.Create("Data"), - UtfAllString.Create("entity"), - UtfAllString.Create("isDeleted"), - UtfAllString.Create("IsDeleted"), - UtfAllString.Create("key"), - UtfAllString.Create("Key"), - UtfAllString.Create("Location"), - UtfAllString.Create("partition"), - UtfAllString.Create("partition_id"), - UtfAllString.Create("partitionKey"), - UtfAllString.Create("PartitionKey"), - UtfAllString.Create("pk"), - UtfAllString.Create("state"), - UtfAllString.Create("State"), - UtfAllString.Create("status"), - UtfAllString.Create("Status"), - UtfAllString.Create("subscriptionId"), - UtfAllString.Create("SubscriptionId"), - UtfAllString.Create("tenantId"), - UtfAllString.Create("TenantId"), - UtfAllString.Create("timestamp"), - UtfAllString.Create("Timestamp"), - UtfAllString.Create("ttl"), - UtfAllString.Create("userId"), - UtfAllString.Create("UserId"), }.ToImmutableArray(); public static int? GetSystemStringId(Utf8Span buffer) @@ -93,15 +61,11 @@ public static class SystemStrings 3 => GetSystemStringIdLength3(buffer.Span), 4 => GetSystemStringIdLength4(buffer.Span), 5 => GetSystemStringIdLength5(buffer.Span), - 6 => GetSystemStringIdLength6(buffer.Span), 7 => GetSystemStringIdLength7(buffer.Span), 8 => GetSystemStringIdLength8(buffer.Span), - 9 => GetSystemStringIdLength9(buffer.Span), 10 => GetSystemStringIdLength10(buffer.Span), 11 => GetSystemStringIdLength11(buffer.Span), 12 => GetSystemStringIdLength12(buffer.Span), - 13 => GetSystemStringIdLength13(buffer.Span), - 14 => GetSystemStringIdLength14(buffer.Span), 15 => GetSystemStringIdLength15(buffer.Span), 17 => GetSystemStringIdLength17(buffer.Span), 18 => GetSystemStringIdLength18(buffer.Span), @@ -131,11 +95,6 @@ public static class SystemStrings return 12; } - if (buffer.SequenceEqual(Strings[50].Utf8String.Span.Span)) - { - return 50; - } - return null; } private static int? GetSystemStringIdLength3(ReadOnlySpan buffer) @@ -155,31 +114,6 @@ public static class SystemStrings return 31; } - if (buffer.SequenceEqual(Strings[32].Utf8String.Span.Span)) - { - return 32; - } - - if (buffer.SequenceEqual(Strings[33].Utf8String.Span.Span)) - { - return 33; - } - - if (buffer.SequenceEqual(Strings[43].Utf8String.Span.Span)) - { - return 43; - } - - if (buffer.SequenceEqual(Strings[44].Utf8String.Span.Span)) - { - return 44; - } - - if (buffer.SequenceEqual(Strings[61].Utf8String.Span.Span)) - { - return 61; - } - return null; } private static int? GetSystemStringIdLength4(ReadOnlySpan buffer) @@ -214,16 +148,6 @@ public static class SystemStrings return 27; } - if (buffer.SequenceEqual(Strings[38].Utf8String.Span.Span)) - { - return 38; - } - - if (buffer.SequenceEqual(Strings[39].Utf8String.Span.Span)) - { - return 39; - } - return null; } private static int? GetSystemStringIdLength5(ReadOnlySpan buffer) @@ -258,55 +182,6 @@ public static class SystemStrings return 28; } - if (buffer.SequenceEqual(Strings[36].Utf8String.Span.Span)) - { - return 36; - } - - if (buffer.SequenceEqual(Strings[51].Utf8String.Span.Span)) - { - return 51; - } - - if (buffer.SequenceEqual(Strings[52].Utf8String.Span.Span)) - { - return 52; - } - - return null; - } - private static int? GetSystemStringIdLength6(ReadOnlySpan buffer) - { - if (buffer.SequenceEqual(Strings[37].Utf8String.Span.Span)) - { - return 37; - } - - if (buffer.SequenceEqual(Strings[40].Utf8String.Span.Span)) - { - return 40; - } - - if (buffer.SequenceEqual(Strings[53].Utf8String.Span.Span)) - { - return 53; - } - - if (buffer.SequenceEqual(Strings[54].Utf8String.Span.Span)) - { - return 54; - } - - if (buffer.SequenceEqual(Strings[62].Utf8String.Span.Span)) - { - return 62; - } - - if (buffer.SequenceEqual(Strings[63].Utf8String.Span.Span)) - { - return 63; - } - return null; } private static int? GetSystemStringIdLength7(ReadOnlySpan buffer) @@ -321,11 +196,6 @@ public static class SystemStrings return 29; } - if (buffer.SequenceEqual(Strings[34].Utf8String.Span.Span)) - { - return 34; - } - return null; } private static int? GetSystemStringIdLength8(ReadOnlySpan buffer) @@ -335,50 +205,6 @@ public static class SystemStrings return 10; } - if (buffer.SequenceEqual(Strings[45].Utf8String.Span.Span)) - { - return 45; - } - - if (buffer.SequenceEqual(Strings[57].Utf8String.Span.Span)) - { - return 57; - } - - if (buffer.SequenceEqual(Strings[58].Utf8String.Span.Span)) - { - return 58; - } - - return null; - } - private static int? GetSystemStringIdLength9(ReadOnlySpan buffer) - { - if (buffer.SequenceEqual(Strings[41].Utf8String.Span.Span)) - { - return 41; - } - - if (buffer.SequenceEqual(Strings[42].Utf8String.Span.Span)) - { - return 42; - } - - if (buffer.SequenceEqual(Strings[46].Utf8String.Span.Span)) - { - return 46; - } - - if (buffer.SequenceEqual(Strings[59].Utf8String.Span.Span)) - { - return 59; - } - - if (buffer.SequenceEqual(Strings[60].Utf8String.Span.Span)) - { - return 60; - } - return null; } private static int? GetSystemStringIdLength10(ReadOnlySpan buffer) @@ -426,44 +252,6 @@ public static class SystemStrings return 20; } - if (buffer.SequenceEqual(Strings[47].Utf8String.Span.Span)) - { - return 47; - } - - if (buffer.SequenceEqual(Strings[48].Utf8String.Span.Span)) - { - return 48; - } - - if (buffer.SequenceEqual(Strings[49].Utf8String.Span.Span)) - { - return 49; - } - - return null; - } - private static int? GetSystemStringIdLength13(ReadOnlySpan buffer) - { - if (buffer.SequenceEqual(Strings[35].Utf8String.Span.Span)) - { - return 35; - } - - return null; - } - private static int? GetSystemStringIdLength14(ReadOnlySpan buffer) - { - if (buffer.SequenceEqual(Strings[55].Utf8String.Span.Span)) - { - return 55; - } - - if (buffer.SequenceEqual(Strings[56].Utf8String.Span.Span)) - { - return 56; - } - return null; } private static int? GetSystemStringIdLength15(ReadOnlySpan buffer) diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.tt b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.tt index c369e3e489..fd06958ed0 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.tt +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.SystemStrings.tt @@ -43,38 +43,6 @@ string[] systemStrings = new string[] "Feature", "FeatureCollection", "_id", - "$id", - "$pk", - "_isEdge", - "_partitionKey", - "_type", - "_value", - "data", - "Data", - "entity", - "isDeleted", - "IsDeleted", - "key", - "Key", - "Location", - "partition", - "partition_id", - "partitionKey", - "PartitionKey", - "pk", - "state", - "State", - "status", - "Status", - "subscriptionId", - "SubscriptionId", - "tenantId", - "TenantId", - "timestamp", - "Timestamp", - "ttl", - "userId", - "UserId", }; int[] distinctStringLengths = systemStrings.Select(x => x.Length).Distinct().OrderBy(x => x).ToArray(); diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs index 5c17074451..8fab1e22fb 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.TypeMarker.cs @@ -27,7 +27,7 @@ public readonly struct TypeMarker public const byte LiteralIntMax = LiteralIntMin + 32; #endregion - #region [0x20, 0x60): Encoded 1-byte system string (64 values) + #region [0x20, 0x40): Encoded 1-byte system string (32 values) /// /// The first type marker for a system string whose value can be encoded in a 1 byte type marker. /// @@ -36,14 +36,26 @@ public readonly struct TypeMarker /// /// The last type marker for a system string whose value can be encoded in a 1 byte type marker. /// - public const byte SystemString1ByteLengthMax = SystemString1ByteLengthMin + 64; + public const byte SystemString1ByteLengthMax = SystemString1ByteLengthMin + 32; + #endregion + + #region [0x40, 0x60): Encoded 1-byte user string (32 values) + /// + /// The first type marker for a user string whose value can be encoded in a 1 byte type marker. + /// + public const byte UserString1ByteLengthMin = SystemString1ByteLengthMax; + + /// + /// The last type marker for a user string whose value can be encoded in a 1 byte type marker. + /// + public const byte UserString1ByteLengthMax = UserString1ByteLengthMin + 32; #endregion #region [0x60, 0x68): 2-byte user string (8 values) /// /// The first type marker for a system string whose value can be encoded in a 2 byte type marker. /// - public const byte UserString2ByteLengthMin = SystemString1ByteLengthMax; + public const byte UserString2ByteLengthMin = UserString1ByteLengthMax; /// /// The last type marker for a system string whose value can be encoded in a 2 byte type marker. @@ -455,6 +467,17 @@ public static bool IsSystemString(byte typeMarker) return InRange(typeMarker, SystemString1ByteLengthMin, SystemString1ByteLengthMax); } + /// + /// Gets whether a typeMarker is for a one byte encoded user string. + /// + /// The input type marker. + /// Whether the typeMarker is for a one byte encoded user string. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsOneByteEncodedUserString(byte typeMarker) + { + return InRange(typeMarker, UserString1ByteLengthMin, UserString1ByteLengthMax); + } + /// /// Gets whether a typeMarker is for a two byte encoded user string. /// @@ -474,7 +497,7 @@ public static bool IsTwoByteEncodedUserString(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsUserString(byte typeMarker) { - return IsTwoByteEncodedUserString(typeMarker); + return IsOneByteEncodedUserString(typeMarker) || IsTwoByteEncodedUserString(typeMarker); } /// @@ -485,7 +508,7 @@ public static bool IsUserString(byte typeMarker) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsOneByteEncodedString(byte typeMarker) { - return InRange(typeMarker, SystemString1ByteLengthMin, SystemString1ByteLengthMax); + return InRange(typeMarker, SystemString1ByteLengthMin, UserString1ByteLengthMax); } /// diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs index c8b8daac7d..29427c9dbd 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonBinaryEncoding.ValueLengths.cs @@ -43,11 +43,13 @@ private static class ValueLengths 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - // Encoded 1-byte system string (64 values) + // Encoded 1-byte system string (32 values) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + // Encoded 1-byte user string (32 values) 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs b/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs index 1c64b1999a..02b11a9cc1 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonReader.JsonBinaryReader.cs @@ -26,11 +26,13 @@ abstract partial class JsonReader : IJsonReader JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, JsonTokenType.Number, - // Encoded 1-byte system string (64 values) + // Encoded 1-byte system string (32 values) JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, + + // Encoded 1-byte user string (32 values) JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, JsonTokenType.String, diff --git a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs index 0df6582cf6..6b20d99f59 100644 --- a/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Json/JsonWriter.JsonBinaryWriter.cs @@ -81,16 +81,18 @@ private enum RawValueType : byte RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, - // Encoded 1-byte system string (64 values) - RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, - RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, - RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, - RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, + // Encoded 1-byte system string (32 values) RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, RawValueType.Token, + // Encoded 1-byte user string (32 values) + RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, + RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, + RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, + RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, + // Encoded 2-byte user string (8 values) RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, RawValueType.StrUsr, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs index 52571f33e9..2f31613d08 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonReaderTests.cs @@ -2281,9 +2281,9 @@ public void SimpleObjectTest() List elements = new List { - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 0 }, + new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin }, new byte[] { JsonBinaryEncoding.TypeMarker.LiteralIntMin + 10 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 1 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 1) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "example glossary".Length), 101, 120, 97, 109, 112, 108, 101, 32, 103, 108, 111, 115, 115, 97, 114, 121 } }; byte[] elementsBytes = elements.SelectMany(x => x).ToArray(); @@ -2405,25 +2405,25 @@ public void AllPrimitivesObjectTest() new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin + 12) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "7029d079-4016-4436-b7da-36c0bae54ff6".Length), 55, 48, 50, 57, 100, 48, 55, 57, 45, 52, 48, 49, 54, 45, 52, 52, 51, 54, 45, 98, 55, 100, 97, 45, 51, 54, 99, 48, 98, 97, 101, 53, 52, 102, 102, 54 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 0 }, + new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin }, new byte[] { JsonBinaryEncoding.TypeMarker.NumberDouble, 0x98, 0x8B, 0x30, 0xE3, 0xCB, 0x45, 0xC8, 0x3F }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 1 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 1) }, new byte[] { JsonBinaryEncoding.TypeMarker.NumberInt32, 0x19, 0xDF, 0xB6, 0xB0 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 2 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 2) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "XCPCFXPHHF".Length), 88, 67, 80, 67, 70, 88, 80, 72, 72, 70 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 3 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 3) }, new byte[] { JsonBinaryEncoding.TypeMarker.True }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 4 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 4) }, new byte[] { JsonBinaryEncoding.TypeMarker.Null }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 5 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 5) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "2526-07-11T18:18:16.4520716".Length), 50, 53, 50, 54, 45, 48, 55, 45, 49, 49, 84, 49, 56, 58, 49, 56, 58, 49, 54, 46, 52, 53, 50, 48, 55, 49, 54 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 6 } + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 6) } }; List innerObjectElements = new List @@ -2447,7 +2447,7 @@ public void AllPrimitivesObjectTest() elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); - elements.Add(new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 7 }); + elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 7) }); elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.String1ByteLength, (byte)"tiger diamond newbrunswick snowleopard chocolate dog snowleopard turtle cat sapphire peach sapphire vancouver white chocolate horse diamond lion superlongcolourname ruby".Length, 116, 105, 103, 101, 114, 32, 100, 105, 97, 109, 111, 110, 100, 32, 110, 101, 119, 98, 114, 117, 110, 115, 119, 105, 99, 107, 32, 115, 110, 111, 119, 108, 101, 111, 112, 97, 114, 100, 32, 99, 104, 111, 99, 111, 108, 97, 116, 101, 32, 100, 111, 103, 32, 115, 110, 111, 119, 108, 101, 111, 112, 97, 114, 100, 32, 116, 117, 114, 116, 108, 101, 32, 99, 97, 116, 32, 115, 97, 112, 112, 104, 105, 114, 101, 32, 112, 101, 97, 99, 104, 32, 115, 97, 112, 112, 104, 105, 114, 101, 32, 118, 97, 110, 99, 111, 117, 118, 101, 114, 32, 119, 104, 105, 116, 101, 32, 99, 104, 111, 99, 111, 108, 97, 116, 101, 32, 104, 111, 114, 115, 101, 32, 100, 105, 97, 109, 111, 110, 100, 32, 108, 105, 111, 110, 32, 115, 117, 112, 101, 114, 108, 111, 110, 103, 99, 111, 108, 111, 117, 114, 110, 97, 109, 101, 32, 114, 117, 98, 121 }); byte[] elementsBytes = elements.SelectMany(x => x).ToArray(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs index b44cb49b1f..0997b4dfd2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Json/JsonWriterTests.cs @@ -2353,9 +2353,9 @@ public void SimpleObjectTest() List elements = new List { - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 0 }, + new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin }, new byte[] { JsonBinaryEncoding.TypeMarker.LiteralIntMin + 10 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 1 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 1) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "example glossary".Length), 101, 120, 97, 109, 112, 108, 101, 32, 103, 108, 111, 115, 115, 97, 114, 121 } }; byte[] elementsBytes = elements.SelectMany(x => x).ToArray(); @@ -2484,25 +2484,25 @@ public void AllPrimitivesObjectTest() new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.SystemString1ByteLengthMin + 12) }, new byte[] { JsonBinaryEncoding.TypeMarker.LowercaseGuidString, 0x07, 0x92, 0x0D, 0x97, 0x04, 0x61, 0x44, 0x63, 0x7B, 0xAD, 0x63, 0x0C, 0xAB, 0x5E, 0xF4, 0x6F }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 0 }, + new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin }, new byte[] { JsonBinaryEncoding.TypeMarker.NumberDouble, 0x98, 0x8B, 0x30, 0xE3, 0xCB, 0x45, 0xC8, 0x3F }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 1 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 1) }, new byte[] { JsonBinaryEncoding.TypeMarker.NumberInt32, 0x19, 0xDF, 0xB6, 0xB0 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 2 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 2) }, new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.EncodedStringLengthMin + "XCPCFXPHHF".Length), 88, 67, 80, 67, 70, 88, 80, 72, 72, 70 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 3 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 3) }, new byte[] { JsonBinaryEncoding.TypeMarker.True }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 4 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 4) }, new byte[] { JsonBinaryEncoding.TypeMarker.Null }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 5 }, + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 5) }, new byte[] { JsonBinaryEncoding.TypeMarker.CompressedDateTimeString, 0x1B, 0x63, 0x73, 0x1C, 0xC8, 0x22, 0x2E, 0xB9, 0x92, 0x2B, 0xD7, 0x65, 0x13, 0x28, 0x07 }, - new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 6 } + new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 6) } }; List innerObjectElements = new List @@ -2526,7 +2526,7 @@ public void AllPrimitivesObjectTest() elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Object1ByteLength, (byte)innerObjectElementsBytes.Length }); elements.Add(innerObjectElementsBytes); - elements.Add(new byte[] { (byte)JsonBinaryEncoding.TypeMarker.UserString2ByteLengthMin, 7 }); + elements.Add(new byte[] { (byte)(JsonBinaryEncoding.TypeMarker.UserString1ByteLengthMin + 7) }); elements.Add(new byte[] { JsonBinaryEncoding.TypeMarker.Packed7BitStringLength1, (byte)"tiger diamond newbrunswick snowleopard chocolate dog snowleopard turtle cat sapphire peach sapphire vancouver white chocolate horse diamond lion superlongcolourname ruby".Length, 0xF4, 0xF4, 0xB9, 0x2C, 0x07, 0x91, 0xD3, 0xE1, 0xF6, 0xDB, 0x4D, 0x06, 0xB9, 0xCB, 0x77, 0xB1, 0xBC, 0xEE, 0x9E, 0xDF, 0xD3, 0xE3, 0x35, 0x68, 0xEE, 0x7E, 0xDF, 0xD9, 0xE5, 0x37, 0x3C, 0x2C, 0x27, 0x83, 0xC6, 0xE8, 0xF7, 0xF8, 0xCD, 0x0E, 0xD3, 0xCB, 0x20, 0xF2, 0xFB, 0x0C, 0x9A, 0xBB, 0xDF, 0x77, 0x76, 0xF9, 0x0D, 0x0F, 0xCB, 0xC9, 0x20, 0x7A, 0x5D, 0x4E, 0x67, 0x97, 0x41, 0xE3, 0x30, 0x1D, 0x34, 0x0F, 0xC3, 0xE1, 0xE8, 0xB4, 0xBC, 0x0C, 0x82, 0x97, 0xC3, 0x63, 0x34, 0x68, 0x1E, 0x86, 0xC3, 0xD1, 0x69, 0x79, 0x19, 0x64, 0x0F, 0xBB, 0xC7, 0xEF, 0xBA, 0xBD, 0x2C, 0x07, 0xDD, 0xD1, 0x69, 0x7A, 0x19, 0x34, 0x46, 0xBF, 0xC7, 0x6F, 0x76, 0x98, 0x5E, 0x06, 0xA1, 0xDF, 0xF2, 0x79, 0x19, 0x44, 0x4E, 0x87, 0xDB, 0x6F, 0x37, 0x19, 0xC4, 0x4E, 0xBF, 0xDD, 0xA0, 0x79, 0x1D, 0x5E, 0x96, 0xB3, 0xDF, 0xEE, 0xF3, 0xF8, 0xCD, 0x7E, 0xD7, 0xE5, 0xEE, 0x70, 0xBB, 0x0C, 0x92, 0xD7, 0xC5, 0x79 }); byte[] elementsBytes = elements.SelectMany(x => x).ToArray(); From e2fb347a4a72801fc6c0fcbcd0fc6fa06f48c3db Mon Sep 17 00:00:00 2001 From: iain Date: Tue, 10 Oct 2023 16:59:39 +0100 Subject: [PATCH 207/337] CosmosClientOptions: Adds support for multiple formats of Azure region names (#4016) * Allow ComosClientOptions to take ApplicationRegion and ApplicationPreferredRegions in multiple region name formats. This is a proposed fix for - https://github.com/Azure/azure-cosmos-dotnet-v3/issues/2330 * Address PR comment to avoid duplicating list of names. * Remove the map table cache The map table is only used on initialization, so there's no need to keep a cache of it for the lifetime of the application * Only convert the region names when the client is initializing The cache is created before converting all the names, so it only needs created once, but doesn't remain for the entire lifetime of the application * Update tests * Make RegionNameMapper an instantiable class Instead of having a prepare/clear cache system on a static class, make RegionNameMapper a class that gets instantiated for use and let the ctor handle it. * Remove debugging * Update tests to actually test things --------- Co-authored-by: Pradeep Chellappan Co-authored-by: Pradeep Chellappan <94089783+pradeep-chellappan@users.noreply.github.com> Co-authored-by: Matias Quaranta Co-authored-by: Kiran Kumar Kolli --- .../src/CosmosClientOptions.cs | 19 +- .../src/RegionNameMapper.cs | 53 ++++++ .../CosmosClientOptionsUnitTests.cs | 167 +++++++++++++++++- 3 files changed, 230 insertions(+), 9 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/RegionNameMapper.cs diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index b3b21e4f3b..aac863f0e7 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -785,14 +785,17 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) connectionPolicy.CosmosClientTelemetryOptions = this.CosmosClientTelemetryOptions; } - if (this.ApplicationRegion != null) - { - connectionPolicy.SetCurrentLocation(this.ApplicationRegion); - } - - if (this.ApplicationPreferredRegions != null) - { - connectionPolicy.SetPreferredLocations(this.ApplicationPreferredRegions); + RegionNameMapper mapper = new RegionNameMapper(); + if (!string.IsNullOrEmpty(this.ApplicationRegion)) + { + connectionPolicy.SetCurrentLocation(mapper.GetCosmosDBRegionName(this.ApplicationRegion)); + } + + if (this.ApplicationPreferredRegions != null) + { + List mappedRegions = this.ApplicationPreferredRegions.Select(s => mapper.GetCosmosDBRegionName(s)).ToList(); + + connectionPolicy.SetPreferredLocations(mappedRegions); } if (this.MaxRetryAttemptsOnRateLimitedRequests != null) diff --git a/Microsoft.Azure.Cosmos/src/RegionNameMapper.cs b/Microsoft.Azure.Cosmos/src/RegionNameMapper.cs new file mode 100644 index 0000000000..dbcf0d7c08 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/RegionNameMapper.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Collections.Generic; + using System.Reflection; + + /// + /// Maps a normalized region name to the format that CosmosDB is expecting (for e.g. from 'westus2' to 'West US 2') + /// + internal sealed class RegionNameMapper + { + private readonly Dictionary normalizedToCosmosDBRegionNameMapping; + + public RegionNameMapper() + { + FieldInfo[] fields = typeof(Regions).GetFields(BindingFlags.Public | BindingFlags.Static); + + this.normalizedToCosmosDBRegionNameMapping = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (FieldInfo field in fields) + { + this.normalizedToCosmosDBRegionNameMapping[field.Name] = field.GetValue(null).ToString(); + } + } + + /// + /// Given a normalized region name, this function retrieves the region name in the format that CosmosDB expects. + /// If the region is not known, the same value as input is returned. + /// + /// An Azure region name in a normalized format. The input is not case sensitive. + /// A string that contains the region name in the format that CosmosDB expects. + public string GetCosmosDBRegionName(string normalizedRegionName) + { + if (string.IsNullOrEmpty(normalizedRegionName)) + { + return string.Empty; + } + + normalizedRegionName = normalizedRegionName.Replace(" ", string.Empty); + if (this.normalizedToCosmosDBRegionNameMapping.TryGetValue(normalizedRegionName, + out string cosmosDBRegionName)) + { + return cosmosDBRegionName; + } + + return normalizedRegionName; + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index f3c45adf48..04d51ea06c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -6,7 +6,8 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; using System.Collections; - using System.Collections.Generic; + using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Linq; using System.Net; using System.Net.Http; @@ -556,6 +557,170 @@ public void WithQuorumReadWithEventualConsistencyAccount() Assert.IsTrue(cosmosClientOptions.EnableUpgradeConsistencyToLocalQuorum); } + [TestMethod] + public void VerifyRegionNameFormatConversionForApplicationRegion() + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions(); + cosmosClientOptions.ApplicationRegion = "westus2"; + + ConnectionPolicy policy = cosmosClientOptions.GetConnectionPolicy(0); + + // Need to see Regions.WestUS2 in the list, but not "westus2" + bool seenWestUS2 = false; + bool seenNormalized = false; + + foreach (string region in policy.PreferredLocations) + { + if (region == "westus2") + { + seenNormalized = true; + } + + if (region == Regions.WestUS2) + { + seenWestUS2 = true; + } + } + Assert.IsTrue(seenWestUS2); + Assert.IsFalse(seenNormalized); + } + + [TestMethod] + public void VerifyRegionNameFormatConversionBypassForApplicationRegion() + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions(); + + // No conversion for expected format. + cosmosClientOptions.ApplicationRegion = Regions.NorthCentralUS; + + ConnectionPolicy policy = cosmosClientOptions.GetConnectionPolicy(0); + + Assert.AreEqual(Regions.NorthCentralUS, policy.PreferredLocations[0]); + + // Ignore unknown values. + cosmosClientOptions.ApplicationRegion = null; + + policy = cosmosClientOptions.GetConnectionPolicy(0); + + Assert.AreEqual(0, policy.PreferredLocations.Count); + + cosmosClientOptions.ApplicationRegion = string.Empty; + policy = cosmosClientOptions.GetConnectionPolicy(0); + + Assert.AreEqual(0, policy.PreferredLocations.Count); + + cosmosClientOptions.ApplicationRegion = "Invalid region"; + Assert.ThrowsException(() => cosmosClientOptions.GetConnectionPolicy(0)); + } + + [TestMethod] + public void VerifyRegionNameFormatConversionForApplicationPreferredRegions() + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions(); + cosmosClientOptions.ApplicationPreferredRegions = new List {"westus2", "usdodcentral", Regions.ChinaNorth3}; + + ConnectionPolicy policy = cosmosClientOptions.GetConnectionPolicy(0); + + bool seenUSDodCentral = false; + bool seenWestUS2 = false; + bool seenChinaNorth3 = false; + bool seenNormalizedUSDodCentral = false; + bool seenNormalizedWestUS2 = false; + + foreach (string region in policy.PreferredLocations) + { + if (region == Regions.USDoDCentral) + { + seenUSDodCentral = true; + } + + if (region == Regions.WestUS2) + { + seenWestUS2 = true; + } + + if (region == Regions.ChinaNorth3) + { + seenChinaNorth3 = true; + } + + if (region == "westus2") + { + seenNormalizedWestUS2 = true; + } + + if (region == "usdodcentral") + { + seenNormalizedUSDodCentral = true; + } + } + + Assert.IsTrue(seenChinaNorth3); + Assert.IsTrue(seenWestUS2); + Assert.IsTrue(seenUSDodCentral); + Assert.IsFalse(seenNormalizedUSDodCentral); + Assert.IsFalse(seenNormalizedWestUS2); + } + + [TestMethod] + public void VerifyRegionNameFormatConversionBypassForInvalidApplicationPreferredRegions() + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions(); + + // List contains valid and invalid values + cosmosClientOptions.ApplicationPreferredRegions = new List + { + null, + string.Empty, + Regions.JioIndiaCentral, + "westus2", + "Invalid region" + }; + + ConnectionPolicy policy = cosmosClientOptions.GetConnectionPolicy(0); + + bool seenJioIndiaCentral = false; + bool seenWestUS2 = false; + bool seenNormalized = false; + + foreach (string region in policy.PreferredLocations) + { + if (region == Regions.JioIndiaCentral) + { + seenJioIndiaCentral = true; + } + + if (region == Regions.WestUS2) + { + seenWestUS2 = true; + } + + if (region == "westus2") + { + seenNormalized = true; + } + } + + Assert.IsTrue(seenJioIndiaCentral); + Assert.IsTrue(seenWestUS2); + Assert.IsFalse(seenNormalized); + } + + [TestMethod] + public void RegionNameMappingTest() + { + RegionNameMapper mapper = new RegionNameMapper(); + + // Test normalized name + Assert.AreEqual(Regions.WestUS2, mapper.GetCosmosDBRegionName("westus2")); + + // Test with spaces + Assert.AreEqual(Regions.WestUS2, mapper.GetCosmosDBRegionName("west us 2")); + + // Test for case insenstive + Assert.AreEqual(Regions.WestUS2, mapper.GetCosmosDBRegionName("wEsTuS2")); + } + [TestMethod] public void InvalidApplicationNameCatchTest() { From 4e2beda5efddcc52c0b433bcc2cce788d9b5ca27 Mon Sep 17 00:00:00 2001 From: Arooshi Avasthy <113193425+aavasthy@users.noreply.github.com> Date: Tue, 10 Oct 2023 15:19:07 -0700 Subject: [PATCH 208/337] Distributed Tracing: Fixes traceid null exception issue (#4111) * Fix traceid null exception issue * Fixing merge conflicts * Fixing merge conflicts * Update script * Code cleanup * Updated change description * updated comment description * updated comment description --------- Co-authored-by: Matias Quaranta --- .../OpenTelemetryRecorderFactory.cs | 24 +++++- .../DistributedTracingOTelTests.cs | 73 +++++++++++++++---- .../Tracing/AssertActivity.cs | 4 +- .../Tracing/CustomListener.cs | 29 ++++++-- .../Tracing/CustomOtelExporter.cs | 3 +- 5 files changed, 106 insertions(+), 27 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 61d8889aaa..b8babd37da 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -48,7 +48,9 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, DiagnosticScope scope = LazyOperationScopeFactory.Value.CreateScope(name: operationName, kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); - // Record values only when we have a valid Diagnostic Scope + // Need a parent activity id associated with the operation which is logged in diagnostics and used for tracing purpose. + // If there are listeners at operation level then scope is enabled and it tries to create activity. + // However, if available listeners are not subscribed to operation level event then it will lead to scope being enabled but no activity is created. if (scope.IsEnabled) { scope.SetDisplayName($"{operationName} {containerName}"); @@ -63,14 +65,28 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); } #if !INTERNAL - else if (Activity.Current is null) + // Need a parent activity which groups all network activities under it and is logged in diagnostics and used for tracing purpose. + // If there are listeners at network level then scope is enabled and it tries to create activity. + // However, if available listeners are not subscribed to network event then it will lead to scope being enabled but no activity is created. + else { DiagnosticScope requestScope = LazyNetworkScopeFactory.Value.CreateScope(name: operationName); + openTelemetryRecorder = requestScope.IsEnabled ? OpenTelemetryCoreRecorder.CreateNetworkLevelParentActivity(networkScope: requestScope) : openTelemetryRecorder; + } - openTelemetryRecorder = requestScope.IsEnabled ? OpenTelemetryCoreRecorder.CreateNetworkLevelParentActivity(networkScope: requestScope) : OpenTelemetryCoreRecorder.CreateParentActivity(operationName); + // If there are no listeners at operation level and network level and no parent activity created. + // Then create a dummy activity as there should be a parent level activity always to send a traceid to the backend services through context propagation. + // The parent activity id is logged in diagnostics and used for tracing purpose. + if (Activity.Current is null) + { + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateParentActivity(operationName); } #endif - trace.AddDatum("DistributedTraceId", Activity.Current?.TraceId); + // Safety check as diagnostic logs should not break the code. + if (Activity.Current?.TraceId != null) + { + trace.AddDatum("DistributedTraceId", Activity.Current.TraceId); + } } return openTelemetryRecorder; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs index 53b0eb6e24..43d9be341d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs @@ -19,6 +19,7 @@ namespace Microsoft.Azure.Cosmos using System.Diagnostics; using Microsoft.Azure.Cosmos.Tracing; using System.Net.Http; + using Microsoft.Azure.Cosmos.Tests; [VisualStudio.TestTools.UnitTesting.TestClass] public sealed class DistributedTracingOTelTests : BaseCosmosClientHelper @@ -33,7 +34,8 @@ public void TestInitialize() [DataTestMethod] [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] - public async Task SourceEnabled_FlagOn_DirectMode_RecordsActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) + [DataRow(null, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at network level with Diagnostic TraceId being added to logs")] + public async Task SourceEnabled_FlagOn_DirectMode_RecordsOperationNetworkActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) { string[] sources = new string[] { operationLevelSource, networkLevelSource }; sources = sources.Where(x => x != null).ToArray(); @@ -43,12 +45,12 @@ public async Task SourceEnabled_FlagOn_DirectMode_RecordsActivity_AssertLogTrace .AddSource(sources) .Build(); - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { + { DisableDistributedTracing = false - }) + }) .WithConnectionModeDirect()); Container containerResponse = await this.database.CreateContainerAsync( @@ -106,7 +108,8 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, [DataTestMethod] [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] - public async Task SourceEnabled_FlagOn_GatewayMode_RecordsActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) + [DataRow(null, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at network level with Diagnostic TraceId being added to logs")] + public async Task SourceEnabled_FlagOn_GatewayMode_RecordsOperationNetworkActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) { string[] sources = new string[] { operationLevelSource, networkLevelSource }; sources = sources.Where(x => x != null).ToArray(); @@ -128,12 +131,12 @@ public async Task SourceEnabled_FlagOn_GatewayMode_RecordsActivity_AssertLogTrac .AddSource(sources) .Build(); - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { + { DisableDistributedTracing = false - }) + }) .WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper)) .WithConnectionModeGateway()); @@ -142,7 +145,6 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, partitionKeyPath: "/id", throughput: 20000); - List b = CustomOtelExporter.CollectedActivities.ToList(); //Assert traceId in Diagnostics logs string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); @@ -169,7 +171,7 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, [DataRow(true, true, "random.source.name", DisplayName = "GatewayMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] [DataRow(false, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "DirectMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] [DataRow(true, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "GatewayMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] - public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_AssertLogTraceId(bool useGateway, bool disableDistributingTracing, string source) + public async Task NoSourceNoFlagEnabled_ResultsInNoOperationNetworkActivityCreation_AssertLogTraceId(bool useGateway, bool disableDistributingTracing, string source) { using TracerProvider provider = Sdk.CreateTracerProviderBuilder() .AddCustomOtelExporter() @@ -178,20 +180,20 @@ public async Task NoSourceEnabled_ResultsInNoSourceParentActivityCreation_Assert if (useGateway) { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { + { DisableDistributedTracing = disableDistributingTracing }) .WithConnectionModeGateway()); } else { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, customizeClientBuilder: (builder) => builder .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { + { DisableDistributedTracing = disableDistributingTracing })); } @@ -221,6 +223,49 @@ await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, Assert.AreEqual(0, CustomOtelExporter.CollectedActivities.Count()); } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public async Task SuppressListenerEvents_ResultsInNoScopeActivityCreation_AssertTraceIdNotNull(bool useGateway) + { + // Initialize CustomListener with suppression + CustomListener customListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics", true); + + if (useGateway) + { + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + }) + .WithConnectionModeGateway()); + } + else + { + await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, + customizeClientBuilder: (builder) => builder + .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + })); + } + + ContainerResponse containerResponse = await this.database.CreateContainerAsync( + id: Guid.NewGuid().ToString(), + partitionKeyPath: "/id", + throughput: 20000); + + // Assert traceId in Diagnostics logs + string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); + JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); + Assert.IsNotNull(objDiagnosticsCreate["data"]["DistributedTraceId"], "Distributed Trace Id has value in diagnostics i.e. " + (string)objDiagnosticsCreate["data"]["DistributedTraceId"]); + + // Cleanup + customListener.Dispose(); + } + [TestCleanup] public async Task CleanUp() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index 9b9be4479a..2bcd002b79 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -83,7 +83,9 @@ public static void AreEqualAcrossListeners() { Assert.AreEqual( JsonConvert.SerializeObject(CustomListener.CollectedOperationActivities.OrderBy(x => x.Id)), - JsonConvert.SerializeObject(CustomOtelExporter.CollectedActivities.OrderBy(x => x.Id))); + JsonConvert.SerializeObject(CustomOtelExporter.CollectedActivities + .Where(activity => activity.Source.Name == $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") + .OrderBy(x => x.Id))); } private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index cae05fa94d..6d612c29c7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -26,7 +26,8 @@ internal class CustomListener : { private readonly Func sourceNameFilter; private readonly string eventName; - + private readonly bool suppressAllEvents; + private ConcurrentBag subscriptions = new(); private ConcurrentBag Scopes { get; } = new(); @@ -36,21 +37,22 @@ internal class CustomListener : private static List EventSources { set; get; } = new(); - public CustomListener(string name, string eventName) - : this(n => Regex.Match(n, name).Success, eventName) + public CustomListener(string name, string eventName, bool suppressAllEvents = false) + : this(n => Regex.Match(n, name).Success, eventName, suppressAllEvents) { } - public CustomListener(Func filter, string eventName) + public CustomListener(Func filter, string eventName, bool suppressAllEvents = false) { this.sourceNameFilter = filter; this.eventName = eventName; + this.suppressAllEvents = suppressAllEvents; foreach (EventSource eventSource in EventSources) { this.OnEventSourceCreated(eventSource); } - + DiagnosticListener.AllListeners.Subscribe(this); } @@ -149,7 +151,15 @@ public void OnNext(DiagnosticListener value) { lock (this.Scopes) { - this.subscriptions?.Add(value.Subscribe(this)); + IDisposable subscriber = value.Subscribe(this, isEnabled: (name) => + { + if (this.suppressAllEvents) + { + return false; + } + return true; + }); + this.subscriptions?.Add(subscriber); } } } @@ -159,7 +169,12 @@ public void OnNext(DiagnosticListener value) /// protected override void OnEventSourceCreated(EventSource eventSource) { - if(this.eventName == null) + if (this.eventName == null) + { + EventSources.Add(eventSource); + } + + if (this.eventName == null) { EventSources.Add(eventSource); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs index eb46d83e48..a115a64084 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -35,7 +35,8 @@ public override ExportResult Export(in Batch batch) foreach (Activity activity in batch) { - if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase) + || string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", StringComparison.OrdinalIgnoreCase)) { AssertActivity.IsValidOperationActivity(activity); From 7db0aa08a7480da450e8839fd817298250586232 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 12 Oct 2023 21:15:42 +0530 Subject: [PATCH 209/337] Telemetry Options: Adds telemetry options in GA package (#4117) * GA telemetry options and updated contract * enabe requuest level option * added request option in public contract --- .../src/CosmosClientOptions.cs | 7 +- .../src/CosmosClientTelemetryOptions.cs | 28 +-- .../src/CosmosThresholdOptions.cs | 7 +- .../src/Fluent/CosmosClientBuilder.cs | 7 +- .../src/RequestOptions/RequestOptions.cs | 5 +- .../Contracts/DotNetPreviewSDKAPI.json | 153 ----------------- .../Contracts/DotNetSDKAPI.json | 160 ++++++++++++++++++ 7 files changed, 170 insertions(+), 197 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index aac863f0e7..60ae9298b0 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -732,12 +732,7 @@ internal Protocol ConnectionProtocol /// /// Gets or sets Client Telemetry Options like feature flags and corresponding options /// -#if PREVIEW - public -#else - internal -#endif - CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } internal void SetSerializerIfNotConfigured(CosmosSerializer serializer) { diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs index 8b2a2aa6a0..ec16c0f3b8 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs @@ -7,36 +7,21 @@ namespace Microsoft.Azure.Cosmos /// /// Telemetry Options for Cosmos Client to enable/disable telemetry and distributed tracing along with corresponding threshold values. /// -#if PREVIEW - public -#else - internal -#endif - class CosmosClientTelemetryOptions + public class CosmosClientTelemetryOptions { /// /// Disable sending telemetry to service, is not applicable to this as of now. /// /// This option will disable sending telemetry to service.even it is opt-in from portal. /// true -#if PREVIEW - public -#else - internal -#endif - bool DisableSendingMetricsToService { get; set; } = true; + public bool DisableSendingMetricsToService { get; set; } = true; /// /// This method enable/disable generation of operation level if listener is subscribed to the Source Name "Azure.Cosmos.Operation". /// /// false /// Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters -#if PREVIEW - public -#else - internal -#endif - bool DisableDistributedTracing { get; set; } = + public bool DisableDistributedTracing { get; set; } = #if PREVIEW false; #else @@ -47,12 +32,7 @@ class CosmosClientTelemetryOptions /// Threshold values for Distributed Tracing. /// These values decides whether to generate operation level with request diagnostics or not. /// -#if PREVIEW - public -#else - internal -#endif - CosmosThresholdOptions CosmosThresholdOptions { get; set; } = new CosmosThresholdOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } = new CosmosThresholdOptions(); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs index 5a04286f68..57b7cbf57a 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs @@ -9,12 +9,7 @@ namespace Microsoft.Azure.Cosmos /// /// Threshold values for Distributed Tracing /// -#if PREVIEW - public -#else - internal -#endif - class CosmosThresholdOptions + public class CosmosThresholdOptions { /// /// Latency Threshold for non point operations i.e. Query diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 8ba2ffa266..59325ecb83 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -686,12 +686,7 @@ internal CosmosClientBuilder WithRetryWithOptions( /// /// /// The object -#if PREVIEW - public -#else - internal -#endif - CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options) + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options) { this.clientOptions.CosmosClientTelemetryOptions = options; return this; diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index 56c152568a..e8d4c602ff 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -64,9 +64,10 @@ public class RequestOptions PriorityLevel? PriorityLevel { get; set; } /// - /// Set Request Level Distributed Tracing Options. + /// Threshold values for Distributed Tracing. + /// These values decides whether to generate operation level with request diagnostics or not. /// - internal CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } /// /// Gets or sets the boolean to use effective partition key routing in the cosmos db request. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 8f25a74f08..dde2d208bc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -352,148 +352,6 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.CosmosClientOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Boolean DisableDistributedTracing": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean DisableDistributedTracing;CanRead:True;CanWrite:True;Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean DisableSendingMetricsToService": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean DisableSendingMetricsToService;CanRead:True;CanWrite:True;Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_DisableDistributedTracing()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_DisableSendingMetricsToService()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void .ctor()": { - "Type": "Constructor", - "Attributes": [], - "MethodInfo": "[Void .ctor(), Void .ctor()]" - }, - "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_DisableDistributedTracing(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_DisableSendingMetricsToService(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.CosmosThresholdOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "System.TimeSpan get_NonPointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.TimeSpan get_PointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.TimeSpan NonPointOperationLatencyThreshold": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "System.TimeSpan NonPointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.TimeSpan PointOperationLatencyThreshold": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "System.TimeSpan PointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void .ctor()": { - "Type": "Constructor", - "Attributes": [], - "MethodInfo": "[Void .ctor(), Void .ctor()]" - }, - "Void set_NonPointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_PointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -568,17 +426,6 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.Linq.CosmosLinqExtensions;System.Object;IsAbstract:True;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 2ba2523435..fd2aa8b93e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2736,6 +2736,18 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.ConnectionMode get_ConnectionMode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions CosmosClientTelemetryOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions get_CosmosClientTelemetryOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.CosmosSerializationOptions get_SerializerOptions()": { "Type": "Method", "Attributes": [], @@ -3007,6 +3019,13 @@ ], "MethodInfo": "Void set_ConsistencyLevel(System.Nullable`1[Microsoft.Azure.Cosmos.ConsistencyLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_CosmosClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableContentResponseOnWrite(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -3116,6 +3135,74 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Boolean DisableDistributedTracing": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean DisableDistributedTracing;CanRead:True;CanWrite:True;Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean DisableSendingMetricsToService": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean DisableSendingMetricsToService;CanRead:True;CanWrite:True;Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_DisableDistributedTracing()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_DisableDistributedTracing();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_DisableSendingMetricsToService()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_DisableSendingMetricsToService();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DisableDistributedTracing(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DisableDistributedTracing(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DisableSendingMetricsToService(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DisableSendingMetricsToService(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.CosmosDiagnostics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -3535,6 +3622,55 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.TimeSpan get_NonPointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_PointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan NonPointOperationLatencyThreshold": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan NonPointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_NonPointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan PointOperationLatencyThreshold": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan PointOperationLatencyThreshold;CanRead:True;CanWrite:True;System.TimeSpan get_PointOperationLatencyThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_NonPointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_PointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Database;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -4418,6 +4554,11 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithBulkExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithClientTelemetryOptions(Microsoft.Azure.Cosmos.CosmosClientTelemetryOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithConnectionModeDirect()": { "Type": "Method", "Attributes": [], @@ -7804,6 +7945,18 @@ } }, "Members": { + "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions CosmosThresholdOptions;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Microsoft.Azure.Cosmos.CosmosThresholdOptions get_CosmosThresholdOptions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.RequestOptions ShallowCopy()": { "Type": "Method", "Attributes": [], @@ -7869,6 +8022,13 @@ ], "MethodInfo": "Void set_AddRequestHeaders(System.Action`1[Microsoft.Azure.Cosmos.Headers]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_IfMatchEtag(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ From 20547bce55d935518803d81f2ad5d235d543fb5d Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 12 Oct 2023 19:43:07 -0700 Subject: [PATCH 210/337] [Internal] Direct Package: Adds version bump (#4120) * direct version bump * Code changes to fix emulator tests to comply with direct release 3.31.5. --------- Co-authored-by: Debdatta Kunda --- Directory.Build.props | 2 +- .../ClientCreateAndInitializeTest.cs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 404becc428..0afd5f98c2 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.35.4 3.35.4 preview - 3.31.4 + 3.31.5 2.0.3 2.0.3 preview diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs index e07fe85a7e..8bbb7f5d54 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs @@ -276,10 +276,9 @@ public async Task CreateAndInitializeAsync_WithValidDatabaseAndContainer_ShouldO .GetValue(loadBalancingPartition); Assert.IsNotNull(openChannels); - Assert.AreEqual(48, openChannels.Count, "Here the expected value 48 rather explains how many time we call the" + - "LoadBalancingPartition.OpenChannelAsync(). The emulator by default returns 12 partitions, and each partition has 4 replicas," + - "and by behavior the emulator uses the same URI for eac of these replica, hence 12 * 4 = 48 times we call the OpenChannelAsync()." + - "In ideal world, the value should be 1, because for each unique URI, the OpenChannelAsync() call will just be 1."); + Assert.AreEqual(1, openChannels.Count, "Here the expected value 1 explains how many TCP connections were opened by the LoadBalancingPartition.OpenChannelAsync()." + + "The emulator by default returns 12 partitions, and each partition has 4 replicas, and by behavior the emulator uses the same URI for each of these replica," + + "hence 12 * 4 = 48 times we call the OpenChannelAsync(). However, the number of TCP connections established would be just one per each unique endpoint."); Assert.AreEqual(openChannels.Count * maxRequestsPerConnection, channelCapacity); Documents.Rntbd.LbChannelState channelState = openChannels.First(); From 8f65cd244293cb19c3af56bb6de91737a9535c1b Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Tue, 17 Oct 2023 07:39:29 -0700 Subject: [PATCH 211/337] Query : Adds Missing QueryMetrics Documentation (#4127) * Update ServerSidePartitionedMetrics.cs * Update ServerSidePartitionedMetrics.cs --- .../src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs index 3fd1f47094..be5a624a42 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs @@ -22,6 +22,9 @@ public abstract class ServerSidePartitionedMetrics /// /// Gets the partition key range id for the partition. /// + /// + /// Only has a value in direct mode. When using gateway mode, this is null. + /// public abstract int? PartitionKeyRangeId { get; } } } From 51a8c6c2fe9c6af397b0c0e19f808c22e85f0575 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 18 Oct 2023 14:48:33 +0530 Subject: [PATCH 212/337] TriggerOperation: Adds Upsert Operation Support (#4119) * Added Upsert Trigger Operation Support * updated contract * fix test --- .../src/Resource/Settings/TriggerOperation.cs | 7 ++- .../TriggersTests.cs | 60 +++++++++++++------ .../Contracts/DotNetSDKAPI.json | 5 ++ .../SettingsContractTests.cs | 13 +++- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/TriggerOperation.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/TriggerOperation.cs index 1f1aa61ab2..d877671f5a 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/TriggerOperation.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/TriggerOperation.cs @@ -32,6 +32,11 @@ public enum TriggerOperation : short /// /// Specifies replace operations only. /// - Replace = 0x4 + Replace = 0x4, + + /// + /// Specifies upsert operations only. + /// + Upsert = 0x5 } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs index 82d76427d5..b21feb3e68 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/TriggersTests.cs @@ -106,7 +106,9 @@ public async Task CRUDTest() } [TestMethod] - public async Task ValidatePreTriggerTest() + [DataRow(TriggerOperation.Create)] + [DataRow(TriggerOperation.Upsert)] + public async Task ValidatePreTriggerTest(TriggerOperation triggerOperation) { string triggerId = "SetJobNumber"; @@ -124,7 +126,7 @@ public async Task ValidatePreTriggerTest() { Id = triggerId, TriggerType = TriggerType.Pre, - TriggerOperation = TriggerOperation.Create, + TriggerOperation = triggerOperation, Body = @"function setJobNumber() { var context = getContext(); var request = context.getRequest(); @@ -150,15 +152,27 @@ public async Task ValidatePreTriggerTest() Job value = new Job() { Id = Guid.NewGuid(), InvestigationKey = "investigation~1" }; - // this should create the document successfully with jobnumber of 1 - Job createdItem = await this.container.CreateItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + Job item = null; + if (triggerOperation == TriggerOperation.Create) { - PreTriggers = new List { triggerId } - }); - - Assert.AreEqual(value.Id, createdItem.Id); - Assert.AreEqual(value.InvestigationKey, createdItem.InvestigationKey); - Assert.AreEqual(1, createdItem.JobNumber); + // this should create the document successfully with jobnumber of 1 + item = await this.container.CreateItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + { + PreTriggers = new List { triggerId } + }); + } + else if(triggerOperation == TriggerOperation.Upsert) + { + // this should create the document successfully with jobnumber of 1 + item = await this.container.UpsertItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + { + PreTriggers = new List { triggerId } + }); + } + + Assert.AreEqual(value.Id, item.Id); + Assert.AreEqual(value.InvestigationKey, item.InvestigationKey); + Assert.AreEqual(1, item.JobNumber); List result = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true).Where(x => x.InvestigationKey == "investigation~1").ToList(); Assert.IsNotNull(result); @@ -171,15 +185,27 @@ public async Task ValidatePreTriggerTest() value.Id = Guid.NewGuid(); - // this should create the document successfully with jobnumber of 2 - Job createdItem2 = await this.container.CreateItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + Job item2 = null; + if (triggerOperation == TriggerOperation.Create) { - PreTriggers = new List { "SetJobNumber" } - }); + // this should create the document successfully with jobnumber of 2 + item2 = await this.container.CreateItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + { + PreTriggers = new List { "SetJobNumber" } + }); + } + else if (triggerOperation == TriggerOperation.Upsert) + { + // this should create the document successfully with jobnumber of 1 + item2 = await this.container.UpsertItemAsync(item: value, partitionKey: null, requestOptions: new ItemRequestOptions + { + PreTriggers = new List { "SetJobNumber" } + }); + } - Assert.AreEqual(value.Id, createdItem2.Id); - Assert.AreEqual(value.InvestigationKey, createdItem2.InvestigationKey); - Assert.AreEqual(2, createdItem2.JobNumber); + Assert.AreEqual(value.Id, item2.Id); + Assert.AreEqual(value.InvestigationKey, item2.InvestigationKey); + Assert.AreEqual(2, item2.JobNumber); result = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true).Where(x => x.InvestigationKey == "investigation~1").ToList(); Assert.IsNotNull(result); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index fd2aa8b93e..8c8d7d6ae1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -8799,6 +8799,11 @@ "Type": "Field", "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.Scripts.TriggerOperation Update;IsInitOnly:False;IsStatic:True;" + }, + "Microsoft.Azure.Cosmos.Scripts.TriggerOperation Upsert": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Scripts.TriggerOperation Upsert;IsInitOnly:False;IsStatic:True;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs index 2e8df92318..4cf045cd7b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs @@ -69,7 +69,7 @@ public void OperationKindMatchesDirect() [TestMethod] public void TriggerOperationMatchesDirect() { - this.AssertEnums(); + this.AssertEnumsContains(); } [TestMethod] @@ -1147,5 +1147,16 @@ private void AssertEnums() where TFirstEnum : struct, I Assert.AreEqual(Convert.ToInt32(documentssVersion), Convert.ToInt32(cosmosVersion)); } } + + private void AssertEnumsContains() where TFirstEnum : struct, IConvertible where TSecondEnum : struct, IConvertible + { + string[] allCosmosEntries = Enum.GetNames(typeof(TFirstEnum)); + string[] allDocumentsEntries = Enum.GetNames(typeof(TSecondEnum)); + + foreach(string entry in allDocumentsEntries) + { + Assert.IsTrue(allCosmosEntries.Contains(entry)); + } + } } } From 5777a3af0d9161f929849adbc03a73770c8dd081 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 18 Oct 2023 21:21:56 +0530 Subject: [PATCH 213/337] SDK 3.36.0 : Adds version bump and changelog (#4118) * first draft * updated changelog * remove already released PRs * updated pr links * changelog and contract changes * updated changelog * updated changelog * updated changelog * remove 4071 from changelog as it should be internal PR * removed an query internal log * updated contracts --- Directory.Build.props | 4 +- .../contracts/API_3.36.0-preview.txt | 1610 +++++++++++++++++ .../contracts/API_3.36.0.txt | 1551 ++++++++++++++++ changelog.md | 26 +- 4 files changed, 3188 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.36.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.36.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 0afd5f98c2..514e8e7abb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.35.4 - 3.35.4 + 3.36.0 + 3.36.0 preview 3.31.5 2.0.3 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.36.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.36.0-preview.txt new file mode 100644 index 0000000000..e94727e915 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.36.0-preview.txt @@ -0,0 +1,1610 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.36.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.36.0.txt new file mode 100644 index 0000000000..e4f36a2457 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.36.0.txt @@ -0,0 +1,1551 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index d6ca1007c1..8b08e37210 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,30 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-17 + +#### Fixed +- [4039](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4039) GatewayAddressCache: Fixes Unobserved Exception During Background Address Refresh (#4039) +- [4098](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4098) Distributed Tracing: Fixes dependency failure on appinsights (#4098) +- [4097](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4097) Distributed Tracing: Fixes SDK responses compatibility with opentelemetry response (#4097) +- [4111](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4111) Distributed Tracing: Fixes traceid null exception issue (#4111) + +#### Added +- [4009](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4009) Query: Adds ODE continuation token support for non-ODE pipelines (#4009) +- [4078](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4078) Query: Adds LINQ RegexMatch Extension method (#4078) +- [4001](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4001) Query: Adds public backend metrics property to Diagnostics (#4001) +- [4016](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4016) CosmosClientOptions: Adds support for multiple formats of Azure region names (#4016) +- [4056](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4056) Client Telemetry: Adds new public APIs (#4056) +> Note: Refer this [3983](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3983) for API signature and default values. +- [4119](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4119) TriggerOperation: Adds Upsert Operation Support(#4119) + +### [3.356.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0-preview) - 2023-10-17 + +#### Added + - [4056](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4056) Client Telemetry: Adds new public APIs (#4056). WARNING: This is breaking change for preview SDK + > Note: `isDistributedTracingEnabled` is removed from `CosmosClientOptions` and `withDistributedTracing()` is removed from `CosmosClientBuilder`. + > Refer this [3983](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3983) for new API signature and default values + ### [3.35.4-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.4-preview) - 2023-09-15 ### [3.35.4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.4) - 2023-09-15 @@ -22,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### [3.35.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3-preview) - 2023-08-10 ### [3.35.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3) - 2023-08-10 + #### Fixed - [4030](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4030) Upgrade Resiliency: Fixes Race Condition by Calling Dispose Too Early @@ -215,7 +240,6 @@ If you have a scenario where tokens generated from the newer SDKs are used by an - [#3433](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3433) CosmosOperationCanceledException: Adds serializable functionality - [#3419](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3419) Documentation: Removes mention of obsolete disableAutomaticIdGeneration - [#3404](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3404) Patch: Adds public to `PatchOperation` class for testing -- [#3400](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3400) Query: Adds new system strings in JsonBinaryEncoding, replacing 1-byte user strings - [#3380](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3380) Query: Adds aggressive prefetching for `GROUP BY` and `COUNT(DISTINCT)` ### [3.30.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.30.1) - 2022-09-01 From f3a9cae960278377bacc936a047ea7ca6c009614 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 18 Oct 2023 23:33:21 +0530 Subject: [PATCH 214/337] Release 3.36.0: Fixes pipeline by removing ReleasePackage variable (#4130) * remove release variable * revert build config variable change also --- azure-pipelines-official.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 81cd3d3d91..db77d4b0fd 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -7,7 +7,6 @@ variables: VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops BuildConfiguration: Release Packaging.EnableSBOMSigning: true - ReleasePackage: true OS: 'Windows' stages: @@ -61,8 +60,8 @@ stages: jobs: - template: templates/nuget-pack.yml parameters: - BuildConfiguration: $(BuildConfiguration) + BuildConfiguration: Release VmImage: $(VmImage) - ReleasePackage: $(ReleasePackage) + ReleasePackage: true OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' BlobVersion: $(BlobVersion) \ No newline at end of file From 28204bb5a261af1bb6711a3cba3961079c558351 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:16:43 -0400 Subject: [PATCH 215/337] Item Operations: Fixes JsonSerialization exception when MissingMemberHandling = Error on Json default settings when NotFound on Item operations. (#4125) * issue 4115 initial checkin. need insight from issuer on reproducing this issue * test refactoring and adding more coverage for other NotFound scenarios * commit on some actionables * setting JsonConvert.DefaultSettings to null so that other tests will not fail * as requested, removed catches from test methods --- .../CosmosExceptionFactory.cs | 9 +- .../CosmosItemTests.cs | 354 +++++++++++++++++- 2 files changed, 350 insertions(+), 13 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs index 0648aecbc3..741f8906fa 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs @@ -159,6 +159,7 @@ internal static (Error, string) GetErrorFromStream( using (StreamReader streamReader = new StreamReader(content)) { string errorContent = streamReader.ReadToEnd(); + try { JObject errorObj = JObject.Parse(errorContent); @@ -179,7 +180,7 @@ internal static (Error, string) GetErrorFromStream( return (error, message.ToString()); } } - catch (Newtonsoft.Json.JsonReaderException) + catch (Exception exception) when (CosmosExceptionFactory.ExceptionsToIgnore(exception)) { } @@ -193,6 +194,12 @@ internal static (Error, string) GetErrorFromStream( } } + private static bool ExceptionsToIgnore(Exception exception) + { + return exception is Newtonsoft.Json.JsonReaderException || + exception is Newtonsoft.Json.JsonSerializationException; + } + internal static CosmosException CreateRequestTimeoutException( string message, Headers headers, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index 607b552b83..860c780e41 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -781,7 +781,7 @@ public async Task PartitionKeyDeleteTestForSubpartitionedContainer() try { database = await client.CreateDatabaseIfNotExistsAsync("mydb"); - + ContainerProperties containerProperties = new ContainerProperties("subpartitionedcontainer", new List { "/Country", "/City" }); Container container = await database.CreateContainerAsync(containerProperties); ContainerInternal containerInternal = (ContainerInternal)container; @@ -812,7 +812,7 @@ public async Task PartitionKeyDeleteTestForSubpartitionedContainer() doc1.SetValue("Country", "USA"); doc1.SetValue("City", "Stonybrook"); documents[4] = await container.CreateItemAsync(doc1); - + Cosmos.PartitionKey partitionKey1 = new PartitionKeyBuilder().Add("USA").Add("Stonybrook").Build(); using (ResponseMessage pKDeleteResponse = await containerInternal.DeleteAllItemsByPartitionKeyStreamAsync(partitionKey1)) @@ -844,7 +844,7 @@ public async Task PartitionKeyDeleteTestForSubpartitionedContainer() finally { HttpConstants.Versions.CurrentVersion = currentVersion; - if(database != null) await database.DeleteAsync(); + if (database != null) await database.DeleteAsync(); } } @@ -973,7 +973,7 @@ public async Task ItemCustomSerializerTest() // Each parameter in query spec should be a call to the custom serializer int parameterCount = queryDefinition.ToSqlQuerySpec().Parameters.Count; - Assert.AreEqual((parameterCount*pageCount)+parameterCount, toStreamCount, $"missing to stream call. Expected: {(parameterCount * pageCount) + parameterCount}, Actual: {toStreamCount} for query:{queryDefinition.ToSqlQuerySpec().QueryText}"); + Assert.AreEqual((parameterCount * pageCount) + parameterCount, toStreamCount, $"missing to stream call. Expected: {(parameterCount * pageCount) + parameterCount}, Actual: {toStreamCount} for query:{queryDefinition.ToSqlQuerySpec().QueryText}"); Assert.AreEqual(pageCount, fromStreamCount); } } @@ -1195,7 +1195,7 @@ public async Task QueryStreamValueTest() { Assert.AreEqual(3, pageCount); } - + IReadOnlyList<(string Name, object Value)> parameters1 = queryDefinition.GetQueryParameters(); @@ -1362,7 +1362,7 @@ public async Task ItemMultiplePartitionQuery() { FeedResponse iter = await feedIterator.ReadNextAsync(); Assert.IsTrue(iter.Count() <= 1); - if(iter.Count() == 1) + if (iter.Count() == 1) { found = true; ToDoActivity response = iter.First(); @@ -1493,8 +1493,8 @@ public async Task ItemMultiplePartitionOrderByQueryStream() }; IList deleteList = await ToDoActivity.CreateRandomItems( - this.Container, - 300, + this.Container, + 300, randomPartitionKey: true, randomTaskNumber: true); @@ -1753,8 +1753,8 @@ public async Task ItemEpkQuerySingleKeyRangeValidation() public async Task ItemQueryStreamSerializationSetting() { IList deleteList = await ToDoActivity.CreateRandomItems( - container: this.Container, - pkCount: 101, + container: this.Container, + pkCount: 101, randomTaskNumber: true); QueryDefinition sql = new QueryDefinition("SELECT * FROM toDoActivity t ORDER BY t.taskNum"); @@ -2135,9 +2135,9 @@ public async Task ItemPatchSuccessTest() Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Resource); Assert.AreEqual(null, response.Resource.children[0].id); - + patchOperations.Clear(); - patchOperations.Add(PatchOperation.Add("/children/1/description","Child#1")); + patchOperations.Add(PatchOperation.Add("/children/1/description", "Child#1")); patchOperations.Add(PatchOperation.Move("/children/0/description", "/description")); patchOperations.Add(PatchOperation.Move("/children/1/description", "/children/0/description")); // with content response @@ -3151,6 +3151,336 @@ public async Task HaLayerDoesNotThrowNullOnGoneExceptionTest() } } + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("ReadItemStreamAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and the MissingMemberHandling is set to MissingMemberHandling.Error. " + + "ReadItemStreamAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenReadItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemStreamAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, cancellationToken) => await container.ReadItemStreamAsync( + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("ReadItemAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and MissingMemberHandling is set to MissingMemberHandling.Error. " + + "ReadItemAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenReadItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, toDoActivity, cancellationToken) => await container.ReadItemAsync( + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("DeleteItemStreamAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and the MissingMemberHandling is set to MissingMemberHandling.Error. " + + "DeleteItemStreamAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenDeleteItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemStreamAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, cancellationToken) => await container.DeleteItemStreamAsync( + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("DeleteItemAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and MissingMemberHandling is set to MissingMemberHandling.Error. " + + "DeleteItemAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenDeleteItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, toDoActivity, cancellationToken) => await container.DeleteItemAsync( + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("DeleteItemStreamAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and the MissingMemberHandling is set to MissingMemberHandling.Error. " + + "DeleteItemStreamAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenReplaceItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemStreamAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, cancellationToken) => await container.ReplaceItemStreamAsync( + streamPayload: new MemoryStream(), + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("ReplaceItemAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and MissingMemberHandling is set to MissingMemberHandling.Error. " + + "ReplaceItemAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenReplaceItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + await CosmosItemTests.GivenItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, toDoActivity, cancellationToken) => await container.ReplaceItemAsync( + item: toDoActivity, + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("PatchItemStreamAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and the MissingMemberHandling is set to MissingMemberHandling.Error. " + + "PatchItemStreamAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenPatchItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + List patchOperations = new() + { + PatchOperation.Add("/children/1/pk", "patched"), + PatchOperation.Remove("/description"), + PatchOperation.Replace("/taskNum", 1) + }; + + await CosmosItemTests.GivenItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemStreamAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, cancellationToken) => await container.PatchItemStreamAsync( + patchOperations: patchOperations, + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + /// + /// + /// + /// + [TestMethod] + [Owner("philipthomas")] + [Description("PatchItemAsync is yielding a Newtonsoft.Json.JsonSerializationException whenever " + + "the item is not found and MissingMemberHandling is set to MissingMemberHandling.Error. " + + "PatchItemAsync should yield a CosmosException with a NotFound StatusCode.")] + public async Task GivenPatchItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync() + { + List patchOperations = new() + { + PatchOperation.Add("/children/1/pk", "patched"), + PatchOperation.Remove("/description"), + PatchOperation.Replace("/taskNum", 1) + }; + + await CosmosItemTests.GivenItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + itemAsync: async (container, itemIdThatWillNotExist, partitionKeyValue, toDoActivity, cancellationToken) => await container.PatchItemAsync( + patchOperations: patchOperations, + id: itemIdThatWillNotExist, + partitionKey: new Cosmos.PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken)); + } + + private static async Task GivenItemStreamAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + Func> itemStreamAsync) + { + // AAA + // Arrange + CancellationTokenSource cancellationTokenSource = new(); + CancellationToken cancellationToken = cancellationTokenSource.Token; + + // Food for thought, actionable items. + // + // 1. Is there anything else that we should be concerned with that would give us the same behavior? + // 2. Are there other operations other than those that can yield an NotFound exception that we should be + // concerned with? + // 3. Can we also reset the DefaultSettings before we make the call, and reset it back once it is done? + + JsonConvert.DefaultSettings = () => new JsonSerializerSettings + { + MissingMemberHandling = MissingMemberHandling.Error + }; + + CosmosClient cosmosClient = TestCommon.CreateCosmosClient(); + + string databaseId = Guid.NewGuid().ToString(); + Cosmos.Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync( + id: databaseId, + cancellationToken: cancellationToken); + + try + { + string containerId = Guid.NewGuid().ToString(); + Container container = await database.CreateContainerIfNotExistsAsync( + containerProperties: new ContainerProperties + { + Id = containerId, + PartitionKeyPath = "/pk", + }, + cancellationToken: cancellationToken); + + + // Act + string itemIdThatWillNotExist = Guid.NewGuid().ToString(); + string partitionKeyValue = Guid.NewGuid().ToString(); + + ResponseMessage response = await itemStreamAsync(container, itemIdThatWillNotExist, partitionKeyValue, cancellationToken); + + // Assert + Debug.Assert( + condition: response != null, + message: $"{response}"); + + Assert.AreEqual( + expected: HttpStatusCode.NotFound, + actual: response.StatusCode); + + string content = JsonConvert.SerializeObject(response.Content); + + Assert.AreEqual( + expected: "null", + actual: content); + + string errorMessage = JsonConvert.SerializeObject(response.ErrorMessage); + + Assert.IsNotNull(value: errorMessage); + + Debug.Assert( + condition: response.CosmosException != null, + message: $"{response.CosmosException}"); + + Assert.AreEqual( + expected: HttpStatusCode.NotFound, + actual: response.StatusCode); + + Debug.WriteLine(message: $"{nameof(response.CosmosException)}: {response.CosmosException}"); + + Assert.AreEqual( + actual: response.CosmosException.StatusCode, + expected: HttpStatusCode.NotFound); + } + finally + { + if (database != null) + { + // Remove the test database. Cleanup. + _ = await database.DeleteAsync(cancellationToken: cancellationToken); + + Debug.WriteLine($"The {nameof(database)} with id '{databaseId}' was removed."); + } + + // Setting this back because it blows up other serialization tests. + + JsonConvert.DefaultSettings = () => default; + } + } + + private static async Task GivenItemAsyncWhenMissingMemberHandlingIsErrorThenExpectsCosmosExceptionTestAsync( + Func>> itemAsync) + { + // AAA + // Arrange + CancellationTokenSource cancellationTokenSource = new(); + CancellationToken cancellationToken = cancellationTokenSource.Token; + + // Food for thought, actionable items. + // + // 1. Is there anything else that we should be concerned with that would give us the same behavior? + // 2. Are there other operations other than those that can yield an NotFound exception that we should be + // concerned with? + // 3. Can we also reset the DefaultSettings before we make the call, and reset it back once it is done? + + JsonConvert.DefaultSettings = () => new JsonSerializerSettings + { + MissingMemberHandling = MissingMemberHandling.Error + }; + + CosmosClient cosmosClient = TestCommon.CreateCosmosClient(); + + string databaseId = Guid.NewGuid().ToString(); + Cosmos.Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync( + id: databaseId, + cancellationToken: cancellationToken); + + try + { + string containerId = Guid.NewGuid().ToString(); + Container container = await database.CreateContainerIfNotExistsAsync( + containerProperties: new ContainerProperties + { + Id = containerId, + PartitionKeyPath = "/pk", + }, + cancellationToken: cancellationToken); + + + // Act + // If any thing other than a CosmosException is thrown, the call to ReadItemAsync below will fail. + string itemIdThatWillNotExist = Guid.NewGuid().ToString(); + string partitionKeyValue = Guid.NewGuid().ToString(); + + CosmosException cosmosException = await Assert.ThrowsExceptionAsync(action: + async () => await itemAsync(container, itemIdThatWillNotExist, partitionKeyValue, new ToDoActivity { id = Guid.NewGuid().ToString(), pk = "Georgia" }, cancellationToken)) ; + + // Assert + Debug.Assert( + condition: cosmosException != null, + message: $"{cosmosException}"); + + Debug.WriteLine(message: $"{nameof(cosmosException)}: {cosmosException}"); + + Assert.AreEqual( + actual: cosmosException.StatusCode, + expected: HttpStatusCode.NotFound); + } + finally + { + if (database != null) + { + // Remove the test database. Cleanup. + _ = await database.DeleteAsync(cancellationToken: cancellationToken); + + Debug.WriteLine($"The {nameof(database)} with id '{databaseId}' was removed."); + } + + // Setting this back because it blows up other serialization tests. + + JsonConvert.DefaultSettings = () => default; + } + } + private async Task AutoGenerateIdPatternTest(Cosmos.PartitionKey pk, T itemWithoutId) { string autoId = Guid.NewGuid().ToString(); From 1afcacd3169a7a9bcc4a196837b71509c63df1d2 Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Wed, 18 Oct 2023 14:56:37 -0700 Subject: [PATCH 216/337] [Internal] Query : Adds test coverage for custom serializers (#4114) * initial cleanup * test updates - working * cleanup * more cleanup * more * whoops * Add results to basline * adding payload to xml * some generics * cleanup * Add datamember serializer * reorder functions and test fix * tostring() update and add case * fix payload * fix datamembertest * cleanup * cleanup * PR comment --------- Co-authored-by: Matias Quaranta --- .../src/Linq/ExpressionToSQL.cs | 15 +- .../Resource/Container/ContainerCore.Items.cs | 5 - .../Serializer/CosmosLinqSerializerOptions.cs | 4 - ...seline.TestMemberInitializerDataMember.xml | 236 ++++++++++ ...erBaseline.TestMemberInitializerDotNet.xml | 236 ++++++++++ ...e.TestMemberInitializerMultiSerializer.xml | 236 ++++++++++ ...seline.TestMemberInitializerNewtonsoft.xml | 236 ++++++++++ .../CustomSerializationTests.cs | 32 +- .../Linq/LinqTestsCommon.cs | 140 ++++-- ...TranslationWithCustomSerializerBaseline.cs | 407 ++++++++++++++++++ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 20 +- 11 files changed, 1486 insertions(+), 81 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index 2ada0738da..fef136d8d2 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -15,12 +15,10 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Reflection; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.CosmosElements.Numbers; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Spatial; using Microsoft.Azure.Cosmos.SqlObjects; using Microsoft.Azure.Documents; using Newtonsoft.Json; - using Newtonsoft.Json.Linq; using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings; // ReSharper disable UnusedParameter.Local @@ -77,10 +75,9 @@ public static class LinqMethods public const string Where = "Where"; } - private static string SqlRoot = "root"; - private static string DefaultParameterName = "v"; - private static bool usePropertyRef = false; - private static SqlIdentifier RootIdentifier = SqlIdentifier.Create(SqlRoot); + private static readonly string SqlRoot = "root"; + private static readonly string DefaultParameterName = "v"; + private static readonly bool usePropertyRef = false; /// /// Toplevel entry point. @@ -455,12 +452,12 @@ private static SqlScalarExpression VisitBinary(BinaryExpression inputExpression, { if (TryMatchStringCompareTo(methodCallExpression, constantExpression, inputExpression.NodeType)) { - return ExpressionToSql.VisitStringCompareTo(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context); + return ExpressionToSql.VisitStringCompareTo(methodCallExpression, inputExpression.NodeType, reverseNodeType, context); } if (TryMatchStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType)) { - return ExpressionToSql.VisitStringCompare(methodCallExpression, constantExpression, inputExpression.NodeType, reverseNodeType, context); + return ExpressionToSql.VisitStringCompare(methodCallExpression, inputExpression.NodeType, reverseNodeType, context); } } @@ -613,7 +610,6 @@ private static bool TryMatchStringCompareTo(MethodCallExpression left, ConstantE private static SqlScalarExpression VisitStringCompareTo( MethodCallExpression left, - ConstantExpression right, ExpressionType compareOperator, bool reverseNodeType, TranslationContext context) @@ -690,7 +686,6 @@ private static bool TryMatchStringCompare(MethodCallExpression left, ConstantExp private static SqlScalarExpression VisitStringCompare( MethodCallExpression left, - ConstantExpression right, ExpressionType compareOperator, bool reverseNodeType, TranslationContext context) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index a694b78019..fd9ad03b53 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -16,8 +16,6 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.ChangeFeed; using Microsoft.Azure.Cosmos.ChangeFeed.FeedProcessing; using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; - using Microsoft.Azure.Cosmos.ChangeFeed.Utils; - using Microsoft.Azure.Cosmos.Common; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Cosmos.Linq; @@ -29,11 +27,8 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Microsoft.Azure.Cosmos.ReadFeed; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; - using Microsoft.Azure.Cosmos.Routing; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; - using Microsoft.Azure.Documents.Routing; /// /// Used to perform operations on items. There are two different types of operations. diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs index b7523b2c6a..3b215a9cc8 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptions.cs @@ -4,10 +4,6 @@ namespace Microsoft.Azure.Cosmos { - using System; - using System.Collections.Generic; - using System.Text; - /// /// This class provides a way to configure Linq Serialization Properties /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml new file mode 100644 index 0000000000..6734a125fa --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml @@ -0,0 +1,236 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectDataMember() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectDataMember() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectDataMember() {NumericField = 1, StringField = "1"}, new DataObjectDataMember() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectDataMember() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectDataMember() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectDataMember() {NumericField = 1, StringField = "1"}, new DataObjectDataMember() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml new file mode 100644 index 0000000000..b381e2b651 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml @@ -0,0 +1,236 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectDotNet() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectDotNet() {NumericField = 1, StringField = "1"}, new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumericField": 1, "StringField": "1", "id": null, "Pk": null} : {"NumericField": 1, "StringField": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectDotNet() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectDotNet() {NumericField = 1, StringField = "1"}, new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumericField": 1, "StringField": "1", "id": null, "Pk": null} : {"NumericField": 1, "StringField": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml new file mode 100644 index 0000000000..704eb39807 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml @@ -0,0 +1,236 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}, new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectMultiSerializer() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}, new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectMultiSerializer() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml new file mode 100644 index 0000000000..b5b16752cc --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml @@ -0,0 +1,236 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectNewtonsoft() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoft() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectNewtonsoft() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CustomSerializationTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CustomSerializationTests.cs index 5e6e2fe7bb..3334c201d1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CustomSerializationTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CustomSerializationTests.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.Utils; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; @@ -35,7 +34,7 @@ public abstract class CustomSerializationTests private Uri databaseUri; private Uri collectionUri; private Uri partitionedCollectionUri; - private PartitionKeyDefinition defaultPartitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; + private readonly PartitionKeyDefinition defaultPartitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/pk" }), Kind = PartitionKind.Hash }; internal abstract DocumentClient CreateDocumentClient( Uri hostUri, @@ -77,7 +76,7 @@ public void TestSetup() { if (ex.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable) { - // Emulator con sometimes fail under load, so we retry + // Emulator can sometimes fail under load, so we retry Task.Delay(1000); this.documentClient.CreateDocumentCollectionAsync(this.databaseUri, newCollection, new RequestOptions { OfferThroughput = 400 }).Wait(); } @@ -100,7 +99,7 @@ public void TestSetup() { if (ex.StatusCode == System.Net.HttpStatusCode.ServiceUnavailable) { - // Emulator con sometimes fail under load, so we retry + // Emulator can sometimes fail under load, so we retry Task.Delay(1000); this.documentClient.CreateDocumentCollectionAsync(this.databaseUri, partitionedCollection, new RequestOptions { OfferThroughput = 10000 }).Wait(); } @@ -136,13 +135,12 @@ public void TestDateParseHandlingOnReadDocument() // Verify round-trip create and read document RequestOptions applyRequestOptions = this.ApplyRequestOptions(new RequestOptions(), serializerSettings); - this.AssertPropertyOnReadDocument(client, this.collectionUri, createdDocument, applyRequestOptions, originalDocument, jsonProperty); - this.AssertPropertyOnReadDocument(client, this.partitionedCollectionUri, partitionedDocument, applyRequestOptions, originalDocument, jsonProperty); + this.AssertPropertyOnReadDocument(client, createdDocument, applyRequestOptions, originalDocument, jsonProperty); + this.AssertPropertyOnReadDocument(client, partitionedDocument, applyRequestOptions, originalDocument, jsonProperty); } private void AssertPropertyOnReadDocument( DocumentClient client, - Uri targetCollectionUri, Document createdDocument, RequestOptions requestOptions, Document originalDocument, @@ -311,26 +309,6 @@ public async Task TestJsonSerializerSettings(bool useGateway) } this.AssertEqual(testDocument, allDocuments.First()); - - //Will add LINQ test once it is available with new V3 OM - // // LINQ Lambda - // var query1 = client.CreateDocumentQuery(partitionedCollectionUri, options) - // .Where(_ => _.Id.CompareTo(String.Empty) > 0) - // .Select(_ => _.Id); - // string query1Str = query1.ToString(); - // var result = query1.ToList(); - // Assert.AreEqual(1, result.Count); - // Assert.AreEqual(testDocument.Id, result[0]); - - // // LINQ Query - // var query2 = - // from f in client.CreateDocumentQuery(partitionedCollectionUri, options) - // where f.Id.CompareTo(String.Empty) > 0 - // select f.Id; - // string query2Str = query2.ToString(); - // var result2 = query2.ToList(); - // Assert.AreEqual(1, result2.Count); - // Assert.AreEqual(testDocument.Id, result2[0]); } [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 87b33110e2..c8513e41b8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -156,12 +156,11 @@ public static Boolean IsAnonymousType(Type type) } /// - /// Validate the results of CosmosDB query and the results of LinQ query on the original data - /// Using Assert, will fail the unit test if the two results list are not SequenceEqual + /// Gets the results of CosmosDB query and the results of LINQ query on the original data /// /// /// - public static void ValidateResults(IQueryable queryResults, IQueryable dataResults) + public static (List queryResults, List dataResults) GetResults(IQueryable queryResults, IQueryable dataResults) { // execution validation IEnumerator queryEnumerator = queryResults.GetEnumerator(); @@ -171,7 +170,19 @@ public static void ValidateResults(IQueryable queryResults, IQueryable dataResul queryResultsList.Add(queryEnumerator.Current); } - List dataResultsList = dataResults.Cast().ToList(); + List dataResultsList = dataResults?.Cast()?.ToList(); + + return (queryResultsList, dataResultsList); + } + + /// + /// Validates the results of CosmosDB query and the results of LINQ query on the original data + /// Using Assert, will fail the unit test if the two results list are not SequenceEqual + /// + /// + /// + private static void ValidateResults(List queryResultsList, List dataResultsList) + { bool resultMatched = true; string actualStr = null; string expectedStr = null; @@ -229,9 +240,8 @@ public static void ValidateResults(IQueryable queryResults, IQueryable dataResul string assertMsg = string.Empty; if (!resultMatched) { - if (actualStr == null) actualStr = JsonConvert.SerializeObject(queryResultsList); - - if (expectedStr == null) expectedStr = JsonConvert.SerializeObject(dataResultsList); + actualStr ??= JsonConvert.SerializeObject(queryResultsList); + expectedStr ??= JsonConvert.SerializeObject(dataResultsList); resultMatched |= actualStr.Equals(expectedStr); if (!resultMatched) @@ -271,7 +281,7 @@ public static DateTime RandomDateTime(Random random, DateTime midDateTime) } /// - /// Generate test data for most LinQ tests + /// Generate test data for most LINQ tests /// /// the object type /// the lamda to create an instance of test data @@ -315,6 +325,44 @@ public static Func> GenerateTestCosmosData(Func + /// Generate a non-random payload for serializer LINQ tests. + /// + /// the object type + /// the lamda to create an instance of test data + /// number of test data to be created + /// the target container + /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. Also the serialized payload. + public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, bool camelCaseSerialization = false) + { + List data = new List(); + for (int i = 0; i < count; i++) + { + data.Add(func(i, camelCaseSerialization)); + } + + foreach (T obj in data) + { + ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions() + { +#if PREVIEW + EnableOptimisticDirectExecution = false +#endif + }; + + CosmosLinqSerializerOptions linqSerializerOptions = new CosmosLinqSerializerOptions { PropertyNamingPolicy = camelCaseSerialization ? CosmosPropertyNamingPolicy.CamelCase : CosmosPropertyNamingPolicy.Default }; + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); + + IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); + + return getQuery; + } + public static Func> GenerateFamilyCosmosData( Cosmos.Database cosmosDatabase, out Container container) { @@ -434,7 +482,7 @@ Family createDataObj(Random random) for (int j = 0; j < random.Next(MaxThings) + 1; ++j) { obj.Children[i].Things.Add( - j == 0 ? "A" : $"{j}-{random.Next().ToString()}", + j == 0 ? "A" : $"{j}-{random.Next()}", LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength))); } } @@ -462,9 +510,7 @@ Family createDataObj(Random random) return getQuery; } - public static Func> GenerateSimpleCosmosData( - Cosmos.Database cosmosDatabase - ) + public static Func> GenerateSimpleCosmosData(Cosmos.Database cosmosDatabase) { const int DocumentCount = 10; PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; @@ -480,7 +526,7 @@ Cosmos.Database cosmosDatabase { Id = Guid.NewGuid().ToString(), Number = random.Next(-10000, 10000), - Flag = index % 2 == 0 ? true : false, + Flag = index % 2 == 0, Multiples = new int[] { index, index * 2, index * 3, index * 4 }, Pk = "Test" }; @@ -508,28 +554,35 @@ Cosmos.Database cosmosDatabase return getQuery; } - public static LinqTestOutput ExecuteTest(LinqTestInput input) + public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResultsInBaseline = false) { string querySqlStr = string.Empty; try { Func compiledQuery = input.Expression.Compile(); - IQueryable queryResults = compiledQuery(true); - querySqlStr = JObject.Parse(queryResults.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); + IQueryable query = compiledQuery(true); + querySqlStr = JObject.Parse(query.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); - // we skip unordered query because the LinQ results vs actual query results are non-deterministic + IQueryable dataQuery = input.skipVerification ? null : compiledQuery(false); + + (List queryResults, List dataResults) = GetResults(query, dataQuery); + + // we skip unordered query because the LINQ results vs actual query results are non-deterministic if (!input.skipVerification) { - IQueryable dataResults = compiledQuery(false); LinqTestsCommon.ValidateResults(queryResults, dataResults); } - return new LinqTestOutput(querySqlStr); + string serializedResults = serializeResultsInBaseline ? + JsonConvert.SerializeObject(queryResults.Select(item => item is LinqTestObject ? item.ToString() : item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented}) : + null; + + return new LinqTestOutput(querySqlStr, serializedResults, errorMsg: null, input.inputData); } catch (Exception e) { - return new LinqTestOutput(querySqlStr, LinqTestsCommon.BuildExceptionMessageForTest(e)); + return new LinqTestOutput(querySqlStr, serializedResults: null, errorMsg: LinqTestsCommon.BuildExceptionMessageForTest(e), inputData: input.inputData); } } @@ -570,13 +623,15 @@ public class LinqTestObject { private string json; + protected virtual string SerializeForTestBaseline() + { + return JsonConvert.SerializeObject(this); + } + public override string ToString() { // simple cached serialization - if (this.json == null) - { - this.json = JsonConvert.SerializeObject(this); - } + this.json ??= this.SerializeForTestBaseline(); return this.json; } @@ -608,18 +663,25 @@ public class LinqTestInput : BaselineTestInput internal int randomSeed = -1; internal Expression> Expression { get; } internal string expressionStr; + internal string inputData; // We skip the verification between Cosmos DB and actual query restuls in the following cases // - unordered query since the results are not deterministics for LinQ results and actual query results // - scenarios not supported in LINQ, e.g. sequence doesn't contain element. internal bool skipVerification; - internal LinqTestInput(string description, Expression> expr, bool skipVerification = false, string expressionStr = null) + internal LinqTestInput( + string description, + Expression> expr, + bool skipVerification = false, + string expressionStr = null, + string inputData = null) : base(description) { this.Expression = expr ?? throw new ArgumentNullException($"{nameof(expr)} must not be null."); this.skipVerification = skipVerification; this.expressionStr = expressionStr; + this.inputData = inputData; } public static string FilterInputExpression(string input) @@ -656,11 +718,7 @@ public override void SerializeAsXml(XmlWriter xmlWriter) throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); } - if (this.expressionStr == null) - { - this.expressionStr = LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); - } - + this.expressionStr ??= LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); xmlWriter.WriteStartElement("Description"); xmlWriter.WriteCData(this.Description); @@ -678,7 +736,9 @@ public class LinqTestOutput : BaselineTestOutput internal static Regex newLine = new Regex("(\r\n|\r|\n)"); internal string SqlQuery { get; } - internal string ErrorMessage { get; private set; } + internal string ErrorMessage { get; } + internal string Results { get; } + internal string InputData { get; } private static readonly Dictionary newlineKeywords = new Dictionary() { { "SELECT", "\nSELECT" }, @@ -704,10 +764,12 @@ public static string FormatErrorMessage(string msg) return msg; } - internal LinqTestOutput(string sqlQuery, string errorMsg = null) + internal LinqTestOutput(string sqlQuery, string serializedResults, string errorMsg, string inputData) { this.SqlQuery = FormatSql(sqlQuery); + this.Results = serializedResults; this.ErrorMessage = errorMsg; + this.InputData = inputData; } public static String FormatSql(string sqlQuery) @@ -740,7 +802,7 @@ public static String FormatSql(string sqlQuery) } else if (tokens[i].StartsWith(endCue, StringComparison.OrdinalIgnoreCase)) { - indentSb.Length = indentSb.Length - oneTab.Length; + indentSb.Length -= oneTab.Length; } sb.Append(indentSb).Append(tokens[i]).Append("\n"); @@ -754,6 +816,18 @@ public override void SerializeAsXml(XmlWriter xmlWriter) xmlWriter.WriteStartElement(nameof(this.SqlQuery)); xmlWriter.WriteCData(this.SqlQuery); xmlWriter.WriteEndElement(); + if (this.InputData != null) + { + xmlWriter.WriteStartElement("InputData"); + xmlWriter.WriteCData(this.InputData); + xmlWriter.WriteEndElement(); + } + if (this.Results != null) + { + xmlWriter.WriteStartElement("Results"); + xmlWriter.WriteCData(this.Results); + xmlWriter.WriteEndElement(); + } if (this.ErrorMessage != null) { xmlWriter.WriteStartElement("ErrorMessage"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs new file mode 100644 index 0000000000..3266809926 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs @@ -0,0 +1,407 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Linq.Dynamic; + using System.Runtime.Serialization; + using System.Text.Json; + using System.Text.Json.Serialization; + using System.Threading.Tasks; + using BaselineTest; + using global::Azure.Core.Serialization; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + [SDK.EmulatorTests.TestClass] + public class LinqTranslationWithCustomSerializerBaseline : BaselineTests + { + private static CosmosClient CosmosClient; + private static Database TestDb; + private static Container TestContainer; + + private const int RecordCount = 3; + private const int MaxValue = 500; + private const int MaxStringLength = 100; + private const int PropertyCount = 4; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + CosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) + => cosmosClientBuilder.WithCustomSerializer(new SystemTextJsonSerializer(new JsonSerializerOptions()))); + + string dbName = $"{nameof(LinqTranslationBaselineTests)}-{Guid.NewGuid():N}"; + TestDb = await CosmosClient.CreateDatabaseAsync(dbName); + } + + [ClassCleanup] + public async static Task Cleanup() + { + if (TestDb != null) + { + await TestDb.DeleteStreamAsync(); + } + } + + [TestInitialize] + public async Task TestInitialize() + { + TestContainer = await TestDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")); + } + + [TestCleanup] + public async Task TestCleanup() + { + await TestContainer.DeleteContainerStreamAsync(); + } + + public override LinqTestOutput ExecuteTest(LinqTestInput input) + { + return LinqTestsCommon.ExecuteTest(input, serializeResultsInBaseline: true); + } + + [TestMethod] + public void TestMemberInitializerDotNet() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + + string insertedData = this.GetInsertedData().Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + // TODO (10/13/23): extend this and other tests cases as more LINQ features are added (GROUP BY, etc.) + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDotNet() { NumericField = 1, StringField = "1" } : new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + + // Negative test case: serializing only field name using custom serializer not currently supported + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestMemberInitializerNewtonsoft() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + + string insertedData = this.GetInsertedData().Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" } : new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + + // Negative test case: serializing only field name using custom serializer not currently supported + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestMemberInitializerDataMember() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + + string insertedData = this.GetInsertedData().Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDataMember() { NumericField = 1, StringField = "1" } : new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + + // Negative test case: serializing only field name using custom serializer not currently supported + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestMemberInitializerMultiSerializer() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + + string insertedData = this.GetInsertedData().Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" } : new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + + // Negative test case: serializing only field name using custom serializer not currently supported + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectMultiSerializer() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } + + this.ExecuteTestSuite(inputs); + } + + private (Func>, Func>) InsertDataAndGetQueryables() where T : LinqTestObject + { + static T createDataObj(int index, bool camelCase) + { + T obj = (T)Activator.CreateInstance(typeof(T), new object[] + { + index, index.ToString(), $"{index}-{camelCase}", "Test" + }); + return obj; + } + + Func> getQueryCamelCase = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, TestContainer, camelCaseSerialization: true); + Func> getQueryDefault = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, TestContainer, camelCaseSerialization: false); + + return (getQueryCamelCase, getQueryDefault); + } + + private async Task GetInsertedData() + { + List insertedDataList = new List(); + using (FeedIterator feedIterator = TestContainer.GetItemQueryStreamIterator("SELECT * FROM c")) + { + while (feedIterator.HasMoreResults) + { + using (ResponseMessage response = await feedIterator.ReadNextAsync()) + { + response.EnsureSuccessStatusCode(); + using (StreamReader streamReader = new StreamReader(response.Content)) + using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) + { + // manual parsing of response object to preserve property names + JObject queryResponseObject = await JObject.LoadAsync(jsonTextReader); + IEnumerable info = queryResponseObject["Documents"].AsEnumerable(); + + foreach (JToken docToken in info) + { + string documentString = "{"; + for (int index = 0; index < PropertyCount; index++) + { + documentString += index == 0 ? String.Empty : ", "; + documentString += docToken.ElementAt(index).ToString(); + } + documentString += "}"; + insertedDataList.Add(documentString); + } + } + } + } + } + + string insertedData = JsonConvert.SerializeObject(insertedDataList.Select(item => item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented }); + return insertedData; + } + + private class SystemTextJsonSerializer : CosmosSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, typeof(T), default); + streamPayload.Position = 0; + return streamPayload; + } + } + + private class DataObjectDotNet : LinqTestObject + { + [JsonPropertyName("numberValueDotNet")] + public double NumericField { get; set; } + + [JsonPropertyName("stringValueDotNet")] + public string StringField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectDotNet() { } + + public DataObjectDotNet(double numericField, string stringField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.id = id; + this.Pk = pk; + } + + public override string ToString() + { + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } + + private class DataObjectNewtonsoft : LinqTestObject + { + [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] + public double NumericField { get; set; } + + [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] + public string StringField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectNewtonsoft() { } + + public DataObjectNewtonsoft(double numericField, string stringField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.id = id; + this.Pk = pk; + } + + public override string ToString() + { + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } + + [DataContract] + private class DataObjectDataMember : LinqTestObject + { + [DataMember(Name = "NumericFieldDataMember")] + public double NumericField { get; set; } + + [DataMember(Name = "StringFieldDataMember")] + public string StringField { get; set; } + + [DataMember(Name = "id")] + public string id { get; set; } + + [DataMember(Name = "Pk")] + public string Pk { get; set; } + + public DataObjectDataMember() { } + + public DataObjectDataMember(double numericField, string stringField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.id = id; + this.Pk = pk; + } + + public override string ToString() + { + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } + + private class DataObjectMultiSerializer : LinqTestObject + { + [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] + [JsonPropertyName("numberValueDotNet")] + public double NumericField { get; set; } + + [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] + [JsonPropertyName("stringValueDotNet")] + public string StringField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectMultiSerializer() { } + + public DataObjectMultiSerializer(double numericField, string stringField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.id = id; + this.Pk = pk; + } + + public override string ToString() + { + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 30c29ec5db..7ff30b3cee 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -1,4 +1,4 @@ - + true true @@ -38,6 +38,10 @@ + + + + @@ -251,7 +255,19 @@ PreserveNewest - PreserveNewest + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest PreserveNewest From a0fb14f1a67a72ee8a0ddfff6f2e759624fe1993 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 19 Oct 2023 17:05:15 +0530 Subject: [PATCH 217/337] Release 3.36.0 : Fixes Client Telemetry Release Test (#4132) * Client Telemetry Release test fix * get endpoint from env variable * read client telemetry endpoint service from env * updated yaml --- .../ClientTelemetryReleaseTests.cs | 2 -- .../ClientTelemetryTestsBase.cs | 4 +--- azure-pipelines-official.yml | 1 + 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs index 7a54f490c0..07230e63a8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs @@ -4,11 +4,9 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { - using System; using System.Net.Http; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Fluent; - using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.VisualStudio.TestTools.UnitTesting; /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs index 3bb8a53c0c..85e3496731 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs @@ -15,11 +15,9 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Telemetry; - using Microsoft.Azure.Cosmos.Handler; using Microsoft.Azure.Documents; using Newtonsoft.Json.Linq; using Newtonsoft.Json; - using Documents.Rntbd; using System.Globalization; using System.Linq; using Cosmos.Util; @@ -27,7 +25,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public abstract class ClientTelemetryTestsBase : BaseCosmosClientHelper { - protected static readonly Uri telemetryServiceEndpoint = new Uri("http://dummy.telemetry.service/api/url"); + protected static readonly Uri telemetryServiceEndpoint = new Uri(ConfigurationManager.GetEnvironmentVariable("CLIENT_TELEMETRY_SERVICE_ENDPOINT", "https://dummy.url/api/clienttelemetry")); private static readonly List preferredRegionList = new List { diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index db77d4b0fd..2410dfb61f 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -54,6 +54,7 @@ stages: testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests env: COSMOSDB_ACCOUNT_CONNECTION_STRING: $(COSMOSDB_ACCOUNT_CONNECTION_STRING) # Real Account Connection String used by Integration Tests while running as part of release pipeline + CLIENT_TELEMETRY_SERVICE_ENDPOINT: $(CLIENT_TELEMETRY_SERVICE_ENDPOINT) # Client telemetry service url returned by configured account client config API - stage: displayName: Publish From e2ce570b38667373a31efc74abfcf00410b0e56f Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:49:50 -0700 Subject: [PATCH 218/337] Update CosmosItemTests.cs (#4141) --- .../Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index 860c780e41..75cf001b3b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -1286,7 +1286,7 @@ public async Task QuerySinglePartitionItemStreamTest(int perPKItemCount, int max Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); ServerSideCumulativeMetrics metrics = response.Diagnostics.GetQueryMetrics(); - Assert.IsTrue(metrics.PartitionedMetrics.Count == 1); + Assert.IsTrue(metrics.PartitionedMetrics.Count > 0); Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); @@ -3604,4 +3604,4 @@ private static async Task TestNonePKForNonExistingContainer(Container container) } } } -} \ No newline at end of file +} From b8d9225b986e49b40ca8421846b79d0050a6e6de Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 24 Oct 2023 00:21:57 +0530 Subject: [PATCH 219/337] Release 3.36.0: Fixes client config test and preview pipeline (#4149) (#4150) * Fixed client cpnfig test and preview pipeline * fix telemertry service step --- .../ClientConfigurationDiagnosticTest.cs | 7 +++++- azure-pipelines-official.yml | 22 +++++++++---------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs index 50b0125338..9a5c4255a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -45,7 +46,11 @@ public async Task ClientConfigTest() ItemResponse response = await this.Container.CreateItemAsync(testItem, new Cosmos.PartitionKey(testItem.pk)); Assert.IsNotNull(response.Diagnostics); ITrace trace = ((CosmosTraceDiagnostics)response.Diagnostics).Value; - Assert.AreEqual(trace.Data.Count, 1); +#if PREVIEW + Assert.AreEqual(trace.Data.Count, 2, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); // Distributed Tracing Id +#else + Assert.AreEqual(trace.Data.Count, 1, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); +#endif ClientConfigurationTraceDatum clientConfigurationTraceDatum = (ClientConfigurationTraceDatum)trace.Data["Client Configuration"]; Assert.IsNotNull(clientConfigurationTraceDatum.UserAgentContainer.UserAgent); } diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 2410dfb61f..4fad394780 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -4,10 +4,9 @@ pr: none variables: ReleaseArguments: ' --filter "TestCategory!=Quarantine" --verbosity normal ' - VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops BuildConfiguration: Release Packaging.EnableSBOMSigning: true - OS: 'Windows' + VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops stages: - stage: @@ -15,19 +14,18 @@ stages: jobs: - template: templates/static-tools.yml parameters: - BuildConfiguration: $(BuildConfiguration) - VmImage: $(VmImage) + BuildConfiguration: '${{ variables.BuildConfiguration }}' + VmImage: '${{ variables.VmImage }}' - template: templates/build-test.yml parameters: - BuildConfiguration: $(BuildConfiguration) - Arguments: $(ReleaseArguments) - VmImage: $(VmImage) + BuildConfiguration: '${{ variables.BuildConfiguration }}' + Arguments: '${{ variables.ReleaseArguments }}' + VmImage: '${{ variables.VmImage }}' - job: - displayName: TelemetryToService $(BuildConfiguration) + displayName: TelemetryToService ${{ variables.BuildConfiguration }} timeoutInMinutes: 120 - condition: and(succeeded(), eq('$(OS)', 'Windows')) pool: vmImage: windows-2019 @@ -48,7 +46,7 @@ stages: inputs: command: test projects: 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/*.csproj' - arguments: --filter "TestCategory=ClientTelemetryRelease" --verbosity normal --configuration $(BuildConfiguration) /p:OS=$(OS) + arguments: --filter "TestCategory=ClientTelemetryRelease" --verbosity normal --configuration ${{ variables.BuildConfiguration }} /p:OS=Windows nugetConfigPath: NuGet.config publishTestResults: true testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests @@ -62,7 +60,7 @@ stages: - template: templates/nuget-pack.yml parameters: BuildConfiguration: Release - VmImage: $(VmImage) + VmImage: '${{ variables.VmImage }}' ReleasePackage: true - OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/$(BuildConfiguration)/Microsoft.Azure.Cosmos' + OutputPath: '$(Build.ArtifactStagingDirectory)/bin/AnyCPU/Release/Microsoft.Azure.Cosmos' BlobVersion: $(BlobVersion) \ No newline at end of file From 6de10ddc98d45440d7fd334a55b2f1d171785f28 Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 24 Oct 2023 10:07:57 -0700 Subject: [PATCH 220/337] Query : Fixes querying conflicts (#4100) * Initial commit * Update * Updated the test * Updated the test * Sample fix; to validate Suite0. * Skipped the ConflictsTest (which depends on azure cosmosdb account) * Addressed comments * Added Unit Test. * Reverted unnecessary change. --- .../src/Query/v3Query/QueryIterator.cs | 10 +- .../Resource/Container/ContainerCore.Items.cs | 12 +- .../Query/ConflictsE2ETest.cs | 313 ++++++++++++++++++ .../CosmosConflictTests.cs | 45 ++- 4 files changed, 370 insertions(+), 10 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index 7dfcea9818..49407f7a4c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query { using System; using System.Collections.Generic; - using System.Linq; + using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; @@ -67,7 +67,8 @@ public static QueryIterator Create( bool isContinuationExpected, bool allowNonValueAggregateQuery, bool forcePassthrough, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + Documents.ResourceType resourceType) { if (queryRequestOptions == null) { @@ -77,7 +78,7 @@ public static QueryIterator Create( Guid correlatedActivityId = Guid.NewGuid(); CosmosQueryContextCore cosmosQueryContext = new CosmosQueryContextCore( client: client, - resourceTypeEnum: Documents.ResourceType.Document, + resourceTypeEnum: resourceType, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, @@ -90,7 +91,8 @@ public static QueryIterator Create( containerCore, client, correlatedActivityId, - queryRequestOptions); + queryRequestOptions, + resourceType: resourceType); DocumentContainer documentContainer = new DocumentContainer(networkAttachedDocumentContainer); CosmosElement requestContinuationToken; diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index fd9ad03b53..7bca68c8c8 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -375,7 +375,8 @@ public override async Task TryExecuteQueryAsync( isContinuationExpected: false, allowNonValueAggregateQuery: true, forcePassthrough: true, // Forcing a passthrough, since we don't want to get the query plan nor try to rewrite it. - partitionedQueryExecutionInfo: null); + partitionedQueryExecutionInfo: null, + resourceType: ResourceType.Document); return new QueryPlanIsSupportedResult(passthroughQueryIterator); } @@ -438,7 +439,8 @@ public override async Task TryExecuteQueryAsync( isContinuationExpected: false, allowNonValueAggregateQuery: true, forcePassthrough: false, - partitionedQueryExecutionInfo: queryPlan); + partitionedQueryExecutionInfo: queryPlan, + resourceType: ResourceType.Document); tryExecuteQueryResult = new QueryPlanIsSupportedResult(queryIterator); } @@ -834,7 +836,8 @@ public override FeedIteratorInternal GetItemQueryStreamIteratorInternal( isContinuationExpected: isContinuationExcpected, allowNonValueAggregateQuery: true, forcePassthrough: false, - partitionedQueryExecutionInfo: null); + partitionedQueryExecutionInfo: null, + resourceType: ResourceType.Document); } public override FeedIteratorInternal GetReadFeedIterator( @@ -872,7 +875,8 @@ public override FeedIteratorInternal GetReadFeedIterator( isContinuationExpected: false, allowNonValueAggregateQuery: true, forcePassthrough: false, - partitionedQueryExecutionInfo: null); + partitionedQueryExecutionInfo: null, + resourceType: resourceType); } else { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs new file mode 100644 index 0000000000..0edd95b22d --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs @@ -0,0 +1,313 @@ +namespace Microsoft.Azure.Cosmos.EmulatorTests.Query +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + /// + /// This is an end to end test that requires connecting to azure cosmos db accounts. + /// + [TestClass] + public class ConflictsE2ETest + { + private const int MaxRetries = 10; + + private const string Database = "Microsoft.Azure.Cosmos.EmulatorTests.Conflicts"; + private const string Collection = "ConflictsTest"; + private const string Key = ""; + private static readonly Endpoint Endpoint1 = new Endpoint("", ConnectionMode.Direct); + private static readonly Endpoint Endpoint2 = new Endpoint("", ConnectionMode.Direct); + + private class Endpoint + { + public Endpoint(string url, ConnectionMode connectionMode) + { + this.Url = url; + this.ConnectionMode = connectionMode; + } + + public ConnectionMode ConnectionMode { get; } + + public string Url { get; } + } + + /// + /// Tests querying conflicts in a cosmosdb collection. + /// + /// + /// This test uses ConflictsTestSettings.json for test configuration. + /// 1. An actual cosmosdb account in Azure is required for this test to run since none of the emulators do not allow for required test setup. + /// 2. Test setup will create a well known database (drop if it exists) and collection. + /// 3. The conditions for generating a conflict are subject to backend non-determinism. For increasing chances of generating a conflict: + /// - Ensure that the account is set to use eventual consistency + /// - Use more than 2 regions in the configuration. + /// + /// + [Ignore] + [TestMethod] + public async Task TestConflicts() + { + Assert.IsTrue(!string.IsNullOrWhiteSpace(Key), "Please specify a valid key"); + + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers = await this.CreateDatabaseAndContainer( + Database, + Collection, + Key, + Endpoint1, + Endpoint2); + + await this.InsertWithoutConflict(cosmosContainers); + await this.InsertWithConflict(cosmosContainers); + await this.VerifyConflict(cosmosContainers); + } + + private async Task VerifyConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + { + List> conflictsUsingDefaultIterator = await this.GetConflictsUsingDefaultIterator(cosmosContainers); + List> conflictsUsingQueryWithoutOptions = await this.GetConflictsUsingQueryWithoutOptions(cosmosContainers); + + Assert.AreEqual(conflictsUsingDefaultIterator.Count, conflictsUsingQueryWithoutOptions.Count, "Conflict count should be identical"); + for (int i = 0; i < conflictsUsingDefaultIterator.Count; i++) + { + Assert.AreEqual(string.Join(",", conflictsUsingDefaultIterator[i].ToString()), string.Join(",", conflictsUsingQueryWithoutOptions[i].ToString())); + } + } + + private async Task>> GetConflictsUsingQueryWithoutOptions(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.GetConflicts( + cosmosContainers, + query: @"SELECT * FROM c", + options: null); + + private async Task>> GetConflictsUsingDefaultIterator(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.GetConflicts(cosmosContainers, query: null, options: null); + + private async Task>> GetConflicts( + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers, + string query, + QueryRequestOptions options) + { + List> allConflicts = new List>(); + foreach ((CosmosClient client, Container container) pair in cosmosContainers) + { + List clientReportedConflicts = new List(); + FeedIterator iterator = pair.container.Conflicts.GetConflictQueryIterator(queryText: query, requestOptions: options); + while (iterator.HasMoreResults) + { + FeedResponse page = await iterator.ReadNextAsync(); + clientReportedConflicts.AddRange(page); + } + + allConflicts.Add(clientReportedConflicts); + } + + // Ideally each client will observe exactly 1 conflict. However this is dependent upon regional (eventual) consistency and underlying race condition with this test. + Assert.IsTrue(allConflicts.Any(list => list.Count == 1), "Exactly 1 conflict is expected!"); + + return allConflicts; + } + + /// + /// Inserts a document that is guaranteed to not conflict with any other. + /// + private async Task InsertWithoutConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.InsertFromMultipleClients( + cosmosContainers, + payloadFormat: @"{{""id"" : ""NoConflict_{0}"", ""type"":""noconflict"", ""pk"":""1""}}", + clientFilter: clientIndex => clientIndex == 0); + + /// + /// Insert documents until exactly one conflict is generated. + /// This is a non-deterministic operation (in terms of both duration and outcome) due to backend's behavior. + /// It will terminate the test based on simple heuristic if desired outcome cannot be achieved. + /// + private async Task InsertWithConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.InsertFromMultipleClients( + cosmosContainers, + payloadFormat: @"{{""id"" : ""Conflict_{0}"", ""type"":""conflict"", ""pk"":""1"", ""index"":{1}}}"); + + /// + /// Inserts items from multiple clients. + /// + /// Containers to insert documents to. + /// Format of the document with placeholders for insertion iteration (one round across all clients) and optional client index. + /// Optional filter that determines whether a client should be used for insertion. + /// + private async Task InsertFromMultipleClients( + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers, + string payloadFormat, + Func clientFilter = null) + { + PartitionKey partitionKey = new PartitionKey("1"); + bool retry = true; + int i = 0; + + // To offset the backend specific non-determinism, we change the order in which we use containers to create the items. + // Other mitigations to explore include having more than 2 regions and ordering those randomly while creating items. + IEnumerable containersInOrder = cosmosContainers.Select(pair => pair.Container); + IEnumerable containersInReverseOrder = cosmosContainers.Reverse().Select(pair => pair.Container); + while (retry) + { + int clientIndex = 0; + List responses = new List(); + IEnumerable containers = + i % 2 == 1 ? + containersInOrder : + containersInReverseOrder; + foreach (Container container in containers) + { + bool useClient = clientFilter == null || clientFilter(clientIndex); + if (useClient) + { + ResponseMessage response = await this.CreateItem( + container, + string.Format(payloadFormat, i, clientIndex), + partitionKey); + responses.Add(response); + } + + clientIndex++; + } + + Assert.IsTrue(responses.Count > 0, "At least one client should attempt document creation!"); + + // Sometimes the conflicts may be detected (and rejected) by the backend with status code = Conflict synchronously with the request. + // We keep retrying until all clients are able to "successfully" create item in the backend which will be later detected as conflict. + retry = responses.Any(response => response.StatusCode != HttpStatusCode.Created); + i++; + + // Even with the measures above, the conflicts may continue to get detected (and rejected) by the backend perpetually in a synchronous manner. + // After 3000 tries (which can take upto 5 minutes for 2 regions), we determine that the test is inconclusive, since the setup failed. + if (i > 3000) + { + string expectedResponses = string.Join(",", Enumerable.Repeat("Created", cosmosContainers.Count)); + string actualResponses = string.Join(",", responses.Select(response => response.StatusCode.ToString())); + Assert.Fail($@"Document insertion failed after 3000 tries. Please rerun the test. Expected responses : ""{expectedResponses}"". Actual responses : ""{actualResponses}""."); + } + } + } + + private async Task CreateItem(Container container, string payload, PartitionKey partitionKey) + { + return await this.ExecuteOperationWithRetry( + MaxRetries, + () => container.CreateItemStreamAsync( + this.ToStream(payload), + partitionKey), + // Since the test also creates the database and document collection, first few read/write operations on the collection can return NotFound. + responseMessage => responseMessage.StatusCode == HttpStatusCode.NotFound); + } + + private Stream ToStream(string stringValue) + { + MemoryStream stream = new(); + StreamWriter writer = new(stream); + writer.Write(stringValue); + writer.Flush(); + stream.Position = 0; + return stream; + } + + /// + /// Instantiates client and container pointing to each region. Creates (drops if exists) database, container using one region's connections. + /// + /// Returns the CosmosClient and Container pointing to each region. + private async Task> CreateDatabaseAndContainer( + string database, + string collection, + string key, + params Endpoint[] endpoints) + { + Assert.IsTrue(endpoints?.Length > 1, "At least one endpoint must be specified"); + + HashSet endpointSet = new HashSet(endpoints.Select(endpoint => endpoint.Url)); + Assert.AreEqual(endpoints.Length, endpointSet.Count, "Please specify unique endpoints!"); + + int endpointIndex = 0; + List<(CosmosClient Client, Container Container)> clients = new(); + foreach (Endpoint endpoint in endpoints) + { + CosmosClient client = new CosmosClient(endpoint.Url, key, new CosmosClientOptions { ConnectionMode = endpoint.ConnectionMode }); + + if (endpointIndex == 0) + { + ConsistencyLevel consistencyLevel = await client.GetAccountConsistencyLevelAsync(); + Assert.AreEqual(ConsistencyLevel.Eventual, consistencyLevel, "Only account with eventual consistency is supported by this test."); + } + + DatabaseResponse databaseResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => client.CreateDatabaseIfNotExistsAsync(database)); + if (endpointIndex == 0 && databaseResponse.StatusCode == HttpStatusCode.OK) + { + await databaseResponse.Database.DeleteAsync(); + databaseResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => client.CreateDatabaseIfNotExistsAsync(database)); + } + + HttpStatusCode expectedStatus = endpointIndex == 0 ? HttpStatusCode.Created : HttpStatusCode.OK; + Assert.AreEqual(expectedStatus, databaseResponse.StatusCode, + $"Endpoint#: {endpointIndex}, Endpoint : {endpoint.Url}. CreateDatabaseIfNotExistsAsync received unexpected response."); + + ContainerResponse containerResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => databaseResponse.Database.CreateContainerIfNotExistsAsync( + new ContainerProperties(collection, "/pk") + { + ConflictResolutionPolicy = new ConflictResolutionPolicy() { Mode = ConflictResolutionMode.Custom } + })); + Assert.AreEqual(expectedStatus, databaseResponse.StatusCode, + $"Endpoint#: {endpointIndex}, Endpoint : {endpoint.Url}. CreateContainerIfNotExistsAsync received unexpected response."); + + clients.Add((client, containerResponse.Container)); + endpointIndex++; + } + + return clients; + } + + private async Task ExecuteOperationWithRetry(int maxRetryCount, Func> operation, Func shouldRetryWithoutException = null) + { + for (int i = 0; i < maxRetryCount; i++) + { + try + { + T result = await operation(); + if (shouldRetryWithoutException != null && shouldRetryWithoutException(result)) + { + if (i + 1 < maxRetryCount) + { + await Task.Delay(i * 1000); + continue; + } + + break; + } + + return result; + } + catch (Exception ex) + { + Console.WriteLine($"Attempt {i + 1}. Max Retries {maxRetryCount}. Exception: {ex}."); + if (i + 1 < maxRetryCount) + { + Thread.Sleep(i * 1000); + } + else + { + throw; + } + } + } + + throw new InvalidOperationException($"Operation failed after retries!"); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs index 2bb48fc75b..50adab3aef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs @@ -5,15 +5,19 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; + using System.IO; + using System.Net; + using System.Text; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json.Linq; - using Microsoft.Azure.Cosmos.Tracing; [TestClass] public class CosmosConflictTests @@ -33,6 +37,43 @@ public async Task ConflictsFeedSetsPartitionKeyRangeIdentity() } } + [TestMethod] + public async Task QueryConflicts() + { + ContainerInternal container = CosmosConflictTests.GetMockedContainer(async (request, cancellationToken) => { + Assert.AreEqual(ResourceType.Conflict, request.ResourceType); + ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK) + { + Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Conflicts"": [{ ""id"": ""Test""}]}")) + }; + return responseMessage; + }); + + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator(); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator("SELECT * FROM c"); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator( + queryText: "SELECT * FROM c", + requestOptions: new QueryRequestOptions { MaxItemCount = 1 }); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + } + [TestMethod] public async Task ReadCurrentGetsCorrectRID() { From 8253befe99d92c489f8ca7ef6111511fb48dac6b Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 24 Oct 2023 23:40:21 +0530 Subject: [PATCH 221/337] Fixes changelog typo and date (#4155) --- changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 8b08e37210..18cac46b8a 100644 --- a/changelog.md +++ b/changelog.md @@ -13,7 +13,7 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -### [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-17 +### [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-24 #### Fixed - [4039](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4039) GatewayAddressCache: Fixes Unobserved Exception During Background Address Refresh (#4039) @@ -30,7 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > Note: Refer this [3983](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3983) for API signature and default values. - [4119](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4119) TriggerOperation: Adds Upsert Operation Support(#4119) -### [3.356.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0-preview) - 2023-10-17 +### [3.36.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0-preview) - 2023-10-24 #### Added - [4056](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4056) Client Telemetry: Adds new public APIs (#4056). WARNING: This is breaking change for preview SDK From 42cc6812489ce98b964ad54b90d68568ca67ba57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 19:05:30 +0000 Subject: [PATCH 222/337] Bump Azure.Identity in /Microsoft.Azure.Cosmos.Samples/Usage/Encryption (#4136) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.5.0 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.5.0...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../Usage/Encryption/Encryption.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj index 75a2a94922..3d29248400 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj @@ -8,7 +8,7 @@ latest - + From 083df87e6ebf8cfc25092e8642846f34273158f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 24 Oct 2023 22:10:10 +0000 Subject: [PATCH 223/337] Bump Azure.Identity (#4135) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.5.0 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.5.0...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Usage/ReEncryption/ReEncryption.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj index e29aaac1ea..54c70c4ec6 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj @@ -8,7 +8,7 @@ latest - + From a4836ff452eead0ec6f7c2525bc97b3aaf994f41 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 27 Oct 2023 11:31:24 -0700 Subject: [PATCH 224/337] Per Partition Automatic Failover: Fixes Gateway 503 Cold Start Issue (#4073) * Code changes to add retry logic for GW returned 503.9002. * Revert "Code changes to add retry logic for GW returned 503.9002." This reverts commit 53ef5f3c1b038d14dbb1473cafa18223b33af2ce. * Code changes to clean up the PPAF retry logic fix. * Code changes to add retry logic for GW returned 503.9002. * Revert "Code changes to add retry logic for GW returned 503.9002." This reverts commit 53ef5f3c1b038d14dbb1473cafa18223b33af2ce. * Code changes to clean up the PPAF retry logic fix. * Code changes to revert location cache changes. * Code changes ro revert location cache changes. * Code changes to fix some of the failing tests. * Code changes to fix unit tests. * Code changes to add unit tests for client options. * Code changes to draft docs for PPAF design approach. * Code changes to add SDK side design docs for PPAF. * Code changes to modify the PPAF design. * Code changes to fix unit test. * Code changes to rename test name. * Code changes to add some cosmetic changes. * Code changes to enable retry on write for all regions in single master accounts. * Code changes to add code comments. * Code changes to clean up and handle endpoints in location cache. * Code changes to fix unit tests. Added detailed code comments. * Code changes to clean up the account read endpoints generation logic. * Code changes to fix unit tests. * Code changes to disable retry when ppaf is not enabled. Also validated application preferred region. * Code changes to fix unit tests. * Code changes to update md file. * Code changes to remove chache expiry check for account read endpoints. * Code changes to fix unit test. * Code changes to fix more tests. * Code changes to address review comments. * Code changes to fix verbaige in design document. --- .../src/ClientRetryPolicy.cs | 22 ++- .../src/CosmosClientOptions.cs | 12 +- Microsoft.Azure.Cosmos/src/RetryPolicy.cs | 9 +- .../src/Routing/GlobalEndpointManager.cs | 6 +- .../GlobalPartitionEndpointManagerCore.cs | 15 +- .../src/Routing/IGlobalEndpointManager.cs | 2 + .../src/Routing/LocationCache.cs | 41 +++-- .../src/Util/ConfigurationManager.cs | 28 +++- .../ClientRetryPolicyTests.cs | 10 +- .../CosmosClientOptionsUnitTests.cs | 149 +++++++++++++++++- .../LocationCacheTests.cs | 59 +++---- .../GlobalPartitionEndpointManagerTests.cs | 76 +++++++-- ...GlobalPartitionEndpointManagerUnitTests.cs | 4 +- docs/PerPartitionAutomaticFailoverDesign.md | 28 ++++ 14 files changed, 378 insertions(+), 83 deletions(-) create mode 100644 docs/PerPartitionAutomaticFailoverDesign.md diff --git a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs index 2933baa1a9..7cef90d541 100644 --- a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs @@ -28,6 +28,7 @@ internal sealed class ClientRetryPolicy : IDocumentClientRetryPolicy private readonly GlobalEndpointManager globalEndpointManager; private readonly GlobalPartitionEndpointManager partitionKeyRangeLocationCache; private readonly bool enableEndpointDiscovery; + private readonly bool isPertitionLevelFailoverEnabled; private int failoverRetryCount; private int sessionTokenRetryCount; @@ -41,8 +42,9 @@ internal sealed class ClientRetryPolicy : IDocumentClientRetryPolicy public ClientRetryPolicy( GlobalEndpointManager globalEndpointManager, GlobalPartitionEndpointManager partitionKeyRangeLocationCache, + RetryOptions retryOptions, bool enableEndpointDiscovery, - RetryOptions retryOptions) + bool isPertitionLevelFailoverEnabled) { this.throttlingRetry = new ResourceThrottleRetryPolicy( retryOptions.MaxRetryAttemptsOnThrottledRequests, @@ -55,6 +57,7 @@ public ClientRetryPolicy( this.sessionTokenRetryCount = 0; this.serviceUnavailableRetryCount = 0; this.canUseMultipleWriteLocations = false; + this.isPertitionLevelFailoverEnabled = isPertitionLevelFailoverEnabled; } /// @@ -247,8 +250,7 @@ private async Task ShouldRetryInternalAsync( } // Received 503 due to client connect timeout or Gateway - if (statusCode == HttpStatusCode.ServiceUnavailable - && ClientRetryPolicy.IsRetriableServiceUnavailable(subStatusCode)) + if (statusCode == HttpStatusCode.ServiceUnavailable) { DefaultTrace.TraceWarning("ClientRetryPolicy: ServiceUnavailable. Refresh cache and retry. Failed Location: {0}; ResourceAddress: {1}", this.documentServiceRequest?.RequestContext?.LocationEndpointToRoute?.ToString() ?? string.Empty, @@ -265,12 +267,6 @@ private async Task ShouldRetryInternalAsync( return null; } - private static bool IsRetriableServiceUnavailable(SubStatusCodes? subStatusCode) - { - return subStatusCode == SubStatusCodes.Unknown || - (subStatusCode.HasValue && subStatusCode.Value.IsSDKGeneratedSubStatus()); - } - private async Task ShouldRetryOnEndpointFailureAsync( bool isReadRequest, bool markBothReadAndWriteAsUnavailable, @@ -390,7 +386,7 @@ private ShouldRetryResult ShouldRetryOnSessionNotAvailable() /// /// For a ServiceUnavailable (503.0) we could be having a timeout from Direct/TCP locally or a request to Gateway request with a similar response due to an endpoint not yet available. - /// We try and retry the request only if there are other regions available. + /// We try and retry the request only if there are other regions available. The retry logic is applicable for single master write accounts as well. /// private ShouldRetryResult ShouldRetryOnServiceUnavailable() { @@ -401,9 +397,11 @@ private ShouldRetryResult ShouldRetryOnServiceUnavailable() } if (!this.canUseMultipleWriteLocations - && !this.isReadRequest) + && !this.isReadRequest + && !this.isPertitionLevelFailoverEnabled) { - // Write requests on single master cannot be retried, no other regions available + // Write requests on single master cannot be retried if partition level failover is disabled. + // This means there are no other regions available to serve the writes. return ShouldRetryResult.NoRetry(); } diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 60ae9298b0..a90a2e04a6 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -608,7 +608,7 @@ public Func HttpClientFactory /// /// Enable partition key level failover /// - internal bool EnablePartitionLevelFailover { get; set; } = false; + internal bool EnablePartitionLevelFailover { get; set; } = ConfigurationManager.IsPartitionLevelFailoverEnabled(defaultValue: false); /// /// Quorum Read allowed with eventual consistency account or consistent prefix account. @@ -752,6 +752,7 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) { this.ValidateDirectTCPSettings(); this.ValidateLimitToEndpointSettings(); + this.ValidatePartitionLevelFailoverSettings(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -888,6 +889,15 @@ private void ValidateLimitToEndpointSettings() } } + private void ValidatePartitionLevelFailoverSettings() + { + if (this.EnablePartitionLevelFailover + && (this.ApplicationPreferredRegions == null || this.ApplicationPreferredRegions.Count == 0)) + { + throw new ArgumentException($"{nameof(this.ApplicationPreferredRegions)} is required when {nameof(this.EnablePartitionLevelFailover)} is enabled."); + } + } + private void ValidateDirectTCPSettings() { string settingName = string.Empty; diff --git a/Microsoft.Azure.Cosmos/src/RetryPolicy.cs b/Microsoft.Azure.Cosmos/src/RetryPolicy.cs index 4ec05a3b65..47e64f0cbc 100644 --- a/Microsoft.Azure.Cosmos/src/RetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/RetryPolicy.cs @@ -13,17 +13,19 @@ internal sealed class RetryPolicy : IRetryPolicyFactory private readonly GlobalPartitionEndpointManager partitionKeyRangeLocationCache; private readonly GlobalEndpointManager globalEndpointManager; private readonly bool enableEndpointDiscovery; + private readonly bool isPertitionLevelFailoverEnabled; private readonly RetryOptions retryOptions; /// /// Initialize the instance of the RetryPolicy class /// public RetryPolicy( - GlobalEndpointManager globalEndpointManager, + GlobalEndpointManager globalEndpointManager, ConnectionPolicy connectionPolicy, GlobalPartitionEndpointManager partitionKeyRangeLocationCache) { this.enableEndpointDiscovery = connectionPolicy.EnableEndpointDiscovery; + this.isPertitionLevelFailoverEnabled = connectionPolicy.EnablePartitionLevelFailover; this.globalEndpointManager = globalEndpointManager; this.retryOptions = connectionPolicy.RetryOptions; this.partitionKeyRangeLocationCache = partitionKeyRangeLocationCache; @@ -37,10 +39,11 @@ public IDocumentClientRetryPolicy GetRequestPolicy() ClientRetryPolicy clientRetryPolicy = new ClientRetryPolicy( this.globalEndpointManager, this.partitionKeyRangeLocationCache, + this.retryOptions, this.enableEndpointDiscovery, - this.retryOptions); + this.isPertitionLevelFailoverEnabled); return clientRetryPolicy; } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index 956212d5a2..bcaae809f4 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -89,9 +89,11 @@ public GlobalEndpointManager(IDocumentClientInternal owner, ConnectionPolicy con } } - public ReadOnlyCollection ReadEndpoints => this.locationCache.ReadEndpoints; + public ReadOnlyCollection ReadEndpoints => this.locationCache.ReadEndpoints; + + public ReadOnlyCollection AccountReadEndpoints => this.locationCache.AccountReadEndpoints; - public ReadOnlyCollection WriteEndpoints => this.locationCache.WriteEndpoints; + public ReadOnlyCollection WriteEndpoints => this.locationCache.WriteEndpoints; public int PreferredLocationCount => this.connectionPolicy.PreferredLocations != null ? this.connectionPolicy.PreferredLocations.Count : 0; diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs index a4ab1221e6..fe2e256601 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs @@ -134,11 +134,20 @@ public override bool TryMarkEndpointUnavailableForPartitionKeyRange( PartitionKeyRangeFailoverInfo partionFailover = this.PartitionKeyRangeToLocation.Value.GetOrAdd( partitionKeyRange, - (_) => new PartitionKeyRangeFailoverInfo(failedLocation)); - + (_) => new PartitionKeyRangeFailoverInfo(failedLocation)); + + // For any single master write accounts, the next locations to fail over will be the read regions configured at the account level. + // For multi master write accounts, since all the regions are treated as write regions, the next locations to fail over + // will be the preferred read regions that are configured in the application preferred regions in the CosmosClientOptions. + bool isSingleMasterWriteAccount = !this.globalEndpointManager.CanUseMultipleWriteLocations(request); + + ReadOnlyCollection nextLocations = isSingleMasterWriteAccount + ? this.globalEndpointManager.AccountReadEndpoints + : this.globalEndpointManager.ReadEndpoints; + // Will return true if it was able to update to a new region if (partionFailover.TryMoveNextLocation( - locations: this.globalEndpointManager.ReadEndpoints, + locations: nextLocations, failedLocation: failedLocation)) { DefaultTrace.TraceInformation("Partition level override added to new location. PartitionKeyRange: {0}, failedLocation: {1}, new location: {2}", diff --git a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs index dd3d8a2611..83f49cf0de 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs @@ -13,6 +13,8 @@ internal interface IGlobalEndpointManager : IDisposable { ReadOnlyCollection ReadEndpoints { get; } + ReadOnlyCollection AccountReadEndpoints { get; } + ReadOnlyCollection WriteEndpoints { get; } int PreferredLocationCount { get; } diff --git a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs index 9c6308d8b6..4480df1826 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs @@ -101,6 +101,11 @@ public ReadOnlyCollection ReadEndpoints } } + /// + /// Gets list of account level read endpoints. + /// + public ReadOnlyCollection AccountReadEndpoints => this.locationInfo.AccountReadEndpoints; + /// /// Gets list of write endpoints ordered by /// 1. Preferred location @@ -491,20 +496,35 @@ private void UpdateLocationCache( if (readLocations != null) { - ReadOnlyCollection availableReadLocations; - nextLocationInfo.AvailableReadEndpointByLocation = this.GetEndpointByLocation(readLocations, out availableReadLocations); + nextLocationInfo.AvailableReadEndpointByLocation = this.GetEndpointByLocation( + readLocations, + out ReadOnlyCollection availableReadLocations); + nextLocationInfo.AvailableReadLocations = availableReadLocations; + nextLocationInfo.AccountReadEndpoints = nextLocationInfo.AvailableReadEndpointByLocation.Select(x => x.Value).ToList().AsReadOnly(); } if (writeLocations != null) { - ReadOnlyCollection availableWriteLocations; - nextLocationInfo.AvailableWriteEndpointByLocation = this.GetEndpointByLocation(writeLocations, out availableWriteLocations); + nextLocationInfo.AvailableWriteEndpointByLocation = this.GetEndpointByLocation( + writeLocations, + out ReadOnlyCollection availableWriteLocations); + nextLocationInfo.AvailableWriteLocations = availableWriteLocations; } - nextLocationInfo.WriteEndpoints = this.GetPreferredAvailableEndpoints(nextLocationInfo.AvailableWriteEndpointByLocation, nextLocationInfo.AvailableWriteLocations, OperationType.Write, this.defaultEndpoint); - nextLocationInfo.ReadEndpoints = this.GetPreferredAvailableEndpoints(nextLocationInfo.AvailableReadEndpointByLocation, nextLocationInfo.AvailableReadLocations, OperationType.Read, nextLocationInfo.WriteEndpoints[0]); + nextLocationInfo.WriteEndpoints = this.GetPreferredAvailableEndpoints( + endpointsByLocation: nextLocationInfo.AvailableWriteEndpointByLocation, + orderedLocations: nextLocationInfo.AvailableWriteLocations, + expectedAvailableOperation: OperationType.Write, + fallbackEndpoint: this.defaultEndpoint); + + nextLocationInfo.ReadEndpoints = this.GetPreferredAvailableEndpoints( + endpointsByLocation: nextLocationInfo.AvailableReadEndpointByLocation, + orderedLocations: nextLocationInfo.AvailableReadLocations, + expectedAvailableOperation: OperationType.Read, + fallbackEndpoint: nextLocationInfo.WriteEndpoints[0]); + this.lastCacheUpdateTimestamp = DateTime.UtcNow; DefaultTrace.TraceInformation("Current WriteEndpoints = ({0}) ReadEndpoints = ({1})", @@ -534,8 +554,7 @@ private ReadOnlyCollection GetPreferredAvailableEndpoints(ReadOnlyDictionar foreach (string location in currentLocationInfo.PreferredLocations) { - Uri endpoint; - if (endpointsByLocation.TryGetValue(location, out endpoint)) + if (endpointsByLocation.TryGetValue(location, out Uri endpoint)) { if (this.IsEndpointUnavailable(endpoint, expectedAvailableOperation)) { @@ -560,9 +579,8 @@ private ReadOnlyCollection GetPreferredAvailableEndpoints(ReadOnlyDictionar { foreach (string location in orderedLocations) { - Uri endpoint; if (!string.IsNullOrEmpty(location) && // location is empty during manual failover - endpointsByLocation.TryGetValue(location, out endpoint)) + endpointsByLocation.TryGetValue(location, out Uri endpoint)) { endpoints.Add(endpoint); } @@ -634,6 +652,7 @@ public DatabaseAccountLocationsInfo(ReadOnlyCollection preferredLocation this.AvailableWriteEndpointByLocation = new ReadOnlyDictionary(new Dictionary(StringComparer.OrdinalIgnoreCase)); this.AvailableReadEndpointByLocation = new ReadOnlyDictionary(new Dictionary(StringComparer.OrdinalIgnoreCase)); this.WriteEndpoints = new List() { defaultEndpoint }.AsReadOnly(); + this.AccountReadEndpoints = new List() { defaultEndpoint }.AsReadOnly(); this.ReadEndpoints = new List() { defaultEndpoint }.AsReadOnly(); } @@ -645,6 +664,7 @@ public DatabaseAccountLocationsInfo(DatabaseAccountLocationsInfo other) this.AvailableWriteEndpointByLocation = other.AvailableWriteEndpointByLocation; this.AvailableReadEndpointByLocation = other.AvailableReadEndpointByLocation; this.WriteEndpoints = other.WriteEndpoints; + this.AccountReadEndpoints = other.AccountReadEndpoints; this.ReadEndpoints = other.ReadEndpoints; } @@ -655,6 +675,7 @@ public DatabaseAccountLocationsInfo(DatabaseAccountLocationsInfo other) public ReadOnlyDictionary AvailableReadEndpointByLocation { get; set; } public ReadOnlyCollection WriteEndpoints { get; set; } public ReadOnlyCollection ReadEndpoints { get; set; } + public ReadOnlyCollection AccountReadEndpoints { get; set; } } [Flags] diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 748f81833a..0b7786d8c3 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -9,12 +9,19 @@ namespace Microsoft.Azure.Cosmos internal static class ConfigurationManager { /// - /// A read-only string containing the environment variablename for enabling replica validation. - /// This will eventually be removed oncereplica valdiatin is enabled by default for both preview + /// A read-only string containing the environment variable name for enabling replica validation. + /// This will eventually be removed once replica valdiatin is enabled by default for both preview /// and GA. /// internal static readonly string ReplicaConnectivityValidationEnabled = "AZURE_COSMOS_REPLICA_VALIDATION_ENABLED"; + /// + /// A read-only string containing the environment variable name for enabling per partition automatic failover. + /// This will eventually be removed once per partition automatic failover is enabled by default for both preview + /// and GA. + /// + internal static readonly string PartitionLevelFailoverEnabled = "AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED"; + public static T GetEnvironmentVariable(string variable, T defaultValue) { string value = Environment.GetEnvironmentVariable(variable); @@ -50,5 +57,22 @@ public static bool IsReplicaAddressValidationEnabled( variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, defaultValue: replicaValidationDefaultValue); } + + /// + /// Gets the boolean value of the partition level failover environment variable. Note that, partition level failover + /// is disabled by default for both preview and GA releases. The user can set the respective environment variable + /// 'AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED' to override the value for both preview and GA. The method will + /// eventually be removed, once partition level failover is enabled by default for both preview and GA. + /// + /// A boolean field containing the default value for partition level failover. + /// A boolean flag indicating if partition level failover is enabled. + public static bool IsPartitionLevelFailoverEnabled( + bool defaultValue) + { + return ConfigurationManager + .GetEnvironmentVariable( + variable: ConfigurationManager.PartitionLevelFailoverEnabled, + defaultValue: defaultValue); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs index 0851952f40..cf1c739388 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs @@ -47,7 +47,7 @@ public void MultimasterMetadataWriteRetryTest() multimasterMetadataWriteRetryTest: true); - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery, new RetryOptions()); + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery, false); //Creates a metadata write request DocumentServiceRequest request = this.CreateRequest(false, true); @@ -102,8 +102,8 @@ public void Http503SubStatusHandelingTests(int testCode) isPreferredLocationsListEmpty: true); //Create Retry Policy - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery, new RetryOptions()); - + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery, false); + CancellationToken cancellationToken = new CancellationToken(); Exception serviceUnavailableException = new Exception(); Mock nameValueCollection = new Mock(); @@ -216,8 +216,8 @@ private async Task ValidateConnectTimeoutTriggersClientRetryPolicy( replicatedResourceClient.GoneAndRetryWithRetryTimeoutInSecondsOverride = 1; this.partitionKeyRangeLocationCache = GlobalPartitionEndpointManagerNoOp.Instance; - - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(mockDocumentClientContext.GlobalEndpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery: true, new RetryOptions()); + + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(mockDocumentClientContext.GlobalEndpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery: true, isPertitionLevelFailoverEnabled: false); INameValueCollection headers = new DictionaryNameValueCollection(); headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.BoundedStaleness.ToString()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 04d51ea06c..b625858c09 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos.Tests using System.Linq; using System.Net; using System.Net.Http; - using Cosmos.Telemetry; using global::Azure.Core; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; @@ -116,8 +115,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithBulkExecution(true) .WithSerializerOptions(cosmosSerializerOptions) - .WithConsistencyLevel(consistencyLevel) - .WithPartitionLevelFailoverEnabled(); + .WithConsistencyLevel(consistencyLevel); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); clientOptions = cosmosClient.ClientOptions; @@ -140,7 +138,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(object.ReferenceEquals(webProxy, clientOptions.WebProxy)); Assert.IsTrue(clientOptions.AllowBulkExecution); Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); - Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); + Assert.IsFalse(clientOptions.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue && clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); //Verify GetConnectionPolicy returns the correct values @@ -155,7 +153,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, policy.RetryOptions.MaxRetryAttemptsOnThrottledRequests); Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds); Assert.AreEqual((Documents.ConsistencyLevel)consistencyLevel, clientOptions.GetDocumentsConsistencyLevel()); - Assert.IsTrue(policy.EnablePartitionLevelFailover); + Assert.IsFalse(policy.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; @@ -206,6 +204,147 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is missing, then the client + /// initialization should throw an argument exception and fail. This should hold true for both environment variable and CosmosClientOptions. + /// + [TestMethod] + [Owner("dkunda")] + [DataRow(true, DisplayName = "Validate that when enevironment variable is used to enable PPAF, the outcome of the test should be same.")] + [DataRow(false, DisplayName = "Validate that when CosmosClientOptions is used to enable PPAF, the outcome of the test should be same.")] + public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredRegionsNotSet_ShouldThrowArgumentException(bool useEnvironmentVariable) + { + try + { + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, "True"); + } + + string endpoint = AccountEndpoint; + string key = MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey; + TimeSpan requestTimeout = TimeSpan.FromDays(1); + string userAgentSuffix = "testSuffix"; + RequestHandler preProcessHandler = new TestHandler(); + ApiType apiType = ApiType.Sql; + int maxRetryAttemptsOnThrottledRequests = 9999; + TimeSpan maxRetryWaitTime = TimeSpan.FromHours(6); + CosmosSerializationOptions cosmosSerializerOptions = new CosmosSerializationOptions() + { + IgnoreNullValues = true, + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase, + }; + + Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + CosmosClientBuilder cosmosClientBuilder = new( + accountEndpoint: endpoint, + authKeyOrResourceToken: key); + + cosmosClientBuilder + .WithConnectionModeDirect() + .WithRequestTimeout(requestTimeout) + .WithApplicationName(userAgentSuffix) + .AddCustomHandlers(preProcessHandler) + .WithApiType(apiType) + .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) + .WithSerializerOptions(cosmosSerializerOptions) + .WithConsistencyLevel(consistencyLevel); + + if (!useEnvironmentVariable) + { + cosmosClientBuilder + .WithPartitionLevelFailoverEnabled(); + } + + ArgumentException exception = Assert.ThrowsException(() => cosmosClientBuilder.Build()); + + Assert.AreEqual( + expected: "ApplicationPreferredRegions is required when EnablePartitionLevelFailover is enabled.", + actual: exception.Message); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, null); + } + } + + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is provided, then the client + /// initialization should be successful. This holds true for both environment variable and CosmosClientOptions. + /// + [TestMethod] + [Owner("dkunda")] + [DataRow(true, DisplayName = "Validate that when enevironment variable is used to enable PPAF, the outcome of the test should be same.")] + [DataRow(false, DisplayName = "Validate that when CosmosClientOptions is used to enable PPAF, the outcome of the test should be same.")] + public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredRegionsSet_ShouldInitializeSuccessfully(bool useEnvironmentVariable) + { + try + { + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, "True"); + } + + string endpoint = AccountEndpoint; + string key = MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey; + TimeSpan requestTimeout = TimeSpan.FromDays(1); + string userAgentSuffix = "testSuffix"; + RequestHandler preProcessHandler = new TestHandler(); + ApiType apiType = ApiType.Sql; + int maxRetryAttemptsOnThrottledRequests = 9999; + TimeSpan maxRetryWaitTime = TimeSpan.FromHours(6); + CosmosSerializationOptions cosmosSerializerOptions = new CosmosSerializationOptions() + { + IgnoreNullValues = true, + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase, + }; + + Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + CosmosClientBuilder cosmosClientBuilder = new( + accountEndpoint: endpoint, + authKeyOrResourceToken: key); + + cosmosClientBuilder + .WithConnectionModeDirect() + .WithRequestTimeout(requestTimeout) + .WithApplicationName(userAgentSuffix) + .AddCustomHandlers(preProcessHandler) + .WithApiType(apiType) + .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) + .WithSerializerOptions(cosmosSerializerOptions) + .WithConsistencyLevel(consistencyLevel) + .WithPartitionLevelFailoverEnabled() + .WithApplicationPreferredRegions( + new List() + { + Regions.NorthCentralUS, + Regions.WestUS, + Regions.EastAsia, + }); + + CosmosClientOptions clientOptions = cosmosClientBuilder.Build().ClientOptions; + + Assert.AreEqual(ConnectionMode.Direct, clientOptions.ConnectionMode); + Assert.AreEqual(requestTimeout, clientOptions.RequestTimeout); + Assert.AreEqual(userAgentSuffix, clientOptions.ApplicationName); + Assert.AreEqual(preProcessHandler, clientOptions.CustomHandlers[0]); + Assert.AreEqual(apiType, clientOptions.ApiType); + Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, clientOptions.MaxRetryAttemptsOnRateLimitedRequests); + Assert.AreEqual(maxRetryWaitTime, clientOptions.MaxRetryWaitTimeOnRateLimitedRequests); + Assert.AreEqual(cosmosSerializerOptions.IgnoreNullValues, clientOptions.SerializerOptions.IgnoreNullValues); + Assert.AreEqual(cosmosSerializerOptions.PropertyNamingPolicy, clientOptions.SerializerOptions.PropertyNamingPolicy); + Assert.AreEqual(cosmosSerializerOptions.Indented, clientOptions.SerializerOptions.Indented); + Assert.IsFalse(clientOptions.AllowBulkExecution); + Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); + Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); + Assert.IsNotNull(clientOptions.ApplicationPreferredRegions); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, null); + } + } + [TestMethod] public void VerifyConsisentencyLevels() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs index 8273897374..b93107b302 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs @@ -131,7 +131,7 @@ private async Task ValidateRetryOnSessionNotAvailabeWithEndpointDiscoveryDisable useMultipleWriteLocations: useMultipleWriteLocations, enableEndpointDiscovery: enableEndpointDiscovery, isPreferredLocationsListEmpty: isPreferredLocationsListEmpty); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { @@ -174,14 +174,16 @@ await BackoffRetryUtility.ExecuteAsync( } private ClientRetryPolicy CreateClientRetryPolicy( - bool enableEndpointDiscovery, + bool enableEndpointDiscovery, + bool partitionLevelFailoverEnabled, GlobalEndpointManager endpointManager) { return new ClientRetryPolicy( endpointManager, this.partitionKeyRangeLocationCache, - enableEndpointDiscovery, - new RetryOptions()); + new RetryOptions(), + enableEndpointDiscovery, + isPertitionLevelFailoverEnabled: partitionLevelFailoverEnabled); } [TestMethod] @@ -203,7 +205,7 @@ private async Task ValidateRetryOnSessionNotAvailabeWithDisableMultipleWriteLoca isPreferredLocationsListEmpty: isPreferredLocationsListEmpty); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: true, isMasterResourceType: false)) { @@ -281,7 +283,7 @@ private async Task ValidateRetryOnReadSessionNotAvailabeWithEnableMultipleWriteL preferedRegionListOverride: preferredList); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: true, isMasterResourceType: false)) { @@ -357,7 +359,7 @@ private async Task ValidateRetryOnWriteSessionNotAvailabeWithEnableMultipleWrite preferedRegionListOverride: preferredList); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: false, isMasterResourceType: false)) { @@ -429,7 +431,7 @@ public async Task ValidateRetryOnWriteForbiddenExceptionAsync() isPreferredLocationsListEmpty: false); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: false, isMasterResourceType: false)) { @@ -501,7 +503,7 @@ private async Task ValidateRetryOnDatabaseAccountNotFoundAsync(bool enableMultip isPreferredLocationsListEmpty: false); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); int expectedRetryCount = isReadRequest || enableMultipleWriteLocations ? 2 : 1; @@ -606,7 +608,7 @@ private async Task ValidateRetryOnHttpExceptionAsync(bool enableMultipleWriteLoc enforceSingleMasterSingleWriteLocation: true); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { @@ -676,22 +678,22 @@ await BackoffRetryUtility.ExecuteAsync( } [DataTestMethod] - [DataRow(true, false, false, false, false, DisplayName = "Read request - Single master - no preferred locations - should NOT retry")] - [DataRow(false, false, false, false, false, DisplayName = "Write request - Single master - no preferred locations - should NOT retry")] - [DataRow(true, true, false, false, false, DisplayName = "Read request - Multi master - no preferred locations - should NOT retry")] - [DataRow(false, true, false, false, false, DisplayName = "Write request - Multi master - no preferred locations - should NOT retry")] - [DataRow(true, false, true, true, false, DisplayName = "Read request - Single master - with preferred locations - should retry")] - [DataRow(false, false, true, false, false, DisplayName = "Write request - Single master - with preferred locations - should NOT retry")] - [DataRow(true, true, true, true, false, DisplayName = "Read request - Multi master - with preferred locations - should retry")] - [DataRow(false, true, true, true, false, DisplayName = "Write request - Multi master - with preferred locations - should retry")] - [DataRow(true, false, false, false, true, DisplayName = "Read request - Single master - no preferred locations - should NOT retry")] - [DataRow(false, false, false, false, true, DisplayName = "Write request - Single master - no preferred locations - should NOT retry")] - [DataRow(true, true, false, false, true, DisplayName = "Read request - Multi master - no preferred locations - should NOT retry")] - [DataRow(false, true, false, false, true, DisplayName = "Write request - Multi master - no preferred locations - should NOT retry")] - [DataRow(true, false, true, true, true, DisplayName = "Read request - Single master - with preferred locations - should retry")] - [DataRow(false, false, true, false, true, DisplayName = "Write request - Single master - with preferred locations - should NOT retry")] - [DataRow(true, true, true, true, true, DisplayName = "Read request - Multi master - with preferred locations - should retry")] - [DataRow(false, true, true, true, true, DisplayName = "Write request - Multi master - with preferred locations - should retry")] + [DataRow(true, false, false, false, false, DisplayName = "Read request - Single master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(false, false, false, false, false, DisplayName = "Write request - Single master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, true, false, false, false, DisplayName = "Read request - Multi master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(false, true, false, false, false, DisplayName = "Write request - Multi master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, false, true, true, false, DisplayName = "Read request - Single master - with preferred locations - without partition level failover - should retry")] + [DataRow(false, false, true, false, false, DisplayName = "Write request - Single master - with preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, true, true, true, false, DisplayName = "Read request - Multi master - with preferred locations - without partition level failover - should retry")] + [DataRow(false, true, true, true, false, DisplayName = "Write request - Multi master - with preferred locations - without partition level failover - should retry")] + [DataRow(true, false, false, false, true, DisplayName = "Read request - Single master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, false, false, false, true, DisplayName = "Write request - Single master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(true, true, false, false, true, DisplayName = "Read request - Multi master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, true, false, false, true, DisplayName = "Write request - Multi master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(true, false, true, true, true, DisplayName = "Read request - Single master - with preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, false, true, true, true, DisplayName = "Write request - Single master - with preferred locations - with partition level failover - should retry")] + [DataRow(true, true, true, true, true, DisplayName = "Read request - Multi master - with preferred locations - with partition level failover - should retry")] + [DataRow(false, true, true, true, true, DisplayName = "Write request - Multi master - with preferred locations - with partition level failover - should retry")] public async Task ClientRetryPolicy_ValidateRetryOnServiceUnavailable( bool isReadRequest, bool useMultipleWriteLocations, @@ -714,8 +716,9 @@ public async Task ClientRetryPolicy_ValidateRetryOnServiceUnavailable( preferedRegionListOverride: preferredList, enforceSingleMasterSingleWriteLocation: true); - endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); + + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: enablePartitionLevelFailover, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs index a075d439f6..05cbfc8384 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs @@ -106,9 +106,13 @@ public async Task TestWriteForbiddenScenarioAsync() } } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list provided, if the first + /// region is unavailable for write, then the write should eventually get retried to the next preferred region. + /// [TestMethod] [Timeout(10000)] - public async Task TestServiceUnavailableExceptionScenarioAsync() + public async Task CreateItemAsync_WithPreferredRegionsAndServiceUnavailableForFirstPreferredRegion_ShouldRetryAndSucceedToTheNextPreferredRegion() { GlobalPartitionEndpointManagerTests.SetupAccountAndCacheOperations( out string secondaryRegionNameForUri, @@ -168,16 +172,7 @@ public async Task TestServiceUnavailableExceptionScenarioAsync() Pk = "TestPk" }; - // First create will fail because it is not certain if the payload was sent or not. - try - { - await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); - Assert.Fail("Should throw an exception"); - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.ServiceUnavailable) - { - Assert.IsNotNull(ce); - } + await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); ItemResponse response = await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); @@ -203,6 +198,65 @@ public async Task TestServiceUnavailableExceptionScenarioAsync() Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is missing, then the client + /// initialization should throw an argument exception and fail. + /// + [TestMethod] + public void CreateItemAsync_WithNoPreferredRegionsAndServiceUnavailable_ShouldThrowArgumentException() + { + GlobalPartitionEndpointManagerTests.SetupAccountAndCacheOperations( + out string secondaryRegionNameForUri, + out string globalEndpoint, + out string secondaryRegionEndpiont, + out string databaseName, + out string containerName, + out ResourceId containerResourceId, + out Mock mockHttpHandler, + out IReadOnlyList primaryRegionPartitionKeyRangeIds, + out TransportAddressUri primaryRegionprimaryReplicaUri); + + Mock mockTransport = new Mock(MockBehavior.Strict); + + MockSetupsHelper.SetupServiceUnavailableException( + mockTransport, + primaryRegionprimaryReplicaUri); + + mockTransport.Setup(x => x.Dispose()); + + // Partition key ranges are the same in both regions so the SDK + // does not need to go the secondary to get the partition key ranges. + // Only the addresses need to be mocked on the secondary + MockSetupsHelper.SetupAddresses( + mockHttpHandler: mockHttpHandler, + partitionKeyRangeId: primaryRegionPartitionKeyRangeIds.First(), + regionEndpoint: secondaryRegionEndpiont, + regionName: secondaryRegionNameForUri, + containerResourceId: containerResourceId, + primaryReplicaUri: out TransportAddressUri secondaryRegionPrimaryReplicaUri); + + MockSetupsHelper.SetupCreateItemResponse( + mockTransport, + secondaryRegionPrimaryReplicaUri); + + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + EnablePartitionLevelFailover = true, + ConsistencyLevel = Cosmos.ConsistencyLevel.Strong, + HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)), + TransportClientHandlerFactory = (original) => mockTransport.Object, + }; + + ArgumentException exception = Assert.ThrowsException(() => new CosmosClient( + globalEndpoint, + Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())), + cosmosClientOptions)); + + Assert.AreEqual( + expected: "ApplicationPreferredRegions is required when EnablePartitionLevelFailover is enabled.", + actual: exception.Message); + } + [TestMethod] [Timeout(10000)] public async Task TestRequestTimeoutExceptionScenarioAsync() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs index 8f1da91c53..06ca0a4c2c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs @@ -73,13 +73,15 @@ public void VerifyAllReadRegionsAreVisited(int numOfReadRegions) Mock mockEndpointManager = new Mock(MockBehavior.Strict); GlobalPartitionEndpointManagerCore failoverManager = new GlobalPartitionEndpointManagerCore(mockEndpointManager.Object); - List readRegions = new List(); + List readRegions = new (), writeRegions = new(); for(int i = 0; i < numOfReadRegions; i++) { readRegions.Add(new Uri($"https://localhost:{i}/")); } mockEndpointManager.Setup(x => x.ReadEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); + mockEndpointManager.Setup(x => x.AccountReadEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); + mockEndpointManager.Setup(x => x.WriteEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); // Create a random pk range PartitionKeyRange partitionKeyRange = new PartitionKeyRange() diff --git a/docs/PerPartitionAutomaticFailoverDesign.md b/docs/PerPartitionAutomaticFailoverDesign.md new file mode 100644 index 0000000000..fa1425c5d3 --- /dev/null +++ b/docs/PerPartitionAutomaticFailoverDesign.md @@ -0,0 +1,28 @@ +# Working Principles for Per Partition Automatic Failover + +## Table of Contents + +* [Scope.](#scope) +* [Background.](#background) +* [How Does the SDK know Which Region to Fail Over.](#how-does-the-sdk-know-which-region-to-fail-over) +* [References.](#references) + +## Scope + +The scope of the per partition automatic failover design document is applicable for the Cosmos .NET SDK configured only for `Direct` mode at the moment. + +## Background + +Today, the partition level failovers are applicable for multi master write acounts, for a simple reason. If one of the write region fails with a write forbidden 403 exception, then the SDK has the knowledge (by looking up the `ApplicationPreferredRegions`) of the other regions to failover. With the per partition automatic failover, if a partition is in quorum loss, then the backend automatically marks another region as the write region, based on the account configuration. Therefore, any retry for the write requests, to the next preferred region should be successful. + +This idea extends the SDK's retry logic to retry the write requests for single master write accounts, for any service unavailable (status codes 503) errors. + +## How Does the SDK know Which Region to Fail Over + +Right now, the .NET SDK depends upon the `GlobalPartitionEndpointManagerCore` to resolve the endpoints. There is a method `TryMarkEndpointUnavailableForPartitionKeyRange()` within the class, that is responsible to add the override by iterating over the next read regions. This is how the .NET SDK knows which region to fail over. + +## References + +- [SDK not retrying with next region in case address resolution call to Gateway call fails with 503.](https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2475521/) +- [First client write request after failover is failing with 503(21005)](https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2492475/) +- [PPAF Testing in Test, Staging and Prod.](https://microsoft.sharepoint.com/:w:/r/teams/DocumentDB/_layouts/15/doc2.aspx?sourcedoc=%7B7587D267-212F-47BE-AAD6-18FC53482B68%7D&file=PPAF%20Testing%20in%20Test%2C%20Staging%20and%20Prod.docx&action=default&mobileredirect=true) \ No newline at end of file From 646d0061099dbc3e5702f8f5b329c6accc7c9ac3 Mon Sep 17 00:00:00 2001 From: sc978345 <115834537+sc978345@users.noreply.github.com> Date: Mon, 30 Oct 2023 12:20:04 -0500 Subject: [PATCH 225/337] [Internal] Query: Fixes optimalPageSize logic for OFFSET LIMIT in ORDER BY queries (#4158) * Fix logic in CosmosQueryExecutionContextFactory where we determine optimal page size for ORDER BY queries that have an OFFSET/LIMIT clause. Previously, the logic was only being applied to TOP and not OFFSET/LIMIT. * Changes based on PR feedback * Change based on PR feedback --- .../CosmosQueryExecutionContextFactory.cs | 15 +- .../Core/QueryPlan/QueryPartitionProvider.cs | 3 + .../Query/Pipeline/FullPipelineTests.cs | 250 +++++++++++++++++- 3 files changed, 260 insertions(+), 8 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index adb19c303f..4c43b83e58 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -551,7 +551,20 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx if (queryInfo.HasOrderBy) { int top; - if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0) + if (queryInfo.HasTop && (partitionedQueryExecutionInfo.QueryInfo.Top.Value > 0)) + { + top = partitionedQueryExecutionInfo.QueryInfo.Top.Value; + } + else if (queryInfo.HasLimit && (partitionedQueryExecutionInfo.QueryInfo.Limit.Value > 0)) + { + top = (partitionedQueryExecutionInfo.QueryInfo.Offset ?? 0) + partitionedQueryExecutionInfo.QueryInfo.Limit.Value; + } + else + { + top = 0; + } + + if (top > 0) { // All partitions should initially fetch about 1/nth of the top value. long pageSizeWithTop = (long)Math.Min( diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs index c62a65b27a..6f95673d80 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -290,6 +291,8 @@ internal TryCatch TryGetPartitionedQueryE MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr }); + Debug.Assert(!(queryInfoInternal.QueryInfo.HasTop && queryInfoInternal.QueryInfo.HasLimit)); + return TryCatch.FromResult(queryInfoInternal); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index 0f8f6f2be7..d717b86f89 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -7,19 +7,27 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline using System; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.IO; using System.Linq; + using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; using Microsoft.Azure.Cosmos.Tests.Pagination; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; using Newtonsoft.Json; [TestClass] @@ -46,7 +54,7 @@ public async Task TestMerge() MergeTestUtil mergeTest = new MergeTestUtil(); mergeTest.DocumentContainer = await CreateDocumentContainerAsync( documents: documents, - numPartitions: 2, + numSplits: 2, failureConfigs: new FlakyDocumentContainer.FailureConfigs( inject429s: false, injectEmptyPages: false, @@ -249,6 +257,160 @@ public async Task Tracing() Assert.AreEqual(numTraces, rootTrace.Children.Count); } + [TestMethod] + public async Task OffsetLimitPageSize() + { + List documents = new List(); + for (int i = 0; i < 1100; i++) + { + documents.Add(CosmosObject.Parse($"{{\"pk\" : {i} }}")); + } + + MockInMemoryContainer mockInMemoryContainer = new MockInMemoryContainer(new InMemoryContainer(partitionKeyDefinition)); + DocumentContainer documentContainer = await CreateDocumentContainerAsync(documents, mockInMemoryContainer, numSplits: 4); + + // OFFSET/LIMIT with ORDER BY + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 315, expectedResults: 500, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10000 LIMIT 5000", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 70, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 65, expectedResults: 0, mockInMemoryContainer, documentContainer); + + // OFFSET/LIMIT without ORDER BY + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 10 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 0 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 100 LIMIT 0", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); + + // TOP with ORDER BY + await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c ORDER BY c.pk", expectedPageSize: 5, expectedResults: 5, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + + // TOP without ORDER BY + await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c", expectedPageSize: 1000, expectedResults: 5, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + } + + private async Task TestPageSizeAsync(string query, int expectedPageSize, int expectedResults, MockInMemoryContainer inMemoryContainer, DocumentContainer documentContainer) + { + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext( + query, + partitionKeyDefinition, + null, + new QueryRequestOptions()); + + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); + + List elements = new List(); + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + { + TryCatch tryGetQueryPage = queryPipelineStage.Current; + tryGetQueryPage.ThrowIfFailed(); + + elements.AddRange(tryGetQueryPage.Result.Documents); + } + + Assert.AreEqual(expected: expectedPageSize, actual: inMemoryContainer.PageSizeSpecified); + Assert.AreEqual(expected: expectedResults, actual: elements.Count); + } + + private static Tuple CreateInputParamsAndQueryContext( + string query, + PartitionKeyDefinition partitionKeyDefinition, + Cosmos.PartitionKey? partitionKeyValue, + QueryRequestOptions queryRequestOptions) + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(query), Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( + sqlQuerySpec: new SqlQuerySpec(query), + initialUserContinuationToken: null, + initialFeedRange: null, + maxConcurrency: queryRequestOptions.MaxConcurrency, + maxItemCount: queryRequestOptions.MaxItemCount, + maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, + partitionKey: partitionKeyValue, + properties: new Dictionary() { { "x-ms-query-partitionkey-definition", partitionKeyDefinition } }, + partitionedQueryExecutionInfo: null, + executionEnvironment: null, + returnResultsInDeterministicOrder: null, + forcePassthrough: false, + enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, + testInjections: queryRequestOptions.TestSettings); + + string databaseId = "db1234"; + string resourceLink = $"dbs/{databaseId}/colls"; + + const string suffix = "-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF"; + + List partitionKeyRanges = new List + { + new PartitionKeyRange() { MinInclusive = Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, MaxExclusive = "1F" + suffix }, + new PartitionKeyRange() { MinInclusive = "1F" + suffix, MaxExclusive = "3F" + suffix }, + new PartitionKeyRange() { MinInclusive = "3F" + suffix, MaxExclusive = "5F" + suffix }, + new PartitionKeyRange() { MinInclusive = "5F" + suffix, MaxExclusive = "7F" + suffix }, + new PartitionKeyRange() { MinInclusive = "7F" + suffix, MaxExclusive = "9F" + suffix }, + new PartitionKeyRange() { MinInclusive = "9F" + suffix, MaxExclusive = "BF" + suffix }, + new PartitionKeyRange() { MinInclusive = "BF" + suffix, MaxExclusive = "DF" + suffix }, + new PartitionKeyRange() { MinInclusive = "DF" + suffix, MaxExclusive = Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey }, + }; + + Mock mockClient = new Mock(); + + mockClient.Setup(x => x.GetTargetPartitionKeyRangesAsync( + It.IsAny(), + It.IsAny(), + It.IsAny>>(), + It.IsAny(), + It.IsAny())) + .Returns((string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) => Task.FromResult(partitionKeyRanges)); + + mockClient.Setup(x => x.TryGetPartitionedQueryExecutionInfoAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns((SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) => + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; + return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); + } + ); + + CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( + client: mockClient.Object, + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); + + return Tuple.Create(inputParameters, cosmosQueryContextCore); + } + internal static async Task> ExecuteQueryAsync( string query, IReadOnlyList documents, @@ -329,13 +491,13 @@ private static async Task> DrainWithStateAsync(string query, return elements; } - internal static Task CreateDocumentContainerAsync( + internal static Task CreateDocumentContainerAsync( IReadOnlyList documents, - int numPartitions = 3, + int numSplits = 3, FlakyDocumentContainer.FailureConfigs failureConfigs = null) { IMonadicDocumentContainer monadicDocumentContainer = CreateMonadicDocumentContainerAsync(failureConfigs); - return CreateDocumentContainerAsync(documents, monadicDocumentContainer, numPartitions); + return CreateDocumentContainerAsync(documents, monadicDocumentContainer, numSplits); } internal static IMonadicDocumentContainer CreateMonadicDocumentContainerAsync(FlakyDocumentContainer.FailureConfigs failureConfigs) @@ -349,14 +511,14 @@ internal static IMonadicDocumentContainer CreateMonadicDocumentContainerAsync(Fl return monadicDocumentContainer; } - internal static async Task CreateDocumentContainerAsync( + internal static async Task CreateDocumentContainerAsync( IReadOnlyList documents, IMonadicDocumentContainer monadicDocumentContainer, - int numPartitions) + int numSplits) { DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - for (int i = 0; i < numPartitions; i++) + for (int i = 0; i < numSplits; i++) { IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( trace: NoOpTrace.Singleton, @@ -461,5 +623,79 @@ public async Task ShouldReturnFailure() } } } + + private class MockInMemoryContainer : IMonadicDocumentContainer + { + public int? PageSizeSpecified { get; private set; } + public IMonadicDocumentContainer MonadicDocumentContainer { get; } + + public MockInMemoryContainer(IMonadicDocumentContainer documentContainer) + { + this.MonadicDocumentContainer = documentContainer; + this.PageSizeSpecified = null; + } + + public void Reset() + { + this.PageSizeSpecified = null; + } + + public Task> MonadicChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicChangeFeedAsync(feedRangeState, changeFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicCreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicCreateItemAsync(payload, cancellationToken); + } + + public Task>> MonadicGetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetChildRangeAsync(feedRange, trace, cancellationToken); + } + + public Task>> MonadicGetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetFeedRangesAsync(trace, cancellationToken); + } + + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetResourceIdentifierAsync(trace, cancellationToken); + } + + public Task MonadicMergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicMergeAsync(feedRange1, feedRange2, cancellationToken); + } + + public Task> MonadicQueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + this.PageSizeSpecified = queryPaginationOptions.PageSizeLimit; + + return this.MonadicDocumentContainer.MonadicQueryAsync(sqlQuerySpec, feedRangeState, queryPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicReadFeedAsync(feedRangeState, readFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicReadItemAsync(CosmosElement partitionKey, string identifier, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicReadItemAsync(partitionKey, identifier, cancellationToken); + } + + public Task MonadicRefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicRefreshProviderAsync(trace, cancellationToken); + } + + public Task MonadicSplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicSplitAsync(feedRange, cancellationToken); + } + } } } From 9175f51fa500ebd5e91196359680891bfd913be0 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 31 Oct 2023 22:07:48 +0530 Subject: [PATCH 226/337] [Internal] Client Telemetry: Adds telemetry contract (#4161) * add tests * fix tests * remove unreated files --- CODEOWNERS | 1 + .../Contracts/ContractEnforcement.cs | 39 +- .../Contracts/ContractEnforcementTests.cs | 10 + .../Contracts/DotNetSDKTelemetryAPI.json | 356 ++++++++++++++++++ .../Microsoft.Azure.Cosmos.Tests.csproj | 3 + UpdateContracts.ps1 | 8 + 6 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json diff --git a/CODEOWNERS b/CODEOWNERS index 6015906184..d7c4173831 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,4 +20,5 @@ Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts @kirillg @ki Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Contracts @kirillg @kirankumarkolli @ealsur @FabianMeiswinkel Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @Azure/azure-cosmosdb-lt Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @Azure/azure-cosmosdb-lt +Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json @Azure/azure-cosmosdb-lt CODEOWNERS @kirillg @kirankumarkolli diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs index 6c71504738..f0e127495a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs @@ -130,7 +130,7 @@ private static string GenerateNameWithFieldAttributes(FieldInfo fieldInfo) $"{nameof(fieldInfo.IsStatic)}:{(fieldInfo.IsStatic ? bool.TrueString : bool.FalseString)};"; } - private static TypeTree BuildTypeTree(TypeTree root, Type[] types) + private static TypeTree BuildTypeTree(TypeTree root, Type[] types, BindingFlags bindingflags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) { IEnumerable subclassTypes = types.Where((type) => type.IsSubclassOf(root.Type)).OrderBy(o => o.FullName, invariantComparer); foreach (Type subclassType in subclassTypes) @@ -139,7 +139,7 @@ private static TypeTree BuildTypeTree(TypeTree root, Type[] types) } IEnumerable> memberInfos = - root.Type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + root.Type.GetMembers(bindingflags) .Select(memberInfo => new KeyValuePair($"{memberInfo}{string.Join("-", ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.CustomAttributes))}", memberInfo)) .OrderBy(o => o.Key, invariantComparer); foreach (KeyValuePair memberInfo in memberInfos) @@ -203,6 +203,18 @@ public static void ValidateContractContainBreakingChanges( ContractEnforcement.ValidateJsonAreSame(localJson, baselineJson); } + public static void ValidateTelemetryContractContainBreakingChanges( + string dllName, + string baselinePath, + string breakingChangesPath) + { + string localTelemetryJson = GetCurrentTelemetryContract(dllName); + File.WriteAllText($"Contracts/{breakingChangesPath}", localTelemetryJson); + + string telemetryBaselineJson = GetBaselineContract(baselinePath); + ContractEnforcement.ValidateJsonAreSame(localTelemetryJson, telemetryBaselineJson); + } + public static void ValidatePreviewContractContainBreakingChanges( string dllName, string officialBaselinePath, @@ -238,6 +250,29 @@ public static string GetCurrentContract(string dllName) return localJson; } + public static string GetCurrentTelemetryContract(string dllName) + { + List nonTelemetryModels = new List + { + "AzureVMMetadata", + "Compute" + }; + + TypeTree locally = new TypeTree(typeof(object)); + Assembly assembly = ContractEnforcement.GetAssemblyLocally(dllName); + Type[] exportedTypes = assembly.GetTypes().Where(t => + t!= null && + t.Namespace != null && + t.Namespace.Contains("Microsoft.Azure.Cosmos.Telemetry.Models") && + !nonTelemetryModels.Contains(t.Name)) + .ToArray(); + + ContractEnforcement.BuildTypeTree(locally, exportedTypes, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); + + string localJson = JsonConvert.SerializeObject(locally, Formatting.Indented); + return localJson; + } + public static string GetBaselineContract(string baselinePath) { string baselineFile = File.ReadAllText("Contracts/" + baselinePath); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs index 2e3a6457b3..c4fdacc939 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs @@ -10,6 +10,7 @@ public class ContractEnforcementTests { private const string DllName = "Microsoft.Azure.Cosmos.Client"; private const string OfficialBaselinePath = "DotNetSDKAPI.json"; + private const string OfficialTelemetryBaselinePath = "DotNetSDKTelemetryAPI.json"; #if PREVIEW [TestMethod] @@ -30,6 +31,15 @@ public void ContractChanges() baselinePath: OfficialBaselinePath, breakingChangesPath: "DotNetSDKAPIChanges.json"); } + + [TestMethod] + public void TelemetryContractChanges() + { + ContractEnforcement.ValidateTelemetryContractContainBreakingChanges( + dllName: DllName, + baselinePath: OfficialTelemetryBaselinePath, + breakingChangesPath: "DotNetSDKTelemetryAPIChanges.json"); + } #endif [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json new file mode 100644 index 0000000000..bfc2bb20e6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json @@ -0,0 +1,356 @@ +{ + "Subclasses": { + "Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo;Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.ClientTelemetryProperties;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)[Newtonsoft.Json.JsonConstructorAttribute()]": { + "Type": "Constructor", + "Attributes": [ + "JsonConstructorAttribute" + ], + "MethodInfo": "[Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)[Newtonsoft.Json.JsonConstructorAttribute()], Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)]" + }, + "Void Write(Newtonsoft.Json.JsonWriter)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void Write(Newtonsoft.Json.JsonWriter);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double])": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double]), Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double])]" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": { + "Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo;Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + }, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 get_SubStatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 SubStatusCode[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"subStatusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "Int32 SubStatusCode;CanRead:True;CanWrite:False;Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo Copy()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo Copy();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_StatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] StatusCode[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"statusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] StatusCode;CanRead:True;CanWrite:False;System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo), Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)]" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double GetP99Latency()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double GetP99Latency();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double GetSampleCount()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double GetSampleCount();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 get_SubStatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCodeForSampler()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCodeForSampler();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 SubStatusCode[Newtonsoft.Json.JsonPropertyAttribute(\"subStatusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "Int32 SubStatusCode;CanRead:True;CanWrite:True;Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_SubStatusCode(Int32);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] Metrics[Newtonsoft.Json.JsonPropertyAttribute(\"metricInfo\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] Metrics;CanRead:True;CanWrite:True;System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_StatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] StatusCode[Newtonsoft.Json.JsonPropertyAttribute(\"statusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] StatusCode;CanRead:True;CanWrite:True;System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_StatusCode(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String ContainerName[Newtonsoft.Json.JsonPropertyAttribute(\"containerName\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String ContainerName;CanRead:True;CanWrite:True;System.String get_ContainerName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ContainerName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String DatabaseName[Newtonsoft.Json.JsonPropertyAttribute(\"databaseName\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String DatabaseName;CanRead:True;CanWrite:True;System.String get_DatabaseName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DatabaseName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_ContainerName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_ContainerName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_DatabaseName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_DatabaseName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Operation()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Operation();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Resource()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Resource();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Uri()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Uri();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Operation[Newtonsoft.Json.JsonPropertyAttribute(\"operation\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Operation;CanRead:True;CanWrite:True;System.String get_Operation();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Operation(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Resource[Newtonsoft.Json.JsonPropertyAttribute(\"resource\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Resource;CanRead:True;CanWrite:True;System.String get_Resource();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Resource(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String ToString()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String ToString();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Uri[Newtonsoft.Json.JsonPropertyAttribute(\"uri\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Uri;CanRead:True;CanWrite:True;System.String get_Uri();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Uri(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_ContainerName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_ContainerName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DatabaseName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DatabaseName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Operation(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Operation(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Resource(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Resource(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_StatusCode(System.Nullable`1[System.Int32])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_StatusCode(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_SubStatusCode(Int32)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_SubStatusCode(Int32);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Uri(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Uri(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo), Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)]" + } + }, + "NestedTypes": {} + } + }, + "Members": { + "System.Object MemberwiseClone()[System.Runtime.CompilerServices.NullableContextAttribute((Byte)1)]-[System.Runtime.CompilerServices.IntrinsicAttribute()]": { + "Type": "Method", + "Attributes": [ + "IntrinsicAttribute", + "NullableContextAttribute" + ], + "MethodInfo": "System.Object MemberwiseClone();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void Finalize()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void Finalize();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 6f1657f37c..81d0b6797a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -271,6 +271,9 @@ Always + + Always + PreserveNewest diff --git a/UpdateContracts.ps1 b/UpdateContracts.ps1 index 513860136e..cece416f54 100644 --- a/UpdateContracts.ps1 +++ b/UpdateContracts.ps1 @@ -13,6 +13,14 @@ if(!(Test-Path -Path $updatedContractFile)){ Write-Output ("Updated contract " + $updatedContractFile) } +$updatedContractFile = ".\Microsoft.Azure.Cosmos\tests\Microsoft.Azure.Cosmos.Tests\bin\Release\net6.0\Contracts\DotNetSDKTelemetryAPIChanges.json" +if(!(Test-Path -Path $updatedContractFile)){ + Write-Error ("The contract file did not get updated with the build. Please fix the test to output the contract file: " + $updatedContractFile) +}else{ + Copy-Item -Path $updatedContractFile -Destination ".\Microsoft.Azure.Cosmos\tests\Microsoft.Azure.Cosmos.Tests\Contracts\DotNetSDKTelemetryAPI.json" + Write-Output ("Updated contract " + $updatedContractFile) +} + $updatedContractFolder = ".\Microsoft.Azure.Cosmos\tests\Microsoft.Azure.Cosmos.Tests\bin\Release\net6.0\BaselineTest\TestOutput\*" if(!(Test-Path -Path $updatedContractFolder)){ Write-Error ("The contract file did not get updated with the build. Please fix the test to output the contract file: " + $updatedContractFile) From 1f81b54a7a9cc3106a39bfd4aa84afb91778c741 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Nov 2023 06:53:33 +0530 Subject: [PATCH 227/337] Client Encryption: Adds Azure.Identity from 1.1.1 to 1.10.2 (#4134) * Bump Azure.Identity in /Microsoft.Azure.Cosmos.Encryption.Custom/src Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.1.1 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.1.1...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Update Microsoft.Azure.Cosmos.Encryption.Custom.csproj Updated the Azure.Core version --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index a9f729c9ab..306cd923a9 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 Microsoft.Azure.Cosmos.Encryption.Custom @@ -35,8 +35,8 @@ - - + + From f379919702a5cc5a7464c402a6704dac5397746d Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Fri, 3 Nov 2023 09:33:39 -0700 Subject: [PATCH 228/337] [Internal] Query: Removes ForcePassThrough support (#4160) * Remove passThrough from the codebase * Updated TestOptimisticDirectExecutionQueryAsync() to remove all aspects of passThrough from it * Undoing previous change * Removed forcePassThrough from FullPipelineTests.cs * Undoing changes to remove PassThrough * Undoing passThrough removal pt2 * Undoing changes to SanityQueryTests.cs * Updated TestTryExecuteQueryHelper() * Updated comment * Changed boolean location * Removed TryExecuteQueryAsync() * Fixed indentation --- .../CosmosQueryExecutionContextFactory.cs | 66 +++------- .../src/Query/v3Query/QueryIterator.cs | 2 - .../Resource/Container/ContainerCore.Items.cs | 117 ------------------ .../Resource/Container/ContainerInternal.cs | 9 -- .../Query/SanityQueryTests.cs | 99 --------------- ...misticDirectExecutionQueryBaselineTests.cs | 1 - .../Query/Pipeline/FullPipelineTests.cs | 1 - 7 files changed, 18 insertions(+), 277 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 4c43b83e58..08e6292a03 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -161,29 +161,7 @@ private static async Task> TryCreateCoreContextAsy } PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; - if (inputParameters.ForcePassthrough) - { - partitionedQueryExecutionInfo = new PartitionedQueryExecutionInfo() - { - QueryInfo = new QueryInfo() - { - Aggregates = null, - DistinctType = DistinctQueryType.None, - GroupByAliases = null, - GroupByAliasToAggregateType = null, - GroupByExpressions = null, - HasSelectValue = false, - Limit = null, - Offset = null, - OrderBy = null, - OrderByExpressions = null, - RewrittenQuery = null, - Top = null, - }, - QueryRanges = new List>(), - }; - } - else if (queryPlanFromContinuationToken != null) + if (queryPlanFromContinuationToken != null) { partitionedQueryExecutionInfo = queryPlanFromContinuationToken; } @@ -270,26 +248,7 @@ private static async Task> TryCreateFromPartitione inputParameters.InitialFeedRange, trace); - bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue - || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) - && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); - bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates - && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct - && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; - bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; - - bool clientStreamingQuery = - serverStreamingQuery - && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy - && !partitionedQueryExecutionInfo.QueryInfo.HasTop - && !partitionedQueryExecutionInfo.QueryInfo.HasLimit - && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; - bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; - - bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; - TryCatch tryCreatePipelineStage; - Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( inputParameters, partitionedQueryExecutionInfo, @@ -311,6 +270,22 @@ private static async Task> TryCreateFromPartitione } else { + bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue + || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) + && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); + bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates + && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct + && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; + bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; + + bool clientStreamingQuery = serverStreamingQuery + && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy + && !partitionedQueryExecutionInfo.QueryInfo.HasTop + && !partitionedQueryExecutionInfo.QueryInfo.HasLimit + && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; + bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; + bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; + if (createPassthroughQuery) { SetTestInjectionPipelineType(inputParameters, Passthrough); @@ -432,7 +407,6 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx inputParameters.PartitionedQueryExecutionInfo, inputParameters.ExecutionEnvironment, inputParameters.ReturnResultsInDeterministicOrder, - inputParameters.ForcePassthrough, inputParameters.EnableOptimisticDirectExecution, inputParameters.TestInjections); } @@ -746,7 +720,7 @@ private static void SetTestInjectionPipelineType(InputParameters inputParameters { responseStats.PipelineType = TestInjections.PipelineType.Specialized; } - else + else { responseStats.PipelineType = TestInjections.PipelineType.Passthrough; } @@ -865,7 +839,6 @@ public InputParameters( PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ExecutionEnvironment? executionEnvironment, bool? returnResultsInDeterministicOrder, - bool forcePassthrough, bool enableOptimisticDirectExecution, TestInjections testInjections) { @@ -899,7 +872,6 @@ public InputParameters( this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; this.ExecutionEnvironment = executionEnvironment.GetValueOrDefault(InputParameters.DefaultExecutionEnvironment); this.ReturnResultsInDeterministicOrder = returnResultsInDeterministicOrder.GetValueOrDefault(InputParameters.DefaultReturnResultsInDeterministicOrder); - this.ForcePassthrough = forcePassthrough; this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; this.TestInjections = testInjections; } @@ -916,7 +888,6 @@ public InputParameters( public ExecutionEnvironment ExecutionEnvironment { get; } public bool ReturnResultsInDeterministicOrder { get; } public TestInjections TestInjections { get; } - public bool ForcePassthrough { get; } public bool EnableOptimisticDirectExecution { get; } public InputParameters WithContinuationToken(CosmosElement token) @@ -933,7 +904,6 @@ public InputParameters WithContinuationToken(CosmosElement token) this.PartitionedQueryExecutionInfo, this.ExecutionEnvironment, this.ReturnResultsInDeterministicOrder, - this.ForcePassthrough, this.EnableOptimisticDirectExecution, this.TestInjections); } diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index 49407f7a4c..344e3e56e4 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -66,7 +66,6 @@ public static QueryIterator Create( string resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, - bool forcePassthrough, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, Documents.ResourceType resourceType) { @@ -145,7 +144,6 @@ public static QueryIterator Create( partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, - forcePassthrough: forcePassthrough, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 7bca68c8c8..13e5425d7d 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -337,121 +337,6 @@ public async Task> ReadManyItemsAsync( cancellationToken); } - /// - /// Used in the compute gateway to support legacy gateway interface. - /// - public override async Task TryExecuteQueryAsync( - QueryFeatures supportedQueryFeatures, - QueryDefinition queryDefinition, - string continuationToken, - FeedRangeInternal feedRangeInternal, - QueryRequestOptions requestOptions, - GeospatialType geospatialType, - CancellationToken cancellationToken = default) - { - if (queryDefinition == null) - { - throw new ArgumentNullException(nameof(queryDefinition)); - } - - if (requestOptions == null) - { - throw new ArgumentNullException(nameof(requestOptions)); - } - - if (feedRangeInternal != null) - { - // The user has scoped down to a physical partition or logical partition. - // In either case let the query execute as a passthrough. - QueryIterator passthroughQueryIterator = QueryIterator.Create( - containerCore: this, - client: this.queryClient, - clientContext: this.ClientContext, - sqlQuerySpec: queryDefinition.ToSqlQuerySpec(), - continuationToken: continuationToken, - feedRangeInternal: feedRangeInternal, - queryRequestOptions: requestOptions, - resourceLink: this.LinkUri, - isContinuationExpected: false, - allowNonValueAggregateQuery: true, - forcePassthrough: true, // Forcing a passthrough, since we don't want to get the query plan nor try to rewrite it. - partitionedQueryExecutionInfo: null, - resourceType: ResourceType.Document); - - return new QueryPlanIsSupportedResult(passthroughQueryIterator); - } - - cancellationToken.ThrowIfCancellationRequested(); - - Documents.PartitionKeyDefinition partitionKeyDefinition; - if (requestOptions.Properties != null - && requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject)) - { - if (!(partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)) - { - throw new ArgumentException( - "partitionkeydefinition has invalid type", - nameof(partitionKeyDefinitionObject)); - } - - partitionKeyDefinition = definition; - } - else - { - ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync( - this.LinkUri, - requestOptions.PartitionKey, - NoOpTrace.Singleton, - cancellationToken); - partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition; - } - - QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient); - - TryCatch<(PartitionedQueryExecutionInfo queryPlan, bool supported)> tryGetQueryInfoAndIfSupported = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync( - supportedQueryFeatures, - queryDefinition.ToSqlQuerySpec(), - ResourceType.Document, - partitionKeyDefinition, - requestOptions.PartitionKey.HasValue, - useSystemPrefix: QueryIterator.IsSystemPrefixExpected(requestOptions), - geospatialType: geospatialType, - cancellationToken); - - if (tryGetQueryInfoAndIfSupported.Failed) - { - return new FailedToGetQueryPlanResult(tryGetQueryInfoAndIfSupported.Exception); - } - - (PartitionedQueryExecutionInfo queryPlan, bool supported) = tryGetQueryInfoAndIfSupported.Result; - TryExecuteQueryResult tryExecuteQueryResult; - if (supported) - { - QueryIterator queryIterator = QueryIterator.Create( - containerCore: this, - client: this.queryClient, - clientContext: this.ClientContext, - sqlQuerySpec: queryDefinition.ToSqlQuerySpec(), - continuationToken: continuationToken, - feedRangeInternal: feedRangeInternal, - queryRequestOptions: requestOptions, - resourceLink: this.LinkUri, - isContinuationExpected: false, - allowNonValueAggregateQuery: true, - forcePassthrough: false, - partitionedQueryExecutionInfo: queryPlan, - resourceType: ResourceType.Document); - - tryExecuteQueryResult = new QueryPlanIsSupportedResult(queryIterator); - } - else - { - tryExecuteQueryResult = new QueryPlanNotSupportedResult(queryPlan); - } - - return tryExecuteQueryResult; - } - public override FeedIterator GetItemQueryIterator( string queryText = null, string continuationToken = null, @@ -835,7 +720,6 @@ public override FeedIteratorInternal GetItemQueryStreamIteratorInternal( resourceLink: this.LinkUri, isContinuationExpected: isContinuationExcpected, allowNonValueAggregateQuery: true, - forcePassthrough: false, partitionedQueryExecutionInfo: null, resourceType: ResourceType.Document); } @@ -874,7 +758,6 @@ public override FeedIteratorInternal GetReadFeedIterator( resourceLink: resourceLink, isContinuationExpected: false, allowNonValueAggregateQuery: true, - forcePassthrough: false, partitionedQueryExecutionInfo: null, resourceType: resourceType); } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index 920fc5d694..dc532f6977 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -65,15 +65,6 @@ public abstract Task>> GetPartitionKeyPathTo public abstract Task GetRoutingMapAsync(CancellationToken cancellationToken); - public abstract Task TryExecuteQueryAsync( - QueryFeatures supportedQueryFeatures, - QueryDefinition queryDefinition, - string continuationToken, - FeedRangeInternal feedRangeInternal, - QueryRequestOptions requestOptions, - GeospatialType geospatialType, - CancellationToken cancellationToken = default); - public abstract FeedIterator GetStandByFeedIterator( string continuationToken = default, int? maxItemCount = default, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 9eecd81e30..2074902249 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -569,105 +569,6 @@ await QueryTestsBase.RunQueryAsync( } } - [TestMethod] - public async Task TestTryExecuteQuery() - { - await this.CreateIngestQueryDeleteAsync( - ConnectionModes.Direct | ConnectionModes.Gateway, - CollectionTypes.SinglePartition, - QueryTestsBase.NoDocuments, - this.TestTryExecuteQueryHelper); - } - - private async Task TestTryExecuteQueryHelper( - Container container, - IReadOnlyList documents) - { - ContainerInternal conatinerCore = (ContainerInlineCore)container; - foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) - { - foreach (int maxItemCount in new int[] { 10, 100 }) - { - foreach ((string query, QueryFeatures queryFeatures, bool canSupportExpected) in new Tuple[] - { - new Tuple("SELECT * FROM c", QueryFeatures.None, true), - new Tuple("SELECT * FROM c ORDER BY c._ts", QueryFeatures.None, false), - new Tuple("SELECT * FROM c ORDER BY c._ts", QueryFeatures.OrderBy, true), - }) - { - string continuationToken = null; - do - { - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: queryFeatures, - queryDefinition: new QueryDefinition(query), - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = maxDegreeOfParallelism, - MaxItemCount = maxItemCount, - }, - feedRangeInternal: null, - continuationToken: continuationToken, - geospatialType: Cosmos.GeospatialType.Geography); - - if (canSupportExpected) - { - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanIsSupportedResult); - } - else - { - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanNotSupportedResult); - } - - if (canSupportExpected) - { - ContainerInternal.QueryPlanIsSupportedResult queryPlanIsSupportedResult = (ContainerInternal.QueryPlanIsSupportedResult)tryExecuteQueryResult; - ResponseMessage cosmosQueryResponse = await queryPlanIsSupportedResult.QueryIterator.ReadNextAsync(); - continuationToken = cosmosQueryResponse.ContinuationToken; - } - } while (continuationToken != null); - } - } - } - - { - // Test the syntax error case - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: QueryFeatures.None, - queryDefinition: new QueryDefinition("This is not a valid query."), - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = 1, - MaxItemCount = 1, - }, - feedRangeInternal: null, - continuationToken: null, - geospatialType: Cosmos.GeospatialType.Geography); - - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.FailedToGetQueryPlanResult); - } - - { - // Test that the force passthrough mechanism works - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: QueryFeatures.None, // Not supporting any features - queryDefinition: new QueryDefinition("SELECT VALUE [{\"item\": {\"sum\": SUM(c.blah), \"count\": COUNT(c.blah)}}] FROM c"), // Query has aggregates - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = 1, - MaxItemCount = 1, - }, - feedRangeInternal: new FeedRangePartitionKeyRange("0"), // filtering on a PkRangeId. - continuationToken: null, - geospatialType: Cosmos.GeospatialType.Geography); - - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanIsSupportedResult); - ContainerInternal.QueryPlanIsSupportedResult queryPlanIsSupportedResult = (ContainerInternal.QueryPlanIsSupportedResult)tryExecuteQueryResult; - ResponseMessage response = await queryPlanIsSupportedResult.QueryIterator.ReadNextAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, response.ErrorMessage); - } - } - [TestMethod] public async Task TestMalformedPipelinedContinuationToken() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 9076506e64..d9d543c050 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -801,7 +801,6 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect partitionedQueryExecutionInfo: null, executionEnvironment: null, returnResultsInDeterministicOrder: null, - forcePassthrough: false, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index d717b86f89..b02f19374a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -342,7 +342,6 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp partitionedQueryExecutionInfo: null, executionEnvironment: null, returnResultsInDeterministicOrder: null, - forcePassthrough: false, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); From f7a4c56f26b0d86ab1c3e9ea3f629ea3bb5ca775 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Sun, 5 Nov 2023 22:27:16 -0800 Subject: [PATCH 229/337] [Internal] Upgrade Resiliency: Fixes Duplicate Channel and Task Creation. (#4123) * Code changes to fix duplicate channel and thread pool on refresh flow. * Code changes to fix failed tests. * Code changes to add global semaphore for concurrency control in address cache. * Code changes to refactor the refresh async method. * Code changes to address review comments. * Code changes to update summary. --- .../src/Routing/AsyncCacheNonBlocking.cs | 24 ++- .../src/Routing/GatewayAddressCache.cs | 50 ++++- .../CosmosBadReplicaTests.cs | 14 +- .../GatewayAddressCacheTests.cs | 199 +++++++++++++++--- .../MockSetupsHelper.cs | 11 +- .../Routing/AsyncCacheNonBlockingTests.cs | 74 +++---- 6 files changed, 271 insertions(+), 101 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs index 9fb908d83f..4025863d19 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs @@ -9,7 +9,6 @@ namespace Microsoft.Azure.Cosmos using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.Tracing.TraceData; /// /// This is a thread safe AsyncCache that allows refreshing values in the background. @@ -179,21 +178,26 @@ public bool TryRemove(TKey key) /// /// Refreshes the async non blocking cache on-demand for the given - /// and caches the result for later usage. + /// and caches the result for later usage. Note that this method doesn't control the number + /// of tasks created in parallel, and the concurrency needed to be controlled at the caller. /// /// The requested key to be refreshed. /// A func delegate to be invoked at a later point of time. - public async Task RefreshAsync( + public void Refresh( TKey key, Func> singleValueInitFunc) { if (this.values.TryGetValue(key, out AsyncLazyWithRefreshTask initialLazyValue)) { - await this.UpdateCacheAndGetValueFromBackgroundTaskAsync( - key: key, - initialValue: initialLazyValue, - callbackDelegate: singleValueInitFunc, - operationName: nameof(RefreshAsync)); + Task backgroundRefreshTask = this.GetAsync( + key: key, + singleValueInitFunc: singleValueInitFunc, + forceRefresh: (_) => true); + + Task continuationTask = backgroundRefreshTask + .ContinueWith( + task => DefaultTrace.TraceVerbose("Failed to refresh addresses in the background with exception: {0}", task.Exception), + TaskContinuationOptions.OnlyOnFaulted); } } @@ -250,8 +254,8 @@ private sealed class AsyncLazyWithRefreshTask { private readonly CancellationToken cancellationToken; private readonly Func> createValueFunc; - private readonly object valueLock = new object(); - private readonly object removedFromCacheLock = new object(); + private readonly object valueLock = new (); + private readonly object removedFromCacheLock = new (); private bool removedFromCache = false; private Task value; diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 8bc429070e..f2012fe0bc 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -50,12 +50,14 @@ internal class GatewayAddressCache : IAddressCache, IDisposable private readonly ICosmosAuthorizationTokenProvider tokenProvider; private readonly bool enableTcpConnectionEndpointRediscovery; + private readonly SemaphoreSlim semaphore; private readonly CosmosHttpClient httpClient; private readonly bool isReplicaAddressValidationEnabled; private Tuple masterPartitionAddressCache; private DateTime suboptimalMasterPartitionTimestamp; private bool disposedValue; + private bool validateUnknownReplicas; private IOpenConnectionsHandler openConnectionsHandler; public GatewayAddressCache( @@ -90,8 +92,10 @@ public GatewayAddressCache( Constants.Properties.Protocol, GatewayAddressCache.ProtocolString(this.protocol)); + this.semaphore = new SemaphoreSlim(1, 1); this.openConnectionsHandler = openConnectionsHandler; this.isReplicaAddressValidationEnabled = replicaAddressValidationEnabled; + this.validateUnknownReplicas = false; } public Uri ServiceEndpoint => this.serviceEndpoint; @@ -120,6 +124,14 @@ public async Task OpenConnectionsAsync( List tasks = new (); int batchSize = GatewayAddressCache.DefaultBatchSize; + // By design, the Unknown replicas are validated only when the following two conditions meet: + // 1) The CosmosClient is initiated using the CreateAndInitializaAsync() flow. + // 2) The advanced replica selection feature enabled. + if (shouldOpenRntbdChannels) + { + this.validateUnknownReplicas = true; + } + #if !(NETSTANDARD15 || NETSTANDARD16) #if NETSTANDARD20 // GetEntryAssembly returns null when loaded from native netstandard2.0 @@ -302,11 +314,12 @@ public async Task TryGetAddressesAsync( .ReplicaTransportAddressUris .Any(x => x.ShouldRefreshHealthStatus())) { - Task refreshAddressesInBackgroundTask = Task.Run(async () => + bool slimAcquired = await this.semaphore.WaitAsync(0); + try { - try + if (slimAcquired) { - await this.serverPartitionAddressCache.RefreshAsync( + this.serverPartitionAddressCache.Refresh( key: partitionKeyRangeIdentity, singleValueInitFunc: (currentCachedValue) => this.GetAddressesForRangeIdAsync( request, @@ -315,14 +328,21 @@ await this.serverPartitionAddressCache.RefreshAsync( partitionKeyRangeIdentity.PartitionKeyRangeId, forceRefresh: true)); } - catch (Exception ex) + else { - DefaultTrace.TraceWarning("Failed to refresh addresses in the background for the collection rid: {0} with exception: {1}. '{2}'", + DefaultTrace.TraceVerbose("Failed to refresh addresses in the background for the collection rid: {0}, partition key range id: {1}, because the semaphore is already acquired. '{2}'", partitionKeyRangeIdentity.CollectionRid, - ex, + partitionKeyRangeIdentity.PartitionKeyRangeId, System.Diagnostics.Trace.CorrelationManager.ActivityId); } - }); + } + finally + { + if (slimAcquired) + { + this.semaphore.Release(); + } + } } return addresses; @@ -1008,18 +1028,26 @@ private static PartitionAddressInformation MergeAddresses( /// Returns a list of needed to validate their health status. Validating /// a uri is done by opening Rntbd connection to the backend replica, which is a costly operation by nature. Therefore /// vaidating both Unhealthy and Unknown replicas at the same time could impose a high CPU utilization. To avoid this - /// situation, the RntbdOpenConnectionHandler has good concurrency control mechanism to open the connections gracefully/>. + /// situation, the RntbdOpenConnectionHandler has good concurrency control mechanism to open the connections gracefully. + /// By default, this method only returns the Unhealthy replicas that requires to validate it's connectivity status. The + /// Unknown replicas are validated only when the CosmosClient is initiated using the CreateAndInitializaAsync() flow. /// /// A read only list of s. /// A list of that needs to validate their status. private IEnumerable GetAddressesNeededToValidateStatus( IReadOnlyList transportAddresses) { - return transportAddresses - .Where(address => address + return this.validateUnknownReplicas + ? transportAddresses + .Where(address => address + .GetCurrentHealthState() + .GetHealthStatus() is + TransportAddressHealthState.HealthStatus.UnhealthyPending or + TransportAddressHealthState.HealthStatus.Unknown) + : transportAddresses + .Where(address => address .GetCurrentHealthState() .GetHealthStatus() is - TransportAddressHealthState.HealthStatus.Unknown or TransportAddressHealthState.HealthStatus.UnhealthyPending); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs index 151e0690a8..9834f39a47 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs @@ -71,11 +71,11 @@ public async Task TestGoneFromServiceScenarioAsync( "44444444444444444", }; - HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( - replicaIds1, - partitionKeyRanges.First(), - "eastus", - cRid); + HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( + replicaIds1, + partitionKeyRanges.First(), + "eastus", + cRid); // One replica changed on the refresh List replicaIds2 = new List() @@ -176,6 +176,10 @@ public async Task TestGoneFromServiceScenarioAsync( mockTransportClient.VerifyAll(); mockHttpHandler.VerifyAll(); + mockTransportClient + .Setup(x => x.OpenConnectionAsync(It.IsAny())) + .Returns(Task.CompletedTask); + Documents.TransportAddressUri failedReplica = urisVisited.First(); // With replica validation enabled in preview mode, the failed replica will be validated as a part of the flow, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index c855599465..fded897e42 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -965,7 +965,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat { // Arrange. ManualResetEvent manualResetEvent = new(initialState: false); - Mock mockHttpHandler = new (MockBehavior.Strict); + Mock mockHttpHandler = new(MockBehavior.Strict); string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; @@ -987,12 +987,12 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat newAddress, })); - FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( failingIndexes: new HashSet(), manualResetEvent: manualResetEvent); - HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); - GatewayAddressCache cache = new ( + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Tcp, this.mockTokenProvider.Object, @@ -1023,10 +1023,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat manualResetEvent: manualResetEvent, shouldReset: true); - // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. + // Because the Unknown Replicas are not validated, the health status should remain as unknown. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Connected, + expected: TransportAddressHealthState.HealthStatus.Unknown, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( @@ -1076,17 +1076,17 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( addressInfo: addressInfo, - numberOfConnectedReplicas: 2, - numberOfUnknownReplicas: 1, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 3, numberOfUnhealthyPendingReplicas: 1, numberOfUnhealthyReplicas: 0); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, - expectedTotalHandlerInvocationCount: 2, - expectedTotalReceivedAddressesCount: 6, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 1, + expectedTotalSuccessAddressesToOpenCount: 1); } /// @@ -1099,7 +1099,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUriExistsForOneMinute_ShouldForceRefreshUnhealthyReplicas() { // Arrange. - ManualResetEvent manualResetEvent = new (initialState: false); + ManualResetEvent manualResetEvent = new(initialState: false); Mock mockHttpHandler = new(MockBehavior.Strict); string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; @@ -1129,15 +1129,15 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr newAddress, })); - FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( failIndexesByAttempts: new Dictionary>() { - { 0, new HashSet() { 2 } } + { 0, new HashSet() { 1 } } }, manualResetEvent: manualResetEvent); - HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); - GatewayAddressCache cache = new ( + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Tcp, this.mockTokenProvider.Object, @@ -1178,14 +1178,14 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, - expectedTotalHandlerInvocationCount: 1, - expectedTotalReceivedAddressesCount: 4, - expectedTotalSuccessAddressesToOpenCount: 4); + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); - // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. + // Because the Unknown Replicas are not validated, the health status should remain as unknown. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Connected, + expected: TransportAddressHealthState.HealthStatus.Unknown, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); Assert.AreEqual(4, addressInfo.AllAddresses.Count); @@ -1228,17 +1228,17 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( addressInfo: addressInfo, - numberOfConnectedReplicas: 2, - numberOfUnknownReplicas: 1, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 3, numberOfUnhealthyPendingReplicas: 1, numberOfUnhealthyReplicas: 0); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 2, - expectedTotalReceivedAddressesCount: 6, - expectedTotalSuccessAddressesToOpenCount: 5); + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 1, + expectedTotalSuccessAddressesToOpenCount: 0); // A delay of 2 minute was added to make the replica unhealthy for more than one minute. This // will make sure the unhealthy replica gets a chance to re-validate it's health status. @@ -1263,9 +1263,9 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 3, - expectedTotalReceivedAddressesCount: 7, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 2, + expectedTotalSuccessAddressesToOpenCount: 1); addressInfo = await cache.TryGetAddressesAsync( request: request, @@ -1293,9 +1293,140 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 3, - expectedTotalReceivedAddressesCount: 7, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 2, + expectedTotalSuccessAddressesToOpenCount: 1); + } + + /// + /// Test to validate that when replica validation is enabled and there exists a replica such that it remained unhealthy for a period of one minute or + /// more, then even though a force refresh is not requested, the unhealthy replicas at least get a chance to re-validate it's status by the + /// on-demand async non-blocking cache refresh flow and eventually marks itself as healthy once the open connection attempt is successful. The purpose + /// of this test to validate the above scenario with high number of concurrent execution and validate that the concurrent executions doesn't create an + /// unbounded number of tasks and the task creation is limited to just one, thus reducing the pressure on the task scheduler drammatically. + /// + [TestMethod] + [Owner("dkunda")] + public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndCSListenerMarksReplicaUnhealthyWithParallelInvocation_ShouldValidateUnhealthyReplicasOnce() + { + // Arrange. + int maxIteration = 2; + ManualResetEvent manualResetEvent = new(initialState: false); + Mock mockHttpHandler = new(MockBehavior.Strict); + string oldAddress = "rntbd://dummytenant.documents.azure.com:14004/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; + string newAddress = "rntbd://dummytenant.documents.azure.com:14004/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; + string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14002/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + oldAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })); + + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( + failIndexesByAttempts: new Dictionary>(), + manualResetEvent: manualResetEvent, + openConnectionDelayInSeconds: 1); + + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Documents.Client.Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2, + enableTcpConnectionEndpointRediscovery: true, + replicaAddressValidationEnabled: true); + + DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); + + // Act and Assert. + PartitionAddressInformation addressInfo = default; + TransportAddressUri refreshedUri = default; + + for (int iterationIndex = 1; iterationIndex <= maxIteration; iterationIndex++) + { + List openConnectionTasks = new(); + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + // Mimic the Connection State Listener based approach to mark a replica to unhealthy. + await cache.MarkAddressesToUnhealthyAsync( + new ServerKey( + new Uri( + uriString: addressTobeMarkedUnhealthy))); + + refreshedUri = addressInfo + .Get(Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + ReflectionUtils.AddMinuteToDateTimeFieldUsingReflection( + objectName: refreshedUri.GetCurrentHealthState(), + fieldName: "lastUnhealthyTimestamp", + delayInMinutes: -2 * iterationIndex); + + for (int j = 0; j < 500 * iterationIndex; j++) + { + openConnectionTasks + .Add( + cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None)); + } + + // awaits for the parallel execution to finish. + await Task.WhenAll(openConnectionTasks); + + // This assertion validates that there are no extra tasks created in the thread pool. + Assert.AreEqual(0, ThreadPool.PendingWorkItemCount); + + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: true); + + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: iterationIndex, + expectedTotalReceivedAddressesCount: iterationIndex, + expectedTotalSuccessAddressesToOpenCount: iterationIndex); + } } /// @@ -1577,11 +1708,13 @@ public FakeOpenConnectionHandler( public FakeOpenConnectionHandler( Dictionary> failIndexesByAttempts, - ManualResetEvent manualResetEvent = null) + ManualResetEvent manualResetEvent = null, + int openConnectionDelayInSeconds = 0) { this.useAttemptBasedFailingIndexs = true; this.failIndexesByAttempts = failIndexesByAttempts; this.manualResetEvent = manualResetEvent; + this.openConnectionDelayInSeconds = openConnectionDelayInSeconds; } public int GetTotalSuccessfulInvocationCount() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs index ebc0e9c61b..5bf63cd3ba 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs @@ -279,7 +279,14 @@ internal static HttpResponseMessage CreateAddresses( string regionName, ResourceId containerResourceId) { - string basePhysicalUri = $"rntbd://cdb-ms-prod-{regionName}-fd4.documents.azure.com:14382/apps/9dc0394e-d25f-4c98-baa5-72f1c700bf3e/services/060067c7-a4e9-4465-a412-25cb0104cb58/partitions/2cda760c-f81f-4094-85d0-7bcfb2acc4e6/replicas/"; + int initialPort = 14382; + int[] ports = new int[replicaIds.Count]; + string basePhysicalUri = "rntbd://cdb-ms-prod-{0}-fd4.documents.azure.com:{1}/apps/9dc0394e-d25f-4c98-baa5-72f1c700bf3e/services/060067c7-a4e9-4465-a412-25cb0104cb58/partitions/2cda760c-f81f-4094-85d0-7bcfb2acc4e6/replicas/{2}"; + + for (int i=0; i< replicaIds.Count; i++) + { + ports[i] = initialPort++; + } // Use the partition key range id at the end of each replica id to avoid conflicts when setting up multiple partition key ranges List
addresses = new List
(); @@ -290,7 +297,7 @@ internal static HttpResponseMessage CreateAddresses( { IsPrimary = i == 0, PartitionKeyRangeId = partitionKeyRangeId, - PhysicalUri = basePhysicalUri + repliaId, + PhysicalUri = string.Format(basePhysicalUri, regionName, ports[i], repliaId), Protocol = "rntbd", PartitionIndex = "7718513@164605136" }); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs index d58ab3db5b..944cb6de8c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs @@ -394,15 +394,15 @@ await asyncCache.GetAsync( } /// - /// Test to validate that when RefreshAsync() is invoked for a valid existing key, the + /// Test to validate that when Refresh() is invoked for a valid existing key, the /// cache refreshes the key successfully and the new value is updated in the cache. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenRefreshRequestedForAnExistingKey_ShouldRefreshTheCache() + public async Task Refresh_WhenRefreshRequestedForAnExistingKey_ShouldRefreshTheCache() { // Arrange. - AsyncCacheNonBlocking asyncCache = new (); + AsyncCacheNonBlocking asyncCache = new(); // Act and Assert. string result = await asyncCache.GetAsync( @@ -412,10 +412,14 @@ public async Task RefreshAsync_WhenRefreshRequestedForAnExistingKey_ShouldRefres Assert.AreEqual("value1", result); - await asyncCache.RefreshAsync( + asyncCache.Refresh( "key", (_) => Task.FromResult("value2")); + // Add some delay for the background refresh task to complete. + await Task.Delay( + millisecondsDelay: 50); + result = await asyncCache.GetAsync( "key", (_) => throw new Exception("Should not refresh."), @@ -425,15 +429,15 @@ await asyncCache.RefreshAsync( } /// - /// Test to validate that when a DocumentClientException is thrown during RefreshAsync() operation, + /// Test to validate that when a DocumentClientException is thrown during Refresh() operation, /// then the cache removes the key for which a refresh was requested. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenThrowsDocumentClientException_ShouldRemoveKeyFromTheCache() + public async Task Refresh_WhenThrowsDocumentClientException_ShouldRemoveKeyFromTheCache() { // Arrange. - AsyncCacheNonBlocking asyncCache = new (); + AsyncCacheNonBlocking asyncCache = new(); // Act and Assert. string result = await asyncCache.GetAsync( @@ -453,23 +457,20 @@ public async Task RefreshAsync_WhenThrowsDocumentClientException_ShouldRemoveKey // and still return the old cached value. Assert.AreEqual("value1", result); - NotFoundException notFoundException = new ( + NotFoundException notFoundException = new( message: "Item was deleted."); - try - { - await asyncCache.RefreshAsync( - "key", - async (_) => - { - await Task.Delay(TimeSpan.FromMilliseconds(5)); - throw notFoundException; - }); - Assert.Fail("Should throw a NotFoundException"); - } - catch (NotFoundException exception) - { - Assert.AreEqual(notFoundException, exception); - } + + asyncCache.Refresh( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw notFoundException; + }); + + // Add some delay for the background refresh task to complete. + await Task.Delay( + millisecondsDelay: 50); // Because the key was deleted from the cache, the func delegate should get invoked at // this point and update the value to value2. @@ -482,12 +483,12 @@ await asyncCache.RefreshAsync( } /// - /// Test to validate that when some other Exception is thrown during RefreshAsync() operation, + /// Test to validate that when some other Exception is thrown during Refresh() operation, /// then the cache does not remove the key for which the refresh was originally requested. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenThrowsOtherException_ShouldNotRemoveKeyFromTheCache() + public async Task Refresh_WhenThrowsOtherException_ShouldNotRemoveKeyFromTheCache() { // Arrange. AsyncCacheNonBlocking asyncCache = new(); @@ -512,21 +513,14 @@ public async Task RefreshAsync_WhenThrowsOtherException_ShouldNotRemoveKeyFromTh Exception exception = new( message: "Timeout exception."); - try - { - await asyncCache.RefreshAsync( - "key", - async (_) => - { - await Task.Delay(TimeSpan.FromMilliseconds(5)); - throw exception; - }); - Assert.Fail("Should throw a NotFoundException"); - } - catch (Exception ex) - { - Assert.AreEqual(ex, exception); - } + + asyncCache.Refresh( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw exception; + }); // Because the key should not get deleted from the cache, the func delegate should not get invoked at // this point. From b1918341a6648811f5d92278156f47668a3c360b Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 6 Nov 2023 13:20:37 -0800 Subject: [PATCH 230/337] [Internal] DocumentClient: Adds TryGetAccountProperties (#4167) * add api * tests * Update test * Rename --- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 17 +++++++++++++++++ .../ClientTests.cs | 18 ++++++++++++++++++ .../InterfaceParityTest.cs | 1 + 3 files changed, 36 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 3c261490a7..632c158f96 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -1235,6 +1235,23 @@ public virtual Documents.ConsistencyLevel ConsistencyLevel } } + /// + /// Returns the account properties available in the service configuration if the client was initialized. + /// + public bool TryGetCachedAccountProperties(out AccountProperties properties) + { + if (this.isSuccessfullyInitialized + && this.accountServiceConfiguration != null + && this.accountServiceConfiguration.AccountProperties != null) + { + properties = this.accountServiceConfiguration.AccountProperties; + return true; + } + + properties = null; + return false; + } + /// /// Disposes the client for the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index c8a9a0aff7..9bbbb980e3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -290,6 +290,24 @@ public async Task ValidateAzureKeyCredentialDirectModeUpdateAsync() } } + [TestMethod] + public async Task ValidateTryGetAccountProperties() + { + using CosmosClient cosmosClient = new CosmosClient( + ConfigurationManager.AppSettings["GatewayEndpoint"], + ConfigurationManager.AppSettings["MasterKey"] + ); + + Assert.IsFalse(cosmosClient.DocumentClient.TryGetCachedAccountProperties(out AccountProperties propertiesFromMethod)); + + AccountProperties accountProperties = await cosmosClient.ReadAccountAsync(); + + Assert.IsTrue(cosmosClient.DocumentClient.TryGetCachedAccountProperties(out propertiesFromMethod)); + + Assert.AreEqual(accountProperties.Consistency.DefaultConsistencyLevel, propertiesFromMethod.Consistency.DefaultConsistencyLevel); + Assert.AreEqual(accountProperties.Id, propertiesFromMethod.Id); + } + private int TaskStartedCount = 0; private async Task ReadNotFound(Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs index 281e550d24..9d5e391748 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs @@ -24,6 +24,7 @@ public void TestAllPublicMethodsExistInIDocumentClient() string[] excludedMethods = new string[] { "OpenAsync", // exposed public methods. + "TryGetCachedAccountProperties", // currently only internal "get_PartitionResolvers", "get_ResourceTokens", // Obsolete getters. "ToString", "Equals", "GetHashCode", "GetType", "get_httpClient" }; From 4db6078dc5eccb7133c5554e4ae35c5636ae9677 Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Mon, 6 Nov 2023 17:17:26 -0800 Subject: [PATCH 231/337] Query: Fixes documentation to reflect state of System.Text.Json serializer (#4170) * Update Program.cs * Update Program.cs * Update Program.cs * Update Program.cs --------- Co-authored-by: Matias Quaranta --- .../Usage/SystemTextJson/Program.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs index ac990a4e28..d66d54f5a2 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs @@ -177,15 +177,19 @@ private static async Task CleanupAsync() // public class ToDoActivity { + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("id")] public string Id { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("partitionKey")] public string PartitionKey { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("activityId")] public string ActivityId { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("status")] public string Status { get; set; } } From d287f085e3210c021179882e2a89cba257493661 Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Wed, 8 Nov 2023 10:57:25 -0800 Subject: [PATCH 232/337] [Internal] Query: Adds interface for linq serialization functions (#4163) * intial commit * add interface * PR comments and TranslationContext cleanup * update params * fix parameters * PR comments * PR comments * PR comments * simplifying serializer class * interface updates * Update docs * PR comments * PR comments * PR comments - rename and fix assert --- ...smosElementToSqlScalarExpressionVisitor.cs | 93 +++++++ .../src/Linq/DefaultCosmosLinqSerializer.cs | 110 ++++++++ .../src/Linq/ExpressionToSQL.cs | 239 +++++------------- .../src/Linq/ICosmosLinqSerializer.cs | 33 +++ .../src/Linq/QueryUnderConstruction.cs | 8 +- .../src/Linq/SQLTranslator.cs | 1 - .../src/Linq/TranslationContext.cs | 45 ++-- Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs | 46 +--- .../LinqAttributeContractBaselineTests.cs | 16 +- 9 files changed, 345 insertions(+), 246 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs create mode 100644 Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs create mode 100644 Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs new file mode 100644 index 0000000000..68232330de --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Diagnostics; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + using Microsoft.Azure.Cosmos.SqlObjects; + + internal sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor + { + public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); + + private CosmosElementToSqlScalarExpressionVisitor() + { + // Private constructor, since this class is a singleton. + } + + public SqlScalarExpression Visit(CosmosArray cosmosArray) + { + List items = new List(); + foreach (CosmosElement item in cosmosArray) + { + items.Add(item.Accept(this)); + } + + return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosBinary cosmosBinary) + { + // Can not convert binary to scalar expression without knowing the API type. + Debug.Fail("CosmosElementToSqlScalarExpressionVisitor Assert", "Unreachable"); + throw new InvalidOperationException(); + } + + public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) + { + return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); + } + + public SqlScalarExpression Visit(CosmosGuid cosmosGuid) + { + // Can not convert guid to scalar expression without knowing the API type. + Debug.Fail("CosmosElementToSqlScalarExpressionVisitor Assert", "Unreachable"); + throw new InvalidOperationException(); + } + + public SqlScalarExpression Visit(CosmosNull cosmosNull) + { + return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); + } + + public SqlScalarExpression Visit(CosmosNumber cosmosNumber) + { + if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) + { + throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); + } + + return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); + } + + public SqlScalarExpression Visit(CosmosObject cosmosObject) + { + List properties = new List(); + foreach (KeyValuePair prop in cosmosObject) + { + SqlPropertyName name = SqlPropertyName.Create(prop.Key); + CosmosElement value = prop.Value; + SqlScalarExpression expression = value.Accept(this); + SqlObjectProperty property = SqlObjectProperty.Create(name, expression); + properties.Add(property); + } + + return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosString cosmosString) + { + return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); + } + + public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) + { + return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs new file mode 100644 index 0000000000..024c33fab0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Diagnostics; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + + internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializer + { + public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType) + { + // There are two ways to specify a custom attribute + // 1- by specifying the JsonConverterAttribute on a Class/Enum + // [JsonConverter(typeof(StringEnumConverter))] + // Enum MyEnum + // { + // ... + // } + // + // 2- by specifying the JsonConverterAttribute on a property + // class MyClass + // { + // [JsonConverter(typeof(StringEnumConverter))] + // public MyEnum MyEnum; + // } + // + // Newtonsoft gives high precedence to the attribute specified + // on a property over on a type (class/enum) + // so we check both attributes and apply the same precedence rules + // JsonConverterAttribute doesn't allow duplicates so it's safe to + // use FirstOrDefault() + CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + + return memberAttribute != null || typeAttribute != null; + } + + public string Serialize(object value, MemberExpression memberExpression, Type memberType) + { + CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData converterAttribute = memberAttribute ?? typeAttribute; + + Debug.Assert(converterAttribute.ConstructorArguments.Count > 0, $"{nameof(DefaultCosmosLinqSerializer)} Assert!", "At least one constructor argument exists."); + Type converterType = (Type)converterAttribute.ConstructorArguments[0].Value; + + string serializedValue = converterType.GetConstructor(Type.EmptyTypes) != null + ? JsonConvert.SerializeObject(value, (Newtonsoft.Json.JsonConverter)Activator.CreateInstance(converterType)) + : JsonConvert.SerializeObject(value); + + return serializedValue; + } + + public string SerializeScalarExpression(ConstantExpression inputExpression) + { + return JsonConvert.SerializeObject(inputExpression.Value); + } + + public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) + { + string memberName = null; + + // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. + Newtonsoft.Json.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null && jsonExtensionDataAttribute.ReadData) + { + return null; + } + + // Json.Net honors JsonPropertyAttribute more than DataMemberAttribute + // So we check for JsonPropertyAttribute first. + JsonPropertyAttribute jsonPropertyAttribute = memberInfo.GetCustomAttribute(true); + if (jsonPropertyAttribute != null && !string.IsNullOrEmpty(jsonPropertyAttribute.PropertyName)) + { + memberName = jsonPropertyAttribute.PropertyName; + } + else + { + DataContractAttribute dataContractAttribute = memberInfo.DeclaringType.GetCustomAttribute(true); + if (dataContractAttribute != null) + { + DataMemberAttribute dataMemberAttribute = memberInfo.GetCustomAttribute(true); + if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name)) + { + memberName = dataMemberAttribute.Name; + } + } + } + + if (memberName == null) + { + memberName = memberInfo.Name; + } + + if (linqSerializerOptions != null) + { + memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName); + } + + return memberName; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index fef136d8d2..5153f29115 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq.Expressions; using System.Reflection; using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Spatial; using Microsoft.Azure.Cosmos.SqlObjects; using Microsoft.Azure.Documents; @@ -94,7 +93,7 @@ public static SqlQuery TranslateQuery( TranslationContext context = new TranslationContext(linqSerializerOptions, parameters); ExpressionToSql.Translate(inputExpression, context); // ignore result here - QueryUnderConstruction query = context.currentQuery; + QueryUnderConstruction query = context.CurrentQuery; query = query.FlattenAsPossible(); SqlQuery result = query.GetSqlQuery(); @@ -159,7 +158,7 @@ private static Collection TranslateInput(ConstantExpression inputExpression, Tra throw new DocumentQueryException(ClientResources.InputIsNotIDocumentQuery); } - context.currentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); + context.CurrentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); Type elemType = TypeSystem.GetElementType(inputExpression.Type); context.SetInputParameter(elemType, ParameterSubstitution.InputParameterName); // ignore result @@ -169,7 +168,7 @@ private static Collection TranslateInput(ConstantExpression inputExpression, Tra } /// - /// Get a paramter name to be binded to the a collection from the next lambda. + /// Get a parameter name to be binded to the collection from the next lambda. /// It's merely for readability purpose. If that is not possible, use a default /// parameter name. /// @@ -189,7 +188,7 @@ private static string GetBindingParameterName(TranslationContext context) } } - if (parameterName == null) parameterName = ExpressionToSql.DefaultParameterName; + parameterName ??= ExpressionToSql.DefaultParameterName; return parameterName; } @@ -474,17 +473,17 @@ private static SqlScalarExpression VisitBinary(BinaryExpression inputExpression, if (left is SqlMemberIndexerScalarExpression && right is SqlLiteralScalarExpression literalScalarExpression) { - right = ExpressionToSql.ApplyCustomConverters(inputExpression.Left, literalScalarExpression); + right = ExpressionToSql.ApplyCustomConverters(inputExpression.Left, literalScalarExpression, context); } else if (right is SqlMemberIndexerScalarExpression && left is SqlLiteralScalarExpression sqlLiteralScalarExpression) { - left = ExpressionToSql.ApplyCustomConverters(inputExpression.Right, sqlLiteralScalarExpression); + left = ExpressionToSql.ApplyCustomConverters(inputExpression.Right, sqlLiteralScalarExpression, context); } return SqlBinaryScalarExpression.Create(op, left, right); } - private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLiteralScalarExpression right) + private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLiteralScalarExpression right, TranslationContext context) { MemberExpression memberExpression; if (left is UnaryExpression unaryExpression) @@ -504,48 +503,28 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit memberType = memberType.NullableUnderlyingType(); } - // There are two ways to specify a custom attribute - // 1- by specifying the JsonConverterAttribute on a Class/Enum - // [JsonConverter(typeof(StringEnumConverter))] - // Enum MyEnum - // { - // ... - // } - // - // 2- by specifying the JsonConverterAttribute on a property - // class MyClass - // { - // [JsonConverter(typeof(StringEnumConverter))] - // public MyEnum MyEnum; - // } - // - // Newtonsoft gives high precedence to the attribute specified - // on a property over on a type (class/enum) - // so we check both attributes and apply the same precedence rules - // JsonConverterAttribute doesn't allow duplicates so it's safe to - // use FirstOrDefault() - CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.Where(ca => ca.AttributeType == typeof(JsonConverterAttribute)).FirstOrDefault(); - CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().Where(ca => ca.AttributeType == typeof(JsonConverterAttribute)).FirstOrDefault(); - - CustomAttributeData converterAttribute = memberAttribute ?? typeAttribute; - if (converterAttribute != null) + bool requiresCustomSerializatior = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType); + if (requiresCustomSerializatior) { - Debug.Assert(converterAttribute.ConstructorArguments.Count > 0); - - Type converterType = (Type)converterAttribute.ConstructorArguments[0].Value; - object value = default(object); // Enum if (memberType.IsEnum()) { - Number64 number64 = ((SqlNumberLiteral)right.Literal).Value; - if (number64.IsDouble) + try { - value = Enum.ToObject(memberType, Number64.ToDouble(number64)); + Number64 number64 = ((SqlNumberLiteral)right.Literal).Value; + if (number64.IsDouble) + { + value = Enum.ToObject(memberType, Number64.ToDouble(number64)); + } + else + { + value = Enum.ToObject(memberType, Number64.ToLong(number64)); + } } - else + catch { - value = Enum.ToObject(memberType, Number64.ToLong(number64)); + value = ((SqlStringLiteral)right.Literal).Value; } } @@ -558,17 +537,7 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit if (value != default(object)) { - string serializedValue; - - if (converterType.GetConstructor(Type.EmptyTypes) != null) - { - serializedValue = JsonConvert.SerializeObject(value, (JsonConverter)Activator.CreateInstance(converterType)); - } - else - { - serializedValue = JsonConvert.SerializeObject(value); - } - + string serializedValue = context.CosmosLinqSerializer.Serialize(value, memberExpression, memberType); return CosmosElement.Parse(serializedValue).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); } } @@ -717,17 +686,17 @@ public static SqlScalarExpression VisitConstant(ConstantExpression inputExpressi if (inputExpression.Type.IsNullable()) { - return ExpressionToSql.VisitConstant(Expression.Constant(inputExpression.Value, Nullable.GetUnderlyingType(inputExpression.Type)), context); + return VisitConstant(Expression.Constant(inputExpression.Value, Nullable.GetUnderlyingType(inputExpression.Type)), context); } - if (context.parameters != null && context.parameters.TryGetValue(inputExpression.Value, out string paramName)) + if (context.Parameters != null && context.Parameters.TryGetValue(inputExpression.Value, out string paramName)) { SqlParameter sqlParameter = SqlParameter.Create(paramName); return SqlParameterRefScalarExpression.Create(sqlParameter); } Type constantType = inputExpression.Value.GetType(); - if (constantType.IsValueType()) + if (constantType.IsValueType) { if (inputExpression.Value is bool boolValue) { @@ -764,13 +733,15 @@ public static SqlScalarExpression VisitConstant(ConstantExpression inputExpressi foreach (object item in enumerable) { - arrayItems.Add(ExpressionToSql.VisitConstant(Expression.Constant(item), context)); + arrayItems.Add(VisitConstant(Expression.Constant(item), context)); } return SqlArrayCreateScalarExpression.Create(arrayItems.ToImmutableArray()); } - return CosmosElement.Parse(JsonConvert.SerializeObject(inputExpression.Value)).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); + string serializedConstant = context.CosmosLinqSerializer.SerializeScalarExpression(inputExpression); + + return CosmosElement.Parse(serializedConstant).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); } private static SqlScalarExpression VisitConditional(ConditionalExpression inputExpression, TranslationContext context) @@ -798,7 +769,7 @@ private static SqlScalarExpression VisitParameter(ParameterExpression inputExpre private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpression, TranslationContext context) { SqlScalarExpression memberExpression = ExpressionToSql.VisitScalarExpression(inputExpression.Expression, context); - string memberName = inputExpression.Member.GetMemberName(context.linqSerializerOptions); + string memberName = inputExpression.Member.GetMemberName(context); // If the resulting memberName is null, then the indexer should be on the root of the object. if (memberName == null) @@ -809,7 +780,7 @@ private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpre // if expression is nullable if (inputExpression.Expression.Type.IsNullable()) { - MemberNames memberNames = context.memberNames; + MemberNames memberNames = context.MemberNames; // ignore .Value if (memberName == memberNames.Value) @@ -853,7 +824,7 @@ private static SqlScalarExpression[] VisitExpressionList(ReadOnlyCollectionThe scalar Any collection private static Collection ConvertToScalarAnyCollection(TranslationContext context) { - SqlQuery query = context.currentQuery.FlattenAsPossible().GetSqlQuery(); + SqlQuery query = context.CurrentQuery.FlattenAsPossible().GetSqlQuery(); SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); Binding binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); - context.currentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); - context.currentQuery.AddBinding(binding); + context.CurrentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); + context.CurrentQuery.AddBinding(binding); SqlSelectSpec selectSpec = SqlSelectValueSpec.Create( SqlBinaryScalarExpression.Create( @@ -1032,7 +1003,7 @@ private static Collection ConvertToScalarAnyCollection(TranslationContext contex SqlPropertyRefScalarExpression.Create(null, SqlIdentifier.Create(parameterExpression.Name))), SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(0)))); SqlSelectClause selectClause = SqlSelectClause.Create(selectSpec); - context.currentQuery.AddSelectClause(selectClause); + context.CurrentQuery.AddSelectClause(selectClause); return new Collection(LinqMethods.Any); } @@ -1173,106 +1144,106 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.PushCollection(collection); Collection result = new Collection(inputExpression.Method.Name); - bool shouldBeOnNewQuery = context.currentQuery.ShouldBeOnNewQuery(inputExpression.Method.Name, inputExpression.Arguments.Count); + bool shouldBeOnNewQuery = context.CurrentQuery.ShouldBeOnNewQuery(inputExpression.Method.Name, inputExpression.Arguments.Count); context.PushSubqueryBinding(shouldBeOnNewQuery); switch (inputExpression.Method.Name) { case LinqMethods.Select: { SqlSelectClause select = ExpressionToSql.VisitSelect(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Where: { SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(where, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); break; } case LinqMethods.SelectMany: { - context.currentQuery = context.PackageCurrentQueryIfNeccessary(); + context.CurrentQuery = context.PackageCurrentQueryIfNeccessary(); result = ExpressionToSql.VisitSelectMany(inputExpression.Arguments, context); break; } case LinqMethods.OrderBy: { SqlOrderByClause orderBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); - context.currentQuery = context.currentQuery.AddOrderByClause(orderBy, context); + context.CurrentQuery = context.CurrentQuery.AddOrderByClause(orderBy, context); break; } case LinqMethods.OrderByDescending: { SqlOrderByClause orderBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); - context.currentQuery = context.currentQuery.AddOrderByClause(orderBy, context); + context.CurrentQuery = context.CurrentQuery.AddOrderByClause(orderBy, context); break; } case LinqMethods.ThenBy: { SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); - context.currentQuery = context.currentQuery.UpdateOrderByClause(thenBy, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } case LinqMethods.ThenByDescending: { SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); - context.currentQuery = context.currentQuery.UpdateOrderByClause(thenBy, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } case LinqMethods.Skip: { SqlOffsetSpec offsetSpec = ExpressionToSql.VisitSkip(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddOffsetSpec(offsetSpec, context); + context.CurrentQuery = context.CurrentQuery.AddOffsetSpec(offsetSpec, context); break; } case LinqMethods.Take: { - if (context.currentQuery.HasOffsetSpec()) + if (context.CurrentQuery.HasOffsetSpec()) { SqlLimitSpec limitSpec = ExpressionToSql.VisitTakeLimit(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddLimitSpec(limitSpec, context); + context.CurrentQuery = context.CurrentQuery.AddLimitSpec(limitSpec, context); } else { SqlTopSpec topSpec = ExpressionToSql.VisitTakeTop(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddTopSpec(topSpec); + context.CurrentQuery = context.CurrentQuery.AddTopSpec(topSpec); } break; } case LinqMethods.Distinct: { SqlSelectClause select = ExpressionToSql.VisitDistinct(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Max: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Max); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Min: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Min); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Average: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Avg); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Count: { SqlSelectClause select = ExpressionToSql.VisitCount(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Sum: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Sum); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Any: @@ -1282,7 +1253,7 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, { // Any is translated to an SELECT VALUE EXISTS() where Any operation itself is treated as a Where. SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(where, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); } break; } @@ -1509,7 +1480,7 @@ private static SqlScalarExpression VisitScalarExpression(Expression expression, ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); SqlCollection subqueryCollection = ExpressionToSql.CreateSubquerySqlCollection( - query, context, + query, isMinMaxAvgMethod ? SubqueryKind.ArrayScalarExpression : expressionObjKind.Value); Binding newBinding = new Binding(parameterExpression, subqueryCollection, @@ -1536,9 +1507,8 @@ private static SqlScalarExpression VisitScalarExpression(Expression expression, /// Create a subquery SQL collection object for a SQL query ///
/// The SQL query object - /// The translation context /// The subquery type - private static SqlCollection CreateSubquerySqlCollection(SqlQuery query, TranslationContext context, SubqueryKind subqueryType) + private static SqlCollection CreateSubquerySqlCollection(SqlQuery query, SubqueryKind subqueryType) { SqlCollection subqueryCollection; switch (subqueryType) @@ -1583,18 +1553,18 @@ private static SqlQuery CreateSubquery(Expression expression, ReadOnlyCollection { bool shouldBeOnNewQuery = context.CurrentSubqueryBinding.ShouldBeOnNewQuery; - QueryUnderConstruction queryBeforeVisit = context.currentQuery; - QueryUnderConstruction packagedQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc(), context.currentQuery); - packagedQuery.fromParameters.SetInputParameter(typeof(object), context.currentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); - context.currentQuery = packagedQuery; + QueryUnderConstruction queryBeforeVisit = context.CurrentQuery; + QueryUnderConstruction packagedQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc(), context.CurrentQuery); + packagedQuery.fromParameters.SetInputParameter(typeof(object), context.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); + context.CurrentQuery = packagedQuery; if (shouldBeOnNewQuery) context.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; Collection collection = ExpressionToSql.VisitCollectionExpression(expression, parameters, context); - QueryUnderConstruction subquery = context.currentQuery.GetSubquery(queryBeforeVisit); + QueryUnderConstruction subquery = context.CurrentQuery.GetSubquery(queryBeforeVisit); context.CurrentSubqueryBinding.ShouldBeOnNewQuery = shouldBeOnNewQuery; - context.currentQuery = queryBeforeVisit; + context.CurrentQuery = queryBeforeVisit; SqlQuery sqlSubquery = subquery.FlattenAsPossible().GetSqlQuery(); return sqlSubquery; @@ -1665,7 +1635,7 @@ private static Collection VisitSelectMany(ReadOnlyCollection argumen SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); - context.currentQuery.fromParameters.Add(binding); + context.CurrentQuery.fromParameters.Add(binding); } return collection; @@ -1902,7 +1872,7 @@ private static SqlSelectClause VisitCount( if (arguments.Count == 2) { SqlWhereClause whereClause = ExpressionToSql.VisitWhere(arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(whereClause, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(whereClause, context); } else if (arguments.Count != 1) { @@ -2004,83 +1974,6 @@ private static SqlInputPathCollection ConvertMemberIndexerToPath(SqlMemberIndexe #endregion LINQ Specific Visitors - private sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor - { - public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); - - private CosmosElementToSqlScalarExpressionVisitor() - { - // Private constructor, since this class is a singleton. - } - - public SqlScalarExpression Visit(CosmosArray cosmosArray) - { - List items = new List(); - foreach (CosmosElement item in cosmosArray) - { - items.Add(item.Accept(this)); - } - - return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosBinary cosmosBinary) - { - // Can not convert binary to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) - { - return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); - } - - public SqlScalarExpression Visit(CosmosGuid cosmosGuid) - { - // Can not convert guid to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosNull cosmosNull) - { - return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); - } - - public SqlScalarExpression Visit(CosmosNumber cosmosNumber) - { - if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) - { - throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); - } - - return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); - } - - public SqlScalarExpression Visit(CosmosObject cosmosObject) - { - List properties = new List(); - foreach (KeyValuePair prop in cosmosObject) - { - SqlPropertyName name = SqlPropertyName.Create(prop.Key); - CosmosElement value = prop.Value; - SqlScalarExpression expression = value.Accept(this); - SqlObjectProperty property = SqlObjectProperty.Create(name, expression); - properties.Add(property); - } - - return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosString cosmosString) - { - return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); - } - - public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) - { - return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); - } - } private enum SubqueryKind { ArrayScalarExpression, diff --git a/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs new file mode 100644 index 0000000000..f31490832d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Linq.Expressions; + using System.Reflection; + + internal interface ICosmosLinqSerializer + { + /// + /// Returns true if there are custom attributes on a member expression. + /// + bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType); + + // TODO : Clean up this interface member for better generalizability + /// + /// Serializes object. + /// + string Serialize(object value, MemberExpression memberExpression, Type memberType); + + /// + /// Serializes a ConstantExpression. + /// + string SerializeScalarExpression(ConstantExpression inputExpression); + + /// + /// Serializes a member name with LINQ serializer options applied. + /// + string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null); + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs index c5c0573a14..d2e19046e1 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs @@ -583,13 +583,13 @@ public QueryUnderConstruction AddOrderByClause(SqlOrderByClause orderBy, Transla public QueryUnderConstruction UpdateOrderByClause(SqlOrderByClause thenBy, TranslationContext context) { - List items = new List(context.currentQuery.orderByClause.OrderByItems); + List items = new List(context.CurrentQuery.orderByClause.OrderByItems); items.AddRange(thenBy.OrderByItems); - context.currentQuery.orderByClause = SqlOrderByClause.Create(items.ToImmutableArray()); + context.CurrentQuery.orderByClause = SqlOrderByClause.Create(items.ToImmutableArray()); - foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) context.currentQuery.AddBinding(binding); + foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) context.CurrentQuery.AddBinding(binding); - return context.currentQuery; + return context.CurrentQuery; } public QueryUnderConstruction AddOffsetSpec(SqlOffsetSpec offsetSpec, TranslationContext context) diff --git a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs index 8648019219..c0bd6d38a0 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs @@ -6,7 +6,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; ///
diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index 8fc95d8701..f5d53bd1e7 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System; using System.Collections.Generic; using System.Linq.Expressions; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; using static Microsoft.Azure.Cosmos.Linq.ExpressionToSql; using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings; @@ -20,39 +19,54 @@ internal sealed class TranslationContext /// /// Member names for special mapping cases /// - internal readonly MemberNames memberNames; + public readonly MemberNames MemberNames; + + /// + /// The LINQ serializer + /// + public readonly ICosmosLinqSerializer CosmosLinqSerializer; + + /// + /// User-provided LINQ serializer options + /// + public CosmosLinqSerializerOptions LinqSerializerOptions; /// /// Set of parameters in scope at any point; used to generate fresh parameter names if necessary. /// public HashSet InScope; + /// /// Query that is being assembled. /// - public QueryUnderConstruction currentQuery; + public QueryUnderConstruction CurrentQuery; /// /// Dictionary for parameter name and value /// - public IDictionary parameters; + public IDictionary Parameters; /// /// If the FROM clause uses a parameter name, it will be substituted for the parameter used in /// the lambda expressions for the WHERE and SELECT clauses. /// private ParameterSubstitution substitutions; + /// /// We are currently visiting these methods. /// private List methodStack; + /// /// Stack of parameters from lambdas currently in scope. /// private List lambdaParametersStack; + /// /// Stack of collection-valued inputs. /// private List collectionStack; + /// /// The stack of subquery binding information. /// @@ -65,15 +79,14 @@ public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDi this.methodStack = new List(); this.lambdaParametersStack = new List(); this.collectionStack = new List(); - this.currentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); + this.CurrentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); this.subqueryBindingStack = new Stack(); - this.linqSerializerOptions = linqSerializerOptions; - this.parameters = parameters; - this.memberNames = new MemberNames(linqSerializerOptions); + this.LinqSerializerOptions = linqSerializerOptions; + this.Parameters = parameters; + this.MemberNames = new MemberNames(linqSerializerOptions); + this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer(); } - public CosmosLinqSerializerOptions linqSerializerOptions; - public Expression LookupSubstitution(ParameterExpression parameter) { return this.substitutions.Lookup(parameter); @@ -103,12 +116,12 @@ public void PushParameter(ParameterExpression parameter, bool shouldBeOnNewQuery if (last.isOuter) { // substitute - ParameterExpression inputParam = this.currentQuery.GetInputParameterInContext(shouldBeOnNewQuery); + ParameterExpression inputParam = this.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery); this.substitutions.AddSubstitution(parameter, inputParam); } else { - this.currentQuery.Bind(parameter, last.inner); + this.CurrentQuery.Bind(parameter, last.inner); } } @@ -182,7 +195,7 @@ public void PopCollection() /// Suggested name for the input parameter. public ParameterExpression SetInputParameter(Type type, string name) { - return this.currentQuery.fromParameters.SetInputParameter(type, name, this.InScope); + return this.CurrentQuery.fromParameters.SetInputParameter(type, name, this.InScope); } /// @@ -193,7 +206,7 @@ public ParameterExpression SetInputParameter(Type type, string name) public void SetFromParameter(ParameterExpression parameter, SqlCollection collection) { Binding binding = new Binding(parameter, collection, isInCollection: true); - this.currentQuery.fromParameters.Add(binding); + this.CurrentQuery.fromParameters.Add(binding); } /// @@ -258,11 +271,11 @@ public QueryUnderConstruction PackageCurrentQueryIfNeccessary() { if (this.CurrentSubqueryBinding.ShouldBeOnNewQuery) { - this.currentQuery = this.currentQuery.PackageQuery(this.InScope); + this.CurrentQuery = this.CurrentQuery.PackageQuery(this.InScope); this.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; } - return this.currentQuery; + return this.CurrentQuery; } public class SubqueryBinding diff --git a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs index 7c8e62d69c..e11c145c71 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs @@ -10,10 +10,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; - using System.Runtime.Serialization; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Documents; - using Newtonsoft.Json; internal static class TypeSystem { @@ -22,48 +19,9 @@ public static Type GetElementType(Type type) return GetElementType(type, new HashSet()); } - public static string GetMemberName(this MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) + public static string GetMemberName(this MemberInfo memberInfo, TranslationContext context) { - string memberName = null; - - // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. - JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); - if (jsonExtensionDataAttribute != null && jsonExtensionDataAttribute.ReadData) - { - return null; - } - - // Json.Net honors JsonPropertyAttribute more than DataMemberAttribute - // So we check for JsonPropertyAttribute first. - JsonPropertyAttribute jsonPropertyAttribute = memberInfo.GetCustomAttribute(true); - if (jsonPropertyAttribute != null && !string.IsNullOrEmpty(jsonPropertyAttribute.PropertyName)) - { - memberName = jsonPropertyAttribute.PropertyName; - } - else - { - DataContractAttribute dataContractAttribute = memberInfo.DeclaringType.GetCustomAttribute(true); - if (dataContractAttribute != null) - { - DataMemberAttribute dataMemberAttribute = memberInfo.GetCustomAttribute(true); - if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name)) - { - memberName = dataMemberAttribute.Name; - } - } - } - - if (memberName == null) - { - memberName = memberInfo.Name; - } - - if (linqSerializerOptions != null) - { - memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName); - } - - return memberName; + return context.CosmosLinqSerializer.SerializeMemberName(memberInfo, context.LinqSerializerOptions); } private static Type GetElementType(Type type, HashSet visitedSet) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs index 7ffc36bdbd..5ea03bf0b6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs @@ -9,14 +9,13 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using VisualStudio.TestTools.UnitTesting; + using System.Threading.Tasks; using BaselineTest; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.SDK.EmulatorTests; using Microsoft.Azure.Documents; - using System.Threading.Tasks; + using Newtonsoft.Json; + using VisualStudio.TestTools.UnitTesting; /// /// Class that tests to see that we honor the attributes for members in a class / struct when we create LINQ queries. @@ -173,10 +172,11 @@ public Datum2(string jsonProperty, string dataMember, string defaultMember, stri [TestMethod] public void TestAttributePriority() { - Assert.AreEqual("jsonProperty", TypeSystem.GetMemberName(typeof(Datum).GetMember("JsonProperty").First())); - Assert.AreEqual("dataMember", TypeSystem.GetMemberName(typeof(Datum).GetMember("DataMember").First())); - Assert.AreEqual("Default", TypeSystem.GetMemberName(typeof(Datum).GetMember("Default").First())); - Assert.AreEqual("jsonPropertyHasHigherPriority", TypeSystem.GetMemberName(typeof(Datum).GetMember("JsonPropertyAndDataMember").First())); + ICosmosLinqSerializer cosmosLinqSerializer = new DefaultCosmosLinqSerializer(); + Assert.AreEqual("jsonProperty", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("JsonProperty").First())); + Assert.AreEqual("dataMember", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("DataMember").First())); + Assert.AreEqual("Default", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("Default").First())); + Assert.AreEqual("jsonPropertyHasHigherPriority", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("JsonPropertyAndDataMember").First())); } /// From 966b48146436c24b06a8d17293ba5d87580360bf Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 9 Nov 2023 12:52:11 -0800 Subject: [PATCH 233/337] Routing: Adds ExcludeRegions Feature to RequestOptions (#4128) * adds excludeRegions * suggested changes * removed unused usings * fixed blank line error * removed using * update contracts * fixed test * reverted automatic changes to BaselineTests * requested changes * bug fix * PPOF test fix --- .../src/ClientRetryPolicy.cs | 8 +- .../src/Handler/RequestMessage.cs | 4 +- .../src/RequestOptions/QueryRequestOptions.cs | 1 - .../src/RequestOptions/RequestOptions.cs | 7 + .../src/Routing/GlobalEndpointManager.cs | 5 + .../src/Routing/LocationCache.cs | 62 ++++- .../Contracts/DotNetSDKAPI.json | 19 ++ .../LocationCacheTests.cs | 229 ++++++++++++++++-- 8 files changed, 303 insertions(+), 32 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs index 7cef90d541..147977e130 100644 --- a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs @@ -246,9 +246,9 @@ private async Task ShouldRetryInternalAsync( if (statusCode == HttpStatusCode.NotFound && subStatusCode == SubStatusCodes.ReadSessionNotAvailable) { - return this.ShouldRetryOnSessionNotAvailable(); + return this.ShouldRetryOnSessionNotAvailable(this.documentServiceRequest); } - + // Received 503 due to client connect timeout or Gateway if (statusCode == HttpStatusCode.ServiceUnavailable) { @@ -330,7 +330,7 @@ private async Task ShouldRetryOnEndpointFailureAsync( return ShouldRetryResult.RetryAfter(retryDelay); } - private ShouldRetryResult ShouldRetryOnSessionNotAvailable() + private ShouldRetryResult ShouldRetryOnSessionNotAvailable(DocumentServiceRequest request) { this.sessionTokenRetryCount++; @@ -343,7 +343,7 @@ private ShouldRetryResult ShouldRetryOnSessionNotAvailable() { if (this.canUseMultipleWriteLocations) { - ReadOnlyCollection endpoints = this.isReadRequest ? this.globalEndpointManager.ReadEndpoints : this.globalEndpointManager.WriteEndpoints; + ReadOnlyCollection endpoints = this.globalEndpointManager.GetApplicableEndpoints(request, this.isReadRequest); if (this.sessionTokenRetryCount > endpoints.Count) { diff --git a/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs index 6748e79921..67d3dbdc27 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs @@ -282,7 +282,8 @@ internal DocumentServiceRequest ToDocumentServiceRequest() { this.DocumentServiceRequest.RouteTo(this.PartitionKeyRangeId); } - + + this.DocumentServiceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions; this.OnBeforeRequestHandler(this.DocumentServiceRequest); return this.DocumentServiceRequest; } @@ -299,6 +300,7 @@ private static Headers CreateHeaders() private void OnBeforeRequestHandler(DocumentServiceRequest serviceRequest) { + serviceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions; this.OnBeforeSendRequestActions?.Invoke(serviceRequest); } diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 2b4aba5ac0..a4557da6d2 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -5,7 +5,6 @@ namespace Microsoft.Azure.Cosmos { using System; - using System.ComponentModel; using System.Text; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Query; diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index e8d4c602ff..dd24f3e45e 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -69,6 +69,13 @@ public class RequestOptions /// public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + /// + /// List of regions to be excluded routing the request to. + /// This can be used to route a request to a specific region by excluding all other regions. + /// If all regions are excluded, then the request will be routed to the primary/hub region. + /// + public List ExcludeRegions { get; set; } + /// /// Gets or sets the boolean to use effective partition key routing in the cosmos db request. /// diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index bcaae809f4..e12d99255d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -362,6 +362,11 @@ public string GetLocation(Uri endpoint) return this.locationCache.GetLocation(endpoint); } + public ReadOnlyCollection GetApplicableEndpoints(DocumentServiceRequest request, bool isReadRequest) + { + return this.locationCache.GetApplicableEndpoints(request, isReadRequest); + } + public bool TryGetLocationForGatewayDiagnostics(Uri endpoint, out string regionName) { return this.locationCache.TryGetLocationForGatewayDiagnostics(endpoint, out regionName); diff --git a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs index 4480df1826..88a369bd2d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs @@ -31,6 +31,7 @@ internal sealed class LocationCache private readonly TimeSpan unavailableLocationsExpirationTime; private readonly int connectionLimit; private readonly ConcurrentDictionary locationUnavailablityInfoByEndpoint; + private readonly RegionNameMapper regionNameMapper; private DatabaseAccountLocationsInfo locationInfo; private DateTime lastCacheUpdateTimestamp; @@ -54,6 +55,7 @@ public LocationCache( this.lastCacheUpdateTimestamp = DateTime.MinValue; this.enableMultipleWriteLocations = false; this.unavailableLocationsExpirationTime = TimeSpan.FromSeconds(LocationCache.DefaultUnavailableLocationsExpirationTimeInSeconds); + this.regionNameMapper = new RegionNameMapper(); #if !(NETSTANDARD15 || NETSTANDARD16) #if NETSTANDARD20 @@ -281,7 +283,7 @@ public Uri ResolveServiceEndpoint(DocumentServiceRequest request) } else { - ReadOnlyCollection endpoints = request.OperationType.IsWriteOperation() ? this.WriteEndpoints : this.ReadEndpoints; + ReadOnlyCollection endpoints = this.GetApplicableEndpoints(request, !request.OperationType.IsWriteOperation()); locationEndpointToRoute = endpoints[locationIndex % endpoints.Count]; } @@ -289,6 +291,64 @@ public Uri ResolveServiceEndpoint(DocumentServiceRequest request) return locationEndpointToRoute; } + public ReadOnlyCollection GetApplicableEndpoints(DocumentServiceRequest request, bool isReadRequest) + { + ReadOnlyCollection endpoints = isReadRequest ? this.ReadEndpoints : this.WriteEndpoints; + + if (request.RequestContext.ExcludeRegions == null || request.RequestContext.ExcludeRegions.Count == 0) + { + return endpoints; + } + + return this.GetApplicableEndpoints( + endpoints, + isReadRequest ? this.locationInfo.AvailableReadEndpointByLocation : this.locationInfo.AvailableWriteEndpointByLocation, + this.defaultEndpoint, + request.RequestContext.ExcludeRegions); + } + + /// + /// Gets applicable endpoints for a request, if there are no applicable endpoints, returns the fallback endpoint + /// + /// + /// + /// + /// + /// a list of applicable endpoints for a request + private ReadOnlyCollection GetApplicableEndpoints( + IReadOnlyList endpoints, + ReadOnlyDictionary regionNameByEndpoint, + Uri fallbackEndpoint, + IReadOnlyList excludeRegions) + { + List applicableEndpoints = new List(endpoints.Count); + HashSet excludeUris = new HashSet(); + + foreach (string region in excludeRegions) + { + string normalizedRegionName = this.regionNameMapper.GetCosmosDBRegionName(region); + if (regionNameByEndpoint.ContainsKey(normalizedRegionName)) + { + excludeUris.Add(regionNameByEndpoint[normalizedRegionName]); + } + } + + foreach (Uri endpoint in endpoints) + { + if (!excludeUris.Contains(endpoint)) + { + applicableEndpoints.Add(endpoint); + } + } + + if (applicableEndpoints.Count == 0) + { + applicableEndpoints.Add(fallbackEndpoint); + } + + return new ReadOnlyCollection(applicableEndpoints); + } + public bool ShouldRefreshEndpoints(out bool canRefreshInBackground) { canRefreshInBackground = true; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 8c8d7d6ae1..46bdf1c170 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -7986,6 +7986,18 @@ "Attributes": [], "MethodInfo": "System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] Properties;CanRead:True;CanWrite:True;System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] get_Properties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Properties(System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Collections.Generic.List`1[System.String] ExcludeRegions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.List`1[System.String] ExcludeRegions;CanRead:True;CanWrite:True;System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[System.String] get_ExcludeRegions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String get_IfMatchEtag()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -8029,6 +8041,13 @@ ], "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_IfMatchEtag(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs index b93107b302..06ed0d4026 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs @@ -770,11 +770,180 @@ await BackoffRetryUtility.ExecuteAsync( } } + [TestMethod] + [DataRow(true, true, true, DisplayName = "Read request - Multi master - with preferred locations")] + [DataRow(true, true, false, DisplayName = "Read request - Multi master - no preferred locations")] + [DataRow(true, false, true, DisplayName = "Read request - Single master - with preferred locations")] + [DataRow(true, false, false, DisplayName = "Read request - Single master - no preferred locations")] + [DataRow(false, true, true, DisplayName = "Write request - Multi master - with preferred locations")] + [DataRow(false, true, false, DisplayName = "Write request - Multi master - no preferred locations")] + [DataRow(false, false, true, DisplayName = "Write request - Single master - with preferred locations")] + [DataRow(false, false, false, DisplayName = "Write request - Single master - no preferred locations")] + public void VerifyRegionExcludedTest( + bool isReadRequest, + bool useMultipleWriteLocations, + bool usesPreferredLocations) + { + bool enableEndpointDiscovery = true; + + ReadOnlyCollection preferredList = usesPreferredLocations ? + isReadRequest ? + new List { + "location4", + "location2", + "location1" + }.AsReadOnly() : + new List { + "location3", + "location2", + "location1" + }.AsReadOnly() : + isReadRequest ? + new List() { + "default", + "location1", + "location2", + "location4" + }.AsReadOnly() : + new List() { + "default", + "location1", + "location2", + "location3" + }.AsReadOnly(); + + List> excludeRegionCases = isReadRequest ? + new List>() + { + new List {"default"}, new List {"default", "location1"}, new List {"default", "location2"}, new List {"default", "location4"}, + new List {"default", "location1", "location2"}, new List {"default", "location1", "location4"}, new List {"default", "location2", "location4"}, + new List {"default", "location1", "location2", "location4"}, new List { "location1" }, new List {"location1", "location2"}, + new List {"location1", "location4"}, new List {"location1", "location2", "location4"},new List { "location2" }, + new List {"location2", "location4"},new List { "location4" }, + } : + new List>() + { + new List {"default" }, new List {"default", "location1"}, new List {"default", "location2"}, new List {"default", "location3"}, + new List {"default", "location1", "location2"}, new List {"default", "location1", "location3"}, new List {"default", "location2", "location3"}, + new List {"default", "location1", "location2", "location3"}, new List { "location1" }, new List {"location1", "location2"}, + new List {"location1", "location3"}, new List {"location1", "location2", "location3"},new List { "location2" }, + new List {"location2", "location3"},new List { "location3" }, + }; + + foreach (List excludeRegions in excludeRegionCases) + { + using GlobalEndpointManager endpointManager = this.Initialize( + useMultipleWriteLocations: useMultipleWriteLocations, + enableEndpointDiscovery: enableEndpointDiscovery, + isPreferredLocationsListEmpty: false, + preferedRegionListOverride: preferredList, + enforceSingleMasterSingleWriteLocation: true, + isExcludeRegionsTest: true); + + endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); + + using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) + { + request.RequestContext.ExcludeRegions = excludeRegions; + + ReadOnlyCollection applicableEndpoints = endpointManager.GetApplicableEndpoints(request, isReadRequest); + + Uri endpoint = endpointManager.ResolveServiceEndpoint(request); + ReadOnlyCollection applicableRegions = this.GetApplicableRegions(isReadRequest, useMultipleWriteLocations, usesPreferredLocations, excludeRegions); + + Assert.AreEqual(applicableRegions.Count, applicableEndpoints.Count); + for(int i = 0; i < applicableRegions.Count; i++) + { + Assert.AreEqual(applicableRegions[i], applicableEndpoints[i]); + } + + Assert.AreEqual(applicableRegions[0], endpoint); + } + } + + } + + private ReadOnlyCollection GetApplicableRegions(bool isReadRequest, bool useMultipleWriteLocations, bool usesPreferredLocations, List excludeRegions) + { + if(!isReadRequest && !useMultipleWriteLocations) + { + return new List() {LocationCacheTests.DefaultEndpoint }.AsReadOnly(); + } + + Dictionary readWriteLocations = usesPreferredLocations ? + isReadRequest ? + new Dictionary() + { + {"location4", LocationCacheTests.Location4Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + } : + useMultipleWriteLocations ? + new Dictionary() + { + {"location3", LocationCacheTests.Location3Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + } : + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + } : + isReadRequest ? + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location4", LocationCacheTests.Location4Endpoint }, + } : + useMultipleWriteLocations ? + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location3", LocationCacheTests.Location3Endpoint }, + } : + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint} + }; + + List applicableRegions = new List(); + + foreach (string region in readWriteLocations.Keys) + { + if(!excludeRegions.Contains(region)) + { + applicableRegions.Add(readWriteLocations[region]); + } + } + + if (applicableRegions.Count == 0) + { + applicableRegions.Add(LocationCacheTests.DefaultEndpoint); + } + + return applicableRegions.AsReadOnly(); + } + private static AccountProperties CreateDatabaseAccount( bool useMultipleWriteLocations, - bool enforceSingleMasterSingleWriteLocation) + bool enforceSingleMasterSingleWriteLocation, + bool isExcludeRegionsTest = false) { - Collection writeLocations = new Collection() + Collection writeLocations = isExcludeRegionsTest ? + + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } }, + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location3", Endpoint = LocationCacheTests.Location3Endpoint.ToString() } }, + } : + new Collection() { { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, @@ -786,21 +955,34 @@ private static AccountProperties CreateDatabaseAccount( { // Some pre-existing tests depend on the account having multiple write locations even on single master setup // Newer tests can correctly define a single master account (single write region) without breaking existing tests - writeLocations = new Collection() - { - { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } } - }; + writeLocations = isExcludeRegionsTest ? + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } } + } : + new Collection() + { + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } } + } ; } AccountProperties databaseAccount = new AccountProperties() { EnableMultipleWriteLocations = useMultipleWriteLocations, - ReadLocationsInternal = new Collection() - { - { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, - { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, - { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, - }, + ReadLocationsInternal = isExcludeRegionsTest ? + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } }, + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, + } : + new Collection() + { + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, + }, WriteLocationsInternal = writeLocations }; @@ -813,11 +995,13 @@ private GlobalEndpointManager Initialize( bool isPreferredLocationsListEmpty, bool enforceSingleMasterSingleWriteLocation = false, // Some tests depend on the Initialize to create an account with multiple write locations, even when not multi master ReadOnlyCollection preferedRegionListOverride = null, - bool enablePartitionLevelFailover = false) + bool enablePartitionLevelFailover = false, + bool isExcludeRegionsTest = false) { this.databaseAccount = LocationCacheTests.CreateDatabaseAccount( useMultipleWriteLocations, - enforceSingleMasterSingleWriteLocation); + enforceSingleMasterSingleWriteLocation, + isExcludeRegionsTest); if (isPreferredLocationsListEmpty) { @@ -826,7 +1010,7 @@ private GlobalEndpointManager Initialize( else { // Allow for override at the test method level if needed - this.preferredLocations = preferedRegionListOverride != null ? preferedRegionListOverride : new List() + this.preferredLocations = preferedRegionListOverride ?? new List() { "location1", "location2", @@ -844,8 +1028,8 @@ private GlobalEndpointManager Initialize( this.cache.OnDatabaseAccountRead(this.databaseAccount); this.mockedClient = new Mock(); - mockedClient.Setup(owner => owner.ServiceEndpoint).Returns(LocationCacheTests.DefaultEndpoint); - mockedClient.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny(), It.IsAny())).ReturnsAsync(this.databaseAccount); + this.mockedClient.Setup(owner => owner.ServiceEndpoint).Returns(LocationCacheTests.DefaultEndpoint); + this.mockedClient.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny(), It.IsAny())).ReturnsAsync(this.databaseAccount); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -860,14 +1044,9 @@ private GlobalEndpointManager Initialize( GlobalEndpointManager endpointManager = new GlobalEndpointManager(this.mockedClient.Object, connectionPolicy); - if (enablePartitionLevelFailover) - { - this.partitionKeyRangeLocationCache = new GlobalPartitionEndpointManagerCore(endpointManager); - } - else - { - this.partitionKeyRangeLocationCache = GlobalPartitionEndpointManagerNoOp.Instance; - } + this.partitionKeyRangeLocationCache = enablePartitionLevelFailover + ? new GlobalPartitionEndpointManagerCore(endpointManager) + : GlobalPartitionEndpointManagerNoOp.Instance; return endpointManager; } From 4fee54695bb9d3b4a950473c56529c10e74f7a0d Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 15 Nov 2023 10:15:42 -0800 Subject: [PATCH 234/337] Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview (#4180) * Code changes to enable replica validation for preview. * Code changes to enable replica validation for preview and GA. --- Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 0b7786d8c3..3c48b1f5ab 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -44,8 +44,6 @@ public static T GetEnvironmentVariable(string variable, T defaultValue) public static bool IsReplicaAddressValidationEnabled( ConnectionPolicy connectionPolicy) { - bool replicaValidationDefaultValue = false; - if (connectionPolicy != null && connectionPolicy.EnableAdvancedReplicaSelectionForTcp.HasValue) { @@ -55,7 +53,7 @@ public static bool IsReplicaAddressValidationEnabled( return ConfigurationManager .GetEnvironmentVariable( variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, - defaultValue: replicaValidationDefaultValue); + defaultValue: true); } /// From f471418c23ac44b28bf2be45804e662357bd391c Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Wed, 15 Nov 2023 12:59:52 -0800 Subject: [PATCH 235/337] VS 17.8 auto runs NuGetAudit and flagging 10.0.2, CosmosDB SDK already mitigated it by changing the MAXDEPATH (#4185) --- Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index f8afb4af6c..b94151babd 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -117,7 +117,7 @@ - + From e205d411db41917e4027e0e25c77377e2df3329b Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Wed, 15 Nov 2023 23:30:13 -0800 Subject: [PATCH 236/337] Documentation: Adds Upsert documentation to include status codes for Created vs Replaced (#4186) * Upset status codes clarification * Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview (#4180) * Code changes to enable replica validation for preview. * Code changes to enable replica validation for preview and GA. --------- Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> --- .../src/Resource/Container/Container.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 2978d741bf..5b6f188e89 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -470,6 +470,13 @@ public abstract Task> ReadItemAsync( /// Check the HTTP status code on the response to check if the operation failed. /// /// https://aka.ms/cosmosdb-dot-net-exceptions#stream-api + /// + /// + /// Upsert result i.e. creation or replace can be identified by the status code: + /// 201 - item created + /// 200 - item replaced + /// + /// /// /// Upsert a Stream containing the item to Cosmos /// @@ -506,6 +513,13 @@ public abstract Task UpsertItemStreamAsync( /// (Optional) representing request cancellation. /// The that was upserted contained within a object representing the service response for the asynchronous operation. /// https://aka.ms/cosmosdb-dot-net-exceptions#typed-api + /// + /// + /// Upsert result i.e. creation or replace can be identified by the status code: + /// 201 - item created + /// 200 - item replaced + /// + /// /// /// /// Date: Thu, 16 Nov 2023 08:21:57 -0800 Subject: [PATCH 237/337] [Internal] Code Analysis: Fixes all warning in source/test/usage projects (#4188) * [Internal] CodeAnalsis: Fixing CA2200 for test projects * Making code warning clean * fixing the usages projects * Removing the insource overrides * One mroe small fix --------- Co-authored-by: Sourabh Jain --- .../Usage/ApplicationInsights/Program.cs | 2 +- .../CustomDiagnosticAndEventListener/Program.cs | 4 ++-- .../ClientCreateAndInitializeTest.cs | 4 ++-- .../QueryTests.cs | 8 ++++---- .../Benchmarks/StopwatchAllocationsBenchmark.cs | 4 ++++ .../Contracts/DirectContractTests.cs | 1 - .../CosmosConflictTests.cs | 4 ++-- .../CosmosHttpClientCoreTests.cs | 11 +++++------ .../GatewayStoreModelTest.cs | 2 ++ .../OptimisticDirectExecutionQueryBaselineTests.cs | 12 +++++++----- .../ServicePointAccessorTests.cs | 6 +++++- 11 files changed, 34 insertions(+), 24 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs index 288ce80c64..526452beb2 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs @@ -16,7 +16,7 @@ internal class Program private static readonly string databaseName = "samples"; private static readonly string containerName = "ai-sample"; - private static TelemetryClient? _telemetryClient; + private static TelemetryClient _telemetryClient; static async Task Main() { diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs index 77580936f7..08d7956f35 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs @@ -83,8 +83,8 @@ public static async Task RunCrudDemo(Container container) internal class Item { [JsonProperty("id")] - public string Id { get; set; } + public string? Id { get; set; } - public string Status { get; set; } + public string? Status { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs index 8bbb7f5d54..1813700e05 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs @@ -138,7 +138,7 @@ public async Task DatabaseIncorrectTest() catch (CosmosException ex) { Assert.IsTrue(ex.StatusCode == HttpStatusCode.NotFound); - throw ex; + throw; } } @@ -156,7 +156,7 @@ public async Task ContainerIncorrectTest() catch (CosmosException ex) { Assert.IsTrue(ex.StatusCode == HttpStatusCode.NotFound); - throw ex; + throw; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index 762bbbd945..359bc07715 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -2135,12 +2135,12 @@ private void TestContinuationLimitHeaders(Database database, bool partitionedCol { if (!(e.InnerException is DocumentClientException exception)) { - throw e; + throw; } if (exception.StatusCode != HttpStatusCode.BadRequest) { - throw e; + throw; } Assert.IsTrue(exception.Message.Contains("continuation token limit specified is not large enough")); @@ -2159,12 +2159,12 @@ private void TestContinuationLimitHeaders(Database database, bool partitionedCol { if (!(e.InnerException is DocumentClientException exception)) { - throw e; + throw; } if (exception.StatusCode != HttpStatusCode.BadRequest) { - throw e; + throw; } Assert.IsTrue(exception.Message.Contains("Please pass in a valid continuation token size limit which must be a positive integer")); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs index 334fc74ecf..0e10faf438 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs @@ -39,12 +39,16 @@ public void ValueStopwatchBoxedAsField() private class StopwatchHolder { +#pragma warning disable CS0414 // Remove unread private members private readonly Stopwatch stopwatch = new Stopwatch(); +#pragma warning restore CS0414 // Remove unread private members } private class ValueStopwatchHolder { +#pragma warning disable CS0414 // Remove unread private members private readonly ValueStopwatch stopwatch = new ValueStopwatch(); +#pragma warning restore CS0414 // Remove unread private members } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs index 2634ea1bc3..3300c84d60 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs @@ -37,7 +37,6 @@ public void TestInteropTest() Assert.IsTrue(ServiceInteropWrapper.AssembliesExist.Value); string configJson = "{}"; - IntPtr provider; TryCatch tryCreateServiceProvider = QueryPartitionProvider.TryCreateServiceProvider(configJson); Assert.IsFalse(tryCreateServiceProvider.Failed); // Don't leak on tests diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs index 50adab3aef..cbaf45fe88 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs @@ -40,13 +40,13 @@ public async Task ConflictsFeedSetsPartitionKeyRangeIdentity() [TestMethod] public async Task QueryConflicts() { - ContainerInternal container = CosmosConflictTests.GetMockedContainer(async (request, cancellationToken) => { + ContainerInternal container = CosmosConflictTests.GetMockedContainer((request, cancellationToken) => { Assert.AreEqual(ResourceType.Conflict, request.ResourceType); ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK) { Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Conflicts"": [{ ""id"": ""Test""}]}")) }; - return responseMessage; + return Task.FromResult(responseMessage); }); { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 03fdb84ead..09401bda13 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -243,7 +243,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio public async Task Retry3TimesOnDefaultPolicyTestAsync() { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { count++; @@ -268,7 +268,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio cancellationToken: default); } } - catch (Exception ex) + catch (Exception) { //Ignore the exception } @@ -283,7 +283,7 @@ public async Task HttpTimeoutThrow503TestAsync() async Task TestScenarioAsync(HttpMethod method, ResourceType resourceType, HttpTimeoutPolicy timeoutPolicy, Type expectedException, int expectedNumberOfRetrys) { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { count++; @@ -346,7 +346,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio public async Task NoRetryOnNoRetryPolicyTestAsync() { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { if(count == 0) { @@ -355,7 +355,6 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio count++; throw new OperationCanceledException("API with exception"); - } DocumentClientEventSource eventSource = DocumentClientEventSource.Instance; @@ -375,7 +374,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio cancellationToken: default); } } - catch (Exception ex) + catch (Exception) { //Ignore the exception } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index e16f176e61..fd9a8a3efd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -175,11 +175,13 @@ public async Task PassesPropertiesFromDocumentServiceRequest() Func> sendFunc = request => { +#pragma warning disable CS0618 // Type or member is obsolete Assert.AreEqual(properties.Count, request.Properties.Count); foreach (KeyValuePair item in properties) { Assert.AreEqual(item.Value, request.Properties[item.Key]); } +#pragma warning restore CS0618 // Type or member is obsolete return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) ); }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index d9d543c050..824232c412 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -144,7 +144,7 @@ public void NegativeOptimisticDirectExecutionOutput() // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done [TestMethod] - public async Task TestDefaultQueryRequestOptionsSettings() + public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); bool odeExpectedValue = @@ -644,7 +644,7 @@ internal static TryCatch TryGetPartitionedQueryEx return tryGetQueryPlan; } - private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) + private static Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) { (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); @@ -655,7 +655,7 @@ private static async Task GetOdePipelineAsync(OptimisticDir NoOpTrace.Singleton); Assert.IsNotNull(queryPipelineStage); - return queryPipelineStage; + return Task.FromResult(queryPipelineStage); } private static async Task CreateDocumentContainerAsync( @@ -912,6 +912,7 @@ public MergeTestUtil(bool isFailedFallbackPipelineTest) this.IsFailedFallbackPipelineTest = isFailedFallbackPipelineTest; } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task ShouldReturnFailure() { this.MoveNextCounter++; @@ -939,6 +940,7 @@ public async Task ShouldReturnFailure() return null; } +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously } } @@ -1093,7 +1095,7 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); @@ -1101,7 +1103,7 @@ public override async Task> TryGetPartit TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; - return TryCatch.FromResult(partitionedQueryExecutionInfo); + return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs index 5ff15ed9a3..f9cb21805f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs @@ -11,7 +11,7 @@ namespace Microsoft.Azure.Cosmos.Tests [TestClass] public class ServicePointAccessorTests { - private static Uri uri = new Uri("https://localhost"); + private static readonly Uri uri = new Uri("https://localhost"); [TestMethod] public void ServicePointAccessor_SetConnectionLimit() @@ -20,7 +20,9 @@ public void ServicePointAccessor_SetConnectionLimit() ServicePointAccessor accessor = ServicePointAccessor.FindServicePoint(ServicePointAccessorTests.uri); Assert.IsNotNull(accessor); accessor.ConnectionLimit = limit; +#pragma warning disable SYSLIB0014 // Type or member is obsolete ServicePoint servicePoint = ServicePointManager.FindServicePoint(ServicePointAccessorTests.uri); +#pragma warning restore SYSLIB0014 // Type or member is obsolete Assert.AreEqual(limit, servicePoint.ConnectionLimit); } @@ -29,7 +31,9 @@ public void ServicePointAccessor_DisableNagle() { ServicePointAccessor accessor = ServicePointAccessor.FindServicePoint(ServicePointAccessorTests.uri); Assert.IsNotNull(accessor); +#pragma warning disable SYSLIB0014 // Type or member is obsolete ServicePoint servicePoint = ServicePointManager.FindServicePoint(ServicePointAccessorTests.uri); +#pragma warning restore SYSLIB0014 // Type or member is obsolete Assert.IsFalse(servicePoint.UseNagleAlgorithm); } } From c6918b472094ca33181f792fb469919025f146e9 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 17 Nov 2023 15:00:25 -0800 Subject: [PATCH 238/337] 3.37.0: Adds new SDK versions and contract files (#4191) * Updated change log and bumped up the patch version. * Updated change log and bumped up the minor version. * Updated change log to reflect correct version. --- Directory.Build.props | 4 +- .../contracts/API_3.37.0-preview.txt | 1611 +++++++++++++++++ .../contracts/API_3.37.0.txt | 1552 ++++++++++++++++ changelog.md | 11 + 4 files changed, 3176 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 514e8e7abb..57ee59de6f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.36.0 - 3.36.0 + 3.37.0 + 3.37.0 preview 3.31.5 2.0.3 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt new file mode 100644 index 0000000000..672794b621 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt @@ -0,0 +1,1611 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt new file mode 100644 index 0000000000..1c02b4efb2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt @@ -0,0 +1,1552 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 18cac46b8a..c6f797d1ec 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,17 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.37.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0-preview) - 2023-11-17 +### [3.37.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0) - 2023-11-17 + +#### Fixed +- [4100](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4100) Query : Fixes querying conflicts (#4100) +- [4125](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4125) Item Operations: Fixes JsonSerialization exception when MissingMemberHandling = Error on Json default settings when NotFound on Item operations (#4125) + +#### Added +- [4180](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4180) Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview and GA (#4180) +- [4128](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4128) Routing: Adds ExcludeRegions Feature to RequestOptions (#4128) + ### [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-24 #### Fixed From a0f1c30521024791aaf93aa3a07aba77c2f8b1bd Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 21 Nov 2023 14:00:40 -0800 Subject: [PATCH 239/337] [Internal] Versioning: Adds guidance for versioning SDK releases (#4192) * Create versioning.md * Update versioning.md * Update versioning.md * Update versioning.md * Update README.md * Update versioning.md * Update versioning.md * Apply suggestions from code review Co-authored-by: Kevin Pilch * Update versioning.md * Update versioning.md --------- Co-authored-by: Kevin Pilch --- README.md | 2 ++ docs/versioning.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 docs/versioning.md diff --git a/README.md b/README.md index f1dcffa7b9..861235223a 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ using (FeedIterator feedIterator = container.GetItemQueryIterator :information_source: General Availability of an API or feature present in a Preview SDK is not guaranteed on the next GA SDK release following the Preview SDK release when it was introduced. Each Preview API can have an independent GA cycle that can be dependent on the Azure Cosmos DB Service. + +## Major releases + +Major releases are defined by: + +* Significant breaking changes to the API surface of the SDK. +* Significant breaking changes to dependencies + +> :information_source: No new major release is currently planned. + +## Minor releases + +Minor releases are defined by: + +* Changes in the public API surface of the SDK, such as new features, or GAing APIs that were in preview +* Changes in the version of one of the dependencies + +In these cases, the **GA SDK** should **increase the minor version** and **Preview SDK** should **increase the minor version to be one more than GA SDK**. + +For example, if `3.10.0` is being released for **GA SDK**, then `3.11.0-preview.0` should be released for **Preview SDK**. + +## Patch releases + +Patch releases are defined by: + +* No Public API changes +* Includes a subset of the bug fixes reported after the last major release + +In these cases, the **GA SDK** should **increase the patch version** and **Preview SDK** should **increase the preview suffix version**. + +For example, if `3.10.0` is being patched, for **GA SDK** we would release `3.10.1` and for **Preview SDK** we would release `3.11.0-preview.1`. + +If `3.10.1` is being patched, for **GA SDK** we would release `3.10.2` and for **Preview SDK** we would release `3.11.0-preview.2`. + +## Complete full example + +| GA | Preview | +|----------|-----------| +| 3.10.0 | 3.11.0-preview.0 | +| 3.10.1 | 3.11.0-preview.1 | +| 3.10.2 | 3.11.0-preview.2 | +| 3.11.0 | 3.12.0-preview.0 | From d07f9cabad7d67ee1e3d3cb5e709a5d7207c0318 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Fri, 1 Dec 2023 09:21:15 -0800 Subject: [PATCH 240/337] [Internal] Query: Adds Baseline test for exceeding header length for index advisor (#4176) * add baseline tests * added back missing bracket * update csporj file --------- Co-authored-by: Minh Le --- ...eTest.IndexUtilizationHeaderLengthTest.xml | 86 +++++++++++++++++++ .../IndexMetricsParserBaselineTest.cs | 41 ++++++++- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 4 + 3 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml new file mode 100644 index 0000000000..09fc864403 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + 0 AND r.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb > 0]]> + + + + + + + + + 0]]> + + + + + + + + + 0 AND r.cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc > 0]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index 598ee51c9d..a78f8bf7a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -131,9 +131,46 @@ public void IndexUtilizationParse() this.ExecuteTestSuite(inputs); } - public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestInput input) + [TestMethod] + public void IndexUtilizationHeaderLengthTest() { - // V2 + const int repeatCount = 10000; + string property1 = "r." + new string('a', repeatCount); + string property2 = "r." + new string('b', repeatCount); + string property3 = "r." + new string('c', repeatCount); + + const string equalityFilter = " = 0"; + const string inequalityFilter = " > 0"; + List inputs = new List + { + new IndexMetricsParserTestInput + ( + description: "Single property", + query: "SELECT * FROM root r WHERE " + property1 + equalityFilter + ), + new IndexMetricsParserTestInput + ( + description: "Only single index recommendation", + query: "SELECT * FROM root r WHERE " + property1 + inequalityFilter + " AND " + property2 + inequalityFilter + ), + new IndexMetricsParserTestInput + ( + description: "Only one composite index recommendation", + query: "SELECT * FROM root r WHERE " + property1 + equalityFilter + " AND " + property2 + inequalityFilter + ), + // Notice in this baseline the composite index recommendation is cut off + new IndexMetricsParserTestInput + ( + description: "Multiple composite index recommendation", + query: "SELECT * FROM root r WHERE " + property1 + equalityFilter + " AND " + property2 + inequalityFilter + " AND " + property3 + inequalityFilter + ), + }; + + this.ExecuteTestSuite(inputs); + } + + public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestInput input) + { QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true }; FeedIterator itemQuery = testContainer.GetItemQueryIterator( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 7ff30b3cee..7dd766d5d3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -35,6 +35,7 @@ + @@ -101,6 +102,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 07aa28eee6d869535f130a315f8ed52dcabcd648 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 12 Dec 2023 14:40:53 -0800 Subject: [PATCH 241/337] [Internal] Automation: Fixes check for issue assignment (#4213) * Removing * fix --- .github/policies/resourceManagement.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml index 7d78118b0e..daa00a6a21 100644 --- a/.github/policies/resourceManagement.yml +++ b/.github/policies/resourceManagement.yml @@ -20,7 +20,6 @@ configuration: label: needs-more-information - noActivitySince: days: 14 - - isNotAssigned actions: - addReply: reply: '@${issueAuthor} this issue requires more information for the team to be able to help. In case this information is available, please add it and re-open the Issue.' From 6258e24651048e7eaa1802706bd222905ea9c30a Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 12 Dec 2023 18:00:04 -0800 Subject: [PATCH 242/337] Query: Add Optimistic Direct Execution configuration override support on the Client (#4122) * Added ability to accept the AllowOptimisticDirectExecution flag from the backend and use that flag to decide if the Ode pipeline should be used or not. * Added comment and removed extra spacing * Added test coverage * Added exception handling logic * Resolved comments * Added null check for key parameter * Removed changes to common test infra * Removed all changes from QueryPartitionProviderTestInstance * Remove changes pt2 * Removed the dictionary in QueryPartitionProvider and added a bool instead * Updated GetClientDisableOptimisticDirectExecution() * Fixed comments * Revert QueryIterator.cs * Undoing changes to settings.json * Undoing changes to QueryIterator.cs * Updated error message * Made functions static * Cast to bool instead of recasting in GetClientDisableOptimisticDirectExecution() * Added ignore flag * Fixed merge conflicts * Updated GetPartitionedQueryExecutionInfoAndPartitionProvider() * Updated return type in OffsetLimitPageSize() --- .../CosmosQueryExecutionContextFactory.cs | 22 +- .../Core/QueryClient/CosmosQueryClient.cs | 2 + .../Core/QueryPlan/QueryPartitionProvider.cs | 17 ++ .../Query/v3Query/CosmosQueryClientCore.cs | 6 + .../OptimisticDirectExecutionQueryTests.cs | 17 ++ ...misticDirectExecutionQueryBaselineTests.cs | 192 +++++++++++++++--- .../Query/Pipeline/FullPipelineTests.cs | 3 +- 7 files changed, 219 insertions(+), 40 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 08e6292a03..01be3ffc83 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -32,6 +32,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext internal static class CosmosQueryExecutionContextFactory { + internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; private const string QueryInspectionPattern = @"\s+(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; private const string OptimisticDirectExecution = "OptimisticDirectExecution"; @@ -250,9 +251,9 @@ private static async Task> TryCreateFromPartitione TryCatch tryCreatePipelineStage; Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( - inputParameters, - partitionedQueryExecutionInfo, - cosmosQueryContext, + inputParameters, + partitionedQueryExecutionInfo, + cosmosQueryContext, containerQueryProperties, trace); @@ -761,13 +762,18 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ContainerQueryProperties containerQueryProperties, ITrace trace) { - if (!inputParameters.EnableOptimisticDirectExecution) + bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); + + // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true + if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) { - if (inputParameters.InitialUserContinuationToken != null - && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) + if (inputParameters.InitialUserContinuationToken != null + && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) { - throw new MalformedContinuationTokenException($"The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. " + - $"{inputParameters.InitialUserContinuationToken}"); + string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + + "If the error persists after that, contact system administrator."; + + throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}"); } return null; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs index d9dc0ac976..f32ab1035c 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs @@ -63,6 +63,8 @@ public abstract Task> ExecuteItemQueryAsync( ITrace trace, CancellationToken cancellationToken); + public abstract Task GetClientDisableOptimisticDirectExecutionAsync(); + public abstract Task ExecuteQueryPlanRequestAsync( string resourceUri, Documents.ResourceType resourceType, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs index 6f95673d80..dcb17d6463 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs @@ -12,6 +12,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan using System.Text; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Tracing; @@ -46,6 +47,9 @@ internal sealed class QueryPartitionProvider : IDisposable private bool disposed; private string queryengineConfiguration; + // TODO: Move this into a config class of its own + public bool ClientDisableOptimisticDirectExecution { get; private set; } + public QueryPartitionProvider(IDictionary queryengineConfiguration) { if (queryengineConfiguration == null) @@ -60,6 +64,7 @@ public QueryPartitionProvider(IDictionary queryengineConfigurati this.disposed = false; this.queryengineConfiguration = JsonConvert.SerializeObject(queryengineConfiguration); + this.ClientDisableOptimisticDirectExecution = GetClientDisableOptimisticDirectExecution((IReadOnlyDictionary)queryengineConfiguration); this.serviceProvider = IntPtr.Zero; this.serviceProviderStateLock = new object(); @@ -92,6 +97,7 @@ public void Update(IDictionary queryengineConfiguration) if (!string.Equals(this.queryengineConfiguration, newConfiguration)) { this.queryengineConfiguration = newConfiguration; + this.ClientDisableOptimisticDirectExecution = GetClientDisableOptimisticDirectExecution((IReadOnlyDictionary)queryengineConfiguration); if (!this.disposed && this.serviceProvider != IntPtr.Zero) { @@ -132,6 +138,7 @@ public TryCatch TryGetPartitionedQueryExecutionIn allowDCount: allowDCount, useSystemPrefix: useSystemPrefix, geospatialType: geospatialType); + if (!tryGetInternalQueryInfo.Succeeded) { return TryCatch.FromException(tryGetInternalQueryInfo.Exception); @@ -141,6 +148,16 @@ public TryCatch TryGetPartitionedQueryExecutionIn return TryCatch.FromResult(queryInfo); } + private static bool GetClientDisableOptimisticDirectExecution(IReadOnlyDictionary queryengineConfiguration) + { + if (queryengineConfiguration.TryGetValue(CosmosQueryExecutionContextFactory.ClientDisableOptimisticDirectExecution, out object queryConfigProperty)) + { + return (bool)queryConfigProperty; + } + + return false; + } + internal PartitionedQueryExecutionInfo ConvertPartitionedQueryExecutionInfo( PartitionedQueryExecutionInfoInternal queryInfoInternal, PartitionKeyDefinition partitionKeyDefinition) diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index a392632649..78fe2c985d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -209,6 +209,12 @@ public override async Task ExecuteQueryPlanReques return partitionedQueryExecutionInfo; } + public override async Task GetClientDisableOptimisticDirectExecutionAsync() + { + QueryPartitionProvider provider = await this.clientContext.DocumentClient.QueryPartitionProvider; + return provider.ClientDisableOptimisticDirectExecution; + } + public override async Task> GetTargetPartitionKeyRangeByFeedRangeAsync( string resourceLink, string collectionResourceId, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 78d4ddb8ed..0ac41b6f39 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -17,6 +17,7 @@ public sealed class OptimisticDirectExecutionQueryTests : QueryTestsBase private const string PartitionKeyField = "key"; private const string NumberField = "numberField"; private const string NullField = "nullField"; + private const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; private static class PageSizeOptions { @@ -538,6 +539,22 @@ await this.CreateIngestQueryDeleteAsync( documents, (container, documents) => RunFailingTests(container, invalidQueries), "/" + PartitionKeyField); + } + + //TODO: Remove Ignore flag once emulator is updated to 1101 + [Ignore] + [TestMethod] + public async Task TestClientDisableOdeDefaultValue() + { + string authKey = Utils.ConfigurationManager.AppSettings["MasterKey"]; + string endpoint = Utils.ConfigurationManager.AppSettings["GatewayEndpoint"]; + + CosmosClient client = new CosmosClient($"AccountEndpoint={endpoint};AccountKey={authKey}"); + AccountProperties properties = await client.ReadAccountAsync(); + + bool success = bool.TryParse(properties.QueryEngineConfiguration[ClientDisableOptimisticDirectExecution].ToString(), out bool clientDisablOde); + Assert.IsTrue(success, $"Parsing must succeed. Value supplied '{ClientDisableOptimisticDirectExecution}'"); + Assert.IsFalse(clientDisablOde); } private static async Task RunTests(IEnumerable testCases, Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 824232c412..8ec63b59ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -29,6 +29,7 @@ using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Routing; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; using Newtonsoft.Json; [TestClass] @@ -162,6 +163,7 @@ public void TestDefaultQueryRequestOptionsSettings() public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() { int numItems = 100; + int documentCountInSinglePartition = 0; OptimisticDirectExecutionTestInput input = CreateInput( description: @"Single Partition Key and Value Field", query: "SELECT VALUE COUNT(1) FROM c", @@ -172,7 +174,6 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: false); IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); - int documentCountInSinglePartition = 0; while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { @@ -214,13 +215,15 @@ public async Task TestOdeTokenWithSpecializedPipeline() DocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems, multiPartition: false); QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: input.ExpectedOptimisticDirectExecution); (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, inputParameters, NoOpTrace.Singleton); - string expectedErrorMessage = "The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. "; + string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + + "If the error persists after that, contact system administrator."; while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { @@ -446,7 +449,7 @@ public async Task TestQueryValidityCheckWithODEAsync() } catch (Exception ex) { - Assert.IsTrue(ex.InnerException.Message.Contains(testCase.ExpectedMessage)); + Assert.IsTrue(ex.InnerException.InnerException.Message.Contains(testCase.ExpectedMessage)); continue; } } @@ -494,6 +497,88 @@ public async Task TestPipelineForDistributedQueryAsync() Assert.AreEqual(1, result); } + [TestMethod] + public async Task TestClientDisableOdeLogic() + { + // GetPipelineAndDrainAsyc() contains asserts to confirm that the Ode pipeline only gets picked if clientDisableOptimisticDirectExecution flag is false + int numItems = 100; + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Value Field", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + // Test with ClientDisableOde = true + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: 10, + requiresDist: false, + clientDisableOde: true); + + Assert.AreEqual(numItems, result); + + // Test with ClientDisableOde = false + result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: 10, + requiresDist: false, + clientDisableOde: false); + + Assert.AreEqual(numItems, result); + } + + [TestMethod] + public async Task TestOdeFlagsWithContinuationToken() + { + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: Guid.NewGuid().ToString(), + range: new Range("A", "B", true, false)); + + OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); + CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); + + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: cosmosElementContinuationToken); + + // All of these cases should throw the same exception message. + await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: true, clientDisableOde: true); + await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: true); + await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: false); + } + + private async Task ValidateErrorMessageWithModifiedOdeFlags(OptimisticDirectExecutionTestInput input, bool enableOde, bool clientDisableOde) + { + string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + + "If the error persists after that, contact system administrator."; + try + { + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 10, + requiresDist: false, + enableOde, + clientDisableOde); + + Assert.Fail("A MalformedContinuationTokenException was expected in this scenario"); + } + catch (Exception ex) + { + Assert.IsTrue(ex.InnerException.Message.Contains(expectedErrorMessage)); + } + } + // Creates a gone exception after the first MoveNexyAsync() call. This allows for the pipeline to return some documents before failing private static async Task ExecuteGoneExceptionOnODEPipeline(bool isMultiPartition) { @@ -584,23 +669,28 @@ private static async Task TestHandlingOfFailedFallbackPipeline(bool isMult return (mergeTest, queryPipelineStage); } - private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestInput input, int numItems, bool isMultiPartition, int expectedContinuationTokenCount, bool requiresDist = false) + private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestInput input, int numItems, bool isMultiPartition, int expectedContinuationTokenCount, bool requiresDist = false, bool enableOptimisticDirectExecution = true, bool clientDisableOde = false) { - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); - IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); - List documents = new List(); int continuationTokenCount = 0; + List documents = new List(); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); + IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions, clientDisableOde); while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) { - if (!requiresDist) + TryCatch tryGetPage = queryPipelineStage.Current; + tryGetPage.ThrowIfFailed(); + + if (clientDisableOde || !enableOptimisticDirectExecution) { - Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - TryCatch tryGetPage = queryPipelineStage.Current; - tryGetPage.ThrowIfFailed(); + if (!clientDisableOde && enableOptimisticDirectExecution && !requiresDist) + { + Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + } documents.AddRange(tryGetPage.Result.Documents); @@ -628,9 +718,10 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn return documents.Count; } - internal static TryCatch TryGetPartitionedQueryExecutionInfo(string querySpecJsonString, PartitionKeyDefinition pkDefinition) + internal static Tuple GetPartitionedQueryExecutionInfoAndPartitionProvider(string querySpecJsonString, PartitionKeyDefinition pkDefinition, bool clientDisableOde = false) { - TryCatch tryGetQueryPlan = QueryPartitionProviderTestInstance.Object.TryGetPartitionedQueryExecutionInfo( + QueryPartitionProvider queryPartitionProvider = CreateCustomQueryPartitionProvider("clientDisableOptimisticDirectExecution", clientDisableOde.ToString().ToLower()); + TryCatch tryGetQueryPlan = queryPartitionProvider.TryGetPartitionedQueryExecutionInfo( querySpecJsonString: querySpecJsonString, partitionKeyDefinition: pkDefinition, requireFormattableOrderByQuery: true, @@ -640,14 +731,14 @@ internal static TryCatch TryGetPartitionedQueryEx allowDCount: true, useSystemPrefix: false, geospatialType: Cosmos.GeospatialType.Geography); - - return tryGetQueryPlan; + + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = tryGetQueryPlan.Succeeded ? tryGetQueryPlan.Result : throw tryGetQueryPlan.Exception; + return Tuple.Create(partitionedQueryExecutionInfo, queryPartitionProvider); } - private static Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) + private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) { - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, clientDisableOde); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -655,7 +746,7 @@ private static Task GetOdePipelineAsync(OptimisticDirectExe NoOpTrace.Singleton); Assert.IsNotNull(queryPipelineStage); - return Task.FromResult(queryPipelineStage); + return queryPipelineStage; } private static async Task CreateDocumentContainerAsync( @@ -725,6 +816,38 @@ private static async Task CreateDocumentContainerAsync( return documentContainer; } + private static QueryPartitionProvider CreateCustomQueryPartitionProvider(string key, string value) + { + Dictionary queryEngineConfiguration = new Dictionary() + { + {"maxSqlQueryInputLength", 262144}, + {"maxJoinsPerSqlQuery", 5}, + {"maxLogicalAndPerSqlQuery", 2000}, + {"maxLogicalOrPerSqlQuery", 2000}, + {"maxUdfRefPerSqlQuery", 10}, + {"maxInExpressionItemsCount", 16000}, + {"queryMaxGroupByTableCellCount", 500000 }, + {"queryMaxInMemorySortDocumentCount", 500}, + {"maxQueryRequestTimeoutFraction", 0.90}, + {"sqlAllowNonFiniteNumbers", false}, + {"sqlAllowAggregateFunctions", true}, + {"sqlAllowSubQuery", true}, + {"sqlAllowScalarSubQuery", true}, + {"allowNewKeywords", true}, + {"sqlAllowLike", true}, + {"sqlAllowGroupByClause", true}, + {"maxSpatialQueryCells", 12}, + {"spatialMaxGeometryPointCount", 256}, + {"sqlDisableQueryILOptimization", false}, + {"sqlDisableFilterPlanOptimization", false}, + {"clientDisableOptimisticDirectExecution", false} + }; + + queryEngineConfiguration[key] = bool.TryParse(value, out bool boolValue) ? boolValue : value; + + return new QueryPartitionProvider(queryEngineConfiguration); + } + private static OptimisticDirectExecutionTestInput CreateInput( string description, string query, @@ -755,11 +878,8 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect // gets DocumentContainer IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(input.PartitionKeyDefinition); DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -783,12 +903,13 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); } - private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions) + private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(input.Query), Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, input.PartitionKeyDefinition, clientDisableOde); CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( sqlQuerySpec: new SqlQuerySpec(input.Query), initialUserContinuationToken: input.ContinuationToken, @@ -807,7 +928,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect string databaseId = "db1234"; string resourceLink = $"dbs/{databaseId}/colls"; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(), + client: new TestCosmosQueryClient(queryPartitionProvider), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), @@ -1032,6 +1153,13 @@ public override void SerializeAsXml(XmlWriter xmlWriter) internal class TestCosmosQueryClient : CosmosQueryClient { + private readonly QueryPartitionProvider queryPartitionProvider; + + public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider) + { + this.queryPartitionProvider = queryPartitionProvider; + } + public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); public override bool BypassQueryParsing() @@ -1075,6 +1203,11 @@ public override Task GetCachedContainerQueryProperties Cosmos.GeospatialType.Geometry)); } + public override async Task GetClientDisableOptimisticDirectExecutionAsync() + { + return this.queryPartitionProvider.ClientDisableOptimisticDirectExecution; + } + public override Task> GetTargetPartitionKeyRangeByFeedRangeAsync(string resourceLink, string collectionResourceId, PartitionKeyDefinition partitionKeyDefinition, FeedRangeInternal feedRangeInternal, bool forceRefresh, ITrace trace) { throw new NotImplementedException(); @@ -1095,15 +1228,14 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); - - TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; - return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); + + (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, partitionKeyDefinition); + return TryCatch.FromResult(partitionedQueryExecutionInfo); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index b02f19374a..ce2d808304 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -390,8 +390,7 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); - TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; + (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, partitionKeyDefinition); return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); } ); From ea269c99b54a2ac2a4394edbcb50b2ed0cb6c0b0 Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:41:39 -0800 Subject: [PATCH 243/337] [Internal] Query: Adds ClientQL Compatibility Level support on client (#4177) * Added ability to accept the AllowOptimisticDirectExecution flag from the backend and use that flag to decide if the Ode pipeline should be used or not. * Added comment and removed extra spacing * Added test coverage * Added exception handling logic * Resolved comments * Added null check for key parameter * Removed changes to common test infra * Removed all changes from QueryPartitionProviderTestInstance * Remove changes pt2 * Removed the dictionary in QueryPartitionProvider and added a bool instead * Updated GetClientDisableOptimisticDirectExecution() * Fixed comments * Revert QueryIterator.cs * Undoing changes to settings.json * Undoing changes to QueryIterator.cs * Updated error message * Made functions static * Cast to bool instead of recasting in GetClientDisableOptimisticDirectExecution() * Added clientQLCompatibilityLevel support on client * Updated assert * Updated client tests to use Data Contract serializer and deserializer * Added support to obtain the distribution plan payload on the client * Added binary support * Removed CheckCompatibilityLevelFlagInQuerySpec() * Renamed ParseElementsFromRestStream() * Updated test response * Switched to using binary json navigator * Using local variable before type check * Updated name to DistributionPlanSpec * Added support to test multiple distribution plan samples * Removed binary sample * Updated binary test * Added ignore flag * Fixed merge conflicts 2.0 * Resolved comments * Updated function name * Removed an unnecessary assert * Fixed comment * Improved debug assert message * Added checks to confirm that resourceType is document before getting distributionPlan * Removed changes to resourceManagement.yml --- .../src/Query/Core/DistributionPlanSpec.cs | 31 + .../AggregateQueryPipelineStage.Client.cs | 1 + .../AggregateQueryPipelineStage.Compute.cs | 2 + ...OrderByCrossPartitionQueryPipelineStage.cs | 8 + ...arallelCrossPartitionQueryPipelineStage.cs | 1 + .../DCount/DCountQueryPipelineStage.Client.cs | 1 + .../DCountQueryPipelineStage.Compute.cs | 2 + .../DistinctQueryPipelineStage.Client.cs | 2 + .../DistinctQueryPipelineStage.Compute.cs | 1 + .../GroupByQueryPipelineStage.Client.cs | 1 + .../GroupByQueryPipelineStage.Compute.cs | 2 + ...misticDirectExecutionQueryPipelineStage.cs | 10 +- .../Core/Pipeline/Pagination/QueryPage.cs | 4 + .../Skip/SkipQueryPipelineStage.Client.cs | 1 + .../Skip/SkipQueryPipelineStage.Compute.cs | 1 + .../SkipEmptyPageQueryPipelineStage.cs | 3 + .../Take/TakeQueryPipelineStage.Client.cs | 1 + .../Take/TakeQueryPipelineStage.Compute.cs | 1 + .../src/Query/Core/SqlQuerySpec.cs | 9 +- .../Query/v3Query/CosmosQueryClientCore.cs | 77 +- .../ReadFeedCrossFeedRangeAsyncEnumerator.cs | 6 +- .../ClientTests.cs | 126 +- .../Pagination/FlakyDocumentContainer.cs | 1 + .../Pagination/InMemoryContainer.cs | 1 + .../OrderByQueryResultTests.cs | 6 +- .../Binary/BinarySample.json | 10 + .../Text/AggregateEnumerable.json | 689 ++++++++++ .../Text/ArrayCreateScalar.json | 645 ++++++++++ .../DistributionPlans/Text/BinaryScalar.json | 659 ++++++++++ .../Text/Distinct-SelectEnumerable.json | 332 +++++ .../Text/GroupByEnumerable.json | 1137 +++++++++++++++++ .../DistributionPlans/Text/LiteralScalar.json | 359 ++++++ .../Text/SelectManyEnumerable.json | 396 ++++++ .../Text/SimpleEnumerable.json | 121 ++ .../Text/SystemFunctionCallScalar.json | 354 +++++ .../Text/TakeEnumerable.json | 337 +++++ ...misticDirectExecutionQueryBaselineTests.cs | 76 +- .../AggressivePrefetchPipelineTests.cs | 1 + .../Query/Pipeline/MockQueryPipelineStage.cs | 1 + ...ByCrossPartitionQueryPipelineStageTests.cs | 1 + .../SkipEmptyPageQueryPipelineStageTests.cs | 4 +- 41 files changed, 5327 insertions(+), 94 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/DistributionPlanSpec.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Binary/BinarySample.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/AggregateEnumerable.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/ArrayCreateScalar.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/BinaryScalar.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct-SelectEnumerable.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/GroupByEnumerable.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/LiteralScalar.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SelectManyEnumerable.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SystemFunctionCallScalar.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/TakeEnumerable.json diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/DistributionPlanSpec.cs b/Microsoft.Azure.Cosmos/src/Query/Core/DistributionPlanSpec.cs new file mode 100644 index 0000000000..119e2b4b02 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/DistributionPlanSpec.cs @@ -0,0 +1,31 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core +{ + using System; + + internal sealed class DistributionPlanSpec + { + public DistributionPlanSpec(string backendDistributionPlan, string clientDistributionPlan) + { + if (string.IsNullOrEmpty(backendDistributionPlan)) + { + throw new ArgumentException("Backend distribution plan cannot be null or empty."); + } + + if (string.IsNullOrEmpty(clientDistributionPlan)) + { + throw new ArgumentException("Client distribution plan cannot be null or empty."); + } + + this.BackendDistributionPlan = backendDistributionPlan; + this.ClientDistributionPlan = clientDistributionPlan; + } + + public string BackendDistributionPlan { get; } + + public string ClientDistributionPlan { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs index aab5a723f8..ddaea9aaa5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs @@ -126,6 +126,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: responseLengthBytes, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: default); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs index 4cd0de254e..8a34e69a8a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs @@ -146,6 +146,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: queryState); @@ -169,6 +170,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: default, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: default); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index 10c3b0ee5e..43f4176de3 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -115,6 +115,7 @@ private async ValueTask MoveNextAsync_Initialize_FromBeginningAsync( activityId: string.Empty, responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: this.state)); @@ -153,6 +154,7 @@ private async ValueTask MoveNextAsync_Initialize_FromBeginningAsync( activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, responseLengthInBytes: page.ResponseLengthInBytes, cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, additionalHeaders: page.AdditionalHeaders, state: null)); @@ -173,6 +175,7 @@ private async ValueTask MoveNextAsync_Initialize_FromBeginningAsync( activityId: page.ActivityId, responseLengthInBytes: page.ResponseLengthInBytes, cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, additionalHeaders: page.AdditionalHeaders, state: this.state)); @@ -235,6 +238,7 @@ private async ValueTask MoveNextAsync_Initialize_FilterAsync( activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, responseLengthInBytes: page.ResponseLengthInBytes, cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, additionalHeaders: page.AdditionalHeaders, state: null)); @@ -278,6 +282,7 @@ private async ValueTask MoveNextAsync_Initialize_FilterAsync( activityId: page.ActivityId, responseLengthInBytes: page.ResponseLengthInBytes, cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, additionalHeaders: page.AdditionalHeaders, state: InitializingQueryState)); @@ -426,6 +431,7 @@ private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace) activityId: default, responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: currentEnumerator.Current.Result.Page.AdditionalHeaders, state: this.state)); @@ -481,6 +487,7 @@ private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace) activityId: default, responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: currentEnumerator?.Current.Result.Page.AdditionalHeaders, state: this.state)); @@ -543,6 +550,7 @@ public ValueTask MoveNextAsync(ITrace trace) activityId: Guid.NewGuid().ToString(), responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: null)); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs index c9ccb31653..b84a36870e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs @@ -122,6 +122,7 @@ public async ValueTask MoveNextAsync(ITrace trace) backendQueryPage.ActivityId, backendQueryPage.ResponseLengthInBytes, backendQueryPage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, backendQueryPage.DisallowContinuationTokenMessage, backendQueryPage.AdditionalHeaders, queryState); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs index 86a1a000fe..162408e6ff 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs @@ -107,6 +107,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: responseLengthBytes, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: additionalHeaders, state: default); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs index 9068017ee5..0970be1706 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs @@ -128,6 +128,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: queryState); @@ -151,6 +152,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: default, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: default); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs index fbde8890ee..c250193a60 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs @@ -173,6 +173,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: state); @@ -185,6 +186,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: ClientDistinctQueryPipelineStage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: null); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs index 571cfd9694..06921710c4 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs @@ -131,6 +131,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: ComputeDistinctQueryPipelineStage.UseTryGetContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: queryState); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs index dad99bb26b..5d82409a19 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs @@ -120,6 +120,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: responseLengthInBytes, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: ClientGroupByQueryPipelineStage.ContinuationTokenNotSupportedWithGroupBy, additionalHeaders: addtionalHeaders, state: default); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs index 7b1963c7b0..2183952a1d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs @@ -142,6 +142,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: null, additionalHeaders: sourcePage.AdditionalHeaders, state: state); @@ -172,6 +173,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: default, responseLengthInBytes: default, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: state); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index e62ecf41f0..c968c0b34f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -47,7 +47,6 @@ private OptimisticDirectExecutionQueryPipelineStage(TryCatch> FallbackQueryPipelineStageFactory(CosmosElement continuationToken); @@ -165,6 +164,7 @@ public static TryCatch MonadicCreate( private sealed class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage { + private const int ClientQLCompatibilityLevel = 1; private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; private OptimisticDirectExecutionQueryPipelineImpl( @@ -230,6 +230,7 @@ public async ValueTask MoveNextAsync(ITrace trace) backendQueryPage.ActivityId, backendQueryPage.ResponseLengthInBytes, backendQueryPage.CosmosQueryExecutionInfo, + backendQueryPage.DistributionPlanSpec, disallowContinuationTokenMessage: null, backendQueryPage.AdditionalHeaders, queryState); @@ -268,10 +269,15 @@ public static TryCatch MonadicCreate( return TryCatch.FromException(monadicExtractState.Exception); } + SqlQuerySpec updatedSqlQuerySpec = new SqlQuerySpec(sqlQuerySpec.QueryText, sqlQuerySpec.Parameters) + { + ClientQLCompatibilityLevel = ClientQLCompatibilityLevel + }; + FeedRangeState feedRangeState = monadicExtractState.Result; QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( documentContainer, - sqlQuerySpec, + updatedSqlQuerySpec, feedRangeState, partitionKey, queryPaginationOptions, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs index 1fea010222..eab1f61c79 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs @@ -27,6 +27,7 @@ public QueryPage( string activityId, long responseLengthInBytes, Lazy cosmosQueryExecutionInfo, + DistributionPlanSpec distributionPlanSpec, string disallowContinuationTokenMessage, IReadOnlyDictionary additionalHeaders, QueryState state) @@ -35,6 +36,7 @@ public QueryPage( this.Documents = documents ?? throw new ArgumentNullException(nameof(documents)); this.ResponseLengthInBytes = responseLengthInBytes < 0 ? throw new ArgumentOutOfRangeException(nameof(responseLengthInBytes)) : responseLengthInBytes; this.CosmosQueryExecutionInfo = cosmosQueryExecutionInfo; + this.DistributionPlanSpec = distributionPlanSpec; this.DisallowContinuationTokenMessage = disallowContinuationTokenMessage; } @@ -44,6 +46,8 @@ public QueryPage( public Lazy CosmosQueryExecutionInfo { get; } + public DistributionPlanSpec DistributionPlanSpec { get; } + public string DisallowContinuationTokenMessage { get; } protected override ImmutableHashSet DerivedClassBannedHeaders => QueryPage.BannedHeaders; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs index 5a4c6a3bbe..7f80df9930 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs @@ -144,6 +144,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: state); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs index 29412a1b2b..a7cd0ddea2 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs @@ -125,6 +125,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: state); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs index 17c6aa4e90..95be4d4003 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs @@ -56,6 +56,7 @@ public async ValueTask MoveNextAsync(ITrace trace) activityId: Guid.Empty.ToString(), responseLengthInBytes: this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: this.cumulativeAdditionalHeaders, state: default); @@ -92,6 +93,7 @@ public async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes + this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: default); @@ -117,6 +119,7 @@ public async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes + this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: sourcePage.State); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs index b67a8c3a47..2d403ae45a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs @@ -231,6 +231,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: state); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs index f897a559a9..7e1e8d6f62 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs @@ -148,6 +148,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) activityId: sourcePage.ActivityId, responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, state: queryState); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs index d03eb25629..67a684965b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs @@ -14,7 +14,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core internal sealed class SqlQuerySpec { private SqlParameterCollection parameters; - + /// /// Initializes a new instance of the class for the Azure Cosmos DB service. /// @@ -52,6 +52,13 @@ public SqlQuerySpec(string queryText, SqlParameterCollection parameters) [DataMember(Name = "query")] public string QueryText { get; set; } + /// + /// Gets or sets the ClientQL Compatibility Level supported by the client. + /// + /// The integer value representing the compatibility of the client. + [DataMember(Name = "clientQLCompatibilityLevel", EmitDefaultValue = false)] + public int? ClientQLCompatibilityLevel { get; set; } + /// /// Gets or sets the instance, which represents the collection of Azure Cosmos DB query parameters. /// diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index 78fe2c985d..a805786ca6 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -6,9 +6,11 @@ namespace Microsoft.Azure.Cosmos { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; + using System.Text; using System.Threading; using System.Threading.Tasks; @@ -329,9 +331,26 @@ private static TryCatch GetCosmosElementResponse( } long responseLengthBytes = memoryStream.Length; - CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( + CosmosQueryClientCore.ParseRestStream( memoryStream, - resourceType); + resourceType, + out CosmosArray documents, + out CosmosObject distributionPlan); + + DistributionPlanSpec distributionPlanSpec = null; + + if (distributionPlan != null) + { + bool backendPlan = distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan); + bool clientPlan = distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan); + + Debug.Assert(clientPlan == backendPlan, "Response Body Contract was violated. Out of the backend and client plans, only one is present in the distribution plan."); + + if (backendPlan && clientPlan) + { + distributionPlanSpec = new DistributionPlanSpec(backendDistributionPlan.ToString(), clientDistributionPlan.ToString()); + } + } QueryState queryState; if (cosmosResponseMessage.Headers.ContinuationToken != null) @@ -366,6 +385,7 @@ private static TryCatch GetCosmosElementResponse( cosmosResponseMessage.Headers.ActivityId, responseLengthBytes, cosmosQueryExecutionInfo, + distributionPlanSpec, disallowContinuationTokenMessage: null, additionalHeaders, queryState); @@ -438,10 +458,13 @@ private Task GetRoutingMapProviderAsync() /// /// The memory stream response for the query REST response Azure Cosmos /// The resource type - /// An array of CosmosElements parsed from the response body. - public static CosmosArray ParseElementsFromRestStream( + /// An array of CosmosElements parsed from the response body + /// An object containing the distribution plan for the client + public static void ParseRestStream( Stream stream, - ResourceType resourceType) + ResourceType resourceType, + out CosmosArray documents, + out CosmosObject distributionPlan) { if (!(stream is MemoryStream memoryStream)) { @@ -465,7 +488,25 @@ public static CosmosArray ParseElementsFromRestStream( // "_attachments": "attachments\/", // "_ts": 1501107886 // }], - // "_count": 1 + // "_count": 1, + // "_distributionPlan": { + // "backendDistributionPlan": { + // "query": "\nSELECT Count(r.a) AS count_a\nFROM r", + // "obfuscatedQuery": "{\"query\":\"SELECT Count(r.a) AS p1\\nFROM r\",\"parameters\":[]}", + // "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":1},\"From\":{\"Expr\":\"Aliased\"}}", + // "signature":-4885972563975185329, + // "shapeSignature":-6171928203673877984, + // "queryIL": {...}, + // "noSpatial": true, + // "language": "QueryIL" + // }, + // "coordinatorDistributionPlan": { + // "clientQL": { + // "Kind": "Input", + // "Name": "root" + // } + // } + // } // } // You want to create a CosmosElement for each document in "Documents". @@ -493,7 +534,29 @@ public static CosmosArray ParseElementsFromRestStream( throw new InvalidOperationException($"QueryResponse did not have an array of : {resourceName}"); } - return cosmosArray; + documents = cosmosArray; + + if (resourceType == ResourceType.Document && jsonNavigator.TryGetObjectProperty(jsonNavigator.GetRootNode(), "_distributionPlan", out ObjectProperty distributionPlanObjectProperty)) + { + switch (CosmosElement.Dispatch(jsonNavigator, distributionPlanObjectProperty.ValueNode)) + { + case CosmosString binaryDistributionPlan: + byte[] binaryJson = Convert.FromBase64String(binaryDistributionPlan.Value); + IJsonNavigator binaryJsonNavigator = JsonNavigator.Create(binaryJson); + IJsonNavigatorNode binaryJsonNavigatorNode = binaryJsonNavigator.GetRootNode(); + distributionPlan = CosmosObject.Create(binaryJsonNavigator, binaryJsonNavigatorNode); + break; + case CosmosObject textDistributionPlan: + distributionPlan = textDistributionPlan; + break; + default: + throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse did not have property: {resourceName}"); + } + } + else + { + distributionPlan = null; + } } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs index 95fb8b23cf..996b1eaf78 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs @@ -43,9 +43,11 @@ public async ValueTask MoveNextAsync() CrossFeedRangeState crossFeedRangeState = innerReadFeedPage.State; ReadFeedCrossFeedRangeState? state = crossFeedRangeState != null ? new ReadFeedCrossFeedRangeState(crossFeedRangeState.Value) : (ReadFeedCrossFeedRangeState?)null; - CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( + CosmosQueryClientCore.ParseRestStream( innerReadFeedPage.Page.Content, - Documents.ResourceType.Document); + Documents.ResourceType.Document, + out CosmosArray documents, + out CosmosObject distributionPlan); ReadFeedPage page = new ReadFeedPage( documents, innerReadFeedPage.Page.RequestCharge, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index 9bbbb980e3..cbe1343106 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Net.Http; using System.Net.Security; using System.Reflection; + using System.Runtime.Serialization.Json; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; @@ -511,157 +512,105 @@ public void SqlQuerySpecSerializationTest() { Action verifyJsonSerialization = (expectedText, query) => { - string actualText = JsonConvert.SerializeObject(query); + string actualText = SerializeQuerySpecToJson(query); + SqlQuerySpec querySpec = DeserializeJsonToQuerySpec(actualText); + string otherText = SerializeQuerySpecToJson(querySpec); Assert.AreEqual(expectedText, actualText); - - SqlQuerySpec otherQuery = JsonConvert.DeserializeObject(actualText); - string otherText = JsonConvert.SerializeObject(otherQuery); Assert.AreEqual(expectedText, otherText); }; Action verifyJsonSerializationText = (text) => { - SqlQuerySpec query = JsonConvert.DeserializeObject(text); - string otherText = JsonConvert.SerializeObject(query); + + SqlQuerySpec querySpec = DeserializeJsonToQuerySpec(text); + string otherText = SerializeQuerySpecToJson(querySpec); Assert.AreEqual(text, otherText); }; // Verify serialization - verifyJsonSerialization("{\"query\":null}", new SqlQuerySpec()); - verifyJsonSerialization("{\"query\":\"SELECT 1\"}", new SqlQuerySpec("SELECT 1")); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[{\"name\":null,\"value\":null}]}", + verifyJsonSerialization("{\"parameters\":[],\"query\":null}", new SqlQuerySpec()); + verifyJsonSerialization("{\"parameters\":[],\"query\":\"SELECT 1\"}", new SqlQuerySpec("SELECT 1")); + verifyJsonSerialization("{\"parameters\":[{\"name\":null,\"value\":null}],\"query\":\"SELECT 1\"}", new SqlQuerySpec() { QueryText = "SELECT 1", Parameters = new SqlParameterCollection() { new SqlParameter() } }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + + verifyJsonSerialization("{\"parameters\":[" + "{\"name\":\"@p1\",\"value\":5}" + - "]}", + "],\"query\":\"SELECT 1\"}", new SqlQuerySpec() { QueryText = "SELECT 1", Parameters = new SqlParameterCollection() { new SqlParameter("@p1", 5) } }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + + verifyJsonSerialization("{\"parameters\":[" + "{\"name\":\"@p1\",\"value\":5}," + "{\"name\":\"@p1\",\"value\":true}" + - "]}", + "],\"query\":\"SELECT 1\"}", new SqlQuerySpec() { QueryText = "SELECT 1", Parameters = new SqlParameterCollection() { new SqlParameter("@p1", 5), new SqlParameter("@p1", true) } }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + + verifyJsonSerialization("{\"parameters\":[" + "{\"name\":\"@p1\",\"value\":\"abc\"}" + - "]}", + "],\"query\":\"SELECT 1\"}", new SqlQuerySpec() { QueryText = "SELECT 1", Parameters = new SqlParameterCollection() { new SqlParameter("@p1", "abc") } }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + + verifyJsonSerialization("{\"parameters\":[" + "{\"name\":\"@p1\",\"value\":[1,2,3]}" + - "]}", + "],\"query\":\"SELECT 1\"}", new SqlQuerySpec() { QueryText = "SELECT 1", Parameters = new SqlParameterCollection() { new SqlParameter("@p1", new int[] { 1, 2, 3 }) } }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,3]}}" + - "]}", - new SqlQuerySpec() - { - QueryText = "SELECT 1", - Parameters = new SqlParameterCollection() { new SqlParameter("@p1", JObject.Parse("{\"a\":[1,2,3]}")) } - }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,3]}}" + - "]}", - new SqlQuerySpec() - { - QueryText = "SELECT 1", - Parameters = new SqlParameterCollection() { new SqlParameter("@p1", new JRaw("{\"a\":[1,2,3]}")) } - }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,3]}}" + - "]}", - new SqlQuerySpec() - { - QueryText = "SELECT 1", - Parameters = new SqlParameterCollection() { new SqlParameter("@p1", new JRaw("{\"a\":[1,2,3]}")) }, - }); - verifyJsonSerialization("{\"query\":\"SELECT 1\",\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,3]}}" + - "]}", - new SqlQuerySpec() - { - QueryText = "SELECT 1", - Parameters = new SqlParameterCollection() { new SqlParameter("@p1", new JRaw("{\"a\":[1,2,3]}")) }, - }); // Verify roundtrips - verifyJsonSerializationText("{\"query\":null}"); - verifyJsonSerializationText("{\"query\":\"SELECT 1\"}"); + verifyJsonSerializationText("{\"parameters\":[],\"query\":null}"); + verifyJsonSerializationText("{\"parameters\":[],\"query\":\"SELECT 1\"}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":null,\"value\":null}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":\"@p1\",\"value\":null}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":\"@p1\",\"value\":true}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":\"@p1\",\"value\":false}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":\"@p1\",\"value\":123}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); verifyJsonSerializationText( "{" + - "\"query\":\"SELECT 1\"," + "\"parameters\":[" + "{\"name\":\"@p1\",\"value\":\"abc\"}" + - "]" + - "}"); - verifyJsonSerializationText( - "{" + - "\"query\":\"SELECT 1\"," + - "\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,\"abc\"]}}" + - "]" + - "}"); - verifyJsonSerializationText( - "{" + - "\"query\":\"SELECT 1\"," + - "\"parameters\":[" + - "{\"name\":\"@p1\",\"value\":{\"a\":[1,2,\"abc\"]}}" + - "]" + + "]," + "\"query\":\"SELECT 1\"" + "}"); } @@ -977,6 +926,29 @@ public static IReadOnlyList GetActiveConnections() return connections; } } + + private static string SerializeQuerySpecToJson(SqlQuerySpec querySpec) + { + string queryText; + using (MemoryStream stream = new MemoryStream()) + { + new DataContractJsonSerializer(typeof(SqlQuerySpec), new[] { typeof(object[]), typeof(int[]), typeof(SqlParameterCollection) }).WriteObject(stream, querySpec); + queryText = Encoding.UTF8.GetString(stream.ToArray()); + } + + return queryText; + } + + private static SqlQuerySpec DeserializeJsonToQuerySpec(string queryText) + { + SqlQuerySpec querySpec; + using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(queryText))) + { + querySpec = (SqlQuerySpec)new DataContractJsonSerializer(typeof(SqlQuerySpec), new[] { typeof(object[]), typeof(int[]), typeof(SqlParameterCollection) }).ReadObject(stream); + } + + return querySpec; + } } internal static class StringHelper diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs index cc038ff4ed..132d575905 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs @@ -170,6 +170,7 @@ public async Task> MonadicQueryAsync( activityId: Guid.NewGuid().ToString(), responseLengthInBytes: "[]".Length, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: feedRangeState.State ?? StateForStartedButNoDocumentsReturned)); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs index 5c6e8961e7..7d17786159 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs @@ -649,6 +649,7 @@ public virtual Task> MonadicQueryAsync( activityId: Guid.NewGuid().ToString(), responseLengthInBytes: 1337, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: additionalHeaders.ToImmutable(), state: queryState))); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs index 7207f897be..3ca62e4057 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs @@ -29,9 +29,11 @@ public void TestOrderByUndefined() MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testResponse)); - CosmosArray documents = CosmosQueryClientCore.ParseElementsFromRestStream( + CosmosQueryClientCore.ParseRestStream( memoryStream, - Documents.ResourceType.Document); + Documents.ResourceType.Document, + out CosmosArray documents, + out CosmosObject distributionPlan); List orderByQueryResults = documents.Select(x => new OrderByQueryResult(x)).ToList(); Assert.AreEqual(14, orderByQueryResults.Count); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Binary/BinarySample.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Binary/BinarySample.json new file mode 100644 index 0000000000..6a42acce6b --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Binary/BinarySample.json @@ -0,0 +1,10 @@ +{ + "_rid": "AgAAAP-tzwk=", + "Documents": [ + { + "count_a": 30 + } + ], + "_count": 1, + "_distributionPlan": "gOsBBJdiYWNrZW5kRGlzdHJpYnV0aW9uUGxhbussA4VxdWVyeaQKU0VMRUNUIENvdW50KHIuYSkgQVMgY291bnRfYQpGUk9NIHKPb2JmdXNjYXRlZFF1ZXJ5u3sicXVlcnkiOiJTRUxFQ1QgQ291bnQoci5hKSBBUyBwMVxuRlJPTSByIiwicGFyYW1ldGVycyI6W119hXNoYXBlwEF7IlNlbGVjdCI6eyJUeXBlIjoiTGlzdCIsIkFnZ0NvdW50IjoxfSwiRnJvbSI6eyJFeHByIjoiQWxpYXNlZCJ9fYlzaWduYXR1cmXLT1z0DdeJMbyOc2hhcGVTaWduYXR1cmXLIMLNwP\/nWKqHcXVlcnlJTOmKRXhwcmVzc2lvbusOAoRLaW5kiUFnZ3JlZ2F0ZTfqQsQhAYRFbnVtiEl0ZW1UeXBl6i\/EIQGEQmFzZYxCYXNlVHlwZUtpbmSGTnVtYmVykUV4Y2x1ZGVzVW5kZWZpbmVk0sQmAephxCEBh0J1aWx0aW6JU2lnbmF0dXJl6jfEOwHqFcQhAcRJAcROAYdWYXJpYW50xGIB0YpSZXN1bHRUeXBl6hDEIQHESQHETgHEWwHEYgHSjE9wZXJhdG9yS2luZIVDb3VudJBTb3VyY2VFeHByZXNzaW9u60ABxCEBhlNlbGVjdDfqG8QhAcQ2AcQ7AeoQxCEBxEkBxE4BxJ8BxGIB0YhEZWxlZ2F0ZerexCEBkFNjYWxhckV4cHJlc3Npb2436hDEIQHESQHETgHEnwHEYgHRkERlY2xhcmVkVmFyaWFibGXqITaCdjCIVW5pcXVlSWQAN+oQxCEBxEkBxE4BxJ8BxGIB0sQTAep+xCEBi1Byb3BlcnR5UmVmN+oQxCEBxEkBxE4BxJ8BxGIB0cQTAepIxCEBi1ZhcmlhYmxlUmVmN+oQxCEBxEkBxE4BxJ8BxGIB0ohWYXJpYWJsZeobNoJ2MMRgAgA36hDEIQHESQHETgHEnwHEYgHSjFByb3BlcnR5TmFtZYFhxNsB6irEIQGFSW5wdXQ36hvEIQHENgHEOwHqEMQhAcRJAcROAcSfAcRiAdI2gXKJbm9TcGF0aWFs0ohsYW5ndWFnZYdRdWVyeUlMlmNsaWVudERpc3RyaWJ1dGlvblBsYW7piGNsaWVudFFM6pfEIQHE8gHESQLqCDaCdjDEYAICxBMB6lHEIQGMT2JqZWN0Q3JlYXRlik9iamVjdEtpbmSGT2JqZWN0ilByb3BlcnRpZXPh6iE2h2NvdW50X2HEEwHqE8QhAcSsAsTLAuoINoJ2MMRgAgLE2wHqKcQhAcQmAcQmAeoNxCEBxH0BxMgBg1N1bcTbAeoMxCEBxAgDNoRyb290" +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/AggregateEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/AggregateEnumerable.json new file mode 100644 index 0000000000..5dc3fd15c6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/AggregateEnumerable.json @@ -0,0 +1,689 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [ + {} + ], + "_count": 1, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT max(r.a+r.b) FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT max((r.a + r.b))\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":1},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 1617577102403904921, + "shapeSignature": -2200556368766744533, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + } + }, + "Index": 1 + } + ] + } + }, + "SourceExpression": { + "Kind": "Aggregate", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Aggregate": { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "OperatorKind": "Max" + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + }, + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "OperatorKind": "Add", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + "RightExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + } + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + } + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 1 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/ArrayCreateScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/ArrayCreateScalar.json new file mode 100644 index 0000000000..c72a4a964e --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/ArrayCreateScalar.json @@ -0,0 +1,645 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT [r.a, r.b] as arr FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT [r.a, r.b] AS p1\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": -4859180975618908982, + "shapeSignature": 1900106125401909581, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "arr", + "Expression": { + "Kind": "ArrayCreate", + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ] + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/BinaryScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/BinaryScalar.json new file mode 100644 index 0000000000..1fb50c5439 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/BinaryScalar.json @@ -0,0 +1,659 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT r.a AND r.b FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT (r.a AND r.b)\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 8670442764837589376, + "shapeSignature": -830497809479614178, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct-SelectEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct-SelectEnumerable.json new file mode 100644 index 0000000000..8d7afcca65 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct-SelectEnumerable.json @@ -0,0 +1,332 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT r.a FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT r.a\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 5623696622904809165, + "shapeSignature": -7071247513508949191, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/GroupByEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/GroupByEnumerable.json new file mode 100644 index 0000000000..fb4e7ae38c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/GroupByEnumerable.json @@ -0,0 +1,1137 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT r.a, max(r.b) FROM r GROUP BY r.a", + "obfuscatedQuery": "{\"query\":\"SELECT r.a, max(r.b)\\nFROM r\\nGROUP BY r.a\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":1},\"From\":{\"Expr\":\"Aliased\"},\"GroupBy\":{\"ItemCount\":1}}", + "signature": 5885090021484876333, + "shapeSignature": 4401005608116703893, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + }, + "Index": 1 + } + ] + } + }, + "SourceExpression": { + "Kind": "GroupBy", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Keys": [ + { + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + ], + "Aggregates": [ + { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "OperatorKind": "Max" + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "$1", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 1, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Max" + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 9 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 0 + }, + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 2 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/LiteralScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/LiteralScalar.json new file mode 100644 index 0000000000..999880ebdb --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/LiteralScalar.json @@ -0,0 +1,359 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT r.a = 5 as EqualsFive FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT (r.a = 5) AS p1__10\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 8545592500936011639, + "shapeSignature": -767125698482361778, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "EqualsFive", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SelectManyEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SelectManyEnumerable.json new file mode 100644 index 0000000000..60bdcb8027 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SelectManyEnumerable.json @@ -0,0 +1,396 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT (SELECT VALUE Count(1) FROM a2 IN c.a WHERE a2 = 435) as s\r\nFROM c\r\nGROUP BY c.a", + "obfuscatedQuery": "{\"query\":\"SELECT (SELECT VALUE Count(1)\\nFROM r1 IN c.a\\nWHERE (r1 = 440.01)) AS s\\nFROM c\\nGROUP BY c.a\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\"},\"From\":{\"Expr\":\"Aliased\"},\"GroupBy\":{\"ItemCount\":1}}", + "signature": -1004994291944242492, + "shapeSignature": 7117013218658174347, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 18, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 18, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 7, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 15, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 15, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "c" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 16 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "s", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 16 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "SelectorExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 9 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 19 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 19 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json new file mode 100644 index 0000000000..b491479a58 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json @@ -0,0 +1,121 @@ +{ + "_rid": "AgAAALHVPPs=", + "Documents": [ + { + "count_a": 30 + } + ], + "_count": 1, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "\nSELECT Count(r.a) AS count_a\nFROM r", + "obfuscatedQuery": "{\"query\":\"SELECT Count(r.a) AS p1\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":1},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": -4885972563975185329, + "shapeSignature": -6171928203673877984, + "queryIL": { + "Expression": { + "Kind": "Aggregate", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "Aggregate": { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Input", + "Name": "root" + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SystemFunctionCallScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SystemFunctionCallScalar.json new file mode 100644 index 0000000000..f29698aaf4 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SystemFunctionCallScalar.json @@ -0,0 +1,354 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT IS_INTEGER(r.a) FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT IS_INTEGER(r.a)\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": -4972642973329292581, + "shapeSignature": 4685047233331412499, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Integer", + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ] + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/TakeEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/TakeEnumerable.json new file mode 100644 index 0000000000..4b1395e995 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/TakeEnumerable.json @@ -0,0 +1,337 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT c.a FROM c OFFSET 2 LIMIT 5", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT c.a\\nFROM c\\nOFFSET 2 LIMIT 5\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"},\"OffsetLimit\":{\"Offset\":2,\"Limit\":5}}", + "signature": -4272373468412855685, + "shapeSignature": -4443273821025974173, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "c" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Take", + "SkipValue": 2, + "TakeValue": 5, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 8ec63b59ae..d236b73a56 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Net; + using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; @@ -31,6 +32,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json; + using Newtonsoft.Json.Linq; [TestClass] public class OptimisticDirectExecutionQueryBaselineTests : BaselineTests @@ -579,6 +581,72 @@ private async Task ValidateErrorMessageWithModifiedOdeFlags(OptimisticDirectExec } } + [TestMethod] + public async Task TestTextDistributionPlanParsingFromStream() + { + string textPath = "../../../Query/DistributionPlans/Text"; + string[] filePaths = Directory.GetFiles(textPath); + + foreach (string filePath in filePaths) + { + string testResponse = File.ReadAllText(filePath); + JObject jsonObject = JObject.Parse(testResponse); + + string expectedBackendPlan = jsonObject["_distributionPlan"]["backendDistributionPlan"].ToString(); + expectedBackendPlan = RemoveJsonFormattingFromString(expectedBackendPlan); + + string expectedClientPlan = jsonObject["_distributionPlan"]["clientDistributionPlan"].ToString(); + expectedClientPlan = RemoveJsonFormattingFromString(expectedClientPlan); + + MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testResponse)); + CosmosQueryClientCore.ParseRestStream( + memoryStream, + Documents.ResourceType.Document, + out CosmosArray documents, + out CosmosObject distributionPlan); + + if (distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan) && + distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan)) + { + Assert.AreEqual(expectedBackendPlan, RemoveJsonFormattingFromString(backendDistributionPlan.ToString())); + Assert.AreEqual(expectedClientPlan, RemoveJsonFormattingFromString(clientDistributionPlan.ToString())); + } + else + { + Assert.Fail(); + } + } + } + + [TestMethod] + public async Task TestBinaryDistributionPlanParsingFromStream() + { + string expectedBackendPlan = "{\"query\":\"\\nSELECT Count(r.a) AS count_a\\nFROM r\",\"obfuscatedQuery\":\"{\\\"query\\\":\\\"SELECT Count(r.a) AS p1\\\\nFROM r\\\",\\\"parameters\\\":[]}\",\"shape\":\"{\\\"Select\\\":{\\\"Type\\\":\\\"List\\\",\\\"AggCount\\\":1},\\\"From\\\":{\\\"Expr\\\":\\\"Aliased\\\"}}\",\"signature\":-4885972563975185329,\"shapeSignature\":-6171928203673877984,\"queryIL\":{\"Expression\":{\"Kind\":\"Aggregate\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Number\",\"ExcludesUndefined\":true}},\"Aggregate\":{\"Kind\":\"Builtin\",\"Signature\":{\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"ResultType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Number\",\"ExcludesUndefined\":true}},\"OperatorKind\":\"Count\"},\"SourceExpression\":{\"Kind\":\"Select\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false}},\"Delegate\":{\"Kind\":\"ScalarExpression\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"DeclaredVariable\":{\"Name\":\"v0\",\"UniqueId\":0,\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}},\"Expression\":{\"Kind\":\"PropertyRef\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"Expression\":{\"Kind\":\"VariableRef\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true},\"Variable\":{\"Name\":\"v0\",\"UniqueId\":0,\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}}},\"PropertyName\":\"a\"}},\"SourceExpression\":{\"Kind\":\"Input\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}},\"Name\":\"r\"}}}},\"noSpatial\":true,\"language\":\"QueryIL\"}"; + string expectedClientPlan = "{\"clientQL\":{\"Kind\":\"Select\",\"DeclaredVariable\":{\"Name\":\"v0\",\"UniqueId\":2},\"Expression\":{\"Kind\":\"ObjectCreate\",\"ObjectKind\":\"Object\",\"Properties\":[{\"Name\":\"count_a\",\"Expression\":{\"Kind\":\"VariableRef\",\"Variable\":{\"Name\":\"v0\",\"UniqueId\":2}}}]},\"SourceExpression\":{\"Kind\":\"Aggregate\",\"Aggregate\":{\"Kind\":\"Builtin\",\"OperatorKind\":\"Sum\"},\"SourceExpression\":{\"Kind\":\"Input\",\"Name\":\"root\"}}}}"; + + string textPath = "../../../Query/DistributionPlans/Binary"; + string[] filePaths = Directory.GetFiles(textPath); + string testResponse = File.ReadAllText(filePaths[0]); + + MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testResponse)); + CosmosQueryClientCore.ParseRestStream( + memoryStream, + Documents.ResourceType.Document, + out CosmosArray documents, + out CosmosObject distributionPlan); + + if (distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan) && + distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan)) + { + Assert.IsTrue(backendDistributionPlan.ToString().Equals(expectedBackendPlan)); + Assert.IsTrue(clientDistributionPlan.ToString().Equals(expectedClientPlan)); + } + else + { + Assert.Fail(); + } + } + // Creates a gone exception after the first MoveNexyAsync() call. This allows for the pipeline to return some documents before failing private static async Task ExecuteGoneExceptionOnODEPipeline(bool isMultiPartition) { @@ -644,6 +712,11 @@ private static async Task TestHandlingOfFailedFallbackPipeline(bool isMult return false; } + private static string RemoveJsonFormattingFromString(string jsonString) + { + return jsonString.Replace(" ", string.Empty).Replace("\t", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty); + } + private static async Task<(MergeTestUtil, IQueryPipelineStage)> CreateFallbackPipelineTestInfrastructure(int numItems, bool isFailedFallbackPipelineTest, bool isMultiPartition, QueryRequestOptions queryRequestOptions) { List documents = new List(); @@ -1012,6 +1085,7 @@ public override async Task> MonadicQueryAsync( activityId: Guid.NewGuid().ToString(), responseLengthInBytes: 1337, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: additionalHeaders.ToImmutable(), state: queryPage.Result.Result.State))); @@ -1033,7 +1107,6 @@ public MergeTestUtil(bool isFailedFallbackPipelineTest) this.IsFailedFallbackPipelineTest = isFailedFallbackPipelineTest; } -#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task ShouldReturnFailure() { this.MoveNextCounter++; @@ -1061,7 +1134,6 @@ public async Task ShouldReturnFailure() return null; } -#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs index f49285c325..102e532477 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs @@ -244,6 +244,7 @@ public override async Task> MonadicQueryAsync( activityId: "E7980B1F-436E-44DF-B7A5-655C56D38648", responseLengthInBytes: 48, cosmosQueryExecutionInfo: new Lazy(() => new CosmosQueryExecutionInfo(false, false)), + distributionPlanSpec: default, disallowContinuationTokenMessage: null, additionalHeaders: null, state: continuationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs index bc0c912c82..282b025031 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs @@ -59,6 +59,7 @@ public override ValueTask MoveNextAsync(ITrace trace) activityId: Guid.NewGuid().ToString(), responseLengthInBytes: default, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: state); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs index 52062c8afb..f1042ee6fb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs @@ -287,6 +287,7 @@ public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsy activityId: string.Empty, responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: default); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs index 7f0f3f93d9..1b88966a8c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs @@ -129,16 +129,18 @@ public enum PageType { Empty, NonEmpty, Error }; activityId: Guid.NewGuid().ToString(), responseLengthInBytes: "[]".Length, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: new QueryState(CosmosString.Create("Empty")))); private static readonly TryCatch NonEmpty = TryCatch.FromResult(new QueryPage( - documents: new List { CosmosElement.Parse("42") }, + documents: new List { CosmosElement.Parse("42") }, requestCharge: 100, activityId: Guid.NewGuid().ToString(), responseLengthInBytes: "[42]".Length, cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, state: new QueryState(CosmosString.Create("NonEmpty")))); From 7a32b96c621dc69acc305931d6c9bdb489f77482 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 19 Dec 2023 14:04:44 -0800 Subject: [PATCH 244/337] [Internal] CTL: Fixes docker image version dependency (#4216) * update csproj * image * Right image * Sigh --------- Co-authored-by: Kiran Kumar Kolli --- Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj | 6 +++--- Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj index 6b219668a5..ec83107b27 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CosmosCTL.csproj @@ -1,7 +1,7 @@ Exe - netcoreapp3.1 + net6 CosmosCTL CosmosCTL true @@ -14,8 +14,8 @@ - - + + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile index f7da30feca..0fc2f9fec3 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/dotnet/core/runtime:3.1 +FROM mcr.microsoft.com/dotnet/runtime:6.0 COPY artifacts/CTL/. /usr/app/. COPY run_ctl.sh /usr/app/. WORKDIR /usr/app From 3cb1c55678ce24b75f4271b00adfe1febe1871f8 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 20 Dec 2023 21:18:09 +0530 Subject: [PATCH 245/337] Distributed Tracing: Refactors Samples to use latest cosmosdb SDK (#4218) * Updated Cosmosd SDK version in Open telemetry and AppInsight Samples * clean up code * fixd samples * remove underscore from variable name --- .../ApplicationInsights.csproj | 4 +- .../Usage/ApplicationInsights/Program.cs | 55 +++++++++----- .../Usage/OpenTelemetry/OpenTelemetry.csproj | 7 +- .../Usage/OpenTelemetry/Program.cs | 71 +++++++++++++------ 4 files changed, 92 insertions(+), 45 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj index 59162abaca..2f48dc20f1 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/ApplicationInsights.csproj @@ -9,8 +9,8 @@ - - + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs index 526452beb2..7e1a6e2c4d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs @@ -4,19 +4,18 @@ using System.Threading.Tasks; using Newtonsoft.Json; using Microsoft.Azure.Cosmos; - using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.ApplicationInsights; using Microsoft.ApplicationInsights.WorkerService; - using Microsoft.Extensions.Logging.ApplicationInsights; + using Microsoft.ApplicationInsights.DataContracts; internal class Program { private static readonly string databaseName = "samples"; private static readonly string containerName = "ai-sample"; - private static TelemetryClient _telemetryClient; + private static TelemetryClient telemetryClient; static async Task Main() { @@ -49,35 +48,57 @@ static async Task Main() services.AddApplicationInsightsTelemetryWorkerService((ApplicationInsightsServiceOptions options) => options.ConnectionString = aiConnectionString); IServiceProvider serviceProvider = services.BuildServiceProvider(); - _telemetryClient = serviceProvider.GetRequiredService(); + telemetryClient = serviceProvider.GetRequiredService(); // - CosmosClientOptions options = new CosmosClientOptions() - { - IsDistributedTracingEnabled = true // Defaults to true, set to false to disable - }; - using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) - { - Console.WriteLine($"Getting container reference for {containerName}."); + var infoOperation = telemetryClient.StartOperation(".Net SDK : ApplicationInsights SDK"); // Application level activity to track the entire execution of the application - ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + var gops = telemetryClient.StartOperation("GATEWAY MODE"); // Activity to track the execution of the gateway mode + await Program.RunCosmosDbOperation(ConnectionMode.Gateway, endpoint, authKey); + telemetryClient.StopOperation(gops); - await client.CreateDatabaseIfNotExistsAsync(databaseName); - Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + var dops = telemetryClient.StartOperation("DIRECT MODE"); // Activity to track the execution of the direct mode + await Program.RunCosmosDbOperation(ConnectionMode.Direct, endpoint, authKey); + telemetryClient.StopOperation(dops); - await Program.RunCrudDemo(container); - } + telemetryClient.StopOperation(infoOperation); } finally { // Explicitly calling Flush() followed by sleep is required for Application Insights logging in console apps to ensure that telemetry is sent to the back-end even if application terminates. - _telemetryClient?.Flush(); + telemetryClient?.Flush(); await Task.Delay(5000); Console.WriteLine("End of demo."); } } + private static async Task RunCosmosDbOperation(ConnectionMode connMode, string endpoint, string authKey) + { + // + CosmosClientOptions options = new CosmosClientOptions() + { + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + }, + ConnectionMode = connMode + }; + // + + using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + await Program.RunCrudDemo(container); + } + } + public static async Task RunCrudDemo(Container container) { // Any operations will automatically generate telemetry diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj index 83224d4570..42eb521c7a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj @@ -9,10 +9,11 @@ - - - + + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs index b4729e41c7..562ccb2902 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs @@ -11,6 +11,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Azure.Monitor.OpenTelemetry.Exporter; + using System.Diagnostics; internal class Program { @@ -52,15 +53,15 @@ static async Task Main() serviceVersion: "1.0.0"); // Set up logging to forward logs to chosen exporter - using ILoggerFactory loggerFactory + using ILoggerFactory loggerFactory = LoggerFactory.Create(builder => builder .AddConfiguration(configuration.GetSection("Logging")) .AddOpenTelemetry(options => - { - options.IncludeFormattedMessage = true; - options.SetResourceBuilder(resource); - options.AddAzureMonitorLogExporter(o => o.ConnectionString = aiConnectionString); // Set up exporter of your choice - })); + { + options.IncludeFormattedMessage = true; + options.SetResourceBuilder(resource); + options.AddAzureMonitorLogExporter(o => o.ConnectionString = aiConnectionString); // Set up exporter of your choice + })); /*.AddFilter(level => level == LogLevel.Error) // Filter is irrespective of event type or event name*/ AzureEventSourceLogForwarder logforwader = new AzureEventSourceLogForwarder(loggerFactory); @@ -69,30 +70,28 @@ static async Task Main() // Configure OpenTelemetry trace provider AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); _traceProvider = Sdk.CreateTracerProviderBuilder() - .AddSource("Azure.Cosmos.Operation") // Cosmos DB source for operation level telemetry + .AddSource("Azure.Cosmos.Operation", // Cosmos DB source for operation level telemetry + "Azure.Cosmos.Request", // Cosmos DB source for DIRECT Mode network request level telemetry + "Sample.Application") .AddAzureMonitorTraceExporter(o => o.ConnectionString = aiConnectionString) // Set up exporter of your choice + .AddHttpClientInstrumentation() // Added to capture HTTP telemetry .SetResourceBuilder(resource) .Build(); // - // - CosmosClientOptions options = new CosmosClientOptions() + ActivitySource source = new ActivitySource("Sample.Application"); + using (_ = source.StartActivity(".Net SDK : Azure Monitor : Open Telemetry Sample")) // Application level activity to track the entire execution of the application { - IsDistributedTracingEnabled = true // Defaults to true, set to false to disable - }; - - // - using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) - { - Console.WriteLine($"Getting container reference for {containerName}."); - - ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); - - await client.CreateDatabaseIfNotExistsAsync(databaseName); - Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); - - await Program.RunCrudDemo(container); + using (_ = source.StartActivity("GATEWAY MODE")) // Activity to track the execution of the gateway mode + { + await Program.RunCosmosDbOperation(ConnectionMode.Gateway, endpoint, authKey); + } + using (_ = source.StartActivity("DIRECT MODE")) // Activity to track the execution of the direct mode + { + await Program.RunCosmosDbOperation(ConnectionMode.Direct, endpoint, authKey); + } } + } finally { @@ -104,6 +103,32 @@ static async Task Main() } } + private static async Task RunCosmosDbOperation(ConnectionMode connMode, string endpoint, string authKey) + { + // + CosmosClientOptions options = new CosmosClientOptions() + { + CosmosClientTelemetryOptions = new CosmosClientTelemetryOptions() + { + DisableDistributedTracing = false + }, + ConnectionMode = connMode + }; + // + + using (CosmosClient client = new CosmosClient(endpoint, authKey, options)) + { + Console.WriteLine($"Getting container reference for {containerName}."); + + ContainerProperties properties = new ContainerProperties(containerName, partitionKeyPath: "/id"); + + await client.CreateDatabaseIfNotExistsAsync(databaseName); + Container container = await client.GetDatabase(databaseName).CreateContainerIfNotExistsAsync(properties); + + await Program.RunCrudDemo(container); + } + } + public static async Task RunCrudDemo(Container container) { // Any operations will automatically generate telemetry From 1e49b16a93f7216493f7422292299d0338115f33 Mon Sep 17 00:00:00 2001 From: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Date: Thu, 21 Dec 2023 23:04:11 +0530 Subject: [PATCH 246/337] Client Encryption: Adds Microsoft.Azure.Cosmos compatibility to version 3.35.4 (#4214) * changing version * changing version * changing version * new versioning --------- Co-authored-by: Kiran Kumar Kolli --- Directory.Build.props | 6 +++--- Microsoft.Azure.Cosmos.Encryption/changelog.md | 10 ++++++++++ .../src/Microsoft.Azure.Cosmos.Encryption.csproj | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 57ee59de6f..05ef3a1ad8 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -4,9 +4,9 @@ 3.37.0 preview 3.31.5 - 2.0.3 - 2.0.3 - preview + 2.0.4 + 2.1.0 + preview4 1.0.0-preview06 1.1.0-preview3 10.0 diff --git a/Microsoft.Azure.Cosmos.Encryption/changelog.md b/Microsoft.Azure.Cosmos.Encryption/changelog.md index 2f50fcbdf3..791f512aea 100644 --- a/Microsoft.Azure.Cosmos.Encryption/changelog.md +++ b/Microsoft.Azure.Cosmos.Encryption/changelog.md @@ -3,6 +3,16 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [2.0.4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.4) - 2023-12-12 + +#### Added +- [#4214](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4214) Adds support for Microsoft.Azure.Cosmos from version 3.35.4 to 3.37.0 + +### [2.1.0-preview4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.1.0-preview4) - 2023-12-12 + +#### Added +- [#4214](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4214) Adds support for Microsoft.Azure.Cosmos 3.37.0-preview. + ### [2.0.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos.Encryption/2.0.3) - 2023-07-12 #### Added diff --git a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj index f7baa75f60..c58aca9785 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Encryption/src/Microsoft.Azure.Cosmos.Encryption.csproj @@ -28,11 +28,11 @@ - + - + From 5a096d11369124f85063747e7b767e0e9a400114 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 21 Dec 2023 16:28:38 -0800 Subject: [PATCH 247/337] Change Feed Processor: Fixes disposal of unused CancellationTokenSource (#4220) * Calling dispose * Tests * refactoring --- .../FeedManagement/PartitionControllerCore.cs | 7 ++++--- .../PartitionControllerSplitTests.cs | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs index e181dadbec..7407477c21 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs @@ -89,8 +89,7 @@ public override async Task AddOrUpdateLeaseAsync(DocumentServiceLease lease) throw; } - PartitionSupervisor supervisor = this.partitionSupervisorFactory.Create(lease); - this.ProcessPartitionAsync(supervisor, lease).LogException(); + this.ProcessPartitionAsync(lease).LogException(); } public override async Task ShutdownAsync() @@ -146,8 +145,10 @@ private async Task RemoveLeaseAsync(DocumentServiceLease lease, bool wasAcquired } } - private async Task ProcessPartitionAsync(PartitionSupervisor partitionSupervisor, DocumentServiceLease lease) + private async Task ProcessPartitionAsync(DocumentServiceLease lease) { + using PartitionSupervisor partitionSupervisor = this.partitionSupervisorFactory.Create(lease); + try { await partitionSupervisor.RunAsync(this.shutdownCts.Token).ConfigureAwait(false); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerSplitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerSplitTests.cs index 25704e05c8..ba56424ee0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerSplitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerSplitTests.cs @@ -48,6 +48,9 @@ public async Task Controller_ShouldSignalSynchronizerSplitPartition_IfPartitionS await sut.ShutdownAsync().ConfigureAwait(false); Mock.Get(synchronizer).VerifyAll(); + + Mock.Get(partitionSupervisor) + .Verify(s => s.Dispose(), Times.Once); } [TestMethod] @@ -76,6 +79,9 @@ public async Task Controller_ShouldPassLastKnownContinuationTokenToSynchronizer_ await sut.ShutdownAsync().ConfigureAwait(false); Mock.Get(synchronizer).VerifyAll(); + + Mock.Get(partitionSupervisor) + .Verify(s => s.Dispose(), Times.Once); } [TestMethod] @@ -108,6 +114,9 @@ public async Task Controller_ShouldCopyParentLeaseProperties_IfPartitionSplitHap .VerifySet(l => l.Properties = customProperties, Times.Once); Mock.Get(leaseChild2) .VerifySet(l => l.Properties = customProperties, Times.Once); + + Mock.Get(partitionSupervisor) + .Verify(s => s.Dispose(), Times.Once); } [TestMethod] @@ -132,6 +141,9 @@ public async Task Controller_ShouldKeepParentLease_IfSplitThrows() await sut.ShutdownAsync().ConfigureAwait(false); Mock.Get(leaseManager).Verify(manager => manager.DeleteAsync(lease), Times.Never); + + Mock.Get(partitionSupervisor) + .Verify(s => s.Dispose(), Times.Once); } [TestMethod] @@ -180,6 +192,13 @@ public async Task Controller_ShouldRunProcessingOnChildPartitions_IfHappyPath() monitor.Verify(m => m.NotifyLeaseAcquireAsync(leaseChild1.CurrentLeaseToken), Times.Once); monitor.Verify(m => m.NotifyLeaseReleaseAsync(leaseChild2.CurrentLeaseToken), Times.Once); + + Mock.Get(partitionSupervisor) + .Verify(s => s.Dispose(), Times.Once); + Mock.Get(partitionSupervisor1) + .Verify(s => s.Dispose(), Times.Once); + Mock.Get(partitionSupervisor2) + .Verify(s => s.Dispose(), Times.Once); } [TestMethod] From c5556853dbc8a63466d5bea5bc1f69ccdd0014e2 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Sat, 30 Dec 2023 04:51:20 -0800 Subject: [PATCH 248/337] [Internal] Per Partition Automatic Failover: Fixes Metadata Requests Retry Policy (#4205) * Code changes to retry on next preferred region for metadata reads on gateway timeouts. * Code changes to add retry for PK Ranges call. * Code changes to mark endpoint unavailable for read when cosmos exception occurs! * Code changes to fix unit tests. Added global endpoint manager in Pk Range Cache ctor. * Code changes to fix unit tests. * Code changes to fix build break. * Minor code clean-up. * Code changes to capture metadata location endpoint within on before send request. * Code changes to address review comments. * Code changes to fix build failure. * Code changes to refactor metadata timeout policy. * Code changes to add retry for request timeout. Fix emulator tests. * Code changes to add metadata retry policy unit tests. * Code changes to add more tests. * Code changes to refactor metadata retry policy logic to increment location index. Addressed review comments. * Code changes to address review comments. * Code changes to address review comments. * Code changes to add separate condition for pk range requests. --- .../src/ClientRetryPolicy.cs | 14 ++ Microsoft.Azure.Cosmos/src/DocumentClient.cs | 4 +- .../src/HttpClient/HttpTimeoutPolicy.cs | 13 +- .../src/MetadataRequestThrottleRetryPolicy.cs | 190 ++++++++++++++++++ .../src/Routing/PartitionKeyRangeCache.cs | 62 +++--- .../Mocks/MockDocumentClient.cs | 2 +- .../Batch/BatchAsyncBatcherTests.cs | 2 +- .../Batch/BatchAsyncContainerExecutorTests.cs | 2 +- .../Batch/BatchAsyncOperationContextTests.cs | 2 +- ...lkPartitionKeyRangeGoneRetryPolicyTests.cs | 2 +- .../PartitionSynchronizerCoreTests.cs | 43 +++- .../GatewayAddressCacheTests.cs | 4 +- .../GatewayStoreModelTest.cs | 24 +-- ...MetadataRequestThrottleRetryPolicyTests.cs | 129 ++++++++++++ .../PartitionKeyRangeCacheTest.cs | 141 ++++++++++++- .../PartitionKeyRangeHandlerTests.cs | 7 +- .../Utils/MockDocumentClient.cs | 9 +- 17 files changed, 578 insertions(+), 72 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/MetadataRequestThrottleRetryPolicy.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/MetadataRequestThrottleRetryPolicyTests.cs diff --git a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs index 147977e130..e19433c17e 100644 --- a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs @@ -98,6 +98,20 @@ public async Task ShouldRetryAsync( } } + // Any metadata request will throw a cosmos exception from CosmosHttpClientCore if + // it receives a 503 service unavailable from gateway. This check is to add retry + // mechanism for the metadata requests in such cases. + if (exception is CosmosException cosmosException) + { + ShouldRetryResult shouldRetryResult = await this.ShouldRetryInternalAsync( + cosmosException.StatusCode, + cosmosException.Headers.SubStatusCode); + if (shouldRetryResult != null) + { + return shouldRetryResult; + } + } + return await this.throttlingRetry.ShouldRetryAsync(exception, cancellationToken); } diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 632c158f96..8340df8207 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -662,7 +662,7 @@ private async Task OpenPrivateAsync(CancellationToken cancellationToken) tokenProvider: this, retryPolicy: this.retryPolicy, telemetryToServiceHelper: this.telemetryToServiceHelper); - this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache); + this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache, this.GlobalEndpointManager); DefaultTrace.TraceWarning("{0} occurred while OpenAsync. Exception Message: {1}", ex.ToString(), ex.Message); } @@ -1033,7 +1033,7 @@ private async Task GetInitializationTaskAsync(IStoreClientFactory storeCli tokenProvider: this, retryPolicy: this.retryPolicy, telemetryToServiceHelper: this.telemetryToServiceHelper); - this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache); + this.partitionKeyRangeCache = new PartitionKeyRangeCache(this, this.GatewayStoreModel, this.collectionCache, this.GlobalEndpointManager); this.ResetSessionTokenRetryPolicy = new ResetSessionTokenRetryPolicyFactory(this.sessionContainer, this.collectionCache, this.retryPolicy); gatewayStoreModel.SetCaches(this.partitionKeyRangeCache, this.collectionCache); diff --git a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs index 42742f86c1..5b39a2c113 100644 --- a/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs @@ -29,8 +29,15 @@ public static HttpTimeoutPolicy GetTimeoutPolicy( return HttpTimeoutPolicyControlPlaneRetriableHotPath.InstanceShouldThrow503OnTimeout; } - //Partition Key Requests - if (documentServiceRequest.ResourceType == ResourceType.PartitionKeyRange) + //Get Partition Key Range Requests + if (documentServiceRequest.ResourceType == ResourceType.PartitionKeyRange + && documentServiceRequest.OperationType == OperationType.ReadFeed) + { + return HttpTimeoutPolicyControlPlaneRetriableHotPath.InstanceShouldThrow503OnTimeout; + } + + //Get Addresses Requests + if (documentServiceRequest.ResourceType == ResourceType.Address) { return HttpTimeoutPolicyControlPlaneRetriableHotPath.Instance; } @@ -44,7 +51,7 @@ public static HttpTimeoutPolicy GetTimeoutPolicy( //Meta Data Read if (HttpTimeoutPolicy.IsMetaData(documentServiceRequest) && documentServiceRequest.IsReadOnlyRequest) { - return HttpTimeoutPolicyDefault.InstanceShouldThrow503OnTimeout; + return HttpTimeoutPolicyControlPlaneRetriableHotPath.InstanceShouldThrow503OnTimeout; } //Default behavior diff --git a/Microsoft.Azure.Cosmos/src/MetadataRequestThrottleRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/MetadataRequestThrottleRetryPolicy.cs new file mode 100644 index 0000000000..928d2f2e87 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/MetadataRequestThrottleRetryPolicy.cs @@ -0,0 +1,190 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Documents; + + /// + /// Metadata Request Throttle Retry Policy is combination of endpoint change retry + throttling retry. + /// + internal sealed class MetadataRequestThrottleRetryPolicy : IDocumentClientRetryPolicy + { + /// + /// A constant integer defining the default maximum retry wait time in seconds. + /// + private const int DefaultMaxWaitTimeInSeconds = 60; + + /// + /// A constant integer defining the default maximum retry count on service unavailable. + /// + private const int DefaultMaxServiceUnavailableRetryCount = 1; + + /// + /// An instance of . + /// + private readonly IGlobalEndpointManager globalEndpointManager; + + /// + /// Defines the throttling retry policy that is used as the underlying retry policy. + /// + private readonly IDocumentClientRetryPolicy throttlingRetryPolicy; + + /// + /// An integer defining the maximum retry count on service unavailable. + /// + private readonly int maxServiceUnavailableRetryCount; + + /// + /// An instance of containing the location endpoint where the partition key + /// range http request will be sent over. + /// + private MetadataRetryContext retryContext; + + /// + /// An integer capturing the current retry count on service unavailable. + /// + private int serviceUnavailableRetryCount; + + /// + /// The constructor to initialize an instance of . + /// + /// An instance of + /// An integer defining the maximum number + /// of attempts to retry when requests are throttled. + /// An integer defining the maximum wait time in seconds. + public MetadataRequestThrottleRetryPolicy( + IGlobalEndpointManager endpointManager, + int maxRetryAttemptsOnThrottledRequests, + int maxRetryWaitTimeInSeconds = DefaultMaxWaitTimeInSeconds) + { + this.globalEndpointManager = endpointManager; + this.maxServiceUnavailableRetryCount = Math.Max( + MetadataRequestThrottleRetryPolicy.DefaultMaxServiceUnavailableRetryCount, + this.globalEndpointManager.PreferredLocationCount); + + this.throttlingRetryPolicy = new ResourceThrottleRetryPolicy( + maxRetryAttemptsOnThrottledRequests, + maxRetryWaitTimeInSeconds); + + this.retryContext = new MetadataRetryContext + { + RetryLocationIndex = 0, + RetryRequestOnPreferredLocations = true, + }; + } + + /// + /// Should the caller retry the operation. + /// + /// Exception that occured when the operation was tried + /// An instance of . + /// True indicates caller should retry, False otherwise + public Task ShouldRetryAsync( + Exception exception, + CancellationToken cancellationToken) + { + if (exception is CosmosException cosmosException + && cosmosException.StatusCode == HttpStatusCode.ServiceUnavailable + && cosmosException.Headers.SubStatusCode == SubStatusCodes.TransportGenerated503) + { + if (this.IncrementRetryIndexOnServiceUnavailableForMetadataRead()) + { + return Task.FromResult(ShouldRetryResult.RetryAfter(TimeSpan.Zero)); + } + } + + return this.throttlingRetryPolicy.ShouldRetryAsync(exception, cancellationToken); + } + + /// + /// Should the caller retry the operation. + /// + /// in return of the request + /// An instance of . + /// True indicates caller should retry, False otherwise + public Task ShouldRetryAsync( + ResponseMessage cosmosResponseMessage, + CancellationToken cancellationToken) + { + if (cosmosResponseMessage?.StatusCode == HttpStatusCode.ServiceUnavailable + && cosmosResponseMessage?.Headers?.SubStatusCode == SubStatusCodes.TransportGenerated503) + { + if (this.IncrementRetryIndexOnServiceUnavailableForMetadataRead()) + { + return Task.FromResult(ShouldRetryResult.RetryAfter(TimeSpan.Zero)); + } + } + + return this.throttlingRetryPolicy.ShouldRetryAsync(cosmosResponseMessage, cancellationToken); + } + + /// + /// Method that is called before a request is sent to allow the retry policy implementation + /// to modify the state of the request. + /// + /// The request being sent to the service. + public void OnBeforeSendRequest(DocumentServiceRequest request) + { + // Clear the previous location-based routing directive. + request.RequestContext.ClearRouteToLocation(); + request.RequestContext.RouteToLocation( + this.retryContext.RetryLocationIndex, + this.retryContext.RetryRequestOnPreferredLocations); + + Uri metadataLocationEndpoint = this.globalEndpointManager.ResolveServiceEndpoint(request); + + DefaultTrace.TraceInformation("MetadataRequestThrottleRetryPolicy: Routing the metadata request to: {0} for operation type: {1} and resource type: {2}.", metadataLocationEndpoint, request.OperationType, request.ResourceType); + request.RequestContext.RouteToLocation(metadataLocationEndpoint); + } + + /// + /// Increments the location index when a service unavailable exception ocurrs, for any future read requests. + /// + /// A boolean flag indicating if the operation was successful. + private bool IncrementRetryIndexOnServiceUnavailableForMetadataRead() + { + if (this.serviceUnavailableRetryCount++ >= this.maxServiceUnavailableRetryCount) + { + DefaultTrace.TraceWarning("MetadataRequestThrottleRetryPolicy: Retry count: {0} has exceeded the maximum permitted retry count on service unavailable: {1}.", this.serviceUnavailableRetryCount, this.maxServiceUnavailableRetryCount); + return false; + } + + // Retrying on second PreferredLocations. + // RetryCount is used as zero-based index. + DefaultTrace.TraceWarning("MetadataRequestThrottleRetryPolicy: Incrementing the metadata retry location index to: {0}.", this.serviceUnavailableRetryCount); + this.retryContext = new MetadataRetryContext() + { + RetryLocationIndex = this.serviceUnavailableRetryCount, + RetryRequestOnPreferredLocations = true, + }; + + return true; + } + + /// + /// A helper class containing the required attributes for + /// metadata retry context. + /// + internal sealed class MetadataRetryContext + { + /// + /// An integer defining the current retry location index. + /// + public int RetryLocationIndex { get; set; } + + /// + /// A boolean flag indicating if the request should retry on + /// preferred locations. + /// + public bool RetryRequestOnPreferredLocations { get; set; } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs index d9e2854b2b..d849e4d3c0 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyRangeCache.cs @@ -30,17 +30,20 @@ internal class PartitionKeyRangeCache : IRoutingMapProvider, ICollectionRoutingM private readonly ICosmosAuthorizationTokenProvider authorizationTokenProvider; private readonly IStoreModel storeModel; private readonly CollectionCache collectionCache; + private readonly IGlobalEndpointManager endpointManager; public PartitionKeyRangeCache( ICosmosAuthorizationTokenProvider authorizationTokenProvider, IStoreModel storeModel, - CollectionCache collectionCache) + CollectionCache collectionCache, + IGlobalEndpointManager endpointManager) { this.routingMapCache = new AsyncCacheNonBlocking( keyEqualityComparer: StringComparer.Ordinal); this.authorizationTokenProvider = authorizationTokenProvider; this.storeModel = storeModel; this.collectionCache = collectionCache; + this.endpointManager = endpointManager; } public virtual async Task> TryGetOverlappingRangesAsync( @@ -121,10 +124,10 @@ public virtual async Task TryLookupAsync( return await this.routingMapCache.GetAsync( key: collectionRid, singleValueInitFunc: (_) => this.GetRoutingMapForCollectionAsync( - collectionRid, - previousValue, - trace, - request?.RequestContext?.ClientRequestStatistics), + collectionRid: collectionRid, + previousRoutingMap: previousValue, + trace: trace, + clientSideRequestStatistics: request?.RequestContext?.ClientRequestStatistics), forceRefresh: (currentValue) => PartitionKeyRangeCache.ShouldForceRefresh(previousValue, currentValue)); } catch (DocumentClientException ex) @@ -174,35 +177,6 @@ private static bool ShouldForceRefresh( return previousValue.ChangeFeedNextIfNoneMatch == currentValue.ChangeFeedNextIfNoneMatch; } - public async Task TryGetRangeByPartitionKeyRangeIdAsync(string collectionRid, - string partitionKeyRangeId, - ITrace trace, - IClientSideRequestStatistics clientSideRequestStatistics) - { - try - { - CollectionRoutingMap routingMap = await this.routingMapCache.GetAsync( - key: collectionRid, - singleValueInitFunc: (_) => this.GetRoutingMapForCollectionAsync( - collectionRid: collectionRid, - previousRoutingMap: null, - trace: trace, - clientSideRequestStatistics: clientSideRequestStatistics), - forceRefresh: (_) => false); - - return routingMap.TryGetRangeByPartitionKeyRangeId(partitionKeyRangeId); - } - catch (DocumentClientException ex) - { - if (ex.StatusCode == HttpStatusCode.NotFound) - { - return null; - } - - throw; - } - } - private async Task GetRoutingMapForCollectionAsync( string collectionRid, CollectionRoutingMap previousRoutingMap, @@ -213,6 +187,12 @@ private async Task GetRoutingMapForCollectionAsync( string changeFeedNextIfNoneMatch = previousRoutingMap?.ChangeFeedNextIfNoneMatch; HttpStatusCode lastStatusCode = HttpStatusCode.OK; + + RetryOptions retryOptions = new RetryOptions(); + MetadataRequestThrottleRetryPolicy metadataRetryPolicy = new ( + endpointManager: this.endpointManager, + maxRetryAttemptsOnThrottledRequests: retryOptions.MaxRetryAttemptsOnThrottledRequests, + maxRetryWaitTimeInSeconds: retryOptions.MaxRetryWaitTimeInSeconds); do { INameValueCollection headers = new RequestNameValueCollection(); @@ -224,10 +204,9 @@ private async Task GetRoutingMapForCollectionAsync( headers.Set(HttpConstants.HttpHeaders.IfNoneMatch, changeFeedNextIfNoneMatch); } - RetryOptions retryOptions = new RetryOptions(); using (DocumentServiceResponse response = await BackoffRetryUtility.ExecuteAsync( - () => this.ExecutePartitionKeyRangeReadChangeFeedAsync(collectionRid, headers, trace, clientSideRequestStatistics), - new ResourceThrottleRetryPolicy(retryOptions.MaxRetryAttemptsOnThrottledRequests, retryOptions.MaxRetryWaitTimeInSeconds))) + () => this.ExecutePartitionKeyRangeReadChangeFeedAsync(collectionRid, headers, trace, clientSideRequestStatistics, metadataRetryPolicy), + retryPolicy: metadataRetryPolicy)) { lastStatusCode = response.StatusCode; changeFeedNextIfNoneMatch = response.Headers[HttpConstants.HttpHeaders.ETag]; @@ -274,7 +253,8 @@ private async Task GetRoutingMapForCollectionAsync( private async Task ExecutePartitionKeyRangeReadChangeFeedAsync(string collectionRid, INameValueCollection headers, ITrace trace, - IClientSideRequestStatistics clientSideRequestStatistics) + IClientSideRequestStatistics clientSideRequestStatistics, + IDocumentClientRetryPolicy retryPolicy) { using (ITrace childTrace = trace.StartChild("Read PartitionKeyRange Change Feed", TraceComponent.Transport, Tracing.TraceLevel.Info)) { @@ -285,6 +265,7 @@ private async Task ExecutePartitionKeyRangeReadChangeFe AuthorizationTokenType.PrimaryMasterKey, headers)) { + retryPolicy.OnBeforeSendRequest(request); string authorizationToken = null; try { @@ -333,6 +314,11 @@ private async Task ExecutePartitionKeyRangeReadChangeFe childTrace.AddDatum("Exception Message", ex.Message); throw; } + catch (CosmosException ce) + { + childTrace.AddDatum("Exception Message", ce.Message); + throw; + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs index 7d268407de..c6b59b8cea 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs @@ -228,7 +228,7 @@ private void Init() }, string.Empty); - this.partitionKeyRangeCache = new Mock(null, null, null); + this.partitionKeyRangeCache = new Mock(null, null, null, null); this.partitionKeyRangeCache.Setup( m => m.TryLookupAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs index 044a735734..acc83d3ff4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncBatcherTests.cs @@ -798,7 +798,7 @@ private class ClientWithSplitDetection : MockDocumentClient public ClientWithSplitDetection() { - this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null); + this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null, null); this.partitionKeyRangeCache.Setup( m => m.TryGetOverlappingRangesAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs index 993afa449b..c6bca20950 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncContainerExecutorTests.cs @@ -376,7 +376,7 @@ private class ClientWithSplitDetection : MockDocumentClient public ClientWithSplitDetection() { - this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null); + this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null, null); this.partitionKeyRangeCache.Setup( m => m.TryGetOverlappingRangesAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncOperationContextTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncOperationContextTests.cs index 5ec655d386..8e3c6bcbc3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncOperationContextTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Batch/BatchAsyncOperationContextTests.cs @@ -287,7 +287,7 @@ private class ClientWithSplitDetection : MockDocumentClient public ClientWithSplitDetection() { - this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null); + this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null, null); this.partitionKeyRangeCache.Setup( m => m.TryGetOverlappingRangesAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BulkPartitionKeyRangeGoneRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BulkPartitionKeyRangeGoneRetryPolicyTests.cs index e1c8ad0cdf..1f87d40635 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BulkPartitionKeyRangeGoneRetryPolicyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BulkPartitionKeyRangeGoneRetryPolicyTests.cs @@ -145,7 +145,7 @@ private class ClientWithSplitDetection : MockDocumentClient public ClientWithSplitDetection() { - this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null); + this.partitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null, null); this.partitionKeyRangeCache.Setup( m => m.TryGetOverlappingRangesAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionSynchronizerCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionSynchronizerCoreTests.cs index b56a9b377a..166b0c52cf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionSynchronizerCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionSynchronizerCoreTests.cs @@ -20,6 +20,28 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.Tests [TestCategory("ChangeFeed")] public class PartitionSynchronizerCoreTests { + private GlobalEndpointManager endpointManager; + + [TestInitialize] + public void TestInitialize() + { + Mock mockDocumentClient = new(); + + mockDocumentClient + .Setup(client => client.ServiceEndpoint) + .Returns(new Uri("https://foo")); + + this.endpointManager = new( + mockDocumentClient.Object, + new ConnectionPolicy()); + } + + [TestCleanup] + public void Cleanup() + { + this.endpointManager.Dispose(); + } + /// /// Verifies handling of Splits on PKRange based leases /// @@ -39,7 +61,8 @@ public async Task HandlePartitionGoneAsync_PKRangeBasedLease_Split() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -102,7 +125,8 @@ public async Task HandlePartitionGoneAsync_EpkBasedLease_Split() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -170,7 +194,8 @@ public async Task HandlePartitionGoneAsync_PKRangeBasedLease_Merge() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -228,7 +253,8 @@ public async Task HandlePartitionGoneAsync_EpkBasedLease_Merge() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -276,7 +302,8 @@ public async Task CreateMissingLeases_NoLeases() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -321,7 +348,8 @@ public async Task CreateMissingLeases_SomePKRangeLeases() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { @@ -372,7 +400,8 @@ public async Task CreateMissingLeases_SomePKRangeAndEPKLeases() Mock pkRangeCache = new Mock( Mock.Of(), Mock.Of(), - Mock.Of()); + Mock.Of(), + this.endpointManager); List resultingRanges = new List() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index fded897e42..4b49c29d8e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -60,7 +60,7 @@ public GatewayAddressCacheTests() } }; - this.partitionKeyRangeCache = new Mock(null, null, null); + this.partitionKeyRangeCache = new Mock(null, null, null, null); this.partitionKeyRangeCache .Setup(m => m.TryGetOverlappingRangesAsync( It.IsAny(), @@ -755,7 +755,7 @@ public async Task GlobalAddressResolver_OpenConnectionsToAllReplicasAsync_WhenIn .Returns(Task.FromResult(containerProperties)); string exceptionMessage = "Failed to lookup partition key ranges."; - Mock partitionKeyRangeCache = new (null, null, null); + Mock partitionKeyRangeCache = new (null, null, null, null); partitionKeyRangeCache .Setup(m => m.TryGetOverlappingRangesAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index fd9a8a3efd..c578aef620 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -274,7 +274,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsr, ConsistencyLevel.Session, new Mock().Object, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: Mock.Of()); @@ -301,7 +301,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsrQueryPlan, ConsistencyLevel.Session, new Mock().Object, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: Mock.Of()); @@ -355,7 +355,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsr, ConsistencyLevel.Session, new Mock().Object, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: Mock.Of()); @@ -385,7 +385,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsrNoSessionToken, ConsistencyLevel.Session, sessionContainer, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: globalEndpointManager.Object); @@ -426,7 +426,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( It.IsAny(), NoOpTrace.Singleton)).Returns(Task.FromResult(containerProperties)); - Mock mockPartitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null); + Mock mockPartitionKeyRangeCache = new Mock(MockBehavior.Strict, null, null, null, null); mockPartitionKeyRangeCache.Setup(x => x.TryGetPartitionKeyRangeByIdAsync( containerProperties.ResourceId, partitionKeyRangeId, @@ -473,7 +473,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsrSprocExecute, ConsistencyLevel.Session, new Mock().Object, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: Mock.Of()); @@ -512,7 +512,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( dsrNoSessionToken, ConsistencyLevel.Session, sessionContainer, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(new SessionContainer("testhost"), gatewayStoreModel, null, null, null).Object, globalEndpointManager: globalEndpointManager.Object); @@ -972,7 +972,7 @@ public async Task GatewayStoreModel_AvoidGlobalSessionToken() null, MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient())); Mock clientCollectionCache = new Mock(new SessionContainer("testhost"), storeModel, null, null, null); - Mock partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache.Object); + Mock partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache.Object, endpointManager); sessionContainer.SetSessionToken( ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(), @@ -1068,7 +1068,7 @@ Task sendFunc(HttpRequestMessage request) Mock clientCollectionCache = new Mock(new SessionContainer("testhost"), storeModel, null, null, null); - Mock partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache.Object); + Mock partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache.Object, endpointManager); storeModel.SetCaches(partitionKeyRangeCache.Object, clientCollectionCache.Object); INameValueCollection headers = new RequestNameValueCollection(); @@ -1136,7 +1136,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( documentServiceRequestToChild, ConsistencyLevel.Session, sessionContainer, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(sessionContainer, gatewayStoreModel, null, null, null).Object, globalEndpointManager: globalEndpointManager.Object); @@ -1202,7 +1202,7 @@ await GatewayStoreModel.ApplySessionTokenAsync( documentServiceRequestToChild, ConsistencyLevel.Session, sessionContainer, - partitionKeyRangeCache: new Mock(null, null, null).Object, + partitionKeyRangeCache: new Mock(null, null, null, null).Object, clientCollectionCache: new Mock(sessionContainer, gatewayStoreModel, null, null, null).Object, globalEndpointManager: globalEndpointManager.Object); @@ -1273,7 +1273,7 @@ static async Task messageHandler(HttpRequestMessage request MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(httpMessageHandler))); ClientCollectionCache clientCollectionCache = new Mock(new SessionContainer("testhost"), storeModel, null, null, null).Object; - PartitionKeyRangeCache partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache).Object; + PartitionKeyRangeCache partitionKeyRangeCache = new Mock(null, storeModel, clientCollectionCache, endpointManager).Object; storeModel.SetCaches(partitionKeyRangeCache, clientCollectionCache); await executeWithGatewayStoreModel(storeModel); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/MetadataRequestThrottleRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/MetadataRequestThrottleRetryPolicyTests.cs new file mode 100644 index 0000000000..40faac51e2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/MetadataRequestThrottleRetryPolicyTests.cs @@ -0,0 +1,129 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests +{ + using System; + using System.Threading.Tasks; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; + using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; + using Microsoft.Azure.Cosmos.Tracing; + using System.Net; + using System.Reflection; + using static Microsoft.Azure.Cosmos.MetadataRequestThrottleRetryPolicy; + + /// + /// Unit tests for . + /// + [TestClass] + public class MetadataRequestThrottleRetryPolicyTests + { + [TestMethod] + [Owner("dkunda")] + [DataRow(true, true, DisplayName = "Test when a response message with a valid substatus code was used.")] + [DataRow(false, true, DisplayName = "Test when an exception was thrown with a valid substatus code.")] + [DataRow(true, false, DisplayName = "Test when a response message with an invalid substatus code was used.")] + [DataRow(false, false, DisplayName = "Test when an exception was thrown with an invalid substatus code.")] + public async Task ShouldRetryAsync_WithValidAndInvalidSubStatusCodes_ShouldIncrementLocationIndexOrSkip( + bool useResponseMessage, + bool isValidSubStatusCode) + { + // Arrange. + ShouldRetryResult retryResult; + string collectionRid = "test-collection"; + Uri primaryServiceEndpoint = new ("https://default-endpoint-region1.net/"); + Uri routedServiceEndpoint = new("https://default-endpoint-region2.net/"); + + Documents.Collections.INameValueCollection headers = new Documents.Collections.RequestNameValueCollection(); + + headers.Set(HttpConstants.HttpHeaders.PageSize, "10"); + headers.Set(HttpConstants.HttpHeaders.A_IM, HttpConstants.A_IMHeaderValues.IncrementalFeed); + + DocumentServiceRequest request = DocumentServiceRequest.Create( + OperationType.ReadFeed, + collectionRid, + Documents.ResourceType.PartitionKeyRange, + AuthorizationTokenType.PrimaryMasterKey, + headers); + + Mock mockedGlobalEndpointManager = new (); + mockedGlobalEndpointManager + .SetupSequence(gem => gem.ResolveServiceEndpoint(It.IsAny())) + .Returns(primaryServiceEndpoint) + .Returns(isValidSubStatusCode ? routedServiceEndpoint : primaryServiceEndpoint); + + MetadataRequestThrottleRetryPolicy policy = new (mockedGlobalEndpointManager.Object, 0); + policy.OnBeforeSendRequest(request); + + Assert.AreEqual(primaryServiceEndpoint, request.RequestContext.LocationEndpointToRoute); + + // Act. + if (useResponseMessage) + { + Headers responseHeaders = new() + { + SubStatusCode = isValidSubStatusCode + ? SubStatusCodes.TransportGenerated503 + : SubStatusCodes.BWTermCountLimitExceeded + }; + + ResponseMessage responseMessage = new( + statusCode: HttpStatusCode.ServiceUnavailable, + requestMessage: null, + headers: responseHeaders, + cosmosException: null, + trace: NoOpTrace.Singleton); + + retryResult = await policy.ShouldRetryAsync(responseMessage, default); + } + else + { + CosmosException exception = CosmosExceptionFactory.CreateServiceUnavailableException( + message: "Service Unavailable at the moment.", + headers: new Headers() + { + ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), + SubStatusCode = isValidSubStatusCode + ? SubStatusCodes.TransportGenerated503 + : SubStatusCodes.BWTermCountLimitExceeded + }, + trace: NoOpTrace.Singleton, + innerException: null); + + + retryResult = await policy.ShouldRetryAsync(exception, default); + } + + policy.OnBeforeSendRequest(request); + + // Assert. + FieldInfo fieldInfo = policy + .GetType() + .GetField( + name: "retryContext", + bindingAttr: BindingFlags.Instance | BindingFlags.NonPublic); + + MetadataRetryContext retryContext = (MetadataRetryContext)fieldInfo + .GetValue( + obj: policy); + + Assert.IsNotNull(retryResult); + if (isValidSubStatusCode) + { + Assert.AreEqual(true, retryResult.ShouldRetry, "MetadataRequestThrottleRetryPolicy should return true since the sub status code indicates to retry the request in the next preferred read region."); + Assert.AreEqual(1, retryContext.RetryLocationIndex, "Indicates that the retry location index was incremented."); + Assert.AreEqual(routedServiceEndpoint, request.RequestContext.LocationEndpointToRoute); + } + else + { + Assert.AreEqual(false, retryResult.ShouldRetry, "ResourceThrottleRetryPolicy should return false since the status code does not indicate the request was throttled."); + Assert.AreEqual(0, retryContext.RetryLocationIndex, "Indicates that the retry location index remain unchanged."); + Assert.AreEqual(primaryServiceEndpoint, request.RequestContext.LocationEndpointToRoute); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeCacheTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeCacheTest.cs index 8d7b32a7b7..44eb2fc565 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeCacheTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeCacheTest.cs @@ -21,6 +21,8 @@ namespace Microsoft.Azure.Cosmos.Tests using TraceLevel = Cosmos.Tracing.TraceLevel; using Newtonsoft.Json.Linq; using Newtonsoft.Json; + using System; + using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; /// /// Unit Tests for . @@ -77,6 +79,11 @@ public async Task TryGetOverlappingRangesAsync_WithFreshContainer_ShouldNotAddSa [HttpConstants.HttpHeaders.ETag] = eTag, }; + Mock mockDocumentClient = new Mock(); + mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo")); + + using GlobalEndpointManager endpointManager = new (mockDocumentClient.Object, new ConnectionPolicy()); + mockStoreModel.SetupSequence(x => x.ProcessMessageAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new DocumentServiceResponse(new MemoryStream(singlePkCollectionCacheByte), new StoreResponseNameValueCollection() @@ -91,7 +98,7 @@ public async Task TryGetOverlappingRangesAsync_WithFreshContainer_ShouldNotAddSa .Returns(new ValueTask(authToken)); // Act. - PartitionKeyRangeCache partitionKeyRangeCache = new(mockTokenProvider.Object, mockStoreModel.Object, mockCollectioNCache.Object); + PartitionKeyRangeCache partitionKeyRangeCache = new(mockTokenProvider.Object, mockStoreModel.Object, mockCollectioNCache.Object, endpointManager); IReadOnlyList partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( containerRId, FeedRangeEpk.FullRange.Range, @@ -119,5 +126,137 @@ public async Task TryGetOverlappingRangesAsync_WithFreshContainer_ShouldNotAddSa Assert.AreEqual(eTag, secondPkRangeValue); } } + + /// + /// Test to validate that when the gateway service is unavailable, the partition key range cache is able to retry + /// the Get PK Range calls to different regions, based on the preferred locations count. Therefore, the cache keep + /// retrying until the max attempt is exausted. + /// + [TestMethod] + [DataRow(1, false, DisplayName = "Validates when the preferred location count is just one, the cache retries only once and fails.")] + [DataRow(2, false, DisplayName = "Validates when the preferred location count is two, the cache retries twice and fails.")] + [DataRow(3, true, DisplayName = "Validates when the preferred location count is three, the cache retries thrice and succeeds on the last attempt.")] + public async Task TryGetOverlappingRangesAsync_WhenGatewayThrowsServiceUnavailable_ShouldMarkReadEndpointAsUnavailable2(int preferredLocationsCount, bool shouldSucceed) + { + // Arrange. + string eTag = "483"; + string authToken = "token!"; + string containerRId = "kjhsAA=="; + string singlePkCollectionCache = "{\"_rid\":\"3FIlAOzjvyg=\",\"PartitionKeyRanges\":[{\"_rid\":\"3FIlAOzjvygCAAAAAAAAUA==\",\"id\":\"0\",\"_etag\":\"\\\"00005565-0000-0800-0000-621fd98a0000\\\"\",\"minInclusive\":\"\",\"maxExclusive\":\"FF\",\"ridPrefix\":0,\"_self\":\"dbs/3FIlAA==/colls/3FIlAOzjvyg=/pkranges/3FIlAOzjvygCAAAAAAAAUA==/\",\"throughputFraction\":1,\"status\":\"splitting\",\"parents\":[],\"_ts\":1646254474,\"_lsn\":44}],\"_count\":1}"; + byte[] singlePkCollectionCacheByte = Encoding.UTF8.GetBytes(singlePkCollectionCache); + using (ITrace trace = Trace.GetRootTrace(this.TestContext.TestName, TraceComponent.Unknown, TraceLevel.Info)) + { + Mock mockStoreModel = new(); + Mock mockCollectioNCache = new(); + Mock mockTokenProvider = new(); + NameValueCollectionWrapper headers = new() + { + [HttpConstants.HttpHeaders.ETag] = eTag, + }; + + Uri serviceUri = new("https://foo"); + Mock mockDocumentClient = new Mock(); + mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(serviceUri); + + Mock mockedEndpointManager = new Mock(); + mockedEndpointManager + .Setup(gem => gem.ResolveServiceEndpoint(It.IsAny())) + .Returns(serviceUri); + + mockedEndpointManager + .Setup(gem => gem.PreferredLocationCount) + .Returns(preferredLocationsCount); + + mockStoreModel.SetupSequence(x => x.ProcessMessageAsync(It.IsAny(), It.IsAny())) + .ThrowsAsync(CosmosExceptionFactory.CreateServiceUnavailableException( + message: "Service is Unavailable.", + headers: new Headers() + { + ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), + SubStatusCode = SubStatusCodes.TransportGenerated503 + }, + trace: trace, + innerException: null)) + .ThrowsAsync(CosmosExceptionFactory.CreateServiceUnavailableException( + message: "Service is Unavailable.", + headers: new Headers() + { + ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), + SubStatusCode = SubStatusCodes.TransportGenerated503 + }, + trace: trace, + innerException: null)) + .ThrowsAsync(CosmosExceptionFactory.CreateServiceUnavailableException( + message: "Service is Unavailable.", + headers: new Headers() + { + ActivityId = System.Diagnostics.Trace.CorrelationManager.ActivityId.ToString(), + SubStatusCode = SubStatusCodes.TransportGenerated503 + }, + trace: trace, + innerException: null)) + .ReturnsAsync(new DocumentServiceResponse(new MemoryStream(singlePkCollectionCacheByte), + new StoreResponseNameValueCollection() + { + ETag = eTag, + }, + HttpStatusCode.OK)) + .ReturnsAsync(new DocumentServiceResponse(null, headers, HttpStatusCode.NotModified, null)) + .ReturnsAsync(new DocumentServiceResponse(null, headers, HttpStatusCode.NotModified, null)); + + mockTokenProvider.Setup(x => x.GetUserAuthorizationTokenAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(new ValueTask(authToken)); + + PartitionKeyRangeCache partitionKeyRangeCache = new(mockTokenProvider.Object, mockStoreModel.Object, mockCollectioNCache.Object, mockedEndpointManager.Object); + + if (shouldSucceed) + { + // Act. + IReadOnlyList partitionKeyRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( + containerRId, + FeedRangeEpk.FullRange.Range, + trace, + forceRefresh: true); + + // Assert. + string dataPath = "children[0].data", previousContinuationTokenKey = "['Previous Continuation Token']", diagnostics = new CosmosTraceDiagnostics(trace).ToString(); + JObject traceData = JsonConvert.DeserializeObject(diagnostics); + + Assert.IsNotNull(traceData); + + string firstPkRangeCacheKeyName = ((JProperty)traceData.SelectToken(dataPath)?.First).Name; + string secondPkRangeCacheKeyName = ((JProperty)traceData.SelectToken(dataPath)?.Last).Name; + + Assert.IsTrue(!string.IsNullOrWhiteSpace(firstPkRangeCacheKeyName)); + Assert.IsTrue(!string.IsNullOrWhiteSpace(secondPkRangeCacheKeyName)); + Assert.AreNotEqual(firstPkRangeCacheKeyName, secondPkRangeCacheKeyName); + + string firstPkRangeValue = ((JProperty)traceData.SelectToken(dataPath).First)?.Value?.SelectToken(previousContinuationTokenKey)?.ToString(); + string secondPkRangeValue = ((JProperty)traceData.SelectToken(dataPath).Last)?.Value?.SelectToken(previousContinuationTokenKey)?.ToString(); + + Assert.IsTrue(!string.IsNullOrWhiteSpace(secondPkRangeValue)); + Assert.IsTrue(string.IsNullOrEmpty(firstPkRangeValue)); + Assert.AreEqual(eTag, secondPkRangeValue); + } + else + { + // Act. + CosmosException cosmosException = await Assert.ThrowsExceptionAsync(() => partitionKeyRangeCache.TryGetOverlappingRangesAsync( + containerRId, + FeedRangeEpk.FullRange.Range, + trace, + forceRefresh: true)); + + // Assert. + string diagnostics = new CosmosTraceDiagnostics(trace).ToString(); + JObject traceData = JsonConvert.DeserializeObject(diagnostics); + + Assert.IsNotNull(cosmosException); + Assert.IsNotNull(traceData); + Assert.AreEqual(HttpStatusCode.ServiceUnavailable, cosmosException.StatusCode); + Assert.AreEqual(SubStatusCodes.TransportGenerated503, cosmosException.Headers.SubStatusCode); + } + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeHandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeHandlerTests.cs index 66eed8a723..2db6f9e9d7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeHandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeHandlerTests.cs @@ -651,6 +651,10 @@ public async Task PartitionKeyRangeGoneTracePlumbingTest() containerProperties.Id = "TestContainer"; containerProperties.PartitionKey = partitionKeyDefinition; + Mock mockDocumentClient = new Mock(); + mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo")); + + using GlobalEndpointManager endpointManager = new(mockDocumentClient.Object, new ConnectionPolicy()); Mock collectionCache = new Mock(MockBehavior.Strict); collectionCache.Setup(c => c.ResolveCollectionAsync(It.IsAny(), default, trace)) @@ -661,7 +665,8 @@ public async Task PartitionKeyRangeGoneTracePlumbingTest() MockBehavior.Strict, new Mock().Object, new Mock().Object, - collectionCache.Object); + collectionCache.Object, + endpointManager); partitionKeyRangeCache.Setup(c => c.TryLookupAsync(collectionRid, null, It.IsAny(), trace)) .ReturnsAsync(collectionRoutingMap); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs index b0c29eb016..b6498dec6f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Utils/MockDocumentClient.cs @@ -227,7 +227,14 @@ private void Init() return Task.FromResult(cosmosContainerSetting); }); - this.partitionKeyRangeCache = new Mock(null, null, null); + Mock mockDocumentClient = new(); + mockDocumentClient + .Setup(client => client.ServiceEndpoint) + .Returns(new Uri("https://foo")); + + using GlobalEndpointManager endpointManager = new(mockDocumentClient.Object, new ConnectionPolicy()); + + this.partitionKeyRangeCache = new Mock(null, null, null, endpointManager); this.partitionKeyRangeCache.Setup( m => m.TryLookupAsync( It.IsAny(), From 02e4f3475e4842c5dbe551dc706464a52b4172d4 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Sun, 31 Dec 2023 15:16:56 -0500 Subject: [PATCH 249/337] [Internal] GlobalEndpointManager: Fixes Memory Leak (#4226) * memory leak fix * removed commented out code * changed to async so test would pass, with just static GetPropetiesHelper will get disposed before requests go through * added thread saftey * fixed to interlock pattern --------- Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> --- .../src/Routing/GlobalEndpointManager.cs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index e12d99255d..64156f729e 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -114,25 +114,26 @@ public Uri GetHubUri() /// The 2 additional tasks will go through all the preferred regions in parallel /// It will return the first success and stop the parallel tasks. /// - public static Task GetDatabaseAccountFromAnyLocationsAsync( + public static async Task GetDatabaseAccountFromAnyLocationsAsync( Uri defaultEndpoint, IList? locations, Func> getDatabaseAccountFn, CancellationToken cancellationToken) - { - GetAccountPropertiesHelper threadSafeGetAccountHelper = new GetAccountPropertiesHelper( + { + using (GetAccountPropertiesHelper threadSafeGetAccountHelper = new GetAccountPropertiesHelper( defaultEndpoint, locations?.GetEnumerator(), getDatabaseAccountFn, - cancellationToken); - - return threadSafeGetAccountHelper.GetAccountPropertiesAsync(); + cancellationToken)) + { + return await threadSafeGetAccountHelper.GetAccountPropertiesAsync(); + } } /// /// This is a helper class to /// - private class GetAccountPropertiesHelper + private class GetAccountPropertiesHelper : IDisposable { private readonly CancellationTokenSource CancellationTokenSource; private readonly Uri DefaultEndpoint; @@ -140,7 +141,8 @@ private class GetAccountPropertiesHelper private readonly Func> GetDatabaseAccountFn; private readonly List TransientExceptions = new List(); private AccountProperties? AccountProperties = null; - private Exception? NonRetriableException = null; + private Exception? NonRetriableException = null; + private int disposeCounter = 0; public GetAccountPropertiesHelper( Uri defaultEndpoint, @@ -345,7 +347,16 @@ private static bool IsNonRetriableException(Exception exception) } return false; - } + } + + public void Dispose() + { + if (Interlocked.Increment(ref this.disposeCounter) == 1) + { + this.CancellationTokenSource?.Cancel(); + this.CancellationTokenSource?.Dispose(); + } + } } public virtual Uri ResolveServiceEndpoint(DocumentServiceRequest request) From 4195ec0efa5097a36e36534e140dea5afab8832e Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:40:52 -0500 Subject: [PATCH 250/337] SDK 3.37.1 : Adds version bump and changelog (#4231) * [Internal] GlobalEndpointManager: Fixes Memory Leak (#4226) * memory leak fix * removed commented out code * changed to async so test would pass, with just static GetPropetiesHelper will get disposed before requests go through * added thread saftey * fixed to interlock pattern --------- Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> * changelog + version bump * genAPI * remove code changes * removed nit --------- Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> --- Directory.Build.props | 4 +- .../contracts/API_3.37.1-preview.txt | 1611 +++++++++++++++++ .../contracts/API_3.37.1.txt | 1552 ++++++++++++++++ changelog.md | 6 + 4 files changed, 3171 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.1-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.1.txt diff --git a/Directory.Build.props b/Directory.Build.props index 05ef3a1ad8..d77c3f59e3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.37.0 - 3.37.0 + 3.37.1 + 3.37.1 preview 3.31.5 2.0.4 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.1-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.1-preview.txt new file mode 100644 index 0000000000..672794b621 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.1-preview.txt @@ -0,0 +1,1611 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.1.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.1.txt new file mode 100644 index 0000000000..1c02b4efb2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.1.txt @@ -0,0 +1,1552 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index c6f797d1ec..1fd2e31825 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.37.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.1-preview) - 2024-1-2 +### [3.37.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.1) - 2024-1-2 + +#### Fixed +- [4226](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4226) GlobalEndpointManager: Fixes Memory Leak (#4226) + ### [3.37.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0-preview) - 2023-11-17 ### [3.37.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0) - 2023-11-17 From 17bbdab53b3760664c38f95cc5edace18da4639d Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:30:29 -0800 Subject: [PATCH 251/337] Query: Adds support for System.Text LINQ Custom Serializer (#4138) * initial commit * add more tests * cleanup * camel case fix * fix precidence and add test * cleanup * cleanup * Implement serializers * clenaup and bugfix * cleanup constructors * fix baseline * updates * cleanup * removed requirement to decorate enums * nit PR comments * bug fix and api updates * Pr comments * remove datacontract and newtonsoft serializer types * Pr comments and adding tests * updates * Aggregate tests and new serializer member * More tests and cleanup * PR comments * PR comments * PR comments - internal options class * Update Program.cs * comment fixes * PR comments * Add preview flag * API changes * new serialization interface * Update API and serializer updates * API fix * cleanup * PR comments * update interface * fix * API * Update Microsoft.Azure.Cosmos/src/Serializer/ICosmosLinqSerializer.cs Co-authored-by: Kiran Kumar Kolli * Some PR comments * adding sample code * Enum rename and interfact to abstract class * PR comments * PR comments * Remove CosmosLinqSerializerType * last one (hopefully) * Update Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs Co-authored-by: Matias Quaranta --------- Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- .../src/Linq/CosmosLinqQuery.cs | 8 +- .../src/Linq/CosmosLinqQueryProvider.cs | 5 +- .../src/Linq/CustomCosmosLinqSerializer.cs | 56 ++++ .../src/Linq/DefaultCosmosLinqSerializer.cs | 23 +- .../src/Linq/DocumentQueryEvaluator.cs | 4 +- .../src/Linq/ExpressionToSQL.cs | 8 +- ...er.cs => ICosmosLinqSerializerInternal.cs} | 4 +- .../src/Linq/SQLTranslator.cs | 7 +- .../src/Linq/TranslationContext.cs | 35 ++- Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs | 2 +- .../Resource/Container/ContainerCore.Items.cs | 12 +- .../src/Serializer/CosmosLinqSerializer.cs | 84 +++++ .../CosmosLinqSerializerOptionsInternal.cs | 56 ++++ .../src/Serializer/CosmosSerializationUtil.cs | 23 +- .../src/Serializer/CosmosSerializer.cs | 5 +- ...stAggregateQueriesWithCustomSerializer.xml | 126 ++++++++ ...ine.TestAggregatesWithCustomSerializer.xml | 58 ++++ ...emberInitializerDotNetCustomSerializer.xml | 143 +++++++++ ...TestMemberInitializerDotNetDataMember.xml} | 36 +-- ...seline.TestMemberInitializerNewtonsoft.xml | 120 ++++---- ...tMemberInitializerNewtonsoftDataMember.xml | 236 +++++++++++++++ ...TestMemberInitializerNewtonsoftDotNet.xml} | 16 +- ...inqAggregateCustomSerializationBaseline.cs | 198 ++++++++++++ .../LinqAttributeContractBaselineTests.cs | 2 +- .../Linq/LinqTestsCommon.cs | 105 ++++++- ...TranslationWithCustomSerializerBaseline.cs | 286 ++++++++++++------ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 21 +- .../Contracts/DotNetPreviewSDKAPI.json | 28 ++ .../Linq/CosmosLinqJsonConverterTests.cs | 151 ++++++--- 29 files changed, 1570 insertions(+), 288 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Linq/CustomCosmosLinqSerializer.cs rename Microsoft.Azure.Cosmos/src/Linq/{ICosmosLinqSerializer.cs => ICosmosLinqSerializerInternal.cs} (86%) create mode 100644 Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs create mode 100644 Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptionsInternal.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregateQueriesWithCustomSerializer.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregatesWithCustomSerializer.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/{LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml => LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetDataMember.xml} (84%) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDataMember.xml rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/{LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml => LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDotNet.xml} (92%) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAggregateCustomSerializationBaseline.cs diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs index f8400229b2..a4c4c5e938 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs @@ -12,8 +12,8 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Diagnostics; - using Microsoft.Azure.Cosmos.Query; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; using Newtonsoft.Json; @@ -32,7 +32,7 @@ internal sealed class CosmosLinqQuery : IDocumentQuery, IOrderedQueryable< private readonly QueryRequestOptions cosmosQueryRequestOptions; private readonly bool allowSynchronousQueryExecution = false; private readonly string continuationToken; - private readonly CosmosLinqSerializerOptions linqSerializationOptions; + private readonly CosmosLinqSerializerOptionsInternal linqSerializationOptions; public CosmosLinqQuery( ContainerInternal container, @@ -42,7 +42,7 @@ public CosmosLinqQuery( QueryRequestOptions cosmosQueryRequestOptions, Expression expression, bool allowSynchronousQueryExecution, - CosmosLinqSerializerOptions linqSerializationOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializationOptions = null) { this.container = container ?? throw new ArgumentNullException(nameof(container)); this.responseFactory = responseFactory ?? throw new ArgumentNullException(nameof(responseFactory)); @@ -72,7 +72,7 @@ public CosmosLinqQuery( string continuationToken, QueryRequestOptions cosmosQueryRequestOptions, bool allowSynchronousQueryExecution, - CosmosLinqSerializerOptions linqSerializerOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) : this( container, responseFactory, diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs index 8ba71d7b98..2c695c6477 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs @@ -5,7 +5,6 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; - using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -24,7 +23,7 @@ internal sealed class CosmosLinqQueryProvider : IQueryProvider private readonly bool allowSynchronousQueryExecution; private readonly Action onExecuteScalarQueryCallback; private readonly string continuationToken; - private readonly CosmosLinqSerializerOptions linqSerializerOptions; + private readonly CosmosLinqSerializerOptionsInternal linqSerializerOptions; public CosmosLinqQueryProvider( ContainerInternal container, @@ -34,7 +33,7 @@ public CosmosLinqQueryProvider( QueryRequestOptions cosmosQueryRequestOptions, bool allowSynchronousQueryExecution, Action onExecuteScalarQueryCallback = null, - CosmosLinqSerializerOptions linqSerializerOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) { this.container = container; this.responseFactory = responseFactory; diff --git a/Microsoft.Azure.Cosmos/src/Linq/CustomCosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/CustomCosmosLinqSerializer.cs new file mode 100644 index 0000000000..03f7c9cff6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/CustomCosmosLinqSerializer.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Globalization; + using System.IO; + using System.Linq.Expressions; + using System.Reflection; + + internal class CustomCosmosLinqSerializer : ICosmosLinqSerializerInternal + { + private readonly CosmosLinqSerializer CustomCosmosSerializer; + + public CustomCosmosLinqSerializer(CosmosLinqSerializer customCosmosLinqSerializer) + { + this.CustomCosmosSerializer = customCosmosLinqSerializer; + } + + public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType) + { + return true; + } + + public string Serialize(object value, MemberExpression memberExpression, Type memberType) + { + return this.SerializeWithCustomSerializer(value); + } + + public string SerializeScalarExpression(ConstantExpression inputExpression) + { + return this.SerializeWithCustomSerializer(inputExpression.Value); + } + + public string SerializeMemberName(MemberInfo memberInfo) + { + return this.CustomCosmosSerializer.SerializeMemberName(memberInfo); + } + + private string SerializeWithCustomSerializer(object value) + { + StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); + + using (Stream stream = this.CustomCosmosSerializer.ToStream(value)) + { + using (StreamReader streamReader = new StreamReader(stream)) + { + string propertyValue = streamReader.ReadToEnd(); + writer.Write(propertyValue); + return writer.ToString(); + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs index 024c33fab0..31f20d5059 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs @@ -12,8 +12,15 @@ namespace Microsoft.Azure.Cosmos.Linq using Microsoft.Azure.Documents; using Newtonsoft.Json; - internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializer + internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializerInternal { + private readonly CosmosPropertyNamingPolicy PropertyNamingPolicy; + + public DefaultCosmosLinqSerializer(CosmosPropertyNamingPolicy propertyNamingPolicy) + { + this.PropertyNamingPolicy = propertyNamingPolicy; + } + public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType) { // There are two ways to specify a custom attribute @@ -63,9 +70,9 @@ public string SerializeScalarExpression(ConstantExpression inputExpression) return JsonConvert.SerializeObject(inputExpression.Value); } - public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) + public string SerializeMemberName(MemberInfo memberInfo) { - string memberName = null; + string memberName = memberInfo.Name; // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. Newtonsoft.Json.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); @@ -94,15 +101,7 @@ public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOpt } } - if (memberName == null) - { - memberName = memberInfo.Name; - } - - if (linqSerializerOptions != null) - { - memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName); - } + memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(this.PropertyNamingPolicy, memberName); return memberName; } diff --git a/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs b/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs index c81f5a9645..da25188bc2 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs @@ -17,7 +17,7 @@ internal static class DocumentQueryEvaluator public static SqlQuerySpec Evaluate( Expression expression, - CosmosLinqSerializerOptions linqSerializerOptions = null, + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null, IDictionary parameters = null) { switch (expression.NodeType) @@ -76,7 +76,7 @@ private static SqlQuerySpec HandleEmptyQuery(ConstantExpression expression) private static SqlQuerySpec HandleMethodCallExpression( MethodCallExpression expression, IDictionary parameters, - CosmosLinqSerializerOptions linqSerializerOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) { if (DocumentQueryEvaluator.IsTransformExpression(expression)) { diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index 5153f29115..6be1e82e9c 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -14,10 +14,10 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq.Expressions; using System.Reflection; using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Spatial; using Microsoft.Azure.Cosmos.SqlObjects; using Microsoft.Azure.Documents; - using Newtonsoft.Json; using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings; // ReSharper disable UnusedParameter.Local @@ -88,7 +88,7 @@ public static class LinqMethods public static SqlQuery TranslateQuery( Expression inputExpression, IDictionary parameters, - CosmosLinqSerializerOptions linqSerializerOptions) + CosmosLinqSerializerOptionsInternal linqSerializerOptions) { TranslationContext context = new TranslationContext(linqSerializerOptions, parameters); ExpressionToSql.Translate(inputExpression, context); // ignore result here @@ -503,8 +503,8 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit memberType = memberType.NullableUnderlyingType(); } - bool requiresCustomSerializatior = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType); - if (requiresCustomSerializatior) + bool requiresCustomSerialization = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType); + if (requiresCustomSerialization) { object value = default(object); // Enum diff --git a/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializerInternal.cs similarity index 86% rename from Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs rename to Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializerInternal.cs index f31490832d..7a3054e3b6 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializerInternal.cs @@ -7,7 +7,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq.Expressions; using System.Reflection; - internal interface ICosmosLinqSerializer + internal interface ICosmosLinqSerializerInternal { /// /// Returns true if there are custom attributes on a member expression. @@ -28,6 +28,6 @@ internal interface ICosmosLinqSerializer /// /// Serializes a member name with LINQ serializer options applied. /// - string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null); + string SerializeMemberName(MemberInfo memberInfo); } } diff --git a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs index c0bd6d38a0..8491d9cf0c 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; /// @@ -21,7 +22,7 @@ internal static class SqlTranslator /// A string describing the expression translation. internal static string TranslateExpression( Expression inputExpression, - CosmosLinqSerializerOptions linqSerializerOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) { TranslationContext context = new TranslationContext(linqSerializerOptions); @@ -32,7 +33,7 @@ internal static string TranslateExpression( internal static string TranslateExpressionOld( Expression inputExpression, - CosmosLinqSerializerOptions linqSerializerOptions = null) + CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) { TranslationContext context = new TranslationContext(linqSerializerOptions); @@ -43,7 +44,7 @@ internal static string TranslateExpressionOld( internal static SqlQuerySpec TranslateQuery( Expression inputExpression, - CosmosLinqSerializerOptions linqSerializerOptions, + CosmosLinqSerializerOptionsInternal linqSerializerOptions, IDictionary parameters) { inputExpression = ConstantEvaluator.PartialEval(inputExpression); diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index f5d53bd1e7..3b1d9cd20b 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System; using System.Collections.Generic; using System.Linq.Expressions; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; using static Microsoft.Azure.Cosmos.Linq.ExpressionToSql; using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings; @@ -24,12 +25,7 @@ internal sealed class TranslationContext /// /// The LINQ serializer /// - public readonly ICosmosLinqSerializer CosmosLinqSerializer; - - /// - /// User-provided LINQ serializer options - /// - public CosmosLinqSerializerOptions LinqSerializerOptions; + public readonly ICosmosLinqSerializerInternal CosmosLinqSerializer; /// /// Set of parameters in scope at any point; used to generate fresh parameter names if necessary. @@ -72,7 +68,11 @@ internal sealed class TranslationContext /// private Stack subqueryBindingStack; - public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDictionary parameters = null) + private static readonly ICosmosLinqSerializerInternal DefaultLinqSerializer = new DefaultCosmosLinqSerializer(new CosmosLinqSerializerOptions().PropertyNamingPolicy); + + private static readonly MemberNames DefaultMemberNames = new MemberNames(new CosmosLinqSerializerOptions()); + + public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOptionsInternal, IDictionary parameters = null) { this.InScope = new HashSet(); this.substitutions = new ParameterSubstitution(); @@ -81,10 +81,25 @@ public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDi this.collectionStack = new List(); this.CurrentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); this.subqueryBindingStack = new Stack(); - this.LinqSerializerOptions = linqSerializerOptions; this.Parameters = parameters; - this.MemberNames = new MemberNames(linqSerializerOptions); - this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer(); + + if (linqSerializerOptionsInternal?.CustomCosmosLinqSerializer != null) + { + this.CosmosLinqSerializer = new CustomCosmosLinqSerializer(linqSerializerOptionsInternal.CustomCosmosLinqSerializer); + this.MemberNames = new MemberNames(new CosmosLinqSerializerOptions()); + } + else if (linqSerializerOptionsInternal?.CosmosLinqSerializerOptions != null) + { + CosmosLinqSerializerOptions linqSerializerOptions = linqSerializerOptionsInternal.CosmosLinqSerializerOptions; + + this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer(linqSerializerOptions.PropertyNamingPolicy); + this.MemberNames = new MemberNames(linqSerializerOptions); + } + else + { + this.CosmosLinqSerializer = TranslationContext.DefaultLinqSerializer; + this.MemberNames = TranslationContext.DefaultMemberNames; + } } public Expression LookupSubstitution(ParameterExpression parameter) diff --git a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs index e11c145c71..dbe6809017 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs @@ -21,7 +21,7 @@ public static Type GetElementType(Type type) public static string GetMemberName(this MemberInfo memberInfo, TranslationContext context) { - return context.CosmosLinqSerializer.SerializeMemberName(memberInfo, context.LinqSerializerOptions); + return context.CosmosLinqSerializer.SerializeMemberName(memberInfo); } private static Type GetElementType(Type type, HashSet visitedSet) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 13e5425d7d..2397ab437a 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -24,9 +24,9 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.QueryClient; - using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Microsoft.Azure.Cosmos.ReadFeed; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; @@ -387,14 +387,16 @@ public override IOrderedQueryable GetItemLinqQueryable( { requestOptions ??= new QueryRequestOptions(); - if (linqSerializerOptions == null && this.ClientContext.ClientOptions.SerializerOptions != null) + if (this.ClientContext.ClientOptions != null) { - linqSerializerOptions = new CosmosLinqSerializerOptions + linqSerializerOptions ??= new CosmosLinqSerializerOptions { - PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions.PropertyNamingPolicy + PropertyNamingPolicy = this.ClientContext.ClientOptions.SerializerOptions?.PropertyNamingPolicy ?? CosmosPropertyNamingPolicy.Default }; } + CosmosLinqSerializerOptionsInternal linqSerializerOptionsInternal = CosmosLinqSerializerOptionsInternal.Create(linqSerializerOptions, this.ClientContext.ClientOptions.Serializer); + return new CosmosLinqQuery( this, this.ClientContext.ResponseFactory, @@ -402,7 +404,7 @@ public override IOrderedQueryable GetItemLinqQueryable( continuationToken, requestOptions, allowSynchronousQueryExecution, - linqSerializerOptions); + linqSerializerOptionsInternal); } public override FeedIterator GetItemQueryIterator( diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs new file mode 100644 index 0000000000..e58abfcebd --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Reflection; + + /// + /// This abstract class can be implemented to allow a custom serializer (Non [Json.NET serializer](https://www.newtonsoft.com/json/help/html/Introduction.htm)'s) + /// to be used by the CosmosClient for LINQ queries. + /// + /// + /// This example implements the CosmosLinqSerializer contract. + /// This example custom serializer will honor System.Text.Json attributes. + /// + /// (Stream stream) + /// { + /// if (stream == null) + /// throw new ArgumentNullException(nameof(stream)); + /// + /// using (stream) + /// { + /// if (stream.CanSeek && stream.Length == 0) + /// { + /// return default; + /// } + /// + /// if (typeof(Stream).IsAssignableFrom(typeof(T))) + /// { + /// return (T)(object)stream; + /// } + /// + /// return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + /// } + /// } + /// + /// public override Stream ToStream(T input) + /// { + /// MemoryStream streamPayload = new MemoryStream(); + /// this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + /// streamPayload.Position = 0; + /// return streamPayload; + /// } + /// + /// public override string SerializeMemberName(MemberInfo memberInfo) + /// { + /// JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + /// + /// string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) + /// ? jsonPropertyNameAttribute.Name + /// : memberInfo.Name; + /// + /// return memberName; + /// } + /// } + /// ]]> + /// + /// +#if PREVIEW + public +#else + internal +#endif + abstract class CosmosLinqSerializer : CosmosSerializer + { + /// + /// Convert a MemberInfo to a string for use in LINQ query translation. + /// This must be implemented when using a custom serializer for LINQ queries. + /// + /// Any MemberInfo used in the query. + /// A serialized representation of the member. + public abstract string SerializeMemberName(MemberInfo memberInfo); + } +} diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptionsInternal.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptionsInternal.cs new file mode 100644 index 0000000000..638c05c47b --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializerOptionsInternal.cs @@ -0,0 +1,56 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Serializer +{ + using System; + using Microsoft.Azure.Cosmos; + + /// + /// This class stores user-provided LINQ Serialization Properties. + /// + internal sealed class CosmosLinqSerializerOptionsInternal + { + /// + /// Creates an instance of CosmosSerializationOptionsInternal. + /// + public static CosmosLinqSerializerOptionsInternal Create( + CosmosLinqSerializerOptions cosmosLinqSerializerOptions, + CosmosSerializer customCosmosSerializer) + { + if (customCosmosSerializer is CosmosLinqSerializer customQueryCosmosSerializer) + { + if (cosmosLinqSerializerOptions.PropertyNamingPolicy != CosmosPropertyNamingPolicy.Default) + { + throw new InvalidOperationException($"CosmosPropertyNamingPolicy must be CosmosPropertyNamingPolicy.Default if using custom serializer for LINQ translations. See https://aka.ms/CosmosDB/dotnetlinq for more information."); + } + + return new CosmosLinqSerializerOptionsInternal(cosmosLinqSerializerOptions, customQueryCosmosSerializer); + } + else + { + return new CosmosLinqSerializerOptionsInternal(cosmosLinqSerializerOptions, null); + } + } + + private CosmosLinqSerializerOptionsInternal( + CosmosLinqSerializerOptions cosmosLinqSerializerOptions, + CosmosLinqSerializer customCosmosLinqSerializer) + { + this.CosmosLinqSerializerOptions = cosmosLinqSerializerOptions; + this.CustomCosmosLinqSerializer = customCosmosLinqSerializer; + } + + /// + /// User-provided CosmosLinqSerializerOptions. + /// + public CosmosLinqSerializerOptions CosmosLinqSerializerOptions { get; } + + /// + /// User defined customer serializer, if one exists. + /// Otherwise set to null. + /// + public CosmosLinqSerializer CustomCosmosLinqSerializer { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationUtil.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationUtil.cs index b2e0838248..8946d9ac7a 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationUtil.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializationUtil.cs @@ -4,26 +4,31 @@ namespace Microsoft.Azure.Cosmos { - using Microsoft.Azure.Cosmos.Serializer; + using System; using Newtonsoft.Json.Serialization; internal static class CosmosSerializationUtil { private static readonly CamelCaseNamingStrategy camelCaseNamingStrategy = new CamelCaseNamingStrategy(); - internal static string ToCamelCase(string name) - { - return CosmosSerializationUtil.camelCaseNamingStrategy.GetPropertyName(name, false); - } - internal static string GetStringWithPropertyNamingPolicy(CosmosLinqSerializerOptions options, string name) { - if (options != null && options.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase) + if (options == null) { - return CosmosSerializationUtil.ToCamelCase(name); + return name; } - return name; + return GetStringWithPropertyNamingPolicy(options.PropertyNamingPolicy, name); + } + + internal static string GetStringWithPropertyNamingPolicy(CosmosPropertyNamingPolicy namingPolicy, string name) + { + return namingPolicy switch + { + CosmosPropertyNamingPolicy.CamelCase => CosmosSerializationUtil.camelCaseNamingStrategy.GetPropertyName(name, false), + CosmosPropertyNamingPolicy.Default => name, + _ => throw new NotImplementedException("Unsupported CosmosPropertyNamingPolicy value"), + }; } } } diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializer.cs index 3632bd6740..e6bd34d1f5 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializer.cs @@ -7,8 +7,11 @@ namespace Microsoft.Azure.Cosmos using System.IO; /// - /// This is an interface to allow a custom serializer to be used by the CosmosClient + /// This abstract class can be implemented to allow a custom serializer to be used by the CosmosClient. /// + /// + /// To use the custom serializer for LINQ queries, must be implemented. + /// public abstract class CosmosSerializer { /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregateQueriesWithCustomSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregateQueriesWithCustomSerializer.xml new file mode 100644 index 0000000000..1a7337ba81 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregateQueriesWithCustomSerializer.xml @@ -0,0 +1,126 @@ + + + + + doc.NumericField), Object)]]> + + + + + + + + + doc.NumericField), Object)]]> + + + + + + + + Filter -> Select -> Average, Custom serializer: True]]> + doc.ArrayField.Where(m => ((m % 3) == 0)).Select(m => m)).Average(), Object)]]> + + + + + + + + Skip -> Count, Custom serializer: True]]> + f.NumericField).Skip(2).Count(), Object)]]> + + + + + + + + + Min w/ mapping]]> + doc.NumericField).Min(num => num), Object)]]> + + + + + + + + + doc.NumericField), Object)]]> + + + + + + + + + doc.NumericField), Object)]]> + + + + + + + + Filter -> Select -> Average, Custom serializer: False]]> + doc.ArrayField.Where(m => ((m % 3) == 0)).Select(m => m)).Average(), Object)]]> + + + + + + + + Skip -> Count, Custom serializer: False]]> + f.NumericField).Skip(2).Count(), Object)]]> + + + + + + + + + Min w/ mapping]]> + doc.NumericField).Min(num => num), Object)]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregatesWithCustomSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregatesWithCustomSerializer.xml new file mode 100644 index 0000000000..752edecde8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqAggregateCustomSerializationBaseline.TestAggregatesWithCustomSerializer.xml @@ -0,0 +1,58 @@ + + + + + doc.NumericField), Object)]]> + + + + . Actual:<0>. ]]> + + + + + + doc.NumericField), Object)]]> + + + + . Actual:<0>. ]]> + + + + + + + + + 0) +FROM ( + SELECT VALUE root + FROM root) AS v0 +]]> + + + + + + Filter -> Select -> Any]]> + doc.ArrayField.Where(m => ((m % 3) == 0)).Select(m => m)).Any(), Object)]]> + + + 0) +FROM ( + SELECT VALUE m0 + FROM root + JOIN m0 IN root["ArrayField"] + WHERE ((m0 % 3) = 0)) AS v0 +]]> + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml new file mode 100644 index 0000000000..a9c63ebf41 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml @@ -0,0 +1,143 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectDotNet() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectDotNet() {NumericField = 1, StringField = "1"}, new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null} : {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null}) +FROM root]]> + + + + + + + + (doc == new DataObjectDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + x).OrderBy(x => x.NumericField).Take(5)]]> + + + + + + + + + + + IIF((c.NumericField > 1), "true", "false"))]]> + + + 1) ? "true" : "false") +FROM root]]> + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetDataMember.xml similarity index 84% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetDataMember.xml index b381e2b651..df12581f67 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNet.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetDataMember.xml @@ -8,7 +8,7 @@ +WHERE (root["numericFieldDataMember"] = 1)]]> - (doc == new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + (doc == new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}))]]> +WHERE (root = {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"})]]> - new DataObjectDotNet() {NumericField = 1, StringField = "1"})]]> + new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"})]]> - IIF((doc.NumericField > 1), new DataObjectDotNet() {NumericField = 1, StringField = "1"}, new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + IIF((doc.NumericField > 1), new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}, new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}))]]> 1) ? {"NumericField": 1, "StringField": "1", "id": null, "Pk": null} : {"NumericField": 1, "StringField": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["numericFieldDataMember"] > 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"}) FROM root]]> - (doc == new DataObjectDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + (doc == new DataObjectDotNetDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> +WHERE (root = {"numericFieldDataMember": root["numericFieldDataMember"], "stringFieldDataMember": root["stringFieldDataMember"]})]]> +WHERE (root["NumericFieldDataMember"] = 1)]]> - (doc == new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + (doc == new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}))]]> +WHERE (root = {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"})]]> - new DataObjectDotNet() {NumericField = 1, StringField = "1"})]]> + new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"})]]> - IIF((doc.NumericField > 1), new DataObjectDotNet() {NumericField = 1, StringField = "1"}, new DataObjectDotNet() {NumericField = 1, StringField = "1"}))]]> + IIF((doc.NumericField > 1), new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}, new DataObjectDotNetDataMember() {NumericField = 1, StringField = "1"}))]]> 1) ? {"NumericField": 1, "StringField": "1", "id": null, "Pk": null} : {"NumericField": 1, "StringField": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["NumericFieldDataMember"] > 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"}) FROM root]]> - (doc == new DataObjectDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + (doc == new DataObjectDotNetDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> +WHERE (root = {"NumericFieldDataMember": root["NumericFieldDataMember"], "StringFieldDataMember": root["StringFieldDataMember"]})]]> @@ -31,12 +31,12 @@ SELECT VALUE root FROM root WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null})]]> @@ -51,12 +51,12 @@ WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": n SELECT VALUE {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} FROM root]]> SELECT VALUE ((root["numberValueNewtonsoft"] > 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) FROM root]]> @@ -127,12 +127,12 @@ SELECT VALUE root FROM root WHERE (root["NumberValueNewtonsoft"] = 1)]]> @@ -148,12 +148,12 @@ SELECT VALUE root FROM root WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null})]]> @@ -168,12 +168,12 @@ WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": n SELECT VALUE {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} FROM root]]> SELECT VALUE ((root["NumberValueNewtonsoft"] > 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) FROM root]]> diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDataMember.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDataMember.xml new file mode 100644 index 0000000000..215f54921f --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDataMember.xml @@ -0,0 +1,236 @@ + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"}) +FROM root]]> + + + + + + + + (doc == new DataObjectNewtonsoftDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + + + + (doc.NumericField == 1))]]> + + + + + + + + + + + (doc == new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}))]]> + + + + + + + + + + + new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"})]]> + + + + + + + + + + + IIF((doc.NumericField > 1), new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoftDataMember() {NumericField = 1, StringField = "1"}))]]> + + + 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"}) +FROM root]]> + + + + + + + + (doc == new DataObjectNewtonsoftDataMember() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDotNet.xml similarity index 92% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDotNet.xml index 704eb39807..be82c8dea7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerMultiSerializer.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoftDotNet.xml @@ -23,7 +23,7 @@ WHERE (root["numberValueNewtonsoft"] = 1)]]> - (doc == new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + (doc == new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}))]]> - new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"})]]> + new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"})]]> - IIF((doc.NumericField > 1), new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}, new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + IIF((doc.NumericField > 1), new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}))]]> - (doc == new DataObjectMultiSerializer() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + (doc == new DataObjectNewtonsoftDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> - (doc == new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + (doc == new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}))]]> - new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"})]]> + new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"})]]> - IIF((doc.NumericField > 1), new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}, new DataObjectMultiSerializer() {NumericField = 1, StringField = "1"}))]]> + IIF((doc.NumericField > 1), new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}, new DataObjectNewtonsoftDotNet() {NumericField = 1, StringField = "1"}))]]> - (doc == new DataObjectMultiSerializer() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + (doc == new DataObjectNewtonsoftDotNet() {NumericField = doc.NumericField, StringField = doc.StringField})).Select(b => "A")]]> + { + private static CosmosSerializer customCosmosLinqSerializer; + private static CosmosClient clientLinq; + private static Cosmos.Database testDbLinq; + private static Container testContainerLinq; + private static IQueryable lastExecutedScalarQuery; + + private static CosmosSerializer customCosmosSerializer; + private static CosmosClient client; + private static Cosmos.Database testDb; + private static Container testContainer; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + customCosmosLinqSerializer = new SystemTextJsonLinqSerializer(new JsonSerializerOptions()); + clientLinq = TestCommon.CreateCosmosClient((cosmosClientBuilder) + => cosmosClientBuilder.WithCustomSerializer(customCosmosLinqSerializer)); + + // Set a callback to get the handle of the last executed query to do the verification + // This is neede because aggregate queries return type is a scalar so it can't be used + // to verify the translated LINQ directly as other queries type. + clientLinq.DocumentClient.OnExecuteScalarQueryCallback = q => lastExecutedScalarQuery = q; + + string dbName = $"{nameof(LinqAggregateCustomSerializationBaseline)}-{Guid.NewGuid().ToString("N")}"; + testDbLinq = await clientLinq.CreateDatabaseAsync(dbName); + testContainerLinq = testDbLinq.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")).Result; + + customCosmosSerializer = new SystemTextJsonSerializer(new JsonSerializerOptions()); + + client = TestCommon.CreateCosmosClient((cosmosClientBuilder) + => cosmosClientBuilder.WithCustomSerializer(customCosmosSerializer)); + + // Set a callback to get the handle of the last executed query to do the verification + // This is neede because aggregate queries return type is a scalar so it can't be used + // to verify the translated LINQ directly as other queries type. + client.DocumentClient.OnExecuteScalarQueryCallback = q => lastExecutedScalarQuery = q; + + dbName = $"{nameof(LinqAggregateCustomSerializationBaseline)}-{Guid.NewGuid().ToString("N")}"; + testDb = await client.CreateDatabaseAsync(dbName); + testContainer = testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")).Result; + } + + [ClassCleanup] + public async static Task CleanUp() + { + if (testDbLinq != null) + { + await testDbLinq.DeleteStreamAsync(); + } + + clientLinq?.Dispose(); + + if (testDb != null) + { + await testDb.DeleteStreamAsync(); + } + + client?.Dispose(); + } + + [TestMethod] + [Owner("mayapainter")] + public void TestAggregateQueriesWithCustomSerializer() + { + static DataObjectDotNet createDataObj(int index, bool camelCase) + { + DataObjectDotNet obj = new DataObjectDotNet + { + NumericField = index, + StringField = index.ToString(), + ArrayField = new int[] { 1, 2, 3, 4, 5 }, + id = Guid.NewGuid().ToString(), + Pk = "Test" + }; + return obj; + } + + List>> getQueryList = new List>> + { + LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, 5, testContainerLinq, new CosmosLinqSerializerOptions()), + LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, 5, testContainer, new CosmosLinqSerializerOptions()) + }; + + List inputs = new List(); + + foreach (bool applyCustomSerializer in new List{ true, false }) + { + Func> getQuery = getQueryList[applyCustomSerializer ? 0 : 1]; + + inputs.Add(new LinqAggregateInput( + "Avg, Custom serializer: " + applyCustomSerializer, b => getQuery(b) + .Average(doc => doc.NumericField))); + + inputs.Add(new LinqAggregateInput( + "Sum, Custom serializer: " + applyCustomSerializer, b => getQuery(b) + .Sum(doc => doc.NumericField))); + + inputs.Add(new LinqAggregateInput( + "Select many -> Filter -> Select -> Average, Custom serializer: " + applyCustomSerializer, b => getQuery(b) + .SelectMany(doc => doc.ArrayField.Where(m => (m % 3) == 0).Select(m => m)).Average())); + + inputs.Add(new LinqAggregateInput( + "Select number -> Skip -> Count, Custom serializer: " + applyCustomSerializer, b => getQuery(b) + .Select(f => f.NumericField).Skip(2).Count())); + + inputs.Add(new LinqAggregateInput( + "Select number -> Min w/ mapping", b => getQuery(b) + .Select(doc => doc.NumericField).Min(num => num))); + } + + this.ExecuteTestSuite(inputs); + } + + public override LinqAggregateOutput ExecuteTest(LinqAggregateInput input) + { + lastExecutedScalarQuery = null; + Func compiledQuery = input.expression.Compile(); + + string errorMessage = null; + string query = string.Empty; + try + { + object queryResult; + try + { + queryResult = compiledQuery(true); + } + finally + { + Assert.IsNotNull(lastExecutedScalarQuery, "lastExecutedScalarQuery is not set"); + + query = JObject + .Parse(lastExecutedScalarQuery.ToString()) + .GetValue("query", StringComparison.Ordinal) + .ToString(); + } + } + catch (Exception e) + { + errorMessage = LinqTestsCommon.BuildExceptionMessageForTest(e); + } + + return new LinqAggregateOutput(query, errorMessage); + } + + private class DataObjectDotNet : LinqTestObject + { + [JsonPropertyName("NumberValueDotNet")] + public double NumericField { get; set; } + + [JsonPropertyName("StringValueDotNet")] + public string StringField { get; set; } + + [JsonPropertyName("ArrayValuesDotNet")] + public int[] ArrayField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectDotNet() { } + + public DataObjectDotNet(double numericField, string stringField, int[] arrayField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.ArrayField = arrayField; + this.id = id; + this.Pk = pk; + } + + public override string ToString() + { + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs index 5ea03bf0b6..1f511a3c11 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs @@ -172,7 +172,7 @@ public Datum2(string jsonProperty, string dataMember, string defaultMember, stri [TestMethod] public void TestAttributePriority() { - ICosmosLinqSerializer cosmosLinqSerializer = new DefaultCosmosLinqSerializer(); + ICosmosLinqSerializerInternal cosmosLinqSerializer = new DefaultCosmosLinqSerializer(new CosmosPropertyNamingPolicy()); Assert.AreEqual("jsonProperty", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("JsonProperty").First())); Assert.AreEqual("dataMember", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("DataMember").First())); Assert.AreEqual("Default", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("Default").First())); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index c8513e41b8..8cc819014a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -10,18 +10,23 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; + using System.IO; using System.Linq; using System.Linq.Expressions; + using System.Reflection; using System.Runtime.CompilerServices; using System.Text; + using System.Text.Json.Serialization; + using System.Text.Json; using System.Text.RegularExpressions; using System.Xml; + using global::Azure.Core.Serialization; using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - + using Newtonsoft.Json.Linq; + internal class LinqTestsCommon { /// @@ -333,13 +338,13 @@ public static Func> GenerateTestCosmosData(Funcnumber of test data to be created /// the target container /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied - /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. Also the serialized payload. - public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, bool camelCaseSerialization = false) + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. + public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, CosmosLinqSerializerOptions linqSerializerOptions) { List data = new List(); for (int i = 0; i < count; i++) { - data.Add(func(i, camelCaseSerialization)); + data.Add(func(i, linqSerializerOptions.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase)); } foreach (T obj in data) @@ -355,7 +360,6 @@ public static Func> GenerateSerializationTestCosmosData(F #endif }; - CosmosLinqSerializerOptions linqSerializerOptions = new CosmosLinqSerializerOptions { PropertyNamingPolicy = camelCaseSerialization ? CosmosPropertyNamingPolicy.CamelCase : CosmosPropertyNamingPolicy.Default }; IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); @@ -836,4 +840,93 @@ public override void SerializeAsXml(XmlWriter xmlWriter) } } } + + class SystemTextJsonLinqSerializer : CosmosLinqSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + + public override string SerializeMemberName(MemberInfo memberInfo) + { + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + + string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) + ? jsonPropertyNameAttribute.Name + : memberInfo.Name; + + return memberName; + } + } + + class SystemTextJsonSerializer : CosmosSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs index 3266809926..817b030a60 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs @@ -15,7 +15,6 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using System.Text.Json.Serialization; using System.Threading.Tasks; using BaselineTest; - using global::Azure.Core.Serialization; using Microsoft.Azure.Cosmos.SDK.EmulatorTests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; @@ -24,6 +23,10 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests [SDK.EmulatorTests.TestClass] public class LinqTranslationWithCustomSerializerBaseline : BaselineTests { + private static CosmosClient CosmosLinqClient; + private static Database TestDbLinq; + private static Container TestLinqContainer; + private static CosmosClient CosmosClient; private static Database TestDb; private static Container TestContainer; @@ -36,8 +39,14 @@ public class LinqTranslationWithCustomSerializerBaseline : BaselineTests cosmosClientBuilder.WithCustomSerializer(new SystemTextJsonLinqSerializer(new JsonSerializerOptions()))); + + string dbNameLinq = $"{nameof(LinqTranslationBaselineTests)}-{Guid.NewGuid():N}"; + TestDbLinq = await CosmosLinqClient.CreateDatabaseAsync(dbNameLinq); + CosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) - => cosmosClientBuilder.WithCustomSerializer(new SystemTextJsonSerializer(new JsonSerializerOptions()))); + => cosmosClientBuilder.WithCustomSerializer(new SystemTextJsonSerializer(new JsonSerializerOptions()))); string dbName = $"{nameof(LinqTranslationBaselineTests)}-{Guid.NewGuid():N}"; TestDb = await CosmosClient.CreateDatabaseAsync(dbName); @@ -46,6 +55,11 @@ public async static Task Initialize(TestContext textContext) [ClassCleanup] public async static Task Cleanup() { + if (TestDbLinq != null) + { + await TestDbLinq.DeleteStreamAsync(); + } + if (TestDb != null) { await TestDb.DeleteStreamAsync(); @@ -55,12 +69,14 @@ public async static Task Cleanup() [TestInitialize] public async Task TestInitialize() { + TestLinqContainer = await TestDbLinq.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")); TestContainer = await TestDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/Pk")); } [TestCleanup] public async Task TestCleanup() { + await TestLinqContainer.DeleteContainerStreamAsync(); await TestContainer.DeleteContainerStreamAsync(); } @@ -70,33 +86,23 @@ public override LinqTestOutput ExecuteTest(LinqTestInput input) } [TestMethod] - public void TestMemberInitializerDotNet() + public void TestMemberInitializerDotNetCustomSerializer() { - Func> getQueryCamelCase; - Func> getQueryDefault; - (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + Func> getQuery; + (_, getQuery) = this.InsertDataAndGetQueryables(true, TestLinqContainer); - string insertedData = this.GetInsertedData().Result; + string insertedData = this.GetInsertedData(TestLinqContainer).Result; - List inputs = new List(); - foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + List inputs = new List { - Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; - - List camelCaseSettingInputs = new List - { - // TODO (10/13/23): extend this and other tests cases as more LINQ features are added (GROUP BY, etc.) - new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), - new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDotNet() { NumericField = 1, StringField = "1" } : new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - - // Negative test case: serializing only field name using custom serializer not currently supported - new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) - }; - - inputs.AddRange(camelCaseSettingInputs); - } + new LinqTestInput("Filter w/ constant value", b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value", b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer", b => getQuery(b).Select(doc => new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference", b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDotNet() { NumericField = 1, StringField = "1" } : new DataObjectDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with member initialization", b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData), + new LinqTestInput("OrderBy query", b => getQuery(b).Select(x => x).OrderBy(x => x.NumericField).Take(5), skipVerification : true, inputData: insertedData), + new LinqTestInput("Conditional", b => getQuery(b).Select(c => c.NumericField > 1 ? "true" : "false"), skipVerification : true, inputData: insertedData), + }; this.ExecuteTestSuite(inputs); } @@ -106,9 +112,9 @@ public void TestMemberInitializerNewtonsoft() { Func> getQueryCamelCase; Func> getQueryDefault; - (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(false, TestContainer); - string insertedData = this.GetInsertedData().Result; + string insertedData = this.GetInsertedData(TestContainer).Result; List inputs = new List(); foreach (bool useCamelCaseSerializer in new bool[] { true, false }) @@ -121,8 +127,6 @@ public void TestMemberInitializerNewtonsoft() new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" } : new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - - // Negative test case: serializing only field name using custom serializer not currently supported new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) }; @@ -137,9 +141,9 @@ public void TestMemberInitializerDataMember() { Func> getQueryCamelCase; Func> getQueryDefault; - (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(false, TestContainer); - string insertedData = this.GetInsertedData().Result; + string insertedData = this.GetInsertedData(TestContainer).Result; List inputs = new List(); foreach (bool useCamelCaseSerializer in new bool[] { true, false }) @@ -152,8 +156,6 @@ public void TestMemberInitializerDataMember() new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDataMember() { NumericField = 1, StringField = "1" } : new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - - // Negative test case: serializing only field name using custom serializer not currently supported new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) }; @@ -164,28 +166,55 @@ public void TestMemberInitializerDataMember() } [TestMethod] - public void TestMemberInitializerMultiSerializer() + public void TestMemberInitializerNewtonsoftDotNet() { - Func> getQueryCamelCase; - Func> getQueryDefault; - (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(); + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(false, TestContainer); - string insertedData = this.GetInsertedData().Result; + string insertedData = this.GetInsertedData(TestContainer).Result; List inputs = new List(); foreach (bool useCamelCaseSerializer in new bool[] { true, false }) { - Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; List camelCaseSettingInputs = new List { new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), - new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" } : new DataObjectMultiSerializer() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoftDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectNewtonsoftDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectNewtonsoftDotNet() { NumericField = 1, StringField = "1" } : new DataObjectNewtonsoftDotNet() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoftDotNet() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } - // Negative test case: serializing only field name using custom serializer not currently supported - new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectMultiSerializer() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestMemberInitializerNewtonsoftDataMember() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(false, TestContainer); + + string insertedData = this.GetInsertedData(TestContainer).Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoftDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectNewtonsoftDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectNewtonsoftDataMember() { NumericField = 1, StringField = "1" } : new DataObjectNewtonsoftDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoftDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) }; inputs.AddRange(camelCaseSettingInputs); @@ -194,7 +223,36 @@ public void TestMemberInitializerMultiSerializer() this.ExecuteTestSuite(inputs); } - private (Func>, Func>) InsertDataAndGetQueryables() where T : LinqTestObject + [TestMethod] + public void TestMemberInitializerDotNetDataMember() + { + Func> getQueryCamelCase; + Func> getQueryDefault; + (getQueryCamelCase, getQueryDefault) = this.InsertDataAndGetQueryables(false, TestContainer); + + string insertedData = this.GetInsertedData(TestContainer).Result; + + List inputs = new List(); + foreach (bool useCamelCaseSerializer in new bool[] { true, false }) + { + Func> getQuery = useCamelCaseSerializer ? getQueryCamelCase : getQueryDefault; + + List camelCaseSettingInputs = new List + { + new LinqTestInput("Filter w/ constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.NumericField == 1), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNetDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDotNetDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDotNetDataMember() { NumericField = 1, StringField = "1" } : new DataObjectDotNetDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDotNetDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + }; + + inputs.AddRange(camelCaseSettingInputs); + } + + this.ExecuteTestSuite(inputs); + } + + private (Func>, Func>) InsertDataAndGetQueryables(bool customSerializer, Container container) where T : LinqTestObject { static T createDataObj(int index, bool camelCase) { @@ -205,16 +263,28 @@ static T createDataObj(int index, bool camelCase) return obj; } - Func> getQueryCamelCase = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, TestContainer, camelCaseSerialization: true); - Func> getQueryDefault = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, TestContainer, camelCaseSerialization: false); + CosmosLinqSerializerOptions linqSerializerOptionsCamelCase = new CosmosLinqSerializerOptions + { + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase, + }; + + CosmosLinqSerializerOptions linqSerializerOptionsDefault = new CosmosLinqSerializerOptions(); + + Func> getQueryCamelCase = null; + if (!customSerializer) + { + getQueryCamelCase = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, container, linqSerializerOptionsCamelCase); + } + + Func> getQueryDefault = LinqTestsCommon.GenerateSerializationTestCosmosData(createDataObj, RecordCount, container, linqSerializerOptionsDefault); return (getQueryCamelCase, getQueryDefault); } - private async Task GetInsertedData() + private async Task GetInsertedData(Container container) { List insertedDataList = new List(); - using (FeedIterator feedIterator = TestContainer.GetItemQueryStreamIterator("SELECT * FROM c")) + using (FeedIterator feedIterator = container.GetItemQueryStreamIterator("SELECT * FROM c")) { while (feedIterator.HasMoreResults) { @@ -244,64 +314,91 @@ private async Task GetInsertedData() } } - string insertedData = JsonConvert.SerializeObject(insertedDataList.Select(item => item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented }); - return insertedData; + return JsonConvert.SerializeObject(insertedDataList.Select(item => item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented }); } - private class SystemTextJsonSerializer : CosmosSerializer + private class DataObjectDotNet : LinqTestObject { - private readonly JsonObjectSerializer systemTextJsonSerializer; + [JsonPropertyName("NumberValueDotNet")] + public double NumericField { get; set; } + + [JsonPropertyName("StringValueDotNet")] + public string StringField { get; set; } + + [System.Text.Json.Serialization.JsonIgnore] + public string IgnoreField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectDotNet() { } - public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) + public DataObjectDotNet(double numericField, string stringField, string id, string pk) { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + this.NumericField = numericField; + this.StringField = stringField; + this.IgnoreField = "Ignore"; + this.id = id; + this.Pk = pk; } - public override T FromStream(Stream stream) + public override string ToString() { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; + } + } - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } + private class DataObjectNewtonsoft : LinqTestObject + { + [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] + public double NumericField { get; set; } - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } + [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] + public string StringField { get; set; } - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } + [Newtonsoft.Json.JsonIgnore] + public string IgnoreField { get; set; } + + public string id { get; set; } + + public string Pk { get; set; } + + public DataObjectNewtonsoft() { } + + public DataObjectNewtonsoft(double numericField, string stringField, string id, string pk) + { + this.NumericField = numericField; + this.StringField = stringField; + this.IgnoreField = "ignore"; + this.id = id; + this.Pk = pk; } - public override Stream ToStream(T input) + public override string ToString() { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, typeof(T), default); - streamPayload.Position = 0; - return streamPayload; + return $"{{NumericField:{this.NumericField},StringField:{this.StringField},id:{this.id},Pk:{this.Pk}}}"; } } - private class DataObjectDotNet : LinqTestObject + [DataContract] + private class DataObjectDataMember : LinqTestObject { - [JsonPropertyName("numberValueDotNet")] + [DataMember(Name = "NumericFieldDataMember")] public double NumericField { get; set; } - [JsonPropertyName("stringValueDotNet")] + [DataMember(Name = "StringFieldDataMember")] public string StringField { get; set; } + [DataMember(Name = "id")] public string id { get; set; } + [DataMember(Name = "Pk")] public string Pk { get; set; } - public DataObjectDotNet() { } + public DataObjectDataMember() { } - public DataObjectDotNet(double numericField, string stringField, string id, string pk) + public DataObjectDataMember(double numericField, string stringField, string id, string pk) { this.NumericField = numericField; this.StringField = stringField; @@ -315,21 +412,23 @@ public override string ToString() } } - private class DataObjectNewtonsoft : LinqTestObject + private class DataObjectNewtonsoftDotNet : LinqTestObject { [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] + [JsonPropertyName("numberValueDotNet")] public double NumericField { get; set; } [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] + [JsonPropertyName("stringValueDotNet")] public string StringField { get; set; } public string id { get; set; } public string Pk { get; set; } - public DataObjectNewtonsoft() { } + public DataObjectNewtonsoftDotNet() { } - public DataObjectNewtonsoft(double numericField, string stringField, string id, string pk) + public DataObjectNewtonsoftDotNet(double numericField, string stringField, string id, string pk) { this.NumericField = numericField; this.StringField = stringField; @@ -344,23 +443,23 @@ public override string ToString() } [DataContract] - private class DataObjectDataMember : LinqTestObject + private class DataObjectNewtonsoftDataMember : LinqTestObject { + [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] [DataMember(Name = "NumericFieldDataMember")] public double NumericField { get; set; } + [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] [DataMember(Name = "StringFieldDataMember")] public string StringField { get; set; } - [DataMember(Name = "id")] public string id { get; set; } - [DataMember(Name = "Pk")] public string Pk { get; set; } - public DataObjectDataMember() { } + public DataObjectNewtonsoftDataMember() { } - public DataObjectDataMember(double numericField, string stringField, string id, string pk) + public DataObjectNewtonsoftDataMember(double numericField, string stringField, string id, string pk) { this.NumericField = numericField; this.StringField = stringField; @@ -374,13 +473,14 @@ public override string ToString() } } - private class DataObjectMultiSerializer : LinqTestObject + [DataContract] + private class DataObjectDotNetDataMember : LinqTestObject { - [Newtonsoft.Json.JsonProperty(PropertyName = "NumberValueNewtonsoft")] + [DataMember(Name = "NumericFieldDataMember")] [JsonPropertyName("numberValueDotNet")] public double NumericField { get; set; } - [Newtonsoft.Json.JsonProperty(PropertyName = "StringValueNewtonsoft")] + [DataMember(Name = "StringFieldDataMember")] [JsonPropertyName("stringValueDotNet")] public string StringField { get; set; } @@ -388,9 +488,9 @@ private class DataObjectMultiSerializer : LinqTestObject public string Pk { get; set; } - public DataObjectMultiSerializer() { } + public DataObjectDotNetDataMember() { } - public DataObjectMultiSerializer(double numericField, string stringField, string id, string pk) + public DataObjectDotNetDataMember(double numericField, string stringField, string id, string pk) { this.NumericField = numericField; this.StringField = stringField; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 7dd766d5d3..83de702ef3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -40,9 +40,11 @@ - - + + + + @@ -123,6 +125,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -264,13 +269,19 @@ PreserveNewest - + PreserveNewest - + PreserveNewest - + + PreserveNewest + + + PreserveNewest + + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index dde2d208bc..94aae6155b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -352,6 +352,34 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.String SerializeMemberName(System.Reflection.MemberInfo)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.CosmosSerializer;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": { + "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.String SerializeMemberName(System.Reflection.MemberInfo)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + }, + "Members": {}, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs index 8e50a21dd0..0931271d92 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs @@ -10,7 +10,10 @@ namespace Microsoft.Azure.Cosmos.Linq using System.IO; using System.Linq; using System.Linq.Expressions; + using System.Reflection; + using System.Text.Json.Serialization; using global::Azure.Core.Serialization; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -18,6 +21,8 @@ namespace Microsoft.Azure.Cosmos.Linq [TestClass] public class CosmosLinqJsonConverterTests { + private readonly CosmosLinqSerializerOptions defaultOptions = new(); + [TestMethod] public void DateTimeKindIsPreservedTest() { @@ -37,63 +42,59 @@ public void DateTimeKindIsPreservedTest() [TestMethod] public void EnumIsPreservedAsINTest() { - // Arrange - CosmosLinqSerializerOptions options = new() - { - //CustomCosmosSerializer = new TestCustomJsonSerializer() - }; + CosmosLinqSerializerOptionsInternal options = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonLinqSerializer()); + CosmosLinqSerializerOptionsInternal defaultOptions = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonSerializer()); - // Act TestEnum[] values = new[] { TestEnum.One, TestEnum.Two }; + Expression> expr = a => values.Contains(a.Value); - string sql = SqlTranslator.TranslateExpression(expr.Body, options); - // Assert - // Assert.AreEqual("(a[\"Value\"] IN (\"One\", \"Two\"))", sql); // <- TODO - Desired Behavior with CustomSerializer - Assert.AreEqual("(a[\"Value\"] IN (0, 1))", sql); // <- Actual behavior, with ability to set custom serializor reverted + Expression> exprNewtonsoft = a => values.Contains(a.Value); + string sqlDefault = SqlTranslator.TranslateExpression(exprNewtonsoft.Body, defaultOptions); + + Assert.AreEqual("(a[\"Value\"] IN (\"One\", \"Two\"))", sql); + Assert.AreEqual("(a[\"Value\"] IN (0, 1))", sqlDefault); } [TestMethod] public void EnumIsPreservedAsEQUALSTest() { - // Arrange - CosmosLinqSerializerOptions options = new() - { - // CustomCosmosSerializer = new TestCustomJsonSerializer() - }; + CosmosLinqSerializerOptionsInternal options = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonLinqSerializer()); + CosmosLinqSerializerOptionsInternal defaultOptions = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonSerializer()); - // Act TestEnum statusValue = TestEnum.One; - Expression> expr = a => a.Value == statusValue; + Expression> expr = a => a.Value == statusValue; string sql = SqlTranslator.TranslateExpression(expr.Body, options); - // Assert - // Assert.AreEqual("(a[\"Value\"] = \"One\")", sql); // <- THIS is the correct value, if we are able to use the custom serializer - Assert.AreEqual("(a[\"Value\"] = 0)", sql); // <- THIS is the current mis-behavior of the SDK + Expression> exprDefault = a => a.Value == statusValue; + string sqlNewtonsoft = SqlTranslator.TranslateExpression(exprDefault.Body, defaultOptions); + + Assert.AreEqual("(a[\"Value\"] = \"One\")", sql); + Assert.AreEqual("(a[\"Value\"] = \"One\")", sqlNewtonsoft); } [TestMethod] public void EnumIsPreservedAsEXPRESSIONTest() { - // Arrange - CosmosLinqSerializerOptions options = new() - { - // CustomCosmosSerializer = new TestCustomJsonSerializer() - }; - - // Act + CosmosLinqSerializerOptionsInternal options = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonLinqSerializer()); + CosmosLinqSerializerOptionsInternal defaultOptions = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonSerializer()); // Get status constant ConstantExpression status = Expression.Constant(TestEnum.One); // Get member access expression - ParameterExpression arg = Expression.Parameter(typeof(TestEnumNewtonsoftDocument), "a"); + ParameterExpression arg = Expression.Parameter(typeof(TestEnumDocument), "a"); + ParameterExpression argNewtonsoft = Expression.Parameter(typeof(TestEnumNewtonsoftDocument), "a"); // Access the value property MemberExpression docValueExpression = Expression.MakeMemberAccess( arg, + typeof(TestEnumDocument).GetProperty(nameof(TestEnumDocument.Value))! + ); + MemberExpression docValueExpressionDefault = Expression.MakeMemberAccess( + argNewtonsoft, typeof(TestEnumNewtonsoftDocument).GetProperty(nameof(TestEnumNewtonsoftDocument.Value))! ); @@ -102,15 +103,22 @@ public void EnumIsPreservedAsEXPRESSIONTest() docValueExpression, status ); + BinaryExpression expressionDefault = Expression.Equal( + docValueExpressionDefault, + status + ); // Create lambda expression - Expression> lambda = - Expression.Lambda>(expression, arg); - + Expression> lambda = + Expression.Lambda>(expression, arg); string sql = SqlTranslator.TranslateExpression(lambda.Body, options); - // Assert + Expression> lambdaNewtonsoft = + Expression.Lambda>(expressionDefault, argNewtonsoft); + string sqlDefault = SqlTranslator.TranslateExpression(lambdaNewtonsoft.Body, defaultOptions); + Assert.AreEqual("(a[\"Value\"] = \"One\")", sql); + Assert.AreEqual("(a[\"Value\"] = \"One\")", sqlDefault); } enum TestEnum @@ -122,19 +130,18 @@ enum TestEnum class TestEnumDocument { - [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] // TODO: Remove this once we have the ability to use custom serializer for LINQ queries public TestEnum Value { get; set; } } class TestEnumNewtonsoftDocument { - [JsonConverter(typeof(StringEnumConverter))] + [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] public TestEnum Value { get; set; } } class TestDocument { - [JsonConverter(typeof(DateJsonConverter))] + [Newtonsoft.Json.JsonConverter(typeof(DateJsonConverter))] public DateTime StartDate { get; set; } } @@ -156,8 +163,10 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s [TestMethod] public void TestNewtonsoftExtensionDataQuery() { + CosmosLinqSerializerOptionsInternal defaultOptions = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, null); + Expression> expr = a => (string)a.NewtonsoftExtensionData["foo"] == "bar"; - string sql = SqlTranslator.TranslateExpression(expr.Body); + string sql = SqlTranslator.TranslateExpression(expr.Body, defaultOptions); Assert.AreEqual("(a[\"foo\"] = \"bar\")", sql); } @@ -165,11 +174,11 @@ public void TestNewtonsoftExtensionDataQuery() [TestMethod] public void TestSystemTextJsonExtensionDataQuery() { + CosmosLinqSerializerOptionsInternal dotNetOptions = CosmosLinqSerializerOptionsInternal.Create(this.defaultOptions, new TestCustomJsonLinqSerializer()); + Expression> expr = a => ((object)a.NetExtensionData["foo"]) == "bar"; - string sql = SqlTranslator.TranslateExpression(expr.Body); + string sql = SqlTranslator.TranslateExpression(expr.Body, dotNetOptions); - // TODO: This is a limitation in the translator. It should be able to handle STJ extension data, if a custom - // JSON serializer is specified. Assert.AreEqual("(a[\"NetExtensionData\"][\"foo\"] = \"bar\")", sql); } @@ -182,6 +191,66 @@ class DocumentWithExtensionData public Dictionary NetExtensionData { get; set; } } + /// + // See: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs + /// + class TestCustomJsonLinqSerializer : CosmosLinqSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public static readonly System.Text.Json.JsonSerializerOptions JsonOptions = new() + { + DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, + PropertyNameCaseInsensitive = true, + Converters = { + new System.Text.Json.Serialization.JsonStringEnumConverter(), + } + }; + + public TestCustomJsonLinqSerializer() + { + this.systemTextJsonSerializer = new JsonObjectSerializer(JsonOptions); + } + + public override T FromStream(Stream stream) + { + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream stream = new(); + + this.systemTextJsonSerializer.Serialize(stream, input, input.GetType(), default); + stream.Position = 0; + return stream; + } + + public override string SerializeMemberName(MemberInfo memberInfo) + { + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + + string memberName = jsonPropertyNameAttribute != null && !string.IsNullOrEmpty(jsonPropertyNameAttribute.Name) + ? jsonPropertyNameAttribute.Name + : memberInfo.Name; + + return memberName; + } + } + /// // See: https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs /// @@ -223,9 +292,9 @@ public override T FromStream(Stream stream) public override Stream ToStream(T input) { - MemoryStream stream = new (); + MemoryStream stream = new(); - this.systemTextJsonSerializer.Serialize(stream, input, typeof(T), default); + this.systemTextJsonSerializer.Serialize(stream, input, input.GetType(), default); stream.Position = 0; return stream; } From 6cb9038fd4f5de8b94a5e51a304b7de72028045e Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Sun, 7 Jan 2024 23:42:38 -0800 Subject: [PATCH 252/337] BulkMode: Adds PartitionKeyRangeId in Bulk Mode and TransactionalBatch Response Headers (#4240) * Code changes to add partition key range id header to bulk and transactional responses. * Code changes to add pk range id check in emulator tests. --- .../Batch/TransactionalBatchOperationResult.cs | 6 ++++++ .../src/Batch/TransactionalBatchResponse.cs | 2 ++ .../Batch/BatchAsyncContainerExecutorTests.cs | 1 + .../Batch/CosmosItemBulkTests.cs | 16 ++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs index fc3d888ac5..0aa6d9bbf7 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchOperationResult.cs @@ -98,6 +98,11 @@ public virtual bool IsSuccessStatusCode /// internal virtual string SessionToken { get; set; } + /// + /// A string containing the partition key range id assigned to this result. + /// + internal virtual string PartitionKeyRangeId { get; set; } + /// /// ActivityId related to the operation /// @@ -218,6 +223,7 @@ internal ResponseMessage ToResponseMessage(ContainerInternal cosmosContainerCore RetryAfter = this.RetryAfter, RequestCharge = this.RequestCharge, Session = this.SessionToken, + PartitionKeyRangeId = this.PartitionKeyRangeId, ActivityId = this.ActivityId, }; diff --git a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchResponse.cs b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchResponse.cs index 86564dadee..e594644731 100644 --- a/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Batch/TransactionalBatchResponse.cs @@ -312,6 +312,7 @@ private void CreateAndPopulateResults(IReadOnlyList operatio SubStatusCode = this.SubStatusCode, RetryAfter = TimeSpan.FromMilliseconds(retryAfterMilliseconds), SessionToken = this.Headers.Session, + PartitionKeyRangeId = this.Headers.PartitionKeyRangeId, ActivityId = this.ActivityId, }; @@ -345,6 +346,7 @@ private static async Task PopulateFromContentAsync( operationResult.Trace = trace; operationResult.SessionToken = responseMessage.Headers.Session; + operationResult.PartitionKeyRangeId = responseMessage.Headers.PartitionKeyRangeId; operationResult.ActivityId = responseMessage.Headers.ActivityId; results.Add(operationResult); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchAsyncContainerExecutorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchAsyncContainerExecutorTests.cs index 1c2998b7f9..86ea3cab79 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchAsyncContainerExecutorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/BatchAsyncContainerExecutorTests.cs @@ -61,6 +61,7 @@ public async Task DoOperationsAsync() MyDocument document = cosmosDefaultJsonSerializer.FromStream(result.ResourceStream); Assert.AreEqual(i.ToString(), document.id); + Assert.IsNotNull(result.PartitionKeyRangeId); ItemResponse storedDoc = await this.cosmosContainer.ReadItemAsync(i.ToString(), new Cosmos.PartitionKey(i.ToString())); Assert.IsNotNull(storedDoc.Resource); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs index 2658b00dfc..00c59d085c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Batch/CosmosItemBulkTests.cs @@ -96,6 +96,7 @@ public async Task CreateItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); ToDoActivity document = TestCommon.SerializerCore.FromStream(result.Content); Assert.AreEqual(i.ToString(), document.id); @@ -120,6 +121,7 @@ public async Task CreateItemAsync_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } @@ -197,6 +199,7 @@ public async Task CreateItemAsyncValidateIntendedCollRid_WithBulk() Task> task = tasks[i]; ItemResponse result = await task; Assert.IsTrue(result.Headers.RequestCharge > 0); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } @@ -228,6 +231,7 @@ public async Task CreateItemAsyncValidateIntendedCollRid_WithBulk() Task> task = tasks[i]; ItemResponse result = await task; Assert.IsTrue(result.Headers.RequestCharge > 0); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } @@ -251,6 +255,7 @@ public async Task CreateItemJObjectWithoutPK_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } @@ -275,6 +280,7 @@ public async Task UpsertItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); ToDoActivity document = TestCommon.SerializerCore.FromStream(result.Content); Assert.AreEqual(i.ToString(), document.id); @@ -299,6 +305,7 @@ public async Task UpsertItem_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } @@ -334,6 +341,7 @@ public async Task DeleteItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.NoContent, result.StatusCode); } @@ -369,6 +377,7 @@ public async Task DeleteItem_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.NoContent, result.StatusCode); } @@ -404,6 +413,7 @@ public async Task ReadItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); } @@ -439,6 +449,7 @@ public async Task ReadItem_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); } @@ -474,6 +485,7 @@ public async Task ReplaceItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); } @@ -509,6 +521,7 @@ public async Task ReplaceItem_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); } @@ -548,6 +561,7 @@ public async Task PatchItemStream_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); } @@ -587,6 +601,7 @@ public async Task PatchItem_WithBulk() Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.OK, result.StatusCode); Assert.AreEqual("patched", result.Resource.description); @@ -630,6 +645,7 @@ private async Task CreateLargeItemStreamWithBulk(int appxItemSize) Assert.IsTrue(result.Headers.RequestCharge > 0); Assert.IsNotNull(result.Headers.Session); Assert.IsNotNull(result.Headers.ActivityId); + Assert.IsNotNull(result.Headers.PartitionKeyRangeId); Assert.IsFalse(string.IsNullOrEmpty(result.Diagnostics.ToString())); Assert.AreEqual(HttpStatusCode.Created, result.StatusCode); } From 8af055c68e01af1df9d530d3b716437c68ee5579 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 10 Jan 2024 04:47:49 -0500 Subject: [PATCH 253/337] GatewayClientStore: Fixes an issue with dealing with invalid JSON HTTP responses (#4229) * initial commit * add back a using to fix build * change exception message * check for json validity using parse * some refactoring and tests. I want to see if I can mine more tests later. * comment to rethink removing the media type check * more tests and refactoring. going to mine out more tests before I undraft it * moved string to top of class * more tests and some refactoring * simplified some more things in tests * removing this method * removed unnecessary usings * last refactoring to ignore dealing with Error.Message when empty * removed null check on 2 arguments because it was breaking other tests. I will maybe come back to it later. * && and > 0 in the conditional --- .../src/GatewayStoreClient.cs | 99 ++++--- .../GatewayStoreClientTests.cs | 256 ++++++++++++++++++ 2 files changed, 310 insertions(+), 45 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreClientTests.cs diff --git a/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs b/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs index e151ffcd94..db6f4a027f 100644 --- a/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs +++ b/Microsoft.Azure.Cosmos/src/GatewayStoreClient.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos using System.Text; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Tracing.TraceData; using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Collections; @@ -132,69 +131,79 @@ internal static INameValueCollection ExtractResponseHeaders(HttpResponseMessage return headers; } + /// + /// Creating a new DocumentClientException using the Gateway response message. + /// + /// + /// internal static async Task CreateDocumentClientExceptionAsync( HttpResponseMessage responseMessage, IClientSideRequestStatistics requestStatistics) { - bool isNameBased = false; - bool isFeed = false; - string resourceTypeString; - string resourceIdOrFullName; - - string resourceLink = responseMessage.RequestMessage.RequestUri.LocalPath; - if (!PathsHelper.TryParsePathSegments(resourceLink, out isFeed, out resourceTypeString, out resourceIdOrFullName, out isNameBased)) + if (!PathsHelper.TryParsePathSegments( + resourceUrl: responseMessage.RequestMessage.RequestUri.LocalPath, + isFeed: out _, + resourcePath: out _, + resourceIdOrFullName: out string resourceIdOrFullName, + isNameBased: out _)) { // if resourceLink is invalid - we will not set resourceAddress in exception. } // If service rejects the initial payload like header is to large it will return an HTML error instead of JSON. - if (string.Equals(responseMessage.Content?.Headers?.ContentType?.MediaType, "application/json", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(responseMessage.Content?.Headers?.ContentType?.MediaType, "application/json", StringComparison.OrdinalIgnoreCase) && + responseMessage.Content?.Headers.ContentLength > 0) { - Stream readStream = await responseMessage.Content.ReadAsStreamAsync(); - Error error = Documents.Resource.LoadFrom(readStream); - return new DocumentClientException( - error, - responseMessage.Headers, - responseMessage.StatusCode) + try + { + Stream contentAsStream = await responseMessage.Content.ReadAsStreamAsync(); + Error error = JsonSerializable.LoadFrom(stream: contentAsStream); + + return new DocumentClientException( + errorResource: error, + responseHeaders: responseMessage.Headers, + statusCode: responseMessage.StatusCode) + { + StatusDescription = responseMessage.ReasonPhrase, + ResourceAddress = resourceIdOrFullName, + RequestStatistics = requestStatistics + }; + } + catch { - StatusDescription = responseMessage.ReasonPhrase, - ResourceAddress = resourceIdOrFullName, - RequestStatistics = requestStatistics - }; + } } - else + + StringBuilder contextBuilder = new StringBuilder(); + contextBuilder.AppendLine(await responseMessage.Content.ReadAsStringAsync()); + + HttpRequestMessage requestMessage = responseMessage.RequestMessage; + + if (requestMessage != null) { - StringBuilder context = new StringBuilder(); - context.AppendLine(await responseMessage.Content.ReadAsStringAsync()); + contextBuilder.AppendLine($"RequestUri: {requestMessage.RequestUri};"); + contextBuilder.AppendLine($"RequestMethod: {requestMessage.Method.Method};"); - HttpRequestMessage requestMessage = responseMessage.RequestMessage; - if (requestMessage != null) + if (requestMessage.Headers != null) { - context.AppendLine($"RequestUri: {requestMessage.RequestUri.ToString()};"); - context.AppendLine($"RequestMethod: {requestMessage.Method.Method};"); - - if (requestMessage.Headers != null) + foreach (KeyValuePair> header in requestMessage.Headers) { - foreach (KeyValuePair> header in requestMessage.Headers) - { - context.AppendLine($"Header: {header.Key} Length: {string.Join(",", header.Value).Length};"); - } + contextBuilder.AppendLine($"Header: {header.Key} Length: {string.Join(",", header.Value).Length};"); } } - - String message = await responseMessage.Content.ReadAsStringAsync(); - return new DocumentClientException( - message: context.ToString(), - innerException: null, - responseHeaders: responseMessage.Headers, - statusCode: responseMessage.StatusCode, - requestUri: responseMessage.RequestMessage.RequestUri) - { - StatusDescription = responseMessage.ReasonPhrase, - ResourceAddress = resourceIdOrFullName, - RequestStatistics = requestStatistics - }; } + + return new DocumentClientException( + message: contextBuilder.ToString(), + innerException: null, + responseHeaders: responseMessage.Headers, + statusCode: responseMessage.StatusCode, + requestUri: responseMessage.RequestMessage.RequestUri) + { + StatusDescription = responseMessage.ReasonPhrase, + ResourceAddress = resourceIdOrFullName, + RequestStatistics = requestStatistics + }; } internal static bool IsAllowedRequestHeader(string headerName) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreClientTests.cs new file mode 100644 index 0000000000..ff750f8ed6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreClientTests.cs @@ -0,0 +1,256 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Net; + using System.Net.Http; + using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Tracing.TraceData; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + + /// + /// Tests for . + /// + [TestClass] + public class GatewayStoreClientTests + { + /// + /// Testing CreateDocumentClientExceptionAsync when media type is NOT application/json and the error message has a length that is not zero. + /// This is not meant to be an exhaustive test for all legitimate content media types. + /// + /// + [TestMethod] + [DataRow("text/html", "")] + [DataRow("text/plain", "This is a test error message.")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsNotApplicationJsonAndErrorMessageLengthIsNotZeroAsync( + string mediaType, + string errorMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: JsonConvert.SerializeObject( + value: new Error() { Code = HttpStatusCode.NotFound.ToString(), Message = errorMessage })), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsTrue(condition: documentClientException.Message.Contains(errorMessage)); + + Assert.IsNotNull(value: documentClientException.Error); + Assert.AreEqual(expected: HttpStatusCode.NotFound.ToString(), actual: documentClientException.Error.Code); + Assert.IsTrue(documentClientException.Error.Message.Contains(errorMessage)); + } + + /// + /// Testing CreateDocumentClientExceptionAsync when media type is NOT application/json and the error message has a length that is zero. + /// This is not meant to be an exhaustive test for all legitimate content media types. + /// + /// + [TestMethod] + [DataRow("text/html", "")] + [DataRow("text/html", " ")] + [DataRow("text/plain", "")] + [DataRow("text/plain", " ")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsNotApplicationJsonAndErrorMessageLengthIsZeroAsync( + string mediaType, + string errorMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: JsonConvert.SerializeObject( + value: new Error() { Code = HttpStatusCode.NotFound.ToString(), Message = errorMessage })), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsNotNull(value: documentClientException.Message); + + Assert.IsNotNull(value: documentClientException.Error); + Assert.AreEqual(expected: HttpStatusCode.NotFound.ToString(), actual: documentClientException.Error.Code); + Assert.IsNotNull(value: documentClientException.Error.Message); + } + + /// + /// Testing CreateDocumentClientExceptionAsync when media type is NOT application/json and the header content length is zero. + /// This is not meant to be an exhaustive test for all legitimate content media types. + /// + /// + [TestMethod] + [DataRow("text/plain", @"")] + [DataRow("text/plain", @" ")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsNotApplicationJsonAndHeaderContentLengthIsZeroAsync( + string mediaType, + string contentMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: contentMessage), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsNotNull(value: documentClientException.Message); + + Assert.IsNotNull(value: documentClientException.Error); + Assert.AreEqual(expected: HttpStatusCode.NotFound.ToString(), actual: documentClientException.Error.Code); + Assert.IsNotNull(value: documentClientException.Error.Message); + } + + /// + /// Testing CreateDocumentClientExceptionAsync when media type is application/json and the error message length is zero. + /// + /// + [TestMethod] + [DataRow("application/json", "")] + [DataRow("application/json", " ")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsApplicationJsonAndErrorMessageLengthIsZeroAsync( + string mediaType, + string errorMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: JsonConvert.SerializeObject( + value: new Error() { Code = HttpStatusCode.NotFound.ToString(), Message = errorMessage })), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsNotNull(value: documentClientException.Message); + + Assert.IsNotNull(value: documentClientException.Error); + Assert.AreEqual(expected: HttpStatusCode.NotFound.ToString(), actual: documentClientException.Error.Code); + Assert.IsNotNull(value: documentClientException.Error.Message); + } + + /// + /// Testing CreateDocumentClientExceptionAsync when media type is application/json and the content message is not valid json. + /// and has a content length that is not zero after trim. + /// + /// + [TestMethod] + [DataRow("application/json", @"")] + [DataRow("application/json", @" ")] + [DataRow("application/json", @" ")] + [DataRow("application/json", @" ")] + [DataRow("application/json", @"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")] + [DataRow("application/json", @" ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")] + [DataRow("application/json", @"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ")] + [DataRow("application/json", @" ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 ")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsApplicationJsonAndContentMessageIsNotValidJsonAsync( + string mediaType, + string contentMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: contentMessage), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsTrue(condition: documentClientException.Message.Contains(contentMessage)); + } + + /// + /// Testing CreateDocumentClientExceptionAsync when media type is application/json and the header content length is zero. + /// + [TestMethod] + [DataRow("application/json", @"")] + [DataRow("application/json", @" ")] + [Owner("philipthomas-MSFT")] + public async Task TestCreateDocumentClientExceptionWhenMediaTypeIsApplicationJsonAndHeaderContentLengthIsZeroAsync( + string mediaType, + string contentMessage) + { + HttpResponseMessage responseMessage = new(statusCode: HttpStatusCode.NotFound) + { + RequestMessage = new HttpRequestMessage( + method: HttpMethod.Get, + requestUri: @"https://pt_ac_test_uri.com/"), + Content = new StringContent( + mediaType: mediaType, + encoding: Encoding.UTF8, + content: contentMessage), + }; + + DocumentClientException documentClientException = await GatewayStoreClient.CreateDocumentClientExceptionAsync( + responseMessage: responseMessage, + requestStatistics: GatewayStoreClientTests.CreateClientSideRequestStatistics()); + + Assert.IsNotNull(value: documentClientException); + Assert.AreEqual(expected: HttpStatusCode.NotFound, actual: documentClientException.StatusCode); + Assert.IsNotNull(value: documentClientException.Message); + + Assert.IsNotNull(value: documentClientException.Error); + Assert.AreEqual(expected: HttpStatusCode.NotFound.ToString(), actual: documentClientException.Error.Code); + Assert.IsNotNull(value: documentClientException.Error.Message); + } + + private static IClientSideRequestStatistics CreateClientSideRequestStatistics() + { + return new ClientSideRequestStatisticsTraceDatum( + startTime: DateTime.UtcNow, + trace: NoOpTrace.Singleton); + } + } +} From 24ee86b78c993f58a2b83f16183087f4cb6ea56c Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Tue, 16 Jan 2024 10:39:08 -0800 Subject: [PATCH 254/337] [Internal] FaultInjection: Adds support for FaultInjection for RNTBD V3 SDK (#4217) * Adds fault injection support * chaos factory method * added null check * fixed null check * requested changes * removed resolveFaultInjectionEndpoints * added requested comments --- Microsoft.Azure.Cosmos/src/AssemblyInfo.cs | 4 +++ .../src/CosmosClientOptions.cs | 6 ++-- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 12 ++++++-- .../IChaosInterceptorFactory.cs | 20 +++++++++++++ .../src/Fluent/CosmosClientBuilder.cs | 10 +++++++ .../src/Resource/ClientContextCore.cs | 3 +- .../src/Routing/GlobalEndpointManager.cs | 27 +++++++++++++++++- .../src/Routing/IGlobalEndpointManager.cs | 4 +++ .../src/Routing/LocationCache.cs | 28 +++++++++++++++++-- 9 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs diff --git a/Microsoft.Azure.Cosmos/src/AssemblyInfo.cs b/Microsoft.Azure.Cosmos/src/AssemblyInfo.cs index 97c216c0d5..6e78a4d416 100644 --- a/Microsoft.Azure.Cosmos/src/AssemblyInfo.cs +++ b/Microsoft.Azure.Cosmos/src/AssemblyInfo.cs @@ -5,6 +5,10 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyKeys.MoqPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection" + AssemblyKeys.ProductPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection" + AssemblyKeys.TestPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection.Tests" + AssemblyKeys.ProductPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection.Tests" + AssemblyKeys.TestPublicKey)] [assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends" + AssemblyKeys.ProductPublicKey)] [assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Friends" + AssemblyKeys.TestPublicKey)] [assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.Extensions" + AssemblyKeys.ProductPublicKey)] diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index a90a2e04a6..c49183e435 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -15,7 +15,7 @@ namespace Microsoft.Azure.Cosmos using System.Security.Cryptography.X509Certificates; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; - using Microsoft.Azure.Documents.Client; + using Microsoft.Azure.Documents.Client; using Newtonsoft.Json; /// @@ -732,7 +732,9 @@ internal Protocol ConnectionProtocol /// /// Gets or sets Client Telemetry Options like feature flags and corresponding options /// - public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + + internal IChaosInterceptorFactory ChaosInterceptorFactory { get; set; } internal void SetSerializerIfNotConfigured(CosmosSerializer serializer) { diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 8340df8207..f205815a5c 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -20,7 +20,6 @@ namespace Microsoft.Azure.Cosmos using global::Azure.Core; using Microsoft.Azure.Cosmos.Common; using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.Handler; using Microsoft.Azure.Cosmos.Query; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Microsoft.Azure.Cosmos.Routing; @@ -30,6 +29,7 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.FaultInjection; using Microsoft.Azure.Documents.Routing; using Newtonsoft.Json; @@ -115,6 +115,8 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider private readonly bool IsLocalQuorumConsistency = false; private readonly bool isReplicaAddressValidationEnabled; + private readonly IChaosInterceptor chaosInterceptor; + //Auth internal readonly AuthorizationTokenProvider cosmosAuthorization; @@ -433,6 +435,7 @@ internal DocumentClient(Uri serviceEndpoint, /// /// This delegate responsible for validating the third party certificate. /// This is distributed tracing flag + /// This is the chaos interceptor used for fault injection /// /// The service endpoint can be obtained from the Azure Management Portal. /// If you are connecting using one of the Master Keys, these can be obtained along with the endpoint from the Azure Management Portal @@ -460,7 +463,8 @@ internal DocumentClient(Uri serviceEndpoint, bool isLocalQuorumConsistency = false, string cosmosClientId = null, RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, - CosmosClientTelemetryOptions cosmosClientTelemetryOptions = null) + CosmosClientTelemetryOptions cosmosClientTelemetryOptions = null, + IChaosInterceptorFactory chaosInterceptorFactory = null) { if (sendingRequestEventArgs != null) { @@ -483,6 +487,7 @@ internal DocumentClient(Uri serviceEndpoint, this.transportClientHandlerFactory = transportClientHandlerFactory; this.IsLocalQuorumConsistency = isLocalQuorumConsistency; this.initTaskCache = new AsyncCacheNonBlocking(cancellationToken: this.cancellationTokenSource.Token); + this.chaosInterceptor = chaosInterceptorFactory?.CreateInterceptor(this); this.Initialize( serviceEndpoint: serviceEndpoint, @@ -6666,7 +6671,8 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory addressResolver: this.AddressResolver, rntbdMaxConcurrentOpeningConnectionCount: this.rntbdMaxConcurrentOpeningConnectionCount, remoteCertificateValidationCallback: this.remoteCertificateValidationCallback, - distributedTracingOptions: distributedTracingOptions); + distributedTracingOptions: distributedTracingOptions, + chaosInterceptor: this.chaosInterceptor); if (this.transportClientHandlerFactory != null) { diff --git a/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs new file mode 100644 index 0000000000..d87a9d25a0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs @@ -0,0 +1,20 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using Microsoft.Azure.Documents.FaultInjection; + + /// + /// This interface is used by the fault injection library to create an instance of IChaosInterceptor + /// This allows the fault injection library to intercept requests and inject faults in the request process + /// + internal interface IChaosInterceptorFactory + { + /// + /// Creates the IChaosInterceptor interceptor that will be used to inject fault injection rules. + /// + /// + public IChaosInterceptor CreateInterceptor(DocumentClient documentClient); + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 59325ecb83..5258987a35 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -658,6 +658,16 @@ internal CosmosClientBuilder WithPartitionLevelFailoverEnabled() return this; } + /// + /// Enables SDK to inject fault. Used for testing applications. + /// + /// + internal CosmosClientBuilder WithFaultInjection(IChaosInterceptorFactory chaosInterceptorFactory) + { + this.clientOptions.ChaosInterceptorFactory = chaosInterceptorFactory; + return this; + } + /// /// To enable LocalQuorum Consistency, i.e. Allows Quorum read with Eventual Consistency Account or with Consistent Prefix Account. /// Use By Compute Only diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index 5d5b66ee71..9d1b534c07 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -82,7 +82,8 @@ internal static CosmosClientContext Create( sessionContainer: clientOptions.SessionContainer, cosmosClientId: cosmosClient.Id, remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback), - cosmosClientTelemetryOptions: clientOptions.CosmosClientTelemetryOptions); + cosmosClientTelemetryOptions: clientOptions.CosmosClientTelemetryOptions, + chaosInterceptorFactory: clientOptions.ChaosInterceptorFactory); return ClientContextCore.Create( cosmosClient, diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index 64156f729e..15ac52bea0 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -362,7 +362,32 @@ public void Dispose() public virtual Uri ResolveServiceEndpoint(DocumentServiceRequest request) { return this.locationCache.ResolveServiceEndpoint(request); - } + } + + /// + /// Gets the default endpoint of the account + /// + /// the default endpoint. + public Uri GetDefaultEndpoint() + { + return this.locationCache.GetDefaultEndpoint(); + } + + /// + /// Gets the mapping of available write region names to the respective endpoints + /// + public ReadOnlyDictionary GetAvailableWriteEndpointsByLocation() + { + return this.locationCache.GetAvailableWriteEndpointsByLocation(); + } + + /// + /// Gets the mapping of available read region names to the respective endpoints + /// + public ReadOnlyDictionary GetAvailableReadEndpointsByLocation() + { + return this.locationCache.GetAvailableReadEndpointsByLocation(); + } /// /// Returns location corresponding to the endpoint diff --git a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs index 83f49cf0de..427bbb8d2d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs @@ -32,5 +32,9 @@ internal interface IGlobalEndpointManager : IDisposable void InitializeAccountPropertiesAndStartBackgroundRefresh(AccountProperties databaseAccount); Task RefreshLocationAsync(bool forceRefresh = false); + + ReadOnlyDictionary GetAvailableWriteEndpointsByLocation(); + + ReadOnlyDictionary GetAvailableReadEndpointsByLocation(); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs index 88a369bd2d..b6b2c3927d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs @@ -8,10 +8,7 @@ namespace Microsoft.Azure.Cosmos.Routing using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; - using System.Globalization; using System.Linq; - using System.Net; - using global::Azure.Core; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Documents; @@ -229,6 +226,31 @@ public bool IsMultimasterMetadataWriteRequest(DocumentServiceRequest request) } + /// + /// Gets the default endpoint of the account + /// + /// the default endpoint. + public Uri GetDefaultEndpoint() + { + return this.defaultEndpoint; + } + + /// + /// Gets the mapping of available write region names to the respective endpoints + /// + public ReadOnlyDictionary GetAvailableWriteEndpointsByLocation() + { + return this.locationInfo.AvailableWriteEndpointByLocation; + } + + /// + /// Gets the mapping of available read region names to the respective endpoints + /// + public ReadOnlyDictionary GetAvailableReadEndpointsByLocation() + { + return this.locationInfo.AvailableReadEndpointByLocation; + } + public Uri GetHubUri() { DatabaseAccountLocationsInfo currentLocationInfo = this.locationInfo; From 40647466e5798039f9e4a02d57d6da79d22a9e61 Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 16 Jan 2024 16:26:37 -0800 Subject: [PATCH 255/337] [Internal] Query: Adds ClientQL serialization support on the client (#4171) * Creating pipelines from Client Distribution Plan * Added DistributionPlanWriter * Added support for CqlSelectEnumerable * Added support for CqlArrayIndexerScalarExpression * Added support for literals * Added ScalarAsEnumerableExpression support * Modified comma code * Updated UserDefined Deserialization * Updated implementation for Undefined Literal * Updated baseline tests * Adds missing baseline file * Modified baseline tests to only show the client distribution plan instead of the whole distribution plan * Updated RemoveWhitespace() * Updated RemoveWhitespace() in ClientDistributionPlanBaselineTests * Removed dependencies on Newtonsoft --- .../ClientDistributionPlanDeserializer.cs | 12 +- .../Cql/CqlAggregate.cs | 2 + .../Cql/CqlAggregateEnumerableExpression.cs | 4 +- .../Cql/CqlArrayCreateScalarExpression.cs | 2 + .../Cql/CqlArrayIndexerScalarExpression.cs | 2 + .../Cql/CqlArrayLiteral.cs | 2 + .../Cql/CqlBinaryScalarExpression.cs | 2 + .../Cql/CqlBooleanLiteral.cs | 2 + .../Cql/CqlBuiltinAggregate.cs | 2 + .../Cql/CqlDistinctEnumerableExpression.cs | 2 + .../Cql/CqlEnumerableExpression.cs | 2 + .../Cql/CqlGroupByEnumerableExpression.cs | 2 + .../Cql/CqlInputEnumerableExpression.cs | 2 + .../Cql/CqlIsOperatorScalarExpression.cs | 2 + .../Cql/CqlLetScalarExpression.cs | 2 + .../ClientDistributionPlan/Cql/CqlLiteral.cs | 2 + .../Cql/CqlLiteralScalarExpression.cs | 2 + .../Cql/CqlMuxScalarExpression.cs | 2 + .../Cql/CqlNullLiteral.cs | 2 + .../Cql/CqlNumberLiteral.cs | 2 + .../Cql/CqlObjectCreateScalarExpression.cs | 2 + .../Cql/CqlObjectLiteral.cs | 2 + .../Cql/CqlOrderByEnumerableExpression.cs | 2 + .../Cql/CqlPropertyRefScalarExpression.cs | 2 + .../Cql/CqlScalarAsEnumerableExpression.cs | 2 + .../Cql/CqlScalarExpression.cs | 2 + .../Cql/CqlSelectEnumerableExpression.cs | 2 + .../Cql/CqlSelectManyEnumerableExpression.cs | 2 + .../Cql/CqlStringLiteral.cs | 2 + .../CqlSystemFunctionCallScalarExpression.cs | 2 + .../Cql/CqlTakeEnumerableExpression.cs | 2 + .../Cql/CqlTupleAggregate.cs | 2 + .../Cql/CqlTupleCreateScalarExpression.cs | 2 + .../Cql/CqlTupleItemRefScalarExpression.cs | 2 + .../Cql/CqlUnaryScalarExpression.cs | 2 + .../Cql/CqlUndefinedLiteral.cs | 2 + ...UserDefinedFunctionCallScalarExpression.cs | 2 + .../Cql/CqlVariableRefScalarExpression.cs | 2 + .../Cql/CqlWhereEnumerableExpression.cs | 2 + .../ClientDistributionPlan/ICqlVisitor.cs | 66 + ...misticDirectExecutionQueryPipelineStage.cs | 4 +- ...tClientDistributionPlanDeserialization.xml | 6828 +++++++++++++++-- .../ClientDistributionPlanBaselineTests.cs | 87 +- .../Query/DistributionPlanWriter.cs | 534 ++ .../DistributionPlans/Text/Complex_Query.json | 4148 ++++++++++ .../Text/Count_plus_five.json | 258 + .../Text/Distinct_with_where.json | 717 ++ .../Text/Multiple_Aggregates.json | 1689 ++++ ...able.json => Simple_Query_Enumerable.json} | 0 .../DistributionPlans/Text/UnaryScalar.json | 352 + .../Text/UserDefinedFunctionScalar.json | 357 + ...misticDirectExecutionQueryBaselineTests.cs | 12 +- 52 files changed, 14617 insertions(+), 525 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ICqlVisitor.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlanWriter.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Complex_Query.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Count_plus_five.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct_with_where.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Multiple_Aggregates.json rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/{SimpleEnumerable.json => Simple_Query_Enumerable.json} (100%) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UnaryScalar.json create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UserDefinedFunctionScalar.json diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs index df19b88b3d..caa71b2f35 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ClientDistributionPlanDeserializer.cs @@ -19,7 +19,7 @@ private static class Constants public const string Aggregate = "Aggregate"; public const string Aggregates = "Aggregates"; public const string Builtin = "Builtin"; - public const string Cql = "Cql"; + public const string ClientQL = "clientQL"; public const string ConditionExpression = "ConditionExpression"; public const string ClientDistributionPlan = "clientDistributionPlan"; public const string DeclaredVariable = "DeclaredVariable"; @@ -27,6 +27,7 @@ private static class Constants public const string Distinct = "Distinct"; public const string EnumerationKind = "EnumerationKind"; public const string Expression = "Expression"; + public const string Expressions = "Expressions"; public const string FunctionKind = "FunctionKind"; public const string GroupBy = "GroupBy"; public const string Identifier = "Identifier"; @@ -69,7 +70,7 @@ public static ClientDistributionPlan DeserializeClientDistributionPlan(string js { CosmosObject cosmosObject = CosmosObject.Parse(jsonString); CosmosObject clientDistributionPlanElement = GetValue(cosmosObject, Constants.ClientDistributionPlan); - CosmosObject cqlElement = GetValue(clientDistributionPlanElement, Constants.Cql); + CosmosObject cqlElement = GetValue(clientDistributionPlanElement, Constants.ClientQL); CqlEnumerableExpression expression = DeserializeCqlEnumerableExpression(cqlElement); return new ClientDistributionPlan(expression); @@ -118,7 +119,7 @@ private static CqlDistinctEnumerableExpression DeserializeDistinctEnumerableExpr { CqlEnumerableExpression sourceExpression = DeserializeCqlEnumerableExpression(GetValue(cosmosObject, Constants.SourceExpression)); CqlVariable declaredVariable = DeserializeCqlVariable(GetValue(cosmosObject, Constants.DeclaredVariable)); - IReadOnlyList expressions = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Expression)); + IReadOnlyList expressions = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Expressions)); return new CqlDistinctEnumerableExpression(sourceExpression, declaredVariable, expressions); } @@ -318,8 +319,9 @@ private static CqlUnaryScalarExpression DeserializeUnaryScalarExpression(CosmosO private static CqlUserDefinedFunctionCallScalarExpression DeserializeUserDefinedFunctionCallScalarExpression(CosmosObject cosmosObject) { - string identifierString = GetValue(cosmosObject, Constants.Identifier).Value; - CqlFunctionIdentifier functionIdentifier = new CqlFunctionIdentifier(identifierString); + CosmosObject identifier = GetValue(cosmosObject, Constants.Identifier); + string nameString = GetValue(identifier, Constants.Name).Value; + CqlFunctionIdentifier functionIdentifier = new CqlFunctionIdentifier(nameString); IReadOnlyList arguments = DeserializeScalarExpressionArray(GetValue(cosmosObject, Constants.Arguments)); bool builtin = GetValue(cosmosObject, Constants.Builtin).Value; return new CqlUserDefinedFunctionCallScalarExpression(functionIdentifier, arguments, builtin); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs index 3df9af326f..2535e3269d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregate.cs @@ -12,5 +12,7 @@ protected CqlAggregate(CqlAggregateKind kind) } public CqlAggregateKind Kind { get; } + + public abstract void Accept(ICqlVisitor cqlVisitor); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs index eb4a09a966..dd6430f468 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlAggregateEnumerableExpression.cs @@ -10,7 +10,7 @@ internal class CqlAggregateEnumerableExpression : CqlEnumerableExpression { public CqlAggregateEnumerableExpression(CqlEnumerableExpression sourceExpression, CqlAggregate aggregate) : base(CqlEnumerableExpressionKind.Aggregate) - { + { this.SourceExpression = sourceExpression ?? throw new ArgumentNullException(nameof(sourceExpression)); this.Aggregate = aggregate ?? throw new ArgumentNullException(nameof(aggregate)); } @@ -18,5 +18,7 @@ public CqlAggregateEnumerableExpression(CqlEnumerableExpression sourceExpression public CqlEnumerableExpression SourceExpression { get; } public CqlAggregate Aggregate { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs index 84b829179c..e213773cd8 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayCreateScalarExpression.cs @@ -21,5 +21,7 @@ public CqlArrayCreateScalarExpression(IReadOnlyList items) public string ArrayKind { get; } public IReadOnlyList Items { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs index 65d280a02e..f848213536 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayIndexerScalarExpression.cs @@ -18,5 +18,7 @@ public CqlArrayIndexerScalarExpression(CqlScalarExpression expression, ulong ind public CqlScalarExpression Expression { get; } public ulong Index { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs index a50036123d..c72269251b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlArrayLiteral.cs @@ -16,5 +16,7 @@ public CqlArrayLiteral(IReadOnlyList items) } public IReadOnlyList Items { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs index 9f3a382fd0..36cdbae2a5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBinaryScalarExpression.cs @@ -21,5 +21,7 @@ public CqlBinaryScalarExpression(CqlBinaryScalarOperatorKind operatorKind, CqlSc public CqlScalarExpression LeftExpression { get; } public CqlScalarExpression RightExpression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs index 06f06b4e64..b7c1f0d5ed 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBooleanLiteral.cs @@ -13,5 +13,7 @@ public CqlBooleanLiteral(bool value) } public bool Value { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs index 8dcebf5bb8..88e9f0de48 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlBuiltinAggregate.cs @@ -13,5 +13,7 @@ public CqlBuiltinAggregate(CqlAggregateOperatorKind operatorKind) } public CqlAggregateOperatorKind OperatorKind { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs index 8fa7515235..200299bd31 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlDistinctEnumerableExpression.cs @@ -22,5 +22,7 @@ public CqlDistinctEnumerableExpression(CqlEnumerableExpression sourceExpression, public CqlVariable DeclaredVariable { get; } public IReadOnlyList Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs index 7b30bdc629..6b544153eb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlEnumerableExpression.cs @@ -12,5 +12,7 @@ protected CqlEnumerableExpression(CqlEnumerableExpressionKind kind) } public CqlEnumerableExpressionKind Kind { get; } + + public abstract void Accept(ICqlVisitor cqlVisitor); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs index b3efe8cb5d..36c23af516 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlGroupByEnumerableExpression.cs @@ -22,5 +22,7 @@ public CqlGroupByEnumerableExpression(CqlEnumerableExpression sourceExpression, public ulong KeyCount { get; } public IReadOnlyList Aggregates { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs index a9a1ba8d6f..f17f136ca2 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlInputEnumerableExpression.cs @@ -15,5 +15,7 @@ public CqlInputEnumerableExpression(string name) } public string Name { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs index c1aa03907d..c606c6f6eb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlIsOperatorScalarExpression.cs @@ -19,5 +19,7 @@ public CqlIsOperatorScalarExpression(CqlIsOperatorKind operatorKind, CqlScalarEx public CqlIsOperatorKind OperatorKind { get; } public CqlScalarExpression Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs index 329e2f36cd..3b5e4c2427 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLetScalarExpression.cs @@ -21,5 +21,7 @@ public CqlLetScalarExpression(CqlVariable declaredVariable, CqlScalarExpression public CqlScalarExpression DeclaredVariableExpression { get; } public CqlScalarExpression Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs index d5b17b06ac..277f2f9bd7 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteral.cs @@ -12,5 +12,7 @@ protected CqlLiteral(CqlLiteralKind kind) } public CqlLiteralKind Kind { get; } + + public abstract void Accept(ICqlVisitor cqlVisitor); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs index ebc82d9048..edac3ae5b2 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlLiteralScalarExpression.cs @@ -15,5 +15,7 @@ public CqlLiteralScalarExpression(CqlLiteral literal) } public CqlLiteral Literal { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs index 0ebb3cab53..42200c2626 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlMuxScalarExpression.cs @@ -21,5 +21,7 @@ public CqlMuxScalarExpression(CqlScalarExpression conditionExpression, CqlScalar public CqlScalarExpression LeftExpression { get; } public CqlScalarExpression RightExpression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs index 53696840b1..f89a1b68b5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNullLiteral.cs @@ -12,5 +12,7 @@ private CqlNullLiteral() : base(CqlLiteralKind.Null) { } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs index 28769462d7..e0aa1d929d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlNumberLiteral.cs @@ -15,5 +15,7 @@ public CqlNumberLiteral(Number64 value) } public Number64 Value { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs index 1bcd44e106..9c2676f9d5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectCreateScalarExpression.cs @@ -21,5 +21,7 @@ public CqlObjectCreateScalarExpression(IReadOnlyList properti public IReadOnlyList Properties { get; } public string ObjectKind { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs index e5ba8ff343..28d15dfa50 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlObjectLiteral.cs @@ -16,5 +16,7 @@ public CqlObjectLiteral(IReadOnlyList properties) } public IReadOnlyList Properties { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs index b4b9603841..21298bb1a5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlOrderByEnumerableExpression.cs @@ -22,5 +22,7 @@ public CqlOrderByEnumerableExpression(CqlEnumerableExpression sourceExpression, public CqlVariable DeclaredVariable { get; } public IReadOnlyList Items { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs index e93a31fe3e..e7e2cff74d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlPropertyRefScalarExpression.cs @@ -19,5 +19,7 @@ public CqlPropertyRefScalarExpression(CqlScalarExpression expression, string pro public CqlScalarExpression Expression { get; } public string PropertyName { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs index 0d69d8b424..74aee3ca25 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarAsEnumerableExpression.cs @@ -18,5 +18,7 @@ public CqlScalarAsEnumerableExpression(CqlScalarExpression expression, CqlEnumer public CqlScalarExpression Expression { get; } public CqlEnumerationKind EnumerationKind { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs index 659bdc5f58..b42f06874d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlScalarExpression.cs @@ -12,5 +12,7 @@ protected CqlScalarExpression(CqlScalarExpressionKind kind) } public CqlScalarExpressionKind Kind { get; } + + public abstract void Accept(ICqlVisitor cqlVisitor); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs index 0d052e980b..922576621f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectEnumerableExpression.cs @@ -21,5 +21,7 @@ public CqlSelectEnumerableExpression(CqlEnumerableExpression sourceExpression, C public CqlVariable DeclaredVariable { get; } public CqlScalarExpression Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs index e34d4ba874..e3f4af6fa9 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSelectManyEnumerableExpression.cs @@ -21,5 +21,7 @@ public CqlSelectManyEnumerableExpression(CqlEnumerableExpression sourceExpressio public CqlVariable DeclaredVariable { get; } public CqlEnumerableExpression SelectorExpression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs index a20947b0dd..2167b11bd3 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlStringLiteral.cs @@ -15,5 +15,7 @@ public CqlStringLiteral(string value) } public string Value { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs index d42ee09f15..71a98ca735 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlSystemFunctionCallScalarExpression.cs @@ -19,5 +19,7 @@ public CqlSystemFunctionCallScalarExpression(CqlBuiltinScalarFunctionKind functi public CqlBuiltinScalarFunctionKind FunctionKind { get; } public IReadOnlyList Arguments { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs index 0391db64fd..ffccde14a9 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTakeEnumerableExpression.cs @@ -21,5 +21,7 @@ public CqlTakeEnumerableExpression(CqlEnumerableExpression sourceExpression, ulo public ulong SkipValue { get; } public ulong TakeValue { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs index 6f553c1ec8..31f090addf 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleAggregate.cs @@ -16,5 +16,7 @@ public CqlTupleAggregate(IReadOnlyList items) } public IReadOnlyList Items { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs index 0c30e79d33..fdfb1ecc4b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleCreateScalarExpression.cs @@ -16,5 +16,7 @@ public CqlTupleCreateScalarExpression(IReadOnlyList items) } public IReadOnlyList Items { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs index bc011cecf7..786fc46f03 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlTupleItemRefScalarExpression.cs @@ -18,5 +18,7 @@ public CqlTupleItemRefScalarExpression(CqlScalarExpression expression, ulong ind public CqlScalarExpression Expression { get; } public ulong Index { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs index 8131ea618d..dd6a1cccc1 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUnaryScalarExpression.cs @@ -18,5 +18,7 @@ public CqlUnaryScalarExpression(CqlUnaryScalarOperatorKind operatorKind, CqlScal public CqlUnaryScalarOperatorKind OperatorKind { get; } public CqlScalarExpression Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs index ecc8d556b2..c4b0cf3e9b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUndefinedLiteral.cs @@ -12,5 +12,7 @@ private CqlUndefinedLiteral() : base(CqlLiteralKind.Undefined) { } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs index fda301a6a1..0bf70f291f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlUserDefinedFunctionCallScalarExpression.cs @@ -22,5 +22,7 @@ public CqlUserDefinedFunctionCallScalarExpression(CqlFunctionIdentifier identifi public IReadOnlyList Arguments { get; } public bool Builtin { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs index a909fb39a1..39885b9001 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlVariableRefScalarExpression.cs @@ -15,5 +15,7 @@ public CqlVariableRefScalarExpression(CqlVariable variable) } public CqlVariable Variable { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs index 3f6db64aa2..1a3af07ca7 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/Cql/CqlWhereEnumerableExpression.cs @@ -21,5 +21,7 @@ public CqlWhereEnumerableExpression(CqlEnumerableExpression sourceExpression, Cq public CqlVariable DeclaredVariable { get; } public CqlScalarExpression Expression { get; } + + public override void Accept(ICqlVisitor cqlVisitor) => cqlVisitor.Visit(this); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ICqlVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ICqlVisitor.cs new file mode 100644 index 0000000000..a20d564caa --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/ClientDistributionPlan/ICqlVisitor.cs @@ -0,0 +1,66 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan +{ + using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql; + + internal interface ICqlVisitor + { + void Visit(CqlAggregate cqlAggregate); + void Visit(CqlAggregateEnumerableExpression cqlAggregateEnumerableExpression); + void Visit(CqlAggregateKind cqlAggregateKind); + void Visit(CqlAggregateOperatorKind cqlAggregateOperatorKind); + void Visit(CqlArrayCreateScalarExpression cqlArrayCreateScalarExpression); + void Visit(CqlArrayIndexerScalarExpression cqlArrayIndexerScalarExpression); + void Visit(CqlArrayLiteral cqlArrayLiteral); + void Visit(CqlBinaryScalarExpression cqlBinaryScalarExpression); + void Visit(CqlBinaryScalarOperatorKind cqlBinaryScalarOperatorKind); + void Visit(CqlBooleanLiteral cqlBooleanLiteral); + void Visit(CqlBuiltinAggregate cqlBuiltinAggregate); + void Visit(CqlBuiltinScalarFunctionKind cqlBuiltinScalarFunctionKind); + void Visit(CqlDistinctEnumerableExpression cqlDistinctEnumerableExpression); + void Visit(CqlEnumerableExpression cqlEnumerableExpression); + void Visit(CqlEnumerableExpressionKind cqlEnumerableExpressionKind); + void Visit(CqlEnumerationKind cqlEnumerationKind); + void Visit(CqlFunctionIdentifier cqlFunctionIdentifier); + void Visit(CqlGroupByEnumerableExpression cqlGroupByEnumerableExpression); + void Visit(CqlInputEnumerableExpression cqlInputEnumerableExpression); + void Visit(CqlIsOperatorKind cqlIsOperatorKind); + void Visit(CqlIsOperatorScalarExpression cqlIsOperatorScalarExpression); + void Visit(CqlLetScalarExpression cqlLetScalarExpression); + void Visit(CqlLiteral cqlLiteral); + void Visit(CqlLiteralKind cqlLiteralKind); + void Visit(CqlLiteralScalarExpression cqlLiteralScalarExpression); + void Visit(CqlMuxScalarExpression cqlMuxScalarExpression); + void Visit(CqlNullLiteral cqlNullLiteral); + void Visit(CqlNumberLiteral cqlNumberLiteral); + void Visit(CqlObjectCreateScalarExpression cqlObjectCreateScalarExpression); + void Visit(CqlObjectLiteral cqlObjectLiteral); + void Visit(CqlObjectLiteralProperty cqlObjectLiteralProperty); + void Visit(CqlObjectProperty cqlObjectProperty); + void Visit(CqlOrderByEnumerableExpression cqlOrderByEnumerableExpression); + void Visit(CqlOrderByItem cqlOrderByItem); + void Visit(CqlPropertyRefScalarExpression cqlPropertyRefScalarExpression); + void Visit(CqlScalarAsEnumerableExpression cqlScalarAsEnumerableExpression); + void Visit(CqlScalarExpression cqlScalarExpression); + void Visit(CqlScalarExpressionKind cqlScalarExpressionKind); + void Visit(CqlSelectEnumerableExpression cqlSelectEnumerableExpression); + void Visit(CqlSelectManyEnumerableExpression cqlSelectManyEnumerableExpression); + void Visit(CqlSortOrder cqlSortOrder); + void Visit(CqlStringLiteral cqlStringLiteral); + void Visit(CqlSystemFunctionCallScalarExpression cqlSystemFunctionCallScalarExpression); + void Visit(CqlTakeEnumerableExpression cqlTakeEnumerableExpression); + void Visit(CqlTupleAggregate cqlTupleAggregate); + void Visit(CqlTupleCreateScalarExpression cqlTupleCreateScalarExpression); + void Visit(CqlTupleItemRefScalarExpression cqlTupleItemRefScalarExpression); + void Visit(CqlUnaryScalarExpression cqlUnaryScalarExpression); + void Visit(CqlUnaryScalarOperatorKind cqlUnaryScalarOperatorKind); + void Visit(CqlUndefinedLiteral cqlUndefinedLiteral); + void Visit(CqlUserDefinedFunctionCallScalarExpression cqlUserDefinedFunctionCallScalarExpression); + void Visit(CqlVariable cqlVariable); + void Visit(CqlVariableRefScalarExpression cqlVariableRefScalarExpression); + void Visit(CqlWhereEnumerableExpression cqlWhereEnumerableExpression); + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index c968c0b34f..7e571d0a41 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -82,13 +82,15 @@ public async ValueTask MoveNextAsync(ITrace trace) if (this.previousRequiresDistribution.HasValue && this.previousRequiresDistribution != requiresDistribution) { - // We should never enter this if statement as requiresDistribution flag can never switch mid execution. + // We should never come here as requiresDistribution flag can never switch mid execution. // Hence, this exception should never be thrown. throw new InvalidOperationException($"Unexpected switch in {HttpConstants.HttpHeaders.RequiresDistribution} value. Previous value : {this.previousRequiresDistribution} Current value : {requiresDistribution}."); } if (requiresDistribution) { + // This is where we will unwrap tne continuation token and extract the client distribution plan + // Pipelines to handle client distribution would be generated here success = await this.SwitchToFallbackPipelineAsync(continuationToken: null, trace); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml index c59b58aef1..3f122ecd8b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ClientDistributionPlanBaselineTests.TestClientDistributionPlanDeserialization.xml @@ -1,606 +1,6488 @@  - Input Expression - {"clientDistributionPlan": {"Cql": {"Kind": "Input","Name": "root"}}} - - - { - "Cql": { - "Name": "root", - "Kind": 3 - } -} - - - - - Aggregate and ObjectCreate Expressions - {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a","Expression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6}}}]},"SourceExpression": {"Kind": "Aggregate","Aggregate": {"Kind": "Builtin","OperatorKind": "Sum"},"SourceExpression": {"Kind": "Input","Name": "root"}}}}} - - - { - "Cql": { - "SourceExpression": { - "SourceExpression": { - "Name": "root", - "Kind": 3 - }, - "Aggregate": { - "OperatorKind": 8, - "Kind": 0 - }, - "Kind": 0 - }, - "DeclaredVariable": { - "Name": "v0", - "UniqueId": 6 - }, - "Expression": { - "Properties": [ - { - "Name": "count_a", - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 6 - }, - "Kind": 14 - } - } - ], - "ObjectKind": "Object", - "Kind": 7 - }, - "Kind": 6 - } -} - - - - - Select, Aggregate and BinaryOperator Expressions - {"clientDistributionPlan": {"Cql": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 10 }, "Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [ {"Name": "F1","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "FieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "FieldSum", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 1 }},{ "Name": "FieldAvg", "Expression": {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "Equal", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }, "RightExpression": {"Kind": "Literal","Literal": { "Kind": "Number", "Value": 0} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Undefined" }},"RightExpression": { "Kind": "BinaryOperator", "OperatorKind": "Divide", "LeftExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 0 }, "RightExpression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 10} }, "Index": 2},"Index": 1 }}}}]}}, {"Name": "F2","Expression": { "Kind": "ObjectCreate", "ObjectKind": "Object", "Properties": [{ "Name": "OtherFieldA", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 0 }},{ "Name": "OtherFieldMax", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 10 }},"Index": 3 }} ]} }] }, "SourceExpression": {"Kind": "GroupBy","KeyCount": 1,"Aggregates": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Tuple","Items": [ {"Kind": "Builtin","OperatorKind": "Sum" }, {"Kind": "Builtin","OperatorKind": "Sum" }] }, {"Kind": "Builtin","OperatorKind": "Max" }],"SourceExpression": { "Kind": "Select", "DeclaredVariable": {"Name": "v0","UniqueId": 16 }, "Expression": {"Kind": "TupleCreate","Items": [ {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 0 }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 1 }, "Index": 0} }, {"Kind": "TupleCreate","Items": [ {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 0 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 2 }, "Index": 0} }, {"Kind": "TupleItemRef","Expression": { "Kind": "TupleItemRef", "Expression": {"Kind": "VariableRef","Variable": { "Name": "v0", "UniqueId": 16} }, "Index": 2},"Index": 1 }] }, {"Kind": "Mux","ConditionExpression": { "Kind": "BinaryOperator", "OperatorKind": "And", "LeftExpression": {"Kind": "BinaryOperator","OperatorKind": "NotEqual","LeftExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 1},"RightExpression": { "Kind": "Literal", "Literal": {"Kind": "Number","Value": 0 }} }, "RightExpression": {"Kind": "UnaryOperator","OperatorKind": "Not","Expression": { "Kind": "SystemFunctionCall", "FunctionKind": "Is_Defined", "Arguments": [{ "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16 }},"Index": 3 }, "Index": 0} ]} }},"LeftExpression": { "Kind": "Literal", "Literal": {"Kind": "Array","Items": [] }},"RightExpression": { "Kind": "TupleItemRef", "Expression": {"Kind": "TupleItemRef","Expression": { "Kind": "VariableRef", "Variable": {"Name": "v0","UniqueId": 16}},"Index": 3}, "Index": 0}}]}, "SourceExpression": {"Kind": "Input","Name": "root"}}}}}} - - - { - "Cql": { - "SourceExpression": { - "SourceExpression": { - "SourceExpression": { - "Name": "root", - "Kind": 3 - }, + AggregateEnumerable.json + { + "clientQL": { + "Kind": "Select", "DeclaredVariable": { "Name": "v0", - "UniqueId": 16 + "UniqueId": 2 }, "Expression": { - "Items": [ + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ { + "Name": "$1", "Expression": { + "Kind": "VariableRef", "Variable": { "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 0, - "Kind": 11 + "UniqueId": 2 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 }, - { + "Expression": { + "Kind": "Mux", "ConditionExpression": { - "OperatorKind": 1, + "Kind": "BinaryOperator", + "OperatorKind": "And", "LeftExpression": { - "OperatorKind": 14, + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", "LeftExpression": { + "Kind": "TupleItemRef", "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 1, - "Kind": 11 + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, - "Index": 1, - "Kind": 11 + "Index": 1 }, "RightExpression": { + "Kind": "Literal", "Literal": { - "Value": 0, - "Kind": 4 - }, - "Kind": 5 - }, - "Kind": 2 + "Kind": "Number", + "Value": 0 + } + } }, "RightExpression": { - "OperatorKind": 2, + "Kind": "UnaryOperator", + "OperatorKind": "Not", "Expression": { - "FunctionKind": 55, + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", "Arguments": [ { + "Kind": "TupleItemRef", "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 1, - "Kind": 11 + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, - "Index": 0, - "Kind": 11 + "Index": 0 } - ], - "Kind": 9 - }, - "Kind": 12 - }, - "Kind": 2 + ] + } + } }, "LeftExpression": { + "Kind": "Literal", "Literal": { - "Items": [], - "Kind": 1 - }, - "Kind": 5 + "Kind": "Array", + "Items": [] + } }, "RightExpression": { + "Kind": "TupleItemRef", "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 1, - "Kind": 11 + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, - "Index": 0, - "Kind": 11 - }, - "Kind": 6 + "Index": 0 + } }, - { - "Items": [ - { - "ConditionExpression": { - "OperatorKind": 1, - "LeftExpression": { - "OperatorKind": 14, - "LeftExpression": { - "Expression": { - "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 2, - "Kind": 11 - }, - "Index": 0, - "Kind": 11 - }, - "Index": 1, - "Kind": 11 - }, - "RightExpression": { - "Literal": { - "Value": 0, - "Kind": 4 - }, - "Kind": 5 - }, - "Kind": 2 - }, - "RightExpression": { - "OperatorKind": 2, - "Expression": { - "FunctionKind": 55, - "Arguments": [ - { - "Expression": { - "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 2, - "Kind": 11 - }, - "Index": 0, - "Kind": 11 - }, - "Index": 0, - "Kind": 11 - } - ], - "Kind": 9 - }, - "Kind": 12 - }, - "Kind": 2 - }, - "LeftExpression": { - "Literal": { - "Items": [], - "Kind": 1 - }, - "Kind": 5 - }, - "RightExpression": { + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "VariableRef", "Variable": { "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 + "UniqueId": 7 + } }, - "Index": 2, - "Kind": 11 + "Index": 0 }, - "Index": 0, - "Kind": 11 + "Index": 0 }, - "Kind": 6 - }, - { - "Expression": { + { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "VariableRef", "Variable": { "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 2, - "Kind": 11 - }, - "Index": 1, - "Kind": 11 - } - ], - "Kind": 10 - }, - { - "ConditionExpression": { - "OperatorKind": 1, - "LeftExpression": { - "OperatorKind": 14, - "LeftExpression": { - "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 3, - "Kind": 11 - }, - "Index": 1, - "Kind": 11 - }, - "RightExpression": { - "Literal": { - "Value": 0, - "Kind": 4 - }, - "Kind": 5 - }, - "Kind": 2 - }, - "RightExpression": { - "OperatorKind": 2, - "Expression": { - "FunctionKind": 55, - "Arguments": [ - { - "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 - }, - "Kind": 14 - }, - "Index": 3, - "Kind": 11 - }, - "Index": 0, - "Kind": 11 + "UniqueId": 7 } - ], - "Kind": 9 - }, - "Kind": 12 - }, - "Kind": 2 - }, - "LeftExpression": { - "Literal": { - "Items": [], - "Kind": 1 - }, - "Kind": 5 - }, - "RightExpression": { - "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 16 }, - "Kind": 14 - }, - "Index": 3, - "Kind": 11 - }, - "Index": 0, - "Kind": 11 + "Index": 1 + } + ] }, - "Kind": 6 - } - ], - "Kind": 10 - }, - "Kind": 6 - }, - "KeyCount": 1, - "Aggregates": [ - { - "OperatorKind": 8, - "Kind": 0 - }, - { - "Items": [ - { - "OperatorKind": 8, - "Kind": 0 - }, - { - "OperatorKind": 8, - "Kind": 0 + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } } - ], - "Kind": 1 - }, - { - "OperatorKind": 6, - "Kind": 0 + } } - ], - "Kind": 2 - }, + } + } + + + { + "clientQL": { + "Kind": "Select", "DeclaredVariable": { "Name": "v0", - "UniqueId": 10 + "UniqueId": 2 }, "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", "Properties": [ { - "Name": "F1", + "Name": "$1", "Expression": { - "Properties": [ - { - "Name": "FieldA", + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 10 - }, - "Kind": 14 - }, - "Index": 0, - "Kind": 11 - } + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + } + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ { - "Name": "FieldSum", + "Kind": "ArrayIndexer", "Expression": { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "VariableRef", "Variable": { "Name": "v0", - "UniqueId": 10 - }, - "Kind": 14 + "UniqueId": 7 + } }, - "Index": 1, - "Kind": 11 - } + "Index": 0 + }, + "Index": 0 }, { - "Name": "FieldAvg", + "Kind": "ArrayIndexer", "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 1 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + ArrayCreateScalar.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "arr", + "Expression": { + "Kind": "ArrayCreate", + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ] + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "arr", + "Expression": { + "Kind": "ArrayCreate", + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ] + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } +} + + + + + BinaryScalar.json + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + Complex_Query.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 69 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 2 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 0 + } + }, + { + "Name": "b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 1 + } + }, + { + "Name": "d", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 4 + } + }, + { + "Name": "avg_c", + "Expression": { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Undefined" + } + }, + "RightExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Divide", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 36 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 67 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 67 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Array" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 64 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 7 + } + }, + { + "Name": "min", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 8 + } + }, + { + "Name": "max", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 9 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 4 + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 58 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 62 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 7 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 8 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 62 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 60 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 60 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 52 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 56 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 7 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 56 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Min" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 54 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 54 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 46 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 50 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 6 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 50 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 48 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 39 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 5 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Any" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a2", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 425 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 38 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 38 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + } + ] + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 2, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 76 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 1 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 75 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 3 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 4 + } + ] + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 5 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 69 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 2 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 0 + } + }, + { + "Name": "b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 1 + } + }, + { + "Name": "d", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 4 + } + }, + { + "Name": "avg_c", + "Expression": { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Undefined" + } + }, + "RightExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Divide", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 36 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 67 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 67 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Array" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 64 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 7 + } + }, + { + "Name": "min", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 8 + } + }, + { + "Name": "max", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 9 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 4 + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 58 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 62 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 7 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 8 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 62 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 60 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 60 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 52 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 56 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 7 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 56 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Min" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 54 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 54 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 46 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 50 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 6 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 50 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 48 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 39 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 5 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Any" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a2", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 425 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 38 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 38 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + } + ] + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 2, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 76 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 1 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 75 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 3 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 4 + } + ] + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 5 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } +} + + + + + Count_plus_five.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count_a_plus_five", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Add", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count_a_plus_five", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Add", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } +} + + + + + Distinct-SelectEnumerable.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } +} + + + + + Distinct_with_where.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "FirstName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + } + }, + { + "Name": "LastName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "FirstName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + } + }, + { + "Name": "LastName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } +} + + + + + GroupByEnumerable.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "$1", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 1, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Max" + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 9 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 0 + }, + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 2 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "$1", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 1, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Max" + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 9 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 0 + }, + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 9 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 2 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + LiteralScalar.json + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "EqualsFive", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "EqualsFive", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + Multiple_Aggregates.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "sum_a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "sum_b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "Mux", "ConditionExpression": { - "OperatorKind": 6, + "Kind": "BinaryOperator", + "OperatorKind": "And", "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 1 + } + ] + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 2 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 3 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "sum_a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "sum_b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 10 + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, - "Kind": 14 + "Index": 0 }, - "Index": 2, - "Kind": 11 - }, - "Index": 1, - "Kind": 11 - }, - "RightExpression": { - "Literal": { - "Value": 0, - "Kind": 4 - }, - "Kind": 5 - }, - "Kind": 2 + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", "LeftExpression": { - "Literal": { - "Kind": 0 + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 }, - "Kind": 5 + "Index": 1 }, "RightExpression": { - "OperatorKind": 5, - "LeftExpression": { - "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 10 + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } }, - "Kind": 14 + "Index": 1 }, - "Index": 2, - "Kind": 11 + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } }, - "Index": 0, - "Kind": 11 + "Index": 0 }, - "RightExpression": { + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 1 + } + ] + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", "Expression": { - "Expression": { - "Variable": { - "Name": "v0", - "UniqueId": 10 - }, - "Kind": 14 - }, - "Index": 2, - "Kind": 11 + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } }, - "Index": 1, - "Kind": 11 + "Index": 2 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } }, - "Kind": 2 + "Index": 3 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + SelectManyEnumerable.json + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 16 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "s", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 16 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "SelectorExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 9 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 19 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 19 + } }, - "Kind": 6 + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 16 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "s", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 16 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "SelectorExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 9 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 9 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 19 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 19 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + Simple_Query_Enumerable.json + { + "clientQL": { + "Kind": "Input", + "Name": "root" + } + } + + + { + "clientQL": { + "Kind": "Input", + "Name": "root" + } +} + + + + + SystemFunctionCallScalar.json + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Integer", + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ] + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 } } ], - "ObjectKind": "Object", - "Kind": 7 + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Integer", + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ] + } } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 }, - { - "Name": "F2", + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + TakeEnumerable.json + { + "clientQL": { + "Kind": "Take", + "SkipValue": 2, + "TakeValue": 5, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", "Properties": [ { - "Name": "OtherFieldA", + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "ArrayIndexer", "Expression": { + "Kind": "VariableRef", "Variable": { "Name": "v0", - "UniqueId": 10 - }, - "Kind": 14 + "UniqueId": 7 + } }, - "Index": 0, - "Kind": 11 + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + + + { + "clientQL": { + "Kind": "Take", + "SkipValue": 2, + "TakeValue": 5, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 4 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 4 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 } }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} + + + + + UnaryScalar.json + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ { - "Name": "OtherFieldMax", + "Name": "$1", "Expression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", "Expression": { + "Kind": "VariableRef", "Variable": { - "Name": "v0", - "UniqueId": 10 - }, - "Kind": 14 - }, - "Index": 3, - "Kind": 11 + "Name": "s0", + "UniqueId": 3 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 } } ], - "ObjectKind": "Object", - "Kind": 7 + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } } } - ], - "ObjectKind": "Object", - "Kind": 7 + } + } + + + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 }, - "Kind": 6 + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } } -} +} - Select, Sum and VariableRef Expressions - {"clientDistributionPlan": {"Cql": {"Kind": "Select","DeclaredVariable": {"Name": "v0","UniqueId": 6},"Expression": {"Kind": "ObjectCreate","ObjectKind": "Object","Properties": [{"Name": "count_a_plus_five","Expression": {"Kind": "BinaryOperator","OperatorKind": "Add","LeftExpression": {"Kind": "VariableRef","Variable": {"Name": "v0","UniqueId": 6 }}, "RightExpression": { "Kind": "Literal", "Literal": { "Kind": "Number", "Value": 5 }}}}]}, "SourceExpression": { "Kind": "Aggregate", "Aggregate": { "Kind": "Builtin", "OperatorKind": "Sum" }, "SourceExpression": { "Kind": "Input", "Name": "root" }}}}} + UserDefinedFunctionScalar.json + { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "aUpper", + "Expression": { + "Kind": "UserDefinedFunctionCall", + "Identifier": { + "Name": "toUpper" + }, + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "Builtin": false + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } - { - "Cql": { - "SourceExpression": { - "SourceExpression": { - "Name": "root", - "Kind": 3 - }, - "Aggregate": { - "OperatorKind": 8, - "Kind": 0 - }, - "Kind": 0 - }, + { + "clientQL": { + "Kind": "Distinct", "DeclaredVariable": { "Name": "v0", - "UniqueId": 6 + "UniqueId": 1 }, - "Expression": { - "Properties": [ - { - "Name": "count_a_plus_five", - "Expression": { - "OperatorKind": 0, - "LeftExpression": { - "Variable": { - "Name": "v0", - "UniqueId": 6 + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "aUpper", + "Expression": { + "Kind": "UserDefinedFunctionCall", + "Identifier": { + "Name": "toUpper" }, - "Kind": 14 - }, - "RightExpression": { - "Literal": { - "Value": 5, - "Kind": 4 + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "Builtin": false + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } }, - "Kind": 5 + "Index": 0 }, - "Kind": 2 + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" } } - ], - "ObjectKind": "Object", - "Kind": 7 - }, - "Kind": 6 + } + } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs index 845f71d25e..96d5906ae9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ClientDistributionPlanBaselineTests.cs @@ -1,13 +1,13 @@ namespace Microsoft.Azure.Cosmos.Tests.Query { using System.Collections.Generic; + using System.IO; + using System.Text.Json; using System.Xml; using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan; using Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan.Cql; using Microsoft.Azure.Cosmos.Test.BaselineTest; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; [TestClass] public class ClientDistributionPlanBaselineTests : BaselineTests @@ -16,84 +16,93 @@ public class ClientDistributionPlanBaselineTests : BaselineTests testVariations = new List + List testVariations = new List(); + string textPath = "../../../Query/DistributionPlans/Text"; + string[] filePaths = Directory.GetFiles(textPath); + + foreach (string filePath in filePaths) { - CreateInput( - description: @"Input Expression", - clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}"), + string testResponse = File.ReadAllText(filePath); + JsonDocument jsonDocument = JsonDocument.Parse(testResponse); - CreateInput( - description: @"Aggregate and ObjectCreate Expressions", - clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a\",\"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6}}}]},\"SourceExpression\": {\"Kind\": \"Aggregate\",\"Aggregate\": {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\"},\"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}"), + JsonElement root = jsonDocument.RootElement; + JsonElement distributionPlanElement = root.GetProperty("_distributionPlan"); + string expectedDistributionPlan = distributionPlanElement.ToString(); - CreateInput( - description: @"Select, Aggregate and BinaryOperator Expressions", - clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 10 }, \"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [ {\"Name\": \"F1\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"FieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"FieldSum\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 1 }},{ \"Name\": \"FieldAvg\", \"Expression\": {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Equal\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }, \"RightExpression\": {\"Kind\": \"Literal\",\"Literal\": { \"Kind\": \"Number\", \"Value\": 0} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Undefined\" }},\"RightExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"Divide\", \"LeftExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 0 }, \"RightExpression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 10} }, \"Index\": 2},\"Index\": 1 }}}}]}}, {\"Name\": \"F2\",\"Expression\": { \"Kind\": \"ObjectCreate\", \"ObjectKind\": \"Object\", \"Properties\": [{ \"Name\": \"OtherFieldA\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 0 }},{ \"Name\": \"OtherFieldMax\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 10 }},\"Index\": 3 }} ]} }] }, \"SourceExpression\": {\"Kind\": \"GroupBy\",\"KeyCount\": 1,\"Aggregates\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Tuple\",\"Items\": [ {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Sum\" }] }, {\"Kind\": \"Builtin\",\"OperatorKind\": \"Max\" }],\"SourceExpression\": { \"Kind\": \"Select\", \"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 16 }, \"Expression\": {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 0 }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 1 }, \"Index\": 0} }, {\"Kind\": \"TupleCreate\",\"Items\": [ {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 0 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 2 }, \"Index\": 0} }, {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"VariableRef\",\"Variable\": { \"Name\": \"v0\", \"UniqueId\": 16} }, \"Index\": 2},\"Index\": 1 }] }, {\"Kind\": \"Mux\",\"ConditionExpression\": { \"Kind\": \"BinaryOperator\", \"OperatorKind\": \"And\", \"LeftExpression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"NotEqual\",\"LeftExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 1},\"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Number\",\"Value\": 0 }} }, \"RightExpression\": {\"Kind\": \"UnaryOperator\",\"OperatorKind\": \"Not\",\"Expression\": { \"Kind\": \"SystemFunctionCall\", \"FunctionKind\": \"Is_Defined\", \"Arguments\": [{ \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16 }},\"Index\": 3 }, \"Index\": 0} ]} }},\"LeftExpression\": { \"Kind\": \"Literal\", \"Literal\": {\"Kind\": \"Array\",\"Items\": [] }},\"RightExpression\": { \"Kind\": \"TupleItemRef\", \"Expression\": {\"Kind\": \"TupleItemRef\",\"Expression\": { \"Kind\": \"VariableRef\", \"Variable\": {\"Name\": \"v0\",\"UniqueId\": 16}},\"Index\": 3}, \"Index\": 0}}]}, \"SourceExpression\": {\"Kind\": \"Input\",\"Name\": \"root\"}}}}}}"), + string fileName = Path.GetFileName(filePath); - CreateInput( - description: @"Select, Sum and VariableRef Expressions", - clientPlanJson: "{\"clientDistributionPlan\": {\"Cql\": {\"Kind\": \"Select\",\"DeclaredVariable\": {\"Name\": \"v0\",\"UniqueId\": 6},\"Expression\": {\"Kind\": \"ObjectCreate\",\"ObjectKind\": \"Object\",\"Properties\": [{\"Name\": \"count_a_plus_five\",\"Expression\": {\"Kind\": \"BinaryOperator\",\"OperatorKind\": \"Add\",\"LeftExpression\": {\"Kind\": \"VariableRef\",\"Variable\": {\"Name\": \"v0\",\"UniqueId\": 6 }}, \"RightExpression\": { \"Kind\": \"Literal\", \"Literal\": { \"Kind\": \"Number\", \"Value\": 5 }}}}]}, \"SourceExpression\": { \"Kind\": \"Aggregate\", \"Aggregate\": { \"Kind\": \"Builtin\", \"OperatorKind\": \"Sum\" }, \"SourceExpression\": { \"Kind\": \"Input\", \"Name\": \"root\" }}}}}"), - }; + testVariations.Add( + CreateInput( + description: fileName, + distributionPlanJson: expectedDistributionPlan)); + } this.ExecuteTestSuite(testVariations); } - private static ClientDistributionPlanTestInput CreateInput( string description, - string clientPlanJson) + string distributionPlanJson) { - return new ClientDistributionPlanTestInput(description, clientPlanJson); + return new ClientDistributionPlanTestInput(description, distributionPlanJson); } public override ClientDistributionPlanTestOutput ExecuteTest(ClientDistributionPlanTestInput input) { - JsonSerializerSettings settings = new JsonSerializerSettings - { - Formatting = Newtonsoft.Json.Formatting.Indented - }; - - ClientDistributionPlan distributionPlan = ClientDistributionPlanDeserializer.DeserializeClientDistributionPlan(input.ClientPlanJson); - string serializedDistributionPlan = JsonConvert.SerializeObject(distributionPlan, settings); - - return new ClientDistributionPlanTestOutput(serializedDistributionPlan); + ClientDistributionPlan clientDistributionPlan = ClientDistributionPlanDeserializer.DeserializeClientDistributionPlan(input.DistributionPlanJson); + DistributionPlanWriter visitor = new DistributionPlanWriter(); + clientDistributionPlan.Cql.Accept(visitor); + return new ClientDistributionPlanTestOutput(visitor.SerializedOutput); } public sealed class ClientDistributionPlanTestOutput : BaselineTestOutput { public ClientDistributionPlanTestOutput(string serializedclientPlanJson) { - this.SerializedclientPlanJson = serializedclientPlanJson; + this.SerializedClientPlanJson = serializedclientPlanJson; } - public string SerializedclientPlanJson { get; } + public string SerializedClientPlanJson { get; } public override void SerializeAsXml(XmlWriter xmlWriter) { - JObject jObject = JObject.Parse(this.SerializedclientPlanJson); - string jsonString = jObject.ToString(); - xmlWriter.WriteStartElement("SerializedClientPlanJson"); - xmlWriter.WriteString(jsonString); - xmlWriter.WriteEndElement(); + JsonDocument clientPlan = JsonDocument.Parse(this.SerializedClientPlanJson); + JsonElement clientPlanElement = clientPlan.RootElement; + using (StringWriter stringWriter = new StringWriter()) + { + JsonSerializerOptions jsonOptions = new JsonSerializerOptions + { + WriteIndented = true + }; + + string formattedJson = JsonSerializer.Serialize(clientPlanElement.GetProperty("clientDistributionPlan"), jsonOptions); + + xmlWriter.WriteStartElement("SerializedClientDistributionPlan"); + xmlWriter.WriteString(formattedJson); + xmlWriter.WriteEndElement(); + } } } public sealed class ClientDistributionPlanTestInput : BaselineTestInput { - internal string ClientPlanJson { get; set; } + internal string DistributionPlanJson { get; set; } internal ClientDistributionPlanTestInput( string description, - string clientPlanJson) + string distributionPlanJson) : base(description) { - this.ClientPlanJson = clientPlanJson; + this.DistributionPlanJson = distributionPlanJson; } public override void SerializeAsXml(XmlWriter xmlWriter) { + JsonDocument distributionPlan = JsonDocument.Parse(this.DistributionPlanJson); + JsonElement distributionPlanElement = distributionPlan.RootElement; + xmlWriter.WriteElementString("Description", this.Description); - xmlWriter.WriteElementString("ClientDistributionPlanJson", this.ClientPlanJson); + xmlWriter.WriteElementString("ClientDistributionPlanJson", distributionPlanElement.GetProperty("clientDistributionPlan").ToString()); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlanWriter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlanWriter.cs new file mode 100644 index 0000000000..c0541fce78 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlanWriter.cs @@ -0,0 +1,534 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.ClientDistributionPlan +{ + using System; + using System.Collections.Generic; + using System.Text; + using Cql; + + internal class DistributionPlanWriter : ICqlVisitor + { + private StringBuilder output = new StringBuilder(); + + public string SerializedOutput => "{ \"clientDistributionPlan\": { \"clientQL\": { " + this.output.ToString() + " } } }"; + + void ICqlVisitor.Visit(CqlAggregate cqlAggregate) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlAggregateEnumerableExpression cqlAggregateEnumerableExpression) + { + this.output.Append("\"Kind\": \"Aggregate\", "); + this.output.Append("\"Aggregate\": { "); + cqlAggregateEnumerableExpression.Aggregate.Accept(this); + this.output.Append(" }, "); + this.output.Append("\"SourceExpression\": { "); + cqlAggregateEnumerableExpression.SourceExpression.Accept(this); + this.output.Append("}"); + } + + void ICqlVisitor.Visit(CqlAggregateKind cqlAggregateKind) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlAggregateOperatorKind cqlAggregateOperatorKind) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlArrayCreateScalarExpression cqlArrayCreateScalarExpression) + { + this.output.Append("\"Kind\": \"ArrayCreate\", "); + this.output.Append($"\"ArrayKind\": \"{cqlArrayCreateScalarExpression.ArrayKind}\", "); + this.output.Append("\"Items\": ["); + int count = 0; + foreach (CqlScalarExpression item in cqlArrayCreateScalarExpression.Items) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + item.Accept(this); + this.output.Append("}"); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlArrayIndexerScalarExpression cqlArrayIndexerScalarExpression) + { + this.output.Append("\"Kind\": \"ArrayIndexer\", "); + this.output.Append("\"Expression\": { "); + cqlArrayIndexerScalarExpression.Expression.Accept(this); + this.output.Append("}, "); + this.output.Append($"\"Index\": {cqlArrayIndexerScalarExpression.Index} "); + } + + void ICqlVisitor.Visit(CqlArrayLiteral cqlArrayLiteral) + { + this.output.Append("\"Items\": ["); + int count = 0; + + foreach (CqlLiteral item in cqlArrayLiteral.Items) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + item.Accept(this); + this.output.Append("}"); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlBinaryScalarExpression cqlBinaryScalarExpression) + { + this.output.Append("\"Kind\": \"BinaryOperator\", "); + this.output.Append($"\"OperatorKind\": \"{cqlBinaryScalarExpression.OperatorKind.ToString()}\", "); + this.output.Append("\"LeftExpression\": { "); + cqlBinaryScalarExpression.LeftExpression.Accept(this); + this.output.Append("}, "); + this.output.Append("\"RightExpression\": { "); + cqlBinaryScalarExpression.RightExpression.Accept(this); + this.output.Append("} "); + } + + void ICqlVisitor.Visit(CqlBinaryScalarOperatorKind cqlBinaryScalarOperatorKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlBooleanLiteral cqlBooleanLiteral) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlBuiltinAggregate cqlBuiltinAggregate) + { + this.output.Append($"\"Kind\": \"{cqlBuiltinAggregate.Kind.ToString()}\", "); + this.output.Append($"\"OperatorKind\": \"{cqlBuiltinAggregate.OperatorKind.ToString()}\""); + } + + void ICqlVisitor.Visit(CqlBuiltinScalarFunctionKind cqlBuiltinScalarFunctionKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlDistinctEnumerableExpression cqlDistinctEnumerableExpression) + { + this.output.Append("\"Kind\": \"Distinct\", "); + string name = cqlDistinctEnumerableExpression.DeclaredVariable.Name; + long uniqueId = cqlDistinctEnumerableExpression.DeclaredVariable.UniqueId; + this.output.Append($"\"DeclaredVariable\": {{ \"Name\": \"{name}\", \"UniqueId\": {uniqueId} }}, "); + IReadOnlyList scalarExpressions = cqlDistinctEnumerableExpression.Expression; + this.output.Append("\"Expressions\": [ "); + int count = 0; + foreach (CqlScalarExpression scalarExpression in scalarExpressions) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + scalarExpression.Accept(this); + this.output.Append("} "); + } + + this.output.Append(" ], "); + this.output.Append("\"SourceExpression\": { "); + cqlDistinctEnumerableExpression.SourceExpression.Accept(this); + this.output.Append(" }"); + } + + void ICqlVisitor.Visit(CqlEnumerableExpression cqlEnumerableExpression) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlEnumerableExpressionKind cqlEnumerableExpressionKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlEnumerationKind cqlEnumerationKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlFunctionIdentifier cqlFunctionIdentifier) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlGroupByEnumerableExpression cqlGroupByEnumerableExpression) + { + this.output.Append("\"Kind\": \"GroupBy\", "); + this.output.Append($"\"KeyCount\": {cqlGroupByEnumerableExpression.KeyCount}, \"Aggregates\": [ "); + int count = 0; + foreach (CqlAggregate aggregate in cqlGroupByEnumerableExpression.Aggregates) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + aggregate.Accept(this); + this.output.Append("}"); + } + + this.output.Append("], "); + this.output.Append("\"SourceExpression\": { "); + cqlGroupByEnumerableExpression.SourceExpression.Accept(this); + this.output.Append(" } "); + } + + void ICqlVisitor.Visit(CqlInputEnumerableExpression cqlInputEnumerableExpression) + { + string name = cqlInputEnumerableExpression.Name; + this.output.Append($"\"Kind\": \"Input\", \"Name\": \"{name}\""); + } + + void ICqlVisitor.Visit(CqlIsOperatorKind cqlIsOperatorKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlIsOperatorScalarExpression cqlIsOperatorScalarExpression) + { + this.output.Append("\"Kind\": \"IsOperator\", "); + this.output.Append("\"Expression\": { "); + cqlIsOperatorScalarExpression.Expression.Accept(this); + this.output.Append(" }, "); + } + + void ICqlVisitor.Visit(CqlLetScalarExpression cqlLetScalarExpression) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlLiteral cqlLiteral) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlLiteralKind cqlLiteralKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlLiteralScalarExpression cqlLiteralScalarExpression) + { + CqlLiteralKind literalKind = cqlLiteralScalarExpression.Literal.Kind; + this.output.Append("\"Kind\": \"Literal\", "); + this.output.Append("\"Literal\": { "); + this.output.Append($"\"Kind\": \"{literalKind}\""); + if (literalKind != CqlLiteralKind.Undefined) + { + this.output.Append(", "); + cqlLiteralScalarExpression.Literal.Accept(this); + } + + this.output.Append("}"); + } + + void ICqlVisitor.Visit(CqlMuxScalarExpression cqlMuxScalarExpression) + { + this.output.Append("\"Kind\": \"Mux\", "); + this.output.Append("\"ConditionExpression\": { "); + cqlMuxScalarExpression.ConditionExpression.Accept(this); + this.output.Append("}, "); + this.output.Append("\"LeftExpression\": { "); + cqlMuxScalarExpression.LeftExpression.Accept(this); + this.output.Append("}, "); + this.output.Append("\"RightExpression\": { "); + cqlMuxScalarExpression.RightExpression.Accept(this); + this.output.Append("} "); + } + + void ICqlVisitor.Visit(CqlNullLiteral cqlNullLiteral) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlNumberLiteral cqlNumberLiteral) + { + this.output.Append($"\"Value\": {cqlNumberLiteral.Value} "); + } + + void ICqlVisitor.Visit(CqlObjectCreateScalarExpression cqlObjectCreateScalarExpression) + { + this.output.Append("\"Kind\": \"ObjectCreate\", "); + string objectKind = cqlObjectCreateScalarExpression.ObjectKind; + this.output.Append($"\"ObjectKind\": \"{objectKind}\", "); + this.output.Append("\"Properties\": [ "); + int count = 0; + foreach (CqlObjectProperty property in cqlObjectCreateScalarExpression.Properties) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append($"{{ \"Name\": \"{property.Name}\", "); + this.output.Append("\"Expression\": { "); + property.Expression.Accept(this); + this.output.Append("} } "); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlObjectLiteral cqlObjectLiteral) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlObjectLiteralProperty cqlObjectLiteralProperty) + { + } + + void ICqlVisitor.Visit(CqlObjectProperty cqlObjectProperty) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlOrderByEnumerableExpression cqlOrderByEnumerableExpression) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlOrderByItem cqlOrderByItem) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlPropertyRefScalarExpression cqlPropertyRefScalarExpression) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlScalarAsEnumerableExpression cqlScalarAsEnumerableExpression) + { + this.output.Append("\"Kind\": \"ScalarAsEnumerable\", "); + this.output.Append("\"Expression\": { "); + cqlScalarAsEnumerableExpression.Expression.Accept(this); + this.output.Append("}, "); + this.output.Append($"\"EnumerationKind\": \"{cqlScalarAsEnumerableExpression.EnumerationKind}\""); + } + + void ICqlVisitor.Visit(CqlScalarExpression cqlScalarExpression) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlScalarExpressionKind cqlScalarExpressionKind) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlSelectEnumerableExpression cqlSelectEnumerableExpression) + { + this.output.Append("\"Kind\": \"Select\", "); + string name = cqlSelectEnumerableExpression.DeclaredVariable.Name; + long uniqueId = cqlSelectEnumerableExpression.DeclaredVariable.UniqueId; + this.output.Append($"\"DeclaredVariable\": {{ \"Name\": \"{name}\", \"UniqueId\": {uniqueId} }}, "); + this.output.Append("\"Expression\": { "); + cqlSelectEnumerableExpression.Expression.Accept(this); + this.output.Append("}, "); + this.output.Append("\"SourceExpression\": { "); + cqlSelectEnumerableExpression.SourceExpression.Accept(this); + this.output.Append(" }"); + } + + void ICqlVisitor.Visit(CqlSelectManyEnumerableExpression cqlSelectManyEnumerableExpression) + { + this.output.Append("\"Kind\": \"SelectMany\", "); + string name = cqlSelectManyEnumerableExpression.DeclaredVariable.Name; + long uniqueId = cqlSelectManyEnumerableExpression.DeclaredVariable.UniqueId; + this.output.Append($"\"DeclaredVariable\": {{ \"Name\": \"{name}\", \"UniqueId\": {uniqueId} }}, "); + this.output.Append("\"SelectorExpression\": { "); + cqlSelectManyEnumerableExpression.SelectorExpression.Accept(this); + this.output.Append("},"); + this.output.Append("\"SourceExpression\": { "); + cqlSelectManyEnumerableExpression.SourceExpression.Accept(this); + this.output.Append('}'); + } + + void ICqlVisitor.Visit(CqlSortOrder cqlSortOrder) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlStringLiteral cqlStringLiteral) + { + this.output.Append("\"Kind\": \"String\", "); + this.output.Append($"\"Value\": \"{cqlStringLiteral.Value}\""); + } + + void ICqlVisitor.Visit(CqlSystemFunctionCallScalarExpression cqlSystemFunctionCallScalarExpression) + { + this.output.Append("\"Kind\": \"SystemFunctionCall\", "); + this.output.Append($"\"FunctionKind\": \"{cqlSystemFunctionCallScalarExpression.FunctionKind.ToString()}\", "); + IReadOnlyList scalarExpressions = cqlSystemFunctionCallScalarExpression.Arguments; + this.output.Append("\"Arguments\": [ "); + int count = 0; + foreach (CqlScalarExpression scalarExpression in scalarExpressions) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + scalarExpression.Accept(this); + this.output.Append("}"); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlTakeEnumerableExpression cqlTakeEnumerableExpression) + { + this.output.Append($"\"Kind\": \"Take\", \"SkipValue\": {cqlTakeEnumerableExpression.SkipValue}, \"TakeValue\": {cqlTakeEnumerableExpression.TakeValue}, "); + this.output.Append("\"SourceExpression\": { "); + cqlTakeEnumerableExpression.SourceExpression.Accept(this); + this.output.Append(" } "); + } + + void ICqlVisitor.Visit(CqlTupleAggregate cqlTupleAggregate) + { + this.output.Append("\"Kind\": \"Tuple\", "); + this.output.Append("\"Items\": ["); + int count = 0; + foreach (CqlAggregate item in cqlTupleAggregate.Items) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + item.Accept(this); + this.output.Append("}"); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlTupleCreateScalarExpression cqlTupleCreateScalarExpression) + { + this.output.Append(" \"Kind\": \"TupleCreate\", "); + this.output.Append("\"Items\": ["); + int count = 0; + foreach (CqlScalarExpression scalarExpression in cqlTupleCreateScalarExpression.Items) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + scalarExpression.Accept(this); + this.output.Append("}"); + } + + this.output.Append("]"); + } + + void ICqlVisitor.Visit(CqlTupleItemRefScalarExpression cqlTupleItemRefScalarExpression) + { + this.output.Append("\"Kind\": \"TupleItemRef\", "); + this.output.Append("\"Expression\": { "); + cqlTupleItemRefScalarExpression.Expression.Accept(this); + this.output.Append("}, "); + this.output.Append($"\"Index\": {cqlTupleItemRefScalarExpression.Index}"); + } + + void ICqlVisitor.Visit(CqlUnaryScalarExpression cqlUnaryScalarExpression) + { + this.output.Append("\"Kind\": \"UnaryOperator\", "); + this.output.Append($"\"OperatorKind\": \"{cqlUnaryScalarExpression.OperatorKind.ToString()}\", "); + this.output.Append("\"Expression\": { "); + cqlUnaryScalarExpression.Expression.Accept(this); + this.output.Append("} "); + } + + void ICqlVisitor.Visit(CqlUnaryScalarOperatorKind cqlUnaryScalarOperatorKind) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlUndefinedLiteral cqlUndefinedLiteral) + { + throw new NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlUserDefinedFunctionCallScalarExpression cqlUserDefinedFunctionCallScalarExpression) + { + this.output.Append("\"Kind\": \"UserDefinedFunctionCall\", "); + this.output.Append($"\"Identifier\": {{ \"Name\": \"{cqlUserDefinedFunctionCallScalarExpression.Identifier.Name}\" }}, "); + this.output.Append("\"Arguments\": [ "); + int count = 0; + foreach (CqlScalarExpression argument in cqlUserDefinedFunctionCallScalarExpression.Arguments) + { + if (count >= 1) + { + this.output.Append(", "); + } + + count++; + this.output.Append("{ "); + argument.Accept(this); + this.output.Append("}"); + } + + this.output.Append(" ], "); + this.output.Append($"\"Builtin\": {cqlUserDefinedFunctionCallScalarExpression.Builtin.ToString().ToLower()} "); + } + + void ICqlVisitor.Visit(CqlVariable cqlVariable) + { + throw new System.NotImplementedException(); + } + + void ICqlVisitor.Visit(CqlVariableRefScalarExpression cqlVariableRefScalarExpression) + { + this.output.Append("\"Kind\": \"VariableRef\", "); + this.output.Append($"\"Variable\": {{ \"Name\": \"{cqlVariableRefScalarExpression.Variable.Name}\", \"UniqueId\": {cqlVariableRefScalarExpression.Variable.UniqueId} }} "); + } + + void ICqlVisitor.Visit(CqlWhereEnumerableExpression cqlWhereEnumerableExpression) + { + this.output.Append("\"Kind\": \"Where\", "); + this.output.Append("\"DeclaredVariable\": {"); + this.output.Append($"\"Name\": \"{cqlWhereEnumerableExpression.DeclaredVariable.Name}\", "); + this.output.Append($"\"UniqueId\": {cqlWhereEnumerableExpression.DeclaredVariable.UniqueId} }}, "); + this.output.Append("\"Expression\": { "); + cqlWhereEnumerableExpression.Expression.Accept(this); + this.output.Append("}, "); + this.output.Append("\"SourceExpression\": { "); + cqlWhereEnumerableExpression.SourceExpression.Accept(this); + this.output.Append(" }"); + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Complex_Query.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Complex_Query.json new file mode 100644 index 0000000000..d020fd6e3d --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Complex_Query.json @@ -0,0 +1,4148 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT Count(1) AS count, c.a, c.b, ARRAY( SELECT (SELECT VALUE Count(1) FROM a2 IN c.a WHERE a2 = 435 OR b IN ('First', 'Second')) AS count, (SELECT VALUE Min(a2) FROM a2 IN c.a WHERE a2 = 435 OR b IN ('First', 'Second')) AS min, (SELECT VALUE Max(a2) FROM a2 IN c.a WHERE a2 = 435 OR b IN ('First', 'Second')) AS max, ac AS a FROM ac IN c.a JOIN c.b WHERE EXISTS(SELECT a2 FROM a2 IN c.a WHERE a2 = 425)) AS d, Avg(c.c) AS avg_c FROM c GROUP BY c.a, c.b", + "obfuscatedQuery": "{\"query\":\"SELECT Count(1) AS p1, c.a, c.b, ARRAY(SELECT (SELECT VALUE Count(1)\\n FROM r1 IN c.a\\n WHERE ((r1 = 440.01) OR (b IN ('str1', 'str2')))) AS p1, (SELECT VALUE Min(r1)\\n FROM r1 IN c.a\\n WHERE ((r1 = 440.01) OR (b IN ('str1', 'str2')))) AS p2, (SELECT VALUE Max(r1)\\n FROM r1 IN c.a\\n WHERE ((r1 = 440.01) OR (b IN ('str1', 'str2')))) AS p3, r2 AS a\\n FROM r2 IN c.a\\n JOIN c.b\\n WHERE EXISTS(SELECT r1\\n FROM r1 IN c.a\\n WHERE (r1 = 430.02))\\n)\\n AS d, Avg(c.c) AS p4\\nFROM c\\nGROUP BY c.a, c.b\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":2},\"From\":{\"Expr\":\"Aliased\"},\"GroupBy\":{\"ItemCount\":2}}", + "signature": -5553493019097379213, + "shapeSignature": 6135906453532752526, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 2 + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 74, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 1 + } + ] + } + }, + "SourceExpression": { + "Kind": "GroupBy", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Keys": [ + { + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + { + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + ], + "Aggregates": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + }, + { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + }, + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Items": [ + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 73, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 3 + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 34, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 3 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + }, + { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "c" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 71, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 71, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "c" + } + } + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 69 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 2 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 0 + } + }, + { + "Name": "b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 1 + } + }, + { + "Name": "d", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 4 + } + }, + { + "Name": "avg_c", + "Expression": { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Undefined" + } + }, + "RightExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Divide", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 69 + } + }, + "Index": 3 + }, + "Index": 1 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 36 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 67 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 67 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Array" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 64 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 7 + } + }, + { + "Name": "min", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 8 + } + }, + { + "Name": "max", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 9 + } + }, + { + "Name": "a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 64 + } + }, + "Index": 4 + } + } + ] + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 58 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 62 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 7 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 8 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 62 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Max" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 60 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 60 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 58 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 52 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 56 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 6 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 7 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 56 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Min" + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 54 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 54 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 52 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 46 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 50 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 6 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 50 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 1 + } + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 48 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Or", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 48 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 435 + } + } + }, + "RightExpression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Array_Contains", + "Arguments": [ + { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [ + { + "Kind": "String", + "Value": "First" + }, + { + "Kind": "String", + "Value": "Second" + } + ] + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 5 + } + ] + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 46 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + }, + "SourceExpression": { + "Kind": "SelectMany", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 39 + }, + "SelectorExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 3 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 4 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 5 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 44 + }, + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 44 + } + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Any" + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "a2", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Where", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 41 + }, + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 41 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 425 + } + } + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 39 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v1", + "UniqueId": 38 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 2 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 3 + }, + { + "Kind": "VariableRef", + "Variable": { + "Name": "v1", + "UniqueId": 38 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 1 + } + ] + }, + "SourceExpression": { + "Kind": "ScalarAsEnumerable", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 36 + } + }, + "Index": 0 + }, + "EnumerationKind": "ArrayItems" + } + } + } + } + } + } + } + } + }, + "SourceExpression": { + "Kind": "GroupBy", + "KeyCount": 2, + "Aggregates": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 76 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 76 + } + }, + "Index": 3 + }, + "Index": 1 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 75 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 1 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 2 + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 3 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 4 + } + ] + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 75 + } + }, + "Index": 5 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Count_plus_five.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Count_plus_five.json new file mode 100644 index 0000000000..0bed097ffd --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Count_plus_five.json @@ -0,0 +1,258 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [ + { + "count_a_plus_five": 5 + } + ], + "_count": 1, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT Count(r.a * 2) + 5 AS count_a_plus_five FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT (Count((r.a * 2)) + 5) AS p1__17\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":1},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 2484093724948031272, + "shapeSignature": -995540351760288838, + "queryIL": { + "Expression": { + "Kind": "Aggregate", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "Aggregate": { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "OperatorKind": "Multiply", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "Number", + "Value": 2 + } + } + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "count_a_plus_five", + "Expression": { + "Kind": "BinaryOperator", + "OperatorKind": "Add", + "LeftExpression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 5 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct_with_where.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct_with_where.json new file mode 100644 index 0000000000..7a134bb33b --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Distinct_with_where.json @@ -0,0 +1,717 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT r.FirstName, r.LastName FROM root r WHERE r.LastName = 'Marx'", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT r.p1, r.p2\\nFROM r1 AS r\\nWHERE (r.p2 = 'str1')\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"},\"Where\":{\"Expr\":\"Binary\"}}", + "signature": -5425553105971744231, + "shapeSignature": -7076426752146404075, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "FirstName" + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "LastName" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "LastName" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "Marx" + } + } + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "root" + } + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "FirstName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + } + }, + { + "Name": "LastName", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + }, + "Index": 1 + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Multiple_Aggregates.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Multiple_Aggregates.json new file mode 100644 index 0000000000..ec4c9c362d --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Multiple_Aggregates.json @@ -0,0 +1,1689 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [ + { + "sum_a": 0, + "sum_b": 0 + } + ], + "_count": 1, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT sum(r.a * 2) AS sum_a, sum(r.b) AS sum_b FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT sum((r.a * 2)) AS p1, sum(r.b) AS p2\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"AggCount\":2},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": 5810491931252949147, + "shapeSignature": -8049532835674525869, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 0 + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 0 + }, + "Index": 1 + }, + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Expression": { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 6, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + } + }, + "Index": 1 + }, + "Index": 1 + } + ] + } + }, + "SourceExpression": { + "Kind": "Aggregate", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Aggregate": { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + ] + } + }, + "Items": [ + { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + }, + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + }, + { + "Kind": "Tuple", + "Signature": { + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "ResultType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + ] + } + }, + "Items": [ + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + }, + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "Signature": { + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "ResultType": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + } + }, + "OperatorKind": "Count" + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + ] + }, + "Items": [ + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 0 + } + ] + }, + { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + }, + { + "Kind": "TupleItemRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + } + ] + } + } + }, + "Index": 1 + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "TupleCreate", + "Type": { + "Kind": "Tuple", + "Types": [ + { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + ] + }, + "Items": [ + { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": false + }, + "OperatorKind": "Multiply", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Number", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "Number", + "Value": 2 + } + } + }, + { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "b" + } + ] + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 4, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 2 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "sum_a", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 0 + } + }, + { + "Name": "sum_b", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 2 + } + }, + "Index": 1 + } + } + ] + }, + "SourceExpression": { + "Kind": "Aggregate", + "Aggregate": { + "Kind": "Tuple", + "Items": [ + { + "Kind": "Builtin", + "OperatorKind": "Sum" + }, + { + "Kind": "Builtin", + "OperatorKind": "Sum" + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 8 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 0 + }, + "Index": 0 + } + }, + { + "Kind": "Mux", + "ConditionExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "And", + "LeftExpression": { + "Kind": "BinaryOperator", + "OperatorKind": "NotEqual", + "LeftExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 1 + }, + "RightExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Number", + "Value": 0 + } + } + }, + "RightExpression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "SystemFunctionCall", + "FunctionKind": "Is_Defined", + "Arguments": [ + { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + } + ] + } + } + }, + "LeftExpression": { + "Kind": "Literal", + "Literal": { + "Kind": "Array", + "Items": [] + } + }, + "RightExpression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "TupleItemRef", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 8 + } + }, + "Index": 1 + }, + "Index": 0 + } + } + ] + }, + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 7 + }, + "Expression": { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 0 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 1 + } + ] + }, + { + "Kind": "TupleCreate", + "Items": [ + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 2 + }, + "Index": 0 + }, + { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 7 + } + }, + "Index": 3 + } + ] + } + ] + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Simple_Query_Enumerable.json similarity index 100% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/SimpleEnumerable.json rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/Simple_Query_Enumerable.json diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UnaryScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UnaryScalar.json new file mode 100644 index 0000000000..49c4f08740 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UnaryScalar.json @@ -0,0 +1,352 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT not r.a FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT (NOT r.a)\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": -2655796821372811892, + "shapeSignature": 6057952350481090709, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "$1", + "Expression": { + "Kind": "UnaryOperator", + "OperatorKind": "Not", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UserDefinedFunctionScalar.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UserDefinedFunctionScalar.json new file mode 100644 index 0000000000..7d77889684 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/DistributionPlans/Text/UserDefinedFunctionScalar.json @@ -0,0 +1,357 @@ +{ + "_rid": "7+JyAOgQsps=", + "Documents": [], + "_count": 0, + "_distributionPlan": { + "backendDistributionPlan": { + "query": "SELECT DISTINCT udf.toUpper(r.a) as aUpper FROM r", + "obfuscatedQuery": "{\"query\":\"SELECT DISTINCT udf.toUpper(r.a) AS p1\\nFROM r\",\"parameters\":[]}", + "shape": "{\"Select\":{\"Type\":\"List\",\"Distinct\":true},\"From\":{\"Expr\":\"Aliased\"}}", + "signature": -4301689830817130579, + "shapeSignature": -4084183748823952763, + "queryIL": { + "Expression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expression": { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "ArrayCreate", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Array", + "ExcludesUndefined": true + }, + "ArrayKind": "Array", + "Items": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "v0", + "UniqueId": 5, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ] + } + ] + } + }, + "SourceExpression": { + "Kind": "Distinct", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Variable": { + "Name": "s0", + "UniqueId": 3, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + } + } + ], + "SourceExpression": { + "Kind": "Select", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "v0", + "UniqueId": 0, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "a" + } + }, + "SourceExpression": { + "Kind": "Where", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Delegate": { + "Kind": "ScalarExpression", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "DeclaredVariable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Expression": { + "Kind": "BinaryOperator", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Boolean", + "ExcludesUndefined": false + }, + "OperatorKind": "Equal", + "LeftExpression": { + "Kind": "PropertyRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": false + }, + "Expression": { + "Kind": "VariableRef", + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + }, + "Variable": { + "Name": "r", + "UniqueId": 2, + "Type": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + } + }, + "PropertyName": "pk" + }, + "RightExpression": { + "Kind": "Literal", + "Type": { + "Kind": "Base", + "BaseTypeKind": "String", + "ExcludesUndefined": true + }, + "Literal": { + "Kind": "String", + "Value": "90850703-b087-4580-91ee-e4a3918c3e85" + } + } + } + }, + "SourceExpression": { + "Kind": "Input", + "Type": { + "Kind": "Enum", + "ItemType": { + "Kind": "Base", + "BaseTypeKind": "Variant", + "ExcludesUndefined": true + } + }, + "Name": "r" + } + } + } + } + } + }, + "noSpatial": true, + "language": "QueryIL" + }, + "clientDistributionPlan": { + "clientQL": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 1 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 1 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expression": { + "Kind": "ObjectCreate", + "ObjectKind": "Object", + "Properties": [ + { + "Name": "aUpper", + "Expression": { + "Kind": "UserDefinedFunctionCall", + "Identifier": { + "Name": "toUpper" + }, + "Arguments": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "Builtin": false + } + } + ] + }, + "SourceExpression": { + "Kind": "Distinct", + "DeclaredVariable": { + "Name": "s0", + "UniqueId": 3 + }, + "Expressions": [ + { + "Kind": "VariableRef", + "Variable": { + "Name": "s0", + "UniqueId": 3 + } + } + ], + "SourceExpression": { + "Kind": "Select", + "DeclaredVariable": { + "Name": "v0", + "UniqueId": 6 + }, + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "ArrayIndexer", + "Expression": { + "Kind": "VariableRef", + "Variable": { + "Name": "v0", + "UniqueId": 6 + } + }, + "Index": 0 + }, + "Index": 0 + }, + "SourceExpression": { + "Kind": "Input", + "Name": "root" + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index d236b73a56..840e6c3ccf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -593,10 +593,10 @@ public async Task TestTextDistributionPlanParsingFromStream() JObject jsonObject = JObject.Parse(testResponse); string expectedBackendPlan = jsonObject["_distributionPlan"]["backendDistributionPlan"].ToString(); - expectedBackendPlan = RemoveJsonFormattingFromString(expectedBackendPlan); + expectedBackendPlan = RemoveWhitespace(expectedBackendPlan); string expectedClientPlan = jsonObject["_distributionPlan"]["clientDistributionPlan"].ToString(); - expectedClientPlan = RemoveJsonFormattingFromString(expectedClientPlan); + expectedClientPlan = RemoveWhitespace(expectedClientPlan); MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(testResponse)); CosmosQueryClientCore.ParseRestStream( @@ -608,8 +608,8 @@ public async Task TestTextDistributionPlanParsingFromStream() if (distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan) && distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan)) { - Assert.AreEqual(expectedBackendPlan, RemoveJsonFormattingFromString(backendDistributionPlan.ToString())); - Assert.AreEqual(expectedClientPlan, RemoveJsonFormattingFromString(clientDistributionPlan.ToString())); + Assert.AreEqual(expectedBackendPlan, RemoveWhitespace(backendDistributionPlan.ToString())); + Assert.AreEqual(expectedClientPlan, RemoveWhitespace(clientDistributionPlan.ToString())); } else { @@ -712,9 +712,9 @@ private static async Task TestHandlingOfFailedFallbackPipeline(bool isMult return false; } - private static string RemoveJsonFormattingFromString(string jsonString) + private static string RemoveWhitespace(string jsonString) { - return jsonString.Replace(" ", string.Empty).Replace("\t", string.Empty).Replace("\n", string.Empty).Replace("\r", string.Empty); + return jsonString.Replace(" ", string.Empty); } private static async Task<(MergeTestUtil, IQueryPipelineStage)> CreateFallbackPipelineTestInfrastructure(int numItems, bool isFailedFallbackPipelineTest, bool isMultiPartition, QueryRequestOptions queryRequestOptions) From 431c6f224747e463bed0475083d5e0d7c1afaee2 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:50:35 -0800 Subject: [PATCH 256/337] Documentation: Fixes API comment for `RequestOptions.IfMatchEtag` (#4249) * Code changes to update documentation. * Code changes to add code comment for etag property. * Code changes to update API docs for ReadItemAsync(). * Code changes to address minor doc correction. * Code changes to update remarks for patch item async. --- Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs | 3 +-- Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index dd24f3e45e..2502c75823 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -18,8 +18,7 @@ public class RequestOptions /// Gets or sets the If-Match (ETag) associated with the request in the Azure Cosmos DB service. /// /// - /// Most commonly used with the Delete* and Replace* methods of such as - /// but can be used with other methods like for caching scenarios. + /// Most commonly used with the Delete* and Replace* methods of such as . /// public string IfMatchEtag { get; set; } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 5b6f188e89..7084eb5ada 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -433,6 +433,7 @@ public abstract Task ReadItemStreamAsync( /// * "_ts": Gets the last modified time stamp associated with the item from the Azure Cosmos DB service. /// * "_etag": Gets the entity tag associated with the item from the Azure Cosmos DB service. /// * "ttl": Gets the time to live in seconds of the item in the Azure Cosmos DB service. + /// Note that, this API does not support the usage of property at the moment. /// /// https://aka.ms/cosmosdb-dot-net-exceptions#typed-api /// @@ -719,6 +720,7 @@ public abstract Task> ReadManyItemsAsync( /// To change an item's partition key value you must delete the original item and insert a new item. /// The patch operations are atomic and are executed sequentially. /// By default, resource body will be returned as part of the response. User can request no content by setting flag to false. + /// Note that, this API does not support the usage of property at the moment. /// /// The Cosmos item id of the item to be patched. /// for the item From 4d9b7bd9848ddde59a8aea50e2dff4c25045f83d Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Fri, 19 Jan 2024 10:23:15 -0800 Subject: [PATCH 257/337] Query: Fixes LINQ Translation of SqlNullLiteral Values (#4260) * initial commit * moar tests * test fix * more test --- .../src/Linq/ExpressionToSQL.cs | 3 +- ...seline.TestMemberInitializerDataMember.xml | 222 +++++++++++++++++- ...emberInitializerDotNetCustomSerializer.xml | 100 +++++++- ...seline.TestMemberInitializerNewtonsoft.xml | 222 +++++++++++++++++- ...TranslationWithCustomSerializerBaseline.cs | 38 ++- 5 files changed, 567 insertions(+), 18 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index 6be1e82e9c..ad9d02cab4 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -495,7 +495,8 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit memberExpression = left as MemberExpression; } - if (memberExpression != null) + if (memberExpression != null && + right.Literal is not SqlNullLiteral) { Type memberType = memberExpression.Type; if (memberType.IsNullable()) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml index 6734a125fa..215d593da2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml @@ -29,7 +29,7 @@ WHERE (root["numericFieldDataMember"] = 1)]]> +WHERE (root = {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null})]]> 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["numericFieldDataMember"] > 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null}) FROM root]]> + + + + + + + (doc.DateTimeField != null))]]> + + + + + + + + + + + (doc.DataTypeField != null))]]> + + + + + + + + + + + (doc.DateTimeField == Convert(new DateTime(1970, 1, 1, 0, 0, 0, 0, Utc), Nullable`1)))]]> + + + + + + + + + + + (Convert(doc.DataTypeField, Nullable`1) == Convert(Point, Nullable`1)))]]> + + + + + + + + + + + (doc.StringField != null))]]> + + + + @@ -146,7 +251,7 @@ WHERE (root["NumericFieldDataMember"] = 1)]]> +WHERE (root = {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null})]]> 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["NumericFieldDataMember"] > 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null}) FROM root]]> + + + + + + + (doc.DateTimeField != null))]]> + + + + + + + + + + + (doc.DataTypeField != null))]]> + + + + + + + + + + + (doc.DateTimeField == Convert(new DateTime(1970, 1, 1, 0, 0, 0, 0, Utc), Nullable`1)))]]> + + + + + + + + + + + (Convert(doc.DataTypeField, Nullable`1) == Convert(Point, Nullable`1)))]]> + + + + + + + + + + + (doc.StringField != null))]]> + + + + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml index a9c63ebf41..ca941f5bd0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDotNetCustomSerializer.xml @@ -28,7 +28,7 @@ WHERE (root["NumberValueDotNet"] = 1)]]> +WHERE (root = {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null, "DateTimeFieldDotNet": null, "DataTypeField": null})]]> 1) ? {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null} : {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["NumberValueDotNet"] > 1) ? {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null, "DateTimeFieldDotNet": null, "DataTypeField": null} : {"NumberValueDotNet": 1, "StringValueDotNet": "1", "id": null, "Pk": null, "DateTimeFieldDotNet": null, "DataTypeField": null}) FROM root]]> "false", "false", "true" +]]]> + + + + + + (doc.DateTimeField != null))]]> + + + + + + + + + + + (doc.DataTypeField != null))]]> + + + + + + + + + + + (doc.DateTimeField == Convert(new DateTime(1970, 1, 1, 0, 0, 0, 0, Utc), Nullable`1)))]]> + + + + + + + + + + + (Convert(doc.DataTypeField, Nullable`1) == Convert(Point, Nullable`1)))]]> + + + + + + + + + + + (doc.StringField != null))]]> + + + + + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml index 5ecf5171bc..83c0adb53b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerNewtonsoft.xml @@ -29,7 +29,7 @@ WHERE (root["numberValueNewtonsoft"] = 1)]]> +WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null})]]> 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["numberValueNewtonsoft"] > 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null}) FROM root]]> + + + + + + + (doc.DateTimeField != null))]]> + + + + + + + + + + + (doc.DataTypeField != null))]]> + + + + + + + + + + + (doc.DateTimeField == Convert(new DateTime(1970, 1, 1, 0, 0, 0, 0, Utc), Nullable`1)))]]> + + + + + + + + + + + (Convert(doc.DataTypeField, Nullable`1) == Convert(Point, Nullable`1)))]]> + + + + + + + + + + + (doc.StringField != null))]]> + + + + @@ -146,7 +251,7 @@ WHERE (root["NumberValueNewtonsoft"] = 1)]]> +WHERE (root = {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null})]]> 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["NumberValueNewtonsoft"] > 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null}) FROM root]]> + + + + + + + (doc.DateTimeField != null))]]> + + + + + + + + + + + (doc.DataTypeField != null))]]> + + + + + + + + + + + (doc.DateTimeField == Convert(new DateTime(1970, 1, 1, 0, 0, 0, 0, Utc), Nullable`1)))]]> + + + + + + + + + + + (Convert(doc.DataTypeField, Nullable`1) == Convert(Point, Nullable`1)))]]> + + + + + + + + + + + (doc.StringField != null))]]> + + + + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs index 817b030a60..91a537522c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationWithCustomSerializerBaseline.cs @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using Microsoft.Azure.Cosmos.SDK.EmulatorTests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; + using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; [SDK.EmulatorTests.TestClass] @@ -102,6 +103,11 @@ public void TestMemberInitializerDotNetCustomSerializer() new LinqTestInput("Filter w/ DataObject initializer with member initialization", b => getQuery(b).Where(doc => doc == new DataObjectDotNet() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData), new LinqTestInput("OrderBy query", b => getQuery(b).Select(x => x).OrderBy(x => x.NumericField).Take(5), skipVerification : true, inputData: insertedData), new LinqTestInput("Conditional", b => getQuery(b).Select(c => c.NumericField > 1 ? "true" : "false"), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable property", b => getQuery(b).Where(doc => doc.DateTimeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable enum", b => getQuery(b).Where(doc => doc.DataTypeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable property", b => getQuery(b).Where(doc => doc.DateTimeField == new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable enum", b => getQuery(b).Where(doc => doc.DataTypeField == DataType.Point), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ string null comparison", b => getQuery(b).Where(doc => doc.StringField != null), skipVerification : true, inputData: insertedData), }; this.ExecuteTestSuite(inputs); @@ -127,7 +133,12 @@ public void TestMemberInitializerNewtonsoft() new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" } : new DataObjectNewtonsoft() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectNewtonsoft() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable property, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.DateTimeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable enum, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.DataTypeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable property", b => getQuery(b).Where(doc => doc.DateTimeField == new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable enum", b => getQuery(b).Where(doc => doc.DataTypeField == DataType.Point), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ string null comparison, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.StringField != null), skipVerification : true, inputData: insertedData), }; inputs.AddRange(camelCaseSettingInputs); @@ -156,7 +167,12 @@ public void TestMemberInitializerDataMember() new LinqTestInput("Filter w/ DataObject initializer with constant value, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Select w/ DataObject initializer, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), new LinqTestInput("Deeper than top level reference, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Select(doc => doc.NumericField > 1 ? new DataObjectDataMember() { NumericField = 1, StringField = "1" } : new DataObjectDataMember() { NumericField = 1, StringField = "1" }), skipVerification : true, inputData: insertedData), - new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData) + new LinqTestInput("Filter w/ DataObject initializer with member initialization, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc == new DataObjectDataMember() { NumericField = doc.NumericField, StringField = doc.StringField }).Select(b => "A"), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable property, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.DateTimeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ nullable enum, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.DataTypeField != null), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable property", b => getQuery(b).Where(doc => doc.DateTimeField == new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ non-null nullable enum", b => getQuery(b).Where(doc => doc.DataTypeField == DataType.Point), skipVerification : true, inputData: insertedData), + new LinqTestInput("Filter w/ string null comparison, camelcase = " + useCamelCaseSerializer, b => getQuery(b).Where(doc => doc.StringField != null), skipVerification : true, inputData: insertedData), }; inputs.AddRange(camelCaseSettingInputs); @@ -332,6 +348,12 @@ private class DataObjectDotNet : LinqTestObject public string Pk { get; set; } + [JsonPropertyName("DateTimeFieldDotNet")] + public DateTime? DateTimeField { get; set; } + + [System.Text.Json.Serialization.JsonConverter(typeof(System.Text.Json.Serialization.JsonStringEnumConverter))] + public DataType? DataTypeField { get; set; } + public DataObjectDotNet() { } public DataObjectDotNet(double numericField, string stringField, string id, string pk) @@ -364,6 +386,12 @@ private class DataObjectNewtonsoft : LinqTestObject public string Pk { get; set; } + [Newtonsoft.Json.JsonConverter(typeof(IsoDateTimeConverter))] + public DateTime? DateTimeField { get; set; } + + [Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))] + public DataType? DataTypeField { get; set; } + public DataObjectNewtonsoft() { } public DataObjectNewtonsoft(double numericField, string stringField, string id, string pk) @@ -396,6 +424,12 @@ private class DataObjectDataMember : LinqTestObject [DataMember(Name = "Pk")] public string Pk { get; set; } + [DataMember(Name = "DateTimeFieldDataMember")] + public DateTime? DateTimeField { get; set; } + + [DataMember(Name = "DataTypeFieldDataMember")] + public DataType? DataTypeField { get; set; } + public DataObjectDataMember() { } public DataObjectDataMember(double numericField, string stringField, string id, string pk) From 3c1815633eddf64a5b71ea566fd9d7295768c492 Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:31:49 -0800 Subject: [PATCH 258/337] Query : Adds Request Charge to Query Metrics (#4252) * initial commit * Initial commit * Revert "initial commit" This reverts commit 83935992fcf43d05ce764026533ff93e176f9fb0. * contract updates * support gateway * PR comments * add totalrequestcharge * API update * new trace class * Class cleanup * Move request charge to serversidemetrics - optional * Revert "Move request charge to serversidemetrics - optional" This reverts commit 299908477101a15715a4100edd5a3010662a79ac. * nit fixes --- .../src/Diagnostics/CosmosTraceDiagnostics.cs | 2 +- .../Metrics/ServerSideCumulativeMetrics.cs | 5 ++ .../ServerSideCumulativeMetricsInternal.cs | 3 + .../Core/Metrics/ServerSideMetricsInternal.cs | 2 + .../ServerSideMetricsInternalAccumulator.cs | 62 ---------------- .../ServerSideMetricsTraceExtractor.cs | 70 +++++++++++++++++++ .../Metrics/ServerSidePartitionedMetrics.cs | 5 ++ .../ServerSidePartitionedMetricsInternal.cs | 8 ++- .../CosmosItemTests.cs | 9 ++- .../Contracts/DotNetSDKAPI.json | 20 ++++++ 10 files changed, 120 insertions(+), 66 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTraceExtractor.cs diff --git a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs index 2d92a2cfb7..ef74ad3d6e 100644 --- a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs @@ -111,7 +111,7 @@ private ReadOnlyMemory WriteTraceToJsonWriter(JsonSerializationFormat json private static ServerSideCumulativeMetrics PopulateServerSideCumulativeMetrics(ITrace trace) { ServerSideMetricsInternalAccumulator accumulator = new ServerSideMetricsInternalAccumulator(); - ServerSideMetricsInternalAccumulator.WalkTraceTreeForQueryMetrics(trace, accumulator); + ServerSideMetricsTraceExtractor.WalkTraceTreeForQueryMetrics(trace, accumulator); IReadOnlyList serverSideMetricsList = accumulator.GetPartitionedServerSideMetrics().Select(metrics => new ServerSidePartitionedMetricsInternal(metrics)).ToList(); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs index 3e7364f957..c6e07fb8bb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs @@ -15,6 +15,11 @@ public abstract class ServerSideCumulativeMetrics /// public abstract ServerSideMetrics CumulativeMetrics { get; } + /// + /// Gets the total request charge for all partitions. + /// + public abstract double TotalRequestCharge { get; } + /// /// Gets the list of ServerSideMetrics, one for for each partition. /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs index 5405482bb5..4f66f3ec13 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs @@ -20,10 +20,13 @@ internal ServerSideCumulativeMetricsInternal(IEnumerable partitionedMetrics.ServerSideMetricsInternal)); + this.TotalRequestCharge = serverSideMetricsList.Sum(partitionedMetrics => partitionedMetrics.RequestCharge); } public override ServerSideMetrics CumulativeMetrics { get; } public override IReadOnlyList PartitionedMetrics { get; } + + public override double TotalRequestCharge { get; } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs index 6e80de06a5..a7e9e283da 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs @@ -124,6 +124,8 @@ public ServerSideMetricsInternal( public int? PartitionKeyRangeId { get; set; } + public double RequestCharge { get; set; } + public static ServerSideMetricsInternal Create(IEnumerable serverSideMetricsEnumerable) { ServerSideMetricsInternalAccumulator accumulator = new ServerSideMetricsInternalAccumulator(); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs index 64be05e6b8..261f8786e9 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs @@ -80,67 +80,5 @@ public List GetPartitionedServerSideMetrics() { return this.serverSideMetricsList; } - - public static void WalkTraceTreeForQueryMetrics(ITrace currentTrace, ServerSideMetricsInternalAccumulator accumulator) - { - if (currentTrace == null) - { - return; - } - - foreach (object datum in currentTrace.Data.Values) - { - if (datum is QueryMetricsTraceDatum queryMetricsTraceDatum) - { - queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.FeedRange = currentTrace.Name; - queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.PartitionKeyRangeId = WalkTraceTreeForPartitionKeyRangeId(currentTrace); - accumulator.Accumulate(queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics); - return; - } - } - - foreach (ITrace childTrace in currentTrace.Children) - { - WalkTraceTreeForQueryMetrics(childTrace, accumulator); - } - - return; - } - - private static int? WalkTraceTreeForPartitionKeyRangeId(ITrace currentTrace) - { - if (currentTrace == null) - { - return null; - } - - foreach (Object datum in currentTrace.Data.Values) - { - if (datum is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) - { - if (clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList.Count > 0) - { - return int.TryParse(clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList[0].StoreResult.PartitionKeyRangeId, out int pKRangeId) - ? pKRangeId - : null; - } - else - { - return null; - } - } - } - - foreach (ITrace childTrace in currentTrace.Children) - { - int? partitionKeyRangeId = WalkTraceTreeForPartitionKeyRangeId(childTrace); - if (partitionKeyRangeId != null) - { - return partitionKeyRangeId; - } - } - - return null; - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTraceExtractor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTraceExtractor.cs new file mode 100644 index 0000000000..0bfafabab9 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTraceExtractor.cs @@ -0,0 +1,70 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Tracing.TraceData; + + internal static class ServerSideMetricsTraceExtractor + { + public static void WalkTraceTreeForQueryMetrics(ITrace currentTrace, ServerSideMetricsInternalAccumulator accumulator) + { + if (currentTrace == null) + { + return; + } + + foreach (object datum in currentTrace.Data.Values) + { + if (datum is QueryMetricsTraceDatum queryMetricsTraceDatum) + { + ServerSideMetricsInternal serverSideMetrics = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics; + serverSideMetrics.FeedRange = currentTrace.Name; + ServerSideMetricsTraceExtractor.WalkTraceTreeForPartitionInfo(currentTrace, serverSideMetrics); + accumulator.Accumulate(serverSideMetrics); + } + } + + foreach (ITrace childTrace in currentTrace.Children) + { + ServerSideMetricsTraceExtractor.WalkTraceTreeForQueryMetrics(childTrace, accumulator); + } + } + + private static void WalkTraceTreeForPartitionInfo(ITrace currentTrace, ServerSideMetricsInternal serverSideMetrics) + { + if (currentTrace == null) + { + return; + } + + foreach (Object datum in currentTrace.Data.Values) + { + if (datum is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) + { + if (clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList.Count > 0) + { + if (int.TryParse(clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList[0].StoreResult.PartitionKeyRangeId, out int pKRangeId)) + { + serverSideMetrics.PartitionKeyRangeId = pKRangeId; + } + + serverSideMetrics.RequestCharge = clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList[0].StoreResult.RequestCharge; + } + } + else if (datum is PointOperationStatisticsTraceDatum pointOperationStatisticsTraceDatum) + { + serverSideMetrics.RequestCharge = pointOperationStatisticsTraceDatum.RequestCharge; + } + } + + foreach (ITrace childTrace in currentTrace.Children) + { + ServerSideMetricsTraceExtractor.WalkTraceTreeForPartitionInfo(childTrace, serverSideMetrics); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs index be5a624a42..4ca4c9f5c7 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs @@ -26,5 +26,10 @@ public abstract class ServerSidePartitionedMetrics /// Only has a value in direct mode. When using gateway mode, this is null. /// public abstract int? PartitionKeyRangeId { get; } + + /// + /// Gets the request charge for the operation on this partition. + /// + public abstract double RequestCharge { get; } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs index 9ed30963a6..2779e0f0b0 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs @@ -12,7 +12,7 @@ namespace Microsoft.Azure.Cosmos internal class ServerSidePartitionedMetricsInternal : ServerSidePartitionedMetrics { internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSideMetricsInternal) - : this(serverSideMetricsInternal, serverSideMetricsInternal.FeedRange, serverSideMetricsInternal.PartitionKeyRangeId) + : this(serverSideMetricsInternal, serverSideMetricsInternal.FeedRange, serverSideMetricsInternal.PartitionKeyRangeId, serverSideMetricsInternal.RequestCharge) { } @@ -22,11 +22,13 @@ internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSi /// /// /// - internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSideMetricsInternal, string feedRange, int? partitionKeyRangeId) + /// + internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSideMetricsInternal, string feedRange, int? partitionKeyRangeId, double requestCharge) { this.ServerSideMetricsInternal = serverSideMetricsInternal; this.FeedRange = feedRange; this.PartitionKeyRangeId = partitionKeyRangeId; + this.RequestCharge = requestCharge; } public ServerSideMetricsInternal ServerSideMetricsInternal { get; } @@ -36,5 +38,7 @@ internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSi public override string FeedRange { get; } public override int? PartitionKeyRangeId { get; } + + public override double RequestCharge { get; } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index 75cf001b3b..1463321ee7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -33,7 +33,6 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Reflection; using System.Text.RegularExpressions; using Microsoft.Azure.Cosmos.Diagnostics; - using Microsoft.Azure.Cosmos.Query.Core.Metrics; [TestClass] public class CosmosItemTests : BaseCosmosClientHelper @@ -1287,8 +1286,10 @@ public async Task QuerySinglePartitionItemStreamTest(int perPKItemCount, int max ServerSideCumulativeMetrics metrics = response.Diagnostics.GetQueryMetrics(); Assert.IsTrue(metrics.PartitionedMetrics.Count > 0); + Assert.IsTrue(metrics.PartitionedMetrics[0].RequestCharge > 0); Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + Assert.IsTrue(metrics.TotalRequestCharge > 0); if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) { @@ -1376,11 +1377,14 @@ public async Task ItemMultiplePartitionQuery() Assert.IsTrue(metrics.PartitionedMetrics.Count == 3); Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + Assert.IsTrue(metrics.TotalRequestCharge > 0); foreach (ServerSidePartitionedMetrics partitionedMetrics in metrics.PartitionedMetrics) { Assert.IsNotNull(partitionedMetrics); + Assert.IsNotNull(partitionedMetrics.FeedRange); Assert.IsNotNull(partitionedMetrics.PartitionKeyRangeId); + Assert.IsTrue(partitionedMetrics.RequestCharge > 0); } if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) @@ -1455,11 +1459,14 @@ public async Task ItemSinglePartitionQueryGateway() Assert.IsTrue(metrics.PartitionedMetrics.Count == 1); Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + Assert.IsTrue(metrics.TotalRequestCharge > 0); foreach (ServerSidePartitionedMetrics partitionedMetrics in metrics.PartitionedMetrics) { Assert.IsNotNull(partitionedMetrics); + Assert.IsNotNull(partitionedMetrics.FeedRange); Assert.IsNull(partitionedMetrics.PartitionKeyRangeId); + Assert.IsTrue(partitionedMetrics.RequestCharge > 0); } if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 46bdf1c170..a336902647 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -9235,6 +9235,16 @@ "Microsoft.Azure.Cosmos.ServerSideCumulativeMetrics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Double get_TotalRequestCharge()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double get_TotalRequestCharge();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double TotalRequestCharge": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Double TotalRequestCharge;CanRead:True;CanWrite:False;Double get_TotalRequestCharge();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.ServerSideMetrics CumulativeMetrics": { "Type": "Property", "Attributes": [], @@ -9387,6 +9397,16 @@ "Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Double get_RequestCharge()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double get_RequestCharge();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double RequestCharge": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Double RequestCharge;CanRead:True;CanWrite:False;Double get_RequestCharge();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.ServerSideMetrics get_ServerSideMetrics()": { "Type": "Method", "Attributes": [], From fccbc93fb117f981e27443caaa36e753ceeacdb3 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 22 Jan 2024 14:37:58 -0800 Subject: [PATCH 259/337] [Internal] Pipelines: Adds permissions to workflow (#4270) * Adding permissions to workflow * changing permissions * Lowering permissions * It was read * Nope it was write --- .github/workflows/prlint.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/prlint.yml b/.github/workflows/prlint.yml index af6ddaa521..eb7d90bc7b 100644 --- a/.github/workflows/prlint.yml +++ b/.github/workflows/prlint.yml @@ -6,6 +6,9 @@ on: jobs: pr-lint: + permissions: + checks: write + pull-requests: write runs-on: ubuntu-latest steps: - uses: morrisoncole/pr-lint-action@v1.7.0 From e11dc9b49d70510a66f85ac4b78598fba33317d0 Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Tue, 23 Jan 2024 21:08:50 -0800 Subject: [PATCH 260/337] Query: Refactors Optimistic Direct Execution to be turned on by default on .NET SDK (#4225) * Turned on ODe by default * update subpartitioning tests to include ODE * Updated contracts * adds multihash test cases * Updated client serialization test output * Updated OffsetLimitPageSize() test * Revert changes to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml * Updated EndToEndTraceWriterBaselineTests.ReadManyAsync baseline test * Removed account details * Updated performance benchmark results * Set enableODE to true for some of the tests * Updated Feed token tests to test ODE and non ODE cases * Added ODE testing for Session token regression test * Updated AggregateQueryTests() and CosmosMultiHashTest() * Reverted changes to OffsetLimitPageSize() * Added ODE testing to AggregateFunctionAsync() * Removed account details from baseline tests * Added assert to confirm that the right document is being returned every time * Updated location of foreach loop for ODE * Updated baselines * Fixed comments * Cleaned up code * Fixed baselines * Updated more baselines * Setting QueryRequestRateTest() to not use ODE --------- Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> --- .../CosmosQueryExecutionContextFactory.cs | 4 +- .../src/RequestOptions/QueryRequestOptions.cs | 10 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 196 +++ ...TraceWriterBaselineTests.ReadManyAsync.xml | 1050 +++++++---------- ...lBaselineTests.TestDistinctTranslation.xml | 28 +- ...ralBaselineTests.TestThenByTranslation.xml | 8 +- .../CosmosBasicQueryTests.cs | 11 +- .../CosmosGatewayTimeoutTests.cs | 3 +- .../CosmosItemSessionTokenTests.cs | 312 ++--- .../CosmosJsonSerializerTests.cs | 88 +- .../CosmosMultiHashTest.cs | 104 +- .../FeedToken/QueryFeedTokenTests.cs | 152 +-- .../Linq/LinqTestsCommon.cs | 61 +- .../Linq/LinqTranslationBaselineTests.cs | 7 +- .../Query/AggregateQueryTests.cs | 184 ++- .../Query/SanityQueryTests.cs | 6 +- .../EndToEndTraceWriterBaselineTests.cs | 7 +- .../Contracts/BenchmarkResults.json | 36 +- .../Contracts/DotNetPreviewSDKAPI.json | 53 +- .../Contracts/DotNetSDKAPI.json | 38 + ...misticDirectExecutionQueryBaselineTests.cs | 9 +- .../Query/Pipeline/FullPipelineTests.cs | 60 +- 22 files changed, 1263 insertions(+), 1164 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 01be3ffc83..e7a65b7457 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -34,7 +34,7 @@ internal static class CosmosQueryExecutionContextFactory { internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; - private const string QueryInspectionPattern = @"\s+(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; + private const string QueryInspectionPattern = @"\s*(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; private const string OptimisticDirectExecution = "OptimisticDirectExecution"; private const string Passthrough = "Passthrough"; private const string Specialized = "Specialized"; @@ -782,7 +782,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); List targetRanges; - if (partitionedQueryExecutionInfo != null) + if (partitionedQueryExecutionInfo != null || inputParameters.InitialFeedRange != null) { targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( cosmosQueryContext.QueryClient, diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index a4557da6d2..3e410c3892 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,15 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// -#if PREVIEW - public -#else - internal -#endif - bool EnableOptimisticDirectExecution { get; set; } -#if PREVIEW - = true; -#endif + public bool EnableOptimisticDirectExecution { get; set; } = true; /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index eeb3c0d890..ab07cd8448 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -34,8 +34,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -206,6 +210,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -218,6 +232,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -755,8 +779,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -931,6 +959,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -943,6 +981,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -1497,8 +1545,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1678,6 +1730,26 @@ "duration in milliseconds": 0 } ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 } ] }, @@ -2219,8 +2291,12 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2395,6 +2471,16 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -2407,6 +2493,16 @@ } ] }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -2985,8 +3081,12 @@ │ │ │ [PointOperationStatisticsTraceDatum] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) + │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3220,6 +3320,26 @@ "duration in milliseconds": 0 } ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + }, + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 } ] }, @@ -3779,9 +3899,15 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3967,6 +4093,38 @@ ] } ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + } + ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] } ] }, @@ -4510,9 +4668,15 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -4702,6 +4866,38 @@ ] } ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] + } + ] + } + ] + }, + { + "name": "Get Overlapping Feed Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Get Partition Key Ranges", + "duration in milliseconds": 0, + "children": [ + { + "name": "Try Get Overlapping Ranges", + "duration in milliseconds": 0 + } + ] } ] }, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index af2afbcb73..55033eeb40 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -25,120 +25,105 @@ │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ ( │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Query Metrics] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [System Info] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Query Metrics] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [System Info] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ]]> 10) ORDER BY v2 ASC ]]> - + @@ -423,7 +423,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -442,7 +442,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -482,7 +482,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -559,7 +559,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -578,7 +578,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -597,7 +597,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -616,7 +616,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -635,7 +635,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -654,7 +654,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -689,7 +689,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -707,7 +707,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -773,7 +773,7 @@ JOIN ( JOIN p0 IN root["Parents"]) AS v1 ORDER BY v1 ASC ]]> - + @@ -792,7 +792,7 @@ JOIN ( WHERE (LENGTH(v1) > 10) ORDER BY v1 ASC ]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml index 73b8b19748..75054876fc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml @@ -119,7 +119,7 @@ JOIN ( SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> - + @@ -132,7 +132,7 @@ ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] DESC]]> - + @@ -388,7 +388,6 @@ FROM ( JOIN c0 IN root["Children"]) AS v1) AS r1 ORDER BY r1["FamilyId"] ASC, r1["FamilyNumber"] ASC ]]> - @@ -435,7 +434,6 @@ FROM ( WHERE (p0["GivenName"]["Length"] > 5)) AS v0) AS r0 ORDER BY r0["FamilyId"] ASC, r0["FamilyNumber"] ASC ]]> - @@ -586,7 +584,7 @@ FROM root JOIN f0 IN root["Records"]["Transactions"] WHERE (ARRAY_LENGTH(root["Children"]) > 0) ORDER BY f0["Type"] ASC, f0["Amount"] ASC]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs index bfd6366104..a50ff87fe0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosBasicQueryTests.cs @@ -240,9 +240,7 @@ public async Task QueryRequestRateTest(bool directMode) { MaxItemCount = 1, MaxConcurrency = 1, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = false, })) { while (feedIterator.HasMoreResults) @@ -271,9 +269,7 @@ public async Task QueryRequestRateTest(bool directMode) { MaxItemCount = 1, MaxConcurrency = 1, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = false, }); // First request should be a success @@ -803,7 +799,6 @@ public async Task TesOdeTokenCompatibilityWithNonOdePipeline() QueryRequestOptions queryRequestOptions = new QueryRequestOptions { MaxItemCount = 50, - EnableOptimisticDirectExecution = true }; FeedIteratorInternal feedIterator = @@ -833,7 +828,7 @@ public async Task TesOdeTokenCompatibilityWithNonOdePipeline() responseMessage = await feedIteratorNew.ReadNextAsync(CancellationToken.None); } - string expectedErrorMessage = "The continuation token supplied requires the Optimistic Direct Execution flag to be enabled in QueryRequestOptions for the query execution to resume. "; + string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. "; Assert.IsTrue(responseMessage.CosmosException.ToString().Contains(expectedErrorMessage)); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs index 241b60fb7f..7931bc607a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosGatewayTimeoutTests.cs @@ -83,9 +83,8 @@ public async Task QueryPlanRetryTimeoutTestAsync() QueryRequestOptions requestOptions = new QueryRequestOptions() { -#if PREVIEW + // ODE set to false in this scenario as using ODE could cause the query plan to not get invoked. EnableOptimisticDirectExecution = false -#endif }; using FeedIterator iterator = gatewayQueryPlanContainer.GetItemQueryIterator("select * From T order by T.status", requestOptions: requestOptions); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs index c76110f1fb..e967f495a6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemSessionTokenTests.cs @@ -302,181 +302,185 @@ public async Task NoSessionTokenCaptureForThrottledUpsertRequestsTest() [TestMethod] public async Task InvalidSessionTokenAfterContainerRecreationAndCollectionCacheRefreshReproTest() { - // ingestionClinet is dedicated client simulating the writes / container recreation in - // the separate process - like Spark job - using CosmosClient ingestionClient = TestCommon.CreateCosmosClient(); - Cosmos.Database ingestionDatabase = ingestionClient.GetDatabase(this.database.Id); - - ContainerProperties multiPartitionContainerSettings = - new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk"); - Container ingestionContainer = - await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); - - const int itemCountToBeIngested = 10; - string pk = Guid.NewGuid().ToString("N"); - long? latestLsn = null; - Console.WriteLine("INGEST DOCUMENTS"); - for (int i = 0; i < itemCountToBeIngested; i++) + foreach (bool enableODE in new bool[] { false, true }) { - ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); - testItem.pk = pk; - - ItemResponse response = - await ingestionContainer.CreateItemAsync(item: testItem); - Assert.IsNotNull(response); - Assert.IsNotNull(response.Resource); - Assert.IsNotNull(response.Diagnostics); - long? lsnAfterCreate = await GetLSNFromSessionContainer( - ingestionContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterCreate); - Assert.IsTrue(latestLsn == null || lsnAfterCreate.Value > latestLsn.Value); - latestLsn = lsnAfterCreate; - CosmosTraceDiagnostics diagnostics = (CosmosTraceDiagnostics)response.Diagnostics; - Assert.IsFalse(diagnostics.IsGoneExceptionHit()); - Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString())); - Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero); - } + // ingestionClient is dedicated client simulating the writes / container recreation in + // the separate process - like Spark job + using CosmosClient ingestionClient = TestCommon.CreateCosmosClient(); + Cosmos.Database ingestionDatabase = ingestionClient.GetDatabase(this.database.Id); + + ContainerProperties multiPartitionContainerSettings = + new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk"); + Container ingestionContainer = + await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); + + const int itemCountToBeIngested = 10; + string pk = Guid.NewGuid().ToString("N"); + long? latestLsn = null; + Console.WriteLine("INGEST DOCUMENTS"); + for (int i = 0; i < itemCountToBeIngested; i++) + { + ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity(); + testItem.pk = pk; - // Dedciated query client used only for queries simulating the customer's app - string lastRequestedSessionToken = null; - Container queryContainer = TransportClientHelper.GetContainerWithIntercepter( - this.database.Id, - ingestionContainer.Id, - (uri, operation, request) => + ItemResponse response = + await ingestionContainer.CreateItemAsync(item: testItem); + Assert.IsNotNull(response); + Assert.IsNotNull(response.Resource); + Assert.IsNotNull(response.Diagnostics); + long? lsnAfterCreate = await GetLSNFromSessionContainer( + ingestionContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterCreate); + Assert.IsTrue(latestLsn == null || lsnAfterCreate.Value > latestLsn.Value); + latestLsn = lsnAfterCreate; + CosmosTraceDiagnostics diagnostics = (CosmosTraceDiagnostics)response.Diagnostics; + Assert.IsFalse(diagnostics.IsGoneExceptionHit()); + Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString())); + Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero); + } + + // Dedciated query client used only for queries simulating the customer's app + string lastRequestedSessionToken = null; + Container queryContainer = TransportClientHelper.GetContainerWithIntercepter( + this.database.Id, + ingestionContainer.Id, + (uri, operation, request) => + { + if (request.ResourceType == ResourceType.Document && + request.OperationType == OperationType.Query) + { + lastRequestedSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + } + }, + false, + null); + + long? lsnAfterQueryOnOldContainer = null; + + // Issueing two queries - first won't use session tokens yet + // second will provide session tokens captured from first request in the request to the backend + for (int i = 0; i < 2; i++) { - if (request.ResourceType == ResourceType.Document && - request.OperationType == OperationType.Query) + Console.WriteLine("RUN QUERY ON OLD CONTAINER ({0})", i); + using FeedIterator queryIteratorOldContainer = queryContainer.GetItemQueryIterator( + new QueryDefinition("Select c.id FROM c"), + continuationToken: null, + new QueryRequestOptions + { + ConsistencyLevel = Cosmos.ConsistencyLevel.Session, + PartitionKey = new Cosmos.PartitionKey(pk), + EnableOptimisticDirectExecution = enableODE + }); + int itemCountOldContainer = 0; + while (queryIteratorOldContainer.HasMoreResults) { - lastRequestedSessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + FeedResponse response = await queryIteratorOldContainer.ReadNextAsync(); + if(i == 0) + { + string diagnosticString = response.Diagnostics.ToString(); + Assert.IsTrue(diagnosticString.Contains("PKRangeCache Info(")); + JObject diagnosticJobject = JObject.Parse(diagnosticString); + + JToken actualToken = diagnosticJobject.SelectToken(enableODE ? + "$.children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data" : + "$.children[0].children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data"); + JToken actualNode = actualToken.Children().First().First(); + + Assert.IsTrue(actualNode["Previous Continuation Token"].ToString().Length == 0); + Assert.IsTrue(actualNode["Continuation Token"].ToString().Length > 0); + } + + itemCountOldContainer += response.Count; } - }, - false, - null); - long? lsnAfterQueryOnOldContainer = null; + Assert.AreEqual(itemCountToBeIngested, itemCountOldContainer); + lsnAfterQueryOnOldContainer = await GetLSNFromSessionContainer( + queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterQueryOnOldContainer); + Assert.AreEqual(latestLsn.Value, lsnAfterQueryOnOldContainer.Value); + if (i == 0) + { + Assert.IsNull(lastRequestedSessionToken); + } + else + { + Assert.IsNotNull(lastRequestedSessionToken); + Assert.AreEqual(latestLsn.Value, SessionTokenHelper.Parse(lastRequestedSessionToken).LSN); + } + } - // Issueing two queries - first won't use session tokens yet - // second will provide session tokens captured from first request in the request to the backend - for (int i = 0; i < 2; i++) - { - Console.WriteLine("RUN QUERY ON OLD CONTAINER ({0})", i); - using FeedIterator queryIteratorOldContainer = queryContainer.GetItemQueryIterator( + Console.WriteLine( + "DELETE CONTAINER {0}", + (await queryContainer.ReadContainerAsync()).Resource.ResourceId); + await ingestionContainer.DeleteContainerAsync(); + + Console.WriteLine("RECREATING CONTAINER..."); + ContainerResponse ingestionContainerResponse = + await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); + ingestionContainer = ingestionContainerResponse.Container; + + string responseSessionTokenValue = + ingestionContainerResponse.Headers[HttpConstants.HttpHeaders.SessionToken]; + long? lsnAfterRecreatingContainerFromIngestionClient = responseSessionTokenValue != null ? + SessionTokenHelper.Parse(responseSessionTokenValue).LSN : null; + Console.WriteLine( + "RECREATED CONTAINER with new CollectionRid: {0} - LSN: {1}", + ingestionContainerResponse.Resource.ResourceId, + lsnAfterRecreatingContainerFromIngestionClient); + + // validates that the query container still uses the LSN captured from the old LSN + long? lsnAfterCreatingNewContainerFromQueryClient = await GetLSNFromSessionContainer( + queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); + Assert.IsNotNull(lsnAfterCreatingNewContainerFromQueryClient); + Assert.AreEqual(latestLsn.Value, lsnAfterCreatingNewContainerFromQueryClient.Value); + + Console.WriteLine("GET FEED RANGES"); + // this will force a CollectionCache refresh - because no pk ranegs can be identified + // for the old container anymore + _ = await queryContainer.GetFeedRangesAsync(); + + + Console.WriteLine("RUN QUERY ON NEW CONTAINER"); + int itemCountNewContainer = 0; + using FeedIterator queryIteratorNewContainer = queryContainer.GetItemQueryIterator( new QueryDefinition("Select c.id FROM c"), continuationToken: null, new QueryRequestOptions { ConsistencyLevel = Cosmos.ConsistencyLevel.Session, PartitionKey = new Cosmos.PartitionKey(pk), -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif }); - int itemCountOldContainer = 0; - while (queryIteratorOldContainer.HasMoreResults) + Console.WriteLine("Query iterator created"); + while (queryIteratorNewContainer.HasMoreResults) { - FeedResponse response = await queryIteratorOldContainer.ReadNextAsync(); - if(i == 0) + Console.WriteLine("Retrieving first page"); + try + { + FeedResponse response = await queryIteratorNewContainer.ReadNextAsync(); + Console.WriteLine("Request Diagnostics for query against new container: {0}", + response.Diagnostics.ToString()); + itemCountNewContainer += response.Count; + } + catch (CosmosException cosmosException) { - string diagnosticString = response.Diagnostics.ToString(); - Assert.IsTrue(diagnosticString.Contains("PKRangeCache Info(")); - JObject diagnosticJobject = JObject.Parse(diagnosticString); - JToken actualToken = diagnosticJobject.SelectToken("$.children[0].children[?(@.name=='Get Partition Key Ranges')].children[?(@.name=='Try Get Overlapping Ranges')].data"); - JToken actualNode = actualToken.Children().First().First(); - - Assert.IsTrue(actualNode["Previous Continuation Token"].ToString().Length == 0); - Assert.IsTrue(actualNode["Continuation Token"].ToString().Length > 0); + Console.WriteLine("COSMOS EXCEPTION: {0}", cosmosException); + throw; } - - itemCountOldContainer += response.Count; } - Assert.AreEqual(itemCountToBeIngested, itemCountOldContainer); - lsnAfterQueryOnOldContainer = await GetLSNFromSessionContainer( + Assert.AreEqual(0, itemCountNewContainer); + long? lsnAfterQueryOnNewContainer = await GetLSNFromSessionContainer( queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterQueryOnOldContainer); - Assert.AreEqual(latestLsn.Value, lsnAfterQueryOnOldContainer.Value); - if (i == 0) - { - Assert.IsNull(lastRequestedSessionToken); - } - else - { - Assert.IsNotNull(lastRequestedSessionToken); - Assert.AreEqual(latestLsn.Value, SessionTokenHelper.Parse(lastRequestedSessionToken).LSN); - } - } - - Console.WriteLine( - "DELETE CONTAINER {0}", - (await queryContainer.ReadContainerAsync()).Resource.ResourceId); - await ingestionContainer.DeleteContainerAsync(); - - Console.WriteLine("RECREATING CONTAINER..."); - ContainerResponse ingestionContainerResponse = - await ingestionDatabase.CreateContainerAsync(multiPartitionContainerSettings); - ingestionContainer = ingestionContainerResponse.Container; - - string responseSessionTokenValue = - ingestionContainerResponse.Headers[HttpConstants.HttpHeaders.SessionToken]; - long? lsnAfterRecreatingContainerFromIngestionClient = responseSessionTokenValue != null ? - SessionTokenHelper.Parse(responseSessionTokenValue).LSN : null; - Console.WriteLine( - "RECREATED CONTAINER with new CollectionRid: {0} - LSN: {1}", - ingestionContainerResponse.Resource.ResourceId, - lsnAfterRecreatingContainerFromIngestionClient); - - // validates that the query container still uses the LSN captured from the old LSN - long? lsnAfterCreatingNewContainerFromQueryClient = await GetLSNFromSessionContainer( - queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterCreatingNewContainerFromQueryClient); - Assert.AreEqual(latestLsn.Value, lsnAfterCreatingNewContainerFromQueryClient.Value); - - Console.WriteLine("GET FEED RANGES"); - // this will force a CollectionCache refresh - because no pk ranegs can be identified - // for the old container anymore - _ = await queryContainer.GetFeedRangesAsync(); - - - Console.WriteLine("RUN QUERY ON NEW CONTAINER"); - int itemCountNewContainer = 0; - using FeedIterator queryIteratorNewContainer = queryContainer.GetItemQueryIterator( - new QueryDefinition("Select c.id FROM c"), - continuationToken: null, - new QueryRequestOptions - { - ConsistencyLevel = Cosmos.ConsistencyLevel.Session, - PartitionKey = new Cosmos.PartitionKey(pk), - }); - Console.WriteLine("Query iterator created"); - while (queryIteratorNewContainer.HasMoreResults) - { - Console.WriteLine("Retrieving first page"); - try - { - FeedResponse response = await queryIteratorNewContainer.ReadNextAsync(); - Console.WriteLine("Request Diagnostics for query against new container: {0}", - response.Diagnostics.ToString()); - itemCountNewContainer += response.Count; - } - catch (CosmosException cosmosException) - { - Console.WriteLine("COSMOS EXCEPTION: {0}", cosmosException); - throw; - } + Assert.IsNotNull(lsnAfterQueryOnNewContainer); + Assert.IsTrue( + lastRequestedSessionToken == null || + SessionTokenHelper.Parse(lastRequestedSessionToken).LSN == + lsnAfterRecreatingContainerFromIngestionClient, + $"The requested session token {lastRequestedSessionToken} on the last query request should be null " + + $"or have LSN '{lsnAfterRecreatingContainerFromIngestionClient}' (which is the LSN after " + + "re-creating the container) if the session cache or the new CollectionName to Rid mapping was " + + "correctly populated in the SessionCache."); } - - Assert.AreEqual(0, itemCountNewContainer); - long? lsnAfterQueryOnNewContainer = await GetLSNFromSessionContainer( - queryContainer, multiPartitionContainerSettings, new PartitionKey(pk)); - Assert.IsNotNull(lsnAfterQueryOnNewContainer); - Assert.IsTrue( - lastRequestedSessionToken == null || - SessionTokenHelper.Parse(lastRequestedSessionToken).LSN == - lsnAfterRecreatingContainerFromIngestionClient, - $"The requested session token {lastRequestedSessionToken} on the last query request should be null " + - $"or have LSN '{lsnAfterRecreatingContainerFromIngestionClient}' (which is the LSN after " + - "re-creating the container) if the session cache or the new CollectionName to Rid mapping was " + - "correctly populated in the SessionCache."); } private static async Task GetPKRangeIdForPartitionKey( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs index eadb62da7c..09e3ccfa0f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosJsonSerializerTests.cs @@ -94,48 +94,64 @@ public async Task TestQueryWithCustomJsonSerializer() Assert.AreEqual(1, toStreamCount, "parameter should use custom serializer"); Assert.AreEqual(0, fromStreamCount); - toStreamCount = 0; - fromStreamCount = 0; - - FeedIterator itemIterator = container.GetItemQueryIterator( - query -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - List items = new List(); - while (itemIterator.HasMoreResults) + foreach (bool enableODE in new bool[] { false, true }) { - items.AddRange(await itemIterator.ReadNextAsync()); - } - - Assert.AreEqual(2, toStreamCount); - Assert.AreEqual(1, fromStreamCount); - - toStreamCount = 0; - fromStreamCount = 0; + toStreamCount = 0; + fromStreamCount = 0; + + FeedIterator itemIterator = container.GetItemQueryIterator( + query, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + List items = new List(); + while (itemIterator.HasMoreResults) + { + items.AddRange(await itemIterator.ReadNextAsync()); + } - // Verify that the custom serializer is actually being used via stream - FeedIterator itemStreamIterator = container.GetItemQueryStreamIterator( - query -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - while (itemStreamIterator.HasMoreResults) - { - ResponseMessage response = await itemStreamIterator.ReadNextAsync(); - using (StreamReader reader = new StreamReader(response.Content)) + // The toStreamCount variable will differ between ODE and non-ODE pipelines due to the non-ODE pipelines needing to get the query plan which makes an additional serialization call during its initialization. + if (enableODE) { - string content = await reader.ReadToEndAsync(); - Assert.IsTrue(content.Contains("9001.42")); - Assert.IsFalse(content.Contains("description"), "Description should be ignored and not in the JSON"); + Assert.AreEqual(1, toStreamCount); + } + else + { + Assert.AreEqual(2, toStreamCount); + } + + Assert.AreEqual(1, fromStreamCount); + + toStreamCount = 0; + fromStreamCount = 0; + + // Verify that the custom serializer is actually being used via stream + FeedIterator itemStreamIterator = container.GetItemQueryStreamIterator( + query, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + while (itemStreamIterator.HasMoreResults) + { + ResponseMessage response = await itemStreamIterator.ReadNextAsync(); + using (StreamReader reader = new StreamReader(response.Content)) + { + string content = await reader.ReadToEndAsync(); + Assert.IsTrue(content.Contains("9001.42")); + Assert.IsFalse(content.Contains("description"), "Description should be ignored and not in the JSON"); + } } - } - Assert.AreEqual(2, toStreamCount); - Assert.AreEqual(0, fromStreamCount); + // The toStreamCount variable will differ between ODE and non-ODE pipelines due to the non-ODE pipelines needing to get the query plan which makes an additional serialization call during its initialization. + if (enableODE) + { + Assert.AreEqual(1, toStreamCount); + } + else + { + Assert.AreEqual(2, toStreamCount); + } + Assert.AreEqual(0, fromStreamCount); + } } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs index 5307145dfc..01e1fc5c66 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosMultiHashTest.cs @@ -447,64 +447,68 @@ public async Task MultiHashQueryItemTest() doc.SetValue("Type", "Goverment"); documents[2] = await this.container.CreateItemAsync(doc); - //Query - foreach (Document document in documents) + foreach (bool odeEnabled in new bool[] { false, true }) { - pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Add(document.GetPropertyValue("City")) - .Build(); - - badPKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("City")) - .Build(); - - String query = $"SELECT * from c where c.id = \"{document.GetPropertyValue("id")}\""; - - using (FeedIterator feedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = pKey })) + //Query + foreach (Document document in documents) { - Assert.IsTrue(feedIterator.HasMoreResults); + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Add(document.GetPropertyValue("City")) + .Build(); - FeedResponse queryDoc = await feedIterator.ReadNextAsync(); - queryDoc.First(); - Assert.IsTrue(queryDoc.Count == 1); - feedIterator.Dispose(); - } + badPKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("City")) + .Build(); - //Using an incomplete partition key with prefix of PK path definition - pKey = new PartitionKeyBuilder() - .Add(document.GetPropertyValue("ZipCode")) - .Build(); - using (FeedIterator feedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = pKey })) - { - Assert.IsTrue(feedIterator.HasMoreResults); + String query = $"SELECT * from c where c.id = \"{document.GetPropertyValue("id")}\""; - FeedResponse queryDoc = await feedIterator.ReadNextAsync(); - queryDoc.First(); - Assert.IsTrue(queryDoc.Count == 1); - feedIterator.Dispose(); - } + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); - //Negative test - using incomplete partition key - using (FeedIterator badFeedIterator = this.container.GetItemQueryIterator( - query, - null, - new QueryRequestOptions() { PartitionKey = badPKey})) - { - FeedResponse queryDocBad = await badFeedIterator.ReadNextAsync(); - Assert.ThrowsException(() => - queryDocBad.First() - ); - badFeedIterator.Dispose(); + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + Document retrievedDocument = queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + Assert.AreEqual(document.Id, retrievedDocument.Id); + feedIterator.Dispose(); + } + + //Using an incomplete partition key with prefix of PK path definition + pKey = new PartitionKeyBuilder() + .Add(document.GetPropertyValue("ZipCode")) + .Build(); + using (FeedIterator feedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = pKey })) + { + Assert.IsTrue(feedIterator.HasMoreResults); + + FeedResponse queryDoc = await feedIterator.ReadNextAsync(); + Document retrievedDocument = queryDoc.First(); + Assert.IsTrue(queryDoc.Count == 1); + Assert.AreEqual(document.Id, retrievedDocument.Id); + feedIterator.Dispose(); + } + + //Negative test - using incomplete partition key + using (FeedIterator badFeedIterator = this.container.GetItemQueryIterator( + query, + null, + new QueryRequestOptions() { EnableOptimisticDirectExecution = odeEnabled, PartitionKey = badPKey })) + { + FeedResponse queryDocBad = await badFeedIterator.ReadNextAsync(); + Assert.ThrowsException(() => + queryDocBad.First() + ); + badFeedIterator.Dispose(); + } } } } - } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs index ce9723e7ee..a5652e1010 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/QueryFeedTokenTests.cs @@ -98,19 +98,19 @@ public async Task InexistentPKRangeId() string feedRangeSerialization = JsonConvert.SerializeObject(new { PKRangeId = "10" }); FeedRange feedRange = FeedRange.FromJsonString(feedRangeSerialization); - FeedIterator feedIterator = container.GetItemQueryIterator( - queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), - feedRange: feedRange, - continuationToken: null - -#if PREVIEW - , requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = false } -#endif - ); - - CosmosException exception = await Assert.ThrowsExceptionAsync(() => feedIterator.ReadNextAsync()); - Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); - Assert.AreEqual((int)Documents.SubStatusCodes.PartitionKeyRangeGone, exception.SubStatusCode); + foreach (bool enableODE in new bool[] { false, true }) + { + FeedIterator feedIterator = container.GetItemQueryIterator( + queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), + feedRange: feedRange, + continuationToken: null, + requestOptions: new QueryRequestOptions() { EnableOptimisticDirectExecution = enableODE } + ); + + CosmosException exception = await Assert.ThrowsExceptionAsync(() => feedIterator.ReadNextAsync()); + Assert.AreEqual(HttpStatusCode.Gone, exception.StatusCode); + Assert.AreEqual((int)Documents.SubStatusCodes.PartitionKeyRangeGone, exception.SubStatusCode); + } } finally { @@ -151,65 +151,68 @@ public async Task ParallelizeQueryThroughTokens() Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); - List>> tasks = feedTokens.Select(async feedToken => + foreach (bool enableODE in new bool[] { false, true }) { - List results = new List(); - FeedIteratorInternal feedIterator = container.GetItemQueryStreamIterator( - queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), - feedRange: feedToken, - continuationToken: null, - requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }) as FeedIteratorInternal; - string continuation = null; - while (feedIterator.HasMoreResults) + List>> tasks = feedTokens.Select(async feedToken => { - using (ResponseMessage responseMessage = - await feedIterator.ReadNextAsync(this.cancellationToken)) + List results = new List(); + FeedIteratorInternal feedIterator = container.GetItemQueryStreamIterator( + queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), + feedRange: feedToken, + continuationToken: null, + requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }) as FeedIteratorInternal; + string continuation = null; + while (feedIterator.HasMoreResults) { - if (responseMessage.IsSuccessStatusCode) + using (ResponseMessage responseMessage = + await feedIterator.ReadNextAsync(this.cancellationToken)) { - using (StreamReader reader = new StreamReader(responseMessage.Content)) + if (responseMessage.IsSuccessStatusCode) { - string json = await reader.ReadToEndAsync(); - JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); - foreach(JObject document in documents) + using (StreamReader reader = new StreamReader(responseMessage.Content)) { - results.Add(document.SelectToken("id").ToString()); + string json = await reader.ReadToEndAsync(); + JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); + foreach (JObject document in documents) + { + results.Add(document.SelectToken("id").ToString()); + } } } - } - continuation = responseMessage.ContinuationToken; - break; + continuation = responseMessage.ContinuationToken; + break; + } } - } - feedIterator = container.GetItemQueryStreamIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }) as FeedIteratorInternal; - while (feedIterator.HasMoreResults) - { - using (ResponseMessage responseMessage = - await feedIterator.ReadNextAsync(this.cancellationToken)) + feedIterator = container.GetItemQueryStreamIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }) as FeedIteratorInternal; + while (feedIterator.HasMoreResults) { - if (responseMessage.IsSuccessStatusCode) + using (ResponseMessage responseMessage = + await feedIterator.ReadNextAsync(this.cancellationToken)) { - using (StreamReader reader = new StreamReader(responseMessage.Content)) + if (responseMessage.IsSuccessStatusCode) { - string json = await reader.ReadToEndAsync(); - JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); - foreach (JObject document in documents) + using (StreamReader reader = new StreamReader(responseMessage.Content)) { - results.Add(document.SelectToken("id").ToString()); + string json = await reader.ReadToEndAsync(); + JArray documents = (JArray)JObject.Parse(json).SelectToken("Documents"); + foreach (JObject document in documents) + { + results.Add(document.SelectToken("id").ToString()); + } } } } } - } - return results; - }).ToList(); + return results; + }).ToList(); - await Task.WhenAll(tasks); + await Task.WhenAll(tasks); - CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + } } finally { @@ -250,39 +253,42 @@ public async Task ParallelizeQueryThroughTokens_OfT() Assert.IsTrue(feedTokens.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); - List>> tasks = feedTokens.Select(async feedToken => + foreach (bool enableODE in new bool[] { false, true }) { - List results = new List(); - FeedIterator feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); - string continuation = null; - while (feedIterator.HasMoreResults) + List>> tasks = feedTokens.Select(async feedToken => { - FeedResponse response = await feedIterator.ReadNextAsync(); - foreach (ToDoActivity toDoActivity in response) + List results = new List(); + FeedIterator feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }); + string continuation = null; + while (feedIterator.HasMoreResults) { - results.Add(toDoActivity.id); - } + FeedResponse response = await feedIterator.ReadNextAsync(); + foreach (ToDoActivity toDoActivity in response) + { + results.Add(toDoActivity.id); + } - continuation = response.ContinuationToken; - break; - } + continuation = response.ContinuationToken; + break; + } - feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10 }); - while (feedIterator.HasMoreResults) - { - FeedResponse response = await feedIterator.ReadNextAsync(); - foreach (ToDoActivity toDoActivity in response) + feedIterator = container.GetItemQueryIterator(queryDefinition: new QueryDefinition("select * from T where STARTSWITH(T.id, \"BasicItem\")"), feedRange: feedToken, continuationToken: continuation, requestOptions: new QueryRequestOptions() { MaxItemCount = 10, EnableOptimisticDirectExecution = enableODE }); + while (feedIterator.HasMoreResults) { - results.Add(toDoActivity.id); + FeedResponse response = await feedIterator.ReadNextAsync(); + foreach (ToDoActivity toDoActivity in response) + { + results.Add(toDoActivity.id); + } } - } - return results; - }).ToList(); + return results; + }).ToList(); - await Task.WhenAll(tasks); + await Task.WhenAll(tasks); - CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + CollectionAssert.AreEquivalent(generatedIds, tasks.SelectMany(t => t.Result).ToList()); + } } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 8cc819014a..815de90537 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -311,12 +311,7 @@ public static Func> GenerateTestCosmosData(Func query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -353,12 +348,7 @@ public static Func> GenerateSerializationTestCosmosData(F } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); @@ -540,12 +530,7 @@ public static Func> GenerateSimpleCosmosData(Cosmos.Datab } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -591,32 +576,52 @@ public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResu } public static string BuildExceptionMessageForTest(Exception ex) - { - StringBuilder message = new StringBuilder(); + { + StringBuilder message = new StringBuilder(); do { if (ex is CosmosException cosmosException) - { - message.Append($"Status Code: {cosmosException.StatusCode}"); + { + // ODE scenario: The backend generates an error response message with significant variations when compared to the Service Interop which gets called in the Non ODE scenario. + // The objective is to standardize and normalize the backend response for consistency. + Match match = Regex.Match(ex.Message, @"Reason:(.*?}]})", RegexOptions.IgnoreCase); + Match requestURIMatch = Regex.Match(ex.Message, @"Request URI", RegexOptions.IgnoreCase); + if (match.Success && requestURIMatch.Success) + { + string reason = match.Groups[1].Value; + reason = reason.Replace("\\", ""); + + string transformedString = "Status Code: " + reason; + transformedString = transformedString.Replace(" (", ""); + transformedString = transformedString.Replace("{\"code\":\"", ""); + transformedString = transformedString.Replace("\",\"message\":\"Message: {\"errors\":[", ",{\"errors\":["); + transformedString = transformedString.Replace("}]}", "}]},0x800A0B00"); + + return transformedString; + } + else + { + message.Append($"Status Code: {cosmosException.StatusCode}"); + } } else if (ex is DocumentClientException documentClientException) { message.Append(documentClientException.RawErrorMessage); } else - { - message.Append(ex.Message); + { + message.Append(ex.Message); } - + ex = ex.InnerException; if (ex != null) { message.Append(","); } } - while (ex != null); - - return message.ToString(); + while (ex != null); + + return message.ToString(); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs index f13a92da82..58aef32721 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs @@ -1219,12 +1219,7 @@ public void TestSelectTop() Tuple> generatedData = this.CreateDataTestSelectTop(); int seed = generatedData.Item1; List data = generatedData.Item2; - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); IOrderedQueryable query = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); Func> getQuery = useQuery => useQuery ? query : data.AsQueryable(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs index d60f76f92c..d06fdc84d7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/AggregateQueryTests.cs @@ -14,7 +14,6 @@ using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; using Newtonsoft.Json.Linq; [TestClass] @@ -62,66 +61,87 @@ await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct | ConnectionModes.Gateway, CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, documents, - ImplementationAsync, + NonOdeImplementationAsync, args, "/" + args.PartitionKey); - async Task ImplementationAsync( + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition, + documents, + OdeImplementationAsync, + args, + "/" + args.PartitionKey); + + async Task NonOdeImplementationAsync( Container container, IReadOnlyList inputDocuments, AggregateTestArgs aggregateTestArgs) { - IReadOnlyList documentsWherePkIsANumber = inputDocuments - .Where(doc => - { - return double.TryParse( - doc[aggregateTestArgs.PartitionKey].ToString(), - out double result); - }) - .ToList(); - double numberSum = documentsWherePkIsANumber - .Sum(doc => + AggregateQueryArguments[] aggregateQueryArgumentsList = CreateAggregateQueryArguments(inputDocuments, aggregateTestArgs); + foreach (int maxDoP in new[] { 0, 10 }) + { + foreach (AggregateQueryArguments argument in aggregateQueryArgumentsList) { - if (!doc.TryGetValue(aggregateTestArgs.PartitionKey, out CosmosNumber number)) + string[] queryFormats = new[] { - Assert.Fail("Failed to get partition key from document"); - } + "SELECT VALUE {0}(r.{1}) FROM r WHERE {2}", + "SELECT VALUE {0}(r.{1}) FROM r WHERE {2} ORDER BY r.{1}" + }; - return Number64.ToDouble(number.Value); - }); - double count = documentsWherePkIsANumber.Count(); - AggregateQueryArguments[] aggregateQueryArgumentsList = new AggregateQueryArguments[] - { - new AggregateQueryArguments( - aggregateOperator: "AVG", - expectedValue: CosmosNumber64.Create(numberSum / count), - predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), - new AggregateQueryArguments( - aggregateOperator: "AVG", - expectedValue: CosmosUndefined.Create(), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "COUNT", - expectedValue: CosmosNumber64.Create(documents.Count()), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "MAX", - expectedValue: CosmosString.Create("xyz"), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "MIN", - expectedValue: CosmosBoolean.Create(false), - predicate: "true"), - new AggregateQueryArguments( - aggregateOperator: "SUM", - expectedValue: CosmosNumber64.Create(numberSum), - predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), - new AggregateQueryArguments( - aggregateOperator: "SUM", - expectedValue: CosmosUndefined.Create(), - predicate: $"true"), - }; + foreach (string queryFormat in queryFormats) + { + string query = string.Format( + CultureInfo.InvariantCulture, + queryFormat, + argument.AggregateOperator, + aggregateTestArgs.PartitionKey, + argument.Predicate); + string message = string.Format( + CultureInfo.InvariantCulture, + "query: {0}, data: {1}", + query, + argument.ToString()); + + List items = await QueryTestsBase.RunQueryAsync( + container, + query, + new QueryRequestOptions() + { + MaxConcurrency = maxDoP, + EnableOptimisticDirectExecution = false + }); + if (argument.ExpectedValue == null) + { + Assert.AreEqual(0, items.Count, message); + } + else + { + Assert.AreEqual(1, items.Count, message); + CosmosElement expected = argument.ExpectedValue; + CosmosElement actual = items.Single(); + + if ((expected is CosmosNumber expectedNumber) && (actual is CosmosNumber actualNumber)) + { + Assert.AreEqual(Number64.ToDouble(expectedNumber.Value), Number64.ToDouble(actualNumber.Value), .01); + } + else + { + Assert.AreEqual(expected, actual, message); + } + } + } + } + } + } + + async Task OdeImplementationAsync( + Container container, + IReadOnlyList inputDocuments, + AggregateTestArgs aggregateTestArgs) + { + AggregateQueryArguments[] aggregateQueryArgumentsList = CreateAggregateQueryArguments(inputDocuments, aggregateTestArgs); foreach (int maxDoP in new[] { 0, 10 }) { foreach (AggregateQueryArguments argument in aggregateQueryArgumentsList) @@ -152,12 +172,10 @@ async Task ImplementationAsync( new QueryRequestOptions() { MaxConcurrency = maxDoP, -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif + EnableOptimisticDirectExecution = true }); - if (argument.ExpectedValue == null) + if (argument.ExpectedValue == CosmosUndefined.Create()) { Assert.AreEqual(0, items.Count, message); } @@ -182,6 +200,64 @@ async Task ImplementationAsync( } } + private static AggregateQueryArguments[] CreateAggregateQueryArguments( + IReadOnlyList inputDocuments, + AggregateTestArgs aggregateTestArgs) + { + IReadOnlyList documentsWherePkIsANumber = inputDocuments + .Where(doc => + { + return double.TryParse( + doc[aggregateTestArgs.PartitionKey].ToString(), + out double result); + }) + .ToList(); + double numberSum = documentsWherePkIsANumber + .Sum(doc => + { + if (!doc.TryGetValue(aggregateTestArgs.PartitionKey, out CosmosNumber number)) + { + Assert.Fail("Failed to get partition key from document"); + } + + return Number64.ToDouble(number.Value); + }); + double count = documentsWherePkIsANumber.Count(); + AggregateQueryArguments[] aggregateQueryArgumentsList = new AggregateQueryArguments[] + { + new AggregateQueryArguments( + aggregateOperator: "AVG", + expectedValue: CosmosNumber64.Create(numberSum / count), + predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), + new AggregateQueryArguments( + aggregateOperator: "AVG", + expectedValue: CosmosUndefined.Create(), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "COUNT", + expectedValue: CosmosNumber64.Create(inputDocuments.Count()), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "MAX", + expectedValue: CosmosString.Create("xyz"), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "MIN", + expectedValue: CosmosBoolean.Create(false), + predicate: "true"), + new AggregateQueryArguments( + aggregateOperator: "SUM", + expectedValue: CosmosNumber64.Create(numberSum), + predicate: $"IS_NUMBER(r.{aggregateTestArgs.PartitionKey})"), + new AggregateQueryArguments( + aggregateOperator: "SUM", + expectedValue: CosmosUndefined.Create(), + predicate: $"true"), + }; + + return aggregateQueryArgumentsList; + } + private readonly struct AggregateTestArgs { public AggregateTestArgs( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 2074902249..48ae5d4464 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -538,9 +538,6 @@ static async Task ImplementationAsync(Container container, IReadOnlyList { foreach (Cosmos.PartitionKey? partitionKey in new Cosmos.PartitionKey?[] { new Cosmos.PartitionKey(5), default }) { + // ODE is set to false to allow for the testing of other pipelines in single partition scenarios QueryRequestOptions feedOptions = new QueryRequestOptions { MaxBufferedItemCount = 7000, MaxConcurrency = maxDegreeOfParallelism, MaxItemCount = maxItemCount, -#if PREVIEW EnableOptimisticDirectExecution = false -#endif }; async Task> AssertPassthroughAsync(string query, Cosmos.PartitionKey? pk = default) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs index 6cd8905b07..923f892fa7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/EndToEndTraceWriterBaselineTests.cs @@ -484,12 +484,7 @@ public async Task ChangeFeedAsync() public async Task QueryAsync() { List inputs = new List(); - QueryRequestOptions requestOptions = new QueryRequestOptions() - { -#if PREVIEW - EnableOptimisticDirectExecution = false -#endif - }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); int startLineNumber; int endLineNumber; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index 8e45a72922..3b597d3367 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -4,28 +4,28 @@ "MockedItemBenchmark.CreateItem;[Type=OfT]": 36356, "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 36362, "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 36359.5, - "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 57472.25, - "MockedItemBenchmark.CreateItem;[Type=Stream]": 24673.25, - "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 32308.5, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 32328, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 32321.25, - "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 53231.25, - "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 24696, + "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 58900.5, + "MockedItemBenchmark.CreateItem;[Type=Stream]": 25212.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 33015.25, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTCustom]": 33007.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 33015.75, + "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 54402.75, + "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 25229.25, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42172.5, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 42174.75, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 42166.5, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338, - "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 37610, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13342232, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13341058, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13355160, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13612338, + "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 38373.5, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 11988727, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 11988284.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 11988606.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 12198686.5, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithClientTelemetryEnabled]": 2244658, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2310842, - "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 1005038, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTWithDiagnosticsToString]": 2251235.75, + "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=Stream]": 978459.25, "MockedItemBenchmark.ReadFeed;[Type=OfT]": 560692, "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716, "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25, @@ -44,13 +44,13 @@ "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 36587.25, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 57649, - "MockedItemBenchmark.UpdateItem;[Type=Stream]": 24894.75, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 59152, + "MockedItemBenchmark.UpdateItem;[Type=Stream]": 25428, "MockedItemBenchmark.UpsertItem;[Type=OfT]": 36577.25, "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 36583.75, "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 36578.5, - "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 57732.5, - "MockedItemBenchmark.UpsertItem;[Type=Stream]": 24878.5, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 59613, + "MockedItemBenchmark.UpsertItem;[Type=Stream]": 25445.5, "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168, "MockedItemBulkBenchmark.CreateItem;[Type=OfTCustom]": 1195808, "MockedItemBulkBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 1235418, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 94aae6155b..c102e8075e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -488,59 +488,8 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": { - "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "Boolean EnableOptimisticDirectExecution": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - } - }, + "Subclasses": {}, "Members": { "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index a336902647..9b73ab714a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6439,6 +6439,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -6593,6 +6605,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -7466,6 +7485,18 @@ "Microsoft.Azure.Cosmos.QueryRequestOptions;Microsoft.Azure.Cosmos.RequestOptions;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Boolean EnableOptimisticDirectExecution": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Boolean EnableOptimisticDirectExecution;CanRead:True;CanWrite:True;Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Boolean get_EnableOptimisticDirectExecution()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Boolean get_EnableOptimisticDirectExecution();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions": { "Type": "Property", "Attributes": [], @@ -7620,6 +7651,13 @@ ], "MethodInfo": "Void set_EnableLowPrecisionOrderBy(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_EnableOptimisticDirectExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_EnableOptimisticDirectExecution(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_EnableScanInQuery(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 840e6c3ccf..9582b754e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -150,14 +150,7 @@ public void NegativeOptimisticDirectExecutionOutput() public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); - bool odeExpectedValue = -#if PREVIEW - true; -#else - false; -#endif - - Assert.AreEqual(odeExpectedValue, requestOptions.EnableOptimisticDirectExecution); + Assert.AreEqual(true, requestOptions.EnableOptimisticDirectExecution); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index ce2d808304..97598ea59f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -270,11 +270,11 @@ public async Task OffsetLimitPageSize() DocumentContainer documentContainer = await CreateDocumentContainerAsync(documents, mockInMemoryContainer, numSplits: 4); // OFFSET/LIMIT with ORDER BY - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 315, expectedResults: 500, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 500, expectedResults: 500, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10000 LIMIT 5000", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 70, expectedResults: 100, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 65, expectedResults: 0, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 110, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 100, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); // OFFSET/LIMIT without ORDER BY await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 10 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); @@ -283,7 +283,7 @@ public async Task OffsetLimitPageSize() // TOP with ORDER BY await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c ORDER BY c.pk", expectedPageSize: 5, expectedResults: 5, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 100, expectedResults: 100, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); @@ -347,7 +347,6 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp string databaseId = "db1234"; string resourceLink = $"dbs/{databaseId}/colls"; - const string suffix = "-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF"; List partitionKeyRanges = new List @@ -366,7 +365,7 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp mockClient.Setup(x => x.GetTargetPartitionKeyRangesAsync( It.IsAny(), - It.IsAny(), + "HelloWorld", It.IsAny>>(), It.IsAny(), It.IsAny())) @@ -396,19 +395,48 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp ); CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: mockClient.Object, - resourceTypeEnum: Documents.ResourceType.Document, - operationType: Documents.OperationType.Query, - resourceType: typeof(QueryResponseCore), - resourceLink: resourceLink, - isContinuationExpected: true, - allowNonValueAggregateQuery: true, - useSystemPrefix: false, - correlatedActivityId: Guid.NewGuid()); + client: new TestCosmosQueryClient(GetQueryPartitionProvider()), + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); return Tuple.Create(inputParameters, cosmosQueryContextCore); } + internal static QueryPartitionProvider GetQueryPartitionProvider() + { + IDictionary DefaultQueryengineConfiguration = new Dictionary() + { + {"maxSqlQueryInputLength", 30720}, + {"maxJoinsPerSqlQuery", 5}, + {"maxLogicalAndPerSqlQuery", 200}, + {"maxLogicalOrPerSqlQuery", 200}, + {"maxUdfRefPerSqlQuery", 2}, + {"maxInExpressionItemsCount", 8000}, + {"queryMaxInMemorySortDocumentCount", 500}, + {"maxQueryRequestTimeoutFraction", 0.90}, + {"sqlAllowNonFiniteNumbers", false}, + {"sqlAllowAggregateFunctions", true}, + {"sqlAllowSubQuery", true}, + {"sqlAllowScalarSubQuery", false}, + {"allowNewKeywords", true}, + {"sqlAllowLike", true}, + {"sqlAllowGroupByClause", false}, + {"queryEnableMongoNativeRegex", true}, + {"maxSpatialQueryCells", 12}, + {"spatialMaxGeometryPointCount", 256}, + {"sqlDisableOptimizationFlags", 0}, + {"sqlEnableParameterExpansionCheck", true} + }; + + return new QueryPartitionProvider(DefaultQueryengineConfiguration); + } + internal static async Task> ExecuteQueryAsync( string query, IReadOnlyList documents, From f33b2afcd981469d70758e9345a72dae45289a3b Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 24 Jan 2024 20:47:20 +0530 Subject: [PATCH 261/337] Emulator : Adds support for flag in connection string to ignore SSL check (#4251) * first drfat * add test * add test * add documentation * builder changes * updating contract file * add tests * fix tests * remove builder method * updated contract * update gttpclient * cleanup * added validation nd doc * added validation * modified error message * Update Microsoft.Azure.Cosmos/src/CosmosClient.cs Co-authored-by: Kiran Kumar Kolli * Update Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs Co-authored-by: Matias Quaranta * remove validation * updated client options * remving test * rename flag to DisableServerCertificateValidation * updated docs * updated test * updated doc --------- Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- Microsoft.Azure.Cosmos/src/CosmosClient.cs | 12 ++- .../src/CosmosClientOptions.cs | 89 +++++++++++++------ .../src/Fluent/CosmosClientBuilder.cs | 7 ++ .../CosmosClientOptionsUnitTests.cs | 33 ++++++- 4 files changed, 107 insertions(+), 34 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClient.cs b/Microsoft.Azure.Cosmos/src/CosmosClient.cs index 7b143196fe..89c628635f 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClient.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClient.cs @@ -183,7 +183,9 @@ protected CosmosClient() /// /// /// - /// The returned reference doesn't guarantee credentials or connectivity validations because creation doesn't make any network calls. + /// Emulator: To ignore SSL Certificate please suffix connectionstring with "DisableServerCertificateValidation=True;". + /// When CosmosClientOptions.HttpClientFactory is used, SSL certificate needs to be handled appropriately. + /// NOTE: DO NOT use this flag in production (only for emulator) /// /// /// @@ -195,7 +197,7 @@ public CosmosClient( : this( CosmosClientOptions.GetAccountEndpoint(connectionString), CosmosClientOptions.GetAccountKey(connectionString), - clientOptions) + CosmosClientOptions.GetCosmosClientOptionsWithCertificateFlag(connectionString, clientOptions)) { } @@ -495,6 +497,11 @@ public static async Task CreateAndInitializeAsync(string accountEn /// ]]> /// /// + /// + /// Emulator: To ignore SSL Certificate please suffix connectionstring with "DisableServerCertificateValidation=True;". + /// When CosmosClientOptions.HttpClientFactory is used, SSL certificate needs to be handled appropriately. + /// NOTE: DO NOT use this flag in production (only for emulator) + /// public static async Task CreateAndInitializeAsync(string connectionString, IReadOnlyList<(string databaseId, string containerId)> containers, CosmosClientOptions cosmosClientOptions = null, @@ -504,6 +511,7 @@ public static async Task CreateAndInitializeAsync(string connectio { throw new ArgumentNullException(nameof(containers)); } + cosmosClientOptions = CosmosClientOptions.GetCosmosClientOptionsWithCertificateFlag(connectionString, cosmosClientOptions); CosmosClient cosmosClient = new CosmosClient(connectionString, cosmosClientOptions); diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index c49183e435..1fd66c3169 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -51,6 +51,7 @@ public class CosmosClientOptions private const string ConnectionStringAccountEndpoint = "AccountEndpoint"; private const string ConnectionStringAccountKey = "AccountKey"; + private const string ConnectionStringDisableServerCertificateValidation = "DisableServerCertificateValidation"; private const ApiType DefaultApiType = ApiType.None; @@ -651,7 +652,9 @@ internal Protocol ConnectionProtocol /// /// /// - /// Customizing SSL verification is not recommended in production environments. + /// Emulator: To ignore SSL Certificate please suffix connectionstring with "DisableServerCertificateValidation=True;". + /// When CosmosClientOptions.HttpClientFactory is used, SSL certificate needs to be handled appropriately. + /// NOTE: DO NOT use this flag in production (only for emulator) /// /// public Func ServerCertificateCustomValidationCallback { get; set; } @@ -843,34 +846,62 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) return (Documents.ConsistencyLevel)this.ConsistencyLevel.Value; } - internal static string GetAccountEndpoint(string connectionString) - { - return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountEndpoint); - } - - internal static string GetAccountKey(string connectionString) - { - return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountKey); - } - - private static string GetValueFromConnectionString(string connectionString, string keyName) - { - if (connectionString == null) - { - throw new ArgumentNullException(nameof(connectionString)); - } - - DbConnectionStringBuilder builder = new DbConnectionStringBuilder { ConnectionString = connectionString }; - if (builder.TryGetValue(keyName, out object value)) - { - string keyNameValue = value as string; - if (!string.IsNullOrEmpty(keyNameValue)) - { - return keyNameValue; - } - } - - throw new ArgumentException("The connection string is missing a required property: " + keyName); + internal static string GetAccountEndpoint(string connectionString) + { + return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountEndpoint, null); + } + + internal static string GetAccountKey(string connectionString) + { + return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountKey, null); + } + + internal static bool IsConnectionStringDisableServerCertificateValidationFlag(string connectionString) + { + return Convert.ToBoolean(CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringDisableServerCertificateValidation, false)); + } + + internal static CosmosClientOptions GetCosmosClientOptionsWithCertificateFlag(string connectionString, CosmosClientOptions clientOptions) + { + clientOptions ??= new CosmosClientOptions(); + if (CosmosClientOptions.IsConnectionStringDisableServerCertificateValidationFlag(connectionString)) + { + clientOptions.ServerCertificateCustomValidationCallback = (_, _, _) => true; + } + + return clientOptions; + } + + private static T GetValueFromConnectionString(string connectionString, string keyName, T defaultValue) + { + if (connectionString == null) + { + throw new ArgumentNullException(nameof(connectionString)); + } + + DbConnectionStringBuilder builder = new DbConnectionStringBuilder { ConnectionString = connectionString }; + if (builder.TryGetValue(keyName, out object value)) + { + string keyNameValue = value as string; + if (!string.IsNullOrEmpty(keyNameValue)) + { + try + { + return (T)Convert.ChangeType(value, typeof(T)); + } + catch (InvalidCastException) + { + throw new ArgumentException("The connection string contains invalid property: " + keyName); + } + } + } + + if (defaultValue != null) + { + return defaultValue; + } + + throw new ArgumentException("The connection string is missing a required property: " + keyName); } private void ValidateLimitToEndpointSettings() diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index 5258987a35..e030411338 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -124,6 +124,11 @@ public CosmosClientBuilder( /// /// "AccountEndpoint=https://mytestcosmosaccount.documents.azure.com:443/;AccountKey={SecretAccountKey};" /// The connection string must contain AccountEndpoint and AccountKey or ResourceToken. + /// + /// Emulator: To ignore SSL Certificate please suffix connectionstring with "DisableServerCertificateValidation=True;". + /// When CosmosClientOptions.HttpClientFactory is used, SSL certificate needs to be handled appropriately. + /// NOTE: DO NOT use this flag in production (only for emulator) + /// public CosmosClientBuilder(string connectionString) { if (connectionString == null) @@ -133,6 +138,8 @@ public CosmosClientBuilder(string connectionString) this.accountEndpoint = CosmosClientOptions.GetAccountEndpoint(connectionString); this.accountKey = CosmosClientOptions.GetAccountKey(connectionString); + + this.clientOptions = CosmosClientOptions.GetCosmosClientOptionsWithCertificateFlag(connectionString, this.clientOptions); } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index b625858c09..51aee132ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -7,10 +7,12 @@ namespace Microsoft.Azure.Cosmos.Tests using System; using System.Collections; using System.Collections.Generic; - using System.Collections.ObjectModel; using System.Linq; using System.Net; - using System.Net.Http; + using System.Net.Http; + using System.Net.Security; + using System.Security.Cryptography; + using System.Security.Cryptography.X509Certificates; using global::Azure.Core; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; @@ -885,7 +887,32 @@ public void InvalidApplicationNameCatchTest() ApplicationName = illegal }); } - } + } + + [TestMethod] + [DataRow(ConnectionString, false)] + [DataRow(ConnectionString + "DisableServerCertificateValidation=true;", true)] + public void TestServerCertificatesValidationCallback(string connStr, bool expectedIgnoreCertificateFlag) + { + //Arrange + X509Certificate2 x509Certificate2 = new CertificateRequest("cn=www.test", ECDsa.Create(), HashAlgorithmName.SHA256).CreateSelfSigned(DateTime.Now, DateTime.Now.AddYears(1)); + X509Chain x509Chain = new X509Chain(); + SslPolicyErrors sslPolicyErrors = new SslPolicyErrors(); + + CosmosClient cosmosClient = new CosmosClient(connStr); + + if (expectedIgnoreCertificateFlag) + { + Assert.IsNotNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); + Assert.IsTrue(cosmosClient + .ClientOptions + .ServerCertificateCustomValidationCallback(x509Certificate2, x509Chain, sslPolicyErrors)); + } + else + { + Assert.IsNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); + } + } private class TestWebProxy : IWebProxy { From 72957d192772648e8a4c913443ed3233d9245c7d Mon Sep 17 00:00:00 2001 From: Aditya Kotalwar <94020786+akotalwar@users.noreply.github.com> Date: Wed, 24 Jan 2024 19:36:27 -0800 Subject: [PATCH 262/337] [Internal] Pre-Checkin Tests: Fixes Failing Tests After Emulator Refresh; Marks Failing Encryption Test as Ignore (#4271) * Changed return pipeline type to ODE * Fixed following query team owned tests: IndexUtilizationHeaderLengthTest IndexUtilizationParse Fixed following SDK team owned test (based on guidance from Philip): ChangeFeedIteratorCore_WithFullFidelityReadFromBeginning Not able to repro failure for following test (all 3 instances pass locally): EncryptionChangeFeedDecryptionSuccessful * Marks following encryption test as ignored since it's flaky per offline discussion: EncryptionChangeFeedDecryptionSuccessful * Added fix for following test: TestQueryPlanGatewayAndServiceInteropAsync * Removed unused usings. --------- Co-authored-by: REDMOND\adityasa Co-authored-by: Matias Quaranta --- .../tests/EmulatorTests/MdeEncryptionTests.cs | 13 ++ ...eTest.IndexUtilizationHeaderLengthTest.xml | 4 +- ...rserBaselineTest.IndexUtilizationParse.xml | 18 +-- .../FeedToken/ChangeFeedIteratorCoreTests.cs | 1 - .../OptimisticDirectExecutionQueryTests.cs | 61 ++------- .../Query/SanityQueryTests.cs | 128 ++++++++++-------- 6 files changed, 109 insertions(+), 116 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs index 3489cdf02e..a084dcdab4 100644 --- a/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs +++ b/Microsoft.Azure.Cosmos.Encryption/tests/EmulatorTests/MdeEncryptionTests.cs @@ -898,6 +898,19 @@ public async Task EncryptionReadManyItemAsync() } } + // ISSUE-TODO-VipulVishal - This test passes locally, but often fails in pre-checkin validation. + // Re-enable once the test is stabilized. + // Here's one example failure for reference: + // Test method Microsoft.Azure.Cosmos.Encryption.EmulatorTests.MdeEncryptionTests.EncryptionChangeFeedDecryptionSuccessful threw exception: + // System.NullReferenceException: Object reference not set to an instance of an object. + // at Microsoft.Azure.Cosmos.Encryption.EmulatorTests.MdeEncryptionTests.<>c__DisplayClass51_0.b__2(TestDoc doc) in D:\a\1\s\Microsoft.Azure.Cosmos.Encryption\tests\EmulatorTests\MdeEncryptionTests.cs:line 3152 + // at System.Linq.Enumerable.WhereListIterator`1.MoveNext() + // at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) + // at System.Linq.Enumerable.FirstOrDefault[TSource] (IEnumerable`1 source) + // at Microsoft.Azure.Cosmos.Encryption.EmulatorTests.MdeEncryptionTests.ValidateChangeFeedProcessorResponse(Container container, TestDoc testDoc1, TestDoc testDoc2) in D:\a\1\s\Microsoft.Azure.Cosmos.Encryption\tests\EmulatorTests\MdeEncryptionTests.cs:line 3152 + // at Microsoft.Azure.Cosmos.Encryption.EmulatorTests.MdeEncryptionTests.EncryptionChangeFeedDecryptionSuccessful() in D:\a\1\s\Microsoft.Azure.Cosmos.Encryption\tests\EmulatorTests\MdeEncryptionTests.cs:line 911 + // at Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.ThreadOperations.ExecuteWithAbortSafety(Action action) + [Ignore] [TestMethod] public async Task EncryptionChangeFeedDecryptionSuccessful() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml index 09fc864403..749f507caf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml @@ -71,10 +71,10 @@ Index Utilization Information ?:\"{}|ßÁŒÆ12ếàưỏốởặ"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -103,7 +103,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /"Der schnelle Braunfuchs springt über den faulen Hund"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -121,7 +121,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /"Η γρήγορη καφέ αλεπού πηδάει πάνω από το τεμπέλικο σκυλί"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -139,7 +139,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /"الثعلب البني السريع يقفز فوق الكلب الكسول"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -157,7 +157,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /"Быстрая коричневая лиса прыгает через ленивую собаку"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -175,7 +175,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /素早く茶色のキツネが怠惰な犬を飛び越えます/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes @@ -193,7 +193,7 @@ Index Utilization Information Index Utilization Information Utilized Single Indexes Index Spec: /"तेज, भूरी लोमडी आलसी कुत्ते के उपर कूद गई"/? - Index Impact Score: Low + Index Impact Score: High --- Potential Single Indexes Utilized Composite Indexes diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs index 4a1d92c59c..b8d132e141 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs @@ -792,7 +792,6 @@ public async Task ChangeFeedIteratorCore_WithFullFidelityReadFromBeginning() CosmosException cosmosException = await Assert.ThrowsExceptionAsync(() => fullFidelityIterator.ReadNextAsync()); Assert.AreEqual(HttpStatusCode.BadRequest, cosmosException.StatusCode, "Full Fidelity Change Feed does not work with StartFromBeginning currently."); - Assert.IsTrue(cosmosException.Message.Contains("FullFidelity Change Feed must have valid If-None-Match header.")); } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 0ac41b6f39..cb70aacb41 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -53,7 +53,7 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: false, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.Passthrough), - + // Simple query (requiresDist = false) CreateInput( query: $"SELECT VALUE r.numberField FROM r", @@ -62,32 +62,27 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: null, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: null, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // DISTINCT with ORDER BY (requiresDist = true) CreateInput( @@ -159,16 +154,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", expectedResult: first5Integers, @@ -176,15 +168,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", expectedResult: first5Integers, partitionKey: null, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // TOP with ORDER BY (requiresDist = false) CreateInput( @@ -194,16 +184,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", expectedResult: first5Integers, @@ -211,15 +198,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", expectedResult: first5Integers, partitionKey: null, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), // OFFSET LIMIT with WHERE and BETWEEN (requiresDist = false) CreateInput( @@ -261,17 +246,14 @@ public async Task TestPassingOptimisticDirectExecutionQueries() partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first7Integers, @@ -325,16 +307,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r", expectedResult: first5Integers, @@ -358,16 +337,13 @@ public async Task TestPassingOptimisticDirectExecutionQueries() enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", expectedResult: first5Integers, partitionKey: partitionKeyValue, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.NonGroupByWithContinuationTokenPageSizeOptions, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT TOP 5 VALUE r.{NumberField} FROM r ORDER BY r.{NumberField}", expectedResult: first5Integers, @@ -468,34 +444,27 @@ public async Task TestQueriesWithPartitionKeyNone() enableOptimisticDirectExecution: false, pageSizeOptions: PageSizeOptions.PageSize100, expectedPipelineType: TestInjections.PipelineType.Passthrough), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 CreateInput( query: $"SELECT VALUE r.numberField FROM r", expectedResult: first400Integers, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.Specialized), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} ASC", expectedResult: first400Integers, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.Specialized), - - //TODO: Change expectedPipelineType to OptimisticDirectExecution once emulator is updated to 0415 + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.{NumberField} FROM r ORDER BY r.{NumberField} DESC", expectedResult: first400IntegersReversed, partitionKey: PartitionKey.None, enableOptimisticDirectExecution: true, pageSizeOptions: PageSizeOptions.PageSize100, - expectedPipelineType: TestInjections.PipelineType.Specialized), - + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), CreateInput( query: $"SELECT VALUE r.numberField FROM r WHERE r.{NumberField} BETWEEN 0 AND {NumberOfDocuments} OFFSET 1 LIMIT 1", expectedResult: new List { 1 }, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 48ae5d4464..4a5f02ff7c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -451,73 +451,85 @@ public async Task TestQueryPlanGatewayAndServiceInteropAsync() QueryOracleUtil util = new QueryOracle2(seed); IEnumerable inputDocuments = util.GetDocuments(numberOfDocuments); - ConnectionModes connectionModes = ConnectionModes.Direct; - await this.CreateIngestQueryDeleteAsync( - connectionModes, - CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, - inputDocuments, - ImplementationAsync); - - connectionModes = ConnectionModes.Gateway; - await this.CreateIngestQueryDeleteAsync( - connectionModes, - CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, - inputDocuments, - ImplementationAsync); - - async Task ImplementationAsync(Container container, IReadOnlyList documents) + foreach (ConnectionModes connectionModes in new[] { ConnectionModes.Direct, ConnectionModes.Gateway }) { - ContainerInternal containerCore = (ContainerInlineCore)container; - - List isGatewayQueryPlanOptions = new List { true }; - if (connectionModes == ConnectionModes.Direct) + foreach (CollectionTypes collectionTypes in new[] { - isGatewayQueryPlanOptions.Append(false); - } - - foreach (bool isGatewayQueryPlan in isGatewayQueryPlanOptions) + CollectionTypes.SinglePartition, + CollectionTypes.MultiPartition + }) { - MockCosmosQueryClient cosmosQueryClientCore = new MockCosmosQueryClient( - containerCore.ClientContext, - containerCore, - isGatewayQueryPlan); - - ContainerInternal containerWithForcedPlan = new ContainerInlineCore( - containerCore.ClientContext, - (DatabaseCore)containerCore.Database, - containerCore.Id, - cosmosQueryClientCore); - - int numOfQueries = 0; - foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) + await this.CreateIngestQueryDeleteAsync( + connectionModes, + collectionTypes, + inputDocuments, + ImplementationAsync); + + async Task ImplementationAsync(Container container, IReadOnlyList documents) { - foreach (int maxItemCount in new int[] { 10, 100 }) + Assert.IsTrue(collectionTypes == CollectionTypes.SinglePartition || + collectionTypes == CollectionTypes.MultiPartition, + "The test validation requires that single/multi-partition scenario be executed separately."); + ContainerInternal containerCore = (ContainerInlineCore)container; + + List isGatewayQueryPlanOptions = new List { true }; + if (connectionModes == ConnectionModes.Direct) { - numOfQueries++; - QueryRequestOptions feedOptions = new QueryRequestOptions - { - MaxBufferedItemCount = 7000, - MaxConcurrency = maxDegreeOfParallelism, - MaxItemCount = maxItemCount, - }; + isGatewayQueryPlanOptions.Append(false); + } - List queryResults = await QueryTestsBase.RunQueryAsync( - containerWithForcedPlan, - "SELECT * FROM c ORDER BY c._ts", - feedOptions); + foreach (bool isGatewayQueryPlan in isGatewayQueryPlanOptions) + { + foreach (bool ode in new [] { true, false }) + { + MockCosmosQueryClient cosmosQueryClientCore = new MockCosmosQueryClient( + containerCore.ClientContext, + containerCore, + isGatewayQueryPlan); + + ContainerInternal containerWithForcedPlan = new ContainerInlineCore( + containerCore.ClientContext, + (DatabaseCore)containerCore.Database, + containerCore.Id, + cosmosQueryClientCore); + + int numOfQueries = 0; + foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) + { + foreach (int maxItemCount in new int[] { 10, 100 }) + { + numOfQueries++; + QueryRequestOptions feedOptions = new QueryRequestOptions + { + MaxBufferedItemCount = 7000, + MaxConcurrency = maxDegreeOfParallelism, + MaxItemCount = maxItemCount, + EnableOptimisticDirectExecution = ode, + }; + + List queryResults = await QueryTestsBase.RunQueryAsync( + containerWithForcedPlan, + "SELECT * FROM c ORDER BY c._ts", + feedOptions); + + Assert.AreEqual(documents.Count(), queryResults.Count); + } + } - Assert.AreEqual(documents.Count(), queryResults.Count); + if (isGatewayQueryPlan) + { + bool expected = ode && (collectionTypes == CollectionTypes.SinglePartition) ? + cosmosQueryClientCore.QueryPlanCalls == 0 : + cosmosQueryClientCore.QueryPlanCalls > numOfQueries; + Assert.IsTrue(expected); + } + else + { + Assert.AreEqual(0, cosmosQueryClientCore.QueryPlanCalls, "ServiceInterop mode should not be calling gateway plan retriever"); + } + } } } - - if (isGatewayQueryPlan) - { - Assert.IsTrue(cosmosQueryClientCore.QueryPlanCalls > numOfQueries); - } - else - { - Assert.AreEqual(0, cosmosQueryClientCore.QueryPlanCalls, "ServiceInterop mode should not be calling gateway plan retriever"); - } } } } From 8087dd69532d311546443787d7633b39fb208de9 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Thu, 25 Jan 2024 03:21:40 -0800 Subject: [PATCH 263/337] [Internal] Query: Fixes Group By queries with Select Value returning incorrect return type (#4221) * Primary Code Change * Added test coverage * addressed code review * address code review * add baseline capabilitiesadd baselines --------- Co-authored-by: Minh Le --- .../Aggregate/Aggregators/AggregateItem.cs | 29 +- .../GroupByQueryPipelineStage.Client.cs | 2 + .../GroupByQueryPipelineStage.Compute.cs | 2 + .../GroupBy/GroupByQueryPipelineStage.cs | 14 +- .../Query/Core/Pipeline/PipelineFactory.cs | 1 + .../QueryBaselineTest.TestGroupByQueries.xml | 284 +++++++++++ ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 3 + .../Query/GroupByQueryTests.cs | 142 +++++- .../Query/QueryBaselineTest.cs | 458 ++++++++++++++++++ .../QueryPlanBaselineTests.GroupBy.xml | 118 +++++ .../GroupByQueryPipelineStageTests.cs | 1 + .../Query/QueryPlanBaselineTests.cs | 22 +- 12 files changed, 1063 insertions(+), 13 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/QueryBaselineTest.TestGroupByQueries.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/Aggregators/AggregateItem.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/Aggregators/AggregateItem.cs index 4cfad3344d..1821e5b7fa 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/Aggregators/AggregateItem.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/Aggregators/AggregateItem.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate.Aggregators { using System; + using System.Text.RegularExpressions; using Microsoft.Azure.Cosmos.CosmosElements; internal readonly struct AggregateItem @@ -16,17 +17,31 @@ internal readonly struct AggregateItem public AggregateItem(CosmosElement cosmosElement) { - if (cosmosElement == null) - { - throw new ArgumentNullException($"{nameof(cosmosElement)} must not be null."); - } + // If the query is not a select value query then the top level is a an object + CosmosObject cosmosObject = cosmosElement as CosmosObject; - if (!(cosmosElement is CosmosObject cosmosObject)) + if (cosmosObject == null) { - throw new ArgumentException($"{nameof(cosmosElement)} must not be an object."); + // In case of Aggregate query with VALUE query plan, the top level is an array of one item after it is rewritten + // For example, if the query is + // SELECT VALUE {"age": c.age} + // FROM c + // GROUP BY c.age + // Fhe rewritten query is + // SELECT [{"item": c.age}] AS groupByItems, {"age": c.age} AS payload + // FROM c + // GROUP BY c.age + + // In this case, the top level is an array of one item [{"item": c.age}] + CosmosArray cosmosArray = cosmosElement as CosmosArray; + if (cosmosArray.Count == 1) + { + cosmosObject = cosmosArray[0] as CosmosObject; + } } - this.cosmosObject = cosmosObject; + // If the object is still null, then we have an invalid aggregate item + this.cosmosObject = cosmosObject ?? throw new ArgumentException($"Unsupported aggregate item. Expected CosmosObject"); } public CosmosElement Item diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs index 5d82409a19..cea8f6e566 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs @@ -33,12 +33,14 @@ public static TryCatch MonadicCreate( CosmosElement requestContinuation, CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, + IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, IReadOnlyList orderedAliases, bool hasSelectValue, int pageSize) { TryCatch tryCreateGroupingTable = GroupingTable.TryCreateFromContinuationToken( + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs index 2183952a1d..079c69465f 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs @@ -40,6 +40,7 @@ public static TryCatch MonadicCreate( CosmosElement requestContinuation, CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, + IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, IReadOnlyList orderedAliases, bool hasSelectValue, @@ -79,6 +80,7 @@ public static TryCatch MonadicCreate( } TryCatch tryCreateGroupingTable = GroupingTable.TryCreateFromContinuationToken( + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs index 329b62e81d..f42be927cc 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs @@ -67,6 +67,7 @@ public static TryCatch MonadicCreate( CosmosElement continuationToken, CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, + IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, IReadOnlyList orderedAliases, bool hasSelectValue, @@ -76,6 +77,7 @@ public static TryCatch MonadicCreate( continuationToken, cancellationToken, monadicCreatePipelineStage, + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue, @@ -84,6 +86,7 @@ public static TryCatch MonadicCreate( continuationToken, cancellationToken, monadicCreatePipelineStage, + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue, @@ -166,15 +169,18 @@ protected sealed class GroupingTable : IEnumerable EmptyAggregateOperators = new AggregateOperator[] { }; private readonly Dictionary table; + private readonly IReadOnlyList aggregates; private readonly IReadOnlyDictionary groupByAliasToAggregateType; private readonly IReadOnlyList orderedAliases; private readonly bool hasSelectValue; private GroupingTable( + IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, IReadOnlyList orderedAliases, bool hasSelectValue) { + this.aggregates = aggregates ?? throw new ArgumentNullException(nameof(aggregates)); this.groupByAliasToAggregateType = groupByAliasToAggregateType ?? throw new ArgumentNullException(nameof(groupByAliasToAggregateType)); this.orderedAliases = orderedAliases; this.hasSelectValue = hasSelectValue; @@ -195,7 +201,7 @@ public void AddPayload(RewrittenGroupByProjection rewrittenGroupByProjection) if (!this.table.TryGetValue(groupByKeysHash, out SingleGroupAggregator singleGroupAggregator)) { singleGroupAggregator = SingleGroupAggregator.TryCreate( - EmptyAggregateOperators, + this.aggregates, this.groupByAliasToAggregateType, this.orderedAliases, this.hasSelectValue, @@ -225,7 +231,7 @@ public IReadOnlyList Drain(int maxItemCount) List results = new List(); foreach (SingleGroupAggregator singleGroupAggregator in singleGroupAggregators) { - results.Add(singleGroupAggregator.GetResult()); + results.Add(singleGroupAggregator.GetResult()); } if (this.Count == 0) @@ -250,12 +256,14 @@ public CosmosElement GetCosmosElementContinuationToken() public IEnumerator> GetEnumerator => this.table.GetEnumerator(); public static TryCatch TryCreateFromContinuationToken( + IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, IReadOnlyList orderedAliases, bool hasSelectValue, CosmosElement continuationToken) { GroupingTable groupingTable = new GroupingTable( + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue); @@ -282,7 +290,7 @@ public static TryCatch TryCreateFromContinuationToken( } TryCatch tryCreateSingleGroupAggregator = SingleGroupAggregator.TryCreate( - EmptyAggregateOperators, + aggregates, groupByAliasToAggregateType, orderedAliases, hasSelectValue, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs index a6a2a5d624..a119d5866a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs @@ -128,6 +128,7 @@ public static TryCatch MonadicCreate( continuationToken, cancellationToken, monadicCreateSourceStage, + queryInfo.Aggregates, queryInfo.GroupByAliasToAggregateType, queryInfo.GroupByAliases, queryInfo.HasSelectValue, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/QueryBaselineTest.TestGroupByQueries.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/QueryBaselineTest.TestGroupByQueries.xml new file mode 100644 index 0000000000..9ba929aa32 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/QueryBaselineTest.TestGroupByQueries.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 83de702ef3..296072a411 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -284,6 +284,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/GroupByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/GroupByQueryTests.cs index 5b3b79b5fc..f2257bbf34 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/GroupByQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/GroupByQueryTests.cs @@ -89,10 +89,10 @@ await this.CreateIngestQueryDeleteAsync( ConnectionModes.Direct, CollectionTypes.MultiPartition, documents, - this.TestGroupByQueryHelper); + this.TestGroupByQueryHelper1); } - private async Task TestGroupByQueryHelper( + private async Task TestGroupByQueryHelper1( Container container, IReadOnlyList documents) { @@ -276,6 +276,144 @@ private async Task TestGroupByQueryHelper( .ToList() ), + ( + "SELECT VALUE COUNT(1) FROM c GROUP BY c.age", + documents + .GroupBy(document => document["age"]) + .Select(grouping => CosmosNumber64.Create(grouping.Count())) + .ToList() + ), + + ( + "SELECT VALUE MIN(c.age) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(grouping.Min(document => document["age"].ToDouble()))) + .ToList() + ), + + ( + "SELECT VALUE MAX(c.age) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(grouping.Max(document => document["age"].ToDouble()))) + .ToList() + ), + + ( + "SELECT VALUE AVG(c.age) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(grouping.Average(document => document["age"].ToDouble()))) + .ToList() + ), + + ( + "SELECT VALUE SUM(c.age) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(grouping.Sum(document => document["age"].ToDouble()))) + .ToList() + ), + + ( + "SELECT VALUE { 'Name' : c.name , 'Age' : c.age} FROM c GROUP BY c.name, c.age", + documents + .GroupBy(document => new { key1 = document["name"], key2 = document["age"]}) + .Select(grouping => CosmosObject.Create( + new Dictionary() + { + { "Name", grouping.Key.key1 }, + { "Age", grouping.Key.key2}, + })) + .ToList() + ), + + ( + "SELECT VALUE {'age' : c.age} FROM c GROUP BY {'age' : c.age}", + documents + .GroupBy(document => new { age = document["age"]}) + .Select(grouping => CosmosObject.Create( + new Dictionary() + { + { "age", grouping.Key.age}, + })) + .ToList() + ), + + // GROUP BY with SELECT VALUE on undefined aggregate fields + // sum and count default the counter at 0 + ( + "SELECT VALUE SUM(c.doesNotExist) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(0)) + .ToList() + ), + + ( + "SELECT VALUE COUNT(c.doesNotExist) FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosNumber64.Create(0)) + .ToList() + ), + + ( + "SELECT VALUE AVG(c.unKnownField) FROM c GROUP BY c.age", + documents + .GroupBy(document => new { age = document["age"]}) + .Select(grouping => CosmosUndefined.Create()) + .ToList() + ), + + + ( + "SELECT VALUE MIN(c.unKnownField) FROM c GROUP BY c.age", + documents + .GroupBy(document => new { age = document["age"]}) + .Select(grouping => CosmosUndefined.Create()) + .ToList() + ), + + + ( + "SELECT VALUE MAX(c.unKnownField) FROM c GROUP BY c.age", + documents + .GroupBy(document => new { age = document["age"]}) + .Select(grouping => CosmosUndefined.Create()) + .ToList() + ), + + /* Composition of Aggregates currently not supported + ( + "SELECT VALUE {'count' : COUNT(1)} FROM c GROUP BY c.age", + documents + .GroupBy(document => new { age = document["age"]}) + .Select(grouping => CosmosObject.Create( + new Dictionary() + { + { "count", CosmosNumber64.Create(grouping.Count()) } + })) + .ToList() + ), + + ( + "SELECT VALUE { 'name' : c.name , 'count' : COUNT(1), 'min_age' : MIN(c.age), 'max_age' : c.age} FROM c GROUP BY c.name", + documents + .GroupBy(document => document["name"]) + .Select(grouping => CosmosObject.Create( + new Dictionary() + { + { "name", grouping.Key }, + { "count", CosmosNumber64.Create(grouping.Count()) }, + { "min_age", CosmosNumber64.Create(grouping.Min(document => document["age"].ToDouble())) }, + { "max_age", CosmosNumber64.Create(grouping.Max(document => document["age"].ToDouble())) }, + })) + .ToList() + ), + */ + // ------------------------------------------ // Corner Cases // ------------------------------------------ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs new file mode 100644 index 0000000000..c3cc566526 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs @@ -0,0 +1,458 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest +{ + using Microsoft.Azure.Cosmos.EmulatorTests.Query; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.Azure.Cosmos.Services.Management.Tests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using System; + using System.Text.RegularExpressions; + using System.Threading.Tasks; + using System.Xml; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Serialization.HybridRow.Schemas; + using Newtonsoft.Json.Linq; + using System.Collections.Concurrent; + + [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] + public class QueryBaselineTest : BaselineTests + { + private static CosmosClient cosmosClient; + private static Cosmos.Database testDb; + private static Container testContainer; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + string authKey = Utils.ConfigurationManager.AppSettings["MasterKey"]; + Uri uri = new Uri(Utils.ConfigurationManager.AppSettings["GatewayEndpoint"]); + ConnectionPolicy connectionPolicy = new ConnectionPolicy + { + ConnectionMode = ConnectionMode.Gateway, + EnableEndpointDiscovery = true, + }; + + cosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) => + { + cosmosClientBuilder.WithCustomSerializer(new CustomJsonSerializer(new JsonSerializerSettings() + { + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + // We want to simulate the property not exist so ignoring the null value + NullValueHandling = NullValueHandling.Ignore + })).WithConnectionModeGateway(); + }); + + string dbName = $"{nameof(QueryBaselineTest)}-{Guid.NewGuid().ToString("N")}"; + testDb = await cosmosClient.CreateDatabaseAsync(dbName); + } + + [ClassCleanup] + public async static Task CleanUp() + { + if (testDb != null) + { + await testDb.DeleteStreamAsync(); + } + + cosmosClient?.Dispose(); + } + + [TestInitialize] + public async Task TestInitialize() + { + testContainer = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/id")); + } + + [TestCleanup] + public async Task TestCleanUp() + { + await testContainer.DeleteContainerStreamAsync(); + } + + [TestMethod] + public void TestGroupByQueries() + { + string[] documents = new string[] + { + @" { ""id"": ""01"", ""name"": ""John"", ""age"": 11, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""02"", ""name"": ""Mady"", ""age"": 15, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [52, 13, 94, 31] } ", + @" { ""id"": ""03"", ""name"": ""John"", ""age"": 13, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""04"", ""name"": ""Mary"", ""age"": 18, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""05"", ""name"": ""Fred"", ""age"": 17, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""06"", ""name"": ""Adam"", ""age"": 16, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""07"", ""name"": ""Alex"", ""age"": 13, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [52, 13, 94, 31] } ", + @" { ""id"": ""08"", ""name"": ""Fred"", ""age"": 12, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""09"", ""name"": ""Fred"", ""age"": 15, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""10"", ""name"": ""Mary"", ""age"": 18, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""11"", ""name"": ""Fred"", ""age"": 18, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""12"", ""name"": ""Abby"", ""age"": 17, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""13"", ""name"": ""John"", ""age"": 16, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""14"", ""name"": ""Ella"", ""age"": 16, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""15"", ""name"": ""Mary"", ""age"": 18, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""16"", ""name"": ""Carl"", ""age"": 17, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [52, 13, 94, 31] } ", + @" { ""id"": ""17"", ""name"": ""Mady"", ""age"": 18, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""18"", ""name"": ""Mike"", ""age"": 15, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""19"", ""name"": ""Eric"", ""age"": 16, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""20"", ""name"": ""Ryan"", ""age"": 11, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""21"", ""name"": ""Alex"", ""age"": 14, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""22"", ""name"": ""Mike"", ""age"": 15, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""23"", ""name"": ""John"", ""age"": 14, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""24"", ""name"": ""Dave"", ""age"": 15, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""25"", ""name"": ""Lisa"", ""age"": 11, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""26"", ""name"": ""Zara"", ""age"": 11, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""27"", ""name"": ""Abby"", ""age"": 17, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""28"", ""name"": ""Abby"", ""age"": 13, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""29"", ""name"": ""Lucy"", ""age"": 14, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""30"", ""name"": ""Lucy"", ""age"": 14, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""31"", ""name"": ""Bill"", ""age"": 13, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""32"", ""name"": ""Bill"", ""age"": 11, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""33"", ""name"": ""Zara"", ""age"": 12, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""34"", ""name"": ""Adam"", ""age"": 13, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""35"", ""name"": ""Bill"", ""age"": 13, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""36"", ""name"": ""Alex"", ""age"": 15, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""37"", ""name"": ""Lucy"", ""age"": 14, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""38"", ""name"": ""Alex"", ""age"": 11, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""39"", ""name"": ""Mike"", ""age"": 15, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""40"", ""name"": ""Eric"", ""age"": 11, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""41"", ""name"": ""John"", ""age"": 12, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""42"", ""name"": ""Ella"", ""age"": 17, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60291 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""43"", ""name"": ""Lucy"", ""age"": 12, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""44"", ""name"": ""Mady"", ""age"": 14, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""45"", ""name"": ""Lori"", ""age"": 17, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [88, 88, 88, 88] } ", + @" { ""id"": ""46"", ""name"": ""Gary"", ""age"": 17, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""47"", ""name"": ""Eric"", ""age"": 18, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""48"", ""name"": ""Mary"", ""age"": 15, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [23, 11, 11, 66] } ", + @" { ""id"": ""49"", ""name"": ""Zara"", ""age"": 17, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [90, 45, 62, 21] } ", + @" { ""id"": ""50"", ""name"": ""Carl"", ""age"": 17, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""51"", ""name"": ""Lori"", ""age"": 11, ""gender"": ""F"", ""team"": ""D"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""52"", ""name"": ""Adam"", ""age"": 13, ""gender"": ""M"", ""team"": ""A"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""53"", ""name"": ""Bill"", ""age"": 16, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""54"", ""name"": ""Zara"", ""age"": 12, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""55"", ""name"": ""Lisa"", ""age"": 16, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""56"", ""name"": ""Ryan"", ""age"": 12, ""gender"": ""M"", ""team"": ""B"", ""address"": { ""city"": ""Chicago"", ""state"": ""IL"", ""zip"": 60292 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""57"", ""name"": ""Abby"", ""age"": 12, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98102 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""58"", ""name"": ""John"", ""age"": 16, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32801 }, ""scores"": [38, 66, 54, 25] } ", + @" { ""id"": ""59"", ""name"": ""Mary"", ""age"": 15, ""gender"": ""F"", ""team"": ""A"", ""address"": { ""city"": ""Seattle"", ""state"": ""WA"", ""zip"": 98101 }, ""scores"": [52, 13, 94, 31] } ", + @" { ""id"": ""60"", ""name"": ""John"", ""age"": 16, ""gender"": ""M"", ""team"": ""D"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""61"", ""name"": ""Mary"", ""age"": 17, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [12, 10, 12, 10] } ", + @" { ""id"": ""62"", ""name"": ""Lucy"", ""age"": 12, ""gender"": ""F"", ""team"": ""C"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30302 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""63"", ""name"": ""Rose"", ""age"": 14, ""gender"": ""F"", ""team"": ""B"", ""address"": { ""city"": ""Orlando"", ""state"": ""FL"", ""zip"": 32802 }, ""scores"": [88, 47, 90, 76] } ", + @" { ""id"": ""64"", ""name"": ""Gary"", ""age"": 14, ""gender"": ""M"", ""team"": ""C"", ""address"": { ""city"": ""Atlanta"", ""state"": ""GA"", ""zip"": 30301 }, ""scores"": [88, 47, 90, 76] } ", + }; + + //insert documents into container + foreach (string document in documents) + { + JObject documentObject = JsonConvert.DeserializeObject(document); + string jObjectPartitionKey = "/id".Remove(0, 1); + JValue pkToken = (JValue)documentObject[jObjectPartitionKey]; + Cosmos.PartitionKey pkValue; + + switch (pkToken.Type) + { + case JTokenType.Integer: + case JTokenType.Float: + pkValue = new Cosmos.PartitionKey(pkToken.Value()); + break; + case JTokenType.String: + pkValue = new Cosmos.PartitionKey(pkToken.Value()); + break; + case JTokenType.Boolean: + pkValue = new Cosmos.PartitionKey(pkToken.Value()); + break; + case JTokenType.Null: + pkValue = Cosmos.PartitionKey.Null; + break; + default: + throw new ArgumentException("Unknown partition key type"); + } + + var _ = testContainer.CreateItemAsync(documentObject, pkValue).Result; + } + + List<(string /*query text*/, string /*description*/)> queryTestCases = new List<(string, string)>() + { + // ------------------------------------------ + // Simple property reference + // ------------------------------------------ + + ( + "SELECT c.age FROM c GROUP BY c.age", + "Simple property reference 1" + ), + + ( + "SELECT c.name FROM c GROUP BY c.name", + "Simple property reference 2" + ), + + ( + "SELECT c.team FROM c GROUP BY c.team", + "Simple property reference 3" + ), + + ( + "SELECT c.gender FROM c GROUP BY c.gender", + "Simple property reference 4" + ), + + ( + "SELECT c.id FROM c GROUP BY c.id", + "Simple property reference 5" + ), + + ( + "SELECT c.age, c.name FROM c GROUP BY c.age, c.name", + "Simple property reference 6" + ), + + // ------------------------------------------ + // With Aggregates + // ------------------------------------------ + + ( + "SELECT c.age, COUNT(1) as count FROM c GROUP BY c.age", + "With SELECT Aggregates 1" + ), + + ( + "SELECT c.name, MIN(c.age) AS min_age FROM c GROUP BY c.name", + "With SELECT Aggregates 2" + ), + + ( + "SELECT c.name, MAX(c.age) AS max_age FROM c GROUP BY c.name", + "With SELECT Aggregates 3" + ), + + ( + "SELECT c.name, SUM(c.age) AS sum_age FROM c GROUP BY c.name", + "With SELECT Aggregates 4" + ), + + ( + "SELECT c.name, AVG(c.age) AS avg_age FROM c GROUP BY c.name", + "With SELECT Aggregates 5" + ), + + ( + "SELECT c.name, Count(1) AS count, Min(c.age) AS min_age, Max(c.age) AS max_age FROM c GROUP BY c.name", + "With SELECT Aggregates 6" + ), + + // ------------------------------------------ + // SELECT VALUE + // ------------------------------------------ + + ( + "SELECT VALUE c.age FROM c GROUP BY c.age", + "With SELECT VALUE" + ), + + ( + "SELECT VALUE COUNT(1) FROM c GROUP BY c.age", + "With SELECT VALUE Aggregates 1" + ), + + ( + "SELECT VALUE MIN(c.age) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregates 2" + ), + + ( + "SELECT VALUE MAX(c.age) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregates 3" + ), + + ( + "SELECT VALUE AVG(c.age) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregates 4" + ), + + ( + "SELECT VALUE SUM(c.age) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregates 5" + ), + + ( + "SELECT VALUE { 'Name' : c.name , 'Age' : c.age} FROM c GROUP BY c.name, c.age", + "With SELECT VALUE Object" + ), + + ( + "SELECT VALUE {'age' : c.age} FROM c GROUP BY {'age' : c.age}", + "With SELECT VALUE Object 2" + ), + + // GROUP BY with SELECT VALUE on undefined aggregate fields + // sum and count default the counter at 0 + ( + "SELECT VALUE SUM(c.doesNotExist) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregate on a term that does not exist 1" + ), + + ( + "SELECT VALUE COUNT(c.doesNotExist) FROM c GROUP BY c.name", + "With SELECT VALUE Aggregate on a term that does not exist 2" + ), + + ( + "SELECT VALUE AVG(c.unKnownField) FROM c GROUP BY c.age", + "With SELECT VALUE Aggregate on a term that does not exist 3" + ), + + + ( + "SELECT VALUE MIN(c.unKnownField) FROM c GROUP BY c.age", + "With SELECT VALUE Aggregate on a term that does not exist 4" + ), + + + ( + "SELECT VALUE MAX(c.unKnownField) FROM c GROUP BY c.age", + "With SELECT VALUE Aggregate on a term that does not exist 5" + ), + + /* Composition of Aggregates currently not supported + ( + "SELECT VALUE {'count' : COUNT(1)} FROM c GROUP BY c.age", + "Compositetion of Aggregate 1" + ), + + ( + "SELECT VALUE { 'name' : c.name , 'count' : COUNT(1), 'min_age' : MIN(c.age), 'max_age' : c.age} FROM c GROUP BY c.name", + "Compositetion of Aggregate 2" + ), + */ + + // ------------------------------------------ + // Corner Cases + // ------------------------------------------ + + ( + "SELECT AVG(\"asdf\") as avg_asdf FROM c GROUP BY c.age", + "Corner Case 1" + ), + + ( + @"SELECT + c.age, + AVG(c.doesNotExist) as undefined_avg, + MIN(c.doesNotExist) as undefined_min, + MAX(c.doesNotExist) as undefined_max, + COUNT(c.doesNotExist) as undefined_count, + SUM(c.doesNotExist) as undefined_sum + FROM c + GROUP BY c.age", + "Corner Case 2" + ), + + ( + @"SELECT + c.age, + c.doesNotExist + FROM c + GROUP BY c.age, c.doesNotExist", + "Corner Case 3" + ), + + // ------------------------------------------ + // GROUP BY partition key + // ------------------------------------------ + + ( + "SELECT VALUE c.id FROM c GROUP BY c.id", + "With Partition Key" + ), + + // ------------------------------------------ + // GROUP BY undefined + // ------------------------------------------ + + ( + "SELECT COUNT(1) as count, c.DoesNotExist as DoesNotExist FROM c GROUP BY c.DoesNotExist", + "Group By Undefined" + ), + }; + + List inputs = new List(); + foreach ((string query, string description) in queryTestCases) + { + QueryTestInput input = new QueryTestInput(description, query); + inputs.Add(input); + } + + this.ExecuteTestSuite(inputs); + } + + public override QueryTestOutput ExecuteTest(QueryTestInput input) + { + FeedIterator iterator = testContainer.GetItemQueryIterator(input.QueryText); + + List results = new List(); + while (iterator.HasMoreResults) + { + FeedResponse response = iterator.ReadNextAsync().Result; + foreach(var item in response) + { + results.Add(item); + } + } + + return new QueryTestOutput(serializedResults: JsonConvert.SerializeObject(results)); + } + } + + + public sealed class QueryTestInput : BaselineTestInput + { + internal string QueryText; + + internal QueryTestInput( + string description, + string queryText) + : base(description) + { + this.QueryText = queryText; + } + public override void SerializeAsXml(XmlWriter xmlWriter) + { + if (xmlWriter == null) + { + throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); + } + + xmlWriter.WriteStartElement("Description"); + xmlWriter.WriteCData(this.Description); + xmlWriter.WriteEndElement(); + xmlWriter.WriteStartElement("Expression"); + xmlWriter.WriteCData(this.QueryText); + xmlWriter.WriteEndElement(); + } + } + + public class QueryTestOutput : BaselineTestOutput + { + internal string Results { get; } + + internal QueryTestOutput(string serializedResults) + { + this.Results = serializedResults; + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + if (this.Results != null) + { + xmlWriter.WriteStartElement("Results"); + xmlWriter.WriteCData(this.Results); + xmlWriter.WriteEndElement(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml index 0810cfd30e..c832978d6f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml @@ -117,6 +117,124 @@ GROUP BY {"age": c.age}]]> + + + SELECT VALUE object create with non-object create GROUP BY + + SELECT VALUE {"age": c.age} + FROM c + GROUP BY c.age + + Hash + + + + + None + + + + + c.age + + + + + + + True + + + + [[],"Infinity") + + + + + + + + + SELECT VALUE aggregate average + + SELECT VALUE AVG(c.age) + FROM c + GROUP BY c.age + + Hash + + + + + None + + + + + c.age + + + + + Average + + + + True + + + + [[],"Infinity") + + + + + + + + + SELECT VALUE aggregate COUNT + + SELECT VALUE COUNT(1) + FROM c + GROUP BY c.age + + Hash + + + + + None + + + + + c.age + + + + + Count + + + + True + + + + [[],"Infinity") + + + + + + Simple GROUP BY with no aggregates diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs index de604a8934..c9197c48fd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs @@ -60,6 +60,7 @@ private static async Task> CreateAndDrainAsync( continuationToken: continuationToken, cancellationToken: default, monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken cancellationToken) => TryCatch.FromResult(source), + aggregates: new AggregateOperator[] { }, groupByAliasToAggregateType: groupByAliasToAggregateType, orderedAliases: orderedAliases, hasSelectValue: hasSelectValue, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs index 79d674d7b9..204d3608d0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPlanBaselineTests.cs @@ -328,7 +328,6 @@ public void GroupBy() { List testVariations = new List { - //------------------------- // Negative //------------------------- @@ -370,6 +369,27 @@ FROM c FROM c GROUP BY {""age"": c.age}"), + Hash( + @"SELECT VALUE object create with non-object create GROUP BY", + @" + SELECT VALUE {""age"": c.age} + FROM c + GROUP BY c.age"), + + Hash( + @"SELECT VALUE aggregate average", + @" + SELECT VALUE AVG(c.age) + FROM c + GROUP BY c.age"), + + Hash( + @"SELECT VALUE aggregate COUNT", + @" + SELECT VALUE COUNT(1) + FROM c + GROUP BY c.age"), + Hash( @"Simple GROUP BY with no aggregates", @" From 5ab5a7e8093473c0a1ba135ed78af89b8895a400 Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Thu, 25 Jan 2024 07:50:37 -0800 Subject: [PATCH 264/337] Change Feed Processor: Fixes LeaseLostException on Notifications API for Renewer (#4276) * Logging * tests --- .../FeedManagement/PartitionControllerCore.cs | 11 +++ .../ChangeFeed/PartitionControllerTests.cs | 85 ++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs index 7407477c21..37ef33cff5 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedManagement/PartitionControllerCore.cs @@ -161,6 +161,17 @@ private async Task ProcessPartitionAsync(DocumentServiceLease lease) { DefaultTrace.TraceVerbose("Lease with token {0}: processing canceled", lease.CurrentLeaseToken); } + catch (LeaseLostException leaseLostException) + { + // LeaseLostException by itself is not loggable, unless it contains a related inner exception + // For cases when the lease or container has been deleted or the lease has been stolen + if (leaseLostException.InnerException != null) + { + await this.monitor.NotifyErrorAsync(lease.CurrentLeaseToken, leaseLostException.InnerException); + } + + DefaultTrace.TraceVerbose("Lease with token {0}: lease was lost", lease.CurrentLeaseToken); + } catch (Exception ex) { await this.monitor.NotifyErrorAsync(lease.CurrentLeaseToken, ex); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerTests.cs index b273dc563f..d3f9e98569 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/PartitionControllerTests.cs @@ -254,7 +254,7 @@ public async Task Controller_ShouldNotify_IfProcessingFails() manualResetEvent.Set(); throw exception; }); - + Mock.Get(this.partitionSupervisorFactory) .Setup(f => f.Create(this.lease)) .Returns(supervisor.Object); @@ -532,6 +532,89 @@ public async Task Shutdown_ShouldNotify_Monitor() .Verify(m => m.NotifyLeaseReleaseAsync(this.lease.CurrentLeaseToken), Times.Once); } + [TestMethod] + public async Task Renewer_ShouldNotNotify_IfLeaseAcquireFailsWithLeaseLost_WithoutInnerException() + { + Mock.Get(this.partitionProcessor) + .Reset(); + + Mock supervisor = new Mock(); + + LeaseLostException exception = new LeaseLostException(); + + ManualResetEvent manualResetEvent = new ManualResetEvent(false); + + supervisor + .Setup(s => s.RunAsync(It.IsAny())) + .ThrowsAsync(exception) + .Callback((CancellationToken ct) => + { + manualResetEvent.Set(); + throw exception; + }); + + Mock.Get(this.partitionSupervisorFactory) + .Setup(f => f.Create(this.lease)) + .Returns(supervisor.Object); + + await this.sut.AddOrUpdateLeaseAsync(this.lease); + + bool timeout = manualResetEvent.WaitOne(100); + Assert.IsTrue(timeout, "Partition supervisor not started"); + + this.healthMonitor + .Verify(m => m.NotifyErrorAsync(this.lease.CurrentLeaseToken, exception), Times.Never); + + Mock.Get(this.leaseManager) + .Verify(manager => manager.ReleaseAsync(this.lease), Times.Once); + + this.healthMonitor + .Verify(m => m.NotifyLeaseReleaseAsync(this.lease.CurrentLeaseToken), Times.Once); + } + + [TestMethod] + public async Task Renewer_ShouldNotify_IfLeaseAcquireFailsWithLeaseLost_WithInnerException() + { + Mock.Get(this.partitionProcessor) + .Reset(); + + Mock supervisor = new Mock(); + + Exception internalException = new Exception(); + + LeaseLostException exception = new LeaseLostException("some error", internalException); + + ManualResetEvent manualResetEvent = new ManualResetEvent(false); + + supervisor + .Setup(s => s.RunAsync(It.IsAny())) + .Callback((CancellationToken ct) => + { + manualResetEvent.Set(); + throw exception; + }); + + Mock.Get(this.partitionSupervisorFactory) + .Setup(f => f.Create(this.lease)) + .Returns(supervisor.Object); + + await this.sut.AddOrUpdateLeaseAsync(this.lease).ConfigureAwait(false); + + bool timeout = manualResetEvent.WaitOne(100); + Assert.IsTrue(timeout, "Partition supervisor not started"); + + this.healthMonitor + .Verify(m => m.NotifyErrorAsync(this.lease.CurrentLeaseToken, internalException), Times.Once); + + Mock.Get(this.leaseManager) + .Verify(manager => manager.ReleaseAsync(this.lease), Times.Once); + + this.healthMonitor + .Verify(m => m.NotifyLeaseReleaseAsync(this.lease.CurrentLeaseToken), Times.Once); + } + + + public Task InitializeAsync() { return Task.FromResult(false); From 32d0078647da6b2a65174beb0c7dae7f4af14f8e Mon Sep 17 00:00:00 2001 From: leminh98 Date: Thu, 25 Jan 2024 15:04:52 -0800 Subject: [PATCH 265/337] [Internal] Query: Adds ability to send plain text response as the default (#4183) * add baseline tests * added back missing bracket * Enable text response for index advisor * update csproj * address code review * update tests --------- Co-authored-by: Minh Le --- .../src/Handler/ResponseMessage.cs | 8 +- .../src/Query/v3Query/QueryResponse.cs | 7 +- .../src/RequestOptions/QueryRequestOptions.cs | 3 +- ...eTest.IndexUtilizationHeaderLengthTest.xml | 56 +------- ...rserBaselineTest.IndexUtilizationParse.xml | 121 ++---------------- 5 files changed, 23 insertions(+), 172 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs index 60ff675172..e29204c489 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs @@ -83,7 +83,7 @@ internal ResponseMessage( this.CosmosException = cosmosException; this.Headers = headers ?? new Headers(); - this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics(this.Headers, true); + this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics(this.Headers, isBase64Encoded: true); if (requestMessage != null && requestMessage.Trace != null) { @@ -269,9 +269,9 @@ static internal Lazy DecodeIndexMetrics(Headers responseMessageHeaders, return stringBuilder.ToString(); } - - // Return the JSON from the response header - return responseMessageHeaders.IndexUtilizationText; + + // Return the JSON from the response header after url decode + return System.Web.HttpUtility.UrlDecode(responseMessageHeaders.IndexUtilizationText, Encoding.UTF8); }); } diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs index 47c9136a8f..49f9e40232 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs @@ -184,12 +184,11 @@ private QueryResponse( cosmosArray: cosmosElements, serializerCore: serializerCore); - // Chose how to decode depending on which PopulateIndexMetrics request header was sent - // If none was sent, we currently default to V1 - // TODO: Switch the flag to false once V2 is deployed + // 1/25/2024: The default for request message is plain text + // for any release after this date, no longer base64 encoded this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics( responseMessageHeaders, - isBase64Encoded: true); + isBase64Encoded: false); this.RequestMessage = requestMessage; } diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 3e410c3892..7d4da6f535 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -260,8 +260,7 @@ internal override void PopulateRequestOptions(RequestMessage request) if (this.PopulateIndexMetrics.HasValue) { - // TODO: Switch to V2 - request.Headers.CosmosMessageHeaders.Add(HttpConstants.HttpHeaders.PopulateIndexMetrics, this.PopulateIndexMetrics.ToString()); + request.Headers.CosmosMessageHeaders.Add(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, this.PopulateIndexMetrics.ToString()); } DedicatedGatewayRequestOptions.PopulateMaxIntegratedCacheStalenessOption(this.DedicatedGatewayRequestOptions, request); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml index 749f507caf..90bb023e23 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationHeaderLengthTest.xml @@ -5,16 +5,7 @@ - + @@ -23,19 +14,7 @@ Index Utilization Information 0 AND r.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb > 0]]> - + @@ -44,22 +23,7 @@ Index Utilization Information 0]]> - + @@ -68,19 +32,7 @@ Index Utilization Information 0 AND r.cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc > 0]]> - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationParse.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationParse.xml index 6c780ba437..414ce6838f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationParse.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationParse.xml @@ -7,16 +7,7 @@ FROM c WHERE STARTSWITH(c.statement, 'The quick brown fox jumps over the lazy dog', false)]]> - + @@ -27,16 +18,7 @@ FROM c WHERE STARTSWITH(c['Η γρήγορη καφέ αλεπού πηδάει πάνω από το τεμπέλικο ÏƑκυλί'], 's', false)]]> - + @@ -45,16 +27,7 @@ Index Utilization Information - + @@ -63,16 +36,7 @@ Index Utilization Information - + @@ -81,16 +45,7 @@ Index Utilization Information ?:"{}|ßÁŒÆ12ếàưỏốởặ'], 's', true) FROM root r]]> - ?:\"{}|ßÁŒÆ12ếàưỏốởặ"/? - Index Impact Score: High - --- - Potential Single Indexes - Utilized Composite Indexes - Potential Composite Indexes -]]> + ?:\\\"{}|ßÁŒÆ12ếàưỏốởặ\"\/?","FilterPreciseSet":true,"IndexPreciseSet":true,"IndexImpactScore":"High"}],"PotentialSingleIndexes":[],"UtilizedCompositeIndexes":[],"PotentialCompositeIndexes":[]}]]> @@ -99,16 +54,7 @@ Index Utilization Information - + @@ -117,16 +63,7 @@ Index Utilization Information - + @@ -135,16 +72,7 @@ Index Utilization Information - + @@ -153,16 +81,7 @@ Index Utilization Information - + @@ -171,16 +90,7 @@ Index Utilization Information - + @@ -189,16 +99,7 @@ Index Utilization Information - + \ No newline at end of file From 7209b3878253215f27fa7e0b14f1d609844179bf Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:02:24 -0800 Subject: [PATCH 266/337] Region Availability: Adds Spain Central and Mexico Central Regions For Public Usage. (#4279) * Code changes to add spain and mexico central regions for public usage. * Code changes to revert isreal central region. * Code changes to add isreal central region in API contract. * Code changes to fix test failures. --------- Co-authored-by: Matias Quaranta --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/Regions.cs | 10 ++++++++++ .../Contracts/DotNetSDKAPI.json | 10 ++++++++++ .../ValidationHelpersTests.cs | 3 ++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index d77c3f59e3..7e9c4741ba 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.37.1 3.37.1 preview - 3.31.5 + 3.32.0 2.0.4 2.1.0 preview4 diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index 33c258aaf7..aae88eb22b 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -364,5 +364,15 @@ public static class Regions /// Name of the Azure Israel Central region in the Azure Cosmos DB service. /// public const string IsraelCentral = "Israel Central"; + + /// + /// Name of the Azure Mexico Central region in the Azure Cosmos DB service. + /// + public const string MexicoCentral = "Mexico Central"; + + /// + /// Name of the Azure Spain Central region in the Azure Cosmos DB service. + /// + public const string SpainCentral = "Spain Central"; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 9b73ab714a..f49a470177 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -6904,6 +6904,11 @@ "Attributes": [], "MethodInfo": "System.String MalaysiaSouth;IsInitOnly:False;IsStatic:True;" }, + "System.String MexicoCentral": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String MexicoCentral;IsInitOnly:False;IsStatic:True;" + }, "System.String NorthCentralUS": { "Type": "Field", "Attributes": [], @@ -6959,6 +6964,11 @@ "Attributes": [], "MethodInfo": "System.String SouthIndia;IsInitOnly:False;IsStatic:True;" }, + "System.String SpainCentral": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String SpainCentral;IsInitOnly:False;IsStatic:True;" + }, "System.String SwedenCentral": { "Type": "Field", "Attributes": [], diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs index dbfc45eb36..b369d491cf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ValidationHelpersTests.cs @@ -75,7 +75,8 @@ public void TestIsValidConsistencyLevelOverwrite_BoundedPromotionsRejected( Documents.OperationTypeExtensions.IsReadOperation(operationType) && operationType != Documents.OperationType.Head && operationType != Documents.OperationType.HeadFeed - && operationType != Documents.OperationType.QueryPlan); + && operationType != Documents.OperationType.QueryPlan + && operationType != Documents.OperationType.MetadataCheckAccess); } return perOperationOverride; From 06333893e3315cfe54bc733e3363596b6f1974a6 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Fri, 26 Jan 2024 12:01:24 -0800 Subject: [PATCH 267/337] Changed to Async Method (#4284) --- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 14 ++++++++++++-- .../src/FaultInjection/IChaosInterceptorFactory.cs | 3 ++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index f205815a5c..7d5a572754 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -115,7 +115,9 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider private readonly bool IsLocalQuorumConsistency = false; private readonly bool isReplicaAddressValidationEnabled; - private readonly IChaosInterceptor chaosInterceptor; + //Fault Injection + private readonly IChaosInterceptorFactory chaosInterceptorFactory; + private IChaosInterceptor chaosInterceptor; //Auth internal readonly AuthorizationTokenProvider cosmosAuthorization; @@ -487,7 +489,7 @@ internal DocumentClient(Uri serviceEndpoint, this.transportClientHandlerFactory = transportClientHandlerFactory; this.IsLocalQuorumConsistency = isLocalQuorumConsistency; this.initTaskCache = new AsyncCacheNonBlocking(cancellationToken: this.cancellationTokenSource.Token); - this.chaosInterceptor = chaosInterceptorFactory?.CreateInterceptor(this); + this.chaosInterceptorFactory = chaosInterceptorFactory; this.Initialize( serviceEndpoint: serviceEndpoint, @@ -1015,6 +1017,14 @@ internal virtual void Initialize(Uri serviceEndpoint, // Always called from under the lock except when called from Intilialize method during construction. private async Task GetInitializationTaskAsync(IStoreClientFactory storeClientFactory) { + //Create the chaos interceptor if using fault injection + //Creating the chaos interceptor requires async calls, so we do it here instead of in the constructor + //This must also be done before creating the storeClientFactory for direct mode + if (this.chaosInterceptorFactory != null) + { + this.chaosInterceptor = await this.chaosInterceptorFactory.CreateInterceptorAsync(this); + } + await this.InitializeGatewayConfigurationReaderAsync(); if (this.desiredConsistencyLevel.HasValue) diff --git a/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs index d87a9d25a0..85aafeb1e3 100644 --- a/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs +++ b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs @@ -3,6 +3,7 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Cosmos { + using System.Threading.Tasks; using Microsoft.Azure.Documents.FaultInjection; /// @@ -15,6 +16,6 @@ internal interface IChaosInterceptorFactory /// Creates the IChaosInterceptor interceptor that will be used to inject fault injection rules. /// /// - public IChaosInterceptor CreateInterceptor(DocumentClient documentClient); + public Task CreateInterceptorAsync(DocumentClient documentClient); } } \ No newline at end of file From 1bbe101e2bef34e683949653388260e35082ca95 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 30 Jan 2024 06:50:08 +0530 Subject: [PATCH 268/337] CosmosClientOptions: Adds validation to check DisableServerCertificateValidation and ServerCertificateCustomValidationCallback are set together (#4283) * Added validation to check HttpFactory and ServerCallback are set together * fix validation --- .../src/CosmosClientOptions.cs | 21 ++++++++++++++++++- .../CosmosClientOptionsUnitTests.cs | 13 ++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 1fd66c3169..8700f2e56e 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -731,6 +731,11 @@ internal Protocol ConnectionProtocol /// Flag that controls whether CPU monitoring thread is created to enrich timeout exceptions with additional diagnostic. Default value is true. /// internal bool? EnableCpuMonitor { get; set; } + + /// + /// Flag indicates the value of DisableServerCertificateValidation flag set at connection string level.Default it is false. + /// + internal bool DisableServerCertificateValidation { get; set; } /// /// Gets or sets Client Telemetry Options like feature flags and corresponding options @@ -758,6 +763,7 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) this.ValidateDirectTCPSettings(); this.ValidateLimitToEndpointSettings(); this.ValidatePartitionLevelFailoverSettings(); + this.ValidateAndSetServerCallbackSettings(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -866,7 +872,7 @@ internal static CosmosClientOptions GetCosmosClientOptionsWithCertificateFlag(st clientOptions ??= new CosmosClientOptions(); if (CosmosClientOptions.IsConnectionStringDisableServerCertificateValidationFlag(connectionString)) { - clientOptions.ServerCertificateCustomValidationCallback = (_, _, _) => true; + clientOptions.DisableServerCertificateValidation = true; } return clientOptions; @@ -929,6 +935,19 @@ private void ValidatePartitionLevelFailoverSettings() { throw new ArgumentException($"{nameof(this.ApplicationPreferredRegions)} is required when {nameof(this.EnablePartitionLevelFailover)} is enabled."); } + } + + private void ValidateAndSetServerCallbackSettings() + { + if (this.DisableServerCertificateValidation && this.ServerCertificateCustomValidationCallback != null) + { + throw new ArgumentException($"Cannot specify {nameof(this.DisableServerCertificateValidation)} flag in Connection String and {nameof(this.ServerCertificateCustomValidationCallback)}. Only one can be set."); + } + + if (this.DisableServerCertificateValidation) + { + this.ServerCertificateCustomValidationCallback = (_, _, _) => true; + } } private void ValidateDirectTCPSettings() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 51aee132ae..b0b6b8be35 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -892,6 +892,7 @@ public void InvalidApplicationNameCatchTest() [TestMethod] [DataRow(ConnectionString, false)] [DataRow(ConnectionString + "DisableServerCertificateValidation=true;", true)] + [DataRow(ConnectionString + "DisableServerCertificateValidation=false;", false)] public void TestServerCertificatesValidationCallback(string connStr, bool expectedIgnoreCertificateFlag) { //Arrange @@ -913,6 +914,18 @@ public void TestServerCertificatesValidationCallback(string connStr, bool expect Assert.IsNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); } } + + [TestMethod] + [DataRow(ConnectionString + "DisableServerCertificateValidation=true;")] + [ExpectedException(typeof(ArgumentException))] + public void TestServerCertificatesValidationWithDisableSSLFlagTrue(string connStr) + { + CosmosClientOptions options = new CosmosClientOptions + { + ServerCertificateCustomValidationCallback = (certificate, chain, sslPolicyErrors) => true + }; + CosmosClient cosmosClient = new CosmosClient(connStr, options); + } private class TestWebProxy : IWebProxy { From 2c7c7ad39dec358f7b75e3158d8739afa688ff9f Mon Sep 17 00:00:00 2001 From: Aditya Date: Mon, 29 Jan 2024 21:09:27 -0800 Subject: [PATCH 269/337] Query: Adds LINQ Support for FirstOrDefault (#4286) * Initial commit * Fixed failing aggregate tests. * Added validation for unsupported overloads of FirstOrDefault. * Addressed a couple of TODOs. * Addressed comments. * Addressed comments. * Addressed remaining comment. --- .../src/Linq/CosmosLinqExtensions.cs | 3 +- .../src/Linq/CosmosLinqQuery.cs | 95 +- .../src/Linq/CosmosLinqQueryProvider.cs | 5 +- .../src/Linq/DocumentQuery.cs | 6 +- .../src/Linq/DocumentQueryEvaluator.cs | 17 +- .../src/Linq/ExpressionToSQL.cs | 143 +- .../src/Linq/LinqQueryOperation.cs | 24 + .../src/Linq/SQLTranslator.cs | 10 +- .../src/Linq/ScalarOperationKind.cs | 27 + .../src/Linq/TranslationContext.cs | 16 + .../DocumentQueryExecutionContextBase.cs | 9 +- ...nctionBaselineTests.TestFirstOrDefault.xml | 231 +++ .../Linq/ILinqTestDataGenerator.cs | 14 + .../Linq/LinqCleanupTests.cs | 71 + .../Linq/LinqScalarFunctionBaselineTests.cs | 332 +++ .../Linq/LinqTestData.cs | 45 +- .../Linq/LinqTestDataGenerator.cs | 34 + .../Linq/LinqTestRandomDataGenerator.cs | 41 + .../Linq/LinqTestsCommon.cs | 1798 ++++++++--------- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 4 + 20 files changed, 1924 insertions(+), 1001 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Linq/LinqQueryOperation.cs create mode 100644 Microsoft.Azure.Cosmos/src/Linq/ScalarOperationKind.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqScalarFunctionBaselineTests.TestFirstOrDefault.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/ILinqTestDataGenerator.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqScalarFunctionBaselineTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestDataGenerator.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestRandomDataGenerator.cs diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs index 619c1c1ecf..7f7a22b466 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqExtensions.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq; using System.Linq.Expressions; using System.Reflection; - using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Diagnostics; @@ -774,7 +773,7 @@ public static Task> SumAsync( return ResponseHelperAsync(source.Sum()); } - return ((CosmosLinqQueryProvider)source.Provider).ExecuteAggregateAsync( + return cosmosLinqQueryProvider.ExecuteAggregateAsync( Expression.Call( GetMethodInfoOf, int?>(Queryable.Sum), source.Expression), diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs index a4c4c5e938..6676d096c9 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQuery.cs @@ -16,6 +16,7 @@ namespace Microsoft.Azure.Cosmos.Linq using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; using Newtonsoft.Json; + using Debug = System.Diagnostics.Debug; /// /// This is the entry point for LINQ query creation/execution, it generate query provider, implements IOrderedQueryable. @@ -108,7 +109,12 @@ public IEnumerator GetEnumerator() " use GetItemQueryIterator to execute asynchronously"); } - FeedIterator localFeedIterator = this.CreateFeedIterator(false); + FeedIterator localFeedIterator = this.CreateFeedIterator(false, out ScalarOperationKind scalarOperationKind); + Debug.Assert( + scalarOperationKind == ScalarOperationKind.None, + "CosmosLinqQuery Assert!", + $"Unexpected client operation. Expected 'None', Received '{scalarOperationKind}'"); + while (localFeedIterator.HasMoreResults) { #pragma warning disable VSTHRD002 // Avoid problematic synchronous waits @@ -133,7 +139,7 @@ IEnumerator IEnumerable.GetEnumerator() public override string ToString() { - SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions); + SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions).SqlQuerySpec; if (querySpec != null) { return JsonConvert.SerializeObject(querySpec); @@ -144,20 +150,36 @@ public override string ToString() public QueryDefinition ToQueryDefinition(IDictionary parameters = null) { - SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions, parameters); - return QueryDefinition.CreateFromQuerySpec(querySpec); + LinqQueryOperation linqQueryOperation = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions, parameters); + ScalarOperationKind scalarOperationKind = linqQueryOperation.ScalarOperationKind; + Debug.Assert( + scalarOperationKind == ScalarOperationKind.None, + "CosmosLinqQuery Assert!", + $"Unexpected client operation. Expected 'None', Received '{scalarOperationKind}'"); + + return QueryDefinition.CreateFromQuerySpec(linqQueryOperation.SqlQuerySpec); } public FeedIterator ToFeedIterator() { - return new FeedIteratorInlineCore(this.CreateFeedIterator(true), - this.container.ClientContext); + FeedIterator iterator = this.CreateFeedIterator(true, out ScalarOperationKind scalarOperationKind); + Debug.Assert( + scalarOperationKind == ScalarOperationKind.None, + "CosmosLinqQuery Assert!", + $"Unexpected client operation. Expected 'None', Received '{scalarOperationKind}'"); + + return new FeedIteratorInlineCore(iterator, this.container.ClientContext); } public FeedIterator ToStreamIterator() { - return new FeedIteratorInlineCore(this.CreateStreamIterator(true), - this.container.ClientContext); + FeedIterator iterator = this.CreateStreamIterator(true, out ScalarOperationKind scalarOperationKind); + Debug.Assert( + scalarOperationKind == ScalarOperationKind.None, + "CosmosLinqQuery Assert!", + $"Unexpected client operation. Expected 'None', Received '{scalarOperationKind}'"); + + return new FeedIteratorInlineCore(iterator, this.container.ClientContext); } public void Dispose() @@ -180,15 +202,18 @@ internal async Task> AggregateResultAsync(CancellationToken cancella List result = new List(); Headers headers = new Headers(); - FeedIterator localFeedIterator = this.CreateFeedIterator(isContinuationExpected: false); - FeedIteratorInternal localFeedIteratorInternal = (FeedIteratorInternal)localFeedIterator; + FeedIteratorInlineCore localFeedIterator = this.CreateFeedIterator(isContinuationExpected: false, scalarOperationKind: out ScalarOperationKind scalarOperationKind); + Debug.Assert( + scalarOperationKind == ScalarOperationKind.None, + "CosmosLinqQuery Assert!", + $"Unexpected client operation. Expected 'None', Received '{scalarOperationKind}'"); ITrace rootTrace; using (rootTrace = Trace.GetRootTrace("Aggregate LINQ Operation")) { while (localFeedIterator.HasMoreResults) { - FeedResponse response = await localFeedIteratorInternal.ReadNextAsync(rootTrace, cancellationToken); + FeedResponse response = await localFeedIterator.ReadNextAsync(rootTrace, cancellationToken); headers.RequestCharge += response.RequestCharge; result.AddRange(response); } @@ -202,23 +227,57 @@ internal async Task> AggregateResultAsync(CancellationToken cancella null); } - private FeedIteratorInternal CreateStreamIterator(bool isContinuationExcpected) + internal T ExecuteScalar() + { + FeedIteratorInlineCore localFeedIterator = this.CreateFeedIterator(isContinuationExpected: false, out ScalarOperationKind scalarOperationKind); + Headers headers = new Headers(); + + List result = new List(); + ITrace rootTrace; + using (rootTrace = Trace.GetRootTrace("Scalar LINQ Operation")) + { + while (localFeedIterator.HasMoreResults) + { + FeedResponse response = localFeedIterator.ReadNextAsync(rootTrace, cancellationToken: default).GetAwaiter().GetResult(); + headers.RequestCharge += response.RequestCharge; + result.AddRange(response); + } + } + + switch (scalarOperationKind) + { + case ScalarOperationKind.FirstOrDefault: + return result.FirstOrDefault(); + + // ExecuteScalar gets called when (sync) aggregates such as Max, Min, Sum are invoked on the IQueryable. + // Since query fully supprots these operations, there is no client operation involved. + // In these cases we return FirstOrDefault which handles empty/undefined/null result set from the backend. + case ScalarOperationKind.None: + return result.SingleOrDefault(); + + default: + throw new InvalidOperationException($"Unsupported scalar operation {scalarOperationKind}"); + } + } + + private FeedIteratorInternal CreateStreamIterator(bool isContinuationExcpected, out ScalarOperationKind scalarOperationKind) { - SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions); + LinqQueryOperation linqQueryOperation = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions); + scalarOperationKind = linqQueryOperation.ScalarOperationKind; return this.container.GetItemQueryStreamIteratorInternal( - sqlQuerySpec: querySpec, + sqlQuerySpec: linqQueryOperation.SqlQuerySpec, isContinuationExcpected: isContinuationExcpected, continuationToken: this.continuationToken, feedRange: null, requestOptions: this.cosmosQueryRequestOptions); } - private FeedIterator CreateFeedIterator(bool isContinuationExpected) + private FeedIteratorInlineCore CreateFeedIterator(bool isContinuationExpected, out ScalarOperationKind scalarOperationKind) { - SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression, this.linqSerializationOptions); - - FeedIteratorInternal streamIterator = this.CreateStreamIterator(isContinuationExpected); + FeedIteratorInternal streamIterator = this.CreateStreamIterator( + isContinuationExpected, + out scalarOperationKind); return new FeedIteratorInlineCore(new FeedIteratorCore( streamIterator, this.responseFactory.CreateQueryFeedUserTypeResponse), diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs index 2c695c6477..d681caaef5 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosLinqQueryProvider.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; + using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; @@ -60,6 +61,7 @@ public IQueryable CreateQuery(Expression expression) public IQueryable CreateQuery(Expression expression) { + // ISSUE-TODO-adityasa-2024/1/26 - Investigate if reflection usage can be removed. Type expressionType = TypeSystem.GetElementType(expression.Type); Type documentQueryType = typeof(CosmosLinqQuery).GetGenericTypeDefinition().MakeGenericType(expressionType); return (IQueryable)Activator.CreateInstance( @@ -76,6 +78,7 @@ public IQueryable CreateQuery(Expression expression) public TResult Execute(Expression expression) { + // ISSUE-TODO-adityasa-2024/1/26 - We should be able to delegate the implementation to ExecuteAggregateAsync method below by providing an Async implementation of ExecuteScalar. Type cosmosQueryType = typeof(CosmosLinqQuery).GetGenericTypeDefinition().MakeGenericType(typeof(TResult)); CosmosLinqQuery cosmosLINQQuery = (CosmosLinqQuery)Activator.CreateInstance( cosmosQueryType, @@ -88,7 +91,7 @@ public TResult Execute(Expression expression) this.allowSynchronousQueryExecution, this.linqSerializerOptions); this.onExecuteScalarQueryCallback?.Invoke(cosmosLINQQuery); - return cosmosLINQQuery.ToList().FirstOrDefault(); + return cosmosLINQQuery.ExecuteScalar(); } //Sync execution of query via direct invoke on IQueryProvider. diff --git a/Microsoft.Azure.Cosmos/src/Linq/DocumentQuery.cs b/Microsoft.Azure.Cosmos/src/Linq/DocumentQuery.cs index 6d0b7f82b0..be86284dab 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/DocumentQuery.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/DocumentQuery.cs @@ -273,10 +273,10 @@ IEnumerator IEnumerable.GetEnumerator() public override string ToString() { - SqlQuerySpec querySpec = DocumentQueryEvaluator.Evaluate(this.Expression); - if (querySpec != null) + LinqQueryOperation linqQueryOperation = DocumentQueryEvaluator.Evaluate(this.Expression); + if (linqQueryOperation.SqlQuerySpec != null) { - return JsonConvert.SerializeObject(querySpec); + return JsonConvert.SerializeObject(linqQueryOperation.SqlQuerySpec); } return new Uri(this.client.ServiceEndpoint, this.documentsFeedOrDatabaseLink).ToString(); diff --git a/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs b/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs index da25188bc2..dec354bd19 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/DocumentQueryEvaluator.cs @@ -15,7 +15,7 @@ internal static class DocumentQueryEvaluator { private const string SQLMethod = "AsSQL"; - public static SqlQuerySpec Evaluate( + public static LinqQueryOperation Evaluate( Expression expression, CosmosLinqSerializerOptionsInternal linqSerializerOptions = null, IDictionary parameters = null) @@ -51,7 +51,7 @@ public static bool IsTransformExpression(Expression expression) /// foreach(Database db in client.CreateDatabaseQuery()) {} /// /// - private static SqlQuerySpec HandleEmptyQuery(ConstantExpression expression) + private static LinqQueryOperation HandleEmptyQuery(ConstantExpression expression) { if (expression.Value == null) { @@ -69,11 +69,12 @@ private static SqlQuerySpec HandleEmptyQuery(ConstantExpression expression) ClientResources.BadQuery_InvalidExpression, expression.ToString())); } + //No query specified. - return null; + return new LinqQueryOperation(sqlQuerySpec: null, scalarOperationKind: ScalarOperationKind.None); } - private static SqlQuerySpec HandleMethodCallExpression( + private static LinqQueryOperation HandleMethodCallExpression( MethodCallExpression expression, IDictionary parameters, CosmosLinqSerializerOptionsInternal linqSerializerOptions = null) @@ -100,7 +101,7 @@ private static SqlQuerySpec HandleMethodCallExpression( /// foreach(string record in client.CreateDocumentQuery().Navigate("Raw JQuery")) /// /// - private static SqlQuerySpec HandleAsSqlTransformExpression(MethodCallExpression expression) + private static LinqQueryOperation HandleAsSqlTransformExpression(MethodCallExpression expression) { Expression paramExpression = expression.Arguments[1]; @@ -122,7 +123,7 @@ private static SqlQuerySpec HandleAsSqlTransformExpression(MethodCallExpression } } - private static SqlQuerySpec GetSqlQuerySpec(object value) + private static LinqQueryOperation GetSqlQuerySpec(object value) { if (value == null) { @@ -133,11 +134,11 @@ private static SqlQuerySpec GetSqlQuerySpec(object value) } else if (value.GetType() == typeof(SqlQuerySpec)) { - return (SqlQuerySpec)value; + return new LinqQueryOperation((SqlQuerySpec)value, ScalarOperationKind.None); } else if (value.GetType() == typeof(string)) { - return new SqlQuerySpec((string)value); + return new LinqQueryOperation(new SqlQuerySpec((string)value), ScalarOperationKind.None); } else { diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index ad9d02cab4..62b9132a8e 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -59,18 +59,22 @@ public static class LinqMethods public const string Any = "Any"; public const string Average = "Average"; public const string Count = "Count"; + public const string Distinct = "Distinct"; + public const string First = "First"; + public const string FirstOrDefault = "FirstOrDefault"; public const string Max = "Max"; public const string Min = "Min"; public const string OrderBy = "OrderBy"; - public const string ThenBy = "ThenBy"; public const string OrderByDescending = "OrderByDescending"; - public const string ThenByDescending = "ThenByDescending"; public const string Select = "Select"; public const string SelectMany = "SelectMany"; - public const string Sum = "Sum"; + public const string Single = "Single"; + public const string SingleOrDefault = "SingleOrDefault"; public const string Skip = "Skip"; + public const string Sum = "Sum"; + public const string ThenBy = "ThenBy"; + public const string ThenByDescending = "ThenByDescending"; public const string Take = "Take"; - public const string Distinct = "Distinct"; public const string Where = "Where"; } @@ -84,11 +88,13 @@ public static class LinqMethods /// An Expression representing a Query on a IDocumentQuery object. /// Optional dictionary for parameter name and value /// Optional serializer options. + /// Indicates the client operation that needs to be performed on the results of SqlQuery. /// The corresponding SQL query. public static SqlQuery TranslateQuery( Expression inputExpression, IDictionary parameters, - CosmosLinqSerializerOptionsInternal linqSerializerOptions) + CosmosLinqSerializerOptionsInternal linqSerializerOptions, + out ScalarOperationKind clientOperation) { TranslationContext context = new TranslationContext(linqSerializerOptions, parameters); ExpressionToSql.Translate(inputExpression, context); // ignore result here @@ -96,6 +102,7 @@ public static SqlQuery TranslateQuery( QueryUnderConstruction query = context.CurrentQuery; query = query.FlattenAsPossible(); SqlQuery result = query.GetSqlQuery(); + clientOperation = context.ClientOperation; return result; } @@ -1149,22 +1156,67 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.PushSubqueryBinding(shouldBeOnNewQuery); switch (inputExpression.Method.Name) { - case LinqMethods.Select: + case LinqMethods.Any: { - SqlSelectClause select = ExpressionToSql.VisitSelect(inputExpression.Arguments, context); + result = new Collection(string.Empty); + + if (inputExpression.Arguments.Count == 2) + { + // Any is translated to an SELECT VALUE EXISTS() where Any operation itself is treated as a Where. + SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); + } + break; + } + case LinqMethods.Average: + { + SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Avg); context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } - case LinqMethods.Where: + case LinqMethods.Count: { - SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); + SqlSelectClause select = ExpressionToSql.VisitCount(inputExpression.Arguments, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } - case LinqMethods.SelectMany: + case LinqMethods.Distinct: { - context.CurrentQuery = context.PackageCurrentQueryIfNeccessary(); - result = ExpressionToSql.VisitSelectMany(inputExpression.Arguments, context); + SqlSelectClause select = ExpressionToSql.VisitDistinct(inputExpression.Arguments, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + break; + } + case LinqMethods.FirstOrDefault: + { + if (inputExpression.Arguments.Count == 1) + { + // TOP is not allowed when OFFSET ... LIMIT is present. + if (!context.CurrentQuery.HasOffsetSpec()) + { + SqlNumberLiteral sqlNumberLiteral = SqlNumberLiteral.Create(1); + SqlTopSpec topSpec = SqlTopSpec.Create(sqlNumberLiteral); + context.CurrentQuery = context.CurrentQuery.AddTopSpec(topSpec); + } + + context.SetClientOperation(ScalarOperationKind.FirstOrDefault); + } + else + { + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.InvalidArgumentsCount, inputExpression.Method.Name, 0, inputExpression.Arguments.Count - 1)); + } + + break; + } + case LinqMethods.Max: + { + SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Max); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + break; + } + case LinqMethods.Min: + { + SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Min); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.OrderBy: @@ -1179,16 +1231,16 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.CurrentQuery = context.CurrentQuery.AddOrderByClause(orderBy, context); break; } - case LinqMethods.ThenBy: + case LinqMethods.Select: { - SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); - context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); + SqlSelectClause select = ExpressionToSql.VisitSelect(inputExpression.Arguments, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } - case LinqMethods.ThenByDescending: + case LinqMethods.SelectMany: { - SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); - context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); + context.CurrentQuery = context.PackageCurrentQueryIfNeccessary(); + result = ExpressionToSql.VisitSelectMany(inputExpression.Arguments, context); break; } case LinqMethods.Skip: @@ -1197,6 +1249,12 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.CurrentQuery = context.CurrentQuery.AddOffsetSpec(offsetSpec, context); break; } + case LinqMethods.Sum: + { + SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Sum); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + break; + } case LinqMethods.Take: { if (context.CurrentQuery.HasOffsetSpec()) @@ -1211,51 +1269,22 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, } break; } - case LinqMethods.Distinct: - { - SqlSelectClause select = ExpressionToSql.VisitDistinct(inputExpression.Arguments, context); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); - break; - } - case LinqMethods.Max: - { - SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Max); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); - break; - } - case LinqMethods.Min: - { - SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Min); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); - break; - } - case LinqMethods.Average: - { - SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Avg); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); - break; - } - case LinqMethods.Count: + case LinqMethods.ThenBy: { - SqlSelectClause select = ExpressionToSql.VisitCount(inputExpression.Arguments, context); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } - case LinqMethods.Sum: + case LinqMethods.ThenByDescending: { - SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Sum); - context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } - case LinqMethods.Any: + case LinqMethods.Where: { - result = new Collection(string.Empty); - if (inputExpression.Arguments.Count == 2) - { - // Any is translated to an SELECT VALUE EXISTS() where Any operation itself is treated as a Where. - SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); - } + SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); break; } default: diff --git a/Microsoft.Azure.Cosmos/src/Linq/LinqQueryOperation.cs b/Microsoft.Azure.Cosmos/src/Linq/LinqQueryOperation.cs new file mode 100644 index 0000000000..b1f07bc561 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/LinqQueryOperation.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Linq +{ + using Microsoft.Azure.Cosmos.Query.Core; + + /// + /// Represents a linq expression as a combination of sql query and client operation. + /// + internal class LinqQueryOperation + { + public LinqQueryOperation(SqlQuerySpec sqlQuerySpec, ScalarOperationKind scalarOperationKind) + { + this.SqlQuerySpec = sqlQuerySpec; + this.ScalarOperationKind = scalarOperationKind; + } + + public SqlQuerySpec SqlQuerySpec { get; } + + public ScalarOperationKind ScalarOperationKind { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs index 8491d9cf0c..9cf44e1af0 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs @@ -42,14 +42,13 @@ internal static string TranslateExpressionOld( return scalarExpression.ToString(); } - internal static SqlQuerySpec TranslateQuery( + internal static LinqQueryOperation TranslateQuery( Expression inputExpression, CosmosLinqSerializerOptionsInternal linqSerializerOptions, IDictionary parameters) { inputExpression = ConstantEvaluator.PartialEval(inputExpression); - SqlQuery query = ExpressionToSql.TranslateQuery(inputExpression, parameters, linqSerializerOptions); - string queryText = null; + SqlQuery query = ExpressionToSql.TranslateQuery(inputExpression, parameters, linqSerializerOptions, out ScalarOperationKind clientOperation); SqlParameterCollection sqlParameters = new SqlParameterCollection(); if (parameters != null && parameters.Count > 0) { @@ -58,10 +57,11 @@ internal static SqlQuerySpec TranslateQuery( sqlParameters.Add(new Microsoft.Azure.Cosmos.Query.Core.SqlParameter(keyValuePair.Value, keyValuePair.Key)); } } - queryText = query.ToString(); + + string queryText = query.ToString(); SqlQuerySpec sqlQuerySpec = new SqlQuerySpec(queryText, sqlParameters); - return sqlQuerySpec; + return new LinqQueryOperation(sqlQuerySpec, clientOperation); } } } diff --git a/Microsoft.Azure.Cosmos/src/Linq/ScalarOperationKind.cs b/Microsoft.Azure.Cosmos/src/Linq/ScalarOperationKind.cs new file mode 100644 index 0000000000..a145af3e6d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/ScalarOperationKind.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Linq +{ + /// + /// Represents the operation that needs to be performed on the client side. + /// + /// + /// This enum represents scalar operations such as FirstOrDefault. Scalar operations are disallowed in sub-expressions/sub-queries. + /// With these restrictations, enum is sufficient, but in future for a larger surface area we may need + /// to use an object model like ClientQL to represent these operations better. + /// + internal enum ScalarOperationKind + { + /// + /// Indicates that client does not need to perform any operation on query results. + /// + None, + + /// + /// Indicates that the client needs to perform FirstOrDefault on the query results returned by the backend. + /// + FirstOrDefault + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index 3b1d9cd20b..82150b6d4a 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Linq { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq.Expressions; using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; @@ -72,6 +73,8 @@ internal sealed class TranslationContext private static readonly MemberNames DefaultMemberNames = new MemberNames(new CosmosLinqSerializerOptions()); + private ScalarOperationKind? clientOperation; + public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOptionsInternal, IDictionary parameters = null) { this.InScope = new HashSet(); @@ -82,6 +85,7 @@ public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOpti this.CurrentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); this.subqueryBindingStack = new Stack(); this.Parameters = parameters; + this.clientOperation = null; if (linqSerializerOptionsInternal?.CustomCosmosLinqSerializer != null) { @@ -102,6 +106,18 @@ public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOpti } } + public ScalarOperationKind ClientOperation => this.clientOperation ?? ScalarOperationKind.None; + + public void SetClientOperation(ScalarOperationKind clientOperation) + { + // CosmosLinqQuery which is the only indirect sole consumer of this class can only see at most one scalar operation at the top level, since the return type of scalar operation is no longer IQueryable. + // Furthermore, any nested scalar operations (on nested properties of type IEnumerable) are not handled in the same way as the top level operations. + // As a result clientOperation can only be set at most once. + Debug.Assert(this.clientOperation == null, "TranslationContext Assert!", "ClientOperation can be set at most once!"); + + this.clientOperation = clientOperation; + } + public Expression LookupSubstitution(ParameterExpression parameter) { return this.substitutions.Lookup(parameter); diff --git a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs index 053c951f6c..5bd47c8a21 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v2Query/DocumentQueryExecutionContextBase.cs @@ -134,7 +134,14 @@ protected SqlQuerySpec QuerySpec { if (!this.isExpressionEvaluated) { - this.querySpec = DocumentQueryEvaluator.Evaluate(this.expression); + LinqQueryOperation linqQuery = DocumentQueryEvaluator.Evaluate(this.expression); + + if (linqQuery.ScalarOperationKind != ScalarOperationKind.None) + { + throw new NotSupportedException($"This operation does not support the supplied LINQ expression since it involves client side operation : {linqQuery.ScalarOperationKind}"); + } + + this.querySpec = linqQuery.SqlQuerySpec; this.isExpressionEvaluated = true; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqScalarFunctionBaselineTests.TestFirstOrDefault.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqScalarFunctionBaselineTests.TestFirstOrDefault.xml new file mode 100644 index 0000000000..58f80c538b --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqScalarFunctionBaselineTests.TestFirstOrDefault.xml @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + FirstOrDefault 1]]> + data.Flag).FirstOrDefault(), Object)]]> + + + + + + + + + FirstOrDefault 2]]> + data.Multiples).FirstOrDefault()]]> + + + + + + + + + FirstOrDefault 1]]> + (data.Id == "1")).FirstOrDefault()]]> + + + + + + + + + FirstOrDefault 2]]> + data.Flag).FirstOrDefault()]]> + + + + + + + + + Where -> FirstOrDefault]]> + data.Flag).Where(flag => flag).FirstOrDefault(), Object)]]> + + + + + + + + + Select -> FirstOrDefault]]> + data.Id).Select(data => data.Flag).FirstOrDefault(), Object)]]> + + + + + + + + + FirstOrDefault]]> + data.Multiples).FirstOrDefault(), Object)]]> + + + + + + + + + FirstOrDefault]]> + + + + + + + + + + Skip -> Take -> FirstOrDefault]]> + data).Skip(5).Take(5).FirstOrDefault()]]> + + + + + + + + + FirstOrDefault]]> + + + + + + + + + + + (data.Flag AndAlso Not(data.Flag))).FirstOrDefault()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True)]]> + + + + + + + + + + + True, new Data())]]> + + + + + + + + + + + True, value(Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqScalarFunctionBaselineTests).GetDefaultData())]]> + + + + + + + + + + + data.Multiples.FirstOrDefault()).Min(), Object)]]> + + + + + + + + + + + new List`1() {Void Add(Int32)(1), Void Add(Int32)(2), Void Add(Int32)(3)}.FirstOrDefault()).Min(), Object)]]> + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/ILinqTestDataGenerator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/ILinqTestDataGenerator.cs new file mode 100644 index 0000000000..5d39585531 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/ILinqTestDataGenerator.cs @@ -0,0 +1,14 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests +{ + using System.Collections.Generic; + + internal interface ILinqTestDataGenerator + { + IEnumerable GenerateData(); + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs new file mode 100644 index 0000000000..6e16380f90 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqCleanupTests.cs @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Text.RegularExpressions; + using System.Threading.Tasks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using TestCommon = Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestCommon; + + /// + /// Contains test that cleans up databases left over during debugging of LINQ tests. + /// This test does not run by default, but automates the process of deleting the databases left over during debugging session. + /// + [TestClass] + public class LinqCleanupTests + { + [Ignore] + [TestMethod] + public async Task CleanupLinqTestDatabases() + { + CosmosClient client = TestCommon.CreateCosmosClient(true); + Uri uri = client.ClientContext.Client.Endpoint; + if (uri.ToString().StartsWith(@"https://localhost:") || + uri.ToString().StartsWith(@"https://127.0.0.1:")) + { + Debug.WriteLine($"Executing against local endpoint '{uri}', continuing."); + FeedIterator feedIterator = client + .GetDatabaseQueryIterator( + queryDefinition: null, + continuationToken: null, + requestOptions: new QueryRequestOptions() { MaxItemCount = 2 }); + + Regex linqTestDatabaseRegex = new Regex("^Linq.*Baseline(Tests)?-[0-9A-Fa-f]{32}$"); + List databasesToDelete = new List(); + while (feedIterator.HasMoreResults) + { + FeedResponse databasePropertiesResponse = await feedIterator.ReadNextAsync(); + foreach (DatabaseProperties database in databasePropertiesResponse) + { + if (linqTestDatabaseRegex.IsMatch(database.Id)) + { + Debug.WriteLine($"Recognized database for deletion : '{database.Id}'"); + databasesToDelete.Add(database.Id); + } + else + { + Debug.WriteLine($"Database not recognized for deletion : '{database.Id}'"); + } + } + } + + foreach (string databaseToDelete in databasesToDelete) + { + Debug.WriteLine($"Deleting database '{databaseToDelete}'"); + Database database = client.GetDatabase(databaseToDelete); + DatabaseResponse response = await database.DeleteAsync(); + } + } + else + { + Debug.WriteLine($"Executing against non-local endpoint '{uri}', aborting."); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqScalarFunctionBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqScalarFunctionBaselineTests.cs new file mode 100644 index 0000000000..74e52ab3b6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqScalarFunctionBaselineTests.cs @@ -0,0 +1,332 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Expressions; + using System.Threading.Tasks; + using System.Xml; + using TestCommon = Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestCommon; + using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using Microsoft.Azure.Cosmos.Linq; + + /// + /// LINQ tests for Non aggregate scalar functions such as FirstOrDefault + /// + [TestClass] + public class LinqScalarFunctionBaselineTests : BaselineTests + { + private static CosmosClient client; + private static Cosmos.Database testDb; + private static Func> getQuery; + private static Func> getQueryFamily; + private static IQueryable lastExecutedScalarQuery; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + client = TestCommon.CreateCosmosClient(true); + + // Set a callback to get the handle of the last executed query to do the verification + // This is neede because aggregate queries return type is a scalar so it can't be used + // to verify the translated LINQ directly as other queries type. + client.DocumentClient.OnExecuteScalarQueryCallback = q => lastExecutedScalarQuery = q; + + string dbName = $"{nameof(LinqAggregateFunctionBaselineTests)}-{Guid.NewGuid().ToString("N")}"; + testDb = await client.CreateDatabaseAsync(dbName); + + getQuery = LinqTestsCommon.GenerateSimpleCosmosData(testDb, useRandomData: false); + getQueryFamily = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out _); + } + + [TestMethod] + [Owner("adityasa")] + public void TestFirstOrDefault() + { + List inputs = new List(); + + /////////////////////////////////////////////////// + // Positive cases - With at least one result + /////////////////////////////////////////////////// + + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault", + b => getQuery(b) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Select -> FirstOrDefault 1", + b => getQuery(b) + .Select(data => data.Flag) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Select -> FirstOrDefault 2", + b => getQuery(b) + .Select(data => data.Multiples) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Where -> FirstOrDefault 1", + b => getQuery(b) + .Where(data => data.Id == "1") + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Where -> FirstOrDefault 2", + b => getQuery(b) + .Where(data => data.Flag) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Select -> Where -> FirstOrDefault", + b => getQuery(b) + .Select(data => data.Flag) + .Where(flag => flag) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "OrderBy -> Select -> FirstOrDefault", + b => getQuery(b) + .OrderBy(data => data.Id) + .Select(data => data.Flag) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "SelectMany -> FirstOrDefault", + b => getQuery(b) + .SelectMany(data => data.Multiples) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Take -> FirstOrDefault", + b => getQuery(b) + .Take(10) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Select -> Skip -> Take -> FirstOrDefault", + b => getQuery(b) + .Select(data => data) + .Skip(5) + .Take(5) + .FirstOrDefault())); + + inputs.Add(new LinqScalarFunctionInput( + "Skip -> FirstOrDefault", + b => getQuery(b) + .Skip(3) + .FirstOrDefault())); + + /////////////////////////////////////////////////// + // Positive cases - With no results + /////////////////////////////////////////////////// + + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault (default)", + b => getQuery(b) + .Where(data => data.Flag && !data.Flag) + .FirstOrDefault())); + + ///////////////// + // Negative cases + ///////////////// + + // ISSUE-TODO-adityasa-2024/1/26 - Support FirstOrDefault overloads. + // Please note, this requires potential support for user code invocation in context of rest of the client code (except maybe some simple cases). + // We do not currently do this for any other scenarios. + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault with explicit (inline) default", + b => getQuery(b) + .FirstOrDefault(new Data()))); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault with explicit default from function invocation", + b => getQuery(b) + .FirstOrDefault(this.GetDefaultData()))); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault with predicate", + b => getQuery(b) + .FirstOrDefault(_ => true))); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault with explicit (inline) default and predicate", + b => getQuery(b) + .FirstOrDefault(_ => true, new Data()))); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "FirstOrDefault with explicit default from function invocation and predicate", + b => getQuery(b) + .FirstOrDefault(_ => true, this.GetDefaultData()))); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "Nested FirstOrDefault 1", + b => getQuery(b) + .Select(data => data.Multiples.FirstOrDefault()) + .Min())); + + // Unsupported + inputs.Add(new LinqScalarFunctionInput( + "Nested FirstOrDefault 2", + b => getQuery(b) + .Select(data => new List { 1, 2, 3 }.FirstOrDefault()) + .Min())); + + this.ExecuteTestSuite(inputs); + } + + private Data GetDefaultData() + { + return new Data(); + } + + public override LinqScalarFunctionOutput ExecuteTest(LinqScalarFunctionInput input) + { + lastExecutedScalarQuery = null; + Func compiledQuery = input.Expression.Compile(); + + string errorMessage = null; + string query = string.Empty; + object queryResult = null; + try + { + try + { + queryResult = compiledQuery(true); + } + finally + { + Assert.IsNotNull(lastExecutedScalarQuery, "lastExecutedScalarQuery is not set"); + + query = JObject + .Parse(lastExecutedScalarQuery.ToString()) + .GetValue("query", StringComparison.Ordinal) + .ToString(); + } + + try + { + object dataResult = compiledQuery(false); + Assert.IsTrue(AreEqual(dataResult, queryResult)); + } + catch (ArgumentException) + { + // Min and Max operations cannot be done on Document type + // In this case, the queryResult should be null + Assert.AreEqual(null, queryResult); + } + } + catch (Exception e) + { + errorMessage = LinqTestsCommon.BuildExceptionMessageForTest(e); + } + + string serializedResults = JsonConvert.SerializeObject( + queryResult, + new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented }); + + return new LinqScalarFunctionOutput(query, errorMessage, serializedResults); + } + + private static bool AreEqual(object obj1, object obj2) + { + bool equals = obj1 == obj2; + if (equals) + { + return true; + } + + if (obj1 is int[] intArray1 && obj2 is int[] intArray2) + { + return intArray1.SequenceEqual(intArray2); + } + + return obj1.Equals(obj2); + } + } + + public sealed class LinqScalarFunctionOutput : BaselineTestOutput + { + public string SqlQuery { get; } + + public string ErrorMessage { get; } + + public string SerializedResults { get; } + + internal LinqScalarFunctionOutput(string sqlQuery, string errorMessage, string serializedResults) + { + this.SqlQuery = sqlQuery; + this.ErrorMessage = errorMessage; + this.SerializedResults = serializedResults; + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteStartElement(nameof(this.SqlQuery)); + xmlWriter.WriteCData(LinqTestOutput.FormatSql(this.SqlQuery)); + xmlWriter.WriteEndElement(); + if (this.ErrorMessage != null) + { + xmlWriter.WriteStartElement(nameof(this.ErrorMessage)); + xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.ErrorMessage)); + xmlWriter.WriteEndElement(); + } + + if (this.SerializedResults != null) + { + xmlWriter.WriteStartElement(nameof(this.SerializedResults)); + xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.SerializedResults)); + xmlWriter.WriteEndElement(); + } + } + } + + public sealed class LinqScalarFunctionInput : BaselineTestInput + { + internal LinqScalarFunctionInput(string description, Expression> expression) + : base(description) + { + if (expression == null) + { + throw new ArgumentNullException($"{nameof(expression)} must not be null."); + } + + this.Expression = expression; + } + + public Expression> Expression { get; } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + if (xmlWriter == null) + { + throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); + } + + string expressionString = LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); + + xmlWriter.WriteStartElement("Description"); + xmlWriter.WriteCData(this.Description); + xmlWriter.WriteEndElement(); + xmlWriter.WriteStartElement("Expression"); + xmlWriter.WriteCData(expressionString); + xmlWriter.WriteEndElement(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs index a543a00418..4044b623fc 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs @@ -5,9 +5,10 @@ //----------------------------------------------------------------------- namespace Microsoft.Azure.Cosmos.Services.Management.Tests { - using Newtonsoft.Json; using System; using System.Collections.Generic; + using System.Linq; + using Newtonsoft.Json; #region Family classes @@ -95,6 +96,48 @@ public class Data public bool Flag { get; set; } public int[] Multiples { get; set; } + + public override bool Equals(object obj) + { + Data other = obj as Data; + + if(other == null) + { + return false; + } + + bool equals = this.Id == other.Id && + this.Number == other.Number && + this.Pk == other.Pk && + this.Flag == other.Flag && + (this.Multiples?.Length == other.Multiples?.Length); + + if (equals && + this.Multiples != null) + { + equals &= this.Multiples.SequenceEqual(other.Multiples); + } + + return equals; + } + + public override int GetHashCode() + { + int hashCode = this.Id.GetHashCode() ^ + this.Number.GetHashCode() ^ + this.Pk.GetHashCode() ^ + this.Flag.GetHashCode(); + + if (this.Multiples != null) + { + foreach (int value in this.Multiples) + { + hashCode ^= value.GetHashCode(); + } + } + + return hashCode; + } } #endregion diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestDataGenerator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestDataGenerator.cs new file mode 100644 index 0000000000..ef1ba2430c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestDataGenerator.cs @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests +{ + using System.Collections.Generic; + + internal class LinqTestDataGenerator : ILinqTestDataGenerator + { + private readonly int count; + + public LinqTestDataGenerator(int count) + { + this.count = count; + } + + public IEnumerable GenerateData() + { + for (int index = 0; index < this.count; index++) + { + yield return new Data() + { + Id = index.ToString(), + Number = index * 1000, + Flag = index % 2 == 0, + Multiples = new int[] { index, index * 2, index * 3, index * 4 }, + Pk = "Test" + }; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestRandomDataGenerator.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestRandomDataGenerator.cs new file mode 100644 index 0000000000..7e45310746 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestRandomDataGenerator.cs @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + + internal class LinqTestRandomDataGenerator : ILinqTestDataGenerator + { + private readonly int count; + private readonly Random random; + + public LinqTestRandomDataGenerator(int count) + { + this.count = count; + int seed = DateTime.Now.Millisecond; + this.random = new Random(seed); + + Debug.WriteLine("Random seed: {0}", seed); + } + + public IEnumerable GenerateData() + { + for (int index = 0; index < this.count; index++) + { + yield return new Data() + { + Id = Guid.NewGuid().ToString(), + Number = this.random.Next(-10000, 10000), + Flag = index % 2 == 0, + Multiples = new int[] { index, index * 2, index * 3, index * 4 }, + Pk = "Test" + }; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 815de90537..7d703061a4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -1,586 +1,574 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - using System.Runtime.CompilerServices; - using System.Text; - using System.Text.Json.Serialization; - using System.Text.Json; - using System.Text.RegularExpressions; - using System.Xml; - using global::Azure.Core.Serialization; - using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; - using Microsoft.Azure.Documents; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using System.Runtime.CompilerServices; + using System.Text; + using System.Text.Json.Serialization; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Xml; + using global::Azure.Core.Serialization; + using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; using Newtonsoft.Json.Linq; - internal class LinqTestsCommon - { - /// - /// Compare two list of anonymous objects - /// - /// - /// - /// - private static bool CompareListOfAnonymousType(List queryResults, List dataResults) - { - return queryResults.SequenceEqual(dataResults); - } - - /// - /// Compare 2 IEnumerable which may contain IEnumerable themselves. - /// - /// The query results from Cosmos DB - /// The query results from actual data - /// True if the two IEbumerable equal - private static bool NestedListsSequenceEqual(IEnumerable queryResults, IEnumerable dataResults) - { - IEnumerator queryIter, dataIter; - for (queryIter = queryResults.GetEnumerator(), dataIter = dataResults.GetEnumerator(); - queryIter.MoveNext() && dataIter.MoveNext();) - { - IEnumerable queryEnumerable = queryIter.Current as IEnumerable; - IEnumerable dataEnumerable = dataIter.Current as IEnumerable; - if (queryEnumerable == null && dataEnumerable == null) - { - if (!queryIter.Current.Equals(dataIter.Current)) return false; - - } - - else if (queryEnumerable == null || dataEnumerable == null) - { - return false; - } - - else - { - if (!LinqTestsCommon.NestedListsSequenceEqual(queryEnumerable, dataEnumerable)) return false; - } - } - - return !(queryIter.MoveNext() || dataIter.MoveNext()); - } - - /// - /// Compare the list of results from CosmosDB query and the list of results from LinQ query on the original data - /// Similar to Collections.SequenceEqual with the assumption that these lists are non-empty - /// - /// A list representing the query restuls from CosmosDB - /// A list representing the linQ query results from the original data - /// true if the two - private static bool CompareListOfArrays(List queryResults, List dataResults) - { - if (NestedListsSequenceEqual(queryResults, dataResults)) return true; - - bool resultMatched = true; - - // dataResults contains type ConcatIterator whereas queryResults may contain IEnumerable - // therefore it's simpler to just cast them into List> manually for simplify the verification - List> l1 = new List>(); - foreach (IEnumerable list in dataResults) - { - List l = new List(); - IEnumerator iterator = list.GetEnumerator(); - while (iterator.MoveNext()) - { - l.Add(iterator.Current); - } - - l1.Add(l); - } - - List> l2 = new List>(); - foreach (IEnumerable list in queryResults) - { - List l = new List(); - IEnumerator iterator = list.GetEnumerator(); - while (iterator.MoveNext()) - { - l.Add(iterator.Current); - } - - l2.Add(l); - } - - foreach (IEnumerable list in l1) - { - if (!l2.Any(a => a.SequenceEqual(list))) - { - resultMatched = false; - return false; - } - } - - foreach (IEnumerable list in l2) - { - if (!l1.Any(a => a.SequenceEqual(list))) - { - resultMatched = false; - break; - } - } - - return resultMatched; - } - - private static bool IsNumber(dynamic value) - { - return value is sbyte - || value is byte - || value is short - || value is ushort - || value is int - || value is uint - || value is long - || value is ulong - || value is float - || value is double - || value is decimal; - } - - public static Boolean IsAnonymousType(Type type) - { - Boolean hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; - Boolean nameContainsAnonymousType = type.FullName.Contains("AnonymousType"); - Boolean isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; - - return isAnonymousType; - } - - /// - /// Gets the results of CosmosDB query and the results of LINQ query on the original data - /// - /// - /// - public static (List queryResults, List dataResults) GetResults(IQueryable queryResults, IQueryable dataResults) - { - // execution validation - IEnumerator queryEnumerator = queryResults.GetEnumerator(); - List queryResultsList = new List(); - while (queryEnumerator.MoveNext()) - { - queryResultsList.Add(queryEnumerator.Current); - } - - List dataResultsList = dataResults?.Cast()?.ToList(); - - return (queryResultsList, dataResultsList); - } - - /// - /// Validates the results of CosmosDB query and the results of LINQ query on the original data - /// Using Assert, will fail the unit test if the two results list are not SequenceEqual - /// - /// - /// - private static void ValidateResults(List queryResultsList, List dataResultsList) - { - bool resultMatched = true; - string actualStr = null; - string expectedStr = null; - if (dataResultsList.Count == 0 || queryResultsList.Count == 0) - { - resultMatched &= dataResultsList.Count == queryResultsList.Count; - } - else - { - dynamic firstElem = dataResultsList.FirstOrDefault(); - if (firstElem is IEnumerable) - { - resultMatched &= CompareListOfArrays(queryResultsList, dataResultsList); - } - else if (LinqTestsCommon.IsAnonymousType(firstElem.GetType())) - { - resultMatched &= CompareListOfAnonymousType(queryResultsList, dataResultsList); - } - else if (LinqTestsCommon.IsNumber(firstElem)) - { - const double Epsilon = 1E-6; - Type dataType = firstElem.GetType(); - List dataSortedList = dataResultsList.OrderBy(x => x).ToList(); - List querySortedList = queryResultsList.OrderBy(x => x).ToList(); - if (dataSortedList.Count != querySortedList.Count) - { - resultMatched = false; - } - else - { - for (int i = 0; i < dataSortedList.Count; ++i) - { - if (Math.Abs(dataSortedList[i] - (dynamic)querySortedList[i]) > (dynamic)Convert.ChangeType(Epsilon, dataType)) - { - resultMatched = false; - break; - } - } - } - - if (!resultMatched) - { - actualStr = JsonConvert.SerializeObject(querySortedList); - expectedStr = JsonConvert.SerializeObject(dataSortedList); - } - } - else - { - List dataNotQuery = dataResultsList.Except(queryResultsList).ToList(); - List queryNotData = queryResultsList.Except(dataResultsList).ToList(); - resultMatched &= !dataNotQuery.Any() && !queryNotData.Any(); - } - } - - string assertMsg = string.Empty; - if (!resultMatched) - { - actualStr ??= JsonConvert.SerializeObject(queryResultsList); - expectedStr ??= JsonConvert.SerializeObject(dataResultsList); - - resultMatched |= actualStr.Equals(expectedStr); - if (!resultMatched) - { - assertMsg = $"Expected: {expectedStr}, Actual: {actualStr}, RandomSeed: {LinqTestInput.RandomSeed}"; - } - } - - Assert.IsTrue(resultMatched, assertMsg); - } - - /// - /// Generate a random string containing alphabetical characters - /// - /// - /// - /// a random string - public static string RandomString(Random random, int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz "; - return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); - } - - /// - /// Generate a random DateTime object from a DateTime, - /// with the variance of the time span between the provided DateTime to the current time - /// - /// - /// - /// - public static DateTime RandomDateTime(Random random, DateTime midDateTime) - { - TimeSpan timeSpan = DateTime.Now - midDateTime; - TimeSpan newSpan = new TimeSpan(0, random.Next(0, (int)timeSpan.TotalMinutes * 2) - (int)timeSpan.TotalMinutes, 0); - DateTime newDate = midDateTime + newSpan; - return newDate; - } - - /// - /// Generate test data for most LINQ tests - /// - /// the object type - /// the lamda to create an instance of test data - /// number of test data to be created - /// the target container - /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable - public static Func> GenerateTestCosmosData(Func func, int count, Container container) - { - List data = new List(); - int seed = DateTime.Now.Millisecond; - Random random = new Random(seed); - Debug.WriteLine("Random seed: {0}", seed); - LinqTestInput.RandomSeed = seed; - for (int i = 0; i < count; ++i) - { - data.Add(func(random)); - } - - foreach (T obj in data) - { - ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); - - // To cover both query against backend and queries on the original data using LINQ nicely, - // the LINQ expression should be written once and they should be compiled and executed against the two sources. - // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query - // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values - // to this getQuery method. - IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); - - return getQuery; - } - - /// - /// Generate a non-random payload for serializer LINQ tests. - /// - /// the object type - /// the lamda to create an instance of test data - /// number of test data to be created - /// the target container - /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied - /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. - public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, CosmosLinqSerializerOptions linqSerializerOptions) - { - List data = new List(); - for (int i = 0; i < count; i++) - { - data.Add(func(i, linqSerializerOptions.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase)); - } - - foreach (T obj in data) - { - ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); - - IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); - - return getQuery; - } - - public static Func> GenerateFamilyCosmosData( - Cosmos.Database cosmosDatabase, out Container container) - { - // The test collection should have range index on string properties - // for the orderby tests - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; - ContainerProperties newCol = new ContainerProperties() - { - Id = Guid.NewGuid().ToString(), - PartitionKey = partitionKeyDefinition, - IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy() - { - IncludedPaths = new Collection() - { - new Cosmos.IncludedPath() - { - Path = "/*", - Indexes = new System.Collections.ObjectModel.Collection() - { - Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1), - Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1) - } - } - }, - CompositeIndexes = new Collection>() - { - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } - } - } - } - }; - container = cosmosDatabase.CreateContainerAsync(newCol).Result; - const int Records = 100; - const int MaxNameLength = 100; - const int MaxThingStringLength = 50; - const int MaxChild = 5; - const int MaxPets = MaxChild; - const int MaxThings = MaxChild; - const int MaxGrade = 101; - const int MaxTransaction = 20; - const int MaxTransactionMinuteRange = 200; - int MaxTransactionType = Enum.GetValues(typeof(TransactionType)).Length; - Family createDataObj(Random random) - { - Family obj = new Family - { - FamilyId = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(), - IsRegistered = random.NextDouble() < 0.5, - NullableInt = random.NextDouble() < 0.5 ? (int?)random.Next() : null, - Int = random.NextDouble() < 0.5 ? 5 : random.Next(), - Id = Guid.NewGuid().ToString(), - Pk = "Test", - Parents = new Parent[random.Next(2) + 1] - }; - for (int i = 0; i < obj.Parents.Length; ++i) - { - obj.Parents[i] = new Parent() - { - FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) - }; - } - - obj.Tags = new string[random.Next(MaxChild)]; - for (int i = 0; i < obj.Tags.Length; ++i) - { - obj.Tags[i] = (i + random.Next(30, 36)).ToString(); - } - - obj.Children = new Child[random.Next(MaxChild)]; - for (int i = 0; i < obj.Children.Length; ++i) - { - obj.Children[i] = new Child() - { - Gender = random.NextDouble() < 0.5 ? "male" : "female", - FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName, - GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - Grade = random.Next(MaxGrade) - }; - - obj.Children[i].Pets = new List(); - for (int j = 0; j < random.Next(MaxPets); ++j) - { - obj.Children[i].Pets.Add(new Pet() - { - GivenName = random.NextDouble() < 0.5 ? - LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) : - "Fluffy" - }); - } - - obj.Children[i].Things = new Dictionary(); - for (int j = 0; j < random.Next(MaxThings) + 1; ++j) - { - obj.Children[i].Things.Add( - j == 0 ? "A" : $"{j}-{random.Next()}", - LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength))); - } - } - - obj.Records = new Logs - { - LogId = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - Transactions = new Transaction[random.Next(MaxTransaction)] - }; - for (int i = 0; i < obj.Records.Transactions.Length; ++i) - { - Transaction transaction = new Transaction() - { - Amount = random.Next(), - Date = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)), - Type = (TransactionType)random.Next(MaxTransactionType) - }; - obj.Records.Transactions[i] = transaction; - } - - return obj; - } - - Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container); - return getQuery; - } - - public static Func> GenerateSimpleCosmosData(Cosmos.Database cosmosDatabase) - { - const int DocumentCount = 10; - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; - Container container = cosmosDatabase.CreateContainerAsync(new ContainerProperties { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; - - int seed = DateTime.Now.Millisecond; - Random random = new Random(seed); - Debug.WriteLine("Random seed: {0}", seed); - List testData = new List(); - for (int index = 0; index < DocumentCount; index++) - { - Data dataEntry = new Data() - { - Id = Guid.NewGuid().ToString(), - Number = random.Next(-10000, 10000), - Flag = index % 2 == 0, - Multiples = new int[] { index, index * 2, index * 3, index * 4 }, - Pk = "Test" - }; - - Data response = container.CreateItemAsync(dataEntry, new Cosmos.PartitionKey(dataEntry.Pk)).Result; - testData.Add(dataEntry); - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); - - // To cover both query against backend and queries on the original data using LINQ nicely, - // the LINQ expression should be written once and they should be compiled and executed against the two sources. - // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query - // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values - // to this getQuery method. - IQueryable getQuery(bool useQuery) => useQuery ? query : testData.AsQueryable(); - return getQuery; - } - - public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResultsInBaseline = false) - { - string querySqlStr = string.Empty; - try - { - Func compiledQuery = input.Expression.Compile(); - - IQueryable query = compiledQuery(true); - querySqlStr = JObject.Parse(query.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); - - IQueryable dataQuery = input.skipVerification ? null : compiledQuery(false); - - (List queryResults, List dataResults) = GetResults(query, dataQuery); - - // we skip unordered query because the LINQ results vs actual query results are non-deterministic - if (!input.skipVerification) - { - LinqTestsCommon.ValidateResults(queryResults, dataResults); - } - - string serializedResults = serializeResultsInBaseline ? - JsonConvert.SerializeObject(queryResults.Select(item => item is LinqTestObject ? item.ToString() : item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented}) : - null; - - return new LinqTestOutput(querySqlStr, serializedResults, errorMsg: null, input.inputData); - } - catch (Exception e) - { - return new LinqTestOutput(querySqlStr, serializedResults: null, errorMsg: LinqTestsCommon.BuildExceptionMessageForTest(e), inputData: input.inputData); - } - } - - public static string BuildExceptionMessageForTest(Exception ex) + internal class LinqTestsCommon + { + /// + /// Compare two list of anonymous objects + /// + /// + /// + /// + private static bool CompareListOfAnonymousType(List queryResults, List dataResults) + { + return queryResults.SequenceEqual(dataResults); + } + + /// + /// Compare 2 IEnumerable which may contain IEnumerable themselves. + /// + /// The query results from Cosmos DB + /// The query results from actual data + /// True if the two IEbumerable equal + private static bool NestedListsSequenceEqual(IEnumerable queryResults, IEnumerable dataResults) + { + IEnumerator queryIter, dataIter; + for (queryIter = queryResults.GetEnumerator(), dataIter = dataResults.GetEnumerator(); + queryIter.MoveNext() && dataIter.MoveNext();) + { + IEnumerable queryEnumerable = queryIter.Current as IEnumerable; + IEnumerable dataEnumerable = dataIter.Current as IEnumerable; + if (queryEnumerable == null && dataEnumerable == null) + { + if (!queryIter.Current.Equals(dataIter.Current)) return false; + + } + + else if (queryEnumerable == null || dataEnumerable == null) + { + return false; + } + + else + { + if (!LinqTestsCommon.NestedListsSequenceEqual(queryEnumerable, dataEnumerable)) return false; + } + } + + return !(queryIter.MoveNext() || dataIter.MoveNext()); + } + + /// + /// Compare the list of results from CosmosDB query and the list of results from LinQ query on the original data + /// Similar to Collections.SequenceEqual with the assumption that these lists are non-empty + /// + /// A list representing the query restuls from CosmosDB + /// A list representing the linQ query results from the original data + /// true if the two + private static bool CompareListOfArrays(List queryResults, List dataResults) + { + if (NestedListsSequenceEqual(queryResults, dataResults)) return true; + + bool resultMatched = true; + + // dataResults contains type ConcatIterator whereas queryResults may contain IEnumerable + // therefore it's simpler to just cast them into List> manually for simplify the verification + List> l1 = new List>(); + foreach (IEnumerable list in dataResults) + { + List l = new List(); + IEnumerator iterator = list.GetEnumerator(); + while (iterator.MoveNext()) + { + l.Add(iterator.Current); + } + + l1.Add(l); + } + + List> l2 = new List>(); + foreach (IEnumerable list in queryResults) + { + List l = new List(); + IEnumerator iterator = list.GetEnumerator(); + while (iterator.MoveNext()) + { + l.Add(iterator.Current); + } + + l2.Add(l); + } + + foreach (IEnumerable list in l1) + { + if (!l2.Any(a => a.SequenceEqual(list))) + { + resultMatched = false; + return false; + } + } + + foreach (IEnumerable list in l2) + { + if (!l1.Any(a => a.SequenceEqual(list))) + { + resultMatched = false; + break; + } + } + + return resultMatched; + } + + private static bool IsNumber(dynamic value) + { + return value is sbyte + || value is byte + || value is short + || value is ushort + || value is int + || value is uint + || value is long + || value is ulong + || value is float + || value is double + || value is decimal; + } + + public static Boolean IsAnonymousType(Type type) + { + Boolean hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; + Boolean nameContainsAnonymousType = type.FullName.Contains("AnonymousType"); + Boolean isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; + + return isAnonymousType; + } + + /// + /// Gets the results of CosmosDB query and the results of LINQ query on the original data + /// + /// + /// + public static (List queryResults, List dataResults) GetResults(IQueryable queryResults, IQueryable dataResults) + { + // execution validation + IEnumerator queryEnumerator = queryResults.GetEnumerator(); + List queryResultsList = new List(); + while (queryEnumerator.MoveNext()) + { + queryResultsList.Add(queryEnumerator.Current); + } + + List dataResultsList = dataResults?.Cast()?.ToList(); + + return (queryResultsList, dataResultsList); + } + + /// + /// Validates the results of CosmosDB query and the results of LINQ query on the original data + /// Using Assert, will fail the unit test if the two results list are not SequenceEqual + /// + /// + /// + private static void ValidateResults(List queryResultsList, List dataResultsList) + { + bool resultMatched = true; + string actualStr = null; + string expectedStr = null; + if (dataResultsList.Count == 0 || queryResultsList.Count == 0) + { + resultMatched &= dataResultsList.Count == queryResultsList.Count; + } + else + { + dynamic firstElem = dataResultsList.FirstOrDefault(); + if (firstElem is IEnumerable) + { + resultMatched &= CompareListOfArrays(queryResultsList, dataResultsList); + } + else if (LinqTestsCommon.IsAnonymousType(firstElem.GetType())) + { + resultMatched &= CompareListOfAnonymousType(queryResultsList, dataResultsList); + } + else if (LinqTestsCommon.IsNumber(firstElem)) + { + const double Epsilon = 1E-6; + Type dataType = firstElem.GetType(); + List dataSortedList = dataResultsList.OrderBy(x => x).ToList(); + List querySortedList = queryResultsList.OrderBy(x => x).ToList(); + if (dataSortedList.Count != querySortedList.Count) + { + resultMatched = false; + } + else + { + for (int i = 0; i < dataSortedList.Count; ++i) + { + if (Math.Abs(dataSortedList[i] - (dynamic)querySortedList[i]) > (dynamic)Convert.ChangeType(Epsilon, dataType)) + { + resultMatched = false; + break; + } + } + } + + if (!resultMatched) + { + actualStr = JsonConvert.SerializeObject(querySortedList); + expectedStr = JsonConvert.SerializeObject(dataSortedList); + } + } + else + { + List dataNotQuery = dataResultsList.Except(queryResultsList).ToList(); + List queryNotData = queryResultsList.Except(dataResultsList).ToList(); + resultMatched &= !dataNotQuery.Any() && !queryNotData.Any(); + } + } + + string assertMsg = string.Empty; + if (!resultMatched) + { + actualStr ??= JsonConvert.SerializeObject(queryResultsList); + expectedStr ??= JsonConvert.SerializeObject(dataResultsList); + + resultMatched |= actualStr.Equals(expectedStr); + if (!resultMatched) + { + assertMsg = $"Expected: {expectedStr}, Actual: {actualStr}, RandomSeed: {LinqTestInput.RandomSeed}"; + } + } + + Assert.IsTrue(resultMatched, assertMsg); + } + + /// + /// Generate a random string containing alphabetical characters + /// + /// + /// + /// a random string + public static string RandomString(Random random, int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz "; + return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); + } + + /// + /// Generate a random DateTime object from a DateTime, + /// with the variance of the time span between the provided DateTime to the current time + /// + /// + /// + /// + public static DateTime RandomDateTime(Random random, DateTime midDateTime) + { + TimeSpan timeSpan = DateTime.Now - midDateTime; + TimeSpan newSpan = new TimeSpan(0, random.Next(0, (int)timeSpan.TotalMinutes * 2) - (int)timeSpan.TotalMinutes, 0); + DateTime newDate = midDateTime + newSpan; + return newDate; + } + + /// + /// Generate test data for most LINQ tests + /// + /// the object type + /// the lamda to create an instance of test data + /// number of test data to be created + /// the target container + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable + public static Func> GenerateTestCosmosData(Func func, int count, Container container) + { + List data = new List(); + int seed = DateTime.Now.Millisecond; + Random random = new Random(seed); + Debug.WriteLine("Random seed: {0}", seed); + LinqTestInput.RandomSeed = seed; + for (int i = 0; i < count; ++i) + { + data.Add(func(random)); + } + + foreach (T obj in data) + { + ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); + + // To cover both query against backend and queries on the original data using LINQ nicely, + // the LINQ expression should be written once and they should be compiled and executed against the two sources. + // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query + // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values + // to this getQuery method. + IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); + + return getQuery; + } + + /// + /// Generate a non-random payload for serializer LINQ tests. + /// + /// the object type + /// the lamda to create an instance of test data + /// number of test data to be created + /// the target container + /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. + public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, CosmosLinqSerializerOptions linqSerializerOptions) + { + List data = new List(); + for (int i = 0; i < count; i++) + { + data.Add(func(i, linqSerializerOptions.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase)); + } + + foreach (T obj in data) + { + ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); + + IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); + + return getQuery; + } + + public static Func> GenerateFamilyCosmosData( + Cosmos.Database cosmosDatabase, out Container container) + { + // The test collection should have range index on string properties + // for the orderby tests + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; + ContainerProperties newCol = new ContainerProperties() + { + Id = Guid.NewGuid().ToString(), + PartitionKey = partitionKeyDefinition, + IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy() + { + IncludedPaths = new Collection() + { + new Cosmos.IncludedPath() + { + Path = "/*", + Indexes = new System.Collections.ObjectModel.Collection() + { + Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1), + Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1) + } + } + }, + CompositeIndexes = new Collection>() + { + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } + } + } + } + }; + container = cosmosDatabase.CreateContainerAsync(newCol).Result; + const int Records = 100; + const int MaxNameLength = 100; + const int MaxThingStringLength = 50; + const int MaxChild = 5; + const int MaxPets = MaxChild; + const int MaxThings = MaxChild; + const int MaxGrade = 101; + const int MaxTransaction = 20; + const int MaxTransactionMinuteRange = 200; + int MaxTransactionType = Enum.GetValues(typeof(TransactionType)).Length; + Family createDataObj(Random random) + { + Family obj = new Family + { + FamilyId = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(), + IsRegistered = random.NextDouble() < 0.5, + NullableInt = random.NextDouble() < 0.5 ? (int?)random.Next() : null, + Int = random.NextDouble() < 0.5 ? 5 : random.Next(), + Id = Guid.NewGuid().ToString(), + Pk = "Test", + Parents = new Parent[random.Next(2) + 1] + }; + for (int i = 0; i < obj.Parents.Length; ++i) + { + obj.Parents[i] = new Parent() + { + FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) + }; + } + + obj.Tags = new string[random.Next(MaxChild)]; + for (int i = 0; i < obj.Tags.Length; ++i) + { + obj.Tags[i] = (i + random.Next(30, 36)).ToString(); + } + + obj.Children = new Child[random.Next(MaxChild)]; + for (int i = 0; i < obj.Children.Length; ++i) + { + obj.Children[i] = new Child() + { + Gender = random.NextDouble() < 0.5 ? "male" : "female", + FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName, + GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + Grade = random.Next(MaxGrade) + }; + + obj.Children[i].Pets = new List(); + for (int j = 0; j < random.Next(MaxPets); ++j) + { + obj.Children[i].Pets.Add(new Pet() + { + GivenName = random.NextDouble() < 0.5 ? + LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) : + "Fluffy" + }); + } + + obj.Children[i].Things = new Dictionary(); + for (int j = 0; j < random.Next(MaxThings) + 1; ++j) + { + obj.Children[i].Things.Add( + j == 0 ? "A" : $"{j}-{random.Next()}", + LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength))); + } + } + + obj.Records = new Logs + { + LogId = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + Transactions = new Transaction[random.Next(MaxTransaction)] + }; + for (int i = 0; i < obj.Records.Transactions.Length; ++i) + { + Transaction transaction = new Transaction() + { + Amount = random.Next(), + Date = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)), + Type = (TransactionType)random.Next(MaxTransactionType) + }; + obj.Records.Transactions[i] = transaction; + } + + return obj; + } + + Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container); + return getQuery; + } + + public static Func> GenerateSimpleCosmosData(Cosmos.Database cosmosDatabase, bool useRandomData = true) + { + const int DocumentCount = 10; + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; + Container container = cosmosDatabase.CreateContainerAsync(new ContainerProperties { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + + ILinqTestDataGenerator dataGenerator = useRandomData ? new LinqTestRandomDataGenerator(DocumentCount) : new LinqTestDataGenerator(DocumentCount); + List testData = new List(dataGenerator.GenerateData()); + foreach (Data dataEntry in testData) + { + Data response = container.CreateItemAsync(dataEntry, new Cosmos.PartitionKey(dataEntry.Pk)).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); + + // To cover both query against backend and queries on the original data using LINQ nicely, + // the LINQ expression should be written once and they should be compiled and executed against the two sources. + // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query + // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values + // to this getQuery method. + IQueryable getQuery(bool useQuery) => useQuery ? query : testData.AsQueryable(); + return getQuery; + } + + public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResultsInBaseline = false) + { + string querySqlStr = string.Empty; + try + { + Func compiledQuery = input.Expression.Compile(); + + IQueryable query = compiledQuery(true); + querySqlStr = JObject.Parse(query.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); + + IQueryable dataQuery = input.skipVerification ? null : compiledQuery(false); + + (List queryResults, List dataResults) = GetResults(query, dataQuery); + + // we skip unordered query because the LINQ results vs actual query results are non-deterministic + if (!input.skipVerification) + { + LinqTestsCommon.ValidateResults(queryResults, dataResults); + } + + string serializedResults = serializeResultsInBaseline ? + JsonConvert.SerializeObject(queryResults.Select(item => item is LinqTestObject ? item.ToString() : item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented}) : + null; + + return new LinqTestOutput(querySqlStr, serializedResults, errorMsg: null, input.inputData); + } + catch (Exception e) + { + return new LinqTestOutput(querySqlStr, serializedResults: null, errorMsg: LinqTestsCommon.BuildExceptionMessageForTest(e), inputData: input.inputData); + } + } + + public static string BuildExceptionMessageForTest(Exception ex) { StringBuilder message = new StringBuilder(); - do - { - if (ex is CosmosException cosmosException) + do + { + if (ex is CosmosException cosmosException) { // ODE scenario: The backend generates an error response message with significant variations when compared to the Service Interop which gets called in the Non ODE scenario. // The objective is to standardize and normalize the backend response for consistency. @@ -602,336 +590,336 @@ public static string BuildExceptionMessageForTest(Exception ex) else { message.Append($"Status Code: {cosmosException.StatusCode}"); - } - } - else if (ex is DocumentClientException documentClientException) - { - message.Append(documentClientException.RawErrorMessage); - } - else + } + } + else if (ex is DocumentClientException documentClientException) + { + message.Append(documentClientException.RawErrorMessage); + } + else { message.Append(ex.Message); - } - - ex = ex.InnerException; - if (ex != null) - { - message.Append(","); - } - } + } + + ex = ex.InnerException; + if (ex != null) + { + message.Append(","); + } + } while (ex != null); return message.ToString(); - } - } - - /// - /// A base class that determines equality based on its json representation - /// - public class LinqTestObject - { - private string json; - - protected virtual string SerializeForTestBaseline() - { - return JsonConvert.SerializeObject(this); - } - - public override string ToString() - { - // simple cached serialization - this.json ??= this.SerializeForTestBaseline(); - return this.json; - } - - public override bool Equals(object obj) - { - if (!(obj is LinqTestObject && - obj.GetType().IsAssignableFrom(this.GetType()) && - this.GetType().IsAssignableFrom(obj.GetType()))) return false; - if (obj == null) return false; - - return this.ToString().Equals(obj.ToString()); - } - - public override int GetHashCode() - { - return this.ToString().GetHashCode(); - } - } - - public class LinqTestInput : BaselineTestInput - { - internal static Regex classNameRegex = new Regex("(value\\(.+?\\+)?\\<\\>.+?__([A-Za-z]+)((\\d+_\\d+(`\\d+\\[.+?\\])?\\)(\\.value)?)|\\d+`\\d+)"); - internal static Regex invokeCompileRegex = new Regex("(Convert\\()?Invoke\\([^.]+\\.[^.,]+(\\.Compile\\(\\))?, b\\)(\\.Cast\\(\\))?(\\))?"); - - // As the tests are executed sequentially - // We can store the random seed in a static variable for diagnostics - internal static int RandomSeed = -1; - - internal int randomSeed = -1; - internal Expression> Expression { get; } - internal string expressionStr; - internal string inputData; - - // We skip the verification between Cosmos DB and actual query restuls in the following cases - // - unordered query since the results are not deterministics for LinQ results and actual query results - // - scenarios not supported in LINQ, e.g. sequence doesn't contain element. - internal bool skipVerification; - - internal LinqTestInput( - string description, - Expression> expr, - bool skipVerification = false, - string expressionStr = null, - string inputData = null) - : base(description) - { - this.Expression = expr ?? throw new ArgumentNullException($"{nameof(expr)} must not be null."); - this.skipVerification = skipVerification; - this.expressionStr = expressionStr; - this.inputData = inputData; - } - - public static string FilterInputExpression(string input) - { - StringBuilder expressionSb = new StringBuilder(input); - // simplify full qualified class name - // e.g. before: value(Microsoft.Azure.Documents.Services.Management.Tests.LinqSQLTranslationTest+<>c__DisplayClass7_0), after: DisplayClass - // before: <>f__AnonymousType14`2(, after: AnonymousType( - // value(Microsoft.Azure.Documents.Services.Management.Tests.LinqProviderTests.LinqTranslationBaselineTests +<> c__DisplayClass24_0`1[System.String]).value - Match match = classNameRegex.Match(expressionSb.ToString()); - while (match.Success) - { - expressionSb = expressionSb.Replace(match.Groups[0].Value, match.Groups[2].Value); - match = match.NextMatch(); - } - - // remove the Invoke().Compile() string from the Linq scanning tests - match = invokeCompileRegex.Match(expressionSb.ToString()); - while (match.Success) - { - expressionSb = expressionSb.Replace(match.Groups[0].Value, string.Empty); - match = match.NextMatch(); - } - - expressionSb.Insert(0, "query"); - - return expressionSb.ToString(); - } - - public override void SerializeAsXml(XmlWriter xmlWriter) - { - if (xmlWriter == null) - { - throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); - } - - this.expressionStr ??= LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); - - xmlWriter.WriteStartElement("Description"); - xmlWriter.WriteCData(this.Description); - xmlWriter.WriteEndElement(); - xmlWriter.WriteStartElement("Expression"); - xmlWriter.WriteCData(this.expressionStr); - xmlWriter.WriteEndElement(); - } - } - - public class LinqTestOutput : BaselineTestOutput - { - internal static Regex sdkVersion = new Regex("(,\\W*)?documentdb-dotnet-sdk[^]]+"); - internal static Regex activityId = new Regex("(,\\W*)?ActivityId:.+", RegexOptions.Multiline); - internal static Regex newLine = new Regex("(\r\n|\r|\n)"); - - internal string SqlQuery { get; } - internal string ErrorMessage { get; } - internal string Results { get; } - internal string InputData { get; } - - private static readonly Dictionary newlineKeywords = new Dictionary() { - { "SELECT", "\nSELECT" }, - { "FROM", "\nFROM" }, - { "WHERE", "\nWHERE" }, - { "JOIN", "\nJOIN" }, - { "ORDER BY", "\nORDER BY" }, - { "OFFSET", "\nOFFSET" }, - { " )", "\n)" } - }; - - public static string FormatErrorMessage(string msg) - { - msg = newLine.Replace(msg, string.Empty); - - // remove sdk version in the error message which can change in the future. - // e.g. - msg = sdkVersion.Replace(msg, string.Empty); - - // remove activity Id - msg = activityId.Replace(msg, string.Empty); - - return msg; - } - - internal LinqTestOutput(string sqlQuery, string serializedResults, string errorMsg, string inputData) - { - this.SqlQuery = FormatSql(sqlQuery); - this.Results = serializedResults; - this.ErrorMessage = errorMsg; - this.InputData = inputData; - } - - public static String FormatSql(string sqlQuery) - { - const string subqueryCue = "(SELECT"; - bool hasSubquery = sqlQuery.IndexOf(subqueryCue, StringComparison.OrdinalIgnoreCase) > 0; - - StringBuilder sb = new StringBuilder(sqlQuery); - foreach (KeyValuePair kv in newlineKeywords) - { - sb.Replace(kv.Key, kv.Value); - } - - if (!hasSubquery) return sb.ToString(); - - const string oneTab = " "; - const string startCue = "SELECT"; - const string endCue = ")"; - - string[] tokens = sb.ToString().Split('\n'); - bool firstSelect = true; - sb.Length = 0; - StringBuilder indentSb = new StringBuilder(); - for (int i = 0; i < tokens.Length; ++i) - { - if (tokens[i].StartsWith(startCue, StringComparison.OrdinalIgnoreCase)) - { - if (!firstSelect) indentSb.Append(oneTab); else firstSelect = false; - - } - else if (tokens[i].StartsWith(endCue, StringComparison.OrdinalIgnoreCase)) - { - indentSb.Length -= oneTab.Length; - } - - sb.Append(indentSb).Append(tokens[i]).Append("\n"); - } - - return sb.ToString(); - } - - public override void SerializeAsXml(XmlWriter xmlWriter) - { - xmlWriter.WriteStartElement(nameof(this.SqlQuery)); - xmlWriter.WriteCData(this.SqlQuery); - xmlWriter.WriteEndElement(); - if (this.InputData != null) - { - xmlWriter.WriteStartElement("InputData"); - xmlWriter.WriteCData(this.InputData); - xmlWriter.WriteEndElement(); - } - if (this.Results != null) - { - xmlWriter.WriteStartElement("Results"); - xmlWriter.WriteCData(this.Results); - xmlWriter.WriteEndElement(); - } - if (this.ErrorMessage != null) - { - xmlWriter.WriteStartElement("ErrorMessage"); - xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.ErrorMessage)); - xmlWriter.WriteEndElement(); - } - } - } - - class SystemTextJsonLinqSerializer : CosmosLinqSerializer - { - private readonly JsonObjectSerializer systemTextJsonSerializer; - - public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) - { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); - } - - public override T FromStream(Stream stream) - { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); - - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } - - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } - - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } - } - - public override Stream ToStream(T input) - { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); - streamPayload.Position = 0; - return streamPayload; - } - - public override string SerializeMemberName(MemberInfo memberInfo) - { - JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); - - string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) - ? jsonPropertyNameAttribute.Name - : memberInfo.Name; - - return memberName; - } + } } - class SystemTextJsonSerializer : CosmosSerializer - { - private readonly JsonObjectSerializer systemTextJsonSerializer; - - public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) - { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); - } - - public override T FromStream(Stream stream) - { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); - - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } - - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } - - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } - } - - public override Stream ToStream(T input) - { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); - streamPayload.Position = 0; - return streamPayload; - } - } -} + /// + /// A base class that determines equality based on its json representation + /// + public class LinqTestObject + { + private string json; + + protected virtual string SerializeForTestBaseline() + { + return JsonConvert.SerializeObject(this); + } + + public override string ToString() + { + // simple cached serialization + this.json ??= this.SerializeForTestBaseline(); + return this.json; + } + + public override bool Equals(object obj) + { + if (!(obj is LinqTestObject && + obj.GetType().IsAssignableFrom(this.GetType()) && + this.GetType().IsAssignableFrom(obj.GetType()))) return false; + if (obj == null) return false; + + return this.ToString().Equals(obj.ToString()); + } + + public override int GetHashCode() + { + return this.ToString().GetHashCode(); + } + } + + public class LinqTestInput : BaselineTestInput + { + internal static Regex classNameRegex = new Regex("(value\\(.+?\\+)?\\<\\>.+?__([A-Za-z]+)((\\d+_\\d+(`\\d+\\[.+?\\])?\\)(\\.value)?)|\\d+`\\d+)"); + internal static Regex invokeCompileRegex = new Regex("(Convert\\()?Invoke\\([^.]+\\.[^.,]+(\\.Compile\\(\\))?, b\\)(\\.Cast\\(\\))?(\\))?"); + + // As the tests are executed sequentially + // We can store the random seed in a static variable for diagnostics + internal static int RandomSeed = -1; + + internal int randomSeed = -1; + internal Expression> Expression { get; } + internal string expressionStr; + internal string inputData; + + // We skip the verification between Cosmos DB and actual query restuls in the following cases + // - unordered query since the results are not deterministics for LinQ results and actual query results + // - scenarios not supported in LINQ, e.g. sequence doesn't contain element. + internal bool skipVerification; + + internal LinqTestInput( + string description, + Expression> expr, + bool skipVerification = false, + string expressionStr = null, + string inputData = null) + : base(description) + { + this.Expression = expr ?? throw new ArgumentNullException($"{nameof(expr)} must not be null."); + this.skipVerification = skipVerification; + this.expressionStr = expressionStr; + this.inputData = inputData; + } + + public static string FilterInputExpression(string input) + { + StringBuilder expressionSb = new StringBuilder(input); + // simplify full qualified class name + // e.g. before: value(Microsoft.Azure.Documents.Services.Management.Tests.LinqSQLTranslationTest+<>c__DisplayClass7_0), after: DisplayClass + // before: <>f__AnonymousType14`2(, after: AnonymousType( + // value(Microsoft.Azure.Documents.Services.Management.Tests.LinqProviderTests.LinqTranslationBaselineTests +<> c__DisplayClass24_0`1[System.String]).value + Match match = classNameRegex.Match(expressionSb.ToString()); + while (match.Success) + { + expressionSb = expressionSb.Replace(match.Groups[0].Value, match.Groups[2].Value); + match = match.NextMatch(); + } + + // remove the Invoke().Compile() string from the Linq scanning tests + match = invokeCompileRegex.Match(expressionSb.ToString()); + while (match.Success) + { + expressionSb = expressionSb.Replace(match.Groups[0].Value, string.Empty); + match = match.NextMatch(); + } + + expressionSb.Insert(0, "query"); + + return expressionSb.ToString(); + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + if (xmlWriter == null) + { + throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); + } + + this.expressionStr ??= LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); + + xmlWriter.WriteStartElement("Description"); + xmlWriter.WriteCData(this.Description); + xmlWriter.WriteEndElement(); + xmlWriter.WriteStartElement("Expression"); + xmlWriter.WriteCData(this.expressionStr); + xmlWriter.WriteEndElement(); + } + } + + public class LinqTestOutput : BaselineTestOutput + { + internal static Regex sdkVersion = new Regex("(,\\W*)?documentdb-dotnet-sdk[^]]+"); + internal static Regex activityId = new Regex("(,\\W*)?ActivityId:.+", RegexOptions.Multiline); + internal static Regex newLine = new Regex("(\r\n|\r|\n)"); + + internal string SqlQuery { get; } + internal string ErrorMessage { get; } + internal string Results { get; } + internal string InputData { get; } + + private static readonly Dictionary newlineKeywords = new Dictionary() { + { "SELECT", "\nSELECT" }, + { "FROM", "\nFROM" }, + { "WHERE", "\nWHERE" }, + { "JOIN", "\nJOIN" }, + { "ORDER BY", "\nORDER BY" }, + { "OFFSET", "\nOFFSET" }, + { " )", "\n)" } + }; + + public static string FormatErrorMessage(string msg) + { + msg = newLine.Replace(msg, string.Empty); + + // remove sdk version in the error message which can change in the future. + // e.g. + msg = sdkVersion.Replace(msg, string.Empty); + + // remove activity Id + msg = activityId.Replace(msg, string.Empty); + + return msg; + } + + internal LinqTestOutput(string sqlQuery, string serializedResults, string errorMsg, string inputData) + { + this.SqlQuery = FormatSql(sqlQuery); + this.Results = serializedResults; + this.ErrorMessage = errorMsg; + this.InputData = inputData; + } + + public static String FormatSql(string sqlQuery) + { + const string subqueryCue = "(SELECT"; + bool hasSubquery = sqlQuery.IndexOf(subqueryCue, StringComparison.OrdinalIgnoreCase) > 0; + + StringBuilder sb = new StringBuilder(sqlQuery); + foreach (KeyValuePair kv in newlineKeywords) + { + sb.Replace(kv.Key, kv.Value); + } + + if (!hasSubquery) return sb.ToString(); + + const string oneTab = " "; + const string startCue = "SELECT"; + const string endCue = ")"; + + string[] tokens = sb.ToString().Split('\n'); + bool firstSelect = true; + sb.Length = 0; + StringBuilder indentSb = new StringBuilder(); + for (int i = 0; i < tokens.Length; ++i) + { + if (tokens[i].StartsWith(startCue, StringComparison.OrdinalIgnoreCase)) + { + if (!firstSelect) indentSb.Append(oneTab); else firstSelect = false; + + } + else if (tokens[i].StartsWith(endCue, StringComparison.OrdinalIgnoreCase)) + { + indentSb.Length -= oneTab.Length; + } + + sb.Append(indentSb).Append(tokens[i]).Append("\n"); + } + + return sb.ToString(); + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteStartElement(nameof(this.SqlQuery)); + xmlWriter.WriteCData(this.SqlQuery); + xmlWriter.WriteEndElement(); + if (this.InputData != null) + { + xmlWriter.WriteStartElement("InputData"); + xmlWriter.WriteCData(this.InputData); + xmlWriter.WriteEndElement(); + } + if (this.Results != null) + { + xmlWriter.WriteStartElement("Results"); + xmlWriter.WriteCData(this.Results); + xmlWriter.WriteEndElement(); + } + if (this.ErrorMessage != null) + { + xmlWriter.WriteStartElement("ErrorMessage"); + xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.ErrorMessage)); + xmlWriter.WriteEndElement(); + } + } + } + + class SystemTextJsonLinqSerializer : CosmosLinqSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + + public override string SerializeMemberName(MemberInfo memberInfo) + { + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + + string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) + ? jsonPropertyNameAttribute.Name + : memberInfo.Name; + + return memberName; + } + } + + class SystemTextJsonSerializer : CosmosSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 296072a411..61e7745427 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -37,6 +37,7 @@ + @@ -164,6 +165,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 7b18607b8b0eeef592efc93671243c7855ac7cb5 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Tue, 30 Jan 2024 15:21:03 -0800 Subject: [PATCH 270/337] Documentation refresh: Fixes DeleteItem API will not return context in response (#4291) * Update csproj * Applying suggestion from comment --------- Co-authored-by: Jake Willey --- Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 7084eb5ada..bc5b1323c3 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -820,6 +820,8 @@ public abstract Task PatchItemStreamAsync( /// /// https://aka.ms/cosmosdb-dot-net-exceptions#stream-api /// + /// For delete operations, the will be null. Item content is not expected in the response. + /// /// The Stream operation only throws on client side exceptions. This is to increase performance and prevent the overhead of throwing exceptions. Check the HTTP status code on the response to check if the operation failed. /// /// @@ -854,6 +856,8 @@ public abstract Task DeleteItemStreamAsync( /// /// is always null /// + /// For delete operations, the will be null. Item content is not expected in the response. + /// /// https://aka.ms/cosmosdb-dot-net-exceptions#typed-api /// /// From d7a954f8ec216f7494e0bc6ff6762e9fce081822 Mon Sep 17 00:00:00 2001 From: Achint-Agrawal <45819170+Achint-Agrawal@users.noreply.github.com> Date: Wed, 31 Jan 2024 06:17:47 +0530 Subject: [PATCH 271/337] PriorityBasedExecution: Adds PriorityLevel in CosmosClientOptions (#4262) * Added PriorityLevel in CosmosClientoptions * Addressed comments on PR * Changed remark to remarks * Corrected null check * Updated contracts * reverted changes to PartitionKeyHashBaselineTest.Lists.xml * Update Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs Co-authored-by: Matias Quaranta * Making priority level as GA contract * fixing the preview contract API * resetting few misc files * Builder and contract changes: --------- Co-authored-by: Achint Agrawal Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta --- .../src/CosmosClientOptions.cs | 64 ++++++++------ .../src/Fluent/CosmosClientBuilder.cs | 16 ++++ .../src/Handler/ClientPipelineBuilder.cs | 6 +- .../src/Handler/RequestInvokerHandler.cs | 26 +++++- .../src/RequestOptions/RequestOptions.cs | 8 +- .../src/Resource/ClientContextCore.cs | 1 + .../src/Resource/Settings/PriorityLevel.cs | 8 +- .../Contracts/DotNetPreviewSDKAPI.json | 46 ---------- .../Contracts/DotNetSDKAPI.json | 64 ++++++++++++++ .../CosmosClientOptionsUnitTests.cs | 38 ++++++++- .../HandlerTests.cs | 84 +++++++++++++++++-- .../RetryHandlerTests.cs | 15 ++-- 12 files changed, 271 insertions(+), 105 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 8700f2e56e..a6da426992 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -280,6 +280,16 @@ public ConnectionMode ConnectionMode /// public ConsistencyLevel? ConsistencyLevel { get; set; } + /// + /// Sets the priority level for requests created using cosmos client. + /// + /// + /// If priority level is also set at request level in , that priority is used. + /// If is set to true in CosmosClientOptions, priority level set on the CosmosClient is used. + /// + /// + public PriorityLevel? PriorityLevel { get; set; } + /// /// Gets or sets the maximum number of retries in the case where the request fails /// because the Azure Cosmos DB service has applied rate limiting on the client. @@ -731,8 +741,8 @@ internal Protocol ConnectionProtocol /// Flag that controls whether CPU monitoring thread is created to enrich timeout exceptions with additional diagnostic. Default value is true. /// internal bool? EnableCpuMonitor { get; set; } - - /// + + /// /// Flag indicates the value of DisableServerCertificateValidation flag set at connection string level.Default it is false. /// internal bool DisableServerCertificateValidation { get; set; } @@ -852,13 +862,13 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) return (Documents.ConsistencyLevel)this.ConsistencyLevel.Value; } - internal static string GetAccountEndpoint(string connectionString) - { + internal static string GetAccountEndpoint(string connectionString) + { return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountEndpoint, null); - } - - internal static string GetAccountKey(string connectionString) - { + } + + internal static string GetAccountKey(string connectionString) + { return CosmosClientOptions.GetValueFromConnectionString(connectionString, CosmosClientOptions.ConnectionStringAccountKey, null); } @@ -876,21 +886,21 @@ internal static CosmosClientOptions GetCosmosClientOptionsWithCertificateFlag(st } return clientOptions; - } - + } + private static T GetValueFromConnectionString(string connectionString, string keyName, T defaultValue) - { - if (connectionString == null) - { - throw new ArgumentNullException(nameof(connectionString)); - } - - DbConnectionStringBuilder builder = new DbConnectionStringBuilder { ConnectionString = connectionString }; - if (builder.TryGetValue(keyName, out object value)) - { - string keyNameValue = value as string; - if (!string.IsNullOrEmpty(keyNameValue)) - { + { + if (connectionString == null) + { + throw new ArgumentNullException(nameof(connectionString)); + } + + DbConnectionStringBuilder builder = new DbConnectionStringBuilder { ConnectionString = connectionString }; + if (builder.TryGetValue(keyName, out object value)) + { + string keyNameValue = value as string; + if (!string.IsNullOrEmpty(keyNameValue)) + { try { return (T)Convert.ChangeType(value, typeof(T)); @@ -905,9 +915,9 @@ private static T GetValueFromConnectionString(string connectionString, string if (defaultValue != null) { return defaultValue; - } - - throw new ArgumentException("The connection string is missing a required property: " + keyName); + } + + throw new ArgumentException("The connection string is missing a required property: " + keyName); } private void ValidateLimitToEndpointSettings() @@ -935,8 +945,8 @@ private void ValidatePartitionLevelFailoverSettings() { throw new ArgumentException($"{nameof(this.ApplicationPreferredRegions)} is required when {nameof(this.EnablePartitionLevelFailover)} is enabled."); } - } - + } + private void ValidateAndSetServerCallbackSettings() { if (this.DisableServerCertificateValidation && this.ServerCertificateCustomValidationCallback != null) diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index e030411338..a4d0381e6c 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -442,6 +442,22 @@ public CosmosClientBuilder WithConsistencyLevel(Cosmos.ConsistencyLevel consiste } + /// + /// Sets the priority level for requests created using cosmos client. + /// + /// + /// If priority level is also set at request level in , that priority is used. + /// If is set to true, priority level set on the CosmosClient is used. + /// + /// The desired priority level for the client. + /// The current . + /// + public CosmosClientBuilder WithPriorityLevel(Cosmos.PriorityLevel priorityLevel) + { + this.clientOptions.PriorityLevel = priorityLevel; + return this; + } + /// /// Sets the connection mode to Gateway. This is used by the client when connecting to the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs index aa69b770e1..5427700911 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ClientPipelineBuilder.cs @@ -15,6 +15,7 @@ internal class ClientPipelineBuilder { private readonly CosmosClient client; private readonly ConsistencyLevel? requestedClientConsistencyLevel; + private readonly PriorityLevel? requestedPriorityLevel; private readonly DiagnosticsHandler diagnosticsHandler; private readonly RequestHandler invalidPartitionExceptionRetryHandler; private readonly RequestHandler transportHandler; @@ -26,11 +27,13 @@ internal class ClientPipelineBuilder public ClientPipelineBuilder( CosmosClient client, ConsistencyLevel? requestedClientConsistencyLevel, + PriorityLevel? requestedClientPriorityLevel, IReadOnlyCollection customHandlers, TelemetryToServiceHelper telemetryToServiceHelper) { this.client = client ?? throw new ArgumentNullException(nameof(client)); this.requestedClientConsistencyLevel = requestedClientConsistencyLevel; + this.requestedPriorityLevel = requestedClientPriorityLevel; this.transportHandler = new TransportHandler(client); Debug.Assert(this.transportHandler.InnerHandler == null, nameof(this.transportHandler)); @@ -149,7 +152,8 @@ public RequestInvokerHandler Build() { RequestInvokerHandler root = new RequestInvokerHandler( this.client, - this.requestedClientConsistencyLevel); + this.requestedClientConsistencyLevel, + this.requestedPriorityLevel); RequestHandler current = root; if (this.CustomHandlers != null && this.CustomHandlers.Any()) diff --git a/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs index bb322f19b1..74888b5316 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/RequestInvokerHandler.cs @@ -27,16 +27,19 @@ internal class RequestInvokerHandler : RequestHandler private readonly CosmosClient client; private readonly Cosmos.ConsistencyLevel? RequestedClientConsistencyLevel; + private readonly Cosmos.PriorityLevel? RequestedClientPriorityLevel; private bool? IsLocalQuorumConsistency; private Cosmos.ConsistencyLevel? AccountConsistencyLevel = null; public RequestInvokerHandler( CosmosClient client, - Cosmos.ConsistencyLevel? requestedClientConsistencyLevel) + Cosmos.ConsistencyLevel? requestedClientConsistencyLevel, + Cosmos.PriorityLevel? requestedClientPriorityLevel) { this.client = client; this.RequestedClientConsistencyLevel = requestedClientConsistencyLevel; + this.RequestedClientPriorityLevel = requestedClientPriorityLevel; } public override async Task SendAsync( @@ -66,6 +69,8 @@ public override async Task SendAsync( } await this.ValidateAndSetConsistencyLevelAsync(request); + this.SetPriorityLevel(request); + (bool isError, ResponseMessage errorResponse) = await this.EnsureValidClientAsync(request, request.Trace); if (isError) { @@ -431,6 +436,25 @@ private async Task ValidateAndSetConsistencyLevelAsync(RequestMessage requestMes } } + /// + /// Set the PriorityLevel in the request headers + /// + /// + private void SetPriorityLevel(RequestMessage requestMessage) + { + Cosmos.PriorityLevel? priorityLevel = this.RequestedClientPriorityLevel; + RequestOptions promotedRequestOptions = requestMessage.RequestOptions; + if (promotedRequestOptions?.PriorityLevel.HasValue == true) + { + priorityLevel = promotedRequestOptions.PriorityLevel.Value; + } + + if (priorityLevel.HasValue) + { + requestMessage.Headers.Set(HttpConstants.HttpHeaders.PriorityLevel, priorityLevel.ToString()); + } + } + internal static bool ShouldSetNoContentResponseHeaders(RequestOptions requestOptions, CosmosClientOptions clientOptions, OperationType operationType, diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index 2502c75823..dffda96fab 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -47,6 +47,7 @@ public class RequestOptions /// /// Setting priority level only has an effect if Priority Based Execution is enabled. /// If it is not enabled, the priority level is ignored by the backend. + /// If is set to true on CosmosClient, priority level set in RequestOptions is ignored. /// Default PriorityLevel for each request is treated as High. It can be explicitly set to Low for some requests. /// When Priority based execution is enabled, if there are more requests than the configured RU/S in a second, /// then Cosmos DB will throttle low priority requests to allow high priority requests to execute. @@ -55,12 +56,7 @@ public class RequestOptions /// configured RU/s, low priority requests start getting throttled first to allow execution of mission critical workloads. /// /// -#if PREVIEW - public -#else - internal -#endif - PriorityLevel? PriorityLevel { get; set; } + public PriorityLevel? PriorityLevel { get; set; } /// /// Threshold values for Distributed Tracing. diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index 9d1b534c07..c9331afacd 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -120,6 +120,7 @@ internal static CosmosClientContext Create( ClientPipelineBuilder clientPipelineBuilder = new ClientPipelineBuilder( cosmosClient, clientOptions.ConsistencyLevel, + clientOptions.PriorityLevel, clientOptions.CustomHandlers, telemetryToServiceHelper: documentClient.telemetryToServiceHelper); diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs index 6644d0931f..cfbddb0a86 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/PriorityLevel.cs @@ -18,13 +18,7 @@ namespace Microsoft.Azure.Cosmos /// configured RU/s, low priority requests start getting throttled first to allow execution of mission critical workloads. /// /// - -#if PREVIEW - public -#else - internal -#endif - enum PriorityLevel + public enum PriorityLevel { /// /// High Priority diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index c102e8075e..fc09ffd7cf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -466,52 +466,6 @@ } }, "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.PriorityLevel;System.Enum;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:True;IsClass:False;IsValueType:True;IsNested:False;IsGenericType:False;IsSerializable:True": { - "Subclasses": {}, - "Members": { - "Int32 value__": { - "Type": "Field", - "Attributes": [], - "MethodInfo": "Int32 value__;IsInitOnly:False;IsStatic:False;" - }, - "Microsoft.Azure.Cosmos.PriorityLevel High": { - "Type": "Field", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel High;IsInitOnly:False;IsStatic:True;" - }, - "Microsoft.Azure.Cosmos.PriorityLevel Low": { - "Type": "Field", - "Attributes": [], - "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel Low;IsInitOnly:False;IsStatic:True;" - } - }, - "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.RequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} } }, "Members": {}, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index f49a470177..3ce587dcd3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2854,6 +2854,18 @@ "Attributes": [], "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode] PortReuseMode;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode] get_PortReuseMode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PortReuseMode(System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Nullable`1[System.Boolean] EnableContentResponseOnWrite": { "Type": "Property", "Attributes": [], @@ -3096,6 +3108,13 @@ "Attributes": [], "MethodInfo": "Void set_PortReuseMode(System.Nullable`1[Microsoft.Azure.Cosmos.PortReuseMode]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_RequestTimeout(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -4599,6 +4618,11 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithLimitToEndpoint(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithPriorityLevel(Microsoft.Azure.Cosmos.PriorityLevel)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithPriorityLevel(Microsoft.Azure.Cosmos.PriorityLevel);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithRequestTimeout(System.TimeSpan)": { "Type": "Method", "Attributes": [], @@ -6396,6 +6420,27 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.PriorityLevel;System.Enum;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:True;IsClass:False;IsValueType:True;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Int32 value__": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Int32 value__;IsInitOnly:False;IsStatic:False;" + }, + "Microsoft.Azure.Cosmos.PriorityLevel High": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel High;IsInitOnly:False;IsStatic:True;" + }, + "Microsoft.Azure.Cosmos.PriorityLevel Low": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.PriorityLevel Low;IsInitOnly:False;IsStatic:True;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.QueryDefinition;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -8046,6 +8091,18 @@ ], "MethodInfo": "System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] PriorityLevel;CanRead:True;CanWrite:True;System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel] get_PriorityLevel();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String get_IfMatchEtag()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -8110,6 +8167,13 @@ ], "MethodInfo": "Void set_IfNoneMatchEtag(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_PriorityLevel(System.Nullable`1[Microsoft.Azure.Cosmos.PriorityLevel]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_Properties(System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index b0b6b8be35..53ed1c343d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -54,6 +54,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Cosmos.PortReuseMode portReuseMode = Cosmos.PortReuseMode.PrivatePortPool; IWebProxy webProxy = new TestWebProxy(); Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + Cosmos.PriorityLevel priorityLevel = Cosmos.PriorityLevel.Low; CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder( accountEndpoint: endpoint, @@ -82,6 +83,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(clientOptions.EnableTcpConnectionEndpointRediscovery); Assert.IsNull(clientOptions.HttpClientFactory); Assert.AreNotEqual(consistencyLevel, clientOptions.ConsistencyLevel); + Assert.AreNotEqual(priorityLevel, clientOptions.PriorityLevel); Assert.IsFalse(clientOptions.EnablePartitionLevelFailover); Assert.IsFalse(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue); @@ -117,7 +119,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithBulkExecution(true) .WithSerializerOptions(cosmosSerializerOptions) - .WithConsistencyLevel(consistencyLevel); + .WithConsistencyLevel(consistencyLevel) + .WithPriorityLevel(priorityLevel); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); clientOptions = cosmosClient.ClientOptions; @@ -140,6 +143,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(object.ReferenceEquals(webProxy, clientOptions.WebProxy)); Assert.IsTrue(clientOptions.AllowBulkExecution); Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); + Assert.AreEqual(priorityLevel, clientOptions.PriorityLevel); Assert.IsFalse(clientOptions.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue && clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); @@ -238,6 +242,8 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg }; Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + Cosmos.PriorityLevel priorityLevel = Cosmos.PriorityLevel.Low; + CosmosClientBuilder cosmosClientBuilder = new( accountEndpoint: endpoint, authKeyOrResourceToken: key); @@ -250,7 +256,8 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg .WithApiType(apiType) .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithSerializerOptions(cosmosSerializerOptions) - .WithConsistencyLevel(consistencyLevel); + .WithConsistencyLevel(consistencyLevel) + .WithPriorityLevel(priorityLevel); if (!useEnvironmentVariable) { @@ -302,6 +309,7 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg }; Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + Cosmos.PriorityLevel priorityLevel = Cosmos.PriorityLevel.Low; CosmosClientBuilder cosmosClientBuilder = new( accountEndpoint: endpoint, authKeyOrResourceToken: key); @@ -315,6 +323,7 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithSerializerOptions(cosmosSerializerOptions) .WithConsistencyLevel(consistencyLevel) + .WithPriorityLevel(priorityLevel) .WithPartitionLevelFailoverEnabled() .WithApplicationPreferredRegions( new List() @@ -372,6 +381,31 @@ public void VerifyConsisentencyLevels() Assert.IsNull(cosmosClientOptionsNull.GetDocumentsConsistencyLevel()); } + + [TestMethod] + public void VerifyPriorityLevels() + { + List cosmosLevels = Enum.GetValues(typeof(Cosmos.PriorityLevel)).Cast().ToList(); + List documentLevels = Enum.GetValues(typeof(Documents.PriorityLevel)).Cast().ToList(); + CollectionAssert.AreEqual(cosmosLevels, documentLevels, new EnumComparer(), "Document priority level is different from cosmos priority level"); + + foreach (Cosmos.PriorityLevel priorityLevel in cosmosLevels) + { + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + PriorityLevel = priorityLevel + }; + + Assert.AreEqual(priorityLevel, cosmosClientOptions.PriorityLevel); + } + + CosmosClientOptions cosmosClientOptionsNull = new CosmosClientOptions() + { + PriorityLevel = null + }; + + Assert.IsNull(cosmosClientOptionsNull.PriorityLevel); + } [TestMethod] public void VerifyPortReuseModeIsSyncedWithDirect() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs index d3d0e45653..fa4dd942a3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/HandlerTests.cs @@ -126,7 +126,7 @@ public async Task RequestOptionsHandlerCanHandleRequestOptions() CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -176,7 +176,7 @@ public async Task RequestOptionsConsistencyLevel() return TestHandler.ReturnSuccess(); }); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -227,7 +227,7 @@ public async Task QueryRequestOptionsDedicatedGatewayRequestOptions() using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -257,7 +257,7 @@ public async Task QueryRequestOptionsSessionToken() using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -285,7 +285,7 @@ public async Task ConsistencyLevelClient() return TestHandler.ReturnSuccess(); }); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: client.ClientOptions.ConsistencyLevel) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: client.ClientOptions.ConsistencyLevel, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -301,6 +301,73 @@ public async Task ConsistencyLevelClient() } } + [TestMethod] + public async Task PriorityLevelClient() + { + List cosmosLevels = Enum.GetValues(typeof(Cosmos.PriorityLevel)).Cast().ToList(); + foreach (Cosmos.PriorityLevel clientLevel in cosmosLevels) + { + using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( + accountConsistencyLevel: null, + customizeClientBuilder: builder => builder.WithPriorityLevel(clientLevel)); + + TestHandler testHandler = new TestHandler((request, cancellationToken) => + { + Assert.AreEqual(clientLevel.ToString(), request.Headers[HttpConstants.HttpHeaders.PriorityLevel]); + return TestHandler.ReturnSuccess(); + }); + + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: client.ClientOptions.PriorityLevel) + { + InnerHandler = testHandler + }; + + RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")) + { + ResourceType = ResourceType.Document + }; + requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); + requestMessage.OperationType = OperationType.Read; + + await invoker.SendAsync(requestMessage, new CancellationToken()); + } + } + + [TestMethod] + public async Task TestRequestPriorityLevelTakesPrecedence() + { + Cosmos.PriorityLevel clientLevel = Cosmos.PriorityLevel.Low; + Cosmos.PriorityLevel requestLevel = Cosmos.PriorityLevel.High; + + using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient( + accountConsistencyLevel: null, + customizeClientBuilder: builder => builder.WithPriorityLevel(clientLevel)); + + TestHandler testHandler = new TestHandler((request, cancellationToken) => + { + Assert.AreEqual(requestLevel.ToString(), request.Headers[HttpConstants.HttpHeaders.PriorityLevel]); + return TestHandler.ReturnSuccess(); + }); + + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: client.ClientOptions.PriorityLevel) + { + InnerHandler = testHandler + }; + + RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")) + { + ResourceType = ResourceType.Document + }; + requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); + requestMessage.OperationType = OperationType.Read; + requestMessage.RequestOptions = new RequestOptions + { + PriorityLevel = requestLevel + }; + + await invoker.SendAsync(requestMessage, new CancellationToken()); + } + [TestMethod] public async Task ConsistencyLevelClientAndRequestOption() { @@ -315,7 +382,7 @@ public async Task ConsistencyLevelClientAndRequestOption() return TestHandler.ReturnSuccess(); }); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -353,7 +420,7 @@ public async Task RequestOptionsHandlerCanHandleDataPlaneRequestOptions() using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null) + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null) { InnerHandler = testHandler }; @@ -544,7 +611,8 @@ private static async Task TestResolveFeedRangeBasedOnPrefixAsync( RequestInvokerHandler invoker = new( client: client, - requestedClientConsistencyLevel: default); + requestedClientConsistencyLevel: default, + requestedClientPriorityLevel: default); Cosmos.FeedRange feedRange = await RequestInvokerHandler.ResolveFeedRangeBasedOnPrefixContainerAsync( feedRange: inputFeedRange, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RetryHandlerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RetryHandlerTests.cs index 109b5c5ebe..6e5bd4bac3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RetryHandlerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/RetryHandlerTests.cs @@ -33,7 +33,7 @@ public async Task RetryHandlerDoesNotRetryOnSuccess() }); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Delete, RetryHandlerTests.TestUri); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); @@ -63,7 +63,7 @@ public async Task RetryHandlerRetriesOn429() }); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Delete, RetryHandlerTests.TestUri); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); @@ -93,7 +93,7 @@ public async Task RetryHandlerDoesNotRetryOnException() }); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); @@ -135,7 +135,7 @@ public async Task RetryHandlerHttpClientExceptionRefreshesLocations() }); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new System.Uri("https://dummy.documents.azure.com:443/dbs")); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); @@ -189,7 +189,7 @@ private async Task RetryHandlerDontRetryOnStatusCode( RetryHandler retryHandler = new RetryHandler(client); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Delete, RetryHandlerTests.TestUri); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); @@ -217,7 +217,8 @@ public async Task InvalidPartitionExceptionRetryHandlerDoesNotRetryOnSuccess() retryHandler.InnerHandler = testHandler; RequestInvokerHandler invoker = new RequestInvokerHandler( client, - requestedClientConsistencyLevel: null) + requestedClientConsistencyLevel: null, + requestedClientPriorityLevel: null) { InnerHandler = retryHandler }; @@ -249,7 +250,7 @@ public async Task InvalidPartitionExceptionRetryHandlerDoesNotRetryOn410() }); retryHandler.InnerHandler = testHandler; - RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null); + RequestInvokerHandler invoker = new RequestInvokerHandler(client, requestedClientConsistencyLevel: null, requestedClientPriorityLevel: null); invoker.InnerHandler = retryHandler; RequestMessage requestMessage = new RequestMessage(HttpMethod.Get, new Uri("https://dummy.documents.azure.com:443/dbs")); From 83958bb3cee2bb7d0533dc526951d26878b7a261 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 31 Jan 2024 08:54:16 -0800 Subject: [PATCH 272/337] GlobalEndpointManager: Fixes Unobserved and Unhandled Exception from Getting Thrown (#4241) * Code changes to add continuation token for account properties task. * Code changes to fix unobserved exception from getting thrown. * Code changes to sync up with master and remvoe unnecessary changes. --- .../src/Routing/GlobalEndpointManager.cs | 7 +++- .../GlobalEndpointManagerTest.cs | 39 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index 15ac52bea0..db1a01cd61 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -584,7 +584,12 @@ private async Task RefreshDatabaseAccountInternalAsync(bool forceRefresh) { this.LastBackgroundRefreshUtc = DateTime.UtcNow; this.locationCache.OnDatabaseAccountRead(await this.GetDatabaseAccountAsync(true)); - + } + catch (Exception ex) + { + DefaultTrace.TraceWarning("Failed to refresh database account with exception: {0}. Activity Id: '{1}'", + ex, + System.Diagnostics.Trace.CorrelationManager.ActivityId); } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs index 28e24d7e55..30c0d4e457 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs @@ -407,6 +407,45 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() } } + /// + /// Test to validate that when an exception is thrown during a RefreshLocationAsync call + /// the exception should not be bubbled up and remain unobserved. The exception should be + /// handled gracefully and logged as a warning trace event. + /// + [TestMethod] + public async Task RefreshLocationAsync_WhenGetDatabaseThrowsException_ShouldNotBubbleUpAsUnobservedException() + { + // Arrange. + Mock mockOwner = new Mock(); + mockOwner.Setup(owner => owner.ServiceEndpoint).Returns(new Uri("https://defaultendpoint.net/")); + mockOwner.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny(), It.IsAny())).ThrowsAsync(new TaskCanceledException()); + + //Create connection policy and populate preferred locations + ConnectionPolicy connectionPolicy = new ConnectionPolicy(); + connectionPolicy.PreferredLocations.Add("ReadLocation1"); + connectionPolicy.PreferredLocations.Add("ReadLocation2"); + + bool isExceptionLogged = false; + void TraceHandler(string message) + { + if (message.Contains("Failed to refresh database account with exception:")) + { + isExceptionLogged = true; + } + } + + DefaultTrace.TraceSource.Listeners.Add(new TestTraceListener { Callback = TraceHandler }); + DefaultTrace.InitEventListener(); + + using GlobalEndpointManager globalEndpointManager = new (mockOwner.Object, connectionPolicy); + + // Act. + await globalEndpointManager.RefreshLocationAsync(forceRefresh: false); + + // Assert. + Assert.IsTrue(isExceptionLogged, "The exception was logged as a warning trace event."); + } + private sealed class GetAccountRequestInjector { public Func ShouldFailRequest { get; set; } From b933cb8e450df5f1e6d79c648d161a06c46ea65b Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 31 Jan 2024 14:13:14 -0800 Subject: [PATCH 273/337] 3.38.0: Adds new SDK versions and contract files (#4277) * Updated change log and bumped up the minor version. * Code changes to add few more required commits. * Code changes to pick new commits. * Code changes to address review comments. * Code changes to address more review comments. * Refactored the Warning section for better visibility. * Removed some of the unnecessary items. --- Directory.Build.props | 6 +- .../contracts/API_3.38.0.txt | 1565 ++++++++++++++++ .../contracts/API_3.39.0-preview.0.txt | 1622 +++++++++++++++++ changelog.md | 30 + 4 files changed, 3220 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.38.0.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.39.0-preview.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 7e9c4741ba..8b31c98888 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.37.1 - 3.37.1 - preview + 3.38.0 + 3.39.0 + preview.0 3.32.0 2.0.4 2.1.0 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.38.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.38.0.txt new file mode 100644 index 0000000000..90efc0b0d0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.38.0.txt @@ -0,0 +1,1565 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MexicoCentral = "Mexico Central"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.39.0-preview.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.39.0-preview.0.txt new file mode 100644 index 0000000000..dbc344e943 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.39.0-preview.0.txt @@ -0,0 +1,1622 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public abstract class CosmosLinqSerializer : CosmosSerializer + { + protected CosmosLinqSerializer(); + public abstract string SerializeMemberName(MemberInfo memberInfo); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MexicoCentral = "Mexico Central"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 1fd2e31825..09228b9cfe 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,36 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.39.0-preview.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.0) - 2024-01-31 + +#### Added +- [4138](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4138) Query: Adds support for LINQ Custom Serializer (#4138) + +### [3.38.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.38.0) - 2024-01-31 + > :warning: Note: Starting with version `3.38.0`, the .NET SDK enables the ODE feature by default. This can potentially cause a new type of continuation token to be generated. Such a token is not recognized by the older SDKs by design and this could result in a Malformed Continuation Token Exception. + > If you have a scenario where tokens generated from the newer SDKs are used by an older SDK, we recommend a 2 step approach to upgrade: + > - Upgrade to the new SDK and disable ODE, both together as part of a single deployment. Wait for all nodes to upgrade. + > - In order to disable ODE, set EnableOptimisticDirectExecution to false in the QueryRequestOptions. + > - Enable ODE as part of second deployment for all nodes. + +#### Fixed +- [4205](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4205) ClientRetryPolicy: Fixes Metadata Requests Retry Policy (#4205) +- [4220](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4220) Change Feed Processor: Fixes disposal of unused CancellationTokenSource (#4220) +- [4229](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4229) GatewayClientStore: Fixes an issue with dealing with invalid JSON HTTP responses (#4229) +- [4260](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4260) Query: Fixes LINQ Translation of SqlNullLiteral Values (#4260) +- [4276](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4276) Change Feed Processor: Fixes LeaseLostException on Notifications API for Renewer (#4276) +- [4241](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4241) GlobalEndpointManager: Fixes Unobserved and Unhandled Exception from Getting Thrown (#4241) + +#### Added +- [4122](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4122) Query: Adds Optimistic Direct Execution configuration override support on the Client (#4122) +- [4240](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4240) BulkMode: Adds PartitionKeyRangeId in Bulk Mode and TransactionalBatch Response Headers (#4240) +- [4252](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4252) Query: Adds Request Charge to Query Metrics (#4252) +- [4225](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4225) Query: Refactors Optimistic Direct Execution to be turned on by default on .NET SDK (#4225). **WARNING:** This is breaking change for GA. For more details, please take a look at the `3.38.0` Note section. +- [4251](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4251) Emulator : Adds support for flag in connection string to ignore SSL check (#4251) +- [4279](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4279) Region Availability: Adds Spain Central and Mexico Central Regions For Public Usage (#4279) +- [4286](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4286) Query: Adds LINQ Support for FirstOrDefault (#4286) +- [4262](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4262) PriorityBasedExecution: Adds PriorityLevel in CosmosClientOptions (#4262) + ### [3.37.1-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.1-preview) - 2024-1-2 ### [3.37.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.1) - 2024-1-2 From 95912534b903d7f9838263e46c7d1c1dccf76300 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 1 Feb 2024 18:34:35 -0800 Subject: [PATCH 274/337] [Internal] Query: Adds environment variable for overriding EnableOptimisticDirectExecution default (#4299) * Configured default value for EnableOptimisticDirectExecution setting to honor environment variable. * Updated tests to include case insensitive checks no environment variable name. * Addressed comments. * Removed unused using. --- .../src/RequestOptions/QueryRequestOptions.cs | 2 +- .../src/Util/ConfigurationManager.cs | 17 +++ .../OptimisticDirectExecutionQueryTests.cs | 144 +++++++++++++++++- 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 7d4da6f535..1035fac1c9 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,7 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - public bool EnableOptimisticDirectExecution { get; set; } = true; + public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: true); /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 3c48b1f5ab..1be83b2430 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -22,6 +22,11 @@ internal static class ConfigurationManager /// internal static readonly string PartitionLevelFailoverEnabled = "AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED"; + /// + /// Environment variable name for overriding optimistic direct execution of queries. + /// + internal static readonly string OptimisticDirectExecutionEnabled = "AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED"; + public static T GetEnvironmentVariable(string variable, T defaultValue) { string value = Environment.GetEnvironmentVariable(variable); @@ -72,5 +77,17 @@ public static bool IsPartitionLevelFailoverEnabled( variable: ConfigurationManager.PartitionLevelFailoverEnabled, defaultValue: defaultValue); } + + /// + /// Gets the boolean value indicating whether optimistic direct execution is enabled based on the environment variable override. + /// + public static bool IsOptimisticDirectExecutionEnabled( + bool defaultValue) + { + return ConfigurationManager + .GetEnvironmentVariable( + variable: OptimisticDirectExecutionEnabled, + defaultValue: defaultValue); + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index cb70aacb41..dbcfafa5ad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -524,6 +524,136 @@ public async Task TestClientDisableOdeDefaultValue() bool success = bool.TryParse(properties.QueryEngineConfiguration[ClientDisableOptimisticDirectExecution].ToString(), out bool clientDisablOde); Assert.IsTrue(success, $"Parsing must succeed. Value supplied '{ClientDisableOptimisticDirectExecution}'"); Assert.IsFalse(clientDisablOde); + } + + [TestMethod] + public async Task TestOdeEnvironmentVariable() + { + QueryRequestOptions options = new QueryRequestOptions(); + Assert.IsTrue(options.EnableOptimisticDirectExecution); + + foreach ((string name, string value, bool expectedValue) in new[] + { + // Environment variables are case insensitive in windows + ("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", "true", true), + ("AZURE_COSMOS_optimistic_direct_execution_enabled", "True", true), + ("azure_cosmos_optimistic_direct_execution_enabled", "TRUE", true), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "truE", true), + ("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", "false", false), + ("AZURE_COSMOS_optimistic_direct_execution_enabled", "False", false), + ("azure_cosmos_optimistic_direct_execution_enabled", "FALSE", false), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "false", false), + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, true), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", true), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, true), + ("enableode", "false", true) + }) + { + try + { + // Test new value + Environment.SetEnvironmentVariable(name, value); + QueryRequestOptions options2 = new QueryRequestOptions(); + bool areEqual = expectedValue == options2.EnableOptimisticDirectExecution; + Assert.IsTrue(areEqual, $"EnvironmentVariable:'{name}', value:'{value}', expected:'{expectedValue}', actual:'{options2.EnableOptimisticDirectExecution}'"); + } + finally + { + // Remove side effects. + Environment.SetEnvironmentVariable(name, null); + } + } + + foreach (string value in new[] + { + "'", + "-", + "asdf", + "'true'", + "'false'" + }) + { + bool receivedException = false; + try + { + // Test new value + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", value); + QueryRequestOptions options2 = new QueryRequestOptions(); + } + catch(FormatException fe) + { + Assert.IsTrue(fe.ToString().Contains($@"String '{value}' was not recognized as a valid Boolean.")); + receivedException = true; + } + finally + { + // Remove side effects. + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", null); + } + + Assert.IsTrue(receivedException, $"Expected exception was not received for value '{value}'"); + } + + await this.TestQueryExecutionUsingODEEnvironmentVariable( + environmentVariableValue: "false", + expectODEPipeline: false); + + await this.TestQueryExecutionUsingODEEnvironmentVariable( + environmentVariableValue: "true", + expectODEPipeline: true); + } + + private async Task TestQueryExecutionUsingODEEnvironmentVariable(string environmentVariableValue, bool expectODEPipeline) + { + IReadOnlyList empty = new List(0); + IReadOnlyList first5Integers = Enumerable.Range(0, 5).ToList(); + IReadOnlyList first7Integers = Enumerable.Range(0, NumberOfDocuments).ToList(); + IReadOnlyList first7IntegersReversed = Enumerable.Range(0, NumberOfDocuments).Reverse().ToList(); + + try + { + // Test query execution using environment variable + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", environmentVariableValue); + PartitionKey partitionKeyValue = new PartitionKey("/value"); + List singlePartitionContainerTestCases = new List() + { + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: null, // Uses environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: expectODEPipeline ? TestInjections.PipelineType.OptimisticDirectExecution : TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: false, // Overrides environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.Passthrough), + CreateInput( + query: $"SELECT TOP 5 VALUE r.numberField FROM r ORDER BY r.{PartitionKeyField}", + expectedResult: first5Integers, + partitionKey: partitionKeyValue, + enableOptimisticDirectExecution: true, // Overrides environment variable + pageSizeOptions: PageSizeOptions.NonGroupByAndNoContinuationTokenPageSizeOptions, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution), + }; + + IReadOnlyList documents = CreateDocuments(NumberOfDocuments, PartitionKeyField, NumberField, NullField); + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition, + documents, + (container, documents) => RunTests(singlePartitionContainerTestCases, container), + "/" + PartitionKeyField); + } + finally + { + // Attempt to protect other ODE tests from side-effects in case of test failure. + Environment.SetEnvironmentVariable("AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED", null); + } } private static async Task RunTests(IEnumerable testCases, Container container) @@ -536,9 +666,13 @@ private static async Task RunTests(IEnumerable testCase { MaxItemCount = pageSize, PartitionKey = testCase.PartitionKey, - EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution, TestSettings = new TestInjections(simulate429s: false, simulateEmptyPages: false, new TestInjections.ResponseStats()) - }; + }; + + if(testCase.EnableOptimisticDirectExecution.HasValue) + { + feedOptions.EnableOptimisticDirectExecution = testCase.EnableOptimisticDirectExecution.Value; + } List items = await RunQueryAsync( container, @@ -600,7 +734,7 @@ private static DirectExecutionTestCase CreateInput( string query, IReadOnlyList expectedResult, PartitionKey? partitionKey, - bool enableOptimisticDirectExecution, + bool? enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) { @@ -612,7 +746,7 @@ private readonly struct DirectExecutionTestCase public string Query { get; } public IReadOnlyList ExpectedResult { get; } public PartitionKey? PartitionKey { get; } - public bool EnableOptimisticDirectExecution { get; } + public bool? EnableOptimisticDirectExecution { get; } public int[] PageSizeOptions { get; } public TestInjections.PipelineType ExpectedPipelineType { get; } @@ -620,7 +754,7 @@ public DirectExecutionTestCase( string query, IReadOnlyList expectedResult, PartitionKey? partitionKey, - bool enableOptimisticDirectExecution, + bool? enableOptimisticDirectExecution, int[] pageSizeOptions, TestInjections.PipelineType expectedPipelineType) { From 3f421fbb03f7f93950bd6eb16032ce4d852420c3 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Fri, 2 Feb 2024 15:02:53 -0800 Subject: [PATCH 275/337] DisableServerCertificateValidation: Fixes Default HttpClient to honor DisableServerCertificateValidation (#4294) * DisableServerCertificateValidation: Fix ensuring that both HttpClient and DocumentClient use a consistency way * E2E Emulator test coverage * - Supporting the combination of both DisableServerCertificateValidation and ServerCertificateCustomValidationCallback combination - Supporting test hook for DisableServerCertificateValidationInvocationCallback (specifically for only Disable checking) * Addressing comments * Fixing a warning * Update Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs Co-authored-by: Fabian Meiswinkel * Update Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs Co-authored-by: Fabian Meiswinkel * Addressing commens * Undoing a change * Fixing UT * Renaming a test case name --------- Co-authored-by: Fabian Meiswinkel --- .../src/CosmosClientOptions.cs | 53 +++++++++++++------ .../src/Resource/ClientContextCore.cs | 4 +- .../ClientTests.cs | 38 +++++++++++++ .../CosmosClientOptionsUnitTests.cs | 41 +++++++++++--- 4 files changed, 112 insertions(+), 24 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index a6da426992..293712a64e 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -664,11 +664,46 @@ internal Protocol ConnectionProtocol /// /// Emulator: To ignore SSL Certificate please suffix connectionstring with "DisableServerCertificateValidation=True;". /// When CosmosClientOptions.HttpClientFactory is used, SSL certificate needs to be handled appropriately. - /// NOTE: DO NOT use this flag in production (only for emulator) + /// NOTE: DO NOT use the `DisableServerCertificateValidation` flag in production (only for emulator) /// /// public Func ServerCertificateCustomValidationCallback { get; set; } - + + /// + /// Real call back that will be hooked down-stream to the transport clients (both http and tcp). + /// NOTE: All down stream real-usage should come through this API only and not through the public API. + /// + /// Test hook DisableServerCertificateValidationInvocationCallback + /// - When configured will invoke it when ever custom validation is done + /// + internal Func GetServerCertificateCustomValidationCallback() + { + if (this.DisableServerCertificateValidation) + { + if (this.DisableServerCertificateValidationInvocationCallback == null) + { + return this.ServerCertificateCustomValidationCallback ?? ((_, _, _) => true); + } + else + { + return (X509Certificate2 cert, X509Chain chain, SslPolicyErrors policyErrors) => + { + bool bValidationResult = true; + if (this.ServerCertificateCustomValidationCallback != null) + { + bValidationResult = this.ServerCertificateCustomValidationCallback(cert, chain, policyErrors); + } + this.DisableServerCertificateValidationInvocationCallback?.Invoke(); + return bValidationResult; + }; + } + } + + return this.ServerCertificateCustomValidationCallback; + } + + internal Action DisableServerCertificateValidationInvocationCallback { get; set; } + /// /// API type for the account /// @@ -773,7 +808,6 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) this.ValidateDirectTCPSettings(); this.ValidateLimitToEndpointSettings(); this.ValidatePartitionLevelFailoverSettings(); - this.ValidateAndSetServerCallbackSettings(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -947,19 +981,6 @@ private void ValidatePartitionLevelFailoverSettings() } } - private void ValidateAndSetServerCallbackSettings() - { - if (this.DisableServerCertificateValidation && this.ServerCertificateCustomValidationCallback != null) - { - throw new ArgumentException($"Cannot specify {nameof(this.DisableServerCertificateValidation)} flag in Connection String and {nameof(this.ServerCertificateCustomValidationCallback)}. Only one can be set."); - } - - if (this.DisableServerCertificateValidation) - { - this.ServerCertificateCustomValidationCallback = (_, _, _) => true; - } - } - private void ValidateDirectTCPSettings() { string settingName = string.Empty; diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index c9331afacd..b2db7e7107 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -66,7 +66,7 @@ internal static CosmosClientContext Create( HttpMessageHandler httpMessageHandler = CosmosHttpClientCore.CreateHttpClientHandler( clientOptions.GatewayModeMaxConnectionLimit, clientOptions.WebProxy, - clientOptions.ServerCertificateCustomValidationCallback); + clientOptions.GetServerCertificateCustomValidationCallback()); DocumentClient documentClient = new DocumentClient( cosmosClient.Endpoint, @@ -81,7 +81,7 @@ internal static CosmosClientContext Create( handler: httpMessageHandler, sessionContainer: clientOptions.SessionContainer, cosmosClientId: cosmosClient.Id, - remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.ServerCertificateCustomValidationCallback), + remoteCertificateValidationCallback: ClientContextCore.SslCustomValidationCallBack(clientOptions.GetServerCertificateCustomValidationCallback()), cosmosClientTelemetryOptions: clientOptions.CosmosClientTelemetryOptions, chaosInterceptorFactory: clientOptions.ChaosInterceptorFactory); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index cbe1343106..403cd30bc9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -507,6 +507,44 @@ public async Task Verify_CertificateCallBackGetsCalled_ForTCP_HTTP() } } + [TestMethod] + public async Task Verify_DisableCertificateValidationCallBackGetsCalled_ForTCP_HTTP() + { + int counter = 0; + CosmosClientOptions options = new CosmosClientOptions() + { + DisableServerCertificateValidationInvocationCallback = () => counter++, + }; + + string authKey = ConfigurationManager.AppSettings["MasterKey"]; + string endpoint = ConfigurationManager.AppSettings["GatewayEndpoint"]; + string connectionStringWithSslDisable = $"AccountEndpoint={endpoint};AccountKey={authKey};DisableServerCertificateValidation=true"; + + using CosmosClient cosmosClient = new CosmosClient(connectionStringWithSslDisable, options); + + string databaseName = Guid.NewGuid().ToString(); + string databaseId = Guid.NewGuid().ToString(); + Cosmos.Database database = null; + + try + { + //HTTP callback + Trace.TraceInformation("Creating test database and container"); + database = await cosmosClient.CreateDatabaseAsync(databaseId); + Cosmos.Container container = await database.CreateContainerAsync(Guid.NewGuid().ToString(), "/id"); + + // TCP callback + ToDoActivity item = ToDoActivity.CreateRandomToDoActivity(); + ResponseMessage responseMessage = await container.CreateItemStreamAsync(TestCommon.SerializerCore.ToStream(item), new Cosmos.PartitionKey(item.id)); + } + finally + { + await database?.DeleteStreamAsync(); + } + + Assert.IsTrue(counter >= 2); + } + [TestMethod] public void SqlQuerySpecSerializationTest() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 53ed1c343d..274723f24e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -938,27 +938,56 @@ public void TestServerCertificatesValidationCallback(string connStr, bool expect if (expectedIgnoreCertificateFlag) { - Assert.IsNotNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); + Assert.IsNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); + Assert.IsNull(cosmosClient.DocumentClient.ConnectionPolicy.ServerCertificateCustomValidationCallback); + Assert.IsTrue(cosmosClient.ClientOptions.DisableServerCertificateValidation); Assert.IsTrue(cosmosClient .ClientOptions - .ServerCertificateCustomValidationCallback(x509Certificate2, x509Chain, sslPolicyErrors)); + .GetServerCertificateCustomValidationCallback()(x509Certificate2, x509Chain, sslPolicyErrors)); + + + CosmosHttpClient httpClient = cosmosClient.DocumentClient.httpClient; + SocketsHttpHandler socketsHttpHandler = (SocketsHttpHandler)httpClient.HttpMessageHandler; + + RemoteCertificateValidationCallback httpClientRemoreCertValidationCallback = socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback; + Assert.IsNotNull(httpClientRemoreCertValidationCallback); + + Assert.IsTrue(httpClientRemoreCertValidationCallback(this, x509Certificate2, x509Chain, sslPolicyErrors)); } else { Assert.IsNull(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback); + Assert.IsFalse(cosmosClient.ClientOptions.DisableServerCertificateValidation); + + Assert.IsNull(cosmosClient.DocumentClient.ConnectionPolicy.ServerCertificateCustomValidationCallback); } } [TestMethod] - [DataRow(ConnectionString + "DisableServerCertificateValidation=true;")] - [ExpectedException(typeof(ArgumentException))] - public void TestServerCertificatesValidationWithDisableSSLFlagTrue(string connStr) + [DataRow(ConnectionString + "DisableServerCertificateValidation=true;", true)] + [DataRow(ConnectionString + "DisableServerCertificateValidation=true;", false)] + public void TestServerCertificatesValidationWithDisableSSLFlagTrue(string connStr, bool setCallback) { CosmosClientOptions options = new CosmosClientOptions { - ServerCertificateCustomValidationCallback = (certificate, chain, sslPolicyErrors) => true + ServerCertificateCustomValidationCallback = (certificate, chain, sslPolicyErrors) => true, }; + + if (setCallback) + { + options.DisableServerCertificateValidationInvocationCallback = () => { }; + } + CosmosClient cosmosClient = new CosmosClient(connStr, options); + Assert.IsTrue(cosmosClient.ClientOptions.DisableServerCertificateValidation); + Assert.AreEqual(cosmosClient.ClientOptions.ServerCertificateCustomValidationCallback, options.ServerCertificateCustomValidationCallback); + Assert.AreEqual(cosmosClient.DocumentClient.ConnectionPolicy.ServerCertificateCustomValidationCallback, options.ServerCertificateCustomValidationCallback); + + CosmosHttpClient httpClient = cosmosClient.DocumentClient.httpClient; + SocketsHttpHandler socketsHttpHandler = (SocketsHttpHandler)httpClient.HttpMessageHandler; + + RemoteCertificateValidationCallback? httpClientRemoreCertValidationCallback = socketsHttpHandler.SslOptions.RemoteCertificateValidationCallback; + Assert.IsNotNull(httpClientRemoreCertValidationCallback); } private class TestWebProxy : IWebProxy From 792dc39923ba8c16745cba934666d51f79da5091 Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:55:58 -0800 Subject: [PATCH 276/337] [Internal] Query: Adds Handling of STJ ExtensionData to Sample Custom Serializer (#4306) * Initial commit * Revert "Initial commit" This reverts commit f826457476c4d2c57f271c2bc910509ec4897151. * sample custom serializer update * update docs --- .../src/Serializer/CosmosLinqSerializer.cs | 15 ++++++++++++--- .../Linq/LinqTestsCommon.cs | 7 +++++++ .../Linq/CosmosLinqJsonConverterTests.cs | 11 +++++++++-- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs index e58abfcebd..191de3a137 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs @@ -3,8 +3,8 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Cosmos { - using System.Reflection; - + using System.Reflection; + /// /// This abstract class can be implemented to allow a custom serializer (Non [Json.NET serializer](https://www.newtonsoft.com/json/help/html/Introduction.htm)'s) /// to be used by the CosmosClient for LINQ queries. @@ -54,11 +54,20 @@ namespace Microsoft.Azure.Cosmos /// /// public override string SerializeMemberName(MemberInfo memberInfo) /// { + /// System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = + /// memberInfo.GetCustomAttribute(true); + /// if (jsonExtensionDataAttribute != null) + /// { + /// return null; + /// } + /// /// JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); /// /// string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) /// ? jsonPropertyNameAttribute.Name - /// : memberInfo.Name; + /// : memberInfo.Name; + /// + /// // Users must add handling for any additional attributes here /// /// return memberName; /// } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 7d703061a4..f8fea9959f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -874,6 +874,13 @@ public override Stream ToStream(T input) public override string SerializeMemberName(MemberInfo memberInfo) { + System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = + memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null) + { + return null; + } + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs index 0931271d92..e3882b3bf3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs @@ -179,7 +179,7 @@ public void TestSystemTextJsonExtensionDataQuery() Expression> expr = a => ((object)a.NetExtensionData["foo"]) == "bar"; string sql = SqlTranslator.TranslateExpression(expr.Body, dotNetOptions); - Assert.AreEqual("(a[\"NetExtensionData\"][\"foo\"] = \"bar\")", sql); + Assert.AreEqual("(a[\"foo\"] = \"bar\")", sql); } class DocumentWithExtensionData @@ -240,7 +240,14 @@ public override Stream ToStream(T input) } public override string SerializeMemberName(MemberInfo memberInfo) - { + { + System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = + memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null) + { + return null; + } + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); string memberName = jsonPropertyNameAttribute != null && !string.IsNullOrEmpty(jsonPropertyNameAttribute.Name) From 8d74003ac5edc758a096e6eac4514efae970cc36 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 6 Feb 2024 03:43:52 +0530 Subject: [PATCH 277/337] [Internal] Direct Version Upgrade: Fixes code to make it compatible with 3.32.1 of direct package (#4282) * upgrade direct package to 3.32.1 * degrade core and add doagnosticspource 6.0.1 * updated otel contract * update otel factory * update contract * fix test * fixed tests * fixed tests * fixed tests * fixed source name and operation name in tests * fix tests * changed add tag fucn for integer fields * updated tests * unmask status code and substatuscode * updated contracts * fix query contract * update contracts after ordered operation activity * removed optional attributes * fix versioning * remove exception creation on request fail * changed message --------- Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> --- Directory.Build.props | 2 +- .../src/Microsoft.Azure.Cosmos.csproj | 5 +- .../CosmosExceptions/CosmosException.cs | 6 +- .../OpenTelemetryAttributeKeys.cs | 2 - .../OpenTelemetryCoreRecorder.cs | 32 +- .../OpenTelemetryRecorderFactory.cs | 18 +- ...iterBaselineTests.BatchOperationsAsync.xml | 22 +- ...riterBaselineTests.BulkOperationsAsync.xml | 1410 ++++++----------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 343 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 56 +- ...neTests.PointOperationsExceptionsAsync.xml | 54 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 350 ++-- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 216 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 46 +- ...selineTests.StreamPointOperationsAsync.xml | 88 +- ...aselineTests.TypedPointOperationsAsync.xml | 88 +- .../Tracing/AssertActivity.cs | 21 +- .../Tracing/CustomListener.cs | 86 +- .../Tracing/CustomOtelExporter.cs | 4 +- .../PartitionKeyHashBaselineTest.Lists.xml | 60 +- .../Contracts/DirectContractTests.cs | 3 +- 21 files changed, 1097 insertions(+), 1815 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 8b31c98888..64957f5af3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.38.0 3.39.0 preview.0 - 3.32.0 + 3.32.1 2.0.4 2.1.0 preview4 diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index b94151babd..6fa9a6f282 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -46,7 +46,7 @@ - + @@ -114,6 +114,7 @@ + @@ -126,7 +127,7 @@ - + diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs index 9d0856507e..aa973bd021 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosException.cs @@ -289,9 +289,9 @@ private string ToStringHelper( /// internal static void RecordOtelAttributes(CosmosException exception, DiagnosticScope scope) { - scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)exception.StatusCode); - scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)exception.SubStatusCode); - scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, exception.RequestCharge); + scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)exception.StatusCode); + scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.SubStatusCode, (int)exception.SubStatusCode); + scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.RequestCharge, (int)exception.RequestCharge); scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(exception.Diagnostics?.GetContactedRegions())); scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 1bb66170b5..14053761f4 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -33,9 +33,7 @@ internal sealed class OpenTelemetryAttributeKeys public const string SubStatusCode = "db.cosmosdb.sub_status_code"; public const string RequestCharge = "db.cosmosdb.request_charge"; public const string Region = "db.cosmosdb.regions_contacted"; - public const string RetryCount = "db.cosmosdb.retry_count"; public const string ItemCount = "db.cosmosdb.item_count"; - public const string RequestDiagnostics = "db.cosmosdb.request_diagnostics"; public const string ActivityId = "db.cosmosdb.activity_id"; public const string CorrelatedActivityId = "db.cosmosdb.correlated_activity_id"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 2928685d97..7679640709 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry using System.Diagnostics; using global::Azure.Core; using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; + using Microsoft.Azure.Documents; /// /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 @@ -21,7 +22,9 @@ internal struct OpenTelemetryCoreRecorder : IDisposable private readonly CosmosThresholdOptions config = null; private readonly Activity activity = null; - private readonly Documents.OperationType operationType = Documents.OperationType.Invalid; + private readonly OperationType operationType = OperationType.Invalid; + private readonly string connectionModeCache = null; + private OpenTelemetryAttributes response = null; internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() @@ -50,13 +53,16 @@ private OpenTelemetryCoreRecorder( string operationName, string containerName, string databaseName, - Documents.OperationType operationType, - CosmosClientContext clientContext, CosmosThresholdOptions config) + OperationType operationType, + CosmosClientContext clientContext, + CosmosThresholdOptions config) { this.scope = scope; this.config = config; + this.operationType = operationType; - + this.connectionModeCache = Enum.GetName(typeof(ConnectionMode), clientContext.ClientOptions.ConnectionMode); + if (scope.IsEnabled) { this.scope.Start(); @@ -145,7 +151,7 @@ public void Record( // Client Information this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id); this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, clientContext.ClientOptions.ConnectionMode); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, this.connectionModeCache); } } @@ -170,7 +176,7 @@ public void MarkFailed(Exception exception) if (this.IsEnabled) { this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionStacktrace, exception.StackTrace); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionType, exception.GetType()); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionType, exception.GetType().Name); // If Exception is not registered with open Telemetry if (!OpenTelemetryCoreRecorder.IsExceptionRegistered(exception, this.scope)) @@ -213,18 +219,18 @@ public void Dispose() { if (this.IsEnabled) { - Documents.OperationType operationType - = (this.response == null || this.response?.OperationType == Documents.OperationType.Invalid) ? this.operationType : this.response.OperationType; + OperationType operationType + = (this.response == null || this.response?.OperationType == OperationType.Invalid) ? this.operationType : this.response.OperationType; - this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, operationType); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, Enum.GetName(typeof(OperationType), operationType)); if (this.response != null) { this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, this.response.RequestContentLength); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, this.response.ResponseContentLength); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.SubStatusCode, this.response.SubStatusCode); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestCharge, this.response.RequestCharge); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.SubStatusCode, this.response.SubStatusCode); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.RequestCharge, (int)this.response.RequestCharge); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, this.response.ItemCount); this.scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, this.response.ActivityId); this.scope.AddAttribute(OpenTelemetryAttributeKeys.CorrelatedActivityId, this.response.CorrelatedActivityId); @@ -237,7 +243,7 @@ Documents.OperationType operationType if (!DiagnosticsFilterHelper.IsSuccessfulResponse(this.response.StatusCode, this.response.SubStatusCode)) { - this.scope.Failed(); + this.scope.Failed($"{(int)this.response.StatusCode}/{this.response.SubStatusCode}"); } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index b8babd37da..b88bb790ee 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -17,17 +17,9 @@ internal static class OpenTelemetryRecorderFactory /// /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once /// - private static readonly Lazy LazyOperationScopeFactory = new Lazy( + private static readonly Lazy LazyScopeFactory = new Lazy( valueFactory: () => new DiagnosticScopeFactory( - clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.OperationPrefix}", - resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true, - suppressNestedClientActivities: true), - isThreadSafe: true); - - private static readonly Lazy LazyNetworkScopeFactory = new Lazy( - valueFactory: () => new DiagnosticScopeFactory( - clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.{OpenTelemetryAttributeKeys.NetworkLevelPrefix}", + clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}", resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, isActivityEnabled: true, suppressNestedClientActivities: true), @@ -45,8 +37,8 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, if (clientContext is { ClientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing: false }) { // If there is no source then it will return default otherwise a valid diagnostic scope - DiagnosticScope scope = LazyOperationScopeFactory.Value.CreateScope(name: operationName, - kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); + DiagnosticScope scope = LazyScopeFactory.Value.CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", + kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? ActivityKind.Internal : ActivityKind.Client); // Need a parent activity id associated with the operation which is logged in diagnostics and used for tracing purpose. // If there are listeners at operation level then scope is enabled and it tries to create activity. @@ -70,7 +62,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, // However, if available listeners are not subscribed to network event then it will lead to scope being enabled but no activity is created. else { - DiagnosticScope requestScope = LazyNetworkScopeFactory.Value.CreateScope(name: operationName); + DiagnosticScope requestScope = LazyScopeFactory.Value.CreateScope(name: $"{OpenTelemetryAttributeKeys.NetworkLevelPrefix}.{operationName}"); openTelemetryRecorder = requestScope.IsEnabled ? OpenTelemetryCoreRecorder.CreateNetworkLevelParentActivity(networkScope: requestScope) : openTelemetryRecorder; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index fb6a5fb720..fea625f80b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -139,9 +139,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ExecuteAsync databaseName containerName @@ -152,22 +152,20 @@ Some Value Direct Batch - Some Value - Some Value - Some Value - Some Value + 400 + 1001 Some Value Some Value Some Value - Some Value South Central US + 400/1001 - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 1001 - 207 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 207 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index d24e0d6ac3..ccbeb216c8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -163,9 +163,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -176,19 +176,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -199,19 +194,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -222,19 +212,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -245,19 +230,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -268,19 +248,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -291,19 +266,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -314,19 +284,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -337,19 +302,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -360,19 +320,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -383,22 +338,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -557,9 +507,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -570,19 +520,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -593,19 +538,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -616,19 +556,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -639,19 +574,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -662,19 +592,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -685,19 +610,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -708,19 +628,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -731,19 +646,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -754,19 +664,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -777,22 +682,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -951,9 +851,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -964,19 +864,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -987,19 +882,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1010,19 +900,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1033,19 +918,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1056,19 +936,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1079,19 +954,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1102,19 +972,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1125,19 +990,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1148,19 +1008,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1171,22 +1026,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -1345,9 +1195,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1358,19 +1208,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1381,19 +1226,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1404,19 +1244,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1427,19 +1262,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1450,19 +1280,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1473,19 +1298,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1496,19 +1316,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1519,19 +1334,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1542,19 +1352,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1565,22 +1370,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -1739,9 +1539,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1752,19 +1552,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1775,19 +1570,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1798,19 +1588,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1821,19 +1606,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1844,19 +1624,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1867,19 +1642,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1890,19 +1660,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1913,19 +1678,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1936,19 +1696,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1959,22 +1714,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2133,9 +1883,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2146,19 +1896,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2169,19 +1914,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2192,19 +1932,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2215,19 +1950,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2238,19 +1968,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2261,19 +1986,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2284,19 +2004,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2307,19 +2022,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2330,19 +2040,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2353,22 +2058,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2527,9 +2227,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2540,19 +2240,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2563,19 +2258,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2586,19 +2276,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2609,19 +2294,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2632,19 +2312,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2655,19 +2330,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2678,19 +2348,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2701,19 +2366,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2724,19 +2384,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2747,22 +2402,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2921,9 +2571,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2934,19 +2584,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2957,19 +2602,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -2980,19 +2620,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3003,19 +2638,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3026,19 +2656,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3049,19 +2674,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3072,19 +2692,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3095,19 +2710,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3118,19 +2728,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3141,22 +2746,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -3315,9 +2915,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3328,19 +2928,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3351,19 +2946,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3374,19 +2964,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3397,19 +2982,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3420,19 +3000,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3443,19 +3018,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3466,19 +3036,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3489,19 +3054,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3512,19 +3072,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3535,22 +3090,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -3709,9 +3259,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3722,19 +3272,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3745,19 +3290,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3768,19 +3308,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3791,19 +3326,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3814,19 +3344,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3837,19 +3362,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3860,19 +3380,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3883,19 +3398,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3906,19 +3416,14 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -3929,22 +3434,17 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -4720,9 +4220,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -4734,11 +4234,11 @@ Direct Some Value Some Value - Some Value - Some Value + 429 + 3 Some Value - Some Value + Microsoft.Azure.Cosmos.CosmosException Create diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 76bc97fa45..c19bdc3c47 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -1023,9 +1023,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -1036,19 +1036,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 304 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -1059,19 +1055,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -1082,19 +1074,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -1105,19 +1093,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -1128,29 +1112,25 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 304 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 304 @@ -1803,9 +1783,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1816,19 +1796,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 304 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1839,19 +1815,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1862,19 +1834,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1885,19 +1853,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1908,29 +1872,25 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 304 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 304 @@ -2564,9 +2524,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -2577,19 +2537,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 304 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -2600,19 +2556,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -2623,19 +2575,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -2646,19 +2594,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Iterator Read Next Async databaseName containerName @@ -2669,29 +2613,25 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 304 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 304 @@ -3345,9 +3285,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3358,19 +3298,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 304 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3381,19 +3317,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3404,19 +3336,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3427,19 +3355,15 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3450,29 +3374,25 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 304 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 304 @@ -3780,9 +3700,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Change Feed Estimator Read Next Async databaseName containerName @@ -3793,22 +3713,17 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value - Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 554f884631..cff19fd002 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -117,12 +117,11 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 DeleteAsync miscdbcustonhandler - cosmosdb Some Value 127.0.0.1 @@ -130,22 +129,16 @@ Some Value Direct Delete - Some Value - Some Value - Some Value - Some Value + 204 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateDatabaseAsync miscdbcustonhandler - cosmosdb Some Value 127.0.0.1 @@ -153,15 +146,10 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - @@ -270,12 +258,11 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 DeleteAsync miscdbdataplane - cosmosdb Some Value 127.0.0.1 @@ -283,22 +270,16 @@ Some Value Direct Delete - Some Value - Some Value - Some Value - Some Value + 204 + 0 Some Value - Some Value Some Value - Some Value - - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateDatabaseAsync miscdbdataplane - cosmosdb Some Value 127.0.0.1 @@ -306,15 +287,10 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 62b8f5b2bb..15a3a7a1c2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -158,9 +158,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -172,11 +172,12 @@ Direct Some Value Some Value - Some Value - Some Value + 408 + 0 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create @@ -434,9 +435,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -448,11 +449,12 @@ Direct Some Value Some Value - Some Value - Some Value + 429 + 3 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create @@ -688,9 +690,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -702,11 +704,12 @@ Direct Some Value Some Value - Some Value - Some Value + 408 + 0 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create @@ -974,9 +977,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -988,11 +991,12 @@ Direct Some Value Some Value - Some Value - Some Value + 408 + 0 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create @@ -1324,9 +1328,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1338,11 +1342,12 @@ Direct Some Value Some Value - Some Value - Some Value + 408 + 0 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create @@ -1507,9 +1512,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -1521,11 +1526,12 @@ Direct Some Value Some Value - Some Value - Some Value + 503 + 20006 Some Value South Central US Some Value + Microsoft.Azure.Cosmos.CosmosException Create diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index ab07cd8448..1bb21e8747 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -639,9 +639,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -652,19 +652,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -675,19 +673,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -698,19 +694,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -721,22 +715,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -1404,9 +1396,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1417,19 +1409,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1440,19 +1430,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1463,19 +1451,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1486,22 +1472,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2150,9 +2134,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2163,19 +2147,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2186,19 +2168,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2209,19 +2189,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2232,22 +2210,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2916,9 +2892,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2929,19 +2905,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2952,19 +2926,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2975,19 +2947,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2998,22 +2968,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -3756,9 +3724,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3769,19 +3737,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3792,19 +3758,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3815,19 +3779,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -3838,22 +3800,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -4525,9 +4485,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -4538,19 +4498,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -4561,19 +4519,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -4584,19 +4540,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -4607,22 +4561,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -5314,9 +5266,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -5327,19 +5279,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -5350,19 +5300,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -5373,19 +5321,17 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -5396,22 +5342,20 @@ Some Value Direct Query - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 60f1b42df3..4c8984d3b8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -576,9 +576,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -589,19 +589,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -612,19 +609,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -635,19 +629,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -658,22 +649,19 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -1278,9 +1266,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1291,19 +1279,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1314,19 +1299,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1337,19 +1319,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -1360,22 +1339,19 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -1961,9 +1937,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -1974,19 +1950,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -1997,19 +1970,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2020,19 +1990,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 FeedIterator Read Next Async databaseName containerName @@ -2043,22 +2010,19 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -2664,9 +2628,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2677,19 +2641,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2700,19 +2661,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2723,19 +2681,16 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 Typed FeedIterator ReadNextAsync databaseName containerName @@ -2746,22 +2701,19 @@ Some Value Direct ReadFeed - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 55033eeb40..9900ce054d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -473,9 +473,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReadManyItemsStreamAsync databaseName containerName @@ -486,22 +486,17 @@ Some Value Direct Read - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value - Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -992,9 +987,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReadManyItemsAsync databaseName containerName @@ -1005,22 +1000,17 @@ Some Value Direct Read - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value - Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index d7b4635605..34415a6ee4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -99,9 +99,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemStreamAsync databaseName containerName @@ -112,22 +112,18 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 201 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 201 @@ -226,9 +222,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReadItemStreamAsync databaseName containerName @@ -239,22 +235,18 @@ Some Value Direct Read - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -361,9 +353,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReplaceItemStreamAsync databaseName containerName @@ -374,22 +366,18 @@ Some Value Direct Replace - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -491,9 +479,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 DeleteItemStreamAsync databaseName containerName @@ -504,22 +492,18 @@ Some Value Direct Delete - Some Value - Some Value - Some Value - Some Value + 204 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 204 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 204 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 1bdc803867..bb3576f9ed 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -119,9 +119,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 CreateItemAsync databaseName containerName @@ -132,22 +132,18 @@ Some Value Direct Create - Some Value - Some Value - Some Value - Some Value + 201 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 201 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 201 @@ -251,9 +247,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReadItemAsync databaseName containerName @@ -264,22 +260,18 @@ Some Value Direct Read - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -396,9 +388,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 ReplaceItemAsync databaseName containerName @@ -409,22 +401,18 @@ Some Value Direct Replace - Some Value - Some Value - Some Value - Some Value + 200 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 200 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 200 @@ -530,9 +518,9 @@ } ] }]]> - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 + https://opentelemetry.io/schemas/1.23.0 DeleteItemAsync databaseName containerName @@ -543,22 +531,18 @@ Some Value Direct Delete - Some Value - Some Value - Some Value - Some Value + 204 + 0 Some Value - Some Value Some Value - Some Value South Central US - + Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.17.0 - Some Value - 0 - 204 + https://opentelemetry.io/schemas/1.23.0 + Some Value + 0 + 204 diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index 2bcd002b79..9a44ec0a82 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -19,7 +19,7 @@ internal static class AssertActivity { public static void IsValidOperationActivity(Activity activity) { - if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase)) + if (activity.OperationName.StartsWith("Operation.", StringComparison.OrdinalIgnoreCase)) { Assert.IsFalse(string.IsNullOrEmpty(activity.GetTagItem("db.cosmosdb.connection_mode").ToString()), $"connection mode is empty for {activity.OperationName}"); @@ -60,10 +60,11 @@ public static void IsValidOperationActivity(Activity activity) "exception.message", "exception.stacktrace", "db.cosmosdb.activity_id", - "db.cosmosdb.correlated_activity_id" + "db.cosmosdb.correlated_activity_id", + "error.type" }; - foreach (KeyValuePair actualTag in activity.Tags) + foreach (KeyValuePair actualTag in activity.TagObjects) { Assert.IsTrue(expectedTags.Contains(actualTag.Key), $"{actualTag.Key} is not allowed for {activity.OperationName}"); @@ -84,19 +85,19 @@ public static void AreEqualAcrossListeners() Assert.AreEqual( JsonConvert.SerializeObject(CustomListener.CollectedOperationActivities.OrderBy(x => x.Id)), JsonConvert.SerializeObject(CustomOtelExporter.CollectedActivities - .Where(activity => activity.Source.Name == $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation") + .Where(activity => activity.OperationName.StartsWith("Operation.")) .OrderBy(x => x.Id))); } - private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) + private static void AssertDatabaseAndContainerName(string name, KeyValuePair tag) { IList exceptionsForContainerAttribute = new List { - "CreateDatabaseAsync", - "CreateDatabaseIfNotExistsAsync", - "ReadAsync", - "DeleteAsync", - "DeleteStreamAsync" + "Operation.CreateDatabaseAsync", + "Operation.CreateDatabaseIfNotExistsAsync", + "Operation.ReadAsync", + "Operation.DeleteAsync", + "Operation.DeleteStreamAsync" }; if ((tag.Key == OpenTelemetryAttributeKeys.ContainerName && !exceptionsForContainerAttribute.Contains(name)) || diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 6d612c29c7..1ce1597ffd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -27,6 +27,31 @@ internal class CustomListener : private readonly Func sourceNameFilter; private readonly string eventName; private readonly bool suppressAllEvents; + private static readonly List TagsWithStaticValue = new List + { + "az.schema_url", + "kind", + "az.namespace", + "db.operation", + "db.system", + "net.peer.name", + "db.name", + "db.cosmosdb.container", + "db.cosmosdb.connection_mode", + "db.cosmosdb.operation_type", + "db.cosmosdb.regions_contacted", + "db.cosmosdb.status_code", + "db.cosmosdb.sub_status_code", + "rntbd.sub_status_code", + "rntbd.status_code", + "error.type" + }; + + private static readonly List TagsToSkip = new List + { + "db.cosmosdb.request_content_length_bytes", + "db.cosmosdb.response_content_length_bytes" + }; private ConcurrentBag subscriptions = new(); private ConcurrentBag Scopes { get; } = new(); @@ -108,12 +133,12 @@ public void OnNext(KeyValuePair value) { if (producedDiagnosticScope.Activity.Id == Activity.Current.Id) { - if (producedDiagnosticScope.Activity.Source.Name.EndsWith("Operation")) + if (producedDiagnosticScope.Activity.OperationName.StartsWith("Operation.")) { AssertActivity.IsValidOperationActivity(producedDiagnosticScope.Activity); CustomListener.CollectedOperationActivities.Add(producedDiagnosticScope.Activity); } - else if (producedDiagnosticScope.Activity.Source.Name.EndsWith("Request")) + else if (producedDiagnosticScope.Activity.OperationName.StartsWith("Request.")) { CustomListener.CollectedNetworkActivities.Add(producedDiagnosticScope.Activity); } @@ -249,28 +274,17 @@ public override void Dispose() private string GenerateTagForBaselineTest(Activity activity) { - List tagsWithStaticValue = new List - { - "az.schema_url", - "kind", - "az.namespace", - "db.operation", - "db.system", - "net.peer.name", - "db.name", - "db.cosmosdb.container", - "db.cosmosdb.connection_mode", - "db.cosmosdb.operation_type", - "db.cosmosdb.regions_contacted", - "tcp.sub_status_code", - "tcp.status_code" - }; - StringBuilder builder = new StringBuilder(); builder.Append($""); - foreach (KeyValuePair tag in activity.Tags) + + foreach (KeyValuePair tag in activity.TagObjects) { - if (tagsWithStaticValue.Contains(tag.Key)) + if (TagsToSkip.Contains(tag.Key)) + { + continue; + } + + if (TagsWithStaticValue.Contains(tag.Key)) { builder .Append($"{tag.Value}"); @@ -291,20 +305,40 @@ public List GetRecordedAttributes() { List generatedActivityTagsForBaselineXmls = new(); + // Get all the recorded operation level activities List collectedOperationActivities = new List(CustomListener.CollectedOperationActivities); + + // Order them by the static values. This is to make sure that the order of the attributes is always same. + List orderedUniqueOperationActivities = collectedOperationActivities + .OrderBy(act => + { + string key = act.Source.Name + act.OperationName; + foreach (string tagName in TagsWithStaticValue) + { + key += act.GetTagItem(tagName); + } + return key; + }).ToList(); + + // Generate XML tags for Baseline xmls foreach (Activity activity in collectedOperationActivities) { generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); } + // Get all the recorded network level activities HashSet collectedNetworkActivities = new HashSet(CustomListener.CollectedNetworkActivities, new NetworkActivityComparer()); + + // Order them by the static values. This is to make sure that the order of the attributes is always same. List orderedUniqueNetworkActivities = collectedNetworkActivities .OrderBy(act => act.Source.Name + act.OperationName + - act.GetTagItem("tcp.status_code") + - act.GetTagItem("tcp.sub_status_code")) + act.GetTagItem("rntbd.status_code") + + act.GetTagItem("rntbd.sub_status_code")) .ToList(); + + // Generate XML tags for Baseline xmls foreach (Activity activity in orderedUniqueNetworkActivities) { generatedActivityTagsForBaselineXmls.Add(this.GenerateTagForBaselineTest(activity)); @@ -369,15 +403,15 @@ public class NetworkActivityComparer : IEqualityComparer { public bool Equals(Activity x, Activity y) { - string xData = x.Source.Name + x.OperationName + x.GetTagItem("tcp.status_code") + x.GetTagItem("tcp.sub_status_code"); - string yData = y.Source.Name + y.OperationName + y.GetTagItem("tcp.status_code") + y.GetTagItem("tcp.sub_status_code"); + string xData = x.Source.Name + x.OperationName + x.GetTagItem("rntbd.status_code") + x.GetTagItem("rntbd.sub_status_code"); + string yData = y.Source.Name + y.OperationName + y.GetTagItem("rntbd.status_code") + y.GetTagItem("rntbd.sub_status_code"); return xData.Equals(yData, StringComparison.OrdinalIgnoreCase); } public int GetHashCode(Activity obj) { - return (obj.Source.Name + obj.OperationName + obj.GetTagItem("tcp.status_code") + obj.GetTagItem("tcp.sub_status_code")).GetHashCode() ; + return (obj.Source.Name + obj.OperationName + obj.GetTagItem("rntbd.status_code") + obj.GetTagItem("rntbd.sub_status_code")).GetHashCode() ; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs index a115a64084..7038ef3194 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomOtelExporter.cs @@ -35,8 +35,8 @@ public override ExportResult Export(in Batch batch) foreach (Activity activity in batch) { - if (string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", StringComparison.OrdinalIgnoreCase) - || string.Equals(activity.Source.Name, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", StringComparison.OrdinalIgnoreCase)) + if (activity.OperationName.StartsWith("Operation.", StringComparison.OrdinalIgnoreCase) + || activity.OperationName.StartsWith("Request.", StringComparison.OrdinalIgnoreCase)) { AssertActivity.IsValidOperationActivity(activity); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml index 3f7faa9f26..1d9e1162bb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml @@ -1,32 +1,32 @@  - - - 1 Path List - ["/path1"] - - - 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05 - B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12 - - - - - 2 Path List - ["/path1","/path2"] - - - 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78 - B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C - - - - - 3 Path List - ["/path1","/path2","/path3"] - - - 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78-00-00-00-00-00-00-00-00-00-00-00-00-9A-B4-68-CD - B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C-88-A6-18-5D-2D-D5-1C-96-D0-47-75-B7-2E-FA-BE-08 - - + + + 1 Path List + ["/path1"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05 + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12 + + + + + 2 Path List + ["/path1","/path2"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78 + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C + + + + + 3 Path List + ["/path1","/path2","/path3"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78-00-00-00-00-00-00-00-00-00-00-00-00-9A-B4-68-CD + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C-88-A6-18-5D-2D-D5-1C-96-D0-47-75-B7-2E-FA-BE-08 + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs index 3300c84d60..c09cf3553c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs @@ -109,11 +109,12 @@ public void ProjectPackageDependenciesTest() { "System.Configuration.ConfigurationManager", new Version(6, 0, 0) }, { "System.Memory", new Version(4, 5, 4) }, { "System.Buffers", new Version(4, 5, 1) }, - { "System.Runtime.CompilerServices.Unsafe", new Version(4, 6, 0) }, + { "System.Runtime.CompilerServices.Unsafe", new Version(6, 0, 0) }, { "System.Threading.Tasks.Extensions", new Version(4, 5, 4) }, { "System.ValueTuple", new Version(4, 5, 0) }, { "Microsoft.Bcl.HashCode", new Version(1, 1, 0) }, { "Azure.Core", new Version(1, 19, 0) }, + { "System.Diagnostics.DiagnosticSource", new Version(6, 0, 1) }, }; Assert.AreEqual(projectDependencies.Count, baselineDependencies.Count); From e827b6bdb01cfff225e15f92432f77c6727b34b5 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Mon, 5 Feb 2024 18:29:41 -0500 Subject: [PATCH 278/337] [Internal] Change Feed Processor: Adds AllVersionsAndDeletes support (#4264) * porting Ian changes to new branch * changing DynamicTests back to its original state. Create a new test class for AllVersionsAndDeletes * including tests for AllVersionsAndDeletes DynamicTests * get master version of DynamicTests * testing changefeedprocessor with allversionsanddeletes * tests for changefeedprocessor with allversionsanddeletes * need to change name here also * adding example documentation to the GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes * removed a line from example that was not necessary * removed ChangeFeedMode from Create signature and using what is in ChangeFeedProcessorOptions * undoing file * default to LatestVersion, not Incremental * change Incremental to LatestVersion on tests * change access modifier and remove PREVIEW gate for internal classes * more removal of unnecessary mode on Create for PartitionController and PartitionSupervisor * change access modifiers and moving methods around due to PREVIEW * adding GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes to EncryptionContainer since it inherits Container * running UpdateContract powershell * override instead of abstract * fixing override, but not sure about how this works * taking guessing on this * lets try this again * once more * once more * internal on new change feed builder * making it public to test * internalizing the GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes * removed DecryptChangeFeedDocumentAsync * undoing this file * removing commented code * moved to ContainerCore.Items.cs * removing and undoing some files created or updated by UpdateContracts.ps1 * removed space and undoing a file --- ...geFeedPartitionKeyResultSetIteratorCore.cs | 11 +- .../ChangeFeedEstimatorIterator.cs | 1 + .../ChangeFeedProcessorBuilder.cs | 11 ++ .../ChangeFeedProcessorOptions.cs | 2 + .../FeedProcessorFactoryCore.cs | 1 + .../ChangeFeedObserverFactoryCore.cs | 45 +++++ .../Resource/Container/ContainerCore.Items.cs | 42 ++++- .../Resource/Container/ContainerInlineCore.cs | 9 + .../Resource/Container/ContainerInternal.cs | 82 ++++++++- ...orBuilderWithAllVersionsAndDeletesTests.cs | 159 ++++++++++++++++++ .../ChangeFeedObserverFactoryCoreTests.cs | 4 +- ...dPartitionKeyResultSetIteratorCoreTests.cs | 4 + 12 files changed, 355 insertions(+), 16 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs index 4c7b8f34f0..738a1d23b7 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCore.cs @@ -20,6 +20,7 @@ internal sealed class ChangeFeedPartitionKeyResultSetIteratorCore : FeedIterator { public static ChangeFeedPartitionKeyResultSetIteratorCore Create( DocumentServiceLease lease, + ChangeFeedMode mode, string continuationToken, int? maxItemCount, ContainerInternal container, @@ -56,6 +57,7 @@ public static ChangeFeedPartitionKeyResultSetIteratorCore Create( return new ChangeFeedPartitionKeyResultSetIteratorCore( container: container, + mode: mode, changeFeedStartFrom: startFrom, options: requestOptions); } @@ -63,15 +65,19 @@ public static ChangeFeedPartitionKeyResultSetIteratorCore Create( private readonly CosmosClientContext clientContext; private readonly ChangeFeedRequestOptions changeFeedOptions; + private readonly ChangeFeedMode mode; + private ChangeFeedStartFrom changeFeedStartFrom; private bool hasMoreResultsInternal; private ChangeFeedPartitionKeyResultSetIteratorCore( ContainerInternal container, + ChangeFeedMode mode, ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedRequestOptions options) { this.container = container ?? throw new ArgumentNullException(nameof(container)); + this.mode = mode; this.changeFeedStartFrom = changeFeedStartFrom ?? throw new ArgumentNullException(nameof(changeFeedStartFrom)); this.clientContext = this.container.ClientContext; this.changeFeedOptions = options; @@ -125,9 +131,8 @@ public override async Task ReadNextAsync(ITrace trace, Cancella this.changeFeedOptions.PageSizeHint.Value.ToString(CultureInfo.InvariantCulture)); } - requestMessage.Headers.Add( - HttpConstants.HttpHeaders.A_IM, - HttpConstants.A_IMHeaderValues.IncrementalFeed); + // Add the necessary mode headers + this.mode.Accept(requestMessage); }, feedRange: this.changeFeedStartFrom.FeedRange, streamPayload: default, diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs index 47469542de..b70585597a 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs @@ -54,6 +54,7 @@ public ChangeFeedEstimatorIterator( changeFeedEstimatorRequestOptions, (DocumentServiceLease lease, string continuationToken, bool startFromBeginning) => ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: lease, + mode: ChangeFeedMode.LatestVersion, continuationToken: continuationToken, maxItemCount: 1, container: monitoredContainer, diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs index 9a23e3e7a0..df3db6f2bf 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs @@ -69,6 +69,17 @@ public ChangeFeedProcessorBuilder WithInstanceName(string instanceName) return this; } + /// + /// Sets the mode for the change freed processor. + /// + /// + /// The instance of to use. + internal ChangeFeedProcessorBuilder WithChangeFeedMode(ChangeFeedMode changeFeedMode) + { + this.changeFeedProcessorOptions.Mode = changeFeedMode; + return this; + } + /// /// Sets a custom configuration to be used by this instance of to control how leases are maintained in a container when using . /// diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs index 3c9223a02e..4f2df5bba0 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedProcessorOptions.cs @@ -84,5 +84,7 @@ public DateTime? StartTime public bool StartFromBeginning { get; set; } public ChangeFeedProcessorHealthMonitorCore HealthMonitor { get; set; } = new ChangeFeedProcessorHealthMonitorCore(); + + public ChangeFeedMode Mode { get; set; } = ChangeFeedMode.LatestVersion; } } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedProcessing/FeedProcessorFactoryCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedProcessing/FeedProcessorFactoryCore.cs index 6d3751cba3..2d45abe24f 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedProcessing/FeedProcessorFactoryCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/FeedProcessing/FeedProcessorFactoryCore.cs @@ -46,6 +46,7 @@ public override FeedProcessor Create(DocumentServiceLease lease, ChangeFeedObser PartitionCheckpointerCore checkpointer = new PartitionCheckpointerCore(this.leaseCheckpointer, lease); ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: lease, + mode: this.changeFeedProcessorOptions.Mode, continuationToken: options.StartContinuation, maxItemCount: options.MaxItemCount, container: this.container, diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs index 9386032f4a..c71d6f06a2 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs @@ -52,6 +52,7 @@ internal sealed class ChangeFeedObserverFactoryCore : ChangeFeedObserverFacto private readonly ChangesHandler legacyOnChanges; private readonly ChangeFeedHandler onChanges; private readonly ChangeFeedHandlerWithManualCheckpoint onChangesWithManualCheckpoint; + private readonly ChangeFeedHandler> onAllVersionsAndDeletesChanges; private readonly CosmosSerializerCore serializerCore; public ChangeFeedObserverFactoryCore( @@ -70,6 +71,14 @@ public ChangeFeedObserverFactoryCore( this.onChanges = onChanges ?? throw new ArgumentNullException(nameof(onChanges)); } + public ChangeFeedObserverFactoryCore( + ChangeFeedHandler> onChanges, + CosmosSerializerCore serializerCore) + : this(serializerCore) + { + this.onAllVersionsAndDeletesChanges = onChanges ?? throw new ArgumentNullException(nameof(onChanges)); + } + public ChangeFeedObserverFactoryCore( ChangeFeedHandlerWithManualCheckpoint onChanges, CosmosSerializerCore serializerCore) @@ -92,6 +101,11 @@ private Task ChangesStreamHandlerAsync( Stream stream, CancellationToken cancellationToken) { + if (this.onAllVersionsAndDeletesChanges != null) + { + return this.AllVersionsAndDeletesStreamHandlerAsync(context, stream, cancellationToken); + } + IReadOnlyCollection changes = this.AsIReadOnlyCollection(stream, context); if (changes.Count == 0) { @@ -111,6 +125,20 @@ private Task ChangesStreamHandlerAsync( return this.onChangesWithManualCheckpoint(context, changes, context.CheckpointAsync, cancellationToken); } + private Task AllVersionsAndDeletesStreamHandlerAsync( + ChangeFeedObserverContextCore context, + Stream stream, + CancellationToken cancellationToken) + { + IReadOnlyCollection> changes = this.AllVersionsAsIReadOnlyCollection(stream, context); + if (changes.Count == 0) + { + return Task.CompletedTask; + } + + return this.onAllVersionsAndDeletesChanges(context, changes, cancellationToken); + } + private IReadOnlyCollection AsIReadOnlyCollection( Stream stream, ChangeFeedObserverContextCore context) @@ -127,5 +155,22 @@ private IReadOnlyCollection AsIReadOnlyCollection( throw new ChangeFeedProcessorUserException(serializationException, context); } } + + private IReadOnlyCollection> AllVersionsAsIReadOnlyCollection( + Stream stream, + ChangeFeedObserverContextCore context) + { + try + { + return CosmosFeedResponseSerializer.FromFeedResponseStream>( + this.serializerCore, + stream); + } + catch (Exception serializationException) + { + // Error using custom serializer to parse stream + throw new ChangeFeedProcessorUserException(serializationException, context); + } + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 2397ab437a..5e96126c71 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -461,7 +461,8 @@ public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder( ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( new ChangeFeedObserverFactoryCore(onChangesDelegate, this.ClientContext.SerializerCore), withManualCheckpointing: false); - return this.GetChangeFeedProcessorBuilderPrivate(processorName, observerFactory); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, ChangeFeedMode.LatestVersion); } public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder( @@ -481,7 +482,8 @@ public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder( ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( new ChangeFeedObserverFactoryCore(onChangesDelegate, this.ClientContext.SerializerCore), withManualCheckpointing: false); - return this.GetChangeFeedProcessorBuilderPrivate(processorName, observerFactory); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, ChangeFeedMode.LatestVersion); } public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint( @@ -501,7 +503,8 @@ public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManu ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( new ChangeFeedObserverFactoryCore(onChangesDelegate, this.ClientContext.SerializerCore), withManualCheckpointing: true); - return this.GetChangeFeedProcessorBuilderPrivate(processorName, observerFactory); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, ChangeFeedMode.LatestVersion); } public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder( @@ -521,7 +524,8 @@ public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder( ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( new ChangeFeedObserverFactoryCore(onChangesDelegate), withManualCheckpointing: false); - return this.GetChangeFeedProcessorBuilderPrivate(processorName, observerFactory); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, ChangeFeedMode.LatestVersion); } public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint( @@ -541,7 +545,9 @@ public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManu ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( new ChangeFeedObserverFactoryCore(onChangesDelegate), withManualCheckpointing: true); - return this.GetChangeFeedProcessorBuilderPrivate(processorName, observerFactory); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, + ChangeFeedMode.LatestVersion); } public override ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder( @@ -1214,16 +1220,38 @@ public Task PatchItemStreamAsync( cancellationToken: cancellationToken); } + public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate) + { + if (processorName == null) + { + throw new ArgumentNullException(nameof(processorName)); + } + + if (onChangesDelegate == null) + { + throw new ArgumentNullException(nameof(onChangesDelegate)); + } + + ChangeFeedObserverFactory observerFactory = new CheckpointerObserverFactory( + new ChangeFeedObserverFactoryCore(onChangesDelegate, this.ClientContext.SerializerCore), + withManualCheckpointing: false); + return this.GetChangeFeedProcessorBuilderPrivate(processorName, + observerFactory, ChangeFeedMode.AllVersionsAndDeletes); + } + private ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderPrivate( string processorName, - ChangeFeedObserverFactory observerFactory) + ChangeFeedObserverFactory observerFactory, + ChangeFeedMode mode) { ChangeFeedProcessorCore changeFeedProcessor = new ChangeFeedProcessorCore(observerFactory); return new ChangeFeedProcessorBuilder( processorName: processorName, container: this, changeFeedProcessor: changeFeedProcessor, - applyBuilderConfiguration: changeFeedProcessor.ApplyBuildConfiguration); + applyBuilderConfiguration: changeFeedProcessor.ApplyBuildConfiguration).WithChangeFeedMode(mode); } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs index 8e6e4495aa..ede4aebc22 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs @@ -661,5 +661,14 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( task: (trace) => base.DeleteAllItemsByPartitionKeyStreamAsync(partitionKey, trace, requestOptions, cancellationToken), openTelemetry: (response) => new OpenTelemetryResponse(response)); } + + public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate) + { + return base.GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + processorName, + onChangesDelegate); + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index dc532f6977..27b007ed8e 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -140,16 +140,90 @@ public abstract Task PatchItemStreamAsync( #if !PREVIEW public abstract Task DeleteAllItemsByPartitionKeyStreamAsync( - Cosmos.PartitionKey partitionKey, - RequestOptions requestOptions = null, - CancellationToken cancellationToken = default); + Cosmos.PartitionKey partitionKey, + RequestOptions requestOptions = null, + CancellationToken cancellationToken = default); public abstract Task> GetPartitionKeyRangesAsync( FeedRange feedRange, CancellationToken cancellationToken = default); - #endif + /// + /// Initializes a for change feed processing with all versions and deletes. + /// + /// Document type + /// A name that identifies the Processor and the particular work it will do. + /// Delegate to receive all changes and deletes + /// + /// + /// > documents, CancellationToken token) => + /// { + /// Console.WriteLine($"number of documents processed: {documents.Count}"); + /// + /// string id = default; + /// string pk = default; + /// string description = default; + /// + /// foreach (ChangeFeedItemChange changeFeedItem in documents) + /// { + /// if (changeFeedItem.Metadata.OperationType != ChangeFeedOperationType.Delete) + /// { + /// id = changeFeedItem.Current.id.ToString(); + /// pk = changeFeedItem.Current.pk.ToString(); + /// description = changeFeedItem.Current.description.ToString(); + /// } + /// else + /// { + /// id = changeFeedItem.Previous.id.ToString(); + /// pk = changeFeedItem.Previous.pk.ToString(); + /// description = changeFeedItem.Previous.description.ToString(); + /// } + /// + /// ChangeFeedOperationType operationType = changeFeedItem.Metadata.OperationType; + /// long previousLsn = changeFeedItem.Metadata.PreviousLsn; + /// DateTime conflictResolutionTimestamp = changeFeedItem.Metadata.ConflictResolutionTimestamp; + /// long lsn = changeFeedItem.Metadata.Lsn; + /// bool isTimeToLiveExpired = changeFeedItem.Metadata.IsTimeToLiveExpired; + /// } + /// + /// return Task.CompletedTask; + /// }) + /// .WithInstanceName(Guid.NewGuid().ToString()) + /// .WithLeaseContainer(leaseContainer) + /// .WithErrorNotification((leaseToken, error) => + /// { + /// Console.WriteLine(error.ToString()); + /// + /// return Task.CompletedTask; + /// }) + /// .Build(); + /// + /// await changeFeedProcessor.StartAsync(); + /// await Task.Delay(1000); + /// await this.Container.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); + /// await this.Container.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); + /// await this.Container.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); + /// + /// allProcessedDocumentsEvent.WaitOne(10 * 1000); + /// + /// await changeFeedProcessor.StopAsync(); + /// ]]> + /// + /// + /// An instance of + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate); + public abstract class TryExecuteQueryResult { } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs new file mode 100644 index 0000000000..9292e4d1e7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs @@ -0,0 +1,159 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + [TestCategory("ChangeFeedProcessor with AllVersionsAndDeletes")] + public class GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests : BaseChangeFeedClientHelper + { + private ContainerInternal Container; + + [TestInitialize] + public async Task TestInitialize() + { + await base.ChangeFeedTestInit(); + + string PartitionKey = "/pk"; + ContainerProperties properties = new ContainerProperties(id: Guid.NewGuid().ToString(), + partitionKeyPath: PartitionKey); + properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5); + + ContainerResponse response = await this.database.CreateContainerAsync(properties, + throughput: 10000, + cancellationToken: this.cancellationToken); + this.Container = (ContainerInternal)response; + } + + [TestCleanup] + public async Task Cleanup() + { + await base.TestCleanup(); + } + + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: When a document is created, then updated, and finally deleted, there should be 3 changes that will appear for that " + + "document when using ChangeFeedProcessor with AllVersionsAndDeletes.")] + public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() + { + ManualResetEvent allDocsProcessed = new ManualResetEvent(false); + Exception exception = default; + + ChangeFeedProcessor processor = this.Container + .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> docs, CancellationToken token) => + { + string id = default; + string pk = default; + string description = default; + + foreach (ChangeFeedItemChange change in docs) + { + if (change.Metadata.OperationType != ChangeFeedOperationType.Delete) + { + id = change.Current.id.ToString(); + pk = change.Current.pk.ToString(); + description = change.Current.description.ToString(); + } + else + { + id = change.Previous.id.ToString(); + pk = change.Previous.pk.ToString(); + description = change.Previous.description.ToString(); + } + + ChangeFeedOperationType operationType = change.Metadata.OperationType; + long previousLsn = change.Metadata.PreviousLsn; + DateTime m = change.Metadata.ConflictResolutionTimestamp; + long lsn = change.Metadata.Lsn; + bool isTimeToLiveExpired = change.Metadata.IsTimeToLiveExpired; + } + + Assert.IsNotNull(context.LeaseToken); + Assert.IsNotNull(context.Diagnostics); + Assert.IsNotNull(context.Headers); + Assert.IsNotNull(context.Headers.Session); + Assert.IsTrue(context.Headers.RequestCharge > 0); + Assert.IsTrue(context.Diagnostics.ToString().Contains("Change Feed Processor Read Next Async")); + Assert.AreEqual(expected: 3, actual: docs.Count); + + ChangeFeedItemChange createChange = docs.ElementAt(0); + Assert.IsNotNull(createChange.Current); + Assert.AreEqual(expected: "1", actual: createChange.Current.id.ToString()); + Assert.AreEqual(expected: "1", actual: createChange.Current.pk.ToString()); + Assert.AreEqual(expected: "original test", actual: createChange.Current.description.ToString()); + Assert.AreEqual(expected: createChange.Metadata.OperationType, actual: ChangeFeedOperationType.Create); + Assert.AreEqual(expected: createChange.Metadata.PreviousLsn, actual: 0); + Assert.IsNull(createChange.Previous); + + ChangeFeedItemChange replaceChange = docs.ElementAt(1); + Assert.IsNotNull(replaceChange.Current); + Assert.AreEqual(expected: "1", actual: replaceChange.Current.id.ToString()); + Assert.AreEqual(expected: "1", actual: replaceChange.Current.pk.ToString()); + Assert.AreEqual(expected: "test after replace", actual: replaceChange.Current.description.ToString()); + Assert.AreEqual(expected: replaceChange.Metadata.OperationType, actual: ChangeFeedOperationType.Replace); + Assert.AreEqual(expected: createChange.Metadata.Lsn, actual: replaceChange.Metadata.PreviousLsn); + Assert.IsNull(replaceChange.Previous); + + ChangeFeedItemChange deleteChange = docs.ElementAt(2); + Assert.IsNull(deleteChange.Current.id); + Assert.AreEqual(expected: deleteChange.Metadata.OperationType, actual: ChangeFeedOperationType.Delete); + Assert.AreEqual(expected: replaceChange.Metadata.Lsn, actual: deleteChange.Metadata.PreviousLsn); + Assert.IsNotNull(deleteChange.Previous); + Assert.AreEqual(expected: "1", actual: deleteChange.Previous.id.ToString()); + Assert.AreEqual(expected: "1", actual: deleteChange.Previous.pk.ToString()); + Assert.AreEqual(expected: "test after replace", actual: deleteChange.Previous.description.ToString()); + + Assert.IsTrue(condition: createChange.Metadata.ConflictResolutionTimestamp < replaceChange.Metadata.ConflictResolutionTimestamp, message: "The create operation must happen before the replace operation."); + Assert.IsTrue(condition: replaceChange.Metadata.ConflictResolutionTimestamp < deleteChange.Metadata.ConflictResolutionTimestamp, message: "The replace operation must happen before the delete operation."); + Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The create operation must happen before the replace operation."); + Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The replace operation must happen before the delete operation."); + + Console.WriteLine("Assertions completed."); + + return Task.CompletedTask; + }) + .WithInstanceName(Guid.NewGuid().ToString()) + .WithLeaseContainer(this.LeaseContainer) + .WithErrorNotification((leaseToken, error) => + { + exception = error.InnerException; + Console.WriteLine(error.ToString()); + + return Task.CompletedTask; + }) + .Build(); + + // Start the processor, insert 1 document to generate a checkpoint, modify it, and then delete it. + // 1 second delay between operations to get different timestamps. + + await processor.StartAsync(); + await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); + + await this.Container.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); + await Task.Delay(1000); + + await this.Container.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); + await Task.Delay(1000); + + await this.Container.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); + + bool isStartOk = allDocsProcessed.WaitOne(10 * BaseChangeFeedClientHelper.ChangeFeedSetupTime); + + await processor.StopAsync(); + + if (exception != default) + { + Assert.Fail(exception.ToString()); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedObserverFactoryCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedObserverFactoryCoreTests.cs index bc3fa55489..1464784909 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedObserverFactoryCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedObserverFactoryCoreTests.cs @@ -35,7 +35,7 @@ Task changesHandler(IReadOnlyCollection docs, CancellationToken token) return Task.CompletedTask; } - ChangeFeedObserverFactoryCore changeFeedObserverFactoryCore = new ChangeFeedObserverFactoryCore(changesHandler, this.cosmosSerializerCore); + ChangeFeedObserverFactoryCore changeFeedObserverFactoryCore = new ChangeFeedObserverFactoryCore((Cosmos.Container.ChangesHandler)changesHandler, this.cosmosSerializerCore); ChangeFeedObserver changeFeedObserver = changeFeedObserverFactoryCore.CreateObserver(); @@ -60,7 +60,7 @@ Task changesHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changeFeedObserverFactoryCore = new ChangeFeedObserverFactoryCore(changesHandler, this.cosmosSerializerCore); + ChangeFeedObserverFactoryCore changeFeedObserverFactoryCore = new ChangeFeedObserverFactoryCore((Container.ChangeFeedHandler)changesHandler, this.cosmosSerializerCore); ChangeFeedObserver changeFeedObserver = changeFeedObserverFactoryCore.CreateObserver(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs index ebbb837943..08baba746b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedPartitionKeyResultSetIteratorCoreTests.cs @@ -78,6 +78,7 @@ public async Task EtagPassesContinuation() ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, + mode: ChangeFeedMode.LatestVersion, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, @@ -159,6 +160,7 @@ public async Task NextReadHasUpdatedContinuation() ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, + mode: ChangeFeedMode.AllVersionsAndDeletes, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, @@ -226,6 +228,7 @@ public async Task ShouldSetFeedRangePartitionKeyRange() ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, + mode: ChangeFeedMode.LatestVersion, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, @@ -310,6 +313,7 @@ public async Task ShouldUseFeedRangeEpk() ChangeFeedPartitionKeyResultSetIteratorCore iterator = ChangeFeedPartitionKeyResultSetIteratorCore.Create( lease: documentServiceLeaseCore, + mode: ChangeFeedMode.LatestVersion, continuationToken: null, maxItemCount: itemCount, container: containerMock.Object, From d32f72de65f0f88b440be0c689a55a420f6b02df Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Mon, 5 Feb 2024 20:51:33 -0800 Subject: [PATCH 279/337] 3.38.1: Adds new SDK versions and contract files (#4305) * Code changes to bump up release versions. * Updated changelog. --------- Co-authored-by: REDMOND\adityasa --- Directory.Build.props | 4 ++-- changelog.md | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 64957f5af3..89cc974a3e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.38.0 + 3.38.1 3.39.0 - preview.0 + preview.1 3.32.1 2.0.4 2.1.0 diff --git a/changelog.md b/changelog.md index 09228b9cfe..d87d89a505 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,21 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.39.0-preview.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.1) - 2024-02-02 +### [3.38.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.38.1) - 2024-02-02 + +#### Fixed +- [4294](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4294) DisableServerCertificateValidation: Fixes Default HttpClient to honor DisableServerCertificateValidation (#4294) + +#### Added +- [4299](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4299) Query: Adds environment variable for overriding EnableOptimisticDirectExecution default (#4299) + > Note: This change provides another way to manage the upgrade to `3.38`. It provides an option to avoid potential disruption due to the breaking change (see the note below) if only config deployment is preferred, instead of any explicit code modification. + > With this change, users can set the environment variable AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED to false in their production environments while upgrading from previous minor version (`3.37` or below) to `3.38.1` (or above). + > This will signal the SDK to disable Optimistic Direct Execution by default. + > Once the environment is fully upgraded to the target version, the environment variable can be removed (or set to true) to enable ODE. + > It is recommended that the environment variable is used only to manage the upgrade and removed once the deployment is complete. + > Please note that environment variable acts as the override only for choosing the default value. If the code explicitly modifies the setting, that value will be honored during actual operations. + ### [3.39.0-preview.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.0) - 2024-01-31 #### Added From 03a617eed025b512d03aebc25199c47b924e8ef4 Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 6 Feb 2024 15:53:16 -0800 Subject: [PATCH 280/337] Bypass distribution plan parsing. (#4293) --- .../Query/v3Query/CosmosQueryClientCore.cs | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index a805786ca6..e1c23c156b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -339,18 +339,19 @@ private static TryCatch GetCosmosElementResponse( DistributionPlanSpec distributionPlanSpec = null; - if (distributionPlan != null) - { - bool backendPlan = distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan); - bool clientPlan = distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan); - - Debug.Assert(clientPlan == backendPlan, "Response Body Contract was violated. Out of the backend and client plans, only one is present in the distribution plan."); - - if (backendPlan && clientPlan) - { - distributionPlanSpec = new DistributionPlanSpec(backendDistributionPlan.ToString(), clientDistributionPlan.ToString()); - } - } + // ISSUE-TODO-adityasa-2024/1/31 - Uncomment this when distributionPlanSpec is hooked with rest of the code so that it can be tested. + // if (distributionPlan != null) + // { + // bool backendPlan = distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan); + // bool clientPlan = distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan); + + // Debug.Assert(clientPlan == backendPlan, "Response Body Contract was violated. Out of the backend and client plans, only one is present in the distribution plan."); + + // if (backendPlan && clientPlan) + // { + // distributionPlanSpec = new DistributionPlanSpec(backendDistributionPlan.ToString(), clientDistributionPlan.ToString()); + // } + // } QueryState queryState; if (cosmosResponseMessage.Headers.ContinuationToken != null) From f6609eeccba51de63a41557ae5a93d16df80a1c2 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Tue, 6 Feb 2024 16:55:21 -0800 Subject: [PATCH 281/337] [Internal] Query: Fixes Aggregate Pipelines resetting headers (#4303) * Init commit * address code review * address code review part 2 * fix formating --------- Co-authored-by: Minh Le --- .../AggregateQueryPipelineStage.Client.cs | 13 +- ...ndexUtilizationClientSideExistenceTest.xml | 290 ++++++++++++++++++ .../IndexMetricsParserBaselineTest.cs | 270 +++++++++++++++- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 4 + 4 files changed, 569 insertions(+), 8 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationClientSideExistenceTest.xml diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs index ddaea9aaa5..c1fff1ac59 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate.Aggregators; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; internal abstract partial class AggregateQueryPipelineStage : QueryPipelineStageBase { @@ -88,6 +89,8 @@ public override async ValueTask MoveNextAsync(ITrace trace) double requestCharge = 0; long responseLengthBytes = 0; + IReadOnlyDictionary cumulativeAdditionalHeaders = default; + while (await this.inputStage.MoveNextAsync(trace)) { TryCatch tryGetPageFromSource = this.inputStage.Current; @@ -102,6 +105,14 @@ public override async ValueTask MoveNextAsync(ITrace trace) requestCharge += sourcePage.RequestCharge; responseLengthBytes += sourcePage.ResponseLengthInBytes; + // Note-2024-02-02: + // Here the IndexMetrics headers are non-accumulative, so we are copying that header from the source page. + // Other headers might need similar traeatment, and it's up to the area owner to implement that here. + if (sourcePage.AdditionalHeaders.ContainsKey(HttpConstants.HttpHeaders.IndexUtilization)) + { + cumulativeAdditionalHeaders = new Dictionary() {{ HttpConstants.HttpHeaders.IndexUtilization, sourcePage.AdditionalHeaders[HttpConstants.HttpHeaders.IndexUtilization] }}; + } + foreach (CosmosElement element in sourcePage.Documents) { this.cancellationToken.ThrowIfCancellationRequested(); @@ -128,7 +139,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, - additionalHeaders: default, + additionalHeaders: cumulativeAdditionalHeaders, state: default); this.Current = TryCatch.FromResult(queryPage); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationClientSideExistenceTest.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationClientSideExistenceTest.xml new file mode 100644 index 0000000000..4f12c7312b --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/IndexMetricsParserBaselineTest.IndexUtilizationClientSideExistenceTest.xml @@ -0,0 +1,290 @@ + + + + + + + + + + + + + + + + + + + + + + + "Abc"]]> + + + + + + + + + "1" and c.name > "Abc"]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc"]]> + + + + + + + + + "1" and c.name > "Abc"]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc"]]> + + + + + + + + + "1" and c.name > "Abc"]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc" ORDER BY c.id ASC]]> + + + + + + + + + "1" and c.name > "Abc" ORDER BY c.id ASC]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc" GROUP BY c.id]]> + + + + + + + + + "1" and c.name > "Abc" GROUP BY c.id]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc" GROUP BY c.id, c.name]]> + + + + + + + + + "1" and c.name > "Abc" GROUP BY c.id, c.name]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc"]]> + + + + + + + + + "1" and c.name > "Abc"]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + "Abc" GROUP BY c.id, c.name]]> + + + + + + + + + "1" and c.name > "Abc" GROUP BY c.id, c.name]]> + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index a78f8bf7a7..43d6fad184 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -15,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests using Microsoft.Azure.Documents; using Antlr4.Runtime.Sharpen; using System.Collections.Generic; + using OpenTelemetry.Trace; // End-to-end testing for IndexMetrics handling and parsing. [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] @@ -169,21 +170,276 @@ public void IndexUtilizationHeaderLengthTest() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void IndexUtilizationClientSideExistenceTest() + { + List inputs = new List + { + new IndexMetricsParserTestInput + ( + description: "Simple 1", + query: "SELECT * FROM c WHERE c.id = \"1\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Simple 2", + query: "SELECT * FROM c WHERE c.id = \"1\" and c.name = \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Simple 3", + query: "SELECT * FROM c WHERE c.id = \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Simple 4", + query: "SELECT * FROM c WHERE c.id > \"1\" and c.name > \"Abc\"" + ), + + // Aggregate + new IndexMetricsParserTestInput + ( + description: "Aggregate 1", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate 2", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate 3", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate 4", + query: "SELECT COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate Value 1", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate Value 2", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate Value 3", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "Aggregate Value 4", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\"" + ), + + // Order By + new IndexMetricsParserTestInput + ( + description: "OrderBy 1", + query: "SELECT * FROM c WHERE c.id = \"1\" ORDER BY c.id ASC" + ), + + new IndexMetricsParserTestInput + ( + description: "OrderBy 2", + query: "SELECT * FROM c WHERE c.id = \"1\" and c.name = \"Abc\" ORDER BY c.id ASC" + ), + + new IndexMetricsParserTestInput + ( + description: "OrderBy 3", + query: "SELECT * FROM c WHERE c.id = \"1\" and c.name > \"Abc\" ORDER BY c.id ASC" + ), + + new IndexMetricsParserTestInput + ( + description: "OrderBy 4", + query: "SELECT * FROM c WHERE c.id > \"1\" and c.name > \"Abc\" ORDER BY c.id ASC" + ), + + // Group By + new IndexMetricsParserTestInput + ( + description: "GroupBy 1", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" GROUP BY c.id" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 2", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\" GROUP BY c.id" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 3", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\" GROUP BY c.id" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 4", + query: "SELECT COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\" GROUP BY c.id" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 5", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 6", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 7", + query: "SELECT COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy 8", + query: "SELECT COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 1", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\"" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 2", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 3", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 4", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\"" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 5", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 6", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name = \"Abc\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 7", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id = \"1\" and c.name > \"Abc\" GROUP BY c.id, c.name" + ), + + new IndexMetricsParserTestInput + ( + description: "GroupBy Value 8", + query: "SELECT VALUE COUNT(1) FROM c WHERE c.id > \"1\" and c.name > \"Abc\" GROUP BY c.id, c.name" + ) + }; + + this.ExecuteTestSuite(inputs); + } + public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestInput input) - { - QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true }; + { + string indexMetricsNonODE = default; + // Execute without ODE + QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = false }; FeedIterator itemQuery = testContainer.GetItemQueryIterator( input.Query, requestOptions: requestOptions); // Index Metrics is returned fully on the first page so no need to worry about result set - FeedResponse page = itemQuery.ReadNextAsync().Result; - Assert.IsTrue(page.Headers.AllKeys().Length > 1); - Assert.IsNotNull(page.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); - Assert.IsNotNull(page.IndexMetrics, "Expected index metrics response for query"); + int roundTripCount = 1; + while (itemQuery.HasMoreResults) + { + FeedResponse page = itemQuery.ReadNextAsync().Result; + Assert.IsTrue(page.Headers.AllKeys().Length > 1); + + if (roundTripCount > 1) + { + if (page.IndexMetrics != null) Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount); + } + else + { + Assert.IsNotNull(page.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); + Assert.IsNotNull(page.IndexMetrics, "Expected index metrics response for query"); + + indexMetricsNonODE = page.IndexMetrics; + } + + roundTripCount++; + } + + // Execute with ODE + string indexMetricsODE = default; + QueryRequestOptions requestOptions2 = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = true }; + + FeedIterator itemQuery2 = testContainer.GetItemQueryIterator( + input.Query, + requestOptions: requestOptions2); + + // Index Metrics is returned fully on the first page so no need to worry about result set + int roundTripCount2 = 1; + while (itemQuery2.HasMoreResults) + { + FeedResponse page2 = itemQuery2.ReadNextAsync().Result; + Assert.IsTrue(page2.Headers.AllKeys().Length > 1); + + if (roundTripCount2 > 1) + { + if (page2.IndexMetrics != null) Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount2); + } + else + { + Assert.IsNotNull(page2.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); + Assert.IsNotNull(page2.IndexMetrics, "Expected index metrics response for query"); + + indexMetricsODE = page2.IndexMetrics; + } + + roundTripCount2++; + } + + // Make sure ODE and non-ODE is consistent + Assert.AreEqual(indexMetricsNonODE, indexMetricsODE); - return new IndexMetricsParserTestOutput(page.IndexMetrics); + return new IndexMetricsParserTestOutput(indexMetricsNonODE); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 61e7745427..0cb2585dc5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -34,6 +34,7 @@ + @@ -102,6 +103,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From a9599bd64854d406e6de1a34b35db5ccdf9f145d Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 8 Feb 2024 11:58:07 -0800 Subject: [PATCH 282/337] FaultInjection: Adds Fault Injection Library (#4281) * initial commit * add files * restructure + some cleanup * fixed await for chaos interceptor creation * added default operation/conntection type values * threshold to thresholdpercentage * more threshold changes * changed application to rule application for clarity * changed method names in application context * spelling fix * addressed comments * tests/csproj fixes * requested changes * requested changes * added comments arrount duration * added comments arrount duration * application context changes to avoid bounded staleness problem * requested changes and test fixes * removed unused code * update contracts * Revert "update contracts" This reverts commit 8df331713ff934c2c8964e901a72b0fd1092afad. --- .../Tools/FaultInjection/src/AssemblyInfo.cs | 9 + .../FaultInjection/src/FaultInjection.csproj | 39 + .../FaultInjection/src/FaultInjection.sln | 37 + .../src/FaultInjectionCondition.cs | 91 ++ .../src/FaultInjectionConditionBuilder.cs | 87 ++ .../FaultInjectionConnectionErrorResult.cs | 73 + ...ltInjectionConnectionErrorResultBuilder.cs | 74 + .../src/FaultInjectionConnectionErrorType.cs | 21 + .../src/FaultInjectionConnectionType.cs | 21 + .../src/FaultInjectionEndpoint.cs | 93 ++ .../src/FaultInjectionEndpointBuilder.cs | 68 + .../src/FaultInjectionOperationType.cs | 56 + .../src/FaultInjectionResultBuilder.cs | 33 + .../FaultInjection/src/FaultInjectionRule.cs | 187 +++ .../src/FaultInjectionRuleBuilder.cs | 109 ++ .../src/FaultInjectionServerErrorResult.cs | 84 ++ .../FaultInjectionServerErrorResultBuilder.cs | 88 ++ .../src/FaultInjectionServerErrorType.cs | 67 + .../Tools/FaultInjection/src/FaultInjector.cs | 52 + .../src/implementataion/ChaosInterceptor.cs | 227 +++ .../FaultInjectionApplicationContext.cs | 86 ++ .../FaultInjectionConditionInternal.cs | 236 ++++ .../FaultInjectionConnectionErrorRule.cs | 92 ++ .../FaultInjectionDynamicChannelStore.cs | 36 + .../FaultInjectionRuleProcessor.cs | 381 +++++ .../FaultInjectionRuleStore.cs | 160 +++ ...FaultInjectionServerErrorResultInternal.cs | 243 ++++ .../FaultInjectionServerErrorRule.cs | 205 +++ .../implementataion/IFaultInjectionResult.cs | 12 + .../IFaultInjectionRuleInternal.cs | 60 + .../RntbdConnectionErrorInjector.cs | 233 ++++ .../tests/FaultInjectionDirectModeTests.cs | 1220 +++++++++++++++++ .../tests/FaultInjectionTests.csproj | 45 + .../tests/FaultInjectionTests.sln | 25 + .../tests/FaultInjectionUnitTests.cs | 77 ++ .../Tools/FaultInjection/tests/Usings.cs | 3 + .../FaultInjection/tests/Utils/TestCommon.cs | 68 + Microsoft.Azure.Cosmos/src/DocumentClient.cs | 19 +- .../IChaosInterceptorFactory.cs | 7 +- 39 files changed, 4714 insertions(+), 10 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/AssemblyInfo.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.sln create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionCondition.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConditionBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResult.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResultBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorType.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionType.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpoint.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpointBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionResultBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRule.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRuleBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResult.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjector.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionApplicationContext.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConditionInternal.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConnectionErrorRule.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionDynamicChannelStore.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorRule.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionResult.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionRuleInternal.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/RntbdConnectionErrorInjector.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.csproj create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.sln create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionUnitTests.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Usings.cs create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/AssemblyInfo.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/AssemblyInfo.cs new file mode 100644 index 0000000000..d44b531839 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/AssemblyInfo.cs @@ -0,0 +1,9 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2" + AssemblyKeys.MoqPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection.Tests" + AssemblyKeys.ProductPublicKey)] +[assembly: InternalsVisibleTo("Microsoft.Azure.Cosmos.FaultInjection.Tests" + AssemblyKeys.TestPublicKey)] diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.csproj new file mode 100644 index 0000000000..9d40a016f8 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.csproj @@ -0,0 +1,39 @@ + + + + Microsoft Corporation + Microsoft(R) Azure Cosmos + This client library enables client applications to inject faults into Azure Cosmos DB applications. + © Microsoft Corporation. All rights reserved. + en-US + $([System.DateTime]::Now.ToString(yyyyMMdd)) + Exe + net6 + library + Microsoft.Azure.Cosmos.FaultInjection + Microsoft.Azure.Cosmos.FaultInjection + enable + enable + True + + + + + + + + + + + + + + + + + + true + true + ..\..\..\..\testkey.snk + + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.sln b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.sln new file mode 100644 index 0000000000..24e5c5196e --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjection.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33530.505 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaultInjection", "FaultInjection.csproj", "{35F312B5-93FF-45E5-BAD9-513697476B7C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaultInjectionTests", "..\tests\FaultInjectionTests.csproj", "{C14C69A7-C282-4526-BCD1-CEADA4ECED8F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Cosmos", "..\..\..\..\Microsoft.Azure.Cosmos\src\Microsoft.Azure.Cosmos.csproj", "{01A51453-D95E-4ED6-88AD-76A958CF516B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {35F312B5-93FF-45E5-BAD9-513697476B7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35F312B5-93FF-45E5-BAD9-513697476B7C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35F312B5-93FF-45E5-BAD9-513697476B7C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35F312B5-93FF-45E5-BAD9-513697476B7C}.Release|Any CPU.Build.0 = Release|Any CPU + {C14C69A7-C282-4526-BCD1-CEADA4ECED8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C14C69A7-C282-4526-BCD1-CEADA4ECED8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C14C69A7-C282-4526-BCD1-CEADA4ECED8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C14C69A7-C282-4526-BCD1-CEADA4ECED8F}.Release|Any CPU.Build.0 = Release|Any CPU + {01A51453-D95E-4ED6-88AD-76A958CF516B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {01A51453-D95E-4ED6-88AD-76A958CF516B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {01A51453-D95E-4ED6-88AD-76A958CF516B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {01A51453-D95E-4ED6-88AD-76A958CF516B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {9B003F88-147A-4B56-9BB3-EBCF53BA8D2A} + EndGlobalSection +EndGlobal diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionCondition.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionCondition.cs new file mode 100644 index 0000000000..fe73b8266e --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionCondition.cs @@ -0,0 +1,91 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// Fault Injection Condition + /// + public sealed class FaultInjectionCondition + { + private readonly FaultInjectionOperationType operationType; + private readonly FaultInjectionConnectionType connectionType; + private readonly string region; + private readonly FaultInjectionEndpoint endpoint; + + /// + /// Creates a . + /// + /// Specifies which operation type rule will target. + /// Specifies which connection type rule will target. + /// Specifies wich region the rule will target. + /// Specifies which endpoint the rule will tareget. + public FaultInjectionCondition( + FaultInjectionOperationType? operationType = null, + FaultInjectionConnectionType? connectionType = null, + string? region = null, + FaultInjectionEndpoint? endpoint = null) + { + + RegionNameMapper mapper = new RegionNameMapper(); + this.region = string.IsNullOrEmpty(region) ? string.Empty : mapper.GetCosmosDBRegionName(region); + + this.operationType = operationType ?? FaultInjectionOperationType.All; + this.connectionType = connectionType ?? FaultInjectionConnectionType.All; + this.endpoint = endpoint ?? FaultInjectionEndpoint.Empty; + } + + /// + /// The operation type the rule will target. + /// + /// the . + public FaultInjectionOperationType GetOperationType() + { + return this.operationType; + } + + /// + /// The connection type the rule will target. + /// + /// the . + public FaultInjectionConnectionType GetConnectionType() + { + return this.connectionType; + } + + /// + /// The region the rule will target. + /// Will return the empty string if the rule is not targeting a specific region. + /// + /// the region represented as a string. + public string GetRegion() + { + return this.region; + } + + /// + /// The endpoint the rule will target. + /// + /// the . + public FaultInjectionEndpoint GetEndpoint() + { + return this.endpoint; + } + + /// + /// To String method + /// + /// A string represeting the . + public override string ToString() + { + return String.Format( + "FaultInjectionCondition{{ OperationType: {0}, ConnectionType: {1}, Region: {2}, Endpoint: {3}", + this.operationType, + this.connectionType, + this.region, + this.endpoint.ToString()); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConditionBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConditionBuilder.cs new file mode 100644 index 0000000000..893bfce536 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConditionBuilder.cs @@ -0,0 +1,87 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using Microsoft.Azure.Cosmos; + + /// + /// This class is used to build a + /// + public sealed class FaultInjectionConditionBuilder + { + private FaultInjectionOperationType operationType = FaultInjectionOperationType.All; + private FaultInjectionConnectionType connectionType = FaultInjectionConnectionType.All; + private string region = string.Empty; + private FaultInjectionEndpoint endpoint = FaultInjectionEndpoint.Empty; + + /// + /// Optional. Specifies which operation type rule will target. Once set, the rule will only target requests with this operation type. + /// By default, the rule will target all operation types. + /// + /// + /// the . + public FaultInjectionConditionBuilder WithOperationType(FaultInjectionOperationType operationType) + { + this.operationType = operationType; + return this; + } + + /// + /// Optional. Specifies which connection type rule will target. Once set, the rule will only target requests with this connection type. + /// By default, the rule will target all connection types. + /// + /// + /// the . + public FaultInjectionConditionBuilder WithConnectionType(FaultInjectionConnectionType connectionType) + { + this.connectionType = connectionType; + return this; + } + + /// + /// Optional. Specifies which region the rule will target. Once set, the rule will only target requests targeting that region. + /// By default, the rule will target all regions. + /// + /// + /// the + public FaultInjectionConditionBuilder WithRegion(string region) + { + RegionNameMapper mapper = new RegionNameMapper(); + string regionName = mapper.GetCosmosDBRegionName(region); + this.region = string.IsNullOrEmpty(regionName) + ? throw new ArgumentNullException(nameof(region), "Argument 'region' cannot be null.") + : regionName; + + return this; + } + + /// + /// Optional. Specifies which endpoint the rule will target. Once set, the rule will only target requests targeting that endpoint. + /// Only applicable to direct mode since only direct mode specifies physical endpoints. + /// By default, the rule will target all endpoints + /// + /// + /// the + public FaultInjectionConditionBuilder WithEndpoint(FaultInjectionEndpoint endpoint) + { + this.endpoint = endpoint; + return this; + } + + /// + /// Creates the . + /// + /// the . + public FaultInjectionCondition Build() + { + return new FaultInjectionCondition( + this.operationType, + this.connectionType, + this.region, + this.endpoint); + } + + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResult.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResult.cs new file mode 100644 index 0000000000..cf92a37e09 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResult.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// Fault Injection Connection Error Result. + /// + public sealed class FaultInjectionConnectionErrorResult : IFaultInjectionResult + { + private readonly FaultInjectionConnectionErrorType connectionErrorType; + private readonly TimeSpan interval; + private readonly double thresholdPercentage; + + /// + /// Creates a new FaultInjectionConnectionErrorResult + /// + /// Specifies the connection error type. + /// Timespan representing the ammount of time the SDK will wait before returning the error. + /// Percentage of the established connections that will be impaceted. + public FaultInjectionConnectionErrorResult( + FaultInjectionConnectionErrorType connectionErrorType, + TimeSpan interval, + double thresholdPercentage) + { + this.connectionErrorType = connectionErrorType; + this.interval = interval; + this.thresholdPercentage = thresholdPercentage; + } + + /// + /// Gets the Connection Error Type. + /// + /// the . + public FaultInjectionConnectionErrorType GetConnectionErrorType() + { + return this.connectionErrorType; + } + + /// + /// The ammount of time the SDK will wait before returning the error. + /// + /// the Timespan + public TimeSpan GetTimespan() + { + return this.interval; + } + + /// + /// Returns the percentage of the established connections that will be impacted. By default, the threshold is 100% or 1.0. + /// + /// the threshold represented as a double. + public double GetThresholdPercentage() + { + return this.thresholdPercentage; + } + + /// + /// To String method + /// + /// A string represeting the . + public override string ToString() + { + return String.Format( + "FaultInjectionConnection{{ ConnectionErrorType: {0}, Interval: {1}, Threshold: {2}%}}", + this.connectionErrorType, + this.interval, + this.thresholdPercentage * 100); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResultBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResultBuilder.cs new file mode 100644 index 0000000000..75be94d040 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorResultBuilder.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using Microsoft.Azure.Documents.FaultInjection; + + /// + /// Used to build a . + /// + public sealed class FaultInjectionConnectionErrorResultBuilder + { + private readonly FaultInjectionConnectionErrorType connectionErrorType; + private TimeSpan interval; + private double thresholdPercentage = 1.0; + + /// + /// Creates a new instance of the . + /// + /// + public FaultInjectionConnectionErrorResultBuilder(FaultInjectionConnectionErrorType connectionErrorType) + { + this.connectionErrorType = connectionErrorType; + } + + /// + /// Indicates how often the connection error will be injected. + /// + /// + /// + /// + public FaultInjectionConnectionErrorResultBuilder WithInterval(TimeSpan interval) + { + if (interval <= TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException(nameof(interval), "Argument 'interval' must be greater than zero."); + } + + this.interval = interval; + return this; + } + + /// + /// Percentage of establised conection that will be impacted by the fault injection. + /// Values must be between within the range (0, 1]. + /// The default value is 1. + /// + /// + /// the . + public FaultInjectionConnectionErrorResultBuilder WithThreshold(double thresholdPercentage) + { + if (thresholdPercentage <= 0 || thresholdPercentage > 1) + { + throw new ArgumentOutOfRangeException(nameof(thresholdPercentage), "Argument 'thresholdPercentage' must be within the range (0, 1]."); + } + + this.thresholdPercentage = thresholdPercentage; + return this; + } + + /// + /// Builds the . + /// + /// a . + public FaultInjectionConnectionErrorResult Build() + { + return new FaultInjectionConnectionErrorResult( + this.connectionErrorType, + this.interval, + this.thresholdPercentage); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorType.cs new file mode 100644 index 0000000000..3a3b5a96ad --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionErrorType.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Connection Error Type for Fault Injection + /// + public enum FaultInjectionConnectionErrorType + { + /// + /// Emulates a connection close because of a received stream close + /// + ReceiveStreamClosed, + + /// + /// Emulates a connection close because of a failure to recieve a response + /// + ReceiveFailed, + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionType.cs new file mode 100644 index 0000000000..51df5d6d00 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionConnectionType.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Connection Error Type for Fault Injection + /// + public enum FaultInjectionConnectionType + { + /// + /// Client using Direct Mode + /// + Direct, + + /// + /// All connection types. Default value. + /// + All, + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpoint.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpoint.cs new file mode 100644 index 0000000000..08ba4580aa --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpoint.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using Microsoft.Azure.Cosmos; + + /// + /// Fault Injection Endpoint + /// + public sealed class FaultInjectionEndpoint + { + private readonly string databaseName; + private readonly string containerName; + private readonly FeedRange feedRange; + private readonly bool includePrimary; + private readonly int replicaCount; + + internal static FaultInjectionEndpoint Empty = new FaultInjectionEndpoint( + string.Empty, + string.Empty, + new FeedRangePartitionKey(new PartitionKey()), false, 0); + + /// + /// Creates a . + /// + /// The database name. + /// The container name. + /// The . + /// Indicates wether primary replica can be used + /// Replica count. + public FaultInjectionEndpoint( + string databaseName, + string containerName, + FeedRange feedRange, + bool includePrimary, + int replicaCount) + { + this.databaseName = databaseName; + this.containerName = containerName; + this.feedRange = feedRange; + this.includePrimary = includePrimary; + this.replicaCount = replicaCount; + } + + /// + /// Get the FeedRange. + /// + /// the + public FeedRange GetFeedRange() + { + return this.feedRange; + } + + /// + /// Get the flag indicating if primary replica address can be used. + /// + /// The flag indicating if a primary replica address can be used. + public bool IsIncludePrimary() + { + return this.includePrimary; + } + + /// + /// Gets the replica count. Used to inidcate how many physical addresses can be applied to the fault injection rule. + /// + /// an int, the replica count + public int GetReplicaCount() + { + return this.replicaCount; + } + + public string GetResoureName() + { + return $"dbs/{this.databaseName}/colls/{this.containerName}"; + } + + /// + /// To String method + /// + /// A string represeting the . + public override string ToString() + { + return String.Format( + "\"FaultInjectionEndpoint\":{{ \"ResourceName\": \"{0}\", \"FeedRange\": \"{1}\", \"IncludePrimary\": \"{2}\", \"ReplicaCount\": \"{3}\"}}", + this.GetResoureName(), + this.feedRange, + this.includePrimary, + this.replicaCount); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpointBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpointBuilder.cs new file mode 100644 index 0000000000..5a6948236d --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionEndpointBuilder.cs @@ -0,0 +1,68 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// This class is used to build a + /// + public sealed class FaultInjectionEndpointBuilder + { + private readonly string databaseName; + private readonly string containerName; + private readonly FeedRange feedRange; + private int replicaCount = int.MaxValue; + private bool includePrimary = true; + + /// + /// Used to create a + /// + /// the database name. + /// the container name. + /// the . + public FaultInjectionEndpointBuilder(string databaseName, string containerName, FeedRange feedRange) + { + this.databaseName = databaseName; + this.containerName = containerName; + this.feedRange = feedRange; + } + + /// + /// Set the replica count of the . + /// + /// int representing the replica count. + /// the . + public FaultInjectionEndpointBuilder WithReplicaCount(int replicaCount) + { + if (replicaCount < 0) + { + throw new ArgumentOutOfRangeException(nameof(replicaCount), "Argument 'replicaCount' cannot be negative."); + } + + this.replicaCount = replicaCount; + return this; + } + + /// + /// Flag to indicate whether primary replica address can be used. + /// + /// flag to indicate whether primary addresses can be used. + /// the . + public FaultInjectionEndpointBuilder WithIncludePrimary(bool includePrimary) + { + this.includePrimary = includePrimary; + return this; + } + + /// + /// Creates a new . + /// + /// the . + public FaultInjectionEndpoint Build() + { + return new FaultInjectionEndpoint(this.databaseName, this.containerName, this.feedRange, this.includePrimary, this.replicaCount); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs new file mode 100644 index 0000000000..675e33f4bb --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Operation Types fault injection can be applied to. + /// + public enum FaultInjectionOperationType + { + /// + /// Read items. + /// + ReadItem, + + /// + /// Query items. + /// + QueryItem, + + /// + /// Create items. + /// + CreateItem, + + /// + /// Upsert items. + /// + UpsertItem, + + /// + /// Replace items. + /// + ReplaceItem, + + /// + /// Delete items. + /// + DeleteItem, + + /// + /// Patch items. + /// + PatchItem, + + /// + /// Batch operations. + /// + Batch, + + /// + /// All operation types. Default value. + /// + All, + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionResultBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionResultBuilder.cs new file mode 100644 index 0000000000..2e9f73d239 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionResultBuilder.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Fault Injection Result Builder. + /// Based on error type will return either a or a . + /// + public sealed class FaultInjectionResultBuilder + { + + /// + /// Gets the server error result builder. + /// + /// the server error type. + /// the fault injection server error builder. + public static FaultInjectionServerErrorResultBuilder GetResultBuilder(FaultInjectionServerErrorType serverErrorType) + { + return new FaultInjectionServerErrorResultBuilder(serverErrorType); + } + + /// + /// Gets the connection error result builder. + /// + /// the connection error type. + /// the fault injection connection error builder. + public static FaultInjectionConnectionErrorResultBuilder GetResultBuilder(FaultInjectionConnectionErrorType connectionErrorType) + { + return new FaultInjectionConnectionErrorResultBuilder(connectionErrorType); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRule.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRule.cs new file mode 100644 index 0000000000..24b146af45 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRule.cs @@ -0,0 +1,187 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + + /// + /// Fault Injector Rule + /// + public sealed class FaultInjectionRule + { + private readonly IFaultInjectionResult result; + private readonly FaultInjectionCondition condition; + private readonly string id; + private readonly TimeSpan duration; + private readonly TimeSpan startDelay; + private readonly int hitLimit; + private bool enabled; + private IFaultInjectionRuleInternal? effectiveRule; + + /// + /// Initializes a new instance of the class. + /// + /// the of the rule. + /// the of the rule. + /// the id of the rule + /// the lifetime of the rule. The duration starts at the time of the rule creation, not the time of when the rule is enabled (rule is enabled by default). + /// the start delay of the rule. + /// the maximum number of times the rule can be applied. + /// whether the rule is enabled. + public FaultInjectionRule( + IFaultInjectionResult result, + FaultInjectionCondition condition, + string id, + TimeSpan duration, + TimeSpan startDelay, + int hitLimit, + bool enabled) + { + this.result = result ?? throw new ArgumentNullException(nameof(result), "Argument 'result' cannot be null."); + this.condition = condition; + this.id = id; + this.duration = duration; + this.startDelay = startDelay; + this.hitLimit = hitLimit; + this.enabled = enabled; + } + + /// + /// The fault injection result. + /// + /// the . + public IFaultInjectionResult GetResult() + { + return this.result; + } + + /// + /// Gets the fault injection condition. + /// + /// the . + public FaultInjectionCondition GetCondition() + { + return this.condition; + } + + /// + /// Gets the effictive life span of the fault injection rule. + /// + /// a representing the duration. + public TimeSpan GetDuration() + { + return this.duration; + } + + /// + /// Gets the start delay of the fault injection rule. + /// + /// a representing the start delay. + public TimeSpan GetStartDelay() + { + return this.startDelay; + } + + /// + /// The hit limit of the fault injection rule. + /// + /// the hit count. + public int GetHitLimit() + { + return this.hitLimit; + } + + /// + /// Gets the id of the fault injection rule. + /// + /// the id. + public string GetId() + { + return this.id; + } + + /// + /// Gets the flag to indicate whether the rule is enabled. + /// + /// the flag to indicate whether the rule is enabled. + public bool IsEnabled() + { + return this.enabled; + } + + /// + /// Disables the fault injection rule. + /// + public void Disable() + { + this.enabled = false; + + this.effectiveRule?.Disable(); + } + + /// + /// Enables the fault injection rule. + /// + public void Enable() + { + this.enabled = true; + + this.effectiveRule?.Enable(); + } + + /// + /// Gets the count of how many times the rule has been applied. + /// + /// the hit count. + public long GetHitCount() + { + return this.effectiveRule == null ? 0 : this.effectiveRule.GetHitCount(); + } + + /// + /// Get the physical addresses of the fault injection rule. + /// + /// a List of Uri's of the physical addresses + public List GetAddresses() + { + return this.effectiveRule?.GetAddresses() ?? new List { }; + } + + /// + /// Gets the region endpoints of the fault injection rule. + /// + /// a List of Uri's of the region endpoints + public List GetRegionEndpoints() + { + return this.effectiveRule?.GetRegionEndpoints() ?? new List { }; + } + + /// + /// Sets the effective fault injection rule. + /// + /// the effective fault injection rule. + internal void SetEffectiveFaultInjectionRule(IFaultInjectionRuleInternal effectiveRule) + { + this.effectiveRule = effectiveRule; + } + + /// + /// Represents Fault Injection Rule as a string. + /// + /// the fault injection rule represented as a string. + public override string ToString() + { + return string.Format( + "FaultInjectionRule{{ id: {0}, result: {1}, condition: {2}, duration: {3}, startDelay: {4}, hitlimit: {5}, enabled: {6}}}", + this.id, + this.result, + this.condition, + this.duration, + this.startDelay, + this.hitLimit, + this.enabled); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRuleBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRuleBuilder.cs new file mode 100644 index 0000000000..331b1f03bd --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionRuleBuilder.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// Builds a . + /// + public sealed class FaultInjectionRuleBuilder + { + private readonly string id; + private readonly IFaultInjectionResult result; + private readonly FaultInjectionCondition condition; + private TimeSpan duration; + private TimeSpan startDelay; + private int hitLimit; + private bool enabled = true; + + /// + /// Initializes a new instance of the class. + /// Sets the id of the rule. + /// + /// The id of the rule. Cannot be null or empty + /// the + /// the Cannot be null + public FaultInjectionRuleBuilder(string id, FaultInjectionCondition condition, IFaultInjectionResult result) + { + if (string.IsNullOrEmpty(id)) + { + throw new ArgumentNullException(nameof(id), "Argument 'id' cannot be null or empty."); + } + + this.id = id; + this.condition = condition ?? throw new ArgumentNullException(nameof(condition), "Argument 'condition' cannot be null."); + this.result = result ?? throw new ArgumentNullException(nameof(result), "Argument 'result' cannot be null."); + } + + /// + /// Set the effective duration of the rule. The rule will not be applied after the duration has elapsed. + /// By default, the duration will be until the end of the application. + /// The duration starts at the time of the rule creation, not the time of when the rule is enabled (rule is enabled by default). + /// + /// the effective duration. + /// the . + public FaultInjectionRuleBuilder WithDuration(TimeSpan duration) + { + this.duration = duration; + return this; + } + + /// + /// Sets the start delay of the rule. + /// + /// the time before the rule will become effective. + /// the . + public FaultInjectionRuleBuilder WithStartDelay(TimeSpan startDelay) + { + this.startDelay = startDelay; + return this; + } + + /// + /// Sets the maximum number of times the rule can be applied. + /// + /// the hit limit. + /// the . + public FaultInjectionRuleBuilder WithHitLimit(int hitLimit) + { + if (hitLimit <= 0) + { + throw new ArgumentOutOfRangeException(nameof(hitLimit), "Argument 'hitLimit' must be greater than 0."); + } + + this.hitLimit = hitLimit; + return this; + } + + /// + /// Flag to indicate whether the rule is enabled. The rule will not be applied if it is disabled. + /// A rule can be enabled or disabled multiple times. + /// The default value is true. + /// + /// flag to indicate whether the rule is enabled. + /// the . + public FaultInjectionRuleBuilder IsEnabled(bool enabled) + { + this.enabled = enabled; + return this; + } + + /// + /// Creates a new . + /// + /// the . + public FaultInjectionRule Build() + { + return new FaultInjectionRule( + this.result, + this.condition, + this.id, + this.duration, + this.startDelay, + this.hitLimit, + this.enabled); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResult.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResult.cs new file mode 100644 index 0000000000..1aa6849cad --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResult.cs @@ -0,0 +1,84 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// Fault Injection Server Error Result. + /// + public sealed class FaultInjectionServerErrorResult : IFaultInjectionResult + { + private readonly FaultInjectionServerErrorType serverErrorType; + private readonly int times; + private readonly TimeSpan delay; + private readonly bool suppressServiceRequests; + + /// + /// Creates a new FaultInjectionServerErrorResult. + /// + /// Specifies the server error type. + /// Specifies the number of times a rule can be applied on a single operation. + /// Specifies the injected delay for the server error. + public FaultInjectionServerErrorResult(FaultInjectionServerErrorType serverErrorType, int times, TimeSpan delay, bool suppressServiceRequests) + { + this.serverErrorType = serverErrorType; + this.times = times; + this.delay = delay; + this.suppressServiceRequests = suppressServiceRequests; + } + + /// + /// Gets the fault injection server error type. + /// + /// the . + public FaultInjectionServerErrorType GetServerErrorType() + { + return this.serverErrorType; + } + + /// + /// Gets the number of times a rule can be applied on a single operation. + /// + /// An int representing the number of times a rule can be applied. + public int GetTimes() + { + return this.times; + } + + /// + /// Gets the injected delay for the server error. + /// Required for RESPONSE_DELAY and CONNECTION_DELAY error types. + /// + /// A TimeSpan represeting the lenght of the delay. + public TimeSpan GetDelay() + { + return this.delay; + } + + /// + /// Get a flag indicating whether service requests should be suppressed. If not specified (null) the default + /// behavior is applied - only sending the request to the service when the delay is lower + /// than the network request timeout. + /// + /// a flag indicating whether service requests should be suppressed. + public bool GetSuppressServiceRequests() + { + return this.suppressServiceRequests; + } + + /// + /// To String method + /// + /// a string represeting the . + public override string ToString() + { + return String.Format( + "FaultInjectionServerErrorResult{{ serverErrorType: {0}, times: {1}, delay: {2}}}", + this.serverErrorType, + this.times, + this.delay); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs new file mode 100644 index 0000000000..6dfc17e0b0 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs @@ -0,0 +1,88 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + + /// + /// Used to create a . + /// + public sealed class FaultInjectionServerErrorResultBuilder + { + private readonly FaultInjectionServerErrorType serverErrorType; + private int times = int.MaxValue; + private TimeSpan delay; + private bool suppressServiceRequest; + private bool isDelaySet = false; + + /// + /// Creates a . + /// + /// + public FaultInjectionServerErrorResultBuilder(FaultInjectionServerErrorType serverErrorType) + { + this.serverErrorType = serverErrorType; + } + + /// + /// Sets the number of times the same fault injection rule can be applied per operation, + /// by default there is no limit. + /// + /// The maximum number of times the same fault injection rule can be applied per operation. + /// The current . + public FaultInjectionServerErrorResultBuilder WithTimes(int times) + { + this.times = times; + return this; + } + + /// + /// Sets the injected delay time for the server error. + /// + /// Only used RESPONSE_DELAY and CONNECTION_DELAY. + /// + /// For RESPONSE_DELAY, it is the delay added before the response. + /// For CONNECTION_DELAY, it is the delay added before the connection is established. + /// + /// + /// The duration of the delay. + /// The current . + public FaultInjectionServerErrorResultBuilder WithDelay(TimeSpan delay) + { + if (this.serverErrorType == FaultInjectionServerErrorType.ResponseDelay + || this.serverErrorType == FaultInjectionServerErrorType.ConnectionDelay) + { + this.delay = delay; + this.isDelaySet = true; + } + return this; + } + + public FaultInjectionServerErrorResultBuilder WithSuppressServiceRequest(bool suppressServiceRequest) + { + this.suppressServiceRequest = suppressServiceRequest; + return this; + } + + /// + /// Creates a new . + /// + /// the . + public FaultInjectionServerErrorResult Build() + { + if ((this.serverErrorType == FaultInjectionServerErrorType.ResponseDelay + || this.serverErrorType == FaultInjectionServerErrorType.ConnectionDelay) + && !this.isDelaySet) + { + throw new ArgumentNullException(nameof(this.delay), "Argument 'delay' required for server error type: " + this.serverErrorType); + } + + return new FaultInjectionServerErrorResult( + this.serverErrorType, + this.times, + this.delay, + this.suppressServiceRequest); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs new file mode 100644 index 0000000000..fa096f4d4c --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Types of ServerErrors that can be injected + /// + public enum FaultInjectionServerErrorType + { + /// + /// 410: Gone from server + /// + Gone, + + /// + /// 449: RetryWith from server + /// + RetryWith, + + /// + /// 500: Internal Server Error from server + /// + InternalServerEror, + + /// + /// 429:Too Many Requests from server + /// + TooManyRequests, + + /// + /// 404-1002: Read session not available from server + /// + ReadSessionNotAvailable, + + /// + /// 408: Request Timeout from server + /// + Timeout, + + /// + /// 410-1008: Partition is splitting + /// + PartitionIsSplitting, + + /// + /// 410-1008: Partition is migrating from server + /// + PartitionIsMigrating, + + /// + /// Used to simulate a transient timeout/broken connection when over request timeout + /// + ResponseDelay, + + /// + /// Used to simulate hight channel acquisiton. + /// When over a connection timeouts can simulate connectionTimeoutException + /// + ConnectionDelay, + + /// + /// 503: Service Unavailable from server + /// + ServiceUnavailable + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjector.cs new file mode 100644 index 0000000000..9d821cec5a --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjector.cs @@ -0,0 +1,52 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Documents.FaultInjection; + + public class FaultInjector + { + private readonly ChaosInterceptorFactory chaosInterceptorFactory; + + public FaultInjector(List rules) + { + this.chaosInterceptorFactory = new ChaosInterceptorFactory(rules); + } + + public CosmosClientOptions GetFaultInjectionClientOptions(CosmosClientOptions clientOptions) + { + clientOptions.ChaosInterceptorFactory = this.chaosInterceptorFactory; + return clientOptions; + } + + /// + /// Gets the fault injection rule id for the given activity id + /// If multible FaultInjectionRules are applied to the same activity, the first rule applied will be returned + /// + /// + /// the fault injection rule id + public string? GetFaultInjectionRuleId(Guid activityId) + { + return this.chaosInterceptorFactory.ChaosInterceptor?.GetFaultInjectionRuleId(activityId); + } + + //Get Application Context + public FaultInjectionApplicationContext? GetApplicationContext() + { + return this.chaosInterceptorFactory.ChaosInterceptor?.GetApplicationContext(); + } + + internal IChaosInterceptor? GetChaosInterceptor() + { + return this.chaosInterceptorFactory.ChaosInterceptor; + } + + internal IChaosInterceptorFactory GetChaosInterceptorFactory() + { + return this.chaosInterceptorFactory; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs new file mode 100644 index 0000000000..fa92c25b3f --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs @@ -0,0 +1,227 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using Microsoft.Azure.Documents.Rntbd; + using Microsoft.Azure.Documents.FaultInjection; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents; + + internal class ChaosInterceptorFactory : IChaosInterceptorFactory + { + private readonly List rules; + + public ChaosInterceptor? ChaosInterceptor { get; private set; } + + public ChaosInterceptorFactory(List rules) + { + this.rules = rules; + } + + public IChaosInterceptor CreateInterceptor(DocumentClient documentClient) + { + this.ChaosInterceptor = new ChaosInterceptor(this.rules, documentClient); + + return this.ChaosInterceptor; + } + + public async Task ConfigureChaosInterceptorAsync() + { + if (this.ChaosInterceptor != null) + { + await this.ChaosInterceptor.ConfigureFaultInjectionRules(); + } + } + } + + internal class ChaosInterceptor : IChaosInterceptor + { + private FaultInjectionRuleStore? ruleStore; + private RntbdConnectionErrorInjector? connectionErrorInjector; + private TimeSpan requestTimeout; + + private readonly DocumentClient documentClient; + private readonly List rules; + private readonly FaultInjectionDynamicChannelStore channelStore; + private readonly FaultInjectionApplicationContext applicationContext; + + public ChaosInterceptor(List rules, DocumentClient documentClient) + { + this.documentClient = documentClient; + this.rules = rules; + this.channelStore = new FaultInjectionDynamicChannelStore(); + this.applicationContext = new FaultInjectionApplicationContext(); + } + + public async Task ConfigureFaultInjectionRules() + { + this.ruleStore = await FaultInjectionRuleStore.CreateAsync(this.documentClient, this.applicationContext); + this.connectionErrorInjector = new RntbdConnectionErrorInjector(this.ruleStore, this.channelStore); + this.requestTimeout = this.documentClient.ConnectionPolicy.RequestTimeout; + + foreach (FaultInjectionRule rule in this.rules) + { + if (this.ruleStore != null) + { + IFaultInjectionRuleInternal? effectiveRule = await this.ruleStore.ConfigureFaultInjectionRuleAsync(rule); + if (effectiveRule != null) { this.connectionErrorInjector?.Accept(effectiveRule); } + } + } + } + + /// + /// Used to inject faults on request call + /// + /// + /// + public async Task<(bool, StoreResponse?)> OnRequestCallAsync(ChannelCallArguments args) + { + StoreResponse faultyResponse; + FaultInjectionServerErrorRule? serverResponseErrorRule = this.ruleStore?.FindRntbdServerResponseErrorRule(args); + if (serverResponseErrorRule != null) + { + this.applicationContext.AddRuleExecution(serverResponseErrorRule.GetId(), args.CommonArguments.ActivityId); + + faultyResponse = serverResponseErrorRule.GetInjectedServerError(args); + + DefaultTrace.TraceInformation("FaultInjection: FaultInjection Rule {0} Inserted error for request {1}", + serverResponseErrorRule.GetId(), args.CommonArguments.ActivityId); + + if (serverResponseErrorRule.GetInjectedServerErrorType() == FaultInjectionServerErrorType.Timeout) + { + TransportException transportException = new TransportException( + TransportErrorCode.RequestTimeout, + new TimeoutException("Fault Injection Server Error: Timeout"), + args.CommonArguments.ActivityId, + args.PreparedCall.Uri, + "Fault Injection Server Error: Timeout", + args.CommonArguments.UserPayload, + args.CommonArguments.PayloadSent); + await Task.Delay(this.requestTimeout); + throw transportException; + } + + return (true, faultyResponse); + } + + return (false, null); + } + + /// + /// Used to inject faults on channel open + /// + /// + /// + /// + /// + /// + public async Task OnChannelOpenAsync(Guid activityId, Guid connectionCorrilationId, Uri serverUri, DocumentServiceRequest openingRequest, Channel channel) + { + FaultInjectionServerErrorRule? serverConnectionDelayRule = this.ruleStore?.FindRntbdServerConnectionDelayRule( + serverUri, + openingRequest, + activityId); + this.channelStore.AddChannel(connectionCorrilationId, channel); + + if (serverConnectionDelayRule != null) + { + serverConnectionDelayRule.GetDelay(); + + this.applicationContext.AddRuleExecution(serverConnectionDelayRule.GetId(), activityId); + + DefaultTrace.TraceInformation("FaultInjection: FaultInjection Rule {0} Inserted {1} duration connection delay for request {2}", + serverConnectionDelayRule.GetId(), serverConnectionDelayRule.GetDelay(), activityId); + + TimeSpan connectionDelay = serverConnectionDelayRule.GetDelay(); + await Task.Delay(connectionDelay); + } + } + + /// + /// Used to update internal active channel store on channel close + /// + /// + public void OnChannelDispose(Guid connectionCorrelationId) + { + this.channelStore.RemoveChannel(connectionCorrelationId); + } + + /// + /// Used to inject faults before connection writes + /// + /// + public async Task OnBeforeConnectionWriteAsync(ChannelCallArguments args) + { + FaultInjectionServerErrorRule? serverResponseDelayRule = this.ruleStore?.FindRntbdServerResponseDelayRule(args); + + if (serverResponseDelayRule != null) + { + this.applicationContext.AddRuleExecution(serverResponseDelayRule.GetId(), args.CommonArguments.ActivityId); + TimeSpan delay = serverResponseDelayRule.GetDelay(); + + DefaultTrace.TraceInformation("FaultInjection: FaultInjection Rule {0} Inserted {1} duration response delay for request {2}", + serverResponseDelayRule.GetId(), delay, args.CommonArguments.ActivityId); + + await Task.Delay(delay); + } + } + + /// + /// Used to inject faults after connection writes + /// + /// + public async Task OnAfterConnectionWriteAsync(ChannelCallArguments args) + { + FaultInjectionServerErrorRule? serverResponseDelayRule = this.ruleStore?.FindRntbdServerResponseDelayRule(args); + + if (serverResponseDelayRule != null) + { + this.applicationContext.AddRuleExecution(serverResponseDelayRule.GetId(), args.CommonArguments.ActivityId); + TimeSpan delay = serverResponseDelayRule.GetDelay(); + + DefaultTrace.TraceInformation("FaultInjection: FaultInjection Rule {0} Inserted {1} duration response delay for request {2}", + serverResponseDelayRule.GetId(), delay, args.CommonArguments.ActivityId); + + await Task.Delay(delay); + } + } + + /// + /// Gets the fault injection rule id for the given activity id + /// If multible FaultInjectionRules are applied to the same activity, the first rule applied will be returned + /// Will return the empty string if no rule is found + /// + /// + /// the fault injection rule id + public string GetFaultInjectionRuleId(Guid activityId) + { + if (this.applicationContext.TryGetRuleExecutionByActivityId(activityId, out (DateTime, string) execution)) + { + return execution.Item2; + } + return string.Empty; + } + + public FaultInjectionApplicationContext GetApplicationContext() + { + return this.applicationContext; + } + + internal FaultInjectionRuleStore? GetRuleStore() + { + return this.ruleStore; + } + + internal TimeSpan GetRequestTimeout() + { + return this.requestTimeout; + } + + internal FaultInjectionDynamicChannelStore GetChannelStore() + { + return this.channelStore; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionApplicationContext.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionApplicationContext.cs new file mode 100644 index 0000000000..283d1ceabb --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionApplicationContext.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Concurrent; + + public class FaultInjectionApplicationContext + { + + private readonly ConcurrentDictionary> executionsByRuleId; + private readonly ConcurrentDictionary> executionsByActivityId; + private readonly BlockingCollection<(DateTime, string, Guid)> values; + + public FaultInjectionApplicationContext() + { + this.executionsByActivityId = new ConcurrentDictionary>(); + this.executionsByRuleId = new ConcurrentDictionary>(); + this.values = new BlockingCollection<(DateTime, string, Guid)>(); + } + + internal void AddRuleExecution(string ruleId, Guid activityId) + { + if(!this.executionsByRuleId.TryAdd(ruleId, new List<(DateTime, Guid)>() { (DateTime.UtcNow, activityId) })) + { + this.executionsByRuleId[ruleId].Add((DateTime.UtcNow, activityId)); + } + + if (!this.executionsByActivityId.TryAdd(activityId, new List<(DateTime, string)>() { (DateTime.UtcNow, ruleId) })) + { + this.executionsByActivityId[activityId].Add((DateTime.UtcNow, ruleId)); + } + + this.values.Add((DateTime.UtcNow, ruleId, activityId)); + } + + /// + /// Gets all execution of fault injection rules by DateTime, RuleId, ActivityId + /// + /// of Execution Time, RuleId, ActivityId + public BlockingCollection<(DateTime, string, Guid)> GetAllRuleExecutions() + { + return this.values; + } + + public ConcurrentDictionary> GetAllRuleExecutionsByRuleId() + { + return this.executionsByRuleId; + } + + public ConcurrentDictionary> GetAllRuleExecutionsByActivityId() + { + return this.executionsByActivityId; + } + + public bool TryGetRuleExecutionsByRuleId(string ruleId, out List<(DateTime, Guid)> execution) + { + if (this.executionsByRuleId.TryGetValue(ruleId, out List<(DateTime, Guid)>? ruleExecutions)) + { + execution = ruleExecutions; + return true; + } + + execution = new List<(DateTime, Guid)>(); + return false; + } + + /// + /// Gets the fault injection rule id for the given activity id + /// If multible FaultInjectionRules are applied to the same activity, the first rule applied will be returned + /// + /// the fault injection rule id + public bool TryGetRuleExecutionByActivityId(Guid activityId, out (DateTime, string) execution) + { + if (this.executionsByActivityId.TryGetValue(activityId, out List<(DateTime, string)>? ruleExecutions)) + { + execution = ruleExecutions[0]; + return true; + } + + execution = (DateTime.MinValue, string.Empty); + return false; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConditionInternal.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConditionInternal.cs new file mode 100644 index 0000000000..f250ad9480 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConditionInternal.cs @@ -0,0 +1,236 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Rntbd; + + internal class FaultInjectionConditionInternal + { + private readonly List validators; + + private string containerResourceId = string.Empty; + private OperationType? operationType = null; + private List regionEndpoints = new List{ }; + private List physicalAddresses = new List { }; + + public FaultInjectionConditionInternal() + { + this.validators = new List(); + } + + public OperationType? GetOperationType() + { + return this.operationType; + } + + public void SetContainerResourceId(string containerResourcePath) + { + this.containerResourceId = containerResourcePath; + if (!string.IsNullOrEmpty(this.containerResourceId)) + { + this.validators.Add(new ContainerValidator(this.containerResourceId)); + } + } + + public void SetOperationType(OperationType operationType) + { + this.operationType = operationType; + if (this.operationType != null) + { + this.validators.Add(new OperationTypeValidator(this.operationType.Value)); + } + } + + public void SetRegionEndpoints(List regionEndpoints) + { + this.regionEndpoints = regionEndpoints; + if (this.regionEndpoints != null) + { + this.validators.Add(new RegionEndpointValidator(this.regionEndpoints)); + } + } + + public string GetContainerResourceId() + { + return this.containerResourceId; + } + + public List GetRegionEndpoints() + { + return this.regionEndpoints; + } + + public List GetPhysicalAddresses() + { + return this.physicalAddresses; + } + + public void SetAddresses(List physicalAddresses) + { + this.physicalAddresses = physicalAddresses; + if (this.physicalAddresses != null && physicalAddresses.Count > 0) + { + this.validators.Add(new AddressValidator(this.physicalAddresses)); + } + } + + public bool IsApplicable(string ruleId, ChannelCallArguments args) + { + foreach (IFaultInjectionConditionValidator validator in this.validators) + { + if (!validator.IsApplicable(ruleId, args)) + { + return false; + } + } + + return true; + } + + //Used for connection delay + public bool IsApplicable(Uri callUri, DocumentServiceRequest request) + { + foreach (IFaultInjectionConditionValidator validator in this.validators) + { + if (validator.GetType() == typeof(RegionEndpointValidator)) + { + RegionEndpointValidator regionEndpointValidator = (RegionEndpointValidator)validator; + if (!regionEndpointValidator.IsApplicable(request)) + { + return false; + } + } + else if (validator.GetType() == typeof(OperationTypeValidator)) + { + OperationTypeValidator operationTypeValidator = (OperationTypeValidator)validator; + if (!operationTypeValidator.IsApplicable(request)) + { + return false; + } + } + else if (validator.GetType() == typeof(ContainerValidator)) + { + ContainerValidator containerValidator = (ContainerValidator)validator; + if (!containerValidator.IsApplicable(request)) + { + return false; + } + } + else if (validator.GetType() == typeof(AddressValidator)) + { + AddressValidator addressValidator = (AddressValidator)validator; + if (!addressValidator.IsApplicable(callUri)) + { + return false; + } + } + else + { + throw new ArgumentException($"Unknown validator type {validator.GetType()}"); + } + } + + return true; + } + + private interface IFaultInjectionConditionValidator + { + public bool IsApplicable(string ruleId, ChannelCallArguments args); + } + + private class RegionEndpointValidator : IFaultInjectionConditionValidator + { + private readonly List regionEndpoints; + + public RegionEndpointValidator(List regionEndpoints) + { + this.regionEndpoints = regionEndpoints; + } + + public bool IsApplicable(string ruleId, ChannelCallArguments args) + { + bool isApplicable = this.regionEndpoints.Any(uri => args.LocationEndpointToRouteTo.AbsoluteUri.StartsWith(uri.AbsoluteUri)); + + return isApplicable; + } + + //Used for Connection Delay + public bool IsApplicable(DocumentServiceRequest request) + { + return this.regionEndpoints.Contains(request.RequestContext.LocationEndpointToRoute); + } + } + + private class OperationTypeValidator : IFaultInjectionConditionValidator + { + private readonly OperationType operationType; + + public OperationTypeValidator(OperationType operationType) + { + this.operationType = operationType; + } + + public bool IsApplicable(string ruleId, ChannelCallArguments args) + { + return args.OperationType == this.operationType; + } + + //Used for Connection Delay + public bool IsApplicable(DocumentServiceRequest request) + { + return request.OperationType == this.operationType; + } + } + + private class ContainerValidator : IFaultInjectionConditionValidator + { + private readonly string containerResourceId; + + public ContainerValidator(string containerResourceId) + { + this.containerResourceId = containerResourceId; + } + + public bool IsApplicable(string ruleId, ChannelCallArguments args) + { + return String.Equals(this.containerResourceId, args.ResolvedCollectionRid); + } + + //Used for Connection Delay + public bool IsApplicable(DocumentServiceRequest request) + { + return String.Equals(this.containerResourceId, request.RequestContext.ResolvedCollectionRid); + } + } + + private class AddressValidator : IFaultInjectionConditionValidator + { + private readonly List addresses; + + public AddressValidator(List addresses) + { + this.addresses = addresses; + } + + public bool IsApplicable(string ruleId, ChannelCallArguments args) + { + bool isApplicable = this.addresses.Exists(uri => args.PreparedCall.Uri.AbsoluteUri.StartsWith(uri.AbsoluteUri)); + + return isApplicable; + } + + //Used for Connection Delay + public bool IsApplicable(Uri callUri) + { + bool isApplicable = this.addresses.Exists(uri => callUri.AbsoluteUri.StartsWith(uri.AbsoluteUri)); + + return isApplicable; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConnectionErrorRule.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConnectionErrorRule.cs new file mode 100644 index 0000000000..bcf82ff939 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionConnectionErrorRule.cs @@ -0,0 +1,92 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + + public class FaultInjectionConnectionErrorRule : IFaultInjectionRuleInternal + { + private readonly string id; + private readonly DateTime startTime; + private readonly DateTime expireTime; + private readonly List regionEndpoints; + private readonly List addresses; + private readonly FaultInjectionConnectionType connectionType; + private readonly FaultInjectionConnectionErrorResult result; + + private long hitCount; + private bool enabled; + + public FaultInjectionConnectionErrorRule( + String id, + bool enabled, + TimeSpan delay, + TimeSpan duration, + List regionEndpoints, + List addresses, + FaultInjectionConnectionType connectionType, + FaultInjectionConnectionErrorResult result) + { + this.id = string.IsNullOrEmpty(id) ? throw new ArgumentException("Argument {nameof(id)} cannot be null or empty") : id; + this.enabled = enabled; + this.startTime = DateTime.UtcNow + delay; + this.expireTime = this.startTime + duration; + this.regionEndpoints = regionEndpoints; + this.addresses = addresses; + this.connectionType = connectionType; + this.result = result ?? throw new ArgumentNullException(nameof(result)); + this.hitCount = 0; + } + public void Disable() + { + this.enabled = false; + } + + public void Enable() + { + this.enabled = true; + } + + public List GetAddresses() + { + return this.addresses; + } + + public FaultInjectionConnectionType GetConnectionType() + { + return this.connectionType; + } + + public long GetHitCount() + { + return this.hitCount; + } + + public string GetId() + { + return this.id; + } + + public List GetRegionEndpoints() + { + return this.regionEndpoints; + } + + public FaultInjectionConnectionErrorResult GetResult() + { + return this.result; + } + + public bool IsValid() + { + return this.enabled && DateTime.UtcNow >= this.startTime && DateTime.UtcNow <= this.expireTime; + } + + public void ApplyRule() + { + Interlocked.Increment(ref this.hitCount); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionDynamicChannelStore.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionDynamicChannelStore.cs new file mode 100644 index 0000000000..7e94b49b28 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionDynamicChannelStore.cs @@ -0,0 +1,36 @@ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Concurrent; + using Microsoft.Azure.Documents.Rntbd; + + internal class FaultInjectionDynamicChannelStore + { + private readonly ConcurrentDictionary channelDictonary; + + public FaultInjectionDynamicChannelStore() + { + this.channelDictonary = new ConcurrentDictionary(); + } + + public void AddChannel(Guid connectionCorrelationId, Channel channel) + { + this.channelDictonary.TryAdd(connectionCorrelationId, channel); + } + + public void RemoveChannel(Guid connectionCorrelationId) + { + this.channelDictonary.TryRemove(connectionCorrelationId, out _); + } + + public List GetAllChannels() + { + return this.channelDictonary.Values.ToList(); + } + + public List GetAllChannelIds() + { + return this.channelDictonary.Keys.ToList(); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs new file mode 100644 index 0000000000..a9ebdf9b73 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs @@ -0,0 +1,381 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.Common; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + + internal class FaultInjectionRuleProcessor + { + private readonly ConnectionMode connectionMode; + private readonly CollectionCache collectionCache; + private readonly GlobalEndpointManager globalEndpointManager; + private readonly GlobalAddressResolver addressResolver; + private readonly Func retryPolicy; + private readonly IRoutingMapProvider routingMapProvider; + private readonly FaultInjectionApplicationContext applicationContext; + + private readonly RegionNameMapper regionNameMapper = new RegionNameMapper(); + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + /// + /// + /// + public FaultInjectionRuleProcessor( + Func retryPolicy, + ConnectionMode connectionMode, + CollectionCache collectionCache, + GlobalEndpointManager globalEndpointManager, + GlobalAddressResolver addressResolver, + IRoutingMapProvider routingMapProvider, + FaultInjectionApplicationContext applicationContext) + { + this.connectionMode = connectionMode; + this.collectionCache = collectionCache ?? throw new ArgumentNullException(nameof(collectionCache)); + this.globalEndpointManager = globalEndpointManager ?? throw new ArgumentNullException(nameof(globalEndpointManager)); + this.addressResolver = addressResolver ?? throw new ArgumentNullException(nameof(addressResolver)); + this.retryPolicy = retryPolicy ?? throw new ArgumentNullException(nameof(retryPolicy)); + this.routingMapProvider = routingMapProvider ?? throw new ArgumentNullException(nameof(routingMapProvider)); + this.applicationContext = applicationContext ?? throw new ArgumentNullException(nameof(applicationContext)); + } + + public async Task ProcessFaultInjectionRule(FaultInjectionRule rule) + { + _ = rule ?? throw new ArgumentNullException(nameof(rule)); + + this.ValidateRule(rule); + return await this.GetEffectiveRule(rule); + + } + + private void ValidateRule(FaultInjectionRule rule) + { + if ((rule.GetCondition().GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetCondition().GetConnectionType() == FaultInjectionConnectionType.All) + && this.connectionMode != ConnectionMode.Direct) + { + throw new ArgumentException("Direct connection mode is not supported when client is not in direct mode"); + } + } + + private async Task GetEffectiveRule(FaultInjectionRule rule) + { + if (rule.GetResult().GetType() == typeof(FaultInjectionServerErrorResult)) + { + return await this.GetEffectiveServerErrorRule(rule); + } + + if (rule.GetResult().GetType() == typeof(FaultInjectionConnectionErrorResult)) + { + return await this.GetEffectiveConnectionErrorRule(rule); + } + + throw new Exception($"{rule.GetResult().GetType()} is not supported"); + } + + private async Task GetEffectiveServerErrorRule(FaultInjectionRule rule) + { + FaultInjectionServerErrorType errorType = ((FaultInjectionServerErrorResult)rule.GetResult()).GetServerErrorType(); + FaultInjectionConditionInternal effectiveCondition = new FaultInjectionConditionInternal(); + + FaultInjectionOperationType operationType = rule.GetCondition().GetOperationType(); + if ((operationType != FaultInjectionOperationType.All) && this.CanErrorLimitToOperation(errorType)) + { + effectiveCondition.SetOperationType(this.GetEffectiveOperationType(operationType)); + } + + if (rule.GetCondition().GetEndpoint() != FaultInjectionEndpoint.Empty) + { + DocumentServiceRequest request = DocumentServiceRequest.CreateFromName( + operationType: OperationType.Read, + resourceFullName: rule.GetCondition().GetEndpoint().GetResoureName(), + resourceType: ResourceType.Document, + authorizationTokenType: AuthorizationTokenType.PrimaryMasterKey); ; + + ContainerProperties collection = await this.collectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton); + + effectiveCondition.SetContainerResourceId(collection.ResourceId); + } + + List regionEndpoints = this.GetRegionEndpoints(rule.GetCondition()); + + if (!string.IsNullOrEmpty(rule.GetCondition().GetRegion())) + { + effectiveCondition.SetRegionEndpoints(regionEndpoints); + } + else + { + List defaultRegion = new List(regionEndpoints) + { + this.globalEndpointManager.GetDefaultEndpoint() + }; + effectiveCondition.SetRegionEndpoints(defaultRegion); + } + + List effectiveAddresses = await BackoffRetryUtility>.ExecuteAsync( + () => this.ResolvePhyicalAddresses( + regionEndpoints, + rule.GetCondition(), + this.IsWriteOnly(rule.GetCondition())), + this.retryPolicy()); + + if (!this.CanErrorLimitToOperation(errorType)) + { + effectiveAddresses = effectiveAddresses.Select(address => + new Uri(string.Format( + "{0}://{1}:{2}/", + address.Scheme.ToString(), + address.Host.ToString(), + address.Port.ToString()))).ToList(); + } + + effectiveCondition.SetAddresses(effectiveAddresses); + + FaultInjectionServerErrorResult result = (FaultInjectionServerErrorResult)rule.GetResult(); + + return new FaultInjectionServerErrorRule( + id: rule.GetId(), + enabled: rule.IsEnabled(), + delay: rule.GetStartDelay(), + duration: rule.GetDuration(), + hitLimit: rule.GetHitLimit(), + connectionType: rule.GetCondition().GetConnectionType(), + condition: effectiveCondition, + result: new FaultInjectionServerErrorResultInternal( + result.GetServerErrorType(), + result.GetTimes(), + result.GetDelay(), + result.GetSuppressServiceRequests(), + this.applicationContext)); + + } + + private async Task GetEffectiveConnectionErrorRule(FaultInjectionRule rule) + { + List regionEndpoints = string.IsNullOrEmpty(rule.GetCondition().GetRegion()) + ? new List() : this.GetRegionEndpoints(rule.GetCondition()); + + List resolvedPhysicalAdresses = await this.ResolvePhyicalAddresses( + regionEndpoints, + rule.GetCondition(), + this.IsWriteOnly(rule.GetCondition())); + + resolvedPhysicalAdresses.ForEach(address => + new Uri(string.Format( + "{0}://{1}:{2}/", + address.Scheme.ToString(), + address.Host.ToString(), + address.Port.ToString()))); + + FaultInjectionConnectionErrorResult result = (FaultInjectionConnectionErrorResult)rule.GetResult(); + return new FaultInjectionConnectionErrorRule( + rule.GetId(), + rule.IsEnabled(), + rule.GetStartDelay(), + rule.GetDuration(), + regionEndpoints, + resolvedPhysicalAdresses, + rule.GetCondition().GetConnectionType(), + result); + } + + private bool CanErrorLimitToOperation(FaultInjectionServerErrorType errorType) + { + // Some errors should only be applied to specific operationTypes/ requests + // others can be applied to all operations + return errorType != FaultInjectionServerErrorType.Gone + && errorType != FaultInjectionServerErrorType.ConnectionDelay; + } + + private OperationType GetEffectiveOperationType(FaultInjectionOperationType faultInjectionOperationType) + { + return faultInjectionOperationType switch + { + FaultInjectionOperationType.ReadItem => OperationType.Read, + FaultInjectionOperationType.CreateItem => OperationType.Create, + FaultInjectionOperationType.QueryItem => OperationType.Query, + FaultInjectionOperationType.UpsertItem => OperationType.Upsert, + FaultInjectionOperationType.ReplaceItem => OperationType.Replace, + FaultInjectionOperationType.DeleteItem => OperationType.Delete, + FaultInjectionOperationType.PatchItem => OperationType.Patch, + FaultInjectionOperationType.Batch => OperationType.Batch, + _ => throw new ArgumentException($"FaultInjectionOperationType: {faultInjectionOperationType} is not supported"), + }; + } + + private List GetRegionEndpoints(FaultInjectionCondition condition) + { + bool isWriteOnlyEndpoints = this.IsWriteOnly(condition); + + if(!string.IsNullOrEmpty(condition.GetRegion())) + { + return new List { this.ResolveFaultInjectionServiceEndpoint(condition.GetRegion(), isWriteOnlyEndpoints) }; + } + else + { + return isWriteOnlyEndpoints + ? this.globalEndpointManager.GetAvailableWriteEndpointsByLocation().Values.ToList() + : this.globalEndpointManager.GetAvailableReadEndpointsByLocation().Values.ToList(); + } + } + + private Uri ResolveFaultInjectionServiceEndpoint(string region, bool isWriteOnlyEndpoints) + { + if (isWriteOnlyEndpoints) + { + if (this.globalEndpointManager.GetAvailableWriteEndpointsByLocation().TryGetValue( + this.regionNameMapper.GetCosmosDBRegionName(region), + out Uri? endpoint)) + { + return endpoint; + } + } + else + { + if (this.globalEndpointManager.GetAvailableReadEndpointsByLocation().TryGetValue( + this.regionNameMapper.GetCosmosDBRegionName(region), + out Uri? endpoint)) + { + return endpoint; + } + } + + throw new ArgumentException($"Cannot find service endpoint for region: {region}"); + } + + private bool IsWriteOnly(FaultInjectionCondition condition) + { + return condition.GetOperationType() != FaultInjectionOperationType.All + && this.GetEffectiveOperationType(condition.GetOperationType()).IsWriteOperation(); + } + + private async Task> ResolvePhyicalAddresses( + List regionEndpoints, + FaultInjectionCondition condition, + bool isWriteOnly) + { + FaultInjectionEndpoint addressEndpoints = condition.GetEndpoint(); + if (addressEndpoints == null || addressEndpoints == FaultInjectionEndpoint.Empty) + { + return new List{ }; + } + + List resolvedPhysicalAddresses = new List(); + + FeedRangeInternal feedRangeInternal = (FeedRangeInternal)addressEndpoints.GetFeedRange(); + + DocumentServiceRequest request = DocumentServiceRequest.CreateFromName( + operationType: OperationType.Read, + resourceFullName: condition.GetEndpoint().GetResoureName(), + resourceType: ResourceType.Document, + authorizationTokenType: AuthorizationTokenType.PrimaryMasterKey); + + ContainerProperties collection = await this.collectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton); + + foreach (Uri regionEndpoint in regionEndpoints) + { + //The feed range can be mapped to multiple physical partitions, get the feed range list and resolve addresses for each partition + IEnumerable pkRanges = await feedRangeInternal.GetPartitionKeyRangesAsync( + this.routingMapProvider, + collection.ResourceId, + collection.PartitionKey, + cancellationToken: new CancellationToken(), + trace: NoOpTrace.Singleton); + + foreach (string partitionKeyRange in pkRanges) + { + DocumentServiceRequest fauntInjectionAddressRequest = DocumentServiceRequest.Create( + operationType: OperationType.Read, + resourceId: collection.ResourceId, + resourceType: ResourceType.Document, + authorizationTokenType: AuthorizationTokenType.PrimaryMasterKey); + + fauntInjectionAddressRequest.RequestContext.RouteToLocation(regionEndpoint); + fauntInjectionAddressRequest.RouteTo(new PartitionKeyRangeIdentity(partitionKeyRange)); + + if (isWriteOnly) + { + TransportAddressUri primary = await this.ResolvePrimaryTransportAddressUriAsync(fauntInjectionAddressRequest, true); + return new List { primary.Uri }; + } + + // Make sure Primary URI is the first one in the list + IEnumerable resolvedEndpoints = (await this.ResolveAllTransportAddressUriAsync( + fauntInjectionAddressRequest, + addressEndpoints.IsIncludePrimary(), + true)) + .Take(addressEndpoints.GetReplicaCount()) + .Select(address => address.Uri); + resolvedPhysicalAddresses.AddRange(resolvedEndpoints); + } + } + + return resolvedPhysicalAddresses; + } + + private async Task> ResolveAllTransportAddressUriAsync( + DocumentServiceRequest request, + bool includePrimary, + bool forceAddressRefresh) + { + PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesHelperAsync(request, forceAddressRefresh); + + if (includePrimary) + { + List allAddresses = new List(); + TransportAddressUri primary = partitionPerProtocolAddress.PrimaryReplicaTransportAddressUri; + allAddresses.Add(primary); + + foreach (TransportAddressUri transportAddressUri in partitionPerProtocolAddress.ReplicaTransportAddressUris) + { + if (transportAddressUri != primary) + { + allAddresses.Add(transportAddressUri); + } + } + return allAddresses; + } + + return partitionPerProtocolAddress.NonPrimaryReplicaTransportAddressUris; + } + + private async Task ResolvePrimaryTransportAddressUriAsync( + DocumentServiceRequest request, + bool forceAddressRefresh) + { + PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesHelperAsync(request, forceAddressRefresh); + + return partitionPerProtocolAddress.GetPrimaryAddressUri(request); + } + + private async Task ResolveAddressesHelperAsync( + DocumentServiceRequest request, + bool forceAddressRefresh) + { + PartitionAddressInformation partitionAddressInformation = + await this.addressResolver.ResolveAsync(request, forceAddressRefresh, CancellationToken.None); + + return partitionAddressInformation.Get(Documents.Client.Protocol.Tcp); + } + + internal GlobalEndpointManager GetGlobalEndpointManager() + { + return this.globalEndpointManager; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs new file mode 100644 index 0000000000..df2804b6ed --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs @@ -0,0 +1,160 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.Common; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Rntbd; + + internal class FaultInjectionRuleStore + { + private readonly ConcurrentDictionary serverResponseDelayRuleSet = new ConcurrentDictionary(); + private readonly ConcurrentDictionary serverResponseErrorRuleSet = new ConcurrentDictionary(); + private readonly ConcurrentDictionary serverConnectionDelayRuleSet = new ConcurrentDictionary(); + private readonly ConcurrentDictionary connectionErrorRuleSet = new ConcurrentDictionary(); + + private readonly FaultInjectionRuleProcessor ruleProcessor; + + public static async Task CreateAsync( + DocumentClient client, + FaultInjectionApplicationContext applicationContext) + { + CollectionCache collectionCache = await client.GetCollectionCacheAsync(NoOpTrace.Singleton); + IRoutingMapProvider routingMapProvider = await client.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); + + return new FaultInjectionRuleStore( + connectionMode: client.ConnectionPolicy.ConnectionMode, + collectionCache: collectionCache, + globalEndpointManager: client.GlobalEndpointManager, + addressResolver: client.AddressResolver, + retryPolicy: client.ResetSessionTokenRetryPolicy.GetRequestPolicy, + routingMapProvider: routingMapProvider, + applicationContext: applicationContext); + } + + private FaultInjectionRuleStore( + ConnectionMode connectionMode, + CollectionCache collectionCache, + GlobalEndpointManager globalEndpointManager, + GlobalAddressResolver addressResolver, + Func retryPolicy, + IRoutingMapProvider routingMapProvider, + FaultInjectionApplicationContext applicationContext) + { + this.ruleProcessor = new FaultInjectionRuleProcessor( + connectionMode: connectionMode, + collectionCache: collectionCache, + globalEndpointManager: globalEndpointManager, + addressResolver: addressResolver, + retryPolicy: retryPolicy, + routingMapProvider: routingMapProvider, + applicationContext: applicationContext); + } + + public async Task ConfigureFaultInjectionRuleAsync(FaultInjectionRule rule) + { + _ = rule ?? throw new ArgumentNullException(nameof(rule)); + + IFaultInjectionRuleInternal effectiveRule = await this.ruleProcessor.ProcessFaultInjectionRule(rule); + rule.SetEffectiveFaultInjectionRule(effectiveRule); + + if (effectiveRule.GetType() == typeof(FaultInjectionConnectionErrorRule)) + { + this.connectionErrorRuleSet.TryAdd((FaultInjectionConnectionErrorRule)effectiveRule, 0); + } + else if (effectiveRule.GetType() == typeof(FaultInjectionServerErrorRule)) + { + FaultInjectionServerErrorRule serverErrorRule = (FaultInjectionServerErrorRule)effectiveRule; + + switch (serverErrorRule.GetResult().GetServerErrorType()) + { + case FaultInjectionServerErrorType.ResponseDelay: + this.serverResponseDelayRuleSet.TryAdd(serverErrorRule, 0); + break; + case FaultInjectionServerErrorType.ConnectionDelay: + this.serverConnectionDelayRuleSet.TryAdd(serverErrorRule, 0); + break; + default: + this.serverResponseErrorRuleSet.TryAdd(serverErrorRule, 0); + break; + } + } + + return effectiveRule; + } + + public FaultInjectionServerErrorRule? FindRntbdServerResponseErrorRule(ChannelCallArguments args) + { + foreach (FaultInjectionServerErrorRule rule in this.serverResponseErrorRuleSet.Keys) + { + if ((rule.GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetConnectionType() == FaultInjectionConnectionType.All) + && rule.IsApplicable(args)) + { + return rule; + } + } + + return null; + } + + public FaultInjectionServerErrorRule? FindRntbdServerResponseDelayRule(ChannelCallArguments args) + { + foreach (FaultInjectionServerErrorRule rule in this.serverResponseDelayRuleSet.Keys) + { + if ((rule.GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetConnectionType() == FaultInjectionConnectionType.All) + && rule.IsApplicable(args)) + { + return rule; + } + } + + return null; + } + + public FaultInjectionServerErrorRule? FindRntbdServerConnectionDelayRule( + Uri callUri, + DocumentServiceRequest request, + Guid activityId) + { + foreach (FaultInjectionServerErrorRule rule in this.serverConnectionDelayRuleSet.Keys) + { + if ((rule.GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetConnectionType() == FaultInjectionConnectionType.All) + && rule.IsApplicable( + callUri, + request, + activityId)) + { + return rule; + } + } + + return null; + } + + public bool ContainsRule(FaultInjectionConnectionErrorRule rule) + { + return this.connectionErrorRuleSet.ContainsKey(rule); + } + + public bool RemoveRule(FaultInjectionConnectionErrorRule rule) + { + return this.connectionErrorRuleSet.Remove(rule, out byte _); + } + + internal FaultInjectionRuleProcessor GetRuleProcessor() + { + return this.ruleProcessor; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs new file mode 100644 index 0000000000..71ebcc842b --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs @@ -0,0 +1,243 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Globalization; + using System.Text; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.Rntbd; + + /// + /// Fault Injection Server Error Result. + /// + internal class FaultInjectionServerErrorResultInternal + { + private readonly FaultInjectionServerErrorType serverErrorType; + private readonly int times; + private readonly TimeSpan delay; + private readonly bool suppressServiceRequest; + private readonly FaultInjectionApplicationContext applicationContext; + + /// + /// Constructor for FaultInjectionServerErrorResultInternal + /// + /// + /// + /// + /// + public FaultInjectionServerErrorResultInternal( + FaultInjectionServerErrorType serverErrorType, + int times, + TimeSpan delay, + bool suppressServiceRequest, + FaultInjectionApplicationContext applicationContext) + { + this.serverErrorType = serverErrorType; + this.times = times; + this.delay = delay; + this.suppressServiceRequest = suppressServiceRequest; + this.applicationContext = applicationContext; + } + + /// + /// Returns Server Error Type + /// + /// the + public FaultInjectionServerErrorType GetServerErrorType() + { + return this.serverErrorType; + } + + /// + /// Gets the number of times a rule can be applied on a single operation. + /// + /// An int representing the number of times a rule can be applied. + public int GetTimes() + { + return this.times; + } + + /// + /// Gets the injected delay for the server error. + /// Required for RESPONSE_DELAY and CONNECTION_DELAY error types. + /// + /// A TimeSpan represeting the lenght of the delay. + public TimeSpan GetDelay() + { + return this.delay; + } + + /// + /// Return whether or not the service request should be suppressed. + /// + /// + public bool GetSuppressServiceRequest() + { + return this.suppressServiceRequest; + } + + /// + /// Determins if the rule can be applied. + /// + /// + /// + /// if the rule can be applied. + public bool IsApplicable(string ruleId, Guid activityId) + { + bool hasRuleExecution = this.applicationContext.TryGetRuleExecutionsByRuleId(ruleId, out List<(DateTime, Guid)>? applicationByRuleId); + + if (this.times == 0 || !hasRuleExecution) + { + return true; + } + int count = 0; + foreach ((DateTime, Guid) application in applicationByRuleId) + { + if (application.Item2 == activityId) + { + count++; + } + } + return count < this.times; + } + + /// + /// Gets the FaultInjectionServerErrorType + /// + /// + public FaultInjectionServerErrorType GetInjectedServerErrorType() + { + return this.serverErrorType; + } + + /// + /// Get server error to be injected + /// + /// + /// + /// + /// + public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ruleId) + { + StoreResponse storeResponse; + + switch (this.serverErrorType) + { + case FaultInjectionServerErrorType.Gone: + INameValueCollection goneHeaders = args.RequestHeaders; + goneHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ServerGenerated410).ToString(CultureInfo.InvariantCulture)); + storeResponse = new StoreResponse() + { + Status = 410, + Headers = goneHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Gone, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.RetryWith: + storeResponse = new StoreResponse() + { + Status = 449, + Headers = args.RequestHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Retry With, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.TooManyRequests: + INameValueCollection tooManyRequestsHeaders = args.RequestHeaders; + tooManyRequestsHeaders.Add(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, "500"); + tooManyRequestsHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.RUBudgetExceeded).ToString(CultureInfo.InvariantCulture)); + + storeResponse = new StoreResponse() + { + Status = 429, + Headers = tooManyRequestsHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Too Many Requests, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.Timeout: + + storeResponse = new StoreResponse() + { + Status = 408, + Headers = args.RequestHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Timeout, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.InternalServerEror: + storeResponse = new StoreResponse() + { + Status = 500, + Headers = args.RequestHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Internal Server Error, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.ReadSessionNotAvailable: + + const string badSesstionToken = "1:1#1#1=1#1=1"; + + INameValueCollection readSessionHeaders = args.RequestHeaders; + readSessionHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(CultureInfo.InvariantCulture)); + readSessionHeaders.Add(HttpConstants.HttpHeaders.SessionToken, badSesstionToken); + + storeResponse = new StoreResponse() + { + Status = 404, + Headers = readSessionHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Read Session Not Available, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.PartitionIsMigrating: + INameValueCollection partitionMigrationHeaders = args.RequestHeaders; + partitionMigrationHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture)); + + storeResponse = new StoreResponse() + { + Status = 410, + Headers = partitionMigrationHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Partition Migrating, rule: {ruleId}")) + }; + + return storeResponse; + + case FaultInjectionServerErrorType.PartitionIsSplitting: + INameValueCollection partitionSplitting = args.RequestHeaders; + partitionSplitting.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture)); + + storeResponse = new StoreResponse() + { + Status = 410, + Headers = partitionSplitting, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Partition Splitting, rule: {ruleId}")) + }; + + return storeResponse; + case FaultInjectionServerErrorType.ServiceUnavailable: + storeResponse = new StoreResponse() + { + Status = 503, + Headers = args.RequestHeaders, + ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Service Unavailable, rule: {ruleId}")) + }; + + return storeResponse; + + default: + throw new ArgumentException($"Server error type {this.serverErrorType} is not supported"); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorRule.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorRule.cs new file mode 100644 index 0000000000..310fd2dfb4 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorRule.cs @@ -0,0 +1,205 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Rntbd; + + internal class FaultInjectionServerErrorRule : IFaultInjectionRuleInternal + { + private readonly string id; + private readonly DateTime startTime; + private readonly DateTime expireTime; + private readonly int hitLimit; + private readonly ConcurrentDictionary hitCountDetails; + private readonly FaultInjectionConnectionType connectionType; + private readonly FaultInjectionConditionInternal condition; + private readonly FaultInjectionServerErrorResultInternal result; + + private long hitCount; + private long evaluationCount; + private bool enabled; + + public FaultInjectionServerErrorRule( + string id, + bool enabled, + TimeSpan delay, + TimeSpan duration, + int hitLimit, + FaultInjectionConnectionType connectionType, + FaultInjectionConditionInternal condition, + FaultInjectionServerErrorResultInternal result) + { + this.id = id; + this.enabled = enabled; + this.hitLimit = hitLimit; + this.startTime = DateTime.UtcNow + delay; + this.expireTime = duration == TimeSpan.MaxValue ? DateTime.MaxValue : this.startTime + duration; + this.hitCount = 0; + this.hitCountDetails = new ConcurrentDictionary(); + this.evaluationCount = 0; + this.condition = condition ?? throw new ArgumentNullException(nameof(condition)); + this.result = result ?? throw new ArgumentNullException(nameof(result)); + this.connectionType = connectionType; + } + + public bool IsApplicable(ChannelCallArguments args) + { + if (!this.IsValid()) + { + return false; + } + + // the failure reason will be populated during condition evaluation + if (!this.condition.IsApplicable(this.id, args)) + { + return false; + } + + if (!this.result.IsApplicable(this.id, args.CommonArguments.ActivityId)) + { + return false; + } + + long evaluationCount = this.evaluationCount + 1; + Interlocked.Increment(ref this.evaluationCount); + bool withinHitLimit = this.hitLimit == 0 || evaluationCount <= this.hitLimit; + if (!withinHitLimit) + { + return false; + } + else + { + Interlocked.Increment(ref this.hitCount); + + // track hit count details, keay is operationType-ResourceType + String key = args.OperationType.ToString() + "-" + args.ResourceType.ToString(); + this.hitCountDetails.AddOrUpdate( + key, + 1L, + (k, v) => v ++); + + return true; + } + } + + //Used for Connection Delay + public bool IsApplicable( + Uri callUri, + DocumentServiceRequest request, + Guid activityId) + { + if (!this.IsValid()) + { + return false; + } + + // the failure reason will be populated during condition evaluation + if (!this.condition.IsApplicable(callUri, request)) + { + return false; + } + + if (!this.result.IsApplicable(this.id, activityId)) + { + return false; + } + + long evaluationCount = this.evaluationCount + 1; + Interlocked.Increment(ref this.evaluationCount); + bool withinHitLimit = this.hitLimit == 0 || evaluationCount <= this.hitLimit; + if (!withinHitLimit) + { + return false; + } + else + { + Interlocked.Increment(ref this.hitCount); + + // track hit count details, key is operationType-ResourceType + String key = request.OperationType.ToString() + "-" + request.ResourceType.ToString(); + this.hitCountDetails.AddOrUpdate( + key, + 1L, + (k, v) => v++); + + return true; + } + } + + public StoreResponse GetInjectedServerError(ChannelCallArguments args) + { + return this.result.GetInjectedServerError(args, this.id); + } + + public FaultInjectionServerErrorType GetInjectedServerErrorType() + { + return this.result.GetInjectedServerErrorType(); + } + + public string GetId() + { + return this.id; + } + + public long GetHitCount() + { + return this.hitCount; + } + + public ConcurrentDictionary GetHitCountDetails() + { + return this.hitCountDetails; + } + + public FaultInjectionConnectionType GetConnectionType() + { + return this.connectionType; + } + + public FaultInjectionConditionInternal GetCondition() + { + return this.condition; + } + + public FaultInjectionServerErrorResultInternal GetResult() + { + return this.result; + } + + public TimeSpan GetDelay() + { + return this.result.GetDelay(); + } + + public bool IsValid() + { + DateTime now = DateTime.UtcNow; + return this.enabled && now >= this.startTime && now <= this.expireTime; + } + + public void Disable() + { + this.enabled = false; + } + + public void Enable() + { + this.enabled = true; + } + + public List GetAddresses() + { + return this.condition.GetPhysicalAddresses(); + } + + public List GetRegionEndpoints() + { + return this.condition.GetRegionEndpoints(); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionResult.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionResult.cs new file mode 100644 index 0000000000..001f9c5cc3 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionResult.cs @@ -0,0 +1,12 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + /// + /// Interface of Fault Injection Result + /// + public interface IFaultInjectionResult + { + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionRuleInternal.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionRuleInternal.cs new file mode 100644 index 0000000000..bd7876ab9d --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/IFaultInjectionRuleInternal.cs @@ -0,0 +1,60 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + + /// + /// Interface for a Fault Injection Rule + /// + public interface IFaultInjectionRuleInternal + { + /// + /// Disables the rule + /// + void Disable(); + + /// + /// Enables the rule + /// + void Enable(); + + /// + /// Gets the physical addresses of the rule. + /// + /// a list of the physical addresses of the rule. + List GetAddresses(); + + /// + /// Gets the region endpoints of the rule. + /// + /// a list of the region endpoints. + List GetRegionEndpoints(); + + /// + /// A flag indicating if the rule is valid. + /// + /// the flag. + bool IsValid(); + + /// + /// Gets the id of the rule. + /// + /// the id + string GetId(); + + /// + /// Gets tht hit count of the rule. + /// + /// the hit count. + long GetHitCount(); + + /// + /// Gets the connection type of the rule. + /// + /// the . + FaultInjectionConnectionType GetConnectionType(); + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/RntbdConnectionErrorInjector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/RntbdConnectionErrorInjector.cs new file mode 100644 index 0000000000..9cb6a11d4e --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/RntbdConnectionErrorInjector.cs @@ -0,0 +1,233 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Rntbd; + + internal class RntbdConnectionErrorInjector + { + private readonly FaultInjectionRuleStore ruleStore; + private readonly FaultInjectionDynamicChannelStore channelStore; + private readonly RegionNameMapper regionNameMapper; + private readonly Dictionary regionSpecialCases; + + public RntbdConnectionErrorInjector(FaultInjectionRuleStore ruleStore, FaultInjectionDynamicChannelStore channelStore) + { + this.ruleStore = ruleStore ?? throw new ArgumentNullException(nameof(ruleStore)); + this.channelStore = channelStore ?? throw new ArgumentNullException(nameof(channelStore)); + this.regionNameMapper = new RegionNameMapper(); + // Some regions have different names in the RNTBD endpoint and in the location endpoint + // this dictionary maps the RNTBD endpoint region name to the location endpoint region name + this.regionSpecialCases = new Dictionary + { + { "westus1", "westus" }, + { "eastus1", "eastus" }, + { "chinanorth1", "chinanorth" }, + { "chinaeast1", "chinaeast" }, + { "australiacentral1", "australiacentral" }, + }; + } + + public bool Accept(IFaultInjectionRuleInternal rule) + { + if ((rule.GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetConnectionType() == FaultInjectionConnectionType.All) + && (rule.GetType() == typeof(FaultInjectionConnectionErrorRule))) + { + this.InjectConnectionErrorTask((FaultInjectionConnectionErrorRule)rule); + return true; + } + return false; + } + + public Task InjectConnectionErrorTask(FaultInjectionConnectionErrorRule rule) + { + TimeSpan delay = rule.GetResult().GetTimespan(); + + return Task.Delay(delay).ContinueWith( + t => + { + //check to see if rule is valid + if (this.IsEffectiveRule(rule)) + { + List allChannels = this.channelStore.GetAllChannels(); + Random random = new Random(); + FaultInjectionConnectionErrorType connectionErrorType = rule.GetResult().GetConnectionErrorType(); + //Case 1: Inject connection error for specific physical address + List addresses = rule.GetAddresses(); + if (addresses != null && addresses.Count > 0) + { + foreach (Uri addressUri in addresses) + { + foreach (Channel channel in allChannels) + { + Uri serverUri; + try + { + serverUri = channel.GetServerUri(); + } + catch (Exception) + { + //Channel is alread disposed, there can sometimes be lag from when the rule is applied and when the channel is disposed + //and marked unhealthy + continue; + } + + if (serverUri.Equals(addressUri)) + { + rule.ApplyRule(); + if (random.NextDouble() < rule.GetResult().GetThresholdPercentage()) + { + rule.ApplyRule(); + DefaultTrace.TraceInformation("FaultInjection: Injecting {0} connection error rule: {1}, for address {2}", + connectionErrorType, + rule.GetId(), + addressUri); + channel.InjectFaultInjectionConnectionError(this.GetTransportException(connectionErrorType, serverUri)); + } + } + } + } + + return Task.CompletedTask; + } + + //Case 2: Inject connection error for all endpoints of one region when there is no specific physical address + List regionEndpoints = rule.GetRegionEndpoints(); + if (regionEndpoints != null && regionEndpoints.Count > 0) + { + + foreach (Uri regionEndpoint in regionEndpoints) + { + foreach (Channel channel in allChannels) + { + Uri serverUri; + try + { + serverUri = channel.GetServerUri(); + } + catch (Exception) + { + //Channel is alread disposed, there can sometimes be lag from when the rule is applied and when the channel is disposed + //and marked unhealthy + continue; + } + + if(this.ParseRntbdEndpointForNormalizedRegion(serverUri).Equals(this.ParseRntbdEndpointForNormalizedRegion(regionEndpoint))) + { + if (random.NextDouble() < rule.GetResult().GetThresholdPercentage()) + { + rule.ApplyRule(); + DefaultTrace.TraceInformation("FaultInjection: Injecting {0} connection error rule: {1} for region {2}", + connectionErrorType, + rule.GetId(), + regionEndpoint); + channel.InjectFaultInjectionConnectionError(this.GetTransportException(connectionErrorType, serverUri)); + } + } + } + } + + return Task.CompletedTask; + } + + //Case 3: Inject connection error for all endpoints of all regions when there is no specific physical address and region + foreach (Channel channel in allChannels) + { + Uri serverUri; + try + { + serverUri = channel.GetServerUri(); + } + catch (Exception) + { + //Channel is alread disposed, there can sometimes be lag from when the rule is applied and when the channel is disposed + //and marked unhealthy + continue; + } + + if (random.NextDouble() < rule.GetResult().GetThresholdPercentage()) + { + rule.ApplyRule(); + DefaultTrace.TraceInformation("FaultInjection: Injecting {0} connection error rule: {1}", + connectionErrorType, + rule.GetId()); + channel.InjectFaultInjectionConnectionError(this.GetTransportException(connectionErrorType, serverUri)); + } + } + + return Task.CompletedTask; + } + + return Task.CompletedTask; + }).ContinueWith( + t => + { + //repeats rule injection if rule is still valid + if (this.IsEffectiveRule(rule)) + { + this.InjectConnectionErrorTask(rule); + } + else + { + //removes rule from rule store one rule is no longer valid + this.ruleStore.RemoveRule(rule); + } + }); + } + + private TransportException GetTransportException(FaultInjectionConnectionErrorType errorType, Uri serverUri) + { + return errorType switch + { + FaultInjectionConnectionErrorType.ReceiveStreamClosed => new TransportException( + errorCode: TransportErrorCode.ReceiveStreamClosed, + innerException: null, + activityId: Guid.Empty, + requestUri: serverUri, + sourceDescription: "FaultInjectionConnectionError", + userPayload: false, + payloadSent: true), + FaultInjectionConnectionErrorType.ReceiveFailed => new TransportException( + errorCode: TransportErrorCode.ReceiveFailed, + innerException: null, + activityId: Guid.Empty, + requestUri: serverUri, + sourceDescription: "FaultInjectionConnectionError", + userPayload: false, + payloadSent: true), + _ => throw new ArgumentException("Invalid connection error type"), + }; + } + + private bool IsEffectiveRule(FaultInjectionConnectionErrorRule rule) + { + return this.ruleStore.ContainsRule(rule) && rule.IsValid(); + } + + private string ParseRntbdEndpointForNormalizedRegion(Uri endpoint) + { + string region = endpoint.ToString().Split(new char[] { '-' })[3]; + region = this.regionNameMapper.GetCosmosDBRegionName( + this.regionSpecialCases.ContainsKey(region) + ? this.regionSpecialCases[region] + : region); + return region; + } + + private string ParseLocationEndpointForNormalizedRegion(Uri endpoint) + { + string region = endpoint.ToString().Split(new char[] { '-' }).Last(); + region = region[0..region.IndexOf('.')]; + region = this.regionNameMapper.GetCosmosDBRegionName(region); + return region; + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs new file mode 100644 index 0000000000..0996b0ab76 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs @@ -0,0 +1,1220 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.FaultInjection.Tests +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Linq; + using System.Net; + using System.Net.Sockets; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.FaultInjection.Tests.Utils; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Documents; + using Newtonsoft.Json.Linq; + + [TestClass] + public class FaultInjectionDirectModeTests + { + private const int Timeout = 60000; + + private CosmosClient? client; + private Cosmos.Database? database; + private Container? container; + + public async Task Initialize(FaultInjector faultInjector, bool multiRegion) + { + this.client = TestCommon.CreateCosmosClient(false, faultInjector, multiRegion); + this.database = await this.client.CreateDatabaseIfNotExistsAsync("testDb"); + + ContainerProperties containerProperties = new ContainerProperties + { + Id = "test", + PartitionKeyPath = "/Pk" + }; + this.container = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 5000); + } + + public async Task Initialize(bool multiRegion) + { + this.client = TestCommon.CreateCosmosClient(false, multiRegion); + this.database = await this.client.CreateDatabaseIfNotExistsAsync("testDb"); + + ContainerProperties containerProperties = new ContainerProperties + { + Id = "test", + PartitionKeyPath = "/Pk" + }; + this.container = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 5000); + } + + public async Task InitilizePreferredRegionsClient(FaultInjector faultInjector, List preferredRegionList, bool multiRegion) + { + this.client = TestCommon.CreateCosmosClient(false, faultInjector, multiRegion, preferredRegionList); + this.database = await this.client.CreateDatabaseIfNotExistsAsync("testDb"); + + ContainerProperties containerProperties = new ContainerProperties + { + Id = "test", + PartitionKeyPath = "/Pk" + }; + this.container = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 5000); + } + + [TestCleanup] + public async Task Cleanup() + { + if (this.database != null) { await this.database.DeleteAsync(); } + this.client?.Dispose(); + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests filtering rules on operation type")] + + public void FaultInjectionServerErrorRule_OperationTypeTest() + { + + List testScenarios = new List + { + OperationType.Read, + OperationType.Replace, + OperationType.Create, + OperationType.Delete, + OperationType.Query, + OperationType.Patch + }; + + foreach (OperationType operationType in testScenarios) + { + if (!this.Timeout_FaultInjectionServerErrorRule_OperationTypeTest(operationType).Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_OperationTypeTest(OperationType operationType) + { + //Test Server gone, operation type will be ignored after getting the address + string serverGoneRuleId = "serverGoneRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule serverGoneRule = new FaultInjectionRuleBuilder( + id: serverGoneRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.ReadItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + string tooManyRequestsRuleId = "tooManyRequestsRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule tooManyRequestsRule = new FaultInjectionRuleBuilder( + id: tooManyRequestsRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.ReadItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.TooManyRequests) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + serverGoneRule.Disable(); + tooManyRequestsRule.Disable(); + + List ruleList = new List { serverGoneRule, tooManyRequestsRule }; + FaultInjector faultInjector = new FaultInjector(ruleList); + await this.Initialize(faultInjector, true); + Assert.AreEqual(0, serverGoneRule.GetAddresses().Count); + + try + { + JObject item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + if (operationType != OperationType.Create) + { + _ = this.container != null + ? await this.container.CreateItemAsync(item) : null; + } + + serverGoneRule.Enable(); + + CosmosDiagnostics? diagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, operationType, item) + : null; + Assert.IsNotNull(diagnostics); + + this.ValidateFaultInjectionRuleApplication( + diagnostics, + (int)HttpStatusCode.Gone, + (int)SubStatusCodes.Unknown, + serverGoneRule); + + serverGoneRule.Disable(); + + if (operationType == OperationType.Delete) + { + _ = this.container != null + ? await this.container.CreateItemAsync(item) : null; + } + + if (operationType == OperationType.Create) + { + _ = this.container != null + ? await this.container.DeleteItemAsync( + (string)item["id"], + new Cosmos.PartitionKey((string)item["Pk"])) + : null; + } + + Assert.AreEqual(0, tooManyRequestsRule.GetAddresses().Count); + + tooManyRequestsRule.Enable(); + + diagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, operationType, item) + : null; + Assert.IsNotNull(diagnostics); + + if (operationType == OperationType.Read) + { + this.ValidateHitCount(tooManyRequestsRule, 1); + } + else + { + this.ValidateFaultInjectionRuleNotApplied( + diagnostics, + tooManyRequestsRule); + } + } + finally + { + serverGoneRule.Disable(); + tooManyRequestsRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests filtering rule applications on physical endpoint")] + public void FaultInjectionServerErrorRule_OperationTypeAddressTest() + { + List testScenarios = new List + { + OperationType.Read, + OperationType.Replace, + OperationType.Create, + OperationType.Delete, + OperationType.Query, + OperationType.Patch + }; + + foreach (OperationType operationType in testScenarios) + { + if (!this.Timeout_FaultInjectionServerErrorRule_OperationTypeAddressTest(operationType).Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_OperationTypeAddressTest(OperationType operationType) + { + await this.Initialize(true); + + List preferredRegions = new List() { }; + List writeRegions = new List(); + List readRegions; + + GlobalEndpointManager? globalEndpointManager = this.client?.ClientContext.DocumentClient.GlobalEndpointManager; + if (globalEndpointManager != null) + { + (writeRegions, readRegions) = await this.GetReadWriteEndpoints(globalEndpointManager); + + for (int i = 0; i < readRegions?.Count; i++) + { + if (writeRegions != null && writeRegions.Contains(readRegions[i])) + { + preferredRegions.Add(readRegions[i].ToString()); + } + else + { + preferredRegions.Insert(0, readRegions[i].ToString()); + } + } + } + + this.client?.Dispose(); + + JObject item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + + string writeRegionServerGoneRuleId = "writeRegionServerGoneRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule writeRegionServerGoneRule = new FaultInjectionRuleBuilder( + id: writeRegionServerGoneRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .WithStartDelay(TimeSpan.FromMilliseconds(200)) + .Build(); + + string primaryReplicaServerGoneRuleId = "primaryReplicaServerGoneRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule primaryReplicaServerGoneRule = new FaultInjectionRuleBuilder( + id: primaryReplicaServerGoneRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .WithEndpoint( + new FaultInjectionEndpointBuilder( + "testDb", + "test", + FeedRange.FromPartitionKey(new Cosmos.PartitionKey((string)item["Pk"]))) + .WithReplicaCount(3) + .Build()) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .WithStartDelay(TimeSpan.FromMilliseconds(200)) + .Build(); + + writeRegionServerGoneRule.Disable(); + primaryReplicaServerGoneRule.Disable(); + + List ruleList = new List { writeRegionServerGoneRule, primaryReplicaServerGoneRule }; + FaultInjector faultInjector = new FaultInjector(ruleList); + + await this.InitilizePreferredRegionsClient(faultInjector, preferredRegions, true); + + _ = this.container != null + ? await this.container.CreateItemAsync(item) : null; + + ChaosInterceptor? interceptor = faultInjector.GetChaosInterceptor() as ChaosInterceptor; + + Assert.IsNotNull(interceptor); + + globalEndpointManager = interceptor + .GetRuleStore()? + .GetRuleProcessor()? + .GetGlobalEndpointManager(); + Assert.IsNotNull(globalEndpointManager); + + try + { + Assert.AreEqual(writeRegions?.Count + 1, writeRegionServerGoneRule.GetRegionEndpoints().Count); + + writeRegionServerGoneRule.Enable(); + CosmosDiagnostics? diagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, operationType, item) : null; + Assert.IsNotNull(diagnostics); + + if (OperationTypeExtensions.IsWriteOperation(operationType)) + { + this.ValidateHitCount(writeRegionServerGoneRule, 1); + this.ValidateFaultInjectionRuleApplication( + diagnostics, + (int)HttpStatusCode.Gone, + (int)SubStatusCodes.Unknown, + writeRegionServerGoneRule); + } + else + { + this.ValidateFaultInjectionRuleNotApplied( + diagnostics, + writeRegionServerGoneRule); + } + + writeRegionServerGoneRule.Disable(); + primaryReplicaServerGoneRule.Enable(); + + Assert.AreEqual(globalEndpointManager.WriteEndpoints.Count + 1, primaryReplicaServerGoneRule.GetRegionEndpoints().Count); + foreach (Uri region in globalEndpointManager.WriteEndpoints) + { + Assert.IsTrue(primaryReplicaServerGoneRule.GetRegionEndpoints().Contains(region)); + } + Assert.AreEqual(globalEndpointManager.WriteEndpoints.Count, primaryReplicaServerGoneRule.GetAddresses().Count); + } + finally + { + writeRegionServerGoneRule.Disable(); + primaryReplicaServerGoneRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests filtering on region")] + public void FaultInjectionServerErrorRule_RegionTest() + { + if (!this.Timeout_FaultInjectionServerErrorRule_RegionTest().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_RegionTest() + { + await this.Initialize(true); + + List preferredRegions = new List() { }; + List readRegions; + ReadOnlyDictionary readEndpoints = new ReadOnlyDictionary(new Dictionary()); + + GlobalEndpointManager? globalEndpointManager = this.client?.ClientContext.DocumentClient.GlobalEndpointManager; + if (globalEndpointManager != null) + { + readEndpoints = globalEndpointManager.GetAvailableReadEndpointsByLocation(); + (_, readRegions) = await this.GetReadWriteEndpoints(globalEndpointManager); + + preferredRegions = new List(readRegions); + } + + this.client?.Dispose(); + + string localRegionRuleId = "localRegionRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule localRegionRule = new FaultInjectionRuleBuilder( + id: localRegionRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithRegion(preferredRegions[0]) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + string remoteRegionRuleId = "remoteRegionRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule remoteRegionRule = new FaultInjectionRuleBuilder( + id: remoteRegionRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithRegion(preferredRegions[1]) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + localRegionRule.Disable(); + remoteRegionRule.Disable(); + + try + { + List rules = new List { localRegionRule, remoteRegionRule }; + FaultInjector faultInjector = new FaultInjector(rules); + await this.Initialize(faultInjector, true); + + JObject databaseItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + _ = this.container != null + ? await this.container.CreateItemAsync(databaseItem) : null; + + globalEndpointManager = this.client?.ClientContext.DocumentClient.GlobalEndpointManager; + + if (globalEndpointManager != null) + { + Assert.AreEqual(1, localRegionRule.GetRegionEndpoints().Count); + Assert.AreEqual(readEndpoints[preferredRegions[0]], localRegionRule.GetRegionEndpoints()[0]); + + Assert.AreEqual(1, remoteRegionRule.GetRegionEndpoints().Count); + Assert.AreEqual(readEndpoints[preferredRegions[1]], remoteRegionRule.GetRegionEndpoints()[0]); + } + + localRegionRule.Enable(); + remoteRegionRule.Enable(); + + CosmosDiagnostics? diagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Read, databaseItem) + : null; + Assert.IsNotNull(diagnostics); + + this.ValidateHitCount(localRegionRule, 1); + this.ValidateHitCount(remoteRegionRule, 0); + this.ValidateFaultInjectionRuleApplication( + diagnostics, + (int)HttpStatusCode.Gone, + (int)SubStatusCodes.ServerGenerated410, + localRegionRule); + } + finally + { + localRegionRule.Disable(); + remoteRegionRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests filtering on partition")] + public void FaultInjectionServerErrorRule_PartitionTest() + { + if (!this.Timeout_FaultInjectionServerErrorRule_RegionTest().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_PartitionTest() + { + await this.Initialize(true); + if (this.container != null && this.client != null) + { + for (int i = 0; i < 10; i++) + { + await this.container.CreateItemAsync(JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() })); + } + + List feedRanges = (List)await this.container.GetFeedRangesAsync(); + Assert.IsTrue(feedRanges.Count > 1); + + string query = "SELECT * FROM c"; + QueryRequestOptions queryOptions = new QueryRequestOptions + { + FeedRange = feedRanges[0] + }; + + JObject query0 = (await this.container.GetItemQueryIterator(query, requestOptions: queryOptions).ReadNextAsync()).First(); + + queryOptions.FeedRange = feedRanges[1]; + JObject query1 = (await this.container.GetItemQueryIterator(query, requestOptions: queryOptions).ReadNextAsync()).First(); + + this.client?.Dispose(); + + string serverErrorFeedRangeRuleId = "serverErrorFeedRangeRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule serverErrorFeedRangeRule = new FaultInjectionRuleBuilder( + id: serverErrorFeedRangeRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithEndpoint( + new FaultInjectionEndpointBuilder("testDb", "testContianer", feedRanges[0]) + .Build()) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.TooManyRequests) + .WithTimes(1) + .Build()) + .Build(); + + serverErrorFeedRangeRule.Disable(); + + List rules = new List { serverErrorFeedRangeRule }; + FaultInjector faultInjector = new FaultInjector(rules); + await this.Initialize(faultInjector, true); + + GlobalEndpointManager? globalEndpointManager = this.client?.ClientContext.DocumentClient.GlobalEndpointManager; + List readRegions = new List(); + if (globalEndpointManager != null) { readRegions = (List)globalEndpointManager.ReadEndpoints.AsEnumerable(); } + + Assert.IsTrue(serverErrorFeedRangeRule.GetRegionEndpoints().Count == readRegions.Count); + + foreach (Uri regionEndpoint in readRegions) + { + Assert.IsTrue(serverErrorFeedRangeRule.GetRegionEndpoints().Contains(regionEndpoint)); + } + + Assert.IsTrue( + serverErrorFeedRangeRule.GetAddresses().Count >= 3 * readRegions.Count + && serverErrorFeedRangeRule.GetAddresses().Count <= 5 * readRegions.Count); + + serverErrorFeedRangeRule.Enable(); + + CosmosDiagnostics? diagnostics = this.container != null + ? (await this.container.ReadItemAsync((string)query0["id"], new Cosmos.PartitionKey((string)query0["Pk"]))).Diagnostics + : null; + Assert.IsNotNull(diagnostics); + + this.ValidateHitCount(serverErrorFeedRangeRule, 1); + this.ValidateFaultInjectionRuleApplication( + diagnostics, + (int)StatusCodes.TooManyRequests, + (int)SubStatusCodes.Unknown, + serverErrorFeedRangeRule); + + try + { + diagnostics = this.container != null + ? (await this.container.ReadItemAsync((string)query1["id"], new Cosmos.PartitionKey((string)query1["Pk"]))).Diagnostics + : null; + Assert.IsNotNull(diagnostics); + Assert.IsTrue(diagnostics.ToString().Contains("200")); + this.ValidateHitCount(serverErrorFeedRangeRule, 1); + } + finally + { + serverErrorFeedRangeRule.Disable(); + } + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests response delay")] + public void FaultInjectionServerErrorRule_ServerResponseDelay() + { + if (!this.Timeout_FaultInjectionServerErrorRule_ServerResponseDelay().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ServerResponseDelay() + { + string timeoutRuleId = "timeoutRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule timeoutRule = new FaultInjectionRuleBuilder( + id: timeoutRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.ReadItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Timeout) + .WithDelay(TimeSpan.FromSeconds(6)) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + timeoutRule.Disable(); + + await this.Initialize(true); + + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + ItemResponse? itemResponse = this.container != null + ? await this.container.CreateItemAsync(createdItem) + : null; + Assert.IsNotNull(itemResponse); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { timeoutRule }); + + CosmosClient testClient = new CosmosClient( + accountEndpoint: TestCommon.EndpointMultiRegion, + authKeyOrResourceToken: TestCommon.AuthKeyMultiRegion, + clientOptions: faultInjector.GetFaultInjectionClientOptions( + new CosmosClientOptions() + { + EnableContentResponseOnWrite = true, + ConnectionMode = ConnectionMode.Direct, + OpenTcpConnectionTimeout = TimeSpan.FromSeconds(1) + })); + + Container testContainer = testClient.GetContainer("testDb", "test"); + timeoutRule.Enable(); + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + ItemResponse? readResponse = await testContainer.ReadItemAsync( + (string)createdItem["id"], + new Cosmos.PartitionKey((string)createdItem["Pk"])); + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + + Assert.IsTrue(elapsed.TotalSeconds >= 6); + Assert.IsNotNull(readResponse); + this.ValidateHitCount(timeoutRule, 1); + this.ValidateFaultInjectionRuleApplication( + readResponse.Diagnostics, + (int)StatusCodes.Gone, + (int)SubStatusCodes.TransportGenerated410, + timeoutRule); + testClient.Dispose(); + } + finally + { + timeoutRule.Disable(); + } + } + + [TestMethod] + [Ignore("Connection Timeouts are currently broken, next Direct release will fix issue")] + [Owner("nalutripician")] + [Description("Tests injection a connection timeout")] + public void FaultInjectionServerErrorRule_ConnectionTimeout() + { + if (!this.Timeout_FaultInjectionServerErrorRule_ConnecitonTimeout().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ConnecitonTimeout() + { + string connectionTimeoutRuleId = "serverConnectionTimeoutRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule connectionTimeoutRule = new FaultInjectionRuleBuilder( + id: connectionTimeoutRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ConnectionDelay) + .WithDelay(TimeSpan.FromSeconds(2)) + .WithTimes(10) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + connectionTimeoutRule.Disable(); + await this.Initialize(true); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { connectionTimeoutRule }); + + CosmosClient testClient = new CosmosClient( + accountEndpoint: TestCommon.EndpointMultiRegion, + authKeyOrResourceToken: TestCommon.AuthKeyMultiRegion, + clientOptions: faultInjector.GetFaultInjectionClientOptions( + new CosmosClientOptions() + { + EnableContentResponseOnWrite = true, + ConnectionMode = ConnectionMode.Direct, + OpenTcpConnectionTimeout = TimeSpan.FromSeconds(1) + })); + Container testContainer = testClient.GetContainer("testDb", "test"); + + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + connectionTimeoutRule.Enable(); + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + ItemResponse? itemResponse = await testContainer.CreateItemAsync(createdItem); + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + + Assert.IsTrue(elapsed.TotalSeconds >= 2); + Assert.IsNotNull(itemResponse); + Assert.IsTrue(connectionTimeoutRule.GetHitCount() == 1 || connectionTimeoutRule.GetHitCount() == 2); + testClient.Dispose(); + } + finally + { + connectionTimeoutRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests filtering connection delay")] + public void FaultInjectionServerErrorRule_ConnectionDelay() + { + if (!this.Timeout_FaultInjectionServerErrorRule_ConnecitonDelay().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ConnecitonDelay() + { + string connectionDelayRuleId = "serverConnectionDelayRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule connectionDelayRule = new FaultInjectionRuleBuilder( + id: connectionDelayRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ConnectionDelay) + .WithDelay(TimeSpan.FromMilliseconds(100)) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + await this.Initialize(true); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { connectionDelayRule }); + + CosmosClient timeoutClient = new CosmosClient( + accountEndpoint: TestCommon.EndpointMultiRegion, + authKeyOrResourceToken: TestCommon.AuthKeyMultiRegion, + clientOptions: faultInjector.GetFaultInjectionClientOptions( + new CosmosClientOptions() + { + EnableContentResponseOnWrite = true, + ConnectionMode = ConnectionMode.Direct, + OpenTcpConnectionTimeout = TimeSpan.FromSeconds(1) + })); + Container timeoutContainer = timeoutClient.GetContainer("testDb", "test"); + + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + ItemResponse? itemResponse = await timeoutContainer.CreateItemAsync(createdItem); + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + + Assert.IsTrue(elapsed.TotalMilliseconds >= 100); + timeoutClient.Dispose(); + + Assert.IsNotNull(itemResponse); + Assert.IsTrue(connectionDelayRule.GetHitCount() == 1 || connectionDelayRule.GetHitCount() == 2); + Assert.IsTrue((int)itemResponse.StatusCode == (int)StatusCodes.Created); + } + finally + { + connectionDelayRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests injecting a server error response")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.Gone, 410, 21005, DisplayName = "Gone")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.InternalServerEror, 500, 0, DisplayName = "InternalServerError")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.RetryWith, 449, 0, DisplayName = "RetryWith")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.TooManyRequests, 429, 0, DisplayName = "TooManyRequests")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.ReadSessionNotAvailable, 404, 1002, DisplayName = "ReadSessionNotAvailable")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.Timeout, 410, 20001, DisplayName = "Timeout")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.PartitionIsMigrating, 410, 1008, DisplayName = "PartitionIsMigrating")] + [DataRow(FaultInjectionOperationType.ReadItem, FaultInjectionServerErrorType.PartitionIsSplitting, 410, 1007, DisplayName = "PartitionIsSplitting")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.Gone, 410, 21005, DisplayName = "Gone Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.InternalServerEror, 500, 0, DisplayName = "InternalServerError Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.RetryWith, 449, 0, DisplayName = "RetryWith Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.TooManyRequests, 429, 0, DisplayName = "TooManyRequests Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.ReadSessionNotAvailable, 404, 1002, DisplayName = "ReadSessionNotAvailable Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.Timeout, 410, 20001, DisplayName = "Timeout Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.PartitionIsMigrating, 410, 1008, DisplayName = "PartitionIsMigrating Write")] + [DataRow(FaultInjectionOperationType.CreateItem, FaultInjectionServerErrorType.PartitionIsSplitting, 410, 1007, DisplayName = "PartitionIsSplitting Write")] + public void FaultInjectionServerErrorRule_ServerErrorResponseTest( + FaultInjectionOperationType faultInjectionOperationType, + FaultInjectionServerErrorType serverErrorType, + int errorStatusCode, + int substatusCode) + { + OperationType operationType = faultInjectionOperationType == FaultInjectionOperationType.ReadItem + ? OperationType.Read + : OperationType.Create; + + if (!this.Timeout_FaultInjectionServerErrorRule_ServerErrorResponseTest( + operationType, + faultInjectionOperationType, + serverErrorType, + errorStatusCode, + substatusCode).Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ServerErrorResponseTest( + OperationType operationType, + FaultInjectionOperationType faultInjectionOperationType, + FaultInjectionServerErrorType serverErrorType, + int errorStatusCode, + int substatusCode) + { + await this.Initialize(true); + + JObject item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + _ = this.container != null ? await this.container.CreateItemAsync(item) : null; + this.client?.Dispose(); + + string serverErrorResponseRuleId = "serverErrorResponseRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule serverErrorResponseRule = new FaultInjectionRuleBuilder( + id: serverErrorResponseRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(faultInjectionOperationType) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(serverErrorType) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + serverErrorResponseRule.Disable(); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { serverErrorResponseRule }); + await this.Initialize(faultInjector, true); + + serverErrorResponseRule.Enable(); + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + CosmosDiagnostics? diagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, operationType, item) + : null; + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + + if (serverErrorType == FaultInjectionServerErrorType.Timeout) + { + ChaosInterceptor? interceptor = faultInjector.GetChaosInterceptor() as ChaosInterceptor; + + Assert.IsNotNull(interceptor); + Assert.IsTrue( + elapsed.TotalSeconds + >= interceptor.GetRequestTimeout().TotalSeconds); + } + Assert.IsNotNull(diagnostics); + + this.ValidateHitCount(serverErrorResponseRule, 1); + this.ValidateFaultInjectionRuleApplication( + diagnostics, + errorStatusCode, + substatusCode, + serverErrorResponseRule); + } + finally + { + serverErrorResponseRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests hit count limit")] + public void FaultInjectionServerErrorRule_HitCountTest() + { + if (!this.Timeout_FaultInjectionServerErrorRule_HitCountTest().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_HitCountTest() + { + string hitCountRuleId = "hitCountRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule hitCountRule = new FaultInjectionRuleBuilder( + id: hitCountRuleId, + condition: + new FaultInjectionConditionBuilder() + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithHitLimit(2) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + hitCountRule.Disable(); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { hitCountRule }); + + await this.Initialize(faultInjector, true); + + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + + ItemResponse? itemResponse = this.container != null + ? await this.container.CreateItemAsync(createdItem) + : null; + Assert.IsNotNull(itemResponse); + + CosmosDiagnostics? cosmosDiagnostics; + + hitCountRule.Enable(); + for (int i = 0; i < 3; i++) + { + cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Read, createdItem) + : null; + Assert.IsNotNull(cosmosDiagnostics); + + if (i < 2) + { + this.ValidateFaultInjectionRuleApplication( + cosmosDiagnostics, + (int)HttpStatusCode.Gone, (int)SubStatusCodes.ServerGenerated410, + hitCountRule); + this.ValidateHitCount(hitCountRule, i + 1); + } + else + { + Assert.IsTrue(cosmosDiagnostics.ToString().Contains("200")); + this.ValidateHitCount(hitCountRule, 2); + } + } + } + finally + { + hitCountRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests endpoint filtering with including primary replica")] + public void FaultInjectionServerErrorRule_IncludePrimaryTest() + { + if (!this.Timeout_FaultInjectionServerErrorRule_IncludePrimaryTest().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_IncludePrimaryTest() + { + await this.Initialize(false); + + List? feedRanges = this.container != null + ? (List)await this.container.GetFeedRangesAsync() : null; + Assert.IsTrue(feedRanges != null && feedRanges.Count > 0); + + JObject item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + + string includePrimaryServerGoneRuleId = "includePrimaryServerGoneRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule includePrimaryServerGoneRule = new FaultInjectionRuleBuilder( + id: includePrimaryServerGoneRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .WithEndpoint( + new FaultInjectionEndpointBuilder("testDb", "test", feedRanges[0]) + .WithReplicaCount(1) + .WithIncludePrimary(true) + .Build()) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.Gone) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + includePrimaryServerGoneRule.Disable(); + this.client?.Dispose(); + + List ruleList = new List { includePrimaryServerGoneRule }; + FaultInjector faultInjector = new FaultInjector(ruleList); + + await this.Initialize(faultInjector, false); + + try + { + includePrimaryServerGoneRule.Enable(); + CosmosDiagnostics? cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Create, item) + : null; + Assert.IsNotNull(cosmosDiagnostics); + + this.ValidateHitCount(includePrimaryServerGoneRule, 1); + this.ValidateFaultInjectionRuleApplication( + cosmosDiagnostics, + (int)HttpStatusCode.Gone, + (int)SubStatusCodes.ServerGenerated410, + includePrimaryServerGoneRule); + + cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Upsert, item) + : null; + Assert.IsNotNull(cosmosDiagnostics); + this.ValidateHitCount(includePrimaryServerGoneRule, 2); + this.ValidateFaultInjectionRuleApplication( + cosmosDiagnostics, + (int)HttpStatusCode.Gone, + (int)SubStatusCodes.ServerGenerated410, + includePrimaryServerGoneRule); + } + finally + { + includePrimaryServerGoneRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests fault injection connection error rules")] + public void FaultInjectionConnectionErrorRule_Test() + { + if (!this.Timeout_FaultInjectionConnectionErrorRule_Test().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionConnectionErrorRule_Test() + { + string ruldId = "connectionErrorRule-close-" + Guid.NewGuid().ToString(); + FaultInjectionRule connectionErrorRule = new FaultInjectionRuleBuilder( + id: ruldId, + condition: + new FaultInjectionConditionBuilder() + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionConnectionErrorType.ReceiveStreamClosed) + .WithInterval(TimeSpan.FromSeconds(1)) + .WithThreshold(1.0) + .Build()) + .WithDuration(TimeSpan.FromSeconds(30)) + .Build(); + + FaultInjector faultInjector = new FaultInjector(new List { connectionErrorRule }); + await this.Initialize(faultInjector, true); + + ChaosInterceptor? interceptor = faultInjector.GetChaosInterceptor() as ChaosInterceptor; + Assert.IsNotNull(interceptor); + + JObject item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + CosmosDiagnostics? cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Create, item) + : null; + Assert.IsNotNull(cosmosDiagnostics); + + FaultInjectionDynamicChannelStore channelStore = interceptor.GetChannelStore(); + Assert.IsTrue(channelStore.GetAllChannels().Count > 0); + List channelGuids = channelStore.GetAllChannelIds(); + + await Task.Delay(TimeSpan.FromSeconds(2)); + + item = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Create, item) + : null; + Assert.IsNotNull(cosmosDiagnostics); + Assert.IsTrue(connectionErrorRule.GetHitCount() >= 1); + + await Task.Delay(TimeSpan.FromSeconds(2)); + + for (int i =0; i < 10; i++) + { + cosmosDiagnostics = this.container != null + ? await this.PerformDocumentOperation(this.container, OperationType.Read, item) + : null; + } + + int hitCount = (int)connectionErrorRule.GetHitCount(); + connectionErrorRule.Disable(); + + Assert.IsNotNull(cosmosDiagnostics); + Assert.IsTrue(connectionErrorRule.GetHitCount() == hitCount); + + bool disposedChannel = false; + foreach (Guid channelGuid in channelGuids) + { + disposedChannel = disposedChannel || channelStore.GetAllChannelIds().Contains(channelGuid); + } + Assert.IsTrue(disposedChannel); + } + + private async Task PerformDocumentOperation(Container testContainer, OperationType operationType, JObject item) + { + try + { + if (operationType == OperationType.Query) + { + QueryRequestOptions queryOptions = new QueryRequestOptions(); + string query = String.Format("SELECT * FROM c WHERE c.Id = '{0}'", item["id"]); + FeedResponse? queryResponse = await testContainer.GetItemQueryIterator(query, requestOptions: queryOptions).ReadNextAsync(); + + return queryResponse.Diagnostics; + } + + if (operationType == OperationType.Read + || operationType == OperationType.Delete + || operationType == OperationType.Replace + || operationType == OperationType.Patch + || operationType == OperationType.Create + || operationType == OperationType.Upsert) + { + if (operationType == OperationType.Read) + { + return (await testContainer.ReadItemAsync((string)item["id"], new Cosmos.PartitionKey((string)item["Pk"]))).Diagnostics; + } + + if (operationType == OperationType.Replace) + { + return (await testContainer.ReplaceItemAsync( + item, + (string)item["id"], + new Cosmos.PartitionKey((string)item["Pk"]))).Diagnostics; + } + + if (operationType == OperationType.Delete) + { + return (await testContainer.DeleteItemAsync((string)item["id"], new Cosmos.PartitionKey((string)item["Pk"]))).Diagnostics; + } + + if (operationType == OperationType.Create) + { + return (await testContainer.CreateItemAsync(item, new Cosmos.PartitionKey((string)item["Pk"]))).Diagnostics; + + } + + if (operationType == OperationType.Upsert) + { + return (await testContainer.UpsertItemAsync(item, new Cosmos.PartitionKey((string)item["Pk"]))).Diagnostics; + } + + if (operationType == OperationType.Patch) + { + List patchOperations = new List + { + PatchOperation.Add("/" + Guid.NewGuid().ToString(), Guid.NewGuid().ToString()) + }; + + return (await testContainer.PatchItemAsync( + (string)item["id"], + new Cosmos.PartitionKey((string)item["Pk"]), + patchOperations)).Diagnostics; + } + } + + throw new ArgumentException("Invalid Operation Type"); + } + catch (CosmosException ex) + { + return ex.Diagnostics; + } + } + + private async Task<(List, List)> GetReadWriteEndpoints(GlobalEndpointManager globalEndpointManager) + { + AccountProperties accountProperties = await globalEndpointManager.GetDatabaseAccountAsync(); + List writeRegions = accountProperties.WritableRegions.Select(region => region.Name).ToList(); + List readRegions = accountProperties.ReadableRegions.Select(region => region.Name).ToList(); + return (writeRegions, readRegions); + } + private void ValidateHitCount(FaultInjectionRule rule, long expectedHitCount) + { + Assert.AreEqual(expectedHitCount, rule.GetHitCount()); + } + + private void ValidateFaultInjectionRuleNotApplied( + CosmosDiagnostics diagnostics, + FaultInjectionRule rule) + { + string diagnosticsString = diagnostics.ToString(); + Assert.AreEqual(0, rule.GetHitCount()); + Assert.AreEqual(0, diagnostics.GetFailedRequestCount()); + Assert.IsTrue( + diagnosticsString.Contains("200") + || diagnosticsString.Contains("201") + || diagnosticsString.Contains("204")); + } + private void ValidateFaultInjectionRuleApplication( + CosmosDiagnostics diagnostics, + int statusCode, + int subStatusCode, + FaultInjectionRule rule) + { + string diagnosticsString = diagnostics.ToString(); + Assert.IsTrue(1 <= rule.GetHitCount()); + Assert.IsTrue(1 <= diagnostics.GetFailedRequestCount()); + Assert.IsTrue(diagnosticsString.Contains(statusCode.ToString())); + Assert.IsTrue(diagnosticsString.Contains(subStatusCode.ToString())); + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.csproj new file mode 100644 index 0000000000..f52fc7cdfd --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.csproj @@ -0,0 +1,45 @@ + + + + enable + true + true + AnyCPU + net6.0 + false + false + Microsoft.Azure.Cosmos.FaultInjection.Tests + Microsoft.Azure.Cosmos.FaultInjection.Tests + true + master + True + $(LangVersion) + + + + + + + + + + + + + + + + + + + + true + true + ..\..\..\..\testkey.snk + + + + x64 + true + + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.sln b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.sln new file mode 100644 index 0000000000..fe4062b23c --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionTests.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34408.163 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FaultInjectionTests", "FaultInjectionTests.csproj", "{F30981C2-BBBD-45AF-AC10-06368322B5F2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F30981C2-BBBD-45AF-AC10-06368322B5F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F30981C2-BBBD-45AF-AC10-06368322B5F2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F30981C2-BBBD-45AF-AC10-06368322B5F2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F30981C2-BBBD-45AF-AC10-06368322B5F2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {03E55460-4462-48E6-8098-3A4FEBB27700} + EndGlobalSection +EndGlobal diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionUnitTests.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionUnitTests.cs new file mode 100644 index 0000000000..a430336523 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionUnitTests.cs @@ -0,0 +1,77 @@ +namespace Microsoft.Azure.Cosmos.FaultInjection.Tests +{ + using System; + + [TestClass] + public class FaultInjectionUnitTests + { + [TestMethod] + [Owner("nalutripician")] + [Description("Tests Fault Injection Rule Builder classes")] + public void FaultInjectionBuilderTests() + { + + string ruleId = "rule_id"; + FaultInjectionCondition faultInjectionCondition = new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .WithConnectionType(FaultInjectionConnectionType.Direct) + .WithRegion("East US") + .WithEndpoint( + new FaultInjectionEndpointBuilder( + databaseName: "db", + containerName: "col", + feedRange: FeedRange.FromPartitionKey(new PartitionKey("test"))) + .WithReplicaCount(3) + .WithIncludePrimary(true) + .Build()) + .Build(); + FaultInjectionRule faultInjectionRule = new FaultInjectionRuleBuilder( + id: ruleId, + condition: faultInjectionCondition, + result: FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ConnectionDelay) + .WithDelay(TimeSpan.FromSeconds(6)) + .WithTimes(1) + .WithSuppressServiceRequest(true) + .Build() + ) + .WithDuration(TimeSpan.FromSeconds(10)) + .WithStartDelay(TimeSpan.FromSeconds(5)) + .WithHitLimit(3) + .Build(); + + //Test FaultInjectionRule + Assert.AreEqual(TimeSpan.FromSeconds(10), faultInjectionRule.GetDuration()); + Assert.AreEqual(TimeSpan.FromSeconds(5), faultInjectionRule.GetStartDelay()); + Assert.AreEqual(3, faultInjectionRule.GetHitLimit()); + Assert.AreEqual(ruleId, faultInjectionRule.GetId()); + Assert.IsTrue(faultInjectionRule.IsEnabled()); + + faultInjectionRule.Disable(); + Assert.IsFalse(faultInjectionRule.IsEnabled()); + faultInjectionRule.Enable(); + Assert.IsTrue(faultInjectionRule.IsEnabled()); + + Assert.AreEqual(0, faultInjectionRule.GetHitCount()); + + //Test FaultInjectionCondition + Assert.AreEqual(FaultInjectionOperationType.CreateItem, faultInjectionRule.GetCondition().GetOperationType()); + Assert.AreEqual(FaultInjectionConnectionType.Direct, faultInjectionRule.GetCondition().GetConnectionType()); + Assert.AreEqual("East US", faultInjectionRule.GetCondition().GetRegion()); + + //Test FaultInjectionEndpoint + PartitionKey test = new PartitionKey("test"); + Assert.AreEqual(FeedRange.FromPartitionKey(test).ToString(), faultInjectionRule.GetCondition().GetEndpoint().GetFeedRange().ToString()); + Assert.AreEqual("dbs/db/colls/col", faultInjectionRule.GetCondition().GetEndpoint().GetResoureName()); + Assert.AreEqual(3, faultInjectionRule.GetCondition().GetEndpoint().GetReplicaCount()); + Assert.IsTrue(faultInjectionRule.GetCondition().GetEndpoint().IsIncludePrimary()); + + //Test FaultInjectionResult + Assert.AreEqual(FaultInjectionServerErrorType.ConnectionDelay, + ((FaultInjectionServerErrorResult)faultInjectionRule.GetResult()).GetServerErrorType()); + Assert.AreEqual(TimeSpan.FromSeconds(6), ((FaultInjectionServerErrorResult)faultInjectionRule.GetResult()).GetDelay()); + Assert.AreEqual(1, ((FaultInjectionServerErrorResult)faultInjectionRule.GetResult()).GetTimes()); + Assert.IsTrue(((FaultInjectionServerErrorResult)faultInjectionRule.GetResult()).GetSuppressServiceRequests()); + + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Usings.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Usings.cs new file mode 100644 index 0000000000..80adca60ee --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Usings.cs @@ -0,0 +1,3 @@ +global using Microsoft.VisualStudio.TestTools.UnitTesting; +global using Microsoft.Azure.Cosmos.FaultInjection; +global using Microsoft.Azure.Cosmos; \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs new file mode 100644 index 0000000000..902bb7fe54 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs @@ -0,0 +1,68 @@ +namespace Microsoft.Azure.Cosmos.FaultInjection.Tests.Utils +{ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Cosmos.Fluent; + + internal static class TestCommon + { + public const string Endpoint = ""; + public const string AuthKey = ""; + public const string EndpointMultiRegion = ""; + public const string AuthKeyMultiRegion = ""; + + internal static CosmosClient CreateCosmosClient( + bool useGateway, + FaultInjector injector, + bool multiRegion, + List? preferredRegion = null, + Action? customizeClientBuilder = null) + { + CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(multiRegion); + cosmosClientBuilder.WithFaultInjection(injector.GetChaosInterceptorFactory()); + + customizeClientBuilder?.Invoke(cosmosClientBuilder); + + if (useGateway) + { + cosmosClientBuilder.WithConnectionModeGateway(); + } + + if (preferredRegion != null) + { + cosmosClientBuilder.WithApplicationPreferredRegions(preferredRegion); + } + + return cosmosClientBuilder.Build(); + } + + internal static CosmosClient CreateCosmosClient( + bool useGateway, + bool multiRegion, + Action? customizeClientBuilder = null) + { + CosmosClientBuilder cosmosClientBuilder = GetDefaultConfiguration(multiRegion); + + customizeClientBuilder?.Invoke(cosmosClientBuilder); + + if (useGateway) + { + cosmosClientBuilder.WithConnectionModeGateway(); + } + + return cosmosClientBuilder.Build(); + } + + internal static CosmosClientBuilder GetDefaultConfiguration( + bool multiRegion, + string? accountEndpointOverride = null) + { + CosmosClientBuilder clientBuilder = new CosmosClientBuilder( + accountEndpoint: accountEndpointOverride + ?? (multiRegion ? EndpointMultiRegion : Endpoint), + authKeyOrResourceToken: multiRegion ? AuthKeyMultiRegion : AuthKey); + + return clientBuilder; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 7d5a572754..873f09fa51 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -117,7 +117,9 @@ internal partial class DocumentClient : IDisposable, IAuthorizationTokenProvider //Fault Injection private readonly IChaosInterceptorFactory chaosInterceptorFactory; - private IChaosInterceptor chaosInterceptor; + private readonly IChaosInterceptor chaosInterceptor; + + private bool isChaosInterceptorInititalized = false; //Auth internal readonly AuthorizationTokenProvider cosmosAuthorization; @@ -490,6 +492,7 @@ internal DocumentClient(Uri serviceEndpoint, this.IsLocalQuorumConsistency = isLocalQuorumConsistency; this.initTaskCache = new AsyncCacheNonBlocking(cancellationToken: this.cancellationTokenSource.Token); this.chaosInterceptorFactory = chaosInterceptorFactory; + this.chaosInterceptor = chaosInterceptorFactory?.CreateInterceptor(this); this.Initialize( serviceEndpoint: serviceEndpoint, @@ -1017,14 +1020,6 @@ internal virtual void Initialize(Uri serviceEndpoint, // Always called from under the lock except when called from Intilialize method during construction. private async Task GetInitializationTaskAsync(IStoreClientFactory storeClientFactory) { - //Create the chaos interceptor if using fault injection - //Creating the chaos interceptor requires async calls, so we do it here instead of in the constructor - //This must also be done before creating the storeClientFactory for direct mode - if (this.chaosInterceptorFactory != null) - { - this.chaosInterceptor = await this.chaosInterceptorFactory.CreateInterceptorAsync(this); - } - await this.InitializeGatewayConfigurationReaderAsync(); if (this.desiredConsistencyLevel.HasValue) @@ -1593,6 +1588,12 @@ internal virtual async Task EnsureValidClientAsync(ITrace trace) childTrace.AddDatum("initializeTask failed", e); throw; } + + if (this.chaosInterceptorFactory != null && !this.isChaosInterceptorInititalized) + { + this.isChaosInterceptorInititalized = true; + await this.chaosInterceptorFactory.ConfigureChaosInterceptorAsync(); + } } } diff --git a/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs index 85aafeb1e3..a6f905ca9e 100644 --- a/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs +++ b/Microsoft.Azure.Cosmos/src/FaultInjection/IChaosInterceptorFactory.cs @@ -16,6 +16,11 @@ internal interface IChaosInterceptorFactory /// Creates the IChaosInterceptor interceptor that will be used to inject fault injection rules. /// /// - public Task CreateInterceptorAsync(DocumentClient documentClient); + public IChaosInterceptor CreateInterceptor(DocumentClient documentClient); + + /// + /// Configures Intercetor + /// + public Task ConfigureChaosInterceptorAsync(); } } \ No newline at end of file From 0589e8a30dd99e0067a569d827f4c04404244862 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 9 Feb 2024 07:04:48 -0800 Subject: [PATCH 283/337] CosmosClientOptions: Adds Private Custom Account Endpoints (#4265) * Code changes to add regional endpoints for account metadata calls. * Code changes to refactor some codes. * Code changes to add unit tests. * Code changes to make minor code clean-up. * Code changes to fix tests. Refactored API. * Code changes to refactor the enumeration logic inside global endpoint manager. * Code changes to address review comments. * Code changes to fix minor API parameter. * Code changes to update the API naming. * Code changes to update some attribute names. * Code changes to refactor service endpoint creation logic. * Code changes to address review comments. * Code changes to address review comments. * Code changes to update the API contract. * Cosmetic code changes. * Code changes to address review comments. --- .../src/ConnectionPolicy.cs | 41 +++++ .../src/CosmosClientOptions.cs | 41 +++++ .../src/Fluent/CosmosClientBuilder.cs | 35 ++++ .../src/GatewayAccountReader.cs | 2 +- .../src/Routing/GlobalEndpointManager.cs | 132 ++++++++++----- .../Contracts/DotNetSDKAPI.json | 24 +++ .../CosmosClientOptionsUnitTests.cs | 25 ++- .../CosmosClientTests.cs | 2 +- .../GatewayAccountReaderTests.cs | 152 ++++++++++++++++++ .../GlobalEndpointManagerTest.cs | 10 ++ 10 files changed, 415 insertions(+), 49 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index bd1b23b16c..b54c4837c4 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -29,6 +29,7 @@ internal sealed class ConnectionPolicy private Protocol connectionProtocol; private ObservableCollection preferredLocations; + private ObservableCollection accountInitializationCustomEndpoints; /// /// Initializes a new instance of the class to connect to the Azure Cosmos DB service. @@ -43,6 +44,7 @@ public ConnectionPolicy() this.MediaReadMode = MediaReadMode.Buffered; this.UserAgentContainer = new UserAgentContainer(clientId: 0); this.preferredLocations = new ObservableCollection(); + this.accountInitializationCustomEndpoints = new ObservableCollection(); this.EnableEndpointDiscovery = true; this.MaxConnectionLimit = defaultMaxConcurrentConnectionLimit; this.RetryOptions = new RetryOptions(); @@ -90,6 +92,27 @@ public void SetPreferredLocations(IReadOnlyList regions) } } + /// + /// Sets the custom private endpoints required to fetch account information from + /// private domain names. + /// + /// An instance of containing the custom DNS endpoints + /// provided by the customer. + public void SetAccountInitializationCustomEndpoints( + IEnumerable customEndpoints) + { + if (customEndpoints == null) + { + throw new ArgumentNullException(nameof(customEndpoints)); + } + + this.accountInitializationCustomEndpoints.Clear(); + foreach (Uri endpoint in customEndpoints) + { + this.accountInitializationCustomEndpoints.Add(endpoint); + } + } + /// /// Gets or sets the maximum number of concurrent fanout requests sent to the Azure Cosmos DB service. /// @@ -270,6 +293,24 @@ public Collection PreferredLocations } } + /// + /// Gets the custom private endpoints for geo-replicated database accounts in the Azure Cosmos DB service. + /// + /// + /// + /// During the CosmosClient initialization the account information, including the available regions, is obtained from the . + /// Should the global endpoint become inaccessible, the CosmosClient will attempt to obtain the account information issuing requests to the custom endpoints + /// provided in the customAccountEndpoints list. + /// + /// + public Collection AccountInitializationCustomEndpoints + { + get + { + return this.accountInitializationCustomEndpoints; + } + } + /// /// Gets or sets the flag to enable endpoint discovery for geo-replicated database accounts in the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 293712a64e..0c2d73a315 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -191,6 +191,42 @@ public string ApplicationName /// /// High availability on regional outages public IReadOnlyList ApplicationPreferredRegions { get; set; } + + /// + /// Gets and sets the custom endpoints to use for account initialization for geo-replicated database accounts in the Azure Cosmos DB service. + /// + /// + /// + /// During the CosmosClient initialization the account information, including the available regions, is obtained from the . + /// Should the global endpoint become inaccessible, the CosmosClient will attempt to obtain the account information issuing requests to the custom endpoints provided in . + /// + /// + /// Nevertheless, this parameter remains optional and is recommended for implementation when a customer has configured an endpoint with a custom DNS hostname + /// (instead of accountname-region.documents.azure.com) etc. for their Cosmos DB account. + /// + /// + /// See also Diagnose + /// and troubleshoot the availability of Cosmos SDKs for more details. + /// + /// + /// + /// + /// () + /// { + /// new Uri("custom.p-1.documents.azure.com"), + /// new Uri("custom.p-2.documents.azure.com") + /// } + /// }; + /// + /// CosmosClient client = new CosmosClient("endpoint", "key", clientOptions); + /// ]]> + /// + /// + /// High availability on regional outages + public IEnumerable AccountInitializationCustomEndpoints { get; set; } /// /// Get or set the maximum number of concurrent connections allowed for the target @@ -847,6 +883,11 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) List mappedRegions = this.ApplicationPreferredRegions.Select(s => mapper.GetCosmosDBRegionName(s)).ToList(); connectionPolicy.SetPreferredLocations(mappedRegions); + } + + if (this.AccountInitializationCustomEndpoints != null) + { + connectionPolicy.SetAccountInitializationCustomEndpoints(this.AccountInitializationCustomEndpoints); } if (this.MaxRetryAttemptsOnRateLimitedRequests != null) diff --git a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs index a4d0381e6c..c56fe7feda 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs @@ -308,6 +308,41 @@ public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList return this; } + /// + /// Sets the custom endpoints to use for account initialization for geo-replicated database accounts in the Azure Cosmos DB service. + /// During the CosmosClient initialization the account information, including the available regions, is obtained from the . + /// Should the global endpoint become inaccessible, the CosmosClient will attempt to obtain the account information issuing requests to the custom endpoints + /// provided in the customAccountEndpoints list. + /// + /// An instance of of Uri containing the custom private endpoints for the cosmos db account. + /// + /// This function is optional and is recommended for implementation when a customer has configured one or more endpoints with a custom DNS + /// hostname (instead of accountname-region.documents.azure.com) etc. for their Cosmos DB account. + /// + /// + /// The example below creates a new instance of with the regional endpoints. + /// + /// () + /// { + /// new Uri("https://region-1.documents-test.windows-int.net:443/"), + /// new Uri("https://region-2.documents-test.windows-int.net:443/") + /// }); + /// CosmosClient client = cosmosClientBuilder.Build(); + /// ]]> + /// + /// + /// The current . + /// + public CosmosClientBuilder WithCustomAccountEndpoints(IEnumerable customAccountEndpoints) + { + this.clientOptions.AccountInitializationCustomEndpoints = customAccountEndpoints; + return this; + } + /// /// Limits the operations to the provided endpoint on the CosmosClientBuilder constructor. /// diff --git a/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs b/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs index 5413103fee..1a2c3e14a4 100644 --- a/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs +++ b/Microsoft.Azure.Cosmos/src/GatewayAccountReader.cs @@ -5,7 +5,6 @@ namespace Microsoft.Azure.Cosmos { using System; - using System.Globalization; using System.Net.Http; using System.Threading; using System.Threading.Tasks; @@ -89,6 +88,7 @@ public async Task InitializeReaderAsync() AccountProperties databaseAccount = await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( defaultEndpoint: this.serviceEndpoint, locations: this.connectionPolicy.PreferredLocations, + accountInitializationCustomEndpoints: this.connectionPolicy.AccountInitializationCustomEndpoints, getDatabaseAccountFn: this.GetDatabaseAccountAsync, cancellationToken: this.cancellationToken); diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index db1a01cd61..2d60e57adb 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -116,13 +116,15 @@ public Uri GetHubUri() /// public static async Task GetDatabaseAccountFromAnyLocationsAsync( Uri defaultEndpoint, - IList? locations, + IList? locations, + IList? accountInitializationCustomEndpoints, Func> getDatabaseAccountFn, CancellationToken cancellationToken) { using (GetAccountPropertiesHelper threadSafeGetAccountHelper = new GetAccountPropertiesHelper( defaultEndpoint, - locations?.GetEnumerator(), + locations, + accountInitializationCustomEndpoints, getDatabaseAccountFn, cancellationToken)) { @@ -137,7 +139,8 @@ private class GetAccountPropertiesHelper : IDisposable { private readonly CancellationTokenSource CancellationTokenSource; private readonly Uri DefaultEndpoint; - private readonly IEnumerator? Locations; + private readonly bool LimitToGlobalEndpointOnly; + private readonly IEnumerator ServiceEndpointEnumerator; private readonly Func> GetDatabaseAccountFn; private readonly List TransientExceptions = new List(); private AccountProperties? AccountProperties = null; @@ -146,24 +149,31 @@ private class GetAccountPropertiesHelper : IDisposable public GetAccountPropertiesHelper( Uri defaultEndpoint, - IEnumerator? locations, + IList? locations, + IList? accountInitializationCustomEndpoints, Func> getDatabaseAccountFn, CancellationToken cancellationToken) { this.DefaultEndpoint = defaultEndpoint; - this.Locations = locations; - this.GetDatabaseAccountFn = getDatabaseAccountFn; - this.CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + this.LimitToGlobalEndpointOnly = (locations == null || locations.Count == 0) && (accountInitializationCustomEndpoints == null || accountInitializationCustomEndpoints.Count == 0); + this.GetDatabaseAccountFn = getDatabaseAccountFn; + this.CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + this.ServiceEndpointEnumerator = GetAccountPropertiesHelper + .GetServiceEndpoints( + defaultEndpoint, + locations, + accountInitializationCustomEndpoints) + .GetEnumerator(); } public async Task GetAccountPropertiesAsync() { - // If there are no preferred regions then just wait for the global endpoint results - if (this.Locations == null) + // If there are no preferred regions or private endpoints, then just wait for the global endpoint results + if (this.LimitToGlobalEndpointOnly) { return await this.GetOnlyGlobalEndpointAsync(); } - + Task globalEndpointTask = this.GetAndUpdateAccountPropertiesAsync(this.DefaultEndpoint); // Start a timer to start secondary requests in parallel. @@ -219,9 +229,9 @@ public async Task GetAccountPropertiesAsync() private async Task GetOnlyGlobalEndpointAsync() { - if (this.Locations != null) + if (!this.LimitToGlobalEndpointOnly) { - throw new ArgumentException("GetOnlyGlobalEndpointAsync should only be called if there are no other regions"); + throw new ArgumentException("GetOnlyGlobalEndpointAsync should only be called if there are no other private endpoints or regions"); } await this.GetAndUpdateAccountPropertiesAsync(this.DefaultEndpoint); @@ -250,52 +260,53 @@ private async Task GetOnlyGlobalEndpointAsync() } /// - /// This is done in a thread safe way to allow multiple tasks to iterate over the - /// list of locations. + /// This is done in a thread safe way to allow multiple tasks to iterate over the list of service endpoints. /// private async Task TryGetAccountPropertiesFromAllLocationsAsync() - { - while (this.TryMoveNextLocationThreadSafe( - out string? location)) + { + while (this.TryMoveNextServiceEndpointhreadSafe( + out Uri? serviceEndpoint)) { - if (location == null) + if (serviceEndpoint == null) { - DefaultTrace.TraceCritical("GlobalEndpointManager: location is null for TryMoveNextLocationThreadSafe"); + DefaultTrace.TraceCritical("GlobalEndpointManager: serviceEndpoint is null for TryMoveNextServiceEndpointhreadSafe."); return; } - await this.TryGetAccountPropertiesFromRegionalEndpointsAsync(location); + await this.GetAndUpdateAccountPropertiesAsync( + endpoint: serviceEndpoint); } - } - - private bool TryMoveNextLocationThreadSafe( - out string? location) + } + + /// + /// We first iterate through all the private endpoints to fetch the account information. + /// If all the attempt fails to fetch the metadata from the private endpoints, we will + /// attempt to retrieve the account information from the regional endpoints constructed + /// using the preferred regions list. + /// + /// An instance of that will contain the service endpoint. + /// A boolean flag indicating if the was advanced in a thread safe manner. + private bool TryMoveNextServiceEndpointhreadSafe( + out Uri? serviceEndpoint) { - if (this.CancellationTokenSource.IsCancellationRequested - || this.Locations == null) + if (this.CancellationTokenSource.IsCancellationRequested) { - location = null; + serviceEndpoint = null; return false; } - lock (this.Locations) + lock (this.ServiceEndpointEnumerator) { - if (!this.Locations.MoveNext()) + if (!this.ServiceEndpointEnumerator.MoveNext()) { - location = null; + serviceEndpoint = null; return false; } - location = this.Locations.Current; + serviceEndpoint = this.ServiceEndpointEnumerator.Current; return true; } - } - - private Task TryGetAccountPropertiesFromRegionalEndpointsAsync(string location) - { - return this.GetAndUpdateAccountPropertiesAsync( - LocationHelper.GetLocationEndpoint(this.DefaultEndpoint, location)); - } + } private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint) { @@ -305,7 +316,7 @@ private async Task GetAndUpdateAccountPropertiesAsync(Uri endpoint) { lock (this.TransientExceptions) { - this.TransientExceptions.Add(new OperationCanceledException("GlobalEndpointManager: Get account information canceled")); + this.TransientExceptions.Add(new OperationCanceledException($"GlobalEndpointManager: Get account information canceled for URI: {endpoint}")); } return; @@ -349,6 +360,40 @@ private static bool IsNonRetriableException(Exception exception) return false; } + /// + /// Returns an instance of containing the private and regional service endpoints to iterate over. + /// + /// An instance of containing the default global endpoint. + /// An instance of containing the preferred serviceEndpoint names. + /// An instance of containing the custom private endpoints. + /// An instance of containing the service endpoints. + private static IEnumerable GetServiceEndpoints( + Uri defaultEndpoint, + IList? locations, + IList? accountInitializationCustomEndpoints) + { + // We first iterate over all the private endpoints and yield return them. + if (accountInitializationCustomEndpoints?.Count > 0) + { + foreach (Uri customEndpoint in accountInitializationCustomEndpoints) + { + // Yield return all of the custom private endpoints first. + yield return customEndpoint; + } + } + + // The next step is to iterate over the preferred locations, construct and yield return the regional endpoints one by one. + // The regional endpoints will be constructed by appending the preferred region name as a suffix to the default global endpoint. + if (locations?.Count > 0) + { + foreach (string location in locations) + { + // Yield return all of the regional endpoints once the private custom endpoints are visited. + yield return LocationHelper.GetLocationEndpoint(defaultEndpoint, location); + } + } + } + public void Dispose() { if (Interlocked.Increment(ref this.disposeCounter) == 1) @@ -390,7 +435,7 @@ public ReadOnlyDictionary GetAvailableReadEndpointsByLocation() } /// - /// Returns location corresponding to the endpoint + /// Returns serviceEndpoint corresponding to the endpoint /// /// public string GetLocation(Uri endpoint) @@ -530,7 +575,7 @@ private async void StartLocationBackgroundRefreshLoop() return; } - DefaultTrace.TraceCritical("GlobalEndpointManager: StartLocationBackgroundRefreshWithTimer() - Unable to refresh database account from any location. Exception: {0}", ex.ToString()); + DefaultTrace.TraceCritical("GlobalEndpointManager: StartLocationBackgroundRefreshWithTimer() - Unable to refresh database account from any serviceEndpoint. Exception: {0}", ex.ToString()); } // Call itself to create a loop to continuously do background refresh every 5 minutes @@ -549,7 +594,7 @@ private void OnPreferenceChanged(object sender, NotifyCollectionChangedEventArgs } /// - /// Thread safe refresh account and location info. + /// Thread safe refresh account and serviceEndpoint info. /// private async Task RefreshDatabaseAccountInternalAsync(bool forceRefresh) { @@ -607,7 +652,8 @@ internal async Task GetDatabaseAccountAsync(bool forceRefresh obsoleteValue: null, singleValueInitFunc: () => GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( this.defaultEndpoint, - this.connectionPolicy.PreferredLocations, + this.connectionPolicy.PreferredLocations, + this.connectionPolicy.AccountInitializationCustomEndpoints, this.GetDatabaseAccountAsync, this.cancellationTokenSource.Token), cancellationToken: this.cancellationTokenSource.Token, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 3ce587dcd3..d7335051ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -2770,6 +2770,18 @@ ], "MethodInfo": "Microsoft.Azure.Cosmos.CosmosSerializer Serializer;CanRead:True;CanWrite:True;Microsoft.Azure.Cosmos.CosmosSerializer get_Serializer();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Serializer(Microsoft.Azure.Cosmos.CosmosSerializer);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Collections.Generic.IEnumerable`1[System.Uri] AccountInitializationCustomEndpoints": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.IEnumerable`1[System.Uri] AccountInitializationCustomEndpoints;CanRead:True;CanWrite:True;System.Collections.Generic.IEnumerable`1[System.Uri] get_AccountInitializationCustomEndpoints();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_AccountInitializationCustomEndpoints(System.Collections.Generic.IEnumerable`1[System.Uri]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.IEnumerable`1[System.Uri] get_AccountInitializationCustomEndpoints()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Collections.Generic.IEnumerable`1[System.Uri] get_AccountInitializationCustomEndpoints();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Collections.Generic.IReadOnlyList`1[System.String] ApplicationPreferredRegions": { "Type": "Property", "Attributes": [], @@ -2993,6 +3005,13 @@ "Attributes": [], "MethodInfo": "[Void .ctor(), Void .ctor()]" }, + "Void set_AccountInitializationCustomEndpoints(System.Collections.Generic.IEnumerable`1[System.Uri])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_AccountInitializationCustomEndpoints(System.Collections.Generic.IEnumerable`1[System.Uri]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_AllowBulkExecution(Boolean)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -4603,6 +4622,11 @@ "Attributes": [], "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithContentResponseOnWrite(Boolean);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithCustomAccountEndpoints(System.Collections.Generic.IEnumerable`1[System.Uri])": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithCustomAccountEndpoints(System.Collections.Generic.IEnumerable`1[System.Uri]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Microsoft.Azure.Cosmos.Fluent.CosmosClientBuilder WithCustomSerializer(Microsoft.Azure.Cosmos.CosmosSerializer)": { "Type": "Method", "Attributes": [], diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 274723f24e..293c3b14ab 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -162,7 +162,13 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsFalse(policy.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); - IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; + IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; + ISet regionalEndpoints = new HashSet() + { + new Uri("https://testfed2.documents-test.windows-int.net:443/"), + new Uri("https://testfed4.documents-test.windows-int.net:443/") + }; + //Verify Direct Mode settings cosmosClientBuilder = new CosmosClientBuilder( accountEndpoint: endpoint, @@ -174,7 +180,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() maxTcpConnectionsPerEndpoint, portReuseMode, enableTcpConnectionEndpointRediscovery) - .WithApplicationPreferredRegions(preferredLocations) + .WithApplicationPreferredRegions(preferredLocations) + .WithCustomAccountEndpoints(regionalEndpoints) .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() { DisableDistributedTracing = false, @@ -194,7 +201,8 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(maxTcpConnectionsPerEndpoint, clientOptions.MaxTcpConnectionsPerEndpoint); Assert.AreEqual(portReuseMode, clientOptions.PortReuseMode); Assert.IsTrue(clientOptions.EnableTcpConnectionEndpointRediscovery); - CollectionAssert.AreEqual(preferredLocations.ToArray(), clientOptions.ApplicationPreferredRegions.ToArray()); + CollectionAssert.AreEqual(preferredLocations.ToArray(), clientOptions.ApplicationPreferredRegions.ToArray()); + CollectionAssert.AreEqual(regionalEndpoints.ToArray(), clientOptions.AccountInitializationCustomEndpoints.ToArray()); Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.CosmosClientTelemetryOptions.CosmosThresholdOptions.PointOperationLatencyThreshold); Assert.AreEqual(TimeSpan.FromMilliseconds(100), clientOptions.CosmosClientTelemetryOptions.CosmosThresholdOptions.NonPointOperationLatencyThreshold); Assert.IsFalse(clientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing); @@ -208,6 +216,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(portReuseMode, policy.PortReuseMode); Assert.IsTrue(policy.EnableTcpConnectionEndpointRediscovery); CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); + CollectionAssert.AreEqual(regionalEndpoints.ToArray(), policy.AccountInitializationCustomEndpoints.ToArray()); } /// @@ -331,6 +340,13 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg Regions.NorthCentralUS, Regions.WestUS, Regions.EastAsia, + }) + .WithCustomAccountEndpoints( + new HashSet() + { + new Uri("https://testfed2.documents-test.windows-int.net:443/"), + new Uri("https://testfed3.documents-test.windows-int.net:443/"), + new Uri("https://testfed4.documents-test.windows-int.net:443/"), }); CosmosClientOptions clientOptions = cosmosClientBuilder.Build().ClientOptions; @@ -348,7 +364,8 @@ public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredReg Assert.IsFalse(clientOptions.AllowBulkExecution); Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); - Assert.IsNotNull(clientOptions.ApplicationPreferredRegions); + Assert.IsNotNull(clientOptions.ApplicationPreferredRegions); + Assert.IsNotNull(clientOptions.AccountInitializationCustomEndpoints); } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs index 6740001f53..353e94b642 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs @@ -138,7 +138,7 @@ public async Task InvalidKey_ExceptionFullStacktrace(string endpoint, string key } catch (Exception ex) { - Assert.IsTrue(ex.StackTrace.Contains("GatewayAccountReader.GetDatabaseAccountAsync"), ex.StackTrace); + Assert.IsTrue(ex.StackTrace.Contains("GatewayAccountReader.InitializeReaderAsync"), ex.StackTrace); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs index cf54b12a52..41e447ac35 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAccountReaderTests.cs @@ -16,6 +16,7 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; + using System.Collections.Generic; /// /// Tests for . @@ -100,6 +101,157 @@ public void DocumentClient_BuildHttpClientFactory_WithFactory() .Verify(f => f(), Times.Once); } + [TestMethod] + [Owner("dkunda")] + [DataRow(true, DisplayName = "Validate that when custom endpoints are provided in the connection policy, the request will be retried in the regional endpoints.")] + [DataRow(false, DisplayName = "Validate that when custom endpoints are not provided in the connection policy, the request will be failed in the primary endpoint.")] + public async Task InitializeReaderAsync_WhenCustomEndpointsProvided_ShouldRetryWithPrivateCustomEndpointsWhenPrimaryFails( + bool customEndpointsProvided) + { + string accountPropertiesResponse = "{\r\n \"_self\": \"\",\r\n \"id\": \"localhost\",\r\n \"_rid\": \"127.0.0.1\",\r\n \"media\": \"//media/\",\r\n \"addresses\": \"//addresses/\",\r\n \"_dbs\": \"//dbs/\",\r\n \"writableLocations\": [\r\n {\r\n \"name\": \"South Central US\",\r\n \"databaseAccountEndpoint\": \"https://127.0.0.1:8081/\"\r\n }" + + "\r\n ],\r\n \"readableLocations\": [\r\n {\r\n \"name\": \"South Central US\",\r\n \"databaseAccountEndpoint\": \"https://127.0.0.1:8081/\"\r\n }\r\n ],\r\n \"enableMultipleWriteLocations\": false,\r\n \"userReplicationPolicy\": {\r\n \"asyncReplication\": false,\r\n \"minReplicaSetSize\": 1,\r\n \"maxReplicasetSize\": 4\r\n },\r\n \"userConsistencyPolicy\": {\r\n " + + "\"defaultConsistencyLevel\": \"Session\"\r\n },\r\n \"systemReplicationPolicy\": {\r\n \"minReplicaSetSize\": 1,\r\n \"maxReplicasetSize\": 4\r\n },\r\n \"readPolicy\": {\r\n \"primaryReadCoefficient\": 1,\r\n \"secondaryReadCoefficient\": 1\r\n },\r\n \"queryEngineConfiguration\": \"{\\\"maxSqlQueryInputLength\\\":262144,\\\"maxJoinsPerSqlQuery\\\":5," + + "\\\"maxLogicalAndPerSqlQuery\\\":500,\\\"maxLogicalOrPerSqlQuery\\\":500,\\\"maxUdfRefPerSqlQuery\\\":10,\\\"maxInExpressionItemsCount\\\":16000,\\\"queryMaxInMemorySortDocumentCount\\\":500,\\\"maxQueryRequestTimeoutFraction\\\":0.9,\\\"sqlAllowNonFiniteNumbers\\\":false,\\\"sqlAllowAggregateFunctions\\\":true,\\\"sqlAllowSubQuery\\\":true,\\\"sqlAllowScalarSubQuery\\\":true,\\\"allowNewKeywords\\\":true,\\\"" + + "sqlAllowLike\\\":true,\\\"sqlAllowGroupByClause\\\":true,\\\"maxSpatialQueryCells\\\":12,\\\"spatialMaxGeometryPointCount\\\":256,\\\"sqlDisableOptimizationFlags\\\":0,\\\"sqlAllowTop\\\":true,\\\"enableSpatialIndexing\\\":true}\"\r\n}"; + + Uri globalEndpoint = new("https://testfed1.documents-test.windows-int.net:443/"); + Uri privateEndpoint1 = new ("https://testfed2.documents-test.windows-int.net:443/"); + Uri privateEndpoint2 = new ("https://testfed3.documents-test.windows-int.net:443/"); + Uri privateEndpoint3 = new ("https://testfed4.documents-test.windows-int.net:443/"); + Uri endpointSucceeded = default; + + StringContent content = new(accountPropertiesResponse); + HttpResponseMessage responseMessage = new() + { + StatusCode = HttpStatusCode.OK, + Content = content, + }; + + Mock mockHttpClient = new(); + + GatewayAccountReaderTests.SetupMockToThrowException( + mockHttpClient: mockHttpClient, + endpoints: new List() + { + globalEndpoint, + privateEndpoint1, + privateEndpoint2, + }); + + mockHttpClient + .Setup(x => x.GetAsync( + privateEndpoint3, + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + Uri serviceEndpoint, + INameValueCollection _, + ResourceType _, + HttpTimeoutPolicy _, + IClientSideRequestStatistics _, + CancellationToken _) => endpointSucceeded = serviceEndpoint) + .ReturnsAsync(responseMessage); + + ConnectionPolicy connectionPolicy = new() + { + ConnectionMode = ConnectionMode.Direct, + }; + + if (customEndpointsProvided) + { + connectionPolicy.SetAccountInitializationCustomEndpoints( + new HashSet() + { + privateEndpoint1, + privateEndpoint2, + privateEndpoint3, + }); + } + + GatewayAccountReader accountReader = new GatewayAccountReader( + serviceEndpoint: globalEndpoint, + cosmosAuthorization: Mock.Of(), + connectionPolicy: connectionPolicy, + httpClient: mockHttpClient.Object); + + if (customEndpointsProvided) + { + AccountProperties accountProperties = await accountReader.InitializeReaderAsync(); + + Assert.IsNotNull(accountProperties); + Assert.AreEqual("localhost", accountProperties.Id); + Assert.AreEqual("127.0.0.1", accountProperties.ResourceId); + Assert.AreEqual(endpointSucceeded, privateEndpoint3); + } + else + { + Exception exception = await Assert.ThrowsExceptionAsync(() => accountReader.InitializeReaderAsync()); + Assert.IsNull(endpointSucceeded); + Assert.IsNotNull(exception); + Assert.AreEqual("Service is Unavailable at the Moment.", exception.Message); + } + } + + [TestMethod] + [Owner("dkunda")] + public async Task InitializeReaderAsync_WhenRegionalEndpointsProvided_ShouldThrowAggregateExceptionWithAllEndpointsFail() + { + Mock mockHttpClient = new(); + mockHttpClient + .Setup(x => x.GetAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Service is Unavailable at the Moment.")); + + ConnectionPolicy connectionPolicy = new() + { + ConnectionMode = ConnectionMode.Direct, + }; + + connectionPolicy.SetAccountInitializationCustomEndpoints( + new HashSet() + { + new ("https://testfed2.documents-test.windows-int.net:443/"), + new ("https://testfed3.documents-test.windows-int.net:443/"), + new ("https://testfed4.documents-test.windows-int.net:443/"), + }); + + GatewayAccountReader accountReader = new GatewayAccountReader( + serviceEndpoint: new Uri("https://testfed1.documents-test.windows-int.net:443/"), + cosmosAuthorization: Mock.Of(), + connectionPolicy: connectionPolicy, + httpClient: mockHttpClient.Object); + + AggregateException exception = await Assert.ThrowsExceptionAsync(() => accountReader.InitializeReaderAsync()); + Assert.IsNotNull(exception); + Assert.AreEqual("Service is Unavailable at the Moment.", exception.InnerException.Message); + } + + private static void SetupMockToThrowException( + Mock mockHttpClient, + IList endpoints) + { + foreach(Uri endpoint in endpoints) + { + mockHttpClient + .Setup(x => x.GetAsync( + endpoint, + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Service is Unavailable at the Moment.")); + } + } + public class CustomMessageHandler : HttpMessageHandler { protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs index 30c0d4e457..931e1fc8b4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GlobalEndpointManagerTest.cs @@ -118,6 +118,7 @@ await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => throw new Exception("The operation should be canceled and never make the network call."), cancellationTokenSource.Token); @@ -147,6 +148,7 @@ await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => { count++; @@ -177,6 +179,7 @@ await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: async (uri) => { count++; @@ -208,6 +211,7 @@ await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => { count++; @@ -239,6 +243,7 @@ await GlobalEndpointManager.GetDatabaseAccountFromAnyLocationsAsync( "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => { count++; @@ -307,6 +312,7 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => slowPrimaryRegionHelper.RequestHelper(uri), cancellationToken: default); @@ -329,6 +335,7 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => slowPrimaryRegionHelper.RequestHelper(uri), cancellationToken: default); stopwatch.Stop(); @@ -352,6 +359,7 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => slowPrimaryRegionHelper.RequestHelper(uri), cancellationToken: default); @@ -373,6 +381,7 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() "southeastasia", "northcentralus" }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => slowPrimaryRegionHelper.RequestHelper(uri), cancellationToken: default); @@ -398,6 +407,7 @@ public async Task GetDatabaseAccountFromAnyLocationsMockTestAsync() "westus6", "westus7", }, + accountInitializationCustomEndpoints: null, getDatabaseAccountFn: (uri) => slowPrimaryRegionHelper.RequestHelper(uri), cancellationToken: default); From caa1aebe846cdfd604a82d4dc77659dc9ee31b02 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 13 Feb 2024 22:12:12 +0530 Subject: [PATCH 284/337] Distributed Tracing: Refactors code to rename net.peer.name attribute to server.address (#4316) * Marking Distributed tracing feature as stable and changed an attribute name * remove it from emulator test * marked stable as false * fix tests * updated changefeedxml * remove statuscode and subsstatus from staic list * regenerated xml files * remove event counters events --- .../OpenTelemetryAttributeKeys.cs | 2 +- .../OpenTelemetryCoreRecorder.cs | 2 +- .../OpenTelemetryRecorderFactory.cs | 3 +- ...iterBaselineTests.BatchOperationsAsync.xml | 6 +- ...riterBaselineTests.BulkOperationsAsync.xml | 606 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 126 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 24 +- ...neTests.PointOperationsExceptionsAsync.xml | 36 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 168 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 96 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 12 +- ...selineTests.StreamPointOperationsAsync.xml | 24 +- ...aselineTests.TypedPointOperationsAsync.xml | 24 +- .../Tracing/AssertActivity.cs | 4 +- .../Tracing/CustomListener.cs | 4 +- 15 files changed, 567 insertions(+), 570 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs index 14053761f4..9e71e5edbe 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryAttributeKeys.cs @@ -16,7 +16,7 @@ internal sealed class OpenTelemetryAttributeKeys public const string DbSystemName = "db.system"; public const string DbName = "db.name"; public const string DbOperation = "db.operation"; - public const string NetPeerName = "net.peer.name"; + public const string ServerAddress = "server.address"; // Cosmos Db Specific public const string ClientId = "db.cosmosdb.client_id"; diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 7679640709..8659286b3d 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -146,7 +146,7 @@ public void Record( // Other information this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb); this.scope.AddAttribute(OpenTelemetryAttributeKeys.MachineId, VmMetadataApiHandler.GetMachineId()); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.NetPeerName, clientContext.Client?.Endpoint?.Host); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ServerAddress, clientContext.Client?.Endpoint?.Host); // Client Information this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index b88bb790ee..8117dda493 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -22,7 +22,8 @@ internal static class OpenTelemetryRecorderFactory clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}", resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, isActivityEnabled: true, - suppressNestedClientActivities: true), + suppressNestedClientActivities: true, + isStable: false), isThreadSafe: true); public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index fea625f80b..be3f14d016 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -147,13 +147,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Batch - 400 - 1001 + Some Value + Some Value Some Value Some Value Some Value diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index ccbeb216c8..5de1a309d7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -171,13 +171,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -189,13 +189,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -207,13 +207,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -225,13 +225,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -243,13 +243,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -261,13 +261,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -279,13 +279,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -297,13 +297,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -315,13 +315,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -333,13 +333,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -515,13 +515,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -533,13 +533,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -551,13 +551,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -569,13 +569,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -587,13 +587,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -605,13 +605,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -623,13 +623,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -641,13 +641,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -659,13 +659,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -677,13 +677,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -859,13 +859,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -877,13 +877,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -895,13 +895,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -913,13 +913,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -931,13 +931,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -949,13 +949,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -967,13 +967,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -985,13 +985,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1003,13 +1003,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1021,13 +1021,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1203,13 +1203,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1221,13 +1221,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1239,13 +1239,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1257,13 +1257,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1275,13 +1275,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1293,13 +1293,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1311,13 +1311,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1329,13 +1329,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1347,13 +1347,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1365,13 +1365,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1547,13 +1547,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1565,13 +1565,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1583,13 +1583,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1601,13 +1601,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1619,13 +1619,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1637,13 +1637,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1655,13 +1655,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1673,13 +1673,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1691,13 +1691,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1709,13 +1709,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1891,13 +1891,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1909,13 +1909,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1927,13 +1927,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1945,13 +1945,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1963,13 +1963,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1981,13 +1981,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -1999,13 +1999,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2017,13 +2017,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2035,13 +2035,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2053,13 +2053,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2235,13 +2235,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2253,13 +2253,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2271,13 +2271,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2289,13 +2289,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2307,13 +2307,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2325,13 +2325,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2343,13 +2343,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2361,13 +2361,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2379,13 +2379,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2397,13 +2397,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2579,13 +2579,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2597,13 +2597,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2615,13 +2615,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2633,13 +2633,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2651,13 +2651,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2669,13 +2669,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2687,13 +2687,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2705,13 +2705,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2723,13 +2723,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2741,13 +2741,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2923,13 +2923,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2941,13 +2941,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2959,13 +2959,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2977,13 +2977,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -2995,13 +2995,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3013,13 +3013,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3031,13 +3031,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3049,13 +3049,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3067,13 +3067,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3085,13 +3085,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3267,13 +3267,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3285,13 +3285,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3303,13 +3303,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3321,13 +3321,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3339,13 +3339,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3357,13 +3357,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3375,13 +3375,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3393,13 +3393,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3411,13 +3411,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -3429,13 +3429,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -4228,14 +4228,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 429 - 3 + Some Value + Some Value Some Value Some Value Microsoft.Azure.Cosmos.CosmosException diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index c19bdc3c47..42d0cb4f23 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -1031,13 +1031,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 304 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1050,13 +1050,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1069,13 +1069,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1088,13 +1088,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1107,13 +1107,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1791,13 +1791,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 304 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1810,13 +1810,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1829,13 +1829,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1848,13 +1848,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -1867,13 +1867,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -2532,13 +2532,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 304 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -2551,13 +2551,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -2570,13 +2570,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -2589,13 +2589,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -2608,13 +2608,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3293,13 +3293,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 304 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3312,13 +3312,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3331,13 +3331,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3350,13 +3350,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3369,13 +3369,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -3708,13 +3708,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value South Central US diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index cff19fd002..533473c213 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -124,13 +124,13 @@ miscdbcustonhandler cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Delete - 204 - 0 + Some Value + Some Value Some Value Some Value @@ -141,13 +141,13 @@ miscdbcustonhandler cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value @@ -265,13 +265,13 @@ miscdbdataplane cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Delete - 204 - 0 + Some Value + Some Value Some Value Some Value @@ -282,13 +282,13 @@ miscdbdataplane cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml index 15a3a7a1c2..365d96f2c5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.PointOperationsExceptionsAsync.xml @@ -166,14 +166,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 408 - 0 + Some Value + Some Value Some Value South Central US Some Value @@ -443,14 +443,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 429 - 3 + Some Value + Some Value Some Value South Central US Some Value @@ -698,14 +698,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 408 - 0 + Some Value + Some Value Some Value South Central US Some Value @@ -985,14 +985,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 408 - 0 + Some Value + Some Value Some Value South Central US Some Value @@ -1336,14 +1336,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 408 - 0 + Some Value + Some Value Some Value South Central US Some Value @@ -1520,14 +1520,14 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Some Value Some Value - 503 - 20006 + Some Value + Some Value Some Value South Central US Some Value diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 1bb21e8747..5a1d7b5c43 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -647,13 +647,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -668,13 +668,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -689,13 +689,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -710,13 +710,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1404,13 +1404,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1425,13 +1425,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1446,13 +1446,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1467,13 +1467,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2142,13 +2142,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2163,13 +2163,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2184,13 +2184,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2205,13 +2205,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2900,13 +2900,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2921,13 +2921,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2942,13 +2942,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2963,13 +2963,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -3732,13 +3732,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -3753,13 +3753,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -3774,13 +3774,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -3795,13 +3795,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -4493,13 +4493,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -4514,13 +4514,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -4535,13 +4535,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -4556,13 +4556,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -5274,13 +5274,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -5295,13 +5295,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -5316,13 +5316,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -5337,13 +5337,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Query - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 4c8984d3b8..78241c3050 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -584,13 +584,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -604,13 +604,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -624,13 +624,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -644,13 +644,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1274,13 +1274,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1294,13 +1294,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1314,13 +1314,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1334,13 +1334,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1945,13 +1945,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1965,13 +1965,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -1985,13 +1985,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2005,13 +2005,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2636,13 +2636,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2656,13 +2656,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2676,13 +2676,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value @@ -2696,13 +2696,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct ReadFeed - 200 - 0 + Some Value + Some Value Some Value Some Value Some Value diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 9900ce054d..ad6be29190 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -481,13 +481,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Read - 200 - 0 + Some Value + Some Value Some Value South Central US @@ -995,13 +995,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Read - 200 - 0 + Some Value + Some Value Some Value South Central US diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 34415a6ee4..6bf7447aad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -107,13 +107,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -230,13 +230,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Read - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -361,13 +361,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Replace - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -487,13 +487,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Delete - 204 - 0 + Some Value + Some Value Some Value Some Value South Central US diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index bb3576f9ed..c3ce1e8786 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -127,13 +127,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Create - 201 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -255,13 +255,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Read - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -396,13 +396,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Replace - 200 - 0 + Some Value + Some Value Some Value Some Value South Central US @@ -526,13 +526,13 @@ containerName cosmosdb Some Value - 127.0.0.1 + 127.0.0.1 Some Value Some Value Direct Delete - 204 - 0 + Some Value + Some Value Some Value Some Value South Central US diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs index 9a44ec0a82..3bc5b1be3c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/AssertActivity.cs @@ -40,7 +40,7 @@ public static void IsValidOperationActivity(Activity activity) "db.system", "db.name", "db.operation", - "net.peer.name", + "server.address", "db.cosmosdb.client_id", "db.cosmosdb.machine_id", "user_agent.original", @@ -53,9 +53,7 @@ public static void IsValidOperationActivity(Activity activity) "db.cosmosdb.sub_status_code", "db.cosmosdb.request_charge", "db.cosmosdb.regions_contacted", - "db.cosmosdb.retry_count", "db.cosmosdb.item_count", - "db.cosmosdb.request_diagnostics", "exception.type", "exception.message", "exception.stacktrace", diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs index 1ce1597ffd..8d5e79a78f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Tracing/CustomListener.cs @@ -34,14 +34,12 @@ internal class CustomListener : "az.namespace", "db.operation", "db.system", - "net.peer.name", + "server.address", "db.name", "db.cosmosdb.container", "db.cosmosdb.connection_mode", "db.cosmosdb.operation_type", "db.cosmosdb.regions_contacted", - "db.cosmosdb.status_code", - "db.cosmosdb.sub_status_code", "rntbd.sub_status_code", "rntbd.status_code", "error.type" From cba93d3fad6be84a59ddb4a920af990dff6a6fa4 Mon Sep 17 00:00:00 2001 From: Bala Perumalswamy Date: Tue, 13 Feb 2024 12:33:44 -0800 Subject: [PATCH 285/337] [Internal] Query: Adds support for continuation using SqlQuerySpec (#3774) * initial change to support sending continuation as resume value in query spec * serialize resume value in continuation token. * fix unit test that was failing. other minor refactors * additional refactoring update exception messages * few minor changes * additional tests * code refactoring * Create separate top level object to represent SqlQueryResumeValue. Different types of resume values are private in this object Consolidate all the visitor and serialization of resume value to SqlQueryResumeValue Other code review comments * handle different continuation token for target partition * update test for continuation from array and object values. other minor code refactors * save resume value as CosmosElement instead of defining a separate derived objects. update cosmosundefinedquerytests. other code review comments. * support on CosmosNumber64. Other number types are not supported for resume value. unit tests for SqlQueryResumeValue. * update cosmosundefinedquerytests to include arrays and object in order by and group by tests. reducing the document count to reduce execution time. * revert change to have separate SqlQueryResumeValue objects as it is better symmetry for comparing arrays and objects. * group resume value into 3 types: Undefined, Primitive and Complex * minor fix --------- Co-authored-by: Bala Perumalswamy Co-authored-by: Aditya --- .../src/CosmosSqlQuerySpecJsonConverter.cs | 48 +- .../OrderBy/OrderByContinuationToken.cs | 169 +++++-- ...OrderByCrossPartitionQueryPipelineStage.cs | 320 ++++++++++++-- .../src/Query/Core/SqlQueryResumeFilter.cs | 38 ++ .../src/Query/Core/SqlQueryResumeValue.cs | 411 ++++++++++++++++++ .../src/Query/Core/SqlQuerySpec.cs | 27 +- .../Query/CosmosUndefinedQueryTests.cs | 52 ++- .../Query/OrderByQueryTests.cs | 50 +-- .../CosmosJsonSerializerUnitTests.cs | 50 +++ .../Pagination/InMemoryContainer.cs | 48 +- .../OrderByContinuationTokenTests.cs | 158 ++++++- ...misticDirectExecutionQueryBaselineTests.cs | 1 + ...ByCrossPartitionQueryPipelineStageTests.cs | 107 ++++- 13 files changed, 1318 insertions(+), 161 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeFilter.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeValue.cs diff --git a/Microsoft.Azure.Cosmos/src/CosmosSqlQuerySpecJsonConverter.cs b/Microsoft.Azure.Cosmos/src/CosmosSqlQuerySpecJsonConverter.cs index aae033701e..f7582530a0 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosSqlQuerySpecJsonConverter.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosSqlQuerySpecJsonConverter.cs @@ -24,7 +24,8 @@ internal CosmosSqlQuerySpecJsonConverter(CosmosSerializer userSerializer) public override bool CanConvert(Type objectType) { - return typeof(SqlParameter) == objectType; + return typeof(SqlParameter) == objectType + || typeof(SqlQueryResumeValue).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) @@ -34,32 +35,37 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { - SqlParameter sqlParameter = (SqlParameter)value; - - writer.WriteStartObject(); - writer.WritePropertyName("name"); - serializer.Serialize(writer, sqlParameter.Name); - writer.WritePropertyName("value"); - - // if the SqlParameter has stream value we dont pass it through the custom serializer. - if (sqlParameter.Value is SerializedParameterValue serializedEncryptedData) - { - writer.WriteRawValue(serializedEncryptedData.rawSerializedJsonValue); - } - else + if (value is SqlParameter sqlParameter) { - // Use the user serializer for the parameter values so custom conversions are correctly handled - using (Stream str = this.UserSerializer.ToStream(sqlParameter.Value)) + writer.WriteStartObject(); + writer.WritePropertyName("name"); + serializer.Serialize(writer, sqlParameter.Name); + writer.WritePropertyName("value"); + + // if the SqlParameter has stream value we dont pass it through the custom serializer. + if (sqlParameter.Value is SerializedParameterValue serializedEncryptedData) { - using (StreamReader streamReader = new StreamReader(str)) + writer.WriteRawValue(serializedEncryptedData.rawSerializedJsonValue); + } + else + { + // Use the user serializer for the parameter values so custom conversions are correctly handled + using (Stream str = this.UserSerializer.ToStream(sqlParameter.Value)) { - string parameterValue = streamReader.ReadToEnd(); - writer.WriteRawValue(parameterValue); + using (StreamReader streamReader = new StreamReader(str)) + { + string parameterValue = streamReader.ReadToEnd(); + writer.WriteRawValue(parameterValue); + } } } - } - writer.WriteEndObject(); + writer.WriteEndObject(); + } + else if (value is SqlQueryResumeValue resumeValue) + { + SqlQueryResumeValue.Serialize(writer, resumeValue, serializer); + } } /// diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByContinuationToken.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByContinuationToken.cs index 3c638f27ac..cdf0eee23d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByContinuationToken.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByContinuationToken.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; using Microsoft.Azure.Documents.Routing; using Newtonsoft.Json; @@ -46,12 +45,12 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy /// 2. All partitions, that have greater Range.Min than that of the target partition, have exhausted all values less than or equal to X /// /// - /// Given this background, below is an example of order by continuation token. The class members below explains the different + /// Given this background, below is an example of orderby continuation token. The class members below explains the different /// component/states of the continuation token. /// /// /// - /// Order by continuation token example. + /// OrderBy continuation token example. /// 1"} /// ]]> @@ -62,6 +61,7 @@ private static class PropertyNames { public const string CompositeToken = "compositeToken"; public const string OrderByItems = "orderByItems"; + public const string ResumeValues = "resumeValues"; public const string Rid = "rid"; public const string SkipCount = "skipCount"; public const string Filter = "filter"; @@ -71,22 +71,19 @@ private static class PropertyNames /// Initializes a new instance of the OrderByContinuationToken struct. /// /// The composite continuation token (refer to property documentation). - /// The order by items (refer to property documentation). + /// The orderby items (refer to property documentation). + /// OrderBy property values the query needs to resume from in the next round trip /// The rid (refer to property documentation). /// The skip count (refer to property documentation). /// The filter (refer to property documentation). public OrderByContinuationToken( ParallelContinuationToken compositeContinuationToken, IReadOnlyList orderByItems, + IReadOnlyList resumeValues, string rid, int skipCount, string filter) { - if (orderByItems.Count == 0) - { - throw new ArgumentException($"{nameof(orderByItems)} can not be empty."); - } - if (string.IsNullOrWhiteSpace(rid)) { throw new ArgumentNullException($"{nameof(rid)} can not be null or empty or whitespace."); @@ -99,7 +96,30 @@ public OrderByContinuationToken( //// filter is allowed to be null. this.ParallelContinuationToken = compositeContinuationToken ?? throw new ArgumentNullException(nameof(compositeContinuationToken)); - this.OrderByItems = orderByItems ?? throw new ArgumentNullException(nameof(orderByItems)); + + if (resumeValues != null) + { + if (resumeValues.Count == 0) + { + throw new ArgumentException($"{nameof(resumeValues)} can not be empty."); + } + + this.ResumeValues = resumeValues; + } + else if (orderByItems != null) + { + if (orderByItems.Count == 0) + { + throw new ArgumentException($"{nameof(orderByItems)} can not be empty."); + } + + this.OrderByItems = orderByItems; + } + else + { + throw new ArgumentException($"Either {nameof(orderByItems)} or {nameof(resumeValues)} needs to be provided."); + } + this.Rid = rid; this.SkipCount = skipCount; this.Filter = filter; @@ -131,7 +151,7 @@ public ParallelContinuationToken ParallelContinuationToken /// ]]> /// /// - /// Right now, we don't support orderBy by multiple fields, so orderByItems is an array of one element. + /// This is an array to support multi item orderby. /// > [JsonProperty(PropertyNames.OrderByItems)] public IReadOnlyList OrderByItems @@ -139,6 +159,25 @@ public IReadOnlyList OrderByItems get; } + /// + /// Gets: Values in the top most OrderByQueryResult from the target partition. + /// resumeValues is used for filtering when we resume. + /// + /// + /// The below array has one value "2" which was the last orderby value returned. + /// + /// + /// + /// This is an array to support multi item orderby. + /// > + [JsonProperty(PropertyNames.ResumeValues)] + public IReadOnlyList ResumeValues + { + get; + } + /// /// Gets: Rid in the top most OrderByQueryResult from the target partition. /// Rid is used for filtering after we resume, when orderByItems have the same value. @@ -169,7 +208,7 @@ public string Rid /// online to understand this better. /// /// - /// This behavior has implications on how pagination work for CosmosDB queries, especially for order by queries across + /// This behavior has implications on how pagination work for CosmosDB queries, especially for orderby queries across /// multiple partition. /// /// @@ -215,26 +254,52 @@ public string Filter public static CosmosElement ToCosmosElement(OrderByContinuationToken orderByContinuationToken) { CosmosElement compositeContinuationToken = ParallelContinuationToken.ToCosmosElement(orderByContinuationToken.ParallelContinuationToken); - List orderByItemsRaw = new List(); - foreach (OrderByItem orderByItem in orderByContinuationToken.OrderByItems) + + List orderByItemsRaw; + List resumeValuesRaw; + if (orderByContinuationToken.OrderByItems != null) { - orderByItemsRaw.Add(OrderByItem.ToCosmosElement(orderByItem)); + resumeValuesRaw = null; + orderByItemsRaw = new List(orderByContinuationToken.OrderByItems.Count); + foreach (OrderByItem orderByItem in orderByContinuationToken.OrderByItems) + { + orderByItemsRaw.Add(OrderByItem.ToCosmosElement(orderByItem)); + } } - - CosmosArray orderByItems = CosmosArray.Create(orderByItemsRaw); - - CosmosElement filter = orderByContinuationToken.Filter == null ? CosmosNull.Create() : (CosmosElement)CosmosString.Create(orderByContinuationToken.Filter); - - CosmosObject cosmosObject = CosmosObject.Create( - new Dictionary() + else if (orderByContinuationToken.ResumeValues != null) + { + orderByItemsRaw = null; + resumeValuesRaw = new List(orderByContinuationToken.ResumeValues.Count); + foreach (SqlQueryResumeValue resumeValue in orderByContinuationToken.ResumeValues) { - { PropertyNames.CompositeToken, compositeContinuationToken }, - { PropertyNames.OrderByItems, orderByItems }, - { PropertyNames.Rid, CosmosString.Create(orderByContinuationToken.Rid) }, - { PropertyNames.SkipCount, CosmosNumber64.Create(orderByContinuationToken.SkipCount) }, - { PropertyNames.Filter, filter }, - }); + resumeValuesRaw.Add(SqlQueryResumeValue.ToCosmosElement(resumeValue)); + } + } + else + { + throw new ArgumentException($"Either {nameof(orderByContinuationToken.ResumeValues)} or {nameof(orderByContinuationToken.OrderByItems)} needs to be specified."); + } + + CosmosElement filter = orderByContinuationToken.Filter == null ? CosmosNull.Create() : CosmosString.Create(orderByContinuationToken.Filter); + CosmosObject cosmosObject = (resumeValuesRaw == null) + ? CosmosObject.Create( + new Dictionary() + { + { PropertyNames.CompositeToken, compositeContinuationToken }, + { PropertyNames.OrderByItems, CosmosArray.Create(orderByItemsRaw) }, + { PropertyNames.Rid, CosmosString.Create(orderByContinuationToken.Rid) }, + { PropertyNames.SkipCount, CosmosNumber64.Create(orderByContinuationToken.SkipCount) }, + { PropertyNames.Filter, filter }, + }) + : CosmosObject.Create( + new Dictionary() + { + { PropertyNames.CompositeToken, compositeContinuationToken }, + { PropertyNames.ResumeValues, CosmosArray.Create(resumeValuesRaw) }, + { PropertyNames.Rid, CosmosString.Create(orderByContinuationToken.Rid) }, + { PropertyNames.SkipCount, CosmosNumber64.Create(orderByContinuationToken.SkipCount) }, + }); return cosmosObject; } @@ -260,14 +325,29 @@ public static TryCatch TryCreateFromCosmosElement(Cosm ParallelContinuationToken compositeContinuationToken = tryCompositeContinuation.Result; - if (!cosmosObject.TryGetValue(PropertyNames.OrderByItems, out CosmosArray orderByItemsRaw)) + // Try to get ResumeValues first, if it is not present then try to get orderby items + List resumeValues; + List orderByItems; + if (cosmosObject.TryGetValue(PropertyNames.ResumeValues, out CosmosArray resumeValuesRaw)) + { + orderByItems = null; + resumeValues = new List(resumeValuesRaw.Count); + foreach (CosmosElement resumeValue in resumeValuesRaw) + { + resumeValues.Add(SqlQueryResumeValue.FromCosmosElement(resumeValue)); + } + } + else if (cosmosObject.TryGetValue(PropertyNames.OrderByItems, out CosmosArray orderByItemsRaw)) + { + resumeValues = null; + orderByItems = orderByItemsRaw.Select(x => OrderByItem.FromCosmosElement(x)).ToList(); + } + else { return TryCatch.FromException( - new MalformedContinuationTokenException($"{nameof(OrderByContinuationToken)} is missing field: '{PropertyNames.OrderByItems}': {cosmosElement}")); + new MalformedContinuationTokenException($"{nameof(OrderByContinuationToken)} is missing field: '{PropertyNames.OrderByItems}': {cosmosElement}")); } - List orderByItems = orderByItemsRaw.Select(x => OrderByItem.FromCosmosElement(x)).ToList(); - if (!cosmosObject.TryGetValue(PropertyNames.Rid, out CosmosString ridRaw)) { return TryCatch.FromException( @@ -284,16 +364,24 @@ public static TryCatch TryCreateFromCosmosElement(Cosm int skipCount = (int)Number64.ToLong(skipCountRaw.GetValue()); - if (!cosmosObject.TryGetValue(PropertyNames.Filter, out CosmosElement filterRaw)) - { - return TryCatch.FromException( - new MalformedContinuationTokenException($"{nameof(OrderByContinuationToken)} is missing field: '{PropertyNames.Filter}': {cosmosElement}")); - } - + // filter will be present only when orderByItems is present. This property is not used for resumeValue base continuation string filter; - if (filterRaw is CosmosString filterStringRaw) + if (orderByItems != null) { - filter = filterStringRaw.Value; + if (!cosmosObject.TryGetValue(PropertyNames.Filter, out CosmosElement filterRaw)) + { + return TryCatch.FromException( + new MalformedContinuationTokenException($"{nameof(OrderByContinuationToken)} is missing field: '{PropertyNames.Filter}': {cosmosElement}")); + } + + if (filterRaw is CosmosString filterStringRaw) + { + filter = filterStringRaw.Value; + } + else + { + filter = null; + } } else { @@ -303,6 +391,7 @@ public static TryCatch TryCreateFromCosmosElement(Cosm OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( compositeContinuationToken, orderByItems, + resumeValues, rid, skipCount, filter); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index 43f4176de3..f22eb8a6af 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Collections; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; @@ -264,6 +265,7 @@ private async ValueTask MoveNextAsync_Initialize_FilterAsync( ((CosmosString)uninitializedEnumerator.FeedRangeState.State.Value).Value, ((FeedRangeEpk)uninitializedEnumerator.FeedRangeState.FeedRange).Range), token.OrderByItems, + token.ResumeValues, token.Rid, itemsLeftToSkip, token.Filter); @@ -408,12 +410,11 @@ private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace) this.uninitializedEnumeratorsAndTokens.Enqueue((currentEnumerator, (OrderByContinuationToken)null)); // Use the token for the next page, since we fully drained the enumerator. - OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( new ParallelContinuationToken( - token: ((CosmosString)currentEnumerator.FeedRangeState.State.Value).Value, - range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), - orderByQueryResult.OrderByItems, - orderByQueryResult.Rid, + token: ((CosmosString)currentEnumerator.FeedRangeState.State.Value).Value, + range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), + orderByQueryResult, skipCount: 0, filter: currentEnumerator.Filter); @@ -461,14 +462,13 @@ private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace) } else { - OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( new ParallelContinuationToken( - token: currentEnumerator.StartOfPageState != null ? ((CosmosString)currentEnumerator.StartOfPageState.Value).Value : null, - range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), - orderByQueryResult.OrderByItems, - orderByQueryResult.Rid, - skipCount: skipCount, - filter: currentEnumerator.Filter); + token: currentEnumerator.StartOfPageState != null ? ((CosmosString)currentEnumerator.StartOfPageState.Value).Value : null, + range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), + orderByQueryResult, + skipCount, + currentEnumerator.Filter); CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); @@ -641,58 +641,171 @@ public static TryCatch MonadicCreate( } PartitionMapper.PartitionMapping partitionMapping = monadicGetOrderByContinuationTokenMapping.Result; - IReadOnlyList orderByItems = partitionMapping - .TargetMapping - .Values - .First() - .OrderByItems - .Select(x => x.Item) - .ToList(); - if (orderByItems.Count != orderByColumns.Count) + OrderByContinuationToken targetContinuationToken = partitionMapping.TargetMapping.Values.First(); + + int orderByResumeValueCount = 0; + IReadOnlyList resumeValues; + IReadOnlyList orderByItems; + if (targetContinuationToken.ResumeValues != null) { - return TryCatch.FromException( - new MalformedContinuationTokenException( - $"Order By Items from continuation token did not match the query text. " + - $"Order by item count: {orderByItems.Count()} did not match column count {orderByColumns.Count()}. " + - $"Continuation token: {continuationToken}")); + // Use SqlQueryResumeValue for continuation if it is present. + resumeValues = targetContinuationToken.ResumeValues; + orderByItems = null; + orderByResumeValueCount = resumeValues.Count; } + else + { + // If continuation token has only OrderByItems, check if it can be converted to SqlQueryResumeValue. This will + // help avoid re-writing the query. Conversion will work as long as the order by item type is a supported type. + orderByResumeValueCount = targetContinuationToken.OrderByItems.Count; - ReadOnlyMemory<(OrderByColumn, CosmosElement)> columnAndItems = orderByColumns.Zip(orderByItems, (column, item) => (column, item)).ToArray(); + if (ContainsSupportedResumeTypes(targetContinuationToken.OrderByItems)) + { + // Convert the order by items to SqlQueryResumeValue + List generatedResumeValues = new List(targetContinuationToken.OrderByItems.Count); + //foreach (CosmosElement orderByItem in orderByItems) + foreach (OrderByItem orderByItem in targetContinuationToken.OrderByItems) + { + generatedResumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); + } - // For ascending order-by, left of target partition has filter expression > value, - // right of target partition has filter expression >= value, - // and target partition takes the previous filter from continuation (or true if no continuation) - (string leftFilter, string targetFilter, string rightFilter) = OrderByCrossPartitionQueryPipelineStage.GetFormattedFilters(columnAndItems); - List<(IReadOnlyDictionary, string)> tokenMappingAndFilters = new List<(IReadOnlyDictionary, string)>() + resumeValues = generatedResumeValues; + orderByItems = null; + } + else + { + orderByItems = targetContinuationToken.OrderByItems.Select(x => x.Item).ToList(); + resumeValues = null; + } + } + + if (orderByResumeValueCount != orderByColumns.Count) { - { (partitionMapping.MappingLeftOfTarget, leftFilter) }, - { (partitionMapping.TargetMapping, targetFilter) }, - { (partitionMapping.MappingRightOfTarget, rightFilter) }, - }; + return TryCatch.FromException( + new MalformedContinuationTokenException( + $"Order By Items from continuation token did not match the query text. " + + $"Order by item count: {orderByResumeValueCount} did not match column count {orderByColumns.Count()}. " + + $"Continuation token: {targetContinuationToken}")); + } enumeratorsAndTokens = new List<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)>(); - foreach ((IReadOnlyDictionary tokenMapping, string filter) in tokenMappingAndFilters) + if (resumeValues != null) { - SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: filter), - sqlQuerySpec.Parameters); + // Continuation contains resume values, so update SqlQuerySpec to include SqlQueryResumeFilter which + // will specify the resume point to the backend. This avoid having to re-write the query. + + // Process partitions left of Target. The resume values in these partition have + // already been processed so exclude flag is set to true. + SqlQuerySpec leftQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, null, true)); - foreach (KeyValuePair kvp in tokenMapping) + foreach (KeyValuePair kvp in partitionMapping.MappingLeftOfTarget) { FeedRangeEpk range = kvp.Key; OrderByContinuationToken token = kvp.Value; OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( documentContainer, - rewrittenQueryForOrderBy, + leftQuerySpec, new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), partitionKey, queryPaginationOptions, - filter, + filter: null, cancellationToken); enumeratorsAndTokens.Add((remoteEnumerator, token)); } + + // Process Target Partitions which is the last partition from which data has been returned. + // For this partition the Rid value needs to be set if present. Exclude flag is not set as the document + // matching the Rid will be skipped in SDK based on SkipCount value. + // Backend requests can contains both SqlQueryResumeFilter and ContinuationToken and the backend will pick + // the resume point that is bigger i.e. most restrictive + foreach (KeyValuePair kvp in partitionMapping.TargetMapping) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + + SqlQuerySpec targetQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, token?.Rid, false)); + + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( + documentContainer, + targetQuerySpec, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter: null, + cancellationToken); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + + // Process partitions right of target. The Resume value in these partitions have not been processed so the exclude value is set to false. + SqlQuerySpec rightQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, null, false)); + + foreach (KeyValuePair kvp in partitionMapping.MappingRightOfTarget) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( + documentContainer, + rightQuerySpec, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter: null, + cancellationToken); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + } + else + { + // If continuation token doesn't have resume values or if order by items cannot be converted to resume values then + // rewrite the query filter to get the correct resume point + ReadOnlyMemory<(OrderByColumn, CosmosElement)> columnAndItems = orderByColumns.Zip(orderByItems, (column, item) => (column, item)).ToArray(); + + // For ascending order-by, left of target partition has filter expression > value, + // right of target partition has filter expression >= value, + // and target partition takes the previous filter from continuation (or true if no continuation) + (string leftFilter, string targetFilter, string rightFilter) = OrderByCrossPartitionQueryPipelineStage.GetFormattedFilters(columnAndItems); + List<(IReadOnlyDictionary, string)> tokenMappingAndFilters = new List<(IReadOnlyDictionary, string)>() + { + { (partitionMapping.MappingLeftOfTarget, leftFilter) }, + { (partitionMapping.TargetMapping, targetFilter) }, + { (partitionMapping.MappingRightOfTarget, rightFilter) }, + }; + + foreach ((IReadOnlyDictionary tokenMapping, string filter) in tokenMappingAndFilters) + { + SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: filter), + sqlQuerySpec.Parameters); + + foreach (KeyValuePair kvp in tokenMapping) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( + documentContainer, + rewrittenQueryForOrderBy, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter, + cancellationToken); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + } } } @@ -775,7 +888,8 @@ private static TryCatch> MonadicExtractOrderByTok foreach (OrderByContinuationToken suppliedOrderByContinuationToken in orderByContinuationTokens) { - if (suppliedOrderByContinuationToken.OrderByItems.Count != numOrderByColumns) + int orderByCount = GetOrderByItemCount(suppliedOrderByContinuationToken); + if (orderByCount != numOrderByColumns) { return TryCatch>.FromException( new MalformedContinuationTokenException( @@ -786,6 +900,12 @@ private static TryCatch> MonadicExtractOrderByTok return TryCatch>.FromResult(orderByContinuationTokens); } + private static int GetOrderByItemCount(OrderByContinuationToken orderByContinuationToken) + { + return orderByContinuationToken.ResumeValues != null ? + orderByContinuationToken.ResumeValues.Count : orderByContinuationToken.OrderByItems.Count; + } + private static void AppendToBuilders((StringBuilder leftFilter, StringBuilder targetFilter, StringBuilder rightFilter) builders, object str) { OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, str, str, str); @@ -1038,6 +1158,58 @@ private static (string leftFilter, string targetFilter, string rightFilter) GetF return (left.ToString(), target.ToString(), right.ToString()); } + private static OrderByContinuationToken CreateOrderByContinuationToken( + ParallelContinuationToken parallelToken, + OrderByQueryResult orderByQueryResult, + int skipCount, + string filter) + { + OrderByContinuationToken token; + // If order by items have c* types then it cannot be converted to resume values + if (ContainsSupportedResumeTypes(orderByQueryResult.OrderByItems)) + { + List resumeValues = new List(orderByQueryResult.OrderByItems.Count); + foreach (OrderByItem orderByItem in orderByQueryResult.OrderByItems) + { + resumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); + } + + token = new OrderByContinuationToken( + parallelToken, + orderByItems: null, + resumeValues, + orderByQueryResult.Rid, + skipCount: skipCount, + filter: filter); + } + else + { + token = new OrderByContinuationToken( + parallelToken, + orderByQueryResult.OrderByItems, + resumeValues: null, + orderByQueryResult.Rid, + skipCount: skipCount, + filter: filter); + } + + return token; + } + + // Helper method to check that resume values are of type that is supported by SqlQueryResumeValue + private static bool ContainsSupportedResumeTypes(IReadOnlyList orderByItems) + { + foreach (OrderByItem orderByItem in orderByItems) + { + if (!orderByItem.Item.Accept(SupportedResumeTypeVisitor.Singleton)) + { + return false; + } + } + + return true; + } + private static async Task monadicQueryByPage)>> FilterNextAsync( OrderByQueryPartitionRangePageAsyncEnumerator enumerator, IReadOnlyList sortOrders, @@ -1084,9 +1256,11 @@ private static (string leftFilter, string targetFilter, string rightFilter) GetF OrderByQueryResult orderByResult = new OrderByQueryResult(documents.Current); for (int i = 0; (i < sortOrders.Count) && (sortOrderCompare == 0); ++i) { - sortOrderCompare = ItemComparer.Instance.Compare( - continuationToken.OrderByItems[i].Item, - orderByResult.OrderByItems[i].Item); + sortOrderCompare = continuationToken.ResumeValues != null + ? continuationToken.ResumeValues[i].CompareTo(orderByResult.OrderByItems[i].Item) + : ItemComparer.Instance.Compare( + continuationToken.OrderByItems[i].Item, + orderByResult.OrderByItems[i].Item); if (sortOrderCompare != 0) { @@ -1308,5 +1482,59 @@ public ComparisionWithUndefinedFilters( public string GreaterThan { get; } public string GreaterThanOrEqualTo { get; } } + + private sealed class SupportedResumeTypeVisitor : ICosmosElementVisitor + { + public static readonly SupportedResumeTypeVisitor Singleton = new SupportedResumeTypeVisitor(); + + private SupportedResumeTypeVisitor() + { + } + + public bool Visit(CosmosArray cosmosArray) + { + return true; + } + + public bool Visit(CosmosBinary cosmosBinary) + { + return false; + } + + public bool Visit(CosmosBoolean cosmosBoolean) + { + return true; + } + + public bool Visit(CosmosGuid cosmosGuid) + { + return false; + } + + public bool Visit(CosmosNull cosmosNull) + { + return true; + } + + public bool Visit(CosmosNumber cosmosNumber) + { + return cosmosNumber.Accept(SqlQueryResumeValue.SupportedResumeNumberTypeVisitor.Singleton); + } + + public bool Visit(CosmosObject cosmosObject) + { + return true; + } + + public bool Visit(CosmosString cosmosString) + { + return true; + } + + public bool Visit(CosmosUndefined cosmosUndefined) + { + return true; + } + } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeFilter.cs b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeFilter.cs new file mode 100644 index 0000000000..a8f5011d3a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeFilter.cs @@ -0,0 +1,38 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core +{ + using System; + using System.Collections.Generic; + using System.Runtime.Serialization; + + [DataContract] + internal sealed class SqlQueryResumeFilter + { + [DataMember(Name = "value")] + public IReadOnlyList ResumeValues { get; } + + [DataMember(Name = "rid", EmitDefaultValue = false)] + public string Rid { get; } + + [DataMember(Name = "exclude")] + public bool Exclude { get; } + + public SqlQueryResumeFilter( + IReadOnlyList resumeValues, + string rid, + bool exclude) + { + if ((resumeValues == null) || (resumeValues.Count == 0)) + { + throw new ArgumentException($"{nameof(resumeValues)} can not be empty."); + } + + this.ResumeValues = resumeValues; + this.Rid = rid; + this.Exclude = exclude; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeValue.cs b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeValue.cs new file mode 100644 index 0000000000..8cf8dd0762 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQueryResumeValue.cs @@ -0,0 +1,411 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core +{ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Cosmos.Core.Utf8; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + // Class that represents the resume value of a query. Primarily used to represent the resume value for order by query + // The actual value is saved as a CosmosElement. Only native JSON types are supported. C* types are not supported. + // Objects and Arrays are represented by their UInt128 hash value. All other types are represented by their actual value. + // Example for Object and Array: + // {"type":"array", "low": 1000000000, "high": 8888888888} + // {"type":"object", "low": 1000000000, "high": 8888888888} + internal class SqlQueryResumeValue : IComparable + { + private static class PropertyNames + { + public const string ArrayType = "array"; + public const string High = "high"; + public const string Low = "low"; + public const string ObjectType = "object"; + public const string Type = "type"; + } + + private static readonly CosmosElement EmptyObject = CosmosObject.Create(new Dictionary()); + + private class UndefinedResumeValue : SqlQueryResumeValue + { + private static readonly UndefinedResumeValue Singelton = new UndefinedResumeValue(); + + private UndefinedResumeValue() + { + } + + public static UndefinedResumeValue Create() + { + return Singelton; + } + } + + private class PrimitiveResumeValue : SqlQueryResumeValue + { + public CosmosElement Value { get; } + + private PrimitiveResumeValue(CosmosElement value) + { + this.Value = value; + } + + public static PrimitiveResumeValue Create(CosmosElement value) + { + return value switch + { + CosmosNull or CosmosBoolean or CosmosNumber or CosmosString => new PrimitiveResumeValue(value), + _ => throw new ArgumentException("Non primitive value passed to PrimitiveResumeValue"), + }; + } + } + + private class ComplexResumeValue : SqlQueryResumeValue + { + public bool IsArray { get; } + + public UInt128 HashValue { get; } + + private ComplexResumeValue(bool isArray, UInt128 hashValue) + { + this.IsArray = isArray; + this.HashValue = hashValue; + } + + public static ComplexResumeValue Create(bool isArray, UInt128 hashValue) + { + return new ComplexResumeValue(isArray, hashValue); + } + + public static ComplexResumeValue Create(CosmosArray arrayValue) + { + return Create(isArray: true, DistinctHash.GetHash(arrayValue)); + } + + public static ComplexResumeValue Create(CosmosObject objectValue) + { + return Create(isArray: false, DistinctHash.GetHash(objectValue)); + } + } + + // Method to compare a value represented as CosmosElement with the resume value. + // Object and Array needs special handling as the resume value is a UInt128 hash. + public int CompareTo(CosmosElement cosmosElement) + { + // Convert ResumeValue to CosmosElement and invoke ItemComparer to compare the cosmoselements + switch (this) + { + case UndefinedResumeValue: + return ItemComparer.Instance.Compare(CosmosUndefined.Create(), cosmosElement); + + case PrimitiveResumeValue primitiveResumeValue: + return ItemComparer.Instance.Compare(primitiveResumeValue.Value, cosmosElement); + + case ComplexResumeValue complexResumeValue: + { + if (complexResumeValue.IsArray) + { + // If the order by result is also of array type, then compare the hash values + // For other types create an empty array and call CosmosElement comparer which + // will take care of ordering based on types. + if (cosmosElement is CosmosArray arrayResult) + { + return UInt128BinaryComparer.Singleton.Compare(complexResumeValue.HashValue, DistinctHash.GetHash(arrayResult)); + } + else + { + return ItemComparer.Instance.Compare(CosmosArray.Empty, cosmosElement); + } + + } + else + { + // If the order by result is also of object type, then compare the hash values + // For other types create an empty object and call CosmosElement comparer which + // will take care of ordering based on types. + if (cosmosElement is CosmosObject objectResult) + { + // same type so compare the hash values + return UInt128BinaryComparer.Singleton.Compare(complexResumeValue.HashValue, DistinctHash.GetHash(objectResult)); + } + else + { + return ItemComparer.Instance.Compare(EmptyObject, cosmosElement); + } + } + } + + default: + throw new ArgumentException($"Invalid {nameof(SqlQueryResumeValue)} type."); + } + } + + // Utility method that converts SqlQueryResumeValue to CosmosElement which can then be serialized to string + public static CosmosElement ToCosmosElement(SqlQueryResumeValue resumeValue) + { + return resumeValue switch + { + UndefinedResumeValue => CosmosArray.Empty, + PrimitiveResumeValue primiteResumeValue => primiteResumeValue.Value, + ComplexResumeValue complexResumeValue => CosmosObject.Create( + new Dictionary() + { + { PropertyNames.Type, CosmosString.Create(complexResumeValue.IsArray ? PropertyNames.ArrayType : PropertyNames.ObjectType) }, + { PropertyNames.Low, CosmosNumber64.Create((long)complexResumeValue.HashValue.GetLow()) }, + { PropertyNames.High, CosmosNumber64.Create((long)complexResumeValue.HashValue.GetHigh()) } + }), + _ => throw new ArgumentException($"Invalid {nameof(SqlQueryResumeValue)} type."), + }; + } + + public static SqlQueryResumeValue FromCosmosElement(CosmosElement value) + { + return value.Accept(CosmosElementToResumeValueVisitor.Singleton); + } + + // Generates the SqlQueryResumeValue given an exact orderby value from the query. + // The orderby value is provided as CosmosElement. + public static SqlQueryResumeValue FromOrderByValue(CosmosElement orderByValue) + { + return orderByValue.Accept(OrderByValueToResumeValueVisitor.Singleton); + } + + // Serializer that gets called when serializing SqlQueryResumeValue to send to backend. + public static void Serialize(JsonWriter writer, SqlQueryResumeValue value, JsonSerializer serializer) + { + switch (value) + { + case UndefinedResumeValue: + writer.WriteStartArray(); + writer.WriteEndArray(); + break; + + case PrimitiveResumeValue primitiveResumeValue: + serializer.Serialize(writer, primitiveResumeValue.Value); + break; + + case ComplexResumeValue complexResumeValue: + { + writer.WriteStartObject(); + writer.WritePropertyName(PropertyNames.Type); + writer.WriteValue(complexResumeValue.IsArray ? PropertyNames.ArrayType : PropertyNames.ObjectType); + writer.WritePropertyName(PropertyNames.Low); + writer.WriteValue((long)complexResumeValue.HashValue.GetLow()); + writer.WritePropertyName(PropertyNames.High); + writer.WriteValue((long)complexResumeValue.HashValue.GetHigh()); + writer.WriteEndObject(); + } + break; + + default: + throw new ArgumentException($"Invalid {nameof(SqlQueryResumeValue)} type."); + } + } + + // Visitor to verify if the number type is supported by resume value. C* number types are not supported + public sealed class SupportedResumeNumberTypeVisitor : ICosmosNumberVisitor + { + public static readonly SupportedResumeNumberTypeVisitor Singleton = new SupportedResumeNumberTypeVisitor(); + + private SupportedResumeNumberTypeVisitor() + { + } + + public bool Visit(CosmosNumber64 cosmosNumber64) + { + return true; + } + + public bool Visit(CosmosInt8 cosmosInt8) + { + return false; + } + + public bool Visit(CosmosInt16 cosmosInt16) + { + return false; + } + + public bool Visit(CosmosInt32 cosmosInt32) + { + return false; + } + + public bool Visit(CosmosInt64 cosmosInt64) + { + return false; + } + + public bool Visit(CosmosUInt32 cosmosUInt32) + { + return false; + } + public bool Visit(CosmosFloat32 cosmosFloat32) + { + return false; + } + + public bool Visit(CosmosFloat64 cosmosFloat64) + { + return false; + } + } + + // Visitor to convert resume values that are represented as CosmosElement to ResumeValue + // This is the inverse of ToCosmosElement method. The input for this is from the Client continuation token. + private sealed class CosmosElementToResumeValueVisitor : ICosmosElementVisitor + { + public static readonly CosmosElementToResumeValueVisitor Singleton = new CosmosElementToResumeValueVisitor(); + + private CosmosElementToResumeValueVisitor() + { + } + + public SqlQueryResumeValue Visit(CosmosArray cosmosArray) + { + if (cosmosArray.Count != 0) + { + throw new ArgumentException($"Only empty arrays can be converted to ResumeValue. Array has {cosmosArray.Count} elements."); + } + + return UndefinedResumeValue.Create(); + } + + public SqlQueryResumeValue Visit(CosmosBinary cosmosBinary) + { + throw new NotSupportedException($"Converting {nameof(CosmosBinary)} to {nameof(SqlQueryResumeValue)} is not supported"); + } + + public SqlQueryResumeValue Visit(CosmosBoolean cosmosBoolean) + { + return PrimitiveResumeValue.Create(cosmosBoolean); + } + + public SqlQueryResumeValue Visit(CosmosGuid cosmosGuid) + { + throw new NotSupportedException($"Converting {nameof(CosmosGuid)} to {nameof(SqlQueryResumeValue)} is not supported"); + } + + public SqlQueryResumeValue Visit(CosmosNull cosmosNull) + { + return PrimitiveResumeValue.Create(cosmosNull); + } + + public SqlQueryResumeValue Visit(CosmosUndefined cosmosUndefined) + { + return UndefinedResumeValue.Create(); + } + + public SqlQueryResumeValue Visit(CosmosNumber cosmosNumber) + { + bool bSupportedType = cosmosNumber.Accept(SupportedResumeNumberTypeVisitor.Singleton); + if (!bSupportedType) + { + throw new NotSupportedException($"Extended number types are not supported in SqlQueryResumeValue."); + } + + return PrimitiveResumeValue.Create(cosmosNumber); + } + + public SqlQueryResumeValue Visit(CosmosObject cosmosObject) + { + if (!cosmosObject.TryGetValue(PropertyNames.Type, out CosmosString objectType) + || !cosmosObject.TryGetValue(PropertyNames.Low, out CosmosNumber64 lowValue) + || !cosmosObject.TryGetValue(PropertyNames.High, out CosmosNumber64 highValue)) + { + throw new ArgumentException($"Incorrect Array / Object Resume Value. One or more of the required properties are missing."); + } + + UInt128 hashValue = UInt128.Create( + (ulong)Number64.ToLong(lowValue.Value), + (ulong)Number64.ToLong(highValue.Value)); + + if (string.Equals(objectType.Value, PropertyNames.ArrayType)) + { + return ComplexResumeValue.Create(isArray: true, hashValue); + } + else if (string.Equals(objectType.Value, PropertyNames.ObjectType)) + { + return ComplexResumeValue.Create(isArray: false, hashValue); + } + else + { + throw new ArgumentException($"Incorrect value for {PropertyNames.Type} property. Value is {objectType.Value}."); + } + } + + public SqlQueryResumeValue Visit(CosmosString cosmosString) + { + return PrimitiveResumeValue.Create(cosmosString); + } + } + + // Visitor to convert OrderBy values received from the backend to SqlQueryResumeValue + // OrderBy values from backend are represented as CosmosElement + private sealed class OrderByValueToResumeValueVisitor : ICosmosElementVisitor + { + public static readonly OrderByValueToResumeValueVisitor Singleton = new OrderByValueToResumeValueVisitor(); + + private OrderByValueToResumeValueVisitor() + { + } + + public SqlQueryResumeValue Visit(CosmosArray cosmosArray) + { + return ComplexResumeValue.Create(cosmosArray); + } + + public SqlQueryResumeValue Visit(CosmosBinary cosmosBinary) + { + throw new NotSupportedException($"Converting {nameof(CosmosBinary)} to {nameof(SqlQueryResumeValue)} is not supported"); + } + + public SqlQueryResumeValue Visit(CosmosBoolean cosmosBoolean) + { + return PrimitiveResumeValue.Create(cosmosBoolean); + } + + public SqlQueryResumeValue Visit(CosmosGuid cosmosGuid) + { + throw new NotSupportedException($"Converting {nameof(CosmosGuid)} to {nameof(SqlQueryResumeValue)} is not supported"); + } + + public SqlQueryResumeValue Visit(CosmosNull cosmosNull) + { + return PrimitiveResumeValue.Create(cosmosNull); + } + + public SqlQueryResumeValue Visit(CosmosUndefined cosmosUndefined) + { + return UndefinedResumeValue.Create(); + } + + public SqlQueryResumeValue Visit(CosmosNumber cosmosNumber) + { + bool bSupportedType = cosmosNumber.Accept(SupportedResumeNumberTypeVisitor.Singleton); + if (!bSupportedType) + { + throw new NotSupportedException($"Extended number types are not supported in SqlQueryResumeValue."); + } + + return PrimitiveResumeValue.Create(cosmosNumber); + } + + public SqlQueryResumeValue Visit(CosmosObject cosmosObject) + { + return ComplexResumeValue.Create(cosmosObject); + } + + public SqlQueryResumeValue Visit(CosmosString cosmosString) + { + return PrimitiveResumeValue.Create(cosmosString); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs index 67a684965b..277ce63494 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/SqlQuerySpec.cs @@ -40,11 +40,23 @@ public SqlQuerySpec(string queryText) /// The text of the database query. /// The instance, which represents the collection of query parameters. public SqlQuerySpec(string queryText, SqlParameterCollection parameters) + : this(queryText, parameters, null) + { + } + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// The text of the database query. + /// The instance, which represents the collection of query parameters. + /// The instance, which represents the query resume filter. + public SqlQuerySpec(string queryText, SqlParameterCollection parameters, SqlQueryResumeFilter resumeFilter) { this.QueryText = queryText; this.parameters = parameters ?? throw new ArgumentNullException("parameters"); + this.ResumeFilter = resumeFilter; } - + /// /// Gets or sets the text of the Azure Cosmos DB database query. /// @@ -66,16 +78,13 @@ public SqlQuerySpec(string queryText, SqlParameterCollection parameters) [DataMember(Name = "parameters")] public SqlParameterCollection Parameters { - get - { - return this.parameters; - } - set - { - this.parameters = value ?? throw new ArgumentNullException("value"); - } + get => this.parameters; + set => this.parameters = value ?? throw new ArgumentNullException("value"); } + [DataMember(Name = "resumeFilter", EmitDefaultValue = false)] + public SqlQueryResumeFilter ResumeFilter { get; set; } + /// /// Returns a value that indicates whether the Azure Cosmos DB database property should be serialized. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs index 1b44c773fa..eea629aa33 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/CosmosUndefinedQueryTests.cs @@ -15,15 +15,19 @@ namespace Microsoft.Azure.Cosmos.EmulatorTests.Query [TestCategory("Query")] public sealed class CosmosUndefinedQueryTests : QueryTestsBase { - private const int DocumentCount = 400; + private const int DocumentCount = 350; - private const int MixedTypeCount = 5; + private const int MixedTypeCount = 7; private const int DocumentsPerTypeCount = DocumentCount / MixedTypeCount; private const int IntegerValue = 42; - private const string StringValue = "string"; + private const string StringValue = "string"; + + private const string ArrayValue = "[10, 20]"; + + private const string ObjectValue = "{\"type\":\"object\"}"; private static readonly int[] PageSizes = new[] { 5, 10, -1 }; @@ -231,6 +235,12 @@ private static async Task GroupByTests(Container container) MakeGrouping( key: CosmosString.Create(StringValue), value: DocumentsPerTypeCount), + MakeGrouping( + key: CosmosArray.Parse(ArrayValue), + value: DocumentsPerTypeCount), + MakeGrouping( + key: CosmosObject.Parse(ObjectValue), + value: DocumentsPerTypeCount), }), MakeGroupByTest( query: $"SELECT SUM(c.{nameof(MixedTypeDocument.MixedTypeField)}) as {nameof(GroupByProjection.MixedTypeField)}, " + @@ -254,6 +264,12 @@ private static async Task GroupByTests(Container container) MakeGrouping( key: null, value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), }), MakeGroupByTest( query: $"SELECT AVG(c.{nameof(MixedTypeDocument.MixedTypeField)}) as {nameof(GroupByProjection.MixedTypeField)}, " + @@ -277,6 +293,12 @@ private static async Task GroupByTests(Container container) MakeGrouping( key: null, value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), }), MakeGroupByTest( query: $"SELECT MIN(c.{nameof(MixedTypeDocument.MixedTypeField)}) as {nameof(GroupByProjection.MixedTypeField)}, " + @@ -300,6 +322,12 @@ private static async Task GroupByTests(Container container) MakeGrouping( key: CosmosString.Create(StringValue), value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), }), MakeGroupByTest( query: $"SELECT MAX(c.{nameof(MixedTypeDocument.MixedTypeField)}) as {nameof(GroupByProjection.MixedTypeField)}, " + @@ -323,13 +351,19 @@ private static async Task GroupByTests(Container container) MakeGrouping( key: CosmosString.Create(StringValue), value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), + MakeGrouping( + key: null, + value: DocumentsPerTypeCount), }), }; foreach (GroupByUndefinedTestCase testCase in mixedTypeTestCases) - { + { foreach (int pageSize in PageSizes) - { + { List actual = await QueryWithoutContinuationTokensAsync( container, testCase.Query, @@ -423,6 +457,14 @@ private static List CreateDocuments(int count) case 4: mixedTypeElement = CosmosString.Create(StringValue); break; + + case 5: + mixedTypeElement = CosmosArray.Parse(ArrayValue); + break; + + case 6: + mixedTypeElement = CosmosObject.Parse(ObjectValue); + break; default: mixedTypeElement = null; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs index e0c106e0ea..94ef30a365 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs @@ -1226,7 +1226,6 @@ public int Compare(CosmosElement element1, CosmosElement element2) { return ItemComparer.Instance.Compare(element1, element2); } - } [Flags] @@ -1296,34 +1295,6 @@ FROM c WHERE {filter} ORDER BY c.{nameof(MixedTypedDocument.MixedTypeField)} {orderString}"; - QueryRequestOptions feedOptions = new QueryRequestOptions() - { - MaxBufferedItemCount = 1000, - MaxItemCount = 16, - MaxConcurrency = 10, - }; - -#if false - For now we can not serve the query through continuation tokens correctly. - This is because we allow order by on mixed types but not comparisions across types - For example suppose the following query: - SELECT c.MixedTypeField FROM c ORDER BY c.MixedTypeField - returns: - [ - {"MixedTypeField":[]}, - {"MixedTypeField":[1, 2, 3]}, - {"MixedTypeField":{}}, - ] - and we left off on [1, 2, 3] then at some point the cross partition code resumes the query by running the following: - SELECT c.MixedTypeField FROM c WHERE c.MixedTypeField > [1, 2, 3] ORDER BY c.MixedTypeField - And comparison on arrays and objects is undefined. -#endif - - List actual = await QueryTestsBase.QueryWithoutContinuationTokensAsync( - container, - query, - queryRequestOptions: feedOptions); - IEnumerable insertedDocs = documents .Select(document => CosmosElement.CreateFromBuffer(Encoding.UTF8.GetBytes(document.ToString()))) .Select(document => @@ -1403,11 +1374,26 @@ And comparison on arrays and objects is undefined. }, MockOrderByComparer.Value); } - Assert.IsTrue( - expected.SequenceEqual(actual), - $@" queryWithoutContinuations: {query}, + foreach (int pageSize in new int[] { 1, documents.Count / 2, documents.Count }) + { + QueryRequestOptions feedOptions = new QueryRequestOptions() + { + MaxBufferedItemCount = 1000, + MaxItemCount = pageSize, + MaxConcurrency = 10, + }; + + List actual = await RunQueryAsync( + container, + query, + queryRequestOptions: feedOptions); + + Assert.IsTrue( + expected.SequenceEqual(actual), + $@" queryWithoutContinuations: {query}, expected:{JsonConvert.SerializeObject(expected)}, actual: {JsonConvert.SerializeObject(actual)}"); + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs index 8b318ad09e..227785f791 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Core.Tests using System.Net; using System.Text; using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Scripts; using Microsoft.Azure.Cosmos.Tracing; @@ -269,6 +270,55 @@ public void ValidateResponseFactoryJsonSerializerWithContent() mockUserJsonSerializer.VerifyAll(); } + [TestMethod] + public void ValidateSqlQuerySpecSerializerWithResumeFilter() + { + // Test serializing of different types + string queryText = "SELECT * FROM root r"; + (SqlQueryResumeValue resumeValue, string resumeString)[] testValues = new (SqlQueryResumeValue resumeValue, string resumeString)[] { + (SqlQueryResumeValue.FromCosmosElement(CosmosUndefined.Create()), "[]"), + (SqlQueryResumeValue.FromCosmosElement(CosmosNull.Create()), "null"), + (SqlQueryResumeValue.FromCosmosElement(CosmosBoolean.Create(true)), "true"), + (SqlQueryResumeValue.FromCosmosElement(CosmosBoolean.Create(false)), "false"), + (SqlQueryResumeValue.FromCosmosElement(CosmosNumber64.Create(10)), "10"), + (SqlQueryResumeValue.FromCosmosElement(CosmosString.Create("testval")), "\"testval\""), + (SqlQueryResumeValue.FromCosmosElement(CosmosObject.Parse("{\"type\":\"array\",\"low\":10000,\"high\":20000}")), "{\"type\":\"array\",\"low\":10000,\"high\":20000}"), + (SqlQueryResumeValue.FromCosmosElement(CosmosObject.Parse("{\"type\":\"object\",\"low\":10000,\"high\":20000}")), "{\"type\":\"object\",\"low\":10000,\"high\":20000}"), + (SqlQueryResumeValue.FromOrderByValue(CosmosArray.Parse("[]")), "{\"type\":\"array\",\"low\":-6706074647855398782,\"high\":9031114912533472255}"), + (SqlQueryResumeValue.FromOrderByValue(CosmosObject.Parse("{}")), "{\"type\":\"object\",\"low\":1457042291250783704,\"high\":1493060239874959160}") + }; + + CosmosJsonDotNetSerializer userSerializer = new CosmosJsonDotNetSerializer(); + CosmosJsonDotNetSerializer propertiesSerializer = new CosmosJsonDotNetSerializer(); + + CosmosSerializer sqlQuerySpecSerializer = CosmosSqlQuerySpecJsonConverter.CreateSqlQuerySpecSerializer( + userSerializer, + propertiesSerializer); + + foreach ((SqlQueryResumeValue resumeValue, string resumeString) in testValues) + { + foreach(string rid in new string[] { "rid", null}) + { + SqlQuerySpec querySpec = new SqlQuerySpec( + queryText, + new SqlParameterCollection(), + new SqlQueryResumeFilter(new List() { resumeValue }, rid, true)); + + Stream stream = sqlQuerySpecSerializer.ToStream(querySpec); + using (StreamReader sr = new StreamReader(stream)) + { + string result = sr.ReadToEnd(); + Assert.IsNotNull(result); + + string expectedValue = string.IsNullOrEmpty(rid) + ? $"{{\"query\":\"{queryText}\",\"resumeFilter\":{{\"value\":[{resumeString}],\"exclude\":true}}}}" + : $"{{\"query\":\"{queryText}\",\"resumeFilter\":{{\"value\":[{resumeString}],\"rid\":\"{rid}\",\"exclude\":true}}}}"; + Assert.AreEqual(expectedValue, result); + } + } + } + } + [TestMethod] public void ValidateSqlQuerySpecSerializer() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs index 7d17786159..ad17a6bac6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs @@ -22,6 +22,8 @@ namespace Microsoft.Azure.Cosmos.Tests.Pagination using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Parser; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; using Microsoft.Azure.Cosmos.Routing; @@ -30,6 +32,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Pagination using Microsoft.Azure.Cosmos.Tests.Query.OfflineEngine; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; + using static Microsoft.Azure.Cosmos.Query.Core.SqlQueryResumeFilter; using ResourceIdentifier = Cosmos.Pagination.ResourceIdentifier; using UInt128 = UInt128; @@ -508,7 +511,7 @@ public virtual Task> MonadicQueryAsync( } SqlQuery sqlQuery = monadicParse.Result; - if ((sqlQuery.OrderByClause != null) && (feedRangeState.State != null)) + if ((sqlQuery.OrderByClause != null) && (feedRangeState.State != null) && (sqlQuerySpec.ResumeFilter == null)) { // This is a hack. // If the query is an ORDER BY query then we need to seek to the resume term. @@ -548,6 +551,49 @@ public virtual Task> MonadicQueryAsync( IEnumerable queryResults = SqlInterpreter.ExecuteQuery(documents, sqlQuery); IEnumerable queryPageResults = queryResults; + // If the resume value is passed in query spec, filter out the results that has order by item value smaller than resume values + if (sqlQuerySpec.ResumeFilter != null) + { + if (sqlQuery.OrderByClause.OrderByItems.Length != 1) + { + throw new NotImplementedException("Can only support a single order by column"); + } + + SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; + IEnumerator queryResultEnumerator = queryPageResults.GetEnumerator(); + + int skipCount = 0; + while(queryResultEnumerator.MoveNext()) + { + CosmosObject document = (CosmosObject)queryResultEnumerator.Current; + CosmosElement orderByValue = ((CosmosObject)((CosmosArray)document["orderByItems"])[0])["item"]; + + int sortOrderCompare = sqlQuerySpec.ResumeFilter.ResumeValues[0].CompareTo(orderByValue); + + if (sortOrderCompare != 0) + { + sortOrderCompare = orderByItem.IsDescending ? -sortOrderCompare : sortOrderCompare; + } + + if (sortOrderCompare < 0) + { + // We might have passed the item due to deletions and filters. + break; + } + + if (sortOrderCompare >= 0) + { + // This document does not match the sort order, so skip it. + skipCount++; + } + } + + queryPageResults = queryPageResults.Skip(skipCount); + + // NOTE: We still need to handle duplicate values and break the tie with the rid + // But since all the values are unique for our testing purposes we can ignore this for now. + } + // Filter for the continuation token string continuationResourceId; int continuationSkipCount; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByContinuationTokenTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByContinuationTokenTests.cs index c527c6dc30..987c91ed77 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByContinuationTokenTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByContinuationTokenTests.cs @@ -6,12 +6,11 @@ namespace Microsoft.Azure.Cosmos.Query { using System; using System.Collections.Generic; - using System.IO; - using System.Linq; using System.Text; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Json; + using Microsoft.Azure.Cosmos.Query.Core; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; @@ -41,6 +40,7 @@ public void TestRoundTripAsCosmosElement() OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( parallelContinuationToken, orderByItems, + resumeValues: null, rid, skipCount, filter); @@ -56,12 +56,54 @@ public void TestRoundTripAsCosmosElement() Assert.AreEqual(cosmosElementToken.ToString(), OrderByContinuationToken.ToCosmosElement(orderByContinuationTokenFromCosmosElement).ToString()); } + [TestMethod] + public void TestResumeFilterRoundTripAsCosmosElement() + { + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: "someToken", + range: new Range("asdf", "asdf", false, false)); + + List resumeValues = new List() + { + SqlQueryResumeValue.FromCosmosElement(CosmosUndefined.Create()), + SqlQueryResumeValue.FromCosmosElement(CosmosNull.Create()), + SqlQueryResumeValue.FromCosmosElement(CosmosBoolean.Create(true)), + SqlQueryResumeValue.FromCosmosElement(CosmosString.Create("asdf")), + SqlQueryResumeValue.FromCosmosElement(CosmosNumber64.Create(1337)), + SqlQueryResumeValue.FromOrderByValue(CosmosArray.Parse("[]")), + SqlQueryResumeValue.FromOrderByValue(CosmosObject.Parse("{}")) + }; + + string rid = "someRid"; + int skipCount = 42; + string filter = "someFilter"; + OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + parallelContinuationToken, + orderByItems: null, + resumeValues, + rid, + skipCount, + filter); + + CosmosElement cosmosElementToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); + Assert.AreEqual( + @"{""compositeToken"":{""token"":""someToken"",""range"":{""min"":""asdf"",""max"":""asdf""}},""resumeValues"":[[],null,true,""asdf"",1337,{""type"":""array"",""low"":-6706074647855398782,""high"":9031114912533472255},{""type"":""object"",""low"":1457042291250783704,""high"":1493060239874959160}],""rid"":""someRid"",""skipCount"":42}", + cosmosElementToken.ToString()); + + TryCatch tryOrderByContinuationTokenFromCosmosElement = OrderByContinuationToken.TryCreateFromCosmosElement(cosmosElementToken); + Assert.IsTrue(tryOrderByContinuationTokenFromCosmosElement.Succeeded); + + OrderByContinuationToken orderByContinuationTokenFromCosmosElement = tryOrderByContinuationTokenFromCosmosElement.Result; + Assert.IsNotNull(orderByContinuationTokenFromCosmosElement); + Assert.AreEqual(cosmosElementToken.ToString(), OrderByContinuationToken.ToCosmosElement(orderByContinuationTokenFromCosmosElement).ToString()); + } + [TestMethod] public void TestOrderByQueryLiterals() { StringBuilder sb = new StringBuilder(); CosmosElement element = CosmosObject.Create( - new Dictionary() {{"item", CosmosString.Create("asdf")}}); + new Dictionary() { { "item", CosmosString.Create("asdf") } }); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( @"{""item"":""asdf""}", @@ -137,7 +179,7 @@ public void TestOrderByQueryLiterals() sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( - $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":C_Binary(""0x{hexString}"")}}", + $@"{{""item"":C_Guid(""{guid}""),""item2"":C_Binary(""0x{hexString}"")}}", sb.ToString()); // deeply nested arrays and objects @@ -166,8 +208,114 @@ public void TestOrderByQueryLiterals() sb.Clear(); element.Accept(new CosmosElementToQueryLiteral(sb)); Assert.AreEqual( - $@"{{""item"":C_Guid(""{guid.ToString()}""),""item2"":[],""item3"":{{}},""item4"":[{{""a"":C_Int8(3),""b"":""adf""}},C_Int16(25)]}}", + $@"{{""item"":C_Guid(""{guid}""),""item2"":[],""item3"":{{}},""item4"":[{{""a"":C_Int8(3),""b"":""adf""}},C_Int16(25)]}}", sb.ToString()); } + + [TestMethod] + public void TestSqlQueryResumeValueRoundTrip() + { + (CosmosElement orderByValue, string resumeValueString)[] testValues = new(CosmosElement orderByValue, string resumeValueString)[] { + (CosmosUndefined.Create(), "[]"), + (CosmosNull.Create(), "null"), + (CosmosBoolean.Create(true), "true"), + (CosmosBoolean.Create(false), "false"), + (CosmosNumber64.Create(1337), "1337"), + (CosmosNumber64.Create(-1), "-1"), + (CosmosNumber64.Create(3.416), "3.416"), + (CosmosString.Create("asdf"), "\"asdf\""), + (CosmosString.Create("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\""), + (CosmosArray.Parse("[]"), "{\"type\":\"array\",\"low\":-6706074647855398782,\"high\":9031114912533472255}"), + (CosmosObject.Parse("{}"), "{\"type\":\"object\",\"low\":1457042291250783704,\"high\":1493060239874959160}"), + (CosmosArray.Parse("[100, 200, true, \"asdf\"]"), "{\"type\":\"array\",\"low\":-343833024563930322,\"high\":-7302890837749904085}"), + (CosmosObject.Parse("{\"num1\":100, \"num2\":2000, \"str\":\"asdf\"}"), "{\"type\":\"object\",\"low\":-725443068664622182,\"high\":-5851519632801302561}") + }; + + foreach ((CosmosElement orderByValue, string resumeValueString) in testValues) + { + // Validate that the order by value serializes as expected + SqlQueryResumeValue resumeValue = SqlQueryResumeValue.FromOrderByValue(orderByValue); + Assert.AreEqual(SqlQueryResumeValue.ToCosmosElement(resumeValue).ToString(), resumeValueString); + + // Validate that deserialize works as expected + SqlQueryResumeValue resumeValueFromString = SqlQueryResumeValue.FromCosmosElement(CosmosElement.Parse(resumeValueString)); + Assert.IsTrue(resumeValueFromString.CompareTo(orderByValue) == 0); + } + } + + [TestMethod] + public void TestSqlQueryResumeValueComparison() + { + CosmosElement[] orderedValues = new CosmosElement[] + { + CosmosUndefined.Create(), + CosmosNull.Create(), + CosmosBoolean.Create(false), + CosmosBoolean.Create(true), + CosmosNumber64.Create(-1), + CosmosNumber64.Create(10.5), + CosmosNumber64.Create(10000000), + CosmosNumber64.Create(9031114912533472255), + CosmosString.Create("abc"), + CosmosString.Create("abd"), + CosmosString.Create("zzzzzzz"), + CosmosArray.Parse("[]"), + CosmosArray.Parse("[100, 200, true, \"asdf\"]"), + CosmosArray.Parse("[{}, [200, true]]"), + CosmosObject.Parse("{}"), + CosmosObject.Parse("{\"num1\":100, \"num2\":2000, \"str\":\"asdf\"}") + }; + + for(int i = 0; i < orderedValues.Length; i++) + { + SqlQueryResumeValue resumeValue = SqlQueryResumeValue.FromOrderByValue(orderedValues[i]); + + for(int j = 0; j < orderedValues.Length; j++) + { + int cosmosElementCompareResult = orderedValues[i].CompareTo(orderedValues[j]); + int resumeValueCompareResult = resumeValue.CompareTo(orderedValues[j]); + + Assert.AreEqual(cosmosElementCompareResult, resumeValueCompareResult); + } + } + } + + [TestMethod] + public void TestSqlQueryResumeValueNegativeCases() + { + CosmosElement[] incorrectResumeValues = new CosmosElement[] + { + CosmosArray.Parse("[100]"), + CosmosObject.Parse("{\"type\":\"obj\",\"low\":1457042291250783704,\"high\":1493060239874959160}"), + CosmosObject.Parse("{\"low\":1457042291250783704,\"high\":1493060239874959160}"), + CosmosObject.Parse("{\"type\":\"object\",\"high\":1493060239874959160}"), + }; + + foreach (CosmosElement element in incorrectResumeValues) + { + Assert.ThrowsException(() => SqlQueryResumeValue.FromCosmosElement(element)); + } + + Guid guid = Guid.Parse("69D5AB17-C94A-4173-A278-B59D0D9C7C37"); + byte[] randomBytes = guid.ToByteArray(); + + CosmosElement[] unsupportedResumeValues = new CosmosElement[] + { + CosmosInt8.Create(10), + CosmosInt16.Create(42), + CosmosInt32.Create(42), + CosmosInt64.Create(42), + CosmosUInt32.Create(1234), + CosmosFloat32.Create(1337.42f), + CosmosFloat64.Create(1337.42), + CosmosBinary.Create(new ReadOnlyMemory(randomBytes)), + CosmosGuid.Create(guid), + }; + + foreach (CosmosElement element in unsupportedResumeValues) + { + Assert.ThrowsException(() => SqlQueryResumeValue.FromOrderByValue(element)); + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 9582b754e7..bfbdda891c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -113,6 +113,7 @@ public void NegativeOptimisticDirectExecutionOutput() OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( parallelContinuationToken, new List() { new OrderByItem(CosmosObject.Create(new Dictionary() { { "item", CosmosString.Create("asdf") } })) }, + resumeValues: null, rid: "43223532", skipCount: 42, filter: "filter"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs index f1042ee6fb..af4ccc4eae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs @@ -47,6 +47,21 @@ public class OrderByCrossPartitionQueryPipelineStageTests }; } + private static IReadOnlyList<(string serializedToken, SqlQueryResumeValue resumeValue)> ResumeValueTestData() + { + return new List<(string, SqlQueryResumeValue)> + { + ("[]", SqlQueryResumeValue.FromCosmosElement(CosmosUndefined.Create())), + ("null", SqlQueryResumeValue.FromCosmosElement(CosmosNull.Create())), + ("false", SqlQueryResumeValue.FromCosmosElement(CosmosBoolean.Create(false))), + ("true", SqlQueryResumeValue.FromCosmosElement(CosmosBoolean.Create(true))), + ("1337", SqlQueryResumeValue.FromCosmosElement(CosmosNumber64.Create(1337))), + ("asdf", SqlQueryResumeValue.FromCosmosElement(CosmosString.Create("asdf"))), + ("{\"type\":\"array\",\"low\":-6706074647855398782,\"high\":9031114912533472255}", SqlQueryResumeValue.FromOrderByValue(CosmosArray.Parse("[]"))), + ("{\"type\":\"object\",\"low\":1457042291250783704,\"high\":1493060239874959160}", SqlQueryResumeValue.FromOrderByValue(CosmosObject.Parse("{}"))) + }; + } + [TestMethod] public void MonadicCreate_NullContinuationToken() { @@ -149,6 +164,7 @@ public void MonadicCreate_SingleOrderByContinuationToken() OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( parallelContinuationToken, new List() { new OrderByItem(CosmosObject.Create(new Dictionary() { { "item", element} })) }, + resumeValues: null, rid: "rid", skipCount: 42, filter: "filter"); @@ -188,6 +204,7 @@ public void MonadicCreate_SingleOrderByContinuationToken() new OrderByItem(CosmosObject.Create(new Dictionary(){ { "item1", element1 } })), new OrderByItem(CosmosObject.Create(new Dictionary(){ { "item2", element2 } })) }, + resumeValues: null, rid: "rid", skipCount: 42, filter: "filter"); @@ -236,6 +253,7 @@ public void MonadicCreate_MultipleOrderByContinuationToken() OrderByContinuationToken orderByContinuationToken1 = new OrderByContinuationToken( parallelContinuationToken1, new List() { new OrderByItem(CosmosObject.Create(new Dictionary() { { "item", element1 } })) }, + resumeValues: null, rid: "rid", skipCount: 42, filter: "filter"); @@ -247,6 +265,7 @@ public void MonadicCreate_MultipleOrderByContinuationToken() OrderByContinuationToken orderByContinuationToken2 = new OrderByContinuationToken( parallelContinuationToken2, new List() { new OrderByItem(CosmosObject.Create(new Dictionary() { { "item", element2 } })) }, + resumeValues: null, rid: "rid", skipCount: 42, filter: "filter"); @@ -278,6 +297,90 @@ public void MonadicCreate_MultipleOrderByContinuationToken() } } + [TestMethod] + public void MonadicCreate_OrderByWithResumeValues() + { + Mock mockDocumentContainer = new Mock(); + IReadOnlyList<(string serializedToken, SqlQueryResumeValue resumeValue)> tokens = ResumeValueTestData(); + + foreach ((string serializedToken, SqlQueryResumeValue resumeValue) in tokens) + { + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: serializedToken, + range: new Documents.Routing.Range("A", "B", true, false)); + + OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + parallelContinuationToken, + orderByItems: null, + resumeValues: new List() { resumeValue}, + rid: "rid", + skipCount: 42, + filter: null); + + TryCatch monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: mockDocumentContainer.Object, + sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c.item"), + targetRanges: new List() { new FeedRangeEpk(new Range(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)) }, + partitionKey: null, + orderByColumns: new List() + { + new OrderByColumn("item", SortOrder.Ascending) + }, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), + maxConcurrency: 10, + cancellationToken: default, + continuationToken: CosmosArray.Create( + new List() + { + OrderByContinuationToken.ToCosmosElement(orderByContinuationToken) + })); + Assert.IsTrue(monadicCreate.Succeeded); + } + + // Multiple resume values + foreach ((string token1, SqlQueryResumeValue resumeValue1) in tokens) + { + foreach ((string token2, SqlQueryResumeValue resumeValue2) in tokens) + { + ParallelContinuationToken parallelContinuationToken1 = new ParallelContinuationToken( + token: $"[{token1}, {token2}]", + range: new Documents.Routing.Range("A", "B", true, false)); + + OrderByContinuationToken orderByContinuationToken = new OrderByContinuationToken( + parallelContinuationToken1, + orderByItems: null, + new List() { resumeValue1, resumeValue2 }, + rid: "rid", + skipCount: 42, + filter: null); + + TryCatch monadicCreate = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: mockDocumentContainer.Object, + sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c ORDER BY c.item1, c.item2"), + targetRanges: new List() + { + new FeedRangeEpk(new Range(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)), + new FeedRangeEpk(new Range(min: "B", max: "C", isMinInclusive: true, isMaxInclusive: false)), + }, + partitionKey: null, + orderByColumns: new List() + { + new OrderByColumn("item1", SortOrder.Ascending), + new OrderByColumn("item2", SortOrder.Ascending) + }, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), + maxConcurrency: 10, + cancellationToken: default, + continuationToken: CosmosArray.Create( + new List() + { + OrderByContinuationToken.ToCosmosElement(orderByContinuationToken) + })); + Assert.IsTrue(monadicCreate.Succeeded); + } + } + } + [TestMethod] public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsync() { @@ -292,12 +395,12 @@ public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsy additionalHeaders: default, state: default); - string expectedQuerySpec = "SELECT * FROM c WHERE ( c._ts >= 1665482200 OR IS_STRING(c._ts) OR IS_ARRAY(c._ts) OR IS_OBJECT(c._ts) ) ORDER BY c._ts"; + string expectedQuerySpec = "SELECT * FROM c WHERE true ORDER BY c._ts"; Mock mockContainer = new Mock(MockBehavior.Strict); mockContainer .Setup( c => c.MonadicQueryAsync( - It.Is(sqlQuerySpec => expectedQuerySpec.Equals(sqlQuerySpec.QueryText)), + It.Is(sqlQuerySpec => expectedQuerySpec.Equals(sqlQuerySpec.QueryText) && sqlQuerySpec.ResumeFilter.ResumeValues.Count == 1), It.IsAny>(), It.IsAny(), NoOpTrace.Singleton, From 40dfa25a8b9a302a20e479c3ba5d9526b0d6c3de Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 15 Feb 2024 18:13:57 -0800 Subject: [PATCH 286/337] Initial commit (#4322) --- .../src/Resource/Container/Container.cs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index bc5b1323c3..21d660b744 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -972,9 +972,6 @@ public abstract FeedIterator GetItemQueryIterator( /// (Optional) The continuation token in the Azure Cosmos DB service. /// (Optional) The options for the item query request. /// An iterator to go through the items. - /// - /// Query as a stream only supports single partition queries - /// /// https://aka.ms/cosmosdb-dot-net-exceptions#stream-api /// /// 1. Create a query to get all the ToDoActivity that have a cost greater than 9000 for the specified partition @@ -1115,9 +1112,6 @@ public abstract FeedIterator GetItemQueryIterator( /// (Optional) The continuation token in the Azure Cosmos DB service. /// (Optional) The options for the item query request. /// An iterator to go through the items. - /// - /// Query as a stream only supports single partition queries - /// /// https://aka.ms/cosmosdb-dot-net-exceptions#stream-api /// /// Create a query to get all the ToDoActivity that have a cost greater than 9000 for the specified partition @@ -1168,9 +1162,6 @@ public abstract FeedIterator GetItemQueryStreamIterator( /// (Optional) The continuation token in the Azure Cosmos DB service. /// (Optional) The options for the item query request. /// An iterator to go through the items. - /// - /// Query as a stream only supports single partition queries - /// /// https://aka.ms/cosmosdb-dot-net-exceptions#typed-api /// /// Create a query to get all the ToDoActivity that have a cost greater than 9000 for the specified partition From 23dac8b3f2a80eb76b5bf602a42ef9a3a6a2d581 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 16 Feb 2024 23:52:30 +0530 Subject: [PATCH 287/337] Client Telemetry: Refactors code to stop throwing an exception. (#4317) * Remove all code related to throwing an exception from client telemetry module * Update Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs Co-authored-by: Matias Quaranta * updated tests * remove extra try catch * updated message * cosmetic changes --------- Co-authored-by: Matias Quaranta --- .../src/Telemetry/ClientTelemetry.cs | 4 +- .../src/Telemetry/ClientTelemetryProcessor.cs | 85 ++++---- .../Telemetry/ClientTelemetryTests.cs | 185 +++++++++--------- 3 files changed, 135 insertions(+), 139 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 8460998711..7542311f2f 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -221,9 +221,7 @@ internal static async Task RunProcessorTaskAsync(string telemetryDate, Task proc Task resultTask = await Task.WhenAny(processingTask, delayTask); if (resultTask == delayTask) { - DefaultTrace.TraceVerbose($"Processor task with date as {0} is canceled as it did not finish in {1}", telemetryDate, timeout); - // Operation cancelled - throw new OperationCanceledException(string.Format($"Processor task with date as {0} is canceled as it did not finish in {1}", telemetryDate, timeout)); + DefaultTrace.TraceError($"Processor task with date as {0} is cancelled as it did not finish in {1} milliseconds", telemetryDate, timeout.TotalMilliseconds); } else { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs index ffa74c2466..fbbfb68c45 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs @@ -51,8 +51,7 @@ await ClientTelemetryPayloadWriter.SerializedPayloadChunksAsync( } catch (Exception ex) { - DefaultTrace.TraceError($"Exception while serializing telemetry payload: {ex}"); - throw; + DefaultTrace.TraceError("Exception while serializing telemetry payload or sending data to service: {0}", ex); } } @@ -75,62 +74,52 @@ private async Task SendAsync( return; } - try - { - DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl); + DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl); - using HttpRequestMessage request = new HttpRequestMessage - { - Method = HttpMethod.Post, - RequestUri = new Uri(endpointUrl), - Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json") - }; - - async ValueTask CreateRequestMessage() - { - INameValueCollection headersCollection = new StoreResponseNameValueCollection(); - await this.tokenProvider.AddAuthorizationHeaderAsync( - headersCollection, - new Uri(endpointUrl), - "POST", - AuthorizationTokenType.PrimaryMasterKey); - - foreach (string key in headersCollection.AllKeys()) - { - request.Headers.Add(key, headersCollection[key]); - } - - request.Headers.Add(HttpConstants.HttpHeaders.DatabaseAccountName, globalDatabaseAccountName); - String envName = ClientTelemetryOptions.GetEnvironmentName(); - if (!String.IsNullOrEmpty(envName)) - { - request.Headers.Add(HttpConstants.HttpHeaders.EnvironmentName, envName); - } - - return request; - } + using HttpRequestMessage request = new HttpRequestMessage + { + Method = HttpMethod.Post, + RequestUri = new Uri(endpointUrl), + Content = new StringContent(jsonPayload, Encoding.UTF8, RuntimeConstants.MediaTypes.Json) + }; - using HttpResponseMessage response = await this.httpClient.SendHttpAsync(CreateRequestMessage, - ResourceType.Telemetry, - HttpTimeoutPolicyNoRetry.Instance, - null, - cancellationToken); + async ValueTask CreateRequestMessage() + { + INameValueCollection headersCollection = new StoreResponseNameValueCollection(); + await this.tokenProvider.AddAuthorizationHeaderAsync( + headersCollection: headersCollection, + requestAddress: new Uri(endpointUrl), + verb: HttpMethod.Post.Method, + tokenType: AuthorizationTokenType.PrimaryMasterKey); - if (!response.IsSuccessStatusCode) + foreach (string key in headersCollection.AllKeys()) { - DefaultTrace.TraceError("Telemetry Service API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase); - throw new Exception(string.Format("Telemetry Service API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase)); + request.Headers.Add(key, headersCollection[key]); } - else + + request.Headers.Add(HttpConstants.HttpHeaders.DatabaseAccountName, globalDatabaseAccountName); + string envName = ClientTelemetryOptions.GetEnvironmentName(); + if (!string.IsNullOrEmpty(envName)) { - DefaultTrace.TraceInformation("Telemetry data sent successfully."); + request.Headers.Add(HttpConstants.HttpHeaders.EnvironmentName, envName); } + return request; } - catch (Exception ex) + + using HttpResponseMessage response = await this.httpClient.SendHttpAsync(CreateRequestMessage, + ResourceType.Telemetry, + HttpTimeoutPolicyNoRetry.Instance, + null, + cancellationToken); + + if (!response.IsSuccessStatusCode) + { + DefaultTrace.TraceError("Telemetry Service API response not successful. Status Code : {0}, Message : {1}", response.StatusCode, response.ReasonPhrase); + } + else { - DefaultTrace.TraceError("Exception while sending telemetry data : {0}", ex.Message); - throw; + DefaultTrace.TraceInformation("Telemetry data sent successfully."); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs index 6005ec3045..a5abc3e92b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs @@ -19,6 +19,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Telemetry using System.Threading; using System.Net; using System.Collections.Concurrent; + using Microsoft.Azure.Documents; /// /// Tests for . @@ -167,8 +168,8 @@ public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInf "containerName", Documents.OperationType.Read, Documents.ResourceType.Document, - 200, - 0); + (int)HttpStatusCode.OK, + (int)SubStatusCodes.Unknown); LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, ClientTelemetryOptions.RequestLatencyMax, @@ -194,8 +195,8 @@ ConcurrentDictionary cacheRefreshInfo "containerName", Documents.OperationType.Read, Documents.ResourceType.Document, - 200, - 1002, + (int)HttpStatusCode.OK, + (int)SubStatusCodes.PartitionKeyRangeGone, "dummycache") ; LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, @@ -249,100 +250,108 @@ await processor.ProcessAndSendAsync( [TestMethod] public async Task ClientTelmetryProcessor_should_timeout() { - string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); - ClientTelemetryProperties clientTelemetryProperties = JsonConvert.DeserializeObject(data); - - int actualOperationInfoSize = 0; - int actualCacheRefreshInfoSize = 0; - - Mock mockHttpHandler = new Mock(); - _ = mockHttpHandler.Setup(x => x.SendAsync( - It.IsAny(), - It.IsAny())) - .Callback( - (request, cancellationToken) => - { - string payloadJson = request.Content.ReadAsStringAsync().Result; - Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); + try + { + string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); + ClientTelemetryProperties clientTelemetryProperties = JsonConvert.DeserializeObject(data); - ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); + int actualOperationInfoSize = 0; + int actualCacheRefreshInfoSize = 0; - actualOperationInfoSize += propertiesToSend.OperationInfo?.Count ?? 0; - actualCacheRefreshInfoSize += propertiesToSend.CacheRefreshInfo?.Count ?? 0; - }) - .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); + Mock mockHttpHandler = new Mock(); + _ = mockHttpHandler.Setup(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Callback( + (request, cancellationToken) => + { + string payloadJson = request.Content.ReadAsStringAsync().Result; + Assert.IsTrue(payloadJson.Length <= ClientTelemetryOptions.PayloadSizeThreshold, "Payload Size is " + payloadJson.Length); - ClientTelemetryProcessor processor = new ClientTelemetryProcessor( - MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object))), - Mock.Of()); - - ConcurrentDictionary operationInfoSnapshot - = new ConcurrentDictionary(); + ClientTelemetryProperties propertiesToSend = JsonConvert.DeserializeObject(payloadJson); - for (int i = 0; i < 20; i++) - { - OperationInfo opeInfo = new OperationInfo(Regions.WestUS, - 0, - Documents.ConsistencyLevel.Session.ToString(), - "databaseName" + i, - "containerName", - Documents.OperationType.Read, - Documents.ResourceType.Document, - 200, - 0); + actualOperationInfoSize += propertiesToSend.OperationInfo?.Count ?? 0; + actualCacheRefreshInfoSize += propertiesToSend.CacheRefreshInfo?.Count ?? 0; + }) + .Returns(Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK))); - LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, - ClientTelemetryOptions.RequestLatencyMax, - ClientTelemetryOptions.RequestLatencyPrecision); - latency.RecordValue(10); + ClientTelemetryProcessor processor = new ClientTelemetryProcessor( + MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object))), + Mock.Of()); - LongConcurrentHistogram requestcharge = new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, - ClientTelemetryOptions.RequestChargeMax, - ClientTelemetryOptions.RequestChargePrecision); - requestcharge.RecordValue(11); + ConcurrentDictionary operationInfoSnapshot + = new ConcurrentDictionary(); - operationInfoSnapshot.TryAdd(opeInfo, (latency, requestcharge)); + for (int i = 0; i < 20; i++) + { + OperationInfo opeInfo = new OperationInfo(Regions.WestUS, + 0, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + (int)HttpStatusCode.OK, + (int)SubStatusCodes.Unknown); + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10); + + LongConcurrentHistogram requestcharge = new LongConcurrentHistogram(ClientTelemetryOptions.RequestChargeMin, + ClientTelemetryOptions.RequestChargeMax, + ClientTelemetryOptions.RequestChargePrecision); + requestcharge.RecordValue(11); + + operationInfoSnapshot.TryAdd(opeInfo, (latency, requestcharge)); + } + + ConcurrentDictionary cacheRefreshInfoSnapshot + = new ConcurrentDictionary(); + for (int i = 0; i < 10; i++) + { + CacheRefreshInfo crInfo = new CacheRefreshInfo(Regions.WestUS, + 10, + Documents.ConsistencyLevel.Session.ToString(), + "databaseName" + i, + "containerName", + Documents.OperationType.Read, + Documents.ResourceType.Document, + (int)HttpStatusCode.OK, + (int)SubStatusCodes.PartitionKeyRangeGone, + "dummycache"); + + LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, + ClientTelemetryOptions.RequestLatencyMax, + ClientTelemetryOptions.RequestLatencyPrecision); + latency.RecordValue(10); + + cacheRefreshInfoSnapshot.TryAdd(crInfo, latency); + } + + Task processorTask = Task.Run(async () => + { + CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); + await Task.Delay(1000, cts.Token); // Making this task wait to ensure that processir is taking more time. + await processor.ProcessAndSendAsync(clientTelemetryProperties, + operationInfoSnapshot, + cacheRefreshInfoSnapshot, + default, + "http://dummy.telemetry.endpoint/", + cts.Token); + }); + + await ClientTelemetry.RunProcessorTaskAsync( + telemetryDate: DateTime.Now.ToString(), + processingTask: processorTask, + timeout: TimeSpan.FromTicks(1)); } - - ConcurrentDictionary cacheRefreshInfoSnapshot - = new ConcurrentDictionary(); - for (int i = 0; i < 10; i++) + catch (Exception ex) { - CacheRefreshInfo crInfo = new CacheRefreshInfo(Regions.WestUS, - 10, - Documents.ConsistencyLevel.Session.ToString(), - "databaseName" + i, - "containerName", - Documents.OperationType.Read, - Documents.ResourceType.Document, - 200, - 1002, - "dummycache"); - - LongConcurrentHistogram latency = new LongConcurrentHistogram(ClientTelemetryOptions.RequestLatencyMin, - ClientTelemetryOptions.RequestLatencyMax, - ClientTelemetryOptions.RequestLatencyPrecision); - latency.RecordValue(10); - - cacheRefreshInfoSnapshot.TryAdd(crInfo, latency); - } + Assert.Fail("Exception should not be thrown. Exception: " + ex); + } - Task processorTask = Task.Run(async () => - { - CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromMilliseconds(1)); - await Task.Delay(1000, cts.Token); // Making this task wait to ensure that processir is taking more time. - await processor.ProcessAndSendAsync(clientTelemetryProperties, - operationInfoSnapshot, - cacheRefreshInfoSnapshot, - default, - "http://dummy.telemetry.endpoint/", - cts.Token); - }); - - await Assert.ThrowsExceptionAsync(() => ClientTelemetry.RunProcessorTaskAsync( - telemetryDate: DateTime.Now.ToString(), - processingTask: processorTask, - timeout: TimeSpan.FromTicks(1))); } } } From bf0f6291f214836200e8495190b6485b4ec4e10e Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:19:27 -0800 Subject: [PATCH 288/337] initial commit (#4323) --- .../src/Serializer/CosmosLinqSerializer.cs | 7 +---- .../Contracts/DotNetPreviewSDKAPI.json | 28 ------------------- .../Contracts/DotNetSDKAPI.json | 25 ++++++++++++++++- 3 files changed, 25 insertions(+), 35 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs index 191de3a137..6f9406ea2f 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs @@ -75,12 +75,7 @@ namespace Microsoft.Azure.Cosmos /// ]]> /// /// -#if PREVIEW - public -#else - internal -#endif - abstract class CosmosLinqSerializer : CosmosSerializer + public abstract class CosmosLinqSerializer : CosmosSerializer { /// /// Convert a MemberInfo to a string for use in LINQ query translation. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index fc09ffd7cf..66cdf8f4d5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -352,34 +352,6 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "System.String SerializeMemberName(System.Reflection.MemberInfo)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, - "Microsoft.Azure.Cosmos.CosmosSerializer;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": { - "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "System.String SerializeMemberName(System.Reflection.MemberInfo)": { - "Type": "Method", - "Attributes": [], - "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - } - }, - "Members": {}, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index d7335051ae..a0cce31949 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -3406,6 +3406,17 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.String SerializeMemberName(System.Reflection.MemberInfo)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.CosmosLinqSerializerOptions;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { @@ -3645,7 +3656,19 @@ "NestedTypes": {} }, "Microsoft.Azure.Cosmos.CosmosSerializer;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, + "Subclasses": { + "Microsoft.Azure.Cosmos.CosmosLinqSerializer;Microsoft.Azure.Cosmos.CosmosSerializer;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "System.String SerializeMemberName(System.Reflection.MemberInfo)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String SerializeMemberName(System.Reflection.MemberInfo);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + }, "Members": { "System.IO.Stream ToStream[T](T)": { "Type": "Method", From d1a7d49859746f9b706a060318cc810b150227df Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 5 Mar 2024 22:43:52 +0530 Subject: [PATCH 289/337] Diagnostics: Adds Client Configuration for Synchronization context cases (#4338) * disable network level tracing in sdk * Revert "disable network level tracing in sdk" This reverts commit 627cba6404841154113dc21f5ee2f7a81dbf450b. * Including Client Configuration in request Diagnostics for Sync calls also --- Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs | 1 + .../SynchronizationContextTests.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs index b2db7e7107..abe57bbcd2 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/ClientContextCore.cs @@ -286,6 +286,7 @@ private Task OperationHelperWithRootTraceWithSynchronizationContextAsyn using (ITrace trace = disableDiagnostics ? NoOpTrace.Singleton : (ITrace)Tracing.Trace.GetRootTrace(operationName, traceComponent, traceLevel)) { + trace.AddDatum("Client Configuration", this.client.ClientConfigurationTraceDatum); trace.AddDatum("Synchronization Context", syncContextVirtualAddress); return await this.RunWithDiagnosticsHelperAsync( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs index a51a77f14f..fd7ab80eb0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs @@ -85,6 +85,7 @@ public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) Assert.IsNotNull(response); string diagnostics = response.Diagnostics.ToString(); Assert.IsTrue(diagnostics.Contains("Synchronization Context")); + Assert.IsTrue(diagnostics.Contains("Client Configuration")); using CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); From deab135c9b8709abf3e62f7be08e6c022513e4bf Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 7 Mar 2024 07:28:49 +0530 Subject: [PATCH 290/337] Distributed Tracing: Adds configuration to disable network level tracing in sdk permanently (#4333) * disable network level tracing in sdk * update sample * remove network level tracing logic altogrther * 'fix spelling --- .../Usage/OpenTelemetry/Program.cs | 1 - Microsoft.Azure.Cosmos/src/DocumentClient.cs | 7 + .../OpenTelemetryRecorderFactory.cs | 17 -- ...iterBaselineTests.BatchOperationsAsync.xml | 7 - ...riterBaselineTests.BulkOperationsAsync.xml | 70 ----- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 63 ---- ...EndTraceWriterBaselineTests.QueryAsync.xml | 49 --- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 28 -- ...TraceWriterBaselineTests.ReadManyAsync.xml | 14 - ...selineTests.StreamPointOperationsAsync.xml | 28 -- ...aselineTests.TypedPointOperationsAsync.xml | 28 -- .../DistributedTracingOTelTests.cs | 278 ------------------ 12 files changed, 7 insertions(+), 583 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs index 562ccb2902..24e9768379 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/Program.cs @@ -71,7 +71,6 @@ static async Task Main() AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); _traceProvider = Sdk.CreateTracerProviderBuilder() .AddSource("Azure.Cosmos.Operation", // Cosmos DB source for operation level telemetry - "Azure.Cosmos.Request", // Cosmos DB source for DIRECT Mode network request level telemetry "Sample.Application") .AddAzureMonitorTraceExporter(o => o.ConnectionString = aiConnectionString) // Set up exporter of your choice .AddHttpClientInstrumentation() // Added to capture HTTP telemetry diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 873f09fa51..ce1c9a43c2 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -6654,9 +6654,16 @@ private void InitializeDirectConnectivity(IStoreClientFactory storeClientFactory } else { + // It is decided to switch this feature off completely for external users but keep it unchanged for internal users, + // due to the nature of information, we are collecting here. RNTBD is internal protocol and we do not expose it to the customers. Documents.Telemetry.DistributedTracingOptions distributedTracingOptions = new () { +#if INTERNAL IsDistributedTracingEnabled = !this.cosmosClientTelemetryOptions.DisableDistributedTracing +#else + IsDistributedTracingEnabled = false +#endif + }; StoreClientFactory newClientFactory = new StoreClientFactory( diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 8117dda493..f1d02583f9 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -57,24 +57,7 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, clientContext: clientContext, config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); } -#if !INTERNAL - // Need a parent activity which groups all network activities under it and is logged in diagnostics and used for tracing purpose. - // If there are listeners at network level then scope is enabled and it tries to create activity. - // However, if available listeners are not subscribed to network event then it will lead to scope being enabled but no activity is created. - else - { - DiagnosticScope requestScope = LazyScopeFactory.Value.CreateScope(name: $"{OpenTelemetryAttributeKeys.NetworkLevelPrefix}.{operationName}"); - openTelemetryRecorder = requestScope.IsEnabled ? OpenTelemetryCoreRecorder.CreateNetworkLevelParentActivity(networkScope: requestScope) : openTelemetryRecorder; - } - // If there are no listeners at operation level and network level and no parent activity created. - // Then create a dummy activity as there should be a parent level activity always to send a traceid to the backend services through context propagation. - // The parent activity id is logged in diagnostics and used for tracing purpose. - if (Activity.Current is null) - { - openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateParentActivity(operationName); - } -#endif // Safety check as diagnostic logs should not break the code. if (Activity.Current?.TraceId != null) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml index be3f14d016..8e8a427763 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BatchOperationsAsync.xml @@ -160,13 +160,6 @@ South Central US 400/1001 - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 207 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index 5de1a309d7..af8d3b4cf7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -343,13 +343,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -687,13 +680,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1031,13 +1017,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1375,13 +1354,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1719,13 +1691,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2063,13 +2028,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2407,13 +2365,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2751,13 +2702,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -3095,13 +3039,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -3439,13 +3376,6 @@ Some Value Some Value - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 42d0cb4f23..9d6cb5c5a9 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -1118,20 +1118,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 304 - @@ -1878,20 +1864,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 304 - @@ -2619,20 +2591,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 304 - @@ -3380,20 +3338,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 304 - @@ -3718,13 +3662,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 5a1d7b5c43..7577f2ae4f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -723,13 +723,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1480,13 +1473,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2218,13 +2204,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2976,13 +2955,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -3808,13 +3780,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -4569,13 +4534,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -5350,13 +5308,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 78241c3050..736119560b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -656,13 +656,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1346,13 +1339,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2017,13 +2003,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -2708,13 +2687,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index ad6be29190..5f242a1d00 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -491,13 +491,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -1005,13 +998,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index 6bf7447aad..d49a6731e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -118,13 +118,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 201 - @@ -241,13 +234,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -372,13 +358,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -498,13 +477,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 204 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index c3ce1e8786..8cd5278ea1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -138,13 +138,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 201 - @@ -266,13 +259,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -407,13 +393,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 200 - @@ -537,13 +516,6 @@ Some Value South Central US - - Microsoft.DocumentDB - https://opentelemetry.io/schemas/1.23.0 - Some Value - 0 - 204 - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs deleted file mode 100644 index 43d9be341d..0000000000 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/DistributedTracingOTelTests.cs +++ /dev/null @@ -1,278 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json.Linq; - using OpenTelemetry.Trace; - using OpenTelemetry; - using AzureCore = global::Azure.Core; - using Microsoft.Azure.Cosmos.Telemetry; - using System.Diagnostics; - using Microsoft.Azure.Cosmos.Tracing; - using System.Net.Http; - using Microsoft.Azure.Cosmos.Tests; - - [VisualStudio.TestTools.UnitTesting.TestClass] - public sealed class DistributedTracingOTelTests : BaseCosmosClientHelper - { - [TestInitialize] - public void TestInitialize() - { - AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", true); - AzureCore.ActivityExtensions.ResetFeatureSwitch(); - } - - [DataTestMethod] - [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] - [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] - [DataRow(null, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "DirectMode and DistributedFlag On: Asserts activity creation at network level with Diagnostic TraceId being added to logs")] - public async Task SourceEnabled_FlagOn_DirectMode_RecordsOperationNetworkActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) - { - string[] sources = new string[] { operationLevelSource, networkLevelSource }; - sources = sources.Where(x => x != null).ToArray(); - - using TracerProvider provider = Sdk.CreateTracerProviderBuilder() - .AddCustomOtelExporter() - .AddSource(sources) - .Build(); - - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = false - }) - .WithConnectionModeDirect()); - - Container containerResponse = await this.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), - partitionKeyPath: "/id", - throughput: 20000); - - CosmosObject cosmosObject = CosmosObject.Create( - new Dictionary() - { - { "id", CosmosString.Create("1") } - }); - - ItemResponse createResponse = await containerResponse.CreateItemAsync(JToken.Parse(cosmosObject.ToString())); - - //Assert traceparent header in Direct mode request - Assert.IsTrue(createResponse.RequestMessage.Headers.TryGetValue("traceparent", out string traceheader)); - Assert.IsNotNull(traceheader); - string[] traceheaderParts = traceheader.Split('-'); - string traceheaderId = traceheaderParts[1]; - - //Assert traceId in Diagnostics logs - string diagnosticsCreateItem = createResponse.Diagnostics.ToString(); - JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateItem); - string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; - Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId)); - - //Assert diagnostics log trace id is same as parent trace id of the activity - string operationName = (string)objDiagnosticsCreate["name"]; - string traceIdCreateItem = CustomOtelExporter.CollectedActivities - .Where(x => x.OperationName.Contains(operationName)) - .FirstOrDefault() - .TraceId - .ToString(); - //Assert created activity traceId and diagnosticsLog traceId - Assert.AreEqual(distributedTraceId, traceIdCreateItem); - - //Assert requestHeader trace id and and diagnosticsLog traceId - Assert.AreEqual(distributedTraceId, traceheaderId); - - //Assert activity creation - Assert.IsNotNull(CustomOtelExporter.CollectedActivities); - - if (networkLevelSource != null) - { - // Assert activity created at network level have an existing parent activity - Activity networkLevelChildActivity = CustomOtelExporter.CollectedActivities - .Where(x => x.OperationName.Contains("Request")) - .FirstOrDefault(); - Assert.IsNotNull(CustomOtelExporter.CollectedActivities - .Where(x => x.Id == networkLevelChildActivity.ParentId)); - } - } - - [DataTestMethod] - [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation and network level with Diagnostic TraceId being added to logs")] - [DataRow($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", null, DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at operation level with Diagnostic TraceId being added to logs")] - [DataRow(null, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Request", DisplayName = "GatewayMode and DistributedFlag On: Asserts activity creation at network level with Diagnostic TraceId being added to logs")] - public async Task SourceEnabled_FlagOn_GatewayMode_RecordsOperationNetworkActivity_AssertLogTraceId_AssertTraceparent(string operationLevelSource, string networkLevelSource) - { - string[] sources = new string[] { operationLevelSource, networkLevelSource }; - sources = sources.Where(x => x != null).ToArray(); - - HttpClientHandlerHelper httpClientHandlerHelper = new HttpClientHandlerHelper - { - RequestCallBack = (request, cancellation) => - { - if (request.Headers.TryGetValues("traceparent", out IEnumerable traceparentHeaderValues)) - { - Assert.IsNotNull(traceparentHeaderValues); - } - return null; - } - }; - - using TracerProvider provider = Sdk.CreateTracerProviderBuilder() - .AddCustomOtelExporter() - .AddSource(sources) - .Build(); - - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = false - }) - .WithHttpClientFactory(() => new HttpClient(httpClientHandlerHelper)) - .WithConnectionModeGateway()); - - ContainerResponse containerResponse = await this.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), - partitionKeyPath: "/id", - throughput: 20000); - - //Assert traceId in Diagnostics logs - string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); - JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); - string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; - Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId)); - - //Assert diagnostics log trace id is same as parent trace id of the activity - string operationName = (string)objDiagnosticsCreate["name"]; - string traceIdCreateContainer = CustomOtelExporter.CollectedActivities - .Where(x => x.OperationName.Contains(operationName)) - .FirstOrDefault() - .TraceId - .ToString(); - Assert.AreEqual(distributedTraceId, traceIdCreateContainer); - - //Assert activity creation - Assert.IsNotNull(CustomOtelExporter.CollectedActivities); - } - - [DataTestMethod] - [DataRow(false, false, "random.source.name", DisplayName = "DirectMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] - [DataRow(true, false, "random.source.name", DisplayName = "GatewayMode, DistributedFlag On, Random/No Source:Asserts no activity creation")] - [DataRow(false, true, "random.source.name", DisplayName = "DirectMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] - [DataRow(true, true, "random.source.name", DisplayName = "GatewayMode, DistributedFlag Off, Random/No Source:Asserts no activity creation")] - [DataRow(false, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "DirectMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] - [DataRow(true, true, $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.Operation", DisplayName = "GatewayMode, DistributedFlag Off, OperationLevel Source:Asserts no activity creation")] - public async Task NoSourceNoFlagEnabled_ResultsInNoOperationNetworkActivityCreation_AssertLogTraceId(bool useGateway, bool disableDistributingTracing, string source) - { - using TracerProvider provider = Sdk.CreateTracerProviderBuilder() - .AddCustomOtelExporter() - .AddSource(source) - .Build(); - - if (useGateway) - { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = disableDistributingTracing - }) - .WithConnectionModeGateway()); - } - else - { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = disableDistributingTracing - })); - } - - ContainerResponse containerResponse = await this.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), - partitionKeyPath: "/id", - throughput: 20000); - - //Assert traceId in Diagnostics logs - string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); - JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); - - if (!disableDistributingTracing) - { - //DistributedTraceId present in logs - string distributedTraceId = (string)objDiagnosticsCreate["data"]["DistributedTraceId"]; - Assert.IsFalse(string.IsNullOrEmpty(distributedTraceId), "Distributed Trace Id is not there in diagnostics"); - } - else - { - //DistributedTraceId field not present in logs - Assert.IsNull(objDiagnosticsCreate["data"]["DistributedTraceId"], "Distributed Trace Id has value in diagnostics i.e. " + (string)objDiagnosticsCreate["data"]["DistributedTraceId"]); - } - - //Assert no activity with attached source is created - Assert.AreEqual(0, CustomOtelExporter.CollectedActivities.Count()); - } - - - [DataTestMethod] - [DataRow(false)] - [DataRow(true)] - public async Task SuppressListenerEvents_ResultsInNoScopeActivityCreation_AssertTraceIdNotNull(bool useGateway) - { - // Initialize CustomListener with suppression - CustomListener customListener = new CustomListener($"{OpenTelemetryAttributeKeys.DiagnosticNamespace}.*", "Azure-Cosmos-Operation-Request-Diagnostics", true); - - if (useGateway) - { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = false - }) - .WithConnectionModeGateway()); - } - else - { - await base.TestInit(validateSinglePartitionKeyRangeCacheCall: false, - customizeClientBuilder: (builder) => builder - .WithClientTelemetryOptions(new CosmosClientTelemetryOptions() - { - DisableDistributedTracing = false - })); - } - - ContainerResponse containerResponse = await this.database.CreateContainerAsync( - id: Guid.NewGuid().ToString(), - partitionKeyPath: "/id", - throughput: 20000); - - // Assert traceId in Diagnostics logs - string diagnosticsCreateContainer = containerResponse.Diagnostics.ToString(); - JObject objDiagnosticsCreate = JObject.Parse(diagnosticsCreateContainer); - Assert.IsNotNull(objDiagnosticsCreate["data"]["DistributedTraceId"], "Distributed Trace Id has value in diagnostics i.e. " + (string)objDiagnosticsCreate["data"]["DistributedTraceId"]); - - // Cleanup - customListener.Dispose(); - } - - [TestCleanup] - public async Task CleanUp() - { - await base.TestCleanup(); - - AppContext.SetSwitch("Azure.Experimental.EnableActivitySource", false); - AzureCore.ActivityExtensions.ResetFeatureSwitch(); - } - } -} \ No newline at end of file From c064a79d29053604e0ebf3bf3ea33552a4480ae1 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 13 Mar 2024 13:42:55 -0400 Subject: [PATCH 291/337] [Internal] ChangeFeedEstimator: Fixes ChangeFeedProcessorState.EstimatedLag to 1 When CFP is Dormant after a Partition Split (#4324) * adding a test to repro issue 4285 * fix plus e2e test * not all request have cosmos exception * add a quick unit test for ChangeFeedEstimatorIterator when Gone exception happens * added a test description * ignoring long running test. meant to be ran manually * move long running tests to its own folder and category; check response and header for status/substatus * one test category only, removed using, and exluding LongRunning category from build pipeline * Update templates/build-test.yml I am committing your suggestion. Also, the goal of this PR is not to executed long running tests. I will create a new PR for this. Because there are other unknowns that I need to answer. So for now, I just don't want it to be executed with the existing pipelines. Co-authored-by: Matias Quaranta * change name of connectionString ENV to something more intention revealing --------- Co-authored-by: Matias Quaranta Co-authored-by: Sourabh Jain --- .../ChangeFeedEstimatorIterator.cs | 34 ++- .../LongRunning/ChangeFeedEstimatorTests.cs | 259 ++++++++++++++++++ .../ChangeFeedEstimatorIteratorTests.cs | 62 +++++ templates/build-test.yml | 4 +- 4 files changed, 348 insertions(+), 11 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/LongRunning/ChangeFeedEstimatorTests.cs diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs index b70585597a..20108af23c 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs @@ -113,15 +113,15 @@ private ChangeFeedEstimatorIterator( public override Task> ReadNextAsync(CancellationToken cancellationToken = default) { return this.monitoredContainer.ClientContext.OperationHelperAsync( - operationName: "Change Feed Estimator Read Next Async", - containerName: this.monitoredContainer?.Id, - databaseName: this.monitoredContainer?.Database?.Id, - operationType: Documents.OperationType.ReadFeed, - requestOptions: null, - task: (trace) => this.ReadNextAsync(trace, cancellationToken), - openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response), - traceComponent: TraceComponent.ChangeFeed, - traceLevel: TraceLevel.Info); + operationName: "Change Feed Estimator Read Next Async", + containerName: this.monitoredContainer?.Id, + databaseName: this.monitoredContainer?.Database?.Id, + operationType: Documents.OperationType.ReadFeed, + requestOptions: null, + task: (trace) => this.ReadNextAsync(trace, cancellationToken), + openTelemetry: (response) => new OpenTelemetryResponse(responseMessage: response), + traceComponent: TraceComponent.ChangeFeed, + traceLevel: TraceLevel.Info); } public async Task> ReadNextAsync(ITrace trace, CancellationToken cancellationToken) @@ -279,6 +279,22 @@ private static IEnumerable GetItemsFromResponse(ResponseMessage respons try { ResponseMessage response = await iterator.ReadNextAsync(trace, cancellationToken).ConfigureAwait(false); + + // NOTE(philipthomas-MSFT): + // https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4285 + // Given a change feed processor has started, then stopped. + // And the change feed processor is now dormant. + // When a split occurs on the monitored container. + // And the change feed estimator has started. + // And it is using the same lease container before the split occured. + // And a ReadNextAsync returns a 410/1002 due to the partition no longer existing. + // Then the state of the change feed processor will have an estimatedLag equal to '1'. + + if (response.StatusCode == HttpStatusCode.Gone && response.Headers.SubStatusCode == Documents.SubStatusCodes.PartitionKeyRangeGone) + { + return (new ChangeFeedProcessorState(existingLease.CurrentLeaseToken, 1, existingLease.Owner), response); + } + if (response.StatusCode != HttpStatusCode.NotModified) { response.EnsureSuccessStatusCode(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/LongRunning/ChangeFeedEstimatorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/LongRunning/ChangeFeedEstimatorTests.cs new file mode 100644 index 0000000000..74a09aada9 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/LongRunning/ChangeFeedEstimatorTests.cs @@ -0,0 +1,259 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed.LongRunning +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + + /// + /// For future long running tests. + /// TODO: Setup a PR to include in a CI pipeline. + /// TODO: Need to determine what database account, connectionString, that these test + /// can be safely ran against. Make sure the connectionString is added to Environment + /// variables securely. + /// + [TestClass] + [TestCategory("LongRunning")] + public class ChangeFeedEstimatorTests + { + private readonly CancellationTokenSource CancellationTokenSource = new(); + + private CosmosClient CosmosClient { get; set; } + + private Database Database { get; set; } + + private CancellationToken CancellationToken { get; set; } + + private Container LeaseContainer { get; set; } + + private ContainerResponse MonitoredContainerResponse { get; set; } + + private Container MonitoredContainer { get; set; } + + private static readonly string ConnectionString = "TestCategory_LongRunning_Connectionstring"; + + [TestInitialize] + public async Task TestInitialize() + { + this.CancellationToken = this.CancellationTokenSource.Token; + + if (Environment.GetEnvironmentVariable(ChangeFeedEstimatorTests.ConnectionString) == null) + { + throw new ArgumentNullException(paramName: nameof(Environment.GetEnvironmentVariable)); + } + + this.CosmosClient = new CosmosClient(connectionString: Environment.GetEnvironmentVariable(ChangeFeedEstimatorTests.ConnectionString)); + + this.Database = await this.CosmosClient.CreateDatabaseIfNotExistsAsync( + id: Guid.NewGuid().ToString(), + throughput: 400, + cancellationToken: this.CancellationToken); + + Debug.WriteLine($"The {nameof(this.Database)} '{this.Database.Id}' was created."); + + this.LeaseContainer = await this.Database.CreateContainerIfNotExistsAsync( + containerProperties: new ContainerProperties + { + Id = "leases", + PartitionKeyPath = "/id", + }, cancellationToken: this.CancellationToken); + + Debug.WriteLine($"The {nameof(this.LeaseContainer)} '{this.LeaseContainer.Id}' was created."); + + this.MonitoredContainerResponse = await this.Database.CreateContainerIfNotExistsAsync( + containerProperties: new ContainerProperties + { + Id = Guid.NewGuid().ToString(), + PartitionKeyPath = "/pk", + }, cancellationToken: this.CancellationToken); + + this.MonitoredContainer = this.MonitoredContainerResponse.Container; + + Debug.WriteLine($"The {nameof(this.MonitoredContainer)} '{this.MonitoredContainer.Id}' was created."); + } + + [TestCleanup] + public async Task TestCleanup() + { + if (this.Database != null) + { + await this.Database.DeleteAsync(); + + Debug.WriteLine($"The database is deleted."); + } + + this.CancellationTokenSource?.Cancel(); + + this.CosmosClient.Dispose(); + } + + + /// + /// + /// Steps + /// 1. Create a database with 400 RU. + /// 2. Create a lease container. + /// 3. Create a monitored container. + /// 4. Load 100 documents. + /// 5. Create a CFP instance. + /// 6. Start the CFP instance. + /// 7. Stop the CFP instance. + /// 8. Update the RU to 12K on the database. + /// 9. Wait until the split happens on the monitored container. + /// 10. Load 100 more documents. + /// 11. Create a CFE instance. + /// a. (Use Estimator Iterator -> https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/how-to-use-change-feed-estimator?tabs=dotnet#as-an-on-demand-detailed-estimation) + /// 12. Boom! + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Used to repro an issue #4285")] + public async Task GivenADormantCFPWhenASplitOccursThenFeedEstimatorThrowsAnExceptionAsync() + { + string partitionKeyValue = Guid.NewGuid().ToString(); + + await LoadDocuments( + monitoredContainer: this.MonitoredContainer, + partitionKeyValue: partitionKeyValue, + cancellationToken: this.CancellationToken); + + ChangeFeedProcessor changeFeedProcessor = this.MonitoredContainer + .GetChangeFeedProcessorBuilder( + processorName: "changeFeedEstimator", + onChangesDelegate: (IReadOnlyCollection changes, CancellationToken cancellationToken) => Task.CompletedTask) + .WithInstanceName("consoleHost") + .WithLeaseContainer(this.LeaseContainer) + .WithErrorNotification(errorDelegate: (leaseToken, exception) => + { + Console.WriteLine($"{nameof(exception)}: {exception}"); + Console.WriteLine($"{nameof(leaseToken)}: {leaseToken}"); + + return Task.CompletedTask; + }) + .Build(); + + await changeFeedProcessor.StartAsync(); + + await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); + + await changeFeedProcessor.StopAsync(); + + await UpdateThroughput( + database: this.Database, + cosmosClient: this.CosmosClient, + monitoredContainerResponse: this.MonitoredContainerResponse, + throughtput: 12000); + + await LoadDocuments( + monitoredContainer: this.MonitoredContainer, + partitionKeyValue: partitionKeyValue, + startAt: 100, + endAt: 200, + cancellationToken: this.CancellationToken); + + ChangeFeedEstimator changeFeedEstimator = this.MonitoredContainer + .GetChangeFeedEstimator( + processorName: "changeFeedEstimator", + leaseContainer: this.LeaseContainer); + + Debug.WriteLine("Checking estimation..."); + + using FeedIterator estimatorIterator = changeFeedEstimator.GetCurrentStateIterator(); + + long actualEstimatedLog = 0; + + while (estimatorIterator.HasMoreResults) + { + FeedResponse states = await estimatorIterator.ReadNextAsync(this.CancellationToken); + + foreach (ChangeFeedProcessorState leaseState in states) + { + Debug.WriteLine(JsonConvert.SerializeObject(leaseState)); + + string host = leaseState.InstanceName == null ? $"not owned by any host currently" : $"owned by host {leaseState.InstanceName}"; + + Debug.WriteLine($"Lease [{leaseState.LeaseToken}] {host} reports {leaseState.EstimatedLag} as estimated lag."); + + actualEstimatedLog = leaseState.EstimatedLag; + } + } + + Assert.AreEqual(expected: 1, actual: actualEstimatedLog); + } + + /// + /// Update the throughput and wait for a split. + /// + /// The database. + /// The CosmosClient. + /// The monitored container's response. + /// The throughput. + /// The number of partitions detected before the split. Loop breaks when the overlapping ranges count is no longer the same as the partition count. + /// The number of minutes to timeout. + /// + private static async Task UpdateThroughput( + Database database, + CosmosClient cosmosClient, + ContainerResponse monitoredContainerResponse, + int throughtput, + int partitionCount = 1, + double timeoutInMinutes = 25) + { + _ = await database.ReplaceThroughputAsync(throughput: throughtput); + Routing.PartitionKeyRangeCache partitionKeyRangeCache = await cosmosClient.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); + Stopwatch stopWatch = Stopwatch.StartNew(); + IReadOnlyList overlappingRanges; + + do + { + overlappingRanges = await partitionKeyRangeCache.TryGetOverlappingRangesAsync( + collectionRid: monitoredContainerResponse.Resource.ResourceId, + range: FeedRangeEpk.FullRange.Range, + trace: NoOpTrace.Singleton, + forceRefresh: true); + + if (stopWatch.Elapsed.TotalMinutes > timeoutInMinutes) // failsafe to break loop if it takes longer than 'timeoutInMinutes' to split. + { + break; + } + + } while (overlappingRanges.Count == partitionCount); // when overlapping ranges count no longer equals the partitionCount, break loop. + + Debug.WriteLine($"{nameof(overlappingRanges)}: {JsonConvert.SerializeObject(overlappingRanges)}"); + + stopWatch.Stop(); + TimeSpan timeTakenForASplit = stopWatch.Elapsed; + string elapsedTime = string.Format("{0:00}:{1:00}:{2:00}.{3:00}", + timeTakenForASplit.Hours, timeTakenForASplit.Minutes, timeTakenForASplit.Seconds, + timeTakenForASplit.Milliseconds / 10); + + Debug.WriteLine($"Time taken for a split to occur: {elapsedTime}"); + } + + private static async Task LoadDocuments( + Container monitoredContainer, + string partitionKeyValue, + int endAt = 100, + int startAt = 0, + CancellationToken cancellationToken = default) + { + for (int counter = startAt; counter < endAt; counter++) + { + _ = await monitoredContainer.CreateItemAsync( + item: new { id = counter.ToString(), pk = partitionKeyValue }, + partitionKey: new PartitionKey(partitionKeyValue), + cancellationToken: cancellationToken); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs index 232c0c9e3a..8589a5e049 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedEstimatorIteratorTests.cs @@ -14,6 +14,8 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.Tests using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Collections; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json.Linq; @@ -324,6 +326,53 @@ FeedIteratorInternal feedCreator(DocumentServiceLease lease, string continuation Assert.AreEqual(leaseToken, remainingLeaseWork.LeaseToken); } + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Testing that estimated lag returns a value of 1 when a 410/1002 status/subStatus occurs.")] + public async Task ShouldReturnEstimatedLagIsOneWhenGoneCosmosException() + { + // Arrange + string instanceName = Guid.NewGuid().ToString(); + string leaseToken = Guid.NewGuid().ToString(); + List ranges = new List() { leaseToken }; + + List leases = new List() { + new DocumentServiceLeaseCore() + { + LeaseToken = leaseToken, + Owner = instanceName + } + }; + Mock mockIterator = new Mock(); + mockIterator.Setup(i => i.ReadNextAsync(It.IsAny(), It.IsAny())).ReturnsAsync(GetResponseWithGoneStatusCosmosException); + Mock mockContainer = new Mock(); + mockContainer.Setup(c => c.GetAllLeasesAsync()).ReturnsAsync(leases); + + FeedIteratorInternal feedCreator(DocumentServiceLease lease, string continuationToken, bool startFromBeginning) + { + return mockIterator.Object; + } + + // Act + + ChangeFeedEstimatorIterator remainingWorkEstimator = new ChangeFeedEstimatorIterator( + ChangeFeedEstimatorIteratorTests.GetMockedContainer(), + Mock.Of(), + mockContainer.Object, + feedCreator, + null); + + // Assert + + FeedResponse firstResponse = await remainingWorkEstimator.ReadNextAsync(default); + + ChangeFeedProcessorState remainingLeaseWork = firstResponse.First(); + + Assert.AreEqual(expected: instanceName, actual: remainingLeaseWork.InstanceName); + Assert.AreEqual(expected: leaseToken, actual: remainingLeaseWork.LeaseToken); + Assert.AreEqual(expected: 1, actual: remainingLeaseWork.EstimatedLag); + } + [TestMethod] public async Task ShouldInitializeDocumentLeaseContainer() { @@ -421,6 +470,19 @@ private static ResponseMessage GetResponse(HttpStatusCode statusCode, string loc return message; } + private static ResponseMessage GetResponseWithGoneStatusCosmosException() + { + return new ResponseMessage( + statusCode: HttpStatusCode.Gone, + requestMessage: new RequestMessage( + method: System.Net.Http.HttpMethod.Get, + requestUriString: default, + trace: NoOpTrace.Singleton), + headers: new Headers() { SubStatusCode = SubStatusCodes.PartitionKeyRangeGone}, + cosmosException: default, + trace: NoOpTrace.Singleton); + } + private static ContainerInternal GetMockedContainer() { Mock mockClient = new Mock(); diff --git a/templates/build-test.yml b/templates/build-test.yml index 8d22aeb758..61ae6e48b7 100644 --- a/templates/build-test.yml +++ b/templates/build-test.yml @@ -5,8 +5,8 @@ parameters: Arguments: '' VmImage: '' # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops OS: 'Windows' - EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' - EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed" --verbosity normal ' + EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=LongRunning & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' + EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed & TestCategory!=LongRunning" --verbosity normal ' EmulatorPipeline1CategoryListName: ' Client Telemetry, Query, ChangeFeed, ReadFeed, Batch ' # Divided in 2 categories to run them in parallel and reduce the PR feedback time EmulatorPipeline2CategoryListName: ' Others ' From f0953f69fcf608a5d057cf581fe21906c0955175 Mon Sep 17 00:00:00 2001 From: Xavier Date: Fri, 15 Mar 2024 12:02:11 -0700 Subject: [PATCH 292/337] Update ReplicaValidationDesign.md (#4352) Fix spelling --- docs/ReplicaValidationDesign.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ReplicaValidationDesign.md b/docs/ReplicaValidationDesign.md index 0e23db09d7..f03b725a28 100644 --- a/docs/ReplicaValidationDesign.md +++ b/docs/ReplicaValidationDesign.md @@ -19,7 +19,7 @@ The scope of the replica validation workstream is targed for the `CosmosClient` configured for `Direct` mode. -## Backgraund +## Background During an upgrade scenario in the backend replica nodes, there has been an observation of increased request latency. One of the primary reason for the latency is that, during an upgrade, a replica which is still undergoing upgrade may still be returned back to SDK, when an address refresh occurres. As of today, the incoming request will have `25%` chance to hit the replica that not ready yet, therefore causing the `ConnectionTimeoutException`, which contributes to the increased latency. @@ -335,4 +335,4 @@ Here is the [link to a sample PR](https://github.com/Azure/azure-cosmos-dotnet-v - [Mermaid Documentation.](https://mermaid-js.github.io/mermaid/#/) - [Upgrade Resiliency Tasks List.](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3409) -- [Design Document to Utilize RNTBD Context Negotiation During `CosmosClient` Initialization.](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3442) \ No newline at end of file +- [Design Document to Utilize RNTBD Context Negotiation During `CosmosClient` Initialization.](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3442) From 652b99d98cbd63d9d99b57d533dc5a94caa2544b Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Sat, 16 Mar 2024 20:04:10 -0700 Subject: [PATCH 293/337] added known issue (#4349) --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index d87d89a505..48a400269a 100644 --- a/changelog.md +++ b/changelog.md @@ -1317,6 +1317,7 @@ Below is a list of any know issues affecting the [recommended minimum version](# | Issue | Impact | Mitigation | Tracking link | | --- | --- | --- | --- | +| `FeedIterator` enters an infinite loop after a physical partition split occurs in a container using hierarchical partition keys. | Queries using prefix partition keys. | Rather than having the PK included in the query request options, filtering on top level hierarchical Pks should be done through where clauses. | [#4326](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4326) | ## Release & Retirement dates From ab8017023d7414e4966679bdaa6c6abe8842ffd9 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:49:06 -0700 Subject: [PATCH 294/337] [Internal] Pipelines: Adds yml Files for New Multi-region CI Pipelines (#4301) * added yml files * added TestCategory param * fixed pipeline yml files * Update templates/build-test.yml Co-authored-by: Matias Quaranta * suggested changes --------- Co-authored-by: Matias Quaranta --- templates/build-test.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/templates/build-test.yml b/templates/build-test.yml index 61ae6e48b7..42c67d664c 100644 --- a/templates/build-test.yml +++ b/templates/build-test.yml @@ -7,8 +7,10 @@ parameters: OS: 'Windows' EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=LongRunning & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed & TestCategory!=LongRunning" --verbosity normal ' + EmulatorPipeline3Arguments: ' --filter "TestCategory=MultiRegion" --verbosity normal ' EmulatorPipeline1CategoryListName: ' Client Telemetry, Query, ChangeFeed, ReadFeed, Batch ' # Divided in 2 categories to run them in parallel and reduce the PR feedback time EmulatorPipeline2CategoryListName: ' Others ' + EmulatorPipeline3CategoryListName: ' MultiRegion ' jobs: - job: @@ -205,3 +207,32 @@ jobs: nugetConfigPath: NuGet.config publishTestResults: true testRunTitle: Microsoft.Azure.Cosmos.Encryption.Custom.EmulatorTests + +- job: + displayName: EmulatorTests ${{ parameters.BuildConfiguration }} - ${{ parameters.EmulatorPipeline3CategoryListName }} + timeoutInMinutes: 120 + condition: and(succeeded(), eq('${{ parameters.OS }}', 'Windows')) + pool: + vmImage: ${{ parameters.VmImage }} + + steps: + - checkout: self # self represents the repo where the initial Pipelines YAML file was found + clean: true # if true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching + + # Add this Command to Include the .NET 6 SDK + - task: UseDotNet@2 + displayName: Use .NET 6.0 + inputs: + packageType: 'sdk' + version: '6.x' + + - task: DotNetCoreCLI@2 + displayName: Microsoft.Azure.Cosmos.EmulatorTests + condition: succeeded() + inputs: + command: test + projects: 'Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/*.csproj' + arguments: ${{ parameters.EmulatorPipeline3Arguments }} --configuration ${{ parameters.BuildConfiguration }} /p:OS=${{ parameters.OS }} + nugetConfigPath: NuGet.config + publishTestResults: true + testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests From d1f879fed11531280897d796088d1c7be2796ab7 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 22 Mar 2024 06:56:54 +0530 Subject: [PATCH 295/337] Distributed Tracing Documentation : Fixes the default value mentioned in code doc (#4357) * Distributed Tracing Dcoumentation : Changed the default value mentioned in comment * Update Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs Co-authored-by: Matias Quaranta --------- Co-authored-by: Matias Quaranta --- Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs index 57b7cbf57a..b4f59d25f0 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs @@ -14,13 +14,13 @@ public class CosmosThresholdOptions /// /// Latency Threshold for non point operations i.e. Query /// - /// 500 ms + /// 3 seconds public TimeSpan NonPointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(3); /// /// Latency Threshold for point operations i.e operation other than Query /// - /// 100 ms + /// 1 second public TimeSpan PointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(1); } } From dbdf8064f538c35fc1566554cad68e62eb509d20 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Fri, 22 Mar 2024 10:39:33 -0400 Subject: [PATCH 296/337] ChangeFeedProcessor: Fixes when ChangeFeedMode is switched should throw an exception. (#4334) * test to prove no exception, no documents when change feed more is changed. * renaming * throwing exception when changeFeedMode change on CFP with same lease container * removed PREVIEW tags under advisement. Well create a PR later * removed usings * revert to old summary * defaulting change feed mode to latestversion * change feed mode exception on switching and tests based on last recommendation. * more changes based on discussions * some refactoring * fixed some tests * more changes based on recommendations * another refactor * change from CosmosException to ArgumentException * removed CosmosException from comments * fixin tests to account for extra GetAllLeasesAsync call * some recommendation changes --- .../ChangeFeedEstimatorIterator.cs | 3 +- .../ChangeFeedEstimatorRunner.cs | 13 +- .../ChangeFeedProcessorBuilder.cs | 4 +- .../ChangeFeedProcessorCore.cs | 27 +- .../Configuration/ChangeFeedLeaseOptions.cs | 5 + .../LeaseManagement/DocumentServiceLease.cs | 5 + .../DocumentServiceLeaseCore.cs | 3 + .../DocumentServiceLeaseCoreEpk.cs | 3 + .../DocumentServiceLeaseManager.cs | 54 ++++ .../DocumentServiceLeaseManagerCosmos.cs | 13 +- ...DocumentServiceLeaseStoreManagerBuilder.cs | 14 +- ...DocumentServiceLeaseStoreManagerOptions.cs | 2 + .../src/Resource/Container/Container.cs | 1 - ...orBuilderWithAllVersionsAndDeletesTests.cs | 274 ++++++++++++++++-- .../ChangeFeedProcessorCoreTests.cs | 5 +- ...entServiceLeaseStoreManagerBuilderTests.cs | 12 +- 16 files changed, 394 insertions(+), 44 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs index 20108af23c..4d1fc6fd4a 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorIterator.cs @@ -334,7 +334,8 @@ private async Task InitializeLeaseStoreAsync(ITrace trace, CancellationToken can monitoredContainer: this.monitoredContainer, leaseContainer: this.leaseContainer, leaseContainerPrefix: leasePrefix, - instanceName: ChangeFeedEstimatorIterator.EstimatorDefaultHostName); + instanceName: ChangeFeedEstimatorIterator.EstimatorDefaultHostName, + changeFeedMode: ChangeFeedMode.LatestVersion); this.documentServiceLeaseContainer = documentServiceLeaseStoreManager.LeaseContainer; } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorRunner.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorRunner.cs index 8f8a8b9d81..e3d4468d0f 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorRunner.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedEstimatorRunner.cs @@ -139,11 +139,14 @@ private async Task InitializeLeaseStoreAsync() { string monitoredContainerAndDatabaseRid = await this.monitoredContainer.GetMonitoredDatabaseAndContainerRidAsync(default); string leasePrefix = this.monitoredContainer.GetLeasePrefix(this.changeFeedLeaseOptions.LeasePrefix, monitoredContainerAndDatabaseRid); - DocumentServiceLeaseStoreManager documentServiceLeaseStoreManager = await DocumentServiceLeaseStoreManagerBuilder.InitializeAsync( - monitoredContainer: this.monitoredContainer, - leaseContainer: this.leaseContainer, - leaseContainerPrefix: leasePrefix, - instanceName: ChangeFeedEstimatorRunner.EstimatorDefaultHostName); + DocumentServiceLeaseStoreManager documentServiceLeaseStoreManager = await DocumentServiceLeaseStoreManagerBuilder + .InitializeAsync( + monitoredContainer: this.monitoredContainer, + leaseContainer: this.leaseContainer, + leaseContainerPrefix: leasePrefix, + instanceName: ChangeFeedEstimatorRunner.EstimatorDefaultHostName, + changeFeedMode: ChangeFeedMode.LatestVersion) + .ConfigureAwait(false); this.documentServiceLeaseContainer = documentServiceLeaseStoreManager.LeaseContainer; } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs index df3db6f2bf..49bfa9d816 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorBuilder.cs @@ -70,13 +70,15 @@ public ChangeFeedProcessorBuilder WithInstanceName(string instanceName) } /// - /// Sets the mode for the change freed processor. + /// Sets the mode for the change feed processor. /// /// /// The instance of to use. internal ChangeFeedProcessorBuilder WithChangeFeedMode(ChangeFeedMode changeFeedMode) { this.changeFeedProcessorOptions.Mode = changeFeedMode; + this.changeFeedLeaseOptions.Mode = changeFeedMode; + return this; } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorCore.cs index 94c3e09dac..db0ecacb32 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/ChangeFeedProcessorCore.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed { using System; + using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.ChangeFeed.Bootstrapping; using Microsoft.Azure.Cosmos.ChangeFeed.Configuration; @@ -14,6 +15,7 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed using Microsoft.Azure.Cosmos.ChangeFeed.Utils; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; internal sealed class ChangeFeedProcessorCore : ChangeFeedProcessor { @@ -75,19 +77,36 @@ public override async Task StopAsync() private async Task InitializeAsync() { string containerRid = await this.monitoredContainer.GetCachedRIDAsync( - forceRefresh: false, - NoOpTrace.Singleton, + forceRefresh: false, + NoOpTrace.Singleton, default); + string monitoredDatabaseAndContainerRid = await this.monitoredContainer.GetMonitoredDatabaseAndContainerRidAsync(); string leaseContainerPrefix = this.monitoredContainer.GetLeasePrefix(this.changeFeedLeaseOptions.LeasePrefix, monitoredDatabaseAndContainerRid); Routing.PartitionKeyRangeCache partitionKeyRangeCache = await this.monitoredContainer.ClientContext.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton); if (this.documentServiceLeaseStoreManager == null) { - this.documentServiceLeaseStoreManager = await DocumentServiceLeaseStoreManagerBuilder.InitializeAsync(this.monitoredContainer, this.leaseContainer, leaseContainerPrefix, this.instanceName).ConfigureAwait(false); + this.documentServiceLeaseStoreManager = await DocumentServiceLeaseStoreManagerBuilder + .InitializeAsync( + this.monitoredContainer, + this.leaseContainer, + leaseContainerPrefix, + this.instanceName, + changeFeedMode: this.changeFeedProcessorOptions.Mode) + .ConfigureAwait(false); } + this.documentServiceLeaseStoreManager + .LeaseManager + .ChangeFeedModeSwitchingCheck( + documentServiceLeases: await this.documentServiceLeaseStoreManager + .LeaseContainer + .GetAllLeasesAsync() + .ConfigureAwait(false), + changeFeedLeaseOptionsMode: this.changeFeedLeaseOptions.Mode); + this.partitionManager = this.BuildPartitionManager( - containerRid, + containerRid, partitionKeyRangeCache); this.initialized = true; } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedLeaseOptions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedLeaseOptions.cs index e72e00efb9..dac334c038 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedLeaseOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Configuration/ChangeFeedLeaseOptions.cs @@ -44,5 +44,10 @@ public ChangeFeedLeaseOptions() /// instances pointing at the same feed while using the same auxiliary collection. /// public string LeasePrefix { get; set; } + + /// + /// Gets or sets the . + /// + public ChangeFeedMode Mode { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLease.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLease.cs index 95200f48ee..ab9d6beb43 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLease.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLease.cs @@ -70,5 +70,10 @@ internal abstract class DocumentServiceLease /// Gets or sets custom lease properties which can be managed from . /// public abstract Dictionary Properties { get; set; } + + /// + /// Gets or sets the ChangeFeedMode. + /// + public abstract string Mode { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCore.cs index 65e4e6e725..ed6b050278 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCore.cs @@ -95,6 +95,9 @@ public override DateTime Timestamp [JsonProperty("_ts")] private long TS { get; set; } + [JsonProperty("Mode", NullValueHandling = NullValueHandling.Ignore)] + public override string Mode { get; set; } + public override string ToString() { return string.Format( diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCoreEpk.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCoreEpk.cs index 55c4105c3a..ab46ebba29 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCoreEpk.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseCoreEpk.cs @@ -66,6 +66,9 @@ public override DateTime Timestamp [JsonProperty("properties")] public override Dictionary Properties { get; set; } = new Dictionary(); + [JsonProperty("Mode", NullValueHandling = NullValueHandling.Ignore)] + public override string Mode { get; set; } + [JsonProperty("timestamp")] private DateTime? ExplicitTimestamp { get; set; } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs index 27dafd2162..18b0e790ba 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs @@ -4,6 +4,8 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.LeaseManagement { + using System; + using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.ChangeFeed.Exceptions; using Microsoft.Azure.Documents; @@ -63,5 +65,57 @@ internal abstract class DocumentServiceLeaseManager /// Updated lease. /// Thrown if other host acquired the lease public abstract Task UpdatePropertiesAsync(DocumentServiceLease leaseToUpdatePropertiesFrom); + + /// + /// If the lease container's lease document is found, this method checks for lease + /// document's ChangeFeedMode and if the new ChangeFeedMode is different + /// from the current ChangeFeedMode, an exception is thrown. + /// This is based on an issue located at . + /// + public void ChangeFeedModeSwitchingCheck( + IReadOnlyList documentServiceLeases, + ChangeFeedMode changeFeedLeaseOptionsMode) + { + // No lease documents. Return. + + if (documentServiceLeases.Count == 0) + { + return; + } + + DocumentServiceLease documentServiceLease = documentServiceLeases[0]; + + // Mode attribute exists on lease document, but it is not set. legacy is always LatestVersion because + // AllVersionsAndDeletes does not exist. There should not be any legacy lease documents that are + // AllVersionsAndDeletes. If the ChangeFeedProcessor's mode is not legacy, an exception should thrown. + // If the ChangeFeedProcessor mode is not the mode in the lease document, an exception should be thrown. + + bool shouldThrowException = this.VerifyChangeFeedProcessorMode( + changeFeedMode: + string.IsNullOrEmpty(documentServiceLease.Mode) + ? ChangeFeedMode.LatestVersion + : changeFeedLeaseOptionsMode, + leaseChangeFeedMode: documentServiceLease.Mode, + normalizedProcessorChangeFeedMode: out string normalizedProcessorChangeFeedMode); + + // If shouldThrowException is true, throw the exception. + + if (shouldThrowException) + { + throw new ArgumentException(message: $"Switching {nameof(ChangeFeedMode)} {documentServiceLease.Mode} to {normalizedProcessorChangeFeedMode} is not allowed."); + } + } + + private bool VerifyChangeFeedProcessorMode( + ChangeFeedMode changeFeedMode, + string leaseChangeFeedMode, + out string normalizedProcessorChangeFeedMode) + { + normalizedProcessorChangeFeedMode = changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes + ? HttpConstants.A_IMHeaderValues.FullFidelityFeed + : HttpConstants.A_IMHeaderValues.IncrementalFeed; + + return string.Compare(leaseChangeFeedMode, normalizedProcessorChangeFeedMode, StringComparison.OrdinalIgnoreCase) != 0; + } } } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs index d5a75abb47..0f343a7732 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManagerCosmos.cs @@ -124,7 +124,8 @@ public override Task CreateLeaseIfNotExistAsync( LeaseId = leaseDocId, LeaseToken = leaseToken, ContinuationToken = continuationToken, - FeedRange = new FeedRangeEpk(partitionKeyRange.ToRange()) + FeedRange = new FeedRangeEpk(partitionKeyRange.ToRange()), + Mode = this.GetChangeFeedMode() }; this.requestOptionsFactory.AddPartitionKeyIfNeeded((string pk) => documentServiceLease.LeasePartitionKey = pk, Guid.NewGuid().ToString()); @@ -148,7 +149,8 @@ public override Task CreateLeaseIfNotExistAsync( LeaseId = leaseDocId, LeaseToken = leaseToken, ContinuationToken = continuationToken, - FeedRange = feedRange + FeedRange = feedRange, + Mode = this.GetChangeFeedMode() }; this.requestOptionsFactory.AddPartitionKeyIfNeeded((string pk) => documentServiceLease.LeasePartitionKey = pk, Guid.NewGuid().ToString()); @@ -156,6 +158,13 @@ public override Task CreateLeaseIfNotExistAsync( return this.TryCreateDocumentServiceLeaseAsync(documentServiceLease); } + private string GetChangeFeedMode() + { + return this.options.Mode == ChangeFeedMode.AllVersionsAndDeletes + ? HttpConstants.A_IMHeaderValues.FullFidelityFeed + : HttpConstants.A_IMHeaderValues.IncrementalFeed; + } + public override async Task ReleaseAsync(DocumentServiceLease lease) { if (lease == null) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerBuilder.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerBuilder.cs index 70358bca22..b5fb29a095 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerBuilder.cs @@ -22,7 +22,8 @@ public static async Task InitializeAsync( ContainerInternal monitoredContainer, ContainerInternal leaseContainer, string leaseContainerPrefix, - string instanceName) + string instanceName, + ChangeFeedMode changeFeedMode) { ContainerProperties containerProperties = await leaseContainer.GetCachedContainerPropertiesAsync(forceRefresh: false, NoOpTrace.Singleton, cancellationToken: default); @@ -58,7 +59,8 @@ public static async Task InitializeAsync( .WithMonitoredContainer(monitoredContainer) .WithLeaseContainer(leaseContainer) .WithRequestOptionsFactory(requestOptionsFactory) - .WithHostName(instanceName); + .WithHostName(instanceName) + .WithChangeFeedMode(changeFeedMode); return leaseStoreManagerBuilder.Build(); } @@ -70,7 +72,7 @@ public static async Task InitializeAsync( private DocumentServiceLeaseStoreManagerBuilder WithMonitoredContainer(ContainerInternal monitoredContainer) { - this.monitoredContainer = monitoredContainer ?? throw new ArgumentNullException(nameof(leaseContainer)); + this.monitoredContainer = monitoredContainer ?? throw new ArgumentNullException(nameof(monitoredContainer)); return this; } @@ -98,6 +100,12 @@ private DocumentServiceLeaseStoreManagerBuilder WithHostName(string hostName) return this; } + private DocumentServiceLeaseStoreManagerBuilder WithChangeFeedMode(ChangeFeedMode changeFeedMode) + { + this.options.Mode = changeFeedMode ?? throw new ArgumentNullException(nameof(changeFeedMode)); + return this; + } + private DocumentServiceLeaseStoreManager Build() { if (this.monitoredContainer == null) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerOptions.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerOptions.cs index 146c7a32a3..942db791db 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerOptions.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseStoreManagerOptions.cs @@ -16,5 +16,7 @@ internal string GetPartitionLeasePrefix() { return this.ContainerNamePrefix + PartitionLeasePrefixSeparator; } + + internal ChangeFeedMode Mode { get; set; } } } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 21d660b744..5936f5e05d 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -1681,7 +1681,6 @@ public abstract Task DeleteAllItemsByPartitionKeyStreamAsync( public abstract Task> GetPartitionKeyRangesAsync( FeedRange feedRange, CancellationToken cancellationToken = default); - #endif } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs index 9292e4d1e7..33f5d9d0c4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs @@ -6,31 +6,20 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] - [TestCategory("ChangeFeedProcessor with AllVersionsAndDeletes")] + [TestCategory("ChangeFeedProcessor")] public class GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests : BaseChangeFeedClientHelper { - private ContainerInternal Container; - [TestInitialize] public async Task TestInitialize() { await base.ChangeFeedTestInit(); - - string PartitionKey = "/pk"; - ContainerProperties properties = new ContainerProperties(id: Guid.NewGuid().ToString(), - partitionKeyPath: PartitionKey); - properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5); - - ContainerResponse response = await this.database.CreateContainerAsync(properties, - throughput: 10000, - cancellationToken: this.cancellationToken); - this.Container = (ContainerInternal)response; } [TestCleanup] @@ -42,13 +31,14 @@ public async Task Cleanup() [TestMethod] [Owner("philipthomas-MSFT")] [Description("Scenario: When a document is created, then updated, and finally deleted, there should be 3 changes that will appear for that " + - "document when using ChangeFeedProcessor with AllVersionsAndDeletes.")] + "document when using ChangeFeedProcessor with AllVersionsAndDeletes set as the ChangeFeedMode.")] public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.AllVersionsAndDeletes); ManualResetEvent allDocsProcessed = new ManualResetEvent(false); Exception exception = default; - ChangeFeedProcessor processor = this.Container + ChangeFeedProcessor processor = monitoredContainer .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> docs, CancellationToken token) => { string id = default; @@ -117,7 +107,7 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The create operation must happen before the replace operation."); Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The replace operation must happen before the delete operation."); - Console.WriteLine("Assertions completed."); + Debug.WriteLine("Assertions completed."); return Task.CompletedTask; }) @@ -126,7 +116,9 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() .WithErrorNotification((leaseToken, error) => { exception = error.InnerException; - Console.WriteLine(error.ToString()); + + Debug.WriteLine("WithErrorNotification"); + Debug.WriteLine(error.ToString()); return Task.CompletedTask; }) @@ -138,13 +130,13 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() await processor.StartAsync(); await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); - await this.Container.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); + await monitoredContainer.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); await Task.Delay(1000); - - await this.Container.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); + + await monitoredContainer.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); await Task.Delay(1000); - await this.Container.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); + await monitoredContainer.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); bool isStartOk = allDocsProcessed.WaitOne(10 * BaseChangeFeedClientHelper.ChangeFeedSetupTime); @@ -155,5 +147,245 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.Fail(exception.ToString()); } } + + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: When ChangeFeedMode on ChangeFeedProcessor, switches from LatestVersion to AllVersionsAndDeletes," + + "an exception is expected. LatestVersion's WithStartFromBeginning can be set, or not set.")] + [DataRow(false)] + [DataRow(true)] + public async Task WhenLatestVersionSwitchToAllVersionsAndDeletesExpectsAexceptionTestAsync(bool withStartFromBeginning) + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.LatestVersion); + ManualResetEvent allDocsProcessed = new(false); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + + ArgumentException exception = await Assert.ThrowsExceptionAsync( + () => GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed)); + + Debug.WriteLine(exception.ToString()); + + Assert.AreEqual(expected: "Switching ChangeFeedMode Incremental Feed to Full-Fidelity Feed is not allowed.", actual: exception.Message); + + Debug.WriteLine("Assertions completed."); + } + + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: When ChangeFeedMode on ChangeFeedProcessor, switches from AllVersionsAndDeletes to LatestVersion," + + "an exception is expected. LatestVersion's WithStartFromBeginning can be set, or not set.")] + [DataRow(false)] + [DataRow(true)] + public async Task WhenAllVersionsAndDeletesSwitchToLatestVersionExpectsAexceptionTestAsync(bool withStartFromBeginning) + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.AllVersionsAndDeletes); + ManualResetEvent allDocsProcessed = new(false); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed); + + ArgumentException exception = await Assert.ThrowsExceptionAsync( + () => GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning)); + + Debug.WriteLine(exception.ToString()); + + Assert.AreEqual(expected: "Switching ChangeFeedMode Full-Fidelity Feed to Incremental Feed is not allowed.", actual: exception.Message); + + Debug.WriteLine("Assertions completed."); + } + + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: When ChangeFeedMode on ChangeFeedProcessor does not switch, AllVersionsAndDeletes," + + "no exception is expected.")] + public async Task WhenNoSwitchAllVersionsAndDeletesFDoesNotExpectAexceptionTestAsync() + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.AllVersionsAndDeletes); + ManualResetEvent allDocsProcessed = new(false); + + try + { + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed); + + Debug.WriteLine("No exceptions occurred."); + } + catch + { + Assert.Fail("An exception occurred when one was not expceted."); ; + } + } + + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: When ChangeFeedMode on ChangeFeedProcessor does not switch, LatestVersion," + + "no exception is expected. LatestVersion's WithStartFromBeginning can be set, or not set.")] + [DataRow(false)] + [DataRow(true)] + public async Task WhenNoSwitchLatestVersionDoesNotExpectAexceptionTestAsync(bool withStartFromBeginning) + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.LatestVersion); + ManualResetEvent allDocsProcessed = new(false); + + try + { + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + + Debug.WriteLine("No exceptions occurred."); + } + catch + { + Assert.Fail("An exception occurred when one was not expceted."); ; + } + } + + private static async Task BuildChangeFeedProcessorWithLatestVersionAsync( + ContainerInternal monitoredContainer, + Container leaseContainer, + ManualResetEvent allDocsProcessed, + bool withStartFromBeginning) + { + Exception exception = default; + ChangeFeedProcessor latestVersionProcessorAtomic = null; + + ChangeFeedProcessorBuilder processorBuilder = monitoredContainer + .GetChangeFeedProcessorBuilder(processorName: $"processorName", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection documents, CancellationToken token) => Task.CompletedTask) + .WithInstanceName(Guid.NewGuid().ToString()) + .WithLeaseContainer(leaseContainer) + .WithErrorNotification((leaseToken, error) => + { + exception = error.InnerException; + + Debug.WriteLine("WithErrorNotification"); + Debug.WriteLine(error.ToString()); + + return Task.CompletedTask; + }); + + if (withStartFromBeginning) + { + processorBuilder.WithStartFromBeginning(); + } + + + ChangeFeedProcessor processor = processorBuilder.Build(); + Interlocked.Exchange(ref latestVersionProcessorAtomic, processor); + + await processor.StartAsync(); + await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); + bool isStartOk = allDocsProcessed.WaitOne(10 * BaseChangeFeedClientHelper.ChangeFeedSetupTime); + + if (exception != default) + { + Assert.Fail(exception.ToString()); + } + } + + private static async Task BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + ContainerInternal monitoredContainer, + Container leaseContainer, + ManualResetEvent allDocsProcessed) + { + Exception exception = default; + ChangeFeedProcessor allVersionsAndDeletesProcessorAtomic = null; + + ChangeFeedProcessorBuilder allVersionsAndDeletesProcessorBuilder = monitoredContainer + .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: $"processorName", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> documents, CancellationToken token) => Task.CompletedTask) + .WithInstanceName(Guid.NewGuid().ToString()) + .WithMaxItems(1) + .WithLeaseContainer(leaseContainer) + .WithErrorNotification((leaseToken, error) => + { + exception = error.InnerException; + + Debug.WriteLine("WithErrorNotification"); + Debug.WriteLine(error.ToString()); + + return Task.FromResult(exception); + }); + + ChangeFeedProcessor processor = allVersionsAndDeletesProcessorBuilder.Build(); + Interlocked.Exchange(ref allVersionsAndDeletesProcessorAtomic, processor); + + await processor.StartAsync(); + await Task.Delay(BaseChangeFeedClientHelper.ChangeFeedSetupTime); + bool isStartOk = allDocsProcessed.WaitOne(10 * BaseChangeFeedClientHelper.ChangeFeedSetupTime); + + if (exception != default) + { + Assert.Fail(exception.ToString()); + } + } + + private async Task CreateMonitoredContainer(ChangeFeedMode changeFeedMode) + { + string PartitionKey = "/pk"; + ContainerProperties properties = new ContainerProperties(id: Guid.NewGuid().ToString(), + partitionKeyPath: PartitionKey); + + if (changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes) + { + Debug.WriteLine($"{nameof(properties.ChangeFeedPolicy.FullFidelityRetention)} initialized."); + + properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5); + } + + ContainerResponse response = await this.database.CreateContainerAsync(properties, + throughput: 10000, + cancellationToken: this.cancellationToken); + + return (ContainerInternal)response; + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs index c5e74fbfd9..f2684576c5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/ChangeFeedProcessorCoreTests.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.Tests using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.ChangeFeed.Configuration; - using Microsoft.Azure.Cosmos.ChangeFeed.FeedProcessing; using Microsoft.Azure.Cosmos.ChangeFeed.LeaseManagement; using Microsoft.Azure.Cosmos.Tests; using Microsoft.Azure.Cosmos.Tracing; @@ -98,6 +97,7 @@ public async Task StartAsync() Mock leaseContainer = new Mock(); leaseContainer.Setup(l => l.GetOwnedLeasesAsync()).Returns(Task.FromResult(Enumerable.Empty())); + leaseContainer.Setup(l => l.GetAllLeasesAsync()).ReturnsAsync(new List()); Mock leaseStoreManager = new Mock(); leaseStoreManager.Setup(l => l.LeaseContainer).Returns(leaseContainer.Object); @@ -148,6 +148,7 @@ public async Task ObserverIsCreated() Mock leaseContainer = new Mock(); leaseContainer.Setup(l => l.GetOwnedLeasesAsync()).Returns(Task.FromResult(ownedLeases)); + leaseContainer.Setup(l => l.GetAllLeasesAsync()).ReturnsAsync(new List()); Mock leaseStoreManager = new Mock(); leaseStoreManager.Setup(l => l.LeaseContainer).Returns(leaseContainer.Object); @@ -211,7 +212,7 @@ public async Task StopAsync() await processor.StopAsync(); Mock.Get(leaseContainer.Object) - .Verify(store => store.GetAllLeasesAsync(), Times.Once); + .Verify(store => store.GetAllLeasesAsync(), Times.Exactly(2)); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseStoreManagerBuilderTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseStoreManagerBuilderTests.cs index f6901bb75b..6a9fb11fc2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseStoreManagerBuilderTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/DocumentServiceLeaseStoreManagerBuilderTests.cs @@ -36,7 +36,8 @@ await DocumentServiceLeaseStoreManagerBuilder.InitializeAsync( Mock.Of(), leaseContainerMock.Object, Guid.NewGuid().ToString(), - Guid.NewGuid().ToString()); + Guid.NewGuid().ToString(), + ChangeFeedMode.LatestVersion); } [TestMethod] @@ -59,7 +60,8 @@ await DocumentServiceLeaseStoreManagerBuilder.InitializeAsync( Mock.Of(), leaseContainerMock.Object, Guid.NewGuid().ToString(), - Guid.NewGuid().ToString()); + Guid.NewGuid().ToString(), + ChangeFeedMode.LatestVersion); } [TestMethod] @@ -82,7 +84,8 @@ await DocumentServiceLeaseStoreManagerBuilder.InitializeAsync( Mock.Of(), leaseContainerMock.Object, Guid.NewGuid().ToString(), - Guid.NewGuid().ToString()); + Guid.NewGuid().ToString(), + ChangeFeedMode.LatestVersion); } [TestMethod] @@ -105,7 +108,8 @@ await Assert.ThrowsExceptionAsync(() => DocumentServiceLeaseS Mock.Of(), leaseContainerMock.Object, Guid.NewGuid().ToString(), - Guid.NewGuid().ToString())); + Guid.NewGuid().ToString(), + ChangeFeedMode.LatestVersion)); } } } From 75a2e5f98af8b9c11c621e052cb5761c3d15aaf3 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Mon, 25 Mar 2024 14:19:04 -0700 Subject: [PATCH 297/337] [Internal] Pipelines: Fixes Multi-Region CI pipeline to include env variable (#4363) * Fixes Multi-Region CI pipeline to include env variable * fixed space * added validation test * string conversion * temp * temp2 * Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs Co-authored-by: Matias Quaranta * changed env location * temp * test * space * remove env * possible fix * test fix * clean up * changed enviroment variable get * test * test fix * ensure multiregion tests do not run with regular emulator tests --------- Co-authored-by: Matias Quaranta --- .../ClientTests.cs | 12 ++++++++++++ .../Utils/TestCommon.cs | 5 +++++ azure-pipelines.yml | 1 + templates/build-test.yml | 7 +++++-- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index 403cd30bc9..0600c7be85 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -924,6 +924,18 @@ public void PooledConnectionLifetimeTest() Type clientMessageHandlerType = cosmosClient.ClientContext.DocumentClient.httpClient.HttpMessageHandler.GetType(); Assert.AreEqual(socketHandlerType, clientMessageHandlerType); } + + [TestMethod] + [TestCategory("MultiRegion")] + public async Task MultiRegionAccountTest() + { + string connectionString = TestCommon.GetMultiRegionConnectionString(); + Assert.IsFalse(string.IsNullOrEmpty(connectionString), "Connection String Not Set"); + using CosmosClient cosmosClient = new CosmosClient(connectionString); + Assert.IsNotNull(cosmosClient); + AccountProperties properties = await cosmosClient.ReadAccountAsync(); + Assert.IsNotNull(properties); + } public static IReadOnlyList GetActiveConnections() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index 48a5025289..050e6ed4a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -73,6 +73,11 @@ internal static (string endpoint, string authKey) GetAccountInfo() return (endpoint, authKey); } + internal static string GetMultiRegionConnectionString() + { + return Cosmos.ConfigurationManager.GetEnvironmentVariable("COSMOSDB_MULTI_REGION", string.Empty); + } + internal static CosmosClientBuilder GetDefaultConfiguration( bool useCustomSeralizer = true, bool validatePartitionKeyRangeCalls = false, diff --git a/azure-pipelines.yml b/azure-pipelines.yml index aae5115a5e..6d5c599c89 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -50,6 +50,7 @@ jobs: BuildConfiguration: Release Arguments: $(ReleaseArguments) VmImage: $(VmImage) + MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION) - template: templates/build-internal.yml parameters: diff --git a/templates/build-test.yml b/templates/build-test.yml index 42c67d664c..a3cfedd231 100644 --- a/templates/build-test.yml +++ b/templates/build-test.yml @@ -5,12 +5,13 @@ parameters: Arguments: '' VmImage: '' # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops OS: 'Windows' - EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=LongRunning & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' - EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed & TestCategory!=LongRunning" --verbosity normal ' + EmulatorPipeline1Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=LongRunning & TestCategory!=MultiRegion & (TestCategory=ClientTelemetryEmulator|TestCategory=Query|TestCategory=ReadFeed|TestCategory=Batch|TestCategory=ChangeFeed)" --verbosity normal ' + EmulatorPipeline2Arguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional & TestCategory!=ClientTelemetryRelease & TestCategory!=ClientTelemetryEmulator & TestCategory!=Query & TestCategory!=ReadFeed & TestCategory!=Batch & TestCategory!=ChangeFeed & TestCategory!=LongRunning & TestCategory!=MultiRegion" --verbosity normal ' EmulatorPipeline3Arguments: ' --filter "TestCategory=MultiRegion" --verbosity normal ' EmulatorPipeline1CategoryListName: ' Client Telemetry, Query, ChangeFeed, ReadFeed, Batch ' # Divided in 2 categories to run them in parallel and reduce the PR feedback time EmulatorPipeline2CategoryListName: ' Others ' EmulatorPipeline3CategoryListName: ' MultiRegion ' + MultiRegionConnectionString : '' jobs: - job: @@ -236,3 +237,5 @@ jobs: nugetConfigPath: NuGet.config publishTestResults: true testRunTitle: Microsoft.Azure.Cosmos.EmulatorTests + env: + COSMOSDB_MULTI_REGION: ${{ parameters.MultiRegionConnectionString }} From 71e58ee83386442d8b168568cc422ea9c7898dec Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:32:13 -0400 Subject: [PATCH 298/337] ChangeFeedProcessor: Adds AllVersionsAndDeletes support to ChangeFeedProcessor (#4370) * preview cfp ffcf * ran updatecontracts * including this in Encryption * fixing name onChangesDelegate * sdkproject on encryptioncontainer * try this again * try, try, try again * with impl --- .../src/EncryptionContainer.cs | 11 ++- .../src/EncryptionContainer.cs | 9 ++- .../src/Resource/Container/Container.cs | 78 ++++++++++++++++++- .../Resource/Container/ContainerInlineCore.cs | 10 --- .../Resource/Container/ContainerInternal.cs | 73 +---------------- .../Contracts/DotNetPreviewSDKAPI.json | 5 ++ 6 files changed, 100 insertions(+), 86 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs index eebf5900cf..bdba7677b6 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos.Encryption.Custom using System.Linq; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos; using Newtonsoft.Json.Linq; internal sealed class EncryptionContainer : Container @@ -1023,6 +1022,16 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( } #endif +#if SDKPROJECTREF + public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate) + { + return this.container.GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + processorName, + onChangesDelegate); + } +#endif private async Task ReadManyItemsHelperAsync( IReadOnlyList<(string id, PartitionKey partitionKey)> items, ReadManyRequestOptions readManyRequestOptions = null, diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs index 0bd342f0ef..32df3587bb 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos.Encryption using System.Net; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos; using Newtonsoft.Json.Linq; internal sealed class EncryptionContainer : Container @@ -756,6 +755,14 @@ public override Task> GetPartitionKeyRangesAsync( } #endif +#if SDKPROJECTREF + public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate) + { + throw new NotImplementedException(); + } +#endif /// /// This function handles the scenario where a container is deleted(say from different Client) and recreated with same Id but with different client encryption policy. /// The idea is to have the container Rid cached and sent out as part of RequestOptions with Container Rid set in "x-ms-cosmos-intended-collection-rid" header. diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 5936f5e05d..2ee396cac6 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -10,7 +10,6 @@ namespace Microsoft.Azure.Cosmos using System.Linq; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Serializer; /// /// Operations for reading, replacing, or deleting a specific, existing container or item in a container by id. @@ -1681,6 +1680,81 @@ public abstract Task DeleteAllItemsByPartitionKeyStreamAsync( public abstract Task> GetPartitionKeyRangesAsync( FeedRange feedRange, CancellationToken cancellationToken = default); + + /// + /// Initializes a for change feed processing with all versions and deletes. + /// + /// Document type + /// A name that identifies the Processor and the particular work it will do. + /// Delegate to receive all changes and deletes + /// + /// + /// > documents, CancellationToken token) => + /// { + /// Console.WriteLine($"number of documents processed: {documents.Count}"); + /// + /// string id = default; + /// string pk = default; + /// string description = default; + /// + /// foreach (ChangeFeedItemChange changeFeedItem in documents) + /// { + /// if (changeFeedItem.Metadata.OperationType != ChangeFeedOperationType.Delete) + /// { + /// id = changeFeedItem.Current.id.ToString(); + /// pk = changeFeedItem.Current.pk.ToString(); + /// description = changeFeedItem.Current.description.ToString(); + /// } + /// else + /// { + /// id = changeFeedItem.Previous.id.ToString(); + /// pk = changeFeedItem.Previous.pk.ToString(); + /// description = changeFeedItem.Previous.description.ToString(); + /// } + /// + /// ChangeFeedOperationType operationType = changeFeedItem.Metadata.OperationType; + /// long previousLsn = changeFeedItem.Metadata.PreviousLsn; + /// DateTime conflictResolutionTimestamp = changeFeedItem.Metadata.ConflictResolutionTimestamp; + /// long lsn = changeFeedItem.Metadata.Lsn; + /// bool isTimeToLiveExpired = changeFeedItem.Metadata.IsTimeToLiveExpired; + /// } + /// + /// return Task.CompletedTask; + /// }) + /// .WithInstanceName(Guid.NewGuid().ToString()) + /// .WithLeaseContainer(leaseContainer) + /// .WithErrorNotification((leaseToken, error) => + /// { + /// Console.WriteLine(error.ToString()); + /// + /// return Task.CompletedTask; + /// }) + /// .Build(); + /// + /// await changeFeedProcessor.StartAsync(); + /// await Task.Delay(1000); + /// await this.Container.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); + /// await this.Container.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); + /// await this.Container.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); + /// + /// allProcessedDocumentsEvent.WaitOne(10 * 1000); + /// + /// await changeFeedProcessor.StopAsync(); + /// ]]> + /// + /// + /// An instance of + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( + string processorName, + ChangeFeedHandler> onChangesDelegate); #endif } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs index ede4aebc22..f3153a33cf 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInlineCore.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.ReadFeed; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Tracing; // This class acts as a wrapper for environments that use SynchronizationContext. @@ -661,14 +660,5 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( task: (trace) => base.DeleteAllItemsByPartitionKeyStreamAsync(partitionKey, trace, requestOptions, cancellationToken), openTelemetry: (response) => new OpenTelemetryResponse(response)); } - - public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( - string processorName, - ChangeFeedHandler> onChangesDelegate) - { - return base.GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( - processorName, - onChangesDelegate); - } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index 27b007ed8e..7e980bac56 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -147,82 +147,11 @@ public abstract Task DeleteAllItemsByPartitionKeyStreamAsync( public abstract Task> GetPartitionKeyRangesAsync( FeedRange feedRange, CancellationToken cancellationToken = default); -#endif - /// - /// Initializes a for change feed processing with all versions and deletes. - /// - /// Document type - /// A name that identifies the Processor and the particular work it will do. - /// Delegate to receive all changes and deletes - /// - /// - /// > documents, CancellationToken token) => - /// { - /// Console.WriteLine($"number of documents processed: {documents.Count}"); - /// - /// string id = default; - /// string pk = default; - /// string description = default; - /// - /// foreach (ChangeFeedItemChange changeFeedItem in documents) - /// { - /// if (changeFeedItem.Metadata.OperationType != ChangeFeedOperationType.Delete) - /// { - /// id = changeFeedItem.Current.id.ToString(); - /// pk = changeFeedItem.Current.pk.ToString(); - /// description = changeFeedItem.Current.description.ToString(); - /// } - /// else - /// { - /// id = changeFeedItem.Previous.id.ToString(); - /// pk = changeFeedItem.Previous.pk.ToString(); - /// description = changeFeedItem.Previous.description.ToString(); - /// } - /// - /// ChangeFeedOperationType operationType = changeFeedItem.Metadata.OperationType; - /// long previousLsn = changeFeedItem.Metadata.PreviousLsn; - /// DateTime conflictResolutionTimestamp = changeFeedItem.Metadata.ConflictResolutionTimestamp; - /// long lsn = changeFeedItem.Metadata.Lsn; - /// bool isTimeToLiveExpired = changeFeedItem.Metadata.IsTimeToLiveExpired; - /// } - /// - /// return Task.CompletedTask; - /// }) - /// .WithInstanceName(Guid.NewGuid().ToString()) - /// .WithLeaseContainer(leaseContainer) - /// .WithErrorNotification((leaseToken, error) => - /// { - /// Console.WriteLine(error.ToString()); - /// - /// return Task.CompletedTask; - /// }) - /// .Build(); - /// - /// await changeFeedProcessor.StartAsync(); - /// await Task.Delay(1000); - /// await this.Container.CreateItemAsync(new { id = "1", pk = "1", description = "original test" }, partitionKey: new PartitionKey("1")); - /// await this.Container.UpsertItemAsync(new { id = "1", pk = "1", description = "test after replace" }, partitionKey: new PartitionKey("1")); - /// await this.Container.DeleteItemAsync(id: "1", partitionKey: new PartitionKey("1")); - /// - /// allProcessedDocumentsEvent.WaitOne(10 * 1000); - /// - /// await changeFeedProcessor.StopAsync(); - /// ]]> - /// - /// - /// An instance of public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, ChangeFeedHandler> onChangesDelegate); +#endif public abstract class TryExecuteQueryResult { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index 66cdf8f4d5..d29800471a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -299,6 +299,11 @@ "Microsoft.Azure.Cosmos.Container;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "Microsoft.Azure.Cosmos.ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes[T](System.String, ChangeFeedHandler`1)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes[T](System.String, ChangeFeedHandler`1);IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:True;IsConstructor:False;IsFinal:False;" + }, "System.Threading.Tasks.Task`1[Microsoft.Azure.Cosmos.ResponseMessage] DeleteAllItemsByPartitionKeyStreamAsync(Microsoft.Azure.Cosmos.PartitionKey, Microsoft.Azure.Cosmos.RequestOptions, System.Threading.CancellationToken)": { "Type": "Method", "Attributes": [], From dfee5ad2b0363b9c4209a028e41fc486ba7a309e Mon Sep 17 00:00:00 2001 From: jiajunpeng-msft <32749342+jiajunpeng-msft@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:07:35 -0700 Subject: [PATCH 299/337] integrated cache: make BypassIntegratedCache API GA (#4377) Co-authored-by: Jiajun Peng --- .../DedicatedGatewayRequestOptions.cs | 7 +----- .../Contracts/DotNetPreviewSDKAPI.json | 25 ------------------- .../Contracts/DotNetSDKAPI.json | 19 ++++++++++++++ 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs index 31f82644a9..ffb0144148 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/DedicatedGatewayRequestOptions.cs @@ -50,12 +50,7 @@ public class DedicatedGatewayRequestOptions /// ]]> /// /// -#if PREVIEW - public -#else - internal -#endif - bool? BypassIntegratedCache { get; set; } + public bool? BypassIntegratedCache { get; set; } internal static void PopulateMaxIntegratedCacheStalenessOption(DedicatedGatewayRequestOptions dedicatedGatewayRequestOptions, RequestMessage request) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index d29800471a..b19e9c455e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -357,31 +357,6 @@ }, "NestedTypes": {} }, - "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { - "Subclasses": {}, - "Members": { - "System.Nullable`1[System.Boolean] BypassIntegratedCache": { - "Type": "Property", - "Attributes": [], - "MethodInfo": "System.Nullable`1[System.Boolean] BypassIntegratedCache;CanRead:True;CanWrite:True;System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "System.Nullable`1[System.Boolean] get_BypassIntegratedCache()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - }, - "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { - "Type": "Method", - "Attributes": [ - "CompilerGeneratedAttribute" - ], - "MethodInfo": "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" - } - }, - "NestedTypes": {} - }, "Microsoft.Azure.Cosmos.Fluent.ChangeFeedPolicyDefinition;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index a0cce31949..aef32b7f9c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -4129,6 +4129,18 @@ "Microsoft.Azure.Cosmos.DedicatedGatewayRequestOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "System.Nullable`1[System.Boolean] BypassIntegratedCache": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Boolean] BypassIntegratedCache;CanRead:True;CanWrite:True;System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Boolean] get_BypassIntegratedCache()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Boolean] get_BypassIntegratedCache();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Nullable`1[System.TimeSpan] get_MaxIntegratedCacheStaleness()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -4146,6 +4158,13 @@ "Attributes": [], "MethodInfo": "[Void .ctor(), Void .ctor()]" }, + "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_BypassIntegratedCache(System.Nullable`1[System.Boolean]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_MaxIntegratedCacheStaleness(System.Nullable`1[System.TimeSpan])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ From 4855a6afd75eb4b096594b7796a8b851b275bc9b Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Fri, 29 Mar 2024 15:48:48 -0400 Subject: [PATCH 300/337] ChangeFeedProcessor: Refactors AVAD metadata Contract (#4380) * refactoring for name change * more refactoring and run UpdateContracts --- .../src/EncryptionContainer.cs | 2 +- .../src/EncryptionContainer.cs | 2 +- .../ChangeFeedObserverFactoryCore.cs | 10 ++-- .../src/Resource/Container/Container.cs | 6 +-- .../Resource/Container/ContainerCore.Items.cs | 2 +- .../Resource/Container/ContainerInternal.cs | 2 +- ...FeedItemChange{T}.cs => ChangeFeedItem.cs} | 12 ++--- .../FullFidelity/ChangeFeedMetadata.cs | 2 +- .../src/Serializer/CosmosSerializerCore.cs | 2 +- ...orBuilderWithAllVersionsAndDeletesTests.cs | 12 ++--- .../FeedToken/ChangeFeedIteratorCoreTests.cs | 50 +++++++++---------- .../Contracts/DotNetPreviewSDKAPI.json | 2 +- 12 files changed, 52 insertions(+), 52 deletions(-) rename Microsoft.Azure.Cosmos/src/Resource/FullFidelity/{ChangeFeedItemChange{T}.cs => ChangeFeedItem.cs} (78%) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs index bdba7677b6..10496f704a 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/EncryptionContainer.cs @@ -1025,7 +1025,7 @@ public override Task DeleteAllItemsByPartitionKeyStreamAsync( #if SDKPROJECTREF public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, - ChangeFeedHandler> onChangesDelegate) + ChangeFeedHandler> onChangesDelegate) { return this.container.GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( processorName, diff --git a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs index 32df3587bb..64c7dc36a1 100644 --- a/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs +++ b/Microsoft.Azure.Cosmos.Encryption/src/EncryptionContainer.cs @@ -758,7 +758,7 @@ public override Task> GetPartitionKeyRangesAsync( #if SDKPROJECTREF public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, - ChangeFeedHandler> onChangesDelegate) + ChangeFeedHandler> onChangesDelegate) { throw new NotImplementedException(); } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs index c71d6f06a2..2154a27856 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/Observers/ChangeFeedObserverFactoryCore.cs @@ -52,7 +52,7 @@ internal sealed class ChangeFeedObserverFactoryCore : ChangeFeedObserverFacto private readonly ChangesHandler legacyOnChanges; private readonly ChangeFeedHandler onChanges; private readonly ChangeFeedHandlerWithManualCheckpoint onChangesWithManualCheckpoint; - private readonly ChangeFeedHandler> onAllVersionsAndDeletesChanges; + private readonly ChangeFeedHandler> onAllVersionsAndDeletesChanges; private readonly CosmosSerializerCore serializerCore; public ChangeFeedObserverFactoryCore( @@ -72,7 +72,7 @@ public ChangeFeedObserverFactoryCore( } public ChangeFeedObserverFactoryCore( - ChangeFeedHandler> onChanges, + ChangeFeedHandler> onChanges, CosmosSerializerCore serializerCore) : this(serializerCore) { @@ -130,7 +130,7 @@ private Task AllVersionsAndDeletesStreamHandlerAsync( Stream stream, CancellationToken cancellationToken) { - IReadOnlyCollection> changes = this.AllVersionsAsIReadOnlyCollection(stream, context); + IReadOnlyCollection> changes = this.AllVersionsAsIReadOnlyCollection(stream, context); if (changes.Count == 0) { return Task.CompletedTask; @@ -156,13 +156,13 @@ private IReadOnlyCollection AsIReadOnlyCollection( } } - private IReadOnlyCollection> AllVersionsAsIReadOnlyCollection( + private IReadOnlyCollection> AllVersionsAsIReadOnlyCollection( Stream stream, ChangeFeedObserverContextCore context) { try { - return CosmosFeedResponseSerializer.FromFeedResponseStream>( + return CosmosFeedResponseSerializer.FromFeedResponseStream>( this.serializerCore, stream); } diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 2ee396cac6..4aeef068ff 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -1697,7 +1697,7 @@ public abstract Task> GetPartitionKeyRangesAsync( /// ManualResetEvent allProcessedDocumentsEvent = new ManualResetEvent(false); /// /// ChangeFeedProcessor changeFeedProcessor = this.Container - /// .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> documents, CancellationToken token) => + /// .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> documents, CancellationToken token) => /// { /// Console.WriteLine($"number of documents processed: {documents.Count}"); /// @@ -1705,7 +1705,7 @@ public abstract Task> GetPartitionKeyRangesAsync( /// string pk = default; /// string description = default; /// - /// foreach (ChangeFeedItemChange changeFeedItem in documents) + /// foreach (ChangeFeedItem changeFeedItem in documents) /// { /// if (changeFeedItem.Metadata.OperationType != ChangeFeedOperationType.Delete) /// { @@ -1754,7 +1754,7 @@ public abstract Task> GetPartitionKeyRangesAsync( /// An instance of public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, - ChangeFeedHandler> onChangesDelegate); + ChangeFeedHandler> onChangesDelegate); #endif } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs index 5e96126c71..0a7c4b2082 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerCore.Items.cs @@ -1222,7 +1222,7 @@ public Task PatchItemStreamAsync( public override ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, - ChangeFeedHandler> onChangesDelegate) + ChangeFeedHandler> onChangesDelegate) { if (processorName == null) { diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index 7e980bac56..cedef3f3de 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -150,7 +150,7 @@ public abstract Task> GetPartitionKeyRangesAsync( public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes( string processorName, - ChangeFeedHandler> onChangesDelegate); + ChangeFeedHandler> onChangesDelegate); #endif public abstract class TryExecuteQueryResult diff --git a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItem.cs similarity index 78% rename from Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs rename to Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItem.cs index deb9c7db87..fc0c04ffd0 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItemChange{T}.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedItem.cs @@ -23,19 +23,19 @@ namespace Microsoft.Azure.Cosmos /// PartitionKey partitionKey = new PartitionKey(@"learning"); /// ChangeFeedStartFrom changeFeedStartFrom = ChangeFeedStartFrom.Now(FeedRange.FromPartitionKey(partitionKey)); /// - /// using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( + /// using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( /// changeFeedStartFrom: changeFeedStartFrom, /// changeFeedMode: changeFeedMode)) /// { /// while (feedIterator.HasMoreResults) /// { - /// FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); + /// FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); /// /// if (feedResponse.StatusCode != HttpStatusCode.NotModified) /// { - /// IEnumerable> feedResource = feedResponse.Resource; + /// IEnumerable> feedResource = feedResponse.Resource; /// - /// foreach(ChangeFeedItemChanges itemChanges in feedResource) + /// foreach(ChangeFeedItem itemChanges in feedResource) /// { /// ToDoActivity currentToDoActivity = itemChanges.Current; /// ToDoActivity previousToDoActivity = itemChanges.Previous; @@ -47,13 +47,13 @@ namespace Microsoft.Azure.Cosmos /// ]]> /// /// - /// is an optional helper class that uses Newtonsoft serialization libraries. Users are welcome to create their own custom helper class. + /// is an optional helper class that uses Newtonsoft serialization libraries. Users are welcome to create their own custom helper class. #if PREVIEW public #else internal #endif - class ChangeFeedItemChange + class ChangeFeedItem { /// /// The full fidelity change feed current item. diff --git a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs index 81b10461f9..c5bd4642fa 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FullFidelity/ChangeFeedMetadata.cs @@ -20,7 +20,7 @@ namespace Microsoft.Azure.Cosmos class ChangeFeedMetadata { /// - /// New instance of meta data for created. + /// New instance of meta data for created. /// /// /// diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializerCore.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializerCore.cs index 2c4996048c..703b2f2374 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializerCore.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosSerializerCore.cs @@ -162,7 +162,7 @@ private CosmosSerializer GetSerializer() string directAssemblyName = typeof(Documents.PartitionKeyRange).Assembly.GetName().Name; string inputAssemblyName = inputType.Assembly.GetName().Name; bool inputIsClientOrDirect = string.Equals(inputAssemblyName, clientAssemblyName) || string.Equals(inputAssemblyName, directAssemblyName); - bool typeIsWhiteListed = inputType == typeof(Document) || (inputType.IsGenericType && inputType.GetGenericTypeDefinition() == typeof(ChangeFeedItemChange<>)); + bool typeIsWhiteListed = inputType == typeof(Document) || (inputType.IsGenericType && inputType.GetGenericTypeDefinition() == typeof(ChangeFeedItem<>)); if (!typeIsWhiteListed && inputIsClientOrDirect) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs index 33f5d9d0c4..5a31025e71 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs @@ -39,13 +39,13 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Exception exception = default; ChangeFeedProcessor processor = monitoredContainer - .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> docs, CancellationToken token) => + .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: "processor", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> docs, CancellationToken token) => { string id = default; string pk = default; string description = default; - foreach (ChangeFeedItemChange change in docs) + foreach (ChangeFeedItem change in docs) { if (change.Metadata.OperationType != ChangeFeedOperationType.Delete) { @@ -75,7 +75,7 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.IsTrue(context.Diagnostics.ToString().Contains("Change Feed Processor Read Next Async")); Assert.AreEqual(expected: 3, actual: docs.Count); - ChangeFeedItemChange createChange = docs.ElementAt(0); + ChangeFeedItem createChange = docs.ElementAt(0); Assert.IsNotNull(createChange.Current); Assert.AreEqual(expected: "1", actual: createChange.Current.id.ToString()); Assert.AreEqual(expected: "1", actual: createChange.Current.pk.ToString()); @@ -84,7 +84,7 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.AreEqual(expected: createChange.Metadata.PreviousLsn, actual: 0); Assert.IsNull(createChange.Previous); - ChangeFeedItemChange replaceChange = docs.ElementAt(1); + ChangeFeedItem replaceChange = docs.ElementAt(1); Assert.IsNotNull(replaceChange.Current); Assert.AreEqual(expected: "1", actual: replaceChange.Current.id.ToString()); Assert.AreEqual(expected: "1", actual: replaceChange.Current.pk.ToString()); @@ -93,7 +93,7 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.AreEqual(expected: createChange.Metadata.Lsn, actual: replaceChange.Metadata.PreviousLsn); Assert.IsNull(replaceChange.Previous); - ChangeFeedItemChange deleteChange = docs.ElementAt(2); + ChangeFeedItem deleteChange = docs.ElementAt(2); Assert.IsNull(deleteChange.Current.id); Assert.AreEqual(expected: deleteChange.Metadata.OperationType, actual: ChangeFeedOperationType.Delete); Assert.AreEqual(expected: replaceChange.Metadata.Lsn, actual: deleteChange.Metadata.PreviousLsn); @@ -341,7 +341,7 @@ private static async Task BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync ChangeFeedProcessor allVersionsAndDeletesProcessorAtomic = null; ChangeFeedProcessorBuilder allVersionsAndDeletesProcessorBuilder = monitoredContainer - .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: $"processorName", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> documents, CancellationToken token) => Task.CompletedTask) + .GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(processorName: $"processorName", onChangesDelegate: (ChangeFeedProcessorContext context, IReadOnlyCollection> documents, CancellationToken token) => Task.CompletedTask) .WithInstanceName(Guid.NewGuid().ToString()) .WithMaxItems(1) .WithLeaseContainer(leaseContainer) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs index b8d132e141..a43d86faf5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/FeedToken/ChangeFeedIteratorCoreTests.cs @@ -822,7 +822,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( enableQueryOnPreviousImage: true); ContainerCore container = (ContainerCore)response; // FF does not work with StartFromBeginning currently, so we capture an initial continuation. - FeedIterator> fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( + FeedIterator> fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.Now(), ChangeFeedMode.AllVersionsAndDeletes, querySpec, @@ -831,7 +831,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( string initialContinuation = null; while (fullFidelityIterator.HasMoreResults) { - FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); + FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); initialContinuation = feedResponse.ContinuationToken; if (feedResponse.StatusCode == HttpStatusCode.NotModified) @@ -855,7 +855,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( } // Resume Change Feed and verify we pickup the events where documents matches the query - fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( + fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.ContinuationToken(initialContinuation), ChangeFeedMode.AllVersionsAndDeletes, querySpec, @@ -864,9 +864,9 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( while (fullFidelityIterator.HasMoreResults) { - FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); + FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); - foreach (ChangeFeedItemChange item in feedResponse) + foreach (ChangeFeedItem item in feedResponse) { Assert.AreEqual("id3", item.Current.Id); } @@ -884,7 +884,7 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( await container.DeleteItemAsync("id2", new Cosmos.PartitionKey("pkey1")); await container.DeleteItemAsync("id3", new Cosmos.PartitionKey("pkey1")); - fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( + fullFidelityIterator = container.GetChangeFeedIteratorWithQuery>( ChangeFeedStartFrom.ContinuationToken(initialContinuation), ChangeFeedMode.AllVersionsAndDeletes, querySpec, @@ -892,9 +892,9 @@ private async Task ValidateChangeFeedIteratorCore_WithQuery( detectedEvents = 0; while (fullFidelityIterator.HasMoreResults) { - FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); + FeedResponse> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken); - foreach (ChangeFeedItemChange item in feedResponse) + foreach (ChangeFeedItem item in feedResponse) { Assert.AreEqual("id3", item.Previous.Id); Assert.AreEqual(ChangeFeedOperationType.Delete, item.Metadata.OperationType); @@ -925,14 +925,14 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_VerifyingWir ChangeFeedMode changeFeedMode = ChangeFeedMode.AllVersionsAndDeletes; ChangeFeedStartFrom changeFeedStartFrom = ChangeFeedStartFrom.Now(FeedRange.FromPartitionKey(partitionKey)); - using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( + using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( changeFeedStartFrom: changeFeedStartFrom, changeFeedMode: changeFeedMode)) { string continuation = null; while (feedIterator.HasMoreResults) { - FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); + FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); if (feedResponse.StatusCode == HttpStatusCode.NotModified) { @@ -950,20 +950,20 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_VerifyingWir #if DEBUG Console.WriteLine(JsonConvert.SerializeObject(feedResponse.Resource)); #endif - IEnumerable> itemChanges = feedResponse.Resource; + IEnumerable> itemChanges = feedResponse.Resource; ChangeFeedIteratorCoreTests.AssertGatewayMode(feedResponse); Assert.AreEqual(expected: 2, actual: itemChanges.Count()); - foreach(ChangeFeedItemChange item in itemChanges) + foreach(ChangeFeedItem item in itemChanges) { Item current = item.Current; Item previous = item.Previous; ChangeFeedMetadata metadata = item.Metadata; } - ChangeFeedItemChange createOperation = itemChanges.ElementAtOrDefault(0); + ChangeFeedItem createOperation = itemChanges.ElementAtOrDefault(0); Assert.AreEqual(expected: id, actual: createOperation.Current.Id); Assert.AreEqual(expected: "One Microsoft Way", actual: createOperation.Current.Line1); @@ -977,7 +977,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_VerifyingWir Assert.AreEqual(expected: default, actual: createOperation.Metadata.PreviousLsn); Assert.IsFalse(createOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange replaceOperation = itemChanges.ElementAtOrDefault(1); + ChangeFeedItem replaceOperation = itemChanges.ElementAtOrDefault(1); Assert.AreEqual(expected: id, actual: replaceOperation.Current.Id); Assert.AreEqual(expected: "205 16th St NW", actual: replaceOperation.Current.Line1); @@ -1010,14 +1010,14 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() string id = Guid.NewGuid().ToString(); string otherId = Guid.NewGuid().ToString(); - using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( + using (FeedIterator> feedIterator = container.GetChangeFeedIterator>( changeFeedStartFrom: ChangeFeedStartFrom.Now(), changeFeedMode: ChangeFeedMode.AllVersionsAndDeletes)) { string continuation = null; while (feedIterator.HasMoreResults) { - FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); + FeedResponse> feedResponse = await feedIterator.ReadNextAsync(); if (feedResponse.StatusCode == HttpStatusCode.NotModified) { @@ -1037,13 +1037,13 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() #if DEBUG Console.WriteLine(JsonConvert.SerializeObject(feedResponse.Resource)); #endif - List> resources = feedResponse.Resource.ToList(); + List> resources = feedResponse.Resource.ToList(); ChangeFeedIteratorCoreTests.AssertGatewayMode(feedResponse); Assert.AreEqual(expected: 4, actual: resources.Count); - ChangeFeedItemChange firstCreateOperation = resources[0]; + ChangeFeedItem firstCreateOperation = resources[0]; Assert.AreEqual(expected: otherId, actual: firstCreateOperation.Current.Id); Assert.AreEqual(expected: "87 38floor, Witthayu Rd, Lumphini, Pathum Wan District", actual: firstCreateOperation.Current.Line1); @@ -1056,7 +1056,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() Assert.AreEqual(expected: default, actual: firstCreateOperation.Metadata.PreviousLsn); Assert.IsFalse(firstCreateOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange createOperation = resources[1]; + ChangeFeedItem createOperation = resources[1]; Assert.AreEqual(expected: id, actual: createOperation.Current.Id); Assert.AreEqual(expected: "One Microsoft Way", actual: createOperation.Current.Line1); @@ -1069,7 +1069,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() Assert.AreEqual(expected: default, actual: createOperation.Metadata.PreviousLsn); Assert.IsFalse(createOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange replaceOperation = resources[2]; + ChangeFeedItem replaceOperation = resources[2]; Assert.AreEqual(expected: id, actual: replaceOperation.Current.Id); Assert.AreEqual(expected: "205 16th St NW", actual: replaceOperation.Current.Line1); @@ -1082,7 +1082,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_VerifyingWireFormatTests() Assert.AreNotEqual(notExpected: default, actual: replaceOperation.Metadata.PreviousLsn); Assert.IsFalse(replaceOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange deleteOperation = resources[3]; + ChangeFeedItem deleteOperation = resources[3]; Assert.IsNull(deleteOperation.Current.Id); Assert.IsNull(deleteOperation.Current.Line1); @@ -1144,14 +1144,14 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_Dynamic_Veri #if DEBUG Console.WriteLine(JsonConvert.SerializeObject(feedResponse.Resource)); #endif - List> itemChanges = JsonConvert.DeserializeObject>>( + List> itemChanges = JsonConvert.DeserializeObject>>( JsonConvert.SerializeObject(feedResponse.Resource)); ChangeFeedIteratorCoreTests.AssertGatewayMode(feedResponse); Assert.AreEqual(expected: 3, actual: itemChanges.Count); - ChangeFeedItemChange createOperation = itemChanges[0]; + ChangeFeedItem createOperation = itemChanges[0]; Assert.AreEqual(expected: id, actual: createOperation.Current.Id); Assert.AreEqual(expected: "One Microsoft Way", actual: createOperation.Current.Line1); @@ -1165,7 +1165,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_Dynamic_Veri Assert.AreEqual(expected: default, actual: createOperation.Metadata.PreviousLsn); Assert.IsFalse(createOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange replaceOperation = itemChanges[1]; + ChangeFeedItem replaceOperation = itemChanges[1]; Assert.AreEqual(expected: id, actual: replaceOperation.Current.Id); Assert.AreEqual(expected: "205 16th St NW", actual: replaceOperation.Current.Line1); @@ -1179,7 +1179,7 @@ public async Task ChangeFeedIteratorCore_FeedRange_FromPartitionKey_Dynamic_Veri Assert.AreNotEqual(notExpected: default, actual: replaceOperation.Metadata.PreviousLsn); Assert.IsFalse(replaceOperation.Metadata.IsTimeToLiveExpired); - ChangeFeedItemChange deleteOperation = itemChanges[2]; + ChangeFeedItem deleteOperation = itemChanges[2]; Assert.IsNotNull(deleteOperation.Metadata); Assert.AreEqual(expected: ChangeFeedOperationType.Delete, actual: deleteOperation.Metadata.OperationType); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json index b19e9c455e..f11e74d42a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @@ -1,6 +1,6 @@ { "Subclasses": { - "Microsoft.Azure.Cosmos.ChangeFeedItemChange`1;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:True;IsSerializable:False": { + "Microsoft.Azure.Cosmos.ChangeFeedItem`1;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:True;IsSerializable:False": { "Subclasses": {}, "Members": { "Microsoft.Azure.Cosmos.ChangeFeedMetadata get_Metadata()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { From 578832669c16e64578215a7524cd43cebc0aed19 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Mon, 1 Apr 2024 10:21:53 -0700 Subject: [PATCH 301/337] Query: Adds support for non streaming ORDER BY (#4362) * Initial prep for adding a non streaming order by query pipline stage * Change TracingAsyncEnumerator to be an adapter class between ITracingAsyncEnumerator and IAsyncEnumerator * Move TracingAsyncEnumerator to product code * Change ITracingAsyncEnumerator.MoveNext to take a CancellationToken, thereby removing the awkward method SetCancellationToken from IQueryPipelineStage * draft implementation of non streaming order by pipeline stage * Fix bug that drops first record on an initialized page * Add a test class for non streaming order by unit tests * remove unnecessary usings * Add an emulator test for non streaming order by. Also lay groundwork for an alternative implementation for non streaming order by * Remove the ResponseLengthInBytes property from QueryPage. This was being calculated incorrectly, and seems to be unused to boot. * Add an ItemCount property to the Page class * Add a multi level heap implementation for non streaming order by * Add infrastructure for writing parity tests * Fix a bug that caused the page enumerator to be dropped when we reach flat heap sizze limit * When cloning OrderByQueryPartitionRangePageAsyncEnumerator as a fully buffered enumerator, make sure that we set the page size to maximum for the backend requests * Simplify the non streaming pipeline stage, and add performance test * Revert the changes for Headers.ItemCount Keep it as a string * Avoid an allocation each time the OrderByItems property of OrderByQueryResult is touched * Fix up the OrderByPipelineSatgeBenchmark to use fully materialized CosmosElements in the oages returned from MockContainer * Add a few more unit tests for non streaming order by * Add emulator tests for non streaming order by * Add a few more integration test cases * Fix up broken unit test * Add more test coverage for the non streaming order by * If there is no continuationtoken, assume that the response is streaming * Add stronger validation to the non streaming order by unit tests * Fix up broken unit tests to account for ItemCount * fix up plumbing for index utilization, and incorporate code review feedback * Minor clean up * revert bug introduced in pursuit of more elegant code :) * fix up broken unit test * Fix up broken perf test * Fix up broken IndexMetricsParserBaselineTest * Minor bug fixes for OrderByCrossPartitionEnumerator --- ...ChangeFeedCrossFeedRangeAsyncEnumerable.cs | 14 +- ...ChangeFeedCrossFeedRangeAsyncEnumerator.cs | 13 +- .../src/ChangeFeed/ChangeFeedIteratorCore.cs | 6 +- .../Pagination/ChangeFeedNotModifiedPage.cs | 8 +- ...geFeedPartitionRangePageAsyncEnumerator.cs | 5 +- .../Pagination/ChangeFeedSuccessPage.cs | 12 +- ...CrossPartitionChangeFeedAsyncEnumerator.cs | 47 +- ...fferedPartitionRangePageAsyncEnumerator.cs | 31 +- ...edPartitionRangePageAsyncEnumeratorBase.cs | 13 +- .../src/Pagination/CrossFeedRangePage.cs | 6 +- .../CrossPartitionRangePageAsyncEnumerator.cs | 29 +- ...lyBufferedPartitionRangeAsyncEnumerator.cs | 44 +- .../src/Pagination/ITracingAsyncEnumerator.cs | 5 +- .../NetworkAttachedDocumentContainer.cs | 12 +- Microsoft.Azure.Cosmos/src/Pagination/Page.cs | 10 +- .../src/Pagination/PaginationOptions.cs | 7 +- .../PartitionRangePageAsyncEnumerator.cs | 14 +- .../Pagination}/TracingAsyncEnumerator.cs | 15 +- .../AggregateQueryPipelineStage.Client.cs | 37 +- .../AggregateQueryPipelineStage.Compute.cs | 29 +- .../Aggregate/AggregateQueryPipelineStage.cs | 9 +- .../Pipeline/CatchAllQueryPipelineStage.cs | 8 +- .../CosmosQueryExecutionContextFactory.cs | 79 +- .../OrderByCrossPartitionEnumerator.cs | 206 + ...OrderByCrossPartitionQueryPipelineStage.cs | 3555 ++++++++++------- .../OrderBy/OrderByEnumeratorComparer.cs | 75 +- .../OrderBy/OrderByQueryPage.cs | 6 +- ...yQueryPartitionRangePageAsyncEnumerator.cs | 112 +- .../OrderBy/OrderByQueryResult.cs | 75 +- .../OrderBy/OrderByQueryResultComparer.cs | 85 + ...arallelCrossPartitionQueryPipelineStage.cs | 37 +- .../QueryPartitionRangePageAsyncEnumerator.cs | 5 +- .../DCount/DCountQueryPipelineStage.Client.cs | 25 +- .../DCountQueryPipelineStage.Compute.cs | 29 +- .../DCount/DCountQueryPipelineStage.cs | 9 +- .../DistinctQueryPipelineStage.Client.cs | 27 +- .../DistinctQueryPipelineStage.Compute.cs | 19 +- .../Distinct/DistinctQueryPipelineStage.cs | 10 +- .../Core/Pipeline/EmptyQueryPipelineStage.cs | 7 +- .../Pipeline/FaultedQueryPipelineStage.cs | 7 +- .../GroupByQueryPipelineStage.Client.cs | 22 +- .../GroupByQueryPipelineStage.Compute.cs | 22 +- .../GroupBy/GroupByQueryPipelineStage.cs | 6 +- .../Core/Pipeline/IQueryPipelineStage.cs | 5 - .../Core/Pipeline/IndexUtilizationHelper.cs | 48 + .../Core/Pipeline/LazyQueryPipelineStage.cs | 16 +- .../Pipeline/MonadicCreatePipelineStage.cs | 2 +- .../NameCacheStaleRetryQueryPipelineStage.cs | 11 +- ...misticDirectExecutionQueryPipelineStage.cs | 33 +- .../Core/Pipeline/Pagination/QueryPage.cs | 109 +- .../Pagination/QueryPaginationOptions.cs | 2 +- .../Query/Core/Pipeline/PipelineFactory.cs | 38 +- .../Core/Pipeline/QueryPipelineStageBase.cs | 14 +- .../Skip/SkipQueryPipelineStage.Client.cs | 17 +- .../Skip/SkipQueryPipelineStage.Compute.cs | 18 +- .../Pipeline/Skip/SkipQueryPipelineStage.cs | 6 +- .../SkipEmptyPageQueryPipelineStage.cs | 46 +- .../Take/TakeQueryPipelineStage.Client.cs | 21 +- .../Take/TakeQueryPipelineStage.Compute.cs | 21 +- .../Pipeline/Take/TakeQueryPipelineStage.cs | 9 +- .../Query/v3Query/CosmosQueryClientCore.cs | 34 +- .../src/Query/v3Query/QueryIterator.cs | 5 +- .../src/Query/v3Query/QueryResponse.cs | 18 - .../CrossPartitionReadFeedAsyncEnumerator.cs | 29 +- .../src/ReadFeed/Pagination/ReadFeedPage.cs | 12 +- .../ReadFeedPartitionRangeEnumerator.cs | 5 +- .../ReadFeedCrossFeedRangeAsyncEnumerable.cs | 8 +- .../ReadFeedCrossFeedRangeAsyncEnumerator.cs | 17 +- .../src/ReadFeed/ReadFeedIteratorCore.cs | 6 +- .../IndexMetricsParserBaselineTest.cs | 68 +- .../Query/NonStreamingOrderByQueryTests.cs | 178 + .../Query/QueryBaselineTest.cs | 7 - .../Mocks/MockRequestHelper.cs | 6 +- .../Program.cs | 5 - .../Query/OrderByPipelineStageBenchmark.cs | 325 ++ ...raceWriterBaselineTests.ScenariosAsync.xml | 3252 ++++++++------- ...PartitionChangeFeedAsyncEnumeratorTests.cs | 51 +- .../NetworkAttachedDocumentContainerTests.cs | 6 +- .../CosmosConflictTests.cs | 3 +- .../CosmosJsonSerializerUnitTests.cs | 1 - .../BufferedPartitionRangeEnumeratorTests.cs | 44 +- ...sPartitionPartitionRangeEnumeratorTests.cs | 919 +++-- .../Pagination/FlakyDocumentContainer.cs | 10 +- .../Pagination/InMemoryContainer.cs | 3328 +++++++-------- ...ePartitionPartitionRangeEnumeratorTests.cs | 18 +- .../OrderByQueryResultTests.cs | 3 +- ...misticDirectExecutionQueryBaselineTests.cs | 54 +- ...yPartitionRangePageAsyncEnumeratorTests.cs | 9 +- .../AggregateQueryPipelineStageTests.cs | 3 +- .../AggressivePrefetchPipelineTests.cs | 4 +- .../CrossPartitionRangePageAsyncEnumerable.cs | 4 +- .../Pipeline/DCountQueryPipelineStageTests.cs | 8 +- .../DistinctQueryPipelineStageTests.cs | 3 +- .../Query/Pipeline/EnumerableStage.cs | 2 +- .../Query/Pipeline/FactoryTests.cs | 1 - .../Query/Pipeline/FullPipelineTests.cs | 11 +- .../GroupByQueryPipelineStageTests.cs | 3 +- .../Query/Pipeline/MockQueryPipelineStage.cs | 9 +- .../Pipeline/NonStreamingOrderByQueryTests.cs | 1004 +++++ ...ByCrossPartitionQueryPipelineStageTests.cs | 59 +- ...elCrossPartitionQueryPipelineStageTests.cs | 9 +- .../PartitionRangePageAsyncEnumerable.cs | 2 +- .../SkipEmptyPageQueryPipelineStageTests.cs | 25 +- .../Pipeline/SkipQueryPipelineStageTests.cs | 3 +- .../Pipeline/TakeQueryPipelineStageTests.cs | 3 +- .../QueryPartitionRangePageEnumeratorTests.cs | 12 +- .../Scenarios/GremlinScenarioTests.cs | 2 - .../TestHandler.cs | 7 +- .../Tracing/TraceWriterBaselineTests.cs | 13 +- 109 files changed, 8445 insertions(+), 6371 deletions(-) rename Microsoft.Azure.Cosmos/{tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline => src/Pagination}/TracingAsyncEnumerator.cs (75%) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionEnumerator.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResultComparer.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IndexUtilizationHelper.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/NonStreamingOrderByQueryTests.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerable.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerable.cs index 369202892c..9823538fba 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerable.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerable.cs @@ -10,8 +10,9 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Serializer; - + using Microsoft.Azure.Cosmos.Serializer; + using Microsoft.Azure.Cosmos.Tracing; + internal sealed class ChangeFeedCrossFeedRangeAsyncEnumerable : IAsyncEnumerable> { private readonly IDocumentContainer documentContainer; @@ -37,12 +38,13 @@ public IAsyncEnumerator> GetAsyncEnumerator(Cancellatio CrossPartitionChangeFeedAsyncEnumerator innerEnumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( this.documentContainer, innerState, - this.changeFeedPaginationOptions, - cancellationToken); + this.changeFeedPaginationOptions); - return new ChangeFeedCrossFeedRangeAsyncEnumerator( + ChangeFeedCrossFeedRangeAsyncEnumerator changeFeedEnumerator = new ChangeFeedCrossFeedRangeAsyncEnumerator( innerEnumerator, - this.jsonSerializationFormatOptions); + this.jsonSerializationFormatOptions); + + return new TracingAsyncEnumerator>(changeFeedEnumerator, NoOpTrace.Singleton, cancellationToken); } } } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerator.cs index 7186cbb057..b964b4e7e4 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedCrossFeedRangeAsyncEnumerator.cs @@ -5,14 +5,15 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed { using System; - using System.Collections.Generic; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Serializer; - - internal sealed class ChangeFeedCrossFeedRangeAsyncEnumerator : IAsyncEnumerator> + using Microsoft.Azure.Cosmos.Serializer; + using Microsoft.Azure.Cosmos.Tracing; + + internal sealed class ChangeFeedCrossFeedRangeAsyncEnumerator : ITracingAsyncEnumerator> { private readonly CrossPartitionChangeFeedAsyncEnumerator enumerator; private readonly JsonSerializationFormatOptions jsonSerializationFormatOptions; @@ -29,9 +30,9 @@ public ChangeFeedCrossFeedRangeAsyncEnumerator( public ValueTask DisposeAsync() => this.enumerator.DisposeAsync(); - public async ValueTask MoveNextAsync() + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - if (!await this.enumerator.MoveNextAsync()) + if (!await this.enumerator.MoveNextAsync(trace, cancellationToken)) { throw new InvalidOperationException("Change Feed should always be able to move next."); } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs index 87b34cca17..bafe2c3b89 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/ChangeFeedIteratorCore.cs @@ -208,8 +208,7 @@ public ChangeFeedIteratorCore( changeFeedRequestOptions?.PageSizeHint, changeFeedRequestOptions?.JsonSerializationFormatOptions?.JsonSerializationFormat, additionalHeaders, - this.changeFeedQuerySpec), - cancellationToken: default); + this.changeFeedQuerySpec)); TryCatch monadicEnumerator = TryCatch.FromResult(enumerator); return monadicEnumerator; @@ -274,11 +273,10 @@ private async Task ReadNextInternalAsync(ITrace trace, Cancella } CrossPartitionChangeFeedAsyncEnumerator enumerator = monadicEnumerator.Result; - enumerator.SetCancellationToken(cancellationToken); try { - if (!await enumerator.MoveNextAsync(trace)) + if (!await enumerator.MoveNextAsync(trace, cancellationToken)) { throw new InvalidOperationException("ChangeFeed enumerator should always have a next continuation"); } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedNotModifiedPage.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedNotModifiedPage.cs index 7c1b09bf59..814d1b583e 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedNotModifiedPage.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedNotModifiedPage.cs @@ -12,14 +12,16 @@ internal sealed class ChangeFeedNotModifiedPage : ChangeFeedPage private static readonly ImmutableHashSet bannedHeaders = new HashSet().ToImmutableHashSet(); public ChangeFeedNotModifiedPage( - double requestCharge, + double requestCharge, string activityId, IReadOnlyDictionary additionalHeaders, ChangeFeedState state) : base(requestCharge, activityId, additionalHeaders, state) { - } - + } + + public override int ItemCount => 0; + protected override ImmutableHashSet DerivedClassBannedHeaders => bannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPartitionRangePageAsyncEnumerator.cs index 4c0b6e169d..15228e92e9 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedPartitionRangePageAsyncEnumerator.cs @@ -19,9 +19,8 @@ internal sealed class ChangeFeedPartitionRangePageAsyncEnumerator : PartitionRan public ChangeFeedPartitionRangePageAsyncEnumerator( IChangeFeedDataSource changeFeedDataSource, FeedRangeState feedRangeState, - ChangeFeedPaginationOptions changeFeedPaginationOptions, - CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) + ChangeFeedPaginationOptions changeFeedPaginationOptions) + : base(feedRangeState) { this.changeFeedDataSource = changeFeedDataSource ?? throw new ArgumentNullException(nameof(changeFeedDataSource)); this.changeFeedPaginationOptions = changeFeedPaginationOptions ?? throw new ArgumentNullException(nameof(changeFeedPaginationOptions)); diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedSuccessPage.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedSuccessPage.cs index caf9d3276f..8499a9f7ca 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedSuccessPage.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/ChangeFeedSuccessPage.cs @@ -15,17 +15,21 @@ internal sealed class ChangeFeedSuccessPage : ChangeFeedPage public ChangeFeedSuccessPage( Stream content, - double requestCharge, + double requestCharge, + int itemCount, string activityId, IReadOnlyDictionary additionalHeaders, ChangeFeedState state) : base(requestCharge, activityId, additionalHeaders, state) { - this.Content = content ?? throw new ArgumentNullException(nameof(content)); + this.Content = content ?? throw new ArgumentNullException(nameof(content)); + this.ItemCount = itemCount; } - public Stream Content { get; } - + public Stream Content { get; } + + public override int ItemCount { get; } + protected override ImmutableHashSet DerivedClassBannedHeaders => bannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/CrossPartitionChangeFeedAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/CrossPartitionChangeFeedAsyncEnumerator.cs index a359a9baaf..0ecb494546 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/CrossPartitionChangeFeedAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeed/Pagination/CrossPartitionChangeFeedAsyncEnumerator.cs @@ -12,32 +12,24 @@ namespace Microsoft.Azure.Cosmos.ChangeFeed.Pagination using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Tracing; - internal sealed class CrossPartitionChangeFeedAsyncEnumerator : IAsyncEnumerator>> + internal sealed class CrossPartitionChangeFeedAsyncEnumerator : ITracingAsyncEnumerator>> { private readonly CrossPartitionRangePageAsyncEnumerator crossPartitionEnumerator; - private CancellationToken cancellationToken; private TryCatch>? bufferedException; private CrossPartitionChangeFeedAsyncEnumerator( - CrossPartitionRangePageAsyncEnumerator crossPartitionEnumerator, - CancellationToken cancellationToken) + CrossPartitionRangePageAsyncEnumerator crossPartitionEnumerator) { this.crossPartitionEnumerator = crossPartitionEnumerator ?? throw new ArgumentNullException(nameof(crossPartitionEnumerator)); - this.cancellationToken = cancellationToken; } public TryCatch> Current { get; private set; } public ValueTask DisposeAsync() => this.crossPartitionEnumerator.DisposeAsync(); - public ValueTask MoveNextAsync() - { - return this.MoveNextAsync(NoOpTrace.Singleton); - } - - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -53,7 +45,7 @@ public async ValueTask MoveNextAsync(ITrace trace) return true; } - if (!await this.crossPartitionEnumerator.MoveNextAsync(changeFeedMoveNextTrace)) + if (!await this.crossPartitionEnumerator.MoveNextAsync(changeFeedMoveNextTrace, cancellationToken)) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } @@ -80,7 +72,7 @@ public async ValueTask MoveNextAsync(ITrace trace) double totalRequestCharge = backendPage.RequestCharge; do { - if (!await this.crossPartitionEnumerator.MoveNextAsync(drainNotModifedPages)) + if (!await this.crossPartitionEnumerator.MoveNextAsync(drainNotModifedPages, cancellationToken)) { throw new InvalidOperationException("ChangeFeed should always have a next page."); } @@ -107,7 +99,8 @@ public async ValueTask MoveNextAsync(ITrace trace) { backendPage = new ChangeFeedSuccessPage( changeFeedSuccessPage.Content, - totalRequestCharge, + totalRequestCharge, + changeFeedSuccessPage.ItemCount, changeFeedSuccessPage.ActivityId, changeFeedSuccessPage.AdditionalHeaders, changeFeedSuccessPage.State); @@ -115,7 +108,7 @@ public async ValueTask MoveNextAsync(ITrace trace) else { backendPage = new ChangeFeedNotModifiedPage( - totalRequestCharge, + totalRequestCharge, backendPage.ActivityId, backendPage.AdditionalHeaders, backendPage.State); @@ -133,17 +126,10 @@ public async ValueTask MoveNextAsync(ITrace trace) } } - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - this.crossPartitionEnumerator.SetCancellationToken(cancellationToken); - } - public static CrossPartitionChangeFeedAsyncEnumerator Create( IDocumentContainer documentContainer, CrossFeedRangeState state, - ChangeFeedPaginationOptions changeFeedPaginationOptions, - CancellationToken cancellationToken) + ChangeFeedPaginationOptions changeFeedPaginationOptions) { changeFeedPaginationOptions ??= ChangeFeedPaginationOptions.Default; @@ -156,17 +142,14 @@ public static CrossPartitionChangeFeedAsyncEnumerator Create( documentContainer, CrossPartitionChangeFeedAsyncEnumerator.MakeCreateFunction( documentContainer, - changeFeedPaginationOptions, - cancellationToken), + changeFeedPaginationOptions), comparer: default /* this uses a regular queue instead of priority queue */, maxConcurrency: default, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: cancellationToken, state: state); CrossPartitionChangeFeedAsyncEnumerator enumerator = new CrossPartitionChangeFeedAsyncEnumerator( - crossPartitionEnumerator, - cancellationToken); + crossPartitionEnumerator); return enumerator; } @@ -181,11 +164,9 @@ private static bool IsNextRangeEqualToOriginal( private static CreatePartitionRangePageAsyncEnumerator MakeCreateFunction( IChangeFeedDataSource changeFeedDataSource, - ChangeFeedPaginationOptions changeFeedPaginationOptions, - CancellationToken cancellationToken) => (FeedRangeState feedRangeState) => new ChangeFeedPartitionRangePageAsyncEnumerator( + ChangeFeedPaginationOptions changeFeedPaginationOptions) => (FeedRangeState feedRangeState) => new ChangeFeedPartitionRangePageAsyncEnumerator( changeFeedDataSource, feedRangeState, - changeFeedPaginationOptions, - cancellationToken); + changeFeedPaginationOptions); } } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumerator.cs index de689618f6..d79bd2bf7c 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumerator.cs @@ -15,10 +15,27 @@ internal sealed class BufferedPartitionRangePageAsyncEnumerator : where TState : State { private readonly PartitionRangePageAsyncEnumerator enumerator; - private TryCatch? bufferedPage; + private TryCatch? bufferedPage; + + public override Exception BufferedException + { + get + { + if (this.bufferedPage.HasValue && this.bufferedPage.Value.Failed) + { + return this.bufferedPage.Value.Exception; + } + + return null; + } + } + + public override int BufferedItemCount => this.bufferedPage.HasValue && this.bufferedPage.Value.Succeeded ? + this.bufferedPage.Value.Result.ItemCount : + 0; - public BufferedPartitionRangePageAsyncEnumerator(PartitionRangePageAsyncEnumerator enumerator, CancellationToken cancellationToken) - : base(enumerator.FeedRangeState, cancellationToken) + public BufferedPartitionRangePageAsyncEnumerator(PartitionRangePageAsyncEnumerator enumerator) + : base(enumerator.FeedRangeState) { this.enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator)); } @@ -59,15 +76,9 @@ public override async ValueTask PrefetchAsync(ITrace trace, CancellationToken ca using (ITrace prefetchTrace = trace.StartChild("Prefetch", TraceComponent.Pagination, TraceLevel.Info)) { - await this.enumerator.MoveNextAsync(prefetchTrace); + await this.enumerator.MoveNextAsync(prefetchTrace, cancellationToken); this.bufferedPage = this.enumerator.Current; } } - - public override void SetCancellationToken(CancellationToken cancellationToken) - { - base.SetCancellationToken(cancellationToken); - this.enumerator.SetCancellationToken(cancellationToken); - } } } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumeratorBase.cs b/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumeratorBase.cs index 67af30c353..d54d3c1c64 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumeratorBase.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/BufferedPartitionRangePageAsyncEnumeratorBase.cs @@ -3,7 +3,8 @@ // ------------------------------------------------------------ namespace Microsoft.Azure.Cosmos.Pagination -{ +{ + using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Tracing; @@ -12,10 +13,14 @@ internal abstract class BufferedPartitionRangePageAsyncEnumeratorBase where TState : State { - protected BufferedPartitionRangePageAsyncEnumeratorBase(FeedRangeState feedRangeState, CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) + protected BufferedPartitionRangePageAsyncEnumeratorBase(FeedRangeState feedRangeState) + : base(feedRangeState) { - } + } + + public abstract Exception BufferedException { get; } + + public abstract int BufferedItemCount { get; } public abstract ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken); } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/CrossFeedRangePage.cs b/Microsoft.Azure.Cosmos/src/Pagination/CrossFeedRangePage.cs index 578e6b6459..675620885b 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/CrossFeedRangePage.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/CrossFeedRangePage.cs @@ -19,8 +19,10 @@ public CrossFeedRangePage(TBackendPage backendEndPage, CrossFeedRangeState this.Page.ItemCount; + protected override ImmutableHashSet DerivedClassBannedHeaders => bannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/CrossPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/CrossPartitionRangePageAsyncEnumerator.cs index a56a21d593..4feb66363e 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/CrossPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/CrossPartitionRangePageAsyncEnumerator.cs @@ -26,7 +26,6 @@ internal sealed class CrossPartitionRangePageAsyncEnumerator : IT private readonly IFeedRangeProvider feedRangeProvider; private readonly CreatePartitionRangePageAsyncEnumerator createPartitionRangeEnumerator; private readonly AsyncLazy>> lazyEnumerators; - private CancellationToken cancellationToken; private FeedRangeState? nextState; public CrossPartitionRangePageAsyncEnumerator( @@ -35,12 +34,10 @@ public CrossPartitionRangePageAsyncEnumerator( IComparer> comparer, int? maxConcurrency, PrefetchPolicy prefetchPolicy, - CancellationToken cancellationToken, CrossFeedRangeState state = default) { this.feedRangeProvider = feedRangeProvider ?? throw new ArgumentNullException(nameof(feedRangeProvider)); this.createPartitionRangeEnumerator = createPartitionRangeEnumerator ?? throw new ArgumentNullException(nameof(createPartitionRangeEnumerator)); - this.cancellationToken = cancellationToken; this.lazyEnumerators = new AsyncLazy>>((ITrace trace, CancellationToken token) => InitializeEnumeratorsAsync( @@ -58,7 +55,7 @@ public CrossPartitionRangePageAsyncEnumerator( public FeedRangeInternal CurrentRange { get; private set; } - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { @@ -69,7 +66,7 @@ public async ValueTask MoveNextAsync(ITrace trace) { IQueue> enumerators = await this.lazyEnumerators.GetValueAsync( childTrace, - cancellationToken: this.cancellationToken); + cancellationToken); if (enumerators.Count == 0) { this.Current = default; @@ -79,11 +76,10 @@ public async ValueTask MoveNextAsync(ITrace trace) } PartitionRangePageAsyncEnumerator currentPaginator = enumerators.Dequeue(); - currentPaginator.SetCancellationToken(this.cancellationToken); bool moveNextResult = false; try { - moveNextResult = await currentPaginator.MoveNextAsync(childTrace); + moveNextResult = await currentPaginator.MoveNextAsync(childTrace, cancellationToken); } catch { @@ -96,7 +92,7 @@ public async ValueTask MoveNextAsync(ITrace trace) { // Current enumerator is empty, // so recursively retry on the next enumerator. - return await this.MoveNextAsync(childTrace); + return await this.MoveNextAsync(childTrace, cancellationToken); } if (currentPaginator.Current.Failed) @@ -114,18 +110,18 @@ public async ValueTask MoveNextAsync(ITrace trace) List childRanges = await this.feedRangeProvider.GetChildRangeAsync( currentPaginator.FeedRangeState.FeedRange, childTrace, - this.cancellationToken); + cancellationToken); if (childRanges.Count <= 1) { // We optimistically assumed that the cache is not stale. // In the event that it is (where we only get back one child / the partition that we think got split) // Then we need to refresh the cache - await this.feedRangeProvider.RefreshProviderAsync(childTrace, this.cancellationToken); + await this.feedRangeProvider.RefreshProviderAsync(childTrace, cancellationToken); childRanges = await this.feedRangeProvider.GetChildRangeAsync( currentPaginator.FeedRangeState.FeedRange, childTrace, - this.cancellationToken); + cancellationToken); } if (childRanges.Count < 1) @@ -157,7 +153,7 @@ public async ValueTask MoveNextAsync(ITrace trace) } // Recursively retry - return await this.MoveNextAsync(childTrace); + return await this.MoveNextAsync(childTrace, cancellationToken); } // Just enqueue the paginator and the user can decide if they want to retry. @@ -218,11 +214,6 @@ public bool TryPeekNext(out FeedRangeState nextState) return false; } - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - } - private static bool IsSplitException(Exception exeception) { return exeception is CosmosException cosmosException @@ -304,8 +295,8 @@ private static IReadOnlyList enumerator = createPartitionRangeEnumerator(feedRangeState); BufferedPartitionRangePageAsyncEnumeratorBase bufferedEnumerator = policy switch { - PrefetchPolicy.PrefetchSinglePage => new BufferedPartitionRangePageAsyncEnumerator(enumerator, cancellationToken), - PrefetchPolicy.PrefetchAll => new FullyBufferedPartitionRangeAsyncEnumerator(enumerator, cancellationToken), + PrefetchPolicy.PrefetchSinglePage => new BufferedPartitionRangePageAsyncEnumerator(enumerator), + PrefetchPolicy.PrefetchAll => new FullyBufferedPartitionRangeAsyncEnumerator(enumerator), _ => throw new ArgumentOutOfRangeException(nameof(policy)), }; bufferedEnumerators.Add(bufferedEnumerator); diff --git a/Microsoft.Azure.Cosmos/src/Pagination/FullyBufferedPartitionRangeAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/FullyBufferedPartitionRangeAsyncEnumerator.cs index d9da53e15c..d029fa667e 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/FullyBufferedPartitionRangeAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/FullyBufferedPartitionRangeAsyncEnumerator.cs @@ -16,16 +16,31 @@ internal sealed class FullyBufferedPartitionRangeAsyncEnumerator { private readonly PartitionRangePageAsyncEnumerator enumerator; private readonly List bufferedPages; - private int currentIndex; + private int currentIndex; + private int bufferedItemCount; private Exception exception; - private bool HasPrefetched => (this.exception != null) || (this.bufferedPages.Count > 0); + private bool hasPrefetched; + + public override Exception BufferedException => this.exception; + + public override int BufferedItemCount => this.bufferedItemCount; - public FullyBufferedPartitionRangeAsyncEnumerator(PartitionRangePageAsyncEnumerator enumerator, CancellationToken cancellationToken) - : base(enumerator.FeedRangeState, cancellationToken) + public FullyBufferedPartitionRangeAsyncEnumerator(PartitionRangePageAsyncEnumerator enumerator) + : this(enumerator, null) + { + } + + public FullyBufferedPartitionRangeAsyncEnumerator(PartitionRangePageAsyncEnumerator enumerator, IReadOnlyList bufferedPages) + : base(enumerator.FeedRangeState) { this.enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator)); - this.bufferedPages = new List(); + this.bufferedPages = new List(); + + if (bufferedPages != null) + { + this.bufferedPages.AddRange(bufferedPages); + } } public override ValueTask DisposeAsync() @@ -40,7 +55,7 @@ public override async ValueTask PrefetchAsync(ITrace trace, CancellationToken ca throw new ArgumentNullException(nameof(trace)); } - if (this.HasPrefetched) + if (this.hasPrefetched) { return; } @@ -49,13 +64,14 @@ public override async ValueTask PrefetchAsync(ITrace trace, CancellationToken ca using (ITrace prefetchTrace = trace.StartChild("Prefetch", TraceComponent.Pagination, TraceLevel.Info)) { - while (await this.enumerator.MoveNextAsync(prefetchTrace)) + while (await this.enumerator.MoveNextAsync(prefetchTrace, cancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); TryCatch current = this.enumerator.Current; if (current.Succeeded) { - this.bufferedPages.Add(current.Result); + this.bufferedPages.Add(current.Result); + this.bufferedItemCount += current.Result.ItemCount; } else { @@ -63,7 +79,9 @@ public override async ValueTask PrefetchAsync(ITrace trace, CancellationToken ca break; } } - } + } + + this.hasPrefetched = true; } protected override async Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken) @@ -79,18 +97,12 @@ protected override async Task> GetNextPageAsync(ITrace trace, Ca } else { - await this.enumerator.MoveNextAsync(trace); + await this.enumerator.MoveNextAsync(trace, cancellationToken); result = this.enumerator.Current; } ++this.currentIndex; return result; } - - public override void SetCancellationToken(CancellationToken cancellationToken) - { - base.SetCancellationToken(cancellationToken); - this.enumerator.SetCancellationToken(cancellationToken); - } } } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/ITracingAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/ITracingAsyncEnumerator.cs index a4c232af48..d9c656a2e2 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/ITracingAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/ITracingAsyncEnumerator.cs @@ -4,7 +4,8 @@ namespace Microsoft.Azure.Cosmos.Pagination { - using System; + using System; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Tracing; @@ -12,6 +13,6 @@ internal interface ITracingAsyncEnumerator : IAsyncDisposable { T Current { get; } - ValueTask MoveNextAsync(ITrace trace); + ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs index 8420cb0540..eb87821663 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/NetworkAttachedDocumentContainer.cs @@ -206,7 +206,8 @@ public async Task> MonadicReadFeedAsync( if (responseMessage.StatusCode == HttpStatusCode.OK) { double requestCharge = responseMessage.Headers.RequestCharge; - string activityId = responseMessage.Headers.ActivityId; + string activityId = responseMessage.Headers.ActivityId; + int itemCount = int.Parse(responseMessage.Headers.ItemCount); ReadFeedState state = responseMessage.Headers.ContinuationToken != null ? ReadFeedState.Continuation(CosmosString.Create(responseMessage.Headers.ContinuationToken)) : null; Dictionary additionalHeaders = GetAdditionalHeaders( responseMessage.Headers.CosmosMessageHeaders, @@ -214,7 +215,8 @@ public async Task> MonadicReadFeedAsync( ReadFeedPage readFeedPage = new ReadFeedPage( responseMessage.Content, - requestCharge, + requestCharge, + itemCount, activityId, additionalHeaders, state); @@ -327,7 +329,8 @@ public async Task> MonadicChangeFeedAsync( if (pageHasResult) { double requestCharge = responseMessage.Headers.RequestCharge; - string activityId = responseMessage.Headers.ActivityId; + string activityId = responseMessage.Headers.ActivityId; + int itemCount = int.Parse(responseMessage.Headers.ItemCount); ChangeFeedState state = ChangeFeedState.Continuation(CosmosString.Create(responseMessage.Headers.ETag)); Dictionary additionalHeaders = GetAdditionalHeaders( responseMessage.Headers.CosmosMessageHeaders, @@ -338,7 +341,8 @@ public async Task> MonadicChangeFeedAsync( { changeFeedPage = new ChangeFeedSuccessPage( responseMessage.Content, - requestCharge, + requestCharge, + itemCount, activityId, additionalHeaders, state); diff --git a/Microsoft.Azure.Cosmos/src/Pagination/Page.cs b/Microsoft.Azure.Cosmos/src/Pagination/Page.cs index ee0db8af85..f3ed29ebf4 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/Page.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/Page.cs @@ -17,15 +17,15 @@ internal abstract class Page Microsoft.Azure.Documents.HttpConstants.HttpHeaders.ActivityId, }.ToImmutableHashSet(); - private static readonly IReadOnlyDictionary EmptyDictionary = new Dictionary(); + private static readonly IReadOnlyDictionary EmptyDictionary = new Dictionary().ToImmutableDictionary(); protected Page( - double requestCharge, + double requestCharge, string activityId, IReadOnlyDictionary additionalHeaders, TState state) { - this.RequestCharge = requestCharge < 0 ? throw new ArgumentOutOfRangeException(nameof(requestCharge)) : requestCharge; + this.RequestCharge = requestCharge < 0 ? throw new ArgumentOutOfRangeException(nameof(requestCharge)) : requestCharge; this.ActivityId = activityId; this.State = state; @@ -47,7 +47,9 @@ protected Page( this.AdditionalHeaders = additionalHeaders ?? EmptyDictionary; } - public double RequestCharge { get; } + public double RequestCharge { get; } + + public abstract int ItemCount { get; } public string ActivityId { get; } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs b/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs index 593d761ec0..ac50876ab8 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/PaginationOptions.cs @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.Pagination using System; using System.Collections.Generic; using System.Collections.Immutable; - using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Documents; internal abstract class PaginationOptions @@ -23,10 +22,10 @@ internal abstract class PaginationOptions protected PaginationOptions( int? pageSizeLimit = null, - Dictionary additionalHeaders = null) + IReadOnlyDictionary additionalHeaders = null) { this.PageSizeLimit = pageSizeLimit; - this.AdditionalHeaders = additionalHeaders != null ? additionalHeaders.ToImmutableDictionary() : EmptyDictionary; + this.AdditionalHeaders = additionalHeaders ?? EmptyDictionary; foreach (string key in this.AdditionalHeaders.Keys) { @@ -39,7 +38,7 @@ protected PaginationOptions( public int? PageSizeLimit { get; } - public ImmutableDictionary AdditionalHeaders { get; } + public IReadOnlyDictionary AdditionalHeaders { get; } protected abstract ImmutableHashSet BannedAdditionalHeaders { get; } } diff --git a/Microsoft.Azure.Cosmos/src/Pagination/PartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/PartitionRangePageAsyncEnumerator.cs index ac9b56d5ee..1dc017527f 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/PartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/PartitionRangePageAsyncEnumerator.cs @@ -18,12 +18,9 @@ internal abstract class PartitionRangePageAsyncEnumerator : ITrac where TPage : Page where TState : State { - private CancellationToken cancellationToken; - - protected PartitionRangePageAsyncEnumerator(FeedRangeState feedRangeState, CancellationToken cancellationToken) + protected PartitionRangePageAsyncEnumerator(FeedRangeState feedRangeState) { this.FeedRangeState = feedRangeState; - this.cancellationToken = cancellationToken; } public FeedRangeState FeedRangeState { get; private set; } @@ -34,7 +31,7 @@ protected PartitionRangePageAsyncEnumerator(FeedRangeState feedRangeStat private bool HasMoreResults => !this.HasStarted || (this.FeedRangeState.State != default); - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { @@ -48,7 +45,7 @@ public async ValueTask MoveNextAsync(ITrace trace) return false; } - this.Current = await this.GetNextPageAsync(trace: childTrace, cancellationToken: this.cancellationToken); + this.Current = await this.GetNextPageAsync(trace: childTrace, cancellationToken); if (this.Current.Succeeded) { this.FeedRangeState = new FeedRangeState(this.FeedRangeState.FeedRange, this.Current.Result.State); @@ -62,10 +59,5 @@ public async ValueTask MoveNextAsync(ITrace trace) protected abstract Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken); public abstract ValueTask DisposeAsync(); - - public virtual void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TracingAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Pagination/TracingAsyncEnumerator.cs similarity index 75% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TracingAsyncEnumerator.cs rename to Microsoft.Azure.Cosmos/src/Pagination/TracingAsyncEnumerator.cs index e37b87a978..b4af0ea01f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TracingAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/TracingAsyncEnumerator.cs @@ -2,10 +2,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // ------------------------------------------------------------ -namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline +namespace Microsoft.Azure.Cosmos.Pagination { using System; - using System.Collections.Generic; + using System.Collections.Generic; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Tracing; @@ -13,12 +14,14 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline internal sealed class TracingAsyncEnumerator : IAsyncEnumerator { private readonly ITracingAsyncEnumerator enumerator; - private readonly ITrace trace; + private readonly ITrace trace; + private readonly CancellationToken cancellationToken; - public TracingAsyncEnumerator(ITracingAsyncEnumerator enumerator, ITrace trace) + public TracingAsyncEnumerator(ITracingAsyncEnumerator enumerator, ITrace trace, CancellationToken cancellationToken) { this.enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator)); - this.trace = trace ?? throw new ArgumentNullException(nameof(trace)); + this.trace = trace ?? throw new ArgumentNullException(nameof(trace)); + this.cancellationToken = cancellationToken; } public T Current => this.enumerator.Current; @@ -30,7 +33,7 @@ public ValueTask DisposeAsync() public ValueTask MoveNextAsync() { - return this.enumerator.MoveNextAsync(this.trace); + return this.enumerator.MoveNextAsync(this.trace, this.cancellationToken); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs index c1fff1ac59..7966918fcc 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Client.cs @@ -13,7 +13,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Aggregate.Aggregators; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Documents; + using static IndexUtilizationHelper; internal abstract partial class AggregateQueryPipelineStage : QueryPipelineStageBase { @@ -22,9 +22,8 @@ private sealed class ClientAggregateQueryPipelineStage : AggregateQueryPipelineS private ClientAggregateQueryPipelineStage( IQueryPipelineStage source, SingleGroupAggregator singleGroupAggregator, - bool isValueAggregateQuery, - CancellationToken cancellationToken) - : base(source, singleGroupAggregator, isValueAggregateQuery, cancellationToken) + bool isValueAggregateQuery) + : base(source, singleGroupAggregator, isValueAggregateQuery) { // all the work is done in the base constructor. } @@ -35,7 +34,6 @@ public static TryCatch MonadicCreate( IReadOnlyList orderedAliases, bool hasSelectValue, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (monadicCreatePipelineStage == null) @@ -54,7 +52,7 @@ public static TryCatch MonadicCreate( return TryCatch.FromException(tryCreateSingleGroupAggregator.Exception); } - TryCatch tryCreateSource = monadicCreatePipelineStage(continuationToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(continuationToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -63,15 +61,14 @@ public static TryCatch MonadicCreate( ClientAggregateQueryPipelineStage stage = new ClientAggregateQueryPipelineStage( tryCreateSource.Result, tryCreateSingleGroupAggregator.Result, - hasSelectValue, - cancellationToken); + hasSelectValue); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -88,10 +85,9 @@ public override async ValueTask MoveNextAsync(ITrace trace) // but then we will have to design a continuation token. double requestCharge = 0; - long responseLengthBytes = 0; IReadOnlyDictionary cumulativeAdditionalHeaders = default; - while (await this.inputStage.MoveNextAsync(trace)) + while (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { TryCatch tryGetPageFromSource = this.inputStage.Current; if (tryGetPageFromSource.Failed) @@ -103,19 +99,14 @@ public override async ValueTask MoveNextAsync(ITrace trace) QueryPage sourcePage = tryGetPageFromSource.Result; requestCharge += sourcePage.RequestCharge; - responseLengthBytes += sourcePage.ResponseLengthInBytes; - // Note-2024-02-02: - // Here the IndexMetrics headers are non-accumulative, so we are copying that header from the source page. - // Other headers might need similar traeatment, and it's up to the area owner to implement that here. - if (sourcePage.AdditionalHeaders.ContainsKey(HttpConstants.HttpHeaders.IndexUtilization)) - { - cumulativeAdditionalHeaders = new Dictionary() {{ HttpConstants.HttpHeaders.IndexUtilization, sourcePage.AdditionalHeaders[HttpConstants.HttpHeaders.IndexUtilization] }}; - } + cumulativeAdditionalHeaders = AccumulateIndexUtilization( + cumulativeHeaders: cumulativeAdditionalHeaders, + currentHeaders: sourcePage.AdditionalHeaders); foreach (CosmosElement element in sourcePage.Documents) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueQuery, @@ -135,12 +126,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: finalResult, requestCharge: requestCharge, activityId: default, - responseLengthInBytes: responseLengthBytes, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: cumulativeAdditionalHeaders, - state: default); + state: default, + streaming: default); this.Current = TryCatch.FromResult(queryPage); this.returnedFinalPage = true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs index 8a34e69a8a..fb938b530d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.Compute.cs @@ -26,9 +26,8 @@ private sealed class ComputeAggregateQueryPipelineStage : AggregateQueryPipeline private ComputeAggregateQueryPipelineStage( IQueryPipelineStage source, SingleGroupAggregator singleGroupAggregator, - bool isValueAggregateQuery, - CancellationToken cancellationToken) - : base(source, singleGroupAggregator, isValueAggregateQuery, cancellationToken) + bool isValueAggregateQuery) + : base(source, singleGroupAggregator, isValueAggregateQuery) { // all the work is done in the base constructor. } @@ -39,11 +38,8 @@ public static TryCatch MonadicCreate( IReadOnlyList orderedAliases, bool hasSelectValue, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { - cancellationToken.ThrowIfCancellationRequested(); - AggregateContinuationToken aggregateContinuationToken; if (continuationToken != null) { @@ -79,7 +75,7 @@ public static TryCatch MonadicCreate( } else { - tryCreateSource = monadicCreatePipelineStage(aggregateContinuationToken.SourceContinuationToken, cancellationToken); + tryCreateSource = monadicCreatePipelineStage(aggregateContinuationToken.SourceContinuationToken); } if (tryCreateSource.Failed) @@ -90,15 +86,14 @@ public static TryCatch MonadicCreate( ComputeAggregateQueryPipelineStage stage = new ComputeAggregateQueryPipelineStage( tryCreateSource.Result, tryCreateSingleGroupAggregator.Result, - hasSelectValue, - cancellationToken); + hasSelectValue); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -113,7 +108,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) // Draining aggregates is broken down into two stages QueryPage queryPage; - if (await this.inputStage.MoveNextAsync(trace)) + if (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { // Stage 1: // Drain the aggregates fully from all continuations and all partitions @@ -128,7 +123,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) QueryPage sourcePage = tryGetSourcePage.Result; foreach (CosmosElement element in sourcePage.Documents) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); RewrittenAggregateProjections rewrittenAggregateProjections = new RewrittenAggregateProjections( this.isValueQuery, @@ -144,12 +139,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: EmptyResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: queryState); + state: queryState, + streaming: sourcePage.Streaming); queryPage = emptyPage; } @@ -168,12 +163,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: finalResult, requestCharge: default, activityId: default, - responseLengthInBytes: default, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: default); + state: default, + streaming: default); queryPage = finalPage; this.returnedFinalPage = true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.cs index 0146c3b15e..cf681d0d4d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Aggregate/AggregateQueryPipelineStage.cs @@ -46,14 +46,12 @@ internal abstract partial class AggregateQueryPipelineStage : QueryPipelineStage /// The source component that will supply the local aggregates from multiple continuations and partitions. /// The single group aggregator that we will feed results into. /// Whether or not the query has the 'VALUE' keyword. - /// The cancellation token for cooperative yeilding. /// This constructor is private since there is some async initialization that needs to happen in CreateAsync(). public AggregateQueryPipelineStage( IQueryPipelineStage source, SingleGroupAggregator singleGroupAggregator, - bool isValueQuery, - CancellationToken cancellationToken) - : base(source, cancellationToken) + bool isValueQuery) + : base(source) { this.singleGroupAggregator = singleGroupAggregator ?? throw new ArgumentNullException(nameof(singleGroupAggregator)); this.isValueQuery = isValueQuery; @@ -66,7 +64,6 @@ public static TryCatch MonadicCreate( IReadOnlyList orderedAliases, bool hasSelectValue, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch { ExecutionEnvironment.Client => ClientAggregateQueryPipelineStage.MonadicCreate( @@ -75,7 +72,6 @@ public static TryCatch MonadicCreate( orderedAliases, hasSelectValue, continuationToken, - cancellationToken, monadicCreatePipelineStage), ExecutionEnvironment.Compute => ComputeAggregateQueryPipelineStage.MonadicCreate( aggregates, @@ -83,7 +79,6 @@ public static TryCatch MonadicCreate( orderedAliases, hasSelectValue, continuationToken, - cancellationToken, monadicCreatePipelineStage), _ => throw new ArgumentException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}."), }; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CatchAllQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CatchAllQueryPipelineStage.cs index 827fc1c02c..74c953a93e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CatchAllQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CatchAllQueryPipelineStage.cs @@ -13,12 +13,12 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline internal sealed class CatchAllQueryPipelineStage : QueryPipelineStageBase { - public CatchAllQueryPipelineStage(IQueryPipelineStage inputStage, CancellationToken cancellationToken) - : base(inputStage, cancellationToken) + public CatchAllQueryPipelineStage(IQueryPipelineStage inputStage) + : base(inputStage) { } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { @@ -27,7 +27,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) try { - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index e7a65b7457..fdca4ee452 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -19,7 +19,6 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext using Microsoft.Azure.Cosmos.Query.Core.Parser; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Tokens; @@ -68,18 +67,18 @@ public static IQueryPipelineStage Create( { // Query Iterator requires that the creation of the query context is deferred until the user calls ReadNextAsync AsyncLazy> lazyTryCreateStage = new AsyncLazy>( - valueFactory: (trace, innerCancellationToken) => CosmosQueryExecutionContextFactory.TryCreateCoreContextAsync( + valueFactory: (trace, innerCancellationToken) => TryCreateCoreContextAsync( documentContainer, cosmosQueryContext, inputParameters, trace, innerCancellationToken)); - LazyQueryPipelineStage lazyQueryPipelineStage = new LazyQueryPipelineStage(lazyTryCreateStage: lazyTryCreateStage, cancellationToken: default); + LazyQueryPipelineStage lazyQueryPipelineStage = new LazyQueryPipelineStage(lazyTryCreateStage: lazyTryCreateStage); return lazyQueryPipelineStage; }); - CatchAllQueryPipelineStage catchAllQueryPipelineStage = new CatchAllQueryPipelineStage(nameCacheStaleRetryQueryPipelineStage, cancellationToken: default); + CatchAllQueryPipelineStage catchAllQueryPipelineStage = new CatchAllQueryPipelineStage(nameCacheStaleRetryQueryPipelineStage); return catchAllQueryPipelineStage; } @@ -201,11 +200,10 @@ private static async Task> TryCreateCoreContextAsy forceRefresh: false, createQueryPipelineTrace); - return CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContext( + return TryCreatePassthroughQueryExecutionContext( documentContainer, inputParameters, - targetRanges, - cancellationToken); + targetRanges); } } } @@ -240,7 +238,7 @@ private static async Task> TryCreateFromPartitione { cancellationToken.ThrowIfCancellationRequested(); - List targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( + List targetRanges = await GetTargetPartitionKeyRangesAsync( cosmosQueryContext.QueryClient, cosmosQueryContext.ResourceLink, partitionedQueryExecutionInfo, @@ -291,15 +289,19 @@ private static async Task> TryCreateFromPartitione { SetTestInjectionPipelineType(inputParameters, Passthrough); - tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreatePassthroughQueryExecutionContext( + tryCreatePipelineStage = TryCreatePassthroughQueryExecutionContext( documentContainer, inputParameters, - targetRanges, - cancellationToken); + targetRanges); } else { - tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext(documentContainer, cosmosQueryContext, inputParameters, targetRanges, partitionedQueryExecutionInfo, cancellationToken); + tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext( + documentContainer, + cosmosQueryContext, + inputParameters, + targetRanges, + partitionedQueryExecutionInfo); } } @@ -330,7 +332,7 @@ private static async Task> TryCreateSinglePartitio // Test code added to confirm the correct pipeline is being utilized SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); - TryCatch tryCreatePipelineStage = CosmosQueryExecutionContextFactory.TryCreateOptimisticDirectExecutionContext( + TryCatch tryCreatePipelineStage = TryCreateOptimisticDirectExecutionContext( documentContainer, cosmosQueryContext, containerQueryProperties, @@ -359,8 +361,7 @@ private static async Task> TryCreateSinglePartitio cosmosQueryContext, inputParameters, targetRanges, - partitionedQueryExecutionInfo, - cancellationToken); + partitionedQueryExecutionInfo); } else { @@ -382,8 +383,7 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx CosmosQueryContext cosmosQueryContext, InputParameters inputParameters, List targetRanges, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - CancellationToken cancellationToken) + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) { SetTestInjectionPipelineType(inputParameters, Specialized); @@ -412,13 +412,12 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx inputParameters.TestInjections); } - return CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContext( + return TryCreateSpecializedDocumentQueryExecutionContext( documentContainer, cosmosQueryContext, inputParameters, partitionedQueryExecutionInfo, - targetRanges, - cancellationToken); + targetRanges); } private static async Task> TryCreateSpecializedDocumentQueryExecutionContextAsync( @@ -436,7 +435,7 @@ private static async Task> TryCreateSpecializedDoc trace, cancellationToken); - List targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( + List targetRanges = await GetTargetPartitionKeyRangesAsync( cosmosQueryContext.QueryClient, cosmosQueryContext.ResourceLink, partitionedQueryExecutionInfo, @@ -450,8 +449,7 @@ private static async Task> TryCreateSpecializedDoc cosmosQueryContext, inputParameters, targetRanges, - partitionedQueryExecutionInfo, - cancellationToken); + partitionedQueryExecutionInfo); } private static TryCatch TryCreateOptimisticDirectExecutionContext( @@ -467,28 +465,22 @@ private static TryCatch TryCreateOptimisticDirectExecutionC documentContainer: documentContainer, inputParameters: inputParameters, targetRange: new FeedRangeEpk(targetRange.ToRange()), - fallbackQueryPipelineStageFactory: (continuationToken) => - { - // In fallback scenario, the Specialized pipeline is always invoked - Task> tryCreateContext = - CosmosQueryExecutionContextFactory.TryCreateSpecializedDocumentQueryExecutionContextAsync( - documentContainer, - cosmosQueryContext, - containerQueryProperties, - inputParameters.WithContinuationToken(continuationToken), - NoOpTrace.Singleton, - default); - - return tryCreateContext; - }, + fallbackQueryPipelineStageFactory: (continuationToken) => + // In fallback scenario, the Specialized pipeline is always invoked + TryCreateSpecializedDocumentQueryExecutionContextAsync( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters.WithContinuationToken(continuationToken), + NoOpTrace.Singleton, + cancellationToken), cancellationToken: cancellationToken); } private static TryCatch TryCreatePassthroughQueryExecutionContext( DocumentContainer documentContainer, InputParameters inputParameters, - List targetRanges, - CancellationToken cancellationToken) + List targetRanges) { // Return a parallel context, since we still want to be able to handle splits and concurrency / buffering. return ParallelCrossPartitionQueryPipelineStage.MonadicCreate( @@ -507,7 +499,6 @@ private static TryCatch TryCreatePassthroughQueryExecutionC partitionKey: inputParameters.PartitionKey, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, maxConcurrency: inputParameters.MaxConcurrency, - cancellationToken: cancellationToken, continuationToken: inputParameters.InitialUserContinuationToken); } @@ -516,8 +507,7 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx CosmosQueryContext cosmosQueryContext, InputParameters inputParameters, PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - List targetRanges, - CancellationToken cancellationToken) + List targetRanges) { QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; @@ -577,8 +567,7 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx queryPaginationOptions: new QueryPaginationOptions( pageSizeHint: (int)optimalPageSize), maxConcurrency: inputParameters.MaxConcurrency, - requestContinuationToken: inputParameters.InitialUserContinuationToken, - requestCancellationToken: cancellationToken); + requestContinuationToken: inputParameters.InitialUserContinuationToken); } private static async Task GetPartitionedQueryExecutionInfoAsync( @@ -784,7 +773,7 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP List targetRanges; if (partitionedQueryExecutionInfo != null || inputParameters.InitialFeedRange != null) { - targetRanges = await CosmosQueryExecutionContextFactory.GetTargetPartitionKeyRangesAsync( + targetRanges = await GetTargetPartitionKeyRangesAsync( cosmosQueryContext.QueryClient, cosmosQueryContext.ResourceLink, partitionedQueryExecutionInfo, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionEnumerator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionEnumerator.cs new file mode 100644 index 0000000000..968b1e1c84 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionEnumerator.cs @@ -0,0 +1,206 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Pagination +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Query.Core.Collections; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Tracing; + + internal sealed class OrderByCrossPartitionEnumerator : IEnumerator + { + private readonly PriorityQueue> queue; + + private bool started; + + public OrderByQueryResult Current => this.queue.Peek().Current; + + object IEnumerator.Current => this.Current; + + public OrderByCrossPartitionEnumerator(PriorityQueue> queue) + { + this.queue = queue ?? throw new ArgumentNullException(nameof(queue)); + } + + public static async Task<(IEnumerator orderbyQueryResultEnumerator, double totalRequestCharge)> CreateAsync( + IEnumerable enumerators, + IComparer comparer, + int levelSize, + ITrace trace, + CancellationToken cancellationToken) + { + if (enumerators == null) + { + throw new ArgumentNullException(nameof(enumerators)); + } + + if (comparer == null) + { + throw new ArgumentNullException(nameof(comparer)); + } + + double totalRequestCharge = 0; + EnumeratorComparer enumeratorComparer = new EnumeratorComparer(comparer); + PriorityQueue> queue = new PriorityQueue>(enumeratorComparer); + foreach (ITracingAsyncEnumerator> enumerator in enumerators) + { + while (await enumerator.MoveNextAsync(trace, cancellationToken)) + { + TryCatch currentPage = enumerator.Current; + if (currentPage.Failed) + { + throw currentPage.Exception; + } + + totalRequestCharge += currentPage.Result.RequestCharge; + IReadOnlyList page = currentPage.Result.Page.Documents; + + if (page.Count > 0) + { + PageEnumerator pageEnumerator = new PageEnumerator(page); + pageEnumerator.MoveNext(); + + queue.Enqueue(pageEnumerator); + + if (queue.Count >= levelSize) + { + OrderByCrossPartitionEnumerator newEnumerator = new OrderByCrossPartitionEnumerator(queue); + newEnumerator.MoveNext(); + + queue = new PriorityQueue>(enumeratorComparer); + queue.Enqueue(newEnumerator); + } + } + } + } + + if (queue.Count == 0) + { + return (EmptyEnumerator.Instance, totalRequestCharge); + } + + return (new OrderByCrossPartitionEnumerator(queue), totalRequestCharge); + } + + public bool MoveNext() + { + if (this.queue.Count == 0) + { + return false; + } + + if (!this.started) + { + // We never start empty + this.started = true; + return true; + } + + IEnumerator enumerator = this.queue.Dequeue(); + if (enumerator.MoveNext()) + { + this.queue.Enqueue(enumerator); + } + + return this.queue.Count > 0; + } + + public void Reset() + { + throw new NotSupportedException(); + } + + public void Dispose() + { + while (this.queue.Count > 0) + { + IEnumerator enumerator = this.queue.Dequeue(); + enumerator.Dispose(); + } + } + + private sealed class EmptyEnumerator : IEnumerator + { + public static readonly EmptyEnumerator Instance = new EmptyEnumerator(); + + public OrderByQueryResult Current => throw new InvalidOperationException(); + + object IEnumerator.Current => this.Current; + + private EmptyEnumerator() + { + } + + public bool MoveNext() + { + return false; + } + + public void Reset() + { + } + + public void Dispose() + { + } + } + + private sealed class EnumeratorComparer : IComparer> + { + private readonly IComparer comparer; + + public EnumeratorComparer(IComparer comparer) + { + this.comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); + } + + public int Compare(IEnumerator x, IEnumerator y) + { + return this.comparer.Compare(x.Current, y.Current); + } + } + + private sealed class PageEnumerator : IEnumerator + { + private readonly IEnumerator enumerator; + + public OrderByQueryResult Current { get; private set; } + + object IEnumerator.Current => this.Current; + + public PageEnumerator(IReadOnlyList page) + { + this.enumerator = page?.GetEnumerator() ?? throw new ArgumentNullException(nameof(page)); + } + + public bool MoveNext() + { + if (this.enumerator.MoveNext()) + { + this.Current = new OrderByQueryResult(this.enumerator.Current); + return true; + } + + return false; + } + + public void Reset() + { + this.enumerator.Reset(); + } + + public void Dispose() + { + this.enumerator.Dispose(); + } + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index f22eb8a6af..edd2fa7be7 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -1,1540 +1,2015 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Expressions; - using System.Net; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.CosmosElements.Numbers; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Collections; - using Microsoft.Azure.Cosmos.Query.Core.Exceptions; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.QueryClient; - using Microsoft.Azure.Cosmos.Tracing; - using ResourceId = Documents.ResourceId; - - /// - /// CosmosOrderByItemQueryExecutionContext is a concrete implementation for CrossPartitionQueryExecutionContext. - /// This class is responsible for draining cross partition queries that have order by conditions. - /// The way order by queries work is that they are doing a k-way merge of sorted lists from each partition with an added condition. - /// The added condition is that if 2 or more top documents from different partitions are equivalent then we drain from the left most partition first. - /// This way we can generate a single continuation token for all n partitions. - /// This class is able to stop and resume execution by generating continuation tokens and reconstructing an execution context from said token. - /// - internal sealed class OrderByCrossPartitionQueryPipelineStage : IQueryPipelineStage - { - /// - /// Order by queries are rewritten to allow us to inject a filter. - /// This placeholder is so that we can just string replace it with the filter we want without having to understand the structure of the query. - /// - private const string FormatPlaceHolder = "{documentdb-formattableorderbyquery-filter}"; - - /// - /// If query does not need a filter then we replace the FormatPlaceHolder with "true", since - /// "SELECT * FROM c WHERE blah and true" is the same as "SELECT * FROM c where blah" - /// - private const string TrueFilter = "true"; - - private static readonly QueryState InitializingQueryState = new QueryState(CosmosString.Create("ORDER BY NOT INITIALIZED YET!")); - private static readonly IReadOnlyList EmptyPage = new List(); - - private readonly IDocumentContainer documentContainer; - private readonly IReadOnlyList sortOrders; - private readonly PriorityQueue enumerators; - private readonly Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens; - private readonly QueryPaginationOptions queryPaginationOptions; - private readonly int maxConcurrency; - - private CancellationToken cancellationToken; - private QueryState state; - private bool returnedFinalPage; - - private static class Expressions - { - public const string LessThan = "<"; - public const string LessThanOrEqualTo = "<="; - public const string EqualTo = "="; - public const string GreaterThan = ">"; - public const string GreaterThanOrEqualTo = ">="; - public const string True = "true"; - public const string False = "false"; - } - - private OrderByCrossPartitionQueryPipelineStage( - IDocumentContainer documentContainer, - IReadOnlyList sortOrders, - QueryPaginationOptions queryPaginationOptions, - int maxConcurrency, - IEnumerable<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)> uninitializedEnumeratorsAndTokens, - QueryState state, - CancellationToken cancellationToken) - { - this.documentContainer = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer)); - this.sortOrders = sortOrders ?? throw new ArgumentNullException(nameof(sortOrders)); - this.enumerators = new PriorityQueue(new OrderByEnumeratorComparer(this.sortOrders)); - this.queryPaginationOptions = queryPaginationOptions ?? QueryPaginationOptions.Default; - this.maxConcurrency = maxConcurrency < 0 ? throw new ArgumentOutOfRangeException($"{nameof(maxConcurrency)} must be a non negative number.") : maxConcurrency; - this.uninitializedEnumeratorsAndTokens = new Queue<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)>(uninitializedEnumeratorsAndTokens ?? throw new ArgumentNullException(nameof(uninitializedEnumeratorsAndTokens))); - this.state = state ?? InitializingQueryState; - this.cancellationToken = cancellationToken; - } - - public TryCatch Current { get; private set; } - - public ValueTask DisposeAsync() => default; - - private async ValueTask MoveNextAsync_Initialize_FromBeginningAsync( - OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, - ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - if (uninitializedEnumerator == null) - { - throw new ArgumentNullException(nameof(uninitializedEnumerator)); - } - - // We need to prime the page - if (!await uninitializedEnumerator.MoveNextAsync(trace)) - { - // No more documents, so just return an empty page - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: 0, - activityId: string.Empty, - responseLengthInBytes: 0, - cosmosQueryExecutionInfo: default, - distributionPlanSpec: default, - disallowContinuationTokenMessage: default, - additionalHeaders: default, - state: this.state)); - return true; - } - - if (uninitializedEnumerator.Current.Failed) - { - if (IsSplitException(uninitializedEnumerator.Current.Exception)) - { - return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token: null, trace); - } - - this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, token: null)); - this.Current = TryCatch.FromException(uninitializedEnumerator.Current.Exception); - } - else - { - QueryPage page = uninitializedEnumerator.Current.Result.Page; - - if (!uninitializedEnumerator.Current.Result.Enumerator.MoveNext()) - { - // Page was empty - if (uninitializedEnumerator.FeedRangeState.State != null) - { - this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, token: null)); - } - - if ((this.uninitializedEnumeratorsAndTokens.Count == 0) && (this.enumerators.Count == 0)) - { - // Query did not match any results. We need to emit a fake empty page with null continuation - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: page.RequestCharge, - activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, - responseLengthInBytes: page.ResponseLengthInBytes, - cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, - distributionPlanSpec: default, - disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, - additionalHeaders: page.AdditionalHeaders, - state: null)); - this.returnedFinalPage = true; - return true; - } - } - else - { - this.enumerators.Enqueue(uninitializedEnumerator); - } - - // Just return an empty page with the stats - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: page.RequestCharge, - activityId: page.ActivityId, - responseLengthInBytes: page.ResponseLengthInBytes, - cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, - distributionPlanSpec: default, - disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, - additionalHeaders: page.AdditionalHeaders, - state: this.state)); - } - - return true; - } - - private async ValueTask MoveNextAsync_Initialize_FilterAsync( - OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, - OrderByContinuationToken token, - ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - if (uninitializedEnumerator == null) - { - throw new ArgumentNullException(nameof(uninitializedEnumerator)); - } - - if (token == null) - { - throw new ArgumentNullException(nameof(token)); - } - - TryCatch<(bool, int, TryCatch)> filterMonad = await FilterNextAsync( - uninitializedEnumerator, - this.sortOrders, - token, - trace, - cancellationToken: default); - - if (filterMonad.Failed) - { - if (IsSplitException(filterMonad.Exception)) - { - return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token, trace); - } - - this.Current = TryCatch.FromException(filterMonad.Exception); - return true; - } - - (bool doneFiltering, int itemsLeftToSkip, TryCatch monadicQueryByPage) = filterMonad.Result; - QueryPage page = uninitializedEnumerator.Current.Result.Page; - if (doneFiltering) - { - if (uninitializedEnumerator.Current.Result.Enumerator.Current != null) - { - this.enumerators.Enqueue(uninitializedEnumerator); - } - else if ((this.uninitializedEnumeratorsAndTokens.Count == 0) && (this.enumerators.Count == 0)) - { - // Query did not match any results. - // We need to emit a fake empty page with null continuation - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: page.RequestCharge, - activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, - responseLengthInBytes: page.ResponseLengthInBytes, - cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, - distributionPlanSpec: default, - disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, - additionalHeaders: page.AdditionalHeaders, - state: null)); - this.returnedFinalPage = true; - return true; - } - } - else - { - if (monadicQueryByPage.Failed) - { - if (IsSplitException(filterMonad.Exception)) - { - return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token, trace); - } - } - - if (uninitializedEnumerator.FeedRangeState.State != default) - { - // We need to update the token - OrderByContinuationToken modifiedToken = new OrderByContinuationToken( - new ParallelContinuationToken( - ((CosmosString)uninitializedEnumerator.FeedRangeState.State.Value).Value, - ((FeedRangeEpk)uninitializedEnumerator.FeedRangeState.FeedRange).Range), - token.OrderByItems, - token.ResumeValues, - token.Rid, - itemsLeftToSkip, - token.Filter); - this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, modifiedToken)); - CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(modifiedToken); - CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); - this.state = new QueryState(continuationTokenList); - } - } - - // Just return an empty page with the stats - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: page.RequestCharge, - activityId: page.ActivityId, - responseLengthInBytes: page.ResponseLengthInBytes, - cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, - distributionPlanSpec: default, - disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, - additionalHeaders: page.AdditionalHeaders, - state: InitializingQueryState)); - - return true; - } - - private async ValueTask MoveNextAsync_InitializeAsync_HandleSplitAsync( - OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, - OrderByContinuationToken token, - ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - IReadOnlyList childRanges = await this.documentContainer.GetChildRangeAsync( - uninitializedEnumerator.FeedRangeState.FeedRange, - trace, - this.cancellationToken); - - if (childRanges.Count <= 1) - { - // We optimistically assumed that the cache is not stale. - // In the event that it is (where we only get back one child / the partition that we think got split) - // Then we need to refresh the cache - await this.documentContainer.RefreshProviderAsync(trace, this.cancellationToken); - childRanges = await this.documentContainer.GetChildRangeAsync( - uninitializedEnumerator.FeedRangeState.FeedRange, - trace, - this.cancellationToken); - } - - if (childRanges.Count < 1) - { - string errorMessage = "SDK invariant violated 82086B2D: Must have at least one EPK range in a cross partition enumerator"; - throw Resource.CosmosExceptions.CosmosExceptionFactory.CreateInternalServerErrorException( - message: errorMessage, - headers: null, - stackTrace: null, - trace: trace, - error: new Microsoft.Azure.Documents.Error { Code = "SDK_invariant_violated_82086B2D", Message = errorMessage }); - } - - if (childRanges.Count == 1) - { - // On a merge, the 410/1002 results in a single parent - // We maintain the current enumerator's range and let the RequestInvokerHandler logic kick in - OrderByQueryPartitionRangePageAsyncEnumerator childPaginator = new OrderByQueryPartitionRangePageAsyncEnumerator( - this.documentContainer, - uninitializedEnumerator.SqlQuerySpec, - new FeedRangeState(uninitializedEnumerator.FeedRangeState.FeedRange, uninitializedEnumerator.StartOfPageState), - partitionKey: null, - uninitializedEnumerator.QueryPaginationOptions, - uninitializedEnumerator.Filter, - this.cancellationToken); - this.uninitializedEnumeratorsAndTokens.Enqueue((childPaginator, token)); - } - else - { - // Split - foreach (FeedRangeInternal childRange in childRanges) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - OrderByQueryPartitionRangePageAsyncEnumerator childPaginator = new OrderByQueryPartitionRangePageAsyncEnumerator( - this.documentContainer, - uninitializedEnumerator.SqlQuerySpec, - new FeedRangeState(childRange, uninitializedEnumerator.StartOfPageState), - partitionKey: null, - uninitializedEnumerator.QueryPaginationOptions, - uninitializedEnumerator.Filter, - this.cancellationToken); - this.uninitializedEnumeratorsAndTokens.Enqueue((childPaginator, token)); - } - } - - // Recursively retry - return await this.MoveNextAsync(trace); - } - - private async ValueTask MoveNextAsync_InitializeAsync(ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - await ParallelPrefetch.PrefetchInParallelAsync( - this.uninitializedEnumeratorsAndTokens.Select(value => value.enumerator), - this.maxConcurrency, - trace, - this.cancellationToken); - (OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, OrderByContinuationToken token) = this.uninitializedEnumeratorsAndTokens.Dequeue(); - bool movedNext = token is null - ? await this.MoveNextAsync_Initialize_FromBeginningAsync(uninitializedEnumerator, trace) - : await this.MoveNextAsync_Initialize_FilterAsync(uninitializedEnumerator, token, trace); - return movedNext; - } - - private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - - OrderByQueryPartitionRangePageAsyncEnumerator currentEnumerator = default; - OrderByQueryResult orderByQueryResult = default; - - // Try to form a page with as many items in the sorted order without having to do async work. - List results = new List(); - while (results.Count < this.queryPaginationOptions.PageSizeLimit.GetValueOrDefault(int.MaxValue)) - { - currentEnumerator = this.enumerators.Dequeue(); - orderByQueryResult = new OrderByQueryResult(currentEnumerator.Current.Result.Enumerator.Current); - results.Add(orderByQueryResult); - - if (!currentEnumerator.Current.Result.Enumerator.MoveNext()) - { - // The order by page ran out of results - if (currentEnumerator.FeedRangeState.State != null) - { - // If the continuation isn't null - // then mark the enumerator as unitialized and it will get requeueed on the next iteration with a fresh page. - this.uninitializedEnumeratorsAndTokens.Enqueue((currentEnumerator, (OrderByContinuationToken)null)); - - // Use the token for the next page, since we fully drained the enumerator. - OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( - new ParallelContinuationToken( - token: ((CosmosString)currentEnumerator.FeedRangeState.State.Value).Value, - range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), - orderByQueryResult, - skipCount: 0, - filter: currentEnumerator.Filter); - - CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); - CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); - - this.state = new QueryState(continuationTokenList); - - // Return a page of results - // No stats to report, since we already reported it when we moved to this page. - this.Current = TryCatch.FromResult( - new QueryPage( - documents: results.Select(result => result.Payload).ToList(), - requestCharge: 0, - activityId: default, - responseLengthInBytes: 0, - cosmosQueryExecutionInfo: default, - distributionPlanSpec: default, - disallowContinuationTokenMessage: default, - additionalHeaders: currentEnumerator.Current.Result.Page.AdditionalHeaders, - state: this.state)); - return new ValueTask(true); - } - - // Todo: we can optimize this by having a special "Done" continuation token - // so we don't grab a full page and filter it through - // but this would break older clients, so wait for a compute only fork. - - break; - } - - this.enumerators.Enqueue(currentEnumerator); - } - - // It is possible that we emit multiple documents with the same rid due to JOIN queries. - // This means it is not enough to serialize the rid that we left on to resume the query. - // We need to also serialize the number of documents with that rid, so we can skip it when resuming - int skipCount = results.Where(result => string.Equals(result.Rid, orderByQueryResult.Rid)).Count(); - - // Create the continuation token. - CosmosElement state; - if ((this.enumerators.Count == 0) && (this.uninitializedEnumeratorsAndTokens.Count == 0)) - { - state = null; - } - else - { - OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( - new ParallelContinuationToken( - token: currentEnumerator.StartOfPageState != null ? ((CosmosString)currentEnumerator.StartOfPageState.Value).Value : null, - range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), - orderByQueryResult, - skipCount, - currentEnumerator.Filter); - - CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); - CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); - - state = continuationTokenList; - } - - this.state = state != null ? new QueryState(state) : null; - - // Return a page of results - // No stats to report, since we already reported it when we moved to this page. - this.Current = TryCatch.FromResult( - new QueryPage( - documents: results.Select(result => result.Payload).ToList(), - requestCharge: 0, - activityId: default, - responseLengthInBytes: 0, - cosmosQueryExecutionInfo: default, - distributionPlanSpec: default, - disallowContinuationTokenMessage: default, - additionalHeaders: currentEnumerator?.Current.Result.Page.AdditionalHeaders, - state: this.state)); - - if (state == null) - { - this.returnedFinalPage = true; - } - - return new ValueTask(true); - } - - //// In order to maintain the continuation token for the user we must drain with a few constraints - //// 1) We always drain from the partition, which has the highest priority item first - //// 2) If multiple partitions have the same priority item then we drain from the left most first - //// otherwise we would need to keep track of how many of each item we drained from each partition - //// (just like parallel queries). - //// Visually that look the following case where we have three partitions that are numbered and store letters. - //// For teaching purposes I have made each item a tuple of the following form: - //// - //// So that duplicates across partitions are distinct, but duplicates within partitions are indistinguishable. - //// |-------| |-------| |-------| - //// | | | | | | - //// | | | | | | - //// | | | | | | - //// | | | | | | - //// | | | | | | - //// | | | | | | - //// | | | | | | - //// |-------| |-------| |-------| - //// Now the correct drain order in this case is: - //// ,,,,,,,,,,, - //// ,,,,,,,,, - //// In more mathematical terms - //// 1) always comes before where x < z - //// 2) always come before where j < k - public ValueTask MoveNextAsync(ITrace trace) - { - this.cancellationToken.ThrowIfCancellationRequested(); - - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - - if (this.uninitializedEnumeratorsAndTokens.Count != 0) - { - return this.MoveNextAsync_InitializeAsync(trace); - } - - if (this.enumerators.Count == 0) - { - if (!this.returnedFinalPage) - { - // return a empty page with null continuation token - this.Current = TryCatch.FromResult( - new QueryPage( - documents: EmptyPage, - requestCharge: 0, - activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: 0, - cosmosQueryExecutionInfo: default, - distributionPlanSpec: default, - disallowContinuationTokenMessage: default, - additionalHeaders: default, - state: null)); - this.returnedFinalPage = true; - return new ValueTask(true); - } - - // Finished draining. - return new ValueTask(false); - } - - return this.MoveNextAsync_DrainPageAsync(trace); - } - - public static TryCatch MonadicCreate( - IDocumentContainer documentContainer, - SqlQuerySpec sqlQuerySpec, - IReadOnlyList targetRanges, - Cosmos.PartitionKey? partitionKey, - IReadOnlyList orderByColumns, - QueryPaginationOptions queryPaginationOptions, - int maxConcurrency, - CosmosElement continuationToken, - CancellationToken cancellationToken) - { - // TODO (brchon): For now we are not honoring non deterministic ORDER BY queries, since there is a bug in the continuation logic. - // We can turn it back on once the bug is fixed. - // This shouldn't hurt any query results. - - if (documentContainer == null) - { - throw new ArgumentNullException(nameof(documentContainer)); - } - - if (sqlQuerySpec == null) - { - throw new ArgumentNullException(nameof(sqlQuerySpec)); - } - - if (targetRanges == null) - { - throw new ArgumentNullException(nameof(targetRanges)); - } - - if (targetRanges.Count == 0) - { - throw new ArgumentException($"{nameof(targetRanges)} must not be empty."); - } - - if (orderByColumns == null) - { - throw new ArgumentNullException(nameof(orderByColumns)); - } - - if (orderByColumns.Count == 0) - { - throw new ArgumentException($"{nameof(orderByColumns)} must not be empty."); - } - - List<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)> enumeratorsAndTokens; - if (continuationToken == null) - { - // Start off all the partition key ranges with null continuation - SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), - sqlQuerySpec.Parameters); - - enumeratorsAndTokens = targetRanges - .Select(range => (new OrderByQueryPartitionRangePageAsyncEnumerator( - documentContainer, - rewrittenQueryForOrderBy, - new FeedRangeState(range, state: default), - partitionKey, - queryPaginationOptions, - TrueFilter, - cancellationToken), (OrderByContinuationToken)null)) - .ToList(); - } - else - { - TryCatch> monadicGetOrderByContinuationTokenMapping = MonadicGetOrderByContinuationTokenMapping( - targetRanges, - continuationToken, - orderByColumns.Count); - if (monadicGetOrderByContinuationTokenMapping.Failed) - { - return TryCatch.FromException(monadicGetOrderByContinuationTokenMapping.Exception); - } - - PartitionMapper.PartitionMapping partitionMapping = monadicGetOrderByContinuationTokenMapping.Result; - - OrderByContinuationToken targetContinuationToken = partitionMapping.TargetMapping.Values.First(); - - int orderByResumeValueCount = 0; - IReadOnlyList resumeValues; - IReadOnlyList orderByItems; - if (targetContinuationToken.ResumeValues != null) - { - // Use SqlQueryResumeValue for continuation if it is present. - resumeValues = targetContinuationToken.ResumeValues; - orderByItems = null; - orderByResumeValueCount = resumeValues.Count; - } - else - { - // If continuation token has only OrderByItems, check if it can be converted to SqlQueryResumeValue. This will - // help avoid re-writing the query. Conversion will work as long as the order by item type is a supported type. - orderByResumeValueCount = targetContinuationToken.OrderByItems.Count; - - if (ContainsSupportedResumeTypes(targetContinuationToken.OrderByItems)) - { - // Convert the order by items to SqlQueryResumeValue - List generatedResumeValues = new List(targetContinuationToken.OrderByItems.Count); - //foreach (CosmosElement orderByItem in orderByItems) - foreach (OrderByItem orderByItem in targetContinuationToken.OrderByItems) - { - generatedResumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); - } - - resumeValues = generatedResumeValues; - orderByItems = null; - } - else - { - orderByItems = targetContinuationToken.OrderByItems.Select(x => x.Item).ToList(); - resumeValues = null; - } - } - - if (orderByResumeValueCount != orderByColumns.Count) - { - return TryCatch.FromException( - new MalformedContinuationTokenException( - $"Order By Items from continuation token did not match the query text. " + - $"Order by item count: {orderByResumeValueCount} did not match column count {orderByColumns.Count()}. " + - $"Continuation token: {targetContinuationToken}")); - } - - enumeratorsAndTokens = new List<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)>(); - if (resumeValues != null) - { - // Continuation contains resume values, so update SqlQuerySpec to include SqlQueryResumeFilter which - // will specify the resume point to the backend. This avoid having to re-write the query. - - // Process partitions left of Target. The resume values in these partition have - // already been processed so exclude flag is set to true. - SqlQuerySpec leftQuerySpec = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), - sqlQuerySpec.Parameters, - new SqlQueryResumeFilter(resumeValues, null, true)); - - foreach (KeyValuePair kvp in partitionMapping.MappingLeftOfTarget) - { - FeedRangeEpk range = kvp.Key; - OrderByContinuationToken token = kvp.Value; - OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( - documentContainer, - leftQuerySpec, - new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), - partitionKey, - queryPaginationOptions, - filter: null, - cancellationToken); - - enumeratorsAndTokens.Add((remoteEnumerator, token)); - } - - // Process Target Partitions which is the last partition from which data has been returned. - // For this partition the Rid value needs to be set if present. Exclude flag is not set as the document - // matching the Rid will be skipped in SDK based on SkipCount value. - // Backend requests can contains both SqlQueryResumeFilter and ContinuationToken and the backend will pick - // the resume point that is bigger i.e. most restrictive - foreach (KeyValuePair kvp in partitionMapping.TargetMapping) - { - FeedRangeEpk range = kvp.Key; - OrderByContinuationToken token = kvp.Value; - - SqlQuerySpec targetQuerySpec = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), - sqlQuerySpec.Parameters, - new SqlQueryResumeFilter(resumeValues, token?.Rid, false)); - - OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( - documentContainer, - targetQuerySpec, - new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), - partitionKey, - queryPaginationOptions, - filter: null, - cancellationToken); - - enumeratorsAndTokens.Add((remoteEnumerator, token)); - } - - // Process partitions right of target. The Resume value in these partitions have not been processed so the exclude value is set to false. - SqlQuerySpec rightQuerySpec = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), - sqlQuerySpec.Parameters, - new SqlQueryResumeFilter(resumeValues, null, false)); - - foreach (KeyValuePair kvp in partitionMapping.MappingRightOfTarget) - { - FeedRangeEpk range = kvp.Key; - OrderByContinuationToken token = kvp.Value; - OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( - documentContainer, - rightQuerySpec, - new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), - partitionKey, - queryPaginationOptions, - filter: null, - cancellationToken); - - enumeratorsAndTokens.Add((remoteEnumerator, token)); - } - } - else - { - // If continuation token doesn't have resume values or if order by items cannot be converted to resume values then - // rewrite the query filter to get the correct resume point - ReadOnlyMemory<(OrderByColumn, CosmosElement)> columnAndItems = orderByColumns.Zip(orderByItems, (column, item) => (column, item)).ToArray(); - - // For ascending order-by, left of target partition has filter expression > value, - // right of target partition has filter expression >= value, - // and target partition takes the previous filter from continuation (or true if no continuation) - (string leftFilter, string targetFilter, string rightFilter) = OrderByCrossPartitionQueryPipelineStage.GetFormattedFilters(columnAndItems); - List<(IReadOnlyDictionary, string)> tokenMappingAndFilters = new List<(IReadOnlyDictionary, string)>() - { - { (partitionMapping.MappingLeftOfTarget, leftFilter) }, - { (partitionMapping.TargetMapping, targetFilter) }, - { (partitionMapping.MappingRightOfTarget, rightFilter) }, - }; - - foreach ((IReadOnlyDictionary tokenMapping, string filter) in tokenMappingAndFilters) - { - SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( - sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: filter), - sqlQuerySpec.Parameters); - - foreach (KeyValuePair kvp in tokenMapping) - { - FeedRangeEpk range = kvp.Key; - OrderByContinuationToken token = kvp.Value; - OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = new OrderByQueryPartitionRangePageAsyncEnumerator( - documentContainer, - rewrittenQueryForOrderBy, - new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), - partitionKey, - queryPaginationOptions, - filter, - cancellationToken); - - enumeratorsAndTokens.Add((remoteEnumerator, token)); - } - } - } - } - - OrderByCrossPartitionQueryPipelineStage stage = new OrderByCrossPartitionQueryPipelineStage( - documentContainer, - orderByColumns.Select(column => column.SortOrder).ToList(), - queryPaginationOptions, - maxConcurrency, - enumeratorsAndTokens, - continuationToken == null ? null : new QueryState(continuationToken), - cancellationToken); - return TryCatch.FromResult(stage); - } - - private static TryCatch> MonadicGetOrderByContinuationTokenMapping( - IReadOnlyList partitionKeyRanges, - CosmosElement continuationToken, - int numOrderByItems) - { - if (partitionKeyRanges == null) - { - throw new ArgumentOutOfRangeException(nameof(partitionKeyRanges)); - } - - if (numOrderByItems < 0) - { - throw new ArgumentOutOfRangeException(nameof(numOrderByItems)); - } - - if (continuationToken == null) - { - throw new ArgumentNullException(nameof(continuationToken)); - } - - TryCatch> monadicExtractContinuationTokens = MonadicExtractOrderByTokens(continuationToken, numOrderByItems); - if (monadicExtractContinuationTokens.Failed) - { - return TryCatch>.FromException(monadicExtractContinuationTokens.Exception); - } - - return PartitionMapper.MonadicGetPartitionMapping( - partitionKeyRanges, - monadicExtractContinuationTokens.Result); - } - - private static TryCatch> MonadicExtractOrderByTokens( - CosmosElement continuationToken, - int numOrderByColumns) - { - if (continuationToken == null) - { - return TryCatch>.FromResult(default); - } - - if (!(continuationToken is CosmosArray cosmosArray)) - { - return TryCatch>.FromException( - new MalformedContinuationTokenException( - $"Order by continuation token must be an array: {continuationToken}.")); - } - - if (cosmosArray.Count == 0) - { - return TryCatch>.FromException( - new MalformedContinuationTokenException( - $"Order by continuation token cannot be empty: {continuationToken}.")); - } - - List orderByContinuationTokens = new List(); - foreach (CosmosElement arrayItem in cosmosArray) - { - TryCatch tryCreateOrderByContinuationToken = OrderByContinuationToken.TryCreateFromCosmosElement(arrayItem); - if (!tryCreateOrderByContinuationToken.Succeeded) - { - return TryCatch>.FromException(tryCreateOrderByContinuationToken.Exception); - } - - orderByContinuationTokens.Add(tryCreateOrderByContinuationToken.Result); - } - - foreach (OrderByContinuationToken suppliedOrderByContinuationToken in orderByContinuationTokens) - { - int orderByCount = GetOrderByItemCount(suppliedOrderByContinuationToken); - if (orderByCount != numOrderByColumns) - { - return TryCatch>.FromException( - new MalformedContinuationTokenException( - $"Invalid order-by items in continuation token {continuationToken} for OrderBy~Context.")); - } - } - - return TryCatch>.FromResult(orderByContinuationTokens); - } - - private static int GetOrderByItemCount(OrderByContinuationToken orderByContinuationToken) - { - return orderByContinuationToken.ResumeValues != null ? - orderByContinuationToken.ResumeValues.Count : orderByContinuationToken.OrderByItems.Count; - } - - private static void AppendToBuilders((StringBuilder leftFilter, StringBuilder targetFilter, StringBuilder rightFilter) builders, object str) - { - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, str, str, str); - } - - private static void AppendToBuilders((StringBuilder leftFilter, StringBuilder targetFilter, StringBuilder rightFilter) builders, object left, object target, object right) - { - builders.leftFilter.Append(left); - builders.targetFilter.Append(target); - builders.rightFilter.Append(right); - } - - private static (string leftFilter, string targetFilter, string rightFilter) GetFormattedFilters( - ReadOnlyMemory<(OrderByColumn orderByColumn, CosmosElement orderByItem)> columnAndItems) - { - // When we run cross partition queries, - // we only serialize the continuation token for the partition that we left off on. - // The only problem is that when we resume the order by query, - // we don't have continuation tokens for all other partition. - // The saving grace is that the data has a composite sort order(query sort order, partition key range id) - // so we can generate range filters which in turn the backend will turn into rid based continuation tokens, - // which is enough to get the streams of data flowing from all partitions. - // The details of how this is done is described below: - int numOrderByItems = columnAndItems.Length; - bool isSingleOrderBy = numOrderByItems == 1; - StringBuilder left = new StringBuilder(); - StringBuilder target = new StringBuilder(); - StringBuilder right = new StringBuilder(); - - (StringBuilder, StringBuilder, StringBuilder) builders = (left, target, right); - - if (isSingleOrderBy) - { - //For a single order by query we resume the continuations in this manner - // Suppose the query is SELECT* FROM c ORDER BY c.string ASC - // And we left off on partition N with the value "B" - // Then - // All the partitions to the left will have finished reading "B" - // Partition N is still reading "B" - // All the partitions to the right have let to read a "B - // Therefore the filters should be - // > "B" , >= "B", and >= "B" respectively - // Repeat the same logic for DESC and you will get - // < "B", <= "B", and <= "B" respectively - // The general rule becomes - // For ASC - // > for partitions to the left - // >= for the partition we left off on - // >= for the partitions to the right - // For DESC - // < for partitions to the left - // <= for the partition we left off on - // <= for the partitions to the right - (OrderByColumn orderByColumn, CosmosElement orderByItem) = columnAndItems.Span[0]; - (string expression, SortOrder sortOrder) = (orderByColumn.Expression, orderByColumn.SortOrder); - - AppendToBuilders(builders, "( "); - - // We need to add the filter for within the same type. - if (orderByItem is not CosmosUndefined) - { - StringBuilder sb = new StringBuilder(); - CosmosElementToQueryLiteral cosmosElementToQueryLiteral = new CosmosElementToQueryLiteral(sb); - orderByItem.Accept(cosmosElementToQueryLiteral); - - string orderByItemToString = sb.ToString(); - - left.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThan : Expressions.GreaterThan)} {orderByItemToString}"); - target.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThanOrEqualTo : Expressions.GreaterThanOrEqualTo)} {orderByItemToString}"); - right.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThanOrEqualTo : Expressions.GreaterThanOrEqualTo)} {orderByItemToString}"); - } - else - { - // User is ordering by undefined, so we need to avoid a null reference exception. - - // What we really want is to support expression > undefined, - // but the engine evaluates to undefined instead of true or false, - // so we work around this by using the IS_DEFINED() system function. - - ComparisionWithUndefinedFilters filters = new ComparisionWithUndefinedFilters(expression); - left.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThan : filters.GreaterThan)}"); - target.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThanOrEqualTo : filters.GreaterThanOrEqualTo)}"); - right.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThanOrEqualTo : filters.GreaterThanOrEqualTo)}"); - } - - // Now we need to include all the types that match the sort order. - ReadOnlyMemory isDefinedFunctions = orderByItem.Accept(CosmosElementToIsSystemFunctionsVisitor.Singleton, sortOrder == SortOrder.Ascending); - foreach (string isDefinedFunction in isDefinedFunctions.Span) - { - AppendToBuilders(builders, " OR "); - AppendToBuilders(builders, $"{isDefinedFunction}({expression})"); - } - - AppendToBuilders(builders, " )"); - } - else - { - //For a multi order by query - // Suppose the query is SELECT* FROM c ORDER BY c.string ASC, c.number ASC - // And we left off on partition N with the value("A", 1) - // Then - // All the partitions to the left will have finished reading("A", 1) - // Partition N is still reading("A", 1) - // All the partitions to the right have let to read a "(A", 1) - // The filters are harder to derive since their are multiple columns - // But the problem reduces to "How do you know one document comes after another in a multi order by query" - // The answer is to just look at it one column at a time. - // For this particular scenario: - // If a first column is greater ex. ("B", blah), then the document comes later in the sort order - // Therefore we want all documents where the first column is greater than "A" which means > "A" - // Or if the first column is a tie, then you look at the second column ex. ("A", blah). - // Therefore we also want all documents where the first column was a tie but the second column is greater which means = "A" AND > 1 - // Therefore the filters should be - // (> "A") OR (= "A" AND > 1), (> "A") OR (= "A" AND >= 1), (> "A") OR (= "A" AND >= 1) - // Notice that if we repeated the same logic we for single order by we would have gotten - // > "A" AND > 1, >= "A" AND >= 1, >= "A" AND >= 1 - // which is wrong since we missed some documents - // Repeat the same logic for ASC, DESC - // (> "A") OR (= "A" AND < 1), (> "A") OR (= "A" AND <= 1), (> "A") OR (= "A" AND <= 1) - // Again for DESC, ASC - // (< "A") OR (= "A" AND > 1), (< "A") OR (= "A" AND >= 1), (< "A") OR (= "A" AND >= 1) - // And again for DESC DESC - // (< "A") OR (= "A" AND < 1), (< "A") OR (= "A" AND <= 1), (< "A") OR (= "A" AND <= 1) - // The general we look at all prefixes of the order by columns to look for tie breakers. - // Except for the full prefix whose last column follows the rules for single item order by - // And then you just OR all the possibilities together - for (int prefixLength = 1; prefixLength <= numOrderByItems; prefixLength++) - { - ReadOnlySpan<(OrderByColumn orderByColumn, CosmosElement orderByItem)> columnAndItemPrefix = columnAndItems.Span.Slice(start: 0, length: prefixLength); - - bool lastPrefix = prefixLength == numOrderByItems; - - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, "("); - - for (int index = 0; index < prefixLength; index++) - { - string expression = columnAndItemPrefix[index].orderByColumn.Expression; - SortOrder sortOrder = columnAndItemPrefix[index].orderByColumn.SortOrder; - CosmosElement orderByItem = columnAndItemPrefix[index].orderByItem; - bool lastItem = index == prefixLength - 1; - - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, "("); - - bool wasInequality; - // We need to add the filter for within the same type. - if (orderByItem is CosmosUndefined) - { - ComparisionWithUndefinedFilters filters = new ComparisionWithUndefinedFilters(expression); - - // Refer to the logic from single order by for how we are handling order by undefined - if (lastItem) - { - if (lastPrefix) - { - if (sortOrder == SortOrder.Descending) - { - // <, <=, <= - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.LessThan, filters.LessThanOrEqualTo, filters.LessThanOrEqualTo); - } - else - { - // >, >=, >= - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.GreaterThan, filters.GreaterThanOrEqualTo, filters.GreaterThanOrEqualTo); - } - } - else - { - if (sortOrder == SortOrder.Descending) - { - // <, <, < - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.LessThan, filters.LessThan, filters.LessThan); - } - else - { - // >, >, > - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.GreaterThan, filters.GreaterThan, filters.GreaterThan); - } - } - - wasInequality = true; - } - else - { - // =, =, = - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.EqualTo); - wasInequality = false; - } - } - else - { - // Append Expression - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, expression); - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, " "); - - // Append Binary Operator - if (lastItem) - { - string inequality = sortOrder == SortOrder.Descending ? Expressions.LessThan : Expressions.GreaterThan; - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, inequality); - if (lastPrefix) - { - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, string.Empty, Expressions.EqualTo, Expressions.EqualTo); - } - - wasInequality = true; - } - else - { - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, Expressions.EqualTo); - wasInequality = false; - } - - // Append OrderBy Item - StringBuilder sb = new StringBuilder(); - CosmosElementToQueryLiteral cosmosElementToQueryLiteral = new CosmosElementToQueryLiteral(sb); - orderByItem.Accept(cosmosElementToQueryLiteral); - string orderByItemToString = sb.ToString(); - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, " "); - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, orderByItemToString); - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, " "); - } - - if (wasInequality) - { - // Now we need to include all the types that match the sort order. - ReadOnlyMemory isDefinedFunctions = orderByItem.Accept(CosmosElementToIsSystemFunctionsVisitor.Singleton, sortOrder == SortOrder.Ascending); - foreach (string isDefinedFunction in isDefinedFunctions.Span) - { - AppendToBuilders(builders, " OR "); - AppendToBuilders(builders, $"{isDefinedFunction}({expression}) "); - } - } - - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, ")"); - - if (!lastItem) - { - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, " AND "); - } - } - - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, ")"); - if (!lastPrefix) - { - OrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, " OR "); - } - } - } - - return (left.ToString(), target.ToString(), right.ToString()); - } - - private static OrderByContinuationToken CreateOrderByContinuationToken( - ParallelContinuationToken parallelToken, - OrderByQueryResult orderByQueryResult, - int skipCount, - string filter) - { - OrderByContinuationToken token; - // If order by items have c* types then it cannot be converted to resume values - if (ContainsSupportedResumeTypes(orderByQueryResult.OrderByItems)) - { - List resumeValues = new List(orderByQueryResult.OrderByItems.Count); - foreach (OrderByItem orderByItem in orderByQueryResult.OrderByItems) - { - resumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); - } - - token = new OrderByContinuationToken( - parallelToken, - orderByItems: null, - resumeValues, - orderByQueryResult.Rid, - skipCount: skipCount, - filter: filter); - } - else - { - token = new OrderByContinuationToken( - parallelToken, - orderByQueryResult.OrderByItems, - resumeValues: null, - orderByQueryResult.Rid, - skipCount: skipCount, - filter: filter); - } - - return token; - } - - // Helper method to check that resume values are of type that is supported by SqlQueryResumeValue - private static bool ContainsSupportedResumeTypes(IReadOnlyList orderByItems) - { - foreach (OrderByItem orderByItem in orderByItems) - { - if (!orderByItem.Item.Accept(SupportedResumeTypeVisitor.Singleton)) - { - return false; - } - } - - return true; - } - - private static async Task monadicQueryByPage)>> FilterNextAsync( - OrderByQueryPartitionRangePageAsyncEnumerator enumerator, - IReadOnlyList sortOrders, - OrderByContinuationToken continuationToken, - ITrace trace, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - // When we resume a query on a partition there is a possibility that we only read a partial page from the backend - // meaning that will we repeat some documents if we didn't do anything about it. - // The solution is to filter all the documents that come before in the sort order, since we have already emitted them to the client. - // The key is to seek until we get an order by value that matches the order by value we left off on. - // Once we do that we need to seek to the correct _rid within the term, - // since there might be many documents with the same order by value we left off on. - // Finally we need to skip some duplicate _rids, since JOINs emit multiples documents with the same rid and we read a partial page. - // You can also think about this as a seek on a composite index where the columns are [sort_order, rid, skip_count] - - int itemsToSkip = continuationToken.SkipCount; - if (!ResourceId.TryParse(continuationToken.Rid, out ResourceId continuationRid)) - { - return TryCatch<(bool, int, TryCatch)>.FromException( - new MalformedContinuationTokenException( - $"Invalid Rid in the continuation token {continuationToken.ParallelContinuationToken.Token} for OrderBy~Context.")); - } - - if (!await enumerator.MoveNextAsync(trace)) - { - return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); - } - - TryCatch monadicOrderByQueryPage = enumerator.Current; - if (monadicOrderByQueryPage.Failed) - { - return TryCatch<(bool, int, TryCatch)>.FromException(monadicOrderByQueryPage.Exception); - } - - OrderByQueryPage orderByQueryPage = monadicOrderByQueryPage.Result; - IEnumerator documents = orderByQueryPage.Enumerator; - - while (documents.MoveNext()) - { - int sortOrderCompare = 0; - // Filter out documents until we find something that matches the sort order. - OrderByQueryResult orderByResult = new OrderByQueryResult(documents.Current); - for (int i = 0; (i < sortOrders.Count) && (sortOrderCompare == 0); ++i) - { - sortOrderCompare = continuationToken.ResumeValues != null - ? continuationToken.ResumeValues[i].CompareTo(orderByResult.OrderByItems[i].Item) - : ItemComparer.Instance.Compare( - continuationToken.OrderByItems[i].Item, - orderByResult.OrderByItems[i].Item); - - if (sortOrderCompare != 0) - { - sortOrderCompare = sortOrders[i] == SortOrder.Ascending ? sortOrderCompare : -sortOrderCompare; - } - } - - if (sortOrderCompare < 0) - { - // We might have passed the item due to deletions and filters. - return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); - } - - if (sortOrderCompare > 0) - { - // This document does not match the sort order, so skip it. - continue; - } - - // Once the item matches the order by items from the continuation tokens - // We still need to remove all the documents that have a lower or same rid in the rid sort order. - // If there is a tie in the sort order the documents should be in _rid order in the same direction as the index (given by the backend) - ResourceId rid = ResourceId.Parse(orderByResult.Rid); - int ridOrderCompare = continuationRid.Document.CompareTo(rid.Document); - - Lazy cosmosQueryExecutionInfo = orderByQueryPage.Page.CosmosQueryExecutionInfo; - if ((cosmosQueryExecutionInfo == null) || cosmosQueryExecutionInfo.Value.ReverseRidEnabled) - { - // If reverse rid is enabled on the backend then fallback to the old way of doing it. - if (sortOrders[0] == SortOrder.Descending) - { - ridOrderCompare = -ridOrderCompare; - } - } - else - { - // Go by the whatever order the index wants - if (cosmosQueryExecutionInfo.Value.ReverseIndexScan) - { - ridOrderCompare = -ridOrderCompare; - } - } - - if (ridOrderCompare < 0) - { - // We might have passed the rid due to deletions and filters. - return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); - } - - if (ridOrderCompare > 0) - { - // This document does not match the rid order, so skip it. - continue; - } - - // At this point we need to skip due to joins - if (--itemsToSkip < 0) - { - return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); - } - } - - // If we made it here it means we failed to find the resume order by item which is possible - // if the user added documents inbetween continuations, so we need to yield and filter the next page of results also. - return TryCatch<(bool, int, TryCatch)>.FromResult((false, itemsToSkip, enumerator.Current)); - } - - private static bool IsSplitException(Exception exception) - { - while (exception.InnerException != null) - { - exception = exception.InnerException; - } - - return exception.IsPartitionSplitException(); - } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - foreach (OrderByQueryPartitionRangePageAsyncEnumerator enumerator in this.enumerators) - { - enumerator.SetCancellationToken(cancellationToken); - } - - foreach ((OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken) enumeratorAndToken in this.uninitializedEnumeratorsAndTokens) - { - enumeratorAndToken.Item1.SetCancellationToken(cancellationToken); - } - } - - private sealed class CosmosElementToIsSystemFunctionsVisitor : ICosmosElementVisitor> - { - public static readonly CosmosElementToIsSystemFunctionsVisitor Singleton = new CosmosElementToIsSystemFunctionsVisitor(); - - private static class IsSystemFunctions - { - public const string Defined = "IS_DEFINED"; - public const string Undefined = "NOT IS_DEFINED"; - public const string Null = "IS_NULL"; - public const string Boolean = "IS_BOOLEAN"; - public const string Number = "IS_NUMBER"; - public const string String = "IS_STRING"; - public const string Array = "IS_ARRAY"; - public const string Object = "IS_OBJECT"; - } - - private static readonly ReadOnlyMemory SystemFunctionSortOrder = new string[] - { - IsSystemFunctions.Undefined, - IsSystemFunctions.Null, - IsSystemFunctions.Boolean, - IsSystemFunctions.Number, - IsSystemFunctions.String, - IsSystemFunctions.Array, - IsSystemFunctions.Object, - }; - - private static readonly ReadOnlyMemory ExtendedTypesSystemFunctionSortOrder = new string[] - { - IsSystemFunctions.Undefined, - IsSystemFunctions.Defined - }; - - private static class SortOrder - { - public const int Undefined = 0; - public const int Null = 1; - public const int Boolean = 2; - public const int Number = 3; - public const int String = 4; - public const int Array = 5; - public const int Object = 6; - } - - private static class ExtendedTypesSortOrder - { - public const int Undefined = 0; - public const int Defined = 1; - } - - private CosmosElementToIsSystemFunctionsVisitor() - { - } - - public ReadOnlyMemory Visit(CosmosArray cosmosArray, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.Array, isAscending); - } - - public ReadOnlyMemory Visit(CosmosBinary cosmosBinary, bool isAscending) - { - return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending); - } - - public ReadOnlyMemory Visit(CosmosBoolean cosmosBoolean, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.Boolean, isAscending); - } - - public ReadOnlyMemory Visit(CosmosGuid cosmosGuid, bool isAscending) - { - return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending); - } - - public ReadOnlyMemory Visit(CosmosNull cosmosNull, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.Null, isAscending); - } - - public ReadOnlyMemory Visit(CosmosUndefined cosmosUndefined, bool isAscending) - { - return isAscending ? SystemFunctionSortOrder.Slice(start: 1) : ReadOnlyMemory.Empty; - } - - public ReadOnlyMemory Visit(CosmosNumber cosmosNumber, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.Number, isAscending); - } - - public ReadOnlyMemory Visit(CosmosObject cosmosObject, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.Object, isAscending); - } - - public ReadOnlyMemory Visit(CosmosString cosmosString, bool isAscending) - { - return GetIsDefinedFunctions(SortOrder.String, isAscending); - } - - private static ReadOnlyMemory GetIsDefinedFunctions(int index, bool isAscending) - { - return isAscending ? SystemFunctionSortOrder.Slice(index + 1) : SystemFunctionSortOrder.Slice(start: 0, index); - } - - private static ReadOnlyMemory GetExtendedTypesIsDefinedFunctions(int index, bool isAscending) - { - return isAscending ? - ExtendedTypesSystemFunctionSortOrder.Slice(index + 1) : - ExtendedTypesSystemFunctionSortOrder.Slice(start: 0, index); - } - } - - private readonly struct ComparisionWithUndefinedFilters - { - public ComparisionWithUndefinedFilters( - string expression) - { - this.LessThan = "false"; - this.LessThanOrEqualTo = $"NOT IS_DEFINED({expression})"; - this.EqualTo = $"NOT IS_DEFINED({expression})"; - this.GreaterThan = $"IS_DEFINED({expression})"; - this.GreaterThanOrEqualTo = "true"; - } - - public string LessThan { get; } - public string LessThanOrEqualTo { get; } - public string EqualTo { get; } - public string GreaterThan { get; } - public string GreaterThanOrEqualTo { get; } - } - - private sealed class SupportedResumeTypeVisitor : ICosmosElementVisitor - { - public static readonly SupportedResumeTypeVisitor Singleton = new SupportedResumeTypeVisitor(); - - private SupportedResumeTypeVisitor() - { - } - - public bool Visit(CosmosArray cosmosArray) - { - return true; - } - - public bool Visit(CosmosBinary cosmosBinary) - { - return false; - } - - public bool Visit(CosmosBoolean cosmosBoolean) - { - return true; - } - - public bool Visit(CosmosGuid cosmosGuid) - { - return false; - } - - public bool Visit(CosmosNull cosmosNull) - { - return true; - } - - public bool Visit(CosmosNumber cosmosNumber) - { - return cosmosNumber.Accept(SqlQueryResumeValue.SupportedResumeNumberTypeVisitor.Singleton); - } - - public bool Visit(CosmosObject cosmosObject) - { - return true; - } - - public bool Visit(CosmosString cosmosString) - { - return true; - } - - public bool Visit(CosmosUndefined cosmosUndefined) - { - return true; - } - } - } -} +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Collections; + using Microsoft.Azure.Cosmos.Query.Core.Exceptions; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Tracing; + using ResourceId = Documents.ResourceId; + + internal sealed class OrderByCrossPartitionQueryPipelineStage : IQueryPipelineStage + { + /// + /// Order by queries are rewritten to allow us to inject a filter. + /// This placeholder is so that we can just string replace it with the filter we want without having to understand the structure of the query. + /// + private const string FormatPlaceHolder = "{documentdb-formattableorderbyquery-filter}"; + + /// + /// If query does not need a filter then we replace the FormatPlaceHolder with "true", since + /// "SELECT * FROM c WHERE blah and true" is the same as "SELECT * FROM c where blah" + /// + private const string TrueFilter = "true"; + + private static readonly QueryState InitializingQueryState = new QueryState(CosmosString.Create("ORDER BY NOT INITIALIZED YET!")); + + private static readonly IReadOnlyList EmptyPage = new List(); + + private sealed class InitializationParameters + { + public IDocumentContainer DocumentContainer { get; } + + public SqlQuerySpec SqlQuerySpec { get; } + + public IReadOnlyList TargetRanges { get; } + + public Cosmos.PartitionKey? PartitionKey { get; } + + public IReadOnlyList OrderByColumns { get; } + + public QueryPaginationOptions QueryPaginationOptions { get; } + + public int MaxConcurrency { get; } + + public InitializationParameters( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + IReadOnlyList targetRanges, + PartitionKey? partitionKey, + IReadOnlyList orderByColumns, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency) + { + this.DocumentContainer = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer)); + this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); + this.TargetRanges = targetRanges ?? throw new ArgumentNullException(nameof(targetRanges)); + this.PartitionKey = partitionKey; + this.OrderByColumns = orderByColumns ?? throw new ArgumentNullException(nameof(orderByColumns)); + this.QueryPaginationOptions = queryPaginationOptions ?? throw new ArgumentNullException(nameof(queryPaginationOptions)); + this.MaxConcurrency = maxConcurrency; + } + } + + private sealed class QueryPageParameters + { + public string ActivityId { get; } + + public Lazy CosmosQueryExecutionInfo { get; } + + public DistributionPlanSpec DistributionPlanSpec { get; } + + public IReadOnlyDictionary AdditionalHeaders { get; } + + public QueryPageParameters( + string activityId, + Lazy cosmosQueryExecutionInfo, + DistributionPlanSpec distributionPlanSpec, + IReadOnlyDictionary additionalHeaders) + { + this.ActivityId = activityId ?? throw new ArgumentNullException(nameof(activityId)); + this.CosmosQueryExecutionInfo = cosmosQueryExecutionInfo; + this.DistributionPlanSpec = distributionPlanSpec; + this.AdditionalHeaders = additionalHeaders; + } + } + + private enum ExecutionState + { + Uninitialized, + Initialized + } + + private readonly InitializationParameters initializationParameters; + + private ExecutionState state; + + private Queue bufferedPages; + + private TryCatch inner; + + public TryCatch Current => this.GetCurrentPage(); + + private OrderByCrossPartitionQueryPipelineStage(InitializationParameters initializationParameters) + { + this.initializationParameters = initializationParameters ?? throw new ArgumentNullException(nameof(initializationParameters)); + this.state = ExecutionState.Uninitialized; + this.bufferedPages = new Queue(); + } + + private TryCatch GetCurrentPage() + { + if (this.state == ExecutionState.Uninitialized) + { + throw new InvalidOperationException("MoveNextAsync must be called before accessing the Current property."); + } + + if (this.bufferedPages.Count != 0) + { + return TryCatch.FromResult(this.bufferedPages.Peek()); + } + + return this.inner.Try(pipelineStage => pipelineStage.Current); + } + + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) + { + if (this.state == ExecutionState.Uninitialized) + { + // Note: when we set the state to initialized here, we no longer allowing a retry for these failures + // To allow retries, we must not set the state to initialized until construction of the inner pipeline succeeds + (this.inner, this.bufferedPages) = await MoveNextAsync_InitializeAsync(this.initializationParameters, trace, cancellationToken); + this.state = ExecutionState.Initialized; + + if (this.bufferedPages.Count > 0) + { + return true; + } + } + + if (this.bufferedPages.Count > 0) + { + this.bufferedPages.Dequeue(); + if (this.bufferedPages.Count > 0) + { + return true; + } + } + + TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace, cancellationToken)); + return hasNext.Succeeded && hasNext.Result; + } + + public ValueTask DisposeAsync() + { + if (this.state == ExecutionState.Initialized && this.inner.Succeeded) + { + return this.inner.Result.DisposeAsync(); + } + + return default; + } + + public static TryCatch MonadicCreate( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + IReadOnlyList targetRanges, + Cosmos.PartitionKey? partitionKey, + IReadOnlyList orderByColumns, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency, + CosmosElement continuationToken) + { + if (documentContainer == null) + { + throw new ArgumentNullException(nameof(documentContainer)); + } + + if (sqlQuerySpec == null) + { + throw new ArgumentNullException(nameof(sqlQuerySpec)); + } + + if (targetRanges == null) + { + throw new ArgumentNullException(nameof(targetRanges)); + } + + if (targetRanges.Count == 0) + { + throw new ArgumentException($"{nameof(targetRanges)} must not be empty."); + } + + if (orderByColumns == null) + { + throw new ArgumentNullException(nameof(orderByColumns)); + } + + if (orderByColumns.Count == 0) + { + throw new ArgumentException($"{nameof(orderByColumns)} must not be empty."); + } + + if (continuationToken != null) + { + return StreamingOrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer, + sqlQuerySpec, + targetRanges, + partitionKey, + orderByColumns, + queryPaginationOptions, + maxConcurrency, + continuationToken); + } + + InitializationParameters init = new InitializationParameters( + documentContainer, + sqlQuerySpec, + targetRanges, + partitionKey, + orderByColumns, + queryPaginationOptions, + maxConcurrency); + + return TryCatch.FromResult(new OrderByCrossPartitionQueryPipelineStage(init)); + } + + private static async ValueTask<(TryCatch, Queue)> MoveNextAsync_InitializeAsync(InitializationParameters init, ITrace trace, CancellationToken cancellationToken) + { + SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( + init.SqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + init.SqlQuerySpec.Parameters); + + List uninitializedEnumerators = init.TargetRanges + .Select(range => OrderByQueryPartitionRangePageAsyncEnumerator.Create( + init.DocumentContainer, + rewrittenQueryForOrderBy, + new FeedRangeState(range, state: default), + init.PartitionKey, + init.QueryPaginationOptions, + TrueFilter, + PrefetchPolicy.PrefetchSinglePage)) + .ToList(); + + Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens = new Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)>( + uninitializedEnumerators + .Select(x => (x, (OrderByContinuationToken)null))); + + await ParallelPrefetch.PrefetchInParallelAsync(uninitializedEnumerators, init.MaxConcurrency, trace, cancellationToken); + + IReadOnlyList sortOrders = init.OrderByColumns.Select(column => column.SortOrder).ToList(); + PriorityQueue initializedEnumerators = new PriorityQueue(new OrderByEnumeratorComparer(sortOrders)); + Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> enumeratorsAndTokens = new Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)>(); + + bool nonStreaming = false; + Queue bufferedPages = new Queue(); + QueryPageParameters queryPageParameters = null; + while (uninitializedEnumeratorsAndTokens.Count != 0) + { + (OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token) = uninitializedEnumeratorsAndTokens.Dequeue(); + if (await enumerator.MoveNextAsync(trace, cancellationToken)) + { + if (enumerator.Current.Failed) + { + if (IsSplitException(enumerator.Current.Exception)) + { + await MoveNextAsync_InitializeAsync_HandleSplitAsync( + init.DocumentContainer, + uninitializedEnumeratorsAndTokens, + enumerator, + token, + trace, + cancellationToken); + + continue; + } + else + { + // early return + return (TryCatch.FromException(enumerator.Current.Exception), bufferedPages); + } + } + + QueryPage page = enumerator.Current.Result.Page; + if (queryPageParameters == null) + { + // It is difficult to merge the headers because the type is not strong enough to support merging. + // Moreover, the existing code also does not merge the headers. + // Instead they grab the headers at random from some pages and send them onwards. + queryPageParameters = new QueryPageParameters( + activityId: page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: page.DistributionPlanSpec, + additionalHeaders: page.AdditionalHeaders); + } + + // For backwards compatibility the default value of streaming for ORDER BY is _true_ + nonStreaming = nonStreaming || (!page.Streaming.GetValueOrDefault(true) && (page.State != null)); + + if (enumerator.Current.Result.Enumerator.MoveNext()) + { + // the page is non-empty then we need to enqueue the enumerator in the PriorityQueue + initializedEnumerators.Enqueue(enumerator); + } + else + { + enumeratorsAndTokens.Enqueue((enumerator, token)); + } + + // Ensure proper reporting of query charges + bufferedPages.Enqueue(new QueryPage( + documents: EmptyPage, + requestCharge: page.RequestCharge, + activityId: page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: page.DistributionPlanSpec, + disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, + additionalHeaders: page.AdditionalHeaders, + state: InitializingQueryState, + streaming: page.Streaming)); + } + } + + IQueryPipelineStage pipelineStage; + if (nonStreaming) + { + Queue orderbyEnumerators = new Queue(); + foreach ((OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken _) in enumeratorsAndTokens) + { + OrderByQueryPartitionRangePageAsyncEnumerator bufferedEnumerator = enumerator.CloneAsFullyBufferedEnumerator(); + orderbyEnumerators.Enqueue(bufferedEnumerator); + } + + foreach (OrderByQueryPartitionRangePageAsyncEnumerator initializedEnumerator in initializedEnumerators) + { + OrderByQueryPartitionRangePageAsyncEnumerator bufferedEnumerator = initializedEnumerator.CloneAsFullyBufferedEnumerator(); + orderbyEnumerators.Enqueue(bufferedEnumerator); + } + + await ParallelPrefetch.PrefetchInParallelAsync(orderbyEnumerators, init.MaxConcurrency, trace, cancellationToken); + + pipelineStage = await NonStreamingOrderByPipelineStage.CreateAsync( + init.QueryPaginationOptions, + sortOrders, + orderbyEnumerators, + queryPageParameters, + trace, + cancellationToken); + } + else + { + pipelineStage = StreamingOrderByCrossPartitionQueryPipelineStage.Create( + init.DocumentContainer, + sortOrders, + initializedEnumerators, + enumeratorsAndTokens, + init.QueryPaginationOptions, + init.MaxConcurrency); + } + + return (TryCatch.FromResult(pipelineStage), bufferedPages); + } + + private static async ValueTask MoveNextAsync_InitializeAsync_HandleSplitAsync( + IDocumentContainer documentContainer, + Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens, + OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, + OrderByContinuationToken token, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + IReadOnlyList childRanges = await documentContainer.GetChildRangeAsync( + uninitializedEnumerator.FeedRangeState.FeedRange, + trace, + cancellationToken); + + if (childRanges.Count <= 1) + { + // We optimistically assumed that the cache is not stale. + // In the event that it is (where we only get back one child / the partition that we think got split) + // Then we need to refresh the cache + await documentContainer.RefreshProviderAsync(trace, cancellationToken); + childRanges = await documentContainer.GetChildRangeAsync( + uninitializedEnumerator.FeedRangeState.FeedRange, + trace, + cancellationToken); + } + + if (childRanges.Count < 1) + { + string errorMessage = "SDK invariant violated 82086B2D: Must have at least one EPK range in a cross partition enumerator"; + throw Resource.CosmosExceptions.CosmosExceptionFactory.CreateInternalServerErrorException( + message: errorMessage, + headers: null, + stackTrace: null, + trace: trace, + error: new Microsoft.Azure.Documents.Error { Code = "SDK_invariant_violated_82086B2D", Message = errorMessage }); + } + + if (childRanges.Count == 1) + { + // On a merge, the 410/1002 results in a single parent + // We maintain the current enumerator's range and let the RequestInvokerHandler logic kick in + OrderByQueryPartitionRangePageAsyncEnumerator childPaginator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + uninitializedEnumerator.SqlQuerySpec, + new FeedRangeState(uninitializedEnumerator.FeedRangeState.FeedRange, uninitializedEnumerator.StartOfPageState), + partitionKey: null, + uninitializedEnumerator.QueryPaginationOptions, + uninitializedEnumerator.Filter, + PrefetchPolicy.PrefetchSinglePage); + uninitializedEnumeratorsAndTokens.Enqueue((childPaginator, token)); + } + else + { + // Split + foreach (FeedRangeInternal childRange in childRanges) + { + cancellationToken.ThrowIfCancellationRequested(); + + OrderByQueryPartitionRangePageAsyncEnumerator childPaginator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + uninitializedEnumerator.SqlQuerySpec, + new FeedRangeState(childRange, uninitializedEnumerator.StartOfPageState), + partitionKey: null, + uninitializedEnumerator.QueryPaginationOptions, + uninitializedEnumerator.Filter, + PrefetchPolicy.PrefetchSinglePage); + uninitializedEnumeratorsAndTokens.Enqueue((childPaginator, token)); + } + } + } + + private static bool IsSplitException(Exception exception) + { + while (exception.InnerException != null) + { + exception = exception.InnerException; + } + + return exception.IsPartitionSplitException(); + } + + /// + /// This class is responsible for draining cross partition queries that have order by conditions. + /// The way order by queries work is that they are doing a k-way merge of sorted lists from each partition with an added condition. + /// The added condition is that if 2 or more top documents from different partitions are equivalent then we drain from the left most partition first. + /// This way we can generate a single continuation token for all n partitions. + /// This class is able to stop and resume execution by generating continuation tokens and reconstructing an execution context from said token. + /// + private sealed class StreamingOrderByCrossPartitionQueryPipelineStage : IQueryPipelineStage + { + private readonly IDocumentContainer documentContainer; + private readonly IReadOnlyList sortOrders; + private readonly PriorityQueue enumerators; + private readonly Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens; + private readonly QueryPaginationOptions queryPaginationOptions; + private readonly int maxConcurrency; + + private QueryState state; + private bool returnedFinalPage; + + private static class Expressions + { + public const string LessThan = "<"; + public const string LessThanOrEqualTo = "<="; + public const string EqualTo = "="; + public const string GreaterThan = ">"; + public const string GreaterThanOrEqualTo = ">="; + public const string True = "true"; + public const string False = "false"; + } + + private StreamingOrderByCrossPartitionQueryPipelineStage( + IDocumentContainer documentContainer, + IReadOnlyList sortOrders, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency, + IEnumerable<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)> uninitializedEnumeratorsAndTokens, + QueryState state) + { + this.documentContainer = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer)); + this.sortOrders = sortOrders ?? throw new ArgumentNullException(nameof(sortOrders)); + this.enumerators = new PriorityQueue(new OrderByEnumeratorComparer(this.sortOrders)); + this.queryPaginationOptions = queryPaginationOptions ?? QueryPaginationOptions.Default; + this.maxConcurrency = maxConcurrency < 0 ? throw new ArgumentOutOfRangeException($"{nameof(maxConcurrency)} must be a non negative number.") : maxConcurrency; + this.uninitializedEnumeratorsAndTokens = new Queue<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)>(uninitializedEnumeratorsAndTokens ?? throw new ArgumentNullException(nameof(uninitializedEnumeratorsAndTokens))); + this.state = state ?? InitializingQueryState; + } + + private StreamingOrderByCrossPartitionQueryPipelineStage( + IDocumentContainer documentContainer, + IReadOnlyList sortOrders, + PriorityQueue enumerators, + Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency) + { + this.documentContainer = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer)); + this.sortOrders = sortOrders ?? throw new ArgumentNullException(nameof(sortOrders)); + this.enumerators = enumerators ?? throw new ArgumentNullException(nameof(enumerators)); + this.uninitializedEnumeratorsAndTokens = uninitializedEnumeratorsAndTokens ?? throw new ArgumentNullException(nameof(uninitializedEnumeratorsAndTokens)); + this.queryPaginationOptions = queryPaginationOptions ?? throw new ArgumentNullException(nameof(queryPaginationOptions)); + this.maxConcurrency = maxConcurrency; + this.state = InitializingQueryState; + } + + public TryCatch Current { get; private set; } + + public ValueTask DisposeAsync() + { + return default; + } + + private async ValueTask MoveNextAsync_Initialize_FromBeginningAsync( + OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (uninitializedEnumerator == null) + { + throw new ArgumentNullException(nameof(uninitializedEnumerator)); + } + + // We need to prime the page + if (!await uninitializedEnumerator.MoveNextAsync(trace, cancellationToken)) + { + // No more documents, so just return an empty page + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: 0, + activityId: string.Empty, + cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, + disallowContinuationTokenMessage: default, + additionalHeaders: default, + state: this.state, + streaming: true)); + return true; + } + + if (uninitializedEnumerator.Current.Failed) + { + if (IsSplitException(uninitializedEnumerator.Current.Exception)) + { + return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token: null, trace, cancellationToken); + } + + this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, token: null)); + this.Current = TryCatch.FromException(uninitializedEnumerator.Current.Exception); + } + else + { + QueryPage page = uninitializedEnumerator.Current.Result.Page; + + if (!uninitializedEnumerator.Current.Result.Enumerator.MoveNext()) + { + // Page was empty + if (uninitializedEnumerator.FeedRangeState.State != null) + { + this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, token: null)); + } + + if ((this.uninitializedEnumeratorsAndTokens.Count == 0) && (this.enumerators.Count == 0)) + { + // Query did not match any results. We need to emit a fake empty page with null continuation + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: page.RequestCharge, + activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, + disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, + additionalHeaders: page.AdditionalHeaders, + state: null, + streaming: page.Streaming)); + this.returnedFinalPage = true; + return true; + } + } + else + { + this.enumerators.Enqueue(uninitializedEnumerator); + } + + // Just return an empty page with the stats + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: page.RequestCharge, + activityId: page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, + disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, + additionalHeaders: page.AdditionalHeaders, + state: this.state, + page.Streaming)); + } + + return true; + } + + private async ValueTask MoveNextAsync_Initialize_FilterAsync( + OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, + OrderByContinuationToken token, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (uninitializedEnumerator == null) + { + throw new ArgumentNullException(nameof(uninitializedEnumerator)); + } + + if (token == null) + { + throw new ArgumentNullException(nameof(token)); + } + + TryCatch<(bool, int, TryCatch)> filterMonad = await FilterNextAsync( + uninitializedEnumerator, + this.sortOrders, + token, + trace, + cancellationToken: default); + + if (filterMonad.Failed) + { + if (IsSplitException(filterMonad.Exception)) + { + return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token, trace, cancellationToken); + } + + this.Current = TryCatch.FromException(filterMonad.Exception); + return true; + } + + (bool doneFiltering, int itemsLeftToSkip, TryCatch monadicQueryByPage) = filterMonad.Result; + QueryPage page = uninitializedEnumerator.Current.Result.Page; + if (doneFiltering) + { + if (uninitializedEnumerator.Current.Result.Enumerator.Current != null) + { + this.enumerators.Enqueue(uninitializedEnumerator); + } + else if ((this.uninitializedEnumeratorsAndTokens.Count == 0) && (this.enumerators.Count == 0)) + { + // Query did not match any results. + // We need to emit a fake empty page with null continuation + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: page.RequestCharge, + activityId: string.IsNullOrEmpty(page.ActivityId) ? Guid.NewGuid().ToString() : page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, + disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, + additionalHeaders: page.AdditionalHeaders, + state: null, + streaming: page.Streaming)); + this.returnedFinalPage = true; + return true; + } + } + else + { + if (monadicQueryByPage.Failed) + { + if (IsSplitException(filterMonad.Exception)) + { + return await this.MoveNextAsync_InitializeAsync_HandleSplitAsync(uninitializedEnumerator, token, trace, cancellationToken); + } + } + + if (uninitializedEnumerator.FeedRangeState.State != default) + { + // We need to update the token + OrderByContinuationToken modifiedToken = new OrderByContinuationToken( + new ParallelContinuationToken( + ((CosmosString)uninitializedEnumerator.FeedRangeState.State.Value).Value, + ((FeedRangeEpk)uninitializedEnumerator.FeedRangeState.FeedRange).Range), + token.OrderByItems, + token.ResumeValues, + token.Rid, + itemsLeftToSkip, + token.Filter); + this.uninitializedEnumeratorsAndTokens.Enqueue((uninitializedEnumerator, modifiedToken)); + CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(modifiedToken); + CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); + this.state = new QueryState(continuationTokenList); + } + } + + // Just return an empty page with the stats + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: page.RequestCharge, + activityId: page.ActivityId, + cosmosQueryExecutionInfo: page.CosmosQueryExecutionInfo, + distributionPlanSpec: default, + disallowContinuationTokenMessage: page.DisallowContinuationTokenMessage, + additionalHeaders: page.AdditionalHeaders, + state: InitializingQueryState, + streaming: page.Streaming)); + + return true; + } + + private async ValueTask MoveNextAsync_InitializeAsync_HandleSplitAsync( + OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, + OrderByContinuationToken token, + ITrace trace, + CancellationToken cancellationToken) + { + await OrderByCrossPartitionQueryPipelineStage.MoveNextAsync_InitializeAsync_HandleSplitAsync( + this.documentContainer, + this.uninitializedEnumeratorsAndTokens, + uninitializedEnumerator, + token, + trace, + cancellationToken); + + // Recursively retry + return await this.MoveNextAsync(trace, cancellationToken); + } + + private async ValueTask MoveNextAsync_InitializeAsync(ITrace trace, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + await ParallelPrefetch.PrefetchInParallelAsync( + this.uninitializedEnumeratorsAndTokens.Select(value => value.enumerator), + this.maxConcurrency, + trace, + cancellationToken); + (OrderByQueryPartitionRangePageAsyncEnumerator uninitializedEnumerator, OrderByContinuationToken token) = this.uninitializedEnumeratorsAndTokens.Dequeue(); + bool movedNext = token is null + ? await this.MoveNextAsync_Initialize_FromBeginningAsync(uninitializedEnumerator, trace, cancellationToken) + : await this.MoveNextAsync_Initialize_FilterAsync(uninitializedEnumerator, token, trace, cancellationToken); + return movedNext; + } + + private ValueTask MoveNextAsync_DrainPageAsync(ITrace trace, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + + OrderByQueryPartitionRangePageAsyncEnumerator currentEnumerator = default; + OrderByQueryResult orderByQueryResult = default; + + // Try to form a page with as many items in the sorted order without having to do async work. + List results = new List(); + while (results.Count < this.queryPaginationOptions.PageSizeLimit.GetValueOrDefault(int.MaxValue)) + { + currentEnumerator = this.enumerators.Dequeue(); + orderByQueryResult = new OrderByQueryResult(currentEnumerator.Current.Result.Enumerator.Current); + results.Add(orderByQueryResult); + + if (!currentEnumerator.Current.Result.Enumerator.MoveNext()) + { + // The order by page ran out of results + if (currentEnumerator.FeedRangeState.State != null) + { + // If the continuation isn't null + // then mark the enumerator as unitialized and it will get requeueed on the next iteration with a fresh page. + this.uninitializedEnumeratorsAndTokens.Enqueue((currentEnumerator, (OrderByContinuationToken)null)); + + // Use the token for the next page, since we fully drained the enumerator. + OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( + new ParallelContinuationToken( + token: ((CosmosString)currentEnumerator.FeedRangeState.State.Value).Value, + range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), + orderByQueryResult, + skipCount: 0, + filter: currentEnumerator.Filter); + + CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); + CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); + + this.state = new QueryState(continuationTokenList); + + // Return a page of results + // No stats to report, since we already reported it when we moved to this page. + this.Current = TryCatch.FromResult( + new QueryPage( + documents: results.Select(result => result.Payload).ToList(), + requestCharge: 0, + activityId: default, + cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, + disallowContinuationTokenMessage: default, + additionalHeaders: currentEnumerator.Current.Result.Page.AdditionalHeaders, + state: this.state, + streaming: true)); + return new ValueTask(true); + } + + // Todo: we can optimize this by having a special "Done" continuation token + // so we don't grab a full page and filter it through + // but this would break older clients, so wait for a compute only fork. + + break; + } + + this.enumerators.Enqueue(currentEnumerator); + } + + // It is possible that we emit multiple documents with the same rid due to JOIN queries. + // This means it is not enough to serialize the rid that we left on to resume the query. + // We need to also serialize the number of documents with that rid, so we can skip it when resuming + int skipCount = results.Where(result => string.Equals(result.Rid, orderByQueryResult.Rid)).Count(); + + // Create the continuation token. + CosmosElement state; + if ((this.enumerators.Count == 0) && (this.uninitializedEnumeratorsAndTokens.Count == 0)) + { + state = null; + } + else + { + OrderByContinuationToken orderByContinuationToken = CreateOrderByContinuationToken( + new ParallelContinuationToken( + token: currentEnumerator.StartOfPageState != null ? ((CosmosString)currentEnumerator.StartOfPageState.Value).Value : null, + range: ((FeedRangeEpk)currentEnumerator.FeedRangeState.FeedRange).Range), + orderByQueryResult, + skipCount, + currentEnumerator.Filter); + + CosmosElement cosmosElementOrderByContinuationToken = OrderByContinuationToken.ToCosmosElement(orderByContinuationToken); + CosmosArray continuationTokenList = CosmosArray.Create(new List() { cosmosElementOrderByContinuationToken }); + + state = continuationTokenList; + } + + this.state = state != null ? new QueryState(state) : null; + + // Return a page of results + // No stats to report, since we already reported it when we moved to this page. + this.Current = TryCatch.FromResult( + new QueryPage( + documents: results.Select(result => result.Payload).ToList(), + requestCharge: 0, + activityId: default, + cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, + disallowContinuationTokenMessage: default, + additionalHeaders: currentEnumerator?.Current.Result.Page.AdditionalHeaders, + state: this.state, + streaming: true)); + + if (state == null) + { + this.returnedFinalPage = true; + } + + return new ValueTask(true); + } + + //// In order to maintain the continuation token for the user we must drain with a few constraints + //// 1) We always drain from the partition, which has the highest priority item first + //// 2) If multiple partitions have the same priority item then we drain from the left most first + //// otherwise we would need to keep track of how many of each item we drained from each partition + //// (just like parallel queries). + //// Visually that look the following case where we have three partitions that are numbered and store letters. + //// For teaching purposes I have made each item a tuple of the following form: + //// + //// So that duplicates across partitions are distinct, but duplicates within partitions are indistinguishable. + //// |-------| |-------| |-------| + //// | | | | | | + //// | | | | | | + //// | | | | | | + //// | | | | | | + //// | | | | | | + //// | | | | | | + //// | | | | | | + //// |-------| |-------| |-------| + //// Now the correct drain order in this case is: + //// ,,,,,,,,,,, + //// ,,,,,,,,, + //// In more mathematical terms + //// 1) always comes before where x < z + //// 2) always come before where j < k + public ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + + if (this.uninitializedEnumeratorsAndTokens.Count != 0) + { + return this.MoveNextAsync_InitializeAsync(trace, cancellationToken); + } + + if (this.enumerators.Count == 0) + { + if (!this.returnedFinalPage) + { + // return a empty page with null continuation token + this.Current = TryCatch.FromResult( + new QueryPage( + documents: EmptyPage, + requestCharge: 0, + activityId: Guid.NewGuid().ToString(), + cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, + disallowContinuationTokenMessage: default, + additionalHeaders: default, + state: default, + streaming: true)); + this.returnedFinalPage = true; + return new ValueTask(true); + } + + // Finished draining. + return new ValueTask(false); + } + + return this.MoveNextAsync_DrainPageAsync(trace, cancellationToken); + } + + public static IQueryPipelineStage Create( + IDocumentContainer documentContainer, + IReadOnlyList sortOrders, + PriorityQueue enumerators, + Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> uninitializedEnumeratorsAndTokens, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency) + { + return new StreamingOrderByCrossPartitionQueryPipelineStage( + documentContainer, + sortOrders, + enumerators, + uninitializedEnumeratorsAndTokens, + queryPaginationOptions, + maxConcurrency); + } + + public static TryCatch MonadicCreate( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + IReadOnlyList targetRanges, + Cosmos.PartitionKey? partitionKey, + IReadOnlyList orderByColumns, + QueryPaginationOptions queryPaginationOptions, + int maxConcurrency, + CosmosElement continuationToken) + { + // TODO (brchon): For now we are not honoring non deterministic ORDER BY queries, since there is a bug in the continuation logic. + // We can turn it back on once the bug is fixed. + // This shouldn't hurt any query results. + + List<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)> enumeratorsAndTokens; + if (continuationToken == null) + { + // Start off all the partition key ranges with null continuation + SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters); + + enumeratorsAndTokens = targetRanges + .Select(range => (OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + rewrittenQueryForOrderBy, + new FeedRangeState(range, state: default), + partitionKey, + queryPaginationOptions, + TrueFilter, + PrefetchPolicy.PrefetchSinglePage), + (OrderByContinuationToken)null)) + .ToList(); + } + else + { + TryCatch> monadicGetOrderByContinuationTokenMapping = MonadicGetOrderByContinuationTokenMapping( + targetRanges, + continuationToken, + orderByColumns.Count); + if (monadicGetOrderByContinuationTokenMapping.Failed) + { + return TryCatch.FromException(monadicGetOrderByContinuationTokenMapping.Exception); + } + + PartitionMapper.PartitionMapping partitionMapping = monadicGetOrderByContinuationTokenMapping.Result; + + OrderByContinuationToken targetContinuationToken = partitionMapping.TargetMapping.Values.First(); + + int orderByResumeValueCount = 0; + IReadOnlyList resumeValues; + IReadOnlyList orderByItems; + if (targetContinuationToken.ResumeValues != null) + { + // Use SqlQueryResumeValue for continuation if it is present. + resumeValues = targetContinuationToken.ResumeValues; + orderByItems = null; + orderByResumeValueCount = resumeValues.Count; + } + else + { + // If continuation token has only OrderByItems, check if it can be converted to SqlQueryResumeValue. This will + // help avoid re-writing the query. Conversion will work as long as the order by item type is a supported type. + orderByResumeValueCount = targetContinuationToken.OrderByItems.Count; + + if (ContainsSupportedResumeTypes(targetContinuationToken.OrderByItems)) + { + // Convert the order by items to SqlQueryResumeValue + List generatedResumeValues = new List(targetContinuationToken.OrderByItems.Count); + //foreach (CosmosElement orderByItem in orderByItems) + foreach (OrderByItem orderByItem in targetContinuationToken.OrderByItems) + { + generatedResumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); + } + + resumeValues = generatedResumeValues; + orderByItems = null; + } + else + { + orderByItems = targetContinuationToken.OrderByItems.Select(x => x.Item).ToList(); + resumeValues = null; + } + } + + if (orderByResumeValueCount != orderByColumns.Count) + { + return TryCatch.FromException( + new MalformedContinuationTokenException( + $"Order By Items from continuation token did not match the query text. " + + $"Order by item count: {orderByResumeValueCount} did not match column count {orderByColumns.Count()}. " + + $"Continuation token: {targetContinuationToken}")); + } + + enumeratorsAndTokens = new List<(OrderByQueryPartitionRangePageAsyncEnumerator, OrderByContinuationToken)>(); + if (resumeValues != null) + { + // Continuation contains resume values, so update SqlQuerySpec to include SqlQueryResumeFilter which + // will specify the resume point to the backend. This avoid having to re-write the query. + + // Process partitions left of Target. The resume values in these partition have + // already been processed so exclude flag is set to true. + SqlQuerySpec leftQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, null, true)); + + foreach (KeyValuePair kvp in partitionMapping.MappingLeftOfTarget) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + leftQuerySpec, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter: null, + PrefetchPolicy.PrefetchSinglePage); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + + // Process Target Partitions which is the last partition from which data has been returned. + // For this partition the Rid value needs to be set if present. Exclude flag is not set as the document + // matching the Rid will be skipped in SDK based on SkipCount value. + // Backend requests can contains both SqlQueryResumeFilter and ContinuationToken and the backend will pick + // the resume point that is bigger i.e. most restrictive + foreach (KeyValuePair kvp in partitionMapping.TargetMapping) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + + SqlQuerySpec targetQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, token?.Rid, false)); + + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + targetQuerySpec, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter: null, + PrefetchPolicy.PrefetchSinglePage); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + + // Process partitions right of target. The Resume value in these partitions have not been processed so the exclude value is set to false. + SqlQuerySpec rightQuerySpec = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + sqlQuerySpec.Parameters, + new SqlQueryResumeFilter(resumeValues, null, false)); + + foreach (KeyValuePair kvp in partitionMapping.MappingRightOfTarget) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + rightQuerySpec, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter: null, + PrefetchPolicy.PrefetchSinglePage); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + } + else + { + // If continuation token doesn't have resume values or if order by items cannot be converted to resume values then + // rewrite the query filter to get the correct resume point + ReadOnlyMemory<(OrderByColumn, CosmosElement)> columnAndItems = orderByColumns.Zip(orderByItems, (column, item) => (column, item)).ToArray(); + + // For ascending order-by, left of target partition has filter expression > value, + // right of target partition has filter expression >= value, + // and target partition takes the previous filter from continuation (or true if no continuation) + (string leftFilter, string targetFilter, string rightFilter) = GetFormattedFilters(columnAndItems); + List<(IReadOnlyDictionary, string)> tokenMappingAndFilters = new List<(IReadOnlyDictionary, string)>() + { + { (partitionMapping.MappingLeftOfTarget, leftFilter) }, + { (partitionMapping.TargetMapping, targetFilter) }, + { (partitionMapping.MappingRightOfTarget, rightFilter) }, + }; + + foreach ((IReadOnlyDictionary tokenMapping, string filter) in tokenMappingAndFilters) + { + SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( + sqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: filter), + sqlQuerySpec.Parameters); + + foreach (KeyValuePair kvp in tokenMapping) + { + FeedRangeEpk range = kvp.Key; + OrderByContinuationToken token = kvp.Value; + OrderByQueryPartitionRangePageAsyncEnumerator remoteEnumerator = OrderByQueryPartitionRangePageAsyncEnumerator.Create( + documentContainer, + rewrittenQueryForOrderBy, + new FeedRangeState(range, token?.ParallelContinuationToken?.Token != null ? new QueryState(CosmosString.Create(token.ParallelContinuationToken.Token)) : null), + partitionKey, + queryPaginationOptions, + filter, + PrefetchPolicy.PrefetchSinglePage); + + enumeratorsAndTokens.Add((remoteEnumerator, token)); + } + } + } + } + + StreamingOrderByCrossPartitionQueryPipelineStage stage = new StreamingOrderByCrossPartitionQueryPipelineStage( + documentContainer, + orderByColumns.Select(column => column.SortOrder).ToList(), + queryPaginationOptions, + maxConcurrency, + enumeratorsAndTokens, + continuationToken == null ? null : new QueryState(continuationToken)); + return TryCatch.FromResult(stage); + } + + private static TryCatch> MonadicGetOrderByContinuationTokenMapping( + IReadOnlyList partitionKeyRanges, + CosmosElement continuationToken, + int numOrderByItems) + { + if (partitionKeyRanges == null) + { + throw new ArgumentOutOfRangeException(nameof(partitionKeyRanges)); + } + + if (numOrderByItems < 0) + { + throw new ArgumentOutOfRangeException(nameof(numOrderByItems)); + } + + if (continuationToken == null) + { + throw new ArgumentNullException(nameof(continuationToken)); + } + + TryCatch> monadicExtractContinuationTokens = MonadicExtractOrderByTokens(continuationToken, numOrderByItems); + if (monadicExtractContinuationTokens.Failed) + { + return TryCatch>.FromException(monadicExtractContinuationTokens.Exception); + } + + return PartitionMapper.MonadicGetPartitionMapping( + partitionKeyRanges, + monadicExtractContinuationTokens.Result); + } + + private static TryCatch> MonadicExtractOrderByTokens( + CosmosElement continuationToken, + int numOrderByColumns) + { + if (continuationToken == null) + { + return TryCatch>.FromResult(default); + } + + if (!(continuationToken is CosmosArray cosmosArray)) + { + return TryCatch>.FromException( + new MalformedContinuationTokenException( + $"Order by continuation token must be an array: {continuationToken}.")); + } + + if (cosmosArray.Count == 0) + { + return TryCatch>.FromException( + new MalformedContinuationTokenException( + $"Order by continuation token cannot be empty: {continuationToken}.")); + } + + List orderByContinuationTokens = new List(); + foreach (CosmosElement arrayItem in cosmosArray) + { + TryCatch tryCreateOrderByContinuationToken = OrderByContinuationToken.TryCreateFromCosmosElement(arrayItem); + if (!tryCreateOrderByContinuationToken.Succeeded) + { + return TryCatch>.FromException(tryCreateOrderByContinuationToken.Exception); + } + + orderByContinuationTokens.Add(tryCreateOrderByContinuationToken.Result); + } + + foreach (OrderByContinuationToken suppliedOrderByContinuationToken in orderByContinuationTokens) + { + int orderByCount = GetOrderByItemCount(suppliedOrderByContinuationToken); + if (orderByCount != numOrderByColumns) + { + return TryCatch>.FromException( + new MalformedContinuationTokenException( + $"Invalid order-by items in continuation token {continuationToken} for OrderBy~Context.")); + } + } + + return TryCatch>.FromResult(orderByContinuationTokens); + } + + private static int GetOrderByItemCount(OrderByContinuationToken orderByContinuationToken) + { + return orderByContinuationToken.ResumeValues != null ? + orderByContinuationToken.ResumeValues.Count : orderByContinuationToken.OrderByItems.Count; + } + + private static void AppendToBuilders((StringBuilder leftFilter, StringBuilder targetFilter, StringBuilder rightFilter) builders, object str) + { + AppendToBuilders(builders, str, str, str); + } + + private static void AppendToBuilders((StringBuilder leftFilter, StringBuilder targetFilter, StringBuilder rightFilter) builders, object left, object target, object right) + { + builders.leftFilter.Append(left); + builders.targetFilter.Append(target); + builders.rightFilter.Append(right); + } + + private static (string leftFilter, string targetFilter, string rightFilter) GetFormattedFilters( + ReadOnlyMemory<(OrderByColumn orderByColumn, CosmosElement orderByItem)> columnAndItems) + { + // When we run cross partition queries, + // we only serialize the continuation token for the partition that we left off on. + // The only problem is that when we resume the order by query, + // we don't have continuation tokens for all other partition. + // The saving grace is that the data has a composite sort order(query sort order, partition key range id) + // so we can generate range filters which in turn the backend will turn into rid based continuation tokens, + // which is enough to get the streams of data flowing from all partitions. + // The details of how this is done is described below: + int numOrderByItems = columnAndItems.Length; + bool isSingleOrderBy = numOrderByItems == 1; + StringBuilder left = new StringBuilder(); + StringBuilder target = new StringBuilder(); + StringBuilder right = new StringBuilder(); + + (StringBuilder, StringBuilder, StringBuilder) builders = (left, target, right); + + if (isSingleOrderBy) + { + //For a single order by query we resume the continuations in this manner + // Suppose the query is SELECT* FROM c ORDER BY c.string ASC + // And we left off on partition N with the value "B" + // Then + // All the partitions to the left will have finished reading "B" + // Partition N is still reading "B" + // All the partitions to the right have let to read a "B + // Therefore the filters should be + // > "B" , >= "B", and >= "B" respectively + // Repeat the same logic for DESC and you will get + // < "B", <= "B", and <= "B" respectively + // The general rule becomes + // For ASC + // > for partitions to the left + // >= for the partition we left off on + // >= for the partitions to the right + // For DESC + // < for partitions to the left + // <= for the partition we left off on + // <= for the partitions to the right + (OrderByColumn orderByColumn, CosmosElement orderByItem) = columnAndItems.Span[0]; + (string expression, SortOrder sortOrder) = (orderByColumn.Expression, orderByColumn.SortOrder); + + AppendToBuilders(builders, "( "); + + // We need to add the filter for within the same type. + if (orderByItem is not CosmosUndefined) + { + StringBuilder sb = new StringBuilder(); + CosmosElementToQueryLiteral cosmosElementToQueryLiteral = new CosmosElementToQueryLiteral(sb); + orderByItem.Accept(cosmosElementToQueryLiteral); + + string orderByItemToString = sb.ToString(); + + left.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThan : Expressions.GreaterThan)} {orderByItemToString}"); + target.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThanOrEqualTo : Expressions.GreaterThanOrEqualTo)} {orderByItemToString}"); + right.Append($"{expression} {(sortOrder == SortOrder.Descending ? Expressions.LessThanOrEqualTo : Expressions.GreaterThanOrEqualTo)} {orderByItemToString}"); + } + else + { + // User is ordering by undefined, so we need to avoid a null reference exception. + + // What we really want is to support expression > undefined, + // but the engine evaluates to undefined instead of true or false, + // so we work around this by using the IS_DEFINED() system function. + + ComparisionWithUndefinedFilters filters = new ComparisionWithUndefinedFilters(expression); + left.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThan : filters.GreaterThan)}"); + target.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThanOrEqualTo : filters.GreaterThanOrEqualTo)}"); + right.Append($"{(sortOrder == SortOrder.Descending ? filters.LessThanOrEqualTo : filters.GreaterThanOrEqualTo)}"); + } + + // Now we need to include all the types that match the sort order. + ReadOnlyMemory isDefinedFunctions = orderByItem.Accept(CosmosElementToIsSystemFunctionsVisitor.Singleton, sortOrder == SortOrder.Ascending); + foreach (string isDefinedFunction in isDefinedFunctions.Span) + { + AppendToBuilders(builders, " OR "); + AppendToBuilders(builders, $"{isDefinedFunction}({expression})"); + } + + AppendToBuilders(builders, " )"); + } + else + { + //For a multi order by query + // Suppose the query is SELECT* FROM c ORDER BY c.string ASC, c.number ASC + // And we left off on partition N with the value("A", 1) + // Then + // All the partitions to the left will have finished reading("A", 1) + // Partition N is still reading("A", 1) + // All the partitions to the right have let to read a "(A", 1) + // The filters are harder to derive since their are multiple columns + // But the problem reduces to "How do you know one document comes after another in a multi order by query" + // The answer is to just look at it one column at a time. + // For this particular scenario: + // If a first column is greater ex. ("B", blah), then the document comes later in the sort order + // Therefore we want all documents where the first column is greater than "A" which means > "A" + // Or if the first column is a tie, then you look at the second column ex. ("A", blah). + // Therefore we also want all documents where the first column was a tie but the second column is greater which means = "A" AND > 1 + // Therefore the filters should be + // (> "A") OR (= "A" AND > 1), (> "A") OR (= "A" AND >= 1), (> "A") OR (= "A" AND >= 1) + // Notice that if we repeated the same logic we for single order by we would have gotten + // > "A" AND > 1, >= "A" AND >= 1, >= "A" AND >= 1 + // which is wrong since we missed some documents + // Repeat the same logic for ASC, DESC + // (> "A") OR (= "A" AND < 1), (> "A") OR (= "A" AND <= 1), (> "A") OR (= "A" AND <= 1) + // Again for DESC, ASC + // (< "A") OR (= "A" AND > 1), (< "A") OR (= "A" AND >= 1), (< "A") OR (= "A" AND >= 1) + // And again for DESC DESC + // (< "A") OR (= "A" AND < 1), (< "A") OR (= "A" AND <= 1), (< "A") OR (= "A" AND <= 1) + // The general we look at all prefixes of the order by columns to look for tie breakers. + // Except for the full prefix whose last column follows the rules for single item order by + // And then you just OR all the possibilities together + for (int prefixLength = 1; prefixLength <= numOrderByItems; prefixLength++) + { + ReadOnlySpan<(OrderByColumn orderByColumn, CosmosElement orderByItem)> columnAndItemPrefix = columnAndItems.Span.Slice(start: 0, length: prefixLength); + + bool lastPrefix = prefixLength == numOrderByItems; + + AppendToBuilders(builders, "("); + + for (int index = 0; index < prefixLength; index++) + { + string expression = columnAndItemPrefix[index].orderByColumn.Expression; + SortOrder sortOrder = columnAndItemPrefix[index].orderByColumn.SortOrder; + CosmosElement orderByItem = columnAndItemPrefix[index].orderByItem; + bool lastItem = index == prefixLength - 1; + + AppendToBuilders(builders, "("); + + bool wasInequality; + // We need to add the filter for within the same type. + if (orderByItem is CosmosUndefined) + { + ComparisionWithUndefinedFilters filters = new ComparisionWithUndefinedFilters(expression); + + // Refer to the logic from single order by for how we are handling order by undefined + if (lastItem) + { + if (lastPrefix) + { + if (sortOrder == SortOrder.Descending) + { + // <, <=, <= + AppendToBuilders(builders, filters.LessThan, filters.LessThanOrEqualTo, filters.LessThanOrEqualTo); + } + else + { + // >, >=, >= + AppendToBuilders(builders, filters.GreaterThan, filters.GreaterThanOrEqualTo, filters.GreaterThanOrEqualTo); + } + } + else + { + if (sortOrder == SortOrder.Descending) + { + // <, <, < + AppendToBuilders(builders, filters.LessThan, filters.LessThan, filters.LessThan); + } + else + { + // >, >, > + StreamingOrderByCrossPartitionQueryPipelineStage.AppendToBuilders(builders, filters.GreaterThan, filters.GreaterThan, filters.GreaterThan); + } + } + + wasInequality = true; + } + else + { + // =, =, = + AppendToBuilders(builders, filters.EqualTo); + wasInequality = false; + } + } + else + { + // Append Expression + AppendToBuilders(builders, expression); + AppendToBuilders(builders, " "); + + // Append Binary Operator + if (lastItem) + { + string inequality = sortOrder == SortOrder.Descending ? Expressions.LessThan : Expressions.GreaterThan; + AppendToBuilders(builders, inequality); + if (lastPrefix) + { + AppendToBuilders(builders, string.Empty, Expressions.EqualTo, Expressions.EqualTo); + } + + wasInequality = true; + } + else + { + AppendToBuilders(builders, Expressions.EqualTo); + wasInequality = false; + } + + // Append OrderBy Item + StringBuilder sb = new StringBuilder(); + CosmosElementToQueryLiteral cosmosElementToQueryLiteral = new CosmosElementToQueryLiteral(sb); + orderByItem.Accept(cosmosElementToQueryLiteral); + string orderByItemToString = sb.ToString(); + AppendToBuilders(builders, " "); + AppendToBuilders(builders, orderByItemToString); + AppendToBuilders(builders, " "); + } + + if (wasInequality) + { + // Now we need to include all the types that match the sort order. + ReadOnlyMemory isDefinedFunctions = orderByItem.Accept(CosmosElementToIsSystemFunctionsVisitor.Singleton, sortOrder == SortOrder.Ascending); + foreach (string isDefinedFunction in isDefinedFunctions.Span) + { + AppendToBuilders(builders, " OR "); + AppendToBuilders(builders, $"{isDefinedFunction}({expression}) "); + } + } + + AppendToBuilders(builders, ")"); + + if (!lastItem) + { + AppendToBuilders(builders, " AND "); + } + } + + AppendToBuilders(builders, ")"); + if (!lastPrefix) + { + AppendToBuilders(builders, " OR "); + } + } + } + + return (left.ToString(), target.ToString(), right.ToString()); + } + + private static OrderByContinuationToken CreateOrderByContinuationToken( + ParallelContinuationToken parallelToken, + OrderByQueryResult orderByQueryResult, + int skipCount, + string filter) + { + OrderByContinuationToken token; + // If order by items have c* types then it cannot be converted to resume values + if (ContainsSupportedResumeTypes(orderByQueryResult.OrderByItems)) + { + List resumeValues = new List(orderByQueryResult.OrderByItems.Count); + foreach (OrderByItem orderByItem in orderByQueryResult.OrderByItems) + { + resumeValues.Add(SqlQueryResumeValue.FromOrderByValue(orderByItem.Item)); + } + + token = new OrderByContinuationToken( + parallelToken, + orderByItems: null, + resumeValues, + orderByQueryResult.Rid, + skipCount: skipCount, + filter: filter); + } + else + { + token = new OrderByContinuationToken( + parallelToken, + orderByQueryResult.OrderByItems, + resumeValues: null, + orderByQueryResult.Rid, + skipCount: skipCount, + filter: filter); + } + + return token; + } + + // Helper method to check that resume values are of type that is supported by SqlQueryResumeValue + private static bool ContainsSupportedResumeTypes(IReadOnlyList orderByItems) + { + foreach (OrderByItem orderByItem in orderByItems) + { + if (!orderByItem.Item.Accept(SupportedResumeTypeVisitor.Singleton)) + { + return false; + } + } + + return true; + } + + private static async Task monadicQueryByPage)>> FilterNextAsync( + OrderByQueryPartitionRangePageAsyncEnumerator enumerator, + IReadOnlyList sortOrders, + OrderByContinuationToken continuationToken, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + // When we resume a query on a partition there is a possibility that we only read a partial page from the backend + // meaning that will we repeat some documents if we didn't do anything about it. + // The solution is to filter all the documents that come before in the sort order, since we have already emitted them to the client. + // The key is to seek until we get an order by value that matches the order by value we left off on. + // Once we do that we need to seek to the correct _rid within the term, + // since there might be many documents with the same order by value we left off on. + // Finally we need to skip some duplicate _rids, since JOINs emit multiples documents with the same rid and we read a partial page. + // You can also think about this as a seek on a composite index where the columns are [sort_order, rid, skip_count] + + int itemsToSkip = continuationToken.SkipCount; + if (!ResourceId.TryParse(continuationToken.Rid, out ResourceId continuationRid)) + { + return TryCatch<(bool, int, TryCatch)>.FromException( + new MalformedContinuationTokenException( + $"Invalid Rid in the continuation token {continuationToken.ParallelContinuationToken.Token} for OrderBy~Context.")); + } + + if (!await enumerator.MoveNextAsync(trace, cancellationToken)) + { + return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); + } + + TryCatch monadicOrderByQueryPage = enumerator.Current; + if (monadicOrderByQueryPage.Failed) + { + return TryCatch<(bool, int, TryCatch)>.FromException(monadicOrderByQueryPage.Exception); + } + + OrderByQueryPage orderByQueryPage = monadicOrderByQueryPage.Result; + IEnumerator documents = orderByQueryPage.Enumerator; + + while (documents.MoveNext()) + { + int sortOrderCompare = 0; + // Filter out documents until we find something that matches the sort order. + OrderByQueryResult orderByResult = new OrderByQueryResult(documents.Current); + for (int i = 0; (i < sortOrders.Count) && (sortOrderCompare == 0); ++i) + { + sortOrderCompare = continuationToken.ResumeValues != null + ? continuationToken.ResumeValues[i].CompareTo(orderByResult.OrderByItems[i].Item) + : ItemComparer.Instance.Compare( + continuationToken.OrderByItems[i].Item, + orderByResult.OrderByItems[i].Item); + + if (sortOrderCompare != 0) + { + sortOrderCompare = sortOrders[i] == SortOrder.Ascending ? sortOrderCompare : -sortOrderCompare; + } + } + + if (sortOrderCompare < 0) + { + // We might have passed the item due to deletions and filters. + return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); + } + + if (sortOrderCompare > 0) + { + // This document does not match the sort order, so skip it. + continue; + } + + // Once the item matches the order by items from the continuation tokens + // We still need to remove all the documents that have a lower or same rid in the rid sort order. + // If there is a tie in the sort order the documents should be in _rid order in the same direction as the index (given by the backend) + ResourceId rid = ResourceId.Parse(orderByResult.Rid); + int ridOrderCompare = continuationRid.Document.CompareTo(rid.Document); + + Lazy cosmosQueryExecutionInfo = orderByQueryPage.Page.CosmosQueryExecutionInfo; + if ((cosmosQueryExecutionInfo == null) || cosmosQueryExecutionInfo.Value.ReverseRidEnabled) + { + // If reverse rid is enabled on the backend then fallback to the old way of doing it. + if (sortOrders[0] == SortOrder.Descending) + { + ridOrderCompare = -ridOrderCompare; + } + } + else + { + // Go by the whatever order the index wants + if (cosmosQueryExecutionInfo.Value.ReverseIndexScan) + { + ridOrderCompare = -ridOrderCompare; + } + } + + if (ridOrderCompare < 0) + { + // We might have passed the rid due to deletions and filters. + return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); + } + + if (ridOrderCompare > 0) + { + // This document does not match the rid order, so skip it. + continue; + } + + // At this point we need to skip due to joins + if (--itemsToSkip < 0) + { + return TryCatch<(bool, int, TryCatch)>.FromResult((true, 0, enumerator.Current)); + } + } + + // If we made it here it means we failed to find the resume order by item which is possible + // if the user added documents inbetween continuations, so we need to yield and filter the next page of results also. + return TryCatch<(bool, int, TryCatch)>.FromResult((false, itemsToSkip, enumerator.Current)); + } + + private sealed class CosmosElementToIsSystemFunctionsVisitor : ICosmosElementVisitor> + { + public static readonly CosmosElementToIsSystemFunctionsVisitor Singleton = new CosmosElementToIsSystemFunctionsVisitor(); + + private static class IsSystemFunctions + { + public const string Defined = "IS_DEFINED"; + public const string Undefined = "NOT IS_DEFINED"; + public const string Null = "IS_NULL"; + public const string Boolean = "IS_BOOLEAN"; + public const string Number = "IS_NUMBER"; + public const string String = "IS_STRING"; + public const string Array = "IS_ARRAY"; + public const string Object = "IS_OBJECT"; + } + + private static readonly ReadOnlyMemory SystemFunctionSortOrder = new string[] + { + IsSystemFunctions.Undefined, + IsSystemFunctions.Null, + IsSystemFunctions.Boolean, + IsSystemFunctions.Number, + IsSystemFunctions.String, + IsSystemFunctions.Array, + IsSystemFunctions.Object, + }; + + private static readonly ReadOnlyMemory ExtendedTypesSystemFunctionSortOrder = new string[] + { + IsSystemFunctions.Undefined, + IsSystemFunctions.Defined + }; + + private static class SortOrder + { + public const int Undefined = 0; + public const int Null = 1; + public const int Boolean = 2; + public const int Number = 3; + public const int String = 4; + public const int Array = 5; + public const int Object = 6; + } + + private static class ExtendedTypesSortOrder + { + public const int Undefined = 0; + public const int Defined = 1; + } + + private CosmosElementToIsSystemFunctionsVisitor() + { + } + + public ReadOnlyMemory Visit(CosmosArray cosmosArray, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.Array, isAscending); + } + + public ReadOnlyMemory Visit(CosmosBinary cosmosBinary, bool isAscending) + { + return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending); + } + + public ReadOnlyMemory Visit(CosmosBoolean cosmosBoolean, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.Boolean, isAscending); + } + + public ReadOnlyMemory Visit(CosmosGuid cosmosGuid, bool isAscending) + { + return GetExtendedTypesIsDefinedFunctions(ExtendedTypesSortOrder.Defined, isAscending); + } + + public ReadOnlyMemory Visit(CosmosNull cosmosNull, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.Null, isAscending); + } + + public ReadOnlyMemory Visit(CosmosUndefined cosmosUndefined, bool isAscending) + { + return isAscending ? SystemFunctionSortOrder.Slice(start: 1) : ReadOnlyMemory.Empty; + } + + public ReadOnlyMemory Visit(CosmosNumber cosmosNumber, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.Number, isAscending); + } + + public ReadOnlyMemory Visit(CosmosObject cosmosObject, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.Object, isAscending); + } + + public ReadOnlyMemory Visit(CosmosString cosmosString, bool isAscending) + { + return GetIsDefinedFunctions(SortOrder.String, isAscending); + } + + private static ReadOnlyMemory GetIsDefinedFunctions(int index, bool isAscending) + { + return isAscending ? SystemFunctionSortOrder.Slice(index + 1) : SystemFunctionSortOrder.Slice(start: 0, index); + } + + private static ReadOnlyMemory GetExtendedTypesIsDefinedFunctions(int index, bool isAscending) + { + return isAscending ? + ExtendedTypesSystemFunctionSortOrder.Slice(index + 1) : + ExtendedTypesSystemFunctionSortOrder.Slice(start: 0, index); + } + } + + private readonly struct ComparisionWithUndefinedFilters + { + public ComparisionWithUndefinedFilters( + string expression) + { + this.LessThan = "false"; + this.LessThanOrEqualTo = $"NOT IS_DEFINED({expression})"; + this.EqualTo = $"NOT IS_DEFINED({expression})"; + this.GreaterThan = $"IS_DEFINED({expression})"; + this.GreaterThanOrEqualTo = "true"; + } + + public string LessThan { get; } + public string LessThanOrEqualTo { get; } + public string EqualTo { get; } + public string GreaterThan { get; } + public string GreaterThanOrEqualTo { get; } + } + + private sealed class SupportedResumeTypeVisitor : ICosmosElementVisitor + { + public static readonly SupportedResumeTypeVisitor Singleton = new SupportedResumeTypeVisitor(); + + private SupportedResumeTypeVisitor() + { + } + + public bool Visit(CosmosArray cosmosArray) + { + return true; + } + + public bool Visit(CosmosBinary cosmosBinary) + { + return false; + } + + public bool Visit(CosmosBoolean cosmosBoolean) + { + return true; + } + + public bool Visit(CosmosGuid cosmosGuid) + { + return false; + } + + public bool Visit(CosmosNull cosmosNull) + { + return true; + } + + public bool Visit(CosmosNumber cosmosNumber) + { + return cosmosNumber.Accept(SqlQueryResumeValue.SupportedResumeNumberTypeVisitor.Singleton); + } + + public bool Visit(CosmosObject cosmosObject) + { + return true; + } + + public bool Visit(CosmosString cosmosString) + { + return true; + } + + public bool Visit(CosmosUndefined cosmosUndefined) + { + return true; + } + } + } + + private sealed class NonStreamingOrderByPipelineStage : IQueryPipelineStage + { + private const int FlatHeapSizeLimit = 4096; + + private const int MaximumPageSize = 2048; + + private const string DisallowContinuationTokenMessage = "Continuation tokens are not supported for the non streaming order by pipeline."; + + private static readonly QueryState NonStreamingOrderByInProgress = new QueryState(CosmosString.Create("NonStreamingOrderByInProgress")); + + private readonly int pageSize; + + private readonly double totalRequestCharge; + + private readonly string activityId; + + private readonly Lazy cosmosQueryExecutionInfo; + + private readonly DistributionPlanSpec distributionPlanSpec; + + private readonly IReadOnlyDictionary additionalHeaders; + + private readonly IEnumerator enumerator; + + private int totalBufferedResultCount; + + private bool firstPage; + + public TryCatch Current { get; private set; } + + private NonStreamingOrderByPipelineStage( + int pageSize, + double totalRequestCharge, + string activityId, + Lazy cosmosQueryExecutionInfo, + DistributionPlanSpec distributionPlanSpec, + IReadOnlyDictionary additionalHeaders, + IEnumerator enumerator, + int totalBufferedResultCount) + { + this.pageSize = pageSize; + this.totalRequestCharge = totalRequestCharge; + this.activityId = activityId ?? throw new ArgumentNullException(nameof(activityId)); + this.cosmosQueryExecutionInfo = cosmosQueryExecutionInfo; + this.distributionPlanSpec = distributionPlanSpec; + this.additionalHeaders = additionalHeaders; + this.firstPage = true; + this.enumerator = enumerator ?? throw new ArgumentNullException(nameof(enumerator)); + this.totalBufferedResultCount = totalBufferedResultCount; + } + + public ValueTask DisposeAsync() + { + this.enumerator.Dispose(); + return default; + } + + public ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + List documents = this.totalBufferedResultCount >= this.pageSize ? new List(this.pageSize) : new List(); + for (int count = 0; count < this.pageSize && this.enumerator.MoveNext(); ++count) + { + documents.Add(this.enumerator.Current.Payload); + } + + this.totalBufferedResultCount -= documents.Count; + + if (this.firstPage || documents.Count > 0) + { + double requestCharge = this.firstPage ? this.totalRequestCharge : 0; + QueryPage queryPage = new QueryPage( + documents: documents, + requestCharge: requestCharge, + activityId: this.activityId, + cosmosQueryExecutionInfo: this.cosmosQueryExecutionInfo, + distributionPlanSpec: this.distributionPlanSpec, + disallowContinuationTokenMessage: DisallowContinuationTokenMessage, + additionalHeaders: this.additionalHeaders, + state: documents.Count > 0 ? NonStreamingOrderByInProgress : null, + streaming: false); + + this.firstPage = false; + this.Current = TryCatch.FromResult(queryPage); + return new ValueTask(true); + } + else + { + return new ValueTask(false); + } + } + + public static async Task CreateAsync( + QueryPaginationOptions queryPaginationOptions, + IReadOnlyList sortOrders, + IEnumerable enumerators, + QueryPageParameters queryPageParameters, + ITrace trace, + CancellationToken cancellationToken) + { + int pageSize = queryPaginationOptions.PageSizeLimit.GetValueOrDefault(MaximumPageSize) > 0 ? + Math.Min(MaximumPageSize, queryPaginationOptions.PageSizeLimit.Value) : + MaximumPageSize; + + int totalBufferedResultCount = 0; + foreach (OrderByQueryPartitionRangePageAsyncEnumerator enumerator in enumerators) + { + totalBufferedResultCount += enumerator.BufferedResultCount; + } + + OrderByQueryResultComparer comparer = new OrderByQueryResultComparer(sortOrders); + (IEnumerator orderbyQueryResultEnumerator, double totalRequestCharge) = await OrderByCrossPartitionEnumerator.CreateAsync( + enumerators, + comparer, + FlatHeapSizeLimit, + trace, + cancellationToken); + + return new NonStreamingOrderByPipelineStage( + pageSize, + totalRequestCharge, + queryPageParameters.ActivityId, + queryPageParameters.CosmosQueryExecutionInfo, + queryPageParameters.DistributionPlanSpec, + queryPageParameters.AdditionalHeaders, + orderbyQueryResultEnumerator, + totalBufferedResultCount); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByEnumeratorComparer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByEnumeratorComparer.cs index 5b9858154a..4c3acd6eaa 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByEnumeratorComparer.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByEnumeratorComparer.cs @@ -4,9 +4,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy { - using System; using System.Collections.Generic; - using System.Diagnostics; /// /// For cross partition order by queries we serve documents from the partition @@ -14,12 +12,8 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy /// If there is a tie, then we break the tie by picking the leftmost partition. /// internal sealed class OrderByEnumeratorComparer : IComparer - { - /// - /// The sort orders for the query (1 for each order by in the query). - /// Until composite indexing is released this will just be an array of length 1. - /// - private readonly IReadOnlyList sortOrders; + { + private readonly OrderByQueryResultComparer comparer; /// /// Initializes a new instance of the OrderByConsumeComparer class. @@ -27,17 +21,7 @@ internal sealed class OrderByEnumeratorComparer : IComparerThe sort orders for the query. public OrderByEnumeratorComparer(IReadOnlyList sortOrders) { - if (sortOrders == null) - { - throw new ArgumentNullException("Sort Orders array can not be null for an order by comparer."); - } - - if (sortOrders.Count == 0) - { - throw new ArgumentException("Sort Orders array can not be empty for an order by comparer."); - } - - this.sortOrders = new List(sortOrders); + this.comparer = new OrderByQueryResultComparer(sortOrders); } /// @@ -78,7 +62,7 @@ public int Compare( OrderByQueryResult result2 = new OrderByQueryResult(enumerator2.Current.Result.Enumerator.Current); // First compare the documents based on the sort order of the query. - int cmp = this.CompareOrderByItems(result1.OrderByItems, result2.OrderByItems); + int cmp = this.comparer.Compare(result1, result2); if (cmp != 0) { // If there is no tie just return that. @@ -88,56 +72,5 @@ public int Compare( // If there is a tie, then break the tie by picking the one from the left most partition. return string.CompareOrdinal(((FeedRangeEpk)enumerator1.FeedRangeState.FeedRange).Range.Min, ((FeedRangeEpk)enumerator2.FeedRangeState.FeedRange).Range.Min); } - - /// - /// Takes the items relevant to the sort and return an integer defining the relationship. - /// - /// The items relevant to the sort from the first partition. - /// The items relevant to the sort from the second partition. - /// The sort relationship. - /// - /// Suppose the query was "SELECT * FROM c ORDER BY c.name asc, c.age desc", - /// then items1 could be ["Brandon", 22] and items2 could be ["Felix", 28] - /// Then we would first compare "Brandon" to "Felix" and say that "Brandon" comes first in an ascending lex order (we don't even have to look at age). - /// If items1 was ["Brandon", 22] and items2 was ["Brandon", 23] then we would say have to look at the age to break the tie and in this case 23 comes first in a descending order. - /// Some examples of composite order by: http://www.dofactory.com/sql/order-by - /// - public int CompareOrderByItems(IReadOnlyList items1, IReadOnlyList items2) - { - if (object.ReferenceEquals(items1, items2)) - { - return 0; - } - - Debug.Assert( - items1 != null && items2 != null, - "Order-by items must be present."); - - Debug.Assert( - items1.Count == items2.Count, - "OrderByResult instances should have the same number of order-by items."); - - Debug.Assert( - items1.Count > 0, - "OrderByResult instances should have at least 1 order-by item."); - - Debug.Assert( - this.sortOrders.Count == items1.Count, - "SortOrders must match size of order-by items."); - - for (int i = 0; i < this.sortOrders.Count; ++i) - { - int cmp = ItemComparer.Instance.Compare( - items1[i].Item, - items2[i].Item); - - if (cmp != 0) - { - return this.sortOrders[i] != SortOrder.Descending ? cmp : -cmp; - } - } - - return 0; - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPage.cs index 5a482ba6e6..9bb2b3c3b5 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPage.cs @@ -28,8 +28,10 @@ public OrderByQueryPage(QueryPage queryPage) public QueryPage Page { get; } - public IEnumerator Enumerator { get; } - + public IEnumerator Enumerator { get; } + + public override int ItemCount => this.Page.ItemCount; + protected override ImmutableHashSet DerivedClassBannedHeaders => bannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPartitionRangePageAsyncEnumerator.cs index bf5bb863fe..49aedfc912 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryPartitionRangePageAsyncEnumerator.cs @@ -4,7 +4,8 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy { - using System; + using System; + using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Pagination; @@ -15,51 +16,93 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy internal sealed class OrderByQueryPartitionRangePageAsyncEnumerator : PartitionRangePageAsyncEnumerator, IPrefetcher { private readonly InnerEnumerator innerEnumerator; - private readonly BufferedPartitionRangePageAsyncEnumerator bufferedEnumerator; - - public OrderByQueryPartitionRangePageAsyncEnumerator( + private readonly BufferedPartitionRangePageAsyncEnumeratorBase bufferedEnumerator; + + public static OrderByQueryPartitionRangePageAsyncEnumerator Create( IQueryDataSource queryDataSource, SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, PartitionKey? partitionKey, QueryPaginationOptions queryPaginationOptions, - string filter, - CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) - { - this.StartOfPageState = feedRangeState.State; - this.innerEnumerator = new InnerEnumerator( + string filter, + PrefetchPolicy prefetchPolicy) + { + InnerEnumerator enumerator = new InnerEnumerator( queryDataSource, sqlQuerySpec, feedRangeState, partitionKey, queryPaginationOptions, - filter, - cancellationToken); - this.bufferedEnumerator = new BufferedPartitionRangePageAsyncEnumerator( - this.innerEnumerator, - cancellationToken); - } - + filter); + + BufferedPartitionRangePageAsyncEnumeratorBase bufferedEnumerator = prefetchPolicy switch + { + PrefetchPolicy.PrefetchSinglePage => new BufferedPartitionRangePageAsyncEnumerator(enumerator), + PrefetchPolicy.PrefetchAll => new FullyBufferedPartitionRangeAsyncEnumerator(enumerator), + _ => throw new ArgumentOutOfRangeException(nameof(prefetchPolicy)), + }; + + return new OrderByQueryPartitionRangePageAsyncEnumerator(enumerator, bufferedEnumerator, feedRangeState); + } + + private OrderByQueryPartitionRangePageAsyncEnumerator( + InnerEnumerator innerEnumerator, + BufferedPartitionRangePageAsyncEnumeratorBase bufferedEnumerator, + FeedRangeState feedRangeState) + : base(feedRangeState) + { + this.innerEnumerator = innerEnumerator ?? throw new ArgumentNullException(nameof(innerEnumerator)); + this.bufferedEnumerator = bufferedEnumerator ?? throw new ArgumentNullException(nameof(bufferedEnumerator)); + this.StartOfPageState = feedRangeState.State; + } + public SqlQuerySpec SqlQuerySpec => this.innerEnumerator.SqlQuerySpec; public QueryPaginationOptions QueryPaginationOptions => this.innerEnumerator.QueryPaginationOptions; public string Filter => this.innerEnumerator.Filter; - public QueryState StartOfPageState { get; private set; } + public QueryState StartOfPageState { get; private set; } + + public int BufferedResultCount => this.bufferedEnumerator.BufferedItemCount; - public override ValueTask DisposeAsync() => default; + public override ValueTask DisposeAsync() + { + // the innerEnumerator is passed to the bufferedEnumerator + return this.bufferedEnumerator.DisposeAsync(); + } protected override async Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken) { this.StartOfPageState = this.FeedRangeState.State; - await this.bufferedEnumerator.MoveNextAsync(trace); + await this.bufferedEnumerator.MoveNextAsync(trace, cancellationToken); return this.bufferedEnumerator.Current; } - public ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) => this.bufferedEnumerator.PrefetchAsync(trace, cancellationToken); - + public ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.bufferedEnumerator.PrefetchAsync(trace, cancellationToken); + } + + public OrderByQueryPartitionRangePageAsyncEnumerator CloneAsFullyBufferedEnumerator() + { + if (this.Current.Failed) + { + throw new InvalidOperationException($"{nameof(CloneAsFullyBufferedEnumerator)} is valid only if the enumerator has not failed"); + } + + InnerEnumerator innerEnumerator = this.innerEnumerator.CloneWithMaxPageSize(); + + FullyBufferedPartitionRangeAsyncEnumerator bufferedEnumerator = new FullyBufferedPartitionRangeAsyncEnumerator( + innerEnumerator, + new List { this.Current.Result }); + + return new OrderByQueryPartitionRangePageAsyncEnumerator( + innerEnumerator, + bufferedEnumerator, + this.FeedRangeState); + } + private sealed class InnerEnumerator : PartitionRangePageAsyncEnumerator { private readonly IQueryDataSource queryDataSource; @@ -70,9 +113,8 @@ public InnerEnumerator( FeedRangeState feedRangeState, PartitionKey? partitionKey, QueryPaginationOptions queryPaginationOptions, - string filter, - CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) + string filter) + : base(feedRangeState) { this.queryDataSource = queryDataSource ?? throw new ArgumentNullException(nameof(queryDataSource)); this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); @@ -87,8 +129,24 @@ public InnerEnumerator( public QueryPaginationOptions QueryPaginationOptions { get; } - public string Filter { get; } - + public string Filter { get; } + + public InnerEnumerator CloneWithMaxPageSize() + { + QueryPaginationOptions options = new QueryPaginationOptions( + pageSizeHint: int.MaxValue, + optimisticDirectExecute: this.QueryPaginationOptions.OptimisticDirectExecute, + additionalHeaders: this.QueryPaginationOptions.AdditionalHeaders); + + return new InnerEnumerator( + this.queryDataSource, + this.SqlQuerySpec, + this.FeedRangeState, + this.PartitionKey, + options, + this.Filter); + } + public override ValueTask DisposeAsync() => default; protected override async Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResult.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResult.cs index e3f46bd848..ed43b01794 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResult.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResult.cs @@ -25,8 +25,10 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy /// /// internal readonly struct OrderByQueryResult - { - private readonly CosmosObject cosmosObject; + { + private readonly CosmosObject cosmosObject; + + private readonly IReadOnlyList orderByItems; public OrderByQueryResult(CosmosElement cosmosElement) { @@ -40,7 +42,8 @@ public OrderByQueryResult(CosmosElement cosmosElement) throw new ArgumentException($"{nameof(cosmosElement)} must not be an object."); } - this.cosmosObject = cosmosObject; + this.cosmosObject = cosmosObject; + this.orderByItems = GetOrderByItems(cosmosObject); } /// @@ -51,17 +54,17 @@ public string Rid get { // cassandra row uses __sys_rid as opposed to _rid - if (!this.cosmosObject.TryGetValue("_rid", out CosmosElement cosmosElement)) + if (!this.cosmosObject.TryGetValue(FieldNames.Rid, out CosmosElement cosmosElement)) { - if (!this.cosmosObject.TryGetValue("__sys_rid", out cosmosElement)) + if (!this.cosmosObject.TryGetValue(FieldNames.CassandraRid, out cosmosElement)) { - throw new InvalidOperationException($"Underlying object does not have an '_rid' or '__sys_rid' field."); + throw new InvalidOperationException($"Underlying object does not have an '{FieldNames.Rid}' or '{FieldNames.CassandraRid}' field."); } } if (!(cosmosElement is CosmosString cosmosString)) { - throw new InvalidOperationException($"'_rid' or '__sys_rid' field was not a string."); + throw new InvalidOperationException($"'{FieldNames.Rid}' or ' {FieldNames.CassandraRid} ' field.g."); } return cosmosString.Value; @@ -71,29 +74,7 @@ public string Rid /// /// Gets the order by items from the document. /// - public IReadOnlyList OrderByItems - { - get - { - if (!this.cosmosObject.TryGetValue("orderByItems", out CosmosElement cosmosElement)) - { - throw new InvalidOperationException($"Underlying object does not have an 'orderByItems' field."); - } - - if (!(cosmosElement is CosmosArray cosmosArray)) - { - throw new InvalidOperationException($"orderByItems field was not an array."); - } - - List orderByItems = new List(cosmosArray.Count); - foreach (CosmosElement orderByItem in cosmosArray) - { - orderByItems.Add(new OrderByItem(orderByItem)); - } - - return orderByItems; - } - } + public IReadOnlyList OrderByItems => this.orderByItems; /// /// Gets the actual document. @@ -102,13 +83,45 @@ public CosmosElement Payload { get { - if (!this.cosmosObject.TryGetValue("payload", out CosmosElement cosmosElement)) + if (!this.cosmosObject.TryGetValue(FieldNames.Payload, out CosmosElement cosmosElement)) { return CosmosUndefined.Create(); } return cosmosElement; } + } + + private static IReadOnlyList GetOrderByItems(CosmosObject cosmosObject) + { + if (!cosmosObject.TryGetValue(FieldNames.OrderByItems, out CosmosElement cosmosElement)) + { + throw new InvalidOperationException($"Underlying object does not have an 'orderByItems' field."); + } + + if (!(cosmosElement is CosmosArray cosmosArray)) + { + throw new InvalidOperationException($"orderByItems field was not an array."); + } + + List orderByItems = new List(cosmosArray.Count); + foreach (CosmosElement orderByItem in cosmosArray) + { + orderByItems.Add(new OrderByItem(orderByItem)); + } + + return orderByItems; + } + + private static class FieldNames + { + public const string OrderByItems = "orderByItems"; + + public const string Payload = "payload"; + + public const string Rid = "_rid"; + + public const string CassandraRid = "__sys_rid"; } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResultComparer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResultComparer.cs new file mode 100644 index 0000000000..929ccc5e7b --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByQueryResultComparer.cs @@ -0,0 +1,85 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy +{ + using System.Collections.Generic; + using System.Diagnostics; + + internal sealed class OrderByQueryResultComparer : IComparer + { + private readonly IReadOnlyList sortOrders; + + public OrderByQueryResultComparer(IReadOnlyList sortOrders) + { + if (sortOrders == null) + { + throw new System.ArgumentNullException("Sort Orders array can not be null for an order by comparer."); + } + + if (sortOrders.Count == 0) + { + throw new System.ArgumentException("Sort Orders array can not be empty for an order by comparer."); + } + + this.sortOrders = sortOrders; + } + + public int Compare(OrderByQueryResult x, OrderByQueryResult y) + { + return this.CompareOrderByItems(x.OrderByItems, y.OrderByItems); + } + + /// + /// Takes the items relevant to the sort and return an integer defining the relationship. + /// + /// The items relevant to the sort from the first partition. + /// The items relevant to the sort from the second partition. + /// The sort relationship. + /// + /// Suppose the query was "SELECT * FROM c ORDER BY c.name asc, c.age desc", + /// then items1 could be ["Brandon", 22] and items2 could be ["Felix", 28] + /// Then we would first compare "Brandon" to "Felix" and say that "Brandon" comes first in an ascending lex order (we don't even have to look at age). + /// If items1 was ["Brandon", 22] and items2 was ["Brandon", 23] then we would say have to look at the age to break the tie and in this case 23 comes first in a descending order. + /// Some examples of composite order by: http://www.dofactory.com/sql/order-by + /// + private int CompareOrderByItems(IReadOnlyList items1, IReadOnlyList items2) + { + if (object.ReferenceEquals(items1, items2)) + { + return 0; + } + + Debug.Assert( + items1 != null && items2 != null, + "Order-by items must be present."); + + Debug.Assert( + items1.Count == items2.Count, + "OrderByResult instances should have the same number of order-by items."); + + Debug.Assert( + items1.Count > 0, + "OrderByResult instances should have at least 1 order-by item."); + + Debug.Assert( + this.sortOrders.Count == items1.Count, + "SortOrders must match size of order-by items."); + + for (int i = 0; i < this.sortOrders.Count; ++i) + { + int cmp = ItemComparer.Instance.Compare( + items1[i].Item, + items2[i].Item); + + if (cmp != 0) + { + return this.sortOrders[i] != SortOrder.Descending ? cmp : -cmp; + } + } + + return 0; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs index b84a36870e..d9b564b5f3 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs @@ -27,14 +27,11 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel internal sealed class ParallelCrossPartitionQueryPipelineStage : IQueryPipelineStage { private readonly CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator; - private CancellationToken cancellationToken; private ParallelCrossPartitionQueryPipelineStage( - CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator, - CancellationToken cancellationToken) + CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator) { this.crossPartitionRangePageAsyncEnumerator = crossPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(crossPartitionRangePageAsyncEnumerator)); - this.cancellationToken = cancellationToken; } public TryCatch Current { get; private set; } @@ -48,14 +45,14 @@ public ValueTask DisposeAsync() // 1) We fully drain from the left most partition before moving on to the next partition // 2) We drain only full pages from the document producer so we aren't left with a partial page // otherwise we would need to add to the continuation token how many items to skip over on that page. - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.crossPartitionRangePageAsyncEnumerator.MoveNextAsync(trace)) + if (!await this.crossPartitionRangePageAsyncEnumerator.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -97,7 +94,7 @@ public async ValueTask MoveNextAsync(ITrace trace) foreach (FeedRangeState feedRangeState in feedRangeStates.Skip(1)) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (feedRangeState.State != null) { @@ -120,12 +117,12 @@ public async ValueTask MoveNextAsync(ITrace trace) backendQueryPage.Documents, backendQueryPage.RequestCharge, backendQueryPage.ActivityId, - backendQueryPage.ResponseLengthInBytes, backendQueryPage.CosmosQueryExecutionInfo, distributionPlanSpec: default, backendQueryPage.DisallowContinuationTokenMessage, backendQueryPage.AdditionalHeaders, - queryState); + queryState, + backendQueryPage.Streaming); this.Current = TryCatch.FromResult(crossPartitionQueryPage); return true; @@ -139,8 +136,7 @@ public static TryCatch MonadicCreate( QueryPaginationOptions queryPaginationOptions, int maxConcurrency, PrefetchPolicy prefetchPolicy, - CosmosElement continuationToken, - CancellationToken cancellationToken) + CosmosElement continuationToken) { if (targetRanges == null) { @@ -162,14 +158,13 @@ public static TryCatch MonadicCreate( CrossPartitionRangePageAsyncEnumerator crossPartitionPageEnumerator = new CrossPartitionRangePageAsyncEnumerator( feedRangeProvider: documentContainer, - createPartitionRangeEnumerator: ParallelCrossPartitionQueryPipelineStage.MakeCreateFunction(documentContainer, sqlQuerySpec, queryPaginationOptions, partitionKey, cancellationToken), + createPartitionRangeEnumerator: ParallelCrossPartitionQueryPipelineStage.MakeCreateFunction(documentContainer, sqlQuerySpec, queryPaginationOptions, partitionKey), comparer: Comparer.Singleton, maxConcurrency: maxConcurrency, prefetchPolicy: prefetchPolicy, - state: state, - cancellationToken: cancellationToken); + state: state); - ParallelCrossPartitionQueryPipelineStage stage = new ParallelCrossPartitionQueryPipelineStage(crossPartitionPageEnumerator, cancellationToken); + ParallelCrossPartitionQueryPipelineStage stage = new ParallelCrossPartitionQueryPipelineStage(crossPartitionPageEnumerator); return TryCatch.FromResult(stage); } @@ -248,20 +243,12 @@ private static CreatePartitionRangePageAsyncEnumerator Ma IQueryDataSource queryDataSource, SqlQuerySpec sqlQuerySpec, QueryPaginationOptions queryPaginationOptions, - Cosmos.PartitionKey? partitionKey, - CancellationToken cancellationToken) => (FeedRangeState feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( + Cosmos.PartitionKey? partitionKey) => (FeedRangeState feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( queryDataSource, sqlQuerySpec, feedRangeState, partitionKey, - queryPaginationOptions, - cancellationToken); - - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - this.crossPartitionRangePageAsyncEnumerator.SetCancellationToken(cancellationToken); - } + queryPaginationOptions); private sealed class Comparer : IComparer> { diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs index e2918a366e..5744ed734b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs @@ -24,9 +24,8 @@ public QueryPartitionRangePageAsyncEnumerator( SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, Cosmos.PartitionKey? partitionKey, - QueryPaginationOptions queryPaginationOptions, - CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) + QueryPaginationOptions queryPaginationOptions) + : base(feedRangeState) { this.queryDataSource = queryDataSource ?? throw new ArgumentNullException(nameof(queryDataSource)); this.sqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs index 162408e6ff..0e09e2c159 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Client.cs @@ -25,9 +25,8 @@ private sealed class ClientDCountQueryPipelineStage : DCountQueryPipelineStage private ClientDCountQueryPipelineStage( IQueryPipelineStage source, long count, - DCountInfo info, - CancellationToken cancellationToken) - : base(source, count, info, cancellationToken) + DCountInfo info) + : base(source, count, info) { // all the work is done in the base constructor. } @@ -35,7 +34,6 @@ private ClientDCountQueryPipelineStage( public static TryCatch MonadicCreate( DCountInfo info, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (monadicCreatePipelineStage == null) @@ -43,7 +41,7 @@ public static TryCatch MonadicCreate( throw new ArgumentNullException(nameof(monadicCreatePipelineStage)); } - TryCatch tryCreateSource = monadicCreatePipelineStage(continuationToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(continuationToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -52,15 +50,14 @@ public static TryCatch MonadicCreate( ClientDCountQueryPipelineStage stage = new ClientDCountQueryPipelineStage( source: tryCreateSource.Result, count: 0, - info: info, - cancellationToken: cancellationToken); + info: info); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -73,9 +70,8 @@ public override async ValueTask MoveNextAsync(ITrace trace) } double requestCharge = 0; - long responseLengthBytes = 0; IReadOnlyDictionary additionalHeaders = null; - while (await this.inputStage.MoveNextAsync(trace)) + while (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { TryCatch tryGetPageFromSource = this.inputStage.Current; if (tryGetPageFromSource.Failed) @@ -87,10 +83,9 @@ public override async ValueTask MoveNextAsync(ITrace trace) QueryPage sourcePage = tryGetPageFromSource.Result; requestCharge += sourcePage.RequestCharge; - responseLengthBytes += sourcePage.ResponseLengthInBytes; additionalHeaders = sourcePage.AdditionalHeaders; - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); this.count += sourcePage.Documents.Count; } @@ -105,12 +100,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: finalResult, requestCharge: requestCharge, activityId: default, - responseLengthInBytes: responseLengthBytes, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: additionalHeaders, - state: default); + state: default, + streaming: default); this.Current = TryCatch.FromResult(queryPage); this.returnedFinalPage = true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs index 0970be1706..84f8cfff64 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.Compute.cs @@ -29,9 +29,8 @@ private sealed class ComputeDCountQueryPipelineStage : DCountQueryPipelineStage private ComputeDCountQueryPipelineStage( IQueryPipelineStage source, long count, - DCountInfo info, - CancellationToken cancellationToken) - : base(source, count, info, cancellationToken) + DCountInfo info) + : base(source, count, info) { // all the work is done in the base constructor. } @@ -39,11 +38,8 @@ private ComputeDCountQueryPipelineStage( public static TryCatch MonadicCreate( DCountInfo info, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { - cancellationToken.ThrowIfCancellationRequested(); - DCountContinuationToken dcountContinuationToken; if (continuationToken != null) { @@ -68,7 +64,7 @@ public static TryCatch MonadicCreate( } else { - tryCreateSource = monadicCreatePipelineStage(dcountContinuationToken.SourceContinuationToken, cancellationToken); + tryCreateSource = monadicCreatePipelineStage(dcountContinuationToken.SourceContinuationToken); } if (tryCreateSource.Failed) @@ -79,15 +75,14 @@ public static TryCatch MonadicCreate( ComputeDCountQueryPipelineStage stage = new ComputeDCountQueryPipelineStage( tryCreateSource.Result, dcountContinuationToken.Count, - info, - cancellationToken); + info); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -102,7 +97,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) // Draining aggregates is broken down into two stages QueryPage queryPage; - if (await this.inputStage.MoveNextAsync(trace)) + if (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { // Stage 1: // Drain the aggregates fully from all continuations and all partitions @@ -115,7 +110,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) } QueryPage sourcePage = tryGetSourcePage.Result; - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); this.count += sourcePage.Documents.Count; DCountContinuationToken dcountContinuationToken = new DCountContinuationToken( @@ -126,12 +121,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: EmptyResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: queryState); + state: queryState, + streaming: sourcePage.Streaming); queryPage = emptyPage; } @@ -150,12 +145,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: finalResult, requestCharge: default, activityId: default, - responseLengthInBytes: default, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: default); + state: default, + streaming: default); queryPage = finalPage; this.returnedFinalPage = true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.cs index 067379cd5e..3f4079ad45 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/DCount/DCountQueryPipelineStage.cs @@ -35,14 +35,12 @@ internal abstract partial class DCountQueryPipelineStage : QueryPipelineStageBas /// The source component that will supply the local aggregates from multiple continuations and partitions. /// The actual dcount that will be reported. /// Metadata about the original dcount query that is elided in the rewritten query - /// The cancellation token for cooperative yeilding. /// This constructor is private since there is some async initialization that needs to happen in CreateAsync(). public DCountQueryPipelineStage( IQueryPipelineStage source, long count, - DCountInfo info, - CancellationToken cancellationToken) - : base(source, cancellationToken) + DCountInfo info) + : base(source) { this.count = count; this.info = info; @@ -52,18 +50,15 @@ public static TryCatch MonadicCreate( ExecutionEnvironment executionEnvironment, DCountInfo info, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch { ExecutionEnvironment.Client => ClientDCountQueryPipelineStage.MonadicCreate( info, continuationToken, - cancellationToken, monadicCreatePipelineStage), ExecutionEnvironment.Compute => ComputeDCountQueryPipelineStage.MonadicCreate( info, continuationToken, - cancellationToken, monadicCreatePipelineStage), _ => throw new ArgumentException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}."), }; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs index c250193a60..b8536f6c05 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Client.cs @@ -31,9 +31,8 @@ private sealed class ClientDistinctQueryPipelineStage : DistinctQueryPipelineSta private ClientDistinctQueryPipelineStage( DistinctQueryType distinctQueryType, DistinctMap distinctMap, - IQueryPipelineStage source, - CancellationToken cancellationToken) - : base(distinctMap, source, cancellationToken) + IQueryPipelineStage source) + : base(distinctMap, source) { if ((distinctQueryType != DistinctQueryType.Unordered) && (distinctQueryType != DistinctQueryType.Ordered)) { @@ -45,7 +44,6 @@ private ClientDistinctQueryPipelineStage( public static TryCatch MonadicCreate( CosmosElement requestContinuation, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, DistinctQueryType distinctQueryType) { @@ -101,7 +99,7 @@ public static TryCatch MonadicCreate( sourceToken = null; } - TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken); if (!tryCreateSource.Succeeded) { return TryCatch.FromException(tryCreateSource.Exception); @@ -111,20 +109,19 @@ public static TryCatch MonadicCreate( new ClientDistinctQueryPipelineStage( distinctQueryType, tryCreateDistinctMap.Result, - tryCreateSource.Result, - cancellationToken)); + tryCreateSource.Result)); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -142,7 +139,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) List distinctResults = new List(); foreach (CosmosElement document in sourcePage.Documents) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (this.distinctMap.Add(document, out UInt128 _)) { @@ -171,12 +168,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: distinctResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: state); + state: state, + streaming: sourcePage.Streaming); } else { @@ -184,12 +181,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: distinctResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: ClientDistinctQueryPipelineStage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: null); + state: null, + streaming: sourcePage.Streaming); } this.Current = TryCatch.FromResult(queryPage); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs index 06921710c4..43489e6f30 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.Compute.cs @@ -28,15 +28,13 @@ private sealed class ComputeDistinctQueryPipelineStage : DistinctQueryPipelineSt private ComputeDistinctQueryPipelineStage( DistinctMap distinctMap, - IQueryPipelineStage source, - CancellationToken cancellationToken) - : base(distinctMap, source, cancellationToken) + IQueryPipelineStage source) + : base(distinctMap, source) { } public static TryCatch MonadicCreate( CosmosElement requestContinuation, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, DistinctQueryType distinctQueryType) { @@ -68,7 +66,7 @@ public static TryCatch MonadicCreate( return TryCatch.FromException(tryCreateDistinctMap.Exception); } - TryCatch tryCreateSource = monadicCreatePipelineStage(distinctContinuationToken.SourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(distinctContinuationToken.SourceToken); if (!tryCreateSource.Succeeded) { return TryCatch.FromException(tryCreateSource.Exception); @@ -77,18 +75,17 @@ public static TryCatch MonadicCreate( return TryCatch.FromResult( new ComputeDistinctQueryPipelineStage( tryCreateDistinctMap.Result, - tryCreateSource.Result, - cancellationToken)); + tryCreateSource.Result)); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -129,12 +126,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: distinctResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: ComputeDistinctQueryPipelineStage.UseTryGetContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: queryState); + state: queryState, + streaming: sourcePage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.cs index 088c64cc23..c929f84dcb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Distinct/DistinctQueryPipelineStage.cs @@ -5,9 +5,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct { using System; - using System.Threading; using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; using Microsoft.Azure.Cosmos.Query.Core.Monads; /// @@ -30,9 +28,8 @@ internal abstract partial class DistinctQueryPipelineStage : QueryPipelineStageB protected DistinctQueryPipelineStage( DistinctMap distinctMap, - IQueryPipelineStage source, - CancellationToken cancellationToken) - : base(source, cancellationToken) + IQueryPipelineStage source) + : base(source) { this.distinctMap = distinctMap ?? throw new ArgumentNullException(nameof(distinctMap)); } @@ -40,18 +37,15 @@ protected DistinctQueryPipelineStage( public static TryCatch MonadicCreate( ExecutionEnvironment executionEnvironment, CosmosElement requestContinuation, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, DistinctQueryType distinctQueryType) => executionEnvironment switch { ExecutionEnvironment.Client => ClientDistinctQueryPipelineStage.MonadicCreate( requestContinuation, - cancellationToken, monadicCreatePipelineStage, distinctQueryType), ExecutionEnvironment.Compute => ComputeDistinctQueryPipelineStage.MonadicCreate( requestContinuation, - cancellationToken, monadicCreatePipelineStage, distinctQueryType), _ => throw new ArgumentException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}."), diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/EmptyQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/EmptyQueryPipelineStage.cs index 78c4fe9769..298de02386 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/EmptyQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/EmptyQueryPipelineStage.cs @@ -29,14 +29,9 @@ public ValueTask DisposeAsync() return this.emptyAsyncEnumerator.DisposeAsync(); } - public ValueTask MoveNextAsync(ITrace trace) + public ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { return this.emptyAsyncEnumerator.MoveNextAsync(trace); } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - // No work to do since this enumerator is fully sync. - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/FaultedQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/FaultedQueryPipelineStage.cs index 01eb048472..bb90db3603 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/FaultedQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/FaultedQueryPipelineStage.cs @@ -33,14 +33,9 @@ public ValueTask DisposeAsync() return this.justAsyncEnumerator.DisposeAsync(); } - public ValueTask MoveNextAsync(ITrace trace) + public ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { return this.justAsyncEnumerator.MoveNextAsync(trace); } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - // No work to do with since this enumerator is fully sync. - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs index cea8f6e566..6ed1804abf 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Client.cs @@ -6,7 +6,6 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.GroupBy { using System; using System.Collections.Generic; - using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; @@ -22,16 +21,14 @@ private sealed class ClientGroupByQueryPipelineStage : GroupByQueryPipelineStage public const string ContinuationTokenNotSupportedWithGroupBy = "Continuation token is not supported for queries with GROUP BY. Do not use FeedResponse.ResponseContinuation or remove the GROUP BY from the query."; private ClientGroupByQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, GroupingTable groupingTable, int pageSize) - : base(source, cancellationToken, groupingTable, pageSize) + : base(source, groupingTable, pageSize) { } public static TryCatch MonadicCreate( CosmosElement requestContinuation, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, @@ -51,7 +48,7 @@ public static TryCatch MonadicCreate( return TryCatch.FromException(tryCreateGroupingTable.Exception); } - TryCatch tryCreateSource = monadicCreatePipelineStage(requestContinuation, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(requestContinuation); if (tryCreateSource.Failed) { return tryCreateSource; @@ -59,16 +56,15 @@ public static TryCatch MonadicCreate( IQueryPipelineStage stage = new ClientGroupByQueryPipelineStage( tryCreateSource.Result, - cancellationToken, tryCreateGroupingTable.Result, pageSize); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -84,12 +80,11 @@ public override async ValueTask MoveNextAsync(ITrace trace) // Draining GROUP BY is broken down into two stages: double requestCharge = 0.0; - long responseLengthInBytes = 0; IReadOnlyDictionary addtionalHeaders = null; - while (await this.inputStage.MoveNextAsync(trace)) + while (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); // Stage 1: // Drain the groupings fully from all continuation and all partitions @@ -103,7 +98,6 @@ public override async ValueTask MoveNextAsync(ITrace trace) QueryPage sourcePage = tryGetSourcePage.Result; requestCharge += sourcePage.RequestCharge; - responseLengthInBytes += sourcePage.ResponseLengthInBytes; addtionalHeaders = sourcePage.AdditionalHeaders; this.AggregateGroupings(sourcePage.Documents); } @@ -120,12 +114,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: results, requestCharge: requestCharge, activityId: default, - responseLengthInBytes: responseLengthInBytes, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: ClientGroupByQueryPipelineStage.ContinuationTokenNotSupportedWithGroupBy, additionalHeaders: addtionalHeaders, - state: default); + state: default, + streaming: null); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs index 079c69465f..2692e9ba6b 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.Compute.cs @@ -9,7 +9,6 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.GroupBy using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Query.Core.Exceptions; using Microsoft.Azure.Cosmos.Query.Core.Metrics; using Microsoft.Azure.Cosmos.Query.Core.Monads; @@ -29,16 +28,14 @@ private sealed class ComputeGroupByQueryPipelineStage : GroupByQueryPipelineStag private ComputeGroupByQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, GroupingTable groupingTable, int pageSize) - : base(source, cancellationToken, groupingTable, pageSize) + : base(source, groupingTable, pageSize) { } public static TryCatch MonadicCreate( CosmosElement requestContinuation, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, @@ -71,7 +68,7 @@ public static TryCatch MonadicCreate( } else { - tryCreateSource = monadicCreatePipelineStage(groupByContinuationToken.SourceContinuationToken, cancellationToken); + tryCreateSource = monadicCreatePipelineStage(groupByContinuationToken.SourceContinuationToken); } if (!tryCreateSource.Succeeded) @@ -94,14 +91,13 @@ public static TryCatch MonadicCreate( return TryCatch.FromResult( new ComputeGroupByQueryPipelineStage( tryCreateSource.Result, - cancellationToken, tryCreateGroupingTable.Result, pageSize)); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -116,7 +112,7 @@ public override async ValueTask MoveNextAsync(ITrace trace) // Draining GROUP BY is broken down into two stages: QueryPage queryPage; - if (await this.inputStage.MoveNextAsync(trace)) + if (await this.inputStage.MoveNextAsync(trace, cancellationToken)) { // Stage 1: // Drain the groupings fully from all continuation and all partitions @@ -142,12 +138,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: EmptyResults, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: null, additionalHeaders: sourcePage.AdditionalHeaders, - state: state); + state: state, + streaming: sourcePage.Streaming); } else { @@ -173,12 +169,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: results, requestCharge: default, activityId: default, - responseLengthInBytes: default, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: state); + state: state, + streaming: null); } this.Current = TryCatch.FromResult(queryPage); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs index f42be927cc..58e400b72e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/GroupBy/GroupByQueryPipelineStage.cs @@ -53,10 +53,9 @@ internal abstract partial class GroupByQueryPipelineStage : QueryPipelineStageBa protected GroupByQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, GroupingTable groupingTable, int pageSize) - : base(source, cancellationToken) + : base(source) { this.groupingTable = groupingTable ?? throw new ArgumentNullException(nameof(groupingTable)); this.pageSize = pageSize; @@ -65,7 +64,6 @@ protected GroupByQueryPipelineStage( public static TryCatch MonadicCreate( ExecutionEnvironment executionEnvironment, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage, IReadOnlyList aggregates, IReadOnlyDictionary groupByAliasToAggregateType, @@ -75,7 +73,6 @@ public static TryCatch MonadicCreate( { ExecutionEnvironment.Client => ClientGroupByQueryPipelineStage.MonadicCreate( continuationToken, - cancellationToken, monadicCreatePipelineStage, aggregates, groupByAliasToAggregateType, @@ -84,7 +81,6 @@ public static TryCatch MonadicCreate( pageSize), ExecutionEnvironment.Compute => ComputeGroupByQueryPipelineStage.MonadicCreate( continuationToken, - cancellationToken, monadicCreatePipelineStage, aggregates, groupByAliasToAggregateType, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IQueryPipelineStage.cs index 11796385cb..151ba5db9a 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IQueryPipelineStage.cs @@ -4,17 +4,12 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline { - using System; - using System.Collections.Generic; using System.Threading; - using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Tracing; internal interface IQueryPipelineStage : ITracingAsyncEnumerator> { - void SetCancellationToken(CancellationToken cancellationToken); } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IndexUtilizationHelper.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IndexUtilizationHelper.cs new file mode 100644 index 0000000000..cb7a7add84 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/IndexUtilizationHelper.cs @@ -0,0 +1,48 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline +{ + using System.Collections.Generic; + + internal static class IndexUtilizationHelper + { + public static IReadOnlyDictionary AccumulateIndexUtilization( + IReadOnlyDictionary cumulativeHeaders, + IReadOnlyDictionary currentHeaders) + { + if (cumulativeHeaders == null) + { + return currentHeaders; + } + + if (currentHeaders == null) + { + return cumulativeHeaders; + } + + // Index utilization is supposed to be static across partitions and round trips. + if (currentHeaders.ContainsKey(Documents.HttpConstants.HttpHeaders.IndexUtilization) || + !cumulativeHeaders.ContainsKey(Documents.HttpConstants.HttpHeaders.IndexUtilization)) + { + return currentHeaders; + } + + // We could try to cast currentHeaders to a dictionary, but this can cause unpleasant side effects with singletons + Dictionary additionalHeaders = new Dictionary(); + + // Until we get the new .NET version, we need to copy the headers manually. + foreach (KeyValuePair header in currentHeaders) + { + additionalHeaders.Add(header.Key, header.Value); + } + + additionalHeaders.Add( + Documents.HttpConstants.HttpHeaders.IndexUtilization, + cumulativeHeaders[Documents.HttpConstants.HttpHeaders.IndexUtilization]); + + return additionalHeaders; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/LazyQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/LazyQueryPipelineStage.cs index 3f7a7d316e..7e83643cc2 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/LazyQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/LazyQueryPipelineStage.cs @@ -14,12 +14,10 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline internal sealed class LazyQueryPipelineStage : IQueryPipelineStage { private readonly AsyncLazy> lazyTryCreateStage; - private CancellationToken cancellationToken; - public LazyQueryPipelineStage(AsyncLazy> lazyTryCreateStage, CancellationToken cancellationToken) + public LazyQueryPipelineStage(AsyncLazy> lazyTryCreateStage) { this.lazyTryCreateStage = lazyTryCreateStage ?? throw new ArgumentNullException(nameof(lazyTryCreateStage)); - this.cancellationToken = cancellationToken; } public TryCatch Current { get; private set; } @@ -38,14 +36,14 @@ public ValueTask DisposeAsync() return default; } - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - TryCatch tryCreateStage = await this.lazyTryCreateStage.GetValueAsync(trace, this.cancellationToken); + TryCatch tryCreateStage = await this.lazyTryCreateStage.GetValueAsync(trace, cancellationToken); if (tryCreateStage.Failed) { this.Current = TryCatch.FromException(tryCreateStage.Exception); @@ -53,8 +51,7 @@ public async ValueTask MoveNextAsync(ITrace trace) } IQueryPipelineStage stage = tryCreateStage.Result; - stage.SetCancellationToken(this.cancellationToken); - if (!await stage.MoveNextAsync(trace)) + if (!await stage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -63,10 +60,5 @@ public async ValueTask MoveNextAsync(ITrace trace) this.Current = stage.Current; return true; } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/MonadicCreatePipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/MonadicCreatePipelineStage.cs index 9067eb471b..cffac556e0 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/MonadicCreatePipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/MonadicCreatePipelineStage.cs @@ -8,5 +8,5 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Query.Core.Monads; - internal delegate TryCatch MonadicCreatePipelineStage(CosmosElement continuationToken, CancellationToken cancellationToken); + internal delegate TryCatch MonadicCreatePipelineStage(CosmosElement continuationToken); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/NameCacheStaleRetryQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/NameCacheStaleRetryQueryPipelineStage.cs index 177589193c..50fbb31b35 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/NameCacheStaleRetryQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/NameCacheStaleRetryQueryPipelineStage.cs @@ -36,9 +36,9 @@ public ValueTask DisposeAsync() return this.currentQueryPipelineStage.DisposeAsync(); } - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - if (!await this.currentQueryPipelineStage.MoveNextAsync(trace)) + if (!await this.currentQueryPipelineStage.MoveNextAsync(trace, cancellationToken)) { return false; } @@ -61,16 +61,11 @@ await this.cosmosQueryContext.QueryClient.ForceRefreshCollectionCacheAsync( this.alreadyRetried = true; await this.currentQueryPipelineStage.DisposeAsync(); this.currentQueryPipelineStage = this.queryPipelineStageFactory(); - return await this.MoveNextAsync(trace); + return await this.MoveNextAsync(trace, cancellationToken); } } return true; } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.currentQueryPipelineStage.SetCancellationToken(cancellationToken); - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index 7e571d0a41..8bad485a32 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -58,9 +58,9 @@ public ValueTask DisposeAsync() return this.inner.Failed ? default : this.inner.Result.DisposeAsync(); } - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace)); + TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace, cancellationToken)); bool success = hasNext.Succeeded && hasNext.Result; if (this.executionState == ExecutionState.OptimisticDirectExecution) { @@ -91,7 +91,7 @@ public async ValueTask MoveNextAsync(ITrace trace) { // This is where we will unwrap tne continuation token and extract the client distribution plan // Pipelines to handle client distribution would be generated here - success = await this.SwitchToFallbackPipelineAsync(continuationToken: null, trace); + success = await this.SwitchToFallbackPipelineAsync(continuationToken: null, trace, cancellationToken); } this.previousRequiresDistribution = requiresDistribution; @@ -99,18 +99,13 @@ public async ValueTask MoveNextAsync(ITrace trace) } else if (isPartitionSplitException) { - success = await this.SwitchToFallbackPipelineAsync(continuationToken: UnwrapContinuationToken(this.continuationToken), trace); + success = await this.SwitchToFallbackPipelineAsync(continuationToken: UnwrapContinuationToken(this.continuationToken), trace, cancellationToken); } } return success; } - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.inner.Try(pipelineStage => pipelineStage.SetCancellationToken(cancellationToken)); - } - private static CosmosElement UnwrapContinuationToken(CosmosElement continuationToken) { if (continuationToken == null) return null; @@ -122,7 +117,7 @@ private static CosmosElement UnwrapContinuationToken(CosmosElement continuationT return CosmosArray.Create(backendContinuationToken); } - private async Task SwitchToFallbackPipelineAsync(CosmosElement continuationToken, ITrace trace) + private async Task SwitchToFallbackPipelineAsync(CosmosElement continuationToken, ITrace trace, CancellationToken cancellationToken) { Debug.Assert(this.executionState == ExecutionState.OptimisticDirectExecution, "OptimisticDirectExecuteQueryPipelineStage Assert!", "Only OptimisticDirectExecute pipeline can create this fallback pipeline"); this.executionState = ExecutionState.SpecializedDocumentQueryExecution; @@ -135,7 +130,7 @@ private async Task SwitchToFallbackPipelineAsync(CosmosElement continuatio return false; } - return await this.inner.Result.MoveNextAsync(trace); + return await this.inner.Result.MoveNextAsync(trace, cancellationToken); } public static TryCatch MonadicCreate( @@ -182,19 +177,14 @@ public ValueTask DisposeAsync() return this.queryPartitionRangePageAsyncEnumerator.DisposeAsync(); } - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.queryPartitionRangePageAsyncEnumerator.SetCancellationToken(cancellationToken); - } - - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.queryPartitionRangePageAsyncEnumerator.MoveNextAsync(trace)) + if (!await this.queryPartitionRangePageAsyncEnumerator.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -230,12 +220,12 @@ public async ValueTask MoveNextAsync(ITrace trace) backendQueryPage.Documents, backendQueryPage.RequestCharge, backendQueryPage.ActivityId, - backendQueryPage.ResponseLengthInBytes, backendQueryPage.CosmosQueryExecutionInfo, backendQueryPage.DistributionPlanSpec, disallowContinuationTokenMessage: null, backendQueryPage.AdditionalHeaders, - queryState); + queryState, + backendQueryPage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; @@ -282,8 +272,7 @@ public static TryCatch MonadicCreate( updatedSqlQuerySpec, feedRangeState, partitionKey, - queryPaginationOptions, - cancellationToken); + queryPaginationOptions); OptimisticDirectExecutionQueryPipelineImpl stage = new OptimisticDirectExecutionQueryPipelineImpl(partitionPageEnumerator); return TryCatch.FromResult(stage); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs index eab1f61c79..942d642110 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPage.cs @@ -1,55 +1,56 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination -{ - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - using System.Linq; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.QueryClient; - using Newtonsoft.Json; - - internal sealed class QueryPage : Page - { - public static readonly ImmutableHashSet BannedHeaders = new HashSet() - { - Microsoft.Azure.Documents.HttpConstants.HttpHeaders.Continuation, - Microsoft.Azure.Documents.HttpConstants.HttpHeaders.ContinuationToken, - }.Concat(BannedHeadersBase).ToImmutableHashSet(); - - public QueryPage( - IReadOnlyList documents, - double requestCharge, - string activityId, - long responseLengthInBytes, - Lazy cosmosQueryExecutionInfo, - DistributionPlanSpec distributionPlanSpec, - string disallowContinuationTokenMessage, - IReadOnlyDictionary additionalHeaders, - QueryState state) - : base(requestCharge, activityId, additionalHeaders, state) - { - this.Documents = documents ?? throw new ArgumentNullException(nameof(documents)); - this.ResponseLengthInBytes = responseLengthInBytes < 0 ? throw new ArgumentOutOfRangeException(nameof(responseLengthInBytes)) : responseLengthInBytes; - this.CosmosQueryExecutionInfo = cosmosQueryExecutionInfo; - this.DistributionPlanSpec = distributionPlanSpec; - this.DisallowContinuationTokenMessage = disallowContinuationTokenMessage; - } - - public IReadOnlyList Documents { get; } - - public long ResponseLengthInBytes { get; } - - public Lazy CosmosQueryExecutionInfo { get; } - - public DistributionPlanSpec DistributionPlanSpec { get; } - - public string DisallowContinuationTokenMessage { get; } - - protected override ImmutableHashSet DerivedClassBannedHeaders => QueryPage.BannedHeaders; - } +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination +{ + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Linq; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + + internal sealed class QueryPage : Page + { + public static readonly ImmutableHashSet BannedHeaders = new HashSet() + { + Microsoft.Azure.Documents.HttpConstants.HttpHeaders.Continuation, + Microsoft.Azure.Documents.HttpConstants.HttpHeaders.ContinuationToken, + }.Concat(BannedHeadersBase).ToImmutableHashSet(); + + public QueryPage( + IReadOnlyList documents, + double requestCharge, + string activityId, + Lazy cosmosQueryExecutionInfo, + DistributionPlanSpec distributionPlanSpec, + string disallowContinuationTokenMessage, + IReadOnlyDictionary additionalHeaders, + QueryState state, + bool? streaming) + : base(requestCharge, activityId, additionalHeaders, state) + { + this.Documents = documents ?? throw new ArgumentNullException(nameof(documents)); + this.CosmosQueryExecutionInfo = cosmosQueryExecutionInfo; + this.DistributionPlanSpec = distributionPlanSpec; + this.DisallowContinuationTokenMessage = disallowContinuationTokenMessage; + this.Streaming = streaming; + } + + public IReadOnlyList Documents { get; } + + public Lazy CosmosQueryExecutionInfo { get; } + + public DistributionPlanSpec DistributionPlanSpec { get; } + + public string DisallowContinuationTokenMessage { get; } + + public bool? Streaming { get; } + + public override int ItemCount => this.Documents.Count; + + protected override ImmutableHashSet DerivedClassBannedHeaders => QueryPage.BannedHeaders; + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs index c985158828..e0f179a127 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Pagination/QueryPaginationOptions.cs @@ -32,7 +32,7 @@ internal sealed class QueryPaginationOptions : PaginationOptions public QueryPaginationOptions( int? pageSizeHint = null, bool optimisticDirectExecute = false, - Dictionary additionalHeaders = null) + IReadOnlyDictionary additionalHeaders = null) : base(pageSizeHint, additionalHeaders) { this.OptimisticDirectExecute = optimisticDirectExecute; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs index a119d5866a..1ae5312c2e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs @@ -33,8 +33,7 @@ public static TryCatch MonadicCreate( QueryInfo queryInfo, QueryPaginationOptions queryPaginationOptions, int maxConcurrency, - CosmosElement requestContinuationToken, - CancellationToken requestCancellationToken) + CosmosElement requestContinuationToken) { if (documentContainer == null) { @@ -68,7 +67,7 @@ public static TryCatch MonadicCreate( MonadicCreatePipelineStage monadicCreatePipelineStage; if (queryInfo.HasOrderBy) { - monadicCreatePipelineStage = (continuationToken, cancellationToken) => OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => OrderByCrossPartitionQueryPipelineStage.MonadicCreate( documentContainer: documentContainer, sqlQuerySpec: sqlQuerySpec, targetRanges: targetRanges, @@ -78,12 +77,11 @@ public static TryCatch MonadicCreate( .Zip(queryInfo.OrderBy, (expression, sortOrder) => new OrderByColumn(expression, sortOrder)).ToList(), queryPaginationOptions: queryPaginationOptions, maxConcurrency: maxConcurrency, - continuationToken: continuationToken, - cancellationToken: cancellationToken); + continuationToken: continuationToken); } else { - monadicCreatePipelineStage = (continuationToken, cancellationToken) => ParallelCrossPartitionQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => ParallelCrossPartitionQueryPipelineStage.MonadicCreate( documentContainer: documentContainer, sqlQuerySpec: sqlQuerySpec, targetRanges: targetRanges, @@ -91,31 +89,28 @@ public static TryCatch MonadicCreate( partitionKey: partitionKey, prefetchPolicy: prefetchPolicy, maxConcurrency: maxConcurrency, - continuationToken: continuationToken, - cancellationToken: cancellationToken); + continuationToken: continuationToken); } if (queryInfo.HasAggregates && !queryInfo.HasGroupBy) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => AggregateQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => AggregateQueryPipelineStage.MonadicCreate( executionEnvironment, queryInfo.Aggregates, queryInfo.GroupByAliasToAggregateType, queryInfo.GroupByAliases, queryInfo.HasSelectValue, continuationToken, - cancellationToken, monadicCreateSourceStage); } if (queryInfo.HasDistinct) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => DistinctQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => DistinctQueryPipelineStage.MonadicCreate( executionEnvironment, continuationToken, - cancellationToken, monadicCreateSourceStage, queryInfo.DistinctType); } @@ -123,10 +118,9 @@ public static TryCatch MonadicCreate( if (queryInfo.HasGroupBy) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => GroupByQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => GroupByQueryPipelineStage.MonadicCreate( executionEnvironment, continuationToken, - cancellationToken, monadicCreateSourceStage, queryInfo.Aggregates, queryInfo.GroupByAliasToAggregateType, @@ -138,49 +132,45 @@ public static TryCatch MonadicCreate( if (queryInfo.HasOffset) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => SkipQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => SkipQueryPipelineStage.MonadicCreate( executionEnvironment, queryInfo.Offset.Value, continuationToken, - cancellationToken, monadicCreateSourceStage); } if (queryInfo.HasLimit) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => TakeQueryPipelineStage.MonadicCreateLimitStage( + monadicCreatePipelineStage = (continuationToken) => TakeQueryPipelineStage.MonadicCreateLimitStage( executionEnvironment, queryInfo.Limit.Value, continuationToken, - cancellationToken, monadicCreateSourceStage); } if (queryInfo.HasTop) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => TakeQueryPipelineStage.MonadicCreateTopStage( + monadicCreatePipelineStage = (continuationToken) => TakeQueryPipelineStage.MonadicCreateTopStage( executionEnvironment, queryInfo.Top.Value, continuationToken, - cancellationToken, monadicCreateSourceStage); } if (queryInfo.HasDCount) { MonadicCreatePipelineStage monadicCreateSourceStage = monadicCreatePipelineStage; - monadicCreatePipelineStage = (continuationToken, cancellationToken) => DCountQueryPipelineStage.MonadicCreate( + monadicCreatePipelineStage = (continuationToken) => DCountQueryPipelineStage.MonadicCreate( executionEnvironment, queryInfo.DCountInfo, continuationToken, - cancellationToken, monadicCreateSourceStage); } - return monadicCreatePipelineStage(requestContinuationToken, requestCancellationToken) - .Try(onSuccess: (stage) => new SkipEmptyPageQueryPipelineStage(stage, requestCancellationToken)); + return monadicCreatePipelineStage(requestContinuationToken) + .Try(onSuccess: stage => new SkipEmptyPageQueryPipelineStage(stage)); } private static PrefetchPolicy DeterminePrefetchPolicy(QueryInfo queryInfo) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/QueryPipelineStageBase.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/QueryPipelineStageBase.cs index 5cfc69f0d9..561bbd89ae 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/QueryPipelineStageBase.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/QueryPipelineStageBase.cs @@ -14,12 +14,10 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline internal abstract class QueryPipelineStageBase : IQueryPipelineStage { protected readonly IQueryPipelineStage inputStage; - protected CancellationToken cancellationToken; - protected QueryPipelineStageBase(IQueryPipelineStage inputStage, CancellationToken cancellationToken) + protected QueryPipelineStageBase(IQueryPipelineStage inputStage) { this.inputStage = inputStage ?? throw new ArgumentNullException(nameof(inputStage)); - this.cancellationToken = cancellationToken; } public TryCatch Current { get; protected set; } @@ -29,14 +27,6 @@ public ValueTask DisposeAsync() return this.inputStage.DisposeAsync(); } - public abstract ValueTask MoveNextAsync(ITrace trace); - - public void SetCancellationToken(CancellationToken cancellationToken) - { - // Only here to support legacy query iterator and ExecuteNextAsync - // can be removed only we only expose IAsyncEnumerable in v4 sdk. - this.cancellationToken = cancellationToken; - this.inputStage.SetCancellationToken(cancellationToken); - } + public abstract ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken); } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs index 7f80df9930..e04b75207d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Client.cs @@ -22,9 +22,8 @@ private sealed class ClientSkipQueryPipelineStage : SkipQueryPipelineStage { private ClientSkipQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, long skipCount) - : base(source, cancellationToken, skipCount) + : base(source, skipCount) { // Work is done in base constructor. } @@ -32,7 +31,6 @@ private ClientSkipQueryPipelineStage( public static TryCatch MonadicCreate( int offsetCount, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (monadicCreatePipelineStage == null) @@ -81,7 +79,7 @@ public static TryCatch MonadicCreate( sourceToken = null; } - TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -89,22 +87,21 @@ public static TryCatch MonadicCreate( IQueryPipelineStage stage = new ClientSkipQueryPipelineStage( tryCreateSource.Result, - cancellationToken, offsetContinuationToken.Offset); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -142,12 +139,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: documentsAfterSkip, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: state); + state: state, + streaming: sourcePage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs index a7cd0ddea2..8acb424510 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.Compute.cs @@ -20,8 +20,8 @@ internal abstract partial class SkipQueryPipelineStage : QueryPipelineStageBase { private sealed class ComputeSkipQueryPipelineStage : SkipQueryPipelineStage { - private ComputeSkipQueryPipelineStage(IQueryPipelineStage source, CancellationToken cancellationToken, long skipCount) - : base(source, cancellationToken, skipCount) + private ComputeSkipQueryPipelineStage(IQueryPipelineStage source, long skipCount) + : base(source, skipCount) { // Work is done in base constructor. } @@ -29,7 +29,6 @@ private ComputeSkipQueryPipelineStage(IQueryPipelineStage source, CancellationTo public static TryCatch MonadicCreate( int offsetCount, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (monadicCreatePipelineStage == null) @@ -61,7 +60,7 @@ public static TryCatch MonadicCreate( "offset count in continuation token can not be greater than the offsetcount in the query.")); } - TryCatch tryCreateSource = monadicCreatePipelineStage(offsetContinuationToken.SourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(offsetContinuationToken.SourceToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -69,22 +68,21 @@ public static TryCatch MonadicCreate( IQueryPipelineStage stage = new ComputeSkipQueryPipelineStage( tryCreateSource.Result, - cancellationToken, offsetContinuationToken.Offset); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; return false; @@ -123,12 +121,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: documentsAfterSkip, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: state); + state: state, + streaming: sourcePage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.cs index ef4d279ecf..adf84a9fb6 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Skip/SkipQueryPipelineStage.cs @@ -19,9 +19,8 @@ internal abstract partial class SkipQueryPipelineStage : QueryPipelineStageBase protected SkipQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, long skipCount) - : base(source, cancellationToken) + : base(source) { if (skipCount > int.MaxValue) { @@ -35,7 +34,6 @@ public static TryCatch MonadicCreate( ExecutionEnvironment executionEnvironment, int offsetCount, CosmosElement continuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { TryCatch tryCreate = executionEnvironment switch @@ -43,12 +41,10 @@ public static TryCatch MonadicCreate( ExecutionEnvironment.Client => ClientSkipQueryPipelineStage.MonadicCreate( offsetCount, continuationToken, - cancellationToken, monadicCreatePipelineStage), ExecutionEnvironment.Compute => ComputeSkipQueryPipelineStage.MonadicCreate( offsetCount, continuationToken, - cancellationToken, monadicCreatePipelineStage), _ => throw new ArgumentException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}"), }; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs index 95be4d4003..adb592d436 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/SkipEmptyPageQueryPipelineStage.cs @@ -6,13 +6,13 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline { using System; using System.Collections.Generic; - using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Tracing; + using static IndexUtilizationHelper; internal sealed class SkipEmptyPageQueryPipelineStage : IQueryPipelineStage { @@ -20,24 +20,21 @@ internal sealed class SkipEmptyPageQueryPipelineStage : IQueryPipelineStage private readonly IQueryPipelineStage inputStage; private double cumulativeRequestCharge; - private long cumulativeResponseLengthInBytes; private IReadOnlyDictionary cumulativeAdditionalHeaders; - private CancellationToken cancellationToken; private bool returnedFinalStats; - public SkipEmptyPageQueryPipelineStage(IQueryPipelineStage inputStage, CancellationToken cancellationToken) + public SkipEmptyPageQueryPipelineStage(IQueryPipelineStage inputStage) { this.inputStage = inputStage ?? throw new ArgumentNullException(nameof(inputStage)); - this.cancellationToken = cancellationToken; } public TryCatch Current { get; private set; } public ValueTask DisposeAsync() => this.inputStage.DisposeAsync(); - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { @@ -46,7 +43,7 @@ public async ValueTask MoveNextAsync(ITrace trace) for (int documentCount = 0; documentCount == 0;) { - if (!await this.inputStage.MoveNextAsync(trace)) + if (!await this.inputStage.MoveNextAsync(trace, cancellationToken)) { if (!this.returnedFinalStats) { @@ -54,14 +51,13 @@ public async ValueTask MoveNextAsync(ITrace trace) documents: EmptyPage, requestCharge: this.cumulativeRequestCharge, activityId: Guid.Empty.ToString(), - responseLengthInBytes: this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: this.cumulativeAdditionalHeaders, - state: default); + state: default, + streaming: null); this.cumulativeRequestCharge = 0; - this.cumulativeResponseLengthInBytes = 0; this.cumulativeAdditionalHeaders = null; this.returnedFinalStats = true; this.Current = TryCatch.FromResult(queryPage); @@ -91,22 +87,24 @@ public async ValueTask MoveNextAsync(ITrace trace) documents: EmptyPage, requestCharge: sourcePage.RequestCharge + this.cumulativeRequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes + this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, - additionalHeaders: sourcePage.AdditionalHeaders, - state: default); + additionalHeaders: AccumulateIndexUtilization( + cumulativeHeaders: this.cumulativeAdditionalHeaders, + currentHeaders: sourcePage.AdditionalHeaders), + state: default, + streaming: sourcePage.Streaming); this.cumulativeRequestCharge = 0; - this.cumulativeResponseLengthInBytes = 0; this.cumulativeAdditionalHeaders = null; this.Current = TryCatch.FromResult(queryPage); return true; } this.cumulativeRequestCharge += sourcePage.RequestCharge; - this.cumulativeResponseLengthInBytes += sourcePage.ResponseLengthInBytes; - this.cumulativeAdditionalHeaders = sourcePage.AdditionalHeaders; + this.cumulativeAdditionalHeaders = AccumulateIndexUtilization( + cumulativeHeaders: this.cumulativeAdditionalHeaders, + currentHeaders: sourcePage.AdditionalHeaders); } else { @@ -117,14 +115,15 @@ public async ValueTask MoveNextAsync(ITrace trace) documents: sourcePage.Documents, requestCharge: sourcePage.RequestCharge + this.cumulativeRequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes + this.cumulativeResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, - additionalHeaders: sourcePage.AdditionalHeaders, - state: sourcePage.State); + additionalHeaders: AccumulateIndexUtilization( + cumulativeHeaders: this.cumulativeAdditionalHeaders, + currentHeaders: sourcePage.AdditionalHeaders), + state: sourcePage.State, + streaming: sourcePage.Streaming); this.cumulativeRequestCharge = 0; - this.cumulativeResponseLengthInBytes = 0; this.cumulativeAdditionalHeaders = null; } else @@ -138,10 +137,5 @@ public async ValueTask MoveNextAsync(ITrace trace) return true; } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.cancellationToken = cancellationToken; - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs index 2d403ae45a..d7d0dea1b4 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Client.cs @@ -24,10 +24,9 @@ private sealed class ClientTakeQueryPipelineStage : TakeQueryPipelineStage private ClientTakeQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, int takeCount, TakeEnum takeEnum) - : base(source, cancellationToken, takeCount) + : base(source, takeCount) { this.takeEnum = takeEnum; } @@ -35,7 +34,6 @@ private ClientTakeQueryPipelineStage( public static TryCatch MonadicCreateLimitStage( int limitCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (limitCount < 0) @@ -89,7 +87,7 @@ public static TryCatch MonadicCreateLimitStage( sourceToken = null; } - TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -97,7 +95,6 @@ public static TryCatch MonadicCreateLimitStage( IQueryPipelineStage stage = new ClientTakeQueryPipelineStage( tryCreateSource.Result, - cancellationToken, limitContinuationToken.Limit, TakeEnum.Limit); @@ -107,7 +104,6 @@ public static TryCatch MonadicCreateLimitStage( public static TryCatch MonadicCreateTopStage( int topCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (topCount < 0) @@ -161,7 +157,7 @@ public static TryCatch MonadicCreateTopStage( sourceToken = null; } - TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(sourceToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -169,23 +165,22 @@ public static TryCatch MonadicCreateTopStage( IQueryPipelineStage stage = new ClientTakeQueryPipelineStage( tryCreateSource.Result, - cancellationToken, topContinuationToken.Top, TakeEnum.Top); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (this.ReturnedFinalPage || !await this.inputStage.MoveNextAsync(trace)) + if (this.ReturnedFinalPage || !await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; this.takeCount = 0; @@ -229,12 +224,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: takedDocuments, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: state); + state: state, + streaming: sourcePage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs index 7e1e8d6f62..fd6e0bd5ff 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.Compute.cs @@ -22,9 +22,8 @@ private sealed class ComputeTakeQueryPipelineStage : TakeQueryPipelineStage { private ComputeTakeQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, int takeCount) - : base(source, cancellationToken, takeCount) + : base(source, takeCount) { // Work is done in the base class. } @@ -32,27 +31,22 @@ private ComputeTakeQueryPipelineStage( public static TryCatch MonadicCreateLimitStage( int takeCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => ComputeTakeQueryPipelineStage.MonadicCreate( takeCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage); public static TryCatch MonadicCreateTopStage( int takeCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => ComputeTakeQueryPipelineStage.MonadicCreate( takeCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage); private static TryCatch MonadicCreate( int takeCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) { if (takeCount < 0) @@ -87,7 +81,7 @@ private static TryCatch MonadicCreate( $"{nameof(TakeContinuationToken.TakeCount)} in {nameof(TakeContinuationToken)}: {requestContinuationToken}: {takeContinuationToken.TakeCount} can not be greater than the limit count in the query: {takeCount}.")); } - TryCatch tryCreateSource = monadicCreatePipelineStage(takeContinuationToken.SourceToken, cancellationToken); + TryCatch tryCreateSource = monadicCreatePipelineStage(takeContinuationToken.SourceToken); if (tryCreateSource.Failed) { return tryCreateSource; @@ -95,22 +89,21 @@ private static TryCatch MonadicCreate( IQueryPipelineStage stage = new ComputeTakeQueryPipelineStage( tryCreateSource.Result, - cancellationToken, takeContinuationToken.TakeCount); return TryCatch.FromResult(stage); } - public override async ValueTask MoveNextAsync(ITrace trace) + public override async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - this.cancellationToken.ThrowIfCancellationRequested(); + cancellationToken.ThrowIfCancellationRequested(); if (trace == null) { throw new ArgumentNullException(nameof(trace)); } - if (this.ReturnedFinalPage || !await this.inputStage.MoveNextAsync(trace)) + if (this.ReturnedFinalPage || !await this.inputStage.MoveNextAsync(trace, cancellationToken)) { this.Current = default; this.takeCount = 0; @@ -146,12 +139,12 @@ public override async ValueTask MoveNextAsync(ITrace trace) documents: takedDocuments, requestCharge: sourcePage.RequestCharge, activityId: sourcePage.ActivityId, - responseLengthInBytes: sourcePage.ResponseLengthInBytes, cosmosQueryExecutionInfo: sourcePage.CosmosQueryExecutionInfo, distributionPlanSpec: default, disallowContinuationTokenMessage: sourcePage.DisallowContinuationTokenMessage, additionalHeaders: sourcePage.AdditionalHeaders, - state: queryState); + state: queryState, + streaming: sourcePage.Streaming); this.Current = TryCatch.FromResult(queryPage); return true; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.cs index d2bb5c4567..5dea48e840 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/Take/TakeQueryPipelineStage.cs @@ -17,9 +17,8 @@ internal abstract partial class TakeQueryPipelineStage : QueryPipelineStageBase protected TakeQueryPipelineStage( IQueryPipelineStage source, - CancellationToken cancellationToken, int takeCount) - : base(source, cancellationToken) + : base(source) { this.takeCount = takeCount; } @@ -28,18 +27,15 @@ public static TryCatch MonadicCreateLimitStage( ExecutionEnvironment executionEnvironment, int limitCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch { ExecutionEnvironment.Client => ClientTakeQueryPipelineStage.MonadicCreateLimitStage( limitCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage), ExecutionEnvironment.Compute => ComputeTakeQueryPipelineStage.MonadicCreateLimitStage( limitCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage), _ => throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}."), }; @@ -48,18 +44,15 @@ public static TryCatch MonadicCreateTopStage( ExecutionEnvironment executionEnvironment, int limitCount, CosmosElement requestContinuationToken, - CancellationToken cancellationToken, MonadicCreatePipelineStage monadicCreatePipelineStage) => executionEnvironment switch { ExecutionEnvironment.Client => ClientTakeQueryPipelineStage.MonadicCreateTopStage( limitCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage), ExecutionEnvironment.Compute => ComputeTakeQueryPipelineStage.MonadicCreateTopStage( limitCount, requestContinuationToken, - cancellationToken, monadicCreatePipelineStage), _ => throw new ArgumentOutOfRangeException($"Unknown {nameof(ExecutionEnvironment)}: {executionEnvironment}."), }; diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index e1c23c156b..f4817997ab 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -330,12 +330,12 @@ private static TryCatch GetCosmosElementResponse( cosmosResponseMessage.Content.CopyTo(memoryStream); } - long responseLengthBytes = memoryStream.Length; CosmosQueryClientCore.ParseRestStream( memoryStream, resourceType, out CosmosArray documents, - out CosmosObject distributionPlan); + out CosmosObject distributionPlan, + out bool? streaming); DistributionPlanSpec distributionPlanSpec = null; @@ -384,12 +384,12 @@ private static TryCatch GetCosmosElementResponse( documents, cosmosResponseMessage.Headers.RequestCharge, cosmosResponseMessage.Headers.ActivityId, - responseLengthBytes, cosmosQueryExecutionInfo, distributionPlanSpec, disallowContinuationTokenMessage: null, additionalHeaders, - queryState); + queryState, + streaming); return TryCatch.FromResult(response); } @@ -460,12 +460,14 @@ private Task GetRoutingMapProviderAsync() /// The memory stream response for the query REST response Azure Cosmos /// The resource type /// An array of CosmosElements parsed from the response body - /// An object containing the distribution plan for the client + /// An object containing the distribution plan for the client + /// An optional return value indicating if the backend response is streaming public static void ParseRestStream( Stream stream, ResourceType resourceType, out CosmosArray documents, - out CosmosObject distributionPlan) + out CosmosObject distributionPlan, + out bool? streaming) { if (!(stream is MemoryStream memoryStream)) { @@ -507,7 +509,8 @@ public static void ParseRestStream( // "Name": "root" // } // } - // } + // }, + // "_streaming": true // } // You want to create a CosmosElement for each document in "Documents". @@ -557,7 +560,22 @@ public static void ParseRestStream( else { distributionPlan = null; - } + } + + if (resourceType == ResourceType.Document && jsonNavigator.TryGetObjectProperty(jsonNavigator.GetRootNode(), "_streaming", out ObjectProperty streamingProperty)) + { + JsonNodeType jsonNodeType = jsonNavigator.GetNodeType(streamingProperty.ValueNode); + streaming = jsonNodeType switch + { + JsonNodeType.False => false, + JsonNodeType.True => true, + _ => throw new InvalidOperationException($"Response Body Contract was violated. QueryResponse had _streaming property as a non boolean: {jsonNodeType}"), + }; + } + else + { + streaming = null; + } } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index 344e3e56e4..fe540f222e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -192,14 +192,12 @@ public override async Task ReadNextAsync(ITrace trace, Cancella try { // This catches exception thrown by the pipeline and converts it to QueryResponse - this.queryPipelineStage.SetCancellationToken(cancellationToken); - if (!await this.queryPipelineStage.MoveNextAsync(trace)) + if (!await this.queryPipelineStage.MoveNextAsync(trace, cancellationToken)) { this.hasMoreResults = false; return QueryResponse.CreateSuccess( result: EmptyPage, count: EmptyPage.Count, - responseLengthBytes: default, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: new CosmosQueryResponseMessageHeaders( continauationToken: default, @@ -248,7 +246,6 @@ public override async Task ReadNextAsync(ITrace trace, Cancella return QueryResponse.CreateSuccess( result: tryGetQueryPage.Result.Documents, count: tryGetQueryPage.Result.Documents.Count, - responseLengthBytes: tryGetQueryPage.Result.ResponseLengthInBytes, serializationOptions: this.cosmosSerializationFormatOptions, responseHeaders: headers, trace: trace); diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs index 49f9e40232..898a628088 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryResponse.cs @@ -38,7 +38,6 @@ internal QueryResponse() private QueryResponse( IReadOnlyList result, int count, - long responseLengthBytes, CosmosQueryResponseMessageHeaders responseHeaders, HttpStatusCode statusCode, RequestMessage requestMessage, @@ -55,7 +54,6 @@ private QueryResponse( { this.CosmosElements = result; this.Count = count; - this.ResponseLengthBytes = responseLengthBytes; this.memoryStream = memoryStream; this.CosmosSerializationOptions = serializationOptions; } @@ -68,14 +66,6 @@ private QueryResponse( internal virtual CosmosQueryResponseMessageHeaders QueryHeaders => (CosmosQueryResponseMessageHeaders)this.Headers; - /// - /// Gets the response length in bytes - /// - /// - /// This value is only set for Direct mode. - /// - internal long ResponseLengthBytes { get; } - internal virtual CosmosSerializationFormatOptions CosmosSerializationOptions { get; } internal bool GetHasMoreResults() @@ -86,7 +76,6 @@ internal bool GetHasMoreResults() internal static QueryResponse CreateSuccess( IReadOnlyList result, int count, - long responseLengthBytes, CosmosQueryResponseMessageHeaders responseHeaders, CosmosSerializationFormatOptions serializationOptions, ITrace trace) @@ -96,11 +85,6 @@ internal static QueryResponse CreateSuccess( throw new ArgumentOutOfRangeException("count must be positive"); } - if (responseLengthBytes < 0) - { - throw new ArgumentOutOfRangeException("responseLengthBytes must be positive"); - } - Lazy memoryStream = new Lazy(() => CosmosElementSerializer.ToStream( responseHeaders.ContainerRid, result, @@ -110,7 +94,6 @@ internal static QueryResponse CreateSuccess( QueryResponse cosmosQueryResponse = new QueryResponse( result: result, count: count, - responseLengthBytes: responseLengthBytes, responseHeaders: responseHeaders, statusCode: HttpStatusCode.OK, cosmosException: null, @@ -132,7 +115,6 @@ internal static QueryResponse CreateFailure( QueryResponse cosmosQueryResponse = new QueryResponse( result: new List(), count: 0, - responseLengthBytes: 0, responseHeaders: responseHeaders, statusCode: statusCode, cosmosException: cosmosException, diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/CrossPartitionReadFeedAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/CrossPartitionReadFeedAsyncEnumerator.cs index 5641318ec3..709b410de2 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/CrossPartitionReadFeedAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/CrossPartitionReadFeedAsyncEnumerator.cs @@ -14,7 +14,7 @@ namespace Microsoft.Azure.Cosmos.ReadFeed.Pagination using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; - internal sealed class CrossPartitionReadFeedAsyncEnumerator : IAsyncEnumerator>> + internal sealed class CrossPartitionReadFeedAsyncEnumerator : ITracingAsyncEnumerator>> { private readonly CrossPartitionRangePageAsyncEnumerator crossPartitionEnumerator; @@ -26,12 +26,7 @@ private CrossPartitionReadFeedAsyncEnumerator( public TryCatch> Current { get; set; } - public ValueTask MoveNextAsync() - { - return this.MoveNextAsync(NoOpTrace.Singleton); - } - - public async ValueTask MoveNextAsync(ITrace trace) + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (trace == null) { @@ -40,7 +35,7 @@ public async ValueTask MoveNextAsync(ITrace trace) using (ITrace moveNextAsyncTrace = trace.StartChild(name: nameof(MoveNextAsync), component: TraceComponent.ReadFeed, level: TraceLevel.Info)) { - if (!await this.crossPartitionEnumerator.MoveNextAsync(moveNextAsyncTrace)) + if (!await this.crossPartitionEnumerator.MoveNextAsync(moveNextAsyncTrace, cancellationToken)) { this.Current = default; return false; @@ -61,16 +56,10 @@ public async ValueTask MoveNextAsync(ITrace trace) public ValueTask DisposeAsync() => this.crossPartitionEnumerator.DisposeAsync(); - public void SetCancellationToken(CancellationToken cancellationToken) - { - this.crossPartitionEnumerator.SetCancellationToken(cancellationToken); - } - public static CrossPartitionReadFeedAsyncEnumerator Create( IDocumentContainer documentContainer, CrossFeedRangeState crossFeedRangeState, - ReadFeedPaginationOptions readFeedPaginationOptions, - CancellationToken cancellationToken) + ReadFeedPaginationOptions readFeedPaginationOptions) { if (documentContainer == null) { @@ -100,12 +89,10 @@ public static CrossPartitionReadFeedAsyncEnumerator Create( documentContainer, CrossPartitionReadFeedAsyncEnumerator.MakeCreateFunction( documentContainer, - readFeedPaginationOptions, - cancellationToken), + readFeedPaginationOptions), comparer: comparer, maxConcurrency: default, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken, crossFeedRangeState); CrossPartitionReadFeedAsyncEnumerator enumerator = new CrossPartitionReadFeedAsyncEnumerator( @@ -116,14 +103,12 @@ public static CrossPartitionReadFeedAsyncEnumerator Create( private static CreatePartitionRangePageAsyncEnumerator MakeCreateFunction( IReadFeedDataSource readFeedDataSource, - ReadFeedPaginationOptions readFeedPaginationOptions, - CancellationToken cancellationToken) + ReadFeedPaginationOptions readFeedPaginationOptions) { return (FeedRangeState feedRangeState) => new ReadFeedPartitionRangeEnumerator( readFeedDataSource, feedRangeState, - readFeedPaginationOptions, - cancellationToken); + readFeedPaginationOptions); } private sealed class PartitionRangePageAsyncEnumeratorComparerForward : IComparer> diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPage.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPage.cs index 391cfcc145..b7528b62d3 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPage.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPage.cs @@ -22,17 +22,21 @@ internal sealed class ReadFeedPage : Page public ReadFeedPage( Stream content, - double requestCharge, + double requestCharge, + int itemCount, string activityId, IReadOnlyDictionary additionalHeaders, ReadFeedState state) : base(requestCharge, activityId, additionalHeaders, state) { - this.Content = content ?? throw new ArgumentNullException(nameof(content)); + this.Content = content ?? throw new ArgumentNullException(nameof(content)); + this.ItemCount = itemCount; } - public Stream Content { get; } - + public Stream Content { get; } + + public override int ItemCount { get; } + protected override ImmutableHashSet DerivedClassBannedHeaders => BannedHeaders; } } diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPartitionRangeEnumerator.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPartitionRangeEnumerator.cs index c2969f6356..6fc27dea80 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPartitionRangeEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/Pagination/ReadFeedPartitionRangeEnumerator.cs @@ -20,9 +20,8 @@ internal sealed class ReadFeedPartitionRangeEnumerator : PartitionRangePageAsync public ReadFeedPartitionRangeEnumerator( IReadFeedDataSource readFeedDataSource, FeedRangeState feedRangeState, - ReadFeedPaginationOptions readFeedPaginationOptions, - CancellationToken cancellationToken) - : base(feedRangeState, cancellationToken) + ReadFeedPaginationOptions readFeedPaginationOptions) + : base(feedRangeState) { this.readFeedDataSource = readFeedDataSource ?? throw new ArgumentNullException(nameof(readFeedDataSource)); this.readFeedPaginationOptions = readFeedPaginationOptions; diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerable.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerable.cs index d581e742b5..a1c7ff927c 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerable.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerable.cs @@ -7,9 +7,11 @@ namespace Microsoft.Azure.Cosmos.ReadFeed using System; using System.Collections.Generic; using System.Threading; + using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Tracing; internal sealed class ReadFeedCrossFeedRangeAsyncEnumerable : IAsyncEnumerable> { @@ -33,10 +35,10 @@ public IAsyncEnumerator> GetAsyncEnumerator(CancellationT CrossPartitionReadFeedAsyncEnumerator innerEnumerator = CrossPartitionReadFeedAsyncEnumerator.Create( this.documentContainer, innerState, - this.readFeedPaginationOptions, - cancellationToken); + this.readFeedPaginationOptions); - return new ReadFeedCrossFeedRangeAsyncEnumerator(innerEnumerator); + ReadFeedCrossFeedRangeAsyncEnumerator readFeedEnumerator = new ReadFeedCrossFeedRangeAsyncEnumerator(innerEnumerator); + return new TracingAsyncEnumerator>(readFeedEnumerator, NoOpTrace.Singleton, cancellationToken); } } } diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs index 996b1eaf78..2f6780cdc9 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedCrossFeedRangeAsyncEnumerator.cs @@ -5,14 +5,16 @@ namespace Microsoft.Azure.Cosmos.ReadFeed { using System; - using System.Collections.Generic; + using System.Collections.Generic; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.ReadFeed.Pagination; - - internal sealed class ReadFeedCrossFeedRangeAsyncEnumerator : IAsyncEnumerator> + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + + internal sealed class ReadFeedCrossFeedRangeAsyncEnumerator : ITracingAsyncEnumerator> { private readonly CrossPartitionReadFeedAsyncEnumerator enumerator; @@ -25,9 +27,9 @@ public ReadFeedCrossFeedRangeAsyncEnumerator(CrossPartitionReadFeedAsyncEnumerat public ValueTask DisposeAsync() => this.enumerator.DisposeAsync(); - public async ValueTask MoveNextAsync() + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { - if (!await this.enumerator.MoveNextAsync()) + if (!await this.enumerator.MoveNextAsync(trace, cancellationToken)) { return false; } @@ -47,7 +49,8 @@ public async ValueTask MoveNextAsync() innerReadFeedPage.Page.Content, Documents.ResourceType.Document, out CosmosArray documents, - out CosmosObject distributionPlan); + out CosmosObject distributionPlan, + out bool? ignored); ReadFeedPage page = new ReadFeedPage( documents, innerReadFeedPage.Page.RequestCharge, diff --git a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs index 8a46196a56..1e997d0b8c 100644 --- a/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs +++ b/Microsoft.Azure.Cosmos/src/ReadFeed/ReadFeedIteratorCore.cs @@ -181,8 +181,7 @@ public ReadFeedIteratorCore( CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, new CrossFeedRangeState(monadicReadFeedState.Result.FeedRangeStates), - readFeedPaginationOptions, - cancellationToken)); + readFeedPaginationOptions)); } this.hasMoreResults = true; @@ -232,12 +231,11 @@ public override async Task ReadNextAsync( } CrossPartitionReadFeedAsyncEnumerator enumerator = this.monadicEnumerator.Result; - enumerator.SetCancellationToken(cancellationToken); TryCatch> monadicPage; try { - if (!await enumerator.MoveNextAsync(trace)) + if (!await enumerator.MoveNextAsync(trace, cancellationToken)) { throw new InvalidOperationException("Should not be calling enumerator that does not have any more results"); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index 43d6fad184..d54fa8cd67 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -376,73 +376,57 @@ public void IndexUtilizationClientSideExistenceTest() public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestInput input) { - string indexMetricsNonODE = default; // Execute without ODE - QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = false }; + string indexMetricsNonODE = RunTest(input.Query, enableOptimisticDirectExecution: false); - FeedIterator itemQuery = testContainer.GetItemQueryIterator( - input.Query, + // Execute with ODE + string indexMetricsODE = RunTest(input.Query, enableOptimisticDirectExecution: true); + + // Make sure ODE and non-ODE is consistent + Assert.AreEqual(indexMetricsNonODE, indexMetricsODE); + + return new IndexMetricsParserTestOutput(indexMetricsNonODE); + } + + private static string RunTest(string query, bool enableOptimisticDirectExecution) + { + QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = enableOptimisticDirectExecution }; + + using FeedIterator itemQuery = testContainer.GetItemQueryIterator( + query, requestOptions: requestOptions); // Index Metrics is returned fully on the first page so no need to worry about result set - int roundTripCount = 1; + int roundTripCount = 0; + string indexMetrics = null; while (itemQuery.HasMoreResults) { FeedResponse page = itemQuery.ReadNextAsync().Result; Assert.IsTrue(page.Headers.AllKeys().Length > 1); - if (roundTripCount > 1) + if (roundTripCount > 0) { - if (page.IndexMetrics != null) Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount); + if (page.IndexMetrics != null) + { + Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount); + } } else { Assert.IsNotNull(page.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); Assert.IsNotNull(page.IndexMetrics, "Expected index metrics response for query"); - indexMetricsNonODE = page.IndexMetrics; + indexMetrics = page.IndexMetrics; } roundTripCount++; } - // Execute with ODE - string indexMetricsODE = default; - QueryRequestOptions requestOptions2 = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = true }; - - FeedIterator itemQuery2 = testContainer.GetItemQueryIterator( - input.Query, - requestOptions: requestOptions2); - - // Index Metrics is returned fully on the first page so no need to worry about result set - int roundTripCount2 = 1; - while (itemQuery2.HasMoreResults) - { - FeedResponse page2 = itemQuery2.ReadNextAsync().Result; - Assert.IsTrue(page2.Headers.AllKeys().Length > 1); - - if (roundTripCount2 > 1) - { - if (page2.IndexMetrics != null) Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount2); - } - else - { - Assert.IsNotNull(page2.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); - Assert.IsNotNull(page2.IndexMetrics, "Expected index metrics response for query"); - - indexMetricsODE = page2.IndexMetrics; - } - - roundTripCount2++; - } - - // Make sure ODE and non-ODE is consistent - Assert.AreEqual(indexMetricsNonODE, indexMetricsODE); - - return new IndexMetricsParserTestOutput(indexMetricsNonODE); + return indexMetrics; } } + public sealed class IndexMetricsParserTestInput : BaselineTestInput { public IndexMetricsParserTestInput(string description, string query) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/NonStreamingOrderByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/NonStreamingOrderByQueryTests.cs new file mode 100644 index 0000000000..355e6b0fac --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/NonStreamingOrderByQueryTests.cs @@ -0,0 +1,178 @@ +namespace Microsoft.Azure.Cosmos.EmulatorTests.Query +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + [TestCategory("Query")] + public sealed class NonStreamingOrderByQueryTests : QueryTestsBase + { + private const string Embedding = "[-0.008861,0.097097,0.100236,0.070044,-0.079279,0.000923,-0.012829,0.064301,-0.029405,-0.009858,-0.017753,0.063115,0.033623,0.019805,0.052704,-0.100458,0.089387,-0.040792,-0.088936,0.110212,-0.044749,0.077675,-0.017062,-0.063745,-0.009502,-0.079371,0.066952,-0.070209,0.063761,-0.038194,-0.046252,0.049983,-0.094985,-0.086341,0.024665,-0.112857,-0.038358,-0.007008,-0.010063,-0.000183,0.068841,0.024942,-0.042561,-0.044576,0.010776,0.006323,0.088285,-0.062522,0.028216,0.088291,0.033231,-0.033732,-0.002995,0.118994,0.000453,0.158588,-0.044475,-0.137629,0.066080,0.062824,-0.128369,-0.087959,0.028080,0.070063,0.046700,-0.083278,-0.118428,0.071118,0.100757,0.017944,0.026296,0.017282,-0.082127,-0.006148,0.002967,-0.032857,-0.076493,-0.072842,-0.055179,-0.081703,0.011437,-0.038698,-0.062540,-0.027899,0.087635,0.031870,0.029164,0.000524,-0.039895,-0.055559,0.024582,-0.030595,0.003942,-0.034500,0.003012,-0.023863,0.033831,0.061476,-0.090183,-0.039206,-0.026586,-0.042763,0.049835,-0.052496,-0.020044,0.073703,0.096775,0.033063,0.000313,-0.022581,-0.141154,0.032095,0.077733,-0.063739,-0.055647,-0.017604,0.044639,-0.062925,-0.001960,0.024665,-0.009416,-0.021381,0.082724,-0.031026,0.027255,0.066198,0.000845,0.008393,0.039434,0.054104,-0.060255,0.034266,0.079435,0.043624,-0.015871,-0.038030,-0.030374,-0.020542,0.007132,0.008708,0.087840,0.017351,-0.089493,0.030182,0.026961,-0.071212,-0.004854,0.007389,0.067203,-0.026351,-0.011460,-0.058723,0.013153,-0.020313,-0.051170,0.002242,0.088222,-0.004267,-0.073523,-0.021874,-0.033585,-0.048553,-0.019119,-0.025310,0.053096,0.111063,0.035042,-0.082811,-0.073749,-0.010048,0.012265,-0.023893,-0.125340,0.026611,0.043258,-0.010473,-0.044428,-0.039251,-0.046891,-0.013008,0.062219,0.078732,-0.086303,0.016901,0.010331,-0.043754,-0.057733,-0.037964,0.024907,0.068143,-0.019992,-0.035030,0.038854,0.034345,-0.048839,-0.105419,0.043013,-0.023374,-0.077629,-0.076465,0.078564,-0.024519,0.041293,-0.032088,-0.007053,0.022618,-0.004657,-0.093970,-0.000199,0.004813,-0.044789,-0.127900,-0.033516,-0.043816,0.033056,-0.057619,0.004901,0.018863,0.039752,0.000739,-0.136350,-0.067819,-0.014856,0.058351,-0.014275,-0.000873,-0.039388,-0.017191,-0.051184,-0.046863,0.006143,-0.075998,-0.064695,0.046676,-0.020558,0.082474,0.160449,-0.027475,0.009541,-0.021876,0.027416,0.078049,0.089309,0.032928,-0.033272,0.048905,0.061164,0.054811,0.024527,-0.034978,-0.018083,-0.077601,0.034112,-0.021121,0.098856,0.019585,-0.058928,-0.016126,-0.011748,0.031588,0.003205,-0.077483,-0.002372,-0.113548,0.047445,-0.027094,-0.032843,0.042378,-0.074703,0.057001,0.012020,0.131156,0.002080,-0.065770,0.112443,0.047786,0.024492,-0.108401,0.016836,0.001478,0.041542,-0.067801,0.102876,-0.052808,-0.136035,0.073852,0.079966,-0.000586,0.034055,-0.053040,0.050461,-0.021550,0.014827,0.077605,-0.024783,-0.082388,0.074410,-0.033689,-0.010982,0.043733]"; + + private static readonly IReadOnlyList Documents = new List + { + @"{""id"":""0"", ""word"":""sayVERB"", ""embedding"":[-0.008861,0.097097,0.100236,0.070044,-0.079279,0.000923,-0.012829,0.064301,-0.029405,-0.009858,-0.017753,0.063115,0.033623,0.019805,0.052704,-0.100458,0.089387,-0.040792,-0.088936,0.110212,-0.044749,0.077675,-0.017062,-0.063745,-0.009502,-0.079371,0.066952,-0.070209,0.063761,-0.038194,-0.046252,0.049983,-0.094985,-0.086341,0.024665,-0.112857,-0.038358,-0.007008,-0.010063,-0.000183,0.068841,0.024942,-0.042561,-0.044576,0.010776,0.006323,0.088285,-0.062522,0.028216,0.088291,0.033231,-0.033732,-0.002995,0.118994,0.000453,0.158588,-0.044475,-0.137629,0.066080,0.062824,-0.128369,-0.087959,0.028080,0.070063,0.046700,-0.083278,-0.118428,0.071118,0.100757,0.017944,0.026296,0.017282,-0.082127,-0.006148,0.002967,-0.032857,-0.076493,-0.072842,-0.055179,-0.081703,0.011437,-0.038698,-0.062540,-0.027899,0.087635,0.031870,0.029164,0.000524,-0.039895,-0.055559,0.024582,-0.030595,0.003942,-0.034500,0.003012,-0.023863,0.033831,0.061476,-0.090183,-0.039206,-0.026586,-0.042763,0.049835,-0.052496,-0.020044,0.073703,0.096775,0.033063,0.000313,-0.022581,-0.141154,0.032095,0.077733,-0.063739,-0.055647,-0.017604,0.044639,-0.062925,-0.001960,0.024665,-0.009416,-0.021381,0.082724,-0.031026,0.027255,0.066198,0.000845,0.008393,0.039434,0.054104,-0.060255,0.034266,0.079435,0.043624,-0.015871,-0.038030,-0.030374,-0.020542,0.007132,0.008708,0.087840,0.017351,-0.089493,0.030182,0.026961,-0.071212,-0.004854,0.007389,0.067203,-0.026351,-0.011460,-0.058723,0.013153,-0.020313,-0.051170,0.002242,0.088222,-0.004267,-0.073523,-0.021874,-0.033585,-0.048553,-0.019119,-0.025310,0.053096,0.111063,0.035042,-0.082811,-0.073749,-0.010048,0.012265,-0.023893,-0.125340,0.026611,0.043258,-0.010473,-0.044428,-0.039251,-0.046891,-0.013008,0.062219,0.078732,-0.086303,0.016901,0.010331,-0.043754,-0.057733,-0.037964,0.024907,0.068143,-0.019992,-0.035030,0.038854,0.034345,-0.048839,-0.105419,0.043013,-0.023374,-0.077629,-0.076465,0.078564,-0.024519,0.041293,-0.032088,-0.007053,0.022618,-0.004657,-0.093970,-0.000199,0.004813,-0.044789,-0.127900,-0.033516,-0.043816,0.033056,-0.057619,0.004901,0.018863,0.039752,0.000739,-0.136350,-0.067819,-0.014856,0.058351,-0.014275,-0.000873,-0.039388,-0.017191,-0.051184,-0.046863,0.006143,-0.075998,-0.064695,0.046676,-0.020558,0.082474,0.160449,-0.027475,0.009541,-0.021876,0.027416,0.078049,0.089309,0.032928,-0.033272,0.048905,0.061164,0.054811,0.024527,-0.034978,-0.018083,-0.077601,0.034112,-0.021121,0.098856,0.019585,-0.058928,-0.016126,-0.011748,0.031588,0.003205,-0.077483,-0.002372,-0.113548,0.047445,-0.027094,-0.032843,0.042378,-0.074703,0.057001,0.012020,0.131156,0.002080,-0.065770,0.112443,0.047786,0.024492,-0.108401,0.016836,0.001478,0.041542,-0.067801,0.102876,-0.052808,-0.136035,0.073852,0.079966,-0.000586,0.034055,-0.053040,0.050461,-0.021550,0.014827,0.077605,-0.024783,-0.082388,0.074410,-0.033689,-0.010982,0.043733]}", + @"{""id"":""1"", ""word"":""go_VERB"", ""embedding"":[0.010490,0.094733,0.143699,0.040344,-0.103710,-0.000016,-0.014351,0.019653,0.069472,-0.046938,-0.057882,0.076405,-0.025230,0.026663,0.029986,-0.001605,-0.027803,0.037521,-0.050608,0.016215,0.025947,0.061172,-0.037448,-0.079232,0.071731,-0.085143,0.021494,-0.135554,-0.026115,-0.066408,0.022858,0.083231,0.020998,-0.049906,-0.079992,-0.060827,-0.028916,-0.029005,0.026067,-0.074869,0.073802,0.023593,-0.024348,-0.093236,0.006169,0.013119,0.007817,-0.088096,-0.012373,0.099807,0.011438,0.028583,0.025614,0.175403,0.007033,0.038856,0.004040,-0.088907,0.079697,0.037448,-0.128230,-0.066502,-0.018969,0.025777,0.035905,0.003710,-0.089079,0.071521,0.039237,0.052136,0.020986,-0.030793,-0.069486,-0.137115,0.008305,0.020813,-0.155342,0.000619,-0.033499,-0.104162,-0.061528,-0.043877,-0.042524,-0.032872,0.045071,0.072908,0.096057,0.141987,-0.078056,-0.013102,-0.026589,-0.073783,0.114807,0.077389,-0.041879,-0.052886,0.053710,0.036806,-0.035973,0.049071,-0.107199,-0.043581,0.016515,-0.029278,-0.026228,0.068037,-0.024183,0.040984,-0.020469,-0.103833,-0.007225,-0.073788,-0.051063,-0.037850,0.052581,-0.053090,-0.012198,-0.057343,0.024050,-0.046498,0.003065,-0.058912,0.043695,0.006340,0.060953,-0.008608,-0.029686,0.081187,-0.020058,0.059240,-0.061306,-0.002190,-0.020671,0.076712,0.049087,0.001153,0.087481,0.008559,0.069936,-0.015886,0.006122,0.038000,-0.071984,0.005263,0.060463,-0.051217,-0.034060,0.045217,0.059163,-0.048462,-0.005371,0.009663,0.081303,0.051019,-0.001248,-0.022637,0.016228,-0.006395,-0.053985,-0.014513,-0.017219,-0.010658,-0.012446,-0.035279,-0.003882,0.036453,0.029681,0.021278,0.006188,0.027861,0.076864,-0.042835,-0.022834,0.013928,0.066150,0.040982,-0.110985,-0.018865,0.006675,0.019173,0.021484,-0.021977,-0.035462,0.000464,-0.024281,0.010881,-0.064037,-0.024893,-0.095968,0.020834,-0.114225,-0.023433,-0.043971,0.014273,0.013481,-0.007542,0.079197,0.021280,-0.129871,0.080770,0.028912,-0.044134,-0.019904,-0.039406,-0.076024,0.058488,-0.094331,-0.082633,0.017676,-0.084006,-0.024444,-0.049778,-0.044615,-0.013499,-0.036736,-0.038579,-0.117319,0.012026,-0.007846,0.024003,-0.101645,0.111720,-0.010241,0.050279,-0.002212,0.060056,-0.116837,0.006078,-0.017954,-0.021794,0.020252,-0.031337,-0.032407,0.081086,-0.095125,0.041699,0.015953,-0.045653,-0.022522,-0.021422,-0.029167,0.052594,0.016523,0.081598,-0.027877,0.000609,0.012837,0.011880,0.074220,0.009736,0.006465,-0.140252,0.010762,-0.038319,0.038924,0.042537,0.005027,0.014024,0.024548,0.050131,-0.048069,-0.012616,-0.052162,-0.100378,0.067741,-0.067824,-0.020692,-0.043022,-0.038036,-0.016860,0.027835,0.140990,-0.045201,-0.069347,0.174518,-0.000236,0.008150,-0.039823,0.041197,0.056322,0.085883,0.027376,0.036537,0.094723,-0.103076,0.105746,0.059074,0.010947,0.099756,-0.027213,0.128793,-0.054593,0.025890,0.053512,0.005200,-0.035256,0.063273,-0.027069,0.046354,-0.002262]}", + @"{""id"":""2"", ""word"":""make_VERB"", ""embedding"":[-0.013029,0.038892,0.008581,0.056925,-0.100181,0.011566,-0.072478,0.156239,0.038442,-0.073817,-0.000439,0.114153,-0.051814,-0.056424,-0.038872,0.054174,0.000059,0.039477,-0.021345,0.053860,-0.131669,-0.020844,0.012362,-0.016145,0.048171,-0.122080,0.028292,-0.043984,-0.025178,-0.006927,-0.029133,-0.085539,-0.086455,0.001830,-0.099361,-0.029536,0.071144,-0.003143,0.027941,-0.035858,0.026530,0.004768,0.021307,-0.065139,-0.053572,0.038951,0.045786,-0.045258,-0.037586,0.038983,-0.062755,-0.000504,0.044502,0.123845,-0.050279,0.030425,-0.067798,-0.037958,0.023805,-0.011021,-0.041084,-0.090643,0.130500,0.046460,-0.040764,0.020988,-0.087054,-0.017896,0.056193,0.007352,-0.019590,-0.048728,-0.027895,-0.027241,-0.038715,0.008038,-0.172688,-0.106911,-0.012085,-0.050829,-0.053590,-0.059879,-0.030488,-0.025220,0.020381,0.102120,0.041989,0.119341,-0.006702,0.035009,0.016077,-0.014298,0.124971,0.050049,0.113425,-0.027587,-0.001379,-0.031188,0.041054,-0.013872,-0.134232,-0.073757,0.075578,-0.064260,0.035823,0.032695,-0.059019,0.086900,-0.049042,-0.105385,-0.024058,0.095202,-0.044429,-0.053781,-0.013759,-0.077265,-0.043720,-0.082217,0.128089,-0.041757,-0.023743,0.027764,0.008487,-0.022274,-0.023357,-0.013653,0.047372,0.098364,-0.020791,-0.063818,0.055996,-0.007599,0.018954,-0.003601,0.055991,-0.089158,0.008229,-0.027915,0.056351,0.101133,0.043454,0.026218,0.010540,0.053571,0.079725,-0.048278,-0.048708,-0.075923,-0.045807,0.083970,-0.087983,0.058780,0.025992,-0.008407,-0.059681,-0.022862,0.099799,0.083928,-0.024096,0.008313,-0.065932,-0.003852,0.051210,-0.104068,-0.029864,0.021315,-0.036515,-0.050546,0.003077,0.007452,-0.020468,0.035296,-0.025792,-0.045913,0.042664,-0.025302,-0.057182,-0.026525,-0.053029,-0.009697,0.031003,0.064251,-0.096399,-0.020674,0.006306,-0.004981,-0.118857,-0.058013,-0.018890,0.042343,-0.111604,-0.071149,0.042898,0.094869,-0.029797,-0.134403,-0.030753,0.050269,-0.096115,0.019021,0.014348,-0.049818,-0.017920,0.044926,0.038627,-0.091947,-0.001567,0.064930,-0.065977,-0.015673,0.034979,0.064560,0.036580,-0.000075,-0.064665,-0.054986,-0.090783,-0.033908,0.106271,0.058234,-0.100301,0.015398,-0.072886,0.019940,0.066563,0.063845,-0.036548,-0.018204,-0.008618,0.098109,-0.128401,-0.053501,-0.032671,0.027777,-0.043889,-0.018033,0.099028,-0.026501,-0.026575,-0.106259,0.036872,0.024990,0.003347,0.045086,-0.083903,0.021039,0.056445,-0.053898,0.011539,-0.033661,0.020421,-0.051413,0.021900,0.075706,0.089103,-0.022953,-0.032130,-0.049067,0.014476,-0.036070,0.010638,-0.049193,-0.005560,-0.094642,-0.045530,-0.010048,0.074026,0.053386,-0.006803,0.043264,-0.004896,0.020676,0.002030,0.019262,0.043679,-0.006854,-0.064545,-0.059780,-0.070871,0.004817,0.058769,-0.052450,-0.023481,-0.036496,-0.029701,-0.002672,-0.029965,0.053667,0.038260,-0.026692,0.068764,-0.070122,0.060288,0.124118,-0.064670,-0.044363,0.023818,-0.022746,-0.086708,0.016196]}", + @"{""id"":""3"", ""word"":""get_VERB"", ""embedding"":[0.019242,0.144838,0.155635,0.009607,-0.169437,-0.004972,-0.021559,0.009400,0.074920,-0.033244,-0.032937,0.112560,0.041283,-0.030355,-0.048271,-0.061402,0.048208,0.083419,-0.043215,0.069025,-0.027292,0.097641,-0.070595,-0.034194,0.091538,-0.068585,0.012530,-0.120053,-0.014222,0.002379,0.070677,0.015263,0.030467,-0.001756,-0.013990,-0.026711,0.036041,0.014917,0.031644,-0.055844,0.115340,-0.003877,-0.045724,-0.025892,-0.024716,0.020095,-0.024788,0.005623,0.055026,0.078559,0.011337,0.033604,0.051766,0.135975,0.061593,0.029842,-0.021268,-0.136608,0.079957,0.011375,-0.155011,-0.151481,0.076298,0.031386,0.020274,0.028823,-0.127225,0.016972,0.000477,0.005670,-0.015052,-0.032207,-0.054631,-0.125453,0.027146,0.026122,-0.025028,-0.046540,0.021146,-0.082786,-0.051401,-0.015178,-0.017908,0.031622,0.061065,0.053762,0.093668,0.120508,0.013383,-0.019997,0.047220,-0.039273,0.070729,0.006117,0.033016,-0.059557,0.080700,0.044238,-0.013197,0.072017,-0.049897,-0.035379,-0.028077,-0.068918,0.048224,0.093904,-0.011614,0.143074,-0.066022,-0.104345,-0.080770,-0.034034,0.019643,-0.048965,0.020702,-0.061310,-0.077258,-0.091273,0.063781,-0.111229,0.058853,-0.006970,0.029294,0.001331,0.057966,-0.035211,0.033447,0.015224,0.027628,0.020672,0.023872,0.007849,-0.001215,0.045739,-0.032844,-0.027810,0.047459,0.011252,0.034142,-0.020341,0.063802,-0.005105,-0.014244,0.015935,-0.008431,-0.028795,-0.043172,-0.003883,0.023328,-0.022711,0.001897,0.032548,0.064574,0.097152,0.003275,-0.109298,0.024141,0.090362,-0.038664,-0.023928,-0.006557,0.025754,-0.011571,-0.053434,0.040903,0.061501,0.144468,0.017326,-0.032445,-0.024866,-0.000533,-0.067980,-0.099827,0.011754,0.026172,0.041204,-0.059723,0.026298,0.006623,-0.030971,0.030617,-0.008276,-0.084025,-0.030169,0.044463,0.002809,-0.030988,-0.025040,-0.059924,0.042590,-0.041501,0.018392,-0.107077,0.040232,-0.015956,-0.034321,0.064614,0.023561,-0.118772,0.011774,0.053385,-0.059752,-0.007313,-0.024684,0.012329,0.024288,-0.019210,-0.043125,0.031520,-0.072438,-0.043097,-0.061750,-0.049240,-0.039941,-0.086947,-0.019136,-0.082013,-0.095680,-0.012216,0.044958,-0.083804,-0.020841,-0.024199,0.085375,-0.000988,0.002353,-0.075649,-0.016678,-0.042220,0.002328,0.046584,-0.053008,-0.002773,0.059518,-0.113334,0.082102,0.038316,-0.023807,0.014160,-0.024084,0.049738,0.003309,0.020473,0.056583,-0.040877,-0.036386,0.033831,0.014504,0.005588,-0.098602,0.013935,-0.115838,0.048181,-0.013819,0.030253,-0.035629,0.022863,-0.019994,-0.016116,-0.052284,-0.034443,0.024592,-0.028994,-0.093012,-0.007058,0.013011,0.000991,-0.014438,-0.044545,0.040938,-0.043503,0.103244,-0.090978,0.005134,0.156962,0.013555,0.053622,-0.059002,0.032924,0.010204,-0.054882,-0.070490,0.102098,0.071841,-0.041202,0.079912,0.031834,0.048141,0.104557,-0.010763,0.057594,-0.091408,0.010093,0.010459,0.074382,0.028358,0.016023,-0.091680,0.031687,-0.108943]}", + @"{""id"":""4"", ""word"":""one_NUM"", ""embedding"":[0.056419,-0.021141,0.090616,-0.032564,-0.054807,0.031836,-0.004311,0.064928,-0.033537,0.008632,0.052463,0.034665,0.016636,-0.006993,0.002519,-0.049758,0.003396,0.076139,-0.040574,-0.034938,-0.018776,0.016026,-0.049461,-0.058605,0.052319,-0.022392,0.037263,-0.101570,-0.015736,0.014700,0.005736,-0.098316,0.023485,0.079696,0.000523,-0.072989,0.112214,-0.042671,-0.039667,-0.048063,0.076580,-0.044722,-0.009309,-0.029152,-0.032665,-0.017058,0.066964,-0.003375,0.010473,0.053499,-0.057250,0.022080,0.031383,0.110925,-0.070559,0.090881,0.004533,-0.072508,0.064684,0.078511,-0.096904,-0.011367,0.023967,0.045979,0.047333,-0.058862,-0.043411,0.133778,-0.040768,-0.027242,-0.013070,-0.021536,0.068636,-0.093734,-0.071668,0.021352,0.002289,0.037268,-0.065373,-0.020971,-0.023998,-0.035441,0.033266,-0.028960,0.040619,0.064281,0.065757,0.123596,0.082568,-0.004874,0.028938,0.047771,0.025916,0.021118,-0.023998,0.009172,0.100679,-0.078543,-0.046099,0.037856,-0.161992,-0.039157,0.007258,-0.039263,0.063678,0.060994,0.025443,0.036222,-0.007018,-0.108600,0.022631,-0.031306,-0.050116,0.006508,-0.018496,-0.098152,-0.043395,-0.012609,0.047591,-0.006303,0.029529,0.003471,0.004601,-0.050615,0.014272,0.049927,0.105728,0.021712,-0.030996,0.026857,-0.060846,-0.107893,0.017269,0.011160,0.020126,-0.115469,-0.015772,-0.007356,0.083882,0.119524,0.075473,-0.050709,0.036562,-0.059548,-0.053619,-0.049486,-0.124977,0.004016,-0.001549,0.007669,-0.039740,0.002400,-0.069183,-0.065801,-0.088064,-0.107159,0.072443,0.083424,-0.030178,-0.033223,0.084401,0.044171,0.013811,-0.084562,0.003194,0.056247,-0.022866,0.023806,0.047635,0.025468,0.069964,-0.096787,-0.025001,-0.021526,0.061188,0.045733,-0.099350,0.016400,-0.084030,0.056672,0.099467,-0.052893,-0.100382,0.124380,0.018206,0.034541,-0.014580,-0.124287,-0.103852,0.053850,-0.017001,-0.062173,-0.063301,0.024652,-0.023819,-0.057063,-0.013738,-0.027791,-0.013030,0.030126,-0.000573,-0.026613,-0.005942,0.057634,-0.079672,0.022556,0.000011,-0.037800,0.074457,-0.071388,0.086022,0.013307,-0.035879,-0.072396,0.034418,0.004146,-0.011763,0.010722,-0.015462,0.070248,-0.097890,-0.033176,-0.078940,0.169393,0.050572,0.045639,0.004937,0.008214,-0.024237,-0.039713,-0.082674,-0.056171,-0.114638,-0.037084,-0.019666,0.023100,0.091380,-0.070856,0.019748,0.032893,0.054247,0.001259,0.166033,-0.021817,-0.076404,-0.046031,0.002690,-0.015014,0.087486,-0.147485,0.035263,-0.095335,-0.035910,-0.060311,0.068841,0.034646,-0.004976,-0.025316,-0.066141,0.042181,-0.001685,-0.061911,-0.060588,-0.036907,-0.003193,-0.042462,-0.023907,0.015987,-0.030946,0.041203,0.003092,0.075626,0.082451,-0.077289,0.102090,-0.026878,0.057229,-0.067434,-0.041582,0.036640,0.022304,0.018005,-0.005375,0.038557,-0.087250,0.042553,-0.052500,0.070422,0.079278,-0.017086,0.055328,0.025901,0.111785,0.057416,0.022670,0.048453,-0.034165,-0.034901,0.014241,0.061734]}", + @"{""id"":""5"", ""word"":""see_VERB"", ""embedding"":[0.033784,-0.033085,0.020113,-0.010017,-0.081187,-0.021287,-0.009972,0.037831,-0.001592,0.079325,0.025121,-0.012038,-0.060439,0.023697,-0.011899,-0.009593,0.043340,-0.054792,-0.058171,0.111542,-0.072478,0.046219,-0.036414,-0.038994,0.010711,-0.022551,0.051247,-0.030018,-0.015760,-0.022421,0.029474,0.033584,0.077213,0.026976,-0.026057,-0.024171,-0.060402,-0.022088,0.036667,0.050913,0.044288,0.050425,0.020312,-0.079651,0.039995,0.025213,-0.093921,0.123022,-0.018795,-0.019389,0.002286,0.001979,-0.101728,0.107971,-0.068966,0.035741,0.015628,-0.035574,0.153279,0.094290,-0.104906,-0.052320,0.123525,0.008491,-0.095255,-0.007215,0.046057,0.073950,0.000288,0.048581,0.015934,0.018141,-0.025546,-0.197751,-0.042662,-0.052096,-0.026476,-0.062207,0.041462,-0.126658,-0.054443,0.032953,-0.042276,-0.002271,0.064819,-0.000886,0.057284,0.151726,-0.005298,0.027951,-0.030457,-0.006905,-0.063591,0.038784,0.042528,0.009519,-0.006915,0.012526,-0.026987,-0.031367,-0.032849,-0.069462,0.078398,-0.077442,0.025363,0.015721,0.006499,0.050169,0.013559,-0.041564,-0.021559,0.038734,-0.048881,-0.014219,0.018850,-0.076032,-0.031383,-0.053150,0.073602,-0.060924,0.059121,-0.135463,-0.065702,0.017648,0.056463,-0.019903,0.036354,0.063048,0.043614,-0.058998,0.036254,-0.089223,-0.017289,-0.016416,0.103582,-0.060645,-0.003059,-0.069493,0.018295,-0.066589,0.049994,0.053174,-0.001443,-0.069640,0.044240,-0.050163,-0.073309,0.004212,0.096908,0.120702,-0.067013,-0.009905,-0.043493,-0.076316,0.014215,-0.031754,-0.021288,-0.004769,-0.137067,-0.024747,-0.031678,0.015084,0.031505,-0.103574,-0.066272,0.042509,0.060396,-0.059968,0.002428,-0.024155,0.063192,-0.077420,-0.094139,0.057205,0.022803,0.069838,-0.001844,0.020190,-0.049075,-0.048242,0.025786,0.067670,-0.152904,0.038227,0.090410,-0.012939,-0.040886,-0.011291,0.012498,-0.020443,-0.048081,0.018145,0.055328,0.065196,-0.062635,-0.106917,0.064730,0.044867,-0.068668,-0.037746,0.057211,-0.034426,0.051337,-0.025572,0.046295,-0.011716,-0.006654,-0.030194,-0.051332,0.026101,0.104883,-0.007145,-0.070217,-0.000867,0.002503,-0.064973,0.037842,0.021236,0.023925,-0.017935,-0.079966,0.055120,-0.034364,0.071393,-0.029756,0.055380,-0.002203,0.004057,0.018498,0.023873,-0.042996,-0.027251,-0.031769,-0.023764,-0.056463,-0.019280,0.102642,-0.095517,0.071215,0.080328,-0.003316,0.068579,0.052600,0.053909,0.108883,0.012581,0.043106,0.031879,0.054328,-0.030787,-0.028546,-0.068817,-0.013480,0.036747,0.036505,-0.026683,0.034958,0.075650,0.001530,0.077361,-0.012978,-0.059580,-0.003257,-0.075410,0.026864,-0.090516,0.148559,-0.067887,-0.009229,0.107859,0.011224,0.026525,-0.020502,0.029137,0.059563,0.094475,0.072240,-0.095192,0.006081,0.021361,0.136805,-0.011188,-0.004593,0.007071,-0.166692,0.081480,0.042853,-0.013095,0.103005,0.036355,-0.033840,-0.017550,0.021768,0.056411,-0.041009,-0.057657,0.068774,0.006003,0.083118,-0.005328]}", + @"{""id"":""6"", ""word"":""time_NOUN"", ""embedding"":[0.028551,-0.088598,0.050082,0.007181,-0.104172,0.101837,0.035492,-0.016076,-0.036470,-0.031597,0.008517,0.081070,0.005958,0.011227,0.055194,-0.085483,-0.028711,-0.041737,-0.087045,0.040034,-0.014075,0.115195,0.014005,-0.067294,0.107071,-0.100702,-0.009378,-0.124226,0.017455,0.003322,0.005558,-0.061389,0.162625,-0.079217,-0.014027,0.008225,0.009872,0.019838,0.037906,-0.081853,0.025483,0.006533,-0.027086,-0.061254,0.021571,-0.058520,-0.030755,-0.037765,0.013022,0.099744,-0.015871,-0.040148,0.013853,0.174780,-0.030214,0.036497,-0.030496,-0.072386,0.129520,-0.039360,-0.012611,-0.044570,0.009870,0.027195,-0.018254,-0.064432,-0.027389,0.076080,0.017096,0.094141,-0.004854,-0.119384,-0.079426,-0.096194,-0.061261,-0.046198,-0.066695,-0.095495,0.071205,-0.035128,-0.109664,0.000560,-0.008151,0.001801,0.033679,0.077297,0.069809,0.126302,-0.106770,0.054766,-0.059580,-0.031521,0.100238,0.050529,-0.093611,0.014521,0.113995,0.047877,0.043517,0.046725,-0.064180,-0.012568,-0.001566,-0.058337,0.033448,0.017877,-0.060126,0.057385,-0.074544,0.033809,-0.063151,0.051488,-0.082470,0.012745,-0.012867,-0.022761,-0.073556,-0.064041,0.072679,0.004931,0.033317,-0.036562,0.097679,0.064440,0.006349,0.029687,0.079091,0.126180,0.017304,-0.055640,-0.004360,-0.071465,0.020999,0.020292,0.020851,-0.059998,0.026812,-0.025640,0.056559,0.062663,0.068633,0.003051,0.038869,-0.033266,-0.003146,-0.004676,-0.060268,-0.099329,-0.011529,-0.024929,0.052014,0.016963,0.007527,-0.074523,-0.107231,-0.095747,0.040862,0.055063,0.037597,0.030260,-0.060898,-0.035649,0.030211,-0.061037,-0.030174,0.025636,0.006325,-0.005351,-0.055750,0.042350,0.005378,-0.067135,-0.089138,-0.024828,-0.011560,0.063750,-0.050910,-0.029080,-0.003223,0.070240,-0.015769,0.085594,-0.091409,0.066143,-0.005699,-0.074672,0.015766,-0.008242,-0.016767,0.064410,-0.070908,-0.074450,0.005181,0.062501,-0.007251,-0.036160,-0.030252,-0.006774,-0.117676,0.085261,0.055248,0.023099,-0.001916,0.010082,0.004036,0.009452,0.009258,0.015016,0.040363,0.048659,0.021832,-0.100119,-0.093323,0.046102,0.003035,-0.010301,0.019116,0.004175,0.018846,0.026686,-0.200220,0.021341,-0.039848,0.050640,-0.026792,0.057337,-0.060018,0.013275,-0.043792,-0.020855,0.018315,-0.052217,-0.129547,-0.029040,-0.041891,-0.064859,-0.007379,-0.078831,-0.039299,-0.070625,-0.035255,0.058762,0.083695,0.085014,-0.052283,-0.005346,0.002431,0.030622,0.076632,-0.101137,0.037876,-0.031314,0.000538,-0.022329,0.090587,0.060532,-0.022718,-0.007348,0.040430,0.084318,-0.037918,-0.041699,0.064522,-0.004134,-0.056841,0.021044,0.019699,-0.000656,-0.051270,-0.011215,-0.010951,-0.015126,-0.095848,-0.043651,0.068587,-0.033160,0.112103,-0.069295,0.069698,-0.027304,-0.032045,0.011533,0.078525,0.012872,-0.072700,-0.018674,-0.048350,0.033240,0.006589,0.038484,0.049222,-0.036532,0.050987,0.054671,-0.073558,-0.075419,-0.051517,-0.082573,-0.022406,0.042652]}", + @"{""id"":""7"", ""word"":""take_VERB"", ""embedding"":[-0.085915,0.072050,0.061177,0.034385,-0.130897,-0.020019,0.041692,-0.001646,-0.000336,-0.085338,0.038205,0.018875,-0.083286,-0.061232,0.016179,0.066189,0.060670,0.000543,-0.135004,0.049699,-0.012316,-0.007948,-0.024639,-0.000349,-0.021084,-0.054148,0.061099,-0.111185,0.005860,-0.023507,0.029399,0.055637,0.049720,0.019389,0.024483,0.000545,-0.015728,-0.084071,-0.045200,-0.039850,-0.057122,-0.043768,-0.087916,-0.003074,0.094422,0.002184,0.054202,-0.081253,0.060053,0.047244,0.096669,0.020689,0.049919,0.160756,0.074185,0.068677,0.081737,0.046915,0.130613,0.003062,-0.094222,-0.038692,0.007875,0.048645,0.055408,-0.037991,-0.064129,0.057689,0.079305,0.059282,0.004156,0.006521,0.049386,-0.046141,-0.058870,-0.012268,-0.029792,-0.073071,-0.006719,-0.020783,-0.053037,-0.029306,-0.123163,-0.016259,-0.005775,-0.005656,0.082892,0.182866,-0.053775,0.081097,0.031257,-0.082803,0.072860,0.058470,-0.042368,-0.044028,-0.007983,0.027884,0.029243,-0.005043,-0.027391,-0.081547,0.087199,-0.054481,0.092473,0.073842,0.080296,0.116464,-0.060440,-0.112892,0.000785,0.031157,-0.055366,-0.042485,-0.029086,-0.058525,0.026030,-0.063302,0.052599,-0.005851,0.048085,-0.056849,-0.002640,0.003858,-0.009217,0.042292,0.014251,0.111839,0.003789,0.004826,-0.055015,0.037018,0.051596,0.034754,0.054819,-0.125969,-0.021572,-0.046395,0.050502,0.015387,0.046864,0.004564,0.036650,0.010489,0.024583,-0.036233,-0.043142,-0.063384,-0.008670,0.051395,0.047257,-0.015780,0.067077,-0.027996,-0.014117,-0.058627,0.018429,0.073644,0.050070,0.010536,0.027303,-0.002755,0.026361,-0.045678,-0.013685,0.031982,-0.006479,0.034540,-0.003912,0.057480,-0.007845,-0.097392,0.028641,-0.050393,0.085079,0.011244,-0.097678,0.007091,-0.027963,0.022363,0.002283,0.037801,-0.037196,0.169746,-0.038624,0.078767,-0.001875,0.054219,-0.052247,0.026505,-0.138177,-0.021248,-0.073399,0.058894,-0.001102,-0.008011,-0.044078,-0.001408,-0.078455,0.096208,-0.010742,-0.043702,0.079016,-0.018590,0.013306,0.022266,0.032821,0.004880,-0.002337,0.045593,-0.024818,-0.007891,0.008684,-0.061167,-0.045740,-0.051571,-0.049655,-0.008531,-0.006200,0.048838,-0.072153,0.049921,-0.059215,0.127064,0.040236,0.098747,-0.042659,-0.028465,-0.056385,0.065828,0.036884,-0.096360,0.006464,0.006201,0.056877,0.071954,0.114779,-0.087398,0.008548,0.044174,0.007840,-0.017414,0.046436,0.096034,-0.127091,-0.028683,-0.013463,-0.020997,-0.010382,-0.030867,0.037462,-0.108436,0.018027,-0.034779,0.058547,-0.068791,0.021402,-0.011831,0.002013,0.060412,-0.078119,-0.019209,0.013182,-0.094492,0.110161,-0.063736,0.046850,0.022188,0.007599,-0.007369,-0.058936,0.056017,-0.049103,-0.057295,0.058677,0.147318,0.107422,-0.079093,-0.010623,0.073036,0.024813,-0.045329,0.095850,0.046119,-0.086194,0.039533,-0.001355,0.052867,0.066449,-0.062630,0.020811,-0.032284,-0.087716,0.034099,-0.028051,-0.021583,-0.030066,-0.009957,0.022330,0.032838]}", + @"{""id"":""8"", ""word"":""know_VERB"", ""embedding"":[-0.025984,0.067260,0.034687,0.040777,-0.161350,0.013020,-0.007056,-0.024733,0.058577,0.032559,-0.012518,0.108795,0.025453,-0.025084,-0.102243,-0.040177,-0.021312,-0.043816,-0.081668,0.091292,0.038419,0.055116,0.035742,-0.050125,-0.018741,-0.049817,0.012086,-0.079459,-0.000711,-0.023625,0.013238,0.074507,0.030027,-0.001057,0.035990,-0.050576,-0.003847,0.060832,0.011826,0.008473,-0.015987,-0.049248,-0.043038,-0.075997,0.000403,0.001103,-0.003824,-0.029661,0.098314,0.062112,-0.109037,-0.013936,-0.008971,0.112062,-0.019038,-0.048354,0.006206,-0.070438,0.065072,0.018215,-0.104006,-0.086250,0.071208,0.083047,-0.001287,-0.120081,-0.014862,0.129383,0.042387,-0.065375,0.006762,-0.073221,-0.010304,-0.115515,0.007240,0.022477,-0.058240,-0.010925,-0.000522,-0.142643,0.035225,0.062995,-0.036440,-0.023326,0.043814,0.082391,0.105983,0.029809,-0.019996,0.034061,0.027599,-0.003354,-0.002728,0.053269,-0.012316,-0.085819,0.030923,0.038884,-0.022784,0.034281,-0.092045,-0.079878,-0.006614,-0.093812,0.035342,0.094636,-0.057155,0.051942,0.024737,-0.080949,-0.065721,-0.039007,-0.005870,-0.073761,0.076176,-0.017809,0.005946,-0.080602,0.032073,-0.102764,0.038929,-0.075056,-0.013560,-0.018190,0.069482,0.083503,0.027585,0.023521,0.014033,-0.036928,-0.005933,0.030368,0.006602,0.030084,0.044758,-0.018216,0.035520,-0.012898,0.045371,-0.001641,0.110703,0.017023,0.005551,0.045749,-0.005427,-0.074813,-0.010974,-0.010148,0.095004,0.013014,-0.005125,0.016952,-0.030893,-0.062859,-0.080818,-0.051509,0.006347,0.010265,-0.063437,0.009479,0.009224,0.006066,-0.008744,-0.104529,-0.025839,0.070249,0.095893,-0.047559,0.013237,0.055287,0.009931,-0.023470,-0.098192,-0.030587,0.049573,-0.017828,-0.071414,-0.018803,-0.014656,-0.002473,0.036026,0.041413,-0.054189,0.018682,0.084050,-0.029306,-0.026105,-0.016993,-0.026153,0.102438,-0.018404,-0.094386,0.000044,0.060043,-0.082400,-0.121982,-0.031880,-0.045073,-0.080735,0.012308,0.069106,-0.024642,0.040432,0.055083,-0.017416,0.011888,-0.057825,-0.112030,-0.016259,0.037437,0.081257,-0.035797,-0.070929,-0.093251,-0.083276,-0.047928,-0.043073,-0.057629,0.043480,0.033591,-0.152529,0.020240,0.020165,0.082562,-0.033501,0.070734,-0.085496,0.029878,-0.066357,0.026343,-0.050701,-0.037989,-0.134138,0.017599,-0.078392,0.056217,-0.005646,0.014984,0.065454,-0.014985,-0.032853,0.037999,0.024869,0.056706,0.094115,0.001015,0.021370,0.050369,0.088182,-0.045817,-0.098003,-0.092237,0.017012,-0.017444,0.094234,-0.003846,-0.046259,-0.039507,0.024746,0.046465,-0.040855,0.020798,-0.003858,-0.007113,0.013065,-0.084681,0.009278,0.061606,-0.135605,-0.049061,0.016939,0.093177,0.044400,-0.003246,0.153727,0.036902,0.033454,-0.019347,-0.016304,-0.004672,0.098153,0.026940,0.091487,0.098230,-0.060728,0.079308,-0.048837,0.049123,0.109093,-0.037728,0.096776,-0.065414,0.025478,0.105321,-0.037531,-0.086120,0.071593,-0.032246,-0.014722,-0.013469]}", + @"{""id"":""9"", ""word"":""year_NOUN"", ""embedding"":[-0.025786,-0.042872,0.017601,0.063622,-0.103329,0.023634,0.054678,0.040233,-0.051739,-0.064657,0.023516,0.033084,0.090718,0.051757,-0.013683,-0.097553,0.067920,-0.079240,-0.076960,0.099556,-0.005586,0.087658,0.021216,-0.030638,0.090439,-0.043562,0.046424,-0.070301,-0.073923,-0.085469,-0.028303,-0.072659,0.055611,-0.092044,0.070280,-0.034189,0.078083,0.056718,0.015751,-0.049231,0.043795,0.046121,-0.010422,-0.021453,-0.048846,-0.048375,0.018076,-0.139829,-0.001987,0.070634,-0.099343,-0.025047,-0.002585,0.108708,-0.068641,0.086222,0.025860,-0.030051,0.036753,-0.005112,-0.008837,-0.009897,0.013929,0.026580,-0.013089,0.020542,-0.060059,0.062302,0.095074,0.023722,0.034571,-0.059392,-0.000980,-0.000784,-0.061180,-0.069526,-0.018580,-0.118761,-0.012066,-0.083601,-0.028266,0.088769,-0.012761,0.118279,-0.012628,0.020282,0.053124,-0.029784,-0.087240,0.028490,-0.002649,-0.028264,0.074022,0.044470,-0.046292,0.062624,0.027311,0.075023,-0.005248,0.025290,0.033313,-0.107309,0.042446,-0.011116,0.009652,0.060412,0.024261,0.098144,-0.125430,-0.014803,-0.042813,-0.010587,-0.018827,-0.033675,0.056361,-0.035354,-0.044778,-0.009897,0.011386,0.035792,-0.002038,-0.031330,-0.009778,-0.001057,0.028198,-0.000704,0.023876,0.065053,0.046788,0.018013,-0.047985,-0.039999,-0.027081,0.060187,0.064933,-0.061414,0.052294,-0.003506,0.099521,-0.025471,0.085860,-0.024881,0.078323,-0.131082,0.120399,-0.000521,-0.042779,-0.023151,0.014987,-0.048307,-0.023339,0.023993,-0.050328,-0.055788,-0.087864,-0.023055,0.031015,0.043504,-0.011933,-0.047324,-0.022298,-0.056046,-0.028270,-0.041753,0.022536,0.032980,-0.093301,0.021712,0.044414,-0.027758,-0.076788,-0.021686,-0.067725,-0.004186,-0.008080,0.034993,-0.039559,-0.003645,-0.002335,-0.009184,0.008698,-0.002859,-0.058528,0.083969,0.069957,-0.043843,0.042897,-0.064762,0.021673,0.053250,-0.074874,-0.086903,-0.095449,-0.005371,0.064299,0.096931,0.043711,0.032208,-0.019445,0.214736,0.055460,-0.070967,0.015095,0.056014,-0.037825,0.039392,-0.034608,0.032038,0.103250,0.029820,0.038454,-0.064354,-0.128182,0.016288,0.015339,0.044159,-0.061186,-0.037290,-0.094278,0.066222,-0.148060,-0.024454,-0.018784,0.034114,0.040694,-0.008600,-0.029586,-0.024523,0.011347,0.001708,-0.033704,-0.051059,-0.074759,-0.042689,-0.059257,-0.045433,0.094440,-0.126478,0.037676,0.067256,0.119020,0.027962,0.120834,0.033210,-0.025278,-0.052161,0.016049,-0.021046,0.055670,-0.075887,-0.040669,-0.074454,-0.038057,0.063454,0.033169,0.035221,0.025169,0.037108,0.003785,0.011474,-0.060609,-0.065979,-0.102240,0.042050,0.028562,0.032571,-0.039410,-0.109837,-0.060135,0.050419,0.011264,-0.015715,0.044828,-0.046791,0.101858,-0.035604,-0.024885,-0.064720,0.043942]}", + }; + + private static readonly IReadOnlyList VectorDistanceTestCases = new List + { + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'Cosine'}}) ASC", + Expectations.DocumentsAreInCosineDistanceOrder()), + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'Cosine'}}) DESC", + Expectations.DocumentsAreInDescendingCosineDistanceOrder()), + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'DotProduct'}}) ASC", + Expectations.DocumentsAreInDotProductDistanceOrder()), + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'DotProduct'}}) DESC", + Expectations.DocumentsAreInDescendingDotProductDistanceOrder()), + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'Euclidean'}}) ASC", + Expectations.DocumentsAreInEuclideanDistanceOrder()), + MakeTest( + @"SELECT c.id AS Id, c.word AS Word " + + @"FROM c " + + @$"ORDER BY VectorDistance(""{Embedding}"", c.embedding, true, {{distanceFunction:'Euclidean'}}) DESC", + Expectations.DocumentsAreInDescendingEuclideanDistanceOrder()) + }; + + [Ignore("Requires new build of emulator and ServiceInterop from the 0318 branch")] + [TestMethod] + public async Task VectorDistanceTestsAsync() + { + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + Documents, + RunVectorDistanceTestsAsync); + } + + private static async Task RunVectorDistanceTestsAsync(Container container, IReadOnlyList _) + { + foreach (TestCase testCase in VectorDistanceTestCases) + { + Trace.WriteLine("Executing test case: "); + Trace.WriteLine(testCase.Query); + FeedIterator iterator = container.GetItemQueryIterator(testCase.Query); + + List documents = new List(); + while (iterator.HasMoreResults) + { + FeedResponse response = await iterator.ReadNextAsync(); + Assert.IsTrue(response.StatusCode.IsSuccess()); + + documents.AddRange(response.Resource); + } + + if (!testCase.Expected.SequenceEqual(documents)) + { + Trace.WriteLine("Mismatch between expected and actual results:"); + foreach (Document document in documents) + { + Trace.WriteLine(System.Text.Json.JsonSerializer.Serialize(document)); + } + + Assert.Fail(); + } + } + } + + private static TestCase MakeTest(string query, IEnumerable expected) + { + return new TestCase(query, expected); + } + + private sealed class TestCase + { + public string Query { get; } + + public IEnumerable Expected { get; } + + public TestCase(string query, IEnumerable expected) + { + this.Query = query ?? throw new ArgumentNullException(nameof(query)); + this.Expected = expected ?? throw new ArgumentNullException(nameof(expected)); + } + } + + private static class Expectations + { + public static IEnumerable DocumentsAreInCosineDistanceOrder() + { + return new[] + { + new Document {Id = "0", Word = "sayVERB"}, + new Document {Id = "8", Word = "know_VERB"}, + new Document {Id = "1", Word = "go_VERB"}, + new Document {Id = "3", Word = "get_VERB"}, + new Document {Id = "7", Word = "take_VERB"}, + new Document {Id = "5", Word = "see_VERB"}, + new Document {Id = "6", Word = "time_NOUN"}, + new Document {Id = "2", Word = "make_VERB"}, + new Document {Id = "4", Word = "one_NUM"}, + new Document {Id = "9", Word = "year_NOUN"}, + }; + } + + public static IEnumerable DocumentsAreInDotProductDistanceOrder() + { + return DocumentsAreInCosineDistanceOrder(); + } + + public static IEnumerable DocumentsAreInEuclideanDistanceOrder() + { + return DocumentsAreInCosineDistanceOrder(); + } + + public static IEnumerable DocumentsAreInDescendingCosineDistanceOrder() + { + return DocumentsAreInCosineDistanceOrder() + .Reverse(); + } + + public static IEnumerable DocumentsAreInDescendingDotProductDistanceOrder() + { + return DocumentsAreInDotProductDistanceOrder() + .Reverse(); + } + + public static IEnumerable DocumentsAreInDescendingEuclideanDistanceOrder() + { + return DocumentsAreInEuclideanDistanceOrder() + .Reverse(); + } + } + + private sealed class Document + { + public string Id { get; set; } + public string Word { get; set; } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs index c3cc566526..2c0f9d32b1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/QueryBaselineTest.cs @@ -3,21 +3,14 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest { - using Microsoft.Azure.Cosmos.EmulatorTests.Query; using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using Microsoft.Azure.Cosmos.Services.Management.Tests; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using System; - using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Xml; using System.Collections.Generic; - using System.Linq; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Serialization.HybridRow.Schemas; using Newtonsoft.Json.Linq; - using System.Collections.Concurrent; [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] public class QueryBaselineTest : BaselineTests diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockRequestHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockRequestHelper.cs index 7d3c88e84c..ae7a34e233 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockRequestHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockRequestHelper.cs @@ -144,7 +144,8 @@ public static StoreResponse GetStoreResponse(DocumentServiceRequest request) CurrentReplicaSetSize = "1", CurrentWriteQuorum = "1", CurrentResourceQuotaUsage = "documentSize=0;documentsSize=1;documentsCount=1;collectionSize=1;", - GlobalCommittedLSN = "-1", + GlobalCommittedLSN = "-1", + ItemCount = "1", LSN = "2540", LocalLSN = "2540", LastStateChangeUtc = "Wed, 18 Aug 2021 20:30:05.117 GMT", @@ -253,7 +254,8 @@ public static StoreResponse GetStoreResponse(DocumentServiceRequest request) if (request.ResourceType == ResourceType.Document && request.OperationType == OperationType.ReadFeed) - { + { + headers.ItemCount = "1"; return new StoreResponse() { ResponseBody = new MemoryStream(MockRequestHelper.testItemFeedResponsePayload, 0, MockRequestHelper.testItemFeedResponsePayload.Length, writable: false, publiclyVisible: true), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs index b9882b337f..9b109428b7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Program.cs @@ -4,14 +4,9 @@ namespace Microsoft.Azure.Cosmos.Performance.Tests { - using System; using System.Collections.Generic; - using System.Linq; - using System.Security.Cryptography.X509Certificates; - using BenchmarkDotNet.Configs; using BenchmarkDotNet.Reports; using BenchmarkDotNet.Running; - using Newtonsoft.Json; class Program { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs new file mode 100644 index 0000000000..4ec2009758 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs @@ -0,0 +1,325 @@ +namespace Microsoft.Azure.Cosmos.Performance.Tests.Query +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using BenchmarkDotNet.Attributes; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + + [MemoryDiagnoser] + public class OrderByPipelineStageBenchmark + { + private const int EndUserPageSize = 100; + + private const int MaxConcurrency = 10; + + private static readonly SqlQuerySpec SqlQuerySpec = new SqlQuerySpec(@" + SELECT c._rid AS _rid, [{""item"": c.index}] AS orderByItems, {""index"": c.index} AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.index"); + + private static readonly IReadOnlyList OrderByColumns = new List + { + new OrderByColumn("c.index", SortOrder.Ascending) + }; + + private static readonly IDocumentContainer StreamingContainer = MockDocumentContainer.Create(streaming: true); + + private static readonly IDocumentContainer NonStreamingContainer = MockDocumentContainer.Create(streaming: false); + + [Benchmark(Baseline = true)] + public Task StreamingOrderByPipelineStage() + { + return CreateAndRunPipeline(StreamingContainer); + } + + [Benchmark] + public Task NonStreamingOrderByPipelineStage() + { + return CreateAndRunPipeline(NonStreamingContainer); + } + + private static async Task CreateAndRunPipeline(IDocumentContainer documentContainer) + { + IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + + TryCatch pipelineStage = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: SqlQuerySpec, + targetRanges: ranges, + partitionKey: null, + orderByColumns: OrderByColumns, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: EndUserPageSize), + maxConcurrency: MaxConcurrency, + continuationToken: null); + + IQueryPipelineStage pipeline = pipelineStage.Result; + + int documentCount = 0; + while (await pipeline.MoveNextAsync(NoOpTrace.Singleton, CancellationToken.None)) + { + TryCatch tryGetQueryPage = pipeline.Current; + QueryPage queryPage = tryGetQueryPage.Result; + + List documents = new List(queryPage.Documents.Count); + foreach (CosmosElement document in queryPage.Documents) + { + documents.Add(document.ToString()); + } + + documentCount += documents.Count; + } + } + + private sealed class MockDocumentContainer : IDocumentContainer + { + private const int LeafPageCount = 100; + + private const int PageSize = 1000; + + private const string ActivityId = "ActivityId"; + + private const int QueryCharge = 42; + + private const string CollectionRid = "1HNeAM-TiQY="; + + private const string _rid = "_rid"; + + private const string orderByItems = "orderByItems"; + + private const string payload = "payload"; + + private const string item = "item"; + + private const string Index = "index"; + + private static readonly IReadOnlyDictionary AdditionalHeaders = new Dictionary + { + ["x-ms-query-test-header"] = "This is a test", + }; + + private readonly IReadOnlyDictionary> pages; + + private MockDocumentContainer(IReadOnlyDictionary> pages) + { + this.pages = pages ?? throw new ArgumentNullException(nameof(pages)); + } + + public static IDocumentContainer Create(bool streaming) + { + IReadOnlyList feedRanges = new List + { + new FeedRangeEpk(new Documents.Routing.Range(string.Empty, "AA", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("AA", "BB", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("BB", "CC", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("CC", "DD", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("DD", "EE", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("EE", "FF", true, false)), + }; + + int feedRangeIndex = 0; + Dictionary> pages = new Dictionary>(); + foreach (FeedRangeEpk feedRange in feedRanges) + { + int index = feedRangeIndex; + Dictionary leafPages = new Dictionary(); + for (int pageIndex = 0; pageIndex < LeafPageCount; ++pageIndex) + { + CosmosElement state = pageIndex == 0 ? CosmosNull.Create() : CosmosString.Create(pageIndex.ToString()); + CosmosElement continuationToken = pageIndex == LeafPageCount - 1 ? null : CosmosString.Create((pageIndex + 1).ToString()); + + List documents = new List(PageSize); + for (int documentCount = 0; documentCount < PageSize; ++documentCount) + { + documents.Add(CreateDocument(index)); + index += feedRanges.Count; + } + + QueryPage queryPage = new QueryPage( + documents: documents, + requestCharge: QueryCharge, + activityId: ActivityId, + cosmosQueryExecutionInfo: null, + distributionPlanSpec: null, + disallowContinuationTokenMessage: null, + state: continuationToken != null ? new QueryState(continuationToken) : null, + additionalHeaders: AdditionalHeaders, + streaming: streaming); + + leafPages.Add(state, queryPage); + } + + pages.Add(feedRange, leafPages); + ++feedRangeIndex; + } + + return new MockDocumentContainer(pages); + } + + private static CosmosElement CreateDocument(int index) + { + Documents.ResourceId resourceId = Documents.ResourceId.NewCollectionChildResourceId( + CollectionRid, + (ulong)index, + Documents.ResourceType.Document); + + CosmosElement document = CosmosObject.Create(new Dictionary + { + [_rid] = CosmosString.Create(resourceId.ToString()), + [orderByItems] = CosmosArray.Create(new List + { + CosmosObject.Create(new Dictionary + { + [item] = CosmosNumber64.Create(index) + }) + }), + [payload] = CosmosObject.Create(new Dictionary + { + [Index] = CosmosNumber64.Create(index) + }) + }); + + return document; + } + + public Task ChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task CreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> GetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> GetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult( + this.pages.Keys + .Cast() + .ToList()); + } + + public Task GetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicCreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task>> MonadicGetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task>> MonadicGetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult( + TryCatch>.FromResult( + this.pages.Keys + .Cast() + .ToList())); + } + + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicMergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public async Task> MonadicQueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + CosmosElement state = feedRangeState.State?.Value ?? CosmosNull.Create(); + QueryPage queryPage = this.pages[feedRangeState.FeedRange][state]; + + await Task.Delay(TimeSpan.FromMilliseconds(2)); + return TryCatch.FromResult(queryPage); + } + + public Task> MonadicReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicReadItemAsync(CosmosElement partitionKey, string identifer, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicRefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicSplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task QueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task ReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task ReadItemAsync(CosmosElement partitionKey, string identifier, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task RefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task SplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + } + + + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml index 27ddc7bc78..fb5f00ce1c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.ScenariosAsync.xml @@ -1,1628 +1,1626 @@ - - - - ReadFeed - (ReadFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), - new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default); - - int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. - TraceForBaselineTesting rootTrace; - using (rootTrace = TraceForBaselineTesting.GetRootTrace()) - { - while (await enumerator.MoveNextAsync(rootTrace)) - { - numChildren++; - } - } - - Assert.AreEqual(numChildren, rootTrace.Children.Count); -]]> - - - - - - - - - ChangeFeed - ( - ChangeFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), - new ChangeFeedPaginationOptions( - ChangeFeedMode.Incremental, - pageSizeHint: int.MaxValue), - cancellationToken: default); - - int numChildren = 0; - TraceForBaselineTesting rootTrace; - using (rootTrace = TraceForBaselineTesting.GetRootTrace()) - { - while (await enumerator.MoveNextAsync(rootTrace)) - { - numChildren++; - - if (enumerator.Current.Result.Page is ChangeFeedNotModifiedPage) - { - break; - } - } - } - - Assert.AreEqual(numChildren, rootTrace.Children.Count); -]]> - - - - - - - - - Query - - - - - - - + + + + ReadFeed + (ReadFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), + new ReadFeedPaginationOptions(pageSizeHint: 10)); + + int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. + TraceForBaselineTesting rootTrace; + using (rootTrace = TraceForBaselineTesting.GetRootTrace()) + { + while (await enumerator.MoveNextAsync(rootTrace, cancellationToken: default)) + { + numChildren++; + } + } + + Assert.AreEqual(numChildren, rootTrace.Children.Count); +]]> + + + + + + + + + ChangeFeed + ( + ChangeFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), + new ChangeFeedPaginationOptions( + ChangeFeedMode.Incremental, + pageSizeHint: int.MaxValue)); + + int numChildren = 0; + TraceForBaselineTesting rootTrace; + using (rootTrace = TraceForBaselineTesting.GetRootTrace()) + { + while (await enumerator.MoveNextAsync(rootTrace, cancellationToken: default)) + { + numChildren++; + + if (enumerator.Current.Result.Page is ChangeFeedNotModifiedPage) + { + break; + } + } + } + + Assert.AreEqual(numChildren, rootTrace.Children.Count); +]]> + + + + + + + + + Query + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/CrossPartitionChangeFeedAsyncEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/CrossPartitionChangeFeedAsyncEnumeratorTests.cs index 8056fcf076..5ad11ec019 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/CrossPartitionChangeFeedAsyncEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/CrossPartitionChangeFeedAsyncEnumeratorTests.cs @@ -34,10 +34,9 @@ public async Task NoChangesAsync() { new FeedRangeState(FeedRangeEpk.FullRange, ChangeFeedState.Beginning()) }), - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); - Assert.IsTrue(await enumerator.MoveNextAsync()); + Assert.IsTrue(await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); Assert.IsTrue(enumerator.Current.Succeeded); Assert.IsTrue(enumerator.Current.Result.Page is ChangeFeedNotModifiedPage); Assert.IsNotNull(enumerator.Current.Result.State); @@ -54,16 +53,15 @@ public async Task SomeChangesAsync() { new FeedRangeState(FeedRangeEpk.FullRange, ChangeFeedState.Beginning()) }), - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); // First page should be true and skip the 304 not modified - Assert.IsTrue(await enumerator.MoveNextAsync()); + Assert.IsTrue(await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); Assert.IsTrue(enumerator.Current.Succeeded); Assert.IsTrue(enumerator.Current.Result.Page is ChangeFeedSuccessPage); // Second page should surface up the 304 - Assert.IsTrue(await enumerator.MoveNextAsync()); + Assert.IsTrue(await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); Assert.IsTrue(enumerator.Current.Succeeded); Assert.IsTrue(enumerator.Current.Result.Page is ChangeFeedNotModifiedPage); } @@ -82,8 +80,7 @@ public async Task StartFromBeginningAsync(bool useContinuations) { new FeedRangeState(FeedRangeEpk.FullRange, ChangeFeedState.Beginning()) }), - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); (int globalCount, double _) = await (useContinuations ? DrainWithUntilNotModifiedWithContinuationTokens(documentContainer, enumerator) @@ -105,8 +102,7 @@ public async Task StartFromTimeAsync(bool useContinuations) { new FeedRangeState(FeedRangeEpk.FullRange, ChangeFeedState.Time(DateTime.UtcNow)) }), - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); for (int i = 0; i < numItems; i++) { @@ -143,8 +139,7 @@ public async Task StartFromNowAsync(bool useContinuations) { new FeedRangeState(FeedRangeEpk.FullRange, ChangeFeedState.Now()) }), - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); (int globalCount, double _) = await (useContinuations ? DrainWithUntilNotModifiedWithContinuationTokens(documentContainer, enumerator) @@ -221,8 +216,7 @@ public async Task ShouldReturnNotModifiedAfterCyclingOnAllRanges(int partitions) CrossPartitionChangeFeedAsyncEnumerator enumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( documentContainer.Object, state, - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); (int _, double requestCharge) = await DrainUntilNotModifedAsync(enumerator); @@ -323,7 +317,13 @@ public async Task ShouldSkipNotModifiedAndReturnResults() It.IsAny(), It.IsAny())).ReturnsAsync( (FeedRangeState state, ChangeFeedPaginationOptions options, ITrace trace, CancellationToken token) - => TryCatch.FromResult(new ChangeFeedSuccessPage(content: new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), requestCharge: 5, activityId: string.Empty, additionalHeaders: default, state.State))); + => TryCatch.FromResult(new ChangeFeedSuccessPage( + content: new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), + requestCharge: 5, + itemCount: 0, + activityId: string.Empty, + additionalHeaders: default, + state.State))); // Returns a 304 with 1RU charge on CC-FF documentContainer.Setup(c => c.MonadicChangeFeedAsync( @@ -337,8 +337,7 @@ public async Task ShouldSkipNotModifiedAndReturnResults() CrossPartitionChangeFeedAsyncEnumerator enumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( documentContainer.Object, state, - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); (int _, double requestCharge) = await DrainUntilSuccessAsync(enumerator); @@ -399,12 +398,11 @@ public async Task ShouldReturnTryCatchOnException() CrossPartitionChangeFeedAsyncEnumerator enumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( documentContainer.Object, state, - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); try { - await enumerator.MoveNextAsync(NoOpTrace.Singleton); + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); Assert.Fail("Should have thrown"); } catch (Exception caughtException) @@ -415,7 +413,7 @@ public async Task ShouldReturnTryCatchOnException() // Should be able to read MoveNextAsync again try { - await enumerator.MoveNextAsync(NoOpTrace.Singleton); + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); Assert.Fail("Should have thrown"); } catch (Exception caughtException) @@ -428,7 +426,7 @@ public async Task ShouldReturnTryCatchOnException() { int globalCount = 0; double requestCharge = 0; - while (await enumerator.MoveNextAsync()) + while (await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { Assert.IsTrue(enumerator.Current.Succeeded); requestCharge += enumerator.Current.Result.Page.RequestCharge; @@ -447,7 +445,7 @@ public async Task ShouldReturnTryCatchOnException() { int globalCount = 0; double requestCharge = 0; - while (await enumerator.MoveNextAsync()) + while (await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { Assert.IsTrue(enumerator.Current.Succeeded); requestCharge += enumerator.Current.Result.Page.RequestCharge; @@ -469,7 +467,7 @@ public async Task ShouldReturnTryCatchOnException() List globalChanges = new List(); while (true) { - if (!await enumerator.MoveNextAsync()) + if (!await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { throw new InvalidOperationException(); } @@ -488,8 +486,7 @@ public async Task ShouldReturnTryCatchOnException() enumerator = CrossPartitionChangeFeedAsyncEnumerator.Create( documentContainer, enumerator.Current.Result.State, - ChangeFeedPaginationOptions.Default, - cancellationToken: default); + ChangeFeedPaginationOptions.Default); } return (globalChanges.Count, requestCharge); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs index a8f5c4810c..2095773937 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ChangeFeed/NetworkAttachedDocumentContainerTests.cs @@ -62,7 +62,8 @@ public async Task MonadicChangeFeedAsync_ChangeFeedMode_Incremental() ResponseMessage response = new ResponseMessage(System.Net.HttpStatusCode.NotModified); response.Headers.ETag = Guid.NewGuid().ToString(); response.Headers.ActivityId = Guid.NewGuid().ToString(); - response.Headers.RequestCharge = 1; + response.Headers.RequestCharge = 1; + response.Headers[HttpConstants.HttpHeaders.ItemCount] = "0"; context.SetupSequence(c => c.ProcessResourceOperationStreamAsync( It.IsAny(), @@ -121,7 +122,8 @@ public async Task MonadicChangeFeedAsync_ChangeFeedMode_FullFidelity() ResponseMessage response = new ResponseMessage(System.Net.HttpStatusCode.NotModified); response.Headers.ETag = Guid.NewGuid().ToString(); response.Headers.ActivityId = Guid.NewGuid().ToString(); - response.Headers.RequestCharge = 1; + response.Headers.RequestCharge = 1; + response.Headers[HttpConstants.HttpHeaders.ItemCount] = "0"; context.SetupSequence(c => c.ProcessResourceOperationStreamAsync( It.IsAny(), diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs index cbaf45fe88..b488455965 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs @@ -45,7 +45,8 @@ public async Task QueryConflicts() ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK) { Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Conflicts"": [{ ""id"": ""Test""}]}")) - }; + }; + responseMessage.Headers.Add(HttpConstants.HttpHeaders.ItemCount, "1"); return Task.FromResult(responseMessage); }); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs index 227785f791..43482842ff 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosJsonSerializerUnitTests.cs @@ -424,7 +424,6 @@ private ResponseMessage CreateQueryResponse() ResponseMessage cosmosResponse = QueryResponse.CreateSuccess( cosmosElements, 1, - Encoding.UTF8.GetByteCount(serializedItem), new CosmosQueryResponseMessageHeaders( continauationToken: null, disallowContinuationTokenMessage: null, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/BufferedPartitionRangeEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/BufferedPartitionRangeEnumeratorTests.cs index 62114fcdf9..7b8133c2ea 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/BufferedPartitionRangeEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/BufferedPartitionRangeEnumeratorTests.cs @@ -5,10 +5,8 @@ using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.VisualStudio.TestTools.UnitTesting; - using System; using System.Threading; using Microsoft.Azure.Cosmos.ReadFeed.Pagination; - using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tests.Query.Pipeline; @@ -134,8 +132,7 @@ public async Task TestSplitAsync(bool aggressivePrefetch, bool exercisePrefetch) (feedRangeState) => new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton); HashSet resourceIdentifiers = await this.DrainFullyAsync(enumerable); @@ -158,18 +155,14 @@ public async Task TestBufferPageAsync(bool aggressivePrefetch, bool exercisePref feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default) : + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))) : new BufferedPartitionRangePageAsyncEnumerator( new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))); int count = 0; @@ -179,7 +172,7 @@ public async Task TestBufferPageAsync(bool aggressivePrefetch, bool exercisePref await enumerator.PrefetchAsync(trace: NoOpTrace.Singleton, default); } - while (await enumerator.MoveNextAsync(NoOpTrace.Singleton)) + while (await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { count += enumerator.Current.Result.GetRecords().Count; if (exercisePrefetch) @@ -209,18 +202,14 @@ public async Task TestMoveNextAndBufferPageAsync(bool aggressivePrefetch, bool e feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default) : + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))) : new BufferedPartitionRangePageAsyncEnumerator( new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))); if (exercisePrefetch) { @@ -228,7 +217,7 @@ public async Task TestMoveNextAndBufferPageAsync(bool aggressivePrefetch, bool e } int count = 0; - while (await enumerator.MoveNextAsync(NoOpTrace.Singleton)) + while (await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { count += enumerator.Current.Result.GetRecords().Count; @@ -259,16 +248,12 @@ PartitionRangePageAsyncEnumerator CreateBufferedEnu new ReadFeedPartitionRangeEnumerator( documentContainer, feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default) : + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))) : new BufferedPartitionRangePageAsyncEnumerator( new ReadFeedPartitionRangeEnumerator( documentContainer, feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - cancellationToken: default); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))); return enumerator; }; @@ -295,18 +280,14 @@ protected async override Task>> CreateEn feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), state ?? ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: cancellationToken), - cancellationToken: cancellationToken) : + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))) : new BufferedPartitionRangePageAsyncEnumerator( new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), state ?? ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: cancellationToken), - cancellationToken: cancellationToken); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10))); if (exercisePrefetch) { @@ -315,7 +296,8 @@ protected async override Task>> CreateEn return new TracingAsyncEnumerator>( enumerator: enumerator, - trace: NoOpTrace.Singleton); + trace: NoOpTrace.Singleton, + cancellationToken: default); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/CrossPartitionPartitionRangeEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/CrossPartitionPartitionRangeEnumeratorTests.cs index 20338aa768..33b2c9d42d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/CrossPartitionPartitionRangeEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/CrossPartitionPartitionRangeEnumeratorTests.cs @@ -1,462 +1,457 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Tests.Pagination -{ - using System; - using System.Collections.Generic; - using System.IO; - using System.Linq; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.ReadFeed.Pagination; - using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; - using Microsoft.Azure.Cosmos.Tests.Query.Pipeline; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Moq; - - [TestClass] - public sealed class CrossPartitionPartitionRangeEnumeratorTests - { - [TestMethod] - public async Task Test429sAsync() - { - Implementation implementation = new Implementation(false); - await implementation.Test429sAsync(false); - } - - [TestMethod] - public async Task Test429sWithContinuationsAsync() - { - Implementation implementation = new Implementation(false); - await implementation.Test429sWithContinuationsAsync(false, false); - } - - [TestMethod] - [DataRow(false)] - [DataRow(true)] - public async Task TestEmptyPages(bool aggressivePrefetch) - { - Implementation implementation = new Implementation(false); - await implementation.TestEmptyPages(aggressivePrefetch); - } - - [TestMethod] - public async Task TestMergeToSinglePartition() - { - Implementation implementation = new Implementation(true); - await implementation.TestMergeToSinglePartition(); - } - - // Validates that on a merge (split with 1 result) we do not create new child enumerators for the merge result - [TestMethod] - public async Task OnMergeRequeueRange() - { - // We expect only creation of enumerators for the original ranges, not any child ranges - List createdEnumerators = new List(); - PartitionRangePageAsyncEnumerator createEnumerator( - FeedRangeState feedRangeState) - { - EnumeratorThatSplits enumerator = new EnumeratorThatSplits(feedRangeState, default, createdEnumerators.Count == 0); - createdEnumerators.Add(enumerator); - return enumerator; - } - - // We expect a request for children and we return the merged range - Mock feedRangeProvider = new Mock(); - feedRangeProvider.Setup(p => p.GetChildRangeAsync( - It.Is(splitRange => ((FeedRangeEpk)splitRange).Range.Min == "" && ((FeedRangeEpk)splitRange).Range.Max == "A"), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(new List() { - FeedRangeEpk.FullRange}); - - CrossPartitionRangePageAsyncEnumerator enumerator = new CrossPartitionRangePageAsyncEnumerator( - feedRangeProvider: feedRangeProvider.Object, - createPartitionRangeEnumerator: createEnumerator, - comparer: null, - maxConcurrency: 0, - prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, - state: new CrossFeedRangeState( - new FeedRangeState[] - { - // start with 2 ranges - new FeedRangeState(new FeedRangeEpk(new Documents.Routing.Range("", "A", true, false)), ReadFeedState.Beginning()), - new FeedRangeState(new FeedRangeEpk(new Documents.Routing.Range("A", "FF", true, false)), ReadFeedState.Beginning()) - })); - - // Trigger merge, should requeue and read second enumerator - await enumerator.MoveNextAsync(NoOpTrace.Singleton); - - // Should read first enumerator again - await enumerator.MoveNextAsync(NoOpTrace.Singleton); - - Assert.AreEqual(2, createdEnumerators.Count, "Should only create the original 2 enumerators"); - Assert.AreEqual("", ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Min); - Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Max); - Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Min); - Assert.AreEqual("FF", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Max); - - Assert.AreEqual(2, createdEnumerators[0].GetNextPageAsyncCounter, "First enumerator should have been requeued and called again"); - Assert.AreEqual(1, createdEnumerators[1].GetNextPageAsyncCounter, "Second enumerator should be used once"); - } - - // Validates that on a split we create children enumerators and use them - [TestMethod] - public async Task OnSplitQueueNewEnumerators() - { - // We expect creation of the initial full range enumerator and the 2 children - List createdEnumerators = new List(); - PartitionRangePageAsyncEnumerator createEnumerator( - FeedRangeState feedRangeState) - { - EnumeratorThatSplits enumerator = new EnumeratorThatSplits(feedRangeState, default, createdEnumerators.Count == 0); - createdEnumerators.Add(enumerator); - return enumerator; - } - - // We expect a request for children and we return the new children - Mock feedRangeProvider = new Mock(); - feedRangeProvider.Setup(p => p.GetChildRangeAsync( - It.Is(splitRange => ((FeedRangeEpk)splitRange).Range.Min == FeedRangeEpk.FullRange.Range.Min && ((FeedRangeEpk)splitRange).Range.Max == FeedRangeEpk.FullRange.Range.Max), - It.IsAny(), - It.IsAny())) - .ReturnsAsync(new List() { - new FeedRangeEpk(new Documents.Routing.Range("", "A", true, false)), - new FeedRangeEpk(new Documents.Routing.Range("A", "FF", true, false))}); - - CrossPartitionRangePageAsyncEnumerator enumerator = new CrossPartitionRangePageAsyncEnumerator( - feedRangeProvider: feedRangeProvider.Object, - createPartitionRangeEnumerator: createEnumerator, - comparer: null, - prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - maxConcurrency: 0, - cancellationToken: default, - state: new CrossFeedRangeState( - new FeedRangeState[] - { - // start with 1 range - new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) - })); - - // Trigger split, should create children and call first children - await enumerator.MoveNextAsync(NoOpTrace.Singleton); - - // Should read second children - await enumerator.MoveNextAsync(NoOpTrace.Singleton); - - Assert.AreEqual(3, createdEnumerators.Count, "Should have the original enumerator and the children"); - Assert.AreEqual(FeedRangeEpk.FullRange.Range.Min, ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Min); - Assert.AreEqual(FeedRangeEpk.FullRange.Range.Max, ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Max); - Assert.AreEqual("", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Min); - Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Max); - Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[2].FeedRangeState.FeedRange).Range.Min); - Assert.AreEqual("FF", ((FeedRangeEpk)createdEnumerators[2].FeedRangeState.FeedRange).Range.Max); - - Assert.AreEqual(1, createdEnumerators[0].GetNextPageAsyncCounter, "First enumerator should have been called once"); - Assert.AreEqual(1, createdEnumerators[1].GetNextPageAsyncCounter, "Second enumerator should have been called once"); - Assert.AreEqual(1, createdEnumerators[2].GetNextPageAsyncCounter, "Second enumerator should not be used"); - } - - private class EnumeratorThatSplits : PartitionRangePageAsyncEnumerator - { - private readonly bool throwError; - - public EnumeratorThatSplits( - FeedRangeState feedRangeState, - CancellationToken cancellationToken, - bool throwError = true) - : base(feedRangeState, cancellationToken) - { - this.throwError = throwError; - } - - public override ValueTask DisposeAsync() - { - throw new NotImplementedException(); - } - - public int GetNextPageAsyncCounter { get; private set; } - - protected override Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken) - { - this.GetNextPageAsyncCounter++; - - if (this.GetNextPageAsyncCounter == 1 - && this.throwError) - { - CosmosException splitError = new CosmosException("merge", System.Net.HttpStatusCode.Gone, (int)Documents.SubStatusCodes.PartitionKeyRangeGone, string.Empty, 0); - TryCatch state = TryCatch.FromException(splitError); - return Task.FromResult(state); - } - else - { - return Task.FromResult(TryCatch.FromResult( - new ReadFeedPage( - new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), - requestCharge: 1, - activityId: Guid.NewGuid().ToString(), - additionalHeaders: null, - state: ReadFeedState.Beginning()))); - } - } - } - - [TestMethod] - [DataRow(false, false, false, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: false")] - [DataRow(false, false, true, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: true")] - [DataRow(false, true, false, DisplayName = "Use State: false, Allow Splits: true, Allow Merges: false")] - [DataRow(false, true, true, DisplayName = "Use State: false, Allow Splits: true, Allow Merges: true")] - [DataRow(true, false, false, DisplayName = "Use State: true, Allow Splits: false, Allow Merges: false")] - [DataRow(true, false, true, DisplayName = "Use State: true, Allow Splits: false, Allow Merges: true")] - [DataRow(true, true, false, DisplayName = "Use State: true, Allow Splits: true, Allow Merges: false")] - [DataRow(true, true, true, DisplayName = "Use State: true, Allow Splits: true, Allow Merges: true")] - public async Task TestSplitAndMergeAsync(bool useState, bool allowSplits, bool allowMerges) - { - Implementation implementation = new Implementation(singlePartition: false); - await implementation.TestSplitAndMergeImplementationAsync(useState, allowSplits, allowMerges); - } - - private sealed class Implementation : PartitionRangeEnumeratorTests, CrossFeedRangeState> - { - enum TriState { NotReady, Ready, Done }; - - public Implementation(bool singlePartition) - : base(singlePartition) - { - this.ShouldMerge = TriState.NotReady; - } - - private TriState ShouldMerge { get; set; } - - private IDocumentContainer DocumentContainer { get; set; } - - private async Task ShouldReturnFailure() - { - if (this.ShouldMerge == TriState.Ready) - { - await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); - List ranges = await this.DocumentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - - await this.DocumentContainer.MergeAsync(ranges[0], ranges[1], default); - await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, default); - this.ShouldMerge = TriState.Done; - - return new CosmosException( - message: "PKRange was split/merged", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)Documents.SubStatusCodes.PartitionKeyRangeGone, - activityId: "BC0CCDA5-D378-4922-B8B0-D51D745B9139", - requestCharge: 0.0); - } - else - { - return null; - } - } - - public async Task TestMergeToSinglePartition() - { - int numItems = 1000; - FlakyDocumentContainer.FailureConfigs config = new FlakyDocumentContainer.FailureConfigs( - inject429s: false, - injectEmptyPages: false, - shouldReturnFailure: this.ShouldReturnFailure); - - this.DocumentContainer = await this.CreateDocumentContainerAsync(numItems: numItems, failureConfigs: config); - - await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); - List ranges = await this.DocumentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - await this.DocumentContainer.SplitAsync(ranges.First(), cancellationToken: default); - - IAsyncEnumerator>> enumerator = await this.CreateEnumeratorAsync(this.DocumentContainer); - List identifiers = new List(); - int iteration = 0; - while (await enumerator.MoveNextAsync()) - { - TryCatch> tryGetPage = enumerator.Current; - tryGetPage.ThrowIfFailed(); - - IReadOnlyList records = this.GetRecordsFromPage(tryGetPage.Result); - foreach (Record record in records) - { - identifiers.Add(record.Payload["pk"].ToString()); - } - - ++iteration; - if (iteration == 1) - { - this.ShouldMerge = TriState.Ready; - } - } - - Assert.AreEqual(numItems, identifiers.Count); - } - - public async Task TestSplitAndMergeImplementationAsync( - bool useState, - bool allowSplits, - bool allowMerges) - { - int numItems = 1000; - IDocumentContainer inMemoryCollection = await this.CreateDocumentContainerAsync(numItems); - IAsyncEnumerator>> enumerator = await this.CreateEnumeratorAsync(inMemoryCollection); - HashSet identifiers = new HashSet(); - Random random = new Random(); - while (await enumerator.MoveNextAsync()) - { - TryCatch> tryGetPage = enumerator.Current; - tryGetPage.ThrowIfFailed(); - - IReadOnlyList records = this.GetRecordsFromPage(tryGetPage.Result); - foreach (Record record in records) - { - identifiers.Add(record.Payload["pk"].ToString()); - } - - if (useState) - { - if (tryGetPage.Result.State == null) - { - break; - } - - enumerator = await this.CreateEnumeratorAsync( - inMemoryCollection, - false, - false, - tryGetPage.Result.State); - } - - if (random.Next() % 2 == 0) - { - if (allowSplits && (random.Next() % 2 == 0)) - { - // Split - await inMemoryCollection.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); - List ranges = await inMemoryCollection.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - FeedRangeInternal randomRangeToSplit = ranges[random.Next(0, ranges.Count)]; - await inMemoryCollection.SplitAsync(randomRangeToSplit, cancellationToken: default); - } - - if (allowMerges && (random.Next() % 2 == 0)) - { - // Merge - await inMemoryCollection.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); - List ranges = await inMemoryCollection.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - if (ranges.Count > 1) - { - ranges = ranges.OrderBy(range => range.Range.Min).ToList(); - int indexToMerge = random.Next(0, ranges.Count); - int adjacentIndex = indexToMerge == (ranges.Count - 1) ? indexToMerge - 1 : indexToMerge + 1; - await inMemoryCollection.MergeAsync(ranges[indexToMerge], ranges[adjacentIndex], cancellationToken: default); - } - } - } - } - - Assert.AreEqual(numItems, identifiers.Count); - } - - protected override IAsyncEnumerable>> CreateEnumerable( - IDocumentContainer inMemoryCollection, - bool aggressivePrefetch = false, - CrossFeedRangeState state = null) - { - PartitionRangePageAsyncEnumerator createEnumerator( - FeedRangeState feedRangeState) => new ReadFeedPartitionRangeEnumerator( - inMemoryCollection, - feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default); - - return new CrossPartitionRangePageAsyncEnumerable( - feedRangeProvider: inMemoryCollection, - createPartitionRangeEnumerator: createEnumerator, - comparer: PartitionRangePageAsyncEnumeratorComparer.Singleton, - maxConcurrency: 10, - prefetchPolicy: aggressivePrefetch ? PrefetchPolicy.PrefetchAll : PrefetchPolicy.PrefetchSinglePage, - trace: NoOpTrace.Singleton, - state: state ?? new CrossFeedRangeState( - new FeedRangeState[] - { - new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) - })); - } - - protected override Task>>> CreateEnumeratorAsync( - IDocumentContainer inMemoryCollection, - bool aggressivePrefetch = false, - bool exercisePrefetch = false, - CrossFeedRangeState state = null, - CancellationToken cancellationToken = default) - { - PartitionRangePageAsyncEnumerator createEnumerator( - FeedRangeState feedRangeState) - { - return new ReadFeedPartitionRangeEnumerator( - inMemoryCollection, - feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default); - } - - IAsyncEnumerator>> enumerator = new TracingAsyncEnumerator>>( - new CrossPartitionRangePageAsyncEnumerator( - feedRangeProvider: inMemoryCollection, - createPartitionRangeEnumerator: createEnumerator, - comparer: PartitionRangePageAsyncEnumeratorComparer.Singleton, - maxConcurrency: 10, - prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: cancellationToken, - state: state ?? new CrossFeedRangeState( - new FeedRangeState[] - { - new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) - })), - NoOpTrace.Singleton); - - return Task.FromResult(enumerator); - } - - public override IReadOnlyList GetRecordsFromPage(CrossFeedRangePage page) - { - return page.Page.GetRecords(); - } - - private sealed class PartitionRangePageAsyncEnumeratorComparer : IComparer> - { - public static readonly PartitionRangePageAsyncEnumeratorComparer Singleton = new PartitionRangePageAsyncEnumeratorComparer(); - - public int Compare( - PartitionRangePageAsyncEnumerator partitionRangePageEnumerator1, - PartitionRangePageAsyncEnumerator partitionRangePageEnumerator2) - { - if (object.ReferenceEquals(partitionRangePageEnumerator1, partitionRangePageEnumerator2)) - { - return 0; - } - - // Either both don't have results or both do. - return string.CompareOrdinal( - ((FeedRangeEpk)partitionRangePageEnumerator1.FeedRangeState.FeedRange).Range.Min, - ((FeedRangeEpk)partitionRangePageEnumerator2.FeedRangeState.FeedRange).Range.Min); - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Pagination +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Tests.Query.Pipeline; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; + + [TestClass] + public sealed class CrossPartitionPartitionRangeEnumeratorTests + { + [TestMethod] + public async Task Test429sAsync() + { + Implementation implementation = new Implementation(false); + await implementation.Test429sAsync(false); + } + + [TestMethod] + public async Task Test429sWithContinuationsAsync() + { + Implementation implementation = new Implementation(false); + await implementation.Test429sWithContinuationsAsync(false, false); + } + + [TestMethod] + [DataRow(false)] + [DataRow(true)] + public async Task TestEmptyPages(bool aggressivePrefetch) + { + Implementation implementation = new Implementation(false); + await implementation.TestEmptyPages(aggressivePrefetch); + } + + [TestMethod] + public async Task TestMergeToSinglePartition() + { + Implementation implementation = new Implementation(true); + await implementation.TestMergeToSinglePartition(); + } + + // Validates that on a merge (split with 1 result) we do not create new child enumerators for the merge result + [TestMethod] + public async Task OnMergeRequeueRange() + { + // We expect only creation of enumerators for the original ranges, not any child ranges + List createdEnumerators = new List(); + PartitionRangePageAsyncEnumerator createEnumerator( + FeedRangeState feedRangeState) + { + EnumeratorThatSplits enumerator = new EnumeratorThatSplits(feedRangeState, createdEnumerators.Count == 0); + createdEnumerators.Add(enumerator); + return enumerator; + } + + // We expect a request for children and we return the merged range + Mock feedRangeProvider = new Mock(); + feedRangeProvider.Setup(p => p.GetChildRangeAsync( + It.Is(splitRange => ((FeedRangeEpk)splitRange).Range.Min == "" && ((FeedRangeEpk)splitRange).Range.Max == "A"), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(new List() { + FeedRangeEpk.FullRange}); + + CrossPartitionRangePageAsyncEnumerator enumerator = new CrossPartitionRangePageAsyncEnumerator( + feedRangeProvider: feedRangeProvider.Object, + createPartitionRangeEnumerator: createEnumerator, + comparer: null, + maxConcurrency: 0, + prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, + state: new CrossFeedRangeState( + new FeedRangeState[] + { + // start with 2 ranges + new FeedRangeState(new FeedRangeEpk(new Documents.Routing.Range("", "A", true, false)), ReadFeedState.Beginning()), + new FeedRangeState(new FeedRangeEpk(new Documents.Routing.Range("A", "FF", true, false)), ReadFeedState.Beginning()) + })); + + // Trigger merge, should requeue and read second enumerator + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); + + // Should read first enumerator again + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); + + Assert.AreEqual(2, createdEnumerators.Count, "Should only create the original 2 enumerators"); + Assert.AreEqual("", ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Min); + Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Max); + Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Min); + Assert.AreEqual("FF", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Max); + + Assert.AreEqual(2, createdEnumerators[0].GetNextPageAsyncCounter, "First enumerator should have been requeued and called again"); + Assert.AreEqual(1, createdEnumerators[1].GetNextPageAsyncCounter, "Second enumerator should be used once"); + } + + // Validates that on a split we create children enumerators and use them + [TestMethod] + public async Task OnSplitQueueNewEnumerators() + { + // We expect creation of the initial full range enumerator and the 2 children + List createdEnumerators = new List(); + PartitionRangePageAsyncEnumerator createEnumerator( + FeedRangeState feedRangeState) + { + EnumeratorThatSplits enumerator = new EnumeratorThatSplits(feedRangeState, createdEnumerators.Count == 0); + createdEnumerators.Add(enumerator); + return enumerator; + } + + // We expect a request for children and we return the new children + Mock feedRangeProvider = new Mock(); + feedRangeProvider.Setup(p => p.GetChildRangeAsync( + It.Is(splitRange => ((FeedRangeEpk)splitRange).Range.Min == FeedRangeEpk.FullRange.Range.Min && ((FeedRangeEpk)splitRange).Range.Max == FeedRangeEpk.FullRange.Range.Max), + It.IsAny(), + It.IsAny())) + .ReturnsAsync(new List() { + new FeedRangeEpk(new Documents.Routing.Range("", "A", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("A", "FF", true, false))}); + + CrossPartitionRangePageAsyncEnumerator enumerator = new CrossPartitionRangePageAsyncEnumerator( + feedRangeProvider: feedRangeProvider.Object, + createPartitionRangeEnumerator: createEnumerator, + comparer: null, + prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, + maxConcurrency: 0, + state: new CrossFeedRangeState( + new FeedRangeState[] + { + // start with 1 range + new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) + })); + + // Trigger split, should create children and call first children + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); + + // Should read second children + await enumerator.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); + + Assert.AreEqual(3, createdEnumerators.Count, "Should have the original enumerator and the children"); + Assert.AreEqual(FeedRangeEpk.FullRange.Range.Min, ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Min); + Assert.AreEqual(FeedRangeEpk.FullRange.Range.Max, ((FeedRangeEpk)createdEnumerators[0].FeedRangeState.FeedRange).Range.Max); + Assert.AreEqual("", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Min); + Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[1].FeedRangeState.FeedRange).Range.Max); + Assert.AreEqual("A", ((FeedRangeEpk)createdEnumerators[2].FeedRangeState.FeedRange).Range.Min); + Assert.AreEqual("FF", ((FeedRangeEpk)createdEnumerators[2].FeedRangeState.FeedRange).Range.Max); + + Assert.AreEqual(1, createdEnumerators[0].GetNextPageAsyncCounter, "First enumerator should have been called once"); + Assert.AreEqual(1, createdEnumerators[1].GetNextPageAsyncCounter, "Second enumerator should have been called once"); + Assert.AreEqual(1, createdEnumerators[2].GetNextPageAsyncCounter, "Second enumerator should not be used"); + } + + private class EnumeratorThatSplits : PartitionRangePageAsyncEnumerator + { + private readonly bool throwError; + + public EnumeratorThatSplits( + FeedRangeState feedRangeState, + bool throwError = true) + : base(feedRangeState) + { + this.throwError = throwError; + } + + public override ValueTask DisposeAsync() + { + throw new NotImplementedException(); + } + + public int GetNextPageAsyncCounter { get; private set; } + + protected override Task> GetNextPageAsync(ITrace trace, CancellationToken cancellationToken) + { + this.GetNextPageAsyncCounter++; + + if (this.GetNextPageAsyncCounter == 1 + && this.throwError) + { + CosmosException splitError = new CosmosException("merge", System.Net.HttpStatusCode.Gone, (int)Documents.SubStatusCodes.PartitionKeyRangeGone, string.Empty, 0); + TryCatch state = TryCatch.FromException(splitError); + return Task.FromResult(state); + } + else + { + return Task.FromResult(TryCatch.FromResult( + new ReadFeedPage( + new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), + requestCharge: 1, + itemCount: 0, + activityId: Guid.NewGuid().ToString(), + additionalHeaders: null, + state: ReadFeedState.Beginning()))); + } + } + } + + [TestMethod] + [DataRow(false, false, false, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: false")] + [DataRow(false, false, true, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: true")] + [DataRow(false, true, false, DisplayName = "Use State: false, Allow Splits: true, Allow Merges: false")] + [DataRow(false, true, true, DisplayName = "Use State: false, Allow Splits: true, Allow Merges: true")] + [DataRow(true, false, false, DisplayName = "Use State: true, Allow Splits: false, Allow Merges: false")] + [DataRow(true, false, true, DisplayName = "Use State: true, Allow Splits: false, Allow Merges: true")] + [DataRow(true, true, false, DisplayName = "Use State: true, Allow Splits: true, Allow Merges: false")] + [DataRow(true, true, true, DisplayName = "Use State: true, Allow Splits: true, Allow Merges: true")] + public async Task TestSplitAndMergeAsync(bool useState, bool allowSplits, bool allowMerges) + { + Implementation implementation = new Implementation(singlePartition: false); + await implementation.TestSplitAndMergeImplementationAsync(useState, allowSplits, allowMerges); + } + + private sealed class Implementation : PartitionRangeEnumeratorTests, CrossFeedRangeState> + { + enum TriState { NotReady, Ready, Done }; + + public Implementation(bool singlePartition) + : base(singlePartition) + { + this.ShouldMerge = TriState.NotReady; + } + + private TriState ShouldMerge { get; set; } + + private IDocumentContainer DocumentContainer { get; set; } + + private async Task ShouldReturnFailure() + { + if (this.ShouldMerge == TriState.Ready) + { + await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + List ranges = await this.DocumentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + + await this.DocumentContainer.MergeAsync(ranges[0], ranges[1], default); + await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, default); + this.ShouldMerge = TriState.Done; + + return new CosmosException( + message: "PKRange was split/merged", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)Documents.SubStatusCodes.PartitionKeyRangeGone, + activityId: "BC0CCDA5-D378-4922-B8B0-D51D745B9139", + requestCharge: 0.0); + } + else + { + return null; + } + } + + public async Task TestMergeToSinglePartition() + { + int numItems = 1000; + FlakyDocumentContainer.FailureConfigs config = new FlakyDocumentContainer.FailureConfigs( + inject429s: false, + injectEmptyPages: false, + shouldReturnFailure: this.ShouldReturnFailure); + + this.DocumentContainer = await this.CreateDocumentContainerAsync(numItems: numItems, failureConfigs: config); + + await this.DocumentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + List ranges = await this.DocumentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + await this.DocumentContainer.SplitAsync(ranges.First(), cancellationToken: default); + + IAsyncEnumerator>> enumerator = await this.CreateEnumeratorAsync(this.DocumentContainer); + List identifiers = new List(); + int iteration = 0; + while (await enumerator.MoveNextAsync()) + { + TryCatch> tryGetPage = enumerator.Current; + tryGetPage.ThrowIfFailed(); + + IReadOnlyList records = this.GetRecordsFromPage(tryGetPage.Result); + foreach (Record record in records) + { + identifiers.Add(record.Payload["pk"].ToString()); + } + + ++iteration; + if (iteration == 1) + { + this.ShouldMerge = TriState.Ready; + } + } + + Assert.AreEqual(numItems, identifiers.Count); + } + + public async Task TestSplitAndMergeImplementationAsync( + bool useState, + bool allowSplits, + bool allowMerges) + { + int numItems = 1000; + IDocumentContainer inMemoryCollection = await this.CreateDocumentContainerAsync(numItems); + IAsyncEnumerator>> enumerator = await this.CreateEnumeratorAsync(inMemoryCollection); + HashSet identifiers = new HashSet(); + Random random = new Random(); + while (await enumerator.MoveNextAsync()) + { + TryCatch> tryGetPage = enumerator.Current; + tryGetPage.ThrowIfFailed(); + + IReadOnlyList records = this.GetRecordsFromPage(tryGetPage.Result); + foreach (Record record in records) + { + identifiers.Add(record.Payload["pk"].ToString()); + } + + if (useState) + { + if (tryGetPage.Result.State == null) + { + break; + } + + enumerator = await this.CreateEnumeratorAsync( + inMemoryCollection, + false, + false, + tryGetPage.Result.State); + } + + if (random.Next() % 2 == 0) + { + if (allowSplits && (random.Next() % 2 == 0)) + { + // Split + await inMemoryCollection.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + List ranges = await inMemoryCollection.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + FeedRangeInternal randomRangeToSplit = ranges[random.Next(0, ranges.Count)]; + await inMemoryCollection.SplitAsync(randomRangeToSplit, cancellationToken: default); + } + + if (allowMerges && (random.Next() % 2 == 0)) + { + // Merge + await inMemoryCollection.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + List ranges = await inMemoryCollection.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + if (ranges.Count > 1) + { + ranges = ranges.OrderBy(range => range.Range.Min).ToList(); + int indexToMerge = random.Next(0, ranges.Count); + int adjacentIndex = indexToMerge == (ranges.Count - 1) ? indexToMerge - 1 : indexToMerge + 1; + await inMemoryCollection.MergeAsync(ranges[indexToMerge], ranges[adjacentIndex], cancellationToken: default); + } + } + } + } + + Assert.AreEqual(numItems, identifiers.Count); + } + + protected override IAsyncEnumerable>> CreateEnumerable( + IDocumentContainer inMemoryCollection, + bool aggressivePrefetch = false, + CrossFeedRangeState state = null) + { + PartitionRangePageAsyncEnumerator createEnumerator( + FeedRangeState feedRangeState) => new ReadFeedPartitionRangeEnumerator( + inMemoryCollection, + feedRangeState: feedRangeState, + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)); + + return new CrossPartitionRangePageAsyncEnumerable( + feedRangeProvider: inMemoryCollection, + createPartitionRangeEnumerator: createEnumerator, + comparer: PartitionRangePageAsyncEnumeratorComparer.Singleton, + maxConcurrency: 10, + prefetchPolicy: aggressivePrefetch ? PrefetchPolicy.PrefetchAll : PrefetchPolicy.PrefetchSinglePage, + trace: NoOpTrace.Singleton, + state: state ?? new CrossFeedRangeState( + new FeedRangeState[] + { + new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) + })); + } + + protected override Task>>> CreateEnumeratorAsync( + IDocumentContainer inMemoryCollection, + bool aggressivePrefetch = false, + bool exercisePrefetch = false, + CrossFeedRangeState state = null, + CancellationToken cancellationToken = default) + { + PartitionRangePageAsyncEnumerator createEnumerator( + FeedRangeState feedRangeState) + { + return new ReadFeedPartitionRangeEnumerator( + inMemoryCollection, + feedRangeState: feedRangeState, + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)); + } + + IAsyncEnumerator>> enumerator = new TracingAsyncEnumerator>>( + new CrossPartitionRangePageAsyncEnumerator( + feedRangeProvider: inMemoryCollection, + createPartitionRangeEnumerator: createEnumerator, + comparer: PartitionRangePageAsyncEnumeratorComparer.Singleton, + maxConcurrency: 10, + prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, + state: state ?? new CrossFeedRangeState( + new FeedRangeState[] + { + new FeedRangeState(FeedRangeEpk.FullRange, ReadFeedState.Beginning()) + })), + NoOpTrace.Singleton, + cancellationToken: default); + + return Task.FromResult(enumerator); + } + + public override IReadOnlyList GetRecordsFromPage(CrossFeedRangePage page) + { + return page.Page.GetRecords(); + } + + private sealed class PartitionRangePageAsyncEnumeratorComparer : IComparer> + { + public static readonly PartitionRangePageAsyncEnumeratorComparer Singleton = new PartitionRangePageAsyncEnumeratorComparer(); + + public int Compare( + PartitionRangePageAsyncEnumerator partitionRangePageEnumerator1, + PartitionRangePageAsyncEnumerator partitionRangePageEnumerator2) + { + if (object.ReferenceEquals(partitionRangePageEnumerator1, partitionRangePageEnumerator2)) + { + return 0; + } + + // Either both don't have results or both do. + return string.CompareOrdinal( + ((FeedRangeEpk)partitionRangePageEnumerator1.FeedRangeState.FeedRange).Range.Min, + ((FeedRangeEpk)partitionRangePageEnumerator2.FeedRangeState.FeedRange).Range.Min); + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs index 132d575905..6ce08b615a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/FlakyDocumentContainer.cs @@ -125,7 +125,8 @@ public async Task> MonadicReadFeedAsync( return TryCatch.FromResult( new ReadFeedPage( new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), - requestCharge: 42, + requestCharge: 42, + itemCount: 0, activityId: Guid.NewGuid().ToString(), additionalHeaders: null, state: nonNullState)); @@ -168,12 +169,12 @@ public async Task> MonadicQueryAsync( documents: new List(), requestCharge: 42, activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: "[]".Length, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: feedRangeState.State ?? StateForStartedButNoDocumentsReturned)); + state: feedRangeState.State ?? StateForStartedButNoDocumentsReturned, + streaming: default)); } Exception failure = await this.ShouldReturnFailure(); @@ -206,7 +207,8 @@ public async Task> MonadicChangeFeedAsync( return TryCatch.FromResult( new ChangeFeedSuccessPage( content: new MemoryStream(Encoding.UTF8.GetBytes("{\"Documents\": [], \"_count\": 0, \"_rid\": \"asdf\"}")), - requestCharge: 42, + requestCharge: 42, + itemCount: 0, activityId: Guid.NewGuid().ToString(), additionalHeaders: default, state: feedRangeState.State)); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs index ad17a6bac6..bfcfb0c725 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs @@ -1,1664 +1,1666 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Tests.Pagination -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Immutable; - using System.IO; - using System.Linq; - using System.Reflection; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos; - using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.CosmosElements.Numbers; - using Microsoft.Azure.Cosmos.Json; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Parser; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.ReadFeed.Pagination; - using Microsoft.Azure.Cosmos.Routing; - using Microsoft.Azure.Cosmos.Serialization.HybridRow; - using Microsoft.Azure.Cosmos.SqlObjects; - using Microsoft.Azure.Cosmos.Tests.Query.OfflineEngine; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Documents; - using static Microsoft.Azure.Cosmos.Query.Core.SqlQueryResumeFilter; - using ResourceIdentifier = Cosmos.Pagination.ResourceIdentifier; - using UInt128 = UInt128; - - // Collection useful for mocking requests and repartitioning (splits / merge). - internal class InMemoryContainer : IMonadicDocumentContainer - { - private readonly PartitionKeyDefinition partitionKeyDefinition; - private readonly Dictionary parentToChildMapping; - - private PartitionKeyHashRangeDictionary partitionedRecords; - private PartitionKeyHashRangeDictionary> partitionedChanges; - private Dictionary partitionKeyRangeIdToHashRange; - private Dictionary cachedPartitionKeyRangeIdToHashRange; - - public InMemoryContainer( - PartitionKeyDefinition partitionKeyDefinition) - { - this.partitionKeyDefinition = partitionKeyDefinition ?? throw new ArgumentNullException(nameof(partitionKeyDefinition)); - PartitionKeyHashRange fullRange = new PartitionKeyHashRange(startInclusive: null, endExclusive: new PartitionKeyHash(Cosmos.UInt128.MaxValue)); - PartitionKeyHashRanges partitionKeyHashRanges = PartitionKeyHashRanges.Create(new PartitionKeyHashRange[] { fullRange }); - this.partitionedRecords = new PartitionKeyHashRangeDictionary(partitionKeyHashRanges); - this.partitionedRecords[fullRange] = new Records(); - this.partitionedChanges = new PartitionKeyHashRangeDictionary>(partitionKeyHashRanges); - this.partitionedChanges[fullRange] = new List(); - this.partitionKeyRangeIdToHashRange = new Dictionary() - { - { 0, fullRange } - }; - this.cachedPartitionKeyRangeIdToHashRange = new Dictionary() - { - { 0, fullRange } - }; - this.parentToChildMapping = new Dictionary(); - } - - public Task>> MonadicGetFeedRangesAsync( - ITrace trace, - CancellationToken cancellationToken) => this.MonadicGetChildRangeAsync( - FeedRangeEpk.FullRange, - trace, - cancellationToken); - - public async Task>> MonadicGetChildRangeAsync( - FeedRangeInternal feedRange, - ITrace trace, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (feedRange == null) - { - throw new ArgumentNullException(nameof(feedRange)); - } - - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - - using (ITrace getChildRangesTrace = trace.StartChild(name: "Get Child Ranges", TraceComponent.Routing, TraceLevel.Info)) - { - FeedRangeEpk CreateRangeFromId(int id) - { - PartitionKeyHashRange hashRange = this.cachedPartitionKeyRangeIdToHashRange[id]; - return new FeedRangeEpk( - new Documents.Routing.Range( - min: hashRange.StartInclusive.HasValue ? hashRange.StartInclusive.Value.ToString() : string.Empty, - max: hashRange.EndExclusive.HasValue ? hashRange.EndExclusive.Value.ToString() : string.Empty, - isMinInclusive: true, - isMaxInclusive: false)); - } - - if (feedRange is FeedRangePartitionKey) - { - throw new ArgumentException("Can not get the child of a logical partition key"); - } - - if (feedRange.Equals(FeedRangeEpk.FullRange)) - { - List ranges = new List(); - foreach (int id in this.cachedPartitionKeyRangeIdToHashRange.Keys) - { - ranges.Add(CreateRangeFromId(id)); - } - - return TryCatch>.FromResult(ranges); - } - - if (feedRange is FeedRangeEpk feedRangeEpk) - { - // look for overlapping epk ranges. - List overlappingRanges; - if (feedRangeEpk.Range.Min.Equals(FeedRangeEpk.FullRange.Range.Min) && feedRangeEpk.Range.Max.Equals(FeedRangeEpk.FullRange.Range.Max)) - { - overlappingRanges = this.cachedPartitionKeyRangeIdToHashRange.Select(kvp => CreateRangeFromId(kvp.Key)).ToList(); - } - else - { - overlappingRanges = new List(); - PartitionKeyHashRange userRange = FeedRangeEpkToHashRange(feedRangeEpk); - foreach (PartitionKeyHashRange systemRange in this.cachedPartitionKeyRangeIdToHashRange.Values) - { - if (userRange.TryGetOverlappingRange(systemRange, out PartitionKeyHashRange overlappingRange)) - { - overlappingRanges.Add(HashRangeToFeedRangeEpk(overlappingRange)); - } - } - } - - if (overlappingRanges.Count == 0) - { - return TryCatch>.FromException( - new KeyNotFoundException( - $"PartitionKeyRangeId: {feedRangeEpk} does not exist.")); - } - - return TryCatch>.FromResult(overlappingRanges); - } - - if (!(feedRange is FeedRangePartitionKeyRange feedRangePartitionKeyRange)) - { - throw new InvalidOperationException("Expected feed range to be a partition key range at this point."); - } - - if (!int.TryParse(feedRangePartitionKeyRange.PartitionKeyRangeId, out int partitionKeyRangeId)) - { - return TryCatch>.FromException( - new FormatException( - $"PartitionKeyRangeId: {feedRangePartitionKeyRange.PartitionKeyRangeId} is not an integer.")); - } - - if (!this.parentToChildMapping.TryGetValue(partitionKeyRangeId, out (int left, int right) children)) - { - // This range has no children (base case) - if (!this.cachedPartitionKeyRangeIdToHashRange.TryGetValue(partitionKeyRangeId, out PartitionKeyHashRange hashRange)) - { - return TryCatch>.FromException( - new KeyNotFoundException( - $"PartitionKeyRangeId: {partitionKeyRangeId} does not exist.")); - } - - List singleRange = new List() - { - CreateRangeFromId(partitionKeyRangeId), - }; - - return TryCatch>.FromResult(singleRange); - } - - // Recurse on the left and right child. - FeedRangeInternal left = new FeedRangePartitionKeyRange(children.left.ToString()); - FeedRangeInternal right = new FeedRangePartitionKeyRange(children.right.ToString()); - - TryCatch> tryGetLeftRanges = await this.MonadicGetChildRangeAsync(left, trace, cancellationToken); - if (tryGetLeftRanges.Failed) - { - return tryGetLeftRanges; - } - - TryCatch> tryGetRightRanges = await this.MonadicGetChildRangeAsync(right, trace, cancellationToken); - if (tryGetRightRanges.Failed) - { - return tryGetRightRanges; - } - - List recursiveOverlappingRanges = tryGetLeftRanges.Result.Concat(tryGetRightRanges.Result).ToList(); - return TryCatch>.FromResult(recursiveOverlappingRanges); - } - } - - public Task MonadicRefreshProviderAsync( - ITrace trace, - CancellationToken cancellationToken) - { - using (ITrace refreshProviderTrace = trace.StartChild("Refreshing FeedRangeProvider", TraceComponent.Routing, TraceLevel.Info)) - { - this.cachedPartitionKeyRangeIdToHashRange = new Dictionary(this.partitionKeyRangeIdToHashRange); - return Task.FromResult(TryCatch.FromResult()); - } - } - - public Task> MonadicCreateItemAsync( - CosmosObject payload, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (payload == null) - { - throw new ArgumentNullException(nameof(payload)); - } - - PartitionKeyHash partitionKeyHash = GetHashFromPayload(payload, this.partitionKeyDefinition); - if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) - { - records = new Records(); - this.partitionedRecords[partitionKeyHash] = records; - } - - int? pkrangeid = null; - foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) - { - if (kvp.Value.Contains(partitionKeyHash)) - { - pkrangeid = kvp.Key; - } - } - - if (!pkrangeid.HasValue) - { - throw new InvalidOperationException(); - } - - Record recordAdded = records.Add(pkrangeid.Value, payload); - - if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) - { - changes = new List(); - this.partitionedChanges[partitionKeyHash] = changes; - } - - ulong maxLogicalSequenceNumber = changes.Count == 0 ? 0 : changes.Select(change => change.LogicalSequenceNumber).Max(); - - Change change = new Change( - recordAdded, - partitionKeyRangeId: (ulong)pkrangeid.Value, - logicalSequenceNumber: maxLogicalSequenceNumber + 1); - - changes.Add(change); - return Task.FromResult(TryCatch.FromResult(recordAdded)); - } - - public Task> MonadicReadItemAsync( - CosmosElement partitionKey, - string identifier, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - static Task> CreateNotFoundException(CosmosElement partitionKey, string identifer) - { - return Task.FromResult( - TryCatch.FromException( - new CosmosException( - message: $"Document with partitionKey: {partitionKey?.ToString() ?? "UNDEFINED"} and id: {identifer} not found.", - statusCode: System.Net.HttpStatusCode.NotFound, - subStatusCode: default, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys( - new List { partitionKey }, - this.partitionKeyDefinition); - - if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) - { - return CreateNotFoundException(partitionKey, identifier); - } - - foreach (Record candidate in records) - { - bool identifierMatches = candidate.Identifier == identifier; - - CosmosElement candidatePartitionKey = GetPartitionKeyFromPayload( - candidate.Payload, - this.partitionKeyDefinition); - - bool partitionKeyMatches; - if (candidatePartitionKey is null && partitionKey is null) - { - partitionKeyMatches = true; - } - else if ((candidatePartitionKey != null) && (partitionKey != null)) - { - partitionKeyMatches = candidatePartitionKey.Equals(partitionKey); - } - else - { - partitionKeyMatches = false; - } - - if (identifierMatches && partitionKeyMatches) - { - return Task.FromResult(TryCatch.FromResult(candidate)); - } - } - - return CreateNotFoundException(partitionKey, identifier); - } - - public Task> MonadicReadFeedAsync( - FeedRangeState feedRangeState, - ReadFeedPaginationOptions readFeedPaginationOptions, - ITrace trace, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - readFeedPaginationOptions ??= ReadFeedPaginationOptions.Default; - - using (ITrace readFeed = trace.StartChild("Read Feed Transport", TraceComponent.Transport, TraceLevel.Info)) - { - TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); - if (monadicPartitionKeyRangeId.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); - } - - int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; - - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - partitionKeyRangeId, - out PartitionKeyHashRange range)) - { - return Task.FromResult( - TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedRecords.TryGetValue(range, out Records records)) - { - throw new InvalidOperationException("failed to find the range."); - } - - (ulong pkrangeId, ulong documentIndex) rangeIdAndIndex; - if (feedRangeState.State is ReadFeedBeginningState) - { - rangeIdAndIndex = (0, 0); - } - else if (feedRangeState.State is ReadFeedContinuationState readFeedContinuationState) - { - ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse(((CosmosString)readFeedContinuationState.ContinuationToken).Value); - rangeIdAndIndex = (resourceIdentifier.Database, resourceIdentifier.Document); - } - else - { - throw new InvalidOperationException("Unknown read feed state"); - } - - List page = records - .Where((record) => - { - if (!IsRecordWithinFeedRange(record, feedRangeState.FeedRange, this.partitionKeyDefinition)) - { - return false; - } - - // We do a filter on a composite index here - int pkRangeIdCompare = record.ResourceIdentifier.Database.CompareTo((uint)rangeIdAndIndex.pkrangeId); - if (pkRangeIdCompare < 0) - { - return false; - } - else if (pkRangeIdCompare > 0) - { - return true; - } - else // pkRangeIdCompare == 0 - { - return record.ResourceIdentifier.Document > rangeIdAndIndex.documentIndex; - } - }) - .Take(readFeedPaginationOptions.PageSizeLimit.GetValueOrDefault(int.MaxValue)) - .ToList(); - - List documents = new List(); - foreach (Record record in page) - { - CosmosObject document = ConvertRecordToCosmosElement(record); - documents.Add(CosmosObject.Create(document)); - } - - ReadFeedState continuationState; - if (documents.Count == 0) - { - continuationState = null; - } - else - { - ResourceId resourceIdentifier = page.Last().ResourceIdentifier; - CosmosString continuationToken = CosmosString.Create(resourceIdentifier.ToString()); - continuationState = ReadFeedState.Continuation(continuationToken); - } - - CosmosArray cosmosDocuments = CosmosArray.Create(documents); - CosmosNumber cosmosCount = CosmosNumber64.Create(cosmosDocuments.Count); - CosmosString cosmosRid = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA=="); - - Dictionary responseDictionary = new Dictionary() - { - { "Documents", cosmosDocuments }, - { "_count", cosmosCount }, - { "_rid", cosmosRid }, - }; - CosmosObject cosmosResponse = CosmosObject.Create(responseDictionary); - IJsonWriter jsonWriter = Cosmos.Json.JsonWriter.Create(JsonSerializationFormat.Text); - cosmosResponse.WriteTo(jsonWriter); - byte[] result = jsonWriter.GetResult().ToArray(); - MemoryStream responseStream = new MemoryStream(result); - - ReadFeedPage readFeedPage = new ReadFeedPage( - responseStream, - requestCharge: 42, - activityId: Guid.NewGuid().ToString(), - additionalHeaders: new Dictionary() - { - { "test-header", "test-value" } - }, - continuationState); - - return Task.FromResult(TryCatch.FromResult(readFeedPage)); - } - } - - public virtual Task> MonadicQueryAsync( - SqlQuerySpec sqlQuerySpec, - FeedRangeState feedRangeState, - QueryPaginationOptions queryPaginationOptions, - ITrace trace, - CancellationToken cancellationToken) - { - if (cancellationToken.IsCancellationRequested) - { - return Task.FromCanceled>(cancellationToken); - } - if (sqlQuerySpec == null) - { - throw new ArgumentNullException(nameof(sqlQuerySpec)); - } - - using (ITrace childTrace = trace.StartChild("Query Transport", TraceComponent.Transport, TraceLevel.Info)) - { - TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); - if (monadicPartitionKeyRangeId.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); - } - - int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; - - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - partitionKeyRangeId, - out PartitionKeyHashRange range)) - { - return Task.FromResult(TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedRecords.TryGetValue(range, out Records records)) - { - throw new InvalidOperationException("failed to find the range."); - } - - List documents = new List(); - foreach (Record record in records.Where(r => IsRecordWithinFeedRange(r, feedRangeState.FeedRange, this.partitionKeyDefinition))) - { - CosmosObject document = ConvertRecordToCosmosElement(record); - documents.Add(CosmosObject.Create(document)); - } - - TryCatch monadicParse = SqlQueryParser.Monadic.Parse(sqlQuerySpec.QueryText); - if (monadicParse.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicParse.Exception)); - } - - SqlQuery sqlQuery = monadicParse.Result; - if ((sqlQuery.OrderByClause != null) && (feedRangeState.State != null) && (sqlQuerySpec.ResumeFilter == null)) - { - // This is a hack. - // If the query is an ORDER BY query then we need to seek to the resume term. - // Since I don't want to port over the proper logic from the backend I will just inject a filter. - // For now I am only handling the single order by item case - if (sqlQuery.OrderByClause.OrderByItems.Length != 1) - { - throw new NotImplementedException("Can only support a single order by column"); - } - - SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; - CosmosObject parsedContinuationToken = CosmosObject.Parse(((CosmosString)feedRangeState.State.Value).Value); - SqlBinaryScalarExpression resumeFilter = SqlBinaryScalarExpression.Create( - orderByItem.IsDescending ? SqlBinaryScalarOperatorKind.LessThan : SqlBinaryScalarOperatorKind.GreaterThan, - orderByItem.Expression, - parsedContinuationToken["orderByItem"].Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton)); - - SqlWhereClause modifiedWhereClause = sqlQuery.WhereClause.FilterExpression == null - ? SqlWhereClause.Create(resumeFilter) - : SqlWhereClause.Create( - SqlBinaryScalarExpression.Create( - SqlBinaryScalarOperatorKind.And, - sqlQuery.WhereClause.FilterExpression, - resumeFilter)); - - sqlQuery = SqlQuery.Create( - sqlQuery.SelectClause, - sqlQuery.FromClause, - modifiedWhereClause, - sqlQuery.GroupByClause, - sqlQuery.OrderByClause, - sqlQuery.OffsetLimitClause); - - // We still need to handle duplicate values and break the tie with the rid - // But since all the values are unique for our testing purposes we can ignore this for now. - } - IEnumerable queryResults = SqlInterpreter.ExecuteQuery(documents, sqlQuery); - IEnumerable queryPageResults = queryResults; - - // If the resume value is passed in query spec, filter out the results that has order by item value smaller than resume values - if (sqlQuerySpec.ResumeFilter != null) - { - if (sqlQuery.OrderByClause.OrderByItems.Length != 1) - { - throw new NotImplementedException("Can only support a single order by column"); - } - - SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; - IEnumerator queryResultEnumerator = queryPageResults.GetEnumerator(); - - int skipCount = 0; - while(queryResultEnumerator.MoveNext()) - { - CosmosObject document = (CosmosObject)queryResultEnumerator.Current; - CosmosElement orderByValue = ((CosmosObject)((CosmosArray)document["orderByItems"])[0])["item"]; - - int sortOrderCompare = sqlQuerySpec.ResumeFilter.ResumeValues[0].CompareTo(orderByValue); - - if (sortOrderCompare != 0) - { - sortOrderCompare = orderByItem.IsDescending ? -sortOrderCompare : sortOrderCompare; - } - - if (sortOrderCompare < 0) - { - // We might have passed the item due to deletions and filters. - break; - } - - if (sortOrderCompare >= 0) - { - // This document does not match the sort order, so skip it. - skipCount++; - } - } - - queryPageResults = queryPageResults.Skip(skipCount); - - // NOTE: We still need to handle duplicate values and break the tie with the rid - // But since all the values are unique for our testing purposes we can ignore this for now. - } - - // Filter for the continuation token - string continuationResourceId; - int continuationSkipCount; - - if ((sqlQuery.OrderByClause == null) && (feedRangeState.State != null)) - { - CosmosObject parsedContinuationToken = CosmosObject.Parse(((CosmosString)feedRangeState.State.Value).Value); - continuationResourceId = ((CosmosString)parsedContinuationToken["resourceId"]).Value; - continuationSkipCount = (int)Number64.ToLong(((CosmosNumber64)parsedContinuationToken["skipCount"]).Value); - - ResourceIdentifier continuationParsedResourceId = ResourceIdentifier.Parse(continuationResourceId); - queryPageResults = queryPageResults.Where(c => - { - ResourceId documentResourceId = ResourceId.Parse(((CosmosString)((CosmosObject)c)["_rid"]).Value); - // Perform a composite filter on pkrange id and document index - int pkRangeIdCompare = documentResourceId.Database.CompareTo(continuationParsedResourceId.Database); - if (pkRangeIdCompare < 0) - { - return false; - } - else if (pkRangeIdCompare > 0) - { - return true; - } - else // pkRangeIdCompare == 0 - { - int documentCompare = documentResourceId.Document.CompareTo(continuationParsedResourceId.Document); - - // If we have a skip count, then we can't skip over the rid we last saw, since - // there are documents with the same rid that we need to skip over. - return continuationSkipCount == 0 ? documentCompare > 0 : documentCompare >= 0; - } - }); - - for (int i = 0; i < continuationSkipCount; i++) - { - if (queryPageResults.FirstOrDefault() is CosmosObject firstDocument) - { - string currentResourceId = ((CosmosString)firstDocument["_rid"]).Value; - if (currentResourceId == continuationResourceId) - { - queryPageResults = queryPageResults.Skip(1); - } - } - } - } - else - { - continuationResourceId = null; - continuationSkipCount = 0; - } - - queryPageResults = queryPageResults.Take((queryPaginationOptions ?? QueryPaginationOptions.Default).PageSizeLimit.GetValueOrDefault(int.MaxValue)); - List queryPageResultList = queryPageResults.ToList(); - QueryState queryState; - if (queryPageResultList.LastOrDefault() is CosmosObject lastDocument - && lastDocument.TryGetValue("_rid", out CosmosString resourceId)) - { - string currentResourceId = resourceId.Value; - int currentSkipCount = queryPageResultList - .Where(document => ((CosmosString)((CosmosObject)document)["_rid"]).Value == currentResourceId) - .Count(); - if (currentResourceId == continuationResourceId) - { - currentSkipCount += continuationSkipCount; - } - - Dictionary queryStateDictionary = new Dictionary() - { - { "resourceId", CosmosString.Create(currentResourceId) }, - { "skipCount", CosmosNumber64.Create(currentSkipCount) }, - }; - - if (sqlQuery.OrderByClause != null) - { - SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; - string propertyName = ((SqlPropertyRefScalarExpression)orderByItem.Expression).Identifier.Value; - queryStateDictionary["orderByItem"] = ((CosmosObject)lastDocument["payload"])[propertyName]; - } - - CosmosObject queryStateValue = CosmosObject.Create(queryStateDictionary); - - queryState = new QueryState(CosmosString.Create(queryStateValue.ToString())); - } - else - { - queryState = default; - } - - ImmutableDictionary.Builder additionalHeaders = ImmutableDictionary.CreateBuilder(); - additionalHeaders.Add("x-ms-documentdb-partitionkeyrangeid", "0"); - additionalHeaders.Add("x-ms-test-header", "true"); - - return Task.FromResult( - TryCatch.FromResult( - new QueryPage( - queryPageResultList, - requestCharge: 42, - activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: 1337, - cosmosQueryExecutionInfo: default, - distributionPlanSpec: default, - disallowContinuationTokenMessage: default, - additionalHeaders: additionalHeaders.ToImmutable(), - state: queryState))); - } - } - - public Task> MonadicChangeFeedAsync( - FeedRangeState feedRangeState, - ChangeFeedPaginationOptions changeFeedPaginationOptions, - ITrace trace, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (ITrace childTrace = trace.StartChild("Change Feed Transport", TraceComponent.Transport, TraceLevel.Info)) - { - TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); - if (monadicPartitionKeyRangeId.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); - } - - int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; - - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - partitionKeyRangeId, - out PartitionKeyHashRange range)) - { - return Task.FromResult(TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedChanges.TryGetValue(range, out List changes)) - { - throw new InvalidOperationException("failed to find the range."); - } - - List filteredChanges = changes - .Where(change => IsRecordWithinFeedRange(change.Record, feedRangeState.FeedRange, this.partitionKeyDefinition)) - .Where(change => feedRangeState.State.Accept(ChangeFeedPredicate.Singleton, change)) - .Take((changeFeedPaginationOptions ?? ChangeFeedPaginationOptions.Default).PageSizeLimit.GetValueOrDefault(int.MaxValue)) - .ToList(); - - if (filteredChanges.Count == 0) - { - ChangeFeedState notModifiedResponseState = new ChangeFeedStateTime(DateTime.UtcNow); - return Task.FromResult( - TryCatch.FromResult( - new ChangeFeedNotModifiedPage( - requestCharge: 42, - activityId: Guid.NewGuid().ToString(), - additionalHeaders: default, - notModifiedResponseState))); - } - - Change lastChange = filteredChanges.Last(); - CosmosObject continuationToken = CosmosObject.Create( - new Dictionary() - { - { "PkRangeId", CosmosNumber64.Create(lastChange.PartitionKeyRangeId) }, - { "LSN", CosmosNumber64.Create(lastChange.LogicalSequenceNumber) } - }); - - ChangeFeedState responseState = ChangeFeedState.Continuation(continuationToken); - - List documents = new List(); - foreach (Change change in filteredChanges) - { - CosmosObject document = ConvertRecordToCosmosElement(change.Record); - documents.Add(CosmosObject.Create(document)); - } - - CosmosArray cosmosDocuments = CosmosArray.Create(documents); - CosmosNumber cosmosCount = CosmosNumber64.Create(cosmosDocuments.Count); - CosmosString cosmosRid = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA=="); - - Dictionary responseDictionary = new Dictionary() - { - { "Documents", cosmosDocuments }, - { "_count", cosmosCount }, - { "_rid", cosmosRid }, - }; - CosmosObject cosmosResponse = CosmosObject.Create(responseDictionary); - IJsonWriter jsonWriter = Cosmos.Json.JsonWriter.Create(JsonSerializationFormat.Text); - cosmosResponse.WriteTo(jsonWriter); - byte[] result = jsonWriter.GetResult().ToArray(); - MemoryStream responseStream = new MemoryStream(result); - - return Task.FromResult( - TryCatch.FromResult( - new ChangeFeedSuccessPage( - responseStream, - requestCharge: 42, - activityId: Guid.NewGuid().ToString(), - additionalHeaders: default, - responseState))); - } - } - - public Task MonadicSplitAsync( - FeedRangeInternal feedRange, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (feedRange == null) - { - throw new ArgumentNullException(nameof(feedRange)); - } - - TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange); - if (monadicPartitionKeyRangeId.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); - } - - int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; - - // Get the current range and records - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - partitionKeyRangeId, - out PartitionKeyHashRange parentRange)) - { - return Task.FromResult( - TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedRecords.TryGetValue(parentRange, out Records parentRecords)) - { - throw new InvalidOperationException("failed to find the range."); - } - - if (!this.partitionedChanges.TryGetValue(parentRange, out List parentChanges)) - { - throw new InvalidOperationException("failed to find the range."); - } - - // Split the range space - PartitionKeyHashRanges partitionKeyHashRanges; - if (this.partitionKeyDefinition.Kind == PartitionKind.MultiHash && - this.partitionKeyDefinition.Paths.Count > 1) - { - //For MultiHash, to help with testing we will split using the median partition key among documents. - PartitionKeyHash midPoint = this.ComputeMedianSplitPointAmongDocumentsInPKRange(parentRange); - partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange(parentRange, midPoint); - } - else - { - partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange( - parentRange, - rangeCount: 2); - } - - // Update the partition routing map - int maxPartitionKeyRangeId = this.partitionKeyRangeIdToHashRange.Keys.Max(); - this.parentToChildMapping[partitionKeyRangeId] = (maxPartitionKeyRangeId + 1, maxPartitionKeyRangeId + 2); - Dictionary newPartitionKeyRangeIdToHashRange = new Dictionary() - { - { maxPartitionKeyRangeId + 1, partitionKeyHashRanges.First() }, - { maxPartitionKeyRangeId + 2, partitionKeyHashRanges.Last() }, - }; - - foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) - { - int oldRangeId = kvp.Key; - PartitionKeyHashRange oldRange = kvp.Value; - if (!oldRange.Equals(parentRange)) - { - newPartitionKeyRangeIdToHashRange[oldRangeId] = oldRange; - } - } - - // Copy over the partitioned records (minus the parent range) - PartitionKeyHashRangeDictionary newPartitionedRecords = new PartitionKeyHashRangeDictionary( - PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); - - newPartitionedRecords[partitionKeyHashRanges.First()] = new Records(); - newPartitionedRecords[partitionKeyHashRanges.Last()] = new Records(); - - foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) - { - if (!range.Equals(parentRange)) - { - newPartitionedRecords[range] = this.partitionedRecords[range]; - } - } - - PartitionKeyHashRangeDictionary> newPartitionedChanges = new PartitionKeyHashRangeDictionary>( - PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); - - newPartitionedChanges[partitionKeyHashRanges.First()] = new List(); - newPartitionedChanges[partitionKeyHashRanges.Last()] = new List(); - - foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) - { - if (!range.Equals(parentRange)) - { - newPartitionedChanges[range] = this.partitionedChanges[range]; - } - } - - this.partitionedRecords = newPartitionedRecords; - this.partitionedChanges = newPartitionedChanges; - this.partitionKeyRangeIdToHashRange = newPartitionKeyRangeIdToHashRange; - - // Rehash the records in the parent range - foreach (Record record in parentRecords) - { - PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); - if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) - { - records = new Records(); - this.partitionedRecords[partitionKeyHash] = records; - } - - records.Add(record); - } - - // Rehash the changes in the parent range - foreach (Change change in parentChanges) - { - PartitionKeyHash partitionKeyHash = GetHashFromPayload(change.Record.Payload, this.partitionKeyDefinition); - if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) - { - changes = new List(); - this.partitionedChanges[partitionKeyHash] = changes; - } - - changes.Add(change); - } - - return Task.FromResult(TryCatch.FromResult()); - } - - public Task MonadicMergeAsync( - FeedRangeInternal feedRange1, - FeedRangeInternal feedRange2, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - if (feedRange1 == null) - { - throw new ArgumentNullException(nameof(feedRange1)); - } - - if (feedRange2 == null) - { - throw new ArgumentNullException(nameof(feedRange2)); - } - - TryCatch monadicPartitionKeyRangeId1 = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange1); - if (monadicPartitionKeyRangeId1.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId1.Exception)); - } - - int sourceRangeId1 = monadicPartitionKeyRangeId1.Result; - - TryCatch monadicPartitionKeyRangeId2 = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange2); - if (monadicPartitionKeyRangeId2.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId2.Exception)); - } - - int sourceRangeId2 = monadicPartitionKeyRangeId2.Result; - - // Get the range and records - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - sourceRangeId1, - out PartitionKeyHashRange sourceHashRange1)) - { - return Task.FromResult( - TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {sourceRangeId1} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedRecords.TryGetValue(sourceHashRange1, out Records sourceRecords1)) - { - throw new InvalidOperationException("failed to find the range."); - } - - if (!this.partitionedChanges.TryGetValue(sourceHashRange1, out List sourceChanges1)) - { - throw new InvalidOperationException("failed to find the range."); - } - - if (!this.partitionKeyRangeIdToHashRange.TryGetValue( - sourceRangeId2, - out PartitionKeyHashRange sourceHashRange2)) - { - return Task.FromResult( - TryCatch.FromException( - new CosmosException( - message: $"PartitionKeyRangeId {sourceRangeId2} is gone", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: 42))); - } - - if (!this.partitionedRecords.TryGetValue(sourceHashRange2, out Records sourceRecords2)) - { - throw new InvalidOperationException("failed to find the range."); - } - - if (!this.partitionedChanges.TryGetValue(sourceHashRange2, out List sourceChanges2)) - { - throw new InvalidOperationException("failed to find the range."); - } - - // Merge the range space - TryCatch monadicRanges = PartitionKeyHashRanges.Monadic.Create(new List() - { - sourceHashRange1, - sourceHashRange2 - }); - - if (monadicRanges.Failed) - { - return Task.FromResult(TryCatch.FromException(monadicRanges.Exception)); - } - - PartitionKeyHashRange mergedHashRange = PartitionKeyHashRangeSplitterAndMerger.MergeRanges( - monadicRanges.Result); - - // Update the partition routing map - int maxPartitionKeyRangeId = this.partitionKeyRangeIdToHashRange.Keys.Max(); - Dictionary newPartitionKeyRangeIdToHashRange = new Dictionary() - { - { maxPartitionKeyRangeId + 1, mergedHashRange }, - }; - - foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) - { - int oldRangeId = kvp.Key; - PartitionKeyHashRange oldRange = kvp.Value; - if (!(oldRange.Equals(sourceHashRange1) || oldRange.Equals(sourceHashRange2))) - { - newPartitionKeyRangeIdToHashRange[oldRangeId] = oldRange; - } - } - - // Copy over the partitioned records (minus the source ranges) - PartitionKeyHashRangeDictionary newPartitionedRecords = new PartitionKeyHashRangeDictionary( - PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); - - newPartitionedRecords[mergedHashRange] = new Records(); - - foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) - { - if (!(range.Equals(sourceHashRange1) || range.Equals(sourceHashRange2))) - { - newPartitionedRecords[range] = this.partitionedRecords[range]; - } - } - - PartitionKeyHashRangeDictionary> newPartitionedChanges = new PartitionKeyHashRangeDictionary>( - PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); - - newPartitionedChanges[mergedHashRange] = new List(); - - foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) - { - if (!(range.Equals(sourceHashRange1) || range.Equals(sourceHashRange2))) - { - newPartitionedChanges[range] = this.partitionedChanges[range]; - } - } - - this.partitionedRecords = newPartitionedRecords; - this.partitionedChanges = newPartitionedChanges; - this.partitionKeyRangeIdToHashRange = newPartitionKeyRangeIdToHashRange; - - // Rehash the records in the source ranges - List combinedOrderedRecords = new List(); - foreach (Records sourceRecords in new Records[] { sourceRecords1, sourceRecords2 }) - { - combinedOrderedRecords.AddRange(sourceRecords); - } - - combinedOrderedRecords = combinedOrderedRecords - .OrderBy(record => record.ResourceIdentifier.Database) - .ThenBy(record => record.ResourceIdentifier.Document) - .ToList(); - - foreach (Record record in combinedOrderedRecords) - { - PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); - if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) - { - records = new Records(); - this.partitionedRecords[partitionKeyHash] = records; - } - - records.Add(record); - } - - // Rehash the changes in the parent range - List combinedOrderedChanges = new List(); - foreach (List sourceChanges in new List[] { sourceChanges1, sourceChanges2 }) - { - combinedOrderedChanges.AddRange(sourceChanges); - } - - combinedOrderedChanges = combinedOrderedChanges - .OrderBy(change => change.PartitionKeyRangeId) - .ThenBy(change => change.LogicalSequenceNumber) - .ToList(); - - foreach (Change change in combinedOrderedChanges) - { - PartitionKeyHash partitionKeyHash = GetHashFromPayload(change.Record.Payload, this.partitionKeyDefinition); - if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) - { - changes = new List(); - this.partitionedChanges[partitionKeyHash] = changes; - } - - changes.Add(change); - } - - return Task.FromResult(TryCatch.FromResult()); - } - - public IEnumerable PartitionKeyRangeIds => this.partitionKeyRangeIdToHashRange.Keys; - - private static PartitionKeyHash GetHashFromPayload( - CosmosObject payload, - PartitionKeyDefinition partitionKeyDefinition) - { - IList partitionKey = GetPartitionKeysFromPayload(payload, partitionKeyDefinition); - return GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); - } - - private static PartitionKeyHash GetHashFromObjectModel( - Cosmos.PartitionKey payload, - PartitionKeyDefinition partitionKeyDefinition) - { - IList partitionKeys = GetPartitionKeysFromObjectModel(payload); - return GetHashFromPartitionKeys(partitionKeys, partitionKeyDefinition); - } - - private static CosmosElement GetPartitionKeyFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) - { - // Restrict the partition key definition for now to keep things simple - if (partitionKeyDefinition.Kind != PartitionKind.Hash) - { - throw new ArgumentOutOfRangeException("Can only support hash partitioning"); - } - - if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) - { - throw new ArgumentOutOfRangeException("Can only support hash v2"); - } - - if (partitionKeyDefinition.Paths.Count != 1) - { - throw new ArgumentOutOfRangeException("Can only support a single partition key path."); - } - - IEnumerable tokens = partitionKeyDefinition.Paths[0].Split("/").Skip(1); - - CosmosElement partitionKey = payload; - foreach (string token in tokens) - { - if (partitionKey != default) - { - if (!payload.TryGetValue(token, out partitionKey)) - { - partitionKey = default; - } - } - } - - return partitionKey; - } - - private static IList GetPartitionKeysFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) - { - // Restrict the partition key definition for now to keep things simple - if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) - { - throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); - } - - if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) - { - throw new ArgumentOutOfRangeException("Can only support hash v2"); - } - - IList cosmosElements = new List(); - foreach (string partitionKeyPath in partitionKeyDefinition.Paths) - { - IEnumerable tokens = partitionKeyPath.Split("/").Skip(1); - CosmosElement partitionKey = payload; - foreach (string token in tokens) - { - if (partitionKey != default) - { - if (!payload.TryGetValue(token, out partitionKey)) - { - partitionKey = default; - } - } - } - cosmosElements.Add(partitionKey); - } - return cosmosElements; - } - - private static IList GetPartitionKeysFromObjectModel(Cosmos.PartitionKey payload) - { - CosmosArray partitionKeyPayload = CosmosArray.Parse(payload.ToJsonString()); - List cosmosElemementPayload = new List(); - foreach (CosmosElement element in partitionKeyPayload) - { - cosmosElemementPayload.Add(element); - } - return cosmosElemementPayload; - } - - private static PartitionKeyHash GetHashFromPartitionKeys(IList partitionKeys, PartitionKeyDefinition partitionKeyDefinition) - { - // Restrict the partition key definition for now to keep things simple - if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) - { - throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); - } - - if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) - { - throw new ArgumentOutOfRangeException("Can only support hash v2"); - } - - IList partitionKeyHashValues = new List(); - - foreach (CosmosElement partitionKey in partitionKeys) - { - if (partitionKey is CosmosArray cosmosArray) - { - foreach (CosmosElement element in cosmosArray) - { - PartitionKeyHash elementHash = element switch - { - null => PartitionKeyHash.V2.HashUndefined(), - CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), - CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), - CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), - CosmosNull _ => PartitionKeyHash.V2.HashNull(), - _ => throw new ArgumentOutOfRangeException(), - }; - partitionKeyHashValues.Add(elementHash.HashValues[0]); - } - continue; - } - - PartitionKeyHash partitionKeyHash = partitionKey switch - { - null => PartitionKeyHash.V2.HashUndefined(), - CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), - CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), - CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), - CosmosNull _ => PartitionKeyHash.V2.HashNull(), - _ => throw new ArgumentOutOfRangeException(), - }; - partitionKeyHashValues.Add(partitionKeyHash.HashValues[0]); - } - - return new PartitionKeyHash(partitionKeyHashValues.ToArray()); - } - - private static CosmosObject ConvertRecordToCosmosElement(Record record) - { - Dictionary keyValuePairs = new Dictionary - { - ["_rid"] = CosmosString.Create(record.ResourceIdentifier.ToString()), - ["_ts"] = CosmosNumber64.Create(record.Timestamp.Ticks), - ["id"] = CosmosString.Create(record.Identifier) - }; - - foreach (KeyValuePair property in record.Payload) - { - keyValuePairs[property.Key] = property.Value; - } - - return CosmosObject.Create(keyValuePairs); - } - - private static bool IsRecordWithinFeedRange( - Record record, - FeedRange feedRange, - PartitionKeyDefinition partitionKeyDefinition) - { - if (feedRange is FeedRangePartitionKey feedRangePartitionKey) - { - IList partitionKey = GetPartitionKeysFromObjectModel(feedRangePartitionKey.PartitionKey); - IList partitionKeyFromRecord = GetPartitionKeysFromPayload(record.Payload, partitionKeyDefinition); - if (partitionKeyDefinition.Kind == PartitionKind.MultiHash) - { - PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); - PartitionKeyHash partitionKeyFromRecordHash = GetHashFromPartitionKeys(partitionKeyFromRecord, partitionKeyDefinition); - - return partitionKeyHash.Equals(partitionKeyFromRecordHash) || partitionKeyFromRecordHash.Value.StartsWith(partitionKeyHash.Value); - } - return partitionKey.SequenceEqual(partitionKeyFromRecord); - } - else if (feedRange is FeedRangeEpk feedRangeEpk) - { - PartitionKeyHashRange hashRange = FeedRangeEpkToHashRange(feedRangeEpk); - PartitionKeyHash hash = GetHashFromPayload(record.Payload, partitionKeyDefinition); - return hashRange.Contains(hash); - } - else if (feedRange is FeedRangePartitionKeyRange) - { - return true; - } - else - { - throw new NotImplementedException(); - } - } - - private TryCatch MonadicGetPartitionKeyRangeIdFromFeedRange(FeedRange feedRange) - { - int partitionKeyRangeId; - if (feedRange is FeedRangeEpk feedRangeEpk) - { - // Check to see if any of the system ranges contain the user range. - List matchIds; - if (feedRangeEpk.Range.Min.Equals(FeedRangeEpk.FullRange.Range.Min) && feedRangeEpk.Range.Max.Equals(FeedRangeEpk.FullRange.Range.Max)) - { - matchIds = this.PartitionKeyRangeIds.ToList(); - } - else - { - PartitionKeyHashRange hashRange = FeedRangeEpkToHashRange(feedRangeEpk); - matchIds = this.partitionKeyRangeIdToHashRange - .Where(kvp => kvp.Value.Contains(hashRange)) - .Select(kvp => kvp.Key) - .ToList(); - } - - if (matchIds.Count != 1) - { - // Simulate a split exception, since we don't have a partition key range id to route to. - CosmosException goneException = new CosmosException( - message: $"Epk Range: {feedRangeEpk.Range} is gone.", - statusCode: System.Net.HttpStatusCode.Gone, - subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, - activityId: Guid.NewGuid().ToString(), - requestCharge: default); - - return TryCatch.FromException(goneException); - } - - partitionKeyRangeId = matchIds[0]; - } - else if (feedRange is FeedRangePartitionKeyRange feedRangePartitionKeyRange) - { - partitionKeyRangeId = int.Parse(feedRangePartitionKeyRange.PartitionKeyRangeId); - } - else if (feedRange is FeedRangePartitionKey feedRangePartitionKey) - { - PartitionKeyHash partitionKeyHash = GetHashFromObjectModel(feedRangePartitionKey.PartitionKey, this.partitionKeyDefinition); - - int? foundValue = null; - foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) - { - if (kvp.Value.Contains(partitionKeyHash)) - { - foundValue = kvp.Key; - } - } - - if (!foundValue.HasValue) - { - throw new InvalidOperationException("Failed to find value"); - } - - partitionKeyRangeId = foundValue.Value; - } - else - { - throw new NotImplementedException("Unknown feed range type"); - } - - return TryCatch.FromResult(partitionKeyRangeId); - } - - private static PartitionKeyHashRange FeedRangeEpkToHashRange(FeedRangeEpk feedRangeEpk) - { - PartitionKeyHash? start = feedRangeEpk.Range.Min == string.Empty ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Min); - PartitionKeyHash? end = feedRangeEpk.Range.Max == string.Empty || feedRangeEpk.Range.Max == "FF" ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Max); - PartitionKeyHashRange hashRange = new PartitionKeyHashRange(start, end); - return hashRange; - } - - private static FeedRangeEpk HashRangeToFeedRangeEpk(PartitionKeyHashRange hashRange) - { - return new FeedRangeEpk( - new Documents.Routing.Range( - min: hashRange.StartInclusive.HasValue ? hashRange.StartInclusive.ToString() : string.Empty, - max: hashRange.EndExclusive.HasValue ? hashRange.EndExclusive.ToString() : string.Empty, - isMinInclusive: true, - isMaxInclusive: false)); - } - - private PartitionKeyHash ComputeMedianSplitPointAmongDocumentsInPKRange(PartitionKeyHashRange hashRange) - { - if (!this.partitionedRecords.TryGetValue(hashRange, out Records parentRecords)) - { - throw new InvalidOperationException("failed to find the range."); - } - - List partitionKeyHashes = new List(); - foreach (Record record in parentRecords) - { - PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); - partitionKeyHashes.Add(partitionKeyHash); - } - - partitionKeyHashes.Sort(); - PartitionKeyHash medianPkHash = partitionKeyHashes[partitionKeyHashes.Count / 2]; - - // For MultiHash Collection, split at top level to ensure documents for top level key exist across partitions - // after split - if (medianPkHash.HashValues.Count > 1) - { - return new PartitionKeyHash(medianPkHash.HashValues[0]); - } - - return medianPkHash; - } - public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) - { - return Task.FromResult(TryCatch.FromResult("AYIMAMmFOw8YAAAAAAAAAA==")); - } - - private sealed class Records : IReadOnlyList - { - private readonly List storage; - - public Records() - { - this.storage = new List(); - } - - public Record this[int index] => this.storage[index]; - - public int Count => this.storage.Count; - - public IEnumerator GetEnumerator() => this.storage.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => this.storage.GetEnumerator(); - - public Record Add(int pkrangeid, CosmosObject payload) - { - // using pkrangeid for database since resource id doesnt serialize both document and pkrangeid. - ResourceId currentResourceId; - if (this.Count == 0) - { - currentResourceId = ResourceId.Parse("AYIMAMmFOw8YAAAAAAAAAA=="); - - PropertyInfo documentProp = currentResourceId - .GetType() - .GetProperty("Document", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - documentProp.SetValue(currentResourceId, (ulong)1); - - PropertyInfo databaseProp = currentResourceId - .GetType() - .GetProperty("Database", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - databaseProp.SetValue(currentResourceId, (uint)pkrangeid + 1); - } - else - { - currentResourceId = this.storage[this.storage.Count - 1].ResourceIdentifier; - } - - ResourceId nextResourceId = ResourceId.Parse("AYIMAMmFOw8YAAAAAAAAAA=="); - { - PropertyInfo documentProp = nextResourceId - .GetType() - .GetProperty("Document", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - documentProp.SetValue(nextResourceId, (ulong)(currentResourceId.Document + 1)); - - PropertyInfo databaseProp = nextResourceId - .GetType() - .GetProperty("Database", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); - databaseProp.SetValue(nextResourceId, (uint)pkrangeid + 1); - } - - Record record = new Record(nextResourceId, DateTime.UtcNow, Guid.NewGuid().ToString(), payload); - this.storage.Add(record); - return record; - } - - public Record Add(Record record) - { - this.storage.Add(record); - return record; - } - } - - private readonly struct Change - { - public Change(Record record, ulong partitionKeyRangeId, ulong logicalSequenceNumber) - { - this.Record = record ?? throw new ArgumentNullException(nameof(record)); - this.PartitionKeyRangeId = partitionKeyRangeId; - this.LogicalSequenceNumber = logicalSequenceNumber; - } - - public Record Record { get; } - public ulong PartitionKeyRangeId { get; } - public ulong LogicalSequenceNumber { get; } - } - - private sealed class ChangeFeedPredicate : IChangeFeedStateVisitor - { - public static readonly ChangeFeedPredicate Singleton = new ChangeFeedPredicate(); - - private ChangeFeedPredicate() - { - } - - public bool Visit(ChangeFeedStateBeginning changeFeedStateBeginning, Change input) => true; - - public bool Visit(ChangeFeedStateTime changeFeedStateTime, Change input) => input.Record.Timestamp >= changeFeedStateTime.StartTime; - - public bool Visit(ChangeFeedStateContinuation changeFeedStateContinuation, Change input) - { - CosmosObject continuation = (CosmosObject)changeFeedStateContinuation.ContinuationToken; - - if (!continuation.TryGetValue("PkRangeId", out CosmosNumber pkRangeIdCosmosElement)) - { - throw new InvalidOperationException("failed to get pkrange id"); - } - - ulong pkRangeId = (ulong)Number64.ToLong(pkRangeIdCosmosElement.Value); - - if (!continuation.TryGetValue("LSN", out CosmosNumber lsnCosmosElement)) - { - throw new InvalidOperationException("failed to get lsn"); - } - - ulong lsn = (ulong)Number64.ToLong(lsnCosmosElement.Value); - - int pkRangeIdCompare = input.PartitionKeyRangeId.CompareTo(pkRangeId); - if (pkRangeIdCompare < 0) - { - return false; - } - else if (pkRangeIdCompare > 0) - { - return true; - } - else - { - return input.LogicalSequenceNumber > lsn; - } - } - - public bool Visit(ChangeFeedStateNow changeFeedStateNow, Change input) - { - DateTime now = DateTime.UtcNow; - ChangeFeedStateTime startTime = new ChangeFeedStateTime(now); - return this.Visit(startTime, input); - } - } - - private sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor - { - public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); - - private CosmosElementToSqlScalarExpressionVisitor() - { - // Private constructor, since this class is a singleton. - } - - public SqlScalarExpression Visit(CosmosArray cosmosArray) - { - List items = new List(); - foreach (CosmosElement item in cosmosArray) - { - items.Add(item.Accept(this)); - } - - return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosBinary cosmosBinary) - { - // Can not convert binary to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) - { - return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); - } - - public SqlScalarExpression Visit(CosmosGuid cosmosGuid) - { - // Can not convert guid to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosNull cosmosNull) - { - return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); - } - - public SqlScalarExpression Visit(CosmosNumber cosmosNumber) - { - if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) - { - throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); - } - - return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); - } - - public SqlScalarExpression Visit(CosmosObject cosmosObject) - { - List properties = new List(); - foreach (KeyValuePair prop in cosmosObject) - { - SqlPropertyName name = SqlPropertyName.Create(prop.Key); - CosmosElement value = prop.Value; - SqlScalarExpression expression = value.Accept(this); - SqlObjectProperty property = SqlObjectProperty.Create(name, expression); - properties.Add(property); - } - - return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosString cosmosString) - { - return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); - } - - public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) - { - return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Pagination +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + using Microsoft.Azure.Cosmos.Json; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Parser; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Distinct; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Serialization.HybridRow; + using Microsoft.Azure.Cosmos.SqlObjects; + using Microsoft.Azure.Cosmos.Tests.Query.OfflineEngine; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using static Microsoft.Azure.Cosmos.Query.Core.SqlQueryResumeFilter; + using ResourceIdentifier = Cosmos.Pagination.ResourceIdentifier; + using UInt128 = UInt128; + + // Collection useful for mocking requests and repartitioning (splits / merge). + internal class InMemoryContainer : IMonadicDocumentContainer + { + private readonly PartitionKeyDefinition partitionKeyDefinition; + private readonly Dictionary parentToChildMapping; + + private PartitionKeyHashRangeDictionary partitionedRecords; + private PartitionKeyHashRangeDictionary> partitionedChanges; + private Dictionary partitionKeyRangeIdToHashRange; + private Dictionary cachedPartitionKeyRangeIdToHashRange; + + public InMemoryContainer( + PartitionKeyDefinition partitionKeyDefinition) + { + this.partitionKeyDefinition = partitionKeyDefinition ?? throw new ArgumentNullException(nameof(partitionKeyDefinition)); + PartitionKeyHashRange fullRange = new PartitionKeyHashRange(startInclusive: null, endExclusive: new PartitionKeyHash(Cosmos.UInt128.MaxValue)); + PartitionKeyHashRanges partitionKeyHashRanges = PartitionKeyHashRanges.Create(new PartitionKeyHashRange[] { fullRange }); + this.partitionedRecords = new PartitionKeyHashRangeDictionary(partitionKeyHashRanges); + this.partitionedRecords[fullRange] = new Records(); + this.partitionedChanges = new PartitionKeyHashRangeDictionary>(partitionKeyHashRanges); + this.partitionedChanges[fullRange] = new List(); + this.partitionKeyRangeIdToHashRange = new Dictionary() + { + { 0, fullRange } + }; + this.cachedPartitionKeyRangeIdToHashRange = new Dictionary() + { + { 0, fullRange } + }; + this.parentToChildMapping = new Dictionary(); + } + + public Task>> MonadicGetFeedRangesAsync( + ITrace trace, + CancellationToken cancellationToken) => this.MonadicGetChildRangeAsync( + FeedRangeEpk.FullRange, + trace, + cancellationToken); + + public async Task>> MonadicGetChildRangeAsync( + FeedRangeInternal feedRange, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (feedRange == null) + { + throw new ArgumentNullException(nameof(feedRange)); + } + + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + + using (ITrace getChildRangesTrace = trace.StartChild(name: "Get Child Ranges", TraceComponent.Routing, TraceLevel.Info)) + { + FeedRangeEpk CreateRangeFromId(int id) + { + PartitionKeyHashRange hashRange = this.cachedPartitionKeyRangeIdToHashRange[id]; + return new FeedRangeEpk( + new Documents.Routing.Range( + min: hashRange.StartInclusive.HasValue ? hashRange.StartInclusive.Value.ToString() : string.Empty, + max: hashRange.EndExclusive.HasValue ? hashRange.EndExclusive.Value.ToString() : string.Empty, + isMinInclusive: true, + isMaxInclusive: false)); + } + + if (feedRange is FeedRangePartitionKey) + { + throw new ArgumentException("Can not get the child of a logical partition key"); + } + + if (feedRange.Equals(FeedRangeEpk.FullRange)) + { + List ranges = new List(); + foreach (int id in this.cachedPartitionKeyRangeIdToHashRange.Keys) + { + ranges.Add(CreateRangeFromId(id)); + } + + return TryCatch>.FromResult(ranges); + } + + if (feedRange is FeedRangeEpk feedRangeEpk) + { + // look for overlapping epk ranges. + List overlappingRanges; + if (feedRangeEpk.Range.Min.Equals(FeedRangeEpk.FullRange.Range.Min) && feedRangeEpk.Range.Max.Equals(FeedRangeEpk.FullRange.Range.Max)) + { + overlappingRanges = this.cachedPartitionKeyRangeIdToHashRange.Select(kvp => CreateRangeFromId(kvp.Key)).ToList(); + } + else + { + overlappingRanges = new List(); + PartitionKeyHashRange userRange = FeedRangeEpkToHashRange(feedRangeEpk); + foreach (PartitionKeyHashRange systemRange in this.cachedPartitionKeyRangeIdToHashRange.Values) + { + if (userRange.TryGetOverlappingRange(systemRange, out PartitionKeyHashRange overlappingRange)) + { + overlappingRanges.Add(HashRangeToFeedRangeEpk(overlappingRange)); + } + } + } + + if (overlappingRanges.Count == 0) + { + return TryCatch>.FromException( + new KeyNotFoundException( + $"PartitionKeyRangeId: {feedRangeEpk} does not exist.")); + } + + return TryCatch>.FromResult(overlappingRanges); + } + + if (!(feedRange is FeedRangePartitionKeyRange feedRangePartitionKeyRange)) + { + throw new InvalidOperationException("Expected feed range to be a partition key range at this point."); + } + + if (!int.TryParse(feedRangePartitionKeyRange.PartitionKeyRangeId, out int partitionKeyRangeId)) + { + return TryCatch>.FromException( + new FormatException( + $"PartitionKeyRangeId: {feedRangePartitionKeyRange.PartitionKeyRangeId} is not an integer.")); + } + + if (!this.parentToChildMapping.TryGetValue(partitionKeyRangeId, out (int left, int right) children)) + { + // This range has no children (base case) + if (!this.cachedPartitionKeyRangeIdToHashRange.TryGetValue(partitionKeyRangeId, out PartitionKeyHashRange hashRange)) + { + return TryCatch>.FromException( + new KeyNotFoundException( + $"PartitionKeyRangeId: {partitionKeyRangeId} does not exist.")); + } + + List singleRange = new List() + { + CreateRangeFromId(partitionKeyRangeId), + }; + + return TryCatch>.FromResult(singleRange); + } + + // Recurse on the left and right child. + FeedRangeInternal left = new FeedRangePartitionKeyRange(children.left.ToString()); + FeedRangeInternal right = new FeedRangePartitionKeyRange(children.right.ToString()); + + TryCatch> tryGetLeftRanges = await this.MonadicGetChildRangeAsync(left, trace, cancellationToken); + if (tryGetLeftRanges.Failed) + { + return tryGetLeftRanges; + } + + TryCatch> tryGetRightRanges = await this.MonadicGetChildRangeAsync(right, trace, cancellationToken); + if (tryGetRightRanges.Failed) + { + return tryGetRightRanges; + } + + List recursiveOverlappingRanges = tryGetLeftRanges.Result.Concat(tryGetRightRanges.Result).ToList(); + return TryCatch>.FromResult(recursiveOverlappingRanges); + } + } + + public Task MonadicRefreshProviderAsync( + ITrace trace, + CancellationToken cancellationToken) + { + using (ITrace refreshProviderTrace = trace.StartChild("Refreshing FeedRangeProvider", TraceComponent.Routing, TraceLevel.Info)) + { + this.cachedPartitionKeyRangeIdToHashRange = new Dictionary(this.partitionKeyRangeIdToHashRange); + return Task.FromResult(TryCatch.FromResult()); + } + } + + public Task> MonadicCreateItemAsync( + CosmosObject payload, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (payload == null) + { + throw new ArgumentNullException(nameof(payload)); + } + + PartitionKeyHash partitionKeyHash = GetHashFromPayload(payload, this.partitionKeyDefinition); + if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) + { + records = new Records(); + this.partitionedRecords[partitionKeyHash] = records; + } + + int? pkrangeid = null; + foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) + { + if (kvp.Value.Contains(partitionKeyHash)) + { + pkrangeid = kvp.Key; + } + } + + if (!pkrangeid.HasValue) + { + throw new InvalidOperationException(); + } + + Record recordAdded = records.Add(pkrangeid.Value, payload); + + if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) + { + changes = new List(); + this.partitionedChanges[partitionKeyHash] = changes; + } + + ulong maxLogicalSequenceNumber = changes.Count == 0 ? 0 : changes.Select(change => change.LogicalSequenceNumber).Max(); + + Change change = new Change( + recordAdded, + partitionKeyRangeId: (ulong)pkrangeid.Value, + logicalSequenceNumber: maxLogicalSequenceNumber + 1); + + changes.Add(change); + return Task.FromResult(TryCatch.FromResult(recordAdded)); + } + + public Task> MonadicReadItemAsync( + CosmosElement partitionKey, + string identifier, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + static Task> CreateNotFoundException(CosmosElement partitionKey, string identifer) + { + return Task.FromResult( + TryCatch.FromException( + new CosmosException( + message: $"Document with partitionKey: {partitionKey?.ToString() ?? "UNDEFINED"} and id: {identifer} not found.", + statusCode: System.Net.HttpStatusCode.NotFound, + subStatusCode: default, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys( + new List { partitionKey }, + this.partitionKeyDefinition); + + if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) + { + return CreateNotFoundException(partitionKey, identifier); + } + + foreach (Record candidate in records) + { + bool identifierMatches = candidate.Identifier == identifier; + + CosmosElement candidatePartitionKey = GetPartitionKeyFromPayload( + candidate.Payload, + this.partitionKeyDefinition); + + bool partitionKeyMatches; + if (candidatePartitionKey is null && partitionKey is null) + { + partitionKeyMatches = true; + } + else if ((candidatePartitionKey != null) && (partitionKey != null)) + { + partitionKeyMatches = candidatePartitionKey.Equals(partitionKey); + } + else + { + partitionKeyMatches = false; + } + + if (identifierMatches && partitionKeyMatches) + { + return Task.FromResult(TryCatch.FromResult(candidate)); + } + } + + return CreateNotFoundException(partitionKey, identifier); + } + + public Task> MonadicReadFeedAsync( + FeedRangeState feedRangeState, + ReadFeedPaginationOptions readFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + readFeedPaginationOptions ??= ReadFeedPaginationOptions.Default; + + using (ITrace readFeed = trace.StartChild("Read Feed Transport", TraceComponent.Transport, TraceLevel.Info)) + { + TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); + if (monadicPartitionKeyRangeId.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); + } + + int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; + + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + partitionKeyRangeId, + out PartitionKeyHashRange range)) + { + return Task.FromResult( + TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedRecords.TryGetValue(range, out Records records)) + { + throw new InvalidOperationException("failed to find the range."); + } + + (ulong pkrangeId, ulong documentIndex) rangeIdAndIndex; + if (feedRangeState.State is ReadFeedBeginningState) + { + rangeIdAndIndex = (0, 0); + } + else if (feedRangeState.State is ReadFeedContinuationState readFeedContinuationState) + { + ResourceIdentifier resourceIdentifier = ResourceIdentifier.Parse(((CosmosString)readFeedContinuationState.ContinuationToken).Value); + rangeIdAndIndex = (resourceIdentifier.Database, resourceIdentifier.Document); + } + else + { + throw new InvalidOperationException("Unknown read feed state"); + } + + List page = records + .Where((record) => + { + if (!IsRecordWithinFeedRange(record, feedRangeState.FeedRange, this.partitionKeyDefinition)) + { + return false; + } + + // We do a filter on a composite index here + int pkRangeIdCompare = record.ResourceIdentifier.Database.CompareTo((uint)rangeIdAndIndex.pkrangeId); + if (pkRangeIdCompare < 0) + { + return false; + } + else if (pkRangeIdCompare > 0) + { + return true; + } + else // pkRangeIdCompare == 0 + { + return record.ResourceIdentifier.Document > rangeIdAndIndex.documentIndex; + } + }) + .Take(readFeedPaginationOptions.PageSizeLimit.GetValueOrDefault(int.MaxValue)) + .ToList(); + + List documents = new List(); + foreach (Record record in page) + { + CosmosObject document = ConvertRecordToCosmosElement(record); + documents.Add(CosmosObject.Create(document)); + } + + ReadFeedState continuationState; + if (documents.Count == 0) + { + continuationState = null; + } + else + { + ResourceId resourceIdentifier = page.Last().ResourceIdentifier; + CosmosString continuationToken = CosmosString.Create(resourceIdentifier.ToString()); + continuationState = ReadFeedState.Continuation(continuationToken); + } + + CosmosArray cosmosDocuments = CosmosArray.Create(documents); + CosmosNumber cosmosCount = CosmosNumber64.Create(cosmosDocuments.Count); + CosmosString cosmosRid = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA=="); + + Dictionary responseDictionary = new Dictionary() + { + { "Documents", cosmosDocuments }, + { "_count", cosmosCount }, + { "_rid", cosmosRid }, + }; + CosmosObject cosmosResponse = CosmosObject.Create(responseDictionary); + IJsonWriter jsonWriter = Cosmos.Json.JsonWriter.Create(JsonSerializationFormat.Text); + cosmosResponse.WriteTo(jsonWriter); + byte[] result = jsonWriter.GetResult().ToArray(); + MemoryStream responseStream = new MemoryStream(result); + + ReadFeedPage readFeedPage = new ReadFeedPage( + responseStream, + requestCharge: 42, + itemCount: cosmosDocuments.Count, + activityId: Guid.NewGuid().ToString(), + additionalHeaders: new Dictionary() + { + { "test-header", "test-value" } + }, + continuationState); + + return Task.FromResult(TryCatch.FromResult(readFeedPage)); + } + } + + public virtual Task> MonadicQueryAsync( + SqlQuerySpec sqlQuerySpec, + FeedRangeState feedRangeState, + QueryPaginationOptions queryPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) + { + return Task.FromCanceled>(cancellationToken); + } + if (sqlQuerySpec == null) + { + throw new ArgumentNullException(nameof(sqlQuerySpec)); + } + + using (ITrace childTrace = trace.StartChild("Query Transport", TraceComponent.Transport, TraceLevel.Info)) + { + TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); + if (monadicPartitionKeyRangeId.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); + } + + int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; + + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + partitionKeyRangeId, + out PartitionKeyHashRange range)) + { + return Task.FromResult(TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedRecords.TryGetValue(range, out Records records)) + { + throw new InvalidOperationException("failed to find the range."); + } + + List documents = new List(); + foreach (Record record in records.Where(r => IsRecordWithinFeedRange(r, feedRangeState.FeedRange, this.partitionKeyDefinition))) + { + CosmosObject document = ConvertRecordToCosmosElement(record); + documents.Add(CosmosObject.Create(document)); + } + + TryCatch monadicParse = SqlQueryParser.Monadic.Parse(sqlQuerySpec.QueryText); + if (monadicParse.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicParse.Exception)); + } + + SqlQuery sqlQuery = monadicParse.Result; + if ((sqlQuery.OrderByClause != null) && (feedRangeState.State != null) && (sqlQuerySpec.ResumeFilter == null)) + { + // This is a hack. + // If the query is an ORDER BY query then we need to seek to the resume term. + // Since I don't want to port over the proper logic from the backend I will just inject a filter. + // For now I am only handling the single order by item case + if (sqlQuery.OrderByClause.OrderByItems.Length != 1) + { + throw new NotImplementedException("Can only support a single order by column"); + } + + SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; + CosmosObject parsedContinuationToken = CosmosObject.Parse(((CosmosString)feedRangeState.State.Value).Value); + SqlBinaryScalarExpression resumeFilter = SqlBinaryScalarExpression.Create( + orderByItem.IsDescending ? SqlBinaryScalarOperatorKind.LessThan : SqlBinaryScalarOperatorKind.GreaterThan, + orderByItem.Expression, + parsedContinuationToken["orderByItem"].Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton)); + + SqlWhereClause modifiedWhereClause = sqlQuery.WhereClause.FilterExpression == null + ? SqlWhereClause.Create(resumeFilter) + : SqlWhereClause.Create( + SqlBinaryScalarExpression.Create( + SqlBinaryScalarOperatorKind.And, + sqlQuery.WhereClause.FilterExpression, + resumeFilter)); + + sqlQuery = SqlQuery.Create( + sqlQuery.SelectClause, + sqlQuery.FromClause, + modifiedWhereClause, + sqlQuery.GroupByClause, + sqlQuery.OrderByClause, + sqlQuery.OffsetLimitClause); + + // We still need to handle duplicate values and break the tie with the rid + // But since all the values are unique for our testing purposes we can ignore this for now. + } + IEnumerable queryResults = SqlInterpreter.ExecuteQuery(documents, sqlQuery); + IEnumerable queryPageResults = queryResults; + + // If the resume value is passed in query spec, filter out the results that has order by item value smaller than resume values + if (sqlQuerySpec.ResumeFilter != null) + { + if (sqlQuery.OrderByClause.OrderByItems.Length != 1) + { + throw new NotImplementedException("Can only support a single order by column"); + } + + SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; + IEnumerator queryResultEnumerator = queryPageResults.GetEnumerator(); + + int skipCount = 0; + while(queryResultEnumerator.MoveNext()) + { + CosmosObject document = (CosmosObject)queryResultEnumerator.Current; + CosmosElement orderByValue = ((CosmosObject)((CosmosArray)document["orderByItems"])[0])["item"]; + + int sortOrderCompare = sqlQuerySpec.ResumeFilter.ResumeValues[0].CompareTo(orderByValue); + + if (sortOrderCompare != 0) + { + sortOrderCompare = orderByItem.IsDescending ? -sortOrderCompare : sortOrderCompare; + } + + if (sortOrderCompare < 0) + { + // We might have passed the item due to deletions and filters. + break; + } + + if (sortOrderCompare >= 0) + { + // This document does not match the sort order, so skip it. + skipCount++; + } + } + + queryPageResults = queryPageResults.Skip(skipCount); + + // NOTE: We still need to handle duplicate values and break the tie with the rid + // But since all the values are unique for our testing purposes we can ignore this for now. + } + + // Filter for the continuation token + string continuationResourceId; + int continuationSkipCount; + + if ((sqlQuery.OrderByClause == null) && (feedRangeState.State != null)) + { + CosmosObject parsedContinuationToken = CosmosObject.Parse(((CosmosString)feedRangeState.State.Value).Value); + continuationResourceId = ((CosmosString)parsedContinuationToken["resourceId"]).Value; + continuationSkipCount = (int)Number64.ToLong(((CosmosNumber64)parsedContinuationToken["skipCount"]).Value); + + ResourceIdentifier continuationParsedResourceId = ResourceIdentifier.Parse(continuationResourceId); + queryPageResults = queryPageResults.Where(c => + { + ResourceId documentResourceId = ResourceId.Parse(((CosmosString)((CosmosObject)c)["_rid"]).Value); + // Perform a composite filter on pkrange id and document index + int pkRangeIdCompare = documentResourceId.Database.CompareTo(continuationParsedResourceId.Database); + if (pkRangeIdCompare < 0) + { + return false; + } + else if (pkRangeIdCompare > 0) + { + return true; + } + else // pkRangeIdCompare == 0 + { + int documentCompare = documentResourceId.Document.CompareTo(continuationParsedResourceId.Document); + + // If we have a skip count, then we can't skip over the rid we last saw, since + // there are documents with the same rid that we need to skip over. + return continuationSkipCount == 0 ? documentCompare > 0 : documentCompare >= 0; + } + }); + + for (int i = 0; i < continuationSkipCount; i++) + { + if (queryPageResults.FirstOrDefault() is CosmosObject firstDocument) + { + string currentResourceId = ((CosmosString)firstDocument["_rid"]).Value; + if (currentResourceId == continuationResourceId) + { + queryPageResults = queryPageResults.Skip(1); + } + } + } + } + else + { + continuationResourceId = null; + continuationSkipCount = 0; + } + + queryPageResults = queryPageResults.Take((queryPaginationOptions ?? QueryPaginationOptions.Default).PageSizeLimit.GetValueOrDefault(int.MaxValue)); + List queryPageResultList = queryPageResults.ToList(); + QueryState queryState; + if (queryPageResultList.LastOrDefault() is CosmosObject lastDocument + && lastDocument.TryGetValue("_rid", out CosmosString resourceId)) + { + string currentResourceId = resourceId.Value; + int currentSkipCount = queryPageResultList + .Where(document => ((CosmosString)((CosmosObject)document)["_rid"]).Value == currentResourceId) + .Count(); + if (currentResourceId == continuationResourceId) + { + currentSkipCount += continuationSkipCount; + } + + Dictionary queryStateDictionary = new Dictionary() + { + { "resourceId", CosmosString.Create(currentResourceId) }, + { "skipCount", CosmosNumber64.Create(currentSkipCount) }, + }; + + if (sqlQuery.OrderByClause != null) + { + SqlOrderByItem orderByItem = sqlQuery.OrderByClause.OrderByItems[0]; + string propertyName = ((SqlPropertyRefScalarExpression)orderByItem.Expression).Identifier.Value; + queryStateDictionary["orderByItem"] = ((CosmosObject)lastDocument["payload"])[propertyName]; + } + + CosmosObject queryStateValue = CosmosObject.Create(queryStateDictionary); + + queryState = new QueryState(CosmosString.Create(queryStateValue.ToString())); + } + else + { + queryState = default; + } + + ImmutableDictionary.Builder additionalHeaders = ImmutableDictionary.CreateBuilder(); + additionalHeaders.Add("x-ms-documentdb-partitionkeyrangeid", "0"); + additionalHeaders.Add("x-ms-test-header", "true"); + + return Task.FromResult( + TryCatch.FromResult( + new QueryPage( + queryPageResultList, + requestCharge: 42, + activityId: Guid.NewGuid().ToString(), + cosmosQueryExecutionInfo: default, + distributionPlanSpec: default, + disallowContinuationTokenMessage: default, + additionalHeaders: additionalHeaders.ToImmutable(), + state: queryState, + streaming: default))); + } + } + + public Task> MonadicChangeFeedAsync( + FeedRangeState feedRangeState, + ChangeFeedPaginationOptions changeFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + using (ITrace childTrace = trace.StartChild("Change Feed Transport", TraceComponent.Transport, TraceLevel.Info)) + { + TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); + if (monadicPartitionKeyRangeId.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); + } + + int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; + + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + partitionKeyRangeId, + out PartitionKeyHashRange range)) + { + return Task.FromResult(TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedChanges.TryGetValue(range, out List changes)) + { + throw new InvalidOperationException("failed to find the range."); + } + + List filteredChanges = changes + .Where(change => IsRecordWithinFeedRange(change.Record, feedRangeState.FeedRange, this.partitionKeyDefinition)) + .Where(change => feedRangeState.State.Accept(ChangeFeedPredicate.Singleton, change)) + .Take((changeFeedPaginationOptions ?? ChangeFeedPaginationOptions.Default).PageSizeLimit.GetValueOrDefault(int.MaxValue)) + .ToList(); + + if (filteredChanges.Count == 0) + { + ChangeFeedState notModifiedResponseState = new ChangeFeedStateTime(DateTime.UtcNow); + return Task.FromResult( + TryCatch.FromResult( + new ChangeFeedNotModifiedPage( + requestCharge: 42, + activityId: Guid.NewGuid().ToString(), + additionalHeaders: default, + notModifiedResponseState))); + } + + Change lastChange = filteredChanges.Last(); + CosmosObject continuationToken = CosmosObject.Create( + new Dictionary() + { + { "PkRangeId", CosmosNumber64.Create(lastChange.PartitionKeyRangeId) }, + { "LSN", CosmosNumber64.Create(lastChange.LogicalSequenceNumber) } + }); + + ChangeFeedState responseState = ChangeFeedState.Continuation(continuationToken); + + List documents = new List(); + foreach (Change change in filteredChanges) + { + CosmosObject document = ConvertRecordToCosmosElement(change.Record); + documents.Add(CosmosObject.Create(document)); + } + + CosmosArray cosmosDocuments = CosmosArray.Create(documents); + CosmosNumber cosmosCount = CosmosNumber64.Create(cosmosDocuments.Count); + CosmosString cosmosRid = CosmosString.Create("AYIMAMmFOw8YAAAAAAAAAA=="); + + Dictionary responseDictionary = new Dictionary() + { + { "Documents", cosmosDocuments }, + { "_count", cosmosCount }, + { "_rid", cosmosRid }, + }; + CosmosObject cosmosResponse = CosmosObject.Create(responseDictionary); + IJsonWriter jsonWriter = Cosmos.Json.JsonWriter.Create(JsonSerializationFormat.Text); + cosmosResponse.WriteTo(jsonWriter); + byte[] result = jsonWriter.GetResult().ToArray(); + MemoryStream responseStream = new MemoryStream(result); + + return Task.FromResult( + TryCatch.FromResult( + new ChangeFeedSuccessPage( + responseStream, + requestCharge: 42, + itemCount: cosmosDocuments.Count, + activityId: Guid.NewGuid().ToString(), + additionalHeaders: default, + responseState))); + } + } + + public Task MonadicSplitAsync( + FeedRangeInternal feedRange, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (feedRange == null) + { + throw new ArgumentNullException(nameof(feedRange)); + } + + TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange); + if (monadicPartitionKeyRangeId.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); + } + + int partitionKeyRangeId = monadicPartitionKeyRangeId.Result; + + // Get the current range and records + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + partitionKeyRangeId, + out PartitionKeyHashRange parentRange)) + { + return Task.FromResult( + TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {partitionKeyRangeId} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedRecords.TryGetValue(parentRange, out Records parentRecords)) + { + throw new InvalidOperationException("failed to find the range."); + } + + if (!this.partitionedChanges.TryGetValue(parentRange, out List parentChanges)) + { + throw new InvalidOperationException("failed to find the range."); + } + + // Split the range space + PartitionKeyHashRanges partitionKeyHashRanges; + if (this.partitionKeyDefinition.Kind == PartitionKind.MultiHash && + this.partitionKeyDefinition.Paths.Count > 1) + { + //For MultiHash, to help with testing we will split using the median partition key among documents. + PartitionKeyHash midPoint = this.ComputeMedianSplitPointAmongDocumentsInPKRange(parentRange); + partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange(parentRange, midPoint); + } + else + { + partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange( + parentRange, + rangeCount: 2); + } + + // Update the partition routing map + int maxPartitionKeyRangeId = this.partitionKeyRangeIdToHashRange.Keys.Max(); + this.parentToChildMapping[partitionKeyRangeId] = (maxPartitionKeyRangeId + 1, maxPartitionKeyRangeId + 2); + Dictionary newPartitionKeyRangeIdToHashRange = new Dictionary() + { + { maxPartitionKeyRangeId + 1, partitionKeyHashRanges.First() }, + { maxPartitionKeyRangeId + 2, partitionKeyHashRanges.Last() }, + }; + + foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) + { + int oldRangeId = kvp.Key; + PartitionKeyHashRange oldRange = kvp.Value; + if (!oldRange.Equals(parentRange)) + { + newPartitionKeyRangeIdToHashRange[oldRangeId] = oldRange; + } + } + + // Copy over the partitioned records (minus the parent range) + PartitionKeyHashRangeDictionary newPartitionedRecords = new PartitionKeyHashRangeDictionary( + PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); + + newPartitionedRecords[partitionKeyHashRanges.First()] = new Records(); + newPartitionedRecords[partitionKeyHashRanges.Last()] = new Records(); + + foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) + { + if (!range.Equals(parentRange)) + { + newPartitionedRecords[range] = this.partitionedRecords[range]; + } + } + + PartitionKeyHashRangeDictionary> newPartitionedChanges = new PartitionKeyHashRangeDictionary>( + PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); + + newPartitionedChanges[partitionKeyHashRanges.First()] = new List(); + newPartitionedChanges[partitionKeyHashRanges.Last()] = new List(); + + foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) + { + if (!range.Equals(parentRange)) + { + newPartitionedChanges[range] = this.partitionedChanges[range]; + } + } + + this.partitionedRecords = newPartitionedRecords; + this.partitionedChanges = newPartitionedChanges; + this.partitionKeyRangeIdToHashRange = newPartitionKeyRangeIdToHashRange; + + // Rehash the records in the parent range + foreach (Record record in parentRecords) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); + if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) + { + records = new Records(); + this.partitionedRecords[partitionKeyHash] = records; + } + + records.Add(record); + } + + // Rehash the changes in the parent range + foreach (Change change in parentChanges) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(change.Record.Payload, this.partitionKeyDefinition); + if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) + { + changes = new List(); + this.partitionedChanges[partitionKeyHash] = changes; + } + + changes.Add(change); + } + + return Task.FromResult(TryCatch.FromResult()); + } + + public Task MonadicMergeAsync( + FeedRangeInternal feedRange1, + FeedRangeInternal feedRange2, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (feedRange1 == null) + { + throw new ArgumentNullException(nameof(feedRange1)); + } + + if (feedRange2 == null) + { + throw new ArgumentNullException(nameof(feedRange2)); + } + + TryCatch monadicPartitionKeyRangeId1 = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange1); + if (monadicPartitionKeyRangeId1.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId1.Exception)); + } + + int sourceRangeId1 = monadicPartitionKeyRangeId1.Result; + + TryCatch monadicPartitionKeyRangeId2 = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange2); + if (monadicPartitionKeyRangeId2.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId2.Exception)); + } + + int sourceRangeId2 = monadicPartitionKeyRangeId2.Result; + + // Get the range and records + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + sourceRangeId1, + out PartitionKeyHashRange sourceHashRange1)) + { + return Task.FromResult( + TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {sourceRangeId1} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedRecords.TryGetValue(sourceHashRange1, out Records sourceRecords1)) + { + throw new InvalidOperationException("failed to find the range."); + } + + if (!this.partitionedChanges.TryGetValue(sourceHashRange1, out List sourceChanges1)) + { + throw new InvalidOperationException("failed to find the range."); + } + + if (!this.partitionKeyRangeIdToHashRange.TryGetValue( + sourceRangeId2, + out PartitionKeyHashRange sourceHashRange2)) + { + return Task.FromResult( + TryCatch.FromException( + new CosmosException( + message: $"PartitionKeyRangeId {sourceRangeId2} is gone", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: 42))); + } + + if (!this.partitionedRecords.TryGetValue(sourceHashRange2, out Records sourceRecords2)) + { + throw new InvalidOperationException("failed to find the range."); + } + + if (!this.partitionedChanges.TryGetValue(sourceHashRange2, out List sourceChanges2)) + { + throw new InvalidOperationException("failed to find the range."); + } + + // Merge the range space + TryCatch monadicRanges = PartitionKeyHashRanges.Monadic.Create(new List() + { + sourceHashRange1, + sourceHashRange2 + }); + + if (monadicRanges.Failed) + { + return Task.FromResult(TryCatch.FromException(monadicRanges.Exception)); + } + + PartitionKeyHashRange mergedHashRange = PartitionKeyHashRangeSplitterAndMerger.MergeRanges( + monadicRanges.Result); + + // Update the partition routing map + int maxPartitionKeyRangeId = this.partitionKeyRangeIdToHashRange.Keys.Max(); + Dictionary newPartitionKeyRangeIdToHashRange = new Dictionary() + { + { maxPartitionKeyRangeId + 1, mergedHashRange }, + }; + + foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) + { + int oldRangeId = kvp.Key; + PartitionKeyHashRange oldRange = kvp.Value; + if (!(oldRange.Equals(sourceHashRange1) || oldRange.Equals(sourceHashRange2))) + { + newPartitionKeyRangeIdToHashRange[oldRangeId] = oldRange; + } + } + + // Copy over the partitioned records (minus the source ranges) + PartitionKeyHashRangeDictionary newPartitionedRecords = new PartitionKeyHashRangeDictionary( + PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); + + newPartitionedRecords[mergedHashRange] = new Records(); + + foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) + { + if (!(range.Equals(sourceHashRange1) || range.Equals(sourceHashRange2))) + { + newPartitionedRecords[range] = this.partitionedRecords[range]; + } + } + + PartitionKeyHashRangeDictionary> newPartitionedChanges = new PartitionKeyHashRangeDictionary>( + PartitionKeyHashRanges.Create(newPartitionKeyRangeIdToHashRange.Values)); + + newPartitionedChanges[mergedHashRange] = new List(); + + foreach (PartitionKeyHashRange range in this.partitionKeyRangeIdToHashRange.Values) + { + if (!(range.Equals(sourceHashRange1) || range.Equals(sourceHashRange2))) + { + newPartitionedChanges[range] = this.partitionedChanges[range]; + } + } + + this.partitionedRecords = newPartitionedRecords; + this.partitionedChanges = newPartitionedChanges; + this.partitionKeyRangeIdToHashRange = newPartitionKeyRangeIdToHashRange; + + // Rehash the records in the source ranges + List combinedOrderedRecords = new List(); + foreach (Records sourceRecords in new Records[] { sourceRecords1, sourceRecords2 }) + { + combinedOrderedRecords.AddRange(sourceRecords); + } + + combinedOrderedRecords = combinedOrderedRecords + .OrderBy(record => record.ResourceIdentifier.Database) + .ThenBy(record => record.ResourceIdentifier.Document) + .ToList(); + + foreach (Record record in combinedOrderedRecords) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); + if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) + { + records = new Records(); + this.partitionedRecords[partitionKeyHash] = records; + } + + records.Add(record); + } + + // Rehash the changes in the parent range + List combinedOrderedChanges = new List(); + foreach (List sourceChanges in new List[] { sourceChanges1, sourceChanges2 }) + { + combinedOrderedChanges.AddRange(sourceChanges); + } + + combinedOrderedChanges = combinedOrderedChanges + .OrderBy(change => change.PartitionKeyRangeId) + .ThenBy(change => change.LogicalSequenceNumber) + .ToList(); + + foreach (Change change in combinedOrderedChanges) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(change.Record.Payload, this.partitionKeyDefinition); + if (!this.partitionedChanges.TryGetValue(partitionKeyHash, out List changes)) + { + changes = new List(); + this.partitionedChanges[partitionKeyHash] = changes; + } + + changes.Add(change); + } + + return Task.FromResult(TryCatch.FromResult()); + } + + public IEnumerable PartitionKeyRangeIds => this.partitionKeyRangeIdToHashRange.Keys; + + private static PartitionKeyHash GetHashFromPayload( + CosmosObject payload, + PartitionKeyDefinition partitionKeyDefinition) + { + IList partitionKey = GetPartitionKeysFromPayload(payload, partitionKeyDefinition); + return GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); + } + + private static PartitionKeyHash GetHashFromObjectModel( + Cosmos.PartitionKey payload, + PartitionKeyDefinition partitionKeyDefinition) + { + IList partitionKeys = GetPartitionKeysFromObjectModel(payload); + return GetHashFromPartitionKeys(partitionKeys, partitionKeyDefinition); + } + + private static CosmosElement GetPartitionKeyFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) + { + // Restrict the partition key definition for now to keep things simple + if (partitionKeyDefinition.Kind != PartitionKind.Hash) + { + throw new ArgumentOutOfRangeException("Can only support hash partitioning"); + } + + if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) + { + throw new ArgumentOutOfRangeException("Can only support hash v2"); + } + + if (partitionKeyDefinition.Paths.Count != 1) + { + throw new ArgumentOutOfRangeException("Can only support a single partition key path."); + } + + IEnumerable tokens = partitionKeyDefinition.Paths[0].Split("/").Skip(1); + + CosmosElement partitionKey = payload; + foreach (string token in tokens) + { + if (partitionKey != default) + { + if (!payload.TryGetValue(token, out partitionKey)) + { + partitionKey = default; + } + } + } + + return partitionKey; + } + + private static IList GetPartitionKeysFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) + { + // Restrict the partition key definition for now to keep things simple + if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) + { + throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); + } + + if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) + { + throw new ArgumentOutOfRangeException("Can only support hash v2"); + } + + IList cosmosElements = new List(); + foreach (string partitionKeyPath in partitionKeyDefinition.Paths) + { + IEnumerable tokens = partitionKeyPath.Split("/").Skip(1); + CosmosElement partitionKey = payload; + foreach (string token in tokens) + { + if (partitionKey != default) + { + if (!payload.TryGetValue(token, out partitionKey)) + { + partitionKey = default; + } + } + } + cosmosElements.Add(partitionKey); + } + return cosmosElements; + } + + private static IList GetPartitionKeysFromObjectModel(Cosmos.PartitionKey payload) + { + CosmosArray partitionKeyPayload = CosmosArray.Parse(payload.ToJsonString()); + List cosmosElemementPayload = new List(); + foreach (CosmosElement element in partitionKeyPayload) + { + cosmosElemementPayload.Add(element); + } + return cosmosElemementPayload; + } + + private static PartitionKeyHash GetHashFromPartitionKeys(IList partitionKeys, PartitionKeyDefinition partitionKeyDefinition) + { + // Restrict the partition key definition for now to keep things simple + if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) + { + throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); + } + + if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) + { + throw new ArgumentOutOfRangeException("Can only support hash v2"); + } + + IList partitionKeyHashValues = new List(); + + foreach (CosmosElement partitionKey in partitionKeys) + { + if (partitionKey is CosmosArray cosmosArray) + { + foreach (CosmosElement element in cosmosArray) + { + PartitionKeyHash elementHash = element switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V2.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValues.Add(elementHash.HashValues[0]); + } + continue; + } + + PartitionKeyHash partitionKeyHash = partitionKey switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V2.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValues.Add(partitionKeyHash.HashValues[0]); + } + + return new PartitionKeyHash(partitionKeyHashValues.ToArray()); + } + + private static CosmosObject ConvertRecordToCosmosElement(Record record) + { + Dictionary keyValuePairs = new Dictionary + { + ["_rid"] = CosmosString.Create(record.ResourceIdentifier.ToString()), + ["_ts"] = CosmosNumber64.Create(record.Timestamp.Ticks), + ["id"] = CosmosString.Create(record.Identifier) + }; + + foreach (KeyValuePair property in record.Payload) + { + keyValuePairs[property.Key] = property.Value; + } + + return CosmosObject.Create(keyValuePairs); + } + + private static bool IsRecordWithinFeedRange( + Record record, + FeedRange feedRange, + PartitionKeyDefinition partitionKeyDefinition) + { + if (feedRange is FeedRangePartitionKey feedRangePartitionKey) + { + IList partitionKey = GetPartitionKeysFromObjectModel(feedRangePartitionKey.PartitionKey); + IList partitionKeyFromRecord = GetPartitionKeysFromPayload(record.Payload, partitionKeyDefinition); + if (partitionKeyDefinition.Kind == PartitionKind.MultiHash) + { + PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); + PartitionKeyHash partitionKeyFromRecordHash = GetHashFromPartitionKeys(partitionKeyFromRecord, partitionKeyDefinition); + + return partitionKeyHash.Equals(partitionKeyFromRecordHash) || partitionKeyFromRecordHash.Value.StartsWith(partitionKeyHash.Value); + } + return partitionKey.SequenceEqual(partitionKeyFromRecord); + } + else if (feedRange is FeedRangeEpk feedRangeEpk) + { + PartitionKeyHashRange hashRange = FeedRangeEpkToHashRange(feedRangeEpk); + PartitionKeyHash hash = GetHashFromPayload(record.Payload, partitionKeyDefinition); + return hashRange.Contains(hash); + } + else if (feedRange is FeedRangePartitionKeyRange) + { + return true; + } + else + { + throw new NotImplementedException(); + } + } + + private TryCatch MonadicGetPartitionKeyRangeIdFromFeedRange(FeedRange feedRange) + { + int partitionKeyRangeId; + if (feedRange is FeedRangeEpk feedRangeEpk) + { + // Check to see if any of the system ranges contain the user range. + List matchIds; + if (feedRangeEpk.Range.Min.Equals(FeedRangeEpk.FullRange.Range.Min) && feedRangeEpk.Range.Max.Equals(FeedRangeEpk.FullRange.Range.Max)) + { + matchIds = this.PartitionKeyRangeIds.ToList(); + } + else + { + PartitionKeyHashRange hashRange = FeedRangeEpkToHashRange(feedRangeEpk); + matchIds = this.partitionKeyRangeIdToHashRange + .Where(kvp => kvp.Value.Contains(hashRange)) + .Select(kvp => kvp.Key) + .ToList(); + } + + if (matchIds.Count != 1) + { + // Simulate a split exception, since we don't have a partition key range id to route to. + CosmosException goneException = new CosmosException( + message: $"Epk Range: {feedRangeEpk.Range} is gone.", + statusCode: System.Net.HttpStatusCode.Gone, + subStatusCode: (int)SubStatusCodes.PartitionKeyRangeGone, + activityId: Guid.NewGuid().ToString(), + requestCharge: default); + + return TryCatch.FromException(goneException); + } + + partitionKeyRangeId = matchIds[0]; + } + else if (feedRange is FeedRangePartitionKeyRange feedRangePartitionKeyRange) + { + partitionKeyRangeId = int.Parse(feedRangePartitionKeyRange.PartitionKeyRangeId); + } + else if (feedRange is FeedRangePartitionKey feedRangePartitionKey) + { + PartitionKeyHash partitionKeyHash = GetHashFromObjectModel(feedRangePartitionKey.PartitionKey, this.partitionKeyDefinition); + + int? foundValue = null; + foreach (KeyValuePair kvp in this.partitionKeyRangeIdToHashRange) + { + if (kvp.Value.Contains(partitionKeyHash)) + { + foundValue = kvp.Key; + } + } + + if (!foundValue.HasValue) + { + throw new InvalidOperationException("Failed to find value"); + } + + partitionKeyRangeId = foundValue.Value; + } + else + { + throw new NotImplementedException("Unknown feed range type"); + } + + return TryCatch.FromResult(partitionKeyRangeId); + } + + private static PartitionKeyHashRange FeedRangeEpkToHashRange(FeedRangeEpk feedRangeEpk) + { + PartitionKeyHash? start = feedRangeEpk.Range.Min == string.Empty ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Min); + PartitionKeyHash? end = feedRangeEpk.Range.Max == string.Empty || feedRangeEpk.Range.Max == "FF" ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Max); + PartitionKeyHashRange hashRange = new PartitionKeyHashRange(start, end); + return hashRange; + } + + private static FeedRangeEpk HashRangeToFeedRangeEpk(PartitionKeyHashRange hashRange) + { + return new FeedRangeEpk( + new Documents.Routing.Range( + min: hashRange.StartInclusive.HasValue ? hashRange.StartInclusive.ToString() : string.Empty, + max: hashRange.EndExclusive.HasValue ? hashRange.EndExclusive.ToString() : string.Empty, + isMinInclusive: true, + isMaxInclusive: false)); + } + + private PartitionKeyHash ComputeMedianSplitPointAmongDocumentsInPKRange(PartitionKeyHashRange hashRange) + { + if (!this.partitionedRecords.TryGetValue(hashRange, out Records parentRecords)) + { + throw new InvalidOperationException("failed to find the range."); + } + + List partitionKeyHashes = new List(); + foreach (Record record in parentRecords) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); + partitionKeyHashes.Add(partitionKeyHash); + } + + partitionKeyHashes.Sort(); + PartitionKeyHash medianPkHash = partitionKeyHashes[partitionKeyHashes.Count / 2]; + + // For MultiHash Collection, split at top level to ensure documents for top level key exist across partitions + // after split + if (medianPkHash.HashValues.Count > 1) + { + return new PartitionKeyHash(medianPkHash.HashValues[0]); + } + + return medianPkHash; + } + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult(TryCatch.FromResult("AYIMAMmFOw8YAAAAAAAAAA==")); + } + + private sealed class Records : IReadOnlyList + { + private readonly List storage; + + public Records() + { + this.storage = new List(); + } + + public Record this[int index] => this.storage[index]; + + public int Count => this.storage.Count; + + public IEnumerator GetEnumerator() => this.storage.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => this.storage.GetEnumerator(); + + public Record Add(int pkrangeid, CosmosObject payload) + { + // using pkrangeid for database since resource id doesnt serialize both document and pkrangeid. + ResourceId currentResourceId; + if (this.Count == 0) + { + currentResourceId = ResourceId.Parse("AYIMAMmFOw8YAAAAAAAAAA=="); + + PropertyInfo documentProp = currentResourceId + .GetType() + .GetProperty("Document", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + documentProp.SetValue(currentResourceId, (ulong)1); + + PropertyInfo databaseProp = currentResourceId + .GetType() + .GetProperty("Database", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + databaseProp.SetValue(currentResourceId, (uint)pkrangeid + 1); + } + else + { + currentResourceId = this.storage[this.storage.Count - 1].ResourceIdentifier; + } + + ResourceId nextResourceId = ResourceId.Parse("AYIMAMmFOw8YAAAAAAAAAA=="); + { + PropertyInfo documentProp = nextResourceId + .GetType() + .GetProperty("Document", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + documentProp.SetValue(nextResourceId, (ulong)(currentResourceId.Document + 1)); + + PropertyInfo databaseProp = nextResourceId + .GetType() + .GetProperty("Database", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + databaseProp.SetValue(nextResourceId, (uint)pkrangeid + 1); + } + + Record record = new Record(nextResourceId, DateTime.UtcNow, Guid.NewGuid().ToString(), payload); + this.storage.Add(record); + return record; + } + + public Record Add(Record record) + { + this.storage.Add(record); + return record; + } + } + + private readonly struct Change + { + public Change(Record record, ulong partitionKeyRangeId, ulong logicalSequenceNumber) + { + this.Record = record ?? throw new ArgumentNullException(nameof(record)); + this.PartitionKeyRangeId = partitionKeyRangeId; + this.LogicalSequenceNumber = logicalSequenceNumber; + } + + public Record Record { get; } + public ulong PartitionKeyRangeId { get; } + public ulong LogicalSequenceNumber { get; } + } + + private sealed class ChangeFeedPredicate : IChangeFeedStateVisitor + { + public static readonly ChangeFeedPredicate Singleton = new ChangeFeedPredicate(); + + private ChangeFeedPredicate() + { + } + + public bool Visit(ChangeFeedStateBeginning changeFeedStateBeginning, Change input) => true; + + public bool Visit(ChangeFeedStateTime changeFeedStateTime, Change input) => input.Record.Timestamp >= changeFeedStateTime.StartTime; + + public bool Visit(ChangeFeedStateContinuation changeFeedStateContinuation, Change input) + { + CosmosObject continuation = (CosmosObject)changeFeedStateContinuation.ContinuationToken; + + if (!continuation.TryGetValue("PkRangeId", out CosmosNumber pkRangeIdCosmosElement)) + { + throw new InvalidOperationException("failed to get pkrange id"); + } + + ulong pkRangeId = (ulong)Number64.ToLong(pkRangeIdCosmosElement.Value); + + if (!continuation.TryGetValue("LSN", out CosmosNumber lsnCosmosElement)) + { + throw new InvalidOperationException("failed to get lsn"); + } + + ulong lsn = (ulong)Number64.ToLong(lsnCosmosElement.Value); + + int pkRangeIdCompare = input.PartitionKeyRangeId.CompareTo(pkRangeId); + if (pkRangeIdCompare < 0) + { + return false; + } + else if (pkRangeIdCompare > 0) + { + return true; + } + else + { + return input.LogicalSequenceNumber > lsn; + } + } + + public bool Visit(ChangeFeedStateNow changeFeedStateNow, Change input) + { + DateTime now = DateTime.UtcNow; + ChangeFeedStateTime startTime = new ChangeFeedStateTime(now); + return this.Visit(startTime, input); + } + } + + private sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor + { + public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); + + private CosmosElementToSqlScalarExpressionVisitor() + { + // Private constructor, since this class is a singleton. + } + + public SqlScalarExpression Visit(CosmosArray cosmosArray) + { + List items = new List(); + foreach (CosmosElement item in cosmosArray) + { + items.Add(item.Accept(this)); + } + + return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosBinary cosmosBinary) + { + // Can not convert binary to scalar expression without knowing the API type. + throw new NotImplementedException(); + } + + public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) + { + return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); + } + + public SqlScalarExpression Visit(CosmosGuid cosmosGuid) + { + // Can not convert guid to scalar expression without knowing the API type. + throw new NotImplementedException(); + } + + public SqlScalarExpression Visit(CosmosNull cosmosNull) + { + return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); + } + + public SqlScalarExpression Visit(CosmosNumber cosmosNumber) + { + if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) + { + throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); + } + + return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); + } + + public SqlScalarExpression Visit(CosmosObject cosmosObject) + { + List properties = new List(); + foreach (KeyValuePair prop in cosmosObject) + { + SqlPropertyName name = SqlPropertyName.Create(prop.Key); + CosmosElement value = prop.Value; + SqlScalarExpression expression = value.Accept(this); + SqlObjectProperty property = SqlObjectProperty.Create(name, expression); + properties.Add(property); + } + + return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosString cosmosString) + { + return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); + } + + public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) + { + return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/SinglePartitionPartitionRangeEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/SinglePartitionPartitionRangeEnumeratorTests.cs index cf63ef8f10..8288148aab 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/SinglePartitionPartitionRangeEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/SinglePartitionPartitionRangeEnumeratorTests.cs @@ -80,9 +80,9 @@ public async Task TestSplitAsync() new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: new FeedRangeState(ranges[0], ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), - NoOpTrace.Singleton); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)), + NoOpTrace.Singleton, + cancellationToken: default); (HashSet parentIdentifiers, ReadFeedState state) = await this.PartialDrainAsync(enumerator, numIterations: 3); @@ -106,8 +106,7 @@ public async Task TestSplitAsync() (feedRangeState) => new ReadFeedPartitionRangeEnumerator( inMemoryCollection, feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton); HashSet resourceIdentifiers = await this.DrainFullyAsync(enumerable); @@ -134,8 +133,7 @@ protected override IAsyncEnumerable> CreateEnumerable( (feedRangeState) => new ReadFeedPartitionRangeEnumerator( documentContainer, feedRangeState: feedRangeState, - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default), + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton); } @@ -152,9 +150,9 @@ protected override Task>> CreateEnumerat feedRangeState: new FeedRangeState( new FeedRangePartitionKeyRange(partitionKeyRangeId: "0"), state ?? ReadFeedState.Beginning()), - readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: cancellationToken), - trace: NoOpTrace.Singleton); + readFeedPaginationOptions: new ReadFeedPaginationOptions(pageSizeHint: 10)), + trace: NoOpTrace.Singleton, + cancellationToken: default); return Task.FromResult(enumerator); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs index 3ca62e4057..4208dcee34 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/ContinuationTokens/OrderByQueryResultTests.cs @@ -33,7 +33,8 @@ public void TestOrderByUndefined() memoryStream, Documents.ResourceType.Document, out CosmosArray documents, - out CosmosObject distributionPlan); + out CosmosObject distributionPlan, + out bool? streaming); List orderByQueryResults = documents.Select(x => new OrderByQueryResult(x)).ToList(); Assert.AreEqual(14, orderByQueryResults.Count); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index bfbdda891c..7e697260f1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -169,9 +169,9 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: false); - IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); + IQueryPipelineStage queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); @@ -221,7 +221,7 @@ public async Task TestOdeTokenWithSpecializedPipeline() string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + "If the error persists after that, contact system administrator."; - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { if (queryPipelineStage.Current.Failed) { @@ -576,7 +576,7 @@ private async Task ValidateErrorMessageWithModifiedOdeFlags(OptimisticDirectExec } [TestMethod] - public async Task TestTextDistributionPlanParsingFromStream() + public void TestTextDistributionPlanParsingFromStream() { string textPath = "../../../Query/DistributionPlans/Text"; string[] filePaths = Directory.GetFiles(textPath); @@ -597,7 +597,8 @@ public async Task TestTextDistributionPlanParsingFromStream() memoryStream, Documents.ResourceType.Document, out CosmosArray documents, - out CosmosObject distributionPlan); + out CosmosObject distributionPlan, + out bool? ignored); if (distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan) && distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan)) @@ -613,7 +614,7 @@ public async Task TestTextDistributionPlanParsingFromStream() } [TestMethod] - public async Task TestBinaryDistributionPlanParsingFromStream() + public void TestBinaryDistributionPlanParsingFromStream() { string expectedBackendPlan = "{\"query\":\"\\nSELECT Count(r.a) AS count_a\\nFROM r\",\"obfuscatedQuery\":\"{\\\"query\\\":\\\"SELECT Count(r.a) AS p1\\\\nFROM r\\\",\\\"parameters\\\":[]}\",\"shape\":\"{\\\"Select\\\":{\\\"Type\\\":\\\"List\\\",\\\"AggCount\\\":1},\\\"From\\\":{\\\"Expr\\\":\\\"Aliased\\\"}}\",\"signature\":-4885972563975185329,\"shapeSignature\":-6171928203673877984,\"queryIL\":{\"Expression\":{\"Kind\":\"Aggregate\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Number\",\"ExcludesUndefined\":true}},\"Aggregate\":{\"Kind\":\"Builtin\",\"Signature\":{\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"ResultType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Number\",\"ExcludesUndefined\":true}},\"OperatorKind\":\"Count\"},\"SourceExpression\":{\"Kind\":\"Select\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false}},\"Delegate\":{\"Kind\":\"ScalarExpression\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"DeclaredVariable\":{\"Name\":\"v0\",\"UniqueId\":0,\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}},\"Expression\":{\"Kind\":\"PropertyRef\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":false},\"Expression\":{\"Kind\":\"VariableRef\",\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true},\"Variable\":{\"Name\":\"v0\",\"UniqueId\":0,\"Type\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}}},\"PropertyName\":\"a\"}},\"SourceExpression\":{\"Kind\":\"Input\",\"Type\":{\"Kind\":\"Enum\",\"ItemType\":{\"Kind\":\"Base\",\"BaseTypeKind\":\"Variant\",\"ExcludesUndefined\":true}},\"Name\":\"r\"}}}},\"noSpatial\":true,\"language\":\"QueryIL\"}"; string expectedClientPlan = "{\"clientQL\":{\"Kind\":\"Select\",\"DeclaredVariable\":{\"Name\":\"v0\",\"UniqueId\":2},\"Expression\":{\"Kind\":\"ObjectCreate\",\"ObjectKind\":\"Object\",\"Properties\":[{\"Name\":\"count_a\",\"Expression\":{\"Kind\":\"VariableRef\",\"Variable\":{\"Name\":\"v0\",\"UniqueId\":2}}}]},\"SourceExpression\":{\"Kind\":\"Aggregate\",\"Aggregate\":{\"Kind\":\"Builtin\",\"OperatorKind\":\"Sum\"},\"SourceExpression\":{\"Kind\":\"Input\",\"Name\":\"root\"}}}}"; @@ -627,7 +628,8 @@ public async Task TestBinaryDistributionPlanParsingFromStream() memoryStream, Documents.ResourceType.Document, out CosmosArray documents, - out CosmosObject distributionPlan); + out CosmosObject distributionPlan, + out bool? streaming); if (distributionPlan.TryGetValue("backendDistributionPlan", out CosmosElement backendDistributionPlan) && distributionPlan.TryGetValue("clientDistributionPlan", out CosmosElement clientDistributionPlan)) @@ -649,7 +651,7 @@ private static async Task ExecuteGoneExceptionOnODEPipeline(bool isMultiPa QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); (MergeTestUtil mergeTest, IQueryPipelineStage queryPipelineStage) = await CreateFallbackPipelineTestInfrastructure(numItems, isFailedFallbackPipelineTest: false, isMultiPartition, queryRequestOptions); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { if (mergeTest.MoveNextCounter == 1) { @@ -682,7 +684,7 @@ private static async Task TestHandlingOfFailedFallbackPipeline(bool isMult QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); (MergeTestUtil mergeTest, IQueryPipelineStage queryPipelineStage) = await CreateFallbackPipelineTestInfrastructure(numItems, isFailedFallbackPipelineTest: true, isMultiPartition, queryRequestOptions); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; if (tryGetPage.Failed) @@ -729,9 +731,9 @@ private static string RemoveWhitespace(string jsonString) failureConfigs: new FlakyDocumentContainer.FailureConfigs( inject429s: false, injectEmptyPages: false, - shouldReturnFailure: mergeTest.ShouldReturnFailure)); + shouldReturnFailure: () => Task.FromResult(mergeTest.ShouldReturnFailure()))); - IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); + IQueryPipelineStage queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions); return (mergeTest, queryPipelineStage); } @@ -742,9 +744,9 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn List documents = new List(); QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution); DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); - IQueryPipelineStage queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions, clientDisableOde); + IQueryPipelineStage queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions, clientDisableOde); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); @@ -775,7 +777,7 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn partitionKeyValue: input.PartitionKeyValue, continuationToken: tryGetPage.Result.State.Value); - queryPipelineStage = await GetOdePipelineAsync(input, inMemoryCollection, queryRequestOptions); + queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions); } continuationTokenCount++; @@ -803,7 +805,7 @@ internal static Tuple Get return Tuple.Create(partitionedQueryExecutionInfo, queryPartitionProvider); } - private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) + private static IQueryPipelineStage CreateOdePipeline(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) { (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, clientDisableOde); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( @@ -953,7 +955,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect inputParameters, NoOpTrace.Singleton); - bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton).AsTask().GetAwaiter().GetResult(); + bool result = queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default).AsTask().GetAwaiter().GetResult(); if (input.ExpectedOptimisticDirectExecution) { @@ -1077,16 +1079,16 @@ public override async Task> MonadicQueryAsync( queryPage.Result.Result.Documents, requestCharge: 42, activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: 1337, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: additionalHeaders.ToImmutable(), - state: queryPage.Result.Result.State))); + state: queryPage.Result.Result.State, + streaming: default))); } } - private class MergeTestUtil + private sealed class MergeTestUtil { public int MoveNextCounter { get; private set; } @@ -1101,7 +1103,7 @@ public MergeTestUtil(bool isFailedFallbackPipelineTest) this.IsFailedFallbackPipelineTest = isFailedFallbackPipelineTest; } - public async Task ShouldReturnFailure() + public Exception ShouldReturnFailure() { this.MoveNextCounter++; if (this.MoveNextCounter == 2 && !this.GoneExceptionCreated) @@ -1269,9 +1271,9 @@ public override Task GetCachedContainerQueryProperties Cosmos.GeospatialType.Geometry)); } - public override async Task GetClientDisableOptimisticDirectExecutionAsync() + public override Task GetClientDisableOptimisticDirectExecutionAsync() { - return this.queryPartitionProvider.ClientDisableOptimisticDirectExecution; + return Task.FromResult(this.queryPartitionProvider.ClientDisableOptimisticDirectExecution); } public override Task> GetTargetPartitionKeyRangeByFeedRangeAsync(string resourceLink, string collectionResourceId, PartitionKeyDefinition partitionKeyDefinition, FeedRangeInternal feedRangeInternal, bool forceRefresh, ITrace trace) @@ -1294,14 +1296,14 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { - CosmosSerializerCore serializerCore = new(); - using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + CosmosSerializerCore serializerCore = new CosmosSerializerCore(); + using StreamReader streamReader = new StreamReader(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); string sqlQuerySpecJsonString = streamReader.ReadToEnd(); (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, partitionKeyDefinition); - return TryCatch.FromResult(partitionedQueryExecutionInfo); + return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OrderByQueryPartitionRangePageAsyncEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OrderByQueryPartitionRangePageAsyncEnumeratorTests.cs index b08f01e317..5c96a8ff77 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OrderByQueryPartitionRangePageAsyncEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OrderByQueryPartitionRangePageAsyncEnumeratorTests.cs @@ -57,15 +57,16 @@ protected override Task>> CreateEnum Assert.AreEqual(1, ranges.Count); IAsyncEnumerator> enumerator = new TracingAsyncEnumerator>( - new OrderByQueryPartitionRangePageAsyncEnumerator( + OrderByQueryPartitionRangePageAsyncEnumerator.Create( queryDataSource: documentContainer, sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), feedRangeState: new FeedRangeState(ranges[0], state), partitionKey: null, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - filter: "filter", - cancellationToken: cancellationToken), - NoOpTrace.Singleton); + filter: "filter", + PrefetchPolicy.PrefetchSinglePage), + NoOpTrace.Singleton, + cancellationToken); return Task.FromResult(enumerator); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggregateQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggregateQueryPipelineStageTests.cs index 72e08e606f..61dba34d02 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggregateQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggregateQueryPipelineStageTests.cs @@ -111,8 +111,7 @@ private static async Task> CreateAndDrain( orderedAliases: orderedAliases, hasSelectValue: hasSelectValue, continuationToken: continuationToken, - cancellationToken: default, - monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken cancellationToken) => TryCatch.FromResult(source)); + monadicCreatePipelineStage: (CosmosElement continuationToken) => TryCatch.FromResult(source)); Assert.IsTrue(tryCreateAggregateQueryPipelineStage.Succeeded); IQueryPipelineStage aggregateQueryPipelineStage = tryCreateAggregateQueryPipelineStage.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs index 102e532477..2cc702b6bd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/AggressivePrefetchPipelineTests.cs @@ -242,12 +242,12 @@ public override async Task> MonadicQueryAsync( documents: documents, requestCharge: 3.0, activityId: "E7980B1F-436E-44DF-B7A5-655C56D38648", - responseLengthInBytes: 48, cosmosQueryExecutionInfo: new Lazy(() => new CosmosQueryExecutionInfo(false, false)), distributionPlanSpec: default, disallowContinuationTokenMessage: null, additionalHeaders: null, - state: continuationToken); + state: continuationToken, + streaming: default); return TryCatch.FromResult(page); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/CrossPartitionRangePageAsyncEnumerable.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/CrossPartitionRangePageAsyncEnumerable.cs index 7b96480a5f..1bc2c1ec28 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/CrossPartitionRangePageAsyncEnumerable.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/CrossPartitionRangePageAsyncEnumerable.cs @@ -53,9 +53,9 @@ public IAsyncEnumerator>> GetAsyncEnu this.comparer, this.maxConcurrency, this.prefetchPolicy, - cancellationToken, this.state), - this.trace); + this.trace, + cancellationToken); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DCountQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DCountQueryPipelineStageTests.cs index 89fce6f1e7..93dc5b9459 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DCountQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DCountQueryPipelineStageTests.cs @@ -200,7 +200,7 @@ private static async Task> CreateAndDrainWithStateAsync( distinctQueryType: distinctQueryType, dcountAlias: dcountAlias); - if(!await stage.MoveNextAsync(NoOpTrace.Singleton)) + if(!await stage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { break; } @@ -222,22 +222,20 @@ private static IQueryPipelineStage Create( DistinctQueryType distinctQueryType, string dcountAlias) { - MonadicCreatePipelineStage source = (CosmosElement continuationToken, CancellationToken cancellationToken) => + MonadicCreatePipelineStage source = (CosmosElement continuationToken) => TryCatch.FromResult(MockQueryPipelineStage.Create(pages, continuationToken)); - MonadicCreatePipelineStage createDistinctQueryPipelineStage = (CosmosElement continuationToken, CancellationToken cancellationToken) => + MonadicCreatePipelineStage createDistinctQueryPipelineStage = (CosmosElement continuationToken) => DistinctQueryPipelineStage.MonadicCreate( executionEnvironment: executionEnvironment, requestContinuation: continuationToken, distinctQueryType: distinctQueryType, - cancellationToken: cancellationToken, monadicCreatePipelineStage: source); TryCatch tryCreateDCountQueryPipelineStage = DCountQueryPipelineStage.MonadicCreate( executionEnvironment: executionEnvironment, continuationToken: requestContinuationToken, info: new DCountInfo { DCountAlias = dcountAlias }, - cancellationToken: default, monadicCreatePipelineStage: createDistinctQueryPipelineStage); Assert.IsTrue(tryCreateDCountQueryPipelineStage.Succeeded); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs index 9b9ade94c6..f71559e11e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/DistinctQueryPipelineStageTests.cs @@ -220,8 +220,7 @@ private static async Task> CreateAndDrainAsync( executionEnvironment: executionEnvironment, requestContinuation: continuationToken, distinctQueryType: distinctQueryType, - cancellationToken: default, - monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken cancellationToken) => TryCatch.FromResult(source)); + monadicCreatePipelineStage: (CosmosElement continuationToken) => TryCatch.FromResult(source)); Assert.IsTrue(tryCreateDistinctQueryPipelineStage.Succeeded); IQueryPipelineStage distinctQueryPipelineStage = tryCreateDistinctQueryPipelineStage.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/EnumerableStage.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/EnumerableStage.cs index 7d45f5ff38..8c6a4236e1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/EnumerableStage.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/EnumerableStage.cs @@ -28,7 +28,7 @@ public EnumerableStage(IQueryPipelineStage stage, ITrace trace) public IAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) { - return new TracingAsyncEnumerator>(this.stage, this.trace); + return new TracingAsyncEnumerator>(this.stage, this.trace, cancellationToken); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs index 21f87f2014..54e5b99899 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs @@ -31,7 +31,6 @@ public void TestCreate() queryInfo: new QueryInfo() { }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - requestCancellationToken: default, requestContinuationToken: default); ; Assert.IsTrue(monadicCreatePipeline.Succeeded); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index 97598ea59f..68b5b7d9cd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -66,7 +66,7 @@ public async Task TestMerge() List elements = new List(); int iteration = 0; - while (await pipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await pipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetQueryPage = pipelineStage.Current; tryGetQueryPage.ThrowIfFailed(); @@ -245,7 +245,7 @@ public async Task Tracing() int numTraces = (await documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, default)).Count; using (rootTrace = Trace.GetRootTrace("Cross Partition Query")) { - while (await pipelineStage.MoveNextAsync(rootTrace)) + while (await pipelineStage.MoveNextAsync(rootTrace, cancellationToken: default)) { TryCatch tryGetQueryPage = pipelineStage.Current; tryGetQueryPage.ThrowIfFailed(); @@ -308,7 +308,7 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp NoOpTrace.Singleton); List elements = new List(); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetQueryPage = queryPipelineStage.Current; tryGetQueryPage.ThrowIfFailed(); @@ -480,7 +480,7 @@ internal static async Task> DrainWithoutStateAsync(string qu IQueryPipelineStage pipelineStage = await CreatePipelineAsync(documentContainer, query, pageSize); List elements = new List(); - while (await pipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await pipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetQueryPage = pipelineStage.Current; tryGetQueryPage.ThrowIfFailed(); @@ -501,7 +501,7 @@ private static async Task> DrainWithStateAsync(string query, { pipelineStage = await CreatePipelineAsync(documentContainer, query, pageSize, state); - if (!await pipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + if (!await pipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { break; } @@ -591,7 +591,6 @@ private static async Task CreatePipelineAsync( GetQueryPlan(query), queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: pageSize), maxConcurrency: 10, - requestCancellationToken: default, requestContinuationToken: state); tryCreatePipeline.ThrowIfFailed(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs index c9197c48fd..da5a5a7648 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/GroupByQueryPipelineStageTests.cs @@ -58,8 +58,7 @@ private static async Task> CreateAndDrainAsync( TryCatch tryCreateGroupByStage = GroupByQueryPipelineStage.MonadicCreate( executionEnvironment: executionEnvironment, continuationToken: continuationToken, - cancellationToken: default, - monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken cancellationToken) => TryCatch.FromResult(source), + monadicCreatePipelineStage: (CosmosElement continuationToken) => TryCatch.FromResult(source), aggregates: new AggregateOperator[] { }, groupByAliasToAggregateType: groupByAliasToAggregateType, orderedAliases: orderedAliases, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs index 282b025031..389022f8af 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/MockQueryPipelineStage.cs @@ -13,7 +13,6 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Tests.Query.OfflineEngineTests; using Microsoft.Azure.Cosmos.Tracing; internal sealed class MockQueryPipelineStage : QueryPipelineStageBase @@ -23,7 +22,7 @@ internal sealed class MockQueryPipelineStage : QueryPipelineStageBase public long PageIndex { get; private set; } public MockQueryPipelineStage(IReadOnlyList> pages) - : base(EmptyQueryPipelineStage.Singleton, cancellationToken: default) + : base(EmptyQueryPipelineStage.Singleton) { this.pages = pages ?? throw new ArgumentNullException(nameof(pages)); } @@ -43,7 +42,7 @@ public static MockQueryPipelineStage Create( return stage; } - public override ValueTask MoveNextAsync(ITrace trace) + public override ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { if (this.PageIndex == this.pages.Count) { @@ -57,12 +56,12 @@ public override ValueTask MoveNextAsync(ITrace trace) documents: documents, requestCharge: default, activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: default, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: state); + state: state, + streaming: default); this.Current = TryCatch.FromResult(page); return new ValueTask(true); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs new file mode 100644 index 0000000000..daac63b9b1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs @@ -0,0 +1,1004 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline +{ + using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.OrderBy; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; + using Microsoft.Azure.Cosmos.Tests.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using System.Collections.Generic; + using System.Diagnostics; + using System.Threading.Tasks; + using System.Threading; + using System; + using System.Linq; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + + [TestClass] + public class NonStreamingOrderByQueryTests + { + private const int MaxConcurrency = 10; + + private const int DocumentCount = 420; + + private const int LeafPageCount = 100; + + private const int PageSize = 10; + + private const string ActivityId = "ActivityId"; + + private const int QueryCharge = 42; + + private const string CollectionRid = "1HNeAM-TiQY="; + + private const string RId = "_rid"; + + private const string OrderByItems = "orderByItems"; + + private const string Payload = "payload"; + + private const string Item = "item"; + + private const string Index = "index"; + + private const string IndexString = "indexString"; + + private static readonly int[] PageSizes = new [] { 1, 10, 100, DocumentCount }; + + [TestMethod] + public async Task InMemoryContainerParityTests() + { + IDocumentContainer documentContainer = await CreateDocumentContainerAsync(DocumentCount); + + IReadOnlyList idColumnAsc = new List + { + new OrderByColumn("c.id", SortOrder.Ascending) + }; + + IReadOnlyList idColumnDesc = new List + { + new OrderByColumn("c.id", SortOrder.Descending) + }; + + IReadOnlyList testCases = new List + { + MakeTest( + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.id}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.id", + orderByColumns: idColumnAsc, + validate: result => Validate.IndexIsInOrder(result, propertyName: "id", DocumentCount, reversed: false)), + MakeTest( + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.id}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.id DESC", + orderByColumns: idColumnDesc, + validate: result => Validate.IndexIsInOrder(result, propertyName: "id",DocumentCount, reversed: true)), + + // Empty result set + MakeTest( + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.id}] AS orderByItems, c AS payload + FROM c + WHERE c.doesNotExist = true AND {documentdb-formattableorderbyquery-filter} + ORDER BY c.id", + orderByColumns: idColumnAsc, + validate: result => result.Count == 0), + MakeTest( + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.id}] AS orderByItems, c AS payload + FROM c + WHERE c.doesNotExist = true AND {documentdb-formattableorderbyquery-filter} + ORDER BY c.id DESC", + orderByColumns: idColumnDesc, + validate: result => result.Count == 0), + }; + + await RunParityTests( + documentContainer, + new NonStreamingDocumentContainer(documentContainer), + await documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, default), + testCases); + } + + [TestMethod] + public async Task ShufflingContainerParityTests() + { + static bool IndexIsInOrder(IReadOnlyList result, bool reversed) + { + return Validate.IndexIsInOrder(result, propertyName: Index, LeafPageCount * PageSize, reversed); + } + + IReadOnlyList testCases = new List + { + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreaming, + documentCreationMode: DocumentCreationMode.SingleItem, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.index}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.index", + orderByColumns: new List + { + new OrderByColumn($"c.{Index}", SortOrder.Ascending) + }, + validate: result => IndexIsInOrder(result, reversed: false)), + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreamingReversed, + documentCreationMode: DocumentCreationMode.SingleItem, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.index}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.index DESC", + orderByColumns: new List + { + new OrderByColumn($"c.{Index}", SortOrder.Descending) + }, + validate: result => IndexIsInOrder(result, reversed: true)), + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreaming, + documentCreationMode: DocumentCreationMode.MultiItem, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.index}, {""item"": c.indexString}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.index, c.indexString", + orderByColumns: new List + { + new OrderByColumn($"c.{Index}", SortOrder.Ascending), + new OrderByColumn($"c.{IndexString}", SortOrder.Ascending) + }, + validate: result => IndexIsInOrder(result, reversed: false)), + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreamingReversed, + documentCreationMode: DocumentCreationMode.MultiItem, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.index}, {""item"": c.indexString}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.index DESC, c.indexString DESC", + orderByColumns: new List + { + new OrderByColumn($"c.{Index}", SortOrder.Descending), + new OrderByColumn($"c.{IndexString}", SortOrder.Descending) + }, + validate: result => IndexIsInOrder(result, reversed: true)), + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreaming, + documentCreationMode: DocumentCreationMode.MultiItemSwapped, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.indexString}, {""item"": c.index}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.indexString, c.index", + orderByColumns: new List + { + new OrderByColumn($"c.{IndexString}", SortOrder.Ascending), + new OrderByColumn($"c.{Index}", SortOrder.Ascending), + }, + validate: result => IndexIsInOrder(result, reversed: false)), + MakeParityTest( + feedMode: PartitionedFeedMode.NonStreamingReversed, + documentCreationMode: DocumentCreationMode.MultiItemSwapped, + queryText: @" + SELECT c._rid AS _rid, [{""item"": c.indexString}, {""item"": c.index}] AS orderByItems, c AS payload + FROM c + WHERE {documentdb-formattableorderbyquery-filter} + ORDER BY c.indexString DESC, c.index DESC", + orderByColumns: new List + { + new OrderByColumn($"c.{IndexString}", SortOrder.Descending), + new OrderByColumn($"c.{Index}", SortOrder.Descending), + }, + validate: result => IndexIsInOrder(result, reversed: true)), + }; + + await RunParityTests(testCases); + } + + private static async Task RunParityTests( + IDocumentContainer documentContainer, + IDocumentContainer nonStreamingDocumentContainer, + IReadOnlyList ranges, + IReadOnlyList testCases) + { + foreach (TestCase testCase in testCases) + { + foreach (int pageSize in testCase.PageSizes) + { + IReadOnlyList nonStreamingResult = await CreateAndRunPipelineStage( + documentContainer: nonStreamingDocumentContainer, + ranges: ranges, + queryText: testCase.QueryText, + orderByColumns: testCase.OrderByColumns, + pageSize: pageSize); + + IReadOnlyList streamingResult = await CreateAndRunPipelineStage( + documentContainer: documentContainer, + ranges: ranges, + queryText: testCase.QueryText, + orderByColumns: testCase.OrderByColumns, + pageSize: pageSize); + + if (!streamingResult.SequenceEqual(nonStreamingResult)) + { + Assert.Fail($"Results mismatch for query:\n{testCase.QueryText}\npageSize: {pageSize}"); + } + + if (!testCase.Validate(nonStreamingResult)) + { + Assert.Fail($"Could not validate result for query:\n{testCase.QueryText}\npageSize: {pageSize}"); + } + } + } + } + + private static async Task> CreateAndRunPipelineStage( + IDocumentContainer documentContainer, + IReadOnlyList ranges, + string queryText, + IReadOnlyList orderByColumns, + int pageSize) + { + TryCatch pipelineStage = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: new SqlQuerySpec(queryText), + targetRanges: ranges, + partitionKey: null, + orderByColumns: orderByColumns, + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: pageSize), + maxConcurrency: MaxConcurrency, + continuationToken: null); + + Assert.IsTrue(pipelineStage.Succeeded); + + IQueryPipelineStage stage = pipelineStage.Result; + List documents = new List(); + while (await stage.MoveNextAsync(NoOpTrace.Singleton, default)) + { + Assert.IsTrue(stage.Current.Succeeded); + Assert.IsTrue(stage.Current.Result.Documents.Count <= pageSize); + DebugTraceHelpers.TracePipelineStagePage(stage.Current.Result); + documents.AddRange(stage.Current.Result.Documents); + } + + return documents; + } + + private static async Task RunParityTests(IReadOnlyList testCases) + { + foreach (ParityTestCase testCase in testCases) + { + IReadOnlyList ranges = new List + { + new FeedRangeEpk(new Documents.Routing.Range(string.Empty, "AA", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("AA", "BB", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("BB", "CC", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("CC", "DD", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("DD", "EE", true, false)), + new FeedRangeEpk(new Documents.Routing.Range("EE", "FF", true, false)), + }; + + IDocumentContainer nonStreamingDocumentContainer = MockDocumentContainer.Create(ranges, testCase.FeedMode, testCase.DocumentCreationMode); + + IDocumentContainer streamingDocumentContainer = MockDocumentContainer.Create( + ranges, + testCase.FeedMode & PartitionedFeedMode.StreamingReversed, + testCase.DocumentCreationMode); + + foreach (int pageSize in testCase.PageSizes) + { + DebugTraceHelpers.TraceNonStreamingPipelineStarting(); + IReadOnlyList nonStreamingResult = await CreateAndRunPipelineStage( + documentContainer: nonStreamingDocumentContainer, + ranges: ranges, + queryText: testCase.QueryText, + orderByColumns: testCase.OrderByColumns, + pageSize: pageSize); + + DebugTraceHelpers.TraceStreamingPipelineStarting(); + IReadOnlyList streamingResult = await CreateAndRunPipelineStage( + documentContainer: streamingDocumentContainer, + ranges: ranges, + queryText: testCase.QueryText, + orderByColumns: testCase.OrderByColumns, + pageSize: pageSize); + + if (!streamingResult.SequenceEqual(nonStreamingResult)) + { + Assert.Fail($"Results mismatch for query:\n{testCase.QueryText}\npageSize: {pageSize}"); + } + } + } + } + + private static TestCase MakeTest(string queryText, IReadOnlyList orderByColumns, Func, bool> validate) + { + return MakeTest(queryText, orderByColumns, PageSizes, validate); + } + + private static TestCase MakeTest( + string queryText, + IReadOnlyList orderByColumns, + int[] pageSizes, + Func, bool> validate) + { + return new TestCase(queryText, orderByColumns, pageSizes, validate); + } + + private class TestCase + { + public string QueryText { get; } + + public IReadOnlyList OrderByColumns { get; } + + public int[] PageSizes { get; } + + public Func, bool> Validate { get; } + + public TestCase( + string queryText, + IReadOnlyList orderByColumns, + int[] pageSizes, + Func, bool> validate) + { + this.QueryText = queryText; + this.OrderByColumns = orderByColumns; + this.PageSizes = pageSizes; + this.Validate = validate; + } + } + + private static ParityTestCase MakeParityTest( + PartitionedFeedMode feedMode, + DocumentCreationMode documentCreationMode, + string queryText, + IReadOnlyList orderByColumns, + Func, bool> validate) + { + return MakeParityTest(feedMode, documentCreationMode, queryText, orderByColumns, PageSizes, validate); + } + + private static ParityTestCase MakeParityTest( + PartitionedFeedMode feedMode, + DocumentCreationMode documentCreationMode, + string queryText, + IReadOnlyList orderByColumns, + int[] pageSizes, + Func, bool> validate) + { + return new ParityTestCase(feedMode, documentCreationMode, queryText, orderByColumns, pageSizes, validate); + } + + private sealed class ParityTestCase : TestCase + { + public PartitionedFeedMode FeedMode { get; } + + public DocumentCreationMode DocumentCreationMode { get; } + + public ParityTestCase( + PartitionedFeedMode feedMode, + DocumentCreationMode documentCreationMode, + string queryText, + IReadOnlyList orderByColumns, + int[] pageSizes, + Func, bool> validate) + : base(queryText, orderByColumns, pageSizes, validate) + { + this.FeedMode = feedMode; + this.DocumentCreationMode = documentCreationMode; + } + } + + private static class Validate + { + public static bool IndexIsInOrder(IReadOnlyList documents, string propertyName, int count, bool reversed) + { + List expected = Enumerable + .Range(0, count) + .ToList(); + + if (reversed) + { + expected.Reverse(); + } + + IEnumerable actual = documents + .Cast() + .Select(x => x[propertyName]) + .Cast() + .Select(x => (int)Number64.ToLong(x.Value)); + + return expected.SequenceEqual(actual); + } + } + + private sealed class NonStreamingDocumentContainer : IDocumentContainer + { + private readonly IDocumentContainer inner; + + public NonStreamingDocumentContainer(IDocumentContainer inner) + { + this.inner = inner ?? throw new ArgumentNullException(nameof(inner)); + } + + public Task ChangeFeedAsync( + FeedRangeState feedRangeState, + ChangeFeedPaginationOptions changeFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.ChangeFeedAsync(feedRangeState, changeFeedPaginationOptions, trace, cancellationToken); + } + + public Task CreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + return this.inner.CreateItemAsync(payload, cancellationToken); + } + + public Task> GetChildRangeAsync( + FeedRangeInternal feedRange, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.GetChildRangeAsync(feedRange, trace, cancellationToken); + } + + public Task> GetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.GetFeedRangesAsync(trace, cancellationToken); + } + + public Task GetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.GetResourceIdentifierAsync(trace, cancellationToken); + } + + public Task MergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + return this.inner.MergeAsync(feedRange1, feedRange2, cancellationToken); + } + + public Task> MonadicChangeFeedAsync( + FeedRangeState feedRangeState, + ChangeFeedPaginationOptions changeFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.MonadicChangeFeedAsync(feedRangeState, changeFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicCreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + return this.inner.MonadicCreateItemAsync(payload, cancellationToken); + } + + public Task>> MonadicGetChildRangeAsync( + FeedRangeInternal feedRange, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.MonadicGetChildRangeAsync(feedRange, trace, cancellationToken); + } + + public Task>> MonadicGetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.MonadicGetFeedRangesAsync(trace, cancellationToken); + } + + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.MonadicGetResourceIdentifierAsync(trace, cancellationToken); + } + + public Task MonadicMergeAsync( + FeedRangeInternal feedRange1, + FeedRangeInternal feedRange2, + CancellationToken cancellationToken) + { + return this.inner.MonadicMergeAsync(feedRange1, feedRange2, cancellationToken); + } + + public async Task> MonadicQueryAsync( + SqlQuerySpec sqlQuerySpec, + FeedRangeState feedRangeState, + QueryPaginationOptions queryPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + TryCatch queryPage = await this.inner.MonadicQueryAsync(sqlQuerySpec, feedRangeState, queryPaginationOptions, trace, cancellationToken); + + if (queryPage.Failed) + { + return queryPage; + } + + QueryPage page = queryPage.Result; + DebugTraceHelpers.TraceBackendResponse(page); + + return TryCatch.FromResult(new QueryPage( + page.Documents, + page.RequestCharge, + page.ActivityId, + page.CosmosQueryExecutionInfo, + page.DistributionPlanSpec, + page.DisallowContinuationTokenMessage, + page.AdditionalHeaders, + page.State, + streaming: false)); + } + + public Task> MonadicReadFeedAsync( + FeedRangeState feedRangeState, + ReadFeedPaginationOptions readFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.MonadicReadFeedAsync(feedRangeState, readFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicReadItemAsync( + CosmosElement partitionKey, + string identifer, + CancellationToken cancellationToken) + { + return this.inner.MonadicReadItemAsync(partitionKey, identifer, cancellationToken); + } + + public Task MonadicRefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.MonadicRefreshProviderAsync(trace, cancellationToken); + } + + public Task MonadicSplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + return this.inner.MonadicSplitAsync(feedRange, cancellationToken); + } + + public async Task QueryAsync( + SqlQuerySpec sqlQuerySpec, + FeedRangeState feedRangeState, + QueryPaginationOptions queryPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + TryCatch queryPage = await this.MonadicQueryAsync( + sqlQuerySpec, + feedRangeState, + queryPaginationOptions, + trace, + cancellationToken); + queryPage.ThrowIfFailed(); + return queryPage.Result; + } + + public Task ReadFeedAsync( + FeedRangeState feedRangeState, + ReadFeedPaginationOptions readFeedPaginationOptions, + ITrace trace, + CancellationToken cancellationToken) + { + return this.inner.ReadFeedAsync(feedRangeState, readFeedPaginationOptions, trace, cancellationToken); + } + + public Task ReadItemAsync(CosmosElement partitionKey, string identifier, CancellationToken cancellationToken) + { + return this.inner.ReadItemAsync(partitionKey, identifier, cancellationToken); + } + + public Task RefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.inner.RefreshProviderAsync(trace, cancellationToken); + } + + public Task SplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + return this.inner.SplitAsync(feedRange, cancellationToken); + } + } + + private static class DebugTraceHelpers + { + private const bool Enabled = false; + + [Conditional("DEBUG")] + public static void TraceNonStreamingPipelineStarting() + { + if (Enabled) + { + System.Diagnostics.Trace.WriteLine("\nStarting non streaming pipeline\n"); + } + } + + [Conditional("DEBUG")] + public static void TraceStreamingPipelineStarting() + { + if (Enabled) + { + System.Diagnostics.Trace.WriteLine("\nStarting streaming pipeline\n"); + } + } + + [Conditional("DEBUG")] + public static void TracePipelineStagePage(QueryPage page) + { + if (Enabled) + { + System.Diagnostics.Trace.WriteLine("\nReceived next page from pipeline: "); + TracePage(page); + } + } + + [Conditional("DEBUG")] + public static void TraceBackendResponse(QueryPage page) + { + if (Enabled) + { + System.Diagnostics.Trace.WriteLine("Serving query from backend: "); + TracePage(page); + } + } + + [Conditional("DEBUG")] + public static void TracePage(QueryPage page) + { + if (Enabled) + { + System.Diagnostics.Trace.WriteLine("Page:"); + System.Diagnostics.Trace.WriteLine($" ActivityId: {page.ActivityId}"); + System.Diagnostics.Trace.WriteLine($" RequestCharge: {page.RequestCharge}"); + System.Diagnostics.Trace.WriteLine($" ActivityId: {page.ActivityId}"); + + System.Diagnostics.Trace.WriteLine($" AdditionalHeaders: "); + foreach (KeyValuePair header in page.AdditionalHeaders) + { + System.Diagnostics.Trace.WriteLine($" [{header.Key}] = {header.Value}"); + } + + System.Diagnostics.Trace.WriteLine($" Results:"); + foreach (CosmosElement result in page.Documents) + { + System.Diagnostics.Trace.WriteLine($" {result}"); + } + } + } + } + + private class MockDocumentContainer : IDocumentContainer + { + private readonly IReadOnlyDictionary>> pages; + + private readonly bool streaming; + + public static IDocumentContainer Create(IReadOnlyList feedRanges, PartitionedFeedMode feedMode, DocumentCreationMode documentCreationMode) + { + IReadOnlyDictionary>> pages = CreatePartitionedFeed( + feedRanges, + LeafPageCount, + PageSize, + feedMode, + (index) => CreateDocument(index, documentCreationMode)); + return new MockDocumentContainer(pages, !feedMode.HasFlag(PartitionedFeedMode.NonStreaming)); + } + + private MockDocumentContainer(IReadOnlyDictionary>> pages, bool streaming) + { + this.pages = pages ?? throw new ArgumentNullException(nameof(pages)); + this.streaming = streaming; + } + + public Task ChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task CreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> GetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> GetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult(this.pages.Keys.Cast().ToList()); + } + + public Task GetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicCreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task>> MonadicGetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task>> MonadicGetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult(TryCatch>.FromResult(this.pages.Keys.Cast().ToList())); + } + + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicMergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicQueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + IReadOnlyList> feedRangePages = this.pages[feedRangeState.FeedRange]; + int index = feedRangeState.State == null ? 0 : int.Parse(((CosmosString)feedRangeState.State.Value).Value); + IReadOnlyList documents = feedRangePages[index]; + + QueryState state = index < feedRangePages.Count - 1 ? new QueryState(CosmosString.Create((index + 1).ToString())) : null; + QueryPage queryPage = new QueryPage( + documents: documents, + requestCharge: QueryCharge, + activityId: ActivityId, + cosmosQueryExecutionInfo: null, + distributionPlanSpec: null, + disallowContinuationTokenMessage: null, + additionalHeaders: null, + state: state, + streaming: this.streaming); + + return Task.FromResult(TryCatch.FromResult(queryPage)); + } + + public Task> MonadicReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task> MonadicReadItemAsync(CosmosElement partitionKey, string identifer, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicRefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task MonadicSplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public async Task QueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + TryCatch queryPage = await this.MonadicQueryAsync(sqlQuerySpec, feedRangeState, queryPaginationOptions, trace, cancellationToken); + return queryPage.Result; + } + + public Task ReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task ReadItemAsync(CosmosElement partitionKey, string identifier, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task RefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task SplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + } + + [Flags] + enum PartitionedFeedMode + { + Streaming = 0, + NonStreaming = 1, + Reversed = 2, + + StreamingReversed = Streaming | Reversed, + NonStreamingReversed = NonStreaming | Reversed, + } + + private static IReadOnlyDictionary>> CreatePartitionedFeed( + IReadOnlyList feedRanges, + int leafPageCount, + int pageSize, + PartitionedFeedMode mode, + Func createDocument) + { + int feedRangeIndex = 0; + Dictionary>> pages = new Dictionary>>(); + foreach (FeedRangeEpk feedRange in feedRanges) + { + int index = feedRangeIndex; + List> leafPages = new List>(leafPageCount); + for (int pageIndex = 0; pageIndex < leafPageCount; ++pageIndex) + { + List documents = new List(pageSize); + for (int documentCount = 0; documentCount < pageSize; ++documentCount) + { + documents.Add(createDocument(index)); + index += feedRanges.Count; + } + + if (mode.HasFlag(PartitionedFeedMode.Reversed)) + { + documents.Reverse(); + } + + leafPages.Add(documents); + } + + if (mode.HasFlag(PartitionedFeedMode.NonStreaming)) + { + FischerYatesShuffle(leafPages); + } + + if (mode == PartitionedFeedMode.StreamingReversed) + { + leafPages.Reverse(); + } + + pages.Add(feedRange, leafPages); + ++feedRangeIndex; + } + + return pages; + } + + [Flags] + enum DocumentCreationMode + { + SingleItem = 0, + MultiItem = 1, + Swapped = 2, + + MultiItemSwapped = MultiItem | Swapped, + } + + private static CosmosElement CreateDocument(int index, DocumentCreationMode mode) + { + CosmosElement indexElement = CosmosNumber64.Create(index); + CosmosElement indexStringElement = CosmosString.Create(index.ToString("D4")); + + List orderByItems = new List + { + CosmosObject.Create(new Dictionary + { + [Item] = indexElement + }) + }; + + if (mode.HasFlag(DocumentCreationMode.MultiItem)) + { + orderByItems.Add(CosmosObject.Create(new Dictionary + { + [Item] = indexStringElement + })); + } + + if (mode.HasFlag(DocumentCreationMode.Swapped)) + { + orderByItems.Reverse(); + } + + Dictionary payload = new Dictionary + { + [Index] = indexElement + }; + + if (mode.HasFlag(DocumentCreationMode.MultiItem)) + { + payload.Add(IndexString, indexStringElement); + } + + Documents.ResourceId resourceId = Documents.ResourceId.NewCollectionChildResourceId( + CollectionRid, + (ulong)index, + Documents.ResourceType.Document); + + CosmosElement document = CosmosObject.Create(new Dictionary + { + [RId] = CosmosString.Create(resourceId.ToString()), + [OrderByItems] = CosmosArray.Create(orderByItems), + [Payload] = CosmosObject.Create(payload) + }); + + return document; + } + + private static void FischerYatesShuffle(IList list) + { + Random random = new Random(); + for (int index = list.Count - 1; index > 0; --index) + { + int other = random.Next(index + 1); + T temp = list[index]; + list[index] = list[other]; + list[other] = temp; + } + } + + private static async Task CreateDocumentContainerAsync(int documentCount) + { + Documents.PartitionKeyDefinition partitionKeyDefinition = new Documents.PartitionKeyDefinition() + { + Paths = new System.Collections.ObjectModel.Collection() + { + "/id" + }, + Kind = Documents.PartitionKind.Hash, + Version = Documents.PartitionKeyDefinitionVersion.V2, + }; + + IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(partitionKeyDefinition); + DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); + + for (int i = 0; i < 3; i++) + { + await documentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + foreach (FeedRangeInternal range in ranges) + { + await documentContainer.SplitAsync(range, cancellationToken: default); + } + } + + for (int i = 0; i < documentCount; i++) + { + // Insert an item + CosmosObject item = CosmosObject.Parse($"{{\"id\": {i}, \"repeated\": {i % 5} }}"); + TryCatch monadicCreateRecord = await documentContainer.MonadicCreateItemAsync(item, cancellationToken: default); + Assert.IsTrue(monadicCreateRecord.Succeeded); + } + + return documentContainer; + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs index af4ccc4eae..eebd3b1b83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs @@ -5,7 +5,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline { using System; - using System.Collections.Generic; + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; @@ -78,7 +78,6 @@ public void MonadicCreate_NullContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); } @@ -99,7 +98,6 @@ public void MonadicCreate_NonCosmosArrayContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosObject.Create(new Dictionary())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -121,7 +119,6 @@ public void MonadicCreate_EmptyArrayContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create(new List())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -143,7 +140,6 @@ public void MonadicCreate_NonParallelContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create(new List() { CosmosString.Create("asdf") })); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -180,7 +176,6 @@ public void MonadicCreate_SingleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -225,7 +220,6 @@ public void MonadicCreate_SingleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -285,7 +279,6 @@ public void MonadicCreate_MultipleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -328,7 +321,6 @@ public void MonadicCreate_OrderByWithResumeValues() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -370,7 +362,6 @@ public void MonadicCreate_OrderByWithResumeValues() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -388,12 +379,12 @@ public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsy documents: new List(), requestCharge: 0, activityId: string.Empty, - responseLengthInBytes: 0, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: default); + state: default, + streaming: default); string expectedQuerySpec = "SELECT * FROM c WHERE true ORDER BY c._ts"; Mock mockContainer = new Mock(MockBehavior.Strict); @@ -426,17 +417,16 @@ public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsy }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 1), maxConcurrency: 0, - cancellationToken: default, continuationToken: CosmosElement.Parse(continuationToken)); Assert.IsTrue(monadicCreate.Succeeded); IQueryPipelineStage queryPipelineStage = monadicCreate.Result; for (int i = 0; i < targetRanges.Count; ++i) { - Assert.IsTrue(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)); + Assert.IsTrue(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); } - Assert.IsFalse(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)); + Assert.IsFalse(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); } [TestMethod] @@ -462,13 +452,12 @@ FROM c }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); IQueryPipelineStage queryPipelineStage = monadicCreate.Result; List documents = new List(); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetQueryPage = queryPipelineStage.Current; if (tryGetQueryPage.Failed) @@ -479,7 +468,11 @@ FROM c QueryPage queryPage = tryGetQueryPage.Result; documents.AddRange(queryPage.Documents); - Assert.AreEqual(42, queryPage.RequestCharge); + if (queryPage.RequestCharge > 0) + { + // some empty pages may be emitted + Assert.AreEqual(42, queryPage.RequestCharge); + } } Assert.AreEqual(numItems, documents.Count); @@ -508,12 +501,12 @@ FROM c }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); IQueryPipelineStage queryPipelineStage = monadicCreate.Result; - - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + + int countAdditionalHeadersReceived = 0; + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetQueryPage = queryPipelineStage.Current; if (tryGetQueryPage.Failed) @@ -521,11 +514,20 @@ FROM c Assert.Fail(tryGetQueryPage.Exception.ToString()); } - QueryPage queryPage = tryGetQueryPage.Result; - Assert.IsTrue(queryPage.AdditionalHeaders.Count > 0); - } - } - + QueryPage queryPage = tryGetQueryPage.Result; + if (queryPage.AdditionalHeaders.Count > 0) + { + ++countAdditionalHeadersReceived; + } + } + + int countFeedRanges = (await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default)) + .Count; + Assert.IsTrue(countAdditionalHeadersReceived >= countFeedRanges); + } + [TestMethod] [DataRow(false, false, false, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: false")] [DataRow(false, false, true, DisplayName = "Use State: false, Allow Splits: false, Allow Merges: true")] @@ -556,7 +558,6 @@ FROM c }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, - cancellationToken: default, continuationToken: continuationToken); monadicQueryPipelineStage.ThrowIfFailed(); IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; @@ -569,7 +570,7 @@ FROM c IQueryPipelineStage queryPipelineStage = await CreatePipelineStateAsync(inMemoryCollection, continuationToken: null); List documents = new List(); Random random = new Random(); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); @@ -584,7 +585,7 @@ FROM c { // We need to drain out all the initial empty pages, // since they are non resumable state. - Assert.IsTrue(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)); + Assert.IsTrue(await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); TryCatch tryGetQueryPage = queryPipelineStage.Current; if (tryGetQueryPage.Failed) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs index e772996748..e4e06635b3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs @@ -38,7 +38,6 @@ public void MonadicCreate_NullContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); } @@ -56,7 +55,6 @@ public void MonadicCreate_NonCosmosArrayContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: CosmosObject.Create(new Dictionary())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -75,7 +73,6 @@ public void MonadicCreate_EmptyArrayContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: CosmosArray.Create(new List())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -94,7 +91,6 @@ public void MonadicCreate_NonParallelContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: CosmosArray.Create(new List() { CosmosString.Create("asdf") })); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -117,7 +113,6 @@ public void MonadicCreate_SingleParallelContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: CosmosArray.Create(new List() { ParallelContinuationToken.ToCosmosElement(token) })); Assert.IsTrue(monadicCreate.Succeeded); } @@ -147,7 +142,6 @@ public void MonadicCreate_MultipleParallelContinuationToken() partitionKey: null, maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: CosmosArray.Create( new List() { @@ -188,7 +182,6 @@ async Task CreatePipelineStateAsync(IDocumentContainer docu partitionKey: null, maxConcurrency: 10, prefetchPolicy: aggressivePrefetch ? PrefetchPolicy.PrefetchAll : PrefetchPolicy.PrefetchSinglePage, - cancellationToken: default, continuationToken: continuationToken); Assert.IsTrue(monadicQueryPipelineStage.Succeeded); IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; @@ -201,7 +194,7 @@ async Task CreatePipelineStateAsync(IDocumentContainer docu IQueryPipelineStage queryPipelineStage = await CreatePipelineStateAsync(inMemoryCollection, continuationToken: null); List documents = new List(); Random random = new Random(); - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; tryGetPage.ThrowIfFailed(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/PartitionRangePageAsyncEnumerable.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/PartitionRangePageAsyncEnumerable.cs index eb8981a65e..12a6ca9a1e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/PartitionRangePageAsyncEnumerable.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/PartitionRangePageAsyncEnumerable.cs @@ -34,7 +34,7 @@ public IAsyncEnumerator> GetAsyncEnumerator(CancellationToken ca { cancellationToken.ThrowIfCancellationRequested(); - return new TracingAsyncEnumerator>(this.createPartitionRangeEnumerator(this.feedRangeState), this.trace); + return new TracingAsyncEnumerator>(this.createPartitionRangeEnumerator(this.feedRangeState), this.trace, cancellationToken); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs index 1b88966a8c..c498ade871 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipEmptyPageQueryPipelineStageTests.cs @@ -26,7 +26,7 @@ public async Task StackOverflowTest() .Repeat(EmptyPagePipelineStage.PageType.Empty, 2000) .Concat(Enumerable.Repeat(EmptyPagePipelineStage.PageType.Error, 1)) .ToList()); - bool hasNext = await pipeline.MoveNextAsync(NoOpTrace.Singleton); + bool hasNext = await pipeline.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default); Assert.IsTrue(hasNext); TryCatch result = pipeline.Current; Assert.IsFalse(result.Succeeded); @@ -75,7 +75,7 @@ public async Task BasicTests() await using IQueryPipelineStage pipeline = CreatePipeline(testCase.Input); for (int index = 0; index < testCase.Expected.Count; ++index) { - Assert.IsTrue(await pipeline.MoveNextAsync(NoOpTrace.Singleton)); + Assert.IsTrue(await pipeline.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)); if (testCase.Expected[index]) { @@ -112,11 +112,8 @@ public TestCase(IReadOnlyList input, IReadOnlyL private static IQueryPipelineStage CreatePipeline(IReadOnlyList pages) { EmptyPagePipelineStage emptyPagePipelineStage = new EmptyPagePipelineStage(pages); - SkipEmptyPageQueryPipelineStage skipEmptyPageStage = new SkipEmptyPageQueryPipelineStage( - inputStage: emptyPagePipelineStage, - cancellationToken: default); - - return new CatchAllQueryPipelineStage(inputStage: skipEmptyPageStage, cancellationToken: default); + SkipEmptyPageQueryPipelineStage skipEmptyPageStage = new SkipEmptyPageQueryPipelineStage(emptyPagePipelineStage); + return new CatchAllQueryPipelineStage(skipEmptyPageStage); } internal class EmptyPagePipelineStage : IQueryPipelineStage @@ -127,23 +124,23 @@ public enum PageType { Empty, NonEmpty, Error }; documents: new List(), requestCharge: 42, activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: "[]".Length, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: new QueryState(CosmosString.Create("Empty")))); + state: new QueryState(CosmosString.Create("Empty")), + streaming: default)); private static readonly TryCatch NonEmpty = TryCatch.FromResult(new QueryPage( documents: new List { CosmosElement.Parse("42") }, requestCharge: 100, activityId: Guid.NewGuid().ToString(), - responseLengthInBytes: "[42]".Length, cosmosQueryExecutionInfo: default, distributionPlanSpec: default, disallowContinuationTokenMessage: default, additionalHeaders: default, - state: new QueryState(CosmosString.Create("NonEmpty")))); + state: new QueryState(CosmosString.Create("NonEmpty")), + streaming: default)); private readonly IReadOnlyList pages; @@ -162,7 +159,7 @@ public ValueTask DisposeAsync() return new ValueTask(); } - public ValueTask MoveNextAsync(ITrace trace) + public ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) { ++this.current; if (this.current >= this.pages.Count) @@ -189,10 +186,6 @@ public ValueTask MoveNextAsync(ITrace trace) return new ValueTask(true); } - - public void SetCancellationToken(CancellationToken cancellationToken) - { - } } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipQueryPipelineStageTests.cs index d2749f9f9d..c134d4b72d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/SkipQueryPipelineStageTests.cs @@ -52,8 +52,7 @@ private static async Task> CreateAndDrainAsync( executionEnvironment: executionEnvironment, offsetCount: offsetCount, continuationToken: continuationToken, - cancellationToken: default, - monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken token) => TryCatch.FromResult(source)); + monadicCreatePipelineStage: (CosmosElement continuationToken) => TryCatch.FromResult(source)); Assert.IsTrue(tryCreateSkipQueryPipelineStage.Succeeded); IQueryPipelineStage aggregateQueryPipelineStage = tryCreateSkipQueryPipelineStage.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TakeQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TakeQueryPipelineStageTests.cs index 36b2c189c9..c86e2c7905 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TakeQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/TakeQueryPipelineStageTests.cs @@ -92,8 +92,7 @@ public async Task BasicTests() executionEnvironment: executionEnvironment, limitCount: takeCount, requestContinuationToken: continuationToken, - cancellationToken: default, - monadicCreatePipelineStage: (CosmosElement continuationToken, CancellationToken cancellationToken) => TryCatch.FromResult(source)); + monadicCreatePipelineStage: (CosmosElement continuationToken) => TryCatch.FromResult(source)); Assert.IsTrue(tryCreateSkipQueryPipelineStage.Succeeded); IQueryPipelineStage takeQueryPipelineStage = tryCreateSkipQueryPipelineStage.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs index 4672fb17f5..2bb6813ff6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs @@ -100,8 +100,7 @@ public async Task TestSplitAsync() sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), feedRangeState: feedRangeState, partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - cancellationToken: default), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton); HashSet resourceIdentifiers = await this.DrainFullyAsync(enumerable); @@ -143,8 +142,7 @@ protected override IAsyncEnumerable> CreateEnumerable( sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), feedRangeState: feedRangeState, partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - cancellationToken: default), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton); } @@ -166,9 +164,9 @@ protected override Task>> CreateEnumeratorA sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), feedRangeState: new FeedRangeState(ranges[0], state), partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - cancellationToken: cancellationToken), - trace: NoOpTrace.Singleton); + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), + trace: NoOpTrace.Singleton, + cancellationToken: cancellationToken); return Task.FromResult(enumerator); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Scenarios/GremlinScenarioTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Scenarios/GremlinScenarioTests.cs index 093944190e..1a894d7f1b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Scenarios/GremlinScenarioTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Scenarios/GremlinScenarioTests.cs @@ -644,7 +644,6 @@ internal void GetCosmosElementsFromQueryResponseTest(JsonSerializationFormat jso QueryResponse queryResponse = QueryResponse.CreateSuccess( vertexArray, count: 2, - responseLengthBytes: vertex1JsonWriterResult.Length + vertex2JsonWriterResult.Length, serializationOptions: null, trace: NoOpTrace.Singleton, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders( @@ -726,7 +725,6 @@ internal void GetDeserializedObjectsFromQueryResponseTest(JsonSerializationForma QueryResponse queryResponse = QueryResponse.CreateSuccess( vertexArray, count: 2, - responseLengthBytes: vertex1JsonWriterResult.Length + vertex2JsonWriterResult.Length, serializationOptions: null, trace: NoOpTrace.Singleton, responseHeaders: CosmosQueryResponseMessageHeaders.ConvertToQueryHeaders( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/TestHandler.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/TestHandler.cs index 2d947912e2..199fb3c88f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/TestHandler.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/TestHandler.cs @@ -38,8 +38,11 @@ public static Task ReturnSuccess() { ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK) { - Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Documents"": [{ ""id"": ""Test""}]}")) - }; + Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""_count"": 1, ""Documents"": [{ ""id"": ""Test""}]}")) + }; + + responseMessage.Headers.Add(HttpConstants.HttpHeaders.ItemCount, "1"); + return responseMessage; }); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index 2d69341182..aa2e145850 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -526,14 +526,13 @@ public async Task ScenariosAsync() CrossPartitionReadFeedAsyncEnumerator enumerator = CrossPartitionReadFeedAsyncEnumerator.Create( documentContainer, new CrossFeedRangeState(ReadFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), - new ReadFeedPaginationOptions(pageSizeHint: 10), - cancellationToken: default); + new ReadFeedPaginationOptions(pageSizeHint: 10)); int numChildren = 1; // One extra since we need to read one past the last user page to get the null continuation. TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - while (await enumerator.MoveNextAsync(rootTrace)) + while (await enumerator.MoveNextAsync(rootTrace, cancellationToken: default)) { numChildren++; } @@ -559,14 +558,13 @@ public async Task ScenariosAsync() ChangeFeedCrossFeedRangeState.CreateFromBeginning().FeedRangeStates), new ChangeFeedPaginationOptions( ChangeFeedMode.Incremental, - pageSizeHint: int.MaxValue), - cancellationToken: default); + pageSizeHint: int.MaxValue)); int numChildren = 0; TraceForBaselineTesting rootTrace; using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - while (await enumerator.MoveNextAsync(rootTrace)) + while (await enumerator.MoveNextAsync(rootTrace, cancellationToken: default)) { numChildren++; @@ -597,7 +595,7 @@ public async Task ScenariosAsync() int numChildren = (await documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, default)).Count; // One extra since we need to read one past the last user page to get the null continuation. using (rootTrace = TraceForBaselineTesting.GetRootTrace()) { - while (await pipelineStage.MoveNextAsync(rootTrace)) + while (await pipelineStage.MoveNextAsync(rootTrace, cancellationToken: default)) { numChildren++; } @@ -759,7 +757,6 @@ private static IQueryPipelineStage CreatePipeline(IDocumentContainer documentCon GetQueryPlan(query), new QueryPaginationOptions(pageSizeHint: pageSize), maxConcurrency: 10, - requestCancellationToken: default, requestContinuationToken: state); tryCreatePipeline.ThrowIfFailed(); From 15d83a7d08f2f70d98653355e0d219e1a878b475 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Mon, 1 Apr 2024 12:18:15 -0700 Subject: [PATCH 302/337] Query: Adds translation support for single key single value select GROUP BY LINQ queries (#4074) * preliminary change * Add some more boiler plate code * move all linq test to the same folder; add some groupBy test * fix references error in test refactoring add code for group by substitution. Still need to adjust binding post groupby * preliminary for the groupby functions with key and value selector * trying to change collection inputs for group by * WIP bookmark * Successfully ignore "key" * clean up code * Sucessfully bind the case of group by with only key selector and no value selector followed by an optional select clause * enable one group by test * add support for aggregate value selector * added baseline * working on adding support for multivalue value selector and key selector * code clean up * more clean up * more clean up * update test * Move test to separate file * code clean up * remove baseline file that got moved * fix merge issue * Changes test infrastructure to reflect changes from Master * address code review part 1 * Address code review 2 and adds code coverage * Addressed code review and added tests. Still a couple of bugs to iron out * Fix group by translation issue and add more test * update comments * address pr comment --------- Co-authored-by: Minh Le Co-authored-by: Aditya --- .../src/Linq/ExpressionToSQL.cs | 157 +- .../src/Linq/QueryUnderConstruction.cs | 143 +- .../src/Linq/TranslationContext.cs | 35 +- Microsoft.Azure.Cosmos/src/Linq/Utilities.cs | 7 +- .../Visitors/SqlObjectTextSerializer.cs | 1 + ...alBaselineTests.TestGroupByTranslation.xml | 449 +++++ .../Linq/LinqGeneralBaselineTests.cs | 149 ++ .../Linq/LinqTestsCommon.cs | 1776 ++++++++--------- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 3 + ...upByClauseSqlParserBaselineTests.Tests.xml | 6 +- ...lObjectVisitorBaselineTests.SqlQueries.xml | 28 +- 11 files changed, 1789 insertions(+), 965 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index 62b9132a8e..5dac768dce 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -8,12 +8,15 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; + using System.Data.Common; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Linq.Expressions; using System.Reflection; + using System.Text.RegularExpressions; using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Serialization.HybridRow; using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.Spatial; using Microsoft.Azure.Cosmos.SqlObjects; @@ -64,6 +67,7 @@ public static class LinqMethods public const string FirstOrDefault = "FirstOrDefault"; public const string Max = "Max"; public const string Min = "Min"; + public const string GroupBy = "GroupBy"; public const string OrderBy = "OrderBy"; public const string OrderByDescending = "OrderByDescending"; public const string Select = "Select"; @@ -109,7 +113,7 @@ public static SqlQuery TranslateQuery( /// /// Translate an expression into a query. - /// Query is constructed as a side-effect in context.currentQuery. + /// Query is constructed as a side-effect in context.CurrentQuery. /// /// Expression to translate. /// Context for translation. @@ -805,8 +809,8 @@ private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpre if (usePropertyRef) { - SqlIdentifier propertyIdnetifier = SqlIdentifier.Create(memberName); - SqlPropertyRefScalarExpression propertyRefExpression = SqlPropertyRefScalarExpression.Create(memberExpression, propertyIdnetifier); + SqlIdentifier propertyIdentifier = SqlIdentifier.Create(memberName); + SqlPropertyRefScalarExpression propertyRefExpression = SqlPropertyRefScalarExpression.Create(memberExpression, propertyIdentifier); return propertyRefExpression; } else @@ -997,7 +1001,7 @@ private static Collection ConvertToScalarAnyCollection(TranslationContext contex SqlQuery query = context.CurrentQuery.FlattenAsPossible().GetSqlQuery(); SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); - ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + ParameterExpression parameterExpression = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); Binding binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); context.CurrentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); @@ -1111,7 +1115,7 @@ private static Collection VisitMemberAccessCollectionExpression(Expression input Collection collection = ExpressionToSql.ConvertToCollection(body); context.PushCollection(collection); - ParameterExpression parameter = context.GenFreshParameter(type, parameterName); + ParameterExpression parameter = context.GenerateFreshParameter(type, parameterName); context.PushParameter(parameter, context.CurrentSubqueryBinding.ShouldBeOnNewQuery); context.PopParameter(); context.PopCollection(); @@ -1120,7 +1124,7 @@ private static Collection VisitMemberAccessCollectionExpression(Expression input } /// - /// Visit a method call, construct the corresponding query in context.currentQuery. + /// Visit a method call, construct the corresponding query in context.CurrentQuery. /// At ExpressionToSql point only LINQ method calls are allowed. /// These methods are static extension methods of IQueryable or IEnumerable. /// @@ -1149,11 +1153,18 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, Type inputElementType = TypeSystem.GetElementType(inputCollection.Type); Collection collection = ExpressionToSql.Translate(inputCollection, context); + context.PushCollection(collection); Collection result = new Collection(inputExpression.Method.Name); bool shouldBeOnNewQuery = context.CurrentQuery.ShouldBeOnNewQuery(inputExpression.Method.Name, inputExpression.Arguments.Count); context.PushSubqueryBinding(shouldBeOnNewQuery); + + if (context.LastExpressionIsGroupBy) + { + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, "Group By cannot be followed by other methods")); + } + switch (inputExpression.Method.Name) { case LinqMethods.Any: @@ -1219,6 +1230,13 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } + case LinqMethods.GroupBy: + { + context.CurrentQuery = context.PackageCurrentQueryIfNeccessary(); + result = ExpressionToSql.VisitGroupBy(returnElementType, inputExpression.Arguments, context); + context.LastExpressionIsGroupBy = true; + break; + } case LinqMethods.OrderBy: { SqlOrderByClause orderBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); @@ -1376,6 +1394,7 @@ private static bool IsSubqueryScalarExpression(Expression expression, out Subque case LinqMethods.Skip: case LinqMethods.Take: case LinqMethods.Distinct: + case LinqMethods.GroupBy: isSubqueryExpression = true; expressionObjKind = SubqueryKind.ArrayScalarExpression; break; @@ -1405,7 +1424,7 @@ private static SqlScalarExpression VisitScalarExpression(LambdaExpression lambda } /// - /// Visit an lambda expression which is in side a lambda and translate it to a scalar expression or a collection scalar expression. + /// Visit an lambda expression which is inside a lambda and translate it to a scalar expression or a collection scalar expression. /// If it is a collection scalar expression, e.g. should be translated to subquery such as SELECT VALUE ARRAY, SELECT VALUE EXISTS, /// SELECT VALUE [aggregate], the subquery will be aliased to a new binding for the FROM clause. E.g. consider /// Select(family => family.Children.Select(child => child.Grade)). Since the inner Select corresponds to a subquery, this method would @@ -1508,7 +1527,7 @@ private static SqlScalarExpression VisitScalarExpression(Expression expression, { SqlQuery query = ExpressionToSql.CreateSubquery(expression, parameters, context); - ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + ParameterExpression parameterExpression = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); SqlCollection subqueryCollection = ExpressionToSql.CreateSubquerySqlCollection( query, isMinMaxAvgMethod ? SubqueryKind.ArrayScalarExpression : expressionObjKind.Value); @@ -1585,7 +1604,7 @@ private static SqlQuery CreateSubquery(Expression expression, ReadOnlyCollection QueryUnderConstruction queryBeforeVisit = context.CurrentQuery; QueryUnderConstruction packagedQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc(), context.CurrentQuery); - packagedQuery.fromParameters.SetInputParameter(typeof(object), context.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); + packagedQuery.FromParameters.SetInputParameter(typeof(object), context.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); context.CurrentQuery = packagedQuery; if (shouldBeOnNewQuery) context.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; @@ -1663,9 +1682,108 @@ private static Collection VisitSelectMany(ReadOnlyCollection argumen Binding binding; SqlQuery query = ExpressionToSql.CreateSubquery(lambda.Body, lambda.Parameters, context); SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); - ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + ParameterExpression parameterExpression = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); - context.CurrentQuery.fromParameters.Add(binding); + context.CurrentQuery.FromParameters.Add(binding); + } + + return collection; + } + + private static Collection VisitGroupBy(Type returnElementType, ReadOnlyCollection arguments, TranslationContext context) + { + if (arguments.Count != 3) + { + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.InvalidArgumentsCount, LinqMethods.GroupBy, 3, arguments.Count)); + } + + // bind the parameters in the value selector to the current input + foreach (ParameterExpression par in Utilities.GetLambda(arguments[2]).Parameters) + { + context.PushParameter(par, context.CurrentSubqueryBinding.ShouldBeOnNewQuery); + } + + // First argument is input, second is key selector and third is value selector + LambdaExpression keySelectorLambda = Utilities.GetLambda(arguments[1]); + + // Current GroupBy doesn't allow subquery, so we need to visit non subquery scalar lambda + SqlScalarExpression keySelectorFunc = ExpressionToSql.VisitNonSubqueryScalarLambda(keySelectorLambda, context); + + SqlGroupByClause groupby = SqlGroupByClause.Create(keySelectorFunc); + + context.CurrentQuery = context.CurrentQuery.AddGroupByClause(groupby, context); + + // Create a GroupBy collection and bind the new GroupBy collection to the new parameters created from the key + Collection collection = ExpressionToSql.ConvertToCollection(keySelectorFunc); + collection.isOuter = true; + collection.Name = "GroupBy"; + + ParameterExpression parameterExpression = context.GenerateFreshParameter(returnElementType, keySelectorFunc.ToString(), includeSuffix: false); + Binding binding = new Binding(parameterExpression, collection.inner, isInCollection: false, isInputParameter: true); + + context.CurrentQuery.GroupByParameter = new FromParameterBindings(); + context.CurrentQuery.GroupByParameter.Add(binding); + + // The alias for the key in the value selector lambda is the first arguemt lambda - we bound it to the parameter expression, which already has substitution + ParameterExpression valueSelectorKeyExpressionAlias = Utilities.GetLambda(arguments[2]).Parameters[0]; + context.GroupByKeySubstitution.AddSubstitution(valueSelectorKeyExpressionAlias, parameterExpression/*Utilities.GetLambda(arguments[1]).Body*/); + + // Translate the body of the value selector lambda + Expression valueSelectorExpression = Utilities.GetLambda(arguments[2]).Body; + + // The value selector function needs to be either a MethodCall or an AnonymousType + switch (valueSelectorExpression.NodeType) + { + case ExpressionType.Constant: + { + ConstantExpression constantExpression = (ConstantExpression)valueSelectorExpression; + SqlScalarExpression selectExpression = ExpressionToSql.VisitConstant(constantExpression, context); + + SqlSelectSpec sqlSpec = SqlSelectValueSpec.Create(selectExpression); + SqlSelectClause select = SqlSelectClause.Create(sqlSpec, null); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + break; + } + case ExpressionType.Parameter: + { + ParameterExpression parameterValueExpression = (ParameterExpression)valueSelectorExpression; + SqlScalarExpression selectExpression = ExpressionToSql.VisitParameter(parameterValueExpression, context); + + SqlSelectSpec sqlSpec = SqlSelectValueSpec.Create(selectExpression); + SqlSelectClause select = SqlSelectClause.Create(sqlSpec, null); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); + break; + } + case ExpressionType.Call: + { + // Single Value Selector + MethodCallExpression methodCallExpression = (MethodCallExpression)valueSelectorExpression; + switch (methodCallExpression.Method.Name) + { + case LinqMethods.Max: + case LinqMethods.Min: + case LinqMethods.Average: + case LinqMethods.Count: + case LinqMethods.Sum: + ExpressionToSql.VisitMethodCall(methodCallExpression, context); + break; + default: + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.MethodNotSupported, methodCallExpression.Method.Name)); + } + + break; + } + case ExpressionType.New: + // TODO: Multi Value Selector + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.ExpressionTypeIsNotSupported, ExpressionType.New)); + + default: + throw new DocumentQueryException(string.Format(CultureInfo.CurrentCulture, ClientResources.ExpressionTypeIsNotSupported, valueSelectorExpression.NodeType)); + } + + foreach (ParameterExpression par in Utilities.GetLambda(arguments[2]).Parameters) + { + context.PopParameter(); } return collection; @@ -1700,7 +1818,7 @@ private static bool TryGetTopSkipTakeLiteral( // it is necessary to trigger the binding because Skip is just a spec with no binding on its own. // This can be done by pushing and popping a temporary parameter. E.g. In SelectMany(f => f.Children.Skip(1)), // it's necessary to consider Skip as Skip(x => x, 1) to bind x to f.Children. Similarly for Top and Limit. - ParameterExpression parameter = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + ParameterExpression parameter = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); context.PushParameter(parameter, context.CurrentSubqueryBinding.ShouldBeOnNewQuery); context.PopParameter(); @@ -1848,16 +1966,21 @@ private static SqlSelectClause VisitAggregateFunction( SqlScalarExpression aggregateExpression; if (arguments.Count == 1) { - // Need to trigger parameter binding for cases where a aggregate function immediately follows a member access. - ParameterExpression parameter = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + // Need to trigger parameter binding for cases where an aggregate function immediately follows a member access. + ParameterExpression parameter = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); context.PushParameter(parameter, context.CurrentSubqueryBinding.ShouldBeOnNewQuery); + + // If there is a groupby, since there is no argument to the aggregate, we consider it to be invoked on the source collection, and not the group by keys aggregateExpression = ExpressionToSql.VisitParameter(parameter, context); context.PopParameter(); } else if (arguments.Count == 2) - { + { LambdaExpression lambda = Utilities.GetLambda(arguments[1]); - aggregateExpression = ExpressionToSql.VisitScalarExpression(lambda, context); + + aggregateExpression = context.CurrentQuery.GroupByParameter != null + ? ExpressionToSql.VisitNonSubqueryScalarLambda(lambda, context) + : ExpressionToSql.VisitScalarExpression(lambda, context); } else { @@ -1884,7 +2007,7 @@ private static SqlSelectClause VisitDistinct( // We consider Distinct as Distinct(v0 => v0) // It's necessary to visit this identity method to replace the parameters names - ParameterExpression parameter = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); + ParameterExpression parameter = context.GenerateFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); LambdaExpression identityLambda = Expression.Lambda(parameter, parameter); SqlScalarExpression sqlfunc = ExpressionToSql.VisitNonSubqueryScalarLambda(identityLambda, context); SqlSelectSpec sqlSpec = SqlSelectValueSpec.Create(sqlfunc); diff --git a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs index d2e19046e1..25129d7eec 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs @@ -27,7 +27,16 @@ internal sealed class QueryUnderConstruction /// /// Binding for the FROM parameters. /// - public FromParameterBindings fromParameters + public FromParameterBindings FromParameters + { + get; + set; + } + + /// + /// Binding for the Group By clause. + /// + public FromParameterBindings GroupByParameter { get; set; @@ -51,6 +60,7 @@ public ParameterExpression Alias private SqlSelectClause selectClause; private SqlWhereClause whereClause; private SqlOrderByClause orderByClause; + private SqlGroupByClause groupByClause; // The specs could be in clauses to reflect the SqlQuery. // However, they are separated to avoid update recreation of the readonly DOMs and lengthy code. @@ -61,7 +71,7 @@ public ParameterExpression Alias private Lazy alias; /// - /// Input subquery. + /// Input subquery / query to the left of the current query. /// private QueryUnderConstruction inputQuery; @@ -72,7 +82,7 @@ public QueryUnderConstruction(Func aliasCreatorFunc public QueryUnderConstruction(Func aliasCreatorFunc, QueryUnderConstruction inputQuery) { - this.fromParameters = new FromParameterBindings(); + this.FromParameters = new FromParameterBindings(); this.aliasCreatorFunc = aliasCreatorFunc; this.inputQuery = inputQuery; this.alias = new Lazy(() => aliasCreatorFunc(QueryUnderConstruction.DefaultSubqueryRoot)); @@ -85,22 +95,22 @@ public void Bind(ParameterExpression parameter, SqlCollection collection) public void AddBinding(Binding binding) { - this.fromParameters.Add(binding); + this.FromParameters.Add(binding); } public ParameterExpression GetInputParameterInContext(bool isInNewQuery) { - return isInNewQuery ? this.Alias : this.fromParameters.GetInputParameter(); + return isInNewQuery ? this.Alias : this.FromParameters.GetInputParameter(); } /// /// Create a FROM clause from a set of FROM parameter bindings. /// /// The created FROM clause. - private SqlFromClause CreateFrom(SqlCollectionExpression inputCollectionExpression) + private SqlFromClause CreateFromClause(SqlCollectionExpression inputCollectionExpression) { bool first = true; - foreach (Binding paramDef in this.fromParameters.GetBindings()) + foreach (Binding paramDef in this.FromParameters.GetBindings()) { // If input collection expression is provided, the first binding, // which is the input paramter name, should be omitted. @@ -147,7 +157,7 @@ private SqlFromClause CreateSubqueryFromClause() ParameterExpression inputParam = this.inputQuery.Alias; SqlIdentifier identifier = SqlIdentifier.Create(inputParam.Name); SqlAliasedCollectionExpression colExp = SqlAliasedCollectionExpression.Create(collection, identifier); - SqlFromClause fromClause = this.CreateFrom(colExp); + SqlFromClause fromClause = this.CreateFromClause(colExp); return fromClause; } @@ -169,7 +179,7 @@ public SqlQuery GetSqlQuery() } else { - fromClause = this.CreateFrom(inputCollectionExpression: null); + fromClause = this.CreateFromClause(inputCollectionExpression: null); } // Create a SqlSelectClause with the topSpec. @@ -178,7 +188,7 @@ public SqlQuery GetSqlQuery() SqlSelectClause selectClause = this.selectClause; if (selectClause == null) { - string parameterName = this.fromParameters.GetInputParameter().Name; + string parameterName = this.FromParameters.GetInputParameter().Name; SqlScalarExpression parameterExpression = SqlPropertyRefScalarExpression.Create(null, SqlIdentifier.Create(parameterName)); selectClause = this.selectClause = SqlSelectClause.Create(SqlSelectValueSpec.Create(parameterExpression)); } @@ -186,7 +196,7 @@ public SqlQuery GetSqlQuery() SqlOffsetLimitClause offsetLimitClause = (this.offsetSpec != null) ? SqlOffsetLimitClause.Create(this.offsetSpec, this.limitSpec ?? SqlLimitSpec.Create(SqlNumberLiteral.Create(int.MaxValue))) : offsetLimitClause = default(SqlOffsetLimitClause); - SqlQuery result = SqlQuery.Create(selectClause, fromClause, this.whereClause, /*GroupBy*/ null, this.orderByClause, offsetLimitClause); + SqlQuery result = SqlQuery.Create(selectClause, fromClause, this.whereClause, this.groupByClause, this.orderByClause, offsetLimitClause); return result; } @@ -198,7 +208,7 @@ public SqlQuery GetSqlQuery() public QueryUnderConstruction PackageQuery(HashSet inScope) { QueryUnderConstruction result = new QueryUnderConstruction(this.aliasCreatorFunc); - result.fromParameters.SetInputParameter(typeof(object), this.Alias.Name, inScope); + result.FromParameters.SetInputParameter(typeof(object), this.Alias.Name, inScope); result.inputQuery = this; return result; } @@ -214,13 +224,14 @@ public QueryUnderConstruction FlattenAsPossible() // 1. Select clause appears after Distinct // 2. There are any operations after Take that is not a pure Select. // 3. There are nested Select, Where or OrderBy + // 4. Group by clause appears after Select QueryUnderConstruction parentQuery = null; QueryUnderConstruction flattenQuery = null; bool seenSelect = false; bool seenAnyNonSelectOp = false; for (QueryUnderConstruction query = this; query != null; query = query.inputQuery) { - foreach (Binding binding in query.fromParameters.GetBindings()) + foreach (Binding binding in query.FromParameters.GetBindings()) { if ((binding.ParameterDefinition != null) && (binding.ParameterDefinition is SqlSubqueryCollection)) { @@ -232,8 +243,15 @@ public QueryUnderConstruction FlattenAsPossible() // In Select -> SelectMany cases, fromParameter substitution is not yet supported . // Therefore these are un-flattenable. if (query.inputQuery != null && - (query.fromParameters.GetBindings().First().Parameter.Name == query.inputQuery.Alias.Name) && - query.fromParameters.GetBindings().Any(b => b.ParameterDefinition != null)) + (query.FromParameters.GetBindings().First().Parameter.Name == query.inputQuery.Alias.Name) && + query.FromParameters.GetBindings().Any(b => b.ParameterDefinition != null)) + { + flattenQuery = this; + break; + } + + // In case of Select -> Group by cases, the Select query should not be flattened and kept as a subquery + if ((query.inputQuery?.selectClause != null) && (query.groupByClause != null)) { flattenQuery = this; break; @@ -253,10 +271,12 @@ public QueryUnderConstruction FlattenAsPossible() seenAnyNonSelectOp |= (query.whereClause != null) || (query.orderByClause != null) || + (query.groupByClause != null) || (query.topSpec != null) || (query.offsetSpec != null) || - query.fromParameters.GetBindings().Any(b => b.ParameterDefinition != null) || - ((query.selectClause != null) && (query.selectClause.HasDistinct || this.HasSelectAggregate())); + query.FromParameters.GetBindings().Any(b => b.ParameterDefinition != null) || + ((query.selectClause != null) && (query.selectClause.HasDistinct || + this.HasSelectAggregate())); parentQuery = query; } @@ -272,7 +292,7 @@ public QueryUnderConstruction FlattenAsPossible() private QueryUnderConstruction Flatten() { // SELECT fo(y) FROM y IN (SELECT fi(x) FROM x WHERE gi(x)) WHERE go(y) - // is translated by substituting fi(x) for y in the outer query + // is translated by substituting y for fi(x) in the outer query // producing // SELECT fo(fi(x)) FROM x WHERE gi(x) AND (go(fi(x)) if (this.inputQuery == null) @@ -281,7 +301,8 @@ private QueryUnderConstruction Flatten() if (this.selectClause == null) { // If selectClause doesn't exists, use SELECT v0 where v0 is the input parameter, instead of SELECT *. - string parameterName = this.fromParameters.GetInputParameter().Name; + // If there is a groupby clause, the input parameter comes from the groupBy binding instead of the from clause binding + string parameterName = (this.GroupByParameter ?? this.FromParameters).GetInputParameter().Name; SqlScalarExpression parameterExpression = SqlPropertyRefScalarExpression.Create(null, SqlIdentifier.Create(parameterName)); this.selectClause = SqlSelectClause.Create(SqlSelectValueSpec.Create(parameterExpression)); } @@ -302,12 +323,12 @@ private QueryUnderConstruction Flatten() // That is because if it has been binded before, it has global scope and should not be replaced. string paramName = null; HashSet inputQueryParams = new HashSet(); - foreach (Binding binding in this.inputQuery.fromParameters.GetBindings()) + foreach (Binding binding in this.inputQuery.FromParameters.GetBindings()) { inputQueryParams.Add(binding.Parameter.Name); } - foreach (Binding binding in this.fromParameters.GetBindings()) + foreach (Binding binding in this.FromParameters.GetBindings()) { if (binding.ParameterDefinition == null || inputQueryParams.Contains(binding.Parameter.Name)) { @@ -316,11 +337,14 @@ private QueryUnderConstruction Flatten() } SqlIdentifier replacement = SqlIdentifier.Create(paramName); - SqlSelectClause composedSelect = this.Substitute(inputSelect, inputSelect.TopSpec ?? this.topSpec, replacement, this.selectClause); + SqlSelectClause composedSelect; + + composedSelect = this.Substitute(inputSelect, inputSelect.TopSpec ?? this.topSpec, replacement, this.selectClause); SqlWhereClause composedWhere = this.Substitute(inputSelect.SelectSpec, replacement, this.whereClause); SqlOrderByClause composedOrderBy = this.Substitute(inputSelect.SelectSpec, replacement, this.orderByClause); + SqlGroupByClause composedGroupBy = this.Substitute(inputSelect.SelectSpec, replacement, this.groupByClause); SqlWhereClause and = QueryUnderConstruction.CombineWithConjunction(inputwhere, composedWhere); - FromParameterBindings fromParams = QueryUnderConstruction.CombineInputParameters(flatInput.fromParameters, this.fromParameters); + FromParameterBindings fromParams = QueryUnderConstruction.CombineInputParameters(flatInput.FromParameters, this.FromParameters); SqlOffsetSpec offsetSpec; SqlLimitSpec limitSpec; if (flatInput.offsetSpec != null) @@ -338,8 +362,9 @@ private QueryUnderConstruction Flatten() selectClause = composedSelect, whereClause = and, inputQuery = null, - fromParameters = flatInput.fromParameters, + FromParameters = flatInput.FromParameters, orderByClause = composedOrderBy ?? this.inputQuery.orderByClause, + groupByClause = composedGroupBy ?? this.inputQuery.groupByClause, offsetSpec = offsetSpec, limitSpec = limitSpec, alias = new Lazy(() => this.Alias) @@ -349,25 +374,25 @@ private QueryUnderConstruction Flatten() private SqlSelectClause Substitute(SqlSelectClause inputSelectClause, SqlTopSpec topSpec, SqlIdentifier inputParam, SqlSelectClause selectClause) { - SqlSelectSpec selectSpec = inputSelectClause.SelectSpec; + SqlSelectSpec inputSelectSpec = inputSelectClause.SelectSpec; if (selectClause == null) { - return selectSpec != null ? SqlSelectClause.Create(selectSpec, topSpec, inputSelectClause.HasDistinct) : null; + return inputSelectSpec != null ? SqlSelectClause.Create(inputSelectSpec, topSpec, inputSelectClause.HasDistinct) : null; } - if (selectSpec is SqlSelectStarSpec) + if (inputSelectSpec is SqlSelectStarSpec) { - return SqlSelectClause.Create(selectSpec, topSpec, inputSelectClause.HasDistinct); + return SqlSelectClause.Create(inputSelectSpec, topSpec, inputSelectClause.HasDistinct); } - SqlSelectValueSpec selValue = selectSpec as SqlSelectValueSpec; + SqlSelectValueSpec selValue = inputSelectSpec as SqlSelectValueSpec; if (selValue != null) { SqlSelectSpec intoSpec = selectClause.SelectSpec; if (intoSpec is SqlSelectStarSpec) { - return SqlSelectClause.Create(selectSpec, topSpec, selectClause.HasDistinct || inputSelectClause.HasDistinct); + return SqlSelectClause.Create(inputSelectSpec, topSpec, selectClause.HasDistinct || inputSelectClause.HasDistinct); } SqlSelectValueSpec intoSelValue = intoSpec as SqlSelectValueSpec; @@ -381,7 +406,7 @@ private SqlSelectClause Substitute(SqlSelectClause inputSelectClause, SqlTopSpec throw new DocumentQueryException("Unexpected SQL select clause type: " + intoSpec.GetType()); } - throw new DocumentQueryException("Unexpected SQL select clause type: " + selectSpec.GetType()); + throw new DocumentQueryException("Unexpected SQL select clause type: " + inputSelectSpec.GetType()); } private SqlWhereClause Substitute(SqlSelectSpec spec, SqlIdentifier inputParam, SqlWhereClause whereClause) @@ -440,6 +465,30 @@ private SqlOrderByClause Substitute(SqlSelectSpec spec, SqlIdentifier inputParam throw new DocumentQueryException("Unexpected SQL select clause type: " + spec.GetType()); } + private SqlGroupByClause Substitute(SqlSelectSpec spec, SqlIdentifier inputParam, SqlGroupByClause groupByClause) + { + if (groupByClause == null) + { + return null; + } + + SqlSelectValueSpec selectValueSpec = spec as SqlSelectValueSpec; + if (selectValueSpec != null) + { + SqlScalarExpression replaced = selectValueSpec.Expression; + SqlScalarExpression[] substitutedItems = new SqlScalarExpression[groupByClause.Expressions.Length]; + for (int i = 0; i < substitutedItems.Length; ++i) + { + SqlScalarExpression substituted = SqlExpressionManipulation.Substitute(replaced, inputParam, groupByClause.Expressions[i]); + substitutedItems[i] = substituted; + } + SqlGroupByClause result = SqlGroupByClause.Create(substitutedItems); + return result; + } + + throw new DocumentQueryException("Unexpected SQL select clause type: " + spec.GetType()); + } + /// /// Determine if the current method call should create a new QueryUnderConstruction node or not. /// @@ -449,10 +498,14 @@ private SqlOrderByClause Substitute(SqlSelectSpec spec, SqlIdentifier inputParam public bool ShouldBeOnNewQuery(string methodName, int argumentCount) { // In the LINQ provider perspective, a SQL query (without subquery) the order of the execution of the operations is: - // Join -> Where -> Order By -> Aggregates/Distinct/Select -> Top/Offset Limit + // Join -> Where -> Order By -> Aggregates/Distinct/Select -> Top/Offset Limit + // | | + // |-> Group By->| // // The order for the corresponding LINQ operations is: - // SelectMany -> Where -> OrderBy -> Aggregates/Distinct/Select -> Skip/Take + // SelectMany -> Where -> OrderBy -> Aggregates/Distinct/Select -> Skip/Take + // | | + // |-> Group By->| // // In general, if an operation Op1 is being visited and the current query already has Op0 which // appear not before Op1 in the execution order, then this Op1 needs to be in a new query. This ensures @@ -495,7 +548,7 @@ public bool ShouldBeOnNewQuery(string methodName, int argumentCount) break; case LinqMethods.Where: - // Where expression parameter needs to be substitued if necessary so + // Where expression parameter needs to be substituted if necessary so // It is not needed in Select distinct because the Select distinct would have the necessary parameter name adjustment. case LinqMethods.Any: case LinqMethods.OrderBy: @@ -506,7 +559,16 @@ public bool ShouldBeOnNewQuery(string methodName, int argumentCount) // New query is needed when there is already a Take or a non-distinct Select shouldPackage = (this.topSpec != null) || (this.offsetSpec != null) || - (this.selectClause != null && !this.selectClause.HasDistinct); + (this.selectClause != null && !this.selectClause.HasDistinct) || + (this.groupByClause != null); + break; + + case LinqMethods.GroupBy: + // New query is needed when there is already a Take or a Select or a Group by clause + shouldPackage = (this.topSpec != null) || + (this.offsetSpec != null) || + (this.selectClause != null) || + (this.groupByClause != null); break; case LinqMethods.Skip: @@ -592,6 +654,16 @@ public QueryUnderConstruction UpdateOrderByClause(SqlOrderByClause thenBy, Trans return context.CurrentQuery; } + public QueryUnderConstruction AddGroupByClause(SqlGroupByClause groupBy, TranslationContext context) + { + QueryUnderConstruction result = context.PackageCurrentQueryIfNeccessary(); + + result.groupByClause = groupBy; + foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) result.AddBinding(binding); + + return result; + } + public QueryUnderConstruction AddOffsetSpec(SqlOffsetSpec offsetSpec, TranslationContext context) { QueryUnderConstruction result = context.PackageCurrentQueryIfNeccessary(); @@ -826,6 +898,7 @@ public bool HasOffsetSpec() private bool HasSelectAggregate() { string functionCallName = ((this.selectClause?.SelectSpec as SqlSelectValueSpec)?.Expression as SqlFunctionCallScalarExpression)?.Name.Value; + return (functionCallName != null) && ((functionCallName == SqlFunctionCallScalarExpression.Names.Max) || (functionCallName == SqlFunctionCallScalarExpression.Names.Min) || diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index 82150b6d4a..606ade1d84 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -43,6 +43,16 @@ internal sealed class TranslationContext /// public IDictionary Parameters; + /// + /// Dictionary for group by key substitution. + /// + public ParameterSubstitution GroupByKeySubstitution; + + /// + /// Boolean to indicate a GroupBy expression is the last expression to finished processing. + /// + public bool LastExpressionIsGroupBy; + /// /// If the FROM clause uses a parameter name, it will be substituted for the parameter used in /// the lambda expressions for the WHERE and SELECT clauses. @@ -86,6 +96,7 @@ public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOpti this.subqueryBindingStack = new Stack(); this.Parameters = parameters; this.clientOperation = null; + this.LastExpressionIsGroupBy = false; if (linqSerializerOptionsInternal?.CustomCosmosLinqSerializer != null) { @@ -104,6 +115,8 @@ public TranslationContext(CosmosLinqSerializerOptionsInternal linqSerializerOpti this.CosmosLinqSerializer = TranslationContext.DefaultLinqSerializer; this.MemberNames = TranslationContext.DefaultMemberNames; } + + this.GroupByKeySubstitution = new ParameterSubstitution(); } public ScalarOperationKind ClientOperation => this.clientOperation ?? ScalarOperationKind.None; @@ -120,17 +133,25 @@ public void SetClientOperation(ScalarOperationKind clientOperation) public Expression LookupSubstitution(ParameterExpression parameter) { + if (this.CurrentQuery.GroupByParameter != null) + { + Expression groupBySubstitutionExpression = this.GroupByKeySubstitution.Lookup(parameter); + if (groupBySubstitutionExpression != null) + { + return groupBySubstitutionExpression; + } + } return this.substitutions.Lookup(parameter); } - public ParameterExpression GenFreshParameter(Type parameterType, string baseParameterName) + public ParameterExpression GenerateFreshParameter(Type parameterType, string baseParameterName, bool includeSuffix = true) { - return Utilities.NewParameter(baseParameterName, parameterType, this.InScope); + return Utilities.NewParameter(baseParameterName, parameterType, this.InScope, includeSuffix); } public Func GetGenFreshParameterFunc() { - return (paramName) => this.GenFreshParameter(typeof(object), paramName); + return (paramName) => this.GenerateFreshParameter(typeof(object), paramName); } /// @@ -211,12 +232,12 @@ public void PushCollection(Collection collection) throw new ArgumentNullException("collection"); } - this.collectionStack.Add(collection); + if (this.CurrentQuery.GroupByParameter == null) this.collectionStack.Add(collection); } public void PopCollection() { - this.collectionStack.RemoveAt(this.collectionStack.Count - 1); + if (this.CurrentQuery.GroupByParameter == null) this.collectionStack.RemoveAt(this.collectionStack.Count - 1); } /// @@ -226,7 +247,7 @@ public void PopCollection() /// Suggested name for the input parameter. public ParameterExpression SetInputParameter(Type type, string name) { - return this.CurrentQuery.fromParameters.SetInputParameter(type, name, this.InScope); + return this.CurrentQuery.FromParameters.SetInputParameter(type, name, this.InScope); } /// @@ -237,7 +258,7 @@ public ParameterExpression SetInputParameter(Type type, string name) public void SetFromParameter(ParameterExpression parameter, SqlCollection collection) { Binding binding = new Binding(parameter, collection, isInCollection: true); - this.CurrentQuery.fromParameters.Add(binding); + this.CurrentQuery.FromParameters.Add(binding); } /// diff --git a/Microsoft.Azure.Cosmos/src/Linq/Utilities.cs b/Microsoft.Azure.Cosmos/src/Linq/Utilities.cs index f7870d2081..ca39671f74 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/Utilities.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/Utilities.cs @@ -45,15 +45,16 @@ public static LambdaExpression GetLambda(Expression expr) /// Prefix for the parameter name. /// Parameter type. /// Names to avoid. + /// Enable suffix to parameter name /// The new parameter. - public static ParameterExpression NewParameter(string prefix, Type type, HashSet inScope) + public static ParameterExpression NewParameter(string prefix, Type type, HashSet inScope, bool includeSuffix = true) { int suffix = 0; while (true) { - string name = prefix + suffix.ToString(CultureInfo.InvariantCulture); + string name = prefix + (includeSuffix ? suffix.ToString(CultureInfo.InvariantCulture) : string.Empty); ParameterExpression param = Expression.Parameter(type, name); - if (!inScope.Any(p => p.Name.Equals(name))) + if (!inScope.Any(p => p.Name.Equals(name)) || !includeSuffix) { inScope.Add(param); return param; diff --git a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs index a29435744d..150be14275 100644 --- a/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/SqlObjects/Visitors/SqlObjectTextSerializer.cs @@ -495,6 +495,7 @@ public override void Visit(SqlQuery sqlQuery) if (sqlQuery.GroupByClause != null) { + this.WriteDelimiter(string.Empty); sqlQuery.GroupByClause.Accept(this); this.writer.Write(" "); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml new file mode 100644 index 0000000000..f5256c787c --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml @@ -0,0 +1,449 @@ + + + + + k, (key, values) => key)]]> + + + + + + + + + k.Id, (key, values) => key)]]> + + + + + + + + + k.Id, (stringField, values) => stringField)]]> + + + + + + + + + k.Id, (key, values) => values.Min(value => value.Int))]]> + + + + + + + + + k.Id, (key, values) => values.Max(value => value.Int))]]> + + + + + + + + + k.Id, (key, values) => values.Count())]]> + + + + + + + + + k.Id, (key, values) => values.Average(value => value.Int))]]> + + + + + + + + + k.Int, (key, values) => values.Min())]]> + + + + + + + + + + k.Int, (key, values) => values.Max())]]> + + + + + + + + + + k.Int, (key, values) => "string")]]> + + + + + + + + + k.Id)]]> + + + + + + + + + + k.Int, k2 => k2.Int, (key, values) => "string")]]> + + + + + + + + + + k.Id, (key, values) => values.Select(value => value.Int))]]> + + + + + + + + + + k.Id, (key, values) => values.OrderBy(f => f.FamilyId))]]> + + + + + + + + + + k.FamilyId, (key, values) => new AnonymousType(familyId = key, familyIdCount = values.Count()))]]> + + + + + + + + + + x.Id).GroupBy(k => k, (key, values) => key)]]> + + + + + + + + + new AnonymousType(Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children)).GroupBy(k => k.family1, (key, values) => key)]]> + + + + + + + + + x.Children).GroupBy(k => k.Grade, (key, values) => key)]]> + + + + + + + + + f.Children).Where(c => (c.Pets.Count() > 0)).SelectMany(c => c.Pets.Select(p => p.GivenName)).GroupBy(k => k, (key, values) => key)]]> + + + 0)) AS r0 + GROUP BY r0 +]]> + + + + + + k.Id, (key, values) => key)]]> + + + + + + + + + + k.Id, (key, values) => key)]]> + + + + + + + + + + k.Id, (key, values) => key)]]> + + + + + + + + + + (x.Id != "a")).GroupBy(k => k.Id, (key, values) => key)]]> + + + + + + + + + x.Int).GroupBy(k => k.Id, (key, values) => key)]]> + + + + + + + + + + x.Id).GroupBy(k => k.Id, (key, values) => key)]]> + + + + + + + + + (x.Id != "a")).OrderBy(x => x.Id).GroupBy(k => k.Id, (key, values) => key)]]> + + + + + + + + + (x.Id != "a")).Where(x => (x.Children.Min(y => y.Grade) > 10)).GroupBy(k => k.Id, (key, values) => key)]]> + + + 10)) + GROUP BY root["id"] +]]> + + + + + + + k.Id, (key, values) => key).Select(x => x)]]> + + + + + + + + + + k.Id, (key, values) => key).Skip(10)]]> + + + + + + + + + + k.Id, (key, values) => key).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => key).Skip(10).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => key).Where(x => (x == "a"))]]> + + + + + + + + + + k.Id, (key, values) => key).OrderBy(x => x)]]> + + + + + + + + + + k.Id, (key, values) => key).OrderByDescending(x => x)]]> + + + + + + + + + + k.Id, (key, values) => key).Where(x => (x == "a")).Skip(10).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => key).GroupBy(k => k, (key, values) => key)]]> + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs index e76b2827be..21172812f7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs @@ -697,6 +697,155 @@ public void TestSubquery() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void TestGroupByTranslation() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (stringField, values) => stringField /*return the group by key */))); + + + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Count() /*return the Count of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); + + // Negative cases + + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Min() /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Max() /*return the Max of each group */))); + + // Unsupported node type + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Incorrect number of arguments + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( + k => k.Int, + k2 => k2.Int, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); + + // Currently unsupported case + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); + + // Other methods followed by GroupBy + + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => p.GivenName)) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // The result for this is not correct yet - the select clause is wrong + inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .Where(x => x.Children.Min(y => y.Grade) > 10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Select(x => x))); + + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10))); + + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a"))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderBy(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderByDescending(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a").Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + this.ExecuteTestSuite(inputs); + } + [TestMethod] [Ignore] public void DebuggingTest() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index f8fea9959f..ab5155cbfe 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -1,574 +1,574 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Diagnostics; - using System.IO; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - using System.Runtime.CompilerServices; - using System.Text; - using System.Text.Json.Serialization; - using System.Text.Json; - using System.Text.RegularExpressions; - using System.Xml; - using global::Azure.Core.Serialization; - using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; - using Microsoft.Azure.Documents; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.IO; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using System.Runtime.CompilerServices; + using System.Text; + using System.Text.Json.Serialization; + using System.Text.Json; + using System.Text.RegularExpressions; + using System.Xml; + using global::Azure.Core.Serialization; + using Microsoft.Azure.Cosmos.Services.Management.Tests.BaselineTest; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; using Newtonsoft.Json.Linq; - internal class LinqTestsCommon - { - /// - /// Compare two list of anonymous objects - /// - /// - /// - /// - private static bool CompareListOfAnonymousType(List queryResults, List dataResults) - { - return queryResults.SequenceEqual(dataResults); - } - - /// - /// Compare 2 IEnumerable which may contain IEnumerable themselves. - /// - /// The query results from Cosmos DB - /// The query results from actual data - /// True if the two IEbumerable equal - private static bool NestedListsSequenceEqual(IEnumerable queryResults, IEnumerable dataResults) - { - IEnumerator queryIter, dataIter; - for (queryIter = queryResults.GetEnumerator(), dataIter = dataResults.GetEnumerator(); - queryIter.MoveNext() && dataIter.MoveNext();) - { - IEnumerable queryEnumerable = queryIter.Current as IEnumerable; - IEnumerable dataEnumerable = dataIter.Current as IEnumerable; - if (queryEnumerable == null && dataEnumerable == null) - { - if (!queryIter.Current.Equals(dataIter.Current)) return false; - - } - - else if (queryEnumerable == null || dataEnumerable == null) - { - return false; - } - - else - { - if (!LinqTestsCommon.NestedListsSequenceEqual(queryEnumerable, dataEnumerable)) return false; - } - } - - return !(queryIter.MoveNext() || dataIter.MoveNext()); - } - - /// - /// Compare the list of results from CosmosDB query and the list of results from LinQ query on the original data - /// Similar to Collections.SequenceEqual with the assumption that these lists are non-empty - /// - /// A list representing the query restuls from CosmosDB - /// A list representing the linQ query results from the original data - /// true if the two - private static bool CompareListOfArrays(List queryResults, List dataResults) - { - if (NestedListsSequenceEqual(queryResults, dataResults)) return true; - - bool resultMatched = true; - - // dataResults contains type ConcatIterator whereas queryResults may contain IEnumerable - // therefore it's simpler to just cast them into List> manually for simplify the verification - List> l1 = new List>(); - foreach (IEnumerable list in dataResults) - { - List l = new List(); - IEnumerator iterator = list.GetEnumerator(); - while (iterator.MoveNext()) - { - l.Add(iterator.Current); - } - - l1.Add(l); - } - - List> l2 = new List>(); - foreach (IEnumerable list in queryResults) - { - List l = new List(); - IEnumerator iterator = list.GetEnumerator(); - while (iterator.MoveNext()) - { - l.Add(iterator.Current); - } - - l2.Add(l); - } - - foreach (IEnumerable list in l1) - { - if (!l2.Any(a => a.SequenceEqual(list))) - { - resultMatched = false; - return false; - } - } - - foreach (IEnumerable list in l2) - { - if (!l1.Any(a => a.SequenceEqual(list))) - { - resultMatched = false; - break; - } - } - - return resultMatched; - } - - private static bool IsNumber(dynamic value) - { - return value is sbyte - || value is byte - || value is short - || value is ushort - || value is int - || value is uint - || value is long - || value is ulong - || value is float - || value is double - || value is decimal; - } - - public static Boolean IsAnonymousType(Type type) - { - Boolean hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; - Boolean nameContainsAnonymousType = type.FullName.Contains("AnonymousType"); - Boolean isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; - - return isAnonymousType; - } - - /// - /// Gets the results of CosmosDB query and the results of LINQ query on the original data - /// - /// - /// - public static (List queryResults, List dataResults) GetResults(IQueryable queryResults, IQueryable dataResults) - { - // execution validation - IEnumerator queryEnumerator = queryResults.GetEnumerator(); - List queryResultsList = new List(); - while (queryEnumerator.MoveNext()) - { - queryResultsList.Add(queryEnumerator.Current); - } - - List dataResultsList = dataResults?.Cast()?.ToList(); - - return (queryResultsList, dataResultsList); - } - - /// - /// Validates the results of CosmosDB query and the results of LINQ query on the original data - /// Using Assert, will fail the unit test if the two results list are not SequenceEqual - /// - /// - /// - private static void ValidateResults(List queryResultsList, List dataResultsList) - { - bool resultMatched = true; - string actualStr = null; - string expectedStr = null; - if (dataResultsList.Count == 0 || queryResultsList.Count == 0) - { - resultMatched &= dataResultsList.Count == queryResultsList.Count; - } - else - { - dynamic firstElem = dataResultsList.FirstOrDefault(); - if (firstElem is IEnumerable) - { - resultMatched &= CompareListOfArrays(queryResultsList, dataResultsList); - } - else if (LinqTestsCommon.IsAnonymousType(firstElem.GetType())) - { - resultMatched &= CompareListOfAnonymousType(queryResultsList, dataResultsList); - } - else if (LinqTestsCommon.IsNumber(firstElem)) - { - const double Epsilon = 1E-6; - Type dataType = firstElem.GetType(); - List dataSortedList = dataResultsList.OrderBy(x => x).ToList(); - List querySortedList = queryResultsList.OrderBy(x => x).ToList(); - if (dataSortedList.Count != querySortedList.Count) - { - resultMatched = false; - } - else - { - for (int i = 0; i < dataSortedList.Count; ++i) - { - if (Math.Abs(dataSortedList[i] - (dynamic)querySortedList[i]) > (dynamic)Convert.ChangeType(Epsilon, dataType)) - { - resultMatched = false; - break; - } - } - } - - if (!resultMatched) - { - actualStr = JsonConvert.SerializeObject(querySortedList); - expectedStr = JsonConvert.SerializeObject(dataSortedList); - } - } - else - { - List dataNotQuery = dataResultsList.Except(queryResultsList).ToList(); - List queryNotData = queryResultsList.Except(dataResultsList).ToList(); - resultMatched &= !dataNotQuery.Any() && !queryNotData.Any(); - } - } - - string assertMsg = string.Empty; - if (!resultMatched) - { - actualStr ??= JsonConvert.SerializeObject(queryResultsList); - expectedStr ??= JsonConvert.SerializeObject(dataResultsList); - - resultMatched |= actualStr.Equals(expectedStr); - if (!resultMatched) - { - assertMsg = $"Expected: {expectedStr}, Actual: {actualStr}, RandomSeed: {LinqTestInput.RandomSeed}"; - } - } - - Assert.IsTrue(resultMatched, assertMsg); - } - - /// - /// Generate a random string containing alphabetical characters - /// - /// - /// - /// a random string - public static string RandomString(Random random, int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz "; - return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); - } - - /// - /// Generate a random DateTime object from a DateTime, - /// with the variance of the time span between the provided DateTime to the current time - /// - /// - /// - /// - public static DateTime RandomDateTime(Random random, DateTime midDateTime) - { - TimeSpan timeSpan = DateTime.Now - midDateTime; - TimeSpan newSpan = new TimeSpan(0, random.Next(0, (int)timeSpan.TotalMinutes * 2) - (int)timeSpan.TotalMinutes, 0); - DateTime newDate = midDateTime + newSpan; - return newDate; - } - - /// - /// Generate test data for most LINQ tests - /// - /// the object type - /// the lamda to create an instance of test data - /// number of test data to be created - /// the target container - /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable - public static Func> GenerateTestCosmosData(Func func, int count, Container container) - { - List data = new List(); - int seed = DateTime.Now.Millisecond; - Random random = new Random(seed); - Debug.WriteLine("Random seed: {0}", seed); - LinqTestInput.RandomSeed = seed; - for (int i = 0; i < count; ++i) - { - data.Add(func(random)); - } - - foreach (T obj in data) - { - ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); - - // To cover both query against backend and queries on the original data using LINQ nicely, - // the LINQ expression should be written once and they should be compiled and executed against the two sources. - // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query - // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values - // to this getQuery method. - IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); - - return getQuery; - } - - /// - /// Generate a non-random payload for serializer LINQ tests. - /// - /// the object type - /// the lamda to create an instance of test data - /// number of test data to be created - /// the target container - /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied - /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. - public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, CosmosLinqSerializerOptions linqSerializerOptions) - { - List data = new List(); - for (int i = 0; i < count; i++) - { - data.Add(func(i, linqSerializerOptions.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase)); - } - - foreach (T obj in data) - { - ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); - - IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); - - return getQuery; - } - - public static Func> GenerateFamilyCosmosData( - Cosmos.Database cosmosDatabase, out Container container) - { - // The test collection should have range index on string properties - // for the orderby tests - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; - ContainerProperties newCol = new ContainerProperties() - { - Id = Guid.NewGuid().ToString(), - PartitionKey = partitionKeyDefinition, - IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy() - { - IncludedPaths = new Collection() - { - new Cosmos.IncludedPath() - { - Path = "/*", - Indexes = new System.Collections.ObjectModel.Collection() - { - Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1), - Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1) - } - } - }, - CompositeIndexes = new Collection>() - { - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } - }, - new Collection() - { - new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending }, - new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } - } - } - } - }; - container = cosmosDatabase.CreateContainerAsync(newCol).Result; - const int Records = 100; - const int MaxNameLength = 100; - const int MaxThingStringLength = 50; - const int MaxChild = 5; - const int MaxPets = MaxChild; - const int MaxThings = MaxChild; - const int MaxGrade = 101; - const int MaxTransaction = 20; - const int MaxTransactionMinuteRange = 200; - int MaxTransactionType = Enum.GetValues(typeof(TransactionType)).Length; - Family createDataObj(Random random) - { - Family obj = new Family - { - FamilyId = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(), - IsRegistered = random.NextDouble() < 0.5, - NullableInt = random.NextDouble() < 0.5 ? (int?)random.Next() : null, - Int = random.NextDouble() < 0.5 ? 5 : random.Next(), - Id = Guid.NewGuid().ToString(), - Pk = "Test", - Parents = new Parent[random.Next(2) + 1] - }; - for (int i = 0; i < obj.Parents.Length; ++i) - { - obj.Parents[i] = new Parent() - { - FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) - }; - } - - obj.Tags = new string[random.Next(MaxChild)]; - for (int i = 0; i < obj.Tags.Length; ++i) - { - obj.Tags[i] = (i + random.Next(30, 36)).ToString(); - } - - obj.Children = new Child[random.Next(MaxChild)]; - for (int i = 0; i < obj.Children.Length; ++i) - { - obj.Children[i] = new Child() - { - Gender = random.NextDouble() < 0.5 ? "male" : "female", - FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName, - GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - Grade = random.Next(MaxGrade) - }; - - obj.Children[i].Pets = new List(); - for (int j = 0; j < random.Next(MaxPets); ++j) - { - obj.Children[i].Pets.Add(new Pet() - { - GivenName = random.NextDouble() < 0.5 ? - LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) : - "Fluffy" - }); - } - - obj.Children[i].Things = new Dictionary(); - for (int j = 0; j < random.Next(MaxThings) + 1; ++j) - { - obj.Children[i].Things.Add( - j == 0 ? "A" : $"{j}-{random.Next()}", - LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength))); - } - } - - obj.Records = new Logs - { - LogId = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), - Transactions = new Transaction[random.Next(MaxTransaction)] - }; - for (int i = 0; i < obj.Records.Transactions.Length; ++i) - { - Transaction transaction = new Transaction() - { - Amount = random.Next(), - Date = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)), - Type = (TransactionType)random.Next(MaxTransactionType) - }; - obj.Records.Transactions[i] = transaction; - } - - return obj; - } - - Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container); - return getQuery; - } - + internal class LinqTestsCommon + { + /// + /// Compare two list of anonymous objects + /// + /// + /// + /// + private static bool CompareListOfAnonymousType(List queryResults, List dataResults) + { + return queryResults.SequenceEqual(dataResults); + } + + /// + /// Compare 2 IEnumerable which may contain IEnumerable themselves. + /// + /// The query results from Cosmos DB + /// The query results from actual data + /// True if the two IEbumerable equal + private static bool NestedListsSequenceEqual(IEnumerable queryResults, IEnumerable dataResults) + { + IEnumerator queryIter, dataIter; + for (queryIter = queryResults.GetEnumerator(), dataIter = dataResults.GetEnumerator(); + queryIter.MoveNext() && dataIter.MoveNext();) + { + IEnumerable queryEnumerable = queryIter.Current as IEnumerable; + IEnumerable dataEnumerable = dataIter.Current as IEnumerable; + if (queryEnumerable == null && dataEnumerable == null) + { + if (!queryIter.Current.Equals(dataIter.Current)) return false; + + } + + else if (queryEnumerable == null || dataEnumerable == null) + { + return false; + } + + else + { + if (!LinqTestsCommon.NestedListsSequenceEqual(queryEnumerable, dataEnumerable)) return false; + } + } + + return !(queryIter.MoveNext() || dataIter.MoveNext()); + } + + /// + /// Compare the list of results from CosmosDB query and the list of results from LinQ query on the original data + /// Similar to Collections.SequenceEqual with the assumption that these lists are non-empty + /// + /// A list representing the query restuls from CosmosDB + /// A list representing the linQ query results from the original data + /// true if the two + private static bool CompareListOfArrays(List queryResults, List dataResults) + { + if (NestedListsSequenceEqual(queryResults, dataResults)) return true; + + bool resultMatched = true; + + // dataResults contains type ConcatIterator whereas queryResults may contain IEnumerable + // therefore it's simpler to just cast them into List> manually for simplify the verification + List> l1 = new List>(); + foreach (IEnumerable list in dataResults) + { + List l = new List(); + IEnumerator iterator = list.GetEnumerator(); + while (iterator.MoveNext()) + { + l.Add(iterator.Current); + } + + l1.Add(l); + } + + List> l2 = new List>(); + foreach (IEnumerable list in queryResults) + { + List l = new List(); + IEnumerator iterator = list.GetEnumerator(); + while (iterator.MoveNext()) + { + l.Add(iterator.Current); + } + + l2.Add(l); + } + + foreach (IEnumerable list in l1) + { + if (!l2.Any(a => a.SequenceEqual(list))) + { + resultMatched = false; + return false; + } + } + + foreach (IEnumerable list in l2) + { + if (!l1.Any(a => a.SequenceEqual(list))) + { + resultMatched = false; + break; + } + } + + return resultMatched; + } + + private static bool IsNumber(dynamic value) + { + return value is sbyte + || value is byte + || value is short + || value is ushort + || value is int + || value is uint + || value is long + || value is ulong + || value is float + || value is double + || value is decimal; + } + + public static Boolean IsAnonymousType(Type type) + { + Boolean hasCompilerGeneratedAttribute = type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Count() > 0; + Boolean nameContainsAnonymousType = type.FullName.Contains("AnonymousType"); + Boolean isAnonymousType = hasCompilerGeneratedAttribute && nameContainsAnonymousType; + + return isAnonymousType; + } + + /// + /// Gets the results of CosmosDB query and the results of LINQ query on the original data + /// + /// + /// + public static (List queryResults, List dataResults) GetResults(IQueryable queryResults, IQueryable dataResults) + { + // execution validation + IEnumerator queryEnumerator = queryResults.GetEnumerator(); + List queryResultsList = new List(); + while (queryEnumerator.MoveNext()) + { + queryResultsList.Add(queryEnumerator.Current); + } + + List dataResultsList = dataResults?.Cast()?.ToList(); + + return (queryResultsList, dataResultsList); + } + + /// + /// Validates the results of CosmosDB query and the results of LINQ query on the original data + /// Using Assert, will fail the unit test if the two results list are not SequenceEqual + /// + /// + /// + private static void ValidateResults(List queryResultsList, List dataResultsList) + { + bool resultMatched = true; + string actualStr = null; + string expectedStr = null; + if (dataResultsList.Count == 0 || queryResultsList.Count == 0) + { + resultMatched &= dataResultsList.Count == queryResultsList.Count; + } + else + { + dynamic firstElem = dataResultsList.FirstOrDefault(); + if (firstElem is IEnumerable) + { + resultMatched &= CompareListOfArrays(queryResultsList, dataResultsList); + } + else if (LinqTestsCommon.IsAnonymousType(firstElem.GetType())) + { + resultMatched &= CompareListOfAnonymousType(queryResultsList, dataResultsList); + } + else if (LinqTestsCommon.IsNumber(firstElem)) + { + const double Epsilon = 1E-6; + Type dataType = firstElem.GetType(); + List dataSortedList = dataResultsList.OrderBy(x => x).ToList(); + List querySortedList = queryResultsList.OrderBy(x => x).ToList(); + if (dataSortedList.Count != querySortedList.Count) + { + resultMatched = false; + } + else + { + for (int i = 0; i < dataSortedList.Count; ++i) + { + if (Math.Abs(dataSortedList[i] - (dynamic)querySortedList[i]) > (dynamic)Convert.ChangeType(Epsilon, dataType)) + { + resultMatched = false; + break; + } + } + } + + if (!resultMatched) + { + actualStr = JsonConvert.SerializeObject(querySortedList); + expectedStr = JsonConvert.SerializeObject(dataSortedList); + } + } + else + { + List dataNotQuery = dataResultsList.Except(queryResultsList).ToList(); + List queryNotData = queryResultsList.Except(dataResultsList).ToList(); + resultMatched &= !dataNotQuery.Any() && !queryNotData.Any(); + } + } + + string assertMsg = string.Empty; + if (!resultMatched) + { + actualStr ??= JsonConvert.SerializeObject(queryResultsList); + expectedStr ??= JsonConvert.SerializeObject(dataResultsList); + + resultMatched |= actualStr.Equals(expectedStr); + if (!resultMatched) + { + assertMsg = $"Expected: {expectedStr}, Actual: {actualStr}, RandomSeed: {LinqTestInput.RandomSeed}"; + } + } + + Assert.IsTrue(resultMatched, assertMsg); + } + + /// + /// Generate a random string containing alphabetical characters + /// + /// + /// + /// a random string + public static string RandomString(Random random, int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz "; + return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray()); + } + + /// + /// Generate a random DateTime object from a DateTime, + /// with the variance of the time span between the provided DateTime to the current time + /// + /// + /// + /// + public static DateTime RandomDateTime(Random random, DateTime midDateTime) + { + TimeSpan timeSpan = DateTime.Now - midDateTime; + TimeSpan newSpan = new TimeSpan(0, random.Next(0, (int)timeSpan.TotalMinutes * 2) - (int)timeSpan.TotalMinutes, 0); + DateTime newDate = midDateTime + newSpan; + return newDate; + } + + /// + /// Generate test data for most LINQ tests + /// + /// the object type + /// the lamda to create an instance of test data + /// number of test data to be created + /// the target container + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable + public static Func> GenerateTestCosmosData(Func func, int count, Container container) + { + List data = new List(); + int seed = DateTime.Now.Millisecond; + Random random = new Random(seed); + Debug.WriteLine("Random seed: {0}", seed); + LinqTestInput.RandomSeed = seed; + for (int i = 0; i < count; ++i) + { + data.Add(func(random)); + } + + foreach (T obj in data) + { + ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); + + // To cover both query against backend and queries on the original data using LINQ nicely, + // the LINQ expression should be written once and they should be compiled and executed against the two sources. + // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query + // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values + // to this getQuery method. + IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); + + return getQuery; + } + + /// + /// Generate a non-random payload for serializer LINQ tests. + /// + /// the object type + /// the lamda to create an instance of test data + /// number of test data to be created + /// the target container + /// if theCosmosLinqSerializerOption of camelCaseSerialization should be applied + /// a lambda that takes a boolean which indicate where the query should run against CosmosDB or against original data, and return a query results as IQueryable. + public static Func> GenerateSerializationTestCosmosData(Func func, int count, Container container, CosmosLinqSerializerOptions linqSerializerOptions) + { + List data = new List(); + for (int i = 0; i < count; i++) + { + data.Add(func(i, linqSerializerOptions.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase)); + } + + foreach (T obj in data) + { + ItemResponse response = container.CreateItemAsync(obj, new Cosmos.PartitionKey("Test")).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); + + IQueryable getQuery(bool useQuery) => useQuery ? query : data.AsQueryable(); + + return getQuery; + } + + public static Func> GenerateFamilyCosmosData( + Cosmos.Database cosmosDatabase, out Container container) + { + // The test collection should have range index on string properties + // for the orderby tests + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; + ContainerProperties newCol = new ContainerProperties() + { + Id = Guid.NewGuid().ToString(), + PartitionKey = partitionKeyDefinition, + IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy() + { + IncludedPaths = new Collection() + { + new Cosmos.IncludedPath() + { + Path = "/*", + Indexes = new System.Collections.ObjectModel.Collection() + { + Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1), + Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1) + } + } + }, + CompositeIndexes = new Collection>() + { + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending } + }, + new Collection() + { + new Cosmos.CompositePath() { Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending }, + new Cosmos.CompositePath() { Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending } + } + } + } + }; + container = cosmosDatabase.CreateContainerAsync(newCol).Result; + const int Records = 100; + const int MaxNameLength = 100; + const int MaxThingStringLength = 50; + const int MaxChild = 5; + const int MaxPets = MaxChild; + const int MaxThings = MaxChild; + const int MaxGrade = 101; + const int MaxTransaction = 20; + const int MaxTransactionMinuteRange = 200; + int MaxTransactionType = Enum.GetValues(typeof(TransactionType)).Length; + Family createDataObj(Random random) + { + Family obj = new Family + { + FamilyId = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(), + IsRegistered = random.NextDouble() < 0.5, + NullableInt = random.NextDouble() < 0.5 ? (int?)random.Next() : null, + Int = random.NextDouble() < 0.5 ? 5 : random.Next(), + Id = Guid.NewGuid().ToString(), + Pk = "Test", + Parents = new Parent[random.Next(2) + 1] + }; + for (int i = 0; i < obj.Parents.Length; ++i) + { + obj.Parents[i] = new Parent() + { + FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) + }; + } + + obj.Tags = new string[random.Next(MaxChild)]; + for (int i = 0; i < obj.Tags.Length; ++i) + { + obj.Tags[i] = (i + random.Next(30, 36)).ToString(); + } + + obj.Children = new Child[random.Next(MaxChild)]; + for (int i = 0; i < obj.Children.Length; ++i) + { + obj.Children[i] = new Child() + { + Gender = random.NextDouble() < 0.5 ? "male" : "female", + FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName, + GivenName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + Grade = random.Next(MaxGrade) + }; + + obj.Children[i].Pets = new List(); + for (int j = 0; j < random.Next(MaxPets); ++j) + { + obj.Children[i].Pets.Add(new Pet() + { + GivenName = random.NextDouble() < 0.5 ? + LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) : + "Fluffy" + }); + } + + obj.Children[i].Things = new Dictionary(); + for (int j = 0; j < random.Next(MaxThings) + 1; ++j) + { + obj.Children[i].Things.Add( + j == 0 ? "A" : $"{j}-{random.Next()}", + LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength))); + } + } + + obj.Records = new Logs + { + LogId = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)), + Transactions = new Transaction[random.Next(MaxTransaction)] + }; + for (int i = 0; i < obj.Records.Transactions.Length; ++i) + { + Transaction transaction = new Transaction() + { + Amount = random.Next(), + Date = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)), + Type = (TransactionType)random.Next(MaxTransactionType) + }; + obj.Records.Transactions[i] = transaction; + } + + return obj; + } + + Func> getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container); + return getQuery; + } + public static Func> GenerateSimpleCosmosData(Cosmos.Database cosmosDatabase, bool useRandomData = true) - { - const int DocumentCount = 10; - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; - Container container = cosmosDatabase.CreateContainerAsync(new ContainerProperties { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; - + { + const int DocumentCount = 10; + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/Pk" }), Kind = PartitionKind.Hash }; + Container container = cosmosDatabase.CreateContainerAsync(new ContainerProperties { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; + ILinqTestDataGenerator dataGenerator = useRandomData ? new LinqTestRandomDataGenerator(DocumentCount) : new LinqTestDataGenerator(DocumentCount); List testData = new List(dataGenerator.GenerateData()); foreach (Data dataEntry in testData) - { - Data response = container.CreateItemAsync(dataEntry, new Cosmos.PartitionKey(dataEntry.Pk)).Result; - } - - FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); - - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); - - // To cover both query against backend and queries on the original data using LINQ nicely, - // the LINQ expression should be written once and they should be compiled and executed against the two sources. - // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query - // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values - // to this getQuery method. - IQueryable getQuery(bool useQuery) => useQuery ? query : testData.AsQueryable(); - return getQuery; - } - - public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResultsInBaseline = false) - { - string querySqlStr = string.Empty; - try - { - Func compiledQuery = input.Expression.Compile(); - - IQueryable query = compiledQuery(true); - querySqlStr = JObject.Parse(query.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); - - IQueryable dataQuery = input.skipVerification ? null : compiledQuery(false); - - (List queryResults, List dataResults) = GetResults(query, dataQuery); - - // we skip unordered query because the LINQ results vs actual query results are non-deterministic - if (!input.skipVerification) - { - LinqTestsCommon.ValidateResults(queryResults, dataResults); - } - - string serializedResults = serializeResultsInBaseline ? - JsonConvert.SerializeObject(queryResults.Select(item => item is LinqTestObject ? item.ToString() : item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented}) : - null; - - return new LinqTestOutput(querySqlStr, serializedResults, errorMsg: null, input.inputData); - } - catch (Exception e) - { - return new LinqTestOutput(querySqlStr, serializedResults: null, errorMsg: LinqTestsCommon.BuildExceptionMessageForTest(e), inputData: input.inputData); - } - } - - public static string BuildExceptionMessageForTest(Exception ex) + { + Data response = container.CreateItemAsync(dataEntry, new Cosmos.PartitionKey(dataEntry.Pk)).Result; + } + + FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; + QueryRequestOptions requestOptions = new QueryRequestOptions(); + + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); + + // To cover both query against backend and queries on the original data using LINQ nicely, + // the LINQ expression should be written once and they should be compiled and executed against the two sources. + // That is done by using Func that take a boolean Func. The parameter of the Func indicate whether the Cosmos DB query + // or the data list should be used. When a test is executed, the compiled LINQ expression would pass different values + // to this getQuery method. + IQueryable getQuery(bool useQuery) => useQuery ? query : testData.AsQueryable(); + return getQuery; + } + + public static LinqTestOutput ExecuteTest(LinqTestInput input, bool serializeResultsInBaseline = false) + { + string querySqlStr = string.Empty; + try + { + Func compiledQuery = input.Expression.Compile(); + + IQueryable query = compiledQuery(true); + querySqlStr = JObject.Parse(query.ToString()).GetValue("query", StringComparison.Ordinal).ToString(); + + IQueryable dataQuery = input.skipVerification ? null : compiledQuery(false); + + (List queryResults, List dataResults) = GetResults(query, dataQuery); + + // we skip unordered query because the LINQ results vs actual query results are non-deterministic + if (!input.skipVerification) + { + LinqTestsCommon.ValidateResults(queryResults, dataResults); + } + + string serializedResults = serializeResultsInBaseline ? + JsonConvert.SerializeObject(queryResults.Select(item => item is LinqTestObject ? item.ToString() : item), new JsonSerializerSettings { Formatting = Newtonsoft.Json.Formatting.Indented}) : + null; + + return new LinqTestOutput(querySqlStr, serializedResults, errorMsg: null, input.inputData); + } + catch (Exception e) + { + return new LinqTestOutput(querySqlStr, serializedResults: null, errorMsg: LinqTestsCommon.BuildExceptionMessageForTest(e), inputData: input.inputData); + } + } + + public static string BuildExceptionMessageForTest(Exception ex) { StringBuilder message = new StringBuilder(); - do - { - if (ex is CosmosException cosmosException) + do + { + if (ex is CosmosException cosmosException) { // ODE scenario: The backend generates an error response message with significant variations when compared to the Service Interop which gets called in the Non ODE scenario. // The objective is to standardize and normalize the backend response for consistency. @@ -590,290 +590,290 @@ public static string BuildExceptionMessageForTest(Exception ex) else { message.Append($"Status Code: {cosmosException.StatusCode}"); - } - } - else if (ex is DocumentClientException documentClientException) - { - message.Append(documentClientException.RawErrorMessage); - } - else + } + } + else if (ex is DocumentClientException documentClientException) + { + message.Append(documentClientException.RawErrorMessage); + } + else { message.Append(ex.Message); - } - - ex = ex.InnerException; - if (ex != null) - { - message.Append(","); - } - } + } + + ex = ex.InnerException; + if (ex != null) + { + message.Append(","); + } + } while (ex != null); return message.ToString(); - } - } - - /// - /// A base class that determines equality based on its json representation - /// - public class LinqTestObject - { - private string json; - - protected virtual string SerializeForTestBaseline() - { - return JsonConvert.SerializeObject(this); - } - - public override string ToString() - { - // simple cached serialization - this.json ??= this.SerializeForTestBaseline(); - return this.json; - } - - public override bool Equals(object obj) - { - if (!(obj is LinqTestObject && - obj.GetType().IsAssignableFrom(this.GetType()) && - this.GetType().IsAssignableFrom(obj.GetType()))) return false; - if (obj == null) return false; - - return this.ToString().Equals(obj.ToString()); - } - - public override int GetHashCode() - { - return this.ToString().GetHashCode(); - } - } - - public class LinqTestInput : BaselineTestInput - { - internal static Regex classNameRegex = new Regex("(value\\(.+?\\+)?\\<\\>.+?__([A-Za-z]+)((\\d+_\\d+(`\\d+\\[.+?\\])?\\)(\\.value)?)|\\d+`\\d+)"); - internal static Regex invokeCompileRegex = new Regex("(Convert\\()?Invoke\\([^.]+\\.[^.,]+(\\.Compile\\(\\))?, b\\)(\\.Cast\\(\\))?(\\))?"); - - // As the tests are executed sequentially - // We can store the random seed in a static variable for diagnostics - internal static int RandomSeed = -1; - - internal int randomSeed = -1; - internal Expression> Expression { get; } - internal string expressionStr; - internal string inputData; - - // We skip the verification between Cosmos DB and actual query restuls in the following cases - // - unordered query since the results are not deterministics for LinQ results and actual query results - // - scenarios not supported in LINQ, e.g. sequence doesn't contain element. - internal bool skipVerification; - - internal LinqTestInput( - string description, - Expression> expr, - bool skipVerification = false, - string expressionStr = null, - string inputData = null) - : base(description) - { - this.Expression = expr ?? throw new ArgumentNullException($"{nameof(expr)} must not be null."); - this.skipVerification = skipVerification; - this.expressionStr = expressionStr; - this.inputData = inputData; - } - - public static string FilterInputExpression(string input) - { - StringBuilder expressionSb = new StringBuilder(input); - // simplify full qualified class name - // e.g. before: value(Microsoft.Azure.Documents.Services.Management.Tests.LinqSQLTranslationTest+<>c__DisplayClass7_0), after: DisplayClass - // before: <>f__AnonymousType14`2(, after: AnonymousType( - // value(Microsoft.Azure.Documents.Services.Management.Tests.LinqProviderTests.LinqTranslationBaselineTests +<> c__DisplayClass24_0`1[System.String]).value - Match match = classNameRegex.Match(expressionSb.ToString()); - while (match.Success) - { - expressionSb = expressionSb.Replace(match.Groups[0].Value, match.Groups[2].Value); - match = match.NextMatch(); - } - - // remove the Invoke().Compile() string from the Linq scanning tests - match = invokeCompileRegex.Match(expressionSb.ToString()); - while (match.Success) - { - expressionSb = expressionSb.Replace(match.Groups[0].Value, string.Empty); - match = match.NextMatch(); - } - - expressionSb.Insert(0, "query"); - - return expressionSb.ToString(); - } - - public override void SerializeAsXml(XmlWriter xmlWriter) - { - if (xmlWriter == null) - { - throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); - } - - this.expressionStr ??= LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); - - xmlWriter.WriteStartElement("Description"); - xmlWriter.WriteCData(this.Description); - xmlWriter.WriteEndElement(); - xmlWriter.WriteStartElement("Expression"); - xmlWriter.WriteCData(this.expressionStr); - xmlWriter.WriteEndElement(); - } - } - - public class LinqTestOutput : BaselineTestOutput - { - internal static Regex sdkVersion = new Regex("(,\\W*)?documentdb-dotnet-sdk[^]]+"); - internal static Regex activityId = new Regex("(,\\W*)?ActivityId:.+", RegexOptions.Multiline); - internal static Regex newLine = new Regex("(\r\n|\r|\n)"); - - internal string SqlQuery { get; } - internal string ErrorMessage { get; } - internal string Results { get; } - internal string InputData { get; } - - private static readonly Dictionary newlineKeywords = new Dictionary() { - { "SELECT", "\nSELECT" }, - { "FROM", "\nFROM" }, - { "WHERE", "\nWHERE" }, - { "JOIN", "\nJOIN" }, - { "ORDER BY", "\nORDER BY" }, + } + } + + /// + /// A base class that determines equality based on its json representation + /// + public class LinqTestObject + { + private string json; + + protected virtual string SerializeForTestBaseline() + { + return JsonConvert.SerializeObject(this); + } + + public override string ToString() + { + // simple cached serialization + this.json ??= this.SerializeForTestBaseline(); + return this.json; + } + + public override bool Equals(object obj) + { + if (!(obj is LinqTestObject && + obj.GetType().IsAssignableFrom(this.GetType()) && + this.GetType().IsAssignableFrom(obj.GetType()))) return false; + if (obj == null) return false; + + return this.ToString().Equals(obj.ToString()); + } + + public override int GetHashCode() + { + return this.ToString().GetHashCode(); + } + } + + public class LinqTestInput : BaselineTestInput + { + internal static Regex classNameRegex = new Regex("(value\\(.+?\\+)?\\<\\>.+?__([A-Za-z]+)((\\d+_\\d+(`\\d+\\[.+?\\])?\\)(\\.value)?)|\\d+`\\d+)"); + internal static Regex invokeCompileRegex = new Regex("(Convert\\()?Invoke\\([^.]+\\.[^.,]+(\\.Compile\\(\\))?, b\\)(\\.Cast\\(\\))?(\\))?"); + + // As the tests are executed sequentially + // We can store the random seed in a static variable for diagnostics + internal static int RandomSeed = -1; + + internal int randomSeed = -1; + internal Expression> Expression { get; } + internal string expressionStr; + internal string inputData; + + // We skip the verification between Cosmos DB and actual query restuls in the following cases + // - unordered query since the results are not deterministics for LinQ results and actual query results + // - scenarios not supported in LINQ, e.g. sequence doesn't contain element. + internal bool skipVerification; + + internal LinqTestInput( + string description, + Expression> expr, + bool skipVerification = false, + string expressionStr = null, + string inputData = null) + : base(description) + { + this.Expression = expr ?? throw new ArgumentNullException($"{nameof(expr)} must not be null."); + this.skipVerification = skipVerification; + this.expressionStr = expressionStr; + this.inputData = inputData; + } + + public static string FilterInputExpression(string input) + { + StringBuilder expressionSb = new StringBuilder(input); + // simplify full qualified class name + // e.g. before: value(Microsoft.Azure.Documents.Services.Management.Tests.LinqSQLTranslationTest+<>c__DisplayClass7_0), after: DisplayClass + // before: <>f__AnonymousType14`2(, after: AnonymousType( + // value(Microsoft.Azure.Documents.Services.Management.Tests.LinqProviderTests.LinqTranslationBaselineTests +<> c__DisplayClass24_0`1[System.String]).value + Match match = classNameRegex.Match(expressionSb.ToString()); + while (match.Success) + { + expressionSb = expressionSb.Replace(match.Groups[0].Value, match.Groups[2].Value); + match = match.NextMatch(); + } + + // remove the Invoke().Compile() string from the Linq scanning tests + match = invokeCompileRegex.Match(expressionSb.ToString()); + while (match.Success) + { + expressionSb = expressionSb.Replace(match.Groups[0].Value, string.Empty); + match = match.NextMatch(); + } + + expressionSb.Insert(0, "query"); + + return expressionSb.ToString(); + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + if (xmlWriter == null) + { + throw new ArgumentNullException($"{nameof(xmlWriter)} cannot be null."); + } + + this.expressionStr ??= LinqTestInput.FilterInputExpression(this.Expression.Body.ToString()); + + xmlWriter.WriteStartElement("Description"); + xmlWriter.WriteCData(this.Description); + xmlWriter.WriteEndElement(); + xmlWriter.WriteStartElement("Expression"); + xmlWriter.WriteCData(this.expressionStr); + xmlWriter.WriteEndElement(); + } + } + + public class LinqTestOutput : BaselineTestOutput + { + internal static Regex sdkVersion = new Regex("(,\\W*)?documentdb-dotnet-sdk[^]]+"); + internal static Regex activityId = new Regex("(,\\W*)?ActivityId:.+", RegexOptions.Multiline); + internal static Regex newLine = new Regex("(\r\n|\r|\n)"); + + internal string SqlQuery { get; } + internal string ErrorMessage { get; } + internal string Results { get; } + internal string InputData { get; } + + private static readonly Dictionary newlineKeywords = new Dictionary() { + { "SELECT", "\nSELECT" }, + { "FROM", "\nFROM" }, + { "WHERE", "\nWHERE" }, + { "JOIN", "\nJOIN" }, + { "ORDER BY", "\nORDER BY" }, { "OFFSET", "\nOFFSET" }, - { " )", "\n)" } - }; - - public static string FormatErrorMessage(string msg) - { - msg = newLine.Replace(msg, string.Empty); - - // remove sdk version in the error message which can change in the future. - // e.g. - msg = sdkVersion.Replace(msg, string.Empty); - - // remove activity Id - msg = activityId.Replace(msg, string.Empty); - - return msg; - } - - internal LinqTestOutput(string sqlQuery, string serializedResults, string errorMsg, string inputData) - { - this.SqlQuery = FormatSql(sqlQuery); - this.Results = serializedResults; - this.ErrorMessage = errorMsg; - this.InputData = inputData; - } - - public static String FormatSql(string sqlQuery) - { - const string subqueryCue = "(SELECT"; - bool hasSubquery = sqlQuery.IndexOf(subqueryCue, StringComparison.OrdinalIgnoreCase) > 0; - - StringBuilder sb = new StringBuilder(sqlQuery); - foreach (KeyValuePair kv in newlineKeywords) - { - sb.Replace(kv.Key, kv.Value); - } - - if (!hasSubquery) return sb.ToString(); - - const string oneTab = " "; - const string startCue = "SELECT"; - const string endCue = ")"; - - string[] tokens = sb.ToString().Split('\n'); - bool firstSelect = true; - sb.Length = 0; - StringBuilder indentSb = new StringBuilder(); - for (int i = 0; i < tokens.Length; ++i) - { - if (tokens[i].StartsWith(startCue, StringComparison.OrdinalIgnoreCase)) - { - if (!firstSelect) indentSb.Append(oneTab); else firstSelect = false; - - } - else if (tokens[i].StartsWith(endCue, StringComparison.OrdinalIgnoreCase)) - { - indentSb.Length -= oneTab.Length; - } - - sb.Append(indentSb).Append(tokens[i]).Append("\n"); - } - - return sb.ToString(); - } - - public override void SerializeAsXml(XmlWriter xmlWriter) - { - xmlWriter.WriteStartElement(nameof(this.SqlQuery)); - xmlWriter.WriteCData(this.SqlQuery); - xmlWriter.WriteEndElement(); - if (this.InputData != null) - { - xmlWriter.WriteStartElement("InputData"); - xmlWriter.WriteCData(this.InputData); - xmlWriter.WriteEndElement(); - } - if (this.Results != null) - { - xmlWriter.WriteStartElement("Results"); - xmlWriter.WriteCData(this.Results); - xmlWriter.WriteEndElement(); - } - if (this.ErrorMessage != null) - { - xmlWriter.WriteStartElement("ErrorMessage"); - xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.ErrorMessage)); - xmlWriter.WriteEndElement(); - } - } - } - - class SystemTextJsonLinqSerializer : CosmosLinqSerializer - { - private readonly JsonObjectSerializer systemTextJsonSerializer; - - public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) - { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); - } - - public override T FromStream(Stream stream) - { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); - - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } - - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } - - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } - } - - public override Stream ToStream(T input) - { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); - streamPayload.Position = 0; - return streamPayload; - } - - public override string SerializeMemberName(MemberInfo memberInfo) - { + { "GROUP BY", "\nGROUP BY" }, + { " )", "\n)" } + }; + + public static string FormatErrorMessage(string msg) + { + msg = newLine.Replace(msg, string.Empty); + + // remove sdk version in the error message which can change in the future. + // e.g. + msg = sdkVersion.Replace(msg, string.Empty); + + // remove activity Id + msg = activityId.Replace(msg, string.Empty); + + return msg; + } + + internal LinqTestOutput(string sqlQuery, string serializedResults, string errorMsg, string inputData) + { + this.SqlQuery = FormatSql(sqlQuery); + this.Results = serializedResults; + this.ErrorMessage = errorMsg; + this.InputData = inputData; + } + + public static String FormatSql(string sqlQuery) + { + const string subqueryCue = "(SELECT"; + bool hasSubquery = sqlQuery.IndexOf(subqueryCue, StringComparison.OrdinalIgnoreCase) > 0; + + StringBuilder sb = new StringBuilder(sqlQuery); + foreach (KeyValuePair kv in newlineKeywords) + { + sb.Replace(kv.Key, kv.Value); + } + + if (!hasSubquery) return sb.ToString(); + + const string oneTab = " "; + const string startCue = "SELECT"; + const string endCue = ")"; + string[] tokens = sb.ToString().Split('\n'); + bool firstSelect = true; + sb.Length = 0; + StringBuilder indentSb = new StringBuilder(); + for (int i = 0; i < tokens.Length; ++i) + { + if (tokens[i].StartsWith(startCue, StringComparison.OrdinalIgnoreCase)) + { + if (!firstSelect) indentSb.Append(oneTab); else firstSelect = false; + + } + else if (tokens[i].StartsWith(endCue, StringComparison.OrdinalIgnoreCase)) + { + indentSb.Length -= oneTab.Length; + } + + sb.Append(indentSb).Append(tokens[i]).Append("\n"); + } + + return sb.ToString(); + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteStartElement(nameof(this.SqlQuery)); + xmlWriter.WriteCData(this.SqlQuery); + xmlWriter.WriteEndElement(); + if (this.InputData != null) + { + xmlWriter.WriteStartElement("InputData"); + xmlWriter.WriteCData(this.InputData); + xmlWriter.WriteEndElement(); + } + if (this.Results != null) + { + xmlWriter.WriteStartElement("Results"); + xmlWriter.WriteCData(this.Results); + xmlWriter.WriteEndElement(); + } + if (this.ErrorMessage != null) + { + xmlWriter.WriteStartElement("ErrorMessage"); + xmlWriter.WriteCData(LinqTestOutput.FormatErrorMessage(this.ErrorMessage)); + xmlWriter.WriteEndElement(); + } + } + } + + class SystemTextJsonLinqSerializer : CosmosLinqSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + + public override string SerializeMemberName(MemberInfo memberInfo) + { System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); if (jsonExtensionDataAttribute != null) @@ -881,52 +881,52 @@ public override string SerializeMemberName(MemberInfo memberInfo) return null; } - JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); - - string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) - ? jsonPropertyNameAttribute.Name - : memberInfo.Name; - - return memberName; - } + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + + string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) + ? jsonPropertyNameAttribute.Name + : memberInfo.Name; + + return memberName; + } } - class SystemTextJsonSerializer : CosmosSerializer - { - private readonly JsonObjectSerializer systemTextJsonSerializer; - - public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) - { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); - } - - public override T FromStream(Stream stream) - { - if (stream == null) - throw new ArgumentNullException(nameof(stream)); - - using (stream) - { - if (stream.CanSeek && stream.Length == 0) - { - return default; - } - - if (typeof(Stream).IsAssignableFrom(typeof(T))) - { - return (T)(object)stream; - } - - return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - } - } - - public override Stream ToStream(T input) - { - MemoryStream streamPayload = new MemoryStream(); - this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); - streamPayload.Position = 0; - return streamPayload; - } - } -} + class SystemTextJsonSerializer : CosmosSerializer + { + private readonly JsonObjectSerializer systemTextJsonSerializer; + + public SystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) + { + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + } + + public override T FromStream(Stream stream) + { + if (stream == null) + throw new ArgumentNullException(nameof(stream)); + + using (stream) + { + if (stream.CanSeek && stream.Length == 0) + { + return default; + } + + if (typeof(Stream).IsAssignableFrom(typeof(T))) + { + return (T)(object)stream; + } + + return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); + } + } + + public override Stream ToStream(T input) + { + MemoryStream streamPayload = new MemoryStream(); + this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); + streamPayload.Position = 0; + return streamPayload; + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 0cb2585dc5..509e89c0a6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -193,6 +193,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/GroupByClauseSqlParserBaselineTests.Tests.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/GroupByClauseSqlParserBaselineTests.Tests.xml index 0241dc23ec..db690101d1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/GroupByClauseSqlParserBaselineTests.Tests.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/GroupByClauseSqlParserBaselineTests.Tests.xml @@ -5,7 +5,7 @@ - + @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SqlObjectVisitorBaselineTests.SqlQueries.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SqlObjectVisitorBaselineTests.SqlQueries.xml index fe02fc060b..94eeeffc08 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SqlObjectVisitorBaselineTests.SqlQueries.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SqlObjectVisitorBaselineTests.SqlQueries.xml @@ -989,16 +989,17 @@ OFFSET 0 LIMIT 0 }]]> - + -245344741 - + @@ -1127,18 +1128,19 @@ OFFSET 0 LIMIT 0 }]]> - + 51808704 - + @@ -1267,18 +1269,19 @@ OFFSET 0 LIMIT 0 }]]> - + -1922520573 - + @@ -1407,18 +1410,19 @@ ARRAY( }]]> - + 1317938775 - + \ No newline at end of file From e04ce514f850cdcaa003b64ec19384662c53e18a Mon Sep 17 00:00:00 2001 From: kevin-montrose Date: Mon, 1 Apr 2024 17:34:37 -0400 Subject: [PATCH 303/337] Performance: Refactors query prefetch mechanism (#4361) * sketch out improved ParallelPrefetcher; focus is on reducing allocations, but we also can't be substantially slower to start all tasks * little more cleanup to further reduce allocations, and save a tiny amount of CPU * start on testing * some tweaks and testing for buffer management * test exception handling; fix a bug in high concurrency case that would swallow exceptions * test cancellation * more testing, a little bit of cleanup * test the case where the enumerator faults; fixes a couple leaks of Tasks and buffers that could occur in that some places * tiny bit of cleanup * cleanup and expand comments; code is tricky, it needs documentation * address a whole bunch of style nits, just to keep compiler Message counts down * address some feedback on comment clarity * don't rely on finalizers for testing, it's too brittle; hold up was not allocating more in the non-test cases, but found a field to reuse; needs benchmarking * complete ITrace proxy for testing * style nits and a bit more commentary * explicit test for concurrent access to the inner IEnumerator * explicit test that IEnumerator is disposed * explicitly implement all ITrace members * address feedback: internal class members should be public or private * address feedback: break test-only bits of ParallelPrefetch out into a partial * address feedback: move const above type declarations * address feedback: naming nits * address feedback: use the existing NoOpTrace * address feedback: remove pointless using * update baseline trace text for QueryAsync test --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> --- .../Pagination/ParallelPrefetch.Testing.cs | 121 ++ .../src/Pagination/ParallelPrefetch.cs | 736 +++++++++- ...EndTraceWriterBaselineTests.QueryAsync.xml | 35 - .../Pagination/ParallelPrefetchTests.cs | 1255 +++++++++++++++++ 4 files changed, 2081 insertions(+), 66 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.Testing.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/ParallelPrefetchTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.Testing.cs b/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.Testing.cs new file mode 100644 index 0000000000..b37fa2f456 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.Testing.cs @@ -0,0 +1,121 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Pagination +{ + using System; + using System.Buffers; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Tracing; + + /// + /// Holds the "just for testing"-bits of . + /// + internal static partial class ParallelPrefetch + { + /// + /// For testing purposes, provides ways to instrument . + /// + /// You shouldn't be using this outside of test projects. + /// + internal sealed class ParallelPrefetchTestConfig : ITrace + { + private ITrace innerTrace; + + private int startedTasks; + private int awaitedTasks; + + public ArrayPool PrefetcherPool { get; private set; } + public ArrayPool TaskPool { get; private set; } + public ArrayPool ObjectPool { get; private set; } + + public int StartedTasks + => this.startedTasks; + + public int AwaitedTasks + => this.awaitedTasks; + + string ITrace.Name => this.innerTrace.Name; + + Guid ITrace.Id => this.innerTrace.Id; + + DateTime ITrace.StartTime => this.innerTrace.StartTime; + + TimeSpan ITrace.Duration => this.innerTrace.Duration; + + TraceLevel ITrace.Level => this.innerTrace.Level; + + TraceComponent ITrace.Component => this.innerTrace.Component; + + TraceSummary ITrace.Summary => this.innerTrace.Summary; + + ITrace ITrace.Parent => this.innerTrace.Parent; + + IReadOnlyList ITrace.Children => this.innerTrace.Children; + + IReadOnlyDictionary ITrace.Data => this.innerTrace.Data; + + public ParallelPrefetchTestConfig( + ArrayPool prefetcherPool, + ArrayPool taskPool, + ArrayPool objectPool) + { + this.PrefetcherPool = prefetcherPool; + this.TaskPool = taskPool; + this.ObjectPool = objectPool; + } + + public void SetInnerTrace(ITrace trace) + { + this.innerTrace = trace; + } + + public void TaskStarted() + { + Interlocked.Increment(ref this.startedTasks); + } + + public void TaskAwaited() + { + Interlocked.Increment(ref this.awaitedTasks); + } + + ITrace ITrace.StartChild(string name) + { + return this.innerTrace.StartChild(name); + } + + ITrace ITrace.StartChild(string name, TraceComponent component, TraceLevel level) + { + return this.innerTrace.StartChild(name, component, level); + } + + void ITrace.AddDatum(string key, TraceDatum traceDatum) + { + this.innerTrace.AddDatum(key, traceDatum); + } + + void ITrace.AddDatum(string key, object value) + { + this.innerTrace.AddDatum(key, value); + } + + void ITrace.AddOrUpdateDatum(string key, object value) + { + this.innerTrace.AddOrUpdateDatum(key, value); + } + + void ITrace.AddChild(ITrace trace) + { + this.innerTrace.AddChild(trace); + } + + void IDisposable.Dispose() + { + this.innerTrace.Dispose(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.cs b/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.cs index 56bc732658..c4782329f7 100644 --- a/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.cs +++ b/Microsoft.Azure.Cosmos/src/Pagination/ParallelPrefetch.cs @@ -5,73 +5,747 @@ namespace Microsoft.Azure.Cosmos.Pagination { using System; + using System.Buffers; using System.Collections.Generic; + using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Tracing; - internal static class ParallelPrefetch + internal static partial class ParallelPrefetch { - public static async Task PrefetchInParallelAsync( + /// + /// Number of tasks started at one time, maximum, when working through prefetchers. + /// + /// Also used as a the limit between Low and High concurrency implementations. + /// + /// This number should be reasonable large, but less than the point where a + /// Task[BatchLimit] ends up on the LOH (which will be around 8,192). + /// + private const int BatchLimit = 512; + + /// + /// Common state that is needed for all tasks started via , unless + /// certain special cases hold. + /// + /// Also used as a synchronization primitive. + /// + private sealed class CommonPrefetchState + { + // we also use this to signal if we're finished enumerating, to save space + private IEnumerator enumerator; + + /// + /// If this is true, it's a signal that new work should not be queued up. + /// + public bool FinishedEnumerating + => Volatile.Read(ref this.enumerator) == null; + + /// + /// Common to be used by all tasks. + /// + /// When testing, this can also include be a . + /// We reuse this to keep allocations down in non-test cases. + /// + public ITrace PrefetchTrace { get; private set; } + + /// + /// The which will produce the next + /// to use. + /// + /// Once at least one Task been started, should only be accessed under a lock. + /// + /// If == true, this returns null. + /// + public IEnumerator Enumerator + => Volatile.Read(ref this.enumerator); + + /// + /// provided via . + /// + public CancellationToken CancellationToken { get; private set; } + + public CommonPrefetchState(ITrace prefetchTrace, IEnumerator enumerator, CancellationToken cancellationToken) + { + this.PrefetchTrace = prefetchTrace; + this.enumerator = enumerator; + this.CancellationToken = cancellationToken; + } + + /// + /// Cause to return true. + /// + public void SetFinishedEnumerating() + { + Volatile.Write(ref this.enumerator, null); + } + } + + /// + /// State passed when we start a Task with an initial . + /// + /// That started Task will obtain it's next IPrefetchers using the + /// that is also provided. + /// + private sealed class SinglePrefetchState + { + /// + /// State common to the whole call. + /// + public CommonPrefetchState CommonState { get; private set; } + + /// + /// which must be invoked next. + /// + public IPrefetcher CurrentPrefetcher { get; set; } + + public SinglePrefetchState(CommonPrefetchState commonState, IPrefetcher initialPrefetcher) + { + this.CommonState = commonState; + this.CurrentPrefetcher = initialPrefetcher; + } + } + + public static Task PrefetchInParallelAsync( + IEnumerable prefetchers, + int maxConcurrency, + ITrace trace, + CancellationToken cancellationToken) + { + prefetchers = prefetchers ?? throw new ArgumentNullException(nameof(prefetchers)); + trace = trace ?? throw new ArgumentNullException(nameof(trace)); + + return PrefetchInParallelCoreAsync(prefetchers, maxConcurrency, trace, null, cancellationToken); + } + + /// + /// Exposed for testing purposes, do not call directly. + /// + public static Task PrefetchInParallelCoreAsync( IEnumerable prefetchers, int maxConcurrency, ITrace trace, + ParallelPrefetchTestConfig config, CancellationToken cancellationToken) { - if (prefetchers == null) + if (maxConcurrency <= 0) + { + // old code would just... allocate and then do nothing + // + // so we do nothing here, for compatability purposes + return Task.CompletedTask; + } + else if (maxConcurrency == 1) + { + return SingleConcurrencyPrefetchInParallelAsync(prefetchers, trace, config, cancellationToken); + } + else if (maxConcurrency <= BatchLimit) { - throw new ArgumentNullException(nameof(prefetchers)); + return LowConcurrencyPrefetchInParallelAsync(prefetchers, maxConcurrency, trace, config, cancellationToken); } + else + { + return HighConcurrencyPrefetchInParallelAsync(prefetchers, maxConcurrency, trace, config, cancellationToken); + } + } + + /// + /// Shared code for starting traces while prefetching. + /// + private static ITrace CommonStartTrace(ITrace trace) + { + return trace.StartChild(name: "Prefetching", TraceComponent.Pagination, TraceLevel.Info); + } - if (trace == null) + /// + /// Helper for grabbing a reusable array. + /// + private static T[] RentArray(ParallelPrefetchTestConfig config, int minSize, bool clear) + { + T[] result; + if (config != null) { - throw new ArgumentNullException(nameof(trace)); +#pragma warning disable IDE0045 // Convert to conditional expression - chained else if is clearer + if (typeof(T) == typeof(IPrefetcher)) + { + result = (T[])(object)config.PrefetcherPool.Rent(minSize); + } + else if (typeof(T) == typeof(Task)) + { + result = (T[])(object)config.TaskPool.Rent(minSize); + } + else + { + result = (T[])(object)config.ObjectPool.Rent(minSize); + } +#pragma warning restore IDE0045 + } + else + { + result = ArrayPool.Shared.Rent(minSize); } - using (ITrace prefetchTrace = trace.StartChild(name: "Prefetching", TraceComponent.Pagination, TraceLevel.Info)) + if (clear) { - HashSet tasks = new HashSet(); - IEnumerator prefetchersEnumerator = prefetchers.GetEnumerator(); - for (int i = 0; i < maxConcurrency; i++) + Array.Clear(result, 0, result.Length); + } + + return result; + } + + /// + /// Helper for returning arrays what were rented via . + /// + private static void ReturnRentedArray(ParallelPrefetchTestConfig config, T[] array, int clearThrough) + { + if (array == null) + { + return; + } + + // this is important, otherwise we might leave Tasks and IPrefetchers + // rooted long enough to cause problems + Array.Clear(array, 0, clearThrough); + + if (config != null) + { + if (typeof(T) == typeof(IPrefetcher)) { - if (!prefetchersEnumerator.MoveNext()) + config.PrefetcherPool.Return((IPrefetcher[])(object)array); + } + else if (typeof(T) == typeof(Task)) + { + config.TaskPool.Return((Task[])(object)array); + } + else + { + config.ObjectPool.Return((object[])(object)array); + } + } + else + { + ArrayPool.Shared.Return(array); + } + } + + /// + /// Starts a new Task that first calls on the passed + /// , and then grabs new ones from and repeats the process + /// until either the enumerator finishes or something sets . + /// + private static Task CommonStartTaskAsync(ParallelPrefetchTestConfig config, CommonPrefetchState commonState, IPrefetcher firstPrefetcher) + { + config?.TaskStarted(); + + SinglePrefetchState state = new (commonState, firstPrefetcher); + + // this is mimicing the behavior of Task.Run(...) (that is, default CancellationToken, default Scheduler, DenyAttachChild, etc.) + // but in a way that let's us pass a context object + // + // this lets us declare a static delegate, and thus let's compiler reuse the delegate allocation + Task taskLoop = + Task.Factory.StartNew( + static async (context) => { - break; - } + // this method is structured a bit oddly to prevent the compiler from putting more data into the + // state of the Task - basically, don't have any locals (except context) that survive across an await + // + // we could go harder here and just not use async/await but that's awful for maintainability + try + { + while (true) + { + // step up to the initial await + { + SinglePrefetchState innerState = (SinglePrefetchState)context; + + CommonPrefetchState innerCommonState = innerState.CommonState; + (ITrace prefetchTrace, CancellationToken cancellationToken) = (innerCommonState.PrefetchTrace, innerCommonState.CancellationToken); + + // we smuggle a test config in as the common ITrace + // + // in most code, this will be null - but this pattern + // let's use keep CommonPrefetchState small + ParallelPrefetchTestConfig config = prefetchTrace as ParallelPrefetchTestConfig; + + config?.TaskStarted(); + config?.TaskAwaited(); + await innerState.CurrentPrefetcher.PrefetchAsync(prefetchTrace, cancellationToken); + } + + // step for preparing the next prefetch + { + SinglePrefetchState innerState = (SinglePrefetchState)context; - IPrefetcher prefetcher = prefetchersEnumerator.Current; - tasks.Add(Task.Run(async () => await prefetcher.PrefetchAsync(prefetchTrace, cancellationToken))); + CommonPrefetchState innerCommonState = innerState.CommonState; + + if (innerCommonState.FinishedEnumerating) + { + // we're done, bail + return; + } + + // proceed to the next item + // + // we need this lock because at this point there + // are other Tasks potentially also looking to call + // enumerator.MoveNext() + lock (innerCommonState) + { + // this can have transitioned to null since we last checked + // so this is basically double-check locking + IEnumerator enumerator = innerCommonState.Enumerator; + if (enumerator == null) + { + return; + } + + if (!enumerator.MoveNext()) + { + // we're done, signal to every other task to also bail + innerCommonState.SetFinishedEnumerating(); + + return; + } + + // move on to the new IPrefetcher just obtained + innerState.CurrentPrefetcher = enumerator.Current; + } + } + } + } + catch + { + SinglePrefetchState innerState = (SinglePrefetchState)context; + + // some error was encountered, we should tell other tasks to stop starting new prefetch tasks + // because we're about to cancel + innerState.CommonState.SetFinishedEnumerating(); + + // percolate the error up + throw; + } + }, + state, + default, + TaskCreationOptions.DenyChildAttach, + TaskScheduler.Default); + + // we _could_ maybe optimize this more... perhaps using a SemaphoreSlim or something + // but that complicates error reporting and is also awful for maintability + Task unwrapped = taskLoop.Unwrap(); + + return unwrapped; + } + + /// + /// Fills a portion of an IPrefetcher[] using the passed enumerator. + /// + /// Returns the index that would next be filled. + /// + /// Updates the passed if the end of the enumerator is reached. + /// + /// Synchronization is the concern of the caller, not this method. + /// + private static int FillPrefetcherBuffer(CommonPrefetchState commonState, IPrefetcher[] prefetchers, int startIndex, int endIndex, IEnumerator enumerator) + { + int curIndex; + for (curIndex = startIndex; curIndex < endIndex; curIndex++) + { + if (!enumerator.MoveNext()) + { + commonState.SetFinishedEnumerating(); + break; } - while (tasks.Count != 0) + prefetchers[curIndex] = enumerator.Current; + } + + return curIndex; + } + + /// + /// Special case for when maxConcurrency == 1. + /// + /// This devolves into a foreach loop. + /// + private static async Task SingleConcurrencyPrefetchInParallelAsync(IEnumerable prefetchers, ITrace trace, ParallelPrefetchTestConfig config, CancellationToken cancellationToken) + { + using (ITrace prefetchTrace = CommonStartTrace(trace)) + { + foreach (IPrefetcher prefetcher in prefetchers) { - Task completedTask = await Task.WhenAny(tasks); - tasks.Remove(completedTask); - try - { - await completedTask; - } - catch + config?.TaskStarted(); + config?.TaskAwaited(); + await prefetcher.PrefetchAsync(prefetchTrace, cancellationToken); + } + } + } + + /// + /// The case where maxConcurrency is less than or equal to BatchLimit. + /// + /// This starts up to maxConcurrency simultanous Tasks, doing so in a way that + /// requires rented arrays of maxConcurrency size. + /// + private static async Task LowConcurrencyPrefetchInParallelAsync( + IEnumerable prefetchers, + int maxConcurrency, + ITrace trace, + ParallelPrefetchTestConfig config, + CancellationToken cancellationToken) + { + IPrefetcher[] initialPrefetchers = null; + Task[] runningTasks = null; + + int nextPrefetcherIndex = 0; + int nextRunningTaskIndex = 0; + + try + { + using (ITrace prefetchTrace = CommonStartTrace(trace)) + { + config?.SetInnerTrace(prefetchTrace); + + using (IEnumerator enumerator = prefetchers.GetEnumerator()) { - // Observe the remaining tasks - try + if (!enumerator.MoveNext()) { - await Task.WhenAll(tasks); + // literally nothing to prefetch + return; } - catch + + IPrefetcher first = enumerator.Current; + + if (!enumerator.MoveNext()) { + // special case: a single prefetcher... just await it, and skip all the heavy work + config?.TaskStarted(); + config?.TaskAwaited(); + await first.PrefetchAsync(prefetchTrace, cancellationToken); + return; } - throw; + // need to actually do things to start prefetching in parallel + // so grab some state and stash the first two prefetchers off + + initialPrefetchers = RentArray(config, maxConcurrency, clear: false); + initialPrefetchers[0] = first; + initialPrefetchers[1] = enumerator.Current; + + CommonPrefetchState commonState = new (config ?? prefetchTrace, enumerator, cancellationToken); + + // batch up a bunch of IPrefetchers to kick off + // + // we do this separately from starting the Tasks so we can avoid a lock + // and quicky get to maxConcurrency degrees of parallelism + nextPrefetcherIndex = FillPrefetcherBuffer(commonState, initialPrefetchers, 2, maxConcurrency, enumerator); + + // actually start all the tasks, stashing them in a rented Task[] + runningTasks = RentArray(config, nextPrefetcherIndex, clear: false); + + for (nextRunningTaskIndex = 0; nextRunningTaskIndex < nextPrefetcherIndex; nextRunningTaskIndex++) + { + IPrefetcher toStart = initialPrefetchers[nextRunningTaskIndex]; + Task startedTask = CommonStartTaskAsync(config, commonState, toStart); + + runningTasks[nextRunningTaskIndex] = startedTask; + } + + // hand the prefetcher array back early, so other callers can use it + ReturnRentedArray(config, initialPrefetchers, nextPrefetcherIndex); + initialPrefetchers = null; + + // now await all Tasks in turn + for (int toAwaitTaskIndex = 0; toAwaitTaskIndex < nextRunningTaskIndex; toAwaitTaskIndex++) + { + Task toAwait = runningTasks[toAwaitTaskIndex]; + + try + { + config?.TaskAwaited(); + await toAwait; + } + catch + { + // if we encountered some exception, tell the remaining tasks to bail + // the next time they check commonState + commonState.SetFinishedEnumerating(); + + // we still need to observe all the tasks we haven't yet to avoid an UnobservedTaskException + for (int awaitAndIgnoreTaskIndex = toAwaitTaskIndex + 1; awaitAndIgnoreTaskIndex < nextRunningTaskIndex; awaitAndIgnoreTaskIndex++) + { + try + { + config?.TaskAwaited(); + await runningTasks[awaitAndIgnoreTaskIndex]; + } + catch + { + // intentionally left empty, we swallow all errors after the first + } + } + + throw; + } + } } + } + } + finally + { + ReturnRentedArray(config, initialPrefetchers, nextPrefetcherIndex); + ReturnRentedArray(config, runningTasks, nextRunningTaskIndex); + } + } - if (prefetchersEnumerator.MoveNext()) + /// + /// The case where maxConcurrency is greater than BatchLimit. + /// + /// This starts up to maxConcurrency simultanous Tasks, doing so in batches + /// of BatchLimit (or less) size. Active Tasks are tracked in a psuedo-linked-list + /// over rented object[]. + /// + /// This is more complicated, less likely to hit maxConcurrency degrees of + /// parallelism, and less allocation efficient when compared to LowConcurrencyPrefetchInParallelAsync. + /// + /// However, it doesn't allocate gigantic arrays and doesn't wait for full enumeration + /// before starting to prefetch. + /// + private static async Task HighConcurrencyPrefetchInParallelAsync( + IEnumerable prefetchers, + int maxConcurrency, + ITrace trace, + ParallelPrefetchTestConfig config, + CancellationToken cancellationToken) + { + IPrefetcher[] currentBatch = null; + + // this ends up holding a sort of linked list where + // each entry is actually a Task until the very last one + // which is an object[] + // + // as soon as a null is encountered, either where a Task or + // an object[] is expected, the linked list is done + object[] runningTasks = null; + + try + { + using (ITrace prefetchTrace = CommonStartTrace(trace)) + { + config?.SetInnerTrace(prefetchTrace); + + using (IEnumerator enumerator = prefetchers.GetEnumerator()) { - IPrefetcher bufferable = prefetchersEnumerator.Current; - tasks.Add(Task.Run(async () => await bufferable.PrefetchAsync(prefetchTrace, cancellationToken))); + if (!enumerator.MoveNext()) + { + // no prefetchers at all + return; + } + + IPrefetcher first = enumerator.Current; + + if (!enumerator.MoveNext()) + { + // special case: a single prefetcher... just await it, and skip all the heavy work + config?.TaskStarted(); + config?.TaskAwaited(); + await first.PrefetchAsync(prefetchTrace, cancellationToken); + return; + } + + // need to actually do things to start prefetching in parallel + // so grab some state and stash the first two prefetchers off + + currentBatch = RentArray(config, BatchLimit, clear: false); + currentBatch[0] = first; + currentBatch[1] = enumerator.Current; + + // we need this all null because we use null as a stopping condition later + runningTasks = RentArray(config, BatchLimit, clear: true); + + CommonPrefetchState commonState = new (config ?? prefetchTrace, enumerator, cancellationToken); + + // what we do here is buffer up to BatchLimit IPrefetchers to start + // and then... start them all + // + // we stagger this so we quickly get a bunch of tasks started without spending too + // much time pre-loading everything + + // grab our first bunch of prefetchers outside of the lock + // + // we know that maxConcurrency > BatchLimit, so can just pass it as our cutoff here + int bufferedPrefetchers = FillPrefetcherBuffer(commonState, currentBatch, 2, BatchLimit, enumerator); + + int nextChunkIndex = 0; + object[] currentChunk = runningTasks; + + int remainingConcurrency = maxConcurrency; + + // if we encounter any error, we remember it + // but as soon as we start a single task we've got + // to see most of this code through so we observe them + ExceptionDispatchInfo capturedException = null; + + while (true) + { + // start and store the last set of Tasks we got from FillPrefetcherBuffer + for (int toStartIndex = 0; toStartIndex < bufferedPrefetchers; toStartIndex++) + { + IPrefetcher prefetcher = currentBatch[toStartIndex]; + Task startedTask = CommonStartTaskAsync(config, commonState, prefetcher); + + currentChunk[nextChunkIndex] = startedTask; + nextChunkIndex++; + + // check if we need a new slab to store tasks + if (nextChunkIndex == currentChunk.Length - 1) + { + // we need this all null because we use null as a stopping condition later + object[] newChunk = RentArray(config, BatchLimit, clear: true); + + currentChunk[currentChunk.Length - 1] = newChunk; + + currentChunk = newChunk; + nextChunkIndex = 0; + } + } + + remainingConcurrency -= bufferedPrefetchers; + + // check to see if we've started all the concurrent Tasks we can + if (remainingConcurrency == 0) + { + break; + } + + int nextBatchSizeLimit = remainingConcurrency < BatchLimit ? remainingConcurrency : BatchLimit; + + // if one of the previously started Tasks exhausted the enumerator + // we're done, even if we still have space + if (commonState.FinishedEnumerating) + { + break; + } + + // now that Tasks have started, we MUST synchronize access to + // the enumerator + lock (commonState) + { + // the answer might have changed, so we double-check + // this once we've got the lock + if (commonState.FinishedEnumerating) + { + break; + } + + // grab the next set of prefetchers to start + try + { + bufferedPrefetchers = FillPrefetcherBuffer(commonState, currentBatch, 0, nextBatchSizeLimit, enumerator); + } + catch (Exception exc) + { + // this can get raised if the enumerator faults + // + // in this case we might have some tasks started, and so we need to _stop_ starting new tasks but + // still move on to observing everything we've already started + + commonState.SetFinishedEnumerating(); + capturedException = ExceptionDispatchInfo.Capture(exc); + + break; + } + } + + // if we got nothing back, we can break right here + if (bufferedPrefetchers == 0) + { + break; + } + } + + // hand the prefetch array back, we're done with it + ReturnRentedArray(config, currentBatch, BatchLimit); + currentBatch = null; + + // now wait for all the tasks to complete + // + // we walk through all of them, even if we encounter an error + // because we need to walk the whole linked-list and this is + // simpler than an explicit error code path + + int toAwaitIndex = 0; + while (runningTasks != null) + { + Task toAwait = (Task)runningTasks[toAwaitIndex]; + + // if we see a null, we're done + if (toAwait == null) + { + // hand the last of the arrays back + ReturnRentedArray(config, runningTasks, toAwaitIndex); + runningTasks = null; + + break; + } + + try + { + config?.TaskAwaited(); + await toAwait; + } + catch (Exception ex) + { + if (capturedException == null) + { + // if we encountered some exception, tell the remaining tasks to bail + // the next time they check commonState + commonState.SetFinishedEnumerating(); + + // save the exception so we can rethrow it later + capturedException = ExceptionDispatchInfo.Capture(ex); + } + } + + // advance, moving to the next chunk if we've hit that limit + toAwaitIndex++; + + if (toAwaitIndex == runningTasks.Length - 1) + { + object[] oldChunk = runningTasks; + + runningTasks = (object[])runningTasks[runningTasks.Length - 1]; + toAwaitIndex = 0; + + // we're done with this, let some other caller reuse it immediately + ReturnRentedArray(config, oldChunk, oldChunk.Length); + } + } + + // fault, if any task failed, after we've finished cleaning up + capturedException?.Throw(); } } } + finally + { + // cleanup if something went wrong while these were still rented + // + // this can basically only happen if the enumerator itself faults + // which is unlikely, but far from impossible + + ReturnRentedArray(config, currentBatch, BatchLimit); + + while (runningTasks != null) + { + object[] oldChunk = runningTasks; + + runningTasks = (object[])runningTasks[runningTasks.Length - 1]; + + ReturnRentedArray(config, oldChunk, oldChunk.Length); + } + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 7577f2ae4f..460eaa593c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -41,7 +41,6 @@ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -246,10 +245,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -771,7 +766,6 @@ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -980,10 +974,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -1522,7 +1512,6 @@ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1727,10 +1716,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -2253,7 +2238,6 @@ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2462,10 +2446,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -3028,7 +3008,6 @@ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3287,10 +3266,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -3834,7 +3809,6 @@ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -4057,10 +4031,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, @@ -4588,7 +4558,6 @@ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Prefetching(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -4815,10 +4784,6 @@ "name": "MoveNextAsync", "duration in milliseconds": 0, "children": [ - { - "name": "Prefetching", - "duration in milliseconds": 0 - }, { "name": "[,05C1CFFFFFFFF8) move next", "duration in milliseconds": 0, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/ParallelPrefetchTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/ParallelPrefetchTests.cs new file mode 100644 index 0000000000..84511c8337 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/ParallelPrefetchTests.cs @@ -0,0 +1,1255 @@ +namespace Microsoft.Azure.Cosmos.Tests.Pagination +{ + using System; + using System.Buffers; + using System.Collections; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class ParallelPrefetchTests + { + /// + /// IPrefetcher which can only be run once, and invokes callbacks as it executes. + /// + private sealed class TestOncePrefetcher : IPrefetcher + { + private int hasRun; + + private readonly Action beforeAwait; + private readonly Action afterAwait; + + internal TestOncePrefetcher(Action beforeAwait, Action afterAwait) + { + this.hasRun = 0; + this.beforeAwait = beforeAwait; + this.afterAwait = afterAwait; + } + + public async ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) + { + // test that ParallelPrefetch doesn't start the same Task twice. + int oldRun = Interlocked.Exchange(ref this.hasRun, 1); + Assert.AreEqual(0, oldRun); + + // we use two callbacks to test that ParallelPrefetch is correctly monitoring + // continuations - without this, we might incorrectly consider a Task completed + // despite it awaiting an inner Task + + this.beforeAwait(); + + await Task.Yield(); + cancellationToken.ThrowIfCancellationRequested(); + + this.afterAwait(); + cancellationToken.ThrowIfCancellationRequested(); + } + } + + /// + /// IPrefetcher that does complicated things. + /// + private sealed class ComplicatedPrefetcher : IPrefetcher + { + public long StartTimestamp { get; private set; } + public long AfterYieldTimestamp { get; private set; } + public long AfterDelay1Timestamp { get; private set; } + public long AfterSemaphoreTimestamp { get; private set; } + public long AfterDelay2Timestamp { get; private set; } + public long AfterDelay3Timestamp { get; private set; } + public long AfterDelay4Timestamp { get; private set; } + public long WhenAllTimestamp { get; private set; } + public long EndTimestamp { get; private set; } + + public async ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) + { + this.StartTimestamp = Stopwatch.GetTimestamp(); + + await Task.Yield(); + + this.AfterYieldTimestamp = Stopwatch.GetTimestamp(); + + using (SemaphoreSlim semaphore = new(0, 1)) + { + Task delay = Task.Delay(5, cancellationToken).ContinueWith(_ => { this.AfterDelay1Timestamp = Stopwatch.GetTimestamp(); semaphore.Release(); }, cancellationToken); + + await semaphore.WaitAsync(cancellationToken); + this.AfterSemaphoreTimestamp = Stopwatch.GetTimestamp(); + + await delay; + } + + await Task.WhenAll( + Task.Delay(2, cancellationToken).ContinueWith(_ => this.AfterDelay2Timestamp = Stopwatch.GetTimestamp(), cancellationToken), + Task.Delay(3, cancellationToken).ContinueWith(_ => this.AfterDelay3Timestamp = Stopwatch.GetTimestamp(), cancellationToken), + Task.Delay(4, cancellationToken).ContinueWith(_ => this.AfterDelay4Timestamp = Stopwatch.GetTimestamp(), cancellationToken)); + this.WhenAllTimestamp = Stopwatch.GetTimestamp(); + + await Task.Yield(); + + this.EndTimestamp = Stopwatch.GetTimestamp(); + } + + internal void AssertCorrect() + { + Assert.IsTrue(this.StartTimestamp > 0); + + Assert.IsTrue(this.AfterYieldTimestamp > this.StartTimestamp); + Assert.IsTrue(this.AfterDelay1Timestamp > this.AfterYieldTimestamp); + Assert.IsTrue(this.AfterSemaphoreTimestamp > this.AfterDelay1Timestamp); + + // these can all fire in any order (delay doesn't guarantee any particular order) + Assert.IsTrue(this.AfterDelay2Timestamp > this.AfterSemaphoreTimestamp); + Assert.IsTrue(this.AfterDelay3Timestamp > this.AfterSemaphoreTimestamp); + Assert.IsTrue(this.AfterDelay4Timestamp > this.AfterSemaphoreTimestamp); + + // but by WhenAll()'ing them, we can assert WhenAll completes after all the other delays + Assert.IsTrue(this.WhenAllTimestamp > this.AfterDelay2Timestamp); + Assert.IsTrue(this.WhenAllTimestamp > this.AfterDelay3Timestamp); + Assert.IsTrue(this.WhenAllTimestamp > this.AfterDelay4Timestamp); + + Assert.IsTrue(this.EndTimestamp > this.WhenAllTimestamp); + } + } + + /// + /// IPrefetcher that asserts it got a trace with an expected parent. + /// + private sealed class ExpectedParentTracePrefetcher : IPrefetcher + { + private readonly ITrace expectedParentTrace; + + internal ExpectedParentTracePrefetcher(ITrace expectedParentTrace) + { + this.expectedParentTrace = expectedParentTrace; + } + + public ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) + { + Assert.AreSame(this.expectedParentTrace, trace.Parent); + + return default; + } + } + + /// + /// IEnumerable which throws if touched. + /// + private sealed class ThrowsEnumerable : IEnumerable + { + public IEnumerator GetEnumerator() + { + throw new NotSupportedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + + /// + /// IEnumerable whose IEnumerator throws if access concurrently. + /// + private sealed class NonConcurrentAssertingEnumerable : IEnumerable + { + private sealed class Enumerator : IEnumerator + { + private readonly T[] inner; + private int index; + + private int active; + + internal Enumerator(T[] inner) + { + this.inner = inner; + } + + public T Current { get; private set; } + + object IEnumerator.Current => this.Current; + + public void Dispose() + { + } + + public bool MoveNext() + { + int isActive = Interlocked.Exchange(ref this.active, 1); + Assert.AreEqual(0, isActive, "Modified concurrently"); + + try + { + if (this.index < this.inner.Length) + { + this.Current = this.inner[this.index]; + this.index++; + return true; + } + + return false; + } + finally + { + int wasActive = Interlocked.Exchange(ref this.active, 0); + Assert.AreEqual(1, wasActive, "Modified concurrently"); + } + } + + public void Reset() + { + throw new NotImplementedException(); + } + } + + private readonly T[] inner; + + internal NonConcurrentAssertingEnumerable(T[] inner) + { + this.inner = inner; + } + + public IEnumerator GetEnumerator() + { + return new Enumerator(this.inner); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + + /// + /// IEnumerable whose IEnumerator throws if access concurrently. + /// + private sealed class DisposeTrackingEnumerable : IEnumerable + { + private sealed class Enumerator : IEnumerator + { + private readonly DisposeTrackingEnumerable outer; + + private int index; + + internal Enumerator(DisposeTrackingEnumerable outer) + { + this.outer = outer; + } + + public T Current { get; private set; } + + object IEnumerator.Current => this.Current; + + public void Dispose() + { + this.outer.DisposeCalls++; + } + + public bool MoveNext() + { + if (this.index < this.outer.inner.Length) + { + this.Current = this.outer.inner[this.index]; + this.index++; + return true; + } + + return false; + } + + public void Reset() + { + throw new NotImplementedException(); + } + } + + private readonly T[] inner; + + internal DisposeTrackingEnumerable(T[] inner) + { + this.inner = inner; + } + + internal int DisposeCalls { get; private set; } + + public IEnumerator GetEnumerator() + { + return new Enumerator(this); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + + /// + /// IEnumerable whose IEnumerator throws after a certain number of + /// calls to MoveNext(). + /// + private sealed class ThrowsAfterEnumerable : IEnumerable + { + private sealed class Enumerator : IEnumerator + { + private readonly IEnumerator inner; + private readonly int throwAfter; + private int callNumber; + + public T Current { get; set; } + + object IEnumerator.Current => this.Current; + + + internal Enumerator(IEnumerator inner, int throwAfter) + { + this.inner = inner; + this.throwAfter = throwAfter; + } + public void Dispose() + { + this.inner.Dispose(); + } + + public bool MoveNext() + { + if (this.callNumber >= this.throwAfter) + { + throw new InvalidOperationException(); + } + + this.callNumber++; + + if (this.inner.MoveNext()) + { + this.Current = this.inner.Current; + return true; + } + + this.Current = default; + return false; + } + + public void Reset() + { + this.inner.Reset(); + } + } + + private readonly IEnumerable inner; + private readonly int throwAfter; + + public ThrowsAfterEnumerable(IEnumerable inner, int throwAfter) + { + this.inner = inner; + this.throwAfter = throwAfter; + } + + public IEnumerator GetEnumerator() + { + return new Enumerator(this.inner.GetEnumerator(), this.throwAfter); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.GetEnumerator(); + } + } + + /// + /// IPrefetcher which throws if touched. + /// + private sealed class ThrowsPrefetcher : IPrefetcher + { + public ValueTask PrefetchAsync(ITrace trace, CancellationToken cancellationToken) + { + throw new NotSupportedException(); + } + } + + /// + /// ArrayPool that tracks leaks, double returns, and includes non-null values in + /// returned arrays. + /// + private sealed class ValidatingRandomizedArrayPool : ArrayPool + where T : class + { + private readonly T existingValue; + + private readonly ConcurrentBag created; + private readonly ConcurrentDictionary rented; + + internal ValidatingRandomizedArrayPool(T existingValue) + { + this.existingValue = existingValue; + this.created = new(); + this.rented = new(); + } + + public override T[] Rent(int minimumLength) + { + int extra = Random.Shared.Next(6); + + T[] ret = new T[minimumLength + extra]; + for (int i = 0; i < ret.Length; i++) + { + ret[i] = Random.Shared.Next(2) == 0 ? this.existingValue : null; + } + + this.created.Add(ret); + + Assert.IsTrue(this.rented.TryAdd(ret, null)); + + return ret; + } + + public override void Return(T[] array, bool clearArray = false) + { + Assert.IsFalse(clearArray, "Caller should clean up array itself"); + + Assert.IsTrue(this.rented.TryRemove(array, out _), "Tried to return array that isn't rented"); + + for (int i = 0; i < array.Length; i++) + { + object value = array[i]; + + if (object.ReferenceEquals(value, this.existingValue)) + { + continue; + } + + Assert.IsNull(value, "Returned array shouldn't have any non-null values, except those included by the original Rent call"); + } + } + + internal void AssertAllReturned() + { + Assert.IsTrue(this.rented.IsEmpty); + } + } + + /// + /// ITrace which only traces children and parents. + /// + private sealed class SimpleTrace : ITrace + { + public string Name { get; private set; } + + public Guid Id { get; } = Guid.NewGuid(); + + public DateTime StartTime { get; } = DateTime.UtcNow; + + public TimeSpan Duration => DateTime.UtcNow - this.StartTime; + + public Cosmos.Tracing.TraceLevel Level { get; private set; } + + public TraceComponent Component { get; private set; } + + public TraceSummary Summary => new(); + + public ITrace Parent { get; private set; } + + public IReadOnlyList Children { get; } = new List(); + + public IReadOnlyDictionary Data { get; } = new Dictionary(); + + internal SimpleTrace(ITrace parent, string name, TraceComponent component, Cosmos.Tracing.TraceLevel level) + { + this.Parent = parent; + this.Name = name; + this.Component = component; + this.Level = level; + } + + public void AddChild(ITrace trace) + { + List children = (List)this.Children; + lock (children) + { + children.Add(trace); + } + } + + public void AddDatum(string key, TraceDatum traceDatum) + { + } + + public void AddDatum(string key, object value) + { + } + + public void AddOrUpdateDatum(string key, object value) + { + } + + public void Dispose() + { + } + + public ITrace StartChild(string name) + { + return this.StartChild(name, TraceComponent.Unknown, Cosmos.Tracing.TraceLevel.Off); + } + + public ITrace StartChild(string name, TraceComponent component, Cosmos.Tracing.TraceLevel level) + { + ITrace child = new SimpleTrace(this, name, component, level); + + List children = (List)this.Children; + lock (children) + { + children.Add(child); + } + + return child; + } + } + + /// + /// Different task counts which explore different code paths. + /// + private static readonly int[] TaskCounts = new[] { 0, 1, 2, 511, 512, 513, 1024, 1025 }; + + /// + /// Different max concurrencies which explore different code paths. + /// + private static readonly int[] Concurrencies = new[] { 1, 2, 511, 512, 513, int.MaxValue }; + + private static readonly ITrace EmptyTrace = NoOpTrace.Singleton; + + [TestMethod] + public async Task ParameterValidationAsync() + { + // test contract for parameters + + ArgumentNullException prefetchersArg = Assert.ThrowsException( + () => + ParallelPrefetch.PrefetchInParallelAsync( + null, + 123, + EmptyTrace, + default)); + Assert.AreEqual("prefetchers", prefetchersArg.ParamName); + + ArgumentNullException traceArg = Assert.ThrowsException( + () => + ParallelPrefetch.PrefetchInParallelAsync( + Array.Empty(), + 123, + null, + default)); + Assert.AreEqual("trace", traceArg.ParamName); + + // maxConcurrency can be < 0 ; check that that doesn't throw + await ParallelPrefetch.PrefetchInParallelAsync(Array.Empty(), -123, EmptyTrace, default); + } + + [TestMethod] + public async Task ZeroConcurrencyOptimizationAsync() + { + // test that we correctly special case maxConcurrency == 0 as "do nothing" + + IEnumerable prefetchers = new ThrowsEnumerable(); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + 0, + EmptyTrace, + default); + } + + [TestMethod] + public async Task AllExecutedAsync() + { + // test that all prefetchers are actually invoked + + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + int executed1 = 0; + int executed2 = 0; + IEnumerable prefetchers = CreatePrefetchers(taskCount, () => Interlocked.Increment(ref executed1), () => Interlocked.Increment(ref executed2)); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + default); + + Assert.AreEqual(taskCount, executed1); + Assert.AreEqual(taskCount, executed2); + } + } + + static IEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + + [TestMethod] + public async Task EnumeratorNotConcurrentlyAccessedAsync() + { + // test that the IEnumerator is only accessed by one thread at a time + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + IEnumerable prefetchers = CreatePrefetchers(taskCount, static () => { }, static () => { }); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + default); + } + } + + static IEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + IPrefetcher[] inner = new IPrefetcher[count]; + for (int i = 0; i < count; i++) + { + inner[i] = new TestOncePrefetcher(beforeAwait, afterAwait); + } + + return new NonConcurrentAssertingEnumerable(inner); + } + } + + [TestMethod] + public async Task EnumeratorDisposedAsync() + { + // test that the IEnumerator is only accessed by one thread at a time + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + DisposeTrackingEnumerable prefetchers = CreatePrefetchers(taskCount, static () => { }, static () => { }); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + default); + + Assert.AreEqual(1, prefetchers.DisposeCalls); + } + } + + static DisposeTrackingEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + IPrefetcher[] inner = new IPrefetcher[count]; + for (int i = 0; i < count; i++) + { + inner[i] = new TestOncePrefetcher(beforeAwait, afterAwait); + } + + return new DisposeTrackingEnumerable(inner); + } + } + + [TestMethod] + public async Task ComplicatedPrefetcherAsync() + { + // test that a complicated prefetcher is full started and completed + // + // the rest of the tests don't use a completely trivial + // IPrefetcher, but they are substantially simpler + + foreach (int maxConcurrency in Concurrencies) + { + ComplicatedPrefetcher prefetcher = new(); + + await ParallelPrefetch.PrefetchInParallelAsync( + new IPrefetcher[] { prefetcher }, + maxConcurrency, + EmptyTrace, + default); + + prefetcher.AssertCorrect(); + } + } + + [TestMethod] + public async Task MaxConcurrencyRespectedAsync() + { + // test that we never get above maxConcurrency + // + // whether or not we _reach_ it is dependent on the scheduler + // so we can't reliably test that + + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + int observedMax = 0; + int current = 0; + + IEnumerable prefetchers = + CreatePrefetchers( + taskCount, + () => + { + int newCurrent = Interlocked.Increment(ref current); + Assert.IsTrue(newCurrent <= maxConcurrency); + + int oldMax = Volatile.Read(ref observedMax); + + while (newCurrent > oldMax) + { + oldMax = Interlocked.CompareExchange(ref observedMax, newCurrent, oldMax); + } + }, + () => + { + int newCurrent = Interlocked.Decrement(ref current); + + Assert.IsTrue(current >= 0); + }); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + default); + + Assert.IsTrue(Volatile.Read(ref observedMax) <= maxConcurrency); + Assert.AreEqual(0, Volatile.Read(ref current)); + } + } + + static IEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + + [TestMethod] + public async Task TraceCorrectlyPassedAsync() + { + // test that we make ONE ITrace per invocation + // and that it the returned child trace is correctly + // passed to all IPrefetchers + + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + using ITrace simpleTrace = new SimpleTrace(null, "Root", TraceComponent.Batch, Cosmos.Tracing.TraceLevel.Off); + + IEnumerable prefetchers = CreatePrefetchers(taskCount, simpleTrace); + + await ParallelPrefetch.PrefetchInParallelAsync( + prefetchers, + maxConcurrency, + simpleTrace, + default); + + // our prefetchers don't create any children, but we expect one + // to be created by ParallelPrefetch + Assert.AreEqual(1, simpleTrace.Children.Count); + Assert.AreEqual(0, simpleTrace.Children[0].Children.Count); + + // the one trace we start has a well known set of attributes, so check them + Assert.AreEqual("Prefetching", simpleTrace.Children[0].Name); + Assert.AreEqual(TraceComponent.Pagination, simpleTrace.Children[0].Component); + Assert.AreEqual(Cosmos.Tracing.TraceLevel.Info, simpleTrace.Children[0].Level); + } + } + + static IEnumerable CreatePrefetchers(int count, ITrace expectedParentTrace) + { + for (int i = 0; i < count; i++) + { + yield return new ExpectedParentTracePrefetcher(expectedParentTrace); + } + } + } + + [TestMethod] + public async Task RentedBuffersAllReturnedAsync() + { + // test that all rented buffers are correctly returned + // (and in the expected state) + + Task faultedTask = Task.FromException(new NotSupportedException()); + + try + { + foreach (int maxConcurrency in Concurrencies) + { + foreach (int taskCount in TaskCounts) + { + IEnumerable prefetchers = CreatePrefetchers(taskCount, static () => { }, static () => { }); + + ValidatingRandomizedArrayPool prefetcherPool = new(new ThrowsPrefetcher()); + ValidatingRandomizedArrayPool taskPool = new(faultedTask); + ValidatingRandomizedArrayPool objectPool = new("unexpected value"); + + ParallelPrefetch.ParallelPrefetchTestConfig config = + new( + prefetcherPool, + taskPool, + objectPool + ); + + await ParallelPrefetch.PrefetchInParallelCoreAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + config, + default); + + Assert.AreEqual(config.StartedTasks, config.AwaitedTasks, $"maxConcurrency={maxConcurrency}, taskCount={taskCount}; some tasks left unawaited"); + + prefetcherPool.AssertAllReturned(); + taskPool.AssertAllReturned(); + objectPool.AssertAllReturned(); + } + } + } + finally + { + // observe this intentionally faulted task, no matter what + try + { + await faultedTask; + } + catch + { + // intentionally empty + } + } + + static IEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + + [TestMethod] + public async Task TaskSingleExceptionHandledAsync() + { + // test that raising exceptions during processing tasks + // doesn't leak or otherwise fail + + Task faultedTask = Task.FromException(new NotSupportedException()); + + try + { + foreach (int maxConcurrency in Concurrencies) + { + if (maxConcurrency <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + foreach (int taskCount in TaskCounts) + { + if (taskCount <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + for (int faultOnTask = 0; faultOnTask < taskCount; faultOnTask++) + { + IEnumerable prefetchers = CreatePrefetchers(taskCount, faultOnTask, static () => { }, static () => { }); + + ValidatingRandomizedArrayPool prefetcherPool = new(new ThrowsPrefetcher()); + ValidatingRandomizedArrayPool taskPool = new(faultedTask); + ValidatingRandomizedArrayPool objectPool = new("unexpected value"); + + ParallelPrefetch.ParallelPrefetchTestConfig config = + new( + prefetcherPool, + taskPool, + objectPool + ); + + Exception caught = null; + try + { + await ParallelPrefetch.PrefetchInParallelCoreAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + config, + default); + } + catch (Exception e) + { + caught = e; + } + + Assert.IsNotNull(caught, $"concurrency={maxConcurrency}, tasks={taskCount}, faultOn={faultOnTask} - didn't produce exception as expected"); + + Assert.AreEqual(config.StartedTasks, config.AwaitedTasks, $"maxConcurrency={maxConcurrency}, taskCount={taskCount}, faultOnTask={faultedTask}; some tasks left unawaited"); + + // buffer management can't break in the face of errors, so check here too + prefetcherPool.AssertAllReturned(); + taskPool.AssertAllReturned(); + objectPool.AssertAllReturned(); + } + } + } + } + finally + { + // observe this intentionally faulted task, no matter what + try + { + await faultedTask; + } + catch + { + // intentionally empty + } + } + + static IEnumerable CreatePrefetchers(int count, int faultOnTask, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + if (faultOnTask == i) + { + yield return new ThrowsPrefetcher(); + } + else + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + } + + [TestMethod] + public async Task TaskMultipleExceptionsHandledAsync() + { + // we throw a lot of exceptions in this test, which is expensive + // so we only probe proportionally to this constant for expediency's + // sake + const int StepRatio = 10; + + // test that raising exceptions during processing tasks + // doesn't leak or otherwise fail + + Task faultedTask = Task.FromException(new NotSupportedException()); + + try + { + foreach (int maxConcurrency in Concurrencies) + { + if (maxConcurrency <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + foreach (int taskCount in TaskCounts) + { + if (taskCount <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + int step = Math.Max(1, taskCount / StepRatio); + + for (int faultOnAndAfterTask = 0; faultOnAndAfterTask < taskCount; faultOnAndAfterTask += step) + { + IEnumerable prefetchers = CreatePrefetchers(taskCount, faultOnAndAfterTask, static () => { }, static () => { }); + + ValidatingRandomizedArrayPool prefetcherPool = new(new ThrowsPrefetcher()); + ValidatingRandomizedArrayPool taskPool = new(faultedTask); + ValidatingRandomizedArrayPool objectPool = new("unexpected value"); + + ParallelPrefetch.ParallelPrefetchTestConfig config = + new( + prefetcherPool, + taskPool, + objectPool + ); + + Exception caught = null; + try + { + await ParallelPrefetch.PrefetchInParallelCoreAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + config, + default); + } + catch (Exception e) + { + caught = e; + } + + Assert.IsNotNull(caught, $"concurrency={maxConcurrency}, tasks={taskCount}, faultOnAndAfterTask={faultOnAndAfterTask} - didn't produce exception as expected"); + + Assert.AreEqual(config.StartedTasks, config.AwaitedTasks, $"maxConcurrency={maxConcurrency}, taskCount={taskCount}, faultedOnAndAfterTask={faultOnAndAfterTask}; some tasks left unawaited"); + + // buffer management can't break in the face of errors, so check here too + prefetcherPool.AssertAllReturned(); + taskPool.AssertAllReturned(); + objectPool.AssertAllReturned(); + } + } + } + } + finally + { + // observe this intentionally faulted task, no matter what + try + { + await faultedTask; + } + catch + { + // intentionally empty + } + } + + static IEnumerable CreatePrefetchers(int count, int faultOnTask, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + if (faultOnTask >= i) + { + yield return new ThrowsPrefetcher(); + } + else + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + } + + [TestMethod] + public async Task EnumerableExceptionsHandledAsync() + { + // test that raising exceptions during enumeration + // doesn't leak or otherwise fail + + Task faultedTask = Task.FromException(new NotSupportedException()); + + try + { + foreach (int maxConcurrency in Concurrencies.Reverse()) + { + if (maxConcurrency <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + foreach (int taskCount in TaskCounts) + { + for (int faultAfter = 0; faultAfter < taskCount; faultAfter++) + { + IEnumerable prefetchersRaw = CreatePrefetchers(taskCount, faultAfter, static () => { }, static () => { }); + IEnumerable prefetchers = new ThrowsAfterEnumerable(prefetchersRaw, faultAfter); + + ValidatingRandomizedArrayPool prefetcherPool = new(new ThrowsPrefetcher()); + ValidatingRandomizedArrayPool taskPool = new(faultedTask); + ValidatingRandomizedArrayPool objectPool = new("unexpected value"); + + ParallelPrefetch.ParallelPrefetchTestConfig config = + new( + prefetcherPool, + taskPool, + objectPool + ); + + Exception caught = null; + try + { + await ParallelPrefetch.PrefetchInParallelCoreAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + config, + default); + } + catch (Exception e) + { + caught = e; + } + + Assert.IsNotNull(caught, $"concurrency={maxConcurrency}, tasks={taskCount}, faultAfter={faultAfter} - didn't produce exception as expected"); + + Assert.AreEqual(config.StartedTasks, config.AwaitedTasks, $"maxConcurrency={maxConcurrency}, taskCount={taskCount}; some tasks left unawaited"); + + // buffer management can't break in the face of errors, so check here too + prefetcherPool.AssertAllReturned(); + taskPool.AssertAllReturned(); + objectPool.AssertAllReturned(); + } + } + } + } + finally + { + // observe this intentionally faulted task, no matter what + try + { + await faultedTask; + } + catch + { + // intentionally empty + } + } + + static IEnumerable CreatePrefetchers(int count, int faultOnTask, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + + [TestMethod] + public async Task CancellationHandledAsync() + { + // cancellation is expensive, so rather than check every + // cancellation point - we just probe some proportional + // to this constant + const int StepRatio = 10; + + // test that cancellation during processing + // doesn't leak or otherwise fail + + Task faultedTask = Task.FromException(new NotSupportedException()); + + try + { + foreach (int maxConcurrency in Concurrencies) + { + if (maxConcurrency <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + foreach (int taskCount in TaskCounts) + { + if (taskCount <= 1) + { + // we won't do anything fancy, so skip + continue; + } + + int step = Math.Max(1, taskCount / StepRatio); + + for (int cancelBeforeTask = 0; cancelBeforeTask < taskCount; cancelBeforeTask += step) + { + using CancellationTokenSource cts = new(); + + int startedBeforeCancellation = 0; + object sync = new(); + + IEnumerable prefetchers = + CreatePrefetchers( + taskCount, + () => + { + if (!cts.IsCancellationRequested) + { + int newValue = Interlocked.Increment(ref startedBeforeCancellation); + + if (newValue >= cancelBeforeTask) + { + cts.Cancel(); + } + } + }, + () => { }); + + ValidatingRandomizedArrayPool prefetcherPool = new(new ThrowsPrefetcher()); + ValidatingRandomizedArrayPool taskPool = new(faultedTask); + ValidatingRandomizedArrayPool objectPool = new("unexpected value"); + + ParallelPrefetch.ParallelPrefetchTestConfig config = + new( + prefetcherPool, + taskPool, + objectPool + ); + + Exception caught = null; + try + { + await ParallelPrefetch.PrefetchInParallelCoreAsync( + prefetchers, + maxConcurrency, + EmptyTrace, + config, + cts.Token); + } + catch (Exception e) + { + caught = e; + } + + Assert.IsNotNull(caught, $"concurrency={maxConcurrency}, tasks={taskCount}, cancelBeforeTask={cancelBeforeTask} - didn't produce exception as expected"); + + // we might burst above this, but we should always at least _reach_ it + Assert.IsTrue(cancelBeforeTask <= startedBeforeCancellation, $"{cancelBeforeTask} > {startedBeforeCancellation} ; we should have reach our cancellation point"); + + Assert.IsTrue(caught is OperationCanceledException); + + Assert.AreEqual(config.StartedTasks, config.AwaitedTasks, $"maxConcurrency={maxConcurrency}, taskCount={taskCount}, cancelBeforeTask={cancelBeforeTask}; some tasks left unawaited"); + + // buffer management can't break in the face of cancellation, so check here too + prefetcherPool.AssertAllReturned(); + taskPool.AssertAllReturned(); + objectPool.AssertAllReturned(); + } + } + + static IEnumerable CreatePrefetchers(int count, Action beforeAwait, Action afterAwait) + { + for (int i = 0; i < count; i++) + { + yield return new TestOncePrefetcher(beforeAwait, afterAwait); + } + } + } + } + finally + { + // observe this intentionally faulted task, no matter what + try + { + await faultedTask; + } + catch + { + // intentionally empty + } + } + } + } +} From 1106cd7cfe1fa1650cd8e237e85754b7a8301712 Mon Sep 17 00:00:00 2001 From: Aditya Date: Tue, 2 Apr 2024 15:51:01 -0700 Subject: [PATCH 304/337] [Internal] Query: Fixes occasional hang while querying using partial partition key against a sub-partitioned container (#4359) * Initial commit * Suite0 fixes. * Updated Test. --- .../CosmosQueryExecutionContextFactory.cs | 2156 +++++++++-------- ...arallelCrossPartitionQueryPipelineStage.cs | 530 ++-- .../QueryPartitionRangePageAsyncEnumerator.cs | 100 +- ...misticDirectExecutionQueryPipelineStage.cs | 619 ++--- .../Query/Core/Pipeline/PipelineFactory.cs | 3 + ...itionTests.TestQueriesOnSplitContainer.xml | 60 + .../Microsoft.Azure.Cosmos.Tests.csproj | 4 + .../Pagination/InMemoryContainer.cs | 154 +- ...misticDirectExecutionQueryBaselineTests.cs | 24 +- .../Query/Pipeline/FactoryTests.cs | 1 + .../Query/Pipeline/FullPipelineTests.cs | 1 + ...elCrossPartitionQueryPipelineStageTests.cs | 7 + .../QueryPartitionRangePageEnumeratorTests.cs | 351 +-- .../Query/SubpartitionTests.cs | 392 +++ .../Tracing/TraceWriterBaselineTests.cs | 1 + 15 files changed, 2562 insertions(+), 1841 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SubpartitionTests.TestQueriesOnSplitContainer.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SubpartitionTests.cs diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index fdca4ee452..d778db2438 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -1,470 +1,472 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Text.RegularExpressions; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Cosmos.Query.Core.Exceptions; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Parser; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Tokens; - using Microsoft.Azure.Cosmos.Query.Core.QueryClient; - using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; - using Microsoft.Azure.Cosmos.SqlObjects; - using Microsoft.Azure.Cosmos.SqlObjects.Visitors; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Documents.Routing; - - internal static class CosmosQueryExecutionContextFactory - { - internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; - private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; - private const string QueryInspectionPattern = @"\s*(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; - private const string OptimisticDirectExecution = "OptimisticDirectExecution"; - private const string Passthrough = "Passthrough"; - private const string Specialized = "Specialized"; - private const int PageSizeFactorForTop = 5; - private static readonly Regex QueryInspectionRegex = new Regex(QueryInspectionPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); - - public static IQueryPipelineStage Create( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - ITrace trace) - { - if (cosmosQueryContext == null) - { - throw new ArgumentNullException(nameof(cosmosQueryContext)); - } - - if (inputParameters == null) - { - throw new ArgumentNullException(nameof(inputParameters)); - } - - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - - NameCacheStaleRetryQueryPipelineStage nameCacheStaleRetryQueryPipelineStage = new NameCacheStaleRetryQueryPipelineStage( - cosmosQueryContext: cosmosQueryContext, - queryPipelineStageFactory: () => - { - // Query Iterator requires that the creation of the query context is deferred until the user calls ReadNextAsync - AsyncLazy> lazyTryCreateStage = new AsyncLazy>( +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Text.RegularExpressions; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.Exceptions; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Parser; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Tokens; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; + using Microsoft.Azure.Cosmos.SqlObjects; + using Microsoft.Azure.Cosmos.SqlObjects.Visitors; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents.Routing; + + internal static class CosmosQueryExecutionContextFactory + { + internal const string ClientDisableOptimisticDirectExecution = "clientDisableOptimisticDirectExecution"; + private const string InternalPartitionKeyDefinitionProperty = "x-ms-query-partitionkey-definition"; + private const string QueryInspectionPattern = @"\s*(GROUP\s+BY\s+|COUNT\s*\(|MIN\s*\(|MAX\s*\(|AVG\s*\(|SUM\s*\(|DISTINCT\s+)"; + private const string OptimisticDirectExecution = "OptimisticDirectExecution"; + private const string Passthrough = "Passthrough"; + private const string Specialized = "Specialized"; + private const int PageSizeFactorForTop = 5; + private static readonly Regex QueryInspectionRegex = new Regex(QueryInspectionPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); + + public static IQueryPipelineStage Create( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + ITrace trace) + { + if (cosmosQueryContext == null) + { + throw new ArgumentNullException(nameof(cosmosQueryContext)); + } + + if (inputParameters == null) + { + throw new ArgumentNullException(nameof(inputParameters)); + } + + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + + NameCacheStaleRetryQueryPipelineStage nameCacheStaleRetryQueryPipelineStage = new NameCacheStaleRetryQueryPipelineStage( + cosmosQueryContext: cosmosQueryContext, + queryPipelineStageFactory: () => + { + // Query Iterator requires that the creation of the query context is deferred until the user calls ReadNextAsync + AsyncLazy> lazyTryCreateStage = new AsyncLazy>( valueFactory: (trace, innerCancellationToken) => TryCreateCoreContextAsync( - documentContainer, - cosmosQueryContext, - inputParameters, - trace, - innerCancellationToken)); - + documentContainer, + cosmosQueryContext, + inputParameters, + trace, + innerCancellationToken)); + LazyQueryPipelineStage lazyQueryPipelineStage = new LazyQueryPipelineStage(lazyTryCreateStage: lazyTryCreateStage); - return lazyQueryPipelineStage; - }); - + return lazyQueryPipelineStage; + }); + CatchAllQueryPipelineStage catchAllQueryPipelineStage = new CatchAllQueryPipelineStage(nameCacheStaleRetryQueryPipelineStage); - return catchAllQueryPipelineStage; - } - - private static async Task> TryCreateCoreContextAsync( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - ITrace trace, - CancellationToken cancellationToken) - { - // The default - using (ITrace createQueryPipelineTrace = trace.StartChild("Create Query Pipeline", TraceComponent.Query, Tracing.TraceLevel.Info)) - { - // Try to parse the continuation token. - CosmosElement continuationToken = inputParameters.InitialUserContinuationToken; - PartitionedQueryExecutionInfo queryPlanFromContinuationToken = inputParameters.PartitionedQueryExecutionInfo; - if (continuationToken != null) - { - if (!PipelineContinuationToken.TryCreateFromCosmosElement( - continuationToken, - out PipelineContinuationToken pipelineContinuationToken)) - { - return TryCatch.FromException( - new MalformedContinuationTokenException( - $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}.")); - } - - if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) - { - return TryCatch.FromException( - new MalformedContinuationTokenException( - $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. " + - $"Upgrade the SDK to avoid this issue." + - $"{continuationToken}.")); - } - - if (!PipelineContinuationToken.TryConvertToLatest( - pipelineContinuationToken, - out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) - { - return TryCatch.FromException( - new MalformedContinuationTokenException( - $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported.")); - } - - continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; - if (latestVersionPipelineContinuationToken.QueryPlan != null) - { - queryPlanFromContinuationToken = latestVersionPipelineContinuationToken.QueryPlan; - } - } - - CosmosQueryClient cosmosQueryClient = cosmosQueryContext.QueryClient; - - ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync( - cosmosQueryContext.ResourceLink, - inputParameters.PartitionKey, - createQueryPipelineTrace, - cancellationToken); - cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; - - Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( - inputParameters, - queryPlanFromContinuationToken, - cosmosQueryContext, - containerQueryProperties, - trace); - - if (targetRange != null) - { - return await TryCreateSinglePartitionExecutionContextAsync( - documentContainer, - partitionedQueryExecutionInfo: null, - cosmosQueryContext, - containerQueryProperties, - inputParameters, - targetRange, - createQueryPipelineTrace, - cancellationToken); - } - - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; - if (queryPlanFromContinuationToken != null) - { - partitionedQueryExecutionInfo = queryPlanFromContinuationToken; - } - else - { - // If the query would go to gateway, but we have a partition key, - // then try seeing if we can execute as a passthrough using client side only logic. - // This is to short circuit the need to go to the gateway to get the query plan. - if (cosmosQueryContext.QueryClient.BypassQueryParsing() - && inputParameters.PartitionKey.HasValue) - { - bool parsed; - SqlQuery sqlQuery; - using (ITrace queryParseTrace = createQueryPipelineTrace.StartChild("Parse Query", TraceComponent.Query, Tracing.TraceLevel.Info)) - { - parsed = SqlQueryParser.TryParse(inputParameters.SqlQuerySpec.QueryText, out sqlQuery); - } - - if (parsed) - { - bool hasDistinct = sqlQuery.SelectClause.HasDistinct; - bool hasGroupBy = sqlQuery.GroupByClause != default; - bool hasAggregates = AggregateProjectionDetector.HasAggregate(sqlQuery.SelectClause.SelectSpec); - bool createPassthroughQuery = !hasAggregates && !hasDistinct && !hasGroupBy; - - if (createPassthroughQuery) - { - SetTestInjectionPipelineType(inputParameters, Passthrough); - - // Only thing that matters is that we target the correct range. - Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - List targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.ResourceLink, - containerQueryProperties.ResourceId, - containerQueryProperties.EffectiveRangesForPartitionKey, - forceRefresh: false, - createQueryPipelineTrace); - + return catchAllQueryPipelineStage; + } + + private static async Task> TryCreateCoreContextAsync( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + ITrace trace, + CancellationToken cancellationToken) + { + // The default + using (ITrace createQueryPipelineTrace = trace.StartChild("Create Query Pipeline", TraceComponent.Query, Tracing.TraceLevel.Info)) + { + // Try to parse the continuation token. + CosmosElement continuationToken = inputParameters.InitialUserContinuationToken; + PartitionedQueryExecutionInfo queryPlanFromContinuationToken = inputParameters.PartitionedQueryExecutionInfo; + if (continuationToken != null) + { + if (!PipelineContinuationToken.TryCreateFromCosmosElement( + continuationToken, + out PipelineContinuationToken pipelineContinuationToken)) + { + return TryCatch.FromException( + new MalformedContinuationTokenException( + $"Malformed {nameof(PipelineContinuationToken)}: {continuationToken}.")); + } + + if (PipelineContinuationToken.IsTokenFromTheFuture(pipelineContinuationToken)) + { + return TryCatch.FromException( + new MalformedContinuationTokenException( + $"{nameof(PipelineContinuationToken)} Continuation token is from a newer version of the SDK. " + + $"Upgrade the SDK to avoid this issue." + + $"{continuationToken}.")); + } + + if (!PipelineContinuationToken.TryConvertToLatest( + pipelineContinuationToken, + out PipelineContinuationTokenV1_1 latestVersionPipelineContinuationToken)) + { + return TryCatch.FromException( + new MalformedContinuationTokenException( + $"{nameof(PipelineContinuationToken)}: '{continuationToken}' is no longer supported.")); + } + + continuationToken = latestVersionPipelineContinuationToken.SourceContinuationToken; + if (latestVersionPipelineContinuationToken.QueryPlan != null) + { + queryPlanFromContinuationToken = latestVersionPipelineContinuationToken.QueryPlan; + } + } + + CosmosQueryClient cosmosQueryClient = cosmosQueryContext.QueryClient; + + ContainerQueryProperties containerQueryProperties = await cosmosQueryClient.GetCachedContainerQueryPropertiesAsync( + cosmosQueryContext.ResourceLink, + inputParameters.PartitionKey, + createQueryPipelineTrace, + cancellationToken); + cosmosQueryContext.ContainerResourceId = containerQueryProperties.ResourceId; + + Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( + inputParameters, + queryPlanFromContinuationToken, + cosmosQueryContext, + containerQueryProperties, + trace); + + if (targetRange != null) + { + return await TryCreateSinglePartitionExecutionContextAsync( + documentContainer, + partitionedQueryExecutionInfo: null, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + targetRange, + createQueryPipelineTrace, + cancellationToken); + } + + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; + if (queryPlanFromContinuationToken != null) + { + partitionedQueryExecutionInfo = queryPlanFromContinuationToken; + } + else + { + // If the query would go to gateway, but we have a partition key, + // then try seeing if we can execute as a passthrough using client side only logic. + // This is to short circuit the need to go to the gateway to get the query plan. + if (cosmosQueryContext.QueryClient.BypassQueryParsing() + && inputParameters.PartitionKey.HasValue) + { + bool parsed; + SqlQuery sqlQuery; + using (ITrace queryParseTrace = createQueryPipelineTrace.StartChild("Parse Query", TraceComponent.Query, Tracing.TraceLevel.Info)) + { + parsed = SqlQueryParser.TryParse(inputParameters.SqlQuerySpec.QueryText, out sqlQuery); + } + + if (parsed) + { + bool hasDistinct = sqlQuery.SelectClause.HasDistinct; + bool hasGroupBy = sqlQuery.GroupByClause != default; + bool hasAggregates = AggregateProjectionDetector.HasAggregate(sqlQuery.SelectClause.SelectSpec); + bool createPassthroughQuery = !hasAggregates && !hasDistinct && !hasGroupBy; + + if (createPassthroughQuery) + { + SetTestInjectionPipelineType(inputParameters, Passthrough); + + // Only thing that matters is that we target the correct range. + Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); + List targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( + cosmosQueryContext.ResourceLink, + containerQueryProperties.ResourceId, + containerQueryProperties.EffectiveRangesForPartitionKey, + forceRefresh: false, + createQueryPipelineTrace); + return TryCreatePassthroughQueryExecutionContext( - documentContainer, - inputParameters, - targetRanges); - } - } - } - - partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( - cosmosQueryContext, - inputParameters, - containerQueryProperties, - createQueryPipelineTrace, - cancellationToken); - } - - return await TryCreateFromPartitionedQueryExecutionInfoAsync( - documentContainer, - partitionedQueryExecutionInfo, - containerQueryProperties, - cosmosQueryContext, - inputParameters, - createQueryPipelineTrace, - cancellationToken); - } - } - - private static async Task> TryCreateFromPartitionedQueryExecutionInfoAsync( - DocumentContainer documentContainer, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - ContainerQueryProperties containerQueryProperties, - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - ITrace trace, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - + documentContainer, + inputParameters, + targetRanges, + containerQueryProperties); + } + } + } + + partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + createQueryPipelineTrace, + cancellationToken); + } + + return await TryCreateFromPartitionedQueryExecutionInfoAsync( + documentContainer, + partitionedQueryExecutionInfo, + containerQueryProperties, + cosmosQueryContext, + inputParameters, + createQueryPipelineTrace, + cancellationToken); + } + } + + private static async Task> TryCreateFromPartitionedQueryExecutionInfoAsync( + DocumentContainer documentContainer, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + ContainerQueryProperties containerQueryProperties, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + ITrace trace, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + List targetRanges = await GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.QueryClient, - cosmosQueryContext.ResourceLink, - partitionedQueryExecutionInfo, - containerQueryProperties, - inputParameters.Properties, - inputParameters.InitialFeedRange, - trace); - - TryCatch tryCreatePipelineStage; - Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( - inputParameters, - partitionedQueryExecutionInfo, - cosmosQueryContext, - containerQueryProperties, - trace); - - if (targetRange != null) - { - tryCreatePipelineStage = await TryCreateSinglePartitionExecutionContextAsync( - documentContainer, - partitionedQueryExecutionInfo, - cosmosQueryContext, - containerQueryProperties, - inputParameters, - targetRange, - trace, - cancellationToken); - } - else - { - bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue - || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) - && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); - bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates - && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct - && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; - bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; - - bool clientStreamingQuery = serverStreamingQuery - && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy - && !partitionedQueryExecutionInfo.QueryInfo.HasTop - && !partitionedQueryExecutionInfo.QueryInfo.HasLimit - && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; - bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; - bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; - - if (createPassthroughQuery) - { - SetTestInjectionPipelineType(inputParameters, Passthrough); - + cosmosQueryContext.QueryClient, + cosmosQueryContext.ResourceLink, + partitionedQueryExecutionInfo, + containerQueryProperties, + inputParameters.Properties, + inputParameters.InitialFeedRange, + trace); + + TryCatch tryCreatePipelineStage; + Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( + inputParameters, + partitionedQueryExecutionInfo, + cosmosQueryContext, + containerQueryProperties, + trace); + + if (targetRange != null) + { + tryCreatePipelineStage = await TryCreateSinglePartitionExecutionContextAsync( + documentContainer, + partitionedQueryExecutionInfo, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + targetRange, + trace, + cancellationToken); + } + else + { + bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue + || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) + && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); + bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates + && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct + && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; + bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; + + bool clientStreamingQuery = serverStreamingQuery + && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy + && !partitionedQueryExecutionInfo.QueryInfo.HasTop + && !partitionedQueryExecutionInfo.QueryInfo.HasLimit + && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; + bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; + bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; + + if (createPassthroughQuery) + { + SetTestInjectionPipelineType(inputParameters, Passthrough); + tryCreatePipelineStage = TryCreatePassthroughQueryExecutionContext( - documentContainer, - inputParameters, - targetRanges); - } - else - { + documentContainer, + inputParameters, + targetRanges, + containerQueryProperties); + } + else + { + tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext(documentContainer, cosmosQueryContext, inputParameters, targetRanges, containerQueryProperties, partitionedQueryExecutionInfo); + } + } + + return tryCreatePipelineStage; + } + + private static async Task> TryCreateSinglePartitionExecutionContextAsync( + DocumentContainer documentContainer, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + InputParameters inputParameters, + Documents.PartitionKeyRange targetRange, + ITrace trace, + CancellationToken cancellationToken) + { + // Retrieve the query plan in a subset of cases to ensure the query is valid before creating the Ode pipeline + if (partitionedQueryExecutionInfo == null && QueryInspectionRegex.IsMatch(inputParameters.SqlQuerySpec.QueryText)) + { + partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + trace, + cancellationToken); + } + + // Test code added to confirm the correct pipeline is being utilized + SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); + + TryCatch tryCreatePipelineStage = TryCreateOptimisticDirectExecutionContext( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + targetRange, + cancellationToken); + + // A malformed continuation token exception would happen for 2 reasons here + // 1. the token is actually malformed + // 2. Its a non Ode continuation token + // In both cases, Ode pipeline delegates the work to the Specialized pipeline + // as Ode pipeline should not take over execution while some other pipeline is already handling it + if (tryCreatePipelineStage.Failed && tryCreatePipelineStage.InnerMostException is MalformedContinuationTokenException) + { + SetTestInjectionPipelineType(inputParameters, Specialized); + + if (partitionedQueryExecutionInfo != null) + { + List targetRanges = new List + { + targetRange + }; + tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext( documentContainer, cosmosQueryContext, inputParameters, targetRanges, - partitionedQueryExecutionInfo); - } - } - - return tryCreatePipelineStage; - } - - private static async Task> TryCreateSinglePartitionExecutionContextAsync( - DocumentContainer documentContainer, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - CosmosQueryContext cosmosQueryContext, - ContainerQueryProperties containerQueryProperties, - InputParameters inputParameters, - Documents.PartitionKeyRange targetRange, - ITrace trace, - CancellationToken cancellationToken) - { - // Retrieve the query plan in a subset of cases to ensure the query is valid before creating the Ode pipeline - if (partitionedQueryExecutionInfo == null && QueryInspectionRegex.IsMatch(inputParameters.SqlQuerySpec.QueryText)) - { - partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( - cosmosQueryContext, - inputParameters, - containerQueryProperties, - trace, - cancellationToken); - } - - // Test code added to confirm the correct pipeline is being utilized - SetTestInjectionPipelineType(inputParameters, OptimisticDirectExecution); - - TryCatch tryCreatePipelineStage = TryCreateOptimisticDirectExecutionContext( - documentContainer, - cosmosQueryContext, - containerQueryProperties, - inputParameters, - targetRange, - cancellationToken); - - // A malformed continuation token exception would happen for 2 reasons here - // 1. the token is actually malformed - // 2. Its a non Ode continuation token - // In both cases, Ode pipeline delegates the work to the Specialized pipeline - // as Ode pipeline should not take over execution while some other pipeline is already handling it - if (tryCreatePipelineStage.Failed && tryCreatePipelineStage.InnerMostException is MalformedContinuationTokenException) - { - SetTestInjectionPipelineType(inputParameters, Specialized); - - if (partitionedQueryExecutionInfo != null) - { - List targetRanges = new List - { - targetRange - }; - - tryCreatePipelineStage = TryCreateSpecializedDocumentQueryExecutionContext( - documentContainer, - cosmosQueryContext, - inputParameters, - targetRanges, - partitionedQueryExecutionInfo); - } - else - { - tryCreatePipelineStage = await TryCreateSpecializedDocumentQueryExecutionContextAsync( - documentContainer, - cosmosQueryContext, - containerQueryProperties, - inputParameters, - trace, - cancellationToken); - } - } - - return tryCreatePipelineStage; - } - - private static TryCatch TryCreateSpecializedDocumentQueryExecutionContext( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - List targetRanges, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) - { - SetTestInjectionPipelineType(inputParameters, Specialized); - - if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery)) - { - // We need pass down the rewritten query. - SqlQuerySpec rewrittenQuerySpec = new SqlQuerySpec() - { - QueryText = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, - Parameters = inputParameters.SqlQuerySpec.Parameters - }; - - inputParameters = new InputParameters( - rewrittenQuerySpec, - inputParameters.InitialUserContinuationToken, - inputParameters.InitialFeedRange, - inputParameters.MaxConcurrency, - inputParameters.MaxItemCount, - inputParameters.MaxBufferedItemCount, - inputParameters.PartitionKey, - inputParameters.Properties, - inputParameters.PartitionedQueryExecutionInfo, - inputParameters.ExecutionEnvironment, - inputParameters.ReturnResultsInDeterministicOrder, - inputParameters.EnableOptimisticDirectExecution, - inputParameters.TestInjections); - } - + containerQueryProperties, + partitionedQueryExecutionInfo); + } + else + { + tryCreatePipelineStage = await TryCreateSpecializedDocumentQueryExecutionContextAsync( + documentContainer, + cosmosQueryContext, + containerQueryProperties, + inputParameters, + trace, + cancellationToken); + } + } + + return tryCreatePipelineStage; + } + + private static TryCatch TryCreateSpecializedDocumentQueryExecutionContext( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + List targetRanges, + ContainerQueryProperties containerQueryProperties, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) + { + SetTestInjectionPipelineType(inputParameters, Specialized); + + if (!string.IsNullOrEmpty(partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery)) + { + // We need pass down the rewritten query. + SqlQuerySpec rewrittenQuerySpec = new SqlQuerySpec() + { + QueryText = partitionedQueryExecutionInfo.QueryInfo.RewrittenQuery, + Parameters = inputParameters.SqlQuerySpec.Parameters + }; + + inputParameters = new InputParameters( + rewrittenQuerySpec, + inputParameters.InitialUserContinuationToken, + inputParameters.InitialFeedRange, + inputParameters.MaxConcurrency, + inputParameters.MaxItemCount, + inputParameters.MaxBufferedItemCount, + inputParameters.PartitionKey, + inputParameters.Properties, + inputParameters.PartitionedQueryExecutionInfo, + inputParameters.ExecutionEnvironment, + inputParameters.ReturnResultsInDeterministicOrder, + inputParameters.EnableOptimisticDirectExecution, + inputParameters.TestInjections); + } + return TryCreateSpecializedDocumentQueryExecutionContext( - documentContainer, - cosmosQueryContext, - inputParameters, - partitionedQueryExecutionInfo, - targetRanges); - } - - private static async Task> TryCreateSpecializedDocumentQueryExecutionContextAsync( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - ContainerQueryProperties containerQueryProperties, - InputParameters inputParameters, - ITrace trace, - CancellationToken cancellationToken) - { - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( - cosmosQueryContext, - inputParameters, - containerQueryProperties, - trace, - cancellationToken); - + documentContainer, + cosmosQueryContext, + inputParameters, + partitionedQueryExecutionInfo, + targetRanges, + containerQueryProperties); + } + + private static async Task> TryCreateSpecializedDocumentQueryExecutionContextAsync( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + InputParameters inputParameters, + ITrace trace, + CancellationToken cancellationToken) + { + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await GetPartitionedQueryExecutionInfoAsync( + cosmosQueryContext, + inputParameters, + containerQueryProperties, + trace, + cancellationToken); + List targetRanges = await GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.QueryClient, - cosmosQueryContext.ResourceLink, - partitionedQueryExecutionInfo, - containerQueryProperties, - inputParameters.Properties, - inputParameters.InitialFeedRange, - trace); - - return TryCreateSpecializedDocumentQueryExecutionContext( - documentContainer, - cosmosQueryContext, - inputParameters, - targetRanges, - partitionedQueryExecutionInfo); - } - - private static TryCatch TryCreateOptimisticDirectExecutionContext( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - ContainerQueryProperties containerQueryProperties, - InputParameters inputParameters, - Documents.PartitionKeyRange targetRange, - CancellationToken cancellationToken) - { - // Return a OptimisticDirectExecution context - return OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( - documentContainer: documentContainer, - inputParameters: inputParameters, - targetRange: new FeedRangeEpk(targetRange.ToRange()), + cosmosQueryContext.QueryClient, + cosmosQueryContext.ResourceLink, + partitionedQueryExecutionInfo, + containerQueryProperties, + inputParameters.Properties, + inputParameters.InitialFeedRange, + trace); + + return TryCreateSpecializedDocumentQueryExecutionContext( + documentContainer, + cosmosQueryContext, + inputParameters, + targetRanges, + containerQueryProperties, + partitionedQueryExecutionInfo); + } + + private static TryCatch TryCreateOptimisticDirectExecutionContext( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + InputParameters inputParameters, + Documents.PartitionKeyRange targetRange, + CancellationToken cancellationToken) + { + // Return a OptimisticDirectExecution context + return OptimisticDirectExecutionQueryPipelineStage.MonadicCreate( + documentContainer: documentContainer, + inputParameters: inputParameters, + targetRange: new FeedRangeEpk(targetRange.ToRange()), + containerQueryProperties: containerQueryProperties, fallbackQueryPipelineStageFactory: (continuationToken) => // In fallback scenario, the Specialized pipeline is always invoked TryCreateSpecializedDocumentQueryExecutionContextAsync( @@ -474,628 +476,632 @@ private static TryCatch TryCreateOptimisticDirectExecutionC inputParameters.WithContinuationToken(continuationToken), NoOpTrace.Singleton, cancellationToken), - cancellationToken: cancellationToken); - } - - private static TryCatch TryCreatePassthroughQueryExecutionContext( - DocumentContainer documentContainer, - InputParameters inputParameters, - List targetRanges) - { - // Return a parallel context, since we still want to be able to handle splits and concurrency / buffering. - return ParallelCrossPartitionQueryPipelineStage.MonadicCreate( - documentContainer: documentContainer, - sqlQuerySpec: inputParameters.SqlQuerySpec, - targetRanges: targetRanges - .Select(range => new FeedRangeEpk( - new Documents.Routing.Range( - min: range.MinInclusive, - max: range.MaxExclusive, - isMinInclusive: true, - isMaxInclusive: false))) - .ToList(), - queryPaginationOptions: new QueryPaginationOptions( - pageSizeHint: inputParameters.MaxItemCount), - partitionKey: inputParameters.PartitionKey, - prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, - maxConcurrency: inputParameters.MaxConcurrency, + cancellationToken: cancellationToken); + } + + private static TryCatch TryCreatePassthroughQueryExecutionContext( + DocumentContainer documentContainer, + InputParameters inputParameters, + List targetRanges, + ContainerQueryProperties containerQueryProperties) + { + // Return a parallel context, since we still want to be able to handle splits and concurrency / buffering. + return ParallelCrossPartitionQueryPipelineStage.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: inputParameters.SqlQuerySpec, + targetRanges: targetRanges + .Select(range => new FeedRangeEpk( + new Documents.Routing.Range( + min: range.MinInclusive, + max: range.MaxExclusive, + isMinInclusive: true, + isMaxInclusive: false))) + .ToList(), + queryPaginationOptions: new QueryPaginationOptions( + pageSizeHint: inputParameters.MaxItemCount), + partitionKey: inputParameters.PartitionKey, + containerQueryProperties: containerQueryProperties, + maxConcurrency: inputParameters.MaxConcurrency, + prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: inputParameters.InitialUserContinuationToken); - } - - private static TryCatch TryCreateSpecializedDocumentQueryExecutionContext( - DocumentContainer documentContainer, - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - List targetRanges) - { - QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; - - // We need to compute the optimal initial page size for order-by queries - long optimalPageSize = inputParameters.MaxItemCount; - if (queryInfo.HasOrderBy) - { - int top; - if (queryInfo.HasTop && (partitionedQueryExecutionInfo.QueryInfo.Top.Value > 0)) - { - top = partitionedQueryExecutionInfo.QueryInfo.Top.Value; - } - else if (queryInfo.HasLimit && (partitionedQueryExecutionInfo.QueryInfo.Limit.Value > 0)) - { - top = (partitionedQueryExecutionInfo.QueryInfo.Offset ?? 0) + partitionedQueryExecutionInfo.QueryInfo.Limit.Value; - } - else - { - top = 0; - } - - if (top > 0) - { - // All partitions should initially fetch about 1/nth of the top value. - long pageSizeWithTop = (long)Math.Min( - Math.Ceiling(top / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop, - top); - - optimalPageSize = Math.Min(pageSizeWithTop, optimalPageSize); - } - else if (cosmosQueryContext.IsContinuationExpected) - { - optimalPageSize = (long)Math.Min( - Math.Ceiling(optimalPageSize / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop, - optimalPageSize); - } - } - - Debug.Assert( - (optimalPageSize > 0) && (optimalPageSize <= int.MaxValue), - $"Invalid MaxItemCount {optimalPageSize}"); - - return PipelineFactory.MonadicCreate( - executionEnvironment: inputParameters.ExecutionEnvironment, - documentContainer: documentContainer, - sqlQuerySpec: inputParameters.SqlQuerySpec, - targetRanges: targetRanges - .Select(range => new FeedRangeEpk( - new Documents.Routing.Range( - min: range.MinInclusive, - max: range.MaxExclusive, - isMinInclusive: true, - isMaxInclusive: false))) - .ToList(), - partitionKey: inputParameters.PartitionKey, - queryInfo: partitionedQueryExecutionInfo.QueryInfo, - queryPaginationOptions: new QueryPaginationOptions( - pageSizeHint: (int)optimalPageSize), - maxConcurrency: inputParameters.MaxConcurrency, + } + + private static TryCatch TryCreateSpecializedDocumentQueryExecutionContext( + DocumentContainer documentContainer, + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + List targetRanges, + ContainerQueryProperties containerQueryProperties) + { + QueryInfo queryInfo = partitionedQueryExecutionInfo.QueryInfo; + + // We need to compute the optimal initial page size for order-by queries + long optimalPageSize = inputParameters.MaxItemCount; + if (queryInfo.HasOrderBy) + { + int top; + if (queryInfo.HasTop && (partitionedQueryExecutionInfo.QueryInfo.Top.Value > 0)) + { + top = partitionedQueryExecutionInfo.QueryInfo.Top.Value; + } + else if (queryInfo.HasLimit && (partitionedQueryExecutionInfo.QueryInfo.Limit.Value > 0)) + { + top = (partitionedQueryExecutionInfo.QueryInfo.Offset ?? 0) + partitionedQueryExecutionInfo.QueryInfo.Limit.Value; + } + else + { + top = 0; + } + + if (top > 0) + { + // All partitions should initially fetch about 1/nth of the top value. + long pageSizeWithTop = (long)Math.Min( + Math.Ceiling(top / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop, + top); + + optimalPageSize = Math.Min(pageSizeWithTop, optimalPageSize); + } + else if (cosmosQueryContext.IsContinuationExpected) + { + optimalPageSize = (long)Math.Min( + Math.Ceiling(optimalPageSize / (double)targetRanges.Count) * CosmosQueryExecutionContextFactory.PageSizeFactorForTop, + optimalPageSize); + } + } + + Debug.Assert( + (optimalPageSize > 0) && (optimalPageSize <= int.MaxValue), + $"Invalid MaxItemCount {optimalPageSize}"); + + return PipelineFactory.MonadicCreate( + executionEnvironment: inputParameters.ExecutionEnvironment, + documentContainer: documentContainer, + sqlQuerySpec: inputParameters.SqlQuerySpec, + targetRanges: targetRanges + .Select(range => new FeedRangeEpk( + new Documents.Routing.Range( + min: range.MinInclusive, + max: range.MaxExclusive, + isMinInclusive: true, + isMaxInclusive: false))) + .ToList(), + partitionKey: inputParameters.PartitionKey, + queryInfo: partitionedQueryExecutionInfo.QueryInfo, + queryPaginationOptions: new QueryPaginationOptions( + pageSizeHint: (int)optimalPageSize), + containerQueryProperties: containerQueryProperties, + maxConcurrency: inputParameters.MaxConcurrency, requestContinuationToken: inputParameters.InitialUserContinuationToken); - } - - private static async Task GetPartitionedQueryExecutionInfoAsync( - CosmosQueryContext cosmosQueryContext, - InputParameters inputParameters, - ContainerQueryProperties containerQueryProperties, - ITrace trace, - CancellationToken cancellationToken) - { - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; - if (cosmosQueryContext.QueryClient.BypassQueryParsing()) - { - // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. - // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this - partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( - cosmosQueryContext, - inputParameters.SqlQuerySpec, - cosmosQueryContext.ResourceLink, - inputParameters.PartitionKey, - trace, - cancellationToken); - } - else - { - Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - - partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( - cosmosQueryContext.QueryClient, - inputParameters.SqlQuerySpec, - cosmosQueryContext.ResourceTypeEnum, - partitionKeyDefinition, - inputParameters.PartitionKey != null, - containerQueryProperties.GeospatialType, - cosmosQueryContext.UseSystemPrefix, - trace, - cancellationToken); - } - - return partitionedQueryExecutionInfo; - } - - /// - /// Gets the list of partition key ranges. - /// 1. Check partition key range id - /// 2. Check Partition key - /// 3. Check the effective partition key - /// 4. Get the range from the FeedToken - /// 5. Get the range from the PartitionedQueryExecutionInfo - /// - internal static async Task> GetTargetPartitionKeyRangesAsync( - CosmosQueryClient queryClient, - string resourceLink, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - ContainerQueryProperties containerQueryProperties, - IReadOnlyDictionary properties, - FeedRangeInternal feedRangeInternal, - ITrace trace) - { - List targetRanges; - if (containerQueryProperties.EffectiveRangesForPartitionKey != null) - { - targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( - resourceLink, - containerQueryProperties.ResourceId, - containerQueryProperties.EffectiveRangesForPartitionKey, - forceRefresh: false, - trace); - } - else if (TryGetEpkProperty(properties, out string effectivePartitionKeyString)) - { - //Note that here we have no way to consume the EPK string as there is no way to convert - //the string to the partition key type to evaulate the number of components which needs to be done for the - //multihahs methods/classes. This is particually important for queries with prefix partition key. - //the EPK sting header is only for internal use but this needs to be fixed in the future. - List> effectiveRanges = new List> - { Range.GetPointRange(effectivePartitionKeyString) }; - - targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( - resourceLink, - containerQueryProperties.ResourceId, - effectiveRanges, - forceRefresh: false, - trace); - } - else if (feedRangeInternal != null) - { - targetRanges = await queryClient.GetTargetPartitionKeyRangeByFeedRangeAsync( - resourceLink, - containerQueryProperties.ResourceId, - containerQueryProperties.PartitionKeyDefinition, - feedRangeInternal, - forceRefresh: false, - trace); - } - else - { - targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( - resourceLink, - containerQueryProperties.ResourceId, - partitionedQueryExecutionInfo.QueryRanges, - forceRefresh: false, - trace); - } - - return targetRanges; - } - - private static bool TryGetEpkProperty( - IReadOnlyDictionary properties, - out string effectivePartitionKeyString) - { - if (properties != null - && properties.TryGetValue( - Documents.WFConstants.BackendHeaders.EffectivePartitionKeyString, - out object effectivePartitionKeyStringObject)) - { - effectivePartitionKeyString = effectivePartitionKeyStringObject as string; - if (string.IsNullOrEmpty(effectivePartitionKeyString)) - { - throw new ArgumentOutOfRangeException(nameof(effectivePartitionKeyString)); - } - - return true; - } - - effectivePartitionKeyString = null; - return false; - } - - private static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) - { - TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; - if (responseStats != null) - { - if (pipelineType == OptimisticDirectExecution) - { - responseStats.PipelineType = TestInjections.PipelineType.OptimisticDirectExecution; - } - else if (pipelineType == Specialized) - { - responseStats.PipelineType = TestInjections.PipelineType.Specialized; - } - else - { - responseStats.PipelineType = TestInjections.PipelineType.Passthrough; - } - } - } - - private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputParameters inputParameters, ContainerQueryProperties containerQueryProperties) - { - //todo:elasticcollections this may rely on information from collection cache which is outdated - //if collection is deleted/created with same name. - //need to make it not rely on information from collection cache. - - Documents.PartitionKeyDefinition partitionKeyDefinition; - if ((inputParameters.Properties != null) - && inputParameters.Properties.TryGetValue(InternalPartitionKeyDefinitionProperty, out object partitionKeyDefinitionObject)) - { - if (!(partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)) - { - throw new ArgumentException( - "partitionkeydefinition has invalid type", - nameof(partitionKeyDefinitionObject)); - } - - partitionKeyDefinition = definition; - } - else - { - partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition; - } - - return partitionKeyDefinition; - } - - private static async Task TryGetTargetRangeOptimisticDirectExecutionAsync( - InputParameters inputParameters, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - CosmosQueryContext cosmosQueryContext, - ContainerQueryProperties containerQueryProperties, - ITrace trace) - { - bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); - - // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true - if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) - { - if (inputParameters.InitialUserContinuationToken != null - && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) - { - string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - - throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}"); - } - - return null; - } - - Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); - - List targetRanges; - if (partitionedQueryExecutionInfo != null || inputParameters.InitialFeedRange != null) - { + } + + private static async Task GetPartitionedQueryExecutionInfoAsync( + CosmosQueryContext cosmosQueryContext, + InputParameters inputParameters, + ContainerQueryProperties containerQueryProperties, + ITrace trace, + CancellationToken cancellationToken) + { + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; + if (cosmosQueryContext.QueryClient.BypassQueryParsing()) + { + // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case. + // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this + partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanThroughGatewayAsync( + cosmosQueryContext, + inputParameters.SqlQuerySpec, + cosmosQueryContext.ResourceLink, + inputParameters.PartitionKey, + trace, + cancellationToken); + } + else + { + Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); + + partitionedQueryExecutionInfo = await QueryPlanRetriever.GetQueryPlanWithServiceInteropAsync( + cosmosQueryContext.QueryClient, + inputParameters.SqlQuerySpec, + cosmosQueryContext.ResourceTypeEnum, + partitionKeyDefinition, + inputParameters.PartitionKey != null, + containerQueryProperties.GeospatialType, + cosmosQueryContext.UseSystemPrefix, + trace, + cancellationToken); + } + + return partitionedQueryExecutionInfo; + } + + /// + /// Gets the list of partition key ranges. + /// 1. Check partition key range id + /// 2. Check Partition key + /// 3. Check the effective partition key + /// 4. Get the range from the FeedToken + /// 5. Get the range from the PartitionedQueryExecutionInfo + /// + internal static async Task> GetTargetPartitionKeyRangesAsync( + CosmosQueryClient queryClient, + string resourceLink, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + ContainerQueryProperties containerQueryProperties, + IReadOnlyDictionary properties, + FeedRangeInternal feedRangeInternal, + ITrace trace) + { + List targetRanges; + if (containerQueryProperties.EffectiveRangesForPartitionKey != null) + { + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( + resourceLink, + containerQueryProperties.ResourceId, + containerQueryProperties.EffectiveRangesForPartitionKey, + forceRefresh: false, + trace); + } + else if (TryGetEpkProperty(properties, out string effectivePartitionKeyString)) + { + //Note that here we have no way to consume the EPK string as there is no way to convert + //the string to the partition key type to evaulate the number of components which needs to be done for the + //multihahs methods/classes. This is particually important for queries with prefix partition key. + //the EPK sting header is only for internal use but this needs to be fixed in the future. + List> effectiveRanges = new List> + { Range.GetPointRange(effectivePartitionKeyString) }; + + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( + resourceLink, + containerQueryProperties.ResourceId, + effectiveRanges, + forceRefresh: false, + trace); + } + else if (feedRangeInternal != null) + { + targetRanges = await queryClient.GetTargetPartitionKeyRangeByFeedRangeAsync( + resourceLink, + containerQueryProperties.ResourceId, + containerQueryProperties.PartitionKeyDefinition, + feedRangeInternal, + forceRefresh: false, + trace); + } + else + { + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( + resourceLink, + containerQueryProperties.ResourceId, + partitionedQueryExecutionInfo.QueryRanges, + forceRefresh: false, + trace); + } + + return targetRanges; + } + + private static bool TryGetEpkProperty( + IReadOnlyDictionary properties, + out string effectivePartitionKeyString) + { + if (properties != null + && properties.TryGetValue( + Documents.WFConstants.BackendHeaders.EffectivePartitionKeyString, + out object effectivePartitionKeyStringObject)) + { + effectivePartitionKeyString = effectivePartitionKeyStringObject as string; + if (string.IsNullOrEmpty(effectivePartitionKeyString)) + { + throw new ArgumentOutOfRangeException(nameof(effectivePartitionKeyString)); + } + + return true; + } + + effectivePartitionKeyString = null; + return false; + } + + private static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) + { + TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; + if (responseStats != null) + { + if (pipelineType == OptimisticDirectExecution) + { + responseStats.PipelineType = TestInjections.PipelineType.OptimisticDirectExecution; + } + else if (pipelineType == Specialized) + { + responseStats.PipelineType = TestInjections.PipelineType.Specialized; + } + else + { + responseStats.PipelineType = TestInjections.PipelineType.Passthrough; + } + } + } + + private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputParameters inputParameters, ContainerQueryProperties containerQueryProperties) + { + //todo:elasticcollections this may rely on information from collection cache which is outdated + //if collection is deleted/created with same name. + //need to make it not rely on information from collection cache. + + Documents.PartitionKeyDefinition partitionKeyDefinition; + if ((inputParameters.Properties != null) + && inputParameters.Properties.TryGetValue(InternalPartitionKeyDefinitionProperty, out object partitionKeyDefinitionObject)) + { + if (!(partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)) + { + throw new ArgumentException( + "partitionkeydefinition has invalid type", + nameof(partitionKeyDefinitionObject)); + } + + partitionKeyDefinition = definition; + } + else + { + partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition; + } + + return partitionKeyDefinition; + } + + private static async Task TryGetTargetRangeOptimisticDirectExecutionAsync( + InputParameters inputParameters, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + CosmosQueryContext cosmosQueryContext, + ContainerQueryProperties containerQueryProperties, + ITrace trace) + { + bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); + + // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true + if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) + { + if (inputParameters.InitialUserContinuationToken != null + && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) + { + string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + + "If the error persists after that, contact system administrator."; + + throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}"); + } + + return null; + } + + Debug.Assert(containerQueryProperties.ResourceId != null, "CosmosQueryExecutionContextFactory Assert!", "Container ResourceId cannot be null!"); + + List targetRanges; + if (partitionedQueryExecutionInfo != null || inputParameters.InitialFeedRange != null) + { targetRanges = await GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.QueryClient, - cosmosQueryContext.ResourceLink, - partitionedQueryExecutionInfo, - containerQueryProperties, - inputParameters.Properties, - inputParameters.InitialFeedRange, - trace); - } - else - { - Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - if (inputParameters.PartitionKey.HasValue) - { - Debug.Assert(partitionKeyDefinition != null, "CosmosQueryExecutionContextFactory Assert!", "PartitionKeyDefinition cannot be null if partitionKey is defined"); - targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.ResourceLink, - containerQueryProperties.ResourceId, - containerQueryProperties.EffectiveRangesForPartitionKey, - forceRefresh: false, - trace); - } - else - { - targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( - cosmosQueryContext.ResourceLink, - containerQueryProperties.ResourceId, - new List> { FeedRangeEpk.FullRange.Range }, - forceRefresh: false, - trace); - } - } - - if (targetRanges.Count == 1) - { - return targetRanges.Single(); - } - - return null; - } - - public sealed class InputParameters - { - private const int DefaultMaxConcurrency = 0; - private const int DefaultMaxItemCount = 1000; - private const int DefaultMaxBufferedItemCount = 1000; - private const bool DefaultReturnResultsInDeterministicOrder = true; - private const ExecutionEnvironment DefaultExecutionEnvironment = ExecutionEnvironment.Client; - - public InputParameters( - SqlQuerySpec sqlQuerySpec, - CosmosElement initialUserContinuationToken, - FeedRangeInternal initialFeedRange, - int? maxConcurrency, - int? maxItemCount, - int? maxBufferedItemCount, - PartitionKey? partitionKey, - IReadOnlyDictionary properties, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, - ExecutionEnvironment? executionEnvironment, - bool? returnResultsInDeterministicOrder, - bool enableOptimisticDirectExecution, - TestInjections testInjections) - { - this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); - this.InitialUserContinuationToken = initialUserContinuationToken; - this.InitialFeedRange = initialFeedRange; - - int resolvedMaxConcurrency = maxConcurrency.GetValueOrDefault(InputParameters.DefaultMaxConcurrency); - if (resolvedMaxConcurrency < 0) - { - resolvedMaxConcurrency = int.MaxValue; - } - this.MaxConcurrency = resolvedMaxConcurrency; - - int resolvedMaxItemCount = maxItemCount.GetValueOrDefault(InputParameters.DefaultMaxItemCount); - if (resolvedMaxItemCount < 0) - { - resolvedMaxItemCount = int.MaxValue; - } - this.MaxItemCount = resolvedMaxItemCount; - - int resolvedMaxBufferedItemCount = maxBufferedItemCount.GetValueOrDefault(InputParameters.DefaultMaxBufferedItemCount); - if (resolvedMaxBufferedItemCount < 0) - { - resolvedMaxBufferedItemCount = int.MaxValue; - } - this.MaxBufferedItemCount = resolvedMaxBufferedItemCount; - - this.PartitionKey = partitionKey; - this.Properties = properties; - this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; - this.ExecutionEnvironment = executionEnvironment.GetValueOrDefault(InputParameters.DefaultExecutionEnvironment); - this.ReturnResultsInDeterministicOrder = returnResultsInDeterministicOrder.GetValueOrDefault(InputParameters.DefaultReturnResultsInDeterministicOrder); - this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; - this.TestInjections = testInjections; - } - - public SqlQuerySpec SqlQuerySpec { get; } - public CosmosElement InitialUserContinuationToken { get; } - public FeedRangeInternal InitialFeedRange { get; } - public int MaxConcurrency { get; } - public int MaxItemCount { get; } - public int MaxBufferedItemCount { get; } - public PartitionKey? PartitionKey { get; } - public IReadOnlyDictionary Properties { get; } - public PartitionedQueryExecutionInfo PartitionedQueryExecutionInfo { get; } - public ExecutionEnvironment ExecutionEnvironment { get; } - public bool ReturnResultsInDeterministicOrder { get; } - public TestInjections TestInjections { get; } - public bool EnableOptimisticDirectExecution { get; } - - public InputParameters WithContinuationToken(CosmosElement token) - { - return new InputParameters( - this.SqlQuerySpec, - token, - this.InitialFeedRange, - this.MaxConcurrency, - this.MaxItemCount, - this.MaxBufferedItemCount, - this.PartitionKey, - this.Properties, - this.PartitionedQueryExecutionInfo, - this.ExecutionEnvironment, - this.ReturnResultsInDeterministicOrder, - this.EnableOptimisticDirectExecution, - this.TestInjections); - } - } - - internal sealed class AggregateProjectionDetector - { - /// - /// Determines whether or not the SqlSelectSpec has an aggregate in the outer most query. - /// - /// The select spec to traverse. - /// Whether or not the SqlSelectSpec has an aggregate in the outer most query. - public static bool HasAggregate(SqlSelectSpec selectSpec) - { - return selectSpec.Accept(AggregateProjectionDectorVisitor.Singleton); - } - - private sealed class AggregateProjectionDectorVisitor : SqlSelectSpecVisitor - { - public static readonly AggregateProjectionDectorVisitor Singleton = new AggregateProjectionDectorVisitor(); - - public override bool Visit(SqlSelectListSpec selectSpec) - { - bool hasAggregates = false; - foreach (SqlSelectItem selectItem in selectSpec.Items) - { - hasAggregates |= selectItem.Expression.Accept(AggregateScalarExpressionDetector.Singleton); - } - - return hasAggregates; - } - - public override bool Visit(SqlSelectValueSpec selectSpec) - { - return selectSpec.Expression.Accept(AggregateScalarExpressionDetector.Singleton); - } - - public override bool Visit(SqlSelectStarSpec selectSpec) - { - return false; - } - - /// - /// Determines if there is an aggregate in a scalar expression. - /// - private sealed class AggregateScalarExpressionDetector : SqlScalarExpressionVisitor - { - private enum Aggregate - { - Min, - Max, - Sum, - Count, - Avg, - } - - public static readonly AggregateScalarExpressionDetector Singleton = new AggregateScalarExpressionDetector(); - - public override bool Visit(SqlAllScalarExpression sqlAllScalarExpression) - { - // No need to worry about aggregates within the subquery (they will recursively get rewritten). - return false; - } - - public override bool Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) - { - bool hasAggregates = false; - foreach (SqlScalarExpression item in sqlArrayCreateScalarExpression.Items) - { - hasAggregates |= item.Accept(this); - } - - return hasAggregates; - } - - public override bool Visit(SqlArrayScalarExpression sqlArrayScalarExpression) - { - // No need to worry about aggregates in the subquery (they will recursively get rewritten). - return false; - } - - public override bool Visit(SqlBetweenScalarExpression sqlBetweenScalarExpression) - { - return sqlBetweenScalarExpression.Expression.Accept(this) || - sqlBetweenScalarExpression.StartInclusive.Accept(this) || - sqlBetweenScalarExpression.EndInclusive.Accept(this); - } - - public override bool Visit(SqlBinaryScalarExpression sqlBinaryScalarExpression) - { - return sqlBinaryScalarExpression.LeftExpression.Accept(this) || - sqlBinaryScalarExpression.RightExpression.Accept(this); - } - - public override bool Visit(SqlCoalesceScalarExpression sqlCoalesceScalarExpression) - { - return sqlCoalesceScalarExpression.Left.Accept(this) || - sqlCoalesceScalarExpression.Right.Accept(this); - } - - public override bool Visit(SqlConditionalScalarExpression sqlConditionalScalarExpression) - { - return sqlConditionalScalarExpression.Condition.Accept(this) || - sqlConditionalScalarExpression.Consequent.Accept(this) || - sqlConditionalScalarExpression.Alternative.Accept(this); - } - - public override bool Visit(SqlExistsScalarExpression sqlExistsScalarExpression) - { - // No need to worry about aggregates within the subquery (they will recursively get rewritten). - return false; - } - - public override bool Visit(SqlFirstScalarExpression sqlFirstScalarExpression) - { - // No need to worry about aggregates within the subquery (they will recursively get rewritten). - return false; - } - - public override bool Visit(SqlFunctionCallScalarExpression sqlFunctionCallScalarExpression) - { - return !sqlFunctionCallScalarExpression.IsUdf && - Enum.TryParse(value: sqlFunctionCallScalarExpression.Name.Value, ignoreCase: true, result: out _); - } - - public override bool Visit(SqlInScalarExpression sqlInScalarExpression) - { - bool hasAggregates = false; - for (int i = 0; i < sqlInScalarExpression.Haystack.Length; i++) - { - hasAggregates |= sqlInScalarExpression.Haystack[i].Accept(this); - } - - return hasAggregates; - } - - public override bool Visit(SqlLastScalarExpression sqlLastScalarExpression) - { - // No need to worry about aggregates within the subquery (they will recursively get rewritten). - return false; - } - - public override bool Visit(SqlLiteralScalarExpression sqlLiteralScalarExpression) - { - return false; - } - - public override bool Visit(SqlMemberIndexerScalarExpression sqlMemberIndexerScalarExpression) - { - return sqlMemberIndexerScalarExpression.Member.Accept(this) || - sqlMemberIndexerScalarExpression.Indexer.Accept(this); - } - - public override bool Visit(SqlObjectCreateScalarExpression sqlObjectCreateScalarExpression) - { - bool hasAggregates = false; - foreach (SqlObjectProperty property in sqlObjectCreateScalarExpression.Properties) - { - hasAggregates |= property.Value.Accept(this); - } - - return hasAggregates; - } - - public override bool Visit(SqlPropertyRefScalarExpression sqlPropertyRefScalarExpression) - { - bool hasAggregates = false; - if (sqlPropertyRefScalarExpression.Member != null) - { - hasAggregates = sqlPropertyRefScalarExpression.Member.Accept(this); - } - - return hasAggregates; - } - - public override bool Visit(SqlSubqueryScalarExpression sqlSubqueryScalarExpression) - { - // No need to worry about the aggregates within the subquery since they get recursively evaluated. - return false; - } - - public override bool Visit(SqlUnaryScalarExpression sqlUnaryScalarExpression) - { - return sqlUnaryScalarExpression.Expression.Accept(this); - } - - public override bool Visit(SqlParameterRefScalarExpression scalarExpression) - { - return false; - } - - public override bool Visit(SqlLikeScalarExpression scalarExpression) - { - return false; - } - } - } - } - } + cosmosQueryContext.QueryClient, + cosmosQueryContext.ResourceLink, + partitionedQueryExecutionInfo, + containerQueryProperties, + inputParameters.Properties, + inputParameters.InitialFeedRange, + trace); + } + else + { + Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); + if (inputParameters.PartitionKey.HasValue) + { + Debug.Assert(partitionKeyDefinition != null, "CosmosQueryExecutionContextFactory Assert!", "PartitionKeyDefinition cannot be null if partitionKey is defined"); + targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( + cosmosQueryContext.ResourceLink, + containerQueryProperties.ResourceId, + containerQueryProperties.EffectiveRangesForPartitionKey, + forceRefresh: false, + trace); + } + else + { + targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( + cosmosQueryContext.ResourceLink, + containerQueryProperties.ResourceId, + new List> { FeedRangeEpk.FullRange.Range }, + forceRefresh: false, + trace); + } + } + + if (targetRanges.Count == 1) + { + return targetRanges.Single(); + } + + return null; + } + + public sealed class InputParameters + { + private const int DefaultMaxConcurrency = 0; + private const int DefaultMaxItemCount = 1000; + private const int DefaultMaxBufferedItemCount = 1000; + private const bool DefaultReturnResultsInDeterministicOrder = true; + private const ExecutionEnvironment DefaultExecutionEnvironment = ExecutionEnvironment.Client; + + public InputParameters( + SqlQuerySpec sqlQuerySpec, + CosmosElement initialUserContinuationToken, + FeedRangeInternal initialFeedRange, + int? maxConcurrency, + int? maxItemCount, + int? maxBufferedItemCount, + PartitionKey? partitionKey, + IReadOnlyDictionary properties, + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + ExecutionEnvironment? executionEnvironment, + bool? returnResultsInDeterministicOrder, + bool enableOptimisticDirectExecution, + TestInjections testInjections) + { + this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); + this.InitialUserContinuationToken = initialUserContinuationToken; + this.InitialFeedRange = initialFeedRange; + + int resolvedMaxConcurrency = maxConcurrency.GetValueOrDefault(InputParameters.DefaultMaxConcurrency); + if (resolvedMaxConcurrency < 0) + { + resolvedMaxConcurrency = int.MaxValue; + } + this.MaxConcurrency = resolvedMaxConcurrency; + + int resolvedMaxItemCount = maxItemCount.GetValueOrDefault(InputParameters.DefaultMaxItemCount); + if (resolvedMaxItemCount < 0) + { + resolvedMaxItemCount = int.MaxValue; + } + this.MaxItemCount = resolvedMaxItemCount; + + int resolvedMaxBufferedItemCount = maxBufferedItemCount.GetValueOrDefault(InputParameters.DefaultMaxBufferedItemCount); + if (resolvedMaxBufferedItemCount < 0) + { + resolvedMaxBufferedItemCount = int.MaxValue; + } + this.MaxBufferedItemCount = resolvedMaxBufferedItemCount; + + this.PartitionKey = partitionKey; + this.Properties = properties; + this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; + this.ExecutionEnvironment = executionEnvironment.GetValueOrDefault(InputParameters.DefaultExecutionEnvironment); + this.ReturnResultsInDeterministicOrder = returnResultsInDeterministicOrder.GetValueOrDefault(InputParameters.DefaultReturnResultsInDeterministicOrder); + this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; + this.TestInjections = testInjections; + } + + public SqlQuerySpec SqlQuerySpec { get; } + public CosmosElement InitialUserContinuationToken { get; } + public FeedRangeInternal InitialFeedRange { get; } + public int MaxConcurrency { get; } + public int MaxItemCount { get; } + public int MaxBufferedItemCount { get; } + public PartitionKey? PartitionKey { get; } + public IReadOnlyDictionary Properties { get; } + public PartitionedQueryExecutionInfo PartitionedQueryExecutionInfo { get; } + public ExecutionEnvironment ExecutionEnvironment { get; } + public bool ReturnResultsInDeterministicOrder { get; } + public TestInjections TestInjections { get; } + public bool EnableOptimisticDirectExecution { get; } + + public InputParameters WithContinuationToken(CosmosElement token) + { + return new InputParameters( + this.SqlQuerySpec, + token, + this.InitialFeedRange, + this.MaxConcurrency, + this.MaxItemCount, + this.MaxBufferedItemCount, + this.PartitionKey, + this.Properties, + this.PartitionedQueryExecutionInfo, + this.ExecutionEnvironment, + this.ReturnResultsInDeterministicOrder, + this.EnableOptimisticDirectExecution, + this.TestInjections); + } + } + + internal sealed class AggregateProjectionDetector + { + /// + /// Determines whether or not the SqlSelectSpec has an aggregate in the outer most query. + /// + /// The select spec to traverse. + /// Whether or not the SqlSelectSpec has an aggregate in the outer most query. + public static bool HasAggregate(SqlSelectSpec selectSpec) + { + return selectSpec.Accept(AggregateProjectionDectorVisitor.Singleton); + } + + private sealed class AggregateProjectionDectorVisitor : SqlSelectSpecVisitor + { + public static readonly AggregateProjectionDectorVisitor Singleton = new AggregateProjectionDectorVisitor(); + + public override bool Visit(SqlSelectListSpec selectSpec) + { + bool hasAggregates = false; + foreach (SqlSelectItem selectItem in selectSpec.Items) + { + hasAggregates |= selectItem.Expression.Accept(AggregateScalarExpressionDetector.Singleton); + } + + return hasAggregates; + } + + public override bool Visit(SqlSelectValueSpec selectSpec) + { + return selectSpec.Expression.Accept(AggregateScalarExpressionDetector.Singleton); + } + + public override bool Visit(SqlSelectStarSpec selectSpec) + { + return false; + } + + /// + /// Determines if there is an aggregate in a scalar expression. + /// + private sealed class AggregateScalarExpressionDetector : SqlScalarExpressionVisitor + { + private enum Aggregate + { + Min, + Max, + Sum, + Count, + Avg, + } + + public static readonly AggregateScalarExpressionDetector Singleton = new AggregateScalarExpressionDetector(); + + public override bool Visit(SqlAllScalarExpression sqlAllScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + + public override bool Visit(SqlArrayCreateScalarExpression sqlArrayCreateScalarExpression) + { + bool hasAggregates = false; + foreach (SqlScalarExpression item in sqlArrayCreateScalarExpression.Items) + { + hasAggregates |= item.Accept(this); + } + + return hasAggregates; + } + + public override bool Visit(SqlArrayScalarExpression sqlArrayScalarExpression) + { + // No need to worry about aggregates in the subquery (they will recursively get rewritten). + return false; + } + + public override bool Visit(SqlBetweenScalarExpression sqlBetweenScalarExpression) + { + return sqlBetweenScalarExpression.Expression.Accept(this) || + sqlBetweenScalarExpression.StartInclusive.Accept(this) || + sqlBetweenScalarExpression.EndInclusive.Accept(this); + } + + public override bool Visit(SqlBinaryScalarExpression sqlBinaryScalarExpression) + { + return sqlBinaryScalarExpression.LeftExpression.Accept(this) || + sqlBinaryScalarExpression.RightExpression.Accept(this); + } + + public override bool Visit(SqlCoalesceScalarExpression sqlCoalesceScalarExpression) + { + return sqlCoalesceScalarExpression.Left.Accept(this) || + sqlCoalesceScalarExpression.Right.Accept(this); + } + + public override bool Visit(SqlConditionalScalarExpression sqlConditionalScalarExpression) + { + return sqlConditionalScalarExpression.Condition.Accept(this) || + sqlConditionalScalarExpression.Consequent.Accept(this) || + sqlConditionalScalarExpression.Alternative.Accept(this); + } + + public override bool Visit(SqlExistsScalarExpression sqlExistsScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + + public override bool Visit(SqlFirstScalarExpression sqlFirstScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + + public override bool Visit(SqlFunctionCallScalarExpression sqlFunctionCallScalarExpression) + { + return !sqlFunctionCallScalarExpression.IsUdf && + Enum.TryParse(value: sqlFunctionCallScalarExpression.Name.Value, ignoreCase: true, result: out _); + } + + public override bool Visit(SqlInScalarExpression sqlInScalarExpression) + { + bool hasAggregates = false; + for (int i = 0; i < sqlInScalarExpression.Haystack.Length; i++) + { + hasAggregates |= sqlInScalarExpression.Haystack[i].Accept(this); + } + + return hasAggregates; + } + + public override bool Visit(SqlLastScalarExpression sqlLastScalarExpression) + { + // No need to worry about aggregates within the subquery (they will recursively get rewritten). + return false; + } + + public override bool Visit(SqlLiteralScalarExpression sqlLiteralScalarExpression) + { + return false; + } + + public override bool Visit(SqlMemberIndexerScalarExpression sqlMemberIndexerScalarExpression) + { + return sqlMemberIndexerScalarExpression.Member.Accept(this) || + sqlMemberIndexerScalarExpression.Indexer.Accept(this); + } + + public override bool Visit(SqlObjectCreateScalarExpression sqlObjectCreateScalarExpression) + { + bool hasAggregates = false; + foreach (SqlObjectProperty property in sqlObjectCreateScalarExpression.Properties) + { + hasAggregates |= property.Value.Accept(this); + } + + return hasAggregates; + } + + public override bool Visit(SqlPropertyRefScalarExpression sqlPropertyRefScalarExpression) + { + bool hasAggregates = false; + if (sqlPropertyRefScalarExpression.Member != null) + { + hasAggregates = sqlPropertyRefScalarExpression.Member.Accept(this); + } + + return hasAggregates; + } + + public override bool Visit(SqlSubqueryScalarExpression sqlSubqueryScalarExpression) + { + // No need to worry about the aggregates within the subquery since they get recursively evaluated. + return false; + } + + public override bool Visit(SqlUnaryScalarExpression sqlUnaryScalarExpression) + { + return sqlUnaryScalarExpression.Expression.Accept(this); + } + + public override bool Visit(SqlParameterRefScalarExpression scalarExpression) + { + return false; + } + + public override bool Visit(SqlLikeScalarExpression scalarExpression) + { + return false; + } + } + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs index d9b564b5f3..7f1d1079c1 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/ParallelCrossPartitionQueryPipelineStage.cs @@ -1,273 +1,277 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Exceptions; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Tracing; - using static Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.PartitionMapper; - - /// - /// is an implementation of that drain results from multiple remote nodes. - /// This class is responsible for draining cross partition queries that do not have order by conditions. - /// The way parallel queries work is that it drains from the left most partition first. - /// This class handles draining in the correct order and can also stop and resume the query - /// by generating a continuation token and resuming from said continuation token. - /// - internal sealed class ParallelCrossPartitionQueryPipelineStage : IQueryPipelineStage - { - private readonly CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator; - - private ParallelCrossPartitionQueryPipelineStage( +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Exceptions; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Tracing; + using static Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.PartitionMapper; + + /// + /// is an implementation of that drain results from multiple remote nodes. + /// This class is responsible for draining cross partition queries that do not have order by conditions. + /// The way parallel queries work is that it drains from the left most partition first. + /// This class handles draining in the correct order and can also stop and resume the query + /// by generating a continuation token and resuming from said continuation token. + /// + internal sealed class ParallelCrossPartitionQueryPipelineStage : IQueryPipelineStage + { + private readonly CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator; + + private ParallelCrossPartitionQueryPipelineStage( CrossPartitionRangePageAsyncEnumerator crossPartitionRangePageAsyncEnumerator) - { - this.crossPartitionRangePageAsyncEnumerator = crossPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(crossPartitionRangePageAsyncEnumerator)); - } - - public TryCatch Current { get; private set; } - - public ValueTask DisposeAsync() - { - return this.crossPartitionRangePageAsyncEnumerator.DisposeAsync(); - } - - // In order to maintain the continuation token for the user we must drain with a few constraints - // 1) We fully drain from the left most partition before moving on to the next partition - // 2) We drain only full pages from the document producer so we aren't left with a partial page - // otherwise we would need to add to the continuation token how many items to skip over on that page. + { + this.crossPartitionRangePageAsyncEnumerator = crossPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(crossPartitionRangePageAsyncEnumerator)); + } + + public TryCatch Current { get; private set; } + + public ValueTask DisposeAsync() + { + return this.crossPartitionRangePageAsyncEnumerator.DisposeAsync(); + } + + // In order to maintain the continuation token for the user we must drain with a few constraints + // 1) We fully drain from the left most partition before moving on to the next partition + // 2) We drain only full pages from the document producer so we aren't left with a partial page + // otherwise we would need to add to the continuation token how many items to skip over on that page. public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) - { - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - + { + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + if (!await this.crossPartitionRangePageAsyncEnumerator.MoveNextAsync(trace, cancellationToken)) - { - this.Current = default; - return false; - } - - TryCatch> currentCrossPartitionPage = this.crossPartitionRangePageAsyncEnumerator.Current; - if (currentCrossPartitionPage.Failed) - { - this.Current = TryCatch.FromException(currentCrossPartitionPage.Exception); - return true; - } - - CrossFeedRangePage crossPartitionPageResult = currentCrossPartitionPage.Result; - QueryPage backendQueryPage = crossPartitionPageResult.Page; - CrossFeedRangeState crossPartitionState = crossPartitionPageResult.State; - - QueryState queryState; - if (crossPartitionState == null) - { - queryState = null; - } - else - { - // left most and any non null continuations - IOrderedEnumerable> feedRangeStates = crossPartitionState - .Value - .ToArray() - .OrderBy(tuple => ((FeedRangeEpk)tuple.FeedRange).Range.Min); - - List activeParallelContinuationTokens = new List(); - { - FeedRangeState firstState = feedRangeStates.First(); - ParallelContinuationToken firstParallelContinuationToken = new ParallelContinuationToken( - token: firstState.State != null ? ((CosmosString)firstState.State.Value).Value : null, - range: ((FeedRangeEpk)firstState.FeedRange).Range); - - activeParallelContinuationTokens.Add(firstParallelContinuationToken); - } - - foreach (FeedRangeState feedRangeState in feedRangeStates.Skip(1)) - { + { + this.Current = default; + return false; + } + + TryCatch> currentCrossPartitionPage = this.crossPartitionRangePageAsyncEnumerator.Current; + if (currentCrossPartitionPage.Failed) + { + this.Current = TryCatch.FromException(currentCrossPartitionPage.Exception); + return true; + } + + CrossFeedRangePage crossPartitionPageResult = currentCrossPartitionPage.Result; + QueryPage backendQueryPage = crossPartitionPageResult.Page; + CrossFeedRangeState crossPartitionState = crossPartitionPageResult.State; + + QueryState queryState; + if (crossPartitionState == null) + { + queryState = null; + } + else + { + // left most and any non null continuations + IOrderedEnumerable> feedRangeStates = crossPartitionState + .Value + .ToArray() + .OrderBy(tuple => ((FeedRangeEpk)tuple.FeedRange).Range.Min); + + List activeParallelContinuationTokens = new List(); + { + FeedRangeState firstState = feedRangeStates.First(); + ParallelContinuationToken firstParallelContinuationToken = new ParallelContinuationToken( + token: firstState.State != null ? ((CosmosString)firstState.State.Value).Value : null, + range: ((FeedRangeEpk)firstState.FeedRange).Range); + + activeParallelContinuationTokens.Add(firstParallelContinuationToken); + } + + foreach (FeedRangeState feedRangeState in feedRangeStates.Skip(1)) + { cancellationToken.ThrowIfCancellationRequested(); - - if (feedRangeState.State != null) - { - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: feedRangeState.State != null ? ((CosmosString)feedRangeState.State.Value).Value : null, - range: ((FeedRangeEpk)feedRangeState.FeedRange).Range); - - activeParallelContinuationTokens.Add(parallelContinuationToken); - } - } - - IEnumerable cosmosElementContinuationTokens = activeParallelContinuationTokens - .Select(token => ParallelContinuationToken.ToCosmosElement(token)); - CosmosArray cosmosElementParallelContinuationTokens = CosmosArray.Create(cosmosElementContinuationTokens); - - queryState = new QueryState(cosmosElementParallelContinuationTokens); - } - - QueryPage crossPartitionQueryPage = new QueryPage( - backendQueryPage.Documents, - backendQueryPage.RequestCharge, - backendQueryPage.ActivityId, - backendQueryPage.CosmosQueryExecutionInfo, - distributionPlanSpec: default, - backendQueryPage.DisallowContinuationTokenMessage, - backendQueryPage.AdditionalHeaders, + + if (feedRangeState.State != null) + { + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: feedRangeState.State != null ? ((CosmosString)feedRangeState.State.Value).Value : null, + range: ((FeedRangeEpk)feedRangeState.FeedRange).Range); + + activeParallelContinuationTokens.Add(parallelContinuationToken); + } + } + + IEnumerable cosmosElementContinuationTokens = activeParallelContinuationTokens + .Select(token => ParallelContinuationToken.ToCosmosElement(token)); + CosmosArray cosmosElementParallelContinuationTokens = CosmosArray.Create(cosmosElementContinuationTokens); + + queryState = new QueryState(cosmosElementParallelContinuationTokens); + } + + QueryPage crossPartitionQueryPage = new QueryPage( + backendQueryPage.Documents, + backendQueryPage.RequestCharge, + backendQueryPage.ActivityId, + backendQueryPage.CosmosQueryExecutionInfo, + distributionPlanSpec: default, + backendQueryPage.DisallowContinuationTokenMessage, + backendQueryPage.AdditionalHeaders, queryState, backendQueryPage.Streaming); - - this.Current = TryCatch.FromResult(crossPartitionQueryPage); - return true; - } - - public static TryCatch MonadicCreate( - IDocumentContainer documentContainer, - SqlQuerySpec sqlQuerySpec, - IReadOnlyList targetRanges, - Cosmos.PartitionKey? partitionKey, - QueryPaginationOptions queryPaginationOptions, - int maxConcurrency, - PrefetchPolicy prefetchPolicy, + + this.Current = TryCatch.FromResult(crossPartitionQueryPage); + return true; + } + + public static TryCatch MonadicCreate( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + IReadOnlyList targetRanges, + Cosmos.PartitionKey? partitionKey, + QueryPaginationOptions queryPaginationOptions, + ContainerQueryProperties containerQueryProperties, + int maxConcurrency, + PrefetchPolicy prefetchPolicy, CosmosElement continuationToken) - { - if (targetRanges == null) - { - throw new ArgumentNullException(nameof(targetRanges)); - } - - if (targetRanges.Count == 0) - { - throw new ArgumentException($"{nameof(targetRanges)} must have some elements"); - } - - TryCatch> monadicExtractState = MonadicExtractState(continuationToken, targetRanges); - if (monadicExtractState.Failed) - { - return TryCatch.FromException(monadicExtractState.Exception); - } - - CrossFeedRangeState state = monadicExtractState.Result; - - CrossPartitionRangePageAsyncEnumerator crossPartitionPageEnumerator = new CrossPartitionRangePageAsyncEnumerator( - feedRangeProvider: documentContainer, - createPartitionRangeEnumerator: ParallelCrossPartitionQueryPipelineStage.MakeCreateFunction(documentContainer, sqlQuerySpec, queryPaginationOptions, partitionKey), - comparer: Comparer.Singleton, - maxConcurrency: maxConcurrency, - prefetchPolicy: prefetchPolicy, + { + if (targetRanges == null) + { + throw new ArgumentNullException(nameof(targetRanges)); + } + + if (targetRanges.Count == 0) + { + throw new ArgumentException($"{nameof(targetRanges)} must have some elements"); + } + + TryCatch> monadicExtractState = MonadicExtractState(continuationToken, targetRanges); + if (monadicExtractState.Failed) + { + return TryCatch.FromException(monadicExtractState.Exception); + } + + CrossFeedRangeState state = monadicExtractState.Result; + + CrossPartitionRangePageAsyncEnumerator crossPartitionPageEnumerator = new CrossPartitionRangePageAsyncEnumerator( + feedRangeProvider: documentContainer, + createPartitionRangeEnumerator: ParallelCrossPartitionQueryPipelineStage.MakeCreateFunction(documentContainer, sqlQuerySpec, queryPaginationOptions, partitionKey, containerQueryProperties), + comparer: Comparer.Singleton, + maxConcurrency: maxConcurrency, + prefetchPolicy: prefetchPolicy, state: state); - + ParallelCrossPartitionQueryPipelineStage stage = new ParallelCrossPartitionQueryPipelineStage(crossPartitionPageEnumerator); - return TryCatch.FromResult(stage); - } - - private static TryCatch> MonadicExtractState( - CosmosElement continuationToken, - IReadOnlyList ranges) - { - if (continuationToken == null) - { - // Full fan out to the ranges with null continuations - CrossFeedRangeState fullFanOutState = new CrossFeedRangeState(ranges.Select(range => new FeedRangeState(range, (QueryState)null)).ToArray()); - return TryCatch>.FromResult(fullFanOutState); - } - - if (!(continuationToken is CosmosArray parallelContinuationTokenListRaw)) - { - return TryCatch>.FromException( - new MalformedContinuationTokenException( - $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}")); - } - - if (parallelContinuationTokenListRaw.Count == 0) - { - return TryCatch>.FromException( - new MalformedContinuationTokenException( - $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}")); - } - - List parallelContinuationTokens = new List(); - foreach (CosmosElement parallelContinuationTokenRaw in parallelContinuationTokenListRaw) - { - TryCatch tryCreateParallelContinuationToken = ParallelContinuationToken.TryCreateFromCosmosElement(parallelContinuationTokenRaw); - if (tryCreateParallelContinuationToken.Failed) - { - return TryCatch>.FromException( - tryCreateParallelContinuationToken.Exception); - } - - parallelContinuationTokens.Add(tryCreateParallelContinuationToken.Result); - } - - TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( - ranges, - parallelContinuationTokens); - if (partitionMappingMonad.Failed) - { - return TryCatch>.FromException( - partitionMappingMonad.Exception); - } - - PartitionMapping partitionMapping = partitionMappingMonad.Result; - List> feedRangeStates = new List>(); - - List> rangesToInitialize = new List>() - { - // Skip all the partitions left of the target range, since they have already been drained fully. - partitionMapping.TargetMapping, - partitionMapping.MappingRightOfTarget, - }; - - foreach (IReadOnlyDictionary rangeToInitalize in rangesToInitialize) - { - foreach (KeyValuePair kvp in rangeToInitalize) - { - FeedRangeState feedRangeState = new FeedRangeState(kvp.Key, kvp.Value?.Token != null ? new QueryState(CosmosString.Create(kvp.Value.Token)) : null); - feedRangeStates.Add(feedRangeState); - } - } - - CrossFeedRangeState crossPartitionState = new CrossFeedRangeState(feedRangeStates.ToArray()); - - return TryCatch>.FromResult(crossPartitionState); - } - - private static CreatePartitionRangePageAsyncEnumerator MakeCreateFunction( - IQueryDataSource queryDataSource, - SqlQuerySpec sqlQuerySpec, - QueryPaginationOptions queryPaginationOptions, - Cosmos.PartitionKey? partitionKey) => (FeedRangeState feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( - queryDataSource, - sqlQuerySpec, - feedRangeState, - partitionKey, - queryPaginationOptions); - - private sealed class Comparer : IComparer> - { - public static readonly Comparer Singleton = new Comparer(); - - public int Compare( - PartitionRangePageAsyncEnumerator partitionRangePageEnumerator1, - PartitionRangePageAsyncEnumerator partitionRangePageEnumerator2) - { - if (object.ReferenceEquals(partitionRangePageEnumerator1, partitionRangePageEnumerator2)) - { - return 0; - } - - // Either both don't have results or both do. - return string.CompareOrdinal( - ((FeedRangeEpk)partitionRangePageEnumerator1.FeedRangeState.FeedRange).Range.Min, - ((FeedRangeEpk)partitionRangePageEnumerator2.FeedRangeState.FeedRange).Range.Min); - } - } - } + return TryCatch.FromResult(stage); + } + + private static TryCatch> MonadicExtractState( + CosmosElement continuationToken, + IReadOnlyList ranges) + { + if (continuationToken == null) + { + // Full fan out to the ranges with null continuations + CrossFeedRangeState fullFanOutState = new CrossFeedRangeState(ranges.Select(range => new FeedRangeState(range, (QueryState)null)).ToArray()); + return TryCatch>.FromResult(fullFanOutState); + } + + if (!(continuationToken is CosmosArray parallelContinuationTokenListRaw)) + { + return TryCatch>.FromException( + new MalformedContinuationTokenException( + $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}")); + } + + if (parallelContinuationTokenListRaw.Count == 0) + { + return TryCatch>.FromException( + new MalformedContinuationTokenException( + $"Invalid format for continuation token {continuationToken} for {nameof(ParallelCrossPartitionQueryPipelineStage)}")); + } + + List parallelContinuationTokens = new List(); + foreach (CosmosElement parallelContinuationTokenRaw in parallelContinuationTokenListRaw) + { + TryCatch tryCreateParallelContinuationToken = ParallelContinuationToken.TryCreateFromCosmosElement(parallelContinuationTokenRaw); + if (tryCreateParallelContinuationToken.Failed) + { + return TryCatch>.FromException( + tryCreateParallelContinuationToken.Exception); + } + + parallelContinuationTokens.Add(tryCreateParallelContinuationToken.Result); + } + + TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( + ranges, + parallelContinuationTokens); + if (partitionMappingMonad.Failed) + { + return TryCatch>.FromException( + partitionMappingMonad.Exception); + } + + PartitionMapping partitionMapping = partitionMappingMonad.Result; + List> feedRangeStates = new List>(); + + List> rangesToInitialize = new List>() + { + // Skip all the partitions left of the target range, since they have already been drained fully. + partitionMapping.TargetMapping, + partitionMapping.MappingRightOfTarget, + }; + + foreach (IReadOnlyDictionary rangeToInitalize in rangesToInitialize) + { + foreach (KeyValuePair kvp in rangeToInitalize) + { + FeedRangeState feedRangeState = new FeedRangeState(kvp.Key, kvp.Value?.Token != null ? new QueryState(CosmosString.Create(kvp.Value.Token)) : null); + feedRangeStates.Add(feedRangeState); + } + } + + CrossFeedRangeState crossPartitionState = new CrossFeedRangeState(feedRangeStates.ToArray()); + + return TryCatch>.FromResult(crossPartitionState); + } + + private static CreatePartitionRangePageAsyncEnumerator MakeCreateFunction( + IQueryDataSource queryDataSource, + SqlQuerySpec sqlQuerySpec, + QueryPaginationOptions queryPaginationOptions, + Cosmos.PartitionKey? partitionKey, + ContainerQueryProperties containerQueryProperties) => (FeedRangeState feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( + queryDataSource, + sqlQuerySpec, + feedRangeState, + partitionKey, + queryPaginationOptions, + containerQueryProperties); + + private sealed class Comparer : IComparer> + { + public static readonly Comparer Singleton = new Comparer(); + + public int Compare( + PartitionRangePageAsyncEnumerator partitionRangePageEnumerator1, + PartitionRangePageAsyncEnumerator partitionRangePageEnumerator2) + { + if (object.ReferenceEquals(partitionRangePageEnumerator1, partitionRangePageEnumerator2)) + { + return 0; + } + + // Either both don't have results or both do. + return string.CompareOrdinal( + ((FeedRangeEpk)partitionRangePageEnumerator1.FeedRangeState.FeedRange).Range.Min, + ((FeedRangeEpk)partitionRangePageEnumerator2.FeedRangeState.FeedRange).Range.Min); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs index 5744ed734b..7ff976d7a2 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/Parallel/QueryPartitionRangePageAsyncEnumerator.cs @@ -10,6 +10,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.Tracing; internal sealed class QueryPartitionRangePageAsyncEnumerator : PartitionRangePageAsyncEnumerator @@ -17,6 +18,7 @@ internal sealed class QueryPartitionRangePageAsyncEnumerator : PartitionRangePag private readonly IQueryDataSource queryDataSource; private readonly SqlQuerySpec sqlQuerySpec; private readonly QueryPaginationOptions queryPaginationOptions; + private readonly ContainerQueryProperties containerQueryProperties; private readonly Cosmos.PartitionKey? partitionKey; public QueryPartitionRangePageAsyncEnumerator( @@ -24,13 +26,15 @@ public QueryPartitionRangePageAsyncEnumerator( SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, Cosmos.PartitionKey? partitionKey, - QueryPaginationOptions queryPaginationOptions) + QueryPaginationOptions queryPaginationOptions, + ContainerQueryProperties containerQueryProperties) : base(feedRangeState) { this.queryDataSource = queryDataSource ?? throw new ArgumentNullException(nameof(queryDataSource)); this.sqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); this.queryPaginationOptions = queryPaginationOptions; this.partitionKey = partitionKey; + this.containerQueryProperties = containerQueryProperties; } public override ValueTask DisposeAsync() => default; @@ -42,9 +46,7 @@ protected override Task> GetNextPageAsync(ITrace trace, Canc throw new ArgumentNullException(nameof(trace)); } - // We sadly need to check the partition key, since a user can set a partition key in the request options with a different continuation token. - // In the future the partition filtering and continuation information needs to be a tightly bounded contract (like cross feed range state). - FeedRangeInternal feedRange = this.partitionKey.HasValue ? new FeedRangePartitionKey(this.partitionKey.Value) : this.FeedRangeState.FeedRange; + FeedRangeInternal feedRange = this.LimitFeedRangeToSinglePartition(); return this.queryDataSource.MonadicQueryAsync( sqlQuerySpec: this.sqlQuerySpec, feedRangeState: new FeedRangeState(feedRange, this.FeedRangeState.State), @@ -52,5 +54,95 @@ protected override Task> GetNextPageAsync(ITrace trace, Canc trace: trace, cancellationToken); } + + /// + /// Updates the FeedRange to limit the scope of this enumerator to single physical partition. + /// Generally speaking, a subpartitioned container can experience split partition at any level of hierarchical partition key. + /// This could cause a situation where more than one physical partition contains the data for a partial partition key. + /// Currently, enumerator instantiation does not honor physical partition boundary and allocates entire epk range which could spans across multiple physical partitions to the enumerator. + /// Since such an epk range does not exist at the container level, Service generates a GoneException. + /// This method restrics the range of each container by shrinking the ends of the range so that they do not span across physical partition. + /// + private FeedRangeInternal LimitFeedRangeToSinglePartition() + { + // We sadly need to check the partition key, since a user can set a partition key in the request options with a different continuation token. + // In the future the partition filtering and continuation information needs to be a tightly bounded contract (like cross feed range state). + FeedRangeInternal feedRange = this.FeedRangeState.FeedRange; + if (this.partitionKey.HasValue) + { + // ISSUE-HACK-adityasa-3/25/2024 - We should not update the original feed range inside this class. + // Instead we should guarantee that when enumerator is instantiated it is limited to a single physical partition. + // Ultimately we should remove enumerator's dependency on PartitionKey. + if ((this.containerQueryProperties.PartitionKeyDefinition.Paths.Count > 1) && + (this.partitionKey.Value.InternalKey.Components.Count != this.containerQueryProperties.PartitionKeyDefinition.Paths.Count) && + (feedRange is FeedRangeEpk feedRangeEpk)) + { + if (this.containerQueryProperties.EffectiveRangesForPartitionKey == null || + this.containerQueryProperties.EffectiveRangesForPartitionKey.Count == 0) + { + throw new InvalidOperationException( + "EffectiveRangesForPartitionKey should be populated when PK is specified in request options."); + } + + foreach (Documents.Routing.Range epkForPartitionKey in + this.containerQueryProperties.EffectiveRangesForPartitionKey) + { + if (Documents.Routing.Range.CheckOverlapping( + feedRangeEpk.Range, + epkForPartitionKey)) + { + if (!feedRangeEpk.Range.Equals(epkForPartitionKey)) + { + String overlappingMin; + bool minInclusive; + String overlappingMax; + bool maxInclusive; + + if (Documents.Routing.Range.MinComparer.Instance.Compare( + epkForPartitionKey, + feedRangeEpk.Range) < 0) + { + overlappingMin = feedRangeEpk.Range.Min; + minInclusive = feedRangeEpk.Range.IsMinInclusive; + } + else + { + overlappingMin = epkForPartitionKey.Min; + minInclusive = epkForPartitionKey.IsMinInclusive; + } + + if (Documents.Routing.Range.MaxComparer.Instance.Compare( + epkForPartitionKey, + feedRangeEpk.Range) > 0) + { + overlappingMax = feedRangeEpk.Range.Max; + maxInclusive = feedRangeEpk.Range.IsMaxInclusive; + } + else + { + overlappingMax = epkForPartitionKey.Max; + maxInclusive = epkForPartitionKey.IsMaxInclusive; + } + + feedRange = new FeedRangeEpk( + new Documents.Routing.Range( + overlappingMin, + overlappingMax, + minInclusive, + maxInclusive)); + } + + break; + } + } + } + else + { + feedRange = new FeedRangePartitionKey(this.partitionKey.Value); + } + } + + return feedRange; + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index 8bad485a32..ff5f6bb438 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -1,318 +1,323 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Documents; - - internal sealed class OptimisticDirectExecutionQueryPipelineStage : IQueryPipelineStage - { - private enum ExecutionState - { - OptimisticDirectExecution, - SpecializedDocumentQueryExecution, - } - - private const string OptimisticDirectExecutionToken = "OptimisticDirectExecutionToken"; - private readonly FallbackQueryPipelineStageFactory queryPipelineStageFactory; - private TryCatch inner; - private CosmosElement continuationToken; - private ExecutionState executionState; - private bool? previousRequiresDistribution; - - private OptimisticDirectExecutionQueryPipelineStage(TryCatch inner, FallbackQueryPipelineStageFactory queryPipelineStageFactory, CosmosElement continuationToken) - { - this.inner = inner; - this.queryPipelineStageFactory = queryPipelineStageFactory; - this.continuationToken = continuationToken; - this.executionState = ExecutionState.OptimisticDirectExecution; - - if (this.continuationToken != null) - { - this.previousRequiresDistribution = false; - } - } - - public delegate Task> FallbackQueryPipelineStageFactory(CosmosElement continuationToken); - - public TryCatch Current => this.inner.Try(pipelineStage => pipelineStage.Current); - - public ValueTask DisposeAsync() - { - return this.inner.Failed ? default : this.inner.Result.DisposeAsync(); - } - +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline.OptimisticDirectExecutionQuery +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + + internal sealed class OptimisticDirectExecutionQueryPipelineStage : IQueryPipelineStage + { + private enum ExecutionState + { + OptimisticDirectExecution, + SpecializedDocumentQueryExecution, + } + + private const string OptimisticDirectExecutionToken = "OptimisticDirectExecutionToken"; + private readonly FallbackQueryPipelineStageFactory queryPipelineStageFactory; + private TryCatch inner; + private CosmosElement continuationToken; + private ExecutionState executionState; + private bool? previousRequiresDistribution; + + private OptimisticDirectExecutionQueryPipelineStage(TryCatch inner, FallbackQueryPipelineStageFactory queryPipelineStageFactory, CosmosElement continuationToken) + { + this.inner = inner; + this.queryPipelineStageFactory = queryPipelineStageFactory; + this.continuationToken = continuationToken; + this.executionState = ExecutionState.OptimisticDirectExecution; + + if (this.continuationToken != null) + { + this.previousRequiresDistribution = false; + } + } + + public delegate Task> FallbackQueryPipelineStageFactory(CosmosElement continuationToken); + + public TryCatch Current => this.inner.Try(pipelineStage => pipelineStage.Current); + + public ValueTask DisposeAsync() + { + return this.inner.Failed ? default : this.inner.Result.DisposeAsync(); + } + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) - { + { TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace, cancellationToken)); - bool success = hasNext.Succeeded && hasNext.Result; - if (this.executionState == ExecutionState.OptimisticDirectExecution) - { - bool isPartitionSplitException = hasNext.Succeeded && this.Current.Failed && this.Current.InnerMostException.IsPartitionSplitException(); - if (success && !isPartitionSplitException) - { - this.continuationToken = this.Current.Succeeded ? this.Current.Result.State?.Value : null; - if (this.continuationToken != null) - { - bool requiresDistribution; - if (this.Current.Result.AdditionalHeaders.TryGetValue(HttpConstants.HttpHeaders.RequiresDistribution, out string requiresDistributionHeaderValue)) - { - requiresDistribution = bool.Parse(requiresDistributionHeaderValue); - } - else - { - requiresDistribution = true; - } - - if (this.previousRequiresDistribution.HasValue && this.previousRequiresDistribution != requiresDistribution) - { - // We should never come here as requiresDistribution flag can never switch mid execution. - // Hence, this exception should never be thrown. - throw new InvalidOperationException($"Unexpected switch in {HttpConstants.HttpHeaders.RequiresDistribution} value. Previous value : {this.previousRequiresDistribution} Current value : {requiresDistribution}."); - } - - if (requiresDistribution) - { - // This is where we will unwrap tne continuation token and extract the client distribution plan - // Pipelines to handle client distribution would be generated here + bool success = hasNext.Succeeded && hasNext.Result; + if (this.executionState == ExecutionState.OptimisticDirectExecution) + { + bool isPartitionSplitException = hasNext.Succeeded && this.Current.Failed && this.Current.InnerMostException.IsPartitionSplitException(); + if (success && !isPartitionSplitException) + { + this.continuationToken = this.Current.Succeeded ? this.Current.Result.State?.Value : null; + if (this.continuationToken != null) + { + bool requiresDistribution; + if (this.Current.Result.AdditionalHeaders.TryGetValue(HttpConstants.HttpHeaders.RequiresDistribution, out string requiresDistributionHeaderValue)) + { + requiresDistribution = bool.Parse(requiresDistributionHeaderValue); + } + else + { + requiresDistribution = true; + } + + if (this.previousRequiresDistribution.HasValue && this.previousRequiresDistribution != requiresDistribution) + { + // We should never come here as requiresDistribution flag can never switch mid execution. + // Hence, this exception should never be thrown. + throw new InvalidOperationException($"Unexpected switch in {HttpConstants.HttpHeaders.RequiresDistribution} value. Previous value : {this.previousRequiresDistribution} Current value : {requiresDistribution}."); + } + + if (requiresDistribution) + { + // This is where we will unwrap tne continuation token and extract the client distribution plan + // Pipelines to handle client distribution would be generated here success = await this.SwitchToFallbackPipelineAsync(continuationToken: null, trace, cancellationToken); - } - - this.previousRequiresDistribution = requiresDistribution; - } - } - else if (isPartitionSplitException) - { + } + + this.previousRequiresDistribution = requiresDistribution; + } + } + else if (isPartitionSplitException) + { success = await this.SwitchToFallbackPipelineAsync(continuationToken: UnwrapContinuationToken(this.continuationToken), trace, cancellationToken); - } - } - - return success; - } - - private static CosmosElement UnwrapContinuationToken(CosmosElement continuationToken) - { - if (continuationToken == null) return null; - - CosmosObject cosmosObject = continuationToken as CosmosObject; - CosmosElement backendContinuationToken = cosmosObject[OptimisticDirectExecutionToken]; - Debug.Assert(backendContinuationToken != null); - - return CosmosArray.Create(backendContinuationToken); - } - + } + } + + return success; + } + + private static CosmosElement UnwrapContinuationToken(CosmosElement continuationToken) + { + if (continuationToken == null) return null; + + CosmosObject cosmosObject = continuationToken as CosmosObject; + CosmosElement backendContinuationToken = cosmosObject[OptimisticDirectExecutionToken]; + Debug.Assert(backendContinuationToken != null); + + return CosmosArray.Create(backendContinuationToken); + } + private async Task SwitchToFallbackPipelineAsync(CosmosElement continuationToken, ITrace trace, CancellationToken cancellationToken) - { - Debug.Assert(this.executionState == ExecutionState.OptimisticDirectExecution, "OptimisticDirectExecuteQueryPipelineStage Assert!", "Only OptimisticDirectExecute pipeline can create this fallback pipeline"); - this.executionState = ExecutionState.SpecializedDocumentQueryExecution; - this.inner = continuationToken != null - ? await this.queryPipelineStageFactory(continuationToken) - : await this.queryPipelineStageFactory(null); - - if (this.inner.Failed) - { - return false; - } - + { + Debug.Assert(this.executionState == ExecutionState.OptimisticDirectExecution, "OptimisticDirectExecuteQueryPipelineStage Assert!", "Only OptimisticDirectExecute pipeline can create this fallback pipeline"); + this.executionState = ExecutionState.SpecializedDocumentQueryExecution; + this.inner = continuationToken != null + ? await this.queryPipelineStageFactory(continuationToken) + : await this.queryPipelineStageFactory(null); + + if (this.inner.Failed) + { + return false; + } + return await this.inner.Result.MoveNextAsync(trace, cancellationToken); - } - - public static TryCatch MonadicCreate( - DocumentContainer documentContainer, - CosmosQueryExecutionContextFactory.InputParameters inputParameters, - FeedRangeEpk targetRange, - FallbackQueryPipelineStageFactory fallbackQueryPipelineStageFactory, - CancellationToken cancellationToken) - { - QueryPaginationOptions paginationOptions = new QueryPaginationOptions(pageSizeHint: inputParameters.MaxItemCount, optimisticDirectExecute: true); - TryCatch pipelineStage = OptimisticDirectExecutionQueryPipelineImpl.MonadicCreate( - documentContainer: documentContainer, - sqlQuerySpec: inputParameters.SqlQuerySpec, - targetRange: targetRange, - queryPaginationOptions: paginationOptions, - partitionKey: inputParameters.PartitionKey, - continuationToken: inputParameters.InitialUserContinuationToken, - cancellationToken: cancellationToken); - - if (pipelineStage.Failed) - { - return pipelineStage; - } - - OptimisticDirectExecutionQueryPipelineStage odePipelineStageMonadicCreate = new OptimisticDirectExecutionQueryPipelineStage(pipelineStage, fallbackQueryPipelineStageFactory, inputParameters.InitialUserContinuationToken); - return TryCatch.FromResult(odePipelineStageMonadicCreate); - } - - private sealed class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage - { - private const int ClientQLCompatibilityLevel = 1; - private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; - - private OptimisticDirectExecutionQueryPipelineImpl( - QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator) - { - this.queryPartitionRangePageAsyncEnumerator = queryPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(queryPartitionRangePageAsyncEnumerator)); - } - - public TryCatch Current { get; private set; } - - public ValueTask DisposeAsync() - { - return this.queryPartitionRangePageAsyncEnumerator.DisposeAsync(); - } - + } + + public static TryCatch MonadicCreate( + DocumentContainer documentContainer, + CosmosQueryExecutionContextFactory.InputParameters inputParameters, + FeedRangeEpk targetRange, + ContainerQueryProperties containerQueryProperties, + FallbackQueryPipelineStageFactory fallbackQueryPipelineStageFactory, + CancellationToken cancellationToken) + { + QueryPaginationOptions paginationOptions = new QueryPaginationOptions(pageSizeHint: inputParameters.MaxItemCount, optimisticDirectExecute: true); + TryCatch pipelineStage = OptimisticDirectExecutionQueryPipelineImpl.MonadicCreate( + documentContainer: documentContainer, + sqlQuerySpec: inputParameters.SqlQuerySpec, + targetRange: targetRange, + queryPaginationOptions: paginationOptions, + partitionKey: inputParameters.PartitionKey, + containerQueryProperties: containerQueryProperties, + continuationToken: inputParameters.InitialUserContinuationToken, + cancellationToken: cancellationToken); + + if (pipelineStage.Failed) + { + return pipelineStage; + } + + OptimisticDirectExecutionQueryPipelineStage odePipelineStageMonadicCreate = new OptimisticDirectExecutionQueryPipelineStage(pipelineStage, fallbackQueryPipelineStageFactory, inputParameters.InitialUserContinuationToken); + return TryCatch.FromResult(odePipelineStageMonadicCreate); + } + + private sealed class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage + { + private const int ClientQLCompatibilityLevel = 1; + private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; + + private OptimisticDirectExecutionQueryPipelineImpl( + QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator) + { + this.queryPartitionRangePageAsyncEnumerator = queryPartitionRangePageAsyncEnumerator ?? throw new ArgumentNullException(nameof(queryPartitionRangePageAsyncEnumerator)); + } + + public TryCatch Current { get; private set; } + + public ValueTask DisposeAsync() + { + return this.queryPartitionRangePageAsyncEnumerator.DisposeAsync(); + } + public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cancellationToken) - { - if (trace == null) - { - throw new ArgumentNullException(nameof(trace)); - } - + { + if (trace == null) + { + throw new ArgumentNullException(nameof(trace)); + } + if (!await this.queryPartitionRangePageAsyncEnumerator.MoveNextAsync(trace, cancellationToken)) - { - this.Current = default; - return false; - } - - TryCatch partitionPage = this.queryPartitionRangePageAsyncEnumerator.Current; - if (partitionPage.Failed) - { - this.Current = TryCatch.FromException(partitionPage.Exception); - return true; - } - - QueryPage backendQueryPage = partitionPage.Result; - - QueryState queryState; - if (backendQueryPage.State == null) - { - queryState = null; - } - else - { - QueryState backendQueryState = backendQueryPage.State; - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: (backendQueryState?.Value as CosmosString)?.Value, - range: ((FeedRangeEpk)this.queryPartitionRangePageAsyncEnumerator.FeedRangeState.FeedRange).Range); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - queryState = new QueryState(cosmosElementContinuationToken); - } - - QueryPage queryPage = new QueryPage( - backendQueryPage.Documents, - backendQueryPage.RequestCharge, - backendQueryPage.ActivityId, - backendQueryPage.CosmosQueryExecutionInfo, - backendQueryPage.DistributionPlanSpec, - disallowContinuationTokenMessage: null, - backendQueryPage.AdditionalHeaders, + { + this.Current = default; + return false; + } + + TryCatch partitionPage = this.queryPartitionRangePageAsyncEnumerator.Current; + if (partitionPage.Failed) + { + this.Current = TryCatch.FromException(partitionPage.Exception); + return true; + } + + QueryPage backendQueryPage = partitionPage.Result; + + QueryState queryState; + if (backendQueryPage.State == null) + { + queryState = null; + } + else + { + QueryState backendQueryState = backendQueryPage.State; + ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( + token: (backendQueryState?.Value as CosmosString)?.Value, + range: ((FeedRangeEpk)this.queryPartitionRangePageAsyncEnumerator.FeedRangeState.FeedRange).Range); + + OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); + CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); + queryState = new QueryState(cosmosElementContinuationToken); + } + + QueryPage queryPage = new QueryPage( + backendQueryPage.Documents, + backendQueryPage.RequestCharge, + backendQueryPage.ActivityId, + backendQueryPage.CosmosQueryExecutionInfo, + backendQueryPage.DistributionPlanSpec, + disallowContinuationTokenMessage: null, + backendQueryPage.AdditionalHeaders, queryState, backendQueryPage.Streaming); - - this.Current = TryCatch.FromResult(queryPage); - return true; - } - - public static TryCatch MonadicCreate( - IDocumentContainer documentContainer, - SqlQuerySpec sqlQuerySpec, - FeedRangeEpk targetRange, - Cosmos.PartitionKey? partitionKey, - QueryPaginationOptions queryPaginationOptions, - CosmosElement continuationToken, - CancellationToken cancellationToken) - { - if (targetRange == null) - { - throw new ArgumentNullException(nameof(targetRange)); - } - - TryCatch> monadicExtractState; - if (continuationToken == null) - { - FeedRangeState getState = new (targetRange, (QueryState)null); - monadicExtractState = TryCatch>.FromResult(getState); - } - else - { - monadicExtractState = MonadicExtractState(continuationToken, targetRange); - } - - if (monadicExtractState.Failed) - { - return TryCatch.FromException(monadicExtractState.Exception); - } - - SqlQuerySpec updatedSqlQuerySpec = new SqlQuerySpec(sqlQuerySpec.QueryText, sqlQuerySpec.Parameters) - { - ClientQLCompatibilityLevel = ClientQLCompatibilityLevel - }; - - FeedRangeState feedRangeState = monadicExtractState.Result; - QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( - documentContainer, - updatedSqlQuerySpec, - feedRangeState, - partitionKey, - queryPaginationOptions); - - OptimisticDirectExecutionQueryPipelineImpl stage = new OptimisticDirectExecutionQueryPipelineImpl(partitionPageEnumerator); - return TryCatch.FromResult(stage); - } - - private static TryCatch> MonadicExtractState( - CosmosElement continuationToken, - FeedRangeEpk range) - { - if (continuationToken == null) - { - throw new ArgumentNullException(nameof(continuationToken)); - } - - TryCatch tryCreateContinuationToken = OptimisticDirectExecutionContinuationToken.TryCreateFromCosmosElement(continuationToken); - if (tryCreateContinuationToken.Failed) - { - return TryCatch>.FromException(tryCreateContinuationToken.Exception); - } - - TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( - range, - tryCreateContinuationToken.Result); - - if (partitionMappingMonad.Failed) - { - return TryCatch>.FromException( - partitionMappingMonad.Exception); - } - - PartitionMapper.PartitionMapping partitionMapping = partitionMappingMonad.Result; - - KeyValuePair kvpRange = new KeyValuePair( - partitionMapping.TargetMapping.Keys.First(), - partitionMapping.TargetMapping.Values.First()); - - FeedRangeState feedRangeState = new FeedRangeState(kvpRange.Key, kvpRange.Value?.Token != null ? new QueryState(CosmosString.Create(kvpRange.Value.Token.Token)) : null); - - return TryCatch>.FromResult(feedRangeState); - } - } - } + + this.Current = TryCatch.FromResult(queryPage); + return true; + } + + public static TryCatch MonadicCreate( + IDocumentContainer documentContainer, + SqlQuerySpec sqlQuerySpec, + FeedRangeEpk targetRange, + Cosmos.PartitionKey? partitionKey, + QueryPaginationOptions queryPaginationOptions, + ContainerQueryProperties containerQueryProperties, + CosmosElement continuationToken, + CancellationToken cancellationToken) + { + if (targetRange == null) + { + throw new ArgumentNullException(nameof(targetRange)); + } + + TryCatch> monadicExtractState; + if (continuationToken == null) + { + FeedRangeState getState = new (targetRange, (QueryState)null); + monadicExtractState = TryCatch>.FromResult(getState); + } + else + { + monadicExtractState = MonadicExtractState(continuationToken, targetRange); + } + + if (monadicExtractState.Failed) + { + return TryCatch.FromException(monadicExtractState.Exception); + } + + SqlQuerySpec updatedSqlQuerySpec = new SqlQuerySpec(sqlQuerySpec.QueryText, sqlQuerySpec.Parameters) + { + ClientQLCompatibilityLevel = ClientQLCompatibilityLevel + }; + + FeedRangeState feedRangeState = monadicExtractState.Result; + QueryPartitionRangePageAsyncEnumerator partitionPageEnumerator = new QueryPartitionRangePageAsyncEnumerator( + documentContainer, + updatedSqlQuerySpec, + feedRangeState, + partitionKey, + queryPaginationOptions, + containerQueryProperties); + + OptimisticDirectExecutionQueryPipelineImpl stage = new OptimisticDirectExecutionQueryPipelineImpl(partitionPageEnumerator); + return TryCatch.FromResult(stage); + } + + private static TryCatch> MonadicExtractState( + CosmosElement continuationToken, + FeedRangeEpk range) + { + if (continuationToken == null) + { + throw new ArgumentNullException(nameof(continuationToken)); + } + + TryCatch tryCreateContinuationToken = OptimisticDirectExecutionContinuationToken.TryCreateFromCosmosElement(continuationToken); + if (tryCreateContinuationToken.Failed) + { + return TryCatch>.FromException(tryCreateContinuationToken.Exception); + } + + TryCatch> partitionMappingMonad = PartitionMapper.MonadicGetPartitionMapping( + range, + tryCreateContinuationToken.Result); + + if (partitionMappingMonad.Failed) + { + return TryCatch>.FromException( + partitionMappingMonad.Exception); + } + + PartitionMapper.PartitionMapping partitionMapping = partitionMappingMonad.Result; + + KeyValuePair kvpRange = new KeyValuePair( + partitionMapping.TargetMapping.Keys.First(), + partitionMapping.TargetMapping.Values.First()); + + FeedRangeState feedRangeState = new FeedRangeState(kvpRange.Key, kvpRange.Value?.Token != null ? new QueryState(CosmosString.Create(kvpRange.Value.Token.Token)) : null); + + return TryCatch>.FromResult(feedRangeState); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs index 1ae5312c2e..814682ba72 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs @@ -20,6 +20,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Pipeline using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Skip; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Take; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; internal static class PipelineFactory @@ -32,6 +33,7 @@ public static TryCatch MonadicCreate( PartitionKey? partitionKey, QueryInfo queryInfo, QueryPaginationOptions queryPaginationOptions, + ContainerQueryProperties containerQueryProperties, int maxConcurrency, CosmosElement requestContinuationToken) { @@ -87,6 +89,7 @@ public static TryCatch MonadicCreate( targetRanges: targetRanges, queryPaginationOptions: queryPaginationOptions, partitionKey: partitionKey, + containerQueryProperties: containerQueryProperties, prefetchPolicy: prefetchPolicy, maxConcurrency: maxConcurrency, continuationToken: continuationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SubpartitionTests.TestQueriesOnSplitContainer.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SubpartitionTests.TestQueriesOnSplitContainer.xml new file mode 100644 index 0000000000..192bfd9a20 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/SubpartitionTests.TestQueriesOnSplitContainer.xml @@ -0,0 +1,60 @@ + + + + SELECT + + True + + + + + + + + SELECT without ODE + + False + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 81d0b6797a..c9ad45d555 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -31,6 +31,7 @@ + @@ -349,6 +350,9 @@ + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs index bfcfb0c725..4c0a62b72d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs @@ -8,15 +8,18 @@ namespace Microsoft.Azure.Cosmos.Tests.Pagination using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; + using Debug = System.Diagnostics.Debug; using System.IO; using System.Linq; using System.Reflection; + using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Json; using Microsoft.Azure.Cosmos.Pagination; using Microsoft.Azure.Cosmos.Query.Core; @@ -35,6 +38,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Pagination using static Microsoft.Azure.Cosmos.Query.Core.SqlQueryResumeFilter; using ResourceIdentifier = Cosmos.Pagination.ResourceIdentifier; using UInt128 = UInt128; + using Microsoft.Azure.Documents.Routing; // Collection useful for mocking requests and repartitioning (splits / merge). internal class InMemoryContainer : IMonadicDocumentContainer @@ -46,9 +50,13 @@ internal class InMemoryContainer : IMonadicDocumentContainer private PartitionKeyHashRangeDictionary> partitionedChanges; private Dictionary partitionKeyRangeIdToHashRange; private Dictionary cachedPartitionKeyRangeIdToHashRange; + private readonly bool createSplitForMultiHashAtSecondlevel; + private readonly bool resolvePartitionsBasedOnPrefix; public InMemoryContainer( - PartitionKeyDefinition partitionKeyDefinition) + PartitionKeyDefinition partitionKeyDefinition, + bool createSplitForMultiHashAtSecondlevel = false, + bool resolvePartitionsBasedOnPrefix = false) { this.partitionKeyDefinition = partitionKeyDefinition ?? throw new ArgumentNullException(nameof(partitionKeyDefinition)); PartitionKeyHashRange fullRange = new PartitionKeyHashRange(startInclusive: null, endExclusive: new PartitionKeyHash(Cosmos.UInt128.MaxValue)); @@ -66,6 +74,8 @@ public InMemoryContainer( { 0, fullRange } }; this.parentToChildMapping = new Dictionary(); + this.createSplitForMultiHashAtSecondlevel = createSplitForMultiHashAtSecondlevel; + this.resolvePartitionsBasedOnPrefix = resolvePartitionsBasedOnPrefix; } public Task>> MonadicGetFeedRangesAsync( @@ -472,7 +482,10 @@ public virtual Task> MonadicQueryAsync( using (ITrace childTrace = trace.StartChild("Query Transport", TraceComponent.Transport, TraceLevel.Info)) { - TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeState.FeedRange); + FeedRange feedRange = this.resolvePartitionsBasedOnPrefix ? + ResolveFeedRangeBasedOnPrefixContainer(feedRangeState.FeedRange, this.partitionKeyDefinition) : + feedRangeState.FeedRange; + TryCatch monadicPartitionKeyRangeId = this.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRange); if (monadicPartitionKeyRangeId.Failed) { return Task.FromResult(TryCatch.FromException(monadicPartitionKeyRangeId.Exception)); @@ -943,6 +956,29 @@ public Task MonadicSplitAsync( return Task.FromResult(TryCatch.FromResult()); } + internal static FeedRange ResolveFeedRangeBasedOnPrefixContainer( + FeedRange feedRange, + PartitionKeyDefinition partitionKeyDefinition) + { + if (feedRange is FeedRangePartitionKey feedRangePartitionKey) + { + if (partitionKeyDefinition != null && partitionKeyDefinition.Kind == PartitionKind.MultiHash + && feedRangePartitionKey.PartitionKey.InternalKey?.Components?.Count < partitionKeyDefinition.Paths?.Count) + { + PartitionKeyHash partitionKeyHash = feedRangePartitionKey.PartitionKey.InternalKey.Components[0] switch + { + null => PartitionKeyHash.V2.HashUndefined(), + StringPartitionKeyComponent stringPartitionKey => PartitionKeyHash.V2.Hash((string)stringPartitionKey.ToObject()), + NumberPartitionKeyComponent numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + _ => throw new ArgumentOutOfRangeException(), + }; + feedRange = new FeedRangeEpk(new Documents.Routing.Range(min: partitionKeyHash.Value, max: partitionKeyHash.Value + "-FF", isMinInclusive:true, isMaxInclusive: false)); + } + } + + return feedRange; + } + public Task MonadicMergeAsync( FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, @@ -1337,7 +1373,7 @@ private static bool IsRecordWithinFeedRange( } } - private TryCatch MonadicGetPartitionKeyRangeIdFromFeedRange(FeedRange feedRange) + internal TryCatch MonadicGetPartitionKeyRangeIdFromFeedRange(FeedRange feedRange) { int partitionKeyRangeId; if (feedRange is FeedRangeEpk feedRangeEpk) @@ -1406,12 +1442,118 @@ private TryCatch MonadicGetPartitionKeyRangeIdFromFeedRange(FeedRange feedR private static PartitionKeyHashRange FeedRangeEpkToHashRange(FeedRangeEpk feedRangeEpk) { - PartitionKeyHash? start = feedRangeEpk.Range.Min == string.Empty ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Min); - PartitionKeyHash? end = feedRangeEpk.Range.Max == string.Empty || feedRangeEpk.Range.Max == "FF" ? (PartitionKeyHash?)null : PartitionKeyHash.Parse(feedRangeEpk.Range.Max); + PartitionKeyHash? start = + feedRangeEpk.Range.Min == string.Empty ? + (PartitionKeyHash?)null : + FromHashString(feedRangeEpk.Range.Min); + PartitionKeyHash? end = + feedRangeEpk.Range.Max == string.Empty || feedRangeEpk.Range.Max == "FF" ? + (PartitionKeyHash?)null : + FromHashString(feedRangeEpk.Range.Max); PartitionKeyHashRange hashRange = new PartitionKeyHashRange(start, end); return hashRange; } + /// + /// Creates a partition key hash from a rangeHash value. Supports if the rangeHash is over a hierarchical partition key. + /// + private static PartitionKeyHash FromHashString(string rangeHash) + { + List hashes = new(); + foreach(string hashComponent in GetHashComponents(rangeHash)) + { + // Hash FF has a special meaning in CosmosDB stack. It represents the max range which needs to be correctly represented for UInt128 parsing. + string value = hashComponent.Equals("FF", StringComparison.OrdinalIgnoreCase) ? + "FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF" : + hashComponent; + + bool success = UInt128.TryParse(value, out UInt128 uInt128); + Debug.Assert(success, "InMemoryContainer Assert!", "UInt128 parsing must succeed"); + hashes.Add(uInt128); + } + + return new PartitionKeyHash(hashes.ToArray()); + } + + /// + /// PartitionKeyHash.Parse requires a UInt128 parse-able string which itself requires hyphens to be present between subsequent byte values. + /// The hash values generated by rest of the (test) code may or may not honor this. + /// Furthermore, in case of hierarchical partitions, the hash values are concatenated together and therefore need to be broken into separate segments for parsing each one individually. + /// + /// + /// + private static IEnumerable GetHashComponents(string rangeValue) + { + int start = 0; + + while (start < rangeValue.Length) + { + string uInt128Segment = FixupUInt128(rangeValue, ref start); + yield return uInt128Segment; + } + } + + private static string FixupUInt128(string buffer, ref int start) + { + string result; + if (buffer.Length <= start + 2) + { + result = buffer.Substring(start); + start = buffer.Length; + } + else + { + StringBuilder stringBuilder = new StringBuilder(); + int index = start; + bool done = false; + int count = 0; + while (!done) + { + Debug.Assert(buffer[index] != '-', "InMemoryContainer Assert!", "First character of a chunk cannot be a hyphen"); + stringBuilder.Append(buffer[index]); + index++; + + Debug.Assert(index < buffer.Length, "InMemoryContainer Assert!", "At least 2 characters must be found in a chunk"); + Debug.Assert(buffer[index] != '-', "InMemoryContainer Assert!", "Second character of a chunk cannot be a hyphen"); + stringBuilder.Append(buffer[index]); + index++; + + if ((index < buffer.Length) && (buffer[index] == '-')) + { + index++; + } + + count++; + done = count == 16 || (index >= buffer.Length); + + if (!done) + { + stringBuilder.Append('-'); + } + } + + start = index; + + result = stringBuilder.ToString(); + Debug.Assert( + result.Length >= 2, + "InMemoryContainer Assert!", + "At least 1 byte must be present in hash value"); + Debug.Assert( + result[0] != '-' && result[result.Length - 1] != '-', + "InMemoryContainer Assert!", + "Hyphens should NOT be present at the start of end of the string"); + Debug.Assert( + Enumerable + .Range(1, result.Length - 1) + .All(i => (i % 3 == 2) == (result[i] == '-')), + "InMemoryContainer Assert!", + "Hyphens should be (only) present after every subsequent byte value"); + } + + return result; + } + private static FeedRangeEpk HashRangeToFeedRangeEpk(PartitionKeyHashRange hashRange) { return new FeedRangeEpk( @@ -1441,7 +1583,7 @@ private PartitionKeyHash ComputeMedianSplitPointAmongDocumentsInPKRange(Partitio // For MultiHash Collection, split at top level to ensure documents for top level key exist across partitions // after split - if (medianPkHash.HashValues.Count > 1) + if (medianPkHash.HashValues.Count > 1 && !this.createSplitForMultiHashAtSecondlevel) { return new PartitionKeyHash(medianPkHash.HashValues[0]); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 7e697260f1..e0f94e3e64 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -1257,18 +1257,18 @@ public override Task ForceRefreshCollectionCacheAsync(string collectionLink, Can public override Task GetCachedContainerQueryPropertiesAsync(string containerLink, Cosmos.PartitionKey? partitionKey, ITrace trace, CancellationToken cancellationToken) { - return Task.FromResult(new ContainerQueryProperties( - "test", - new List> - { - new Range( - PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, - PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, - true, - true) - }, - new PartitionKeyDefinition(), - Cosmos.GeospatialType.Geometry)); + return Task.FromResult(new ContainerQueryProperties( + "test", + new List> + { + new Range( + PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, + true, + true) + }, + new PartitionKeyDefinition(), + Cosmos.GeospatialType.Geometry)); } public override Task GetClientDisableOptimisticDirectExecutionAsync() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs index 54e5b99899..bc0c4c94a3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FactoryTests.cs @@ -28,6 +28,7 @@ public void TestCreate() sqlQuerySpec: new SqlQuerySpec("SELECT * FROM c"), targetRanges: new List() { FeedRangeEpk.FullRange }, partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), queryInfo: new QueryInfo() { }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index 68b5b7d9cd..2b68a66ce3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -590,6 +590,7 @@ private static async Task CreatePipelineAsync( partitionKey: null, GetQueryPlan(query), queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: pageSize), + containerQueryProperties: new ContainerQueryProperties(), maxConcurrency: 10, requestContinuationToken: state); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs index e4e06635b3..e3a7554d2f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/ParallelCrossPartitionQueryPipelineStageTests.cs @@ -36,6 +36,7 @@ public void MonadicCreate_NullContinuationToken() targetRanges: new List() { FeedRangeEpk.FullRange }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: null); @@ -53,6 +54,7 @@ public void MonadicCreate_NonCosmosArrayContinuationToken() targetRanges: new List() { FeedRangeEpk.FullRange }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: CosmosObject.Create(new Dictionary())); @@ -71,6 +73,7 @@ public void MonadicCreate_EmptyArrayContinuationToken() targetRanges: new List() { FeedRangeEpk.FullRange }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: CosmosArray.Create(new List())); @@ -89,6 +92,7 @@ public void MonadicCreate_NonParallelContinuationToken() targetRanges: new List() { FeedRangeEpk.FullRange }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: CosmosArray.Create(new List() { CosmosString.Create("asdf") })); @@ -111,6 +115,7 @@ public void MonadicCreate_SingleParallelContinuationToken() targetRanges: new List() { new FeedRangeEpk(new Documents.Routing.Range(min: "A", max: "B", isMinInclusive: true, isMaxInclusive: false)) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: CosmosArray.Create(new List() { ParallelContinuationToken.ToCosmosElement(token) })); @@ -140,6 +145,7 @@ public void MonadicCreate_MultipleParallelContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: PrefetchPolicy.PrefetchSinglePage, continuationToken: CosmosArray.Create( @@ -180,6 +186,7 @@ async Task CreatePipelineStateAsync(IDocumentContainer docu cancellationToken: default), queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, prefetchPolicy: aggressivePrefetch ? PrefetchPolicy.PrefetchAll : PrefetchPolicy.PrefetchSinglePage, continuationToken: continuationToken); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs index 2bb6813ff6..7954de30b7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/QueryPartitionRangePageEnumeratorTests.cs @@ -1,175 +1,178 @@ -namespace Microsoft.Azure.Cosmos.Tests.Query -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.Pagination; - using Microsoft.Azure.Cosmos.Query.Core.Monads; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; - using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; - using Microsoft.Azure.Cosmos.Tests.Pagination; - using Microsoft.Azure.Cosmos.Tests.Query.Pipeline; - using Microsoft.Azure.Cosmos.Tracing; - using Microsoft.Azure.Documents; - using Microsoft.VisualStudio.TestTools.UnitTesting; - - [TestClass] - public class QueryPartitionRangePageAsyncEnumeratorTests - { - [TestMethod] - public async Task Test429sAsync() - { - Implementation implementation = new Implementation(); - await implementation.Test429sAsync(false); - } - - [TestMethod] - public async Task Test429sWithContinuationsAsync() - { - Implementation implementation = new Implementation(); - await implementation.Test429sWithContinuationsAsync(false, false); - } - - [TestMethod] - public async Task TestDrainFullyAsync() - { - Implementation implementation = new Implementation(); - await implementation.TestDrainFullyAsync(false); - } - - [TestMethod] - public async Task TestEmptyPages() - { - Implementation implementation = new Implementation(); - await implementation.TestEmptyPages(false); - } - - [TestMethod] - public async Task TestResumingFromStateAsync() - { - Implementation implementation = new Implementation(); - await implementation.TestResumingFromStateAsync(false, false); - } - - [TestMethod] - public async Task TestSplitAsync() - { - Implementation implementation = new Implementation(); - await implementation.TestSplitAsync(); - } - - [TestClass] - private sealed class Implementation : PartitionRangeEnumeratorTests - { - public Implementation() - : base(singlePartition: true) - { - } - - [TestMethod] - public async Task TestSplitAsync() - { - int numItems = 100; - IDocumentContainer documentContainer = await this.CreateDocumentContainerAsync(numItems); - IAsyncEnumerator> enumerator = await this.CreateEnumeratorAsync(documentContainer); - - (HashSet parentIdentifiers, QueryState state) = await this.PartialDrainAsync(enumerator, numIterations: 3); - - // Split the partition - await documentContainer.SplitAsync(new FeedRangePartitionKeyRange("0"), cancellationToken: default); - - // Try To read from the partition that is gone. - await enumerator.MoveNextAsync(); - Assert.IsTrue(enumerator.Current.Failed); - - // Resume on the children using the parent continuaiton token - HashSet childIdentifiers = new HashSet(); - - await documentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); - List ranges = await documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default); - foreach (FeedRangeEpk range in ranges) - { - IAsyncEnumerable> enumerable = new PartitionRangePageAsyncEnumerable( - feedRangeState: new FeedRangeState(range, state), - (feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( - queryDataSource: documentContainer, - sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), - feedRangeState: feedRangeState, - partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), - trace: NoOpTrace.Singleton); - HashSet resourceIdentifiers = await this.DrainFullyAsync(enumerable); - - childIdentifiers.UnionWith(resourceIdentifiers); - } - - Assert.AreEqual(numItems, parentIdentifiers.Count + childIdentifiers.Count); - } - - public override IReadOnlyList GetRecordsFromPage(QueryPage page) - { - List records = new List(page.Documents.Count); - foreach (CosmosElement element in page.Documents) - { - CosmosObject document = (CosmosObject)element; - ResourceId resourceIdentifier = ResourceId.Parse(((CosmosString)document["_rid"]).Value); - long ticks = Number64.ToLong(((CosmosNumber)document["_ts"]).Value); - string identifer = ((CosmosString)document["id"]).Value; - - records.Add(new Record(resourceIdentifier, new DateTime(ticks: ticks, DateTimeKind.Utc), identifer, document)); - } - - return records; - } - - protected override IAsyncEnumerable> CreateEnumerable( - IDocumentContainer documentContainer, - bool aggressivePrefetch = false, - QueryState state = null) - { - List ranges = documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default).Result; - Assert.AreEqual(1, ranges.Count); - return new PartitionRangePageAsyncEnumerable( - feedRangeState: new FeedRangeState(ranges[0], state), - (feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( - queryDataSource: documentContainer, - sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), - feedRangeState: feedRangeState, - partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), - trace: NoOpTrace.Singleton); - } - - protected override Task>> CreateEnumeratorAsync( - IDocumentContainer documentContainer, - bool aggressivePrefetch = false, - bool exercisePrefetch = false, - QueryState state = default, - CancellationToken cancellationToken = default) - { - List ranges = documentContainer.GetFeedRangesAsync( - trace: NoOpTrace.Singleton, - cancellationToken: default).Result; - Assert.AreEqual(1, ranges.Count); - - IAsyncEnumerator> enumerator = new TracingAsyncEnumerator>( - enumerator: new QueryPartitionRangePageAsyncEnumerator( - queryDataSource: documentContainer, - sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), - feedRangeState: new FeedRangeState(ranges[0], state), - partitionKey: null, - queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), +namespace Microsoft.Azure.Cosmos.Tests.Query +{ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.CrossPartition.Parallel; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Tests.Pagination; + using Microsoft.Azure.Cosmos.Tests.Query.Pipeline; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class QueryPartitionRangePageAsyncEnumeratorTests + { + [TestMethod] + public async Task Test429sAsync() + { + Implementation implementation = new Implementation(); + await implementation.Test429sAsync(false); + } + + [TestMethod] + public async Task Test429sWithContinuationsAsync() + { + Implementation implementation = new Implementation(); + await implementation.Test429sWithContinuationsAsync(false, false); + } + + [TestMethod] + public async Task TestDrainFullyAsync() + { + Implementation implementation = new Implementation(); + await implementation.TestDrainFullyAsync(false); + } + + [TestMethod] + public async Task TestEmptyPages() + { + Implementation implementation = new Implementation(); + await implementation.TestEmptyPages(false); + } + + [TestMethod] + public async Task TestResumingFromStateAsync() + { + Implementation implementation = new Implementation(); + await implementation.TestResumingFromStateAsync(false, false); + } + + [TestMethod] + public async Task TestSplitAsync() + { + Implementation implementation = new Implementation(); + await implementation.TestSplitAsync(); + } + + [TestClass] + private sealed class Implementation : PartitionRangeEnumeratorTests + { + public Implementation() + : base(singlePartition: true) + { + } + + [TestMethod] + public async Task TestSplitAsync() + { + int numItems = 100; + IDocumentContainer documentContainer = await this.CreateDocumentContainerAsync(numItems); + IAsyncEnumerator> enumerator = await this.CreateEnumeratorAsync(documentContainer); + + (HashSet parentIdentifiers, QueryState state) = await this.PartialDrainAsync(enumerator, numIterations: 3); + + // Split the partition + await documentContainer.SplitAsync(new FeedRangePartitionKeyRange("0"), cancellationToken: default); + + // Try To read from the partition that is gone. + await enumerator.MoveNextAsync(); + Assert.IsTrue(enumerator.Current.Failed); + + // Resume on the children using the parent continuaiton token + HashSet childIdentifiers = new HashSet(); + + await documentContainer.RefreshProviderAsync(NoOpTrace.Singleton, cancellationToken: default); + List ranges = await documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default); + foreach (FeedRangeEpk range in ranges) + { + IAsyncEnumerable> enumerable = new PartitionRangePageAsyncEnumerable( + feedRangeState: new FeedRangeState(range, state), + (feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( + queryDataSource: documentContainer, + sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), + feedRangeState: feedRangeState, + partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), + trace: NoOpTrace.Singleton); + HashSet resourceIdentifiers = await this.DrainFullyAsync(enumerable); + + childIdentifiers.UnionWith(resourceIdentifiers); + } + + Assert.AreEqual(numItems, parentIdentifiers.Count + childIdentifiers.Count); + } + + public override IReadOnlyList GetRecordsFromPage(QueryPage page) + { + List records = new List(page.Documents.Count); + foreach (CosmosElement element in page.Documents) + { + CosmosObject document = (CosmosObject)element; + ResourceId resourceIdentifier = ResourceId.Parse(((CosmosString)document["_rid"]).Value); + long ticks = Number64.ToLong(((CosmosNumber)document["_ts"]).Value); + string identifer = ((CosmosString)document["id"]).Value; + + records.Add(new Record(resourceIdentifier, new DateTime(ticks: ticks, DateTimeKind.Utc), identifer, document)); + } + + return records; + } + + protected override IAsyncEnumerable> CreateEnumerable( + IDocumentContainer documentContainer, + bool aggressivePrefetch = false, + QueryState state = null) + { + List ranges = documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default).Result; + Assert.AreEqual(1, ranges.Count); + return new PartitionRangePageAsyncEnumerable( + feedRangeState: new FeedRangeState(ranges[0], state), + (feedRangeState) => new QueryPartitionRangePageAsyncEnumerator( + queryDataSource: documentContainer, + sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), + feedRangeState: feedRangeState, + partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), + trace: NoOpTrace.Singleton); + } + + protected override Task>> CreateEnumeratorAsync( + IDocumentContainer documentContainer, + bool aggressivePrefetch = false, + bool exercisePrefetch = false, + QueryState state = default, + CancellationToken cancellationToken = default) + { + List ranges = documentContainer.GetFeedRangesAsync( + trace: NoOpTrace.Singleton, + cancellationToken: default).Result; + Assert.AreEqual(1, ranges.Count); + + IAsyncEnumerator> enumerator = new TracingAsyncEnumerator>( + enumerator: new QueryPartitionRangePageAsyncEnumerator( + queryDataSource: documentContainer, + sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec("SELECT * FROM c"), + feedRangeState: new FeedRangeState(ranges[0], state), + partitionKey: null, + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10)), trace: NoOpTrace.Singleton, - cancellationToken: cancellationToken); - - return Task.FromResult(enumerator); - } - } - } -} + cancellationToken: default); + + return Task.FromResult(enumerator); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SubpartitionTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SubpartitionTests.cs new file mode 100644 index 0000000000..35869ebbc8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SubpartitionTests.cs @@ -0,0 +1,392 @@ +namespace Microsoft.Azure.Cosmos.Tests.Query +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using System.Xml; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; + using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; + using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Test.BaselineTest; + using Microsoft.Azure.Cosmos.Tests.Pagination; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class SubpartitionTests : BaselineTests + { + private const int DocumentCount = 100; + private const int SplitPartitionKey = 2; + + [TestMethod] + public void TestQueriesOnSplitContainer() + { + List inputs = new List + { + new SubpartitionTestInput("SELECT", query: @"SELECT c.id, c.value2 FROM c", ode: true), + new SubpartitionTestInput("SELECT without ODE", query: @"SELECT c.id, c.value2 FROM c", ode: false), + }; + this.ExecuteTestSuite(inputs); + } + + /// + /// The test is a baseline for mock framework which splits the container at the top level of a hierarchical partition key. + /// After split, it is expected that more than one physical partitions contain data for some value of a top level path of partition key. + /// Please note that this does NOT occur in a single-partition key scenario where all data for a given value of a partition key + /// is contained within single physical partition. + /// This situation is known to create issues, especially while running queries due to inconsistent handling of FeedRangePartitionKey and FeedRangeEpk in the SDK stack. + /// Test framework's behavior in being able to replicate this situation is critical to for ensuring that tests provide sufficient protection against regressions. + /// + [TestMethod] + public async Task VerifyTestFrameworkSupportsPartitionSplit() + { + PartitionKeyDefinition partitionKeyDefinition = CreatePartitionKeyDefinition(); + InMemoryContainer inMemoryContainer = await CreateSplitInMemoryDocumentContainerAsync(DocumentCount, partitionKeyDefinition); + Cosmos.PartitionKey partitionKey = new Cosmos.PartitionKeyBuilder().Add(SplitPartitionKey.ToString()).Build(); + FeedRangePartitionKey feedRangePartitionKey = new FeedRangePartitionKey(partitionKey); + FeedRangeEpk feedRangeEpk = InMemoryContainer.ResolveFeedRangeBasedOnPrefixContainer(feedRangePartitionKey, partitionKeyDefinition) as FeedRangeEpk; + Assert.IsNotNull(feedRangeEpk); + TryCatch pkRangeId = inMemoryContainer.MonadicGetPartitionKeyRangeIdFromFeedRange(feedRangeEpk); + Assert.IsTrue(pkRangeId.Failed, $"Expected to fail for partition key {SplitPartitionKey}"); + Assert.IsTrue(pkRangeId.Exception.InnerException.Message.StartsWith("Epk Range: [B5-D7-B7-26-D6-EA-DB-11-F1-EF-AD-92-12-15-D6-60,B5-D7-B7-26-D6-EA-DB-11-F1-EF-AD-92-12-15-D6-60-FF) is gone."), "Gone exception is expected!"); + } + + public override SubpartitionTestOutput ExecuteTest(SubpartitionTestInput input) + { + IMonadicDocumentContainer monadicDocumentContainer = CreateSplitDocumentContainerAsync(DocumentCount).Result; + DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); + + List documents = new List(); + QueryRequestOptions queryRequestOptions = new QueryRequestOptions() + { + PartitionKey = new PartitionKeyBuilder().Add(SplitPartitionKey.ToString()).Build() + }; + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = + CreateInputParamsAndQueryContext(input, queryRequestOptions); + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); + while (queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default).Result) + { + TryCatch tryGetPage = queryPipelineStage.Current; + + if (tryGetPage.Failed) + { + Assert.Fail("Unexpected error. Gone Exception should not reach till here"); + } + + documents.AddRange(tryGetPage.Result.Documents); + } + + return new SubpartitionTestOutput(documents); + } + + private static Tuple CreateInputParamsAndQueryContext(SubpartitionTestInput input, QueryRequestOptions queryRequestOptions) + { + string query = input.Query; + CosmosElement continuationToken = null; + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() + { + Paths = new System.Collections.ObjectModel.Collection() + { + "/id", + "/value1", + "/value2" + }, + Kind = PartitionKind.MultiHash, + Version = PartitionKeyDefinitionVersion.V2, + }; + + queryRequestOptions.EnableOptimisticDirectExecution = input.ODE; + + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(query), Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, partitionKeyDefinition); + CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( + sqlQuerySpec: new SqlQuerySpec(query), + initialUserContinuationToken: continuationToken, + initialFeedRange: null, + maxConcurrency: queryRequestOptions.MaxConcurrency, + maxItemCount: queryRequestOptions.MaxItemCount, + maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, + partitionKey: queryRequestOptions.PartitionKey, + properties: new Dictionary() { { "x-ms-query-partitionkey-definition", partitionKeyDefinition } }, + partitionedQueryExecutionInfo: null, + executionEnvironment: null, + returnResultsInDeterministicOrder: null, + enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, + testInjections: queryRequestOptions.TestSettings); + + string databaseId = "db1234"; + string resourceLink = $"dbs/{databaseId}/colls"; + CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( + client: new TestCosmosQueryClient(queryPartitionProvider), + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); + + return Tuple.Create(inputParameters, cosmosQueryContextCore); + } + + internal static Tuple GetPartitionedQueryExecutionInfoAndPartitionProvider(string querySpecJsonString, PartitionKeyDefinition pkDefinition) + { + QueryPartitionProvider queryPartitionProvider = CreateCustomQueryPartitionProvider(); + TryCatch tryGetQueryPlan = queryPartitionProvider.TryGetPartitionedQueryExecutionInfo( + querySpecJsonString: querySpecJsonString, + partitionKeyDefinition: pkDefinition, + requireFormattableOrderByQuery: true, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + hasLogicalPartitionKey: false, + allowDCount: true, + useSystemPrefix: false, + geospatialType: Cosmos.GeospatialType.Geography); + + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = tryGetQueryPlan.Succeeded ? tryGetQueryPlan.Result : throw tryGetQueryPlan.Exception; + return Tuple.Create(partitionedQueryExecutionInfo, queryPartitionProvider); + } + + private static QueryPartitionProvider CreateCustomQueryPartitionProvider() + { + Dictionary queryEngineConfiguration = new Dictionary() + { + {"maxSqlQueryInputLength", 262144}, + {"maxJoinsPerSqlQuery", 5}, + {"maxLogicalAndPerSqlQuery", 2000}, + {"maxLogicalOrPerSqlQuery", 2000}, + {"maxUdfRefPerSqlQuery", 10}, + {"maxInExpressionItemsCount", 16000}, + {"queryMaxGroupByTableCellCount", 500000 }, + {"queryMaxInMemorySortDocumentCount", 500}, + {"maxQueryRequestTimeoutFraction", 0.90}, + {"sqlAllowNonFiniteNumbers", false}, + {"sqlAllowAggregateFunctions", true}, + {"sqlAllowSubQuery", true}, + {"sqlAllowScalarSubQuery", true}, + {"allowNewKeywords", true}, + {"sqlAllowLike", true}, + {"sqlAllowGroupByClause", true}, + {"maxSpatialQueryCells", 12}, + {"spatialMaxGeometryPointCount", 256}, + {"sqlDisableQueryILOptimization", false}, + {"sqlDisableFilterPlanOptimization", false}, + {"clientDisableOptimisticDirectExecution", false} + }; + + return new QueryPartitionProvider(queryEngineConfiguration); + } + + internal static PartitionKeyDefinition CreatePartitionKeyDefinition() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() + { + Paths = new System.Collections.ObjectModel.Collection() + { + "/id", + "/value1", + "/value2" + }, + Kind = PartitionKind.MultiHash, + Version = PartitionKeyDefinitionVersion.V2, + }; + + return partitionKeyDefinition; + } + + private static async Task CreateSplitDocumentContainerAsync(int numItems) + { + PartitionKeyDefinition partitionKeyDefinition = CreatePartitionKeyDefinition(); + InMemoryContainer inMemoryContainer = await CreateSplitInMemoryDocumentContainerAsync(numItems, partitionKeyDefinition); + DocumentContainer documentContainer = new DocumentContainer(inMemoryContainer); + return documentContainer; + } + + private static async Task CreateSplitInMemoryDocumentContainerAsync(int numItems, PartitionKeyDefinition partitionKeyDefinition) + { + InMemoryContainer inMemoryContainer = new InMemoryContainer(partitionKeyDefinition, createSplitForMultiHashAtSecondlevel: true, resolvePartitionsBasedOnPrefix: true); + for (int i = 0; i < numItems; i++) + { + CosmosObject item = CosmosObject.Parse($"{{\"id\" : \"{i % 5}\", \"value1\" : \"{Guid.NewGuid()}\", \"value2\" : \"{i}\" }}"); + while (true) + { + TryCatch monadicCreateRecord = await inMemoryContainer.MonadicCreateItemAsync(item, cancellationToken: default); + if (monadicCreateRecord.Succeeded) + { + break; + } + } + } + + await inMemoryContainer.MonadicSplitAsync(FeedRangeEpk.FullRange, cancellationToken: default); + + return inMemoryContainer; + } + internal class TestCosmosQueryClient : CosmosQueryClient + { + private readonly QueryPartitionProvider queryPartitionProvider; + + public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider) + { + this.queryPartitionProvider = queryPartitionProvider; + } + + public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); + + public override bool BypassQueryParsing() + { + return false; + } + + public override void ClearSessionTokenCache(string collectionFullName) + { + throw new NotImplementedException(); + } + + public override Task> ExecuteItemQueryAsync(string resourceUri, ResourceType resourceType, OperationType operationType, Cosmos.FeedRange feedRange, QueryRequestOptions requestOptions, AdditionalRequestHeaders additionalRequestHeaders, SqlQuerySpec sqlQuerySpec, string continuationToken, int pageSize, ITrace trace, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public override Task ExecuteQueryPlanRequestAsync(string resourceUri, ResourceType resourceType, OperationType operationType, SqlQuerySpec sqlQuerySpec, Cosmos.PartitionKey? partitionKey, string supportedQueryFeatures, Guid clientQueryCorrelationId, ITrace trace, CancellationToken cancellationToken) + { + return Task.FromResult(new PartitionedQueryExecutionInfo()); + } + + public override Task ForceRefreshCollectionCacheAsync(string collectionLink, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public override Task GetCachedContainerQueryPropertiesAsync(string containerLink, Cosmos.PartitionKey? partitionKey, ITrace trace, CancellationToken cancellationToken) + { + List hashes = new(); + foreach (Documents.Routing.IPartitionKeyComponent component in partitionKey.Value.InternalKey.Components) + { + PartitionKeyHash partitionKeyHash = component switch + { + null => PartitionKeyHash.V2.HashUndefined(), + Documents.Routing.StringPartitionKeyComponent stringPartitionKey => PartitionKeyHash.V2.Hash((string)stringPartitionKey.ToObject()), + Documents.Routing.NumberPartitionKeyComponent numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + _ => throw new ArgumentOutOfRangeException(), + }; + hashes.Add(partitionKeyHash.Value); + } + + string min = string.Join(string.Empty, hashes); + string max = min + "-FF"; + return Task.FromResult(new ContainerQueryProperties( + "test", + new List> + { + new Documents.Routing.Range( + min, + max, + true, + true) + }, + SubpartitionTests.CreatePartitionKeyDefinition(), + Cosmos.GeospatialType.Geometry)); + } + + public override async Task GetClientDisableOptimisticDirectExecutionAsync() + { + return this.queryPartitionProvider.ClientDisableOptimisticDirectExecution; + } + + public override Task> GetTargetPartitionKeyRangeByFeedRangeAsync(string resourceLink, string collectionResourceId, PartitionKeyDefinition partitionKeyDefinition, FeedRangeInternal feedRangeInternal, bool forceRefresh, ITrace trace) + { + throw new NotImplementedException(); + } + + public override Task> GetTargetPartitionKeyRangesAsync(string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) + { + return Task.FromResult(new List + { + new PartitionKeyRange() + { + MinInclusive = Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, + MaxExclusive = Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey + } + }); + } + + public override Task> TryGetOverlappingRangesAsync(string collectionResourceId, Documents.Routing.Range range, bool forceRefresh = false) + { + throw new NotImplementedException(); + } + + public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + (PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, QueryPartitionProvider queryPartitionProvider) = OptimisticDirectExecutionQueryBaselineTests.GetPartitionedQueryExecutionInfoAndPartitionProvider(sqlQuerySpecJsonString, partitionKeyDefinition); + return TryCatch.FromResult(partitionedQueryExecutionInfo); + } + } + } + + public class SubpartitionTestInput : BaselineTestInput + { + public SubpartitionTestInput(string description, string query, bool ode) + :base(description) + { + this.Query = query; + this.ODE = ode; + } + + internal string Query { get; } + + internal bool ODE { get; } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteElementString("Description", this.Description); + xmlWriter.WriteStartElement("Query"); + xmlWriter.WriteCData(this.Query); + xmlWriter.WriteEndElement(); + xmlWriter.WriteElementString("ODE", this.ODE.ToString()); + } + } + + public class SubpartitionTestOutput : BaselineTestOutput + { + private readonly List documents; + + internal SubpartitionTestOutput(IReadOnlyList documents) + { + this.documents = documents.ToList(); + } + + public override void SerializeAsXml(XmlWriter xmlWriter) + { + xmlWriter.WriteStartElement("Documents"); + string content = string.Join($",{Environment.NewLine}", + this.documents.Select(doc => doc.ToString()).OrderBy(serializedDoc => serializedDoc)); + xmlWriter.WriteCData(content); + xmlWriter.WriteEndElement(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index aa2e145850..39082e940d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -756,6 +756,7 @@ private static IQueryPipelineStage CreatePipeline(IDocumentContainer documentCon partitionKey: null, GetQueryPlan(query), new QueryPaginationOptions(pageSizeHint: pageSize), + containerQueryProperties: new Cosmos.Query.Core.QueryClient.ContainerQueryProperties(), maxConcurrency: 10, requestContinuationToken: state); From 80647baea2cd072d03d76c64571bb4227c4a1206 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Wed, 3 Apr 2024 12:27:00 -0700 Subject: [PATCH 305/337] [Internal] Direct Package: Adds Support for Direct package version 3.33.0 (#4353) * upgraded direct package version * added Taiwan regions * update contracts * fix contracts * fixed more contracts * contracts change * contract change remove * changed baseline files * added space * added region name check test for future verification * nits --------- Co-authored-by: Sourabh Jain --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/Regions.cs | 10 +++++ .../QueryPlanBaselineTests.GroupBy.xml | 36 ++++++++-------- ...ryPlanBaselineTests.NonValueAggregates.xml | 42 +++++++++---------- .../Contracts/DirectContractTests.cs | 17 +++++++- .../Contracts/DotNetSDKAPI.json | 10 +++++ 6 files changed, 75 insertions(+), 42 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 89cc974a3e..69dc328a70 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.38.1 3.39.0 preview.1 - 3.32.1 + 3.33.0 2.0.4 2.1.0 preview4 diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index aae88eb22b..28a54b5def 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -374,5 +374,15 @@ public static class Regions /// Name of the Azure Spain Central region in the Azure Cosmos DB service. /// public const string SpainCentral = "Spain Central"; + + /// + /// Name of the Azure Taiwan North region in the Azure Cosmos DB service. + /// + public const string TaiwanNorth = "Taiwan North"; + + /// + /// Name of the Azure Taiwan Northwest region in the Azure Cosmos DB service. + /// + public const string TaiwanNorthwest = "Taiwan Northwest"; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml index c832978d6f..3059db631a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.GroupBy.xml @@ -311,14 +311,6 @@ GROUP BY c.age, c.name]]> - - min_age - Min - - - max_age - Max - count Count @@ -331,6 +323,14 @@ GROUP BY c.age, c.name]]> team null + + min_age + Min + + + max_age + Max + avg_age Average @@ -504,10 +504,6 @@ GROUP BY UPPER(c.name), SUBSTRING(c.address.city, 0, 3)]]> - - group_name - null - count Count @@ -516,6 +512,10 @@ GROUP BY UPPER(c.name), SUBSTRING(c.address.city, 0, 3)]]> info null + + group_name + null + info @@ -718,17 +718,13 @@ GROUP BY c.name]]> - max_age - Max + count + Count name null - - count - Count - $1 Min @@ -741,6 +737,10 @@ GROUP BY c.name]]> $2 Max + + max_age + Max + avg_age Average diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.NonValueAggregates.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.NonValueAggregates.xml index df0a03b653..29991e9575 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.NonValueAggregates.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/QueryPlanBaselineTests.NonValueAggregates.xml @@ -509,11 +509,11 @@ FROM c]]> - min_blah2 + min_blah Min - min_blah + min_blah2 Min @@ -557,11 +557,11 @@ FROM c]]> - max_blah + max_blah2 Max - max_blah2 + max_blah Max @@ -605,11 +605,11 @@ FROM c]]> - avg_blah2 + avg_blah Average - avg_blah + avg_blah2 Average @@ -989,11 +989,11 @@ FROM c]]> - $1 + count_blah Count - count_blah + $1 Count @@ -1181,11 +1181,11 @@ FROM c]]> - max_blah + $1 Max - $1 + max_blah Max @@ -1229,11 +1229,11 @@ FROM c]]> - max_blah + $1 Max - $1 + max_blah Max @@ -1428,15 +1428,15 @@ FROM c]]> - $1 + count_blah Count - count_blah + count_blah2 Count - count_blah2 + $1 Count @@ -1486,11 +1486,11 @@ FROM c]]> Min - min_blah2 + min_blah Min - min_blah + min_blah2 Min @@ -1536,7 +1536,7 @@ FROM c]]> - max_blah + $1 Max @@ -1544,7 +1544,7 @@ FROM c]]> Max - $1 + max_blah Max @@ -1594,11 +1594,11 @@ FROM c]]> Average - avg_blah2 + avg_blah Average - avg_blah + avg_blah2 Average diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs index c09cf3553c..2b03a74390 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs @@ -10,13 +10,11 @@ namespace Microsoft.Azure.Cosmos.Contracts using System.Linq; using System.Reflection; using System.Runtime.InteropServices; - using System.Text; using System.Text.RegularExpressions; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; [TestCategory("Windows")] [TestClass] @@ -81,6 +79,21 @@ public void MappedRegionsTest() CollectionAssert.AreEquivalent(locationNames, cosmosRegions); } + [TestMethod] + public void RegionValueCheck() + { + string[] cosmosRegions = typeof(Regions) + .GetMembers(BindingFlags.Static | BindingFlags.Public) + .Select(e => e.Name) + .ToArray(); + foreach (string region in cosmosRegions) + { + string locationNameValue = typeof(LocationNames).GetField(region).GetValue(null).ToString(); + string regionNameValue = typeof(Regions).GetField(region).GetValue(null).ToString(); + Assert.AreEqual(locationNameValue, regionNameValue); + } + } + [TestMethod] public void RMContractTest() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index aef32b7f9c..85b292b8c5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -7100,6 +7100,16 @@ "Attributes": [], "MethodInfo": "System.String SwitzerlandWest;IsInitOnly:False;IsStatic:True;" }, + "System.String TaiwanNorth": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String TaiwanNorth;IsInitOnly:False;IsStatic:True;" + }, + "System.String TaiwanNorthwest": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String TaiwanNorthwest;IsInitOnly:False;IsStatic:True;" + }, "System.String UAECentral": { "Type": "Field", "Attributes": [], From 61230f9999326ed7bc93884ecd31fcc135bcb974 Mon Sep 17 00:00:00 2001 From: Taylor Date: Thu, 4 Apr 2024 11:41:17 -0400 Subject: [PATCH 306/337] [Internal] Regions: Adds new USSec Region (#4386) Co-authored-by: Taylor Hamilton --- Directory.Build.props | 2 +- Microsoft.Azure.Cosmos/src/Regions.cs | 5 +++++ .../Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 69dc328a70..6d5f07d246 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ 3.38.1 3.39.0 preview.1 - 3.33.0 + 3.33.1 2.0.4 2.1.0 preview4 diff --git a/Microsoft.Azure.Cosmos/src/Regions.cs b/Microsoft.Azure.Cosmos/src/Regions.cs index 28a54b5def..ae5cb89097 100644 --- a/Microsoft.Azure.Cosmos/src/Regions.cs +++ b/Microsoft.Azure.Cosmos/src/Regions.cs @@ -265,6 +265,11 @@ public static class Regions /// public const string USSecWest = "USSec West"; + /// + /// Name of the Azure USNat West Central region in the Azure Cosmos DB service. + /// + public const string USSecWestCentral = "USSec West Central"; + /// /// Name of the Azure Switzerland North region in the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 85b292b8c5..63046ce862 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -7175,6 +7175,11 @@ "Attributes": [], "MethodInfo": "System.String USSecWest;IsInitOnly:False;IsStatic:True;" }, + "System.String USSecWestCentral": { + "Type": "Field", + "Attributes": [], + "MethodInfo": "System.String USSecWestCentral;IsInitOnly:False;IsStatic:True;" + }, "System.String WestCentralUS": { "Type": "Field", "Attributes": [], From 90b852611a1309c013f0acf72eca20bb843ae5e5 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 4 Apr 2024 16:33:41 -0700 Subject: [PATCH 307/337] [Internal] Query: Fixes Client QL exception by dropping ClientQLCompatibilityLevel (#4387) * Initial commit * Added Test Coverage. --- ...misticDirectExecutionQueryPipelineStage.cs | 2 +- .../OptimisticDirectExecutionQueryTests.cs | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs index ff5f6bb438..e30e383bd4 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/OptimisticDirectExecution/OptimisticDirectExecutionQueryPipelineStage.cs @@ -164,7 +164,7 @@ public static TryCatch MonadicCreate( private sealed class OptimisticDirectExecutionQueryPipelineImpl : IQueryPipelineStage { - private const int ClientQLCompatibilityLevel = 1; + private const int ClientQLCompatibilityLevel = 0; private readonly QueryPartitionRangePageAsyncEnumerator queryPartitionRangePageAsyncEnumerator; private OptimisticDirectExecutionQueryPipelineImpl( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index dbcfafa5ad..1753d3726f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -526,6 +526,62 @@ public async Task TestClientDisableOdeDefaultValue() Assert.IsFalse(clientDisablOde); } + [TestMethod] + public async Task TestKnownIssues() + { + // This query is known to cause high level of nesting in distribution plan in the backend. + // The level of nesting causes backend to fail with an exception. + // Test should fail with ClientCompatibilityLevel = 1 against production account (until backend contains a fix for this case). + // Test should pass with ClientCompatibilityLevel = 0. + string query = @"SELECT DISTINCT VALUE p1.a1 FROM p1 WHERE + (p1.a98=p1.b90 AND p1.a74=p1.b81 AND p1.a74=p1.b5 AND p1.a2=p1.b15 AND p1.a20=p1.b63 AND p1.a91=p1.b50 AND p1.a19=p1.b46 AND + p1.a8=p1.b84 AND p1.a57=p1.b26 AND p1.a1=p1.b94 AND p1.a16=p1.b3 AND p1.a78=p1.b1 AND p1.a75=p1.b64 AND p1.a68=p1.b90 AND + p1.a52=p1.b14 AND p1.a60=p1.b85 AND p1.a76=p1.b8 AND p1.a59=p1.b10 AND p1.a91=p1.b21 AND p1.a41=p1.b79 AND p1.a93=p1.b88 AND + p1.a49=p1.b20 AND p1.a75=p1.b12 AND p1.a19=p1.b39 AND p1.a17=p1.b48 AND p1.a70=p1.b16 AND p1.a2=p1.b55 AND p1.a82=p1.b96 AND + p1.a13=p1.b74 AND p1.a6=p1.b10 AND p1.a36=p1.b12 AND p1.a63=p1.b6 AND p1.a4=p1.b6 AND p1.a73=p1.b12 AND p1.a87=p1.b98 AND + p1.a92=p1.b36 AND p1.a84=p1.b21 AND p1.a1=p1.b27 AND p1.a53=p1.b59 AND p1.a25=p1.b64 AND p1.a45=p1.b30 AND p1.a73=p1.b5 AND + p1.a44=p1.b44 AND p1.a84=p1.b21 AND p1.a25=p1.b63 AND p1.a96=p1.b18 AND p1.a15=p1.b31 AND p1.a43=p1.b81 AND p1.a26=p1.b44 AND + p1.a16=p1.b70 AND p1.a38=p1.b7 AND p1.a51=p1.b18 AND p1.a55=p1.b34 AND p1.a31=p1.b80 AND p1.a54=p1.b55 AND p1.a43=p1.b54 AND + p1.a50=p1.b42 AND p1.a65=p1.b7 AND p1.a38=p1.b58 AND p1.a61=p1.b59 AND p1.a22=p1.b52 AND p1.a86=p1.b24 AND p1.a2=p1.b75 AND + p1.a22=p1.b54 AND p1.a77=p1.b20 AND p1.a2=p1.b10 AND p1.a43=p1.b54 AND p1.a27=p1.b39 AND p1.a78=p1.b56 AND p1.a49=p1.b11 AND + p1.a14=p1.b4 AND p1.a67=p1.b70 AND p1.a21=p1.b42 AND p1.a68=p1.b73 AND p1.a66=p1.b37 AND p1.a43=p1.b67 AND p1.a82=p1.b56 AND + p1.a48=p1.b85 AND p1.a20=p1.b28 AND p1.a16=p1.b79 AND p1.a13=p1.b76 AND p1.a3=p1.b34 AND p1.a54=p1.b34 AND p1.a12=p1.b95 AND + p1.a15=p1.b26 AND p1.a28=p1.b82 AND p1.a10=p1.b51 AND p1.a46=p1.b18 AND p1.a85=p1.b17 AND p1.a4=p1.b60 AND p1.a8=p1.b48 AND + p1.a88=p1.b40 AND p1.a76=p1.b34 AND p1.a27=p1.b86 AND p1.a7=p1.b41 AND p1.a19=p1.b51 AND p1.a40=p1.b70 AND p1.a97=p1.b37 AND + p1.a2=p1.b33 AND p1.a16=p1.b86 AND p1.a31=p1.b73 AND p1.a58=p1.b40 AND p1.a10=p1.b61 AND p1.a58=p1.b31 AND p1.a11=p1.b31 AND + p1.a1=p1.b3 AND p1.a25=p1.b56 AND p1.a72=p1.b64 AND p1.a88=p1.b62 AND p1.a58=p1.b21 AND p1.a7=p1.b25 AND p1.a89=p1.b74 AND + p1.a8=p1.b76 AND p1.a42=p1.b39 AND p1.a54=p1.b9 AND p1.a17=p1.b52 AND p1.a2=p1.b17 AND p1.a29=p1.b35 AND p1.a90=p1.b49 AND + p1.a31=p1.b16) ORDER BY p1.a1"; + + int documentCount = 400; + IReadOnlyList first400Integers = Enumerable.Range(0, documentCount).ToList(); + + IReadOnlyList testCases = new List + { + CreateInput( + query, + expectedResult: new List(), + partitionKey: PartitionKey.None, + enableOptimisticDirectExecution: true, + pageSizeOptions: PageSizeOptions.PageSize100, + expectedPipelineType: TestInjections.PipelineType.OptimisticDirectExecution) + }; + + List documents = new List(documentCount); + for (int i = 0; i < documentCount; ++i) + { + string document = $@"{{ {NumberField}: {i}, {NullField}: null }}"; + documents.Add(document); + } + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct, + CollectionTypes.SinglePartition, + documents, + (container, documents) => RunTests(testCases, container), + "/undefinedPartitionKey"); + } + [TestMethod] public async Task TestOdeEnvironmentVariable() { From b882e26882102a840927c1837bb0b2c174cc8808 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Fri, 5 Apr 2024 14:38:57 -0700 Subject: [PATCH 308/337] fixes bug (#4389) --- .../FaultInjectionServerErrorResultInternal.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs index 71ebcc842b..e903d61ca5 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs @@ -128,7 +128,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru { case FaultInjectionServerErrorType.Gone: INameValueCollection goneHeaders = args.RequestHeaders; - goneHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ServerGenerated410).ToString(CultureInfo.InvariantCulture)); + goneHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ServerGenerated410).ToString(CultureInfo.InvariantCulture)); storeResponse = new StoreResponse() { Status = 410, @@ -150,8 +150,8 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru case FaultInjectionServerErrorType.TooManyRequests: INameValueCollection tooManyRequestsHeaders = args.RequestHeaders; - tooManyRequestsHeaders.Add(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, "500"); - tooManyRequestsHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.RUBudgetExceeded).ToString(CultureInfo.InvariantCulture)); + tooManyRequestsHeaders.Set(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, "500"); + tooManyRequestsHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.RUBudgetExceeded).ToString(CultureInfo.InvariantCulture)); storeResponse = new StoreResponse() { @@ -188,8 +188,8 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru const string badSesstionToken = "1:1#1#1=1#1=1"; INameValueCollection readSessionHeaders = args.RequestHeaders; - readSessionHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(CultureInfo.InvariantCulture)); - readSessionHeaders.Add(HttpConstants.HttpHeaders.SessionToken, badSesstionToken); + readSessionHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(CultureInfo.InvariantCulture)); + readSessionHeaders.Set(HttpConstants.HttpHeaders.SessionToken, badSesstionToken); storeResponse = new StoreResponse() { @@ -202,7 +202,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru case FaultInjectionServerErrorType.PartitionIsMigrating: INameValueCollection partitionMigrationHeaders = args.RequestHeaders; - partitionMigrationHeaders.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture)); + partitionMigrationHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture)); storeResponse = new StoreResponse() { @@ -215,7 +215,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru case FaultInjectionServerErrorType.PartitionIsSplitting: INameValueCollection partitionSplitting = args.RequestHeaders; - partitionSplitting.Add(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture)); + partitionSplitting.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture)); storeResponse = new StoreResponse() { From d1ff001bc94e95d9265abed8328a596f95877ee5 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:39:17 -0700 Subject: [PATCH 309/337] [Internal] ContainerProperties: Adds Vector Embedding and Indexing Policy (#4379) * Initial code changes to add vector embedding policy and index type in container. * Code changes to add container builder for vector index type. * Code changes to add and fix tests. * Revert back client create and initialize test. * Skipping some of the V2 tests for vector indexes. * Code changes to fix GA and preview contracts. * Code changes to address review comments part 1. * Removed unnecessary JSON argument for vector index. * Code changes to update contract changes. * Code changes to update preview contract changes in tests. * Code changes to address few review comments. * Code changes to add few more tests to validate serialization and deserialization. * Code changes to address some review comments for best practices. * Code changes to fix test failures. --- .../src/Fluent/Settings/ContainerBuilder.cs | 27 ++++++ .../Settings/IndexingPolicyDefinition.cs | 16 ++++ .../VectorEmbeddingPolicyDefinition.cs | 42 ++++++++++ .../Fluent/Settings/VectorIndexDefinition.cs | 58 +++++++++++++ .../Resource/Settings/ContainerProperties.cs | 24 ++++++ .../src/Resource/Settings/DistanceFunction.cs | 32 ++++++++ .../src/Resource/Settings/Embedding.cs | 77 +++++++++++++++++ .../src/Resource/Settings/IndexingPolicy.cs | 33 ++++++++ .../src/Resource/Settings/VectorDataType.cs | 37 +++++++++ .../Settings/VectorEmbeddingPolicy.cs | 53 ++++++++++++ .../src/Resource/Settings/VectorIndexPath.cs | 67 +++++++++++++++ .../src/Resource/Settings/VectorIndexType.cs | 31 +++++++ .../Fluent/ContainerSettingsTests.cs | 82 +++++++++++++++++++ .../CosmosContainerSettingsTests.cs | 80 ++++++++++++++++++ .../SettingsContractTests.cs | 62 +++++++++++++- 15 files changed, 719 insertions(+), 2 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorEmbeddingPolicyDefinition.cs create mode 100644 Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorIndexDefinition.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/DistanceFunction.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/Embedding.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/VectorDataType.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/VectorEmbeddingPolicy.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexPath.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexType.cs diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerBuilder.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerBuilder.cs index a08fa3ab4e..6cb6c2a4bb 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerBuilder.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/ContainerBuilder.cs @@ -5,6 +5,8 @@ namespace Microsoft.Azure.Cosmos.Fluent { using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Threading; using System.Threading.Tasks; @@ -20,6 +22,7 @@ public class ContainerBuilder : ContainerDefinition private ConflictResolutionPolicy conflictResolutionPolicy; private ChangeFeedPolicy changeFeedPolicy; private ClientEncryptionPolicy clientEncryptionPolicy; + private VectorEmbeddingPolicy vectorEmbeddingPolicy; /// /// Creates an instance for unit-testing @@ -114,6 +117,20 @@ public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFor policyFormatVersion); } + /// + /// Defined the vector embedding policy for this Azure Cosmos container + /// + /// List of vector embeddings to include in the policy definition. + /// An instance of . + internal VectorEmbeddingPolicyDefinition WithVectorEmbeddingPolicy( + Collection embeddings) + { + return new VectorEmbeddingPolicyDefinition( + this, + embeddings, + (embeddingPolicy) => this.AddVectorEmbeddingPolicy(embeddingPolicy)); + } + /// /// Creates a container with the current fluent definition. /// @@ -220,6 +237,11 @@ public async Task CreateIfNotExistsAsync( containerProperties.ClientEncryptionPolicy = this.clientEncryptionPolicy; } + if (this.vectorEmbeddingPolicy != null) + { + containerProperties.VectorEmbeddingPolicy = this.vectorEmbeddingPolicy; + } + return containerProperties; } @@ -254,5 +276,10 @@ private void AddClientEncryptionPolicy(ClientEncryptionPolicy clientEncryptionPo { this.clientEncryptionPolicy = clientEncryptionPolicy; } + + private void AddVectorEmbeddingPolicy(VectorEmbeddingPolicy embeddingPolicy) + { + this.vectorEmbeddingPolicy = embeddingPolicy; + } } } diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/IndexingPolicyDefinition.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/IndexingPolicyDefinition.cs index d964d22621..9de73206dd 100644 --- a/Microsoft.Azure.Cosmos/src/Fluent/Settings/IndexingPolicyDefinition.cs +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/IndexingPolicyDefinition.cs @@ -113,6 +113,17 @@ public SpatialIndexDefinition> WithSpatialIndex() (spatialIndex) => this.AddSpatialPath(spatialIndex)); } + /// + /// Defines a in the current 's definition. + /// + /// An instance of . + internal VectorIndexDefinition> WithVectorIndex() + { + return new VectorIndexDefinition>( + this, + (vectorIndex) => this.AddVectorIndexPath(vectorIndex)); + } + /// /// Applies the current definition to the parent. /// @@ -133,6 +144,11 @@ private void AddSpatialPath(SpatialPath spatialSpec) this.indexingPolicy.SpatialIndexes.Add(spatialSpec); } + private void AddVectorIndexPath(VectorIndexPath vectorIndexPath) + { + this.indexingPolicy.VectorIndexes.Add(vectorIndexPath); + } + private void AddIncludedPaths(IEnumerable paths) { foreach (string path in paths) diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorEmbeddingPolicyDefinition.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorEmbeddingPolicyDefinition.cs new file mode 100644 index 0000000000..9f47145048 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorEmbeddingPolicyDefinition.cs @@ -0,0 +1,42 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Fluent +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + + /// + /// fluent definition. + /// + internal class VectorEmbeddingPolicyDefinition + { + private readonly ContainerBuilder parent; + private readonly Action attachCallback; + private readonly Collection vectorEmbeddings; + + internal VectorEmbeddingPolicyDefinition( + ContainerBuilder parent, + Collection embeddings, + Action attachCallback) + { + this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); + this.attachCallback = attachCallback ?? throw new ArgumentNullException(nameof(attachCallback)); + this.vectorEmbeddings = embeddings; + } + + /// + /// Applies the current definition to the parent. + /// + /// An instance of the parent. + public ContainerBuilder Attach() + { + VectorEmbeddingPolicy embeddingPolicy = new (this.vectorEmbeddings); + + this.attachCallback(embeddingPolicy); + return this.parent; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorIndexDefinition.cs b/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorIndexDefinition.cs new file mode 100644 index 0000000000..ab5ded29c9 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Fluent/Settings/VectorIndexDefinition.cs @@ -0,0 +1,58 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Fluent +{ + using System; + + /// + /// Vector index fluent definition. + /// + /// + internal class VectorIndexDefinition + { + private readonly VectorIndexPath vectorIndexPath = new VectorIndexPath(); + private readonly T parent; + private readonly Action attachCallback; + + internal VectorIndexDefinition( + T parent, + Action attachCallback) + { + this.parent = parent; + this.attachCallback = attachCallback; + } + + /// + /// Add a path to the current definition with a particular set of s. + /// + /// Property path for the current definition. Example: /property + /// Set of to apply to the path. + /// An instance of the current . + public VectorIndexDefinition Path( + string path, + VectorIndexType indexType) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(nameof(path)); + } + + this.vectorIndexPath.Path = path; + this.vectorIndexPath.Type = indexType; + + return this; + } + + /// + /// Applies the current definition to the parent. + /// + /// An instance of the parent. + public T Attach() + { + this.attachCallback(this.vectorIndexPath); + return this.parent; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs index 534f4f033d..4406ec5164 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ContainerProperties.cs @@ -78,6 +78,9 @@ public class ContainerProperties [JsonProperty(PropertyName = "clientEncryptionPolicy", NullValueHandling = NullValueHandling.Ignore)] private ClientEncryptionPolicy clientEncryptionPolicyInternal; + [JsonProperty(PropertyName = "vectorEmbeddingPolicy", NullValueHandling = NullValueHandling.Ignore)] + private VectorEmbeddingPolicy vectorEmbeddingPolicyInternal; + [JsonProperty(PropertyName = "computedProperties", NullValueHandling = NullValueHandling.Ignore)] private Collection computedProperties; @@ -289,6 +292,27 @@ public IndexingPolicy IndexingPolicy } } + /// + /// Gets or sets the vector embedding policy containing paths for embeddings along with path-specific settings for the item + /// used in performing vector search on the items in a collection in the Azure CosmosDB database service. + /// + /// + /// It is an optional property. + /// By default, VectorEmbeddingPolicy is set to null meaning the feature is turned off for the container. + /// + /// + /// + /// The will be applied to all the items in the container as the default policy. + /// + /// + [JsonIgnore] + internal VectorEmbeddingPolicy VectorEmbeddingPolicy + { + get => this.vectorEmbeddingPolicyInternal; + + set => this.vectorEmbeddingPolicyInternal = value; + } + /// /// Gets or sets the collection containing objects in the container. /// diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/DistanceFunction.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/DistanceFunction.cs new file mode 100644 index 0000000000..24a6b3eb25 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/DistanceFunction.cs @@ -0,0 +1,32 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Runtime.Serialization; + + /// + /// Defines the distance function for a vector index specification in the Azure Cosmos DB service. + /// + /// for usage. + internal enum DistanceFunction + { + /// + /// Represents the euclidean distance function. + /// + [EnumMember(Value = "euclidean")] + Euclidean, + + /// + /// Represents the cosine distance function. + /// + [EnumMember(Value = "cosine")] + Cosine, + + /// + /// Represents the dot product distance function. + /// + [EnumMember(Value = "dotproduct")] + DotProduct + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/Embedding.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/Embedding.cs new file mode 100644 index 0000000000..c27ac95bb1 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/Embedding.cs @@ -0,0 +1,77 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + using Newtonsoft.Json.Linq; + + /// + /// Represents the embedding settings for the vector index. + /// + internal class Embedding : IEquatable + { + /// + /// Gets or sets a string containing the path of the vector index. + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path { get; set; } + + /// + /// Gets or sets the representing the corresponding vector data type. + /// + [JsonProperty(PropertyName = "dataType")] + [JsonConverter(typeof(StringEnumConverter))] + public VectorDataType DataType { get; set; } + + /// + /// Gets or sets a long integer representing the dimensions of a vector. + /// + [JsonProperty(PropertyName = "dimensions")] + public ulong Dimensions { get; set; } + + /// + /// Gets or sets the which is used to calculate the respective distance between the vectors. + /// + [JsonProperty(PropertyName = "distanceFunction")] + [JsonConverter(typeof(StringEnumConverter))] + public DistanceFunction DistanceFunction { get; set; } + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + + /// + /// Ensures that the paths specified in the vector embedding policy are valid. + /// + public void ValidateEmbeddingPath() + { + if (string.IsNullOrEmpty(this.Path)) + { + throw new ArgumentException("Argument {0} can't be null or empty.", nameof(this.Path)); + } + + if (this.Path[0] != '/') + { + throw new ArgumentException("The argument {0} is not a valid path.", this.Path); + } + } + + /// + public bool Equals(Embedding that) + { + return this.Path.Equals(that.Path) + && this.DataType.Equals(that.DataType) + && this.Dimensions == that.Dimensions + && this.Dimensions.Equals(that.Dimensions); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/IndexingPolicy.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/IndexingPolicy.cs index fa56bdbb54..aac39e7bfe 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Settings/IndexingPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/IndexingPolicy.cs @@ -111,12 +111,45 @@ public IndexingPolicy() [JsonProperty(PropertyName = Constants.Properties.CompositeIndexes)] public Collection> CompositeIndexes { get; internal set; } = new Collection>(); + /// + /// Gets the vector indexes for additional indexes + /// + /// + /// + /// + internal Collection VectorIndexes + { + get => this.VectorIndexesInternal ??= new Collection(); + set => this.VectorIndexesInternal = value; + } + /// /// Collection of spatial index definitions to be used /// [JsonProperty(PropertyName = Constants.Properties.SpatialIndexes)] public Collection SpatialIndexes { get; internal set; } = new Collection(); + /// + /// Gets or Sets an internal placeholder collection to hold the vector indexes. + /// + [JsonProperty(PropertyName = "vectorIndexes", NullValueHandling = NullValueHandling.Ignore)] + internal Collection VectorIndexesInternal { get; set; } + /// /// This contains additional values for scenarios where the SDK is not aware of new fields. /// This ensures that if resource is read and updated none of the fields will be lost in the process. diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorDataType.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorDataType.cs new file mode 100644 index 0000000000..06be37b6fb --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorDataType.cs @@ -0,0 +1,37 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Runtime.Serialization; + + /// + /// Defines the target data type of a vector index specification in the Azure Cosmos DB service. + /// + internal enum VectorDataType + { + /// + /// Represent a float16 data type. + /// + [EnumMember(Value = "float16")] + Float16, + + /// + /// Represent a float32 data type. + /// + [EnumMember(Value = "float32")] + Float32, + + /// + /// Represent an uint8 data type. + /// + [EnumMember(Value = "uint8")] + Uint8, + + /// + /// Represent a int8 data type. + /// + [EnumMember(Value = "int8")] + Int8 + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorEmbeddingPolicy.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorEmbeddingPolicy.cs new file mode 100644 index 0000000000..8f8b7f904f --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorEmbeddingPolicy.cs @@ -0,0 +1,53 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents the vector embedding policy configuration for specifying the vector embeddings on documents in the collection in the Azure Cosmos DB service. + /// + /// + internal sealed class VectorEmbeddingPolicy + { + /// + /// Initializes a new instance of the class. + /// + /// List of embeddings to include in the policy definition. + public VectorEmbeddingPolicy(Collection embeddings) + { + VectorEmbeddingPolicy.ValidateEmbeddings(embeddings); + this.Embeddings = embeddings; + } + + /// + /// Gets a collection of that contains the vector embeddings of documents in collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = "vectorEmbeddings")] + public readonly Collection Embeddings; + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + + /// + /// Ensures that the specified vector embeddings in the policy are valid. + /// + private static void ValidateEmbeddings( + IEnumerable embeddings) + { + foreach (Embedding item in embeddings) + { + item.ValidateEmbeddingPath(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexPath.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexPath.cs new file mode 100644 index 0000000000..c6c00801ac --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexPath.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + using Newtonsoft.Json.Linq; + + /// + /// DOM for a vector index path. A vector index path is used in a vector index. + /// + /// + /// + /// + internal sealed class VectorIndexPath + { + /// + /// Gets or sets the full path in a document used for vector indexing. + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path { get; set; } + + /// + /// Gets or sets the for the vector index path. + /// + [JsonProperty(PropertyName = "type")] + [JsonConverter(typeof(StringEnumConverter))] + public VectorIndexType Type { get; set; } + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexType.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexType.cs new file mode 100644 index 0000000000..64318c9389 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/VectorIndexType.cs @@ -0,0 +1,31 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Runtime.Serialization; + + /// + /// Defines the target index type of an vector index path specification in the Azure Cosmos DB service. + /// + internal enum VectorIndexType + { + /// + /// Represents a flat vector index type. + /// + [EnumMember(Value = "flat")] + Flat, + + /// + /// Represents a Disk ANN vector index type. + /// + [EnumMember(Value = "diskANN")] + DiskANN, + + /// + /// Represents a quantized flat vector index type. + /// + [EnumMember(Value = "quantizedFlat")] + QuantizedFlat + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs index 8eb72cac25..a757aec147 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Fluent/ContainerSettingsTests.cs @@ -538,6 +538,88 @@ await databaseForChangeFeed.DefineContainer(containerName, partitionKeyPath) } } + [TestMethod] + [Ignore("This test will be enabled once the vector similarity changes are made available into the public emulator.")] + public async Task TestVectorEmbeddingPolicy() + { + string vector1Path = "/vector1", vector2Path = "/vector2", vector3Path = "/vector3"; + Database databaseForVectorEmbedding = await this.GetClient().CreateDatabaseAsync("vectorEmbeddingContainerTest", + cancellationToken: this.cancellationToken); + + try + { + Collection embeddings = new Collection() + { + new Embedding() + { + Path = vector1Path, + DataType = VectorDataType.Int8, + DistanceFunction = DistanceFunction.DotProduct, + Dimensions = 1200, + }, + new Embedding() + { + Path = vector2Path, + DataType = VectorDataType.Uint8, + DistanceFunction = DistanceFunction.Cosine, + Dimensions = 3, + }, + new Embedding() + { + Path = vector3Path, + DataType = VectorDataType.Float32, + DistanceFunction = DistanceFunction.Euclidean, + Dimensions = 400, + }, + }; + + string containerName = "vectorEmbeddingContainerTest"; + string partitionKeyPath = "/users"; + + ContainerResponse containerResponse = + await databaseForVectorEmbedding.DefineContainer(containerName, partitionKeyPath) + .WithVectorEmbeddingPolicy(embeddings) + .Attach() + .WithIndexingPolicy() + .WithVectorIndex() + .Path(vector1Path, VectorIndexType.Flat) + .Attach() + .WithVectorIndex() + .Path(vector2Path, VectorIndexType.Flat) + .Attach() + .WithVectorIndex() + .Path(vector3Path, VectorIndexType.Flat) + .Attach() + .Attach() + .CreateAsync(); + + Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode); + Assert.AreEqual(containerName, containerResponse.Resource.Id); + Assert.AreEqual(partitionKeyPath, containerResponse.Resource.PartitionKey.Paths.First()); + ContainerProperties containerSettings = containerResponse.Resource; + + // Validate Vector Embeddings. + Assert.IsNotNull(containerSettings.VectorEmbeddingPolicy); + Assert.IsNotNull(containerSettings.VectorEmbeddingPolicy.Embeddings); + Assert.AreEqual(embeddings.Count, containerSettings.VectorEmbeddingPolicy.Embeddings.Count()); + Assert.IsTrue(embeddings.OrderBy(x => x.Path).SequenceEqual(containerSettings.VectorEmbeddingPolicy.Embeddings.OrderBy(x => x.Path))); + + // Validate Vector Indexes. + Assert.IsNotNull(containerSettings.IndexingPolicy.VectorIndexes); + Assert.AreEqual(embeddings.Count, containerSettings.IndexingPolicy.VectorIndexes.Count()); + Assert.AreEqual(vector1Path, containerSettings.IndexingPolicy.VectorIndexes[0].Path); + Assert.AreEqual(VectorIndexType.Flat, containerSettings.IndexingPolicy.VectorIndexes[0].Type); + Assert.AreEqual(vector2Path, containerSettings.IndexingPolicy.VectorIndexes[1].Path); + Assert.AreEqual(VectorIndexType.Flat, containerSettings.IndexingPolicy.VectorIndexes[1].Type); + Assert.AreEqual(vector3Path, containerSettings.IndexingPolicy.VectorIndexes[2].Path); + Assert.AreEqual(VectorIndexType.Flat, containerSettings.IndexingPolicy.VectorIndexes[2].Type); + } + finally + { + await databaseForVectorEmbedding.DeleteAsync(); + } + } + [TestMethod] public async Task WithIndexingPolicy() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs index bda132d6a3..bae30c8acd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosContainerSettingsTests.cs @@ -4,6 +4,7 @@ namespace Microsoft.Azure.Cosmos.Tests { + using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; @@ -179,6 +180,85 @@ public void SettingPKShouldNotResetVersion() Assert.AreEqual(Cosmos.PartitionKeyDefinitionVersion.V2, containerProperties.PartitionKeyDefinitionVersion); } + [TestMethod] + public void ValidateVectorEmbeddingsAndIndexes() + { + Embedding embedding1 = new () + { + Path = "/vector1", + DataType = VectorDataType.Int8, + DistanceFunction = DistanceFunction.DotProduct, + Dimensions = 1200, + }; + + Embedding embedding2 = new () + { + Path = "/vector2", + DataType = VectorDataType.Uint8, + DistanceFunction = DistanceFunction.Cosine, + Dimensions = 3, + }; + + Embedding embedding3 = new () + { + Path = "/vector3", + DataType = VectorDataType.Float32, + DistanceFunction = DistanceFunction.Euclidean, + Dimensions = 400, + }; + + Collection embeddings = new Collection() + { + embedding1, + embedding2, + embedding3, + }; + + ContainerProperties containerSettings = new ContainerProperties(id: "TestContainer", partitionKeyPath: "/partitionKey") + { + VectorEmbeddingPolicy = new(embeddings), + IndexingPolicy = new Cosmos.IndexingPolicy() + { + VectorIndexes = new() + { + new VectorIndexPath() + { + Path = "/vector1", + Type = VectorIndexType.Flat, + }, + new VectorIndexPath() + { + Path = "/vector2", + Type = VectorIndexType.Flat, + }, + new VectorIndexPath() + { + Path = "/vector3", + Type = VectorIndexType.Flat, + } + }, + + }, + }; + + Assert.IsNotNull(containerSettings.IndexingPolicy); + Assert.IsNotNull(containerSettings.VectorEmbeddingPolicy); + Assert.IsNotNull(containerSettings.IndexingPolicy.VectorIndexes); + + VectorEmbeddingPolicy embeddingPolicy = containerSettings.VectorEmbeddingPolicy; + Assert.IsNotNull(embeddingPolicy.Embeddings); + Assert.AreEqual(embeddings.Count, embeddingPolicy.Embeddings.Count()); + CollectionAssert.AreEquivalent(embeddings, embeddingPolicy.Embeddings.ToList()); + + Collection vectorIndexes = containerSettings.IndexingPolicy.VectorIndexes; + Assert.AreEqual("/vector1", vectorIndexes[0].Path); + Assert.AreEqual(VectorIndexType.Flat, vectorIndexes[0].Type); + Assert.AreEqual("/vector2", vectorIndexes[1].Path); + Assert.AreEqual(VectorIndexType.Flat, vectorIndexes[1].Type); + Assert.AreEqual("/vector3", vectorIndexes[2].Path); + Assert.AreEqual(VectorIndexType.Flat, vectorIndexes[2].Type); + } + private static string SerializeDocumentCollection(DocumentCollection collection) { using (MemoryStream ms = new MemoryStream()) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs index 4cf045cd7b..0aebb7e07d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/SettingsContractTests.cs @@ -339,7 +339,7 @@ public void AccountPropertiesDeserializeWithAdditionalDataTest() [TestMethod] public void ContainerPropertiesDeserializeWithAdditionalDataTest() { - string cosmosSerialized = "{\"indexingPolicy\":{\"automatic\":true,\"indexingMode\":\"Consistent\",\"additionalIndexPolicy\":\"indexpolicyvalue\",\"includedPaths\":[{\"path\":\"/included/path\",\"additionalIncludedPath\":\"includedPathValue\",\"indexes\":[]}],\"excludedPaths\":[{\"path\":\"/excluded/path\",\"additionalExcludedPath\":\"excludedPathValue\"}],\"compositeIndexes\":[[{\"path\":\"/composite/path\",\"additionalCompositeIndex\":\"compositeIndexValue\",\"order\":\"ascending\"}]],\"spatialIndexes\":[{\"path\":\"/spatial/path\",\"additionalSpatialIndexes\":\"spatialIndexValue\",\"types\":[]}]},\"computedProperties\":[{\"name\":\"lowerName\",\"query\":\"SELECT VALUE LOWER(c.name) FROM c\"},{\"name\":\"estimatedTax\",\"query\":\"SELECT VALUE c.salary * 0.2 FROM c\"}],\"geospatialConfig\":{\"type\":\"Geography\",\"additionalGeospatialConfig\":\"geospatialConfigValue\"},\"uniqueKeyPolicy\":{\"additionalUniqueKeyPolicy\":\"uniqueKeyPolicyValue\",\"uniqueKeys\":[{\"paths\":[\"/unique/key/path/1\",\"/unique/key/path/2\"]}]},\"conflictResolutionPolicy\":{\"mode\":\"LastWriterWins\",\"additionalConflictResolutionPolicy\":\"conflictResolutionValue\"},\"clientEncryptionPolicy\":{\"includedPaths\":[{\"path\":\"/path\",\"clientEncryptionKeyId\":\"clientEncryptionKeyId\",\"encryptionType\":\"Randomized\",\"additionalIncludedPath\":\"includedPathValue\",\"encryptionAlgorithm\":\"AEAD_AES_256_CBC_HMAC_SHA256\"}],\"policyFormatVersion\":1,\"additionalEncryptionPolicy\":\"clientEncryptionpolicyValue\"},\"id\":\"2a9f501b-6948-4795-8fd1-797defb5c466\",\"partitionKey\":{\"paths\":[],\"kind\":\"Hash\"}}"; + string cosmosSerialized = "{\"indexingPolicy\":{\"automatic\":true,\"indexingMode\":\"Consistent\",\"additionalIndexPolicy\":\"indexpolicyvalue\",\"includedPaths\":[{\"path\":\"/included/path\",\"additionalIncludedPath\":\"includedPathValue\",\"indexes\":[]}],\"excludedPaths\":[{\"path\":\"/excluded/path\",\"additionalExcludedPath\":\"excludedPathValue\"}],\"compositeIndexes\":[[{\"path\":\"/composite/path\",\"additionalCompositeIndex\":\"compositeIndexValue\",\"order\":\"ascending\"}]],\"spatialIndexes\":[{\"path\":\"/spatial/path\",\"additionalSpatialIndexes\":\"spatialIndexValue\",\"types\":[]}],\"vectorIndexes\":[{\"path\":\"/vector1\",\"type\":\"flat\",\"additionalVectorIndex\":\"vectorIndexValue1\"},{\"path\":\"/vector2\",\"type\":\"quantizedFlat\",\"additionalVectorIndex\":\"vectorIndexValue2\"},{\"path\":\"/vector3\",\"type\":\"diskANN\"}]},\"computedProperties\":[{\"name\":\"lowerName\",\"query\":\"SELECT VALUE LOWER(c.name) FROM c\"},{\"name\":\"estimatedTax\",\"query\":\"SELECT VALUE c.salary * 0.2 FROM c\"}],\"geospatialConfig\":{\"type\":\"Geography\",\"additionalGeospatialConfig\":\"geospatialConfigValue\"},\"uniqueKeyPolicy\":{\"additionalUniqueKeyPolicy\":\"uniqueKeyPolicyValue\",\"uniqueKeys\":[{\"paths\":[\"/unique/key/path/1\",\"/unique/key/path/2\"]}]},\"conflictResolutionPolicy\":{\"mode\":\"LastWriterWins\",\"additionalConflictResolutionPolicy\":\"conflictResolutionValue\"},\"clientEncryptionPolicy\":{\"includedPaths\":[{\"path\":\"/path\",\"clientEncryptionKeyId\":\"clientEncryptionKeyId\",\"encryptionType\":\"Randomized\",\"additionalIncludedPath\":\"includedPathValue\",\"encryptionAlgorithm\":\"AEAD_AES_256_CBC_HMAC_SHA256\"}],\"policyFormatVersion\":1,\"additionalEncryptionPolicy\":\"clientEncryptionpolicyValue\"},\"id\":\"2a9f501b-6948-4795-8fd1-797defb5c466\",\"partitionKey\":{\"paths\":[],\"kind\":\"Hash\"},\"vectorEmbeddingPolicy\":{\"vectorEmbeddings\":[{\"path\":\"/vector1\",\"dataType\":\"float32\",\"dimensions\":1200,\"distanceFunction\":\"cosine\"},{\"path\":\"/vector2\",\"dataType\":\"int8\",\"dimensions\":3,\"distanceFunction\":\"dotproduct\"},{\"path\":\"/vector3\",\"dataType\":\"uint8\",\"dimensions\":400,\"distanceFunction\":\"euclidean\"}]}}"; JObject complexObject = JObject.FromObject(new { id = 1, name = new { fname = "fname", lname = "lname" } }); @@ -368,6 +368,14 @@ public void ContainerPropertiesDeserializeWithAdditionalDataTest() Assert.AreEqual(1, containerProperties.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties.Count); Assert.AreEqual("compositeIndexValue", containerProperties.IndexingPolicy.CompositeIndexes[0][0].AdditionalProperties["additionalCompositeIndex"]); + Assert.AreEqual(1, containerProperties.IndexingPolicy.VectorIndexes[0].AdditionalProperties.Count); + Assert.AreEqual("vectorIndexValue1", containerProperties.IndexingPolicy.VectorIndexes[0].AdditionalProperties["additionalVectorIndex"]); + + Assert.AreEqual(1, containerProperties.IndexingPolicy.VectorIndexes[1].AdditionalProperties.Count); + Assert.AreEqual("vectorIndexValue2", containerProperties.IndexingPolicy.VectorIndexes[1].AdditionalProperties["additionalVectorIndex"]); + + Assert.IsNull(containerProperties.IndexingPolicy.VectorIndexes[2].AdditionalProperties); + Assert.AreEqual(1, containerProperties.IndexingPolicy.IncludedPaths[0].AdditionalProperties.Count); Assert.AreEqual("includedPathValue", containerProperties.IndexingPolicy.IncludedPaths[0].AdditionalProperties["additionalIncludedPath"]); @@ -389,6 +397,13 @@ public void ContainerPropertiesDeserializeWithAdditionalDataTest() Assert.AreEqual(1, containerProperties.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties.Count); Assert.AreEqual("includedPathValue", containerProperties.ClientEncryptionPolicy.IncludedPaths.First().AdditionalProperties["additionalIncludedPath"]); + Assert.IsNotNull(containerProperties.VectorEmbeddingPolicy); + Assert.AreEqual(3, containerProperties.VectorEmbeddingPolicy.Embeddings.Count); + Assert.AreEqual("/vector1", containerProperties.VectorEmbeddingPolicy.Embeddings[0].Path); + Assert.AreEqual(VectorDataType.Float32, containerProperties.VectorEmbeddingPolicy.Embeddings[0].DataType); + Assert.AreEqual((ulong)1200, containerProperties.VectorEmbeddingPolicy.Embeddings[0].Dimensions); + Assert.AreEqual(DistanceFunction.Cosine, containerProperties.VectorEmbeddingPolicy.Embeddings[0].DistanceFunction); + Assert.AreEqual(2, containerProperties.ComputedProperties.Count); Assert.AreEqual("lowerName", containerProperties.ComputedProperties[0].Name); Assert.AreEqual("SELECT VALUE LOWER(c.name) FROM c", containerProperties.ComputedProperties[0].Query); @@ -748,7 +763,8 @@ public void ContainerSettingsDefaults() "PartitionKeyDefinitionVersion", "ConflictResolutionPolicy", "ClientEncryptionPolicy", - "PartitionKeyPaths"); + "PartitionKeyPaths", + "VectorEmbeddingPolicy"); #endif // Two equivalent definitions @@ -1054,6 +1070,48 @@ public void ChangeFeedPolicySerialization_InvalidValues() Assert.ThrowsException(() => new Cosmos.ChangeFeedPolicy() { FullFidelityRetention = TimeSpan.FromSeconds(-10) }); } + [TestMethod] + public void VectorEmbeddingPolicySerialization() + { + ContainerProperties containerSettings = new ContainerProperties("TestContainer", "/pk"); + string serialization = JsonConvert.SerializeObject(containerSettings); + Assert.IsFalse(serialization.Contains("vectorEmbeddingPolicy"), "Vector Embedding Policy should not be included by default"); + + Embedding embedding1 = new() + { + Path = "/vector1", + DataType = VectorDataType.Int8, + DistanceFunction = DistanceFunction.DotProduct, + Dimensions = 1200, + }; + + Embedding embedding2 = new() + { + Path = "/vector2", + DataType = VectorDataType.Uint8, + DistanceFunction = DistanceFunction.Cosine, + Dimensions = 3, + }; + + Collection embeddings = new () + { + embedding1, + embedding2, + }; + + containerSettings.VectorEmbeddingPolicy = new VectorEmbeddingPolicy(embeddings); + + string serializationWithValues = JsonConvert.SerializeObject(containerSettings); + Assert.IsTrue(serializationWithValues.Contains("vectorEmbeddingPolicy"), "Vector Embedding Policy should be included."); + Assert.IsTrue(serializationWithValues.Contains("distanceFunction"), "Vector Embedding Policy distance function should be included."); + + JObject parsed = JObject.Parse(serializationWithValues); + JToken vectorEmbeddings = parsed["vectorEmbeddingPolicy"]["vectorEmbeddings"]; + Assert.AreEqual(JTokenType.Array, vectorEmbeddings.Type, "Vector Embedding Policy serialized vectorEmbeddings should be an array."); + Assert.IsTrue(embedding1.Equals(vectorEmbeddings.Value()[0].ToObject())); + Assert.IsTrue(embedding2.Equals(vectorEmbeddings.Value()[1].ToObject())); + } + private static T CosmosDeserialize(string payload) { using (MemoryStream ms = new MemoryStream()) From 4b2196bc6023dca0e6a396612efb4a1ca14cf09a Mon Sep 17 00:00:00 2001 From: joegoldman2 <147369450+joegoldman2@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:27:13 +0000 Subject: [PATCH 310/337] Distributed Tracing: Update operation name for non-generic feed iterator read operation (#4374) * Distributed Tracing: Update operation name for non-generic feed iterator read operation * Update tests --------- Co-authored-by: joegoldman2 <147369450+joegoldman@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../FeedIterators/FeedIteratorInlineCore.cs | 2 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 96 +++++++++---------- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 64 ++++++------- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs index e1d18b72af..674f3adbea 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/FeedIterators/FeedIteratorInlineCore.cs @@ -52,7 +52,7 @@ public override CosmosElement GetCosmosElementContinuationToken() public override Task ReadNextAsync(CancellationToken cancellationToken = default) { return this.clientContext.OperationHelperAsync( - operationName: "FeedIterator Read Next Async", + operationName: "FeedIterator ReadNextAsync", containerName: this.container?.Id, databaseName: this.container?.Database?.Id ?? this.databaseName, operationType: Documents.OperationType.ReadFeed, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 460eaa593c..1a881f3a14 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -21,7 +21,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -655,10 +655,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -676,10 +676,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -697,10 +697,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -1492,7 +1492,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -2126,10 +2126,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -2147,10 +2147,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -2168,10 +2168,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -3786,7 +3786,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -4441,10 +4441,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -4462,10 +4462,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -4483,10 +4483,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index 736119560b..b6ce2e777d 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -20,7 +20,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -596,10 +596,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -616,10 +616,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -636,10 +636,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -1367,7 +1367,7 @@ - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -1943,10 +1943,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -1963,10 +1963,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb @@ -1983,10 +1983,10 @@ Some Value South Central US - + Microsoft.DocumentDB https://opentelemetry.io/schemas/1.23.0 - FeedIterator Read Next Async + FeedIterator ReadNextAsync databaseName containerName cosmosdb From 496ddba88bbe43f1734bc200c6f5ace4ed2ce19f Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Tue, 9 Apr 2024 16:17:24 -0400 Subject: [PATCH 311/337] SDK 3.39.0: Adds version bump and changelog. (#4391) * SDK 3.40.0-preview.0: Adds version bump and changelog. * SDK 3.40.0-preview.0: Adds version bump and changelog. * SDK 3.40.0-preview.0: Adds version bump and changelog. * change version for release; create diffs * added query PRs to changelog * add note for Rename refactoring of ChangeFeedItemChange to changelog * removing 4281 since it was mislabeled. it should have been treated as Internal * grammar error * formatting * case change * Update changelog.md Co-authored-by: Justine Cocchi * removing 4317 from change log. should be internal * add new regions to changelog. also Direct Package version update * fixed linked to DP PR * more changes based on review --------- Co-authored-by: Justine Cocchi --- Directory.Build.props | 6 +- .../contracts/API_3.39.0.txt | 1576 ++++++++++++++++ .../contracts/API_3.40.0-preview.0.txt | 1628 +++++++++++++++++ changelog.md | 30 + 4 files changed, 3237 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.39.0.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.40.0-preview.0.txt diff --git a/Directory.Build.props b/Directory.Build.props index 6d5f07d246..b40a53cfd0 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.38.1 - 3.39.0 - preview.1 + 3.39.0 + 3.40.0 + preview.0 3.33.1 2.0.4 2.1.0 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.39.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.39.0.txt new file mode 100644 index 0000000000..9644b91e25 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.39.0.txt @@ -0,0 +1,1576 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public IEnumerable AccountInitializationCustomEndpoints { get; set; } + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public abstract class CosmosLinqSerializer : CosmosSerializer + { + protected CosmosLinqSerializer(); + public abstract string SerializeMemberName(MemberInfo memberInfo); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MexicoCentral = "Mexico Central"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string TaiwanNorth = "Taiwan North"; + public const string TaiwanNorthwest = "Taiwan Northwest"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string USSecWestCentral = "USSec West Central"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomAccountEndpoints(IEnumerable customAccountEndpoints); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.40.0-preview.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.40.0-preview.0.txt new file mode 100644 index 0000000000..f43f227d14 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.40.0-preview.0.txt @@ -0,0 +1,1628 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItem + { + public ChangeFeedItem(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithAllVersionsAndDeletes(string processorName, Container.ChangeFeedHandler> onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public IEnumerable AccountInitializationCustomEndpoints { get; set; } + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public Nullable PriorityLevel { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public abstract class CosmosLinqSerializer : CosmosSerializer + { + protected CosmosLinqSerializer(); + public abstract string SerializeMemberName(MemberInfo memberInfo); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string MexicoCentral = "Mexico Central"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SpainCentral = "Spain Central"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string TaiwanNorth = "Taiwan North"; + public const string TaiwanNorthwest = "Taiwan Northwest"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string USSecWestCentral = "USSec West Central"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + public abstract double TotalRequestCharge { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract double RequestCharge { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomAccountEndpoints(IEnumerable customAccountEndpoints); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithPriorityLevel(PriorityLevel priorityLevel); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 48a400269a..ba26c7365c 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,36 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.40.0-preview.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.40.0-preview.0) - 2024-04-05 + +#### Fixed +- [4334](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4334) ChangeFeedProcessor: Fixes when ChangeFeedMode is switched, an exception is thrown + +#### Added +- [4370](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4370) ChangeFeedProcessor: Adds AllVersionsAndDeletes support to ChangeFeedProcessor +- [4380](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4380) ChangeFeedProcessor: Refactors AllVersionsAndDeletes Metadata Contract for ChangeFeed and ChangeFeedProcessor + > Note: A Rename refactoring was performed in the effort to reduce redundancy and achieve clarity from a user perspective. The previous type `ChangeFeedItemChange` was strategically renamed to `ChangeFeedItem`. The refactoring affects both ChangeFeed (pull), and the new ChangeFeedProcessor (push), when in AllVersionsAndDeletes ChangeFeedMode. LatestVersion ChangeFeedMode is not affected and will continue to function as expected. + +### [3.39.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0) - 2024-04-05 + +#### Fixed +- [4357](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4357) Distributed Tracing Documentation : Fixes the default value mentioned in code doc + +#### Added +- [4377](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4377) Integrated cache: Adds BypassIntegratedCache for public release +- [4265](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4265) CosmosClientOptions: Adds Private Custom Account Endpoints +- [4316](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4316) Distributed Tracing: Refactors code to rename net.peer.name attribute to server.address. **Warning:** This is a breaking change, only `server.address` will be emitted starting with this version. +- [4339](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4338) Diagnostics: Adds Client Configuration for Synchronization context cases +- [4333](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4333) Distributed Tracing: Adds configuration to disable network level tracing in sdk permanently +- [4323](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4323) Query: Adds Support for LINQ Custom Serializer in Public Release +- [4362](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4362) Query: Adds support for non streaming ORDER BY +- [4074](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4074) Query: Adds translation support for single key single value select GROUP BY LINQ queries +- [4361](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4361) Performance: Refactors query prefetch mechanism +- [4386](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4386) Regions: Adds new Regions + > Note: There is added support for the following regions: `Taiwan North` and `Taiwan Northwest`. + > This also includes a Direct Package version update to 3.33.0 in PR [#4353](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4353) + + ### [3.39.0-preview.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.0-preview.1) - 2024-02-02 ### [3.38.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.38.1) - 2024-02-02 From cb7f923a136a1d44ee169f019cf66ad6a581e6ec Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Wed, 10 Apr 2024 12:51:11 -0700 Subject: [PATCH 312/337] [Internal] Pipelines: Adds MultiRegion Test support for release pipelines (#4398) --- azure-pipelines-official.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines-official.yml b/azure-pipelines-official.yml index 4fad394780..1605914da0 100644 --- a/azure-pipelines-official.yml +++ b/azure-pipelines-official.yml @@ -22,6 +22,7 @@ stages: BuildConfiguration: '${{ variables.BuildConfiguration }}' Arguments: '${{ variables.ReleaseArguments }}' VmImage: '${{ variables.VmImage }}' + MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION) - job: displayName: TelemetryToService ${{ variables.BuildConfiguration }} From 0e066252cf64f998a2fd456995ba49c8b02147e5 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Thu, 11 Apr 2024 12:09:05 -0700 Subject: [PATCH 313/337] Query: Fixes ResponseMessage not parsing the IndexMetrics as text in latest sdk (#4397) * Fix response message not parsing the index advice as text in latest sdk * add test coverage * address code review --------- Co-authored-by: Minh Le (from Dev Box) --- .../src/Handler/ResponseMessage.cs | 2 +- .../IndexMetricsParserBaselineTest.cs | 47 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs index e29204c489..6f1324c9da 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs @@ -83,7 +83,7 @@ internal ResponseMessage( this.CosmosException = cosmosException; this.Headers = headers ?? new Headers(); - this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics(this.Headers, isBase64Encoded: true); + this.IndexUtilizationText = ResponseMessage.DecodeIndexMetrics(this.Headers, isBase64Encoded: false); if (requestMessage != null && requestMessage.Trace != null) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs index d54fa8cd67..0f47f55dbb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/IndexMetricsParserBaselineTest.cs @@ -384,6 +384,18 @@ public override IndexMetricsParserTestOutput ExecuteTest(IndexMetricsParserTestI // Make sure ODE and non-ODE is consistent Assert.AreEqual(indexMetricsNonODE, indexMetricsODE); + + // ---------------------------- + // Test stream API + // ---------------------------- + // Execute without ODE + string indexMetricsNonODEStreaming = RunStreamAPITest(input.Query, enableOptimisticDirectExecution: false); + + // Execute with ODE + string indexMetricsODEStreaming = RunStreamAPITest(input.Query, enableOptimisticDirectExecution: true); + + // Make sure ODE and non-ODE is consistent + Assert.AreEqual(indexMetricsNonODEStreaming, indexMetricsODEStreaming); return new IndexMetricsParserTestOutput(indexMetricsNonODE); } @@ -403,7 +415,42 @@ private static string RunTest(string query, bool enableOptimisticDirectExecution { FeedResponse page = itemQuery.ReadNextAsync().Result; Assert.IsTrue(page.Headers.AllKeys().Length > 1); + if (roundTripCount > 0) + { + if (page.IndexMetrics != null) + { + Assert.Fail("Expected only Index Metrics on first round trip. Current round trip %n", roundTripCount); + } + } + else + { + Assert.IsNotNull(page.Headers.Get(HttpConstants.HttpHeaders.IndexUtilization), "Expected index utilization headers for query"); + Assert.IsNotNull(page.IndexMetrics, "Expected index metrics response for query"); + + indexMetrics = page.IndexMetrics; + } + + roundTripCount++; + } + + return indexMetrics; + } + + private static string RunStreamAPITest(string query, bool enableOptimisticDirectExecution) + { + QueryRequestOptions requestOptions = new QueryRequestOptions() { PopulateIndexMetrics = true, EnableOptimisticDirectExecution = enableOptimisticDirectExecution }; + using FeedIterator itemQuery = testContainer.GetItemQueryStreamIterator( + queryText: query, + requestOptions: requestOptions); + + // Index Metrics is returned fully on the first page so no need to worry about result set + int roundTripCount = 0; + string indexMetrics = null; + while (itemQuery.HasMoreResults) + { + ResponseMessage page = itemQuery.ReadNextAsync().Result; + Assert.IsTrue(page.Headers.AllKeys().Length > 1); if (roundTripCount > 0) { if (page.IndexMetrics != null) From f335f6563b64a83baeecc5df04379ea80112011d Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 11 Apr 2024 18:06:54 -0700 Subject: [PATCH 314/337] update readme to make it more clear (#4399) Co-authored-by: Kiran Kumar Kolli --- .../README.md | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/README.md b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/README.md index 9d27fcd727..60b6959808 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/README.md +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/README.md @@ -1,6 +1,19 @@ -Sample usage pattern +# Cosmos Performance Testing -> dotnet run -c Release --framework net6.0 -- -j Medium -f *MockedItemBenchmark* -m --allStats --join +The goal of this project is to provide a set of benchmarks to measure the performance of Cosmos SDK. The benchmarks are written using the BenchmarkDotNet. This project contains both end-to-end benchmarks and benchmarks using a mocked version of the Cosmos SDK to removed variablility from the network layer. -Run all benchmarks for gates: -dotnet run -c Release --framework net6.0 --allCategories=GateBenchmark -- -j Medium -m --BaselineValidation \ No newline at end of file +## Running the benchmarks + +To run all benchmarks for gates use the command: + +```bash +dotnet run -c Release --framework net6.0 --allCategories=GateBenchmark -- -j Medium -m --BaselineValidation +``` + +To run a particular benchmark or set of benchmarks use the command: + +```bash +dotnet run -c Release --framework net6.0 --allCategories=GateBenchmark -- -j Medium -f *SpecifyBenchmarkHere* -m --allStats --join +``` + +When doing this you can specify the name of the benchmark or benchmark class between the `*`s in the command above. From ef719fb2ae071589e7d3d71a955d647fd8e93909 Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 12 Apr 2024 11:06:49 +0530 Subject: [PATCH 315/337] [Internal] Distributed Tracing: Fixes Client Config Test (#4406) * Adds code to create activity even customer is not subscribed to the feature * Added documentation --- .../OpenTelemetry/OpenTelemetryRecorderFactory.cs | 11 ++++++++++- .../ClientConfigurationDiagnosticTest.cs | 5 ++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index f1d02583f9..1b16f48307 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -57,10 +57,19 @@ public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, clientContext: clientContext, config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); } - +#if !INTERNAL + // If there are no listeners at operation level and no parent activity created. + // Then create a dummy activity as there should be a parent level activity always to send a traceid to the backend services through context propagation. + // The parent activity id logged in diagnostics, can be used for tracing purpose in backend. + if (Activity.Current is null) + { + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateParentActivity(operationName); + } +#endif // Safety check as diagnostic logs should not break the code. if (Activity.Current?.TraceId != null) { + // This id would be useful to trace calls at backend services when distributed tracing feature is available there. trace.AddDatum("DistributedTraceId", Activity.Current.TraceId); } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs index 9a5c4255a7..742d6df4ab 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs @@ -2,7 +2,6 @@ { using System; using System.Collections.Generic; - using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; @@ -47,9 +46,9 @@ public async Task ClientConfigTest() Assert.IsNotNull(response.Diagnostics); ITrace trace = ((CosmosTraceDiagnostics)response.Diagnostics).Value; #if PREVIEW - Assert.AreEqual(trace.Data.Count, 2, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); // Distributed Tracing Id + Assert.AreEqual(actual: trace.Data.Count, expected: 2, message: string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); // Distributed Tracing Id #else - Assert.AreEqual(trace.Data.Count, 1, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); + Assert.AreEqual(actual: trace.Data.Count, expected: 1, message: string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); #endif ClientConfigurationTraceDatum clientConfigurationTraceDatum = (ClientConfigurationTraceDatum)trace.Data["Client Configuration"]; Assert.IsNotNull(clientConfigurationTraceDatum.UserAgentContainer.UserAgent); From 2c5ab47d945b95a7f51854c449cdde4ab0978adb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 18:13:37 +0000 Subject: [PATCH 316/337] Bump Azure.Identity in /Microsoft.Azure.Cosmos.Samples/Usage/Encryption (#4410) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.10.2 to 1.11.0. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.10.2...Azure.Identity_1.11.0) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../Usage/Encryption/Encryption.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj index 3d29248400..903a033ff3 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj @@ -8,7 +8,7 @@ latest - + From 36a35472dfef91535b5afa318419a7e4fab82be1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 20:59:05 +0000 Subject: [PATCH 317/337] Bump Azure.Identity (#4409) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.10.2 to 1.11.0. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.10.2...Azure.Identity_1.11.0) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matias Quaranta --- .../Usage/ReEncryption/ReEncryption.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj index 54c70c4ec6..2677c74426 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj @@ -8,7 +8,7 @@ latest - + From bf4704f5cfec00fd1e7cb8b81c02ce8d53e15d41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 18:36:27 +0000 Subject: [PATCH 318/337] Bump OpenTelemetry.Instrumentation.Http (#4414) Bumps [OpenTelemetry.Instrumentation.Http](https://github.com/open-telemetry/opentelemetry-dotnet) from 1.6.0-rc.1 to 1.8.1. - [Release notes](https://github.com/open-telemetry/opentelemetry-dotnet/releases) - [Commits](https://github.com/open-telemetry/opentelemetry-dotnet/compare/1.6.0-rc.1...Instrumentation.Http-1.8.1) --- updated-dependencies: - dependency-name: OpenTelemetry.Instrumentation.Http dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Usage/OpenTelemetry/OpenTelemetry.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj index 42eb521c7a..899e06fdaf 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/OpenTelemetry/OpenTelemetry.csproj @@ -13,7 +13,7 @@ - + From 08338af632dcbda8d2afdce756a57ea45b09a745 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:24:04 -0700 Subject: [PATCH 319/337] Fix bug in OrderByCrossPartitionQueryPipelineStage to ensure that failures in creating the inner pipeline stage are bubbled up to the higher stages (#4419) --- ...OrderByCrossPartitionQueryPipelineStage.cs | 2 +- .../Query/OrderByQueryTests.cs | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index edd2fa7be7..cfe911966d 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -160,7 +160,7 @@ public async ValueTask MoveNextAsync(ITrace trace, CancellationToken cance } TryCatch hasNext = await this.inner.TryAsync(pipelineStage => pipelineStage.MoveNextAsync(trace, cancellationToken)); - return hasNext.Succeeded && hasNext.Result; + return hasNext.Failed || hasNext.Result; } public ValueTask DisposeAsync() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs index 94ef30a365..14fe64ed8a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OrderByQueryTests.cs @@ -1181,6 +1181,58 @@ await this.CreateIngestQueryDeleteAsync( }, "/id", indexV2Policy); + } + + [TestMethod] + public async Task TestBadOrderByQueriesAsync() + { + const string NoCompositeIndex = "The order by query does not have a corresponding composite index that it can be served from."; + const string OrderByOverCorrelatedPath = "Order-by over correlated collections is not supported."; + + static async Task ImplementationAsync( + Container container, + IReadOnlyList documents) + { + IReadOnlyList<(string query, string error)> queries = new List<(string query, string error)> + { + ("SELECT * FROM c ORDER BY c.id, c.name", NoCompositeIndex), + ("SELECT * FROM c ORDER BY c.id DESC, c._ts DESC", NoCompositeIndex), + ( + @"SELECT DISTINCT VALUE v2 + FROM root + JOIN ( + SELECT DISTINCT VALUE v0 + FROM root + JOIN v0 IN root.Parents) AS v2 + WHERE (LENGTH(v2.FamilyName) > 10) + ORDER BY v2 ASC", + OrderByOverCorrelatedPath + ), + }; + + foreach (bool enableOptmisticDirectExecution in new []{ false, true }) + { + QueryRequestOptions options = new QueryRequestOptions() + { + EnableOptimisticDirectExecution = enableOptmisticDirectExecution, + }; + + foreach ((string query, string error) in queries) + { + using FeedIterator feedIterator = container.GetItemQueryStreamIterator(query, continuationToken: null, options); + ResponseMessage response = await feedIterator.ReadNextAsync(); + Assert.AreEqual(System.Net.HttpStatusCode.BadRequest, response.StatusCode); + Assert.IsNotNull(response.CosmosException); + Assert.IsTrue(response.CosmosException.Message.Contains(error)); + } + } + } + + await this.CreateIngestQueryDeleteAsync( + ConnectionModes.Direct | ConnectionModes.Gateway, + CollectionTypes.SinglePartition | CollectionTypes.MultiPartition, + new List(), + ImplementationAsync); } private sealed class MixedTypedDocument From b875c61193be189826b12931051675f34d3b267a Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 16 Apr 2024 14:27:40 -0700 Subject: [PATCH 320/337] [Internal] Security: Fixes Azure.Identity dependency on Microsoft.Azure.Cosmos.Encryption.Custom (#4421) * Bump dependency * Bump Azure.Core --- .../src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index 306cd923a9..b7c5eb3955 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -35,8 +35,8 @@ - - + + From 5efe2db0467e08709b112a2ed7393c59e906fa08 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Tue, 16 Apr 2024 17:14:06 -0700 Subject: [PATCH 321/337] [Internal] Query: Adds tests for LINQ GROUP BY Multi-value translations (#4403) * init * Added tests --------- Co-authored-by: Minh Le (from Dev Box) --- ...Tests.TestGroupByMultiValueTranslation.xml | 284 + .../Linq/LinqGeneralBaselineTests.cs | 5931 +++++++++-------- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 3 + 3 files changed, 3354 insertions(+), 2864 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByMultiValueTranslation.xml diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByMultiValueTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByMultiValueTranslation.xml new file mode 100644 index 0000000000..dfa3dfd6b7 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByMultiValueTranslation.xml @@ -0,0 +1,284 @@ + + + + + k, (key, values) => new AnonymousType(stringField = "abv", numField = 123))]]> + + + + + + + + + k.Id, (key, values) => new AnonymousType(Key = key, key = key))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(KeyAlias = key, values = 123))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(Min = values.Min(value => value.Int), Max = values.Max(value => value.Int), Avg = values.Average(value => value.Int), Count = values.Count()))]]> + + + + + + + + + + k.FamilyId, (key, values) => new AnonymousType(familyId = key, familyIdCount = values.Count()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(Min = values.Min(), Max = values.Max()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(valueSelect = values.Select(value => value.Int), valueOrderBy = values.OrderBy(f => f.FamilyId)))]]> + + + + + + + + + + x.Id).GroupBy(k => k, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + new AnonymousType(Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children)).GroupBy(k => k.Id1, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + x.Children).GroupBy(k => k, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + (x.Id != "a")).GroupBy(k => k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + x.Int).GroupBy(k => k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + x.Id).GroupBy(k => k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + (x.Id != "a")).OrderBy(x => x.Id).GroupBy(k => k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count()))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Select(x => x)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Select(x => x.keyAlias)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Skip(10)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Skip(10).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Where(x => (x.keyAlias == "a"))]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).OrderBy(x => x.keyAlias)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).OrderByDescending(x => x.count)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).Where(x => (x.keyAlias == "a")).Skip(10).Take(10)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).GroupBy(k => k.count, (key, values) => key)]]> + + + + + + + + + + k.Id, (key, values) => new AnonymousType(keyAlias = key, count = values.Count())).GroupBy(k => k.count, (key, values) => new AnonymousType(keyAlias = key, stringField = "abc"))]]> + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs index 21172812f7..3604a1e89b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs @@ -1,2865 +1,3068 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Dynamic; - using System.Runtime.Serialization; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Linq; - using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; - using BaselineTest; - using Microsoft.Azure.Documents; - using Microsoft.Azure.Cosmos.Scripts; - using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; - - [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] - public class LinqGeneralBaselineTests : BaselineTests - { - private static CosmosClient cosmosClient; - private static Cosmos.Database testDb; - private static Container testContainer; - private static Func> getQuery; - - [ClassInitialize] - public async static Task Initialize(TestContext textContext) - { - cosmosClient = TestCommon.CreateCosmosClient(true); - DocumentClientSwitchLinkExtension.Reset("LinqTests"); - - string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; - testDb = await cosmosClient.CreateDatabaseAsync(dbName); - - getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); - } - - [ClassCleanup] - public async static Task CleanUp() - { - if (testDb != null) - { - await testDb.DeleteStreamAsync(); - } - - cosmosClient?.Dispose(); - } - - public class Address - { - public string State; - public string County; - public string City; - } - - public class GuidClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public Guid Id; - } - - public class ListArrayClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public string Id; - - public int[] ArrayField; - public List ListField; - } - - [DataContract] - public class Sport : LinqTestObject - { - [DataMember(Name = "id")] - public string SportName; - - [JsonProperty(PropertyName = "json")] - [DataMember(Name = "data")] - public string SportType; - } - - public class Sport2 : LinqTestObject - { - [DataMember(Name = "data")] - public string id; - } - - [TestMethod] - public void TestSelectMany() - { - List inputs = new List(); - - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children.Where(c => c.Grade > 10) - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Where)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); - - inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); - - inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); - - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); - - inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); - - inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); - - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); - - inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); - - inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); - - inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); - - inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); - - inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestSimpleSubquery() - { - List inputs = new List(); - - inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); - - inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); - - inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); - - inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); - - inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); - - inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); - - inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); - - inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); - - inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestQueryFlattening() - { - // these queries should make more sense when combined with where and orderby - // these tests verify the flattening part - List inputs = new List(); - inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); - inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); - inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); - inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); - inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); - inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); - inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) - .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) - .Select(f => f.Children[0].Pets[0].GivenName))); - - inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); - inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); - inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) - .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) - .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); - inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); - inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestSubquery() - { - List inputs = new List(); - - // -------------------------------------- - // Subquery lambdas - // -------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Take)", b => getQuery(b) - .Select(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "Select(Where)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(Distinct)", b => getQuery(b) - .Select(f => f.Children.Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(Count)", b => getQuery(b) - .Select(f => f.Children.Count(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(Sum)", b => getQuery(b) - .Select(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Count)", b => getQuery(b) - .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); - - inputs.Add(new LinqTestInput( - "Where(Sum)", b => getQuery(b) - .Where(f => f.Children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "OrderBy(Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Count)", b => getQuery(b) - .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); - - // ------------------------------------------------------------- - // Mutilpe-transformations subquery lambdas - // ------------------------------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select -> Distinct -> Count)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Sum)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); - - inputs.Add(new LinqTestInput( - "Select(SelectMany -> Select)", b => getQuery(b) - .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Count)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); - - inputs.Add(new LinqTestInput( - "Select(Where -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select(array) -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(where -> Select -> Distinct)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); - - inputs.Add(new LinqTestInput( - "Where(Select -> Count)", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Sum)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); - - inputs.Add(new LinqTestInput( - "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Where)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Where -> Count)", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); - - // --------------------------------------------------------- - // Scalar and Built-in expressions with subquery lambdas - // --------------------------------------------------------- - - // Unary - - inputs.Add(new LinqTestInput( - "Where(unary (Where -> Count))", b => getQuery(b) - .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); - - // Binary - - inputs.Add(new LinqTestInput( - "Select(binary with Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(constant + Where -> Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); - - inputs.Add(new LinqTestInput( - "Where((Where -> Count) % constant)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); - - // Conditional - - inputs.Add(new LinqTestInput( - "Select(conditional Any ? Select : Select)", b => getQuery(b) - .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); - - inputs.Add(new LinqTestInput( - "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); - - // New array - - inputs.Add(new LinqTestInput( - "Select(new array)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - // New + member init - - inputs.Add(new LinqTestInput( - "Select(new)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - inputs.Add(new LinqTestInput( - "Select(Select new)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Count) -> Where", b => getQuery(b) - .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); - - // Array builtin functions - - inputs.Add(new LinqTestInput( - "Select(Where -> Concat(Where))", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Sum))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Where -> Count))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); - - // Math builtin functions - - inputs.Add(new LinqTestInput( - "Select(Floor(sum(map), sum(map)))", b => getQuery(b) - .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); - - inputs.Add(new LinqTestInput( - "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) - .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); - - inputs.Add(new LinqTestInput( - "OrderBy(Log(Where -> Count))", b => getQuery(b) - .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); - - // ------------------------------------------------------------------ - // Expression with subquery lambdas -> more transformations - // ------------------------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) - .OrderBy(f => f.ChildrenCount) - .Take(10))); - // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 - //inputs.Add(new LinqTestInput( - // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) - // .OrderBy(f => f.FamilyId) - // .Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), - FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null - }) - .Where(f => f.FirstChild != null) - .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); - - inputs.Add(new LinqTestInput( - "Select(new (Select(new (Select, Select))))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenProfile = f.Children.Select(c => new - { - Fullname = c.GivenName + " " + c.FamilyName, - PetNames = c.Pets.Select(p => p.GivenName), - ParentNames = f.Parents.Select(p => p.GivenName) - }) - }))); - - // ------------------------------------------------ - // Subquery lambda -> subquery lamda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(array) -> Where(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum())", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - // ------------------------------ - // Nested subquery lambdas - // ------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); - - inputs.Add(new LinqTestInput( - "Select(Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Where(c => c.Pets - .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") - .Count() > 0) - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select(Select))", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where(Any))", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Where(Count) -> Count)", b => getQuery(b) - .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); - - inputs.Add(new LinqTestInput( - "Where(Where(Where -> Count) -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Select(Select -> Any))", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - // ------------------------------------- - // Expression -> Subquery lambdas - // ------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(new) -> Select(Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 80)) - .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) - .Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) - .Distinct() - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) - .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - inputs.Add(new LinqTestInput( - "Where -> Select(Select)", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(Select)", b => getQuery(b) - .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Take -> Select(Select)", b => getQuery(b) - .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); - - // ------------------ - // Any in lambda - // ------------------ - - inputs.Add(new LinqTestInput( - "Select(Any w const array)", b => getQuery(b) - .Select(f => new int[] { 1, 2, 3 }.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any)", b => getQuery(b) - .Select(f => f.Children.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any w lambda)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(new Any)", b => getQuery(b) - .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(new 2 Any)", b => getQuery(b) - .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(Nested Any)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Any)", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Where(simple expr && Any)", b => getQuery(b) - .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); - - // ------------------------------------------------ - // SelectMany with Take and OrderBy in lambda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany(Take)", b => getQuery(b) - .SelectMany(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(OrderBy)", b => getQuery(b) - .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take -> Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestGroupByTranslation() - { +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Dynamic; + using System.Runtime.Serialization; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Linq; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using BaselineTest; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.Scripts; + using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; + + [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] + public class LinqGeneralBaselineTests : BaselineTests + { + private static CosmosClient cosmosClient; + private static Cosmos.Database testDb; + private static Container testContainer; + private static Func> getQuery; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + cosmosClient = TestCommon.CreateCosmosClient(true); + DocumentClientSwitchLinkExtension.Reset("LinqTests"); + + string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; + testDb = await cosmosClient.CreateDatabaseAsync(dbName); + + getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); + } + + [ClassCleanup] + public async static Task CleanUp() + { + if (testDb != null) + { + await testDb.DeleteStreamAsync(); + } + + cosmosClient?.Dispose(); + } + + public class Address + { + public string State; + public string County; + public string City; + } + + public class GuidClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public Guid Id; + } + + public class ListArrayClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public string Id; + + public int[] ArrayField; + public List ListField; + } + + [DataContract] + public class Sport : LinqTestObject + { + [DataMember(Name = "id")] + public string SportName; + + [JsonProperty(PropertyName = "json")] + [DataMember(Name = "data")] + public string SportType; + } + + public class Sport2 : LinqTestObject + { + [DataMember(Name = "data")] + public string id; + } + + [TestMethod] + public void TestSelectMany() + { List inputs = new List(); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (stringField, values) => stringField /*return the group by key */))); - - - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Count() /*return the Count of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); - - // Negative cases - - // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] - // but the behavior between LINQ and SQL is different - // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Min() /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Max() /*return the Max of each group */))); - - // Unsupported node type - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Incorrect number of arguments - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( - k => k.Int, - k2 => k2.Int, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Non-aggregate method calls - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); - - // Currently unsupported case - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, - (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); - - // Other methods followed by GroupBy - - inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) - .Select(x => x.Id) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) - .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) - .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) - .SelectMany(x => x.Children) - .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => p.GivenName)) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) - .Skip(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) - .Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) - .Skip(10).Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // should this become a subquery with order by then group by? - inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) - .OrderBy(x => x.Int) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) - .OrderByDescending(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .OrderBy(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // The result for this is not correct yet - the select clause is wrong - inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .Where(x => x.Children.Min(y => y.Grade) > 10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // GroupBy followed by other methods - inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Select(x => x))); - - //We should support skip take - inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10))); - - inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a"))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderBy(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderByDescending(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a").Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void DebuggingTest() - { - - } - - [TestMethod] - [Owner("khdang")] - [Ignore] - public void TestSkipTake() - { - //TODO - //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders - //This will be fine once we convert these test cases to use V3 pipeline - - List inputs = new List(); - - // -------------------------------- - // Skip - Take combinations - // -------------------------------- - - inputs.Add(new LinqTestInput( - "Skip", b => getQuery(b) - .Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take", b => getQuery(b) - .Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Skip(negative number) -> Take", b => getQuery(b) - .Skip(-1).Take(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take(negative number)", b => getQuery(b) - .Skip(1).Take(-2))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take", b => getQuery(b) - .Skip(1).Skip(2).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take", b => getQuery(b) - .Skip(3).Take(5).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(2).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take -> Skip", b => getQuery(b) - .Skip(1).Take(2).Take(3).Skip(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take -> Take", b => getQuery(b) - .Skip(5).Skip(2).Take(10).Take(3))); - - inputs.Add(new LinqTestInput( - "Take -> Skip", b => getQuery(b) - .Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip", b => getQuery(b) - .Take(2).Take(3).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip", b => getQuery(b) - .Take(3).Skip(1).Skip(2))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip -> Skip", b => getQuery(b) - .Take(5).Take(3).Skip(1).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Take -> Skip", b => getQuery(b) - .Take(10).Skip(2).Take(5).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(4).Skip(2).Take(2))); - - // -------------------------- - // Select + Skip & Take - // -------------------------- - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Select -> Take -> Skip", b => getQuery(b) - .Select(f => f.FamilyId).Take(2).Skip(1))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> Select", b => getQuery(b) - .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) - .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Select(f => f.FamilyId).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> Select -> Skip", b => getQuery(b) - .Take(7).Select(f => f.FamilyId).Skip(3))); - - // ------------------------------ - // SelectMany + Skip & Take - // ------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Skip(7).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) - .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) - .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) - .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); - - // --------------------------- - // Where + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip", b => getQuery(b) - .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Where -> Skip", b => getQuery(b) - .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); - - inputs.Add(new LinqTestInput( - "Where -> Take -> Skip -> Where", b => getQuery(b) - .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); - - // --------------------------- - // OrderBy + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> OrderBy", b => getQuery(b) - .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "Take -> OrderByDescending -> Skip", b => getQuery(b) - .Take(50).OrderByDescending(f => f.Int).Skip(13))); - - inputs.Add(new LinqTestInput( - "Skip -> OrderByDescending -> Take", b => getQuery(b) - .Skip(7).OrderByDescending(f => f.Int).Take(17))); - - // --------------------------- - // Distinct + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> Take", b => getQuery(b) - .Distinct().Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Distinct", b => getQuery(b) - .Skip(3).Take(11).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) - .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(7).Distinct().Skip(20).Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Distinct -> Skip", b => getQuery(b) - .Take(30).Skip(10).Distinct().Skip(7))); - - // --------------------------------------------------------------------------------- - // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between - // --------------------------------------------------------------------------------- - - // Select, SelectMany - - inputs.Add(new LinqTestInput( - "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); - - // Select, Where - - inputs.Add(new LinqTestInput( - "Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); - - // Select, OrderBy - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> OrderBy", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) - .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); - - // Select, Distinct - - inputs.Add(new LinqTestInput( - "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) - .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); - - // SelectMany, Where - - inputs.Add(new LinqTestInput( - "SelectMany -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> SelectMany -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); - - // SelectMany, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) - .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // SelectMany, Distinct - - inputs.Add(new LinqTestInput( - "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> SelectMany", b => getQuery(b) - .Distinct().Skip(3).SelectMany(f => f.Children))); - - // Where, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Where -> Take -> OrderBy", b => getQuery(b) - .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); - - // Where, Distinct - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Distinct", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Where -> Take", b => getQuery(b) - .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); - - // ----------------------------------------- - // All basic operations with Skip & Take - // ----------------------------------------- - - // Start with Select - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) - .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) - .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); - - inputs.Add(new LinqTestInput( - "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) - .Skip(1).Select(f => f.L1) - .Skip(2).Select(f => f.L2) - .Skip(3).Select(f => f.L3) - .Skip(4).Select(f => f.L4) - .Skip(5).Select(f => f.Records) - .Skip(6).Select(f => f.Transactions) - .Skip(7).Where(t => t.Count() > 100) - .Take(20))); - - inputs.Add(new LinqTestInput( - "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) - .Select(f => new { L1 = f }) - .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) - .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) - .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) - .Skip(4).Take(25))); - - // Start with Distinct - - inputs.Add(new LinqTestInput( - "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); - - // Start with Where - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) - .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 20).Skip(5).Take(20) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); - - // Start with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(1).Take(10) - .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); - - // Start with Skip - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(2).Take(10).Where(f => f.Int > 10) - .Skip(1).Take(9).OrderBy(f => f.FamilyId) - .Skip(3).Take(5).Select(f => f.Children.Count()) - .Skip(1).Distinct() - .Skip(1).Take(1))); - - // Start with Take - - inputs.Add(new LinqTestInput( - "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); - - // ----------------------------------------------------------------------------- - // All basic operations with Skip & Take with SelectMany in the middle - // ----------------------------------------------------------------------------- - - // SelectMany after Take - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => f.Records).Skip(1).Take(10) - .SelectMany(r => r.Transactions).Skip(1).Take(9))); - - // SelectMany after Where - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // Start with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children) - .Select(c => c.FamilyName).Skip(1).Take(20) - .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); - - // ------------------------------------------------------------- - // Nested Skip & Take in Select, SelectMany, Where, OrderBy - // ------------------------------------------------------------- - - // Nested with Select - - inputs.Add(new LinqTestInput( - "Select(new(Where -> Skip)) -> Where", b => getQuery(b) - .Select(f => new { - id = f.FamilyId, - GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) - }) - .Where(f => f.GoodChildren.Count() > 0))); - - inputs.Add(new LinqTestInput( - "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) - .Select(f => new { - v0 = f.Children.Skip(1).Take(2), - v1 = f.Parents.Skip(1), - v2 = f.Records.Transactions.Take(10) - }) - .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { - v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), - v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), - v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() - }) - .Where(f => f.v2 > 100).Skip(5).Take(20) - .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) - .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); - - // Nested with Where - - inputs.Add(new LinqTestInput( - "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); - - // Nested with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); - - // Nested with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) - .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestUnsupportedScenarios() - { - List inputs = new List(); - - // -------------------- - // Dictionary type - // -------------------- - - // Iterating through Dictionary type - inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); - - // Get a count of a Dictionary type - inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestOrderByTranslation() - { - List inputs = new List(); - - // Ascending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy query", - b => from f in getQuery(b) - orderby f.FamilyId - select f)); - inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - - // Descending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f)); - inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - inputs.Add(new LinqTestInput("OrderBy multiple expressions", - b => from f in getQuery(b) - orderby f.FamilyId, f.Int - select f.FamilyId)); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLambdaReuse() - { - List inputs = new List(); - - System.Linq.Expressions.Expression> predicate = f => f.Int == 5; - inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); - inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); - - System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; - inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", - b => getQuery(b) - .Where(predicate2) - .Select(c => new { Int = 10, Result = c }) - .Where(predicate2))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestThenByTranslation() - { - List inputs = new List(); - - // Ascending and descending - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenByDescending", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - // Subquery in OrderBy or in ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - // OrderBy and ThenBy by the same property (not a realistic scenario) - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // OrderBy and ThenBy with epxressions - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Int * 2) - .ThenBy(f => f.FamilyId.Substring(2, 3)))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => !f.NullableInt.IsDefined()) - .ThenByDescending(f => f.Tags.Count() % 2))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) - .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); - - // Multiple OrderBy and ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .OrderBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // Nested ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenBy(c => c.Pets.Count)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // Nested expressions with ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Take(1) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count) - .Take(10) - .OrderByDescending(c => c.GivenName) - .ThenBy(c => c.Gender)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // On a new object - - inputs.Add(new LinqTestInput( - "Select -> OrderBy -> ThenBy", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber)))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - })) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber) - .Select(r => r.FamilyId))); - - inputs.Add(new LinqTestInput( - "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) - .Select(f => new { - ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), - TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) - }) - .OrderByDescending(r => r.ChildrenWithPets.Count()) - .ThenByDescending(r => r.TotalExpenses))); - - inputs.Add(new LinqTestInput( - "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) - .Select(f => new { - ParentGivenName = f.Parents.Min(p => p.GivenName), - ParentCount = f.Parents.Count(), - GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), - UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() - }) - .OrderByDescending(r => r.GoodChildrenCount) - .ThenBy(r => r.UniquePetsNameCount))); - - // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderByDescending(c => c.Grade) - .ThenBy(c => c.GivenName) - .Skip(2) - .Take(20) - .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) - .Select(c => c.GivenName) - .Distinct())); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Select(c => c.GivenName) - .Distinct() - .Take(10) - .Skip(5) - .OrderBy(n => n.Length))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Records.Transactions) - .OrderBy(t => t.Type) - .ThenBy(t => t.Amount) - .Take(100))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int) - .Skip(5))); - - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Distinct() - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children.Select(c => new { - Name = c.GivenName, - PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() - })) - .Distinct() - .OrderByDescending(r => r.Name) - .ThenBy(r => r.PetWithLongNames))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Grade > 90)) - .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) - .OrderBy(f => f.Children.Min(c => c.GivenName)) - .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) - .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) - .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestDistinctSelectManyIssues() - { - List inputs = new List(); - - // these tests need a fix in the ServiceInterop - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Distinct -> Take", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestDistinctTranslation() - { - static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) - { - return new LinqTestInput(description, expr, true); - } - - List inputs = new List(); - - // Simple distinct - // Select -> Distinct for all data types - inputs.Add(DistinctTestInput( - "Distinct string", - b => getQuery(b).Select(f => f.FamilyId).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct int", - b => getQuery(b).Select(f => f.Int).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct bool", - b => getQuery(b).Select(f => f.IsRegistered).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct nullable int", - b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct null", - b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct children", - b => getQuery(b).SelectMany(f => f.Children).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct parent", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct family", - b => getQuery(b).Distinct())); - - inputs.Add(DistinctTestInput( - "Multiple distincts", - b => getQuery(b).Distinct().Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); - - // Distinct + Take - inputs.Add(DistinctTestInput( - "Distinct -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct", - b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); - - // Distinct + Order By - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); - - inputs.Add(DistinctTestInput( - "OrderBy -> Distinct", - b => getQuery(b).OrderBy(f => f.Int).Distinct())); - - // Distinct + Order By + Take - inputs.Add(new LinqTestInput( - "Distinct -> Take -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Take -> Distinct", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); - - // Distinct + Where - inputs.Add(DistinctTestInput( - "Where -> Distinct", - b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct -> Where", - b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); - - // SelectMany w Distinct - inputs.Add(DistinctTestInput( - "SelectMany(Select obj) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select)) -> Distinct", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet) - .Distinct())))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet.GivenName) - .Select(name => name.Count()))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }).Select(p => p.child)) - .Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }) - .Distinct())))); - - // SelectMany(Distinct) - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); - - // SelectMany(Select -> Distinct) - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicLinq() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); - inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); - inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); - // with parameters - inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); - inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public async Task ValidateLinqQueries() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); - - Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; - Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; - Pet pet = new Pet { GivenName = "Fluffy" }; - Child child = new Child - { - FamilyName = "Merriam", - GivenName = "Jesse", - Gender = "female", - Grade = 1, - Pets = new List() { pet, new Pet() { GivenName = "koko" } }, - Things = new Dictionary() { { "A", "B" }, { "C", "D" } } - }; - - Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; - Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; - - List fList = new List(); - fList.Add(family); - - container.CreateItemAsync(family).Wait(); - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); - Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); - - IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); - Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); - - IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); - Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); - - IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); - Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); - - for (int index = 0; index < 2; index++) - { - IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); - Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); - } - - IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); - Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); - - string nullString = null; - IEnumerable q7 = query.Where(f => nullString == f.FamilyId); - Assert.IsNull(q7.FirstOrDefault()); - - object nullObject = null; - q7 = query.Where(f => f.NullObject == nullObject); - Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); - - q7 = query.Where(f => f.FamilyId == nullString); - Assert.IsNull(q7.FirstOrDefault()); - - IEnumerable q8 = query.Where(f => null == f.FamilyId); - Assert.IsNull(q8.FirstOrDefault()); - - IEnumerable q9 = query.Where(f => f.IsRegistered == false); - Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); - - dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); - Assert.AreEqual(q10.FamilyId, family.FamilyId); - - GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; - container.CreateItemAsync(guidObject).Wait(); - List guidData = new List() { guidObject }; - - IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); - Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); - - IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); - Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); - - ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; - container.CreateItemAsync(arrayObject).Wait(); - - IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); - Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); - - int[] nullArray = null; - q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); - Assert.IsNull(q13.FirstOrDefault()); - - ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; - container.CreateItemAsync(listObject).Wait(); - List listArrayObjectData = new List() { arrayObject, listObject }; - - IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); - Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); - - IEnumerable q15 = query.Where(f => f.NullableInt == null); - Assert.AreEqual(q15.ToList().Count, 0); - - int? nullInt = null; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - q15 = query.Where(f => f.NullableInt == 5); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 5; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.NullableInt == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 3; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.Int == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = null; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - List v = fList.Where(f => f.Int > nullInt).ToList(); - - q15 = query.Where(f => f.Int < nullInt); - - string doc1Id = "document1:x:'!@TT){}\""; - Document doubleQoutesDocument = new Document() { Id = doc1Id }; - container.CreateItemAsync(doubleQoutesDocument).Wait(); - - IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - where book.Id == doc1Id - select book; - - Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); - - GreatFamily greatFamily = new GreatFamily() { Family = family }; - GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; - container.CreateItemAsync(greatGreatFamily).Wait(); - List greatGreatFamilyData = new List() { greatGreatFamily }; - - IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); - - Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); - - Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; - container.CreateItemAsync(sport).Wait(); - List sportData = new List() { sport }; - - IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); - - Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); - - Sport2 sport2 = new Sport2() { id = "json" }; - container.CreateItemAsync(sport2).Wait(); - List sport2Data = new List() { sport2 }; - - IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); - Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); - Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); - Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); - Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); - - int? nullIntVal = null; - int? nullableIntVal = 5; - - List inputs = new List(); - inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); - inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); - inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); - inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); - inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); - inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); - inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); - inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); - inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); - inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); - inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); - inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); - inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); - - inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); - inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); - inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); - inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); - inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); - - inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); - inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); - inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); - inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); - this.ExecuteTestSuite(inputs); - } - - internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, - DocumentCollection collection, - string transientProcedure, - out StoredProcedureResponse response) - { - // create - StoredProcedure storedProcedure = new StoredProcedure - { - Id = "storedProcedure" + Guid.NewGuid().ToString(), - Body = transientProcedure - }; - StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; - - // execute - response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; - - // delete - client.Delete(retrievedStoredProcedure.GetIdOrFullName()); - - return response.Response; - } - - [TestMethod] - public void ValidateBasicQuery() - { - this.ValidateBasicQueryAsync().Wait(); - } - - private async Task ValidateBasicQueryAsync() - { - DocumentClient client = TestCommon.CreateClient(true); - Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - - string databaseName = database.Id; - - List queryResults = new List(); - //Simple Equality - IQueryable dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db; - IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); - Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); - queryResults.AddRange(pagedResponse); - } - - Assert.AreEqual(1, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Logical Or - dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName || db.ResourceId == database.ResourceId - select db; - documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - queryResults.AddRange(await documentQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(2, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Select Property - IQueryable idQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db.ResourceId; - IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); - - List idResults = new List(); - while (documentIdQuery.HasMoreResults) - { - idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(1, idResults.Count); - Assert.AreEqual(database.ResourceId, idResults[0]); - } - - [TestMethod] - public async Task ValidateTransformQuery() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; - DocumentCollection collection = new DocumentCollection - { - Id = Guid.NewGuid().ToString("N"), - PartitionKey = partitionKeyDefinition - }; - collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; - Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); - int documentsToCreate = 100; - for (int i = 0; i < documentsToCreate; i++) - { - dynamic myDocument = new Document(); - myDocument.Id = "doc" + i; - myDocument.Title = "MyBook"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); - } - - //Read response as dynamic. - IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); - - IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); - DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); - - Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); - Assert.AreEqual(documentsToCreate, queryResponse.Count); - - foreach (dynamic myBook in queryResponse) - { - Assert.AreEqual(myBook.Title.ToString(), "MyBook"); - } - - cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); - } - - [TestMethod] - public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. - { - Book myDocument = new Book(); - myDocument.Id = Guid.NewGuid().ToString(); - myDocument.Title = "My Book"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; - - //Create second document to make sure we have atleast one document which are filtered out of query. - Book secondDocument = new Book - { - Id = Guid.NewGuid().ToString(), - Title = "My Second Book", - Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, - Author = new Author { Name = "Carlos", Location = "Cancun" }, - Price = 25, - Editions = new List() { new Edition() { Name = "First", Year = 1970 } } - }; - - //Unfiltered execution. - IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Simple Equality on custom property", - b => from book in getBookQuery(b) - where book.Title == "My Book" - select book)); - inputs.Add(new LinqTestInput("Nested Property access", - b => from book in getBookQuery(b) - where book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("Array references & Project Author out..", - b => from book in getBookQuery(b) - where book.Languages[0].Name == "English" - select book.Author)); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); - inputs.Add(new LinqTestInput("NumericRange query", - b => from book in getBookQuery(b) - where book.Price < 10 - select book.Author)); - inputs.Add(new LinqTestInput("Or query", - b => from book in getBookQuery(b) - where book.Title == "My Book" || book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("SelectMany query on a List type.", - b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); - // Below samples are strictly speaking not Any equivalent. But they join and filter "all" - // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Languages - .Where(lng => lng.Name == "English") - .Select(lng => book.Author)))); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Editions - .Where(edition => edition.Year == 2001) - .Select(lng => book.Author)))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. - { - IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Document myDocument = new Document(); - Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Filter equality on custom property", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title2" - select attachment)); - inputs.Add(new LinqTestInput("Filter equality on custom property #2", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title" - select attachment)); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLinqTypeSystem() - { - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); - - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); - Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); - - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - } - - #region DataDocument type tests - - public class BaseDocument - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public string TypeName { get; set; } - } - - public class DataDocument : BaseDocument - { - public int Number { get; set; } - } - - private class QueryHelper - { - private readonly Container container; - - public QueryHelper(Container container) - { - this.container = container; - } - - public IQueryable Query() where T : BaseDocument - { - IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - .Where(d => d.TypeName == "Hello"); - string queryString = query.ToString(); - return query; - } - } - - [TestMethod] - public async Task ValidateLinqOnDataDocumentType() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); - - DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; - container.CreateItemAsync(doc).Wait(); - - QueryHelper queryHelper = new QueryHelper(container); - IEnumerable result = queryHelper.Query(); - Assert.AreEqual(1, result.Count()); - - BaseDocument baseDocument = result.FirstOrDefault(); - Assert.AreEqual(doc.Id, baseDocument.Id); - - BaseDocument iDocument = doc; - IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable iresult = from f in q - where f.Id == iDocument.Id - select f; - DataDocument id = iresult.FirstOrDefault(); - Assert.AreEqual(doc.Id, id.Id); - } - - #endregion - - #region Book type tests - public class Author - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - public string Location { get; set; } - } - - public class Language - { - public string Name { get; set; } - public string Copyright { get; set; } - } - - public class Edition - { - public string Name { get; set; } - public int Year { get; set; } - } - - public class Book - { - //Verify that we can override the propertyName but still can query them using .NET Property names. - [JsonProperty(PropertyName = "title")] - public string Title { get; set; } - [JsonProperty(PropertyName = "name")] - public string Name { get; set; } - public Language[] Languages { get; set; } - public Author Author { get; set; } - public double Price { get; set; } - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public List Editions { get; set; } - } - - [TestMethod] - public async Task ValidateServerSideQueryEvalWithPagination() - { - await this.ValidateServerSideQueryEvalWithPaginationScenario(); - } - - private async Task ValidateServerSideQueryEvalWithPaginationScenario() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; - ContainerProperties cosmosContainerSettings = new ContainerProperties - { - Id = Guid.NewGuid().ToString(), - PartitionKey = partitionKeyDefinition, - }; - cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; - - Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); - - //Do script post to insert as many document as we could in a tight loop. - string script = @"function() { - var output = 0; - var client = getContext().getCollection(); - function callback(err, docCreated) { - if(err) throw 'Error while creating document'; - output++; - getContext().getResponse().setBody(output); - if(output < 50) - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); - }; - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; - - StoredProcedureExecuteResponse scriptResponse = null; - int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); - - IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); - Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); - - } - - #endregion - - public class SpecialAttachment2 //Non attachemnt derived. - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - - [JsonProperty(PropertyName = "contentType")] - public string ContentType { get; set; } - - [JsonProperty(PropertyName = Constants.Properties.MediaLink)] - public string Media { get; set; } - - public string Author { get; set; } - public string Title { get; set; } - } - - #region TypeSystem test reference classes - public interface IFooItem { } - - public class FooItem : IFooItem { } - - public class DerivedFooItem : FooItem { } - - public class MyList : List { } - - public class MyTupleList : List> { } - - public class DerivedFooCollection : IList, IEnumerable - { - public int IndexOf(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, IFooItem item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public IFooItem this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(IFooItem item) - { - throw new NotImplementedException(); - } - - public void CopyTo(IFooItem[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(IFooItem item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooStringCollection : IList, IEnumerable - { - public int IndexOf(string item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, string item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public string this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(string item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(string item) - { - throw new NotImplementedException(); - } - - public void CopyTo(string[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(string item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooTCollection : List, IEnumerable - { - public new IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - } - #endregion - - public override LinqTestOutput ExecuteTest(LinqTestInput input) - { - return LinqTestsCommon.ExecuteTest(input); - } - } -} + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children.Where(c => c.Grade > 10) + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Where)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); + + inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSimpleSubquery() + { + List inputs = new List(); + + inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); + + inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); + + inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); + + inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestQueryFlattening() + { + // these queries should make more sense when combined with where and orderby + // these tests verify the flattening part + List inputs = new List(); + inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); + inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); + inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); + inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); + inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); + inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); + inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) + .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) + .Select(f => f.Children[0].Pets[0].GivenName))); + + inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); + inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); + inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) + .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) + .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); + inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); + inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSubquery() + { + List inputs = new List(); + + // -------------------------------------- + // Subquery lambdas + // -------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Take)", b => getQuery(b) + .Select(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "Select(Where)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(Distinct)", b => getQuery(b) + .Select(f => f.Children.Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(Count)", b => getQuery(b) + .Select(f => f.Children.Count(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(Sum)", b => getQuery(b) + .Select(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Count)", b => getQuery(b) + .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); + + inputs.Add(new LinqTestInput( + "Where(Sum)", b => getQuery(b) + .Where(f => f.Children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "OrderBy(Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Count)", b => getQuery(b) + .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); + + // ------------------------------------------------------------- + // Mutilpe-transformations subquery lambdas + // ------------------------------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select -> Distinct -> Count)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Sum)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); + + inputs.Add(new LinqTestInput( + "Select(SelectMany -> Select)", b => getQuery(b) + .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Count)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); + + inputs.Add(new LinqTestInput( + "Select(Where -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select(array) -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(where -> Select -> Distinct)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); + + inputs.Add(new LinqTestInput( + "Where(Select -> Count)", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Sum)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); + + inputs.Add(new LinqTestInput( + "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Where)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Where -> Count)", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); + + // --------------------------------------------------------- + // Scalar and Built-in expressions with subquery lambdas + // --------------------------------------------------------- + + // Unary + + inputs.Add(new LinqTestInput( + "Where(unary (Where -> Count))", b => getQuery(b) + .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); + + // Binary + + inputs.Add(new LinqTestInput( + "Select(binary with Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(constant + Where -> Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); + + inputs.Add(new LinqTestInput( + "Where((Where -> Count) % constant)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); + + // Conditional + + inputs.Add(new LinqTestInput( + "Select(conditional Any ? Select : Select)", b => getQuery(b) + .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput( + "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); + + // New array + + inputs.Add(new LinqTestInput( + "Select(new array)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + // New + member init + + inputs.Add(new LinqTestInput( + "Select(new)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + inputs.Add(new LinqTestInput( + "Select(Select new)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Count) -> Where", b => getQuery(b) + .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); + + // Array builtin functions + + inputs.Add(new LinqTestInput( + "Select(Where -> Concat(Where))", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Sum))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Where -> Count))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); + + // Math builtin functions + + inputs.Add(new LinqTestInput( + "Select(Floor(sum(map), sum(map)))", b => getQuery(b) + .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); + + inputs.Add(new LinqTestInput( + "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) + .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); + + inputs.Add(new LinqTestInput( + "OrderBy(Log(Where -> Count))", b => getQuery(b) + .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); + + // ------------------------------------------------------------------ + // Expression with subquery lambdas -> more transformations + // ------------------------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) + .OrderBy(f => f.ChildrenCount) + .Take(10))); + // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 + //inputs.Add(new LinqTestInput( + // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) + // .OrderBy(f => f.FamilyId) + // .Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), + FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null + }) + .Where(f => f.FirstChild != null) + .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); + + inputs.Add(new LinqTestInput( + "Select(new (Select(new (Select, Select))))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenProfile = f.Children.Select(c => new + { + Fullname = c.GivenName + " " + c.FamilyName, + PetNames = c.Pets.Select(p => p.GivenName), + ParentNames = f.Parents.Select(p => p.GivenName) + }) + }))); + + // ------------------------------------------------ + // Subquery lambda -> subquery lamda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(array) -> Where(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum())", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + // ------------------------------ + // Nested subquery lambdas + // ------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); + + inputs.Add(new LinqTestInput( + "Select(Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Where(c => c.Pets + .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") + .Count() > 0) + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select(Select))", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where(Any))", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Where(Count) -> Count)", b => getQuery(b) + .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); + + inputs.Add(new LinqTestInput( + "Where(Where(Where -> Count) -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Select(Select -> Any))", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + // ------------------------------------- + // Expression -> Subquery lambdas + // ------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(new) -> Select(Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 80)) + .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) + .Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) + .Distinct() + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) + .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + inputs.Add(new LinqTestInput( + "Where -> Select(Select)", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(Select)", b => getQuery(b) + .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Take -> Select(Select)", b => getQuery(b) + .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); + + // ------------------ + // Any in lambda + // ------------------ + + inputs.Add(new LinqTestInput( + "Select(Any w const array)", b => getQuery(b) + .Select(f => new int[] { 1, 2, 3 }.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any)", b => getQuery(b) + .Select(f => f.Children.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any w lambda)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(new Any)", b => getQuery(b) + .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(new 2 Any)", b => getQuery(b) + .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(Nested Any)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Any)", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Where(simple expr && Any)", b => getQuery(b) + .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); + + // ------------------------------------------------ + // SelectMany with Take and OrderBy in lambda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany(Take)", b => getQuery(b) + .SelectMany(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(OrderBy)", b => getQuery(b) + .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take -> Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByTranslation() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (stringField, values) => stringField /*return the group by key */))); + + + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Count() /*return the Count of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); + + // Negative cases + + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Min() /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Max() /*return the Max of each group */))); + + // Unsupported node type + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Incorrect number of arguments + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( + k => k.Int, + k2 => k2.Int, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); + + // Currently unsupported case + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); + + // Other methods followed by GroupBy + + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => p.GivenName)) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // The result for this is not correct yet - the select clause is wrong + inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .Where(x => x.Children.Min(y => y.Grade) > 10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Select(x => x))); + + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10))); + + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a"))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderBy(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderByDescending(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a").Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByMultiValueTranslation() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Constant", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => + new { + stringField = "abv", + numField = 123 + }))); + + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Key = key, + key + }))); + + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key and Constant", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + KeyAlias = key, + values = 123 /* intentionally have the same spelling as the IGrouping values */ + }))); + + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(value => value.Int), + Max = values.Max(value => value.Int), + Avg = values.Average(value => value.Int), + Count = values.Count() + }))); + + inputs.Add(new LinqTestInput("GroupBy Multi Value With Property Ref and Aggregate", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { + familyId = key, + familyIdCount = values.Count() + }))); + + // Negative cases + + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate On Root", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(), + Max = values.Max() + }))); + + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Multi Value With Non-Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + valueSelect = values.Select(value => value.Int), + valueOrderBy = values.OrderBy(f => f.FamilyId) + }))); + // Other methods followed by GroupBy + + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.Id1 /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); + + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + Select 2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x.keyAlias))); + + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10))); + + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a"))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderBy(x => x.keyAlias))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderByDescending(x => x.count))); + + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a").Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .GroupBy(k => k.count /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }) + .GroupBy(k => k.count /*keySelector*/, (key, values) => new { + keyAlias = key, + stringField = "abc" + }))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void DebuggingTest() + { + + } + + [TestMethod] + [Owner("khdang")] + [Ignore] + public void TestSkipTake() + { + //TODO + //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders + //This will be fine once we convert these test cases to use V3 pipeline + + List inputs = new List(); + + // -------------------------------- + // Skip - Take combinations + // -------------------------------- + + inputs.Add(new LinqTestInput( + "Skip", b => getQuery(b) + .Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take", b => getQuery(b) + .Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Skip(negative number) -> Take", b => getQuery(b) + .Skip(-1).Take(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take(negative number)", b => getQuery(b) + .Skip(1).Take(-2))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take", b => getQuery(b) + .Skip(1).Skip(2).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take", b => getQuery(b) + .Skip(3).Take(5).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(2).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take -> Skip", b => getQuery(b) + .Skip(1).Take(2).Take(3).Skip(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take -> Take", b => getQuery(b) + .Skip(5).Skip(2).Take(10).Take(3))); + + inputs.Add(new LinqTestInput( + "Take -> Skip", b => getQuery(b) + .Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip", b => getQuery(b) + .Take(2).Take(3).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip", b => getQuery(b) + .Take(3).Skip(1).Skip(2))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip -> Skip", b => getQuery(b) + .Take(5).Take(3).Skip(1).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Take -> Skip", b => getQuery(b) + .Take(10).Skip(2).Take(5).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(4).Skip(2).Take(2))); + + // -------------------------- + // Select + Skip & Take + // -------------------------- + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Select -> Take -> Skip", b => getQuery(b) + .Select(f => f.FamilyId).Take(2).Skip(1))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> Select", b => getQuery(b) + .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) + .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Select(f => f.FamilyId).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> Select -> Skip", b => getQuery(b) + .Take(7).Select(f => f.FamilyId).Skip(3))); + + // ------------------------------ + // SelectMany + Skip & Take + // ------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Skip(7).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) + .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) + .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) + .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); + + // --------------------------- + // Where + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip", b => getQuery(b) + .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Where -> Skip", b => getQuery(b) + .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); + + inputs.Add(new LinqTestInput( + "Where -> Take -> Skip -> Where", b => getQuery(b) + .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); + + // --------------------------- + // OrderBy + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> OrderBy", b => getQuery(b) + .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "Take -> OrderByDescending -> Skip", b => getQuery(b) + .Take(50).OrderByDescending(f => f.Int).Skip(13))); + + inputs.Add(new LinqTestInput( + "Skip -> OrderByDescending -> Take", b => getQuery(b) + .Skip(7).OrderByDescending(f => f.Int).Take(17))); + + // --------------------------- + // Distinct + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> Take", b => getQuery(b) + .Distinct().Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Distinct", b => getQuery(b) + .Skip(3).Take(11).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) + .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(7).Distinct().Skip(20).Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Distinct -> Skip", b => getQuery(b) + .Take(30).Skip(10).Distinct().Skip(7))); + + // --------------------------------------------------------------------------------- + // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between + // --------------------------------------------------------------------------------- + + // Select, SelectMany + + inputs.Add(new LinqTestInput( + "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); + + // Select, Where + + inputs.Add(new LinqTestInput( + "Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); + + // Select, OrderBy + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> OrderBy", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) + .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); + + // Select, Distinct + + inputs.Add(new LinqTestInput( + "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) + .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); + + // SelectMany, Where + + inputs.Add(new LinqTestInput( + "SelectMany -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> SelectMany -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); + + // SelectMany, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) + .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // SelectMany, Distinct + + inputs.Add(new LinqTestInput( + "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> SelectMany", b => getQuery(b) + .Distinct().Skip(3).SelectMany(f => f.Children))); + + // Where, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Where -> Take -> OrderBy", b => getQuery(b) + .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); + + // Where, Distinct + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Distinct", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Where -> Take", b => getQuery(b) + .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); + + // ----------------------------------------- + // All basic operations with Skip & Take + // ----------------------------------------- + + // Start with Select + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) + .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) + .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); + + inputs.Add(new LinqTestInput( + "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) + .Skip(1).Select(f => f.L1) + .Skip(2).Select(f => f.L2) + .Skip(3).Select(f => f.L3) + .Skip(4).Select(f => f.L4) + .Skip(5).Select(f => f.Records) + .Skip(6).Select(f => f.Transactions) + .Skip(7).Where(t => t.Count() > 100) + .Take(20))); + + inputs.Add(new LinqTestInput( + "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) + .Select(f => new { L1 = f }) + .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) + .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) + .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) + .Skip(4).Take(25))); + + // Start with Distinct + + inputs.Add(new LinqTestInput( + "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); + + // Start with Where + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) + .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 20).Skip(5).Take(20) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); + + // Start with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(1).Take(10) + .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); + + // Start with Skip + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(2).Take(10).Where(f => f.Int > 10) + .Skip(1).Take(9).OrderBy(f => f.FamilyId) + .Skip(3).Take(5).Select(f => f.Children.Count()) + .Skip(1).Distinct() + .Skip(1).Take(1))); + + // Start with Take + + inputs.Add(new LinqTestInput( + "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); + + // ----------------------------------------------------------------------------- + // All basic operations with Skip & Take with SelectMany in the middle + // ----------------------------------------------------------------------------- + + // SelectMany after Take + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => f.Records).Skip(1).Take(10) + .SelectMany(r => r.Transactions).Skip(1).Take(9))); + + // SelectMany after Where + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // Start with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children) + .Select(c => c.FamilyName).Skip(1).Take(20) + .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); + + // ------------------------------------------------------------- + // Nested Skip & Take in Select, SelectMany, Where, OrderBy + // ------------------------------------------------------------- + + // Nested with Select + + inputs.Add(new LinqTestInput( + "Select(new(Where -> Skip)) -> Where", b => getQuery(b) + .Select(f => new { + id = f.FamilyId, + GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) + }) + .Where(f => f.GoodChildren.Count() > 0))); + + inputs.Add(new LinqTestInput( + "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) + .Select(f => new { + v0 = f.Children.Skip(1).Take(2), + v1 = f.Parents.Skip(1), + v2 = f.Records.Transactions.Take(10) + }) + .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { + v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), + v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), + v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() + }) + .Where(f => f.v2 > 100).Skip(5).Take(20) + .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) + .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); + + // Nested with Where + + inputs.Add(new LinqTestInput( + "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); + + // Nested with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); + + // Nested with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) + .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestUnsupportedScenarios() + { + List inputs = new List(); + + // -------------------- + // Dictionary type + // -------------------- + + // Iterating through Dictionary type + inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); + + // Get a count of a Dictionary type + inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestOrderByTranslation() + { + List inputs = new List(); + + // Ascending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy query", + b => from f in getQuery(b) + orderby f.FamilyId + select f)); + inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + + // Descending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f)); + inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + inputs.Add(new LinqTestInput("OrderBy multiple expressions", + b => from f in getQuery(b) + orderby f.FamilyId, f.Int + select f.FamilyId)); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLambdaReuse() + { + List inputs = new List(); + + System.Linq.Expressions.Expression> predicate = f => f.Int == 5; + inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); + inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); + + System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; + inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", + b => getQuery(b) + .Where(predicate2) + .Select(c => new { Int = 10, Result = c }) + .Where(predicate2))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestThenByTranslation() + { + List inputs = new List(); + + // Ascending and descending + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenByDescending", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + // Subquery in OrderBy or in ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + // OrderBy and ThenBy by the same property (not a realistic scenario) + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // OrderBy and ThenBy with epxressions + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Int * 2) + .ThenBy(f => f.FamilyId.Substring(2, 3)))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => !f.NullableInt.IsDefined()) + .ThenByDescending(f => f.Tags.Count() % 2))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) + .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); + + // Multiple OrderBy and ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .OrderBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // Nested ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenBy(c => c.Pets.Count)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // Nested expressions with ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Take(1) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count) + .Take(10) + .OrderByDescending(c => c.GivenName) + .ThenBy(c => c.Gender)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // On a new object + + inputs.Add(new LinqTestInput( + "Select -> OrderBy -> ThenBy", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber)))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + })) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber) + .Select(r => r.FamilyId))); + + inputs.Add(new LinqTestInput( + "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) + .Select(f => new { + ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), + TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) + }) + .OrderByDescending(r => r.ChildrenWithPets.Count()) + .ThenByDescending(r => r.TotalExpenses))); + + inputs.Add(new LinqTestInput( + "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) + .Select(f => new { + ParentGivenName = f.Parents.Min(p => p.GivenName), + ParentCount = f.Parents.Count(), + GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), + UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() + }) + .OrderByDescending(r => r.GoodChildrenCount) + .ThenBy(r => r.UniquePetsNameCount))); + + // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderByDescending(c => c.Grade) + .ThenBy(c => c.GivenName) + .Skip(2) + .Take(20) + .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) + .Select(c => c.GivenName) + .Distinct())); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Select(c => c.GivenName) + .Distinct() + .Take(10) + .Skip(5) + .OrderBy(n => n.Length))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Records.Transactions) + .OrderBy(t => t.Type) + .ThenBy(t => t.Amount) + .Take(100))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int) + .Skip(5))); + + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Distinct() + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children.Select(c => new { + Name = c.GivenName, + PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() + })) + .Distinct() + .OrderByDescending(r => r.Name) + .ThenBy(r => r.PetWithLongNames))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Grade > 90)) + .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) + .OrderBy(f => f.Children.Min(c => c.GivenName)) + .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) + .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) + .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestDistinctSelectManyIssues() + { + List inputs = new List(); + + // these tests need a fix in the ServiceInterop + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Distinct -> Take", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestDistinctTranslation() + { + static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) + { + return new LinqTestInput(description, expr, true); + } + + List inputs = new List(); + + // Simple distinct + // Select -> Distinct for all data types + inputs.Add(DistinctTestInput( + "Distinct string", + b => getQuery(b).Select(f => f.FamilyId).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct int", + b => getQuery(b).Select(f => f.Int).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct bool", + b => getQuery(b).Select(f => f.IsRegistered).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct nullable int", + b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct null", + b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct children", + b => getQuery(b).SelectMany(f => f.Children).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct parent", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct family", + b => getQuery(b).Distinct())); + + inputs.Add(DistinctTestInput( + "Multiple distincts", + b => getQuery(b).Distinct().Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); + + // Distinct + Take + inputs.Add(DistinctTestInput( + "Distinct -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct", + b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); + + // Distinct + Order By + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); + + inputs.Add(DistinctTestInput( + "OrderBy -> Distinct", + b => getQuery(b).OrderBy(f => f.Int).Distinct())); + + // Distinct + Order By + Take + inputs.Add(new LinqTestInput( + "Distinct -> Take -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Take -> Distinct", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); + + // Distinct + Where + inputs.Add(DistinctTestInput( + "Where -> Distinct", + b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct -> Where", + b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); + + // SelectMany w Distinct + inputs.Add(DistinctTestInput( + "SelectMany(Select obj) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select)) -> Distinct", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet) + .Distinct())))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet.GivenName) + .Select(name => name.Count()))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }).Select(p => p.child)) + .Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }) + .Distinct())))); + + // SelectMany(Distinct) + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); + + // SelectMany(Select -> Distinct) + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicLinq() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); + inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); + inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); + // with parameters + inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); + inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public async Task ValidateLinqQueries() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); + + Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; + Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; + Pet pet = new Pet { GivenName = "Fluffy" }; + Child child = new Child + { + FamilyName = "Merriam", + GivenName = "Jesse", + Gender = "female", + Grade = 1, + Pets = new List() { pet, new Pet() { GivenName = "koko" } }, + Things = new Dictionary() { { "A", "B" }, { "C", "D" } } + }; + + Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; + Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; + + List fList = new List(); + fList.Add(family); + + container.CreateItemAsync(family).Wait(); + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); + Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); + + IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); + Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); + + IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); + Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); + + IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); + Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); + + for (int index = 0; index < 2; index++) + { + IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); + Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); + } + + IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); + Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); + + string nullString = null; + IEnumerable q7 = query.Where(f => nullString == f.FamilyId); + Assert.IsNull(q7.FirstOrDefault()); + + object nullObject = null; + q7 = query.Where(f => f.NullObject == nullObject); + Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); + + q7 = query.Where(f => f.FamilyId == nullString); + Assert.IsNull(q7.FirstOrDefault()); + + IEnumerable q8 = query.Where(f => null == f.FamilyId); + Assert.IsNull(q8.FirstOrDefault()); + + IEnumerable q9 = query.Where(f => f.IsRegistered == false); + Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); + + dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); + Assert.AreEqual(q10.FamilyId, family.FamilyId); + + GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; + container.CreateItemAsync(guidObject).Wait(); + List guidData = new List() { guidObject }; + + IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); + Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); + + IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); + Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); + + ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; + container.CreateItemAsync(arrayObject).Wait(); + + IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); + Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); + + int[] nullArray = null; + q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); + Assert.IsNull(q13.FirstOrDefault()); + + ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; + container.CreateItemAsync(listObject).Wait(); + List listArrayObjectData = new List() { arrayObject, listObject }; + + IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); + Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); + + IEnumerable q15 = query.Where(f => f.NullableInt == null); + Assert.AreEqual(q15.ToList().Count, 0); + + int? nullInt = null; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + q15 = query.Where(f => f.NullableInt == 5); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 5; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.NullableInt == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 3; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.Int == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = null; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + List v = fList.Where(f => f.Int > nullInt).ToList(); + + q15 = query.Where(f => f.Int < nullInt); + + string doc1Id = "document1:x:'!@TT){}\""; + Document doubleQoutesDocument = new Document() { Id = doc1Id }; + container.CreateItemAsync(doubleQoutesDocument).Wait(); + + IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + where book.Id == doc1Id + select book; + + Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); + + GreatFamily greatFamily = new GreatFamily() { Family = family }; + GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; + container.CreateItemAsync(greatGreatFamily).Wait(); + List greatGreatFamilyData = new List() { greatGreatFamily }; + + IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); + + Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); + + Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; + container.CreateItemAsync(sport).Wait(); + List sportData = new List() { sport }; + + IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); + + Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); + + Sport2 sport2 = new Sport2() { id = "json" }; + container.CreateItemAsync(sport2).Wait(); + List sport2Data = new List() { sport2 }; + + IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); + Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); + Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); + Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); + Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); + + int? nullIntVal = null; + int? nullableIntVal = 5; + + List inputs = new List(); + inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); + inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); + inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); + inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); + inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); + inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); + inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); + inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); + inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); + inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); + inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); + inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); + inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); + + inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); + inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); + inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); + inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); + inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); + + inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); + inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); + inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); + inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); + this.ExecuteTestSuite(inputs); + } + + internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, + DocumentCollection collection, + string transientProcedure, + out StoredProcedureResponse response) + { + // create + StoredProcedure storedProcedure = new StoredProcedure + { + Id = "storedProcedure" + Guid.NewGuid().ToString(), + Body = transientProcedure + }; + StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; + + // execute + response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; + + // delete + client.Delete(retrievedStoredProcedure.GetIdOrFullName()); + + return response.Response; + } + + [TestMethod] + public void ValidateBasicQuery() + { + this.ValidateBasicQueryAsync().Wait(); + } + + private async Task ValidateBasicQueryAsync() + { + DocumentClient client = TestCommon.CreateClient(true); + Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + + string databaseName = database.Id; + + List queryResults = new List(); + //Simple Equality + IQueryable dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db; + IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); + Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); + queryResults.AddRange(pagedResponse); + } + + Assert.AreEqual(1, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Logical Or + dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName || db.ResourceId == database.ResourceId + select db; + documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + queryResults.AddRange(await documentQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(2, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Select Property + IQueryable idQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db.ResourceId; + IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); + + List idResults = new List(); + while (documentIdQuery.HasMoreResults) + { + idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(1, idResults.Count); + Assert.AreEqual(database.ResourceId, idResults[0]); + } + + [TestMethod] + public async Task ValidateTransformQuery() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; + DocumentCollection collection = new DocumentCollection + { + Id = Guid.NewGuid().ToString("N"), + PartitionKey = partitionKeyDefinition + }; + collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; + Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); + int documentsToCreate = 100; + for (int i = 0; i < documentsToCreate; i++) + { + dynamic myDocument = new Document(); + myDocument.Id = "doc" + i; + myDocument.Title = "MyBook"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); + } + + //Read response as dynamic. + IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); + + IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); + DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); + + Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); + Assert.AreEqual(documentsToCreate, queryResponse.Count); + + foreach (dynamic myBook in queryResponse) + { + Assert.AreEqual(myBook.Title.ToString(), "MyBook"); + } + + cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); + } + + [TestMethod] + public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. + { + Book myDocument = new Book(); + myDocument.Id = Guid.NewGuid().ToString(); + myDocument.Title = "My Book"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; + + //Create second document to make sure we have atleast one document which are filtered out of query. + Book secondDocument = new Book + { + Id = Guid.NewGuid().ToString(), + Title = "My Second Book", + Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, + Author = new Author { Name = "Carlos", Location = "Cancun" }, + Price = 25, + Editions = new List() { new Edition() { Name = "First", Year = 1970 } } + }; + + //Unfiltered execution. + IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Simple Equality on custom property", + b => from book in getBookQuery(b) + where book.Title == "My Book" + select book)); + inputs.Add(new LinqTestInput("Nested Property access", + b => from book in getBookQuery(b) + where book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("Array references & Project Author out..", + b => from book in getBookQuery(b) + where book.Languages[0].Name == "English" + select book.Author)); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); + inputs.Add(new LinqTestInput("NumericRange query", + b => from book in getBookQuery(b) + where book.Price < 10 + select book.Author)); + inputs.Add(new LinqTestInput("Or query", + b => from book in getBookQuery(b) + where book.Title == "My Book" || book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("SelectMany query on a List type.", + b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); + // Below samples are strictly speaking not Any equivalent. But they join and filter "all" + // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Languages + .Where(lng => lng.Name == "English") + .Select(lng => book.Author)))); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Editions + .Where(edition => edition.Year == 2001) + .Select(lng => book.Author)))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. + { + IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Document myDocument = new Document(); + Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Filter equality on custom property", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title2" + select attachment)); + inputs.Add(new LinqTestInput("Filter equality on custom property #2", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title" + select attachment)); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLinqTypeSystem() + { + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); + + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); + Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); + + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + } + + #region DataDocument type tests + + public class BaseDocument + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public string TypeName { get; set; } + } + + public class DataDocument : BaseDocument + { + public int Number { get; set; } + } + + private class QueryHelper + { + private readonly Container container; + + public QueryHelper(Container container) + { + this.container = container; + } + + public IQueryable Query() where T : BaseDocument + { + IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + .Where(d => d.TypeName == "Hello"); + string queryString = query.ToString(); + return query; + } + } + + [TestMethod] + public async Task ValidateLinqOnDataDocumentType() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); + + DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; + container.CreateItemAsync(doc).Wait(); + + QueryHelper queryHelper = new QueryHelper(container); + IEnumerable result = queryHelper.Query(); + Assert.AreEqual(1, result.Count()); + + BaseDocument baseDocument = result.FirstOrDefault(); + Assert.AreEqual(doc.Id, baseDocument.Id); + + BaseDocument iDocument = doc; + IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable iresult = from f in q + where f.Id == iDocument.Id + select f; + DataDocument id = iresult.FirstOrDefault(); + Assert.AreEqual(doc.Id, id.Id); + } + + #endregion + + #region Book type tests + public class Author + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + public string Location { get; set; } + } + + public class Language + { + public string Name { get; set; } + public string Copyright { get; set; } + } + + public class Edition + { + public string Name { get; set; } + public int Year { get; set; } + } + + public class Book + { + //Verify that we can override the propertyName but still can query them using .NET Property names. + [JsonProperty(PropertyName = "title")] + public string Title { get; set; } + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + public Language[] Languages { get; set; } + public Author Author { get; set; } + public double Price { get; set; } + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public List Editions { get; set; } + } + + [TestMethod] + public async Task ValidateServerSideQueryEvalWithPagination() + { + await this.ValidateServerSideQueryEvalWithPaginationScenario(); + } + + private async Task ValidateServerSideQueryEvalWithPaginationScenario() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; + ContainerProperties cosmosContainerSettings = new ContainerProperties + { + Id = Guid.NewGuid().ToString(), + PartitionKey = partitionKeyDefinition, + }; + cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; + + Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); + + //Do script post to insert as many document as we could in a tight loop. + string script = @"function() { + var output = 0; + var client = getContext().getCollection(); + function callback(err, docCreated) { + if(err) throw 'Error while creating document'; + output++; + getContext().getResponse().setBody(output); + if(output < 50) + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); + }; + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; + + StoredProcedureExecuteResponse scriptResponse = null; + int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); + + IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); + Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); + + } + + #endregion + + public class SpecialAttachment2 //Non attachemnt derived. + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + + [JsonProperty(PropertyName = "contentType")] + public string ContentType { get; set; } + + [JsonProperty(PropertyName = Constants.Properties.MediaLink)] + public string Media { get; set; } + + public string Author { get; set; } + public string Title { get; set; } + } + + #region TypeSystem test reference classes + public interface IFooItem { } + + public class FooItem : IFooItem { } + + public class DerivedFooItem : FooItem { } + + public class MyList : List { } + + public class MyTupleList : List> { } + + public class DerivedFooCollection : IList, IEnumerable + { + public int IndexOf(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, IFooItem item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public IFooItem this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(IFooItem item) + { + throw new NotImplementedException(); + } + + public void CopyTo(IFooItem[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(IFooItem item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooStringCollection : IList, IEnumerable + { + public int IndexOf(string item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, string item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public string this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(string item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(string item) + { + throw new NotImplementedException(); + } + + public void CopyTo(string[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(string item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooTCollection : List, IEnumerable + { + public new IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + } + #endregion + + public override LinqTestOutput ExecuteTest(LinqTestInput input) + { + return LinqTestsCommon.ExecuteTest(input); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 509e89c0a6..928e057967 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -196,6 +196,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From c9de5a3557e368ff5e7650cfb8517f1c5e529994 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Wed, 17 Apr 2024 14:17:47 -0400 Subject: [PATCH 322/337] ChangeFeedProcessor: Fixes ArgumentException when dealing with Legacy lease incremental documents that do not have a Mode property (#4426) * fix for 4423 * fix comment * some recommendation changes --- .../DocumentServiceLeaseManager.cs | 44 +++--- ...orBuilderWithAllVersionsAndDeletesTests.cs | 140 ++++++++++++++---- 2 files changed, 134 insertions(+), 50 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs index 18b0e790ba..aa455969ab 100644 --- a/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs +++ b/Microsoft.Azure.Cosmos/src/ChangeFeedProcessor/LeaseManagement/DocumentServiceLeaseManager.cs @@ -85,37 +85,33 @@ public void ChangeFeedModeSwitchingCheck( DocumentServiceLease documentServiceLease = documentServiceLeases[0]; - // Mode attribute exists on lease document, but it is not set. legacy is always LatestVersion because - // AllVersionsAndDeletes does not exist. There should not be any legacy lease documents that are - // AllVersionsAndDeletes. If the ChangeFeedProcessor's mode is not legacy, an exception should thrown. - // If the ChangeFeedProcessor mode is not the mode in the lease document, an exception should be thrown. - - bool shouldThrowException = this.VerifyChangeFeedProcessorMode( - changeFeedMode: - string.IsNullOrEmpty(documentServiceLease.Mode) - ? ChangeFeedMode.LatestVersion - : changeFeedLeaseOptionsMode, - leaseChangeFeedMode: documentServiceLease.Mode, - normalizedProcessorChangeFeedMode: out string normalizedProcessorChangeFeedMode); - - // If shouldThrowException is true, throw the exception. - - if (shouldThrowException) - { - throw new ArgumentException(message: $"Switching {nameof(ChangeFeedMode)} {documentServiceLease.Mode} to {normalizedProcessorChangeFeedMode} is not allowed."); - } + this.VerifyChangeFeedProcessorMode( + changeFeedMode: changeFeedLeaseOptionsMode, + leaseChangeFeedMode: documentServiceLease.Mode); } - private bool VerifyChangeFeedProcessorMode( + /// + /// Mode attribute exists on lease document, but it is not set. Legacy is always LatestVersion/IncrementalFeed + /// because AllVersionsAndDeletes does not exist. There should not be any legacy lease documents that are + /// AllVersionsAndDeletes. If the ChangeFeedProcessor's mode is not legacy, an exception should thrown. + /// If the ChangeFeedProcessor mode is not the mode in the lease document, an exception should be thrown. + /// + /// The current change feed mode. + /// The change feed mode on the lease document. + private void VerifyChangeFeedProcessorMode( ChangeFeedMode changeFeedMode, - string leaseChangeFeedMode, - out string normalizedProcessorChangeFeedMode) + string leaseChangeFeedMode) { - normalizedProcessorChangeFeedMode = changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes + leaseChangeFeedMode ??= HttpConstants.A_IMHeaderValues.IncrementalFeed; + + string normalizedProcessorChangeFeedMode = changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes ? HttpConstants.A_IMHeaderValues.FullFidelityFeed : HttpConstants.A_IMHeaderValues.IncrementalFeed; - return string.Compare(leaseChangeFeedMode, normalizedProcessorChangeFeedMode, StringComparison.OrdinalIgnoreCase) != 0; + if (string.Compare(leaseChangeFeedMode, normalizedProcessorChangeFeedMode, StringComparison.OrdinalIgnoreCase) != 0) + { + throw new ArgumentException(message: $"Switching {nameof(ChangeFeedMode)} {leaseChangeFeedMode} to {normalizedProcessorChangeFeedMode} is not allowed."); + } } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs index 5a31025e71..7217993fd5 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ChangeFeed/GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests.cs @@ -6,11 +6,12 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests.ChangeFeed { using System; using System.Collections.Generic; - using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.ChangeFeed.Utils; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json.Linq; [TestClass] [TestCategory("ChangeFeedProcessor")] @@ -107,8 +108,6 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The create operation must happen before the replace operation."); Assert.IsTrue(condition: createChange.Metadata.Lsn < replaceChange.Metadata.Lsn, message: "The replace operation must happen before the delete operation."); - Debug.WriteLine("Assertions completed."); - return Task.CompletedTask; }) .WithInstanceName(Guid.NewGuid().ToString()) @@ -117,9 +116,6 @@ public async Task WhenADocumentIsCreatedThenUpdatedThenDeletedTestsAsync() { exception = error.InnerException; - Debug.WriteLine("WithErrorNotification"); - Debug.WriteLine(error.ToString()); - return Task.CompletedTask; }) .Build(); @@ -176,11 +172,46 @@ await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests leaseContainer: this.LeaseContainer, allDocsProcessed: allDocsProcessed)); - Debug.WriteLine(exception.ToString()); - Assert.AreEqual(expected: "Switching ChangeFeedMode Incremental Feed to Full-Fidelity Feed is not allowed.", actual: exception.Message); + } + + + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: For Legacy lease documents with no Mode property, When ChangeFeedMode on ChangeFeedProcessor, switches from LatestVersion to AllVersionsAndDeletes," + + "an exception is expected. LatestVersion's WithStartFromBeginning can be set, or not set.")] + [DataRow(false)] + [DataRow(true)] + public async Task WhenLegacyLatestVersionSwitchToAllVersionsAndDeletesExpectsAexceptionTestAsync(bool withStartFromBeginning) + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.LatestVersion); + ManualResetEvent allDocsProcessed = new(false); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + + // Read lease documents, remove the Mode, and update the lease documents, so that it mimics a legacy lease document. + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .RevertLeaseDocumentsToLegacyWithNoMode( + leaseContainer: this.LeaseContainer, + leaseDocumentCount: 2); + + ArgumentException exception = await Assert.ThrowsExceptionAsync( + () => GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed)); - Debug.WriteLine("Assertions completed."); + Assert.AreEqual(expected: "Switching ChangeFeedMode Incremental Feed to Full-Fidelity Feed is not allowed.", actual: exception.Message); } /// @@ -211,11 +242,7 @@ await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests allDocsProcessed: allDocsProcessed, withStartFromBeginning: withStartFromBeginning)); - Debug.WriteLine(exception.ToString()); - Assert.AreEqual(expected: "Switching ChangeFeedMode Full-Fidelity Feed to Incremental Feed is not allowed.", actual: exception.Message); - - Debug.WriteLine("Assertions completed."); } /// @@ -243,8 +270,6 @@ await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests monitoredContainer: monitoredContainer, leaseContainer: this.LeaseContainer, allDocsProcessed: allDocsProcessed); - - Debug.WriteLine("No exceptions occurred."); } catch { @@ -281,8 +306,6 @@ await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests leaseContainer: this.LeaseContainer, allDocsProcessed: allDocsProcessed, withStartFromBeginning: withStartFromBeginning); - - Debug.WriteLine("No exceptions occurred."); } catch { @@ -290,6 +313,80 @@ await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests } } + /// + /// This is based on an issue located at . + /// + [TestMethod] + [Owner("philipthomas-MSFT")] + [Description("Scenario: For Legacy lease documents with no Mode property, When ChangeFeedMode on ChangeFeedProcessor " + + "does not switch, LatestVersion, no exception is expected. LatestVersion's WithStartFromBeginning can be set, or not set.")] + [DataRow(false)] + [DataRow(true)] + public async Task WhenLegacyNoSwitchLatestVersionDoesNotExpectAnExceptionTestAsync(bool withStartFromBeginning) + { + ContainerInternal monitoredContainer = await this.CreateMonitoredContainer(ChangeFeedMode.LatestVersion); + ManualResetEvent allDocsProcessed = new(false); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + + // Read lease documents, remove the Mode, and update the lease documents, so that it mimics a legacy lease document. + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .RevertLeaseDocumentsToLegacyWithNoMode( + leaseContainer: this.LeaseContainer, + leaseDocumentCount: 2); + + await GetChangeFeedProcessorBuilderWithAllVersionsAndDeletesTests + .BuildChangeFeedProcessorWithLatestVersionAsync( + monitoredContainer: monitoredContainer, + leaseContainer: this.LeaseContainer, + allDocsProcessed: allDocsProcessed, + withStartFromBeginning: withStartFromBeginning); + } + + private static async Task RevertLeaseDocumentsToLegacyWithNoMode( + Container leaseContainer, + int leaseDocumentCount) + { + FeedIterator iterator = leaseContainer.GetItemQueryStreamIterator( + queryText: "SELECT * FROM c", + continuationToken: null); + + List leases = new List(); + while (iterator.HasMoreResults) + { + using (ResponseMessage responseMessage = await iterator.ReadNextAsync().ConfigureAwait(false)) + { + responseMessage.EnsureSuccessStatusCode(); + leases.AddRange(CosmosFeedResponseSerializer.FromFeedResponseStream( + serializerCore: CosmosContainerExtensions.DefaultJsonSerializer, + streamWithServiceEnvelope: responseMessage.Content)); + } + } + + int counter = 0; + + foreach (JObject lease in leases) + { + if (!lease.ContainsKey("Mode")) + { + continue; + } + + counter++; + lease.Remove("Mode"); + + _ = await leaseContainer.UpsertItemAsync(item: lease); + } + + Assert.AreEqual(expected: leaseDocumentCount, actual: counter); + } + private static async Task BuildChangeFeedProcessorWithLatestVersionAsync( ContainerInternal monitoredContainer, Container leaseContainer, @@ -307,9 +404,6 @@ private static async Task BuildChangeFeedProcessorWithLatestVersionAsync( { exception = error.InnerException; - Debug.WriteLine("WithErrorNotification"); - Debug.WriteLine(error.ToString()); - return Task.CompletedTask; }); @@ -318,7 +412,6 @@ private static async Task BuildChangeFeedProcessorWithLatestVersionAsync( processorBuilder.WithStartFromBeginning(); } - ChangeFeedProcessor processor = processorBuilder.Build(); Interlocked.Exchange(ref latestVersionProcessorAtomic, processor); @@ -349,9 +442,6 @@ private static async Task BuildChangeFeedProcessorWithAllVersionsAndDeletesAsync { exception = error.InnerException; - Debug.WriteLine("WithErrorNotification"); - Debug.WriteLine(error.ToString()); - return Task.FromResult(exception); }); @@ -376,8 +466,6 @@ private async Task CreateMonitoredContainer(ChangeFeedMode ch if (changeFeedMode == ChangeFeedMode.AllVersionsAndDeletes) { - Debug.WriteLine($"{nameof(properties.ChangeFeedPolicy.FullFidelityRetention)} initialized."); - properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5); } From de078b4ad13621c79b9d8c4525d17e88006ad5ba Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:50:23 -0700 Subject: [PATCH 323/337] [Internal] Flakey Tests: Fixes few Tests in `GatewayAddressCacheTests` (#4424) * Code changes to fix one of the GW cache flakey tests. * Code changes to fix some of the assertions. * Code changes to use IsCompletedSuccessfully. --- .../GatewayAddressCacheTests.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index 4b49c29d8e..0f31b9b1ca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -1397,6 +1397,7 @@ await cache.MarkAddressesToUnhealthyAsync( fieldName: "lastUnhealthyTimestamp", delayInMinutes: -2 * iterationIndex); + int numberOfTasksCreated = 0; for (int j = 0; j < 500 * iterationIndex; j++) { openConnectionTasks @@ -1406,14 +1407,21 @@ await cache.MarkAddressesToUnhealthyAsync( partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, serviceIdentity: this.serviceIdentity, forceRefreshPartitionAddresses: false, - cancellationToken: CancellationToken.None)); + cancellationToken: CancellationToken.None) + .ContinueWith(x => + { + if(x.IsCompletedSuccessfully) + { + Interlocked.Increment(ref numberOfTasksCreated); + } + })); } // awaits for the parallel execution to finish. await Task.WhenAll(openConnectionTasks); - // This assertion validates that there are no extra tasks created in the thread pool. - Assert.AreEqual(0, ThreadPool.PendingWorkItemCount); + // This assertion validates that the number of tasks completed are same as the 500 * iterationIndex. + Assert.AreEqual(500 * iterationIndex, numberOfTasksCreated); // Waits until a completion signal from the background task is received. GatewayAddressCacheTests.WaitForManualResetEventSignal( From a8f4b7e80ff6fe5de708399e8a9e247d73bec370 Mon Sep 17 00:00:00 2001 From: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Date: Thu, 18 Apr 2024 03:08:35 -0400 Subject: [PATCH 324/337] SDK 3.39.1/3.40.0-preview.1: Adds version bump and changelog. (#4430) * SDK 3.39.1/3.40.0-preview.1: Adds version bump and changelog. * Update changelog.md Co-authored-by: Matias Quaranta --------- Co-authored-by: Matias Quaranta Co-authored-by: Sourabh Jain --- Directory.Build.props | 4 ++-- changelog.md | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index b40a53cfd0..c839fcd356 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,8 +1,8 @@ - 3.39.0 + 3.39.1 3.40.0 - preview.0 + preview.1 3.33.1 2.0.4 2.1.0 diff --git a/changelog.md b/changelog.md index ba26c7365c..16517e8f95 100644 --- a/changelog.md +++ b/changelog.md @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.40.0-preview.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.40.0-preview.1) - 2024-04-17 +### [3.39.1](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.39.1) - 2024-04-17 + +#### Fixed +- [4426](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4426) ChangeFeedProcessor: Fixes ArgumentException when dealing with Legacy lease incremental documents that do not have a Mode property + ### [3.40.0-preview.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.40.0-preview.0) - 2024-04-05 #### Fixed From a76666dc5f8ad97d011d75dce21da02666aa9877 Mon Sep 17 00:00:00 2001 From: Aditya Date: Thu, 18 Apr 2024 13:11:34 -0700 Subject: [PATCH 325/337] [Internal] ReleaseNotes : Adds known issue to list (#4434) * Initial commit * Update --------- Co-authored-by: Matias Quaranta --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 16517e8f95..7896025977 100644 --- a/changelog.md +++ b/changelog.md @@ -1354,6 +1354,7 @@ Below is a list of any know issues affecting the [recommended minimum version](# | Issue | Impact | Mitigation | Tracking link | | --- | --- | --- | --- | | `FeedIterator` enters an infinite loop after a physical partition split occurs in a container using hierarchical partition keys. | Queries using prefix partition keys. | Rather than having the PK included in the query request options, filtering on top level hierarchical Pks should be done through where clauses. | [#4326](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4326) | +| Single partition queries (queries explicitly targetted to single partition or any queries on collection that had single physical partition) that resume using continuation token after partition split can observe failure on SDK v3.38 and beyond. | Explicit query exeuction using continuation token will fail query execution if these conditions are met. | Turn off Optimistic Direct Execution during query execution either by setting EnableOptimisticDirectExecution to false in query request options or by setting environment variable AZURE_COSMOS_OPTIMISTIC_DIRECT_EXECUTION_ENABLED to false. | [#4432](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/4432) | ## Release & Retirement dates From 61319986f14e3a077a830e97b0b8b5692effec8c Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:03:54 -0700 Subject: [PATCH 326/337] Samples: Adds STJ LINQ Serializer Example (#4420) * initial commit * bump sample version * update comments * sln file fix * update comment * Update Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs Co-authored-by: Matias Quaranta * remarks fix * xml fix --------- Co-authored-by: Matias Quaranta --- .../CosmosSystemTextJsonSerializer.cs | 33 +++++- .../Usage/SystemTextJson/Program.cs | 6 - .../src/Serializer/CosmosLinqSerializer.cs | 109 ++++-------------- .../Linq/LinqTestsCommon.cs | 25 ++-- .../Linq/CosmosLinqJsonConverterTests.cs | 33 +++--- 5 files changed, 92 insertions(+), 114 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs index 9305324ae6..5213e3bb7d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/CosmosSystemTextJsonSerializer.cs @@ -1,21 +1,28 @@ namespace Cosmos.Samples.Shared { using System.IO; + using System.Reflection; using System.Text.Json; + using System.Text.Json.Serialization; using Azure.Core.Serialization; using Microsoft.Azure.Cosmos; /// /// Uses which leverages System.Text.Json providing a simple API to interact with on the Azure SDKs. /// + /// + /// For item CRUD operations and non-LINQ queries, implementing CosmosSerializer is sufficient. To support LINQ query translations as well, CosmosLinqSerializer must be implemented. + /// // - public class CosmosSystemTextJsonSerializer : CosmosSerializer + public class CosmosSystemTextJsonSerializer : CosmosLinqSerializer { private readonly JsonObjectSerializer systemTextJsonSerializer; + private readonly JsonSerializerOptions jsonSerializerOptions; public CosmosSystemTextJsonSerializer(JsonSerializerOptions jsonSerializerOptions) { this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + this.jsonSerializerOptions = jsonSerializerOptions; } public override T FromStream(Stream stream) @@ -44,6 +51,30 @@ public override Stream ToStream(T input) streamPayload.Position = 0; return streamPayload; } + + public override string SerializeMemberName(MemberInfo memberInfo) + { + JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null) + { + return null; + } + + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + if (!string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name)) + { + return jsonPropertyNameAttribute.Name; + } + + if (this.jsonSerializerOptions.PropertyNamingPolicy != null) + { + return this.jsonSerializerOptions.PropertyNamingPolicy.ConvertName(memberInfo.Name); + } + + // Do any additional handling of JsonSerializerOptions here. + + return memberInfo.Name; + } } // } diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs index d66d54f5a2..739595d262 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs @@ -115,8 +115,6 @@ private static async Task RunDemo() Console.WriteLine($"Created Completed activity with id {createCompletedActivity.Resource.Id} that cost {createCompletedActivity.RequestCharge}"); // Execute queries materializing responses using System.Text.Json - // NOTE: GetItemLinqQueryable does not support System.Text.Json attributes. LINQ will not translate the name based on the attributes - // which can result in no or invalid results coming back. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3250 using FeedIterator iterator = container.GetItemQueryIterator("select * from c where c.status = 'Completed'"); while (iterator.HasMoreResults) { @@ -177,19 +175,15 @@ private static async Task CleanupAsync() // public class ToDoActivity { - // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("id")] public string Id { get; set; } - // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("partitionKey")] public string PartitionKey { get; set; } - // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("activityId")] public string ActivityId { get; set; } - // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("status")] public string Status { get; set; } } diff --git a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs index 6f9406ea2f..e2e898d15b 100644 --- a/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Serializer/CosmosLinqSerializer.cs @@ -1,88 +1,25 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Cosmos -{ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ using System.Reflection; - /// - /// This abstract class can be implemented to allow a custom serializer (Non [Json.NET serializer](https://www.newtonsoft.com/json/help/html/Introduction.htm)'s) - /// to be used by the CosmosClient for LINQ queries. - /// - /// - /// This example implements the CosmosLinqSerializer contract. - /// This example custom serializer will honor System.Text.Json attributes. - /// - /// (Stream stream) - /// { - /// if (stream == null) - /// throw new ArgumentNullException(nameof(stream)); - /// - /// using (stream) - /// { - /// if (stream.CanSeek && stream.Length == 0) - /// { - /// return default; - /// } - /// - /// if (typeof(Stream).IsAssignableFrom(typeof(T))) - /// { - /// return (T)(object)stream; - /// } - /// - /// return (T)this.systemTextJsonSerializer.Deserialize(stream, typeof(T), default); - /// } - /// } - /// - /// public override Stream ToStream(T input) - /// { - /// MemoryStream streamPayload = new MemoryStream(); - /// this.systemTextJsonSerializer.Serialize(streamPayload, input, input.GetType(), default); - /// streamPayload.Position = 0; - /// return streamPayload; - /// } - /// - /// public override string SerializeMemberName(MemberInfo memberInfo) - /// { - /// System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = - /// memberInfo.GetCustomAttribute(true); - /// if (jsonExtensionDataAttribute != null) - /// { - /// return null; - /// } - /// - /// JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); - /// - /// string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) - /// ? jsonPropertyNameAttribute.Name - /// : memberInfo.Name; - /// - /// // Users must add handling for any additional attributes here - /// - /// return memberName; - /// } - /// } - /// ]]> - /// - /// - public abstract class CosmosLinqSerializer : CosmosSerializer - { - /// - /// Convert a MemberInfo to a string for use in LINQ query translation. - /// This must be implemented when using a custom serializer for LINQ queries. - /// - /// Any MemberInfo used in the query. - /// A serialized representation of the member. - public abstract string SerializeMemberName(MemberInfo memberInfo); - } -} + /// + /// This abstract class can be implemented to allow a custom serializer (Non [Json.NET serializer](https://www.newtonsoft.com/json/help/html/Introduction.htm)'s) + /// to be used by the CosmosClient for LINQ queries. + /// + /// + /// Refer to the sample project for a full implementation. + /// + public abstract class CosmosLinqSerializer : CosmosSerializer + { + /// + /// Convert a MemberInfo to a string for use in LINQ query translation. + /// This must be implemented when using a custom serializer for LINQ queries. + /// + /// Any MemberInfo used in the query. + /// A serialized representation of the member. + public abstract string SerializeMemberName(MemberInfo memberInfo); + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index ab5155cbfe..6e62be7cef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -836,11 +836,13 @@ public override void SerializeAsXml(XmlWriter xmlWriter) class SystemTextJsonLinqSerializer : CosmosLinqSerializer { - private readonly JsonObjectSerializer systemTextJsonSerializer; + private readonly JsonObjectSerializer systemTextJsonSerializer; + private readonly JsonSerializerOptions jsonSerializerOptions; public SystemTextJsonLinqSerializer(JsonSerializerOptions jsonSerializerOptions) { - this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + this.systemTextJsonSerializer = new JsonObjectSerializer(jsonSerializerOptions); + this.jsonSerializerOptions = jsonSerializerOptions; } public override T FromStream(Stream stream) @@ -882,12 +884,19 @@ public override string SerializeMemberName(MemberInfo memberInfo) } JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); - - string memberName = !string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name) - ? jsonPropertyNameAttribute.Name - : memberInfo.Name; - - return memberName; + if (!string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name)) + { + return jsonPropertyNameAttribute.Name; + } + + if (this.jsonSerializerOptions.PropertyNamingPolicy != null) + { + return this.jsonSerializerOptions.PropertyNamingPolicy.ConvertName(memberInfo.Name); + } + + // Do any additional handling of JsonSerializerOptions here. + + return memberInfo.Name; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs index e3882b3bf3..d6bb329025 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Linq/CosmosLinqJsonConverterTests.cs @@ -198,7 +198,7 @@ class TestCustomJsonLinqSerializer : CosmosLinqSerializer { private readonly JsonObjectSerializer systemTextJsonSerializer; - public static readonly System.Text.Json.JsonSerializerOptions JsonOptions = new() + private readonly System.Text.Json.JsonSerializerOptions jsonSerializerOptions = new() { DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true, @@ -209,7 +209,7 @@ class TestCustomJsonLinqSerializer : CosmosLinqSerializer public TestCustomJsonLinqSerializer() { - this.systemTextJsonSerializer = new JsonObjectSerializer(JsonOptions); + this.systemTextJsonSerializer = new JsonObjectSerializer(this.jsonSerializerOptions); } public override T FromStream(Stream stream) @@ -237,9 +237,9 @@ public override Stream ToStream(T input) this.systemTextJsonSerializer.Serialize(stream, input, input.GetType(), default); stream.Position = 0; return stream; - } - - public override string SerializeMemberName(MemberInfo memberInfo) + } + + public override string SerializeMemberName(MemberInfo memberInfo) { System.Text.Json.Serialization.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); @@ -247,14 +247,21 @@ public override string SerializeMemberName(MemberInfo memberInfo) { return null; } - - JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); - - string memberName = jsonPropertyNameAttribute != null && !string.IsNullOrEmpty(jsonPropertyNameAttribute.Name) - ? jsonPropertyNameAttribute.Name - : memberInfo.Name; - - return memberName; + + JsonPropertyNameAttribute jsonPropertyNameAttribute = memberInfo.GetCustomAttribute(true); + if (!string.IsNullOrEmpty(jsonPropertyNameAttribute?.Name)) + { + return jsonPropertyNameAttribute.Name; + } + + if (this.jsonSerializerOptions.PropertyNamingPolicy != null) + { + return this.jsonSerializerOptions.PropertyNamingPolicy.ConvertName(memberInfo.Name); + } + + // Do any additional handling of JsonSerializerOptions here. + + return memberInfo.Name; } } From 400abfd5184822f1f7f86f59cb285ef1ee3ee19c Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Mon, 22 Apr 2024 15:03:37 -0700 Subject: [PATCH 327/337] [Internal] Documentation: Adds details about retry backoff for 410/449 (#4445) * Update SdkDesign.md * Update SdkDesign.md --- docs/SdkDesign.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/SdkDesign.md b/docs/SdkDesign.md index f3f2ec1581..3c54e58a6f 100644 --- a/docs/SdkDesign.md +++ b/docs/SdkDesign.md @@ -53,7 +53,7 @@ Any failure response from the Transport that matches the [conditions for cross-r * HTTP connection failures or DNS resolution problems (HttpRequestException) - The account information is refreshed, the current region is marked unavailable to be used, and the request is retried on the next available region after account refresh if the account has multiple regions. In case no other regions are available, the SDK keeps retrying by refreshing the account information up to a [maximum of times](../Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs#L24). * HTTP 403 with Substatus 3 - The current region is no longer a Write region (write region failover), the account information is refreshed, and the request is retried on the new Write region. -* HTTP 403 with Substatus 1008 - The current region is not available (adding or removing a region). The region is marked as unavailable and the request retried on the next available region. +* HTTP 403 with Substatus 1008 - The current region is not available (adding or removing a region). The region is marked as unavailable for 5 minutes and the request retried on the next available region. * HTTP 404 with Substatus 1002 - Session consistency request where the region did not yet receive the requested Session Token, the request is retried on the primary (write) region for accounts with a single write region or on the next preferred region for accounts with multiple write regions. * HTTP 503 - The request could not succeed on the region due to repeated TCP connectivity issues, the request is retried on the next preferred region. @@ -150,8 +150,13 @@ If the retry period (30 seconds) is exhausted, it returns an HTTP 503 ServiceUna * HTTP 410 Substatus 1008 (partition is migrating) responses from the service -> Refreshes partition map (rediscovers partitions) and retries. * HTTP 410 Substatus 1007 (partition is splitting) responses from the service -> Refreshes partition map (rediscovers partitions) and retries. * HTTP 410 Substatus 1000 responses from the service, up to 3 times -> Refreshes container map (for cases when the container was recreated with the same name) and retries. + +> :information_source: There is no delay for the first retry. Further retries start with 1 second and using a backoff multiplier of 2 can go up to 15 seconds. + * HTTP 449 responses from the service -> Retries using a random salted period. +> :information_source: There is no delay for the first retry. Further retries start with 10 milliseconds and using a backoff multiplier of 2 with a 5 millisecond salt can go up to 1 second. + ```mermaid flowchart ServerStoreModel --> StoreClient From 85a8444b841dc8e3271ead7494909ade9ba4ff88 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Tue, 23 Apr 2024 10:25:49 -0700 Subject: [PATCH 328/337] Add a new capability for non streaming order by in QueryFeatures and add a new flag to QueryInfo that will be used by ServiceInterop to indicate non streaming order by queries (#4446) --- .../src/Query/Core/QueryPlan/QueryFeature.cs | 3 ++- .../src/Query/Core/QueryPlan/QueryInfo.cs | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryFeature.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryFeature.cs index 6e20108ea7..0b3ed7fdc1 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryFeature.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryFeature.cs @@ -27,6 +27,7 @@ enum QueryFeatures : ulong OrderBy = 1 << 7, Top = 1 << 8, NonValueAggregate = 1 << 9, - DCount = 1 << 10 + DCount = 1 << 10, + NonStreamingOrderBy = 1 << 11, } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryInfo.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryInfo.cs index d210a6daf6..fa796a4965 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryInfo.cs @@ -102,6 +102,13 @@ public bool HasSelectValue [JsonProperty("dCountInfo")] public DCountInfo DCountInfo + { + get; + set; + } + + [JsonProperty("hasNonStreamingOrderBy")] + public bool HasNonStreamingOrderBy { get; set; From 14633455d28dc6627409b421120bd60d6c6f7dd1 Mon Sep 17 00:00:00 2001 From: Aditya Date: Wed, 24 Apr 2024 06:42:46 -0700 Subject: [PATCH 329/337] Query: Fixes Persisted continuationToken issue by turning off ODE by default (#4413) * Turn of ODE by default. * Updated tests * Update * Test fix * Added test for query resumption with ODE token with partition split container (failure case). * Update. * Update Benchmark * Addressed comments. --- .../CosmosQueryExecutionContextFactory.cs | 20 +- .../src/RequestOptions/QueryRequestOptions.cs | 2 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 196 - ...TraceWriterBaselineTests.ReadManyAsync.xml | 1020 +-- ...lBaselineTests.TestDistinctTranslation.xml | 28 +- ...alBaselineTests.TestGroupByTranslation.xml | 2 + ...ralBaselineTests.TestThenByTranslation.xml | 8 +- .../Linq/LinqGeneralBaselineTests.cs | 6066 ++++++++--------- .../Linq/LinqTestsCommon.cs | 28 +- .../OptimisticDirectExecutionQueryTests.cs | 11 +- .../Contracts/BenchmarkResults.json | 48 +- ...misticDirectExecutionQueryBaselineTests.cs | 277 +- .../Query/Pipeline/FullPipelineTests.cs | 11 +- 13 files changed, 3853 insertions(+), 3864 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index d778db2438..7676270416 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -758,19 +758,14 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP ITrace trace) { bool clientDisableOptimisticDirectExecution = await cosmosQueryContext.QueryClient.GetClientDisableOptimisticDirectExecutionAsync(); + bool isOdeContinuationToken = inputParameters.InitialUserContinuationToken != null && + OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken); // Use the Ode code path only if ClientDisableOptimisticDirectExecution is false and EnableOptimisticDirectExecution is true - if (clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) + // But allow the query using ODE pipeline if it's earlier roundtrips are made using ODE continuation token. + if ((clientDisableOptimisticDirectExecution || !inputParameters.EnableOptimisticDirectExecution) && + !isOdeContinuationToken) { - if (inputParameters.InitialUserContinuationToken != null - && OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(inputParameters.InitialUserContinuationToken)) - { - string errorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - - throw new MalformedContinuationTokenException($"{errorMessage} Continuation Token: {inputParameters.InitialUserContinuationToken}"); - } - return null; } @@ -817,6 +812,11 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP return targetRanges.Single(); } + if (isOdeContinuationToken) + { + throw new InvalidOperationException("Execution of this query cannot resume using Optimistic Direct Execution continuation token due to partition split. Please restart the query without the continuation token."); + } + return null; } diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs index 1035fac1c9..ad15e0cd13 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/QueryRequestOptions.cs @@ -50,7 +50,7 @@ public class QueryRequestOptions : RequestOptions /// /// Direct (optimistic) execution offers improved performance for several kinds of queries such as a single partition streaming query. /// - public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: true); + public bool EnableOptimisticDirectExecution { get; set; } = ConfigurationManager.IsOptimisticDirectExecutionEnabled(defaultValue: false); /// /// Gets or sets the maximum number of items that can be buffered client side during diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 1a881f3a14..12e27e0576 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -34,12 +34,8 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -209,16 +205,6 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -231,16 +217,6 @@ } ] }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -759,12 +735,8 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -938,16 +910,6 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -960,16 +922,6 @@ } ] }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -1505,12 +1457,8 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -1689,26 +1637,6 @@ "duration in milliseconds": 0 } ] - }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - } - ] - }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 } ] }, @@ -2231,12 +2159,8 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -2410,16 +2334,6 @@ "name": "Service Interop Query Plan", "duration in milliseconds": 0 }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "Get Partition Key Ranges", "duration in milliseconds": 0, @@ -2432,16 +2346,6 @@ } ] }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - }, { "name": "MoveNextAsync", "duration in milliseconds": 0, @@ -3001,12 +2905,8 @@ │ │ │ [PointOperationStatisticsTraceDatum] │ │ │ Redacted To Not Change The Baselines From Run To Run │ │ │ ) - │ │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3239,26 +3139,6 @@ "duration in milliseconds": 0 } ] - }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - } - ] - }, - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 } ] }, @@ -3799,15 +3679,9 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -3992,38 +3866,6 @@ ] } ] - }, - { - "name": "Get Overlapping Feed Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - } - ] - } - ] - }, - { - "name": "Get Overlapping Feed Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] } ] }, @@ -4548,15 +4390,9 @@ │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds │ ├── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds │ │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds @@ -4745,38 +4581,6 @@ ] } ] - }, - { - "name": "Get Overlapping Feed Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] - } - ] - } - ] - }, - { - "name": "Get Overlapping Feed Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Get Partition Key Ranges", - "duration in milliseconds": 0, - "children": [ - { - "name": "Try Get Overlapping Ranges", - "duration in milliseconds": 0 - } - ] } ] }, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index 5f242a1d00..cf7a291db0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -25,105 +25,117 @@ │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── [05C1CFFFFFFFF8,05C1DFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ├── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ │ ( │ │ [Query Correlated ActivityId] │ │ Redacted To Not Change The Baselines From Run To Run │ │ ) │ ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Query Metrics] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ │ ( - │ │ │ [System Info] - │ │ │ Redacted To Not Change The Baselines From Run To Run - │ │ │ ) - │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [Client Side Request Stats] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ └── [,05C1CFFFFFFFF8) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Query Metrics] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ │ ( + │ │ │ [System Info] + │ │ │ Redacted To Not Change The Baselines From Run To Run + │ │ │ ) + │ │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [Client Side Request Stats] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds └── Execute query for a partitionkeyrange(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds │ ( │ [Query Correlated ActivityId] │ Redacted To Not Change The Baselines From Run To Run │ ) ├── Create Query Pipeline(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds - │ └── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - ├── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Query Metrics] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ │ ( - │ │ [System Info] - │ │ Redacted To Not Change The Baselines From Run To Run - │ │ ) - │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds - │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds - │ ( - │ [Client Side Request Stats] - │ Redacted To Not Change The Baselines From Run To Run - │ ) - └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Container Properties(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ │ └── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Service Interop Query Plan(00000000-0000-0000-0000-000000000000) Query-Component 00:00:00:000 0.00 milliseconds + │ └── Get Overlapping Feed Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Get Partition Key Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + └── MoveNextAsync(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + └── Prefetch(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + └── [05C1E7FFFFFFFA,FF) move next(00000000-0000-0000-0000-000000000000) Pagination-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Query Metrics] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + ├── Microsoft.Azure.Cosmos.Handlers.RequestInvokerHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Collection Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Get Partition Key Range Cache(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ ├── Try Get Overlapping Ranges(00000000-0000-0000-0000-000000000000) Routing-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.DiagnosticsHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ │ ( + │ │ [System Info] + │ │ Redacted To Not Change The Baselines From Run To Run + │ │ ) + │ └── Microsoft.Azure.Cosmos.Handlers.TelemetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RetryHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.RouterHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Cosmos.Handlers.TransportHandler(00000000-0000-0000-0000-000000000000) RequestHandler-Component 00:00:00:000 0.00 milliseconds + │ └── Microsoft.Azure.Documents.ServerStoreModel Transport Request(00000000-0000-0000-0000-000000000000) Transport-Component 00:00:00:000 0.00 milliseconds + │ ( + │ [Client Side Request Stats] + │ Redacted To Not Change The Baselines From Run To Run + │ ) + └── Get Cosmos Element Response(00000000-0000-0000-0000-000000000000) Json-Component 00:00:00:000 0.00 milliseconds ]]> 10) ORDER BY v2 ASC ]]> - + @@ -423,7 +423,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -442,7 +442,7 @@ JOIN ( WHERE ((LENGTH(v2["FamilyName"]) > 10) AND (LENGTH(v2["FamilyName"]) < 20)) ORDER BY v2 ASC ]]> - + @@ -482,7 +482,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -559,7 +559,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -578,7 +578,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -597,7 +597,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -616,7 +616,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2["GivenName"]["Length"] ASC ]]> - + @@ -635,7 +635,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -654,7 +654,7 @@ JOIN ( WHERE (LENGTH(v2["FamilyName"]) > 10) ORDER BY v2 ASC ]]> - + @@ -689,7 +689,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -707,7 +707,7 @@ JOIN ( JOIN v0 IN root["Parents"]) AS v2 ORDER BY v2["FamilyName"] ASC ]]> - + @@ -773,7 +773,7 @@ JOIN ( JOIN p0 IN root["Parents"]) AS v1 ORDER BY v1 ASC ]]> - + @@ -792,7 +792,7 @@ JOIN ( WHERE (LENGTH(v1) > 10) ORDER BY v1 ASC ]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml index f5256c787c..48a78d9afb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestGroupByTranslation.xml @@ -320,6 +320,7 @@ SELECT VALUE root["id"] FROM root GROUP BY root["id"] ORDER BY root["id"] DESC]]> + @@ -334,6 +335,7 @@ FROM root WHERE (root["id"] != "a") GROUP BY root["id"] ORDER BY root["id"] ASC]]> + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml index 75054876fc..73b8b19748 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqGeneralBaselineTests.TestThenByTranslation.xml @@ -119,7 +119,7 @@ JOIN ( SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> - + @@ -132,7 +132,7 @@ ORDER BY root["FamilyId"] ASC, root["FamilyId"] ASC]]> SELECT VALUE root FROM root ORDER BY root["FamilyId"] ASC, root["FamilyId"] DESC]]> - + @@ -388,6 +388,7 @@ FROM ( JOIN c0 IN root["Children"]) AS v1) AS r1 ORDER BY r1["FamilyId"] ASC, r1["FamilyNumber"] ASC ]]> + @@ -434,6 +435,7 @@ FROM ( WHERE (p0["GivenName"]["Length"] > 5)) AS v0) AS r0 ORDER BY r0["FamilyId"] ASC, r0["FamilyNumber"] ASC ]]> + @@ -584,7 +586,7 @@ FROM root JOIN f0 IN root["Records"]["Transactions"] WHERE (ARRAY_LENGTH(root["Children"]) > 0) ORDER BY f0["Type"] ASC, f0["Amount"] ASC]]> - + diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs index 3604a1e89b..9868dc687c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs @@ -1,3068 +1,3068 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests -{ - using System; - using System.Collections.Generic; - using System.Linq; - using System.Linq.Dynamic; - using System.Runtime.Serialization; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Linq; - using Microsoft.Azure.Cosmos.SDK.EmulatorTests; - using Microsoft.VisualStudio.TestTools.UnitTesting; - using Newtonsoft.Json; - using BaselineTest; - using Microsoft.Azure.Documents; - using Microsoft.Azure.Cosmos.Scripts; - using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; - - [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] - public class LinqGeneralBaselineTests : BaselineTests - { - private static CosmosClient cosmosClient; - private static Cosmos.Database testDb; - private static Container testContainer; - private static Func> getQuery; - - [ClassInitialize] - public async static Task Initialize(TestContext textContext) - { - cosmosClient = TestCommon.CreateCosmosClient(true); - DocumentClientSwitchLinkExtension.Reset("LinqTests"); - - string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; - testDb = await cosmosClient.CreateDatabaseAsync(dbName); - - getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); - } - - [ClassCleanup] - public async static Task CleanUp() - { - if (testDb != null) - { - await testDb.DeleteStreamAsync(); - } - - cosmosClient?.Dispose(); - } - - public class Address - { - public string State; - public string County; - public string City; - } - - public class GuidClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public Guid Id; - } - - public class ListArrayClass : LinqTestObject - { - [JsonProperty(PropertyName = "id")] - public string Id; - - public int[] ArrayField; - public List ListField; - } - - [DataContract] - public class Sport : LinqTestObject - { - [DataMember(Name = "id")] - public string SportName; - - [JsonProperty(PropertyName = "json")] - [DataMember(Name = "data")] - public string SportType; - } - - public class Sport2 : LinqTestObject - { - [DataMember(Name = "data")] - public string id; - } - - [TestMethod] - public void TestSelectMany() +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Linq.Dynamic; + using System.Runtime.Serialization; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Linq; + using Microsoft.Azure.Cosmos.SDK.EmulatorTests; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using BaselineTest; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.Scripts; + using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; + + [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] + public class LinqGeneralBaselineTests : BaselineTests + { + private static CosmosClient cosmosClient; + private static Cosmos.Database testDb; + private static Container testContainer; + private static Func> getQuery; + + [ClassInitialize] + public async static Task Initialize(TestContext textContext) + { + cosmosClient = TestCommon.CreateCosmosClient(true); + DocumentClientSwitchLinkExtension.Reset("LinqTests"); + + string dbName = $"{nameof(LinqGeneralBaselineTests)}-{Guid.NewGuid().ToString("N")}"; + testDb = await cosmosClient.CreateDatabaseAsync(dbName); + + getQuery = LinqTestsCommon.GenerateFamilyCosmosData(testDb, out testContainer); + } + + [ClassCleanup] + public async static Task CleanUp() + { + if (testDb != null) + { + await testDb.DeleteStreamAsync(); + } + + cosmosClient?.Dispose(); + } + + public class Address + { + public string State; + public string County; + public string City; + } + + public class GuidClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public Guid Id; + } + + public class ListArrayClass : LinqTestObject + { + [JsonProperty(PropertyName = "id")] + public string Id; + + public int[] ArrayField; + public List ListField; + } + + [DataContract] + public class Sport : LinqTestObject + { + [DataMember(Name = "id")] + public string SportName; + + [JsonProperty(PropertyName = "json")] + [DataMember(Name = "data")] + public string SportType; + } + + public class Sport2 : LinqTestObject + { + [DataMember(Name = "data")] + public string id; + } + + [TestMethod] + public void TestSelectMany() + { + List inputs = new List(); + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", + b => getQuery(b) + .SelectMany(family => family.Children.Where(c => c.Grade > 10) + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))))); + + inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Select)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Where)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); + + inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); + + inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + + inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); + + inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSimpleSubquery() + { + List inputs = new List(); + + inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); + + inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); + + inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); + + inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); + + inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); + + inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); + + inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestQueryFlattening() + { + // these queries should make more sense when combined with where and orderby + // these tests verify the flattening part + List inputs = new List(); + inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); + inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); + inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); + inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); + inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); + inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); + inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) + .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) + .Select(f => f.Children[0].Pets[0].GivenName))); + + inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); + inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); + inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) + .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) + .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); + inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); + inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); + inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestSubquery() + { + List inputs = new List(); + + // -------------------------------------- + // Subquery lambdas + // -------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Take)", b => getQuery(b) + .Select(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "Select(Where)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(Distinct)", b => getQuery(b) + .Select(f => f.Children.Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(Count)", b => getQuery(b) + .Select(f => f.Children.Count(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(Sum)", b => getQuery(b) + .Select(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Count)", b => getQuery(b) + .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); + + inputs.Add(new LinqTestInput( + "Where(Sum)", b => getQuery(b) + .Where(f => f.Children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "OrderBy(Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Count)", b => getQuery(b) + .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); + + // ------------------------------------------------------------- + // Mutilpe-transformations subquery lambdas + // ------------------------------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(Select -> Distinct -> Count)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Sum)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); + + inputs.Add(new LinqTestInput( + "Select(SelectMany -> Select)", b => getQuery(b) + .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Count)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); + + inputs.Add(new LinqTestInput( + "Select(Where -> OrderBy -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(Where -> Select(array) -> Take)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); + + inputs.Add(new LinqTestInput( + "Select(where -> Select -> Distinct)", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); + + inputs.Add(new LinqTestInput( + "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) + .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); + + inputs.Add(new LinqTestInput( + "Where(Select -> Count)", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Where -> Sum)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); + + inputs.Add(new LinqTestInput( + "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Where)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Where -> Count)", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy(Select -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) + .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); + + // --------------------------------------------------------- + // Scalar and Built-in expressions with subquery lambdas + // --------------------------------------------------------- + + // Unary + + inputs.Add(new LinqTestInput( + "Where(unary (Where -> Count))", b => getQuery(b) + .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); + + // Binary + + inputs.Add(new LinqTestInput( + "Select(binary with Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "Select(constant + Where -> Count)", b => getQuery(b) + .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); + + inputs.Add(new LinqTestInput( + "Where((Where -> Count) % constant)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); + + // Conditional + + inputs.Add(new LinqTestInput( + "Select(conditional Any ? Select : Select)", b => getQuery(b) + .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); + + inputs.Add(new LinqTestInput( + "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); + + // New array + + inputs.Add(new LinqTestInput( + "Select(new array)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + // New + member init + + inputs.Add(new LinqTestInput( + "Select(new)", b => getQuery(b) + .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); + + inputs.Add(new LinqTestInput( + "Select(Select new)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where)", b => getQuery(b) + .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); + + inputs.Add(new LinqTestInput( + "Select(new Where -> Count) -> Where", b => getQuery(b) + .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); + + // Array builtin functions + + inputs.Add(new LinqTestInput( + "Select(Where -> Concat(Where))", b => getQuery(b) + .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Sum))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select -> Contains(Where -> Count))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Where -> Select(array indexer)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) + .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); + + // Math builtin functions + + inputs.Add(new LinqTestInput( + "Select(Floor(sum(map), sum(map)))", b => getQuery(b) + .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); + + inputs.Add(new LinqTestInput( + "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) + .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); + + inputs.Add(new LinqTestInput( + "OrderBy(Log(Where -> Count))", b => getQuery(b) + .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); + + // ------------------------------------------------------------------ + // Expression with subquery lambdas -> more transformations + // ------------------------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) + .OrderBy(f => f.ChildrenCount) + .Take(10))); + // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 + //inputs.Add(new LinqTestInput( + // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) + // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) + // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) + // .OrderBy(f => f.FamilyId) + // .Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), + FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null + }) + .Where(f => f.FirstChild != null) + .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); + + inputs.Add(new LinqTestInput( + "Select(new (Select(new (Select, Select))))", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + ChildrenProfile = f.Children.Select(c => new + { + Fullname = c.GivenName + " " + c.FamilyName, + PetNames = c.Pets.Select(p => p.GivenName), + ParentNames = f.Parents.Select(p => p.GivenName) + }) + }))); + + // ------------------------------------------------ + // Subquery lambda -> subquery lamda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "Select(array) -> Where(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum())", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); + + inputs.Add(new LinqTestInput( + "Select(Select) -> Select(Sum(map))", b => getQuery(b) + .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) + .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) + .Select(f => f.Children.Sum(c => c.Pets.Count())))); + + // ------------------------------ + // Nested subquery lambdas + // ------------------------------ + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "Select(Select(Select))", b => getQuery(b) + .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); + + inputs.Add(new LinqTestInput( + "Select(Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); + + inputs.Add(new LinqTestInput( + "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) + .Select(f => f.Children + .Where(c => c.Pets + .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") + .Count() > 0) + .Select(c => new + { + HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 + })))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select(Select))", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where(Any))", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Where(Count) -> Count)", b => getQuery(b) + .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); + + inputs.Add(new LinqTestInput( + "Where(Where(Where -> Count) -> Count)", b => getQuery(b) + .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); + + inputs.Add(new LinqTestInput( + "Where(Select(Select -> Any))", b => getQuery(b) + .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + // ------------------------------------- + // Expression -> Subquery lambdas + // ------------------------------------- + + inputs.Add(new LinqTestInput( + "Select(new) -> Select(Select)", b => getQuery(b) + .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 80)) + .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) + .Select(c => c.Pets.Select(p => p.GivenName.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) + .Distinct() + .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) + .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); + + inputs.Add(new LinqTestInput( + "Where -> Select(Select)", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Distinct -> Select(Select)", b => getQuery(b) + .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); + + inputs.Add(new LinqTestInput( + "Take -> Select(Select)", b => getQuery(b) + .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); + + // ------------------ + // Any in lambda + // ------------------ + + inputs.Add(new LinqTestInput( + "Select(Any w const array)", b => getQuery(b) + .Select(f => new int[] { 1, 2, 3 }.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any)", b => getQuery(b) + .Select(f => f.Children.Any()))); + + inputs.Add(new LinqTestInput( + "Select(Any w lambda)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Grade > 80)))); + + inputs.Add(new LinqTestInput( + "Select(new Any)", b => getQuery(b) + .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(new 2 Any)", b => getQuery(b) + .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); + + inputs.Add(new LinqTestInput( + "Select(Nested Any)", b => getQuery(b) + .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); + + inputs.Add(new LinqTestInput( + "Where(Any)", b => getQuery(b) + .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); + + // Customer requested scenario + inputs.Add(new LinqTestInput( + "Where(simple expr && Any)", b => getQuery(b) + .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); + + // ------------------------------------------------ + // SelectMany with Take and OrderBy in lambda + // ------------------------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany(Take)", b => getQuery(b) + .SelectMany(f => f.Children.Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(OrderBy)", b => getQuery(b) + .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> Take -> Select)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByTranslation() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => key /*return the group by key */))); + inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (stringField, values) => stringField /*return the group by key */))); + + + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Count() /*return the Count of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); + + // Negative cases + + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Min() /*return the Min of each group */))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => values.Max() /*return the Max of each group */))); + + // Unsupported node type + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Incorrect number of arguments + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( + k => k.Int, + k2 => k2.Int, + (key, values) => "string" /* Unsupported Nodetype*/ ))); + + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); + inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); + + // Currently unsupported case + inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); + + // Other methods followed by GroupBy + + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) + .SelectMany(f => f.Children) + .Where(c => c.Pets.Count() > 0) + .SelectMany(c => c.Pets.Select(p => p.GivenName)) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // The result for this is not correct yet - the select clause is wrong + inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .Where(x => x.Children.Min(y => y.Grade) > 10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); + + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Select(x => x))); + + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10))); + + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a"))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderBy(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .OrderByDescending(x => x))); + + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .Where(x => x == "a").Skip(10).Take(10))); + + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) + .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestGroupByMultiValueTranslation() { List inputs = new List(); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Constant", b => getQuery(b).GroupBy(k => k /*keySelector*/, + (key, values) => + new { + stringField = "abv", + numField = 123 + }))); - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(Where -> SelectMany(Where -> Select))", - b => getQuery(b) - .SelectMany(family => family.Children.Where(c => c.Grade > 10) - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))))); - - inputs.Add(new LinqTestInput("SelectMany(SelectMany(Where -> Select new {}))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Select)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Where)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Key = key, + key + }))); - inputs.Add(new LinqTestInput( - "SelectMany(Select) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Select(n => n.Count()))); + inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key and Constant", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + KeyAlias = key, + values = 123 /* intentionally have the same spelling as the IGrouping values */ + }))); - inputs.Add(new LinqTestInput("SelectMany()", b => getQuery(b).SelectMany(root => root.Children))); + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(value => value.Int), + Max = values.Max(value => value.Int), + Avg = values.Average(value => value.Int), + Count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany -> SelectMany", b => getQuery(b).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + inputs.Add(new LinqTestInput("GroupBy Multi Value With Property Ref and Aggregate", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, + (key, values) => new { + familyId = key, + familyIdCount = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children).Where(c => c.Pets.Count() > 0).SelectMany(c => c.Pets.Select(p => p.GivenName)))); + // Negative cases - inputs.Add(new LinqTestInput("SelectMany -> Where -> SelectMany(Select new)", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => new { PetName = p.GivenName, OwnerName = c.GivenName })))); + // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] + // but the behavior between LINQ and SQL is different + // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null + inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate On Root", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + Min = values.Min(), + Max = values.Max() + }))); - inputs.Add(new LinqTestInput("Where -> SelectMany", b => getQuery(b).Where(f => f.Children.Count() > 0).SelectMany(f => f.Children))); + // Non-aggregate method calls + inputs.Add(new LinqTestInput("GroupBy Multi Value With Non-Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, + (key, values) => new { + valueSelect = values.Select(value => value.Int), + valueOrderBy = values.OrderBy(f => f.FamilyId) + }))); + // Other methods followed by GroupBy - inputs.Add(new LinqTestInput("SelectMany -> Select", b => getQuery(b).SelectMany(f => f.Children).Select(c => c.FamilyName))); + inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) + .Select(x => x.Id) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Children.Select(c => c.Pets.Count())))); + inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) + .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) + .GroupBy(k => k.Id1 /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)))); + inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) + .SelectMany(x => x.Children) + .GroupBy(k => k /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select -> Select)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Select(n => n.Count())))); + inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) + .Skip(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Select -> Where)", b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Where(n => n.Count() > 10)))); + inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) + .Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.Take(2).Where(c => c.FamilyName.Count() > 10)))); + inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) + .Skip(10).Take(10) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(OrderBy -> Take -> Where)", b => getQuery(b).SelectMany(f => f.Children.OrderBy(c => c.Grade).Take(2).Where(c => c.FamilyName.Count() > 10)))); + inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("SelectMany(Distinct -> Where)", b => getQuery(b).SelectMany(f => f.Children.Distinct().Where(c => c.FamilyName.Count() > 10)))); + // should this become a subquery with order by then group by? + inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) + .OrderBy(x => x.Int) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - this.ExecuteTestSuite(inputs); - } + inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) + .OrderByDescending(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - [TestMethod] - public void TestSimpleSubquery() - { - List inputs = new List(); + inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) + .Where(x => x.Id != "a") + .OrderBy(x => x.Id) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }))); - inputs.Add(new LinqTestInput("Select -> Select", b => getQuery(b).Select(f => f.FamilyId).Select(n => n.Count()))); + // GroupBy followed by other methods + inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x))); - inputs.Add(new LinqTestInput("Select -> Where", b => getQuery(b).Select(f => f.FamilyId).Where(id => id.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + Select 2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Select(x => x.keyAlias))); - inputs.Add(new LinqTestInput("Select -> OrderBy -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(x => x).OrderBy(x => x).Take(10).Select(f => f.FamilyId).OrderBy(n => n.Count()).Take(5))); + //We should support skip take + inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10))); - inputs.Add(new LinqTestInput("Select -> Orderby -> Take -> Select -> Orderby -> Take", b => getQuery(b).Select(f => f).OrderBy(f => f.Children.Count()).Take(3).Select(x => x).OrderBy(f => f.Parents.Count()).Take(2))); + inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Take(10))); - inputs.Add(new LinqTestInput("Orderby -> Take -> Orderby -> Take", b => getQuery(b).OrderBy(f => f.Children.Count()).Take(3).OrderBy(f => f.Parents.Count()).Take(2))); + inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Skip(10).Take(10))); - inputs.Add(new LinqTestInput("Take -> Orderby -> Take", b => getQuery(b).Take(10).OrderBy(f => f.FamilyId).Take(1))); + inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a"))); - inputs.Add(new LinqTestInput("Take -> Where -> Take -> Where -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Take(9).Where(f => f.Parents.Count() > 0).Take(8).Where(f => f.FamilyId.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderBy(x => x.keyAlias))); - inputs.Add(new LinqTestInput("Take -> Where -> Distinct -> Select -> Take -> Where", b => getQuery(b).Take(10).Where(f => f.Children.Count() > 0).Distinct().Select(f => new { f }).Take(8).Where(f => f.f.FamilyId.Count() > 10))); + inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .OrderByDescending(x => x.count))); - inputs.Add(new LinqTestInput("Distinct -> Select -> Take -> Where -> Take -> Where", b => getQuery(b).Distinct().Select(f => new { f }).Take(10).Where(f => f.f.Children.Count() > 0).Take(9).Where(f => f.f.Parents.Count() > 0))); + inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .Where(x => x.keyAlias == "a").Skip(10).Take(10))); - this.ExecuteTestSuite(inputs); - } + inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count()}) + .GroupBy(k => k.count /*keySelector*/, (key, values) => key /*return the group by key */))); - [TestMethod] - public void TestQueryFlattening() - { - // these queries should make more sense when combined with where and orderby - // these tests verify the flattening part - List inputs = new List(); - inputs.Add(new LinqTestInput("array create", b => getQuery(b).Select(f => f.Int).Select(i => new int[] { i }))); - inputs.Add(new LinqTestInput("unary operation", b => getQuery(b).Select(f => f.Int).Select(i => -i))); - inputs.Add(new LinqTestInput("binary operation", b => getQuery(b).Select(f => f).Select(i => i.Int % 10 * i.Children.Count()))); - inputs.Add(new LinqTestInput("literal", b => getQuery(b).Select(f => f.Int).Select(i => 0))); - inputs.Add(new LinqTestInput("function call", b => getQuery(b).Select(f => f.Parents).Select(p => p.Count()))); - inputs.Add(new LinqTestInput("object create", b => getQuery(b).Select(f => f.Parents).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("conditional", b => getQuery(b).Select(f => f.Children).Select(c => c.Count() > 0 ? "have kids" : "no kids"))); - inputs.Add(new LinqTestInput("property ref + indexer", b => getQuery(b).Select(f => f) - .Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0) - .Select(f => f.Children[0].Pets[0].GivenName))); + inputs.Add(new LinqTestInput("GroupBy + GroupBy2", b => getQuery(b) + .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { + keyAlias = key, + count = values.Count() + }) + .GroupBy(k => k.count /*keySelector*/, (key, values) => new { + keyAlias = key, + stringField = "abc" + }))); - inputs.Add(new LinqTestInput("array creation -> indexer", b => getQuery(b).Select(f => new int[] { f.Int }).Select(array => array[0]))); - inputs.Add(new LinqTestInput("unary, indexer, property, function call -> function call", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => -f.Children[0].Pets.Count()).Select(i => Math.Abs(i)))); - inputs.Add(new LinqTestInput("binary operation, function call -> conditional", b => getQuery(b).Select(i => i.Int % 10 * i.Children.Count()).Select(i => i > 0 ? new int[] { i } : new int[] { }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b) - .Select(f => new { parentCount = f.Parents.Count(), childrenCount = f.Children.Count() }) - .Select(r => r.parentCount > 0 ? Math.Floor((double)r.childrenCount / r.parentCount) : 0))); - inputs.Add(new LinqTestInput("indexer -> function call", b => getQuery(b).Select(f => f.Parents[0]).Select(p => string.Concat(p.FamilyName, p.GivenName)))); - inputs.Add(new LinqTestInput("conditional -> object creation", b => getQuery(b).Select(f => f.Parents.Count() > 0 ? f.Parents : new Parent[0]).Select(p => new { parentCount = p.Count() }))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { children = f.Children }).Select(c => c.children.Count() > 0 ? c.children[0].GivenName : "no kids"))); - inputs.Add(new LinqTestInput("object creation -> conditional", b => getQuery(b).Select(f => new { family = f, children = f.Children.Count() }).Select(f => f.children > 0 && f.family.Children[0].Pets.Count() > 0 ? f.family.Children[0].Pets[0].GivenName : "no kids"))); this.ExecuteTestSuite(inputs); } [TestMethod] - public void TestSubquery() - { - List inputs = new List(); - - // -------------------------------------- - // Subquery lambdas - // -------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Take)", b => getQuery(b) - .Select(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "Select(Where)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(Distinct)", b => getQuery(b) - .Select(f => f.Children.Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(Count)", b => getQuery(b) - .Select(f => f.Children.Count(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(Sum)", b => getQuery(b) - .Select(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Count)", b => getQuery(b) - .Where(f => f.Children.Count(c => c.Pets.Count() > 0) > 0))); - - inputs.Add(new LinqTestInput( - "Where(Sum)", b => getQuery(b) - .Where(f => f.Children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "OrderBy(Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Count)", b => getQuery(b) - .OrderBy(f => f.Children.Count(c => c.Grade > 90)))); - - // ------------------------------------------------------------- - // Mutilpe-transformations subquery lambdas - // ------------------------------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(Select -> Distinct -> Count)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Gender).Distinct().Count()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Sum)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Select(c => c.GivenName).OrderBy(n => n.Length).Take(1)))); - - inputs.Add(new LinqTestInput( - "Select(SelectMany -> Select)", b => getQuery(b) - .Select(f => f.Children.SelectMany(c => c.Pets).Select(c => c.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Count)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Count()))); - - inputs.Add(new LinqTestInput( - "Select(Where -> OrderBy -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).OrderBy(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets.Count()).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(Where -> Select(array) -> Take)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50).Select(c => c.Pets).Take(3)))); - - inputs.Add(new LinqTestInput( - "Select(where -> Select -> Distinct)", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 50 && c.Pets.Count() > 0).Select(c => c.Gender).Distinct()))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Grade).Take(1).Select(c => c.Gender)))); - - inputs.Add(new LinqTestInput( - "Select(OrderBy -> Take -> Select -> Average)", b => getQuery(b) - .Select(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Select(c => c.Grade).Average()))); - - inputs.Add(new LinqTestInput( - "Where(Select -> Count)", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Count()).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Where -> Sum)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Sum(c => c.Grade) < 200))); - - inputs.Add(new LinqTestInput( - "Where(Where -> OrderBy -> Take -> Select)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).OrderBy(c => c.Grade).Take(1).Where(c => c.Grade > 80).Count() > 0))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Where)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Pets.Count()).Where(x => x > 1)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Where -> Count)", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Pets.Count() > 3).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy(Select -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.Select(c => c.Grade).Sum()))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> Take -> Sum)", b => getQuery(b) - .OrderBy(f => f.Children.OrderBy(c => c.Pets.Count()).Take(2).Sum(c => c.Grade)))); - - // --------------------------------------------------------- - // Scalar and Built-in expressions with subquery lambdas - // --------------------------------------------------------- - - // Unary - - inputs.Add(new LinqTestInput( - "Where(unary (Where -> Count))", b => getQuery(b) - .Where(f => -f.Children.Where(c => c.Grade < 20).Count() == 0))); - - // Binary - - inputs.Add(new LinqTestInput( - "Select(binary with Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "Select(constant + Where -> Count)", b => getQuery(b) - .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); - - inputs.Add(new LinqTestInput( - "Where((Where -> Count) % constant)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Count() > 0).Count() % 2 == 1))); - - // Conditional - - inputs.Add(new LinqTestInput( - "Select(conditional Any ? Select : Select)", b => getQuery(b) - .Select(f => f.Children.Any() ? f.Children.Select(c => c.GivenName) : f.Parents.Select(p => p.GivenName)))); - - inputs.Add(new LinqTestInput( - "Select(conditional Any(filter) ? Max : Sum)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 97) ? f.Children.Max(c => c.Grade) : f.Children.Sum(c => c.Grade)))); - - // New array - - inputs.Add(new LinqTestInput( - "Select(new array)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - // New + member init - - inputs.Add(new LinqTestInput( - "Select(new)", b => getQuery(b) - .Select(f => new int[] { f.Children.Count(), f.Children.Sum(c => c.Grade) }))); - - inputs.Add(new LinqTestInput( - "Select(Select new)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenPetCount = f.Children.Select(c => c.Pets.Count()) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where)", b => getQuery(b) - .Select(f => new { f.FamilyId, GoodChildren = f.Children.Where(c => c.Grade > 90) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 3).Select(c => c.GivenName) }))); - - inputs.Add(new LinqTestInput( - "Select(new Where -> Count) -> Where", b => getQuery(b) - .Select(f => new { Family = f, ChildrenCount = f.Children.Where(c => c.Grade > 0).Count() }).Where(f => f.ChildrenCount > 0))); - - // Array builtin functions - - inputs.Add(new LinqTestInput( - "Select(Where -> Concat(Where))", b => getQuery(b) - .Select(f => f.Children.Where(c => c.Grade > 90).Concat(f.Children.Where(c => c.Grade < 10))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Sum))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Sum(c => c.Pets.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select -> Contains(Where -> Count))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade).Contains(f.Children.Where(c => c.Grade > 50).Count())))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Where -> Select(array indexer)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Grade > 20).Count() >= 2) - .Select(f => f.Children.Where(c => c.Grade > 20).ToArray()[f.Children.Count() % 2]))); - - // Math builtin functions - - inputs.Add(new LinqTestInput( - "Select(Floor(sum(map), sum(map)))", b => getQuery(b) - .Select(f => Math.Floor(1.0 * f.Children.Sum(c => c.Grade) / (f.Children.Sum(c => c.Pets.Count()) + 1))))); - - inputs.Add(new LinqTestInput( - "Select(Pow(Sum(map), Count(Any)))", b => getQuery(b) - .Select(f => Math.Pow(f.Children.Sum(c => c.Pets.Count()), f.Children.Count(c => c.Pets.Any(p => p.GivenName.Count() == 0 || p.GivenName.Substring(0, 1) == "A")))))); - - inputs.Add(new LinqTestInput( - "OrderBy(Log(Where -> Count))", b => getQuery(b) - .OrderBy(f => Math.Log(f.Children.Where(c => c.Pets.Count() > 0).Count())))); - - // ------------------------------------------------------------------ - // Expression with subquery lambdas -> more transformations - // ------------------------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - .Where(f => f.FamilyId.CompareTo("ABC") > 0 && f.SmartChildren.Count() > 0) - .OrderBy(f => f.ChildrenCount) - .Take(10))); - // TODO https://github.com/Azure/azure-cosmos-dotnet-v3/issues/375 - //inputs.Add(new LinqTestInput( - // "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) - // .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), SmartChildren = f.Children.Where(c => c.Grade > 90) }) - // .Where(f => f.ChildrenCount > 2 && f.SmartChildren.Count() > 1) - // .OrderBy(f => f.FamilyId) - // .Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new { Select(Select), conditional Count Take }) -> Where -> Select(Select(Any))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenPetFirstChars = f.Children.Select(c => c.Pets.Select(p => p.GivenName.Substring(0, 1))), - FirstChild = f.Children.Count() > 0 ? f.Children.Take(1) : null - }) - .Where(f => f.FirstChild != null) - .Select(f => f.ChildrenPetFirstChars.Select(chArray => chArray.Any(a => f.FamilyId.StartsWith(a)))))); - - inputs.Add(new LinqTestInput( - "Select(new (Select(new (Select, Select))))", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - ChildrenProfile = f.Children.Select(c => new - { - Fullname = c.GivenName + " " + c.FamilyName, - PetNames = c.Pets.Select(p => p.GivenName), - ParentNames = f.Parents.Select(p => p.GivenName) - }) - }))); - - // ------------------------------------------------ - // Subquery lambda -> subquery lamda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "Select(array) -> Where(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Where(children => children.Sum(c => c.Grade) > 100))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum())", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Grade)).Select(children => children.Sum()))); - - inputs.Add(new LinqTestInput( - "Select(Select) -> Select(Sum(map))", b => getQuery(b) - .Select(f => f.Children).Select(children => children.Sum(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Where(Any binary) -> OrderBy(Count(filter)) -> Select(Sum(map))", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Grade > 90) && f.IsRegistered) - .OrderBy(f => f.Children.Count(c => c.Things.Count() > 3)) - .Select(f => f.Children.Sum(c => c.Pets.Count())))); - - // ------------------------------ - // Nested subquery lambdas - // ------------------------------ - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "Select(Select(Select))", b => getQuery(b) - .Select(f => f.Children.Select(c => c.Pets.Select(p => p))))); - - inputs.Add(new LinqTestInput( - "Select(Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "Where -> Select(conditional ? Take : OrderBy -> Array indexer)", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .Select(f => f.Children.Count() == 1 ? f.Children.Take(1).ToArray()[0] : f.Children.OrderBy(c => c.Grade).ToArray()[1]))); - - inputs.Add(new LinqTestInput( - "Select(Where(Where -> Count) -> Select(new Count))", b => getQuery(b) - .Select(f => f.Children - .Where(c => c.Pets - .Where(p => p.GivenName.Count() > 10 && p.GivenName.Substring(0, 1) == "A") - .Count() > 0) - .Select(c => new - { - HasSiblingWithSameStartingChar = f.Children.Count(child => (child.GivenName + " ").Substring(0, 1) == (c.GivenName + " ").Substring(0, 1)) > 1 - })))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select(Select))", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName.Count()))))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where(Any))", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Where(Count) -> Count)", b => getQuery(b) - .Where(f => f.Parents.Where(p => p.FamilyName.Count() > 10).Count() > 1))); - - inputs.Add(new LinqTestInput( - "Where(Where(Where -> Count) -> Count)", b => getQuery(b) - .Where(f => f.Children.Where(c => c.Pets.Where(p => p.GivenName.Count() > 15).Count() > 0).Count() > 0))); - - inputs.Add(new LinqTestInput( - "Where(Select(Select -> Any))", b => getQuery(b) - .Where(f => f.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - // ------------------------------------- - // Expression -> Subquery lambdas - // ------------------------------------- - - inputs.Add(new LinqTestInput( - "Select(new) -> Select(Select)", b => getQuery(b) - .Select(f => new { f.FamilyId, Family = f }).Select(f => f.Family.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where) -> Where(Any) -> Select(Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 80)) - .Where(c => c.Pets.Any(p => p.GivenName.Count() > 20)) - .Select(c => c.Pets.Select(p => p.GivenName.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(new) -> Where(Select(Select -> Any))", b => getQuery(b) - .Distinct() - .Select(f => new { f.FamilyId, ChildrenCount = f.Children.Count(), Family = f }) - .Where(f => f.Family.Children.Select(c => c.Pets.Select(p => p.GivenName)).Any(t => t.Count() > 3)))); - - inputs.Add(new LinqTestInput( - "Where -> Select(Select)", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Distinct -> Select(Select)", b => getQuery(b) - .Distinct().Select(f => f.Children.Select(c => c.Pets.Count())))); - - inputs.Add(new LinqTestInput( - "Take -> Select(Select)", b => getQuery(b) - .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); - - // ------------------ - // Any in lambda - // ------------------ - - inputs.Add(new LinqTestInput( - "Select(Any w const array)", b => getQuery(b) - .Select(f => new int[] { 1, 2, 3 }.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any)", b => getQuery(b) - .Select(f => f.Children.Any()))); - - inputs.Add(new LinqTestInput( - "Select(Any w lambda)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Grade > 80)))); - - inputs.Add(new LinqTestInput( - "Select(new Any)", b => getQuery(b) - .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(new 2 Any)", b => getQuery(b) - .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - - inputs.Add(new LinqTestInput( - "Select(Nested Any)", b => getQuery(b) - .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); - - inputs.Add(new LinqTestInput( - "Where(Any)", b => getQuery(b) - .Where(f => f.Children.Any(c => c.Pets.Count() > 0)))); - - // Customer requested scenario - inputs.Add(new LinqTestInput( - "Where(simple expr && Any)", b => getQuery(b) - .Where(f => f.FamilyId.Contains("a") && f.Children.Any(c => c.Pets.Count() > 0)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); - - // ------------------------------------------------ - // SelectMany with Take and OrderBy in lambda - // ------------------------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany(Take)", b => getQuery(b) - .SelectMany(f => f.Children.Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(OrderBy)", b => getQuery(b) - .SelectMany(f => f.Children.OrderBy(c => c.Grade)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2)))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> Take -> Select)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.FamilyName.Count() > 10).Take(2).Select(c => c.Grade)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestGroupByTranslation() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => key /*return the group by key */))); - inputs.Add(new LinqTestInput("GroupBy Single Value Select Key Alias", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (stringField, values) => stringField /*return the group by key */))); - - - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Min(value => value.Int) /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Max(value => value.Int) /*return the Max of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Count() /*return the Count of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Average", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Average(value => value.Int) /*return the Count of each group */))); - - // Negative cases - - // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] - // but the behavior between LINQ and SQL is different - // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Min() /*return the Min of each group */))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Max", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => values.Max() /*return the Max of each group */))); - - // Unsupported node type - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.Int /*keySelector*/, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Incorrect number of arguments - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy( - k => k.Int, - k2 => k2.Int, - (key, values) => "string" /* Unsupported Nodetype*/ ))); - - // Non-aggregate method calls - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.Select(value => value.Int) /*Not an aggregate*/))); - inputs.Add(new LinqTestInput("GroupBy Single Value With Count", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => values.OrderBy(f => f.FamilyId) /*Not an aggregate*/))); - - // Currently unsupported case - inputs.Add(new LinqTestInput("GroupBy Single Value With Min", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, - (key, values) => new { familyId = key, familyIdCount = values.Count() } /*multi-value select */))); - - // Other methods followed by GroupBy - - inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) - .Select(x => x.Id) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) - .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) - .GroupBy(k => k.family1 /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) - .SelectMany(x => x.Children) - .GroupBy(k => k.Grade /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy 2", b => getQuery(b) - .SelectMany(f => f.Children) - .Where(c => c.Pets.Count() > 0) - .SelectMany(c => c.Pets.Select(p => p.GivenName)) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) - .Skip(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) - .Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) - .Skip(10).Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // should this become a subquery with order by then group by? - inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) - .OrderBy(x => x.Int) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) - .OrderByDescending(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .OrderBy(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // The result for this is not correct yet - the select clause is wrong - inputs.Add(new LinqTestInput("Combination 2 + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .Where(x => x.Children.Min(y => y.Grade) > 10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */))); - - // GroupBy followed by other methods - inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Select(x => x))); - - //We should support skip take - inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10))); - - inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a"))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderBy(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .OrderByDescending(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .Where(x => x == "a").Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => key /*return the group by key */) - .GroupBy(k => k /*keySelector*/, (key, values) => key /*return the group by key */))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestGroupByMultiValueTranslation() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Constant", b => getQuery(b).GroupBy(k => k /*keySelector*/, - (key, values) => - new { - stringField = "abv", - numField = 123 - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Key = key, - key - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value Select Key and Constant", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - KeyAlias = key, - values = 123 /* intentionally have the same spelling as the IGrouping values */ - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Min = values.Min(value => value.Int), - Max = values.Max(value => value.Int), - Avg = values.Average(value => value.Int), - Count = values.Count() - }))); - - inputs.Add(new LinqTestInput("GroupBy Multi Value With Property Ref and Aggregate", b => getQuery(b).GroupBy(k => k.FamilyId /*keySelector*/, - (key, values) => new { - familyId = key, - familyIdCount = values.Count() - }))); - - // Negative cases - - // The translation is correct (SELECT VALUE MIN(root) FROM root GROUP BY root["Number"] - // but the behavior between LINQ and SQL is different - // In Linq, it requires the object to have comparer traits, where as in CosmosDB, we will return null - inputs.Add(new LinqTestInput("GroupBy Multi Value With Aggregate On Root", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - Min = values.Min(), - Max = values.Max() - }))); - - // Non-aggregate method calls - inputs.Add(new LinqTestInput("GroupBy Multi Value With Non-Aggregate", b => getQuery(b).GroupBy(k => k.Id /*keySelector*/, - (key, values) => new { - valueSelect = values.Select(value => value.Int), - valueOrderBy = values.OrderBy(f => f.FamilyId) - }))); - // Other methods followed by GroupBy - - inputs.Add(new LinqTestInput("Select + GroupBy", b => getQuery(b) - .Select(x => x.Id) - .GroupBy(k => k /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Select + GroupBy 2", b => getQuery(b) - .Select(x => new { Id1 = x.Id, family1 = x.FamilyId, childrenN1 = x.Children }) - .GroupBy(k => k.Id1 /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("SelectMany + GroupBy", b => getQuery(b) - .SelectMany(x => x.Children) - .GroupBy(k => k /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Skip + GroupBy", b => getQuery(b) - .Skip(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Take + GroupBy", b => getQuery(b) - .Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Skip + Take + GroupBy", b => getQuery(b) - .Skip(10).Take(10) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Filter + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - // should this become a subquery with order by then group by? - inputs.Add(new LinqTestInput("OrderBy + GroupBy", b => getQuery(b) - .OrderBy(x => x.Int) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("OrderBy Descending + GroupBy", b => getQuery(b) - .OrderByDescending(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - inputs.Add(new LinqTestInput("Combination + GroupBy", b => getQuery(b) - .Where(x => x.Id != "a") - .OrderBy(x => x.Id) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }))); - - // GroupBy followed by other methods - inputs.Add(new LinqTestInput("GroupBy + Select", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Select(x => x))); - - inputs.Add(new LinqTestInput("GroupBy + Select 2", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Select(x => x.keyAlias))); - - //We should support skip take - inputs.Add(new LinqTestInput("GroupBy + Skip", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Skip(10))); - - inputs.Add(new LinqTestInput("GroupBy + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Skip + Take", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + Filter", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Where(x => x.keyAlias == "a"))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .OrderBy(x => x.keyAlias))); - - inputs.Add(new LinqTestInput("GroupBy + OrderBy Descending", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .OrderByDescending(x => x.count))); - - inputs.Add(new LinqTestInput("GroupBy + Combination", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .Where(x => x.keyAlias == "a").Skip(10).Take(10))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count()}) - .GroupBy(k => k.count /*keySelector*/, (key, values) => key /*return the group by key */))); - - inputs.Add(new LinqTestInput("GroupBy + GroupBy2", b => getQuery(b) - .GroupBy(k => k.Id /*keySelector*/, (key, values) => new { - keyAlias = key, - count = values.Count() - }) - .GroupBy(k => k.count /*keySelector*/, (key, values) => new { - keyAlias = key, - stringField = "abc" - }))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void DebuggingTest() - { - - } - - [TestMethod] - [Owner("khdang")] - [Ignore] - public void TestSkipTake() - { - //TODO - //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders - //This will be fine once we convert these test cases to use V3 pipeline - - List inputs = new List(); - - // -------------------------------- - // Skip - Take combinations - // -------------------------------- - - inputs.Add(new LinqTestInput( - "Skip", b => getQuery(b) - .Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take", b => getQuery(b) - .Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Skip(negative number) -> Take", b => getQuery(b) - .Skip(-1).Take(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take(negative number)", b => getQuery(b) - .Skip(1).Take(-2))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take", b => getQuery(b) - .Skip(1).Skip(2).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take", b => getQuery(b) - .Skip(3).Take(5).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(2).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Take -> Skip", b => getQuery(b) - .Skip(1).Take(2).Take(3).Skip(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Skip -> Take -> Take", b => getQuery(b) - .Skip(5).Skip(2).Take(10).Take(3))); - - inputs.Add(new LinqTestInput( - "Take -> Skip", b => getQuery(b) - .Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip", b => getQuery(b) - .Take(2).Take(3).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip", b => getQuery(b) - .Take(3).Skip(1).Skip(2))); - - inputs.Add(new LinqTestInput( - "Take -> Take -> Skip -> Skip", b => getQuery(b) - .Take(5).Take(3).Skip(1).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Take -> Skip", b => getQuery(b) - .Take(10).Skip(2).Take(5).Skip(1))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(4).Skip(2).Take(2))); - - // -------------------------- - // Select + Skip & Take - // -------------------------- - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2))); - - inputs.Add(new LinqTestInput( - "Select -> Take -> Skip", b => getQuery(b) - .Select(f => f.FamilyId).Take(2).Skip(1))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> Select", b => getQuery(b) - .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) - .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Select(f => f.FamilyId).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> Select -> Skip", b => getQuery(b) - .Take(7).Select(f => f.FamilyId).Skip(3))); - - // ------------------------------ - // SelectMany + Skip & Take - // ------------------------------ - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Skip(7).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) - .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) - .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) - .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); - - // --------------------------- - // Where + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip", b => getQuery(b) - .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); - - inputs.Add(new LinqTestInput( - "Take -> Where -> Skip", b => getQuery(b) - .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); - - inputs.Add(new LinqTestInput( - "Where -> Take -> Skip -> Where", b => getQuery(b) - .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); - - // --------------------------- - // OrderBy + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) - .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> OrderBy", b => getQuery(b) - .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "Take -> OrderByDescending -> Skip", b => getQuery(b) - .Take(50).OrderByDescending(f => f.Int).Skip(13))); - - inputs.Add(new LinqTestInput( - "Skip -> OrderByDescending -> Take", b => getQuery(b) - .Skip(7).OrderByDescending(f => f.Int).Take(17))); - - // --------------------------- - // Distinct + Skip & Take - // --------------------------- - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> Take", b => getQuery(b) - .Distinct().Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Distinct", b => getQuery(b) - .Skip(3).Take(11).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) - .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(7).Distinct().Skip(20).Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Skip -> Distinct -> Skip", b => getQuery(b) - .Take(30).Skip(10).Distinct().Skip(7))); - - // --------------------------------------------------------------------------------- - // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between - // --------------------------------------------------------------------------------- - - // Select, SelectMany - - inputs.Add(new LinqTestInput( - "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); - - inputs.Add(new LinqTestInput( - "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) - .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); - - inputs.Add(new LinqTestInput( - "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) - .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); - - // Select, Where - - inputs.Add(new LinqTestInput( - "Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); - - // Select, OrderBy - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> OrderBy", b => getQuery(b) - .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) - .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); - - // Select, Distinct - - inputs.Add(new LinqTestInput( - "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) - .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); - - // SelectMany, Where - - inputs.Add(new LinqTestInput( - "SelectMany -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> SelectMany -> Take", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); - - // SelectMany, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) - .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // SelectMany, Distinct - - inputs.Add(new LinqTestInput( - "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); - - inputs.Add(new LinqTestInput( - "Distinct -> Skip -> SelectMany", b => getQuery(b) - .Distinct().Skip(3).SelectMany(f => f.Children))); - - // Where, OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); - - inputs.Add(new LinqTestInput( - "Skip -> Where -> Take -> OrderBy", b => getQuery(b) - .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); - - // Where, Distinct - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> Distinct", b => getQuery(b) - .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); - - inputs.Add(new LinqTestInput( - "Skip -> Distinct -> Where -> Take", b => getQuery(b) - .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); - - // ----------------------------------------- - // All basic operations with Skip & Take - // ----------------------------------------- - - // Start with Select - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) - .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) - .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); - - inputs.Add(new LinqTestInput( - "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) - .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) - .Skip(1).Select(f => f.L1) - .Skip(2).Select(f => f.L2) - .Skip(3).Select(f => f.L3) - .Skip(4).Select(f => f.L4) - .Skip(5).Select(f => f.Records) - .Skip(6).Select(f => f.Transactions) - .Skip(7).Where(t => t.Count() > 100) - .Take(20))); - - inputs.Add(new LinqTestInput( - "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) - .Select(f => new { L1 = f }) - .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) - .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) - .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) - .Skip(4).Take(25))); - - // Start with Distinct - - inputs.Add(new LinqTestInput( - "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); - - // Start with Where - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) - .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.Int > 20).Skip(5).Take(20) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); - - // Start with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Int).Skip(1).Take(10) - .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); - - // Start with Skip - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); - - inputs.Add(new LinqTestInput( - "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) - .Skip(2).Take(10).Where(f => f.Int > 10) - .Skip(1).Take(9).OrderBy(f => f.FamilyId) - .Skip(3).Take(5).Select(f => f.Children.Count()) - .Skip(1).Distinct() - .Skip(1).Take(1))); - - // Start with Take - - inputs.Add(new LinqTestInput( - "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) - .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) - .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); - - // ----------------------------------------------------------------------------- - // All basic operations with Skip & Take with SelectMany in the middle - // ----------------------------------------------------------------------------- - - // SelectMany after Take - - inputs.Add(new LinqTestInput( - "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => f.Records).Skip(1).Take(10) - .SelectMany(r => r.Transactions).Skip(1).Take(9))); - - // SelectMany after Where - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) - .Where(f => f.IsRegistered) - .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); - - // Start with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children) - .Select(c => c.FamilyName).Skip(1).Take(20) - .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); - - // ------------------------------------------------------------- - // Nested Skip & Take in Select, SelectMany, Where, OrderBy - // ------------------------------------------------------------- - - // Nested with Select - - inputs.Add(new LinqTestInput( - "Select(new(Where -> Skip)) -> Where", b => getQuery(b) - .Select(f => new { - id = f.FamilyId, - GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) - }) - .Where(f => f.GoodChildren.Count() > 0))); - - inputs.Add(new LinqTestInput( - "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) - .Select(f => new { - v0 = f.Children.Skip(1).Take(2), - v1 = f.Parents.Skip(1), - v2 = f.Records.Transactions.Take(10) - }) - .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); - - inputs.Add(new LinqTestInput( - "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) - .Select(f => new { - v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), - v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), - v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() - }) - .Where(f => f.v2 > 100).Skip(5).Take(20) - .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); - - inputs.Add(new LinqTestInput( - "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) - .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); - - // Nested with Where - - inputs.Add(new LinqTestInput( - "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); - - // Nested with OrderBy - - inputs.Add(new LinqTestInput( - "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) - .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); - - // Nested with SelectMany - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) - .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); - - inputs.Add(new LinqTestInput( - "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) - .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); - - inputs.Add(new LinqTestInput( - "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) - .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestUnsupportedScenarios() - { - List inputs = new List(); - - // -------------------- - // Dictionary type - // -------------------- - - // Iterating through Dictionary type - inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); - - // Get a count of a Dictionary type - inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestOrderByTranslation() - { - List inputs = new List(); - - // Ascending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy query", - b => from f in getQuery(b) - orderby f.FamilyId - select f)); - inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - - // Descending - inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); - inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", - b => from f in getQuery(b) - where f.Int == 5 && f.NullableInt != null - orderby f.IsRegistered descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f)); - inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", - b => from f in getQuery(b) - orderby f.FamilyId descending - select f.FamilyId)); - inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); - inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); - inputs.Add(new LinqTestInput("OrderBy multiple expressions", - b => from f in getQuery(b) - orderby f.FamilyId, f.Int - select f.FamilyId)); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLambdaReuse() - { - List inputs = new List(); - - System.Linq.Expressions.Expression> predicate = f => f.Int == 5; - inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); - inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); - - System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; - inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", - b => getQuery(b) - .Where(predicate2) - .Select(c => new { Int = 10, Result = c }) - .Where(predicate2))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestThenByTranslation() - { - List inputs = new List(); - - // Ascending and descending - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenBy(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderByDescending -> ThenByDescending", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .ThenByDescending(f => f.Int))); - - // Subquery in OrderBy or in ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - // OrderBy and ThenBy by the same property (not a realistic scenario) - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenByDescending", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.FamilyId))); - - inputs.Add(new LinqTestInput( - "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) - .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // OrderBy and ThenBy with epxressions - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.Int * 2) - .ThenBy(f => f.FamilyId.Substring(2, 3)))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderBy(f => !f.NullableInt.IsDefined()) - .ThenByDescending(f => f.Tags.Count() % 2))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) - .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); - - // Multiple OrderBy and ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) - .OrderByDescending(f => f.FamilyId) - .OrderBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenBy(f => f.Int) - .ThenByDescending(f => f.IsRegistered))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) - .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) - .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); - - // Nested ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenBy(c => c.Pets.Count)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // Nested expressions with ThenBy - - inputs.Add(new LinqTestInput( - "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) - .OrderBy(f => f.FamilyId) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Take(1) - .Select(p => p.FamilyName + p.GivenName)))); - - inputs.Add(new LinqTestInput( - "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) - .OrderBy(f => f.Children - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count) - .Take(10) - .OrderByDescending(c => c.GivenName) - .ThenBy(c => c.Gender)) - .ThenByDescending(f => f.Parents - .OrderBy(p => p.FamilyName) - .ThenByDescending(p => p.GivenName) - .Select(p => p.FamilyName + p.GivenName)))); - - // On a new object - - inputs.Add(new LinqTestInput( - "Select -> OrderBy -> ThenBy", b => getQuery(b) - .Select(f => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - }) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber)))); - - inputs.Add(new LinqTestInput( - "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) - .SelectMany(f => f.Children.Select(c => new - { - f.FamilyId, - FamilyNumber = f.Int, - ChildrenCount = f.Children.Count(), - Name = c.GivenName, - SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() - })) - .OrderBy(r => r.FamilyId) - .ThenBy(r => r.FamilyNumber) - .Select(r => r.FamilyId))); - - inputs.Add(new LinqTestInput( - "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) - .Select(f => new { - ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), - TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) - }) - .OrderByDescending(r => r.ChildrenWithPets.Count()) - .ThenByDescending(r => r.TotalExpenses))); - - inputs.Add(new LinqTestInput( - "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) - .Select(f => new { - ParentGivenName = f.Parents.Min(p => p.GivenName), - ParentCount = f.Parents.Count(), - GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), - UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() - }) - .OrderByDescending(r => r.GoodChildrenCount) - .ThenBy(r => r.UniquePetsNameCount))); - - // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates - - inputs.Add(new LinqTestInput( - "Where -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Take(3))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderByDescending(c => c.Grade) - .ThenBy(c => c.GivenName) - .Skip(2) - .Take(20) - .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) - .Select(c => c.GivenName) - .Distinct())); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children) - .OrderBy(c => c.Grade) - .ThenByDescending(c => c.Pets.Count()) - .Select(c => c.GivenName) - .Distinct() - .Take(10) - .Skip(5) - .OrderBy(n => n.Length))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Records.Transactions) - .OrderBy(t => t.Type) - .ThenBy(t => t.Amount) - .Take(100))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) - .Take(100) - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int) - .Skip(5))); - - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Distinct() - .OrderBy(f => f.IsRegistered) - .ThenByDescending(f => f.Int))); - - inputs.Add(new LinqTestInput( - "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) - .Where(f => f.Children.Count() > 0) - .SelectMany(f => f.Children.Select(c => new { - Name = c.GivenName, - PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() - })) - .Distinct() - .OrderByDescending(r => r.Name) - .ThenBy(r => r.PetWithLongNames))); - - inputs.Add(new LinqTestInput( - "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) - .OrderBy(f => f.Children.Any(c => c.Grade > 90)) - .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); - - inputs.Add(new LinqTestInput( - "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) - .OrderBy(f => f.Children.Min(c => c.GivenName)) - .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) - .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) - .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - [Ignore] - public void TestDistinctSelectManyIssues() - { - List inputs = new List(); - - // these tests need a fix in the ServiceInterop - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Distinct -> Take", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestDistinctTranslation() - { - static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) - { - return new LinqTestInput(description, expr, true); - } - - List inputs = new List(); - - // Simple distinct - // Select -> Distinct for all data types - inputs.Add(DistinctTestInput( - "Distinct string", - b => getQuery(b).Select(f => f.FamilyId).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct int", - b => getQuery(b).Select(f => f.Int).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct bool", - b => getQuery(b).Select(f => f.IsRegistered).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct nullable int", - b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct null", - b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct children", - b => getQuery(b).SelectMany(f => f.Children).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct parent", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct family", - b => getQuery(b).Distinct())); - - inputs.Add(DistinctTestInput( - "Multiple distincts", - b => getQuery(b).Distinct().Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct new obj", - b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); - - // Distinct + Take - inputs.Add(DistinctTestInput( - "Distinct -> Take", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); - - inputs.Add(new LinqTestInput( - "Take -> Distinct", - b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); - - // Distinct + Order By - inputs.Add(new LinqTestInput( - "Distinct -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); - - inputs.Add(DistinctTestInput( - "OrderBy -> Distinct", - b => getQuery(b).OrderBy(f => f.Int).Distinct())); - - // Distinct + Order By + Take - inputs.Add(new LinqTestInput( - "Distinct -> Take -> OrderBy", - b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); - - inputs.Add(new LinqTestInput( - "OrderBy -> Take -> Distinct", - b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); - - // Distinct + Where - inputs.Add(DistinctTestInput( - "Where -> Distinct", - b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); - - inputs.Add(DistinctTestInput( - "Distinct -> Where", - b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); - - // SelectMany w Distinct - inputs.Add(DistinctTestInput( - "SelectMany(Select obj) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select)) -> Distinct", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet) - .Distinct())))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => pet.GivenName) - .Select(name => name.Count()))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }).Select(p => p.child)) - .Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }))) - .Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", - b => getQuery(b) - .SelectMany(family => family.Children - .SelectMany(child => child.Pets - .Where(pet => pet.GivenName == "Fluffy") - .Select(pet => new - { - family = family.FamilyId, - child = child.GivenName, - pet = pet.GivenName - }) - .Distinct())))); - - // SelectMany(Distinct) - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .OrderBy(f => f).Take(5).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() - .Take(5).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct())); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .OrderBy(f => f).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Where -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) - .Where(f => f.FamilyName.Count() < 20))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); - - inputs.Add(new LinqTestInput( - "SelectMany(Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Distinct) -> Select -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); - - // SelectMany(Select -> Distinct) - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); - - inputs.Add(new LinqTestInput( - "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct)", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Distinct", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); - - inputs.Add(DistinctTestInput( - "SelectMany(Select -> Distinct) -> Where", - b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); - - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicLinq() - { - List inputs = new List(); - inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); - inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); - inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); - // with parameters - inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); - inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public async Task ValidateLinqQueries() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); - - Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; - Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; - Pet pet = new Pet { GivenName = "Fluffy" }; - Child child = new Child - { - FamilyName = "Merriam", - GivenName = "Jesse", - Gender = "female", - Grade = 1, - Pets = new List() { pet, new Pet() { GivenName = "koko" } }, - Things = new Dictionary() { { "A", "B" }, { "C", "D" } } - }; - - Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; - Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; - - List fList = new List(); - fList.Add(family); - - container.CreateItemAsync(family).Wait(); - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); - Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); - - IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); - Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); - - IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); - Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); - - IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); - Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); - - for (int index = 0; index < 2; index++) - { - IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); - Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); - } - - IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); - Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); - - string nullString = null; - IEnumerable q7 = query.Where(f => nullString == f.FamilyId); - Assert.IsNull(q7.FirstOrDefault()); - - object nullObject = null; - q7 = query.Where(f => f.NullObject == nullObject); - Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); - - q7 = query.Where(f => f.FamilyId == nullString); - Assert.IsNull(q7.FirstOrDefault()); - - IEnumerable q8 = query.Where(f => null == f.FamilyId); - Assert.IsNull(q8.FirstOrDefault()); - - IEnumerable q9 = query.Where(f => f.IsRegistered == false); - Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); - - dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); - Assert.AreEqual(q10.FamilyId, family.FamilyId); - - GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; - container.CreateItemAsync(guidObject).Wait(); - List guidData = new List() { guidObject }; - - IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); - Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); - - IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); - Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); - - ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; - container.CreateItemAsync(arrayObject).Wait(); - - IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); - Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); - - int[] nullArray = null; - q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); - Assert.IsNull(q13.FirstOrDefault()); - - ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; - container.CreateItemAsync(listObject).Wait(); - List listArrayObjectData = new List() { arrayObject, listObject }; - - IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); - Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); - - IEnumerable q15 = query.Where(f => f.NullableInt == null); - Assert.AreEqual(q15.ToList().Count, 0); - - int? nullInt = null; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - q15 = query.Where(f => f.NullableInt == 5); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 5; - q15 = query.Where(f => f.NullableInt == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.NullableInt == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = 3; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - q15 = query.Where(f => f.Int == nullInt.Value); - Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); - - nullInt = null; - q15 = query.Where(f => f.Int == nullInt); - Assert.AreEqual(q15.ToList().Count, 0); - - List v = fList.Where(f => f.Int > nullInt).ToList(); - - q15 = query.Where(f => f.Int < nullInt); - - string doc1Id = "document1:x:'!@TT){}\""; - Document doubleQoutesDocument = new Document() { Id = doc1Id }; - container.CreateItemAsync(doubleQoutesDocument).Wait(); - - IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - where book.Id == doc1Id - select book; - - Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); - - GreatFamily greatFamily = new GreatFamily() { Family = family }; - GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; - container.CreateItemAsync(greatGreatFamily).Wait(); - List greatGreatFamilyData = new List() { greatGreatFamily }; - - IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); - - Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); - - Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; - container.CreateItemAsync(sport).Wait(); - List sportData = new List() { sport }; - - IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); - - Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); - - Sport2 sport2 = new Sport2() { id = "json" }; - container.CreateItemAsync(sport2).Wait(); - List sport2Data = new List() { sport2 }; - - IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); - Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); - Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); - Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); - Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); - - int? nullIntVal = null; - int? nullableIntVal = 5; - - List inputs = new List(); - inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); - inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); - inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); - inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); - inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); - inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); - inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); - inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); - inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); - inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); - inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); - inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); - inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); - inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); - inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); - inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); - inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); - - inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); - inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); - inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); - inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); - inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); - - inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); - inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); - inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); - inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); - this.ExecuteTestSuite(inputs); - } - - internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, - DocumentCollection collection, - string transientProcedure, - out StoredProcedureResponse response) - { - // create - StoredProcedure storedProcedure = new StoredProcedure - { - Id = "storedProcedure" + Guid.NewGuid().ToString(), - Body = transientProcedure - }; - StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; - - // execute - response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; - - // delete - client.Delete(retrievedStoredProcedure.GetIdOrFullName()); - - return response.Response; - } - - [TestMethod] - public void ValidateBasicQuery() - { - this.ValidateBasicQueryAsync().Wait(); - } - - private async Task ValidateBasicQueryAsync() - { - DocumentClient client = TestCommon.CreateClient(true); - Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - - string databaseName = database.Id; - - List queryResults = new List(); - //Simple Equality - IQueryable dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db; - IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); - Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); - queryResults.AddRange(pagedResponse); - } - - Assert.AreEqual(1, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Logical Or - dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName || db.ResourceId == database.ResourceId - select db; - documentQuery = dbQuery.AsDocumentQuery(); - - while (documentQuery.HasMoreResults) - { - queryResults.AddRange(await documentQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(2, queryResults.Count); - Assert.AreEqual(databaseName, queryResults[0].Id); - - //Select Property - IQueryable idQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db.ResourceId; - IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); - - List idResults = new List(); - while (documentIdQuery.HasMoreResults) - { - idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); - } - - Assert.AreEqual(1, idResults.Count); - Assert.AreEqual(database.ResourceId, idResults[0]); - } - - [TestMethod] - public async Task ValidateTransformQuery() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; - DocumentCollection collection = new DocumentCollection - { - Id = Guid.NewGuid().ToString("N"), - PartitionKey = partitionKeyDefinition - }; - collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; - Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); - collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); - int documentsToCreate = 100; - for (int i = 0; i < documentsToCreate; i++) - { - dynamic myDocument = new Document(); - myDocument.Id = "doc" + i; - myDocument.Title = "MyBook"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); - } - - //Read response as dynamic. - IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); - - IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); - DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); - - Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); - Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); - Assert.AreEqual(documentsToCreate, queryResponse.Count); - - foreach (dynamic myBook in queryResponse) - { - Assert.AreEqual(myBook.Title.ToString(), "MyBook"); - } - - cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); - } - - [TestMethod] - public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. - { - Book myDocument = new Book(); - myDocument.Id = Guid.NewGuid().ToString(); - myDocument.Title = "My Book"; //Simple Property. - myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property - myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property - myDocument.Price = 9.99; - myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; - - //Create second document to make sure we have atleast one document which are filtered out of query. - Book secondDocument = new Book - { - Id = Guid.NewGuid().ToString(), - Title = "My Second Book", - Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, - Author = new Author { Name = "Carlos", Location = "Cancun" }, - Price = 25, - Editions = new List() { new Edition() { Name = "First", Year = 1970 } } - }; - - //Unfiltered execution. - IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Simple Equality on custom property", - b => from book in getBookQuery(b) - where book.Title == "My Book" - select book)); - inputs.Add(new LinqTestInput("Nested Property access", - b => from book in getBookQuery(b) - where book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("Array references & Project Author out..", - b => from book in getBookQuery(b) - where book.Languages[0].Name == "English" - select book.Author)); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); - inputs.Add(new LinqTestInput("NumericRange query", - b => from book in getBookQuery(b) - where book.Price < 10 - select book.Author)); - inputs.Add(new LinqTestInput("Or query", - b => from book in getBookQuery(b) - where book.Title == "My Book" || book.Author.Name == "Don" - select book)); - inputs.Add(new LinqTestInput("SelectMany query on a List type.", - b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); - // Below samples are strictly speaking not Any equivalent. But they join and filter "all" - // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Languages - .Where(lng => lng.Name == "English") - .Select(lng => book.Author)))); - inputs.Add(new LinqTestInput("SelectMany", - b => getBookQuery(b).SelectMany(book => - book.Editions - .Where(edition => edition.Year == 2001) - .Select(lng => book.Author)))); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. - { - IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - Document myDocument = new Document(); - Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); - - List inputs = new List(); - inputs.Add(new LinqTestInput("Filter equality on custom property", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title2" - select attachment)); - inputs.Add(new LinqTestInput("Filter equality on custom property #2", - b => from attachment in getAttachmentQuery(b) - where attachment.Title == "My Book Title" - select attachment)); - this.ExecuteTestSuite(inputs); - } - - [TestMethod] - public void TestLinqTypeSystem() - { - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); - Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); - - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); - Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); - Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); - - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); - Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); - - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); - } - - #region DataDocument type tests - - public class BaseDocument - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public string TypeName { get; set; } - } - - public class DataDocument : BaseDocument - { - public int Number { get; set; } - } - - private class QueryHelper - { - private readonly Container container; - - public QueryHelper(Container container) - { - this.container = container; - } - - public IQueryable Query() where T : BaseDocument - { - IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) - .Where(d => d.TypeName == "Hello"); - string queryString = query.ToString(); - return query; - } - } - - [TestMethod] - public async Task ValidateLinqOnDataDocumentType() - { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); - - DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; - container.CreateItemAsync(doc).Wait(); - - QueryHelper queryHelper = new QueryHelper(container); - IEnumerable result = queryHelper.Query(); - Assert.AreEqual(1, result.Count()); - - BaseDocument baseDocument = result.FirstOrDefault(); - Assert.AreEqual(doc.Id, baseDocument.Id); - - BaseDocument iDocument = doc; - IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - - IEnumerable iresult = from f in q - where f.Id == iDocument.Id - select f; - DataDocument id = iresult.FirstOrDefault(); - Assert.AreEqual(doc.Id, id.Id); - } - - #endregion - - #region Book type tests - public class Author - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - public string Location { get; set; } - } - - public class Language - { - public string Name { get; set; } - public string Copyright { get; set; } - } - - public class Edition - { - public string Name { get; set; } - public int Year { get; set; } - } - - public class Book - { - //Verify that we can override the propertyName but still can query them using .NET Property names. - [JsonProperty(PropertyName = "title")] - public string Title { get; set; } - [JsonProperty(PropertyName = "name")] - public string Name { get; set; } - public Language[] Languages { get; set; } - public Author Author { get; set; } - public double Price { get; set; } - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id { get; set; } - public List Editions { get; set; } - } - - [TestMethod] - public async Task ValidateServerSideQueryEvalWithPagination() - { - await this.ValidateServerSideQueryEvalWithPaginationScenario(); - } - - private async Task ValidateServerSideQueryEvalWithPaginationScenario() - { - PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; - ContainerProperties cosmosContainerSettings = new ContainerProperties - { - Id = Guid.NewGuid().ToString(), - PartitionKey = partitionKeyDefinition, - }; - cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; - - Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); - - //Do script post to insert as many document as we could in a tight loop. - string script = @"function() { - var output = 0; - var client = getContext().getCollection(); - function callback(err, docCreated) { - if(err) throw 'Error while creating document'; - output++; - getContext().getResponse().setBody(output); - if(output < 50) - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); - }; - client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; - - StoredProcedureExecuteResponse scriptResponse = null; - int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); - - IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); - int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); - Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); - - } - - #endregion - - public class SpecialAttachment2 //Non attachemnt derived. - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Name { get; set; } - - [JsonProperty(PropertyName = "contentType")] - public string ContentType { get; set; } - - [JsonProperty(PropertyName = Constants.Properties.MediaLink)] - public string Media { get; set; } - - public string Author { get; set; } - public string Title { get; set; } - } - - #region TypeSystem test reference classes - public interface IFooItem { } - - public class FooItem : IFooItem { } - - public class DerivedFooItem : FooItem { } - - public class MyList : List { } - - public class MyTupleList : List> { } - - public class DerivedFooCollection : IList, IEnumerable - { - public int IndexOf(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, IFooItem item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public IFooItem this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(IFooItem item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(IFooItem item) - { - throw new NotImplementedException(); - } - - public void CopyTo(IFooItem[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(IFooItem item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooStringCollection : IList, IEnumerable - { - public int IndexOf(string item) - { - throw new NotImplementedException(); - } - - public void Insert(int index, string item) - { - throw new NotImplementedException(); - } - - public void RemoveAt(int index) - { - throw new NotImplementedException(); - } - - public string this[int index] - { - get - { - throw new NotImplementedException(); - } - set - { - throw new NotImplementedException(); - } - } - - public void Add(string item) - { - throw new NotImplementedException(); - } - - public void Clear() - { - throw new NotImplementedException(); - } - - public bool Contains(string item) - { - throw new NotImplementedException(); - } - - public void CopyTo(string[] array, int arrayIndex) - { - throw new NotImplementedException(); - } - - public int Count - { - get { throw new NotImplementedException(); } - } - - public bool IsReadOnly - { - get { throw new NotImplementedException(); } - } - - public bool Remove(string item) - { - throw new NotImplementedException(); - } - - public IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - } - - public class FooTCollection : List, IEnumerable - { - public new IEnumerator GetEnumerator() - { - throw new NotImplementedException(); - } - } - #endregion - - public override LinqTestOutput ExecuteTest(LinqTestInput input) - { - return LinqTestsCommon.ExecuteTest(input); - } - } -} + [Ignore] + public void DebuggingTest() + { + + } + + [TestMethod] + [Owner("khdang")] + [Ignore] + public void TestSkipTake() + { + //TODO + //V2 using V3 pipeline causing issue on accessing Continuation in CosmosQueryResponseMessageHeaders + //This will be fine once we convert these test cases to use V3 pipeline + + List inputs = new List(); + + // -------------------------------- + // Skip - Take combinations + // -------------------------------- + + inputs.Add(new LinqTestInput( + "Skip", b => getQuery(b) + .Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take", b => getQuery(b) + .Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Skip(negative number) -> Take", b => getQuery(b) + .Skip(-1).Take(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take(negative number)", b => getQuery(b) + .Skip(1).Take(-2))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take", b => getQuery(b) + .Skip(1).Skip(2).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take", b => getQuery(b) + .Skip(3).Take(5).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(2).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Take -> Skip", b => getQuery(b) + .Skip(1).Take(2).Take(3).Skip(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Skip -> Take -> Take", b => getQuery(b) + .Skip(5).Skip(2).Take(10).Take(3))); + + inputs.Add(new LinqTestInput( + "Take -> Skip", b => getQuery(b) + .Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip", b => getQuery(b) + .Take(2).Take(3).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip", b => getQuery(b) + .Take(3).Skip(1).Skip(2))); + + inputs.Add(new LinqTestInput( + "Take -> Take -> Skip -> Skip", b => getQuery(b) + .Take(5).Take(3).Skip(1).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Take -> Skip", b => getQuery(b) + .Take(10).Skip(2).Take(5).Skip(1))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(4).Skip(2).Take(2))); + + // -------------------------- + // Select + Skip & Take + // -------------------------- + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2))); + + inputs.Add(new LinqTestInput( + "Select -> Take -> Skip", b => getQuery(b) + .Select(f => f.FamilyId).Take(2).Skip(1))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> Select", b => getQuery(b) + .Select(f => f.FamilyId).Skip(7).Take(13).Select(f => f.Count()))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Take -> Skip", b => getQuery(b) + .Skip(5).Take(11).Select(f => f.Children.Count()).Take(7).Skip(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Select(f => f.FamilyId).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> Select -> Skip", b => getQuery(b) + .Take(7).Select(f => f.FamilyId).Skip(3))); + + // ------------------------------ + // SelectMany + Skip & Take + // ------------------------------ + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Skip(7).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Skip -> Take -> SelectMany", b => getQuery(b) + .SelectMany(f => f.Children).Skip(11).Take(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> SelectMany", b => getQuery(b) + .Skip(1).SelectMany(f => f.Children).Take(13).Skip(3).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> SelectMany -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).SelectMany(c => c.Pets).Skip(3).Take(4))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> SelectMany -> Skip -> SelectMany", b => getQuery(b) + .Take(50).Skip(25).SelectMany(f => f.Children).Skip(10).SelectMany(c => c.Pets))); + + // --------------------------- + // Where + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0).Skip(7).Take(11).Where(f => f.Tags.Count() > 2).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip", b => getQuery(b) + .Skip(1).Take(25).Where(f => f.Int > 10).Skip(5))); + + inputs.Add(new LinqTestInput( + "Take -> Where -> Skip", b => getQuery(b) + .Take(25).Where(f => f.FamilyId.Contains("A")).Skip(10))); + + inputs.Add(new LinqTestInput( + "Where -> Take -> Skip -> Where", b => getQuery(b) + .Where(f => f.Children.Count() > 1).Take(10).Skip(3).Where(f => f.Int > 0))); + + // --------------------------- + // OrderBy + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> OrderBy -> Take -> Skip", b => getQuery(b) + .OrderBy(f => f.Int).Skip(3).Take(11).OrderBy(f => f.FamilyId).Take(7).Skip(1))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> OrderBy", b => getQuery(b) + .Skip(3).Take(43).OrderBy(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "Take -> OrderByDescending -> Skip", b => getQuery(b) + .Take(50).OrderByDescending(f => f.Int).Skip(13))); + + inputs.Add(new LinqTestInput( + "Skip -> OrderByDescending -> Take", b => getQuery(b) + .Skip(7).OrderByDescending(f => f.Int).Take(17))); + + // --------------------------- + // Distinct + Skip & Take + // --------------------------- + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> Take", b => getQuery(b) + .Distinct().Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Distinct", b => getQuery(b) + .Skip(3).Take(11).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Distinct -> Skip -> Take -> Distinct -> Skip", b => getQuery(b) + .Skip(10).Take(60).Select(f => f.Int).Distinct().Skip(15).Take(20).Distinct().Skip(7))); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(7).Distinct().Skip(20).Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Skip -> Distinct -> Skip", b => getQuery(b) + .Take(30).Skip(10).Distinct().Skip(7))); + + // --------------------------------------------------------------------------------- + // Select, SelectMany, Where, OrderBy, Distinct with Skip & Take in between + // --------------------------------------------------------------------------------- + + // Select, SelectMany + + inputs.Add(new LinqTestInput( + "Select(new) -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, f.Children }).SelectMany(c => c.Children).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Select(c => c.GivenName).Skip(7).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).Take(20).SelectMany(f => f.Children).Skip(3).Select(c => c.GivenName).Take(5))); + + inputs.Add(new LinqTestInput( + "Skip -> SelectMany -> Take -> Skip -> Select -> Take", b => getQuery(b) + .Skip(10).SelectMany(f => f.Children).Take(10).Skip(1).Select(c => c.FamilyName).Take(7))); + + inputs.Add(new LinqTestInput( + "Take -> SelectMany -> Skip -> Select -> Take", b => getQuery(b) + .Take(30).SelectMany(f => f.Children).Skip(10).Select(c => c.Grade).Take(3))); + + // Select, Where + + inputs.Add(new LinqTestInput( + "Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children).Where(c => c.Count() > 0).Skip(3).Take(7))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Select -> Skip", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(7).Take(3).Select(f => f.FamilyId).Skip(2))); + + // Select, OrderBy + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> OrderBy", b => getQuery(b) + .Select(f => f.FamilyId).Skip(1).Take(2).OrderBy(s => s))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> Take -> Skip -> Select", b => getQuery(b) + .OrderByDescending(f => f.Int).Take(10).Skip(3).Select(f => f.Int + 1))); + + // Select, Distinct + + inputs.Add(new LinqTestInput( + "Take -> Select -> Distinct -> Skip -> Take", b => getQuery(b) + .Take(7).Select(f => f.Int).Distinct().Skip(1).Take(5))); + + // SelectMany, Where + + inputs.Add(new LinqTestInput( + "SelectMany -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Where(c => c.Grade > 100).Skip(10).Take(20))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> SelectMany -> Take", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(10).SelectMany(f => f.Children).Take(7))); + + // SelectMany, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> SelectMany -> SelectMany", b => getQuery(b) + .OrderBy(f => f.Int).Skip(10).SelectMany(f => f.Children).SelectMany(c => c.Pets))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // SelectMany, Distinct + + inputs.Add(new LinqTestInput( + "SelectMany -> Distinct -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children).Distinct().Skip(7).Take(11))); + + inputs.Add(new LinqTestInput( + "Distinct -> Skip -> SelectMany", b => getQuery(b) + .Distinct().Skip(3).SelectMany(f => f.Children))); + + // Where, OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Where(f => f.IsRegistered).Skip(11).Take(3))); + + inputs.Add(new LinqTestInput( + "Skip -> Where -> Take -> OrderBy", b => getQuery(b) + .Skip(20).Where(f => f.Children.Count() > 0).Take(10).OrderBy(f => f.Int))); + + // Where, Distinct + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> Distinct", b => getQuery(b) + .Where(f => f.IsRegistered).Skip(3).Take(17).Distinct())); + + inputs.Add(new LinqTestInput( + "Skip -> Distinct -> Where -> Take", b => getQuery(b) + .Skip(22).Distinct().Where(f => f.Parents.Count() > 0).Take(7))); + + // ----------------------------------------- + // All basic operations with Skip & Take + // ----------------------------------------- + + // Start with Select + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "Select -> Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Select(f => f.FamilyId).Where(id => id.Count() > 10).OrderBy(id => id).Skip(1).Take(10) + .Select(id => id + "_suffix").Where(id => id.Count() > 12).Skip(2).Take(4))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> OrderBy -> Skip -> Distinct -> Skip", b => getQuery(b) + .Select(f => f.Records).Skip(5).OrderBy(r => r.Transactions.Count()).Skip(1).Distinct().Skip(3))); + + inputs.Add(new LinqTestInput( + "Select(new(new(new(new(new))))) -> (Skip -> Select) x 6 -> Skip -> Where -> Take", b => getQuery(b) + .Select(f => new { f.FamilyId, L1 = new { L2 = new { L3 = new { L4 = new { f.Records } } } } }) + .Skip(1).Select(f => f.L1) + .Skip(2).Select(f => f.L2) + .Skip(3).Select(f => f.L3) + .Skip(4).Select(f => f.L4) + .Skip(5).Select(f => f.Records) + .Skip(6).Select(f => f.Transactions) + .Skip(7).Where(t => t.Count() > 100) + .Take(20))); + + inputs.Add(new LinqTestInput( + "Select -> (Skip -> Select -> Where -> OrderBy -> Distinct -> Take) x 3 -> Skip -> Take", b => getQuery(b) + .Select(f => new { L1 = f }) + .Skip(1).Select(f => f.L1).Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Distinct().Take(100) + .Skip(2).Select(f => new { L2 = f }).Where(f => f.L2.FamilyId.CompareTo("A") > 0).OrderBy(f => f.L2.Int).Distinct().Take(50) + .Skip(3).Select(f => f.L2).Where(f => f.Children.Count() > 1).OrderBy(f => f.IsRegistered).Distinct().Take(40) + .Skip(4).Take(25))); + + // Start with Distinct + + inputs.Add(new LinqTestInput( + "Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Distinct().Select(f => f.Records).Where(r => r.Transactions.Count() > 2).Skip(1).Take(10))); + + // Start with Where + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5))); + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 10).OrderBy(f => f.FamilyId).Skip(1).Take(5) + .Select(f => f.Records).Where(r => r.Transactions != null).Skip(1).Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> Skip -> Take -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.Int > 20).Skip(5).Take(20) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(5).Take(10))); + + // Start with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Int).Skip(1).Take(10) + .Select(f => f.Records).Where(r => r.Transactions.Count() > 10).Skip(2).Take(3))); + + // Start with Skip + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Skip(1).Take(10).Select(f => f.Children.Count()).Where(c => c > 1).Skip(1).Take(4))); + + inputs.Add(new LinqTestInput( + "Skip -> Take -> Where -> Skip -> Take -> OrderBy -> Skip -> Take -> Select -> Skip -> Distinct -> Skip -> Take", b => getQuery(b) + .Skip(2).Take(10).Where(f => f.Int > 10) + .Skip(1).Take(9).OrderBy(f => f.FamilyId) + .Skip(3).Take(5).Select(f => f.Children.Count()) + .Skip(1).Distinct() + .Skip(1).Take(1))); + + // Start with Take + + inputs.Add(new LinqTestInput( + "Take -> Skip -> OrderBy -> Skip -> Take", b => getQuery(b) + .Take(10).Skip(2).Where(f => f.IsRegistered).OrderBy(f => f.Int).Skip(1).Take(9))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct -> Select -> Where -> Skip -> Take", b => getQuery(b) + .Take(10).Distinct().Select(f => f.Children).Where(c => c.Count() > 0).Skip(2).Take(5))); + + // ----------------------------------------------------------------------------- + // All basic operations with Skip & Take with SelectMany in the middle + // ----------------------------------------------------------------------------- + + // SelectMany after Take + + inputs.Add(new LinqTestInput( + "Select -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => f.Records).Skip(1).Take(10) + .SelectMany(r => r.Transactions).Skip(1).Take(9))); + + // SelectMany after Where + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> Skip -> Take", b => getQuery(b) + .Where(f => f.IsRegistered) + .SelectMany(f => f.Children).OrderBy(c => c.Grade).Skip(10).Take(20))); + + // Start with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany -> Select -> Skip -> Take -> Select -> Where -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children) + .Select(c => c.FamilyName).Skip(1).Take(20) + .Select(n => n.Count()).Where(l => l > 10).Skip(2).Take(50))); + + // ------------------------------------------------------------- + // Nested Skip & Take in Select, SelectMany, Where, OrderBy + // ------------------------------------------------------------- + + // Nested with Select + + inputs.Add(new LinqTestInput( + "Select(new(Where -> Skip)) -> Where", b => getQuery(b) + .Select(f => new { + id = f.FamilyId, + GoodChildren = f.Children.Where(c => c.Grade > 75).Skip(1) + }) + .Where(f => f.GoodChildren.Count() > 0))); + + inputs.Add(new LinqTestInput( + "Select(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .Select(f => f.Children.Skip(1).Take(1)).Skip(3).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(Skip -> Take, Skip, Take) -> Skip -> Take -> Where", b => getQuery(b) + .Select(f => new { + v0 = f.Children.Skip(1).Take(2), + v1 = f.Parents.Skip(1), + v2 = f.Records.Transactions.Take(10) + }) + .Skip(1).Take(20).Where(f => f.v0.Count() > 0).Take(10))); + + inputs.Add(new LinqTestInput( + "Select(new(SelectMany -> SelectMany -> Distinct, OrderByDescending -> Take -> SelectMany -> Skip, Select -> OrderBy -> Skip -> Take -> Sum) -> Where -> Skip -> Take -> SelectMany -> Skip -> Take", b => getQuery(b) + .Select(f => new { + v0 = f.Children.SelectMany(c => c.Pets.Skip(1).SelectMany(p => p.GivenName).Distinct()), + v1 = f.Children.OrderByDescending(c => c.Grade).Take(2).SelectMany(c => c.Pets.Select(p => p.GivenName).Skip(2)), + v2 = f.Records.Transactions.Select(t => t.Amount).OrderBy(a => a).Skip(10).Take(20).Sum() + }) + .Where(f => f.v2 > 100).Skip(5).Take(20) + .SelectMany(f => f.v1).Distinct().Skip(3).Take(22))); + + inputs.Add(new LinqTestInput( + "Select -> Skip -> SelectMany(Skip -> OrderBy)", b => getQuery(b) + .Select(f => f.Records).Skip(1).SelectMany(r => r.Transactions.Skip(10).OrderBy(t => t.Date)))); + + // Nested with Where + + inputs.Add(new LinqTestInput( + "Where -> Where(Skip -> Take -> Count) - > Skip -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 2).Where(f => f.Children.Skip(1).Take(10).Count() > 1).Skip(1).Take(10))); + + // Nested with OrderBy + + inputs.Add(new LinqTestInput( + "OrderBy(Skip -> Take -> Count) -> Skip -> Take", b => getQuery(b) + .OrderBy(f => f.Children.Skip(1).Take(5).Count()))); + + // Nested with SelectMany + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> Take) -> Skip -> Take -> SelectMany(Skip -> Take) -> Skip -> Take", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).Take(2)).Skip(3).Take(20) + .SelectMany(c => c.Pets.Skip(1).Take(2)).Skip(1).Take(10))); + + inputs.Add(new LinqTestInput( + "SelectMany(Where -> OrderBy -> Skip -> Distinct)", b => getQuery(b) + .SelectMany(f => f.Children.Where(c => c.Grade > 10).OrderBy(c => c.Grade).Skip(1).Distinct()))); + + inputs.Add(new LinqTestInput( + "SelectMany(Skip -> SelectMany(Skip -> Select) -> Take)", b => getQuery(b) + .SelectMany(f => f.Children.Skip(1).SelectMany(c => c.Pets.Skip(1).Select(p => p.GivenName)).Take(10)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestUnsupportedScenarios() + { + List inputs = new List(); + + // -------------------- + // Dictionary type + // -------------------- + + // Iterating through Dictionary type + inputs.Add(new LinqTestInput("Iterating through Dictionary type", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Select(t => t.Key.Count() + t.Value.Count()))))); + + // Get a count of a Dictionary type + inputs.Add(new LinqTestInput("Getting Dictionary count", b => getQuery(b).Select(f => f.Children.Select(c => c.Things.Count())))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestOrderByTranslation() + { + List inputs = new List(); + + // Ascending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderBy(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderBy(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy query", + b => from f in getQuery(b) + orderby f.FamilyId + select f)); + inputs.Add(new LinqTestInput("OrderBy", b => getQuery(b).OrderBy(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderBy(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + + // Descending + inputs.Add(new LinqTestInput("Select -> order by", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id))); + inputs.Add(new LinqTestInput("Select -> order by -> Select", b => getQuery(b).Select(family => family.FamilyId).OrderByDescending(id => id).Select(x => x.Count()))); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select query", + b => from f in getQuery(b) + where f.Int == 5 && f.NullableInt != null + orderby f.IsRegistered descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("Where -> OrderBy Desc -> Select", b => getQuery(b).Where(f => f.Int == 5 && f.NullableInt != null).OrderByDescending(f => f.IsRegistered).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f)); + inputs.Add(new LinqTestInput("OrderBy Desc", b => getQuery(b).OrderByDescending(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select query", + b => from f in getQuery(b) + orderby f.FamilyId descending + select f.FamilyId)); + inputs.Add(new LinqTestInput("OrderBy Desc -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Take", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Take(10))); + inputs.Add(new LinqTestInput("OrderBy -> Select -> Select", b => getQuery(b).OrderByDescending(f => f.FamilyId).Select(f => f.FamilyId).Select(x => x))); + inputs.Add(new LinqTestInput("OrderBy multiple expressions", + b => from f in getQuery(b) + orderby f.FamilyId, f.Int + select f.FamilyId)); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLambdaReuse() + { + List inputs = new List(); + + System.Linq.Expressions.Expression> predicate = f => f.Int == 5; + inputs.Add(new LinqTestInput("Where -> Where with same predicate instance", b => getQuery(b).Where(predicate).Where(predicate))); + inputs.Add(new LinqTestInput("Where -> Select with same predicate instance", b => getQuery(b).Where(predicate).Select(predicate))); + + System.Linq.Expressions.Expression> predicate2 = f => f.ToString() == "a"; + inputs.Add(new LinqTestInput("Where -> Select -> Where with same predicate instance", + b => getQuery(b) + .Where(predicate2) + .Select(c => new { Int = 10, Result = c }) + .Where(predicate2))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestThenByTranslation() + { + List inputs = new List(); + + // Ascending and descending + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenBy(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderByDescending -> ThenByDescending", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .ThenByDescending(f => f.Int))); + + // Subquery in OrderBy or in ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + // OrderBy and ThenBy by the same property (not a realistic scenario) + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenByDescending", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.FamilyId))); + + inputs.Add(new LinqTestInput( + "OrderByDescending subquery -> ThenBy subquery", b => getQuery(b) + .OrderByDescending(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // OrderBy and ThenBy with epxressions + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.Int * 2) + .ThenBy(f => f.FamilyId.Substring(2, 3)))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderBy(f => !f.NullableInt.IsDefined()) + .ThenByDescending(f => f.Tags.Count() % 2))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.IsRegistered ? f.FamilyId : f.Int.ToString()) + .ThenBy(f => f.Records.Transactions.Max(t => t.Amount) % 1000))); + + // Multiple OrderBy and ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> OrderBy -> ThenBy", b => getQuery(b) + .OrderByDescending(f => f.FamilyId) + .OrderBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy -> ThenBy", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenBy(f => f.Int) + .ThenByDescending(f => f.IsRegistered))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Orderby subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .OrderBy(f => f.Children.Where(c => c.Grade > 100).Count()) + .ThenBy(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()))); + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy subquery -> ThenBy subquery", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents.Where(p => p.GivenName.Length > 10).Count()) + .ThenBy(f => f.Children.Where(c => c.Grade > 100).Count()))); + + // Nested ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenBy(c => c.Pets.Count)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // Nested expressions with ThenBy + + inputs.Add(new LinqTestInput( + "OrderBy -> ThenBy(OrderBy -> ThenBy -> Take -> Select)", b => getQuery(b) + .OrderBy(f => f.FamilyId) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Take(1) + .Select(p => p.FamilyName + p.GivenName)))); + + inputs.Add(new LinqTestInput( + "OrderBy(OrderBy -> ThenBy -> Take -> OrderBy -> ThenBy) -> ThenBy(OrderBy -> ThenBy)", b => getQuery(b) + .OrderBy(f => f.Children + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count) + .Take(10) + .OrderByDescending(c => c.GivenName) + .ThenBy(c => c.Gender)) + .ThenByDescending(f => f.Parents + .OrderBy(p => p.FamilyName) + .ThenByDescending(p => p.GivenName) + .Select(p => p.FamilyName + p.GivenName)))); + + // On a new object + + inputs.Add(new LinqTestInput( + "Select -> OrderBy -> ThenBy", b => getQuery(b) + .Select(f => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + ChildrenPetCount = f.Children.Select(c => c.Pets.Count()).Sum() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + }) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber)))); + + inputs.Add(new LinqTestInput( + "SelectMany -> OrderBy -> ThenBy", b => getQuery(b) + .SelectMany(f => f.Children.Select(c => new + { + f.FamilyId, + FamilyNumber = f.Int, + ChildrenCount = f.Children.Count(), + Name = c.GivenName, + SpecialPetCount = c.Pets.Where(p => p.GivenName.Length > 5).Count() + })) + .OrderBy(r => r.FamilyId) + .ThenBy(r => r.FamilyNumber) + .Select(r => r.FamilyId))); + + inputs.Add(new LinqTestInput( + "Select(new(Where, Sum) -> OrderBy(Count) -> ThenBy)", b => getQuery(b) + .Select(f => new { + ChildrenWithPets = f.Children.Where(c => c.Pets.Count() > 0), + TotalExpenses = f.Records.Transactions.Sum(t => t.Amount) + }) + .OrderByDescending(r => r.ChildrenWithPets.Count()) + .ThenByDescending(r => r.TotalExpenses))); + + inputs.Add(new LinqTestInput( + "Select(new(Min, Count, SelectMany->Select->Distinct->Count)) -> OrderByDescending -> ThenBy", b => getQuery(b) + .Select(f => new { + ParentGivenName = f.Parents.Min(p => p.GivenName), + ParentCount = f.Parents.Count(), + GoodChildrenCount = f.Children.Where(c => c.Grade > 95).Count(), + UniquePetsNameCount = f.Children.SelectMany(c => c.Pets).Select(p => p.GivenName).Distinct().Count() + }) + .OrderByDescending(r => r.GoodChildrenCount) + .ThenBy(r => r.UniquePetsNameCount))); + + // With other LINQ operators: Where, SelectMany, Distinct, Skip, Take, and aggregates + + inputs.Add(new LinqTestInput( + "Where -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Take(3))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Skip -> Take -> Where -> Select -> Distinct", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderByDescending(c => c.Grade) + .ThenBy(c => c.GivenName) + .Skip(2) + .Take(20) + .Where(c => c.Pets.Where(p => p.GivenName.Length > 10).Count() > 0) + .Select(c => c.GivenName) + .Distinct())); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Select => Distinct => Take => OrderBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children) + .OrderBy(c => c.Grade) + .ThenByDescending(c => c.Pets.Count()) + .Select(c => c.GivenName) + .Distinct() + .Take(10) + .Skip(5) + .OrderBy(n => n.Length))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany -> OrderBy -> ThenBy -> Take", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Records.Transactions) + .OrderBy(t => t.Type) + .ThenBy(t => t.Amount) + .Take(100))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Take -> OrderBy -> ThenBy -> Skip", b => getQuery(b) + .Take(100) + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int) + .Skip(5))); + + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Distinct() + .OrderBy(f => f.IsRegistered) + .ThenByDescending(f => f.Int))); + + inputs.Add(new LinqTestInput( + "Where -> SelectMany(Select(new Where->Count)) -> Distinct -> OrderBy -> ThenBy", b => getQuery(b) + .Where(f => f.Children.Count() > 0) + .SelectMany(f => f.Children.Select(c => new { + Name = c.GivenName, + PetWithLongNames = c.Pets.Where(p => p.GivenName.Length > 8).Count() + })) + .Distinct() + .OrderByDescending(r => r.Name) + .ThenBy(r => r.PetWithLongNames))); + + inputs.Add(new LinqTestInput( + "OrderBy(Any) -> ThenBy(Any)", b => getQuery(b) + .OrderBy(f => f.Children.Any(c => c.Grade > 90)) + .ThenByDescending(f => f.Parents.Any(p => p.GivenName.Length > 10)))); + + inputs.Add(new LinqTestInput( + "OrderBy(Min) -> ThenBy(Max) -> ThenBy(Sum) -> ThenBy(Avg)", b => getQuery(b) + .OrderBy(f => f.Children.Min(c => c.GivenName)) + .ThenByDescending(f => f.Parents.Max(p => p.GivenName)) + .ThenBy(f => f.Records.Transactions.Sum(t => t.Amount)) + .ThenByDescending(f => f.Records.Transactions.Average(t => t.Amount)))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + [Ignore] + public void TestDistinctSelectManyIssues() + { + List inputs = new List(); + + // these tests need a fix in the ServiceInterop + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x).Take(10))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Distinct -> Take", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Distinct().Take(10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestDistinctTranslation() + { + static LinqTestInput DistinctTestInput(string description, System.Linq.Expressions.Expression> expr) + { + return new LinqTestInput(description, expr, true); + } + + List inputs = new List(); + + // Simple distinct + // Select -> Distinct for all data types + inputs.Add(DistinctTestInput( + "Distinct string", + b => getQuery(b).Select(f => f.FamilyId).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct int", + b => getQuery(b).Select(f => f.Int).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct bool", + b => getQuery(b).Select(f => f.IsRegistered).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct nullable int", + b => getQuery(b).Where(f => f.NullableInt != null).Select(f => f.NullableInt).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct null", + b => getQuery(b).Where(f => f.NullObject != null).Select(f => f.NullObject).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct children", + b => getQuery(b).SelectMany(f => f.Children).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct parent", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct family", + b => getQuery(b).Distinct())); + + inputs.Add(DistinctTestInput( + "Multiple distincts", + b => getQuery(b).Distinct().Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct new obj", + b => getQuery(b).Select(f => new { Parents = f.Parents.Count(), Children = f.Children.Count() }).Select(f => f.Parents).Distinct())); + + // Distinct + Take + inputs.Add(DistinctTestInput( + "Distinct -> Take", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10))); + + inputs.Add(new LinqTestInput( + "Take -> Distinct", + b => getQuery(b).Select(f => f.Int).Take(10).Distinct())); + + // Distinct + Order By + inputs.Add(new LinqTestInput( + "Distinct -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().OrderBy(x => x))); + + inputs.Add(DistinctTestInput( + "OrderBy -> Distinct", + b => getQuery(b).OrderBy(f => f.Int).Distinct())); + + // Distinct + Order By + Take + inputs.Add(new LinqTestInput( + "Distinct -> Take -> OrderBy", + b => getQuery(b).Select(f => f.Int).Distinct().Take(10).OrderBy(x => x))); + + inputs.Add(new LinqTestInput( + "OrderBy -> Take -> Distinct", + b => getQuery(b).Select(f => f.Int).OrderBy(x => x).Take(10).Distinct())); + + // Distinct + Where + inputs.Add(DistinctTestInput( + "Where -> Distinct", + b => getQuery(b).Select(f => f.Int).Where(x => x > 10).Distinct())); + + inputs.Add(DistinctTestInput( + "Distinct -> Where", + b => getQuery(b).Select(f => f.Int).Distinct().Where(x => x > 10))); + + // SelectMany w Distinct + inputs.Add(DistinctTestInput( + "SelectMany(Select obj) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select)) -> Distinct", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet) + .Distinct())))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => pet.GivenName) + .Select(name => name.Count()))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Select) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }).Select(p => p.child)) + .Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {}) -> Distinct)", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }))) + .Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(SelectMany(Where -> Select new {} -> Distinct))", + b => getQuery(b) + .SelectMany(family => family.Children + .SelectMany(child => child.Pets + .Where(pet => pet.GivenName == "Fluffy") + .Select(pet => new + { + family = family.FamilyId, + child = child.GivenName, + pet = pet.GivenName + }) + .Distinct())))); + + // SelectMany(Distinct) + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Where -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Where(f => f.FamilyName.Count() < 20).Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> OrderBy -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .OrderBy(f => f).Take(5).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct().Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> Distinct -> Take -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10).Distinct() + .Take(5).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct())); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Distinct().OrderBy(f => f.GivenName.Length).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Distinct -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .OrderBy(f => f).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Where -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Where(f => f.FamilyName.Count() > 10) + .Where(f => f.FamilyName.Count() < 20))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName))); + + inputs.Add(new LinqTestInput( + "SelectMany(Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).OrderBy(f => f.FamilyName).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Distinct) -> Select -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Distinct()).Select(f => f.FamilyName.Count()).Take(5))); + + // SelectMany(Select -> Distinct) + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).OrderBy(n => n).Take(5))); + + inputs.Add(new LinqTestInput( + "SelectMany(Select -> Distinct) -> Where -> OrderBy -> Take", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10).OrderBy(n => n).Take(5))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName)).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct)", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.FamilyName).Distinct()))); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Distinct", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Distinct())); + + inputs.Add(DistinctTestInput( + "SelectMany(Select -> Distinct) -> Where", + b => getQuery(b).SelectMany(f => f.Parents.Select(p => p.GivenName).Distinct()).Where(n => n.Count() > 10))); + + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicLinq() + { + List inputs = new List(); + inputs.Add(new LinqTestInput("Select", b => getQuery(b).Select("FamilyId"))); + inputs.Add(new LinqTestInput("Where", b => getQuery(b).Where("FamilyId = \"some id\""))); + inputs.Add(new LinqTestInput("Where longer", b => getQuery(b).Where("FamilyId = \"some id\" AND IsRegistered = True OR Int > 101"))); + // with parameters + inputs.Add(new LinqTestInput("Where w/ parameters", b => getQuery(b).Where("FamilyId = @0 AND IsRegistered = @1 OR Int > @2", "some id", true, 101))); + inputs.Add(new LinqTestInput("Where -> Select", b => getQuery(b).Where("FamilyId = \"some id\"").Select("Int"))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public async Task ValidateLinqQueries() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); + + Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; + Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; + Pet pet = new Pet { GivenName = "Fluffy" }; + Child child = new Child + { + FamilyName = "Merriam", + GivenName = "Jesse", + Gender = "female", + Grade = 1, + Pets = new List() { pet, new Pet() { GivenName = "koko" } }, + Things = new Dictionary() { { "A", "B" }, { "C", "D" } } + }; + + Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; + Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; + + List fList = new List(); + fList.Add(family); + + container.CreateItemAsync(family).Wait(); + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); + Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); + + IEnumerable q2 = query.Select(f => f.Children[0].Grade + 13); + Assert.AreEqual(q2.FirstOrDefault(), family.Children[0].Grade + 13); + + IEnumerable q3 = query.Where(f => f.Children[0].Pets[0].GivenName == "Fluffy"); + Assert.AreEqual(q3.FirstOrDefault().FamilyId, family.FamilyId); + + IEnumerable q4 = query.Where(f => f.Children[0].Things["A"] == "B"); + Assert.AreEqual(q4.FirstOrDefault().FamilyId, family.FamilyId); + + for (int index = 0; index < 2; index++) + { + IEnumerable q5 = query.Where(f => f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[index]); + Assert.AreEqual(q5.FirstOrDefault().GivenName, family.Children[0].Pets[index].GivenName); + } + + IEnumerable q6 = query.SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })); + Assert.AreEqual(q6.FirstOrDefault().Id, family.FamilyId); + + string nullString = null; + IEnumerable q7 = query.Where(f => nullString == f.FamilyId); + Assert.IsNull(q7.FirstOrDefault()); + + object nullObject = null; + q7 = query.Where(f => f.NullObject == nullObject); + Assert.AreEqual(q7.FirstOrDefault().FamilyId, family.FamilyId); + + q7 = query.Where(f => f.FamilyId == nullString); + Assert.IsNull(q7.FirstOrDefault()); + + IEnumerable q8 = query.Where(f => null == f.FamilyId); + Assert.IsNull(q8.FirstOrDefault()); + + IEnumerable q9 = query.Where(f => f.IsRegistered == false); + Assert.AreEqual(q9.FirstOrDefault().FamilyId, family.FamilyId); + + dynamic q10 = query.Where(f => f.FamilyId.Equals("WakefieldFamily")).AsEnumerable().FirstOrDefault(); + Assert.AreEqual(q10.FamilyId, family.FamilyId); + + GuidClass guidObject = new GuidClass() { Id = new Guid("098aa945-7ed8-4c50-b7b8-bd99eddb54bc") }; + container.CreateItemAsync(guidObject).Wait(); + List guidData = new List() { guidObject }; + + IOrderedQueryable guid = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IQueryable q11 = guid.Where(g => g.Id == guidObject.Id); + Assert.AreEqual(((IEnumerable)q11).FirstOrDefault().Id, guidObject.Id); + + IQueryable q12 = guid.Where(g => g.Id.ToString() == guidObject.Id.ToString()); + Assert.AreEqual(((IEnumerable)q12).FirstOrDefault().Id, guidObject.Id); + + ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; + container.CreateItemAsync(arrayObject).Wait(); + + IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); + Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); + + int[] nullArray = null; + q13 = listArrayQuery.Where(a => a.ArrayField == nullArray); + Assert.IsNull(q13.FirstOrDefault()); + + ListArrayClass listObject = new ListArrayClass() { Id = "listObject", ListField = new List { 1, 2, 3 } }; + container.CreateItemAsync(listObject).Wait(); + List listArrayObjectData = new List() { arrayObject, listObject }; + + IEnumerable q14 = listArrayQuery.Where(a => a.ListField == listObject.ListField); + Assert.AreEqual(q14.FirstOrDefault().Id, listObject.Id); + + IEnumerable q15 = query.Where(f => f.NullableInt == null); + Assert.AreEqual(q15.ToList().Count, 0); + + int? nullInt = null; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + q15 = query.Where(f => f.NullableInt == 5); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 5; + q15 = query.Where(f => f.NullableInt == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.NullableInt == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = 3; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + q15 = query.Where(f => f.Int == nullInt.Value); + Assert.AreEqual(q15.FirstOrDefault().FamilyId, family.FamilyId); + + nullInt = null; + q15 = query.Where(f => f.Int == nullInt); + Assert.AreEqual(q15.ToList().Count, 0); + + List v = fList.Where(f => f.Int > nullInt).ToList(); + + q15 = query.Where(f => f.Int < nullInt); + + string doc1Id = "document1:x:'!@TT){}\""; + Document doubleQoutesDocument = new Document() { Id = doc1Id }; + container.CreateItemAsync(doubleQoutesDocument).Wait(); + + IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + where book.Id == doc1Id + select book; + + Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); + + GreatFamily greatFamily = new GreatFamily() { Family = family }; + GreatGreatFamily greatGreatFamily = new GreatGreatFamily() { GreatFamilyId = Guid.NewGuid().ToString(), GreatFamily = greatFamily }; + container.CreateItemAsync(greatGreatFamily).Wait(); + List greatGreatFamilyData = new List() { greatGreatFamily }; + + IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); + + Assert.AreEqual(q16.FirstOrDefault().GreatFamilyId, greatGreatFamily.GreatFamilyId); + + Sport sport = new Sport() { SportName = "Tennis", SportType = "Racquet" }; + container.CreateItemAsync(sport).Wait(); + List sportData = new List() { sport }; + + IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); + + Assert.AreEqual(sport.SportName, q17.FirstOrDefault().SportName); + + Sport2 sport2 = new Sport2() { id = "json" }; + container.CreateItemAsync(sport2).Wait(); + List sport2Data = new List() { sport2 }; + + IOrderedQueryable sport2Query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + Func> getGuidQuery = useQuery => useQuery ? guid : guidData.AsQueryable(); + Func> getListArrayQuery = useQuery => useQuery ? listArrayQuery : listArrayObjectData.AsQueryable(); + Func> getGreatFamilyQuery = useQuery => useQuery ? queryable : greatGreatFamilyData.AsQueryable(); + Func> getSportQuery = useQuery => useQuery ? sportQuery : sportData.AsQueryable(); + Func> getSport2Query = useQuery => useQuery ? sport2Query : sport2Data.AsQueryable(); + + int? nullIntVal = null; + int? nullableIntVal = 5; + + List inputs = new List(); + inputs.Add(new LinqTestInput("Select 1st parent family name", b => getQuery(b).Where(f => f.Parents.Count() > 0).Select(f => f.Parents[0].FamilyName))); + inputs.Add(new LinqTestInput("Select 1st children grade expr", b => getQuery(b).Where(f => f.Children.Count() > 0).Select(f => f.Children[0].Grade + 13))); + inputs.Add(new LinqTestInput("Filter 1st children's 1st pet name", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Pets[0].GivenName == "Fluffy"))); + inputs.Add(new LinqTestInput("Filter 1st children's thing A value", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Things["A"] == "B"))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 1st pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 0 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[0]))); + inputs.Add(new LinqTestInput("Filter 1st children's gender -> Select his 2nd pet", b => getQuery(b).Where(f => f.Children.Count() > 0 && f.Children[0].Pets.Count() > 1 && f.Children[0].Gender == "female").Select(f => f.Children[0].Pets[1]))); + inputs.Add(new LinqTestInput("Select FamilyId of all children", b => getQuery(b).SelectMany(f => f.Children.Select(c => new { Id = f.FamilyId })))); + inputs.Add(new LinqTestInput("Filter family with null Id", b => getQuery(b).Where(f => (string)null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter family with null Id #2", b => getQuery(b).Where(f => f.FamilyId == (string)null))); + inputs.Add(new LinqTestInput("Filter family with null object", b => getQuery(b).Where(f => f.NullObject == (object)null))); + inputs.Add(new LinqTestInput("Filter family with null Id #3", b => getQuery(b).Where(f => null == f.FamilyId))); + inputs.Add(new LinqTestInput("Filter registered family", b => getQuery(b).Where(f => f.IsRegistered == false))); + inputs.Add(new LinqTestInput("Filter family by FamilyId", b => getQuery(b).Where(f => f.FamilyId.Equals("WakefieldFamily")))); + inputs.Add(new LinqTestInput("Filter family nullable int", b => getQuery(b).Where(f => f.NullableInt == null))); + inputs.Add(new LinqTestInput("Filter family nullable int #2", b => getQuery(b).Where(f => f.NullableInt == nullIntVal))); + inputs.Add(new LinqTestInput("Filter family nullable int =", b => getQuery(b).Where(f => f.NullableInt == 5))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter nullableInt = nullInt value", b => getQuery(b).Where(f => f.NullableInt == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullableIntVal))); + inputs.Add(new LinqTestInput("Filter int = nullInt value", b => getQuery(b).Where(f => f.Int == nullableIntVal.Value))); + inputs.Add(new LinqTestInput("Filter int = nullInt", b => getQuery(b).Where(f => f.Int == nullIntVal))); + inputs.Add(new LinqTestInput("Filter int < nullInt", b => getQuery(b).Where(f => f.Int < nullIntVal))); + + inputs.Add(new LinqTestInput("Guid filter by Id", b => getGuidQuery(b).Where(g => g.Id == guidObject.Id))); + inputs.Add(new LinqTestInput("Guid filter by Id #2", b => getGuidQuery(b).Where(g => g.Id.ToString() == guidObject.Id.ToString()))); + inputs.Add(new LinqTestInput("Array compare", b => getListArrayQuery(b).Where(a => a.ArrayField == arrayObject.ArrayField))); + inputs.Add(new LinqTestInput("Array compare null", b => getListArrayQuery(b).Where(a => a.ArrayField == nullArray))); + inputs.Add(new LinqTestInput("List compare", b => getListArrayQuery(b).Where(a => a.ListField == listObject.ListField))); + + inputs.Add(new LinqTestInput("Nested great family query filter children name", b => getGreatFamilyQuery(b).SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)))); + inputs.Add(new LinqTestInput("Sport filter sport name", b => getSportQuery(b).Where(s => s.SportName == "Tennis"))); + inputs.Add(new LinqTestInput("Sport filter sport type", b => getSportQuery(b).Where(s => s.SportType == "Racquet"))); + inputs.Add(new LinqTestInput("Sport2 filter by id", b => getSport2Query(b).Where(s => s.id == "json"))); + this.ExecuteTestSuite(inputs); + } + + internal static TValue CreateExecuteAndDeleteProcedure(DocumentClient client, + DocumentCollection collection, + string transientProcedure, + out StoredProcedureResponse response) + { + // create + StoredProcedure storedProcedure = new StoredProcedure + { + Id = "storedProcedure" + Guid.NewGuid().ToString(), + Body = transientProcedure + }; + StoredProcedure retrievedStoredProcedure = client.CreateStoredProcedureAsync(collection, storedProcedure).Result; + + // execute + response = client.ExecuteStoredProcedureAsync(retrievedStoredProcedure).Result; + + // delete + client.Delete(retrievedStoredProcedure.GetIdOrFullName()); + + return response.Response; + } + + [TestMethod] + public void ValidateBasicQuery() + { + this.ValidateBasicQueryAsync().Wait(); + } + + private async Task ValidateBasicQueryAsync() + { + DocumentClient client = TestCommon.CreateClient(true); + Documents.Database database = await client.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + + string databaseName = database.Id; + + List queryResults = new List(); + //Simple Equality + IQueryable dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db; + IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + DocumentFeedResponse pagedResponse = await documentQuery.ExecuteNextAsync(); + Assert.IsNotNull(pagedResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(pagedResponse.ActivityId, "Query ActivityId is null"); + queryResults.AddRange(pagedResponse); + } + + Assert.AreEqual(1, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Logical Or + dbQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName || db.ResourceId == database.ResourceId + select db; + documentQuery = dbQuery.AsDocumentQuery(); + + while (documentQuery.HasMoreResults) + { + queryResults.AddRange(await documentQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(2, queryResults.Count); + Assert.AreEqual(databaseName, queryResults[0].Id); + + //Select Property + IQueryable idQuery = from db in client.CreateDatabaseQuery() + where db.Id == databaseName + select db.ResourceId; + IDocumentQuery documentIdQuery = idQuery.AsDocumentQuery(); + + List idResults = new List(); + while (documentIdQuery.HasMoreResults) + { + idResults.AddRange(await documentIdQuery.ExecuteNextAsync()); + } + + Assert.AreEqual(1, idResults.Count); + Assert.AreEqual(database.ResourceId, idResults[0]); + } + + [TestMethod] + public async Task ValidateTransformQuery() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/id" }), Kind = PartitionKind.Hash }; + DocumentCollection collection = new DocumentCollection + { + Id = Guid.NewGuid().ToString("N"), + PartitionKey = partitionKeyDefinition + }; + collection.IndexingPolicy.IndexingMode = IndexingMode.Consistent; + Database database = await cosmosClient.DocumentClient.ReadDatabaseAsync(string.Format("dbs/{0}", testDb.Id)); + collection = cosmosClient.DocumentClient.Create(database.ResourceId, collection); + int documentsToCreate = 100; + for (int i = 0; i < documentsToCreate; i++) + { + dynamic myDocument = new Document(); + myDocument.Id = "doc" + i; + myDocument.Title = "MyBook"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument = await cosmosClient.DocumentClient.CreateDocumentAsync(collection.DocumentsLink, myDocument); + } + + //Read response as dynamic. + IQueryable docQuery = cosmosClient.DocumentClient.CreateDocumentQuery(collection.DocumentsLink, @"select * from root r where r.Title=""MyBook""", new FeedOptions { EnableCrossPartitionQuery = true }); + + IDocumentQuery DocumentQuery = docQuery.AsDocumentQuery(); + DocumentFeedResponse queryResponse = await DocumentQuery.ExecuteNextAsync(); + + Assert.IsNotNull(queryResponse.ResponseHeaders, "ResponseHeaders is null"); + Assert.IsNotNull(queryResponse.ActivityId, "ActivityId is null"); + Assert.AreEqual(documentsToCreate, queryResponse.Count); + + foreach (dynamic myBook in queryResponse) + { + Assert.AreEqual(myBook.Title.ToString(), "MyBook"); + } + + cosmosClient.DocumentClient.DeleteDocumentCollectionAsync(collection.SelfLink).Wait(); + } + + [TestMethod] + public void ValidateDynamicDocumentQuery() //Ensure query on custom property of document. + { + Book myDocument = new Book(); + myDocument.Id = Guid.NewGuid().ToString(); + myDocument.Title = "My Book"; //Simple Property. + myDocument.Languages = new Language[] { new Language { Name = "English", Copyright = "London Publication" }, new Language { Name = "French", Copyright = "Paris Publication" } }; //Array Property + myDocument.Author = new Author { Name = "Don", Location = "France" }; //Complex Property + myDocument.Price = 9.99; + myDocument.Editions = new List() { new Edition() { Name = "First", Year = 2001 }, new Edition() { Name = "Second", Year = 2005 } }; + + //Create second document to make sure we have atleast one document which are filtered out of query. + Book secondDocument = new Book + { + Id = Guid.NewGuid().ToString(), + Title = "My Second Book", + Languages = new Language[] { new Language { Name = "Spanish", Copyright = "Mexico Publication" } }, + Author = new Author { Name = "Carlos", Location = "Cancun" }, + Price = 25, + Editions = new List() { new Edition() { Name = "First", Year = 1970 } } + }; + + //Unfiltered execution. + IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Simple Equality on custom property", + b => from book in getBookQuery(b) + where book.Title == "My Book" + select book)); + inputs.Add(new LinqTestInput("Nested Property access", + b => from book in getBookQuery(b) + where book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("Array references & Project Author out..", + b => from book in getBookQuery(b) + where book.Languages[0].Name == "English" + select book.Author)); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); + inputs.Add(new LinqTestInput("NumericRange query", + b => from book in getBookQuery(b) + where book.Price < 10 + select book.Author)); + inputs.Add(new LinqTestInput("Or query", + b => from book in getBookQuery(b) + where book.Title == "My Book" || book.Author.Name == "Don" + select book)); + inputs.Add(new LinqTestInput("SelectMany query on a List type.", + b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); + // Below samples are strictly speaking not Any equivalent. But they join and filter "all" + // subchildren which match predicate. When SQL BE supports ANY, we can replace these with Any Flavor. + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Languages + .Where(lng => lng.Name == "English") + .Select(lng => book.Author)))); + inputs.Add(new LinqTestInput("SelectMany", + b => getBookQuery(b).SelectMany(book => + book.Editions + .Where(edition => edition.Year == 2001) + .Select(lng => book.Author)))); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. + { + IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + Document myDocument = new Document(); + Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); + + List inputs = new List(); + inputs.Add(new LinqTestInput("Filter equality on custom property", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title2" + select attachment)); + inputs.Add(new LinqTestInput("Filter equality on custom property #2", + b => from attachment in getAttachmentQuery(b) + where attachment.Title == "My Book Title" + select attachment)); + this.ExecuteTestSuite(inputs); + } + + [TestMethod] + public void TestLinqTypeSystem() + { + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Book))); + Assert.AreEqual(null, TypeSystem.GetElementType(typeof(Author))); + + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(Language[]))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IList))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(IEnumerable))); + Assert.AreEqual(typeof(Language), TypeSystem.GetElementType(typeof(ICollection))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooItem[]))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(List))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(MyList))); + Assert.AreEqual(typeof(Tuple), TypeSystem.GetElementType(typeof(MyTupleList))); + + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(DerivedFooCollection))); + Assert.AreEqual(typeof(string), TypeSystem.GetElementType(typeof(FooStringCollection))); + + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(FooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + Assert.AreEqual(typeof(DerivedFooItem), TypeSystem.GetElementType(typeof(FooTCollection))); + } + + #region DataDocument type tests + + public class BaseDocument + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public string TypeName { get; set; } + } + + public class DataDocument : BaseDocument + { + public int Number { get; set; } + } + + private class QueryHelper + { + private readonly Container container; + + public QueryHelper(Container container) + { + this.container = container; + } + + public IQueryable Query() where T : BaseDocument + { + IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + .Where(d => d.TypeName == "Hello"); + string queryString = query.ToString(); + return query; + } + } + + [TestMethod] + public async Task ValidateLinqOnDataDocumentType() + { + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); + + DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; + container.CreateItemAsync(doc).Wait(); + + QueryHelper queryHelper = new QueryHelper(container); + IEnumerable result = queryHelper.Query(); + Assert.AreEqual(1, result.Count()); + + BaseDocument baseDocument = result.FirstOrDefault(); + Assert.AreEqual(doc.Id, baseDocument.Id); + + BaseDocument iDocument = doc; + IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + + IEnumerable iresult = from f in q + where f.Id == iDocument.Id + select f; + DataDocument id = iresult.FirstOrDefault(); + Assert.AreEqual(doc.Id, id.Id); + } + + #endregion + + #region Book type tests + public class Author + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + public string Location { get; set; } + } + + public class Language + { + public string Name { get; set; } + public string Copyright { get; set; } + } + + public class Edition + { + public string Name { get; set; } + public int Year { get; set; } + } + + public class Book + { + //Verify that we can override the propertyName but still can query them using .NET Property names. + [JsonProperty(PropertyName = "title")] + public string Title { get; set; } + [JsonProperty(PropertyName = "name")] + public string Name { get; set; } + public Language[] Languages { get; set; } + public Author Author { get; set; } + public double Price { get; set; } + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id { get; set; } + public List Editions { get; set; } + } + + [TestMethod] + public async Task ValidateServerSideQueryEvalWithPagination() + { + await this.ValidateServerSideQueryEvalWithPaginationScenario(); + } + + private async Task ValidateServerSideQueryEvalWithPaginationScenario() + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection(new[] { "/title" }), Kind = PartitionKind.Hash }; + ContainerProperties cosmosContainerSettings = new ContainerProperties + { + Id = Guid.NewGuid().ToString(), + PartitionKey = partitionKeyDefinition, + }; + cosmosContainerSettings.IndexingPolicy.IndexingMode = Microsoft.Azure.Cosmos.IndexingMode.Consistent; + + Container collection = await testDb.CreateContainerAsync(cosmosContainerSettings); + + //Do script post to insert as many document as we could in a tight loop. + string script = @"function() { + var output = 0; + var client = getContext().getCollection(); + function callback(err, docCreated) { + if(err) throw 'Error while creating document'; + output++; + getContext().getResponse().setBody(output); + if(output < 50) + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); + }; + client.createDocument(client.getSelfLink(), { id: 'testDoc' + output, title : 'My Book'}, {}, callback); }"; + + StoredProcedureExecuteResponse scriptResponse = null; + int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); + + IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); + int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); + Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); + + } + + #endregion + + public class SpecialAttachment2 //Non attachemnt derived. + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Name { get; set; } + + [JsonProperty(PropertyName = "contentType")] + public string ContentType { get; set; } + + [JsonProperty(PropertyName = Constants.Properties.MediaLink)] + public string Media { get; set; } + + public string Author { get; set; } + public string Title { get; set; } + } + + #region TypeSystem test reference classes + public interface IFooItem { } + + public class FooItem : IFooItem { } + + public class DerivedFooItem : FooItem { } + + public class MyList : List { } + + public class MyTupleList : List> { } + + public class DerivedFooCollection : IList, IEnumerable + { + public int IndexOf(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, IFooItem item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public IFooItem this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(IFooItem item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(IFooItem item) + { + throw new NotImplementedException(); + } + + public void CopyTo(IFooItem[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(IFooItem item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooStringCollection : IList, IEnumerable + { + public int IndexOf(string item) + { + throw new NotImplementedException(); + } + + public void Insert(int index, string item) + { + throw new NotImplementedException(); + } + + public void RemoveAt(int index) + { + throw new NotImplementedException(); + } + + public string this[int index] + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public void Add(string item) + { + throw new NotImplementedException(); + } + + public void Clear() + { + throw new NotImplementedException(); + } + + public bool Contains(string item) + { + throw new NotImplementedException(); + } + + public void CopyTo(string[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + public int Count + { + get { throw new NotImplementedException(); } + } + + public bool IsReadOnly + { + get { throw new NotImplementedException(); } + } + + public bool Remove(string item) + { + throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + public class FooTCollection : List, IEnumerable + { + public new IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + } + #endregion + + public override LinqTestOutput ExecuteTest(LinqTestInput input) + { + return LinqTestsCommon.ExecuteTest(input); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs index 6e62be7cef..2e478abfd0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs @@ -311,7 +311,7 @@ public static Func> GenerateTestCosmosData(Func query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -348,7 +348,7 @@ public static Func> GenerateSerializationTestCosmosData(F } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); + QueryRequestOptions requestOptions = new QueryRequestOptions() { EnableOptimisticDirectExecution = false }; IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions, linqSerializerOptions: linqSerializerOptions); @@ -518,7 +518,7 @@ public static Func> GenerateSimpleCosmosData(Cosmos.Datab } FeedOptions feedOptions = new FeedOptions() { EnableScanInQuery = true, EnableCrossPartitionQuery = true }; - QueryRequestOptions requestOptions = new QueryRequestOptions(); + QueryRequestOptions requestOptions = new QueryRequestOptions() { EnableOptimisticDirectExecution = false }; IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); @@ -570,27 +570,7 @@ public static string BuildExceptionMessageForTest(Exception ex) { if (ex is CosmosException cosmosException) { - // ODE scenario: The backend generates an error response message with significant variations when compared to the Service Interop which gets called in the Non ODE scenario. - // The objective is to standardize and normalize the backend response for consistency. - Match match = Regex.Match(ex.Message, @"Reason:(.*?}]})", RegexOptions.IgnoreCase); - Match requestURIMatch = Regex.Match(ex.Message, @"Request URI", RegexOptions.IgnoreCase); - if (match.Success && requestURIMatch.Success) - { - string reason = match.Groups[1].Value; - reason = reason.Replace("\\", ""); - - string transformedString = "Status Code: " + reason; - transformedString = transformedString.Replace(" (", ""); - transformedString = transformedString.Replace("{\"code\":\"", ""); - transformedString = transformedString.Replace("\",\"message\":\"Message: {\"errors\":[", ",{\"errors\":["); - transformedString = transformedString.Replace("}]}", "}]},0x800A0B00"); - - return transformedString; - } - else - { - message.Append($"Status Code: {cosmosException.StatusCode}"); - } + message.Append($"Status Code: {cosmosException.StatusCode}"); } else if (ex is DocumentClientException documentClientException) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs index 1753d3726f..431081ecb2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/OptimisticDirectExecutionQueryTests.cs @@ -585,8 +585,9 @@ await this.CreateIngestQueryDeleteAsync( [TestMethod] public async Task TestOdeEnvironmentVariable() { + bool defaultValue = false; QueryRequestOptions options = new QueryRequestOptions(); - Assert.IsTrue(options.EnableOptimisticDirectExecution); + Assert.AreEqual(defaultValue, options.EnableOptimisticDirectExecution); foreach ((string name, string value, bool expectedValue) in new[] { @@ -599,10 +600,10 @@ public async Task TestOdeEnvironmentVariable() ("AZURE_COSMOS_optimistic_direct_execution_enabled", "False", false), ("azure_cosmos_optimistic_direct_execution_enabled", "FALSE", false), ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", "false", false), - ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, true), - (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", true), - (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, true), - ("enableode", "false", true) + ("Azure_Cosmos_Optimistic_Direct_Execution_Enabled", string.Empty, defaultValue), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), "false", defaultValue), + (nameof(QueryRequestOptions.EnableOptimisticDirectExecution), null, defaultValue), + ("enableode", "false", defaultValue) }) { try diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json index 3b597d3367..e11a346aff 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Contracts/BenchmarkResults.json @@ -1,9 +1,9 @@ { - "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 534, + "MasterKeyAuthorizationBenchmark.CreateSignatureGeneration;": 554, "MasterKeyAuthorizationBenchmark.ReadSignatureGeneration;": 544, - "MockedItemBenchmark.CreateItem;[Type=OfT]": 36356, - "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 36362, - "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 36359.5, + "MockedItemBenchmark.CreateItem;[Type=OfT]": 37261.25, + "MockedItemBenchmark.CreateItem;[Type=OfTCustom]": 37285, + "MockedItemBenchmark.CreateItem;[Type=OfTWithClientTelemetryEnabled]": 37280.25, "MockedItemBenchmark.CreateItem;[Type=OfTWithDiagnosticsToString]": 58900.5, "MockedItemBenchmark.CreateItem;[Type=Stream]": 25212.75, "MockedItemBenchmark.DeleteItemExists;[Type=OfT]": 33015.25, @@ -11,15 +11,15 @@ "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithClientTelemetryEnabled]": 33015.75, "MockedItemBenchmark.DeleteItemExists;[Type=OfTWithDiagnosticsToString]": 54402.75, "MockedItemBenchmark.DeleteItemExists;[Type=Stream]": 25229.25, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 42172.5, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 42174.75, - "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 42166.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfT]": 43035, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTCustom]": 43030.5, + "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43034.25, "MockedItemBenchmark.DeleteItemNotExists;[Type=OfTWithDiagnosticsToString]": 63338, "MockedItemBenchmark.DeleteItemNotExists;[Type=Stream]": 38373.5, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 11988727, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 11988284.75, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 11988606.75, - "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 12198686.5, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfT]": 13293777.25, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTCustom]": 13298034.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithClientTelemetryEnabled]": 13298733.75, + "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=OfTWithDiagnosticsToString]": 13517039.75, "MockedItemBenchmark.QuerySinglePartitionMultiplePages;[Type=Stream]": 5920952, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfT]": 2241814, "MockedItemBenchmark.QuerySinglePartitionOnePage;[Type=OfTCustom]": 2241810, @@ -30,25 +30,25 @@ "MockedItemBenchmark.ReadFeed;[Type=OfTCustom]": 555716, "MockedItemBenchmark.ReadFeed;[Type=OfTWithClientTelemetryEnabled]": 550898.25, "MockedItemBenchmark.ReadFeed;[Type=OfTWithDiagnosticsToString]": 573734.5, - "MockedItemBenchmark.ReadFeed;[Type=Stream]": 33434, - "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 33630.5, - "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 33636.25, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 33627.75, - "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 55044, - "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26018.25, + "MockedItemBenchmark.ReadFeed;[Type=Stream]": 34192, + "MockedItemBenchmark.ReadItemExists;[Type=OfT]": 34509.75, + "MockedItemBenchmark.ReadItemExists;[Type=OfTCustom]": 34516, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithClientTelemetryEnabled]": 34515.5, + "MockedItemBenchmark.ReadItemExists;[Type=OfTWithDiagnosticsToString]": 56524.5, + "MockedItemBenchmark.ReadItemExists;[Type=Stream]": 26752.5, "MockedItemBenchmark.ReadItemNotExists;[Type=OfT]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTCustom]": 43490, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithClientTelemetryEnabled]": 43489.25, "MockedItemBenchmark.ReadItemNotExists;[Type=OfTWithDiagnosticsToString]": 64764.75, - "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39044, - "MockedItemBenchmark.UpdateItem;[Type=OfT]": 36591, - "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 36594.25, - "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 36587.25, + "MockedItemBenchmark.ReadItemNotExists;[Type=Stream]": 39876, + "MockedItemBenchmark.UpdateItem;[Type=OfT]": 37505.5, + "MockedItemBenchmark.UpdateItem;[Type=OfTCustom]": 37496.25, + "MockedItemBenchmark.UpdateItem;[Type=OfTWithClientTelemetryEnabled]": 37516.5, "MockedItemBenchmark.UpdateItem;[Type=OfTWithDiagnosticsToString]": 59152, "MockedItemBenchmark.UpdateItem;[Type=Stream]": 25428, - "MockedItemBenchmark.UpsertItem;[Type=OfT]": 36577.25, - "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 36583.75, - "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 36578.5, + "MockedItemBenchmark.UpsertItem;[Type=OfT]": 37487.5, + "MockedItemBenchmark.UpsertItem;[Type=OfTCustom]": 37486, + "MockedItemBenchmark.UpsertItem;[Type=OfTWithClientTelemetryEnabled]": 37490, "MockedItemBenchmark.UpsertItem;[Type=OfTWithDiagnosticsToString]": 59613, "MockedItemBenchmark.UpsertItem;[Type=Stream]": 25445.5, "MockedItemBulkBenchmark.CreateItem;[Type=OfT]": 1196168, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index e0f94e3e64..d723a57df7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -100,6 +100,114 @@ public void PositiveOptimisticDirectExecutionOutput() }; this.ExecuteTestSuite(testVariations); + } + + [TestMethod] + public async Task QueryWithODEContinuationTokenShouldUseODEPipelineRegardlessOfODESettings() + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: CosmosElement.Parse( + "{\"OptimisticDirectExecutionToken\":{\"token\":\"{\\\"resourceId\\\":\\\"AQAAAMmFOw8LAAAAAAAAAA==\\\"," + + "\\\"skipCount\\\":1}\", \"range\":{\"min\":\"\",\"max\":\"FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF\"}}}")); + + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 9, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.AreEqual(90, result); + } + + input.PartitionKeyValue = Cosmos.PartitionKey.None; + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + try + { + await this.GetPipelineAndDrainAsync( + input, + numItems: 100, + isMultiPartition: true, + expectedContinuationTokenCount: 0, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.Fail("Expected exception. Received none."); + } + catch(InvalidOperationException ex) + { + Assert.IsTrue(ex.ToString().Contains("Execution of this query cannot resume using Optimistic Direct Execution continuation token due to partition split. Please restart the query without the continuation token.")); + } + } + } + + [TestMethod] + public async Task QueryWithoutODEContinuationTokenShouldHonorODESettings() + { + foreach ((bool enableODE, bool clientForceDisableODEFromBackend) in new[] { (true, true), (true, false), (false, true), (false, false) }) + { + int result = await this.GetPipelineAndDrainAsync( + CreateInput( + description: @"Single Partition Key and Ode continuation token", + query: "SELECT * FROM c", + expectedOptimisticDirectExecution: enableODE && !clientForceDisableODEFromBackend, + partitionKeyPath: @"/pk", + partitionKeyValue: "a", + continuationToken: null), + numItems: 100, + isMultiPartition: false, + expectedContinuationTokenCount: 10, + requiresDist: false, + enableOptimisticDirectExecution: enableODE, + clientDisableOde: clientForceDisableODEFromBackend); + Assert.AreEqual(100, result); + } + } + + [TestMethod] + public async Task TestQueriesWhichNeverRequireDistribution4() + { + // requiresDist = false + int numItems = 100; + List singlePartitionContainerTestCases = new List() + { + new RequiresDistributionTestCase("SELECT * FROM r", 10, 100), + new RequiresDistributionTestCase("SELECT VALUE r.id FROM r", 0, 10), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5", 0, 0), + new RequiresDistributionTestCase("SELECT r.id FROM r JOIN id IN r.id",0, 0), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r ORDER BY r.id", 0, 5), + new RequiresDistributionTestCase("SELECT TOP 5 r.id FROM r WHERE r.id > 5 ORDER BY r.id", 0, 0), + new RequiresDistributionTestCase("SELECT * FROM r OFFSET 5 LIMIT 3", 1, 3), + new RequiresDistributionTestCase("SELECT * FROM r WHERE r.id > 5 OFFSET 5 LIMIT 3", 0, 0) + }; + + foreach (RequiresDistributionTestCase testCase in singlePartitionContainerTestCases) + { + OptimisticDirectExecutionTestInput input = CreateInput( + description: @"Queries which will never require distribution", + query: testCase.Query, + expectedOptimisticDirectExecution: true, + partitionKeyPath: @"/pk", + partitionKeyValue: "a"); + + int result = await this.GetPipelineAndDrainAsync( + input, + numItems: numItems, + isMultiPartition: false, + expectedContinuationTokenCount: testCase.ExpectedContinuationTokenCount, + requiresDist: false); + + Assert.AreEqual(testCase.ExpectedDocumentCount, result); + } } [TestMethod] @@ -151,7 +259,7 @@ public void NegativeOptimisticDirectExecutionOutput() public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); - Assert.AreEqual(true, requestOptions.EnableOptimisticDirectExecution); + Assert.AreEqual(false, requestOptions.EnableOptimisticDirectExecution); } // test checks that the pipeline can take a query to the backend and returns its associated document(s). @@ -189,51 +297,6 @@ public async Task TestPipelineForBackendDocumentsOnSinglePartitionAsync() Assert.AreEqual(100, documentCountInSinglePartition); } - [TestMethod] - public async Task TestOdeTokenWithSpecializedPipeline() - { - int numItems = 100; - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: Guid.NewGuid().ToString(), - range: new Documents.Routing.Range("A", "B", true, false)); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - - OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Single Partition Key and Value Field", - query: "SELECT VALUE COUNT(1) FROM c", - expectedOptimisticDirectExecution: false, - partitionKeyPath: @"/pk", - partitionKeyValue: "a", - continuationToken: cosmosElementContinuationToken); - - DocumentContainer documentContainer = await CreateDocumentContainerAsync(numItems, multiPartition: false); - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: input.ExpectedOptimisticDirectExecution); - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); - - IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( - documentContainer, - cosmosQueryContextCore, - inputParameters, - NoOpTrace.Singleton); - - string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - - while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) - { - if (queryPipelineStage.Current.Failed) - { - Assert.IsTrue(queryPipelineStage.Current.InnerMostException.ToString().Contains(expectedErrorMessage)); - return; - } - - Assert.IsFalse(true); - break; - } - } - [TestMethod] public async Task TestQueriesWhichNeverRequireDistribution() { @@ -456,8 +519,15 @@ public async Task TestQueryValidityCheckWithODEAsync() public async Task TestPipelineForGoneExceptionOnSingleAndMultiplePartitionAsync() { Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: false)); - - Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: true)); + + // ISSUE-TODO-adityasa-2024/4/22 - Reenable this test. + // At the time of authoring this test, the TestCosmosQueryClient always simulated a single partition container scenario by returning a single 00-FF range + // in the GetTargetPartitionKeyRangesAsync call, regardless of whether test asks a MultiPartition container or not. + // As a result tests did not really simulate the multi-partition scenario, as far as CosmosQueryClient is concerned. + // While GetTargetPartitionKeyRangesAsync is now fixed to honor the container properties, GetCachedContainerQueryPropertiesAsync is still not fixed. + // Specifically it does not honor if the partition key is specified for query (container is multi-partition, but query is single partition). + // As a result, for following test, it does not use ODE pipeline which breaks the assertion in ExecuteGoneExceptionOnODEPipeline method. + // Assert.IsTrue(await ExecuteGoneExceptionOnODEPipeline(isMultiPartition: true)); } // test to check if failing fallback pipeline is handled properly @@ -479,7 +549,7 @@ public async Task TestPipelineForDistributedQueryAsync() OptimisticDirectExecutionTestInput input = CreateInput( description: @"Single Partition Key and Value Field", query: "SELECT AVG(c) FROM c", - expectedOptimisticDirectExecution: false, + expectedOptimisticDirectExecution: true, partitionKeyPath: @"/pk", partitionKeyValue: "a"); @@ -501,7 +571,7 @@ public async Task TestClientDisableOdeLogic() OptimisticDirectExecutionTestInput input = CreateInput( description: @"Single Partition Key and Value Field", query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, + expectedOptimisticDirectExecution: false, partitionKeyPath: @"/pk", partitionKeyValue: "a"); @@ -515,7 +585,8 @@ public async Task TestClientDisableOdeLogic() clientDisableOde: true); Assert.AreEqual(numItems, result); - + + input.ExpectedOptimisticDirectExecution = true; // Test with ClientDisableOde = false result = await this.GetPipelineAndDrainAsync( input, @@ -528,52 +599,6 @@ public async Task TestClientDisableOdeLogic() Assert.AreEqual(numItems, result); } - [TestMethod] - public async Task TestOdeFlagsWithContinuationToken() - { - ParallelContinuationToken parallelContinuationToken = new ParallelContinuationToken( - token: Guid.NewGuid().ToString(), - range: new Range("A", "B", true, false)); - - OptimisticDirectExecutionContinuationToken optimisticDirectExecutionContinuationToken = new OptimisticDirectExecutionContinuationToken(parallelContinuationToken); - CosmosElement cosmosElementContinuationToken = OptimisticDirectExecutionContinuationToken.ToCosmosElement(optimisticDirectExecutionContinuationToken); - - OptimisticDirectExecutionTestInput input = CreateInput( - description: @"Single Partition Key and Ode continuation token", - query: "SELECT * FROM c", - expectedOptimisticDirectExecution: true, - partitionKeyPath: @"/pk", - partitionKeyValue: "a", - continuationToken: cosmosElementContinuationToken); - - // All of these cases should throw the same exception message. - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: true, clientDisableOde: true); - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: true); - await this.ValidateErrorMessageWithModifiedOdeFlags(input, enableOde: false, clientDisableOde: false); - } - - private async Task ValidateErrorMessageWithModifiedOdeFlags(OptimisticDirectExecutionTestInput input, bool enableOde, bool clientDisableOde) - { - string expectedErrorMessage = "Execution of this query using the supplied continuation token requires EnableOptimisticDirectExecution to be set in QueryRequestOptions. " + - "If the error persists after that, contact system administrator."; - try - { - int result = await this.GetPipelineAndDrainAsync( - input, - numItems: 100, - isMultiPartition: false, - expectedContinuationTokenCount: 10, - requiresDist: false, - enableOde, - clientDisableOde); - - Assert.Fail("A MalformedContinuationTokenException was expected in this scenario"); - } - catch (Exception ex) - { - Assert.IsTrue(ex.InnerException.Message.Contains(expectedErrorMessage)); - } - } [TestMethod] public void TestTextDistributionPlanParsingFromStream() @@ -743,23 +768,26 @@ private async Task GetPipelineAndDrainAsync(OptimisticDirectExecutionTestIn int continuationTokenCount = 0; List documents = new List(); QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution); - DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); + DocumentContainer inMemoryCollection = await CreateDocumentContainerAsync(numItems, multiPartition: isMultiPartition, requiresDist: requiresDist); IQueryPipelineStage queryPipelineStage = CreateOdePipeline(input, inMemoryCollection, queryRequestOptions, clientDisableOde); while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton, cancellationToken: default)) { TryCatch tryGetPage = queryPipelineStage.Current; - tryGetPage.ThrowIfFailed(); + tryGetPage.ThrowIfFailed(); + bool isODEContinuationToken = input.ContinuationToken != null && + OptimisticDirectExecutionContinuationToken.IsOptimisticDirectExecutionContinuationToken(input.ContinuationToken); - if (clientDisableOde || !enableOptimisticDirectExecution) - { - Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); + if (!isODEContinuationToken && (clientDisableOde || !enableOptimisticDirectExecution)) + { + Assert.AreNotEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); } - - if (!clientDisableOde && enableOptimisticDirectExecution && !requiresDist) + else { Assert.AreEqual(TestInjections.PipelineType.OptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value); - } + } + + Assert.AreEqual(input.ExpectedOptimisticDirectExecution, queryRequestOptions.TestSettings.Stats.PipelineType.Value == TestInjections.PipelineType.OptimisticDirectExecution); documents.AddRange(tryGetPage.Result.Documents); @@ -807,7 +835,8 @@ internal static Tuple Get private static IQueryPipelineStage CreateOdePipeline(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) { - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, clientDisableOde); + List containerRanges = documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, cancellationToken: default).Result; + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, containerRanges, clientDisableOde); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -947,8 +976,9 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect // gets DocumentContainer IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(input.PartitionKeyDefinition); DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); - (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); + QueryRequestOptions queryRequestOptions = GetQueryRequestOptions(enableOptimisticDirectExecution: true); + List containerRanges = documentContainer.GetFeedRangesAsync(NoOpTrace.Singleton, cancellationToken: default).Result; + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions, containerRanges); IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( documentContainer, cosmosQueryContextCore, @@ -972,7 +1002,7 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect return new OptimisticDirectExecutionTestOutput(input.ExpectedOptimisticDirectExecution); } - private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions, bool clientDisableOde = false) + private static Tuple CreateInputParamsAndQueryContext(OptimisticDirectExecutionTestInput input, QueryRequestOptions queryRequestOptions, List containerRanges, bool clientDisableOde = false) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(input.Query), Documents.ResourceType.Document)); @@ -992,12 +1022,22 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect executionEnvironment: null, returnResultsInDeterministicOrder: null, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, - testInjections: queryRequestOptions.TestSettings); + testInjections: queryRequestOptions.TestSettings); + + List targetPkRanges = new (); + foreach(FeedRangeEpk feedRangeEpk in containerRanges) + { + targetPkRanges.Add(new PartitionKeyRange + { + MinInclusive = feedRangeEpk.Range.Min, + MaxExclusive = feedRangeEpk.Range.Max, + }); + } string databaseId = "db1234"; string resourceLink = $"dbs/{databaseId}/colls"; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(queryPartitionProvider), + client: new TestCosmosQueryClient(queryPartitionProvider, targetPkRanges), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), @@ -1221,11 +1261,13 @@ public override void SerializeAsXml(XmlWriter xmlWriter) internal class TestCosmosQueryClient : CosmosQueryClient { - private readonly QueryPartitionProvider queryPartitionProvider; + private readonly QueryPartitionProvider queryPartitionProvider; + private readonly IReadOnlyList targetPartitionKeyRanges; - public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider) + public TestCosmosQueryClient(QueryPartitionProvider queryPartitionProvider, IEnumerable targetPartitionKeyRanges) { - this.queryPartitionProvider = queryPartitionProvider; + this.queryPartitionProvider = queryPartitionProvider; + this.targetPartitionKeyRanges = targetPartitionKeyRanges.ToList(); } public override Action OnExecuteScalarQueryCallback => throw new NotImplementedException(); @@ -1283,12 +1325,7 @@ public override Task> GetTargetPartitionKeyRangeByFeedRa public override Task> GetTargetPartitionKeyRangesAsync(string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) { - return Task.FromResult(new List{new PartitionKeyRange() - { - MinInclusive = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, - MaxExclusive = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey - } - }); + return Task.FromResult(this.targetPartitionKeyRanges.ToList()); } public override Task> TryGetOverlappingRangesAsync(string collectionResourceId, Range range, bool forceRefresh = false) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index 2b68a66ce3..c8ca339530 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -274,7 +274,7 @@ public async Task OffsetLimitPageSize() await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10000 LIMIT 5000", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 110, expectedResults: 100, mockInMemoryContainer, documentContainer); await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 100, expectedResults: 100, mockInMemoryContainer, documentContainer); - await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 100, expectedResults: 0, mockInMemoryContainer, documentContainer); // OFFSET/LIMIT without ORDER BY await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 10 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); @@ -394,8 +394,15 @@ private async Task TestPageSizeAsync(string query, int expectedPageSize, int exp } ); + List targetPartitionKeyRanges = new (){ + new PartitionKeyRange() + { + MinInclusive = "", + MaxExclusive = "FF" + } + }; CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( - client: new TestCosmosQueryClient(GetQueryPartitionProvider()), + client: new TestCosmosQueryClient(GetQueryPartitionProvider(), targetPartitionKeyRanges), resourceTypeEnum: Documents.ResourceType.Document, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), From bf2f5ee19740718e422331d457e69ce28584fba8 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Sun, 28 Apr 2024 09:50:45 -0700 Subject: [PATCH 330/337] FaultInjection: Adds SendDelay ServerErrorType (#4447) * Initial Commit * nits --- .../FaultInjectionServerErrorResultBuilder.cs | 8 +- .../src/FaultInjectionServerErrorType.cs | 7 + .../src/implementataion/ChaosInterceptor.cs | 10 +- .../FaultInjectionRuleStore.cs | 20 ++ .../tests/FaultInjectionDirectModeTests.cs | 171 +++++++++++++++++- .../FaultInjection/tests/Utils/TestCommon.cs | 9 +- 6 files changed, 213 insertions(+), 12 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs index 6dfc17e0b0..65fea244bc 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorResultBuilder.cs @@ -42,15 +42,17 @@ public FaultInjectionServerErrorResultBuilder WithTimes(int times) /// /// Only used RESPONSE_DELAY and CONNECTION_DELAY. /// - /// For RESPONSE_DELAY, it is the delay added before the response. - /// For CONNECTION_DELAY, it is the delay added before the connection is established. + /// For , it is the delay added before the request is sent. + /// For , it is the delay added after the response is recieved. + /// For , it is the delay added before the connection is established. /// /// /// The duration of the delay. /// The current . public FaultInjectionServerErrorResultBuilder WithDelay(TimeSpan delay) { - if (this.serverErrorType == FaultInjectionServerErrorType.ResponseDelay + if ( this.serverErrorType == FaultInjectionServerErrorType.SendDelay + || this.serverErrorType == FaultInjectionServerErrorType.ResponseDelay || this.serverErrorType == FaultInjectionServerErrorType.ConnectionDelay) { this.delay = delay; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs index fa096f4d4c..961f27d65d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionServerErrorType.cs @@ -50,9 +50,16 @@ public enum FaultInjectionServerErrorType /// /// Used to simulate a transient timeout/broken connection when over request timeout + /// In this case, the request will be sent to the server before the delay /// ResponseDelay, + /// + /// Used to simulate a transient timeout/broken connection when over request timeout + /// In this case, the delay will occur before the request is sent to the server + /// + SendDelay, + /// /// Used to simulate hight channel acquisiton. /// When over a connection timeouts can simulate connectionTimeoutException diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs index fa92c25b3f..54c598f620 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/ChaosInterceptor.cs @@ -154,15 +154,15 @@ public void OnChannelDispose(Guid connectionCorrelationId) /// public async Task OnBeforeConnectionWriteAsync(ChannelCallArguments args) { - FaultInjectionServerErrorRule? serverResponseDelayRule = this.ruleStore?.FindRntbdServerResponseDelayRule(args); + FaultInjectionServerErrorRule? serverSendDelayRule = this.ruleStore?.FindRntbdServerSendDelayRule(args); - if (serverResponseDelayRule != null) + if (serverSendDelayRule != null) { - this.applicationContext.AddRuleExecution(serverResponseDelayRule.GetId(), args.CommonArguments.ActivityId); - TimeSpan delay = serverResponseDelayRule.GetDelay(); + this.applicationContext.AddRuleExecution(serverSendDelayRule.GetId(), args.CommonArguments.ActivityId); + TimeSpan delay = serverSendDelayRule.GetDelay(); DefaultTrace.TraceInformation("FaultInjection: FaultInjection Rule {0} Inserted {1} duration response delay for request {2}", - serverResponseDelayRule.GetId(), delay, args.CommonArguments.ActivityId); + serverSendDelayRule.GetId(), delay, args.CommonArguments.ActivityId); await Task.Delay(delay); } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs index df2804b6ed..ddcd51d481 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleStore.cs @@ -17,6 +17,7 @@ namespace Microsoft.Azure.Cosmos.FaultInjection internal class FaultInjectionRuleStore { private readonly ConcurrentDictionary serverResponseDelayRuleSet = new ConcurrentDictionary(); + private readonly ConcurrentDictionary serverSendDelayRuleSet = new ConcurrentDictionary(); private readonly ConcurrentDictionary serverResponseErrorRuleSet = new ConcurrentDictionary(); private readonly ConcurrentDictionary serverConnectionDelayRuleSet = new ConcurrentDictionary(); private readonly ConcurrentDictionary connectionErrorRuleSet = new ConcurrentDictionary(); @@ -79,6 +80,9 @@ public async Task ConfigureFaultInjectionRuleAsync( case FaultInjectionServerErrorType.ResponseDelay: this.serverResponseDelayRuleSet.TryAdd(serverErrorRule, 0); break; + case FaultInjectionServerErrorType.SendDelay: + this.serverSendDelayRuleSet.TryAdd(serverErrorRule, 0); + break; case FaultInjectionServerErrorType.ConnectionDelay: this.serverConnectionDelayRuleSet.TryAdd(serverErrorRule, 0); break; @@ -121,6 +125,22 @@ public async Task ConfigureFaultInjectionRuleAsync( return null; } + public FaultInjectionServerErrorRule? FindRntbdServerSendDelayRule(ChannelCallArguments args) + { + foreach (FaultInjectionServerErrorRule rule in this.serverSendDelayRuleSet.Keys) + { + if ((rule.GetConnectionType() == FaultInjectionConnectionType.Direct + || rule.GetConnectionType() == FaultInjectionConnectionType.All) + && rule.IsApplicable(args)) + { + return rule; + } + } + + return null; + } + + public FaultInjectionServerErrorRule? FindRntbdServerConnectionDelayRule( Uri callUri, DocumentServiceRequest request, diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs index 0996b0ab76..90fe71945a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs @@ -49,6 +49,7 @@ public async Task Initialize(bool multiRegion) PartitionKeyPath = "/Pk" }; this.container = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 5000); + await Task.Delay(5000); } public async Task InitilizePreferredRegionsClient(FaultInjector faultInjector, List preferredRegionList, bool multiRegion) @@ -61,6 +62,7 @@ public async Task InitilizePreferredRegionsClient(FaultInjector faultInjector, L Id = "test", PartitionKeyPath = "/Pk" }; + await Task.Delay(5000); this.container = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 5000); } @@ -566,7 +568,90 @@ private async Task Timeout_FaultInjectionServerErrorRule_PartitionTest() [TestMethod] [Owner("nalutripician")] - [Description("Tests response delay")] + [Description("Tests send delay")] + public void FaultInjectionServerErrorRule_ServerSendDelay() + { + if (!this.Timeout_FaultInjectionServerErrorRule_ServerSendDelay().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ServerSendDelay() + { + string sendDelayRuleId = "sendDelayRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule delayRule = new FaultInjectionRuleBuilder( + id: sendDelayRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.SendDelay) + .WithDelay(TimeSpan.FromSeconds(10)) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + delayRule.Disable(); + + await this.Initialize(true); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { delayRule }); + + CosmosClient testClient = new CosmosClient( + accountEndpoint: TestCommon.EndpointMultiRegion, + authKeyOrResourceToken: TestCommon.AuthKeyMultiRegion, + clientOptions: faultInjector.GetFaultInjectionClientOptions( + new CosmosClientOptions() + { + EnableContentResponseOnWrite = true, + ConnectionMode = ConnectionMode.Direct, + OpenTcpConnectionTimeout = TimeSpan.FromSeconds(1) + })); + + Container testContainer = testClient.GetContainer("testDb", "test"); + delayRule.Enable(); + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + CosmosDiagnostics createDiagnostics = await this.PerformDocumentOperation( + testContainer, + OperationType.Create, + createdItem); + + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + delayRule.Disable(); + + CosmosDiagnostics readDiagnostics = await this.PerformDocumentOperation( + testContainer, + OperationType.Read, + createdItem); + + Assert.IsTrue(readDiagnostics.ToString().Contains("404")); + Assert.IsTrue(elapsed.TotalSeconds >= 6); + this.ValidateHitCount(delayRule, 1); + this.ValidateFaultInjectionRuleApplication( + createDiagnostics, + (int)StatusCodes.RequestTimeout, + (int)SubStatusCodes.Unknown, + delayRule); + testClient.Dispose(); + } + finally + { + delayRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests send delay")] public void FaultInjectionServerErrorRule_ServerResponseDelay() { if (!this.Timeout_FaultInjectionServerErrorRule_ServerResponseDelay().Wait(Timeout)) @@ -576,6 +661,89 @@ public void FaultInjectionServerErrorRule_ServerResponseDelay() } private async Task Timeout_FaultInjectionServerErrorRule_ServerResponseDelay() + { + string responseDelayRuleId = "responseDelayRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule delayRule = new FaultInjectionRuleBuilder( + id: responseDelayRuleId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.CreateItem) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ResponseDelay) + .WithDelay(TimeSpan.FromSeconds(10)) + .WithTimes(1) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + delayRule.Disable(); + + await this.Initialize(true); + + try + { + FaultInjector faultInjector = new FaultInjector(new List { delayRule }); + + CosmosClient testClient = new CosmosClient( + accountEndpoint: TestCommon.EndpointMultiRegion, + authKeyOrResourceToken: TestCommon.AuthKeyMultiRegion, + clientOptions: faultInjector.GetFaultInjectionClientOptions( + new CosmosClientOptions() + { + EnableContentResponseOnWrite = true, + ConnectionMode = ConnectionMode.Direct, + OpenTcpConnectionTimeout = TimeSpan.FromSeconds(1) + })); + + Container testContainer = testClient.GetContainer("testDb", "test"); + delayRule.Enable(); + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + CosmosDiagnostics createDiagnostics = await this.PerformDocumentOperation( + testContainer, + OperationType.Create, + createdItem); + + elapsed = stopwatch.Elapsed; + stopwatch.Stop(); + delayRule.Disable(); + + CosmosDiagnostics readDiagnostics = await this.PerformDocumentOperation( + testContainer, + OperationType.Read, + createdItem); + + Assert.IsTrue(readDiagnostics.ToString().Contains("200")); + Assert.IsTrue(elapsed.TotalSeconds >= 6); + this.ValidateHitCount(delayRule, 1); + this.ValidateFaultInjectionRuleApplication( + createDiagnostics, + (int)StatusCodes.RequestTimeout, + (int)SubStatusCodes.Unknown, + delayRule); + testClient.Dispose(); + } + finally + { + delayRule.Disable(); + } + } + + [TestMethod] + [Owner("nalutripician")] + [Description("Tests response delay")] + public void FaultInjectionServerErrorRule_ServerTimeout() + { + if (!this.Timeout_FaultInjectionServerErrorRule_ServerTimeout().Wait(Timeout)) + { + Assert.Fail("Test timed out"); + } + } + + private async Task Timeout_FaultInjectionServerErrorRule_ServerTimeout() { string timeoutRuleId = "timeoutRule-" + Guid.NewGuid().ToString(); FaultInjectionRule timeoutRule = new FaultInjectionRuleBuilder( @@ -644,7 +812,6 @@ private async Task Timeout_FaultInjectionServerErrorRule_ServerResponseDelay() } [TestMethod] - [Ignore("Connection Timeouts are currently broken, next Direct release will fix issue")] [Owner("nalutripician")] [Description("Tests injection a connection timeout")] public void FaultInjectionServerErrorRule_ConnectionTimeout() diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs index 902bb7fe54..0a2e647ed1 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs @@ -59,8 +59,13 @@ internal static CosmosClientBuilder GetDefaultConfiguration( { CosmosClientBuilder clientBuilder = new CosmosClientBuilder( accountEndpoint: accountEndpointOverride - ?? (multiRegion ? EndpointMultiRegion : Endpoint), - authKeyOrResourceToken: multiRegion ? AuthKeyMultiRegion : AuthKey); + ?? EndpointMultiRegion, + authKeyOrResourceToken: AuthKeyMultiRegion); + + if (!multiRegion) + { + return clientBuilder.WithApplicationPreferredRegions(new List { "Central US" }); + } return clientBuilder; } From bda8290201e2a176927c44ba2d7786ac66227250 Mon Sep 17 00:00:00 2001 From: neildsh <35383880+neildsh@users.noreply.github.com> Date: Mon, 29 Apr 2024 14:17:12 -0700 Subject: [PATCH 331/337] Switch non streaming order by to use flag from query plan instead of _streaming in the response (#4459) --- ...OrderByCrossPartitionQueryPipelineStage.cs | 49 ++++++++++--------- .../Query/Core/Pipeline/PipelineFactory.cs | 3 +- .../Query/OrderByPipelineStageBenchmark.cs | 7 +-- .../Pipeline/NonStreamingOrderByQueryTests.cs | 16 ++++-- ...ByCrossPartitionQueryPipelineStageTests.cs | 25 +++++++--- 5 files changed, 63 insertions(+), 37 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs index cfe911966d..c5f0883089 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CrossPartition/OrderBy/OrderByCrossPartitionQueryPipelineStage.cs @@ -55,6 +55,8 @@ private sealed class InitializationParameters public int MaxConcurrency { get; } + public bool NonStreamingOrderBy { get; } + public InitializationParameters( IDocumentContainer documentContainer, SqlQuerySpec sqlQuerySpec, @@ -62,7 +64,8 @@ public InitializationParameters( PartitionKey? partitionKey, IReadOnlyList orderByColumns, QueryPaginationOptions queryPaginationOptions, - int maxConcurrency) + int maxConcurrency, + bool nonStreamingOrderBy) { this.DocumentContainer = documentContainer ?? throw new ArgumentNullException(nameof(documentContainer)); this.SqlQuerySpec = sqlQuerySpec ?? throw new ArgumentNullException(nameof(sqlQuerySpec)); @@ -71,6 +74,7 @@ public InitializationParameters( this.OrderByColumns = orderByColumns ?? throw new ArgumentNullException(nameof(orderByColumns)); this.QueryPaginationOptions = queryPaginationOptions ?? throw new ArgumentNullException(nameof(queryPaginationOptions)); this.MaxConcurrency = maxConcurrency; + this.NonStreamingOrderBy = nonStreamingOrderBy; } } @@ -181,6 +185,7 @@ public static TryCatch MonadicCreate( IReadOnlyList orderByColumns, QueryPaginationOptions queryPaginationOptions, int maxConcurrency, + bool nonStreamingOrderBy, CosmosElement continuationToken) { if (documentContainer == null) @@ -233,24 +238,28 @@ public static TryCatch MonadicCreate( partitionKey, orderByColumns, queryPaginationOptions, - maxConcurrency); + maxConcurrency, + nonStreamingOrderBy); return TryCatch.FromResult(new OrderByCrossPartitionQueryPipelineStage(init)); } - private static async ValueTask<(TryCatch, Queue)> MoveNextAsync_InitializeAsync(InitializationParameters init, ITrace trace, CancellationToken cancellationToken) + private static async ValueTask<(TryCatch, Queue)> MoveNextAsync_InitializeAsync( + InitializationParameters parameters, + ITrace trace, + CancellationToken cancellationToken) { SqlQuerySpec rewrittenQueryForOrderBy = new SqlQuerySpec( - init.SqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), - init.SqlQuerySpec.Parameters); + parameters.SqlQuerySpec.QueryText.Replace(oldValue: FormatPlaceHolder, newValue: TrueFilter), + parameters.SqlQuerySpec.Parameters); - List uninitializedEnumerators = init.TargetRanges + List uninitializedEnumerators = parameters.TargetRanges .Select(range => OrderByQueryPartitionRangePageAsyncEnumerator.Create( - init.DocumentContainer, + parameters.DocumentContainer, rewrittenQueryForOrderBy, new FeedRangeState(range, state: default), - init.PartitionKey, - init.QueryPaginationOptions, + parameters.PartitionKey, + parameters.QueryPaginationOptions, TrueFilter, PrefetchPolicy.PrefetchSinglePage)) .ToList(); @@ -259,13 +268,12 @@ public static TryCatch MonadicCreate( uninitializedEnumerators .Select(x => (x, (OrderByContinuationToken)null))); - await ParallelPrefetch.PrefetchInParallelAsync(uninitializedEnumerators, init.MaxConcurrency, trace, cancellationToken); + await ParallelPrefetch.PrefetchInParallelAsync(uninitializedEnumerators, parameters.MaxConcurrency, trace, cancellationToken); - IReadOnlyList sortOrders = init.OrderByColumns.Select(column => column.SortOrder).ToList(); + IReadOnlyList sortOrders = parameters.OrderByColumns.Select(column => column.SortOrder).ToList(); PriorityQueue initializedEnumerators = new PriorityQueue(new OrderByEnumeratorComparer(sortOrders)); Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)> enumeratorsAndTokens = new Queue<(OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken token)>(); - bool nonStreaming = false; Queue bufferedPages = new Queue(); QueryPageParameters queryPageParameters = null; while (uninitializedEnumeratorsAndTokens.Count != 0) @@ -278,7 +286,7 @@ public static TryCatch MonadicCreate( if (IsSplitException(enumerator.Current.Exception)) { await MoveNextAsync_InitializeAsync_HandleSplitAsync( - init.DocumentContainer, + parameters.DocumentContainer, uninitializedEnumeratorsAndTokens, enumerator, token, @@ -307,9 +315,6 @@ await MoveNextAsync_InitializeAsync_HandleSplitAsync( additionalHeaders: page.AdditionalHeaders); } - // For backwards compatibility the default value of streaming for ORDER BY is _true_ - nonStreaming = nonStreaming || (!page.Streaming.GetValueOrDefault(true) && (page.State != null)); - if (enumerator.Current.Result.Enumerator.MoveNext()) { // the page is non-empty then we need to enqueue the enumerator in the PriorityQueue @@ -335,7 +340,7 @@ await MoveNextAsync_InitializeAsync_HandleSplitAsync( } IQueryPipelineStage pipelineStage; - if (nonStreaming) + if (parameters.NonStreamingOrderBy) { Queue orderbyEnumerators = new Queue(); foreach ((OrderByQueryPartitionRangePageAsyncEnumerator enumerator, OrderByContinuationToken _) in enumeratorsAndTokens) @@ -350,10 +355,10 @@ await MoveNextAsync_InitializeAsync_HandleSplitAsync( orderbyEnumerators.Enqueue(bufferedEnumerator); } - await ParallelPrefetch.PrefetchInParallelAsync(orderbyEnumerators, init.MaxConcurrency, trace, cancellationToken); + await ParallelPrefetch.PrefetchInParallelAsync(orderbyEnumerators, parameters.MaxConcurrency, trace, cancellationToken); pipelineStage = await NonStreamingOrderByPipelineStage.CreateAsync( - init.QueryPaginationOptions, + parameters.QueryPaginationOptions, sortOrders, orderbyEnumerators, queryPageParameters, @@ -363,12 +368,12 @@ await MoveNextAsync_InitializeAsync_HandleSplitAsync( else { pipelineStage = StreamingOrderByCrossPartitionQueryPipelineStage.Create( - init.DocumentContainer, + parameters.DocumentContainer, sortOrders, initializedEnumerators, enumeratorsAndTokens, - init.QueryPaginationOptions, - init.MaxConcurrency); + parameters.QueryPaginationOptions, + parameters.MaxConcurrency); } return (TryCatch.FromResult(pipelineStage), bufferedPages); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs index 814682ba72..93008125fb 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/PipelineFactory.cs @@ -78,7 +78,8 @@ public static TryCatch MonadicCreate( .OrderByExpressions .Zip(queryInfo.OrderBy, (expression, sortOrder) => new OrderByColumn(expression, sortOrder)).ToList(), queryPaginationOptions: queryPaginationOptions, - maxConcurrency: maxConcurrency, + maxConcurrency: maxConcurrency, + nonStreamingOrderBy: queryInfo.HasNonStreamingOrderBy, continuationToken: continuationToken); } else diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs index 4ec2009758..226c587cee 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/OrderByPipelineStageBenchmark.cs @@ -44,16 +44,16 @@ FROM c [Benchmark(Baseline = true)] public Task StreamingOrderByPipelineStage() { - return CreateAndRunPipeline(StreamingContainer); + return CreateAndRunPipeline(StreamingContainer, nonStreamingOrderBy: false); } [Benchmark] public Task NonStreamingOrderByPipelineStage() { - return CreateAndRunPipeline(NonStreamingContainer); + return CreateAndRunPipeline(NonStreamingContainer, nonStreamingOrderBy: true); } - private static async Task CreateAndRunPipeline(IDocumentContainer documentContainer) + private static async Task CreateAndRunPipeline(IDocumentContainer documentContainer, bool nonStreamingOrderBy) { IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( trace: NoOpTrace.Singleton, @@ -67,6 +67,7 @@ private static async Task CreateAndRunPipeline(IDocumentContainer documentContai orderByColumns: OrderByColumns, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: EndUserPageSize), maxConcurrency: MaxConcurrency, + nonStreamingOrderBy: nonStreamingOrderBy, continuationToken: null); IQueryPipelineStage pipeline = pipelineStage.Result; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs index daac63b9b1..60d01dc69a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/NonStreamingOrderByQueryTests.cs @@ -228,14 +228,16 @@ private static async Task RunParityTests( ranges: ranges, queryText: testCase.QueryText, orderByColumns: testCase.OrderByColumns, - pageSize: pageSize); + pageSize: pageSize, + nonStreamingOrderBy: true); IReadOnlyList streamingResult = await CreateAndRunPipelineStage( documentContainer: documentContainer, ranges: ranges, queryText: testCase.QueryText, orderByColumns: testCase.OrderByColumns, - pageSize: pageSize); + pageSize: pageSize, + nonStreamingOrderBy: false); if (!streamingResult.SequenceEqual(nonStreamingResult)) { @@ -255,7 +257,8 @@ private static async Task> CreateAndRunPipelineStag IReadOnlyList ranges, string queryText, IReadOnlyList orderByColumns, - int pageSize) + int pageSize, + bool nonStreamingOrderBy) { TryCatch pipelineStage = OrderByCrossPartitionQueryPipelineStage.MonadicCreate( documentContainer: documentContainer, @@ -265,6 +268,7 @@ private static async Task> CreateAndRunPipelineStag orderByColumns: orderByColumns, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: pageSize), maxConcurrency: MaxConcurrency, + nonStreamingOrderBy: nonStreamingOrderBy, continuationToken: null); Assert.IsTrue(pipelineStage.Succeeded); @@ -311,7 +315,8 @@ private static async Task RunParityTests(IReadOnlyList testCases ranges: ranges, queryText: testCase.QueryText, orderByColumns: testCase.OrderByColumns, - pageSize: pageSize); + pageSize: pageSize, + nonStreamingOrderBy: true); DebugTraceHelpers.TraceStreamingPipelineStarting(); IReadOnlyList streamingResult = await CreateAndRunPipelineStage( @@ -319,7 +324,8 @@ private static async Task RunParityTests(IReadOnlyList testCases ranges: ranges, queryText: testCase.QueryText, orderByColumns: testCase.OrderByColumns, - pageSize: pageSize); + pageSize: pageSize, + nonStreamingOrderBy: false); if (!streamingResult.SequenceEqual(nonStreamingResult)) { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs index eebd3b1b83..af77a51996 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/OrderByCrossPartitionQueryPipelineStageTests.cs @@ -77,7 +77,8 @@ public void MonadicCreate_NullContinuationToken() new OrderByColumn("_ts", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - maxConcurrency: 10, + maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); } @@ -98,6 +99,7 @@ public void MonadicCreate_NonCosmosArrayContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosObject.Create(new Dictionary())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -119,6 +121,7 @@ public void MonadicCreate_EmptyArrayContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create(new List())); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -140,6 +143,7 @@ public void MonadicCreate_NonParallelContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create(new List() { CosmosString.Create("asdf") })); Assert.IsTrue(monadicCreate.Failed); Assert.IsTrue(monadicCreate.InnerMostException is MalformedContinuationTokenException); @@ -176,6 +180,7 @@ public void MonadicCreate_SingleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create( new List() { @@ -220,6 +225,7 @@ public void MonadicCreate_SingleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create( new List() { @@ -279,6 +285,7 @@ public void MonadicCreate_MultipleOrderByContinuationToken() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create( new List() { @@ -321,6 +328,7 @@ public void MonadicCreate_OrderByWithResumeValues() }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create( new List() { @@ -361,7 +369,8 @@ public void MonadicCreate_OrderByWithResumeValues() new OrderByColumn("item2", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - maxConcurrency: 10, + maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: CosmosArray.Create( new List() { @@ -416,7 +425,8 @@ public async Task TestFormattedFiltersForTargetPartitionWithContinuationTokenAsy new OrderByColumn("c._ts", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 1), - maxConcurrency: 0, + maxConcurrency: 0, + nonStreamingOrderBy: false, continuationToken: CosmosElement.Parse(continuationToken)); Assert.IsTrue(monadicCreate.Succeeded); @@ -451,7 +461,8 @@ FROM c new OrderByColumn("c._ts", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - maxConcurrency: 10, + maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); IQueryPipelineStage queryPipelineStage = monadicCreate.Result; @@ -500,7 +511,8 @@ FROM c new OrderByColumn("c._ts", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - maxConcurrency: 10, + maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: null); Assert.IsTrue(monadicCreate.Succeeded); IQueryPipelineStage queryPipelineStage = monadicCreate.Result; @@ -557,7 +569,8 @@ FROM c new OrderByColumn("c.pk", SortOrder.Ascending) }, queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: 10), - maxConcurrency: 10, + maxConcurrency: 10, + nonStreamingOrderBy: false, continuationToken: continuationToken); monadicQueryPipelineStage.ThrowIfFailed(); IQueryPipelineStage queryPipelineStage = monadicQueryPipelineStage.Result; From a33144864e96eb877941c766b55418c82f865186 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:49:53 -0700 Subject: [PATCH 332/337] FaultInjection: Adds ReadFeed Operation Type (#4448) * initial commit * fixed tests * nits * small fixes * fixed test --- .../src/FaultInjectionOperationType.cs | 5 ++ .../FaultInjectionRuleProcessor.cs | 1 + ...FaultInjectionServerErrorResultInternal.cs | 24 ++++- .../tests/FaultInjectionDirectModeTests.cs | 89 +++++++++++++++++++ .../FaultInjection/tests/Utils/TestCommon.cs | 2 - 5 files changed, 115 insertions(+), 6 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs index 675e33f4bb..ea8b3d19d1 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/FaultInjectionOperationType.cs @@ -48,6 +48,11 @@ public enum FaultInjectionOperationType /// Batch, + /// + /// Read Feed operations for ChangeFeed. + /// + ReadFeed, + /// /// All operation types. Default value. /// diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs index a9ebdf9b73..4ef98d4c71 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionRuleProcessor.cs @@ -214,6 +214,7 @@ private OperationType GetEffectiveOperationType(FaultInjectionOperationType faul FaultInjectionOperationType.DeleteItem => OperationType.Delete, FaultInjectionOperationType.PatchItem => OperationType.Patch, FaultInjectionOperationType.Batch => OperationType.Batch, + FaultInjectionOperationType.ReadFeed => OperationType.ReadFeed, _ => throw new ArgumentException($"FaultInjectionOperationType: {faultInjectionOperationType} is not supported"), }; } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs index e903d61ca5..d4f1a2407b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/src/implementataion/FaultInjectionServerErrorResultInternal.cs @@ -123,12 +123,14 @@ public FaultInjectionServerErrorType GetInjectedServerErrorType() public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ruleId) { StoreResponse storeResponse; + string lsn = args.RequestHeaders.Get(WFConstants.BackendHeaders.LSN) ?? "0"; switch (this.serverErrorType) { case FaultInjectionServerErrorType.Gone: INameValueCollection goneHeaders = args.RequestHeaders; goneHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ServerGenerated410).ToString(CultureInfo.InvariantCulture)); + goneHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { Status = 410, @@ -139,10 +141,12 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru return storeResponse; case FaultInjectionServerErrorType.RetryWith: + INameValueCollection retryWithHeaders = args.RequestHeaders; + retryWithHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { Status = 449, - Headers = args.RequestHeaders, + Headers = retryWithHeaders, ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Retry With, rule: {ruleId}")) }; @@ -152,6 +156,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru INameValueCollection tooManyRequestsHeaders = args.RequestHeaders; tooManyRequestsHeaders.Set(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, "500"); tooManyRequestsHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.RUBudgetExceeded).ToString(CultureInfo.InvariantCulture)); + tooManyRequestsHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { @@ -163,21 +168,26 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru return storeResponse; case FaultInjectionServerErrorType.Timeout: + INameValueCollection timeoutHeaders = args.RequestHeaders; + timeoutHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { Status = 408, - Headers = args.RequestHeaders, + Headers = timeoutHeaders, ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Timeout, rule: {ruleId}")) }; return storeResponse; case FaultInjectionServerErrorType.InternalServerEror: + INameValueCollection internalServerErrorHeaders = args.RequestHeaders; + internalServerErrorHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); + storeResponse = new StoreResponse() { Status = 500, - Headers = args.RequestHeaders, + Headers = internalServerErrorHeaders, ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Internal Server Error, rule: {ruleId}")) }; @@ -190,6 +200,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru INameValueCollection readSessionHeaders = args.RequestHeaders; readSessionHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString(CultureInfo.InvariantCulture)); readSessionHeaders.Set(HttpConstants.HttpHeaders.SessionToken, badSesstionToken); + readSessionHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { @@ -203,6 +214,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru case FaultInjectionServerErrorType.PartitionIsMigrating: INameValueCollection partitionMigrationHeaders = args.RequestHeaders; partitionMigrationHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture)); + partitionMigrationHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { @@ -216,6 +228,7 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru case FaultInjectionServerErrorType.PartitionIsSplitting: INameValueCollection partitionSplitting = args.RequestHeaders; partitionSplitting.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture)); + partitionSplitting.Set(WFConstants.BackendHeaders.LocalLSN, lsn); storeResponse = new StoreResponse() { @@ -226,10 +239,13 @@ public StoreResponse GetInjectedServerError(ChannelCallArguments args, string ru return storeResponse; case FaultInjectionServerErrorType.ServiceUnavailable: + INameValueCollection serviceUnavailableHeaders = args.RequestHeaders; + serviceUnavailableHeaders.Set(WFConstants.BackendHeaders.LocalLSN, lsn); + storeResponse = new StoreResponse() { Status = 503, - Headers = args.RequestHeaders, + Headers = serviceUnavailableHeaders, ResponseBody = new MemoryStream(Encoding.UTF8.GetBytes($"Fault Injection Server Error: Service Unavailable, rule: {ruleId}")) }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs index 90fe71945a..56da481229 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/FaultInjectionDirectModeTests.cs @@ -9,8 +9,10 @@ namespace Microsoft.Azure.Cosmos.FaultInjection.Tests using System.Linq; using System.Net; using System.Net.Sockets; + using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos; + using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.FaultInjection.Tests.Utils; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Documents; @@ -1276,6 +1278,93 @@ private async Task Timeout_FaultInjectionConnectionErrorRule_Test() Assert.IsTrue(disposedChannel); } + [TestMethod] + [Timeout(Timeout)] + [Owner("nalutripician")] + [Description("Tests ReadFeed FaultInjection")] + public async Task FaultInjectionServerErrorRule_ReadFeedTest() + { + string readFeedId = "readFeadRule-" + Guid.NewGuid().ToString(); + FaultInjectionRule readFeedRule = new FaultInjectionRuleBuilder( + id: readFeedId, + condition: + new FaultInjectionConditionBuilder() + .WithOperationType(FaultInjectionOperationType.ReadFeed) + .Build(), + result: + FaultInjectionResultBuilder.GetResultBuilder(FaultInjectionServerErrorType.ServiceUnavailable) + .Build()) + .WithDuration(TimeSpan.FromMinutes(5)) + .Build(); + + readFeedRule.Disable(); + + List ruleList = new List { readFeedRule }; + FaultInjector faultInjector = new FaultInjector(ruleList); + + await this.Initialize(faultInjector, false); + + string changeFeedContainerName = "changeFeedContainer-" + Guid.NewGuid().ToString(); + ContainerProperties containerProperties = new ContainerProperties + { + Id = changeFeedContainerName, + PartitionKeyPath = "/partitionKey" + }; + + if (this.database != null && this.container != null) + { + JObject createdItem = JObject.FromObject(new { id = Guid.NewGuid().ToString(), Pk = Guid.NewGuid().ToString() }); + ItemResponse? itemResponse = await this.container.CreateItemAsync(createdItem); + + readFeedRule.Enable(); + + Container? leaseContainer = await this.database.CreateContainerIfNotExistsAsync(containerProperties, 400); + + ManualResetEvent changeFeedRan = new ManualResetEvent(false); + + ChangeFeedProcessor changeFeedProcessor = this.container.GetChangeFeedProcessorBuilder( + "FaultInjectionTest", + (ChangeFeedProcessorContext context, IReadOnlyCollection docs, CancellationToken token) => + { + Assert.Fail("Change Feed Should Fail"); + return Task.CompletedTask; + }) + .WithInstanceName("test") + .WithLeaseContainer(leaseContainer) + .WithStartFromBeginning() + .WithErrorNotification((string lease, Exception exception) => + { + if (exception is CosmosException cosmosException) + { + Assert.AreEqual(HttpStatusCode.ServiceUnavailable, cosmosException.StatusCode); + } + else + { + Assert.Fail("Unexpected Exception"); + } + + changeFeedRan.Set(); + return Task.CompletedTask; + }) + .Build(); + + await changeFeedProcessor.StartAsync(); + await Task.Delay(1000); + + try + { + bool wasProcessed = changeFeedRan.WaitOne(60000); + Assert.IsTrue(wasProcessed, "Timed out waiting for handler to execute"); + } + finally + { + await changeFeedProcessor.StopAsync(); + readFeedRule.Disable(); + } + } + } + + private async Task PerformDocumentOperation(Container testContainer, OperationType operationType, JObject item) { try diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs index 0a2e647ed1..310e4c0049 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/FaultInjection/tests/Utils/TestCommon.cs @@ -6,8 +6,6 @@ internal static class TestCommon { - public const string Endpoint = ""; - public const string AuthKey = ""; public const string EndpointMultiRegion = ""; public const string AuthKeyMultiRegion = ""; From ca4b969db063537c927e3f11e3973512a3c0a09d Mon Sep 17 00:00:00 2001 From: Matias Quaranta Date: Tue, 30 Apr 2024 13:03:41 -0700 Subject: [PATCH 333/337] [Internal] Pipelines: Adds rolling pipeline (#4460) * adding opt-in flags * adding pipeline --- azure-pipelines-rolling.yml | 26 ++++++++++++++++++++++++++ templates/build-test.yml | 7 +++++-- 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 azure-pipelines-rolling.yml diff --git a/azure-pipelines-rolling.yml b/azure-pipelines-rolling.yml new file mode 100644 index 0000000000..bd743e0694 --- /dev/null +++ b/azure-pipelines-rolling.yml @@ -0,0 +1,26 @@ +# A pipeline with no CI trigger +trigger: none + +pr: none + +schedules: +- cron: "0 7,13,0,5 * * *" # cron syntax https://learn.microsoft.com/en-us/azure/devops/pipelines/process/scheduled-triggers?view=azure-devops&tabs=yaml#cron-syntax + displayName: Cosmos Rolling + branches: + include: + - master + always: true # whether to always run the pipeline or only if there have been source code changes since the last run. The default is false + +variables: + ReleaseArguments: ' --filter "TestCategory!=Quarantine & TestCategory!=Functional" --verbosity normal ' + VmImage: windows-latest # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops + +jobs: +- template: templates/build-test.yml + parameters: + BuildConfiguration: Release + Arguments: $(ReleaseArguments) + VmImage: $(VmImage) + MultiRegionConnectionString: $(COSMOSDB_MULTI_REGION) + IncludeEncryption: true + IncludePerformance: false diff --git a/templates/build-test.yml b/templates/build-test.yml index a3cfedd231..f4074ecce1 100644 --- a/templates/build-test.yml +++ b/templates/build-test.yml @@ -12,6 +12,8 @@ parameters: EmulatorPipeline2CategoryListName: ' Others ' EmulatorPipeline3CategoryListName: ' MultiRegion ' MultiRegionConnectionString : '' + IncludeEncryption: true + IncludePerformance: true jobs: - job: @@ -53,6 +55,7 @@ jobs: - job: displayName: PerformanceTests ${{ parameters.BuildConfiguration }} + condition: and(succeeded(), eq(${{ parameters.IncludePerformance }}, true)) pool: vmImage: ${{ parameters.VmImage }} @@ -150,7 +153,7 @@ jobs: - job: displayName: Encryption EmulatorTests ${{ parameters.BuildConfiguration }} timeoutInMinutes: 90 - condition: and(succeeded(), eq('${{ parameters.OS }}', 'Windows')) + condition: and(eq(${{ parameters.IncludeEncryption }}, true), and(succeeded(), eq('${{ parameters.OS }}', 'Windows'))) pool: vmImage: ${{ parameters.VmImage }} @@ -181,7 +184,7 @@ jobs: - job: displayName: Encryption.Custom EmulatorTests ${{ parameters.BuildConfiguration }} timeoutInMinutes: 90 - condition: and(succeeded(), eq('${{ parameters.OS }}', 'Windows')) + condition: and(eq(${{ parameters.IncludeEncryption }}, true), and(succeeded(), eq('${{ parameters.OS }}', 'Windows'))) pool: vmImage: ${{ parameters.VmImage }} From f304e970c5fc0f0eb42547e7d09e55bdc05876de Mon Sep 17 00:00:00 2001 From: Maya Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Wed, 1 May 2024 12:21:11 -0700 Subject: [PATCH 334/337] initial commit (#4253) Co-authored-by: Matias Quaranta --- .../src/Linq/DefaultCosmosLinqSerializer.cs | 10 +++++++++- ...ializerBaseline.TestMemberInitializerDataMember.xml | 6 +++--- ...rBaseline.TestMemberInitializerDotNetDataMember.xml | 6 +++--- ...ializerBaseline.TestMemberInitializerNewtonsoft.xml | 6 +++--- ...eline.TestMemberInitializerNewtonsoftDataMember.xml | 6 +++--- ...rBaseline.TestMemberInitializerNewtonsoftDotNet.xml | 6 +++--- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs index 31f20d5059..e616d8b349 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs @@ -11,6 +11,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Runtime.Serialization; using Microsoft.Azure.Documents; using Newtonsoft.Json; + using Newtonsoft.Json.Serialization; internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializerInternal { @@ -67,7 +68,14 @@ public string Serialize(object value, MemberExpression memberExpression, Type me public string SerializeScalarExpression(ConstantExpression inputExpression) { - return JsonConvert.SerializeObject(inputExpression.Value); + JsonSerializerSettings settings = this.PropertyNamingPolicy == CosmosPropertyNamingPolicy.CamelCase + ? new JsonSerializerSettings + { + ContractResolver = new CamelCasePropertyNamesContractResolver() + } + : new JsonSerializerSettings(); + + return JsonConvert.SerializeObject(inputExpression.Value, settings); } public string SerializeMemberName(MemberInfo memberInfo) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml index 215d593da2..4fd075260e 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/LinqTranslationWithCustomSerializerBaseline.TestMemberInitializerDataMember.xml @@ -29,7 +29,7 @@ WHERE (root["numericFieldDataMember"] = 1)]]> +WHERE (root = {"numericFieldDataMember": 1, "stringFieldDataMember": "1", "id": null, "pk": null, "dateTimeFieldDataMember": null, "dataTypeFieldDataMember": null})]]> 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1", "id": null, "Pk": null, "DateTimeFieldDataMember": null, "DataTypeFieldDataMember": null}) +SELECT VALUE ((root["numericFieldDataMember"] > 1) ? {"numericFieldDataMember": 1, "stringFieldDataMember": "1", "id": null, "pk": null, "dateTimeFieldDataMember": null, "dataTypeFieldDataMember": null} : {"numericFieldDataMember": 1, "stringFieldDataMember": "1", "id": null, "pk": null, "dateTimeFieldDataMember": null, "dataTypeFieldDataMember": null}) FROM root]]> +WHERE (root = {"numericFieldDataMember": 1, "stringFieldDataMember": "1"})]]> 1) ? {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"} : {"NumericFieldDataMember": 1, "StringFieldDataMember": "1"}) +SELECT VALUE ((root["numericFieldDataMember"] > 1) ? {"numericFieldDataMember": 1, "stringFieldDataMember": "1"} : {"numericFieldDataMember": 1, "stringFieldDataMember": "1"}) FROM root]]> +WHERE (root = {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null, "dateTimeField": null, "dataTypeField": null})]]> 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null, "DateTimeField": null, "DataTypeField": null}) +SELECT VALUE ((root["numberValueNewtonsoft"] > 1) ? {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null, "dateTimeField": null, "dataTypeField": null} : {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null, "dateTimeField": null, "dataTypeField": null}) FROM root]]> +WHERE (root = {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1"})]]> 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1"}) +SELECT VALUE ((root["numberValueNewtonsoft"] > 1) ? {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1"} : {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1"}) FROM root]]> +WHERE (root = {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null})]]> 1) ? {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null} : {"NumberValueNewtonsoft": 1, "StringValueNewtonsoft": "1", "id": null, "Pk": null}) +SELECT VALUE ((root["numberValueNewtonsoft"] > 1) ? {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null} : {"numberValueNewtonsoft": 1, "stringValueNewtonsoft": "1", "id": null, "pk": null}) FROM root]]> Date: Thu, 2 May 2024 09:50:26 +0530 Subject: [PATCH 335/337] Distributed Tracing: Adds Request charge and Payload size Threshold options (#4433) * Added Request charge and Payload size options to generate request diagnostics * Added default values * add exception handling for payload size * Added test * update contract file * added docs * add null check * added more docs * updated contract * changed event name * remove unused import --- .../src/CosmosClientTelemetryOptions.cs | 24 ++- .../src/CosmosThresholdOptions.cs | 34 ++- .../OpenTelemetry/CosmosDbEventSource.cs | 33 +-- .../Filters/DiagnosticsFilterHelper.cs | 47 +++- ...riterBaselineTests.BulkOperationsAsync.xml | 200 +++++++++--------- ...aceWriterBaselineTests.ChangeFeedAsync.xml | 42 ++-- ...eWriterBaselineTests.MiscellanousAsync.xml | 8 +- ...EndTraceWriterBaselineTests.QueryAsync.xml | 56 ++--- ...TraceWriterBaselineTests.ReadFeedAsync.xml | 32 +-- ...TraceWriterBaselineTests.ReadManyAsync.xml | 4 +- ...selineTests.StreamPointOperationsAsync.xml | 8 +- ...aselineTests.TypedPointOperationsAsync.xml | 8 +- .../Contracts/DotNetSDKAPI.json | 38 ++++ .../Telemetry/DiagnosticsFilterHelperTest.cs | 33 ++- 14 files changed, 358 insertions(+), 209 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs index ec16c0f3b8..a8bf4d44d7 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientTelemetryOptions.cs @@ -10,17 +10,30 @@ namespace Microsoft.Azure.Cosmos public class CosmosClientTelemetryOptions { /// - /// Disable sending telemetry to service, is not applicable to this as of now. + /// Disable sending telemetry data to Microsoft, is not applicable for this. /// - /// This option will disable sending telemetry to service.even it is opt-in from portal. + /// This feature has to be enabled at 2 places: + /// + /// Opt-in from portal to subscribe for this feature. + /// Setting this property to false, to enable it for a particular client instance. + /// + /// /// true public bool DisableSendingMetricsToService { get; set; } = true; /// - /// This method enable/disable generation of operation level if listener is subscribed to the Source Name "Azure.Cosmos.Operation". + /// This method enable/disable generation of operation level if listener is subscribed to the Source Name "Azure.Cosmos.Operation"(to capture operation level traces) + /// and "Azure-Cosmos-Operation-Request-Diagnostics"(to capture events with request diagnostics JSON) /// /// false - /// Please Refer https://opentelemetry.io/docs/instrumentation/net/exporters/ to know more about open telemetry exporters + /// + /// You can set different thresholds values by setting . + /// It would generate events with Request Diagnostics JSON, if any of the configured threshold is crossed, otherwise it would always generate events with Request Diagnostics JSON for failed requests. + /// There is some overhead of emitting the more detailed diagnostics - so recommendation is to choose these thresholds that reduce the noise level + /// and only emit detailed diagnostics when there is really business impact seen.

+ /// Refer to know more about open telemetry exporters available.

+ /// Refer to know more about this feature. + ///
public bool DisableDistributedTracing { get; set; } = #if PREVIEW false; @@ -30,9 +43,8 @@ public class CosmosClientTelemetryOptions /// /// Threshold values for Distributed Tracing. - /// These values decides whether to generate operation level with request diagnostics or not. + /// These values decides whether to generate an with request diagnostics or not. /// public CosmosThresholdOptions CosmosThresholdOptions { get; set; } = new CosmosThresholdOptions(); - } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs index b4f59d25f0..3eb768f71b 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosThresholdOptions.cs @@ -7,20 +7,48 @@ namespace Microsoft.Azure.Cosmos using System; /// - /// Threshold values for Distributed Tracing + /// This class describes the thresholds when more details diagnostics events are emitted, if subscribed, for an operation due to high latency, + /// high RU consumption or high payload sizes. /// public class CosmosThresholdOptions { /// - /// Latency Threshold for non point operations i.e. Query + /// Can be used to define custom latency thresholds. When the latency threshold is exceeded more detailed + /// diagnostics will be emitted (including the request diagnostics). There is some overhead of emitting the + /// more detailed diagnostics - so recommendation is to choose latency thresholds that reduce the noise level + /// and only emit detailed diagnostics when there is really business impact seen. + /// The default value for the point operation latency threshold is 3 seconds. + /// all operations except (ReadItem, CreateItem, UpsertItem, ReplaceItem, PatchItem or DeleteItem) /// /// 3 seconds public TimeSpan NonPointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(3); /// - /// Latency Threshold for point operations i.e operation other than Query + /// Can be used to define custom latency thresholds. When the latency threshold is exceeded more detailed + /// diagnostics will be emitted (including the request diagnostics). There is some overhead of emitting the + /// more detailed diagnostics - so recommendation is to choose latency thresholds that reduce the noise level + /// and only emit detailed diagnostics when there is really business impact seen. + /// The default value for the point operation latency threshold is 1 second. + /// Point Operations are: (ReadItem, CreateItem, UpsertItem, ReplaceItem, PatchItem or DeleteItem) /// /// 1 second public TimeSpan PointOperationLatencyThreshold { get; set; } = TimeSpan.FromSeconds(1); + + /// + /// Can be used to define a custom RU (request charge) threshold. When the threshold is exceeded more detailed + /// diagnostics will be emitted (including the request diagnostics). There is some overhead of emitting the + /// more detailed diagnostics - so recommendation is to choose a request charge threshold that reduces the noise + /// level and only emits detailed diagnostics when the request charge is significantly higher than expected. + /// + public double? RequestChargeThreshold { get; set; } = null; + + /// + /// Can be used to define a payload size threshold. When the threshold is exceeded for either request or + /// response payloads more detailed diagnostics will be emitted (including the request diagnostics). + /// There is some overhead of emitting the more detailed diagnostics - so recommendation is to choose a + /// payload size threshold that reduces the noise level and only emits detailed diagnostics when the payload size + /// is significantly higher than expected. + /// + public int? PayloadSizeThresholdInBytes { get; set; } = null; } } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs index f7fe0c307f..fbcae597c9 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/CosmosDbEventSource.cs @@ -15,7 +15,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry internal sealed class CosmosDbEventSource : AzureEventSource { internal const string EventSourceName = "Azure-Cosmos-Operation-Request-Diagnostics"; - + private static CosmosDbEventSource Singleton { get; } = new CosmosDbEventSource(); private CosmosDbEventSource() @@ -35,17 +35,26 @@ public static void RecordDiagnosticsForRequests( Documents.OperationType operationType, OpenTelemetryAttributes response) { - if (!DiagnosticsFilterHelper.IsSuccessfulResponse( - response.StatusCode, response.SubStatusCode) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) - { - CosmosDbEventSource.Singleton.FailedRequest(response.Diagnostics.ToString()); - } - else if (DiagnosticsFilterHelper.IsLatencyThresholdCrossed( - config: config, - operationType: operationType, - response: response) && CosmosDbEventSource.IsEnabled(EventLevel.Warning)) + if (CosmosDbEventSource.IsEnabled(EventLevel.Warning)) { - CosmosDbEventSource.Singleton.LatencyOverThreshold(response.Diagnostics.ToString()); + if (!DiagnosticsFilterHelper.IsSuccessfulResponse( + response.StatusCode, response.SubStatusCode)) + { + CosmosDbEventSource.Singleton.FailedRequest(response.Diagnostics.ToString()); + } + else if (DiagnosticsFilterHelper.IsLatencyThresholdCrossed( + config: config, + operationType: operationType, + response: response) || + (config.RequestChargeThreshold is not null && + config.RequestChargeThreshold <= response.RequestCharge) || + (config.PayloadSizeThresholdInBytes is not null && + DiagnosticsFilterHelper.IsPayloadSizeThresholdCrossed( + config: config, + response: response))) + { + CosmosDbEventSource.Singleton.ThresholdViolation(response.Diagnostics.ToString()); + } } } @@ -65,7 +74,7 @@ private void Exception(string message) } [Event(2, Level = EventLevel.Warning)] - private void LatencyOverThreshold(string message) + private void ThresholdViolation(string message) { this.WriteEvent(2, message); } diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index 3c0646f101..0d0c7019f1 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -21,28 +21,59 @@ public static bool IsLatencyThresholdCrossed( OperationType operationType, OpenTelemetryAttributes response) { - return response.Diagnostics.GetClientElapsedTime() > DiagnosticsFilterHelper.DefaultThreshold(operationType, config); + return response.Diagnostics.GetClientElapsedTime() > DiagnosticsFilterHelper.DefaultLatencyThreshold(operationType, config); + } + + /// + /// Allow only Payload size(request/response) is more the configured threshold + /// + /// true or false + public static bool IsPayloadSizeThresholdCrossed( + CosmosThresholdOptions config, + OpenTelemetryAttributes response) + { + int requestContentLength = 0; + int responseContentLength = 0; + try + { + requestContentLength = Convert.ToInt32(response.RequestContentLength); + } + catch (Exception) + { + // Ignore, if this conversion fails for any reason. + } + + try + { + responseContentLength = Convert.ToInt32(response.ResponseContentLength); + } + catch (Exception) + { + // Ignore, if this conversion fails for any reason. + } + + return config.PayloadSizeThresholdInBytes <= Math.Max(requestContentLength, responseContentLength); } /// /// Check if response HTTP status code is returning successful /// /// true or false - public static bool IsSuccessfulResponse(HttpStatusCode statusCode, int substatusCode) + public static bool IsSuccessfulResponse(HttpStatusCode statusCode, int subStatusCode) { return statusCode.IsSuccess() - || (statusCode == System.Net.HttpStatusCode.NotFound && substatusCode == 0) - || (statusCode == System.Net.HttpStatusCode.NotModified && substatusCode == 0) - || (statusCode == System.Net.HttpStatusCode.Conflict && substatusCode == 0) - || (statusCode == System.Net.HttpStatusCode.PreconditionFailed && substatusCode == 0); + || (statusCode == System.Net.HttpStatusCode.NotFound && subStatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.NotModified && subStatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.Conflict && subStatusCode == 0) + || (statusCode == System.Net.HttpStatusCode.PreconditionFailed && subStatusCode == 0); } /// - /// Get default threshold value based on operation type + /// Get default Latency threshold value based on operation type /// /// /// - internal static TimeSpan DefaultThreshold(OperationType operationType, CosmosThresholdOptions config) + internal static TimeSpan DefaultLatencyThreshold(OperationType operationType, CosmosThresholdOptions config) { config ??= DiagnosticsFilterHelper.defaultThresholdOptions; return DiagnosticsFilterHelper.IsPointOperation(operationType) ? diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml index af8d3b4cf7..69e7a3c52f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.BulkOperationsAsync.xml @@ -343,16 +343,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -680,16 +680,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -1017,16 +1017,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -1354,16 +1354,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -1691,16 +1691,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -2028,16 +2028,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -2365,16 +2365,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -2702,16 +2702,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -3039,16 +3039,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
@@ -3376,16 +3376,16 @@ Some Value Some Value - - - - - - - - - - + + + + + + + + + +
diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml index 9d6cb5c5a9..45781f33c4 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ChangeFeedAsync.xml @@ -1118,11 +1118,11 @@ Some Value South Central US - - - - - + + + + + @@ -1864,11 +1864,11 @@ Some Value South Central US - - - - - + + + + + @@ -2591,11 +2591,11 @@ Some Value South Central US - - - - - + + + + + @@ -3338,11 +3338,11 @@ Some Value South Central US - - - - - + + + + + @@ -3662,7 +3662,7 @@ Some Value South Central US - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml index 533473c213..b445a3d8c7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.MiscellanousAsync.xml @@ -151,8 +151,8 @@ Some Value Some Value - - + + @@ -292,8 +292,8 @@ Some Value Some Value - - + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml index 12e27e0576..82ad44b108 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.QueryAsync.xml @@ -694,10 +694,10 @@ Some Value South Central US - - - - + + + + @@ -1415,10 +1415,10 @@ Some Value South Central US - - - - + + + + @@ -2117,10 +2117,10 @@ Some Value South Central US - - - - + + + + @@ -2839,10 +2839,10 @@ Some Value South Central US - - - - + + + + @@ -3635,10 +3635,10 @@ Some Value South Central US - - - - + + + + @@ -4346,10 +4346,10 @@ Some Value South Central US - - - - + + + + @@ -5077,10 +5077,10 @@ Some Value South Central US - - - - + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml index b6ce2e777d..2282980891 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadFeedAsync.xml @@ -656,10 +656,10 @@ Some Value South Central US - - - - + + + + @@ -1339,10 +1339,10 @@ Some Value South Central US - - - - + + + + @@ -2003,10 +2003,10 @@ Some Value South Central US - - - - + + + + @@ -2687,10 +2687,10 @@ Some Value South Central US - - - - + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml index cf7a291db0..d008ef7dbe 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.ReadManyAsync.xml @@ -569,7 +569,7 @@ Some Value South Central US - + @@ -1154,7 +1154,7 @@ Some Value South Central US - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml index d49a6731e7..bb444ff589 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.StreamPointOperationsAsync.xml @@ -118,7 +118,7 @@ Some Value South Central US - + @@ -234,7 +234,7 @@ Some Value South Central US - + @@ -358,7 +358,7 @@ Some Value South Central US - + @@ -477,7 +477,7 @@ Some Value South Central US - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml index 8cd5278ea1..30629674f6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/BaselineTest/TestBaseline/EndToEndTraceWriterBaselineTests.TypedPointOperationsAsync.xml @@ -138,7 +138,7 @@ Some Value South Central US - + @@ -259,7 +259,7 @@ Some Value South Central US - + @@ -393,7 +393,7 @@ Some Value South Central US - + @@ -516,7 +516,7 @@ Some Value South Central US - + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 63046ce862..962d8e8f71 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -3686,6 +3686,30 @@ "Microsoft.Azure.Cosmos.CosmosThresholdOptions;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { + "System.Nullable`1[System.Double] get_RequestChargeThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Double] get_RequestChargeThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Double] RequestChargeThreshold": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Double] RequestChargeThreshold;CanRead:True;CanWrite:True;System.Nullable`1[System.Double] get_RequestChargeThreshold();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_RequestChargeThreshold(System.Nullable`1[System.Double]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_PayloadSizeThresholdInBytes()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_PayloadSizeThresholdInBytes();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] PayloadSizeThresholdInBytes": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Int32] PayloadSizeThresholdInBytes;CanRead:True;CanWrite:True;System.Nullable`1[System.Int32] get_PayloadSizeThresholdInBytes();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_PayloadSizeThresholdInBytes(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.TimeSpan get_NonPointOperationLatencyThreshold()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -3722,12 +3746,26 @@ ], "MethodInfo": "Void set_NonPointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_PayloadSizeThresholdInBytes(System.Nullable`1[System.Int32])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_PayloadSizeThresholdInBytes(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_PointOperationLatencyThreshold(System.TimeSpan)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ "CompilerGeneratedAttribute" ], "MethodInfo": "Void set_PointOperationLatencyThreshold(System.TimeSpan);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_RequestChargeThreshold(System.Nullable`1[System.Double])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_RequestChargeThreshold(System.Nullable`1[System.Double]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" } }, "NestedTypes": {} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs index 62517239e3..206ca2fc59 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/DiagnosticsFilterHelperTest.cs @@ -51,6 +51,37 @@ public void CheckReturnFalseOnSuccessAndLowerLatencyThanConfiguredConfig() $"and Is response Success : {response.StatusCode.IsSuccess()}" ); } + [TestMethod] + [DataRow("50", "60", false, DisplayName = "When Request and Response content length is less than threshold.")] + [DataRow("150", "60", true, DisplayName = "When Request content length is greater than threshold but response content length is less than threshold.")] + [DataRow("50", "160", true, DisplayName = "When Request content length is less than threshold but response content length is greater than threshold.")] + [DataRow("150", "160", true, DisplayName = "When Request and Response content length is greater than threshold.")] + [DataRow("Invalid Request Length", "160", true, DisplayName = "When Request content length is 'Invalid' and response content length is greater than threshold.")] + [DataRow("Invalid Request Length", "60", false, DisplayName = "When Request content length is 'Invalid' and response content length is less than threshold.")] + [DataRow("150", "Invalid Response Length", true, DisplayName = "When Request content length is greater than threshold and response content length is 'Invalid'.")] + [DataRow("50", "Invalid Response Length", false, DisplayName = "When Request content length is less than threshold and response content length is 'invalid'.")] + [DataRow(null, "160", true, DisplayName = "When Request content length is 'null' and response content length is greater than threshold.")] + [DataRow(null, "60", false, DisplayName = "When Request content length is 'null' and response content length is less than threshold.")] + [DataRow("150", null, true, DisplayName = "When Request content length is greater than threshold and response content length is 'null'.")] + [DataRow("50", null, false, DisplayName = "When Request content length is less than threshold and response content length is 'null'.")] + public void CheckReturnFalseOnSuccessAndLowerPayloadSizeThanConfiguredConfig(string requestContentLength, string responseContentLength, bool expectedResult) + { + CosmosThresholdOptions distributedTracingOptions = new CosmosThresholdOptions + { + PayloadSizeThresholdInBytes = 100 + }; + + OpenTelemetryAttributes response = new OpenTelemetryAttributes + { + ResponseContentLength = requestContentLength, + RequestContentLength = responseContentLength, + }; + + Assert.AreEqual(expectedResult, + DiagnosticsFilterHelper + .IsPayloadSizeThresholdCrossed(distributedTracingOptions, response)); + } + [TestMethod] public void CheckReturnTrueOnFailedStatusCode() { @@ -79,7 +110,7 @@ public void CheckedDefaultThresholdBasedOnOperationType() foreach(OperationType operationType in values) { - TimeSpan defaultThreshold = DiagnosticsFilterHelper.DefaultThreshold(operationType, config); + TimeSpan defaultThreshold = DiagnosticsFilterHelper.DefaultLatencyThreshold(operationType, config); if(DiagnosticsFilterHelper.IsPointOperation(operationType)) Assert.AreEqual(defaultThreshold, config.PointOperationLatencyThreshold); From 2ad1a1bc0d3628e7e5f0c9834207ccbabf17800b Mon Sep 17 00:00:00 2001 From: "Nalu Tripician (from Dev Box)" Date: Thu, 2 May 2024 15:16:31 -0700 Subject: [PATCH 336/337] update msdata direct --- .../src/Linq/SQLTranslator.cs | 3 +- .../src/Microsoft.Azure.Cosmos.csproj | 361 +- .../src/RMResources.Designer.cs | 9617 +++++----- Microsoft.Azure.Cosmos/src/RMResources.resx | 2824 +-- .../OpenTelemetryCoreRecorder.cs | 516 +- .../OpenTelemetryRecorderFactory.cs | 157 +- .../src/direct/AccessCondition.cs | 110 +- .../src/direct/AccessConditionType.cs | 72 +- Microsoft.Azure.Cosmos/src/direct/Address.cs | 189 +- .../src/direct/AddressCacheToken.cs | 82 +- .../src/direct/AddressEnumerator.cs | 690 +- .../src/direct/AddressInformation.cs | 193 +- .../src/direct/AddressSelector.cs | 170 +- Microsoft.Azure.Cosmos/src/direct/ApiType.cs | 38 +- .../src/direct/Attachment.cs | 634 +- .../src/direct/AuthorizationTokenType.cs | 92 +- .../src/direct/BackoffRetryUtility.cs | 502 +- .../src/direct/BadRequestException.cs | 147 +- .../src/direct/BarrierRequestHelper.cs | 497 +- Microsoft.Azure.Cosmos/src/direct/BitUtils.cs | 194 +- .../src/direct/BoolPartitionKeyComponent.cs | 142 +- .../src/direct/BoundingBoxSpec.cs | 254 +- .../src/direct/BufferProvider.cs | 102 +- .../src/direct/ByokConfig.cs | 140 +- .../src/direct/ByokStatus.cs | 40 +- .../src/direct/BytesDeserializer.cs | 224 +- .../src/direct/BytesSerializer.cs | 288 +- .../src/direct/CMKMetadataInfo.cs | 222 +- .../src/direct/ChangeFeedPolicy.cs | 108 +- Microsoft.Azure.Cosmos/src/direct/Channel.cs | 1147 +- .../src/direct/ChannelCallArguments.cs | 121 +- .../src/direct/ChannelCommonArguments.cs | 188 +- .../src/direct/ChannelDictionary.cs | 178 +- .../src/direct/ChannelOpenArguments.cs | 138 +- .../src/direct/ChannelOpenTimeline.cs | 150 +- .../src/direct/ChannelProperties.cs | 224 +- .../direct/ClientEncryptionIncludedPath.cs | 108 +- .../src/direct/ClientEncryptionKey.cs | 150 +- .../src/direct/ClientEncryptionPolicy.cs | 132 +- .../src/direct/ClientSideRequestStatistics.cs | 1074 +- .../src/direct/CloneableStream.cs | 558 +- .../src/direct/CollectionBackupPolicy.cs | 128 +- .../src/direct/CollectionBackupType.cs | 58 +- .../src/direct/CompositePath.cs | 226 +- .../src/direct/ComputedProperty.cs | 170 +- .../src/direct/ConcurrentPrng.cs | 42 +- Microsoft.Azure.Cosmos/src/direct/Conflict.cs | 478 +- .../src/direct/ConflictException.cs | 162 +- .../src/direct/ConflictResolutionMode.cs | 76 +- .../src/direct/ConflictResolutionPolicy.cs | 334 +- .../src/direct/Connection.cs | 2308 +-- .../src/direct/ConnectionEvent.cs | 20 +- .../src/direct/ConnectionHealthChecker.cs | 1136 +- .../src/direct/ConnectionStateListener.cs | 88 +- .../src/direct/ConsistencyLevel.cs | 102 +- .../src/direct/ConsistencyReader.cs | 790 +- .../src/direct/ConsistencyWriter.cs | 830 +- .../src/direct/Constants.cs | 4576 ++--- .../src/direct/ContentSerializationFormat.cs | 48 +- Microsoft.Azure.Cosmos/src/direct/CpuLoad.cs | 52 +- .../src/direct/CpuLoadHistory.cs | 184 +- .../src/direct/CpuMonitor.cs | 566 +- .../src/direct/CustomTypeExtensions.cs | 584 +- .../src/direct/DataEncryptionKeyStatus.cs | 24 +- .../src/direct/DataMaskingIncludedPath.cs | 42 +- .../src/direct/DataMaskingPolicy.cs | 190 +- Microsoft.Azure.Cosmos/src/direct/DataType.cs | 92 +- Microsoft.Azure.Cosmos/src/direct/Database.cs | 392 +- .../direct/DatabaseOrCollectionCreateMode.cs | 24 +- .../src/direct/DefaultTrace.cs | 356 +- .../src/direct/DefaultTraceEx.cs | 130 +- .../direct/DictionaryNameValueCollection.cs | 768 +- .../src/direct/Dispatcher.cs | 2363 +-- Microsoft.Azure.Cosmos/src/direct/Document.cs | 898 +- .../src/direct/DocumentCollection.cs | 2340 ++- .../src/direct/DocumentResponse.cs | 188 +- .../src/direct/DocumentServiceRequest.cs | 2438 +-- .../direct/DocumentServiceRequestContext.cs | 491 +- .../DocumentServiceRequestExtensions.cs | 92 +- .../src/direct/EncryptionScopeMetadata.cs | 222 +- .../src/direct/EnumerationDirection.cs | 40 +- Microsoft.Azure.Cosmos/src/direct/Error.cs | 170 +- .../src/direct/EtwNativeInterop.cs | 86 +- .../src/direct/EtwTraceListener.cs | 446 +- .../src/direct/ExceptionExtensions.cs | 326 +- .../src/direct/ExcludedPath.cs | 132 +- .../src/direct/FanoutOperationState.cs | 42 +- .../FaultInjection/IChaosInterceptor.cs | 113 +- .../src/direct/FeedResource.cs | 168 +- .../src/direct/ForbiddenException.cs | 220 +- .../src/direct/GeoLinkTypes.cs | 36 +- .../src/direct/GeospatialConfig.cs | 178 +- .../src/direct/GeospatialType.cs | 50 +- .../GoneAndRetryWithRequestRetryPolicy.cs | 930 +- .../src/direct/GoneAndRetryWithRetryPolicy.cs | 662 +- .../src/direct/GoneException.cs | 212 +- .../src/direct/GoneOnlyRequestRetryPolicy.cs | 230 +- .../src/direct/HashIndex.cs | 282 +- Microsoft.Azure.Cosmos/src/direct/Helpers.cs | 590 +- .../src/direct/HttpClientExtension.cs | 138 +- .../src/direct/HttpConstants.cs | Bin 117020 -> 117536 bytes .../src/direct/HttpException.cs | 1250 +- .../src/direct/HttpTransportClient.cs | 3023 +-- .../src/direct/HttpUtility.cs | 1628 +- .../src/direct/IAddressEnumerator.cs | 34 +- .../src/direct/IAddressResolver.cs | 46 +- .../src/direct/IAddressResolverExtension.cs | 72 +- .../src/direct/IAuthorizationTokenProvider.cs | 48 +- Microsoft.Azure.Cosmos/src/direct/IChannel.cs | 60 +- .../src/direct/IChannelDictionary.cs | 38 +- .../direct/IClientSideRequestStatistics.cs | 114 +- .../src/direct/ICommunicationEventSource.cs | 30 +- .../src/direct/IConnectionStateListener.cs | 26 +- .../src/direct/IDocumentResponse.cs | 54 +- .../direct/IMasterServiceIdentityProvider.cs | 36 +- .../src/direct/INameValueCollection.cs | 78 +- .../src/direct/INameValueCollectionFactory.cs | 94 +- .../src/direct/IOpenConnectionsHandler.cs | 48 +- .../src/direct/IPartitionKeyComponent.cs | 58 +- .../src/direct/IRequestRetryPolicy.cs | 116 +- .../src/direct/IResourceResponse.cs | 56 +- .../src/direct/IResourceResponseBase.cs | 684 +- .../src/direct/IRetriableResponse.cs | 48 +- .../src/direct/IRetryPolicy.cs | 246 +- .../src/direct/IServiceConfigurationReader.cs | 84 +- .../src/direct/ISessionContainer.cs | 112 +- .../src/direct/ISessionToken.cs | 86 +- .../src/direct/IStoreClient.cs | 80 +- .../src/direct/IStoreClientFactory.cs | 46 +- .../src/direct/IStoreModel.cs | 28 +- .../src/direct/IStoreModelExtension.cs | 56 +- .../src/direct/ITypeResolver.cs | 42 +- .../src/direct/InAccountRestoreParameters.cs | 194 +- .../src/direct/IncludedPath.cs | 262 +- Microsoft.Azure.Cosmos/src/direct/Index.cs | 316 +- .../src/direct/IndexJsonConverter.cs | 184 +- .../src/direct/IndexKind.cs | 86 +- .../src/direct/IndexingDirective.cs | 110 +- .../src/direct/IndexingMode.cs | 92 +- .../src/direct/IndexingPolicy.cs | 1670 +- .../direct/InfinityPartitionKeyComponent.cs | 128 +- Microsoft.Azure.Cosmos/src/direct/Int128.cs | 224 +- .../src/direct/InternalSchemaProperties.cs | 98 +- .../direct/InternalServerErrorException.cs | 171 +- .../src/direct/InvalidPartitionException.cs | 152 +- .../src/direct/JSonSerializable.cs | 1858 +- .../src/direct/JsonSerializableList.cs | 76 +- .../src/direct/KeyWrapMetadata.cs | 134 +- .../src/direct/LbChannelState.cs | 190 +- .../direct/LinuxSystemUtilizationReader.cs | 1228 +- .../src/direct/LoadBalancingChannel.cs | 402 +- .../src/direct/LoadBalancingPartition.cs | 794 +- .../src/direct/LocationNames.cs | 866 +- .../src/direct/LockedException.cs | 158 +- .../src/direct/MaterializedViewDefinition.cs | 190 +- .../src/direct/MaterializedViews.cs | 94 +- .../src/direct/MathUtils.cs | 46 +- .../direct/MaxNumberPartitionKeyComponent.cs | 158 +- .../direct/MaxStringPartitionKeyComponent.cs | 156 +- .../src/direct/MediaIdHelper.cs | 110 +- .../src/direct/MemoryStreamPool.cs | 26 +- .../src/direct/MethodNotAllowedException.cs | 140 +- .../src/direct/MigrateCollectionDirective.cs | 42 +- .../direct/MinNumberPartitionKeyComponent.cs | 156 +- .../direct/MinStringPartitionKeyComponent.cs | 158 +- .../src/direct/MurmurHash.cs | 566 +- .../src/direct/NameValueCollectionWrapper.cs | 476 +- .../src/direct/NativeMethods.Darwin.cs | 108 +- .../src/direct/NativeMethods.Unix.cs | 70 +- .../src/direct/NativeMethods.Windows.cs | 84 +- Microsoft.Azure.Cosmos/src/direct/NetUtil.cs | 306 +- .../src/direct/NotFoundException.cs | 162 +- .../src/direct/NullPartitionKeyComponent.cs | 132 +- .../src/direct/NullSessionContainer.cs | 76 +- .../src/direct/NumberPartitionKeyComponent.cs | 322 +- Microsoft.Azure.Cosmos/src/direct/Offer.cs | 274 +- .../src/direct/OfferContentV2.cs | 830 +- .../src/direct/OfferTypeResolver.cs | 154 +- Microsoft.Azure.Cosmos/src/direct/OfferV2.cs | 666 +- .../src/direct/OperationKind.cs | 96 +- .../src/direct/OperationType.cs | 466 +- .../src/direct/PartitionAddressInformation.cs | 200 +- .../direct/PartitionIsMigratingException.cs | 166 +- .../src/direct/PartitionKey.cs | 354 +- .../src/direct/PartitionKeyComponentType.cs | 74 +- .../src/direct/PartitionKeyDefinition.cs | 328 +- .../direct/PartitionKeyDefinitionVersion.cs | 56 +- .../src/direct/PartitionKeyInternal.cs | 2226 +-- .../PartitionKeyInternalJsonConverter.cs | 324 +- .../src/direct/PartitionKeyRange.cs | 363 +- .../direct/PartitionKeyRangeGoneException.cs | 166 +- .../src/direct/PartitionKeyRangeIdentity.cs | 274 +- .../PartitionKeyRangeIsSplittingException.cs | 166 +- .../src/direct/PartitionKeyRangeStatistics.cs | 168 +- .../src/direct/PartitionKeyRangeStatus.cs | 56 +- .../src/direct/PartitionKeyStatistics.cs | 124 +- .../src/direct/PartitionKind.cs | 54 +- .../src/direct/PartitionedSystemDocument.cs | 32 +- Microsoft.Azure.Cosmos/src/direct/Paths.cs | 916 +- .../src/direct/PathsHelper.cs | 4112 ++-- .../PerProtocolPartitionAddressInformation.cs | 248 +- .../src/direct/PerfCounters.cs | 844 +- .../src/direct/PerformanceActivities.cs | 52 +- .../src/direct/PerformanceActivity.cs | 286 +- .../src/direct/Permission.cs | 206 +- .../src/direct/PermissionMode.cs | 64 +- Microsoft.Azure.Cosmos/src/direct/Platform.cs | 26 +- .../src/direct/PlatformApis.cs | 322 +- .../src/direct/PooledTimer.cs | 218 +- .../src/direct/PortReuseMode.cs | 30 +- .../src/direct/PreconditionFailedException.cs | 154 +- .../src/direct/PriorityLevel.cs | 24 +- Microsoft.Azure.Cosmos/src/direct/Protocol.cs | 84 +- .../src/direct/QueryPlanGenerationMode.cs | 54 +- .../src/direct/QueryResult.cs | 622 +- .../src/direct/QuorumReader.cs | 1865 +- Microsoft.Azure.Cosmos/src/direct/Range.cs | 428 +- .../src/direct/RangeIndex.cs | 282 +- .../src/direct/ReadFeedKeyType.cs | 50 +- Microsoft.Azure.Cosmos/src/direct/ReadMode.cs | 28 +- .../src/direct/ReadPolicy.cs | 106 +- .../src/direct/ReceivedResponseEventArgs.cs | 112 +- .../src/direct/ReferenceCountedDisposable.cs | 440 +- .../src/direct/RegionProximityUtil.cs | 13511 +++++++------ .../src/direct/RemoteStorageType.cs | 52 +- .../src/direct/ReplicatedResourceClient.cs | 863 +- .../src/direct/ReplicationPolicy.cs | 160 +- .../src/direct/RequestChargeTracker.cs | 98 +- .../direct/RequestEntityTooLargeException.cs | 130 +- .../src/direct/RequestHelper.cs | 72 +- .../src/direct/RequestNameValueCollection.cs | 15873 ++++++++-------- .../src/direct/RequestOptions.cs | 1411 +- .../direct/RequestRateTooLargeException.cs | 134 +- .../src/direct/RequestRetryUtility.cs | 338 +- .../src/direct/RequestTimeoutException.cs | 208 +- .../src/direct/RequestedCollectionType.cs | 24 +- Microsoft.Azure.Cosmos/src/direct/Resource.cs | 446 +- .../src/direct/ResourceId.cs | 2584 +-- .../src/direct/ResourceIdBase64Decoder.cs | 496 +- .../src/direct/ResourceOperation.cs | 380 +- .../src/direct/ResourceResponse.cs | 180 +- .../src/direct/ResourceResponseBase.cs | 1350 +- .../src/direct/ResourceType.cs | 288 +- .../src/direct/RetryWithException.cs | 110 +- .../src/direct/Rfc1123DateTimeCache.cs | 142 +- .../src/direct/RntbdConstants.cs | 2617 +-- .../src/direct/RntbdOpenConnectionHandler.cs | 254 +- .../src/direct/RntbdStreamReader.cs | 378 +- .../src/direct/RntbdToken.cs | 424 +- .../src/direct/RntbdTokenStream.cs | 548 +- .../src/direct/RuntimeConstants.cs | 170 +- .../src/direct/SDKSupportedCapabilities.cs | 30 +- .../direct/SDKSupportedCapabilitiesHelpers.cs | 46 +- Microsoft.Azure.Cosmos/src/direct/Schema.cs | 234 +- .../src/direct/SchemaBuilderMode.cs | 56 +- .../src/direct/SchemaDiscoveryPolicy.cs | 156 +- .../src/direct/SendingRequestEventArgs.cs | 82 +- .../direct/SerializableNameValueCollection.cs | 312 +- .../direct/SerializationFormattingPolicy.cs | 46 +- .../src/direct/ServerKey.cs | 150 +- .../src/direct/ServerProperties.cs | 36 +- .../src/direct/ServerStoreModel.cs | 264 +- .../src/direct/ServiceIdentity.cs | 208 +- .../src/direct/ServiceInteropWrapper.cs | 644 +- .../src/direct/ServiceUnavailableException.cs | 329 +- .../src/direct/SessionTokenHelper.cs | 622 +- .../direct/SessionTokenMismatchRetryPolicy.cs | 286 +- .../src/direct/SimpleSessionToken.cs | 182 +- Microsoft.Azure.Cosmos/src/direct/Snapshot.cs | 646 +- .../src/direct/SnapshotContent.cs | 982 +- .../src/direct/SnapshotKind.cs | 54 +- .../src/direct/SnapshotState.cs | 54 +- .../src/direct/SpatialIndex.cs | 178 +- .../src/direct/SpatialSpec.cs | 318 +- .../src/direct/SpatialType.cs | 72 +- .../src/direct/StatusCodes.cs | 707 +- .../src/direct/StoreClient.cs | 638 +- .../src/direct/StoreClientFactory.cs | 934 +- .../src/direct/StoreReader.cs | 1360 +- .../src/direct/StoreResponse.cs | 304 +- .../StoreResponseNameValueCollection.cs | 7956 ++++---- .../src/direct/StoreResult.cs | 1140 +- .../src/direct/StoredProcedure.cs | 96 +- .../src/direct/StreamExtension.cs | 200 +- .../src/direct/StringPartitionKeyComponent.cs | 244 +- .../src/direct/StringSegment.cs | 336 +- .../direct/SupportedSerializationFormats.cs | 58 +- .../src/direct/SystemDocument.cs | 32 +- .../src/direct/SystemDocumentType.cs | 66 +- .../src/direct/SystemSynchronizationScope.cs | 316 +- .../src/direct/SystemUsageHistory.cs | 322 +- .../src/direct/SystemUsageLoad.cs | 120 +- .../src/direct/SystemUsageMonitor.cs | 450 +- .../src/direct/SystemUsageRecorder.cs | 142 +- .../src/direct/SystemUtilizationReaderBase.cs | 276 +- .../src/direct/TaskFactoryExtensions.cs | 182 +- .../src/direct/ThreadInformation.cs | 346 +- .../src/direct/TimeoutHelper.cs | 110 +- .../src/direct/TimerPool.cs | 494 +- .../src/direct/TransportAddressHealthState.cs | 306 +- .../src/direct/TransportAddressUri.cs | 706 +- .../src/direct/TransportClient.cs | 2482 +-- .../src/direct/TransportErrorCode.cs | 160 +- .../src/direct/TransportException.cs | 516 +- .../src/direct/TransportExceptionCounters.cs | 32 +- .../src/direct/TransportExceptions.cs | 440 +- .../direct/TransportPerformanceCounters.cs | 72 +- .../src/direct/TransportRequestStats.cs | 620 +- .../src/direct/TransportSerialization.cs | 5379 +++--- Microsoft.Azure.Cosmos/src/direct/Trigger.cs | 172 +- .../src/direct/TriggerOperation.cs | 92 +- .../src/direct/TriggerType.cs | 52 +- Microsoft.Azure.Cosmos/src/direct/UInt128.cs | 744 +- .../src/direct/UnauthorizedException.cs | 172 +- .../src/direct/Undefined.cs | 128 +- .../direct/UndefinedPartitionKeyComponent.cs | 152 +- .../src/direct/UniqueIndexReIndexContext.cs | 158 +- .../src/direct/UniqueKey.cs | 282 +- .../src/direct/UniqueKeyPolicy.cs | 334 +- .../src/direct/UnixDateTimeConverter.cs | 152 +- .../UnsupportedSystemUtilizationReader.cs | 46 +- .../src/direct/UriUtility.cs | 1010 +- Microsoft.Azure.Cosmos/src/direct/User.cs | 76 +- .../src/direct/UserAgentContainer.cs | 154 +- .../src/direct/UserDefinedFunction.cs | 136 +- .../src/direct/UserDefinedType.cs | 38 +- .../src/direct/UserPortPool.cs | 522 +- .../src/direct/ValueStopwatch.cs | 348 +- .../src/direct/VectorSessionToken.cs | 962 +- .../src/direct/VersionUtility.cs | 240 +- .../src/direct/WFConstants.cs | Bin 26424 -> 27612 bytes .../src/direct/WebExceptionUtility.cs | 98 +- .../direct/WindowsSystemUtilizationReader.cs | 218 +- .../src/direct/msdata_sync.ps1 | 2 +- .../src/direct/rntbd2/TransportClient.cs | 1218 +- 335 files changed, 89317 insertions(+), 87376 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs index 74ca62cfb3..9bd4e1bcc8 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs @@ -5,7 +5,8 @@ namespace Microsoft.Azure.Cosmos.Linq { using System.Collections.Generic; using System.Linq.Expressions; - using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; /// diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 6fa9a6f282..a92d3eac94 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -1,177 +1,184 @@ - - - - Microsoft Corporation - Microsoft(R) Azure Cosmos - This client library enables client applications to connect to Azure Cosmos DB via the NoSQL API. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. - © Microsoft Corporation. All rights reserved. - en-US - $([System.DateTime]::Now.ToString(yyyyMMdd)) - $(ClientOfficialVersion) - $(ClientPreviewVersion) - $(ClientPreviewSuffixVersion) - nightly-$(CurrentDate) - $(VersionSuffix)-nightly-$(CurrentDate) - $(ClientVersion) - $(ClientVersion)-$(VersionSuffix) - $(ClientVersion) - Microsoft - netstandard2.0 - true - true - Microsoft.Azure.Cosmos.Client - Microsoft Azure Cosmos DB Client library - Microsoft.Azure.Cosmos - microsoft;azure;cosmos;cosmosdb;documentdb;docdb;nosql;azureofficial;dotnetcore;netcore;netstandard - The change log for this SDK is made available at https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/changelog.md at the time of release. - https://github.com/Azure/azure-cosmos-dotnet-v3 - true - http://go.microsoft.com/fwlink/?LinkID=288890 - Icon.png - true - true - false - true - AnyCPU - External - Product - portable - false - false - Microsoft.Azure.Cosmos - NU5125 - true - $(LangVersion) - LICENSE - - - - - - - - - - - - - - - - - - - - - - Never - - - - - - True - True - JsonBinaryEncoding.SystemStrings.tt - - - - - - True - True - ClientResources.resx - - - True - True - CosmosNumberCodeGenerator.tt - - - True - True - JsonBinaryEncoding.SystemStrings.tt - - - True - True - SystemStrings.tt - - - - - ResXFileCodeGenerator - ClientResources.Designer.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - PreserveNewest - - - - - - TextTemplatingFileGenerator - CosmosNumberCodeGenerator.cs - - - TextTemplatingFileGenerator - JsonBinaryEncoding.SystemStrings.cs - - - - - - - - - true - true - ..\..\35MSSharedLib1024.snk - - - - $(DefineConstants);SignAssembly - $(DefineConstants);DelaySignKeys - $(DefineConstants);DOCDBCLIENT;COSMOSCLIENT;NETSTANDARD20 - - - + + + + Microsoft Corporation + Microsoft(R) Azure Cosmos + This client library enables client applications to connect to Azure Cosmos DB via the NoSQL API. Azure Cosmos DB is a globally distributed, multi-model database service. For more information, refer to http://azure.microsoft.com/services/cosmos-db/. + © Microsoft Corporation. All rights reserved. + en-US + $([System.DateTime]::Now.ToString(yyyyMMdd)) + $(ClientOfficialVersion) + $(ClientPreviewVersion) + $(ClientPreviewSuffixVersion) + nightly-$(CurrentDate) + $(VersionSuffix)-nightly-$(CurrentDate) + $(ClientVersion) + $(ClientVersion)-$(VersionSuffix) + $(ClientVersion) + Microsoft + netstandard2.0 + true + true + Microsoft.Azure.Cosmos.Client + Microsoft Azure Cosmos DB Client library + Microsoft.Azure.Cosmos + microsoft;azure;cosmos;cosmosdb;documentdb;docdb;nosql;azureofficial;dotnetcore;netcore;netstandard + The change log for this SDK is made available at https://github.com/Azure/azure-cosmos-dotnet-v3/blob/master/changelog.md at the time of release. + https://github.com/Azure/azure-cosmos-dotnet-v3 + true + http://go.microsoft.com/fwlink/?LinkID=288890 + Icon.png + true + true + false + true + AnyCPU + External + Product + portable + false + false + Microsoft.Azure.Cosmos + NU5125 + true + $(LangVersion) + LICENSE + + + + + + + + + + + + + + + + + + + + + + Never + + + + + + True + True + JsonBinaryEncoding.SystemStrings.tt + + + + + + True + True + ClientResources.resx + + + True + True + CosmosNumberCodeGenerator.tt + + + True + True + JsonBinaryEncoding.SystemStrings.tt + + + True + True + SystemStrings.tt + + + + + ResXFileCodeGenerator + ClientResources.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + + + + TextTemplatingFileGenerator + CosmosNumberCodeGenerator.cs + + + TextTemplatingFileGenerator + JsonBinaryEncoding.SystemStrings.cs + + + + + + + + + true + true + ..\..\35MSSharedLib1024.snk + False + False + False + 1591 + + + + $(DefineConstants);SignAssembly + $(DefineConstants);DelaySignKeys + $(DefineConstants);DOCDBCLIENT;COSMOSCLIENT;NETSTANDARD20 + False + False + False + 1591;1587;1572;1573;1574;1580 + + + diff --git a/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs b/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs index 9dfc7537eb..5629d0cc8a 100644 --- a/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs +++ b/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs @@ -1,4777 +1,4842 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class RMResources - { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal RMResources() - { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager - { - get - { - if (object.ReferenceEquals(resourceMan, null)) - { -#if COSMOSCLIENT - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Documents.RMResources", typeof(RMResources).Assembly); -#else - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Documents.RMResources", typeof(RMResources).GetAssembly()); -#endif - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture - { - get - { - return resourceCulture; - } - set - { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to {0} api is not supported for this database account. - /// - internal static string ApiTypeForbidden - { - get - { - return ResourceManager.GetString("ApiTypeForbidden", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} should have {1} argument.. - /// - internal static string ArgumentRequired - { - get - { - return ResourceManager.GetString("ArgumentRequired", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Auto-Scale Setting Change With User Auth Is Disallowed.. - /// - internal static string AutoScaleSettingChangeWithUserAuthIsDisallowed - { - get - { - return ResourceManager.GetString("AutoScaleSettingChangeWithUserAuthIsDisallowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The given request [{0} {1}] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac.. - /// - internal static string AadAuthActionNotSupported - { - get - { - return ResourceManager.GetString("AadAuthActionNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to validate AAD identity since the authenticator is unavailable.. - /// - internal static string AadAuthenticatorNotAvailable - { - get - { - return ResourceManager.GetString("AadAuthenticatorNotAvailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request for Read DatabaseAccount is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on any scope. Learn more: https://aka.ms/cosmos-native-rbac.. - /// - internal static string AadAuthDatabaseAccountRequestBlocked - { - get - { - return ResourceManager.GetString("AadAuthDatabaseAccountRequestBlocked", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This could be because the user's group memberships were not present in the AAD token.. - /// - internal static string AadAuthGroupExpansionNeeded - { - get - { - return ResourceManager.GetString("AadAuthGroupExpansionNeeded", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on resource [{2}]. Learn more: https://aka.ms/cosmos-native-rbac.. - /// - internal static string AadAuthRequestBlocked - { - get - { - return ResourceManager.GetString("AadAuthRequestBlocked", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to validate AAD identity since the authorizer is unavailable.. - /// - internal static string AadAuthorizerNotAvailable - { - get - { - return ResourceManager.GetString("AadAuthorizerNotAvailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to update the AAD Public Keys with value {0}. Exception: {1}.. - /// - internal static string AadAuthPublicKeysFailedToUpdate - { - get - { - return ResourceManager.GetString("AadAuthPublicKeysFailedToUpdate", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SAS Token Authentication is disabled for this account. Please contact Azure Support [https://azure.microsoft.com/support] to enable it.. - /// - internal static string SasTokenAuthDisabled - { - get - { - return ResourceManager.GetString("SasTokenAuthDisabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Local Authorization is disabled. Use an AAD token to authorize all requests.. - /// - internal static string AadLocalAuthDisabled - { - get - { - return ResourceManager.GetString("AadLocalAuthDisabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to At this time, only write operations made from the MongoDB SDKs are supported. Modifications to MongoDB collections using other SDKs is temporarily blocked.. - /// - internal static string BadClientMongo - { - get - { - return ResourceManager.GetString("BadClientMongo", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid response from upstream server or upstream server request failed.. - /// - internal static string BadGateway - { - get - { - return ResourceManager.GetString("BadGateway", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to One of the input values is invalid.. - /// - internal static string BadRequest - { - get - { - return ResourceManager.GetString("BadRequest", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request url is invalid.. - /// - internal static string BadUrl - { - get - { - return ResourceManager.GetString("BadUrl", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot offline a write region that has zero read regions configured. There needs to be atleast one read region to failover to.. - /// - internal static string CannotOfflineWriteRegionWithNoReadRegions - { - get - { - return ResourceManager.GetString("CannotOfflineWriteRegionWithNoReadRegions", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot specify partition key range or partition key for resource that is not partitioned.. - /// - internal static string CannotSpecifyPKRangeForNonPartitionedResource - { - get - { - return ResourceManager.GetString("CannotSpecifyPKRangeForNonPartitionedResource", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to StartTime cannot have DateTimeKind.Unspecified.. - /// - internal static string ChangeFeedOptionsStartTimeWithUnspecifiedDateTimeKind - { - get - { - return ResourceManager.GetString("ChangeFeedOptionsStartTimeWithUnspecifiedDateTimeKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Channel is closed. - /// - internal static string ChannelClosed - { - get - { - return ResourceManager.GetString("ChannelClosed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The channel multiplexer has shut down.. - /// - internal static string ChannelMultiplexerClosedTransportError - { - get - { - return ResourceManager.GetString("ChannelMultiplexerClosedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The transport client failed to open a connection. See the inner exception for details.. - /// - internal static string ChannelOpenFailedTransportError - { - get - { - return ResourceManager.GetString("ChannelOpenFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The transport client timed out when opening a connection. See the inner exception for details.. - /// - internal static string ChannelOpenTimeoutTransportError - { - get - { - return ResourceManager.GetString("ChannelOpenTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There is high CPU detected on your client machine. Requests are more likely to timeout when CPU exceeds 90%. - /// - internal static string Client_CPUOverload - { - get - { - return ResourceManager.GetString("Client_CPUOverload", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Thread starvation or thread-pool blocking detected. - /// - internal static string Client_ThreadStarvation - { - get - { - return ResourceManager.GetString("Client_ThreadStarvation", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU was overloaded during the attempted request.. - /// - internal static string ClientCpuOverload - { - get - { - return ResourceManager.GetString("ClientCpuOverload", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU has thread starvation.. - /// - internal static string ClientCpuThreadStarvation - { - get - { - return ResourceManager.GetString("ClientCpuThreadStarvation", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. Please check for client resource starvation issues and verify connectivity between client and server.. - /// - internal static string ClientUnavailable - { - get - { - return ResourceManager.GetString("ClientUnavailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Collection create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection.. - /// - internal static string CollectionCreateTopologyConflict - { - get - { - return ResourceManager.GetString("CollectionCreateTopologyConflict", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Throughput of this collection cannot be more than {0}, as was provisioned during collection creation time.. - /// - internal static string CollectionThroughputCannotBeMoreThan - { - get - { - return ResourceManager.GetString("CollectionThroughputCannotBeMoreThan", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to connect to the remote endpoint.. - /// - internal static string ConnectFailedTransportError - { - get - { - return ResourceManager.GetString("ConnectFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection failed.. - /// - internal static string ConnectionBrokenTransportError - { - get - { - return ResourceManager.GetString("ConnectionBrokenTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The connection attempt timed out.. - /// - internal static string ConnectTimeoutTransportError - { - get - { - return ResourceManager.GetString("ConnectTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Correlation ID not found in response. - /// - internal static string CorrelationIDNotFoundInResponse - { - get - { - return ResourceManager.GetString("CorrelationIDNotFoundInResponse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid CORS rule. At least one allowed origin is required.. - /// - internal static string CorsAllowedOriginsEmptyList - { - get - { - return ResourceManager.GetString("CorsAllowedOriginsEmptyList", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to InvalidCORS rule. The origin '{0}' is an invalid origin. A valid rigin should not include a uri path.. - /// - internal static string CorsAllowedOriginsInvalidPath - { - get - { - return ResourceManager.GetString("CorsAllowedOriginsInvalidPath", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid CORS rule. The origin '{0}' is not a well formed origin... - /// - internal static string CorsAllowedOriginsMalformedUri - { - get - { - return ResourceManager.GetString("CorsAllowedOriginsMalformedUri", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid CORS rule. Wildcards are not supported.. - /// - internal static string CorsAllowedOriginsWildcardsNotSupported - { - get - { - return ResourceManager.GetString("CorsAllowedOriginsWildcardsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid CORS rules. Only one rule is supported.. - /// - internal static string CorsTooManyRules - { - get - { - return ResourceManager.GetString("CorsTooManyRules", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value specified in the "{0}" header is incompatible with value specified in the "{1}" header of the request.. - /// - internal static string CrossPartitionContinuationAndIndex - { - get - { - return ResourceManager.GetString("CrossPartitionContinuationAndIndex", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cross partition query is required but disabled. Please set x-ms-documentdb-query-enablecrosspartition to true, specify x-ms-documentdb-partitionkey, or revise your query to avoid this exception.. - /// - internal static string CrossPartitionQueryDisabled - { - get - { - return ResourceManager.GetString("CrossPartitionQueryDisabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cross-tenant CMK is not supported with First Party identities as Default identities. Please use an User Assigned identity instead.. - /// - internal static string CrossTenantCMKNotSupportedWithFirstPartyIdentity - { - get - { - return ResourceManager.GetString("CrossTenantCMKNotSupportedWithFirstPartyIdentity", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cross-tenant CMK is not supported with System Assigned identities as Default identities. Please use an User Assigned Identity instead.. - /// - internal static string CrossTenantCMKNotSupportedWithSystemAssignedIdentity - { - get - { - return ResourceManager.GetString("CrossTenantCMKNotSupportedWithSystemAssignedIdentity", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database Account {0} does not exist. - /// - internal static string DatabaseAccountNotFound - { - get - { - return ResourceManager.GetString("DatabaseAccountNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection... - /// - internal static string DatabaseCreateTopologyConflict - { - get - { - return ResourceManager.GetString("DatabaseCreateTopologyConflict", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expecting DateTime value.. - /// - internal static string DateTimeConverterInvalidDateTime - { - get - { - return ResourceManager.GetString("DateTimeConverterInvalidDateTime", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expecting reader to read Integer. - /// - internal static string DateTimeConverterInvalidReaderValue - { - get - { - return ResourceManager.GetString("DateTimeConverterInvalidReaderValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Expecting reader value to be compatible with double conversion.. - /// - internal static string DateTimeConveterInvalidReaderDoubleValue - { - get - { - return ResourceManager.GetString("DateTimeConveterInvalidReaderDoubleValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Error occurred while deserializing content '{0}'.. - /// - internal static string DeserializationError - { - get - { - return ResourceManager.GetString("DeserializationError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The given default identity for {0} is not valid. The format for the default identity is not valid, please use 'FirstPartyIdentity'/'SystemAssignedIdentity'/'UserAssignedIdentity=<UA_resource_id>'. - /// - internal static string DefaultIdentityNotValidFormat - { - get - { - return ResourceManager.GetString("DefaultIdentityNotValidFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to a delegated identity that does not exist in {0}.. - /// - internal static string DefaultIdentityWithoutCorrespondingDelegatedIdentity - { - get - { - return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingDelegatedIdentity", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to a system identity that does not exist in {0}.. - /// - internal static string DefaultIdentityWithoutCorrespondingSystemIdentity - { - get - { - return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingSystemIdentity", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to an user identity that does not exist in {0}.. - /// - internal static string DefaultIdentityWithoutCorrespondingUserIdentity - { - get - { - return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingUserIdentity", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DNS resolution failed.. - /// - internal static string DnsResolutionFailedTransportError - { - get - { - return ResourceManager.GetString("DnsResolutionFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DNS resolution timed out.. - /// - internal static string DnsResolutionTimeoutTransportError - { - get - { - return ResourceManager.GetString("DnsResolutionTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Document Query Execution Context is done.. - /// - internal static string DocumentQueryExecutionContextIsDone - { - get - { - return ResourceManager.GetString("DocumentQueryExecutionContextIsDone", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service is currently unavailable, please retry after a while. If this problem persists please contact support.. - /// - internal static string DocumentServiceUnavailable - { - get - { - return ResourceManager.GetString("DocumentServiceUnavailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Duplicate correlation id generated. - /// - internal static string DuplicateCorrelationIdGenerated - { - get - { - return ResourceManager.GetString("DuplicateCorrelationIdGenerated", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Empty Virtual Network Resource Guid. - /// - internal static string EmptyVirtualNetworkResourceGuid - { - get - { - return ResourceManager.GetString("EmptyVirtualNetworkResourceGuid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Specified Virtual Network Rules list is empty. - /// - internal static string EmptyVirtualNetworkRulesSpecified - { - get - { - return ResourceManager.GetString("EmptyVirtualNetworkRulesSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableAnalyticsStorage on an account with EnableServerless. - /// - internal static string EnableAnalyticsStorageAndEnableServerlessNotSupported - { - get - { - return ResourceManager.GetString("EnableAnalyticsStorageAndEnableServerlessNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer throughput policy specified is invalid. - /// - internal static string InvalidThroughputPolicy - { - get - { - return ResourceManager.GetString("InvalidThroughputPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on an account with EnableServerless. - /// - internal static string EnableMultipleWriteLocationsAndEnableServerlessNotSupported - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsAndEnableServerlessNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on an account with EnableTieredStorageV1. - /// - internal static string EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableOnlyColdStorageContainersInAccountV1 on an account with EnableMaterializedViews - /// - internal static string EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported - { - get - { - return ResourceManager.GetString("EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Accounts configured with default consistency level as 'Strong' cannot be enabled for multiple write locations(i.e. EnableMultipleWriteLocations=true). Consider relaxing default consistency level of the account to enable multiple write locations.. - /// - internal static string EnableMultipleWriteLocationsAndStrongConsistencyNotSupported - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsAndStrongConsistencyNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Availability Zone on a multi region account requires multi master to be enabled. Please enable Multi-Master on the database account to proceed.. - /// - internal static string EnableMultipleWriteLocationsBeforeAddingRegion - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsBeforeAddingRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This account already has EnableMultipleWriteLocations flag set to {0}".. - /// - internal static string EnableMultipleWriteLocationsNotModified - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsNotModified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot add regions to an account with EnableServerless. - /// - internal static string EnableMultiRegionAndEnableServerlessNotSupported - { - get - { - return ResourceManager.GetString("EnableMultiRegionAndEnableServerlessNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Restore is not Supported on this account type. - /// - internal static string PitrNotSupported - { - get - { - return ResourceManager.GetString("PitrNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot add regions to this account type. - /// - internal static string EnableMultiRegionNotSupported - { - get - { - return ResourceManager.GetString("EnableMultiRegionNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on this account type. - /// - internal static string EnableMultipleWriteLocationsNotSupported - { - get - { - return ResourceManager.GetString("EnableMultipleWriteLocationsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set DisableKeyBasedMetadataWriteAccess on this account type. - /// - internal static string DisableKeyBasedMetadataWriteAccessNotSupported - { - get - { - return ResourceManager.GetString("DisableKeyBasedMetadataWriteAccessNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MaterializedViews is not supported on this account type. - /// - internal static string MaterializedViewsNotSupported - { - get - { - return ResourceManager.GetString("MaterializedViewsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Full Fidelity Change Feed is not supported on this account type. - /// - internal static string FullFidelityChangeFeedNotSupported - { - get - { - return ResourceManager.GetString("FullFidelityChangeFeedNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to CassandraConnector not supported for this account type. - /// - internal static string CassandraConnectorNotSupported - { - get - { - return ResourceManager.GetString("CassandraConnectorNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Free Tier is not supported on this account type. - /// - internal static string FreeTierNotSupported - { - get - { - return ResourceManager.GetString("FreeTierNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set IpRangeFilter values on this account type. - /// - internal static string IpRangeFilterNotSupported - { - get - { - return ResourceManager.GetString("IpRangeFilterNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Analytical Storage is not supported on this account type. - /// - internal static string AnalyticalStoreNotSupported - { - get - { - return ResourceManager.GetString("AnalyticalStoreNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set VirtualNetworkFilter on this account type. - /// - internal static string VirtualNetworkFilterNotSupported - { - get - { - return ResourceManager.GetString("VirtualNetworkFilterNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Serverless offer is not supported on this account type. - /// - internal static string ServerlessNotSupported - { - get - { - return ResourceManager.GetString("ServerlessNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to retrieve address of endpoint '{0}' from the address '{1}'. - /// - internal static string EndpointNotFound - { - get - { - return ResourceManager.GetString("EndpointNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Entity with the specified id already exists in the system.. - /// - internal static string EntityAlreadyExists - { - get - { - return ResourceManager.GetString("EntityAlreadyExists", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Message: {0}. - /// - internal static string ExceptionMessage - { - get - { - return ResourceManager.GetString("ExceptionMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0}, Local IP: {1}. - /// - internal static string ExceptionMessageAddIpAddress - { - get - { - return ResourceManager.GetString("ExceptionMessageAddIpAddress", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0}, Request URI: {1}, RequestStats: {2}, SDK: {3}. - /// - internal static string ExceptionMessageAddRequestUri - { - get - { - return ResourceManager.GetString("ExceptionMessageAddRequestUri", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Feature {0} is not supported for Multi-region Account. - /// - internal static string FeatureNotSupportedForMultiRegionAccount - { - get - { - return ResourceManager.GetString("FeatureNotSupportedForMultiRegionAccount", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Feature {0} is not supported in {1} region. - /// - internal static string FeatureNotSupportedInRegion - { - get - { - return ResourceManager.GetString("FeatureNotSupportedInRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} is not supported for the target subscription. - /// - internal static string FeatureNotSupportedOnSubscription - { - get - { - return ResourceManager.GetString("FeatureNotSupportedOnSubscription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MaterializedViews is not supported on this account type. - /// - internal static string MaterializedViewsNotSupportedOnZoneRedundantAccount - { - get - { - return ResourceManager.GetString("MaterializedViewsNotSupportedOnZoneRedundantAccount", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Federation {0} in region {1} is not found. - /// - internal static string FederationEntityNotFound - { - get - { - return ResourceManager.GetString("FederationEntityNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request is blocked by your Cosmos DB account firewall settings.. - /// - internal static string Forbidden - { - get - { - return ResourceManager.GetString("Forbidden", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request originated from IP {0} through public internet. - /// This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden. - /// - internal static string ForbiddenPublicIpv4 - { - get - { - return ResourceManager.GetString("ForbiddenPublicIpv4", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request originated from VNET through service endpoint. - /// This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden. - /// - internal static string ForbiddenServiceEndpoint - { - get - { - return ResourceManager.GetString("ForbiddenServiceEndpoint", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request received through private endpoint. - /// It is blocked because either your account does not have private endpoint configured, - /// or it is not from the private endpoint that your account is configured with. - /// More info: https://aka.ms/cosmosdb-tsg-forbidden. - /// - internal static string ForbiddenPrivateEndpoint - { - get - { - return ResourceManager.GetString("ForbiddenPrivateEndpoint", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Attempt to process the request timed out at remote server.. - /// - internal static string GatewayTimedout - { - get - { - return ResourceManager.GetString("GatewayTimedout", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database and Write Location are not matching. - /// - internal static string GlobalAndWriteRegionMisMatch - { - get - { - return ResourceManager.GetString("GlobalAndWriteRegionMisMatch", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Federation and region are not matching. - /// - internal static string FederationAndRegionMismatch - { - get - { - return ResourceManager.GetString("FederationAndRegionMismatch", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Global Strong write barrier has not been met for the request.. - /// - internal static string GlobalStrongWriteBarrierNotMet - { - get - { - return ResourceManager.GetString("GlobalStrongWriteBarrierNotMet", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested resource is no longer available at the server.. - /// - internal static string Gone - { - get - { - return ResourceManager.GetString("Gone", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to generate id for resourceType = {0}, partitionIndex = {1}, serviceIndex = {2}, partitionCount = {3}.. - /// - internal static string IdGenerationFailed - { - get - { - return ResourceManager.GetString("IdGenerationFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Routing map is not complete.. - /// - internal static string IncompleteRoutingMap - { - get - { - return ResourceManager.GetString("IncompleteRoutingMap", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Insufficient permissions provided in the authorization header for the corresponding request. Please retry with another authorization header.. - /// - internal static string InsufficientPermissions - { - get - { - return ResourceManager.GetString("InsufficientPermissions", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to continue without atleast a single token in the resource tokens input collection.. - /// - internal static string InsufficientResourceTokens - { - get - { - return ResourceManager.GetString("InsufficientResourceTokens", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unknown server error occurred when processing this request.. - /// - internal static string InternalServerError - { - get - { - return ResourceManager.GetString("InternalServerError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid API version. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK.. - /// - internal static string InvalidAPIVersion - { - get - { - return ResourceManager.GetString("InvalidAPIVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid API version for {0}. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK.. - /// - internal static string InvalidAPIVersionForFeature - { - get - { - return ResourceManager.GetString("InvalidAPIVersionForFeature", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to AudienceKind is Invalid. - /// - internal static string InvalidAudienceKind - { - get - { - return ResourceManager.GetString("InvalidAudienceKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid Audience Resource Type. - /// - internal static string InvalidAudienceResourceType - { - get - { - return ResourceManager.GetString("InvalidAudienceResourceType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Authorization header doesn't confirm to the required format. Please verify and try again.. - /// - internal static string InvalidAuthHeaderFormat - { - get - { - return ResourceManager.GetString("InvalidAuthHeaderFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The backend response was not in the correct format.. - /// - internal static string InvalidBackendResponse - { - get - { - return ResourceManager.GetString("InvalidBackendResponse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to "{0} capability cannot be specified with {1} .". - /// - internal static string InvalidCapabilityCombination - { - get - { - return ResourceManager.GetString("InvalidCapabilityCombination", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The resource name presented contains invalid character '{0}'.. - /// - internal static string InvalidCharacterInResourceName - { - get - { - return ResourceManager.GetString("InvalidCharacterInResourceName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid mode '{0}' for setting '{1}'. Mode expected is '{2}'.. - /// - internal static string InvalidConflictResolutionMode - { - get - { - return ResourceManager.GetString("InvalidConflictResolutionMode", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ConsistencyLevel {0} specified in the request is invalid when service is configured with consistency level {1}. Ensure the request consistency level is not stronger than the service consistency level.. - /// - internal static string InvalidConsistencyLevel - { - get - { - return ResourceManager.GetString("InvalidConsistencyLevel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid Continuation Token. - /// - internal static string InvalidContinuationToken - { - get - { - return ResourceManager.GetString("InvalidContinuationToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified document collection is invalid... - /// - internal static string InvalidDatabase - { - get - { - return ResourceManager.GetString("InvalidDatabase", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The input date header is invalid format. Please pass in RFC 1123 style date format.. - /// - internal static string InvalidDateHeader - { - get - { - return ResourceManager.GetString("InvalidDateHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified document collection is invalid.. - /// - internal static string InvalidDocumentCollection - { - get - { - return ResourceManager.GetString("InvalidDocumentCollection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot enable 'enableMultipleWriteLocations' without also enabling 'canEnableMultipleWriteLocations'.. - /// - internal static string InvalidEnableMultipleWriteLocations - { - get - { - return ResourceManager.GetString("InvalidEnableMultipleWriteLocations", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid value {0} passed for enum {1}. - /// - internal static string InvalidEnumValue - { - get - { - return ResourceManager.GetString("InvalidEnumValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failover priority value {0} supplied for region {1} is invalid. - /// - internal static string InvalidFailoverPriority - { - get - { - return ResourceManager.GetString("InvalidFailoverPriority", resourceCulture); - } - } - - - /// - /// Looks up a localized string similar to The CapUncapMetadata action '{0}' is not currently supported.. - /// - internal static string InvalidFederationCapUncapMetadataAction - { - get - { - return ResourceManager.GetString("InvalidFederationCapUncapMetadataAction", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The CapUncapMetadata source '{0}' is invalid.. - /// - internal static string InvalidFederationCapUncapMetadataSource - { - get - { - return ResourceManager.GetString("InvalidFederationCapUncapMetadataSource", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value '{0}' specified for the header '{1}' is invalid. . - /// - internal static string InvalidHeaderValue - { - get - { - return ResourceManager.GetString("InvalidHeaderValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The specified value {0} of the index kind is invalid.. - /// - internal static string InvalidIndexKindValue - { - get - { - return ResourceManager.GetString("InvalidIndexKindValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The index spec format is invalid.. - /// - internal static string InvalidIndexSpecFormat - { - get - { - return ResourceManager.GetString("InvalidIndexSpecFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Received invalid index transformation progress values from all the replicas.. - /// - internal static string InvalidIndexTransformationProgressValues - { - get - { - return ResourceManager.GetString("InvalidIndexTransformationProgressValues", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to List of supplied locations is invalid. - /// - internal static string InvalidLocations - { - get - { - return ResourceManager.GetString("InvalidLocations", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only one manualPrivateLinkServiceConnection or one privateLinkServiceConnection is supported. - /// - internal static string InvalidPrivateLinkServiceConnections - { - get - { - return ResourceManager.GetString("InvalidPrivateLinkServiceConnections", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only one privateLinkServiceProxy is supported. - /// - internal static string InvalidPrivateLinkServiceProxies - { - get - { - return ResourceManager.GetString("InvalidPrivateLinkServiceProxies", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only one groupId is supported. - /// - internal static string InvalidGroupIdCount - { - get - { - return ResourceManager.GetString("InvalidGroupIdCount", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to GroupId {0} is not supported. - /// - internal static string InvalidGroupId - { - get - { - return ResourceManager.GetString("InvalidGroupId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MaxStalenessInterval should be greater than or equal to {0} sec and less than or equal to {1} sec. - /// - internal static string InvalidMaxStalenessInterval - { - get - { - return ResourceManager.GetString("InvalidMaxStalenessInterval", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to MaxStalenessPrefix should be greater than or equal to {0} and less than or equal to {1}. - /// - internal static string InvalidMaxStalenessPrefix - { - get - { - return ResourceManager.GetString("InvalidMaxStalenessPrefix", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer throughput specified exceeded supported maximum throughput for Fixed size container. Please enter value less than {0}.. - /// - internal static string InvalidNonPartitionedOfferThroughput - { - get - { - return ResourceManager.GetString("InvalidNonPartitionedOfferThroughput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The container doesn't have enough data populated with partition key information. Please retry the throughput scale operation after inserting data with partition key information. - /// - internal static string InsufficientPartitionedDataForOfferThroughput - { - get - { - return ResourceManager.GetString("InsufficientPartitionedDataForOfferThroughput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer IsAutoScaleEnabled specified is invalid. Please specify a boolean value.. - /// - internal static string InvalidOfferIsAutoScaleEnabled - { - get - { - return ResourceManager.GetString("InvalidOfferIsAutoScaleEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of OfferAutoScaleMode specified is invalid. Please specfy a valid auto scale mode. - /// - internal static string InvalidOfferAutoScaleMode - { - get - { - return ResourceManager.GetString("InvalidOfferAutoScaleMode", resourceCulture); - } - } - - internal static string OfferAutopilotNotSupportedForNonPartitionedCollections - { - get - { - return ResourceManager.GetString("OfferAutopilotNotSupportedForNonPartitionedCollections", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Autopilot is currently not supported on shared throughput database. - /// - internal static string OfferAutopilotNotSupportedOnSharedThroughputDatabase - { - get - { - return ResourceManager.GetString("OfferAutopilotNotSupportedOnSharedThroughputDatabase", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer IsRUPerMinuteThroughputEnabled specified is invalid. Please specify a boolean value.. - /// - internal static string InvalidOfferIsRUPerMinuteThroughputEnabled - { - get - { - return ResourceManager.GetString("InvalidOfferIsRUPerMinuteThroughputEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer BackgroundTaskMaxAllowedThroughputPercent specified is invalid. Please specify a double value.. - /// - internal static string InvalidBackgroundTaskMaxAllowedThroughputPercent - { - get - { - return ResourceManager.GetString("InvalidBackgroundTaskMaxAllowedThroughputPercent", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please enter valid positive integer.. - /// - internal static string InvalidOfferThroughput - { - get - { - return ResourceManager.GetString("InvalidOfferThroughput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to OfferType {0} specified in the request is invalid. Please refer to offer documentation and specify a valid offer type.. - /// - internal static string InvalidOfferType - { - get - { - return ResourceManager.GetString("InvalidOfferType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The required field Content is missing in Offer version v2.. - /// - internal static string InvalidOfferV2Input - { - get - { - return ResourceManager.GetString("InvalidOfferV2Input", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Offer read/replace is not supported for serverless accounts. - /// - internal static string InvalidOfferCRUDForServerless - { - get - { - return ResourceManager.GetString("InvalidOfferCRUDForServerless", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource {0} is invalid for adding owner resource record. - /// - internal static string InvalidOwnerResourceType - { - get - { - return ResourceManager.GetString("InvalidOwnerResourceType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The input PageSize {0} is invalid. Ensure to pass a valid page size which must be a positive integer or -1 for a dynamic page size.. - /// - internal static string InvalidPageSize - { - get - { - return ResourceManager.GetString("InvalidPageSize", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Partition key {0} is invalid.. - /// - internal static string InvalidPartitionKey - { - get - { - return ResourceManager.GetString("InvalidPartitionKey", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to x-ms-documentdb-partitionkeyrangeid header contains invalid value '{0}'.. - /// - internal static string InvalidPartitionKeyRangeIdHeader - { - get - { - return ResourceManager.GetString("InvalidPartitionKeyRangeIdHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The permission mode provided in the authorization token doesn't provide sufficient permissions.. - /// - internal static string InvalidPermissionMode - { - get - { - return ResourceManager.GetString("InvalidPermissionMode", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid policy type found.. - /// - internal static string InvalidPolicyType - { - get - { - return ResourceManager.GetString("InvalidPolicyType", resourceCulture); - } - } - /// - /// Looks up a localized string similar to Command is not supported by backend. - /// - internal static string InvalidProxyCommand - { - get - { - return ResourceManager.GetString("InvalidProxyCommand", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Query '{0}' specified is either invalid or unsupported.. - /// - internal static string InvalidQuery - { - get - { - return ResourceManager.GetString("InvalidQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value '{0}' specified for the query '{1}' is invalid.. - /// - internal static string InvalidQueryValue - { - get - { - return ResourceManager.GetString("InvalidQueryValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Compared session tokens '{0}' and '{1}' has unexpected regions. . - /// - internal static string InvalidRegionsInSessionToken - { - get - { - return ResourceManager.GetString("InvalidRegionsInSessionToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Strong consistency level cannot be specified with async replication. Either change the replication policy 'AsyncReplication' to false or relax the consistency level.. - /// - internal static string InvalidReplicationAndConsistencyCombination - { - get - { - return ResourceManager.GetString("InvalidReplicationAndConsistencyCombination", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to parse the value '{0}' as ResourceId.. - /// - internal static string InvalidResourceID - { - get - { - return ResourceManager.GetString("InvalidResourceID", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value for {0} should be greater than 0. - /// - internal static string InvalidResourceIdBatchSize - { - get - { - return ResourceManager.GetString("InvalidResourceIdBatchSize", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource kind {0} is invalid. - /// - internal static string InvalidResourceKind - { - get - { - return ResourceManager.GetString("InvalidResourceKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Requested ResourceType {0} passed as generic argument should be same as the one specified by ResourceType member {1}. - /// - internal static string InvalidResourceType - { - get - { - return ResourceManager.GetString("InvalidResourceType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource Url path {0} is invalid.. - /// - internal static string InvalidResourceUrlPath - { - get - { - return ResourceManager.GetString("InvalidResourceUrlPath", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value '{0}' specified for query '{1}' is invalid.. - /// - internal static string InvalidResourceUrlQuery - { - get - { - return ResourceManager.GetString("InvalidResourceUrlQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The input continuation token size limit {0} is invalid. Please pass in a valid continuation token size limit which must be a positive integer.. - /// - internal static string InvalidResponseContinuationTokenLimit - { - get - { - return ResourceManager.GetString("InvalidResponseContinuationTokenLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Script request has invalid body.. - /// - internal static string InvalidScriptResource - { - get - { - return ResourceManager.GetString("InvalidScriptResource", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The session token provided '{0}' is invalid.. - /// - internal static string InvalidSessionToken - { - get - { - return ResourceManager.GetString("InvalidSessionToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The resource name can't end with space.. - /// - internal static string InvalidSpaceEndingInResourceName - { - get - { - return ResourceManager.GetString("InvalidSpaceEndingInResourceName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Staleness Policy specified is invalid. Ensure both MaxPrefix and MaxStalenessIntervalInSeconds are both 0 or both not zero.. - /// - internal static string InvalidStalenessPolicy - { - get - { - return ResourceManager.GetString("InvalidStalenessPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Storage Service index {0} for media account {1} must be within byte range (inclusive).. - /// - internal static string InvalidStorageServiceMediaIndex - { - get - { - return ResourceManager.GetString("InvalidStorageServiceMediaIndex", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot disable 'canEnableMultipleWriteLocations' flag once it has been enabled.. - /// - internal static string InvalidSwitchOffCanEnableMultipleWriteLocations - { - get - { - return ResourceManager.GetString("InvalidSwitchOffCanEnableMultipleWriteLocations", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot enable 'canEnableMultipleWriteLocations' flag once account has been created with it disabled.. - /// - internal static string InvalidSwitchOnCanEnableMultipleWriteLocations - { - get - { - return ResourceManager.GetString("InvalidSwitchOnCanEnableMultipleWriteLocations", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Target for the request is invalid. - /// - internal static string InvalidTarget - { - get - { - return ResourceManager.GetString("InvalidTarget", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The authorization token is not valid at the current time. Please create another token and retry (token start time: {0}, token expiry time: {1}, current server time: {2}).. - /// - internal static string InvalidTokenTimeRange - { - get - { - return ResourceManager.GetString("InvalidTokenTimeRange", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request url is invalid.. - /// - internal static string InvalidUrl - { - get - { - return ResourceManager.GetString("InvalidUrl", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request path {0} is invalid.. - /// - internal static string InvalidRequestUrl - { - get - { - return ResourceManager.GetString("InvalidRequestUrl", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to System key can only access replica root. - /// - internal static string InvalidUseSystemKey - { - get - { - return ResourceManager.GetString("InvalidUseSystemKey", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid version format for {0}. Input Version {1}. - /// - internal static string InvalidVersionFormat - { - get - { - return ResourceManager.GetString("InvalidVersionFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to IpAddress {0} is blocked by Policy. - /// - internal static string IpAddressBlockedByPolicy - { - get - { - return ResourceManager.GetString("IpAddressBlockedByPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Not allowed to force delete federation in this environment.. - /// - internal static string IsForceDeleteFederationAllowed - { - get - { - return ResourceManager.GetString("IsForceDeleteFederationAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tried to write a JSON end array (“]“) symbol without a matching array start symbol (“[“).. - /// - internal static string JsonArrayNotStarted - { - get - { - return ResourceManager.GetString("JsonArrayNotStarted", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid escape character in JSON.. - /// - internal static string JsonInvalidEscapedCharacter - { - get - { - return ResourceManager.GetString("JsonInvalidEscapedCharacter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid number in JSON.. - /// - internal static string JsonInvalidNumber - { - get - { - return ResourceManager.GetString("JsonInvalidNumber", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid parameter in JSON.. - /// - internal static string JsonInvalidParameter - { - get - { - return ResourceManager.GetString("JsonInvalidParameter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid string character in JSON.. - /// - internal static string JsonInvalidStringCharacter - { - get - { - return ResourceManager.GetString("JsonInvalidStringCharacter", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered an element that is not a valid JSON value (false / null / true / object / array / number / string). - /// - internal static string JsonInvalidToken - { - get - { - return ResourceManager.GetString("JsonInvalidToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid Unicode escape sequence in JSON.. - /// - internal static string JsonInvalidUnicodeEscape - { - get - { - return ResourceManager.GetString("JsonInvalidUnicodeEscape", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Exceeded the maximum level of nesting for JSON.. - /// - internal static string JsonMaxNestingExceeded - { - get - { - return ResourceManager.GetString("JsonMaxNestingExceeded", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing a closing quote (") in JSON.. - /// - internal static string JsonMissingClosingQuote - { - get - { - return ResourceManager.GetString("JsonMissingClosingQuote", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing an end array ("]") symbol in JSON.. - /// - internal static string JsonMissingEndArray - { - get - { - return ResourceManager.GetString("JsonMissingEndArray", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing an end object ("}") symbol in JSON.. - /// - internal static string JsonMissingEndObject - { - get - { - return ResourceManager.GetString("JsonMissingEndObject", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing a name separator (":") in JSON.. - /// - internal static string JsonMissingNameSeparator - { - get - { - return ResourceManager.GetString("JsonMissingNameSeparator", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing a JSON property.. - /// - internal static string JsonMissingProperty - { - get - { - return ResourceManager.GetString("JsonMissingProperty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a JSON property name without a corresponding property value. - /// - internal static string JsonNotComplete - { - get - { - return ResourceManager.GetString("JsonNotComplete", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a value that was not a JSON field name.. - /// - internal static string JsonNotFieldnameToken - { - get - { - return ResourceManager.GetString("JsonNotFieldnameToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a value that was not a JSON number.. - /// - internal static string JsonNotNumberToken - { - get - { - return ResourceManager.GetString("JsonNotNumberToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a value that was not a JSON string.. - /// - internal static string JsonNotStringToken - { - get - { - return ResourceManager.GetString("JsonNotStringToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a number that exceeded the range for JSON numbers.. - /// - internal static string JsonNumberOutOfRange - { - get - { - return ResourceManager.GetString("JsonNumberOutOfRange", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a number that was too long for a JSON number.. - /// - internal static string JsonNumberTooLong - { - get - { - return ResourceManager.GetString("JsonNumberTooLong", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Tried to write a JSON object end symbol ("}") without first opening with a JSON object start symbol ("{").. - /// - internal static string JsonObjectNotStarted - { - get - { - return ResourceManager.GetString("JsonObjectNotStarted", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered a JSON property name after another JSON property name.. - /// - internal static string JsonPropertyAlreadyAdded - { - get - { - return ResourceManager.GetString("JsonPropertyAlreadyAdded", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Either a JSON property array or object was not started.. - /// - internal static string JsonPropertyArrayOrObjectNotStarted - { - get - { - return ResourceManager.GetString("JsonPropertyArrayOrObjectNotStarted", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Read a JSON end array ("]") symbol without a matching JSON start array symbol ("[").. - /// - internal static string JsonUnexpectedEndArray - { - get - { - return ResourceManager.GetString("JsonUnexpectedEndArray", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Read a JSON end object ("}") symbol without a matching JSON start object symbol ("{").. - /// - internal static string JsonUnexpectedEndObject - { - get - { - return ResourceManager.GetString("JsonUnexpectedEndObject", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Read a JSON name separator (":") symbol without a corresponding field name.. - /// - internal static string JsonUnexpectedNameSeparator - { - get - { - return ResourceManager.GetString("JsonUnexpectedNameSeparator", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Encountered an unexpected JSON token.. - /// - internal static string JsonUnexpectedToken - { - get - { - return ResourceManager.GetString("JsonUnexpectedToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Read a JSON name separator (",") symbol without a preceding JSON value.. - /// - internal static string JsonUnexpectedValueSeparator - { - get - { - return ResourceManager.GetString("JsonUnexpectedValueSeparator", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The resource that is being accessed is locked.. - /// - internal static string Locked - { - get - { - return ResourceManager.GetString("Locked", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Current maximum throughput per collection is {0}. Please contact Azure support to increase it.. - /// - internal static string MaximumRULimitExceeded - { - get - { - return ResourceManager.GetString("MaximumRULimitExceeded", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot find messageId header. - /// - internal static string MessageIdHeaderMissing - { - get - { - return ResourceManager.GetString("MessageIdHeaderMissing", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested verb is not supported.. - /// - internal static string MethodNotAllowed - { - get - { - return ResourceManager.GetString("MethodNotAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: '{0}'. - /// - internal static string MismatchToken - { - get - { - return ResourceManager.GetString("MismatchToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Required Header authorization is missing. Ensure a valid Authorization token is passed.. - /// - internal static string MissingAuthHeader - { - get - { - return ResourceManager.GetString("MissingAuthHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Authorization token mandates Date headers. Please pass in RFC 1123 style date format.. - /// - internal static string MissingDateForAuthorization - { - get - { - return ResourceManager.GetString("MissingDateForAuthorization", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKey value must be supplied for this operation.. - /// - internal static string MissingPartitionKeyValue - { - get - { - return ResourceManager.GetString("MissingPartitionKeyValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Required property {0} is not specified in the request.. - /// - internal static string MissingProperty - { - get - { - return ResourceManager.GetString("MissingProperty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Required header '{0}' is not specified in the request.. - /// - internal static string MissingRequiredHeader - { - get - { - return ResourceManager.GetString("MissingRequiredHeader", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Required query variable '{0}' is not specified in the request.. - /// - internal static string MissingRequiredQuery - { - get - { - return ResourceManager.GetString("MissingRequiredQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This account already has one backup interval capability.. - /// - internal static string MoreThanOneBackupIntervalCapability - { - get - { - return ResourceManager.GetString("MoreThanOneBackupIntervalCapability", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to This account already has one backup retention capability.. - /// - internal static string MoreThanOneBackupRetentionCapability - { - get - { - return ResourceManager.GetString("MoreThanOneBackupRetentionCapability", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Atleast single region must be specified in PreferredLocation list when automatic failover is disabled.. - /// - internal static string MustHaveNonZeroPreferredRegionWhenAutomaticFailoverDisabled - { - get - { - return ResourceManager.GetString("MustHaveNonZeroPreferredRegionWhenAutomaticFailoverDisabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to NamingProperty {0} not found. - /// - internal static string NamingPropertyNotFound - { - get - { - return ResourceManager.GetString("NamingPropertyNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Property '{0}' integer value must be greater than or equal to zero.. - /// - internal static string NegativeInteger - { - get - { - return ResourceManager.GetString("NegativeInteger", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No graft point. - /// - internal static string NoGraftPoint - { - get - { - return ResourceManager.GetString("NoGraftPoint", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Entity with the specified id does not exist in the system.. - /// - internal static string NotFound - { - get - { - return ResourceManager.GetString("NotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to GraphAPICompute Service cannot be deleted. - /// - internal static string GremlinV2ServiceDeleteNotSupported - { - get - { - return ResourceManager.GetString("GremlinV2ServiceDeleteNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Offer replace request conflicted.. - /// - internal static string OfferReplaceTopologyConflict - { - get - { - return ResourceManager.GetString("OfferReplaceTopologyConflict", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot replace an offer with version {0} with version {1}. - /// - internal static string OfferReplaceWithSpecifiedVersionsNotSupported - { - get - { - return ResourceManager.GetString("OfferReplaceWithSpecifiedVersionsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Offer type and throughput cannot both be specified.. - /// - internal static string OfferTypeAndThroughputCannotBeSpecifiedBoth - { - get - { - return ResourceManager.GetString("OfferTypeAndThroughputCannotBeSpecifiedBoth", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Offer throughput and autopilot settings cannot both be specified.. - /// - internal static string OfferThroughputAndAutoPilotSettingsCannotBeSpecifiedBoth - { - get - { - return ResourceManager.GetString("OfferThroughputAndAutoPilotSettingsCannotBeSpecifiedBoth", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Autopilot tier and AutoPilotSettings cannot both be specified.. - /// - internal static string AutoPilotTierAndAutoPilotSettingsCannotBeSpecifiedBoth - { - get - { - return ResourceManager.GetString("AutoPilotTierAndAutoPilotSettingsCannotBeSpecifiedBoth", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Autopilot autoupgrade is not supported for non-partitioned collections.. - /// - internal static string AutopilotAutoUpgradeUnsupportedNonPartitionedCollection - { - get - { - return ResourceManager.GetString("AutopilotAutoUpgradeUnsupportedNonPartitionedCollection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Requested Operation Status = {0} is invalid.. - /// - internal static string OperationRequestedStatusIsInvalid - { - get - { - return ResourceManager.GetString("OperationRequestedStatusIsInvalid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Selected partition is full, please try insert in different partition.. - /// - internal static string PartitionIsFull - { - get - { - return ResourceManager.GetString("PartitionIsFull", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Either PartitionKey or EffectivePartitionKey are expected.. - /// - internal static string PartitionKeyAndEffectivePartitionKeyBothSpecified - { - get - { - return ResourceManager.GetString("PartitionKeyAndEffectivePartitionKeyBothSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKey and PartitionKeyRangeId cannot be specified at the same time in ChangeFeedOptions.. - /// - internal static string PartitionKeyAndPartitionKeyRangeRangeIdBothSpecified - { - get - { - return ResourceManager.GetString("PartitionKeyAndPartitionKeyRangeRangeIdBothSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document.. - /// - internal static string PartitionKeyMismatch - { - get - { - return ResourceManager.GetString("PartitionKeyMismatch", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKeyRangeId is absent in the context.. - /// - internal static string PartitionKeyRangeIdAbsentInContext - { - get - { - return ResourceManager.GetString("PartitionKeyRangeIdAbsentInContext", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to For partitioned collection, either ChangeFeedOptions.PartitionKeyRangeId or ChangeFeedOptions.PartitionKey must be specified.. - /// - internal static string PartitionKeyRangeIdOrPartitionKeyMustBeSpecified - { - get - { - return ResourceManager.GetString("PartitionKeyRangeIdOrPartitionKeyMustBeSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKeyRange with id '{0}' in collection '{1}' doesn't exist.. - /// - internal static string PartitionKeyRangeNotFound - { - get - { - return ResourceManager.GetString("PartitionKeyRangeNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Property '{0}' integer value must be greater than zero.. - /// - internal static string PositiveInteger - { - get - { - return ResourceManager.GetString("PositiveInteger", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Operation cannot be performed because one of the specified precondition is not met.. - /// - internal static string PreconditionFailed - { - get - { - return ResourceManager.GetString("PreconditionFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database account was created successfully, but the following regions failed to be added to account: \n. - /// - internal static string PrimarySuceededButAdditionalRegionsFailed - { - get - { - return ResourceManager.GetString("PrimarySuceededButAdditionalRegionsFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database account creation failed. Operation Id : {0}, Error : {1}. - /// - internal static string PrimaryWriteRegionFailedFormat - { - get - { - return ResourceManager.GetString("PrimaryWriteRegionFailedFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to {0} : Operation Id : {1}, Error : {2}\n. - /// - internal static string SecondaryRegionsFailedFormat - { - get - { - return ResourceManager.GetString("SecondaryRegionsFailedFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Add or Remove region operation failed. - /// - internal static string AddRemoveRegionOperationFailed - { - get - { - return ResourceManager.GetString("AddRemoveRegionOperationFailed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to resolve primary endpoint for partition {0} for service {1}.. - /// - internal static string PrimaryNotFound - { - get - { - return ResourceManager.GetString("PrimaryNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Property {0} can not be assigned to null.. - /// - internal static string PropertyCannotBeNull - { - get - { - return ResourceManager.GetString("PropertyCannotBeNull", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Property '{0}' is not found in the document.. - /// - internal static string PropertyNotFound - { - get - { - return ResourceManager.GetString("PropertyNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Reached the pre-approved storage limit for the database account. Please contact Azure support to increase this limit.. - /// - internal static string ProvisionLimit - { - get - { - return ResourceManager.GetString("ProvisionLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot authorize request since the [Action] to authorize was not found.. - /// - internal static string RbacMissingAction - { - get - { - return ResourceManager.GetString("RbacMissingAction", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot authorize request since the [User ID] to authorize was not found.. - /// - internal static string RbacMissingUserId - { - get - { - return ResourceManager.GetString("RbacMissingUserId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request is blocked because ResourceId [{0}] cannot be resolved. Principal = [{1}], Action = [{2}], ResourceType = [{3}].. - /// - internal static string RbacCannotResolveResourceRid - { - get - { - return ResourceManager.GetString("RbacCannotResolveResourceRid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Read Quorum size of {0} is not met for the request.. - /// - internal static string ReadQuorumNotMet - { - get - { - return ResourceManager.GetString("ReadQuorumNotMet", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The read session is not available for the input session token.. - /// - internal static string ReadSessionNotAvailable - { - get - { - return ResourceManager.GetString("ReadSessionNotAvailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to read the server response.. - /// - internal static string ReceiveFailedTransportError - { - get - { - return ResourceManager.GetString("ReceiveFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The remote system closed the connection.. - /// - internal static string ReceiveStreamClosedTransportError - { - get - { - return ResourceManager.GetString("ReceiveStreamClosedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request timed out while waiting for a server response.. - /// - internal static string ReceiveTimeoutTransportError - { - get - { - return ResourceManager.GetString("ReceiveTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot remove write region for account {0}. Please issue delete on the account to remove write region. - /// - internal static string RemoveWriteRegionNotSupported - { - get - { - return ResourceManager.GetString("RemoveWriteRegionNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Replica at index '{0}' is currently unavailable.. - /// - internal static string ReplicaAtIndexNotAvailable - { - get - { - return ResourceManager.GetString("ReplicaAtIndexNotAvailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Consistency Level '{0}' requested via header '{1}' is not supported by this service endpoint. Please contact the service administrator.. - /// - internal static string RequestConsistencyLevelNotSupported - { - get - { - return ResourceManager.GetString("RequestConsistencyLevelNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The size of the response exceeded the maximum allowed size, limit the response size by specifying smaller value for '{0}' header.. - /// - internal static string RequestEntityTooLarge - { - get - { - return ResourceManager.GetString("RequestEntityTooLarge", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Request timed out.. - /// - internal static string RequestTimeout - { - get - { - return ResourceManager.GetString("RequestTimeout", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request timed out. See the inner exception for details.. - /// - internal static string RequestTimeoutTransportError - { - get - { - return ResourceManager.GetString("RequestTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The size of the request exceeded the maximum allowed size.. - /// - internal static string RequestTooLarge - { - get - { - return ResourceManager.GetString("RequestTooLarge", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource id cannot be empty.. - /// - internal static string ResourceIdCannotBeEmpty - { - get - { - return ResourceManager.GetString("ResourceIdCannotBeEmpty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ResourceId {0} of type {1} is not a valid resource Id.. - /// - internal static string ResourceIdNotValid - { - get - { - return ResourceManager.GetString("ResourceIdNotValid", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ResourceIdPolicy {0} is not supported. - /// - internal static string ResourceIdPolicyNotSupported - { - get - { - return ResourceManager.GetString("ResourceIdPolicyNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource type {0} is not supported by ResourceIdPartitioner. - /// - internal static string ResourceTypeNotSupported - { - get - { - return ResourceManager.GetString("ResourceTypeNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Retry the request.. - /// - internal static string RetryWith - { - get - { - return ResourceManager.GetString("RetryWith", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Changing id of a script in collections with multiple partitions is not supported.. - /// - internal static string ScriptRenameInMultiplePartitionsIsNotSupported - { - get - { - return ResourceManager.GetString("ScriptRenameInMultiplePartitionsIsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to resolve secondary endpoint for partition {0} for service {1}.. - /// - internal static string SecondariesNotFound - { - get - { - return ResourceManager.GetString("SecondariesNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Sending the request failed.. - /// - internal static string SendFailedTransportError - { - get - { - return ResourceManager.GetString("SendFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Acquiring the send stream lock timed out.. - /// - internal static string SendLockTimeoutTransportError - { - get - { - return ResourceManager.GetString("SendLockTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Sending the request timed out.. - /// - internal static string SendTimeoutTransportError - { - get - { - return ResourceManager.GetString("SendTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Partition reconfiguration exceeded retry limit. Please contact support with the full exception. - /// - internal static string Server_CompletingPartitionMigrationExceededRetryLimit - { - get - { - return ResourceManager.GetString("Server_CompletingPartitionMigrationExceededRetryLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unhandled partition split. Please contact support with the full exception. - /// - internal static string Server_CompletingSplitExceededRetryLimit - { - get - { - return ResourceManager.GetString("Server_CompletingSplitExceededRetryLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not achieve backend quorum for Strong or Bounded Staleness after barrier requests. - /// - internal static string Server_GlobalStrongWriteBarrierNotMet - { - get - { - return ResourceManager.GetString("Server_GlobalStrongWriteBarrierNotMet", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Container was re-created, exceeded retries to resolve new identifier. Please contact support with the full exception. - /// - internal static string Server_NameCacheIsStaleExceededRetryLimit - { - get - { - return ResourceManager.GetString("Server_NameCacheIsStaleExceededRetryLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Store (backend) returned an invalid response. Please contact support with the full exception. - /// - internal static string Server_NoValidStoreResponse - { - get - { - return ResourceManager.GetString("Server_NoValidStoreResponse", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unhandled partition split. Please contact support with the full exception. - /// - internal static string Server_PartitionKeyRangeGoneExceededRetryLimit - { - get - { - return ResourceManager.GetString("Server_PartitionKeyRangeGoneExceededRetryLimit", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not achieve backend quorum. - /// - internal static string Server_ReadQuorumNotMet - { - get - { - return ResourceManager.GetString("Server_ReadQuorumNotMet", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Server returned a 410 response. - /// - internal static string ServerGenerated410 - { - get - { - return ResourceManager.GetString("ServerGenerated410", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Server returned a 503 response. - /// - internal static string ServerGenerated503 - { - get - { - return ResourceManager.GetString("ServerGenerated503", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The response body length is too large. Body length: {0} bytes. Connection: {1}. - /// - internal static string ServerResponseBodyTooLargeError - { - get - { - return ResourceManager.GetString("ServerResponseBodyTooLargeError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The response total header length is too large. Header length: {0} bytes. Connection: {1}. - /// - internal static string ServerResponseHeaderTooLargeError - { - get - { - return ResourceManager.GetString("ServerResponseHeaderTooLargeError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid response total header length. Expected {0} bytes. Received {1} bytes. Connection: {2}. - /// - internal static string ServerResponseInvalidHeaderLengthError - { - get - { - return ResourceManager.GetString("ServerResponseInvalidHeaderLengthError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The transport request ID is missing from the server response.. - /// - internal static string ServerResponseTransportRequestIdMissingError - { - get - { - return ResourceManager.GetString("ServerResponseTransportRequestIdMissingError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service at index {0} not found.. - /// - internal static string ServiceNotFound - { - get - { - return ResourceManager.GetString("ServiceNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service reserved bits can not be more than 24. Otherwise it overlaps with the collection/user multiplexing bit. - /// - internal static string ServiceReservedBitsOutOfRange - { - get - { - return ResourceManager.GetString("ServiceReservedBitsOutOfRange", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service is currently unavailable.. - /// - internal static string ServiceUnavailable - { - get - { - return ResourceManager.GetString("ServiceUnavailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Service Unavailable due to high demand in the region. - /// - internal static string ServiceUnavailableDueToHighDemandInRegion - { - get - { - return ResourceManager.GetString("ServiceUnavailableDueToHighDemandInRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not find service hosting DocumentCollection with ResourceId {0}. - /// - internal static string ServiceWithResourceIdNotFound - { - get - { - return ResourceManager.GetString("ServiceWithResourceIdNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Bounding box must have an even number of coordinates and more than 3.. - /// - internal static string SpatialBoundingBoxInvalidCoordinates - { - get - { - return ResourceManager.GetString("SpatialBoundingBoxInvalidCoordinates", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Spatial operations can be used in Linq expressions only and are evaluated in Azure CosmosDB server.. - /// - internal static string SpatialExtensionMethodsNotImplemented - { - get - { - return ResourceManager.GetString("SpatialExtensionMethodsNotImplemented", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Coordinate Reference System specified in GeoJSON is invalid.. - /// - internal static string SpatialFailedToDeserializeCrs - { - get - { - return ResourceManager.GetString("SpatialFailedToDeserializeCrs", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to deserialize Geometry object because 'type' property is either absent or has invalid value.. - /// - internal static string SpatialInvalidGeometryType - { - get - { - return ResourceManager.GetString("SpatialInvalidGeometryType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Spatial position must have at least two coordinates.. - /// - internal static string SpatialInvalidPosition - { - get - { - return ResourceManager.GetString("SpatialInvalidPosition", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SSL negotiation failed.. - /// - internal static string SslNegotiationFailedTransportError - { - get - { - return ResourceManager.GetString("SslNegotiationFailedTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to SSL negotiation timed out.. - /// - internal static string SslNegotiationTimeoutTransportError - { - get - { - return ResourceManager.GetString("SslNegotiationTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Star and slash should have no arguments.. - /// - internal static string StarSlashArgumentError - { - get - { - return ResourceManager.GetString("StarSlashArgumentError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Storage analytics is not enabled for this account. Ensure storage analytics is enabled before retrying.. - /// - internal static string StorageAnalyticsNotEnabled - { - get - { - return ResourceManager.GetString("StorageAnalyticsNotEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to String agument {0} is null or empty. - /// - internal static string StringArgumentNullOrEmpty - { - get - { - return ResourceManager.GetString("StringArgumentNullOrEmpty", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to System database account with name {0} and type {1} not found. - /// - internal static string SystemDatabaseAccountNotFound - { - get - { - return ResourceManager.GetString("SystemDatabaseAccountNotFound", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to System database account {0} cannot be created with Continuous backup mode. - /// - internal static string SystemDatabaseAccountPitrEnabledNotSupported - { - get - { - return ResourceManager.GetString("SystemDatabaseAccountPitrEnabledNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cross tenant CMK database account doesn't support using delegated identity as the default identity. - /// - internal static string CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported - { - get - { - return ResourceManager.GetString("CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The server encountered an unexpected condition that prevented it from fulfilling the Azure Key Vault resource request. - /// - internal static string UnexpectedExceptionCaughtonKeyVaultAccessClient - { - get - { - return ResourceManager.GetString("UnexpectedExceptionCaughtonKeyVaultAccessClient", resourceCulture); - } - } - - /// - /// The expected scope array should be of length 1. Instead received scope with length {0}. - /// - internal static string InvalidMSALScopeLength - { - get - { - return ResourceManager.GetString("InvalidMSALScopeLength", resourceCulture); - } - } - - /// - /// The requested scope is not a well formed URI string. - /// - internal static string InvalidRequestedScopeFormat - { - get - { - return ResourceManager.GetString("InvalidRequestedScopeFormat", resourceCulture); - } - } - - /// - /// The requested scope is not https. - /// - internal static string InvalidSchemeInScope - { - get - { - return ResourceManager.GetString("InvalidSchemeInScope", resourceCulture); - } - } - - /// - /// The requested scope contains unexpected segments. - /// - internal static string InvalildScopeSegments - { - get - { - return ResourceManager.GetString("InvalildScopeSegments", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Error contacting the Azure Key Vault resource. Please try again. - /// - internal static string KeyVaultServiceUnavailable - { - get - { - return ResourceManager.GetString("KeyVaultServiceUnavailable", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The provided Azure Key Vault resource key URI is invalid. Please follow the format: https://{vault-name}.vault.azure.net/keys/{key-name} or https://{vault-name}.vault.azure.net/certificates/{certificate-name} or https://{vault-name}.vault.azure.net/secrets/{secret-name} . - /// - internal static string InvalidKeyVaultKeyAndCertURI - { - get - { - return ResourceManager.GetString("InvalidKeyVaultKeyAndCertURI", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The provided Azure Key Vault resource key URI is invalid. Please follow the format: https://{vault-name}.vault.azure.net/secrets/{secret-name} . - /// - internal static string InvalidKeyVaulSecretURI - { - get - { - return ResourceManager.GetString("InvalidKeyVaulSecretURI", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The remote name could not be resolved for the Azure Key Vault resource. Please provide a valid URI for an existing Key vault. - /// - internal static string KeyVaultDNSNotResolved - { - get - { - return ResourceManager.GetString("KeyVaultDNSNotResolved", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Could not find any secret with the.pem extension related to the provided certificate. - /// - internal static string KeyVaultCertificateException - { - get - { - return ResourceManager.GetString("KeyVaultCertificateException", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The Input provided is not a valid base 64 string. - /// - internal static string KeyVaultInvalidInputBytes - { - get - { - return ResourceManager.GetString("KeyVaultInvalidInputBytes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to acquire the access token needed to access the Azure Key Vault resource. Please verify that the tenant has all corresponding permissions assigned. - /// - internal static string KeyVaultAadClientCredentialsGrantFailure - { - get - { - return ResourceManager.GetString("KeyVaultAadClientCredentialsGrantFailure", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The Status Code for the first Azure Key Vault resource access try should be Unauthorized. - /// - internal static string FirstKeyVaultAccessAttemptShouldBeUnauthorized - { - get - { - return ResourceManager.GetString("FirstKeyVaultAccessAttemptShouldBeUnauthorized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Network timeout or connectivity failure. - /// - internal static string TimeoutGenerated410 - { - get - { - return ResourceManager.GetString("TimeoutGenerated410", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKey has fewer components than defined the collection resource.. - /// - internal static string TooFewPartitionKeyComponents - { - get - { - return ResourceManager.GetString("TooFewPartitionKeyComponents", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKey has more components than defined the collection resource.. - /// - internal static string TooManyPartitionKeyComponents - { - get - { - return ResourceManager.GetString("TooManyPartitionKeyComponents", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The request rate is too large. Please retry after sometime. Learn more: http://aka.ms/cosmosdb-error-429. - /// - internal static string TooManyRequests - { - get - { - return ResourceManager.GetString("TooManyRequests", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A client transport error occurred: {0}. - /// - internal static string TransportExceptionMessage - { - get - { - return ResourceManager.GetString("TransportExceptionMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The SDK failed to connect to the service. Please check your networking configuration. - /// - internal static string TransportGenerated410 - { - get - { - return ResourceManager.GetString("TransportGenerated410", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Continuous connectivity failures. Client cannot connect after multiple retries. Please check your networking configuration - /// - internal static string TransportGenerated503 - { - get - { - return ResourceManager.GetString("TransportGenerated503", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The transport protocol negotiation timed out. See the inner exception for details.. - /// - internal static string TransportNegotiationTimeoutTransportError - { - get - { - return ResourceManager.GetString("TransportNegotiationTimeoutTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The TCP channel timed out on waiting to open. - /// - internal static string ChannelWaitingToOpenTimeoutException - { - get - { - return ResourceManager.GetString("ChannelWaitingToOpenTimeoutException", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot deserialize PartitionKey value '{0}'. - /// - internal static string UnableToDeserializePartitionKeyValue - { - get - { - return ResourceManager.GetString("UnableToDeserializePartitionKeyValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to find free connection. - /// - internal static string UnableToFindFreeConnection - { - get - { - return ResourceManager.GetString("UnableToFindFreeConnection", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unable to authenticate the request. The request requires valid user authentication.. - /// - internal static string Unauthorized - { - get - { - return ResourceManager.GetString("Unauthorized", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unauthorized Offer Replace Request.. - /// - internal static string UnauthorizedOfferReplaceRequest - { - get - { - return ResourceManager.GetString("UnauthorizedOfferReplaceRequest", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unauthorized Auto-Scale Request.. - /// - internal static string UnauthorizedRequestForAutoScale - { - get - { - return ResourceManager.GetString("UnauthorizedRequestForAutoScale", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Operation not permitted as consistency level is set to {0}. Expected {1}.. - /// - internal static string UnexpectedConsistencyLevel - { - get - { - return ResourceManager.GetString("UnexpectedConsistencyLevel", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unexpected JsonSerializationFormat: {0}. - /// - internal static string UnexpectedJsonSerializationFormat - { - get - { - return ResourceManager.GetString("UnexpectedJsonSerializationFormat", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Failed to register JsonTokenType: {0}. - /// - internal static string UnexpectedJsonTokenType - { - get - { - return ResourceManager.GetString("UnexpectedJsonTokenType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unexpected offer version {0} from store.. - /// - internal static string UnexpectedOfferVersion - { - get - { - return ResourceManager.GetString("UnexpectedOfferVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unexpected operation type {0} for routing requests for multiple partitions.. - /// - internal static string UnexpectedOperationTypeForRoutingRequest - { - get - { - return ResourceManager.GetString("UnexpectedOperationTypeForRoutingRequest", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unexpected operator {0} .. - /// - internal static string UnexpectedOperator - { - get - { - return ResourceManager.GetString("UnexpectedOperator", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKeyRangeId is not expected.. - /// - internal static string UnexpectedPartitionKeyRangeId - { - get - { - return ResourceManager.GetString("UnexpectedPartitionKeyRangeId", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Provided Resource Kind {0} to ReEncrypt is not expected.. - /// - internal static string UnExpectedResourceKindToReEncrypt - { - get - { - return ResourceManager.GetString("UnExpectedResourceKindToReEncrypt", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to ResourceType {0} is unexpected.. - /// - internal static string UnexpectedResourceType - { - get - { - return ResourceManager.GetString("UnexpectedResourceType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource kind {0} is unknown. - /// - internal static string UnknownResourceKind - { - get - { - return ResourceManager.GetString("UnknownResourceKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource type {0} is unknown. - /// - internal static string UnknownResourceType - { - get - { - return ResourceManager.GetString("UnknownResourceType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to An unknown client transport error has occurred.. - /// - internal static string UnknownTransportError - { - get - { - return ResourceManager.GetString("UnknownTransportError", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Distict query requires a matching order by in order to return a continuation token. - ///If you would like to serve this query through continuation tokens, then please rewrite the query in the form 'SELECT DISTINCT VALUE c.blah FROM c ORDER BY c.blah' and please make sure that there is a range index on 'c.blah'.. - /// - internal static string UnorderedDistinctQueryContinuationToken - { - get - { - return ResourceManager.GetString("UnorderedDistinctQueryContinuationToken", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested region '{0}' does not support AZ provisioning yet. Please try other regions or disable zone redundancy for this region.. - /// - internal static string UnsupportedAzRegion - { - get - { - return ResourceManager.GetString("UnsupportedAzRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to "{0} capability is not allowed with kind={1}". - /// - internal static string UnsupportedCapabilityForKind - { - get - { - return ResourceManager.GetString("UnsupportedCapabilityForKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Update of "{0} capability is not allowed. - /// - internal static string UnsupportedCapabilityUpdate - { - get - { - return ResourceManager.GetString("UnsupportedCapabilityUpdate", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to "{0} capability is not compatible with mongo ServerVersion={1} accounts.". - /// - internal static string UnsupportedCapabilityForServerVersion - { - get - { - return ResourceManager.GetString("UnsupportedCapabilityForServerVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot execute cross partition order-by queries on mix types. Consider using IS_STRING/IS_NUMBER to get around this exception. Expect type: {0}. Actual type: {1}. Item value: {2}.. - /// - internal static string UnsupportedCrossPartitionOrderByQueryOnMixedTypes - { - get - { - return ResourceManager.GetString("UnsupportedCrossPartitionOrderByQueryOnMixedTypes", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The provided cross partition query can not be directly served by the gateway. This is a first chance (internal) exception that all newer clients will know how to handle gracefully. This exception is traced, but unless you see it bubble up as an exception (which only happens on older SDK clients), then you can safely ignore this message.. - /// - internal static string UnsupportedCrossPartitionQuery - { - get - { - return ResourceManager.GetString("UnsupportedCrossPartitionQuery", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cross partition query with aggregate functions is not supported.. - /// - internal static string UnsupportedCrossPartitionQueryWithAggregate - { - get - { - return ResourceManager.GetString("UnsupportedCrossPartitionQueryWithAggregate", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported entity type {0}. - /// - internal static string UnsupportedEntityType - { - get - { - return ResourceManager.GetString("UnsupportedEntityType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Indexing Hints are not supported in this deployment. . - /// - internal static string UnsupportedHints - { - get - { - return ResourceManager.GetString("UnsupportedHints", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Key type {0} is unsupported. - /// - internal static string UnsupportedKeyType - { - get - { - return ResourceManager.GetString("UnsupportedKeyType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The operation is only supported for Serverless accounts, per-partition throughput cannot be updated directly for provisioned accounts. - /// - internal static string UnsupportedOfferOperationForProvisionedThroughput - { - get - { - return ResourceManager.GetString("UnsupportedOfferOperationForProvisionedThroughput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please specify a value between {0} and {1} inclusive in increments of {2}. Please contact https://azure.microsoft.com/support to request limit increases beyond {1} RU/s.. - /// - internal static string UnSupportedOfferThroughput - { - get - { - return ResourceManager.GetString("UnSupportedOfferThroughput", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please specify a value between {0} and {1}, or between {2} and {3} inclusive in increments of {4}. Please contact https://azure.microsoft.com/support to request limit increases beyond {3} RU/s.. - /// - internal static string UnSupportedOfferThroughputWithTwoRanges - { - get - { - return ResourceManager.GetString("UnSupportedOfferThroughputWithTwoRanges", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Offer type is not supported with Offer version 'V2' and above.. - /// - internal static string UnsupportedOfferTypeWithV2Offer - { - get - { - return ResourceManager.GetString("UnsupportedOfferTypeWithV2Offer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The supplied offer version {0} is not supported. Please specify either a blank version, 'V1' or 'V2'.. - /// - internal static string UnsupportedOfferVersion - { - get - { - return ResourceManager.GetString("UnsupportedOfferVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported PartitionKey value component '{0}'. Numeric, string, bool, null, Undefined are the only supported types.. - /// - internal static string UnsupportedPartitionKeyComponentValue - { - get - { - return ResourceManager.GetString("UnsupportedPartitionKeyComponentValue", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Program requires to run in 64 bit for elastic query feature to work. Please switch your program to 64 bit or use Gateway connectivity mode.. - /// - internal static string UnsupportedProgram - { - get - { - return ResourceManager.GetString("UnsupportedProgram", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Value '{0}' specified for protocol is unsupported.. - /// - internal static string UnsupportedProtocol - { - get - { - return ResourceManager.GetString("UnsupportedProtocol", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Query that expects full results from aggregate functions is not supported.. - /// - internal static string UnsupportedQueryWithFullResultAggregate - { - get - { - return ResourceManager.GetString("UnsupportedQueryWithFullResultAggregate", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested region '{0}' is not supported.. - /// - internal static string UnsupportedRegion - { - get - { - return ResourceManager.GetString("UnsupportedRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested region '{0}' is not supported for '{1}' cluster creation.. - /// - internal static string UnsupportedClusterRegion - { - get - { - return ResourceManager.GetString("UnsupportedClusterRegion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The requested rollback kind '{0}' is not supported.. - /// - internal static string UnsupportedRollbackKind - { - get - { - return ResourceManager.GetString("UnsupportedRollbackKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Changing Root Indexing Policy is not supported in this deployment.. - /// - internal static string UnsupportedRootPolicyChange - { - get - { - return ResourceManager.GetString("UnsupportedRootPolicyChange", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Federation system key kind {0} is invalid. - /// - internal static string UnsupportedSystemKeyKind - { - get - { - return ResourceManager.GetString("UnsupportedSystemKeyKind", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Unsupported token type {0}. - /// - internal static string UnsupportedTokenType - { - get - { - return ResourceManager.GetString("UnsupportedTokenType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The Offer Version 'V1' is not supported since the associated collection is already a partitioned collection. Please use offer version 'V2'.. - /// - internal static string UnsupportedV1OfferVersion - { - get - { - return ResourceManager.GetString("UnsupportedV1OfferVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to AAD tokens are not supported by the Dedicated Gateway endpoint. - /// - internal static string UnsupportedAadAccessControlType - { - get - { - return ResourceManager.GetString("UnsupportedAadAccessControlType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Resource tokens are not supported by the Dedicated Gateway endpoint. - /// - internal static string UnsupportedAccessControlType - { - get - { - return ResourceManager.GetString("UnsupportedAccessControlType", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Upserts for scripts in collections with multiple partitions are not supported.. - /// - internal static string UpsertsForScriptsWithMultiplePartitionsAreNotSupported - { - get - { - return ResourceManager.GetString("UpsertsForScriptsWithMultiplePartitionsAreNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Web socket requests are not supported. - /// - internal static string WebSocketRequestsNotSupported - { - get - { - return ResourceManager.GetString("WebSocketRequestsNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot offline write region when automatic failover is not enabled. - /// - internal static string WriteRegionAutomaticFailoverNotEnabled - { - get - { - return ResourceManager.GetString("WriteRegionAutomaticFailoverNotEnabled", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot perform failover as it is disabled for the account. - /// - internal static string FailoverDisabled - { - get - { - return ResourceManager.GetString("FailoverDisabled", resourceCulture); - } - } - - - /// - /// Looks up a localized string similar to Cannot add additional regions, since database account provision failed.. - /// - internal static string WriteRegionDoesNotExist - { - get - { - return ResourceManager.GetString("WriteRegionDoesNotExist", resourceCulture); - } - } - - - /// - /// Looks up a localized string similar to Zone Redundant Accounts are not supported in {0} Location yet. Please try other locations.. - /// - internal static string ZoneRedundantAccountsNotSupportedInLocation - { - get - { - return ResourceManager.GetString("ZoneRedundantAccountsNotSupportedInLocation", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Connection is too busy. Please retry after sometime or open more connections. - /// - internal static string ConnectionIsBusy - { - get - { - return ResourceManager.GetString("ConnectionIsBusy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Partition key path {0} is invalid for Gremlin API. The path cannot be '/id', '/label' or a nested path such as '/key/path'.. - /// - internal static string InvalidGremlinPartitionKey - { - get - { - return ResourceManager.GetString("InvalidGremlinPartitionKey", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Please provide non-negative value for UpdateMaxthroughputEverProvisioned.. - /// - internal static string InvalidUpdateMaxthroughputEverProvisioned - { - get - { - return ResourceManager.GetString("InvalidUpdateMaxthroughputEverProvisioned", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to "Operation '{0}' on resource '{1}' is not allowed through Azure Cosmos DB endpoint. Please switch on such operations for your account, or perform this operation through Azure Resource Manager, Azure Portal, Azure CLI or Azure Powershell". - /// - internal static string DataPlaneOperationNotAllowed - { - get - { - return ResourceManager.GetString("DataPlaneOperationNotAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Collection is not yet available for read. Please retry in some time.. - /// - internal static string CollectionCreateInProgress - { - get - { - return ResourceManager.GetString("CollectionCreateInProgress", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Free tier has already been applied to another Azure Cosmos DB account in this subscription. To apply free tier to this account, you can select another subscription for this account or delete the existing free tier account. You can have up to one free tier account per subscription.. - /// - internal static string FreeTierAppliedBefore - { - get - { - return ResourceManager.GetString("FreeTierAppliedBefore", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Free tier is not supported for Internal subscriptions.. - /// - internal static string FreeTierNotSupportedForInternalSubscription - { - get - { - return ResourceManager.GetString("FreeTierNotSupportedForInternalSubscription", resourceCulture); - } - } - - /// Looks up a localized string similar to Could not resolve DataTransfer state store account for region [{0}].. - /// - internal static string DataTransferStateStoreNotResolved - { - get - { - return ResourceManager.GetString("DataTransferStateStoreNotResolved", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot update FreeTier property for existing account.. - /// - internal static string FreeTierUpdateNotSupported - { - get - { - return ResourceManager.GetString("FreeTierUpdateNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Subpartitioning is only supported for atmost 3 partition paths . - /// - internal static string InvalidSubPartitionKeyLength - { - get - { - return ResourceManager.GetString("InvalidSubPartitionKeyLength", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Subpartitioning is only supported for Hash V2. . - /// - internal static string InvalidSubPartitionKeyVersion - { - get - { - return ResourceManager.GetString("InvalidSubPartitionKeyVersion", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Missing '_id' index while creating a MongoDB api collection. - /// - internal static string UnderscoreIdIndexRequiredForMongo - { - get - { - return ResourceManager.GetString("UnderscoreIdIndexRequiredForMongo", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Partition key path {0} is invalid for MongoDB API. - /// - internal static string InvalidMongoPartitionKey - { - get - { - return ResourceManager.GetString("InvalidMongoPartitionKey", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The create request is not allowed since it does not specify the schema for container '{0}'. - /// - internal static string MissingSchemaPolicyOnContainer - { - get - { - return ResourceManager.GetString("MissingSchemaPolicyOnContainer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The container replace request is not allowed since it removes the schema policy from the container {0}. - /// - internal static string CannotRemoveSchemaPolicyFromContainer - { - get - { - return ResourceManager.GetString("CannotRemoveSchemaPolicyFromContainer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The container replace request is not allowed since it removes the Cassandra conflict resolution policy from the container {0}. - /// - internal static string CannotReplaceCassandraConflictPolicyFromContainer - { - get - { - return ResourceManager.GetString("CannotReplaceCassandraConflictPolicyFromContainer", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The container create request is not allowed since it does not contain the Cassandra conflict resolution policy specified for the container {0}. - /// - internal static string CannotCreateContainerWithoutCassandraConflictPolicy - { - get - { - return ResourceManager.GetString("CannotCreateContainerWithoutCassandraConflictPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid type system '{0}' specified for container {1}. - /// - internal static string InvalidTypeSystemPolicy - { - get - { - return ResourceManager.GetString("InvalidTypeSystemPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Type system must be specified for the container {0}. - /// - internal static string MissingTypeSystemPolicy - { - get - { - return ResourceManager.GetString("MissingTypeSystemPolicy", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Auto upgrade policy is not supported for MongDB resources.. - /// - internal static string MongoClientAutoUpgradeNotSupported - { - get - { - return ResourceManager.GetString("MongoClientAutoUpgradeNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Updating offer to autoscale throughput is not allowed. Please invoke migration API to migrate this offer.. - /// - internal static string UpdateToAutoscaleThroughputNotAllowed - { - get - { - return ResourceManager.GetString("UpdateToAutoscaleThroughputNotAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Updating offer to manually provisioned throughput is not allowed. Please invoke migration API to migrate this offer.. - /// - internal static string UpdateToManualThroughputNotAllowed - { - get - { - return ResourceManager.GetString("UpdateToManualThroughputNotAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to System database account {0} delete is not supported through this endpoint. - /// - internal static string SystemDatabaseAccountDeleteNotSupported - { - get - { - return ResourceManager.GetString("SystemDatabaseAccountDeleteNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Only system database account delete is supported through this endpoint. Supplied account {0}. - /// - internal static string InvalidSystemDatabaseAccountDelete - { - get - { - return ResourceManager.GetString("InvalidSystemDatabaseAccountDelete", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Invalid store type specified {0}. - /// - internal static string InvalidStoreTypeSpecified - { - get - { - return ResourceManager.GetString("InvalidStoreTypeSpecified", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Revoke/Grant is not allowed as the Account status is: {0}. - /// - internal static string RevokeRegrantNotAllowed - { - get - { - return ResourceManager.GetString("RevokeRegrantNotAllowed", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to The potential total throughput of this operation exceeds the total throughput limit set for this account. Aborting request. - /// - internal static string InvalidTotalThroughputLimitUpdate - { - get - { - return ResourceManager.GetString("InvalidTotalThroughputLimitUpdate", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to PartitionKey has fewer components than defined the collection resource.. - /// - internal static string UnsupportedPartitionDefinitionKindForPartialKeyOperations - { - get - { - return ResourceManager.GetString("UnsupportedPartitionDefinitionKindForPartialKeyOperations", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There cannot be duplicate physical partition ids in x-ms-cosmos-target-partition-throughput-info header.. - /// - internal static string DuplicatePhysicalPartitionIdInTargetPartitionThroughputInfo - { - get - { - return ResourceManager.GetString("DuplicatePhysicalPartitionIdInTargetPartitionThroughputInfo", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There cannot be duplicate physical partition ids in x-ms-cosmos-source-partition-throughput-info header.. - /// - internal static string DuplicatePhysicalPartitionIdInSourcePartitionThroughputInfo - { - get - { - return ResourceManager.GetString("DuplicatePhysicalPartitionIdInSourcePartitionThroughputInfo", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to There cannot be a common physical partition id both in x-ms-cosmos-target-partition-throughput-info and x-ms-cosmos-source-partition-throughput-info header. Encountered {0}. - /// - internal static string PhysicalPartitionIdinTargetAndSourcePartitionThroughputInfo - { - get - { - return ResourceManager.GetString("PhysicalPartitionIdinTargetAndSourcePartitionThroughputInfo", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to One of the source or target physical partition id doesn't exist.. - /// - internal static string PhysicalPartitionIdinTargetOrSourceDoesNotExist - { - get - { - return ResourceManager.GetString("PhysicalPartitionIdinTargetOrSourceDoesNotExist", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Collection name '{0}' is invalid for MongoDB API.. - /// - internal static string InvalidMongoCollectionName - { - get - { - return ResourceManager.GetString("InvalidMongoCollectionName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Database name '{0}' is invalid for MongoDB API.. - /// - internal static string InvalidMongoDatabaseName - { - get - { - return ResourceManager.GetString("InvalidMongoDatabaseName", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). - /// - internal static string KeyVaultAuthenticationFailureRevokeMessage - { - get - { - return ResourceManager.GetString("KeyVaultAuthenticationFailureRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). - /// - internal static string KeyVaultWrapUnwrapFailureRevokeMessage - { - get - { - return ResourceManager.GetString("KeyVaultWrapUnwrapFailureRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to the correspondent key is not found on the specified Key Vault. - /// - internal static string KeyVaultKeyNotFoundRevokeMessage - { - get - { - return ResourceManager.GetString("KeyVaultKeyNotFoundRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the correspondent Azure Key Vault was not found. - /// - internal static string KeyVaultNotFoundRevokeMessage - { - get - { - return ResourceManager.GetString("KeyVaultNotFoundRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). - /// - internal static string KeyVaultDNSNotResolvedRevokeMessage - { - get - { - return ResourceManager.GetString("KeyVaultDNSNotResolvedRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). - /// - internal static string AadClientCredentialsGrantFailureRevokeMessage - { - get - { - return ResourceManager.GetString("AadClientCredentialsGrantFailureRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). - /// - internal static string UndefinedDefaultIdentityRevokeMessage - { - get - { - return ResourceManager.GetString("UndefinedDefaultIdentityRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). - /// - internal static string InvalidKeyVaultKeyURIRevokeMessage - { - get - { - return ResourceManager.GetString("InvalidKeyVaultKeyURIRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). - /// - internal static string NspOutboundDeniedRevokeMessage - { - get - { - return ResourceManager.GetString("NspOutboundDeniedRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide - /// - internal static string UnknownSubstatusCodeRevokeMessage - { - get - { - return ResourceManager.GetString("UnknownSubstatusCodeRevokeMessage", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Your account has access to the customer managed key. - /// - internal static string CmkAccountIsNotRevoked - { - get - { - return ResourceManager.GetString("CmkAccountIsNotRevoked", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Cannot set EnableDataMaskingPolicy on an account with Log Store features. - /// - internal static string EnableDataMaskingPolicyAndEnableLogStoreNotSupported - { - get - { - return ResourceManager.GetString("EnableDataMaskingPolicyAndEnableLogStoreNotSupported", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to DataMaskingPolicy is not supported on this account type. - /// - internal static string DataMaskingPolicyNotSupported - { - get - { - return ResourceManager.GetString("DataMaskingPolicyNotSupported", resourceCulture); - } - } - } +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class RMResources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal RMResources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if (object.ReferenceEquals(resourceMan, null)) + { +#if COSMOSCLIENT + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Documents.RMResources", typeof(RMResources).Assembly); +#else + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Documents.RMResources", typeof(RMResources).GetAssembly()); +#endif + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to {0} api is not supported for this database account. + /// + internal static string ApiTypeForbidden + { + get + { + return ResourceManager.GetString("ApiTypeForbidden", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} should have {1} argument.. + /// + internal static string ArgumentRequired + { + get + { + return ResourceManager.GetString("ArgumentRequired", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Auto-Scale Setting Change With User Auth Is Disallowed.. + /// + internal static string AutoScaleSettingChangeWithUserAuthIsDisallowed + { + get + { + return ResourceManager.GetString("AutoScaleSettingChangeWithUserAuthIsDisallowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given request [{0} {1}] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac.. + /// + internal static string AadAuthActionNotSupported + { + get + { + return ResourceManager.GetString("AadAuthActionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to validate AAD identity since the authenticator is unavailable.. + /// + internal static string AadAuthenticatorNotAvailable + { + get + { + return ResourceManager.GetString("AadAuthenticatorNotAvailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request for Read DatabaseAccount is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on any scope. Learn more: https://aka.ms/cosmos-native-rbac.. + /// + internal static string AadAuthDatabaseAccountRequestBlocked + { + get + { + return ResourceManager.GetString("AadAuthDatabaseAccountRequestBlocked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This could be because the user's group memberships were not present in the AAD token.. + /// + internal static string AadAuthGroupExpansionNeeded + { + get + { + return ResourceManager.GetString("AadAuthGroupExpansionNeeded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on resource [{2}]. Learn more: https://aka.ms/cosmos-native-rbac.. + /// + internal static string AadAuthRequestBlocked + { + get + { + return ResourceManager.GetString("AadAuthRequestBlocked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to validate AAD identity since the authorizer is unavailable.. + /// + internal static string AadAuthorizerNotAvailable + { + get + { + return ResourceManager.GetString("AadAuthorizerNotAvailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to update the AAD Public Keys with value {0}. Exception: {1}.. + /// + internal static string AadAuthPublicKeysFailedToUpdate + { + get + { + return ResourceManager.GetString("AadAuthPublicKeysFailedToUpdate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SAS Token Authentication is disabled for this account. Please contact Azure Support [https://azure.microsoft.com/support] to enable it.. + /// + internal static string SasTokenAuthDisabled + { + get + { + return ResourceManager.GetString("SasTokenAuthDisabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Local Authorization is disabled. Use an AAD token to authorize all requests.. + /// + internal static string AadLocalAuthDisabled + { + get + { + return ResourceManager.GetString("AadLocalAuthDisabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At this time, only write operations made from the MongoDB SDKs are supported. Modifications to MongoDB collections using other SDKs is temporarily blocked.. + /// + internal static string BadClientMongo + { + get + { + return ResourceManager.GetString("BadClientMongo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid response from upstream server or upstream server request failed.. + /// + internal static string BadGateway + { + get + { + return ResourceManager.GetString("BadGateway", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One of the input values is invalid.. + /// + internal static string BadRequest + { + get + { + return ResourceManager.GetString("BadRequest", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request url is invalid.. + /// + internal static string BadUrl + { + get + { + return ResourceManager.GetString("BadUrl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot offline a write region that has zero read regions configured. There needs to be atleast one read region to failover to.. + /// + internal static string CannotOfflineWriteRegionWithNoReadRegions + { + get + { + return ResourceManager.GetString("CannotOfflineWriteRegionWithNoReadRegions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot specify partition key range or partition key for resource that is not partitioned.. + /// + internal static string CannotSpecifyPKRangeForNonPartitionedResource + { + get + { + return ResourceManager.GetString("CannotSpecifyPKRangeForNonPartitionedResource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to StartTime cannot have DateTimeKind.Unspecified.. + /// + internal static string ChangeFeedOptionsStartTimeWithUnspecifiedDateTimeKind + { + get + { + return ResourceManager.GetString("ChangeFeedOptionsStartTimeWithUnspecifiedDateTimeKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Channel is closed. + /// + internal static string ChannelClosed + { + get + { + return ResourceManager.GetString("ChannelClosed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The channel multiplexer has shut down.. + /// + internal static string ChannelMultiplexerClosedTransportError + { + get + { + return ResourceManager.GetString("ChannelMultiplexerClosedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The transport client failed to open a connection. See the inner exception for details.. + /// + internal static string ChannelOpenFailedTransportError + { + get + { + return ResourceManager.GetString("ChannelOpenFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The transport client timed out when opening a connection. See the inner exception for details.. + /// + internal static string ChannelOpenTimeoutTransportError + { + get + { + return ResourceManager.GetString("ChannelOpenTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There is high CPU detected on your client machine. Requests are more likely to timeout when CPU exceeds 90%. + /// + internal static string Client_CPUOverload + { + get + { + return ResourceManager.GetString("Client_CPUOverload", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Thread starvation or thread-pool blocking detected. + /// + internal static string Client_ThreadStarvation + { + get + { + return ResourceManager.GetString("Client_ThreadStarvation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU was overloaded during the attempted request.. + /// + internal static string ClientCpuOverload + { + get + { + return ResourceManager.GetString("ClientCpuOverload", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU has thread starvation.. + /// + internal static string ClientCpuThreadStarvation + { + get + { + return ResourceManager.GetString("ClientCpuThreadStarvation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. Please check for client resource starvation issues and verify connectivity between client and server.. + /// + internal static string ClientUnavailable + { + get + { + return ResourceManager.GetString("ClientUnavailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Collection create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection.. + /// + internal static string CollectionCreateTopologyConflict + { + get + { + return ResourceManager.GetString("CollectionCreateTopologyConflict", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Throughput of this collection cannot be more than {0}, as was provisioned during collection creation time.. + /// + internal static string CollectionThroughputCannotBeMoreThan + { + get + { + return ResourceManager.GetString("CollectionThroughputCannotBeMoreThan", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to connect to the remote endpoint.. + /// + internal static string ConnectFailedTransportError + { + get + { + return ResourceManager.GetString("ConnectFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection failed.. + /// + internal static string ConnectionBrokenTransportError + { + get + { + return ResourceManager.GetString("ConnectionBrokenTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The connection attempt timed out.. + /// + internal static string ConnectTimeoutTransportError + { + get + { + return ResourceManager.GetString("ConnectTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Correlation ID not found in response. + /// + internal static string CorrelationIDNotFoundInResponse + { + get + { + return ResourceManager.GetString("CorrelationIDNotFoundInResponse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid CORS rule. At least one allowed origin is required.. + /// + internal static string CorsAllowedOriginsEmptyList + { + get + { + return ResourceManager.GetString("CorsAllowedOriginsEmptyList", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to InvalidCORS rule. The origin '{0}' is an invalid origin. A valid rigin should not include a uri path.. + /// + internal static string CorsAllowedOriginsInvalidPath + { + get + { + return ResourceManager.GetString("CorsAllowedOriginsInvalidPath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid CORS rule. The origin '{0}' is not a well formed origin... + /// + internal static string CorsAllowedOriginsMalformedUri + { + get + { + return ResourceManager.GetString("CorsAllowedOriginsMalformedUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid CORS rule. Wildcards are not supported.. + /// + internal static string CorsAllowedOriginsWildcardsNotSupported + { + get + { + return ResourceManager.GetString("CorsAllowedOriginsWildcardsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid CORS rules. Only one rule is supported.. + /// + internal static string CorsTooManyRules + { + get + { + return ResourceManager.GetString("CorsTooManyRules", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value specified in the "{0}" header is incompatible with value specified in the "{1}" header of the request.. + /// + internal static string CrossPartitionContinuationAndIndex + { + get + { + return ResourceManager.GetString("CrossPartitionContinuationAndIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross partition query is required but disabled. Please set x-ms-documentdb-query-enablecrosspartition to true, specify x-ms-documentdb-partitionkey, or revise your query to avoid this exception.. + /// + internal static string CrossPartitionQueryDisabled + { + get + { + return ResourceManager.GetString("CrossPartitionQueryDisabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross-tenant CMK is not supported with First Party identities as Default identities. Please use an User Assigned identity instead.. + /// + internal static string CrossTenantCMKNotSupportedWithFirstPartyIdentity + { + get + { + return ResourceManager.GetString("CrossTenantCMKNotSupportedWithFirstPartyIdentity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross-tenant CMK is not supported with System Assigned identities as Default identities. Please use an User Assigned Identity instead.. + /// + internal static string CrossTenantCMKNotSupportedWithSystemAssignedIdentity + { + get + { + return ResourceManager.GetString("CrossTenantCMKNotSupportedWithSystemAssignedIdentity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database Account {0} does not exist. + /// + internal static string DatabaseAccountNotFound + { + get + { + return ResourceManager.GetString("DatabaseAccountNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection... + /// + internal static string DatabaseCreateTopologyConflict + { + get + { + return ResourceManager.GetString("DatabaseCreateTopologyConflict", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expecting DateTime value.. + /// + internal static string DateTimeConverterInvalidDateTime + { + get + { + return ResourceManager.GetString("DateTimeConverterInvalidDateTime", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expecting reader to read Integer. + /// + internal static string DateTimeConverterInvalidReaderValue + { + get + { + return ResourceManager.GetString("DateTimeConverterInvalidReaderValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expecting reader value to be compatible with double conversion.. + /// + internal static string DateTimeConveterInvalidReaderDoubleValue + { + get + { + return ResourceManager.GetString("DateTimeConveterInvalidReaderDoubleValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error occurred while deserializing content '{0}'.. + /// + internal static string DeserializationError + { + get + { + return ResourceManager.GetString("DeserializationError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given default identity for {0} is not valid. The format for the default identity is not valid, please use 'FirstPartyIdentity'/'SystemAssignedIdentity'/'UserAssignedIdentity=<UA_resource_id>'. + /// + internal static string DefaultIdentityNotValidFormat + { + get + { + return ResourceManager.GetString("DefaultIdentityNotValidFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to a delegated identity that does not exist in {0}.. + /// + internal static string DefaultIdentityWithoutCorrespondingDelegatedIdentity + { + get + { + return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingDelegatedIdentity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to a system identity that does not exist in {0}.. + /// + internal static string DefaultIdentityWithoutCorrespondingSystemIdentity + { + get + { + return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingSystemIdentity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The given default identity for {0} is not valid. The default identity points to an user identity that does not exist in {0}.. + /// + internal static string DefaultIdentityWithoutCorrespondingUserIdentity + { + get + { + return ResourceManager.GetString("DefaultIdentityWithoutCorrespondingUserIdentity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DNS resolution failed.. + /// + internal static string DnsResolutionFailedTransportError + { + get + { + return ResourceManager.GetString("DnsResolutionFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DNS resolution timed out.. + /// + internal static string DnsResolutionTimeoutTransportError + { + get + { + return ResourceManager.GetString("DnsResolutionTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Document Query Execution Context is done.. + /// + internal static string DocumentQueryExecutionContextIsDone + { + get + { + return ResourceManager.GetString("DocumentQueryExecutionContextIsDone", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service is currently unavailable, please retry after a while. If this problem persists please contact support.. + /// + internal static string DocumentServiceUnavailable + { + get + { + return ResourceManager.GetString("DocumentServiceUnavailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Duplicate correlation id generated. + /// + internal static string DuplicateCorrelationIdGenerated + { + get + { + return ResourceManager.GetString("DuplicateCorrelationIdGenerated", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Empty Virtual Network Resource Guid. + /// + internal static string EmptyVirtualNetworkResourceGuid + { + get + { + return ResourceManager.GetString("EmptyVirtualNetworkResourceGuid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified Virtual Network Rules list is empty. + /// + internal static string EmptyVirtualNetworkRulesSpecified + { + get + { + return ResourceManager.GetString("EmptyVirtualNetworkRulesSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableAnalyticsStorage on an account with EnableServerless. + /// + internal static string EnableAnalyticsStorageAndEnableServerlessNotSupported + { + get + { + return ResourceManager.GetString("EnableAnalyticsStorageAndEnableServerlessNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer throughput policy specified is invalid. + /// + internal static string InvalidThroughputPolicy + { + get + { + return ResourceManager.GetString("InvalidThroughputPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on an account with EnableServerless. + /// + internal static string EnableMultipleWriteLocationsAndEnableServerlessNotSupported + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsAndEnableServerlessNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on an account with EnableTieredStorageV1. + /// + internal static string EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableOnlyColdStorageContainersInAccountV1 on an account with EnableMaterializedViews + /// + internal static string EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported + { + get + { + return ResourceManager.GetString("EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Accounts configured with default consistency level as 'Strong' cannot be enabled for multiple write locations(i.e. EnableMultipleWriteLocations=true). Consider relaxing default consistency level of the account to enable multiple write locations.. + /// + internal static string EnableMultipleWriteLocationsAndStrongConsistencyNotSupported + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsAndStrongConsistencyNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Availability Zone on a multi region account requires multi master to be enabled. Please enable Multi-Master on the database account to proceed.. + /// + internal static string EnableMultipleWriteLocationsBeforeAddingRegion + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsBeforeAddingRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This account already has EnableMultipleWriteLocations flag set to {0}".. + /// + internal static string EnableMultipleWriteLocationsNotModified + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsNotModified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot add regions to an account with EnableServerless. + /// + internal static string EnableMultiRegionAndEnableServerlessNotSupported + { + get + { + return ResourceManager.GetString("EnableMultiRegionAndEnableServerlessNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Restore is not Supported on this account type. + /// + internal static string PitrNotSupported + { + get + { + return ResourceManager.GetString("PitrNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot add regions to this account type. + /// + internal static string EnableMultiRegionNotSupported + { + get + { + return ResourceManager.GetString("EnableMultiRegionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on this account type. + /// + internal static string EnableMultipleWriteLocationsNotSupported + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set DisableKeyBasedMetadataWriteAccess on this account type. + /// + internal static string DisableKeyBasedMetadataWriteAccessNotSupported + { + get + { + return ResourceManager.GetString("DisableKeyBasedMetadataWriteAccessNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MaterializedViews is not supported on this account type. + /// + internal static string MaterializedViewsNotSupported + { + get + { + return ResourceManager.GetString("MaterializedViewsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Full Fidelity Change Feed is not supported on this account type. + /// + internal static string FullFidelityChangeFeedNotSupported + { + get + { + return ResourceManager.GetString("FullFidelityChangeFeedNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to CassandraConnector not supported for this account type. + /// + internal static string CassandraConnectorNotSupported + { + get + { + return ResourceManager.GetString("CassandraConnectorNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Free Tier is not supported on this account type. + /// + internal static string FreeTierNotSupported + { + get + { + return ResourceManager.GetString("FreeTierNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set IpRangeFilter values on this account type. + /// + internal static string IpRangeFilterNotSupported + { + get + { + return ResourceManager.GetString("IpRangeFilterNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Analytical Storage is not supported on this account type. + /// + internal static string AnalyticalStoreNotSupported + { + get + { + return ResourceManager.GetString("AnalyticalStoreNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set VirtualNetworkFilter on this account type. + /// + internal static string VirtualNetworkFilterNotSupported + { + get + { + return ResourceManager.GetString("VirtualNetworkFilterNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Serverless offer is not supported on this account type. + /// + internal static string ServerlessNotSupported + { + get + { + return ResourceManager.GetString("ServerlessNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to retrieve address of endpoint '{0}' from the address '{1}'. + /// + internal static string EndpointNotFound + { + get + { + return ResourceManager.GetString("EndpointNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Entity with the specified id already exists in the system.. + /// + internal static string EntityAlreadyExists + { + get + { + return ResourceManager.GetString("EntityAlreadyExists", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Message: {0}. + /// + internal static string ExceptionMessage + { + get + { + return ResourceManager.GetString("ExceptionMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}, Local IP: {1}. + /// + internal static string ExceptionMessageAddIpAddress + { + get + { + return ResourceManager.GetString("ExceptionMessageAddIpAddress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0}, Request URI: {1}, RequestStats: {2}, SDK: {3}. + /// + internal static string ExceptionMessageAddRequestUri + { + get + { + return ResourceManager.GetString("ExceptionMessageAddRequestUri", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feature {0} is not supported for Multi-region Account. + /// + internal static string FeatureNotSupportedForMultiRegionAccount + { + get + { + return ResourceManager.GetString("FeatureNotSupportedForMultiRegionAccount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Feature {0} is not supported in {1} region. + /// + internal static string FeatureNotSupportedInRegion + { + get + { + return ResourceManager.GetString("FeatureNotSupportedInRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} is not supported for the target subscription. + /// + internal static string FeatureNotSupportedOnSubscription + { + get + { + return ResourceManager.GetString("FeatureNotSupportedOnSubscription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MaterializedViews is not supported on this account type. + /// + internal static string MaterializedViewsNotSupportedOnZoneRedundantAccount + { + get + { + return ResourceManager.GetString("MaterializedViewsNotSupportedOnZoneRedundantAccount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Federation {0} in region {1} is not found. + /// + internal static string FederationEntityNotFound + { + get + { + return ResourceManager.GetString("FederationEntityNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request is blocked by your Cosmos DB account firewall settings.. + /// + internal static string Forbidden + { + get + { + return ResourceManager.GetString("Forbidden", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request originated from IP {0} through public internet. + /// This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden. + /// + internal static string ForbiddenPublicIpv4 + { + get + { + return ResourceManager.GetString("ForbiddenPublicIpv4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request originated from VNET through service endpoint. + /// This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden. + /// + internal static string ForbiddenServiceEndpoint + { + get + { + return ResourceManager.GetString("ForbiddenServiceEndpoint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request received through private endpoint. + /// It is blocked because either your account does not have private endpoint configured, + /// or it is not from the private endpoint that your account is configured with. + /// More info: https://aka.ms/cosmosdb-tsg-forbidden. + /// + internal static string ForbiddenPrivateEndpoint + { + get + { + return ResourceManager.GetString("ForbiddenPrivateEndpoint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Attempt to process the request timed out at remote server.. + /// + internal static string GatewayTimedout + { + get + { + return ResourceManager.GetString("GatewayTimedout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database and Write Location are not matching. + /// + internal static string GlobalAndWriteRegionMisMatch + { + get + { + return ResourceManager.GetString("GlobalAndWriteRegionMisMatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Federation and region are not matching. + /// + internal static string FederationAndRegionMismatch + { + get + { + return ResourceManager.GetString("FederationAndRegionMismatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Global Strong write barrier has not been met for the request.. + /// + internal static string GlobalStrongWriteBarrierNotMet + { + get + { + return ResourceManager.GetString("GlobalStrongWriteBarrierNotMet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested resource is no longer available at the server.. + /// + internal static string Gone + { + get + { + return ResourceManager.GetString("Gone", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to generate id for resourceType = {0}, partitionIndex = {1}, serviceIndex = {2}, partitionCount = {3}.. + /// + internal static string IdGenerationFailed + { + get + { + return ResourceManager.GetString("IdGenerationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Routing map is not complete.. + /// + internal static string IncompleteRoutingMap + { + get + { + return ResourceManager.GetString("IncompleteRoutingMap", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Insufficient permissions provided in the authorization header for the corresponding request. Please retry with another authorization header.. + /// + internal static string InsufficientPermissions + { + get + { + return ResourceManager.GetString("InsufficientPermissions", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to continue without atleast a single token in the resource tokens input collection.. + /// + internal static string InsufficientResourceTokens + { + get + { + return ResourceManager.GetString("InsufficientResourceTokens", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown server error occurred when processing this request.. + /// + internal static string InternalServerError + { + get + { + return ResourceManager.GetString("InternalServerError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid API version. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK.. + /// + internal static string InvalidAPIVersion + { + get + { + return ResourceManager.GetString("InvalidAPIVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid API version for {0}. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK.. + /// + internal static string InvalidAPIVersionForFeature + { + get + { + return ResourceManager.GetString("InvalidAPIVersionForFeature", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AudienceKind is Invalid. + /// + internal static string InvalidAudienceKind + { + get + { + return ResourceManager.GetString("InvalidAudienceKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Audience Resource Type. + /// + internal static string InvalidAudienceResourceType + { + get + { + return ResourceManager.GetString("InvalidAudienceResourceType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Authorization header doesn't confirm to the required format. Please verify and try again.. + /// + internal static string InvalidAuthHeaderFormat + { + get + { + return ResourceManager.GetString("InvalidAuthHeaderFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The backend response was not in the correct format.. + /// + internal static string InvalidBackendResponse + { + get + { + return ResourceManager.GetString("InvalidBackendResponse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "{0} capability cannot be specified with {1} .". + /// + internal static string InvalidCapabilityCombination + { + get + { + return ResourceManager.GetString("InvalidCapabilityCombination", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The resource name presented contains invalid character '{0}'.. + /// + internal static string InvalidCharacterInResourceName + { + get + { + return ResourceManager.GetString("InvalidCharacterInResourceName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid mode '{0}' for setting '{1}'. Mode expected is '{2}'.. + /// + internal static string InvalidConflictResolutionMode + { + get + { + return ResourceManager.GetString("InvalidConflictResolutionMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ConsistencyLevel {0} specified in the request is invalid when service is configured with consistency level {1}. Ensure the request consistency level is not stronger than the service consistency level.. + /// + internal static string InvalidConsistencyLevel + { + get + { + return ResourceManager.GetString("InvalidConsistencyLevel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Continuation Token. + /// + internal static string InvalidContinuationToken + { + get + { + return ResourceManager.GetString("InvalidContinuationToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified document collection is invalid... + /// + internal static string InvalidDatabase + { + get + { + return ResourceManager.GetString("InvalidDatabase", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The input date header is invalid format. Please pass in RFC 1123 style date format.. + /// + internal static string InvalidDateHeader + { + get + { + return ResourceManager.GetString("InvalidDateHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified document collection is invalid.. + /// + internal static string InvalidDocumentCollection + { + get + { + return ResourceManager.GetString("InvalidDocumentCollection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot enable 'enableMultipleWriteLocations' without also enabling 'canEnableMultipleWriteLocations'.. + /// + internal static string InvalidEnableMultipleWriteLocations + { + get + { + return ResourceManager.GetString("InvalidEnableMultipleWriteLocations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid value {0} passed for enum {1}. + /// + internal static string InvalidEnumValue + { + get + { + return ResourceManager.GetString("InvalidEnumValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failover priority value {0} supplied for region {1} is invalid. + /// + internal static string InvalidFailoverPriority + { + get + { + return ResourceManager.GetString("InvalidFailoverPriority", resourceCulture); + } + } + + + /// + /// Looks up a localized string similar to The CapUncapMetadata action '{0}' is not currently supported.. + /// + internal static string InvalidFederationCapUncapMetadataAction + { + get + { + return ResourceManager.GetString("InvalidFederationCapUncapMetadataAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The CapUncapMetadata source '{0}' is invalid.. + /// + internal static string InvalidFederationCapUncapMetadataSource + { + get + { + return ResourceManager.GetString("InvalidFederationCapUncapMetadataSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value '{0}' specified for the header '{1}' is invalid. . + /// + internal static string InvalidHeaderValue + { + get + { + return ResourceManager.GetString("InvalidHeaderValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified value {0} of the index kind is invalid.. + /// + internal static string InvalidIndexKindValue + { + get + { + return ResourceManager.GetString("InvalidIndexKindValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The index spec format is invalid.. + /// + internal static string InvalidIndexSpecFormat + { + get + { + return ResourceManager.GetString("InvalidIndexSpecFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Received invalid index transformation progress values from all the replicas.. + /// + internal static string InvalidIndexTransformationProgressValues + { + get + { + return ResourceManager.GetString("InvalidIndexTransformationProgressValues", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to List of supplied locations is invalid. + /// + internal static string InvalidLocations + { + get + { + return ResourceManager.GetString("InvalidLocations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only one manualPrivateLinkServiceConnection or one privateLinkServiceConnection is supported. + /// + internal static string InvalidPrivateLinkServiceConnections + { + get + { + return ResourceManager.GetString("InvalidPrivateLinkServiceConnections", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only one privateLinkServiceProxy is supported. + /// + internal static string InvalidPrivateLinkServiceProxies + { + get + { + return ResourceManager.GetString("InvalidPrivateLinkServiceProxies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only one groupId is supported. + /// + internal static string InvalidGroupIdCount + { + get + { + return ResourceManager.GetString("InvalidGroupIdCount", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GroupId {0} is not supported. + /// + internal static string InvalidGroupId + { + get + { + return ResourceManager.GetString("InvalidGroupId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MaxStalenessInterval should be greater than or equal to {0} sec and less than or equal to {1} sec. + /// + internal static string InvalidMaxStalenessInterval + { + get + { + return ResourceManager.GetString("InvalidMaxStalenessInterval", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to MaxStalenessPrefix should be greater than or equal to {0} and less than or equal to {1}. + /// + internal static string InvalidMaxStalenessPrefix + { + get + { + return ResourceManager.GetString("InvalidMaxStalenessPrefix", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer throughput specified exceeded supported maximum throughput for Fixed size container. Please enter value less than {0}.. + /// + internal static string InvalidNonPartitionedOfferThroughput + { + get + { + return ResourceManager.GetString("InvalidNonPartitionedOfferThroughput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The container doesn't have enough data populated with partition key information. Please retry the throughput scale operation after inserting data with partition key information. + /// + internal static string InsufficientPartitionedDataForOfferThroughput + { + get + { + return ResourceManager.GetString("InsufficientPartitionedDataForOfferThroughput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer IsAutoScaleEnabled specified is invalid. Please specify a boolean value.. + /// + internal static string InvalidOfferIsAutoScaleEnabled + { + get + { + return ResourceManager.GetString("InvalidOfferIsAutoScaleEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of OfferAutoScaleMode specified is invalid. Please specfy a valid auto scale mode. + /// + internal static string InvalidOfferAutoScaleMode + { + get + { + return ResourceManager.GetString("InvalidOfferAutoScaleMode", resourceCulture); + } + } + + internal static string OfferAutopilotNotSupportedForNonPartitionedCollections + { + get + { + return ResourceManager.GetString("OfferAutopilotNotSupportedForNonPartitionedCollections", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Autopilot is currently not supported on shared throughput database. + /// + internal static string OfferAutopilotNotSupportedOnSharedThroughputDatabase + { + get + { + return ResourceManager.GetString("OfferAutopilotNotSupportedOnSharedThroughputDatabase", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer IsRUPerMinuteThroughputEnabled specified is invalid. Please specify a boolean value.. + /// + internal static string InvalidOfferIsRUPerMinuteThroughputEnabled + { + get + { + return ResourceManager.GetString("InvalidOfferIsRUPerMinuteThroughputEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer BackgroundTaskMaxAllowedThroughputPercent specified is invalid. Please specify a double value.. + /// + internal static string InvalidBackgroundTaskMaxAllowedThroughputPercent + { + get + { + return ResourceManager.GetString("InvalidBackgroundTaskMaxAllowedThroughputPercent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please enter valid positive integer.. + /// + internal static string InvalidOfferThroughput + { + get + { + return ResourceManager.GetString("InvalidOfferThroughput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to OfferType {0} specified in the request is invalid. Please refer to offer documentation and specify a valid offer type.. + /// + internal static string InvalidOfferType + { + get + { + return ResourceManager.GetString("InvalidOfferType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The required field Content is missing in Offer version v2.. + /// + internal static string InvalidOfferV2Input + { + get + { + return ResourceManager.GetString("InvalidOfferV2Input", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offer read/replace is not supported for serverless accounts. + /// + internal static string InvalidOfferCRUDForServerless + { + get + { + return ResourceManager.GetString("InvalidOfferCRUDForServerless", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource {0} is invalid for adding owner resource record. + /// + internal static string InvalidOwnerResourceType + { + get + { + return ResourceManager.GetString("InvalidOwnerResourceType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The input PageSize {0} is invalid. Ensure to pass a valid page size which must be a positive integer or -1 for a dynamic page size.. + /// + internal static string InvalidPageSize + { + get + { + return ResourceManager.GetString("InvalidPageSize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Partition key {0} is invalid.. + /// + internal static string InvalidPartitionKey + { + get + { + return ResourceManager.GetString("InvalidPartitionKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to x-ms-documentdb-partitionkeyrangeid header contains invalid value '{0}'.. + /// + internal static string InvalidPartitionKeyRangeIdHeader + { + get + { + return ResourceManager.GetString("InvalidPartitionKeyRangeIdHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The permission mode provided in the authorization token doesn't provide sufficient permissions.. + /// + internal static string InvalidPermissionMode + { + get + { + return ResourceManager.GetString("InvalidPermissionMode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid policy type found.. + /// + internal static string InvalidPolicyType + { + get + { + return ResourceManager.GetString("InvalidPolicyType", resourceCulture); + } + } + /// + /// Looks up a localized string similar to Command is not supported by backend. + /// + internal static string InvalidProxyCommand + { + get + { + return ResourceManager.GetString("InvalidProxyCommand", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Query '{0}' specified is either invalid or unsupported.. + /// + internal static string InvalidQuery + { + get + { + return ResourceManager.GetString("InvalidQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value '{0}' specified for the query '{1}' is invalid.. + /// + internal static string InvalidQueryValue + { + get + { + return ResourceManager.GetString("InvalidQueryValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Compared session tokens '{0}' and '{1}' has unexpected regions. . + /// + internal static string InvalidRegionsInSessionToken + { + get + { + return ResourceManager.GetString("InvalidRegionsInSessionToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Strong consistency level cannot be specified with async replication. Either change the replication policy 'AsyncReplication' to false or relax the consistency level.. + /// + internal static string InvalidReplicationAndConsistencyCombination + { + get + { + return ResourceManager.GetString("InvalidReplicationAndConsistencyCombination", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to parse the value '{0}' as ResourceId.. + /// + internal static string InvalidResourceID + { + get + { + return ResourceManager.GetString("InvalidResourceID", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value for {0} should be greater than 0. + /// + internal static string InvalidResourceIdBatchSize + { + get + { + return ResourceManager.GetString("InvalidResourceIdBatchSize", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource kind {0} is invalid. + /// + internal static string InvalidResourceKind + { + get + { + return ResourceManager.GetString("InvalidResourceKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Requested ResourceType {0} passed as generic argument should be same as the one specified by ResourceType member {1}. + /// + internal static string InvalidResourceType + { + get + { + return ResourceManager.GetString("InvalidResourceType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource Url path {0} is invalid.. + /// + internal static string InvalidResourceUrlPath + { + get + { + return ResourceManager.GetString("InvalidResourceUrlPath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value '{0}' specified for query '{1}' is invalid.. + /// + internal static string InvalidResourceUrlQuery + { + get + { + return ResourceManager.GetString("InvalidResourceUrlQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The input continuation token size limit {0} is invalid. Please pass in a valid continuation token size limit which must be a positive integer.. + /// + internal static string InvalidResponseContinuationTokenLimit + { + get + { + return ResourceManager.GetString("InvalidResponseContinuationTokenLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Script request has invalid body.. + /// + internal static string InvalidScriptResource + { + get + { + return ResourceManager.GetString("InvalidScriptResource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The session token provided '{0}' is invalid.. + /// + internal static string InvalidSessionToken + { + get + { + return ResourceManager.GetString("InvalidSessionToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The resource name can't end with space.. + /// + internal static string InvalidSpaceEndingInResourceName + { + get + { + return ResourceManager.GetString("InvalidSpaceEndingInResourceName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Staleness Policy specified is invalid. Ensure both MaxPrefix and MaxStalenessIntervalInSeconds are both 0 or both not zero.. + /// + internal static string InvalidStalenessPolicy + { + get + { + return ResourceManager.GetString("InvalidStalenessPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Storage Service index {0} for media account {1} must be within byte range (inclusive).. + /// + internal static string InvalidStorageServiceMediaIndex + { + get + { + return ResourceManager.GetString("InvalidStorageServiceMediaIndex", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot disable 'canEnableMultipleWriteLocations' flag once it has been enabled.. + /// + internal static string InvalidSwitchOffCanEnableMultipleWriteLocations + { + get + { + return ResourceManager.GetString("InvalidSwitchOffCanEnableMultipleWriteLocations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot enable 'canEnableMultipleWriteLocations' flag once account has been created with it disabled.. + /// + internal static string InvalidSwitchOnCanEnableMultipleWriteLocations + { + get + { + return ResourceManager.GetString("InvalidSwitchOnCanEnableMultipleWriteLocations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Target for the request is invalid. + /// + internal static string InvalidTarget + { + get + { + return ResourceManager.GetString("InvalidTarget", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The authorization token is not valid at the current time. Please create another token and retry (token start time: {0}, token expiry time: {1}, current server time: {2}).. + /// + internal static string InvalidTokenTimeRange + { + get + { + return ResourceManager.GetString("InvalidTokenTimeRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request url is invalid.. + /// + internal static string InvalidUrl + { + get + { + return ResourceManager.GetString("InvalidUrl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request path {0} is invalid.. + /// + internal static string InvalidRequestUrl + { + get + { + return ResourceManager.GetString("InvalidRequestUrl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to System key can only access replica root. + /// + internal static string InvalidUseSystemKey + { + get + { + return ResourceManager.GetString("InvalidUseSystemKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid version format for {0}. Input Version {1}. + /// + internal static string InvalidVersionFormat + { + get + { + return ResourceManager.GetString("InvalidVersionFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to IpAddress {0} is blocked by Policy. + /// + internal static string IpAddressBlockedByPolicy + { + get + { + return ResourceManager.GetString("IpAddressBlockedByPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not allowed to force delete federation in this environment.. + /// + internal static string IsForceDeleteFederationAllowed + { + get + { + return ResourceManager.GetString("IsForceDeleteFederationAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tried to write a JSON end array (“]“) symbol without a matching array start symbol (“[“).. + /// + internal static string JsonArrayNotStarted + { + get + { + return ResourceManager.GetString("JsonArrayNotStarted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid escape character in JSON.. + /// + internal static string JsonInvalidEscapedCharacter + { + get + { + return ResourceManager.GetString("JsonInvalidEscapedCharacter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid number in JSON.. + /// + internal static string JsonInvalidNumber + { + get + { + return ResourceManager.GetString("JsonInvalidNumber", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid parameter in JSON.. + /// + internal static string JsonInvalidParameter + { + get + { + return ResourceManager.GetString("JsonInvalidParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid string character in JSON.. + /// + internal static string JsonInvalidStringCharacter + { + get + { + return ResourceManager.GetString("JsonInvalidStringCharacter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered an element that is not a valid JSON value (false / null / true / object / array / number / string). + /// + internal static string JsonInvalidToken + { + get + { + return ResourceManager.GetString("JsonInvalidToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Unicode escape sequence in JSON.. + /// + internal static string JsonInvalidUnicodeEscape + { + get + { + return ResourceManager.GetString("JsonInvalidUnicodeEscape", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exceeded the maximum level of nesting for JSON.. + /// + internal static string JsonMaxNestingExceeded + { + get + { + return ResourceManager.GetString("JsonMaxNestingExceeded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing a closing quote (") in JSON.. + /// + internal static string JsonMissingClosingQuote + { + get + { + return ResourceManager.GetString("JsonMissingClosingQuote", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing an end array ("]") symbol in JSON.. + /// + internal static string JsonMissingEndArray + { + get + { + return ResourceManager.GetString("JsonMissingEndArray", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing an end object ("}") symbol in JSON.. + /// + internal static string JsonMissingEndObject + { + get + { + return ResourceManager.GetString("JsonMissingEndObject", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing a name separator (":") in JSON.. + /// + internal static string JsonMissingNameSeparator + { + get + { + return ResourceManager.GetString("JsonMissingNameSeparator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing a JSON property.. + /// + internal static string JsonMissingProperty + { + get + { + return ResourceManager.GetString("JsonMissingProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a JSON property name without a corresponding property value. + /// + internal static string JsonNotComplete + { + get + { + return ResourceManager.GetString("JsonNotComplete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a value that was not a JSON field name.. + /// + internal static string JsonNotFieldnameToken + { + get + { + return ResourceManager.GetString("JsonNotFieldnameToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a value that was not a JSON number.. + /// + internal static string JsonNotNumberToken + { + get + { + return ResourceManager.GetString("JsonNotNumberToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a value that was not a JSON string.. + /// + internal static string JsonNotStringToken + { + get + { + return ResourceManager.GetString("JsonNotStringToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a number that exceeded the range for JSON numbers.. + /// + internal static string JsonNumberOutOfRange + { + get + { + return ResourceManager.GetString("JsonNumberOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a number that was too long for a JSON number.. + /// + internal static string JsonNumberTooLong + { + get + { + return ResourceManager.GetString("JsonNumberTooLong", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Tried to write a JSON object end symbol ("}") without first opening with a JSON object start symbol ("{").. + /// + internal static string JsonObjectNotStarted + { + get + { + return ResourceManager.GetString("JsonObjectNotStarted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered a JSON property name after another JSON property name.. + /// + internal static string JsonPropertyAlreadyAdded + { + get + { + return ResourceManager.GetString("JsonPropertyAlreadyAdded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Either a JSON property array or object was not started.. + /// + internal static string JsonPropertyArrayOrObjectNotStarted + { + get + { + return ResourceManager.GetString("JsonPropertyArrayOrObjectNotStarted", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read a JSON end array ("]") symbol without a matching JSON start array symbol ("[").. + /// + internal static string JsonUnexpectedEndArray + { + get + { + return ResourceManager.GetString("JsonUnexpectedEndArray", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read a JSON end object ("}") symbol without a matching JSON start object symbol ("{").. + /// + internal static string JsonUnexpectedEndObject + { + get + { + return ResourceManager.GetString("JsonUnexpectedEndObject", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read a JSON name separator (":") symbol without a corresponding field name.. + /// + internal static string JsonUnexpectedNameSeparator + { + get + { + return ResourceManager.GetString("JsonUnexpectedNameSeparator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered an unexpected JSON token.. + /// + internal static string JsonUnexpectedToken + { + get + { + return ResourceManager.GetString("JsonUnexpectedToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read a JSON name separator (",") symbol without a preceding JSON value.. + /// + internal static string JsonUnexpectedValueSeparator + { + get + { + return ResourceManager.GetString("JsonUnexpectedValueSeparator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The resource that is being accessed is locked.. + /// + internal static string Locked + { + get + { + return ResourceManager.GetString("Locked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Current maximum throughput per collection is {0}. Please contact Azure support to increase it.. + /// + internal static string MaximumRULimitExceeded + { + get + { + return ResourceManager.GetString("MaximumRULimitExceeded", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot find messageId header. + /// + internal static string MessageIdHeaderMissing + { + get + { + return ResourceManager.GetString("MessageIdHeaderMissing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested verb is not supported.. + /// + internal static string MethodNotAllowed + { + get + { + return ResourceManager.GetString("MethodNotAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: '{0}'. + /// + internal static string MismatchToken + { + get + { + return ResourceManager.GetString("MismatchToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Required Header authorization is missing. Ensure a valid Authorization token is passed.. + /// + internal static string MissingAuthHeader + { + get + { + return ResourceManager.GetString("MissingAuthHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Authorization token mandates Date headers. Please pass in RFC 1123 style date format.. + /// + internal static string MissingDateForAuthorization + { + get + { + return ResourceManager.GetString("MissingDateForAuthorization", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKey value must be supplied for this operation.. + /// + internal static string MissingPartitionKeyValue + { + get + { + return ResourceManager.GetString("MissingPartitionKeyValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Required property {0} is not specified in the request.. + /// + internal static string MissingProperty + { + get + { + return ResourceManager.GetString("MissingProperty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Required header '{0}' is not specified in the request.. + /// + internal static string MissingRequiredHeader + { + get + { + return ResourceManager.GetString("MissingRequiredHeader", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Required query variable '{0}' is not specified in the request.. + /// + internal static string MissingRequiredQuery + { + get + { + return ResourceManager.GetString("MissingRequiredQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This account already has one backup interval capability.. + /// + internal static string MoreThanOneBackupIntervalCapability + { + get + { + return ResourceManager.GetString("MoreThanOneBackupIntervalCapability", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This account already has one backup retention capability.. + /// + internal static string MoreThanOneBackupRetentionCapability + { + get + { + return ResourceManager.GetString("MoreThanOneBackupRetentionCapability", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Atleast single region must be specified in PreferredLocation list when automatic failover is disabled.. + /// + internal static string MustHaveNonZeroPreferredRegionWhenAutomaticFailoverDisabled + { + get + { + return ResourceManager.GetString("MustHaveNonZeroPreferredRegionWhenAutomaticFailoverDisabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to NamingProperty {0} not found. + /// + internal static string NamingPropertyNotFound + { + get + { + return ResourceManager.GetString("NamingPropertyNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Property '{0}' integer value must be greater than or equal to zero.. + /// + internal static string NegativeInteger + { + get + { + return ResourceManager.GetString("NegativeInteger", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No graft point. + /// + internal static string NoGraftPoint + { + get + { + return ResourceManager.GetString("NoGraftPoint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Entity with the specified id does not exist in the system.. + /// + internal static string NotFound + { + get + { + return ResourceManager.GetString("NotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to GraphAPICompute Service cannot be deleted. + /// + internal static string GremlinV2ServiceDeleteNotSupported + { + get + { + return ResourceManager.GetString("GremlinV2ServiceDeleteNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offer replace request conflicted.. + /// + internal static string OfferReplaceTopologyConflict + { + get + { + return ResourceManager.GetString("OfferReplaceTopologyConflict", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot replace an offer with version {0} with version {1}. + /// + internal static string OfferReplaceWithSpecifiedVersionsNotSupported + { + get + { + return ResourceManager.GetString("OfferReplaceWithSpecifiedVersionsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offer type and throughput cannot both be specified.. + /// + internal static string OfferTypeAndThroughputCannotBeSpecifiedBoth + { + get + { + return ResourceManager.GetString("OfferTypeAndThroughputCannotBeSpecifiedBoth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offer throughput and autopilot settings cannot both be specified.. + /// + internal static string OfferThroughputAndAutoPilotSettingsCannotBeSpecifiedBoth + { + get + { + return ResourceManager.GetString("OfferThroughputAndAutoPilotSettingsCannotBeSpecifiedBoth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Autopilot tier and AutoPilotSettings cannot both be specified.. + /// + internal static string AutoPilotTierAndAutoPilotSettingsCannotBeSpecifiedBoth + { + get + { + return ResourceManager.GetString("AutoPilotTierAndAutoPilotSettingsCannotBeSpecifiedBoth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Autopilot autoupgrade is not supported for non-partitioned collections.. + /// + internal static string AutopilotAutoUpgradeUnsupportedNonPartitionedCollection + { + get + { + return ResourceManager.GetString("AutopilotAutoUpgradeUnsupportedNonPartitionedCollection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Requested Operation Status = {0} is invalid.. + /// + internal static string OperationRequestedStatusIsInvalid + { + get + { + return ResourceManager.GetString("OperationRequestedStatusIsInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Selected partition is full, please try insert in different partition.. + /// + internal static string PartitionIsFull + { + get + { + return ResourceManager.GetString("PartitionIsFull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Either PartitionKey or EffectivePartitionKey are expected.. + /// + internal static string PartitionKeyAndEffectivePartitionKeyBothSpecified + { + get + { + return ResourceManager.GetString("PartitionKeyAndEffectivePartitionKeyBothSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKey and PartitionKeyRangeId cannot be specified at the same time in ChangeFeedOptions.. + /// + internal static string PartitionKeyAndPartitionKeyRangeRangeIdBothSpecified + { + get + { + return ResourceManager.GetString("PartitionKeyAndPartitionKeyRangeRangeIdBothSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document.. + /// + internal static string PartitionKeyMismatch + { + get + { + return ResourceManager.GetString("PartitionKeyMismatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKeyRangeId is absent in the context.. + /// + internal static string PartitionKeyRangeIdAbsentInContext + { + get + { + return ResourceManager.GetString("PartitionKeyRangeIdAbsentInContext", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For partitioned collection, either ChangeFeedOptions.PartitionKeyRangeId or ChangeFeedOptions.PartitionKey must be specified.. + /// + internal static string PartitionKeyRangeIdOrPartitionKeyMustBeSpecified + { + get + { + return ResourceManager.GetString("PartitionKeyRangeIdOrPartitionKeyMustBeSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKeyRange with id '{0}' in collection '{1}' doesn't exist.. + /// + internal static string PartitionKeyRangeNotFound + { + get + { + return ResourceManager.GetString("PartitionKeyRangeNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Encountered an error in the partition migration operation. + /// + internal static string PartitionMigrationOperationError + { + get + { + return ResourceManager.GetString("PartitionMigrationOperationError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PerRegionPerPartitionAutoscale is not supported on account {0}. + /// + internal static string PerRegionPerPartitionAutoscaleNotSupported + { + get + { + return ResourceManager.GetString("PerRegionPerPartitionAutoscaleNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PerRegionPerPartitionAutoscale is not supported for serverless accounts. + /// + internal static string PerRegionPerPartitionAutoscaleNotSupportedForServerless + { + get + { + return ResourceManager.GetString("PerRegionPerPartitionAutoscaleNotSupportedForServerless", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Property '{0}' integer value must be greater than zero.. + /// + internal static string PositiveInteger + { + get + { + return ResourceManager.GetString("PositiveInteger", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Operation cannot be performed because one of the specified precondition is not met.. + /// + internal static string PreconditionFailed + { + get + { + return ResourceManager.GetString("PreconditionFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database account was created successfully, but the following regions failed to be added to account: \n. + /// + internal static string PrimarySuceededButAdditionalRegionsFailed + { + get + { + return ResourceManager.GetString("PrimarySuceededButAdditionalRegionsFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database account creation failed. Operation Id : {0}, Error : {1}. + /// + internal static string PrimaryWriteRegionFailedFormat + { + get + { + return ResourceManager.GetString("PrimaryWriteRegionFailedFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} : Operation Id : {1}, Error : {2}\n. + /// + internal static string SecondaryRegionsFailedFormat + { + get + { + return ResourceManager.GetString("SecondaryRegionsFailedFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Add or Remove region operation failed. + /// + internal static string AddRemoveRegionOperationFailed + { + get + { + return ResourceManager.GetString("AddRemoveRegionOperationFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to resolve primary endpoint for partition {0} for service {1}.. + /// + internal static string PrimaryNotFound + { + get + { + return ResourceManager.GetString("PrimaryNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Property {0} can not be assigned to null.. + /// + internal static string PropertyCannotBeNull + { + get + { + return ResourceManager.GetString("PropertyCannotBeNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Property '{0}' is not found in the document.. + /// + internal static string PropertyNotFound + { + get + { + return ResourceManager.GetString("PropertyNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reached the pre-approved storage limit for the database account. Please contact Azure support to increase this limit.. + /// + internal static string ProvisionLimit + { + get + { + return ResourceManager.GetString("ProvisionLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot authorize request since the [Action] to authorize was not found.. + /// + internal static string RbacMissingAction + { + get + { + return ResourceManager.GetString("RbacMissingAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot authorize request since the [User ID] to authorize was not found.. + /// + internal static string RbacMissingUserId + { + get + { + return ResourceManager.GetString("RbacMissingUserId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request is blocked because ResourceId [{0}] cannot be resolved. Principal = [{1}], Action = [{2}], ResourceType = [{3}].. + /// + internal static string RbacCannotResolveResourceRid + { + get + { + return ResourceManager.GetString("RbacCannotResolveResourceRid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Read Quorum size of {0} is not met for the request.. + /// + internal static string ReadQuorumNotMet + { + get + { + return ResourceManager.GetString("ReadQuorumNotMet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The read session is not available for the input session token.. + /// + internal static string ReadSessionNotAvailable + { + get + { + return ResourceManager.GetString("ReadSessionNotAvailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to read the server response.. + /// + internal static string ReceiveFailedTransportError + { + get + { + return ResourceManager.GetString("ReceiveFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The remote system closed the connection.. + /// + internal static string ReceiveStreamClosedTransportError + { + get + { + return ResourceManager.GetString("ReceiveStreamClosedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request timed out while waiting for a server response.. + /// + internal static string ReceiveTimeoutTransportError + { + get + { + return ResourceManager.GetString("ReceiveTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot remove write region for account {0}. Please issue delete on the account to remove write region. + /// + internal static string RemoveWriteRegionNotSupported + { + get + { + return ResourceManager.GetString("RemoveWriteRegionNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Replica at index '{0}' is currently unavailable.. + /// + internal static string ReplicaAtIndexNotAvailable + { + get + { + return ResourceManager.GetString("ReplicaAtIndexNotAvailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Consistency Level '{0}' requested via header '{1}' is not supported by this service endpoint. Please contact the service administrator.. + /// + internal static string RequestConsistencyLevelNotSupported + { + get + { + return ResourceManager.GetString("RequestConsistencyLevelNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The size of the response exceeded the maximum allowed size, limit the response size by specifying smaller value for '{0}' header.. + /// + internal static string RequestEntityTooLarge + { + get + { + return ResourceManager.GetString("RequestEntityTooLarge", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Request timed out.. + /// + internal static string RequestTimeout + { + get + { + return ResourceManager.GetString("RequestTimeout", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request timed out. See the inner exception for details.. + /// + internal static string RequestTimeoutTransportError + { + get + { + return ResourceManager.GetString("RequestTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The size of the request exceeded the maximum allowed size.. + /// + internal static string RequestTooLarge + { + get + { + return ResourceManager.GetString("RequestTooLarge", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource id cannot be empty.. + /// + internal static string ResourceIdCannotBeEmpty + { + get + { + return ResourceManager.GetString("ResourceIdCannotBeEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ResourceId {0} of type {1} is not a valid resource Id.. + /// + internal static string ResourceIdNotValid + { + get + { + return ResourceManager.GetString("ResourceIdNotValid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ResourceIdPolicy {0} is not supported. + /// + internal static string ResourceIdPolicyNotSupported + { + get + { + return ResourceManager.GetString("ResourceIdPolicyNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource type {0} is not supported by ResourceIdPartitioner. + /// + internal static string ResourceTypeNotSupported + { + get + { + return ResourceManager.GetString("ResourceTypeNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Retry the request.. + /// + internal static string RetryWith + { + get + { + return ResourceManager.GetString("RetryWith", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changing id of a script in collections with multiple partitions is not supported.. + /// + internal static string ScriptRenameInMultiplePartitionsIsNotSupported + { + get + { + return ResourceManager.GetString("ScriptRenameInMultiplePartitionsIsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to resolve secondary endpoint for partition {0} for service {1}.. + /// + internal static string SecondariesNotFound + { + get + { + return ResourceManager.GetString("SecondariesNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sending the request failed.. + /// + internal static string SendFailedTransportError + { + get + { + return ResourceManager.GetString("SendFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Acquiring the send stream lock timed out.. + /// + internal static string SendLockTimeoutTransportError + { + get + { + return ResourceManager.GetString("SendLockTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sending the request timed out.. + /// + internal static string SendTimeoutTransportError + { + get + { + return ResourceManager.GetString("SendTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Partition reconfiguration exceeded retry limit. Please contact support with the full exception. + /// + internal static string Server_CompletingPartitionMigrationExceededRetryLimit + { + get + { + return ResourceManager.GetString("Server_CompletingPartitionMigrationExceededRetryLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unhandled partition split. Please contact support with the full exception. + /// + internal static string Server_CompletingSplitExceededRetryLimit + { + get + { + return ResourceManager.GetString("Server_CompletingSplitExceededRetryLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not achieve backend quorum for Strong or Bounded Staleness after barrier requests. + /// + internal static string Server_GlobalStrongWriteBarrierNotMet + { + get + { + return ResourceManager.GetString("Server_GlobalStrongWriteBarrierNotMet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Container was re-created, exceeded retries to resolve new identifier. Please contact support with the full exception. + /// + internal static string Server_NameCacheIsStaleExceededRetryLimit + { + get + { + return ResourceManager.GetString("Server_NameCacheIsStaleExceededRetryLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Store (backend) returned an invalid response. Please contact support with the full exception. + /// + internal static string Server_NoValidStoreResponse + { + get + { + return ResourceManager.GetString("Server_NoValidStoreResponse", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unhandled partition split. Please contact support with the full exception. + /// + internal static string Server_PartitionKeyRangeGoneExceededRetryLimit + { + get + { + return ResourceManager.GetString("Server_PartitionKeyRangeGoneExceededRetryLimit", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not achieve backend quorum. + /// + internal static string Server_ReadQuorumNotMet + { + get + { + return ResourceManager.GetString("Server_ReadQuorumNotMet", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server returned a 410 response. + /// + internal static string ServerGenerated410 + { + get + { + return ResourceManager.GetString("ServerGenerated410", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Server returned a 503 response. + /// + internal static string ServerGenerated503 + { + get + { + return ResourceManager.GetString("ServerGenerated503", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The response body length is too large. Body length: {0} bytes. Connection: {1}. + /// + internal static string ServerResponseBodyTooLargeError + { + get + { + return ResourceManager.GetString("ServerResponseBodyTooLargeError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The response total header length is too large. Header length: {0} bytes. Connection: {1}. + /// + internal static string ServerResponseHeaderTooLargeError + { + get + { + return ResourceManager.GetString("ServerResponseHeaderTooLargeError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid response total header length. Expected {0} bytes. Received {1} bytes. Connection: {2}. + /// + internal static string ServerResponseInvalidHeaderLengthError + { + get + { + return ResourceManager.GetString("ServerResponseInvalidHeaderLengthError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The transport request ID is missing from the server response.. + /// + internal static string ServerResponseTransportRequestIdMissingError + { + get + { + return ResourceManager.GetString("ServerResponseTransportRequestIdMissingError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service at index {0} not found.. + /// + internal static string ServiceNotFound + { + get + { + return ResourceManager.GetString("ServiceNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service reserved bits can not be more than 24. Otherwise it overlaps with the collection/user multiplexing bit. + /// + internal static string ServiceReservedBitsOutOfRange + { + get + { + return ResourceManager.GetString("ServiceReservedBitsOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service is currently unavailable.. + /// + internal static string ServiceUnavailable + { + get + { + return ResourceManager.GetString("ServiceUnavailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Service Unavailable due to high demand in the region. + /// + internal static string ServiceUnavailableDueToHighDemandInRegion + { + get + { + return ResourceManager.GetString("ServiceUnavailableDueToHighDemandInRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find service hosting DocumentCollection with ResourceId {0}. + /// + internal static string ServiceWithResourceIdNotFound + { + get + { + return ResourceManager.GetString("ServiceWithResourceIdNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bounding box must have an even number of coordinates and more than 3.. + /// + internal static string SpatialBoundingBoxInvalidCoordinates + { + get + { + return ResourceManager.GetString("SpatialBoundingBoxInvalidCoordinates", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spatial operations can be used in Linq expressions only and are evaluated in Azure CosmosDB server.. + /// + internal static string SpatialExtensionMethodsNotImplemented + { + get + { + return ResourceManager.GetString("SpatialExtensionMethodsNotImplemented", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Coordinate Reference System specified in GeoJSON is invalid.. + /// + internal static string SpatialFailedToDeserializeCrs + { + get + { + return ResourceManager.GetString("SpatialFailedToDeserializeCrs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to deserialize Geometry object because 'type' property is either absent or has invalid value.. + /// + internal static string SpatialInvalidGeometryType + { + get + { + return ResourceManager.GetString("SpatialInvalidGeometryType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spatial position must have at least two coordinates.. + /// + internal static string SpatialInvalidPosition + { + get + { + return ResourceManager.GetString("SpatialInvalidPosition", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SSL negotiation failed.. + /// + internal static string SslNegotiationFailedTransportError + { + get + { + return ResourceManager.GetString("SslNegotiationFailedTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SSL negotiation timed out.. + /// + internal static string SslNegotiationTimeoutTransportError + { + get + { + return ResourceManager.GetString("SslNegotiationTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Star and slash should have no arguments.. + /// + internal static string StarSlashArgumentError + { + get + { + return ResourceManager.GetString("StarSlashArgumentError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Storage analytics is not enabled for this account. Ensure storage analytics is enabled before retrying.. + /// + internal static string StorageAnalyticsNotEnabled + { + get + { + return ResourceManager.GetString("StorageAnalyticsNotEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to String agument {0} is null or empty. + /// + internal static string StringArgumentNullOrEmpty + { + get + { + return ResourceManager.GetString("StringArgumentNullOrEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to System database account with name {0} and type {1} not found. + /// + internal static string SystemDatabaseAccountNotFound + { + get + { + return ResourceManager.GetString("SystemDatabaseAccountNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to System database account {0} cannot be created with Continuous backup mode. + /// + internal static string SystemDatabaseAccountPitrEnabledNotSupported + { + get + { + return ResourceManager.GetString("SystemDatabaseAccountPitrEnabledNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross tenant CMK database account doesn't support using delegated identity as the default identity. + /// + internal static string CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported + { + get + { + return ResourceManager.GetString("CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The server encountered an unexpected condition that prevented it from fulfilling the Azure Key Vault resource request. + /// + internal static string UnexpectedExceptionCaughtonKeyVaultAccessClient + { + get + { + return ResourceManager.GetString("UnexpectedExceptionCaughtonKeyVaultAccessClient", resourceCulture); + } + } + + /// + /// The expected scope array should be of length 1. Instead received scope with length {0}. + /// + internal static string InvalidMSALScopeLength + { + get + { + return ResourceManager.GetString("InvalidMSALScopeLength", resourceCulture); + } + } + + /// + /// The requested scope is not a well formed URI string. + /// + internal static string InvalidRequestedScopeFormat + { + get + { + return ResourceManager.GetString("InvalidRequestedScopeFormat", resourceCulture); + } + } + + /// + /// The requested scope is not https. + /// + internal static string InvalidSchemeInScope + { + get + { + return ResourceManager.GetString("InvalidSchemeInScope", resourceCulture); + } + } + + /// + /// The requested scope contains unexpected segments. + /// + internal static string InvalildScopeSegments + { + get + { + return ResourceManager.GetString("InvalildScopeSegments", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Error contacting the Azure Key Vault resource. Please try again. + /// + internal static string KeyVaultServiceUnavailable + { + get + { + return ResourceManager.GetString("KeyVaultServiceUnavailable", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided Azure Key Vault resource key URI is invalid. Please follow the format: https://{vault-name}.vault.azure.net/keys/{key-name} or https://{vault-name}.vault.azure.net/certificates/{certificate-name} or https://{vault-name}.vault.azure.net/secrets/{secret-name} . + /// + internal static string InvalidKeyVaultKeyAndCertURI + { + get + { + return ResourceManager.GetString("InvalidKeyVaultKeyAndCertURI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided Azure Key Vault resource key URI is invalid. Please follow the format: https://{vault-name}.vault.azure.net/secrets/{secret-name} . + /// + internal static string InvalidKeyVaulSecretURI + { + get + { + return ResourceManager.GetString("InvalidKeyVaulSecretURI", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The remote name could not be resolved for the Azure Key Vault resource. Please provide a valid URI for an existing Key vault. + /// + internal static string KeyVaultDNSNotResolved + { + get + { + return ResourceManager.GetString("KeyVaultDNSNotResolved", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find any secret with the.pem extension related to the provided certificate. + /// + internal static string KeyVaultCertificateException + { + get + { + return ResourceManager.GetString("KeyVaultCertificateException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Input provided is not a valid base 64 string. + /// + internal static string KeyVaultInvalidInputBytes + { + get + { + return ResourceManager.GetString("KeyVaultInvalidInputBytes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to acquire the access token needed to access the Azure Key Vault resource. Please verify that the tenant has all corresponding permissions assigned. + /// + internal static string KeyVaultAadClientCredentialsGrantFailure + { + get + { + return ResourceManager.GetString("KeyVaultAadClientCredentialsGrantFailure", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Status Code for the first Azure Key Vault resource access try should be Unauthorized. + /// + internal static string FirstKeyVaultAccessAttemptShouldBeUnauthorized + { + get + { + return ResourceManager.GetString("FirstKeyVaultAccessAttemptShouldBeUnauthorized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Network timeout or connectivity failure. + /// + internal static string TimeoutGenerated410 + { + get + { + return ResourceManager.GetString("TimeoutGenerated410", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKey has fewer components than defined the collection resource.. + /// + internal static string TooFewPartitionKeyComponents + { + get + { + return ResourceManager.GetString("TooFewPartitionKeyComponents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKey has more components than defined the collection resource.. + /// + internal static string TooManyPartitionKeyComponents + { + get + { + return ResourceManager.GetString("TooManyPartitionKeyComponents", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The request rate is too large. Please retry after sometime. Learn more: http://aka.ms/cosmosdb-error-429. + /// + internal static string TooManyRequests + { + get + { + return ResourceManager.GetString("TooManyRequests", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A client transport error occurred: {0}. + /// + internal static string TransportExceptionMessage + { + get + { + return ResourceManager.GetString("TransportExceptionMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The SDK failed to connect to the service. Please check your networking configuration. + /// + internal static string TransportGenerated410 + { + get + { + return ResourceManager.GetString("TransportGenerated410", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Continuous connectivity failures. Client cannot connect after multiple retries. Please check your networking configuration + /// + internal static string TransportGenerated503 + { + get + { + return ResourceManager.GetString("TransportGenerated503", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The transport protocol negotiation timed out. See the inner exception for details.. + /// + internal static string TransportNegotiationTimeoutTransportError + { + get + { + return ResourceManager.GetString("TransportNegotiationTimeoutTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The TCP channel timed out on waiting to open. + /// + internal static string ChannelWaitingToOpenTimeoutException + { + get + { + return ResourceManager.GetString("ChannelWaitingToOpenTimeoutException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot deserialize PartitionKey value '{0}'. + /// + internal static string UnableToDeserializePartitionKeyValue + { + get + { + return ResourceManager.GetString("UnableToDeserializePartitionKeyValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to find free connection. + /// + internal static string UnableToFindFreeConnection + { + get + { + return ResourceManager.GetString("UnableToFindFreeConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to authenticate the request. The request requires valid user authentication.. + /// + internal static string Unauthorized + { + get + { + return ResourceManager.GetString("Unauthorized", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unauthorized Offer Replace Request.. + /// + internal static string UnauthorizedOfferReplaceRequest + { + get + { + return ResourceManager.GetString("UnauthorizedOfferReplaceRequest", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unauthorized Auto-Scale Request.. + /// + internal static string UnauthorizedRequestForAutoScale + { + get + { + return ResourceManager.GetString("UnauthorizedRequestForAutoScale", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Operation not permitted as consistency level is set to {0}. Expected {1}.. + /// + internal static string UnexpectedConsistencyLevel + { + get + { + return ResourceManager.GetString("UnexpectedConsistencyLevel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected JsonSerializationFormat: {0}. + /// + internal static string UnexpectedJsonSerializationFormat + { + get + { + return ResourceManager.GetString("UnexpectedJsonSerializationFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Failed to register JsonTokenType: {0}. + /// + internal static string UnexpectedJsonTokenType + { + get + { + return ResourceManager.GetString("UnexpectedJsonTokenType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected offer version {0} from store.. + /// + internal static string UnexpectedOfferVersion + { + get + { + return ResourceManager.GetString("UnexpectedOfferVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected operation type {0} for routing requests for multiple partitions.. + /// + internal static string UnexpectedOperationTypeForRoutingRequest + { + get + { + return ResourceManager.GetString("UnexpectedOperationTypeForRoutingRequest", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected operator {0} .. + /// + internal static string UnexpectedOperator + { + get + { + return ResourceManager.GetString("UnexpectedOperator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKeyRangeId is not expected.. + /// + internal static string UnexpectedPartitionKeyRangeId + { + get + { + return ResourceManager.GetString("UnexpectedPartitionKeyRangeId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Provided Resource Kind {0} to ReEncrypt is not expected.. + /// + internal static string UnExpectedResourceKindToReEncrypt + { + get + { + return ResourceManager.GetString("UnExpectedResourceKindToReEncrypt", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ResourceType {0} is unexpected.. + /// + internal static string UnexpectedResourceType + { + get + { + return ResourceManager.GetString("UnexpectedResourceType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource kind {0} is unknown. + /// + internal static string UnknownResourceKind + { + get + { + return ResourceManager.GetString("UnknownResourceKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource type {0} is unknown. + /// + internal static string UnknownResourceType + { + get + { + return ResourceManager.GetString("UnknownResourceType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An unknown client transport error has occurred.. + /// + internal static string UnknownTransportError + { + get + { + return ResourceManager.GetString("UnknownTransportError", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Distict query requires a matching order by in order to return a continuation token. + ///If you would like to serve this query through continuation tokens, then please rewrite the query in the form 'SELECT DISTINCT VALUE c.blah FROM c ORDER BY c.blah' and please make sure that there is a range index on 'c.blah'.. + /// + internal static string UnorderedDistinctQueryContinuationToken + { + get + { + return ResourceManager.GetString("UnorderedDistinctQueryContinuationToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested region '{0}' does not support AZ provisioning yet. Please try other regions or disable zone redundancy for this region.. + /// + internal static string UnsupportedAzRegion + { + get + { + return ResourceManager.GetString("UnsupportedAzRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "{0} capability is not allowed with kind={1}". + /// + internal static string UnsupportedCapabilityForKind + { + get + { + return ResourceManager.GetString("UnsupportedCapabilityForKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Update of "{0} capability is not allowed. + /// + internal static string UnsupportedCapabilityUpdate + { + get + { + return ResourceManager.GetString("UnsupportedCapabilityUpdate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "{0} capability is not compatible with mongo ServerVersion={1} accounts.". + /// + internal static string UnsupportedCapabilityForServerVersion + { + get + { + return ResourceManager.GetString("UnsupportedCapabilityForServerVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot execute cross partition order-by queries on mix types. Consider using IS_STRING/IS_NUMBER to get around this exception. Expect type: {0}. Actual type: {1}. Item value: {2}.. + /// + internal static string UnsupportedCrossPartitionOrderByQueryOnMixedTypes + { + get + { + return ResourceManager.GetString("UnsupportedCrossPartitionOrderByQueryOnMixedTypes", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided cross partition query can not be directly served by the gateway. This is a first chance (internal) exception that all newer clients will know how to handle gracefully. This exception is traced, but unless you see it bubble up as an exception (which only happens on older SDK clients), then you can safely ignore this message.. + /// + internal static string UnsupportedCrossPartitionQuery + { + get + { + return ResourceManager.GetString("UnsupportedCrossPartitionQuery", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cross partition query with aggregate functions is not supported.. + /// + internal static string UnsupportedCrossPartitionQueryWithAggregate + { + get + { + return ResourceManager.GetString("UnsupportedCrossPartitionQueryWithAggregate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsupported entity type {0}. + /// + internal static string UnsupportedEntityType + { + get + { + return ResourceManager.GetString("UnsupportedEntityType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Indexing Hints are not supported in this deployment. . + /// + internal static string UnsupportedHints + { + get + { + return ResourceManager.GetString("UnsupportedHints", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Key type {0} is unsupported. + /// + internal static string UnsupportedKeyType + { + get + { + return ResourceManager.GetString("UnsupportedKeyType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The operation is only supported for Serverless accounts, per-partition throughput cannot be updated directly for provisioned accounts. + /// + internal static string UnsupportedOfferOperationForProvisionedThroughput + { + get + { + return ResourceManager.GetString("UnsupportedOfferOperationForProvisionedThroughput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please specify a value between {0} and {1} inclusive in increments of {2}. Please contact https://azure.microsoft.com/support to request limit increases beyond {1} RU/s.. + /// + internal static string UnSupportedOfferThroughput + { + get + { + return ResourceManager.GetString("UnSupportedOfferThroughput", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The value of offer throughput specified is invalid. Please specify a value between {0} and {1}, or between {2} and {3} inclusive in increments of {4}. Please contact https://azure.microsoft.com/support to request limit increases beyond {3} RU/s.. + /// + internal static string UnSupportedOfferThroughputWithTwoRanges + { + get + { + return ResourceManager.GetString("UnSupportedOfferThroughputWithTwoRanges", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Offer type is not supported with Offer version 'V2' and above.. + /// + internal static string UnsupportedOfferTypeWithV2Offer + { + get + { + return ResourceManager.GetString("UnsupportedOfferTypeWithV2Offer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The supplied offer version {0} is not supported. Please specify either a blank version, 'V1' or 'V2'.. + /// + internal static string UnsupportedOfferVersion + { + get + { + return ResourceManager.GetString("UnsupportedOfferVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsupported PartitionKey value component '{0}'. Numeric, string, bool, null, Undefined are the only supported types.. + /// + internal static string UnsupportedPartitionKeyComponentValue + { + get + { + return ResourceManager.GetString("UnsupportedPartitionKeyComponentValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Program requires to run in 64 bit for elastic query feature to work. Please switch your program to 64 bit or use Gateway connectivity mode.. + /// + internal static string UnsupportedProgram + { + get + { + return ResourceManager.GetString("UnsupportedProgram", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Value '{0}' specified for protocol is unsupported.. + /// + internal static string UnsupportedProtocol + { + get + { + return ResourceManager.GetString("UnsupportedProtocol", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Query that expects full results from aggregate functions is not supported.. + /// + internal static string UnsupportedQueryWithFullResultAggregate + { + get + { + return ResourceManager.GetString("UnsupportedQueryWithFullResultAggregate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested region '{0}' is not supported.. + /// + internal static string UnsupportedRegion + { + get + { + return ResourceManager.GetString("UnsupportedRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested region '{0}' is not supported for '{1}' cluster creation.. + /// + internal static string UnsupportedClusterRegion + { + get + { + return ResourceManager.GetString("UnsupportedClusterRegion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The requested rollback kind '{0}' is not supported.. + /// + internal static string UnsupportedRollbackKind + { + get + { + return ResourceManager.GetString("UnsupportedRollbackKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Changing Root Indexing Policy is not supported in this deployment.. + /// + internal static string UnsupportedRootPolicyChange + { + get + { + return ResourceManager.GetString("UnsupportedRootPolicyChange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Federation system key kind {0} is invalid. + /// + internal static string UnsupportedSystemKeyKind + { + get + { + return ResourceManager.GetString("UnsupportedSystemKeyKind", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsupported token type {0}. + /// + internal static string UnsupportedTokenType + { + get + { + return ResourceManager.GetString("UnsupportedTokenType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The Offer Version 'V1' is not supported since the associated collection is already a partitioned collection. Please use offer version 'V2'.. + /// + internal static string UnsupportedV1OfferVersion + { + get + { + return ResourceManager.GetString("UnsupportedV1OfferVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to AAD tokens are not supported by the Dedicated Gateway endpoint. + /// + internal static string UnsupportedAadAccessControlType + { + get + { + return ResourceManager.GetString("UnsupportedAadAccessControlType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Resource tokens are not supported by the Dedicated Gateway endpoint. + /// + internal static string UnsupportedAccessControlType + { + get + { + return ResourceManager.GetString("UnsupportedAccessControlType", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upserts for scripts in collections with multiple partitions are not supported.. + /// + internal static string UpsertsForScriptsWithMultiplePartitionsAreNotSupported + { + get + { + return ResourceManager.GetString("UpsertsForScriptsWithMultiplePartitionsAreNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Web socket requests are not supported. + /// + internal static string WebSocketRequestsNotSupported + { + get + { + return ResourceManager.GetString("WebSocketRequestsNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot offline write region when automatic failover is not enabled. + /// + internal static string WriteRegionAutomaticFailoverNotEnabled + { + get + { + return ResourceManager.GetString("WriteRegionAutomaticFailoverNotEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot perform failover as it is disabled for the account. + /// + internal static string FailoverDisabled + { + get + { + return ResourceManager.GetString("FailoverDisabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot perform failover priority change as it is disabled for the account. + /// + internal static string FailoverPriorityChangeDisabled + { + get + { + return ResourceManager.GetString("FailoverPriorityChangeDisabled", resourceCulture); + } + } + + + /// + /// Looks up a localized string similar to Cannot add additional regions, since database account provision failed.. + /// + internal static string WriteRegionDoesNotExist + { + get + { + return ResourceManager.GetString("WriteRegionDoesNotExist", resourceCulture); + } + } + + + /// + /// Looks up a localized string similar to Zone Redundant Accounts are not supported in {0} Location yet. Please try other locations.. + /// + internal static string ZoneRedundantAccountsNotSupportedInLocation + { + get + { + return ResourceManager.GetString("ZoneRedundantAccountsNotSupportedInLocation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection is too busy. Please retry after sometime or open more connections. + /// + internal static string ConnectionIsBusy + { + get + { + return ResourceManager.GetString("ConnectionIsBusy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Partition key path {0} is invalid for Gremlin API. The path cannot be '/id', '/label' or a nested path such as '/key/path'.. + /// + internal static string InvalidGremlinPartitionKey + { + get + { + return ResourceManager.GetString("InvalidGremlinPartitionKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please provide non-negative value for UpdateMaxthroughputEverProvisioned.. + /// + internal static string InvalidUpdateMaxthroughputEverProvisioned + { + get + { + return ResourceManager.GetString("InvalidUpdateMaxthroughputEverProvisioned", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to "Operation '{0}' on resource '{1}' is not allowed through Azure Cosmos DB endpoint. Please switch on such operations for your account, or perform this operation through Azure Resource Manager, Azure Portal, Azure CLI or Azure Powershell". + /// + internal static string DataPlaneOperationNotAllowed + { + get + { + return ResourceManager.GetString("DataPlaneOperationNotAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Collection is not yet available for read. Please retry in some time.. + /// + internal static string CollectionCreateInProgress + { + get + { + return ResourceManager.GetString("CollectionCreateInProgress", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Free tier has already been applied to another Azure Cosmos DB account in this subscription. To apply free tier to this account, you can select another subscription for this account or delete the existing free tier account. You can have up to one free tier account per subscription.. + /// + internal static string FreeTierAppliedBefore + { + get + { + return ResourceManager.GetString("FreeTierAppliedBefore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Free tier is not supported for Internal subscriptions.. + /// + internal static string FreeTierNotSupportedForInternalSubscription + { + get + { + return ResourceManager.GetString("FreeTierNotSupportedForInternalSubscription", resourceCulture); + } + } + + /// Looks up a localized string similar to Could not resolve DataTransfer state store account for region [{0}].. + internal static string DataTransferStateStoreNotResolved + { + get + { + return ResourceManager.GetString("DataTransferStateStoreNotResolved", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot update FreeTier property for existing account.. + /// + internal static string FreeTierUpdateNotSupported + { + get + { + return ResourceManager.GetString("FreeTierUpdateNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Subpartitioning is only supported for atmost 3 partition paths . + /// + internal static string InvalidSubPartitionKeyLength + { + get + { + return ResourceManager.GetString("InvalidSubPartitionKeyLength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Subpartitioning is only supported for Hash V2. . + /// + internal static string InvalidSubPartitionKeyVersion + { + get + { + return ResourceManager.GetString("InvalidSubPartitionKeyVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Missing '_id' index while creating a MongoDB api collection. + /// + internal static string UnderscoreIdIndexRequiredForMongo + { + get + { + return ResourceManager.GetString("UnderscoreIdIndexRequiredForMongo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Partition key path {0} is invalid for MongoDB API. + /// + internal static string InvalidMongoPartitionKey + { + get + { + return ResourceManager.GetString("InvalidMongoPartitionKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The create request is not allowed since it does not specify the schema for container '{0}'. + /// + internal static string MissingSchemaPolicyOnContainer + { + get + { + return ResourceManager.GetString("MissingSchemaPolicyOnContainer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The container replace request is not allowed since it removes the schema policy from the container {0}. + /// + internal static string CannotRemoveSchemaPolicyFromContainer + { + get + { + return ResourceManager.GetString("CannotRemoveSchemaPolicyFromContainer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The container replace request is not allowed since it removes the Cassandra conflict resolution policy from the container {0}. + /// + internal static string CannotReplaceCassandraConflictPolicyFromContainer + { + get + { + return ResourceManager.GetString("CannotReplaceCassandraConflictPolicyFromContainer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The container create request is not allowed since it does not contain the Cassandra conflict resolution policy specified for the container {0}. + /// + internal static string CannotCreateContainerWithoutCassandraConflictPolicy + { + get + { + return ResourceManager.GetString("CannotCreateContainerWithoutCassandraConflictPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid type system '{0}' specified for container {1}. + /// + internal static string InvalidTypeSystemPolicy + { + get + { + return ResourceManager.GetString("InvalidTypeSystemPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type system must be specified for the container {0}. + /// + internal static string MissingTypeSystemPolicy + { + get + { + return ResourceManager.GetString("MissingTypeSystemPolicy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Auto upgrade policy is not supported for MongDB resources.. + /// + internal static string MongoClientAutoUpgradeNotSupported + { + get + { + return ResourceManager.GetString("MongoClientAutoUpgradeNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updating offer to autoscale throughput is not allowed. Please invoke migration API to migrate this offer.. + /// + internal static string UpdateToAutoscaleThroughputNotAllowed + { + get + { + return ResourceManager.GetString("UpdateToAutoscaleThroughputNotAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updating offer to manually provisioned throughput is not allowed. Please invoke migration API to migrate this offer.. + /// + internal static string UpdateToManualThroughputNotAllowed + { + get + { + return ResourceManager.GetString("UpdateToManualThroughputNotAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to System database account {0} delete is not supported through this endpoint. + /// + internal static string SystemDatabaseAccountDeleteNotSupported + { + get + { + return ResourceManager.GetString("SystemDatabaseAccountDeleteNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only system database account delete is supported through this endpoint. Supplied account {0}. + /// + internal static string InvalidSystemDatabaseAccountDelete + { + get + { + return ResourceManager.GetString("InvalidSystemDatabaseAccountDelete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid store type specified {0}. + /// + internal static string InvalidStoreTypeSpecified + { + get + { + return ResourceManager.GetString("InvalidStoreTypeSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Revoke/Grant is not allowed as the Account status is: {0}. + /// + internal static string RevokeRegrantNotAllowed + { + get + { + return ResourceManager.GetString("RevokeRegrantNotAllowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The potential total throughput of this operation exceeds the total throughput limit set for this account. Aborting request. + /// + internal static string InvalidTotalThroughputLimitUpdate + { + get + { + return ResourceManager.GetString("InvalidTotalThroughputLimitUpdate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to PartitionKey has fewer components than defined the collection resource.. + /// + internal static string UnsupportedPartitionDefinitionKindForPartialKeyOperations + { + get + { + return ResourceManager.GetString("UnsupportedPartitionDefinitionKindForPartialKeyOperations", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There cannot be duplicate physical partition ids in x-ms-cosmos-target-partition-throughput-info header.. + /// + internal static string DuplicatePhysicalPartitionIdInTargetPartitionThroughputInfo + { + get + { + return ResourceManager.GetString("DuplicatePhysicalPartitionIdInTargetPartitionThroughputInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There cannot be duplicate physical partition ids in x-ms-cosmos-source-partition-throughput-info header.. + /// + internal static string DuplicatePhysicalPartitionIdInSourcePartitionThroughputInfo + { + get + { + return ResourceManager.GetString("DuplicatePhysicalPartitionIdInSourcePartitionThroughputInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There cannot be a common physical partition id both in x-ms-cosmos-target-partition-throughput-info and x-ms-cosmos-source-partition-throughput-info header. Encountered {0}. + /// + internal static string PhysicalPartitionIdinTargetAndSourcePartitionThroughputInfo + { + get + { + return ResourceManager.GetString("PhysicalPartitionIdinTargetAndSourcePartitionThroughputInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to One of the source or target physical partition id doesn't exist.. + /// + internal static string PhysicalPartitionIdinTargetOrSourceDoesNotExist + { + get + { + return ResourceManager.GetString("PhysicalPartitionIdinTargetOrSourceDoesNotExist", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Collection name '{0}' is invalid for MongoDB API.. + /// + internal static string InvalidMongoCollectionName + { + get + { + return ResourceManager.GetString("InvalidMongoCollectionName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Database name '{0}' is invalid for MongoDB API.. + /// + internal static string InvalidMongoDatabaseName + { + get + { + return ResourceManager.GetString("InvalidMongoDatabaseName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). + /// + internal static string KeyVaultAuthenticationFailureRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultAuthenticationFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). + /// + internal static string KeyVaultWrapUnwrapFailureRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultWrapUnwrapFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the correspondent key is not found on the specified Key Vault. + /// + internal static string KeyVaultKeyNotFoundRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultKeyNotFoundRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the correspondent Azure Key Vault was not found. + /// + internal static string KeyVaultNotFoundRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultNotFoundRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). + /// + internal static string KeyVaultDNSNotResolvedRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultDNSNotResolvedRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). + /// + internal static string AadClientCredentialsGrantFailureRevokeMessage + { + get + { + return ResourceManager.GetString("AadClientCredentialsGrantFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). + /// + internal static string UndefinedDefaultIdentityRevokeMessage + { + get + { + return ResourceManager.GetString("UndefinedDefaultIdentityRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). + /// + internal static string InvalidKeyVaultKeyURIRevokeMessage + { + get + { + return ResourceManager.GetString("InvalidKeyVaultKeyURIRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). + /// + internal static string NspOutboundDeniedRevokeMessage + { + get + { + return ResourceManager.GetString("NspOutboundDeniedRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide + /// + internal static string UnknownSubstatusCodeRevokeMessage + { + get + { + return ResourceManager.GetString("UnknownSubstatusCodeRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your account has access to the customer managed key. + /// + internal static string CmkAccountIsNotRevoked + { + get + { + return ResourceManager.GetString("CmkAccountIsNotRevoked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableDataMaskingPolicy on an account with Log Store features. + /// + internal static string EnableDataMaskingPolicyAndEnableLogStoreNotSupported + { + get + { + return ResourceManager.GetString("EnableDataMaskingPolicyAndEnableLogStoreNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DataMaskingPolicy is not supported on this account type. + /// + internal static string DataMaskingPolicyNotSupported + { + get + { + return ResourceManager.GetString("DataMaskingPolicyNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to UnexpectedResultAtCmkFastScanner for unexpected errors in cmk migation fast scanner. + /// + internal static string UnexpectedResultAtCmkFastScanner + { + get + { + return ResourceManager.GetString("UnexpectedResultAtCmkFastScanner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to InvalidResultAtCmkFastScanner if a document with big id is found in cmk migation fast scanner. + /// + internal static string InvalidResultAtCmkFastScanner + { + get + { + return ResourceManager.GetString("InvalidResultAtCmkFastScanner", resourceCulture); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/RMResources.resx b/Microsoft.Azure.Cosmos/src/RMResources.resx index 2e85bb5a71..1522990ffe 100644 --- a/Microsoft.Azure.Cosmos/src/RMResources.resx +++ b/Microsoft.Azure.Cosmos/src/RMResources.resx @@ -1,1404 +1,1422 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - One of the input values is invalid. - - - Request url is invalid. - - - Cannot remove write region for account {0}. Please issue delete on the account to remove write region - - - Add or Remove region operation failed. - - - Service is currently unavailable, please retry after a while. If this problem persists please contact support. - - - Value specified in the "{0}" header is incompatible with value specified in the "{1}" header of the request. - - - Error occurred while deserializing content '{0}'. - - - Cannot add regions to this account type. - - - Cannot set EnableMultipleWriteLocations on this account type. - - - Pitr is not supported on this account type. - - - Cannot set DisableKeyBasedMetadataWriteAccess on this account type. - - - MaterializedViews is not supported on this account type. - - - Full Fidelity Change Feed is not supported on this account type. - - - CassandraConnector not supported for this account type. - - - Free Tier is not supported on this account type. - - - Analytical Storage is not supported on this account type. - - - Cannot set VirtualNetworkFilter on this account type. - - - Serverless offer is not supported on this account type. - - - Cannot set IpRangeFilter values on this account type. - - - Unable to retrieve address of endpoint '{0}' from the address '{1}' - - - Entity with the specified id already exists in the system. - - - Request is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden - - - Request originated from IP {0} through public internet. This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden - - - Request originated from VNET through service endpoint. This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden - - - Request received through private endpoint. It is blocked because either your account does not have private endpoint configured, or it is not from the private endpoint that your account is configured with. More info: https://aka.ms/cosmosdb-tsg-forbidden - - - The requested resource is no longer available at the server. - - - Insufficient permissions provided in the authorization header for the corresponding request. Please retry with another authorization header. - - - Unknown server error occurred when processing this request. - - - Authorization header doesn't confirm to the required format. Please verify and try again. - - - The backend response was not in the correct format. - - - The input date header is invalid format. Please pass in RFC 1123 style date format. - - - Value '{0}' specified for the header '{1}' is invalid. - - - Command is not supported by backend - - - Query '{0}' specified is either invalid or unsupported. - - - Value '{0}' specified for the query '{1}' is invalid. - - - Failed to parse the value '{0}' as ResourceId. - - - The request path {0} is invalid. - - - The value '{0}' specified for query '{1}' is invalid. - - - Staleness Policy specified is invalid. Ensure both MaxPrefix and MaxStalenessIntervalInSeconds are both 0 or both not zero. - - - Request url is invalid. - - - The requested verb is not supported. - - - The input authorization token can't serve the request. The wrong key is being used or the expected payload is not built as per the protocol. For more info: https://aka.ms/cosmosdb-tsg-unauthorized. Server used the following payload to sign: '{0}' - - - Required Header authorization is missing. Ensure a valid Authorization token is passed. - - - Required property {0} is not specified in the request. - - - Required header '{0}' is not specified in the request. - - - Required query variable '{0}' is not specified in the request. - - - Property '{0}' integer value must be greater than or equal to zero. - - - Entity with the specified id does not exist in the system. More info: https://aka.ms/cosmosdb-tsg-not-found - - - Selected partition is full, please try insert in different partition. - - - Property '{0}' integer value must be greater than zero. - - - Operation cannot be performed because one of the specified precondition is not met. - - - Unable to resolve primary endpoint for partition {0} for service {1}. - - - Property '{0}' is not found in the document. - - - Database account was created successfully, but the following regions failed to be added to account: < br/ > - - - Database account creation failed. Operation Id: {0}, Error : {1} - - - {0} : Operation Id : {1}, Error : {2} < br/ > - - - Read Quorum size of {0} is not met for the request. - - - Replica at index '{0}' is currently unavailable. - - - Consistency Level '{0}' requested via header '{1}' is not supported by this service endpoint. Please contact the service administrator. - - - The size of the response exceeded the maximum allowed size, limit the response size by specifying smaller value for '{0}' header. - - - Request timed out. More info: https://aka.ms/cosmosdb-tsg-request-timeout - - - Retry the request. - - - The size of the request exceeded the maximum allowed size. - - - Unable to resolve secondary endpoint for partition {0} for service {1}. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable - - - The authorization token is not valid at the current time. Please create another token and retry (token start time: {0}, token expiry time: {1}, current server time: {2}). - - - The request rate is too large. Please retry after sometime. Learn more: http://aka.ms/cosmosdb-error-429 - - - Unable to authenticate the request. The request requires valid user authentication. - - - Operation not permitted as consistency level is set to {0}. Expected {1}. - - - Value '{0}' specified for protocol is unsupported. - - - Failed to generate id for resourceType = {0}, partitionIndex = {1}, serviceIndex = {2}, partitionCount = {3}. - - - Attempt to process the request timed out at remote server. - - - Unable to continue without atleast a single token in the resource tokens input collection. - - - Authorization token mandates Date headers. Please pass in RFC 1123 style date format. - - - Value for {0} should be greater than 0 - - - Requested Operation Status = {0} is invalid. - - - Indexing Hints are not supported in this deployment. - - - Changing Root Indexing Policy is not supported in this deployment. - - - The resource name presented contains invalid character '{0}'. - - - The resource name can't end with space. - - - ConsistencyLevel {0} specified in the request is invalid when service is configured with consistency level {1}. Ensure the request consistency level is not stronger than the service consistency level. - - - Requested ResourceType {0} passed as generic argument should be same as the one specified by ResourceType member {1} - - - Only one manualPrivateLinkServiceConnection or one privateLinkServiceConnection is supported - - - Only one privateLinkServiceProxy is supported - - - Only one groupId is supported - - - GroupId {0} is not supported - - - MaxStalenessInterval should be greater than or equal to {0} sec and less than or equal to {1} sec - - - List of supplied locations is invalid - - - Failover priority value {0} supplied for region {1} is invalid - - - Resource kind {0} is unknown - - - Resource kind {0} is invalid - - - Resource type {0} is unknown - - - Resource Url path {0} is invalid. - - - Unable to find free connection - - - Unexpected operator {0} . - - - Star and slash should have no arguments. - - - Resource {0} is invalid for adding owner resource record - - - {0} should have {1} argument. - - - No graft point - - - String agument {0} is null or empty - - - Unsupported token type {0} - - - Unsupported entity type {0} - - - Cannot find messageId header - - - Key type {0} is unsupported - - - System key can only access replica root - - - Duplicate correlation id generated - - - Correlation ID not found in response - - - Channel is closed - - - MaxStalenessPrefix should be greater than or equal to {0} and less than or equal to {1} - - - Invalid response from upstream server or upstream server request failed. - - - Resource type {0} is not supported by ResourceIdPartitioner - - - Invalid value {0} passed for enum {1} - - - Service at index {0} not found. - - - Service reserved bits can not be more than 24. Otherwise it overlaps with the collection/user multiplexing bit - - - NamingProperty {0} not found - - - ResourceIdPolicy {0} is not supported - - - Invalid version format for {0}. Input Version {1} - - - Expecting DateTime value. - - - Expecting reader to read Integer - - - Expecting reader value to be compatible with double conversion. - - - Reached the pre-approved storage limit for the database account. Please contact Azure support to increase this limit. - - - GraphAPICompute Service cannot be deleted. - - - Database Account {0} does not exist - - - Strong consistency level cannot be specified with async replication. Either change the replication policy 'AsyncReplication' to false or relax the consistency level. - - - ResourceType {0} is unexpected. - - - The permission mode provided in the authorization token doesn't provide sufficient permissions. - - - ResourceId {0} of type {1} is not a valid resource Id. - - - OfferType {0} specified in the request is invalid. Please refer to offer documentation and specify a valid offer type. - - - Invalid API version. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK. - - - The requested region '{0}' is not supported. - - - The requested region '{0}' is not supported for '{1}' cluster creation. - - - Could not find service hosting DocumentCollection with ResourceId {0} - - - Message: {0} - - - {0}, Request URI: {1}, RequestStats: {2}, SDK: {3} - - - {0}, Local IP: {1} - - - The requested rollback kind '{0}' is not supported. - - - Federation system key kind {0} is invalid - - - Property {0} can not be assigned to null. - - - The specified value {0} of the index kind is invalid. - - - The index spec format is invalid. - - - The specified document collection is invalid. - - - The input PageSize {0} is invalid. Ensure to pass a valid page size which must be a positive integer or -1 for a dynamic page size. - - - Received invalid index transformation progress values from all the replicas. - - - Target for the request is invalid - - - PartitionKey value must be supplied for this operation. - - - Unsupported PartitionKey value component '{0}'. Numeric, string, bool, null, Undefined are the only supported types. - - - Cannot deserialize PartitionKey value '{0}' - - - Cross partition query is required but disabled. Please set x-ms-documentdb-query-enablecrosspartition to true, specify x-ms-documentdb-partitionkey, or revise your query to avoid this exception. - - - PartitionKey has fewer components than defined the collection resource. - - - Partition key {0} is invalid. - - - Subpartitioning is only supported for Hash V2. - - - Subpartitioning is only supported for atmost 3 partition paths - - - The value of offer throughput specified is invalid. Please enter valid positive integer. - - - Reading or replacing offers is not supported for serverless accounts. - - - The value of offer throughput policy specified is invalid. - - - The value of offer throughput specified exceeded supported maximum throughput for Fixed size container. Please enter value less than {0}. - - - For containers migrated from fixed to unlimited, scale operation can be performed only if the container has documents populated with partition key. Please retry the throughput scale operation after populating documents with partition key. Please see https://aka.ms/migrate-to-partitioned-collection for more information. - - - The value of offer throughput specified is invalid. Please specify a value between {0} and {1} inclusive in increments of {2}. Please contact https://azure.microsoft.com/support to request limit increases beyond {1} RU/s. - - - Current maximum throughput per collection is {0}. Please contact Azure support to increase it. - - - Script request has invalid body. - - - Upserts for scripts in collections with multiple partitions are not supported. - - - Changing id of a script in collections with multiple partitions is not supported. - - - Offer type and throughput cannot both be specified. - - - Offer throughput and autopilot settings cannot both be specified. - - - Autopilot tier and AutoPilotSettings cannot both be specified. - - - Autopilot autoupgrade is not supported for non-partitioned collections. - - - Throughput of this collection cannot be more than {0}, as was provisioned during collection creation time. - - - The session token provided '{0}' is invalid. - - - The provided cross partition query can not be directly served by the gateway. This is a first chance (internal) exception that all newer clients will know how to handle gracefully. This exception is traced, but unless you see it bubble up as an exception (which only happens on older SDK clients), then you can safely ignore this message. - - - Program requires to run in 64 bit for elastic query feature to work. Please switch your program to 64 bit or use Gateway connectivity mode. - - - PartitionKeyRangeId is absent in the context. - - - Bounding box must have an even number of coordinates and more than 3. - - - Spatial operations can be used in Linq expressions only and are evaluated in Azure CosmosDB server. - - - Coordinate Reference System specified in GeoJSON is invalid. - - - Failed to deserialize Geometry object because 'type' property is either absent or has invalid value. - - - Spatial position must have at least two coordinates. - - - Atleast single region must be specified in PreferredLocation list when automatic failover is disabled. - - - This account already has one backup interval capability. - - - This account already has one backup retention capability. - - - The supplied offer version {0} is not supported. Please specify either a blank version, 'V1' or 'V2'. - - - Unexpected offer version {0} from store. - - - The Offer Version 'V1' is not supported since the associated collection is already a partitioned collection. Please use offer version 'V2'. - - - The value of offer throughput specified is invalid. Please specify a value between {0} and {1}, or between {2} and {3} inclusive in increments of {4}. Please contact https://azure.microsoft.com/support to request limit increases beyond {3} RU/s. - - - Offer type is not supported with Offer version 'V2' and above. - - - Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document. - - - The required field Content is missing in Offer version v2. - - - Routing map is not complete. - - - The read session is not available for the input session token. - - - Cannot execute cross partition order-by queries on mix types. Consider using IS_STRING/IS_NUMBER to get around this exception. Expect type: {0}. Actual type: {1}. Item value: {2}. - - - Document Query Execution Context is done. - - - Not allowed to force delete federation in this environment. - - - x-ms-documentdb-partitionkeyrangeid header contains invalid value '{0}'. - - - Unexpected operation type {0} for routing requests for multiple partitions. - - - PartitionKeyRange with id '{0}' in collection '{1}' doesn't exist. - - - Cannot replace an offer with version {0} with version {1} - - - IpAddress {0} is blocked by Policy - - - Collection create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection. - - - Invalid Continuation Token - - - For partitioned collection, either ChangeFeedOptions.PartitionKeyRangeId or ChangeFeedOptions.PartitionKey must be specified. - - - Cannot offline a write region that has zero read regions configured. There needs to be atleast one read region to failover to. - - - Cross partition query with aggregate functions is not supported. - - - Query that expects full results from aggregate functions is not supported. - - - The input continuation token size limit {0} is invalid. Please pass in a valid continuation token size limit which must be a positive integer. - - - PartitionKey has more components than defined the collection resource. - - - StartTime cannot have DateTimeKind.Unspecified. - - - Federation {0} in region {1} is not found - - - The value of offer IsRUPerMinuteThroughputEnabled specified is invalid. Please specify a boolean value. - - - The value of BackgroundTaskMaxAllowedThroughputPercent specified is invalid. Please specify a valid percentage. - - - Cannot offline write region when automatic failover is not enabled - - - Federation {0} and region {1} are not matching. - - - Cannot add additional regions, since database account provision failed. - - - Global Strong write barrier has not been met for the request. - - - At this time, only write operations made from the MongoDB SDKs are supported. Modifications to MongoDB collections using other SDKs is temporarily blocked. - - - Missing a closing quote (") in JSON. - - - Encountered a value that was not a JSON field name. - - - Invalid parameter in JSON. - - - Encountered a number that was too long for a JSON number. - - - Missing a name separator (":") in JSON. - - - Encountered an unexpected JSON token. - - - Read a JSON end array ("]") symbol without a matching JSON start array symbol ("["). - - - Read a JSON end object ("}") symbol without a matching JSON start object symbol ("{"). - - - Encountered an element that is not a valid JSON value (false / null / true / object / array / number / string) - - - Read a JSON name separator (":") symbol without a corresponding field name. - - - Read a JSON name separator (",") symbol without a preceding JSON value. - - - Missing an end object ("}") symbol in JSON. - - - Missing an end array ("]") symbol in JSON. - - - Encountered a value that was not a JSON string. - - - Exceeded the maximum level of nesting for JSON. - - - Invalid escape character in JSON. - - - Invalid Unicode escape sequence in JSON. - - - Invalid string character in JSON. - - - Invalid number in JSON. - - - Encountered a value that was not a JSON number. - - - Encountered a number that exceeded the range for JSON numbers. - - - Missing a JSON property. - - - Encountered a JSON property name after another JSON property name. - - - Tried to write a JSON object end symbol ("}") without first opening with a JSON object start symbol ("{"). - - - Tried to write a JSON end array (“]“) symbol without a matching array start symbol (“[“). - - - Either a JSON property array or object was not started. - - - Encountered a JSON property name without a corresponding property value - - - Failed to register JsonTokenType: {0} - - - Unexpected JsonSerializationFormat: {0} - - - {0} is not supported for the target subscription - - - PartitionKey and PartitionKeyRangeId cannot be specified at the same time in ChangeFeedOptions. - - - Feature {0} is not supported for Multi-region Account - - - Feature {0} is not supported in {1} region - - - Materialized Views are not supported on account with zone redundant region - - - Database and Write Location are not matching - - - Empty Virtual Network Resource Guid - - - Specified Virtual Network Rules list is empty - - - Invalid API version for {0}. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK. - - - AudienceKind is Invalid - - - Invalid Audience Resource Type - - - Distict query requires a matching order by in order to return a continuation token. -If you would like to serve this query through continuation tokens, then please rewrite the query in the form 'SELECT DISTINCT VALUE c.blah FROM c ORDER BY c.blah' and please make sure that there is a range index on 'c.blah'. - - - Database create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection.. - - - The specified document collection is invalid.. - - - Offer replace request conflicted. - - - The value of offer IsAutoScaleEnabled specified is invalid. Please specify a boolean value. - - - The value of OfferAutoScaleMode specified is invalid. Please specify a valid auto scale mode. - - - Autopilot of non-partitioned collections is not supported. Please specify a partition key. - - - Unauthorized Auto-Scale Request. - - - Auto-Scale Setting Change With User Auth Is Disallowed. - - - Compared session tokens '{0}' and '{1}' has unexpected regions. - - - Cannot specify partition key range or partition key for resource that is not partitioned. - - - Invalid mode '{0}' for setting '{1}'. Mode expected is '{2}'. - - - Storage Service index {0} for media account {1} must be within byte range (inclusive). - - - Unauthorized Offer Replace Request. - - - {0} api is not supported for this database account - - - Cannot enable 'enableMultipleWriteLocations' without also enabling 'canEnableMultipleWriteLocations'. - - - Cannot disable 'canEnableMultipleWriteLocations' flag once it has been enabled. - - - Cannot enable 'canEnableMultipleWriteLocations' flag once account has been created with it disabled. - - - A client transport error occurred: {0} - - - Failed to connect to the remote endpoint. - - - DNS resolution failed. - - - The resource that is being accessed is locked. - - - An unknown client transport error has occurred. - - - The channel multiplexer has shut down. - - - Failed to read the server response. - - - The connection failed. - - - The remote system closed the connection. - - - Sending the request failed. - - - SSL negotiation failed. - - - The response body length is too large. Body length: {0} bytes. Connection: {1} - - - The response total header length is too large. Header length: {0} bytes. Connection: {1} - - - Invalid response total header length. Expected {0} bytes. Received {1} bytes. Connection: {2} - - - The transport request ID is missing from the server response. - - - The transport client failed to open a connection. See the inner exception for details. - - - The transport client timed out when opening a connection. See the inner exception for details. - - - The connection attempt timed out. - - - DNS resolution timed out. - - - The request timed out while waiting for a server response. - - - The request timed out. See the inner exception for details. - - - Acquiring the send stream lock timed out. - - - Sending the request timed out. - - - SSL negotiation timed out. - - - The transport protocol negotiation timed out. See the inner exception for details. - - - Invalid CORS rule. At least one allowed origin is required. - - - Invalid CORS rules. Only one rule is supported. - - - Invalid CORS rule. The origin '{0}' is not a well formed origin.. - - - Invalid CORS rule. Wildcards are not supported. - - - InvalidCORS rule. The origin '{0}' is an invalid origin. A valid rigin should not include a uri path. - - - The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. Please check for client resource starvation issues and verify connectivity between client and server. More info: https://aka.ms/cosmosdb-tsg-service-unavailable - - - The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU was overloaded during the attempted request. More info: https://aka.ms/CosmosDB/sql/errors/net/high-cpu - - - Either PartitionKey or EffectivePartitionKey are expected. - - - PartitionKeyRangeId is not expected. - - - Zone Redundant Accounts are not supported in {0} Location yet. Please try other locations. - - - Serverless accounts do not support multiple write locations(i.e. EnableMultipleWriteLocations=true). - - - "Availability Zone on a multi region account requires multi master to be enabled. Please enable Multi-Master on the database account to proceed." - - - Serverless accounts do not support multiple regions. - - - "Operation '{0}' on resource '{1}' is not allowed through Azure Cosmos DB endpoint. Please switch on such operations for your account, or perform this operation through Azure Resource Manager, Azure Portal, Azure CLI or Azure Powershell" - - - Connection is too busy. Please retry after sometime or open more connections. - - - "{0} capability cannot be specified with {1} ." - - - "{0} capability is not allowed with kind={1}" - - - "Update of {0} capability is not allowed." - - - Autopilot is currently not supported on shared throughput database. - - - Accounts configured with default consistency level as 'Strong' cannot be enabled for multiple write locations(i.e. EnableMultipleWriteLocations=true). Consider relaxing default consistency level of the account to enable multiple write locations. - - - This account already has EnableMultipleWriteLocations flag set to {0}". - - - Partition key path {0} is invalid for Gremlin API. The path cannot be '/id', '/label' or a nested path such as '/key/path'. - - - Please provide non-negative value for UpdateMaxthroughputEverProvisioned. - - - Provided Resource Kind {0} to ReEncrypt is not expected - - - Storage analytics is not enabled for this account. Ensure storage analytics is enabled before retrying. - - - Collection is not yet available for read. Please retry in some time. - - - Free tier has already been applied to another Azure Cosmos DB account in this subscription. To apply free tier to this account, you can select another subscription for this account or delete the existing free tier account. You can have up to one free tier account per subscription. - - - Free tier is not supported for Internal subscriptions. - - - DataTransfer service is not available in region [{0}]. - - - Cannot update FreeTier property for existing account. - - - Request is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on resource [{2}]. Learn more: https://aka.ms/cosmos-native-rbac. - - - Request for Read DatabaseAccount is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on any scope. Learn more: https://aka.ms/cosmos-native-rbac. - - - This could be because the user's group memberships were not present in the AAD token. - - - The given request [{0} {1}] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac. - - - Failed to validate AAD identity since the authenticator is unavailable. - - - Failed to validate AAD identity since the authorizer is unavailable. - - - Failed to update the AAD Public Keys with value {0}. Exception: {1}. - - - Missing '_id' index while creating a MongoDB api collection. - - - Partition key path {0} is invalid for MongoDB API. - - - "The create request is not allowed since it does not specify the schema for container '{0}'. - - - The container replace request is not allowed since it removes the schema policy from the container {0}. - - - The container replace request is not allowed since it removes the Cassandra conflict resolution policy from the container {0}. - - - The container create request is not allowed since it does not contain the Cassandra conflict resolution policy specified for the container {0}. - - - Invalid type system '{0}' specified for container {1}. - - - Type system must be specified for the container {0}. - - - Auto upgrade policy is not supported for MongDB resources. - - - Policy type is invalid. - - - Updating offer to autoscale throughput is not allowed. Please invoke migration API to migrate this offer. - - - Updating offer to manually provisioned throughput is not allowed. Please invoke migration API to migrate this offer. - - - Resource id cannot be empty. - - - System database account {0} delete is not supported through this endpoint. - - - Only system database account delete is supported through this endpoint. Supplied account {0} - - - System database account with name {0} and type {1} not found. - - - Invalid store type specified {0}. - - - SAS Token Authentication is disabled for this account. Please contact Azure Support [https://azure.microsoft.com/support] to enable it. - - - Revoke/Grant is not allowed as the Account status is: {0}. - - - The TCP channel timed out on waiting to open. - - - Resource tokens are not supported by the Dedicated Gateway endpoint. - - - AAD tokens are not supported by the Dedicated Gateway endpoint. - - - Local Authorization is disabled. Use an AAD token to authorize all requests. - - - The potential total throughput of this operation exceeds the total throughput limit set for this account. Aborting request. - - - The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU has thread starvation. - - - Cannot authorize request since the [User ID] to authorize was not found. - - - Cannot authorize request since the [Action] to authorize was not found. - - - Cross tenant CMK database account doesn't support using delegated identity as the default identity. - - - System database account {0} cannot be created with Continuous backup mode - {0} = GlobalDatabaseAccountId - - - The server encountered an unexpected condition that prevented it from fulfilling the Azure Key Vault resource request. - - - The provided Azure Key Vault resource key or cert URI does not follow the expected format. - - - The provided Azure Key Vault resource secret URI does not follow the expected format. - - - Error contacting the Azure Key Vault resource. Please try again. - - - The remote name could not be resolved for the Azure Key Vault resource. Please provide a valid URI for an existing Key vault. - - - Could not find any secret with the .pem extension related to the provided certificate. - - - The Input provided is not a valid base 64 string. - - - Failed to acquire the access token needed to access the Azure Key Vault resource. Please verify that the tenant has all corresponding permissions assigned. - - - Unexpected status code for first Azure Key Vault Access. First request to get Azure Key Vault metadata should always return Unauthorized. - - - The expected scope array should be of length 1. Instead received scope with length {0}. - - - The requested scope is not a well formed URI string. - - - The requested scope is not https. - - - The requested scope contains unexpected segments. - - - Cannot perform failover as it is disabled for the account. - - - This partition key definition kind is not supported for partial partition key operations - - - Collection name '{0}' is invalid for MongoDB API. - - - Database name '{0}' is invalid for MongoDB API. - - - There cannot be duplicate physical partition ids in x-ms-cosmos-target-partition-throughput-info header. - - - There cannot be duplicate physical partition ids in x-ms-cosmos-source-partition-throughput-info header. - - - There cannot be a common physical partition id both in x-ms-cosmos-target-partition-throughput-info and x-ms-cosmos-source-partition-throughput-info header. Encountered {0} - - - One of the source or target physical partition id doesn't exist. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. The SDK failed to connect to the service. Please check your networking configuration. - - - The requested region '{0}' does not support AZ provisioning yet. Please try other regions or disable zone redundancy for this region. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. There is high CPU detected on your client machine. Requests are more likely to timeout when CPU exceeds 90%. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Thread starvation or thread-pool blocking detected. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Server returned a 410 response. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Server returned a 503 response. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Partition reconfiguration exceeded retry limit. Please contact support with the full exception. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Unhandled partition split. Please contact support with the full exception. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Could not achieve backend quorum for Strong or Bounded Staleness after barrier requests. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Container was re-created, exceeded retries to resolve new identifier. Please contact support with the full exception. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Store (backend) returned an invalid response. Please contact support with the full exception. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Unhandled partition split. Please contact support with the full exception. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Could not achieve backend quorum. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Network timeout or connectivity failure. - - - Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Continuous connectivity failures. Client cannot connect after multiple retries. Please check your networking configuration - - - "{0} capability is not compatible with mongo ServerVersion={1} accounts." - - - Request is blocked because ResourceId [{0}] cannot be resolved. Principal = [{1}], Action = [{2}], ResourceType = [{3}]. - - - The operation is only supported for Serverless accounts, per-partition throughput cannot be updated directly for provisioned accounts. - - - Cross-tenant CMK is not supported with First Party identities as Default identities. Please use an User Assigned identity instead. - - - Cross-tenant CMK is not supported with System Assigned identities as Default identities. Please use an User Assigned Identity instead. - - - The CapUncapMetadata action '{0}' is not currently supported. - - - The given default identity for {0} is not valid. The format for the default identity is not valid, please use 'FirstPartyIdentity'/'SystemAssignedIdentity'/'UserAssignedIdentity=<UA_resource_id>' - - - The given default identity for {0} is not valid. The default identity points to a delegated identity that does not exist in {0}. - - - The given default identity for {0} is not valid. The default identity points to a system identity that does not exist in {0}. - - - The given default identity for {0} is not valid. The default identity points to an user identity that does not exist in {0}. - - - Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). - - - Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). - - - Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). - - - Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). - - - Access to your account is currently revoked because the correspondent key is not found on the specified Key Vault; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). - - - Access to your account is currently revoked because the correspondent Azure Key Vault was not found; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). - - - Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). - - - Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). - - - Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). - - - Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide - - - Access to the configured customer managed key confirmed. - - - Web socket requests are not supported - - - Sorry, we are currently experiencing high demand in {0} region, and cannot fulfill your request at this time. Please retry after sometime. If the problem persists, please reach out to support. - {0} = Location - - - Enable TieredStorageV1 and Enable Multiple write locations are not supported together on GlobalDatabaseAccount. - - - Dynamic Data Masking is not supported with Continuous Backup/Analytical Store/Materialized View/Full Fidelity Change Feed. - - - Dynamic Data Masking Policy is not supported on this account type. - - - Enable OnlyColdStorageContainersInAccount V1 and EnableMaterializedViews are not supported together on GlobalDatabaseAccount. - - - The CapUncapMetadata source '{0}' is invalid. - - - The federation document for the federation {0} is in an invalid format. - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + One of the input values is invalid. + + + Request url is invalid. + + + Cannot remove write region for account {0}. Please issue delete on the account to remove write region + + + Add or Remove region operation failed. + + + Service is currently unavailable, please retry after a while. If this problem persists please contact support. + + + Value specified in the "{0}" header is incompatible with value specified in the "{1}" header of the request. + + + Error occurred while deserializing content '{0}'. + + + Cannot add regions to this account type. + + + Cannot set EnableMultipleWriteLocations on this account type. + + + Pitr is not supported on this account type. + + + Cannot set DisableKeyBasedMetadataWriteAccess on this account type. + + + MaterializedViews is not supported on this account type. + + + Full Fidelity Change Feed is not supported on this account type. + + + CassandraConnector not supported for this account type. + + + Free Tier is not supported on this account type. + + + Analytical Storage is not supported on this account type. + + + Cannot set VirtualNetworkFilter on this account type. + + + Serverless offer is not supported on this account type. + + + Cannot set IpRangeFilter values on this account type. + + + Unable to retrieve address of endpoint '{0}' from the address '{1}' + + + Entity with the specified id already exists in the system. + + + Request is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden + + + Request originated from IP {0} through public internet. This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden + + + Request originated from VNET through service endpoint. This is blocked by your Cosmos DB account firewall settings. More info: https://aka.ms/cosmosdb-tsg-forbidden + + + Request received through private endpoint. It is blocked because either your account does not have private endpoint configured, or it is not from the private endpoint that your account is configured with. More info: https://aka.ms/cosmosdb-tsg-forbidden + + + The requested resource is no longer available at the server. + + + Insufficient permissions provided in the authorization header for the corresponding request. Please retry with another authorization header. + + + Unknown server error occurred when processing this request. + + + Authorization header doesn't confirm to the required format. Please verify and try again. + + + The backend response was not in the correct format. + + + The input date header is invalid format. Please pass in RFC 1123 style date format. + + + Value '{0}' specified for the header '{1}' is invalid. + + + Command is not supported by backend + + + Query '{0}' specified is either invalid or unsupported. + + + Value '{0}' specified for the query '{1}' is invalid. + + + Failed to parse the value '{0}' as ResourceId. + + + The request path {0} is invalid. + + + The value '{0}' specified for query '{1}' is invalid. + + + Staleness Policy specified is invalid. Ensure both MaxPrefix and MaxStalenessIntervalInSeconds are both 0 or both not zero. + + + Request url is invalid. + + + The requested verb is not supported. + + + The input authorization token can't serve the request. The wrong key is being used or the expected payload is not built as per the protocol. For more info: https://aka.ms/cosmosdb-tsg-unauthorized. Server used the following payload to sign: '{0}' + + + Required Header authorization is missing. Ensure a valid Authorization token is passed. + + + Required property {0} is not specified in the request. + + + Required header '{0}' is not specified in the request. + + + Required query variable '{0}' is not specified in the request. + + + Property '{0}' integer value must be greater than or equal to zero. + + + Entity with the specified id does not exist in the system. More info: https://aka.ms/cosmosdb-tsg-not-found + + + Selected partition is full, please try insert in different partition. + + + Property '{0}' integer value must be greater than zero. + + + Operation cannot be performed because one of the specified precondition is not met. + + + Unable to resolve primary endpoint for partition {0} for service {1}. + + + Property '{0}' is not found in the document. + + + Database account was created successfully, but the following regions failed to be added to account: < br/ > + + + Database account creation failed. Operation Id: {0}, Error : {1} + + + {0} : Operation Id : {1}, Error : {2} < br/ > + + + Read Quorum size of {0} is not met for the request. + + + Replica at index '{0}' is currently unavailable. + + + Consistency Level '{0}' requested via header '{1}' is not supported by this service endpoint. Please contact the service administrator. + + + The size of the response exceeded the maximum allowed size, limit the response size by specifying smaller value for '{0}' header. + + + Request timed out. More info: https://aka.ms/cosmosdb-tsg-request-timeout + + + Retry the request. + + + The size of the request exceeded the maximum allowed size. + + + Unable to resolve secondary endpoint for partition {0} for service {1}. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable + + + The authorization token is not valid at the current time. Please create another token and retry (token start time: {0}, token expiry time: {1}, current server time: {2}). + + + The request rate is too large. Please retry after sometime. Learn more: http://aka.ms/cosmosdb-error-429 + + + Unable to authenticate the request. The request requires valid user authentication. + + + Operation not permitted as consistency level is set to {0}. Expected {1}. + + + Value '{0}' specified for protocol is unsupported. + + + Failed to generate id for resourceType = {0}, partitionIndex = {1}, serviceIndex = {2}, partitionCount = {3}. + + + Attempt to process the request timed out at remote server. + + + Unable to continue without atleast a single token in the resource tokens input collection. + + + Authorization token mandates Date headers. Please pass in RFC 1123 style date format. + + + Value for {0} should be greater than 0 + + + Requested Operation Status = {0} is invalid. + + + Indexing Hints are not supported in this deployment. + + + Changing Root Indexing Policy is not supported in this deployment. + + + The resource name presented contains invalid character '{0}'. + + + The resource name can't end with space. + + + ConsistencyLevel {0} specified in the request is invalid when service is configured with consistency level {1}. Ensure the request consistency level is not stronger than the service consistency level. + + + Requested ResourceType {0} passed as generic argument should be same as the one specified by ResourceType member {1} + + + Only one manualPrivateLinkServiceConnection or one privateLinkServiceConnection is supported + + + Only one privateLinkServiceProxy is supported + + + Only one groupId is supported + + + GroupId {0} is not supported + + + MaxStalenessInterval should be greater than or equal to {0} sec and less than or equal to {1} sec + + + List of supplied locations is invalid + + + Failover priority value {0} supplied for region {1} is invalid + + + Resource kind {0} is unknown + + + Resource kind {0} is invalid + + + Resource type {0} is unknown + + + Resource Url path {0} is invalid. + + + Unable to find free connection + + + Unexpected operator {0} . + + + Star and slash should have no arguments. + + + Resource {0} is invalid for adding owner resource record + + + {0} should have {1} argument. + + + No graft point + + + String agument {0} is null or empty + + + Unsupported token type {0} + + + Unsupported entity type {0} + + + Cannot find messageId header + + + Key type {0} is unsupported + + + System key can only access replica root + + + Duplicate correlation id generated + + + Correlation ID not found in response + + + Channel is closed + + + MaxStalenessPrefix should be greater than or equal to {0} and less than or equal to {1} + + + Invalid response from upstream server or upstream server request failed. + + + Resource type {0} is not supported by ResourceIdPartitioner + + + Invalid value {0} passed for enum {1} + + + Service at index {0} not found. + + + Service reserved bits can not be more than 24. Otherwise it overlaps with the collection/user multiplexing bit + + + NamingProperty {0} not found + + + ResourceIdPolicy {0} is not supported + + + Invalid version format for {0}. Input Version {1} + + + Expecting DateTime value. + + + Expecting reader to read Integer + + + Expecting reader value to be compatible with double conversion. + + + Reached the pre-approved storage limit for the database account. Please contact Azure support to increase this limit. + + + GraphAPICompute Service cannot be deleted. + + + Database Account {0} does not exist + + + Strong consistency level cannot be specified with async replication. Either change the replication policy 'AsyncReplication' to false or relax the consistency level. + + + ResourceType {0} is unexpected. + + + The permission mode provided in the authorization token doesn't provide sufficient permissions. + + + ResourceId {0} of type {1} is not a valid resource Id. + + + OfferType {0} specified in the request is invalid. Please refer to offer documentation and specify a valid offer type. + + + Invalid API version. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK. + + + The requested region '{0}' is not supported. + + + The requested region '{0}' is not supported for '{1}' cluster creation. + + + Could not find service hosting DocumentCollection with ResourceId {0} + + + Message: {0} + + + {0}, Request URI: {1}, RequestStats: {2}, SDK: {3} + + + {0}, Local IP: {1} + + + The requested rollback kind '{0}' is not supported. + + + Federation system key kind {0} is invalid + + + Property {0} can not be assigned to null. + + + The specified value {0} of the index kind is invalid. + + + The index spec format is invalid. + + + The specified document collection is invalid. + + + The input PageSize {0} is invalid. Ensure to pass a valid page size which must be a positive integer or -1 for a dynamic page size. + + + Received invalid index transformation progress values from all the replicas. + + + Target for the request is invalid + + + PartitionKey value must be supplied for this operation. + + + Unsupported PartitionKey value component '{0}'. Numeric, string, bool, null, Undefined are the only supported types. + + + Cannot deserialize PartitionKey value '{0}' + + + Cross partition query is required but disabled. Please set x-ms-documentdb-query-enablecrosspartition to true, specify x-ms-documentdb-partitionkey, or revise your query to avoid this exception. + + + PartitionKey has fewer components than defined the collection resource. + + + Partition key {0} is invalid. + + + Subpartitioning is only supported for Hash V2. + + + Subpartitioning is only supported for atmost 3 partition paths + + + The value of offer throughput specified is invalid. Please enter valid positive integer. + + + Reading or replacing offers is not supported for serverless accounts. + + + The value of offer throughput policy specified is invalid. + + + The value of offer throughput specified exceeded supported maximum throughput for Fixed size container. Please enter value less than {0}. + + + For containers migrated from fixed to unlimited, scale operation can be performed only if the container has documents populated with partition key. Please retry the throughput scale operation after populating documents with partition key. Please see https://aka.ms/migrate-to-partitioned-collection for more information. + + + The value of offer throughput specified is invalid. Please specify a value between {0} and {1} inclusive in increments of {2}. Please contact https://azure.microsoft.com/support to request limit increases beyond {1} RU/s. + + + Current maximum throughput per collection is {0}. Please contact Azure support to increase it. + + + Script request has invalid body. + + + Upserts for scripts in collections with multiple partitions are not supported. + + + Changing id of a script in collections with multiple partitions is not supported. + + + Offer type and throughput cannot both be specified. + + + Offer throughput and autopilot settings cannot both be specified. + + + Autopilot tier and AutoPilotSettings cannot both be specified. + + + Autopilot autoupgrade is not supported for non-partitioned collections. + + + Throughput of this collection cannot be more than {0}, as was provisioned during collection creation time. + + + The session token provided '{0}' is invalid. + + + The provided cross partition query can not be directly served by the gateway. This is a first chance (internal) exception that all newer clients will know how to handle gracefully. This exception is traced, but unless you see it bubble up as an exception (which only happens on older SDK clients), then you can safely ignore this message. + + + Program requires to run in 64 bit for elastic query feature to work. Please switch your program to 64 bit or use Gateway connectivity mode. + + + PartitionKeyRangeId is absent in the context. + + + Bounding box must have an even number of coordinates and more than 3. + + + Spatial operations can be used in Linq expressions only and are evaluated in Azure CosmosDB server. + + + Coordinate Reference System specified in GeoJSON is invalid. + + + Failed to deserialize Geometry object because 'type' property is either absent or has invalid value. + + + Spatial position must have at least two coordinates. + + + Atleast single region must be specified in PreferredLocation list when automatic failover is disabled. + + + This account already has one backup interval capability. + + + This account already has one backup retention capability. + + + The supplied offer version {0} is not supported. Please specify either a blank version, 'V1' or 'V2'. + + + Unexpected offer version {0} from store. + + + The Offer Version 'V1' is not supported since the associated collection is already a partitioned collection. Please use offer version 'V2'. + + + The value of offer throughput specified is invalid. Please specify a value between {0} and {1}, or between {2} and {3} inclusive in increments of {4}. Please contact https://azure.microsoft.com/support to request limit increases beyond {3} RU/s. + + + Offer type is not supported with Offer version 'V2' and above. + + + Partition key provided either doesn't correspond to definition in the collection or doesn't match partition key field values specified in the document. + + + The required field Content is missing in Offer version v2. + + + Routing map is not complete. + + + The read session is not available for the input session token. + + + Cannot execute cross partition order-by queries on mix types. Consider using IS_STRING/IS_NUMBER to get around this exception. Expect type: {0}. Actual type: {1}. Item value: {2}. + + + Document Query Execution Context is done. + + + Not allowed to force delete federation in this environment. + + + x-ms-documentdb-partitionkeyrangeid header contains invalid value '{0}'. + + + Unexpected operation type {0} for routing requests for multiple partitions. + + + PartitionKeyRange with id '{0}' in collection '{1}' doesn't exist. + + + Cannot replace an offer with version {0} with version {1} + + + IpAddress {0} is blocked by Policy + + + Collection create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection. + + + Invalid Continuation Token + + + For partitioned collection, either ChangeFeedOptions.PartitionKeyRangeId or ChangeFeedOptions.PartitionKey must be specified. + + + Cannot offline a write region that has zero read regions configured. There needs to be atleast one read region to failover to. + + + Cross partition query with aggregate functions is not supported. + + + Query that expects full results from aggregate functions is not supported. + + + The input continuation token size limit {0} is invalid. Please pass in a valid continuation token size limit which must be a positive integer. + + + PartitionKey has more components than defined the collection resource. + + + StartTime cannot have DateTimeKind.Unspecified. + + + Federation {0} in region {1} is not found + + + The value of offer IsRUPerMinuteThroughputEnabled specified is invalid. Please specify a boolean value. + + + The value of BackgroundTaskMaxAllowedThroughputPercent specified is invalid. Please specify a valid percentage. + + + Cannot offline write region when automatic failover is not enabled + + + Federation {0} and region {1} are not matching. + + + Cannot add additional regions, since database account provision failed. + + + Global Strong write barrier has not been met for the request. + + + At this time, only write operations made from the MongoDB SDKs are supported. Modifications to MongoDB collections using other SDKs is temporarily blocked. + + + Missing a closing quote (") in JSON. + + + Encountered a value that was not a JSON field name. + + + Invalid parameter in JSON. + + + Encountered a number that was too long for a JSON number. + + + Missing a name separator (":") in JSON. + + + Encountered an unexpected JSON token. + + + Read a JSON end array ("]") symbol without a matching JSON start array symbol ("["). + + + Read a JSON end object ("}") symbol without a matching JSON start object symbol ("{"). + + + Encountered an element that is not a valid JSON value (false / null / true / object / array / number / string) + + + Read a JSON name separator (":") symbol without a corresponding field name. + + + Read a JSON name separator (",") symbol without a preceding JSON value. + + + Missing an end object ("}") symbol in JSON. + + + Missing an end array ("]") symbol in JSON. + + + Encountered a value that was not a JSON string. + + + Exceeded the maximum level of nesting for JSON. + + + Invalid escape character in JSON. + + + Invalid Unicode escape sequence in JSON. + + + Invalid string character in JSON. + + + Invalid number in JSON. + + + Encountered a value that was not a JSON number. + + + Encountered a number that exceeded the range for JSON numbers. + + + Missing a JSON property. + + + Encountered a JSON property name after another JSON property name. + + + Tried to write a JSON object end symbol ("}") without first opening with a JSON object start symbol ("{"). + + + Tried to write a JSON end array (“]“) symbol without a matching array start symbol (“[“). + + + Either a JSON property array or object was not started. + + + Encountered a JSON property name without a corresponding property value + + + Failed to register JsonTokenType: {0} + + + Unexpected JsonSerializationFormat: {0} + + + {0} is not supported for the target subscription + + + PartitionKey and PartitionKeyRangeId cannot be specified at the same time in ChangeFeedOptions. + + + Feature {0} is not supported for Multi-region Account + + + Feature {0} is not supported in {1} region + + + Materialized Views are not supported on account with zone redundant region + + + Database and Write Location are not matching + + + Empty Virtual Network Resource Guid + + + Specified Virtual Network Rules list is empty + + + Invalid API version for {0}. Ensure a valid x-ms-version header value is passed. Please update to the latest version of Azure Cosmos DB SDK. + + + AudienceKind is Invalid + + + Invalid Audience Resource Type + + + Distict query requires a matching order by in order to return a continuation token. +If you would like to serve this query through continuation tokens, then please rewrite the query in the form 'SELECT DISTINCT VALUE c.blah FROM c ORDER BY c.blah' and please make sure that there is a range index on 'c.blah'. + + + Database create request conflicted with ongoing add region or failover operation. Ensure to complete region configuration before creating collection.. + + + The specified document collection is invalid.. + + + Offer replace request conflicted. + + + The value of offer IsAutoScaleEnabled specified is invalid. Please specify a boolean value. + + + The value of OfferAutoScaleMode specified is invalid. Please specify a valid auto scale mode. + + + Autopilot of non-partitioned collections is not supported. Please specify a partition key. + + + Unauthorized Auto-Scale Request. + + + Auto-Scale Setting Change With User Auth Is Disallowed. + + + Compared session tokens '{0}' and '{1}' has unexpected regions. + + + Cannot specify partition key range or partition key for resource that is not partitioned. + + + Invalid mode '{0}' for setting '{1}'. Mode expected is '{2}'. + + + Storage Service index {0} for media account {1} must be within byte range (inclusive). + + + Unauthorized Offer Replace Request. + + + {0} api is not supported for this database account + + + Cannot enable 'enableMultipleWriteLocations' without also enabling 'canEnableMultipleWriteLocations'. + + + Cannot disable 'canEnableMultipleWriteLocations' flag once it has been enabled. + + + Cannot enable 'canEnableMultipleWriteLocations' flag once account has been created with it disabled. + + + A client transport error occurred: {0} + + + Failed to connect to the remote endpoint. + + + DNS resolution failed. + + + The resource that is being accessed is locked. + + + An unknown client transport error has occurred. + + + The channel multiplexer has shut down. + + + Failed to read the server response. + + + The connection failed. + + + The remote system closed the connection. + + + Sending the request failed. + + + SSL negotiation failed. + + + The response body length is too large. Body length: {0} bytes. Connection: {1} + + + The response total header length is too large. Header length: {0} bytes. Connection: {1} + + + Invalid response total header length. Expected {0} bytes. Received {1} bytes. Connection: {2} + + + The transport request ID is missing from the server response. + + + The transport client failed to open a connection. See the inner exception for details. + + + The transport client timed out when opening a connection. See the inner exception for details. + + + The connection attempt timed out. + + + DNS resolution timed out. + + + The request timed out while waiting for a server response. + + + The request timed out. See the inner exception for details. + + + Acquiring the send stream lock timed out. + + + Sending the request timed out. + + + SSL negotiation timed out. + + + The transport protocol negotiation timed out. See the inner exception for details. + + + Invalid CORS rule. At least one allowed origin is required. + + + Invalid CORS rules. Only one rule is supported. + + + Invalid CORS rule. The origin '{0}' is not a well formed origin.. + + + Invalid CORS rule. Wildcards are not supported. + + + InvalidCORS rule. The origin '{0}' is an invalid origin. A valid rigin should not include a uri path. + + + The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. Please check for client resource starvation issues and verify connectivity between client and server. More info: https://aka.ms/cosmosdb-tsg-service-unavailable + + + The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU was overloaded during the attempted request. More info: https://aka.ms/CosmosDB/sql/errors/net/high-cpu + + + Either PartitionKey or EffectivePartitionKey are expected. + + + PartitionKeyRangeId is not expected. + + + Zone Redundant Accounts are not supported in {0} Location yet. Please try other locations. + + + Serverless accounts do not support multiple write locations(i.e. EnableMultipleWriteLocations=true). + + + "Availability Zone on a multi region account requires multi master to be enabled. Please enable Multi-Master on the database account to proceed." + + + Serverless accounts do not support multiple regions. + + + "Operation '{0}' on resource '{1}' is not allowed through Azure Cosmos DB endpoint. Please switch on such operations for your account, or perform this operation through Azure Resource Manager, Azure Portal, Azure CLI or Azure Powershell" + + + Connection is too busy. Please retry after sometime or open more connections. + + + "{0} capability cannot be specified with {1} ." + + + "{0} capability is not allowed with kind={1}" + + + "Update of {0} capability is not allowed." + + + Autopilot is currently not supported on shared throughput database. + + + Accounts configured with default consistency level as 'Strong' cannot be enabled for multiple write locations(i.e. EnableMultipleWriteLocations=true). Consider relaxing default consistency level of the account to enable multiple write locations. + + + This account already has EnableMultipleWriteLocations flag set to {0}". + + + Partition key path {0} is invalid for Gremlin API. The path cannot be '/id', '/label' or a nested path such as '/key/path'. + + + Please provide non-negative value for UpdateMaxthroughputEverProvisioned. + + + Provided Resource Kind {0} to ReEncrypt is not expected + + + Storage analytics is not enabled for this account. Ensure storage analytics is enabled before retrying. + + + Collection is not yet available for read. Please retry in some time. + + + Free tier has already been applied to another Azure Cosmos DB account in this subscription. To apply free tier to this account, you can select another subscription for this account or delete the existing free tier account. You can have up to one free tier account per subscription. + + + Free tier is not supported for Internal subscriptions. + + + DataTransfer service is not available in region [{0}]. + + + Cannot update FreeTier property for existing account. + + + Request is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on resource [{2}]. Learn more: https://aka.ms/cosmos-native-rbac. + + + Request for Read DatabaseAccount is blocked because principal [{0}] does not have required RBAC permissions to perform action [{1}] on any scope. Learn more: https://aka.ms/cosmos-native-rbac. + + + This could be because the user's group memberships were not present in the AAD token. + + + The given request [{0} {1}] cannot be authorized by AAD token in data plane. Learn more: https://aka.ms/cosmos-native-rbac. + + + Failed to validate AAD identity since the authenticator is unavailable. + + + Failed to validate AAD identity since the authorizer is unavailable. + + + Failed to update the AAD Public Keys with value {0}. Exception: {1}. + + + Missing '_id' index while creating a MongoDB api collection. + + + Partition key path {0} is invalid for MongoDB API. + + + "The create request is not allowed since it does not specify the schema for container '{0}'. + + + The container replace request is not allowed since it removes the schema policy from the container {0}. + + + The container replace request is not allowed since it removes the Cassandra conflict resolution policy from the container {0}. + + + The container create request is not allowed since it does not contain the Cassandra conflict resolution policy specified for the container {0}. + + + Invalid type system '{0}' specified for container {1}. + + + Type system must be specified for the container {0}. + + + Auto upgrade policy is not supported for MongDB resources. + + + Policy type is invalid. + + + Updating offer to autoscale throughput is not allowed. Please invoke migration API to migrate this offer. + + + Updating offer to manually provisioned throughput is not allowed. Please invoke migration API to migrate this offer. + + + Resource id cannot be empty. + + + System database account {0} delete is not supported through this endpoint. + + + Only system database account delete is supported through this endpoint. Supplied account {0} + + + System database account with name {0} and type {1} not found. + + + Invalid store type specified {0}. + + + SAS Token Authentication is disabled for this account. Please contact Azure Support [https://azure.microsoft.com/support] to enable it. + + + Revoke/Grant is not allowed as the Account status is: {0}. + + + The TCP channel timed out on waiting to open. + + + Resource tokens are not supported by the Dedicated Gateway endpoint. + + + AAD tokens are not supported by the Dedicated Gateway endpoint. + + + Local Authorization is disabled. Use an AAD token to authorize all requests. + + + The potential total throughput of this operation exceeds the total throughput limit set for this account. Aborting request. + + + The request failed because the client was unable to establish connections to {0} endpoints across {1} regions. The client CPU has thread starvation. + + + Cannot authorize request since the [User ID] to authorize was not found. + + + Cannot authorize request since the [Action] to authorize was not found. + + + Cross tenant CMK database account doesn't support using delegated identity as the default identity. + + + System database account {0} cannot be created with Continuous backup mode + {0} = GlobalDatabaseAccountId + + + The server encountered an unexpected condition that prevented it from fulfilling the Azure Key Vault resource request. + + + The provided Azure Key Vault resource key or cert URI does not follow the expected format. + + + The provided Azure Key Vault resource secret URI does not follow the expected format. + + + Error contacting the Azure Key Vault resource. Please try again. + + + The remote name could not be resolved for the Azure Key Vault resource. Please provide a valid URI for an existing Key vault. + + + Could not find any secret with the .pem extension related to the provided certificate. + + + The Input provided is not a valid base 64 string. + + + Failed to acquire the access token needed to access the Azure Key Vault resource. Please verify that the tenant has all corresponding permissions assigned. + + + Unexpected status code for first Azure Key Vault Access. First request to get Azure Key Vault metadata should always return Unauthorized. + + + The expected scope array should be of length 1. Instead received scope with length {0}. + + + The requested scope is not a well formed URI string. + + + The requested scope is not https. + + + The requested scope contains unexpected segments. + + + Cannot perform failover as it is disabled for the account. + + + Cannot Perform failover priority change as it is disabled for the account. + + + This partition key definition kind is not supported for partial partition key operations + + + Collection name '{0}' is invalid for MongoDB API. + + + Database name '{0}' is invalid for MongoDB API. + + + There cannot be duplicate physical partition ids in x-ms-cosmos-target-partition-throughput-info header. + + + There cannot be duplicate physical partition ids in x-ms-cosmos-source-partition-throughput-info header. + + + There cannot be a common physical partition id both in x-ms-cosmos-target-partition-throughput-info and x-ms-cosmos-source-partition-throughput-info header. Encountered {0} + + + One of the source or target physical partition id doesn't exist. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. The SDK failed to connect to the service. Please check your networking configuration. + + + The requested region '{0}' does not support AZ provisioning yet. Please try other regions or disable zone redundancy for this region. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. There is high CPU detected on your client machine. Requests are more likely to timeout when CPU exceeds 90%. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Thread starvation or thread-pool blocking detected. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Server returned a 410 response. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Server returned a 503 response. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Partition reconfiguration exceeded retry limit. Please contact support with the full exception. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Unhandled partition split. Please contact support with the full exception. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Could not achieve backend quorum for Strong or Bounded Staleness after barrier requests. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Container was re-created, exceeded retries to resolve new identifier. Please contact support with the full exception. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Store (backend) returned an invalid response. Please contact support with the full exception. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Unhandled partition split. Please contact support with the full exception. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Could not achieve backend quorum. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Network timeout or connectivity failure. + + + Service is currently unavailable. More info: https://aka.ms/cosmosdb-tsg-service-unavailable. Continuous connectivity failures. Client cannot connect after multiple retries. Please check your networking configuration + + + "{0} capability is not compatible with mongo ServerVersion={1} accounts." + + + Request is blocked because ResourceId [{0}] cannot be resolved. Principal = [{1}], Action = [{2}], ResourceType = [{3}]. + + + The operation is only supported for Serverless accounts, per-partition throughput cannot be updated directly for provisioned accounts. + + + Cross-tenant CMK is not supported with First Party identities as Default identities. Please use an User Assigned identity instead. + + + Cross-tenant CMK is not supported with System Assigned identities as Default identities. Please use an User Assigned Identity instead. + + + The CapUncapMetadata action '{0}' is not currently supported. + + + The given default identity for {0} is not valid. The format for the default identity is not valid, please use 'FirstPartyIdentity'/'SystemAssignedIdentity'/'UserAssignedIdentity=<UA_resource_id>' + + + The given default identity for {0} is not valid. The default identity points to a delegated identity that does not exist in {0}. + + + The given default identity for {0} is not valid. The default identity points to a system identity that does not exist in {0}. + + + The given default identity for {0} is not valid. The default identity points to an user identity that does not exist in {0}. + + + Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). + + + Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). + + + Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). + + + Access to your account is currently revoked because the correspondent key is not found on the specified Key Vault; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). + + + Access to your account is currently revoked because the correspondent Azure Key Vault was not found; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). + + + Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). + + + Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide + + + Access to the configured customer managed key confirmed. + + + Web socket requests are not supported + + + Sorry, we are currently experiencing high demand in {0} region, and cannot fulfill your request at this time. Please retry after sometime. If the problem persists, please reach out to support. + {0} = Location + + + Enable TieredStorageV1 and Enable Multiple write locations are not supported together on GlobalDatabaseAccount. + + + Dynamic Data Masking is not supported with Continuous Backup/Analytical Store/Materialized View/Full Fidelity Change Feed. + + + Dynamic Data Masking Policy is not supported on this account type. + + + Enable OnlyColdStorageContainersInAccount V1 and EnableMaterializedViews are not supported together on GlobalDatabaseAccount. + + + The CapUncapMetadata source '{0}' is invalid. + + + The federation document for the federation {0} is in an invalid format. + + + PerRegionPerPartitionAutoscale is not supported for serverless accounts + + + Encountered an error in the partition migration operation + + + PerRegionPerPartitionAutoscale is not supported on account {0} + + + Found document with an ID greater than {0} bytes. More info: https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-customer-managed-keys-existing-accounts + + + Unexpected error on document scan for CMK Migration. Please retry the operation. More info: https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-customer-managed-keys-existing-accounts + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs index 8659286b3d..147b3872b2 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryCoreRecorder.cs @@ -1,258 +1,258 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Telemetry -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using global::Azure.Core; - using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; - using Microsoft.Azure.Documents; - - /// - /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 - /// - internal struct OpenTelemetryCoreRecorder : IDisposable - { - private const string CosmosDb = "cosmosdb"; - - private readonly DiagnosticScope scope = default; - private readonly CosmosThresholdOptions config = null; - private readonly Activity activity = null; - - private readonly OperationType operationType = OperationType.Invalid; - private readonly string connectionModeCache = null; - - private OpenTelemetryAttributes response = null; - - internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() - { - { typeof(CosmosNullReferenceException), (exception, scope) => CosmosNullReferenceException.RecordOtelAttributes((CosmosNullReferenceException)exception, scope)}, - { typeof(CosmosObjectDisposedException), (exception, scope) => CosmosObjectDisposedException.RecordOtelAttributes((CosmosObjectDisposedException)exception, scope)}, - { typeof(CosmosOperationCanceledException), (exception, scope) => CosmosOperationCanceledException.RecordOtelAttributes((CosmosOperationCanceledException)exception, scope)}, - { typeof(CosmosException), (exception, scope) => CosmosException.RecordOtelAttributes((CosmosException)exception, scope)}, - { typeof(ChangeFeedProcessorUserException), (exception, scope) => ChangeFeedProcessorUserException.RecordOtelAttributes((ChangeFeedProcessorUserException)exception, scope)} - }; - - private OpenTelemetryCoreRecorder(DiagnosticScope scope) - { - this.scope = scope; - this.scope.Start(); - } - - private OpenTelemetryCoreRecorder(string operationName) - { - this.activity = new Activity(operationName); - this.activity.Start(); - } - - private OpenTelemetryCoreRecorder( - DiagnosticScope scope, - string operationName, - string containerName, - string databaseName, - OperationType operationType, - CosmosClientContext clientContext, - CosmosThresholdOptions config) - { - this.scope = scope; - this.config = config; - - this.operationType = operationType; - this.connectionModeCache = Enum.GetName(typeof(ConnectionMode), clientContext.ClientOptions.ConnectionMode); - - if (scope.IsEnabled) - { - this.scope.Start(); - - this.Record( - operationName: operationName, - containerName: containerName, - databaseName: databaseName, - clientContext: clientContext); - } - } - - /// - /// Used for creating parent activity in scenario where there are no listeners at operation level - /// but they are present at network level - /// - public static OpenTelemetryCoreRecorder CreateNetworkLevelParentActivity(DiagnosticScope networkScope) - { - return new OpenTelemetryCoreRecorder(networkScope); - } - - /// - /// Used for creating parent activity in scenario where there are no listeners at operation level and network level - /// - public static OpenTelemetryCoreRecorder CreateParentActivity(string operationName) - { - return new OpenTelemetryCoreRecorder(operationName); - } - - /// - /// Used for creating parent activity in scenario where there are listeners at operation level - /// - public static OpenTelemetryCoreRecorder CreateOperationLevelParentActivity( - DiagnosticScope operationScope, - string operationName, - string containerName, - string databaseName, - Documents.OperationType operationType, - CosmosClientContext clientContext, - CosmosThresholdOptions config) - { - return new OpenTelemetryCoreRecorder( - operationScope, - operationName, - containerName, - databaseName, - operationType, - clientContext, - config); - } - - public bool IsEnabled => this.scope.IsEnabled; - - public void Record(string key, string value) - { - if (this.IsEnabled) - { - this.scope.AddAttribute(key, value); - } - } - - /// - /// Recording information - /// - /// - /// - /// - /// - public void Record( - string operationName, - string containerName, - string databaseName, - CosmosClientContext clientContext) - { - if (this.IsEnabled) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbOperation, operationName); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName); - - // Other information - this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.MachineId, VmMetadataApiHandler.GetMachineId()); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ServerAddress, clientContext.Client?.Endpoint?.Host); - - // Client Information - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, this.connectionModeCache); - } - } - - /// - /// Record attributes from response - /// - /// - public void Record(OpenTelemetryAttributes response) - { - if (this.IsEnabled) - { - this.response = response; - } - } - - /// - /// Record attributes during exception - /// - /// - public void MarkFailed(Exception exception) - { - if (this.IsEnabled) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionStacktrace, exception.StackTrace); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionType, exception.GetType().Name); - - // If Exception is not registered with open Telemetry - if (!OpenTelemetryCoreRecorder.IsExceptionRegistered(exception, this.scope)) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message); - } - - if (exception is not CosmosException || (exception is CosmosException cosmosException - && !DiagnosticsFilterHelper - .IsSuccessfulResponse(cosmosException.StatusCode, cosmosException.SubStatusCode))) - { - this.scope.Failed(exception); - } - } - } - - /// - /// Checking if passed exception is registered with Open telemetry or Not - /// - /// - /// - /// tru/false - internal static bool IsExceptionRegistered(Exception exception, DiagnosticScope scope) - { - foreach (KeyValuePair> registeredExceptionHandlers in OpenTelemetryCoreRecorder.OTelCompatibleExceptions) - { - Type exceptionType = exception.GetType(); - if (registeredExceptionHandlers.Key.IsAssignableFrom(exceptionType)) - { - registeredExceptionHandlers.Value(exception, scope); - - return true; - } - } - - return false; - } - - public void Dispose() - { - if (this.IsEnabled) - { - OperationType operationType - = (this.response == null || this.response?.OperationType == OperationType.Invalid) ? this.operationType : this.response.OperationType; - - this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, Enum.GetName(typeof(OperationType), operationType)); - - if (this.response != null) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, this.response.RequestContentLength); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, this.response.ResponseContentLength); - this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); - this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.SubStatusCode, this.response.SubStatusCode); - this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.RequestCharge, (int)this.response.RequestCharge); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, this.response.ItemCount); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, this.response.ActivityId); - this.scope.AddAttribute(OpenTelemetryAttributeKeys.CorrelatedActivityId, this.response.CorrelatedActivityId); - - if (this.response.Diagnostics != null) - { - this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(this.response.Diagnostics.GetContactedRegions())); - CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, operationType, this.response); - } - - if (!DiagnosticsFilterHelper.IsSuccessfulResponse(this.response.StatusCode, this.response.SubStatusCode)) - { - this.scope.Failed($"{(int)this.response.StatusCode}/{this.response.SubStatusCode}"); - } - } - - this.scope.Dispose(); - } - else - { - this.activity?.Stop(); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using global::Azure.Core; + using Microsoft.Azure.Cosmos.Telemetry.Diagnostics; + using Microsoft.Azure.Documents; + + /// + /// This class is used to add information in an Activity tags ref. https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3058 + /// + internal struct OpenTelemetryCoreRecorder : IDisposable + { + private const string CosmosDb = "cosmosdb"; + + private readonly DiagnosticScope scope = default; + private readonly CosmosThresholdOptions config = null; + private readonly Activity activity = null; + + private readonly OperationType operationType = OperationType.Invalid; + private readonly string connectionModeCache = null; + + private OpenTelemetryAttributes response = null; + + internal static IDictionary> OTelCompatibleExceptions = new Dictionary>() + { + { typeof(CosmosNullReferenceException), (exception, scope) => CosmosNullReferenceException.RecordOtelAttributes((CosmosNullReferenceException)exception, scope)}, + { typeof(CosmosObjectDisposedException), (exception, scope) => CosmosObjectDisposedException.RecordOtelAttributes((CosmosObjectDisposedException)exception, scope)}, + { typeof(CosmosOperationCanceledException), (exception, scope) => CosmosOperationCanceledException.RecordOtelAttributes((CosmosOperationCanceledException)exception, scope)}, + { typeof(CosmosException), (exception, scope) => CosmosException.RecordOtelAttributes((CosmosException)exception, scope)}, + { typeof(ChangeFeedProcessorUserException), (exception, scope) => ChangeFeedProcessorUserException.RecordOtelAttributes((ChangeFeedProcessorUserException)exception, scope)} + }; + + private OpenTelemetryCoreRecorder(DiagnosticScope scope) + { + this.scope = scope; + this.scope.Start(); + } + + private OpenTelemetryCoreRecorder(string operationName) + { + this.activity = new Activity(operationName); + this.activity.Start(); + } + + private OpenTelemetryCoreRecorder( + DiagnosticScope scope, + string operationName, + string containerName, + string databaseName, + OperationType operationType, + CosmosClientContext clientContext, + CosmosThresholdOptions config) + { + this.scope = scope; + this.config = config; + + this.operationType = operationType; + this.connectionModeCache = Enum.GetName(typeof(ConnectionMode), clientContext.ClientOptions.ConnectionMode); + + if (scope.IsEnabled) + { + this.scope.Start(); + + this.Record( + operationName: operationName, + containerName: containerName, + databaseName: databaseName, + clientContext: clientContext); + } + } + + /// + /// Used for creating parent activity in scenario where there are no listeners at operation level + /// but they are present at network level + /// + public static OpenTelemetryCoreRecorder CreateNetworkLevelParentActivity(DiagnosticScope networkScope) + { + return new OpenTelemetryCoreRecorder(networkScope); + } + + /// + /// Used for creating parent activity in scenario where there are no listeners at operation level and network level + /// + public static OpenTelemetryCoreRecorder CreateParentActivity(string operationName) + { + return new OpenTelemetryCoreRecorder(operationName); + } + + /// + /// Used for creating parent activity in scenario where there are listeners at operation level + /// + public static OpenTelemetryCoreRecorder CreateOperationLevelParentActivity( + DiagnosticScope operationScope, + string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, + CosmosClientContext clientContext, + CosmosThresholdOptions config) + { + return new OpenTelemetryCoreRecorder( + operationScope, + operationName, + containerName, + databaseName, + operationType, + clientContext, + config); + } + + public bool IsEnabled => this.scope.IsEnabled; + + public void Record(string key, string value) + { + if (this.IsEnabled) + { + this.scope.AddAttribute(key, value); + } + } + + /// + /// Recording information + /// + /// + /// + /// + /// + public void Record( + string operationName, + string containerName, + string databaseName, + CosmosClientContext clientContext) + { + if (this.IsEnabled) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbOperation, operationName); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbName, databaseName); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ContainerName, containerName); + + // Other information + this.scope.AddAttribute(OpenTelemetryAttributeKeys.DbSystemName, OpenTelemetryCoreRecorder.CosmosDb); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.MachineId, VmMetadataApiHandler.GetMachineId()); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ServerAddress, clientContext.Client?.Endpoint?.Host); + + // Client Information + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ClientId, clientContext?.Client?.Id); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.UserAgent, clientContext.UserAgent); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ConnectionMode, this.connectionModeCache); + } + } + + /// + /// Record attributes from response + /// + /// + public void Record(OpenTelemetryAttributes response) + { + if (this.IsEnabled) + { + this.response = response; + } + } + + /// + /// Record attributes during exception + /// + /// + public void MarkFailed(Exception exception) + { + if (this.IsEnabled) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionStacktrace, exception.StackTrace); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionType, exception.GetType().Name); + + // If Exception is not registered with open Telemetry + if (!OpenTelemetryCoreRecorder.IsExceptionRegistered(exception, this.scope)) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ExceptionMessage, exception.Message); + } + + if (exception is not CosmosException || (exception is CosmosException cosmosException + && !DiagnosticsFilterHelper + .IsSuccessfulResponse(cosmosException.StatusCode, cosmosException.SubStatusCode))) + { + this.scope.Failed(exception); + } + } + } + + /// + /// Checking if passed exception is registered with Open telemetry or Not + /// + /// + /// + /// tru/false + internal static bool IsExceptionRegistered(Exception exception, DiagnosticScope scope) + { + foreach (KeyValuePair> registeredExceptionHandlers in OpenTelemetryCoreRecorder.OTelCompatibleExceptions) + { + Type exceptionType = exception.GetType(); + if (registeredExceptionHandlers.Key.IsAssignableFrom(exceptionType)) + { + registeredExceptionHandlers.Value(exception, scope); + + return true; + } + } + + return false; + } + + public void Dispose() + { + if (this.IsEnabled) + { + OperationType operationType + = (this.response == null || this.response?.OperationType == OperationType.Invalid) ? this.operationType : this.response.OperationType; + + this.scope.AddAttribute(OpenTelemetryAttributeKeys.OperationType, Enum.GetName(typeof(OperationType), operationType)); + + if (this.response != null) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.RequestContentLength, this.response.RequestContentLength); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ResponseContentLength, this.response.ResponseContentLength); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.StatusCode, (int)this.response.StatusCode); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.SubStatusCode, this.response.SubStatusCode); + this.scope.AddIntegerAttribute(OpenTelemetryAttributeKeys.RequestCharge, (int)this.response.RequestCharge); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ItemCount, this.response.ItemCount); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.ActivityId, this.response.ActivityId); + this.scope.AddAttribute(OpenTelemetryAttributeKeys.CorrelatedActivityId, this.response.CorrelatedActivityId); + + if (this.response.Diagnostics != null) + { + this.scope.AddAttribute(OpenTelemetryAttributeKeys.Region, ClientTelemetryHelper.GetContactedRegions(this.response.Diagnostics.GetContactedRegions())); + CosmosDbEventSource.RecordDiagnosticsForRequests(this.config, operationType, this.response); + } + + if (!DiagnosticsFilterHelper.IsSuccessfulResponse(this.response.StatusCode, this.response.SubStatusCode)) + { + this.scope.Failed(new Exception($"{(int)this.response.StatusCode}/{this.response.SubStatusCode}")); + } + } + + this.scope.Dispose(); + } + else + { + this.activity?.Stop(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs index 1b16f48307..083f8e1b74 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/OpenTelemetryRecorderFactory.cs @@ -1,79 +1,78 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Telemetry -{ - using System; - using System.Diagnostics; - using global::Azure.Core; - using Microsoft.Azure.Cosmos.Tracing; - - /// - /// This class is used to generate Activities with Azure.Cosmos.Operation Source Name - /// - internal static class OpenTelemetryRecorderFactory - { - /// - /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once - /// - private static readonly Lazy LazyScopeFactory = new Lazy( - valueFactory: () => new DiagnosticScopeFactory( - clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}", - resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, - isActivityEnabled: true, - suppressNestedClientActivities: true, - isStable: false), - isThreadSafe: true); - - public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, - string containerName, - string databaseName, - Documents.OperationType operationType, - RequestOptions requestOptions, - ITrace trace, - CosmosClientContext clientContext) - { - OpenTelemetryCoreRecorder openTelemetryRecorder = default; - if (clientContext is { ClientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing: false }) - { - // If there is no source then it will return default otherwise a valid diagnostic scope - DiagnosticScope scope = LazyScopeFactory.Value.CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", - kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? ActivityKind.Internal : ActivityKind.Client); - - // Need a parent activity id associated with the operation which is logged in diagnostics and used for tracing purpose. - // If there are listeners at operation level then scope is enabled and it tries to create activity. - // However, if available listeners are not subscribed to operation level event then it will lead to scope being enabled but no activity is created. - if (scope.IsEnabled) - { - scope.SetDisplayName($"{operationName} {containerName}"); - - openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateOperationLevelParentActivity( - operationScope: scope, - operationName: operationName, - containerName: containerName, - databaseName: databaseName, - operationType: operationType, - clientContext: clientContext, - config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); - } -#if !INTERNAL - // If there are no listeners at operation level and no parent activity created. - // Then create a dummy activity as there should be a parent level activity always to send a traceid to the backend services through context propagation. - // The parent activity id logged in diagnostics, can be used for tracing purpose in backend. - if (Activity.Current is null) - { - openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateParentActivity(operationName); - } -#endif - // Safety check as diagnostic logs should not break the code. - if (Activity.Current?.TraceId != null) - { - // This id would be useful to trace calls at backend services when distributed tracing feature is available there. - trace.AddDatum("DistributedTraceId", Activity.Current.TraceId); - } - } - return openTelemetryRecorder; - } - } -} +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Telemetry +{ + using System; + using System.Diagnostics; + using global::Azure.Core; + using Microsoft.Azure.Cosmos.Tracing; + + /// + /// This class is used to generate Activities with Azure.Cosmos.Operation Source Name + /// + internal static class OpenTelemetryRecorderFactory + { + /// + /// Singleton to make sure we only have one instance of the DiagnosticScopeFactory and pattern matching of listener happens only once + /// + private static readonly Lazy LazyScopeFactory = new Lazy( + valueFactory: () => new DiagnosticScopeFactory( + clientNamespace: $"{OpenTelemetryAttributeKeys.DiagnosticNamespace}", + resourceProviderNamespace: OpenTelemetryAttributeKeys.ResourceProviderNamespace, + isActivityEnabled: true, + suppressNestedClientActivities: true), + isThreadSafe: true); + + public static OpenTelemetryCoreRecorder CreateRecorder(string operationName, + string containerName, + string databaseName, + Documents.OperationType operationType, + RequestOptions requestOptions, + ITrace trace, + CosmosClientContext clientContext) + { + OpenTelemetryCoreRecorder openTelemetryRecorder = default; + if (clientContext is { ClientOptions.CosmosClientTelemetryOptions.DisableDistributedTracing: false }) + { + // If there is no source then it will return default otherwise a valid diagnostic scope + DiagnosticScope scope = LazyScopeFactory.Value.CreateScope(name: $"{OpenTelemetryAttributeKeys.OperationPrefix}.{operationName}", + kind: clientContext.ClientOptions.ConnectionMode == ConnectionMode.Gateway ? DiagnosticScope.ActivityKind.Internal : DiagnosticScope.ActivityKind.Client); + + // Need a parent activity id associated with the operation which is logged in diagnostics and used for tracing purpose. + // If there are listeners at operation level then scope is enabled and it tries to create activity. + // However, if available listeners are not subscribed to operation level event then it will lead to scope being enabled but no activity is created. + if (scope.IsEnabled) + { + scope.SetDisplayName($"{operationName} {containerName}"); + + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateOperationLevelParentActivity( + operationScope: scope, + operationName: operationName, + containerName: containerName, + databaseName: databaseName, + operationType: operationType, + clientContext: clientContext, + config: requestOptions?.CosmosThresholdOptions ?? clientContext.ClientOptions?.CosmosClientTelemetryOptions.CosmosThresholdOptions); + } +#if !INTERNAL + // If there are no listeners at operation level and no parent activity created. + // Then create a dummy activity as there should be a parent level activity always to send a traceid to the backend services through context propagation. + // The parent activity id logged in diagnostics, can be used for tracing purpose in backend. + if (Activity.Current is null) + { + openTelemetryRecorder = OpenTelemetryCoreRecorder.CreateParentActivity(operationName); + } +#endif + // Safety check as diagnostic logs should not break the code. + if (Activity.Current?.TraceId != null) + { + // This id would be useful to trace calls at backend services when distributed tracing feature is available there. + trace.AddDatum("DistributedTraceId", Activity.Current.TraceId); + } + } + return openTelemetryRecorder; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/AccessCondition.cs b/Microsoft.Azure.Cosmos/src/direct/AccessCondition.cs index 6173decca5..9d19829c62 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AccessCondition.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AccessCondition.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Represents a set of access conditions to be used for operations in the Azure Cosmos DB service. - /// - /// - /// The following example shows how to use AccessCondition with DocumentClient. - /// - /// - /// - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class AccessCondition - { - /// - /// Gets or sets the condition type in the Azure Cosmos DB service. - /// - /// - /// The condition type. Can be IfMatch or IfNoneMatch. - /// - public AccessConditionType Type { get; set; } - - /// - /// Gets or sets the value of the condition in the Azure Cosmos DB service. - /// - /// - /// The value of the condition. For IfMatch and IfNotMatch, this is the ETag that has to be compared to. - /// - /// - public string Condition { get; set; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Represents a set of access conditions to be used for operations in the Azure Cosmos DB service. + /// + /// + /// The following example shows how to use AccessCondition with DocumentClient. + /// + /// + /// + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class AccessCondition + { + /// + /// Gets or sets the condition type in the Azure Cosmos DB service. + /// + /// + /// The condition type. Can be IfMatch or IfNoneMatch. + /// + public AccessConditionType Type { get; set; } + + /// + /// Gets or sets the value of the condition in the Azure Cosmos DB service. + /// + /// + /// The value of the condition. For IfMatch and IfNotMatch, this is the ETag that has to be compared to. + /// + /// + public string Condition { get; set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/AccessConditionType.cs b/Microsoft.Azure.Cosmos/src/direct/AccessConditionType.cs index c2980a3ec3..8857df4ed9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AccessConditionType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AccessConditionType.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Specifies the set of types that can be used for operations in the Azure Cosmos DB service. - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum AccessConditionType - { - /// - /// Check if the resource's ETag value matches the ETag value performed. - /// - /// - /// Used for optimistic concurrency control, e.g., replace the document only if the ETag is identical to the one - /// included in the request to avoid lost updates. - /// - IfMatch, - - /// - /// Check if the resource's ETag value does not match ETag value performed. - /// - /// - /// Used for caching scenarios to reduce network traffic, e.g., return the document in the payload only if the ETag - /// has changed from the one in the request. - /// - IfNoneMatch - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Specifies the set of types that can be used for operations in the Azure Cosmos DB service. + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum AccessConditionType + { + /// + /// Check if the resource's ETag value matches the ETag value performed. + /// + /// + /// Used for optimistic concurrency control, e.g., replace the document only if the ETag is identical to the one + /// included in the request to avoid lost updates. + /// + IfMatch, + + /// + /// Check if the resource's ETag value does not match ETag value performed. + /// + /// + /// Used for caching scenarios to reduce network traffic, e.g., return the document in the payload only if the ETag + /// has changed from the one in the request. + /// + IfNoneMatch + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Address.cs b/Microsoft.Azure.Cosmos/src/direct/Address.cs index 84d4e5b62d..f956cb1550 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Address.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Address.cs @@ -1,88 +1,101 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - internal sealed class Address : Resource - { - [JsonProperty(PropertyName = Constants.Properties.IsPrimary)] - public bool IsPrimary - { - get - { - return base.GetValue(Constants.Properties.IsPrimary); - } - internal set - { - base.SetValue(Constants.Properties.IsPrimary, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.Protocol)] - public string Protocol - { - get - { - return base.GetValue(Constants.Properties.Protocol); - } - internal set - { - base.SetValue(Constants.Properties.Protocol, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.LogicalUri)] - public string LogicalUri - { - get - { - return base.GetValue(Constants.Properties.LogicalUri); - } - internal set - { - base.SetValue(Constants.Properties.LogicalUri, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.PhysicalUri)] - public string PhysicalUri - { - get - { - return base.GetValue(Constants.Properties.PhysicalUri); - } - internal set - { - base.SetValue(Constants.Properties.PhysicalUri, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.PartitionIndex)] - public string PartitionIndex - { - get - { - return base.GetValue(Constants.Properties.PartitionIndex); - } - internal set - { - base.SetValue(Constants.Properties.PartitionIndex, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.PartitionKeyRangeId)] - public string PartitionKeyRangeId - { - get - { - return base.GetValue(Constants.Properties.PartitionKeyRangeId); - } - internal set - { - base.SetValue(Constants.Properties.PartitionKeyRangeId, value); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + internal sealed class Address : Resource + { + [JsonProperty(PropertyName = Constants.Properties.IsAuxiliary)] + public bool IsAuxiliary + { + get + { + return base.GetValue(Constants.Properties.IsAuxiliary); + } + internal set + { + base.SetValue(Constants.Properties.IsAuxiliary, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.IsPrimary)] + public bool IsPrimary + { + get + { + return base.GetValue(Constants.Properties.IsPrimary); + } + internal set + { + base.SetValue(Constants.Properties.IsPrimary, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.Protocol)] + public string Protocol + { + get + { + return base.GetValue(Constants.Properties.Protocol); + } + internal set + { + base.SetValue(Constants.Properties.Protocol, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.LogicalUri)] + public string LogicalUri + { + get + { + return base.GetValue(Constants.Properties.LogicalUri); + } + internal set + { + base.SetValue(Constants.Properties.LogicalUri, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.PhysicalUri)] + public string PhysicalUri + { + get + { + return base.GetValue(Constants.Properties.PhysicalUri); + } + internal set + { + base.SetValue(Constants.Properties.PhysicalUri, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.PartitionIndex)] + public string PartitionIndex + { + get + { + return base.GetValue(Constants.Properties.PartitionIndex); + } + internal set + { + base.SetValue(Constants.Properties.PartitionIndex, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.PartitionKeyRangeId)] + public string PartitionKeyRangeId + { + get + { + return base.GetValue(Constants.Properties.PartitionKeyRangeId); + } + internal set + { + base.SetValue(Constants.Properties.PartitionKeyRangeId, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/AddressCacheToken.cs b/Microsoft.Azure.Cosmos/src/direct/AddressCacheToken.cs index 7ebc5a251e..afa0185b62 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AddressCacheToken.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AddressCacheToken.cs @@ -1,42 +1,42 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Models the address cache token used to clear DocClient's address cache - /// when TransportClient triggers an event on conection reset by the node - /// - internal sealed class AddressCacheToken - { - public readonly PartitionKeyRangeIdentity PartitionKeyRangeIdentity; - public Uri ServiceEndpoint { get; private set; } - - public AddressCacheToken( - PartitionKeyRangeIdentity partitionKeyRangeIdentity, - Uri serviceEndpoint) - { - this.PartitionKeyRangeIdentity = partitionKeyRangeIdentity; - this.ServiceEndpoint = serviceEndpoint; - } - - public override bool Equals(object obj) - { - return this.Equals(obj as AddressCacheToken); - } - - public bool Equals(AddressCacheToken token) - { - return token != null && this.PartitionKeyRangeIdentity.Equals(token.PartitionKeyRangeIdentity) && - this.ServiceEndpoint.Equals(token.ServiceEndpoint); - } - - public override int GetHashCode() - { - return this.PartitionKeyRangeIdentity.GetHashCode() ^ this.ServiceEndpoint.GetHashCode(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Models the address cache token used to clear DocClient's address cache + /// when TransportClient triggers an event on conection reset by the node + /// + internal sealed class AddressCacheToken + { + public readonly PartitionKeyRangeIdentity PartitionKeyRangeIdentity; + public Uri ServiceEndpoint { get; private set; } + + public AddressCacheToken( + PartitionKeyRangeIdentity partitionKeyRangeIdentity, + Uri serviceEndpoint) + { + this.PartitionKeyRangeIdentity = partitionKeyRangeIdentity; + this.ServiceEndpoint = serviceEndpoint; + } + + public override bool Equals(object obj) + { + return this.Equals(obj as AddressCacheToken); + } + + public bool Equals(AddressCacheToken token) + { + return token != null && this.PartitionKeyRangeIdentity.Equals(token.PartitionKeyRangeIdentity) && + this.ServiceEndpoint.Equals(token.ServiceEndpoint); + } + + public override int GetHashCode() + { + return this.PartitionKeyRangeIdentity.GetHashCode() ^ this.ServiceEndpoint.GetHashCode(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/AddressEnumerator.cs b/Microsoft.Azure.Cosmos/src/direct/AddressEnumerator.cs index 96fa1671eb..871600ce92 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AddressEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AddressEnumerator.cs @@ -1,346 +1,346 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Linq; - using static Microsoft.Azure.Documents.HttpConstants; - - /// - /// AddressEnumerator randomly iterates a list of TransportAddressUris. - /// - internal sealed class AddressEnumerator : IAddressEnumerator - { - [ThreadStatic] - private static Random random; - - private static int GenerateNextRandom(int start, int maxValue) - { - if (AddressEnumerator.random == null) - { - // Generate random numbers with a seed so that not all the threads without random available - // start producing the same sequence. - AddressEnumerator.random = CustomTypeExtensions.GetRandomNumber(); - } - - return AddressEnumerator.random.Next(start, maxValue); - } - - /// - /// This return a random order of the addresses if there are no addresses that failed. Else it moves the failes addresses to the end. - /// - public IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris, - Lazy> failedEndpoints, - bool replicaAddressValidationEnabled) - { - if (failedEndpoints == null) - { - throw new ArgumentNullException(nameof(failedEndpoints)); - } - - // Get a random Permutation. - IEnumerable randomPermutation = this.GetTransportAddresses(transportAddressUris); - - // We reorder the replica set with the following rule, to avoid landing on to any unhealthy replica/s: - // Scenario 1: When replica validation is enabled, the replicas will be reordered by the preference of - // Connected > Unknown > UnhealthyPending > Unhealthy. - // Scenario 2: When replica validation is disabled, the replicas will be reordered by the preference of - // Connected/Unknown/UnhealthyPending > Unhealthy. - return AddressEnumerator.ReorderReplicasByHealthStatus( - randomPermutation: randomPermutation, - lazyFailedReplicasPerRequest: failedEndpoints, - replicaAddressValidationEnabled: replicaAddressValidationEnabled); - } - - /// - /// This uses the FisherYates shuffle algorithm to return a random order - /// of Transport Address URIs - /// - private IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris) - { - if (transportAddressUris == null) - { - throw new ArgumentNullException(nameof(transportAddressUris)); - } - - if (transportAddressUris.Count == 0) - { - return Enumerable.Empty(); - } - - // Permutation is faster and has less over head compared to Fisher-Yates shuffle - // Permutation is optimized for most common scenario where replica count is 5 or less - // Fisher-Yates shuffle is used in-case the passed in URI list is larger than the predefined permutation list. - if (AddressEnumeratorUsingPermutations.IsSizeInPermutationLimits(transportAddressUris.Count)) - { - return AddressEnumeratorUsingPermutations.GetTransportAddressUrisWithPredefinedPermutation(transportAddressUris); - } - - return AddressEnumeratorFisherYateShuffle.GetTransportAddressUrisWithFisherYateShuffle(transportAddressUris); - } - - /// - /// Fisher-Yates Shuffle gives a random order of TransportAddressUri - /// - private readonly struct AddressEnumeratorFisherYateShuffle - { - public static IEnumerable GetTransportAddressUrisWithFisherYateShuffle(IReadOnlyList transportAddressUris) - { - // Fisher Yates Shuffle algorithm: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle - List transportAddressesCopy = transportAddressUris.ToList(); - - for (int i = 0; i < transportAddressUris.Count - 1; i++) - { - int randomIndex = AddressEnumerator.GenerateNextRandom(i, transportAddressUris.Count); - - AddressEnumeratorFisherYateShuffle.Swap(transportAddressesCopy, i, randomIndex); - yield return transportAddressesCopy[i]; - } - - yield return transportAddressesCopy.Last(); - } - - private static void Swap( - List transportAddressUris, - int firstIndex, - int secondIndex) - { - if (firstIndex == secondIndex) - { - return; - } - - TransportAddressUri temp = transportAddressUris[firstIndex]; - transportAddressUris[firstIndex] = transportAddressUris[secondIndex]; - transportAddressUris[secondIndex] = temp; - } - } - - /// - /// This uses a predefined permutation list to decide the random order of TransportAddressUri - /// This is optimized for the most common scenario. - /// This only requires a single random number and no additional allocation to track items already returned. - /// - private readonly struct AddressEnumeratorUsingPermutations - { - /// - /// Permutation by the size -> All permutation for that size -> The individual permutation - /// - private static readonly IReadOnlyList>> AllPermutationsOfIndexesBySize; - - static AddressEnumeratorUsingPermutations() - { - List>> allPermutationBySize = new List>>(); - // Cosmos DB normally has 4 replicas, but for failover scenario it could be more. - // Having permutations up to 6 will cover all the common scenarios. - for (int i = 0; i <= 6; i++) - { - List> permutations = new List>(); - AddressEnumeratorUsingPermutations.PermuteIndexPositions(Enumerable.Range(0, i).ToArray(), 0, i, permutations); - allPermutationBySize.Add(permutations); - } - - AddressEnumeratorUsingPermutations.AllPermutationsOfIndexesBySize = allPermutationBySize; - } - - public static bool IsSizeInPermutationLimits(int size) - { - return size < AllPermutationsOfIndexesBySize.Count; - } - - public static IEnumerable GetTransportAddressUrisWithPredefinedPermutation(IReadOnlyList transportAddressUris) - { - IReadOnlyList> allPermutationsForSpecificSize = AddressEnumeratorUsingPermutations.AllPermutationsOfIndexesBySize[transportAddressUris.Count]; - int permutation = AddressEnumerator.GenerateNextRandom(0, allPermutationsForSpecificSize.Count); - - foreach (int index in allPermutationsForSpecificSize[permutation]) - { - yield return transportAddressUris[index]; - } - } - - private static void PermuteIndexPositions( - int[] array, - int start, - int length, - List> output) - { - if (start == length) - { - output.Add(array.ToList()); - } - else - { - for (int j = start; j < length; j++) - { - AddressEnumeratorUsingPermutations.Swap(ref array[start], ref array[j]); - AddressEnumeratorUsingPermutations.PermuteIndexPositions(array, start + 1, length, output); - AddressEnumeratorUsingPermutations.Swap(ref array[start], ref array[j]); //backtrack - } - } - } - - private static void Swap( - ref int a, - ref int b) - { - int tmp = a; - a = b; - b = tmp; - } - } - - /// - /// Reorders the replica set to prefer the healthy replicas over the unhealthy ones. When replica address validation - /// is enabled, the address enumerator will pick the replicas in the order of their health statuses: Connected > - /// Unknown > UnhealthyPending > Unhealthy. When replica address validation is disabled, the address enumerator will - /// transition away Unknown/UnhealthyPending replicas and pick the replicas by preferring any of the Connected/ Unknown - /// / UnhealthyPending over the Unhealthy ones. - /// - /// A list containing the permutation of the replicas. - /// A lazy set containing the unhealthy replicas. - /// A boolean flag indicating if the replica validation is enabled. - /// A list of ordered by the replica health statuses. - private static IEnumerable ReorderReplicasByHealthStatus( - IEnumerable randomPermutation, - Lazy> lazyFailedReplicasPerRequest, - bool replicaAddressValidationEnabled) - { - HashSet failedReplicasPerRequest = null; - if (lazyFailedReplicasPerRequest != null && - lazyFailedReplicasPerRequest.IsValueCreated && - lazyFailedReplicasPerRequest.Value.Count > 0) - { - failedReplicasPerRequest = lazyFailedReplicasPerRequest.Value; - } - - if (!replicaAddressValidationEnabled) - { - return AddressEnumerator.MoveFailedReplicasToTheEnd( - addresses: randomPermutation, - failedReplicasPerRequest: failedReplicasPerRequest); - } - else - { - return AddressEnumerator.ReorderAddressesWhenReplicaValidationEnabled( - addresses: randomPermutation, - failedReplicasPerRequest: failedReplicasPerRequest); - } - } - - /// - /// When replica address validation is enabled, the address enumerator will pick the replicas in the order of their health statuses: - /// Connected >> Unknown >> UnhealthyPending >> Unhealthy. The open connection handler will be used to transit away unknown/unhealthy pending status. - /// But in case open connection request can not happen/ finish due to any reason, then after some extended time (for example 1 minute), - /// the address enumerator will mark Unknown/ Unhealthy pending into Healthy category (please check details of TransportAddressUri.GetEffectiveHealthStatus()) - /// - /// A random list containing all of the replica addresses. - /// A hash set containing the failed replica addresses. - /// The reordered list of . - private static IEnumerable ReorderAddressesWhenReplicaValidationEnabled( - IEnumerable addresses, - HashSet failedReplicasPerRequest) - { - List failedReplicas = null, pendingReplicas = null; - foreach (TransportAddressUri transportAddressUri in addresses) - { - TransportAddressHealthState.HealthStatus status = AddressEnumerator.GetEffectiveStatus( - addressUri: transportAddressUri, - failedEndpoints: failedReplicasPerRequest); - - if (status == TransportAddressHealthState.HealthStatus.Connected - || status == TransportAddressHealthState.HealthStatus.Unknown) - { - yield return transportAddressUri; - } - else if (status == TransportAddressHealthState.HealthStatus.UnhealthyPending) - { - pendingReplicas ??= new (); - pendingReplicas.Add(transportAddressUri); - } - else - { - failedReplicas ??= new (); - failedReplicas.Add(transportAddressUri); - } - } - - if (pendingReplicas != null) - { - foreach (TransportAddressUri transportAddressUri in pendingReplicas) - { - yield return transportAddressUri; - } - } - - if (failedReplicas != null) - { - foreach (TransportAddressUri transportAddressUri in failedReplicas) - { - yield return transportAddressUri; - } - } - } - - /// - /// When replica address validation is disabled, the address enumerator will transition away Unknown/UnhealthyPending - /// replicas and pick the replicas by preferring any of the Connected/Unknown/UnhealthyPending over Unhealthy. Therefore - /// it moves the unhealthy replicas to the end of the replica list. - /// - /// A random list containing all of the replica addresses. - /// A hash set containing the failed replica addresses. - /// The reordered list of . - private static IEnumerable MoveFailedReplicasToTheEnd( - IEnumerable addresses, - HashSet failedReplicasPerRequest) - { - List failedReplicas = null; - foreach (TransportAddressUri transportAddressUri in addresses) - { - TransportAddressHealthState.HealthStatus status = AddressEnumerator.GetEffectiveStatus( - addressUri: transportAddressUri, - failedEndpoints: failedReplicasPerRequest); - - if (status == TransportAddressHealthState.HealthStatus.Connected || - status == TransportAddressHealthState.HealthStatus.Unknown || - status == TransportAddressHealthState.HealthStatus.UnhealthyPending) - { - yield return transportAddressUri; - } - else - { - failedReplicas ??= new (); - failedReplicas.Add(transportAddressUri); - } - } - - if (failedReplicas != null) - { - foreach (TransportAddressUri transportAddressUri in failedReplicas) - { - yield return transportAddressUri; - } - } - } - - /// - /// Gets the effective health status of the transport address uri. - /// - /// An instance of the containing the replica address. - /// A set containing the failed endpoints. - /// An instance of indicating the effective health status of the address. - private static TransportAddressHealthState.HealthStatus GetEffectiveStatus( - TransportAddressUri addressUri, - HashSet failedEndpoints) - { - if (failedEndpoints != null && failedEndpoints.Contains(addressUri)) - { - return TransportAddressHealthState.HealthStatus.Unhealthy; - } - - return addressUri.GetEffectiveHealthStatus(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Linq; + using static Microsoft.Azure.Documents.HttpConstants; + + /// + /// AddressEnumerator randomly iterates a list of TransportAddressUris. + /// + internal sealed class AddressEnumerator : IAddressEnumerator + { + [ThreadStatic] + private static Random random; + + private static int GenerateNextRandom(int start, int maxValue) + { + if (AddressEnumerator.random == null) + { + // Generate random numbers with a seed so that not all the threads without random available + // start producing the same sequence. + AddressEnumerator.random = CustomTypeExtensions.GetRandomNumber(); + } + + return AddressEnumerator.random.Next(start, maxValue); + } + + /// + /// This return a random order of the addresses if there are no addresses that failed. Else it moves the failes addresses to the end. + /// + public IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris, + Lazy> failedEndpoints, + bool replicaAddressValidationEnabled) + { + if (failedEndpoints == null) + { + throw new ArgumentNullException(nameof(failedEndpoints)); + } + + // Get a random Permutation. + IEnumerable randomPermutation = this.GetTransportAddresses(transportAddressUris); + + // We reorder the replica set with the following rule, to avoid landing on to any unhealthy replica/s: + // Scenario 1: When replica validation is enabled, the replicas will be reordered by the preference of + // Connected > Unknown > UnhealthyPending > Unhealthy. + // Scenario 2: When replica validation is disabled, the replicas will be reordered by the preference of + // Connected/Unknown/UnhealthyPending > Unhealthy. + return AddressEnumerator.ReorderReplicasByHealthStatus( + randomPermutation: randomPermutation, + lazyFailedReplicasPerRequest: failedEndpoints, + replicaAddressValidationEnabled: replicaAddressValidationEnabled); + } + + /// + /// This uses the FisherYates shuffle algorithm to return a random order + /// of Transport Address URIs + /// + private IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris) + { + if (transportAddressUris == null) + { + throw new ArgumentNullException(nameof(transportAddressUris)); + } + + if (transportAddressUris.Count == 0) + { + return Enumerable.Empty(); + } + + // Permutation is faster and has less over head compared to Fisher-Yates shuffle + // Permutation is optimized for most common scenario where replica count is 5 or less + // Fisher-Yates shuffle is used in-case the passed in URI list is larger than the predefined permutation list. + if (AddressEnumeratorUsingPermutations.IsSizeInPermutationLimits(transportAddressUris.Count)) + { + return AddressEnumeratorUsingPermutations.GetTransportAddressUrisWithPredefinedPermutation(transportAddressUris); + } + + return AddressEnumeratorFisherYateShuffle.GetTransportAddressUrisWithFisherYateShuffle(transportAddressUris); + } + + /// + /// Fisher-Yates Shuffle gives a random order of TransportAddressUri + /// + private readonly struct AddressEnumeratorFisherYateShuffle + { + public static IEnumerable GetTransportAddressUrisWithFisherYateShuffle(IReadOnlyList transportAddressUris) + { + // Fisher Yates Shuffle algorithm: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + List transportAddressesCopy = transportAddressUris.ToList(); + + for (int i = 0; i < transportAddressUris.Count - 1; i++) + { + int randomIndex = AddressEnumerator.GenerateNextRandom(i, transportAddressUris.Count); + + AddressEnumeratorFisherYateShuffle.Swap(transportAddressesCopy, i, randomIndex); + yield return transportAddressesCopy[i]; + } + + yield return transportAddressesCopy.Last(); + } + + private static void Swap( + List transportAddressUris, + int firstIndex, + int secondIndex) + { + if (firstIndex == secondIndex) + { + return; + } + + TransportAddressUri temp = transportAddressUris[firstIndex]; + transportAddressUris[firstIndex] = transportAddressUris[secondIndex]; + transportAddressUris[secondIndex] = temp; + } + } + + /// + /// This uses a predefined permutation list to decide the random order of TransportAddressUri + /// This is optimized for the most common scenario. + /// This only requires a single random number and no additional allocation to track items already returned. + /// + private readonly struct AddressEnumeratorUsingPermutations + { + /// + /// Permutation by the size -> All permutation for that size -> The individual permutation + /// + private static readonly IReadOnlyList>> AllPermutationsOfIndexesBySize; + + static AddressEnumeratorUsingPermutations() + { + List>> allPermutationBySize = new List>>(); + // Cosmos DB normally has 4 replicas, but for failover scenario it could be more. + // Having permutations up to 6 will cover all the common scenarios. + for (int i = 0; i <= 6; i++) + { + List> permutations = new List>(); + AddressEnumeratorUsingPermutations.PermuteIndexPositions(Enumerable.Range(0, i).ToArray(), 0, i, permutations); + allPermutationBySize.Add(permutations); + } + + AddressEnumeratorUsingPermutations.AllPermutationsOfIndexesBySize = allPermutationBySize; + } + + public static bool IsSizeInPermutationLimits(int size) + { + return size < AllPermutationsOfIndexesBySize.Count; + } + + public static IEnumerable GetTransportAddressUrisWithPredefinedPermutation(IReadOnlyList transportAddressUris) + { + IReadOnlyList> allPermutationsForSpecificSize = AddressEnumeratorUsingPermutations.AllPermutationsOfIndexesBySize[transportAddressUris.Count]; + int permutation = AddressEnumerator.GenerateNextRandom(0, allPermutationsForSpecificSize.Count); + + foreach (int index in allPermutationsForSpecificSize[permutation]) + { + yield return transportAddressUris[index]; + } + } + + private static void PermuteIndexPositions( + int[] array, + int start, + int length, + List> output) + { + if (start == length) + { + output.Add(array.ToList()); + } + else + { + for (int j = start; j < length; j++) + { + AddressEnumeratorUsingPermutations.Swap(ref array[start], ref array[j]); + AddressEnumeratorUsingPermutations.PermuteIndexPositions(array, start + 1, length, output); + AddressEnumeratorUsingPermutations.Swap(ref array[start], ref array[j]); //backtrack + } + } + } + + private static void Swap( + ref int a, + ref int b) + { + int tmp = a; + a = b; + b = tmp; + } + } + + /// + /// Reorders the replica set to prefer the healthy replicas over the unhealthy ones. When replica address validation + /// is enabled, the address enumerator will pick the replicas in the order of their health statuses: Connected > + /// Unknown > UnhealthyPending > Unhealthy. When replica address validation is disabled, the address enumerator will + /// transition away Unknown/UnhealthyPending replicas and pick the replicas by preferring any of the Connected/ Unknown + /// / UnhealthyPending over the Unhealthy ones. + /// + /// A list containing the permutation of the replicas. + /// A lazy set containing the unhealthy replicas. + /// A boolean flag indicating if the replica validation is enabled. + /// A list of ordered by the replica health statuses. + private static IEnumerable ReorderReplicasByHealthStatus( + IEnumerable randomPermutation, + Lazy> lazyFailedReplicasPerRequest, + bool replicaAddressValidationEnabled) + { + HashSet failedReplicasPerRequest = null; + if (lazyFailedReplicasPerRequest != null && + lazyFailedReplicasPerRequest.IsValueCreated && + lazyFailedReplicasPerRequest.Value.Count > 0) + { + failedReplicasPerRequest = lazyFailedReplicasPerRequest.Value; + } + + if (!replicaAddressValidationEnabled) + { + return AddressEnumerator.MoveFailedReplicasToTheEnd( + addresses: randomPermutation, + failedReplicasPerRequest: failedReplicasPerRequest); + } + else + { + return AddressEnumerator.ReorderAddressesWhenReplicaValidationEnabled( + addresses: randomPermutation, + failedReplicasPerRequest: failedReplicasPerRequest); + } + } + + /// + /// When replica address validation is enabled, the address enumerator will pick the replicas in the order of their health statuses: + /// Connected >> Unknown >> UnhealthyPending >> Unhealthy. The open connection handler will be used to transit away unknown/unhealthy pending status. + /// But in case open connection request can not happen/ finish due to any reason, then after some extended time (for example 1 minute), + /// the address enumerator will mark Unknown/ Unhealthy pending into Healthy category (please check details of TransportAddressUri.GetEffectiveHealthStatus()) + /// + /// A random list containing all of the replica addresses. + /// A hash set containing the failed replica addresses. + /// The reordered list of . + private static IEnumerable ReorderAddressesWhenReplicaValidationEnabled( + IEnumerable addresses, + HashSet failedReplicasPerRequest) + { + List failedReplicas = null, pendingReplicas = null; + foreach (TransportAddressUri transportAddressUri in addresses) + { + TransportAddressHealthState.HealthStatus status = AddressEnumerator.GetEffectiveStatus( + addressUri: transportAddressUri, + failedEndpoints: failedReplicasPerRequest); + + if (status == TransportAddressHealthState.HealthStatus.Connected + || status == TransportAddressHealthState.HealthStatus.Unknown) + { + yield return transportAddressUri; + } + else if (status == TransportAddressHealthState.HealthStatus.UnhealthyPending) + { + pendingReplicas ??= new (); + pendingReplicas.Add(transportAddressUri); + } + else + { + failedReplicas ??= new (); + failedReplicas.Add(transportAddressUri); + } + } + + if (pendingReplicas != null) + { + foreach (TransportAddressUri transportAddressUri in pendingReplicas) + { + yield return transportAddressUri; + } + } + + if (failedReplicas != null) + { + foreach (TransportAddressUri transportAddressUri in failedReplicas) + { + yield return transportAddressUri; + } + } + } + + /// + /// When replica address validation is disabled, the address enumerator will transition away Unknown/UnhealthyPending + /// replicas and pick the replicas by preferring any of the Connected/Unknown/UnhealthyPending over Unhealthy. Therefore + /// it moves the unhealthy replicas to the end of the replica list. + /// + /// A random list containing all of the replica addresses. + /// A hash set containing the failed replica addresses. + /// The reordered list of . + private static IEnumerable MoveFailedReplicasToTheEnd( + IEnumerable addresses, + HashSet failedReplicasPerRequest) + { + List failedReplicas = null; + foreach (TransportAddressUri transportAddressUri in addresses) + { + TransportAddressHealthState.HealthStatus status = AddressEnumerator.GetEffectiveStatus( + addressUri: transportAddressUri, + failedEndpoints: failedReplicasPerRequest); + + if (status == TransportAddressHealthState.HealthStatus.Connected || + status == TransportAddressHealthState.HealthStatus.Unknown || + status == TransportAddressHealthState.HealthStatus.UnhealthyPending) + { + yield return transportAddressUri; + } + else + { + failedReplicas ??= new (); + failedReplicas.Add(transportAddressUri); + } + } + + if (failedReplicas != null) + { + foreach (TransportAddressUri transportAddressUri in failedReplicas) + { + yield return transportAddressUri; + } + } + } + + /// + /// Gets the effective health status of the transport address uri. + /// + /// An instance of the containing the replica address. + /// A set containing the failed endpoints. + /// An instance of indicating the effective health status of the address. + private static TransportAddressHealthState.HealthStatus GetEffectiveStatus( + TransportAddressUri addressUri, + HashSet failedEndpoints) + { + if (failedEndpoints != null && failedEndpoints.Contains(addressUri)) + { + return TransportAddressHealthState.HealthStatus.Unhealthy; + } + + return addressUri.GetEffectiveHealthStatus(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/AddressInformation.cs b/Microsoft.Azure.Cosmos/src/direct/AddressInformation.cs index 68ad90f8d4..773a6e4b64 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AddressInformation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AddressInformation.cs @@ -1,87 +1,106 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Microsoft.Azure.Documents.Client; - - internal sealed class AddressInformation : IEquatable, IComparable - { - private int? lazyHashCode; - - public AddressInformation( - string physicalUri, - bool isPublic, - bool isPrimary, - Protocol protocol) - { - this.IsPublic = isPublic; - this.IsPrimary = isPrimary; - this.Protocol = protocol; - this.PhysicalUri = physicalUri; - } - - public bool IsPublic { get; } - - public bool IsPrimary { get; } - - public Protocol Protocol { get; } - - public string PhysicalUri { get; } - - public int CompareTo(AddressInformation other) - { - if(other == null) - { - return -1; - } - - int comp = this.IsPrimary.CompareTo(other.IsPrimary); - if(comp != 0) - { - // Put primary first - return -1 * comp; - } - - comp = this.IsPublic.CompareTo(other.IsPublic); - if (comp != 0) - { - return comp; - } - - comp = this.Protocol.CompareTo(other.Protocol); - if (comp != 0) - { - return comp; - } - - return string.Compare(this.PhysicalUri, other.PhysicalUri, StringComparison.OrdinalIgnoreCase); - } - - public bool Equals(AddressInformation other) - { - return this.CompareTo(other) == 0; - } - - public override int GetHashCode() - { - return this.lazyHashCode ??= Calculate(this); - - static int Calculate(AddressInformation self) - { - int hashCode = 17; - hashCode = (hashCode * 397) ^ self.Protocol.GetHashCode(); - hashCode = (hashCode * 397) ^ self.IsPublic.GetHashCode(); - hashCode = (hashCode * 397) ^ self.IsPrimary.GetHashCode(); - if (self.PhysicalUri != null) - { - hashCode = (hashCode * 397) ^ self.PhysicalUri.GetHashCode(); - } - - return hashCode; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Microsoft.Azure.Documents.Client; + + internal sealed class AddressInformation : IEquatable, IComparable + { + private int? lazyHashCode; + + public AddressInformation( + string physicalUri, + bool isPublic, + bool isPrimary, + Protocol protocol, + bool isAuxiliary) + : this(physicalUri, isPublic, isPrimary, protocol) + { + this.IsAuxiliary = isAuxiliary; + } + + public AddressInformation( + string physicalUri, + bool isPublic, + bool isPrimary, + Protocol protocol) + { + this.IsPublic = isPublic; + this.IsPrimary = isPrimary; + this.Protocol = protocol; + this.PhysicalUri = physicalUri; + } + + public bool IsPublic { get; } + + public bool IsPrimary { get; } + + public bool IsAuxiliary { get; } + + public Protocol Protocol { get; } + + public string PhysicalUri { get; } + + public int CompareTo(AddressInformation other) + { + if(other == null) + { + return -1; + } + + int comp = this.IsPrimary.CompareTo(other.IsPrimary); + if(comp != 0) + { + // Put primary first + return -1 * comp; + } + + comp = this.IsAuxiliary.CompareTo(other.IsAuxiliary); + if (comp != 0) + { + return comp; + } + + comp = this.IsPublic.CompareTo(other.IsPublic); + if (comp != 0) + { + return comp; + } + + comp = this.Protocol.CompareTo(other.Protocol); + if (comp != 0) + { + return comp; + } + + return string.Compare(this.PhysicalUri, other.PhysicalUri, StringComparison.OrdinalIgnoreCase); + } + + public bool Equals(AddressInformation other) + { + return this.CompareTo(other) == 0; + } + + public override int GetHashCode() + { + return this.lazyHashCode ??= Calculate(this); + + static int Calculate(AddressInformation self) + { + int hashCode = 17; + hashCode = (hashCode * 397) ^ self.Protocol.GetHashCode(); + hashCode = (hashCode * 397) ^ self.IsPublic.GetHashCode(); + hashCode = (hashCode * 397) ^ self.IsPrimary.GetHashCode(); + if (self.PhysicalUri != null) + { + hashCode = (hashCode * 397) ^ self.PhysicalUri.GetHashCode(); + } + + return hashCode; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/AddressSelector.cs b/Microsoft.Azure.Cosmos/src/direct/AddressSelector.cs index 259c8b0d7b..cc93f88b18 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AddressSelector.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AddressSelector.cs @@ -1,86 +1,86 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Client; - - internal sealed class AddressSelector - { - private readonly IAddressResolver addressResolver; - private readonly Protocol protocol; - - public AddressSelector(IAddressResolver addressResolver, - Protocol protocol) - { - this.addressResolver = addressResolver; - this.protocol = protocol; - } - - /// - /// Resolves the transport address uris from the given request and returns them along with their health statuses. - /// Note that the returned transport address uris are not ordered by their health status and the two lists could - /// have a completely random ordering while returning the addresses. - /// - /// An instance of containing the request payload. - /// A boolean flag indicating if the primary replica needed to be included while resolving the addresses. - /// A boolean flag indicating if force refresh was requested. - /// - public async Task<(IReadOnlyList, IReadOnlyList)> ResolveAllTransportAddressUriAsync( - DocumentServiceRequest request, - bool includePrimary, - bool forceRefresh) - { - PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesAsync(request, forceRefresh); - - return includePrimary - ? (partitionPerProtocolAddress.ReplicaTransportAddressUris, partitionPerProtocolAddress.ReplicaTransportAddressUrisHealthState) - : (partitionPerProtocolAddress.NonPrimaryReplicaTransportAddressUris, partitionPerProtocolAddress.ReplicaTransportAddressUrisHealthState); - } - - public async Task ResolvePrimaryTransportAddressUriAsync( - DocumentServiceRequest request, - bool forceAddressRefresh) - { - PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesAsync(request, forceAddressRefresh); - return partitionPerProtocolAddress.GetPrimaryAddressUri(request); - } - - public async Task ResolveAddressesAsync( - DocumentServiceRequest request, - bool forceAddressRefresh) - { - PartitionAddressInformation partitionAddressInformation = - await this.addressResolver.ResolveAsync(request, forceAddressRefresh, CancellationToken.None); - - return partitionAddressInformation.Get(this.protocol); - } - - public void StartBackgroundAddressRefresh(DocumentServiceRequest request) - { - try - { - // DocumentServiceRequest is not thread safe and must be cloned to avoid - // concurrency issues since this a background task. - DocumentServiceRequest requestClone = request.Clone(); - this.ResolveAllTransportAddressUriAsync(requestClone, true, true).ContinueWith((task) => - { - if (task.IsFaulted) - { - DefaultTrace.TraceWarning( - "Background refresh of the addresses failed with {0}", task.Exception.ToString()); - } - }); - } - catch (Exception exception) - { - DefaultTrace.TraceWarning("Background refresh of the addresses failed with {0}", exception.ToString()); - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Client; + + internal sealed class AddressSelector + { + private readonly IAddressResolver addressResolver; + private readonly Protocol protocol; + + public AddressSelector(IAddressResolver addressResolver, + Protocol protocol) + { + this.addressResolver = addressResolver; + this.protocol = protocol; + } + + /// + /// Resolves the transport address uris from the given request and returns them along with their health statuses. + /// Note that the returned transport address uris are not ordered by their health status and the two lists could + /// have a completely random ordering while returning the addresses. + /// + /// An instance of containing the request payload. + /// A boolean flag indicating if the primary replica needed to be included while resolving the addresses. + /// A boolean flag indicating if force refresh was requested. + /// + public async Task<(IReadOnlyList, IReadOnlyList)> ResolveAllTransportAddressUriAsync( + DocumentServiceRequest request, + bool includePrimary, + bool forceRefresh) + { + PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesAsync(request, forceRefresh); + + return includePrimary + ? (partitionPerProtocolAddress.ReplicaTransportAddressUris, partitionPerProtocolAddress.ReplicaTransportAddressUrisHealthState) + : (partitionPerProtocolAddress.NonPrimaryReplicaTransportAddressUris, partitionPerProtocolAddress.ReplicaTransportAddressUrisHealthState); + } + + public async Task ResolvePrimaryTransportAddressUriAsync( + DocumentServiceRequest request, + bool forceAddressRefresh) + { + PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.ResolveAddressesAsync(request, forceAddressRefresh); + return partitionPerProtocolAddress.GetPrimaryAddressUri(request); + } + + public async Task ResolveAddressesAsync( + DocumentServiceRequest request, + bool forceAddressRefresh) + { + PartitionAddressInformation partitionAddressInformation = + await this.addressResolver.ResolveAsync(request, forceAddressRefresh, CancellationToken.None); + + return partitionAddressInformation.Get(this.protocol); + } + + public void StartBackgroundAddressRefresh(DocumentServiceRequest request) + { + try + { + // DocumentServiceRequest is not thread safe and must be cloned to avoid + // concurrency issues since this a background task. + DocumentServiceRequest requestClone = request.Clone(); + this.ResolveAllTransportAddressUriAsync(requestClone, true, true).ContinueWith((task) => + { + if (task.IsFaulted) + { + DefaultTrace.TraceWarning( + "Background refresh of the addresses failed with {0}", task.Exception.ToString()); + } + }); + } + catch (Exception exception) + { + DefaultTrace.TraceWarning("Background refresh of the addresses failed with {0}", exception.ToString()); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ApiType.cs b/Microsoft.Azure.Cosmos/src/direct/ApiType.cs index f991e4ae94..8f9cbdc101 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ApiType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ApiType.cs @@ -1,20 +1,20 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - [Flags] - internal enum ApiType - { - None = 0x0, - MongoDB = 0x1, - Gremlin = 0x2, - Cassandra = 0x4, - Table = 0x8, - Sql = 0x10, - Etcd = 0x20, - GremlinV2 = 0x40 - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + [Flags] + internal enum ApiType + { + None = 0x0, + MongoDB = 0x1, + Gremlin = 0x2, + Cassandra = 0x4, + Table = 0x8, + Sql = 0x10, + Etcd = 0x20, + GremlinV2 = 0x40 + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Attachment.cs b/Microsoft.Azure.Cosmos/src/direct/Attachment.cs index 29c28872d1..01dbd0b2d4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Attachment.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Attachment.cs @@ -1,317 +1,317 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Dynamic; - using System.Globalization; - using System.Linq.Expressions; - using System.Reflection; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Represents a document attachment in the Azure Cosmos DB service. - /// - /// - /// Each document may contain zero or more attachments containing data of arbitrary formats like images, binary or large text blobs. - /// The Attachment class represents the Azure Cosmos DB resource used to store information about the attachment like its location and - /// MIME content type. The payload itself ("Media") is referenced through the MediaLink property. The Attachment class is a DynamicObject - /// and can contain any custom metadata to be persisted. - /// - /// Attachments can be created as managed or unmanaged. If attachments are created as managed through Azure Cosmos DB, then it is assigned a system - /// generated mediaLink. Azure Cosmos DB then automatically performs garbage collection on the media when parent document is deleted. - /// - /// You can reuse the mediaLink property to store an external location e.g., a file share or an Azure Blob Storage URI. - /// Azure Cosmos DB will not perform garbage collection on mediaLinks for external locations. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Attachment : Resource, IDynamicMetaObjectProvider - { - /// - /// Initializes a new instance of an class for the Azure Cosmos DB service. - /// - public Attachment() - { - - } - - /// - /// Gets or sets the MIME content type of the attachment in the Azure Cosmos DB service. - /// - /// - /// The MIME content type of the attachment. - /// - /// For example, set to "text/plain" for text files, "image/jpeg" for images. - [JsonProperty(PropertyName = Constants.Properties.ContentType)] - public string ContentType - { - get - { - return base.GetValue(Constants.Properties.ContentType); - } - set - { - base.SetValue(Constants.Properties.ContentType, value); - } - } - - /// - /// Gets or sets the media link associated with the attachment content in the Azure Cosmos DB service. - /// - /// - /// The media link associated with the attachment content. - /// - /// Azure Cosmos DB supports both managed and unmanaged attachments. - [JsonProperty(PropertyName = Constants.Properties.MediaLink)] - public string MediaLink - { - get - { - return base.GetValue(Constants.Properties.MediaLink); - } - set - { - base.SetValue(Constants.Properties.MediaLink, value); - } - } - - //Helper to materialize Attachment from any .NET object. - internal static Attachment FromObject(object attachment, JsonSerializerSettings settings = null) - { - if (attachment != null) - { - if (typeof(Attachment).IsAssignableFrom(attachment.GetType())) - { - return (Attachment)attachment; - } - else - { - JObject serializedPropertyBag = JObject.FromObject(attachment); - Attachment typeAttachment = new Attachment(); - typeAttachment.propertyBag = serializedPropertyBag; - typeAttachment.SerializerSettings = settings; - return typeAttachment; - } - } - return null; - } - - //Property Getter/Setter for Expandable User property. - private object GetProperty( - string propertyName, Type returnType) - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if (token != null) - { - return this.SerializerSettings == null ? - token.ToObject(returnType) : - token.ToObject(returnType, JsonSerializer.Create(this.SerializerSettings)); - } - } - - //Any property not in JSON throw exception rather than returning null. - throw new DocumentClientException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.PropertyNotFound, - propertyName), null, null); - } - - private object SetProperty(string propertyName, object value) - { - if (value != null) - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - this.propertyBag[propertyName] = JToken.FromObject(value); - } - else - { - if (this.propertyBag != null) - { - this.propertyBag.Remove(propertyName); - } - } - return value; - } - - private T AsType() //To convert Attachment to any type. - { - if (typeof(T) == typeof(Attachment) || typeof(T) == typeof(object)) - { - return (T)(object)this; - } - - if (this.propertyBag == null) - { - return default(T); - } - - //Materialize the type. - T result = this.SerializerSettings == null ? - (T)this.propertyBag.ToObject() : - (T)this.propertyBag.ToObject(JsonSerializer.Create(this.SerializerSettings)); - - return result; - } - - DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) - { - return new AttachmentDynamicMetaObject(this, parameter); - } - - private class AttachmentDynamicMetaObject : DynamicMetaObject - { - private readonly Attachment attachment; - - public AttachmentDynamicMetaObject(Attachment attachment, Expression expression) - : base(expression, BindingRestrictions.Empty, attachment) - { - this.attachment = attachment; - } - - public override DynamicMetaObject BindGetMember(GetMemberBinder binder) - { - if (AttachmentDynamicMetaObject.IsResourceProperty(binder.Name)) - { - return base.BindGetMember(binder); //Base will bind it statically. - } - - //For all non-resource property, thunk the call to GetProperty method in Attachment. - string methodName = "GetProperty"; - - //Two parameters. - Expression[] parameters = new Expression[] - { - Expression.Constant(binder.Name), //PropertyName - Expression.Constant(binder.ReturnType) //Expected Return Type. - }; - - //Expression: this. - Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); - - //Expression: this.GetProperty(name, returnType); - Expression getPropertyExpression = Expression.Call( - thisExpression, - typeof(Attachment).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - parameters); - - DynamicMetaObject getProperty = new DynamicMetaObject( - getPropertyExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return getProperty; - } - - public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) - { - if (AttachmentDynamicMetaObject.IsResourceProperty(binder.Name)) - { - return base.BindSetMember(binder, value); //Base will bind it statically. - } - - //For all non-resource property, thunk the call to this.SetProperty method in Attachment. - string methodName = "SetProperty"; - - // setup the binding restrictions. - BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); - - //Two params, Name & Value. - Expression[] args = new Expression[2]; - args[0] = Expression.Constant(binder.Name); - args[1] = Expression.Convert(value.Expression, typeof(object)); - - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - // Setup the method call expression - Expression methodCall = Expression.Call(self, - typeof(Attachment).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - args); - - // Create a meta object to invoke Set later: - DynamicMetaObject setProperty = new DynamicMetaObject( - methodCall, - restrictions); - // return that dynamic object - return setProperty; - } - - public override DynamicMetaObject BindConvert(ConvertBinder binder) - { - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - MethodCallExpression methodExpression = Expression.Call( - self, - typeof(Attachment).GetMethod("AsType", - BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); - - //Create a meta object to invoke AsType later. - DynamicMetaObject castOperator = new DynamicMetaObject( - methodExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return castOperator; - } - - public override IEnumerable GetDynamicMemberNames() - { - List dynamicMembers = new List(); - foreach (KeyValuePair pair in this.attachment.propertyBag) - { - // exclude the resource property and static properties - if (!IsResourceSerializedProperty(pair.Key)) - { - dynamicMembers.Add(pair.Key); - } - - } - return dynamicMembers; - } - - internal static bool IsResourceSerializedProperty(string propertyName) - { - if (propertyName == Constants.Properties.Id || - propertyName == Constants.Properties.RId || - propertyName == Constants.Properties.ETag || - propertyName == Constants.Properties.LastModified || - propertyName == Constants.Properties.SelfLink || - propertyName == Constants.Properties.ContentType || - propertyName == Constants.Properties.MediaLink) - { - return true; - } - return false; - } - - //List of Static Property in Attachment which we dont want to thunk. - internal static bool IsResourceProperty(string propertyName) - { - if (propertyName == "Id" || - propertyName == "ResourceId" || - propertyName == "ETag" || - propertyName == "Timestamp" || - propertyName == "SelfLink" || - propertyName == "MediaLink" || - propertyName == "ContentType") - { - return true; - } - return false; - } - } - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Dynamic; + using System.Globalization; + using System.Linq.Expressions; + using System.Reflection; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents a document attachment in the Azure Cosmos DB service. + /// + /// + /// Each document may contain zero or more attachments containing data of arbitrary formats like images, binary or large text blobs. + /// The Attachment class represents the Azure Cosmos DB resource used to store information about the attachment like its location and + /// MIME content type. The payload itself ("Media") is referenced through the MediaLink property. The Attachment class is a DynamicObject + /// and can contain any custom metadata to be persisted. + /// + /// Attachments can be created as managed or unmanaged. If attachments are created as managed through Azure Cosmos DB, then it is assigned a system + /// generated mediaLink. Azure Cosmos DB then automatically performs garbage collection on the media when parent document is deleted. + /// + /// You can reuse the mediaLink property to store an external location e.g., a file share or an Azure Blob Storage URI. + /// Azure Cosmos DB will not perform garbage collection on mediaLinks for external locations. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Attachment : Resource, IDynamicMetaObjectProvider + { + /// + /// Initializes a new instance of an class for the Azure Cosmos DB service. + /// + public Attachment() + { + + } + + /// + /// Gets or sets the MIME content type of the attachment in the Azure Cosmos DB service. + /// + /// + /// The MIME content type of the attachment. + /// + /// For example, set to "text/plain" for text files, "image/jpeg" for images. + [JsonProperty(PropertyName = Constants.Properties.ContentType)] + public string ContentType + { + get + { + return base.GetValue(Constants.Properties.ContentType); + } + set + { + base.SetValue(Constants.Properties.ContentType, value); + } + } + + /// + /// Gets or sets the media link associated with the attachment content in the Azure Cosmos DB service. + /// + /// + /// The media link associated with the attachment content. + /// + /// Azure Cosmos DB supports both managed and unmanaged attachments. + [JsonProperty(PropertyName = Constants.Properties.MediaLink)] + public string MediaLink + { + get + { + return base.GetValue(Constants.Properties.MediaLink); + } + set + { + base.SetValue(Constants.Properties.MediaLink, value); + } + } + + //Helper to materialize Attachment from any .NET object. + internal static Attachment FromObject(object attachment, JsonSerializerSettings settings = null) + { + if (attachment != null) + { + if (typeof(Attachment).IsAssignableFrom(attachment.GetType())) + { + return (Attachment)attachment; + } + else + { + JObject serializedPropertyBag = JObject.FromObject(attachment); + Attachment typeAttachment = new Attachment(); + typeAttachment.propertyBag = serializedPropertyBag; + typeAttachment.SerializerSettings = settings; + return typeAttachment; + } + } + return null; + } + + //Property Getter/Setter for Expandable User property. + private object GetProperty( + string propertyName, Type returnType) + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if (token != null) + { + return this.SerializerSettings == null ? + token.ToObject(returnType) : + token.ToObject(returnType, JsonSerializer.Create(this.SerializerSettings)); + } + } + + //Any property not in JSON throw exception rather than returning null. + throw new DocumentClientException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.PropertyNotFound, + propertyName), null, null); + } + + private object SetProperty(string propertyName, object value) + { + if (value != null) + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + this.propertyBag[propertyName] = JToken.FromObject(value); + } + else + { + if (this.propertyBag != null) + { + this.propertyBag.Remove(propertyName); + } + } + return value; + } + + private T AsType() //To convert Attachment to any type. + { + if (typeof(T) == typeof(Attachment) || typeof(T) == typeof(object)) + { + return (T)(object)this; + } + + if (this.propertyBag == null) + { + return default(T); + } + + //Materialize the type. + T result = this.SerializerSettings == null ? + (T)this.propertyBag.ToObject() : + (T)this.propertyBag.ToObject(JsonSerializer.Create(this.SerializerSettings)); + + return result; + } + + DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) + { + return new AttachmentDynamicMetaObject(this, parameter); + } + + private class AttachmentDynamicMetaObject : DynamicMetaObject + { + private readonly Attachment attachment; + + public AttachmentDynamicMetaObject(Attachment attachment, Expression expression) + : base(expression, BindingRestrictions.Empty, attachment) + { + this.attachment = attachment; + } + + public override DynamicMetaObject BindGetMember(GetMemberBinder binder) + { + if (AttachmentDynamicMetaObject.IsResourceProperty(binder.Name)) + { + return base.BindGetMember(binder); //Base will bind it statically. + } + + //For all non-resource property, thunk the call to GetProperty method in Attachment. + string methodName = "GetProperty"; + + //Two parameters. + Expression[] parameters = new Expression[] + { + Expression.Constant(binder.Name), //PropertyName + Expression.Constant(binder.ReturnType) //Expected Return Type. + }; + + //Expression: this. + Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); + + //Expression: this.GetProperty(name, returnType); + Expression getPropertyExpression = Expression.Call( + thisExpression, + typeof(Attachment).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + parameters); + + DynamicMetaObject getProperty = new DynamicMetaObject( + getPropertyExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return getProperty; + } + + public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) + { + if (AttachmentDynamicMetaObject.IsResourceProperty(binder.Name)) + { + return base.BindSetMember(binder, value); //Base will bind it statically. + } + + //For all non-resource property, thunk the call to this.SetProperty method in Attachment. + string methodName = "SetProperty"; + + // setup the binding restrictions. + BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); + + //Two params, Name & Value. + Expression[] args = new Expression[2]; + args[0] = Expression.Constant(binder.Name); + args[1] = Expression.Convert(value.Expression, typeof(object)); + + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + // Setup the method call expression + Expression methodCall = Expression.Call(self, + typeof(Attachment).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + args); + + // Create a meta object to invoke Set later: + DynamicMetaObject setProperty = new DynamicMetaObject( + methodCall, + restrictions); + // return that dynamic object + return setProperty; + } + + public override DynamicMetaObject BindConvert(ConvertBinder binder) + { + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + MethodCallExpression methodExpression = Expression.Call( + self, + typeof(Attachment).GetMethod("AsType", + BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); + + //Create a meta object to invoke AsType later. + DynamicMetaObject castOperator = new DynamicMetaObject( + methodExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return castOperator; + } + + public override IEnumerable GetDynamicMemberNames() + { + List dynamicMembers = new List(); + foreach (KeyValuePair pair in this.attachment.propertyBag) + { + // exclude the resource property and static properties + if (!IsResourceSerializedProperty(pair.Key)) + { + dynamicMembers.Add(pair.Key); + } + + } + return dynamicMembers; + } + + internal static bool IsResourceSerializedProperty(string propertyName) + { + if (propertyName == Constants.Properties.Id || + propertyName == Constants.Properties.RId || + propertyName == Constants.Properties.ETag || + propertyName == Constants.Properties.LastModified || + propertyName == Constants.Properties.SelfLink || + propertyName == Constants.Properties.ContentType || + propertyName == Constants.Properties.MediaLink) + { + return true; + } + return false; + } + + //List of Static Property in Attachment which we dont want to thunk. + internal static bool IsResourceProperty(string propertyName) + { + if (propertyName == "Id" || + propertyName == "ResourceId" || + propertyName == "ETag" || + propertyName == "Timestamp" || + propertyName == "SelfLink" || + propertyName == "MediaLink" || + propertyName == "ContentType") + { + return true; + } + return false; + } + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs b/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs index 4159928f46..f2f1cdd32c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs @@ -1,46 +1,46 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - - internal enum AuthorizationTokenType - { - Invalid, - PrimaryMasterKey, - PrimaryReadonlyMasterKey, - SecondaryMasterKey, - SecondaryReadonlyMasterKey, - SystemReadOnly, - SystemReadWrite, - SystemAll, - ResourceToken, - ComputeGatewayKey, - AadToken, - CompoundToken, - SasToken, - TokenCredential - } - - internal static class AuthorizationTokenTypeExtensions - { - private static readonly Dictionary CodeNameMap = new Dictionary(); - - static AuthorizationTokenTypeExtensions() - { - AuthorizationTokenTypeExtensions.CodeNameMap[default(int)] = string.Empty; - foreach (AuthorizationTokenType authorizationTokenType in Enum.GetValues(typeof(AuthorizationTokenType))) - { - AuthorizationTokenTypeExtensions.CodeNameMap[(int)authorizationTokenType] = authorizationTokenType.ToString(); - } - } - - public static string ToAuthorizationTokenTypeString(this Documents.AuthorizationTokenType code) - { - return AuthorizationTokenTypeExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + + internal enum AuthorizationTokenType + { + Invalid, + PrimaryMasterKey, + PrimaryReadonlyMasterKey, + SecondaryMasterKey, + SecondaryReadonlyMasterKey, + SystemReadOnly, + SystemReadWrite, + SystemAll, + ResourceToken, + ComputeGatewayKey, + AadToken, + CompoundToken, + SasToken, + TokenCredential + } + + internal static class AuthorizationTokenTypeExtensions + { + private static readonly Dictionary CodeNameMap = new Dictionary(); + + static AuthorizationTokenTypeExtensions() + { + AuthorizationTokenTypeExtensions.CodeNameMap[default(int)] = string.Empty; + foreach (AuthorizationTokenType authorizationTokenType in Enum.GetValues(typeof(AuthorizationTokenType))) + { + AuthorizationTokenTypeExtensions.CodeNameMap[(int)authorizationTokenType] = authorizationTokenType.ToString(); + } + } + + public static string ToAuthorizationTokenTypeString(this Documents.AuthorizationTokenType code) + { + return AuthorizationTokenTypeExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs b/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs index e24ef1a939..2def57999c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs @@ -1,251 +1,251 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Runtime.ExceptionServices; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - /// - /// Utility to retry operations based off retry policies. - /// - /// - /// This implementation differs from the one in SharedFiles on the fact that it does not check the cancellationToken status between capturing an error and evaluating the retry policy. - /// Ref: https://msdata.visualstudio.com/CosmosDB/_git/CosmosDB/pullrequest/550056 - /// - internal static class BackoffRetryUtility - { - public const string ExceptionSourceToIgnoreForIgnoreForRetry = "BackoffRetryUtility"; - - /// - /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. - /// - public static Task ExecuteAsync( - Func> callbackMethod, - IRetryPolicy retryPolicy, - CancellationToken cancellationToken = default(CancellationToken), - Action preRetryCallback = null) - { - return ExecuteRetryAsync( - callbackMethod, - callbackMethodWithParam: null, - callbackMethodWithPolicy: null, - param: default(object), - retryPolicy, - retryPolicyWithArg: null, - inBackoffAlternateCallbackMethod: null, - inBackoffAlternateCallbackMethodWithPolicy: null, - minBackoffForInBackoffCallback: TimeSpan.Zero, - cancellationToken, - preRetryCallback); - } - - public static Task ExecuteAsync( - Func> callbackMethod, - IRetryPolicy retryPolicy, - TParam param, - CancellationToken cancellationToken, - Action preRetryCallback = null) - { - return ExecuteRetryAsync( - callbackMethod: null, - callbackMethodWithParam: callbackMethod, - callbackMethodWithPolicy: null, - param, - retryPolicy, - retryPolicyWithArg: null, - inBackoffAlternateCallbackMethod: null, - inBackoffAlternateCallbackMethodWithPolicy: null, - minBackoffForInBackoffCallback: TimeSpan.Zero, - cancellationToken, - preRetryCallback); - } - - public static Task ExecuteAsync( - Func> callbackMethod, - IRetryPolicy retryPolicy, - CancellationToken cancellationToken = default(CancellationToken), - Action preRetryCallback = null) - { - return ExecuteRetryAsync( - callbackMethod: null, - callbackMethodWithParam: null, - callbackMethodWithPolicy: callbackMethod, - param: null, - retryPolicy: null, - retryPolicyWithArg: retryPolicy, - inBackoffAlternateCallbackMethod: null, - inBackoffAlternateCallbackMethodWithPolicy: null, - minBackoffForInBackoffCallback: TimeSpan.Zero, - cancellationToken, - preRetryCallback); - } - - public static Task ExecuteAsync( - Func> callbackMethod, - IRetryPolicy retryPolicy, - Func> inBackoffAlternateCallbackMethod, - TimeSpan minBackoffForInBackoffCallback, - CancellationToken cancellationToken = default(CancellationToken), - Action preRetryCallback = null) - { - return ExecuteRetryAsync( - callbackMethod, - callbackMethodWithParam: null, - callbackMethodWithPolicy: null, - param: default(object), - retryPolicy, - retryPolicyWithArg: null, - inBackoffAlternateCallbackMethod, - inBackoffAlternateCallbackMethodWithPolicy: null, - minBackoffForInBackoffCallback, - cancellationToken, - preRetryCallback); - } - - public static Task ExecuteAsync( - Func> callbackMethod, - IRetryPolicy retryPolicy, - Func> inBackoffAlternateCallbackMethod, - TimeSpan minBackoffForInBackoffCallback, - CancellationToken cancellationToken = default(CancellationToken), - Action preRetryCallback = null) - { - return ExecuteRetryAsync( - callbackMethod: null, - callbackMethodWithParam: null, - callbackMethodWithPolicy: callbackMethod, - param: null, - retryPolicy: null, - retryPolicyWithArg: retryPolicy, - inBackoffAlternateCallbackMethod: null, - inBackoffAlternateCallbackMethodWithPolicy: inBackoffAlternateCallbackMethod, - minBackoffForInBackoffCallback, - cancellationToken, - preRetryCallback); - } - - /// - /// Common implementation that handles all the different possible configurations. - /// - /// - /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. - /// - private static async Task ExecuteRetryAsync( - Func> callbackMethod, - Func> callbackMethodWithParam, - Func> callbackMethodWithPolicy, - TParam param, - IRetryPolicy retryPolicy, - IRetryPolicy retryPolicyWithArg, - Func> inBackoffAlternateCallbackMethod, - Func> inBackoffAlternateCallbackMethodWithPolicy, - TimeSpan minBackoffForInBackoffCallback, - CancellationToken cancellationToken, - Action preRetryCallback) - { - TPolicy policyArg1; - if (retryPolicyWithArg != null) - { - policyArg1 = retryPolicyWithArg.InitialArgumentValue; - } - else - { - policyArg1 = default; - } - - while (true) - { - try - { - cancellationToken.ThrowIfCancellationRequested(); - ExceptionDispatchInfo exception; - try - { - if (callbackMethod != null) - { - return await callbackMethod(); - } - else if (callbackMethodWithParam != null) - { - return await callbackMethodWithParam(param, cancellationToken); - } - - return await callbackMethodWithPolicy(policyArg1); - } - catch (Exception ex) - { - // this Yield is to "reset" the stack to avoid stack overflows in Framework - // and to keep the total size of the StackTrace down if we fail - await Task.Yield(); - - exception = ExceptionDispatchInfo.Capture(ex); - } - - ShouldRetryResult result; - if (retryPolicyWithArg != null) - { - ShouldRetryResult resultWithPolicy = await retryPolicyWithArg.ShouldRetryAsync(exception.SourceException, cancellationToken); - - policyArg1 = resultWithPolicy.PolicyArg1; - result = resultWithPolicy; - } - else - { - result = await retryPolicy.ShouldRetryAsync(exception.SourceException, cancellationToken); - } - - result.ThrowIfDoneTrying(exception); - - TimeSpan backoffTime = result.BackoffTime; - bool hasBackoffAlternateCallback = inBackoffAlternateCallbackMethod != null || inBackoffAlternateCallbackMethodWithPolicy != null; - - if (hasBackoffAlternateCallback && result.BackoffTime >= minBackoffForInBackoffCallback) - { - ValueStopwatch stopwatch = ValueStopwatch.StartNew(); - TimeSpan elapsed; - try - { - if (inBackoffAlternateCallbackMethod != null) - { - return await inBackoffAlternateCallbackMethod(); - } - - return await inBackoffAlternateCallbackMethodWithPolicy(policyArg1); - } - catch (Exception ex) - { - elapsed = stopwatch.Elapsed; - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), elapsed.TotalMilliseconds); - } - - backoffTime = result.BackoffTime > elapsed ? result.BackoffTime - elapsed : TimeSpan.Zero; - } - - if (preRetryCallback != null) - { - preRetryCallback(exception.SourceException); - } - - if (backoffTime != TimeSpan.Zero) - { - await Task.Delay(backoffTime, cancellationToken); - } - } - catch - { - // if we're going to completely fail, we want to toss all the async continuation - // stack frames so we don't have a gigantic stack trace (which has serious performance - // implications) - await Task.Yield(); - - throw; - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Runtime.ExceptionServices; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// Utility to retry operations based off retry policies. + /// + /// + /// This implementation differs from the one in SharedFiles on the fact that it does not check the cancellationToken status between capturing an error and evaluating the retry policy. + /// Ref: https://msdata.visualstudio.com/CosmosDB/_git/CosmosDB/pullrequest/550056 + /// + internal static class BackoffRetryUtility + { + public const string ExceptionSourceToIgnoreForIgnoreForRetry = "BackoffRetryUtility"; + + /// + /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. + /// + public static Task ExecuteAsync( + Func> callbackMethod, + IRetryPolicy retryPolicy, + CancellationToken cancellationToken = default(CancellationToken), + Action preRetryCallback = null) + { + return ExecuteRetryAsync( + callbackMethod, + callbackMethodWithParam: null, + callbackMethodWithPolicy: null, + param: default(object), + retryPolicy, + retryPolicyWithArg: null, + inBackoffAlternateCallbackMethod: null, + inBackoffAlternateCallbackMethodWithPolicy: null, + minBackoffForInBackoffCallback: TimeSpan.Zero, + cancellationToken, + preRetryCallback); + } + + public static Task ExecuteAsync( + Func> callbackMethod, + IRetryPolicy retryPolicy, + TParam param, + CancellationToken cancellationToken, + Action preRetryCallback = null) + { + return ExecuteRetryAsync( + callbackMethod: null, + callbackMethodWithParam: callbackMethod, + callbackMethodWithPolicy: null, + param, + retryPolicy, + retryPolicyWithArg: null, + inBackoffAlternateCallbackMethod: null, + inBackoffAlternateCallbackMethodWithPolicy: null, + minBackoffForInBackoffCallback: TimeSpan.Zero, + cancellationToken, + preRetryCallback); + } + + public static Task ExecuteAsync( + Func> callbackMethod, + IRetryPolicy retryPolicy, + CancellationToken cancellationToken = default(CancellationToken), + Action preRetryCallback = null) + { + return ExecuteRetryAsync( + callbackMethod: null, + callbackMethodWithParam: null, + callbackMethodWithPolicy: callbackMethod, + param: null, + retryPolicy: null, + retryPolicyWithArg: retryPolicy, + inBackoffAlternateCallbackMethod: null, + inBackoffAlternateCallbackMethodWithPolicy: null, + minBackoffForInBackoffCallback: TimeSpan.Zero, + cancellationToken, + preRetryCallback); + } + + public static Task ExecuteAsync( + Func> callbackMethod, + IRetryPolicy retryPolicy, + Func> inBackoffAlternateCallbackMethod, + TimeSpan minBackoffForInBackoffCallback, + CancellationToken cancellationToken = default(CancellationToken), + Action preRetryCallback = null) + { + return ExecuteRetryAsync( + callbackMethod, + callbackMethodWithParam: null, + callbackMethodWithPolicy: null, + param: default(object), + retryPolicy, + retryPolicyWithArg: null, + inBackoffAlternateCallbackMethod, + inBackoffAlternateCallbackMethodWithPolicy: null, + minBackoffForInBackoffCallback, + cancellationToken, + preRetryCallback); + } + + public static Task ExecuteAsync( + Func> callbackMethod, + IRetryPolicy retryPolicy, + Func> inBackoffAlternateCallbackMethod, + TimeSpan minBackoffForInBackoffCallback, + CancellationToken cancellationToken = default(CancellationToken), + Action preRetryCallback = null) + { + return ExecuteRetryAsync( + callbackMethod: null, + callbackMethodWithParam: null, + callbackMethodWithPolicy: callbackMethod, + param: null, + retryPolicy: null, + retryPolicyWithArg: retryPolicy, + inBackoffAlternateCallbackMethod: null, + inBackoffAlternateCallbackMethodWithPolicy: inBackoffAlternateCallbackMethod, + minBackoffForInBackoffCallback, + cancellationToken, + preRetryCallback); + } + + /// + /// Common implementation that handles all the different possible configurations. + /// + /// + /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. + /// + private static async Task ExecuteRetryAsync( + Func> callbackMethod, + Func> callbackMethodWithParam, + Func> callbackMethodWithPolicy, + TParam param, + IRetryPolicy retryPolicy, + IRetryPolicy retryPolicyWithArg, + Func> inBackoffAlternateCallbackMethod, + Func> inBackoffAlternateCallbackMethodWithPolicy, + TimeSpan minBackoffForInBackoffCallback, + CancellationToken cancellationToken, + Action preRetryCallback) + { + TPolicy policyArg1; + if (retryPolicyWithArg != null) + { + policyArg1 = retryPolicyWithArg.InitialArgumentValue; + } + else + { + policyArg1 = default; + } + + while (true) + { + try + { + cancellationToken.ThrowIfCancellationRequested(); + ExceptionDispatchInfo exception; + try + { + if (callbackMethod != null) + { + return await callbackMethod(); + } + else if (callbackMethodWithParam != null) + { + return await callbackMethodWithParam(param, cancellationToken); + } + + return await callbackMethodWithPolicy(policyArg1); + } + catch (Exception ex) + { + // this Yield is to "reset" the stack to avoid stack overflows in Framework + // and to keep the total size of the StackTrace down if we fail + await Task.Yield(); + + exception = ExceptionDispatchInfo.Capture(ex); + } + + ShouldRetryResult result; + if (retryPolicyWithArg != null) + { + ShouldRetryResult resultWithPolicy = await retryPolicyWithArg.ShouldRetryAsync(exception.SourceException, cancellationToken); + + policyArg1 = resultWithPolicy.PolicyArg1; + result = resultWithPolicy; + } + else + { + result = await retryPolicy.ShouldRetryAsync(exception.SourceException, cancellationToken); + } + + result.ThrowIfDoneTrying(exception); + + TimeSpan backoffTime = result.BackoffTime; + bool hasBackoffAlternateCallback = inBackoffAlternateCallbackMethod != null || inBackoffAlternateCallbackMethodWithPolicy != null; + + if (hasBackoffAlternateCallback && result.BackoffTime >= minBackoffForInBackoffCallback) + { + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + try + { + if (inBackoffAlternateCallbackMethod != null) + { + return await inBackoffAlternateCallbackMethod(); + } + + return await inBackoffAlternateCallbackMethodWithPolicy(policyArg1); + } + catch (Exception ex) + { + elapsed = stopwatch.Elapsed; + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), elapsed.TotalMilliseconds); + } + + backoffTime = result.BackoffTime > elapsed ? result.BackoffTime - elapsed : TimeSpan.Zero; + } + + if (preRetryCallback != null) + { + preRetryCallback(exception.SourceException); + } + + if (backoffTime != TimeSpan.Zero) + { + await Task.Delay(backoffTime, cancellationToken); + } + } + catch + { + // if we're going to completely fail, we want to toss all the async continuation + // stack frames so we don't have a gigantic stack trace (which has serious performance + // implications) + await Task.Yield(); + + throw; + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BadRequestException.cs b/Microsoft.Azure.Cosmos/src/direct/BadRequestException.cs index 556a5e1227..bbc11c7241 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BadRequestException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BadRequestException.cs @@ -1,70 +1,77 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class BadRequestException : DocumentClientException - { - public BadRequestException() - : this(RMResources.BadRequest) - { - - } - - public BadRequestException(string message) - : this(message, (Exception)null, null) - { - - } - - public BadRequestException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public BadRequestException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.BadRequest, requestUri) - { - SetDescription(); - } - - public BadRequestException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public BadRequestException(Exception innerException) - : this(RMResources.BadRequest, innerException, null) - { - - } - - public BadRequestException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.BadRequest, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private BadRequestException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.BadRequest) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.BadRequest; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class BadRequestException : DocumentClientException + { + public BadRequestException() + : this(RMResources.BadRequest) + { + + } + + public BadRequestException(string message) + : this(message, (Exception)null, null) + { + + } + + public BadRequestException(string message, bool rawErrorMessageOnly) + : this(message, (Exception)null, null, rawErrorMessageOnly: rawErrorMessageOnly) + { + + } + + public BadRequestException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public BadRequestException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.BadRequest, requestUri) + { + SetDescription(); + } + + public BadRequestException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public BadRequestException(Exception innerException) + : this(RMResources.BadRequest, innerException, null) + { + + } + + public BadRequestException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, + bool rawErrorMessageOnly = false) + : base(message, innerException, headers, HttpStatusCode.BadRequest, requestUri, rawErrorMessageOnly: rawErrorMessageOnly) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private BadRequestException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.BadRequest) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.BadRequest; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BarrierRequestHelper.cs b/Microsoft.Azure.Cosmos/src/direct/BarrierRequestHelper.cs index d7fa58f5bf..eb0df175d8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BarrierRequestHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BarrierRequestHelper.cs @@ -1,194 +1,303 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal static class BarrierRequestHelper - { - public static async Task CreateAsync( - DocumentServiceRequest request, - IAuthorizationTokenProvider authorizationTokenProvider, - long? targetLsn, - long? targetGlobalCommittedLsn) - { - bool isCollectionHeadRequest = BarrierRequestHelper.IsCollectionHeadBarrierRequest(request.ResourceType, request.OperationType); - - //serviceIdentity, if set to masterService, takes priority over above - if (request.ServiceIdentity != null) - { - if (request.ServiceIdentity.IsMasterService) - { - isCollectionHeadRequest = false; - } - } - - if (request.RequestAuthorizationTokenType == AuthorizationTokenType.Invalid) - { - string message = "AuthorizationTokenType not set for the read request"; - Debug.Assert(false, message); - DefaultTrace.TraceCritical(message); - } - - AuthorizationTokenType originalRequestTokenType = request.RequestAuthorizationTokenType; - - DocumentServiceRequest barrierLsnRequest = null; - if (!isCollectionHeadRequest) - { - // DB Feed - barrierLsnRequest = DocumentServiceRequest.Create( - operationType: OperationType.HeadFeed, - resourceId: null, - resourceType: ResourceType.Database, - headers: null, - authorizationTokenType: originalRequestTokenType); - } - else if (request.IsNameBased) // Name based server request - { - // get the collection full name - // dbs/{id}/colls/{collid}/ - string collectionLink = PathsHelper.GetCollectionPath(request.ResourceAddress); - barrierLsnRequest = DocumentServiceRequest.CreateFromName( - OperationType.Head, - collectionLink, - ResourceType.Collection, - originalRequestTokenType, - null); - } - else // RID based Server request - { - barrierLsnRequest = DocumentServiceRequest.Create( - OperationType.Head, - ResourceId.Parse(request.ResourceId).DocumentCollectionId.ToString(), - ResourceType.Collection, null, originalRequestTokenType); - } - - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow(); - - if (targetLsn.HasValue && targetLsn.Value > 0) - { - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.TargetLsn] = targetLsn.Value.ToString(CultureInfo.InvariantCulture); - } - - if (targetGlobalCommittedLsn.HasValue && targetGlobalCommittedLsn.Value > 0) - { - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.TargetGlobalCommittedLsn] = targetGlobalCommittedLsn.Value.ToString(CultureInfo.InvariantCulture); - } - - switch (originalRequestTokenType) - { - case AuthorizationTokenType.PrimaryMasterKey: - case AuthorizationTokenType.PrimaryReadonlyMasterKey: - case AuthorizationTokenType.SecondaryMasterKey: - case AuthorizationTokenType.SecondaryReadonlyMasterKey: - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.Authorization] = (await authorizationTokenProvider.GetUserAuthorizationAsync( - barrierLsnRequest.ResourceAddress, - isCollectionHeadRequest ? PathsHelper.GetResourcePath(ResourceType.Collection) : PathsHelper.GetResourcePath(ResourceType.Database), - HttpConstants.HttpMethods.Head, - barrierLsnRequest.Headers, - originalRequestTokenType)).token; - break; - - case AuthorizationTokenType.SystemAll: - case AuthorizationTokenType.SystemReadOnly: - case AuthorizationTokenType.SystemReadWrite: - if (request.RequestContext.TargetIdentity == null) - { - DefaultTrace.TraceCritical("TargetIdentity is needed to create the ReadBarrier request"); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - - await authorizationTokenProvider.AddSystemAuthorizationHeaderAsync( - barrierLsnRequest, - ((ServiceIdentity)request.RequestContext.TargetIdentity).FederationId, - HttpConstants.HttpMethods.Head, - resourceId: null); - break; - - case AuthorizationTokenType.AadToken: - case AuthorizationTokenType.ResourceToken: - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.Authorization] = request.Headers[HttpConstants.HttpHeaders.Authorization]; - break; - - default: - string unknownAuthToken = $"Unknown authorization token kind [{originalRequestTokenType}] for read request"; - Debug.Assert(false, unknownAuthToken); - DefaultTrace.TraceCritical(unknownAuthToken); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - - barrierLsnRequest.RequestContext = request.RequestContext.Clone(); - - if (request.ServiceIdentity != null) - { - barrierLsnRequest.RouteTo(request.ServiceIdentity); - } - if (request.PartitionKeyRangeIdentity != null) - { - barrierLsnRequest.RouteTo(request.PartitionKeyRangeIdentity); - } - if (request.Headers[HttpConstants.HttpHeaders.PartitionKey] != null) - { - barrierLsnRequest.Headers[HttpConstants.HttpHeaders.PartitionKey] = request.Headers[HttpConstants.HttpHeaders.PartitionKey]; - } - if (request.Headers[WFConstants.BackendHeaders.CollectionRid] != null) - { - barrierLsnRequest.Headers[WFConstants.BackendHeaders.CollectionRid] = request.Headers[WFConstants.BackendHeaders.CollectionRid]; - } - - if (request.Properties != null && request.Properties.ContainsKey(WFConstants.BackendHeaders.EffectivePartitionKeyString)) - { - if (barrierLsnRequest.Properties == null) - { - barrierLsnRequest.Properties = new Dictionary(); - } - - barrierLsnRequest.Properties[WFConstants.BackendHeaders.EffectivePartitionKeyString] = request.Properties[WFConstants.BackendHeaders.EffectivePartitionKeyString]; - } - - return barrierLsnRequest; - } - - internal static bool IsCollectionHeadBarrierRequest(ResourceType resourceType, OperationType operationType) - { - switch(resourceType) - { - case ResourceType.Attachment: - case ResourceType.Document: - case ResourceType.Conflict: - case ResourceType.StoredProcedure: - case ResourceType.UserDefinedFunction: - case ResourceType.Trigger: - case ResourceType.SystemDocument: - case ResourceType.PartitionedSystemDocument: - return true; - case ResourceType.Collection: - if (operationType != OperationType.ReadFeed && operationType != OperationType.Query && operationType != OperationType.SqlQuery) - { - return true; - } - else - { - return false; - } - case ResourceType.PartitionKeyRange: -#if !COSMOSCLIENT - if (operationType == OperationType.GetSplitPoint || operationType == OperationType.AbortSplit || operationType == OperationType.GetSplitPoints) - { - return true; - } -#endif - return false; - default: - return false; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal static class BarrierRequestHelper + { + private const bool OldBarrierRequestHandlingEnabledDefault = false; + private const int extensiveLsnGapThreshold = 10_000; + private const int highLsnGapThreshold = 1_000; + private const int mediumLsnGapThreshold = 100; + + private static readonly TimeSpan extensiveLsnGapDelayBetweenWriteBarrierCalls = TimeSpan.FromMilliseconds(1000); + private static readonly TimeSpan highLsnGapDelayBetweenWriteBarrierCalls = TimeSpan.FromMilliseconds(100); + private static readonly TimeSpan mediumLsnGapDelayBetweenWriteBarrierCalls = TimeSpan.FromMilliseconds(10); + private static readonly bool isOldBarrierRequestHandlingEnabled = Helpers.GetSafeEnvironmentVariable( + Constants.EnvironmentVariables.OldBarrierRequestHandlingEnabled, + OldBarrierRequestHandlingEnabledDefault); + + public static async Task CreateAsync( + DocumentServiceRequest request, + IAuthorizationTokenProvider authorizationTokenProvider, + long? targetLsn, + long? targetGlobalCommittedLsn) + { + bool isCollectionHeadRequest = BarrierRequestHelper.IsCollectionHeadBarrierRequest(request.ResourceType, request.OperationType); + + //serviceIdentity, if set to masterService, takes priority over above + if (request.ServiceIdentity != null) + { + if (request.ServiceIdentity.IsMasterService) + { + isCollectionHeadRequest = false; + } + } + + if (request.RequestAuthorizationTokenType == AuthorizationTokenType.Invalid) + { + string message = "AuthorizationTokenType not set for the read request"; + Debug.Assert(false, message); + DefaultTrace.TraceCritical(message); + } + + AuthorizationTokenType originalRequestTokenType = request.RequestAuthorizationTokenType; + + DocumentServiceRequest barrierLsnRequest = null; + if (!isCollectionHeadRequest) + { + // DB Feed + barrierLsnRequest = DocumentServiceRequest.Create( + operationType: OperationType.HeadFeed, + resourceId: null, + resourceType: ResourceType.Database, + headers: null, + authorizationTokenType: originalRequestTokenType); + } + else if (request.IsNameBased) // Name based server request + { + // get the collection full name + // dbs/{id}/colls/{collid}/ + string collectionLink = PathsHelper.GetCollectionPath(request.ResourceAddress); + barrierLsnRequest = DocumentServiceRequest.CreateFromName( + OperationType.Head, + collectionLink, + ResourceType.Collection, + originalRequestTokenType, + null); + } + else // RID based Server request + { + barrierLsnRequest = DocumentServiceRequest.Create( + OperationType.Head, + ResourceId.Parse(request.ResourceId).DocumentCollectionId.ToString(), + ResourceType.Collection, null, originalRequestTokenType); + } + + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.XDate] = Rfc1123DateTimeCache.UtcNow(); + + if (targetLsn.HasValue && targetLsn.Value > 0) + { + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.TargetLsn] = targetLsn.Value.ToString(CultureInfo.InvariantCulture); + } + + if (targetGlobalCommittedLsn.HasValue && targetGlobalCommittedLsn.Value > 0) + { + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.TargetGlobalCommittedLsn] = targetGlobalCommittedLsn.Value.ToString(CultureInfo.InvariantCulture); + } + + switch (originalRequestTokenType) + { + case AuthorizationTokenType.PrimaryMasterKey: + case AuthorizationTokenType.PrimaryReadonlyMasterKey: + case AuthorizationTokenType.SecondaryMasterKey: + case AuthorizationTokenType.SecondaryReadonlyMasterKey: + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.Authorization] = (await authorizationTokenProvider.GetUserAuthorizationAsync( + barrierLsnRequest.ResourceAddress, + isCollectionHeadRequest ? PathsHelper.GetResourcePath(ResourceType.Collection) : PathsHelper.GetResourcePath(ResourceType.Database), + HttpConstants.HttpMethods.Head, + barrierLsnRequest.Headers, + originalRequestTokenType)).token; + break; + + case AuthorizationTokenType.SystemAll: + case AuthorizationTokenType.SystemReadOnly: + case AuthorizationTokenType.SystemReadWrite: + if (request.RequestContext.TargetIdentity == null) + { + DefaultTrace.TraceCritical("TargetIdentity is needed to create the ReadBarrier request"); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + + await authorizationTokenProvider.AddSystemAuthorizationHeaderAsync( + barrierLsnRequest, + ((ServiceIdentity)request.RequestContext.TargetIdentity).FederationId, + HttpConstants.HttpMethods.Head, + resourceId: null); + break; + + case AuthorizationTokenType.AadToken: + case AuthorizationTokenType.ResourceToken: + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.Authorization] = request.Headers[HttpConstants.HttpHeaders.Authorization]; + break; + + default: + string unknownAuthToken = $"Unknown authorization token kind [{originalRequestTokenType}] for read request"; + Debug.Assert(false, unknownAuthToken); + DefaultTrace.TraceCritical(unknownAuthToken); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + + barrierLsnRequest.RequestContext = request.RequestContext.Clone(); + + if (request.ServiceIdentity != null) + { + barrierLsnRequest.RouteTo(request.ServiceIdentity); + } + if (request.PartitionKeyRangeIdentity != null) + { + barrierLsnRequest.RouteTo(request.PartitionKeyRangeIdentity); + } + if (request.Headers[HttpConstants.HttpHeaders.PartitionKey] != null) + { + barrierLsnRequest.Headers[HttpConstants.HttpHeaders.PartitionKey] = request.Headers[HttpConstants.HttpHeaders.PartitionKey]; + } + if (request.Headers[WFConstants.BackendHeaders.CollectionRid] != null) + { + barrierLsnRequest.Headers[WFConstants.BackendHeaders.CollectionRid] = request.Headers[WFConstants.BackendHeaders.CollectionRid]; + } + + if (request.Properties != null && request.Properties.ContainsKey(WFConstants.BackendHeaders.EffectivePartitionKeyString)) + { + if (barrierLsnRequest.Properties == null) + { + barrierLsnRequest.Properties = new Dictionary(); + } + + barrierLsnRequest.Properties[WFConstants.BackendHeaders.EffectivePartitionKeyString] = request.Properties[WFConstants.BackendHeaders.EffectivePartitionKeyString]; + } + + return barrierLsnRequest; + } + + internal static bool IsOldBarrierRequestHandlingEnabled + { + get + { + return isOldBarrierRequestHandlingEnabled; + } + } + + internal static bool IsCollectionHeadBarrierRequest(ResourceType resourceType, OperationType operationType) + { + switch(resourceType) + { + case ResourceType.Attachment: + case ResourceType.Document: + case ResourceType.Conflict: + case ResourceType.StoredProcedure: + case ResourceType.UserDefinedFunction: + case ResourceType.Trigger: + case ResourceType.SystemDocument: + case ResourceType.PartitionedSystemDocument: + return true; + case ResourceType.Collection: + if (operationType != OperationType.ReadFeed && operationType != OperationType.Query && operationType != OperationType.SqlQuery) + { + return true; + } + else + { + return false; + } + case ResourceType.PartitionKeyRange: +#if !COSMOSCLIENT + if (operationType == OperationType.GetSplitPoint || operationType == OperationType.AbortSplit || operationType == OperationType.GetSplitPoints) + { + return true; + } +#endif + return false; + default: + return false; + } + } + + /// + /// Used to determine the appropriate back-off time between barrier requests based + /// on the responses to previous barrier requests. The substatus code of HEAD requests + /// indicate the gap - like how far the targeted LSN/GCLSN was missed. + /// As a very naive rule-of-thumb the assumpiton is that even for small documents less than 1 KB + /// only about 2000 write trasnactions can possibly be committed on a single phsyical + /// partition (10,000 RU / 5 RU at least per write operation). The allowed + /// throughput per physical partition could grow and the min. RU per write operations + /// could be reduced. There are also scenarios like copying where replication progress + /// is much faster. So, above is only a vague estimate and the injected delays are more + /// reluctant (assuming up-to 10,000 transactions could be replicated within a second). + /// The delay will also be reduced by the backend latency (in case backend also uses + /// config to inject delay for HEAD requests) - but will at least be as high as before + /// modifying the back-off based on the SubStatusCodes of the HEAD request. + /// The motivation for this change was to reduce the number of barrier requests + /// because they could cause high CPU usage on the backend when a global strong account + /// has at least one partition where one of the read regions is not progressing. + /// + /// Latency for the last HEAD request + /// Responses for the last barrier request + /// The minimum delay that should at least be injected + /// The max delay that should be injected + /// + /// A flag indicating whether a delay before the next barrier request should be injected. + /// + internal static bool ShouldDelayBetweenHeadRequests( + TimeSpan previousHeadRequestLatency, + IList> responses, + TimeSpan minDelay, + out TimeSpan delay) + { + int minLSNGap = Int32.MaxValue; + foreach (ReferenceCountedDisposable response in responses) + { + if (response.Target.StatusCode == StatusCodes.NoContent) + { + switch (response.Target.SubStatusCode) + { + case SubStatusCodes.MissedTargetGlobalCommittedLsnOver100: + minLSNGap = Math.Min(100, minLSNGap); + break; + case SubStatusCodes.MissedTargetGlobalCommittedLsnOver1000: + minLSNGap = Math.Min(1000, minLSNGap); + break; + case SubStatusCodes.MissedTargetGlobalCommittedLsnOver10000: + minLSNGap = Math.Min(10000, minLSNGap); + break; + default: + minLSNGap = 1; + break; + } + } + } + + TimeSpan delayCandidate = GetDelayBetweenHeadRequests(minLSNGap) - previousHeadRequestLatency; + if (delayCandidate > minDelay) + { + delay = delayCandidate; + return true; + } + + delay = minDelay; + return minDelay > TimeSpan.Zero; + } + + private static TimeSpan GetDelayBetweenHeadRequests(int minLSNGap) + { + if (minLSNGap == Int32.MaxValue) + { + return TimeSpan.Zero; + } + + if (minLSNGap >= extensiveLsnGapThreshold) + { + return extensiveLsnGapDelayBetweenWriteBarrierCalls; + } + + if (minLSNGap >= highLsnGapThreshold) + { + return highLsnGapDelayBetweenWriteBarrierCalls; + } + + if (minLSNGap >= mediumLsnGapThreshold) + { + return mediumLsnGapDelayBetweenWriteBarrierCalls; + } + + return TimeSpan.Zero; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BitUtils.cs b/Microsoft.Azure.Cosmos/src/direct/BitUtils.cs index d59bad7f68..aae44ee8e6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BitUtils.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BitUtils.cs @@ -1,97 +1,97 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Documents -{ - /// - /// List of utility for doing bit (hacks). - /// - internal static class BitUtils - { - /// - /// https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers - /// - private static readonly int[] tab64 = new int[] - { - 63, 0, 58, 1, 59, 47, 53, 2, - 60, 39, 48, 27, 54, 33, 42, 3, - 61, 51, 37, 40, 49, 18, 28, 20, - 55, 30, 34, 11, 43, 14, 22, 4, - 62, 57, 46, 52, 38, 26, 32, 41, - 50, 36, 17, 19, 29, 10, 13, 21, - 56, 45, 25, 31, 35, 16, 9, 12, - 44, 24, 15, 8, 23, 7, 6, 5 - }; - - public static long GetMostSignificantBit(long x) - { - // http://aggregate.org/MAGIC/#Most%20Significant%201%20Bit - // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) - // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. - // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. - // Bitwise AND of the original value with the complement of the "folded" value shifted down by one yields the most significant bit. - // For a 64-bit value: - - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - x |= (x >> 32); - return (x & ~(x >> 1)); - } - - public static int FloorLog2(ulong value) - { - value |= value >> 1; - value |= value >> 2; - value |= value >> 4; - value |= value >> 8; - value |= value >> 16; - value |= value >> 32; - return tab64[((ulong)((value - (value >> 1)) * 0x07EDD5E59A4E28C2)) >> 58]; - } - - public static bool IsPowerOf2(ulong x) - { - return (x & (x - 1)) == 0; - } - - public static int GetMostSignificantBitIndex(ulong x) - { - return BitUtils.FloorLog2(x); - } - - public static long GetLeastSignificantBit(long x) - { - // http://aggregate.org/MAGIC/#Least%20Significant%201%20Bit - // Given a 2's complement binary integer value x, (x&-x) is the least significant 1 bit. - // (This was pointed-out by Tom May.) - // The reason this works is that it is equivalent to (x & ((~x) + 1)); - // any trailing zero bits in x become ones in ~x, - // adding 1 to that carries into the following bit, - // and AND with x yields only the flipped bit... the original position of the least significant 1 bit. - - return (int)(x & -x); - } - - public static int GetLeastSignificantBitIndex(long x) - { - return BitUtils.FloorLog2((ulong)BitUtils.GetLeastSignificantBit(x)); - } - - //examines bit b of the address a, returns its current value, and resets the bit to 0. - public static bool BitTestAndReset64(long input, int index, out long output) - { - // https://stackoverflow.com/questions/2431732/checking-if-a-bit-is-set-or-not - bool set = (input & (1L << index)) != 0; - - // https://www.dotnetperls.com/set-bit-zero - output = (input &= ~(1L << index)); - - return set; - } - } -} +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Documents +{ + /// + /// List of utility for doing bit (hacks). + /// + internal static class BitUtils + { + /// + /// https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers + /// + private static readonly int[] tab64 = new int[] + { + 63, 0, 58, 1, 59, 47, 53, 2, + 60, 39, 48, 27, 54, 33, 42, 3, + 61, 51, 37, 40, 49, 18, 28, 20, + 55, 30, 34, 11, 43, 14, 22, 4, + 62, 57, 46, 52, 38, 26, 32, 41, + 50, 36, 17, 19, 29, 10, 13, 21, + 56, 45, 25, 31, 35, 16, 9, 12, + 44, 24, 15, 8, 23, 7, 6, 5 + }; + + public static long GetMostSignificantBit(long x) + { + // http://aggregate.org/MAGIC/#Most%20Significant%201%20Bit + // Given a binary integer value x, the most significant 1 bit (highest numbered element of a bit set) + // can be computed using a SWAR algorithm that recursively "folds" the upper bits into the lower bits. + // This process yields a bit vector with the same most significant 1 as x, but all 1's below it. + // Bitwise AND of the original value with the complement of the "folded" value shifted down by one yields the most significant bit. + // For a 64-bit value: + + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + x |= (x >> 32); + return (x & ~(x >> 1)); + } + + public static int FloorLog2(ulong value) + { + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + value |= value >> 32; + return tab64[((ulong)((value - (value >> 1)) * 0x07EDD5E59A4E28C2)) >> 58]; + } + + public static bool IsPowerOf2(ulong x) + { + return (x & (x - 1)) == 0; + } + + public static int GetMostSignificantBitIndex(ulong x) + { + return BitUtils.FloorLog2(x); + } + + public static long GetLeastSignificantBit(long x) + { + // http://aggregate.org/MAGIC/#Least%20Significant%201%20Bit + // Given a 2's complement binary integer value x, (x&-x) is the least significant 1 bit. + // (This was pointed-out by Tom May.) + // The reason this works is that it is equivalent to (x & ((~x) + 1)); + // any trailing zero bits in x become ones in ~x, + // adding 1 to that carries into the following bit, + // and AND with x yields only the flipped bit... the original position of the least significant 1 bit. + + return (int)(x & -x); + } + + public static int GetLeastSignificantBitIndex(long x) + { + return BitUtils.FloorLog2((ulong)BitUtils.GetLeastSignificantBit(x)); + } + + //examines bit b of the address a, returns its current value, and resets the bit to 0. + public static bool BitTestAndReset64(long input, int index, out long output) + { + // https://stackoverflow.com/questions/2431732/checking-if-a-bit-is-set-or-not + bool set = (input & (1L << index)) != 0; + + // https://www.dotnetperls.com/set-bit-zero + output = (input &= ~(1L << index)); + + return set; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BoolPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/BoolPartitionKeyComponent.cs index 7b3dcbfb33..153c756c6e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BoolPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BoolPartitionKeyComponent.cs @@ -1,71 +1,71 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class BoolPartitionKeyComponent : IPartitionKeyComponent - { - private readonly bool value; - - public BoolPartitionKeyComponent(bool value) - { - this.value = value; - } - - public int CompareTo(IPartitionKeyComponent other) - { - BoolPartitionKeyComponent otherBool = other as BoolPartitionKeyComponent; - if (otherBool == null) - { - throw new ArgumentException("other"); - } - - return Math.Sign((this.value ? 1 : 0) - (otherBool.value ? 1 : 0)); - } - - public int GetTypeOrdinal() - { - return (int)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False); - } - - public override int GetHashCode() - { - return this.value.GetHashCode(); - } - - public void JsonEncode(JsonWriter writer) - { - writer.WriteValue(this.value); - } - - public object ToObject() - { - return this.value; - } - - public IPartitionKeyComponent Truncate() - { - return this; - } - - public void WriteForHashing(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); - } - - public void WriteForHashingV2(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class BoolPartitionKeyComponent : IPartitionKeyComponent + { + private readonly bool value; + + public BoolPartitionKeyComponent(bool value) + { + this.value = value; + } + + public int CompareTo(IPartitionKeyComponent other) + { + BoolPartitionKeyComponent otherBool = other as BoolPartitionKeyComponent; + if (otherBool == null) + { + throw new ArgumentException("other"); + } + + return Math.Sign((this.value ? 1 : 0) - (otherBool.value ? 1 : 0)); + } + + public int GetTypeOrdinal() + { + return (int)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False); + } + + public override int GetHashCode() + { + return this.value.GetHashCode(); + } + + public void JsonEncode(JsonWriter writer) + { + writer.WriteValue(this.value); + } + + public object ToObject() + { + return this.value; + } + + public IPartitionKeyComponent Truncate() + { + return this; + } + + public void WriteForHashing(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); + } + + public void WriteForHashingV2(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)(this.value ? PartitionKeyComponentType.True : PartitionKeyComponentType.False)); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BoundingBoxSpec.cs b/Microsoft.Azure.Cosmos/src/direct/BoundingBoxSpec.cs index 410e21c1fb..d05768c3c7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BoundingBoxSpec.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BoundingBoxSpec.cs @@ -1,128 +1,128 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Represents bounding box for geometry spatial path in the Azure Cosmos DB service - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class BoundingBoxSpec : JsonSerializable, ICloneable - { - /// - /// Gets the x-coordinate of the lower-left corner of the bounding box. - /// - [JsonProperty(PropertyName = Constants.Properties.Xmin)] - public double Xmin - { - get - { - return base.GetValue(Constants.Properties.Xmin); - } - set - { - base.SetValue(Constants.Properties.Xmin, value); - } - } - - /// - /// Gets the y-coordinate of the lower-left corner of the bounding box. - /// - [JsonProperty(PropertyName = Constants.Properties.Ymin)] - public double Ymin - { - get - { - return base.GetValue(Constants.Properties.Ymin); - } - set - { - base.SetValue(Constants.Properties.Ymin, value); - } - } - - /// - /// Gets the x-coordinate of the upper-right corner of the bounding box. - /// - [JsonProperty(PropertyName = Constants.Properties.Xmax)] - public double Xmax - { - get - { - return base.GetValue(Constants.Properties.Xmax); - } - set - { - base.SetValue(Constants.Properties.Xmax, value); - } - } - - /// - /// Gets the y-coordinate of the upper-right corner of the bounding box. - /// - [JsonProperty(PropertyName = Constants.Properties.Ymax)] - public double Ymax - { - get - { - return base.GetValue(Constants.Properties.Ymax); - } - set - { - base.SetValue(Constants.Properties.Ymax, value); - } - } - - public object Clone() - { - BoundingBoxSpec cloned = new BoundingBoxSpec(); - cloned.Xmin = this.Xmin; - cloned.Ymin = this.Ymin; - cloned.Xmax = this.Xmax; - cloned.Ymax = this.Ymax; - - return cloned; - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Xmin); - base.GetValue(Constants.Properties.Ymin); - base.GetValue(Constants.Properties.Xmax); - base.GetValue(Constants.Properties.Ymax); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Represents bounding box for geometry spatial path in the Azure Cosmos DB service + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class BoundingBoxSpec : JsonSerializable, ICloneable + { + /// + /// Gets the x-coordinate of the lower-left corner of the bounding box. + /// + [JsonProperty(PropertyName = Constants.Properties.Xmin)] + public double Xmin + { + get + { + return base.GetValue(Constants.Properties.Xmin); + } + set + { + base.SetValue(Constants.Properties.Xmin, value); + } + } + + /// + /// Gets the y-coordinate of the lower-left corner of the bounding box. + /// + [JsonProperty(PropertyName = Constants.Properties.Ymin)] + public double Ymin + { + get + { + return base.GetValue(Constants.Properties.Ymin); + } + set + { + base.SetValue(Constants.Properties.Ymin, value); + } + } + + /// + /// Gets the x-coordinate of the upper-right corner of the bounding box. + /// + [JsonProperty(PropertyName = Constants.Properties.Xmax)] + public double Xmax + { + get + { + return base.GetValue(Constants.Properties.Xmax); + } + set + { + base.SetValue(Constants.Properties.Xmax, value); + } + } + + /// + /// Gets the y-coordinate of the upper-right corner of the bounding box. + /// + [JsonProperty(PropertyName = Constants.Properties.Ymax)] + public double Ymax + { + get + { + return base.GetValue(Constants.Properties.Ymax); + } + set + { + base.SetValue(Constants.Properties.Ymax, value); + } + } + + public object Clone() + { + BoundingBoxSpec cloned = new BoundingBoxSpec(); + cloned.Xmin = this.Xmin; + cloned.Ymin = this.Ymin; + cloned.Xmax = this.Xmax; + cloned.Ymax = this.Ymax; + + return cloned; + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Xmin); + base.GetValue(Constants.Properties.Ymin); + base.GetValue(Constants.Properties.Xmax); + base.GetValue(Constants.Properties.Ymax); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/BufferProvider.cs b/Microsoft.Azure.Cosmos/src/direct/BufferProvider.cs index b5d3ea232f..682b6d5880 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BufferProvider.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BufferProvider.cs @@ -1,51 +1,51 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Buffers; - - internal sealed class BufferProvider - { - private readonly ArrayPool arrayPool; - - public BufferProvider() - { - this.arrayPool = ArrayPool.Create(); - } - - public DisposableBuffer GetBuffer(int desiredLength) - { - return new DisposableBuffer(this, desiredLength); - } - - public struct DisposableBuffer : IDisposable - { - private readonly BufferProvider provider; - - public DisposableBuffer(byte[] buffer) - { - this.provider = null; - this.Buffer = new ArraySegment(buffer, 0, buffer.Length); - } - - public DisposableBuffer(BufferProvider provider, int desiredLength) - { - this.provider = provider; - this.Buffer = new ArraySegment(provider.arrayPool.Rent(desiredLength), 0, desiredLength); - } - - public ArraySegment Buffer { get; private set; } - - public void Dispose() - { - if (this.Buffer.Array != null) - { - this.provider?.arrayPool.Return(this.Buffer.Array); - this.Buffer = default; - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Buffers; + + internal sealed class BufferProvider + { + private readonly ArrayPool arrayPool; + + public BufferProvider() + { + this.arrayPool = ArrayPool.Create(); + } + + public DisposableBuffer GetBuffer(int desiredLength) + { + return new DisposableBuffer(this, desiredLength); + } + + public struct DisposableBuffer : IDisposable + { + private readonly BufferProvider provider; + + public DisposableBuffer(byte[] buffer) + { + this.provider = null; + this.Buffer = new ArraySegment(buffer, 0, buffer.Length); + } + + public DisposableBuffer(BufferProvider provider, int desiredLength) + { + this.provider = provider; + this.Buffer = new ArraySegment(provider.arrayPool.Rent(desiredLength), 0, desiredLength); + } + + public ArraySegment Buffer { get; private set; } + + public void Dispose() + { + if (this.Buffer.Array != null) + { + this.provider?.arrayPool.Return(this.Buffer.Array); + this.Buffer = default; + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ByokConfig.cs b/Microsoft.Azure.Cosmos/src/direct/ByokConfig.cs index e134dba045..708f7a0ced 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ByokConfig.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ByokConfig.cs @@ -1,70 +1,70 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents byok configuration for a collection in the Azure Cosmos DB service - /// - /// - /// - /// - internal sealed class ByokConfig : JsonSerializable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - /// - /// byok Status is set to None by default. - /// - public ByokConfig() - { - this.ByokStatus = ByokStatus.None; - } - - public ByokConfig(ByokStatus byokStatus) - { - this.ByokStatus = byokStatus; - } - - /// - /// Gets or sets the byok status in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.ByokStatus)] - [JsonConverter(typeof(StringEnumConverter))] - public ByokStatus ByokStatus - { - get - { - ByokStatus result = ByokStatus.None; - string strValue = base.GetValue(Constants.Properties.ByokStatus); - if (!string.IsNullOrEmpty(strValue)) - { - result = (ByokStatus)Enum.Parse(typeof(ByokStatus), strValue, true); - } - return result; - } - - set - { - base.SetValue(Constants.Properties.ByokStatus, value.ToString()); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents byok configuration for a collection in the Azure Cosmos DB service + /// + /// + /// + /// + internal sealed class ByokConfig : JsonSerializable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// + /// byok Status is set to None by default. + /// + public ByokConfig() + { + this.ByokStatus = ByokStatus.None; + } + + public ByokConfig(ByokStatus byokStatus) + { + this.ByokStatus = byokStatus; + } + + /// + /// Gets or sets the byok status in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.ByokStatus)] + [JsonConverter(typeof(StringEnumConverter))] + public ByokStatus ByokStatus + { + get + { + ByokStatus result = ByokStatus.None; + string strValue = base.GetValue(Constants.Properties.ByokStatus); + if (!string.IsNullOrEmpty(strValue)) + { + result = (ByokStatus)Enum.Parse(typeof(ByokStatus), strValue, true); + } + return result; + } + + set + { + base.SetValue(Constants.Properties.ByokStatus, value.ToString()); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ByokStatus.cs b/Microsoft.Azure.Cosmos/src/direct/ByokStatus.cs index 8f1f90f21a..2e958d3d79 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ByokStatus.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ByokStatus.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported byok status in the Azure Cosmos DB service. - /// -internal enum ByokStatus - { - /// - /// Represents byok is not enabled on collection. - /// - None, - - /// - /// Represents byok is enabled on collection. - /// - Active - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported byok status in the Azure Cosmos DB service. + /// +internal enum ByokStatus + { + /// + /// Represents byok is not enabled on collection. + /// + None, + + /// + /// Represents byok is enabled on collection. + /// + Active + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/BytesDeserializer.cs b/Microsoft.Azure.Cosmos/src/direct/BytesDeserializer.cs index 0ca1fe1975..0ab2301325 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BytesDeserializer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BytesDeserializer.cs @@ -1,112 +1,112 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Rntbd -{ - using System; - using System.Runtime.InteropServices; - - internal struct BytesDeserializer - { - private readonly Memory metadata; - - public BytesDeserializer(byte[] metadata, int length) : this() - { - this.metadata = new Memory(metadata, 0, length); - this.Position = 0; - } - - public int Position { get; private set; } - - public int Length => this.metadata.Length; - - public ushort ReadUInt16() - { - ushort value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 2; - return value; - } - - public void AdvancePositionByUInt16() => this.Position += 2; - - public byte ReadByte() - { - byte value = this.metadata.Span[this.Position]; - this.Position++; - return value; - } - - public uint ReadUInt32() - { - uint value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 4; - return value; - } - - public void AdvancePositionByUInt32() => this.Position += 4; - - public int ReadInt32() - { - int value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 4; - return value; - } - - public void AdvancePositionByInt32() => this.Position += 4; - - public ulong ReadUInt64() - { - ulong value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 8; - return value; - } - - public void AdvancePositionByUInt64() => this.Position += 8; - - public long ReadInt64() - { - long value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 8; - return value; - } - - public void AdvancePositionByInt64() => this.Position += 8; - - public float ReadSingle() - { - float value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 4; - return value; - } - - public void AdvancePositionBySingle() => this.Position += 4; - - public double ReadDouble() - { - double value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 8; - return value; - } - - public void AdvancePositionByDouble() => this.Position += 8; - - public Guid ReadGuid() - { - Guid value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); - this.Position += 16; - return value; - } - - public void AdvancePositionByGuid() => this.Position += 16; - - public ReadOnlyMemory ReadBytes(int length) - { - ReadOnlyMemory value = this.metadata.Slice(this.Position, length); - this.Position += length; - return value; - } - - public void AdvancePositionByBytes(int count) => this.Position += count; - } -} +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Rntbd +{ + using System; + using System.Runtime.InteropServices; + + internal struct BytesDeserializer + { + private readonly Memory metadata; + + public BytesDeserializer(byte[] metadata, int length) : this() + { + this.metadata = new Memory(metadata, 0, length); + this.Position = 0; + } + + public int Position { get; private set; } + + public int Length => this.metadata.Length; + + public ushort ReadUInt16() + { + ushort value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 2; + return value; + } + + public void AdvancePositionByUInt16() => this.Position += 2; + + public byte ReadByte() + { + byte value = this.metadata.Span[this.Position]; + this.Position++; + return value; + } + + public uint ReadUInt32() + { + uint value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 4; + return value; + } + + public void AdvancePositionByUInt32() => this.Position += 4; + + public int ReadInt32() + { + int value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 4; + return value; + } + + public void AdvancePositionByInt32() => this.Position += 4; + + public ulong ReadUInt64() + { + ulong value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 8; + return value; + } + + public void AdvancePositionByUInt64() => this.Position += 8; + + public long ReadInt64() + { + long value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 8; + return value; + } + + public void AdvancePositionByInt64() => this.Position += 8; + + public float ReadSingle() + { + float value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 4; + return value; + } + + public void AdvancePositionBySingle() => this.Position += 4; + + public double ReadDouble() + { + double value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 8; + return value; + } + + public void AdvancePositionByDouble() => this.Position += 8; + + public Guid ReadGuid() + { + Guid value = MemoryMarshal.Read(this.metadata.Span.Slice(this.Position)); + this.Position += 16; + return value; + } + + public void AdvancePositionByGuid() => this.Position += 16; + + public ReadOnlyMemory ReadBytes(int length) + { + ReadOnlyMemory value = this.metadata.Slice(this.Position, length); + this.Position += length; + return value; + } + + public void AdvancePositionByBytes(int count) => this.Position += count; + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/BytesSerializer.cs b/Microsoft.Azure.Cosmos/src/direct/BytesSerializer.cs index 7211ba6b58..f2bc11b219 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BytesSerializer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BytesSerializer.cs @@ -1,144 +1,144 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Rntbd -{ - using System; - using System.IO; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Text; - using Microsoft.Azure.Documents; - - /// - /// A no-allocation replacement for BinaryWriter - /// that supports Span and Memory. - /// - internal ref struct BytesSerializer - { - private readonly Span targetByteArray; - private int position; - - public BytesSerializer(byte[] targetByteArray, int length) - { - this.targetByteArray = new Span(targetByteArray, 0, length); - this.position = 0; - } - - public static Guid ReadGuidFromBytes(ArraySegment array) - { - Span activityIdSpan = new Span(array.Array, array.Offset, array.Count); - Guid guid = MemoryMarshal.Read(activityIdSpan); - return guid; - } - - public static unsafe string GetStringFromBytes(ReadOnlyMemory memory) - { - if (memory.IsEmpty) - { - return string.Empty; - } - - fixed (byte* bytes = &memory.Span.GetPinnableReference()) - { - return Encoding.UTF8.GetString(bytes, memory.Length); - } - } - - public static ReadOnlyMemory GetBytesForString(string toConvert, RntbdConstants.Request request) - { - byte[] stringBuffer = request.GetBytes(Encoding.UTF8.GetMaxByteCount(toConvert.Length)); - int length = Encoding.UTF8.GetBytes(toConvert, 0, toConvert.Length, stringBuffer, 0); - return new ReadOnlyMemory(stringBuffer, 0, length); - } - - internal int GetPosition() => this.position; - - /// - /// Separate out getting the size of GUID into a separate method to keep unsafe contexts isolated. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe int GetSizeOfGuid() - { - return sizeof(Guid); - } - - public void Write(byte[] value) - { - this.Write(new ArraySegment(value, 0, value.Length)); - } - - public void Write(uint value) - { - this.WriteValue(value, sizeof(uint)); - } - - public void Write(int value) - { - this.WriteValue(value, sizeof(int)); - } - - public void Write(long value) - { - this.WriteValue(value, sizeof(long)); - } - - public void Write(ulong value) - { - this.WriteValue(value, sizeof(ulong)); - } - - public void Write(float value) - { - this.WriteValue(value, sizeof(float)); - } - - public void Write(double value) - { - this.WriteValue(value, sizeof(double)); - } - - public void Write(ushort value) - { - this.WriteValue(value, sizeof(ushort)); - } - - public void Write(byte value) - { - this.WriteValue(value, sizeof(byte)); - } - - public int Write(Guid value) - { - this.WriteValue(value, BytesSerializer.GetSizeOfGuid()); - return BytesSerializer.GetSizeOfGuid(); - } - - public void Write(ArraySegment value) - { - Span valueToWrite = new Span(value.Array, value.Offset, value.Count); - this.Write(valueToWrite); - } - - public void Write(ReadOnlyMemory valueToWrite) - { - this.Write(valueToWrite.Span); - } - - public void Write(ReadOnlySpan valueToWrite) - { - Span writeSpan = this.targetByteArray.Slice(this.position); - valueToWrite.CopyTo(writeSpan); - this.position += valueToWrite.Length; - } - - private void WriteValue(T value, int sizeT) - where T : struct - { - Span writeSpan = this.targetByteArray.Slice(this.position); - MemoryMarshal.Write(writeSpan, ref value); - this.position += sizeT; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Rntbd +{ + using System; + using System.IO; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Text; + using Microsoft.Azure.Documents; + + /// + /// A no-allocation replacement for BinaryWriter + /// that supports Span and Memory. + /// + internal ref struct BytesSerializer + { + private readonly Span targetByteArray; + private int position; + + public BytesSerializer(byte[] targetByteArray, int length) + { + this.targetByteArray = new Span(targetByteArray, 0, length); + this.position = 0; + } + + public static Guid ReadGuidFromBytes(ArraySegment array) + { + Span activityIdSpan = new Span(array.Array, array.Offset, array.Count); + Guid guid = MemoryMarshal.Read(activityIdSpan); + return guid; + } + + public static unsafe string GetStringFromBytes(ReadOnlyMemory memory) + { + if (memory.IsEmpty) + { + return string.Empty; + } + + fixed (byte* bytes = &memory.Span.GetPinnableReference()) + { + return Encoding.UTF8.GetString(bytes, memory.Length); + } + } + + public static ReadOnlyMemory GetBytesForString(string toConvert, RntbdConstants.Request request) + { + byte[] stringBuffer = request.GetBytes(Encoding.UTF8.GetMaxByteCount(toConvert.Length)); + int length = Encoding.UTF8.GetBytes(toConvert, 0, toConvert.Length, stringBuffer, 0); + return new ReadOnlyMemory(stringBuffer, 0, length); + } + + internal int GetPosition() => this.position; + + /// + /// Separate out getting the size of GUID into a separate method to keep unsafe contexts isolated. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static unsafe int GetSizeOfGuid() + { + return sizeof(Guid); + } + + public void Write(byte[] value) + { + this.Write(new ArraySegment(value, 0, value.Length)); + } + + public void Write(uint value) + { + this.WriteValue(value, sizeof(uint)); + } + + public void Write(int value) + { + this.WriteValue(value, sizeof(int)); + } + + public void Write(long value) + { + this.WriteValue(value, sizeof(long)); + } + + public void Write(ulong value) + { + this.WriteValue(value, sizeof(ulong)); + } + + public void Write(float value) + { + this.WriteValue(value, sizeof(float)); + } + + public void Write(double value) + { + this.WriteValue(value, sizeof(double)); + } + + public void Write(ushort value) + { + this.WriteValue(value, sizeof(ushort)); + } + + public void Write(byte value) + { + this.WriteValue(value, sizeof(byte)); + } + + public int Write(Guid value) + { + this.WriteValue(value, BytesSerializer.GetSizeOfGuid()); + return BytesSerializer.GetSizeOfGuid(); + } + + public void Write(ArraySegment value) + { + Span valueToWrite = new Span(value.Array, value.Offset, value.Count); + this.Write(valueToWrite); + } + + public void Write(ReadOnlyMemory valueToWrite) + { + this.Write(valueToWrite.Span); + } + + public void Write(ReadOnlySpan valueToWrite) + { + Span writeSpan = this.targetByteArray.Slice(this.position); + valueToWrite.CopyTo(writeSpan); + this.position += valueToWrite.Length; + } + + private void WriteValue(T value, int sizeT) + where T : struct + { + Span writeSpan = this.targetByteArray.Slice(this.position); + MemoryMarshal.Write(writeSpan, ref value); + this.position += sizeT; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/CMKMetadataInfo.cs b/Microsoft.Azure.Cosmos/src/direct/CMKMetadataInfo.cs index 1c93b1fdaa..9e96018651 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CMKMetadataInfo.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CMKMetadataInfo.cs @@ -1,111 +1,111 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Defines the CMK metadata(from the encryption scope resource) stored in the collection body. - /// This contains the azure key vault metadata and the metadata of the assigned identity - /// which will be used to access the key vault to get the data encryption key which will be - /// used to encrypt/decrypt the documents that would be stored in the collection. - /// - internal sealed class CMKMetadataInfo : JsonSerializable, ICloneable - { - /// - /// Key vault uri for the customer managed key. - /// - [JsonProperty(PropertyName = Constants.KeyVaultProperties.KeyVaultKeyUri)] - public string KeyVaultKeyUri - { - get - { - return base.GetValue(Constants.KeyVaultProperties.KeyVaultKeyUri); - } - set - { - base.SetValue(Constants.KeyVaultProperties.KeyVaultKeyUri, value); - } - } - - /// - /// Reference of the identity to be used to access the key vault. - /// - [JsonProperty(PropertyName = Constants.Properties.DefaultIdentity)] - public string DefaultIdentity - { - get - { - return base.GetValue(Constants.Properties.DefaultIdentity); - } - set - { - base.SetValue(Constants.Properties.DefaultIdentity, value); - } - } - - /// - /// Reference for the client id of the default identity. - /// - [JsonProperty(PropertyName = Constants.ManagedServiceIdentityProperties.MsiClientId)] - public string MsiClientId - { - get - { - return base.GetValue(Constants.ManagedServiceIdentityProperties.MsiClientId); - } - set - { - base.SetValue(Constants.ManagedServiceIdentityProperties.MsiClientId, value); - } - } - - /// - /// Reference for the client secret encrypted of the default identity. - /// - [JsonProperty(PropertyName = Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted)] - public string MsiClientSecretEncrypted - { - get - { - return base.GetValue(Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted); - } - set - { - base.SetValue(Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted, value); - } - } - - /// - /// Dek encrypted with kek provided from the customer. - /// - [JsonProperty(PropertyName = Constants.KeyVaultProperties.WrappedDek)] - public string WrappedDek - { - get - { - return base.GetValue(Constants.KeyVaultProperties.WrappedDek); - } - set - { - base.SetValue(Constants.KeyVaultProperties.WrappedDek, value); - } - } - - public object Clone() - { - CMKMetadataInfo cloned = new CMKMetadataInfo() - { - KeyVaultKeyUri = this.KeyVaultKeyUri, - DefaultIdentity = this.DefaultIdentity, - MsiClientId = this.MsiClientId, - MsiClientSecretEncrypted = this.MsiClientSecretEncrypted, - WrappedDek = this.WrappedDek, - }; - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Defines the CMK metadata(from the encryption scope resource) stored in the collection body. + /// This contains the azure key vault metadata and the metadata of the assigned identity + /// which will be used to access the key vault to get the data encryption key which will be + /// used to encrypt/decrypt the documents that would be stored in the collection. + /// + internal sealed class CMKMetadataInfo : JsonSerializable, ICloneable + { + /// + /// Key vault uri for the customer managed key. + /// + [JsonProperty(PropertyName = Constants.KeyVaultProperties.KeyVaultKeyUri)] + public string KeyVaultKeyUri + { + get + { + return base.GetValue(Constants.KeyVaultProperties.KeyVaultKeyUri); + } + set + { + base.SetValue(Constants.KeyVaultProperties.KeyVaultKeyUri, value); + } + } + + /// + /// Reference of the identity to be used to access the key vault. + /// + [JsonProperty(PropertyName = Constants.Properties.DefaultIdentity)] + public string DefaultIdentity + { + get + { + return base.GetValue(Constants.Properties.DefaultIdentity); + } + set + { + base.SetValue(Constants.Properties.DefaultIdentity, value); + } + } + + /// + /// Reference for the client id of the default identity. + /// + [JsonProperty(PropertyName = Constants.ManagedServiceIdentityProperties.MsiClientId)] + public string MsiClientId + { + get + { + return base.GetValue(Constants.ManagedServiceIdentityProperties.MsiClientId); + } + set + { + base.SetValue(Constants.ManagedServiceIdentityProperties.MsiClientId, value); + } + } + + /// + /// Reference for the client secret encrypted of the default identity. + /// + [JsonProperty(PropertyName = Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted)] + public string MsiClientSecretEncrypted + { + get + { + return base.GetValue(Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted); + } + set + { + base.SetValue(Constants.ManagedServiceIdentityProperties.MsiClientSecretEncrypted, value); + } + } + + /// + /// Dek encrypted with kek provided from the customer. + /// + [JsonProperty(PropertyName = Constants.KeyVaultProperties.WrappedDek)] + public string WrappedDek + { + get + { + return base.GetValue(Constants.KeyVaultProperties.WrappedDek); + } + set + { + base.SetValue(Constants.KeyVaultProperties.WrappedDek, value); + } + } + + public object Clone() + { + CMKMetadataInfo cloned = new CMKMetadataInfo() + { + KeyVaultKeyUri = this.KeyVaultKeyUri, + DefaultIdentity = this.DefaultIdentity, + MsiClientId = this.MsiClientId, + MsiClientSecretEncrypted = this.MsiClientSecretEncrypted, + WrappedDek = this.WrappedDek, + }; + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ChangeFeedPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/ChangeFeedPolicy.cs index 838218e5e3..d8336697a0 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChangeFeedPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChangeFeedPolicy.cs @@ -1,54 +1,54 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Represents the change feed policy for a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class ChangeFeedPolicy : JsonSerializable, ICloneable - { - /// - /// Gets or sets a value that indicates for how long operation logs have to be retained. - /// - /// - /// Value is in TimeSpan. Any seconds will be ceiled as 1 minute. - /// - [JsonProperty(PropertyName = Constants.Properties.LogRetentionDuration)] - public TimeSpan RetentionDuration - { - get - { - int retentionDurationInMinutes = base.GetValue(Constants.Properties.LogRetentionDuration); - return TimeSpan.FromMinutes(retentionDurationInMinutes); - } - set - { - TimeSpan retentionDuration = value; - int retentionDurationInMinutes = ((int)retentionDuration.TotalMinutes) + (retentionDuration.Seconds > 0 ? 1 : 0); - base.SetValue(Constants.Properties.LogRetentionDuration, retentionDurationInMinutes); - } - } - - /// - /// Performs a deep copy of the operation log policy. - /// - /// - /// A clone of the operation log policy. - /// - public object Clone() - { - ChangeFeedPolicy cloned = new ChangeFeedPolicy() - { - RetentionDuration = this.RetentionDuration - }; - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Represents the change feed policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class ChangeFeedPolicy : JsonSerializable, ICloneable + { + /// + /// Gets or sets a value that indicates for how long operation logs have to be retained. + /// + /// + /// Value is in TimeSpan. Any seconds will be ceiled as 1 minute. + /// + [JsonProperty(PropertyName = Constants.Properties.LogRetentionDuration)] + public TimeSpan RetentionDuration + { + get + { + int retentionDurationInMinutes = base.GetValue(Constants.Properties.LogRetentionDuration); + return TimeSpan.FromMinutes(retentionDurationInMinutes); + } + set + { + TimeSpan retentionDuration = value; + int retentionDurationInMinutes = ((int)retentionDuration.TotalMinutes) + (retentionDuration.Seconds > 0 ? 1 : 0); + base.SetValue(Constants.Properties.LogRetentionDuration, retentionDurationInMinutes); + } + } + + /// + /// Performs a deep copy of the operation log policy. + /// + /// + /// A clone of the operation log policy. + /// + public object Clone() + { + ChangeFeedPolicy cloned = new ChangeFeedPolicy() + { + RetentionDuration = this.RetentionDuration + }; + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Channel.cs b/Microsoft.Azure.Cosmos/src/direct/Channel.cs index b19888a90a..32d52d2e7d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Channel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Channel.cs @@ -1,569 +1,578 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.FaultInjection; - -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - // The RNTBD RPC channel. Supports multiple parallel requests and timeouts. - internal sealed class Channel : IChannel, IDisposable - { - private readonly Dispatcher dispatcher; - private readonly TimerPool timerPool; - private readonly int requestTimeoutSeconds; - private readonly Uri serverUri; - private readonly bool localRegionRequest; - private bool disposed = false; - - private readonly ReaderWriterLockSlim stateLock = - new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - private State state = State.New; // Guarded by stateLock. - private Task initializationTask = null; // Guarded by stateLock. - private volatile bool isInitializationComplete = false; - - private ChannelOpenArguments openArguments; - private readonly SemaphoreSlim openingSlim; - private readonly IChaosInterceptor chaosInterceptor; - - public Channel( - Guid activityId, - Uri serverUri, - ChannelProperties channelProperties, - bool localRegionRequest, SemaphoreSlim openingSlim, - IChaosInterceptor chaosInterceptor = null, - Action onChannelOpen = null) - { - Debug.Assert(channelProperties != null); - this.dispatcher = new Dispatcher(serverUri, - channelProperties.UserAgent, - channelProperties.ConnectionStateListener, - channelProperties.CertificateHostNameOverride, - channelProperties.ReceiveHangDetectionTime, - channelProperties.SendHangDetectionTime, - channelProperties.IdleTimerPool, - channelProperties.IdleTimeout, - channelProperties.EnableChannelMultiplexing, - channelProperties.MemoryStreamPool, - channelProperties.RemoteCertificateValidationCallback, - channelProperties.DnsResolutionFunction, - chaosInterceptor); - this.timerPool = channelProperties.RequestTimerPool; - this.requestTimeoutSeconds = (int) channelProperties.RequestTimeout.TotalSeconds; - this.serverUri = serverUri; - this.localRegionRequest = localRegionRequest; - this.chaosInterceptor = chaosInterceptor; - - TimeSpan openTimeout = localRegionRequest ? channelProperties.LocalRegionOpenTimeout : channelProperties.OpenTimeout; - - this.openArguments = new ChannelOpenArguments( - activityId, new ChannelOpenTimeline(), - openTimeout, - channelProperties.PortReuseMode, - channelProperties.UserPortPool, - channelProperties.CallerId); - - this.openingSlim = openingSlim; - this.Initialize(activityId, onChannelOpen); - } - - public void InjectFaultInjectionConnectionError(TransportException transportException) - { - if (!this.disposed) - { - this.dispatcher.InjectFaultInjectionConnectionError(transportException); - } - } - - public Uri GetServerUri() - { - this.ThrowIfDisposed(); - return this.serverUri; - } - - [DebuggerBrowsable(DebuggerBrowsableState.Never)] - public bool Healthy - { - get - { - this.ThrowIfDisposed(); - Dispatcher dispatcher = null; - this.stateLock.EnterReadLock(); - try - { - switch (this.state) - { - case State.Open: - dispatcher = this.dispatcher; - break; - - - case State.WaitingToOpen: - case State.Opening: - return true; - - case State.Closed: - return false; - - case State.New: - Debug.Assert(false, - "Channel.Healthy called before Initialize()"); - return false; - - default: - Debug.Assert(false, "Unhandled state"); - return false; - } - } - finally - { - this.stateLock.ExitReadLock(); - } - Debug.Assert(dispatcher != null); - return dispatcher.Healthy; - } - } - - private Guid ConnectionCorrelationId { get => this.dispatcher.ConnectionCorrelationId; } - - private void Initialize(Guid activityId, Action onChannelOpen = null) - { - this.ThrowIfDisposed(); - this.stateLock.EnterWriteLock(); - try - { - Debug.Assert(this.state == State.New); - this.state = State.WaitingToOpen; - Debug.Assert(this.initializationTask == null); - - // Initialization should use a task scheduler internal to the Cosmos DB - // client or the default scheduler. Avoid using the current scheduler. - // Some components use custom task schedulers for accounting or to - // control and suspend task execution. It does not make sense - // for channel initialization to be charged to the caller that created - // the connection, and it can be dangerous to play scheduling games - // with this task. - this.initializationTask = Task.Run(async () => - { - Debug.Assert(this.openArguments != null); - Debug.Assert(this.openArguments.CommonArguments != null); - Trace.CorrelationManager.ActivityId = this.openArguments.CommonArguments.ActivityId; - await this.InitializeAsync(activityId, onChannelOpen); - this.isInitializationComplete = true; - this.TestOnInitializeComplete?.Invoke(); - }); - } - finally - { - this.stateLock.ExitWriteLock(); - } - } - - public async Task RequestAsync( - DocumentServiceRequest request, TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, Guid activityId, TransportRequestStats transportRequestStats) - { - this.ThrowIfDisposed(); - - if (!this.isInitializationComplete) - { - transportRequestStats.RequestWaitingForConnectionInitialization = true; - DefaultTrace.TraceInformation( - "[RNTBD Channel {0}] Awaiting RNTBD channel initialization. Request URI: {1}", - this.ConnectionCorrelationId, physicalAddress); - await this.initializationTask; - } - else - { - transportRequestStats.RequestWaitingForConnectionInitialization = false; - } - - // Waiting for channel initialization to move to Pipelined stage - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Pipelined); - - // Ideally, we would set up a timer here, and then hand off the rest of the work - // to the dispatcher. In practice, additional constraints force the interaction to - // be chattier: - // - Serialization errors are handled differently from channel errors. - // - Timeouts only apply to the call (send+recv), not to everything preceding it. - using ChannelCallArguments callArguments = this.chaosInterceptor == null - ? new ChannelCallArguments(activityId) - : new ChannelCallArguments(activityId, request.OperationType, request.ResourceType, request.RequestContext.ResolvedCollectionRid, request.Headers); - try - { - callArguments.PreparedCall = this.dispatcher.PrepareCall( - request, physicalAddress, resourceOperation, activityId, transportRequestStats); - } - catch (DocumentClientException e) - { - e.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - throw; - } - catch (Exception e) - { - DefaultTrace.TraceError( - "[RNTBD Channel {0}] Failed to serialize request. Assuming malformed request payload: {1}", this.ConnectionCorrelationId, e); - DocumentClientException clientException = new BadRequestException(e); - clientException.Headers.Add( - HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - throw clientException; - } - - PooledTimer timer = this.timerPool.GetPooledTimer(this.requestTimeoutSeconds); - Task[] tasks = new Task[2]; - tasks[0] = timer.StartTimerAsync(); - Task dispatcherCall = this.dispatcher.CallAsync(callArguments, transportRequestStats); - TransportClient.GetTransportPerformanceCounters().LogRntbdBytesSentCount(resourceOperation.resourceType, resourceOperation.operationType, callArguments.PreparedCall?.SerializedRequest.RequestSize); - tasks[1] = dispatcherCall; - Task completedTask = await Task.WhenAny(tasks); - if (object.ReferenceEquals(completedTask, tasks[0])) - { - // Timed out. - TransportErrorCode timeoutCode; - bool payloadSent; - callArguments.CommonArguments.SnapshotCallState( - out timeoutCode, out payloadSent); - Debug.Assert(TransportException.IsTimeout(timeoutCode)); - this.dispatcher.CancelCallAndNotifyConnectionOnTimeoutEvent(callArguments.PreparedCall, request.IsReadOnlyRequest); - Channel.HandleTaskTimeout(tasks[1], activityId, this.ConnectionCorrelationId); - Exception ex = completedTask.Exception?.InnerException; - DefaultTrace.TraceWarning("[RNTBD Channel {0}] RNTBD call timed out on channel {1}. Error: {2}", - this.ConnectionCorrelationId, this, timeoutCode); - Debug.Assert(callArguments.CommonArguments.UserPayload); - throw new TransportException( - timeoutCode, ex, activityId, physicalAddress.Uri, this.ToString(), - callArguments.CommonArguments.UserPayload, payloadSent); - } - else - { - // Request completed. - Debug.Assert(object.ReferenceEquals(completedTask, tasks[1])); - timer.CancelTimer(); - - this.dispatcher.NotifyConnectionOnSuccessEvent(); - if (completedTask.IsFaulted) - { - await completedTask; - } - } - - physicalAddress.SetConnected(); - StoreResponse storeResponse = dispatcherCall.Result; - TransportClient.GetTransportPerformanceCounters().LogRntbdBytesReceivedCount(resourceOperation.resourceType, resourceOperation.operationType, storeResponse?.ResponseBody?.Length); - return storeResponse; - } - - /// - /// Returns the background channel initialization task. - /// - /// The initialization task. - public Task OpenChannelAsync(Guid activityId) - { - if(this.initializationTask == null) - { - throw new InvalidOperationException("Channal Initialization Task Can't be null."); - } - - return this.initializationTask; - } - - public override string ToString() - { - return this.dispatcher.ToString(); - } - - public void Close() - { - ((IDisposable) this).Dispose(); - } - - void IDisposable.Dispose() - { - this.chaosInterceptor?.OnChannelDispose(this.ConnectionCorrelationId); - this.ThrowIfDisposed(); - this.disposed = true; - DefaultTrace.TraceInformation("[RNTBD Channel {0}] Disposing RNTBD Channel {1}", this.ConnectionCorrelationId, this); - - Task initTask = null; - this.stateLock.EnterWriteLock(); - try - { - if (this.state != State.Closed) - { - initTask = this.initializationTask; - } - this.state = State.Closed; - } - finally - { - this.stateLock.ExitWriteLock(); - } - if (initTask != null) - { - try - { - initTask.Wait(); - } - catch (Exception e) - { - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] {1} initialization failed. Consuming the task " + - "exception in {2}. Server URI: {3}. Exception: {4}", - this.ConnectionCorrelationId, - nameof(Channel), - nameof(IDisposable.Dispose), - this.serverUri, - e.Message); - // Intentionally swallowing the exception. The caller can't - // do anything useful with it. - } - } - Debug.Assert(this.dispatcher != null); - this.dispatcher.Dispose(); - this.stateLock.Dispose(); - } - - #region Test hook. - - internal event Action TestOnInitializeComplete; - internal event Action TestOnConnectionClosed - { - add - { - this.dispatcher.TestOnConnectionClosed += value; - } - remove - { - this.dispatcher.TestOnConnectionClosed -= value; - } - } - internal bool TestIsIdle - { - get - { - return this.dispatcher.TestIsIdle; - } - } - #endregion - - private void ThrowIfDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException(nameof(Channel)); - } - } - - private async Task InitializeAsync(Guid activityId, Action onChannelOpen = null) - { - bool slimAcquired = false; - try - { - onChannelOpen?.Invoke(activityId, this.ConnectionCorrelationId, this.serverUri, this); - - this.openArguments.CommonArguments.SetTimeoutCode(TransportErrorCode.ChannelWaitingToOpenTimeout); - slimAcquired = await this.openingSlim.WaitAsync(this.openArguments.OpenTimeout).ConfigureAwait(false); - if (!slimAcquired) - { - // Timed out. - TransportErrorCode timeoutCode; - bool payloadSent; - this.openArguments.CommonArguments.SnapshotCallState( - out timeoutCode, out payloadSent); - Debug.Assert(TransportException.IsTimeout(timeoutCode)); - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] RNTBD waiting to open timed out on channel {1}. Error: {2}", this.ConnectionCorrelationId, this, timeoutCode); - throw new TransportException( - timeoutCode, null, this.openArguments.CommonArguments.ActivityId, - this.serverUri, this.ToString(), - this.openArguments.CommonArguments.UserPayload, payloadSent); - } - else - { - this.openArguments.CommonArguments.SetTimeoutCode(TransportErrorCode.ChannelOpenTimeout); - this.state = State.Opening; - - PooledTimer timer = this.timerPool.GetPooledTimer( - this.openArguments.OpenTimeout); - Task[] tasks = new Task[2]; - - // For local region requests the the OpenTimeout could be lower than the TimerPool minSupportedTimerDelayInSeconds, - // so use the lower value - if (this.localRegionRequest && this.openArguments.OpenTimeout < timer.MinSupportedTimeout) - { - tasks[0] = Task.Delay(this.openArguments.OpenTimeout); - } - else - { - tasks[0] = timer.StartTimerAsync(); - } - - tasks[1] = this.dispatcher.OpenAsync(this.openArguments); - Task completedTask = await Task.WhenAny(tasks); - if (object.ReferenceEquals(completedTask, tasks[0])) - { - // Timed out. - TransportErrorCode timeoutCode; - bool payloadSent; - this.openArguments.CommonArguments.SnapshotCallState( - out timeoutCode, out payloadSent); - Debug.Assert(TransportException.IsTimeout(timeoutCode)); - Channel.HandleTaskTimeout( - tasks[1], - this.openArguments.CommonArguments.ActivityId, - this.ConnectionCorrelationId); - Exception ex = completedTask.Exception?.InnerException; - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] RNTBD open timed out on channel {1}. Error: {2}", - this.ConnectionCorrelationId, this, timeoutCode); - Debug.Assert(!this.openArguments.CommonArguments.UserPayload); - throw new TransportException( - timeoutCode, ex, this.openArguments.CommonArguments.ActivityId, - this.serverUri, this.ToString(), - this.openArguments.CommonArguments.UserPayload, payloadSent); - } - else - { - // Open completed. - Debug.Assert(object.ReferenceEquals(completedTask, tasks[1])); - timer.CancelTimer(); - - if (completedTask.IsFaulted) - { - await completedTask; - } - } - - this.FinishInitialization(State.Open); - } - - } - catch (DocumentClientException e) - { - this.FinishInitialization(State.Closed); - - e.Headers.Set( - HttpConstants.HttpHeaders.ActivityId, - this.openArguments.CommonArguments.ActivityId.ToString()); - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] Channel.InitializeAsync failed. Channel: {1}. DocumentClientException: {2}", - this.ConnectionCorrelationId, this, e); - - throw; - } - catch (TransportException e) - { - this.FinishInitialization(State.Closed); - - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] Channel.InitializeAsync failed. Channel: {1}. TransportException: {2}", - this.ConnectionCorrelationId, this, e); - - throw; - } - catch (Exception e) - { - this.FinishInitialization(State.Closed); - - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] Channel.InitializeAsync failed. Wrapping exception in " + - "TransportException. Channel: {1}. Inner exception: {2}", - this.ConnectionCorrelationId, this, e); - - Debug.Assert(!this.openArguments.CommonArguments.UserPayload); - throw new TransportException( - TransportErrorCode.ChannelOpenFailed, e, - this.openArguments.CommonArguments.ActivityId, - this.serverUri, this.ToString(), - this.openArguments.CommonArguments.UserPayload, - this.openArguments.CommonArguments.PayloadSent); - } - finally - { - this.openArguments.OpenTimeline.WriteTrace(); - // The open arguments are no longer needed after this point. - this.openArguments = null; - if (slimAcquired) - { - this.openingSlim.Release(); - } - } - } - - private void FinishInitialization(State nextState) - { - Debug.Assert(!Monitor.IsEntered(this.stateLock)); - Debug.Assert(nextState == State.Open || nextState == State.Closed); - Task initTask = null; - this.stateLock.EnterWriteLock(); - try - { - // this.state might have become Closed if Dispose was already called. - Debug.Assert(this.state == State.WaitingToOpen || this.state == State.Opening || this.state == State.Closed); - if (this.state != State.Closed) - { - this.state = nextState; - initTask = this.initializationTask; - } - } - finally - { - this.stateLock.ExitWriteLock(); - } - if ((nextState == State.Closed) && (initTask != null)) - { - // In the typical case, a channel is created, asynchronous initialization - // starts, and then one or more callers await on the initialization task - // (and thus consume its exception, if one is thrown). - // This code defends against the rare case where a channel begins asynchronous - // initialization which ends in error, but nothing consumes the exception. - initTask.ContinueWith(completedTask => - { - Debug.Assert(completedTask.IsFaulted); - Debug.Assert(this.serverUri != null); - Debug.Assert(completedTask.Exception != null); - DefaultTrace.TraceWarning( - "[RNTBD Channel {0}] {1} initialization failed. Consuming the task " + - "exception asynchronously. Server URI: {2}. Exception: {3}", - this.ConnectionCorrelationId, - nameof(Channel), - this.serverUri, - completedTask.Exception.InnerException?.Message); - }, - TaskContinuationOptions.OnlyOnFaulted); - } - } - - private static void HandleTaskTimeout(Task runawayTask, Guid activityId, Guid connectionCorrelationId) - { - Task ignored = runawayTask.ContinueWith(task => - { - Trace.CorrelationManager.ActivityId = activityId; - Debug.Assert(task.IsFaulted); - Debug.Assert(task.Exception != null); - Exception e = task.Exception.InnerException; - DefaultTrace.TraceInformation( - "[RNTBD Channel {0}] Timed out task completed. Activity ID = {1}. HRESULT = {2:X}. Exception: {3}", - connectionCorrelationId, activityId, e.HResult, e); - }, - TaskContinuationOptions.OnlyOnFaulted); - } - - private enum State - { - New, - WaitingToOpen, - Opening, - Open, - Closed, - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.FaultInjection; + +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + // The RNTBD RPC channel. Supports multiple parallel requests and timeouts. + internal sealed class Channel : IChannel, IDisposable + { + private readonly Dispatcher dispatcher; + private readonly TimerPool timerPool; + private readonly int requestTimeoutSeconds; + private readonly Uri serverUri; + private readonly bool localRegionRequest; + private bool disposed = false; + + private readonly ReaderWriterLockSlim stateLock = + new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); + private State state = State.New; // Guarded by stateLock. + private Task initializationTask = null; // Guarded by stateLock. + private volatile bool isInitializationComplete = false; + + private ChannelOpenArguments openArguments; + private readonly SemaphoreSlim openingSlim; + private readonly IChaosInterceptor chaosInterceptor; + + public Channel( + Guid activityId, + Uri serverUri, + ChannelProperties channelProperties, + bool localRegionRequest, SemaphoreSlim openingSlim, + IChaosInterceptor chaosInterceptor = null, + Func onChannelOpen = null) + { + Debug.Assert(channelProperties != null); + this.dispatcher = new Dispatcher(serverUri, + channelProperties.UserAgent, + channelProperties.ConnectionStateListener, + channelProperties.CertificateHostNameOverride, + channelProperties.ReceiveHangDetectionTime, + channelProperties.SendHangDetectionTime, + channelProperties.IdleTimerPool, + channelProperties.IdleTimeout, + channelProperties.EnableChannelMultiplexing, + channelProperties.MemoryStreamPool, + channelProperties.RemoteCertificateValidationCallback, + channelProperties.DnsResolutionFunction, + chaosInterceptor); + this.timerPool = channelProperties.RequestTimerPool; + this.requestTimeoutSeconds = (int) channelProperties.RequestTimeout.TotalSeconds; + this.serverUri = serverUri; + this.localRegionRequest = localRegionRequest; + this.chaosInterceptor = chaosInterceptor; + + TimeSpan openTimeout = localRegionRequest ? channelProperties.LocalRegionOpenTimeout : channelProperties.OpenTimeout; + + this.openArguments = new ChannelOpenArguments( + activityId, new ChannelOpenTimeline(), + openTimeout, + channelProperties.PortReuseMode, + channelProperties.UserPortPool, + channelProperties.CallerId); + + this.openingSlim = openingSlim; + this.Initialize(activityId, onChannelOpen); + } + + public void InjectFaultInjectionConnectionError(TransportException transportException) + { + if (!this.disposed) + { + this.dispatcher.InjectFaultInjectionConnectionError(transportException); + } + } + + public Uri GetServerUri() + { + this.ThrowIfDisposed(); + return this.serverUri; + } + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + public bool Healthy + { + get + { + this.ThrowIfDisposed(); + Dispatcher dispatcher = null; + this.stateLock.EnterReadLock(); + try + { + switch (this.state) + { + case State.Open: + dispatcher = this.dispatcher; + break; + + + case State.WaitingToOpen: + case State.Opening: + return true; + + case State.Closed: + return false; + + case State.New: + Debug.Assert(false, + "Channel.Healthy called before Initialize()"); + return false; + + default: + Debug.Assert(false, "Unhandled state"); + return false; + } + } + finally + { + this.stateLock.ExitReadLock(); + } + Debug.Assert(dispatcher != null); + return dispatcher.Healthy; + } + } + + private Guid ConnectionCorrelationId { get => this.dispatcher.ConnectionCorrelationId; } + + private void Initialize(Guid activityId, Func onChannelOpen = null) + { + this.ThrowIfDisposed(); + this.stateLock.EnterWriteLock(); + try + { + Debug.Assert(this.state == State.New); + this.state = State.WaitingToOpen; + Debug.Assert(this.initializationTask == null); + + // Initialization should use a task scheduler internal to the Cosmos DB + // client or the default scheduler. Avoid using the current scheduler. + // Some components use custom task schedulers for accounting or to + // control and suspend task execution. It does not make sense + // for channel initialization to be charged to the caller that created + // the connection, and it can be dangerous to play scheduling games + // with this task. + this.initializationTask = Task.Run(async () => + { + Debug.Assert(this.openArguments != null); + Debug.Assert(this.openArguments.CommonArguments != null); + Trace.CorrelationManager.ActivityId = this.openArguments.CommonArguments.ActivityId; + await this.InitializeAsync(activityId, onChannelOpen); + this.isInitializationComplete = true; + this.TestOnInitializeComplete?.Invoke(); + }); + } + finally + { + this.stateLock.ExitWriteLock(); + } + } + + public async Task RequestAsync( + DocumentServiceRequest request, TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, Guid activityId, TransportRequestStats transportRequestStats) + { + this.ThrowIfDisposed(); + + if (!this.isInitializationComplete) + { + transportRequestStats.RequestWaitingForConnectionInitialization = true; + DefaultTrace.TraceInformation( + "[RNTBD Channel {0}] Awaiting RNTBD channel initialization. Request URI: {1}", + this.ConnectionCorrelationId, physicalAddress); + await this.initializationTask; + } + else + { + transportRequestStats.RequestWaitingForConnectionInitialization = false; + } + + // Waiting for channel initialization to move to Pipelined stage + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Pipelined); + + // Ideally, we would set up a timer here, and then hand off the rest of the work + // to the dispatcher. In practice, additional constraints force the interaction to + // be chattier: + // - Serialization errors are handled differently from channel errors. + // - Timeouts only apply to the call (send+recv), not to everything preceding it. + using ChannelCallArguments callArguments = this.chaosInterceptor == null + ? new ChannelCallArguments(activityId) + : new ChannelCallArguments( + activityId, + request.OperationType, + request.ResourceType, + request.RequestContext.ResolvedCollectionRid, + request.Headers, + request.RequestContext.LocationEndpointToRoute); + try + { + callArguments.PreparedCall = this.dispatcher.PrepareCall( + request, physicalAddress, resourceOperation, activityId, transportRequestStats); + } + catch (DocumentClientException e) + { + e.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + throw; + } + catch (Exception e) + { + DefaultTrace.TraceError( + "[RNTBD Channel {0}] Failed to serialize request. Assuming malformed request payload: {1}", this.ConnectionCorrelationId, e); + DocumentClientException clientException = new BadRequestException(e); + clientException.Headers.Add( + HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + throw clientException; + } + + PooledTimer timer = this.timerPool.GetPooledTimer(this.requestTimeoutSeconds); + Task[] tasks = new Task[2]; + tasks[0] = timer.StartTimerAsync(); + Task dispatcherCall = this.dispatcher.CallAsync(callArguments, transportRequestStats); + TransportClient.GetTransportPerformanceCounters().LogRntbdBytesSentCount(resourceOperation.resourceType, resourceOperation.operationType, callArguments.PreparedCall?.SerializedRequest.RequestSize); + tasks[1] = dispatcherCall; + Task completedTask = await Task.WhenAny(tasks); + if (object.ReferenceEquals(completedTask, tasks[0])) + { + // Timed out. + TransportErrorCode timeoutCode; + bool payloadSent; + callArguments.CommonArguments.SnapshotCallState( + out timeoutCode, out payloadSent); + Debug.Assert(TransportException.IsTimeout(timeoutCode)); + this.dispatcher.CancelCallAndNotifyConnectionOnTimeoutEvent(callArguments.PreparedCall, request.IsReadOnlyRequest); + Channel.HandleTaskTimeout(tasks[1], activityId, this.ConnectionCorrelationId); + Exception ex = completedTask.Exception?.InnerException; + DefaultTrace.TraceWarning("[RNTBD Channel {0}] RNTBD call timed out on channel {1}. Error: {2}", + this.ConnectionCorrelationId, this, timeoutCode); + Debug.Assert(callArguments.CommonArguments.UserPayload); + throw new TransportException( + timeoutCode, ex, activityId, physicalAddress.Uri, this.ToString(), + callArguments.CommonArguments.UserPayload, payloadSent); + } + else + { + // Request completed. + Debug.Assert(object.ReferenceEquals(completedTask, tasks[1])); + timer.CancelTimer(); + + this.dispatcher.NotifyConnectionOnSuccessEvent(); + if (completedTask.IsFaulted) + { + await completedTask; + } + } + + physicalAddress.SetConnected(); + StoreResponse storeResponse = dispatcherCall.Result; + TransportClient.GetTransportPerformanceCounters().LogRntbdBytesReceivedCount(resourceOperation.resourceType, resourceOperation.operationType, storeResponse?.ResponseBody?.Length); + return storeResponse; + } + + /// + /// Returns the background channel initialization task. + /// + /// The initialization task. + public Task OpenChannelAsync(Guid activityId) + { + if(this.initializationTask == null) + { + throw new InvalidOperationException("Channal Initialization Task Can't be null."); + } + + return this.initializationTask; + } + + public override string ToString() + { + return this.dispatcher.ToString(); + } + + public void Close() + { + ((IDisposable) this).Dispose(); + } + + void IDisposable.Dispose() + { + this.chaosInterceptor?.OnChannelDispose(this.ConnectionCorrelationId); + this.ThrowIfDisposed(); + this.disposed = true; + DefaultTrace.TraceInformation("[RNTBD Channel {0}] Disposing RNTBD Channel {1}", this.ConnectionCorrelationId, this); + + Task initTask = null; + this.stateLock.EnterWriteLock(); + try + { + if (this.state != State.Closed) + { + initTask = this.initializationTask; + } + this.state = State.Closed; + } + finally + { + this.stateLock.ExitWriteLock(); + } + if (initTask != null) + { + try + { + initTask.Wait(); + } + catch (Exception e) + { + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] {1} initialization failed. Consuming the task " + + "exception in {2}. Server URI: {3}. Exception: {4}", + this.ConnectionCorrelationId, + nameof(Channel), + nameof(IDisposable.Dispose), + this.serverUri, + e.Message); + // Intentionally swallowing the exception. The caller can't + // do anything useful with it. + } + } + Debug.Assert(this.dispatcher != null); + this.dispatcher.Dispose(); + this.stateLock.Dispose(); + } + + #region Test hook. + + internal event Action TestOnInitializeComplete; + internal event Action TestOnConnectionClosed + { + add + { + this.dispatcher.TestOnConnectionClosed += value; + } + remove + { + this.dispatcher.TestOnConnectionClosed -= value; + } + } + internal bool TestIsIdle + { + get + { + return this.dispatcher.TestIsIdle; + } + } + #endregion + + private void ThrowIfDisposed() + { + if (this.disposed) + { + throw new ObjectDisposedException(nameof(Channel)); + } + } + + private async Task InitializeAsync(Guid activityId, Func onChannelOpen = null) + { + bool slimAcquired = false; + try + { + if (this.chaosInterceptor != null) + { + await onChannelOpen?.Invoke(activityId, this.ConnectionCorrelationId, this.serverUri, this); + } + + this.openArguments.CommonArguments.SetTimeoutCode(TransportErrorCode.ChannelWaitingToOpenTimeout); + slimAcquired = await this.openingSlim.WaitAsync(this.openArguments.OpenTimeout).ConfigureAwait(false); + if (!slimAcquired) + { + // Timed out. + TransportErrorCode timeoutCode; + bool payloadSent; + this.openArguments.CommonArguments.SnapshotCallState( + out timeoutCode, out payloadSent); + Debug.Assert(TransportException.IsTimeout(timeoutCode)); + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] RNTBD waiting to open timed out on channel {1}. Error: {2}", this.ConnectionCorrelationId, this, timeoutCode); + throw new TransportException( + timeoutCode, null, this.openArguments.CommonArguments.ActivityId, + this.serverUri, this.ToString(), + this.openArguments.CommonArguments.UserPayload, payloadSent); + } + else + { + this.openArguments.CommonArguments.SetTimeoutCode(TransportErrorCode.ChannelOpenTimeout); + this.state = State.Opening; + + PooledTimer timer = this.timerPool.GetPooledTimer( + this.openArguments.OpenTimeout); + Task[] tasks = new Task[2]; + + // For local region requests the the OpenTimeout could be lower than the TimerPool minSupportedTimerDelayInSeconds, + // so use the lower value + if (this.localRegionRequest && this.openArguments.OpenTimeout < timer.MinSupportedTimeout) + { + tasks[0] = Task.Delay(this.openArguments.OpenTimeout); + } + else + { + tasks[0] = timer.StartTimerAsync(); + } + + tasks[1] = this.dispatcher.OpenAsync(this.openArguments); + Task completedTask = await Task.WhenAny(tasks); + if (object.ReferenceEquals(completedTask, tasks[0])) + { + // Timed out. + TransportErrorCode timeoutCode; + bool payloadSent; + this.openArguments.CommonArguments.SnapshotCallState( + out timeoutCode, out payloadSent); + Debug.Assert(TransportException.IsTimeout(timeoutCode)); + Channel.HandleTaskTimeout( + tasks[1], + this.openArguments.CommonArguments.ActivityId, + this.ConnectionCorrelationId); + Exception ex = completedTask.Exception?.InnerException; + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] RNTBD open timed out on channel {1}. Error: {2}", + this.ConnectionCorrelationId, this, timeoutCode); + Debug.Assert(!this.openArguments.CommonArguments.UserPayload); + throw new TransportException( + timeoutCode, ex, this.openArguments.CommonArguments.ActivityId, + this.serverUri, this.ToString(), + this.openArguments.CommonArguments.UserPayload, payloadSent); + } + else + { + // Open completed. + Debug.Assert(object.ReferenceEquals(completedTask, tasks[1])); + timer.CancelTimer(); + + if (completedTask.IsFaulted) + { + await completedTask; + } + } + + this.FinishInitialization(State.Open); + } + + } + catch (DocumentClientException e) + { + this.FinishInitialization(State.Closed); + + e.Headers.Set( + HttpConstants.HttpHeaders.ActivityId, + this.openArguments.CommonArguments.ActivityId.ToString()); + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] Channel.InitializeAsync failed. Channel: {1}. DocumentClientException: {2}", + this.ConnectionCorrelationId, this, e); + + throw; + } + catch (TransportException e) + { + this.FinishInitialization(State.Closed); + + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] Channel.InitializeAsync failed. Channel: {1}. TransportException: {2}", + this.ConnectionCorrelationId, this, e); + + throw; + } + catch (Exception e) + { + this.FinishInitialization(State.Closed); + + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] Channel.InitializeAsync failed. Wrapping exception in " + + "TransportException. Channel: {1}. Inner exception: {2}", + this.ConnectionCorrelationId, this, e); + + Debug.Assert(!this.openArguments.CommonArguments.UserPayload); + throw new TransportException( + TransportErrorCode.ChannelOpenFailed, e, + this.openArguments.CommonArguments.ActivityId, + this.serverUri, this.ToString(), + this.openArguments.CommonArguments.UserPayload, + this.openArguments.CommonArguments.PayloadSent); + } + finally + { + this.openArguments.OpenTimeline.WriteTrace(); + // The open arguments are no longer needed after this point. + this.openArguments = null; + if (slimAcquired) + { + this.openingSlim.Release(); + } + } + } + + private void FinishInitialization(State nextState) + { + Debug.Assert(!Monitor.IsEntered(this.stateLock)); + Debug.Assert(nextState == State.Open || nextState == State.Closed); + Task initTask = null; + this.stateLock.EnterWriteLock(); + try + { + // this.state might have become Closed if Dispose was already called. + Debug.Assert(this.state == State.WaitingToOpen || this.state == State.Opening || this.state == State.Closed); + if (this.state != State.Closed) + { + this.state = nextState; + initTask = this.initializationTask; + } + } + finally + { + this.stateLock.ExitWriteLock(); + } + if ((nextState == State.Closed) && (initTask != null)) + { + // In the typical case, a channel is created, asynchronous initialization + // starts, and then one or more callers await on the initialization task + // (and thus consume its exception, if one is thrown). + // This code defends against the rare case where a channel begins asynchronous + // initialization which ends in error, but nothing consumes the exception. + initTask.ContinueWith(completedTask => + { + Debug.Assert(completedTask.IsFaulted); + Debug.Assert(this.serverUri != null); + Debug.Assert(completedTask.Exception != null); + DefaultTrace.TraceWarning( + "[RNTBD Channel {0}] {1} initialization failed. Consuming the task " + + "exception asynchronously. Server URI: {2}. Exception: {3}", + this.ConnectionCorrelationId, + nameof(Channel), + this.serverUri, + completedTask.Exception.InnerException?.Message); + }, + TaskContinuationOptions.OnlyOnFaulted); + } + } + + private static void HandleTaskTimeout(Task runawayTask, Guid activityId, Guid connectionCorrelationId) + { + Task ignored = runawayTask.ContinueWith(task => + { + Trace.CorrelationManager.ActivityId = activityId; + Debug.Assert(task.IsFaulted); + Debug.Assert(task.Exception != null); + Exception e = task.Exception.InnerException; + DefaultTrace.TraceInformation( + "[RNTBD Channel {0}] Timed out task completed. Activity ID = {1}. HRESULT = {2:X}. Exception: {3}", + connectionCorrelationId, activityId, e.HResult, e); + }, + TaskContinuationOptions.OnlyOnFaulted); + } + + private enum State + { + New, + WaitingToOpen, + Opening, + Open, + Closed, + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelCallArguments.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelCallArguments.cs index 435dca3f6a..c6524b278c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelCallArguments.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelCallArguments.cs @@ -1,59 +1,64 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.FaultInjection; - - internal sealed class ChannelCallArguments : IDisposable - { - private readonly ChannelCommonArguments commonArguments; - private readonly OperationType operationType; - private readonly ResourceType resourceType; - private readonly string resolvedCollectionRid; - private readonly INameValueCollection requestHeaders; - - public ChannelCallArguments (Guid activityId) - { - this.commonArguments = new ChannelCommonArguments( - activityId, TransportErrorCode.RequestTimeout, - userPayload: true); - } - - public ChannelCallArguments( - Guid activityId, - OperationType operationType, - ResourceType resourceType, - string resolvedCollectionRid, - INameValueCollection requestHeaders) - { - this.commonArguments = new ChannelCommonArguments( - activityId, TransportErrorCode.RequestTimeout, - userPayload: true); - this.operationType = operationType; - this.resourceType = resourceType; - this.resolvedCollectionRid = resolvedCollectionRid; - this.requestHeaders = requestHeaders; - } - - public ChannelCommonArguments CommonArguments { get { return this.commonArguments; } } - - public Dispatcher.PrepareCallResult PreparedCall { get; set; } - - public OperationType OperationType { get { return this.operationType; } } - - public ResourceType ResourceType { get { return this.resourceType; } } - - public string ResolvedCollectionRid { get { return this.resolvedCollectionRid; } } - - public INameValueCollection RequestHeaders { get { return this.requestHeaders; } } - - /// - public void Dispose() - { - this.PreparedCall?.Dispose(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.FaultInjection; + + internal sealed class ChannelCallArguments : IDisposable + { + private readonly ChannelCommonArguments commonArguments; + private readonly OperationType operationType; + private readonly ResourceType resourceType; + private readonly string resolvedCollectionRid; + private readonly INameValueCollection requestHeaders; + private readonly Uri locationEndpointToRouteTo; + + public ChannelCallArguments (Guid activityId) + { + this.commonArguments = new ChannelCommonArguments( + activityId, TransportErrorCode.RequestTimeout, + userPayload: true); + } + + public ChannelCallArguments( + Guid activityId, + OperationType operationType, + ResourceType resourceType, + string resolvedCollectionRid, + INameValueCollection requestHeaders, + Uri locationEndpointToRouteTo) + { + this.commonArguments = new ChannelCommonArguments( + activityId, TransportErrorCode.RequestTimeout, + userPayload: true); + this.operationType = operationType; + this.resourceType = resourceType; + this.resolvedCollectionRid = resolvedCollectionRid; + this.requestHeaders = requestHeaders; + this.locationEndpointToRouteTo = locationEndpointToRouteTo; + } + + public ChannelCommonArguments CommonArguments { get { return this.commonArguments; } } + + public Dispatcher.PrepareCallResult PreparedCall { get; set; } + + public OperationType OperationType { get { return this.operationType; } } + + public ResourceType ResourceType { get { return this.resourceType; } } + + public string ResolvedCollectionRid { get { return this.resolvedCollectionRid; } } + + public INameValueCollection RequestHeaders { get { return this.requestHeaders; } } + + public Uri LocationEndpointToRouteTo { get { return this.locationEndpointToRouteTo; } } + + /// + public void Dispose() + { + this.PreparedCall?.Dispose(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelCommonArguments.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelCommonArguments.cs index 16b65c0611..6728dba0be 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelCommonArguments.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelCommonArguments.cs @@ -1,95 +1,95 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; - - internal sealed class ChannelCommonArguments - { - private readonly object mutex = new object(); - private TransportErrorCode timeoutCode; // Guarded by mutex - private bool payloadSent = false; // Guarded by mutex - - public ChannelCommonArguments( - Guid activityId, - TransportErrorCode initialTimeoutCode, - bool userPayload) - { - this.ActivityId = activityId; - this.UserPayload = userPayload; - this.SetTimeoutCode(initialTimeoutCode); - } - - public Guid ActivityId { get; set; } - - public bool UserPayload { get; private set; } - - // Call SnapshotCallState if you want to fetch all properties at once. - public bool PayloadSent - { - get - { - lock (this.mutex) - { - return this.payloadSent; - } - } - } - - public void SnapshotCallState( - out TransportErrorCode timeoutCode, out bool payloadSent) - { - lock (this.mutex) - { - timeoutCode = this.timeoutCode; - payloadSent = this.payloadSent; - } - } - - // The timeout code is effectively a progress tracker. Various places - // advance it as they make asynchronous calls that might time out. - // The timeout code is an unreliable indicator in two ways: - // - The caller and the actual network operation run on separate tasks. - // Cancellation isn't currently communicated effectively on timer - // expiration. As such, there is an inherent race between the timer - // firing and capturing the timeout code - the network operation can - // complete and advance the timeout code before the caller can fetch it. - // - Even if the caller captures the right timeout code, this is no - // guarantee that the last operation is the one that exhausted the - // timeout budget. - public void SetTimeoutCode(TransportErrorCode errorCode) - { - Debug.Assert(TransportException.IsTimeout(errorCode)); - if (!TransportException.IsTimeout(errorCode)) - { - throw new ArgumentException( - string.Format( - CultureInfo.InvariantCulture, - "{0} is not a timeout error code", - errorCode), - nameof(errorCode)); - } - lock (this.mutex) - { - this.timeoutCode = errorCode; - } - } - - public void SetPayloadSent() - { - lock (this.mutex) - { - Debug.Assert(!this.payloadSent); - if (this.payloadSent) - { - throw new InvalidOperationException( - "TransportException.SetPayloadSent cannot be called more than once."); - } - this.payloadSent = true; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; + + internal sealed class ChannelCommonArguments + { + private readonly object mutex = new object(); + private TransportErrorCode timeoutCode; // Guarded by mutex + private bool payloadSent = false; // Guarded by mutex + + public ChannelCommonArguments( + Guid activityId, + TransportErrorCode initialTimeoutCode, + bool userPayload) + { + this.ActivityId = activityId; + this.UserPayload = userPayload; + this.SetTimeoutCode(initialTimeoutCode); + } + + public Guid ActivityId { get; set; } + + public bool UserPayload { get; private set; } + + // Call SnapshotCallState if you want to fetch all properties at once. + public bool PayloadSent + { + get + { + lock (this.mutex) + { + return this.payloadSent; + } + } + } + + public void SnapshotCallState( + out TransportErrorCode timeoutCode, out bool payloadSent) + { + lock (this.mutex) + { + timeoutCode = this.timeoutCode; + payloadSent = this.payloadSent; + } + } + + // The timeout code is effectively a progress tracker. Various places + // advance it as they make asynchronous calls that might time out. + // The timeout code is an unreliable indicator in two ways: + // - The caller and the actual network operation run on separate tasks. + // Cancellation isn't currently communicated effectively on timer + // expiration. As such, there is an inherent race between the timer + // firing and capturing the timeout code - the network operation can + // complete and advance the timeout code before the caller can fetch it. + // - Even if the caller captures the right timeout code, this is no + // guarantee that the last operation is the one that exhausted the + // timeout budget. + public void SetTimeoutCode(TransportErrorCode errorCode) + { + Debug.Assert(TransportException.IsTimeout(errorCode)); + if (!TransportException.IsTimeout(errorCode)) + { + throw new ArgumentException( + string.Format( + CultureInfo.InvariantCulture, + "{0} is not a timeout error code", + errorCode), + nameof(errorCode)); + } + lock (this.mutex) + { + this.timeoutCode = errorCode; + } + } + + public void SetPayloadSent() + { + lock (this.mutex) + { + Debug.Assert(!this.payloadSent); + if (this.payloadSent) + { + throw new InvalidOperationException( + "TransportException.SetPayloadSent cannot be called more than once."); + } + this.payloadSent = true; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelDictionary.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelDictionary.cs index 7d8b8280b9..aebd505a96 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelDictionary.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelDictionary.cs @@ -1,89 +1,89 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Concurrent; - using System.Diagnostics; - using Microsoft.Azure.Documents.FaultInjection; - - // ChannelDictionary maps server keys to load-balanced channels. There is - // one load-balanced channel per back-end server. - internal sealed class ChannelDictionary : IChannelDictionary, IDisposable - { - private readonly ChannelProperties channelProperties; - private bool disposed = false; - - private ConcurrentDictionary channels = - new ConcurrentDictionary(); - - private readonly IChaosInterceptor chaosInterceptor; - - public ChannelDictionary(ChannelProperties channelProperties, IChaosInterceptor chaosInterceptor = null) - { - Debug.Assert(channelProperties != null); - this.channelProperties = channelProperties; - this.chaosInterceptor = chaosInterceptor; - } - - /// - /// Creates or gets an instance of using the server's physical uri. - /// - /// An instance of containing the backend server URI. - /// A boolean flag indicating if the request is targeting the local region. - /// An instance of containing the . - public IChannel GetChannel( - Uri requestUri, - bool localRegionRequest) - { - this.ThrowIfDisposed(); - ServerKey key = new ServerKey(requestUri); - IChannel value = null; - if (this.channels.TryGetValue(key, out value)) - { - Debug.Assert(value != null); - return value; - } - value = new LoadBalancingChannel( - new Uri(requestUri.GetLeftPart(UriPartial.Authority)), - this.channelProperties, - localRegionRequest, - this.chaosInterceptor); - - if (this.channels.TryAdd(key, value)) - { - return value; - } - bool found = this.channels.TryGetValue(key, out value); - Debug.Assert(found); - Debug.Assert(value != null); - return value; - } - - public bool TryGetChannel(Uri requestUri, out IChannel channel) - { - this.ThrowIfDisposed(); - ServerKey key = new ServerKey(requestUri); - return this.channels.TryGetValue(key, out channel); - } - - public void Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - foreach (IChannel channel in this.channels.Values) - { - channel.Close(); - } - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException(nameof(ChannelDictionary)); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Concurrent; + using System.Diagnostics; + using Microsoft.Azure.Documents.FaultInjection; + + // ChannelDictionary maps server keys to load-balanced channels. There is + // one load-balanced channel per back-end server. + internal sealed class ChannelDictionary : IChannelDictionary, IDisposable + { + private readonly ChannelProperties channelProperties; + private bool disposed = false; + + private ConcurrentDictionary channels = + new ConcurrentDictionary(); + + private readonly IChaosInterceptor chaosInterceptor; + + public ChannelDictionary(ChannelProperties channelProperties, IChaosInterceptor chaosInterceptor = null) + { + Debug.Assert(channelProperties != null); + this.channelProperties = channelProperties; + this.chaosInterceptor = chaosInterceptor; + } + + /// + /// Creates or gets an instance of using the server's physical uri. + /// + /// An instance of containing the backend server URI. + /// A boolean flag indicating if the request is targeting the local region. + /// An instance of containing the . + public IChannel GetChannel( + Uri requestUri, + bool localRegionRequest) + { + this.ThrowIfDisposed(); + ServerKey key = new ServerKey(requestUri); + IChannel value = null; + if (this.channels.TryGetValue(key, out value)) + { + Debug.Assert(value != null); + return value; + } + value = new LoadBalancingChannel( + new Uri(requestUri.GetLeftPart(UriPartial.Authority)), + this.channelProperties, + localRegionRequest, + this.chaosInterceptor); + + if (this.channels.TryAdd(key, value)) + { + return value; + } + bool found = this.channels.TryGetValue(key, out value); + Debug.Assert(found); + Debug.Assert(value != null); + return value; + } + + public bool TryGetChannel(Uri requestUri, out IChannel channel) + { + this.ThrowIfDisposed(); + ServerKey key = new ServerKey(requestUri); + return this.channels.TryGetValue(key, out channel); + } + + public void Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + foreach (IChannel channel in this.channels.Values) + { + channel.Close(); + } + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + throw new ObjectDisposedException(nameof(ChannelDictionary)); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelOpenArguments.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelOpenArguments.cs index ae1bb6096e..602540644b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelOpenArguments.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelOpenArguments.cs @@ -1,69 +1,69 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - - internal sealed class ChannelOpenArguments - { - private readonly ChannelCommonArguments commonArguments; - private readonly ChannelOpenTimeline openTimeline; - private readonly TimeSpan openTimeout; - private readonly PortReuseMode portReuseMode; - private readonly UserPortPool userPortPool; - private readonly RntbdConstants.CallerId callerId; - - public ChannelOpenArguments( - Guid activityId, - ChannelOpenTimeline openTimeline, - TimeSpan openTimeout, - PortReuseMode portReuseMode, - UserPortPool userPortPool, - RntbdConstants.CallerId callerId) - { - this.commonArguments = new ChannelCommonArguments( - activityId, TransportErrorCode.ChannelOpenTimeout, - userPayload: false); - this.openTimeline = openTimeline; - this.openTimeout = openTimeout; -#if DEBUG - switch (portReuseMode) - { - case PortReuseMode.ReuseUnicastPort: - Debug.Assert(userPortPool == null); - break; - - case PortReuseMode.PrivatePortPool: - Debug.Assert(userPortPool != null); - break; - - default: - Debug.Assert( - false, - string.Format( - "Unhandled enum value {0}. Please decide what are the " + - "class invariants for this value.", - portReuseMode.ToString())); - break; - } -#endif - this.portReuseMode = portReuseMode; - this.userPortPool = userPortPool; - this.callerId = callerId; - } - - public ChannelCommonArguments CommonArguments { get { return this.commonArguments; } } - - public ChannelOpenTimeline OpenTimeline { get { return this.openTimeline; } } - - public TimeSpan OpenTimeout { get { return this.openTimeout; } } - - public PortReuseMode PortReuseMode { get { return this.portReuseMode; } } - - public UserPortPool PortPool { get { return this.userPortPool; } } - - public RntbdConstants.CallerId CallerId { get { return this.callerId; } } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + + internal sealed class ChannelOpenArguments + { + private readonly ChannelCommonArguments commonArguments; + private readonly ChannelOpenTimeline openTimeline; + private readonly TimeSpan openTimeout; + private readonly PortReuseMode portReuseMode; + private readonly UserPortPool userPortPool; + private readonly RntbdConstants.CallerId callerId; + + public ChannelOpenArguments( + Guid activityId, + ChannelOpenTimeline openTimeline, + TimeSpan openTimeout, + PortReuseMode portReuseMode, + UserPortPool userPortPool, + RntbdConstants.CallerId callerId) + { + this.commonArguments = new ChannelCommonArguments( + activityId, TransportErrorCode.ChannelOpenTimeout, + userPayload: false); + this.openTimeline = openTimeline; + this.openTimeout = openTimeout; +#if DEBUG + switch (portReuseMode) + { + case PortReuseMode.ReuseUnicastPort: + Debug.Assert(userPortPool == null); + break; + + case PortReuseMode.PrivatePortPool: + Debug.Assert(userPortPool != null); + break; + + default: + Debug.Assert( + false, + string.Format( + "Unhandled enum value {0}. Please decide what are the " + + "class invariants for this value.", + portReuseMode.ToString())); + break; + } +#endif + this.portReuseMode = portReuseMode; + this.userPortPool = userPortPool; + this.callerId = callerId; + } + + public ChannelCommonArguments CommonArguments { get { return this.commonArguments; } } + + public ChannelOpenTimeline OpenTimeline { get { return this.openTimeline; } } + + public TimeSpan OpenTimeout { get { return this.openTimeout; } } + + public PortReuseMode PortReuseMode { get { return this.portReuseMode; } } + + public UserPortPool PortPool { get { return this.userPortPool; } } + + public RntbdConstants.CallerId CallerId { get { return this.callerId; } } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelOpenTimeline.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelOpenTimeline.cs index 717a7d46fd..1a6b8e873b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelOpenTimeline.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelOpenTimeline.cs @@ -1,75 +1,75 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; - -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - internal sealed class ChannelOpenTimeline - { - private readonly DateTimeOffset creationTime; - private DateTimeOffset connectTime = DateTimeOffset.MinValue; - private DateTimeOffset sslHandshakeTime = DateTimeOffset.MinValue; - private DateTimeOffset rntbdHandshakeTime = DateTimeOffset.MinValue; - - public delegate void ConnectionTimerDelegate( - Guid activityId, - string connectionCreationTime, - string tcpConnectCompleteTime, - string sslHandshakeCompleteTime, - string rntbdHandshakeCompleteTime, - string openTaskCompletionTime); - - public ChannelOpenTimeline() - { - this.creationTime = DateTimeOffset.UtcNow; - } - - public void RecordConnectFinishTime() - { - Debug.Assert(this.connectTime == DateTimeOffset.MinValue); - this.connectTime = DateTimeOffset.UtcNow; - } - - public void RecordSslHandshakeFinishTime() - { - Debug.Assert(this.connectTime != DateTimeOffset.MinValue, - string.Format("Call {0} first", nameof(RecordConnectFinishTime))); - Debug.Assert(this.sslHandshakeTime == DateTimeOffset.MinValue); - this.sslHandshakeTime = DateTimeOffset.UtcNow; - } - - public void RecordRntbdHandshakeFinishTime() - { - Debug.Assert(this.sslHandshakeTime != DateTimeOffset.MinValue, - string.Format("Call {0} first", nameof(RecordSslHandshakeFinishTime))); - Debug.Assert(this.rntbdHandshakeTime == DateTimeOffset.MinValue); - this.rntbdHandshakeTime = DateTimeOffset.UtcNow; - } - - public void WriteTrace() - { - DateTimeOffset now = DateTimeOffset.UtcNow; - ChannelOpenTimeline.TraceFunc?.Invoke( - Trace.CorrelationManager.ActivityId, - ChannelOpenTimeline.InvariantString(this.creationTime), - ChannelOpenTimeline.InvariantString(this.connectTime), - ChannelOpenTimeline.InvariantString(this.sslHandshakeTime), - ChannelOpenTimeline.InvariantString(this.rntbdHandshakeTime), - ChannelOpenTimeline.InvariantString(now)); - } - - public static ConnectionTimerDelegate TraceFunc { get; set; } - - private static string InvariantString(DateTimeOffset t) - { - return t.ToString("o", CultureInfo.InvariantCulture); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; + +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + internal sealed class ChannelOpenTimeline + { + private readonly DateTimeOffset creationTime; + private DateTimeOffset connectTime = DateTimeOffset.MinValue; + private DateTimeOffset sslHandshakeTime = DateTimeOffset.MinValue; + private DateTimeOffset rntbdHandshakeTime = DateTimeOffset.MinValue; + + public delegate void ConnectionTimerDelegate( + Guid activityId, + string connectionCreationTime, + string tcpConnectCompleteTime, + string sslHandshakeCompleteTime, + string rntbdHandshakeCompleteTime, + string openTaskCompletionTime); + + public ChannelOpenTimeline() + { + this.creationTime = DateTimeOffset.UtcNow; + } + + public void RecordConnectFinishTime() + { + Debug.Assert(this.connectTime == DateTimeOffset.MinValue); + this.connectTime = DateTimeOffset.UtcNow; + } + + public void RecordSslHandshakeFinishTime() + { + Debug.Assert(this.connectTime != DateTimeOffset.MinValue, + string.Format("Call {0} first", nameof(RecordConnectFinishTime))); + Debug.Assert(this.sslHandshakeTime == DateTimeOffset.MinValue); + this.sslHandshakeTime = DateTimeOffset.UtcNow; + } + + public void RecordRntbdHandshakeFinishTime() + { + Debug.Assert(this.sslHandshakeTime != DateTimeOffset.MinValue, + string.Format("Call {0} first", nameof(RecordSslHandshakeFinishTime))); + Debug.Assert(this.rntbdHandshakeTime == DateTimeOffset.MinValue); + this.rntbdHandshakeTime = DateTimeOffset.UtcNow; + } + + public void WriteTrace() + { + DateTimeOffset now = DateTimeOffset.UtcNow; + ChannelOpenTimeline.TraceFunc?.Invoke( + Trace.CorrelationManager.ActivityId, + ChannelOpenTimeline.InvariantString(this.creationTime), + ChannelOpenTimeline.InvariantString(this.connectTime), + ChannelOpenTimeline.InvariantString(this.sslHandshakeTime), + ChannelOpenTimeline.InvariantString(this.rntbdHandshakeTime), + ChannelOpenTimeline.InvariantString(now)); + } + + public static ConnectionTimerDelegate TraceFunc { get; set; } + + private static string InvariantString(DateTimeOffset t) + { + return t.ToString("o", CultureInfo.InvariantCulture); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ChannelProperties.cs b/Microsoft.Azure.Cosmos/src/direct/ChannelProperties.cs index cf9a2a2072..b074761440 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ChannelProperties.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ChannelProperties.cs @@ -1,112 +1,112 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Net; - using System.Net.Security; - using System.Threading.Tasks; - - internal sealed class ChannelProperties - { - public ChannelProperties(UserAgentContainer userAgent, - string certificateHostNameOverride, IConnectionStateListener connectionStateListener, - TimerPool requestTimerPool, TimeSpan requestTimeout, TimeSpan openTimeout, TimeSpan localRegionOpenTimeout, - PortReuseMode portReuseMode, UserPortPool userPortPool, - int maxChannels, int partitionCount, int maxRequestsPerChannel, - int maxConcurrentOpeningConnectionCount, - TimeSpan receiveHangDetectionTime, TimeSpan sendHangDetectionTime, - TimeSpan idleTimeout, TimerPool idleTimerPool, - RntbdConstants.CallerId callerId, bool enableChannelMultiplexing, - MemoryStreamPool memoryStreamPool, - RemoteCertificateValidationCallback remoteCertificateValidationCallback, - Func> dnsResolutionFunction) - { - Debug.Assert(userAgent != null); - this.UserAgent = userAgent; - this.CertificateHostNameOverride = certificateHostNameOverride; - this.ConnectionStateListener = connectionStateListener; - - Debug.Assert(requestTimerPool != null); - this.RequestTimerPool = requestTimerPool; - this.RequestTimeout = requestTimeout; - this.OpenTimeout = openTimeout; - this.LocalRegionOpenTimeout = localRegionOpenTimeout; - - this.PortReuseMode = portReuseMode; - this.UserPortPool = userPortPool; - - Debug.Assert(maxChannels > 0); - this.MaxChannels = maxChannels; - Debug.Assert(partitionCount > 0); - this.PartitionCount = partitionCount; - Debug.Assert(maxRequestsPerChannel > 0); - this.MaxRequestsPerChannel = maxRequestsPerChannel; - - Debug.Assert(receiveHangDetectionTime > TimeSpan.Zero); - this.ReceiveHangDetectionTime = receiveHangDetectionTime; - Debug.Assert(sendHangDetectionTime > TimeSpan.Zero); - this.SendHangDetectionTime = sendHangDetectionTime; - this.IdleTimeout = idleTimeout; - this.IdleTimerPool = idleTimerPool; - this.CallerId = callerId; - this.EnableChannelMultiplexing = enableChannelMultiplexing; - this.MaxConcurrentOpeningConnectionCount = maxConcurrentOpeningConnectionCount; - this.MemoryStreamPool = memoryStreamPool; - this.RemoteCertificateValidationCallback = remoteCertificateValidationCallback; - this.DnsResolutionFunction = dnsResolutionFunction; - } - - public UserAgentContainer UserAgent { get; private set; } - - public string CertificateHostNameOverride { get; private set; } - - public IConnectionStateListener ConnectionStateListener { get; private set; } - - /// - /// timer pool to track request timeout - /// - public TimerPool RequestTimerPool { get; private set; } - - /// - /// timer pool to track idle channels - /// - public TimerPool IdleTimerPool { get; private set; } - - public TimeSpan RequestTimeout { get; private set; } - - public TimeSpan OpenTimeout { get; private set; } - - public TimeSpan LocalRegionOpenTimeout { get; private set; } - - public PortReuseMode PortReuseMode { get; private set; } - - public int MaxChannels { get; private set; } - - public int PartitionCount { get; private set; } - - public int MaxRequestsPerChannel { get; private set; } - - public TimeSpan ReceiveHangDetectionTime { get; private set; } - - public TimeSpan SendHangDetectionTime { get; private set; } - - public TimeSpan IdleTimeout { get; private set; } - - public UserPortPool UserPortPool { get; private set; } - - public RntbdConstants.CallerId CallerId { get; private set; } - - public bool EnableChannelMultiplexing { get; private set; } - - public int MaxConcurrentOpeningConnectionCount { get; private set; } - - public MemoryStreamPool MemoryStreamPool { get; private set; } - - public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; private set; } - - public Func> DnsResolutionFunction { get; private set; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Net; + using System.Net.Security; + using System.Threading.Tasks; + + internal sealed class ChannelProperties + { + public ChannelProperties(UserAgentContainer userAgent, + string certificateHostNameOverride, IConnectionStateListener connectionStateListener, + TimerPool requestTimerPool, TimeSpan requestTimeout, TimeSpan openTimeout, TimeSpan localRegionOpenTimeout, + PortReuseMode portReuseMode, UserPortPool userPortPool, + int maxChannels, int partitionCount, int maxRequestsPerChannel, + int maxConcurrentOpeningConnectionCount, + TimeSpan receiveHangDetectionTime, TimeSpan sendHangDetectionTime, + TimeSpan idleTimeout, TimerPool idleTimerPool, + RntbdConstants.CallerId callerId, bool enableChannelMultiplexing, + MemoryStreamPool memoryStreamPool, + RemoteCertificateValidationCallback remoteCertificateValidationCallback, + Func> dnsResolutionFunction) + { + Debug.Assert(userAgent != null); + this.UserAgent = userAgent; + this.CertificateHostNameOverride = certificateHostNameOverride; + this.ConnectionStateListener = connectionStateListener; + + Debug.Assert(requestTimerPool != null); + this.RequestTimerPool = requestTimerPool; + this.RequestTimeout = requestTimeout; + this.OpenTimeout = openTimeout; + this.LocalRegionOpenTimeout = localRegionOpenTimeout; + + this.PortReuseMode = portReuseMode; + this.UserPortPool = userPortPool; + + Debug.Assert(maxChannels > 0); + this.MaxChannels = maxChannels; + Debug.Assert(partitionCount > 0); + this.PartitionCount = partitionCount; + Debug.Assert(maxRequestsPerChannel > 0); + this.MaxRequestsPerChannel = maxRequestsPerChannel; + + Debug.Assert(receiveHangDetectionTime > TimeSpan.Zero); + this.ReceiveHangDetectionTime = receiveHangDetectionTime; + Debug.Assert(sendHangDetectionTime > TimeSpan.Zero); + this.SendHangDetectionTime = sendHangDetectionTime; + this.IdleTimeout = idleTimeout; + this.IdleTimerPool = idleTimerPool; + this.CallerId = callerId; + this.EnableChannelMultiplexing = enableChannelMultiplexing; + this.MaxConcurrentOpeningConnectionCount = maxConcurrentOpeningConnectionCount; + this.MemoryStreamPool = memoryStreamPool; + this.RemoteCertificateValidationCallback = remoteCertificateValidationCallback; + this.DnsResolutionFunction = dnsResolutionFunction; + } + + public UserAgentContainer UserAgent { get; private set; } + + public string CertificateHostNameOverride { get; private set; } + + public IConnectionStateListener ConnectionStateListener { get; private set; } + + /// + /// timer pool to track request timeout + /// + public TimerPool RequestTimerPool { get; private set; } + + /// + /// timer pool to track idle channels + /// + public TimerPool IdleTimerPool { get; private set; } + + public TimeSpan RequestTimeout { get; private set; } + + public TimeSpan OpenTimeout { get; private set; } + + public TimeSpan LocalRegionOpenTimeout { get; private set; } + + public PortReuseMode PortReuseMode { get; private set; } + + public int MaxChannels { get; private set; } + + public int PartitionCount { get; private set; } + + public int MaxRequestsPerChannel { get; private set; } + + public TimeSpan ReceiveHangDetectionTime { get; private set; } + + public TimeSpan SendHangDetectionTime { get; private set; } + + public TimeSpan IdleTimeout { get; private set; } + + public UserPortPool UserPortPool { get; private set; } + + public RntbdConstants.CallerId CallerId { get; private set; } + + public bool EnableChannelMultiplexing { get; private set; } + + public int MaxConcurrentOpeningConnectionCount { get; private set; } + + public MemoryStreamPool MemoryStreamPool { get; private set; } + + public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; private set; } + + public Func> DnsResolutionFunction { get; private set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionIncludedPath.cs b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionIncludedPath.cs index 0647cb2442..7ad7865530 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionIncludedPath.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionIncludedPath.cs @@ -1,54 +1,54 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Path that needs encryption and the associated settings within . - /// - internal sealed class ClientEncryptionIncludedPath : JsonSerializable - { - /// - /// Gets or sets the path to be encrypted. Must be a top level path, eg. /salary - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get { return this.GetValue(Constants.Properties.Path); } - set { this.SetValue(Constants.Properties.Path, value); } - } - - /// - /// Gets or sets the identifier of the Client Encryption Key to be used to encrypt the path. - /// - [JsonProperty(PropertyName = Constants.Properties.ClientEncryptionKeyId)] - public string ClientEncryptionKeyId - { - get { return this.GetValue(Constants.Properties.ClientEncryptionKeyId); } - set { this.SetValue(Constants.Properties.ClientEncryptionKeyId, value); } - } - - /// - /// Gets or sets the type of encryption to be performed. Eg - Deterministic, Randomized - /// - [JsonProperty(PropertyName = Constants.Properties.EncryptionType)] - public string EncryptionType - { - get { return this.GetValue(Constants.Properties.EncryptionType); } - set { this.SetValue(Constants.Properties.EncryptionType, value); } - } - - /// - /// Gets or sets the encryption algorithm which will be used. Eg - AEAD_AES_256_CBC_HMAC_SHA256 - /// - [JsonProperty(PropertyName = Constants.Properties.EncryptionAlgorithm)] - public string EncryptionAlgorithm - { - get { return this.GetValue(Constants.Properties.EncryptionAlgorithm); } - set { this.SetValue(Constants.Properties.EncryptionAlgorithm, value); } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Path that needs encryption and the associated settings within . + /// + internal sealed class ClientEncryptionIncludedPath : JsonSerializable + { + /// + /// Gets or sets the path to be encrypted. Must be a top level path, eg. /salary + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get { return this.GetValue(Constants.Properties.Path); } + set { this.SetValue(Constants.Properties.Path, value); } + } + + /// + /// Gets or sets the identifier of the Client Encryption Key to be used to encrypt the path. + /// + [JsonProperty(PropertyName = Constants.Properties.ClientEncryptionKeyId)] + public string ClientEncryptionKeyId + { + get { return this.GetValue(Constants.Properties.ClientEncryptionKeyId); } + set { this.SetValue(Constants.Properties.ClientEncryptionKeyId, value); } + } + + /// + /// Gets or sets the type of encryption to be performed. Eg - Deterministic, Randomized + /// + [JsonProperty(PropertyName = Constants.Properties.EncryptionType)] + public string EncryptionType + { + get { return this.GetValue(Constants.Properties.EncryptionType); } + set { this.SetValue(Constants.Properties.EncryptionType, value); } + } + + /// + /// Gets or sets the encryption algorithm which will be used. Eg - AEAD_AES_256_CBC_HMAC_SHA256 + /// + [JsonProperty(PropertyName = Constants.Properties.EncryptionAlgorithm)] + public string EncryptionAlgorithm + { + get { return this.GetValue(Constants.Properties.EncryptionAlgorithm); } + set { this.SetValue(Constants.Properties.EncryptionAlgorithm, value); } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionKey.cs b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionKey.cs index b101eb9548..42b37de97c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionKey.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionKey.cs @@ -1,75 +1,75 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents a client encryption key in the Azure Cosmos DB service. - /// - internal class ClientEncryptionKey: Resource - { - private KeyWrapMetadata keyWrapMetadata; - - public ClientEncryptionKey() - { - - } - - [JsonProperty(PropertyName = Constants.Properties.EncryptionAlgorithm)] - internal string EncryptionAlgorithm - { - get - { - return this.GetValue(Constants.Properties.EncryptionAlgorithm); - } - set - { - base.SetValue(Constants.Properties.EncryptionAlgorithm, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.WrappedDataEncryptionKey)] - internal byte[] WrappedDataEncryptionKey - { - get - { - return this.GetValue(Constants.Properties.WrappedDataEncryptionKey); - } - set - { - base.SetValue(Constants.Properties.WrappedDataEncryptionKey, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadata)] - internal KeyWrapMetadata KeyWrapMetadata - { - get - { - if (this.keyWrapMetadata == null) - { - this.keyWrapMetadata = base.GetObject(Constants.Properties.KeyWrapMetadata) ?? new KeyWrapMetadata(); - } - - return keyWrapMetadata; - } - set - { - this.keyWrapMetadata = value; - base.SetObject(Constants.Properties.KeyWrapMetadata, value); - } - } - - internal override void OnSave() - { - if (this.keyWrapMetadata != null) - { - this.keyWrapMetadata.OnSave(); - base.SetObject(Constants.Properties.KeyWrapMetadata, this.keyWrapMetadata); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents a client encryption key in the Azure Cosmos DB service. + /// + internal class ClientEncryptionKey: Resource + { + private KeyWrapMetadata keyWrapMetadata; + + public ClientEncryptionKey() + { + + } + + [JsonProperty(PropertyName = Constants.Properties.EncryptionAlgorithm)] + internal string EncryptionAlgorithm + { + get + { + return this.GetValue(Constants.Properties.EncryptionAlgorithm); + } + set + { + base.SetValue(Constants.Properties.EncryptionAlgorithm, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.WrappedDataEncryptionKey)] + internal byte[] WrappedDataEncryptionKey + { + get + { + return this.GetValue(Constants.Properties.WrappedDataEncryptionKey); + } + set + { + base.SetValue(Constants.Properties.WrappedDataEncryptionKey, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadata)] + internal KeyWrapMetadata KeyWrapMetadata + { + get + { + if (this.keyWrapMetadata == null) + { + this.keyWrapMetadata = base.GetObject(Constants.Properties.KeyWrapMetadata) ?? new KeyWrapMetadata(); + } + + return keyWrapMetadata; + } + set + { + this.keyWrapMetadata = value; + base.SetObject(Constants.Properties.KeyWrapMetadata, value); + } + } + + internal override void OnSave() + { + if (this.keyWrapMetadata != null) + { + this.keyWrapMetadata.OnSave(); + base.SetObject(Constants.Properties.KeyWrapMetadata, this.keyWrapMetadata); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionPolicy.cs index 8ce8bf6c8a..175da2daf5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ClientEncryptionPolicy.cs @@ -1,66 +1,66 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - - /// - /// Represents the client encryption policy for a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class ClientEncryptionPolicy : JsonSerializable - { - private Collection includedPaths; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public ClientEncryptionPolicy() - { - } - - /// - /// Paths of the item that need encryption along with path-specific settings. - /// - [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] - public Collection IncludedPaths - { - get - { - if (this.includedPaths == null) - { - this.includedPaths = base.GetObjectCollection(Constants.Properties.IncludedPaths); - if (this.includedPaths == null) - { - this.includedPaths = new Collection(); - } - } - - return this.includedPaths; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IncludedPaths))); - } - - this.includedPaths = value; - base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); - } - } - - internal override void OnSave() - { - if (this.includedPaths != null) - { - base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Represents the client encryption policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class ClientEncryptionPolicy : JsonSerializable + { + private Collection includedPaths; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public ClientEncryptionPolicy() + { + } + + /// + /// Paths of the item that need encryption along with path-specific settings. + /// + [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] + public Collection IncludedPaths + { + get + { + if (this.includedPaths == null) + { + this.includedPaths = base.GetObjectCollection(Constants.Properties.IncludedPaths); + if (this.includedPaths == null) + { + this.includedPaths = new Collection(); + } + } + + return this.includedPaths; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IncludedPaths))); + } + + this.includedPaths = value; + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + } + } + + internal override void OnSave() + { + if (this.includedPaths != null) + { + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs index 589dd91d2d..14771c3a38 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs @@ -1,537 +1,537 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Rntbd; - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Net.Http; - using System.Text; - - internal sealed class ClientSideRequestStatistics : IClientSideRequestStatistics - { - private static readonly SystemUsageMonitor systemUsageMonitor; - private static readonly SystemUsageRecorder systemRecorder; - private static readonly TimeSpan SystemUsageRecordInterval = TimeSpan.FromSeconds(10); - private const string EnableCpuMonitorConfig = "CosmosDbEnableCpuMonitor"; - private const int MaxSupplementalRequestsForToString = 10; - private static bool enableCpuMonitorFlag; - - private DateTime requestStartTime; - private DateTime? requestEndTime; - - private object lockObject = new object(); - private object requestEndTimeLock = new object(); - - private List responseStatisticsList; - private List supplementalResponseStatisticsList; - private Dictionary addressResolutionStatistics; - private Lazy> httpResponseStatisticsList; - private SystemUsageHistory systemUsageHistory; - - static ClientSideRequestStatistics() - { - ClientSideRequestStatistics.enableCpuMonitorFlag = true; -#if !(NETSTANDARD15 || NETSTANDARD16) - string enableCpuMonitorString = System.Configuration.ConfigurationManager.AppSettings[ClientSideRequestStatistics.EnableCpuMonitorConfig]; - if (!string.IsNullOrEmpty(enableCpuMonitorString)) - { - - if (!bool.TryParse(enableCpuMonitorString, out ClientSideRequestStatistics.enableCpuMonitorFlag)) - { - ClientSideRequestStatistics.enableCpuMonitorFlag = true; - } - } -#endif - - if (ClientSideRequestStatistics.enableCpuMonitorFlag) - { - // Have a history up to 1 minute with recording every 10 seconds - ClientSideRequestStatistics.systemRecorder = new SystemUsageRecorder( - identifier: nameof(ClientSideRequestStatistics), - historyLength: 6, - refreshInterval: ClientSideRequestStatistics.SystemUsageRecordInterval); - - ClientSideRequestStatistics.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(new List() - { - ClientSideRequestStatistics.systemRecorder, - }); - } - } - - - public ClientSideRequestStatistics() - { - this.requestStartTime = DateTime.UtcNow; - this.requestEndTime = null; - this.responseStatisticsList = new List(); - this.supplementalResponseStatisticsList = new List(); - this.addressResolutionStatistics = new Dictionary(); - this.ContactedReplicas = new List(); - this.FailedReplicas = new HashSet(); - this.RegionsContacted = new HashSet<(string, Uri)>(); - this.httpResponseStatisticsList = new Lazy>(); - } - - public List ContactedReplicas { get; set; } - - public HashSet FailedReplicas { get; private set; } - - public HashSet<(string, Uri)> RegionsContacted { get; private set; } - - - public TimeSpan? RequestLatency - { - get - { - if (!requestEndTime.HasValue) - { - return null; - } - - return requestEndTime.Value - requestStartTime; - } - } - - public bool? IsCpuHigh - { - get - { - return this.systemUsageHistory?.IsCpuHigh; - } - } - - public bool? IsCpuThreadStarvation - { - get - { - return this.systemUsageHistory?.IsCpuThreadStarvation; - } - } - - internal static void DisableCpuMonitor() - { - // CPU monitor is already disabled - if (!ClientSideRequestStatistics.enableCpuMonitorFlag) - { - return; - } - - ClientSideRequestStatistics.enableCpuMonitorFlag = false; - if (ClientSideRequestStatistics.systemRecorder != null) - { - ClientSideRequestStatistics.systemUsageMonitor.Stop(); - ClientSideRequestStatistics.systemUsageMonitor.Dispose(); - } - } - - public void RecordRequest(DocumentServiceRequest request) - { - } - - public void RecordResponse( - DocumentServiceRequest request, - StoreResult storeResult, - DateTime startTimeUtc, - DateTime endTimeUtc) - { - this.UpdateRequestEndTime(endTimeUtc); - - StoreResponseStatistics responseStatistics; - responseStatistics.RequestStartTime = startTimeUtc; - responseStatistics.RequestResponseTime = endTimeUtc; - responseStatistics.StoreResult = storeResult; - responseStatistics.RequestOperationType = request.OperationType; - responseStatistics.RequestResourceType = request.ResourceType; - - Uri locationEndpoint = request.RequestContext.LocationEndpointToRoute; - string regionName = request.RequestContext.RegionName ?? string.Empty; - - lock (this.lockObject) - { - if (locationEndpoint != null) - { - this.RegionsContacted.Add((regionName, locationEndpoint)); - } - - if (responseStatistics.RequestOperationType == OperationType.Head || responseStatistics.RequestOperationType == OperationType.HeadFeed) - { - this.supplementalResponseStatisticsList.Add(responseStatistics); - } - else - { - this.responseStatisticsList.Add(responseStatistics); - } - } - } - - public void RecordException( - DocumentServiceRequest request, - Exception exception, - DateTime startTime, - DateTime endTimeUtc) - { - this.UpdateRequestEndTime(endTimeUtc); - } - - public string RecordAddressResolutionStart(Uri targetEndpoint) - { - string identifier = Guid.NewGuid().ToString(); - AddressResolutionStatistics resolutionStats = new AddressResolutionStatistics - { - StartTime = DateTime.UtcNow, - EndTime = DateTime.MaxValue, - TargetEndpoint = targetEndpoint == null ? "" : targetEndpoint.ToString() - }; - - lock (this.lockObject) - { - this.addressResolutionStatistics.Add(identifier, resolutionStats); - } - - return identifier; - } - - public void RecordAddressResolutionEnd(string identifier) - { - if (string.IsNullOrEmpty(identifier)) - { - return; - } - - DateTime responseTime = DateTime.UtcNow; - this.UpdateRequestEndTime(DateTime.UtcNow); - lock (this.lockObject) - { - if (!this.addressResolutionStatistics.ContainsKey(identifier)) - { - throw new ArgumentException("Identifier {0} does not exist. Please call start before calling end.", identifier); - } - - this.addressResolutionStatistics[identifier].EndTime = responseTime; - } - } - - public void RecordHttpResponse(HttpRequestMessage request, - HttpResponseMessage response, - ResourceType resourceType, - DateTime requestStartTimeUtc) - { - DateTime requestEndTimeUtc = DateTime.UtcNow; - this.UpdateRequestEndTime(requestEndTimeUtc); - lock (this.httpResponseStatisticsList) - { - this.httpResponseStatisticsList.Value.Add(new HttpResponseStatistics(requestStartTimeUtc, - requestEndTimeUtc, - request.RequestUri, - request.Method, - resourceType, - response, - exception: null)); - } - } - - public void RecordHttpException(HttpRequestMessage request, - Exception exception, - ResourceType resourceType, - DateTime requestStartTimeUtc) - { - DateTime requestEndTimeUtc = DateTime.UtcNow; - this.UpdateRequestEndTime(requestEndTimeUtc); - lock (this.httpResponseStatisticsList) - { - this.httpResponseStatisticsList.Value.Add(new HttpResponseStatistics(requestStartTimeUtc, - requestEndTimeUtc, - request.RequestUri, - request.Method, - resourceType, - responseMessage: null, - exception: exception)); - } - } - - private void UpdateRequestEndTime(DateTime requestEndTimeUtc) - { - lock (this.requestEndTimeLock) - { - if (!this.requestEndTime.HasValue || requestEndTimeUtc > this.requestEndTime) - { - this.UpdateSystemUsageHistory(); - this.requestEndTime = requestEndTimeUtc; - } - } - } - - private void UpdateSystemUsageHistory() - { - // Only update the CPU history if it more than 10 seconds has passed since it was originally collected - if (ClientSideRequestStatistics.enableCpuMonitorFlag && - ClientSideRequestStatistics.systemRecorder != null && - (this.systemUsageHistory == null || this.systemUsageHistory.LastTimestamp + ClientSideRequestStatistics.SystemUsageRecordInterval < DateTime.UtcNow)) - { - try - { - this.systemUsageHistory = ClientSideRequestStatistics.systemRecorder.Data; - } - catch (Exception ex) - { - DefaultTrace.TraceCritical( - "System usage monitor failed with an unexpected exception: {0}", - ex); - } - } - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - this.AppendToBuilder(sb); - return sb.ToString(); - } - - public void AppendToBuilder(StringBuilder stringBuilder) - { - if (stringBuilder == null) - { - throw new ArgumentNullException(nameof(stringBuilder)); - } - - //need to lock in case of concurrent operations. this should be extremely rare since ToString() - //should only be called at the end of request. - lock (this.lockObject) - { - stringBuilder.AppendLine(); - - string endtime; - if (this.requestEndTime.HasValue) - { - endtime = this.requestEndTime.Value.ToString("o", CultureInfo.InvariantCulture); - } - else - { - endtime = $"No response recorded; Current Time: {DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}"; - } - - //first trace request start time, as well as total non-head/headfeed requests made. - stringBuilder.AppendFormat( - CultureInfo.InvariantCulture, - "RequestStartTime: {0}, RequestEndTime: {1}, Number of regions attempted:{2}", - this.requestStartTime.ToString("o", CultureInfo.InvariantCulture), - endtime, - this.RegionsContacted.Count == 0 ? 1 : this.RegionsContacted.Count); - stringBuilder.AppendLine(); - - // This is needed for scenarios where the request was not sent - // so there is no response which triggers saving the system usage - if(this.systemUsageHistory == null) - { - this.UpdateSystemUsageHistory(); - } - - if (this.systemUsageHistory != null && - this.systemUsageHistory.Values.Count > 0) - { - this.systemUsageHistory.AppendJsonString(stringBuilder); - stringBuilder.AppendLine(); - } - else - { - stringBuilder.AppendLine("System history not available."); - } - - //take all responses here - this should be limited in number and each one contains relevant information. - foreach (StoreResponseStatistics item in this.responseStatisticsList) - { - item.AppendToBuilder(stringBuilder); - stringBuilder.AppendLine(); - } - - //take all responses here - this should be limited in number and each one is important. - foreach (AddressResolutionStatistics item in this.addressResolutionStatistics.Values) - { - item.AppendToBuilder(stringBuilder); - stringBuilder.AppendLine(); - } - - //take all responses here - this should be limited in number and each one is important. - lock (this.httpResponseStatisticsList) - { - if (this.httpResponseStatisticsList.IsValueCreated) - { - foreach (HttpResponseStatistics item in this.httpResponseStatisticsList.Value) - { - item.AppendToBuilder(stringBuilder); - stringBuilder.AppendLine(); - } - } - } - - //only take last 10 responses from this list - this has potential of having large number of entries. - //since this is for establishing consistency, we can make do with the last responses to paint a meaningful picture. - int supplementalResponseStatisticsListCount = this.supplementalResponseStatisticsList.Count; - int initialIndex = Math.Max(supplementalResponseStatisticsListCount - ClientSideRequestStatistics.MaxSupplementalRequestsForToString, 0); - - if (initialIndex != 0) - { - stringBuilder.AppendFormat( - CultureInfo.InvariantCulture, - " -- Displaying only the last {0} head/headfeed requests. Total head/headfeed requests: {1}", - ClientSideRequestStatistics.MaxSupplementalRequestsForToString, - supplementalResponseStatisticsListCount); - stringBuilder.AppendLine(); - } - - for (int i = initialIndex; i < supplementalResponseStatisticsListCount; i++) - { - this.supplementalResponseStatisticsList[i].AppendToBuilder(stringBuilder); - stringBuilder.AppendLine(); - } - } - } - - public struct StoreResponseStatistics - { - public DateTime RequestStartTime; - public DateTime RequestResponseTime; - public StoreResult StoreResult; - public ResourceType RequestResourceType; - public OperationType RequestOperationType; - - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder(); - this.AppendToBuilder(stringBuilder); - return stringBuilder.ToString(); - } - - public void AppendToBuilder(StringBuilder stringBuilder) - { - if (stringBuilder == null) - { - throw new ArgumentNullException(nameof(stringBuilder)); - } - - stringBuilder.Append("RequestStart: "); - stringBuilder.Append(this.RequestStartTime.ToString("o", CultureInfo.InvariantCulture)); - stringBuilder.Append("; ResponseTime: "); - stringBuilder.Append(this.RequestResponseTime.ToString("o", CultureInfo.InvariantCulture)); - - stringBuilder.Append("; StoreResult: "); - this.StoreResult?.AppendToBuilder(stringBuilder); - - stringBuilder.AppendLine(); - stringBuilder.AppendFormat( - CultureInfo.InvariantCulture, - " ResourceType: {0}, OperationType: {1}", - this.RequestResourceType, - this.RequestOperationType); - } - } - - - private class AddressResolutionStatistics - { - public DateTime StartTime { get; set; } - public DateTime EndTime { get; set; } - public string TargetEndpoint { get; set; } - - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder(); - this.AppendToBuilder(stringBuilder); - return stringBuilder.ToString(); - } - - public void AppendToBuilder(StringBuilder stringBuilder) - { - if (stringBuilder == null) - { - throw new ArgumentNullException(nameof(stringBuilder)); - } - - stringBuilder - .Append($"AddressResolution - StartTime: {this.StartTime.ToString("o", CultureInfo.InvariantCulture)}, ") - .Append($"EndTime: {this.EndTime.ToString("o", CultureInfo.InvariantCulture)}, ") - .Append("TargetEndpoint: ") - .Append(this.TargetEndpoint); - - } - } - - public readonly struct HttpResponseStatistics - { - public HttpResponseStatistics( - DateTime requestStartTime, - DateTime requestEndTime, - Uri requestUri, - HttpMethod httpMethod, - ResourceType resourceType, - HttpResponseMessage responseMessage, - Exception exception) - { - this.RequestStartTime = requestStartTime; - this.Duration = requestEndTime - requestStartTime; - this.HttpResponseMessage = responseMessage; - this.Exception = exception; - this.ResourceType = resourceType; - this.HttpMethod = httpMethod; - this.RequestUri = requestUri; - this.ActivityId = Trace.CorrelationManager.ActivityId.ToString(); - } - - public DateTime RequestStartTime { get; } - public TimeSpan Duration { get; } - public HttpResponseMessage HttpResponseMessage { get; } - public Exception Exception { get; } - public ResourceType ResourceType { get; } - public HttpMethod HttpMethod { get; } - public Uri RequestUri { get; } - public string ActivityId { get; } - - public void AppendToBuilder(StringBuilder stringBuilder) - { - if (stringBuilder == null) - { - throw new ArgumentNullException(nameof(stringBuilder)); - } - - stringBuilder - .Append("HttpResponseStatistics - ") - .Append("RequestStartTime: ") - .Append(this.RequestStartTime.ToString("o", CultureInfo.InvariantCulture)) - .Append(", DurationInMs: ") - .Append(this.Duration.TotalMilliseconds) - .Append(", RequestUri: ") - .Append(this.RequestUri) - .Append(", ResourceType: ") - .Append(this.ResourceType) - .Append(", HttpMethod: ") - .Append(this.HttpMethod); - - if (this.Exception != null) - { - stringBuilder.Append(", ExceptionType: ") - .Append(this.Exception.GetType()) - .Append(", ExceptionMessage: ") - .Append(this.Exception.Message); - } - - if (this.HttpResponseMessage != null) - { - stringBuilder.Append(", StatusCode: ") - .Append(this.HttpResponseMessage.StatusCode); - if (!this.HttpResponseMessage.IsSuccessStatusCode) - { - stringBuilder.Append(", ReasonPhrase: ") - .Append(this.HttpResponseMessage.ReasonPhrase); - } - } - } - } - } -} - +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Rntbd; + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Net.Http; + using System.Text; + + internal sealed class ClientSideRequestStatistics : IClientSideRequestStatistics + { + private static readonly SystemUsageMonitor systemUsageMonitor; + private static readonly SystemUsageRecorder systemRecorder; + private static readonly TimeSpan SystemUsageRecordInterval = TimeSpan.FromSeconds(10); + private const string EnableCpuMonitorConfig = "CosmosDbEnableCpuMonitor"; + private const int MaxSupplementalRequestsForToString = 10; + private static bool enableCpuMonitorFlag; + + private DateTime requestStartTime; + private DateTime? requestEndTime; + + private object lockObject = new object(); + private object requestEndTimeLock = new object(); + + private List responseStatisticsList; + private List supplementalResponseStatisticsList; + private Dictionary addressResolutionStatistics; + private Lazy> httpResponseStatisticsList; + private SystemUsageHistory systemUsageHistory; + + static ClientSideRequestStatistics() + { + ClientSideRequestStatistics.enableCpuMonitorFlag = true; +#if !(NETSTANDARD15 || NETSTANDARD16) + string enableCpuMonitorString = System.Configuration.ConfigurationManager.AppSettings[ClientSideRequestStatistics.EnableCpuMonitorConfig]; + if (!string.IsNullOrEmpty(enableCpuMonitorString)) + { + + if (!bool.TryParse(enableCpuMonitorString, out ClientSideRequestStatistics.enableCpuMonitorFlag)) + { + ClientSideRequestStatistics.enableCpuMonitorFlag = true; + } + } +#endif + + if (ClientSideRequestStatistics.enableCpuMonitorFlag) + { + // Have a history up to 1 minute with recording every 10 seconds + ClientSideRequestStatistics.systemRecorder = new SystemUsageRecorder( + identifier: nameof(ClientSideRequestStatistics), + historyLength: 6, + refreshInterval: ClientSideRequestStatistics.SystemUsageRecordInterval); + + ClientSideRequestStatistics.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(new List() + { + ClientSideRequestStatistics.systemRecorder, + }); + } + } + + + public ClientSideRequestStatistics() + { + this.requestStartTime = DateTime.UtcNow; + this.requestEndTime = null; + this.responseStatisticsList = new List(); + this.supplementalResponseStatisticsList = new List(); + this.addressResolutionStatistics = new Dictionary(); + this.ContactedReplicas = new List(); + this.FailedReplicas = new HashSet(); + this.RegionsContacted = new HashSet<(string, Uri)>(); + this.httpResponseStatisticsList = new Lazy>(); + } + + public List ContactedReplicas { get; set; } + + public HashSet FailedReplicas { get; private set; } + + public HashSet<(string, Uri)> RegionsContacted { get; private set; } + + + public TimeSpan? RequestLatency + { + get + { + if (!requestEndTime.HasValue) + { + return null; + } + + return requestEndTime.Value - requestStartTime; + } + } + + public bool? IsCpuHigh + { + get + { + return this.systemUsageHistory?.IsCpuHigh; + } + } + + public bool? IsCpuThreadStarvation + { + get + { + return this.systemUsageHistory?.IsCpuThreadStarvation; + } + } + + internal static void DisableCpuMonitor() + { + // CPU monitor is already disabled + if (!ClientSideRequestStatistics.enableCpuMonitorFlag) + { + return; + } + + ClientSideRequestStatistics.enableCpuMonitorFlag = false; + if (ClientSideRequestStatistics.systemRecorder != null) + { + ClientSideRequestStatistics.systemUsageMonitor.Stop(); + ClientSideRequestStatistics.systemUsageMonitor.Dispose(); + } + } + + public void RecordRequest(DocumentServiceRequest request) + { + } + + public void RecordResponse( + DocumentServiceRequest request, + StoreResult storeResult, + DateTime startTimeUtc, + DateTime endTimeUtc) + { + this.UpdateRequestEndTime(endTimeUtc); + + StoreResponseStatistics responseStatistics; + responseStatistics.RequestStartTime = startTimeUtc; + responseStatistics.RequestResponseTime = endTimeUtc; + responseStatistics.StoreResult = storeResult; + responseStatistics.RequestOperationType = request.OperationType; + responseStatistics.RequestResourceType = request.ResourceType; + + Uri locationEndpoint = request.RequestContext.LocationEndpointToRoute; + string regionName = request.RequestContext.RegionName ?? string.Empty; + + lock (this.lockObject) + { + if (locationEndpoint != null) + { + this.RegionsContacted.Add((regionName, locationEndpoint)); + } + + if (responseStatistics.RequestOperationType == OperationType.Head || responseStatistics.RequestOperationType == OperationType.HeadFeed) + { + this.supplementalResponseStatisticsList.Add(responseStatistics); + } + else + { + this.responseStatisticsList.Add(responseStatistics); + } + } + } + + public void RecordException( + DocumentServiceRequest request, + Exception exception, + DateTime startTime, + DateTime endTimeUtc) + { + this.UpdateRequestEndTime(endTimeUtc); + } + + public string RecordAddressResolutionStart(Uri targetEndpoint) + { + string identifier = Guid.NewGuid().ToString(); + AddressResolutionStatistics resolutionStats = new AddressResolutionStatistics + { + StartTime = DateTime.UtcNow, + EndTime = DateTime.MaxValue, + TargetEndpoint = targetEndpoint == null ? "" : targetEndpoint.ToString() + }; + + lock (this.lockObject) + { + this.addressResolutionStatistics.Add(identifier, resolutionStats); + } + + return identifier; + } + + public void RecordAddressResolutionEnd(string identifier) + { + if (string.IsNullOrEmpty(identifier)) + { + return; + } + + DateTime responseTime = DateTime.UtcNow; + this.UpdateRequestEndTime(DateTime.UtcNow); + lock (this.lockObject) + { + if (!this.addressResolutionStatistics.ContainsKey(identifier)) + { + throw new ArgumentException("Identifier {0} does not exist. Please call start before calling end.", identifier); + } + + this.addressResolutionStatistics[identifier].EndTime = responseTime; + } + } + + public void RecordHttpResponse(HttpRequestMessage request, + HttpResponseMessage response, + ResourceType resourceType, + DateTime requestStartTimeUtc) + { + DateTime requestEndTimeUtc = DateTime.UtcNow; + this.UpdateRequestEndTime(requestEndTimeUtc); + lock (this.httpResponseStatisticsList) + { + this.httpResponseStatisticsList.Value.Add(new HttpResponseStatistics(requestStartTimeUtc, + requestEndTimeUtc, + request.RequestUri, + request.Method, + resourceType, + response, + exception: null)); + } + } + + public void RecordHttpException(HttpRequestMessage request, + Exception exception, + ResourceType resourceType, + DateTime requestStartTimeUtc) + { + DateTime requestEndTimeUtc = DateTime.UtcNow; + this.UpdateRequestEndTime(requestEndTimeUtc); + lock (this.httpResponseStatisticsList) + { + this.httpResponseStatisticsList.Value.Add(new HttpResponseStatistics(requestStartTimeUtc, + requestEndTimeUtc, + request.RequestUri, + request.Method, + resourceType, + responseMessage: null, + exception: exception)); + } + } + + private void UpdateRequestEndTime(DateTime requestEndTimeUtc) + { + lock (this.requestEndTimeLock) + { + if (!this.requestEndTime.HasValue || requestEndTimeUtc > this.requestEndTime) + { + this.UpdateSystemUsageHistory(); + this.requestEndTime = requestEndTimeUtc; + } + } + } + + private void UpdateSystemUsageHistory() + { + // Only update the CPU history if it more than 10 seconds has passed since it was originally collected + if (ClientSideRequestStatistics.enableCpuMonitorFlag && + ClientSideRequestStatistics.systemRecorder != null && + (this.systemUsageHistory == null || this.systemUsageHistory.LastTimestamp + ClientSideRequestStatistics.SystemUsageRecordInterval < DateTime.UtcNow)) + { + try + { + this.systemUsageHistory = ClientSideRequestStatistics.systemRecorder.Data; + } + catch (Exception ex) + { + DefaultTrace.TraceCritical( + "System usage monitor failed with an unexpected exception: {0}", + ex); + } + } + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + this.AppendToBuilder(sb); + return sb.ToString(); + } + + public void AppendToBuilder(StringBuilder stringBuilder) + { + if (stringBuilder == null) + { + throw new ArgumentNullException(nameof(stringBuilder)); + } + + //need to lock in case of concurrent operations. this should be extremely rare since ToString() + //should only be called at the end of request. + lock (this.lockObject) + { + stringBuilder.AppendLine(); + + string endtime; + if (this.requestEndTime.HasValue) + { + endtime = this.requestEndTime.Value.ToString("o", CultureInfo.InvariantCulture); + } + else + { + endtime = $"No response recorded; Current Time: {DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}"; + } + + //first trace request start time, as well as total non-head/headfeed requests made. + stringBuilder.AppendFormat( + CultureInfo.InvariantCulture, + "RequestStartTime: {0}, RequestEndTime: {1}, Number of regions attempted:{2}", + this.requestStartTime.ToString("o", CultureInfo.InvariantCulture), + endtime, + this.RegionsContacted.Count == 0 ? 1 : this.RegionsContacted.Count); + stringBuilder.AppendLine(); + + // This is needed for scenarios where the request was not sent + // so there is no response which triggers saving the system usage + if(this.systemUsageHistory == null) + { + this.UpdateSystemUsageHistory(); + } + + if (this.systemUsageHistory != null && + this.systemUsageHistory.Values.Count > 0) + { + this.systemUsageHistory.AppendJsonString(stringBuilder); + stringBuilder.AppendLine(); + } + else + { + stringBuilder.AppendLine("System history not available."); + } + + //take all responses here - this should be limited in number and each one contains relevant information. + foreach (StoreResponseStatistics item in this.responseStatisticsList) + { + item.AppendToBuilder(stringBuilder); + stringBuilder.AppendLine(); + } + + //take all responses here - this should be limited in number and each one is important. + foreach (AddressResolutionStatistics item in this.addressResolutionStatistics.Values) + { + item.AppendToBuilder(stringBuilder); + stringBuilder.AppendLine(); + } + + //take all responses here - this should be limited in number and each one is important. + lock (this.httpResponseStatisticsList) + { + if (this.httpResponseStatisticsList.IsValueCreated) + { + foreach (HttpResponseStatistics item in this.httpResponseStatisticsList.Value) + { + item.AppendToBuilder(stringBuilder); + stringBuilder.AppendLine(); + } + } + } + + //only take last 10 responses from this list - this has potential of having large number of entries. + //since this is for establishing consistency, we can make do with the last responses to paint a meaningful picture. + int supplementalResponseStatisticsListCount = this.supplementalResponseStatisticsList.Count; + int initialIndex = Math.Max(supplementalResponseStatisticsListCount - ClientSideRequestStatistics.MaxSupplementalRequestsForToString, 0); + + if (initialIndex != 0) + { + stringBuilder.AppendFormat( + CultureInfo.InvariantCulture, + " -- Displaying only the last {0} head/headfeed requests. Total head/headfeed requests: {1}", + ClientSideRequestStatistics.MaxSupplementalRequestsForToString, + supplementalResponseStatisticsListCount); + stringBuilder.AppendLine(); + } + + for (int i = initialIndex; i < supplementalResponseStatisticsListCount; i++) + { + this.supplementalResponseStatisticsList[i].AppendToBuilder(stringBuilder); + stringBuilder.AppendLine(); + } + } + } + + public struct StoreResponseStatistics + { + public DateTime RequestStartTime; + public DateTime RequestResponseTime; + public StoreResult StoreResult; + public ResourceType RequestResourceType; + public OperationType RequestOperationType; + + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + this.AppendToBuilder(stringBuilder); + return stringBuilder.ToString(); + } + + public void AppendToBuilder(StringBuilder stringBuilder) + { + if (stringBuilder == null) + { + throw new ArgumentNullException(nameof(stringBuilder)); + } + + stringBuilder.Append("RequestStart: "); + stringBuilder.Append(this.RequestStartTime.ToString("o", CultureInfo.InvariantCulture)); + stringBuilder.Append("; ResponseTime: "); + stringBuilder.Append(this.RequestResponseTime.ToString("o", CultureInfo.InvariantCulture)); + + stringBuilder.Append("; StoreResult: "); + this.StoreResult?.AppendToBuilder(stringBuilder); + + stringBuilder.AppendLine(); + stringBuilder.AppendFormat( + CultureInfo.InvariantCulture, + " ResourceType: {0}, OperationType: {1}", + this.RequestResourceType, + this.RequestOperationType); + } + } + + + private class AddressResolutionStatistics + { + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public string TargetEndpoint { get; set; } + + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + this.AppendToBuilder(stringBuilder); + return stringBuilder.ToString(); + } + + public void AppendToBuilder(StringBuilder stringBuilder) + { + if (stringBuilder == null) + { + throw new ArgumentNullException(nameof(stringBuilder)); + } + + stringBuilder + .Append($"AddressResolution - StartTime: {this.StartTime.ToString("o", CultureInfo.InvariantCulture)}, ") + .Append($"EndTime: {this.EndTime.ToString("o", CultureInfo.InvariantCulture)}, ") + .Append("TargetEndpoint: ") + .Append(this.TargetEndpoint); + + } + } + + public readonly struct HttpResponseStatistics + { + public HttpResponseStatistics( + DateTime requestStartTime, + DateTime requestEndTime, + Uri requestUri, + HttpMethod httpMethod, + ResourceType resourceType, + HttpResponseMessage responseMessage, + Exception exception) + { + this.RequestStartTime = requestStartTime; + this.Duration = requestEndTime - requestStartTime; + this.HttpResponseMessage = responseMessage; + this.Exception = exception; + this.ResourceType = resourceType; + this.HttpMethod = httpMethod; + this.RequestUri = requestUri; + this.ActivityId = Trace.CorrelationManager.ActivityId.ToString(); + } + + public DateTime RequestStartTime { get; } + public TimeSpan Duration { get; } + public HttpResponseMessage HttpResponseMessage { get; } + public Exception Exception { get; } + public ResourceType ResourceType { get; } + public HttpMethod HttpMethod { get; } + public Uri RequestUri { get; } + public string ActivityId { get; } + + public void AppendToBuilder(StringBuilder stringBuilder) + { + if (stringBuilder == null) + { + throw new ArgumentNullException(nameof(stringBuilder)); + } + + stringBuilder + .Append("HttpResponseStatistics - ") + .Append("RequestStartTime: ") + .Append(this.RequestStartTime.ToString("o", CultureInfo.InvariantCulture)) + .Append(", DurationInMs: ") + .Append(this.Duration.TotalMilliseconds) + .Append(", RequestUri: ") + .Append(this.RequestUri) + .Append(", ResourceType: ") + .Append(this.ResourceType) + .Append(", HttpMethod: ") + .Append(this.HttpMethod); + + if (this.Exception != null) + { + stringBuilder.Append(", ExceptionType: ") + .Append(this.Exception.GetType()) + .Append(", ExceptionMessage: ") + .Append(this.Exception.Message); + } + + if (this.HttpResponseMessage != null) + { + stringBuilder.Append(", StatusCode: ") + .Append(this.HttpResponseMessage.StatusCode); + if (!this.HttpResponseMessage.IsSuccessStatusCode) + { + stringBuilder.Append(", ReasonPhrase: ") + .Append(this.HttpResponseMessage.ReasonPhrase); + } + } + } + } + } +} + diff --git a/Microsoft.Azure.Cosmos/src/direct/CloneableStream.cs b/Microsoft.Azure.Cosmos/src/direct/CloneableStream.cs index 426c7cc6fa..02d6867cf3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CloneableStream.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CloneableStream.cs @@ -1,279 +1,279 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.IO; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal sealed class CloneableStream : Stream, ICloneable - { - private readonly MemoryStream internalStream; - private readonly bool allowUnsafeDataAccess; - - public CloneableStream Clone() - { - return new CloneableStream(this.CloneStream(), this.allowUnsafeDataAccess); - } - - object ICloneable.Clone() - { - return new CloneableStream(this.CloneStream(), this.allowUnsafeDataAccess); - } - - private MemoryStream CloneStream() - { - if (this.internalStream is ICloneable cloneableStream) - { - MemoryStream memoryStream = (MemoryStream)cloneableStream.Clone(); - memoryStream.Position = 0; - return memoryStream; - } - - if (!this.allowUnsafeDataAccess) - { - throw new NotSupportedException($"Cloning the stream is not a supported method when {nameof(this.allowUnsafeDataAccess)} is set to false and stream does not implement ICloneable"); - } - - return new MemoryStream(buffer: this.internalStream.GetBuffer(), index: 0, count: (int)this.internalStream.Length, writable: false, publiclyVisible: true); - } - - public CloneableStream(MemoryStream internalStream, bool allowUnsafeDataAccess = true) - { - this.internalStream = CloneableStream.ConvertToExportableMemoryStream(internalStream); - this.allowUnsafeDataAccess = allowUnsafeDataAccess; - } - - public override bool CanRead - { - get - { - return this.internalStream.CanRead; - } - } - - public override bool CanSeek - { - get - { - return this.internalStream.CanSeek; - } - } - - public override bool CanTimeout - { - get - { - return this.internalStream.CanTimeout; - } - } - - public override bool CanWrite - { - get - { - return this.internalStream.CanWrite; - } - } - - public override long Length - { - get - { - return this.internalStream.Length; - } - } - - public override long Position - { - get - { - return this.internalStream.Position; - } - set - { - this.internalStream.Position = value; - } - } - - public override int ReadTimeout - { - get - { - return this.internalStream.ReadTimeout; - } - set - { - this.internalStream.ReadTimeout = value; - } - } - - public override int WriteTimeout - { - get - { - return this.internalStream.WriteTimeout; - } - set - { - this.internalStream.WriteTimeout = value; - } - } - - public ArraySegment GetBuffer() - { - if (!this.allowUnsafeDataAccess) - { - throw new NotSupportedException($"{nameof(GetBuffer)} is not a supported method when {nameof(this.allowUnsafeDataAccess)} is set to false"); - } - - return new ArraySegment(this.internalStream.GetBuffer(), 0, (int)this.internalStream.Length); - } - -#if !NETSTANDARD16 - public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) - { - return this.internalStream.BeginRead(buffer, offset, count, callback, state); - } - - public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) - { - return this.internalStream.BeginWrite(buffer, offset, count, callback, state); - } - - public override void Close() - { - this.internalStream.Close(); - } - - public override int EndRead(IAsyncResult asyncResult) - { - return this.internalStream.EndRead(asyncResult); - } - - public override void EndWrite(IAsyncResult asyncResult) - { - this.internalStream.EndWrite(asyncResult); - } -#endif - - public override void Flush() - { - this.internalStream.Flush(); - } - - public override Task FlushAsync(CancellationToken cancellationToken) - { - return this.internalStream.FlushAsync(cancellationToken); - } - - public override int Read(byte[] buffer, int offset, int count) - { - return this.internalStream.Read(buffer, offset, count); - } - - public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return this.internalStream.ReadAsync(buffer, offset, count, cancellationToken); - } - - public override int ReadByte() - { - return this.internalStream.ReadByte(); - } - - public override long Seek(long offset, SeekOrigin loc) - { - return this.internalStream.Seek(offset, loc); - } - - public override void SetLength(long value) - { - this.internalStream.SetLength(value); - } - - public override void Write(byte[] buffer, int offset, int count) - { - this.internalStream.Write(buffer, offset, count); - } - - public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - return this.internalStream.WriteAsync(buffer, offset, count, cancellationToken); - } - - public override void WriteByte(byte value) - { - this.internalStream.WriteByte(value); - } - - protected override void Dispose(bool disposing) - { - this.internalStream.Dispose(); - - base.Dispose(disposing); - } - - public void WriteTo(Stream target) - { - this.internalStream.WriteTo(target); - } - - public void CopyBufferTo(byte[] buffer, int offset) - { - if (!this.allowUnsafeDataAccess) - { - this.internalStream.Write(buffer, offset, (int)this.internalStream.Length); - } - else - { - ArraySegment internalStreamBuffer = this.GetBuffer(); - Array.Copy( - internalStreamBuffer.Array, - internalStreamBuffer.Offset, - buffer, - offset, - internalStreamBuffer.Count); - } - } - - public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) - { - return this.internalStream.CopyToAsync(destination, bufferSize, cancellationToken); - } - -#if NETFX45 || NETSTANDARD15 || NETSTANDARD16 - private static MemoryStream ConvertToExportableMemoryStream(MemoryStream mediaStream) - { - // This code path does not change now so we can assume that we always get exportable MemoryStream from existing clients - return mediaStream; - } -#else - private static MemoryStream ConvertToExportableMemoryStream(MemoryStream mediaStream) - { - if (mediaStream != null) - { - if (!(mediaStream is ICloneable || mediaStream.TryGetBuffer(out _))) - { - MemoryStream exportableMemoryStream; - int length = (int)mediaStream.Length; - long mediaStreamPosition = mediaStream.Position; - byte[] buffer = new byte[length]; - mediaStream.Read(buffer, offset: 0, count: length); - exportableMemoryStream = new(buffer, index: 0, count: length, writable: false, publiclyVisible: true); - mediaStream.Position = mediaStreamPosition; - mediaStream = exportableMemoryStream; - - // We could not dispose original stream as the application might still be using it - DefaultTrace.TraceWarning("Change the code to prevent the need for convertion into exportable MemoryStream by using streams with publicly visible buffers"); - } - } - - return mediaStream; - } -#endif - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.IO; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal sealed class CloneableStream : Stream, ICloneable + { + private readonly MemoryStream internalStream; + private readonly bool allowUnsafeDataAccess; + + public CloneableStream Clone() + { + return new CloneableStream(this.CloneStream(), this.allowUnsafeDataAccess); + } + + object ICloneable.Clone() + { + return new CloneableStream(this.CloneStream(), this.allowUnsafeDataAccess); + } + + private MemoryStream CloneStream() + { + if (this.internalStream is ICloneable cloneableStream) + { + MemoryStream memoryStream = (MemoryStream)cloneableStream.Clone(); + memoryStream.Position = 0; + return memoryStream; + } + + if (!this.allowUnsafeDataAccess) + { + throw new NotSupportedException($"Cloning the stream is not a supported method when {nameof(this.allowUnsafeDataAccess)} is set to false and stream does not implement ICloneable"); + } + + return new MemoryStream(buffer: this.internalStream.GetBuffer(), index: 0, count: (int)this.internalStream.Length, writable: false, publiclyVisible: true); + } + + public CloneableStream(MemoryStream internalStream, bool allowUnsafeDataAccess = true) + { + this.internalStream = CloneableStream.ConvertToExportableMemoryStream(internalStream); + this.allowUnsafeDataAccess = allowUnsafeDataAccess; + } + + public override bool CanRead + { + get + { + return this.internalStream.CanRead; + } + } + + public override bool CanSeek + { + get + { + return this.internalStream.CanSeek; + } + } + + public override bool CanTimeout + { + get + { + return this.internalStream.CanTimeout; + } + } + + public override bool CanWrite + { + get + { + return this.internalStream.CanWrite; + } + } + + public override long Length + { + get + { + return this.internalStream.Length; + } + } + + public override long Position + { + get + { + return this.internalStream.Position; + } + set + { + this.internalStream.Position = value; + } + } + + public override int ReadTimeout + { + get + { + return this.internalStream.ReadTimeout; + } + set + { + this.internalStream.ReadTimeout = value; + } + } + + public override int WriteTimeout + { + get + { + return this.internalStream.WriteTimeout; + } + set + { + this.internalStream.WriteTimeout = value; + } + } + + public ArraySegment GetBuffer() + { + if (!this.allowUnsafeDataAccess) + { + throw new NotSupportedException($"{nameof(GetBuffer)} is not a supported method when {nameof(this.allowUnsafeDataAccess)} is set to false"); + } + + return new ArraySegment(this.internalStream.GetBuffer(), 0, (int)this.internalStream.Length); + } + +#if !NETSTANDARD16 + public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) + { + return this.internalStream.BeginRead(buffer, offset, count, callback, state); + } + + public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) + { + return this.internalStream.BeginWrite(buffer, offset, count, callback, state); + } + + public override void Close() + { + this.internalStream.Close(); + } + + public override int EndRead(IAsyncResult asyncResult) + { + return this.internalStream.EndRead(asyncResult); + } + + public override void EndWrite(IAsyncResult asyncResult) + { + this.internalStream.EndWrite(asyncResult); + } +#endif + + public override void Flush() + { + this.internalStream.Flush(); + } + + public override Task FlushAsync(CancellationToken cancellationToken) + { + return this.internalStream.FlushAsync(cancellationToken); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return this.internalStream.Read(buffer, offset, count); + } + + public override Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return this.internalStream.ReadAsync(buffer, offset, count, cancellationToken); + } + + public override int ReadByte() + { + return this.internalStream.ReadByte(); + } + + public override long Seek(long offset, SeekOrigin loc) + { + return this.internalStream.Seek(offset, loc); + } + + public override void SetLength(long value) + { + this.internalStream.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + this.internalStream.Write(buffer, offset, count); + } + + public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + return this.internalStream.WriteAsync(buffer, offset, count, cancellationToken); + } + + public override void WriteByte(byte value) + { + this.internalStream.WriteByte(value); + } + + protected override void Dispose(bool disposing) + { + this.internalStream.Dispose(); + + base.Dispose(disposing); + } + + public void WriteTo(Stream target) + { + this.internalStream.WriteTo(target); + } + + public void CopyBufferTo(byte[] buffer, int offset) + { + if (!this.allowUnsafeDataAccess) + { + this.internalStream.Write(buffer, offset, (int)this.internalStream.Length); + } + else + { + ArraySegment internalStreamBuffer = this.GetBuffer(); + Array.Copy( + internalStreamBuffer.Array, + internalStreamBuffer.Offset, + buffer, + offset, + internalStreamBuffer.Count); + } + } + + public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) + { + return this.internalStream.CopyToAsync(destination, bufferSize, cancellationToken); + } + +#if NETFX45 || NETSTANDARD15 || NETSTANDARD16 + private static MemoryStream ConvertToExportableMemoryStream(MemoryStream mediaStream) + { + // This code path does not change now so we can assume that we always get exportable MemoryStream from existing clients + return mediaStream; + } +#else + private static MemoryStream ConvertToExportableMemoryStream(MemoryStream mediaStream) + { + if (mediaStream != null) + { + if (!(mediaStream is ICloneable || mediaStream.TryGetBuffer(out _))) + { + MemoryStream exportableMemoryStream; + int length = (int)mediaStream.Length; + long mediaStreamPosition = mediaStream.Position; + byte[] buffer = new byte[length]; + mediaStream.Read(buffer, offset: 0, count: length); + exportableMemoryStream = new(buffer, index: 0, count: length, writable: false, publiclyVisible: true); + mediaStream.Position = mediaStreamPosition; + mediaStream = exportableMemoryStream; + + // We could not dispose original stream as the application might still be using it + DefaultTrace.TraceWarning("Change the code to prevent the need for convertion into exportable MemoryStream by using streams with publicly visible buffers"); + } + } + + return mediaStream; + } +#endif + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/CollectionBackupPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/CollectionBackupPolicy.cs index b6435b36ad..4f7d2a0240 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CollectionBackupPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CollectionBackupPolicy.cs @@ -1,64 +1,64 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Represents the collection backup policy for a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class CollectionBackupPolicy : JsonSerializable, ICloneable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - /// - /// CollectionBackupType is set to Invalid. - /// - public CollectionBackupPolicy() - { - this.CollectionBackupType = CollectionBackupType.Invalid; - } - - /// - /// Gets or sets the CollectionBackupType (Invalid or Continuous) in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.CollectionBackupType)] - //[JsonConverter(typeof(StringEnumConverter))] - public CollectionBackupType CollectionBackupType - { - get - { - int result = base.GetValue(Constants.Properties.CollectionBackupType); - return (CollectionBackupType)result; - } - set - { - base.SetValue(Constants.Properties.CollectionBackupType, (int)value); - } - } - - /// - /// Performs a deep copy of the collection backup policy. - /// - /// - /// A clone of the collection backup policy. - /// - public object Clone() - { - CollectionBackupPolicy cloned = new CollectionBackupPolicy() - { - CollectionBackupType = this.CollectionBackupType, - }; - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Represents the collection backup policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class CollectionBackupPolicy : JsonSerializable, ICloneable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// + /// CollectionBackupType is set to Invalid. + /// + public CollectionBackupPolicy() + { + this.CollectionBackupType = CollectionBackupType.Invalid; + } + + /// + /// Gets or sets the CollectionBackupType (Invalid or Continuous) in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.CollectionBackupType)] + //[JsonConverter(typeof(StringEnumConverter))] + public CollectionBackupType CollectionBackupType + { + get + { + int result = base.GetValue(Constants.Properties.CollectionBackupType); + return (CollectionBackupType)result; + } + set + { + base.SetValue(Constants.Properties.CollectionBackupType, (int)value); + } + } + + /// + /// Performs a deep copy of the collection backup policy. + /// + /// + /// A clone of the collection backup policy. + /// + public object Clone() + { + CollectionBackupPolicy cloned = new CollectionBackupPolicy() + { + CollectionBackupType = this.CollectionBackupType, + }; + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/CollectionBackupType.cs b/Microsoft.Azure.Cosmos/src/direct/CollectionBackupType.cs index 97af52c291..e7451db14d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CollectionBackupType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CollectionBackupType.cs @@ -1,29 +1,29 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported collection backup type in the Azure Cosmos DB service. - /// - internal enum CollectionBackupType - { - /// - /// CollectionBackupType is defiined with a create collection operation. - /// - /// - /// With Invalid CollectionBackupType, we will reject the logstore collection creation. - /// - /// The default CollectionBackupType is Invalid. - /// - Invalid, - - /// - /// CollectionBackupType is defiined with a create collection operation. - /// - /// - /// With Continuous CollectionBackupType, we will allow LogStore collection creation if valid retention value is set. - /// - Continuous - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported collection backup type in the Azure Cosmos DB service. + /// + internal enum CollectionBackupType + { + /// + /// CollectionBackupType is defined with a create collection operation. + /// + /// + /// With Invalid CollectionBackupType, we will reject the logstore collection creation. + /// + /// The default CollectionBackupType is Invalid. + /// + Invalid, + + /// + /// CollectionBackupType is defiined with a create collection operation. + /// + /// + /// With Continuous CollectionBackupType, we will allow LogStore collection creation if valid retention value is set. + /// + Continuous + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/CompositePath.cs b/Microsoft.Azure.Cosmos/src/direct/CompositePath.cs index 2751a5c5dd..de6e7eda08 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CompositePath.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CompositePath.cs @@ -1,114 +1,114 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Documents -{ - using System; - using System.Runtime.Serialization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Defines the target data type of an index path specification in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum CompositePathSortOrder - { - /// - /// Ascending sort order for composite paths. - /// - [EnumMember(Value = "ascending")] - Ascending, - - /// - /// Descending sort order for composite paths. - /// - [EnumMember(Value = "descending")] - Descending - } - - /// - /// DOM for a composite path. - /// A composite path is used in a composite index. - /// For example if you want to run a query like "SELECT * FROM c ORDER BY c.age, c.height", - /// then you need to add "/age" and "/height" as composite paths to your composite index. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class CompositePath : JsonSerializable, ICloneable - { - /// - /// Gets or sets the full path in a document used for composite indexing. - /// We do not support wildcards in the path. - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get - { - return this.GetValue(Constants.Properties.Path); - } - - set - { - this.SetValue(Constants.Properties.Path, value); - } - } - - /// - /// Gets or sets the sort order for the composite path. - /// For example if you want to run the query "SELECT * FROM c ORDER BY c.age asc, c.height desc", - /// then you need to make the order for "/age" "ascending" and the order for "/height" "descending". - /// - [JsonProperty(PropertyName = Constants.Properties.Order)] - [JsonConverter(typeof(StringEnumConverter))] - public CompositePathSortOrder Order - { - get - { - CompositePathSortOrder result = default(CompositePathSortOrder); - string sortOrder = this.GetValue(Constants.Properties.Order); - if (!string.IsNullOrEmpty(sortOrder)) - { - result = (CompositePathSortOrder)Enum.Parse(typeof(CompositePathSortOrder), sortOrder, true); - } - - return result; - } - - set - { - this.SetValue(Constants.Properties.Order, value); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Path); - Helpers.ValidateEnumProperties(this.Order); - } - - /// - /// Clones the composite path. - /// - /// The cloned composite path. - public object Clone() - { - return new CompositePath() - { - Path = this.Path, - Order = this.Order, - }; - } - } +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Documents +{ + using System; + using System.Runtime.Serialization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Defines the target data type of an index path specification in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum CompositePathSortOrder + { + /// + /// Ascending sort order for composite paths. + /// + [EnumMember(Value = "ascending")] + Ascending, + + /// + /// Descending sort order for composite paths. + /// + [EnumMember(Value = "descending")] + Descending + } + + /// + /// DOM for a composite path. + /// A composite path is used in a composite index. + /// For example if you want to run a query like "SELECT * FROM c ORDER BY c.age, c.height", + /// then you need to add "/age" and "/height" as composite paths to your composite index. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class CompositePath : JsonSerializable, ICloneable + { + /// + /// Gets or sets the full path in a document used for composite indexing. + /// We do not support wildcards in the path. + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get + { + return this.GetValue(Constants.Properties.Path); + } + + set + { + this.SetValue(Constants.Properties.Path, value); + } + } + + /// + /// Gets or sets the sort order for the composite path. + /// For example if you want to run the query "SELECT * FROM c ORDER BY c.age asc, c.height desc", + /// then you need to make the order for "/age" "ascending" and the order for "/height" "descending". + /// + [JsonProperty(PropertyName = Constants.Properties.Order)] + [JsonConverter(typeof(StringEnumConverter))] + public CompositePathSortOrder Order + { + get + { + CompositePathSortOrder result = default(CompositePathSortOrder); + string sortOrder = this.GetValue(Constants.Properties.Order); + if (!string.IsNullOrEmpty(sortOrder)) + { + result = (CompositePathSortOrder)Enum.Parse(typeof(CompositePathSortOrder), sortOrder, true); + } + + return result; + } + + set + { + this.SetValue(Constants.Properties.Order, value); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Path); + Helpers.ValidateEnumProperties(this.Order); + } + + /// + /// Clones the composite path. + /// + /// The cloned composite path. + public object Clone() + { + return new CompositePath() + { + Path = this.Path, + Order = this.Order, + }; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs b/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs index 06ca5c0454..56bb137a0a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs @@ -1,85 +1,85 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using System; - using System.Collections.Generic; - - /// - /// Represents computed property that belongs to a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class ComputedProperty : JsonSerializable, ICloneable - { - /// - /// Gets or sets the name of the computed property. - /// - /// - /// The name of the computed property. - /// - /// - /// Name of the computed property should be chosen such that it does not collide with any existing or future document properties. - /// - [JsonProperty(PropertyName = Constants.Properties.Name)] - public string Name - { - get - { - return base.GetValue(Constants.Properties.Name); - } - set - { - base.SetValue(Constants.Properties.Name, value); - } - } - - /// - /// Gets or sets the query for the computed property. - /// - /// - /// The query used to evaluate the value for the computed property. - /// - /// - /// For example: - /// SELECT VALUE LOWER(c.firstName) FROM c - /// - [JsonProperty(PropertyName = Constants.Properties.Query)] - public string Query - { - get - { - return base.GetValue(Constants.Properties.Query); - } - set - { - base.SetValue(Constants.Properties.Query, value); - } - } - - /// - internal override void Validate() - { - // See IncludedPath.cs implementation - base.Validate(); - base.GetValue(Constants.Properties.Name); - base.GetValue(Constants.Properties.Query); - } - - /// - /// Clones a ComputedProperty object - /// - /// - public object Clone() - { - return new ComputedProperty - { - Name = this.Name, - Query = this.Query - }; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using System; + using System.Collections.Generic; + + /// + /// Represents computed property that belongs to a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class ComputedProperty : JsonSerializable, ICloneable + { + /// + /// Gets or sets the name of the computed property. + /// + /// + /// The name of the computed property. + /// + /// + /// Name of the computed property should be chosen such that it does not collide with any existing or future document properties. + /// + [JsonProperty(PropertyName = Constants.Properties.Name)] + public string Name + { + get + { + return base.GetValue(Constants.Properties.Name); + } + set + { + base.SetValue(Constants.Properties.Name, value); + } + } + + /// + /// Gets or sets the query for the computed property. + /// + /// + /// The query used to evaluate the value for the computed property. + /// + /// + /// For example: + /// SELECT VALUE LOWER(c.firstName) FROM c + /// + [JsonProperty(PropertyName = Constants.Properties.Query)] + public string Query + { + get + { + return base.GetValue(Constants.Properties.Query); + } + set + { + base.SetValue(Constants.Properties.Query, value); + } + } + + /// + internal override void Validate() + { + // See IncludedPath.cs implementation + base.Validate(); + base.GetValue(Constants.Properties.Name); + base.GetValue(Constants.Properties.Query); + } + + /// + /// Clones a ComputedProperty object + /// + /// + public object Clone() + { + return new ComputedProperty + { + Name = this.Name, + Query = this.Query + }; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConcurrentPrng.cs b/Microsoft.Azure.Cosmos/src/direct/ConcurrentPrng.cs index 8e2adca738..1fe4e29f4e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConcurrentPrng.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConcurrentPrng.cs @@ -1,22 +1,22 @@ -namespace Microsoft.Azure.Documents -{ - using System; - - // The class is thread safe. - internal sealed class ConcurrentPrng - { - private readonly object mutex = new object(); - private readonly Random rng = new Random(); - - // Returns a non-negative random integer that is less than the specified - // maximum. - // The function has the same semantics as System.Random.Next(int). - public int Next(int maxValue) - { - lock (this.mutex) - { - return this.rng.Next(maxValue); - } - } - } +namespace Microsoft.Azure.Documents +{ + using System; + + // The class is thread safe. + internal sealed class ConcurrentPrng + { + private readonly object mutex = new object(); + private readonly Random rng = new Random(); + + // Returns a non-negative random integer that is less than the specified + // maximum. + // The function has the same semantics as System.Random.Next(int). + public int Next(int maxValue) + { + lock (this.mutex) + { + return this.rng.Next(maxValue); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Conflict.cs b/Microsoft.Azure.Cosmos/src/direct/Conflict.cs index 81c7abca8b..8dac9f32ca 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Conflict.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Conflict.cs @@ -1,239 +1,239 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.IO; - using System.Text; - - /// - /// This is the conflicting resource resulting from a concurrent async operation in the Azure Cosmos DB service. - /// - /// - /// On rare occasions, during an async operation (insert, replace and delete), a version conflict may occur on a resource. - /// The conflicting resource is persisted as a Conflict resource. - /// Inspecting Conflict resources will allow you to determine which operations and resources resulted in conflicts. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Conflict : Resource - { - /// - /// Initialize a new instance of a Conflict class in the Azure Cosmos DB service. - /// - public Conflict() - { - } - - /// - /// Gets the resource ID for the conflict in the Azure Cosmos DB service. - /// - public string SourceResourceId - { - get - { - return base.GetValue(Constants.Properties.SourceResourceId); - } - - internal set - { - base.SetValue(Constants.Properties.SourceResourceId, value); - } - } - - internal long ConflictLSN - { - get - { - return base.GetValue(Constants.Properties.ConflictLSN); - } - - set - { - base.SetValue(Constants.Properties.ConflictLSN, value); - } - } - - /// - /// Gets the conflicting resource in the Azure Cosmos DB service. - /// - /// The returned type of conflicting resource. - /// The conflicting resource. - public T GetResource() where T : Resource, new() - { - if (typeof(T) != this.ResourceType) - { - throw new ArgumentException( - string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceType, typeof(T).Name, this.ResourceType.Name)); - } - - string content = base.GetValue(Constants.Properties.Content); - if (!string.IsNullOrEmpty(content)) - { - using (MemoryStream stream = new MemoryStream()) - { - using (StreamWriter writer = new StreamWriter(stream)) - { - writer.Write(content); - writer.Flush(); - stream.Position = 0; - return JsonSerializable.LoadFrom(stream); - } - } - } - - return null; - } - - internal void SetResource(T baseResource) where T : Resource, new() - { - if (typeof(T) != this.ResourceType) - { - throw new ArgumentException( - string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceType, typeof(T).Name, this.ResourceType.Name)); - } - - StringBuilder sb = new StringBuilder(); - baseResource.SaveTo(sb); - string content = sb.ToString(); - if (!string.IsNullOrEmpty(content)) - { - this.SetValue(Constants.Properties.Content, content); - } - - this.Id = baseResource.Id; - this.ResourceId = baseResource.ResourceId; - } - - /// - /// Gets the operation that resulted in the conflict in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - public OperationKind OperationKind - { - get - { - string operationKind = base.GetValue(Constants.Properties.OperationType); - - if (string.Equals(Constants.Properties.OperationKindCreate, operationKind, StringComparison.OrdinalIgnoreCase)) - { - return OperationKind.Create; - } - else if (string.Equals(Constants.Properties.OperationKindReplace, operationKind, StringComparison.OrdinalIgnoreCase) || - string.Equals(Constants.Properties.OperationKindPatch, operationKind, StringComparison.OrdinalIgnoreCase)) - { - return OperationKind.Replace; - } - else if (string.Equals(Constants.Properties.OperationKindDelete, operationKind, StringComparison.OrdinalIgnoreCase)) - { - return OperationKind.Delete; - } - else - { - return OperationKind.Invalid; - } - } - - internal set - { - string operationKind = ""; - if (value == OperationKind.Create) - { - operationKind = Constants.Properties.OperationKindCreate; - } - else if (value == OperationKind.Replace) - { - operationKind = Constants.Properties.OperationKindReplace; - } - else if (value == OperationKind.Delete) - { - operationKind = Constants.Properties.OperationKindDelete; - } - else - { - throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, "Unsupported operation kind {0}", value.ToString())); - } - - base.SetValue(Constants.Properties.OperationType, operationKind); - } - } - - /// - /// Gets the type of the conflicting resource in the Azure Cosmos DB service. - /// - /// - /// The type of the resource. - /// - public Type ResourceType - { - get - { - string resourceType = base.GetValue(Constants.Properties.ResourceType); - - if (string.Equals(Constants.Properties.ResourceTypeDocument, resourceType, StringComparison.OrdinalIgnoreCase)) - { - return typeof(Document); - } - else if (string.Equals(Constants.Properties.ResourceTypeStoredProcedure, resourceType, StringComparison.OrdinalIgnoreCase)) - { - return typeof(StoredProcedure); - } - else if (string.Equals(Constants.Properties.ResourceTypeTrigger, resourceType, StringComparison.OrdinalIgnoreCase)) - { - return typeof(Trigger); - } - else if (string.Equals(Constants.Properties.ResourceTypeUserDefinedFunction, resourceType, StringComparison.OrdinalIgnoreCase)) - { - return typeof(UserDefinedFunction); - } - else if (string.Equals(Constants.Properties.ResourceTypeAttachment, resourceType, StringComparison.OrdinalIgnoreCase)) - { - return typeof(Attachment); - } - else - { - return null; - } - } - - internal set - { - string resourceType = null; - if (value == typeof(Document)) - { - resourceType = Constants.Properties.ResourceTypeDocument; - } - else if (value == typeof(StoredProcedure)) - { - resourceType = Constants.Properties.ResourceTypeStoredProcedure; - } - else if (value == typeof(Trigger)) - { - resourceType = Constants.Properties.ResourceTypeTrigger; - } - else if (value == typeof(UserDefinedFunction)) - { - resourceType = Constants.Properties.ResourceTypeUserDefinedFunction; - } - else if (value == typeof(Attachment)) - { - resourceType = Constants.Properties.ResourceTypeAttachment; - } - else - { - throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, "Unsupported resource type {0}", value.ToString())); - } - - base.SetValue(Constants.Properties.ResourceType, resourceType); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.IO; + using System.Text; + + /// + /// This is the conflicting resource resulting from a concurrent async operation in the Azure Cosmos DB service. + /// + /// + /// On rare occasions, during an async operation (insert, replace and delete), a version conflict may occur on a resource. + /// The conflicting resource is persisted as a Conflict resource. + /// Inspecting Conflict resources will allow you to determine which operations and resources resulted in conflicts. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Conflict : Resource + { + /// + /// Initialize a new instance of a Conflict class in the Azure Cosmos DB service. + /// + public Conflict() + { + } + + /// + /// Gets the resource ID for the conflict in the Azure Cosmos DB service. + /// + public string SourceResourceId + { + get + { + return base.GetValue(Constants.Properties.SourceResourceId); + } + + internal set + { + base.SetValue(Constants.Properties.SourceResourceId, value); + } + } + + internal long ConflictLSN + { + get + { + return base.GetValue(Constants.Properties.ConflictLSN); + } + + set + { + base.SetValue(Constants.Properties.ConflictLSN, value); + } + } + + /// + /// Gets the conflicting resource in the Azure Cosmos DB service. + /// + /// The returned type of conflicting resource. + /// The conflicting resource. + public T GetResource() where T : Resource, new() + { + if (typeof(T) != this.ResourceType) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceType, typeof(T).Name, this.ResourceType.Name)); + } + + string content = base.GetValue(Constants.Properties.Content); + if (!string.IsNullOrEmpty(content)) + { + using (MemoryStream stream = new MemoryStream()) + { + using (StreamWriter writer = new StreamWriter(stream)) + { + writer.Write(content); + writer.Flush(); + stream.Position = 0; + return JsonSerializable.LoadFrom(stream); + } + } + } + + return null; + } + + internal void SetResource(T baseResource) where T : Resource, new() + { + if (typeof(T) != this.ResourceType) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceType, typeof(T).Name, this.ResourceType.Name)); + } + + StringBuilder sb = new StringBuilder(); + baseResource.SaveTo(sb); + string content = sb.ToString(); + if (!string.IsNullOrEmpty(content)) + { + this.SetValue(Constants.Properties.Content, content); + } + + this.Id = baseResource.Id; + this.ResourceId = baseResource.ResourceId; + } + + /// + /// Gets the operation that resulted in the conflict in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + public OperationKind OperationKind + { + get + { + string operationKind = base.GetValue(Constants.Properties.OperationType); + + if (string.Equals(Constants.Properties.OperationKindCreate, operationKind, StringComparison.OrdinalIgnoreCase)) + { + return OperationKind.Create; + } + else if (string.Equals(Constants.Properties.OperationKindReplace, operationKind, StringComparison.OrdinalIgnoreCase) || + string.Equals(Constants.Properties.OperationKindPatch, operationKind, StringComparison.OrdinalIgnoreCase)) + { + return OperationKind.Replace; + } + else if (string.Equals(Constants.Properties.OperationKindDelete, operationKind, StringComparison.OrdinalIgnoreCase)) + { + return OperationKind.Delete; + } + else + { + return OperationKind.Invalid; + } + } + + internal set + { + string operationKind = ""; + if (value == OperationKind.Create) + { + operationKind = Constants.Properties.OperationKindCreate; + } + else if (value == OperationKind.Replace) + { + operationKind = Constants.Properties.OperationKindReplace; + } + else if (value == OperationKind.Delete) + { + operationKind = Constants.Properties.OperationKindDelete; + } + else + { + throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, "Unsupported operation kind {0}", value.ToString())); + } + + base.SetValue(Constants.Properties.OperationType, operationKind); + } + } + + /// + /// Gets the type of the conflicting resource in the Azure Cosmos DB service. + /// + /// + /// The type of the resource. + /// + public Type ResourceType + { + get + { + string resourceType = base.GetValue(Constants.Properties.ResourceType); + + if (string.Equals(Constants.Properties.ResourceTypeDocument, resourceType, StringComparison.OrdinalIgnoreCase)) + { + return typeof(Document); + } + else if (string.Equals(Constants.Properties.ResourceTypeStoredProcedure, resourceType, StringComparison.OrdinalIgnoreCase)) + { + return typeof(StoredProcedure); + } + else if (string.Equals(Constants.Properties.ResourceTypeTrigger, resourceType, StringComparison.OrdinalIgnoreCase)) + { + return typeof(Trigger); + } + else if (string.Equals(Constants.Properties.ResourceTypeUserDefinedFunction, resourceType, StringComparison.OrdinalIgnoreCase)) + { + return typeof(UserDefinedFunction); + } + else if (string.Equals(Constants.Properties.ResourceTypeAttachment, resourceType, StringComparison.OrdinalIgnoreCase)) + { + return typeof(Attachment); + } + else + { + return null; + } + } + + internal set + { + string resourceType = null; + if (value == typeof(Document)) + { + resourceType = Constants.Properties.ResourceTypeDocument; + } + else if (value == typeof(StoredProcedure)) + { + resourceType = Constants.Properties.ResourceTypeStoredProcedure; + } + else if (value == typeof(Trigger)) + { + resourceType = Constants.Properties.ResourceTypeTrigger; + } + else if (value == typeof(UserDefinedFunction)) + { + resourceType = Constants.Properties.ResourceTypeUserDefinedFunction; + } + else if (value == typeof(Attachment)) + { + resourceType = Constants.Properties.ResourceTypeAttachment; + } + else + { + throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, "Unsupported resource type {0}", value.ToString())); + } + + base.SetValue(Constants.Properties.ResourceType, resourceType); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConflictException.cs b/Microsoft.Azure.Cosmos/src/direct/ConflictException.cs index 3e98eb8f5b..9335624805 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConflictException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConflictException.cs @@ -1,81 +1,81 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class ConflictException : DocumentClientException - { - public ConflictException() - : this(RMResources.EntityAlreadyExists) - { - - } - - public ConflictException(string message) - : this(message, (Exception)null, null) - { - - } - - public ConflictException(string message, SubStatusCodes subStatusCode) - : base(message, HttpStatusCode.Conflict, subStatusCode) - { - - } - - public ConflictException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public ConflictException(Exception innerException) - : this(RMResources.EntityAlreadyExists, innerException, null) - { - - } - - public ConflictException(Exception innerException, SubStatusCodes subStatusCode) - : this(RMResources.EntityAlreadyExists, innerException, headers: null, subStatusCode: subStatusCode) - { - } - - public ConflictException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public ConflictException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.Conflict, requestUri) - { - SetDescription(); - } - - public ConflictException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null) - : base(message, innerException, headers, HttpStatusCode.Conflict, requestUri, subStatusCode) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private ConflictException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.Conflict) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.Conflict; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class ConflictException : DocumentClientException + { + public ConflictException() + : this(RMResources.EntityAlreadyExists) + { + + } + + public ConflictException(string message) + : this(message, (Exception)null, null) + { + + } + + public ConflictException(string message, SubStatusCodes subStatusCode) + : base(message, HttpStatusCode.Conflict, subStatusCode) + { + + } + + public ConflictException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public ConflictException(Exception innerException) + : this(RMResources.EntityAlreadyExists, innerException, null) + { + + } + + public ConflictException(Exception innerException, SubStatusCodes subStatusCode) + : this(RMResources.EntityAlreadyExists, innerException, headers: null, subStatusCode: subStatusCode) + { + } + + public ConflictException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public ConflictException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.Conflict, requestUri) + { + SetDescription(); + } + + public ConflictException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null) + : base(message, innerException, headers, HttpStatusCode.Conflict, requestUri, subStatusCode) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private ConflictException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.Conflict) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.Conflict; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionMode.cs b/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionMode.cs index cee8269e4d..b85a4720db 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionMode.cs @@ -1,39 +1,39 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported conflict resolution modes, as specified in - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum ConflictResolutionMode - { - /// - /// Last writer wins conflict resolution mode - /// - /// - /// Setting the ConflictResolutionMode to "LastWriterWins" indicates that conflict resolution should be done by inspecting a field in the conflicting documents - /// and picking the document which has the higher value in that path. See for details on how to specify the path - /// to be checked for conflict resolution. - /// - LastWriterWins, - - /// - /// Custom conflict resolution mode - /// - /// - /// Setting the ConflictResolutionMode to "Custom" indicates that conflict resolution is custom handled by a user. - /// The user could elect to register a user specified for handling conflicting resources. - /// Should the user not register a user specified StoredProcedure, conflicts will default to being made available as resources, - /// which the user can inspect and manually resolve. - /// See for details on how to specify the stored procedure - /// to run for conflict resolution. - /// - Custom - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported conflict resolution modes, as specified in + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum ConflictResolutionMode + { + /// + /// Last writer wins conflict resolution mode + /// + /// + /// Setting the ConflictResolutionMode to "LastWriterWins" indicates that conflict resolution should be done by inspecting a field in the conflicting documents + /// and picking the document which has the higher value in that path. See for details on how to specify the path + /// to be checked for conflict resolution. + /// + LastWriterWins, + + /// + /// Custom conflict resolution mode + /// + /// + /// Setting the ConflictResolutionMode to "Custom" indicates that conflict resolution is custom handled by a user. + /// The user could elect to register a user specified for handling conflicting resources. + /// Should the user not register a user specified StoredProcedure, conflicts will default to being made available as resources, + /// which the user can inspect and manually resolve. + /// See for details on how to specify the stored procedure + /// to run for conflict resolution. + /// + Custom + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionPolicy.cs index 3e02bac74d..eefca06a33 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConflictResolutionPolicy.cs @@ -1,168 +1,168 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents the conflict resolution policy configuration for specifying how to resolve conflicts - /// in case writes from different regions result in conflicts on documents in the collection in the Azure Cosmos DB service. - /// - /// - /// A collection with custom conflict resolution with no user-registered stored procedure. - /// - /// - /// - /// A collection with custom conflict resolution with a user-registered stored procedure. - /// - /// - /// - /// A collection with last writer wins conflict resolution, based on a path in the conflicting documents. - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class ConflictResolutionPolicy : JsonSerializable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public ConflictResolutionPolicy() - { - // defaults - this.Mode = ConflictResolutionMode.LastWriterWins; - } - - /// - /// Gets or sets the in the Azure Cosmos DB service. By default it is . - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.Mode)] - [JsonConverter(typeof(StringEnumConverter))] - public ConflictResolutionMode Mode - { - get - { - ConflictResolutionMode result = ConflictResolutionMode.LastWriterWins; - string strValue = base.GetValue(Constants.Properties.Mode); - if (!string.IsNullOrEmpty(strValue)) - { - result = (ConflictResolutionMode)Enum.Parse(typeof(ConflictResolutionMode), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.Mode, value.ToString()); - } - } - - /// - /// Gets or sets the path which is present in each document in the Azure Cosmos DB service for last writer wins conflict-resolution. - /// This path must be present in each document and must be an integer value. - /// In case of a conflict occuring on a document, the document with the higher integer value in the specified path will be picked. - /// If the path is unspecified, by default the path will be used. - /// - /// - /// This value should only be set when using - /// - /// - /// - /// - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionPath)] - public string ConflictResolutionPath - { - get - { - return base.GetValue(Constants.Properties.ConflictResolutionPath); - } - set - { - base.SetValue(Constants.Properties.ConflictResolutionPath, value); - } - } - - /// - /// Gets or sets the which is used for conflict resolution in the Azure Cosmos DB service. - /// This stored procedure may be created after the is created and can be changed as required. - /// - /// - /// 1. This value should only be set when using - /// 2. In case the stored procedure fails or throws an exception, the conflict resolution will default to registering conflicts in the conflicts feed"/>. - /// 3. The user can provide the stored procedure or . - /// - /// - /// - /// - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionProcedure)] - public string ConflictResolutionProcedure - { - get - { - return base.GetValue(Constants.Properties.ConflictResolutionProcedure); - } - set - { - base.SetValue(Constants.Properties.ConflictResolutionProcedure, value); - } - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.Mode); - base.GetValue(Constants.Properties.ConflictResolutionPath); - base.GetValue(Constants.Properties.ConflictResolutionProcedure); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents the conflict resolution policy configuration for specifying how to resolve conflicts + /// in case writes from different regions result in conflicts on documents in the collection in the Azure Cosmos DB service. + /// + /// + /// A collection with custom conflict resolution with no user-registered stored procedure. + /// + /// + /// + /// A collection with custom conflict resolution with a user-registered stored procedure. + /// + /// + /// + /// A collection with last writer wins conflict resolution, based on a path in the conflicting documents. + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class ConflictResolutionPolicy : JsonSerializable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public ConflictResolutionPolicy() + { + // defaults + this.Mode = ConflictResolutionMode.LastWriterWins; + } + + /// + /// Gets or sets the in the Azure Cosmos DB service. By default it is . + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.Mode)] + [JsonConverter(typeof(StringEnumConverter))] + public ConflictResolutionMode Mode + { + get + { + ConflictResolutionMode result = ConflictResolutionMode.LastWriterWins; + string strValue = base.GetValue(Constants.Properties.Mode); + if (!string.IsNullOrEmpty(strValue)) + { + result = (ConflictResolutionMode)Enum.Parse(typeof(ConflictResolutionMode), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.Mode, value.ToString()); + } + } + + /// + /// Gets or sets the path which is present in each document in the Azure Cosmos DB service for last writer wins conflict-resolution. + /// This path must be present in each document and must be an integer value. + /// In case of a conflict occuring on a document, the document with the higher integer value in the specified path will be picked. + /// If the path is unspecified, by default the path will be used. + /// + /// + /// This value should only be set when using + /// + /// + /// + /// + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionPath)] + public string ConflictResolutionPath + { + get + { + return base.GetValue(Constants.Properties.ConflictResolutionPath); + } + set + { + base.SetValue(Constants.Properties.ConflictResolutionPath, value); + } + } + + /// + /// Gets or sets the which is used for conflict resolution in the Azure Cosmos DB service. + /// This stored procedure may be created after the is created and can be changed as required. + /// + /// + /// 1. This value should only be set when using + /// 2. In case the stored procedure fails or throws an exception, the conflict resolution will default to registering conflicts in the conflicts feed"/>. + /// 3. The user can provide the stored procedure or . + /// + /// + /// + /// + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionProcedure)] + public string ConflictResolutionProcedure + { + get + { + return base.GetValue(Constants.Properties.ConflictResolutionProcedure); + } + set + { + base.SetValue(Constants.Properties.ConflictResolutionProcedure, value); + } + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.Mode); + base.GetValue(Constants.Properties.ConflictResolutionPath); + base.GetValue(Constants.Properties.ConflictResolutionProcedure); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Connection.cs b/Microsoft.Azure.Cosmos/src/direct/Connection.cs index 1298d88392..ed47a274cd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Connection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Connection.cs @@ -1,1154 +1,1154 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Net; - using System.Net.Security; - using System.Net.Sockets; - using System.Security.Authentication; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - -#if COSMOSCLIENT - using Microsoft.Azure.Cosmos.Rntbd; -#endif - -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - // Connection encapsulates the TCP connection to one back-end, and all surrounding - // mechanisms (SSL stream, connection state). - internal sealed class Connection : IDisposable - { - private const int ResponseLengthByteLimit = int.MaxValue; - private const SslProtocols TlsProtocols = SslProtocols.Tls12; - private const uint TcpKeepAliveIntervalSocketOptionEnumValue = 17; - private const uint TcpKeepAliveTimeSocketOptionEnumValue = 3; - private const uint DefaultSocketOptionTcpKeepAliveInterval = 1; - private const uint DefaultSocketOptionTcpKeepAliveTime = 30; - private static readonly uint SocketOptionTcpKeepAliveInterval = GetUInt32FromEnvironmentVariableOrDefault( - Constants.EnvironmentVariables.SocketOptionTcpKeepAliveIntervalName, - minValue: 1, - maxValue: 100, - defaultValue: DefaultSocketOptionTcpKeepAliveInterval); - private static readonly uint SocketOptionTcpKeepAliveTime = GetUInt32FromEnvironmentVariableOrDefault( - Constants.EnvironmentVariables.SocketOptionTcpKeepAliveTimeName, - minValue: 1, - maxValue: 100, - defaultValue: DefaultSocketOptionTcpKeepAliveTime); - - private static readonly Lazy rng = - new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); - private static readonly Lazy keepAliveConfiguration = - new Lazy(Connection.GetWindowsKeepAliveConfiguration, - LazyThreadSafetyMode.ExecutionAndPublication); - private static readonly Lazy isKeepAliveCustomizationSupported = - new Lazy(Connection.IsKeepAliveCustomizationSupported, - LazyThreadSafetyMode.ExecutionAndPublication); - - private static readonly TimeSpan recentReceiveWindow = TimeSpan.FromSeconds(1.0); - - private readonly Guid connectionCorrelationId; - private readonly Uri serverUri; - private readonly string hostNameCertificateOverride; - - // Recyclable memory stream pool - private readonly MemoryStreamPool memoryStreamPool; - - // Used only for integration tests - private readonly RemoteCertificateValidationCallback remoteCertificateValidationCallback; - - private bool disposed = false; - - private TcpClient tcpClient; - private UserPortPool portPool; - private IPEndPoint localEndPoint; - private IPEndPoint remoteEndPoint; - - /// - /// a connection is defined as idle if (now - lastReceiveTime >= idleConnectionTimeout) - /// - private readonly TimeSpan idleConnectionTimeout; - - /// - /// Due to race condition, requests may enter a connection when it's evaluated as idle - /// The value is idleConnectionTimeout plus a reasonably adequate buffer for pending requests to complete send and receive. - /// - private readonly TimeSpan idleConnectionClosureTimeout; - - private readonly Func> dnsResolutionFunction; - - // Only one task may write to the stream at once. Reads don't need - // mutual exclusion because only one thread consumes from the stream. - private readonly SemaphoreSlim writeSemaphore = new SemaphoreSlim(1); - private Stream stream; - private RntbdStreamReader streamReader; - - private readonly object timestampLock = new object(); - private DateTime lastSendAttemptTime; // Guarded by timestampLock. - private DateTime lastSendTime; // Guarded by timestampLock. - private DateTime lastReceiveTime; // Guarded by timestampLock. - private long numberOfSendsSinceLastReceive = 0; // Guarded by timestampLock. - private DateTime firstSendSinceLastReceive; // Guarded by timestampLock. - - private readonly object nameLock = new object(); // Acquired after timestampLock. - private string name; // Guarded by nameLock. - private static int numberOfOpenTcpConnections; - - /// - /// An instance of to check the health of the connection. - /// - private readonly ConnectionHealthChecker healthChecker; - - public Connection( - Uri serverUri, - string hostNameCertificateOverride, - TimeSpan receiveHangDetectionTime, - TimeSpan sendHangDetectionTime, - TimeSpan idleTimeout, - MemoryStreamPool memoryStreamPool, - RemoteCertificateValidationCallback remoteCertificateValidationCallback, - Func> dnsResolutionFunction) - { - Debug.Assert(serverUri.PathAndQuery.Equals("/", StringComparison.Ordinal), serverUri.AbsoluteUri, - "The server URI must not specify a path and query"); - this.connectionCorrelationId = Guid.NewGuid(); - this.serverUri = serverUri; - this.hostNameCertificateOverride = hostNameCertificateOverride; - this.BufferProvider = new BufferProvider(); - this.dnsResolutionFunction = dnsResolutionFunction ?? Connection.ResolveHostIncludingIPv6AddressesAsync; - this.lastSendAttemptTime = DateTime.MinValue; - this.lastSendTime = DateTime.MinValue; - this.lastReceiveTime = DateTime.MinValue; - - if (idleTimeout > TimeSpan.Zero) - { - // idle timeout is enabled - // Due to race condition, requests may enter a connection when it's evaluated as idle. - // The race condition is resolved by making the value of idleConnectionClosureTimeout as idleConnectionTimeout plus a reasonably adequate buffer for pending requests to complete send and receive. - this.idleConnectionTimeout = idleTimeout; - this.idleConnectionClosureTimeout = this.idleConnectionTimeout - + TimeSpan.FromTicks(2 * (sendHangDetectionTime.Ticks + receiveHangDetectionTime.Ticks)); - } - - this.name = string.Format(CultureInfo.InvariantCulture, - " -> {0}", this.serverUri); - - this.memoryStreamPool = memoryStreamPool; - this.remoteCertificateValidationCallback = remoteCertificateValidationCallback; - - this.healthChecker = new ( - sendDelayLimit: sendHangDetectionTime, - receiveDelayLimit: receiveHangDetectionTime, - idleConnectionTimeout: idleTimeout); - } - - public static int NumberOfOpenTcpConnections { get { return Connection.numberOfOpenTcpConnections; } } - - public BufferProvider BufferProvider { get; } - - public Uri ServerUri { get { return this.serverUri; } } - - public bool Healthy - { - get - { - this.ThrowIfDisposed(); - if (this.tcpClient == null) - { - return false; - } - - this.SnapshotConnectionTimestamps( - out DateTime lastSendAttempt, - out DateTime lastSend, - out DateTime lastReceive, - out DateTime? firstSendSinceLastReceive, - out long numberOfSendsSinceLastReceive); - - return this.healthChecker.IsHealthy( - currentTime: DateTime.UtcNow, - lastSendAttempt: lastSendAttempt, - lastSend: lastSend, - lastReceive: lastReceive, - firstSendSinceLastReceive: firstSendSinceLastReceive, - numberOfSendsSinceLastReceive: numberOfSendsSinceLastReceive, - socket: this.tcpClient.Client); - } - } - - public bool Disposed { get { return this.disposed; } } - - public Guid ConnectionCorrelationId { get => this.connectionCorrelationId; } - - public sealed class ResponseMetadata : IDisposable - { - private bool disposed; - - private BufferProvider.DisposableBuffer header; - private BufferProvider.DisposableBuffer metadata; - - public ResponseMetadata(BufferProvider.DisposableBuffer header, BufferProvider.DisposableBuffer metadata) - { - this.header = header; - this.metadata = metadata; - this.disposed = false; - } - - public ArraySegment Header => this.header.Buffer; - public ArraySegment Metadata => this.metadata.Buffer; - - /// - public void Dispose() - { - if (!this.disposed) - { - this.header.Dispose(); - this.metadata.Dispose(); - this.disposed = true; - } - } - } - - public async Task OpenAsync(ChannelOpenArguments args) - { - this.ThrowIfDisposed(); - await this.OpenSocketAsync(args); - await this.NegotiateSslAsync(args); - } - - // This method is thread safe. - public async Task WriteRequestAsync(ChannelCommonArguments args, - TransportSerialization.SerializedRequest messagePayload, - TransportRequestStats transportRequestStats) - { - this.ThrowIfDisposed(); - - if (transportRequestStats != null) - { - this.SnapshotConnectionTimestamps( - out DateTime lastSendAttempt, - out DateTime lastSend, - out DateTime lastReceive, - out DateTime? firstSendSinceLastReceive, - out long numberOfSendsSinceLastReceive); - transportRequestStats.ConnectionLastSendAttemptTime = lastSendAttempt; - transportRequestStats.ConnectionLastSendTime = lastSend; - transportRequestStats.ConnectionLastReceiveTime = lastReceive; - } - - args.SetTimeoutCode(TransportErrorCode.SendLockTimeout); - await this.writeSemaphore.WaitAsync(); - try - { - args.SetTimeoutCode(TransportErrorCode.SendTimeout); - args.SetPayloadSent(); - this.UpdateLastSendAttemptTime(); - await messagePayload.CopyToStreamAsync(this.stream); - } - finally - { - this.writeSemaphore.Release(); - } - this.UpdateLastSendTime(); - // Do not update the last receive timestamp here. The fact that sending - // the request succeeded means nothing until the response comes back. - } - - // This method is not thread safe. ReadResponseMetadataAsync and - // ReadResponseBodyAsync must be called in sequence, from a single thread. - [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] - public async Task ReadResponseMetadataAsync(ChannelCommonArguments args) - { - this.ThrowIfDisposed(); - - Trace.CorrelationManager.ActivityId = args.ActivityId; - int metadataHeaderLength = sizeof(UInt32) /* totalLength */ + sizeof(UInt32) /* status */ + - 16; - BufferProvider.DisposableBuffer header = this.BufferProvider.GetBuffer(metadataHeaderLength); - await this.ReadPayloadAsync(header.Buffer.Array, metadataHeaderLength /* sizeof(Guid) */, "header", args); - - UInt32 totalLength = BitConverter.ToUInt32(header.Buffer.Array, 0); - if (totalLength > Connection.ResponseLengthByteLimit) - { - header.Dispose(); - DefaultTrace.TraceCritical("[RNTBD Connection {0}] RNTBD header length says {1} but expected at most {2} bytes. Connection: {3}", - this.connectionCorrelationId, totalLength, Connection.ResponseLengthByteLimit, this); - throw TransportExceptions.GetInternalServerErrorException( - this.serverUri, - string.Format( - CultureInfo.CurrentUICulture, - RMResources.ServerResponseHeaderTooLargeError, - totalLength, this)); - } - - if (totalLength < metadataHeaderLength) - { - DefaultTrace.TraceCritical( - "[RNTBD Connection {0}] Invalid RNTBD header length {1} bytes. Expected at least {2} bytes. Connection: {3}", - this.connectionCorrelationId, totalLength, metadataHeaderLength, this); - throw TransportExceptions.GetInternalServerErrorException( - this.serverUri, - string.Format( - CultureInfo.CurrentUICulture, - RMResources.ServerResponseInvalidHeaderLengthError, - metadataHeaderLength, totalLength, this)); - } - - int metadataLength = (int)totalLength - metadataHeaderLength; - BufferProvider.DisposableBuffer metadata = this.BufferProvider.GetBuffer(metadataLength); - await this.ReadPayloadAsync(metadata.Buffer.Array, metadataLength, "metadata", args); - return new ResponseMetadata(header, metadata); - } - - // This method is not thread safe. ReadResponseMetadataAsync and - // ReadResponseBodyAsync must be called in sequence, from a single thread. - public async Task ReadResponseBodyAsync(ChannelCommonArguments args) - { - this.ThrowIfDisposed(); - - Trace.CorrelationManager.ActivityId = args.ActivityId; - using BufferProvider.DisposableBuffer bodyLengthHeader = this.BufferProvider.GetBuffer(sizeof(uint)); - await this.ReadPayloadAsync(bodyLengthHeader.Buffer.Array, sizeof(uint), - "body length header", args); - - uint length = BitConverter.ToUInt32(bodyLengthHeader.Buffer.Array, 0); - // This check can also validate "length" against the expected total - // response size. - if (length > Connection.ResponseLengthByteLimit) - { - DefaultTrace.TraceCritical("[RNTBD Connection {0}] Invalid RNTBD response body length {1} bytes. Connection: {2}", this.connectionCorrelationId, length, this); - throw TransportExceptions.GetInternalServerErrorException( - this.serverUri, - string.Format( - CultureInfo.CurrentUICulture, - RMResources.ServerResponseBodyTooLargeError, - length, this)); - } - - MemoryStream memoryStream = null; - if (this.memoryStreamPool?.TryGetMemoryStream((int)length, out memoryStream) ?? false) - { - await this.ReadPayloadAsync(memoryStream, (int)length, "body", args); - memoryStream.Position = 0; - return memoryStream; - } - else - { - byte[] body = new byte[length]; - await this.ReadPayloadAsync(body, (int)length, "body", args); - return StreamExtension.CreateExportableMemoryStream(body); - } - } - - public override string ToString() - { - lock (this.nameLock) - { - return this.name; - } - } - - public void Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - - string connectionTimestampsText = this.GetConnectionTimestampsText(); - if (this.tcpClient != null) - { - Debug.Assert(this.tcpClient.Client != null); - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] Disposing RNTBD connection {1} -> {2} to server {3}. {4}", - this.connectionCorrelationId, - this.localEndPoint, - this.remoteEndPoint, - this.serverUri, connectionTimestampsText); - string newName = string.Format( - CultureInfo.InvariantCulture, - " {0} -> {1}", - this.localEndPoint, - this.remoteEndPoint); - lock (this.nameLock) - { - this.name = newName; - } - } - else - { - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] Disposing unused RNTBD connection to server {1}. {2}", - this.connectionCorrelationId, this.serverUri, connectionTimestampsText); - } - - if (this.tcpClient != null) - { - if (this.portPool != null) - { - this.portPool.RemoveReference(this.localEndPoint.AddressFamily, checked((ushort)this.localEndPoint.Port)); - } - this.tcpClient.Close(); - - Interlocked.Decrement(ref Connection.numberOfOpenTcpConnections); - - this.tcpClient = null; - Debug.Assert(this.stream != null); - this.stream.Close(); - this.streamReader?.Dispose(); - TransportClient.GetTransportPerformanceCounters().IncrementRntbdConnectionClosedCount(); - } - } - - // Returns (true, timeToIdle) for active connections and (false, idleTimeout) - // for idle connections. - // timeToIdle is the minimum amount of time that will pass until the - // connection might become idle. - public bool IsActive(out TimeSpan timeToIdle) - { - this.ThrowIfDisposed(); - - // IsActive should not be called if idle timeout is disabled - Debug.Assert(this.idleConnectionTimeout > TimeSpan.Zero); - - this.SnapshotConnectionTimestamps( - out DateTime lastSendAttempt, - out DateTime lastSend, - out DateTime lastReceive, - out DateTime? firstSendSinceLastReceive, - out long numberOfSendsSinceLastReceive); - DateTime now = DateTime.UtcNow; - - if (now - lastReceive > this.idleConnectionTimeout) - { - // idle - timeToIdle = this.idleConnectionClosureTimeout; - return false; - } - else - { - // 'not idle' guarantees lastReceiveTime is a non-default value. - Debug.Assert(lastReceive != DateTime.MinValue); - - timeToIdle = lastReceive + this.idleConnectionClosureTimeout - now; - - // 'not idle' guarantees 'now < lastReceive + idleConnectionTimeout', so that the new timeToIdle is guaranteed to be positive - Debug.Assert(timeToIdle > TimeSpan.Zero); - - return true; - } - } - - /// - /// Notify the connection health status by updating the transit timeout counters. - /// - /// A boolean flag indicating if the request is completed successfully. - /// An optional boolean flag indicating if the current operation is read-only in nature. - internal void NotifyConnectionStatus( - bool isCompleted, - bool isReadRequest = false) - { - this.healthChecker.UpdateTransitTimeoutCounters( - isCompleted, - isReadRequest); - } - - #region Test hook. - - internal TimeSpan TestIdleConnectionClosureTimeout => this.idleConnectionClosureTimeout; - internal void TestSetLastReceiveTime(DateTime lrt) - { - lock (this.timestampLock) - { - this.lastReceiveTime = lrt; - } - } - - #endregion - - private static uint GetUInt32FromEnvironmentVariableOrDefault( - string name, - uint minValue, - uint maxValue, - uint defaultValue) - { - string envVariableValueText = Environment.GetEnvironmentVariable(name); - - if (String.IsNullOrEmpty(envVariableValueText) || - !UInt32.TryParse( - envVariableValueText, - NumberStyles.Integer, - CultureInfo.InvariantCulture, - out uint envVariableValue)) - { - return defaultValue; - } - - if (envVariableValue > maxValue || envVariableValue < minValue) - { - throw new ArgumentOutOfRangeException( - name, - $"Value for environment variable '{name}' is outside expected range of {minValue} - {maxValue}."); - } - - return envVariableValue; - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - Debug.Assert(this.serverUri != null); - throw new ObjectDisposedException( - string.Format("{0}:{1}", nameof(Connection), this.serverUri)); - } - } - - private async Task OpenSocketAsync(ChannelOpenArguments args) - { - if (this.tcpClient != null) - { - throw new InvalidOperationException( - $"Attempting to call Connection.OpenSocketAsync on an " + - $"already initialized connection {this}"); - } - - TcpClient tcpClient = null; - TransportErrorCode errorCode = TransportErrorCode.Unknown; - try - { - errorCode = TransportErrorCode.DnsResolutionFailed; - args.CommonArguments.SetTimeoutCode( - TransportErrorCode.DnsResolutionTimeout); - IPAddress address = await this.dnsResolutionFunction(this.serverUri.DnsSafeHost); - - errorCode = TransportErrorCode.ConnectFailed; - args.CommonArguments.SetTimeoutCode(TransportErrorCode.ConnectTimeout); - - this.UpdateLastSendAttemptTime(); - - DefaultTrace.TraceInformation("[RNTBD Connection {0}] Port reuse mode: {1}. Connection: {2}", this.connectionCorrelationId, args.PortReuseMode, this); - switch (args.PortReuseMode) - { - case PortReuseMode.ReuseUnicastPort: - tcpClient = await Connection.ConnectUnicastPortAsync(this.serverUri, address, this.connectionCorrelationId); - break; - - case PortReuseMode.PrivatePortPool: - Tuple result = await Connection.ConnectUserPortAsync(this.serverUri, address, args.PortPool, this.ToString(), this.connectionCorrelationId); - tcpClient = result.Item1; - bool portPoolUsed = result.Item2; - if (portPoolUsed) - { - Debug.Assert(this.portPool == null); - this.portPool = args.PortPool; - } - else - { - DefaultTrace.TraceInformation("[RNTBD Connection {0}] PrivatePortPool: Configured but actually not used. Connection: {1}", this.connectionCorrelationId, this); - } - - break; - - default: - throw new ArgumentException( - string.Format( - "Unsupported port reuse policy {0}", - args.PortReuseMode.ToString())); - } - - this.UpdateLastSendTime(); - this.UpdateLastReceiveTime(); - args.OpenTimeline.RecordConnectFinishTime(); - - DefaultTrace.TraceInformation("[RNTBD Connection {0}] RNTBD connection established {1} -> {2}", - this.connectionCorrelationId, tcpClient.Client.LocalEndPoint, tcpClient.Client.RemoteEndPoint); - TransportClient.GetTransportPerformanceCounters().IncrementRntbdConnectionEstablishedCount(); - string newName = string.Format( - CultureInfo.InvariantCulture, - "{0} -> {1}", - tcpClient.Client.LocalEndPoint, - tcpClient.Client.RemoteEndPoint); - lock (this.nameLock) - { - this.name = newName; - } - } - catch (Exception ex) - { - // Dispose the socket eagerly to avoid keeping the underlying - // handle around until finalization. - tcpClient?.Close(); - -#if NETFX - SocketException socketEx = ex as SocketException; - if (socketEx != null && socketEx.SocketErrorCode == SocketError.TimedOut) - { - if (PerfCounters.Counters.BackendConnectionOpenFailuresDueToSynRetransmitPerSecond != null) - { - PerfCounters.Counters.BackendConnectionOpenFailuresDueToSynRetransmitPerSecond.Increment(); - } - } -#endif - - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] Connection.OpenSocketAsync failed. Converting to TransportException. " + - "Connection: {1}. Inner exception: {2}", this.connectionCorrelationId, this, ex); - Debug.Assert(errorCode != TransportErrorCode.Unknown); - Debug.Assert(!args.CommonArguments.UserPayload); - Debug.Assert(!args.CommonArguments.PayloadSent); - throw new TransportException(errorCode, ex, - args.CommonArguments.ActivityId, this.serverUri, - this.ToString(), args.CommonArguments.UserPayload, - args.CommonArguments.PayloadSent); - } - - Debug.Assert(tcpClient != null); - this.localEndPoint = (IPEndPoint)tcpClient.Client.LocalEndPoint; - this.remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint; - this.tcpClient = tcpClient; - this.stream = tcpClient.GetStream(); - - Interlocked.Increment(ref Connection.numberOfOpenTcpConnections); - - // Per MSDN, "The Blocking property has no effect on asynchronous methods" - // (https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.blocking), - // but we also try to get the health status of the socket with a - // non-blocking, zero-byte Send. - this.tcpClient.Client.Blocking = false; - } - - private async Task NegotiateSslAsync(ChannelOpenArguments args) - { - string host = this.hostNameCertificateOverride ?? this.serverUri.DnsSafeHost; - Debug.Assert(this.stream != null); - SslStream sslStream = new SslStream(this.stream, leaveInnerStreamOpen: false, userCertificateValidationCallback: this.remoteCertificateValidationCallback); - try - { - args.CommonArguments.SetTimeoutCode( - TransportErrorCode.SslNegotiationTimeout); - this.UpdateLastSendAttemptTime(); - - await sslStream.AuthenticateAsClientAsync(host, clientCertificates: null, - enabledSslProtocols: Connection.TlsProtocols, checkCertificateRevocation: false); - - this.UpdateLastSendTime(); - this.UpdateLastReceiveTime(); - args.OpenTimeline.RecordSslHandshakeFinishTime(); - - this.stream = sslStream; - this.streamReader = new RntbdStreamReader(this.stream); - Debug.Assert(this.tcpClient != null); - DefaultTrace.TraceInformation("[RNTBD Connection {0}] SSL handshake complete {1} -> {2}", - this.connectionCorrelationId, this.localEndPoint, this.remoteEndPoint); - } - catch (Exception ex) - { - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] Connection.NegotiateSslAsync failed. Converting to TransportException. " + - "Connection: {1}. Inner exception: {2}", this.connectionCorrelationId, this, ex); - Debug.Assert(!args.CommonArguments.UserPayload); - Debug.Assert(!args.CommonArguments.PayloadSent); - throw new TransportException( - TransportErrorCode.SslNegotiationFailed, ex, - args.CommonArguments.ActivityId, this.serverUri, - this.ToString(), args.CommonArguments.UserPayload, - args.CommonArguments.PayloadSent); - } - } - - private async Task ReadPayloadAsync( - byte[] payload, - int length, - string type, - ChannelCommonArguments args) - { - Debug.Assert(length > 0); - Debug.Assert(length <= Connection.ResponseLengthByteLimit); - int bytesRead = 0; - while (bytesRead < length) - { - int read = 0; - try - { - read = await this.streamReader.ReadAsync(payload, bytesRead, - length - bytesRead); - } - catch (IOException ex) - { - this.TraceAndThrowReceiveFailedException(ex, type, args); - } - - if (read == 0) - { - this.TraceAndThrowEndOfStream(type, args); - } - this.UpdateLastReceiveTime(); - bytesRead += read; - } - Debug.Assert(bytesRead == length); - Debug.Assert(length <= payload.Length); - } - - - private async Task ReadPayloadAsync( - MemoryStream payload, - int length, - string type, - ChannelCommonArguments args) - { - Debug.Assert(length > 0); - Debug.Assert(length <= Connection.ResponseLengthByteLimit); - int bytesRead = 0; - while (bytesRead < length) - { - int read = 0; - try - { - read = await this.streamReader.ReadAsync(payload, length - bytesRead); - } - catch (IOException ex) - { - this.TraceAndThrowReceiveFailedException(ex, type, args); - } - - if (read == 0) - { - this.TraceAndThrowEndOfStream(type, args); - } - this.UpdateLastReceiveTime(); - bytesRead += read; - } - Debug.Assert(bytesRead == length); - Debug.Assert(length <= payload.Length); - } - - private void TraceAndThrowReceiveFailedException(IOException e, string type, ChannelCommonArguments args) - { - DefaultTrace.TraceError( - "[RNTBD Connection {0}] Hit IOException {1} with HResult {2} while reading {3} on connection {4}. {5}", - this.connectionCorrelationId, - e.Message, - e.HResult, - type, - this, - this.GetConnectionTimestampsText()); - throw new TransportException( - TransportErrorCode.ReceiveFailed, e, args.ActivityId, - this.serverUri, this.ToString(), args.UserPayload, true); - } - - private void TraceAndThrowEndOfStream(string type, ChannelCommonArguments args) - { - DefaultTrace.TraceError( - "[RNTBD Connection {0}] Reached end of stream. Read 0 bytes while reading {1} " + - "on connection {2}. {3}", - this.connectionCorrelationId, type, this, this.GetConnectionTimestampsText()); - throw new TransportException( - TransportErrorCode.ReceiveStreamClosed, null, - args.ActivityId, this.serverUri, this.ToString(), - args.UserPayload, true); - } - - /// - /// Helper method to snapshot the connection timestamps. - /// - /// A field containing the last send attempt time. - /// A field containing the last send time. - /// A field containing the last receive time. - /// A field containing the first send since last receive time. - /// A long integer field containing the number of sends since last receive time. - private void SnapshotConnectionTimestamps( - out DateTime lastSendAttempt, - out DateTime lastSend, - out DateTime lastReceive, - out DateTime? firstSendSinceLastReceive, - out long numberOfSendsSinceLastReceive) - { - Debug.Assert(!Monitor.IsEntered(this.timestampLock)); - lock (this.timestampLock) - { - lastSendAttempt = this.lastSendAttemptTime; - lastSend = this.lastSendTime; - lastReceive = this.lastReceiveTime; - firstSendSinceLastReceive = - this.lastReceiveTime < this.firstSendSinceLastReceive ? this.firstSendSinceLastReceive : null; - numberOfSendsSinceLastReceive = this.numberOfSendsSinceLastReceive; - } - } - - private string GetConnectionTimestampsText() - { - this.SnapshotConnectionTimestamps( - out DateTime lastSendAttempt, - out DateTime lastSend, - out DateTime lastReceive, - out DateTime? firstSendSinceLastReceive, - out long numberOfSendsSinceLastReceive); - return string.Format( - CultureInfo.InvariantCulture, - "Last send attempt time: {0:o}. Last send time: {1:o}. " + - "Last receive time: {2:o}. First sends since last receieve: {3:o}. " + - "# of sends since last receive: {4}", - lastSendAttempt, lastSend, lastReceive, firstSendSinceLastReceive, numberOfSendsSinceLastReceive); - } - - private void UpdateLastSendAttemptTime() - { - Debug.Assert(!Monitor.IsEntered(this.timestampLock)); - lock (this.timestampLock) - { - this.lastSendAttemptTime = DateTime.UtcNow; - } - } - - private void UpdateLastSendTime() - { - Debug.Assert(!Monitor.IsEntered(this.timestampLock)); - lock (this.timestampLock) - { - this.lastSendTime = DateTime.UtcNow; - - if (this.numberOfSendsSinceLastReceive++ == 0) - { - this.firstSendSinceLastReceive = this.lastSendTime; - } - } - } - - private void UpdateLastReceiveTime() - { - Debug.Assert(!Monitor.IsEntered(this.timestampLock)); - lock (this.timestampLock) - { - this.numberOfSendsSinceLastReceive = 0; - this.lastReceiveTime = DateTime.UtcNow; - } - } - - private static async Task ConnectUnicastPortAsync(Uri serverUri, IPAddress resolvedAddress, Guid connectionCorrelationId) - { - TcpClient tcpClient = new TcpClient(resolvedAddress.AddressFamily); - - Connection.SetCommonSocketOptions(tcpClient.Client, connectionCorrelationId); - - Connection.SetReuseUnicastPort(tcpClient.Client, connectionCorrelationId); - - DefaultTrace.TraceInformation("[RNTBD Connection {0}] {1} connecting to {2} (address {3})", - connectionCorrelationId, nameof(ConnectUnicastPortAsync), serverUri, resolvedAddress); - - await tcpClient.ConnectAsync(resolvedAddress, serverUri.Port); - - return tcpClient; - } - - private static async Task> ConnectReuseAddrAsync( - Uri serverUri, IPAddress address, ushort candidatePort, Guid connectionCorrelationId) - { - TcpClient candidateClient = new TcpClient(address.AddressFamily); - TcpClient client = null; - try - { - Connection.SetCommonSocketOptions(candidateClient.Client, connectionCorrelationId); - - candidateClient.Client.SetSocketOption( - SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - - EndPoint bindEndpoint = null; - switch (address.AddressFamily) - { - case AddressFamily.InterNetwork: - bindEndpoint = new IPEndPoint(IPAddress.Any, candidatePort); - break; - - case AddressFamily.InterNetworkV6: - bindEndpoint = new IPEndPoint(IPAddress.IPv6Any, candidatePort); - break; - - default: - throw new NotSupportedException( - string.Format( - CultureInfo.InvariantCulture, - "Address family {0} not supported", - address.AddressFamily)); - } - - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] RNTBD: {1} binding local endpoint {2}", - connectionCorrelationId, nameof(ConnectReuseAddrAsync), bindEndpoint); - - try - { - Debug.Assert(bindEndpoint != null); - candidateClient.Client.Bind(bindEndpoint); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.AccessDenied) - { - Debug.Assert(candidateClient != null); - return Tuple.Create(null, false); - } - else - { - throw; - } - } - - DefaultTrace.TraceInformation("[RNTBD Connection {0}] {1} connecting to {2} (address {3})", - connectionCorrelationId, nameof(ConnectReuseAddrAsync), serverUri, address); - - try - { - await candidateClient.ConnectAsync(address, serverUri.Port); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.AddressAlreadyInUse) - { - return Tuple.Create(null, true); - } - else - { - throw; - } - } - - client = candidateClient; - candidateClient = null; - } - finally - { - if (candidateClient != null) - { - Debug.Assert(client == null); - candidateClient.Close(); - } - } - Debug.Assert(candidateClient == null); - return Tuple.Create(client, true); - } - - private static async Task> ConnectUserPortAsync( - Uri serverUri, IPAddress address, UserPortPool portPool, string connectionName, Guid connectionCorrelationId) - { - ushort[] candidatePorts = portPool.GetCandidatePorts(address.AddressFamily); - if (candidatePorts != null) - { - foreach (ushort candidatePort in candidatePorts) - { - Debug.Assert(candidatePort != 0); - Tuple result = - await Connection.ConnectReuseAddrAsync( - serverUri, address, candidatePort, connectionCorrelationId); - TcpClient portReuseClient = result.Item1; - bool portUsable = result.Item2; - if (portReuseClient != null) - { - ushort localPort = checked((ushort)((IPEndPoint)portReuseClient.Client.LocalEndPoint).Port); - Debug.Assert(localPort == candidatePort); - portPool.AddReference( - address.AddressFamily, localPort); - return Tuple.Create(portReuseClient, true); - } - if (!portUsable) - { - portPool.MarkUnusable(address.AddressFamily, candidatePort); - } - } - - DefaultTrace.TraceInformation("[RNTBD Connection {0}] PrivatePortPool: All {1} candidate ports have been tried but none connects. Connection: {2}", connectionCorrelationId, candidatePorts.Length, connectionName); - } - - Tuple wildcardResult = await Connection.ConnectReuseAddrAsync(serverUri, address, 0, connectionCorrelationId); - TcpClient wildcardClient = wildcardResult.Item1; - if (wildcardClient != null) - { - portPool.AddReference( - address.AddressFamily, - checked((ushort)((IPEndPoint)wildcardClient.Client.LocalEndPoint).Port)); - return Tuple.Create(wildcardClient, true); - } - - DefaultTrace.TraceInformation( - "[RNTBD Connection {0}] PrivatePortPool: Not enough reusable ports in the system or pool. Have to connect unicast port. Pool status: {1}. Connection: {2}", - connectionCorrelationId, portPool.DumpStatus(), connectionName); - return Tuple.Create(await Connection.ConnectUnicastPortAsync(serverUri, address, connectionCorrelationId), false); - } - - /// - /// Wrapper method for that allows IPv6 addresses. - /// Used unless internal clients provide a version that might override decision to use IPv6 addresses. - /// - /// - /// - private static Task ResolveHostIncludingIPv6AddressesAsync(string hostName) => Connection.ResolveHostAsync(hostName, includeIPv6Addresses: true); - - internal static async Task ResolveHostAsync(string hostName, bool includeIPv6Addresses) - { - // Using Linq for a cold path - IPAddress[] serverAddresses = await Dns.GetHostAddressesAsync(hostName); - int serverAddressesCount = serverAddresses.Length; - - if (!includeIPv6Addresses) - { - // Exclude IPv6 addresses - serverAddressesCount = 0; - foreach (IPAddress ipAddress in serverAddresses) - { - if (ipAddress.AddressFamily == AddressFamily.InterNetwork) - { - serverAddresses[serverAddressesCount++] = ipAddress; - } - } - } - - int addressIndex = 0; - if (serverAddressesCount > 1) - { - addressIndex = Connection.rng.Value.Next(serverAddressesCount); - } - - if (serverAddressesCount == 0) - { - throw new ArgumentOutOfRangeException($"DNS Resolve resulted in no internet addresses. includeIPv6Addresses: {includeIPv6Addresses}"); - } - - return serverAddresses[addressIndex]; - } - - private static void SetCommonSocketOptions(Socket clientSocket, Guid connectionCorrelationId) - { - clientSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); - Connection.EnableTcpKeepAlive(clientSocket, connectionCorrelationId); - } - - private static void EnableTcpKeepAlive(Socket clientSocket, Guid connectionCorrelationId) - { - clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); - -#if !NETSTANDARD15 && !NETSTANDARD16 - // This code should use RuntimeInformation.IsOSPlatform(OSPlatform.Windows), - // but the feature is unavailable on .NET Framework 4.5.1. - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - try - { - clientSocket.IOControl( - IOControlCode.KeepAliveValues, - Connection.keepAliveConfiguration.Value, - null); - } - catch (Exception e) - { - DefaultTrace.TraceWarning("[RNTBD Connection {0}] IOControl(KeepAliveValues) failed: {1}", connectionCorrelationId, e); - // Ignore the exception. - } - } - else - { - Connection.SetKeepAliveSocketOptions(clientSocket); - } -#else - Connection.SetKeepAliveSocketOptions(clientSocket); -#endif - } - - private static void SetKeepAliveSocketOptions(Socket clientSocket) - { - if (Connection.isKeepAliveCustomizationSupported.Value) - { - //SocketOptionName.TcpKeepAliveInterval - clientSocket.SetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue, - SocketOptionTcpKeepAliveInterval); - - //SocketOptionName.TcpKeepAliveTime - clientSocket.SetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue, - SocketOptionTcpKeepAliveTime); - } -#if DEBUG - int tcpKeepAliveInterval = (int)clientSocket.GetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue); - int tcpKeepAliveTime = (int)clientSocket.GetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue); - Debug.Equals(tcpKeepAliveInterval, SocketOptionTcpKeepAliveInterval); - Debug.Equals(tcpKeepAliveTime, SocketOptionTcpKeepAliveTime); -#endif - } - - private static bool IsKeepAliveCustomizationSupported() - { - // Check to see if the SetSocketOptionsMethod does not throw - try - { - using (Socket dummySocket = new Socket(SocketType.Stream, ProtocolType.Tcp)) - { - dummySocket.SetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue, - SocketOptionTcpKeepAliveInterval); - dummySocket.SetSocketOption(SocketOptionLevel.Tcp, - (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue, - SocketOptionTcpKeepAliveTime); - return true; - } - } - catch - { - return false; - } - } - - private static byte[] GetWindowsKeepAliveConfiguration() - { - const uint EnableKeepAlive = 1; - const uint KeepAliveIntervalMs = 30 * 1000; - const uint KeepAliveRetryIntervalMs = 1 * 1000; - - // struct tcp_keepalive - // { - // u_long onoff; - // u_long keepalivetime; - // u_long keepaliveinterval; - // }; - byte[] keepAliveConfig = new byte[3 * sizeof(uint)]; - BitConverter.GetBytes(EnableKeepAlive).CopyTo(keepAliveConfig, 0); - BitConverter.GetBytes(KeepAliveIntervalMs).CopyTo(keepAliveConfig, sizeof(uint)); - BitConverter.GetBytes(KeepAliveRetryIntervalMs).CopyTo(keepAliveConfig, 2 * sizeof(uint)); - return keepAliveConfig; - } - - private static void SetReuseUnicastPort(Socket clientSocket, Guid connectionCorrelationId) - { -#if !NETSTANDARD15 && !NETSTANDARD16 - // This code should use RuntimeInformation.IsOSPlatform(OSPlatform.Windows), - // but the feature is unavailable on .NET Framework 4.5.1. - if (Environment.OSVersion.Platform == PlatformID.Win32NT) - { - try - { - Debug.Assert(!clientSocket.IsBound); - // SocketOptionName.ReuseUnicastPort is only present in .NET Framework 4.6.1 and newer. - // Use the numeric value for as long as this code needs to target earlier versions. - const int SO_REUSE_UNICASTPORT = 0x3007; - clientSocket.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)SO_REUSE_UNICASTPORT, true); - } - catch (Exception e) - { - DefaultTrace.TraceWarning("[RNTBD Connection {0}] SetSocketOption(Socket, ReuseUnicastPort) failed: {1}", connectionCorrelationId, e); - // Ignore the exception. - } - } -#endif // !NETSTANDARD15 && !NETSTANDARD16 - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Net; + using System.Net.Security; + using System.Net.Sockets; + using System.Security.Authentication; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + +#if COSMOSCLIENT + using Microsoft.Azure.Cosmos.Rntbd; +#endif + +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + // Connection encapsulates the TCP connection to one back-end, and all surrounding + // mechanisms (SSL stream, connection state). + internal sealed class Connection : IDisposable + { + private const int ResponseLengthByteLimit = int.MaxValue; + private const SslProtocols TlsProtocols = SslProtocols.Tls12; + private const uint TcpKeepAliveIntervalSocketOptionEnumValue = 17; + private const uint TcpKeepAliveTimeSocketOptionEnumValue = 3; + private const uint DefaultSocketOptionTcpKeepAliveInterval = 1; + private const uint DefaultSocketOptionTcpKeepAliveTime = 30; + private static readonly uint SocketOptionTcpKeepAliveInterval = GetUInt32FromEnvironmentVariableOrDefault( + Constants.EnvironmentVariables.SocketOptionTcpKeepAliveIntervalName, + minValue: 1, + maxValue: 100, + defaultValue: DefaultSocketOptionTcpKeepAliveInterval); + private static readonly uint SocketOptionTcpKeepAliveTime = GetUInt32FromEnvironmentVariableOrDefault( + Constants.EnvironmentVariables.SocketOptionTcpKeepAliveTimeName, + minValue: 1, + maxValue: 100, + defaultValue: DefaultSocketOptionTcpKeepAliveTime); + + private static readonly Lazy rng = + new Lazy(LazyThreadSafetyMode.ExecutionAndPublication); + private static readonly Lazy keepAliveConfiguration = + new Lazy(Connection.GetWindowsKeepAliveConfiguration, + LazyThreadSafetyMode.ExecutionAndPublication); + private static readonly Lazy isKeepAliveCustomizationSupported = + new Lazy(Connection.IsKeepAliveCustomizationSupported, + LazyThreadSafetyMode.ExecutionAndPublication); + + private static readonly TimeSpan recentReceiveWindow = TimeSpan.FromSeconds(1.0); + + private readonly Guid connectionCorrelationId; + private readonly Uri serverUri; + private readonly string hostNameCertificateOverride; + + // Recyclable memory stream pool + private readonly MemoryStreamPool memoryStreamPool; + + // Used only for integration tests + private readonly RemoteCertificateValidationCallback remoteCertificateValidationCallback; + + private bool disposed = false; + + private TcpClient tcpClient; + private UserPortPool portPool; + private IPEndPoint localEndPoint; + private IPEndPoint remoteEndPoint; + + /// + /// a connection is defined as idle if (now - lastReceiveTime >= idleConnectionTimeout) + /// + private readonly TimeSpan idleConnectionTimeout; + + /// + /// Due to race condition, requests may enter a connection when it's evaluated as idle + /// The value is idleConnectionTimeout plus a reasonably adequate buffer for pending requests to complete send and receive. + /// + private readonly TimeSpan idleConnectionClosureTimeout; + + private readonly Func> dnsResolutionFunction; + + // Only one task may write to the stream at once. Reads don't need + // mutual exclusion because only one thread consumes from the stream. + private readonly SemaphoreSlim writeSemaphore = new SemaphoreSlim(1); + private Stream stream; + private RntbdStreamReader streamReader; + + private readonly object timestampLock = new object(); + private DateTime lastSendAttemptTime; // Guarded by timestampLock. + private DateTime lastSendTime; // Guarded by timestampLock. + private DateTime lastReceiveTime; // Guarded by timestampLock. + private long numberOfSendsSinceLastReceive = 0; // Guarded by timestampLock. + private DateTime firstSendSinceLastReceive; // Guarded by timestampLock. + + private readonly object nameLock = new object(); // Acquired after timestampLock. + private string name; // Guarded by nameLock. + private static int numberOfOpenTcpConnections; + + /// + /// An instance of to check the health of the connection. + /// + private readonly ConnectionHealthChecker healthChecker; + + public Connection( + Uri serverUri, + string hostNameCertificateOverride, + TimeSpan receiveHangDetectionTime, + TimeSpan sendHangDetectionTime, + TimeSpan idleTimeout, + MemoryStreamPool memoryStreamPool, + RemoteCertificateValidationCallback remoteCertificateValidationCallback, + Func> dnsResolutionFunction) + { + Debug.Assert(serverUri.PathAndQuery.Equals("/", StringComparison.Ordinal), serverUri.AbsoluteUri, + "The server URI must not specify a path and query"); + this.connectionCorrelationId = Guid.NewGuid(); + this.serverUri = serverUri; + this.hostNameCertificateOverride = hostNameCertificateOverride; + this.BufferProvider = new BufferProvider(); + this.dnsResolutionFunction = dnsResolutionFunction ?? Connection.ResolveHostIncludingIPv6AddressesAsync; + this.lastSendAttemptTime = DateTime.MinValue; + this.lastSendTime = DateTime.MinValue; + this.lastReceiveTime = DateTime.MinValue; + + if (idleTimeout > TimeSpan.Zero) + { + // idle timeout is enabled + // Due to race condition, requests may enter a connection when it's evaluated as idle. + // The race condition is resolved by making the value of idleConnectionClosureTimeout as idleConnectionTimeout plus a reasonably adequate buffer for pending requests to complete send and receive. + this.idleConnectionTimeout = idleTimeout; + this.idleConnectionClosureTimeout = this.idleConnectionTimeout + + TimeSpan.FromTicks(2 * (sendHangDetectionTime.Ticks + receiveHangDetectionTime.Ticks)); + } + + this.name = string.Format(CultureInfo.InvariantCulture, + " -> {0}", this.serverUri); + + this.memoryStreamPool = memoryStreamPool; + this.remoteCertificateValidationCallback = remoteCertificateValidationCallback; + + this.healthChecker = new ( + sendDelayLimit: sendHangDetectionTime, + receiveDelayLimit: receiveHangDetectionTime, + idleConnectionTimeout: idleTimeout); + } + + public static int NumberOfOpenTcpConnections { get { return Connection.numberOfOpenTcpConnections; } } + + public BufferProvider BufferProvider { get; } + + public Uri ServerUri { get { return this.serverUri; } } + + public bool Healthy + { + get + { + this.ThrowIfDisposed(); + if (this.tcpClient == null) + { + return false; + } + + this.SnapshotConnectionTimestamps( + out DateTime lastSendAttempt, + out DateTime lastSend, + out DateTime lastReceive, + out DateTime? firstSendSinceLastReceive, + out long numberOfSendsSinceLastReceive); + + return this.healthChecker.IsHealthy( + currentTime: DateTime.UtcNow, + lastSendAttempt: lastSendAttempt, + lastSend: lastSend, + lastReceive: lastReceive, + firstSendSinceLastReceive: firstSendSinceLastReceive, + numberOfSendsSinceLastReceive: numberOfSendsSinceLastReceive, + socket: this.tcpClient.Client); + } + } + + public bool Disposed { get { return this.disposed; } } + + public Guid ConnectionCorrelationId { get => this.connectionCorrelationId; } + + public sealed class ResponseMetadata : IDisposable + { + private bool disposed; + + private BufferProvider.DisposableBuffer header; + private BufferProvider.DisposableBuffer metadata; + + public ResponseMetadata(BufferProvider.DisposableBuffer header, BufferProvider.DisposableBuffer metadata) + { + this.header = header; + this.metadata = metadata; + this.disposed = false; + } + + public ArraySegment Header => this.header.Buffer; + public ArraySegment Metadata => this.metadata.Buffer; + + /// + public void Dispose() + { + if (!this.disposed) + { + this.header.Dispose(); + this.metadata.Dispose(); + this.disposed = true; + } + } + } + + public async Task OpenAsync(ChannelOpenArguments args) + { + this.ThrowIfDisposed(); + await this.OpenSocketAsync(args); + await this.NegotiateSslAsync(args); + } + + // This method is thread safe. + public async Task WriteRequestAsync(ChannelCommonArguments args, + TransportSerialization.SerializedRequest messagePayload, + TransportRequestStats transportRequestStats) + { + this.ThrowIfDisposed(); + + if (transportRequestStats != null) + { + this.SnapshotConnectionTimestamps( + out DateTime lastSendAttempt, + out DateTime lastSend, + out DateTime lastReceive, + out DateTime? firstSendSinceLastReceive, + out long numberOfSendsSinceLastReceive); + transportRequestStats.ConnectionLastSendAttemptTime = lastSendAttempt; + transportRequestStats.ConnectionLastSendTime = lastSend; + transportRequestStats.ConnectionLastReceiveTime = lastReceive; + } + + args.SetTimeoutCode(TransportErrorCode.SendLockTimeout); + await this.writeSemaphore.WaitAsync(); + try + { + args.SetTimeoutCode(TransportErrorCode.SendTimeout); + args.SetPayloadSent(); + this.UpdateLastSendAttemptTime(); + await messagePayload.CopyToStreamAsync(this.stream); + } + finally + { + this.writeSemaphore.Release(); + } + this.UpdateLastSendTime(); + // Do not update the last receive timestamp here. The fact that sending + // the request succeeded means nothing until the response comes back. + } + + // This method is not thread safe. ReadResponseMetadataAsync and + // ReadResponseBodyAsync must be called in sequence, from a single thread. + [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] + public async Task ReadResponseMetadataAsync(ChannelCommonArguments args) + { + this.ThrowIfDisposed(); + + Trace.CorrelationManager.ActivityId = args.ActivityId; + int metadataHeaderLength = sizeof(UInt32) /* totalLength */ + sizeof(UInt32) /* status */ + + 16; + BufferProvider.DisposableBuffer header = this.BufferProvider.GetBuffer(metadataHeaderLength); + await this.ReadPayloadAsync(header.Buffer.Array, metadataHeaderLength /* sizeof(Guid) */, "header", args); + + UInt32 totalLength = BitConverter.ToUInt32(header.Buffer.Array, 0); + if (totalLength > Connection.ResponseLengthByteLimit) + { + header.Dispose(); + DefaultTrace.TraceCritical("[RNTBD Connection {0}] RNTBD header length says {1} but expected at most {2} bytes. Connection: {3}", + this.connectionCorrelationId, totalLength, Connection.ResponseLengthByteLimit, this); + throw TransportExceptions.GetInternalServerErrorException( + this.serverUri, + string.Format( + CultureInfo.CurrentUICulture, + RMResources.ServerResponseHeaderTooLargeError, + totalLength, this)); + } + + if (totalLength < metadataHeaderLength) + { + DefaultTrace.TraceCritical( + "[RNTBD Connection {0}] Invalid RNTBD header length {1} bytes. Expected at least {2} bytes. Connection: {3}", + this.connectionCorrelationId, totalLength, metadataHeaderLength, this); + throw TransportExceptions.GetInternalServerErrorException( + this.serverUri, + string.Format( + CultureInfo.CurrentUICulture, + RMResources.ServerResponseInvalidHeaderLengthError, + metadataHeaderLength, totalLength, this)); + } + + int metadataLength = (int)totalLength - metadataHeaderLength; + BufferProvider.DisposableBuffer metadata = this.BufferProvider.GetBuffer(metadataLength); + await this.ReadPayloadAsync(metadata.Buffer.Array, metadataLength, "metadata", args); + return new ResponseMetadata(header, metadata); + } + + // This method is not thread safe. ReadResponseMetadataAsync and + // ReadResponseBodyAsync must be called in sequence, from a single thread. + public async Task ReadResponseBodyAsync(ChannelCommonArguments args) + { + this.ThrowIfDisposed(); + + Trace.CorrelationManager.ActivityId = args.ActivityId; + using BufferProvider.DisposableBuffer bodyLengthHeader = this.BufferProvider.GetBuffer(sizeof(uint)); + await this.ReadPayloadAsync(bodyLengthHeader.Buffer.Array, sizeof(uint), + "body length header", args); + + uint length = BitConverter.ToUInt32(bodyLengthHeader.Buffer.Array, 0); + // This check can also validate "length" against the expected total + // response size. + if (length > Connection.ResponseLengthByteLimit) + { + DefaultTrace.TraceCritical("[RNTBD Connection {0}] Invalid RNTBD response body length {1} bytes. Connection: {2}", this.connectionCorrelationId, length, this); + throw TransportExceptions.GetInternalServerErrorException( + this.serverUri, + string.Format( + CultureInfo.CurrentUICulture, + RMResources.ServerResponseBodyTooLargeError, + length, this)); + } + + MemoryStream memoryStream = null; + if (this.memoryStreamPool?.TryGetMemoryStream((int)length, out memoryStream) ?? false) + { + await this.ReadPayloadAsync(memoryStream, (int)length, "body", args); + memoryStream.Position = 0; + return memoryStream; + } + else + { + byte[] body = new byte[length]; + await this.ReadPayloadAsync(body, (int)length, "body", args); + return StreamExtension.CreateExportableMemoryStream(body); + } + } + + public override string ToString() + { + lock (this.nameLock) + { + return this.name; + } + } + + public void Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + + string connectionTimestampsText = this.GetConnectionTimestampsText(); + if (this.tcpClient != null) + { + Debug.Assert(this.tcpClient.Client != null); + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] Disposing RNTBD connection {1} -> {2} to server {3}. {4}", + this.connectionCorrelationId, + this.localEndPoint, + this.remoteEndPoint, + this.serverUri, connectionTimestampsText); + string newName = string.Format( + CultureInfo.InvariantCulture, + " {0} -> {1}", + this.localEndPoint, + this.remoteEndPoint); + lock (this.nameLock) + { + this.name = newName; + } + } + else + { + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] Disposing unused RNTBD connection to server {1}. {2}", + this.connectionCorrelationId, this.serverUri, connectionTimestampsText); + } + + if (this.tcpClient != null) + { + if (this.portPool != null) + { + this.portPool.RemoveReference(this.localEndPoint.AddressFamily, checked((ushort)this.localEndPoint.Port)); + } + this.tcpClient.Close(); + + Interlocked.Decrement(ref Connection.numberOfOpenTcpConnections); + + this.tcpClient = null; + Debug.Assert(this.stream != null); + this.stream.Close(); + this.streamReader?.Dispose(); + TransportClient.GetTransportPerformanceCounters().IncrementRntbdConnectionClosedCount(); + } + } + + // Returns (true, timeToIdle) for active connections and (false, idleTimeout) + // for idle connections. + // timeToIdle is the minimum amount of time that will pass until the + // connection might become idle. + public bool IsActive(out TimeSpan timeToIdle) + { + this.ThrowIfDisposed(); + + // IsActive should not be called if idle timeout is disabled + Debug.Assert(this.idleConnectionTimeout > TimeSpan.Zero); + + this.SnapshotConnectionTimestamps( + out DateTime lastSendAttempt, + out DateTime lastSend, + out DateTime lastReceive, + out DateTime? firstSendSinceLastReceive, + out long numberOfSendsSinceLastReceive); + DateTime now = DateTime.UtcNow; + + if (now - lastReceive > this.idleConnectionTimeout) + { + // idle + timeToIdle = this.idleConnectionClosureTimeout; + return false; + } + else + { + // 'not idle' guarantees lastReceiveTime is a non-default value. + Debug.Assert(lastReceive != DateTime.MinValue); + + timeToIdle = lastReceive + this.idleConnectionClosureTimeout - now; + + // 'not idle' guarantees 'now < lastReceive + idleConnectionTimeout', so that the new timeToIdle is guaranteed to be positive + Debug.Assert(timeToIdle > TimeSpan.Zero); + + return true; + } + } + + /// + /// Notify the connection health status by updating the transit timeout counters. + /// + /// A boolean flag indicating if the request is completed successfully. + /// An optional boolean flag indicating if the current operation is read-only in nature. + internal void NotifyConnectionStatus( + bool isCompleted, + bool isReadRequest = false) + { + this.healthChecker.UpdateTransitTimeoutCounters( + isCompleted, + isReadRequest); + } + + #region Test hook. + + internal TimeSpan TestIdleConnectionClosureTimeout => this.idleConnectionClosureTimeout; + internal void TestSetLastReceiveTime(DateTime lrt) + { + lock (this.timestampLock) + { + this.lastReceiveTime = lrt; + } + } + + #endregion + + private static uint GetUInt32FromEnvironmentVariableOrDefault( + string name, + uint minValue, + uint maxValue, + uint defaultValue) + { + string envVariableValueText = Environment.GetEnvironmentVariable(name); + + if (String.IsNullOrEmpty(envVariableValueText) || + !UInt32.TryParse( + envVariableValueText, + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out uint envVariableValue)) + { + return defaultValue; + } + + if (envVariableValue > maxValue || envVariableValue < minValue) + { + throw new ArgumentOutOfRangeException( + name, + $"Value for environment variable '{name}' is outside expected range of {minValue} - {maxValue}."); + } + + return envVariableValue; + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + Debug.Assert(this.serverUri != null); + throw new ObjectDisposedException( + string.Format("{0}:{1}", nameof(Connection), this.serverUri)); + } + } + + private async Task OpenSocketAsync(ChannelOpenArguments args) + { + if (this.tcpClient != null) + { + throw new InvalidOperationException( + $"Attempting to call Connection.OpenSocketAsync on an " + + $"already initialized connection {this}"); + } + + TcpClient tcpClient = null; + TransportErrorCode errorCode = TransportErrorCode.Unknown; + try + { + errorCode = TransportErrorCode.DnsResolutionFailed; + args.CommonArguments.SetTimeoutCode( + TransportErrorCode.DnsResolutionTimeout); + IPAddress address = await this.dnsResolutionFunction(this.serverUri.DnsSafeHost); + + errorCode = TransportErrorCode.ConnectFailed; + args.CommonArguments.SetTimeoutCode(TransportErrorCode.ConnectTimeout); + + this.UpdateLastSendAttemptTime(); + + DefaultTrace.TraceInformation("[RNTBD Connection {0}] Port reuse mode: {1}. Connection: {2}", this.connectionCorrelationId, args.PortReuseMode, this); + switch (args.PortReuseMode) + { + case PortReuseMode.ReuseUnicastPort: + tcpClient = await Connection.ConnectUnicastPortAsync(this.serverUri, address, this.connectionCorrelationId); + break; + + case PortReuseMode.PrivatePortPool: + Tuple result = await Connection.ConnectUserPortAsync(this.serverUri, address, args.PortPool, this.ToString(), this.connectionCorrelationId); + tcpClient = result.Item1; + bool portPoolUsed = result.Item2; + if (portPoolUsed) + { + Debug.Assert(this.portPool == null); + this.portPool = args.PortPool; + } + else + { + DefaultTrace.TraceInformation("[RNTBD Connection {0}] PrivatePortPool: Configured but actually not used. Connection: {1}", this.connectionCorrelationId, this); + } + + break; + + default: + throw new ArgumentException( + string.Format( + "Unsupported port reuse policy {0}", + args.PortReuseMode.ToString())); + } + + this.UpdateLastSendTime(); + this.UpdateLastReceiveTime(); + args.OpenTimeline.RecordConnectFinishTime(); + + DefaultTrace.TraceInformation("[RNTBD Connection {0}] RNTBD connection established {1} -> {2}", + this.connectionCorrelationId, tcpClient.Client.LocalEndPoint, tcpClient.Client.RemoteEndPoint); + TransportClient.GetTransportPerformanceCounters().IncrementRntbdConnectionEstablishedCount(); + string newName = string.Format( + CultureInfo.InvariantCulture, + "{0} -> {1}", + tcpClient.Client.LocalEndPoint, + tcpClient.Client.RemoteEndPoint); + lock (this.nameLock) + { + this.name = newName; + } + } + catch (Exception ex) + { + // Dispose the socket eagerly to avoid keeping the underlying + // handle around until finalization. + tcpClient?.Close(); + +#if NETFX + SocketException socketEx = ex as SocketException; + if (socketEx != null && socketEx.SocketErrorCode == SocketError.TimedOut) + { + if (PerfCounters.Counters.BackendConnectionOpenFailuresDueToSynRetransmitPerSecond != null) + { + PerfCounters.Counters.BackendConnectionOpenFailuresDueToSynRetransmitPerSecond.Increment(); + } + } +#endif + + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] Connection.OpenSocketAsync failed. Converting to TransportException. " + + "Connection: {1}. Inner exception: {2}", this.connectionCorrelationId, this, ex); + Debug.Assert(errorCode != TransportErrorCode.Unknown); + Debug.Assert(!args.CommonArguments.UserPayload); + Debug.Assert(!args.CommonArguments.PayloadSent); + throw new TransportException(errorCode, ex, + args.CommonArguments.ActivityId, this.serverUri, + this.ToString(), args.CommonArguments.UserPayload, + args.CommonArguments.PayloadSent); + } + + Debug.Assert(tcpClient != null); + this.localEndPoint = (IPEndPoint)tcpClient.Client.LocalEndPoint; + this.remoteEndPoint = (IPEndPoint)tcpClient.Client.RemoteEndPoint; + this.tcpClient = tcpClient; + this.stream = tcpClient.GetStream(); + + Interlocked.Increment(ref Connection.numberOfOpenTcpConnections); + + // Per MSDN, "The Blocking property has no effect on asynchronous methods" + // (https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.socket.blocking), + // but we also try to get the health status of the socket with a + // non-blocking, zero-byte Send. + this.tcpClient.Client.Blocking = false; + } + + private async Task NegotiateSslAsync(ChannelOpenArguments args) + { + string host = this.hostNameCertificateOverride ?? this.serverUri.DnsSafeHost; + Debug.Assert(this.stream != null); + SslStream sslStream = new SslStream(this.stream, leaveInnerStreamOpen: false, userCertificateValidationCallback: this.remoteCertificateValidationCallback); + try + { + args.CommonArguments.SetTimeoutCode( + TransportErrorCode.SslNegotiationTimeout); + this.UpdateLastSendAttemptTime(); + + await sslStream.AuthenticateAsClientAsync(host, clientCertificates: null, + enabledSslProtocols: Connection.TlsProtocols, checkCertificateRevocation: false); + + this.UpdateLastSendTime(); + this.UpdateLastReceiveTime(); + args.OpenTimeline.RecordSslHandshakeFinishTime(); + + this.stream = sslStream; + this.streamReader = new RntbdStreamReader(this.stream); + Debug.Assert(this.tcpClient != null); + DefaultTrace.TraceInformation("[RNTBD Connection {0}] SSL handshake complete {1} -> {2}", + this.connectionCorrelationId, this.localEndPoint, this.remoteEndPoint); + } + catch (Exception ex) + { + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] Connection.NegotiateSslAsync failed. Converting to TransportException. " + + "Connection: {1}. Inner exception: {2}", this.connectionCorrelationId, this, ex); + Debug.Assert(!args.CommonArguments.UserPayload); + Debug.Assert(!args.CommonArguments.PayloadSent); + throw new TransportException( + TransportErrorCode.SslNegotiationFailed, ex, + args.CommonArguments.ActivityId, this.serverUri, + this.ToString(), args.CommonArguments.UserPayload, + args.CommonArguments.PayloadSent); + } + } + + private async Task ReadPayloadAsync( + byte[] payload, + int length, + string type, + ChannelCommonArguments args) + { + Debug.Assert(length > 0); + Debug.Assert(length <= Connection.ResponseLengthByteLimit); + int bytesRead = 0; + while (bytesRead < length) + { + int read = 0; + try + { + read = await this.streamReader.ReadAsync(payload, bytesRead, + length - bytesRead); + } + catch (IOException ex) + { + this.TraceAndThrowReceiveFailedException(ex, type, args); + } + + if (read == 0) + { + this.TraceAndThrowEndOfStream(type, args); + } + this.UpdateLastReceiveTime(); + bytesRead += read; + } + Debug.Assert(bytesRead == length); + Debug.Assert(length <= payload.Length); + } + + + private async Task ReadPayloadAsync( + MemoryStream payload, + int length, + string type, + ChannelCommonArguments args) + { + Debug.Assert(length > 0); + Debug.Assert(length <= Connection.ResponseLengthByteLimit); + int bytesRead = 0; + while (bytesRead < length) + { + int read = 0; + try + { + read = await this.streamReader.ReadAsync(payload, length - bytesRead); + } + catch (IOException ex) + { + this.TraceAndThrowReceiveFailedException(ex, type, args); + } + + if (read == 0) + { + this.TraceAndThrowEndOfStream(type, args); + } + this.UpdateLastReceiveTime(); + bytesRead += read; + } + Debug.Assert(bytesRead == length); + Debug.Assert(length <= payload.Length); + } + + private void TraceAndThrowReceiveFailedException(IOException e, string type, ChannelCommonArguments args) + { + DefaultTrace.TraceError( + "[RNTBD Connection {0}] Hit IOException {1} with HResult {2} while reading {3} on connection {4}. {5}", + this.connectionCorrelationId, + e.Message, + e.HResult, + type, + this, + this.GetConnectionTimestampsText()); + throw new TransportException( + TransportErrorCode.ReceiveFailed, e, args.ActivityId, + this.serverUri, this.ToString(), args.UserPayload, true); + } + + private void TraceAndThrowEndOfStream(string type, ChannelCommonArguments args) + { + DefaultTrace.TraceError( + "[RNTBD Connection {0}] Reached end of stream. Read 0 bytes while reading {1} " + + "on connection {2}. {3}", + this.connectionCorrelationId, type, this, this.GetConnectionTimestampsText()); + throw new TransportException( + TransportErrorCode.ReceiveStreamClosed, null, + args.ActivityId, this.serverUri, this.ToString(), + args.UserPayload, true); + } + + /// + /// Helper method to snapshot the connection timestamps. + /// + /// A field containing the last send attempt time. + /// A field containing the last send time. + /// A field containing the last receive time. + /// A field containing the first send since last receive time. + /// A long integer field containing the number of sends since last receive time. + private void SnapshotConnectionTimestamps( + out DateTime lastSendAttempt, + out DateTime lastSend, + out DateTime lastReceive, + out DateTime? firstSendSinceLastReceive, + out long numberOfSendsSinceLastReceive) + { + Debug.Assert(!Monitor.IsEntered(this.timestampLock)); + lock (this.timestampLock) + { + lastSendAttempt = this.lastSendAttemptTime; + lastSend = this.lastSendTime; + lastReceive = this.lastReceiveTime; + firstSendSinceLastReceive = + this.lastReceiveTime < this.firstSendSinceLastReceive ? this.firstSendSinceLastReceive : null; + numberOfSendsSinceLastReceive = this.numberOfSendsSinceLastReceive; + } + } + + private string GetConnectionTimestampsText() + { + this.SnapshotConnectionTimestamps( + out DateTime lastSendAttempt, + out DateTime lastSend, + out DateTime lastReceive, + out DateTime? firstSendSinceLastReceive, + out long numberOfSendsSinceLastReceive); + return string.Format( + CultureInfo.InvariantCulture, + "Last send attempt time: {0:o}. Last send time: {1:o}. " + + "Last receive time: {2:o}. First sends since last receieve: {3:o}. " + + "# of sends since last receive: {4}", + lastSendAttempt, lastSend, lastReceive, firstSendSinceLastReceive, numberOfSendsSinceLastReceive); + } + + private void UpdateLastSendAttemptTime() + { + Debug.Assert(!Monitor.IsEntered(this.timestampLock)); + lock (this.timestampLock) + { + this.lastSendAttemptTime = DateTime.UtcNow; + } + } + + private void UpdateLastSendTime() + { + Debug.Assert(!Monitor.IsEntered(this.timestampLock)); + lock (this.timestampLock) + { + this.lastSendTime = DateTime.UtcNow; + + if (this.numberOfSendsSinceLastReceive++ == 0) + { + this.firstSendSinceLastReceive = this.lastSendTime; + } + } + } + + private void UpdateLastReceiveTime() + { + Debug.Assert(!Monitor.IsEntered(this.timestampLock)); + lock (this.timestampLock) + { + this.numberOfSendsSinceLastReceive = 0; + this.lastReceiveTime = DateTime.UtcNow; + } + } + + private static async Task ConnectUnicastPortAsync(Uri serverUri, IPAddress resolvedAddress, Guid connectionCorrelationId) + { + TcpClient tcpClient = new TcpClient(resolvedAddress.AddressFamily); + + Connection.SetCommonSocketOptions(tcpClient.Client, connectionCorrelationId); + + Connection.SetReuseUnicastPort(tcpClient.Client, connectionCorrelationId); + + DefaultTrace.TraceInformation("[RNTBD Connection {0}] {1} connecting to {2} (address {3})", + connectionCorrelationId, nameof(ConnectUnicastPortAsync), serverUri, resolvedAddress); + + await tcpClient.ConnectAsync(resolvedAddress, serverUri.Port); + + return tcpClient; + } + + private static async Task> ConnectReuseAddrAsync( + Uri serverUri, IPAddress address, ushort candidatePort, Guid connectionCorrelationId) + { + TcpClient candidateClient = new TcpClient(address.AddressFamily); + TcpClient client = null; + try + { + Connection.SetCommonSocketOptions(candidateClient.Client, connectionCorrelationId); + + candidateClient.Client.SetSocketOption( + SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + + EndPoint bindEndpoint = null; + switch (address.AddressFamily) + { + case AddressFamily.InterNetwork: + bindEndpoint = new IPEndPoint(IPAddress.Any, candidatePort); + break; + + case AddressFamily.InterNetworkV6: + bindEndpoint = new IPEndPoint(IPAddress.IPv6Any, candidatePort); + break; + + default: + throw new NotSupportedException( + string.Format( + CultureInfo.InvariantCulture, + "Address family {0} not supported", + address.AddressFamily)); + } + + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] RNTBD: {1} binding local endpoint {2}", + connectionCorrelationId, nameof(ConnectReuseAddrAsync), bindEndpoint); + + try + { + Debug.Assert(bindEndpoint != null); + candidateClient.Client.Bind(bindEndpoint); + } + catch (SocketException e) + { + if (e.SocketErrorCode == SocketError.AccessDenied) + { + Debug.Assert(candidateClient != null); + return Tuple.Create(null, false); + } + else + { + throw; + } + } + + DefaultTrace.TraceInformation("[RNTBD Connection {0}] {1} connecting to {2} (address {3})", + connectionCorrelationId, nameof(ConnectReuseAddrAsync), serverUri, address); + + try + { + await candidateClient.ConnectAsync(address, serverUri.Port); + } + catch (SocketException e) + { + if (e.SocketErrorCode == SocketError.AddressAlreadyInUse) + { + return Tuple.Create(null, true); + } + else + { + throw; + } + } + + client = candidateClient; + candidateClient = null; + } + finally + { + if (candidateClient != null) + { + Debug.Assert(client == null); + candidateClient.Close(); + } + } + Debug.Assert(candidateClient == null); + return Tuple.Create(client, true); + } + + private static async Task> ConnectUserPortAsync( + Uri serverUri, IPAddress address, UserPortPool portPool, string connectionName, Guid connectionCorrelationId) + { + ushort[] candidatePorts = portPool.GetCandidatePorts(address.AddressFamily); + if (candidatePorts != null) + { + foreach (ushort candidatePort in candidatePorts) + { + Debug.Assert(candidatePort != 0); + Tuple result = + await Connection.ConnectReuseAddrAsync( + serverUri, address, candidatePort, connectionCorrelationId); + TcpClient portReuseClient = result.Item1; + bool portUsable = result.Item2; + if (portReuseClient != null) + { + ushort localPort = checked((ushort)((IPEndPoint)portReuseClient.Client.LocalEndPoint).Port); + Debug.Assert(localPort == candidatePort); + portPool.AddReference( + address.AddressFamily, localPort); + return Tuple.Create(portReuseClient, true); + } + if (!portUsable) + { + portPool.MarkUnusable(address.AddressFamily, candidatePort); + } + } + + DefaultTrace.TraceInformation("[RNTBD Connection {0}] PrivatePortPool: All {1} candidate ports have been tried but none connects. Connection: {2}", connectionCorrelationId, candidatePorts.Length, connectionName); + } + + Tuple wildcardResult = await Connection.ConnectReuseAddrAsync(serverUri, address, 0, connectionCorrelationId); + TcpClient wildcardClient = wildcardResult.Item1; + if (wildcardClient != null) + { + portPool.AddReference( + address.AddressFamily, + checked((ushort)((IPEndPoint)wildcardClient.Client.LocalEndPoint).Port)); + return Tuple.Create(wildcardClient, true); + } + + DefaultTrace.TraceInformation( + "[RNTBD Connection {0}] PrivatePortPool: Not enough reusable ports in the system or pool. Have to connect unicast port. Pool status: {1}. Connection: {2}", + connectionCorrelationId, portPool.DumpStatus(), connectionName); + return Tuple.Create(await Connection.ConnectUnicastPortAsync(serverUri, address, connectionCorrelationId), false); + } + + /// + /// Wrapper method for that allows IPv6 addresses. + /// Used unless internal clients provide a version that might override decision to use IPv6 addresses. + /// + /// + /// + private static Task ResolveHostIncludingIPv6AddressesAsync(string hostName) => Connection.ResolveHostAsync(hostName, includeIPv6Addresses: true); + + internal static async Task ResolveHostAsync(string hostName, bool includeIPv6Addresses) + { + // Using Linq for a cold path + IPAddress[] serverAddresses = await Dns.GetHostAddressesAsync(hostName); + int serverAddressesCount = serverAddresses.Length; + + if (!includeIPv6Addresses) + { + // Exclude IPv6 addresses + serverAddressesCount = 0; + foreach (IPAddress ipAddress in serverAddresses) + { + if (ipAddress.AddressFamily == AddressFamily.InterNetwork) + { + serverAddresses[serverAddressesCount++] = ipAddress; + } + } + } + + int addressIndex = 0; + if (serverAddressesCount > 1) + { + addressIndex = Connection.rng.Value.Next(serverAddressesCount); + } + + if (serverAddressesCount == 0) + { + throw new ArgumentOutOfRangeException($"DNS Resolve resulted in no internet addresses. includeIPv6Addresses: {includeIPv6Addresses}"); + } + + return serverAddresses[addressIndex]; + } + + private static void SetCommonSocketOptions(Socket clientSocket, Guid connectionCorrelationId) + { + clientSocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true); + Connection.EnableTcpKeepAlive(clientSocket, connectionCorrelationId); + } + + private static void EnableTcpKeepAlive(Socket clientSocket, Guid connectionCorrelationId) + { + clientSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); + +#if !NETSTANDARD15 && !NETSTANDARD16 + // This code should use RuntimeInformation.IsOSPlatform(OSPlatform.Windows), + // but the feature is unavailable on .NET Framework 4.5.1. + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + try + { + clientSocket.IOControl( + IOControlCode.KeepAliveValues, + Connection.keepAliveConfiguration.Value, + null); + } + catch (Exception e) + { + DefaultTrace.TraceWarning("[RNTBD Connection {0}] IOControl(KeepAliveValues) failed: {1}", connectionCorrelationId, e); + // Ignore the exception. + } + } + else + { + Connection.SetKeepAliveSocketOptions(clientSocket); + } +#else + Connection.SetKeepAliveSocketOptions(clientSocket); +#endif + } + + private static void SetKeepAliveSocketOptions(Socket clientSocket) + { + if (Connection.isKeepAliveCustomizationSupported.Value) + { + //SocketOptionName.TcpKeepAliveInterval + clientSocket.SetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue, + SocketOptionTcpKeepAliveInterval); + + //SocketOptionName.TcpKeepAliveTime + clientSocket.SetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue, + SocketOptionTcpKeepAliveTime); + } +#if DEBUG + int tcpKeepAliveInterval = (int)clientSocket.GetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue); + int tcpKeepAliveTime = (int)clientSocket.GetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue); + Debug.Equals(tcpKeepAliveInterval, SocketOptionTcpKeepAliveInterval); + Debug.Equals(tcpKeepAliveTime, SocketOptionTcpKeepAliveTime); +#endif + } + + private static bool IsKeepAliveCustomizationSupported() + { + // Check to see if the SetSocketOptionsMethod does not throw + try + { + using (Socket dummySocket = new Socket(SocketType.Stream, ProtocolType.Tcp)) + { + dummySocket.SetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveIntervalSocketOptionEnumValue, + SocketOptionTcpKeepAliveInterval); + dummySocket.SetSocketOption(SocketOptionLevel.Tcp, + (SocketOptionName)TcpKeepAliveTimeSocketOptionEnumValue, + SocketOptionTcpKeepAliveTime); + return true; + } + } + catch + { + return false; + } + } + + private static byte[] GetWindowsKeepAliveConfiguration() + { + const uint EnableKeepAlive = 1; + const uint KeepAliveIntervalMs = 30 * 1000; + const uint KeepAliveRetryIntervalMs = 1 * 1000; + + // struct tcp_keepalive + // { + // u_long onoff; + // u_long keepalivetime; + // u_long keepaliveinterval; + // }; + byte[] keepAliveConfig = new byte[3 * sizeof(uint)]; + BitConverter.GetBytes(EnableKeepAlive).CopyTo(keepAliveConfig, 0); + BitConverter.GetBytes(KeepAliveIntervalMs).CopyTo(keepAliveConfig, sizeof(uint)); + BitConverter.GetBytes(KeepAliveRetryIntervalMs).CopyTo(keepAliveConfig, 2 * sizeof(uint)); + return keepAliveConfig; + } + + private static void SetReuseUnicastPort(Socket clientSocket, Guid connectionCorrelationId) + { +#if !NETSTANDARD15 && !NETSTANDARD16 + // This code should use RuntimeInformation.IsOSPlatform(OSPlatform.Windows), + // but the feature is unavailable on .NET Framework 4.5.1. + if (Environment.OSVersion.Platform == PlatformID.Win32NT) + { + try + { + Debug.Assert(!clientSocket.IsBound); + // SocketOptionName.ReuseUnicastPort is only present in .NET Framework 4.6.1 and newer. + // Use the numeric value for as long as this code needs to target earlier versions. + const int SO_REUSE_UNICASTPORT = 0x3007; + clientSocket.SetSocketOption(SocketOptionLevel.Socket, (SocketOptionName)SO_REUSE_UNICASTPORT, true); + } + catch (Exception e) + { + DefaultTrace.TraceWarning("[RNTBD Connection {0}] SetSocketOption(Socket, ReuseUnicastPort) failed: {1}", connectionCorrelationId, e); + // Ignore the exception. + } + } +#endif // !NETSTANDARD15 && !NETSTANDARD16 + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConnectionEvent.cs b/Microsoft.Azure.Cosmos/src/direct/ConnectionEvent.cs index 632aae2c29..44706be01f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConnectionEvent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConnectionEvent.cs @@ -1,11 +1,11 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal enum ConnectionEvent - { - ReadEof, - ReadFailure, - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal enum ConnectionEvent + { + ReadEof, + ReadFailure, + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ConnectionHealthChecker.cs b/Microsoft.Azure.Cosmos/src/direct/ConnectionHealthChecker.cs index 0978b8bbc0..85a7dea4ce 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConnectionHealthChecker.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConnectionHealthChecker.cs @@ -1,568 +1,568 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.Net.Sockets; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Rntbd; - - /// - /// ConnectionHealthChecker is responsible to validate a connection health. - /// - internal sealed class ConnectionHealthChecker - { - /// - /// A constant integer defining the limit for minimum number of sends since last receive. The default value is 3. - /// - private const int MinNumberOfSendsSinceLastReceiveForUnhealthyConnection = 3; - - /// - /// A boolean field indicating if the aggressive timeout detection is enabled. - /// - private const bool AggressiveTimeoutDetectionEnabledDefaultValue = false; - - /// - /// A constant integer defining the default value for aggressive timeout detection time limit in seconds. - /// - private const int TimeoutDetectionTimeLimitDefaultValueInSeconds = 60; - - /// - /// A contant integer defining the default value for the timeout detection threshold on the write path. - /// - private const int TimeoutDetectionOnWriteThresholdDefaultValue = 1; - - /// - /// A constant integer defining the default value for the timeout detection time limit in seconds on the write path. - /// - private const int TimeoutDetectionOnWriteTimeLimitDefaultValueInSeconds = 6; - - /// - /// A constant integer defining the default value for the timeout detection threshold on the high frequency path. - /// - private const int TimeoutDetectionOnHighFrequencyThresholdDefaultValue = 3; - - /// - /// A constant integer defining the default value for the timeout detection time limit in seconds on the high frequency path. - /// - private const int TimeoutDetectionOnHighFrequencyTimeLimitDefaultValueInSeconds = 10; - - /// - /// A constant integer defining the default value for the CPU utilization threshold to skip the aggressive timeout validation. - /// - private const int TimeoutDetectionDisabledOnCPUThresholdDefaultValue = 90; - - /// - /// A read-only containing the cpu usage cache eviction time in seconds. The default value is 10 seconds. - /// - private static readonly TimeSpan TimeoutDetectionCPUUsageCacheEvictionTimeInSeconds = TimeSpan.FromSeconds(10.0); - - /// - /// A read-only containing the send hang grace period. The connection should not - /// declare itself unhealthy if a send was attempted very recently. As such, ignore (lastSendAttemptTime - lastSendTime) - /// gaps lower than sendHangGracePeriod. The grace period should be large enough to accommodate slow sends. - /// In effect, a setting of 2s requires the client to be able to send data at least at 1 MB/s for 2 MB documents. - /// The default value is 2 seconds. - /// - private static readonly TimeSpan sendHangGracePeriod = TimeSpan.FromSeconds(2.0); - - /// - /// A read-only containing the receive hang grace period. The connection should not declare - /// itself unhealthy if a send succeeded very recently. As such, ignore (lastSendTime - lastReceiveTime) gaps lower - /// than receiveHangGracePeriod. The grace period should be large enough to accommodate the round trip time of the - /// slowest server request. Assuming 1s of network RTT, a 2 MB request, a 2 MB response, a connection that can sustain - /// 1 MB/s both ways, and a 5-second deadline at the server, 10 seconds should be enough. The default value is 10 seconds. - /// - private static readonly TimeSpan receiveHangGracePeriod = TimeSpan.FromSeconds(10.0); - - /// - /// A read-only containing the recent receive window time limit. The default value is 1 second. - /// - private static readonly TimeSpan recentReceiveWindow = TimeSpan.FromSeconds(1.0); - - /// - /// A read-only byte array of one byte to validate a socket opening. - /// - private static readonly byte[] healthCheckBuffer = new byte[1]; - - /// - /// A read-only containing the receive delay limit. The connection will declare itself unhealthy if the - /// (lastSendTime - lastReceiveTime) gap grows beyond this value. receiveDelayLimit must be greater than receiveHangGracePeriod. - /// - private readonly TimeSpan receiveDelayLimit; - - /// - /// A read-only containing the send delay limit. The connection will declare itself unhealthy if the - /// (lastSendAttemptTime - lastSendTime) gap grows beyond this value. sendDelayLimit must be greater than sendHangGracePeriod. - /// - private readonly TimeSpan sendDelayLimit; - - /// - /// A read-only containing the connection idle timeout. - /// - private readonly TimeSpan idleConnectionTimeout; - - /// - /// A boolean field indicating if the aggressive timeout detection is enabled. - /// - private readonly bool aggressiveTimeoutDetectionEnabled; - - /// - /// A read-only containing the timeout detection time limit. - /// - private readonly TimeSpan timeoutDetectionTimeLimit; - - /// - /// A read-only integer containing the timeout detection threshold for write operations. - /// - private readonly int timeoutDetectionOnWriteThreshold; - - /// - /// A read-only containing the timeout detection on write timeout. - /// - private readonly TimeSpan timeoutDetectionOnWriteTimeLimit; - - /// - /// A read-only integer containing the timeout detection threshold for high frequency timeout occurences. - /// - private readonly int timeoutDetectionOnHighFrequencyThreshold; - - /// - /// A read-only containing the timeout detection on high frequency timeout. - /// - private readonly TimeSpan timeoutDetectionOnHighFrequencyTimeLimit; - - /// - /// A read-only double field containing the timeout detection threshold for CPU utilization. The timeout - /// detection feature will be disabled if the CPU utilization is below this threshold. - /// - private readonly double timeoutDetectionDisableCPUThreshold; - - /// - /// A read-only instance of . - /// - private readonly SystemUtilizationReaderBase systemUtilizationReader; - - /// - /// An integer containing the number of transit timeouts that occurred on the read path. This - /// counter is updated atomically and resets to 0 when the connection is declared healthy. - /// - private int transitTimeoutOnReadCounter; - - /// - /// An integer containing the number of transit timeouts that occurred on the write path. This - /// counter is updated atomically and resets to 0 when the connection is declared healthy. - /// - private int transitTimeoutOnWriteCounter; - - /// - /// Constructor to initialize a new instance of the . - /// - /// A containing the send delay limit. - /// A containing the receive delay limit. - /// A containing the connection idle timeout. - public ConnectionHealthChecker( - TimeSpan sendDelayLimit, - TimeSpan receiveDelayLimit, - TimeSpan idleConnectionTimeout) - { - if (receiveDelayLimit <= ConnectionHealthChecker.receiveHangGracePeriod) - { - throw new ArgumentOutOfRangeException( - nameof(receiveDelayLimit), - receiveDelayLimit, - string.Format( - CultureInfo.InvariantCulture, - "{0} must be greater than {1} ({2})", - nameof(receiveDelayLimit), - nameof(ConnectionHealthChecker.receiveHangGracePeriod), - ConnectionHealthChecker.receiveHangGracePeriod)); - } - if (sendDelayLimit <= ConnectionHealthChecker.sendHangGracePeriod) - { - throw new ArgumentOutOfRangeException( - nameof(sendDelayLimit), - sendDelayLimit, - string.Format( - CultureInfo.InvariantCulture, - "{0} must be greater than {1} ({2})", - nameof(sendDelayLimit), - nameof(ConnectionHealthChecker.sendHangGracePeriod), - ConnectionHealthChecker.sendHangGracePeriod)); - } - - this.sendDelayLimit = sendDelayLimit; - this.receiveDelayLimit = receiveDelayLimit; - this.idleConnectionTimeout = idleConnectionTimeout; - this.transitTimeoutOnWriteCounter = 0; - this.transitTimeoutOnReadCounter = 0; - this.aggressiveTimeoutDetectionEnabled = Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.AggressiveTimeoutDetectionEnabled, - defaultValue: ConnectionHealthChecker.AggressiveTimeoutDetectionEnabledDefaultValue); - - // The below variables are required only when transit timeout detection is enabled. - if (this.aggressiveTimeoutDetectionEnabled) - { - this.systemUtilizationReader = SystemUtilizationReaderBase.SingletonInstance; - this.timeoutDetectionTimeLimit = TimeSpan.FromSeconds( - Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionTimeLimit, - defaultValue: ConnectionHealthChecker.TimeoutDetectionTimeLimitDefaultValueInSeconds)); - - this.timeoutDetectionOnWriteThreshold = Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionOnWriteThreshold, - defaultValue: ConnectionHealthChecker.TimeoutDetectionOnWriteThresholdDefaultValue); - - this.timeoutDetectionOnWriteTimeLimit = TimeSpan.FromSeconds( - Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionOnWriteTimeLimit, - defaultValue: ConnectionHealthChecker.TimeoutDetectionOnWriteTimeLimitDefaultValueInSeconds)); - - this.timeoutDetectionOnHighFrequencyThreshold = Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionOnHighFrequencyThreshold, - defaultValue: ConnectionHealthChecker.TimeoutDetectionOnHighFrequencyThresholdDefaultValue); - - this.timeoutDetectionOnHighFrequencyTimeLimit = TimeSpan.FromSeconds( - Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionOnHighFrequencyTimeLimit, - defaultValue: ConnectionHealthChecker.TimeoutDetectionOnHighFrequencyTimeLimitDefaultValueInSeconds)); - - this.timeoutDetectionDisableCPUThreshold = Helpers.GetEnvironmentVariable( - name: Constants.EnvironmentVariables.TimeoutDetectionDisabledOnCPUThreshold, - defaultValue: ConnectionHealthChecker.TimeoutDetectionDisabledOnCPUThresholdDefaultValue); - } - } - - /// - /// Validates if a connection is in healthy state and returns a boolean flag to indicate the same. - /// - /// An instance of containing the snapshot of current time. - /// An instance of containing the snapshot of last send attempt time. - /// An instance of containing the snapshot of last send time. - /// An instance of containing the snapshot of last receive time. - /// An instance of containing the snapshot of last send since first receive time. - /// An integer containing the snapshot of number of sends since last receive. - /// An instance of . - /// A boolean flag indicating if the connection is healthy. - public bool IsHealthy( - DateTime currentTime, - DateTime lastSendAttempt, - DateTime lastSend, - DateTime lastReceive, - DateTime? firstSendSinceLastReceive, - long numberOfSendsSinceLastReceive, - Socket socket) - { - // Assume that the connection is healthy if data was received - // recently. - if (ConnectionHealthChecker.IsDataReceivedRecently( - currentTime: currentTime, - lastReceiveTime: lastReceive)) - { - return true; - } - - if (this.IsBlackholeDetected( - currentTime: currentTime, - lastSendAttempt: lastSendAttempt, - lastSend: lastSend, - lastReceive: lastReceive, - firstSendSinceLastReceive: firstSendSinceLastReceive, - numberOfSendsSinceLastReceive: numberOfSendsSinceLastReceive)) - { - return false; - } - - if (this.IsConnectionIdled( - currentTime: currentTime, - lastReceive: lastReceive)) - { - return false; - } - - if (this.IsTransitTimeoutsDetected( - currentTime: currentTime, - lastReceiveTime: lastReceive)) - { - return false; - } - - // See https://aka.ms/zero-byte-send. - // Socket.Send is expensive. Keep this operation last in the chain - return ConnectionHealthChecker.IsSocketConnectionEstablished( - socket: socket); - } - - /// - /// Updates the transit timeout counters by incrementing or resetting them based on the given boolean flags. - /// - /// A boolean flag indicating if the request is completed successfully. - /// A boolean flag indicating if the current operation is read-only in nature. - internal void UpdateTransitTimeoutCounters( - bool isCompleted, - bool isReadReqeust) - { - if (isCompleted) - { - // Resets the transit timeout counters atomically. - this.ResetTransitTimeoutCounters(); - } - else - { - // Increments the transit timeout counters atomically based on the request type. - if (isReadReqeust) - { - this.IncrementTransitTimeoutOnReadCounter(); - } - else - { - this.IncrementTransitTimeoutOnWriteCounter(); - } - } - } - - /// - /// Increments the transit timeout on write counters atomically. - /// - private void IncrementTransitTimeoutOnWriteCounter() - { - Interlocked.Increment(ref this.transitTimeoutOnWriteCounter); - } - - /// - /// Increments the transit timeout on read counters atomically. - /// - private void IncrementTransitTimeoutOnReadCounter() - { - Interlocked.Increment(ref this.transitTimeoutOnReadCounter); - } - - /// - /// Resets the transit timeout counters atomically. This method uses a interlocked exchange - /// to achieve atomicity. - /// - private void ResetTransitTimeoutCounters() - { - Interlocked.Exchange(ref this.transitTimeoutOnReadCounter, 0); - Interlocked.Exchange(ref this.transitTimeoutOnWriteCounter, 0); - } - - /// - /// Detects transit timeouts and returns a boolean flag to indicate the same. - /// - /// An instance of containing the snapshot of current time. - /// An instance of containing the snapshot of last read/ receive time. - /// A boolean flag indicating if a transit timeout was detected. - private bool IsTransitTimeoutsDetected( - DateTime currentTime, - DateTime lastReceiveTime) - { - if (!this.aggressiveTimeoutDetectionEnabled) - { - return false; - } - - this.SnapshotTransitTimeoutCounters( - out int totalTransitTimeoutCounter, - out int transitTimeoutOnWriteCounter); - - // Timeout detection is skipped when there are no timeouts detected on both read and write flow. - if(totalTransitTimeoutCounter == 0) - { - return false; - } - - // Read delay is the difference between the current time and last receive time. - TimeSpan readDelay = currentTime - lastReceiveTime; - - // The channel will be closed if all requests are failed due to transit timeout within the time limit. - // This helps to close channel faster for sparse workload. The default value for timeoutDetectionTimeLimit - // is 60 seconds. - if (totalTransitTimeoutCounter > 0 && readDelay >= this.timeoutDetectionTimeLimit) - { - DefaultTrace.TraceWarning( - $"Unhealthy RNTBD connection: Health check failed due to transit timeout detection time limit exceeded. " + - $"Last channel receive: {lastReceiveTime}. Timeout detection time limit: {this.timeoutDetectionTimeLimit}."); - return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); - } - - // Timeout detection in high frequency. The default values for the high frequency threshold and time limit are: - // timeoutDetectionHighFrequencyThreshold = 3. - // timeoutDetectionHighFrequencyTimeLimit = 10 seconds. - if (totalTransitTimeoutCounter >= this.timeoutDetectionOnHighFrequencyThreshold && - readDelay >= this.timeoutDetectionOnHighFrequencyTimeLimit) - { - DefaultTrace.TraceWarning( - "Unhealthy RNTBD connection: Health check failed due to transit timeout high frequency threshold hit. " + - $"Last channel receive: {lastReceiveTime}. Timeout counts: {totalTransitTimeoutCounter}. " + - $"Timeout detection high frequency threshold: {this.timeoutDetectionOnHighFrequencyThreshold}. Timeout detection high frequency time limit: {this.timeoutDetectionOnHighFrequencyTimeLimit}."); - return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); - } - - // Timeout detection for write operations. The default values for the write threshold and time limit are: - // timeoutDetectionOnWriteThreshold = 1. - // timeoutDetectionOnWriteTimeLimit = 6 seconds. - if (transitTimeoutOnWriteCounter >= this.timeoutDetectionOnWriteThreshold && - readDelay >= this.timeoutDetectionOnWriteTimeLimit) - { - DefaultTrace.TraceWarning( - "Unhealthy RNTBD connection: Health check failed due to transit timeout on write threshold hit: {0}. " + - $"Last channel receive: {lastReceiveTime}. Write timeout counts: {transitTimeoutOnWriteCounter}. " + - $"Timeout detection on write threshold: {this.timeoutDetectionOnWriteThreshold}. Timeout detection on write time limit: {this.timeoutDetectionOnWriteTimeLimit}."); - return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); - } - - return false; - } - - /// - /// Detects a black hole and returns a boolean flag to indicate the same. - /// - /// An instance of containing the snapshot of current time. - /// An instance of containing the snapshot of last send attempt time. - /// An instance of containing the snapshot of last send time. - /// An instance of containing the snapshot of last receive time. - /// An instance of containing the snapshot of last send since first receive time. - /// An integer containing the snapshot of number of sends since last receive. - /// A boolean flag indicating if a blackhole was detected. - private bool IsBlackholeDetected( - DateTime currentTime, - DateTime lastSendAttempt, - DateTime lastSend, - DateTime lastReceive, - DateTime? firstSendSinceLastReceive, - long numberOfSendsSinceLastReceive) - { - // Black hole detection, part 1: - // Treat the connection as unhealthy if the gap between the last - // attempted send and the last successful send grew beyond - // acceptable limits, unless a send was attempted very recently. - // This is a sign of a hung send(). - if ((lastSendAttempt - lastSend > this.sendDelayLimit) && - (currentTime - lastSendAttempt > ConnectionHealthChecker.sendHangGracePeriod)) - { - DefaultTrace.TraceWarning( - "Unhealthy RNTBD connection: Hung send: {0}. " + - "Last send attempt: {1:o}. Last send: {2:o}. " + - "Tolerance {3:c}"); - return true; - } - - // Black hole detection, part 2: - // Treat the connection as unhealthy if the gap between the last - // successful send and the last successful receive grew beyond - // acceptable limits, unless a send succeeded very recently and the number of - // outstanding receives is within reasonable limits. - if ((lastSend - lastReceive > this.receiveDelayLimit) && - ( - currentTime - lastSend > ConnectionHealthChecker.receiveHangGracePeriod || - ( - numberOfSendsSinceLastReceive >= ConnectionHealthChecker.MinNumberOfSendsSinceLastReceiveForUnhealthyConnection && - firstSendSinceLastReceive != null && - currentTime - firstSendSinceLastReceive > ConnectionHealthChecker.receiveHangGracePeriod - ) - )) - { - DefaultTrace.TraceWarning( - "Unhealthy RNTBD connection: Replies not getting back: {0}. " + - "Last send: {1:o}. Last receive: {2:o}. Tolerance: {3:c}. " + - "First send since last receieve: {4:o}. # of sends since last receive: {5}"); - return true; - } - - return false; - } - - /// - /// Detects if data was received recently and returns a boolean flag to indicate the same. - /// - /// An instance of containing the snapshot of current time. - /// An instance of containing the snapshot of last receive time. - /// A boolean flag indicating if data was received recently. - private static bool IsDataReceivedRecently( - DateTime currentTime, - DateTime lastReceiveTime) - { - return currentTime - lastReceiveTime < ConnectionHealthChecker.recentReceiveWindow; - } - - /// - /// Detects socket connectivity and returns a boolean flag to indicate the same. - /// - /// An instance of . - /// A boolean flag indicating if a socket connectivity was established. - private static bool IsSocketConnectionEstablished( - Socket socket) - { - try - { - if (socket == null || !socket.Connected) - { - return false; - } - Debug.Assert(!socket.Blocking); - socket.Send(ConnectionHealthChecker.healthCheckBuffer, 0, 0); - return true; - } - catch (SocketException e) - { - bool healthy = e.SocketErrorCode == SocketError.WouldBlock; - if (!healthy) - { - DefaultTrace.TraceWarning( - "Unhealthy RNTBD connection. Socket error code: {0}", - e.SocketErrorCode.ToString()); - } - return healthy; - } - catch (ObjectDisposedException) - { - return false; - } - } - - /// - /// Detects Idle Timeout and returns a boolean flag to indicate the same. - /// - /// An instance of containing the snapshot of current time. - /// An instance of containing the snapshot of last receive time. - /// A boolean flag indicating if a connection idle timeout was detected. - private bool IsConnectionIdled( - DateTime currentTime, - DateTime lastReceive) - { - // Validates if idle timeout is enabled and exceeds the idle timeout limit. - return this.idleConnectionTimeout > TimeSpan.Zero && currentTime - lastReceive > this.idleConnectionTimeout; - } - - /// - /// Transit timeouts can be a normal symptom under high CPU load. When request times out due to high CPU, - /// closing the existing the connection and re-establish a new one will not help the issue but rather make it worse. - /// Therefore, the timeout detection will be disabled in case the cpu utilization goes beyond the defined threshold. - /// - /// A boolean flag indicating if the CPU utilization is below the defined threshold. - private bool IsCpuUtilizationBelowDisableTimeoutDetectionThreshold() - { - return this.systemUtilizationReader.GetSystemWideCpuUsageCached( - cacheEvictionTimeInSeconds: ConnectionHealthChecker.TimeoutDetectionCPUUsageCacheEvictionTimeInSeconds) <= this.timeoutDetectionDisableCPUThreshold; - } - - /// - /// Helper method to snapshot the transit timeout counters. - /// - /// An integer that will contain the snapshot of total transit timeout counter. - /// An integer that will contain the snapshot of transit timeout on write counter. - private void SnapshotTransitTimeoutCounters( - out int totalTransitTimeoutCounter, - out int transitTimeoutOnWriteCounter) - { - totalTransitTimeoutCounter = this.transitTimeoutOnWriteCounter + this.transitTimeoutOnReadCounter; - transitTimeoutOnWriteCounter = this.transitTimeoutOnWriteCounter; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.Net.Sockets; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Rntbd; + + /// + /// ConnectionHealthChecker is responsible to validate a connection health. + /// + internal sealed class ConnectionHealthChecker + { + /// + /// A constant integer defining the limit for minimum number of sends since last receive. The default value is 3. + /// + private const int MinNumberOfSendsSinceLastReceiveForUnhealthyConnection = 3; + + /// + /// A boolean field indicating if the aggressive timeout detection is enabled. + /// + private const bool AggressiveTimeoutDetectionEnabledDefaultValue = false; + + /// + /// A constant integer defining the default value for aggressive timeout detection time limit in seconds. + /// + private const int TimeoutDetectionTimeLimitDefaultValueInSeconds = 60; + + /// + /// A contant integer defining the default value for the timeout detection threshold on the write path. + /// + private const int TimeoutDetectionOnWriteThresholdDefaultValue = 1; + + /// + /// A constant integer defining the default value for the timeout detection time limit in seconds on the write path. + /// + private const int TimeoutDetectionOnWriteTimeLimitDefaultValueInSeconds = 6; + + /// + /// A constant integer defining the default value for the timeout detection threshold on the high frequency path. + /// + private const int TimeoutDetectionOnHighFrequencyThresholdDefaultValue = 3; + + /// + /// A constant integer defining the default value for the timeout detection time limit in seconds on the high frequency path. + /// + private const int TimeoutDetectionOnHighFrequencyTimeLimitDefaultValueInSeconds = 10; + + /// + /// A constant integer defining the default value for the CPU utilization threshold to skip the aggressive timeout validation. + /// + private const int TimeoutDetectionDisabledOnCPUThresholdDefaultValue = 90; + + /// + /// A read-only containing the cpu usage cache eviction time in seconds. The default value is 10 seconds. + /// + private static readonly TimeSpan TimeoutDetectionCPUUsageCacheEvictionTimeInSeconds = TimeSpan.FromSeconds(10.0); + + /// + /// A read-only containing the send hang grace period. The connection should not + /// declare itself unhealthy if a send was attempted very recently. As such, ignore (lastSendAttemptTime - lastSendTime) + /// gaps lower than sendHangGracePeriod. The grace period should be large enough to accommodate slow sends. + /// In effect, a setting of 2s requires the client to be able to send data at least at 1 MB/s for 2 MB documents. + /// The default value is 2 seconds. + /// + private static readonly TimeSpan sendHangGracePeriod = TimeSpan.FromSeconds(2.0); + + /// + /// A read-only containing the receive hang grace period. The connection should not declare + /// itself unhealthy if a send succeeded very recently. As such, ignore (lastSendTime - lastReceiveTime) gaps lower + /// than receiveHangGracePeriod. The grace period should be large enough to accommodate the round trip time of the + /// slowest server request. Assuming 1s of network RTT, a 2 MB request, a 2 MB response, a connection that can sustain + /// 1 MB/s both ways, and a 5-second deadline at the server, 10 seconds should be enough. The default value is 10 seconds. + /// + private static readonly TimeSpan receiveHangGracePeriod = TimeSpan.FromSeconds(10.0); + + /// + /// A read-only containing the recent receive window time limit. The default value is 1 second. + /// + private static readonly TimeSpan recentReceiveWindow = TimeSpan.FromSeconds(1.0); + + /// + /// A read-only byte array of one byte to validate a socket opening. + /// + private static readonly byte[] healthCheckBuffer = new byte[1]; + + /// + /// A read-only containing the receive delay limit. The connection will declare itself unhealthy if the + /// (lastSendTime - lastReceiveTime) gap grows beyond this value. receiveDelayLimit must be greater than receiveHangGracePeriod. + /// + private readonly TimeSpan receiveDelayLimit; + + /// + /// A read-only containing the send delay limit. The connection will declare itself unhealthy if the + /// (lastSendAttemptTime - lastSendTime) gap grows beyond this value. sendDelayLimit must be greater than sendHangGracePeriod. + /// + private readonly TimeSpan sendDelayLimit; + + /// + /// A read-only containing the connection idle timeout. + /// + private readonly TimeSpan idleConnectionTimeout; + + /// + /// A boolean field indicating if the aggressive timeout detection is enabled. + /// + private readonly bool aggressiveTimeoutDetectionEnabled; + + /// + /// A read-only containing the timeout detection time limit. + /// + private readonly TimeSpan timeoutDetectionTimeLimit; + + /// + /// A read-only integer containing the timeout detection threshold for write operations. + /// + private readonly int timeoutDetectionOnWriteThreshold; + + /// + /// A read-only containing the timeout detection on write timeout. + /// + private readonly TimeSpan timeoutDetectionOnWriteTimeLimit; + + /// + /// A read-only integer containing the timeout detection threshold for high frequency timeout occurences. + /// + private readonly int timeoutDetectionOnHighFrequencyThreshold; + + /// + /// A read-only containing the timeout detection on high frequency timeout. + /// + private readonly TimeSpan timeoutDetectionOnHighFrequencyTimeLimit; + + /// + /// A read-only double field containing the timeout detection threshold for CPU utilization. The timeout + /// detection feature will be disabled if the CPU utilization is below this threshold. + /// + private readonly double timeoutDetectionDisableCPUThreshold; + + /// + /// A read-only instance of . + /// + private readonly SystemUtilizationReaderBase systemUtilizationReader; + + /// + /// An integer containing the number of transit timeouts that occurred on the read path. This + /// counter is updated atomically and resets to 0 when the connection is declared healthy. + /// + private int transitTimeoutOnReadCounter; + + /// + /// An integer containing the number of transit timeouts that occurred on the write path. This + /// counter is updated atomically and resets to 0 when the connection is declared healthy. + /// + private int transitTimeoutOnWriteCounter; + + /// + /// Constructor to initialize a new instance of the . + /// + /// A containing the send delay limit. + /// A containing the receive delay limit. + /// A containing the connection idle timeout. + public ConnectionHealthChecker( + TimeSpan sendDelayLimit, + TimeSpan receiveDelayLimit, + TimeSpan idleConnectionTimeout) + { + if (receiveDelayLimit <= ConnectionHealthChecker.receiveHangGracePeriod) + { + throw new ArgumentOutOfRangeException( + nameof(receiveDelayLimit), + receiveDelayLimit, + string.Format( + CultureInfo.InvariantCulture, + "{0} must be greater than {1} ({2})", + nameof(receiveDelayLimit), + nameof(ConnectionHealthChecker.receiveHangGracePeriod), + ConnectionHealthChecker.receiveHangGracePeriod)); + } + if (sendDelayLimit <= ConnectionHealthChecker.sendHangGracePeriod) + { + throw new ArgumentOutOfRangeException( + nameof(sendDelayLimit), + sendDelayLimit, + string.Format( + CultureInfo.InvariantCulture, + "{0} must be greater than {1} ({2})", + nameof(sendDelayLimit), + nameof(ConnectionHealthChecker.sendHangGracePeriod), + ConnectionHealthChecker.sendHangGracePeriod)); + } + + this.sendDelayLimit = sendDelayLimit; + this.receiveDelayLimit = receiveDelayLimit; + this.idleConnectionTimeout = idleConnectionTimeout; + this.transitTimeoutOnWriteCounter = 0; + this.transitTimeoutOnReadCounter = 0; + this.aggressiveTimeoutDetectionEnabled = Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.AggressiveTimeoutDetectionEnabled, + defaultValue: ConnectionHealthChecker.AggressiveTimeoutDetectionEnabledDefaultValue); + + // The below variables are required only when transit timeout detection is enabled. + if (this.aggressiveTimeoutDetectionEnabled) + { + this.systemUtilizationReader = SystemUtilizationReaderBase.SingletonInstance; + this.timeoutDetectionTimeLimit = TimeSpan.FromSeconds( + Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionTimeLimit, + defaultValue: ConnectionHealthChecker.TimeoutDetectionTimeLimitDefaultValueInSeconds)); + + this.timeoutDetectionOnWriteThreshold = Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionOnWriteThreshold, + defaultValue: ConnectionHealthChecker.TimeoutDetectionOnWriteThresholdDefaultValue); + + this.timeoutDetectionOnWriteTimeLimit = TimeSpan.FromSeconds( + Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionOnWriteTimeLimit, + defaultValue: ConnectionHealthChecker.TimeoutDetectionOnWriteTimeLimitDefaultValueInSeconds)); + + this.timeoutDetectionOnHighFrequencyThreshold = Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionOnHighFrequencyThreshold, + defaultValue: ConnectionHealthChecker.TimeoutDetectionOnHighFrequencyThresholdDefaultValue); + + this.timeoutDetectionOnHighFrequencyTimeLimit = TimeSpan.FromSeconds( + Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionOnHighFrequencyTimeLimit, + defaultValue: ConnectionHealthChecker.TimeoutDetectionOnHighFrequencyTimeLimitDefaultValueInSeconds)); + + this.timeoutDetectionDisableCPUThreshold = Helpers.GetEnvironmentVariable( + name: Constants.EnvironmentVariables.TimeoutDetectionDisabledOnCPUThreshold, + defaultValue: ConnectionHealthChecker.TimeoutDetectionDisabledOnCPUThresholdDefaultValue); + } + } + + /// + /// Validates if a connection is in healthy state and returns a boolean flag to indicate the same. + /// + /// An instance of containing the snapshot of current time. + /// An instance of containing the snapshot of last send attempt time. + /// An instance of containing the snapshot of last send time. + /// An instance of containing the snapshot of last receive time. + /// An instance of containing the snapshot of last send since first receive time. + /// An integer containing the snapshot of number of sends since last receive. + /// An instance of . + /// A boolean flag indicating if the connection is healthy. + public bool IsHealthy( + DateTime currentTime, + DateTime lastSendAttempt, + DateTime lastSend, + DateTime lastReceive, + DateTime? firstSendSinceLastReceive, + long numberOfSendsSinceLastReceive, + Socket socket) + { + // Assume that the connection is healthy if data was received + // recently. + if (ConnectionHealthChecker.IsDataReceivedRecently( + currentTime: currentTime, + lastReceiveTime: lastReceive)) + { + return true; + } + + if (this.IsBlackholeDetected( + currentTime: currentTime, + lastSendAttempt: lastSendAttempt, + lastSend: lastSend, + lastReceive: lastReceive, + firstSendSinceLastReceive: firstSendSinceLastReceive, + numberOfSendsSinceLastReceive: numberOfSendsSinceLastReceive)) + { + return false; + } + + if (this.IsConnectionIdled( + currentTime: currentTime, + lastReceive: lastReceive)) + { + return false; + } + + if (this.IsTransitTimeoutsDetected( + currentTime: currentTime, + lastReceiveTime: lastReceive)) + { + return false; + } + + // See https://aka.ms/zero-byte-send. + // Socket.Send is expensive. Keep this operation last in the chain + return ConnectionHealthChecker.IsSocketConnectionEstablished( + socket: socket); + } + + /// + /// Updates the transit timeout counters by incrementing or resetting them based on the given boolean flags. + /// + /// A boolean flag indicating if the request is completed successfully. + /// A boolean flag indicating if the current operation is read-only in nature. + internal void UpdateTransitTimeoutCounters( + bool isCompleted, + bool isReadReqeust) + { + if (isCompleted) + { + // Resets the transit timeout counters atomically. + this.ResetTransitTimeoutCounters(); + } + else + { + // Increments the transit timeout counters atomically based on the request type. + if (isReadReqeust) + { + this.IncrementTransitTimeoutOnReadCounter(); + } + else + { + this.IncrementTransitTimeoutOnWriteCounter(); + } + } + } + + /// + /// Increments the transit timeout on write counters atomically. + /// + private void IncrementTransitTimeoutOnWriteCounter() + { + Interlocked.Increment(ref this.transitTimeoutOnWriteCounter); + } + + /// + /// Increments the transit timeout on read counters atomically. + /// + private void IncrementTransitTimeoutOnReadCounter() + { + Interlocked.Increment(ref this.transitTimeoutOnReadCounter); + } + + /// + /// Resets the transit timeout counters atomically. This method uses a interlocked exchange + /// to achieve atomicity. + /// + private void ResetTransitTimeoutCounters() + { + Interlocked.Exchange(ref this.transitTimeoutOnReadCounter, 0); + Interlocked.Exchange(ref this.transitTimeoutOnWriteCounter, 0); + } + + /// + /// Detects transit timeouts and returns a boolean flag to indicate the same. + /// + /// An instance of containing the snapshot of current time. + /// An instance of containing the snapshot of last read/ receive time. + /// A boolean flag indicating if a transit timeout was detected. + private bool IsTransitTimeoutsDetected( + DateTime currentTime, + DateTime lastReceiveTime) + { + if (!this.aggressiveTimeoutDetectionEnabled) + { + return false; + } + + this.SnapshotTransitTimeoutCounters( + out int totalTransitTimeoutCounter, + out int transitTimeoutOnWriteCounter); + + // Timeout detection is skipped when there are no timeouts detected on both read and write flow. + if(totalTransitTimeoutCounter == 0) + { + return false; + } + + // Read delay is the difference between the current time and last receive time. + TimeSpan readDelay = currentTime - lastReceiveTime; + + // The channel will be closed if all requests are failed due to transit timeout within the time limit. + // This helps to close channel faster for sparse workload. The default value for timeoutDetectionTimeLimit + // is 60 seconds. + if (totalTransitTimeoutCounter > 0 && readDelay >= this.timeoutDetectionTimeLimit) + { + DefaultTrace.TraceWarning( + $"Unhealthy RNTBD connection: Health check failed due to transit timeout detection time limit exceeded. " + + $"Last channel receive: {lastReceiveTime}. Timeout detection time limit: {this.timeoutDetectionTimeLimit}."); + return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); + } + + // Timeout detection in high frequency. The default values for the high frequency threshold and time limit are: + // timeoutDetectionHighFrequencyThreshold = 3. + // timeoutDetectionHighFrequencyTimeLimit = 10 seconds. + if (totalTransitTimeoutCounter >= this.timeoutDetectionOnHighFrequencyThreshold && + readDelay >= this.timeoutDetectionOnHighFrequencyTimeLimit) + { + DefaultTrace.TraceWarning( + "Unhealthy RNTBD connection: Health check failed due to transit timeout high frequency threshold hit. " + + $"Last channel receive: {lastReceiveTime}. Timeout counts: {totalTransitTimeoutCounter}. " + + $"Timeout detection high frequency threshold: {this.timeoutDetectionOnHighFrequencyThreshold}. Timeout detection high frequency time limit: {this.timeoutDetectionOnHighFrequencyTimeLimit}."); + return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); + } + + // Timeout detection for write operations. The default values for the write threshold and time limit are: + // timeoutDetectionOnWriteThreshold = 1. + // timeoutDetectionOnWriteTimeLimit = 6 seconds. + if (transitTimeoutOnWriteCounter >= this.timeoutDetectionOnWriteThreshold && + readDelay >= this.timeoutDetectionOnWriteTimeLimit) + { + DefaultTrace.TraceWarning( + "Unhealthy RNTBD connection: Health check failed due to transit timeout on write threshold hit: {0}. " + + $"Last channel receive: {lastReceiveTime}. Write timeout counts: {transitTimeoutOnWriteCounter}. " + + $"Timeout detection on write threshold: {this.timeoutDetectionOnWriteThreshold}. Timeout detection on write time limit: {this.timeoutDetectionOnWriteTimeLimit}."); + return this.IsCpuUtilizationBelowDisableTimeoutDetectionThreshold(); + } + + return false; + } + + /// + /// Detects a black hole and returns a boolean flag to indicate the same. + /// + /// An instance of containing the snapshot of current time. + /// An instance of containing the snapshot of last send attempt time. + /// An instance of containing the snapshot of last send time. + /// An instance of containing the snapshot of last receive time. + /// An instance of containing the snapshot of last send since first receive time. + /// An integer containing the snapshot of number of sends since last receive. + /// A boolean flag indicating if a blackhole was detected. + private bool IsBlackholeDetected( + DateTime currentTime, + DateTime lastSendAttempt, + DateTime lastSend, + DateTime lastReceive, + DateTime? firstSendSinceLastReceive, + long numberOfSendsSinceLastReceive) + { + // Black hole detection, part 1: + // Treat the connection as unhealthy if the gap between the last + // attempted send and the last successful send grew beyond + // acceptable limits, unless a send was attempted very recently. + // This is a sign of a hung send(). + if ((lastSendAttempt - lastSend > this.sendDelayLimit) && + (currentTime - lastSendAttempt > ConnectionHealthChecker.sendHangGracePeriod)) + { + DefaultTrace.TraceWarning( + "Unhealthy RNTBD connection: Hung send: {0}. " + + "Last send attempt: {1:o}. Last send: {2:o}. " + + "Tolerance {3:c}"); + return true; + } + + // Black hole detection, part 2: + // Treat the connection as unhealthy if the gap between the last + // successful send and the last successful receive grew beyond + // acceptable limits, unless a send succeeded very recently and the number of + // outstanding receives is within reasonable limits. + if ((lastSend - lastReceive > this.receiveDelayLimit) && + ( + currentTime - lastSend > ConnectionHealthChecker.receiveHangGracePeriod || + ( + numberOfSendsSinceLastReceive >= ConnectionHealthChecker.MinNumberOfSendsSinceLastReceiveForUnhealthyConnection && + firstSendSinceLastReceive != null && + currentTime - firstSendSinceLastReceive > ConnectionHealthChecker.receiveHangGracePeriod + ) + )) + { + DefaultTrace.TraceWarning( + "Unhealthy RNTBD connection: Replies not getting back: {0}. " + + "Last send: {1:o}. Last receive: {2:o}. Tolerance: {3:c}. " + + "First send since last receieve: {4:o}. # of sends since last receive: {5}"); + return true; + } + + return false; + } + + /// + /// Detects if data was received recently and returns a boolean flag to indicate the same. + /// + /// An instance of containing the snapshot of current time. + /// An instance of containing the snapshot of last receive time. + /// A boolean flag indicating if data was received recently. + private static bool IsDataReceivedRecently( + DateTime currentTime, + DateTime lastReceiveTime) + { + return currentTime - lastReceiveTime < ConnectionHealthChecker.recentReceiveWindow; + } + + /// + /// Detects socket connectivity and returns a boolean flag to indicate the same. + /// + /// An instance of . + /// A boolean flag indicating if a socket connectivity was established. + private static bool IsSocketConnectionEstablished( + Socket socket) + { + try + { + if (socket == null || !socket.Connected) + { + return false; + } + Debug.Assert(!socket.Blocking); + socket.Send(ConnectionHealthChecker.healthCheckBuffer, 0, 0); + return true; + } + catch (SocketException e) + { + bool healthy = e.SocketErrorCode == SocketError.WouldBlock; + if (!healthy) + { + DefaultTrace.TraceWarning( + "Unhealthy RNTBD connection. Socket error code: {0}", + e.SocketErrorCode.ToString()); + } + return healthy; + } + catch (ObjectDisposedException) + { + return false; + } + } + + /// + /// Detects Idle Timeout and returns a boolean flag to indicate the same. + /// + /// An instance of containing the snapshot of current time. + /// An instance of containing the snapshot of last receive time. + /// A boolean flag indicating if a connection idle timeout was detected. + private bool IsConnectionIdled( + DateTime currentTime, + DateTime lastReceive) + { + // Validates if idle timeout is enabled and exceeds the idle timeout limit. + return this.idleConnectionTimeout > TimeSpan.Zero && currentTime - lastReceive > this.idleConnectionTimeout; + } + + /// + /// Transit timeouts can be a normal symptom under high CPU load. When request times out due to high CPU, + /// closing the existing the connection and re-establish a new one will not help the issue but rather make it worse. + /// Therefore, the timeout detection will be disabled in case the cpu utilization goes beyond the defined threshold. + /// + /// A boolean flag indicating if the CPU utilization is below the defined threshold. + private bool IsCpuUtilizationBelowDisableTimeoutDetectionThreshold() + { + return this.systemUtilizationReader.GetSystemWideCpuUsageCached( + cacheEvictionTimeInSeconds: ConnectionHealthChecker.TimeoutDetectionCPUUsageCacheEvictionTimeInSeconds) <= this.timeoutDetectionDisableCPUThreshold; + } + + /// + /// Helper method to snapshot the transit timeout counters. + /// + /// An integer that will contain the snapshot of total transit timeout counter. + /// An integer that will contain the snapshot of transit timeout on write counter. + private void SnapshotTransitTimeoutCounters( + out int totalTransitTimeoutCounter, + out int transitTimeoutOnWriteCounter) + { + totalTransitTimeoutCounter = this.transitTimeoutOnWriteCounter + this.transitTimeoutOnReadCounter; + transitTimeoutOnWriteCounter = this.transitTimeoutOnWriteCounter; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConnectionStateListener.cs b/Microsoft.Azure.Cosmos/src/direct/ConnectionStateListener.cs index 36deacf246..07e46aa051 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConnectionStateListener.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConnectionStateListener.cs @@ -1,44 +1,44 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Rntbd; - - /// - /// ConnectionStateListener listens to the connection reset event notification fired by the transport client - /// and refreshes the Document client's address cache - /// - internal sealed class ConnectionStateListener : IConnectionStateListener - { - private readonly IAddressResolver addressResolver; - - public ConnectionStateListener(IAddressResolver addressResolver) - { - this.addressResolver = addressResolver; - } - - public void OnConnectionEvent(ConnectionEvent connectionEvent, DateTime eventTime, ServerKey serverKey) - { - DefaultTrace.TraceInformation("OnConnectionEvent fired, connectionEvent :{0}, eventTime: {1}, serverKey: {2}", - connectionEvent, - eventTime, - serverKey.ToString()); - - if (connectionEvent == ConnectionEvent.ReadEof || connectionEvent == ConnectionEvent.ReadFailure) - { - Task updateCacheTask = Task.Run( - async () => await this.addressResolver.UpdateAsync(serverKey)); - - updateCacheTask.ContinueWith(task => - { - DefaultTrace.TraceWarning("AddressCache update failed: {0}", task.Exception?.InnerException); - }, TaskContinuationOptions.OnlyOnFaulted); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Rntbd; + + /// + /// ConnectionStateListener listens to the connection reset event notification fired by the transport client + /// and refreshes the Document client's address cache + /// + internal sealed class ConnectionStateListener : IConnectionStateListener + { + private readonly IAddressResolver addressResolver; + + public ConnectionStateListener(IAddressResolver addressResolver) + { + this.addressResolver = addressResolver; + } + + public void OnConnectionEvent(ConnectionEvent connectionEvent, DateTime eventTime, ServerKey serverKey) + { + DefaultTrace.TraceInformation("OnConnectionEvent fired, connectionEvent :{0}, eventTime: {1}, serverKey: {2}", + connectionEvent, + eventTime, + serverKey.ToString()); + + if (connectionEvent == ConnectionEvent.ReadEof || connectionEvent == ConnectionEvent.ReadFailure) + { + Task updateCacheTask = Task.Run( + async () => await this.addressResolver.UpdateAsync(serverKey)); + + updateCacheTask.ContinueWith(task => + { + DefaultTrace.TraceWarning("AddressCache update failed: {0}", task.Exception?.InnerException); + }, TaskContinuationOptions.OnlyOnFaulted); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConsistencyLevel.cs b/Microsoft.Azure.Cosmos/src/direct/ConsistencyLevel.cs index f9f8b98b90..e6ae8285e7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConsistencyLevel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConsistencyLevel.cs @@ -1,51 +1,51 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - //Should match string in SchemaConstants.h :: ConsistencyLevel - /// - /// These are the consistency levels supported by the Azure Cosmos DB service. - /// - /// - /// The requested Consistency Level must match or be weaker than that provisioned for the database account. - /// For more information on consistency levels, please see http://azure.microsoft.com/documentation/articles/documentdb-consistency-levels/" Consistency Levels article. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum ConsistencyLevel - { - /// - /// Strong Consistency guarantees that read operations always return the value that was last written. - /// - Strong, - - /// - /// Bounded Staleness guarantees that reads are not too out-of-date. This can be configured based on number of operations (MaxStalenessPrefix) - /// or time (MaxStalenessIntervalInSeconds). For more information on MaxStalenessPrefix and MaxStalenessIntervalInSeconds, please see . - /// - BoundedStaleness, - - /// - /// Session Consistency guarantees monotonic reads (you never read old data, then new, then old again), monotonic writes (writes are ordered) - /// and read your writes (your writes are immediately visible to your reads) within any single session. - /// - Session, - - /// - /// Eventual Consistency guarantees that reads will return a subset of writes. All writes - /// will be eventually be available for reads. - /// - Eventual, - - /// - /// ConsistentPrefix Consistency guarantees that reads will return some prefix of all writes with no gaps. - /// All writes will be eventually be available for reads. - /// - ConsistentPrefix - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + //Should match string in SchemaConstants.h :: ConsistencyLevel + /// + /// These are the consistency levels supported by the Azure Cosmos DB service. + /// + /// + /// The requested Consistency Level must match or be weaker than that provisioned for the database account. + /// For more information on consistency levels, please see http://azure.microsoft.com/documentation/articles/documentdb-consistency-levels/" Consistency Levels article. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum ConsistencyLevel + { + /// + /// Strong Consistency guarantees that read operations always return the value that was last written. + /// + Strong, + + /// + /// Bounded Staleness guarantees that reads are not too out-of-date. This can be configured based on number of operations (MaxStalenessPrefix) + /// or time (MaxStalenessIntervalInSeconds). For more information on MaxStalenessPrefix and MaxStalenessIntervalInSeconds, please see . + /// + BoundedStaleness, + + /// + /// Session Consistency guarantees monotonic reads (you never read old data, then new, then old again), monotonic writes (writes are ordered) + /// and read your writes (your writes are immediately visible to your reads) within any single session. + /// + Session, + + /// + /// Eventual Consistency guarantees that reads will return a subset of writes. All writes + /// will be eventually be available for reads. + /// + Eventual, + + /// + /// ConsistentPrefix Consistency guarantees that reads will return some prefix of all writes with no gaps. + /// All writes will be eventually be available for reads. + /// + ConsistentPrefix + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConsistencyReader.cs b/Microsoft.Azure.Cosmos/src/direct/ConsistencyReader.cs index e9db63f927..746bc7e743 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConsistencyReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConsistencyReader.cs @@ -1,395 +1,395 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Net; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - - /* - ConsistencyLevel Replication Mode Desired ReadMode - ------------------- -------------------- --------------------------------------------------------------------------- - Strong Synchronous Read from Read Quorum - Asynchronous Not supported - - Bounded Staleness Synchronous Read from Read Quorum - Asynchronous Read from Read Quorum. Performing read barrier on Primary is unsupported. - - Session Sync/Async Read Any (With LSN Cookie) - Default to Primary as last resort (which should succeed always) - - Eventual Sync/Async Read Any - - Client does validation of unsupported combinations. - - - Preliminaries - ============= - 1. We do primary copy/single master replication. - 2. We do sync or async replication depending on the value of DefaultConsistencyLevel on a database account. - If the database account is configured with DefaultConsistencyLevel = Strong, we do sync replication. By default, for all other values of DefaultConsistencyLevel, we do asynchronous replication. - - Replica set - =========== - We define N as the current number of replicas protecting a partition. - At any given point, the value of N can fluctuate between NMax and NMin. - NMax is called the target replica set size and NMin is called the minimum write availability set size. - NMin and NMax are statically defined whereas N is dynamic. - Dynamic replica set is great for dealing with successive failures. - Since N fluctuates between NMax and NMin, the value of N at the time of calculation of W may not be the same when R is calculated. - This is a side effect of dynamic quorum and requires careful consideration. - - NMin = 2, NMax >= 3 - - Simultaneous Failures - ===================== - In general N replicas imply 2f+1 simultaneous failures - N = 5 allows for 2 simultaneous failures - N = 4 allows for 1 failure - N = 3 allows for 1 failure - N < 3 allows for 0 failures - - Quorums - ======= - W = Write Quorum = Number of replicas which acknowledge a write before the primary can ack the client. It is majority set i.e. N/2 + 1 - R = Read Quorum = Set of replicas such that there is non-empty intersection between W and R that constitute N i.e. R = N -W + 1 - - For sync replication, W is used as a majority quorum. - For async replication, W = 1. We have two LSNs, one is quorum acknowledged LSN (LSN-Q) and another is what is visible to the client (LSN-C). - LSN-Q is the stable LSN which corresponds to the write quorum of Windows Fabric. LSN-C is unstable and corresponds to W=1. - - Assumptions - =========== - Nmin <= N <= Nmax - W >= N/2 + 1 - R = N -W + 1 - - N from read standpoint means number of address from BE which is returning successful response. - Successful reponse: Any BE response containing LSN response header is considered successful reponse. Typically every response other than 410 is treated as succesful response. - - Strong Consistency - ================== - Strong Read requires following guarantees. - * Read value is the latest that has been written. If a write operation finished. Any subsequent reads should see that value. - * Monotonic guarantee. Any read that starts after a previous read operation, should see atleast return equal or higher version of the value. - - To perform strong read we require that atleast R i.e. Read Quorum number of replicas have the value committed. To acheve that such read : - * Read R replicas. If they have the same LSN, use the read result - * If they don't have the same LSN, we will either return the result with the highest LSN observed from those R replicas, after ensuring that LSN - becomes available with R replicas. - * Secondary replicas are always preferred for reading. If R secondaries have returned the result but cannot agree on the resulting LSN, we can include Primary to satisfy read quorum. - * If we only have R replicas (i.e. N==R), we include primary in reading the result and validate N==R. - - Bounded Staleness - ================= - Sync Replication: - Bounded staleness uses the same logic as Strong for cases where the server is using sync replication. - - Async Replication: - For async replication, we make sure that we do not use the Primary as barrier for read quorum. This is because Primary is always going to run ahead (async replication uses W=1 on Primary). - Using primary would voilate the monotonic read guarantees when we fall back to reading from secondary in the subsequent reads as they are always running slower as compared to Primary. - - Session - ======= - We read from secondaries one by one until we find a match for the client's session token (LSN-C). - We go to primary as a last resort which should satisfy LSN-C. - - Availability for Bounded Staleness (for NMax = 4 and NMin = 2): - When there is a partition, the minority quorum can remain available for read as long as N >= 1 - When there is a partition, the minority quorum can remain available for writes as long as N >= 2 - - Eventual - ======== - We can read from any replicas. - - Availability for Bounded Staleness (for NMax = 4 and NMin = 2): - When there is a partition, the minority quorum can remain available for read as long as N >= 1 - When there is a partition, the minority quorum can remain available for writes as long as N >= 2 - - Read Retry logic - ----------------- - For Any NonQuorum Reads(A.K.A ReadAny); AddressCache is refreshed for following condition. - 1) No Secondary Address is found in Address Cache. - 2) Chosen Secondary Returned GoneException/EndpointNotFoundException. - - For Quorum Read address cache is refreshed on following condition. - 1) We found only R secondary where R < RMAX. - 2) We got GoneException/EndpointNotFoundException on all the secondary we contacted. - - */ - /// - /// ConsistencyReader has a dependency on both StoreReader and QuorumReader. For Bounded Staleness and Strong Consistency, it uses the Quorum Reader - /// to converge on a read from read quorum number of replicas. - /// For Session and Eventual Consistency, it directly uses the store reader. - /// - [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] - internal sealed class ConsistencyReader - { - private const int maxNumberOfSecondaryReadRetries = 3; - - private readonly AddressSelector addressSelector; - private readonly IServiceConfigurationReader serviceConfigReader; - private readonly IAuthorizationTokenProvider authorizationTokenProvider; - private readonly StoreReader storeReader; - private readonly QuorumReader quorumReader; - - public ConsistencyReader( - AddressSelector addressSelector, - ISessionContainer sessionContainer, - TransportClient transportClient, - IServiceConfigurationReader serviceConfigReader, - IAuthorizationTokenProvider authorizationTokenProvider, - bool enableReplicaValidation) - { - this.addressSelector = addressSelector; - this.serviceConfigReader = serviceConfigReader; - this.authorizationTokenProvider = authorizationTokenProvider; - this.storeReader = new StoreReader(transportClient, addressSelector, new AddressEnumerator(), sessionContainer, enableReplicaValidation); - this.quorumReader = new QuorumReader(transportClient, addressSelector, this.storeReader, serviceConfigReader, authorizationTokenProvider); - } - - // Test Hook - public string LastReadAddress - { - get - { - return this.storeReader.LastReadAddress; - } - set - { - this.storeReader.LastReadAddress = value; - } - } - - public Task ReadAsync( - DocumentServiceRequest entity, - TimeoutHelper timeout, - bool isInRetry, - bool forceRefresh, - CancellationToken cancellationToken = default(CancellationToken)) - { - if (!isInRetry) - { - timeout.ThrowTimeoutIfElapsed(); - } - else - { - timeout.ThrowGoneIfElapsed(); - } - - entity.RequestContext.TimeoutHelper = timeout; - - if (entity.RequestContext.RequestChargeTracker == null) - { - entity.RequestContext.RequestChargeTracker = new RequestChargeTracker(); - } - - if(entity.RequestContext.ClientRequestStatistics == null) - { - entity.RequestContext.ClientRequestStatistics = new ClientSideRequestStatistics(); - } - - entity.RequestContext.ForceRefreshAddressCache = forceRefresh; - - ConsistencyLevel targetConsistencyLevel; - bool useSessionToken; - ReadMode desiredReadMode = this.DeduceReadMode(entity, out targetConsistencyLevel, out useSessionToken); - - int maxReplicaCount = this.GetMaxReplicaSetSize(entity); - int readQuorumValue = maxReplicaCount - (maxReplicaCount / 2); - - switch (desiredReadMode) - { - case ReadMode.Primary: - return this.ReadPrimaryAsync(entity, useSessionToken); - - case ReadMode.Strong: - entity.RequestContext.PerformLocalRefreshOnGoneException = true; - return this.quorumReader.ReadStrongAsync(entity, readQuorumValue, desiredReadMode); - - case ReadMode.BoundedStaleness: - entity.RequestContext.PerformLocalRefreshOnGoneException = true; - - // for bounded staleness, we are defaulting to read strong for local region reads. - // this can be done since we are always running with majority quorum w = 3 (or 2 during quorum downshift). - // This means that the primary will always be part of the write quorum, and - // therefore can be included for barrier reads. - - // NOTE: this assumes that we are running with SYNC replication (i.e. majority quorum). - // When we run on a minority write quorum(w=2), to ensure monotonic read guarantees - // we always contact two secondary replicas and exclude primary. - // However, this model significantly reduces availability and available throughput for serving reads for bounded staleness during reconfiguration. - // Therefore, to ensure monotonic read guarantee from any replica set we will just use regular quorum read(R=2) since our write quorum is always majority(W=3) - return this.quorumReader.ReadStrongAsync(entity, readQuorumValue, desiredReadMode); - - case ReadMode.Any: - if (targetConsistencyLevel == ConsistencyLevel.Session) - { - return BackoffRetryUtility.ExecuteAsync( - callbackMethod: () => this.ReadSessionAsync(entity, desiredReadMode), - retryPolicy: new SessionTokenMismatchRetryPolicy(), - cancellationToken: cancellationToken); - } - else - { - return this.ReadAnyAsync(entity, desiredReadMode); - } - - default: - throw new InvalidOperationException(); - } - } - - async private Task ReadPrimaryAsync( - DocumentServiceRequest entity, - bool useSessionToken) - { - // Note: We don't put `repsonse` in a using statement becasue we the underlying resources - // will be copied in `ToResponse()` below. - ReferenceCountedDisposable response = await this.storeReader.ReadPrimaryAsync( - entity, - requiresValidLsn: false, - useSessionToken: useSessionToken); - return response.Target.ToResponse(); - } - - async private Task ReadAnyAsync( - DocumentServiceRequest entity, - ReadMode readMode) - { - IList> responses = await this.storeReader.ReadMultipleReplicaAsync( - entity, - includePrimary: true, - replicaCountToRead: 1, - requiresValidLsn: false, - useSessionToken: false, - readMode: readMode); - - if(responses.Count == 0) - { - throw new GoneException(RMResources.Gone, SubStatusCodes.Server_NoValidStoreResponse); - } - - return responses[0].Target.ToResponse(); - } - - private async Task ReadSessionAsync( - DocumentServiceRequest entity, - ReadMode readMode) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - IList> responses = await this.storeReader.ReadMultipleReplicaAsync( - entity:entity, - includePrimary:true, - replicaCountToRead:1, - requiresValidLsn:true, - useSessionToken:true, - checkMinLSN: true, - readMode: readMode); - - if (responses.Count > 0) - { - try - { - StoreResponse storeResponse = responses[0].Target.ToResponse(entity.RequestContext.RequestChargeTracker); - if (storeResponse.Status == (int)HttpStatusCode.NotFound && entity.IsValidStatusCodeForExceptionlessRetry(storeResponse.Status)) - { - if (entity.RequestContext.SessionToken != null && responses[0].Target.SessionToken != null && !entity.RequestContext.SessionToken.IsValid(responses[0].Target.SessionToken)) - { - DefaultTrace.TraceInformation("Convert to session read exception, request {0} Session Lsn {1}, responseLSN {2}", entity.ResourceAddress, entity.RequestContext.SessionToken.ConvertToString(), responses[0].Target.LSN); - - INameValueCollection headers = new DictionaryNameValueCollection(); - headers.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); - throw new NotFoundException(RMResources.ReadSessionNotAvailable, headers); - } - } - return storeResponse; - } - catch (NotFoundException notFoundException) - { - if (entity.RequestContext.SessionToken != null && responses[0].Target.SessionToken != null && !entity.RequestContext.SessionToken.IsValid(responses[0].Target.SessionToken)) - { - DefaultTrace.TraceInformation("Convert to session read exception, request {0} Session Lsn {1}, responseLSN {2}", entity.ResourceAddress, entity.RequestContext.SessionToken.ConvertToString(), responses[0].Target.LSN); - notFoundException.Headers.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); - } - throw notFoundException; - } - } - - INameValueCollection responseHeaders = new DictionaryNameValueCollection(); - responseHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); - ISessionToken requestSessionToken = entity.RequestContext.SessionToken; - DefaultTrace.TraceInformation("Fail the session read {0}, request session token {1}", entity.ResourceAddress, requestSessionToken == null ? "" : requestSessionToken.ConvertToString()); - throw new NotFoundException(RMResources.ReadSessionNotAvailable, responseHeaders); - } - - private ReadMode DeduceReadMode(DocumentServiceRequest request, out ConsistencyLevel targetConsistencyLevel, out bool useSessionToken) - { - targetConsistencyLevel = RequestHelper.GetConsistencyLevelToUse(this.serviceConfigReader, request); - - useSessionToken = targetConsistencyLevel == ConsistencyLevel.Session; - - if (request.DefaultReplicaIndex.HasValue) - { - // Don't use session token - this is used by internal scenarios which technically don't intend session read when they target - // request to specific replica. - useSessionToken = false; - return ReadMode.Primary; //Let the addressResolver decides which replica to connect to. - } - - switch (targetConsistencyLevel) - { - case ConsistencyLevel.Eventual: - return ReadMode.Any; - - case ConsistencyLevel.ConsistentPrefix: - return ReadMode.Any; - - case ConsistencyLevel.Session: - return ReadMode.Any; - - case ConsistencyLevel.BoundedStaleness: - return ReadMode.BoundedStaleness; - - case ConsistencyLevel.Strong: - return ReadMode.Strong; - - default: - throw new InvalidOperationException(); - } - } - - public int GetMaxReplicaSetSize(DocumentServiceRequest entity) - { - bool isMasterResource = ReplicatedResourceClient.IsReadingFromMaster(entity.ResourceType, entity.OperationType); - if (isMasterResource) - { - return this.serviceConfigReader.SystemReplicationPolicy.MaxReplicaSetSize; - } - else - { - return this.serviceConfigReader.UserReplicationPolicy.MaxReplicaSetSize; - } - } - - public int GetMinReplicaSetSize(DocumentServiceRequest entity) - { - bool isMasterResource = ReplicatedResourceClient.IsReadingFromMaster(entity.ResourceType, entity.OperationType); - if (isMasterResource) - { - return this.serviceConfigReader.SystemReplicationPolicy.MinReplicaSetSize; - } - else - { - return this.serviceConfigReader.UserReplicationPolicy.MinReplicaSetSize; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + + /* + ConsistencyLevel Replication Mode Desired ReadMode + ------------------- -------------------- --------------------------------------------------------------------------- + Strong Synchronous Read from Read Quorum + Asynchronous Not supported + + Bounded Staleness Synchronous Read from Read Quorum + Asynchronous Read from Read Quorum. Performing read barrier on Primary is unsupported. + + Session Sync/Async Read Any (With LSN Cookie) + Default to Primary as last resort (which should succeed always) + + Eventual Sync/Async Read Any + + Client does validation of unsupported combinations. + + + Preliminaries + ============= + 1. We do primary copy/single master replication. + 2. We do sync or async replication depending on the value of DefaultConsistencyLevel on a database account. + If the database account is configured with DefaultConsistencyLevel = Strong, we do sync replication. By default, for all other values of DefaultConsistencyLevel, we do asynchronous replication. + + Replica set + =========== + We define N as the current number of replicas protecting a partition. + At any given point, the value of N can fluctuate between NMax and NMin. + NMax is called the target replica set size and NMin is called the minimum write availability set size. + NMin and NMax are statically defined whereas N is dynamic. + Dynamic replica set is great for dealing with successive failures. + Since N fluctuates between NMax and NMin, the value of N at the time of calculation of W may not be the same when R is calculated. + This is a side effect of dynamic quorum and requires careful consideration. + + NMin = 2, NMax >= 3 + + Simultaneous Failures + ===================== + In general N replicas imply 2f+1 simultaneous failures + N = 5 allows for 2 simultaneous failures + N = 4 allows for 1 failure + N = 3 allows for 1 failure + N < 3 allows for 0 failures + + Quorums + ======= + W = Write Quorum = Number of replicas which acknowledge a write before the primary can ack the client. It is majority set i.e. N/2 + 1 + R = Read Quorum = Set of replicas such that there is non-empty intersection between W and R that constitute N i.e. R = N -W + 1 + + For sync replication, W is used as a majority quorum. + For async replication, W = 1. We have two LSNs, one is quorum acknowledged LSN (LSN-Q) and another is what is visible to the client (LSN-C). + LSN-Q is the stable LSN which corresponds to the write quorum of Windows Fabric. LSN-C is unstable and corresponds to W=1. + + Assumptions + =========== + Nmin <= N <= Nmax + W >= N/2 + 1 + R = N -W + 1 + + N from read standpoint means number of address from BE which is returning successful response. + Successful reponse: Any BE response containing LSN response header is considered successful reponse. Typically every response other than 410 is treated as succesful response. + + Strong Consistency + ================== + Strong Read requires following guarantees. + * Read value is the latest that has been written. If a write operation finished. Any subsequent reads should see that value. + * Monotonic guarantee. Any read that starts after a previous read operation, should see atleast return equal or higher version of the value. + + To perform strong read we require that atleast R i.e. Read Quorum number of replicas have the value committed. To acheve that such read : + * Read R replicas. If they have the same LSN, use the read result + * If they don't have the same LSN, we will either return the result with the highest LSN observed from those R replicas, after ensuring that LSN + becomes available with R replicas. + * Secondary replicas are always preferred for reading. If R secondaries have returned the result but cannot agree on the resulting LSN, we can include Primary to satisfy read quorum. + * If we only have R replicas (i.e. N==R), we include primary in reading the result and validate N==R. + + Bounded Staleness + ================= + Sync Replication: + Bounded staleness uses the same logic as Strong for cases where the server is using sync replication. + + Async Replication: + For async replication, we make sure that we do not use the Primary as barrier for read quorum. This is because Primary is always going to run ahead (async replication uses W=1 on Primary). + Using primary would voilate the monotonic read guarantees when we fall back to reading from secondary in the subsequent reads as they are always running slower as compared to Primary. + + Session + ======= + We read from secondaries one by one until we find a match for the client's session token (LSN-C). + We go to primary as a last resort which should satisfy LSN-C. + + Availability for Bounded Staleness (for NMax = 4 and NMin = 2): + When there is a partition, the minority quorum can remain available for read as long as N >= 1 + When there is a partition, the minority quorum can remain available for writes as long as N >= 2 + + Eventual + ======== + We can read from any replicas. + + Availability for Bounded Staleness (for NMax = 4 and NMin = 2): + When there is a partition, the minority quorum can remain available for read as long as N >= 1 + When there is a partition, the minority quorum can remain available for writes as long as N >= 2 + + Read Retry logic + ----------------- + For Any NonQuorum Reads(A.K.A ReadAny); AddressCache is refreshed for following condition. + 1) No Secondary Address is found in Address Cache. + 2) Chosen Secondary Returned GoneException/EndpointNotFoundException. + + For Quorum Read address cache is refreshed on following condition. + 1) We found only R secondary where R < RMAX. + 2) We got GoneException/EndpointNotFoundException on all the secondary we contacted. + + */ + /// + /// ConsistencyReader has a dependency on both StoreReader and QuorumReader. For Bounded Staleness and Strong Consistency, it uses the Quorum Reader + /// to converge on a read from read quorum number of replicas. + /// For Session and Eventual Consistency, it directly uses the store reader. + /// + [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] + internal sealed class ConsistencyReader + { + private const int maxNumberOfSecondaryReadRetries = 3; + + private readonly AddressSelector addressSelector; + private readonly IServiceConfigurationReader serviceConfigReader; + private readonly IAuthorizationTokenProvider authorizationTokenProvider; + private readonly StoreReader storeReader; + private readonly QuorumReader quorumReader; + + public ConsistencyReader( + AddressSelector addressSelector, + ISessionContainer sessionContainer, + TransportClient transportClient, + IServiceConfigurationReader serviceConfigReader, + IAuthorizationTokenProvider authorizationTokenProvider, + bool enableReplicaValidation) + { + this.addressSelector = addressSelector; + this.serviceConfigReader = serviceConfigReader; + this.authorizationTokenProvider = authorizationTokenProvider; + this.storeReader = new StoreReader(transportClient, addressSelector, new AddressEnumerator(), sessionContainer, enableReplicaValidation); + this.quorumReader = new QuorumReader(transportClient, addressSelector, this.storeReader, serviceConfigReader, authorizationTokenProvider); + } + + // Test Hook + public string LastReadAddress + { + get + { + return this.storeReader.LastReadAddress; + } + set + { + this.storeReader.LastReadAddress = value; + } + } + + public Task ReadAsync( + DocumentServiceRequest entity, + TimeoutHelper timeout, + bool isInRetry, + bool forceRefresh, + CancellationToken cancellationToken = default(CancellationToken)) + { + if (!isInRetry) + { + timeout.ThrowTimeoutIfElapsed(); + } + else + { + timeout.ThrowGoneIfElapsed(); + } + + entity.RequestContext.TimeoutHelper = timeout; + + if (entity.RequestContext.RequestChargeTracker == null) + { + entity.RequestContext.RequestChargeTracker = new RequestChargeTracker(); + } + + if(entity.RequestContext.ClientRequestStatistics == null) + { + entity.RequestContext.ClientRequestStatistics = new ClientSideRequestStatistics(); + } + + entity.RequestContext.ForceRefreshAddressCache = forceRefresh; + + ConsistencyLevel targetConsistencyLevel; + bool useSessionToken; + ReadMode desiredReadMode = this.DeduceReadMode(entity, out targetConsistencyLevel, out useSessionToken); + + int maxReplicaCount = this.GetMaxReplicaSetSize(entity); + int readQuorumValue = maxReplicaCount - (maxReplicaCount / 2); + + switch (desiredReadMode) + { + case ReadMode.Primary: + return this.ReadPrimaryAsync(entity, useSessionToken); + + case ReadMode.Strong: + entity.RequestContext.PerformLocalRefreshOnGoneException = true; + return this.quorumReader.ReadStrongAsync(entity, readQuorumValue, desiredReadMode); + + case ReadMode.BoundedStaleness: + entity.RequestContext.PerformLocalRefreshOnGoneException = true; + + // for bounded staleness, we are defaulting to read strong for local region reads. + // this can be done since we are always running with majority quorum w = 3 (or 2 during quorum downshift). + // This means that the primary will always be part of the write quorum, and + // therefore can be included for barrier reads. + + // NOTE: this assumes that we are running with SYNC replication (i.e. majority quorum). + // When we run on a minority write quorum(w=2), to ensure monotonic read guarantees + // we always contact two secondary replicas and exclude primary. + // However, this model significantly reduces availability and available throughput for serving reads for bounded staleness during reconfiguration. + // Therefore, to ensure monotonic read guarantee from any replica set we will just use regular quorum read(R=2) since our write quorum is always majority(W=3) + return this.quorumReader.ReadStrongAsync(entity, readQuorumValue, desiredReadMode); + + case ReadMode.Any: + if (targetConsistencyLevel == ConsistencyLevel.Session) + { + return BackoffRetryUtility.ExecuteAsync( + callbackMethod: () => this.ReadSessionAsync(entity, desiredReadMode), + retryPolicy: new SessionTokenMismatchRetryPolicy(), + cancellationToken: cancellationToken); + } + else + { + return this.ReadAnyAsync(entity, desiredReadMode); + } + + default: + throw new InvalidOperationException(); + } + } + + async private Task ReadPrimaryAsync( + DocumentServiceRequest entity, + bool useSessionToken) + { + // Note: We don't put `repsonse` in a using statement becasue we the underlying resources + // will be copied in `ToResponse()` below. + ReferenceCountedDisposable response = await this.storeReader.ReadPrimaryAsync( + entity, + requiresValidLsn: false, + useSessionToken: useSessionToken); + return response.Target.ToResponse(); + } + + async private Task ReadAnyAsync( + DocumentServiceRequest entity, + ReadMode readMode) + { + IList> responses = await this.storeReader.ReadMultipleReplicaAsync( + entity, + includePrimary: true, + replicaCountToRead: 1, + requiresValidLsn: false, + useSessionToken: false, + readMode: readMode); + + if(responses.Count == 0) + { + throw new GoneException(RMResources.Gone, SubStatusCodes.Server_NoValidStoreResponse); + } + + return responses[0].Target.ToResponse(); + } + + private async Task ReadSessionAsync( + DocumentServiceRequest entity, + ReadMode readMode) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + IList> responses = await this.storeReader.ReadMultipleReplicaAsync( + entity:entity, + includePrimary:true, + replicaCountToRead:1, + requiresValidLsn:true, + useSessionToken:true, + checkMinLSN: true, + readMode: readMode); + + if (responses.Count > 0) + { + try + { + StoreResponse storeResponse = responses[0].Target.ToResponse(entity.RequestContext.RequestChargeTracker); + if (storeResponse.Status == (int)HttpStatusCode.NotFound && entity.IsValidStatusCodeForExceptionlessRetry(storeResponse.Status)) + { + if (entity.RequestContext.SessionToken != null && responses[0].Target.SessionToken != null && !entity.RequestContext.SessionToken.IsValid(responses[0].Target.SessionToken)) + { + DefaultTrace.TraceInformation("Convert to session read exception, request {0} Session Lsn {1}, responseLSN {2}", entity.ResourceAddress, entity.RequestContext.SessionToken.ConvertToString(), responses[0].Target.LSN); + + INameValueCollection headers = new DictionaryNameValueCollection(); + headers.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); + throw new NotFoundException(RMResources.ReadSessionNotAvailable, headers); + } + } + return storeResponse; + } + catch (NotFoundException notFoundException) + { + if (entity.RequestContext.SessionToken != null && responses[0].Target.SessionToken != null && !entity.RequestContext.SessionToken.IsValid(responses[0].Target.SessionToken)) + { + DefaultTrace.TraceInformation("Convert to session read exception, request {0} Session Lsn {1}, responseLSN {2}", entity.ResourceAddress, entity.RequestContext.SessionToken.ConvertToString(), responses[0].Target.LSN); + notFoundException.Headers.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); + } + throw notFoundException; + } + } + + INameValueCollection responseHeaders = new DictionaryNameValueCollection(); + responseHeaders.Set(WFConstants.BackendHeaders.SubStatus, ((int)SubStatusCodes.ReadSessionNotAvailable).ToString()); + ISessionToken requestSessionToken = entity.RequestContext.SessionToken; + DefaultTrace.TraceInformation("Fail the session read {0}, request session token {1}", entity.ResourceAddress, requestSessionToken == null ? "" : requestSessionToken.ConvertToString()); + throw new NotFoundException(RMResources.ReadSessionNotAvailable, responseHeaders); + } + + private ReadMode DeduceReadMode(DocumentServiceRequest request, out ConsistencyLevel targetConsistencyLevel, out bool useSessionToken) + { + targetConsistencyLevel = RequestHelper.GetConsistencyLevelToUse(this.serviceConfigReader, request); + + useSessionToken = targetConsistencyLevel == ConsistencyLevel.Session; + + if (request.DefaultReplicaIndex.HasValue) + { + // Don't use session token - this is used by internal scenarios which technically don't intend session read when they target + // request to specific replica. + useSessionToken = false; + return ReadMode.Primary; //Let the addressResolver decides which replica to connect to. + } + + switch (targetConsistencyLevel) + { + case ConsistencyLevel.Eventual: + return ReadMode.Any; + + case ConsistencyLevel.ConsistentPrefix: + return ReadMode.Any; + + case ConsistencyLevel.Session: + return ReadMode.Any; + + case ConsistencyLevel.BoundedStaleness: + return ReadMode.BoundedStaleness; + + case ConsistencyLevel.Strong: + return ReadMode.Strong; + + default: + throw new InvalidOperationException(); + } + } + + public int GetMaxReplicaSetSize(DocumentServiceRequest entity) + { + bool isMasterResource = ReplicatedResourceClient.IsReadingFromMaster(entity.ResourceType, entity.OperationType); + if (isMasterResource) + { + return this.serviceConfigReader.SystemReplicationPolicy.MaxReplicaSetSize; + } + else + { + return this.serviceConfigReader.UserReplicationPolicy.MaxReplicaSetSize; + } + } + + public int GetMinReplicaSetSize(DocumentServiceRequest entity) + { + bool isMasterResource = ReplicatedResourceClient.IsReadingFromMaster(entity.ResourceType, entity.OperationType); + if (isMasterResource) + { + return this.serviceConfigReader.SystemReplicationPolicy.MinReplicaSetSize; + } + else + { + return this.serviceConfigReader.UserReplicationPolicy.MinReplicaSetSize; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ConsistencyWriter.cs b/Microsoft.Azure.Cosmos/src/direct/ConsistencyWriter.cs index e614b51133..180ad3fa84 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ConsistencyWriter.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ConsistencyWriter.cs @@ -1,351 +1,479 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.Linq; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - /* - -ConsistencyWriter has two modes for writing - local quorum-acked write and globally strong write. - -The determination of whether a request is a local quorum-acked write or a globally strong write is through several factors: -1. Request.RequestContext.OriginalRequestConsistencyLevel - ensure that original request's consistency level, if set, is strong. -2. Default consistency level of the accoutn should be strong. -3. Number of read regions returned by write response > 0. - -For quorum-acked write: - We send single request to primary of a single partition, which will take care of replicating to its secondaries. Once write quorum number of replicas commits the write, the write request returns to the user with success. There is no additional handling for this case. - -For globally strong write: - Similarly, we send single request to primary of write region, which will take care of replicating to its secondaries, one of which is XPPrimary. XPPrimary will then replicate to all remote regions, which will all ack from within their region. In the write region, the request returns from the backend once write quorum number of replicas commits the write - but at this time, the response cannot be returned to caller, since linearizability guarantees will be violated. ConsistencyWriter will continuously issue barrier head requests against the partition in question, until GlobalCommittedLsn is at least as big as the lsn of the original response. -1. Issue write request to write region -2. Receive response from primary of write region, look at GlobalCommittedLsn and LSN headers. -3. If GlobalCommittedLSN == LSN, return response to caller -4. If GlobalCommittedLSN < LSN, cache LSN in request as SelectedGlobalCommittedLSN, and issue barrier requests against any/all replicas. -5. Each barrier response will contain its own LSN and GlobalCommittedLSN, check for any response that satisfies GlobalCommittedLSN >= SelectedGlobalCommittedLSN -6. Return to caller on success. - - */ - - [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] - internal sealed class ConsistencyWriter - { - private const int maxNumberOfWriteBarrierReadRetries = 30; - private const int delayBetweenWriteBarrierCallsInMs = 30; - - private const int maxShortBarrierRetriesForMultiRegion = 4; - private const int shortbarrierRetryIntervalInMsForMultiRegion = 10; - - private readonly StoreReader storeReader; - private readonly TransportClient transportClient; - private readonly AddressSelector addressSelector; - private readonly ISessionContainer sessionContainer; - private readonly IServiceConfigurationReader serviceConfigReader; - private readonly IAuthorizationTokenProvider authorizationTokenProvider; - private readonly bool useMultipleWriteLocations; - - public ConsistencyWriter( - AddressSelector addressSelector, - ISessionContainer sessionContainer, - TransportClient transportClient, - IServiceConfigurationReader serviceConfigReader, - IAuthorizationTokenProvider authorizationTokenProvider, - bool useMultipleWriteLocations, - bool enableReplicaValidation) - { - this.transportClient = transportClient; - this.addressSelector = addressSelector; - this.sessionContainer = sessionContainer; - this.serviceConfigReader = serviceConfigReader; - this.authorizationTokenProvider = authorizationTokenProvider; - this.useMultipleWriteLocations = useMultipleWriteLocations; - this.storeReader = new StoreReader( - transportClient, - addressSelector, - new AddressEnumerator(), - sessionContainer: null, - enableReplicaValidation); //we need store reader only for global strong, no session is needed*/ - } - - // Test hook - internal string LastWriteAddress - { - get; - private set; - } - - public async Task WriteAsync( - DocumentServiceRequest entity, - TimeoutHelper timeout, - bool forceRefresh, - CancellationToken cancellationToken = default(CancellationToken)) - { - timeout.ThrowTimeoutIfElapsed(); - string sessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; - try - { - return await BackoffRetryUtility.ExecuteAsync( - callbackMethod: () => this.WritePrivateAsync(entity, timeout, forceRefresh), - retryPolicy: new SessionTokenMismatchRetryPolicy(), - cancellationToken: cancellationToken); - } - finally - { - SessionTokenHelper.SetOriginalSessionToken(entity, sessionToken); - } - } - - private async Task WritePrivateAsync( - DocumentServiceRequest request, - TimeoutHelper timeout, - bool forceRefresh) - { - timeout.ThrowTimeoutIfElapsed(); - - request.RequestContext.TimeoutHelper = timeout; - - if (request.RequestContext.RequestChargeTracker == null) - { - request.RequestContext.RequestChargeTracker = new RequestChargeTracker(); - } - - if (request.RequestContext.ClientRequestStatistics == null) - { - request.RequestContext.ClientRequestStatistics = new ClientSideRequestStatistics(); - } - - request.RequestContext.ForceRefreshAddressCache = forceRefresh; - - if (request.RequestContext.GlobalStrongWriteStoreResult == null) - { - StoreResponse response = null; - - string requestedCollectionRid = request.RequestContext.ResolvedCollectionRid; - - PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.addressSelector.ResolveAddressesAsync(request, forceRefresh); - - if (!string.IsNullOrEmpty(requestedCollectionRid) && !string.IsNullOrEmpty(request.RequestContext.ResolvedCollectionRid)) - { - if (!requestedCollectionRid.Equals(request.RequestContext.ResolvedCollectionRid)) - { - this.sessionContainer.ClearTokenByResourceId(requestedCollectionRid); - } - } - - // the transportclient relies on this contacted replicas being present *before* the request is made - // TODO: Can we not rely on this inversion of dependencies. - request.RequestContext.ClientRequestStatistics.ContactedReplicas = partitionPerProtocolAddress.ReplicaTransportAddressUris.ToList(); - - TransportAddressUri primaryUri = partitionPerProtocolAddress.GetPrimaryAddressUri(request); - this.LastWriteAddress = primaryUri.ToString(); - - if ((this.useMultipleWriteLocations || request.OperationType == OperationType.Batch) && - RequestHelper.GetConsistencyLevelToUse(this.serviceConfigReader, request) == ConsistencyLevel.Session) - { - // Set session token to ensure session consistency for write requests - // 1. when writes can be issued to multiple locations - // 2. When we have Batch requests, since it can have Reads in it. - SessionTokenHelper.SetPartitionLocalSessionToken(request, this.sessionContainer); - } - else - { - // When writes can only go to single location, there is no reason - // to session session token to the server. - SessionTokenHelper.ValidateAndRemoveSessionToken(request); - } - - DateTime startTimeUtc = DateTime.UtcNow; - ReferenceCountedDisposable storeResult = null; - try - { - response = await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); - - storeResult = StoreResult.CreateStoreResult( - storeResponse: response, - responseException: null, - requiresValidLsn: true, - useLocalLSNBasedHeaders: false, - replicaHealthStatuses: primaryUri.GetCurrentHealthState().GetHealthStatusDiagnosticsAsReadOnlyEnumerable(), - storePhysicalAddress: primaryUri.Uri); - - request.RequestContext.ClientRequestStatistics.RecordResponse( - request: request, - storeResult: storeResult.Target, - startTimeUtc: startTimeUtc, - endTimeUtc: DateTime.UtcNow); - } - catch (Exception ex) - { - storeResult = StoreResult.CreateStoreResult( - storeResponse: null, - responseException: ex, - requiresValidLsn: true, - useLocalLSNBasedHeaders: false, - replicaHealthStatuses: primaryUri.GetCurrentHealthState().GetHealthStatusDiagnosticsAsReadOnlyEnumerable(), - storePhysicalAddress: primaryUri.Uri); - - request.RequestContext.ClientRequestStatistics.RecordResponse( - request: request, - storeResult: storeResult.Target, - startTimeUtc: startTimeUtc, - endTimeUtc: DateTime.UtcNow); - - if (ex is DocumentClientException) - { - DocumentClientException dce = (DocumentClientException)ex; - StoreResult.VerifyCanContinueOnException(dce); - string value = dce.Headers[HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh]; - if (!string.IsNullOrWhiteSpace(value)) - { - int result; - if (int.TryParse(dce.Headers.GetValues(HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh)[0], - NumberStyles.Integer, - CultureInfo.InvariantCulture, - out result) && result == 1) - { - this.addressSelector.StartBackgroundAddressRefresh(request); - } - } - } - } - - if (storeResult?.Target is null) - { - Debug.Assert(false, "StoreResult cannot be null at this point."); - DefaultTrace.TraceCritical("ConsistencyWriter did not get storeResult!"); - throw new InternalServerErrorException(); - } - - if (ReplicatedResourceClient.IsGlobalStrongEnabled() && this.ShouldPerformWriteBarrierForGlobalStrong(storeResult.Target)) - { - long lsn = storeResult.Target.LSN; - long globalCommittedLsn = storeResult.Target.GlobalCommittedLSN; - - if (lsn == -1 || globalCommittedLsn == -1) - { - DefaultTrace.TraceWarning("ConsistencyWriter: LSN {0} or GlobalCommittedLsn {1} is not set for global strong request", - lsn, globalCommittedLsn); - // Service Generated because no lsn and glsn set by service - throw new GoneException(RMResources.Gone, SubStatusCodes.ServerGenerated410); - } - - request.RequestContext.GlobalStrongWriteStoreResult = storeResult; - request.RequestContext.GlobalCommittedSelectedLSN = lsn; - - //if necessary we would have already refreshed cache by now. - request.RequestContext.ForceRefreshAddressCache = false; - - DefaultTrace.TraceInformation("ConsistencyWriter: globalCommittedLsn {0}, lsn {1}", globalCommittedLsn, lsn); - //barrier only if necessary, i.e. when write region completes write, but read regions have not. - if (globalCommittedLsn < lsn) - { - using (DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(request, this.authorizationTokenProvider, null, request.RequestContext.GlobalCommittedSelectedLSN)) - { - if (!await this.WaitForWriteBarrierAsync(barrierRequest, request.RequestContext.GlobalCommittedSelectedLSN)) - { - DefaultTrace.TraceError("ConsistencyWriter: Write barrier has not been met for global strong request. SelectedGlobalCommittedLsn: {0}", request.RequestContext.GlobalCommittedSelectedLSN); - throw new GoneException(RMResources.GlobalStrongWriteBarrierNotMet, SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet); - } - } - } - } - else - { - return storeResult.Target.ToResponse(); - } - } - else - { - using (DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(request, this.authorizationTokenProvider, null, request.RequestContext.GlobalCommittedSelectedLSN)) - { - if (!await this.WaitForWriteBarrierAsync(barrierRequest, request.RequestContext.GlobalCommittedSelectedLSN)) - { - DefaultTrace.TraceWarning("ConsistencyWriter: Write barrier has not been met for global strong request. SelectedGlobalCommittedLsn: {0}", request.RequestContext.GlobalCommittedSelectedLSN); - throw new GoneException(RMResources.GlobalStrongWriteBarrierNotMet, SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet); - } - } - } - - return request.RequestContext.GlobalStrongWriteStoreResult.Target.ToResponse(); - } - - private bool ShouldPerformWriteBarrierForGlobalStrong(StoreResult storeResult) - { - if (storeResult.StatusCode < StatusCodes.StartingErrorCode || - storeResult.StatusCode == StatusCodes.Conflict || - (storeResult.StatusCode == StatusCodes.NotFound && storeResult.SubStatusCode != SubStatusCodes.ReadSessionNotAvailable) || - storeResult.StatusCode == StatusCodes.PreconditionFailed) - { - if (this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong && storeResult.NumberOfReadRegions > 0) - { - return true; - } - } - - return false; - } - - private async Task WaitForWriteBarrierAsync(DocumentServiceRequest barrierRequest, long selectedGlobalCommittedLsn) - { - int writeBarrierRetryCount = ConsistencyWriter.maxNumberOfWriteBarrierReadRetries; - - long maxGlobalCommittedLsnReceived = 0; - while (writeBarrierRetryCount-- > 0) - { - barrierRequest.RequestContext.TimeoutHelper.ThrowTimeoutIfElapsed(); - IList> responses = await this.storeReader.ReadMultipleReplicaAsync( - barrierRequest, - includePrimary: true, - replicaCountToRead: 1, // any replica with correct globalCommittedLsn is good enough - requiresValidLsn: false, - useSessionToken: false, - readMode: ReadMode.Strong, - checkMinLSN: false, - forceReadAll: false); - - if (responses != null && responses.Any(response => response.Target.GlobalCommittedLSN >= selectedGlobalCommittedLsn)) - { - return true; - } - - //get max global committed lsn from current batch of responses, then update if greater than max of all batches. - long maxGlobalCommittedLsn = responses != null ? responses.Select(s => s.Target.GlobalCommittedLSN).DefaultIfEmpty(0).Max() : 0; - maxGlobalCommittedLsnReceived = maxGlobalCommittedLsnReceived > maxGlobalCommittedLsn ? maxGlobalCommittedLsnReceived : maxGlobalCommittedLsn; - - //only refresh on first barrier call, set to false for subsequent attempts. - barrierRequest.RequestContext.ForceRefreshAddressCache = false; - - //trace on last retry. - if (writeBarrierRetryCount == 0) - { - DefaultTrace.TraceInformation("ConsistencyWriter: WaitForWriteBarrierAsync - Last barrier multi-region strong. Responses: {0}", - string.Join("; ", responses)); - } - else - { - if ((ConsistencyWriter.maxNumberOfWriteBarrierReadRetries - writeBarrierRetryCount) > ConsistencyWriter.maxShortBarrierRetriesForMultiRegion) - { - await Task.Delay(ConsistencyWriter.delayBetweenWriteBarrierCallsInMs); - } - else - { - await Task.Delay(ConsistencyWriter.shortbarrierRetryIntervalInMsForMultiRegion); - } - } - } - - DefaultTrace.TraceInformation("ConsistencyWriter: Highest global committed lsn received for write barrier call is {0}", maxGlobalCommittedLsnReceived); - - return false; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.Linq; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + /* + +ConsistencyWriter has two modes for writing - local quorum-acked write and globally strong write. + +The determination of whether a request is a local quorum-acked write or a globally strong write is through several factors: +1. Request.RequestContext.OriginalRequestConsistencyLevel - ensure that original request's consistency level, if set, is strong. +2. Default consistency level of the accoutn should be strong. +3. Number of read regions returned by write response > 0. + +For quorum-acked write: + We send single request to primary of a single partition, which will take care of replicating to its secondaries. Once write quorum number of replicas commits the write, the write request returns to the user with success. There is no additional handling for this case. + +For globally strong write: + Similarly, we send single request to primary of write region, which will take care of replicating to its secondaries, one of which is XPPrimary. XPPrimary will then replicate to all remote regions, which will all ack from within their region. In the write region, the request returns from the backend once write quorum number of replicas commits the write - but at this time, the response cannot be returned to caller, since linearizability guarantees will be violated. ConsistencyWriter will continuously issue barrier head requests against the partition in question, until GlobalCommittedLsn is at least as big as the lsn of the original response. +1. Issue write request to write region +2. Receive response from primary of write region, look at GlobalCommittedLsn and LSN headers. +3. If GlobalCommittedLSN == LSN, return response to caller +4. If GlobalCommittedLSN < LSN, cache LSN in request as SelectedGlobalCommittedLSN, and issue barrier requests against any/all replicas. +5. Each barrier response will contain its own LSN and GlobalCommittedLSN, check for any response that satisfies GlobalCommittedLSN >= SelectedGlobalCommittedLSN +6. Return to caller on success. + + */ + + [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] + internal sealed class ConsistencyWriter + { + private const int maxNumberOfWriteBarrierReadRetries = 30; + private const int delayBetweenWriteBarrierCallsInMs = 30; + + private const int maxShortBarrierRetriesForMultiRegion = 4; + private const int shortbarrierRetryIntervalInMsForMultiRegion = 10; + + private static readonly TimeSpan shortDelayBetweenWriteBarrierCallsForMultipleRegions = TimeSpan.FromMilliseconds(10); + private static readonly TimeSpan defaultDelayBetweenWriteBarrierCalls = TimeSpan.FromMilliseconds(30); + private static readonly TimeSpan[] defaultBarrierRequestDelays = GetDefaultBarrierRequestDelays(); + private static readonly TimeSpan totalAllowedBarrierRequestDelay = GetTotalAllowedBarrierRequestDelay(); + + private readonly StoreReader storeReader; + private readonly TransportClient transportClient; + private readonly AddressSelector addressSelector; + private readonly ISessionContainer sessionContainer; + private readonly IServiceConfigurationReader serviceConfigReader; + private readonly IAuthorizationTokenProvider authorizationTokenProvider; + private readonly bool useMultipleWriteLocations; + + public ConsistencyWriter( + AddressSelector addressSelector, + ISessionContainer sessionContainer, + TransportClient transportClient, + IServiceConfigurationReader serviceConfigReader, + IAuthorizationTokenProvider authorizationTokenProvider, + bool useMultipleWriteLocations, + bool enableReplicaValidation) + { + this.transportClient = transportClient; + this.addressSelector = addressSelector; + this.sessionContainer = sessionContainer; + this.serviceConfigReader = serviceConfigReader; + this.authorizationTokenProvider = authorizationTokenProvider; + this.useMultipleWriteLocations = useMultipleWriteLocations; + this.storeReader = new StoreReader( + transportClient, + addressSelector, + new AddressEnumerator(), + sessionContainer: null, + enableReplicaValidation); //we need store reader only for global strong, no session is needed*/ + } + + // Test hook + internal string LastWriteAddress + { + get; + private set; + } + + private static TimeSpan[] GetDefaultBarrierRequestDelays() + { + TimeSpan[] delays = new TimeSpan[maxShortBarrierRetriesForMultiRegion + maxNumberOfWriteBarrierReadRetries]; + + for (int i = 0; i < maxShortBarrierRetriesForMultiRegion; i++) + { + delays[i] = shortDelayBetweenWriteBarrierCallsForMultipleRegions; + } + + for (int i = maxShortBarrierRetriesForMultiRegion + ; i < maxShortBarrierRetriesForMultiRegion + maxNumberOfWriteBarrierReadRetries + ; i++) + { + delays[i] = defaultDelayBetweenWriteBarrierCalls; + } + + return delays; + } + + private static TimeSpan GetTotalAllowedBarrierRequestDelay() + { + TimeSpan totalAllowedDelay = TimeSpan.Zero; + foreach (TimeSpan current in GetDefaultBarrierRequestDelays()) + { + totalAllowedDelay += current; + } + + return totalAllowedDelay; + } + + public async Task WriteAsync( + DocumentServiceRequest entity, + TimeoutHelper timeout, + bool forceRefresh, + CancellationToken cancellationToken = default(CancellationToken)) + { + timeout.ThrowTimeoutIfElapsed(); + string sessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; + try + { + return await BackoffRetryUtility.ExecuteAsync( + callbackMethod: () => this.WritePrivateAsync(entity, timeout, forceRefresh), + retryPolicy: new SessionTokenMismatchRetryPolicy(), + cancellationToken: cancellationToken); + } + finally + { + SessionTokenHelper.SetOriginalSessionToken(entity, sessionToken); + } + } + + private async Task WritePrivateAsync( + DocumentServiceRequest request, + TimeoutHelper timeout, + bool forceRefresh) + { + timeout.ThrowTimeoutIfElapsed(); + + request.RequestContext.TimeoutHelper = timeout; + + if (request.RequestContext.RequestChargeTracker == null) + { + request.RequestContext.RequestChargeTracker = new RequestChargeTracker(); + } + + if (request.RequestContext.ClientRequestStatistics == null) + { + request.RequestContext.ClientRequestStatistics = new ClientSideRequestStatistics(); + } + + request.RequestContext.ForceRefreshAddressCache = forceRefresh; + + if (request.RequestContext.GlobalStrongWriteStoreResult == null) + { + StoreResponse response = null; + + string requestedCollectionRid = request.RequestContext.ResolvedCollectionRid; + + PerProtocolPartitionAddressInformation partitionPerProtocolAddress = await this.addressSelector.ResolveAddressesAsync(request, forceRefresh); + + if (!string.IsNullOrEmpty(requestedCollectionRid) && !string.IsNullOrEmpty(request.RequestContext.ResolvedCollectionRid)) + { + if (!requestedCollectionRid.Equals(request.RequestContext.ResolvedCollectionRid)) + { + this.sessionContainer.ClearTokenByResourceId(requestedCollectionRid); + } + } + + // the transportclient relies on this contacted replicas being present *before* the request is made + // TODO: Can we not rely on this inversion of dependencies. + request.RequestContext.ClientRequestStatistics.ContactedReplicas = partitionPerProtocolAddress.ReplicaTransportAddressUris.ToList(); + + TransportAddressUri primaryUri = partitionPerProtocolAddress.GetPrimaryAddressUri(request); + this.LastWriteAddress = primaryUri.ToString(); + + if ((this.useMultipleWriteLocations || request.OperationType == OperationType.Batch) && + RequestHelper.GetConsistencyLevelToUse(this.serviceConfigReader, request) == ConsistencyLevel.Session) + { + // Set session token to ensure session consistency for write requests + // 1. when writes can be issued to multiple locations + // 2. When we have Batch requests, since it can have Reads in it. + SessionTokenHelper.SetPartitionLocalSessionToken(request, this.sessionContainer); + } + else + { + // When writes can only go to single location, there is no reason + // to session session token to the server. + SessionTokenHelper.ValidateAndRemoveSessionToken(request); + } + + DateTime startTimeUtc = DateTime.UtcNow; + ReferenceCountedDisposable storeResult = null; + try + { + response = await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); + + storeResult = StoreResult.CreateStoreResult( + storeResponse: response, + responseException: null, + requiresValidLsn: true, + useLocalLSNBasedHeaders: false, + replicaHealthStatuses: primaryUri.GetCurrentHealthState().GetHealthStatusDiagnosticsAsReadOnlyEnumerable(), + storePhysicalAddress: primaryUri.Uri); + + request.RequestContext.ClientRequestStatistics.RecordResponse( + request: request, + storeResult: storeResult.Target, + startTimeUtc: startTimeUtc, + endTimeUtc: DateTime.UtcNow); + } + catch (Exception ex) + { + storeResult = StoreResult.CreateStoreResult( + storeResponse: null, + responseException: ex, + requiresValidLsn: true, + useLocalLSNBasedHeaders: false, + replicaHealthStatuses: primaryUri.GetCurrentHealthState().GetHealthStatusDiagnosticsAsReadOnlyEnumerable(), + storePhysicalAddress: primaryUri.Uri); + + request.RequestContext.ClientRequestStatistics.RecordResponse( + request: request, + storeResult: storeResult.Target, + startTimeUtc: startTimeUtc, + endTimeUtc: DateTime.UtcNow); + + if (ex is DocumentClientException) + { + DocumentClientException dce = (DocumentClientException)ex; + StoreResult.VerifyCanContinueOnException(dce); + string value = dce.Headers[HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh]; + if (!string.IsNullOrWhiteSpace(value)) + { + int result; + if (int.TryParse(dce.Headers.GetValues(HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh)[0], + NumberStyles.Integer, + CultureInfo.InvariantCulture, + out result) && result == 1) + { + this.addressSelector.StartBackgroundAddressRefresh(request); + } + } + } + } + + if (storeResult?.Target is null) + { + Debug.Assert(false, "StoreResult cannot be null at this point."); + DefaultTrace.TraceCritical("ConsistencyWriter did not get storeResult!"); + throw new InternalServerErrorException(); + } + + if (ReplicatedResourceClient.IsGlobalStrongEnabled() && this.ShouldPerformWriteBarrierForGlobalStrong(storeResult.Target)) + { + long lsn = storeResult.Target.LSN; + long globalCommittedLsn = storeResult.Target.GlobalCommittedLSN; + + if (lsn == -1 || globalCommittedLsn == -1) + { + DefaultTrace.TraceWarning("ConsistencyWriter: LSN {0} or GlobalCommittedLsn {1} is not set for global strong request", + lsn, globalCommittedLsn); + // Service Generated because no lsn and glsn set by service + throw new GoneException(RMResources.Gone, SubStatusCodes.ServerGenerated410); + } + + request.RequestContext.GlobalStrongWriteStoreResult = storeResult; + request.RequestContext.GlobalCommittedSelectedLSN = lsn; + + //if necessary we would have already refreshed cache by now. + request.RequestContext.ForceRefreshAddressCache = false; + + DefaultTrace.TraceInformation("ConsistencyWriter: globalCommittedLsn {0}, lsn {1}", globalCommittedLsn, lsn); + //barrier only if necessary, i.e. when write region completes write, but read regions have not. + if (globalCommittedLsn < lsn) + { + using (DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(request, this.authorizationTokenProvider, null, request.RequestContext.GlobalCommittedSelectedLSN)) + { + if (!await this.WaitForWriteBarrierAsync(barrierRequest, request.RequestContext.GlobalCommittedSelectedLSN)) + { + DefaultTrace.TraceError("ConsistencyWriter: Write barrier has not been met for global strong request. SelectedGlobalCommittedLsn: {0}", request.RequestContext.GlobalCommittedSelectedLSN); + throw new GoneException(RMResources.GlobalStrongWriteBarrierNotMet, SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet); + } + } + } + } + else + { + return storeResult.Target.ToResponse(); + } + } + else + { + using (DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(request, this.authorizationTokenProvider, null, request.RequestContext.GlobalCommittedSelectedLSN)) + { + if (!await this.WaitForWriteBarrierAsync(barrierRequest, request.RequestContext.GlobalCommittedSelectedLSN)) + { + DefaultTrace.TraceWarning("ConsistencyWriter: Write barrier has not been met for global strong request. SelectedGlobalCommittedLsn: {0}", request.RequestContext.GlobalCommittedSelectedLSN); + throw new GoneException(RMResources.GlobalStrongWriteBarrierNotMet, SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet); + } + } + } + + return request.RequestContext.GlobalStrongWriteStoreResult.Target.ToResponse(); + } + + private bool ShouldPerformWriteBarrierForGlobalStrong(StoreResult storeResult) + { + if (storeResult.StatusCode < StatusCodes.StartingErrorCode || + storeResult.StatusCode == StatusCodes.Conflict || + (storeResult.StatusCode == StatusCodes.NotFound && storeResult.SubStatusCode != SubStatusCodes.ReadSessionNotAvailable) || + storeResult.StatusCode == StatusCodes.PreconditionFailed) + { + if (this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong && storeResult.NumberOfReadRegions > 0) + { + return true; + } + } + + return false; + } + + private Task WaitForWriteBarrierAsync( + DocumentServiceRequest barrierRequest, + long selectedGlobalCommittedLsn) + { + if (BarrierRequestHelper.IsOldBarrierRequestHandlingEnabled) + { + return this.WaitForWriteBarrierOldAsync(barrierRequest, selectedGlobalCommittedLsn); + } + + return this.WaitForWriteBarrierNewAsync(barrierRequest, selectedGlobalCommittedLsn); + } + + // NOTE this is only temporarily kept to have a feature flag + // (Env variable 'AZURE_COSMOS_OLD_BARRIER_REQUESTS_HANDLING_ENABLED' allowing to fall back + // This old implementation will be removed (and the environment + // variable not been used anymore) after some bake time. + private async Task WaitForWriteBarrierOldAsync(DocumentServiceRequest barrierRequest, long selectedGlobalCommittedLsn) + { + int writeBarrierRetryCount = ConsistencyWriter.maxNumberOfWriteBarrierReadRetries; + + long maxGlobalCommittedLsnReceived = 0; + while (writeBarrierRetryCount-- > 0) + { + barrierRequest.RequestContext.TimeoutHelper.ThrowTimeoutIfElapsed(); + IList> responses = await this.storeReader.ReadMultipleReplicaAsync( + barrierRequest, + includePrimary: true, + replicaCountToRead: 1, // any replica with correct globalCommittedLsn is good enough + requiresValidLsn: false, + useSessionToken: false, + readMode: ReadMode.Strong, + checkMinLSN: false, + forceReadAll: false); + + if (responses != null && responses.Any(response => response.Target.GlobalCommittedLSN >= selectedGlobalCommittedLsn)) + { + return true; + } + + //get max global committed lsn from current batch of responses, then update if greater than max of all batches. + long maxGlobalCommittedLsn = responses != null ? responses.Select(s => s.Target.GlobalCommittedLSN).DefaultIfEmpty(0).Max() : 0; + maxGlobalCommittedLsnReceived = maxGlobalCommittedLsnReceived > maxGlobalCommittedLsn ? maxGlobalCommittedLsnReceived : maxGlobalCommittedLsn; + + //only refresh on first barrier call, set to false for subsequent attempts. + barrierRequest.RequestContext.ForceRefreshAddressCache = false; + + //trace on last retry. + if (writeBarrierRetryCount == 0) + { + DefaultTrace.TraceInformation("ConsistencyWriter: WaitForWriteBarrierAsync - Last barrier multi-region strong. Responses: {0}", + string.Join("; ", responses.Select(r => r.Target))); + } + else + { + if ((ConsistencyWriter.maxNumberOfWriteBarrierReadRetries - writeBarrierRetryCount) > ConsistencyWriter.maxShortBarrierRetriesForMultiRegion) + { + await Task.Delay(ConsistencyWriter.delayBetweenWriteBarrierCallsInMs); + } + else + { + await Task.Delay(ConsistencyWriter.shortbarrierRetryIntervalInMsForMultiRegion); + } + } + } + + DefaultTrace.TraceInformation("ConsistencyWriter: Highest global committed lsn received for write barrier call is {0}", maxGlobalCommittedLsnReceived); + + return false; + } + + private async Task WaitForWriteBarrierNewAsync( + DocumentServiceRequest barrierRequest, + long selectedGlobalCommittedLsn) + { + TimeSpan remainingDelay = totalAllowedBarrierRequestDelay; + + int writeBarrierRetryCount = 0; + long maxGlobalCommittedLsnReceived = 0; + while (writeBarrierRetryCount < defaultBarrierRequestDelays.Length && remainingDelay >= TimeSpan.Zero) // Retry loop + { + barrierRequest.RequestContext.TimeoutHelper.ThrowTimeoutIfElapsed(); + + ValueStopwatch barrierRequestStopWatch = ValueStopwatch.StartNew(); + IList> responses = await this.storeReader.ReadMultipleReplicaAsync( + barrierRequest, + includePrimary: true, + replicaCountToRead: 1, // any replica with correct globalCommittedLsn is good enough + requiresValidLsn: false, + useSessionToken: false, + readMode: ReadMode.Strong, + checkMinLSN: false, + forceReadAll: false); + barrierRequestStopWatch.Stop(); + + TimeSpan previousBarrierRequestLatency = barrierRequestStopWatch.Elapsed; + long maxGlobalCommittedLsn = 0; + if (responses != null) + { + foreach (ReferenceCountedDisposable response in responses) + { + if (response.Target.GlobalCommittedLSN >= selectedGlobalCommittedLsn) + { + return true; + } + + if (response.Target.GlobalCommittedLSN >= maxGlobalCommittedLsn) + { + maxGlobalCommittedLsn = response.Target.GlobalCommittedLSN; + } + } + } + + //get max global committed lsn from current batch of responses, then update if greater than max of all batches. + maxGlobalCommittedLsnReceived = Math.Max(maxGlobalCommittedLsnReceived, maxGlobalCommittedLsn); + + //only refresh on first barrier call, set to false for subsequent attempts. + barrierRequest.RequestContext.ForceRefreshAddressCache = false; + + bool shouldDelay = BarrierRequestHelper.ShouldDelayBetweenHeadRequests( + previousBarrierRequestLatency, + responses, + defaultBarrierRequestDelays[writeBarrierRetryCount], + out TimeSpan delay); + + writeBarrierRetryCount++; + if (writeBarrierRetryCount >= defaultBarrierRequestDelays.Length || remainingDelay < delay) + { + //trace on last retry. + DefaultTrace.TraceInformation("ConsistencyWriter: WaitForWriteBarrierAsync - Last barrier multi-region strong. Target GCLSN: {0}, Max. GCLSN received: {1}, Responses: {2}", + selectedGlobalCommittedLsn, + maxGlobalCommittedLsn, + string.Join("; ", responses.Select(r => r.Target))); + + break; + } + else if (shouldDelay) + { + await Task.Delay(delay); + remainingDelay -= delay; + } + } + + DefaultTrace.TraceInformation("ConsistencyWriter: Highest global committed lsn received for write barrier call is {0}", maxGlobalCommittedLsnReceived); + + return false; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Constants.cs b/Microsoft.Azure.Cosmos/src/direct/Constants.cs index 0acba36987..bebcfffa55 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Constants.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Constants.cs @@ -1,2246 +1,2330 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal static class Constants - { - public const char DBSeparator = ';'; - public const char ModeSeparator = ':'; - public const char StartArray = '['; - public const char EndArray = ']'; - public const char PartitionSeparator = ','; - public const char UrlPathSeparator = '/'; - - public const string DataContractNamespace = "http://schemas.microsoft.com/windowsazure"; - - // This should match (maxResourceSize - resourceSizePadding) from Server settings.xml - public const int MaxResourceSizeInBytes = (2 * 1024 * 1024) - 1; - - // This should match maxBatchRequestBodySize from Server settings.xml - public const int MaxDirectModeBatchRequestBodySizeInBytes = 2202010; - - // This should match maxBatchOperationsPerRequest from Server settings.xml - public const int MaxOperationsInDirectModeBatchRequest = 100; - - public const int MaxGatewayModeBatchRequestBodySizeInBytes = 16 * 1024 * 1024; - - public const int MaxOperationsInGatewayModeBatchRequest = 1000; - - public const string FirewallAuthorization = "FirewallAuthorization"; - - // As per https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy - // table secondary endpoint is suffixed by -secondary. - public const string TableSecondaryEndpointSuffix = "-secondary"; - - // Attribute stamped on BLOB containers/BLOBs - // for various purposes. - // MUST be in sync with XStoreUploader native code. - public static class Quota - { - // Quota Header Strings, must be in sync with ResourceQuotaManager.h - public const string Database = "databases"; - public const string Collection = "collections"; - public const string User = "users"; - public const string Permission = "permissions"; - public const string CollectionSize = "collectionSize"; - public const string DocumentsSize = "documentsSize"; - public const string DocumentsCount = "documentsCount"; - public const string SampledDistinctPartitionKeyCount = "sampledDistinctPartitionKeyCount"; - public const string StoredProcedure = "storedProcedures"; - public const string Trigger = "triggers"; - public const string UserDefinedFunction = "functions"; - public static char[] DelimiterChars = { '=', ';' }; - } - - public static class BlobStorageAttributes - { - // Container type. Only key is relevant. However set value to be - // same as key to permit future enhancements. - public const string attachmentContainer = "x_ms_attachmentContainer"; - - // Container type. Only key is relevant. However set value to be - // same as key to permit future enhancements. - public const string backupContainer = "x_ms_backupContainer"; - - // Container retention period. - public const string backupRetentionIntervalInHours = "x_ms_backupRetentionIntervalInHours"; - - // Container backup interval. - public const string backupIntervalInMinutes = "x_ms_backupIntervalInMinutes"; - - // non-FQDN. - public const string owningFederation = "x_ms_owningFederation"; - - // Name of the DatabaseAccount for which this blob stores data - public const string owningDatabaseAccountName = "x_ms_databaseAccountName"; - - // Last UTC time the attachment in Azure storage was checked and identified - // to be NOT an orphan (i.e., still referenced from a document) - public const string lastAttachmentCheckTime = "x_ms_lastAttachmentCheckTimeUtc"; - - // Last UTC time the attachment (or an attachment container) - // in Azure storage was checked and identified AS an orphan - // (i.e., NOT referenced from a document or in use by any DSI) - public const string orphanAttachmentProbationStartTime = "x_ms_orphanAttachmentProbationStartTimeUtc"; - - // Last UTC time a backup container in Azure storage was checked and identified - // AS an orphan (i.e., NOT used by any DSI in the federation) - public const string orphanBackupProbationStartTime = "x_ms_orphanBackupProbationStartTime"; - - // FQDN hostname stamped on document attachment BLOB uploads - // to scope orphan attachment BLOB cleanup to - // only those BLOBs that were uploaded by a given - // OneBox. - public const string oneBoxHostName = "x_ms_OneBoxHostName"; - - // The last scan time of a backup log container - public const string lastScanTime = "x_ms_lastScanTime"; - - // Backup hold until - public const string backupHoldUntil = "x_ms_backupHoldUntil"; - - // Backup valid starting time - public const string backupStartTime = "x_ms_backupStartTime"; - - // Backup valid ending time - public const string backupTime = "x_ms_backupTime"; - } - - public static class CosmosDBRequestProperties - { - public const string IsAllowedOrigin = "isAllowedOrigin"; - } - - public static class Offers - { - public const string OfferVersion_None = ""; - public const string OfferVersion_V1 = "V1"; - public const string OfferVersion_V2 = "V2"; - - public const string OfferType_Invalid = "Invalid"; - } - - public static class MongoServerVersion - { - public const string Version3_2 = "3.2"; - public const string Version3_6 = "3.6"; - public const string Version4_0 = "4.0"; - public const string Version4_2 = "4.2"; - public const string Version5_0 = "5.0"; - public const string Version6_0 = "6.0"; - public const string Version7_0 = "7.0"; - } - - internal static class Indexing - { - public const int IndexingSchemeVersionV1 = 1; - public const int IndexingSchemeVersionV2 = 2; - } - - public static class PartitionedQueryExecutionInfo - { - public const int Version_1 = 1; - public const int Version_2 = 2; - public const int CurrentVersion = PartitionedQueryExecutionInfo.Version_2; - } - - public static class Properties - { - public const string Resource = "resource"; - public const string Options = "options"; - public const string SubscriptionId = "subscriptionId"; - public const string FabricClientEndpoints = "fabricClientEndpoints"; - public const string SubscriptionUsageType = "subscriptionUsageType"; - public const string EnabledLocations = "enabledLocations"; - public const string SubscriptionState = "subscriptionState"; - public const string MigratedSubscriptionId = "migratedSubscriptionId"; - public const string QuotaId = "quotaId"; - public const string OfferCategories = "offerCategories"; - public const string DocumentServiceName = "documentServiceName"; - public const string OperationId = "operationId"; - public const string OperationDetails = "operationDetails"; - public const string AffinityGroupName = "affinityGroupName"; - public const string LocationName = "locationName"; - public const string SubRegionId = "subRegionId"; - public const string InstanceSize = "instanceSize"; - public const string Status = "status"; - public const string IsMerged = "merged"; - public const string RequestedStatus = "requestedStatus"; - public const string ExtendedStatus = "extendedStatus"; - public const string ExtendedResult = "extendedResult"; - public const string StatusCode = "statusCode"; - public const string DocumentEndpoint = "documentEndpoint"; - public const string TableEndpoint = "tableEndpoint"; - public const string TableSecondaryEndpoint = "tableSecondaryEndpoint"; - public const string GremlinEndpoint = "gremlinEndpoint"; - public const string CassandraEndpoint = "cassandraEndpoint"; - public const string EtcdEndpoint = "etcdEndpoint"; - public const string SqlEndpoint = "sqlEndpoint"; - public const string SqlxEndpoint = "sqlxEndpoint"; - public const string MongoEndpoint = "mongoEndpoint"; - public const string AnalyticsEndpoint = "analyticsEndpoint"; - public const string DatabaseAccountEndpoint = "databaseAccountEndpoint"; - public const string PrimaryMasterKey = "primaryMasterKey"; - public const string SecondaryMasterKey = "secondaryMasterKey"; - public const string PrimaryReadonlyMasterKey = "primaryReadonlyMasterKey"; - public const string SecondaryReadonlyMasterKey = "secondaryReadonlyMasterKey"; - public const string PrimaryMasterKeyGenerationTimestamp = "primaryMasterKeyGenerationTimestamp"; - public const string SecondaryMasterKeyGenerationTimestamp = "secondaryMasterKeyGenerationTimestamp"; - public const string PrimaryReadonlyKeyGenerationTimestamp = "primaryReadonlyKeyGenerationTimestamp"; - public const string SecondaryReadonlyKeyGenerationTimestamp = "secondaryReadonlyMasterKeyGenerationTimestamp"; - public const string DatabaseAccountKeysMetadata = "keysMetadata"; - public const string ConnectionStrings = "connectionStrings"; - public const string ConnectionString = "connectionString"; - public const string Description = "description"; - public const string ResourceKeySeed = "resourceKeySeed"; - public const string MaxStoredProceduresPerCollection = "maxStoredProceduresPerCollection"; - public const string MaxUDFsPerCollections = "maxUDFsPerCollections"; - public const string MaxTriggersPerCollection = "maxTriggersPerCollection"; - public const string IsolationLevel = "isolationLevel"; - public const string SubscriptionDisabled = "subscriptionDisabled"; - public const string IsDynamic = "isDynamic"; - public const string FederationName = "federationName"; - public const string FederationName1 = "federationName1"; - public const string FederationName2 = "federationName2"; - public const string FederationId = "federationId"; - public const string ComputeFederationId = "computeFederationId"; - public const string PlacementHint = "placementHint"; - public const string CreationTimestamp = "creationTimestamp"; - public const string SourceCreationTimestamp = "sourceCreationTimestamp"; - public const string SourceDeletionTimestamp = "sourceDeletionTimestamp"; - public const string ExtendedProperties = "extendedProperties"; - public const string KeyKind = "keyKind"; - public const string SystemKeyKind = "systemKeyKind"; - public const string ScaleUnits = "scaleUnits"; - public const string Location = "location"; - public const string Kind = "kind"; - public const string Region1 = "region1"; - public const string Region2 = "region2"; - public const string WritableLocations = "writableLocations"; - public const string ReadableLocations = "readableLocations"; - public const string Tags = "tags"; - public const string ResourceGroupName = "resourceGroupName"; - public const string PropertiesName = "properties"; - public const string RegionalPropertiesName = "regionalStateProperties"; - public const string ProvisioningState = "provisioningState"; - public const string CommunicationAPIKind = "communicationAPIKind"; - public const string UseMongoGlobalCacheAccountCursor = "useMongoGlobalCacheAccountCursor"; - public const string StorageSizeInMB = "storageSizeInMB"; - public const string DatabaseAccountOfferType = "databaseAccountOfferType"; - public const string Type = "type"; - public const string TargetType = "targetType"; - public const string TargetSku = "targetSku"; - public const string TargetTier = "targetTier"; - public const string Error = "error"; - public const string State = "state"; - public const string RegistrationDate = "registrationDate"; - public const string Value = "value"; - public const string NextLink = "nextLink"; - public const string DestinationSubscription = "destinationSubscription"; - public const string TargetResourceGroup = "targetResourceGroup"; - public const string ConfigurationOverrides = "configurationOverrides"; - public const string Name = "name"; - public const string Fqdn = "fqdn"; - public const string PublicIPAddressResourceName = "publicIPAddressName"; - public const string PublicIPAddressResourceGroup = "publicIPAddressResourceGroup"; - public const string VnetName = "vnetName"; - public const string VnetResourceGroup = "vnetResourceGroup"; - public const string Ipv4Address = "Ipv4Address"; - public const string RoleNameSuffix = "roleNameSuffix"; - public const string ReservedCname = "reservedCname"; - public const string ServiceType = "serviceType"; - public const string ServiceCount = "serviceCount"; - public const string TargetCapacityInMB = "targetCapacityInMB"; - public const string IsRuntimeServiceBindingEnabled = "isRuntimeServiceBindingEnabled"; - public const string MaxDocumentCollectionCount = "maxDocumentCollectionCount"; - public const string Reserved = "reserved"; - public const string Resources = "resources"; - public const string NamingConfiguration = "namingConfiguration"; - public const string DatabaseAccountName = "databaseAccountName"; - public const string DocumentServiceApiEndpoint = "documentServiceApiEndpoint"; - public const string Health = "health"; - public const string APIVersion = "APIVersion"; - public const string EmitArrayContainsForMongoQueries = "emitArrayContainsForMongoQueries"; - public const string Flights = "flights"; - public const string MigratedRegionalAccountName = "migratedRegionalAccountName"; - public const string DatabaseResourceId = "databaseResourceId"; - public const string SubscriptionKind = "subscriptionKind"; - public const string PlacementPolicies = "placementPolicies"; - public const string Action = "action"; - public const string Audience = "audience"; - public const string AudienceKind = "audienceKind"; - public const string OfferKind = "offerKind"; - public const string TenantId = "tenantId"; - public const string SupportedCapabilities = "supportedCapabilities"; - public const string PlacementHints = "placementHints"; - public const string IsMasterService = "isMasterService"; - public const string CapUncapMetadata = "capUncapMetadata"; - public const string IsCappedForServer = "isCappedForServer"; - public const string CapUncapMetadataForServer = "capUncapMetadataForServer"; - public const string IsCappedForMaster = "isCappedForMaster"; - public const string CapUncapMetadataForMaster = "capUncapMetadataForMaster"; - public const string CapabilityResource = "capabilityResource"; - public const string DocumentType = "documentType"; - public const string SystemDatabaseAccountStoreType = "systemDatabaseAccountStoreType"; - public const string FederationType = "federationType"; - public const string FederationGenerationKind = "federationGenerationKind"; - public const string UseEPKandNameAsPrimaryKeyInDocumentTable = "useEPKandNameAsPrimaryKeyInDocumentTable"; - public const string EnableUserDefinedType = "enableUserDefinedType"; - public const string ExcludeOwnerIdFromDocumentTable = "excludeOwnerIdFromDocumentTable"; - public const string EnableQuerySupportForHybridRow = "enableQuerySupportForHybridRow"; - public const string FederationProxyFqdn = "federationProxyFqdn"; - public const string IsFailedOver = "isFailedOver"; - public const string FederationProxyReservedCname = "federationProxyReservedCname"; - public const string EnableMultiMasterMigration = "enableMultiMasterMigration"; - public const string EnableNativeGridFS = "enableNativeGridFS"; - public const string MongoDefaultsVersion = "mongoDefaultsVersion"; - public const string ServerVersion = "serverVersion"; - public const string ContinuousBackupInformation = "continuousBackupInformation"; - public const string LatestRestorableTimestamp = "latestRestorableTimestamp"; - public const string EnableBinaryEncodingOfContent = "enableBinaryEncodingOfContent"; - public const string SkipMigrateToComputeDatabaseCollectionChecks = "skipMigrateToComputeDatabaseCollectionChecks"; - public const string UseApiOperationHandler = "UseApiOperationHandler"; - public const string AccountKeyManagementType = "accountKeyManagementType"; - public const string ManagedReadWriteAccountKeyResource = "managedReadWriteAccountKeyResource"; - public const string IsManagedReadWriteAccountKeyResourceStale = "isManagedReadWriteAccountKeyResourceStale"; - public const string ManagedReadOnlyAccountKeyResource = "managedReadOnlyAccountKeyResource"; - public const string IsManagedReadOnlyAccountKeyResourceStale = "isManagedReadOnlyAccountKeyResourceStale"; - public const string UserName = "userName"; - public const string Subscriptions = "subscriptions"; - public const string ResourceGroups = "resourceGroups"; - public const string Providers = "providers"; - public const string RestorableDatabaseAccounts = "restorableDatabaseAccounts"; - public const string AsynchronousDeletionRetryCount = "asynchronousDeletionRetryCount"; - public const string Severity = "severity"; - - public const string MasterValue = "masterValue"; - public const string SecondaryValue = "secondaryValue"; - - public const string ArmLocation = "armLocation"; - public const string SubscriptionName = "subscriptionName"; - - //Throughput Pool - public const string MaxThroughput = "maxThroughput"; - - // Query - public const string Query = "query"; - public const string Parameters = "parameters"; - - // Global Database account properties - public const string GlobalDatabaseAccountName = "globalDatabaseAccountName"; - public const string FailoverPriority = "failoverPriority"; - public const string FailoverPolicies = "failoverPolicies"; - public const string Locations = "locations"; - public const string WriteLocations = "writeLocations"; - public const string ReadLocations = "readLocations"; - public const string LocationType = "locationType"; - public const string MasterServiceUri = "masterServiceUri"; - public const string RestoreParams = "restoreParameters"; - public const string CreateMode = "createMode"; - public const string RestoreMode = "restoreMode"; - public const string StoreType = "storeType"; - - // CSM Metric properties - public const string LocalizedValue = "localizedValue"; - public const string Unit = "unit"; - public const string ResourceUri = "resourceUri"; - public const string PrimaryAggregationType = "primaryAggregationType"; - public const string MetricAvailabilities = "metricAvailabilities"; - public const string MetricValues = "metricValues"; - public const string TimeGrain = "timeGrain"; - public const string Retention = "retention"; - public const string TimeStamp = "timestamp"; - public const string Average = "average"; - public const string Minimum = "minimum"; - public const string Maximum = "maximum"; - public const string MetricCount = "count"; - public const string Total = "total"; - public const string StartTime = "startTime"; - public const string EndTime = "endTime"; - public const string DisplayName = "displayName"; - public const string Limit = "limit"; - public const string CurrentValue = "currentValue"; - public const string NextResetTime = "nextResetTime"; - public const string QuotaPeriod = "quotaPeriod"; - public const string SupportedRegions = "supportedRegions"; - public const string Percentiles = "percentiles"; - public const string SourceRegion = "sourceRegion"; - public const string TargetRegion = "targetRegion"; - public const string P10 = "P10"; - public const string P25 = "P25"; - public const string P50 = "P50"; - public const string P75 = "P75"; - public const string P90 = "P90"; - public const string P95 = "P95"; - public const string P99 = "P99"; - - public const string Id = "id"; - public const string RId = "_rid"; - public const string SelfLink = "_self"; - public const string LastModified = "_ts"; - public const string CreatedTime = "_cts"; - public const string Count = "_count"; - public const string ETag = "_etag"; - public const string TimeToLive = "ttl"; - public const string DefaultTimeToLive = "defaultTtl"; - public const string TimeToLivePropertyPath = "ttlPropertyPath"; - public const string AnalyticalStorageTimeToLive = "analyticalStorageTtl"; - - public const string DatabasesLink = "_dbs"; - public const string CollectionsLink = "_colls"; - public const string UsersLink = "_users"; - public const string PermissionsLink = "_permissions"; - public const string AttachmentsLink = "_attachments"; - public const string StoredProceduresLink = "_sprocs"; - public const string TriggersLink = "_triggers"; - public const string UserDefinedFunctionsLink = "_udfs"; - public const string ConflictsLink = "_conflicts"; - public const string DocumentsLink = "_docs"; - public const string ResourceLink = "resource"; - public const string MediaLink = "media"; - public const string SchemasLink = "_schemas"; - - public const string PermissionMode = "permissionMode"; - public const string ResourceKey = "key"; - public const string Token = "_token"; - - public const string FederationOperationKind = "federationOperationKind"; - public const string RollbackKind = "rollbackKind"; - - // Collection Truncate - public const string CollectionTruncate = "collectionTruncate"; - - // Indexing Policy. - public const string IndexingPolicy = "indexingPolicy"; - public const string Automatic = "automatic"; - public const string StringPrecision = "StringPrecision"; - public const string NumericPrecision = "NumericPrecision"; - public const string MaxPathDepth = "maxPathDepth"; - public const string IndexingMode = "indexingMode"; - public const string IndexType = "IndexType"; - public const string IndexKind = "kind"; - public const string DataType = "dataType"; - public const string Precision = "precision"; - public const string PartitionKind = "kind"; - public const string SystemKey = "systemKey"; - - public const string Paths = "paths"; - public const string Path = "path"; - public const string IsFullIndex = "isFullIndex"; - public const string Filter = "filter"; - public const string FrequentPaths = "Frequent"; - public const string IncludedPaths = "includedPaths"; - public const string InFrequentPaths = "InFrequent"; - public const string ExcludedPaths = "excludedPaths"; - public const string Indexes = "indexes"; - public const string IndexingSchemeVersion = "IndexVersion"; - - public const string CompositeIndexes = "compositeIndexes"; - public const string Order = "order"; - - public const string SpatialIndexes = "spatialIndexes"; - public const string Types = "types"; - public const string BoundingBox = "boundingBox"; - public const string Xmin = "xmin"; - public const string Ymin = "ymin"; - public const string Xmax = "xmax"; - public const string Ymax = "ymax"; - - public const string EnableIndexingSchemeV2 = "enableIndexingSchemeV2"; - - // CapUncapMetadata - public const string Source = "source"; - public const string Reason = "reason"; - public const string IncidentId = "incidentId"; - - // GeospatialConfig - public const string GeospatialType = "type"; - public const string GeospatialConfig = "geospatialConfig"; - - // ComputedProperties - public const string ComputedProperties = "computedProperties"; - - // Unique index. - public const string UniqueKeyPolicy = "uniqueKeyPolicy"; - public const string UniqueKeys = "uniqueKeys"; - public const string UniqueIndexReIndexContext = "uniqueIndexReIndexContext"; - public const string UniqueIndexReIndexingState = "uniqueIndexReIndexingState"; - public const string LastDocumentGLSN = "lastDocumentGLSN"; - public const string UniqueIndexNameEncodingMode = "uniqueIndexNameEncodingMode"; - - // ReIndexer - public const string EnableReIndexerProgressCalc = "enableReIndexerProgressCalc"; - - // ChangeFeed policy - public const string ChangeFeedPolicy = "changeFeedPolicy"; - public const string LogRetentionDuration = "retentionDuration"; - - //MaterializedViewDefinition - public const string MaterializedViewDefinition = "materializedViewDefinition"; - public const string AllowMaterializedViews = "allowMaterializedViews"; - public const string SourceCollectionRid = "sourceCollectionRid"; - public const string SourceCollectionId = "sourceCollectionId"; - public const string Definition = "definition"; - public const string ApiSpecificDefinition = "apiSpecificDefinition"; - public const string AllowMaterializedViewsInCollectionDeleteRollForward = "allowMaterializedViewsInCollectionDeleteRollForward"; - public const string MaterializedViews = "materializedViews"; - - //TieredStorageCollection - public const string MaterializedViewContainerType = "containerType"; - - // Schema Policy - public const string SchemaPolicy = "schemaPolicy"; - - // PartitionKeyDelete - public const string PartitionKeyDeleteThroughputFraction = "partitionKeyDeleteThroughputFraction"; - public const string EnableMultiRegionGlsnCheckForPKDelete = "enableMultiRegionGlsnCheckForPKDelete"; - - // Internal Schema Properties - public const string InternalSchemaProperties = "internalSchemaProperties"; - public const string UseSchemaForAnalyticsOnly = "useSchemaForAnalyticsOnly"; - - // ReplicaResource - public const string Quota = "quota"; - - // PartitionInfo - public const string ResourceType = "resourceType"; - public const string ServiceIndex = "serviceIndex"; - public const string PartitionIndex = "partitionIndex"; - - // ModuleCommand - public const string ModuleEvent = "moduleEvent"; - public const string ModuleEventReason = "moduleEventReason"; - public const string ModuleStatus = "moduleStatus"; - public const string ThrottleLevel = "throttleLevel"; - public const string ProcessId = "processId"; - public const string HasFaulted = "hasFaulted"; - public const string Result = "result"; - - // ConsistencyPolicy - public const string ConsistencyPolicy = "consistencyPolicy"; - public const string DefaultConsistencyLevel = "defaultConsistencyLevel"; - public const string MaxStalenessPrefix = "maxStalenessPrefix"; - public const string MaxStalenessIntervalInSeconds = "maxIntervalInSeconds"; - - // ReplicationPolicy - public const string ReplicationPolicy = "replicationPolicy"; - public const string AsyncReplication = "asyncReplication"; - public const string MaxReplicaSetSize = "maxReplicasetSize"; - public const string MinReplicaSetSize = "minReplicaSetSize"; - - // WritePolicy. - public const string WritePolicy = "writePolicy"; - public const string PrimaryCheckpointInterval = "primaryLoggingIntervalInMilliSeconds"; - public const string SecondaryCheckpointInterval = "secondaryLoggingIntervalInMilliSeconds"; - - // Backup container properties - public const string Collection = "RootResourceName"; - public const string CollectionId = "collectionId"; - public const string Completed = "completed"; - public const string BackupOfferType = "OfferType"; - public const string BackupDatabaseAccountName = "x_ms_databaseAccountName"; - public const string BackupContainerName = "backupContainerName"; - public const string UniquePartitionIdentifier = "UniquePartitionIdentifier"; - - // Backup store settings - public const string BackupStoreUri = "fileUploaderUri"; - public const string BackupStoreAccountName = "fileUploaderAccountName"; - - // Backup Policy - public const string GlobalBackupPolicy = "globalBackupPolicy"; - public const string BackupPolicy = "backupPolicy"; - public const string CollectionBackupPolicy = "backupPolicy"; - public const string CollectionBackupType = "type"; - public const string BackupStrategy = "backupStrategy"; - public const string BackupRedundancy = "backupRedundancy"; - public const string BackupStorageRedundancy = "backupStorageRedundancy"; - public const string BackupIntervalInMinutes = "backupIntervalInMinutes"; - public const string BackupRetentionIntervalInHours = "backupRetentionIntervalInHours"; - public const string PeriodicModeProperties = "periodicModeProperties"; - public const string ContinuousModeProperties = "continuousModeProperties"; - public const string BackupPolicyMigrationState = "migrationState"; - - // PITR Migration - public const string PitrMigrationState = "pitrMigrationState"; - public const string PitrMigrationStatus = "pitrMigrationStatus"; - public const string PitrMigrationBeginTimestamp = "pitrMigrationBeginTimestamp"; - public const string PitrMigrationEndTimestamp = "pitrMigrationEndTimestamp"; - public const string PitrMigrationAttemptTimestamp = "pitrMigrationAttemptTimestamp"; - public const string PreMigrationBackupPolicy = "preMigrationBackupPolicy"; - public const string LastPitrStandardOptInTimestamp = "lastPitrStandardOptInTimestamp"; - public const string LastPitrBasicOptInTimestamp = "lastPitrBasicOptInTimestamp"; - public const string PitrMigrationStartTimestamp = "startTime"; - public const string TargetPitrSku = "targetPitrSku"; - - // Backup Storage Accounts - public const string BackupStorageAccountsEnabled = "BackupStorageAccountsEnabled"; - public const string BackupStorageAccountNames = "BackupStorageAccountNames"; - public const string BackupStorageUris = "BackupStorageUris"; - public const string TotalNumberOfDedicatedStorageAccounts = "TotalNumberOfDedicatedStorageAccounts"; - public const string ReplaceOriginalBackupStorageAccounts = "replaceOriginalBackupStorageAccounts"; - public const string StandardStreamGRSStorageServiceNames = "standardStreamGRSStorageServiceNames"; - public const string EnableDedicatedStorageAccounts = "enableDedicatedStorageAccounts"; - public const string EnableSystemSnapshots = "enableSystemSnapshots"; - public const string BackupStorageRedundancies = "backupStorageRedundancies"; - public const string StorageAccountName = "storageAccountName"; - public const string StorageAccountLocation = "storageAccountLocation"; - - // Restore Policy - public const string RestorePolicy = "restorePolicy"; - public const string SourceServiceName = "sourceServiceName"; - public const string RegionalDatabaseAccountInstanceId = "regionalDatabaseAccountInstanceId"; - public const string GlobalDatabaseAccountInstanceId = "globalDatabaseAccountInstanceId"; - public const string InstanceId = "instanceId"; - public const string SourceBackupLocation = "sourceBackupLocation"; - public const string ReuseSourceDatabaseAccountAccessKeys = "reuseSourceDatabaseAccountAccessKeys"; - public const string RecreateDatabase = "recreateDatabase"; - public const string LatestBackupSnapshotInDateTime = "latestBackupSnapshotInDateTime"; - public const string TargetFederation = "targetFederation"; - public const string TargetFederationKind = "targetFederationKind"; - public const string CollectionOrDatabaseResourceIds = "collectionOrDatabaseResourceIds"; - public const string SourceHasMultipleStorageAccounts = "sourceHasMultipleStorageAccounts"; - public const string AllowPartialRestore = "allowPartialRestore"; - public const string DedicatedBackupAccountNames = "dedicatedBackupAccountNames"; - public const string AllowPartitionsRestoreOptimization = "allowPartitionsRestoreOptimization"; - public const string UseUniquePartitionIdBasedRestoreWorkflow = "useUniquePartitionIdBasedRestoreWorkflow"; - public const string UseSnapshotToRestore = "useSnapshotToRestore"; - public const string AllowVnetRestore = "allowVnetRestore"; - public const string UpdateBackupContainerMetadata = "updateBackupContainerMetadata"; - public const string RestoreWithBuiltinDatabaseAccountPicker = "restoreWithBuiltinDatabaseAccountPicker"; - public const string RestoreWithSourceGlobalDatabaseAccountInstanceId = "restoreWithSourceGlobalDatabaseAccountInstanceId"; - public const string RestoreWithTTLDisabled = "restoreWithTTLDisabled"; - public const string DatabasesToRestore = "databasesToRestore"; - public const string DatabaseName = "databaseName"; - public const string CollectionNames = "collectionNames"; - public const string GraphNames = "graphNames"; - public const string TableNames = "tableNames"; - public const string RestoreTillEndOfLogChain = "restoreTillEndOfLogChain"; - public const int TimeToleranceForRestoreTillEndOfLogChain = 1000; //ms - - // Restore Properties - public const string RestoreTimestampInUtc = "restoreTimestampInUtc"; - public const string RestoreSource = "restoreSource"; - public const string IsInAccountRestoreCapabilityEnabled = "isInAccountRestoreCapabilityEnabled"; - public const string CanUndelete = "CanUndelete"; - public const string CanUndeleteReason = "CanUndeleteReason"; - - // Backup Hold - public const string BackupHoldTimeInDays = "backupHoldTimeInDays"; - - // Restore Tags - public const string RestoredSourceDatabaseAccountName = "restoredSourceDatabaseAccountName"; - public const string RestoredAtTimestamp = "restoredAtTimestamp"; - - // Read Policy - // Indicates the relative weight of read from primary compared to secondary. - // Higher this value, cheaper are the reads from primary. - public const string PrimaryReadCoefficient = "primaryReadCoefficient"; - public const string SecondaryReadCoefficient = "secondaryReadCoefficient"; - - // Scripting - public const string Body = "body"; - public const string TriggerType = "triggerType"; - public const string TriggerOperation = "triggerOperation"; - - public const string MaxSize = "maxSize"; - - public const string Content = "content"; - - public const string ContentType = "contentType"; - - // ErrorResource. - public const string Code = "code"; - public const string Message = "message"; - public const string ErrorDetails = "errorDetails"; - public const string AdditionalErrorInfo = "additionalErrorInfo"; - - //CassandraErrorResource. - public const string Target = "target"; - - // AddressResource - public const string IsPrimary = "isPrimary"; - public const string Protocol = "protocol"; - public const string LogicalUri = "logicalUri"; - public const string PhysicalUri = "physcialUri"; - - // Authorization - public const string AuthorizationFormat = "type={0}&ver={1}&sig={2}"; - public const string MasterToken = "master"; - public const string ResourceToken = "resource"; - public const string AadToken = "aad"; - public const string SasToken = "sas"; - public const string TokenVersion = "1.0"; - public const string TokenVersionV2 = "2.0"; - public const string AuthSchemaType = "type"; - public const string ResourceTokenV2Label = "ResourceTokenV2Label"; - public const string ResourceTokenV2Context = "ResourceTokenV2Context"; - public const string AuthVersion = "ver"; - public const string AuthSignature = "sig"; - public const string readPermissionMode = "read"; - public const string allPermissionMode = "all"; - - // Federation Resource - public const string PackageVersion = "packageVersion"; - public const string FabricApplicationVersion = "fabricApplicationVersion"; - public const string FabricRingCodeVersion = "fabricRingCodeVersion"; - public const string FabricRingConfigVersion = "fabricRingConfigVersion"; - public const string CertificateVersion = "certificateVersion"; - public const string DeploymentId = "deploymentId"; - public const string DecommisionedFederations = "decommisionedFederations"; - public const string FederationKind = "federationKind"; - public const string SupportedPlacementHints = "supportedPlacementHints"; - public const string PrimarySystemKeyReadOnly = "primarySystemKeyReadOnly"; - public const string SecondarySystemKeyReadOnly = "secondarySystemKeyReadOnly"; - public const string UsePrimarySystemKeyReadOnly = "UsePrimarySystemKeyReadOnly"; - public const string PrimarySystemKeyReadWrite = "primarySystemKeyReadWrite"; - public const string SecondarySystemKeyReadWrite = "secondarySystemKeyReadWrite"; - public const string UsePrimarySystemKeyReadWrite = "UsePrimarySystemKeyReadWrite"; - public const string PrimarySystemKeyAll = "primarySystemKeyAll"; - public const string SecondarySystemKeyAll = "secondarySystemKeyAll"; - public const string UsePrimarySystemKeyAll = "UsePrimarySystemKeyAll"; - public const string UseSecondaryComputeGatewayKey = "UseSecondaryComputeGatewayKey"; - public const string Weight = "Weight"; - public const string BatchId = "BatchId"; - public const string IsCappedForServerPartitionAllocation = "isCappedForServerPartitionAllocation"; - public const string IsDirty = "IsDirty"; - public const string IsAvailabilityZoneFederation = "IsAvailabilityZoneFederation"; - public const string AZIndex = "AZIndex"; - public const string IsFederationUnavailable = "isFederationUnavailable"; - public const string ServiceExtensions = "serviceExtensions"; - public const string HostedServicesDescription = "hostedServicesDescription"; - public const string CsesMigratedHostedServicesDescription = "csesMigratedHostedServicesDescription"; - public const string FederationProxyResource = "federationProxyResource"; - public const string ReservedDnsName = "reservedDnsName"; - public const string BuildoutStatus = "BuildoutStatus"; - public const string IsCsesCloudService = "IsCsesCloudService"; - public const string IsInBitLockerRotation = "IsInBitLockerRotation"; - public const string PrimaryBitLockerKeyVersion = "PrimaryBitLockerKeyVersion"; - public const string SecondaryBitLockerKeyVersion = "SecondaryBitLockerKeyVersion"; - public const string BitLockerKeysSettingType = "BitLockerKeysSettingType"; - public const string BitLockerKeysRotationState = "BitLockerKeysRotationState"; - public const string InfrastructureServices = "InfrastructureServices"; - public const string SerializableResourceType = "SerializableResourceType"; - - // Federation settings - public const string AllowReutilizationOfComputeResources = "AllowReutilizationOfComputeResources"; - - //Deployment Constants - public const string FabricApplicationName = "fabricApplicationName"; - public const string UseMonitoredUpgrade = "useMonitoredUpgrade"; - public const string UpgradeInfo = "UpgradeInfo"; - - // ManagementVersion Resource - public const string Version = "Version"; - public const string ManagementEndPoint = "ManagementEndPoint"; - - // StorageService Resource - public const string StorageServiceName = "name"; - public const string StorageServiceLocation = "location"; - public const string BlobEndpoint = "blobEndpoint"; - public const string StorageServiceSubscriptionId = "subscriptionId"; - public const string StorageServiceIndex = "storageIndex"; - public const string IsWritable = "isWritable"; - public const string StorageServiceKind = "storageServiceKind"; - public const string StorageAccountType = "storageAccountType"; - public const string StorageServiceResourceGroupName = "resourceGroupName"; - public const string StorageServiceFederationId = "federationId"; - public const string StorageAccountSku = "storageAccountSku"; - public const string IsRegisteredWithSms = "isRegisteredWithSms"; - public const string StorageAccountVersion = "storageAccountVersion"; - public const string StorageAccounts = "StorageAccounts"; - - // Cassandra Connector Constants - public const string ConnectorOffer = "connectorOffer"; - public const string EnableCassandraConnector = "enableCassandraConnector"; - public const string ConnectorMetadataAccountInfo = "connectorMetadataAccountInfo"; - public const string ConnectorMetadataAccountPrimaryKey = "connectorMetadataAccountPrimaryKey"; - public const string ConnectorMetadataAccountSecondaryKey = "connectorMetadataAccountSecondaryKey"; - public const string StorageServiceResource = "storageServiceResource"; - public const string OfferName = "offerName"; - public const string MaxNumberOfSupportedNodes = "maxNumberOfSupportedNodes"; - public const string MaxAllocationsPerStorageAccount = "maxAllocationsPerStorageAccount"; - public const string StorageAccountCount = "storageAccountCount"; - public const string ConnectorStorageAccounts = "connectorStorageAccounts"; - public const string UserProvidedConnectorStorageAccountsInfo = "userProvidedConnectorStorageAccountsInfo"; - public const string UserString = "User"; - public const string SystemString = "System"; - public const string ReplicationStatus = "ReplicationStatus"; - - // ResourceIdResponse Resource - public const string ResourceId = "resourceId"; - - // Managed Service Identity (MSI) - public const string ManagedServiceIdentityInfo = "managedServiceIdentityInfo"; - public const string IdentityName = "identity"; - public const string MsiSystemAssignedType = "SystemAssigned"; - public const string MsiFirstPartyType = "FirstParty"; - public const string MsiNoneType = "None"; - public const string MsiUserAssignedType = "UserAssigned"; - public const string MsiSystemAndUserAssignedType = "SystemAssigned,UserAssigned"; - public const string DefaultIdentity = "defaultIdentity"; - public const string MsiDelegatedUserAssignedType = "DelegatedUserAssigned"; // only used for DefaultMsiProperties - public const string MsiDelegatedSystemAssignedType = "DelegatedSystemAssigned"; // only used for DefaultMsiProperties - - // ServiceDocument Resource - public const string AddressesLink = "addresses"; - public const string UserReplicationPolicy = "userReplicationPolicy"; - public const string UserConsistencyPolicy = "userConsistencyPolicy"; - public const string SystemReplicationPolicy = "systemReplicationPolicy"; - public const string ReadPolicy = "readPolicy"; - public const string QueryEngineConfiguration = "queryEngineConfiguration"; - public const string EnableMultipleWriteLocations = "enableMultipleWriteLocations"; - public const string CanEnableMultipleWriteLocations = "canEnableMultipleWriteLocations"; - public const string IsServerlessEnabled = "isServerlessEnabled"; - public const string EnableSnapshotAcrossDocumentStoreAndIndex = "enableSnapshotAcrossDocumentStoreAndIndex"; - public const string IsZoneRedundant = "isZoneRedundant"; - public const string EnableThroughputAutoScale = "enableThroughputAutoScale"; - public const string ReplicatorSequenceNumberToGLSNDeltaString = "replicatorSequenceNumberToGLSNDeltaString"; - public const string ReplicatorSequenceNumberToLLSNDeltaString = "replicatorSequenceNumberToLLSNDeltaString"; - public const string IsReplicatorSequenceNumberToLLSNDeltaSet = "isReplicatorSequenceNumberToLLSNDeltaSet"; - - // Serverless Configs for 1TB, splits enabled. - public const string IsSplitOnServerlessEnabled = "isSplitOnServerlessEnabled"; - public const string IsRequestLatencyInjectionEnabledForServerless = "isRequestLatencyInjectionEnabledForServerless"; - - public const string LSN = "_lsn"; - public const string LLSN = "llsn"; - - // Conflict Resource Properties - public const string SourceResourceId = "resourceId"; - - // ConflictResource property values - public const string ResourceTypeDocument = "document"; - public const string ResourceTypeStoredProcedure = "storedProcedure"; - public const string ResourceTypeTrigger = "trigger"; - public const string ResourceTypeUserDefinedFunction = "userDefinedFunction"; - public const string ResourceTypeAttachment = "attachment"; - - public const string ConflictLSN = "conflict_lsn"; - - public const string OperationKindCreate = "create"; - public const string OperationKindPatch = "patch"; - public const string OperationKindReplace = "replace"; - public const string OperationKindDelete = "delete"; - - // Conflict - public const string Conflict = "conflict"; - public const string OperationType = "operationType"; - - // Tombstone resource - public const string TombstoneResourceType = "resourceType"; - public const string OwnerId = "ownerId"; - - // Partition resource - public const string CollectionResourceId = "collectionResourceId"; - public const string PartitionKeyRangeResourceId = "partitionKeyRangeResourceId"; - public const string WellKnownServiceUrl = "wellKnownServiceUrl"; - public const string LinkRelationType = "linkRelationType"; - public const string Region = "region"; - public const string GeoLinkIdentifier = "geoLinkIdentifier"; - - // Progress resource - public const string DatalossNumber = "datalossNumber"; - public const string ConfigurationNumber = "configurationNumber"; - - // Replica resource - public const string PartitionId = "partitionId"; - public const string SchemaVersion = "schemaVersion"; - public const string ReplicaId = "replicaId"; - public const string ReplicaRole = "replicaRole"; - public const string ReplicatorAddress = "replicatorAddress"; - public const string ReplicaStatus = "replicaStatus"; - public const string IsAvailableForWrites = "isAvailableForWrites"; - - // Offer resource - public const string OfferType = "offerType"; - public const string OfferResourceId = "offerResourceId"; - public const string OfferThroughput = "offerThroughput"; - public const string BackgroundTaskMaxAllowedThroughputPercent = "BackgroundTaskMaxAllowedThroughputPercent"; - public const string OfferIsRUPerMinuteThroughputEnabled = "offerIsRUPerMinuteThroughputEnabled"; - public const string OfferIsAutoScaleEnabled = "offerIsAutoScaleEnabled"; - public const string OfferVersion = "offerVersion"; - public const string OfferContent = "content"; - public const string CollectionThroughputInfo = "collectionThroughputInfo"; - public const string MinimumRuForCollection = "minimumRUForCollection"; - public const string NumPhysicalPartitions = "numPhysicalPartitions"; - public const string UserSpecifiedThroughput = "userSpecifiedThroughput"; - public const string OfferMinimumThroughputParameters = "offerMinimumThroughputParameters"; - public const string MaxConsumedStorageEverInKB = "maxConsumedStorageEverInKB"; - public const string MaxThroughputEverProvisioned = "maxThroughputEverProvisioned"; - public const string MaxCountOfSharedThroughputCollectionsEverCreated = "maxCountOfSharedThroughputCollectionsEverCreated"; - public const string OfferLastReplaceTimestamp = "offerLastReplaceTimestamp"; - public const string AutopilotSettings = "offerAutopilotSettings"; - public const string IsOfferRestorePending = "isOfferRestorePending"; - public const int DefaultContainerCountForSharedThroughput = 25; - - public const string AutopilotTier = "tier"; - public const string AutopilotTargetTier = "targetTier"; - public const string AutopilotMaximumTierThroughput = "maximumTierThroughput"; - public const string AutopilotAutoUpgrade = "autoUpgrade"; - public const string EnableFreeTier = "enableFreeTier"; - - public const string AutopilotMaxThroughput = "maxThroughput"; - public const string AutopilotTargetMaxThroughput = "targetMaxThroughput"; - public const string AutopilotAutoUpgradePolicy = "autoUpgradePolicy"; - public const string AutopilotThroughputPolicy = "throughputPolicy"; - public const string AutopilotThroughputPolicyIncrementPercent = "incrementPercent"; - - public const string PhysicalPartitionThroughputInfo = "physicalPartitionThroughputInfo"; - public const string SourcePhysicalPartitionThroughputInfo = "sourcePhysicalPartitionThroughputInfo"; - public const string TargetPhysicalPartitionThroughputInfo = "targetPhysicalPartitionThroughputInfo"; - public const string ThroughputPolicy = "throughputPolicy"; - public const string PhysicalPartitionStorageInfoCollection = "physicalPartitionStorageInfoCollection"; - public const string PhysicalPartitionId = "id"; - public const string PhysicalPartitionIds = "physicalPartitionIds"; - public const string PhysicalPartitionThroughput = "throughput"; - public const string PhysicalPartitionStorageInKB = "storageInKB"; - - public const string EnableAdaptiveRu = "enableAdaptiveRU"; - - public const string EnablePartitionMerge = "enablePartitionMerge"; - - public const string EnableBurstCapacity = "enableBurstCapacity"; - public const string EnableUserRateLimitingWithBursting = "enableUserRateLimitingWithBursting"; - - // Priority Based Execution can be enabled by setting the naming config enablePriorityBasedThrottling to true - // When user sets EnablePriorityBasedExecution to true in an account PATCH request, enablePriorityBasedThrottling - // is set to true in the account configuration overrrides - public const string EnablePriorityBasedThrottling = "enablePriorityBasedThrottling"; - public const string EnablePriorityBasedExecution = "enablePriorityBasedExecution"; - public const string DefaultPriorityLevel = "defaultPriorityLevel"; - - // Global Rate Limiting - public const string EnableGlobalRateLimiting = "enableGlobalRateLimiting"; - // Cap the global budget for a partition. The value includes provisioned local budget. It cannot exceed 10K. - public const string GRLTargetUtilizationPerPartition = "GRLTargetUtilizationPerPartition"; - - public const string IsDryRun = "isDryRun"; - - // EnforceRUPerGB - public const string EnforceRUPerGB = "enforceRUPerGB"; - public const string MinRUPerGB = "minRUPerGB"; - - // Storage Management Store - public const string EnableStorageAnalytics = "enableStorageAnalytics"; - public const string EnablePitrAndAnalyticsTogether = "enablePitrAndAnalyticsTogether"; - public const string AnalyticsStorageServiceNames = "analyticsStorageServiceNames"; - public const string LogStoreMetadataStorageAccountName = "logStoreMetadataStorageAccountName"; - public const string IsParallel = "isParallel"; - public const string SasAuthEnabled = "sasAuthEnabled"; - public const string AnalyticsSubDomain = ".analytics.cosmos."; - public const string DocumentsSubDomain = ".documents"; - - // GeoDrReplicaInformationResource - public const string CurrentProgress = "currentProgress"; - public const string CatchupCapability = "catchupCapability"; - public const string PublicAddress = "publicAddress"; - - // Operation resource - public const string OperationName = "name"; - public const string OperationProperties = "properties"; - public const string OperationNextLink = "nextLink"; - public const string OperationDisplay = "display"; - public const string OperationDisplayProvider = "provider"; - public const string OperationDisplayResource = "resource"; - public const string OperationDisplayOperation = "operation"; - public const string OperationDisplayDescription = "description"; - - public const string PartitionKey = "partitionKey"; - public const string PartitionKeyRangeId = "partitionKeyRangeId"; - public const string MinInclusiveEffectivePartitionKey = "minInclusiveEffectivePartitionKey"; - public const string MaxExclusiveEffectivePartitionKey = "maxExclusiveEffectivePartitionKey"; - public const string MinInclusive = "minInclusive"; - public const string MaxExclusive = "maxExclusive"; - public const string RidPrefix = "ridPrefix"; - public const string ThroughputFraction = "throughputFraction"; - public const string PartitionKeyRangeStatus = "status"; - public const string Parents = "parents"; - public const string Lsn = "lsn"; - - public const string NodeStatus = "NodeStatus"; - public const string NodeName = "NodeName"; - public const string HealthState = "HealthState"; - - // CLient side encryption - public const string WrappedDataEncryptionKey = "wrappedDataEncryptionKey"; - public const string EncryptionAlgorithmId = "encryptionAlgorithmId"; - public const string KeyWrapMetadata = "keyWrapMetadata"; - public const string KeyWrapMetadataName = "name"; - public const string KeyWrapMetadataType = "type"; - public const string KeyWrapMetadataValue = "value"; - public const string KeyWrapMetadataAlgorithm = "algorithm"; - public const string EncryptedInfo = "_ei"; - public const string DataEncryptionKeyRid = "_ek"; - public const string EncryptionFormatVersion = "_ef"; - public const string EncryptedData = "_ed"; - public const string ClientEncryptionKeyId = "clientEncryptionKeyId"; - public const string EncryptionType = "encryptionType"; - public const string EncryptionAlgorithm = "encryptionAlgorithm"; - public const string ClientEncryptionPolicy = "clientEncryptionPolicy"; - - public const string DataMaskingPolicy = "dataMaskingPolicy"; - public const string IsPolicyEnabled = "isPolicyEnabled"; - - // ParitionKey Monitor - public const string EnablePartitionKeyMonitor = "enablePartitionKeyMonitor"; - - // Operation diagnostic logs - public const string Origin = "origin"; - public const string AzureMonitorServiceSpecification = "serviceSpecification"; - public const string DiagnosticLogSpecifications = "logSpecifications"; - public const string DiagnosticLogsName = "name"; - public const string DiagnosticLogsDisplayName = "displayName"; - public const string BlobDuration = "blobDuration"; - - // FederationPolicyOverrideResource - public const string FederationPolicyOverride = "federationPolicyOverride"; - public const string MaxCapacityUnits = "maxCapacityUnits"; - public const string MaxDatabaseAccounts = "maxDatabaseAccounts"; - public const string MaxBindableServicesPercentOfFreeSpace = "maxBindableServicesPercentOfFreeSpace"; - public const string DisabledDatabaseAccountManager = "disabledDatabaseAccountManager"; - public const string EnableBsonSchemaOnNewAccounts = "enableBsonSchemaOnNewAccounts"; - - // Metric Definitions - public const string MetricSpecifications = "metricSpecifications"; - public const string DisplayDescription = "displayDescription"; - public const string AggregationType = "aggregationType"; - public const string LockAggregationType = "lockAggregationType"; - public const string SourceMdmAccount = "sourceMdmAccount"; - public const string SourceMdmNamespace = "sourceMdmNamespace"; - public const string FillGapWithZero = "fillGapWithZero"; - public const string Category = "category"; - public const string ResourceIdOverride = "resourceIdDimensionNameOverride"; - public const string Dimensions = "dimensions"; - public const string InternalName = "internalName"; - public const string IsHidden = "isHidden"; - public const string DefaultDimensionValues = "defaultDimensionValues"; - public const string Availabilities = "availabilities"; - public const string InternalMetricName = "internalMetricName"; - public const string SupportedTimeGrainTypes = "supportedTimeGrainTypes"; - public const string SupportedAggregationTypes = "supportedAggregationTypes"; - - // Metric ID Mapping Dimension names (Multi-Resource Metrics) - public const string MicrosoftSubscriptionId = "Microsoft.subscriptionId"; - public const string MicrosoftResourceGroupName = "Microsoft.resourceGroupName"; - public const string MicrosoftResourceType = "Microsoft.resourceType"; - public const string MicrosoftResourceName = "Microsoft.resourceName"; - public const string MicrosoftResourceId = "Microsoft.resourceId"; - - // IP Range resource - public const string IpRangeFilter = "ipRangeFilter"; - public const string IpRules = "ipRules"; - public const string IpAddressOrRange = "ipAddressOrRange"; - - // Property to check if point in time restore is enabled for a global database account - public const string PitrEnabled = "pitrEnabled"; - public const string PitrSku = "pitrSku"; - public const string ReservedInstanceType = "reservedInstanceType"; - public const string ContinuousBackupTier = "tier"; - public const string EnablePitrMigration = "enablePITRMigration"; - public const string EnableLogstoreHeadStartSequenceVector = "enableLogStoreHeadStartSequenceVector"; - public const string AllowSkippingOpLogFlushInRestore = "allowSkippingOpLogFlushInRestore"; - - // Property to allow PITR disabling - public const string AllowPitrDisabling = "allowPITRDisabling"; - - // Property to allow migration to analytical store - public const string AllowCollectionMigrationToAnalyticalStore = "allowCollectionMigrationToAnalyticalStore"; - public const string AllowMongoCollectionMigrationToAnalyticalStore = "allowMongoCollectionMigrationToAnalyticalStore"; - - // Property to enable storage analytics - public const string EnableAnalyticalStorage = "enableAnalyticalStorage"; - - // Properties related to Autoscale billing improvements. - public const string EnableAutoscaleThroughputUtilizationReporting = "enableAutoscaleThroughputUtilizationReporting"; // Configuration to report throughput utilization for autoscale billing. - public const string EnablePerRegionAutoscale = "enablePerRegionAutoscale"; //Configuration to enable PerRegion autoscale billing. - public const string EnableThroughputUtilizationPersistence = "enableThroughputUtilizationPersistence"; // configuration to enable throughput utlization persistance for server replica - public const string EnablePerRegionPerPartitionAutoscale = "enablePerRegionPerPartitionAutoscale"; // Property used in RP call to enable/disable the AutoscalePerRegion feature - public const string EnablePerRegionPerPartitionAutoscaleOptIn = "enablePerRegionPerPartitionAutoscaleOptIn"; // config override which will be used to determine if feature can be enabled or not - - //properties to enable MaterializedViews - public const string EnableMaterializedViews = "enableMaterializedViews"; //at DB account level. - public const string EnableOnlyColdStorageContainersInAccountV1 = "enableOnlyColdStorageContainersInAccountV1"; - - // property to enable full fidelity change feed (change feed with retention from remote+local storage). - public const string EnableFullFidelityChangeFeed = "enableFullFidelityChangeFeed"; - public const string EnableFFCFWithPITR = "enableFFCFWithPITR"; - - // Enable API type check - public const string EnableApiTypeCheck = "enableApiTypeCheck"; - public const string EnabledApiTypesOverride = "enabledApiTypesOverride"; - - public const string ForceDisableFailover = "forceDisableFailover"; - public const string EnableAutomaticFailover = "enableAutomaticFailover"; - public const string SkipGracefulFailoverAttempt = "skipGracefulFailoverAttempt"; - public const string ForceUngracefulFailover = "forceUngraceful"; - - // Location resource - public const string IsEnabled = "isenabled"; - public const string FabricUri = "fabricUri"; - public const string ResourcePartitionKey = "resourcePartitionKey"; - public const string CanaryLocationSurffix = "euap"; - public const string IsSubscriptionRegionAccessAllowedForRegular = "isSubscriptionRegionAccessAllowedForRegular"; - public const string IsSubscriptionRegionAccessAllowedForAz = "isSubscriptionRegionAccessAllowedForAz"; - - // Topology Resource - public const string Topology = "topology"; - public const string AdjacencyList = "adjacencyList"; - public const string WriteRegion = "writeRegion"; - public const string GlobalConfigurationNumber = "globalConfigurationNumber"; - public const string WriteStatusRevokedSatelliteRegions = "writeStatusRevokedSatelliteRegions"; - public const string PreviousWriteRegion = "previousWriteRegion"; - public const string NextWriteRegion = "nextWriteRegion"; - public const string ReadStatusRevoked = "readStatusRevoked"; - - // Capabilities Resource - public const string Capabilities = "capabilities"; - public const string DefaultCapabilities = "defaultCapabilities"; - public const string CapabilityVisibilityPolicies = "capabilityVisibilityPolicies"; - public const string NamingServiceSettings = "namingServiceSettings"; - public const string IsEnabledForAll = "isEnabledForAll"; - public const string IsDefault = "isDefault"; - public const string Key = "key"; - public const string IsCapabilityRingFenced = "isCapabilityRingFenced"; - public const string IsEnabledForAllToOptIn = "isEnabledForAllToOptIn"; - public const string TargetedFederationTypes = "targetedFederationTypes"; - - // PolicyStore - public const string ConfigValueByKey = "configValueByKey"; - public const string NameBasedCollectionUri = "nameBasedCollectionUri"; - public const string UsePolicyStore = "usePolicyStore"; - public const string UsePolicyStoreRuntime = "usePolicyStoreRuntime"; - public const string PolicyStoreVersion = "policyStoreVersion"; - - // System store properties - public const string AccountEndpoint = "AccountEndpoint"; - public const string EncryptedAccountKey = "EncryptedAccountKey"; - - // PolicyStoreConnectionInfo - public const string PolicyStoreConnectionInfoNameBasedCollectionUri = "NameBasedCollectionUri"; - - // BillingStoreConnectionInfo - public const string BillingStoreConnectionInfoAccountEndpoint = "AccountEndpoint"; - public const string BillingStoreConnectionInfoEncryptedAccountKey = "EncryptedAccountKey"; - public const string EnableBackupPolicyBilling = "EnableBackupPolicyBilling"; - public const string EnableBackupRedundancyBilling = "EnableBackupRedundancyBilling"; - - // ConfigurationStoreConnectionInfo - public const string ConfigurationStoreConnectionInfoAccountEndpoint = "AccountEndpoint"; - public const string ConfigurationStoreConnectionInfoEncryptedAccountKey = "EncryptedAccountKey"; - public const string ConfigurationStoreConnectionInfoFederationCollectionUri = "FederationCollectionUri"; - public const string ConfigurationStoreConnectionInfoDatabaseAccountCollectionUri = "DatabaseAccountCollectionUri"; - public const string ConfigurationStoreConnectionInfoRegionalCollectionUri = "RegionalCollectionUri"; - - // ConfigurationLevel - public const string ConfigurationLevel = "configurationLevel"; - - // SkipFederationEntityUpdate - public const string SkipFederationEntityUpdate = "skipFederationEntityUpdate"; - - // TargetOnlyNamingService - public const string TargetOnlyNamingService = "targetOnlyNamingService"; - - // Subscription Properties - public const string SubscriptionTenantId = "tenantId"; - public const string SubscriptionLocationPlacementId = "locationPlacementId"; - public const string SubscriptionQuotaId = "quotaId"; - public const string SubscriptionAddionalProperties = "additionalProperties"; - - // Schema resource - public const string Schema = "schema"; - - // PartitionedQueryExecutionInfo - public const string PartitionedQueryExecutionInfoVersion = "partitionedQueryExecutionInfoVersion"; - public const string QueryInfo = "queryInfo"; - public const string QueryRanges = "queryRanges"; - - // Arm resource type - public const string CosmosResourceProvider = "microsoft.documentdb"; - public const string DatabaseAccounts = "databaseaccounts"; - public const string CosmosArmResouceType = CosmosResourceProvider + "/" + DatabaseAccounts; - - // SchemaDiscoveryPolicy - public const string SchemaDiscoveryPolicy = "schemaDiscoveryPolicy"; - public const string SchemaBuilderMode = "mode"; - - // Global database account resource configuration overrides - public const string EnableBsonSchema = "enableBsonSchema"; - public const string EnableAdditiveSchemaForAnalytics = "enableAdditiveSchemaForAnalytics"; - - // Billing - public const string EnableV2Billing = "enableV2Billing"; - public const string CustomProperties = "CustomProperties"; - public const string StreamName = "StreamName"; - public const string ResourceLocation = "ResourceLocation"; - public const string EventTime = "EventTime"; - public const string ResourceTags = "ResourceTags"; - - // PartitionStatistics - public const string Statistics = "statistics"; - public const string SizeInKB = "sizeInKB"; - public const string CompressedSizeInKB = "compressedSizeInKB"; - public const string DocumentCount = "documentCount"; - public const string SampledDistinctPartitionKeyCount = "sampledDistinctPartitionKeyCount"; - public const string PartitionKeys = "partitionKeys"; - - // Partition quota - public const string AccountStorageQuotaInGB = "databaseAccountStorageQuotaInGB"; - - // PartitionKeyStatistic - public const string Percentage = "percentage"; - public const string EnablePartitionKeyStatsOptimization = "enablePartitionKeyStatsOptimization"; - - public const string PartitionKeyDefinitionVersion = "version"; - - // Federation pinning - public const string EnforcePlacementHintConstraintOnPartitionAllocation = "enforcePlacementHintConstraintOnPartitionAllocation"; - public const string CanUsePolicyStore = "canUsePolicyStore"; - - // SubscriptionsQuota resource - public const string MaxDatabaseAccountCount = "maxDatabaseAccountCount"; - public const string MaxRegionsPerGlobalDatabaseAccount = "maxRegionsPerGlobalDatabaseAccount"; - public const string DisableManualFailoverThrottling = "disableManualFailoverThrottling"; - public const string DisableRemoveRegionThrottling = "disableRemoveRegionThrottling"; - public const string AnalyticsStorageAccountCount = "analyticsStorageAccountCount"; - public const string LibrariesFileShareQuotaInGB = "librariesFileShareQuotaInGB"; - - // Policy Overrides - public const string DefaultSubscriptionPolicySet = "defaultSubscriptionPolicySet"; - public const string SubscriptionPolicySetByLocation = "subscriptionPolicySetByLocation"; - public const string PlacementPolicy = "placementPolicy"; - public const string SubscriptionPolicy = "subscriptionPolicy"; - public const string LocationPolicySettings = "locationPolicySettings"; - public const string DefaultLocationPolicySet = "defaultLocationPolicySet"; - public const string LocationPolicySetBySubscriptionKind = "locationPolicySetBySubscriptionKind"; - public const string SubscriptionPolicySettings = "subscriptionPolicySettings"; - public const string CapabilityPolicySettings = "capabilityPolicySettings"; - - // Location Policy - public const string LocationVisibilityPolicy = "locationVisibilityPolicy"; - public const string IsVisible = "isVisible"; - - // Virtual Network Filter/Acls - // Customer Facing - public const string IsVirtualNetworkFilterEnabled = "isVirtualNetworkFilterEnabled"; - - // PerPartitionFailover Flags - // Likely Customer Facing - public const string EnablePerPartitionFailoverBehavior = "enablePerPartitionFailoverBehavior"; - - // Backend - public const string AccountVNETFilterEnabled = "accountVNETFilterEnabled"; - public const string VirtualNetworkArmUrl = "virtualNetworkArmUrl"; - public const string VirtualNetworkResourceEntries = "virtualNetworkResourceEntries"; - public const string VirtualNetworkResourceId = "virtualNetworkResourceId"; - public const string VirtualNetworkResourceIds = "virtualNetworkResourceIds"; - public const string VNetDatabaseAccountEntries = "vNetDatabaseAccountEntry"; - public const string VirtualNetworkTrafficTags = "vnetFilter"; - public const string VNetETag = "etag"; - public const string PrivateEndpointProxyETag = "etag"; - public const string VirtualNetworkRules = "virtualNetworkRules"; - public const string EnabledApiTypes = "EnabledApiTypes"; - public const string VirtualNetworkPrivateIpConfig = "vnetPrivateIps"; - public const string NspProfileProxyResources = "nspProfileProxyResources"; - public const string NspAssociationProxyResource = "nspAssociationProxyResource"; - public const string EnableNetworkSecurityPerimeter = "enableNetworkSecurityPerimeter"; - public const string EnableConflictResolutionPolicyUpdate = "enableConflictResolutionPolicyUpdate"; - - // VNET/Subnet Resource(Network Resource Provider) - public const string IgnoreMissingVNetServiceEndpoint = "ignoreMissingVNetServiceEndpoint"; - public const string SubnetTrafficTag = "subnetTrafficTag"; - public const string Owner = "owner"; - public const string VNetServiceAssociationLinks = "vNetServiceAssociationLinks"; - public const string VNetTrafficTag = "vNetTrafficTag"; - public const string VirtualNetworkAcled = "virtualNetworkAcled"; - public const string VirtualNetworkResourceGuid = "virtualNetworkResourceGuid"; - public const string VirtualNetworkLocation = "virtualNetworkLocation"; - public const string PrimaryLocations = "primaryLocations"; - public const string AcledSubscriptions = "acledSubscriptions"; - public const string AcledSubnets = "acledSubnets"; - public const string RetryAfter = "retryAfter"; - public const string OperationPollingUri = "operationPollingUri"; - public const string OperationPollingKind = "operationPollingKind"; - public const string PublicNetworkAccess = "publicNetworkAccess"; - public const string UseSubnetDatabaseAccountEntries = "useSubnetDatabaseAccountEntries"; - public const string UseRegionalVNet = "userRegionalVNet"; - - // Auto Migration - public const string EnableFederationDecommission = "enableFederationDecommission2"; - public const string AutoMigrationScheduleIntervalInSeconds = "autoMigrationScheduleIntervalInSeconds2"; - public const string MasterPartitionAutoMigrationProbability = "masterPartitionAutoMigrationProbability2"; - public const string ServerPartitionAutoMigrationProbability = "serverPartitionAutoMigrationProbability2"; - - // Diagnostic Settings - public const string StorageAccountId = "storageAccountId"; - public const string WorkspaceId = "workspaceId"; - public const string EventHubAuthorizationRuleId = "eventHubAuthorizationRuleId"; - public const string Enabled = "enabled"; - public const string Days = "days"; - public const string RetentionPolicy = "retentionPolicy"; - public const string Metrics = "metrics"; - public const string Logs = "logs"; - public const string CategoryGroup = "categoryGroup"; - - // Atp(advanced threat protection) Settings - public const string IsAtpEnabled = "isEnabled"; - - // FullTextQuerySettings for plain text logging - public const string IsFullTextQueryEnabled = "isEnabled"; - - // ResourceLimits - public const string EnableExtendedResourceLimit = "enableExtendedResourceLimit"; - public const string ExtendedResourceNameLimitInBytes = "extendedResourceNameLimitInBytes"; - public const string ExtendedResourceContentLimitInKB = "extendedResourceContentLimitInKB"; - public const string MaxResourceSize = "maxResourceSize"; - public const string MaxBatchRequestBodySize = "maxBatchRequestBodySize"; - public const string MaxResponseMessageSize = "maxResponseMessageSize"; - public const string AnalyzedTermChargeEnabled = "analyzedTermChargeEnabled "; - public const string EnableWriteConflictCharge = "enableWriteConflictCharge"; - public const string ResourceContentBufferThreshold = "resourceContentBufferThreshold"; - public const string EnableExtendedResourceLimitForNewCollections = "enableExtendedResourceLimitForNewCollections"; - public const string DefaultExtendedCollectionChildResourceContentLimitInKB = "defaultExtendedCollectionChildResourceContentLimitInKB"; - public const string MaxScriptInputSize = "maxScriptInputSize"; - public const string MaxBatchTransactionSizeInBytes = "maxBatchTransactionSizeInBytes"; - public const string MaxScriptTransactionSize = "maxScriptTransactionSize"; - public const string ReplicationBatchMaxMessageSizeInBytes = "replicationBatchMaxMessageSizeInBytes"; - public const string TriggeredMasterBackupDuringAccountDelete = "triggeredMasterBackupDuringAccountDelete"; - public const string MaxReadFeedResponseMessageSize = "maxReadFeedResponseMessageSize"; - public const string EnableLargeDocumentSupport = "enableLargeDocumentSupport"; - - // Resource Governance Settings - public const string MaxFeasibleRequestChargeInSeconds = "MaxFeasibleRequestChargeInSeconds"; - public const string ReplicationChargeEnabled = "replicationChargeEnabled"; - - // Multi-Region Strong - public const string BypassMultiRegionStrongVersionCheck = "bypassMultiRegionStrongVersionCheck"; - public const string XPCatchupConfigurationEnabled = "xpCatchupConfigurationEnabled"; - - // LogStore restore - public const string IsRemoteStoreRestoreEnabled = "remoteStoreRestoreEnabled"; - public const string RetentionPeriodInSeconds = "retentionPeriodInSeconds"; - public const string EnableRestoreTillEndOfLogChain = "enableRestoreTillEndOfLogChain"; - - // Remove stale backup blobs - public const string BlobNamePrefix = "blobNamePrefix"; - public const string BlobPartitionLevel = "blobPartitionLevel"; - public const string DryRun = "dryRun"; - public const string UseCustomRetentionPeriod = "UseCustomRetentionPeriod"; - public const string CustomRetentionPeriodInMins = "CustomRetentionPeriodInMins"; - - // Shared throughput offer specific - public const string DisallowOfferOnSharedThroughputCollection = "disallowOfferOnSharedThroughputCollection"; - public const string AllowOnlyPartitionedCollectionsForSharedOffer = "allowOnlyPartitionedCollectionsForSharedThroughputOffer"; - public const string RestrictDatabaseOfferContainerCount = "restrictDatabaseOfferContainerCount"; - public const string MaxSharedOfferDatabaseCount = "maxSharedOfferDatabaseCount"; - public const string MinRUsPerSharedThroughputCollection = "minRUsPerSharedThroughputCollection"; - public const string MaxContainersPerPartition = "maxContainersPerPartition"; - - // Conflict resolution policy - public const string ConflictResolutionPolicy = "conflictResolutionPolicy"; - public const string Mode = "mode"; - public const string ConflictResolutionPath = "conflictResolutionPath"; - public const string ConflictResolutionProcedure = "conflictResolutionProcedure"; - - public const string Progress = "progress"; - public const string ReservedServicesInfo = "reservedServicesInfo"; - - // Update Federation Is Dirty Status Request - public const string RoleInstanceCounts = "RoleInstanceCounts"; - public const string RoleName = "RoleName"; - public const string InstanceCount = "InstanceCount"; - - // Federation Service Extension - public const string ExtensionName = "ExtensionName"; - public const string ExtensionVersion = "ExtensionVersion"; - - // CORS Rules - public const string Cors = "cors"; - public const string AllowedOrigins = "allowedOrigins"; - public const string AllowedMethods = "allowedMethods"; - public const string AllowedHeaders = "allowedHeaders"; - public const string ExposedHeaders = "exposedHeaders"; - public const string MaxAgeInSeconds = "maxAgeInSeconds"; - - // Certificates for SSL authentication - public const string PrimaryClientCertificatePemBytes = "primaryClientCertificatePemBytes"; - public const string SecondaryClientCertificatePemBytes = "secondaryClientCertificatePemBytes"; - - // Adds lsn property to document content - public const string EnableLsnInDocumentContent = "enableLsnInDocumentContent"; - - // Max content per collection In GB - public const string MaxContentPerCollectionInGB = "maxContentPerCollection"; - - // Visibility resource - public const string SkipRepublishConfigFromTargetFederation = "skipRepublishConfigFromTargetFederation"; - public const string MaxDegreeOfParallelismForPublishingFederationKeys = "maxDegreeOfParallelismForPublishingFederationKeys"; - - // Remove federation visibility resource - public const string ValidationOnly = "validationOnly"; - public const string EnforceOrphanServiceCheck = "enforceOrphanServiceCheck"; - public const string ResetPoolCounters = "resetPoolCounters"; - - public const string ProxyName = "proxyName"; - public const string GroupId = "groupId"; - public const string ConnectionDetails = "connectionDetails"; - public const string GroupIds = "groupIds"; - public const string InternalFqdn = "internalFqdn"; - public const string CustomerVisibleFqdns = "customerVisibleFqdns"; - public const string RequiredMembers = "requiredMembers"; - public const string RequiredZoneNames = "requiredZoneNames"; - public const string ManualPrivateLinkServiceConnections = "manualPrivateLinkServiceConnections"; - public const string PrivateLinkServiceConnections = "privateLinkServiceConnections"; - public const string PrivateLinkServiceProxies = "privateLinkServiceProxies"; - public const string RemotePrivateEndpoint = "remotePrivateEndpoint"; - public const string MemberName = "memberName"; - public const string BatchNotifications = "batchNotifications"; - public const string AccountSourceResourceId = "sourceResourceId"; - public const string TargetResourceGroupId = "targetResourceGroupId"; - public const string GroupConnectivityInformation = "groupConnectivityInformation"; - public const string RemotePrivateLinkServiceConnectionState = "remotePrivateLinkServiceConnectionState"; - public const string RemotePrivateEndpointConnection = "remotePrivateEndpointConnection"; - public const string PrivateEndpointConnectionId = "privateEndpointConnectionId"; - public const string ActionsRequired = "actionsRequired"; - public const string RequestMessage = "requestMessage"; - public const string LinkIdentifier = "linkIdentifier"; - public const string PrivateLinkServiceArmRegion = "privateLinkServiceArmRegion"; - public const string PrivateIpAddress = "privateIpAddress"; - public const string PrivateIpConfigGroups = "privateIpConfigGroups"; - public const string IsLastNrpPutRequestManualApprovalWorkflow = "isLastNrpPutRequestManualApprovalWorkflow"; - public const string PrivateLinkServiceConnectionName = "privateLinkServiceConnectionName"; - public const string RedirectMapId = "redirectMapId"; - public const string ImmutableSubscriptionId = "immutableSubscriptionId"; - public const string ImmutableResourceId = "immutableResourceId"; - public const string AccountPrivateEndpointConnectionEnabled = "accountPrivateEndpointConnectionEnabled"; - public const string AccountPrivateEndpointDnsZoneEnabled = "accountPrivateEndpointDnsZoneEnabled"; - public const string PrivateIpConfigs = "privateIpConfigs"; - public const string PrivateEndpoint = "privateEndpoint"; - public const string PrivateLinkServiceConnectionState = "privateLinkServiceConnectionState"; - public const string PrivateEndpointArmUrl = "privateEndpointArmUrl"; - public const string StoragePrivateEndpointConnections = "storagePrivateEndpointConnections"; - public const string PrivateLinkServiceProxyName = "privateLinkServiceProxyName"; - public const string PrivateEndpointConnections = "privateEndpointConnections"; - public const string UpdateIpRangeFilter = "updateIpRangeFilter"; - public const string UpdateVirtualNetworkResources = "updateVirtualNetworkResources"; - public const string UpdatePrivateEndpointConnections = "updatePrivateEndpointConnections"; - public const string ExplicitDnsSettings = "explicitDnsSettings"; - public const string ARecord = "aRecord"; - public const string DnsZoneName = "dnsZoneName"; - public const string ArmSubscriptionId = "armSubscriptionId"; - public const string ChildrenNames = "childrenNames"; - public const string ParentName = "parentName"; - public const string IsActive = "isActive"; - public const string IsRegional = "isRegional"; - public const string MapEntrySize = "mapEntrySize"; - public const string FederationMaps = "federationMaps"; - public const string FederationDns = "federationDns"; - public const string FederationVip = "federationVip"; - public const string Entries = "entries"; - public const string AllowEntryDelete = "allowEntryDelete"; - public const string DeletedFederations = "deletedFederations"; - public const string StartPublicPort = "startPublicPort"; - public const string StartPrivatePort = "startPrivatePort"; - public const string ServiceName = "serviceName"; - public const string PlatformId = "platformId"; - public const string VirtualPortBlockSize = "virtualPortBlockSize"; - public const string LookUpEntries = "lookupEntries"; - public const string RingPublicVipAddress = "ringPublicVipAddress"; - public const string StartInstancePort = "startInstancePort"; - public const string EndInstancePort = "endInstancePort"; - public const string StartVirtualPort = "startVirtualPort"; - public const string EndVirtualPort = "endVirtualPort"; - public const string PublishToNrp = "publishToNrp"; - public const string VnetMapPropagationWaitDurationInMinutes = "vnetMapPropagationWaitDurationInMinutes"; - public const string Map = "map"; - public const string IsSqlEndpointSwapped = "isSqlEndpointSwapped"; - public const string IsSqlEndpointDefaultProvisionedOnCompute = "isSqlEndpointDefaultProvisionedOnCompute"; - public const string ComputeFederationProcess = "computeFederationProcess"; - public const string DatabaseServicesInfo = "DatabaseServicesInfo"; - public const string RedirectMapVersion = "version"; - public const string IsOwnedByExternalProvider = "isOwnedByExternalProvider"; - public const string ConnectionInformation = "connectionInformation"; - public const string CrossSubRegionMigrationInProgress = "CrossSubRegionMigrationInProgress"; - public const string AzMigrationInProgress = "AzMigrationInProgress"; - - // Data Plane Operation Policy - public const string DisableKeyBasedMetadataWriteAccess = "disableKeyBasedMetadataWriteAccess"; - public const string DisableKeyBasedMetadataReadAccess = "disableKeyBasedMetadataReadAccess"; - - //ControlPlane Metric and Diagnostic logs - public const int DiagnosticLogPropertyLengthLimit = 2000; - public const string EventStartSuffix = "Start"; - public const string EventCompleteSuffix = "Complete"; - public const string AddRegionEventGroupName = "RegionAdd"; - public const string RemoveRegionEventGroupName = "RegionRemove"; - public const string DeleteAccountEventGroupName = "AccountDelete"; - public const string RegionFailoverEventGroupName = "RegionFailover"; - public const string CreateAccountEventGroupName = "AccountCreate"; - public const string UpdateAccountEventGroupName = "AccountUpdate"; - public const string UpdateAccountBackUpPolicyEventGroupName = "AccountBackUpPolicyUpdate"; - public const string DeleteVNETEventGroupName = "VirtualNetworkDelete"; - public const string UpdateDiagnosticLogEventGroupName = "DiagnosticLogUpdate"; - public const string SqlRoleDefinitionCreate = "SqlRoleDefinitionCreate"; - public const string SqlRoleDefinitionReplace = "SqlRoleDefinitionReplace"; - public const string SqlRoleDefinitionDelete = "SqlRoleDefinitionDelete"; - public const string SqlRoleAssignmentCreate = "SqlRoleAssignmentCreate"; - public const string SqlRoleAssignmentReplace = "SqlRoleAssignmentReplace"; - public const string SqlRoleAssignmentDelete = "SqlRoleAssignmentDelete"; - - public const string MongoRoleDefinitionCreate = "MongoRoleDefinitionCreate"; - public const string Replace = "AuthPolicyElementReplace"; - public const string MongoRoleDefinitionDelete = "MongoRoleDefinitionDelete"; - - public const string CassandraRoleDefinitionCreate = "CassandraRoleDefinitionCreate"; - public const string CassandraRoleDefinitionReplace = "CassandraRoleDefinitionReplace"; - public const string CassandraRoleDefinitionDelete = "CassandraRoleDefinitionDelete"; - - // Diagnostics settings - public const string EnableControlPlaneRequestsTrace = "enableControlPlaneRequestsTrace"; - public const string AtpEnableControlPlaneRequestsTrace = "atpEnableControlPlaneRequestsTrace"; - - public const string OwnerResourceId = "ownerResourceId"; - - public const string ParentResourceId = "parentResourceId"; - - //Notebook settings - public const string NotebookStorageAllocationInfo = "notebookStorageAllocationInfo"; - - // Spark settings - public const string SparkStorageAllocationInfo = "sparkStorageAllocationInfo"; - - // Throughput split settings - public const string ThroughputSplitInfo = "ThroughputSplitInfo"; - - //CosmosStoreBlobProperties - public const string CacheControl = "cacheControl"; - public const string ContentDisposition = "contentDisposition"; - public const string ContentEncoding = "contentEncoding"; - public const string ContentLanguage = "contentLanguage"; - public const string ContentMD5 = "contentMD5"; - public const string Length = "length"; - - //CosmosBlob - public const string Metadata = "metadata"; - public const string BlobProperties = "blobProperties"; - - // ARM Certificates - public const string ClientCertificates = "clientCertificates"; - public const string Thumbprint = "thumbprint"; - public const string NotBefore = "notBefore"; - public const string NotAfter = "notAfter"; - public const string Certificate = "certificate"; - - public const string IsDiskReceiverEnabled = "isDiskReceiverEnabled"; - - // Service Association Link - public const string LinkedResourceType = "linkedResourceType"; - public const string Link = "link"; - public const string AllowDelete = "allowDelete"; - public const string Details = "Details"; - public const string ServiceAssociationLinkETag = "etag"; - public const string PrimaryContextId = "primaryContextId"; - public const string SecondaryContextId = "secondaryContextId"; - public const string PrimaryContextRequestId = "primaryContextRequestId"; - public const string SecondaryContextRequestId = "secondaryContextRequestId"; - - // GremlinV2 Properties. - public const string GremlinProperties = "gremlinProperties"; - public const string GraphApiServerStartupConfigFileName = "graphapi.startupConfig"; - - // Mongo Properties - public const string GlobalMongoProperties = "globalMongoProperties"; - public const string ApiProperties = "apiProperties"; - public const string Disable16MBCapabilityChecks = "disable16MBCapabilityChecks"; - - // AAD Authentication - public const string TrustedAadTenants = "trustedAadTenants"; - public const string NetworkAclBypass = "networkAclBypass"; - public const string NetworkAclBypassResourceIds = "networkAclBypassResourceIds"; - public const string DisableLocalAuth = "disableLocalAuth"; - - //Logging properties - public const string DiagnosticLogSettings = "diagnosticLogSettings"; - public const string EnableFullTextQuery = "enableFullTextQuery"; - - // Restorable database accounts - public const string CreationTime = "creationTime"; - public const string DeletionTime = "deletionTime"; - public const string OldestRestorableTime = "oldestRestorableTime"; - public const string AccountName = "accountName"; - public const string ApiType = "apiType"; - public const string RestorableLocations = "restorableLocations"; - - public const string CreationTimeInUtc = "creationTimeInUtc"; - public const string DeletionTimeInUtc = "deletionTimeInUtc"; - public const string OldestRestorableTimeInUtc = "oldestRestorableTimeInUtc"; - - // Private endpoint map management - public const string Telemetry = "telemetry"; - public const string DisabledTime = "disabledTime"; - public const string MapVersionBeforeCreation = "mapVersionBeforeCreation"; - public const string MapVersionBeforeDisabled = "mapVersionBeforeDisabled"; - public const string MapVersionBeforeDeletion = "mapVersionBeforeDeletion"; - - // SystemData - public const string SystemData = "systemData"; - - // DeletedGlobalDatabaseAccount resource - public const string DeletedRegionalDatabaseAccounts = "regionalDeletedDatabaseAccounts"; - // Compute MongoClient for RP - public const string DisableMongoClientWorkflows = "disableMongoClientWorkflows"; - - // Enable customer managed key - public const string ByokStatus = "byokStatus"; - public const string ByokConfig = "byokConfig"; - public const string EnableBYOKOnExistingCollections = "enableBYOKOnExistingCollections"; - public const string DisableByokReEncryptor = "disableByokReEncryptor"; - public const string DataEncryptionState = "dataEncryptionState"; - public const string HoboVersion = "hoboVersion"; - - // LocationResource - public const string DeploymentBatch = "deploymentBatch"; - public const string HealthServiceSubscriptionId = "healthServiceSubscriptionId"; - public const string FederationActiveDirectoryTenantId = "federationActiveDirectoryTenantId"; - public const string FederationActiveDirectoryClientId = "federationActiveDirectoryClientId"; - public const string Longitude = "longitude"; - public const string Latitude = "latitude"; - public const string ShortId = "shortId"; - public const string PublicName = "publicName"; - public const string LongName = "longName"; - public const string ServicingLocationPublicName = "servicingLocationPublicName"; - public const string HealthServiceName = "healthServiceName"; - public const string SupportsAvailabilityZone = "supportsAvailabilityZone"; - public const string AvailabilityZonesReady = "availabilityZonesReady"; - public const string ActiveSubRegionId = "activeSubRegionId"; - public const string ActiveAvailabilityZoneSubRegionId = "activeAvailabilityZoneSubRegionId"; - public const string IsResidencyRestricted = "isResidencyRestricted"; - public const string RegionalRPLocationForBuildoutStoreFailover = "regionalRPLocationForBuildoutStoreFailover"; - public const string ManagementStoreName = "managementStoreName"; - public const string MgmtStoreSubscriptionId = "mgmtStoreSubscriptionId"; - public const string MgmtStoreResourceGroup = "mgmtStoreResourceGroup"; - public const string DisallowedSubscriptionOfferKinds = "disallowedSubscriptionOfferKinds"; - - // This is read by Compute. - public const string EnablePartitionLevelFailover = "enablePartitionLevelFailover"; - // This is read by Backend. - public const string EnablePerPartitionAutomaticFailover = "enablePerPartitionAutomaticFailover"; - public const string EnableFailoverManager = "enableFailoverManager"; - - // Capacity settings properties - public const string Capacity = "capacity"; - public const string TotalThroughputLimit = "totalThroughputLimit"; - public const string TotalThroughputLimitBackendName = "currentThroughputCap"; - - // Mongo Partial Unique Indexes properties - public const string EnableConditionalUniqueIndex = "enableConditionalUniqueIndex"; - public const string EnableUniqueIndexReIndexing = "enableUniqueIndexReIndexing"; - public const string GenerateUniqueIndexTermsIfUniqueKeyPolicyDiffer = "generateUniqueIndexTermsIfUniqueKeyPolicyDiffer"; - public const string EnableUseLatestCollectionContent = "enableUseLatestCollectionContent"; - public const string AllowUniqueIndexModificationOnMaster = "allowUniqueIndexModificationOnMaster"; - public const string AllowUniqueIndexModificationWhenDataExists = "allowUniqueIndexModificationWhenDataExists"; - - // UpgradeControlRule - public const string RuleId = "ruleId"; - public const string RuleType = "ruleType"; - public const string RuleScope = "ruleScope"; - public const string ActivePeriod = "activePeriod"; - public const string Justification = "justification"; - public const string AdditionalProperties = "additionalProperties"; - - // Purview-related properties - public const string PurviewEnabled = "purviewEnabled"; - public const string AutoAuthPolicyFullPullScheduleIntervalInSeconds = "autoAuthPolicyFullPullScheduleIntervalInSeconds"; - public const int DefaultFullPullScheduleIntervalInSeconds = 7200; - - // TLS - // New values for Self-Service Tls feature. - public const string MinimalTlsVersion = "minimumAllowedTLSProtocol"; - public const string MinimalTlsVersionDisplay = "minimalTlsVersion"; - // Old deprecated value. - public const string MinimumTransportLayerSecurityLevel = "minimumTransportLayerSecurityLevel"; - - // LogStore Storage Account Rollover Timestamp - public const string EarliestNextLogStoreStorageAccountKeyRolloverTime = "earliestNextLogStoreStorageAccountKeyRolloverTime"; - - // RowRewriter properties - public const string RowRewriterIdleIntervalInSeconds = "rowRewriterIdleIntervalInSeconds"; - public const string DisableRowRewriter = "disableRowRewriter"; - - // Client Configuration Properties - public const string ClientTelemetryConfiguration = "clientTelemetryConfiguration"; - public const string ClientTelemetryEnabled = "isEnabled"; - public const string ClientTelemetryEndpoint = "endpoint"; - public const string ClientConfigApiRefreshIntervalInMinutes = "refreshIntervalInMinutes"; - public const string EnableClientTelemetry = "enableClientTelemetry"; - - // Throughput Pool Properties - public const string ThroughputPoolInstanceId = "throughputPoolInstanceId"; - public const string ThroughputPoolId = "throughputPoolId"; - public const string ThroughputPoolName = "throughputPoolName"; - public const string ThroughputPool = "throughputPool"; - public const string ThroughputPools = "throughputPools"; - public const string ThroughputPoolAccountLocation = "accountARMLocation"; - public const string ThroughputPoolAccountInstanceId = "accountInstanceId"; - public const string ThroughputPoolResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DocumentDB/throughputPools/{3}"; - public const string ThroughputPoolAccountUrl = "accountURI"; - - public static class FederationOperations - { - public const string IsCapOperation = "isCapOperation"; - } - } - - public static class FederationCapActions - { - public const string Cap = "Cap"; - public const string Uncap = "Uncap"; - } - - public static class InAccountUnDeleteNotAllowedReasons - { - // Database UnDelete Failure - public const string DatabaseLive = "Database already exists. Only deleted resources can be restored within same account."; - public const string DatabaseWithSameNameLive = "Database with same name already exist as live database."; - - // Collection UnDelete Failure - public const string DatabaseDoesNotExist = "Could not find the database associated with the collection. Please restore the database before restoring the collection."; - public const string DatabaseWithSameNameExist = "Could not find the database associated with the collection. Another database with same name exist"; - public const string CollectionLive = "Collection already exists. Only deleted resources can be restored within same account."; - public const string CollectionWithSamenNameLive = "Collection with same name already exist as live collection."; - public const string SharedCollectionNotAllowed = "Individual shared database collections restore is not supported. Please restore shared database to restore its collections that share the throughput."; - } - - public static class DocumentResourceExtendedProperties - { - public const string Tags = "Tags"; - public const string ResourceGroupName = "ResourceGroupName"; - public const string SkipDNSUpdateOnFailureDuringFailover = "SkipDNSUpdateOnFailureDuringFailover"; - } - - public static class SnapshotProperties - { - public const string GeoLinkToPKRangeRid = "geoLinkIdToPKRangeRid"; - public const string PartitionKeyRangeResourceIds = "partitionKeyRangeResourceIds"; - public const string PartitionKeyRanges = "partitionKeyRanges"; - public const string ClientEncryptionKeyResources = "clientEncryptionKeyResources"; - public const string CollectionContent = "collectionContent"; - public const string DatabaseContent = "databaseContent"; - public const string SnapshotTimestamp = "snapshotTimestamp"; - public const string EventTimestamp = "eventTimestamp"; - public const string DataDirectories = "dataDirectories"; - public const string MetadataDirectory = "metadataDirectory"; - public const string OperationType = "operationType"; - public const string RestoredPartitionInfo = "restoredPartitionInfo"; - public const string CollectionToSnapshotMap = "collectionToSnapshotMap"; - public const string PartitionKeyRangeList = "partitionKeyRangeList"; - public const string DocumentCollection = "documentCollection"; - public const string Database = "database"; - public const string OfferContent = "offerContent"; - public const string Container = "container"; - public const string Table = "table"; - public const string Keyspace = "keyspace"; - public const string LSN = "lsn"; - public const string IsMasterResourcesDeletionPending = "isMasterResourcesDeletionPending"; - public const string StorageAccountUris = "storageAccountUris"; - } - - public static class RestoreMetadataResourceProperties - { - // RestoreMetadata resource - public const string RId = "_rid"; - public const string LSN = "lsn"; - public const string CollectionDeletionTimestamp = "_ts"; - public const string DatabaseName = "databaseName"; - public const string CollectionName = "collectionName"; - public const string CollectionResourceId = "collectionResourceId"; - public const string PartitionKeyRangeContent = "partitionKeyRangeContent"; - public const string CollectionContent = "collectionContent"; - public const string OfferContent = "offerContent"; - public const string CollectionSecurityIdentifier = "collectionSecurityIdentifier"; - public const string CollectionCreationTimestamp = "creationTimestamp"; - public const string RemoteStoreType = "remoteStorageType"; - } - - public static class CollectionRestoreParamsProperties - { - public const string Version = "Version"; - public const string SourcePartitionKeyRangeId = "SourcePartitionKeyRangeId"; - public const string SourcePartitionKeyRangeRid = "SourcePartitionKeyRangeRid"; - public const string SourceSecurityIdentifier = "SourceSecurityId"; - public const string RestorePointInTime = "RestorePointInTime"; - public const string PartitionCount = "PartitionCount"; - public const string RestoreState = "RestoreState"; - } - - public static class InternalIndexingProperties - { - public const string PropertyName = "internalIndexingProperties"; - public const string LogicalIndexVersion = "logicalIndexVersion"; - public const string IndexEncodingOptions = "indexEncodingOptions"; - public const string EnableIndexingFullFidelity = "enableIndexingFullFidelity"; - public const string IndexUniquifierId = "indexUniquifierId"; - public const string CellExpiryIndexingMethod = "cellExpiryIndexingMethod"; - public const string EnableIndexingEffectivePartitionKey = "enableIndexingEffectivePartitionKey"; - } - - public static class InternalStoreProperties - { - public const string PropertyName = "internalStoreProperties"; - public const string EnableBinaryEncodingOfContent = "enableBinaryEncodingOfContent"; - } - - public static class TypeSystemPolicy - { - public const string PropertyName = "typeSystemPolicy"; - public const string TypeSystem = "typeSystem"; - public const string CosmosCore = "CosmosCore"; - public const string Cql = "Cql"; - public const string Bson = "Bson"; - } - - public static class UpgradeTypes - { - public const string ClusterManifest = "Fabric"; - public const string Package = "Package"; - public const string Application = "App"; - public const string GrowShrink = "GrowShrink"; - } - - public static class TracesConstants - { - // Monitoring properties - public static readonly string TraceContainerName = "trace"; - } - - public static class EncryptionScopeProperties - { - public const string EncryptionScopeId = "encryptionScopeId"; - public const string EncryptionScope = "encryptionScope"; - public const string Name = "name"; - public const string ManagedServiceIdentityInfoV2 = "managedServiceIdentityInfoV2"; - public const string CMKMetadataList = "cmkMetadataList"; - public const string CollectionFanoutCompleted = "collectionFanoutCompleted"; - - public static class MsiProperties - { - public const string Type = "type"; - public const string MsiIdentityUrl = "msiIdentityUrl"; - public const string InternalId = "internalId"; - public const string ImplicitIdentity = "implicitIdentity"; - public const string ExplicitIdentities = "explicitIdentities"; - public const string DelegatedIdentities = "delegatedIdentities"; - - public static class DelegatedIdentityProperties - { - public const string SourceInternalId = "sourceInternalId"; - public const string SourceResourceId = "sourceResourceId"; - public const string SourceTenantId = "sourceTenantId"; - public const string DelegationId = "delegationId"; - public const string DelegationUrl = "delegationUrl"; - public const string UpdateAction = "updateAction"; - public const string WildcardAction = "wildcardAction"; - } - - public static class IdentityProperties - { - public const string ClientId = "clientId"; - public const string ClientSecretEncrypted = "clientSecretEncrypted"; - public const string ClientSecretUrl = "clientSecretUrl"; - public const string TenantId = "tenantId"; - public const string ObjectId = "objectId"; - public const string ResourceId = "resourceId"; - public const string NotBefore = "notBefore"; - public const string NotAfter = "notAfter"; - public const string RenewAfter = "renewAfter"; - public const string CannotRenewAfter = "cannotRenewAfter"; - public const string UpdateAction = "updateAction"; - } - } - } - - public static class StorageKeyManagementProperties - { - public const string StorageAccountSubscriptionId = "storageAccountSubscriptionId"; - public const string StorageAccountResourceGroup = "storageAccountResourceGroup"; - public const string StorageAccountName = "storageAccountName"; - public const string StorageAccountUri = "storageAccountUri"; - public const string StorageAccountPrimaryKeyInUse = "storageAccountPrimaryKeyInUse"; - public const string StorageAccountSecondaryKeyInUse = "storageAccountSecondaryKeyInUse"; - public const string StorageAccountPrimaryKey = "storageAccountPrimaryKey"; - public const string StorageAccountSecondaryKey = "storageAccountSecondaryKey"; - public const string StorageAccountType = "storageAccountType"; - public const string ForceRefresh = "forceRefresh"; - public const string Permissions = "permissions"; - public const string CurrentAccountSasToken = "currentAccountSasToken"; - public const string KeyToSign = "keyToSign"; - public const string AccountSasToken = "accountSasToken"; - public const string ExpiryTime = "expiryTime"; - public const string ListAccountSasRequestServices = "bqtf"; - public const string ListAccountSasRequestResourceTypes = "sco"; - public const string DefaultAccountSasPermissions = "rwdlacup"; - public const string DefaultReadAccountSasPermissions = "rl"; - public const string SasSeparator = "?"; - - // The Storage Management API uses these names for storage account system, primary and secondary keys/sas tokens. - public const string Key1Name = "key1"; - public const string Key2Name = "key2"; - public const string SystemKeyName = "system"; - - // Config hooks - public const string EnableStorageAccountKeyFetch = "enableStorageAccountKeyFetch"; - public const string CachedStorageAccountKeyRefreshIntervalInHours = "cachedStorageAccountKeyRefreshIntervalInHours"; - public const string StorageKeyManagementClientRequestTimeoutInSeconds = "storageKeyManagementClientRequestTimeoutInSeconds"; - public const string StorageKeyManagementAADAuthRetryIntervalInSeconds = "storageKeyManagementAADAuthRetryIntervalInSeconds"; - public const string StorageKeyManagementAADAuthRetryCount = "storageKeyManagementAADAuthRetryCount"; - public const string StorageAccountKeyCacheExpirationIntervalInHours = "storageAccountKeyCacheExpirationIntervalInHours"; - public const string StorageAccountKeyRequestTimeoutInSeconds = "storageAccountKeyRequestTimeoutInSeconds"; - public const string StorageServiceUrlSuffix = "storageServiceUrlSuffix"; - public const string AzureResourceManagerEndpoint = "azureResourceManagerEndpoint"; - public const string StorageSasManagementClientRequestTimeoutInSeconds = "storageSasManagementClientRequestTimeoutInSeconds"; - - public const string FederationAzureActiveDirectoryEndpoint = "FederationAzureActiveDirectoryEndpoint"; - public const string FederationAzureActiveDirectoryClientId = "FederationAzureActiveDirectoryClientId"; - public const string FederationAzureActiveDirectoryTenantId = "FederationAzureActiveDirectoryTenantId"; - public const string FederationToAadCertDsmsSourceLocation = "FederationToAadCertDsmsSourceLocation"; - public const string MasterFederationId = "masterFederationId"; - public const string RegionalDatabaseAccountName = "regionalDatabaseAccountName"; - - // Account sas related configuration properties - public const string SystemSasValidityInHours = "systemSasValidityInHours"; - public const string PrimaryOrSecondaryKeyBasedSasValidityInHours = "primaryOrSecondaryKeyBasedSasValidityInHours"; - public const string CacheSystemSasExpiryInHours = "cacheSystemSasExpiryInHours"; - public const string CachePrimaryOrSecondaryKeyBasedSasExpiryInHours = "cachePrimaryOrSecondaryKeyBasedSasExpiryInHours"; - public const string SasStartTimeSubtractionIntervalInMinutes = "sasStartTimeSubtractionIntervalInMinutes"; - public const string AlwaysReturnKey1BasedSas = "alwaysReturnKey1BasedSas"; - public const string CacheExpirySubtractionTimeInMinutes = "cacheExpirySubtractionTimeInMinutes"; - public const string EnableMasterSideAuthTokenCaching = "enableMasterSideAuthTokenCaching"; - public const string EnableSasRequestRoutingToMasterFederation = "enableSasRequestRoutingToMasterFederation"; - public const string EnableSasTokenLogging = "enableSasTokenLogging"; - } - - public static class VNetServiceAssociationLinkProperties - { - public const string SubnetArmUrl = "subnetArmUrl"; - public const string PrimaryContextRequestId = "primaryContextRequestId"; - public const string SecondaryContextRequestId = "secondaryContextRequestId"; - public const string PrimaryContextId = "primaryContextId"; - public const string SecondaryContextId = "secondaryContextId"; - } - - public static class SystemSubscriptionUsageType - { - public const string SMS = "sms"; - public const string CassandraConnectorStorage = "cassandraconnectorstorage"; - public const string NotebooksStorage = "notebooksstorage"; - public const string AnalyticsStorage = "analyticsstorage"; - public const string SparkStorage = "sparkstorage"; - } - - public static class SystemSubscriptionProperties - { - public const string SystemSubscriptionAction = "systemSubscriptionAction"; - public const string SubscriptionUsageKind = "subscriptionUsageKind"; - } - - public static class ConnectorOfferKind - { - public const string Cassandra = "cassandra"; - } - - public static class ConnectorMetadataAccountNamePrefix - { - public const string CassandraConnectorMetadataAccountNamePrefix = "ccxmeta"; - } - - public static class ConnectorOfferName - { - public const string Small = "small"; - } - - public static class AnalyticsStorageAccountProperties - { - public const string AddStorageServices = "AddStorageServices"; - public const string ResourceGroupName = "AnalyticsStorageAccountRG"; - - // BlobStorageAttributes for Storage Analytics - public const string IsDeletedProperty = "IsDeleted"; - public const string DeletedTimeStampProperty = "DeletedTimeStamp"; - - // Analytics Storage Properties (It is a contract with BE, need to be kept in sync with StreamManager2.h/.cpp) - public const string PartitionedParQuetSuffix = "Partitioned.Parquet"; - public const string CosmosSuffix = "Cosmos"; - public const string RootMetaDataSuffix = "RootMetadata"; - public const string PartitionedPreffix = "Partitioned"; - public const string ParquetFileExtension = "Parquet"; - public const string CompressionType = "snappy"; - public const string RootFileName = "Root"; - public const string MetadataExtension = "Metadata"; - public const string InvalidationFileExtension = "Invalidation"; - public const string InvalidationManifestFileExtension = "InvalidationManifest"; - public const string MergedInvalidationFileExtension = "MergedInvalidation"; - public const string SnapshotFileName = "Snapshot"; - - public const string MetadataBlobFileNameSuffix = "Root.Metadata"; - } - - public static class BackupConstants - { - public const int BackupDisabled = -1; - public const int DefaultBackupIntervalInMinutes = 240; - public const int DefaultBackupRetentionIntervalInHours = 8; - public const int LegacyDefaultBackupRetentionIntervalInHours = 24; - - public const int PitrDefaultBackupIntervalInHours = 168; // Weekly full backups - public const int PitrDefaultBackupRetentionIntervalInDays = 30; - public const int PitrBasicDefaultBackupRetentionIntervalInDays = 7; - - public const int DisableBackupHoldFeature = -1; - public const string BackupHoldIndefinite = "0"; - - public const string ServerBackupContainerIdentifier = "-s-"; - public const string MasterBackupContainerIdentifier = "-m-"; - public const string DummyBackupContainerIdentifier = "-d-"; // Used for NoEdb Restore - - public const int ShortenedPartitionIdLengthInContainerName = 19; - - public const int MinBackupIntervalInMinutes = 60; - public const int MaxBackupIntervalInMinutes = 1440; - - public const int MinBackupRetentionIntervalInHours = 8; - public const int MaxBackupRetentionIntervalInHours = 720; - - public const int InvalidPeriodicBackupInterval = -1; - public const int InvalidPeriodicBackupRetention = -1; - - public const string BackupEndTimestamp = "backupEndTimestamp"; - } - - public static class KeyVaultProperties - { - public const string KeyVaultKeyUri = "keyVaultKeyUri"; - public const string WrappedDek = "wrappedDek"; - public const string EnableByok = "enableByok"; - public const string KeyVaultKeyUriVersion = "keyVaultKeyUriVersion"; - public const string DataEncryptionKeyStatus = "dataEncryptionKeyStatus"; - public const string DataEncryptionKeyRequestOperation = "dataEncryptionKeyRequestOperation"; - public const string KeyVaultUnwrapErrorSubStatusCode = "keyVaultUnwrapErrorSubStatusCode"; - public const string KeyVaultUnwrapError = "keyVaultUnwrapError"; - public const string CustomerManagedKeyStatus = "customerManagedKeyStatus"; - } - - public static class ManagedServiceIdentityProperties - { - public const string MsiClientId = "msiClientId"; - public const string MsiClientSecretEncrypted = "msiClientSecretEncrypted"; - public const string MsiCertRenewAfter = "msiCertRenewAfter"; - public const string MsiTenantId = "msiTenantId"; - - public const string AssignUserAssignedIdentity = "assignUserAssignedIdentity"; - public const string UnassignUserAssignedIdentity = "unassignUserAssignedIdentity"; - - public const string AssignSourceDelegation = "assignSourceDelegation"; - public const string UnassignSourceDelegation = "unassignSourceDelegation"; - - public const string WildcardEnabled = "wildcardEnabled"; - public const string WildcardDisabled = "wildcardDisabled"; - - public const string FederatedClientId = "&FederatedClientId="; - public const string SourceInternalId = "&SourceInternalId="; - } - - public static class LogStoreConstants - { - public const int BasedOnSubscription = 0; - public const int EnsureOperationLogsFlushedTimeoutTimeInMinutes = 60; - public const int CrossRegionRestoreOperationLogsFlushTimeoutTimeInMinutes = 15; - - // StreamStandard => 0x0004 = 4 - public const int PreferredLogStoreMetadataStorageKind = 4; - - // Default timeout value of polling operation WaitForStorageKeyAccessOperation - public const double TimeoutDurationInMinutes = 60.0; - - // It needs to be in sync with bancked config for operation logs flush interval, which is currently 100s - public const int EnsureOperationLogsPauseTimeInSeconds = 200; - - //Blob metadata - public const string PartitionKeyRangeRid = "PartitionKeyRangeRid"; - public const string CollectionLLSN = "CollectionLLSN"; - public const string CollectionGLSN = "CollectionGLSN"; - public const string IsValidTimeStamp = "IsValidTimeStamp"; - public const string CollectionTS = "CollectionTS"; - public const string CollectionInstanceId = "CollectionInstanceId"; - } - - public static class RestoreConstants - { - public const int ListBlobMaxResults = 1000; - public const int ListBlobRetryDeltaBackoffInSeconds = 30; - public const int ListBlobRetryMaxAttempts = 5; - - public const int MaxRetryCount = 3; - public const int RetryDelayInSec = 20; - - public const int RestorableDatabaseAccountUriLength = 9; - public const int DatabaseRequestUriLength = 11; - public const int ContainerRequestUriLength = 13; - } - - public static class SubscriptionsQuotaConstants - { - // based on doc: https://docs.microsoft.com/en-us/azure/cosmos-db/concepts-limits#control-plane-operations - public const int DefaultMaxDatabaseAccountCount = 50; - public const int DefaultMaxRegionsPerGlobalDatabaseAccount = 50; - } - - public static class OperationProgressConstants - { - public const string IsProgressReportingSupported = "IsProgressReportingSupported"; - public const string ProgressPercentage = "ProgressPercentage"; - } - - public static class PolicyConstants - { - public const string PolicyType = "policytype"; - public const string BalancingThreshold = "balancingThreshold"; - public const string TriggerThreshold = "triggerThreshold"; - public const string MetricId = "metricId"; - public const string MetricValue = "metricValue"; - public const string MetricWeight = "metricWeight"; - public const string GlobalPolicyPartitionKey = "global"; - public const string Policies = "policies"; - public const string FederationListSortedByUsageScore = "federationListSortedByUsageScore"; - public const string ServiceAllocationOperationType = "serviceAllocationOperationType"; - public const string MaxAllowedPartitionCount = "maxAllowedPartitionCount"; - public const string DisAllowedSubscriptionOfferKinds = "disAllowedSubscriptionOfferKinds"; - public const string NumberOfFederationsToRandomize = "numberOfFederationsToRandomize"; - public const string RegionAccessTypes = "regionAccessTypes"; - public const string RegionAccessType = "regionAccessType"; - } - - public static class SystemStoreConstants - { - public const int DefaultBackupIntervalInMinute = 60; - public const int SMSDefaultBackupIntervalInMinute = 30; - public const int DefaultBackupRetentionInHour = 720; - public const string ResourceGroupSuffix = "-rg"; - public const string IsDataTransferStateStoreAccount = "IsDataTransferStateStoreAccount"; - } - - public static class TransportControlCommandOperations - { - public const string DeactivateOutputQueue = "deactivateOutputQueue"; - public const string ActivateOutputQueue = "activateOutputQueue"; - } - - public static class RetryConstants - { - public const int DisableOverride = -1; - } - - public static class DedicatedStorageAccountFeatures - { - public const string StorageAnalytics = "StorageAnalytics"; - public const string MaterializedViews = "MaterializedViews"; - public const string PITR = "Continuous mode backup policy (PITR)"; - public const string FullFidelityChangeFeed = "FullFidelityChangeFeed"; - } - - public static class GraphApiConstants - { - public const string ServerStartupConfigV1 = "gremlin-server-azurecosmos-configuration.yaml"; - public const string ServerStartupConfigV2 = "gremlin-server-azurecosmos-configuration-v2.yaml"; - public const string EnableFEHealthIntegration = "enableFEHealthIntegration"; - public const string GraphConfigPrefix = "graphapi."; - } - - public static class ChangeFeedWireFormatVersions - { - // New wire format that separates document content, metadata and previousImage. - // ConflictResolvedTimestamp(crts) exposed in this version. - public static string SeparateMetadataWithCrts = "2021-09-15"; - } - - public static class BatchApplyResourceProperties - { - public static string BatchApplyOperations = "operations"; - } - - public static class ApiSpecificNames - { - public static string SqlDatabase = "Database"; - public static string SqlContainer = "Container"; - public static string MongoDatabase = "Database"; - public static string MongoCollection = "Collection"; - public static string GremlinDatabase = "GremlinDatabase"; - public static string GremlinGraph = "Graph"; - public static string CassandraKeyspace = "Keyspace"; - public static string CassandraTable = "Table"; - public static string Table = "Table"; - } - - public static class ApiSpecificUrlNames - { - public static string SqlDatabase = "sqlDatabases"; - public static string SqlContainer = "containers"; - public static string MongoDatabase = "mongodbDatabases"; - public static string MongoCollection = "collections"; - public static string GremlinDatabase = "gremlinDatabases"; - public static string GremlinGraph = "graphs"; - public static string CassandraKeyspace = "cassandraKeyspaces"; - public static string CassandraTable = "tables"; - public static string Table = "tables"; - } - - public static class MigratePartitionConstants - { - public static string SourceFederationId = "sourceFederationId"; - public static string SourceServiceName = "sourceServiceName"; - } - - public static class MigratePartitionCallerSource - { - public static string Test = "Test"; - public static string Unknown = "Unknown"; - public static string PLB_localRegion = "PLB_localRegion"; - public static string PLB_CrossRegion = "PLB_CrossRegion"; - public static string ACIS_PartitionMigration = "ACIS_PartitionMigration"; - public static string ACIS_BulkPartitionMigration = "ACIS_BulkPartitionMigration"; - public static string ACIS_CrossSubregionAccountMigration = "ACIS_CrossSubregionAccountMigration"; - public static string ACIS_MitigateMasterMigrationFailure = "ACIS_MitigateMasterMigrationFailure"; - public static string ACIS_MitigateServerMigrationFailure = "ACIS_MitigateServerMigrationFailure"; - public static string FederationBuildout_CanaryAccountMigration = "FederationBuildout_CanaryAccountMigration"; - public static string USER_InPlaceAZMigration = "FederationBuildout_CanaryAccountMigration"; - } - - public static class EnvironmentVariables - { - public const string SocketOptionTcpKeepAliveIntervalName = "AZURE_COSMOS_TCP_KEEPALIVE_INTERVAL_SECONDS"; - public const string SocketOptionTcpKeepAliveTimeName = "AZURE_COSMOS_TCP_KEEPALIVE_TIME_SECONDS"; - public const string AggressiveTimeoutDetectionEnabled = "AZURE_COSMOS_AGGRESSIVE_TIMEOUT_DETECTION_ENABLED"; - public const string TimeoutDetectionTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_TIME_LIMIT_IN_SECONDS"; - public const string TimeoutDetectionOnWriteThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_WRITE_THRESHOLD"; - public const string TimeoutDetectionOnWriteTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_WRITE_TIME_LIMIT_IN_SECONDS"; - public const string TimeoutDetectionOnHighFrequencyThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_HIGH_FREQUENCY_THRESHOLD"; - public const string TimeoutDetectionOnHighFrequencyTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_HIGH_FREQUENCY_TIME_LIMIT_IN_SECONDS"; - public const string TimeoutDetectionDisabledOnCPUThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_DISABLED_ON_CPU_THRESHOLD"; - } - - public static class AvailabilityZoneMigrationProperties - { - public const string DesiredIsZoneRedundantValue = "desiredIsZoneRedundantValue"; - public const string MigrateServerPartitionsOnly = "migrateServerPartitionsOnly"; - public const string MasterSourceFederationId = "masterSourceFederationId"; - } - - public static class RoleNames - { - public const string MasterCluster0 = "MasterCluster0"; - public const string ServerCluster0 = "ServerCluster0"; - public const string FabricInfrastructure = "FabricInfrastructure"; - public const string CosmosDBGateway = "CosmosDBGateway"; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal static class Constants + { + public const char DBSeparator = ';'; + public const char ModeSeparator = ':'; + public const char StartArray = '['; + public const char EndArray = ']'; + public const char PartitionSeparator = ','; + public const char UrlPathSeparator = '/'; + + public const string DataContractNamespace = "http://schemas.microsoft.com/windowsazure"; + + // This should match (maxResourceSize - resourceSizePadding) from Server settings.xml + public const int MaxResourceSizeInBytes = (2 * 1024 * 1024) - 1; + + // This should match maxBatchRequestBodySize from Server settings.xml + public const int MaxDirectModeBatchRequestBodySizeInBytes = 2202010; + + // This should match maxBatchOperationsPerRequest from Server settings.xml + public const int MaxOperationsInDirectModeBatchRequest = 100; + + public const int MaxGatewayModeBatchRequestBodySizeInBytes = 16 * 1024 * 1024; + + public const int MaxOperationsInGatewayModeBatchRequest = 1000; + + public const string FirewallAuthorization = "FirewallAuthorization"; + + // As per https://docs.microsoft.com/en-us/azure/storage/common/storage-redundancy + // table secondary endpoint is suffixed by -secondary. + public const string TableSecondaryEndpointSuffix = "-secondary"; + + // Attribute stamped on BLOB containers/BLOBs + // for various purposes. + // MUST be in sync with XStoreUploader native code. + public static class Quota + { + // Quota Header Strings, must be in sync with ResourceQuotaManager.h + public const string Database = "databases"; + public const string Collection = "collections"; + public const string User = "users"; + public const string Permission = "permissions"; + public const string CollectionSize = "collectionSize"; + public const string DocumentsSize = "documentsSize"; + public const string DocumentsCount = "documentsCount"; + public const string SampledDistinctPartitionKeyCount = "sampledDistinctPartitionKeyCount"; + public const string StoredProcedure = "storedProcedures"; + public const string Trigger = "triggers"; + public const string UserDefinedFunction = "functions"; + public static char[] DelimiterChars = { '=', ';' }; + } + + public static class BlobStorageAttributes + { + // Container type. Only key is relevant. However set value to be + // same as key to permit future enhancements. + public const string attachmentContainer = "x_ms_attachmentContainer"; + + // Container type. Only key is relevant. However set value to be + // same as key to permit future enhancements. + public const string backupContainer = "x_ms_backupContainer"; + + // Container retention period. + public const string backupRetentionIntervalInHours = "x_ms_backupRetentionIntervalInHours"; + + // Container backup interval. + public const string backupIntervalInMinutes = "x_ms_backupIntervalInMinutes"; + + // non-FQDN. + public const string owningFederation = "x_ms_owningFederation"; + + // Name of the DatabaseAccount for which this blob stores data + public const string owningDatabaseAccountName = "x_ms_databaseAccountName"; + + // Last UTC time the attachment in Azure storage was checked and identified + // to be NOT an orphan (i.e., still referenced from a document) + public const string lastAttachmentCheckTime = "x_ms_lastAttachmentCheckTimeUtc"; + + // Last UTC time the attachment (or an attachment container) + // in Azure storage was checked and identified AS an orphan + // (i.e., NOT referenced from a document or in use by any DSI) + public const string orphanAttachmentProbationStartTime = "x_ms_orphanAttachmentProbationStartTimeUtc"; + + // Last UTC time a backup container in Azure storage was checked and identified + // AS an orphan (i.e., NOT used by any DSI in the federation) + public const string orphanBackupProbationStartTime = "x_ms_orphanBackupProbationStartTime"; + + // FQDN hostname stamped on document attachment BLOB uploads + // to scope orphan attachment BLOB cleanup to + // only those BLOBs that were uploaded by a given + // OneBox. + public const string oneBoxHostName = "x_ms_OneBoxHostName"; + + // The last scan time of a backup log container + public const string lastScanTime = "x_ms_lastScanTime"; + + // Backup hold until + public const string backupHoldUntil = "x_ms_backupHoldUntil"; + + // Backup valid starting time + public const string backupStartTime = "x_ms_backupStartTime"; + + // Backup valid ending time + public const string backupTime = "x_ms_backupTime"; + } + + public static class CosmosDBRequestProperties + { + public const string IsAllowedOrigin = "isAllowedOrigin"; + } + + public static class Offers + { + public const string OfferVersion_None = ""; + public const string OfferVersion_V1 = "V1"; + public const string OfferVersion_V2 = "V2"; + + public const string OfferType_Invalid = "Invalid"; + } + + public static class MongoServerVersion + { + public const string Version3_2 = "3.2"; + public const string Version3_6 = "3.6"; + public const string Version4_0 = "4.0"; + public const string Version4_2 = "4.2"; + public const string Version5_0 = "5.0"; + public const string Version6_0 = "6.0"; + public const string Version7_0 = "7.0"; + } + + internal static class Indexing + { + public const int IndexingSchemeVersionV1 = 1; + public const int IndexingSchemeVersionV2 = 2; + } + + public static class PartitionedQueryExecutionInfo + { + public const int Version_1 = 1; + public const int Version_2 = 2; + public const int CurrentVersion = PartitionedQueryExecutionInfo.Version_2; + } + + public static class Properties + { + public const string Resource = "resource"; + public const string Options = "options"; + public const string SubscriptionId = "subscriptionId"; + public const string FabricClientEndpoints = "fabricClientEndpoints"; + public const string SubscriptionUsageType = "subscriptionUsageType"; + public const string EnabledLocations = "enabledLocations"; + public const string SubscriptionState = "subscriptionState"; + public const string MigratedSubscriptionId = "migratedSubscriptionId"; + public const string QuotaId = "quotaId"; + public const string OfferCategories = "offerCategories"; + public const string DocumentServiceName = "documentServiceName"; + public const string OperationId = "operationId"; + public const string OperationDetails = "operationDetails"; + public const string AffinityGroupName = "affinityGroupName"; + public const string LocationName = "locationName"; + public const string SecondaryLocationName = "SecondaryLocationName"; + public const string SubRegionId = "subRegionId"; + public const string InstanceSize = "instanceSize"; + public const string Status = "status"; + public const string IsMerged = "merged"; + public const string RequestedStatus = "requestedStatus"; + public const string ExtendedStatus = "extendedStatus"; + public const string ExtendedResult = "extendedResult"; + public const string StatusCode = "statusCode"; + public const string DocumentEndpoint = "documentEndpoint"; + public const string TableEndpoint = "tableEndpoint"; + public const string TableSecondaryEndpoint = "tableSecondaryEndpoint"; + public const string GremlinEndpoint = "gremlinEndpoint"; + public const string CassandraEndpoint = "cassandraEndpoint"; + public const string EtcdEndpoint = "etcdEndpoint"; + public const string SqlEndpoint = "sqlEndpoint"; + public const string SqlxEndpoint = "sqlxEndpoint"; + public const string MongoEndpoint = "mongoEndpoint"; + public const string AnalyticsEndpoint = "analyticsEndpoint"; + public const string DatabaseAccountEndpoint = "databaseAccountEndpoint"; + public const string PrimaryMasterKey = "primaryMasterKey"; + public const string SecondaryMasterKey = "secondaryMasterKey"; + public const string PrimaryReadonlyMasterKey = "primaryReadonlyMasterKey"; + public const string SecondaryReadonlyMasterKey = "secondaryReadonlyMasterKey"; + public const string PrimaryMasterKeyGenerationTimestamp = "primaryMasterKeyGenerationTimestamp"; + public const string SecondaryMasterKeyGenerationTimestamp = "secondaryMasterKeyGenerationTimestamp"; + public const string PrimaryReadonlyKeyGenerationTimestamp = "primaryReadonlyKeyGenerationTimestamp"; + public const string SecondaryReadonlyKeyGenerationTimestamp = "secondaryReadonlyMasterKeyGenerationTimestamp"; + public const string DatabaseAccountKeysMetadata = "keysMetadata"; + public const string ConnectionStrings = "connectionStrings"; + public const string ConnectionString = "connectionString"; + public const string Description = "description"; + public const string ResourceKeySeed = "resourceKeySeed"; + public const string MaxStoredProceduresPerCollection = "maxStoredProceduresPerCollection"; + public const string MaxUDFsPerCollections = "maxUDFsPerCollections"; + public const string MaxTriggersPerCollection = "maxTriggersPerCollection"; + public const string IsolationLevel = "isolationLevel"; + public const string SubscriptionDisabled = "subscriptionDisabled"; + public const string IsDynamic = "isDynamic"; + public const string FederationName = "federationName"; + public const string FederationName1 = "federationName1"; + public const string FederationName2 = "federationName2"; + public const string FederationId = "federationId"; + public const string ComputeFederationId = "computeFederationId"; + public const string PlacementHint = "placementHint"; + public const string CreationTimestamp = "creationTimestamp"; + public const string SourceCreationTimestamp = "sourceCreationTimestamp"; + public const string SourceDeletionTimestamp = "sourceDeletionTimestamp"; + public const string ExtendedProperties = "extendedProperties"; + public const string KeyKind = "keyKind"; + public const string SystemKeyKind = "systemKeyKind"; + public const string ScaleUnits = "scaleUnits"; + public const string Location = "location"; + public const string Kind = "kind"; + public const string Region1 = "region1"; + public const string Region2 = "region2"; + public const string WritableLocations = "writableLocations"; + public const string ReadableLocations = "readableLocations"; + public const string Tags = "tags"; + public const string ResourceGroupName = "resourceGroupName"; + public const string PropertiesName = "properties"; + public const string RegionalPropertiesName = "regionalStateProperties"; + public const string ProvisioningState = "provisioningState"; + public const string CommunicationAPIKind = "communicationAPIKind"; + public const string UseMongoGlobalCacheAccountCursor = "useMongoGlobalCacheAccountCursor"; + public const string StorageSizeInMB = "storageSizeInMB"; + public const string DatabaseAccountOfferType = "databaseAccountOfferType"; + public const string Type = "type"; + public const string TargetType = "targetType"; + public const string TargetSku = "targetSku"; + public const string TargetTier = "targetTier"; + public const string Error = "error"; + public const string State = "state"; + public const string RegistrationDate = "registrationDate"; + public const string Value = "value"; + public const string NextLink = "nextLink"; + public const string DestinationSubscription = "destinationSubscription"; + public const string TargetResourceGroup = "targetResourceGroup"; + public const string ConfigurationOverrides = "configurationOverrides"; + public const string Name = "name"; + public const string Fqdn = "fqdn"; + public const string PublicIPAddressResourceName = "publicIPAddressName"; + public const string PublicIPAddressResourceGroup = "publicIPAddressResourceGroup"; + public const string VnetName = "vnetName"; + public const string VnetResourceGroup = "vnetResourceGroup"; + public const string Ipv4Address = "Ipv4Address"; + public const string RoleNameSuffix = "roleNameSuffix"; + public const string ReservedCname = "reservedCname"; + public const string ServiceType = "serviceType"; + public const string ServiceCount = "serviceCount"; + public const string TargetCapacityInMB = "targetCapacityInMB"; + public const string IsRuntimeServiceBindingEnabled = "isRuntimeServiceBindingEnabled"; + public const string MaxDocumentCollectionCount = "maxDocumentCollectionCount"; + public const string Reserved = "reserved"; + public const string Resources = "resources"; + public const string NamingConfiguration = "namingConfiguration"; + public const string DatabaseAccountName = "databaseAccountName"; + public const string DocumentServiceApiEndpoint = "documentServiceApiEndpoint"; + public const string Health = "health"; + public const string APIVersion = "APIVersion"; + public const string EmitArrayContainsForMongoQueries = "emitArrayContainsForMongoQueries"; + public const string Flights = "flights"; + public const string MigratedRegionalAccountName = "migratedRegionalAccountName"; + public const string DatabaseResourceId = "databaseResourceId"; + public const string SubscriptionKind = "subscriptionKind"; + public const string PlacementPolicies = "placementPolicies"; + public const string Action = "action"; + public const string Audience = "audience"; + public const string AudienceKind = "audienceKind"; + public const string OfferKind = "offerKind"; + public const string TenantId = "tenantId"; + public const string SupportedCapabilities = "supportedCapabilities"; + public const string PlacementHints = "placementHints"; + public const string IsMasterService = "isMasterService"; + public const string CapUncapMetadata = "capUncapMetadata"; + public const string IsCappedForServer = "isCappedForServer"; + public const string CapUncapMetadataForServer = "capUncapMetadataForServer"; + public const string IsCappedForMaster = "isCappedForMaster"; + public const string CapUncapMetadataForMaster = "capUncapMetadataForMaster"; + public const string CapabilityResource = "capabilityResource"; + public const string DocumentType = "documentType"; + public const string SystemDatabaseAccountStoreType = "systemDatabaseAccountStoreType"; + public const string FederationType = "federationType"; + public const string FederationSubType = "federationSubType"; + public const string FederationGenerationKind = "federationGenerationKind"; + public const string UseEPKandNameAsPrimaryKeyInDocumentTable = "useEPKandNameAsPrimaryKeyInDocumentTable"; + public const string EnableUserDefinedType = "enableUserDefinedType"; + public const string ExcludeOwnerIdFromDocumentTable = "excludeOwnerIdFromDocumentTable"; + public const string EnableQuerySupportForHybridRow = "enableQuerySupportForHybridRow"; + public const string FederationProxyFqdn = "federationProxyFqdn"; + public const string IsFailedOver = "isFailedOver"; + public const string FederationProxyReservedCname = "federationProxyReservedCname"; + public const string EnableMultiMasterMigration = "enableMultiMasterMigration"; + public const string EnableNativeGridFS = "enableNativeGridFS"; + public const string MongoDefaultsVersion = "mongoDefaultsVersion"; + public const string ServerVersion = "serverVersion"; + public const string ContinuousBackupInformation = "continuousBackupInformation"; + public const string LatestRestorableTimestamp = "latestRestorableTimestamp"; + public const string EnableBinaryEncodingOfContent = "enableBinaryEncodingOfContent"; + public const string SkipMigrateToComputeDatabaseCollectionChecks = "skipMigrateToComputeDatabaseCollectionChecks"; + public const string UseApiOperationHandler = "UseApiOperationHandler"; + public const string AccountKeyManagementType = "accountKeyManagementType"; + public const string ManagedReadWriteAccountKeyResource = "managedReadWriteAccountKeyResource"; + public const string IsManagedReadWriteAccountKeyResourceStale = "isManagedReadWriteAccountKeyResourceStale"; + public const string ManagedReadOnlyAccountKeyResource = "managedReadOnlyAccountKeyResource"; + public const string IsManagedReadOnlyAccountKeyResourceStale = "isManagedReadOnlyAccountKeyResourceStale"; + public const string UserName = "userName"; + public const string Subscriptions = "subscriptions"; + public const string ResourceGroups = "resourceGroups"; + public const string Providers = "providers"; + public const string RestorableDatabaseAccounts = "restorableDatabaseAccounts"; + public const string AsynchronousDeletionRetryCount = "asynchronousDeletionRetryCount"; + public const string Severity = "severity"; + + public const string MasterValue = "masterValue"; + public const string SecondaryValue = "secondaryValue"; + + public const string ArmLocation = "armLocation"; + public const string SubscriptionName = "subscriptionName"; + + //Throughput Pool + public const string MaxThroughput = "maxThroughput"; + + // Query + public const string Query = "query"; + public const string Parameters = "parameters"; + + // Global Database account properties + public const string GlobalDatabaseAccountName = "globalDatabaseAccountName"; + public const string FailoverPriority = "failoverPriority"; + public const string FailoverPolicies = "failoverPolicies"; + public const string Locations = "locations"; + public const string WriteLocations = "writeLocations"; + public const string ReadLocations = "readLocations"; + public const string LocationType = "locationType"; + public const string MasterServiceUri = "masterServiceUri"; + public const string RestoreParams = "restoreParameters"; + public const string CreateMode = "createMode"; + public const string RestoreMode = "restoreMode"; + public const string StoreType = "storeType"; + + // CSM Metric properties + public const string LocalizedValue = "localizedValue"; + public const string Unit = "unit"; + public const string ResourceUri = "resourceUri"; + public const string PrimaryAggregationType = "primaryAggregationType"; + public const string MetricAvailabilities = "metricAvailabilities"; + public const string MetricValues = "metricValues"; + public const string TimeGrain = "timeGrain"; + public const string Retention = "retention"; + public const string TimeStamp = "timestamp"; + public const string Average = "average"; + public const string Minimum = "minimum"; + public const string Maximum = "maximum"; + public const string MetricCount = "count"; + public const string Total = "total"; + public const string StartTime = "startTime"; + public const string EndTime = "endTime"; + public const string DisplayName = "displayName"; + public const string Limit = "limit"; + public const string CurrentValue = "currentValue"; + public const string NextResetTime = "nextResetTime"; + public const string QuotaPeriod = "quotaPeriod"; + public const string SupportedRegions = "supportedRegions"; + public const string Percentiles = "percentiles"; + public const string SourceRegion = "sourceRegion"; + public const string TargetRegion = "targetRegion"; + public const string P10 = "P10"; + public const string P25 = "P25"; + public const string P50 = "P50"; + public const string P75 = "P75"; + public const string P90 = "P90"; + public const string P95 = "P95"; + public const string P99 = "P99"; + + public const string Id = "id"; + public const string RId = "_rid"; + public const string SelfLink = "_self"; + public const string LastModified = "_ts"; + public const string CreatedTime = "_cts"; + public const string Count = "_count"; + public const string ETag = "_etag"; + public const string TimeToLive = "ttl"; + public const string DefaultTimeToLive = "defaultTtl"; + public const string TimeToLivePropertyPath = "ttlPropertyPath"; + public const string AnalyticalStorageTimeToLive = "analyticalStorageTtl"; + + public const string DatabasesLink = "_dbs"; + public const string CollectionsLink = "_colls"; + public const string UsersLink = "_users"; + public const string PermissionsLink = "_permissions"; + public const string AttachmentsLink = "_attachments"; + public const string StoredProceduresLink = "_sprocs"; + public const string TriggersLink = "_triggers"; + public const string UserDefinedFunctionsLink = "_udfs"; + public const string ConflictsLink = "_conflicts"; + public const string DocumentsLink = "_docs"; + public const string ResourceLink = "resource"; + public const string MediaLink = "media"; + public const string SchemasLink = "_schemas"; + + public const string PermissionMode = "permissionMode"; + public const string ResourceKey = "key"; + public const string Token = "_token"; + + public const string FederationOperationKind = "federationOperationKind"; + public const string RollbackKind = "rollbackKind"; + + // Collection Truncate + public const string CollectionTruncate = "collectionTruncate"; + + // Indexing Policy. + public const string IndexingPolicy = "indexingPolicy"; + public const string Automatic = "automatic"; + public const string StringPrecision = "StringPrecision"; + public const string NumericPrecision = "NumericPrecision"; + public const string MaxPathDepth = "maxPathDepth"; + public const string IndexingMode = "indexingMode"; + public const string IndexType = "IndexType"; + public const string IndexKind = "kind"; + public const string DataType = "dataType"; + public const string Precision = "precision"; + public const string PartitionKind = "kind"; + public const string SystemKey = "systemKey"; + + public const string Paths = "paths"; + public const string Path = "path"; + public const string IsFullIndex = "isFullIndex"; + public const string Filter = "filter"; + public const string FrequentPaths = "Frequent"; + public const string IncludedPaths = "includedPaths"; + public const string InFrequentPaths = "InFrequent"; + public const string ExcludedPaths = "excludedPaths"; + public const string Indexes = "indexes"; + public const string IndexingSchemeVersion = "IndexVersion"; + + public const string CompositeIndexes = "compositeIndexes"; + public const string Order = "order"; + + public const string SpatialIndexes = "spatialIndexes"; + public const string Types = "types"; + public const string BoundingBox = "boundingBox"; + public const string Xmin = "xmin"; + public const string Ymin = "ymin"; + public const string Xmax = "xmax"; + public const string Ymax = "ymax"; + + public const string EnableIndexingSchemeV2 = "enableIndexingSchemeV2"; + + // CapUncapMetadata + public const string Source = "source"; + public const string Reason = "reason"; + public const string IncidentId = "incidentId"; + + // GeospatialConfig + public const string GeospatialType = "type"; + public const string GeospatialConfig = "geospatialConfig"; + + // ComputedProperties + public const string ComputedProperties = "computedProperties"; + + // Unique index. + public const string UniqueKeyPolicy = "uniqueKeyPolicy"; + public const string UniqueKeys = "uniqueKeys"; + public const string UniqueIndexReIndexContext = "uniqueIndexReIndexContext"; + public const string UniqueIndexReIndexingState = "uniqueIndexReIndexingState"; + public const string LastDocumentGLSN = "lastDocumentGLSN"; + public const string UniqueIndexNameEncodingMode = "uniqueIndexNameEncodingMode"; + + // ReIndexer + public const string EnableReIndexerProgressCalc = "enableReIndexerProgressCalc"; + + // ChangeFeed policy + public const string ChangeFeedPolicy = "changeFeedPolicy"; + public const string LogRetentionDuration = "retentionDuration"; + + //MaterializedViewDefinition + public const string MaterializedViewDefinition = "materializedViewDefinition"; + public const string AllowMaterializedViews = "allowMaterializedViews"; + public const string SourceCollectionRid = "sourceCollectionRid"; + public const string SourceCollectionId = "sourceCollectionId"; + public const string Definition = "definition"; + public const string ApiSpecificDefinition = "apiSpecificDefinition"; + public const string AllowMaterializedViewsInCollectionDeleteRollForward = "allowMaterializedViewsInCollectionDeleteRollForward"; + public const string MaterializedViews = "materializedViews"; + + //TieredStorageCollection + public const string MaterializedViewContainerType = "containerType"; + + // Schema Policy + public const string SchemaPolicy = "schemaPolicy"; + + // PartitionKeyDelete + public const string PartitionKeyDeleteThroughputFraction = "partitionKeyDeleteThroughputFraction"; + public const string EnableMultiRegionGlsnCheckForPKDelete = "enableMultiRegionGlsnCheckForPKDelete"; + + // Internal Schema Properties + public const string InternalSchemaProperties = "internalSchemaProperties"; + public const string UseSchemaForAnalyticsOnly = "useSchemaForAnalyticsOnly"; + + // ReplicaResource + public const string Quota = "quota"; + + // PartitionInfo + public const string ResourceType = "resourceType"; + public const string ServiceIndex = "serviceIndex"; + public const string PartitionIndex = "partitionIndex"; + + // ModuleCommand + public const string ModuleEvent = "moduleEvent"; + public const string ModuleEventReason = "moduleEventReason"; + public const string ModuleStatus = "moduleStatus"; + public const string ThrottleLevel = "throttleLevel"; + public const string ProcessId = "processId"; + public const string HasFaulted = "hasFaulted"; + public const string Result = "result"; + + // ConsistencyPolicy + public const string ConsistencyPolicy = "consistencyPolicy"; + public const string DefaultConsistencyLevel = "defaultConsistencyLevel"; + public const string MaxStalenessPrefix = "maxStalenessPrefix"; + public const string MaxStalenessIntervalInSeconds = "maxIntervalInSeconds"; + + // ReplicationPolicy + public const string ReplicationPolicy = "replicationPolicy"; + public const string AsyncReplication = "asyncReplication"; + public const string MaxReplicaSetSize = "maxReplicasetSize"; + public const string MinReplicaSetSize = "minReplicaSetSize"; + + // WritePolicy. + public const string WritePolicy = "writePolicy"; + public const string PrimaryCheckpointInterval = "primaryLoggingIntervalInMilliSeconds"; + public const string SecondaryCheckpointInterval = "secondaryLoggingIntervalInMilliSeconds"; + + // Backup container properties + public const string Collection = "RootResourceName"; + public const string CollectionId = "collectionId"; + public const string Completed = "completed"; + public const string BackupOfferType = "OfferType"; + public const string BackupDatabaseAccountName = "x_ms_databaseAccountName"; + public const string BackupContainerName = "backupContainerName"; + public const string UniquePartitionIdentifier = "UniquePartitionIdentifier"; + + // Backup store settings + public const string BackupStoreUri = "fileUploaderUri"; + public const string BackupStoreAccountName = "fileUploaderAccountName"; + + // Backup Policy + public const string GlobalBackupPolicy = "globalBackupPolicy"; + public const string BackupPolicy = "backupPolicy"; + public const string CollectionBackupPolicy = "backupPolicy"; + public const string CollectionBackupType = "type"; + public const string BackupStrategy = "backupStrategy"; + public const string BackupRedundancy = "backupRedundancy"; + public const string BackupStorageRedundancy = "backupStorageRedundancy"; + public const string BackupIntervalInMinutes = "backupIntervalInMinutes"; + public const string BackupRetentionIntervalInHours = "backupRetentionIntervalInHours"; + public const string PeriodicModeProperties = "periodicModeProperties"; + public const string ContinuousModeProperties = "continuousModeProperties"; + public const string BackupPolicyMigrationState = "migrationState"; + + // PITR Migration + public const string PitrMigrationState = "pitrMigrationState"; + public const string PitrMigrationStatus = "pitrMigrationStatus"; + public const string PitrMigrationBeginTimestamp = "pitrMigrationBeginTimestamp"; + public const string PitrMigrationEndTimestamp = "pitrMigrationEndTimestamp"; + public const string PitrMigrationAttemptTimestamp = "pitrMigrationAttemptTimestamp"; + public const string PreMigrationBackupPolicy = "preMigrationBackupPolicy"; + public const string LastPitrStandardOptInTimestamp = "lastPitrStandardOptInTimestamp"; + public const string LastPitrBasicOptInTimestamp = "lastPitrBasicOptInTimestamp"; + public const string PitrMigrationStartTimestamp = "startTime"; + public const string TargetPitrSku = "targetPitrSku"; + + // Periodic Migration + public const string PeriodicMigrationState = "periodicMigrationState"; + public const string PeriodicMigrationStatus = "periodicMigrationStatus"; + public const string PeriodicMigrationBeginTimestamp = "periodicMigrationBeginTimestamp"; + public const string PeriodicMigrationEndTimestamp = "periodicMigrationEndTimestamp"; + public const string PeriodicMigrationAttemptTimestamp = "periodicMigrationAttemptTimestamp"; + public const string PrePeriodicMigrationPitrSku = "prePeriodicMigrationPitrSku"; + public const string FirstPeriodicMigrationOptInTimestamp = "firstPeriodicMigrationOptInTimestamp"; + + // Backup Storage Accounts + public const string BackupStorageAccountsEnabled = "BackupStorageAccountsEnabled"; + public const string BackupStorageAccountNames = "BackupStorageAccountNames"; + public const string BackupStorageUris = "BackupStorageUris"; + public const string TotalNumberOfDedicatedStorageAccounts = "TotalNumberOfDedicatedStorageAccounts"; + public const string ReplaceOriginalBackupStorageAccounts = "replaceOriginalBackupStorageAccounts"; + public const string EnableDedicatedStorageAccounts = "enableDedicatedStorageAccounts"; + public const string EnableSystemSnapshots = "enableSystemSnapshots"; + public const string BackupStorageRedundancies = "backupStorageRedundancies"; + public const string StorageAccountName = "storageAccountName"; + public const string StorageAccountLocation = "storageAccountLocation"; + + // Restore Policy + public const string RestorePolicy = "restorePolicy"; + public const string SourceServiceName = "sourceServiceName"; + public const string RegionalDatabaseAccountInstanceId = "regionalDatabaseAccountInstanceId"; + public const string GlobalDatabaseAccountInstanceId = "globalDatabaseAccountInstanceId"; + public const string InstanceId = "instanceId"; + public const string SourceBackupLocation = "sourceBackupLocation"; + public const string ReuseSourceDatabaseAccountAccessKeys = "reuseSourceDatabaseAccountAccessKeys"; + public const string RecreateDatabase = "recreateDatabase"; + public const string LatestBackupSnapshotInDateTime = "latestBackupSnapshotInDateTime"; + public const string TargetFederation = "targetFederation"; + public const string TargetFederationKind = "targetFederationKind"; + public const string CollectionOrDatabaseResourceIds = "collectionOrDatabaseResourceIds"; + public const string SourceHasMultipleStorageAccounts = "sourceHasMultipleStorageAccounts"; + public const string AllowPartialRestore = "allowPartialRestore"; + public const string DedicatedBackupAccountNames = "dedicatedBackupAccountNames"; + public const string AllowPartitionsRestoreOptimization = "allowPartitionsRestoreOptimization"; + public const string UseUniquePartitionIdBasedRestoreWorkflow = "useUniquePartitionIdBasedRestoreWorkflow"; + public const string UseSnapshotToRestore = "useSnapshotToRestore"; + public const string AllowVnetRestore = "allowVnetRestore"; + public const string UpdateBackupContainerMetadata = "updateBackupContainerMetadata"; + public const string RestoreWithBuiltinDatabaseAccountPicker = "restoreWithBuiltinDatabaseAccountPicker"; + public const string RestoreWithSourceGlobalDatabaseAccountInstanceId = "restoreWithSourceGlobalDatabaseAccountInstanceId"; + public const string RestoreUsingGeoRedundantBackup = "restoreUsingGeoRedundantBackup"; + public const string RestoreWithTtlDisabled = "restoreWithTtlDisabled"; + public const string DatabasesToRestore = "databasesToRestore"; + public const string DatabaseName = "databaseName"; + public const string CollectionNames = "collectionNames"; + public const string GraphNames = "graphNames"; + public const string TableNames = "tableNames"; + public const string RestoreTillEndOfLogChain = "restoreTillEndOfLogChain"; + public const int TimeToleranceForRestoreTillEndOfLogChain = 1000; //ms + + // Restore Properties + public const string RestoreTimestampInUtc = "restoreTimestampInUtc"; + public const string RestoreSource = "restoreSource"; + public const string IsInAccountRestoreCapabilityEnabled = "isInAccountRestoreCapabilityEnabled"; + public const string CanUndelete = "canUndelete"; + public const string CanUndeleteReason = "canUndeleteReason"; + + // Backup Hold + public const string BackupHoldTimeInDays = "backupHoldTimeInDays"; + + // Restore Tags + public const string RestoredSourceDatabaseAccountName = "restoredSourceDatabaseAccountName"; + public const string RestoredAtTimestamp = "restoredAtTimestamp"; + + // Read Policy + // Indicates the relative weight of read from primary compared to secondary. + // Higher this value, cheaper are the reads from primary. + public const string PrimaryReadCoefficient = "primaryReadCoefficient"; + public const string SecondaryReadCoefficient = "secondaryReadCoefficient"; + + // Scripting + public const string Body = "body"; + public const string TriggerType = "triggerType"; + public const string TriggerOperation = "triggerOperation"; + + public const string MaxSize = "maxSize"; + + public const string Content = "content"; + + public const string ContentType = "contentType"; + + // ErrorResource. + public const string Code = "code"; + public const string Message = "message"; + public const string ErrorDetails = "errorDetails"; + public const string AdditionalErrorInfo = "additionalErrorInfo"; + + //CassandraErrorResource. + public const string Target = "target"; + + // AddressResource + public const string IsPrimary = "isPrimary"; + public const string IsAuxiliary = "isAuxiliary"; + public const string Protocol = "protocol"; + public const string LogicalUri = "logicalUri"; + public const string PhysicalUri = "physcialUri"; + + // Authorization + public const string AuthorizationFormat = "type={0}&ver={1}&sig={2}"; + public const string MasterToken = "master"; + public const string ResourceToken = "resource"; + public const string AadToken = "aad"; + public const string SasToken = "sas"; + public const string TokenVersion = "1.0"; + public const string TokenVersionV1 = "1"; + public const string TokenVersionV2 = "2.0"; + public const string AuthSchemaType = "type"; + public const string ResourceTokenV2Label = "ResourceTokenV2Label"; + public const string ResourceTokenV2Context = "ResourceTokenV2Context"; + public const string AuthVersion = "ver"; + public const string AuthSignature = "sig"; + public const string readPermissionMode = "read"; + public const string allPermissionMode = "all"; + + // Federation Resource + public const string PackageVersion = "packageVersion"; + public const string FabricApplicationVersion = "fabricApplicationVersion"; + public const string FabricRingCodeVersion = "fabricRingCodeVersion"; + public const string FabricRingConfigVersion = "fabricRingConfigVersion"; + public const string CertificateVersion = "certificateVersion"; + public const string DeploymentId = "deploymentId"; + public const string DecommisionedFederations = "decommisionedFederations"; + public const string FederationKind = "federationKind"; + public const string SupportedPlacementHints = "supportedPlacementHints"; + public const string PrimarySystemKeyReadOnly = "primarySystemKeyReadOnly"; + public const string SecondarySystemKeyReadOnly = "secondarySystemKeyReadOnly"; + public const string UsePrimarySystemKeyReadOnly = "UsePrimarySystemKeyReadOnly"; + public const string PrimarySystemKeyReadWrite = "primarySystemKeyReadWrite"; + public const string SecondarySystemKeyReadWrite = "secondarySystemKeyReadWrite"; + public const string UsePrimarySystemKeyReadWrite = "UsePrimarySystemKeyReadWrite"; + public const string PrimarySystemKeyAll = "primarySystemKeyAll"; + public const string SecondarySystemKeyAll = "secondarySystemKeyAll"; + public const string UsePrimarySystemKeyAll = "UsePrimarySystemKeyAll"; + public const string UseSecondaryComputeGatewayKey = "UseSecondaryComputeGatewayKey"; + public const string Weight = "Weight"; + public const string BatchId = "BatchId"; + public const string IsCappedForServerPartitionAllocation = "isCappedForServerPartitionAllocation"; + public const string IsDirty = "IsDirty"; + public const string IsAvailabilityZoneFederation = "IsAvailabilityZoneFederation"; + public const string AZIndex = "AZIndex"; + public const string IsFederationUnavailable = "isFederationUnavailable"; + public const string ServiceExtensions = "serviceExtensions"; + public const string HostedServicesDescription = "hostedServicesDescription"; + public const string CsesMigratedHostedServicesDescription = "csesMigratedHostedServicesDescription"; + public const string FederationProxyResource = "federationProxyResource"; + public const string ReservedDnsName = "reservedDnsName"; + public const string BuildoutStatus = "BuildoutStatus"; + public const string IsCsesCloudService = "IsCsesCloudService"; + public const string IsInBitLockerRotation = "IsInBitLockerRotation"; + public const string PrimaryBitLockerKeyVersion = "PrimaryBitLockerKeyVersion"; + public const string SecondaryBitLockerKeyVersion = "SecondaryBitLockerKeyVersion"; + public const string BitLockerKeysSettingType = "BitLockerKeysSettingType"; + public const string BitLockerKeysRotationState = "BitLockerKeysRotationState"; + public const string InfrastructureServices = "InfrastructureServices"; + public const string SerializableResourceType = "SerializableResourceType"; + public const string EnableTenantProtection = "EnableTenantProtection"; + public const string IsEnabledForClusterSpanning = "IsEnabledForClusterSpanning"; + + // Federation settings + public const string AllowReutilizationOfComputeResources = "AllowReutilizationOfComputeResources"; + + //Deployment Constants + public const string FabricApplicationName = "fabricApplicationName"; + public const string UseMonitoredUpgrade = "useMonitoredUpgrade"; + public const string UpgradeInfo = "UpgradeInfo"; + + // ManagementVersion Resource + public const string Version = "Version"; + public const string ManagementEndPoint = "ManagementEndPoint"; + + // StorageService Resource + public const string StorageServiceName = "name"; + public const string StorageServiceLocation = "location"; + public const string StorageServiceSecondaryLocation = "secondaryLocation"; + public const string BlobEndpoint = "blobEndpoint"; + public const string SecondaryBlobEndpoint = "secondaryBlobEndpoint"; + public const string StorageServiceSubscriptionId = "subscriptionId"; + public const string StorageServiceIndex = "storageIndex"; + public const string IsWritable = "isWritable"; + public const string StorageServiceKind = "storageServiceKind"; + public const string StorageAccountType = "storageAccountType"; + public const string StorageServiceResourceGroupName = "resourceGroupName"; + public const string StorageServiceFederationId = "federationId"; + public const string StorageAccountSku = "storageAccountSku"; + public const string IsRegisteredWithSms = "isRegisteredWithSms"; + public const string StorageAccountVersion = "storageAccountVersion"; + public const string StorageAccounts = "StorageAccounts"; + + // Cassandra Connector Constants + public const string ConnectorOffer = "connectorOffer"; + public const string EnableCassandraConnector = "enableCassandraConnector"; + public const string ConnectorMetadataAccountInfo = "connectorMetadataAccountInfo"; + public const string ConnectorMetadataAccountPrimaryKey = "connectorMetadataAccountPrimaryKey"; + public const string ConnectorMetadataAccountSecondaryKey = "connectorMetadataAccountSecondaryKey"; + public const string StorageServiceResource = "storageServiceResource"; + public const string OfferName = "offerName"; + public const string MaxNumberOfSupportedNodes = "maxNumberOfSupportedNodes"; + public const string MaxAllocationsPerStorageAccount = "maxAllocationsPerStorageAccount"; + public const string StorageAccountCount = "storageAccountCount"; + public const string ConnectorStorageAccounts = "connectorStorageAccounts"; + public const string UserProvidedConnectorStorageAccountsInfo = "userProvidedConnectorStorageAccountsInfo"; + public const string UserString = "User"; + public const string SystemString = "System"; + public const string ReplicationStatus = "ReplicationStatus"; + + // ResourceIdResponse Resource + public const string ResourceId = "resourceId"; + + // Managed Service Identity (MSI) + public const string ManagedServiceIdentityInfo = "managedServiceIdentityInfo"; + public const string IdentityName = "identity"; + public const string MsiSystemAssignedType = "SystemAssigned"; + public const string MsiFirstPartyType = "FirstParty"; + public const string MsiNoneType = "None"; + public const string MsiUserAssignedType = "UserAssigned"; + public const string MsiSystemAndUserAssignedType = "SystemAssigned,UserAssigned"; + public const string DefaultIdentity = "defaultIdentity"; + public const string MsiDelegatedUserAssignedType = "DelegatedUserAssigned"; // only used for DefaultMsiProperties + public const string MsiDelegatedSystemAssignedType = "DelegatedSystemAssigned"; // only used for DefaultMsiProperties + + // ServiceDocument Resource + public const string AddressesLink = "addresses"; + public const string UserReplicationPolicy = "userReplicationPolicy"; + public const string UserConsistencyPolicy = "userConsistencyPolicy"; + public const string SystemReplicationPolicy = "systemReplicationPolicy"; + public const string ReadPolicy = "readPolicy"; + public const string QueryEngineConfiguration = "queryEngineConfiguration"; + public const string EnableMultipleWriteLocations = "enableMultipleWriteLocations"; + public const string CanEnableMultipleWriteLocations = "canEnableMultipleWriteLocations"; + public const string IsServerlessEnabled = "isServerlessEnabled"; + public const string EnableSnapshotAcrossDocumentStoreAndIndex = "enableSnapshotAcrossDocumentStoreAndIndex"; + public const string IsZoneRedundant = "isZoneRedundant"; + public const string EnableThroughputAutoScale = "enableThroughputAutoScale"; + public const string ReplicatorSequenceNumberToGLSNDeltaString = "replicatorSequenceNumberToGLSNDeltaString"; + public const string ReplicatorSequenceNumberToLLSNDeltaString = "replicatorSequenceNumberToLLSNDeltaString"; + public const string IsReplicatorSequenceNumberToLLSNDeltaSet = "isReplicatorSequenceNumberToLLSNDeltaSet"; + + // Serverless Configs for 1TB, splits enabled. + public const string IsSplitOnServerlessEnabled = "isSplitOnServerlessEnabled"; + public const string IsRequestLatencyInjectionEnabledForServerless = "isRequestLatencyInjectionEnabledForServerless"; + + public const string LSN = "_lsn"; + public const string LLSN = "llsn"; + + // Conflict Resource Properties + public const string SourceResourceId = "resourceId"; + + // ConflictResource property values + public const string ResourceTypeDocument = "document"; + public const string ResourceTypeStoredProcedure = "storedProcedure"; + public const string ResourceTypeTrigger = "trigger"; + public const string ResourceTypeUserDefinedFunction = "userDefinedFunction"; + public const string ResourceTypeAttachment = "attachment"; + + public const string ConflictLSN = "conflict_lsn"; + + public const string OperationKindCreate = "create"; + public const string OperationKindPatch = "patch"; + public const string OperationKindReplace = "replace"; + public const string OperationKindDelete = "delete"; + + // Conflict + public const string Conflict = "conflict"; + public const string OperationType = "operationType"; + + // Tombstone resource + public const string TombstoneResourceType = "resourceType"; + public const string OwnerId = "ownerId"; + + // Partition resource + public const string CollectionResourceId = "collectionResourceId"; + public const string PartitionKeyRangeResourceId = "partitionKeyRangeResourceId"; + public const string WellKnownServiceUrl = "wellKnownServiceUrl"; + public const string LinkRelationType = "linkRelationType"; + public const string Region = "region"; + public const string GeoLinkIdentifier = "geoLinkIdentifier"; + + // Progress resource + public const string DatalossNumber = "datalossNumber"; + public const string ConfigurationNumber = "configurationNumber"; + + // Replica resource + public const string PartitionId = "partitionId"; + public const string SchemaVersion = "schemaVersion"; + public const string ReplicaId = "replicaId"; + public const string ReplicaRole = "replicaRole"; + public const string ReplicatorAddress = "replicatorAddress"; + public const string ReplicaStatus = "replicaStatus"; + public const string IsAvailableForWrites = "isAvailableForWrites"; + + // Offer resource + public const string OfferType = "offerType"; + public const string OfferResourceId = "offerResourceId"; + public const string OfferThroughput = "offerThroughput"; + public const string BackgroundTaskMaxAllowedThroughputPercent = "BackgroundTaskMaxAllowedThroughputPercent"; + public const string OfferIsRUPerMinuteThroughputEnabled = "offerIsRUPerMinuteThroughputEnabled"; + public const string OfferIsAutoScaleEnabled = "offerIsAutoScaleEnabled"; + public const string OfferVersion = "offerVersion"; + public const string OfferContent = "content"; + public const string CollectionThroughputInfo = "collectionThroughputInfo"; + public const string MinimumRuForCollection = "minimumRUForCollection"; + public const string NumPhysicalPartitions = "numPhysicalPartitions"; + public const string UserSpecifiedThroughput = "userSpecifiedThroughput"; + public const string OfferMinimumThroughputParameters = "offerMinimumThroughputParameters"; + public const string MaxConsumedStorageEverInKB = "maxConsumedStorageEverInKB"; + public const string MaxThroughputEverProvisioned = "maxThroughputEverProvisioned"; + public const string MaxCountOfSharedThroughputCollectionsEverCreated = "maxCountOfSharedThroughputCollectionsEverCreated"; + public const string OfferLastReplaceTimestamp = "offerLastReplaceTimestamp"; + public const string AutopilotSettings = "offerAutopilotSettings"; + public const string IsOfferRestorePending = "isOfferRestorePending"; + public const int DefaultContainerCountForSharedThroughput = 25; + + public const string AutopilotTier = "tier"; + public const string AutopilotTargetTier = "targetTier"; + public const string AutopilotMaximumTierThroughput = "maximumTierThroughput"; + public const string AutopilotAutoUpgrade = "autoUpgrade"; + public const string EnableFreeTier = "enableFreeTier"; + + public const string AutopilotMaxThroughput = "maxThroughput"; + public const string AutopilotTargetMaxThroughput = "targetMaxThroughput"; + public const string AutopilotAutoUpgradePolicy = "autoUpgradePolicy"; + public const string AutopilotThroughputPolicy = "throughputPolicy"; + public const string AutopilotThroughputPolicyIncrementPercent = "incrementPercent"; + + public const string PhysicalPartitionThroughputInfo = "physicalPartitionThroughputInfo"; + public const string SourcePhysicalPartitionThroughputInfo = "sourcePhysicalPartitionThroughputInfo"; + public const string TargetPhysicalPartitionThroughputInfo = "targetPhysicalPartitionThroughputInfo"; + public const string ThroughputPolicy = "throughputPolicy"; + public const string PhysicalPartitionStorageInfoCollection = "physicalPartitionStorageInfoCollection"; + public const string PhysicalPartitionId = "id"; + public const string PhysicalPartitionIds = "physicalPartitionIds"; + public const string PhysicalPartitionThroughput = "throughput"; + public const string PhysicalPartitionStorageInKB = "storageInKB"; + + public const string EnableAdaptiveRu = "enableAdaptiveRU"; + + public const string EnablePartitionMerge = "enablePartitionMerge"; + + public const string EnableBurstCapacity = "enableBurstCapacity"; + public const string EnableUserRateLimitingWithBursting = "enableUserRateLimitingWithBursting"; + + // Priority Based Execution can be enabled by setting the naming config enablePriorityBasedThrottling to true + // When user sets EnablePriorityBasedExecution to true in an account PATCH request, enablePriorityBasedThrottling + // is set to true in the account configuration overrrides + public const string EnablePriorityBasedThrottling = "enablePriorityBasedThrottling"; + public const string EnablePriorityBasedExecution = "enablePriorityBasedExecution"; + public const string DefaultPriorityLevel = "defaultPriorityLevel"; + public const string MinMaxThresholdsForPriorityBasedExecution = "minMaxThresholdsForPriorityBasedExecution"; + public const string MinPercentForLowPriorityRequests = "minPercentForLowPriorityRequests"; + public const string MaxPercentForLowPriorityRequests = "maxPercentForLowPriorityRequests"; + public const string MinPercentForHighPriorityRequests = "minPercentForHighPriorityRequests"; + public const string MaxPercentForHighPriorityRequests = "maxPercentForHighPriorityRequests"; + public const int DefaultMinPercentForLowPriorityRequests = 0; + public const int DefaultMaxPercentForLowPriorityRequests = 100; + public const int DefaultMinPercentForHighPriorityRequests = 0; + public const int DefaultMaxPercentForHighPriorityRequests = 100; + + // Global Rate Limiting + public const string EnableGlobalRateLimiting = "enableGlobalRateLimiting"; + // Cap the global budget for a partition. The value includes provisioned local budget. It cannot exceed 10K. + public const string GRLTargetUtilizationPerPartition = "GRLTargetUtilizationPerPartition"; + + public const string IsDryRun = "isDryRun"; + + // EnforceRUPerGB + public const string EnforceRUPerGB = "enforceRUPerGB"; + public const string MinRUPerGB = "minRUPerGB"; + + // Storage Management Store + public const string EnableStorageAnalytics = "enableStorageAnalytics"; + public const string EnablePitrAndAnalyticsTogether = "enablePitrAndAnalyticsTogether"; + public const string AnalyticsStorageServiceNames = "analyticsStorageServiceNames"; + public const string PrePeriodicMigrationAnalyticsStorageServiceNames = "prePeriodicMigrationAnalyticsStorageServiceNames"; + public const string StandardStreamGRSStorageServiceNames = "standardStreamGRSStorageServiceNames"; + public const string PrePeriodicMigrationStandardStreamGRSStorageServiceNames = "prePeriodicMigrationStandardStreamGRSStorageServiceNames"; + public const string LogStoreMetadataStorageAccountName = "logStoreMetadataStorageAccountName"; + public const string PrePeriodicMigrationLogStoreMetadataStorageAccountName = "prePeriodicMigrationLogStoreMetadataStorageAccountName"; + public const string IsParallel = "isParallel"; + public const string SasAuthEnabled = "sasAuthEnabled"; + public const string AnalyticsSubDomain = ".analytics.cosmos."; + public const string DocumentsSubDomain = ".documents"; + public const string SasTokenExpiryWindowInSeconds = "SasTokenExpiryWindowInSeconds"; + //This config must be used only for testing purpose + public const string TestOnlyConfigForBypassedFirewallAuthorization = "TestOnlyConfigForBypassedFirewallAuthorization"; + + // GeoDrReplicaInformationResource + public const string CurrentProgress = "currentProgress"; + public const string CatchupCapability = "catchupCapability"; + public const string PublicAddress = "publicAddress"; + + // Operation resource + public const string OperationName = "name"; + public const string OperationProperties = "properties"; + public const string OperationNextLink = "nextLink"; + public const string OperationDisplay = "display"; + public const string OperationDisplayProvider = "provider"; + public const string OperationDisplayResource = "resource"; + public const string OperationDisplayOperation = "operation"; + public const string OperationDisplayDescription = "description"; + + public const string PartitionKey = "partitionKey"; + public const string PartitionKeyRangeId = "partitionKeyRangeId"; + public const string MinInclusiveEffectivePartitionKey = "minInclusiveEffectivePartitionKey"; + public const string MaxExclusiveEffectivePartitionKey = "maxExclusiveEffectivePartitionKey"; + public const string MinInclusive = "minInclusive"; + public const string MaxExclusive = "maxExclusive"; + public const string RidPrefix = "ridPrefix"; + public const string ThroughputFraction = "throughputFraction"; + public const string PartitionKeyRangeStatus = "status"; + public const string Parents = "parents"; + public const string Lsn = "lsn"; + + public const string NodeStatus = "NodeStatus"; + public const string NodeName = "NodeName"; + public const string HealthState = "HealthState"; + + // CLient side encryption + public const string WrappedDataEncryptionKey = "wrappedDataEncryptionKey"; + public const string EncryptionAlgorithmId = "encryptionAlgorithmId"; + public const string KeyWrapMetadata = "keyWrapMetadata"; + public const string KeyWrapMetadataName = "name"; + public const string KeyWrapMetadataType = "type"; + public const string KeyWrapMetadataValue = "value"; + public const string KeyWrapMetadataAlgorithm = "algorithm"; + public const string EncryptedInfo = "_ei"; + public const string DataEncryptionKeyRid = "_ek"; + public const string EncryptionFormatVersion = "_ef"; + public const string EncryptedData = "_ed"; + public const string ClientEncryptionKeyId = "clientEncryptionKeyId"; + public const string EncryptionType = "encryptionType"; + public const string EncryptionAlgorithm = "encryptionAlgorithm"; + public const string ClientEncryptionPolicy = "clientEncryptionPolicy"; + + public const string DataMaskingPolicy = "dataMaskingPolicy"; + public const string IsPolicyEnabled = "isPolicyEnabled"; + + // ParitionKey Monitor + public const string EnablePartitionKeyMonitor = "enablePartitionKeyMonitor"; + + // Operation diagnostic logs + public const string Origin = "origin"; + public const string AzureMonitorServiceSpecification = "serviceSpecification"; + public const string DiagnosticLogSpecifications = "logSpecifications"; + public const string DiagnosticLogsName = "name"; + public const string DiagnosticLogsDisplayName = "displayName"; + public const string BlobDuration = "blobDuration"; + + // FederationPolicyOverrideResource + public const string FederationPolicyOverride = "federationPolicyOverride"; + public const string MaxCapacityUnits = "maxCapacityUnits"; + public const string MaxDatabaseAccounts = "maxDatabaseAccounts"; + public const string MaxBindableServicesPercentOfFreeSpace = "maxBindableServicesPercentOfFreeSpace"; + public const string DisabledDatabaseAccountManager = "disabledDatabaseAccountManager"; + public const string EnableBsonSchemaOnNewAccounts = "enableBsonSchemaOnNewAccounts"; + + // Metric Definitions + public const string MetricSpecifications = "metricSpecifications"; + public const string DisplayDescription = "displayDescription"; + public const string AggregationType = "aggregationType"; + public const string LockAggregationType = "lockAggregationType"; + public const string SourceMdmAccount = "sourceMdmAccount"; + public const string SourceMdmNamespace = "sourceMdmNamespace"; + public const string FillGapWithZero = "fillGapWithZero"; + public const string Category = "category"; + public const string ResourceIdOverride = "resourceIdDimensionNameOverride"; + public const string Dimensions = "dimensions"; + public const string InternalName = "internalName"; + public const string IsHidden = "isHidden"; + public const string DefaultDimensionValues = "defaultDimensionValues"; + public const string Availabilities = "availabilities"; + public const string InternalMetricName = "internalMetricName"; + public const string SupportedTimeGrainTypes = "supportedTimeGrainTypes"; + public const string SupportedAggregationTypes = "supportedAggregationTypes"; + + // Metric ID Mapping Dimension names (Multi-Resource Metrics) + public const string MicrosoftSubscriptionId = "Microsoft.subscriptionId"; + public const string MicrosoftResourceGroupName = "Microsoft.resourceGroupName"; + public const string MicrosoftResourceType = "Microsoft.resourceType"; + public const string MicrosoftResourceName = "Microsoft.resourceName"; + public const string MicrosoftResourceId = "Microsoft.resourceId"; + public const string MicrosoftRegionName = "Microsoft.regionName"; + + // IP Range resource + public const string IpRangeFilter = "ipRangeFilter"; + public const string IpRules = "ipRules"; + public const string IpAddressOrRange = "ipAddressOrRange"; + + // Property to check if point in time restore is enabled for a global database account + public const string PitrEnabled = "pitrEnabled"; + public const string PitrSku = "pitrSku"; + public const string ReservedInstanceType = "reservedInstanceType"; + public const string ContinuousBackupTier = "tier"; + public const string EnablePitrMigration = "enablePITRMigration"; + public const string EnableLogstoreHeadStartSequenceVector = "enableLogStoreHeadStartSequenceVector"; + public const string AllowSkippingOpLogFlushInRestore = "allowSkippingOpLogFlushInRestore"; + public const string ContinuousBackupEnabled = "continuousBackupEnabled"; // used in DatabaseAccountHandler as part of database account response + + // Property to allow PITR disabling + public const string AllowPeriodicMigration = "allowPeriodicMigration"; + + // Property to allow migration to analytical store + public const string AllowCollectionMigrationToAnalyticalStore = "allowCollectionMigrationToAnalyticalStore"; + public const string AllowMongoCollectionMigrationToAnalyticalStore = "allowMongoCollectionMigrationToAnalyticalStore"; + + // Property to enable storage analytics + public const string EnableAnalyticalStorage = "enableAnalyticalStorage"; + + // Properties related to Autoscale billing improvements. + public const string EnableAutoscaleThroughputUtilizationReporting = "enableAutoscaleThroughputUtilizationReporting"; // Configuration to report throughput utilization for autoscale billing. + public const string EnablePerRegionAutoscale = "enablePerRegionAutoscale"; //Configuration to enable PerRegion autoscale billing. + public const string EnableThroughputUtilizationPersistence = "enableThroughputUtilizationPersistence"; // configuration to enable throughput utlization persistance for server replica + public const string EnablePerRegionPerPartitionAutoscale = "enablePerRegionPerPartitionAutoscale"; // Property used in RP call to enable/disable the AutoscalePerRegion feature + public const string EnablePerRegionPerPartitionAutoscaleOptIn = "enablePerRegionPerPartitionAutoscaleOptIn"; // config override which will be used to determine if feature can be enabled or not + + //properties to enable MaterializedViews + public const string EnableMaterializedViews = "enableMaterializedViews"; //at DB account level. + public const string EnableOnlyColdStorageContainersInAccountV1 = "enableOnlyColdStorageContainersInAccountV1"; + + // full fidelity change feed (change feed with retention from remote+local storage) enablement + optimizations. + public const string EnableFullFidelityChangeFeed = "enableFullFidelityChangeFeed"; + public const string EnableFFCFWithPITR = "enableFFCFWithPITR"; + public const string DisableAdvanceLSNWhenFirstBatchIsPreempted = "disableAdvanceLSNWhenFirstBatchIsPreempted"; + public const string DisableChangeFeedPKFilteringOptimizations = "disableChangeFeedPKFilteringOptimizations"; + + // Enable API type check + public const string EnableApiTypeCheck = "enableApiTypeCheck"; + public const string EnabledApiTypesOverride = "enabledApiTypesOverride"; + + public const string ForceDisableFailover = "forceDisableFailover"; + public const string EnableAutomaticFailover = "enableAutomaticFailover"; + public const string DisableFailoverPriorityChange = "disableFailoverPriorityChange"; + public const string SkipGracefulFailoverAttempt = "skipGracefulFailoverAttempt"; + public const string ForceUngracefulFailover = "forceUngraceful"; + + // Location resource + public const string IsEnabled = "isenabled"; + public const string FabricUri = "fabricUri"; + public const string ResourcePartitionKey = "resourcePartitionKey"; + public const string CanaryLocationSurffix = "euap"; + public const string IsSubscriptionRegionAccessAllowedForRegular = "isSubscriptionRegionAccessAllowedForRegular"; + public const string IsSubscriptionRegionAccessAllowedForAz = "isSubscriptionRegionAccessAllowedForAz"; + + // Topology Resource + public const string Topology = "topology"; + public const string AdjacencyList = "adjacencyList"; + public const string WriteRegion = "writeRegion"; + public const string GlobalConfigurationNumber = "globalConfigurationNumber"; + public const string WriteStatusRevokedSatelliteRegions = "writeStatusRevokedSatelliteRegions"; + public const string PreviousWriteRegion = "previousWriteRegion"; + public const string NextWriteRegion = "nextWriteRegion"; + public const string ReadStatusRevoked = "readStatusRevoked"; + + // Capabilities Resource + public const string Capabilities = "capabilities"; + public const string DefaultCapabilities = "defaultCapabilities"; + public const string CapabilityVisibilityPolicies = "capabilityVisibilityPolicies"; + public const string NamingServiceSettings = "namingServiceSettings"; + public const string IsEnabledForAll = "isEnabledForAll"; + public const string IsDefault = "isDefault"; + public const string Key = "key"; + public const string IsCapabilityRingFenced = "isCapabilityRingFenced"; + public const string IsEnabledForAllToOptIn = "isEnabledForAllToOptIn"; + public const string TargetedFederationTypes = "targetedFederationTypes"; + + // PolicyStore + public const string ConfigValueByKey = "configValueByKey"; + public const string NameBasedCollectionUri = "nameBasedCollectionUri"; + public const string UsePolicyStore = "usePolicyStore"; + public const string UsePolicyStoreRuntime = "usePolicyStoreRuntime"; + public const string PolicyStoreVersion = "policyStoreVersion"; + + // System store properties + public const string AccountEndpoint = "AccountEndpoint"; + public const string EncryptedAccountKey = "EncryptedAccountKey"; + + // PolicyStoreConnectionInfo + public const string PolicyStoreConnectionInfoNameBasedCollectionUri = "NameBasedCollectionUri"; + + // BillingStoreConnectionInfo + public const string BillingStoreConnectionInfoAccountEndpoint = "AccountEndpoint"; + public const string BillingStoreConnectionInfoEncryptedAccountKey = "EncryptedAccountKey"; + public const string EnableBackupPolicyBilling = "EnableBackupPolicyBilling"; + public const string EnableBackupRedundancyBilling = "EnableBackupRedundancyBilling"; + + // ConfigurationStoreConnectionInfo + public const string ConfigurationStoreConnectionInfoAccountEndpoint = "AccountEndpoint"; + public const string ConfigurationStoreConnectionInfoEncryptedAccountKey = "EncryptedAccountKey"; + public const string ConfigurationStoreConnectionInfoFederationCollectionUri = "FederationCollectionUri"; + public const string ConfigurationStoreConnectionInfoDatabaseAccountCollectionUri = "DatabaseAccountCollectionUri"; + public const string ConfigurationStoreConnectionInfoRegionalCollectionUri = "RegionalCollectionUri"; + + // ConfigurationLevel + public const string ConfigurationLevel = "configurationLevel"; + + // SkipFederationEntityUpdate + public const string SkipFederationEntityUpdate = "skipFederationEntityUpdate"; + + // TargetOnlyNamingService + public const string TargetOnlyNamingService = "targetOnlyNamingService"; + + // Subscription Properties + public const string SubscriptionTenantId = "tenantId"; + public const string SubscriptionLocationPlacementId = "locationPlacementId"; + public const string SubscriptionQuotaId = "quotaId"; + public const string SubscriptionAddionalProperties = "additionalProperties"; + + // Schema resource + public const string Schema = "schema"; + + // PartitionedQueryExecutionInfo + public const string PartitionedQueryExecutionInfoVersion = "partitionedQueryExecutionInfoVersion"; + public const string QueryInfo = "queryInfo"; + public const string QueryRanges = "queryRanges"; + + // Arm resource type + public const string CosmosResourceProvider = "microsoft.documentdb"; + public const string DatabaseAccounts = "databaseaccounts"; + public const string CosmosArmResouceType = CosmosResourceProvider + "/" + DatabaseAccounts; + + // SchemaDiscoveryPolicy + public const string SchemaDiscoveryPolicy = "schemaDiscoveryPolicy"; + public const string SchemaBuilderMode = "mode"; + + // Global database account resource configuration overrides + public const string EnableBsonSchema = "enableBsonSchema"; + public const string EnableAdditiveSchemaForAnalytics = "enableAdditiveSchemaForAnalytics"; + + // Billing + public const string EnableV2Billing = "enableV2Billing"; + public const string CustomProperties = "CustomProperties"; + public const string StreamName = "StreamName"; + public const string ResourceLocation = "ResourceLocation"; + public const string EventTime = "EventTime"; + public const string ResourceTags = "ResourceTags"; + + // PartitionStatistics + public const string Statistics = "statistics"; + public const string SizeInKB = "sizeInKB"; + public const string CompressedSizeInKB = "compressedSizeInKB"; + public const string DocumentCount = "documentCount"; + public const string SampledDistinctPartitionKeyCount = "sampledDistinctPartitionKeyCount"; + public const string PartitionKeys = "partitionKeys"; + + // Partition quota + public const string AccountStorageQuotaInGB = "databaseAccountStorageQuotaInGB"; + + // PartitionKeyStatistic + public const string Percentage = "percentage"; + public const string EnablePartitionKeyStatsOptimization = "enablePartitionKeyStatsOptimization"; + + public const string PartitionKeyDefinitionVersion = "version"; + + // Federation pinning + public const string EnforcePlacementHintConstraintOnPartitionAllocation = "enforcePlacementHintConstraintOnPartitionAllocation"; + public const string CanUsePolicyStore = "canUsePolicyStore"; + + // SubscriptionsQuota resource + public const string MaxDatabaseAccountCount = "maxDatabaseAccountCount"; + public const string MaxRegionsPerGlobalDatabaseAccount = "maxRegionsPerGlobalDatabaseAccount"; + public const string DisableManualFailoverThrottling = "disableManualFailoverThrottling"; + public const string DisableRemoveRegionThrottling = "disableRemoveRegionThrottling"; + public const string AnalyticsStorageAccountCount = "analyticsStorageAccountCount"; + public const string LibrariesFileShareQuotaInGB = "librariesFileShareQuotaInGB"; + + // Policy Overrides + public const string DefaultSubscriptionPolicySet = "defaultSubscriptionPolicySet"; + public const string SubscriptionPolicySetByLocation = "subscriptionPolicySetByLocation"; + public const string PlacementPolicy = "placementPolicy"; + public const string SubscriptionPolicy = "subscriptionPolicy"; + public const string LocationPolicySettings = "locationPolicySettings"; + public const string DefaultLocationPolicySet = "defaultLocationPolicySet"; + public const string LocationPolicySetBySubscriptionKind = "locationPolicySetBySubscriptionKind"; + public const string SubscriptionPolicySettings = "subscriptionPolicySettings"; + public const string CapabilityPolicySettings = "capabilityPolicySettings"; + + // Location Policy + public const string LocationVisibilityPolicy = "locationVisibilityPolicy"; + public const string IsVisible = "isVisible"; + + // Virtual Network Filter/Acls + // Customer Facing + public const string IsVirtualNetworkFilterEnabled = "isVirtualNetworkFilterEnabled"; + + // PerPartitionFailover Flags + // Likely Customer Facing + public const string EnablePerPartitionFailoverBehavior = "enablePerPartitionFailoverBehavior"; + + // Backend + public const string AccountVNETFilterEnabled = "accountVNETFilterEnabled"; + public const string VirtualNetworkArmUrl = "virtualNetworkArmUrl"; + public const string VirtualNetworkResourceEntries = "virtualNetworkResourceEntries"; + public const string VirtualNetworkResourceId = "virtualNetworkResourceId"; + public const string VirtualNetworkResourceIds = "virtualNetworkResourceIds"; + public const string VNetDatabaseAccountEntries = "vNetDatabaseAccountEntry"; + public const string VirtualNetworkTrafficTags = "vnetFilter"; + public const string VNetETag = "etag"; + public const string PrivateEndpointProxyETag = "etag"; + public const string VirtualNetworkRules = "virtualNetworkRules"; + public const string EnabledApiTypes = "EnabledApiTypes"; + public const string VirtualNetworkPrivateIpConfig = "vnetPrivateIps"; + public const string NspProfileProxyResources = "nspProfileProxyResources"; + public const string NspAssociationProxyResource = "nspAssociationProxyResource"; + // Network Security Perimeter is being changed to be available on accounts by default. + // We are deprecating the feature flag to enable it, and instead introducing a feature flag to disable it. + // The enable flag is being kept for now so that management still can enable the feature on older versions of RG/Backend. + public const string EnableNetworkSecurityPerimeter = "enableNetworkSecurityPerimeter"; + public const string DisableNetworkSecurityPerimeter = "disableNetworkSecurityPerimeter"; + public const string EnableConflictResolutionPolicyUpdate = "enableConflictResolutionPolicyUpdate"; + + // VNET/Subnet Resource(Network Resource Provider) + public const string IgnoreMissingVNetServiceEndpoint = "ignoreMissingVNetServiceEndpoint"; + public const string SubnetTrafficTag = "subnetTrafficTag"; + public const string Owner = "owner"; + public const string VNetServiceAssociationLinks = "vNetServiceAssociationLinks"; + public const string VNetTrafficTag = "vNetTrafficTag"; + public const string VirtualNetworkAcled = "virtualNetworkAcled"; + public const string VirtualNetworkResourceGuid = "virtualNetworkResourceGuid"; + public const string VirtualNetworkLocation = "virtualNetworkLocation"; + public const string PrimaryLocations = "primaryLocations"; + public const string AcledSubscriptions = "acledSubscriptions"; + public const string AcledSubnets = "acledSubnets"; + public const string RetryAfter = "retryAfter"; + public const string OperationPollingUri = "operationPollingUri"; + public const string OperationPollingKind = "operationPollingKind"; + public const string PublicNetworkAccess = "publicNetworkAccess"; + public const string UseSubnetDatabaseAccountEntries = "useSubnetDatabaseAccountEntries"; + public const string UseRegionalVNet = "userRegionalVNet"; + + // Auto Migration + public const string EnableFederationDecommission = "enableFederationDecommission2"; + public const string AutoMigrationScheduleIntervalInSeconds = "autoMigrationScheduleIntervalInSeconds2"; + public const string MasterPartitionAutoMigrationProbability = "masterPartitionAutoMigrationProbability2"; + public const string ServerPartitionAutoMigrationProbability = "serverPartitionAutoMigrationProbability2"; + + // Diagnostic Settings + public const string StorageAccountId = "storageAccountId"; + public const string WorkspaceId = "workspaceId"; + public const string EventHubAuthorizationRuleId = "eventHubAuthorizationRuleId"; + public const string Enabled = "enabled"; + public const string Days = "days"; + public const string RetentionPolicy = "retentionPolicy"; + public const string Metrics = "metrics"; + public const string Logs = "logs"; + public const string CategoryGroup = "categoryGroup"; + + // Atp(advanced threat protection) Settings + public const string IsAtpEnabled = "isEnabled"; + + // FullTextQuerySettings for plain text logging + public const string IsFullTextQueryEnabled = "isEnabled"; + + // ResourceLimits + public const string EnableExtendedResourceLimit = "enableExtendedResourceLimit"; + public const string ExtendedResourceNameLimitInBytes = "extendedResourceNameLimitInBytes"; + public const string ExtendedResourceContentLimitInKB = "extendedResourceContentLimitInKB"; + public const string MaxResourceSize = "maxResourceSize"; + public const string MaxBatchRequestBodySize = "maxBatchRequestBodySize"; + public const string MaxResponseMessageSize = "maxResponseMessageSize"; + public const string AnalyzedTermChargeEnabled = "analyzedTermChargeEnabled "; + public const string EnableWriteConflictCharge = "enableWriteConflictCharge"; + public const string ResourceContentBufferThreshold = "resourceContentBufferThreshold"; + public const string EnableExtendedResourceLimitForNewCollections = "enableExtendedResourceLimitForNewCollections"; + public const string DefaultExtendedCollectionChildResourceContentLimitInKB = "defaultExtendedCollectionChildResourceContentLimitInKB"; + public const string MaxScriptInputSize = "maxScriptInputSize"; + public const string MaxBatchTransactionSizeInBytes = "maxBatchTransactionSizeInBytes"; + public const string MaxScriptTransactionSize = "maxScriptTransactionSize"; + public const string ReplicationBatchMaxMessageSizeInBytes = "replicationBatchMaxMessageSizeInBytes"; + public const string TriggeredMasterBackupDuringAccountDelete = "triggeredMasterBackupDuringAccountDelete"; + public const string MaxReadFeedResponseMessageSize = "maxReadFeedResponseMessageSize"; + public const string EnableLargeDocumentSupport = "enableLargeDocumentSupport"; + + // Resource Governance Settings + public const string MaxFeasibleRequestChargeInSeconds = "MaxFeasibleRequestChargeInSeconds"; + public const string ReplicationChargeEnabled = "replicationChargeEnabled"; + + // Multi-Region Strong + public const string BypassMultiRegionStrongVersionCheck = "bypassMultiRegionStrongVersionCheck"; + public const string XPCatchupConfigurationEnabled = "xpCatchupConfigurationEnabled"; + + // LogStore restore + public const string IsRemoteStoreRestoreEnabled = "remoteStoreRestoreEnabled"; + public const string RetentionPeriodInSeconds = "retentionPeriodInSeconds"; + public const string EnableRestoreTillEndOfLogChain = "enableRestoreTillEndOfLogChain"; + + // Remove stale backup blobs + public const string BlobNamePrefix = "blobNamePrefix"; + public const string BlobPartitionLevel = "blobPartitionLevel"; + public const string DryRun = "dryRun"; + public const string UseCustomRetentionPeriod = "UseCustomRetentionPeriod"; + public const string CustomRetentionPeriodInMins = "CustomRetentionPeriodInMins"; + + // Shared throughput offer specific + public const string DisallowOfferOnSharedThroughputCollection = "disallowOfferOnSharedThroughputCollection"; + public const string AllowOnlyPartitionedCollectionsForSharedOffer = "allowOnlyPartitionedCollectionsForSharedThroughputOffer"; + public const string RestrictDatabaseOfferContainerCount = "restrictDatabaseOfferContainerCount"; + public const string MaxSharedOfferDatabaseCount = "maxSharedOfferDatabaseCount"; + public const string MinRUsPerSharedThroughputCollection = "minRUsPerSharedThroughputCollection"; + public const string MaxContainersPerPartition = "maxContainersPerPartition"; + + // Conflict resolution policy + public const string ConflictResolutionPolicy = "conflictResolutionPolicy"; + public const string Mode = "mode"; + public const string ConflictResolutionPath = "conflictResolutionPath"; + public const string ConflictResolutionProcedure = "conflictResolutionProcedure"; + + public const string Progress = "progress"; + public const string ReservedServicesInfo = "reservedServicesInfo"; + + // Update Federation Is Dirty Status Request + public const string RoleInstanceCounts = "RoleInstanceCounts"; + public const string RoleName = "RoleName"; + public const string InstanceCount = "InstanceCount"; + + // Federation Service Extension + public const string ExtensionName = "ExtensionName"; + public const string ExtensionVersion = "ExtensionVersion"; + + // CORS Rules + public const string Cors = "cors"; + public const string AllowedOrigins = "allowedOrigins"; + public const string AllowedMethods = "allowedMethods"; + public const string AllowedHeaders = "allowedHeaders"; + public const string ExposedHeaders = "exposedHeaders"; + public const string MaxAgeInSeconds = "maxAgeInSeconds"; + + // Certificates for SSL authentication + public const string PrimaryClientCertificatePemBytes = "primaryClientCertificatePemBytes"; + public const string SecondaryClientCertificatePemBytes = "secondaryClientCertificatePemBytes"; + + // Adds lsn property to document content + public const string EnableLsnInDocumentContent = "enableLsnInDocumentContent"; + + // Max content per collection In GB + public const string MaxContentPerCollectionInGB = "maxContentPerCollection"; + + // Visibility resource + public const string SkipRepublishConfigFromTargetFederation = "skipRepublishConfigFromTargetFederation"; + public const string MaxDegreeOfParallelismForPublishingFederationKeys = "maxDegreeOfParallelismForPublishingFederationKeys"; + + // Remove federation visibility resource + public const string ValidationOnly = "validationOnly"; + public const string EnforceOrphanServiceCheck = "enforceOrphanServiceCheck"; + public const string ResetPoolCounters = "resetPoolCounters"; + + public const string ProxyName = "proxyName"; + public const string GroupId = "groupId"; + public const string ConnectionDetails = "connectionDetails"; + public const string GroupIds = "groupIds"; + public const string InternalFqdn = "internalFqdn"; + public const string CustomerVisibleFqdns = "customerVisibleFqdns"; + public const string RequiredMembers = "requiredMembers"; + public const string RequiredZoneNames = "requiredZoneNames"; + public const string ManualPrivateLinkServiceConnections = "manualPrivateLinkServiceConnections"; + public const string PrivateLinkServiceConnections = "privateLinkServiceConnections"; + public const string PrivateLinkServiceProxies = "privateLinkServiceProxies"; + public const string RemotePrivateEndpoint = "remotePrivateEndpoint"; + public const string MemberName = "memberName"; + public const string BatchNotifications = "batchNotifications"; + public const string AccountSourceResourceId = "sourceResourceId"; + public const string TargetResourceGroupId = "targetResourceGroupId"; + public const string GroupConnectivityInformation = "groupConnectivityInformation"; + public const string RemotePrivateLinkServiceConnectionState = "remotePrivateLinkServiceConnectionState"; + public const string RemotePrivateEndpointConnection = "remotePrivateEndpointConnection"; + public const string PrivateEndpointConnectionId = "privateEndpointConnectionId"; + public const string ActionsRequired = "actionsRequired"; + public const string RequestMessage = "requestMessage"; + public const string LinkIdentifier = "linkIdentifier"; + public const string PrivateLinkServiceArmRegion = "privateLinkServiceArmRegion"; + public const string PrivateIpAddress = "privateIpAddress"; + public const string PrivateIpConfigGroups = "privateIpConfigGroups"; + public const string IsLastNrpPutRequestManualApprovalWorkflow = "isLastNrpPutRequestManualApprovalWorkflow"; + public const string PrivateLinkServiceConnectionName = "privateLinkServiceConnectionName"; + public const string RedirectMapId = "redirectMapId"; + public const string ImmutableSubscriptionId = "immutableSubscriptionId"; + public const string ImmutableResourceId = "immutableResourceId"; + public const string AccountPrivateEndpointConnectionEnabled = "accountPrivateEndpointConnectionEnabled"; + public const string AccountPrivateEndpointDnsZoneEnabled = "accountPrivateEndpointDnsZoneEnabled"; + public const string PrivateIpConfigs = "privateIpConfigs"; + public const string PrivateEndpoint = "privateEndpoint"; + public const string PrivateLinkServiceConnectionState = "privateLinkServiceConnectionState"; + public const string PrivateEndpointArmUrl = "privateEndpointArmUrl"; + public const string StoragePrivateEndpointConnections = "storagePrivateEndpointConnections"; + public const string PrivateLinkServiceProxyName = "privateLinkServiceProxyName"; + public const string PrivateEndpointConnections = "privateEndpointConnections"; + public const string UpdateIpRangeFilter = "updateIpRangeFilter"; + public const string UpdateVirtualNetworkResources = "updateVirtualNetworkResources"; + public const string UpdatePrivateEndpointConnections = "updatePrivateEndpointConnections"; + public const string ExplicitDnsSettings = "explicitDnsSettings"; + public const string ARecord = "aRecord"; + public const string DnsZoneName = "dnsZoneName"; + public const string ArmSubscriptionId = "armSubscriptionId"; + public const string ChildrenNames = "childrenNames"; + public const string ParentName = "parentName"; + public const string IsActive = "isActive"; + public const string IsRegional = "isRegional"; + public const string MapEntrySize = "mapEntrySize"; + public const string FederationMaps = "federationMaps"; + public const string FederationDns = "federationDns"; + public const string FederationVip = "federationVip"; + public const string Entries = "entries"; + public const string AllowEntryDelete = "allowEntryDelete"; + public const string DeletedFederations = "deletedFederations"; + public const string StartPublicPort = "startPublicPort"; + public const string StartPrivatePort = "startPrivatePort"; + public const string ServiceName = "serviceName"; + public const string PlatformId = "platformId"; + public const string VirtualPortBlockSize = "virtualPortBlockSize"; + public const string LookUpEntries = "lookupEntries"; + public const string RingPublicVipAddress = "ringPublicVipAddress"; + public const string StartInstancePort = "startInstancePort"; + public const string EndInstancePort = "endInstancePort"; + public const string StartVirtualPort = "startVirtualPort"; + public const string EndVirtualPort = "endVirtualPort"; + public const string PublishToNrp = "publishToNrp"; + public const string VnetMapPropagationWaitDurationInMinutes = "vnetMapPropagationWaitDurationInMinutes"; + public const string Map = "map"; + public const string IsSqlEndpointSwapped = "isSqlEndpointSwapped"; + public const string IsSqlEndpointDefaultProvisionedOnCompute = "isSqlEndpointDefaultProvisionedOnCompute"; + public const string ComputeFederationProcess = "computeFederationProcess"; + public const string DatabaseServicesInfo = "DatabaseServicesInfo"; + public const string RedirectMapVersion = "version"; + public const string IsOwnedByExternalProvider = "isOwnedByExternalProvider"; + public const string ConnectionInformation = "connectionInformation"; + public const string CrossSubRegionMigrationInProgress = "CrossSubRegionMigrationInProgress"; + public const string AzMigrationInProgress = "AzMigrationInProgress"; + public const string BypassAzMigrationDedicatedStorageAccountRedundancyCheck = "BypassAzMigrationDedicatedStorageAccountRedundancyCheck"; + public const string StorageAccountMigration = "storageAccountMigration"; + + // Data Plane Operation Policy + public const string DisableKeyBasedMetadataWriteAccess = "disableKeyBasedMetadataWriteAccess"; + public const string DisableKeyBasedMetadataReadAccess = "disableKeyBasedMetadataReadAccess"; + + //ControlPlane Metric and Diagnostic logs + public const int DiagnosticLogPropertyLengthLimit = 2000; + public const string EventStartSuffix = "Start"; + public const string EventCompleteSuffix = "Complete"; + public const string AddRegionEventGroupName = "RegionAdd"; + public const string RemoveRegionEventGroupName = "RegionRemove"; + public const string DeleteAccountEventGroupName = "AccountDelete"; + public const string RegionFailoverEventGroupName = "RegionFailover"; + public const string CreateAccountEventGroupName = "AccountCreate"; + public const string UpdateAccountEventGroupName = "AccountUpdate"; + public const string UpdateAccountBackUpPolicyEventGroupName = "AccountBackUpPolicyUpdate"; + public const string DeleteVNETEventGroupName = "VirtualNetworkDelete"; + public const string UpdateDiagnosticLogEventGroupName = "DiagnosticLogUpdate"; + public const string SqlRoleDefinitionCreate = "SqlRoleDefinitionCreate"; + public const string SqlRoleDefinitionReplace = "SqlRoleDefinitionReplace"; + public const string SqlRoleDefinitionDelete = "SqlRoleDefinitionDelete"; + public const string SqlRoleAssignmentCreate = "SqlRoleAssignmentCreate"; + public const string SqlRoleAssignmentReplace = "SqlRoleAssignmentReplace"; + public const string SqlRoleAssignmentDelete = "SqlRoleAssignmentDelete"; + + public const string MongoRoleDefinitionCreate = "MongoRoleDefinitionCreate"; + public const string Replace = "AuthPolicyElementReplace"; + public const string MongoRoleDefinitionDelete = "MongoRoleDefinitionDelete"; + + public const string CassandraRoleDefinitionCreate = "CassandraRoleDefinitionCreate"; + public const string CassandraRoleDefinitionReplace = "CassandraRoleDefinitionReplace"; + public const string CassandraRoleDefinitionDelete = "CassandraRoleDefinitionDelete"; + + // Data plane RBAC settings + public const string AllowExtendedRbacActions = "AllowExtendedRbacActions"; + + // Diagnostics settings + public const string EnableControlPlaneRequestsTrace = "enableControlPlaneRequestsTrace"; + public const string AtpEnableControlPlaneRequestsTrace = "atpEnableControlPlaneRequestsTrace"; + + public const string OwnerResourceId = "ownerResourceId"; + + public const string ParentResourceId = "parentResourceId"; + + //Notebook settings + public const string NotebookStorageAllocationInfo = "notebookStorageAllocationInfo"; + + // Spark settings + public const string SparkStorageAllocationInfo = "sparkStorageAllocationInfo"; + + // Throughput split settings + public const string ThroughputSplitInfo = "ThroughputSplitInfo"; + + //CosmosStoreBlobProperties + public const string CacheControl = "cacheControl"; + public const string ContentDisposition = "contentDisposition"; + public const string ContentEncoding = "contentEncoding"; + public const string ContentLanguage = "contentLanguage"; + public const string ContentMD5 = "contentMD5"; + public const string Length = "length"; + + //CosmosBlob + public const string Metadata = "metadata"; + public const string BlobProperties = "blobProperties"; + + // ARM Certificates + public const string ClientCertificates = "clientCertificates"; + public const string Thumbprint = "thumbprint"; + public const string NotBefore = "notBefore"; + public const string NotAfter = "notAfter"; + public const string Certificate = "certificate"; + + public const string IsDiskReceiverEnabled = "isDiskReceiverEnabled"; + + // Service Association Link + public const string LinkedResourceType = "linkedResourceType"; + public const string Link = "link"; + public const string AllowDelete = "allowDelete"; + public const string Details = "Details"; + public const string ServiceAssociationLinkETag = "etag"; + public const string PrimaryContextId = "primaryContextId"; + public const string SecondaryContextId = "secondaryContextId"; + public const string PrimaryContextRequestId = "primaryContextRequestId"; + public const string SecondaryContextRequestId = "secondaryContextRequestId"; + + // GremlinV2 Properties. + public const string GremlinProperties = "gremlinProperties"; + public const string GraphApiServerStartupConfigFileName = "graphapi.startupConfig"; + + // Mongo Properties + public const string GlobalMongoProperties = "globalMongoProperties"; + public const string ApiProperties = "apiProperties"; + public const string Disable16MBCapabilityChecks = "disable16MBCapabilityChecks"; + + // AAD Authentication + public const string TrustedAadTenants = "trustedAadTenants"; + public const string NetworkAclBypass = "networkAclBypass"; + public const string NetworkAclBypassResourceIds = "networkAclBypassResourceIds"; + public const string DisableLocalAuth = "disableLocalAuth"; + + //Logging properties + public const string DiagnosticLogSettings = "diagnosticLogSettings"; + public const string EnableFullTextQuery = "enableFullTextQuery"; + + // Restorable database accounts + public const string CreationTime = "creationTime"; + public const string DeletionTime = "deletionTime"; + public const string OldestRestorableTime = "oldestRestorableTime"; + public const string AccountName = "accountName"; + public const string ApiType = "apiType"; + public const string RestorableLocations = "restorableLocations"; + + public const string CreationTimeInUtc = "creationTimeInUtc"; + public const string DeletionTimeInUtc = "deletionTimeInUtc"; + public const string OldestRestorableTimeInUtc = "oldestRestorableTimeInUtc"; + + // Private endpoint map management + public const string Telemetry = "telemetry"; + public const string DisabledTime = "disabledTime"; + public const string MapVersionBeforeCreation = "mapVersionBeforeCreation"; + public const string MapVersionBeforeDisabled = "mapVersionBeforeDisabled"; + public const string MapVersionBeforeDeletion = "mapVersionBeforeDeletion"; + + // SystemData + public const string SystemData = "systemData"; + + // DeletedGlobalDatabaseAccount resource + public const string DeletedRegionalDatabaseAccounts = "regionalDeletedDatabaseAccounts"; + // Compute MongoClient for RP + public const string DisableMongoClientWorkflows = "disableMongoClientWorkflows"; + + // Enable customer managed key + public const string ByokStatus = "byokStatus"; + public const string ByokConfig = "byokConfig"; + public const string EnableBYOKOnExistingCollections = "enableBYOKOnExistingCollections"; + public const string ShouldEnforceCmkDocumentIdRequirements = "shouldEnforceCmkDocumentIdRequirements"; + public const string DisableByokReEncryptor = "disableByokReEncryptor"; + public const string DataEncryptionState = "dataEncryptionState"; + public const string HoboVersion = "hoboVersion"; + + // LocationResource + public const string DeploymentBatch = "deploymentBatch"; + public const string HealthServiceSubscriptionId = "healthServiceSubscriptionId"; + public const string FederationActiveDirectoryTenantId = "federationActiveDirectoryTenantId"; + public const string FederationActiveDirectoryClientId = "federationActiveDirectoryClientId"; + public const string Longitude = "longitude"; + public const string Latitude = "latitude"; + public const string ShortId = "shortId"; + public const string PublicName = "publicName"; + public const string LongName = "longName"; + public const string ServicingLocationPublicName = "servicingLocationPublicName"; + public const string HealthServiceName = "healthServiceName"; + public const string SupportsAvailabilityZone = "supportsAvailabilityZone"; + public const string AvailabilityZonesReady = "availabilityZonesReady"; + public const string ActiveSubRegionId = "activeSubRegionId"; + public const string ActiveAvailabilityZoneSubRegionId = "activeAvailabilityZoneSubRegionId"; + public const string IsResidencyRestricted = "isResidencyRestricted"; + public const string RegionalRPLocationForBuildoutStoreFailover = "regionalRPLocationForBuildoutStoreFailover"; + public const string ManagementStoreName = "managementStoreName"; + public const string MgmtStoreSubscriptionId = "mgmtStoreSubscriptionId"; + public const string MgmtStoreResourceGroup = "mgmtStoreResourceGroup"; + public const string DisallowedSubscriptionOfferKinds = "disallowedSubscriptionOfferKinds"; + + // This is read by Compute. + public const string EnablePartitionLevelFailover = "enablePartitionLevelFailover"; + // This is read by Backend. + public const string EnablePerPartitionAutomaticFailover = "enablePerPartitionAutomaticFailover"; + public const string EnableFailoverManager = "enableFailoverManager"; + + // Capacity settings properties + public const string Capacity = "capacity"; + public const string TotalThroughputLimit = "totalThroughputLimit"; + public const string TotalThroughputLimitBackendName = "currentThroughputCap"; + + // Mongo Partial Unique Indexes properties + public const string EnableConditionalUniqueIndex = "enableConditionalUniqueIndex"; + public const string EnableUniqueIndexReIndexing = "enableUniqueIndexReIndexing"; + public const string GenerateUniqueIndexTermsIfUniqueKeyPolicyDiffer = "generateUniqueIndexTermsIfUniqueKeyPolicyDiffer"; + public const string EnableUseLatestCollectionContent = "enableUseLatestCollectionContent"; + public const string AllowUniqueIndexModificationOnMaster = "allowUniqueIndexModificationOnMaster"; + public const string AllowUniqueIndexModificationWhenDataExists = "allowUniqueIndexModificationWhenDataExists"; + public const string EnableRenamingUniqueIndexColumns = "enableRenamingUniqueIndexColumns"; + + // UpgradeControlRule + public const string RuleId = "ruleId"; + public const string RuleType = "ruleType"; + public const string RuleScope = "ruleScope"; + public const string ActivePeriod = "activePeriod"; + public const string Justification = "justification"; + public const string AdditionalProperties = "additionalProperties"; + + // Purview-related properties + public const string PurviewEnabled = "purviewEnabled"; + public const string AutoAuthPolicyFullPullScheduleIntervalInSeconds = "autoAuthPolicyFullPullScheduleIntervalInSeconds"; + public const int DefaultFullPullScheduleIntervalInSeconds = 7200; + + // TLS + // New values for Self-Service Tls feature. + public const string MinimalTlsVersion = "minimumAllowedTLSProtocol"; + public const string MinimalTlsVersionDisplay = "minimalTlsVersion"; + // Old deprecated value. + public const string MinimumTransportLayerSecurityLevel = "minimumTransportLayerSecurityLevel"; + + // LogStore Storage Account Rollover Timestamp + public const string EarliestNextLogStoreStorageAccountKeyRolloverTime = "earliestNextLogStoreStorageAccountKeyRolloverTime"; + + // RowRewriter properties + public const string RowRewriterIdleIntervalInSeconds = "rowRewriterIdleIntervalInSeconds"; + public const string DisableRowRewriter = "disableRowRewriter"; + + // Client Configuration Properties + public const string ClientTelemetryConfiguration = "clientTelemetryConfiguration"; + public const string ClientTelemetryEnabled = "isEnabled"; + public const string ClientTelemetryEndpoint = "endpoint"; + public const string ClientConfigApiRefreshIntervalInMinutes = "refreshIntervalInMinutes"; + public const string EnableClientTelemetry = "enableClientTelemetry"; + + // Throughput Pool Properties + public const string ThroughputPoolInstanceId = "throughputPoolInstanceId"; + public const string ThroughputPoolId = "throughputPoolId"; + public const string ThroughputPoolName = "throughputPoolName"; + public const string ThroughputPool = "throughputPool"; + public const string ThroughputPools = "throughputPools"; + public const string ThroughputPoolAccountLocation = "accountArmLocation"; + public const string ThroughputPoolAccountInstanceId = "accountInstanceId"; + public const string ThroughputPoolResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DocumentDB/throughputPools/{3}"; + public const string ThroughputPoolAccountResourceIdentifier = "accountResourceIdentifier"; + + // Migration feature flag + public const string UseOptimizedLockAcquisitionStepsDuringMigratePartition = "useOptimizedLockAcquisitionStepsDuringMigratePartition"; + + public static class FederationOperations + { + public const string IsCapOperation = "isCapOperation"; + } + } + + public static class FederationCapActions + { + public const string Cap = "Cap"; + public const string Uncap = "Uncap"; + } + + public static class AzCapabilities + { + public const string AzEnabled = "AzEnabled"; + public const string HybridAzAllocationEnabled = "HybridAzAllocationEnabled"; + } + + public static class InAccountUnDeleteNotAllowedReasons + { + // Database UnDelete Failure + public const string DatabaseLive = "Database already exists. Only deleted resources can be restored within same account."; + public const string DatabaseWithSameNameLive = "Database with same name already exist as live database."; + + // Collection UnDelete Failure + public const string DatabaseDoesNotExist = "Could not find the database associated with the collection. Please restore the database before restoring the collection."; + public const string DatabaseWithSameNameExist = "Could not find the database associated with the collection. Another database with same name exist"; + public const string CollectionLive = "Collection already exists. Only deleted resources can be restored within same account."; + public const string CollectionWithSamenNameLive = "Collection with same name already exist as live collection."; + public const string SharedCollectionNotAllowed = "Individual shared database collections restore is not supported. Please restore shared database to restore its collections that share the throughput."; + } + + public static class DocumentResourceExtendedProperties + { + public const string Tags = "Tags"; + public const string ResourceGroupName = "ResourceGroupName"; + public const string SkipDNSUpdateOnFailureDuringFailover = "SkipDNSUpdateOnFailureDuringFailover"; + } + + public static class SnapshotProperties + { + public const string GeoLinkToPKRangeRid = "geoLinkIdToPKRangeRid"; + public const string PartitionKeyRangeResourceIds = "partitionKeyRangeResourceIds"; + public const string PartitionKeyRanges = "partitionKeyRanges"; + public const string ClientEncryptionKeyResources = "clientEncryptionKeyResources"; + public const string CollectionContent = "collectionContent"; + public const string DatabaseContent = "databaseContent"; + public const string SnapshotTimestamp = "snapshotTimestamp"; + public const string EventTimestamp = "eventTimestamp"; + public const string DataDirectories = "dataDirectories"; + public const string MetadataDirectory = "metadataDirectory"; + public const string OperationType = "operationType"; + public const string RestoredPartitionInfo = "restoredPartitionInfo"; + public const string CollectionToSnapshotMap = "collectionToSnapshotMap"; + public const string PartitionKeyRangeList = "partitionKeyRangeList"; + public const string DocumentCollection = "documentCollection"; + public const string Database = "database"; + public const string OfferContent = "offerContent"; + public const string Container = "container"; + public const string Table = "table"; + public const string Keyspace = "keyspace"; + public const string LSN = "lsn"; + public const string IsMasterResourcesDeletionPending = "isMasterResourcesDeletionPending"; + public const string StorageAccountUris = "storageAccountUris"; + } + + public static class RestoreMetadataResourceProperties + { + // RestoreMetadata resource + public const string RId = "_rid"; + public const string LSN = "lsn"; + public const string CollectionDeletionTimestamp = "_ts"; + public const string DatabaseName = "databaseName"; + public const string CollectionName = "collectionName"; + public const string CollectionResourceId = "collectionResourceId"; + public const string PartitionKeyRangeContent = "partitionKeyRangeContent"; + public const string CollectionContent = "collectionContent"; + public const string OfferContent = "offerContent"; + public const string CollectionSecurityIdentifier = "collectionSecurityIdentifier"; + public const string CollectionCreationTimestamp = "creationTimestamp"; + public const string RemoteStoreType = "remoteStorageType"; + } + + public static class CollectionRestoreParamsProperties + { + public const string Version = "Version"; + public const string SourcePartitionKeyRangeId = "SourcePartitionKeyRangeId"; + public const string SourcePartitionKeyRangeRid = "SourcePartitionKeyRangeRid"; + public const string SourceSecurityIdentifier = "SourceSecurityId"; + public const string RestorePointInTime = "RestorePointInTime"; + public const string PartitionCount = "PartitionCount"; + public const string RestoreState = "RestoreState"; + } + + public static class InternalIndexingProperties + { + public const string PropertyName = "internalIndexingProperties"; + public const string LogicalIndexVersion = "logicalIndexVersion"; + public const string IndexEncodingOptions = "indexEncodingOptions"; + public const string EnableIndexingFullFidelity = "enableIndexingFullFidelity"; + public const string IndexUniquifierId = "indexUniquifierId"; + public const string CellExpiryIndexingMethod = "cellExpiryIndexingMethod"; + public const string EnableIndexingEffectivePartitionKey = "enableIndexingEffectivePartitionKey"; + public static class UnifiedIndexInternalMetaData + { + public const string PropertyName = "unifiedIndexInternalMetaData"; + public const string CurrentAssignedPrefix = "currentActiveAssignedPrefix"; + public const string LastPrefixUsed = "lastPrefixUsed"; + public const string CurrentPrefixSizeInBytes = "nCurrentPrefixSizeInBytes"; + public const string NumOfPrefixesAssignedSoFar = "numofPrefixesAssignedSoFar"; + public const string IndexSlotAssigned = "nIndexSlotAssigned"; + } + } + + public static class GatewayTransactionMetadata + { + public const string GatewayTransactionId = "gatewayTransactionId"; + public const string TelemetryTimestamp = "telemetryTimestamp"; + } + + public static class InternalStoreProperties + { + public const string PropertyName = "internalStoreProperties"; + public const string EnableBinaryEncodingOfContent = "enableBinaryEncodingOfContent"; + } + + public static class TypeSystemPolicy + { + public const string PropertyName = "typeSystemPolicy"; + public const string TypeSystem = "typeSystem"; + public const string CosmosCore = "CosmosCore"; + public const string Cql = "Cql"; + public const string Bson = "Bson"; + } + + public static class UpgradeTypes + { + public const string ClusterManifest = "Fabric"; + public const string Package = "Package"; + public const string Application = "App"; + public const string GrowShrink = "GrowShrink"; + } + + public static class TracesConstants + { + // Monitoring properties + public static readonly string TraceContainerName = "trace"; + } + + public static class EncryptionScopeProperties + { + public const string EncryptionScopeId = "encryptionScopeId"; + public const string EncryptionScope = "encryptionScope"; + public const string Name = "name"; + public const string ManagedServiceIdentityInfoV2 = "managedServiceIdentityInfoV2"; + public const string CMKMetadataList = "cmkMetadataList"; + public const string CollectionFanoutCompleted = "collectionFanoutCompleted"; + + public static class MsiProperties + { + public const string Type = "type"; + public const string MsiIdentityUrl = "msiIdentityUrl"; + public const string InternalId = "internalId"; + public const string ImplicitIdentity = "implicitIdentity"; + public const string ExplicitIdentities = "explicitIdentities"; + public const string DelegatedIdentities = "delegatedIdentities"; + + public static class DelegatedIdentityProperties + { + public const string SourceInternalId = "sourceInternalId"; + public const string SourceResourceId = "sourceResourceId"; + public const string SourceTenantId = "sourceTenantId"; + public const string SourceGeoLocation = "sourceGeoLocation"; + public const string DelegationId = "delegationId"; + public const string DelegationUrl = "delegationUrl"; + public const string UpdateAction = "updateAction"; + public const string WildcardAction = "wildcardAction"; + } + + public static class IdentityProperties + { + public const string ClientId = "clientId"; + public const string ClientSecretEncrypted = "clientSecretEncrypted"; + public const string ClientSecretUrl = "clientSecretUrl"; + public const string TenantId = "tenantId"; + public const string ObjectId = "objectId"; + public const string ResourceId = "resourceId"; + public const string NotBefore = "notBefore"; + public const string NotAfter = "notAfter"; + public const string RenewAfter = "renewAfter"; + public const string CannotRenewAfter = "cannotRenewAfter"; + public const string UpdateAction = "updateAction"; + } + } + } + + public static class StorageKeyManagementProperties + { + public const string StorageAccountSubscriptionId = "storageAccountSubscriptionId"; + public const string StorageAccountResourceGroup = "storageAccountResourceGroup"; + public const string StorageAccountName = "storageAccountName"; + public const string StorageAccountUri = "storageAccountUri"; + public const string StorageAccountPrimaryKeyInUse = "storageAccountPrimaryKeyInUse"; + public const string StorageAccountSecondaryKeyInUse = "storageAccountSecondaryKeyInUse"; + public const string StorageAccountPrimaryKey = "storageAccountPrimaryKey"; + public const string StorageAccountSecondaryKey = "storageAccountSecondaryKey"; + public const string StorageAccountType = "storageAccountType"; + public const string ForceRefresh = "forceRefresh"; + public const string Permissions = "permissions"; + public const string CurrentAccountSasToken = "currentAccountSasToken"; + public const string KeyToSign = "keyToSign"; + public const string AccountSasToken = "accountSasToken"; + public const string ExpiryTime = "expiryTime"; + public const string ListAccountSasRequestServices = "bqtf"; + public const string ListAccountSasRequestResourceTypes = "sco"; + public const string DefaultAccountSasPermissions = "rwdlacup"; + public const string DefaultReadAccountSasPermissions = "rl"; + public const string SasSeparator = "?"; + + // The Storage Management API uses these names for storage account system, primary and secondary keys/sas tokens. + public const string Key1Name = "key1"; + public const string Key2Name = "key2"; + public const string SystemKeyName = "system"; + + // Config hooks + public const string EnableStorageAccountKeyFetch = "enableStorageAccountKeyFetch"; + public const string CachedStorageAccountKeyRefreshIntervalInHours = "cachedStorageAccountKeyRefreshIntervalInHours"; + public const string StorageKeyManagementClientRequestTimeoutInSeconds = "storageKeyManagementClientRequestTimeoutInSeconds"; + public const string StorageKeyManagementAADAuthRetryIntervalInSeconds = "storageKeyManagementAADAuthRetryIntervalInSeconds"; + public const string StorageKeyManagementAADAuthRetryCount = "storageKeyManagementAADAuthRetryCount"; + public const string StorageAccountKeyCacheExpirationIntervalInHours = "storageAccountKeyCacheExpirationIntervalInHours"; + public const string StorageAccountKeyRequestTimeoutInSeconds = "storageAccountKeyRequestTimeoutInSeconds"; + public const string StorageServiceUrlSuffix = "storageServiceUrlSuffix"; + public const string AzureResourceManagerEndpoint = "azureResourceManagerEndpoint"; + public const string StorageSasManagementClientRequestTimeoutInSeconds = "storageSasManagementClientRequestTimeoutInSeconds"; + + public const string FederationAzureActiveDirectoryEndpoint = "FederationAzureActiveDirectoryEndpoint"; + public const string FederationAzureActiveDirectoryClientId = "FederationAzureActiveDirectoryClientId"; + public const string FederationAzureActiveDirectoryTenantId = "FederationAzureActiveDirectoryTenantId"; + public const string FederationToAadCertDsmsSourceLocation = "FederationToAadCertDsmsSourceLocation"; + public const string MasterFederationId = "masterFederationId"; + public const string RegionalDatabaseAccountName = "regionalDatabaseAccountName"; + + // Account sas related configuration properties + public const string SystemSasValidityInHours = "systemSasValidityInHours"; + public const string PrimaryOrSecondaryKeyBasedSasValidityInHours = "primaryOrSecondaryKeyBasedSasValidityInHours"; + public const string CacheSystemSasExpiryInHours = "cacheSystemSasExpiryInHours"; + public const string CachePrimaryOrSecondaryKeyBasedSasExpiryInHours = "cachePrimaryOrSecondaryKeyBasedSasExpiryInHours"; + public const string SasStartTimeSubtractionIntervalInMinutes = "sasStartTimeSubtractionIntervalInMinutes"; + public const string AlwaysReturnKey1BasedSas = "alwaysReturnKey1BasedSas"; + public const string CacheExpirySubtractionTimeInMinutes = "cacheExpirySubtractionTimeInMinutes"; + public const string EnableMasterSideAuthTokenCaching = "enableMasterSideAuthTokenCaching"; + public const string EnableSasRequestRoutingToMasterFederation = "enableSasRequestRoutingToMasterFederation"; + public const string EnableSasTokenLogging = "enableSasTokenLogging"; + public const string AzureStorageAuthMode = "azureStorageAuthMode"; + } + + public static class VNetServiceAssociationLinkProperties + { + public const string SubnetArmUrl = "subnetArmUrl"; + public const string PrimaryContextRequestId = "primaryContextRequestId"; + public const string SecondaryContextRequestId = "secondaryContextRequestId"; + public const string PrimaryContextId = "primaryContextId"; + public const string SecondaryContextId = "secondaryContextId"; + } + + public static class SystemSubscriptionUsageType + { + public const string SMS = "sms"; + public const string CassandraConnectorStorage = "cassandraconnectorstorage"; + public const string NotebooksStorage = "notebooksstorage"; + public const string AnalyticsStorage = "analyticsstorage"; + public const string SparkStorage = "sparkstorage"; + } + + public static class SystemSubscriptionProperties + { + public const string SystemSubscriptionAction = "systemSubscriptionAction"; + public const string SubscriptionUsageKind = "subscriptionUsageKind"; + } + + public static class ConnectorOfferKind + { + public const string Cassandra = "cassandra"; + } + + public static class ConnectorMetadataAccountNamePrefix + { + public const string CassandraConnectorMetadataAccountNamePrefix = "ccxmeta"; + } + + public static class ConnectorOfferName + { + public const string Small = "small"; + } + + public static class AnalyticsStorageAccountProperties + { + public const string AddStorageServices = "AddStorageServices"; + public const string ResourceGroupName = "AnalyticsStorageAccountRG"; + + // BlobStorageAttributes for Storage Analytics + public const string IsDeletedProperty = "IsDeleted"; + public const string DeletedTimeStampProperty = "DeletedTimeStamp"; + + // Analytics Storage Properties (It is a contract with BE, need to be kept in sync with StreamManager2.h/.cpp) + public const string PartitionedParQuetSuffix = "Partitioned.Parquet"; + public const string CosmosSuffix = "Cosmos"; + public const string RootMetaDataSuffix = "RootMetadata"; + public const string PartitionedPreffix = "Partitioned"; + public const string ParquetFileExtension = "Parquet"; + public const string CompressionType = "snappy"; + public const string RootFileName = "Root"; + public const string MetadataExtension = "Metadata"; + public const string InvalidationFileExtension = "Invalidation"; + public const string InvalidationManifestFileExtension = "InvalidationManifest"; + public const string MergedInvalidationFileExtension = "MergedInvalidation"; + public const string SnapshotFileName = "Snapshot"; + + public const string MetadataBlobFileNameSuffix = "Root.Metadata"; + } + + public static class BackupConstants + { + public const int BackupDisabled = -1; + public const int DefaultBackupIntervalInMinutes = 240; + public const int DefaultBackupRetentionIntervalInHours = 8; + public const int LegacyDefaultBackupRetentionIntervalInHours = 24; + + public const int PitrDefaultBackupIntervalInHours = 168; // Weekly full backups + public const int PitrDefaultBackupRetentionIntervalInDays = 30; + public const int PitrBasicDefaultBackupRetentionIntervalInDays = 7; + + public const int DisableBackupHoldFeature = -1; + public const string BackupHoldIndefinite = "0"; + + public const string ServerBackupContainerIdentifier = "-s-"; + public const string MasterBackupContainerIdentifier = "-m-"; + public const string DummyBackupContainerIdentifier = "-d-"; // Used for NoEdb Restore + + public const int ShortenedPartitionIdLengthInContainerName = 19; + + public const int MinBackupIntervalInMinutes = 60; + public const int MaxBackupIntervalInMinutes = 1440; + + public const int MinBackupRetentionIntervalInHours = 8; + public const int MaxBackupRetentionIntervalInHours = 720; + + public const int InvalidPeriodicBackupInterval = -1; + public const int InvalidPeriodicBackupRetention = -1; + + public const string BackupEndTimestamp = "backupEndTimestamp"; + } + + public static class KeyVaultProperties + { + public const string KeyVaultKeyUri = "keyVaultKeyUri"; + public const string WrappedDek = "wrappedDek"; + public const string EnableByok = "enableByok"; + public const string KeyVaultKeyUriVersion = "keyVaultKeyUriVersion"; + public const string DataEncryptionKeyStatus = "dataEncryptionKeyStatus"; + public const string DataEncryptionKeyRequestOperation = "dataEncryptionKeyRequestOperation"; + public const string KeyVaultUnwrapErrorSubStatusCode = "keyVaultUnwrapErrorSubStatusCode"; + public const string KeyVaultUnwrapError = "keyVaultUnwrapError"; + public const string CustomerManagedKeyStatus = "customerManagedKeyStatus"; + } + + public static class ManagedServiceIdentityProperties + { + public const string MsiClientId = "msiClientId"; + public const string MsiClientSecretEncrypted = "msiClientSecretEncrypted"; + public const string MsiCertRenewAfter = "msiCertRenewAfter"; + public const string MsiTenantId = "msiTenantId"; + + public const string AssignUserAssignedIdentity = "assignUserAssignedIdentity"; + public const string UnassignUserAssignedIdentity = "unassignUserAssignedIdentity"; + + public const string AssignSourceDelegation = "assignSourceDelegation"; + public const string UnassignSourceDelegation = "unassignSourceDelegation"; + + public const string WildcardEnabled = "wildcardEnabled"; + public const string WildcardDisabled = "wildcardDisabled"; + + public const string FederatedClientId = "&FederatedClientId="; + public const string SourceInternalId = "&SourceInternalId="; + } + + public static class LogStoreConstants + { + public const int BasedOnSubscription = 0; + public const int EnsureOperationLogsFlushedTimeoutTimeInMinutes = 60; + public const int CrossRegionRestoreOperationLogsFlushTimeoutTimeInMinutes = 15; + + // StreamStandard => 0x0004 = 4 + public const int PreferredLogStoreMetadataStorageKind = 4; + + // Default timeout value of polling operation WaitForStorageKeyAccessOperation + public const double TimeoutDurationInMinutes = 60.0; + + // It needs to be in sync with bancked config for operation logs flush interval, which is currently 100s + public const int EnsureOperationLogsPauseTimeInSeconds = 200; + + //Blob metadata + public const string PartitionKeyRangeRid = "PartitionKeyRangeRid"; + public const string CollectionLLSN = "CollectionLLSN"; + public const string CollectionGLSN = "CollectionGLSN"; + public const string IsValidTimeStamp = "IsValidTimeStamp"; + public const string CollectionTS = "CollectionTS"; + public const string CollectionInstanceId = "CollectionInstanceId"; + } + + public static class RestoreConstants + { + public const int ListBlobMaxResults = 1000; + public const int ListBlobRetryDeltaBackoffInSeconds = 30; + public const int ListBlobRetryMaxAttempts = 5; + + public const int MaxRetryCount = 3; + public const int RetryDelayInSec = 20; + + public const int RestorableDatabaseAccountUriLength = 9; + public const int DatabaseRequestUriLength = 11; + public const int ContainerRequestUriLength = 13; + } + + public static class SubscriptionsQuotaConstants + { + // based on doc: https://docs.microsoft.com/en-us/azure/cosmos-db/concepts-limits#control-plane-operations + public const int DefaultMaxDatabaseAccountCount = 50; + public const int DefaultMaxRegionsPerGlobalDatabaseAccount = 50; + } + + public static class OperationProgressConstants + { + public const string IsProgressReportingSupported = "IsProgressReportingSupported"; + public const string ProgressPercentage = "ProgressPercentage"; + } + + public static class PolicyConstants + { + public const string PolicyType = "policytype"; + public const string BalancingThreshold = "balancingThreshold"; + public const string TriggerThreshold = "triggerThreshold"; + public const string MetricId = "metricId"; + public const string MetricValue = "metricValue"; + public const string MetricWeight = "metricWeight"; + public const string GlobalPolicyPartitionKey = "global"; + public const string Policies = "policies"; + public const string FederationListSortedByUsageScore = "federationListSortedByUsageScore"; + public const string ServiceAllocationOperationType = "serviceAllocationOperationType"; + public const string MaxAllowedPartitionCount = "maxAllowedPartitionCount"; + public const string DisAllowedSubscriptionOfferKinds = "disAllowedSubscriptionOfferKinds"; + public const string NumberOfFederationsToRandomize = "numberOfFederationsToRandomize"; + public const string RegionAccessTypes = "regionAccessTypes"; + public const string RegionAccessType = "regionAccessType"; + } + + public static class SystemStoreConstants + { + public const int DefaultBackupIntervalInMinute = 60; + public const int SMSDefaultBackupIntervalInMinute = 30; + public const int DefaultBackupRetentionInHour = 720; + public const string ResourceGroupSuffix = "-rg"; + public const string IsDataTransferStateStoreAccount = "IsDataTransferStateStoreAccount"; + } + + public static class TransportControlCommandOperations + { + public const string DeactivateOutputQueue = "deactivateOutputQueue"; + public const string ActivateOutputQueue = "activateOutputQueue"; + } + + public static class RetryConstants + { + public const int DisableOverride = -1; + } + + public static class DedicatedStorageAccountFeatures + { + public const string StorageAnalytics = "StorageAnalytics"; + public const string MaterializedViews = "MaterializedViews"; + public const string PITR = "Continuous mode backup policy (PITR)"; + public const string FullFidelityChangeFeed = "FullFidelityChangeFeed"; + } + + public static class StorageAccountMigrationConstants + { + public const string MigrationFailedDetailedReason = "migrationFailedDetailedReason"; + public const string MigrationFailedReason = "migrationFailedReason"; + public const string MigrationStatus = "migrationStatus"; + public const string TargetSkuName = "targetSkuName"; + } + + public static class GraphApiConstants + { + public const string ServerStartupConfigV1 = "gremlin-server-azurecosmos-configuration.yaml"; + public const string ServerStartupConfigV2 = "gremlin-server-azurecosmos-configuration-v2.yaml"; + public const string EnableFEHealthIntegration = "enableFEHealthIntegration"; + public const string GraphConfigPrefix = "graphapi."; + } + + public static class ChangeFeedWireFormatVersions + { + // New wire format that separates document content, metadata and previousImage. + // ConflictResolvedTimestamp(crts) exposed in this version. + public static string SeparateMetadataWithCrts = "2021-09-15"; + } + + public static class BatchApplyResourceProperties + { + public const string BatchApplyOperations = "operations"; + } + + public static class ApiSpecificNames + { + public static string SqlDatabase = "Database"; + public static string SqlContainer = "Container"; + public static string MongoDatabase = "Database"; + public static string MongoCollection = "Collection"; + public static string GremlinDatabase = "GremlinDatabase"; + public static string GremlinGraph = "Graph"; + public static string CassandraKeyspace = "Keyspace"; + public static string CassandraTable = "Table"; + public static string Table = "Table"; + } + + public static class ApiSpecificUrlNames + { + public static string SqlDatabase = "sqlDatabases"; + public static string SqlContainer = "containers"; + public static string MongoDatabase = "mongodbDatabases"; + public static string MongoCollection = "collections"; + public static string GremlinDatabase = "gremlinDatabases"; + public static string GremlinGraph = "graphs"; + public static string CassandraKeyspace = "cassandraKeyspaces"; + public static string CassandraTable = "tables"; + public static string Table = "tables"; + } + + public static class MigratePartitionConstants + { + public static string SourceFederationId = "sourceFederationId"; + public static string SourceServiceName = "sourceServiceName"; + } + + public static class MigratePartitionCallerSource + { + public static string Test = "Test"; + public static string Unknown = "Unknown"; + public static string PLB_localRegion = "PLB_localRegion"; + public static string PLB_CrossRegion = "PLB_CrossRegion"; + public static string ACIS_PartitionMigration = "ACIS_PartitionMigration"; + public static string ACIS_BulkPartitionMigration = "ACIS_BulkPartitionMigration"; + public static string ACIS_CrossSubregionAccountMigration = "ACIS_CrossSubregionAccountMigration"; + public static string ACIS_MitigateMasterMigrationFailure = "ACIS_MitigateMasterMigrationFailure"; + public static string ACIS_MitigateServerMigrationFailure = "ACIS_MitigateServerMigrationFailure"; + public static string FederationBuildout_CanaryAccountMigration = "FederationBuildout_CanaryAccountMigration"; + public static string USER_InPlaceAZMigration = "USER_InPlaceAZMigration"; + } + + public static class EnvironmentVariables + { + public const string SocketOptionTcpKeepAliveIntervalName = "AZURE_COSMOS_TCP_KEEPALIVE_INTERVAL_SECONDS"; + public const string SocketOptionTcpKeepAliveTimeName = "AZURE_COSMOS_TCP_KEEPALIVE_TIME_SECONDS"; + public const string AggressiveTimeoutDetectionEnabled = "AZURE_COSMOS_AGGRESSIVE_TIMEOUT_DETECTION_ENABLED"; + public const string TimeoutDetectionTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_TIME_LIMIT_IN_SECONDS"; + public const string TimeoutDetectionOnWriteThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_WRITE_THRESHOLD"; + public const string TimeoutDetectionOnWriteTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_WRITE_TIME_LIMIT_IN_SECONDS"; + public const string TimeoutDetectionOnHighFrequencyThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_HIGH_FREQUENCY_THRESHOLD"; + public const string TimeoutDetectionOnHighFrequencyTimeLimit = "AZURE_COSMOS_TIMEOUT_DETECTION_ON_HIGH_FREQUENCY_TIME_LIMIT_IN_SECONDS"; + public const string TimeoutDetectionDisabledOnCPUThreshold = "AZURE_COSMOS_TIMEOUT_DETECTION_DISABLED_ON_CPU_THRESHOLD"; + public const string OldBarrierRequestHandlingEnabled = "AZURE_COSMOS_OLD_BARRIER_REQUESTS_HANDLING_ENABLED"; + } + + public static class AvailabilityZoneMigrationProperties + { + public const string DesiredIsZoneRedundantValue = "desiredIsZoneRedundantValue"; + public const string MigrateServerPartitionsOnly = "migrateServerPartitionsOnly"; + public const string MasterSourceFederationId = "masterSourceFederationId"; + } + + public static class RoleNames + { + public const string MasterCluster0 = "MasterCluster0"; + public const string ServerCluster0 = "ServerCluster0"; + public const string FabricInfrastructure = "FabricInfrastructure"; + public const string CosmosDBGateway = "CosmosDBGateway"; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ContentSerializationFormat.cs b/Microsoft.Azure.Cosmos/src/direct/ContentSerializationFormat.cs index 923de743b9..c0f15a8d71 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ContentSerializationFormat.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ContentSerializationFormat.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum ContentSerializationFormat - { - /// - /// Standard JSON RFC UTF-8 text. - /// - JsonText, - - /// - /// Custom binary for Cosmos DB that encodes a superset of JSON values. - /// - CosmosBinary, - - /// - /// Set the serialization format to HybridRow. - /// - HybridRow, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum ContentSerializationFormat + { + /// + /// Standard JSON RFC UTF-8 text. + /// + JsonText, + + /// + /// Custom binary for Cosmos DB that encodes a superset of JSON values. + /// + CosmosBinary, + + /// + /// Set the serialization format to HybridRow. + /// + HybridRow, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/CpuLoad.cs b/Microsoft.Azure.Cosmos/src/direct/CpuLoad.cs index 127d653826..a80c9d2dfb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CpuLoad.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CpuLoad.cs @@ -1,27 +1,27 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Globalization; - - internal struct CpuLoad - { - public DateTime Timestamp; - public float Value; - - public CpuLoad(DateTime timestamp, float value) - { - this.Timestamp = timestamp; - this.Value = value; - } - - public override string ToString() - { - return string.Format( - CultureInfo.InvariantCulture, "({0:O} {1:F3})", - this.Timestamp, this.Value); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Globalization; + + internal struct CpuLoad + { + public DateTime Timestamp; + public float Value; + + public CpuLoad(DateTime timestamp, float value) + { + this.Timestamp = timestamp; + this.Value = value; + } + + public override string ToString() + { + return string.Format( + CultureInfo.InvariantCulture, "({0:O} {1:F3})", + this.Timestamp, this.Value); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/CpuLoadHistory.cs b/Microsoft.Azure.Cosmos/src/direct/CpuLoadHistory.cs index 3c6ef221f6..052002bc7d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CpuLoadHistory.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CpuLoadHistory.cs @@ -1,93 +1,93 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Threading; - using System.Linq; - - internal sealed class CpuLoadHistory - { - internal ReadOnlyCollection CpuLoad { get; } - private readonly TimeSpan monitoringInterval; - private readonly Lazy cpuOverload; - private readonly Lazy cpuloadHistory; - - public CpuLoadHistory(ReadOnlyCollection cpuLoad, TimeSpan monitoringInterval) - { - if (cpuLoad == null) - { - throw new ArgumentNullException(nameof(cpuLoad)); - } - this.CpuLoad = cpuLoad; - - this.cpuloadHistory = new Lazy(() => - { - if (this.CpuLoad?.Count == 0) - { - return "empty"; - } - return string.Join(", ", this.CpuLoad); - }); - - if (monitoringInterval <= TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException( - nameof(monitoringInterval), - monitoringInterval, - string.Format("{0} must be strictly positive", nameof(monitoringInterval))); - } - - this.monitoringInterval = monitoringInterval; - this.cpuOverload = new Lazy( - new Func(this.GetCpuOverload), - LazyThreadSafetyMode.ExecutionAndPublication); - } - - // Currently used only for unit tests. - internal DateTime LastTimestamp { get { return this.CpuLoad.Last().Timestamp; } } - - public bool IsCpuOverloaded - { - get - { - return this.cpuOverload.Value; - } - } - - public override string ToString() - { - return this.cpuloadHistory.Value; - } - - private bool GetCpuOverload() - { - for (int i = 0; i < this.CpuLoad.Count; i++) - { - if (this.CpuLoad[i].Value > 90.0) - { - return true; - } - } - - // This signal is fragile, because the timestamps come from - // a non-monotonic clock that might have gotten adjusted by - // e.g. NTP. - for (int i = 0; i < this.CpuLoad.Count - 1; i++) - { - if (this.CpuLoad[i + 1].Timestamp.Subtract( - this.CpuLoad[i].Timestamp).TotalMilliseconds > - 1.5 * this.monitoringInterval.TotalMilliseconds) - { - return true; - } - - } - - return false; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Threading; + using System.Linq; + + internal sealed class CpuLoadHistory + { + internal ReadOnlyCollection CpuLoad { get; } + private readonly TimeSpan monitoringInterval; + private readonly Lazy cpuOverload; + private readonly Lazy cpuloadHistory; + + public CpuLoadHistory(ReadOnlyCollection cpuLoad, TimeSpan monitoringInterval) + { + if (cpuLoad == null) + { + throw new ArgumentNullException(nameof(cpuLoad)); + } + this.CpuLoad = cpuLoad; + + this.cpuloadHistory = new Lazy(() => + { + if (this.CpuLoad?.Count == 0) + { + return "empty"; + } + return string.Join(", ", this.CpuLoad); + }); + + if (monitoringInterval <= TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException( + nameof(monitoringInterval), + monitoringInterval, + string.Format("{0} must be strictly positive", nameof(monitoringInterval))); + } + + this.monitoringInterval = monitoringInterval; + this.cpuOverload = new Lazy( + new Func(this.GetCpuOverload), + LazyThreadSafetyMode.ExecutionAndPublication); + } + + // Currently used only for unit tests. + internal DateTime LastTimestamp { get { return this.CpuLoad.Last().Timestamp; } } + + public bool IsCpuOverloaded + { + get + { + return this.cpuOverload.Value; + } + } + + public override string ToString() + { + return this.cpuloadHistory.Value; + } + + private bool GetCpuOverload() + { + for (int i = 0; i < this.CpuLoad.Count; i++) + { + if (this.CpuLoad[i].Value > 90.0) + { + return true; + } + } + + // This signal is fragile, because the timestamps come from + // a non-monotonic clock that might have gotten adjusted by + // e.g. NTP. + for (int i = 0; i < this.CpuLoad.Count - 1; i++) + { + if (this.CpuLoad[i + 1].Timestamp.Subtract( + this.CpuLoad[i].Timestamp).TotalMilliseconds > + 1.5 * this.monitoringInterval.TotalMilliseconds) + { + return true; + } + + } + + return false; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/CpuMonitor.cs b/Microsoft.Azure.Cosmos/src/direct/CpuMonitor.cs index d077813a92..f0ab408343 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CpuMonitor.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CpuMonitor.cs @@ -1,284 +1,284 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Diagnostics; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - // This class is thread safe. - internal sealed class CpuMonitor : IDisposable - { - internal const int DefaultRefreshIntervalInSeconds = 10; - private const int HistoryLength = 6; - private static TimeSpan refreshInterval = - TimeSpan.FromSeconds(DefaultRefreshIntervalInSeconds); - - private bool disposed = false; - - private readonly ReaderWriterLockSlim rwLock = - new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - private CancellationTokenSource cancellation; // Guarded by rwLock. - - // CpuMonitor users get a copy of the internal buffer to avoid racing - // against changes. - private CpuLoadHistory currentReading; // Guarded by rwLock. - - private Task periodicTask; // Guarded by rwLock. - - // Allows tests to override the default refresh interval - internal static void OverrideRefreshInterval(TimeSpan newRefreshInterval) - { - CpuMonitor.refreshInterval = newRefreshInterval; - } - - public void Start() - { - this.ThrowIfDisposed(); - this.rwLock.EnterWriteLock(); - try - { - this.ThrowIfDisposed(); - if (this.periodicTask != null) - { - throw new InvalidOperationException("CpuMonitor already started"); - } - this.cancellation = new CancellationTokenSource(); - CancellationToken cancellationToken = this.cancellation.Token; - this.periodicTask = Task.Factory.StartNew( - () => this.RefreshLoopAsync(cancellationToken), - cancellationToken, - TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, - TaskScheduler.Default).Unwrap(); - this.periodicTask.ContinueWith( - t => - { - DefaultTrace.TraceError( - "The CPU monitor refresh task failed. Exception: {0}", - t.Exception); - }, - TaskContinuationOptions.OnlyOnFaulted); - this.periodicTask.ContinueWith(t => - { - DefaultTrace.TraceInformation( - "The CPU monitor refresh task stopped. Status: {0}", - t.Status); - }, - TaskContinuationOptions.NotOnFaulted); - } - finally - { - this.rwLock.ExitWriteLock(); - } - DefaultTrace.TraceInformation("CpuMonitor started"); - } - - private void StopCoreUnderWriteLock(ref CancellationTokenSource cancel, ref Task backgroundTask) - { - if (this.periodicTask == null) - { - throw new InvalidOperationException("CpuMonitor not started or has been stopped or disposed already."); - } - - cancel = this.cancellation; - backgroundTask = this.periodicTask; - - this.cancellation = null; - this.currentReading = null; - this.periodicTask = null; - } - - private static void StopCoreAfterReleasingWriteLock(CancellationTokenSource cancel, Task backgroundTask) - { - cancel.Cancel(); - try - { - backgroundTask.Wait(); - } - catch (AggregateException) - { } - cancel.Dispose(); - } - - public void Stop() - { - this.ThrowIfDisposed(); - CancellationTokenSource cancel = null; - Task backgroundTask = null; - this.rwLock.EnterWriteLock(); - try - { - this.ThrowIfDisposed(); - this.StopCoreUnderWriteLock(ref cancel, ref backgroundTask); - } - finally - { - this.rwLock.ExitWriteLock(); - } - - StopCoreAfterReleasingWriteLock(cancel, backgroundTask); - - DefaultTrace.TraceInformation("CpuMonitor stopped"); - } - - // Returns a read-only collection of CPU load measurements, or null if - // no results are available yet. - public CpuLoadHistory GetCpuLoad() - { - this.ThrowIfDisposed(); - this.rwLock.EnterReadLock(); - try - { - if (this.periodicTask == null) - { - throw new InvalidOperationException("CpuMonitor was not started or has been stopped or disposed already."); - } - return this.currentReading; - } - finally - { - this.rwLock.ExitReadLock(); - } - } - - public void Dispose() - { - Interlocked.MemoryBarrier(); - if (this.disposed) - { - return; - } - - CancellationTokenSource cancel = null; - Task backgroundTask = null; - this.rwLock.EnterWriteLock(); - try - { - Interlocked.MemoryBarrier(); - if (this.disposed) - { - return; - } - - if (this.periodicTask != null) - { - this.StopCoreUnderWriteLock(ref cancel, ref backgroundTask); - } - } - finally - { - this.MarkDisposed(); - this.rwLock.ExitWriteLock(); - } - - if (backgroundTask != null) - { - StopCoreAfterReleasingWriteLock(cancel, backgroundTask); - } - - this.rwLock.Dispose(); - } - - private void MarkDisposed() - { - this.disposed = true; - Interlocked.MemoryBarrier(); - } - - private void ThrowIfDisposed() - { - Interlocked.MemoryBarrier(); - if (this.disposed) - { - throw new ObjectDisposedException(nameof(CpuMonitor)); - } - } - - private async Task RefreshLoopAsync(CancellationToken cancellationToken) - { - Trace.CorrelationManager.ActivityId = Guid.NewGuid(); - - SystemUtilizationReaderBase cpuReader = SystemUtilizationReaderBase.SingletonInstance; - - CpuLoad[] buffer = new CpuLoad[CpuMonitor.HistoryLength]; - int clockHand = 0; - - TaskCompletionSource cancellationCompletion = - new TaskCompletionSource(); - cancellationToken.Register(() => { cancellationCompletion.SetCanceled(); }); - - Task[] refreshTasks = new Task[2]; - refreshTasks[1] = cancellationCompletion.Task; - - // Increasing nextExpiration in fixed increments helps maintain - // timer cadence regardless of scheduling delays. - DateTime nextExpiration = DateTime.UtcNow; - while (!cancellationToken.IsCancellationRequested) - { - DateTime now = DateTime.UtcNow; - float currentUtilization = cpuReader.GetSystemWideCpuUsage(); - - if (!float.IsNaN(currentUtilization)) - { - List cpuLoadHistory = new List(buffer.Length); - CpuLoadHistory newReading = new CpuLoadHistory( - new ReadOnlyCollection(cpuLoadHistory), - CpuMonitor.refreshInterval); - - buffer[clockHand] = new CpuLoad(now, currentUtilization); - clockHand = (clockHand + 1) % buffer.Length; - - for (int i = 0; i < buffer.Length; i++) - { - int index = (clockHand + i) % buffer.Length; - if (buffer[index].Timestamp != DateTime.MinValue) - { - cpuLoadHistory.Add(buffer[index]); - } - } - - this.rwLock.EnterWriteLock(); - try - { - if (cancellationToken.IsCancellationRequested) - { - break; - } - - this.currentReading = newReading; - } - finally - { - this.rwLock.ExitWriteLock(); - } - } - - // Skip missed beats. - now = DateTime.UtcNow; - while (nextExpiration <= now) - { - nextExpiration += CpuMonitor.refreshInterval; - } - TimeSpan delay = nextExpiration - DateTime.UtcNow; - if (delay > TimeSpan.Zero) - { - refreshTasks[0] = Task.Delay(delay); - Task completedTask = await Task.WhenAny(refreshTasks); - if (object.ReferenceEquals(completedTask, refreshTasks[1])) - { - // Cancelled. - break; - } - } - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + // This class is thread safe. + internal sealed class CpuMonitor : IDisposable + { + internal const int DefaultRefreshIntervalInSeconds = 10; + private const int HistoryLength = 6; + private static TimeSpan refreshInterval = + TimeSpan.FromSeconds(DefaultRefreshIntervalInSeconds); + + private bool disposed = false; + + private readonly ReaderWriterLockSlim rwLock = + new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); + private CancellationTokenSource cancellation; // Guarded by rwLock. + + // CpuMonitor users get a copy of the internal buffer to avoid racing + // against changes. + private CpuLoadHistory currentReading; // Guarded by rwLock. + + private Task periodicTask; // Guarded by rwLock. + + // Allows tests to override the default refresh interval + internal static void OverrideRefreshInterval(TimeSpan newRefreshInterval) + { + CpuMonitor.refreshInterval = newRefreshInterval; + } + + public void Start() + { + this.ThrowIfDisposed(); + this.rwLock.EnterWriteLock(); + try + { + this.ThrowIfDisposed(); + if (this.periodicTask != null) + { + throw new InvalidOperationException("CpuMonitor already started"); + } + this.cancellation = new CancellationTokenSource(); + CancellationToken cancellationToken = this.cancellation.Token; + this.periodicTask = Task.Factory.StartNew( + () => this.RefreshLoopAsync(cancellationToken), + cancellationToken, + TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach, + TaskScheduler.Default).Unwrap(); + this.periodicTask.ContinueWith( + t => + { + DefaultTrace.TraceError( + "The CPU monitor refresh task failed. Exception: {0}", + t.Exception); + }, + TaskContinuationOptions.OnlyOnFaulted); + this.periodicTask.ContinueWith(t => + { + DefaultTrace.TraceInformation( + "The CPU monitor refresh task stopped. Status: {0}", + t.Status); + }, + TaskContinuationOptions.NotOnFaulted); + } + finally + { + this.rwLock.ExitWriteLock(); + } + DefaultTrace.TraceInformation("CpuMonitor started"); + } + + private void StopCoreUnderWriteLock(ref CancellationTokenSource cancel, ref Task backgroundTask) + { + if (this.periodicTask == null) + { + throw new InvalidOperationException("CpuMonitor not started or has been stopped or disposed already."); + } + + cancel = this.cancellation; + backgroundTask = this.periodicTask; + + this.cancellation = null; + this.currentReading = null; + this.periodicTask = null; + } + + private static void StopCoreAfterReleasingWriteLock(CancellationTokenSource cancel, Task backgroundTask) + { + cancel.Cancel(); + try + { + backgroundTask.Wait(); + } + catch (AggregateException) + { } + cancel.Dispose(); + } + + public void Stop() + { + this.ThrowIfDisposed(); + CancellationTokenSource cancel = null; + Task backgroundTask = null; + this.rwLock.EnterWriteLock(); + try + { + this.ThrowIfDisposed(); + this.StopCoreUnderWriteLock(ref cancel, ref backgroundTask); + } + finally + { + this.rwLock.ExitWriteLock(); + } + + StopCoreAfterReleasingWriteLock(cancel, backgroundTask); + + DefaultTrace.TraceInformation("CpuMonitor stopped"); + } + + // Returns a read-only collection of CPU load measurements, or null if + // no results are available yet. + public CpuLoadHistory GetCpuLoad() + { + this.ThrowIfDisposed(); + this.rwLock.EnterReadLock(); + try + { + if (this.periodicTask == null) + { + throw new InvalidOperationException("CpuMonitor was not started or has been stopped or disposed already."); + } + return this.currentReading; + } + finally + { + this.rwLock.ExitReadLock(); + } + } + + public void Dispose() + { + Interlocked.MemoryBarrier(); + if (this.disposed) + { + return; + } + + CancellationTokenSource cancel = null; + Task backgroundTask = null; + this.rwLock.EnterWriteLock(); + try + { + Interlocked.MemoryBarrier(); + if (this.disposed) + { + return; + } + + if (this.periodicTask != null) + { + this.StopCoreUnderWriteLock(ref cancel, ref backgroundTask); + } + } + finally + { + this.MarkDisposed(); + this.rwLock.ExitWriteLock(); + } + + if (backgroundTask != null) + { + StopCoreAfterReleasingWriteLock(cancel, backgroundTask); + } + + this.rwLock.Dispose(); + } + + private void MarkDisposed() + { + this.disposed = true; + Interlocked.MemoryBarrier(); + } + + private void ThrowIfDisposed() + { + Interlocked.MemoryBarrier(); + if (this.disposed) + { + throw new ObjectDisposedException(nameof(CpuMonitor)); + } + } + + private async Task RefreshLoopAsync(CancellationToken cancellationToken) + { + Trace.CorrelationManager.ActivityId = Guid.NewGuid(); + + SystemUtilizationReaderBase cpuReader = SystemUtilizationReaderBase.SingletonInstance; + + CpuLoad[] buffer = new CpuLoad[CpuMonitor.HistoryLength]; + int clockHand = 0; + + TaskCompletionSource cancellationCompletion = + new TaskCompletionSource(); + cancellationToken.Register(() => { cancellationCompletion.SetCanceled(); }); + + Task[] refreshTasks = new Task[2]; + refreshTasks[1] = cancellationCompletion.Task; + + // Increasing nextExpiration in fixed increments helps maintain + // timer cadence regardless of scheduling delays. + DateTime nextExpiration = DateTime.UtcNow; + while (!cancellationToken.IsCancellationRequested) + { + DateTime now = DateTime.UtcNow; + float currentUtilization = cpuReader.GetSystemWideCpuUsage(); + + if (!float.IsNaN(currentUtilization)) + { + List cpuLoadHistory = new List(buffer.Length); + CpuLoadHistory newReading = new CpuLoadHistory( + new ReadOnlyCollection(cpuLoadHistory), + CpuMonitor.refreshInterval); + + buffer[clockHand] = new CpuLoad(now, currentUtilization); + clockHand = (clockHand + 1) % buffer.Length; + + for (int i = 0; i < buffer.Length; i++) + { + int index = (clockHand + i) % buffer.Length; + if (buffer[index].Timestamp != DateTime.MinValue) + { + cpuLoadHistory.Add(buffer[index]); + } + } + + this.rwLock.EnterWriteLock(); + try + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + + this.currentReading = newReading; + } + finally + { + this.rwLock.ExitWriteLock(); + } + } + + // Skip missed beats. + now = DateTime.UtcNow; + while (nextExpiration <= now) + { + nextExpiration += CpuMonitor.refreshInterval; + } + TimeSpan delay = nextExpiration - DateTime.UtcNow; + if (delay > TimeSpan.Zero) + { + refreshTasks[0] = Task.Delay(delay); + Task completedTask = await Task.WhenAny(refreshTasks); + if (object.ReferenceEquals(completedTask, refreshTasks[1])) + { + // Cancelled. + break; + } + } + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs b/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs index d68f898b8c..26b4c957db 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs @@ -1,292 +1,292 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.Tracing; - using System.Globalization; - using System.IO; - using System.Net.Sockets; - using System.Reflection; - using System.Runtime.InteropServices; - using System.Security; - using System.Security.Cryptography; - using Microsoft.Azure.Cosmos.Core.Trace; - - /// - /// Extension class for defining methods/properties on Type class that are - /// not available on .NET Standard 1.6. This allows us to keep the same code - /// we had earlier and when compiling for .NET Standard 1.6, we use these - /// extension methods that call GetTypeInfo() on the Type instance and call - /// the corresponding method on it. - /// - /// IsGenericType, IsEnum, IsValueType, IsInterface and BaseType are properties - /// on Type class but since we cannot define "extension properties", I've converted - /// them to methods and return the underlying property value from the call to - /// GetTypeInfo(). For .NET Framework, these extension methods simply return - /// the underlying property value. - /// - internal static class CustomTypeExtensions - { - public const int UnicodeEncodingCharSize = 2; - -#if COSMOSCLIENT - public const string SDKName = "cosmos-netstandard-sdk"; - public const string SDKVersion = "3.32.0"; -#else - public const string SDKName = "documentdb-netcore-sdk"; - public const string SDKVersion = "2.14.0"; -#endif - - #region Type Extension Methods -#if (NETSTANDARD15 || NETSTANDARD16) - public static bool IsAssignableFrom(this Type type, Type c) - { - return type.GetTypeInfo().IsAssignableFrom(c); - } - - public static bool IsSubclassOf(this Type type, Type c) - { - return type.GetTypeInfo().IsSubclassOf(c); - } - - public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingAttr) - { - return type.GetTypeInfo().GetMethod(name, bindingAttr); - } - - public static MethodInfo GetMethod(this Type type, string name) - { - return type.GetTypeInfo().GetMethod(name); - } - public static MethodInfo GetMethod(this Type type, string name, Type[] types) - { - return type.GetTypeInfo().GetMethod(name, types); - } - - public static Type[] GetGenericArguments(this Type type) - { - return type.GetTypeInfo().GetGenericArguments(); - } - - public static PropertyInfo GetProperty(this Type type, string name) - { - return type.GetTypeInfo().GetProperty(name); - } - - public static PropertyInfo[] GetProperties(this Type type) - { - return type.GetTypeInfo().GetProperties(); - } - - public static PropertyInfo[] GetProperties(this Type type, BindingFlags bindingAttr) - { - return type.GetTypeInfo().GetProperties(bindingAttr); - } - - public static Type[] GetInterfaces(this Type type) - { - return type.GetTypeInfo().GetInterfaces(); - } - - public static ConstructorInfo GetConstructor(this Type type, Type[] types) - { - return type.GetTypeInfo().GetConstructor(types); - } - - public static T GetCustomAttribute(this Type type, bool inherit) where T : Attribute - { - return type.GetTypeInfo().GetCustomAttribute(inherit); - } -#endif - -#if NETSTANDARD16 - public static IEnumerable GetCustomAttributes(this Type type, Type attributeType, bool inherit) - { - return type.GetTypeInfo().GetCustomAttributes(attributeType, inherit); - } -#endif - -#endregion - - #region Misc Extension Methods -#if (NETSTANDARD15 || NETSTANDARD16) - public static byte[] GetBuffer(this MemoryStream stream) - { - ArraySegment buffer; - stream.TryGetBuffer(out buffer); - return buffer.Array; - } - - public static void Close(this Stream stream) - { - stream.Dispose(); - } - - public static void Close(this TcpClient tcpClient) - { - tcpClient.Dispose(); - } -#endif -#endregion - - #region Helper Methods -#if (NETSTANDARD15 || NETSTANDARD16) - public static string GetLeftPart(this Uri uri, UriPartial part) - { - const UriComponents NonPathPart = (UriComponents.Scheme | UriComponents.UserInfo | UriComponents.Host | UriComponents.Port); - - switch (part) - { - case UriPartial.Authority: - return uri.GetComponents(NonPathPart, UriFormat.UriEscaped); - - case UriPartial.Path: - return uri.GetComponents(NonPathPart | UriComponents.Path, UriFormat.UriEscaped); - - case UriPartial.Query: - return uri.GetComponents(NonPathPart | UriComponents.Path | UriComponents.Query, UriFormat.UriEscaped); - - case UriPartial.Scheme: - return uri.GetComponents(UriComponents.Scheme | UriComponents.KeepDelimiter, UriFormat.UriEscaped); - } - - throw new ArgumentException("Invalid part", nameof(part)); - } -#endif - - public static Delegate CreateDelegate(Type delegateType, object target, MethodInfo methodInfo) - { - return methodInfo.CreateDelegate(delegateType, target); - } - - public static IntPtr SecureStringToCoTaskMemAnsi(SecureString secureString) - { - return SecureStringMarshal.SecureStringToCoTaskMemAnsi(secureString); - } - - public static void SetActivityId(ref Guid id) - { - EventSource.SetCurrentThreadActivityId(id); - } - - public static Random GetRandomNumber() - { - using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) - { - byte[] seedArray = new byte[sizeof(int)]; - randomNumberGenerator.GetBytes(seedArray); - return new Random(BitConverter.ToInt32(seedArray, 0)); - } - } - - public static QueryRequestPerformanceActivity StartActivity(DocumentServiceRequest request) - { - return null; - } - - public static string GenerateBaseUserAgentString() - { - string version = PlatformApis.GetOSVersion(); - - // Example: Windows/10.0.14393 documentdb-netcore-sdk/0.0.1 - return string.Format(CultureInfo.InvariantCulture, "{0}/{1} {2}/{3}", - PlatformApis.GetOSPlatform(), - String.IsNullOrEmpty(version) ? "Unknown" : version.Trim(), - SDKName, - SDKVersion); - } - - // This is how you can determine whether a socket is still connected. - public static bool ConfirmOpen(Socket socket) - { - bool blockingState = socket.Blocking; - - try - { - byte[] tmp = new byte[1]; - - // Make a nonblocking, zero-byte Send call - socket.Blocking = false; - socket.Send(tmp, 0, 0); - return true; - } - - catch (SocketException ex) - { - // If the Send call throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected - return (ex.SocketErrorCode == SocketError.WouldBlock); - } - - catch (ObjectDisposedException) - { - // Send with throw ObjectDisposedException if the Socket has been closed - return false; - } - - finally - { - socket.Blocking = blockingState; - } - } - - // Bypass query parsing on 32 bit process on Windows and always on non-Windows(Linux/OSX) platforms or if interop assemblies don't exist. - public static bool ByPassQueryParsing() - { - if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !ServiceInteropWrapper.Is64BitProcess || !ServiceInteropWrapper.AssembliesExist.Value) - { - DefaultTrace.TraceVerbose($"Bypass query parsing. IsWindowsOSPlatform {RuntimeInformation.IsOSPlatform(OSPlatform.Windows)} IntPtr.Size is {IntPtr.Size} ServiceInteropWrapper.AssembliesExist {ServiceInteropWrapper.AssembliesExist.Value}"); - return true; - } - - return false; - } - -#endregion - -#region Properties converted to Methods - public static bool IsGenericType(this Type type) - { - return type.GetTypeInfo().IsGenericType; - } - - public static bool IsEnum(this Type type) - { - return type.GetTypeInfo().IsEnum; - } - - public static bool IsValueType(this Type type) - { - return type.GetTypeInfo().IsValueType; - } - - public static bool IsInterface(this Type type) - { - return type.GetTypeInfo().IsInterface; - } - - public static Type GetBaseType(this Type type) - { - return type.GetTypeInfo().BaseType; - } - - public static Type GeUnderlyingSystemType(this Type type) - { - return type.GetTypeInfo().UnderlyingSystemType; - } - - public static Assembly GetAssembly(this Type type) - { - return type.GetTypeInfo().Assembly; - } - - public static IEnumerable GetsCustomAttributes(this Type type) - { - return type.GetTypeInfo().CustomAttributes; - } -#endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.Tracing; + using System.Globalization; + using System.IO; + using System.Net.Sockets; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Security; + using System.Security.Cryptography; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// Extension class for defining methods/properties on Type class that are + /// not available on .NET Standard 1.6. This allows us to keep the same code + /// we had earlier and when compiling for .NET Standard 1.6, we use these + /// extension methods that call GetTypeInfo() on the Type instance and call + /// the corresponding method on it. + /// + /// IsGenericType, IsEnum, IsValueType, IsInterface and BaseType are properties + /// on Type class but since we cannot define "extension properties", I've converted + /// them to methods and return the underlying property value from the call to + /// GetTypeInfo(). For .NET Framework, these extension methods simply return + /// the underlying property value. + /// + internal static class CustomTypeExtensions + { + public const int UnicodeEncodingCharSize = 2; + +#if COSMOSCLIENT + public const string SDKName = "cosmos-netstandard-sdk"; + public const string SDKVersion = "3.18.0"; +#else + public const string SDKName = "documentdb-netcore-sdk"; + public const string SDKVersion = "2.14.0"; +#endif + + #region Type Extension Methods +#if (NETSTANDARD15 || NETSTANDARD16) + public static bool IsAssignableFrom(this Type type, Type c) + { + return type.GetTypeInfo().IsAssignableFrom(c); + } + + public static bool IsSubclassOf(this Type type, Type c) + { + return type.GetTypeInfo().IsSubclassOf(c); + } + + public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingAttr) + { + return type.GetTypeInfo().GetMethod(name, bindingAttr); + } + + public static MethodInfo GetMethod(this Type type, string name) + { + return type.GetTypeInfo().GetMethod(name); + } + public static MethodInfo GetMethod(this Type type, string name, Type[] types) + { + return type.GetTypeInfo().GetMethod(name, types); + } + + public static Type[] GetGenericArguments(this Type type) + { + return type.GetTypeInfo().GetGenericArguments(); + } + + public static PropertyInfo GetProperty(this Type type, string name) + { + return type.GetTypeInfo().GetProperty(name); + } + + public static PropertyInfo[] GetProperties(this Type type) + { + return type.GetTypeInfo().GetProperties(); + } + + public static PropertyInfo[] GetProperties(this Type type, BindingFlags bindingAttr) + { + return type.GetTypeInfo().GetProperties(bindingAttr); + } + + public static Type[] GetInterfaces(this Type type) + { + return type.GetTypeInfo().GetInterfaces(); + } + + public static ConstructorInfo GetConstructor(this Type type, Type[] types) + { + return type.GetTypeInfo().GetConstructor(types); + } + + public static T GetCustomAttribute(this Type type, bool inherit) where T : Attribute + { + return type.GetTypeInfo().GetCustomAttribute(inherit); + } +#endif + +#if NETSTANDARD16 + public static IEnumerable GetCustomAttributes(this Type type, Type attributeType, bool inherit) + { + return type.GetTypeInfo().GetCustomAttributes(attributeType, inherit); + } +#endif + +#endregion + + #region Misc Extension Methods +#if (NETSTANDARD15 || NETSTANDARD16) + public static byte[] GetBuffer(this MemoryStream stream) + { + ArraySegment buffer; + stream.TryGetBuffer(out buffer); + return buffer.Array; + } + + public static void Close(this Stream stream) + { + stream.Dispose(); + } + + public static void Close(this TcpClient tcpClient) + { + tcpClient.Dispose(); + } +#endif +#endregion + + #region Helper Methods +#if (NETSTANDARD15 || NETSTANDARD16) + public static string GetLeftPart(this Uri uri, UriPartial part) + { + const UriComponents NonPathPart = (UriComponents.Scheme | UriComponents.UserInfo | UriComponents.Host | UriComponents.Port); + + switch (part) + { + case UriPartial.Authority: + return uri.GetComponents(NonPathPart, UriFormat.UriEscaped); + + case UriPartial.Path: + return uri.GetComponents(NonPathPart | UriComponents.Path, UriFormat.UriEscaped); + + case UriPartial.Query: + return uri.GetComponents(NonPathPart | UriComponents.Path | UriComponents.Query, UriFormat.UriEscaped); + + case UriPartial.Scheme: + return uri.GetComponents(UriComponents.Scheme | UriComponents.KeepDelimiter, UriFormat.UriEscaped); + } + + throw new ArgumentException("Invalid part", nameof(part)); + } +#endif + + public static Delegate CreateDelegate(Type delegateType, object target, MethodInfo methodInfo) + { + return methodInfo.CreateDelegate(delegateType, target); + } + + public static IntPtr SecureStringToCoTaskMemAnsi(SecureString secureString) + { + return SecureStringMarshal.SecureStringToCoTaskMemAnsi(secureString); + } + + public static void SetActivityId(ref Guid id) + { + EventSource.SetCurrentThreadActivityId(id); + } + + public static Random GetRandomNumber() + { + using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) + { + byte[] seedArray = new byte[sizeof(int)]; + randomNumberGenerator.GetBytes(seedArray); + return new Random(BitConverter.ToInt32(seedArray, 0)); + } + } + + public static QueryRequestPerformanceActivity StartActivity(DocumentServiceRequest request) + { + return null; + } + + public static string GenerateBaseUserAgentString() + { + string version = PlatformApis.GetOSVersion(); + + // Example: Windows/10.0.14393 documentdb-netcore-sdk/0.0.1 + return string.Format(CultureInfo.InvariantCulture, "{0}/{1} {2}/{3}", + PlatformApis.GetOSPlatform(), + String.IsNullOrEmpty(version) ? "Unknown" : version.Trim(), + SDKName, + SDKVersion); + } + + // This is how you can determine whether a socket is still connected. + public static bool ConfirmOpen(Socket socket) + { + bool blockingState = socket.Blocking; + + try + { + byte[] tmp = new byte[1]; + + // Make a nonblocking, zero-byte Send call + socket.Blocking = false; + socket.Send(tmp, 0, 0); + return true; + } + + catch (SocketException ex) + { + // If the Send call throws a WAEWOULDBLOCK error code (10035), then the socket is still connected; otherwise, the socket is no longer connected + return (ex.SocketErrorCode == SocketError.WouldBlock); + } + + catch (ObjectDisposedException) + { + // Send with throw ObjectDisposedException if the Socket has been closed + return false; + } + + finally + { + socket.Blocking = blockingState; + } + } + + // Bypass query parsing on 32 bit process on Windows and always on non-Windows(Linux/OSX) platforms or if interop assemblies don't exist. + public static bool ByPassQueryParsing() + { + if(!RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || !ServiceInteropWrapper.Is64BitProcess || !ServiceInteropWrapper.AssembliesExist.Value) + { + DefaultTrace.TraceVerbose($"Bypass query parsing. IsWindowsOSPlatform {RuntimeInformation.IsOSPlatform(OSPlatform.Windows)} IntPtr.Size is {IntPtr.Size} ServiceInteropWrapper.AssembliesExist {ServiceInteropWrapper.AssembliesExist.Value}"); + return true; + } + + return false; + } + +#endregion + +#region Properties converted to Methods + public static bool IsGenericType(this Type type) + { + return type.GetTypeInfo().IsGenericType; + } + + public static bool IsEnum(this Type type) + { + return type.GetTypeInfo().IsEnum; + } + + public static bool IsValueType(this Type type) + { + return type.GetTypeInfo().IsValueType; + } + + public static bool IsInterface(this Type type) + { + return type.GetTypeInfo().IsInterface; + } + + public static Type GetBaseType(this Type type) + { + return type.GetTypeInfo().BaseType; + } + + public static Type GeUnderlyingSystemType(this Type type) + { + return type.GetTypeInfo().UnderlyingSystemType; + } + + public static Assembly GetAssembly(this Type type) + { + return type.GetTypeInfo().Assembly; + } + + public static IEnumerable GetsCustomAttributes(this Type type) + { + return type.GetTypeInfo().CustomAttributes; + } +#endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DataEncryptionKeyStatus.cs b/Microsoft.Azure.Cosmos/src/direct/DataEncryptionKeyStatus.cs index ec4e864392..a29b3c3ea9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DataEncryptionKeyStatus.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DataEncryptionKeyStatus.cs @@ -1,12 +1,12 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal enum DataEncryptionKeyStatus - { - Active, - Revoked, - None - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal enum DataEncryptionKeyStatus + { + Active, + Revoked, + None + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs b/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs index 4c62c6f623..73faa5e3b2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - internal sealed class DataMaskingIncludedPath : JsonSerializable - { - /// - /// Gets or sets the path to be masked. Must be a top level path, eg. /salary - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get { return this.GetValue(Constants.Properties.Path); } - set { this.SetValue(Constants.Properties.Path, value); } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + internal sealed class DataMaskingIncludedPath : JsonSerializable + { + /// + /// Gets or sets the path to be masked. Must be a top level path, eg. /salary + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get { return this.GetValue(Constants.Properties.Path); } + set { this.SetValue(Constants.Properties.Path, value); } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs index a783405067..34ce62aa0d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs @@ -1,95 +1,95 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - - /// - /// Represents the data masking policy for a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class DataMaskingPolicy : JsonSerializable - { - private Collection includedPaths; - private Boolean isPolicyEnabled; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public DataMaskingPolicy() - { - } - - /// - /// Paths of the item that need masked along with path-specific settings. - /// - [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] - public Collection IncludedPaths - { - get - { - if (this.includedPaths == null) - { - this.includedPaths = base.GetObjectCollection(Constants.Properties.IncludedPaths); - if (this.includedPaths == null) - { - this.includedPaths = new Collection(); - } - } - - return this.includedPaths; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IncludedPaths))); - } - - this.includedPaths = value; - base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); - } - } - - /// - /// Paths of the item that need masked along with path-specific settings. - /// - [JsonProperty(PropertyName = Constants.Properties.IsPolicyEnabled)] - public Boolean IsPolicyEnabled - { - get - { - if (!this.isPolicyEnabled) - { - this.isPolicyEnabled = base.GetValue(Constants.Properties.IsPolicyEnabled, true); - } - - return this.isPolicyEnabled; - } - set - { - if (!value) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IsPolicyEnabled))); - } - - this.isPolicyEnabled = value; - base.SetValue(Constants.Properties.IsPolicyEnabled, this.IsPolicyEnabled); - } - } - - internal override void OnSave() - { - if (this.includedPaths != null) - { - base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); - base.SetValue(Constants.Properties.IsPolicyEnabled, this.isPolicyEnabled); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Represents the data masking policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class DataMaskingPolicy : JsonSerializable + { + private Collection includedPaths; + private Boolean isPolicyEnabled; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public DataMaskingPolicy() + { + } + + /// + /// Paths of the item that need masked along with path-specific settings. + /// + [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] + public Collection IncludedPaths + { + get + { + if (this.includedPaths == null) + { + this.includedPaths = base.GetObjectCollection(Constants.Properties.IncludedPaths); + if (this.includedPaths == null) + { + this.includedPaths = new Collection(); + } + } + + return this.includedPaths; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IncludedPaths))); + } + + this.includedPaths = value; + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + } + } + + /// + /// Paths of the item that need masked along with path-specific settings. + /// + [JsonProperty(PropertyName = Constants.Properties.IsPolicyEnabled)] + public Boolean IsPolicyEnabled + { + get + { + if (!this.isPolicyEnabled) + { + this.isPolicyEnabled = base.GetValue(Constants.Properties.IsPolicyEnabled, true); + } + + return this.isPolicyEnabled; + } + set + { + if (!value) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IsPolicyEnabled))); + } + + this.isPolicyEnabled = value; + base.SetValue(Constants.Properties.IsPolicyEnabled, this.IsPolicyEnabled); + } + } + + internal override void OnSave() + { + if (this.includedPaths != null) + { + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + base.SetValue(Constants.Properties.IsPolicyEnabled, this.isPolicyEnabled); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DataType.cs b/Microsoft.Azure.Cosmos/src/direct/DataType.cs index 3323fc4e35..64f4c0cc40 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DataType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DataType.cs @@ -1,46 +1,46 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Defines the target data type of an index path specification in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum DataType - { - /// - /// Represents a numeric data type. - /// - Number, - - /// - /// Represents a string data type. - /// - String, - - /// - /// Represent a point data type. - /// - Point, - - /// - /// Represent a line string data type. - /// - LineString, - - /// - /// Represent a polygon data type. - /// - Polygon, - - /// - /// Represent a multi-polygon data type. - /// - MultiPolygon, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Defines the target data type of an index path specification in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum DataType + { + /// + /// Represents a numeric data type. + /// + Number, + + /// + /// Represents a string data type. + /// + String, + + /// + /// Represent a point data type. + /// + Point, + + /// + /// Represent a line string data type. + /// + LineString, + + /// + /// Represent a polygon data type. + /// + Polygon, + + /// + /// Represent a multi-polygon data type. + /// + MultiPolygon, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Database.cs b/Microsoft.Azure.Cosmos/src/direct/Database.cs index 5673e263a1..60fdab39df 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Database.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Database.cs @@ -1,196 +1,196 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents a database in the Azure Cosmos DB account. - /// - /// - /// Each Azure Cosmos DB database account can have zero or more databases. A database in Azure Cosmos DB is a logical container for - /// document collections and users. - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#databases for more details on databases. - /// - /// - /// The example below creates a new Database with an Id property of 'MyDatabase'. - /// - /// - /// - /// - /// - /// The example below creates a collection within this database with OfferThroughput set to 10000. - /// - /// - /// - /// - /// - /// The example below queries for a Database by Id to retrieve the SelfLink. - /// - /// d.Id == "MyDatabase").AsEnumerable().FirstOrDefault(); - /// string databaseLink = database.SelfLink; - /// ]]> - /// - /// - /// - /// The example below deletes the database using its SelfLink property. - /// - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Database : Resource - { - private InAccountRestoreParameters restoreParameters; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public Database() - { - - } - - /// - /// Gets the self-link for collections from the Azure Cosmos DB service. - /// - /// - /// The self-link for collections in the database. - /// - /// - /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. - /// For collections, this takes the form of; - /// /dbs/db_rid/colls/ where db_rid represents the value of the database's resource id. - /// A resource id is not the id given to a database on creation, but an internally generated immutable id. - /// - [JsonProperty(PropertyName = Constants.Properties.CollectionsLink)] - public string CollectionsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.CollectionsLink); - } - } - - /// - /// Gets the self-link for users from the Azure Cosmos DB service. - /// - /// - /// The self-link for users in the database. - /// - /// - /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. - /// For users, this takes the form of; - /// /dbs/db_rid/users/ where db_rid represents the value of the database's resource id. - /// A resource id is not the id given to a database on creation, but an internally generated immutable id. - /// - [JsonProperty(PropertyName = Constants.Properties.UsersLink)] - public string UsersLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.UsersLink); - } - } - - /// - /// Gets the self-link for user defined types from the Azure Cosmos DB service. - /// - /// - /// The self-link for user defined types in the database. - /// - /// - /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. - /// For user defined types, this takes the form of; - /// /dbs/db_rid/udts/ where db_rid represents the value of the database's resource id. - /// A resource id is not the id given to a database on creation, but an internally generated immutable id. - /// - internal string UserDefinedTypesLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + Paths.UserDefinedTypesPathSegment + "/"; - } - } - - /// - /// Gets or sets the for triggering the InAccountRestore of the database - /// - /// - /// It is an optional property. - /// A valid value should be Default or Restore - /// - [JsonProperty(PropertyName = Constants.Properties.CreateMode, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal DatabaseOrCollectionCreateMode? CreateMode - { - get - { - return base.GetValue(Constants.Properties.CreateMode, null); - } - set - { - base.SetValue(Constants.Properties.CreateMode, value.ToString()); - } - } - - /// - /// Gets or sets the for triggering the InAccountRestore of the database - /// - /// - /// It is an optional property. - /// A valid value should have both RestoreSource and RestoreTimestampInUtc - /// - [JsonProperty(PropertyName = Constants.Properties.RestoreParams, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal InAccountRestoreParameters RestoreParameters - { - get - { - if (this.restoreParameters == null) - { - this.restoreParameters = base.GetObject(Constants.Properties.RestoreParams); - } - - return this.restoreParameters; - } - set - { - this.restoreParameters = value; - base.SetObject(Constants.Properties.RestoreParams, value); - } - } - - internal override void Validate() - { - base.Validate(); - } - - internal override void OnSave() - { - if (this.restoreParameters != null) - { - this.restoreParameters.OnSave(); - base.SetObject(Constants.Properties.RestoreParams, this.restoreParameters); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents a database in the Azure Cosmos DB account. + /// + /// + /// Each Azure Cosmos DB database account can have zero or more databases. A database in Azure Cosmos DB is a logical container for + /// document collections and users. + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#databases for more details on databases. + /// + /// + /// The example below creates a new Database with an Id property of 'MyDatabase'. + /// + /// + /// + /// + /// + /// The example below creates a collection within this database with OfferThroughput set to 10000. + /// + /// + /// + /// + /// + /// The example below queries for a Database by Id to retrieve the SelfLink. + /// + /// d.Id == "MyDatabase").AsEnumerable().FirstOrDefault(); + /// string databaseLink = database.SelfLink; + /// ]]> + /// + /// + /// + /// The example below deletes the database using its SelfLink property. + /// + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Database : Resource + { + private InAccountRestoreParameters restoreParameters; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public Database() + { + + } + + /// + /// Gets the self-link for collections from the Azure Cosmos DB service. + /// + /// + /// The self-link for collections in the database. + /// + /// + /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. + /// For collections, this takes the form of; + /// /dbs/db_rid/colls/ where db_rid represents the value of the database's resource id. + /// A resource id is not the id given to a database on creation, but an internally generated immutable id. + /// + [JsonProperty(PropertyName = Constants.Properties.CollectionsLink)] + public string CollectionsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.CollectionsLink); + } + } + + /// + /// Gets the self-link for users from the Azure Cosmos DB service. + /// + /// + /// The self-link for users in the database. + /// + /// + /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. + /// For users, this takes the form of; + /// /dbs/db_rid/users/ where db_rid represents the value of the database's resource id. + /// A resource id is not the id given to a database on creation, but an internally generated immutable id. + /// + [JsonProperty(PropertyName = Constants.Properties.UsersLink)] + public string UsersLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.UsersLink); + } + } + + /// + /// Gets the self-link for user defined types from the Azure Cosmos DB service. + /// + /// + /// The self-link for user defined types in the database. + /// + /// + /// Every Azure Cosmos DB resource has a static, immutable, addressable URI. + /// For user defined types, this takes the form of; + /// /dbs/db_rid/udts/ where db_rid represents the value of the database's resource id. + /// A resource id is not the id given to a database on creation, but an internally generated immutable id. + /// + internal string UserDefinedTypesLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + Paths.UserDefinedTypesPathSegment + "/"; + } + } + + /// + /// Gets or sets the for triggering the InAccountRestore of the database + /// + /// + /// It is an optional property. + /// A valid value should be Default or Restore + /// + [JsonProperty(PropertyName = Constants.Properties.CreateMode, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal DatabaseOrCollectionCreateMode? CreateMode + { + get + { + return base.GetValue(Constants.Properties.CreateMode, null); + } + set + { + base.SetValue(Constants.Properties.CreateMode, value.ToString()); + } + } + + /// + /// Gets or sets the for triggering the InAccountRestore of the database + /// + /// + /// It is an optional property. + /// A valid value should have both RestoreSource and RestoreTimestampInUtc + /// + [JsonProperty(PropertyName = Constants.Properties.RestoreParams, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal InAccountRestoreParameters RestoreParameters + { + get + { + if (this.restoreParameters == null) + { + this.restoreParameters = base.GetObject(Constants.Properties.RestoreParams); + } + + return this.restoreParameters; + } + set + { + this.restoreParameters = value; + base.SetObject(Constants.Properties.RestoreParams, value); + } + } + + internal override void Validate() + { + base.Validate(); + } + + internal override void OnSave() + { + if (this.restoreParameters != null) + { + this.restoreParameters.OnSave(); + base.SetObject(Constants.Properties.RestoreParams, this.restoreParameters); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DatabaseOrCollectionCreateMode.cs b/Microsoft.Azure.Cosmos/src/direct/DatabaseOrCollectionCreateMode.cs index 602b5f12ef..24eedbc3a9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DatabaseOrCollectionCreateMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DatabaseOrCollectionCreateMode.cs @@ -1,12 +1,12 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum DatabaseOrCollectionCreateMode - { - Default, - Restore - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum DatabaseOrCollectionCreateMode + { + Default, + Restore + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DefaultTrace.cs b/Microsoft.Azure.Cosmos/src/direct/DefaultTrace.cs index 81aca07371..9e4d3379d8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DefaultTrace.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DefaultTrace.cs @@ -1,178 +1,178 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Core.Trace -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - using System.Runtime.InteropServices; - - internal static class DefaultTrace - { - public static readonly Guid ProviderId = new Guid("{B30ABF1C-6A50-4F2B-85C4-61823ED6CF24}"); - - private static TraceSource TraceSourceInternal; - - private static bool IsListenerAdded; - - static DefaultTrace() - { - // From MSDN: http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.usegloballock%28v=vs.110%29.aspx - // The global lock is always used if the trace listener is not thread safe, - // regardless of the value of UseGlobalLock. The IsThreadSafe property is used to determine - // if the listener is thread safe. The global lock is not used only if the value of - // UseGlobalLock is false and the value of IsThreadSafe is true. - // The default behavior is to use the global lock. - System.Diagnostics.Trace.UseGlobalLock = false; - - DefaultTrace.TraceSourceInternal = new TraceSource("DocDBTrace"); - - // The DefaultTraceListener can cause lock contention which leads to request failures. - // Remove the DefaultTraceListener unless a debugger is attached. - DefaultTrace.RemoveDefaultTraceListener(); - } - - public static TraceSource TraceSource - { - get { return DefaultTrace.TraceSourceInternal; } - set { DefaultTrace.TraceSourceInternal = value; } - } - - /// - /// Only client need to init this listener. - /// - public static void InitEventListener() - { - if (DefaultTrace.IsListenerAdded) - { - return; - } - - DefaultTrace.IsListenerAdded = true; - -#if !NETSTANDARD16 - SourceSwitch sourceSwitch = new SourceSwitch("ClientSwitch", "Information"); - DefaultTrace.TraceSourceInternal.Switch = sourceSwitch; - -#if !COSMOSCLIENT -#if NETSTANDARD2_0 - // ETW is a Windows-only feature. - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return; - } - - TraceListener listener = new EtwTraceListener(DefaultTrace.ProviderId, "DocDBClientListener"); -#else - TraceListener listener = new System.Diagnostics.Eventing.EventProviderTraceListener(DefaultTrace.ProviderId.ToString(), "DocDBClientListener", "::"); - - DefaultTrace.TraceSourceInternal.Listeners.Add(listener); -#endif // NETSTANDARD2_0 -#endif // !COSMOSCLIENT -#endif // NETSTANDARD16 - } - - public static void Flush() - { - DefaultTrace.TraceSource.Flush(); - } - - public static void TraceVerbose(string message) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Verbose, 0, message); - } - - public static void TraceVerbose(string format, params object[] args) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, args); - } - - public static void TraceInformation(string message) - { - DefaultTrace.TraceSource.TraceInformation(message); - } - - public static void TraceInformation(string format, params object[] args) - { - DefaultTrace.TraceSource.TraceInformation(format, args); - } - - public static void TraceWarning(string message) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Warning, 0, message); - } - - public static void TraceWarning(string format, params object[] args) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Warning, 0, format, args); - } - - public static void TraceError(string message) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Error, 0, message); - } - - public static void TraceError(string format, params object[] args) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Error, 0, format, args); - } - - public static void TraceCritical(string message) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Critical, 0, message); - } - - public static void TraceCritical(string format, params object[] args) - { - DefaultTrace.TraceSource.TraceEvent(TraceEventType.Critical, 0, format, args); - } - - /// - /// Removes the DefaultTraceListener which causes locking issues - /// - public static void RemoveDefaultTraceListener() - { - if (Debugger.IsAttached) - { - return; - } - - if (DefaultTrace.TraceSource.Listeners.Count > 0) - { - List removeDefaultTraceListeners = new List(); - foreach (object traceListenerObject in DefaultTrace.TraceSource.Listeners) - { - if (traceListenerObject is DefaultTraceListener defaultTraceListener) - { - removeDefaultTraceListeners.Add(defaultTraceListener); - } - } - - // Remove all the default trace listeners - foreach (DefaultTraceListener defaultTraceListener in removeDefaultTraceListeners) - { - DefaultTrace.TraceSource.Listeners.Remove(defaultTraceListener); - } - } - } - - /// - /// Emit a trace for a set of metric values. - /// This is intended to be used next to MDM metrics - /// Details: - /// Produce a semi-typed trace format as a pipe delimited list of metrics values. - /// 'TraceMetrics' prefix provides a search term for indexing. - /// 'name' is an identifier to correlate to call site - /// Example: TraceMetric|LogServicePoolInfo|0|123|1. - /// - /// metric name. - /// sequence of values to be emitted in the trace. - internal static void TraceMetrics(string name, params object[] values) - { - DefaultTrace.TraceInformation(string.Join("|", new object[] { "TraceMetrics", name }.Concat(values))); - } - } -} +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Core.Trace +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + using System.Runtime.InteropServices; + + internal static class DefaultTrace + { + public static readonly Guid ProviderId = new Guid("{B30ABF1C-6A50-4F2B-85C4-61823ED6CF24}"); + + private static TraceSource TraceSourceInternal; + + private static bool IsListenerAdded; + + static DefaultTrace() + { + // From MSDN: http://msdn.microsoft.com/en-us/library/system.diagnostics.trace.usegloballock%28v=vs.110%29.aspx + // The global lock is always used if the trace listener is not thread safe, + // regardless of the value of UseGlobalLock. The IsThreadSafe property is used to determine + // if the listener is thread safe. The global lock is not used only if the value of + // UseGlobalLock is false and the value of IsThreadSafe is true. + // The default behavior is to use the global lock. + System.Diagnostics.Trace.UseGlobalLock = false; + + DefaultTrace.TraceSourceInternal = new TraceSource("DocDBTrace"); + + // The DefaultTraceListener can cause lock contention which leads to request failures. + // Remove the DefaultTraceListener unless a debugger is attached. + DefaultTrace.RemoveDefaultTraceListener(); + } + + public static TraceSource TraceSource + { + get { return DefaultTrace.TraceSourceInternal; } + set { DefaultTrace.TraceSourceInternal = value; } + } + + /// + /// Only client need to init this listener. + /// + public static void InitEventListener() + { + if (DefaultTrace.IsListenerAdded) + { + return; + } + + DefaultTrace.IsListenerAdded = true; + +#if !NETSTANDARD16 + SourceSwitch sourceSwitch = new SourceSwitch("ClientSwitch", "Information"); + DefaultTrace.TraceSourceInternal.Switch = sourceSwitch; + +#if !COSMOSCLIENT +#if NETSTANDARD2_0 + // ETW is a Windows-only feature. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + TraceListener listener = new EtwTraceListener(DefaultTrace.ProviderId, "DocDBClientListener"); +#else + TraceListener listener = new System.Diagnostics.Eventing.EventProviderTraceListener(DefaultTrace.ProviderId.ToString(), "DocDBClientListener", "::"); + + DefaultTrace.TraceSourceInternal.Listeners.Add(listener); +#endif // NETSTANDARD2_0 +#endif // !COSMOSCLIENT +#endif // NETSTANDARD16 + } + + public static void Flush() + { + DefaultTrace.TraceSource.Flush(); + } + + public static void TraceVerbose(string message) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Verbose, 0, message); + } + + public static void TraceVerbose(string format, params object[] args) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Verbose, 0, format, args); + } + + public static void TraceInformation(string message) + { + DefaultTrace.TraceSource.TraceInformation(message); + } + + public static void TraceInformation(string format, params object[] args) + { + DefaultTrace.TraceSource.TraceInformation(format, args); + } + + public static void TraceWarning(string message) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Warning, 0, message); + } + + public static void TraceWarning(string format, params object[] args) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Warning, 0, format, args); + } + + public static void TraceError(string message) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Error, 0, message); + } + + public static void TraceError(string format, params object[] args) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Error, 0, format, args); + } + + public static void TraceCritical(string message) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Critical, 0, message); + } + + public static void TraceCritical(string format, params object[] args) + { + DefaultTrace.TraceSource.TraceEvent(TraceEventType.Critical, 0, format, args); + } + + /// + /// Removes the DefaultTraceListener which causes locking issues. + /// + public static void RemoveDefaultTraceListener() + { + if (Debugger.IsAttached) + { + return; + } + + if (DefaultTrace.TraceSource.Listeners.Count > 0) + { + List removeDefaultTraceListeners = new List(); + foreach (object traceListenerObject in DefaultTrace.TraceSource.Listeners) + { + if (traceListenerObject is DefaultTraceListener defaultTraceListener) + { + removeDefaultTraceListeners.Add(defaultTraceListener); + } + } + + // Remove all the default trace listeners + foreach (DefaultTraceListener defaultTraceListener in removeDefaultTraceListeners) + { + DefaultTrace.TraceSource.Listeners.Remove(defaultTraceListener); + } + } + } + + /// + /// Emit a trace for a set of metric values. + /// This is intended to be used next to MDM metrics + /// Details: + /// Produce a semi-typed trace format as a pipe delimited list of metrics values. + /// 'TraceMetrics' prefix provides a search term for indexing. + /// 'name' is an identifier to correlate to call site + /// Example: TraceMetric|LogServicePoolInfo|0|123|1. + /// + /// metric name. + /// sequence of values to be emitted in the trace. + internal static void TraceMetrics(string name, params object[] values) + { + DefaultTrace.TraceInformation(string.Join("|", new object[] { "TraceMetrics", name }.Concat(values))); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DefaultTraceEx.cs b/Microsoft.Azure.Cosmos/src/direct/DefaultTraceEx.cs index baa0bef935..8b633463a7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DefaultTraceEx.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DefaultTraceEx.cs @@ -1,65 +1,65 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Common -{ - using System; - using System.Net.Sockets; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal static class DefaultTraceEx - { - public static void TraceException(Exception e) - { - AggregateException aggregateException = e as AggregateException; - if (aggregateException != null) - { - foreach (Exception exception in aggregateException.InnerExceptions) - { - DefaultTraceEx.TraceExceptionInternal(exception); - } - } - else - { - DefaultTraceEx.TraceExceptionInternal(e); - } - } - - private static void TraceExceptionInternal(Exception e) - { - while (e != null) - { - Uri requestUri = null; - DocumentClientException docClientException = e as DocumentClientException; - if (docClientException != null) - { - requestUri = docClientException.RequestUri; - } - - SocketException socketException = e as SocketException; - if (socketException != null) - { - DefaultTrace.TraceWarning( - "Exception {0}: RequesteUri: {1}, SocketErrorCode: {2}, {3}, {4}", - e.GetType(), - requestUri, - socketException.SocketErrorCode, - e.Message, - e.StackTrace); - } - else - { - DefaultTrace.TraceWarning( - "Exception {0}: RequestUri: {1}, {2}, {3}", - e.GetType(), - requestUri, - e.Message, - e.StackTrace); - } - - e = e.InnerException; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Common +{ + using System; + using System.Net.Sockets; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal static class DefaultTraceEx + { + public static void TraceException(Exception e) + { + AggregateException aggregateException = e as AggregateException; + if (aggregateException != null) + { + foreach (Exception exception in aggregateException.InnerExceptions) + { + DefaultTraceEx.TraceExceptionInternal(exception); + } + } + else + { + DefaultTraceEx.TraceExceptionInternal(e); + } + } + + private static void TraceExceptionInternal(Exception e) + { + while (e != null) + { + Uri requestUri = null; + DocumentClientException docClientException = e as DocumentClientException; + if (docClientException != null) + { + requestUri = docClientException.RequestUri; + } + + SocketException socketException = e as SocketException; + if (socketException != null) + { + DefaultTrace.TraceWarning( + "Exception {0}: RequesteUri: {1}, SocketErrorCode: {2}, {3}, {4}", + e.GetType(), + requestUri, + socketException.SocketErrorCode, + e.Message, + e.StackTrace); + } + else + { + DefaultTrace.TraceWarning( + "Exception {0}: RequestUri: {1}, {2}, {3}", + e.GetType(), + requestUri, + e.Message, + e.StackTrace); + } + + e = e.InnerException; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DictionaryNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/DictionaryNameValueCollection.cs index d5927e4090..a594d2fc4f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DictionaryNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DictionaryNameValueCollection.cs @@ -1,384 +1,384 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Collections -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Specialized; - - internal sealed class DictionaryNameValueCollection: INameValueCollection - { - private static StringComparer defaultStringComparer = StringComparer.OrdinalIgnoreCase; - private readonly Dictionary dictionary; - private CompositeValue nullValue; - - // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. - // However, there are a few public API with NameValueCollection as return type, e.g. DocumentServiceResponse.ResponseHeaders and - // DocumentClientException.ResponseHeaders. - // - // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create - // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is - // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. - // - // Therefore, we want to keep the NameValueCollection consistent within the ResponseHeaders APIs call. In other words, - // once invoked, the ResponseHeaders will return the same NameValueCollection. - private NameValueCollection nvc = null; - - public DictionaryNameValueCollection() - { - this.dictionary = new Dictionary(defaultStringComparer); - } - - public DictionaryNameValueCollection(StringComparer comparer) - { - this.dictionary = new Dictionary(comparer); - } - - public DictionaryNameValueCollection(int capacity) : this(capacity, defaultStringComparer) { } - - private DictionaryNameValueCollection(int capacity, StringComparer comparer) - { - this.dictionary = new Dictionary(capacity, comparer == null ? defaultStringComparer : comparer); - } - - public DictionaryNameValueCollection(INameValueCollection c) : this(c.Count()) - { - if (c == null) - { - throw new ArgumentNullException(nameof(c)); - } - - this.Add(c); - } - - public DictionaryNameValueCollection(NameValueCollection c) : this(c.Count) - { - if (c == null) - { - throw new ArgumentNullException(nameof(c)); - } - - foreach (string key in c) - { - string[] values = c.GetValues(key); - if (values != null) - { - foreach (string value in values) - { - this.Add(key, value); - } - } - else - { - this.Add(key, null); - } - } - } - - public void Add(string key, string value) - { - if (key == null) - { - CompositeValue nullValueSnapshot; - if ((nullValueSnapshot = this.nullValue) == null) - { - this.nullValue = new CompositeValue(value); - } - else - { - nullValueSnapshot.Add(value); - } - return; - } - - CompositeValue compositeValue; - this.dictionary.TryGetValue(key, out compositeValue); - if (compositeValue != null) - { - compositeValue.Add(value); - } - else - { - this.dictionary.Add(key, new CompositeValue(value)); - } - } - - public void Add(INameValueCollection c) - { - if (c == null) - { - throw new ArgumentNullException(nameof(c)); - } - - DictionaryNameValueCollection dictionaryNvc = c as DictionaryNameValueCollection; - if (dictionaryNvc != null) - { - foreach (string key in dictionaryNvc.dictionary.Keys) - { - if (!this.dictionary.ContainsKey(key)) - { - this.dictionary[key] = new CompositeValue(); - } - this.dictionary[key].Add(dictionaryNvc.dictionary[key]); - } - - CompositeValue dictionaryNvcNullValueSnapshot; - if ((dictionaryNvcNullValueSnapshot = dictionaryNvc.nullValue) != null) - { - CompositeValue thisNullValueSnapshot; - if ((thisNullValueSnapshot = this.nullValue) == null) - { - thisNullValueSnapshot = this.nullValue = new CompositeValue(); - } - thisNullValueSnapshot.Add(dictionaryNvcNullValueSnapshot); - } - } - else - { - foreach (string key in c) - { - foreach (string value in c.GetValues(key)) - { - this.Add(key, value); - } - } - } - } - - public void Set(string key, string value) - { - if (key == null) - { - CompositeValue nullValueSnapshot; - if ((nullValueSnapshot = this.nullValue) == null) - { - this.nullValue = new CompositeValue(value); - } else - { - nullValueSnapshot.Reset(value); - } - return; - } - - CompositeValue compositeValue; - this.dictionary.TryGetValue(key, out compositeValue); - if (compositeValue != null) - { - compositeValue.Reset(value); - } - else - { - this.dictionary.Add(key, new CompositeValue(value)); - } - } - - public string Get(string key) - { - CompositeValue value = null; - if (key == null) - { - value = nullValue; - } - else - { - this.dictionary.TryGetValue(key, out value); - } - - return value == null ? null : value.Value; - } - - public string[] GetValues(string key) - { - CompositeValue value = null; - if (key == null) - { - value = nullValue; - } - else - { - this.dictionary.TryGetValue(key, out value); - } - - return value == null ? null : value.Values; - } - - public void Remove(string key) - { - if (key == null) - { - nullValue = null; - } - else - { - this.dictionary.Remove(key); - } - } - - public void Clear() - { - nullValue = null; - this.dictionary.Clear(); - } - - public IEnumerable Keys - { - get - { - foreach (string key in this.dictionary.Keys) - { - yield return key; - } - if (nullValue != null) - { - yield return null; - } - } - } - - public int Count() - { - return this.dictionary.Count + (nullValue != null ? 1 : 0); - } - - public string this[string key] - { - get - { - return this.Get(key); - } - set - { - this.Set(key, value); - } - } - - public IEnumerator GetEnumerator() - { - return this.Keys.GetEnumerator(); - } - - public INameValueCollection Clone() - { - return new DictionaryNameValueCollection(this); - } - - public string[] AllKeys() - { - string[] keys = new string[this.Count()]; - int keyIndex = 0; - foreach (string key in this.dictionary.Keys) - { - keys[keyIndex++] = key; - } - if (this.nullValue != null) - { - keys[keyIndex++] = null; - } - return keys; - } - - IEnumerable INameValueCollection.Keys() - { - return this.Keys; - } - - public NameValueCollection ToNameValueCollection() - { - if (this.nvc == null) - { - lock (this) - { - if (this.nvc == null) - { - this.nvc = new NameValueCollection(this.dictionary.Count, (StringComparer)this.dictionary.Comparer); - foreach (string key in this) - { - string[] values = this.GetValues(key); - if (values == null) - { - this.nvc.Add(key, null); - } - else - { - foreach (string value in this.GetValues(key)) - { - this.nvc.Add(key, value); - } - } - } - } - } - } - return this.nvc; - } - - /// - /// This class represent the value of the key-value entry. - /// It can represent a null value as well as multiple values for a single key. - /// - private class CompositeValue - { - private List values; - - internal CompositeValue() - { - this.values = new List(); - } - - private static string Convert(List values) - { - return string.Join(",", values); - } - - public CompositeValue(string value) : this() - { - this.Add(value); - } - - public void Add(string value) - { - if (value == null) - { - return; - } - - this.values.Add(value); - } - - public void Reset(string value) - { - this.values.Clear(); - - this.Add(value); - } - - public string[] Values - { - get - { - return this.values.Count > 0 ? - this.values.ToArray() : - null; - } - } - - public string Value - { - get - { - return this.values.Count > 0 ? - Convert(this.values) : - null; - } - } - - public void Add(CompositeValue cv) - { - this.values.AddRange(cv.values); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Collections +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + + internal sealed class DictionaryNameValueCollection: INameValueCollection + { + private static StringComparer defaultStringComparer = StringComparer.OrdinalIgnoreCase; + private readonly Dictionary dictionary; + private CompositeValue nullValue; + + // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. + // However, there are a few public API with NameValueCollection as return type, e.g. DocumentServiceResponse.ResponseHeaders and + // DocumentClientException.ResponseHeaders. + // + // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create + // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is + // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. + // + // Therefore, we want to keep the NameValueCollection consistent within the ResponseHeaders APIs call. In other words, + // once invoked, the ResponseHeaders will return the same NameValueCollection. + private NameValueCollection nvc = null; + + public DictionaryNameValueCollection() + { + this.dictionary = new Dictionary(defaultStringComparer); + } + + public DictionaryNameValueCollection(StringComparer comparer) + { + this.dictionary = new Dictionary(comparer); + } + + public DictionaryNameValueCollection(int capacity) : this(capacity, defaultStringComparer) { } + + private DictionaryNameValueCollection(int capacity, StringComparer comparer) + { + this.dictionary = new Dictionary(capacity, comparer == null ? defaultStringComparer : comparer); + } + + public DictionaryNameValueCollection(INameValueCollection c) : this(c.Count()) + { + if (c == null) + { + throw new ArgumentNullException(nameof(c)); + } + + this.Add(c); + } + + public DictionaryNameValueCollection(NameValueCollection c) : this(c.Count) + { + if (c == null) + { + throw new ArgumentNullException(nameof(c)); + } + + foreach (string key in c) + { + string[] values = c.GetValues(key); + if (values != null) + { + foreach (string value in values) + { + this.Add(key, value); + } + } + else + { + this.Add(key, null); + } + } + } + + public void Add(string key, string value) + { + if (key == null) + { + CompositeValue nullValueSnapshot; + if ((nullValueSnapshot = this.nullValue) == null) + { + this.nullValue = new CompositeValue(value); + } + else + { + nullValueSnapshot.Add(value); + } + return; + } + + CompositeValue compositeValue; + this.dictionary.TryGetValue(key, out compositeValue); + if (compositeValue != null) + { + compositeValue.Add(value); + } + else + { + this.dictionary.Add(key, new CompositeValue(value)); + } + } + + public void Add(INameValueCollection c) + { + if (c == null) + { + throw new ArgumentNullException(nameof(c)); + } + + DictionaryNameValueCollection dictionaryNvc = c as DictionaryNameValueCollection; + if (dictionaryNvc != null) + { + foreach (string key in dictionaryNvc.dictionary.Keys) + { + if (!this.dictionary.ContainsKey(key)) + { + this.dictionary[key] = new CompositeValue(); + } + this.dictionary[key].Add(dictionaryNvc.dictionary[key]); + } + + CompositeValue dictionaryNvcNullValueSnapshot; + if ((dictionaryNvcNullValueSnapshot = dictionaryNvc.nullValue) != null) + { + CompositeValue thisNullValueSnapshot; + if ((thisNullValueSnapshot = this.nullValue) == null) + { + thisNullValueSnapshot = this.nullValue = new CompositeValue(); + } + thisNullValueSnapshot.Add(dictionaryNvcNullValueSnapshot); + } + } + else + { + foreach (string key in c) + { + foreach (string value in c.GetValues(key)) + { + this.Add(key, value); + } + } + } + } + + public void Set(string key, string value) + { + if (key == null) + { + CompositeValue nullValueSnapshot; + if ((nullValueSnapshot = this.nullValue) == null) + { + this.nullValue = new CompositeValue(value); + } else + { + nullValueSnapshot.Reset(value); + } + return; + } + + CompositeValue compositeValue; + this.dictionary.TryGetValue(key, out compositeValue); + if (compositeValue != null) + { + compositeValue.Reset(value); + } + else + { + this.dictionary.Add(key, new CompositeValue(value)); + } + } + + public string Get(string key) + { + CompositeValue value = null; + if (key == null) + { + value = nullValue; + } + else + { + this.dictionary.TryGetValue(key, out value); + } + + return value == null ? null : value.Value; + } + + public string[] GetValues(string key) + { + CompositeValue value = null; + if (key == null) + { + value = nullValue; + } + else + { + this.dictionary.TryGetValue(key, out value); + } + + return value == null ? null : value.Values; + } + + public void Remove(string key) + { + if (key == null) + { + nullValue = null; + } + else + { + this.dictionary.Remove(key); + } + } + + public void Clear() + { + nullValue = null; + this.dictionary.Clear(); + } + + public IEnumerable Keys + { + get + { + foreach (string key in this.dictionary.Keys) + { + yield return key; + } + if (nullValue != null) + { + yield return null; + } + } + } + + public int Count() + { + return this.dictionary.Count + (nullValue != null ? 1 : 0); + } + + public string this[string key] + { + get + { + return this.Get(key); + } + set + { + this.Set(key, value); + } + } + + public IEnumerator GetEnumerator() + { + return this.Keys.GetEnumerator(); + } + + public INameValueCollection Clone() + { + return new DictionaryNameValueCollection(this); + } + + public string[] AllKeys() + { + string[] keys = new string[this.Count()]; + int keyIndex = 0; + foreach (string key in this.dictionary.Keys) + { + keys[keyIndex++] = key; + } + if (this.nullValue != null) + { + keys[keyIndex++] = null; + } + return keys; + } + + IEnumerable INameValueCollection.Keys() + { + return this.Keys; + } + + public NameValueCollection ToNameValueCollection() + { + if (this.nvc == null) + { + lock (this) + { + if (this.nvc == null) + { + this.nvc = new NameValueCollection(this.dictionary.Count, (StringComparer)this.dictionary.Comparer); + foreach (string key in this) + { + string[] values = this.GetValues(key); + if (values == null) + { + this.nvc.Add(key, null); + } + else + { + foreach (string value in this.GetValues(key)) + { + this.nvc.Add(key, value); + } + } + } + } + } + } + return this.nvc; + } + + /// + /// This class represent the value of the key-value entry. + /// It can represent a null value as well as multiple values for a single key. + /// + private class CompositeValue + { + private List values; + + internal CompositeValue() + { + this.values = new List(); + } + + private static string Convert(List values) + { + return string.Join(",", values); + } + + public CompositeValue(string value) : this() + { + this.Add(value); + } + + public void Add(string value) + { + if (value == null) + { + return; + } + + this.values.Add(value); + } + + public void Reset(string value) + { + this.values.Clear(); + + this.Add(value); + } + + public string[] Values + { + get + { + return this.values.Count > 0 ? + this.values.ToArray() : + null; + } + } + + public string Value + { + get + { + return this.values.Count > 0 ? + Convert(this.values) : + null; + } + } + + public void Add(CompositeValue cv) + { + this.values.AddRange(cv.values); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs b/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs index b967f05545..d1f89d6dc2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs @@ -1,1178 +1,1187 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.IO; - using System.Net; - using System.Net.Security; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.FaultInjection; -#if COSMOSCLIENT - using Microsoft.Azure.Cosmos.Rntbd; -#endif - -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - // Dispatcher encapsulates the state and logic needed to dispatch multiple requests through - // a single connection. - internal sealed class Dispatcher : IDisposable - { - // Connection is thread-safe for sending. - // Receiving is done only from the receive loop. - // Initialization and disposal are not thread safe. Guard these - // operations with connectionLock. - private readonly Connection connection; - private readonly UserAgentContainer userAgent; - private readonly Uri serverUri; - private readonly IConnectionStateListener connectionStateListener; - // All individual operations on CancellationTokenSource are thread safe. - // When examining IsCancellationRequested in order to decide whether to cancel, - // guard the operation with connectionLock. - private readonly CancellationTokenSource cancellation = new CancellationTokenSource(); - private readonly TimerPool idleTimerPool; - private readonly bool enableChannelMultiplexing; - - private bool disposed = false; - - private ServerProperties serverProperties = null; - - private int nextRequestId = 0; - - // Acquire after connectionLock. - private readonly object callLock = new object(); - private Task receiveTask = null; // Guarded by callLock. - // Guarded by callLock. - private readonly Dictionary calls = new Dictionary(); - - // Guarded by callLock. - // The call map can become frozen if the underlying connection becomes - // unusable. This can happen if initialization fails, either the send - // stream or the receive stream are broken, the receive loop fails etc. - private bool callsAllowed = true; - - // lock used to guard underlying tcp connection state, which is a state level higher than callLock - // Acquire before callLock - private readonly object connectionLock = new object(); - private PooledTimer idleTimer; // Guarded by connectionLock - private Task idleTimerTask; // Guarded by connectionLock - - private readonly IChaosInterceptor chaosInterceptor; - private TransportException faultInjectionTransportException; - private bool isFaultInjectionedConnectionError; - - public Guid ConnectionCorrelationId { get => this.connection.ConnectionCorrelationId; } - - public Dispatcher( - Uri serverUri, - UserAgentContainer userAgent, - IConnectionStateListener connectionStateListener, - string hostNameCertificateOverride, - TimeSpan receiveHangDetectionTime, - TimeSpan sendHangDetectionTime, - TimerPool idleTimerPool, - TimeSpan idleTimeout, - bool enableChannelMultiplexing, - MemoryStreamPool memoryStreamPool, - RemoteCertificateValidationCallback remoteCertificateValidationCallback, - Func> dnsResolutionFunction, - IChaosInterceptor chaosInterceptor) - { - this.connection = new Connection( - serverUri, hostNameCertificateOverride, - receiveHangDetectionTime, sendHangDetectionTime, - idleTimeout, - memoryStreamPool, - remoteCertificateValidationCallback, - dnsResolutionFunction); - this.userAgent = userAgent; - this.connectionStateListener = connectionStateListener; - this.serverUri = serverUri; - this.idleTimerPool = idleTimerPool; - this.enableChannelMultiplexing = enableChannelMultiplexing; - this.chaosInterceptor = chaosInterceptor; - } - - #region Test hook. - - internal event Action TestOnConnectionClosed; - internal bool TestIsIdle - { - get - { - lock (this.connectionLock) - { - if (this.connection.Disposed) - { - return true; - } - TimeSpan ignoredTimeToIdle; - return !this.connection.IsActive(out ignoredTimeToIdle); - } - } - } - - #endregion - - public bool Healthy - { - get - { - this.ThrowIfDisposed(); - - if (this.cancellation.IsCancellationRequested) - { - return false; - } - - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - if (!this.callsAllowed) - { - return false; - } - } - - bool healthy; - try - { - healthy = this.connection.Healthy; - } - catch (ObjectDisposedException) - { - // Connection.Healthy shouldn't be called while the connection is being disposed, or after. - // To avoid additional locking, handle the exception here and store the outcome. - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}] {1} ObjectDisposedException from Connection.Healthy", - this.ConnectionCorrelationId, this); - healthy = false; - } - - if (healthy) - { - return true; - } - - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - this.callsAllowed = false; - } - return false; - } - } - - public async Task OpenAsync(ChannelOpenArguments args) - { - this.ThrowIfDisposed(); - try - { - Debug.Assert(this.connection != null); - await this.connection.OpenAsync(args); - await this.NegotiateRntbdContextAsync(args); - - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - Debug.Assert(this.receiveTask == null); - // The background receive loop and its failure continuation - // task should use a task scheduler internal to the Cosmos DB - // client. In any case, they should avoid using the current - // task scheduler, because some components use task schedulers - // for accounting, others to control and suspend task execution. - // In these cases, it does not make sense for the current - // accounting entity to get charged for the background receive - // loop in perpetuity, and there's a risk the task might get - // suspended and never resumed. - this.receiveTask = Task.Factory.StartNew( - async delegate - { - await this.ReceiveLoopAsync(); - }, - this.cancellation.Token, - TaskCreationOptions.LongRunning | - TaskCreationOptions.DenyChildAttach, - TaskScheduler.Default).Unwrap(); - _ = this.receiveTask.ContinueWith(completedTask => - { - Debug.Assert(completedTask.IsFaulted); - Debug.Assert(this.serverUri != null); - Debug.Assert(completedTask.Exception != null); - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}] Dispatcher.ReceiveLoopAsync failed. Consuming the task " + - "exception asynchronously. Dispatcher: {1}. Exception: {2}", - this.ConnectionCorrelationId, this, completedTask.Exception?.InnerException); - }, - default(CancellationToken), - TaskContinuationOptions.OnlyOnFaulted, - TaskScheduler.Default); - } - - if (this.idleTimerPool != null) - { - // idle timeout is enabled - this.StartIdleTimer(); - } - } - catch (DocumentClientException) - { - this.DisallowInitialCalls(); - throw; - } - catch (TransportException) - { - this.DisallowInitialCalls(); - throw; - } - } - - public void InjectFaultInjectionConnectionError(TransportException transportException) - { - if (!this.disposed) - { - this.isFaultInjectionedConnectionError = true; - this.faultInjectionTransportException = transportException; - } - } - - public sealed class PrepareCallResult : IDisposable - { - private bool disposed = false; - - public PrepareCallResult(uint requestId, Uri uri, TransportSerialization.SerializedRequest serializedRequest) - { - this.RequestId = requestId; - this.Uri = uri; - this.SerializedRequest = serializedRequest; - } - - public uint RequestId { get; private set; } - - public TransportSerialization.SerializedRequest SerializedRequest { get; } - public Uri Uri { get; private set; } - - /// - public void Dispose() - { - if (!this.disposed) - { - this.SerializedRequest.Dispose(); - this.disposed = true; - } - } - } - - // PrepareCall assigns a request ID to the request, serializes it, and - // returns the result. The caller must treat PrepareCallResult as an - // opaque handle. - public PrepareCallResult PrepareCall(DocumentServiceRequest request, - TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, - Guid activityId, - TransportRequestStats transportRequestStats) - { - uint requestId = unchecked((uint) Interlocked.Increment(ref this.nextRequestId)); - string requestIdString = requestId.ToString(CultureInfo.InvariantCulture); - - int headerSize; - int? bodySize; - TransportSerialization.SerializedRequest serializedRequest = TransportSerialization.BuildRequest( - request, - physicalAddress.PathAndQuery, - resourceOperation, - activityId, - this.connection.BufferProvider, - requestIdString, - out headerSize, - out bodySize); - - transportRequestStats.RequestBodySizeInBytes = bodySize; - transportRequestStats.RequestSizeInBytes = serializedRequest.RequestSize; - - return new PrepareCallResult(requestId, physicalAddress.Uri, serializedRequest); - } - - public async Task CallAsync(ChannelCallArguments args, TransportRequestStats transportRequestStats) - { - this.ThrowIfDisposed(); - // The current task scheduler must be used for correctness and to - // track per tenant physical charges for the compute gateway. - using (CallInfo callInfo = new CallInfo( - this.ConnectionCorrelationId, - args.CommonArguments.ActivityId, - args.PreparedCall.Uri, - TaskScheduler.Current, - transportRequestStats)) - { - uint requestId = args.PreparedCall.RequestId; - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - transportRequestStats.NumberOfInflightRequestsInConnection = this.calls.Count; - if (!this.callsAllowed) - { - Debug.Assert(args.CommonArguments.UserPayload); - throw new TransportException( - TransportErrorCode.ChannelMultiplexerClosed, null, - args.CommonArguments.ActivityId, args.PreparedCall.Uri, - this.ToString(), args.CommonArguments.UserPayload, - args.CommonArguments.PayloadSent); - } - this.calls.Add(requestId, callInfo); - } - try - { - try - { - this.chaosInterceptor?.OnBeforeConnectionWrite(args); - if (this.chaosInterceptor != null && this.chaosInterceptor.OnRequestCall(args, out StoreResponse faultyResponse)) - { - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Sent); - return faultyResponse; - } - - await this.connection.WriteRequestAsync( - args.CommonArguments, - args.PreparedCall.SerializedRequest, - transportRequestStats); - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Sent); - this.chaosInterceptor?.OnAfterConnectionWrite(args); - - } - catch (Exception e) - { - callInfo.SendFailed(); - throw new TransportException( - TransportErrorCode.SendFailed, e, - args.CommonArguments.ActivityId, args.PreparedCall.Uri, - this.ToString(), args.CommonArguments.UserPayload, - args.CommonArguments.PayloadSent); - } - // Do not add any code after the end of the previous block. - // Anything that needs to execute before ReadResponseAsync must - // be in the try block, so that no exceptions are missed. - return await callInfo.ReadResponseAsync(args); - } - catch (DocumentClientException) - { - this.DisallowRuntimeCalls(); - throw; - } - catch (TransportException) - { - this.DisallowRuntimeCalls(); - throw; - } - finally - { - this.RemoveCall(requestId); - } - } - } - - /// - /// Cancels a Rntbd call and notifies the connection by incrementing the transit timeout counters. - /// - /// An instance of containing the call result. - /// A boolean flag indicating if the request is read only. - public void CancelCallAndNotifyConnectionOnTimeoutEvent( - PrepareCallResult preparedCall, - bool isReadOnly) - { - this.ThrowIfDisposed(); - this.connection.NotifyConnectionStatus( - isCompleted: true, - isReadRequest: isReadOnly); - - CallInfo call = this.RemoveCall(preparedCall.RequestId); - if (call != null) - { - call.Cancel(); - } - } - - /// - /// Notifies the connection on a successful event, by resetting the transit timeout counters. - /// - public void NotifyConnectionOnSuccessEvent() - { - this.ThrowIfDisposed(); - this.connection.NotifyConnectionStatus( - isCompleted: true); - } - - public override string ToString() - { - return this.connection.ToString(); - } - - public void Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - - DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] Disposing RNTBD Dispatcher {1}", this.ConnectionCorrelationId, this); - - Task idleTimerTaskCopy = null; - Debug.Assert(!Monitor.IsEntered(this.connectionLock)); - lock (this.connectionLock) - { - this.StartConnectionShutdown(); - idleTimerTaskCopy = this.StopIdleTimer(); - } - - this.WaitTask(idleTimerTaskCopy, "idle timer"); - - Task receiveTaskCopy = null; - Debug.Assert(!Monitor.IsEntered(this.connectionLock)); - lock (this.connectionLock) - { - Debug.Assert(this.idleTimer == null); - Debug.Assert(this.idleTimerTask == null); - - receiveTaskCopy = this.CloseConnection(); - } - - this.WaitTask(receiveTaskCopy, "receive loop"); - - DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD Dispatcher {1} is disposed", this.ConnectionCorrelationId, this); - } - - private void StartIdleTimer() - { - DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD idle connection monitor: Timer is starting...", this.ConnectionCorrelationId); - - TimeSpan timeToIdle = TimeSpan.MinValue; - bool scheduled = false; - try - { - Debug.Assert(!Monitor.IsEntered(this.connectionLock)); - lock (this.connectionLock) - { - bool active = this.connection.IsActive(out timeToIdle); - Debug.Assert(active); - if (!active) - { - // This would be rather unexpected. - DefaultTrace.TraceCritical("[RNTBD Dispatcher {0}][{1}] New connection already idle.", this.ConnectionCorrelationId, this); - return; - } - - this.ScheduleIdleTimer(timeToIdle); - scheduled = true; - } - } - finally - { - if (scheduled) - { - DefaultTrace.TraceInformation( - "[RNTBD Dispatcher {0}] RNTBD idle connection monitor {1}: Timer is scheduled to fire {2} seconds later at {3}.", - this.ConnectionCorrelationId, this, timeToIdle.TotalSeconds, DateTime.UtcNow + timeToIdle); - } - else - { - DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD idle connection monitor {1}: Timer is not scheduled.", this.ConnectionCorrelationId, this); - } - } - } - - private void OnIdleTimer(Task precedentTask) - { - Task receiveTaskCopy = null; - - Debug.Assert(!Monitor.IsEntered(this.connectionLock)); - lock (this.connectionLock) - { - if (this.cancellation.IsCancellationRequested) - { - return; - } - - Debug.Assert(!this.connection.Disposed); - TimeSpan timeToIdle; - bool active = this.connection.IsActive(out timeToIdle); - if (active) - { - this.ScheduleIdleTimer(timeToIdle); - return; - } - - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - if (this.calls.Count > 0) - { - DefaultTrace.TraceCritical( - "[RNTBD Dispatcher {0}][{1}] Looks idle but still has {2} pending requests", - this.ConnectionCorrelationId, this, this.calls.Count); - active = true; - } - else - { - this.callsAllowed = false; - } - } - - if (active) - { - this.ScheduleIdleTimer(timeToIdle); - return; - } - - this.idleTimer = null; - this.idleTimerTask = null; - - this.StartConnectionShutdown(); - receiveTaskCopy = this.CloseConnection(); - } - - this.WaitTask(receiveTaskCopy, "receive loop"); - } - - // this.connectionLock must be held. - private void ScheduleIdleTimer(TimeSpan timeToIdle) - { - Debug.Assert(Monitor.IsEntered(this.connectionLock)); - this.idleTimer = this.idleTimerPool.GetPooledTimer((int)timeToIdle.TotalSeconds); - this.idleTimerTask = this.idleTimer.StartTimerAsync().ContinueWith(this.OnIdleTimer, TaskContinuationOptions.OnlyOnRanToCompletion); - this.idleTimerTask.ContinueWith( - failedTask => - { - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}][{1}] Idle timer callback failed: {2}", - this.ConnectionCorrelationId, this, failedTask.Exception?.InnerException); - }, - TaskContinuationOptions.OnlyOnFaulted); - } - - // this.connectionLock must be held. - private void StartConnectionShutdown() - { - Debug.Assert(Monitor.IsEntered(this.connectionLock)); - if (this.cancellation.IsCancellationRequested) - { - return; - } - try - { - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - this.callsAllowed = false; - } - - this.cancellation.Cancel(); - } - catch (AggregateException e) - { - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}][{1}] Registered cancellation callbacks failed: {2}", - this.ConnectionCorrelationId, this, e); - // Deliberately ignoring the exception. - } - } - - // this.connectionLock must be held. - private Task StopIdleTimer() - { - Task idleTimerTaskCopy = null; - Debug.Assert(Monitor.IsEntered(this.connectionLock)); - if (this.idleTimer != null) - { - if (this.idleTimer.CancelTimer()) - { - // Dispose() won the race and the timer was cancelled. - this.idleTimer = null; - this.idleTimerTask = null; - } - else - { - idleTimerTaskCopy = this.idleTimerTask; - } - } - return idleTimerTaskCopy; - } - - // this.connectionLock must be held. - private Task CloseConnection() - { - Task receiveTaskCopy = null; - Debug.Assert(Monitor.IsEntered(this.connectionLock)); - if (!this.connection.Disposed) - { - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - receiveTaskCopy = this.receiveTask; - } - - this.connection.Dispose(); - this.TestOnConnectionClosed?.Invoke(); - } - return receiveTaskCopy; - } - - private void WaitTask(Task t, string description) - { - if (t == null) - { - return; - } - try - { - // Don't hold locks while blocking this thread - Debug.Assert(!Monitor.IsEntered(this.callLock)); - Debug.Assert(!Monitor.IsEntered(this.connectionLock)); - t.Wait(); - } - catch (Exception e) - { - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}][{1}] Parallel task failed: {2}. Exception: {3}", - this.ConnectionCorrelationId, this, description, e); - // Intentionally swallowing the exception. The caller can't - // do anything useful with it. - } - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - Debug.Assert(this.serverUri != null); - throw new ObjectDisposedException( - string.Format("{0}:{1}", nameof(Dispatcher), this.serverUri)); - } - } - - private async Task NegotiateRntbdContextAsync(ChannelOpenArguments args) - { - byte[] contextMessage = TransportSerialization.BuildContextRequest( - args.CommonArguments.ActivityId, this.userAgent, args.CallerId, this.enableChannelMultiplexing); - - await this.connection.WriteRequestAsync( - args.CommonArguments, - new TransportSerialization.SerializedRequest(new BufferProvider.DisposableBuffer(contextMessage), requestBody: null), - transportRequestStats: null); - - // Read the response. - using Connection.ResponseMetadata responseMd = - await this.connection.ReadResponseMetadataAsync(args.CommonArguments); - - // Full header and metadata are read now. Parse out more fields and handle them. - StatusCodes status = (StatusCodes) BitConverter.ToUInt32(responseMd.Header.Array, 4); - byte[] responseActivityIdBytes = new byte[16]; - Buffer.BlockCopy(responseMd.Header.Array, 8, responseActivityIdBytes, 0, 16); - // Server should just be echoing back the ActivityId from the connection request, but retrieve it - // from the wire and use it from here on, to be absolutely certain we have the same ActivityId - // the server is using - Guid activityId = new Guid(responseActivityIdBytes); - Trace.CorrelationManager.ActivityId = activityId; - - BytesDeserializer deserializer = new BytesDeserializer(responseMd.Metadata.Array, responseMd.Metadata.Count); - RntbdConstants.ConnectionContextResponse response = new RntbdConstants.ConnectionContextResponse(); - response.ParseFrom(ref deserializer); - string serverAgent = BytesSerializer.GetStringFromBytes(response.serverAgent.value.valueBytes); - string serverVersion = BytesSerializer.GetStringFromBytes(response.serverVersion.value.valueBytes); - Debug.Assert(this.serverProperties == null); - this.serverProperties = new ServerProperties(serverAgent, serverVersion); - - if ((UInt32)status < 200 || (UInt32)status >= 400) - { - Debug.Assert(args.CommonArguments.UserPayload == false); - - using (MemoryStream errorResponseStream = await this.connection.ReadResponseBodyAsync( - new ChannelCommonArguments(activityId, - TransportErrorCode.TransportNegotiationTimeout, - args.CommonArguments.UserPayload))) - { - Error error = Resource.LoadFrom(errorResponseStream); - - DocumentClientException exception = new DocumentClientException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - error.ToString()), - null, - (HttpStatusCode)status, - this.connection.ServerUri); - - if (response.clientVersion.isPresent) - { - exception.Headers.Add("RequiredClientVersion", - BytesSerializer.GetStringFromBytes(response.clientVersion.value.valueBytes)); - } - - if (response.protocolVersion.isPresent) - { - exception.Headers.Add("RequiredProtocolVersion", - response.protocolVersion.value.valueULong.ToString()); - } - - if (response.serverAgent.isPresent) - { - exception.Headers.Add("ServerAgent", - BytesSerializer.GetStringFromBytes(response.serverAgent.value.valueBytes)); - } - - if (response.serverVersion.isPresent) - { - exception.Headers.Add( - HttpConstants.HttpHeaders.ServerVersion, - BytesSerializer.GetStringFromBytes(response.serverVersion.value.valueBytes)); - } - - throw exception; - } - } - - this.NotifyConnectionOnSuccessEvent(); - args.OpenTimeline.RecordRntbdHandshakeFinishTime(); - } - - private async Task ReceiveLoopAsync() - { - CancellationToken cancellationToken = this.cancellation.Token; - ChannelCommonArguments args = new ChannelCommonArguments( - Guid.Empty, TransportErrorCode.ReceiveTimeout, true); - Connection.ResponseMetadata responseMd = null; - try - { - bool hasTransportErrors = false; - while (!hasTransportErrors && !cancellationToken.IsCancellationRequested) - { - if (this.isFaultInjectionedConnectionError) - { - hasTransportErrors = true; - throw this.faultInjectionTransportException; - } - - args.ActivityId = Guid.Empty; - responseMd = await this.connection.ReadResponseMetadataAsync(args); - ArraySegment metadata = responseMd.Metadata; - - TransportSerialization.RntbdHeader header = - TransportSerialization.DecodeRntbdHeader(responseMd.Header.Array); - - args.ActivityId = header.ActivityId; - BytesDeserializer deserializer = new BytesDeserializer(metadata.Array, metadata.Count); - - MemoryStream bodyStream = null; - if (HeadersTransportSerialization.TryParseMandatoryResponseHeaders(ref deserializer, out bool payloadPresent, out uint transportRequestId)) - { - if (payloadPresent) - { - bodyStream = await this.connection.ReadResponseBodyAsync(args); - } - this.DispatchRntbdResponse(responseMd, header, bodyStream, metadata.Array, metadata.Count, transportRequestId); - } - else - { - hasTransportErrors = true; - this.DispatchChannelFailureException(TransportExceptions.GetInternalServerErrorException(this.serverUri, RMResources.MissingRequiredHeader)); - } - - responseMd = null; - } - this.DispatchCancellation(); - } - catch (OperationCanceledException) - { - responseMd?.Dispose(); - this.DispatchCancellation(); - } - catch (ObjectDisposedException) - { - responseMd?.Dispose(); - this.DispatchCancellation(); - } - catch (Exception e) - { - responseMd?.Dispose(); - this.DispatchChannelFailureException(e); - } - -#if DEBUG - lock (this.callLock) - { - Debug.Assert(!this.callsAllowed); - Debug.Assert(this.calls.Count == 0); - } -#endif - } - - private Dictionary StopCalls() - { - Dictionary clonedCalls; - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - clonedCalls = new Dictionary(this.calls); - this.calls.Clear(); - this.callsAllowed = false; - } - return clonedCalls; - } - - private void DispatchRntbdResponse( - Connection.ResponseMetadata responseMd, - TransportSerialization.RntbdHeader responseHeader, - MemoryStream responseBody, - byte[] metadata, - int metadataLength, - uint transportRequestId) - { - CallInfo call = this.RemoveCall(transportRequestId); - if (call != null) - { - Debug.Assert(this.serverProperties != null); - Debug.Assert(this.serverProperties.Version != null); - call.TransportRequestStats.RecordState(TransportRequestStats.RequestStage.Received); - call.TransportRequestStats.ResponseMetadataSizeInBytes = responseMd.Metadata.Count; - call.TransportRequestStats.ResponseBodySizeInBytes = responseBody?.Length; - call.SetResponse(responseMd, responseHeader, responseBody, this.serverProperties.Version, metadata, metadataLength); - } - else - { - responseBody?.Dispose(); - responseMd.Dispose(); - } - } - - private void DispatchChannelFailureException(Exception ex) - { - Dictionary clonedCalls = this.StopCalls(); - foreach (KeyValuePair entry in clonedCalls) - { - CallInfo call = entry.Value; - Debug.Assert(call != null); - call.SetConnectionBrokenException(ex, this.ToString()); - } - - // If there are no pending calls on this channel and a subscriber is interested - // in connection events, examine the exception and raise the event appropriately. - if ((clonedCalls.Count > 0) || (this.connectionStateListener == null)) - { - // If any calls are pending, the event is unnecessary because callers will get - // TransportException. If this.connectionStateListener is null, the point is moot. - return; - } - TransportException transportException = ex as TransportException; - if (transportException == null) - { - // The client transport stack catches SocketException and IOException and wraps them - // in TransportException as appropriate. Other exception types may also be thrown. - // In some cases, it may be reasonable to catch those exceptions and wrap them in - // TransportException. - // In other cases, it may be reasonable to handle additional exception types here. - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}] Not a TransportException. Will not raise the connection state change event: {1}", - this.ConnectionCorrelationId, ex); - return; - } - - // Copy a bunch of values locally to avoid capturing the this pointer. - ConnectionEvent connectionEvent; - switch (transportException.ErrorCode) - { - case TransportErrorCode.ReceiveStreamClosed: - connectionEvent = ConnectionEvent.ReadEof; - break; - - case TransportErrorCode.ReceiveFailed: - connectionEvent = ConnectionEvent.ReadFailure; - break; - - default: - DefaultTrace.TraceWarning( - "[RNTBD Dispatcher {0}] Will not raise the connection state change event for TransportException error code {1}. Exception: {2}", - this.ConnectionCorrelationId, transportException.ErrorCode.ToString(), transportException.Message); - return; - } - IConnectionStateListener connectionStateListener = this.connectionStateListener; - ServerKey serverKey = new ServerKey(this.serverUri); - DateTime exceptionTime = transportException.Timestamp; - // Run the event handler asynchronously and catch all exceptions. - Task t = Task.Run(() => - { - connectionStateListener.OnConnectionEvent(connectionEvent, exceptionTime, serverKey); - }); - - t.ContinueWith(static (failedTask, connectionIdObject) => - { - DefaultTrace.TraceError("[RNTBD Dispatcher {0}] OnConnectionEvent callback failed: {1}", connectionIdObject, failedTask.Exception?.InnerException); - }, this.ConnectionCorrelationId, TaskContinuationOptions.OnlyOnFaulted); - } - - private void DispatchCancellation() - { - Dictionary clonedCalls = this.StopCalls(); - foreach (KeyValuePair entry in clonedCalls) - { - CallInfo call = entry.Value; - Debug.Assert(call != null); - call.Cancel(); - } - } - - private CallInfo RemoveCall(uint requestId) - { - Debug.Assert(!Monitor.IsEntered(this.callLock)); - CallInfo callInfo = null; - lock (this.callLock) - { - bool found = this.calls.TryGetValue(requestId, out callInfo); - bool removed = this.calls.Remove(requestId); - Debug.Assert(found == removed); - } - return callInfo; - } - - // The only difference between DisallowInitialCalls and - // DisallowRuntimeCalls is an extra debug assert. In debug mode, - // DisallowInitialCalls ensures nobody got in yet. - private void DisallowInitialCalls() - { - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - Debug.Assert(this.calls.Count == 0); - this.callsAllowed = false; - } - } - - private void DisallowRuntimeCalls() - { - Debug.Assert(!Monitor.IsEntered(this.callLock)); - lock (this.callLock) - { - this.callsAllowed = false; - } - } - - internal sealed class CallInfo : IDisposable - { - private readonly TaskCompletionSource completion = - new TaskCompletionSource(); - private readonly SemaphoreSlim sendComplete = - new SemaphoreSlim(0); - - private readonly Guid connectionCorrelationId; - private readonly Guid activityId; - private readonly Uri uri; - private readonly TaskScheduler scheduler; - - private bool disposed = false; - private readonly object stateLock = new object(); - private State state; - - public TransportRequestStats TransportRequestStats { get; } - - public CallInfo(Guid connectionCorrelationId, Guid activityId, Uri uri, TaskScheduler scheduler, TransportRequestStats transportRequestStats) - { - Debug.Assert(connectionCorrelationId != Guid.Empty); - Debug.Assert(activityId != Guid.Empty); - Debug.Assert(uri != null); - Debug.Assert(scheduler != null); - Debug.Assert(transportRequestStats != null); - - this.connectionCorrelationId = connectionCorrelationId; - this.activityId = activityId; - this.uri = uri; - this.scheduler = scheduler; - this.TransportRequestStats = transportRequestStats; - } - - public Task ReadResponseAsync(ChannelCallArguments args) - { - this.ThrowIfDisposed(); - // If execution got this far, sending the request succeeded. - this.CompleteSend(State.Sent); - args.CommonArguments.SetTimeoutCode( - TransportErrorCode.ReceiveTimeout); - return this.completion.Task; - } - - public void SendFailed() - { - this.ThrowIfDisposed(); - this.CompleteSend(State.SendFailed); - } - - public void SetResponse( - Connection.ResponseMetadata responseMd, - TransportSerialization.RntbdHeader responseHeader, - MemoryStream responseBody, - string serverVersion, - byte[] metadata, - int metadataLength) - { - this.ThrowIfDisposed(); - // Call SetResult asynchronously. Otherwise, the tasks awaiting on - // completionSource.Task will be continued on this thread. This is - // undesirable for both correctness reasons (it can lead to - // deadlock, because the receive task will not complete until this - // function returns, which may not happen if a continued task tries - // to dispose this object) and for performance reasons (SetResult - // needs to be fire-and-forget, not synchronous and sequential). - - // .NET Framework 4.6 introduces - // TaskCreationOptions.RunContinuationsAsynchronously. It should be - // used when it becomes available. - this.RunAsynchronously(() => - { - Trace.CorrelationManager.ActivityId = this.activityId; - try - { - BytesDeserializer bytesDeserializer = new BytesDeserializer(metadata, metadataLength); - StoreResponse storeResponse = TransportSerialization.MakeStoreResponse( - responseHeader.Status, - responseHeader.ActivityId, - responseBody, - serverVersion, - ref bytesDeserializer); - this.completion.SetResult(storeResponse); - } - catch (Exception e) - { - this.completion.SetException(e); - responseBody?.Dispose(); - } - finally - { - responseMd.Dispose(); - } - }); - } - - public void SetConnectionBrokenException(Exception inner, string sourceDescription) - { - this.ThrowIfDisposed(); - // Call SetException asynchronously. - this.RunAsynchronously( - async delegate - { - Trace.CorrelationManager.ActivityId = this.activityId; - // When an API caller sends a request, it can get two - // exceptions concurrently, one from the inline SendAsync - // call, and one from the background receive loop doing - // ReceiveAsync. Avoid setting an exception on the - // completion object if sending the request already - // failed. The exception is not necessary, and the - // unused completion would trigger - // UnobservedTaskException upon garbage collection. - await this.sendComplete.WaitAsync(); - lock (this.stateLock) - { - if (this.state != State.Sent) - { - return; - } - } - this.completion.SetException( - new TransportException( - TransportErrorCode.ConnectionBroken, inner, - this.activityId, this.uri, sourceDescription, - true, true)); - }); - } - - public void Cancel() - { - this.ThrowIfDisposed(); - // Call SetCanceled asynchronously. - this.RunAsynchronously(() => - { - Trace.CorrelationManager.ActivityId = this.activityId; - this.completion.SetCanceled(); - }); - } - - public void Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - this.sendComplete.Dispose(); - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException(nameof(CallInfo)); - } - } - - private void RunAsynchronously(Action action) - { - Task.Factory.StartNew( - action, - CancellationToken.None, - TaskCreationOptions.DenyChildAttach, - this.scheduler).ContinueWith( - static (failedTask, connectionIdObject) => - { - DefaultTrace.TraceError( - "[RNTBD Dispatcher.CallInfo {0}] Unexpected: Rntbd asynchronous completion " + - "call failed. Consuming the task exception asynchronously. " + - "Exception: {1}", connectionIdObject, failedTask.Exception?.InnerException); - }, - this.connectionCorrelationId, - TaskContinuationOptions.OnlyOnFaulted); - } - - private void RunAsynchronously(Func action) - { - Task.Factory.StartNew( - action, - CancellationToken.None, - TaskCreationOptions.DenyChildAttach, - this.scheduler).Unwrap().ContinueWith( - static (failedTask, connectionIdObject) => - { - DefaultTrace.TraceError( - "[RNTBD Dispatcher.CallInfo {0}] Unexpected: Rntbd asynchronous completion " + - "call failed. Consuming the task exception asynchronously. " + - "Exception: {1}", connectionIdObject, failedTask.Exception?.InnerException); - }, - this.connectionCorrelationId, - TaskContinuationOptions.OnlyOnFaulted); - } - - private void CompleteSend(State newState) - { - Debug.Assert(!Monitor.IsEntered(this.stateLock)); - lock (this.stateLock) - { - if (this.state != State.New) - { - throw new InvalidOperationException( - "Send may only complete once"); - } - Debug.Assert(this.state == State.New); - Debug.Assert( - newState == State.Sent || - newState == State.SendFailed); - this.state = newState; - this.sendComplete.Release(); - } - } - - private enum State - { - New, - Sent, - SendFailed, - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Net; + using System.Net.Security; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.FaultInjection; +#if COSMOSCLIENT + using Microsoft.Azure.Cosmos.Rntbd; +#endif + +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + // Dispatcher encapsulates the state and logic needed to dispatch multiple requests through + // a single connection. + internal sealed class Dispatcher : IDisposable + { + // Connection is thread-safe for sending. + // Receiving is done only from the receive loop. + // Initialization and disposal are not thread safe. Guard these + // operations with connectionLock. + private readonly Connection connection; + private readonly UserAgentContainer userAgent; + private readonly Uri serverUri; + private readonly IConnectionStateListener connectionStateListener; + // All individual operations on CancellationTokenSource are thread safe. + // When examining IsCancellationRequested in order to decide whether to cancel, + // guard the operation with connectionLock. + private readonly CancellationTokenSource cancellation = new CancellationTokenSource(); + private readonly TimerPool idleTimerPool; + private readonly bool enableChannelMultiplexing; + + private bool disposed = false; + + private ServerProperties serverProperties = null; + + private int nextRequestId = 0; + + // Acquire after connectionLock. + private readonly object callLock = new object(); + private Task receiveTask = null; // Guarded by callLock. + // Guarded by callLock. + private readonly Dictionary calls = new Dictionary(); + + // Guarded by callLock. + // The call map can become frozen if the underlying connection becomes + // unusable. This can happen if initialization fails, either the send + // stream or the receive stream are broken, the receive loop fails etc. + private bool callsAllowed = true; + + // lock used to guard underlying tcp connection state, which is a state level higher than callLock + // Acquire before callLock + private readonly object connectionLock = new object(); + private PooledTimer idleTimer; // Guarded by connectionLock + private Task idleTimerTask; // Guarded by connectionLock + + private readonly IChaosInterceptor chaosInterceptor; + private TransportException faultInjectionTransportException; + private bool isFaultInjectionedConnectionError; + + public Guid ConnectionCorrelationId { get => this.connection.ConnectionCorrelationId; } + + public Dispatcher( + Uri serverUri, + UserAgentContainer userAgent, + IConnectionStateListener connectionStateListener, + string hostNameCertificateOverride, + TimeSpan receiveHangDetectionTime, + TimeSpan sendHangDetectionTime, + TimerPool idleTimerPool, + TimeSpan idleTimeout, + bool enableChannelMultiplexing, + MemoryStreamPool memoryStreamPool, + RemoteCertificateValidationCallback remoteCertificateValidationCallback, + Func> dnsResolutionFunction, + IChaosInterceptor chaosInterceptor) + { + this.connection = new Connection( + serverUri, hostNameCertificateOverride, + receiveHangDetectionTime, sendHangDetectionTime, + idleTimeout, + memoryStreamPool, + remoteCertificateValidationCallback, + dnsResolutionFunction); + this.userAgent = userAgent; + this.connectionStateListener = connectionStateListener; + this.serverUri = serverUri; + this.idleTimerPool = idleTimerPool; + this.enableChannelMultiplexing = enableChannelMultiplexing; + this.chaosInterceptor = chaosInterceptor; + } + + #region Test hook. + + internal event Action TestOnConnectionClosed; + internal bool TestIsIdle + { + get + { + lock (this.connectionLock) + { + if (this.connection.Disposed) + { + return true; + } + TimeSpan ignoredTimeToIdle; + return !this.connection.IsActive(out ignoredTimeToIdle); + } + } + } + + #endregion + + public bool Healthy + { + get + { + this.ThrowIfDisposed(); + + if (this.cancellation.IsCancellationRequested) + { + return false; + } + + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + if (!this.callsAllowed) + { + return false; + } + } + + bool healthy; + try + { + healthy = this.connection.Healthy; + } + catch (ObjectDisposedException) + { + // Connection.Healthy shouldn't be called while the connection is being disposed, or after. + // To avoid additional locking, handle the exception here and store the outcome. + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}] {1} ObjectDisposedException from Connection.Healthy", + this.ConnectionCorrelationId, this); + healthy = false; + } + + if (healthy) + { + return true; + } + + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + this.callsAllowed = false; + } + return false; + } + } + + public async Task OpenAsync(ChannelOpenArguments args) + { + this.ThrowIfDisposed(); + try + { + Debug.Assert(this.connection != null); + await this.connection.OpenAsync(args); + await this.NegotiateRntbdContextAsync(args); + + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + Debug.Assert(this.receiveTask == null); + // The background receive loop and its failure continuation + // task should use a task scheduler internal to the Cosmos DB + // client. In any case, they should avoid using the current + // task scheduler, because some components use task schedulers + // for accounting, others to control and suspend task execution. + // In these cases, it does not make sense for the current + // accounting entity to get charged for the background receive + // loop in perpetuity, and there's a risk the task might get + // suspended and never resumed. + this.receiveTask = Task.Factory.StartNew( + async delegate + { + await this.ReceiveLoopAsync(); + }, + this.cancellation.Token, + TaskCreationOptions.LongRunning | + TaskCreationOptions.DenyChildAttach, + TaskScheduler.Default).Unwrap(); + _ = this.receiveTask.ContinueWith(completedTask => + { + Debug.Assert(completedTask.IsFaulted); + Debug.Assert(this.serverUri != null); + Debug.Assert(completedTask.Exception != null); + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}] Dispatcher.ReceiveLoopAsync failed. Consuming the task " + + "exception asynchronously. Dispatcher: {1}. Exception: {2}", + this.ConnectionCorrelationId, this, completedTask.Exception?.InnerException); + }, + default(CancellationToken), + TaskContinuationOptions.OnlyOnFaulted, + TaskScheduler.Default); + } + + if (this.idleTimerPool != null) + { + // idle timeout is enabled + this.StartIdleTimer(); + } + } + catch (DocumentClientException) + { + this.DisallowInitialCalls(); + throw; + } + catch (TransportException) + { + this.DisallowInitialCalls(); + throw; + } + } + + public void InjectFaultInjectionConnectionError(TransportException transportException) + { + if (!this.disposed) + { + this.isFaultInjectionedConnectionError = true; + this.faultInjectionTransportException = transportException; + } + } + + public sealed class PrepareCallResult : IDisposable + { + private bool disposed = false; + + public PrepareCallResult(uint requestId, Uri uri, TransportSerialization.SerializedRequest serializedRequest) + { + this.RequestId = requestId; + this.Uri = uri; + this.SerializedRequest = serializedRequest; + } + + public uint RequestId { get; private set; } + + public TransportSerialization.SerializedRequest SerializedRequest { get; } + public Uri Uri { get; private set; } + + /// + public void Dispose() + { + if (!this.disposed) + { + this.SerializedRequest.Dispose(); + this.disposed = true; + } + } + } + + // PrepareCall assigns a request ID to the request, serializes it, and + // returns the result. The caller must treat PrepareCallResult as an + // opaque handle. + public PrepareCallResult PrepareCall(DocumentServiceRequest request, + TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, + Guid activityId, + TransportRequestStats transportRequestStats) + { + uint requestId = unchecked((uint) Interlocked.Increment(ref this.nextRequestId)); + string requestIdString = requestId.ToString(CultureInfo.InvariantCulture); + + int headerSize; + int? bodySize; + TransportSerialization.SerializedRequest serializedRequest = TransportSerialization.BuildRequest( + request, + physicalAddress.PathAndQuery, + resourceOperation, + activityId, + this.connection.BufferProvider, + requestIdString, + out headerSize, + out bodySize); + + transportRequestStats.RequestBodySizeInBytes = bodySize; + transportRequestStats.RequestSizeInBytes = serializedRequest.RequestSize; + + return new PrepareCallResult(requestId, physicalAddress.Uri, serializedRequest); + } + + public async Task CallAsync(ChannelCallArguments args, TransportRequestStats transportRequestStats) + { + this.ThrowIfDisposed(); + // The current task scheduler must be used for correctness and to + // track per tenant physical charges for the compute gateway. + using (CallInfo callInfo = new CallInfo( + this.ConnectionCorrelationId, + args.CommonArguments.ActivityId, + args.PreparedCall.Uri, + TaskScheduler.Current, + transportRequestStats)) + { + uint requestId = args.PreparedCall.RequestId; + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + transportRequestStats.NumberOfInflightRequestsInConnection = this.calls.Count; + if (!this.callsAllowed) + { + Debug.Assert(args.CommonArguments.UserPayload); + throw new TransportException( + TransportErrorCode.ChannelMultiplexerClosed, null, + args.CommonArguments.ActivityId, args.PreparedCall.Uri, + this.ToString(), args.CommonArguments.UserPayload, + args.CommonArguments.PayloadSent); + } + this.calls.Add(requestId, callInfo); + } + try + { + try + { + if (this.chaosInterceptor != null) + { + await this.chaosInterceptor.OnBeforeConnectionWriteAsync(args); + (bool isFaulted, StoreResponse faultyResponse) = await this.chaosInterceptor.OnRequestCallAsync(args); + if (isFaulted) + { + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Sent); + return faultyResponse; + } + } + + await this.connection.WriteRequestAsync( + args.CommonArguments, + args.PreparedCall.SerializedRequest, + transportRequestStats); + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Sent); + + if (this.chaosInterceptor != null) + { + await this.chaosInterceptor.OnAfterConnectionWriteAsync(args); + } + + + } + catch (Exception e) + { + callInfo.SendFailed(); + throw new TransportException( + TransportErrorCode.SendFailed, e, + args.CommonArguments.ActivityId, args.PreparedCall.Uri, + this.ToString(), args.CommonArguments.UserPayload, + args.CommonArguments.PayloadSent); + } + // Do not add any code after the end of the previous block. + // Anything that needs to execute before ReadResponseAsync must + // be in the try block, so that no exceptions are missed. + return await callInfo.ReadResponseAsync(args); + } + catch (DocumentClientException) + { + this.DisallowRuntimeCalls(); + throw; + } + catch (TransportException) + { + this.DisallowRuntimeCalls(); + throw; + } + finally + { + this.RemoveCall(requestId); + } + } + } + + /// + /// Cancels a Rntbd call and notifies the connection by incrementing the transit timeout counters. + /// + /// An instance of containing the call result. + /// A boolean flag indicating if the request is read only. + public void CancelCallAndNotifyConnectionOnTimeoutEvent( + PrepareCallResult preparedCall, + bool isReadOnly) + { + this.ThrowIfDisposed(); + this.connection.NotifyConnectionStatus( + isCompleted: true, + isReadRequest: isReadOnly); + + CallInfo call = this.RemoveCall(preparedCall.RequestId); + if (call != null) + { + call.Cancel(); + } + } + + /// + /// Notifies the connection on a successful event, by resetting the transit timeout counters. + /// + public void NotifyConnectionOnSuccessEvent() + { + this.ThrowIfDisposed(); + this.connection.NotifyConnectionStatus( + isCompleted: true); + } + + public override string ToString() + { + return this.connection.ToString(); + } + + public void Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + + DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] Disposing RNTBD Dispatcher {1}", this.ConnectionCorrelationId, this); + + Task idleTimerTaskCopy = null; + Debug.Assert(!Monitor.IsEntered(this.connectionLock)); + lock (this.connectionLock) + { + this.StartConnectionShutdown(); + idleTimerTaskCopy = this.StopIdleTimer(); + } + + this.WaitTask(idleTimerTaskCopy, "idle timer"); + + Task receiveTaskCopy = null; + Debug.Assert(!Monitor.IsEntered(this.connectionLock)); + lock (this.connectionLock) + { + Debug.Assert(this.idleTimer == null); + Debug.Assert(this.idleTimerTask == null); + + receiveTaskCopy = this.CloseConnection(); + } + + this.WaitTask(receiveTaskCopy, "receive loop"); + + DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD Dispatcher {1} is disposed", this.ConnectionCorrelationId, this); + } + + private void StartIdleTimer() + { + DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD idle connection monitor: Timer is starting...", this.ConnectionCorrelationId); + + TimeSpan timeToIdle = TimeSpan.MinValue; + bool scheduled = false; + try + { + Debug.Assert(!Monitor.IsEntered(this.connectionLock)); + lock (this.connectionLock) + { + bool active = this.connection.IsActive(out timeToIdle); + Debug.Assert(active); + if (!active) + { + // This would be rather unexpected. + DefaultTrace.TraceCritical("[RNTBD Dispatcher {0}][{1}] New connection already idle.", this.ConnectionCorrelationId, this); + return; + } + + this.ScheduleIdleTimer(timeToIdle); + scheduled = true; + } + } + finally + { + if (scheduled) + { + DefaultTrace.TraceInformation( + "[RNTBD Dispatcher {0}] RNTBD idle connection monitor {1}: Timer is scheduled to fire {2} seconds later at {3}.", + this.ConnectionCorrelationId, this, timeToIdle.TotalSeconds, DateTime.UtcNow + timeToIdle); + } + else + { + DefaultTrace.TraceInformation("[RNTBD Dispatcher {0}] RNTBD idle connection monitor {1}: Timer is not scheduled.", this.ConnectionCorrelationId, this); + } + } + } + + private void OnIdleTimer(Task precedentTask) + { + Task receiveTaskCopy = null; + + Debug.Assert(!Monitor.IsEntered(this.connectionLock)); + lock (this.connectionLock) + { + if (this.cancellation.IsCancellationRequested) + { + return; + } + + Debug.Assert(!this.connection.Disposed); + TimeSpan timeToIdle; + bool active = this.connection.IsActive(out timeToIdle); + if (active) + { + this.ScheduleIdleTimer(timeToIdle); + return; + } + + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + if (this.calls.Count > 0) + { + DefaultTrace.TraceCritical( + "[RNTBD Dispatcher {0}][{1}] Looks idle but still has {2} pending requests", + this.ConnectionCorrelationId, this, this.calls.Count); + active = true; + } + else + { + this.callsAllowed = false; + } + } + + if (active) + { + this.ScheduleIdleTimer(timeToIdle); + return; + } + + this.idleTimer = null; + this.idleTimerTask = null; + + this.StartConnectionShutdown(); + receiveTaskCopy = this.CloseConnection(); + } + + this.WaitTask(receiveTaskCopy, "receive loop"); + } + + // this.connectionLock must be held. + private void ScheduleIdleTimer(TimeSpan timeToIdle) + { + Debug.Assert(Monitor.IsEntered(this.connectionLock)); + this.idleTimer = this.idleTimerPool.GetPooledTimer((int)timeToIdle.TotalSeconds); + this.idleTimerTask = this.idleTimer.StartTimerAsync().ContinueWith(this.OnIdleTimer, TaskContinuationOptions.OnlyOnRanToCompletion); + this.idleTimerTask.ContinueWith( + failedTask => + { + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}][{1}] Idle timer callback failed: {2}", + this.ConnectionCorrelationId, this, failedTask.Exception?.InnerException); + }, + TaskContinuationOptions.OnlyOnFaulted); + } + + // this.connectionLock must be held. + private void StartConnectionShutdown() + { + Debug.Assert(Monitor.IsEntered(this.connectionLock)); + if (this.cancellation.IsCancellationRequested) + { + return; + } + try + { + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + this.callsAllowed = false; + } + + this.cancellation.Cancel(); + } + catch (AggregateException e) + { + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}][{1}] Registered cancellation callbacks failed: {2}", + this.ConnectionCorrelationId, this, e); + // Deliberately ignoring the exception. + } + } + + // this.connectionLock must be held. + private Task StopIdleTimer() + { + Task idleTimerTaskCopy = null; + Debug.Assert(Monitor.IsEntered(this.connectionLock)); + if (this.idleTimer != null) + { + if (this.idleTimer.CancelTimer()) + { + // Dispose() won the race and the timer was cancelled. + this.idleTimer = null; + this.idleTimerTask = null; + } + else + { + idleTimerTaskCopy = this.idleTimerTask; + } + } + return idleTimerTaskCopy; + } + + // this.connectionLock must be held. + private Task CloseConnection() + { + Task receiveTaskCopy = null; + Debug.Assert(Monitor.IsEntered(this.connectionLock)); + if (!this.connection.Disposed) + { + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + receiveTaskCopy = this.receiveTask; + } + + this.connection.Dispose(); + this.TestOnConnectionClosed?.Invoke(); + } + return receiveTaskCopy; + } + + private void WaitTask(Task t, string description) + { + if (t == null) + { + return; + } + try + { + // Don't hold locks while blocking this thread + Debug.Assert(!Monitor.IsEntered(this.callLock)); + Debug.Assert(!Monitor.IsEntered(this.connectionLock)); + t.Wait(); + } + catch (Exception e) + { + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}][{1}] Parallel task failed: {2}. Exception: {3}", + this.ConnectionCorrelationId, this, description, e); + // Intentionally swallowing the exception. The caller can't + // do anything useful with it. + } + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + Debug.Assert(this.serverUri != null); + throw new ObjectDisposedException( + string.Format("{0}:{1}", nameof(Dispatcher), this.serverUri)); + } + } + + private async Task NegotiateRntbdContextAsync(ChannelOpenArguments args) + { + byte[] contextMessage = TransportSerialization.BuildContextRequest( + args.CommonArguments.ActivityId, this.userAgent, args.CallerId, this.enableChannelMultiplexing); + + await this.connection.WriteRequestAsync( + args.CommonArguments, + new TransportSerialization.SerializedRequest(new BufferProvider.DisposableBuffer(contextMessage), requestBody: null), + transportRequestStats: null); + + // Read the response. + using Connection.ResponseMetadata responseMd = + await this.connection.ReadResponseMetadataAsync(args.CommonArguments); + + // Full header and metadata are read now. Parse out more fields and handle them. + StatusCodes status = (StatusCodes) BitConverter.ToUInt32(responseMd.Header.Array, 4); + byte[] responseActivityIdBytes = new byte[16]; + Buffer.BlockCopy(responseMd.Header.Array, 8, responseActivityIdBytes, 0, 16); + // Server should just be echoing back the ActivityId from the connection request, but retrieve it + // from the wire and use it from here on, to be absolutely certain we have the same ActivityId + // the server is using + Guid activityId = new Guid(responseActivityIdBytes); + Trace.CorrelationManager.ActivityId = activityId; + + BytesDeserializer deserializer = new BytesDeserializer(responseMd.Metadata.Array, responseMd.Metadata.Count); + RntbdConstants.ConnectionContextResponse response = new RntbdConstants.ConnectionContextResponse(); + response.ParseFrom(ref deserializer); + string serverAgent = BytesSerializer.GetStringFromBytes(response.serverAgent.value.valueBytes); + string serverVersion = BytesSerializer.GetStringFromBytes(response.serverVersion.value.valueBytes); + Debug.Assert(this.serverProperties == null); + this.serverProperties = new ServerProperties(serverAgent, serverVersion); + + if ((UInt32)status < 200 || (UInt32)status >= 400) + { + Debug.Assert(args.CommonArguments.UserPayload == false); + + using (MemoryStream errorResponseStream = await this.connection.ReadResponseBodyAsync( + new ChannelCommonArguments(activityId, + TransportErrorCode.TransportNegotiationTimeout, + args.CommonArguments.UserPayload))) + { + Error error = Resource.LoadFrom(errorResponseStream); + + DocumentClientException exception = new DocumentClientException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + error.ToString()), + null, + (HttpStatusCode)status, + this.connection.ServerUri); + + if (response.clientVersion.isPresent) + { + exception.Headers.Add("RequiredClientVersion", + BytesSerializer.GetStringFromBytes(response.clientVersion.value.valueBytes)); + } + + if (response.protocolVersion.isPresent) + { + exception.Headers.Add("RequiredProtocolVersion", + response.protocolVersion.value.valueULong.ToString()); + } + + if (response.serverAgent.isPresent) + { + exception.Headers.Add("ServerAgent", + BytesSerializer.GetStringFromBytes(response.serverAgent.value.valueBytes)); + } + + if (response.serverVersion.isPresent) + { + exception.Headers.Add( + HttpConstants.HttpHeaders.ServerVersion, + BytesSerializer.GetStringFromBytes(response.serverVersion.value.valueBytes)); + } + + throw exception; + } + } + + this.NotifyConnectionOnSuccessEvent(); + args.OpenTimeline.RecordRntbdHandshakeFinishTime(); + } + + private async Task ReceiveLoopAsync() + { + CancellationToken cancellationToken = this.cancellation.Token; + ChannelCommonArguments args = new ChannelCommonArguments( + Guid.Empty, TransportErrorCode.ReceiveTimeout, true); + Connection.ResponseMetadata responseMd = null; + try + { + bool hasTransportErrors = false; + while (!hasTransportErrors && !cancellationToken.IsCancellationRequested) + { + if (this.isFaultInjectionedConnectionError) + { + hasTransportErrors = true; + throw this.faultInjectionTransportException; + } + + args.ActivityId = Guid.Empty; + responseMd = await this.connection.ReadResponseMetadataAsync(args); + ArraySegment metadata = responseMd.Metadata; + + TransportSerialization.RntbdHeader header = + TransportSerialization.DecodeRntbdHeader(responseMd.Header.Array); + + args.ActivityId = header.ActivityId; + BytesDeserializer deserializer = new BytesDeserializer(metadata.Array, metadata.Count); + + MemoryStream bodyStream = null; + if (HeadersTransportSerialization.TryParseMandatoryResponseHeaders(ref deserializer, out bool payloadPresent, out uint transportRequestId)) + { + if (payloadPresent) + { + bodyStream = await this.connection.ReadResponseBodyAsync(args); + } + this.DispatchRntbdResponse(responseMd, header, bodyStream, metadata.Array, metadata.Count, transportRequestId); + } + else + { + hasTransportErrors = true; + this.DispatchChannelFailureException(TransportExceptions.GetInternalServerErrorException(this.serverUri, RMResources.MissingRequiredHeader)); + } + + responseMd = null; + } + this.DispatchCancellation(); + } + catch (OperationCanceledException) + { + responseMd?.Dispose(); + this.DispatchCancellation(); + } + catch (ObjectDisposedException) + { + responseMd?.Dispose(); + this.DispatchCancellation(); + } + catch (Exception e) + { + responseMd?.Dispose(); + this.DispatchChannelFailureException(e); + } + +#if DEBUG + lock (this.callLock) + { + Debug.Assert(!this.callsAllowed); + Debug.Assert(this.calls.Count == 0); + } +#endif + } + + private Dictionary StopCalls() + { + Dictionary clonedCalls; + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + clonedCalls = new Dictionary(this.calls); + this.calls.Clear(); + this.callsAllowed = false; + } + return clonedCalls; + } + + private void DispatchRntbdResponse( + Connection.ResponseMetadata responseMd, + TransportSerialization.RntbdHeader responseHeader, + MemoryStream responseBody, + byte[] metadata, + int metadataLength, + uint transportRequestId) + { + CallInfo call = this.RemoveCall(transportRequestId); + if (call != null) + { + Debug.Assert(this.serverProperties != null); + Debug.Assert(this.serverProperties.Version != null); + call.TransportRequestStats.RecordState(TransportRequestStats.RequestStage.Received); + call.TransportRequestStats.ResponseMetadataSizeInBytes = responseMd.Metadata.Count; + call.TransportRequestStats.ResponseBodySizeInBytes = responseBody?.Length; + call.SetResponse(responseMd, responseHeader, responseBody, this.serverProperties.Version, metadata, metadataLength); + } + else + { + responseBody?.Dispose(); + responseMd.Dispose(); + } + } + + private void DispatchChannelFailureException(Exception ex) + { + Dictionary clonedCalls = this.StopCalls(); + foreach (KeyValuePair entry in clonedCalls) + { + CallInfo call = entry.Value; + Debug.Assert(call != null); + call.SetConnectionBrokenException(ex, this.ToString()); + } + + // If there are no pending calls on this channel and a subscriber is interested + // in connection events, examine the exception and raise the event appropriately. + if ((clonedCalls.Count > 0) || (this.connectionStateListener == null)) + { + // If any calls are pending, the event is unnecessary because callers will get + // TransportException. If this.connectionStateListener is null, the point is moot. + return; + } + TransportException transportException = ex as TransportException; + if (transportException == null) + { + // The client transport stack catches SocketException and IOException and wraps them + // in TransportException as appropriate. Other exception types may also be thrown. + // In some cases, it may be reasonable to catch those exceptions and wrap them in + // TransportException. + // In other cases, it may be reasonable to handle additional exception types here. + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}] Not a TransportException. Will not raise the connection state change event: {1}", + this.ConnectionCorrelationId, ex); + return; + } + + // Copy a bunch of values locally to avoid capturing the this pointer. + ConnectionEvent connectionEvent; + switch (transportException.ErrorCode) + { + case TransportErrorCode.ReceiveStreamClosed: + connectionEvent = ConnectionEvent.ReadEof; + break; + + case TransportErrorCode.ReceiveFailed: + connectionEvent = ConnectionEvent.ReadFailure; + break; + + default: + DefaultTrace.TraceWarning( + "[RNTBD Dispatcher {0}] Will not raise the connection state change event for TransportException error code {1}. Exception: {2}", + this.ConnectionCorrelationId, transportException.ErrorCode.ToString(), transportException.Message); + return; + } + IConnectionStateListener connectionStateListener = this.connectionStateListener; + ServerKey serverKey = new ServerKey(this.serverUri); + DateTime exceptionTime = transportException.Timestamp; + // Run the event handler asynchronously and catch all exceptions. + Task t = Task.Run(() => + { + connectionStateListener.OnConnectionEvent(connectionEvent, exceptionTime, serverKey); + }); + + t.ContinueWith(static (failedTask, connectionIdObject) => + { + DefaultTrace.TraceError("[RNTBD Dispatcher {0}] OnConnectionEvent callback failed: {1}", connectionIdObject, failedTask.Exception?.InnerException); + }, this.ConnectionCorrelationId, TaskContinuationOptions.OnlyOnFaulted); + } + + private void DispatchCancellation() + { + Dictionary clonedCalls = this.StopCalls(); + foreach (KeyValuePair entry in clonedCalls) + { + CallInfo call = entry.Value; + Debug.Assert(call != null); + call.Cancel(); + } + } + + private CallInfo RemoveCall(uint requestId) + { + Debug.Assert(!Monitor.IsEntered(this.callLock)); + CallInfo callInfo = null; + lock (this.callLock) + { + bool found = this.calls.TryGetValue(requestId, out callInfo); + bool removed = this.calls.Remove(requestId); + Debug.Assert(found == removed); + } + return callInfo; + } + + // The only difference between DisallowInitialCalls and + // DisallowRuntimeCalls is an extra debug assert. In debug mode, + // DisallowInitialCalls ensures nobody got in yet. + private void DisallowInitialCalls() + { + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + Debug.Assert(this.calls.Count == 0); + this.callsAllowed = false; + } + } + + private void DisallowRuntimeCalls() + { + Debug.Assert(!Monitor.IsEntered(this.callLock)); + lock (this.callLock) + { + this.callsAllowed = false; + } + } + + internal sealed class CallInfo : IDisposable + { + private readonly TaskCompletionSource completion = + new TaskCompletionSource(); + private readonly SemaphoreSlim sendComplete = + new SemaphoreSlim(0); + + private readonly Guid connectionCorrelationId; + private readonly Guid activityId; + private readonly Uri uri; + private readonly TaskScheduler scheduler; + + private bool disposed = false; + private readonly object stateLock = new object(); + private State state; + + public TransportRequestStats TransportRequestStats { get; } + + public CallInfo(Guid connectionCorrelationId, Guid activityId, Uri uri, TaskScheduler scheduler, TransportRequestStats transportRequestStats) + { + Debug.Assert(connectionCorrelationId != Guid.Empty); + Debug.Assert(activityId != Guid.Empty); + Debug.Assert(uri != null); + Debug.Assert(scheduler != null); + Debug.Assert(transportRequestStats != null); + + this.connectionCorrelationId = connectionCorrelationId; + this.activityId = activityId; + this.uri = uri; + this.scheduler = scheduler; + this.TransportRequestStats = transportRequestStats; + } + + public Task ReadResponseAsync(ChannelCallArguments args) + { + this.ThrowIfDisposed(); + // If execution got this far, sending the request succeeded. + this.CompleteSend(State.Sent); + args.CommonArguments.SetTimeoutCode( + TransportErrorCode.ReceiveTimeout); + return this.completion.Task; + } + + public void SendFailed() + { + this.ThrowIfDisposed(); + this.CompleteSend(State.SendFailed); + } + + public void SetResponse( + Connection.ResponseMetadata responseMd, + TransportSerialization.RntbdHeader responseHeader, + MemoryStream responseBody, + string serverVersion, + byte[] metadata, + int metadataLength) + { + this.ThrowIfDisposed(); + // Call SetResult asynchronously. Otherwise, the tasks awaiting on + // completionSource.Task will be continued on this thread. This is + // undesirable for both correctness reasons (it can lead to + // deadlock, because the receive task will not complete until this + // function returns, which may not happen if a continued task tries + // to dispose this object) and for performance reasons (SetResult + // needs to be fire-and-forget, not synchronous and sequential). + + // .NET Framework 4.6 introduces + // TaskCreationOptions.RunContinuationsAsynchronously. It should be + // used when it becomes available. + this.RunAsynchronously(() => + { + Trace.CorrelationManager.ActivityId = this.activityId; + try + { + BytesDeserializer bytesDeserializer = new BytesDeserializer(metadata, metadataLength); + StoreResponse storeResponse = TransportSerialization.MakeStoreResponse( + responseHeader.Status, + responseHeader.ActivityId, + responseBody, + serverVersion, + ref bytesDeserializer); + this.completion.SetResult(storeResponse); + } + catch (Exception e) + { + this.completion.SetException(e); + responseBody?.Dispose(); + } + finally + { + responseMd.Dispose(); + } + }); + } + + public void SetConnectionBrokenException(Exception inner, string sourceDescription) + { + this.ThrowIfDisposed(); + // Call SetException asynchronously. + this.RunAsynchronously( + async delegate + { + Trace.CorrelationManager.ActivityId = this.activityId; + // When an API caller sends a request, it can get two + // exceptions concurrently, one from the inline SendAsync + // call, and one from the background receive loop doing + // ReceiveAsync. Avoid setting an exception on the + // completion object if sending the request already + // failed. The exception is not necessary, and the + // unused completion would trigger + // UnobservedTaskException upon garbage collection. + await this.sendComplete.WaitAsync(); + lock (this.stateLock) + { + if (this.state != State.Sent) + { + return; + } + } + this.completion.SetException( + new TransportException( + TransportErrorCode.ConnectionBroken, inner, + this.activityId, this.uri, sourceDescription, + true, true)); + }); + } + + public void Cancel() + { + this.ThrowIfDisposed(); + // Call SetCanceled asynchronously. + this.RunAsynchronously(() => + { + Trace.CorrelationManager.ActivityId = this.activityId; + this.completion.SetCanceled(); + }); + } + + public void Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + this.sendComplete.Dispose(); + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + throw new ObjectDisposedException(nameof(CallInfo)); + } + } + + private void RunAsynchronously(Action action) + { + Task.Factory.StartNew( + action, + CancellationToken.None, + TaskCreationOptions.DenyChildAttach, + this.scheduler).ContinueWith( + static (failedTask, connectionIdObject) => + { + DefaultTrace.TraceError( + "[RNTBD Dispatcher.CallInfo {0}] Unexpected: Rntbd asynchronous completion " + + "call failed. Consuming the task exception asynchronously. " + + "Exception: {1}", connectionIdObject, failedTask.Exception?.InnerException); + }, + this.connectionCorrelationId, + TaskContinuationOptions.OnlyOnFaulted); + } + + private void RunAsynchronously(Func action) + { + Task.Factory.StartNew( + action, + CancellationToken.None, + TaskCreationOptions.DenyChildAttach, + this.scheduler).Unwrap().ContinueWith( + static (failedTask, connectionIdObject) => + { + DefaultTrace.TraceError( + "[RNTBD Dispatcher.CallInfo {0}] Unexpected: Rntbd asynchronous completion " + + "call failed. Consuming the task exception asynchronously. " + + "Exception: {1}", connectionIdObject, failedTask.Exception?.InnerException); + }, + this.connectionCorrelationId, + TaskContinuationOptions.OnlyOnFaulted); + } + + private void CompleteSend(State newState) + { + Debug.Assert(!Monitor.IsEntered(this.stateLock)); + lock (this.stateLock) + { + if (this.state != State.New) + { + throw new InvalidOperationException( + "Send may only complete once"); + } + Debug.Assert(this.state == State.New); + Debug.Assert( + newState == State.Sent || + newState == State.SendFailed); + this.state = newState; + this.sendComplete.Release(); + } + } + + private enum State + { + New, + Sent, + SendFailed, + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Document.cs b/Microsoft.Azure.Cosmos/src/direct/Document.cs index e4615cb631..9a05f98aca 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Document.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Document.cs @@ -1,449 +1,449 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Dynamic; - using System.Globalization; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Represents a document in the Azure Cosmos DB service. - /// - /// - /// A document is a structured JSON document. There is no set schema for the JSON documents, and a document may contain any - /// number of custom properties as well as an optional list of attachments. Document is an application resource and can be - /// authorized using the master key or resource keys. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Document : Resource, IDynamicMetaObjectProvider - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public Document() - { - - } - - /// - /// Gets the self-link corresponding to attachments of the document from the Azure Cosmos DB service. - /// - /// - /// The self-link corresponding to attachments of the document. - /// - /// - /// Every document can have between zero and many attachments. The attachments link contains a feed of attachments that belong to - /// the document. - /// - public string AttachmentsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.AttachmentsLink); - } - } - - /// - /// Gets or sets the time to live in seconds of the document in the Azure Cosmos DB service. - /// - /// - /// It is an optional property. - /// A valid value must be either a nonzero positive integer, '-1', or null. - /// By default, TimeToLive is set to null meaning the document inherits the collection's . - /// The unit of measurement is seconds. The maximum allowed value is 2147483647. - /// When the value is '-1', it means never expire regardless of the collection's value. - /// - /// - /// - /// The final time-to-live policy of a document is evaluated after consulting the collection's - /// . - /// - /// - /// When the is null, the document inherits the collection's - /// . - /// If the collection's is a nonzero positive integer, - /// then the document will inherit that value as its time-to-live in seconds, and will be expired - /// after the default time-to-live in seconds since its last write time. The expired documents will be deleted in background. - /// Otherwise, the document will never expire. - /// - /// - /// When the is '-1', the document will never expire regardless of the collection's - /// value. - /// - /// - /// When the is a nonzero positive integer, need to check the collection's - /// . - /// If the collection's is null, which means the time-to-live - /// has been turned off on the collection, and the document's should be disregarded and the document - /// will never expire. - /// Otherwise, the document's will be honored. The document will be expired - /// after the default time-to-live in seconds since its last write time. The expired documents will be deleted in background. - /// - /// - /// The table below shows an example of the matrix to evaluate the final time-to-live policy given a collection's - /// and a document's . - /// - /// - /// - /// Collection - /// Matrix - /// - /// - /// DefaultTimeToLive = null - /// - /// - /// - /// Document - /// Result - /// - /// - /// TimeToLive = null - /// TTL is disabled. The document will never expire (default). - /// - /// - /// TimeToLive = -1 - /// TTL is disabled. The document will never expire. - /// - /// - /// TimeToLive = 2000 - /// TTL is disabled. The document will never expire. - /// - /// - /// - /// - /// - /// DefaultTimeToLive = -1 - /// - /// - /// - /// Document - /// Result - /// - /// - /// TimeToLive = null - /// TTL is enabled. The document will never expire (default). - /// - /// - /// TimeToLive = -1 - /// TTL is enabled. The document will never expire. - /// - /// - /// TimeToLive = 2000 - /// TTL is enabled. The document will expire after 2000 seconds. - /// - /// - /// - /// - /// - /// DefaultTimeToLive = 1000 - /// - /// - /// - /// Document - /// Result - /// - /// - /// TimeToLive = null - /// TTL is enabled. The document will expire after 1000 seconds (default). - /// - /// - /// TimeToLive = -1 - /// TTL is enabled. The document will never expire. - /// - /// - /// TimeToLive = 2000 - /// TTL is enabled. The document will expire after 2000 seconds. - /// - /// - /// - /// - /// - /// - /// - /// The example below removes 'ttl' from document content. - /// The document will inherit the collection's as its time-to-live value. - /// - /// - /// - /// - /// - /// The example below ensures that the document should never expire regardless. - /// - /// - /// - /// - /// - /// The example below sets the time-to-live in seconds on a document. - /// The document will expire after 1000 seconds since its last write time when the collection's - /// is not null. - /// - /// - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.TimeToLive, NullValueHandling = NullValueHandling.Ignore)] - public int? TimeToLive - { - get - { - return base.GetValue(Constants.Properties.TimeToLive); - } - set - { - base.SetValue(Constants.Properties.TimeToLive, value); - } - } - - //Helper to materialize Document from any .NET object. - internal static Document FromObject(object document, JsonSerializerSettings settings = null) - { - if(document != null) - { - if (typeof(Document).IsAssignableFrom(document.GetType())) - { - return (Document)document; - } - else - { - // FromObject: for dynamics, it only go through JsonProperty attribute decorated properties. - // for poco, it will go through all public properties - JObject serializedPropertyBag = (settings == null) ? - JObject.FromObject(document) : - JObject.FromObject(document, JsonSerializer.Create(settings)); - Document typeDocument = new Document() { SerializerSettings = settings }; - - typeDocument.propertyBag = serializedPropertyBag; - return typeDocument; - } - } - return null; - } - - //Property Getter/Setter for Expandable User property. - private object GetProperty( - string propertyName, Type returnType) - { - if(this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if (token != null) - { - return this.SerializerSettings == null ? - token.ToObject(returnType) : - token.ToObject(returnType, JsonSerializer.Create(this.SerializerSettings)); - } - } - - //Any property not in JSON throw exception rather than returning null. - throw new DocumentClientException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.PropertyNotFound, - propertyName), null, null); - } - - private object SetProperty(string propertyName, object value) - { - if (value != null) - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - this.propertyBag[propertyName] = JToken.FromObject(value); - } - else - { - if (this.propertyBag != null) - { - this.propertyBag.Remove(propertyName); - } - } - return value; - } - - private T AsType() //To convert Document to any type. - { - if (typeof(T) == typeof(Document) || typeof(T) == typeof(object)) - { - return (T)(object)this; - } - - if (this.propertyBag == null) - { - return default(T); - } - - //Materialize the type. - return (this.SerializerSettings == null) ? - (T)this.propertyBag.ToObject() : - (T)this.propertyBag.ToObject(JsonSerializer.Create(this.SerializerSettings)); - } - - DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) - { - return new DocumentDynamicMetaObject(this, parameter); - } - - private class DocumentDynamicMetaObject : DynamicMetaObject - { - private readonly Document document; - public DocumentDynamicMetaObject(Document document, Expression expression) - : base(expression, BindingRestrictions.Empty, document) - { - this.document = document; - } - - public override DynamicMetaObject BindGetMember(GetMemberBinder binder) - { - if (DocumentDynamicMetaObject.IsResourceProperty(binder.Name)) - { - return base.BindGetMember(binder); //Base will bind it statically. - } - - //For all non-resource property, thunk the call to GetProperty method in Document. - string methodName = "GetProperty"; - - //Two parameters. - Expression[] parameters = new Expression[] - { - Expression.Constant(binder.Name), //PropertyName - Expression.Constant(binder.ReturnType) //Expected Return Type. - }; - - //Expression: this. - Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); - - //Expression: this.GetProperty(name, returnType); - Expression getPropertyExpression = Expression.Call( - thisExpression, - typeof(Document).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - parameters); - - DynamicMetaObject getProperty = new DynamicMetaObject( - getPropertyExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return getProperty; - } - - public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) - { - if (DocumentDynamicMetaObject.IsResourceProperty(binder.Name)) - { - return base.BindSetMember(binder, value); //Base will bind it statically. - } - - //For all non-resource property, thunk the call to this.SetProperty method in Document. - string methodName = "SetProperty"; - - // setup the binding restrictions. - BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); - - //Two params, Name & Value. - Expression[] args = new Expression[2]; - args[0] = Expression.Constant(binder.Name); - args[1] = Expression.Convert(value.Expression, typeof(object)); - - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - // Setup the method call expression - Expression methodCall = Expression.Call(self, - typeof(Document).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - args); - - // Create a meta object to invoke Set later: - DynamicMetaObject setProperty = new DynamicMetaObject( - methodCall, - restrictions); - // return that dynamic object - return setProperty; - } - - public override DynamicMetaObject BindConvert(ConvertBinder binder) - { - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - MethodCallExpression methodExpression = Expression.Call( - self, - typeof(Document).GetMethod("AsType", - BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); - - //Create a meta object to invoke AsType later. - DynamicMetaObject castOperator = new DynamicMetaObject( - methodExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return castOperator; - } - - public override IEnumerable GetDynamicMemberNames() - { - // Here we don't enumerate this.document.propertyBag, because in Document.FromObject, - // we merge the static defined property into propertyBag - List dynamicMembers = new List(); - - foreach (KeyValuePair pair in this.document.propertyBag) - { - // exclude the resource property - if (!IsResourceSerializedProperty(pair.Key)) - { - dynamicMembers.Add(pair.Key); - } - } - - return dynamicMembers.ToList(); - } - - internal static bool IsResourceSerializedProperty(string propertyName) - { - if (propertyName == Constants.Properties.Id || - propertyName == Constants.Properties.RId || - propertyName == Constants.Properties.ETag || - propertyName == Constants.Properties.LastModified || - propertyName == Constants.Properties.SelfLink || - propertyName == Constants.Properties.AttachmentsLink || - propertyName == Constants.Properties.TimeToLive) - { - return true; - } - return false; - } - - //List of Static Property in Document which we dont want to thunk. - internal static bool IsResourceProperty(string propertyName) - { - if (propertyName == "Id" || - propertyName == "ResourceId" || - propertyName == "ETag" || - propertyName == "Timestamp" || - propertyName == "SelfLink" || - propertyName == "AttachmentsLink" || - propertyName == "TimeToLive") - { - return true; - } - return false; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Dynamic; + using System.Globalization; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents a document in the Azure Cosmos DB service. + /// + /// + /// A document is a structured JSON document. There is no set schema for the JSON documents, and a document may contain any + /// number of custom properties as well as an optional list of attachments. Document is an application resource and can be + /// authorized using the master key or resource keys. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Document : Resource, IDynamicMetaObjectProvider + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public Document() + { + + } + + /// + /// Gets the self-link corresponding to attachments of the document from the Azure Cosmos DB service. + /// + /// + /// The self-link corresponding to attachments of the document. + /// + /// + /// Every document can have between zero and many attachments. The attachments link contains a feed of attachments that belong to + /// the document. + /// + public string AttachmentsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.AttachmentsLink); + } + } + + /// + /// Gets or sets the time to live in seconds of the document in the Azure Cosmos DB service. + /// + /// + /// It is an optional property. + /// A valid value must be either a nonzero positive integer, '-1', or null. + /// By default, TimeToLive is set to null meaning the document inherits the collection's . + /// The unit of measurement is seconds. The maximum allowed value is 2147483647. + /// When the value is '-1', it means never expire regardless of the collection's value. + /// + /// + /// + /// The final time-to-live policy of a document is evaluated after consulting the collection's + /// . + /// + /// + /// When the is null, the document inherits the collection's + /// . + /// If the collection's is a nonzero positive integer, + /// then the document will inherit that value as its time-to-live in seconds, and will be expired + /// after the default time-to-live in seconds since its last write time. The expired documents will be deleted in background. + /// Otherwise, the document will never expire. + /// + /// + /// When the is '-1', the document will never expire regardless of the collection's + /// value. + /// + /// + /// When the is a nonzero positive integer, need to check the collection's + /// . + /// If the collection's is null, which means the time-to-live + /// has been turned off on the collection, and the document's should be disregarded and the document + /// will never expire. + /// Otherwise, the document's will be honored. The document will be expired + /// after the default time-to-live in seconds since its last write time. The expired documents will be deleted in background. + /// + /// + /// The table below shows an example of the matrix to evaluate the final time-to-live policy given a collection's + /// and a document's . + /// + /// + /// + /// Collection + /// Matrix + /// + /// + /// DefaultTimeToLive = null + /// + /// + /// + /// Document + /// Result + /// + /// + /// TimeToLive = null + /// TTL is disabled. The document will never expire (default). + /// + /// + /// TimeToLive = -1 + /// TTL is disabled. The document will never expire. + /// + /// + /// TimeToLive = 2000 + /// TTL is disabled. The document will never expire. + /// + /// + /// + /// + /// + /// DefaultTimeToLive = -1 + /// + /// + /// + /// Document + /// Result + /// + /// + /// TimeToLive = null + /// TTL is enabled. The document will never expire (default). + /// + /// + /// TimeToLive = -1 + /// TTL is enabled. The document will never expire. + /// + /// + /// TimeToLive = 2000 + /// TTL is enabled. The document will expire after 2000 seconds. + /// + /// + /// + /// + /// + /// DefaultTimeToLive = 1000 + /// + /// + /// + /// Document + /// Result + /// + /// + /// TimeToLive = null + /// TTL is enabled. The document will expire after 1000 seconds (default). + /// + /// + /// TimeToLive = -1 + /// TTL is enabled. The document will never expire. + /// + /// + /// TimeToLive = 2000 + /// TTL is enabled. The document will expire after 2000 seconds. + /// + /// + /// + /// + /// + /// + /// + /// The example below removes 'ttl' from document content. + /// The document will inherit the collection's as its time-to-live value. + /// + /// + /// + /// + /// + /// The example below ensures that the document should never expire regardless. + /// + /// + /// + /// + /// + /// The example below sets the time-to-live in seconds on a document. + /// The document will expire after 1000 seconds since its last write time when the collection's + /// is not null. + /// + /// + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.TimeToLive, NullValueHandling = NullValueHandling.Ignore)] + public int? TimeToLive + { + get + { + return base.GetValue(Constants.Properties.TimeToLive); + } + set + { + base.SetValue(Constants.Properties.TimeToLive, value); + } + } + + //Helper to materialize Document from any .NET object. + internal static Document FromObject(object document, JsonSerializerSettings settings = null) + { + if(document != null) + { + if (typeof(Document).IsAssignableFrom(document.GetType())) + { + return (Document)document; + } + else + { + // FromObject: for dynamics, it only go through JsonProperty attribute decorated properties. + // for poco, it will go through all public properties + JObject serializedPropertyBag = (settings == null) ? + JObject.FromObject(document) : + JObject.FromObject(document, JsonSerializer.Create(settings)); + Document typeDocument = new Document() { SerializerSettings = settings }; + + typeDocument.propertyBag = serializedPropertyBag; + return typeDocument; + } + } + return null; + } + + //Property Getter/Setter for Expandable User property. + private object GetProperty( + string propertyName, Type returnType) + { + if(this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if (token != null) + { + return this.SerializerSettings == null ? + token.ToObject(returnType) : + token.ToObject(returnType, JsonSerializer.Create(this.SerializerSettings)); + } + } + + //Any property not in JSON throw exception rather than returning null. + throw new DocumentClientException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.PropertyNotFound, + propertyName), null, null); + } + + private object SetProperty(string propertyName, object value) + { + if (value != null) + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + this.propertyBag[propertyName] = JToken.FromObject(value); + } + else + { + if (this.propertyBag != null) + { + this.propertyBag.Remove(propertyName); + } + } + return value; + } + + private T AsType() //To convert Document to any type. + { + if (typeof(T) == typeof(Document) || typeof(T) == typeof(object)) + { + return (T)(object)this; + } + + if (this.propertyBag == null) + { + return default(T); + } + + //Materialize the type. + return (this.SerializerSettings == null) ? + (T)this.propertyBag.ToObject() : + (T)this.propertyBag.ToObject(JsonSerializer.Create(this.SerializerSettings)); + } + + DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) + { + return new DocumentDynamicMetaObject(this, parameter); + } + + private class DocumentDynamicMetaObject : DynamicMetaObject + { + private readonly Document document; + public DocumentDynamicMetaObject(Document document, Expression expression) + : base(expression, BindingRestrictions.Empty, document) + { + this.document = document; + } + + public override DynamicMetaObject BindGetMember(GetMemberBinder binder) + { + if (DocumentDynamicMetaObject.IsResourceProperty(binder.Name)) + { + return base.BindGetMember(binder); //Base will bind it statically. + } + + //For all non-resource property, thunk the call to GetProperty method in Document. + string methodName = "GetProperty"; + + //Two parameters. + Expression[] parameters = new Expression[] + { + Expression.Constant(binder.Name), //PropertyName + Expression.Constant(binder.ReturnType) //Expected Return Type. + }; + + //Expression: this. + Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); + + //Expression: this.GetProperty(name, returnType); + Expression getPropertyExpression = Expression.Call( + thisExpression, + typeof(Document).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + parameters); + + DynamicMetaObject getProperty = new DynamicMetaObject( + getPropertyExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return getProperty; + } + + public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) + { + if (DocumentDynamicMetaObject.IsResourceProperty(binder.Name)) + { + return base.BindSetMember(binder, value); //Base will bind it statically. + } + + //For all non-resource property, thunk the call to this.SetProperty method in Document. + string methodName = "SetProperty"; + + // setup the binding restrictions. + BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); + + //Two params, Name & Value. + Expression[] args = new Expression[2]; + args[0] = Expression.Constant(binder.Name); + args[1] = Expression.Convert(value.Expression, typeof(object)); + + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + // Setup the method call expression + Expression methodCall = Expression.Call(self, + typeof(Document).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + args); + + // Create a meta object to invoke Set later: + DynamicMetaObject setProperty = new DynamicMetaObject( + methodCall, + restrictions); + // return that dynamic object + return setProperty; + } + + public override DynamicMetaObject BindConvert(ConvertBinder binder) + { + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + MethodCallExpression methodExpression = Expression.Call( + self, + typeof(Document).GetMethod("AsType", + BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); + + //Create a meta object to invoke AsType later. + DynamicMetaObject castOperator = new DynamicMetaObject( + methodExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return castOperator; + } + + public override IEnumerable GetDynamicMemberNames() + { + // Here we don't enumerate this.document.propertyBag, because in Document.FromObject, + // we merge the static defined property into propertyBag + List dynamicMembers = new List(); + + foreach (KeyValuePair pair in this.document.propertyBag) + { + // exclude the resource property + if (!IsResourceSerializedProperty(pair.Key)) + { + dynamicMembers.Add(pair.Key); + } + } + + return dynamicMembers.ToList(); + } + + internal static bool IsResourceSerializedProperty(string propertyName) + { + if (propertyName == Constants.Properties.Id || + propertyName == Constants.Properties.RId || + propertyName == Constants.Properties.ETag || + propertyName == Constants.Properties.LastModified || + propertyName == Constants.Properties.SelfLink || + propertyName == Constants.Properties.AttachmentsLink || + propertyName == Constants.Properties.TimeToLive) + { + return true; + } + return false; + } + + //List of Static Property in Document which we dont want to thunk. + internal static bool IsResourceProperty(string propertyName) + { + if (propertyName == "Id" || + propertyName == "ResourceId" || + propertyName == "ETag" || + propertyName == "Timestamp" || + propertyName == "SelfLink" || + propertyName == "AttachmentsLink" || + propertyName == "TimeToLive") + { + return true; + } + return false; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs index 2adb2de13e..44cb28d6a3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs @@ -1,1172 +1,1168 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Globalization; - using System.Linq; - using Microsoft.Azure.Documents.Routing; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Represents a document collection in the Azure Cosmos DB service. A collection is a named logical container for documents. - /// - /// - /// A database may contain zero or more named collections and each collection consists of zero or more JSON documents. - /// Being schema-free, the documents in a collection do not need to share the same structure or fields. Since collections are application resources, - /// they can be authorized using either the master key or resource keys. - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#collections for more details on collections. - /// - /// - /// The example below creates a new partitioned collection with 50000 Request-per-Unit throughput. - /// The partition key is the first level 'country' property in all the documents within this collection. - /// - /// { "/country" } - /// } - /// }, - /// new RequestOptions { OfferThroughput = 50000} ).Result; - /// ]]> - /// - /// - /// - /// The example below creates a new collection with OfferThroughput set to 10000. - /// - /// - /// - /// - /// - /// The example below creates a new collection with a custom indexing policy. - /// - /// - /// - /// - /// - /// The example below creates a document of type Book inside this collection. - /// - /// - /// - /// - /// - /// The example below queries for a Database by Id to retrieve the SelfLink. - /// - /// c.Id == "myColl").AsEnumerable().FirstOrDefault(); - /// string collectionLink = collection.SelfLink; - /// ]]> - /// - /// - /// - /// The example below deletes this collection. - /// - /// - /// - /// - /// - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class DocumentCollection : Resource - { - private IndexingPolicy indexingPolicy; - private GeospatialConfig geospatialConfig; - private PartitionKeyDefinition partitionKey; - private SchemaDiscoveryPolicy schemaDiscoveryPolicy; - private UniqueKeyPolicy uniqueKeyPolicy; - private UniqueIndexReIndexContext uniqueIndexReIndexContext; - private ConflictResolutionPolicy conflictResolutionPolicy; - private ChangeFeedPolicy changeFeedPolicy; - private CollectionBackupPolicy collectionBackupPolicy; - private MaterializedViewDefinition materializedViewDefinition; - private ByokConfig byokConfig; - private ClientEncryptionPolicy clientEncryptionPolicy; - private DataMaskingPolicy dataMaskingPolicy; - private Collection materializedViews; - private EncryptionScopeMetadata encryptionScopeMetadata; - private InAccountRestoreParameters restoreParameters; - private byte uniqueIndexNameEncodingMode; - private Collection computedProperties; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public DocumentCollection() - { - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// The indexing policy associated with the collection. - /// - public IndexingPolicy IndexingPolicy - { - get - { - if (this.indexingPolicy == null) - { - this.indexingPolicy = base.GetObject(Constants.Properties.IndexingPolicy) ?? new IndexingPolicy(); - } - - return this.indexingPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "IndexingPolicy")); - } - - this.indexingPolicy = value; - base.SetObject(Constants.Properties.IndexingPolicy, value); - } - } - - /// - /// Gets or sets the collection containing objects in the container. - /// - /// - /// The collection containing objects associated with the container. - /// - [JsonProperty(PropertyName = Constants.Properties.ComputedProperties)] - internal Collection ComputedProperties - { - get - { - if (this.computedProperties == null) - { - this.computedProperties = base.GetValue>(Constants.Properties.ComputedProperties); - if (this.computedProperties == null) - { - this.computedProperties = new Collection(); - } - } - - return this.computedProperties; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "computedProperties")); - } - - this.computedProperties = value; - base.SetValue(Constants.Properties.ComputedProperties, this.computedProperties); - } - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// Geospatial type of collection i.e. geography or geometry - /// - [JsonProperty(PropertyName = Constants.Properties.GeospatialConfig)] - public GeospatialConfig GeospatialConfig - { - get - { - if (this.geospatialConfig == null) - { - this.geospatialConfig = base.GetObject(Constants.Properties.GeospatialConfig) ?? new GeospatialConfig(); - } - - return this.geospatialConfig; - } - set - { - this.geospatialConfig = value; - base.SetObject(Constants.Properties.GeospatialConfig, value); - } - } - - /// - /// Gets or sets the encryption scope id of the collection. - /// - /// - /// It is an optional property. This property should be only present when - /// collection level encryption is enabled on the collection. - /// - [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.EncryptionScopeId)] - internal string EncryptionScopeId - { - get - { - return base.GetValue(Constants.EncryptionScopeProperties.EncryptionScopeId); - } - set - { - this.SetValue(Constants.EncryptionScopeProperties.EncryptionScopeId, value); - } - } - - /// - /// Gets the associated with the collection. - /// - [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.EncryptionScope)] - internal EncryptionScopeMetadata EncryptionScopeMetadata - { - get - { - if (this.encryptionScopeMetadata == null) - { - this.encryptionScopeMetadata = - base.GetObject( - Constants.EncryptionScopeProperties.EncryptionScope) ?? new EncryptionScopeMetadata(); - } - - return this.encryptionScopeMetadata; - } - set - { - this.encryptionScopeMetadata = value; - base.SetObject(Constants.EncryptionScopeProperties.EncryptionScope, value); - } - } - - /// - /// Gets the associated with the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.MaterializedViewDefinition)] - internal MaterializedViewDefinition MaterializedViewDefinition - { - get - { - if (this.materializedViewDefinition == null) - { - this.materializedViewDefinition = base.GetObject(Constants.Properties.MaterializedViewDefinition) ?? new MaterializedViewDefinition(); - } - - return this.materializedViewDefinition; - } - set - { - this.materializedViewDefinition = value; - base.SetObject(Constants.Properties.MaterializedViewDefinition, value); - } - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// Byok status of collection i.e. None or Active - /// - [JsonProperty(PropertyName = Constants.Properties.ByokConfig)] - internal ByokConfig ByokConfig - { - get - { - if (this.byokConfig == null) - { - this.byokConfig = base.GetObject(Constants.Properties.ByokConfig) ?? new ByokConfig(); - } - - return this.byokConfig; - } - set - { - this.byokConfig = value; - base.SetObject(Constants.Properties.ByokConfig, value); - } - } - - /// - /// Gets the UniqueIndexNameEncodingMode associated with the collection from the Azure Cosmos DB service. - /// - /// - /// UniqueIndexNameEncodingMode of collection, i.e., either Concatenated (1) or Hashed (2) - /// - [JsonProperty(PropertyName = Constants.Properties.UniqueIndexNameEncodingMode)] - internal byte UniqueIndexNameEncodingMode - { - get - { - return this.GetValue(Constants.Properties.UniqueIndexNameEncodingMode); - } - set - { - if(value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueIndexNameEncodingMode")); - } - this.uniqueIndexNameEncodingMode = value; - this.SetValue(Constants.Properties.UniqueIndexNameEncodingMode, value); - } - } - - /// - /// Gets the self-link for documents in a collection from the Azure Cosmos DB service. - /// - /// - /// The self-link for documents in a collection. - /// - [JsonProperty(PropertyName = Constants.Properties.DocumentsLink)] - public string DocumentsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.DocumentsLink); - } - } - - /// - /// Gets the self-link for stored procedures in a collection from the Azure Cosmos DB service. - /// - /// - /// The self-link for stored procedures in a collection. - /// - [JsonProperty(PropertyName = Constants.Properties.StoredProceduresLink)] - public string StoredProceduresLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.StoredProceduresLink); - } - } - - /// - /// Gets the self-link for triggers in a collection from the Azure Cosmos DB service. - /// - /// - /// The self-link for triggers in a collection. - /// - public string TriggersLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.TriggersLink); - } - } - - /// - /// Gets the self-link for user defined functions in a collection from the Azure Cosmos DB service. - /// - /// - /// The self-link for user defined functions in a collection. - /// - public string UserDefinedFunctionsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.UserDefinedFunctionsLink); - } - } - - /// - /// Gets the self-link for conflicts in a collection from the Azure Cosmos DB service. - /// - /// - /// The self-link for conflicts in a collection. - /// - public string ConflictsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.ConflictsLink); - } - } - - /// - /// Gets or sets object in the Azure Cosmos DB service. - /// - /// - /// object. - /// - [JsonProperty(PropertyName = Constants.Properties.PartitionKey)] - public PartitionKeyDefinition PartitionKey - { - get - { - // Thread safe lazy initialization for case when collection is cached (and is basically readonly). - if (this.partitionKey == null) - { - this.partitionKey = base.GetValue(Constants.Properties.PartitionKey) ?? new PartitionKeyDefinition(); - } - - return this.partitionKey; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "PartitionKey")); - } - - this.partitionKey = value; - base.SetValue(Constants.Properties.PartitionKey, this.partitionKey); - } - } - - /// - /// Gets the default time to live in seconds for documents in a collection from the Azure Cosmos DB service. - /// - /// - /// It is an optional property. - /// A valid value must be either a nonzero positive integer, '-1', or null. - /// By default, DefaultTimeToLive is set to null meaning the time to live is turned off for the collection. - /// The unit of measurement is seconds. The maximum allowed value is 2147483647. - /// - /// - /// - /// The will be applied to all the documents in the collection as the default time-to-live policy. - /// The individual document could override the default time-to-live policy by setting its . - /// - /// - /// When the is null, the time-to-live will be turned off for the collection. - /// It means all the documents will never expire. The individual document's will be disregarded. - /// - /// - /// When the is '-1', the time-to-live will be turned on for the collection. - /// By default, all the documents will never expire. The individual document could be given a specific time-to-live value by setting its - /// . The document's will be honored, and the expired documents - /// will be deleted in background. - /// - /// - /// When the is a nonzero positive integer, the time-to-live will be turned on for the collection. - /// And a default time-to-live in seconds will be applied to all the documents. A document will be expired after the - /// specified value in seconds since its last write time. - /// The individual document could override the default time-to-live policy by setting its . - /// Please refer to the for more details about evaluating the final time-to-live policy of a document. - /// - /// - /// - /// The example below disables time-to-live on a collection. - /// - /// - /// - /// - /// - /// The example below enables time-to-live on a collection. By default, all the documents never expire. - /// - /// - /// - /// - /// - /// The example below enables time-to-live on a collection. By default, the document will expire after 1000 seconds - /// since its last write time. - /// - /// - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.DefaultTimeToLive, NullValueHandling = NullValueHandling.Ignore)] - public int? DefaultTimeToLive - { - get - { - return base.GetValue(Constants.Properties.DefaultTimeToLive); - } - set - { - base.SetValue(Constants.Properties.DefaultTimeToLive, value); - } - } - - /// - /// Gets or sets the time to live base timestamp property path. - /// - /// - /// It is an optional property. - /// This property should be only present when DefaultTimeToLive is set. When this property is present, time to live - /// for a document is decided based on the value of this property in document. - /// By default, TimeToLivePropertyPath is set to null meaning the time to live is based on the _ts property in document. - /// - [JsonProperty(PropertyName = Constants.Properties.TimeToLivePropertyPath, NullValueHandling = NullValueHandling.Ignore)] - public string TimeToLivePropertyPath - { - get - { - return this.GetValue(Constants.Properties.TimeToLivePropertyPath); - } - set - { - this.SetValue(Constants.Properties.TimeToLivePropertyPath, value); - } - } - - /// - /// Gets the associated with the collection. - /// - /// - /// The schema discovery policy associated with the collection. - /// - internal SchemaDiscoveryPolicy SchemaDiscoveryPolicy - { - get - { - // Thread safe lazy initialization for case when collection is cached (and is basically readonly). - if (this.schemaDiscoveryPolicy == null) - { - this.schemaDiscoveryPolicy = base.GetObject(Constants.Properties.SchemaDiscoveryPolicy) ?? new SchemaDiscoveryPolicy(); - } - - return this.schemaDiscoveryPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "SchemaDiscoveryPolicy")); - } - - this.schemaDiscoveryPolicy = value; - base.SetObject(Constants.Properties.SchemaDiscoveryPolicy, value); - } - } - - /// - /// Gets or sets the that guarantees uniqueness of documents in collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.UniqueKeyPolicy)] - public UniqueKeyPolicy UniqueKeyPolicy - { - get - { - // Thread safe lazy initialization for case when collection is cached (and is basically readonly). - if (this.uniqueKeyPolicy == null) - { - this.uniqueKeyPolicy = base.GetObject(Constants.Properties.UniqueKeyPolicy) ?? new UniqueKeyPolicy(); - } - - return this.uniqueKeyPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeyPolicy")); - } - - this.uniqueKeyPolicy = value; - base.SetObject(Constants.Properties.UniqueKeyPolicy, value); - } - } - - /// - /// Gets or sets the that used for internal unique index reindex context purpose. - /// - [JsonProperty(PropertyName = Constants.Properties.UniqueIndexReIndexContext)] - internal UniqueIndexReIndexContext UniqueIndexReIndexContext - { - get - { - // Thread safe lazy initialization for case when collection is cached (and is basically readonly). - if (this.uniqueIndexReIndexContext == null) - { - this.uniqueIndexReIndexContext = base.GetObject(Constants.Properties.UniqueIndexReIndexContext) ?? new UniqueIndexReIndexContext(); - } - - return this.uniqueIndexReIndexContext; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueIndexReIndexContext")); - } - - this.uniqueIndexReIndexContext = value; - base.SetObject(Constants.Properties.UniqueIndexReIndexContext, value); - } - } - - /// - /// Gets or sets the that is used for resolving conflicting writes on documents in different regions, in a collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionPolicy)] - public ConflictResolutionPolicy ConflictResolutionPolicy - { - get - { - // Thread safe lazy initialization for case when collection is cached (and is basically readonly). - if (this.conflictResolutionPolicy == null) - { - this.conflictResolutionPolicy = base.GetObject(Constants.Properties.ConflictResolutionPolicy) ?? new ConflictResolutionPolicy(); - } - - return this.conflictResolutionPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ConflictResolutionPolicy")); - } - - this.conflictResolutionPolicy = value; - base.SetObject(Constants.Properties.ConflictResolutionPolicy, value); - } - } - - /// - /// Gets or sets the PartitionKeyDeleteThroughputFraction for the collection. - /// - [Obsolete("PartitionKeyDeleteThroughputFraction is deprecated.")] - [JsonProperty(PropertyName = Constants.Properties.PartitionKeyDeleteThroughputFraction)] - public double PartitionKeyDeleteThroughputFraction - { - get - { - return this.GetValue(Constants.Properties.PartitionKeyDeleteThroughputFraction); - } - set - { - this.SetValue(Constants.Properties.PartitionKeyDeleteThroughputFraction, value); - } - } - - /// - /// Gets a collection of object in the Azure Cosmos DB service. - /// - /// - /// object. - /// - /// - /// This is reported based on a sub-sampling of partition keys within the collection and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. - /// - /// - /// The following code shows how to log statistics for all partition key ranges as a string: - /// - /// - /// - /// To log individual partition key range statistics, use the following code: - /// - /// - /// - /// The output will look something like that: - /// "statistics": [ - /// {"id":"0","sizeInKB":1410184,"documentCount":42807,"partitionKeys":[]}, - /// {"id":"1","sizeInKB":3803113,"documentCount":150530,"partitionKeys":[{"partitionKey":["4009696"],"sizeInKB":3731654}]}, - /// {"id":"2","sizeInKB":1447855,"documentCount":59056,"partitionKeys":[{"partitionKey":["4009633"],"sizeInKB":2861210},{"partitionKey":["4004207"],"sizeInKB":2293163}]}, - /// {"id":"3","sizeInKB":1026254,"documentCount":44241,"partitionKeys":[]}, - /// {"id":"4","sizeInKB":3250973,"documentCount":124959,"partitionKeys":[]} - /// ] - /// - /// - /// - [JsonIgnore] - public IReadOnlyList PartitionKeyRangeStatistics - { - get - { - List list = this.StatisticsJRaw - .Where(jraw => jraw != null) - .Select(jraw => JsonConvert.DeserializeObject((string)jraw.Value)) - .ToList(); - - return new JsonSerializableList(list); - } - } - - [JsonProperty(PropertyName = Constants.Properties.Statistics)] - internal IReadOnlyList StatisticsJRaw - { - get - { - return base.GetValue>(Constants.Properties.Statistics) ?? new Collection(); - } - set - { - base.SetValue(Constants.Properties.Statistics, value); - } - } - - internal bool HasPartitionKey - { - get - { - if (this.partitionKey != null) - { - return true; - } - - return base.GetValue(Constants.Properties.PartitionKey) != null; - } - } - - /// - /// Instantiates a new instance of the object. - /// - /// - /// The function selects the right partition key constant for inserting documents that don't have - /// a value for partition key. The constant selection is based on whether the collection is migrated - /// or user partitioned - /// - internal PartitionKeyInternal NonePartitionKeyValue - { - get - { - if (this.PartitionKey.Paths.Count == 0 || this.PartitionKey.IsSystemKey.GetValueOrDefault(false)) - { - return PartitionKeyInternal.Empty; - } - else - { - return PartitionKeyInternal.Undefined; - } - } - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// The change feed policy associated with the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.ChangeFeedPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal ChangeFeedPolicy ChangeFeedPolicy - { - get - { - if (this.changeFeedPolicy == null) - { - this.changeFeedPolicy = base.GetObject(Constants.Properties.ChangeFeedPolicy); - } - - return this.changeFeedPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ChangeFeedPolicy")); - } - - this.changeFeedPolicy = value; - base.SetObject(Constants.Properties.ChangeFeedPolicy, value); - } - } - - /// - /// Gets the analytical storage time to live in seconds for documents in a collection from the Azure Cosmos DB service. - /// - /// - /// It is an optional property. - /// A valid value must be either a nonzero positive integer, '-1', or 0. - /// By default, AnalyticalStorageTimeToLive is set to 0 meaning the analytical store is turned off for the collection; -1 means documents - /// in analytical store never expire. - /// The unit of measurement is seconds. The maximum allowed value is 2147483647. - /// - [JsonProperty(PropertyName = Constants.Properties.AnalyticalStorageTimeToLive, NullValueHandling = NullValueHandling.Ignore)] - internal int? AnalyticalStorageTimeToLive - { - get - { - return base.GetValue(Constants.Properties.AnalyticalStorageTimeToLive); - } - set - { - base.SetValue(Constants.Properties.AnalyticalStorageTimeToLive, value); - } - } - - /// - /// Gets if creation of MaterializedViews is allowed on the collection. - /// - /// - /// It is an optional property. - /// A valid value must be either true or false - /// By default, AllowMaterializedViews is set to false meaning the creation of materializedViews is not allowed on collection; - /// - [JsonProperty(PropertyName = Constants.Properties.AllowMaterializedViews, NullValueHandling = NullValueHandling.Ignore)] - internal bool? AllowMaterializedViews - { - get - { - return base.GetValue(Constants.Properties.AllowMaterializedViews); - } - set - { - base.SetValue(Constants.Properties.AllowMaterializedViews, value); - } - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// The backup policy associated with the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.CollectionBackupPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal CollectionBackupPolicy CollectionBackupPolicy - { - get - { - if (this.collectionBackupPolicy == null) - { - this.collectionBackupPolicy = base.GetObject(Constants.Properties.CollectionBackupPolicy); - } - - return this.collectionBackupPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "CollectionBackupPolicy")); - } - - this.collectionBackupPolicy = value; - base.SetObject(Constants.Properties.CollectionBackupPolicy, value); - } - } - - /// - /// Gets or sets the schema policy on collection in the Azure Cosmos DB service. - /// - /// - /// The schema policy here currently is just a raw JSON. Bringing full object model - /// (see Product\Cosmos\Compute\Core\InteropClient\SchemaPolicy.cs) is not currenlty needed. - /// - /// - /// string schemaPolicy = ...; - /// collection.SchemaPolicy = new JRaw(schemaPolicy); - /// collection.InternalSchemaProperties = new InternalSchemaProperties { UseSchemaForAnalyticsOnly = true }; - /// - [JsonProperty(PropertyName = Constants.Properties.SchemaPolicy, NullValueHandling = NullValueHandling.Ignore)] - internal JRaw SchemaPolicy - { - get - { - return base.GetValue(Constants.Properties.SchemaPolicy); - } - set - { - base.SetValue(Constants.Properties.SchemaPolicy, value); - } - } - - /// - /// Gets or sets the schema policy on collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.InternalSchemaProperties, NullValueHandling = NullValueHandling.Ignore)] - internal InternalSchemaProperties InternalSchemaProperties - { - get - { - return base.GetValue(Constants.Properties.InternalSchemaProperties); - } - set - { - base.SetValue(Constants.Properties.InternalSchemaProperties, value); - } - } - - internal bool IsMaterializedView() - { - return this.MaterializedViewDefinition != null - && (!string.IsNullOrEmpty(this.MaterializedViewDefinition.SourceCollectionRid) || !string.IsNullOrEmpty(this.MaterializedViewDefinition.SourceCollectionId)); - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// The ClientEncryptionPolicy associated with the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.ClientEncryptionPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal ClientEncryptionPolicy ClientEncryptionPolicy - { - get - { - if (this.clientEncryptionPolicy == null) - { - this.clientEncryptionPolicy = base.GetObject(Constants.Properties.ClientEncryptionPolicy); - } - - return this.clientEncryptionPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(ClientEncryptionPolicy))); - } - - this.clientEncryptionPolicy = value; - base.SetObject(Constants.Properties.ClientEncryptionPolicy, value); - } - } - - /// - /// Gets the associated with the collection from the Azure Cosmos DB service. - /// - /// - /// The DataMaskingPolicy associated with the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.DataMaskingPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal DataMaskingPolicy DataMaskingPolicy - { - get - { - if (this.dataMaskingPolicy == null) - { - this.dataMaskingPolicy = base.GetObject(Constants.Properties.DataMaskingPolicy); - } - - return this.dataMaskingPolicy; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(DataMaskingPolicy))); - } - - this.dataMaskingPolicy = value; - base.SetObject(Constants.Properties.DataMaskingPolicy, value); - } - } - - /// - /// Gets the materialized views on the collection. - /// - [JsonProperty(PropertyName = Constants.Properties.MaterializedViews, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] - internal Collection MaterializedViews - { - get - { - if (this.materializedViews == null) - { - Collection materializedViewsValues = base.GetValueCollection(Constants.Properties.MaterializedViews); - if (materializedViewsValues == null) - { - this.materializedViews = new Collection(); - } - else - { - this.materializedViews = materializedViewsValues; - } - } - return this.materializedViews; - } - set - { - this.materializedViews = value; - base.SetValueCollection(Constants.Properties.MaterializedViews, value); - } - } - - /// - /// Gets or sets the for triggering the InAccountRestore of the collection - /// - /// - /// It is an optional property. - /// A valid value should be Default or Restore - /// - [JsonProperty(PropertyName = Constants.Properties.CreateMode, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal DatabaseOrCollectionCreateMode? CreateMode - { - get - { - return base.GetValue(Constants.Properties.CreateMode, null); - } - set - { - base.SetValue(Constants.Properties.CreateMode, value.ToString()); - } - } - - /// - /// Gets or sets the for triggering the InAccountRestore of the collection - /// - /// - /// It is an optional property. - /// A valid value should have both RestoreSource and RestoreTimestampInUtc - /// - [JsonProperty(PropertyName = Constants.Properties.RestoreParams, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] - internal InAccountRestoreParameters RestoreParameters - { - get - { - if (this.restoreParameters == null) - { - this.restoreParameters = base.GetObject(Constants.Properties.RestoreParams); - } - - return this.restoreParameters; - } - set - { - this.restoreParameters = value; - base.SetObject(Constants.Properties.RestoreParams, value); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.DefaultTimeToLive); - base.GetValue(Constants.Properties.TimeToLivePropertyPath); - this.IndexingPolicy.Validate(); - this.PartitionKey.Validate(); - this.UniqueKeyPolicy.Validate(); - this.ConflictResolutionPolicy.Validate(); - this.UniqueIndexReIndexContext.Validate(); - - foreach (ComputedProperty computedProperty in this.ComputedProperties) - { - computedProperty.Validate(); - } - } - - internal override void OnSave() - { - if (this.indexingPolicy != null) - { - this.indexingPolicy.OnSave(); - base.SetObject(Constants.Properties.IndexingPolicy, this.indexingPolicy); - } - - if (this.partitionKey != null) - { - base.SetValue(Constants.Properties.PartitionKey, this.partitionKey); - } - - if (this.uniqueKeyPolicy != null) - { - this.uniqueKeyPolicy.OnSave(); - base.SetObject(Constants.Properties.UniqueKeyPolicy, this.uniqueKeyPolicy); - } - - if (this.conflictResolutionPolicy != null) - { - this.conflictResolutionPolicy.OnSave(); - base.SetObject(Constants.Properties.ConflictResolutionPolicy, this.conflictResolutionPolicy); - } - - if (this.schemaDiscoveryPolicy != null) - { - base.SetObject(Constants.Properties.SchemaDiscoveryPolicy, this.schemaDiscoveryPolicy); - } - - if (this.changeFeedPolicy != null) - { - base.SetObject(Constants.Properties.ChangeFeedPolicy, this.changeFeedPolicy); - } - - if (this.collectionBackupPolicy != null) - { - base.SetObject(Constants.Properties.CollectionBackupPolicy, this.collectionBackupPolicy); - } - - if (this.geospatialConfig != null) - { - base.SetObject(Constants.Properties.GeospatialConfig, this.geospatialConfig); - } - - if(this.byokConfig != null) - { - base.SetObject(Constants.Properties.ByokConfig, this.byokConfig); - } - - if (this.uniqueIndexReIndexContext != null) - { - this.uniqueIndexReIndexContext.OnSave(); - base.SetObject(Constants.Properties.UniqueIndexReIndexContext, this.uniqueIndexReIndexContext); - } - - if (this.clientEncryptionPolicy != null) - { - base.SetObject(Constants.Properties.ClientEncryptionPolicy, this.clientEncryptionPolicy); - } - - if (this.dataMaskingPolicy != null) - { - base.SetObject(Constants.Properties.DataMaskingPolicy, this.dataMaskingPolicy); - } - - if (this.materializedViews != null) - { - base.SetValueCollection(Constants.Properties.MaterializedViews, this.materializedViews); - } - - if (this.computedProperties != null) - { - base.SetValueCollection(Constants.Properties.ComputedProperties, this.computedProperties); - } - - if (this.restoreParameters != null) - { - base.SetObject(Constants.Properties.RestoreParams, this.restoreParameters); - } - - // todo(Mukum): remove the encryptionscopeId check once backend contract is checked in. - if (this.encryptionScopeMetadata != null && !string.IsNullOrWhiteSpace(this.encryptionScopeMetadata.Id)) - { - this.encryptionScopeMetadata.OnSave(); - base.SetObject(Constants.EncryptionScopeProperties.EncryptionScope, this.encryptionScopeMetadata); - } - - if(this.uniqueIndexNameEncodingMode != 0) - { - base.SetValue(Constants.Properties.UniqueIndexNameEncodingMode, this.uniqueIndexNameEncodingMode); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Globalization; + using System.Linq; + using Microsoft.Azure.Documents.Routing; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents a document collection in the Azure Cosmos DB service. A collection is a named logical container for documents. + /// + /// + /// A database may contain zero or more named collections and each collection consists of zero or more JSON documents. + /// Being schema-free, the documents in a collection do not need to share the same structure or fields. Since collections are application resources, + /// they can be authorized using either the master key or resource keys. + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#collections for more details on collections. + /// + /// + /// The example below creates a new partitioned collection with 50000 Request-per-Unit throughput. + /// The partition key is the first level 'country' property in all the documents within this collection. + /// + /// { "/country" } + /// } + /// }, + /// new RequestOptions { OfferThroughput = 50000} ).Result; + /// ]]> + /// + /// + /// + /// The example below creates a new collection with OfferThroughput set to 10000. + /// + /// + /// + /// + /// + /// The example below creates a new collection with a custom indexing policy. + /// + /// + /// + /// + /// + /// The example below creates a document of type Book inside this collection. + /// + /// + /// + /// + /// + /// The example below queries for a Database by Id to retrieve the SelfLink. + /// + /// c.Id == "myColl").AsEnumerable().FirstOrDefault(); + /// string collectionLink = collection.SelfLink; + /// ]]> + /// + /// + /// + /// The example below deletes this collection. + /// + /// + /// + /// + /// + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class DocumentCollection : Resource + { + private IndexingPolicy indexingPolicy; + private GeospatialConfig geospatialConfig; + private PartitionKeyDefinition partitionKey; + private SchemaDiscoveryPolicy schemaDiscoveryPolicy; + private UniqueKeyPolicy uniqueKeyPolicy; + private UniqueIndexReIndexContext uniqueIndexReIndexContext; + private ConflictResolutionPolicy conflictResolutionPolicy; + private ChangeFeedPolicy changeFeedPolicy; + private CollectionBackupPolicy collectionBackupPolicy; + private MaterializedViewDefinition materializedViewDefinition; + private ByokConfig byokConfig; + private ClientEncryptionPolicy clientEncryptionPolicy; + private DataMaskingPolicy dataMaskingPolicy; + private Collection materializedViews; + private EncryptionScopeMetadata encryptionScopeMetadata; + private InAccountRestoreParameters restoreParameters; + private byte uniqueIndexNameEncodingMode; + private Collection computedProperties; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public DocumentCollection() + { + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The indexing policy associated with the collection. + /// + public IndexingPolicy IndexingPolicy + { + get + { + if (this.indexingPolicy == null) + { + this.indexingPolicy = base.GetObject(Constants.Properties.IndexingPolicy) ?? new IndexingPolicy(); + } + + return this.indexingPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "IndexingPolicy")); + } + + this.indexingPolicy = value; + base.SetObject(Constants.Properties.IndexingPolicy, value); + } + } + + /// + /// Gets or sets the collection containing objects in the container. + /// + /// + /// The collection containing objects associated with the container. + /// + [JsonProperty(PropertyName = Constants.Properties.ComputedProperties)] + internal Collection ComputedProperties + { + get + { + if (this.computedProperties == null) + { + this.computedProperties = base.GetValue>(Constants.Properties.ComputedProperties); + if (this.computedProperties == null) + { + this.computedProperties = new Collection(); + } + } + + return this.computedProperties; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "computedProperties")); + } + + this.computedProperties = value; + base.SetValue(Constants.Properties.ComputedProperties, this.computedProperties); + } + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// Geospatial type of collection i.e. geography or geometry + /// + [JsonProperty(PropertyName = Constants.Properties.GeospatialConfig)] + public GeospatialConfig GeospatialConfig + { + get + { + if (this.geospatialConfig == null) + { + this.geospatialConfig = base.GetObject(Constants.Properties.GeospatialConfig) ?? new GeospatialConfig(); + } + + return this.geospatialConfig; + } + set + { + this.geospatialConfig = value; + base.SetObject(Constants.Properties.GeospatialConfig, value); + } + } + + /// + /// Gets or sets the encryption scope id of the collection. + /// + /// + /// It is an optional property. This property should be only present when + /// collection level encryption is enabled on the collection. + /// + [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.EncryptionScopeId)] + internal string EncryptionScopeId + { + get + { + return base.GetValue(Constants.EncryptionScopeProperties.EncryptionScopeId); + } + set + { + this.SetValue(Constants.EncryptionScopeProperties.EncryptionScopeId, value); + } + } + + /// + /// Gets the associated with the collection. + /// + [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.EncryptionScope)] + internal EncryptionScopeMetadata EncryptionScopeMetadata + { + get + { + if (this.encryptionScopeMetadata == null) + { + this.encryptionScopeMetadata = + base.GetObject( + Constants.EncryptionScopeProperties.EncryptionScope) ?? new EncryptionScopeMetadata(); + } + + return this.encryptionScopeMetadata; + } + set + { + this.encryptionScopeMetadata = value; + base.SetObject(Constants.EncryptionScopeProperties.EncryptionScope, value); + } + } + + /// + /// Gets the associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.MaterializedViewDefinition)] + internal MaterializedViewDefinition MaterializedViewDefinition + { + get + { + if (this.materializedViewDefinition == null) + { + this.materializedViewDefinition = base.GetObject(Constants.Properties.MaterializedViewDefinition) ?? new MaterializedViewDefinition(); + } + + return this.materializedViewDefinition; + } + set + { + this.materializedViewDefinition = value; + base.SetObject(Constants.Properties.MaterializedViewDefinition, value); + } + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// Byok status of collection i.e. None or Active + /// + [JsonProperty(PropertyName = Constants.Properties.ByokConfig)] + internal ByokConfig ByokConfig + { + get + { + if (this.byokConfig == null) + { + this.byokConfig = base.GetObject(Constants.Properties.ByokConfig) ?? new ByokConfig(); + } + + return this.byokConfig; + } + set + { + this.byokConfig = value; + base.SetObject(Constants.Properties.ByokConfig, value); + } + } + + /// + /// Gets the UniqueIndexNameEncodingMode associated with the collection from the Azure Cosmos DB service. + /// + /// + /// UniqueIndexNameEncodingMode of collection, i.e., either Concatenated (1) or Hashed (2) + /// + [JsonProperty(PropertyName = Constants.Properties.UniqueIndexNameEncodingMode)] + internal byte UniqueIndexNameEncodingMode + { + get + { + return this.GetValue(Constants.Properties.UniqueIndexNameEncodingMode); + } + set + { + this.uniqueIndexNameEncodingMode = value; + this.SetValue(Constants.Properties.UniqueIndexNameEncodingMode, value); + } + } + + /// + /// Gets the self-link for documents in a collection from the Azure Cosmos DB service. + /// + /// + /// The self-link for documents in a collection. + /// + [JsonProperty(PropertyName = Constants.Properties.DocumentsLink)] + public string DocumentsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.DocumentsLink); + } + } + + /// + /// Gets the self-link for stored procedures in a collection from the Azure Cosmos DB service. + /// + /// + /// The self-link for stored procedures in a collection. + /// + [JsonProperty(PropertyName = Constants.Properties.StoredProceduresLink)] + public string StoredProceduresLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.StoredProceduresLink); + } + } + + /// + /// Gets the self-link for triggers in a collection from the Azure Cosmos DB service. + /// + /// + /// The self-link for triggers in a collection. + /// + public string TriggersLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.TriggersLink); + } + } + + /// + /// Gets the self-link for user defined functions in a collection from the Azure Cosmos DB service. + /// + /// + /// The self-link for user defined functions in a collection. + /// + public string UserDefinedFunctionsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.UserDefinedFunctionsLink); + } + } + + /// + /// Gets the self-link for conflicts in a collection from the Azure Cosmos DB service. + /// + /// + /// The self-link for conflicts in a collection. + /// + public string ConflictsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.ConflictsLink); + } + } + + /// + /// Gets or sets object in the Azure Cosmos DB service. + /// + /// + /// object. + /// + [JsonProperty(PropertyName = Constants.Properties.PartitionKey)] + public PartitionKeyDefinition PartitionKey + { + get + { + // Thread safe lazy initialization for case when collection is cached (and is basically readonly). + if (this.partitionKey == null) + { + this.partitionKey = base.GetValue(Constants.Properties.PartitionKey) ?? new PartitionKeyDefinition(); + } + + return this.partitionKey; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "PartitionKey")); + } + + this.partitionKey = value; + base.SetValue(Constants.Properties.PartitionKey, this.partitionKey); + } + } + + /// + /// Gets the default time to live in seconds for documents in a collection from the Azure Cosmos DB service. + /// + /// + /// It is an optional property. + /// A valid value must be either a nonzero positive integer, '-1', or null. + /// By default, DefaultTimeToLive is set to null meaning the time to live is turned off for the collection. + /// The unit of measurement is seconds. The maximum allowed value is 2147483647. + /// + /// + /// + /// The will be applied to all the documents in the collection as the default time-to-live policy. + /// The individual document could override the default time-to-live policy by setting its . + /// + /// + /// When the is null, the time-to-live will be turned off for the collection. + /// It means all the documents will never expire. The individual document's will be disregarded. + /// + /// + /// When the is '-1', the time-to-live will be turned on for the collection. + /// By default, all the documents will never expire. The individual document could be given a specific time-to-live value by setting its + /// . The document's will be honored, and the expired documents + /// will be deleted in background. + /// + /// + /// When the is a nonzero positive integer, the time-to-live will be turned on for the collection. + /// And a default time-to-live in seconds will be applied to all the documents. A document will be expired after the + /// specified value in seconds since its last write time. + /// The individual document could override the default time-to-live policy by setting its . + /// Please refer to the for more details about evaluating the final time-to-live policy of a document. + /// + /// + /// + /// The example below disables time-to-live on a collection. + /// + /// + /// + /// + /// + /// The example below enables time-to-live on a collection. By default, all the documents never expire. + /// + /// + /// + /// + /// + /// The example below enables time-to-live on a collection. By default, the document will expire after 1000 seconds + /// since its last write time. + /// + /// + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.DefaultTimeToLive, NullValueHandling = NullValueHandling.Ignore)] + public int? DefaultTimeToLive + { + get + { + return base.GetValue(Constants.Properties.DefaultTimeToLive); + } + set + { + base.SetValue(Constants.Properties.DefaultTimeToLive, value); + } + } + + /// + /// Gets or sets the time to live base timestamp property path. + /// + /// + /// It is an optional property. + /// This property should be only present when DefaultTimeToLive is set. When this property is present, time to live + /// for a document is decided based on the value of this property in document. + /// By default, TimeToLivePropertyPath is set to null meaning the time to live is based on the _ts property in document. + /// + [JsonProperty(PropertyName = Constants.Properties.TimeToLivePropertyPath, NullValueHandling = NullValueHandling.Ignore)] + public string TimeToLivePropertyPath + { + get + { + return this.GetValue(Constants.Properties.TimeToLivePropertyPath); + } + set + { + this.SetValue(Constants.Properties.TimeToLivePropertyPath, value); + } + } + + /// + /// Gets the associated with the collection. + /// + /// + /// The schema discovery policy associated with the collection. + /// + internal SchemaDiscoveryPolicy SchemaDiscoveryPolicy + { + get + { + // Thread safe lazy initialization for case when collection is cached (and is basically readonly). + if (this.schemaDiscoveryPolicy == null) + { + this.schemaDiscoveryPolicy = base.GetObject(Constants.Properties.SchemaDiscoveryPolicy) ?? new SchemaDiscoveryPolicy(); + } + + return this.schemaDiscoveryPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "SchemaDiscoveryPolicy")); + } + + this.schemaDiscoveryPolicy = value; + base.SetObject(Constants.Properties.SchemaDiscoveryPolicy, value); + } + } + + /// + /// Gets or sets the that guarantees uniqueness of documents in collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.UniqueKeyPolicy)] + public UniqueKeyPolicy UniqueKeyPolicy + { + get + { + // Thread safe lazy initialization for case when collection is cached (and is basically readonly). + if (this.uniqueKeyPolicy == null) + { + this.uniqueKeyPolicy = base.GetObject(Constants.Properties.UniqueKeyPolicy) ?? new UniqueKeyPolicy(); + } + + return this.uniqueKeyPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeyPolicy")); + } + + this.uniqueKeyPolicy = value; + base.SetObject(Constants.Properties.UniqueKeyPolicy, value); + } + } + + /// + /// Gets or sets the that used for internal unique index reindex context purpose. + /// + [JsonProperty(PropertyName = Constants.Properties.UniqueIndexReIndexContext)] + internal UniqueIndexReIndexContext UniqueIndexReIndexContext + { + get + { + // Thread safe lazy initialization for case when collection is cached (and is basically readonly). + if (this.uniqueIndexReIndexContext == null) + { + this.uniqueIndexReIndexContext = base.GetObject(Constants.Properties.UniqueIndexReIndexContext) ?? new UniqueIndexReIndexContext(); + } + + return this.uniqueIndexReIndexContext; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueIndexReIndexContext")); + } + + this.uniqueIndexReIndexContext = value; + base.SetObject(Constants.Properties.UniqueIndexReIndexContext, value); + } + } + + /// + /// Gets or sets the that is used for resolving conflicting writes on documents in different regions, in a collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.ConflictResolutionPolicy)] + public ConflictResolutionPolicy ConflictResolutionPolicy + { + get + { + // Thread safe lazy initialization for case when collection is cached (and is basically readonly). + if (this.conflictResolutionPolicy == null) + { + this.conflictResolutionPolicy = base.GetObject(Constants.Properties.ConflictResolutionPolicy) ?? new ConflictResolutionPolicy(); + } + + return this.conflictResolutionPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ConflictResolutionPolicy")); + } + + this.conflictResolutionPolicy = value; + base.SetObject(Constants.Properties.ConflictResolutionPolicy, value); + } + } + + /// + /// Gets or sets the PartitionKeyDeleteThroughputFraction for the collection. + /// + [Obsolete("PartitionKeyDeleteThroughputFraction is deprecated.")] + [JsonProperty(PropertyName = Constants.Properties.PartitionKeyDeleteThroughputFraction)] + public double PartitionKeyDeleteThroughputFraction + { + get + { + return this.GetValue(Constants.Properties.PartitionKeyDeleteThroughputFraction); + } + set + { + this.SetValue(Constants.Properties.PartitionKeyDeleteThroughputFraction, value); + } + } + + /// + /// Gets a collection of object in the Azure Cosmos DB service. + /// + /// + /// object. + /// + /// + /// This is reported based on a sub-sampling of partition keys within the collection and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. + /// + /// + /// The following code shows how to log statistics for all partition key ranges as a string: + /// + /// + /// + /// To log individual partition key range statistics, use the following code: + /// + /// + /// + /// The output will look something like that: + /// "statistics": [ + /// {"id":"0","sizeInKB":1410184,"documentCount":42807,"partitionKeys":[]}, + /// {"id":"1","sizeInKB":3803113,"documentCount":150530,"partitionKeys":[{"partitionKey":["4009696"],"sizeInKB":3731654}]}, + /// {"id":"2","sizeInKB":1447855,"documentCount":59056,"partitionKeys":[{"partitionKey":["4009633"],"sizeInKB":2861210},{"partitionKey":["4004207"],"sizeInKB":2293163}]}, + /// {"id":"3","sizeInKB":1026254,"documentCount":44241,"partitionKeys":[]}, + /// {"id":"4","sizeInKB":3250973,"documentCount":124959,"partitionKeys":[]} + /// ] + /// + /// + /// + [JsonIgnore] + public IReadOnlyList PartitionKeyRangeStatistics + { + get + { + List list = this.StatisticsJRaw + .Where(jraw => jraw != null) + .Select(jraw => JsonConvert.DeserializeObject((string)jraw.Value)) + .ToList(); + + return new JsonSerializableList(list); + } + } + + [JsonProperty(PropertyName = Constants.Properties.Statistics)] + internal IReadOnlyList StatisticsJRaw + { + get + { + return base.GetValue>(Constants.Properties.Statistics) ?? new Collection(); + } + set + { + base.SetValue(Constants.Properties.Statistics, value); + } + } + + internal bool HasPartitionKey + { + get + { + if (this.partitionKey != null) + { + return true; + } + + return base.GetValue(Constants.Properties.PartitionKey) != null; + } + } + + /// + /// Instantiates a new instance of the object. + /// + /// + /// The function selects the right partition key constant for inserting documents that don't have + /// a value for partition key. The constant selection is based on whether the collection is migrated + /// or user partitioned + /// + internal PartitionKeyInternal NonePartitionKeyValue + { + get + { + if (this.PartitionKey.Paths.Count == 0 || this.PartitionKey.IsSystemKey.GetValueOrDefault(false)) + { + return PartitionKeyInternal.Empty; + } + else + { + return PartitionKeyInternal.Undefined; + } + } + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The change feed policy associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.ChangeFeedPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal ChangeFeedPolicy ChangeFeedPolicy + { + get + { + if (this.changeFeedPolicy == null) + { + this.changeFeedPolicy = base.GetObject(Constants.Properties.ChangeFeedPolicy); + } + + return this.changeFeedPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ChangeFeedPolicy")); + } + + this.changeFeedPolicy = value; + base.SetObject(Constants.Properties.ChangeFeedPolicy, value); + } + } + + /// + /// Gets the analytical storage time to live in seconds for documents in a collection from the Azure Cosmos DB service. + /// + /// + /// It is an optional property. + /// A valid value must be either a nonzero positive integer, '-1', or 0. + /// By default, AnalyticalStorageTimeToLive is set to 0 meaning the analytical store is turned off for the collection; -1 means documents + /// in analytical store never expire. + /// The unit of measurement is seconds. The maximum allowed value is 2147483647. + /// + [JsonProperty(PropertyName = Constants.Properties.AnalyticalStorageTimeToLive, NullValueHandling = NullValueHandling.Ignore)] + internal int? AnalyticalStorageTimeToLive + { + get + { + return base.GetValue(Constants.Properties.AnalyticalStorageTimeToLive); + } + set + { + base.SetValue(Constants.Properties.AnalyticalStorageTimeToLive, value); + } + } + + /// + /// Gets if creation of MaterializedViews is allowed on the collection. + /// + /// + /// It is an optional property. + /// A valid value must be either true or false + /// By default, AllowMaterializedViews is set to false meaning the creation of materializedViews is not allowed on collection; + /// + [JsonProperty(PropertyName = Constants.Properties.AllowMaterializedViews, NullValueHandling = NullValueHandling.Ignore)] + internal bool? AllowMaterializedViews + { + get + { + return base.GetValue(Constants.Properties.AllowMaterializedViews); + } + set + { + base.SetValue(Constants.Properties.AllowMaterializedViews, value); + } + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The backup policy associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.CollectionBackupPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal CollectionBackupPolicy CollectionBackupPolicy + { + get + { + if (this.collectionBackupPolicy == null) + { + this.collectionBackupPolicy = base.GetObject(Constants.Properties.CollectionBackupPolicy); + } + + return this.collectionBackupPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "CollectionBackupPolicy")); + } + + this.collectionBackupPolicy = value; + base.SetObject(Constants.Properties.CollectionBackupPolicy, value); + } + } + + /// + /// Gets or sets the schema policy on collection in the Azure Cosmos DB service. + /// + /// + /// The schema policy here currently is just a raw JSON. Bringing full object model + /// (see Product\Cosmos\Compute\Core\InteropClient\SchemaPolicy.cs) is not currenlty needed. + /// + /// + /// string schemaPolicy = ...; + /// collection.SchemaPolicy = new JRaw(schemaPolicy); + /// collection.InternalSchemaProperties = new InternalSchemaProperties { UseSchemaForAnalyticsOnly = true }; + /// + [JsonProperty(PropertyName = Constants.Properties.SchemaPolicy, NullValueHandling = NullValueHandling.Ignore)] + internal JRaw SchemaPolicy + { + get + { + return base.GetValue(Constants.Properties.SchemaPolicy); + } + set + { + base.SetValue(Constants.Properties.SchemaPolicy, value); + } + } + + /// + /// Gets or sets the schema policy on collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.InternalSchemaProperties, NullValueHandling = NullValueHandling.Ignore)] + internal InternalSchemaProperties InternalSchemaProperties + { + get + { + return base.GetValue(Constants.Properties.InternalSchemaProperties); + } + set + { + base.SetValue(Constants.Properties.InternalSchemaProperties, value); + } + } + + internal bool IsMaterializedView() + { + return this.MaterializedViewDefinition != null + && (!string.IsNullOrEmpty(this.MaterializedViewDefinition.SourceCollectionRid) || !string.IsNullOrEmpty(this.MaterializedViewDefinition.SourceCollectionId)); + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The ClientEncryptionPolicy associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.ClientEncryptionPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal ClientEncryptionPolicy ClientEncryptionPolicy + { + get + { + if (this.clientEncryptionPolicy == null) + { + this.clientEncryptionPolicy = base.GetObject(Constants.Properties.ClientEncryptionPolicy); + } + + return this.clientEncryptionPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(ClientEncryptionPolicy))); + } + + this.clientEncryptionPolicy = value; + base.SetObject(Constants.Properties.ClientEncryptionPolicy, value); + } + } + + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The DataMaskingPolicy associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.DataMaskingPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal DataMaskingPolicy DataMaskingPolicy + { + get + { + if (this.dataMaskingPolicy == null) + { + this.dataMaskingPolicy = base.GetObject(Constants.Properties.DataMaskingPolicy); + } + + return this.dataMaskingPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(DataMaskingPolicy))); + } + + this.dataMaskingPolicy = value; + base.SetObject(Constants.Properties.DataMaskingPolicy, value); + } + } + + /// + /// Gets the materialized views on the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.MaterializedViews, DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] + internal Collection MaterializedViews + { + get + { + if (this.materializedViews == null) + { + Collection materializedViewsValues = base.GetValueCollection(Constants.Properties.MaterializedViews); + if (materializedViewsValues == null) + { + this.materializedViews = new Collection(); + } + else + { + this.materializedViews = materializedViewsValues; + } + } + return this.materializedViews; + } + set + { + this.materializedViews = value; + base.SetValueCollection(Constants.Properties.MaterializedViews, value); + } + } + + /// + /// Gets or sets the for triggering the InAccountRestore of the collection + /// + /// + /// It is an optional property. + /// A valid value should be Default or Restore + /// + [JsonProperty(PropertyName = Constants.Properties.CreateMode, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal DatabaseOrCollectionCreateMode? CreateMode + { + get + { + return base.GetValue(Constants.Properties.CreateMode, null); + } + set + { + base.SetValue(Constants.Properties.CreateMode, value.ToString()); + } + } + + /// + /// Gets or sets the for triggering the InAccountRestore of the collection + /// + /// + /// It is an optional property. + /// A valid value should have both RestoreSource and RestoreTimestampInUtc + /// + [JsonProperty(PropertyName = Constants.Properties.RestoreParams, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal InAccountRestoreParameters RestoreParameters + { + get + { + if (this.restoreParameters == null) + { + this.restoreParameters = base.GetObject(Constants.Properties.RestoreParams); + } + + return this.restoreParameters; + } + set + { + this.restoreParameters = value; + base.SetObject(Constants.Properties.RestoreParams, value); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.DefaultTimeToLive); + base.GetValue(Constants.Properties.TimeToLivePropertyPath); + this.IndexingPolicy.Validate(); + this.PartitionKey.Validate(); + this.UniqueKeyPolicy.Validate(); + this.ConflictResolutionPolicy.Validate(); + this.UniqueIndexReIndexContext.Validate(); + + foreach (ComputedProperty computedProperty in this.ComputedProperties) + { + computedProperty.Validate(); + } + } + + internal override void OnSave() + { + if (this.indexingPolicy != null) + { + this.indexingPolicy.OnSave(); + base.SetObject(Constants.Properties.IndexingPolicy, this.indexingPolicy); + } + + if (this.partitionKey != null) + { + base.SetValue(Constants.Properties.PartitionKey, this.partitionKey); + } + + if (this.uniqueKeyPolicy != null) + { + this.uniqueKeyPolicy.OnSave(); + base.SetObject(Constants.Properties.UniqueKeyPolicy, this.uniqueKeyPolicy); + } + + if (this.conflictResolutionPolicy != null) + { + this.conflictResolutionPolicy.OnSave(); + base.SetObject(Constants.Properties.ConflictResolutionPolicy, this.conflictResolutionPolicy); + } + + if (this.schemaDiscoveryPolicy != null) + { + base.SetObject(Constants.Properties.SchemaDiscoveryPolicy, this.schemaDiscoveryPolicy); + } + + if (this.changeFeedPolicy != null) + { + base.SetObject(Constants.Properties.ChangeFeedPolicy, this.changeFeedPolicy); + } + + if (this.collectionBackupPolicy != null) + { + base.SetObject(Constants.Properties.CollectionBackupPolicy, this.collectionBackupPolicy); + } + + if (this.geospatialConfig != null) + { + base.SetObject(Constants.Properties.GeospatialConfig, this.geospatialConfig); + } + + if(this.byokConfig != null) + { + base.SetObject(Constants.Properties.ByokConfig, this.byokConfig); + } + + if (this.uniqueIndexReIndexContext != null) + { + this.uniqueIndexReIndexContext.OnSave(); + base.SetObject(Constants.Properties.UniqueIndexReIndexContext, this.uniqueIndexReIndexContext); + } + + if (this.clientEncryptionPolicy != null) + { + base.SetObject(Constants.Properties.ClientEncryptionPolicy, this.clientEncryptionPolicy); + } + + if (this.dataMaskingPolicy != null) + { + base.SetObject(Constants.Properties.DataMaskingPolicy, this.dataMaskingPolicy); + } + + if (this.materializedViews != null) + { + base.SetValueCollection(Constants.Properties.MaterializedViews, this.materializedViews); + } + + if (this.computedProperties != null) + { + base.SetValueCollection(Constants.Properties.ComputedProperties, this.computedProperties); + } + + if (this.restoreParameters != null) + { + base.SetObject(Constants.Properties.RestoreParams, this.restoreParameters); + } + + // todo(Mukum): remove the encryptionscopeId check once backend contract is checked in. + if (this.encryptionScopeMetadata != null && !string.IsNullOrWhiteSpace(this.encryptionScopeMetadata.Id)) + { + this.encryptionScopeMetadata.OnSave(); + base.SetObject(Constants.EncryptionScopeProperties.EncryptionScope, this.encryptionScopeMetadata); + } + + if(this.uniqueIndexNameEncodingMode != 0) + { + base.SetValue(Constants.Properties.UniqueIndexNameEncodingMode, this.uniqueIndexNameEncodingMode); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentResponse.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentResponse.cs index f4afb86762..86081cca9e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentResponse.cs @@ -1,94 +1,94 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - using Microsoft.Azure.Documents; - using Newtonsoft.Json; - - /// - /// Represents the template class used by methods returning single objects in the Azure Cosmos DB service. - /// - /// the document type. - /// - /// Response from type-specific read of Document resource(ReadDocumentAsync{TDocument}) returns the response wrapped in a - /// DocumentResponse object. This contains the metadata from the response headers from the Azure Cosmos DB call including - /// the request units (RequestCharge), activity ID, quotas/usage of resources and the typed document object(TDocument). - /// - /// - /// The following example extracts the CustomerName property, request units consumed, activity ID and StatusCode from a ReadDocumentAsync{Customer} call. - /// - /// response = await client.ReadDocumentAsync(documentLink); - /// Console.WriteLine(response.Document.CustomerName); - /// Console.WriteLine(response.RequestCharge); - /// Console.WriteLine(response.ActivityId); - /// Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201 - /// ]]> - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class DocumentResponse : ResourceResponseBase, IDocumentResponse - { - private TDocument document; - private JsonSerializerSettings settings; - - /// - /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. - /// - public DocumentResponse() - { - - } - - /// - /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. - /// - /// - public DocumentResponse(TDocument document) - :this() - { - this.document = document; - } - - internal DocumentResponse(DocumentServiceResponse response, JsonSerializerSettings settings = null) - :base(response) - { - this.settings = settings; - } - - /// - /// Gets the document returned in the response from the Azure Cosmos DB service. - /// - /// - /// The document returned in the response. - /// - public TDocument Document - { - get - { - if (this.document == null) - { - Document doc = this.response.GetResource(); - doc.SerializerSettings = this.settings; - this.document = (TDocument)(dynamic)doc; - } - return this.document; - } - } - - /// - /// Returns the document in the response implicitly from the Azure Cosmos DB service. - /// - /// The DocumentResponse source. - /// The document object. - public static implicit operator TDocument(DocumentResponse source) - { - return source.Document; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + + /// + /// Represents the template class used by methods returning single objects in the Azure Cosmos DB service. + /// + /// the document type. + /// + /// Response from type-specific read of Document resource(ReadDocumentAsync{TDocument}) returns the response wrapped in a + /// DocumentResponse object. This contains the metadata from the response headers from the Azure Cosmos DB call including + /// the request units (RequestCharge), activity ID, quotas/usage of resources and the typed document object(TDocument). + /// + /// + /// The following example extracts the CustomerName property, request units consumed, activity ID and StatusCode from a ReadDocumentAsync{Customer} call. + /// + /// response = await client.ReadDocumentAsync(documentLink); + /// Console.WriteLine(response.Document.CustomerName); + /// Console.WriteLine(response.RequestCharge); + /// Console.WriteLine(response.ActivityId); + /// Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201 + /// ]]> + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class DocumentResponse : ResourceResponseBase, IDocumentResponse + { + private TDocument document; + private JsonSerializerSettings settings; + + /// + /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. + /// + public DocumentResponse() + { + + } + + /// + /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. + /// + /// + public DocumentResponse(TDocument document) + :this() + { + this.document = document; + } + + internal DocumentResponse(DocumentServiceResponse response, JsonSerializerSettings settings = null) + :base(response) + { + this.settings = settings; + } + + /// + /// Gets the document returned in the response from the Azure Cosmos DB service. + /// + /// + /// The document returned in the response. + /// + public TDocument Document + { + get + { + if (this.document == null) + { + Document doc = this.response.GetResource(); + doc.SerializerSettings = this.settings; + this.document = (TDocument)(dynamic)doc; + } + return this.document; + } + } + + /// + /// Returns the document in the response implicitly from the Azure Cosmos DB service. + /// + /// The DocumentResponse source. + /// The document object. + public static implicit operator TDocument(DocumentResponse source) + { + return source.Document; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs index 44ecfc7461..f5643e2f3d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs @@ -1,1219 +1,1219 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - using Newtonsoft.Json; - - //This is core Transport/Connection agnostic request to DocumentService. - //It is marked internal today. If needs arises for client to do no-serialized processing - //we can open this up to public. - internal sealed class DocumentServiceRequest : IDisposable - { - private bool isDisposed = false; - - // The lock is used for locking request body operations like sending request or changing stream position. - private const char PreferHeadersSeparator = ';'; - private const string PreferHeaderValueFormat = "{0}={1}"; - - private ServiceIdentity serviceIdentity; - - private PartitionKeyRangeIdentity partitionKeyRangeIdentity; - - private DocumentServiceRequest() - { - } - - /// - /// This is constructed from the existing request, either RId based or name based. - /// resourceIdOrFullName can be either: (trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded) - /// 1. wo1ZAP7zFQA= - /// 2. dbs/dbName/colls/collectionName/docs/documentName - /// - /// - /// - /// - /// - /// - /// resourceIdOrFullName is resourceId or fullName - /// - internal DocumentServiceRequest( - OperationType operationType, - string resourceIdOrFullName, - ResourceType resourceType, - Stream body, - INameValueCollection headers, - bool isNameBased, - AuthorizationTokenType authorizationTokenType) - { - this.OperationType = operationType; - this.ForceNameCacheRefresh = false; - this.ResourceType = resourceType; - this.Body = body; - this.Headers = headers ?? new DictionaryNameValueCollection(); - this.IsFeed = false; - this.IsNameBased = isNameBased; - - if (isNameBased) - { - this.ResourceAddress = resourceIdOrFullName; - } - else - { - this.ResourceId = resourceIdOrFullName; - this.ResourceAddress = resourceIdOrFullName; - } - - this.RequestAuthorizationTokenType = authorizationTokenType; - this.RequestContext = new DocumentServiceRequestContext(); - - if (!string.IsNullOrEmpty(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId])) - { - this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]); - } - } - - /// - /// The path is the incoming Uri.PathAndQuery, it can be: (the name is url encoded). - /// 1. dbs/dbName/colls/collectionName/docs/documentName/attachments/ - /// 2. dbs/wo1ZAA==/colls/wo1ZAP7zFQA=/ - /// - /// - /// - /// - /// - /// - /// - internal DocumentServiceRequest( - OperationType operationType, - ResourceType resourceType, - string path, - Stream body, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers) - { - this.OperationType = operationType; - this.ForceNameCacheRefresh = false; - this.ResourceType = resourceType; - this.Body = body; - this.Headers = headers ?? new DictionaryNameValueCollection(); - this.RequestAuthorizationTokenType = authorizationTokenType; - this.RequestContext = new DocumentServiceRequestContext(); - - // for address, no parsing is needed. - if (resourceType == ResourceType.Address -#if !COSMOSCLIENT - || resourceType == ResourceType.XPReplicatorAddress -#endif - ) - return; - - if (PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( - path, - out bool isFeed, - out string resourceTypeString, - out string resourceIdOrFullName, - out bool isNameBased, - out string databaseName, - out string collectionName, - out string documentName, - parseDatabaseAndCollectionNames: true)) - { - InitializeWithDataParsedFromUri( - path: path, - isNameBased: isNameBased, - isFeed: isFeed, - resourceIdOrFullName: resourceIdOrFullName, - databaseName: databaseName, - collectionName: collectionName, - documentName: documentName, - resourceTypeString: resourceTypeString); - } - else - { - throw new NotFoundException(string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceUrlQuery, path, HttpConstants.QueryStrings.Url)); - } - - if (!string.IsNullOrEmpty(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId])) - { - this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]); - } - } - - /// - /// The path is the incoming Uri.PathAndQuery, it can be: (the name is url encoded). - /// 1. dbs/dbName/colls/collectionName/docs/documentName/attachments/ - /// 2. dbs/wo1ZAA==/colls/wo1ZAP7zFQA=/ - /// - /// - /// Use if request URI has been parsed. - /// - internal DocumentServiceRequest( - OperationType operationType, - ResourceType resourceType, - string path, - Stream body, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers, - bool isNameBased, - bool isFeed, - string resourceIdOrFullName, - string databaseName, - string collectionName, - string documentName, - string resourceTypeString) - { - this.OperationType = operationType; - this.ForceNameCacheRefresh = false; - this.ResourceType = resourceType; - this.Body = body; - this.Headers = headers ?? new DictionaryNameValueCollection(); - this.RequestAuthorizationTokenType = authorizationTokenType; - this.RequestContext = new DocumentServiceRequestContext(); - - // for address, no parsing is needed. - if (resourceType == ResourceType.Address -#if !COSMOSCLIENT - || resourceType == ResourceType.XPReplicatorAddress -#endif - ) - return; - - InitializeWithDataParsedFromUri( - path: path, - isNameBased: isNameBased, - isFeed: isFeed, - resourceIdOrFullName: resourceIdOrFullName, - databaseName: databaseName, - collectionName: collectionName, - documentName: documentName, - resourceTypeString: resourceTypeString); - - string partitionKeyRangeId = this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]; - if (!string.IsNullOrEmpty(partitionKeyRangeId)) - { - this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(partitionKeyRangeId); - } - } - - public bool IsNameBased { get; private set; } - - public string DatabaseName { get; private set; } - - public string CollectionName { get; private set; } - - public string DocumentName { get; private set; } - - public bool IsResourceNameParsedFromUri { get; private set; } - - /// - /// This is currently used to force non-Windows .NET Core target platforms(Linux and OSX) - /// and on 32-bit host process on Windows for NETFX, to always use Gateway mode for sending - /// cross partition query requests to get partition execution info as that logic is there in - /// ServiceInterop native dll which we haven't ported to Linux and OSX yet and it exists only - /// in 64 bit version on Windows. - /// - public bool UseGatewayMode { get; set; } - - /// - /// This is a flag that indicates whether the DocumentClient internally - /// throws exceptions for status codes 404, 412, and 409 or whether it returns - /// the status codes as part of the result for failures. - /// - public bool UseStatusCodeForFailures { get; set; } - - /// - /// This is a flag that indicates whether the DocumentClient internally - /// throws exceptions for 429 status codes - /// the status codes as part of the result for failures. - /// - public bool UseStatusCodeFor429 { get; set; } - - /// - /// This is a flag that indicates whether the DocumentClient internally - /// throws exceptions for 400 status codes - /// the status codes as part of the result for failures. - /// - public bool UseStatusCodeForBadRequest { get; set; } - - /// - /// Flag indicating whether or not to disable retries on RetryWith Exceptions - /// - public bool DisableRetryWithPolicy { get; set; } - - /// - /// ServiceIdentity of the target service where this request should reach - /// Only valid for gateway - /// - public ServiceIdentity ServiceIdentity - { - get - { - return this.serviceIdentity; - } - private set - { - this.serviceIdentity = value; - } - } - - public SystemAuthorizationParameters SystemAuthorizationParams { get; set; } - - public sealed class SystemAuthorizationParameters - { - public string FederationId { get; set; } - - public string Verb { get; set; } - - public string ResourceId { get; set; } - - public SystemAuthorizationParameters Clone() - { - return new SystemAuthorizationParameters() - { - FederationId = this.FederationId, - Verb = this.Verb, - ResourceId = this.ResourceId - }; - } - } - - public PartitionKeyRangeIdentity PartitionKeyRangeIdentity - { - get - { - return this.partitionKeyRangeIdentity; - } - private set - { - this.partitionKeyRangeIdentity = value; - if (value != null) - { - this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId] = value.ToHeader(); - } - else - { - this.Headers.Remove(WFConstants.BackendHeaders.PartitionKeyRangeId); - } - } - } - - public void RouteTo(ServiceIdentity serviceIdentity) - { - if(this.PartitionKeyRangeIdentity != null) - { - DefaultTrace.TraceCritical("This request was going to be routed to partition key range"); - throw new InternalServerErrorException(); - } - - this.ServiceIdentity = serviceIdentity; - } - - public void RouteTo(PartitionKeyRangeIdentity partitionKeyRangeIdentity) - { - if(this.ServiceIdentity != null) - { - DefaultTrace.TraceCritical("This request was going to be routed to service identity"); - throw new InternalServerErrorException(); - } - - this.PartitionKeyRangeIdentity = partitionKeyRangeIdentity; - } - - public string ResourceId { get; set; } - - public DocumentServiceRequestContext RequestContext { get; set; } - - /// - /// Normalized resourcePath, for both Name based and Rid based. - /// This is the string passed for AuthZ. - /// It is resourceId in Rid case passed for AuthZ - /// - public string ResourceAddress { get; private set; } - - public bool IsFeed { get; set; } - - public string EntityId { get; set; } - - public INameValueCollection Headers { get; private set; } - - /// - /// Contains the context shared by handlers. - /// - public IDictionary Properties { get; set; } - - public Stream Body { get; set; } - - public CloneableStream CloneableBody { get; private set; } - - /// - /// Authorization token used for the request. - /// This will be used to generate any child requests that are needed to process the request. - /// - public AuthorizationTokenType RequestAuthorizationTokenType { get; set; } - - public bool IsBodySeekableClonableAndCountable - { - get - { - return (this.Body == null) || (this.CloneableBody != null); - } - } - - public OperationType OperationType { get; private set; } - - public ResourceType ResourceType { get; private set; } - - public string QueryString { get; set; } - - //Backend Continuation. - public string Continuation - { - get - { - return this.Headers[HttpConstants.HttpHeaders.Continuation]; - } - set - { - this.Headers[HttpConstants.HttpHeaders.Continuation] = value; - } - } - - internal string ApiVersion - { - get - { - return this.Headers[HttpConstants.HttpHeaders.Version]; - } - } - - /// - /// StoreModel vs GatewayStoreModel contract for friends. - /// TODO: SDK V3 start using this contract. - https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2470799 - /// - internal static bool IsGatewayMode(ResourceType resourceType, OperationType operationType) - { - if (resourceType == ResourceType.Offer || - (resourceType.IsScript() && operationType != OperationType.ExecuteJavaScript) || - resourceType == ResourceType.PartitionKeyRange || - resourceType == ResourceType.Snapshot || - resourceType == ResourceType.ClientEncryptionKey || - (resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete)) - { - return true; - } - - if (operationType == OperationType.Create - || operationType == OperationType.Upsert) - { - if (resourceType == ResourceType.Database || - resourceType == ResourceType.User || - resourceType == ResourceType.Collection || - resourceType == ResourceType.Permission) - { - return true; - } - else - { - return false; - } - } - else if (operationType == OperationType.Delete) - { - if (resourceType == ResourceType.Database || - resourceType == ResourceType.User || - resourceType == ResourceType.Collection) - { - return true; - } - else - { - return false; - } - } - else if ((operationType == OperationType.Replace) || (operationType == OperationType.CollectionTruncate)) - { - if (resourceType == ResourceType.Collection) - { - return true; - } - else - { - return false; - } - } - else if (operationType == OperationType.Read) - { - if (resourceType == ResourceType.Collection) - { - return true; - } - else - { - return false; - } - } - - return false; - } - - public bool ForceNameCacheRefresh { get; set; } - - /// - /// CollectionRoutingMap hash code is used in the cache - /// refresh scenarios to avoid doing a refresh when another - /// request already completed one. - /// - public int LastCollectionRoutingMapHashCode { get; set; } - - public bool ForcePartitionKeyRangeRefresh { get; set; } - - public bool ForceCollectionRoutingMapRefresh { get; set; } - - public bool ForceMasterRefresh { get; set; } - - public bool IsReadOnlyRequest - { - get - { - return (this.OperationType == Documents.OperationType.Read - || this.OperationType == Documents.OperationType.ReadFeed - || this.OperationType == Documents.OperationType.Head - || this.OperationType == Documents.OperationType.HeadFeed - || this.OperationType == Documents.OperationType.Query - || this.OperationType == Documents.OperationType.SqlQuery - || this.OperationType == Documents.OperationType.QueryPlan -#if !COSMOSCLIENT - || this.OperationType == Documents.OperationType.GetStorageAuthToken -#endif - ); - } - } - - public bool IsReadOnlyScript - { - get - { - string isReadOnlyScript = this.Headers.Get(HttpConstants.HttpHeaders.IsReadOnlyScript); - if (string.IsNullOrEmpty(isReadOnlyScript)) - { - return false; - } - else - { - return this.OperationType == Documents.OperationType.ExecuteJavaScript - && isReadOnlyScript.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase); - } - } - } - - public bool IsChangeFeedRequest - { - get - { - string aimKey = this.Headers.Get(HttpConstants.HttpHeaders.A_IM); - - return !string.IsNullOrWhiteSpace(aimKey); - } - } - - /// - /// Get the HttpMethod for request based on OperationType and Body - /// - public string HttpMethod - { - get - { - switch (this.OperationType) - { - case OperationType.Create: - case OperationType.ExecuteJavaScript: - case OperationType.Query: - case OperationType.SqlQuery: - case OperationType.Upsert: - case OperationType.BatchApply: - case OperationType.Batch: - case OperationType.QueryPlan: - case OperationType.MetadataCheckAccess: - case OperationType.CompleteUserTransaction: - return HttpConstants.HttpMethods.Post; - - case OperationType.Delete: - return HttpConstants.HttpMethods.Delete; - - case OperationType.Read: - return HttpConstants.HttpMethods.Get; - - case OperationType.ReadFeed: - { - if (this.Body == null) - { - return HttpConstants.HttpMethods.Get; - } - else - { - return HttpConstants.HttpMethods.Post; - } - } - - case OperationType.Replace: - case OperationType.CollectionTruncate: - return HttpConstants.HttpMethods.Put; - - case OperationType.Patch: - return HttpConstants.HttpMethods.Patch; - - case OperationType.Head: - case OperationType.HeadFeed: - return HttpConstants.HttpMethods.Head; - -#if !COSMOSCLIENT - // Control operations - case OperationType.Pause: - case OperationType.Recycle: - case OperationType.Resume: - case OperationType.Stop: - case OperationType.Crash: - case OperationType.ForceConfigRefresh: - case OperationType.Throttle: - case OperationType.PreCreateValidation: - case OperationType.Recreate: - case OperationType.GetSplitPoint: - case OperationType.AbortSplit: - case OperationType.CompleteSplit: - case OperationType.CompleteMergeOnMaster: - case OperationType.CompleteMergeOnTarget: - case OperationType.OfferUpdateOperation: - case OperationType.OfferPreGrowValidation: - case OperationType.BatchReportThroughputUtilization: - case OperationType.AbortPartitionMigration: - case OperationType.CompletePartitionMigration: - case OperationType.PreReplaceValidation: - case OperationType.MigratePartition: - case OperationType.MasterReplaceOfferOperation: - case OperationType.InitiateDatabaseOfferPartitionShrink: - case OperationType.CompleteDatabaseOfferPartitionShrink: - case OperationType.ServiceReservation: - case OperationType.GetSplitPoints: - case OperationType.GetUnwrappedDek: - case OperationType.GetDekProperties: - case OperationType.GetFederationConfigurations: - case OperationType.GetDatabaseAccountConfigurations: - case OperationType.GetStorageServiceConfigurations: - case OperationType.ForcePartitionBackup: - case OperationType.MasterInitiatedProgressCoordination: - case OperationType.CreateSystemSnapshot: - case OperationType.CreateRidRangeResources: - case OperationType.GetAadGroups: - case OperationType.UpdateFailoverPriorityList: - case OperationType.GetStorageAccountSas: - case OperationType.GetBatchCustomerManagedKeyStatus: - case OperationType.UpdatePartitionThroughput: - case OperationType.XPDatabaseAccountMetaData: - case OperationType.Truncate: - return HttpConstants.HttpMethods.Post; - - case OperationType.EnsureSnapshotOperation: - return HttpConstants.HttpMethods.Put; - - case OperationType.ReadReplicaFromMasterPartition: - case OperationType.ReadReplicaFromServerPartition: - case OperationType.GetStorageAuthToken: - case OperationType.GetCustomerManagedKeyStatus: - case OperationType.GetGraphDatabaseAccountConfiguration: - return HttpConstants.HttpMethods.Get; -#endif - - default: - string message = string.Format(CultureInfo.InvariantCulture, "Unsupported operation type: {0}.", this.OperationType); - Debug.Fail(message); - throw new NotImplementedException(message); - } - } - } - - public JsonSerializerSettings SerializerSettings - { - get; - set; - } - -#region Test hooks - - public uint? DefaultReplicaIndex - { - get; - set; - } - -#endregion - - public void Dispose() - { - if (this.isDisposed) - { - return; - } - - if (this.Body != null) - { - this.Body.Dispose(); - this.Body = null; - } - - if (this.CloneableBody != null) - { - this.CloneableBody.Dispose(); - this.CloneableBody = null; - } - - this.isDisposed = true; - } - - /// - /// Verify the address is same as claimed resourceType - /// - /// - public bool IsValidAddress(ResourceType resourceType = ResourceType.Unknown) - { - ResourceType resourceTypeToValidate = ResourceType.Unknown; - - if (resourceType != ResourceType.Unknown) - { - resourceTypeToValidate = resourceType; - } - else - { - if (!this.IsFeed) - { - resourceTypeToValidate = this.ResourceType; - } - else - { - if (this.ResourceType == ResourceType.Database) - { - return true; - } - else if (this.ResourceType == ResourceType.Collection || - this.ResourceType == ResourceType.User || - this.ResourceType == ResourceType.ClientEncryptionKey || - this.ResourceType == ResourceType.UserDefinedType) - { - resourceTypeToValidate = ResourceType.Database; - } - else if (this.ResourceType == ResourceType.Permission) - { - resourceTypeToValidate = ResourceType.User; - } - else if (this.ResourceType == ResourceType.Document || - this.ResourceType == ResourceType.StoredProcedure || - this.ResourceType == ResourceType.UserDefinedFunction || - this.ResourceType == ResourceType.Trigger || - this.ResourceType == ResourceType.Conflict || - this.ResourceType == ResourceType.StoredProcedure || - this.ResourceType == ResourceType.PartitionKeyRange || - this.ResourceType == ResourceType.Schema || - this.ResourceType == ResourceType.PartitionedSystemDocument || - this.ResourceType == ResourceType.SystemDocument) - { - resourceTypeToValidate = ResourceType.Collection; - } - else if (this.ResourceType == ResourceType.Attachment) - { - resourceTypeToValidate = ResourceType.Document; - } - else if (this.ResourceType == ResourceType.Snapshot) - { - return true; - } - else if (this.ResourceType == ResourceType.RoleDefinition) - { - return true; - } - else if (this.ResourceType == ResourceType.RoleAssignment) - { - return true; - } - else if (this.ResourceType == ResourceType.InteropUser) - { - return true; - } - else if (this.ResourceType == ResourceType.AuthPolicyElement) - { - return true; - } - else if (this.ResourceType == ResourceType.EncryptionScope) - { - return true; - } -#if !COSMOSCLIENT - else if (this.ResourceType == ResourceType.VectorClock) - { - return true; - } -#endif - else - { - return false; - } - } - } - - if (IsNameBased) - { - return PathsHelper.ValidateResourceFullName(resourceType != ResourceType.Unknown ? resourceType : resourceTypeToValidate, this.ResourceAddress); - } - else - { - return PathsHelper.ValidateResourceId(resourceTypeToValidate, this.ResourceId); - } - } - - public void AddPreferHeader(string preferHeaderName, string preferHeaderValue) - { - string headerToAdd = string.Format( - CultureInfo.InvariantCulture, - DocumentServiceRequest.PreferHeaderValueFormat, - preferHeaderName, - preferHeaderValue); - - string preferHeader = this.Headers[HttpConstants.HttpHeaders.Prefer]; - - if (!string.IsNullOrEmpty(preferHeader)) - { - preferHeader += DocumentServiceRequest.PreferHeadersSeparator + headerToAdd; - } - else - { - preferHeader = headerToAdd; - } - - this.Headers[HttpConstants.HttpHeaders.Prefer] = preferHeader; - } - - // Clone from request - public static DocumentServiceRequest CreateFromResource( - DocumentServiceRequest request, - Resource modifiedResource) - { - DocumentServiceRequest modifiedRequest; - if (!request.IsNameBased) - { - modifiedRequest = DocumentServiceRequest.Create(request.OperationType, modifiedResource, request.ResourceType, request.RequestAuthorizationTokenType, request.Headers, request.ResourceId); - } - else - { - modifiedRequest = DocumentServiceRequest.CreateFromName(request.OperationType, modifiedResource, request.ResourceType, request.Headers, request.ResourceAddress, request.RequestAuthorizationTokenType); - } - - return modifiedRequest; - } - - - //POST or PUT - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] - public static DocumentServiceRequest Create( - OperationType operationType, - Resource resource, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null, - string ownerResourceId = null, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - MemoryStream stream = new MemoryStream(); - if (resource != null) - { - resource.SaveTo(stream, formattingPolicy); - } - stream.Position = 0; - - DocumentServiceRequest request = new DocumentServiceRequest( - operationType, - ownerResourceId != null ? ownerResourceId : resource.ResourceId, - resourceType, - stream, - headers, - false, - authorizationTokenType); - - request.CloneableBody = new CloneableStream(stream); - return request; - } - - public static DocumentServiceRequest Create( - OperationType operationType, - ResourceType resourceType, - MemoryStream stream, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - DocumentServiceRequest request = new DocumentServiceRequest( - operationType, - null, // resourceIdOrFullName - resourceType, - stream, - headers, - false, // isNameBased - authorizationTokenType); - - request.CloneableBody = new CloneableStream(stream); - return request; - } - - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] - public static DocumentServiceRequest Create( - OperationType operationType, - string ownerResourceId, - byte[] seralizedResource, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - MemoryStream stream = new MemoryStream(seralizedResource); - - return new DocumentServiceRequest( - operationType, - ownerResourceId, - resourceType, - stream, - headers, - false, - authorizationTokenType); - } - - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] - public static DocumentServiceRequest Create( - OperationType operationType, - string ownerResourceId, - ResourceType resourceType, - bool isNameBased, - AuthorizationTokenType authorizationTokenType, - byte[] seralizedResource = null, - INameValueCollection headers = null, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - MemoryStream stream = seralizedResource == null ? null : new MemoryStream(seralizedResource); - - return new DocumentServiceRequest( - operationType, - ownerResourceId, - resourceType, - stream, - headers, - isNameBased, - authorizationTokenType); - } - - public static DocumentServiceRequest Create( - OperationType operationType, - string resourceId, - ResourceType resourceType, - Stream body, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest(operationType, resourceId, resourceType, body, headers, false, authorizationTokenType); - } - - //Get, Delete, FeedRead. - public static DocumentServiceRequest Create( - OperationType operationType, - string resourceId, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest(operationType, resourceId, resourceType, null, headers, false, authorizationTokenType); - } - - public static DocumentServiceRequest CreateFromName( - OperationType operationType, - string resourceFullName, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest(operationType, resourceFullName, resourceType, null, headers, true, authorizationTokenType); - } - - public static DocumentServiceRequest CreateFromName( - OperationType operationType, - Resource resource, - ResourceType resourceType, - INameValueCollection headers, - string resourceFullName, - AuthorizationTokenType authorizationTokenType, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - MemoryStream stream = new MemoryStream(); - resource.SaveTo(stream, formattingPolicy); - stream.Position = 0; - - return new DocumentServiceRequest(operationType, resourceFullName, resourceType, stream, headers, true, authorizationTokenType); - } - - //Replica Request. - public static DocumentServiceRequest Create( - OperationType operationType, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType) - { - return new DocumentServiceRequest(operationType, null, resourceType, null, null, false, authorizationTokenType); - } - - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] - public static DocumentServiceRequest Create( - OperationType operationType, - string relativePath, - Resource resource, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None, - JsonSerializerSettings settings = null) - { - MemoryStream stream = new MemoryStream(); - resource.SaveTo(stream, formattingPolicy, settings); - stream.Position = 0; - - DocumentServiceRequest request = new DocumentServiceRequest(operationType, resourceType, relativePath, stream, authorizationTokenType, headers); - request.SerializerSettings = settings; - - // since we constructed the body ourselves in a way that it can be safely given to a CloneableStream, - // assign that here, so that EnsureBufferedBodyAsync will be a no-op (won't incur unnecessary memcpy) - request.CloneableBody = new CloneableStream(stream); - return request; - } - - [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] - public static DocumentServiceRequest Create( - OperationType operationType, - Uri requestUri, - Resource resource, - ResourceType resourceType, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null, - SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - MemoryStream stream = new MemoryStream(); - resource.SaveTo(stream, formattingPolicy); - stream.Position = 0; - - DocumentServiceRequest request = new DocumentServiceRequest(operationType, resourceType, requestUri.PathAndQuery, stream, authorizationTokenType, headers); - - // since we constructed the body ourselves in a way that it can be safely given to a CloneableStream, - // assign that here, so that EnsureBufferedBodyAsync will be a no-op (won't incur unnecessary memcpy) - request.CloneableBody = new CloneableStream(stream); - return request; - - } - - public static DocumentServiceRequest Create( - OperationType operationType, - ResourceType resourceType, - string relativePath, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest(operationType, resourceType, relativePath, null, authorizationTokenType, headers); - } - - public static DocumentServiceRequest Create( - OperationType operationType, - ResourceType resourceType, - Uri requestUri, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest(operationType, resourceType, requestUri.PathAndQuery, null, authorizationTokenType, headers); - } - - public static DocumentServiceRequest Create(OperationType operationType, - ResourceType resourceType, - string relativePath, - Stream resourceStream, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers = null) - { - return new DocumentServiceRequest( - operationType, - resourceType, - relativePath, - resourceStream, - authorizationTokenType, - headers); - } - - internal static DocumentServiceRequest Create( - OperationType operationType, - ResourceType resourceType, - string relativePath, - Stream resourceStream, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers, - bool isNameBased, - bool isFeed, - string resourceIdOrFullName, - string databaseName, - string collectionName, - string documentName, - string resourceTypeString) - { - return new DocumentServiceRequest( - operationType, - resourceType, - relativePath, - resourceStream, - authorizationTokenType, - headers, - isNameBased, - isFeed, - resourceIdOrFullName, - databaseName, - collectionName, - documentName, - resourceTypeString); - } - - public static DocumentServiceRequest Create(OperationType operationType, - ResourceType resourceType, - Uri requestUri, - Stream resourceStream, - AuthorizationTokenType authorizationTokenType, - INameValueCollection headers) - { - return new DocumentServiceRequest( - operationType, - resourceType, - requestUri.PathAndQuery, - resourceStream, - authorizationTokenType, - headers); - } - - public async Task EnsureBufferedBodyAsync(bool allowUnsafeDataAccess = true) - { - if (this.Body == null) - return; - else if (this.CloneableBody != null) - return; - - this.CloneableBody = await StreamExtension.AsClonableStreamAsync(this.Body, allowUnsafeDataAccess); - } - - public void ClearRoutingHints() - { - this.PartitionKeyRangeIdentity = null; - this.ServiceIdentity = null; - this.RequestContext.TargetIdentity = null; - this.RequestContext.ResolvedPartitionKeyRange = null; - } - - public DocumentServiceRequest Clone() - { - if (!this.IsBodySeekableClonableAndCountable) - { - throw new InvalidOperationException(); - } - - return new DocumentServiceRequest{ - OperationType = this.OperationType, - ForceNameCacheRefresh = this.ForceNameCacheRefresh, - ResourceType = this.ResourceType, - ServiceIdentity = this.ServiceIdentity, - SystemAuthorizationParams = this.SystemAuthorizationParams == null ? null : this.SystemAuthorizationParams.Clone(), - // Body = this.Body, // intentionally don't clone body, as it is not cloneable. - CloneableBody = this.CloneableBody != null ? this.CloneableBody.Clone() : null, - Headers = (INameValueCollection)this.Headers.Clone(), - IsFeed = this.IsFeed, - IsNameBased = this.IsNameBased, - ResourceAddress = this.ResourceAddress, - ResourceId = this.ResourceId, - RequestAuthorizationTokenType = this.RequestAuthorizationTokenType, - RequestContext = this.RequestContext.Clone(), - PartitionKeyRangeIdentity = this.PartitionKeyRangeIdentity, - UseGatewayMode = this.UseGatewayMode, - QueryString = this.QueryString, - Continuation = this.Continuation, - ForcePartitionKeyRangeRefresh = this.ForcePartitionKeyRangeRefresh, - LastCollectionRoutingMapHashCode = this.LastCollectionRoutingMapHashCode, - ForceCollectionRoutingMapRefresh = this.ForceCollectionRoutingMapRefresh, - ForceMasterRefresh = this.ForceMasterRefresh, - DefaultReplicaIndex = this.DefaultReplicaIndex, - Properties = this.Properties, - UseStatusCodeForFailures = this.UseStatusCodeForFailures, - UseStatusCodeFor429 = this.UseStatusCodeFor429, - DatabaseName = this.DatabaseName, - CollectionName = this.CollectionName - }; - } - - private void InitializeWithDataParsedFromUri( - string path, - bool isNameBased, - bool isFeed, - string resourceIdOrFullName, - string databaseName, - string collectionName, - string documentName, - string resourceTypeString) - { - this.IsNameBased = isNameBased; - this.IsResourceNameParsedFromUri = true; - this.IsFeed = isFeed; - - if (this.ResourceType == ResourceType.Unknown) - { - this.ResourceType = PathsHelper.GetResourcePathSegment(resourceTypeString); - } - - if (isNameBased) - { - this.ResourceAddress = resourceIdOrFullName; - this.DatabaseName = databaseName; - this.CollectionName = collectionName; - this.DocumentName = documentName; - } - else - { - this.ResourceId = resourceIdOrFullName; - this.ResourceAddress = resourceIdOrFullName; - - // throw exception when the address parsing fail - // do not parse address for offer/snapshot resource - if (!string.IsNullOrEmpty(this.ResourceId) && - !Documents.ResourceId.TryParse(this.ResourceId, out ResourceId _) && - !(this.ResourceType == ResourceType.Offer) && - !(this.ResourceType == ResourceType.Media) && - !(this.ResourceType == ResourceType.DatabaseAccount) && - !(this.ResourceType == ResourceType.Snapshot) && - !(this.ResourceType == ResourceType.EncryptionScope) && - !(this.ResourceType == ResourceType.RoleDefinition) && - !(this.ResourceType == ResourceType.RoleAssignment) && - !(this.ResourceType == ResourceType.InteropUser) && - !(this.ResourceType == ResourceType.AuthPolicyElement) - #if !COSMOSCLIENT - && !(this.ResourceType == ResourceType.MasterPartition) && - !(this.ResourceType == ResourceType.ServerPartition) && - !(this.ResourceType == ResourceType.RidRange) && - !(this.ResourceType == ResourceType.VectorClock) - #endif - ) - { - throw new NotFoundException(string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceUrlQuery, path, HttpConstants.QueryStrings.Url)); - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + using Newtonsoft.Json; + + //This is core Transport/Connection agnostic request to DocumentService. + //It is marked internal today. If needs arises for client to do no-serialized processing + //we can open this up to public. + internal sealed class DocumentServiceRequest : IDisposable + { + private bool isDisposed = false; + + // The lock is used for locking request body operations like sending request or changing stream position. + private const char PreferHeadersSeparator = ';'; + private const string PreferHeaderValueFormat = "{0}={1}"; + + private ServiceIdentity serviceIdentity; + + private PartitionKeyRangeIdentity partitionKeyRangeIdentity; + + private DocumentServiceRequest() + { + } + + /// + /// This is constructed from the existing request, either RId based or name based. + /// resourceIdOrFullName can be either: (trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded) + /// 1. wo1ZAP7zFQA= + /// 2. dbs/dbName/colls/collectionName/docs/documentName + /// + /// + /// + /// + /// + /// + /// resourceIdOrFullName is resourceId or fullName + /// + internal DocumentServiceRequest( + OperationType operationType, + string resourceIdOrFullName, + ResourceType resourceType, + Stream body, + INameValueCollection headers, + bool isNameBased, + AuthorizationTokenType authorizationTokenType) + { + this.OperationType = operationType; + this.ForceNameCacheRefresh = false; + this.ResourceType = resourceType; + this.Body = body; + this.Headers = headers ?? new DictionaryNameValueCollection(); + this.IsFeed = false; + this.IsNameBased = isNameBased; + + if (isNameBased) + { + this.ResourceAddress = resourceIdOrFullName; + } + else + { + this.ResourceId = resourceIdOrFullName; + this.ResourceAddress = resourceIdOrFullName; + } + + this.RequestAuthorizationTokenType = authorizationTokenType; + this.RequestContext = new DocumentServiceRequestContext(); + + if (!string.IsNullOrEmpty(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId])) + { + this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]); + } + } + + /// + /// The path is the incoming Uri.PathAndQuery, it can be: (the name is url encoded). + /// 1. dbs/dbName/colls/collectionName/docs/documentName/attachments/ + /// 2. dbs/wo1ZAA==/colls/wo1ZAP7zFQA=/ + /// + /// + /// + /// + /// + /// + /// + internal DocumentServiceRequest( + OperationType operationType, + ResourceType resourceType, + string path, + Stream body, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers) + { + this.OperationType = operationType; + this.ForceNameCacheRefresh = false; + this.ResourceType = resourceType; + this.Body = body; + this.Headers = headers ?? new DictionaryNameValueCollection(); + this.RequestAuthorizationTokenType = authorizationTokenType; + this.RequestContext = new DocumentServiceRequestContext(); + + // for address, no parsing is needed. + if (resourceType == ResourceType.Address +#if !COSMOSCLIENT + || resourceType == ResourceType.XPReplicatorAddress +#endif + ) + return; + + if (PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( + path, + out bool isFeed, + out string resourceTypeString, + out string resourceIdOrFullName, + out bool isNameBased, + out string databaseName, + out string collectionName, + out string documentName, + parseDatabaseAndCollectionNames: true)) + { + InitializeWithDataParsedFromUri( + path: path, + isNameBased: isNameBased, + isFeed: isFeed, + resourceIdOrFullName: resourceIdOrFullName, + databaseName: databaseName, + collectionName: collectionName, + documentName: documentName, + resourceTypeString: resourceTypeString); + } + else + { + throw new NotFoundException(string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceUrlQuery, path, HttpConstants.QueryStrings.Url)); + } + + if (!string.IsNullOrEmpty(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId])) + { + this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]); + } + } + + /// + /// The path is the incoming Uri.PathAndQuery, it can be: (the name is url encoded). + /// 1. dbs/dbName/colls/collectionName/docs/documentName/attachments/ + /// 2. dbs/wo1ZAA==/colls/wo1ZAP7zFQA=/ + /// + /// + /// Use if request URI has been parsed. + /// + internal DocumentServiceRequest( + OperationType operationType, + ResourceType resourceType, + string path, + Stream body, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers, + bool isNameBased, + bool isFeed, + string resourceIdOrFullName, + string databaseName, + string collectionName, + string documentName, + string resourceTypeString) + { + this.OperationType = operationType; + this.ForceNameCacheRefresh = false; + this.ResourceType = resourceType; + this.Body = body; + this.Headers = headers ?? new DictionaryNameValueCollection(); + this.RequestAuthorizationTokenType = authorizationTokenType; + this.RequestContext = new DocumentServiceRequestContext(); + + // for address, no parsing is needed. + if (resourceType == ResourceType.Address +#if !COSMOSCLIENT + || resourceType == ResourceType.XPReplicatorAddress +#endif + ) + return; + + InitializeWithDataParsedFromUri( + path: path, + isNameBased: isNameBased, + isFeed: isFeed, + resourceIdOrFullName: resourceIdOrFullName, + databaseName: databaseName, + collectionName: collectionName, + documentName: documentName, + resourceTypeString: resourceTypeString); + + string partitionKeyRangeId = this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId]; + if (!string.IsNullOrEmpty(partitionKeyRangeId)) + { + this.PartitionKeyRangeIdentity = PartitionKeyRangeIdentity.FromHeader(partitionKeyRangeId); + } + } + + public bool IsNameBased { get; private set; } + + public string DatabaseName { get; private set; } + + public string CollectionName { get; private set; } + + public string DocumentName { get; private set; } + + public bool IsResourceNameParsedFromUri { get; private set; } + + /// + /// This is currently used to force non-Windows .NET Core target platforms(Linux and OSX) + /// and on 32-bit host process on Windows for NETFX, to always use Gateway mode for sending + /// cross partition query requests to get partition execution info as that logic is there in + /// ServiceInterop native dll which we haven't ported to Linux and OSX yet and it exists only + /// in 64 bit version on Windows. + /// + public bool UseGatewayMode { get; set; } + + /// + /// This is a flag that indicates whether the DocumentClient internally + /// throws exceptions for status codes 404, 412, and 409 or whether it returns + /// the status codes as part of the result for failures. + /// + public bool UseStatusCodeForFailures { get; set; } + + /// + /// This is a flag that indicates whether the DocumentClient internally + /// throws exceptions for 429 status codes + /// the status codes as part of the result for failures. + /// + public bool UseStatusCodeFor429 { get; set; } + + /// + /// This is a flag that indicates whether the DocumentClient internally + /// throws exceptions for 400 status codes + /// the status codes as part of the result for failures. + /// + public bool UseStatusCodeForBadRequest { get; set; } + + /// + /// Flag indicating whether or not to disable retries on RetryWith Exceptions + /// + public bool DisableRetryWithPolicy { get; set; } + + /// + /// ServiceIdentity of the target service where this request should reach + /// Only valid for gateway + /// + public ServiceIdentity ServiceIdentity + { + get + { + return this.serviceIdentity; + } + private set + { + this.serviceIdentity = value; + } + } + + public SystemAuthorizationParameters SystemAuthorizationParams { get; set; } + + public sealed class SystemAuthorizationParameters + { + public string FederationId { get; set; } + + public string Verb { get; set; } + + public string ResourceId { get; set; } + + public SystemAuthorizationParameters Clone() + { + return new SystemAuthorizationParameters() + { + FederationId = this.FederationId, + Verb = this.Verb, + ResourceId = this.ResourceId + }; + } + } + + public PartitionKeyRangeIdentity PartitionKeyRangeIdentity + { + get + { + return this.partitionKeyRangeIdentity; + } + private set + { + this.partitionKeyRangeIdentity = value; + if (value != null) + { + this.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId] = value.ToHeader(); + } + else + { + this.Headers.Remove(WFConstants.BackendHeaders.PartitionKeyRangeId); + } + } + } + + public void RouteTo(ServiceIdentity serviceIdentity) + { + if(this.PartitionKeyRangeIdentity != null) + { + DefaultTrace.TraceCritical("This request was going to be routed to partition key range"); + throw new InternalServerErrorException(); + } + + this.ServiceIdentity = serviceIdentity; + } + + public void RouteTo(PartitionKeyRangeIdentity partitionKeyRangeIdentity) + { + if(this.ServiceIdentity != null) + { + DefaultTrace.TraceCritical("This request was going to be routed to service identity"); + throw new InternalServerErrorException(); + } + + this.PartitionKeyRangeIdentity = partitionKeyRangeIdentity; + } + + public string ResourceId { get; set; } + + public DocumentServiceRequestContext RequestContext { get; set; } + + /// + /// Normalized resourcePath, for both Name based and Rid based. + /// This is the string passed for AuthZ. + /// It is resourceId in Rid case passed for AuthZ + /// + public string ResourceAddress { get; private set; } + + public bool IsFeed { get; set; } + + public string EntityId { get; set; } + + public INameValueCollection Headers { get; private set; } + + /// + /// Contains the context shared by handlers. + /// + public IDictionary Properties { get; set; } + + public Stream Body { get; set; } + + public CloneableStream CloneableBody { get; private set; } + + /// + /// Authorization token used for the request. + /// This will be used to generate any child requests that are needed to process the request. + /// + public AuthorizationTokenType RequestAuthorizationTokenType { get; set; } + + public bool IsBodySeekableClonableAndCountable + { + get + { + return (this.Body == null) || (this.CloneableBody != null); + } + } + + public OperationType OperationType { get; private set; } + + public ResourceType ResourceType { get; private set; } + + public string QueryString { get; set; } + + //Backend Continuation. + public string Continuation + { + get + { + return this.Headers[HttpConstants.HttpHeaders.Continuation]; + } + set + { + this.Headers[HttpConstants.HttpHeaders.Continuation] = value; + } + } + + internal string ApiVersion + { + get + { + return this.Headers[HttpConstants.HttpHeaders.Version]; + } + } + + /// + /// StoreModel vs GatewayStoreModel contract for friends. + /// TODO: SDK V3 start using this contract. - https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2470799 + /// + internal static bool IsGatewayMode(ResourceType resourceType, OperationType operationType) + { + if (resourceType == ResourceType.Offer || + (resourceType.IsScript() && operationType != OperationType.ExecuteJavaScript) || + resourceType == ResourceType.PartitionKeyRange || + resourceType == ResourceType.Snapshot || + resourceType == ResourceType.ClientEncryptionKey || + (resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete)) + { + return true; + } + + if (operationType == OperationType.Create + || operationType == OperationType.Upsert) + { + if (resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.Collection || + resourceType == ResourceType.Permission) + { + return true; + } + else + { + return false; + } + } + else if (operationType == OperationType.Delete) + { + if (resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + else if ((operationType == OperationType.Replace) || (operationType == OperationType.CollectionTruncate)) + { + if (resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + else if (operationType == OperationType.Read) + { + if (resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + + return false; + } + + public bool ForceNameCacheRefresh { get; set; } + + /// + /// CollectionRoutingMap hash code is used in the cache + /// refresh scenarios to avoid doing a refresh when another + /// request already completed one. + /// + public int LastCollectionRoutingMapHashCode { get; set; } + + public bool ForcePartitionKeyRangeRefresh { get; set; } + + public bool ForceCollectionRoutingMapRefresh { get; set; } + + public bool ForceMasterRefresh { get; set; } + + public bool IsReadOnlyRequest + { + get + { + return (this.OperationType == Documents.OperationType.Read + || this.OperationType == Documents.OperationType.ReadFeed + || this.OperationType == Documents.OperationType.Head + || this.OperationType == Documents.OperationType.HeadFeed + || this.OperationType == Documents.OperationType.Query + || this.OperationType == Documents.OperationType.SqlQuery + || this.OperationType == Documents.OperationType.QueryPlan +#if !COSMOSCLIENT + || this.OperationType == Documents.OperationType.GetStorageAuthToken +#endif + ); + } + } + + public bool IsReadOnlyScript + { + get + { + string isReadOnlyScript = this.Headers.Get(HttpConstants.HttpHeaders.IsReadOnlyScript); + if (string.IsNullOrEmpty(isReadOnlyScript)) + { + return false; + } + else + { + return this.OperationType == Documents.OperationType.ExecuteJavaScript + && isReadOnlyScript.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase); + } + } + } + + public bool IsChangeFeedRequest + { + get + { + string aimKey = this.Headers.Get(HttpConstants.HttpHeaders.A_IM); + + return !string.IsNullOrWhiteSpace(aimKey); + } + } + + /// + /// Get the HttpMethod for request based on OperationType and Body + /// + public string HttpMethod + { + get + { + switch (this.OperationType) + { + case OperationType.Create: + case OperationType.ExecuteJavaScript: + case OperationType.Query: + case OperationType.SqlQuery: + case OperationType.Upsert: + case OperationType.BatchApply: + case OperationType.Batch: + case OperationType.QueryPlan: + case OperationType.MetadataCheckAccess: + case OperationType.CompleteUserTransaction: + return HttpConstants.HttpMethods.Post; + + case OperationType.Delete: + return HttpConstants.HttpMethods.Delete; + + case OperationType.Read: + return HttpConstants.HttpMethods.Get; + + case OperationType.ReadFeed: + { + if (this.Body == null) + { + return HttpConstants.HttpMethods.Get; + } + else + { + return HttpConstants.HttpMethods.Post; + } + } + + case OperationType.Replace: + case OperationType.CollectionTruncate: + return HttpConstants.HttpMethods.Put; + + case OperationType.Patch: + return HttpConstants.HttpMethods.Patch; + + case OperationType.Head: + case OperationType.HeadFeed: + return HttpConstants.HttpMethods.Head; + +#if !COSMOSCLIENT + // Control operations + case OperationType.Pause: + case OperationType.Recycle: + case OperationType.Resume: + case OperationType.Stop: + case OperationType.Crash: + case OperationType.ForceConfigRefresh: + case OperationType.Throttle: + case OperationType.PreCreateValidation: + case OperationType.Recreate: + case OperationType.GetSplitPoint: + case OperationType.AbortSplit: + case OperationType.CompleteSplit: + case OperationType.CompleteMergeOnMaster: + case OperationType.CompleteMergeOnTarget: + case OperationType.OfferUpdateOperation: + case OperationType.OfferPreGrowValidation: + case OperationType.BatchReportThroughputUtilization: + case OperationType.AbortPartitionMigration: + case OperationType.CompletePartitionMigration: + case OperationType.PreReplaceValidation: + case OperationType.MigratePartition: + case OperationType.MasterReplaceOfferOperation: + case OperationType.InitiateDatabaseOfferPartitionShrink: + case OperationType.CompleteDatabaseOfferPartitionShrink: + case OperationType.ServiceReservation: + case OperationType.GetSplitPoints: + case OperationType.GetUnwrappedDek: + case OperationType.GetDekProperties: + case OperationType.GetFederationConfigurations: + case OperationType.GetDatabaseAccountConfigurations: + case OperationType.GetStorageServiceConfigurations: + case OperationType.ForcePartitionBackup: + case OperationType.MasterInitiatedProgressCoordination: + case OperationType.CreateSystemSnapshot: + case OperationType.CreateRidRangeResources: + case OperationType.GetAadGroups: + case OperationType.UpdateFailoverPriorityList: + case OperationType.GetStorageAccountSas: + case OperationType.GetBatchCustomerManagedKeyStatus: + case OperationType.UpdatePartitionThroughput: + case OperationType.XPDatabaseAccountMetaData: + case OperationType.Truncate: + return HttpConstants.HttpMethods.Post; + + case OperationType.EnsureSnapshotOperation: + return HttpConstants.HttpMethods.Put; + + case OperationType.ReadReplicaFromMasterPartition: + case OperationType.ReadReplicaFromServerPartition: + case OperationType.GetStorageAuthToken: + case OperationType.GetCustomerManagedKeyStatus: + case OperationType.GetGraphDatabaseAccountConfiguration: + return HttpConstants.HttpMethods.Get; +#endif + + default: + string message = string.Format(CultureInfo.InvariantCulture, "Unsupported operation type: {0}.", this.OperationType); + Debug.Fail(message); + throw new NotImplementedException(message); + } + } + } + + public JsonSerializerSettings SerializerSettings + { + get; + set; + } + +#region Test hooks + + public uint? DefaultReplicaIndex + { + get; + set; + } + +#endregion + + public void Dispose() + { + if (this.isDisposed) + { + return; + } + + if (this.Body != null) + { + this.Body.Dispose(); + this.Body = null; + } + + if (this.CloneableBody != null) + { + this.CloneableBody.Dispose(); + this.CloneableBody = null; + } + + this.isDisposed = true; + } + + /// + /// Verify the address is same as claimed resourceType + /// + /// + public bool IsValidAddress(ResourceType resourceType = ResourceType.Unknown) + { + ResourceType resourceTypeToValidate = ResourceType.Unknown; + + if (resourceType != ResourceType.Unknown) + { + resourceTypeToValidate = resourceType; + } + else + { + if (!this.IsFeed) + { + resourceTypeToValidate = this.ResourceType; + } + else + { + if (this.ResourceType == ResourceType.Database) + { + return true; + } + else if (this.ResourceType == ResourceType.Collection || + this.ResourceType == ResourceType.User || + this.ResourceType == ResourceType.ClientEncryptionKey || + this.ResourceType == ResourceType.UserDefinedType) + { + resourceTypeToValidate = ResourceType.Database; + } + else if (this.ResourceType == ResourceType.Permission) + { + resourceTypeToValidate = ResourceType.User; + } + else if (this.ResourceType == ResourceType.Document || + this.ResourceType == ResourceType.StoredProcedure || + this.ResourceType == ResourceType.UserDefinedFunction || + this.ResourceType == ResourceType.Trigger || + this.ResourceType == ResourceType.Conflict || + this.ResourceType == ResourceType.StoredProcedure || + this.ResourceType == ResourceType.PartitionKeyRange || + this.ResourceType == ResourceType.Schema || + this.ResourceType == ResourceType.PartitionedSystemDocument || + this.ResourceType == ResourceType.SystemDocument) + { + resourceTypeToValidate = ResourceType.Collection; + } + else if (this.ResourceType == ResourceType.Attachment) + { + resourceTypeToValidate = ResourceType.Document; + } + else if (this.ResourceType == ResourceType.Snapshot) + { + return true; + } + else if (this.ResourceType == ResourceType.RoleDefinition) + { + return true; + } + else if (this.ResourceType == ResourceType.RoleAssignment) + { + return true; + } + else if (this.ResourceType == ResourceType.InteropUser) + { + return true; + } + else if (this.ResourceType == ResourceType.AuthPolicyElement) + { + return true; + } + else if (this.ResourceType == ResourceType.EncryptionScope) + { + return true; + } +#if !COSMOSCLIENT + else if (this.ResourceType == ResourceType.VectorClock) + { + return true; + } +#endif + else + { + return false; + } + } + } + + if (IsNameBased) + { + return PathsHelper.ValidateResourceFullName(resourceType != ResourceType.Unknown ? resourceType : resourceTypeToValidate, this.ResourceAddress); + } + else + { + return PathsHelper.ValidateResourceId(resourceTypeToValidate, this.ResourceId); + } + } + + public void AddPreferHeader(string preferHeaderName, string preferHeaderValue) + { + string headerToAdd = string.Format( + CultureInfo.InvariantCulture, + DocumentServiceRequest.PreferHeaderValueFormat, + preferHeaderName, + preferHeaderValue); + + string preferHeader = this.Headers[HttpConstants.HttpHeaders.Prefer]; + + if (!string.IsNullOrEmpty(preferHeader)) + { + preferHeader += DocumentServiceRequest.PreferHeadersSeparator + headerToAdd; + } + else + { + preferHeader = headerToAdd; + } + + this.Headers[HttpConstants.HttpHeaders.Prefer] = preferHeader; + } + + // Clone from request + public static DocumentServiceRequest CreateFromResource( + DocumentServiceRequest request, + Resource modifiedResource) + { + DocumentServiceRequest modifiedRequest; + if (!request.IsNameBased) + { + modifiedRequest = DocumentServiceRequest.Create(request.OperationType, modifiedResource, request.ResourceType, request.RequestAuthorizationTokenType, request.Headers, request.ResourceId); + } + else + { + modifiedRequest = DocumentServiceRequest.CreateFromName(request.OperationType, modifiedResource, request.ResourceType, request.Headers, request.ResourceAddress, request.RequestAuthorizationTokenType); + } + + return modifiedRequest; + } + + + //POST or PUT + [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] + public static DocumentServiceRequest Create( + OperationType operationType, + Resource resource, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null, + string ownerResourceId = null, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + MemoryStream stream = new MemoryStream(); + if (resource != null) + { + resource.SaveTo(stream, formattingPolicy); + } + stream.Position = 0; + + DocumentServiceRequest request = new DocumentServiceRequest( + operationType, + ownerResourceId != null ? ownerResourceId : resource.ResourceId, + resourceType, + stream, + headers, + false, + authorizationTokenType); + + request.CloneableBody = new CloneableStream(stream); + return request; + } + + public static DocumentServiceRequest Create( + OperationType operationType, + ResourceType resourceType, + MemoryStream stream, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + DocumentServiceRequest request = new DocumentServiceRequest( + operationType, + null, // resourceIdOrFullName + resourceType, + stream, + headers, + false, // isNameBased + authorizationTokenType); + + request.CloneableBody = new CloneableStream(stream); + return request; + } + + [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] + public static DocumentServiceRequest Create( + OperationType operationType, + string ownerResourceId, + byte[] seralizedResource, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + MemoryStream stream = new MemoryStream(seralizedResource); + + return new DocumentServiceRequest( + operationType, + ownerResourceId, + resourceType, + stream, + headers, + false, + authorizationTokenType); + } + + [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] + public static DocumentServiceRequest Create( + OperationType operationType, + string ownerResourceId, + ResourceType resourceType, + bool isNameBased, + AuthorizationTokenType authorizationTokenType, + byte[] seralizedResource = null, + INameValueCollection headers = null, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + MemoryStream stream = seralizedResource == null ? null : new MemoryStream(seralizedResource); + + return new DocumentServiceRequest( + operationType, + ownerResourceId, + resourceType, + stream, + headers, + isNameBased, + authorizationTokenType); + } + + public static DocumentServiceRequest Create( + OperationType operationType, + string resourceId, + ResourceType resourceType, + Stream body, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest(operationType, resourceId, resourceType, body, headers, false, authorizationTokenType); + } + + //Get, Delete, FeedRead. + public static DocumentServiceRequest Create( + OperationType operationType, + string resourceId, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest(operationType, resourceId, resourceType, null, headers, false, authorizationTokenType); + } + + public static DocumentServiceRequest CreateFromName( + OperationType operationType, + string resourceFullName, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest(operationType, resourceFullName, resourceType, null, headers, true, authorizationTokenType); + } + + public static DocumentServiceRequest CreateFromName( + OperationType operationType, + Resource resource, + ResourceType resourceType, + INameValueCollection headers, + string resourceFullName, + AuthorizationTokenType authorizationTokenType, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + MemoryStream stream = new MemoryStream(); + resource.SaveTo(stream, formattingPolicy); + stream.Position = 0; + + return new DocumentServiceRequest(operationType, resourceFullName, resourceType, stream, headers, true, authorizationTokenType); + } + + //Replica Request. + public static DocumentServiceRequest Create( + OperationType operationType, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType) + { + return new DocumentServiceRequest(operationType, null, resourceType, null, null, false, authorizationTokenType); + } + + [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] + public static DocumentServiceRequest Create( + OperationType operationType, + string relativePath, + Resource resource, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None, + JsonSerializerSettings settings = null) + { + MemoryStream stream = new MemoryStream(); + resource.SaveTo(stream, formattingPolicy, settings); + stream.Position = 0; + + DocumentServiceRequest request = new DocumentServiceRequest(operationType, resourceType, relativePath, stream, authorizationTokenType, headers); + request.SerializerSettings = settings; + + // since we constructed the body ourselves in a way that it can be safely given to a CloneableStream, + // assign that here, so that EnsureBufferedBodyAsync will be a no-op (won't incur unnecessary memcpy) + request.CloneableBody = new CloneableStream(stream); + return request; + } + + [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Stream is disposed with request instance")] + public static DocumentServiceRequest Create( + OperationType operationType, + Uri requestUri, + Resource resource, + ResourceType resourceType, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null, + SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + MemoryStream stream = new MemoryStream(); + resource.SaveTo(stream, formattingPolicy); + stream.Position = 0; + + DocumentServiceRequest request = new DocumentServiceRequest(operationType, resourceType, requestUri.PathAndQuery, stream, authorizationTokenType, headers); + + // since we constructed the body ourselves in a way that it can be safely given to a CloneableStream, + // assign that here, so that EnsureBufferedBodyAsync will be a no-op (won't incur unnecessary memcpy) + request.CloneableBody = new CloneableStream(stream); + return request; + + } + + public static DocumentServiceRequest Create( + OperationType operationType, + ResourceType resourceType, + string relativePath, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest(operationType, resourceType, relativePath, null, authorizationTokenType, headers); + } + + public static DocumentServiceRequest Create( + OperationType operationType, + ResourceType resourceType, + Uri requestUri, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest(operationType, resourceType, requestUri.PathAndQuery, null, authorizationTokenType, headers); + } + + public static DocumentServiceRequest Create(OperationType operationType, + ResourceType resourceType, + string relativePath, + Stream resourceStream, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers = null) + { + return new DocumentServiceRequest( + operationType, + resourceType, + relativePath, + resourceStream, + authorizationTokenType, + headers); + } + + internal static DocumentServiceRequest Create( + OperationType operationType, + ResourceType resourceType, + string relativePath, + Stream resourceStream, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers, + bool isNameBased, + bool isFeed, + string resourceIdOrFullName, + string databaseName, + string collectionName, + string documentName, + string resourceTypeString) + { + return new DocumentServiceRequest( + operationType, + resourceType, + relativePath, + resourceStream, + authorizationTokenType, + headers, + isNameBased, + isFeed, + resourceIdOrFullName, + databaseName, + collectionName, + documentName, + resourceTypeString); + } + + public static DocumentServiceRequest Create(OperationType operationType, + ResourceType resourceType, + Uri requestUri, + Stream resourceStream, + AuthorizationTokenType authorizationTokenType, + INameValueCollection headers) + { + return new DocumentServiceRequest( + operationType, + resourceType, + requestUri.PathAndQuery, + resourceStream, + authorizationTokenType, + headers); + } + + public async Task EnsureBufferedBodyAsync(bool allowUnsafeDataAccess = true) + { + if (this.Body == null) + return; + else if (this.CloneableBody != null) + return; + + this.CloneableBody = await StreamExtension.AsClonableStreamAsync(this.Body, allowUnsafeDataAccess); + } + + public void ClearRoutingHints() + { + this.PartitionKeyRangeIdentity = null; + this.ServiceIdentity = null; + this.RequestContext.TargetIdentity = null; + this.RequestContext.ResolvedPartitionKeyRange = null; + } + + public DocumentServiceRequest Clone() + { + if (!this.IsBodySeekableClonableAndCountable) + { + throw new InvalidOperationException(); + } + + return new DocumentServiceRequest{ + OperationType = this.OperationType, + ForceNameCacheRefresh = this.ForceNameCacheRefresh, + ResourceType = this.ResourceType, + ServiceIdentity = this.ServiceIdentity, + SystemAuthorizationParams = this.SystemAuthorizationParams == null ? null : this.SystemAuthorizationParams.Clone(), + // Body = this.Body, // intentionally don't clone body, as it is not cloneable. + CloneableBody = this.CloneableBody != null ? this.CloneableBody.Clone() : null, + Headers = (INameValueCollection)this.Headers.Clone(), + IsFeed = this.IsFeed, + IsNameBased = this.IsNameBased, + ResourceAddress = this.ResourceAddress, + ResourceId = this.ResourceId, + RequestAuthorizationTokenType = this.RequestAuthorizationTokenType, + RequestContext = this.RequestContext.Clone(), + PartitionKeyRangeIdentity = this.PartitionKeyRangeIdentity, + UseGatewayMode = this.UseGatewayMode, + QueryString = this.QueryString, + Continuation = this.Continuation, + ForcePartitionKeyRangeRefresh = this.ForcePartitionKeyRangeRefresh, + LastCollectionRoutingMapHashCode = this.LastCollectionRoutingMapHashCode, + ForceCollectionRoutingMapRefresh = this.ForceCollectionRoutingMapRefresh, + ForceMasterRefresh = this.ForceMasterRefresh, + DefaultReplicaIndex = this.DefaultReplicaIndex, + Properties = this.Properties, + UseStatusCodeForFailures = this.UseStatusCodeForFailures, + UseStatusCodeFor429 = this.UseStatusCodeFor429, + DatabaseName = this.DatabaseName, + CollectionName = this.CollectionName + }; + } + + private void InitializeWithDataParsedFromUri( + string path, + bool isNameBased, + bool isFeed, + string resourceIdOrFullName, + string databaseName, + string collectionName, + string documentName, + string resourceTypeString) + { + this.IsNameBased = isNameBased; + this.IsResourceNameParsedFromUri = true; + this.IsFeed = isFeed; + + if (this.ResourceType == ResourceType.Unknown) + { + this.ResourceType = PathsHelper.GetResourcePathSegment(resourceTypeString); + } + + if (isNameBased) + { + this.ResourceAddress = resourceIdOrFullName; + this.DatabaseName = databaseName; + this.CollectionName = collectionName; + this.DocumentName = documentName; + } + else + { + this.ResourceId = resourceIdOrFullName; + this.ResourceAddress = resourceIdOrFullName; + + // throw exception when the address parsing fail + // do not parse address for offer/snapshot resource + if (!string.IsNullOrEmpty(this.ResourceId) && + !Documents.ResourceId.TryParse(this.ResourceId, out ResourceId _) && + !(this.ResourceType == ResourceType.Offer) && + !(this.ResourceType == ResourceType.Media) && + !(this.ResourceType == ResourceType.DatabaseAccount) && + !(this.ResourceType == ResourceType.Snapshot) && + !(this.ResourceType == ResourceType.EncryptionScope) && + !(this.ResourceType == ResourceType.RoleDefinition) && + !(this.ResourceType == ResourceType.RoleAssignment) && + !(this.ResourceType == ResourceType.InteropUser) && + !(this.ResourceType == ResourceType.AuthPolicyElement) + #if !COSMOSCLIENT + && !(this.ResourceType == ResourceType.MasterPartition) && + !(this.ResourceType == ResourceType.ServerPartition) && + !(this.ResourceType == ResourceType.RidRange) && + !(this.ResourceType == ResourceType.VectorClock) + #endif + ) + { + throw new NotFoundException(string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceUrlQuery, path, HttpConstants.QueryStrings.Url)); + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestContext.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestContext.cs index 283fdd3742..cd318ebcc0 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestContext.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestContext.cs @@ -1,244 +1,249 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Net; - using Microsoft.Azure.Documents.Routing; - - internal sealed class DocumentServiceRequestContext - { - private ReferenceCountedDisposable quorumSelectedStoreResponse; - - public TimeoutHelper TimeoutHelper { get; set; } - - public RequestChargeTracker RequestChargeTracker { get; set; } - - public bool ForceRefreshAddressCache { get; set; } - - /// - /// PartitionAddressInformation hash code is used in the cache - /// refresh scenarios to avoid doing a refresh when another - /// request already completed one. - /// - public int LastPartitionAddressInformationHashCode { get; set; } - - /// - /// Non thread safe. - /// - public ReferenceCountedDisposable QuorumSelectedStoreResponse => this.quorumSelectedStoreResponse; - - public ConsistencyLevel? OriginalRequestConsistencyLevel { get; set; } - - public long QuorumSelectedLSN { get; set; } - - public long GlobalCommittedSelectedLSN { get; set; } - - /// - /// Cache the write storeResult in context during global strong - /// where we want to lock on a single initial write response and perform barrier calls until globalCommittedLsn is caught up - /// - public ReferenceCountedDisposable GlobalStrongWriteStoreResult { get; set; } - - /// - /// Unique Identity that represents the target partition where the request should reach. - /// In gateway it is same as ServiceIdentity. - /// In client it is a string that represents the partition and service index - /// - public ServiceIdentity TargetIdentity { get; set; } - - /// - /// If the StoreReader should perform the local refresh for GoneException instead of - /// throwing is back to retry policy. This is done to avoid losing the state (response + LSN) - /// while executing quorum read logic - /// - public bool PerformLocalRefreshOnGoneException { get; set; } - - /// - /// Effective partition key value to be used for routing. - /// For server resources either this, or PartitionKeyRangeId header must be specified. - /// - public PartitionKeyInternal EffectivePartitionKey { get; set; } - - /// - /// Is used to figure out which part of global session token is relevant - /// for the partition to which request is sent. - /// It is set automatically by address cache. - /// Is set as part of address resolution. - /// - public PartitionKeyRange ResolvedPartitionKeyRange { get; set; } - - /// - /// Session token used for this request. - /// - public ISessionToken SessionToken { get; set; } - - /// - /// If the background refresh has been performed for this request to eliminate the - /// extra replica that is not participating in quorum but causes Gone - /// - public bool PerformedBackgroundAddressRefresh { get; set; } - - public IClientSideRequestStatistics ClientRequestStatistics - { - get; - set; - } - - public string ResolvedCollectionRid { get; set; } - - /// - /// Region which is going to serve the DocumentServiceRequest. - /// Populated during address resolution for the request. - /// - public string RegionName { get; set; } - - /// - /// Indicates if the request is orginating from the same Azure region as the Cosmos DB account - /// - public bool LocalRegionRequest { get; set; } - - /// - /// Indicates if this request is being retried. - /// - public bool IsRetry { get; set; } - - /// - /// A list of regions to exclude routing to, used for per-request level routing exclusion - /// - public List ExcludeRegions { get; set; } - - /// - /// Set of all failed enpoints for a DSR. Used for prioritizing replica selection - /// - public Lazy> FailedEndpoints { get; private set; } - - public DocumentServiceRequestContext() - { - this.FailedEndpoints = new Lazy>(); - } - - /// - /// Uodates selected storeResult and dispose and previously selected result as no longer used/dereferenced. - /// - /// - /// Non thread safe. - /// - public void UpdateQuorumSelectedStoreResponse(ReferenceCountedDisposable storeResult) - { - ReferenceCountedDisposable currentStoreResult = this.quorumSelectedStoreResponse; - if (currentStoreResult == storeResult) - { - // noop to avoid disposal if we try to assign same stream multiple times - return; - } - - // Dispose old StoreResult referenced on context if any when it is dereferenced on request context - currentStoreResult?.Dispose(); - - this.quorumSelectedStoreResponse = storeResult; - } - - public void AddToFailedEndpoints(Exception storeException, TransportAddressUri targetUri) - { - // Add to the FailedEnpoints hashset only for 408, 410, >= 500 to avoid the respective replica on retries - if (storeException is DocumentClientException dce) - { - if (dce.StatusCode == HttpStatusCode.Gone || - dce.StatusCode == HttpStatusCode.RequestTimeout || - (int)dce.StatusCode >= 500) - { - this.FailedEndpoints.Value.Add(targetUri); - } - } - } - - /// - /// Sets routing directive for to resolve - /// the request to endpoint based on location index - /// - /// Index of the location to which the request should be routed - /// Use preferred locations to route request - public void RouteToLocation(int locationIndex, bool usePreferredLocations) - { - this.LocationIndexToRoute = locationIndex; - this.UsePreferredLocations = usePreferredLocations; - this.LocationEndpointToRoute = null; - } - - /// - /// Sets location-based routing directive for to resolve - /// the request to given - /// - /// Location endpoint to which the request should be routed - public void RouteToLocation(Uri locationEndpoint) - { - this.LocationEndpointToRoute = locationEndpoint; - this.LocationIndexToRoute = null; - this.UsePreferredLocations = null; - } - - /// - /// Clears location-based routing directive - /// - public void ClearRouteToLocation() - { - this.LocationIndexToRoute = null; - this.LocationEndpointToRoute = null; - this.UsePreferredLocations = null; - } - - public bool? UsePreferredLocations { get; private set; } - - public int? LocationIndexToRoute { get; private set; } - - public Uri LocationEndpointToRoute { get; private set; } - - public bool EnsureCollectionExistsCheck { get; set; } - - /// - /// Flag that enables ConnectionStateListener to trigger an address cache refresh - /// on connection reset notification - /// - public bool EnableConnectionStateListener { get; set; } - - /// - /// contains the modified materializedview source collection content. - /// It is set during materializedview delete operation. - /// Only required for CosmosFabric based tests. - /// - public string SerializedSourceCollectionForMaterializedView { get; set; } - - public DocumentServiceRequestContext Clone() - { - DocumentServiceRequestContext requestContext = new DocumentServiceRequestContext(); - - requestContext.TimeoutHelper = this.TimeoutHelper; - requestContext.RequestChargeTracker = this.RequestChargeTracker; - requestContext.ForceRefreshAddressCache = this.ForceRefreshAddressCache; - requestContext.TargetIdentity = this.TargetIdentity; - requestContext.PerformLocalRefreshOnGoneException = this.PerformLocalRefreshOnGoneException; - requestContext.SessionToken = this.SessionToken; - requestContext.ResolvedPartitionKeyRange = this.ResolvedPartitionKeyRange; - requestContext.PerformedBackgroundAddressRefresh = this.PerformedBackgroundAddressRefresh; - requestContext.ResolvedCollectionRid = this.ResolvedCollectionRid; - requestContext.EffectivePartitionKey = this.EffectivePartitionKey; - requestContext.ClientRequestStatistics = this.ClientRequestStatistics; - requestContext.OriginalRequestConsistencyLevel = this.OriginalRequestConsistencyLevel; - requestContext.UsePreferredLocations = this.UsePreferredLocations; - requestContext.LocationIndexToRoute = this.LocationIndexToRoute; - requestContext.LocationEndpointToRoute = this.LocationEndpointToRoute; - requestContext.EnsureCollectionExistsCheck = this.EnsureCollectionExistsCheck; - requestContext.EnableConnectionStateListener = this.EnableConnectionStateListener; - requestContext.LocalRegionRequest = this.LocalRegionRequest; - requestContext.FailedEndpoints = this.FailedEndpoints; - requestContext.LastPartitionAddressInformationHashCode = this.LastPartitionAddressInformationHashCode; - requestContext.ExcludeRegions = this.ExcludeRegions; - - return requestContext; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Net; + using Microsoft.Azure.Documents.Routing; + + internal sealed class DocumentServiceRequestContext + { + private ReferenceCountedDisposable quorumSelectedStoreResponse; + + public TimeoutHelper TimeoutHelper { get; set; } + + public RequestChargeTracker RequestChargeTracker { get; set; } + + public bool ForceRefreshAddressCache { get; set; } + + /// + /// PartitionAddressInformation hash code is used in the cache + /// refresh scenarios to avoid doing a refresh when another + /// request already completed one. + /// + public int LastPartitionAddressInformationHashCode { get; set; } + + /// + /// Non thread safe. + /// + public ReferenceCountedDisposable QuorumSelectedStoreResponse => this.quorumSelectedStoreResponse; + + public ConsistencyLevel? OriginalRequestConsistencyLevel { get; set; } + + public long QuorumSelectedLSN { get; set; } + + public long GlobalCommittedSelectedLSN { get; set; } + + /// + /// Cache the write storeResult in context during global strong + /// where we want to lock on a single initial write response and perform barrier calls until globalCommittedLsn is caught up + /// + public ReferenceCountedDisposable GlobalStrongWriteStoreResult { get; set; } + + /// + /// Unique Identity that represents the target partition where the request should reach. + /// In gateway it is same as ServiceIdentity. + /// In client it is a string that represents the partition and service index + /// + public ServiceIdentity TargetIdentity { get; set; } + + /// + /// If the StoreReader should perform the local refresh for GoneException instead of + /// throwing is back to retry policy. This is done to avoid losing the state (response + LSN) + /// while executing quorum read logic + /// + public bool PerformLocalRefreshOnGoneException { get; set; } + + /// + /// Effective partition key value to be used for routing. + /// For server resources either this, or PartitionKeyRangeId header must be specified. + /// + public PartitionKeyInternal EffectivePartitionKey { get; set; } + + /// + /// Is used to figure out which part of global session token is relevant + /// for the partition to which request is sent. + /// It is set automatically by address cache. + /// Is set as part of address resolution. + /// + public PartitionKeyRange ResolvedPartitionKeyRange { get; set; } + + /// + /// Session token used for this request. + /// + public ISessionToken SessionToken { get; set; } + + /// + /// If the background refresh has been performed for this request to eliminate the + /// extra replica that is not participating in quorum but causes Gone + /// + public bool PerformedBackgroundAddressRefresh { get; set; } + + public IClientSideRequestStatistics ClientRequestStatistics + { + get; + set; + } + + public string ResolvedCollectionRid { get; set; } + + /// + /// Region which is going to serve the DocumentServiceRequest. + /// Populated during address resolution for the request. + /// + public string RegionName { get; set; } + + /// + /// Indicates if the request is orginating from the same Azure region as the Cosmos DB account + /// + public bool LocalRegionRequest { get; set; } + + /// + /// Indicates if this request is being retried. + /// + public bool IsRetry { get; set; } + + /// + /// Indicates if this request is being retried on a different region due to Per partition failover. + /// + public bool IsPartitionFailoverRetry { get; set; } + + /// + /// A list of regions to exclude routing to, used for per-request level routing exclusion + /// + public List ExcludeRegions { get; set; } + + /// + /// Set of all failed enpoints for a DSR. Used for prioritizing replica selection + /// + public Lazy> FailedEndpoints { get; private set; } + + public DocumentServiceRequestContext() + { + this.FailedEndpoints = new Lazy>(); + } + + /// + /// Uodates selected storeResult and dispose and previously selected result as no longer used/dereferenced. + /// + /// + /// Non thread safe. + /// + public void UpdateQuorumSelectedStoreResponse(ReferenceCountedDisposable storeResult) + { + ReferenceCountedDisposable currentStoreResult = this.quorumSelectedStoreResponse; + if (currentStoreResult == storeResult) + { + // noop to avoid disposal if we try to assign same stream multiple times + return; + } + + // Dispose old StoreResult referenced on context if any when it is dereferenced on request context + currentStoreResult?.Dispose(); + + this.quorumSelectedStoreResponse = storeResult; + } + + public void AddToFailedEndpoints(Exception storeException, TransportAddressUri targetUri) + { + // Add to the FailedEnpoints hashset only for 408, 410, >= 500 to avoid the respective replica on retries + if (storeException is DocumentClientException dce) + { + if (dce.StatusCode == HttpStatusCode.Gone || + dce.StatusCode == HttpStatusCode.RequestTimeout || + (int)dce.StatusCode >= 500) + { + this.FailedEndpoints.Value.Add(targetUri); + } + } + } + + /// + /// Sets routing directive for to resolve + /// the request to endpoint based on location index + /// + /// Index of the location to which the request should be routed + /// Use preferred locations to route request + public void RouteToLocation(int locationIndex, bool usePreferredLocations) + { + this.LocationIndexToRoute = locationIndex; + this.UsePreferredLocations = usePreferredLocations; + this.LocationEndpointToRoute = null; + } + + /// + /// Sets location-based routing directive for to resolve + /// the request to given + /// + /// Location endpoint to which the request should be routed + public void RouteToLocation(Uri locationEndpoint) + { + this.LocationEndpointToRoute = locationEndpoint; + this.LocationIndexToRoute = null; + this.UsePreferredLocations = null; + } + + /// + /// Clears location-based routing directive + /// + public void ClearRouteToLocation() + { + this.LocationIndexToRoute = null; + this.LocationEndpointToRoute = null; + this.UsePreferredLocations = null; + } + + public bool? UsePreferredLocations { get; private set; } + + public int? LocationIndexToRoute { get; private set; } + + public Uri LocationEndpointToRoute { get; private set; } + + public bool EnsureCollectionExistsCheck { get; set; } + + /// + /// Flag that enables ConnectionStateListener to trigger an address cache refresh + /// on connection reset notification + /// + public bool EnableConnectionStateListener { get; set; } + + /// + /// contains the modified materializedview source collection content. + /// It is set during materializedview delete operation. + /// Only required for CosmosFabric based tests. + /// + public string SerializedSourceCollectionForMaterializedView { get; set; } + + public DocumentServiceRequestContext Clone() + { + DocumentServiceRequestContext requestContext = new DocumentServiceRequestContext(); + + requestContext.TimeoutHelper = this.TimeoutHelper; + requestContext.RequestChargeTracker = this.RequestChargeTracker; + requestContext.ForceRefreshAddressCache = this.ForceRefreshAddressCache; + requestContext.TargetIdentity = this.TargetIdentity; + requestContext.PerformLocalRefreshOnGoneException = this.PerformLocalRefreshOnGoneException; + requestContext.SessionToken = this.SessionToken; + requestContext.ResolvedPartitionKeyRange = this.ResolvedPartitionKeyRange; + requestContext.PerformedBackgroundAddressRefresh = this.PerformedBackgroundAddressRefresh; + requestContext.ResolvedCollectionRid = this.ResolvedCollectionRid; + requestContext.EffectivePartitionKey = this.EffectivePartitionKey; + requestContext.ClientRequestStatistics = this.ClientRequestStatistics; + requestContext.OriginalRequestConsistencyLevel = this.OriginalRequestConsistencyLevel; + requestContext.UsePreferredLocations = this.UsePreferredLocations; + requestContext.LocationIndexToRoute = this.LocationIndexToRoute; + requestContext.LocationEndpointToRoute = this.LocationEndpointToRoute; + requestContext.EnsureCollectionExistsCheck = this.EnsureCollectionExistsCheck; + requestContext.EnableConnectionStateListener = this.EnableConnectionStateListener; + requestContext.LocalRegionRequest = this.LocalRegionRequest; + requestContext.FailedEndpoints = this.FailedEndpoints; + requestContext.LastPartitionAddressInformationHashCode = this.LastPartitionAddressInformationHashCode; + requestContext.ExcludeRegions = this.ExcludeRegions; + + return requestContext; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestExtensions.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestExtensions.cs index ecd10448a1..987e708b19 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequestExtensions.cs @@ -1,47 +1,47 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal static class DocumentServiceRequestExtensions - { - /// - /// This method is used to define if a particular response to the current needs to be processed without exceptions based on the status code and substatus code. - /// - /// Current instance. - /// Status code of the response. - /// of the response of any. - /// Whether the response should be processed without exceptions (true) or not (false). - public static bool IsValidStatusCodeForExceptionlessRetry( - this DocumentServiceRequest request, - int statusCode, - SubStatusCodes subStatusCode = SubStatusCodes.Unknown) - { - // Only for 404, 409, and 412 - if (request.UseStatusCodeForFailures - && (statusCode == (int)System.Net.HttpStatusCode.PreconditionFailed - || statusCode == (int)System.Net.HttpStatusCode.Conflict - // ReadSessionNotAvailable: fall back to exception based approach for reliability - || (statusCode == (int)System.Net.HttpStatusCode.NotFound && subStatusCode != SubStatusCodes.ReadSessionNotAvailable))) - { - return true; - } - - // Only for 429 - if (request.UseStatusCodeFor429 - && statusCode == (int)StatusCodes.TooManyRequests) - { - return true; - } - - // Only for 400 - if (request.UseStatusCodeForBadRequest - && (statusCode == (int)StatusCodes.BadRequest && subStatusCode != SubStatusCodes.PartitionKeyMismatch)) - { - return true; - } - - return false; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal static class DocumentServiceRequestExtensions + { + /// + /// This method is used to define if a particular response to the current needs to be processed without exceptions based on the status code and substatus code. + /// + /// Current instance. + /// Status code of the response. + /// of the response of any. + /// Whether the response should be processed without exceptions (true) or not (false). + public static bool IsValidStatusCodeForExceptionlessRetry( + this DocumentServiceRequest request, + int statusCode, + SubStatusCodes subStatusCode = SubStatusCodes.Unknown) + { + // Only for 404, 409, and 412 + if (request.UseStatusCodeForFailures + && (statusCode == (int)System.Net.HttpStatusCode.PreconditionFailed + || statusCode == (int)System.Net.HttpStatusCode.Conflict + // ReadSessionNotAvailable: fall back to exception based approach for reliability + || (statusCode == (int)System.Net.HttpStatusCode.NotFound && subStatusCode != SubStatusCodes.ReadSessionNotAvailable))) + { + return true; + } + + // Only for 429 + if (request.UseStatusCodeFor429 + && statusCode == (int)StatusCodes.TooManyRequests) + { + return true; + } + + // Only for 400 + if (request.UseStatusCodeForBadRequest + && (statusCode == (int)StatusCodes.BadRequest && subStatusCode != SubStatusCodes.PartitionKeyMismatch)) + { + return true; + } + + return false; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/EncryptionScopeMetadata.cs b/Microsoft.Azure.Cosmos/src/direct/EncryptionScopeMetadata.cs index 09587558ad..31ceff1778 100644 --- a/Microsoft.Azure.Cosmos/src/direct/EncryptionScopeMetadata.cs +++ b/Microsoft.Azure.Cosmos/src/direct/EncryptionScopeMetadata.cs @@ -1,111 +1,111 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using Newtonsoft.Json; - - /// - /// Encryption scope metadata(from encryption scope resource) stored in the collection body. - /// This contains all the required metadata from encryption scoper resource which is needed - /// to call the azure key vault to get the unwrapped dek to encrypt/decrypt the data - /// being stored in the collection - /// - internal sealed class EncryptionScopeMetadata : JsonSerializable, ICloneable - { - private Collection cmkMetadataList; - - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id - { - get - { - return base.GetValue(Constants.Properties.Id); - } - set - { - this.SetValue(Constants.Properties.Id, value); - } - } - - [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.Name)] - public string Name - { - get - { - return base.GetValue(Constants.EncryptionScopeProperties.Name); - } - set - { - this.SetValue(Constants.EncryptionScopeProperties.Name, value); - } - } - - [JsonProperty(PropertyName = Constants.KeyVaultProperties.DataEncryptionKeyStatus)] - public DataEncryptionKeyStatus DataEncryptionKeyStatus - { - get - { - return base.GetValue(Constants.KeyVaultProperties.DataEncryptionKeyStatus); - } - set - { - this.SetValue(Constants.KeyVaultProperties.DataEncryptionKeyStatus, value); - } - } - - [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.CMKMetadataList)] - public Collection CMKMetadataList - { - get - { - if (this.cmkMetadataList == null) - { - this.cmkMetadataList = - base.GetObjectCollection( - Constants.EncryptionScopeProperties.CMKMetadataList); - - if (this.cmkMetadataList == null) - { - this.cmkMetadataList = new Collection(); - } - } - - return this.cmkMetadataList; - } - set - { - this.cmkMetadataList = value; - } - } - - public object Clone() - { - EncryptionScopeMetadata cloned = new EncryptionScopeMetadata() - { - Id = this.Id, - Name = this.Name, - DataEncryptionKeyStatus = this.DataEncryptionKeyStatus - }; - - foreach (CMKMetadataInfo item in this.CMKMetadataList) - { - cloned.CMKMetadataList.Add((CMKMetadataInfo)item.Clone()); - } - - return cloned; - } - - internal override void OnSave() - { - base.OnSave(); - - if (this.cmkMetadataList != null) - { - base.SetObjectCollection(Constants.EncryptionScopeProperties.CMKMetadataList, this.cmkMetadataList); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using Newtonsoft.Json; + + /// + /// Encryption scope metadata(from encryption scope resource) stored in the collection body. + /// This contains all the required metadata from encryption scoper resource which is needed + /// to call the azure key vault to get the unwrapped dek to encrypt/decrypt the data + /// being stored in the collection + /// + internal sealed class EncryptionScopeMetadata : JsonSerializable, ICloneable + { + private Collection cmkMetadataList; + + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id + { + get + { + return base.GetValue(Constants.Properties.Id); + } + set + { + this.SetValue(Constants.Properties.Id, value); + } + } + + [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.Name)] + public string Name + { + get + { + return base.GetValue(Constants.EncryptionScopeProperties.Name); + } + set + { + this.SetValue(Constants.EncryptionScopeProperties.Name, value); + } + } + + [JsonProperty(PropertyName = Constants.KeyVaultProperties.DataEncryptionKeyStatus)] + public DataEncryptionKeyStatus DataEncryptionKeyStatus + { + get + { + return base.GetValue(Constants.KeyVaultProperties.DataEncryptionKeyStatus); + } + set + { + this.SetValue(Constants.KeyVaultProperties.DataEncryptionKeyStatus, value); + } + } + + [JsonProperty(PropertyName = Constants.EncryptionScopeProperties.CMKMetadataList)] + public Collection CMKMetadataList + { + get + { + if (this.cmkMetadataList == null) + { + this.cmkMetadataList = + base.GetObjectCollection( + Constants.EncryptionScopeProperties.CMKMetadataList); + + if (this.cmkMetadataList == null) + { + this.cmkMetadataList = new Collection(); + } + } + + return this.cmkMetadataList; + } + set + { + this.cmkMetadataList = value; + } + } + + public object Clone() + { + EncryptionScopeMetadata cloned = new EncryptionScopeMetadata() + { + Id = this.Id, + Name = this.Name, + DataEncryptionKeyStatus = this.DataEncryptionKeyStatus + }; + + foreach (CMKMetadataInfo item in this.CMKMetadataList) + { + cloned.CMKMetadataList.Add((CMKMetadataInfo)item.Clone()); + } + + return cloned; + } + + internal override void OnSave() + { + base.OnSave(); + + if (this.cmkMetadataList != null) + { + base.SetObjectCollection(Constants.EncryptionScopeProperties.CMKMetadataList, this.cmkMetadataList); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/EnumerationDirection.cs b/Microsoft.Azure.Cosmos/src/direct/EnumerationDirection.cs index b442aa39e0..61322d91d2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/EnumerationDirection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/EnumerationDirection.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Enumeration Direction for Read Feed - /// - internal enum EnumerationDirection - { - /// - /// Use Forward Direction - /// - Forward, - - /// - /// Use Reverse Direction - /// - Reverse - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Enumeration Direction for Read Feed + /// + internal enum EnumerationDirection + { + /// + /// Use Forward Direction + /// + Forward, + + /// + /// Use Reverse Direction + /// + Reverse + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Error.cs b/Microsoft.Azure.Cosmos/src/direct/Error.cs index 960cce25e7..cd4e3646f4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Error.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Error.cs @@ -1,86 +1,86 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Encapsulates error related details in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Error : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public Error() - { - - } - - /// - /// Gets or sets the textual description of error code in the Azure Cosmos DB service. - /// - /// The textual description of error code. - [JsonProperty(PropertyName = Constants.Properties.Code)] - public string Code - { - get - { - return base.GetValue(Constants.Properties.Code); - } - set - { - base.SetValue(Constants.Properties.Code, value); - } - } - - /// - /// Gets or sets the error message in the Azure Cosmos DB service. - /// - /// The error message. - [JsonProperty(PropertyName = Constants.Properties.Message)] - public string Message - { - get - { - return base.GetValue(Constants.Properties.Message); - } - set - { - base.SetValue(Constants.Properties.Message, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.ErrorDetails)] - internal string ErrorDetails //Debug Only. - { - get - { - return base.GetValue(Constants.Properties.ErrorDetails); - } - set - { - base.SetValue(Constants.Properties.ErrorDetails, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.AdditionalErrorInfo)] - internal string AdditionalErrorInfo - { - get - { - return base.GetValue(Constants.Properties.AdditionalErrorInfo); - } - set - { - base.SetValue(Constants.Properties.AdditionalErrorInfo, value); - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Encapsulates error related details in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Error : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public Error() + { + + } + + /// + /// Gets or sets the textual description of error code in the Azure Cosmos DB service. + /// + /// The textual description of error code. + [JsonProperty(PropertyName = Constants.Properties.Code)] + public string Code + { + get + { + return base.GetValue(Constants.Properties.Code); + } + set + { + base.SetValue(Constants.Properties.Code, value); + } + } + + /// + /// Gets or sets the error message in the Azure Cosmos DB service. + /// + /// The error message. + [JsonProperty(PropertyName = Constants.Properties.Message)] + public string Message + { + get + { + return base.GetValue(Constants.Properties.Message); + } + set + { + base.SetValue(Constants.Properties.Message, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.ErrorDetails)] + internal string ErrorDetails //Debug Only. + { + get + { + return base.GetValue(Constants.Properties.ErrorDetails); + } + set + { + base.SetValue(Constants.Properties.ErrorDetails, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.AdditionalErrorInfo)] + internal string AdditionalErrorInfo + { + get + { + return base.GetValue(Constants.Properties.AdditionalErrorInfo); + } + set + { + base.SetValue(Constants.Properties.AdditionalErrorInfo, value); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/EtwNativeInterop.cs b/Microsoft.Azure.Cosmos/src/direct/EtwNativeInterop.cs index 3ede8ce7bb..a8f7e0238d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/EtwNativeInterop.cs +++ b/Microsoft.Azure.Cosmos/src/direct/EtwNativeInterop.cs @@ -1,44 +1,44 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Core.Trace -{ - using System; - using System.Runtime.InteropServices; - using Microsoft.Win32.SafeHandles; - - /// - /// Native ETW-related methods from advapi32.dll. - /// - internal static class EtwNativeInterop - { - [DllImport("advapi32.dll", ExactSpelling = true)] - internal static extern uint EventRegister( - in Guid providerId, - IntPtr enableCallback, - IntPtr callbackContext, - ref ProviderHandle registrationHandle); - - [DllImport("advapi32.dll", ExactSpelling = true)] - internal static extern uint EventUnregister(IntPtr registrationHandle); - - [DllImport("advapi32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] - public static extern uint EventWriteString( - ProviderHandle registrationHandle, - byte level, - long keywords, - string message); - - /// - internal class ProviderHandle : SafeHandleZeroOrMinusOneIsInvalid - { - public ProviderHandle() - : base(true) - { - } - - protected override bool ReleaseHandle() => EtwNativeInterop.EventUnregister(this.handle) == 0; - } - } +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Core.Trace +{ + using System; + using System.Runtime.InteropServices; + using Microsoft.Win32.SafeHandles; + + /// + /// Native ETW-related methods from advapi32.dll. + /// + internal static class EtwNativeInterop + { + [DllImport("advapi32.dll", ExactSpelling = true)] + internal static extern uint EventRegister( + in Guid providerId, + IntPtr enableCallback, + IntPtr callbackContext, + ref ProviderHandle registrationHandle); + + [DllImport("advapi32.dll", ExactSpelling = true)] + internal static extern uint EventUnregister(IntPtr registrationHandle); + + [DllImport("advapi32.dll", ExactSpelling = true, CharSet = CharSet.Unicode)] + public static extern uint EventWriteString( + ProviderHandle registrationHandle, + byte level, + long keywords, + string message); + + /// + internal class ProviderHandle : SafeHandleZeroOrMinusOneIsInvalid + { + public ProviderHandle() + : base(true) + { + } + + protected override bool ReleaseHandle() => EtwNativeInterop.EventUnregister(this.handle) == 0; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/EtwTraceListener.cs b/Microsoft.Azure.Cosmos/src/direct/EtwTraceListener.cs index 0e12db54bd..976d720251 100644 --- a/Microsoft.Azure.Cosmos/src/direct/EtwTraceListener.cs +++ b/Microsoft.Azure.Cosmos/src/direct/EtwTraceListener.cs @@ -1,224 +1,224 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Core.Trace -{ - using System; - using System.ComponentModel; - using System.Diagnostics; - using System.Text; - - /// - /// Listens to trace as emitted by TraceSource and sends them to the ETW subsystem using EventWriteString native call. - /// Only supported operation is TraceEvent. - /// - /// - internal sealed class EtwTraceListener : TraceListener - { - /// - /// Max ETW event length for EventWriteString. - /// Formula = 64KB / sizeof(char)(2) - sizeof(ETW header)(72) - unknown factors ~= 32500 char. - /// The ETW subsystem won't log anything longer than 64KB total. - /// Assuming that logging 32500 chars is preferable to 0, any message exceeding that is truncated. - /// - public const int MaxEtwEventLength = 32500; - - /// - /// Registration handle as provided by ETW RegisterEvent call. - /// - private readonly EtwNativeInterop.ProviderHandle providerHandle = new EtwNativeInterop.ProviderHandle(); - - /// - /// Initializes a new instance of the class. - /// - /// ETW provider guid. - /// Trace listener name (unrelated to ETW). - public EtwTraceListener(Guid providerGuid, string name) - : base(name) - { - this.ProviderGuid = providerGuid; - - uint retVal = EtwNativeInterop.EventRegister(providerGuid, IntPtr.Zero, IntPtr.Zero, ref this.providerHandle); - - if (retVal != 0) - { - throw new Win32Exception((int)retVal); - } - } - - /// - /// ETW provider guid. - /// - public Guid ProviderGuid { get; } - - /// - public override bool IsThreadSafe { get; } = true; - - /// - public override void Close() - { - this.Dispose(); - base.Close(); - } - - /// - /// Unregister ETW handle. - /// - /// Unused. - /// - protected override void Dispose(bool disposing) - { - if (this.providerHandle != null && !this.providerHandle.IsInvalid) - { - this.providerHandle.Dispose(); - } - - base.Dispose(disposing); - } - - /// - public override void TraceEvent( - TraceEventCache eventCache, - string source, - TraceEventType eventType, - int id, - string format, - params object[] args) - { - if (this.IsFiltered(eventCache, source, eventType, id)) - { - return; - } - - string finalMessage = format; - - if (args != null && args.Length > 0) - { - StringBuilder sb = StringBuilderCache.Instance; - sb.AppendFormat(format, args); - - // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. - if (sb.Length > EtwTraceListener.MaxEtwEventLength) - { - sb.Remove(EtwTraceListener.MaxEtwEventLength, sb.Length - EtwTraceListener.MaxEtwEventLength); - } - - finalMessage = sb.ToString(); - } - - this.TraceInternal(eventType, finalMessage); - } - - /// - public override void TraceEvent( - TraceEventCache eventCache, - string source, - TraceEventType eventType, - int id, - string message) - { - if (this.IsFiltered(eventCache, source, eventType, id)) - { - return; - } - - // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. - if (message.Length > EtwTraceListener.MaxEtwEventLength) - { - message = message.Remove(EtwTraceListener.MaxEtwEventLength, message.Length - EtwTraceListener.MaxEtwEventLength); - } - - this.TraceInternal(eventType, message); - } - - private void TraceInternal(TraceEventType eventType, string message) - { - // Discard return value in release mode - errors are not handled. -#if DEBUG - this.LastReturnCode = EtwNativeInterop.EventWriteString(this.providerHandle, (byte)eventType, 0, message); -#else - _ = EtwNativeInterop.EventWriteString(this.providerHandle, (byte)eventType, 0, message); -#endif - } - - /// - /// Error code returned by latest ETW call. - /// - internal uint LastReturnCode { get; private set; } - - /// - /// Should trace be filtered out. - /// - /// Event cache. - /// Source. - /// Event type. - /// Id. - /// True if filtered out, false if trace should go through. - private bool IsFiltered(TraceEventCache eventCache, string source, TraceEventType eventType, int id) - { - return this.Filter != null && - !this.Filter.ShouldTrace( - cache: eventCache, - source: source, - eventType: eventType, - id: id, - formatOrMessage: null, - args: null, - data1: null, - data: null); - } - - /// - /// Traces the message with information level trace. - /// - public override void Write(string message) - { - // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. - if (message.Length > EtwTraceListener.MaxEtwEventLength) - { - message = message.Remove(EtwTraceListener.MaxEtwEventLength, message.Length - EtwTraceListener.MaxEtwEventLength); - } - - this.TraceInternal(TraceEventType.Information, message); - } - - /// - /// Traces the message with information level trace. - /// - public override void WriteLine(string message) => this.Write(message); - - /// - /// Thread static cache for pre-allocated string builder. - /// - private static class StringBuilderCache - { - /// - /// This is the same value as StringBuilder.MaxChunkSize. - /// Avoid needless buffer fragmentation and memory usage remains reasonable. - /// - private const int MaxBuilderSize = 8000; - - [ThreadStatic] - private static StringBuilder cachedInstance; - - /// - /// Get cached string builder or allocate if none. - /// - /// String builder. - public static StringBuilder Instance - { - get - { - if (StringBuilderCache.cachedInstance == null) - { - StringBuilderCache.cachedInstance = new StringBuilder(StringBuilderCache.MaxBuilderSize); - } - - StringBuilderCache.cachedInstance.Clear(); - return StringBuilderCache.cachedInstance; - } - } - } - } +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Core.Trace +{ + using System; + using System.ComponentModel; + using System.Diagnostics; + using System.Text; + + /// + /// Listens to trace as emitted by TraceSource and sends them to the ETW subsystem using EventWriteString native call. + /// Only supported operation is TraceEvent. + /// + /// + internal sealed class EtwTraceListener : TraceListener + { + /// + /// Max ETW event length for EventWriteString. + /// Formula = 64KB / sizeof(char)(2) - sizeof(ETW header)(72) - unknown factors ~= 32500 char. + /// The ETW subsystem won't log anything longer than 64KB total. + /// Assuming that logging 32500 chars is preferable to 0, any message exceeding that is truncated. + /// + public const int MaxEtwEventLength = 32500; + + /// + /// Registration handle as provided by ETW RegisterEvent call. + /// + private readonly EtwNativeInterop.ProviderHandle providerHandle = new EtwNativeInterop.ProviderHandle(); + + /// + /// Initializes a new instance of the class. + /// + /// ETW provider guid. + /// Trace listener name (unrelated to ETW). + public EtwTraceListener(Guid providerGuid, string name) + : base(name) + { + this.ProviderGuid = providerGuid; + + uint retVal = EtwNativeInterop.EventRegister(providerGuid, IntPtr.Zero, IntPtr.Zero, ref this.providerHandle); + + if (retVal != 0) + { + throw new Win32Exception((int)retVal); + } + } + + /// + /// ETW provider guid. + /// + public Guid ProviderGuid { get; } + + /// + public override bool IsThreadSafe { get; } = true; + + /// + public override void Close() + { + this.Dispose(); + base.Close(); + } + + /// + /// Unregister ETW handle. + /// + /// Unused. + /// + protected override void Dispose(bool disposing) + { + if (this.providerHandle != null && !this.providerHandle.IsInvalid) + { + this.providerHandle.Dispose(); + } + + base.Dispose(disposing); + } + + /// + public override void TraceEvent( + TraceEventCache eventCache, + string source, + TraceEventType eventType, + int id, + string format, + params object[] args) + { + if (this.IsFiltered(eventCache, source, eventType, id)) + { + return; + } + + string finalMessage = format; + + if (args != null && args.Length > 0) + { + StringBuilder sb = StringBuilderCache.Instance; + sb.AppendFormat(format, args); + + // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. + if (sb.Length > EtwTraceListener.MaxEtwEventLength) + { + sb.Remove(EtwTraceListener.MaxEtwEventLength, sb.Length - EtwTraceListener.MaxEtwEventLength); + } + + finalMessage = sb.ToString(); + } + + this.TraceInternal(eventType, finalMessage); + } + + /// + public override void TraceEvent( + TraceEventCache eventCache, + string source, + TraceEventType eventType, + int id, + string message) + { + if (this.IsFiltered(eventCache, source, eventType, id)) + { + return; + } + + // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. + if (message.Length > EtwTraceListener.MaxEtwEventLength) + { + message = message.Remove(EtwTraceListener.MaxEtwEventLength, message.Length - EtwTraceListener.MaxEtwEventLength); + } + + this.TraceInternal(eventType, message); + } + + private void TraceInternal(TraceEventType eventType, string message) + { + // Discard return value in release mode - errors are not handled. +#if DEBUG + this.LastReturnCode = EtwNativeInterop.EventWriteString(this.providerHandle, (byte)eventType, 0, message); +#else + _ = EtwNativeInterop.EventWriteString(this.providerHandle, (byte)eventType, 0, message); +#endif + } + + /// + /// Error code returned by latest ETW call. + /// + internal uint LastReturnCode { get; private set; } + + /// + /// Should trace be filtered out. + /// + /// Event cache. + /// Source. + /// Event type. + /// Id. + /// True if filtered out, false if trace should go through. + private bool IsFiltered(TraceEventCache eventCache, string source, TraceEventType eventType, int id) + { + return this.Filter != null && + !this.Filter.ShouldTrace( + cache: eventCache, + source: source, + eventType: eventType, + id: id, + formatOrMessage: null, + args: null, + data1: null, + data: null); + } + + /// + /// Traces the message with information level trace. + /// + public override void Write(string message) + { + // ETW subsystem won't log anything that exceeds buffer size. Ensure data fits. + if (message.Length > EtwTraceListener.MaxEtwEventLength) + { + message = message.Remove(EtwTraceListener.MaxEtwEventLength, message.Length - EtwTraceListener.MaxEtwEventLength); + } + + this.TraceInternal(TraceEventType.Information, message); + } + + /// + /// Traces the message with information level trace. + /// + public override void WriteLine(string message) => this.Write(message); + + /// + /// Thread static cache for pre-allocated string builder. + /// + private static class StringBuilderCache + { + /// + /// This is the same value as StringBuilder.MaxChunkSize. + /// Avoid needless buffer fragmentation and memory usage remains reasonable. + /// + private const int MaxBuilderSize = 8000; + + [ThreadStatic] + private static StringBuilder cachedInstance; + + /// + /// Get cached string builder or allocate if none. + /// + /// String builder. + public static StringBuilder Instance + { + get + { + if (StringBuilderCache.cachedInstance == null) + { + StringBuilderCache.cachedInstance = new StringBuilder(StringBuilderCache.MaxBuilderSize); + } + + StringBuilderCache.cachedInstance.Clear(); + return StringBuilderCache.cachedInstance; + } + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ExceptionExtensions.cs b/Microsoft.Azure.Cosmos/src/direct/ExceptionExtensions.cs index fd43f84659..18ee7db690 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ExceptionExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ExceptionExtensions.cs @@ -1,163 +1,163 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Net; - using System.Reflection; - using System.Text; - - /// - /// Contains extensions to the base Exception class. - /// - internal static class ExceptionExtensions - { - // Iterates through the top level properties of the exception object and - // converts them to a string so output to logging can be more meaningful. - public static string ToLoggingString(this Exception exception) - { - PropertyInfo[] properties = exception.GetType().GetProperties(); - IEnumerable fields = properties.Select( - property => new - { - Name = property.Name, - Value = property.GetValue(exception, null) - }).Select( - x => string.Format( - CultureInfo.InvariantCulture, - "{0}:{1}", - x.Name, - x.Value != null ? x.Value.ToString() : string.Empty)); - - return string.Concat(exception.GetType(), " : ", string.Join(",", fields)); - } - - // System.Exception.ToString() does not inject information from Exception.Data to the exception string. - // This extension method allows us to pump additional useful information into the exception data - // and display it. - public static string ToStringWithData(this Exception exception) - { - StringBuilder sb = new StringBuilder(exception.ToString()); - - List exceptionData = new List(); - ExceptionExtensions.CaptureExceptionData(exception, exceptionData); - - if (exceptionData.Count() > 0) - { - sb.Append(Environment.NewLine); - sb.Append("AdditionalData:"); - - foreach (string data in exceptionData) - { - sb.Append(Environment.NewLine); - sb.Append(data); - } - } - - return sb.ToString(); - } - - public static string ToStringWithMessageAndData(this Exception exception) - { - StringBuilder sb = new StringBuilder(exception.Message); - - List exceptionData = new List(); - ExceptionExtensions.CaptureExceptionData(exception, exceptionData); - - if (exceptionData.Count() > 0) - { - sb.Append(Environment.NewLine); - sb.Append("AdditionalData:"); - - foreach (string data in exceptionData) - { - sb.Append(Environment.NewLine); - sb.Append(data); - } - } - - return sb.ToString(); - } - - /// - /// Returns the equivalent exception of the SubStatusCode. - /// Main motivation for this is because the real error code thrown in a stored procedure call is returned as the SubStatusCode of the BadRequestException. - /// - public static DocumentClientException GetTranslatedStoredProcedureException(DocumentClientException dce) - { - if (dce == null) - { - return dce; - } - - if (dce.StatusCode.HasValue) - { - SubStatusCodes subStatusCode = dce.GetSubStatus(); - switch (dce.StatusCode.Value) - { - case HttpStatusCode.BadRequest: - // Error code thrown in sproc gets returned as subStatusCode of BadRequestException. - HttpStatusCode responseCode = (HttpStatusCode)subStatusCode; - switch (responseCode) - { - case HttpStatusCode.BadRequest: - return new BadRequestException(dce.Message); - case HttpStatusCode.Forbidden: - return new ForbiddenException(dce.Message); - case HttpStatusCode.NotFound: - return new NotFoundException(dce.Message); - case HttpStatusCode.RequestTimeout: - return new RequestTimeoutException(dce.Message); - case HttpStatusCode.Conflict: - return new ConflictException(dce.Message); - case HttpStatusCode.PreconditionFailed: - return new PreconditionFailedException(dce.Message); - case HttpStatusCode.RequestEntityTooLarge: - return new RequestEntityTooLargeException(dce.Message); - case (HttpStatusCode)StatusCodes.RetryWith: - return new RetryWithException(dce.Message); - case (HttpStatusCode)SubStatusCodes.ConfigurationNameNotFound: - return new NotFoundException(dce, SubStatusCodes.ConfigurationNameNotFound); - case (HttpStatusCode)SubStatusCodes.ConfigurationNameAlreadyExists: - return new ConflictException(dce.Message, SubStatusCodes.ConfigurationNameAlreadyExists); - case (HttpStatusCode)SubStatusCodes.ConfigurationNameNotEmpty: - return new InternalServerErrorException(dce.Message); - case HttpStatusCode.ServiceUnavailable: - return new ServiceUnavailableException(dce.Message, SubStatusCodes.Unknown); - case HttpStatusCode.Gone: - return new GoneException(dce.Message, SubStatusCodes.Unknown); - - default: - return dce; - } - - default: - return dce; - } - } - - return dce; - } - - private static void CaptureExceptionData(Exception exception, List exceptionData) - { - if (exception.Data != null && exception.Data.Count > 0) - { - foreach (object key in exception.Data.Keys) - { - exceptionData.Add(string.Format(CultureInfo.InvariantCulture, "{0}: {1}", key.ToString(), exception.Data[key].ToString())); - } - } - - if (exception.InnerException != null) - { - ExceptionExtensions.CaptureExceptionData(exception.InnerException, exceptionData); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Net; + using System.Reflection; + using System.Text; + + /// + /// Contains extensions to the base Exception class. + /// + internal static class ExceptionExtensions + { + // Iterates through the top level properties of the exception object and + // converts them to a string so output to logging can be more meaningful. + public static string ToLoggingString(this Exception exception) + { + PropertyInfo[] properties = exception.GetType().GetProperties(); + IEnumerable fields = properties.Select( + property => new + { + Name = property.Name, + Value = property.GetValue(exception, null) + }).Select( + x => string.Format( + CultureInfo.InvariantCulture, + "{0}:{1}", + x.Name, + x.Value != null ? x.Value.ToString() : string.Empty)); + + return string.Concat(exception.GetType(), " : ", string.Join(",", fields)); + } + + // System.Exception.ToString() does not inject information from Exception.Data to the exception string. + // This extension method allows us to pump additional useful information into the exception data + // and display it. + public static string ToStringWithData(this Exception exception) + { + StringBuilder sb = new StringBuilder(exception.ToString()); + + List exceptionData = new List(); + ExceptionExtensions.CaptureExceptionData(exception, exceptionData); + + if (exceptionData.Count() > 0) + { + sb.Append(Environment.NewLine); + sb.Append("AdditionalData:"); + + foreach (string data in exceptionData) + { + sb.Append(Environment.NewLine); + sb.Append(data); + } + } + + return sb.ToString(); + } + + public static string ToStringWithMessageAndData(this Exception exception) + { + StringBuilder sb = new StringBuilder(exception.Message); + + List exceptionData = new List(); + ExceptionExtensions.CaptureExceptionData(exception, exceptionData); + + if (exceptionData.Count() > 0) + { + sb.Append(Environment.NewLine); + sb.Append("AdditionalData:"); + + foreach (string data in exceptionData) + { + sb.Append(Environment.NewLine); + sb.Append(data); + } + } + + return sb.ToString(); + } + + /// + /// Returns the equivalent exception of the SubStatusCode. + /// Main motivation for this is because the real error code thrown in a stored procedure call is returned as the SubStatusCode of the BadRequestException. + /// + public static DocumentClientException GetTranslatedStoredProcedureException(DocumentClientException dce) + { + if (dce == null) + { + return dce; + } + + if (dce.StatusCode.HasValue) + { + SubStatusCodes subStatusCode = dce.GetSubStatus(); + switch (dce.StatusCode.Value) + { + case HttpStatusCode.BadRequest: + // Error code thrown in sproc gets returned as subStatusCode of BadRequestException. + HttpStatusCode responseCode = (HttpStatusCode)subStatusCode; + switch (responseCode) + { + case HttpStatusCode.BadRequest: + return new BadRequestException(dce.Message); + case HttpStatusCode.Forbidden: + return new ForbiddenException(dce.Message); + case HttpStatusCode.NotFound: + return new NotFoundException(dce.Message); + case HttpStatusCode.RequestTimeout: + return new RequestTimeoutException(dce.Message); + case HttpStatusCode.Conflict: + return new ConflictException(dce.Message); + case HttpStatusCode.PreconditionFailed: + return new PreconditionFailedException(dce.Message); + case HttpStatusCode.RequestEntityTooLarge: + return new RequestEntityTooLargeException(dce.Message); + case (HttpStatusCode)StatusCodes.RetryWith: + return new RetryWithException(dce.Message); + case (HttpStatusCode)SubStatusCodes.ConfigurationNameNotFound: + return new NotFoundException(dce, SubStatusCodes.ConfigurationNameNotFound); + case (HttpStatusCode)SubStatusCodes.ConfigurationNameAlreadyExists: + return new ConflictException(dce.Message, SubStatusCodes.ConfigurationNameAlreadyExists); + case (HttpStatusCode)SubStatusCodes.ConfigurationNameNotEmpty: + return new InternalServerErrorException(dce.Message); + case HttpStatusCode.ServiceUnavailable: + return new ServiceUnavailableException(dce.Message, SubStatusCodes.Unknown); + case HttpStatusCode.Gone: + return new GoneException(dce.Message, SubStatusCodes.Unknown); + + default: + return dce; + } + + default: + return dce; + } + } + + return dce; + } + + private static void CaptureExceptionData(Exception exception, List exceptionData) + { + if (exception.Data != null && exception.Data.Count > 0) + { + foreach (object key in exception.Data.Keys) + { + exceptionData.Add(string.Format(CultureInfo.InvariantCulture, "{0}: {1}", key.ToString(), exception.Data[key].ToString())); + } + } + + if (exception.InnerException != null) + { + ExceptionExtensions.CaptureExceptionData(exception.InnerException, exceptionData); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ExcludedPath.cs b/Microsoft.Azure.Cosmos/src/direct/ExcludedPath.cs index 33f79e2bd6..3ecfcd2fc5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ExcludedPath.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ExcludedPath.cs @@ -1,66 +1,66 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Specifies a path within a JSON document to be excluded while indexing data for the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class ExcludedPath : JsonSerializable, ICloneable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public ExcludedPath() - { - } - - /// - /// Gets or sets the path to be excluded from indexing in the Azure Cosmos DB service. - /// - /// - /// The path to be excluded from indexing. - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get - { - return base.GetValue(Constants.Properties.Path); - } - set - { - base.SetValue(Constants.Properties.Path, value); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Path); - } - - /// - /// Creates a copy of the excluded path in the Azure Cosmos DB service. - /// - /// A clone of the excluded path. - public object Clone() - { - ExcludedPath cloned = new ExcludedPath() - { - Path = this.Path - }; - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Specifies a path within a JSON document to be excluded while indexing data for the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class ExcludedPath : JsonSerializable, ICloneable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public ExcludedPath() + { + } + + /// + /// Gets or sets the path to be excluded from indexing in the Azure Cosmos DB service. + /// + /// + /// The path to be excluded from indexing. + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get + { + return base.GetValue(Constants.Properties.Path); + } + set + { + base.SetValue(Constants.Properties.Path, value); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Path); + } + + /// + /// Creates a copy of the excluded path in the Azure Cosmos DB service. + /// + /// A clone of the excluded path. + public object Clone() + { + ExcludedPath cloned = new ExcludedPath() + { + Path = this.Path + }; + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/FanoutOperationState.cs b/Microsoft.Azure.Cosmos/src/direct/FanoutOperationState.cs index 45f5cfc5da..7656deae00 100644 --- a/Microsoft.Azure.Cosmos/src/direct/FanoutOperationState.cs +++ b/Microsoft.Azure.Cosmos/src/direct/FanoutOperationState.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the fanout operation status. - /// - internal enum FanoutOperationState - { - /// - /// Started a fanout operation. - /// - Started, - - /// - /// Completed a fanout operation. - /// - Completed - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the fanout operation status. + /// + internal enum FanoutOperationState + { + /// + /// Started a fanout operation. + /// + Started, + + /// + /// Completed a fanout operation. + /// + Completed + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/FaultInjection/IChaosInterceptor.cs b/Microsoft.Azure.Cosmos/src/direct/FaultInjection/IChaosInterceptor.cs index 7e20f26105..31a57d8428 100644 --- a/Microsoft.Azure.Cosmos/src/direct/FaultInjection/IChaosInterceptor.cs +++ b/Microsoft.Azure.Cosmos/src/direct/FaultInjection/IChaosInterceptor.cs @@ -1,56 +1,57 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.FaultInjection -{ - using Microsoft.Azure.Documents.Rntbd; - using System; - - /// - /// Interface for Chaos Interceptor - /// - internal interface IChaosInterceptor - { - /// - /// Used to inject faults on request call - /// - /// - /// - /// - public bool OnRequestCall(ChannelCallArguments args, out StoreResponse faultyResponse); - - /// - /// Used to inject faults on channel open - /// - /// - /// - /// - /// - public void OnChannelOpen(Guid activityId, Uri serverUri, DocumentServiceRequest openingRequest, Channel channel); - - /// - /// Used to update internal active channel store on channel close - /// - /// - public void OnChannelDispose(Guid connectionCorrelationId); - - /// - /// Used to inject faults before connection writes - /// - /// - public void OnBeforeConnectionWrite(ChannelCallArguments args); - - /// - /// Used to inject faults after connection writes - /// - /// - public void OnAfterConnectionWrite(ChannelCallArguments args); - - /// - /// Gets the fault injection rule id for the given activity id - /// - /// - /// the fault injection rule id - public string GetFaultInjectionRuleId(Guid activityId); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.FaultInjection +{ + using Microsoft.Azure.Documents.Rntbd; + using System; + using System.Threading.Tasks; + + /// + /// Interface for Chaos Interceptor + /// + internal interface IChaosInterceptor + { + /// + /// Used to inject faults on request call + /// + /// + /// + public Task<(bool, StoreResponse)> OnRequestCallAsync(ChannelCallArguments args); + + /// + /// Used to inject faults on channel open + /// + /// + /// + /// + /// + /// + public Task OnChannelOpenAsync(Guid activityId, Guid connectionCorrelationId, Uri serverUri, DocumentServiceRequest openingRequest, Channel channel); + + /// + /// Used to update internal active channel store on channel close + /// + /// + public void OnChannelDispose(Guid connectionCorrelationId); + + /// + /// Used to inject faults before connection writes + /// + /// + public Task OnBeforeConnectionWriteAsync(ChannelCallArguments args); + + /// + /// Used to inject faults after connection writes + /// + /// + public Task OnAfterConnectionWriteAsync(ChannelCallArguments args); + + /// + /// Gets the fault injection rule id for the given activity id + /// + /// + /// the fault injection rule id + public string GetFaultInjectionRuleId(Guid activityId); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/FeedResource.cs b/Microsoft.Azure.Cosmos/src/direct/FeedResource.cs index 52349fe7ae..750bbbc884 100644 --- a/Microsoft.Azure.Cosmos/src/direct/FeedResource.cs +++ b/Microsoft.Azure.Cosmos/src/direct/FeedResource.cs @@ -1,84 +1,84 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Collections; - using System.Collections.Generic; - using System.Collections.ObjectModel; - - internal sealed class FeedResource : Resource, IEnumerable where T : JsonSerializable, new() - { - private static string collectionName; - - private static string CollectionName - { - get - { - if (FeedResource.collectionName == null) - { - if (typeof(Document).IsAssignableFrom(typeof(T))) - { - FeedResource.collectionName = "Documents"; - } - else if (typeof(Attachment).IsAssignableFrom(typeof(T))) - { - FeedResource.collectionName = "Attachments"; - } - else - { - FeedResource.collectionName = typeof(T).Name + "s"; - } - } - return FeedResource.collectionName; - } - } - - public FeedResource() - { - - } - - public int Count - { - get - { - return this.InnerCollection.Count; - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this.InnerCollection.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this.InnerCollection.GetEnumerator(); - } - - internal Collection InnerCollection - { - get - { - Collection collection = base.GetObjectCollection(FeedResource.CollectionName, typeof(T), this.AltLink); - if (collection == null) - { - collection = new Collection(); - base.SetObjectCollection(FeedResource.CollectionName, collection); - } - return collection; - } - set - { - base.SetObjectCollection(FeedResource.CollectionName, value); - } - } - - internal override void OnSave() - { - base.SetValue(Constants.Properties.Count, this.InnerCollection.Count); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Collections; + using System.Collections.Generic; + using System.Collections.ObjectModel; + + internal sealed class FeedResource : Resource, IEnumerable where T : JsonSerializable, new() + { + private static string collectionName; + + private static string CollectionName + { + get + { + if (FeedResource.collectionName == null) + { + if (typeof(Document).IsAssignableFrom(typeof(T))) + { + FeedResource.collectionName = "Documents"; + } + else if (typeof(Attachment).IsAssignableFrom(typeof(T))) + { + FeedResource.collectionName = "Attachments"; + } + else + { + FeedResource.collectionName = typeof(T).Name + "s"; + } + } + return FeedResource.collectionName; + } + } + + public FeedResource() + { + + } + + public int Count + { + get + { + return this.InnerCollection.Count; + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.InnerCollection.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this.InnerCollection.GetEnumerator(); + } + + internal Collection InnerCollection + { + get + { + Collection collection = base.GetObjectCollection(FeedResource.CollectionName, typeof(T), this.AltLink); + if (collection == null) + { + collection = new Collection(); + base.SetObjectCollection(FeedResource.CollectionName, collection); + } + return collection; + } + set + { + base.SetObjectCollection(FeedResource.CollectionName, value); + } + } + + internal override void OnSave() + { + base.SetValue(Constants.Properties.Count, this.InnerCollection.Count); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ForbiddenException.cs b/Microsoft.Azure.Cosmos/src/direct/ForbiddenException.cs index f89bd2f936..9328a0d277 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ForbiddenException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ForbiddenException.cs @@ -1,110 +1,110 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Net.Sockets; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class ForbiddenException : DocumentClientException - { - public ForbiddenException() - : this(RMResources.Forbidden) - { - - } - - public static ForbiddenException CreateWithClientIpAddress(IPAddress clientIpAddress, bool isPrivateIpPacket) - { - ForbiddenException result; - - // ipv6 is not customer-facing. do not embed it. - if (clientIpAddress.AddressFamily == AddressFamily.InterNetworkV6) - { - result = new ForbiddenException(isPrivateIpPacket ? - RMResources.ForbiddenPrivateEndpoint : - RMResources.ForbiddenServiceEndpoint); - } - else - { - result = new ForbiddenException(string.Format( - CultureInfo.InvariantCulture, - RMResources.ForbiddenPublicIpv4, - clientIpAddress.ToString())); - - result.ClientIpAddress = clientIpAddress; - } - - return result; - } - - public ForbiddenException(string message) - : this(message, (Exception)null, null) - { - - } - - public ForbiddenException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public ForbiddenException(Exception innerException) - : this(RMResources.Forbidden, innerException, null) - { - - } - - public ForbiddenException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public ForbiddenException(string message, SubStatusCodes subStatusCode) - : base(message, HttpStatusCode.Forbidden, subStatusCode) - { - this.SetDescription(); - } - - public ForbiddenException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.Forbidden, requestUri) - { - this.SetDescription(); - } - - public ForbiddenException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.Forbidden, requestUri) - { - this.SetDescription(); - } - - public ForbiddenException(string message, Exception innerException, INameValueCollection headers) - : base(message, innerException, headers, HttpStatusCode.Forbidden) - { - this.SetDescription(); - } - - public IPAddress ClientIpAddress { get; private set; } - -#if !NETSTANDARD16 - private ForbiddenException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.Forbidden) - { - this.SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.Forbidden; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Net.Sockets; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class ForbiddenException : DocumentClientException + { + public ForbiddenException() + : this(RMResources.Forbidden) + { + + } + + public static ForbiddenException CreateWithClientIpAddress(IPAddress clientIpAddress, bool isPrivateIpPacket) + { + ForbiddenException result; + + // ipv6 is not customer-facing. do not embed it. + if (clientIpAddress.AddressFamily == AddressFamily.InterNetworkV6) + { + result = new ForbiddenException(isPrivateIpPacket ? + RMResources.ForbiddenPrivateEndpoint : + RMResources.ForbiddenServiceEndpoint); + } + else + { + result = new ForbiddenException(string.Format( + CultureInfo.InvariantCulture, + RMResources.ForbiddenPublicIpv4, + clientIpAddress.ToString())); + + result.ClientIpAddress = clientIpAddress; + } + + return result; + } + + public ForbiddenException(string message) + : this(message, (Exception)null, null) + { + + } + + public ForbiddenException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public ForbiddenException(Exception innerException) + : this(RMResources.Forbidden, innerException, null) + { + + } + + public ForbiddenException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public ForbiddenException(string message, SubStatusCodes subStatusCode) + : base(message, HttpStatusCode.Forbidden, subStatusCode) + { + this.SetDescription(); + } + + public ForbiddenException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.Forbidden, requestUri) + { + this.SetDescription(); + } + + public ForbiddenException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, HttpStatusCode.Forbidden, requestUri) + { + this.SetDescription(); + } + + public ForbiddenException(string message, Exception innerException, INameValueCollection headers) + : base(message, innerException, headers, HttpStatusCode.Forbidden) + { + this.SetDescription(); + } + + public IPAddress ClientIpAddress { get; private set; } + +#if !NETSTANDARD16 + private ForbiddenException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.Forbidden) + { + this.SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.Forbidden; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GeoLinkTypes.cs b/Microsoft.Azure.Cosmos/src/direct/GeoLinkTypes.cs index 1fce82c8b0..ebef0da870 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GeoLinkTypes.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GeoLinkTypes.cs @@ -1,18 +1,18 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - /// - /// This enum specifies the types of geo links across regions, - /// with strong links having the lowest latency and best reliability, - /// and weak links having the highest latency and worst reliability. - /// - internal enum GeoLinkTypes - { - Strong, // < 100ms RTT; 5000 mile radius - Medium, // < 200ms RTT; 10000 mile radius - Weak // > 200ms RTT; > 10000 mile radius - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// This enum specifies the types of geo links across regions, + /// with strong links having the lowest latency and best reliability, + /// and weak links having the highest latency and worst reliability. + /// + internal enum GeoLinkTypes + { + Strong, // < 100ms RTT; 5000 mile radius + Medium, // < 200ms RTT; 10000 mile radius + Weak // > 200ms RTT; > 10000 mile radius + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GeospatialConfig.cs b/Microsoft.Azure.Cosmos/src/direct/GeospatialConfig.cs index 0628c5a20e..ce6273b593 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GeospatialConfig.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GeospatialConfig.cs @@ -1,89 +1,89 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents geospatial configuration for a collection in the Azure Cosmos DB service - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class GeospatialConfig : JsonSerializable, ICloneable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - /// - /// Geospatial type is set to Geography by default. - /// - public GeospatialConfig() - { - this.GeospatialType = GeospatialType.Geography; - } - - public GeospatialConfig(GeospatialType geospatialType) - { - this.GeospatialType = geospatialType; - } - - /// - /// Gets or sets the geospatial type (geography or geometry) in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.GeospatialType)] - [JsonConverter(typeof(StringEnumConverter))] - public GeospatialType GeospatialType - { - get - { - GeospatialType result = GeospatialType.Geography; - string strValue = base.GetValue(Constants.Properties.GeospatialType); - if (!string.IsNullOrEmpty(strValue)) - { - result = (GeospatialType)Enum.Parse(typeof(GeospatialType), strValue, true); - } - return result; - } - - set - { - base.SetValue(Constants.Properties.GeospatialType, value.ToString()); - } - } - - public object Clone() - { - GeospatialConfig cloned = new GeospatialConfig(); - cloned.GeospatialType = this.GeospatialType; - - return cloned; - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.GeospatialType); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents geospatial configuration for a collection in the Azure Cosmos DB service + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class GeospatialConfig : JsonSerializable, ICloneable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// + /// Geospatial type is set to Geography by default. + /// + public GeospatialConfig() + { + this.GeospatialType = GeospatialType.Geography; + } + + public GeospatialConfig(GeospatialType geospatialType) + { + this.GeospatialType = geospatialType; + } + + /// + /// Gets or sets the geospatial type (geography or geometry) in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.GeospatialType)] + [JsonConverter(typeof(StringEnumConverter))] + public GeospatialType GeospatialType + { + get + { + GeospatialType result = GeospatialType.Geography; + string strValue = base.GetValue(Constants.Properties.GeospatialType); + if (!string.IsNullOrEmpty(strValue)) + { + result = (GeospatialType)Enum.Parse(typeof(GeospatialType), strValue, true); + } + return result; + } + + set + { + base.SetValue(Constants.Properties.GeospatialType, value.ToString()); + } + } + + public object Clone() + { + GeospatialConfig cloned = new GeospatialConfig(); + cloned.GeospatialType = this.GeospatialType; + + return cloned; + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.GeospatialType); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GeospatialType.cs b/Microsoft.Azure.Cosmos/src/direct/GeospatialType.cs index dbd4188b81..14650e6aec 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GeospatialType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GeospatialType.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported geospatial types in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum GeospatialType - { - /// - /// Represents data in round-earth coordinate system. - /// - Geography, - - /// - /// Represents data in Eucledian(flat) coordinate system. - /// - Geometry - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported geospatial types in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum GeospatialType + { + /// + /// Represents data in round-earth coordinate system. + /// + Geography, + + /// + /// Represents data in Eucledian(flat) coordinate system. + /// + Geometry + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs index 968e10fcaa..91d2e6392a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs @@ -1,465 +1,465 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.Net; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Routing; - - /// - /// Policy to perform backoff retry on GoneException, InvalidPartitionException, RetryWithException, PartitionKeyRangeIsSplittingException, and PartitionKeyRangeGoneException, including their associated - /// - internal sealed class GoneAndRetryWithRequestRetryPolicy : - IRequestRetryPolicy where TResponse : IRetriableResponse - { - struct ErrorOrResponse - { - private Exception exception; - private int statusCode; - - public ErrorOrResponse(Exception ex, TResponse response) - { - exception = ex; - this.statusCode = response != null ? (int)response.StatusCode : 0; - } - - public ErrorOrResponse(Exception ex) - { - exception = ex; - statusCode = 0; - } - - private string ExceptionToString() - { - // If no error code is set, use WithMessageAndData - return statusCode != 0 ? exception?.ToStringWithData() : exception?.ToStringWithMessageAndData(); - } - - public override string ToString() => exception != null ? this.ExceptionToString() : statusCode.ToString(CultureInfo.InvariantCulture); - } - - private static readonly ThreadLocal Random = new ThreadLocal(() => new Random()); - - private const int defaultWaitTimeInMilliSeconds = 30000; - private const int minExecutionTimeInMilliSeconds = 5000; - private const int initialBackoffMilliSeconds = 1000; - private const int backoffMultiplier = 2; - private const int defaultMaximumBackoffTimeInMilliSeconds = 15000; - - // RetryWith default behavior - private const int defaultInitialBackoffTimeForRetryWithInMilliseconds = 10; - private const int defaultMaximumBackoffTimeForRetryWithInMilliseconds = 1000; - private const int defaultRandomSaltForRetryWithInMilliseconds = 5; - - private const int minFailedReplicaCountToConsiderConnectivityIssue = 3; - - private readonly int maximumBackoffTimeInMilliSeconds; - private readonly int maximumBackoffTimeInMillisecondsForRetryWith; - private readonly int initialBackoffTimeInMilliSeconds; - private readonly int initialBackoffTimeInMillisecondsForRetryWith; - - private readonly int? randomSaltForRetryWithMilliseconds; - - private Stopwatch durationTimer = new Stopwatch(); - private TimeSpan minBackoffForRegionReroute; - private int attemptCount = 1; - private int attemptCountInvalidPartition = 1; - private int regionRerouteAttemptCount = 0; - - // Don't penalise first retry with delay. - private int? currentBackoffMilliseconds; - private int? currentBackoffMillisecondsForRetryWith; - - private RetryWithException lastRetryWithException = null; - private Exception previousException = null; // Used in case of timeouts during retries - - private readonly int waitTimeInMilliseconds; - private readonly int waitTimeInMillisecondsForRetryWith; - private readonly bool detectConnectivityIssues; - private readonly bool disableRetryWithPolicy; - - public GoneAndRetryWithRequestRetryPolicy( - bool disableRetryWithPolicy, - int? waitTimeInSecondsOverride = null, - TimeSpan minBackoffForRegionReroute = default(TimeSpan), - bool detectConnectivityIssues = false, - RetryWithConfiguration retryWithConfiguration = null) - { - if (waitTimeInSecondsOverride.HasValue) - { - this.waitTimeInMilliseconds = waitTimeInSecondsOverride.Value * 1000; - } - else - { - this.waitTimeInMilliseconds = GoneAndRetryWithRequestRetryPolicy.defaultWaitTimeInMilliSeconds; - } - - this.disableRetryWithPolicy = disableRetryWithPolicy; - this.detectConnectivityIssues = detectConnectivityIssues; - this.minBackoffForRegionReroute = minBackoffForRegionReroute; - - // Initial Context - this.ExecuteContext.RemainingTimeInMsOnClientRequest = TimeSpan.FromMilliseconds(this.waitTimeInMilliseconds); - this.ExecuteContext.TimeoutForInBackoffRetryPolicy = TimeSpan.Zero; - - this.initialBackoffTimeInMilliSeconds = - GoneAndRetryWithRequestRetryPolicy.initialBackoffMilliSeconds; - this.initialBackoffTimeInMillisecondsForRetryWith = - retryWithConfiguration?.InitialRetryIntervalMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultInitialBackoffTimeForRetryWithInMilliseconds; - this.maximumBackoffTimeInMilliSeconds = - GoneAndRetryWithRequestRetryPolicy.defaultMaximumBackoffTimeInMilliSeconds; - this.maximumBackoffTimeInMillisecondsForRetryWith = - retryWithConfiguration?.MaximumRetryIntervalMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultMaximumBackoffTimeForRetryWithInMilliseconds; - this.waitTimeInMillisecondsForRetryWith = - retryWithConfiguration?.TotalWaitTimeMilliseconds ?? this.waitTimeInMilliseconds; - - this.randomSaltForRetryWithMilliseconds = retryWithConfiguration?.RandomSaltMaxValueMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultRandomSaltForRetryWithInMilliseconds; - if (this.randomSaltForRetryWithMilliseconds != null && this.randomSaltForRetryWithMilliseconds < 1) - { - throw new ArgumentException($"{nameof(retryWithConfiguration.RandomSaltMaxValueMilliseconds)} must be a number greater than 1 or null"); - } - - this.durationTimer.Start(); - } - - public void OnBeforeSendRequest(DocumentServiceRequest request) {} - - public GoneAndRetryRequestRetryPolicyContext ExecuteContext { get; } = new GoneAndRetryRequestRetryPolicyContext(); - - public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult) - { - Exception exceptionToThrow = null; - TimeSpan backoffTime = TimeSpan.FromSeconds(0); - TimeSpan timeout = TimeSpan.FromSeconds(0); - bool forceRefreshAddressCache = false; - - request.RequestContext.IsRetry = true; - - bool isRetryWith = false; - if (!GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception) && - !(exception is RetryWithException) && - !(GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception) && (request.ServiceIdentity == null || request.ServiceIdentity.IsMasterService)) && - !(GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception) && (request.PartitionKeyRangeIdentity == null || request.PartitionKeyRangeIdentity.CollectionRid == null)) && - !(GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception) && request.ServiceIdentity == null)) - { - // Have caller propagate original exception / response. - this.durationTimer.Stop(); - shouldRetryResult = ShouldRetryResult.NoRetry(); - return true; - } - else if (exception is RetryWithException) - { - // If the RetryWithPolicy is disabled then - // return the no retry to let it propagate the RetryWith exception. - if (disableRetryWithPolicy) - { - DefaultTrace.TraceWarning( - "The GoneAndRetryWithRequestRetryPolicy is configured with disableRetryWithPolicy to true. Retries on 449(RetryWith) exceptions has been disabled. This is by design to allow users to handle the exception: {0}", - new ErrorOrResponse(exception)); - this.durationTimer.Stop(); - shouldRetryResult = ShouldRetryResult.NoRetry(); - return true; - } - - isRetryWith = true; - this.lastRetryWithException = exception as RetryWithException; - } - - int remainingMilliseconds; - if (isRetryWith) - { - remainingMilliseconds = this.waitTimeInMillisecondsForRetryWith - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); - } - else - { - remainingMilliseconds = this.waitTimeInMilliseconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); - } - - remainingMilliseconds = remainingMilliseconds > 0 ? remainingMilliseconds : 0; - int currentAttemptCount = this.attemptCount; - // Don't penalise first retry with delay. - if (this.attemptCount++ > 1) - { - if (remainingMilliseconds <= 0) - { - if (GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception) || - GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception) || - GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception) || - GoneAndRetryWithRequestRetryPolicy.IsPartitionKeyRangeGone(response, exception) || - GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception)) - { - string message = string.Format("Received {0} after backoff/retry", exception?.GetType().Name ?? response?.StatusCode.ToString()); - - if (this.lastRetryWithException != null) - { - DefaultTrace.TraceError( - "{0} including at least one RetryWithException. " + - "Will fail the request with RetryWithException. Exception: {1}. RetryWithException: {2}", - message, - new ErrorOrResponse(exception, response), - new ErrorOrResponse(this.lastRetryWithException)); - exceptionToThrow = this.lastRetryWithException; - } - else - { - DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, - new ErrorOrResponse(exception, response)); - - SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - if (exceptionSubStatus == SubStatusCodes.TimeoutGenerated410) - { - // If it was a gone exception becuase of a timeout (thrown when the lower layers themselves are retrying like in the StoreReader), take the substatus of the previous exception - if (this.previousException != null) - { - exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(this.previousException); - } - } - - if (this.detectConnectivityIssues && - request.RequestContext.ClientRequestStatistics != null && - request.RequestContext.ClientRequestStatistics.IsCpuHigh.GetValueOrDefault(false)) - { - - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientCpuOverload, - request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - SubStatusCodes.Client_CPUOverload); - } - else if (this.detectConnectivityIssues && - request.RequestContext.ClientRequestStatistics != null && - request.RequestContext.ClientRequestStatistics.IsCpuThreadStarvation.GetValueOrDefault(false)) - { - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientCpuThreadStarvation, - request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - SubStatusCodes.Client_ThreadStarvation); - } - else if (this.detectConnectivityIssues && - request.RequestContext.ClientRequestStatistics != null && - request.RequestContext.ClientRequestStatistics.FailedReplicas.Count >= GoneAndRetryWithRequestRetryPolicy.minFailedReplicaCountToConsiderConnectivityIssue) - { - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientUnavailable, - request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - exception, - exceptionSubStatus); - } - else - { - exceptionToThrow = ServiceUnavailableException.Create(exceptionSubStatus, innerException: exception); - } - } - } - else - { - DefaultTrace.TraceError("Received retry with exception after backoff/retry. Will fail the request. {0}", new ErrorOrResponse(exception, response)); - exceptionToThrow = exception; - } - - this.durationTimer.Stop(); - - shouldRetryResult = ShouldRetryResult.NoRetry(exceptionToThrow); - return true; - } - - this.currentBackoffMillisecondsForRetryWith = - this.currentBackoffMillisecondsForRetryWith ?? this.initialBackoffTimeInMillisecondsForRetryWith; - - this.currentBackoffMilliseconds = - this.currentBackoffMilliseconds ?? this.initialBackoffTimeInMilliSeconds; - - if (isRetryWith) - { - int retryWithMilliseconds = this.currentBackoffMillisecondsForRetryWith.Value; - if (this.randomSaltForRetryWithMilliseconds != null) - { - retryWithMilliseconds += - GoneAndRetryWithRequestRetryPolicy.Random.Value.Next( - 1, - this.randomSaltForRetryWithMilliseconds.Value); - } - - backoffTime = TimeSpan.FromMilliseconds(Math.Min(Math.Min(retryWithMilliseconds, remainingMilliseconds), this.maximumBackoffTimeInMillisecondsForRetryWith)); - - // Cap this.currentBackoffMillisecondsForRetryWith to maximum to avoid overflow - this.currentBackoffMillisecondsForRetryWith = Math.Min(this.currentBackoffMillisecondsForRetryWith.Value * GoneAndRetryWithRequestRetryPolicy.backoffMultiplier, this.maximumBackoffTimeInMillisecondsForRetryWith); - } - else - { - backoffTime = TimeSpan.FromMilliseconds(Math.Min(Math.Min(this.currentBackoffMilliseconds.Value, remainingMilliseconds), this.maximumBackoffTimeInMilliSeconds)); - - // Cap this.currentBackoffMilliseconds to maximum to avoid overflow - this.currentBackoffMilliseconds = Math.Min(this.currentBackoffMilliseconds.Value * GoneAndRetryWithRequestRetryPolicy.backoffMultiplier, this.maximumBackoffTimeInMilliSeconds); - } - } - - // Calculate the remaining time based after accounting for the backoff that we will perform - double timeoutInMilliSeconds = remainingMilliseconds - backoffTime.TotalMilliseconds; - timeout = timeoutInMilliSeconds > 0 ? TimeSpan.FromMilliseconds(timeoutInMilliSeconds) : - TimeSpan.FromMilliseconds(GoneAndRetryWithRequestRetryPolicy.minExecutionTimeInMilliSeconds); - - if (backoffTime >= this.minBackoffForRegionReroute) - { - this.regionRerouteAttemptCount++; - } - - if (GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception)) - { - forceRefreshAddressCache = true; // indicate we are in retry. - } - else if (GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception)) - { - GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); - request.ForceCollectionRoutingMapRefresh = true; - request.ForceMasterRefresh = true; - forceRefreshAddressCache = false; - } - else if (GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception)) - { - GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); - request.RequestContext.GlobalCommittedSelectedLSN = -1; - - if (this.attemptCountInvalidPartition++ > 2) - { - // for third InvalidPartitionException, stop retrying. - SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", - new ErrorOrResponse(exception, response)); - shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); - return true; - } - - if (request != null) - { - request.ForceNameCacheRefresh = true; - } - else - { - DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", new ErrorOrResponse(exception, response)); - shouldRetryResult = ShouldRetryResult.NoRetry(new InternalServerErrorException(exception)); - return true; - } - - // prevent the caller from refreshing fabric caches. - forceRefreshAddressCache = false; - } - else if (GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception)) - { - GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); - request.ForcePartitionKeyRangeRefresh = true; - forceRefreshAddressCache = false; - } - else - { - // For RetryWithException, prevent the caller - // from refreshing any caches. - forceRefreshAddressCache = false; - } - - DefaultTrace.TraceWarning( - "GoneAndRetryWithRequestRetryPolicy Received exception, will retry, attempt: {0}, regionRerouteAttempt: {1}, backoffTime: {2}, Timeout: {3}, Exception: {4}", - this.attemptCount, - this.regionRerouteAttemptCount, - backoffTime, - timeout, - new ErrorOrResponse(exception, response)); - - shouldRetryResult = ShouldRetryResult.RetryAfter(backoffTime); - this.previousException = exception; - - // Update context - this.ExecuteContext.ForceRefresh = forceRefreshAddressCache; - this.ExecuteContext.IsInRetry = true; - this.ExecuteContext.RemainingTimeInMsOnClientRequest = timeout; - this.ExecuteContext.ClientRetryCount = currentAttemptCount; - this.ExecuteContext.RegionRerouteAttemptCount = this.regionRerouteAttemptCount; - this.ExecuteContext.TimeoutForInBackoffRetryPolicy = backoffTime; - return true; - } - - public Task ShouldRetryAsync(DocumentServiceRequest request, TResponse response, Exception exception, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - - private static bool IsBaseGone(TResponse response, Exception exception) - { - return exception is GoneException - || (response?.StatusCode == HttpStatusCode.Gone && - (response?.SubStatusCode == SubStatusCodes.Unknown || (response != null && response.SubStatusCode.IsSDKGeneratedSubStatus()))); - } - - private static bool IsPartitionIsMigrating(TResponse response, Exception exception) - { - return exception is PartitionIsMigratingException - || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.CompletingPartitionMigration); - } - - private static bool IsInvalidPartition(TResponse response, Exception exception) - { - return exception is InvalidPartitionException - || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.NameCacheIsStale); - } - - private static bool IsPartitionKeySplitting(TResponse response, Exception exception) - { - return exception is PartitionKeyRangeIsSplittingException - || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.CompletingSplit); - } - - private static bool IsPartitionKeyRangeGone(TResponse response, Exception exception) - { - return exception is PartitionKeyRangeGoneException - || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.PartitionKeyRangeGone); - } - - private static void ClearRequestContext(DocumentServiceRequest request) - { - request.RequestContext.TargetIdentity = null; - request.RequestContext.ResolvedPartitionKeyRange = null; - request.RequestContext.QuorumSelectedLSN = -1; - request.RequestContext.UpdateQuorumSelectedStoreResponse(null); - } - } - - internal sealed class RetryWithConfiguration - { - public int? InitialRetryIntervalMilliseconds { get; set; } - - public int? MaximumRetryIntervalMilliseconds { get; set; } - - public int? RandomSaltMaxValueMilliseconds { get; set; } - - public int? TotalWaitTimeMilliseconds { get; set; } - } - - internal sealed class GoneAndRetryRequestRetryPolicyContext - { - public bool ForceRefresh { get; set; } - - public bool IsInRetry { get; set; } - - public TimeSpan RemainingTimeInMsOnClientRequest { get; set; } - - public int ClientRetryCount { get; set; } - - public int RegionRerouteAttemptCount { get; set; } - - public TimeSpan TimeoutForInBackoffRetryPolicy { get; set; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Routing; + + /// + /// Policy to perform backoff retry on GoneException, InvalidPartitionException, RetryWithException, PartitionKeyRangeIsSplittingException, and PartitionKeyRangeGoneException, including their associated + /// + internal sealed class GoneAndRetryWithRequestRetryPolicy : + IRequestRetryPolicy where TResponse : IRetriableResponse + { + struct ErrorOrResponse + { + private Exception exception; + private int statusCode; + + public ErrorOrResponse(Exception ex, TResponse response) + { + exception = ex; + this.statusCode = response != null ? (int)response.StatusCode : 0; + } + + public ErrorOrResponse(Exception ex) + { + exception = ex; + statusCode = 0; + } + + private string ExceptionToString() + { + // If no error code is set, use WithMessageAndData + return statusCode != 0 ? exception?.ToStringWithData() : exception?.ToStringWithMessageAndData(); + } + + public override string ToString() => exception != null ? this.ExceptionToString() : statusCode.ToString(CultureInfo.InvariantCulture); + } + + private static readonly ThreadLocal Random = new ThreadLocal(() => new Random()); + + private const int defaultWaitTimeInMilliSeconds = 30000; + private const int minExecutionTimeInMilliSeconds = 5000; + private const int initialBackoffMilliSeconds = 1000; + private const int backoffMultiplier = 2; + private const int defaultMaximumBackoffTimeInMilliSeconds = 15000; + + // RetryWith default behavior + private const int defaultInitialBackoffTimeForRetryWithInMilliseconds = 10; + private const int defaultMaximumBackoffTimeForRetryWithInMilliseconds = 1000; + private const int defaultRandomSaltForRetryWithInMilliseconds = 5; + + private const int minFailedReplicaCountToConsiderConnectivityIssue = 3; + + private readonly int maximumBackoffTimeInMilliSeconds; + private readonly int maximumBackoffTimeInMillisecondsForRetryWith; + private readonly int initialBackoffTimeInMilliSeconds; + private readonly int initialBackoffTimeInMillisecondsForRetryWith; + + private readonly int? randomSaltForRetryWithMilliseconds; + + private Stopwatch durationTimer = new Stopwatch(); + private TimeSpan minBackoffForRegionReroute; + private int attemptCount = 1; + private int attemptCountInvalidPartition = 1; + private int regionRerouteAttemptCount = 0; + + // Don't penalise first retry with delay. + private int? currentBackoffMilliseconds; + private int? currentBackoffMillisecondsForRetryWith; + + private RetryWithException lastRetryWithException = null; + private Exception previousException = null; // Used in case of timeouts during retries + + private readonly int waitTimeInMilliseconds; + private readonly int waitTimeInMillisecondsForRetryWith; + private readonly bool detectConnectivityIssues; + private readonly bool disableRetryWithPolicy; + + public GoneAndRetryWithRequestRetryPolicy( + bool disableRetryWithPolicy, + int? waitTimeInSecondsOverride = null, + TimeSpan minBackoffForRegionReroute = default(TimeSpan), + bool detectConnectivityIssues = false, + RetryWithConfiguration retryWithConfiguration = null) + { + if (waitTimeInSecondsOverride.HasValue) + { + this.waitTimeInMilliseconds = waitTimeInSecondsOverride.Value * 1000; + } + else + { + this.waitTimeInMilliseconds = GoneAndRetryWithRequestRetryPolicy.defaultWaitTimeInMilliSeconds; + } + + this.disableRetryWithPolicy = disableRetryWithPolicy; + this.detectConnectivityIssues = detectConnectivityIssues; + this.minBackoffForRegionReroute = minBackoffForRegionReroute; + + // Initial Context + this.ExecuteContext.RemainingTimeInMsOnClientRequest = TimeSpan.FromMilliseconds(this.waitTimeInMilliseconds); + this.ExecuteContext.TimeoutForInBackoffRetryPolicy = TimeSpan.Zero; + + this.initialBackoffTimeInMilliSeconds = + GoneAndRetryWithRequestRetryPolicy.initialBackoffMilliSeconds; + this.initialBackoffTimeInMillisecondsForRetryWith = + retryWithConfiguration?.InitialRetryIntervalMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultInitialBackoffTimeForRetryWithInMilliseconds; + this.maximumBackoffTimeInMilliSeconds = + GoneAndRetryWithRequestRetryPolicy.defaultMaximumBackoffTimeInMilliSeconds; + this.maximumBackoffTimeInMillisecondsForRetryWith = + retryWithConfiguration?.MaximumRetryIntervalMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultMaximumBackoffTimeForRetryWithInMilliseconds; + this.waitTimeInMillisecondsForRetryWith = + retryWithConfiguration?.TotalWaitTimeMilliseconds ?? this.waitTimeInMilliseconds; + + this.randomSaltForRetryWithMilliseconds = retryWithConfiguration?.RandomSaltMaxValueMilliseconds ?? GoneAndRetryWithRequestRetryPolicy.defaultRandomSaltForRetryWithInMilliseconds; + if (this.randomSaltForRetryWithMilliseconds != null && this.randomSaltForRetryWithMilliseconds < 1) + { + throw new ArgumentException($"{nameof(retryWithConfiguration.RandomSaltMaxValueMilliseconds)} must be a number greater than 1 or null"); + } + + this.durationTimer.Start(); + } + + public void OnBeforeSendRequest(DocumentServiceRequest request) {} + + public GoneAndRetryRequestRetryPolicyContext ExecuteContext { get; } = new GoneAndRetryRequestRetryPolicyContext(); + + public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult) + { + Exception exceptionToThrow = null; + TimeSpan backoffTime = TimeSpan.FromSeconds(0); + TimeSpan timeout = TimeSpan.FromSeconds(0); + bool forceRefreshAddressCache = false; + + request.RequestContext.IsRetry = true; + + bool isRetryWith = false; + if (!GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception) && + !(exception is RetryWithException) && + !(GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception) && (request.ServiceIdentity == null || request.ServiceIdentity.IsMasterService)) && + !(GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception) && (request.PartitionKeyRangeIdentity == null || request.PartitionKeyRangeIdentity.CollectionRid == null)) && + !(GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception) && request.ServiceIdentity == null)) + { + // Have caller propagate original exception / response. + this.durationTimer.Stop(); + shouldRetryResult = ShouldRetryResult.NoRetry(); + return true; + } + else if (exception is RetryWithException) + { + // If the RetryWithPolicy is disabled then + // return the no retry to let it propagate the RetryWith exception. + if (disableRetryWithPolicy) + { + DefaultTrace.TraceWarning( + "The GoneAndRetryWithRequestRetryPolicy is configured with disableRetryWithPolicy to true. Retries on 449(RetryWith) exceptions has been disabled. This is by design to allow users to handle the exception: {0}", + new ErrorOrResponse(exception)); + this.durationTimer.Stop(); + shouldRetryResult = ShouldRetryResult.NoRetry(); + return true; + } + + isRetryWith = true; + this.lastRetryWithException = exception as RetryWithException; + } + + int remainingMilliseconds; + if (isRetryWith) + { + remainingMilliseconds = this.waitTimeInMillisecondsForRetryWith - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); + } + else + { + remainingMilliseconds = this.waitTimeInMilliseconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); + } + + remainingMilliseconds = remainingMilliseconds > 0 ? remainingMilliseconds : 0; + int currentAttemptCount = this.attemptCount; + // Don't penalise first retry with delay. + if (this.attemptCount++ > 1) + { + if (remainingMilliseconds <= 0) + { + if (GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception) || + GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception) || + GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception) || + GoneAndRetryWithRequestRetryPolicy.IsPartitionKeyRangeGone(response, exception) || + GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception)) + { + string message = string.Format("Received {0} after backoff/retry", exception?.GetType().Name ?? response?.StatusCode.ToString()); + + if (this.lastRetryWithException != null) + { + DefaultTrace.TraceError( + "{0} including at least one RetryWithException. " + + "Will fail the request with RetryWithException. Exception: {1}. RetryWithException: {2}", + message, + new ErrorOrResponse(exception, response), + new ErrorOrResponse(this.lastRetryWithException)); + exceptionToThrow = this.lastRetryWithException; + } + else + { + DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, + new ErrorOrResponse(exception, response)); + + SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + if (exceptionSubStatus == SubStatusCodes.TimeoutGenerated410) + { + // If it was a gone exception becuase of a timeout (thrown when the lower layers themselves are retrying like in the StoreReader), take the substatus of the previous exception + if (this.previousException != null) + { + exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(this.previousException); + } + } + + if (this.detectConnectivityIssues && + request.RequestContext.ClientRequestStatistics != null && + request.RequestContext.ClientRequestStatistics.IsCpuHigh.GetValueOrDefault(false)) + { + + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientCpuOverload, + request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + SubStatusCodes.Client_CPUOverload); + } + else if (this.detectConnectivityIssues && + request.RequestContext.ClientRequestStatistics != null && + request.RequestContext.ClientRequestStatistics.IsCpuThreadStarvation.GetValueOrDefault(false)) + { + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientCpuThreadStarvation, + request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + SubStatusCodes.Client_ThreadStarvation); + } + else if (this.detectConnectivityIssues && + request.RequestContext.ClientRequestStatistics != null && + request.RequestContext.ClientRequestStatistics.FailedReplicas.Count >= GoneAndRetryWithRequestRetryPolicy.minFailedReplicaCountToConsiderConnectivityIssue) + { + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientUnavailable, + request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + exception, + exceptionSubStatus); + } + else + { + exceptionToThrow = ServiceUnavailableException.Create(exceptionSubStatus, innerException: exception); + } + } + } + else + { + DefaultTrace.TraceError("Received retry with exception after backoff/retry. Will fail the request. {0}", new ErrorOrResponse(exception, response)); + exceptionToThrow = exception; + } + + this.durationTimer.Stop(); + + shouldRetryResult = ShouldRetryResult.NoRetry(exceptionToThrow); + return true; + } + + this.currentBackoffMillisecondsForRetryWith = + this.currentBackoffMillisecondsForRetryWith ?? this.initialBackoffTimeInMillisecondsForRetryWith; + + this.currentBackoffMilliseconds = + this.currentBackoffMilliseconds ?? this.initialBackoffTimeInMilliSeconds; + + if (isRetryWith) + { + int retryWithMilliseconds = this.currentBackoffMillisecondsForRetryWith.Value; + if (this.randomSaltForRetryWithMilliseconds != null) + { + retryWithMilliseconds += + GoneAndRetryWithRequestRetryPolicy.Random.Value.Next( + 1, + this.randomSaltForRetryWithMilliseconds.Value); + } + + backoffTime = TimeSpan.FromMilliseconds(Math.Min(Math.Min(retryWithMilliseconds, remainingMilliseconds), this.maximumBackoffTimeInMillisecondsForRetryWith)); + + // Cap this.currentBackoffMillisecondsForRetryWith to maximum to avoid overflow + this.currentBackoffMillisecondsForRetryWith = Math.Min(this.currentBackoffMillisecondsForRetryWith.Value * GoneAndRetryWithRequestRetryPolicy.backoffMultiplier, this.maximumBackoffTimeInMillisecondsForRetryWith); + } + else + { + backoffTime = TimeSpan.FromMilliseconds(Math.Min(Math.Min(this.currentBackoffMilliseconds.Value, remainingMilliseconds), this.maximumBackoffTimeInMilliSeconds)); + + // Cap this.currentBackoffMilliseconds to maximum to avoid overflow + this.currentBackoffMilliseconds = Math.Min(this.currentBackoffMilliseconds.Value * GoneAndRetryWithRequestRetryPolicy.backoffMultiplier, this.maximumBackoffTimeInMilliSeconds); + } + } + + // Calculate the remaining time based after accounting for the backoff that we will perform + double timeoutInMilliSeconds = remainingMilliseconds - backoffTime.TotalMilliseconds; + timeout = timeoutInMilliSeconds > 0 ? TimeSpan.FromMilliseconds(timeoutInMilliSeconds) : + TimeSpan.FromMilliseconds(GoneAndRetryWithRequestRetryPolicy.minExecutionTimeInMilliSeconds); + + if (backoffTime >= this.minBackoffForRegionReroute) + { + this.regionRerouteAttemptCount++; + } + + if (GoneAndRetryWithRequestRetryPolicy.IsBaseGone(response, exception)) + { + forceRefreshAddressCache = true; // indicate we are in retry. + } + else if (GoneAndRetryWithRequestRetryPolicy.IsPartitionIsMigrating(response, exception)) + { + GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); + request.ForceCollectionRoutingMapRefresh = true; + request.ForceMasterRefresh = true; + forceRefreshAddressCache = false; + } + else if (GoneAndRetryWithRequestRetryPolicy.IsInvalidPartition(response, exception)) + { + GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); + request.RequestContext.GlobalCommittedSelectedLSN = -1; + + if (this.attemptCountInvalidPartition++ > 2) + { + // for third InvalidPartitionException, stop retrying. + SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", + new ErrorOrResponse(exception, response)); + shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); + return true; + } + + if (request != null) + { + request.ForceNameCacheRefresh = true; + } + else + { + DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", new ErrorOrResponse(exception, response)); + shouldRetryResult = ShouldRetryResult.NoRetry(new InternalServerErrorException(exception)); + return true; + } + + // prevent the caller from refreshing fabric caches. + forceRefreshAddressCache = false; + } + else if (GoneAndRetryWithRequestRetryPolicy.IsPartitionKeySplitting(response, exception)) + { + GoneAndRetryWithRequestRetryPolicy.ClearRequestContext(request); + request.ForcePartitionKeyRangeRefresh = true; + forceRefreshAddressCache = false; + } + else + { + // For RetryWithException, prevent the caller + // from refreshing any caches. + forceRefreshAddressCache = false; + } + + DefaultTrace.TraceWarning( + "GoneAndRetryWithRequestRetryPolicy Received exception, will retry, attempt: {0}, regionRerouteAttempt: {1}, backoffTime: {2}, Timeout: {3}, Exception: {4}", + this.attemptCount, + this.regionRerouteAttemptCount, + backoffTime, + timeout, + new ErrorOrResponse(exception, response)); + + shouldRetryResult = ShouldRetryResult.RetryAfter(backoffTime); + this.previousException = exception; + + // Update context + this.ExecuteContext.ForceRefresh = forceRefreshAddressCache; + this.ExecuteContext.IsInRetry = true; + this.ExecuteContext.RemainingTimeInMsOnClientRequest = timeout; + this.ExecuteContext.ClientRetryCount = currentAttemptCount; + this.ExecuteContext.RegionRerouteAttemptCount = this.regionRerouteAttemptCount; + this.ExecuteContext.TimeoutForInBackoffRetryPolicy = backoffTime; + return true; + } + + public Task ShouldRetryAsync(DocumentServiceRequest request, TResponse response, Exception exception, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + private static bool IsBaseGone(TResponse response, Exception exception) + { + return exception is GoneException + || (response?.StatusCode == HttpStatusCode.Gone && + (response?.SubStatusCode == SubStatusCodes.Unknown || (response != null && response.SubStatusCode.IsSDKGeneratedSubStatus()))); + } + + private static bool IsPartitionIsMigrating(TResponse response, Exception exception) + { + return exception is PartitionIsMigratingException + || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.CompletingPartitionMigration); + } + + private static bool IsInvalidPartition(TResponse response, Exception exception) + { + return exception is InvalidPartitionException + || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.NameCacheIsStale); + } + + private static bool IsPartitionKeySplitting(TResponse response, Exception exception) + { + return exception is PartitionKeyRangeIsSplittingException + || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.CompletingSplit); + } + + private static bool IsPartitionKeyRangeGone(TResponse response, Exception exception) + { + return exception is PartitionKeyRangeGoneException + || (response?.StatusCode == HttpStatusCode.Gone && response?.SubStatusCode == SubStatusCodes.PartitionKeyRangeGone); + } + + private static void ClearRequestContext(DocumentServiceRequest request) + { + request.RequestContext.TargetIdentity = null; + request.RequestContext.ResolvedPartitionKeyRange = null; + request.RequestContext.QuorumSelectedLSN = -1; + request.RequestContext.UpdateQuorumSelectedStoreResponse(null); + } + } + + internal sealed class RetryWithConfiguration + { + public int? InitialRetryIntervalMilliseconds { get; set; } + + public int? MaximumRetryIntervalMilliseconds { get; set; } + + public int? RandomSaltMaxValueMilliseconds { get; set; } + + public int? TotalWaitTimeMilliseconds { get; set; } + } + + internal sealed class GoneAndRetryRequestRetryPolicyContext + { + public bool ForceRefresh { get; set; } + + public bool IsInRetry { get; set; } + + public TimeSpan RemainingTimeInMsOnClientRequest { get; set; } + + public int ClientRetryCount { get; set; } + + public int RegionRerouteAttemptCount { get; set; } + + public TimeSpan TimeoutForInBackoffRetryPolicy { get; set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs index f85a722255..6bf57477b2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs @@ -1,331 +1,331 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Routing; - - /// - /// Policy to perform backoff retry on GoneException, InvalidPartitionException and RetryWithException - /// TArg1: Perform force refresh. - /// TArg2: TimeSpan for completing the work in the callback - /// - internal sealed class GoneAndRetryWithRetryPolicy : - IRetryPolicy, - IRetryPolicy>, - IRetryPolicy> - { - private const int defaultWaitTimeInSeconds = 30; - private const int minExecutionTimeInSeconds = 5; - private const int initialBackoffSeconds = 1; - private const int backoffMultiplier = 2; - private const int maximumBackoffTimeInSeconds = 15; - - private const int minFailedReplicaCountToConsiderConnectivityIssue = 3; - - private Stopwatch durationTimer = new Stopwatch(); - private int attemptCount = 1; - private int attemptCountInvalidPartition = 1; - private int regionRerouteAttemptCount = 0; - - private TimeSpan minBackoffForRegionReroute; - - private RetryWithException lastRetryWithException = null; - - private readonly int waitTimeInSeconds; - - private readonly bool detectConnectivityIssues; - - // Don't penalise first retry with delay. - private int currentBackoffSeconds = GoneAndRetryWithRetryPolicy.initialBackoffSeconds; - - private DocumentServiceRequest request; - - public GoneAndRetryWithRetryPolicy( - DocumentServiceRequest request = null, - int? waitTimeInSecondsOverride = null, - TimeSpan minBackoffForRegionReroute = default(TimeSpan), - bool detectConnectivityIssues = false) - { - if (waitTimeInSecondsOverride.HasValue) - { - this.waitTimeInSeconds = waitTimeInSecondsOverride.Value; - } - else - { - this.waitTimeInSeconds = GoneAndRetryWithRetryPolicy.defaultWaitTimeInSeconds; - } - - this.request = request; - this.detectConnectivityIssues = detectConnectivityIssues; - this.minBackoffForRegionReroute = minBackoffForRegionReroute; - - durationTimer.Start(); - } - - bool IRetryPolicy.InitialArgumentValue - { - get - { - return false; - } - } - - Tuple IRetryPolicy>.InitialArgumentValue - { - get - { - return Tuple.Create(false, false, TimeSpan.FromSeconds(this.waitTimeInSeconds)); - } - } - - Tuple IRetryPolicy>.InitialArgumentValue - { - get - { - return Tuple.Create(false, false, TimeSpan.FromSeconds(this.waitTimeInSeconds), 0, 0, TimeSpan.Zero); - } - } - - /// - /// ShouldRetry method - /// - /// Exception thrown by callback - /// - /// Is the retry helper should retry - async Task> IRetryPolicy.ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) - { - ShouldRetryResult> result = - await ((IRetryPolicy>)this).ShouldRetryAsync(exception, cancellationToken); - - if(result.ShouldRetry) - { - return ShouldRetryResult.RetryAfter(result.BackoffTime, result.PolicyArg1.Item1); - } - else - { - return ShouldRetryResult.NoRetry(result.ExceptionToThrow); - } - } - - async Task>> IRetryPolicy>.ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) - { - ShouldRetryResult> result = - await ((IRetryPolicy>)this).ShouldRetryAsync(exception, cancellationToken); - - if (result.ShouldRetry) - { - return ShouldRetryResult>.RetryAfter(result.BackoffTime, Tuple.Create(result.PolicyArg1.Item1, result.PolicyArg1.Item2, result.PolicyArg1.Item3)); - } - else - { - return ShouldRetryResult>.NoRetry(result.ExceptionToThrow); - } - } - - /// - /// ShouldRetry method - /// - /// Exception thrown by callback - /// - /// Is the retry helper should retry - [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Roslyn Baseline 12/12/2022 16:40")] - Task>> IRetryPolicy>.ShouldRetryAsync( - Exception exception, - CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - Exception exceptionToThrow = null; - TimeSpan backoffTime = TimeSpan.FromSeconds(0); - TimeSpan timeout = TimeSpan.FromSeconds(0); - bool forceRefreshAddressCache = false; - - if (!(exception is GoneException) && - !(exception is RetryWithException) && - !(exception is PartitionIsMigratingException && (request.ServiceIdentity == null || request.ServiceIdentity.IsMasterService)) && - !(exception is InvalidPartitionException && (this.request.PartitionKeyRangeIdentity == null || this.request.PartitionKeyRangeIdentity.CollectionRid == null)) && - !(exception is PartitionKeyRangeIsSplittingException && this.request.ServiceIdentity == null)) - { - // Have caller propagate original exception. - this.durationTimer.Stop(); - return Task.FromResult(ShouldRetryResult>.NoRetry()); - } - else if (exception is RetryWithException) - { - this.lastRetryWithException = exception as RetryWithException; - } - - int remainingSeconds = this.waitTimeInSeconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalSeconds); - remainingSeconds = remainingSeconds > 0 ? remainingSeconds : 0; - - int currentAttemptCount = this.attemptCount; - // Don't penalise first retry with delay. - if (this.attemptCount++ > 1) - { - if (remainingSeconds <= 0) - { - if (exception is GoneException || - exception is PartitionIsMigratingException || - exception is InvalidPartitionException || - exception is PartitionKeyRangeGoneException || - exception is PartitionKeyRangeIsSplittingException) - { - string message = string.Format("Received {0} after backoff/retry", exception.GetType().Name); - - if (this.lastRetryWithException != null) - { - DefaultTrace.TraceError( - "{0} including at least one RetryWithException. " + - "Will fail the request with RetryWithException. Exception: {1}. RetryWithException: {2}", - message, exception.ToStringWithData(), this.lastRetryWithException.ToStringWithData()); - exceptionToThrow = this.lastRetryWithException; - } - else - { - DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, exception.ToStringWithData()); - SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - - - if (this.detectConnectivityIssues && - this.request.RequestContext.ClientRequestStatistics != null && - this.request.RequestContext.ClientRequestStatistics.IsCpuHigh.GetValueOrDefault(false)) - { - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientCpuOverload, - this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - SubStatusCodes.Client_CPUOverload); - } - if (this.detectConnectivityIssues && - this.request.RequestContext.ClientRequestStatistics != null && - this.request.RequestContext.ClientRequestStatistics.IsCpuThreadStarvation.GetValueOrDefault(false)) - { - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientCpuThreadStarvation, - this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - SubStatusCodes.Client_ThreadStarvation); - } - else if (this.detectConnectivityIssues && - this.request.RequestContext.ClientRequestStatistics != null && - this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count >= GoneAndRetryWithRetryPolicy.minFailedReplicaCountToConsiderConnectivityIssue) - { - - exceptionToThrow = new ServiceUnavailableException( - string.Format( - RMResources.ClientUnavailable, - this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, - this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? - 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), - exception, - exceptionSubStatus); - } - else - { - exceptionToThrow = ServiceUnavailableException.Create(exceptionSubStatus, innerException: exception); - } - } - } - else - { - DefaultTrace.TraceError("Received retrywith exception after backoff/retry. Will fail the request. {0}", exception.ToStringWithData()); - } - - this.durationTimer.Stop(); - - return Task.FromResult(ShouldRetryResult>.NoRetry(exceptionToThrow)); - } - - backoffTime = TimeSpan.FromSeconds(Math.Min(Math.Min(this.currentBackoffSeconds, remainingSeconds), GoneAndRetryWithRetryPolicy.maximumBackoffTimeInSeconds)); - this.currentBackoffSeconds *= GoneAndRetryWithRetryPolicy.backoffMultiplier; - } - - // Calculate the remaining time based after accounting for the backoff that we will perfom - double timeoutInSeconds = remainingSeconds - backoffTime.TotalSeconds; - timeout = timeoutInSeconds > 0 ? TimeSpan.FromSeconds(timeoutInSeconds) : - TimeSpan.FromSeconds(GoneAndRetryWithRetryPolicy.minExecutionTimeInSeconds); - - if (backoffTime >= this.minBackoffForRegionReroute) - { - this.regionRerouteAttemptCount++; - } - - if (exception is GoneException) - { - forceRefreshAddressCache = true; // indicate we are in retry. - } - else if (exception is PartitionIsMigratingException) - { - this.ClearRequestContext(); - this.request.ForceCollectionRoutingMapRefresh = true; - this.request.ForceMasterRefresh = true; - forceRefreshAddressCache = false; - } - else if (exception is InvalidPartitionException) - { - this.ClearRequestContext(); - this.request.RequestContext.GlobalCommittedSelectedLSN = -1; - - if (this.attemptCountInvalidPartition++ > 2) - { - // for second InvalidPartitionException, stop retrying. - SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", exception.ToStringWithData()); - return Task.FromResult(ShouldRetryResult>.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception))); - } - - if (this.request != null) - { - this.request.ForceNameCacheRefresh = true; - } - else - { - DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", exception.ToStringWithData()); - return Task.FromResult(ShouldRetryResult>.NoRetry(new InternalServerErrorException(exception))); - } - // prevent the caller from refreshing fabric caches. - forceRefreshAddressCache = false; - } - else if (exception is PartitionKeyRangeIsSplittingException) - { - this.ClearRequestContext(); - this.request.ForcePartitionKeyRangeRefresh = true; - forceRefreshAddressCache = false; - } - else - { - // For RetryWithException, prevent the caller - // from refreshing any caches. - forceRefreshAddressCache = false; - } - - DefaultTrace.TraceWarning( - "GoneAndRetryWithRetryPolicy Received exception, will retry, attempt: {0}, regionRerouteAttempt: {1}, backoffTime: {2}, Timeout: {3}, Exception: {4}", - this.attemptCount, - this.regionRerouteAttemptCount, - backoffTime, - timeout, - exception.ToStringWithData()); - return Task.FromResult(ShouldRetryResult>.RetryAfter( - backoffTime, - Tuple.Create(forceRefreshAddressCache, true, timeout, currentAttemptCount, this.regionRerouteAttemptCount, backoffTime))); - } - - private void ClearRequestContext() - { - this.request.RequestContext.TargetIdentity = null; - this.request.RequestContext.ResolvedPartitionKeyRange = null; - this.request.RequestContext.QuorumSelectedLSN = -1; - this.request.RequestContext.UpdateQuorumSelectedStoreResponse(null); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Routing; + + /// + /// Policy to perform backoff retry on GoneException, InvalidPartitionException and RetryWithException + /// TArg1: Perform force refresh. + /// TArg2: TimeSpan for completing the work in the callback + /// + internal sealed class GoneAndRetryWithRetryPolicy : + IRetryPolicy, + IRetryPolicy>, + IRetryPolicy> + { + private const int defaultWaitTimeInSeconds = 30; + private const int minExecutionTimeInSeconds = 5; + private const int initialBackoffSeconds = 1; + private const int backoffMultiplier = 2; + private const int maximumBackoffTimeInSeconds = 15; + + private const int minFailedReplicaCountToConsiderConnectivityIssue = 3; + + private Stopwatch durationTimer = new Stopwatch(); + private int attemptCount = 1; + private int attemptCountInvalidPartition = 1; + private int regionRerouteAttemptCount = 0; + + private TimeSpan minBackoffForRegionReroute; + + private RetryWithException lastRetryWithException = null; + + private readonly int waitTimeInSeconds; + + private readonly bool detectConnectivityIssues; + + // Don't penalise first retry with delay. + private int currentBackoffSeconds = GoneAndRetryWithRetryPolicy.initialBackoffSeconds; + + private DocumentServiceRequest request; + + public GoneAndRetryWithRetryPolicy( + DocumentServiceRequest request = null, + int? waitTimeInSecondsOverride = null, + TimeSpan minBackoffForRegionReroute = default(TimeSpan), + bool detectConnectivityIssues = false) + { + if (waitTimeInSecondsOverride.HasValue) + { + this.waitTimeInSeconds = waitTimeInSecondsOverride.Value; + } + else + { + this.waitTimeInSeconds = GoneAndRetryWithRetryPolicy.defaultWaitTimeInSeconds; + } + + this.request = request; + this.detectConnectivityIssues = detectConnectivityIssues; + this.minBackoffForRegionReroute = minBackoffForRegionReroute; + + durationTimer.Start(); + } + + bool IRetryPolicy.InitialArgumentValue + { + get + { + return false; + } + } + + Tuple IRetryPolicy>.InitialArgumentValue + { + get + { + return Tuple.Create(false, false, TimeSpan.FromSeconds(this.waitTimeInSeconds)); + } + } + + Tuple IRetryPolicy>.InitialArgumentValue + { + get + { + return Tuple.Create(false, false, TimeSpan.FromSeconds(this.waitTimeInSeconds), 0, 0, TimeSpan.Zero); + } + } + + /// + /// ShouldRetry method + /// + /// Exception thrown by callback + /// + /// Is the retry helper should retry + async Task> IRetryPolicy.ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) + { + ShouldRetryResult> result = + await ((IRetryPolicy>)this).ShouldRetryAsync(exception, cancellationToken); + + if(result.ShouldRetry) + { + return ShouldRetryResult.RetryAfter(result.BackoffTime, result.PolicyArg1.Item1); + } + else + { + return ShouldRetryResult.NoRetry(result.ExceptionToThrow); + } + } + + async Task>> IRetryPolicy>.ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) + { + ShouldRetryResult> result = + await ((IRetryPolicy>)this).ShouldRetryAsync(exception, cancellationToken); + + if (result.ShouldRetry) + { + return ShouldRetryResult>.RetryAfter(result.BackoffTime, Tuple.Create(result.PolicyArg1.Item1, result.PolicyArg1.Item2, result.PolicyArg1.Item3)); + } + else + { + return ShouldRetryResult>.NoRetry(result.ExceptionToThrow); + } + } + + /// + /// ShouldRetry method + /// + /// Exception thrown by callback + /// + /// Is the retry helper should retry + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Roslyn Baseline 12/12/2022 16:40")] + Task>> IRetryPolicy>.ShouldRetryAsync( + Exception exception, + CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + Exception exceptionToThrow = null; + TimeSpan backoffTime = TimeSpan.FromSeconds(0); + TimeSpan timeout = TimeSpan.FromSeconds(0); + bool forceRefreshAddressCache = false; + + if (!(exception is GoneException) && + !(exception is RetryWithException) && + !(exception is PartitionIsMigratingException && (request.ServiceIdentity == null || request.ServiceIdentity.IsMasterService)) && + !(exception is InvalidPartitionException && (this.request.PartitionKeyRangeIdentity == null || this.request.PartitionKeyRangeIdentity.CollectionRid == null)) && + !(exception is PartitionKeyRangeIsSplittingException && this.request.ServiceIdentity == null)) + { + // Have caller propagate original exception. + this.durationTimer.Stop(); + return Task.FromResult(ShouldRetryResult>.NoRetry()); + } + else if (exception is RetryWithException) + { + this.lastRetryWithException = exception as RetryWithException; + } + + int remainingSeconds = this.waitTimeInSeconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalSeconds); + remainingSeconds = remainingSeconds > 0 ? remainingSeconds : 0; + + int currentAttemptCount = this.attemptCount; + // Don't penalise first retry with delay. + if (this.attemptCount++ > 1) + { + if (remainingSeconds <= 0) + { + if (exception is GoneException || + exception is PartitionIsMigratingException || + exception is InvalidPartitionException || + exception is PartitionKeyRangeGoneException || + exception is PartitionKeyRangeIsSplittingException) + { + string message = string.Format("Received {0} after backoff/retry", exception.GetType().Name); + + if (this.lastRetryWithException != null) + { + DefaultTrace.TraceError( + "{0} including at least one RetryWithException. " + + "Will fail the request with RetryWithException. Exception: {1}. RetryWithException: {2}", + message, exception.ToStringWithData(), this.lastRetryWithException.ToStringWithData()); + exceptionToThrow = this.lastRetryWithException; + } + else + { + DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, exception.ToStringWithData()); + SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + + + if (this.detectConnectivityIssues && + this.request.RequestContext.ClientRequestStatistics != null && + this.request.RequestContext.ClientRequestStatistics.IsCpuHigh.GetValueOrDefault(false)) + { + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientCpuOverload, + this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + SubStatusCodes.Client_CPUOverload); + } + if (this.detectConnectivityIssues && + this.request.RequestContext.ClientRequestStatistics != null && + this.request.RequestContext.ClientRequestStatistics.IsCpuThreadStarvation.GetValueOrDefault(false)) + { + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientCpuThreadStarvation, + this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + SubStatusCodes.Client_ThreadStarvation); + } + else if (this.detectConnectivityIssues && + this.request.RequestContext.ClientRequestStatistics != null && + this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count >= GoneAndRetryWithRetryPolicy.minFailedReplicaCountToConsiderConnectivityIssue) + { + + exceptionToThrow = new ServiceUnavailableException( + string.Format( + RMResources.ClientUnavailable, + this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count, + this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count == 0 ? + 1 : this.request.RequestContext.ClientRequestStatistics.RegionsContacted.Count), + exception, + exceptionSubStatus); + } + else + { + exceptionToThrow = ServiceUnavailableException.Create(exceptionSubStatus, innerException: exception); + } + } + } + else + { + DefaultTrace.TraceError("Received retrywith exception after backoff/retry. Will fail the request. {0}", exception.ToStringWithData()); + } + + this.durationTimer.Stop(); + + return Task.FromResult(ShouldRetryResult>.NoRetry(exceptionToThrow)); + } + + backoffTime = TimeSpan.FromSeconds(Math.Min(Math.Min(this.currentBackoffSeconds, remainingSeconds), GoneAndRetryWithRetryPolicy.maximumBackoffTimeInSeconds)); + this.currentBackoffSeconds *= GoneAndRetryWithRetryPolicy.backoffMultiplier; + } + + // Calculate the remaining time based after accounting for the backoff that we will perfom + double timeoutInSeconds = remainingSeconds - backoffTime.TotalSeconds; + timeout = timeoutInSeconds > 0 ? TimeSpan.FromSeconds(timeoutInSeconds) : + TimeSpan.FromSeconds(GoneAndRetryWithRetryPolicy.minExecutionTimeInSeconds); + + if (backoffTime >= this.minBackoffForRegionReroute) + { + this.regionRerouteAttemptCount++; + } + + if (exception is GoneException) + { + forceRefreshAddressCache = true; // indicate we are in retry. + } + else if (exception is PartitionIsMigratingException) + { + this.ClearRequestContext(); + this.request.ForceCollectionRoutingMapRefresh = true; + this.request.ForceMasterRefresh = true; + forceRefreshAddressCache = false; + } + else if (exception is InvalidPartitionException) + { + this.ClearRequestContext(); + this.request.RequestContext.GlobalCommittedSelectedLSN = -1; + + if (this.attemptCountInvalidPartition++ > 2) + { + // for second InvalidPartitionException, stop retrying. + SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", exception.ToStringWithData()); + return Task.FromResult(ShouldRetryResult>.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception))); + } + + if (this.request != null) + { + this.request.ForceNameCacheRefresh = true; + } + else + { + DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", exception.ToStringWithData()); + return Task.FromResult(ShouldRetryResult>.NoRetry(new InternalServerErrorException(exception))); + } + // prevent the caller from refreshing fabric caches. + forceRefreshAddressCache = false; + } + else if (exception is PartitionKeyRangeIsSplittingException) + { + this.ClearRequestContext(); + this.request.ForcePartitionKeyRangeRefresh = true; + forceRefreshAddressCache = false; + } + else + { + // For RetryWithException, prevent the caller + // from refreshing any caches. + forceRefreshAddressCache = false; + } + + DefaultTrace.TraceWarning( + "GoneAndRetryWithRetryPolicy Received exception, will retry, attempt: {0}, regionRerouteAttempt: {1}, backoffTime: {2}, Timeout: {3}, Exception: {4}", + this.attemptCount, + this.regionRerouteAttemptCount, + backoffTime, + timeout, + exception.ToStringWithData()); + return Task.FromResult(ShouldRetryResult>.RetryAfter( + backoffTime, + Tuple.Create(forceRefreshAddressCache, true, timeout, currentAttemptCount, this.regionRerouteAttemptCount, backoffTime))); + } + + private void ClearRequestContext() + { + this.request.RequestContext.TargetIdentity = null; + this.request.RequestContext.ResolvedPartitionKeyRange = null; + this.request.RequestContext.QuorumSelectedLSN = -1; + this.request.RequestContext.UpdateQuorumSelectedStoreResponse(null); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneException.cs b/Microsoft.Azure.Cosmos/src/direct/GoneException.cs index b678cfaf13..d64f103813 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneException.cs @@ -1,106 +1,106 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class GoneException : DocumentClientException - { - public GoneException() - : this(RMResources.Gone, SubStatusCodes.Unknown) - { - - } - - public GoneException(string message) - : this(message, (Exception)null, (HttpResponseHeaders)null, SubStatusCodes.Unknown) - { - } - - public GoneException(string message, SubStatusCodes subStatusCode, Uri requestUri = null) - : this(message, (Exception)null, (HttpResponseHeaders)null, subStatusCode, requestUri) - { - } - - public GoneException(string message, - HttpResponseHeaders headers, - SubStatusCodes? subStatusCode, - Uri requestUri = null) - : this(message, null, headers, subStatusCode, requestUri) - { - } - - public GoneException(string message, - Exception innerException, - SubStatusCodes subStatusCode, - Uri requestUri = null, - string localIpAddress = null) - : this(message, innerException, (HttpResponseHeaders)null, subStatusCode, requestUri) - { - this.LocalIp = localIpAddress; - } - - public GoneException(Exception innerException, SubStatusCodes subStatusCode) - : this(RMResources.Gone, innerException, (HttpResponseHeaders)null, subStatusCode) - { - } - - public GoneException(string message, INameValueCollection headers, SubStatusCodes? substatusCode, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.Gone, substatusCode, requestUri) - { - SetDescription(); - } - - public GoneException(string message, - Exception innerException, - HttpResponseHeaders headers, - SubStatusCodes? subStatusCode, - Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.Gone, requestUri, subStatusCode) - { - SetDescription(); - } - - internal string LocalIp { get; set; } - -#if !NETSTANDARD16 - private GoneException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.Gone) - { - } -#endif - - /// - /// - /// Summary: - /// Gets a message that describes the current exception. - /// - /// - public override string Message - { - get - { - if (!string.IsNullOrEmpty(this.LocalIp)) - { - return string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessageAddIpAddress, - base.Message, - this.LocalIp); - } - return base.Message; - } - } - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.Gone; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class GoneException : DocumentClientException + { + public GoneException() + : this(RMResources.Gone, SubStatusCodes.Unknown) + { + + } + + public GoneException(string message) + : this(message, (Exception)null, (HttpResponseHeaders)null, SubStatusCodes.Unknown) + { + } + + public GoneException(string message, SubStatusCodes subStatusCode, Uri requestUri = null) + : this(message, (Exception)null, (HttpResponseHeaders)null, subStatusCode, requestUri) + { + } + + public GoneException(string message, + HttpResponseHeaders headers, + SubStatusCodes? subStatusCode, + Uri requestUri = null) + : this(message, null, headers, subStatusCode, requestUri) + { + } + + public GoneException(string message, + Exception innerException, + SubStatusCodes subStatusCode, + Uri requestUri = null, + string localIpAddress = null) + : this(message, innerException, (HttpResponseHeaders)null, subStatusCode, requestUri) + { + this.LocalIp = localIpAddress; + } + + public GoneException(Exception innerException, SubStatusCodes subStatusCode) + : this(RMResources.Gone, innerException, (HttpResponseHeaders)null, subStatusCode) + { + } + + public GoneException(string message, INameValueCollection headers, SubStatusCodes? substatusCode, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.Gone, substatusCode, requestUri) + { + SetDescription(); + } + + public GoneException(string message, + Exception innerException, + HttpResponseHeaders headers, + SubStatusCodes? subStatusCode, + Uri requestUri = null) + : base(message, innerException, headers, HttpStatusCode.Gone, requestUri, subStatusCode) + { + SetDescription(); + } + + internal string LocalIp { get; set; } + +#if !NETSTANDARD16 + private GoneException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.Gone) + { + } +#endif + + /// + /// + /// Summary: + /// Gets a message that describes the current exception. + /// + /// + public override string Message + { + get + { + if (!string.IsNullOrEmpty(this.LocalIp)) + { + return string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessageAddIpAddress, + base.Message, + this.LocalIp); + } + return base.Message; + } + } + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.Gone; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneOnlyRequestRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/GoneOnlyRequestRetryPolicy.cs index b2ad6115d5..cc28e1979e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneOnlyRequestRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneOnlyRequestRetryPolicy.cs @@ -1,115 +1,115 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Net; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal class GoneOnlyRequestRetryPolicy : - IRequestRetryPolicy where TResponse : IRetriableResponse - { - private const int backoffMultiplier = 2; - private const int initialBackoffTimeInSeconds = 1; - - private Stopwatch durationTimer = new Stopwatch(); - - private readonly TimeSpan retryTimeout; - private int currentBackoffTimeInSeconds; - private bool isInRetry; - - public GoneOnlyRequestRetryPolicy( - TimeSpan retryTimeout) - { - this.retryTimeout = retryTimeout; - this.currentBackoffTimeInSeconds = initialBackoffTimeInSeconds; - this.isInRetry = false; - - // Initialize context - this.ExecuteContext.RemainingTimeInMsOnClientRequest = retryTimeout; - durationTimer.Start(); - } - - public GoneOnlyRequestRetryPolicyContext ExecuteContext { get; } = new GoneOnlyRequestRetryPolicyContext(); - - public void OnBeforeSendRequest(DocumentServiceRequest request) {} - - public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult) - { - if (response?.StatusCode != HttpStatusCode.Gone - && !(exception is GoneException)) - { - shouldRetryResult = ShouldRetryResult.NoRetry(); - return true; - } - - SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - - TimeSpan elapsed = this.durationTimer.Elapsed; - if (elapsed >= this.retryTimeout) - { - DefaultTrace.TraceInformation("GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}", this.retryTimeout, elapsed); - - this.durationTimer.Stop(); - shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); - return true; - } - - TimeSpan remainingTime = this.retryTimeout - elapsed; - - TimeSpan backoffTime = TimeSpan.Zero; - if (this.isInRetry) - { - backoffTime = TimeSpan.FromSeconds(this.currentBackoffTimeInSeconds); - this.currentBackoffTimeInSeconds *= 2; - - if (backoffTime > remainingTime) - { - DefaultTrace.TraceInformation("GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}, backoffTime {2}", this.retryTimeout, elapsed, backoffTime); - - this.durationTimer.Stop(); - shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); - return true; - } - } - else - { - this.isInRetry = true; - } - - DefaultTrace.TraceInformation( - "GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}, backoffTime {2}, remainingTime {3}", - this.retryTimeout, - elapsed, - backoffTime, - remainingTime); - shouldRetryResult = ShouldRetryResult.RetryAfter(backoffTime); - - // Update context - this.ExecuteContext.IsInRetry = this.isInRetry; - this.ExecuteContext.ForceRefresh = true; - this.ExecuteContext.RemainingTimeInMsOnClientRequest = remainingTime; - - return true; - } - - public Task ShouldRetryAsync(DocumentServiceRequest request, TResponse response, Exception exception, CancellationToken cancellationToken) - { - throw new NotImplementedException(); - } - } - - internal sealed class GoneOnlyRequestRetryPolicyContext - { - public bool ForceRefresh { get; set; } - - public bool IsInRetry { get; set; } - - public TimeSpan RemainingTimeInMsOnClientRequest { get; set; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal class GoneOnlyRequestRetryPolicy : + IRequestRetryPolicy where TResponse : IRetriableResponse + { + private const int backoffMultiplier = 2; + private const int initialBackoffTimeInSeconds = 1; + + private Stopwatch durationTimer = new Stopwatch(); + + private readonly TimeSpan retryTimeout; + private int currentBackoffTimeInSeconds; + private bool isInRetry; + + public GoneOnlyRequestRetryPolicy( + TimeSpan retryTimeout) + { + this.retryTimeout = retryTimeout; + this.currentBackoffTimeInSeconds = initialBackoffTimeInSeconds; + this.isInRetry = false; + + // Initialize context + this.ExecuteContext.RemainingTimeInMsOnClientRequest = retryTimeout; + durationTimer.Start(); + } + + public GoneOnlyRequestRetryPolicyContext ExecuteContext { get; } = new GoneOnlyRequestRetryPolicyContext(); + + public void OnBeforeSendRequest(DocumentServiceRequest request) {} + + public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult) + { + if (response?.StatusCode != HttpStatusCode.Gone + && !(exception is GoneException)) + { + shouldRetryResult = ShouldRetryResult.NoRetry(); + return true; + } + + SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + + TimeSpan elapsed = this.durationTimer.Elapsed; + if (elapsed >= this.retryTimeout) + { + DefaultTrace.TraceInformation("GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}", this.retryTimeout, elapsed); + + this.durationTimer.Stop(); + shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); + return true; + } + + TimeSpan remainingTime = this.retryTimeout - elapsed; + + TimeSpan backoffTime = TimeSpan.Zero; + if (this.isInRetry) + { + backoffTime = TimeSpan.FromSeconds(this.currentBackoffTimeInSeconds); + this.currentBackoffTimeInSeconds *= 2; + + if (backoffTime > remainingTime) + { + DefaultTrace.TraceInformation("GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}, backoffTime {2}", this.retryTimeout, elapsed, backoffTime); + + this.durationTimer.Stop(); + shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); + return true; + } + } + else + { + this.isInRetry = true; + } + + DefaultTrace.TraceInformation( + "GoneOnlyRequestRetryPolicy - timeout {0}, elapsed {1}, backoffTime {2}, remainingTime {3}", + this.retryTimeout, + elapsed, + backoffTime, + remainingTime); + shouldRetryResult = ShouldRetryResult.RetryAfter(backoffTime); + + // Update context + this.ExecuteContext.IsInRetry = this.isInRetry; + this.ExecuteContext.ForceRefresh = true; + this.ExecuteContext.RemainingTimeInMsOnClientRequest = remainingTime; + + return true; + } + + public Task ShouldRetryAsync(DocumentServiceRequest request, TResponse response, Exception exception, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + } + + internal sealed class GoneOnlyRequestRetryPolicyContext + { + public bool ForceRefresh { get; set; } + + public bool IsInRetry { get; set; } + + public TimeSpan RemainingTimeInMsOnClientRequest { get; set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/HashIndex.cs b/Microsoft.Azure.Cosmos/src/direct/HashIndex.cs index 84f222565c..9fbd36e9ab 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HashIndex.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HashIndex.cs @@ -1,142 +1,142 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents details of the hash index setting in an Azure Cosmos DB service. - /// - /// - /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop = 5. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class HashIndex : Index, ICloneable - { - internal HashIndex() - : base(IndexKind.Hash) - { - } - - /// - /// Initializes a new instance of the class with specified DataType for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// - /// - /// Here is an example to instantiate HashIndex class passing in the DataType: - /// - /// - /// - /// - public HashIndex(DataType dataType) - : this() - { - this.DataType = dataType; - } - - /// - /// Initializes a new instance of the class with specified DataType and precision for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// Specifies the precision to be used for the data type associated with this index. - /// - /// - /// Here is an example to instantiate HashIndex class passing in the DataType and precision: - /// - /// - /// - /// - public HashIndex(DataType dataType, short precision) - : this(dataType) - { - this.Precision = precision; - } - - /// - /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. - /// - /// - /// The data type for which this index should be applied. - /// - /// Refer to Customizing the indexing policy of a collection for valid ranges of values. - [JsonProperty(PropertyName = Constants.Properties.DataType)] - [JsonConverter(typeof(StringEnumConverter))] - public DataType DataType - { - get - { - DataType result = Documents.DataType.Number; - string strValue = base.GetValue(Constants.Properties.DataType); - if (!string.IsNullOrEmpty(strValue)) - { - result = (DataType)Enum.Parse(typeof(DataType), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.DataType, value.ToString()); - } - } - - /// - /// Gets or sets the precision for this particular index in the Azure Cosmos DB service. - /// - /// - /// The precision for this particular index. Returns null, if not set. - /// - /// Refer to Customizing the indexing policy of a collection for valid ranges of values. - [JsonProperty(PropertyName = Constants.Properties.Precision, - NullValueHandling = NullValueHandling.Ignore)] - public short? Precision - { - get - { - short? result = null; - string strValue = base.GetValue(Constants.Properties.Precision); - if (!string.IsNullOrEmpty(strValue)) - { - result = Convert.ToInt16(strValue, CultureInfo.InvariantCulture); - } - return result; - } - set - { - base.SetValue(Constants.Properties.Precision, value); - } - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.DataType); - short? precision = this.Precision; - } - - /// - /// Creates a copy of the hash index for the Azure Cosmos DB service. - /// - /// A clone of the hash index. - public object Clone() - { - return new HashIndex(this.DataType) - { - Precision = this.Precision - }; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents details of the hash index setting in an Azure Cosmos DB service. + /// + /// + /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop = 5. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class HashIndex : Index, ICloneable + { + internal HashIndex() + : base(IndexKind.Hash) + { + } + + /// + /// Initializes a new instance of the class with specified DataType for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// + /// + /// Here is an example to instantiate HashIndex class passing in the DataType: + /// + /// + /// + /// + public HashIndex(DataType dataType) + : this() + { + this.DataType = dataType; + } + + /// + /// Initializes a new instance of the class with specified DataType and precision for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// Specifies the precision to be used for the data type associated with this index. + /// + /// + /// Here is an example to instantiate HashIndex class passing in the DataType and precision: + /// + /// + /// + /// + public HashIndex(DataType dataType, short precision) + : this(dataType) + { + this.Precision = precision; + } + + /// + /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. + /// + /// + /// The data type for which this index should be applied. + /// + /// Refer to Customizing the indexing policy of a collection for valid ranges of values. + [JsonProperty(PropertyName = Constants.Properties.DataType)] + [JsonConverter(typeof(StringEnumConverter))] + public DataType DataType + { + get + { + DataType result = Documents.DataType.Number; + string strValue = base.GetValue(Constants.Properties.DataType); + if (!string.IsNullOrEmpty(strValue)) + { + result = (DataType)Enum.Parse(typeof(DataType), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.DataType, value.ToString()); + } + } + + /// + /// Gets or sets the precision for this particular index in the Azure Cosmos DB service. + /// + /// + /// The precision for this particular index. Returns null, if not set. + /// + /// Refer to Customizing the indexing policy of a collection for valid ranges of values. + [JsonProperty(PropertyName = Constants.Properties.Precision, + NullValueHandling = NullValueHandling.Ignore)] + public short? Precision + { + get + { + short? result = null; + string strValue = base.GetValue(Constants.Properties.Precision); + if (!string.IsNullOrEmpty(strValue)) + { + result = Convert.ToInt16(strValue, CultureInfo.InvariantCulture); + } + return result; + } + set + { + base.SetValue(Constants.Properties.Precision, value); + } + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.DataType); + short? precision = this.Precision; + } + + /// + /// Creates a copy of the hash index for the Azure Cosmos DB service. + /// + /// A clone of the hash index. + public object Clone() + { + return new HashIndex(this.DataType) + { + Precision = this.Precision + }; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Helpers.cs b/Microsoft.Azure.Cosmos/src/direct/Helpers.cs index 9dd0af60c6..946aec83a3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Helpers.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Helpers.cs @@ -1,282 +1,308 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Net.Http.Headers; - using Microsoft.Azure.Documents.Collections; - using Newtonsoft.Json; - - internal static class Helpers - { - internal static int ValidateNonNegativeInteger(string name, int value) - { - if (value < 0) - { - throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.NegativeInteger, name)); - } - - return value; - } - - internal static int ValidatePositiveInteger(string name, int value) - { - if (value <= 0) - { - throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.PositiveInteger, name)); - } - - return value; - } - - internal static void ValidateEnumProperties(TEnum enumValue) - { - foreach (TEnum e in Enum.GetValues(typeof(TEnum))) - { - if (e.Equals(enumValue)) return; - } - - throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, "Invalid value {0} for type{1}", enumValue.ToString(), enumValue.GetType().ToString())); - } - - /// - /// Gets the byte value for a header. If header not present, returns the defaultValue. - /// - /// - /// - /// Pls do not set defaultValue to MinValue as MinValue carries valid meaning in some place - /// - public static byte GetHeaderValueByte(INameValueCollection headerValues, string headerName, byte defaultValue = byte.MaxValue) - { - byte result = defaultValue; - string header = headerValues[headerName]; - if (!string.IsNullOrWhiteSpace(header)) - { - if (!byte.TryParse(header, NumberStyles.None, CultureInfo.InvariantCulture, out result)) - { - result = defaultValue; - } - } - return result; - } - - public static string GetDateHeader(INameValueCollection headerValues) - { - if (headerValues == null) - { - return string.Empty; - } - - // Since Date header is overridden by some proxies/http client libraries, we support - // an additional date header 'x-ms-date' and prefer that to the regular 'date' header. - string date = headerValues[HttpConstants.HttpHeaders.XDate]; - if (string.IsNullOrEmpty(date)) - { - date = headerValues[HttpConstants.HttpHeaders.HttpDate]; - } - - return date ?? string.Empty; - } - - public static string GetDateHeader(RequestNameValueCollection requestHeaders) - { - if (requestHeaders == null) - { - return string.Empty; - } - - // Since Date header is overridden by some proxies/http client libraries, we support - // an additional date header 'x-ms-date' and prefer that to the regular 'date' header. - string date = requestHeaders.XDate; - if (string.IsNullOrEmpty(date)) - { - date = requestHeaders.HttpDate; - } - - return date ?? string.Empty; - } - - public static long GetHeaderValueLong(INameValueCollection headerValues, string headerName, long defaultValue = -1) - { - long result = defaultValue; - - string header = headerValues[headerName]; - if (!string.IsNullOrEmpty(header)) - { - if (!long.TryParse(header, NumberStyles.Number, CultureInfo.InvariantCulture, out result)) - { - result = defaultValue; - } - } - return result; - } - - public static double GetHeaderValueDouble(INameValueCollection headerValues, string headerName, double defaultValue = -1) - { - double result = defaultValue; - - string header = headerValues[headerName]; - if (!string.IsNullOrEmpty(header)) - { - if (!double.TryParse(header, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result)) - { - result = defaultValue; - } - } - return result; - } - - internal static string[] ExtractValuesFromHTTPHeaders(HttpHeaders httpHeaders, string[] keys) - { - string[] headerValues = Enumerable.Repeat("", keys.Length).ToArray(); - - if (httpHeaders == null) return headerValues; - - foreach (KeyValuePair > pair in httpHeaders) - { - int pos = Array.FindIndex(keys, t => t.Equals(pair.Key, StringComparison.OrdinalIgnoreCase)); - if (pos < 0) - { - continue; - } - - if (pair.Value.Count() > 0) - { - headerValues[pos] = pair.Value.First(); - } - } - return headerValues; - } - - /// - /// Helper method to set application specific user agent suffix for internal telemetry purposes - /// - /// - /// - /// - internal static string GetAppSpecificUserAgentSuffix(string appName, string appVersion) - { - if (string.IsNullOrEmpty(appName)) - throw new ArgumentNullException("appName"); - - if (string.IsNullOrEmpty(appVersion)) - throw new ArgumentNullException("appVersion"); - - return string.Format(CultureInfo.InvariantCulture, "{0}/{1}", appName, appVersion); - } - - internal static void SetupJsonReader(JsonReader reader, JsonSerializerSettings serializerSettings) - { - if (serializerSettings != null) - { - if (serializerSettings.Culture != null) - { - reader.Culture = serializerSettings.Culture; - } - reader.DateTimeZoneHandling = serializerSettings.DateTimeZoneHandling; - reader.DateParseHandling = serializerSettings.DateParseHandling; - reader.FloatParseHandling = serializerSettings.FloatParseHandling; - if (serializerSettings.MaxDepth.HasValue) - { - reader.MaxDepth = serializerSettings.MaxDepth; - } - if (serializerSettings.DateFormatString != null) - { - reader.DateFormatString = serializerSettings.DateFormatString; - } - } - } - - internal static string GetScriptLogHeader(INameValueCollection headerValues) - { - string urlEscapedLogResult = headerValues?[HttpConstants.HttpHeaders.LogResults]; - if (!string.IsNullOrEmpty(urlEscapedLogResult)) - { - return Uri.UnescapeDataString(urlEscapedLogResult); - } - - return urlEscapedLogResult; - } - - internal static long ToUnixTime(DateTimeOffset dt) - { - TimeSpan dt2 = dt - new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan(0)); - return (long)dt2.TotalSeconds; - } - - // This function should be same with IFXTraceProvider::GetStatusFromStatusCodeType - internal static string GetStatusFromStatusCode(string statusCode) - { - int code; - if (!Int32.TryParse(statusCode, out code)) - { - return "Other"; - } - - return Helpers.GetStatusFromStatusCodeInt(code); - } - - internal static string GetStatusFromStatusCodeInt(int statusCodeInt) - { - if (statusCodeInt >= 200 && statusCodeInt < 300) return "Success"; - else if (statusCodeInt == 304) return "NotModified"; - else if (statusCodeInt == 400) return "BadRequestError"; - else if (statusCodeInt == 401) return "AuthorizationError"; - else if (statusCodeInt == 408) return "ServerTimeoutError"; - else if (statusCodeInt == 429) return "ClientThrottlingError"; - else if (statusCodeInt > 400 && statusCodeInt < 500) return "ClientOtherError"; - else if (statusCodeInt == 500) return "ServerOtherError"; - else if (statusCodeInt == 503) return "ServiceBusyError"; - else return "Other"; - } - - /// - /// Gets the environment variable value using the user provided key. - /// - /// A string containing the environment variable name. - /// A generic field containing the default value of the variable. - /// The environment variable value as a generic field. - internal static T GetEnvironmentVariable( - string name, - T defaultValue) where T : struct - { - string environmentVariableValue = Environment.GetEnvironmentVariable(name); - - if (string.IsNullOrWhiteSpace(environmentVariableValue)) - { - return defaultValue; - } - - switch (typeof(T)) - { - case Type intType when intType == typeof(int): - - if (int.TryParse(environmentVariableValue, out int environmentVariableInteger)) - { - return (T)(object)environmentVariableInteger; - } - - // Value is not valid. - throw new ArgumentException(message: $"Environment variable :{name} has an invalid integer value of: {environmentVariableValue}."); - - case Type boolType when boolType == typeof(bool): - - if (bool.TryParse(environmentVariableValue, out bool environmentVariableBool)) - { - return (T)(object)environmentVariableBool; - } - - // Value is not valid. - throw new ArgumentException(message: $"Environment variable :{name} has an invalid boolean value of: {environmentVariableValue}."); - } - - // Generic is not valid. - throw new ArgumentException(message: $"{typeof(T)} is not a valid generic."); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Net.Http.Headers; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + using Newtonsoft.Json; + + internal static class Helpers + { + internal static int ValidateNonNegativeInteger(string name, int value) + { + if (value < 0) + { + throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.NegativeInteger, name)); + } + + return value; + } + + internal static int ValidatePositiveInteger(string name, int value) + { + if (value <= 0) + { + throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.PositiveInteger, name)); + } + + return value; + } + + internal static void ValidateEnumProperties(TEnum enumValue) + { + foreach (TEnum e in Enum.GetValues(typeof(TEnum))) + { + if (e.Equals(enumValue)) return; + } + + throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, "Invalid value {0} for type{1}", enumValue.ToString(), enumValue.GetType().ToString())); + } + + /// + /// Gets the byte value for a header. If header not present, returns the defaultValue. + /// + /// + /// + /// Pls do not set defaultValue to MinValue as MinValue carries valid meaning in some place + /// + public static byte GetHeaderValueByte(INameValueCollection headerValues, string headerName, byte defaultValue = byte.MaxValue) + { + byte result = defaultValue; + string header = headerValues[headerName]; + if (!string.IsNullOrWhiteSpace(header)) + { + if (!byte.TryParse(header, NumberStyles.None, CultureInfo.InvariantCulture, out result)) + { + result = defaultValue; + } + } + return result; + } + + public static string GetDateHeader(INameValueCollection headerValues) + { + if (headerValues == null) + { + return string.Empty; + } + + // Since Date header is overridden by some proxies/http client libraries, we support + // an additional date header 'x-ms-date' and prefer that to the regular 'date' header. + string date = headerValues[HttpConstants.HttpHeaders.XDate]; + if (string.IsNullOrEmpty(date)) + { + date = headerValues[HttpConstants.HttpHeaders.HttpDate]; + } + + return date ?? string.Empty; + } + + public static string GetDateHeader(RequestNameValueCollection requestHeaders) + { + if (requestHeaders == null) + { + return string.Empty; + } + + // Since Date header is overridden by some proxies/http client libraries, we support + // an additional date header 'x-ms-date' and prefer that to the regular 'date' header. + string date = requestHeaders.XDate; + if (string.IsNullOrEmpty(date)) + { + date = requestHeaders.HttpDate; + } + + return date ?? string.Empty; + } + + public static long GetHeaderValueLong(INameValueCollection headerValues, string headerName, long defaultValue = -1) + { + long result = defaultValue; + + string header = headerValues[headerName]; + if (!string.IsNullOrEmpty(header)) + { + if (!long.TryParse(header, NumberStyles.Number, CultureInfo.InvariantCulture, out result)) + { + result = defaultValue; + } + } + return result; + } + + public static double GetHeaderValueDouble(INameValueCollection headerValues, string headerName, double defaultValue = -1) + { + double result = defaultValue; + + string header = headerValues[headerName]; + if (!string.IsNullOrEmpty(header)) + { + if (!double.TryParse(header, NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out result)) + { + result = defaultValue; + } + } + return result; + } + + internal static string[] ExtractValuesFromHTTPHeaders(HttpHeaders httpHeaders, string[] keys) + { + string[] headerValues = Enumerable.Repeat("", keys.Length).ToArray(); + + if (httpHeaders == null) return headerValues; + + foreach (KeyValuePair> pair in httpHeaders) + { + int pos = Array.FindIndex(keys, t => t.Equals(pair.Key, StringComparison.OrdinalIgnoreCase)); + if (pos < 0) + { + continue; + } + + if (pair.Value.Count() > 0) + { + headerValues[pos] = pair.Value.First(); + } + } + return headerValues; + } + + /// + /// Helper method to set application specific user agent suffix for internal telemetry purposes + /// + /// + /// + /// + internal static string GetAppSpecificUserAgentSuffix(string appName, string appVersion) + { + if (string.IsNullOrEmpty(appName)) + throw new ArgumentNullException("appName"); + + if (string.IsNullOrEmpty(appVersion)) + throw new ArgumentNullException("appVersion"); + + return string.Format(CultureInfo.InvariantCulture, "{0}/{1}", appName, appVersion); + } + + internal static void SetupJsonReader(JsonReader reader, JsonSerializerSettings serializerSettings) + { + if (serializerSettings != null) + { + if (serializerSettings.Culture != null) + { + reader.Culture = serializerSettings.Culture; + } + reader.DateTimeZoneHandling = serializerSettings.DateTimeZoneHandling; + reader.DateParseHandling = serializerSettings.DateParseHandling; + reader.FloatParseHandling = serializerSettings.FloatParseHandling; + if (serializerSettings.MaxDepth.HasValue) + { + reader.MaxDepth = serializerSettings.MaxDepth; + } + if (serializerSettings.DateFormatString != null) + { + reader.DateFormatString = serializerSettings.DateFormatString; + } + } + } + + internal static string GetScriptLogHeader(INameValueCollection headerValues) + { + string urlEscapedLogResult = headerValues?[HttpConstants.HttpHeaders.LogResults]; + if (!string.IsNullOrEmpty(urlEscapedLogResult)) + { + return Uri.UnescapeDataString(urlEscapedLogResult); + } + + return urlEscapedLogResult; + } + + internal static long ToUnixTime(DateTimeOffset dt) + { + TimeSpan dt2 = dt - new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan(0)); + return (long)dt2.TotalSeconds; + } + + // This function should be same with IFXTraceProvider::GetStatusFromStatusCodeType + internal static string GetStatusFromStatusCode(string statusCode) + { + int code; + if (!Int32.TryParse(statusCode, out code)) + { + return "Other"; + } + + return Helpers.GetStatusFromStatusCodeInt(code); + } + + internal static string GetStatusFromStatusCodeInt(int statusCodeInt) + { + if (statusCodeInt >= 200 && statusCodeInt < 300) return "Success"; + else if (statusCodeInt == 304) return "NotModified"; + else if (statusCodeInt == 400) return "BadRequestError"; + else if (statusCodeInt == 401) return "AuthorizationError"; + else if (statusCodeInt == 408) return "ServerTimeoutError"; + else if (statusCodeInt == 429) return "ClientThrottlingError"; + else if (statusCodeInt > 400 && statusCodeInt < 500) return "ClientOtherError"; + else if (statusCodeInt == 500) return "ServerOtherError"; + else if (statusCodeInt == 503) return "ServiceBusyError"; + else return "Other"; + } + + /// + /// Gets the environment variable value using the user provided key. + /// + /// A string containing the environment variable name. + /// A generic field containing the default value of the variable. + /// The environment variable value as a generic field. + internal static T GetEnvironmentVariable( + string name, + T defaultValue) where T : struct + { + string environmentVariableValue = Environment.GetEnvironmentVariable(name); + + if (string.IsNullOrWhiteSpace(environmentVariableValue)) + { + return defaultValue; + } + + switch (typeof(T)) + { + case Type intType when intType == typeof(int): + + if (int.TryParse(environmentVariableValue, out int environmentVariableInteger)) + { + return (T)(object)environmentVariableInteger; + } + + // Value is not valid. + throw new ArgumentException(message: $"Environment variable :{name} has an invalid integer value of: {environmentVariableValue}."); + + case Type boolType when boolType == typeof(bool): + + if (bool.TryParse(environmentVariableValue, out bool environmentVariableBool)) + { + return (T)(object)environmentVariableBool; + } + + // Value is not valid. + throw new ArgumentException(message: $"Environment variable :{name} has an invalid boolean value of: {environmentVariableValue}."); + } + + // Generic is not valid. + throw new ArgumentException(message: $"{typeof(T)} is not a valid generic."); + } + + /// + /// Gets the environment variable value using the user provided key.On any ArguemtnException the default value is used. + /// + /// A string containing the environment variable name. + /// A generic field containing the default value of the variable. + /// The environment variable value as a generic field. + internal static T GetSafeEnvironmentVariable( + string name, + T defaultValue) where T : struct + { + try + { + return GetEnvironmentVariable(name, defaultValue); + } + catch (ArgumentException argException) + { + DefaultTrace.TraceWarning( + "The environment variable '{0}' has an invalid value - the default value '{1}' is used. Exception: {2}", + name, + defaultValue, + argException.Message); + return defaultValue; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpClientExtension.cs b/Microsoft.Azure.Cosmos/src/direct/HttpClientExtension.cs index f45f78cb68..a1f720bdc6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpClientExtension.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpClientExtension.cs @@ -1,69 +1,69 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net.Http; - using System.Threading; - using System.Threading.Tasks; - - internal static class HttpClientExtension - { - internal static void AddUserAgentHeader(this HttpClient httpClient, UserAgentContainer userAgent) - { - // As per RFC 2616, Section 14.43 - httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.UserAgent, userAgent.UserAgent); - } - - internal static void AddApiTypeHeader(this HttpClient httpClient, ApiType apitype) - { - if (!apitype.Equals(ApiType.None)) - { - httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.ApiType, apitype.ToString()); - } - } - - internal static void AddSDKSupportedCapabilitiesHeader(this HttpClient httpClient, ulong capabilities) - { - httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.SDKSupportedCapabilities, capabilities.ToString()); - } - - internal static Task SendHttpAsync(this HttpClient httpClient, HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken)) - { - try - { - return httpClient.SendAsync(requestMessage, cancellationToken); - } - catch (HttpRequestException requestException) - { - throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); - } - } - - internal static Task SendHttpAsync(this HttpClient httpClient, HttpRequestMessage requestMessage, HttpCompletionOption options, CancellationToken cancellationToken = default(CancellationToken)) - { - try - { - return httpClient.SendAsync(requestMessage, options, cancellationToken); - } - catch (HttpRequestException requestException) - { - throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); - } - } - - internal static Task GetHttpAsync(this HttpClient httpClient, Uri serviceEndpoint, CancellationToken cancellationToken = default(CancellationToken)) - { - try - { - return httpClient.GetAsync(serviceEndpoint, cancellationToken); - } - catch (HttpRequestException requestException) - { - throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); - } - } - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + internal static class HttpClientExtension + { + internal static void AddUserAgentHeader(this HttpClient httpClient, UserAgentContainer userAgent) + { + // As per RFC 2616, Section 14.43 + httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.UserAgent, userAgent.UserAgent); + } + + internal static void AddApiTypeHeader(this HttpClient httpClient, ApiType apitype) + { + if (!apitype.Equals(ApiType.None)) + { + httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.ApiType, apitype.ToString()); + } + } + + internal static void AddSDKSupportedCapabilitiesHeader(this HttpClient httpClient, ulong capabilities) + { + httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.SDKSupportedCapabilities, capabilities.ToString()); + } + + internal static Task SendHttpAsync(this HttpClient httpClient, HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken)) + { + try + { + return httpClient.SendAsync(requestMessage, cancellationToken); + } + catch (HttpRequestException requestException) + { + throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); + } + } + + internal static Task SendHttpAsync(this HttpClient httpClient, HttpRequestMessage requestMessage, HttpCompletionOption options, CancellationToken cancellationToken = default(CancellationToken)) + { + try + { + return httpClient.SendAsync(requestMessage, options, cancellationToken); + } + catch (HttpRequestException requestException) + { + throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); + } + } + + internal static Task GetHttpAsync(this HttpClient httpClient, Uri serviceEndpoint, CancellationToken cancellationToken = default(CancellationToken)) + { + try + { + return httpClient.GetAsync(serviceEndpoint, cancellationToken); + } + catch (HttpRequestException requestException) + { + throw ServiceUnavailableException.Create(SubStatusCodes.Unknown, innerException: requestException); + } + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpConstants.cs b/Microsoft.Azure.Cosmos/src/direct/HttpConstants.cs index 7ea352df96cf1ba8b6c25cda63dd4d0362642ef6..3e243f09e07380623bc5d03428d2d60a8b0fd78e 100644 GIT binary patch delta 183 zcmbO;iG9H|_J%EtW?hp#9;!_@Xkb)IHexVgh-WZhFa?r^KvIFh7KoJ?jDTVwIbE=v zE?7>9!5S#14}=N~Aq-9oE?@Y$oa8CRz#@y|5W-vAw007SHC7S>M delta 34 ocmZ25jeX7}_J%EtW?kE#bumV9Y_FNj$j3GvL~h?Oi?P4}0P;5tBme*a diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpException.cs b/Microsoft.Azure.Cosmos/src/direct/HttpException.cs index 9e7e4c82ee..66438c8bd7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpException.cs @@ -1,621 +1,631 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Diagnostics; - using System.Globalization; - using System.Linq; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using System.Text; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.Routing; - - /// - /// The base class for client exceptions in the Azure Cosmos DB service. - /// - [Serializable] -#if COSMOSCLIENT - internal -#else - public -#endif - class DocumentClientException : Exception - { - private Error error; - private SubStatusCodes? substatus = null; - private INameValueCollection responseHeaders; - private string rawErrorMessage; - - internal DocumentClientException(Error errorResource, - HttpResponseHeaders responseHeaders, - HttpStatusCode? statusCode) - : base(DocumentClientException.MessageWithActivityId(errorResource.Message, responseHeaders)) - { - this.error = errorResource; - this.responseHeaders = new StoreResponseNameValueCollection(); - this.StatusCode = statusCode; - - if (responseHeaders != null) - { - foreach (KeyValuePair> header in responseHeaders) - { - this.responseHeaders.Add(header.Key, string.Join(",", header.Value)); - } - } - - // Stamp the activity ID if present. Exception throwers can override this if need be. -#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - if ((Trace.CorrelationManager.ActivityId != null) && - (this.responseHeaders.Get(HttpConstants.HttpHeaders.ActivityId) == null)) - { - this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, - Trace.CorrelationManager.ActivityId.ToString()); - } -#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - - this.LSN = -1; - this.PartitionKeyRangeId = null; - if (this.StatusCode != HttpStatusCode.Gone) - { - DefaultTrace.TraceError( - "DocumentClientException with status code: {0}, message: {1}, and response headers: {2}", - this.StatusCode ?? 0, - errorResource.Message, - SerializeHTTPResponseHeaders(responseHeaders)); - } - } - - internal DocumentClientException(string message, - Exception innerException, - HttpStatusCode? statusCode, - Uri requestUri = null, - string statusDescription = null) - : this(DocumentClientException.MessageWithActivityId(message), innerException, (INameValueCollection)null, statusCode, requestUri) - { - } - - internal DocumentClientException(string message, - Exception innerException, - HttpResponseHeaders responseHeaders, - HttpStatusCode? statusCode, - Uri requestUri = null, - SubStatusCodes? substatusCode = null, - bool traceCallStack = true) - : base(DocumentClientException.MessageWithActivityId(message, responseHeaders), innerException) - { - this.responseHeaders = new StoreResponseNameValueCollection(); - this.StatusCode = statusCode; - - if (responseHeaders != null) - { - foreach (KeyValuePair> header in responseHeaders) - { - this.responseHeaders.Add(header.Key, string.Join(",", header.Value)); - } - } - - // Update SubStatus in the headers if present - this.substatus = substatusCode; - if (this.substatus.HasValue) - { - this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); - } - - // Stamp the ambient activity ID (if present) over the server's response ActivityId (if present). -#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - if (Trace.CorrelationManager.ActivityId != null) - { - this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, - Trace.CorrelationManager.ActivityId.ToString()); - } -#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - - this.RequestUri = requestUri; - this.LSN = -1; - this.PartitionKeyRangeId = null; - this.rawErrorMessage = message; - - if (this.StatusCode != HttpStatusCode.Gone) - { - DefaultTrace.TraceError( - "DocumentClientException with status code {0}, message: {1}, inner exception: {2}, and response headers: {3}", - this.StatusCode ?? 0, - message, - innerException != null ? - (traceCallStack ? innerException.ToString() : innerException.ToStringWithMessageAndData()) : "null", - SerializeHTTPResponseHeaders(responseHeaders)); - } - } - - internal DocumentClientException(string message, - Exception innerException, - INameValueCollection responseHeaders, - HttpStatusCode? statusCode, - SubStatusCodes? substatusCode, - Uri requestUri = null) - : this(message, innerException, responseHeaders, statusCode, requestUri) - { - if (substatusCode.HasValue) - { - this.substatus = substatusCode; - this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); - } - } - - internal DocumentClientException(string message, - Exception innerException, - INameValueCollection responseHeaders, - HttpStatusCode? statusCode, - Uri requestUri = null) - : base(DocumentClientException.MessageWithActivityId(message, responseHeaders), innerException) - { - this.StatusCode = statusCode; - - if (responseHeaders is StoreResponseNameValueCollection storeResponseHeader) - { - this.responseHeaders = storeResponseHeader.Clone(); - } - else - { - this.responseHeaders = new StoreResponseNameValueCollection(); - if (responseHeaders != null) - { - this.responseHeaders.Add(responseHeaders); - } - } - - // Stamp the ambient activity ID (if present) over the server's response ActivityId (if present). -#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - if (Trace.CorrelationManager.ActivityId != null) - { - this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, - Trace.CorrelationManager.ActivityId.ToString()); - } -#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. - - this.RequestUri = requestUri; - this.LSN = -1; - this.PartitionKeyRangeId = null; - this.rawErrorMessage = message; - - if (this.StatusCode != HttpStatusCode.Gone) - { - DefaultTrace.TraceError( - "DocumentClientException with status code {0}, message: {1}, inner exception: {2}, and response headers: {3}", - this.StatusCode ?? 0, - message, - innerException != null ? innerException.ToString() : "null", - SerializeHTTPResponseHeaders(responseHeaders)); - } - } - - internal DocumentClientException(string message, - HttpStatusCode statusCode, - SubStatusCodes subStatusCode) - : this(message, null, statusCode, null) - { - this.substatus = subStatusCode; - this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); - } - - // Deserialisation constructor. -#if !NETSTANDARD16 - internal DocumentClientException(SerializationInfo info, StreamingContext context, HttpStatusCode? statusCode) - : base(info, context) - { - this.StatusCode = statusCode; - this.LSN = -1; - this.PartitionKeyRangeId = null; - - if (this.StatusCode != HttpStatusCode.Gone) - { - DefaultTrace.TraceError( - "DocumentClientException with status code {0}, and serialization info: {1}", - this.StatusCode ?? 0, - info.ToString()); - } - } - - internal DocumentClientException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - this.LSN = -1; - this.PartitionKeyRangeId = null; - } -#endif - - /// - /// Gets the error code associated with the exception in the Azure Cosmos DB service. - /// - public Error Error - { - get - { - if (this.error == null) - { - this.error = new Error - { - Code = this.StatusCode.ToString(), - Message = this.Message - }; - } - - return this.error; - } - - internal set - { - this.error = value; - } - } - - /// - /// Gets the activity ID associated with the request from the Azure Cosmos DB service. - /// - public string ActivityId - { - get - { - if (this.responseHeaders != null) - { - return this.responseHeaders[HttpConstants.HttpHeaders.ActivityId]; - } - - return null; - } - } - - /// - /// Gets the recommended time interval after which the client can retry failed requests from the Azure Cosmos DB service - /// - public TimeSpan RetryAfter - { - get - { - if (this.responseHeaders != null) - { - string header = this.responseHeaders[HttpConstants.HttpHeaders.RetryAfterInMilliseconds]; - if (!string.IsNullOrEmpty(header)) - { - long retryIntervalInMilliseconds = 0; - if (long.TryParse(header, NumberStyles.Number, CultureInfo.InvariantCulture, out retryIntervalInMilliseconds)) - { - return TimeSpan.FromMilliseconds(retryIntervalInMilliseconds); - } - } - } - - // - // In the absence of explicit guidance from the backend, don't introduce - // any unilateral retry delays here. - // - return TimeSpan.Zero; - } - } - - // - // Constructors will allocate the response headers so that - // the activity ID can be set correctly in a single location. - // - - /// - /// Gets the headers associated with the response from the Azure Cosmos DB service. - /// - public NameValueCollection ResponseHeaders - { - get - { - return this.responseHeaders.ToNameValueCollection(); - } - } - - internal INameValueCollection Headers - { - get { return this.responseHeaders; } - } - - /// - /// Gets or sets the request status code in the Azure Cosmos DB service. - /// - public HttpStatusCode? StatusCode { get; internal set; } - - /// - /// Gets the textual description of request completion status. - /// - internal string StatusDescription { get; set; } - - internal TransportRequestStats TransportRequestStats { get; set; } - - /// - /// Cost of the request in the Azure Cosmos DB service. - /// - public double RequestCharge - { - get - { - if (this.responseHeaders != null) - { - return Helpers.GetHeaderValueDouble( - this.responseHeaders, - HttpConstants.HttpHeaders.RequestCharge, - 0); - } - else - { - return 0; - } - } - } - - /// - /// Gets the console.log output from server side scripts statements when script logging is enabled. - /// - public string ScriptLog - { - get - { - return Helpers.GetScriptLogHeader(this.Headers); - } - } - - /// - /// Gets a message that describes the current exception from the Azure Cosmos DB service. - /// - public override string Message - { - get - { - string requestStatisticsMessage = this.RequestStatistics == null ? string.Empty : this.RequestStatistics.ToString(); - if (this.RequestUri != null) - { - return string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessageAddRequestUri, - base.Message, - this.RequestUri.PathAndQuery, - requestStatisticsMessage, - CustomTypeExtensions.GenerateBaseUserAgentString()); - } - else - { - if (string.IsNullOrEmpty(requestStatisticsMessage)) - { - return string.Format(CultureInfo.CurrentCulture, "{0}, {1}", base.Message, CustomTypeExtensions.GenerateBaseUserAgentString()); - } - else - { - return string.Format(CultureInfo.CurrentUICulture, "{0}, {1}, {2}", base.Message, requestStatisticsMessage, CustomTypeExtensions.GenerateBaseUserAgentString()); - } - } - } - } - - internal virtual string PublicMessage - { - get - { - string requestStatisticsMessage = this.RequestStatistics == null ? string.Empty : this.RequestStatistics.ToString(); - if (this.RequestUri != null) - { - return string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessageAddRequestUri, - base.Message, - this.RequestUri.PathAndQuery, - requestStatisticsMessage, - CustomTypeExtensions.GenerateBaseUserAgentString()); - } - else - { - if (string.IsNullOrEmpty(requestStatisticsMessage)) - { - return string.Format(CultureInfo.CurrentCulture, - "{0}, {1}", - base.Message, - CustomTypeExtensions.GenerateBaseUserAgentString()); - } - else - { - return string.Format(CultureInfo.CurrentUICulture, - "{0}, {1}, {2}", - base.Message, - requestStatisticsMessage, - CustomTypeExtensions.GenerateBaseUserAgentString()); - } - } - } - } - - internal string RawErrorMessage - { - get - { - return this.rawErrorMessage ?? base.Message; - } - } - - internal IClientSideRequestStatistics RequestStatistics - { - get; - set; - } - - internal long LSN { get; set; } - - internal string PartitionKeyRangeId { get; set; } - - internal string ResourceAddress { get; set; } - - internal bool UseArmErrorResponse { get; set; } - - /// - /// Gets the request uri from the current exception from the Azure Cosmos DB service. - /// - internal Uri RequestUri { get; private set; } - - private static string MessageWithActivityId(string message, INameValueCollection responseHeaders) - { - string[] activityIds = null; - - if (responseHeaders != null) - { - activityIds = responseHeaders.GetValues(HttpConstants.HttpHeaders.ActivityId); - } - - if (activityIds != null) - { - return DocumentClientException.MessageWithActivityId(message, activityIds.FirstOrDefault()); - } - else - { - return DocumentClientException.MessageWithActivityId(message); - } - } - - private static string MessageWithActivityId(string message, HttpResponseHeaders responseHeaders) - { - IEnumerable activityIds = null; - if (responseHeaders != null && responseHeaders.TryGetValues(HttpConstants.HttpHeaders.ActivityId, out activityIds)) - { - if (activityIds != null) - { - return DocumentClientException.MessageWithActivityId(message, activityIds.FirstOrDefault()); - } - } - - return DocumentClientException.MessageWithActivityId(message); - } - - private static string MessageWithActivityId(string message, string activityIdFromHeaders = null) - { - string activityId = null; - if (!string.IsNullOrEmpty(activityIdFromHeaders)) - { - activityId = activityIdFromHeaders; - } - else if (Trace.CorrelationManager.ActivityId != Guid.Empty) - { - activityId = Trace.CorrelationManager.ActivityId.ToString(); - } - else - { - // If we couldn't find an ActivityId either in the headers or in the CorrelationManager, - // just return the message as-is. - return message; - } - - // If we're making this exception on the client side using the message from the Gateway, - // the message may already have activityId stamped in it. If so, just use the message as-is - if (message.Contains(activityId)) - { - return message; - } - else - { - return string.Format(CultureInfo.InvariantCulture, "{0}" + Environment.NewLine + "ActivityId: {1}", - message, activityId); - } - } - - private static string SerializeHTTPResponseHeaders(HttpResponseHeaders responseHeaders) - { - if (responseHeaders == null) return "null"; - - StringBuilder result = new StringBuilder("{"); - result.Append(Environment.NewLine); - - foreach (KeyValuePair> pair in responseHeaders) - { - foreach (string value in pair.Value) - { - result.Append(string.Format(CultureInfo.InvariantCulture, - "\"{0}\": \"{1}\",{2}", - pair.Key, - value, - Environment.NewLine)); - } - } - - result.Append("}"); - return result.ToString(); - } - - internal SubStatusCodes GetSubStatus() - { - if (this.substatus == null) - { - this.substatus = SubStatusCodes.Unknown; - - string valueSubStatus = this.responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); - if (!string.IsNullOrEmpty(valueSubStatus)) - { - uint nSubStatus = 0; - if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) - { - this.substatus = (SubStatusCodes)nSubStatus; - } - } - } - - return this.substatus != null ? this.substatus.Value : SubStatusCodes.Unknown; - } - - internal static SubStatusCodes GetExceptionSubStatusForGoneRetryPolicy(Exception exception) - { - SubStatusCodes exceptionSubStatus = SubStatusCodes.Unknown; - if (exception is DocumentClientException dce) - { - // convert known 410 substatus codes to specific 503 substatus codes. - if (dce is PartitionIsMigratingException) - { - exceptionSubStatus = SubStatusCodes.Server_CompletingPartitionMigrationExceededRetryLimit; - } - else if (dce is InvalidPartitionException) - { - exceptionSubStatus = SubStatusCodes.Server_NameCacheIsStaleExceededRetryLimit; - } - else if (dce is PartitionKeyRangeIsSplittingException) - { - exceptionSubStatus = SubStatusCodes.Server_CompletingSplitExceededRetryLimit; - } - else if (dce is PartitionKeyRangeGoneException) - { - exceptionSubStatus = SubStatusCodes.Server_PartitionKeyRangeGoneExceededRetryLimit; - } - else - { - exceptionSubStatus = dce.GetSubStatus(); - } - } - - return exceptionSubStatus; - } - - private static string SerializeHTTPResponseHeaders(INameValueCollection responseHeaders) - { - if (responseHeaders == null) return "null"; - - IEnumerable> items = responseHeaders.AllKeys().SelectMany(responseHeaders.GetValues, (k, v) => new Tuple(k, v)); - - StringBuilder result = new StringBuilder("{"); - result.Append(Environment.NewLine); - - foreach (Tuple item in items) - { - result.Append(string.Format(CultureInfo.InvariantCulture, - "\"{0}\": \"{1}\",{2}", - item.Item1, - item.Item2, - Environment.NewLine)); - } - - result.Append("}"); - return result.ToString(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Diagnostics; + using System.Globalization; + using System.Linq; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using System.Text; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.Routing; + + /// + /// The base class for client exceptions in the Azure Cosmos DB service. + /// + [Serializable] +#if COSMOSCLIENT + internal +#else + public +#endif + class DocumentClientException : Exception + { + private Error error; + private SubStatusCodes? substatus = null; + private INameValueCollection responseHeaders; + private string rawErrorMessage; + private Boolean rawErrorMessageOnly; + + internal DocumentClientException(Error errorResource, + HttpResponseHeaders responseHeaders, + HttpStatusCode? statusCode) + : base(DocumentClientException.MessageWithActivityId(errorResource.Message, responseHeaders)) + { + this.error = errorResource; + this.responseHeaders = new StoreResponseNameValueCollection(); + this.StatusCode = statusCode; + + if (responseHeaders != null) + { + foreach (KeyValuePair> header in responseHeaders) + { + this.responseHeaders.Add(header.Key, string.Join(",", header.Value)); + } + } + + // Stamp the activity ID if present. Exception throwers can override this if need be. +#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + if ((Trace.CorrelationManager.ActivityId != null) && + (this.responseHeaders.Get(HttpConstants.HttpHeaders.ActivityId) == null)) + { + this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, + Trace.CorrelationManager.ActivityId.ToString()); + } +#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + + this.LSN = -1; + this.PartitionKeyRangeId = null; + if (this.StatusCode != HttpStatusCode.Gone) + { + DefaultTrace.TraceError( + "DocumentClientException with status code: {0}, message: {1}, and response headers: {2}", + this.StatusCode ?? 0, + errorResource.Message, + SerializeHTTPResponseHeaders(responseHeaders)); + } + } + + internal DocumentClientException(string message, + Exception innerException, + HttpStatusCode? statusCode, + Uri requestUri = null, + string statusDescription = null) + : this(DocumentClientException.MessageWithActivityId(message), innerException, (INameValueCollection)null, statusCode, requestUri) + { + } + + internal DocumentClientException(string message, + Exception innerException, + HttpResponseHeaders responseHeaders, + HttpStatusCode? statusCode, + Uri requestUri = null, + SubStatusCodes? substatusCode = null, + bool traceCallStack = true, + bool rawErrorMessageOnly = false) + : base(DocumentClientException.MessageWithActivityId(message, responseHeaders), innerException) + { + this.responseHeaders = new StoreResponseNameValueCollection(); + this.StatusCode = statusCode; + + if (responseHeaders != null) + { + foreach (KeyValuePair> header in responseHeaders) + { + this.responseHeaders.Add(header.Key, string.Join(",", header.Value)); + } + } + + // Update SubStatus in the headers if present + this.substatus = substatusCode; + if (this.substatus.HasValue) + { + this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); + } + + // Stamp the ambient activity ID (if present) over the server's response ActivityId (if present). +#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + if (Trace.CorrelationManager.ActivityId != null) + { + this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, + Trace.CorrelationManager.ActivityId.ToString()); + } +#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + + this.RequestUri = requestUri; + this.LSN = -1; + this.PartitionKeyRangeId = null; + this.rawErrorMessage = message; + this.rawErrorMessageOnly = rawErrorMessageOnly; + + if (this.StatusCode != HttpStatusCode.Gone) + { + DefaultTrace.TraceError( + "DocumentClientException with status code {0}, message: {1}, inner exception: {2}, and response headers: {3}", + this.StatusCode ?? 0, + message, + innerException != null ? + (traceCallStack ? innerException.ToString() : innerException.ToStringWithMessageAndData()) : "null", + SerializeHTTPResponseHeaders(responseHeaders)); + } + } + + internal DocumentClientException(string message, + Exception innerException, + INameValueCollection responseHeaders, + HttpStatusCode? statusCode, + SubStatusCodes? substatusCode, + Uri requestUri = null) + : this(message, innerException, responseHeaders, statusCode, requestUri) + { + if (substatusCode.HasValue) + { + this.substatus = substatusCode; + this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); + } + } + + internal DocumentClientException(string message, + Exception innerException, + INameValueCollection responseHeaders, + HttpStatusCode? statusCode, + Uri requestUri = null, + bool rawErrorMessageOnly = false) + : base(DocumentClientException.MessageWithActivityId(message, responseHeaders), innerException) + { + this.StatusCode = statusCode; + + if (responseHeaders is StoreResponseNameValueCollection storeResponseHeader) + { + this.responseHeaders = storeResponseHeader.Clone(); + } + else + { + this.responseHeaders = new StoreResponseNameValueCollection(); + if (responseHeaders != null) + { + this.responseHeaders.Add(responseHeaders); + } + } + + // Stamp the ambient activity ID (if present) over the server's response ActivityId (if present). +#pragma warning disable CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + if (Trace.CorrelationManager.ActivityId != null) + { + this.responseHeaders.Set(HttpConstants.HttpHeaders.ActivityId, + Trace.CorrelationManager.ActivityId.ToString()); + } +#pragma warning restore CS8073 // Result of ActivityId (Guid) compared to null here is always true. Fixing the condition can cause unexpected behavior. + + this.RequestUri = requestUri; + this.LSN = -1; + this.PartitionKeyRangeId = null; + this.rawErrorMessage = message; + this.rawErrorMessageOnly = rawErrorMessageOnly; + + if (this.StatusCode != HttpStatusCode.Gone) + { + DefaultTrace.TraceError( + "DocumentClientException with status code {0}, message: {1}, inner exception: {2}, and response headers: {3}", + this.StatusCode ?? 0, + message, + innerException != null ? innerException.ToString() : "null", + SerializeHTTPResponseHeaders(responseHeaders)); + } + } + + internal DocumentClientException(string message, + HttpStatusCode statusCode, + SubStatusCodes subStatusCode) + : this(message, null, statusCode, null) + { + this.substatus = subStatusCode; + this.responseHeaders[WFConstants.BackendHeaders.SubStatus] = ((int)this.substatus).ToString(CultureInfo.InvariantCulture); + } + + // Deserialisation constructor. +#if !NETSTANDARD16 + internal DocumentClientException(SerializationInfo info, StreamingContext context, HttpStatusCode? statusCode) + : base(info, context) + { + this.StatusCode = statusCode; + this.LSN = -1; + this.PartitionKeyRangeId = null; + + if (this.StatusCode != HttpStatusCode.Gone) + { + DefaultTrace.TraceError( + "DocumentClientException with status code {0}, and serialization info: {1}", + this.StatusCode ?? 0, + info.ToString()); + } + } + + internal DocumentClientException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.LSN = -1; + this.PartitionKeyRangeId = null; + } +#endif + + /// + /// Gets the error code associated with the exception in the Azure Cosmos DB service. + /// + public Error Error + { + get + { + if (this.error == null) + { + this.error = new Error + { + Code = this.StatusCode.ToString(), + Message = this.Message + }; + } + + return this.error; + } + + internal set + { + this.error = value; + } + } + + /// + /// Gets the activity ID associated with the request from the Azure Cosmos DB service. + /// + public string ActivityId + { + get + { + if (this.responseHeaders != null) + { + return this.responseHeaders[HttpConstants.HttpHeaders.ActivityId]; + } + + return null; + } + } + + /// + /// Gets the recommended time interval after which the client can retry failed requests from the Azure Cosmos DB service + /// + public TimeSpan RetryAfter + { + get + { + if (this.responseHeaders != null) + { + string header = this.responseHeaders[HttpConstants.HttpHeaders.RetryAfterInMilliseconds]; + if (!string.IsNullOrEmpty(header)) + { + long retryIntervalInMilliseconds = 0; + if (long.TryParse(header, NumberStyles.Number, CultureInfo.InvariantCulture, out retryIntervalInMilliseconds)) + { + return TimeSpan.FromMilliseconds(retryIntervalInMilliseconds); + } + } + } + + // + // In the absence of explicit guidance from the backend, don't introduce + // any unilateral retry delays here. + // + return TimeSpan.Zero; + } + } + + // + // Constructors will allocate the response headers so that + // the activity ID can be set correctly in a single location. + // + + /// + /// Gets the headers associated with the response from the Azure Cosmos DB service. + /// + public NameValueCollection ResponseHeaders + { + get + { + return this.responseHeaders.ToNameValueCollection(); + } + } + + internal INameValueCollection Headers + { + get { return this.responseHeaders; } + } + + /// + /// Gets or sets the request status code in the Azure Cosmos DB service. + /// + public HttpStatusCode? StatusCode { get; internal set; } + + /// + /// Gets the textual description of request completion status. + /// + internal string StatusDescription { get; set; } + + internal TransportRequestStats TransportRequestStats { get; set; } + + /// + /// Cost of the request in the Azure Cosmos DB service. + /// + public double RequestCharge + { + get + { + if (this.responseHeaders != null) + { + return Helpers.GetHeaderValueDouble( + this.responseHeaders, + HttpConstants.HttpHeaders.RequestCharge, + 0); + } + else + { + return 0; + } + } + } + + /// + /// Gets the console.log output from server side scripts statements when script logging is enabled. + /// + public string ScriptLog + { + get + { + return Helpers.GetScriptLogHeader(this.Headers); + } + } + + /// + /// Gets a message that describes the current exception from the Azure Cosmos DB service. + /// + public override string Message + { + get + { + if (this.rawErrorMessageOnly) + { + return this.rawErrorMessage; + } + + string requestStatisticsMessage = this.RequestStatistics == null ? string.Empty : this.RequestStatistics.ToString(); + if (this.RequestUri != null) + { + return string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessageAddRequestUri, + base.Message, + this.RequestUri.PathAndQuery, + requestStatisticsMessage, + CustomTypeExtensions.GenerateBaseUserAgentString()); + } + else + { + if (string.IsNullOrEmpty(requestStatisticsMessage)) + { + return string.Format(CultureInfo.CurrentCulture, "{0}, {1}", base.Message, CustomTypeExtensions.GenerateBaseUserAgentString()); + } + else + { + return string.Format(CultureInfo.CurrentUICulture, "{0}, {1}, {2}", base.Message, requestStatisticsMessage, CustomTypeExtensions.GenerateBaseUserAgentString()); + } + } + } + } + + internal virtual string PublicMessage + { + get + { + string requestStatisticsMessage = this.RequestStatistics == null ? string.Empty : this.RequestStatistics.ToString(); + if (this.RequestUri != null) + { + return string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessageAddRequestUri, + base.Message, + this.RequestUri.PathAndQuery, + requestStatisticsMessage, + CustomTypeExtensions.GenerateBaseUserAgentString()); + } + else + { + if (string.IsNullOrEmpty(requestStatisticsMessage)) + { + return string.Format(CultureInfo.CurrentCulture, + "{0}, {1}", + base.Message, + CustomTypeExtensions.GenerateBaseUserAgentString()); + } + else + { + return string.Format(CultureInfo.CurrentUICulture, + "{0}, {1}, {2}", + base.Message, + requestStatisticsMessage, + CustomTypeExtensions.GenerateBaseUserAgentString()); + } + } + } + } + + internal string RawErrorMessage + { + get + { + return this.rawErrorMessage ?? base.Message; + } + } + + internal IClientSideRequestStatistics RequestStatistics + { + get; + set; + } + + internal long LSN { get; set; } + + internal string PartitionKeyRangeId { get; set; } + + internal string ResourceAddress { get; set; } + + internal bool UseArmErrorResponse { get; set; } + + /// + /// Gets the request uri from the current exception from the Azure Cosmos DB service. + /// + internal Uri RequestUri { get; private set; } + + private static string MessageWithActivityId(string message, INameValueCollection responseHeaders) + { + string[] activityIds = null; + + if (responseHeaders != null) + { + activityIds = responseHeaders.GetValues(HttpConstants.HttpHeaders.ActivityId); + } + + if (activityIds != null) + { + return DocumentClientException.MessageWithActivityId(message, activityIds.FirstOrDefault()); + } + else + { + return DocumentClientException.MessageWithActivityId(message); + } + } + + private static string MessageWithActivityId(string message, HttpResponseHeaders responseHeaders) + { + IEnumerable activityIds = null; + if (responseHeaders != null && responseHeaders.TryGetValues(HttpConstants.HttpHeaders.ActivityId, out activityIds)) + { + if (activityIds != null) + { + return DocumentClientException.MessageWithActivityId(message, activityIds.FirstOrDefault()); + } + } + + return DocumentClientException.MessageWithActivityId(message); + } + + private static string MessageWithActivityId(string message, string activityIdFromHeaders = null) + { + string activityId = null; + if (!string.IsNullOrEmpty(activityIdFromHeaders)) + { + activityId = activityIdFromHeaders; + } + else if (Trace.CorrelationManager.ActivityId != Guid.Empty) + { + activityId = Trace.CorrelationManager.ActivityId.ToString(); + } + else + { + // If we couldn't find an ActivityId either in the headers or in the CorrelationManager, + // just return the message as-is. + return message; + } + + // If we're making this exception on the client side using the message from the Gateway, + // the message may already have activityId stamped in it. If so, just use the message as-is + if (message.Contains(activityId)) + { + return message; + } + else + { + return string.Format(CultureInfo.InvariantCulture, "{0}" + Environment.NewLine + "ActivityId: {1}", + message, activityId); + } + } + + private static string SerializeHTTPResponseHeaders(HttpResponseHeaders responseHeaders) + { + if (responseHeaders == null) return "null"; + + StringBuilder result = new StringBuilder("{"); + result.Append(Environment.NewLine); + + foreach (KeyValuePair> pair in responseHeaders) + { + foreach (string value in pair.Value) + { + result.Append(string.Format(CultureInfo.InvariantCulture, + "\"{0}\": \"{1}\",{2}", + pair.Key, + value, + Environment.NewLine)); + } + } + + result.Append("}"); + return result.ToString(); + } + + internal SubStatusCodes GetSubStatus() + { + if (this.substatus == null) + { + this.substatus = SubStatusCodes.Unknown; + + string valueSubStatus = this.responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); + if (!string.IsNullOrEmpty(valueSubStatus)) + { + uint nSubStatus = 0; + if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) + { + this.substatus = (SubStatusCodes)nSubStatus; + } + } + } + + return this.substatus != null ? this.substatus.Value : SubStatusCodes.Unknown; + } + + internal static SubStatusCodes GetExceptionSubStatusForGoneRetryPolicy(Exception exception) + { + SubStatusCodes exceptionSubStatus = SubStatusCodes.Unknown; + if (exception is DocumentClientException dce) + { + // convert known 410 substatus codes to specific 503 substatus codes. + if (dce is PartitionIsMigratingException) + { + exceptionSubStatus = SubStatusCodes.Server_CompletingPartitionMigrationExceededRetryLimit; + } + else if (dce is InvalidPartitionException) + { + exceptionSubStatus = SubStatusCodes.Server_NameCacheIsStaleExceededRetryLimit; + } + else if (dce is PartitionKeyRangeIsSplittingException) + { + exceptionSubStatus = SubStatusCodes.Server_CompletingSplitExceededRetryLimit; + } + else if (dce is PartitionKeyRangeGoneException) + { + exceptionSubStatus = SubStatusCodes.Server_PartitionKeyRangeGoneExceededRetryLimit; + } + else + { + exceptionSubStatus = dce.GetSubStatus(); + } + } + + return exceptionSubStatus; + } + + private static string SerializeHTTPResponseHeaders(INameValueCollection responseHeaders) + { + if (responseHeaders == null) return "null"; + + IEnumerable> items = responseHeaders.AllKeys().SelectMany(responseHeaders.GetValues, (k, v) => new Tuple(k, v)); + + StringBuilder result = new StringBuilder("{"); + result.Append(Environment.NewLine); + + foreach (Tuple item in items) + { + result.Append(string.Format(CultureInfo.InvariantCulture, + "\"{0}\": \"{1}\",{2}", + item.Item1, + item.Item2, + Environment.NewLine)); + } + + result.Append("}"); + return result.ToString(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs b/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs index 25419952ef..810fce1fee 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs @@ -1,1506 +1,1517 @@ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Net; - using System.Net.Http; - using System.Net.Http.Headers; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.Routing; - - internal sealed class HttpTransportClient : TransportClient - { - private readonly HttpClient httpClient; - private readonly ICommunicationEventSource eventSource; - - public const string Match = "Match"; - - public HttpTransportClient( - int requestTimeout, - ICommunicationEventSource eventSource, - UserAgentContainer userAgent = null, - int idleTimeoutInSeconds = -1, - HttpMessageHandler messageHandler = null) - { -#if NETFX - if (idleTimeoutInSeconds > 0) - { - ServicePointManager.MaxServicePointIdleTime = idleTimeoutInSeconds; - ServicePointManager.SetTcpKeepAlive(true, keepAliveTime: 30000, keepAliveInterval: 1000); - } -#endif - - if (messageHandler != null) - { - this.httpClient = new HttpClient(messageHandler); - } - else - { - this.httpClient = new HttpClient(); - } - - this.httpClient.Timeout = TimeSpan.FromSeconds(requestTimeout); - this.httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; - - // Set requested API version header for version enforcement. - this.httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version, - HttpConstants.Versions.CurrentVersion); - - if (userAgent == null) - { - userAgent = new UserAgentContainer(); - } - - this.httpClient.AddUserAgentHeader(userAgent); - - this.httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Accept, RuntimeConstants.MediaTypes.Json); - - this.eventSource = eventSource; - } - - public override void Dispose() - { - base.Dispose(); - - if (this.httpClient != null) - { - this.httpClient.Dispose(); - } - } - - private void BeforeRequest(Guid activityId, Uri uri, ResourceType resourceType, HttpRequestHeaders requestHeaders) - { -#if NETFX - - if (PerfCounters.Counters.BackendActiveRequests != null) - { - PerfCounters.Counters.BackendActiveRequests.Increment(); - } - - if (PerfCounters.Counters.BackendRequestsPerSec != null) - { - PerfCounters.Counters.BackendRequestsPerSec.Increment(); - } -#endif - - this.eventSource.Request( - activityId, - Guid.Empty, - uri.ToString(), - resourceType.ToResourceTypeString(), - requestHeaders); - } - - private void AfterRequest(Guid activityId, - HttpStatusCode statusCode, - double durationInMilliSeconds, - HttpResponseHeaders responseHeaders) - { -#if NETFX - if (PerfCounters.Counters.BackendActiveRequests != null) - { - PerfCounters.Counters.BackendActiveRequests.Decrement(); - } -#endif - - this.eventSource.Response( - activityId, - Guid.Empty, - (short)statusCode, - durationInMilliSeconds, - responseHeaders); - } - - internal override async Task InvokeStoreAsync( - Uri physicalAddress, - ResourceOperation resourceOperation, - DocumentServiceRequest request) - { - Guid activityId = Trace.CorrelationManager.ActivityId; - Debug.Assert(activityId != Guid.Empty); - - INameValueCollection responseHeaders = new DictionaryNameValueCollection(); - responseHeaders.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - - if (!request.IsBodySeekableClonableAndCountable) - { - throw new InternalServerErrorException(RMResources.InternalServerError, responseHeaders); - } - -#if !COSMOSCLIENT - if (resourceOperation.operationType == OperationType.Recreate) - { - DefaultTrace.TraceCritical("Received Recreate request on Http client"); - throw new InternalServerErrorException(RMResources.InternalServerError, responseHeaders); - } -#endif - - using (HttpRequestMessage requestMessage = this.PrepareHttpMessage( - activityId, - physicalAddress, - resourceOperation, - request)) - { - HttpResponseMessage responseMessage = null; - DateTime sendTimeUtc = DateTime.UtcNow; - try - { - this.BeforeRequest( - activityId, - requestMessage.RequestUri, - request.ResourceType, - requestMessage.Headers); - - responseMessage = await this.httpClient.SendAsync(requestMessage, - HttpCompletionOption.ResponseHeadersRead); - } - catch (Exception exception) - { - Trace.CorrelationManager.ActivityId = activityId; - if (WebExceptionUtility.IsWebExceptionRetriable(exception)) - { - DefaultTrace.TraceInformation("Received retriable exception {0} " + - "sending the request to {1}, will reresolve the address " + - "send time UTC: {2}", - exception, - physicalAddress, - sendTimeUtc); - - GoneException goneException = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - exception, - SubStatusCodes.TransportGenerated410, - null, - physicalAddress.ToString()); - - throw goneException; - } - else if (request.IsReadOnlyRequest) - { - DefaultTrace.TraceInformation("Received exception {0} on readonly request" + - "sending the request to {1}, will reresolve the address " + - "send time UTC: {2}", - exception, - physicalAddress, - sendTimeUtc); - - GoneException goneException = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - exception, - SubStatusCodes.TransportGenerated410, - null, - physicalAddress.ToString()); - - throw goneException; - } - else - { - // We can't throw a GoneException here because it will cause retry and we don't - // know if the request failed before or after the message got sent to the server. - // So in order to avoid duplicating the request we will not retry. - // TODO: a possible solution for this is to add the ability to send a request to the server - // to check if the previous request was received or not and act accordingly. - ServiceUnavailableException serviceUnavailableException = ServiceUnavailableException.Create( - SubStatusCodes.Unknown, - exception, - null, - physicalAddress); - serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh, "1"); - throw serviceUnavailableException; - } - } - finally - { - DateTime receivedTimeUtc = DateTime.UtcNow; - double durationInMilliSeconds = (receivedTimeUtc - sendTimeUtc).TotalMilliseconds; - - this.AfterRequest( - activityId, - responseMessage != null ? responseMessage.StatusCode : 0, - durationInMilliSeconds, - responseMessage != null ? responseMessage.Headers : null); - } - - using (responseMessage) - { - return await HttpTransportClient.ProcessHttpResponse(request.ResourceAddress, activityId.ToString(), responseMessage, physicalAddress, request); - } - } - } - - private static void AddHeader(HttpRequestHeaders requestHeaders, string headerName, DocumentServiceRequest request) - { - string headerValue = request.Headers[headerName]; - if (!string.IsNullOrEmpty(headerValue)) - { - requestHeaders.Add(headerName, headerValue); - } - } - - private static void AddHeader(HttpContentHeaders requestHeaders, string headerName, DocumentServiceRequest request) - { - string headerValue = request.Headers[headerName]; - if (!string.IsNullOrEmpty(headerValue)) - { - requestHeaders.Add(headerName, headerValue); - } - } - - private static void AddHeader(HttpRequestHeaders requestHeaders, string headerName, string headerValue) - { - if (!string.IsNullOrEmpty(headerValue)) - { - requestHeaders.Add(headerName, headerValue); - } - } - - private string GetMatch(DocumentServiceRequest request, ResourceOperation resourceOperation) - { - switch (resourceOperation.operationType) - { - case OperationType.Delete: - case OperationType.ExecuteJavaScript: - case OperationType.Replace: - case OperationType.Patch: - case OperationType.Upsert: - return request.Headers[HttpConstants.HttpHeaders.IfMatch]; - - case OperationType.Read: - case OperationType.ReadFeed: - return request.Headers[HttpConstants.HttpHeaders.IfNoneMatch]; - - default: - return null; - } - } - - [SuppressMessage("Microsoft.Reliability", "CA2000: DisposeObjectsBeforeLosingScope", Justification = "Disposable object returned by method")] - private HttpRequestMessage PrepareHttpMessage( - Guid activityId, - Uri physicalAddress, - ResourceOperation resourceOperation, - DocumentServiceRequest request) - { - HttpRequestMessage httpRequestMessage = new HttpRequestMessage(); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Version, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UserAgent, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PageSize, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PreTriggerInclude, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PreTriggerExclude, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PostTriggerInclude, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PostTriggerExclude, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Authorization, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IndexingDirective, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateCollectionDirective, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ConsistencyLevel, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SessionToken, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Prefer, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ResourceTokenExpiry, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableScanInQuery, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanCharge, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanThrottle, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableLogging, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsReadOnlyScript, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ContentSerializationFormat, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SupportedSerializationFormats, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Continuation, request.Continuation); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ActivityId, activityId.ToString()); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PartitionKey, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PartitionKeyRangeId, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableCrossPartitionQuery, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SDKSupportedCapabilities, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ReadFeedKeyType, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.StartEpk, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EndEpk, request); - - string dateHeader = Helpers.GetDateHeader(request.Headers); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.XDate, dateHeader); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpTransportClient.Match, this.GetMatch(request, resourceOperation)); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IfModifiedSince, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.A_IM, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, request); - - if (!request.IsNameBased) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ResourceId, request.ResourceId); - } - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.EntityId, request.EntityId); - - string fanoutRequestHeader = request.Headers[WFConstants.BackendHeaders.IsFanoutRequest]; - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.IsFanoutRequest, fanoutRequestHeader); - - if (request.ResourceType == ResourceType.Collection) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionPartitionIndex, request.Headers[WFConstants.BackendHeaders.CollectionPartitionIndex]); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionServiceIndex, request.Headers[WFConstants.BackendHeaders.CollectionServiceIndex]); - } - - if (request.Headers[WFConstants.BackendHeaders.RequestedCollectionType] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.RequestedCollectionType, request.Headers[WFConstants.BackendHeaders.RequestedCollectionType]); - } - - if (request.Headers[WFConstants.BackendHeaders.BindReplicaDirective] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.BindReplicaDirective, request.Headers[WFConstants.BackendHeaders.BindReplicaDirective]); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PrimaryMasterKey, request.Headers[WFConstants.BackendHeaders.PrimaryMasterKey]); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.SecondaryMasterKey, request.Headers[WFConstants.BackendHeaders.SecondaryMasterKey]); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PrimaryReadonlyKey, request.Headers[WFConstants.BackendHeaders.PrimaryReadonlyKey]); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.SecondaryReadonlyKey, request.Headers[WFConstants.BackendHeaders.SecondaryReadonlyKey]); - } - - if (request.Headers[HttpConstants.HttpHeaders.CanOfferReplaceComplete] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanOfferReplaceComplete, request.Headers[HttpConstants.HttpHeaders.CanOfferReplaceComplete]); - } - - if (request.Headers[HttpConstants.HttpHeaders.IsThroughputCapRequest] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsThroughputCapRequest, request.Headers[HttpConstants.HttpHeaders.IsThroughputCapRequest]); - } - - if (request.Headers[WFConstants.BackendHeaders.PopulateCapacityType] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PopulateCapacityType, request.Headers[WFConstants.BackendHeaders.PopulateCapacityType]); - } - - if (request.Headers[WFConstants.BackendHeaders.ClientIpAddress] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ClientIpAddress, request.Headers[WFConstants.BackendHeaders.ClientIpAddress]); - } - - if (request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized] != null) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.IsRequestNotAuthorized, request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized]); - } - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsAutoScaleRequest, request); - - //Query - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsQuery, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Query, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsQueryPlanRequest, request); - - // Upsert - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsUpsert, request); - - // SupportSpatialLegacyCoordinates - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PartitionCount, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionRid, request); - - // Filter by schema - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.FilterBySchemaResourceId, request); - - // UsePolygonsSmallerThanAHemisphere - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.GatewaySignature, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateQuotaInfo, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateQueryMetrics, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateIndexMetrics, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateIndexMetricsV2, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CorrelatedActivityId, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ForceQueryScan, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.OptimisticDirectExecute, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TraceParent, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TraceState, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.RemoteStorageType, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ShareThroughput, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulatePartitionStatistics, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ClientRetryAttemptCount, request); - - // target lsn for head requests. - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TargetLsn, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.FederationIdForAuth, request); - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ExcludeSystemProperties, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.FanoutOperationState, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.AllowTentativeWrites, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IncludeTentativeWrites, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PreserveFullContent, request); - - // Max polling interval and start full fidelity LSN (ETag) for change feed. - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsMaterializedViewBuild, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UseArchivalPartition, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, request); - - if (resourceOperation.operationType == OperationType.Batch) - { - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ShouldBatchContinueOnError, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchOrdered, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchAtomic, request); - } - - HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ForceSideBySideIndexMigration, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsClientEncrypted, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateOfferToAutopilot, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsInternalServerlessRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TruncateMergeLogRequest, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowRequestWithoutInstanceId, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateOfferStateToPending, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.OfferReplaceRURedistribution, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PriorityLevel, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsRecreate, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PruneCollectionSchemas, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsMigratedFixedCollection, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.HighPriorityForcedBackup, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, request); - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, request); - - Stream clonedStream = null; - if (request.Body != null) - { - clonedStream = request.CloneableBody.Clone(); - } - - // The StreamContent created below will own and dispose its underlying stream, but we may need to reuse the stream on the - // DocumentServiceRequest for future requests. Hence we need to clone without incurring copy cost, so that when - // HttpRequestMessage -> StreamContent -> MemoryStream all get disposed, the original stream will be left open. - switch (resourceOperation.operationType) - { - case OperationType.Create: - case OperationType.Batch: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.ExecuteJavaScript: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.Delete: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Delete; - break; - - case OperationType.Read: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Get; - break; - - case OperationType.ReadFeed: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); - if (clonedStream != null) - { - // changefeed request with sql query in request body - httpRequestMessage.Method = HttpMethod.Post; - httpRequestMessage.Content = new StreamContent(clonedStream); - HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); - } - else - { - httpRequestMessage.Method = HttpMethod.Get; - } - break; - - case OperationType.Replace: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Put; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.Patch: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = new HttpMethod("PATCH"); - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.QueryPlan: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); - break; - - case OperationType.Query: - case OperationType.SqlQuery: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); - break; - - case OperationType.Upsert: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.Head: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Head; - break; - - case OperationType.HeadFeed: - httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); - httpRequestMessage.Method = HttpMethod.Head; - break; - - case OperationType.MetadataCheckAccess: - httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - -#if !COSMOSCLIENT - // control operations - case OperationType.Pause: - case OperationType.Recycle: - case OperationType.Resume: - case OperationType.Stop: - case OperationType.Crash: - case OperationType.ForceConfigRefresh: - case OperationType.MasterInitiatedProgressCoordination: - httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); - httpRequestMessage.Method = HttpMethod.Post; - break; - - case OperationType.ServiceReservation: - case OperationType.GetFederationConfigurations: - case OperationType.GetStorageServiceConfigurations: - case OperationType.XPDatabaseAccountMetaData: - httpRequestMessage.RequestUri = physicalAddress; - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.GetDatabaseAccountConfigurations: - HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.RequestHopCount, request); - httpRequestMessage.RequestUri = physicalAddress; - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.GetDekProperties: - httpRequestMessage.RequestUri = physicalAddress; - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; - - case OperationType.ReadReplicaFromMasterPartition: - case OperationType.ReadReplicaFromServerPartition: - httpRequestMessage.RequestUri = physicalAddress; - httpRequestMessage.Method = HttpMethod.Get; - break; - - case OperationType.GetStorageAccountKey: - case OperationType.GetStorageAccountSas: - httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - - break; - - case OperationType.ReportThroughputUtilization: - case OperationType.BatchReportThroughputUtilization: - case OperationType.ControllerBatchReportCharges: - case OperationType.ControllerBatchGetOutput: - case OperationType.ControllerBatchAutoscaleRUsConsumption: - case OperationType.ControllerBatchGetAutoscaleAggregateOutput: - httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); - httpRequestMessage.Method = HttpMethod.Post; - Debug.Assert(clonedStream != null); - httpRequestMessage.Content = new StreamContent(clonedStream); - break; -#endif - - default: - DefaultTrace.TraceError("Operation type {0} not found", resourceOperation.operationType); - Debug.Assert(false, "Unsupported operation type"); - throw new NotFoundException(); - } - - return httpRequestMessage; - } - - internal static Uri GetSystemResourceUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) - { - switch (resourceType) - { -#if !COSMOSCLIENT - case ResourceType.ServiceFabricService: - case ResourceType.DatabaseAccount: - return physicalAddress; -#endif - - default: - Debug.Assert(false, "Unexpected resource type: " + resourceType); - throw new NotFoundException(); - } - } - - internal static Uri GetResourceFeedUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) - { - switch (resourceType) - { - case ResourceType.Attachment: - return HttpTransportClient.GetAttachmentFeedUri(physicalAddress, request); - case ResourceType.Collection: - return HttpTransportClient.GetCollectionFeedUri(physicalAddress, request); - case ResourceType.Conflict: - return HttpTransportClient.GetConflictFeedUri(physicalAddress, request); - case ResourceType.Database: - return HttpTransportClient.GetDatabaseFeedUri(physicalAddress); - case ResourceType.Document: - return HttpTransportClient.GetDocumentFeedUri(physicalAddress, request); - case ResourceType.Permission: - return HttpTransportClient.GetPermissionFeedUri(physicalAddress, request); - case ResourceType.StoredProcedure: - return HttpTransportClient.GetStoredProcedureFeedUri(physicalAddress, request); - case ResourceType.Trigger: - return HttpTransportClient.GetTriggerFeedUri(physicalAddress, request); - case ResourceType.User: - return HttpTransportClient.GetUserFeedUri(physicalAddress, request); - case ResourceType.ClientEncryptionKey: - return HttpTransportClient.GetClientEncryptionKeyFeedUri(physicalAddress, request); - case ResourceType.UserDefinedType: - return HttpTransportClient.GetUserDefinedTypeFeedUri(physicalAddress, request); - case ResourceType.UserDefinedFunction: - return HttpTransportClient.GetUserDefinedFunctionFeedUri(physicalAddress, request); - case ResourceType.Schema: - return HttpTransportClient.GetSchemaFeedUri(physicalAddress, request); - case ResourceType.Offer: - return HttpTransportClient.GetOfferFeedUri(physicalAddress, request); - case ResourceType.Snapshot: - return HttpTransportClient.GetSnapshotFeedUri(physicalAddress, request); - case ResourceType.RoleDefinition: - return HttpTransportClient.GetRoleDefinitionFeedUri(physicalAddress, request); - case ResourceType.RoleAssignment: - return HttpTransportClient.GetRoleAssignmentFeedUri(physicalAddress, request); - case ResourceType.EncryptionScope: - return HttpTransportClient.GetEncryptionScopeFeedUri(physicalAddress, request); - case ResourceType.AuthPolicyElement: - return HttpTransportClient.GetAuthPolicyElementFeedUri(physicalAddress, request); - case ResourceType.SystemDocument: - return HttpTransportClient.GetSystemDocumentFeedUri(physicalAddress, request); - case ResourceType.PartitionedSystemDocument: - return HttpTransportClient.GetPartitionedSystemDocumentFeedUri(physicalAddress, request); - case ResourceType.PartitionKeyRange: - return HttpTransportClient.GetPartitionedKeyRangeFeedUri(physicalAddress, request); - case ResourceType.PartitionKey: - return HttpTransportClient.GetPartitionKeyFeedUri(physicalAddress, request); -#if !COSMOSCLIENT - case ResourceType.Module: - case ResourceType.ModuleCommand: - case ResourceType.TransportControlCommand: - case ResourceType.Record: - case ResourceType.Replica: - Debug.Assert(false, "Unexpected resource type: " + resourceType); - throw new NotFoundException(); -#endif - - default: - Debug.Assert(false, "Unexpected resource type: " + resourceType); - throw new NotFoundException(); - } - } - - internal static Uri GetResourceEntryUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) - { - switch (resourceType) - { - case ResourceType.Attachment: - return HttpTransportClient.GetAttachmentEntryUri(physicalAddress, request); - case ResourceType.Collection: - return HttpTransportClient.GetCollectionEntryUri(physicalAddress, request); - case ResourceType.Conflict: - return HttpTransportClient.GetConflictEntryUri(physicalAddress, request); - case ResourceType.Database: - return HttpTransportClient.GetDatabaseEntryUri(physicalAddress, request); - case ResourceType.Document: - return HttpTransportClient.GetDocumentEntryUri(physicalAddress, request); - case ResourceType.Permission: - return HttpTransportClient.GetPermissionEntryUri(physicalAddress, request); - case ResourceType.StoredProcedure: - return HttpTransportClient.GetStoredProcedureEntryUri(physicalAddress, request); - case ResourceType.Trigger: - return HttpTransportClient.GetTriggerEntryUri(physicalAddress, request); - case ResourceType.User: - return HttpTransportClient.GetUserEntryUri(physicalAddress, request); - case ResourceType.ClientEncryptionKey: - return HttpTransportClient.GetClientEncryptionKeyEntryUri(physicalAddress, request); - case ResourceType.UserDefinedType: - return HttpTransportClient.GetUserDefinedTypeEntryUri(physicalAddress, request); - case ResourceType.UserDefinedFunction: - return HttpTransportClient.GetUserDefinedFunctionEntryUri(physicalAddress, request); - case ResourceType.Schema: - return HttpTransportClient.GetSchemaEntryUri(physicalAddress, request); - case ResourceType.Offer: - return HttpTransportClient.GetOfferEntryUri(physicalAddress, request); - case ResourceType.Snapshot: - return HttpTransportClient.GetSnapshotEntryUri(physicalAddress, request); - case ResourceType.RoleDefinition: - return HttpTransportClient.GetRoleDefinitionEntryUri(physicalAddress, request); - case ResourceType.RoleAssignment: - return HttpTransportClient.GetRoleAssignmentEntryUri(physicalAddress, request); - case ResourceType.EncryptionScope: - return HttpTransportClient.GetEncryptionScopeEntryUri(physicalAddress, request); - case ResourceType.AuthPolicyElement: - return HttpTransportClient.GetAuthPolicyElementEntryUri(physicalAddress, request); - case ResourceType.InteropUser: - return HttpTransportClient.GetInteropUserEntryUri(physicalAddress, request); - case ResourceType.SystemDocument: - return HttpTransportClient.GetSystemDocumentEntryUri(physicalAddress, request); - case ResourceType.PartitionedSystemDocument: - return HttpTransportClient.GetPartitionedSystemDocumentEntryUri(physicalAddress, request); - case ResourceType.PartitionKeyRange: - return HttpTransportClient.GetPartitionedKeyRangeEntryUri(physicalAddress, request); - case ResourceType.PartitionKey: - return HttpTransportClient.GetPartitioKeyEntryUri(physicalAddress, request); - -#if !COSMOSCLIENT - case ResourceType.Replica: - return HttpTransportClient.GetRootFeedUri(physicalAddress); - - case ResourceType.Module: - case ResourceType.ModuleCommand: - case ResourceType.TransportControlCommand: -#endif - case ResourceType.Record: - - Debug.Assert(false, "Unexpected resource type: " + resourceType); - throw new NotFoundException(); - - default: - Debug.Assert(false, "Unexpected resource type: " + resourceType); - throw new NotFoundException(); - } - } - - private static Uri GetRootFeedUri(Uri baseAddress) - { - return baseAddress; - } - - internal static Uri GetRootOperationUri(Uri baseAddress, OperationType operationType) - { - return new Uri(baseAddress, PathsHelper.GenerateRootOperationPath(operationType)); - } - - private static Uri GetDatabaseFeedUri(Uri baseAddress) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Database, string.Empty, true)); - } - - private static Uri GetDatabaseEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Database, request, false)); - } - - private static Uri GetCollectionFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Collection, request, true)); - } - - private static Uri GetStoredProcedureFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.StoredProcedure, request, true)); - } - - private static Uri GetTriggerFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Trigger, request, true)); - } - - private static Uri GetUserDefinedFunctionFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedFunction, request, true)); - } - - private static Uri GetCollectionEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Collection, request, false)); - } - - private static Uri GetStoredProcedureEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.StoredProcedure, request, false)); - } - - private static Uri GetTriggerEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Trigger, request, false)); - } - - private static Uri GetUserDefinedFunctionEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedFunction, request, false)); - } - - private static Uri GetDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Document, request, true)); - } - - private static Uri GetDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Document, request, false)); - } - - private static Uri GetConflictFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Conflict, request, true)); - } - - private static Uri GetConflictEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Conflict, request, false)); - } - - private static Uri GetAttachmentFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Attachment, request, true)); - } - - private static Uri GetAttachmentEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Attachment, request, false)); - } - - private static Uri GetUserFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.User, request, true)); - } - - private static Uri GetUserEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.User, request, false)); - } - - private static Uri GetClientEncryptionKeyFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.ClientEncryptionKey, request, true)); - } - - private static Uri GetClientEncryptionKeyEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.ClientEncryptionKey, request, false)); - } - - private static Uri GetUserDefinedTypeFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedType, request, true)); - } - - private static Uri GetUserDefinedTypeEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedType, request, false)); - } - - private static Uri GetPermissionFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Permission, request, true)); - } - - private static Uri GetPermissionEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Permission, request, false)); - } - - private static Uri GetOfferFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Offer, request, true)); - } - - private static Uri GetOfferEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Offer, request, false)); - } - - private static Uri GetSchemaFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Schema, request, true)); - } - - private static Uri GetSchemaEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Schema, request, false)); - } - - private static Uri GetSnapshotFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Snapshot, request, true)); - } - - private static Uri GetSnapshotEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Snapshot, request, false)); - } - - private static Uri GetRoleDefinitionFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleDefinition, request, isFeed: true)); - } - - private static Uri GetRoleDefinitionEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleDefinition, request, isFeed: false)); - } - - private static Uri GetRoleAssignmentFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleAssignment, request, isFeed: true)); - } - - private static Uri GetRoleAssignmentEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleAssignment, request, isFeed: false)); - } - - private static Uri GetEncryptionScopeFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.EncryptionScope, request, isFeed: true)); - } - - private static Uri GetEncryptionScopeEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.EncryptionScope, request, isFeed: false)); - } - - private static Uri GetAuthPolicyElementFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.AuthPolicyElement, request, isFeed: true)); - } - - private static Uri GetAuthPolicyElementEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.AuthPolicyElement, request, isFeed: false)); - } - - private static Uri GetInteropUserEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.InteropUser, request, isFeed: false)); - } - - private static Uri GetSystemDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.SystemDocument, request, isFeed: true)); - } - - private static Uri GetSystemDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.SystemDocument, request, isFeed: false)); - } - - private static Uri GetPartitionedSystemDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionedSystemDocument, request, isFeed: true)); - } - - private static Uri GetPartitionedKeyRangeFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKeyRange, request, isFeed: true)); - } - - private static Uri GetPartitionedKeyRangeEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKeyRange, request, isFeed: false)); - } - - private static Uri GetPartitioKeyEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKey, request, isFeed: false)); - } - - private static Uri GetPartitionedSystemDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionedSystemDocument, request, isFeed: false)); - } - - private static Uri GetPartitionKeyFeedUri(Uri baseAddress, DocumentServiceRequest request) - { - return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKey, request, isFeed: true)); - } - - public static Task ProcessHttpResponse(string resourceAddress, string activityId, HttpResponseMessage response, Uri physicalAddress, DocumentServiceRequest request) - { - if (response == null) - { - InternalServerErrorException exception = - new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.InvalidBackendResponse), - physicalAddress); - exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, - activityId); - exception.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - throw exception; - } - - // If the status code is < 300 or 304 NotModified (we treat not modified as success) then it means that it's a success code and shouldn't throw. - if (response.IsSuccessStatusCode || response.StatusCode == HttpStatusCode.NotModified) - { - return HttpTransportClient.CreateStoreResponseFromHttpResponse(response); - } - else - { - return HttpTransportClient.CreateErrorResponseFromHttpResponse(resourceAddress, activityId, response, request); - } - } - - private static async Task CreateErrorResponseFromHttpResponse( - string resourceAddress, - string activityId, - HttpResponseMessage response, - DocumentServiceRequest request) - { - using (response) - { - HttpStatusCode statusCode = response.StatusCode; - - string errorMessage = await TransportClient.GetErrorResponseAsync(response); - long responseLSN = -1; - IEnumerable lsnValues; - if (response.Headers.TryGetValues(WFConstants.BackendHeaders.LSN, out lsnValues)) - { - string temp = lsnValues.FirstOrDefault(); - long.TryParse(temp, NumberStyles.Integer, CultureInfo.InvariantCulture, out responseLSN); - } - - string responsePartitionKeyRangeId = null; - IEnumerable partitionKeyRangeIdValues; - if (response.Headers.TryGetValues(WFConstants.BackendHeaders.PartitionKeyRangeId, out partitionKeyRangeIdValues)) - { - responsePartitionKeyRangeId = partitionKeyRangeIdValues.FirstOrDefault(); - } - - DocumentClientException exception; - - switch (statusCode) - { - case HttpStatusCode.Unauthorized: - exception = new UnauthorizedException( - string.Format( - CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Unauthorized : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case HttpStatusCode.Forbidden: - exception = new ForbiddenException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Forbidden : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case HttpStatusCode.NotFound: - // HTTP.SYS returns NotFound (404) if the URI - // is not registered. This is really an indication that - // the replica which registered the URI is not - // available at the server. We detect this case by - // the presence of Content-Type header in the response - // and map it to HTTP Gone (410), which is the more - // appropriate response for this case. - if (response.Content != null && response.Content.Headers != null && response.Content.Headers.ContentType != null && - !string.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType) && - response.Content.Headers.ContentType.MediaType.StartsWith(RuntimeConstants.MediaTypes.TextHtml, StringComparison.OrdinalIgnoreCase)) - { - // Have the request URL in the exception message for debugging purposes. - exception = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - SubStatusCodes.Unknown, - response.RequestMessage.RequestUri) - { - LSN = responseLSN, - PartitionKeyRangeId = responsePartitionKeyRangeId - }; - exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, - activityId); - - break; - } - else - { - if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) - { - return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); - } - - exception = new NotFoundException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.NotFound : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - - case HttpStatusCode.BadRequest: - exception = new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.BadRequest : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case HttpStatusCode.MethodNotAllowed: - exception = new MethodNotAllowedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.MethodNotAllowed : errorMessage), - null, - response.Headers, - response.RequestMessage.RequestUri); - break; - - case HttpStatusCode.Gone: - { -#if NETFX - if (PerfCounters.Counters.RoutingFailures != null) - { - PerfCounters.Counters.RoutingFailures.Increment(); - } -#endif - TransportClient.LogGoneException(response.RequestMessage.RequestUri, activityId); - - uint nSubStatus = HttpTransportClient.GetSubsStatusFromHeader(response); - - if ((SubStatusCodes)nSubStatus == SubStatusCodes.NameCacheIsStale) - { - exception = new InvalidPartitionException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.PartitionKeyRangeGone) - { - exception = new PartitionKeyRangeGoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingSplit) - { - exception = new PartitionKeyRangeIsSplittingException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingPartitionMigration) - { - exception = new PartitionIsMigratingException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - else - { - // Have the request URL in the exception message for debugging purposes. - exception = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - response.Headers, - (nSubStatus == 0) ? SubStatusCodes.ServerGenerated410 : null, - response.RequestMessage.RequestUri); - - exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, - activityId); - break; - } - } - - case HttpStatusCode.Conflict: - { - if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) - { - return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); - } - - exception = new ConflictException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.EntityAlreadyExists : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - - case HttpStatusCode.PreconditionFailed: - { - if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) - { - return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); - } - - exception = new PreconditionFailedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.PreconditionFailed : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - - case HttpStatusCode.RequestEntityTooLarge: - exception = new RequestEntityTooLargeException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.Format(CultureInfo.CurrentUICulture, - RMResources.RequestEntityTooLarge, - HttpConstants.HttpHeaders.PageSize)), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case (HttpStatusCode)423: - exception = new LockedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.Locked : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case HttpStatusCode.ServiceUnavailable: - uint subStatus = HttpTransportClient.GetSubsStatusFromHeader(response); - if (!string.IsNullOrEmpty(errorMessage)) - { - exception = new ServiceUnavailableException( - message: string.Format(CultureInfo.CurrentUICulture, RMResources.ExceptionMessage, errorMessage), - headers: response.Headers, - subStatusCode: (subStatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value - requestUri: response.RequestMessage.RequestUri); - } - else - { - exception = ServiceUnavailableException.Create( - (subStatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value - headers: response.Headers, - requestUri: response.RequestMessage.RequestUri); - } - break; - - case HttpStatusCode.RequestTimeout: - exception = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.RequestTimeout : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case (HttpStatusCode)StatusCodes.RetryWith: - exception = new RetryWithException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.RetryWith : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - case (HttpStatusCode)StatusCodes.TooManyRequests: - if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) - { - return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); - } - - exception = - new RequestRateTooLargeException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.TooManyRequests : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - - IEnumerable values = null; - try - { - values = response.Headers.GetValues(HttpConstants.HttpHeaders.RetryAfterInMilliseconds); - } - catch (InvalidOperationException) - { - DefaultTrace.TraceWarning("RequestRateTooLargeException being thrown without RetryAfter."); - } - - if (values != null && values.Any()) - { - exception.Headers.Set(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, values.First()); - } - - break; - - case HttpStatusCode.InternalServerError: - exception = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.InternalServerError : errorMessage), - response.Headers, - response.RequestMessage.RequestUri); - break; - - default: - DefaultTrace.TraceCritical("Unrecognized status code {0} returned by backend. ActivityId {1}", statusCode, activityId); - TransportClient.LogException(response.RequestMessage.RequestUri, activityId); - exception = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.InvalidBackendResponse), - response.Headers, - response.RequestMessage.RequestUri); - break; - } - - exception.LSN = responseLSN; - exception.PartitionKeyRangeId = responsePartitionKeyRangeId; - exception.ResourceAddress = resourceAddress; - throw exception; - } - } - - private static uint GetSubsStatusFromHeader(HttpResponseMessage response) - { - uint nSubStatus = 0; - try - { - IEnumerable valueSubStatus = response.Headers.GetValues(WFConstants.BackendHeaders.SubStatus); - if (valueSubStatus != null && valueSubStatus.Any()) - { - if (!uint.TryParse(valueSubStatus.First(), NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) - { - throw new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.InvalidBackendResponse), - response.Headers, - response.RequestMessage.RequestUri); - } - } - } - catch (InvalidOperationException) - { - DefaultTrace.TraceInformation("SubStatus doesn't exist in the header"); - } - - return nSubStatus; - } - - internal static string GetHeader(string[] names, string[] values, string name) - { - for (int idx = 0; idx < names.Length; idx++) - { - if (string.Equals(names[idx], name, StringComparison.Ordinal)) - { - return values[idx]; - } - } - - return null; - } - - public async static Task CreateStoreResponseFromHttpResponse(HttpResponseMessage responseMessage, bool includeContent = true) - { - StoreResponse response = new StoreResponse() - { - Headers = new DictionaryNameValueCollection(StringComparer.OrdinalIgnoreCase) - }; - - using (responseMessage) - { - foreach (KeyValuePair> kvPair in responseMessage.Headers) - { - if (string.Compare(kvPair.Key, HttpConstants.HttpHeaders.OwnerFullName, StringComparison.Ordinal) == 0) - { - response.Headers[kvPair.Key] = Uri.UnescapeDataString(kvPair.Value.SingleOrDefault()); - } - else - { - response.Headers[kvPair.Key] = kvPair.Value.SingleOrDefault(); - } - } - - response.Status = (int)responseMessage.StatusCode; - - if (includeContent && responseMessage.Content != null) - { - Stream bufferredStream = new MemoryStream(); - - await responseMessage.Content.CopyToAsync(bufferredStream); - bufferredStream.Position = 0; - - response.ResponseBody = bufferredStream; - } - return response; - } - } - } -} +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Net; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.Routing; + + internal sealed class HttpTransportClient : TransportClient + { + private readonly HttpClient httpClient; + private readonly ICommunicationEventSource eventSource; + + public const string Match = "Match"; + + public HttpTransportClient( + int requestTimeout, + ICommunicationEventSource eventSource, + UserAgentContainer userAgent = null, + int idleTimeoutInSeconds = -1, + HttpMessageHandler messageHandler = null) + { +#if NETFX + if (idleTimeoutInSeconds > 0) + { + ServicePointManager.MaxServicePointIdleTime = idleTimeoutInSeconds; + ServicePointManager.SetTcpKeepAlive(true, keepAliveTime: 30000, keepAliveInterval: 1000); + } +#endif + + if (messageHandler != null) + { + this.httpClient = new HttpClient(messageHandler); + } + else + { + this.httpClient = new HttpClient(); + } + + this.httpClient.Timeout = TimeSpan.FromSeconds(requestTimeout); + this.httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; + + // Set requested API version header for version enforcement. + this.httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version, + HttpConstants.Versions.CurrentVersion); + + if (userAgent == null) + { + userAgent = new UserAgentContainer(); + } + + this.httpClient.AddUserAgentHeader(userAgent); + + this.httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Accept, RuntimeConstants.MediaTypes.Json); + + this.eventSource = eventSource; + } + + public override void Dispose() + { + base.Dispose(); + + if (this.httpClient != null) + { + this.httpClient.Dispose(); + } + } + + private void BeforeRequest(Guid activityId, Uri uri, ResourceType resourceType, HttpRequestHeaders requestHeaders) + { +#if NETFX + + if (PerfCounters.Counters.BackendActiveRequests != null) + { + PerfCounters.Counters.BackendActiveRequests.Increment(); + } + + if (PerfCounters.Counters.BackendRequestsPerSec != null) + { + PerfCounters.Counters.BackendRequestsPerSec.Increment(); + } +#endif + + this.eventSource.Request( + activityId, + Guid.Empty, + uri.ToString(), + resourceType.ToResourceTypeString(), + requestHeaders); + } + + private void AfterRequest(Guid activityId, + HttpStatusCode statusCode, + double durationInMilliSeconds, + HttpResponseHeaders responseHeaders) + { +#if NETFX + if (PerfCounters.Counters.BackendActiveRequests != null) + { + PerfCounters.Counters.BackendActiveRequests.Decrement(); + } +#endif + + this.eventSource.Response( + activityId, + Guid.Empty, + (short)statusCode, + durationInMilliSeconds, + responseHeaders); + } + + internal override async Task InvokeStoreAsync( + Uri physicalAddress, + ResourceOperation resourceOperation, + DocumentServiceRequest request) + { + Guid activityId = Trace.CorrelationManager.ActivityId; + Debug.Assert(activityId != Guid.Empty); + + INameValueCollection responseHeaders = new DictionaryNameValueCollection(); + responseHeaders.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + + if (!request.IsBodySeekableClonableAndCountable) + { + throw new InternalServerErrorException(RMResources.InternalServerError, responseHeaders); + } + +#if !COSMOSCLIENT + if (resourceOperation.operationType == OperationType.Recreate) + { + DefaultTrace.TraceCritical("Received Recreate request on Http client"); + throw new InternalServerErrorException(RMResources.InternalServerError, responseHeaders); + } +#endif + + using (HttpRequestMessage requestMessage = this.PrepareHttpMessage( + activityId, + physicalAddress, + resourceOperation, + request)) + { + HttpResponseMessage responseMessage = null; + DateTime sendTimeUtc = DateTime.UtcNow; + try + { + this.BeforeRequest( + activityId, + requestMessage.RequestUri, + request.ResourceType, + requestMessage.Headers); + + responseMessage = await this.httpClient.SendAsync(requestMessage, + HttpCompletionOption.ResponseHeadersRead); + } + catch (Exception exception) + { + Trace.CorrelationManager.ActivityId = activityId; + if (WebExceptionUtility.IsWebExceptionRetriable(exception)) + { + DefaultTrace.TraceInformation("Received retriable exception {0} " + + "sending the request to {1}, will reresolve the address " + + "send time UTC: {2}", + exception, + physicalAddress, + sendTimeUtc); + + GoneException goneException = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + exception, + SubStatusCodes.TransportGenerated410, + null, + physicalAddress.ToString()); + + throw goneException; + } + else if (request.IsReadOnlyRequest) + { + DefaultTrace.TraceInformation("Received exception {0} on readonly request" + + "sending the request to {1}, will reresolve the address " + + "send time UTC: {2}", + exception, + physicalAddress, + sendTimeUtc); + + GoneException goneException = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + exception, + SubStatusCodes.TransportGenerated410, + null, + physicalAddress.ToString()); + + throw goneException; + } + else + { + // We can't throw a GoneException here because it will cause retry and we don't + // know if the request failed before or after the message got sent to the server. + // So in order to avoid duplicating the request we will not retry. + // TODO: a possible solution for this is to add the ability to send a request to the server + // to check if the previous request was received or not and act accordingly. + ServiceUnavailableException serviceUnavailableException = ServiceUnavailableException.Create( + SubStatusCodes.Unknown, + exception, + null, + physicalAddress); + serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.WriteRequestTriggerAddressRefresh, "1"); + throw serviceUnavailableException; + } + } + finally + { + DateTime receivedTimeUtc = DateTime.UtcNow; + double durationInMilliSeconds = (receivedTimeUtc - sendTimeUtc).TotalMilliseconds; + + this.AfterRequest( + activityId, + responseMessage != null ? responseMessage.StatusCode : 0, + durationInMilliSeconds, + responseMessage != null ? responseMessage.Headers : null); + } + + using (responseMessage) + { + return await HttpTransportClient.ProcessHttpResponse(request.ResourceAddress, activityId.ToString(), responseMessage, physicalAddress, request); + } + } + } + + private static void AddHeader(HttpRequestHeaders requestHeaders, string headerName, DocumentServiceRequest request) + { + string headerValue = request.Headers[headerName]; + if (!string.IsNullOrEmpty(headerValue)) + { + requestHeaders.Add(headerName, headerValue); + } + } + + private static void AddHeader(HttpContentHeaders requestHeaders, string headerName, DocumentServiceRequest request) + { + string headerValue = request.Headers[headerName]; + if (!string.IsNullOrEmpty(headerValue)) + { + requestHeaders.Add(headerName, headerValue); + } + } + + private static void AddHeader(HttpRequestHeaders requestHeaders, string headerName, string headerValue) + { + if (!string.IsNullOrEmpty(headerValue)) + { + requestHeaders.Add(headerName, headerValue); + } + } + + private string GetMatch(DocumentServiceRequest request, ResourceOperation resourceOperation) + { + switch (resourceOperation.operationType) + { + case OperationType.Delete: + case OperationType.ExecuteJavaScript: + case OperationType.Replace: + case OperationType.Patch: + case OperationType.Upsert: + return request.Headers[HttpConstants.HttpHeaders.IfMatch]; + + case OperationType.Read: + case OperationType.ReadFeed: + return request.Headers[HttpConstants.HttpHeaders.IfNoneMatch]; + + default: + return null; + } + } + + [SuppressMessage("Microsoft.Reliability", "CA2000: DisposeObjectsBeforeLosingScope", Justification = "Disposable object returned by method")] + private HttpRequestMessage PrepareHttpMessage( + Guid activityId, + Uri physicalAddress, + ResourceOperation resourceOperation, + DocumentServiceRequest request) + { + HttpRequestMessage httpRequestMessage = new HttpRequestMessage(); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Version, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UserAgent, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PageSize, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PreTriggerInclude, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PreTriggerExclude, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PostTriggerInclude, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PostTriggerExclude, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Authorization, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IndexingDirective, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateCollectionDirective, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ConsistencyLevel, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SessionToken, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Prefer, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ResourceTokenExpiry, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableScanInQuery, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanCharge, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanThrottle, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableLogging, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsReadOnlyScript, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ContentSerializationFormat, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SupportedSerializationFormats, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Continuation, request.Continuation); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ActivityId, activityId.ToString()); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PartitionKey, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PartitionKeyRangeId, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableCrossPartitionQuery, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SDKSupportedCapabilities, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ReadFeedKeyType, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.StartEpk, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EndEpk, request); + + string dateHeader = Helpers.GetDateHeader(request.Headers); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.XDate, dateHeader); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpTransportClient.Match, this.GetMatch(request, resourceOperation)); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IfModifiedSince, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.A_IM, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, request); + + if (!request.IsNameBased) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ResourceId, request.ResourceId); + } + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.EntityId, request.EntityId); + + string fanoutRequestHeader = request.Headers[WFConstants.BackendHeaders.IsFanoutRequest]; + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.IsFanoutRequest, fanoutRequestHeader); + + if (request.ResourceType == ResourceType.Collection) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionPartitionIndex, request.Headers[WFConstants.BackendHeaders.CollectionPartitionIndex]); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionServiceIndex, request.Headers[WFConstants.BackendHeaders.CollectionServiceIndex]); + } + + if (request.Headers[WFConstants.BackendHeaders.RequestedCollectionType] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.RequestedCollectionType, request.Headers[WFConstants.BackendHeaders.RequestedCollectionType]); + } + + if (request.Headers[WFConstants.BackendHeaders.BindReplicaDirective] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.BindReplicaDirective, request.Headers[WFConstants.BackendHeaders.BindReplicaDirective]); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PrimaryMasterKey, request.Headers[WFConstants.BackendHeaders.PrimaryMasterKey]); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.SecondaryMasterKey, request.Headers[WFConstants.BackendHeaders.SecondaryMasterKey]); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PrimaryReadonlyKey, request.Headers[WFConstants.BackendHeaders.PrimaryReadonlyKey]); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.SecondaryReadonlyKey, request.Headers[WFConstants.BackendHeaders.SecondaryReadonlyKey]); + } + + if (request.Headers[HttpConstants.HttpHeaders.CanOfferReplaceComplete] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CanOfferReplaceComplete, request.Headers[HttpConstants.HttpHeaders.CanOfferReplaceComplete]); + } + + if (request.Headers[HttpConstants.HttpHeaders.IsThroughputCapRequest] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsThroughputCapRequest, request.Headers[HttpConstants.HttpHeaders.IsThroughputCapRequest]); + } + + if (request.Headers[WFConstants.BackendHeaders.PopulateCapacityType] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PopulateCapacityType, request.Headers[WFConstants.BackendHeaders.PopulateCapacityType]); + } + + if (request.Headers[WFConstants.BackendHeaders.ClientIpAddress] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ClientIpAddress, request.Headers[WFConstants.BackendHeaders.ClientIpAddress]); + } + + if (request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.IsRequestNotAuthorized, request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized]); + } + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsAutoScaleRequest, request); + + //Query + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsQuery, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.Query, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsQueryPlanRequest, request); + + // Upsert + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsUpsert, request); + + // SupportSpatialLegacyCoordinates + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PartitionCount, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CollectionRid, request); + + // Filter by schema + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.FilterBySchemaResourceId, request); + + // UsePolygonsSmallerThanAHemisphere + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.GatewaySignature, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateQuotaInfo, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateQueryMetrics, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateIndexMetrics, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateIndexMetricsV2, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.CorrelatedActivityId, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ForceQueryScan, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.OptimisticDirectExecute, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TraceParent, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TraceState, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.RemoteStorageType, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ShareThroughput, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulatePartitionStatistics, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ClientRetryAttemptCount, request); + + // target lsn for head requests. + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TargetLsn, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.FederationIdForAuth, request); + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ExcludeSystemProperties, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.FanoutOperationState, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.AllowTentativeWrites, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IncludeTentativeWrites, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PreserveFullContent, request); + + // Max polling interval and start full fidelity LSN (ETag) for change feed. + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsMaterializedViewBuild, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UseArchivalPartition, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, request); + + if (resourceOperation.operationType == OperationType.Batch) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ShouldBatchContinueOnError, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchOrdered, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsBatchAtomic, request); + } + + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ForceSideBySideIndexMigration, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsClientEncrypted, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateOfferToAutopilot, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsInternalServerlessRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.TruncateMergeLogRequest, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowRequestWithoutInstanceId, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateOfferStateToPending, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.OfferReplaceRURedistribution, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PriorityLevel, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsRecreate, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.PruneCollectionSchemas, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsMigratedFixedCollection, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.HighPriorityForcedBackup, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PopulateUserStrings, request); + + // Set the CollectionOperation TransactionId if present + // Currently only being done for SharedThroughputTransactionHandler in the collection create path + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.CosmosGatewayTransactionId, request.Headers[WFConstants.BackendHeaders.CosmosGatewayTransactionId]); + + Stream clonedStream = null; + if (request.Body != null) + { + clonedStream = request.CloneableBody.Clone(); + } + + // The StreamContent created below will own and dispose its underlying stream, but we may need to reuse the stream on the + // DocumentServiceRequest for future requests. Hence we need to clone without incurring copy cost, so that when + // HttpRequestMessage -> StreamContent -> MemoryStream all get disposed, the original stream will be left open. + switch (resourceOperation.operationType) + { + case OperationType.Create: + case OperationType.Batch: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.ExecuteJavaScript: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.Delete: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Delete; + break; + + case OperationType.Read: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Get; + break; + + case OperationType.ReadFeed: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); + if (clonedStream != null) + { + // changefeed request with sql query in request body + httpRequestMessage.Method = HttpMethod.Post; + httpRequestMessage.Content = new StreamContent(clonedStream); + HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); + } + else + { + httpRequestMessage.Method = HttpMethod.Get; + } + break; + + case OperationType.Replace: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Put; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.Patch: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = new HttpMethod("PATCH"); + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.QueryPlan: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); + break; + + case OperationType.Query: + case OperationType.SqlQuery: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + HttpTransportClient.AddHeader(httpRequestMessage.Content.Headers, HttpConstants.HttpHeaders.ContentType, request); + break; + + case OperationType.Upsert: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.Head: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceEntryUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Head; + break; + + case OperationType.HeadFeed: + httpRequestMessage.RequestUri = HttpTransportClient.GetResourceFeedUri(resourceOperation.resourceType, physicalAddress, request); + httpRequestMessage.Method = HttpMethod.Head; + break; + + case OperationType.MetadataCheckAccess: + httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + +#if !COSMOSCLIENT + // control operations + case OperationType.Pause: + case OperationType.Recycle: + case OperationType.Resume: + case OperationType.Stop: + case OperationType.Crash: + case OperationType.ForceConfigRefresh: + case OperationType.MasterInitiatedProgressCoordination: + httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); + httpRequestMessage.Method = HttpMethod.Post; + break; + + case OperationType.ServiceReservation: + case OperationType.GetFederationConfigurations: + case OperationType.GetStorageServiceConfigurations: + case OperationType.XPDatabaseAccountMetaData: + // IfModifiedSince and A_IM is already added above + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.ETag, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IfMatch, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IfNoneMatch, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IfUnmodifiedSince, request); + + httpRequestMessage.RequestUri = physicalAddress; + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.GetDatabaseAccountConfigurations: + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.RequestHopCount, request); + httpRequestMessage.RequestUri = physicalAddress; + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.GetDekProperties: + httpRequestMessage.RequestUri = physicalAddress; + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + + case OperationType.ReadReplicaFromMasterPartition: + case OperationType.ReadReplicaFromServerPartition: + httpRequestMessage.RequestUri = physicalAddress; + httpRequestMessage.Method = HttpMethod.Get; + break; + + case OperationType.GetStorageAccountKey: + case OperationType.GetStorageAccountSas: + httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + + break; + + case OperationType.ReportThroughputUtilization: + case OperationType.BatchReportThroughputUtilization: + case OperationType.ControllerBatchReportCharges: + case OperationType.ControllerBatchGetOutput: + case OperationType.ControllerBatchAutoscaleRUsConsumption: + case OperationType.ControllerBatchGetAutoscaleAggregateOutput: + httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; +#endif + + default: + DefaultTrace.TraceError("Operation type {0} not found", resourceOperation.operationType); + Debug.Assert(false, "Unsupported operation type"); + throw new NotFoundException(); + } + + return httpRequestMessage; + } + + internal static Uri GetSystemResourceUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) + { + switch (resourceType) + { +#if !COSMOSCLIENT + case ResourceType.ServiceFabricService: + case ResourceType.DatabaseAccount: + return physicalAddress; +#endif + + default: + Debug.Assert(false, "Unexpected resource type: " + resourceType); + throw new NotFoundException(); + } + } + + internal static Uri GetResourceFeedUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) + { + switch (resourceType) + { + case ResourceType.Attachment: + return HttpTransportClient.GetAttachmentFeedUri(physicalAddress, request); + case ResourceType.Collection: + return HttpTransportClient.GetCollectionFeedUri(physicalAddress, request); + case ResourceType.Conflict: + return HttpTransportClient.GetConflictFeedUri(physicalAddress, request); + case ResourceType.Database: + return HttpTransportClient.GetDatabaseFeedUri(physicalAddress); + case ResourceType.Document: + return HttpTransportClient.GetDocumentFeedUri(physicalAddress, request); + case ResourceType.Permission: + return HttpTransportClient.GetPermissionFeedUri(physicalAddress, request); + case ResourceType.StoredProcedure: + return HttpTransportClient.GetStoredProcedureFeedUri(physicalAddress, request); + case ResourceType.Trigger: + return HttpTransportClient.GetTriggerFeedUri(physicalAddress, request); + case ResourceType.User: + return HttpTransportClient.GetUserFeedUri(physicalAddress, request); + case ResourceType.ClientEncryptionKey: + return HttpTransportClient.GetClientEncryptionKeyFeedUri(physicalAddress, request); + case ResourceType.UserDefinedType: + return HttpTransportClient.GetUserDefinedTypeFeedUri(physicalAddress, request); + case ResourceType.UserDefinedFunction: + return HttpTransportClient.GetUserDefinedFunctionFeedUri(physicalAddress, request); + case ResourceType.Schema: + return HttpTransportClient.GetSchemaFeedUri(physicalAddress, request); + case ResourceType.Offer: + return HttpTransportClient.GetOfferFeedUri(physicalAddress, request); + case ResourceType.Snapshot: + return HttpTransportClient.GetSnapshotFeedUri(physicalAddress, request); + case ResourceType.RoleDefinition: + return HttpTransportClient.GetRoleDefinitionFeedUri(physicalAddress, request); + case ResourceType.RoleAssignment: + return HttpTransportClient.GetRoleAssignmentFeedUri(physicalAddress, request); + case ResourceType.EncryptionScope: + return HttpTransportClient.GetEncryptionScopeFeedUri(physicalAddress, request); + case ResourceType.AuthPolicyElement: + return HttpTransportClient.GetAuthPolicyElementFeedUri(physicalAddress, request); + case ResourceType.SystemDocument: + return HttpTransportClient.GetSystemDocumentFeedUri(physicalAddress, request); + case ResourceType.PartitionedSystemDocument: + return HttpTransportClient.GetPartitionedSystemDocumentFeedUri(physicalAddress, request); + case ResourceType.PartitionKeyRange: + return HttpTransportClient.GetPartitionedKeyRangeFeedUri(physicalAddress, request); + case ResourceType.PartitionKey: + return HttpTransportClient.GetPartitionKeyFeedUri(physicalAddress, request); +#if !COSMOSCLIENT + case ResourceType.Module: + case ResourceType.ModuleCommand: + case ResourceType.TransportControlCommand: + case ResourceType.Record: + case ResourceType.Replica: + Debug.Assert(false, "Unexpected resource type: " + resourceType); + throw new NotFoundException(); +#endif + + default: + Debug.Assert(false, "Unexpected resource type: " + resourceType); + throw new NotFoundException(); + } + } + + internal static Uri GetResourceEntryUri(ResourceType resourceType, Uri physicalAddress, DocumentServiceRequest request) + { + switch (resourceType) + { + case ResourceType.Attachment: + return HttpTransportClient.GetAttachmentEntryUri(physicalAddress, request); + case ResourceType.Collection: + return HttpTransportClient.GetCollectionEntryUri(physicalAddress, request); + case ResourceType.Conflict: + return HttpTransportClient.GetConflictEntryUri(physicalAddress, request); + case ResourceType.Database: + return HttpTransportClient.GetDatabaseEntryUri(physicalAddress, request); + case ResourceType.Document: + return HttpTransportClient.GetDocumentEntryUri(physicalAddress, request); + case ResourceType.Permission: + return HttpTransportClient.GetPermissionEntryUri(physicalAddress, request); + case ResourceType.StoredProcedure: + return HttpTransportClient.GetStoredProcedureEntryUri(physicalAddress, request); + case ResourceType.Trigger: + return HttpTransportClient.GetTriggerEntryUri(physicalAddress, request); + case ResourceType.User: + return HttpTransportClient.GetUserEntryUri(physicalAddress, request); + case ResourceType.ClientEncryptionKey: + return HttpTransportClient.GetClientEncryptionKeyEntryUri(physicalAddress, request); + case ResourceType.UserDefinedType: + return HttpTransportClient.GetUserDefinedTypeEntryUri(physicalAddress, request); + case ResourceType.UserDefinedFunction: + return HttpTransportClient.GetUserDefinedFunctionEntryUri(physicalAddress, request); + case ResourceType.Schema: + return HttpTransportClient.GetSchemaEntryUri(physicalAddress, request); + case ResourceType.Offer: + return HttpTransportClient.GetOfferEntryUri(physicalAddress, request); + case ResourceType.Snapshot: + return HttpTransportClient.GetSnapshotEntryUri(physicalAddress, request); + case ResourceType.RoleDefinition: + return HttpTransportClient.GetRoleDefinitionEntryUri(physicalAddress, request); + case ResourceType.RoleAssignment: + return HttpTransportClient.GetRoleAssignmentEntryUri(physicalAddress, request); + case ResourceType.EncryptionScope: + return HttpTransportClient.GetEncryptionScopeEntryUri(physicalAddress, request); + case ResourceType.AuthPolicyElement: + return HttpTransportClient.GetAuthPolicyElementEntryUri(physicalAddress, request); + case ResourceType.InteropUser: + return HttpTransportClient.GetInteropUserEntryUri(physicalAddress, request); + case ResourceType.SystemDocument: + return HttpTransportClient.GetSystemDocumentEntryUri(physicalAddress, request); + case ResourceType.PartitionedSystemDocument: + return HttpTransportClient.GetPartitionedSystemDocumentEntryUri(physicalAddress, request); + case ResourceType.PartitionKeyRange: + return HttpTransportClient.GetPartitionedKeyRangeEntryUri(physicalAddress, request); + case ResourceType.PartitionKey: + return HttpTransportClient.GetPartitioKeyEntryUri(physicalAddress, request); + +#if !COSMOSCLIENT + case ResourceType.Replica: + return HttpTransportClient.GetRootFeedUri(physicalAddress); + + case ResourceType.Module: + case ResourceType.ModuleCommand: + case ResourceType.TransportControlCommand: +#endif + case ResourceType.Record: + + Debug.Assert(false, "Unexpected resource type: " + resourceType); + throw new NotFoundException(); + + default: + Debug.Assert(false, "Unexpected resource type: " + resourceType); + throw new NotFoundException(); + } + } + + private static Uri GetRootFeedUri(Uri baseAddress) + { + return baseAddress; + } + + internal static Uri GetRootOperationUri(Uri baseAddress, OperationType operationType) + { + return new Uri(baseAddress, PathsHelper.GenerateRootOperationPath(operationType)); + } + + private static Uri GetDatabaseFeedUri(Uri baseAddress) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Database, string.Empty, true)); + } + + private static Uri GetDatabaseEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Database, request, false)); + } + + private static Uri GetCollectionFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Collection, request, true)); + } + + private static Uri GetStoredProcedureFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.StoredProcedure, request, true)); + } + + private static Uri GetTriggerFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Trigger, request, true)); + } + + private static Uri GetUserDefinedFunctionFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedFunction, request, true)); + } + + private static Uri GetCollectionEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Collection, request, false)); + } + + private static Uri GetStoredProcedureEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.StoredProcedure, request, false)); + } + + private static Uri GetTriggerEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Trigger, request, false)); + } + + private static Uri GetUserDefinedFunctionEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedFunction, request, false)); + } + + private static Uri GetDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Document, request, true)); + } + + private static Uri GetDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Document, request, false)); + } + + private static Uri GetConflictFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Conflict, request, true)); + } + + private static Uri GetConflictEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Conflict, request, false)); + } + + private static Uri GetAttachmentFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Attachment, request, true)); + } + + private static Uri GetAttachmentEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Attachment, request, false)); + } + + private static Uri GetUserFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.User, request, true)); + } + + private static Uri GetUserEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.User, request, false)); + } + + private static Uri GetClientEncryptionKeyFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.ClientEncryptionKey, request, true)); + } + + private static Uri GetClientEncryptionKeyEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.ClientEncryptionKey, request, false)); + } + + private static Uri GetUserDefinedTypeFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedType, request, true)); + } + + private static Uri GetUserDefinedTypeEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.UserDefinedType, request, false)); + } + + private static Uri GetPermissionFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Permission, request, true)); + } + + private static Uri GetPermissionEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Permission, request, false)); + } + + private static Uri GetOfferFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Offer, request, true)); + } + + private static Uri GetOfferEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Offer, request, false)); + } + + private static Uri GetSchemaFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Schema, request, true)); + } + + private static Uri GetSchemaEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Schema, request, false)); + } + + private static Uri GetSnapshotFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Snapshot, request, true)); + } + + private static Uri GetSnapshotEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.Snapshot, request, false)); + } + + private static Uri GetRoleDefinitionFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleDefinition, request, isFeed: true)); + } + + private static Uri GetRoleDefinitionEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleDefinition, request, isFeed: false)); + } + + private static Uri GetRoleAssignmentFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleAssignment, request, isFeed: true)); + } + + private static Uri GetRoleAssignmentEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.RoleAssignment, request, isFeed: false)); + } + + private static Uri GetEncryptionScopeFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.EncryptionScope, request, isFeed: true)); + } + + private static Uri GetEncryptionScopeEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.EncryptionScope, request, isFeed: false)); + } + + private static Uri GetAuthPolicyElementFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.AuthPolicyElement, request, isFeed: true)); + } + + private static Uri GetAuthPolicyElementEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.AuthPolicyElement, request, isFeed: false)); + } + + private static Uri GetInteropUserEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.InteropUser, request, isFeed: false)); + } + + private static Uri GetSystemDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.SystemDocument, request, isFeed: true)); + } + + private static Uri GetSystemDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.SystemDocument, request, isFeed: false)); + } + + private static Uri GetPartitionedSystemDocumentFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionedSystemDocument, request, isFeed: true)); + } + + private static Uri GetPartitionedKeyRangeFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKeyRange, request, isFeed: true)); + } + + private static Uri GetPartitionedKeyRangeEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKeyRange, request, isFeed: false)); + } + + private static Uri GetPartitioKeyEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKey, request, isFeed: false)); + } + + private static Uri GetPartitionedSystemDocumentEntryUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionedSystemDocument, request, isFeed: false)); + } + + private static Uri GetPartitionKeyFeedUri(Uri baseAddress, DocumentServiceRequest request) + { + return new Uri(baseAddress, PathsHelper.GeneratePath(ResourceType.PartitionKey, request, isFeed: true)); + } + + public static Task ProcessHttpResponse(string resourceAddress, string activityId, HttpResponseMessage response, Uri physicalAddress, DocumentServiceRequest request) + { + if (response == null) + { + InternalServerErrorException exception = + new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.InvalidBackendResponse), + physicalAddress); + exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, + activityId); + exception.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + throw exception; + } + + // If the status code is < 300 or 304 NotModified (we treat not modified as success) then it means that it's a success code and shouldn't throw. + if (response.IsSuccessStatusCode || response.StatusCode == HttpStatusCode.NotModified) + { + return HttpTransportClient.CreateStoreResponseFromHttpResponse(response); + } + else + { + return HttpTransportClient.CreateErrorResponseFromHttpResponse(resourceAddress, activityId, response, request); + } + } + + private static async Task CreateErrorResponseFromHttpResponse( + string resourceAddress, + string activityId, + HttpResponseMessage response, + DocumentServiceRequest request) + { + using (response) + { + HttpStatusCode statusCode = response.StatusCode; + + string errorMessage = await TransportClient.GetErrorResponseAsync(response); + long responseLSN = -1; + IEnumerable lsnValues; + if (response.Headers.TryGetValues(WFConstants.BackendHeaders.LSN, out lsnValues)) + { + string temp = lsnValues.FirstOrDefault(); + long.TryParse(temp, NumberStyles.Integer, CultureInfo.InvariantCulture, out responseLSN); + } + + string responsePartitionKeyRangeId = null; + IEnumerable partitionKeyRangeIdValues; + if (response.Headers.TryGetValues(WFConstants.BackendHeaders.PartitionKeyRangeId, out partitionKeyRangeIdValues)) + { + responsePartitionKeyRangeId = partitionKeyRangeIdValues.FirstOrDefault(); + } + + DocumentClientException exception; + + switch (statusCode) + { + case HttpStatusCode.Unauthorized: + exception = new UnauthorizedException( + string.Format( + CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Unauthorized : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case HttpStatusCode.Forbidden: + exception = new ForbiddenException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Forbidden : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case HttpStatusCode.NotFound: + // HTTP.SYS returns NotFound (404) if the URI + // is not registered. This is really an indication that + // the replica which registered the URI is not + // available at the server. We detect this case by + // the presence of Content-Type header in the response + // and map it to HTTP Gone (410), which is the more + // appropriate response for this case. + if (response.Content != null && response.Content.Headers != null && response.Content.Headers.ContentType != null && + !string.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType) && + response.Content.Headers.ContentType.MediaType.StartsWith(RuntimeConstants.MediaTypes.TextHtml, StringComparison.OrdinalIgnoreCase)) + { + // Have the request URL in the exception message for debugging purposes. + exception = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + SubStatusCodes.Unknown, + response.RequestMessage.RequestUri) + { + LSN = responseLSN, + PartitionKeyRangeId = responsePartitionKeyRangeId + }; + exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, + activityId); + + break; + } + else + { + if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) + { + return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); + } + + exception = new NotFoundException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.NotFound : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + + case HttpStatusCode.BadRequest: + exception = new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.BadRequest : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case HttpStatusCode.MethodNotAllowed: + exception = new MethodNotAllowedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.MethodNotAllowed : errorMessage), + null, + response.Headers, + response.RequestMessage.RequestUri); + break; + + case HttpStatusCode.Gone: + { +#if NETFX + if (PerfCounters.Counters.RoutingFailures != null) + { + PerfCounters.Counters.RoutingFailures.Increment(); + } +#endif + TransportClient.LogGoneException(response.RequestMessage.RequestUri, activityId); + + uint nSubStatus = HttpTransportClient.GetSubsStatusFromHeader(response); + + if ((SubStatusCodes)nSubStatus == SubStatusCodes.NameCacheIsStale) + { + exception = new InvalidPartitionException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.PartitionKeyRangeGone) + { + exception = new PartitionKeyRangeGoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingSplit) + { + exception = new PartitionKeyRangeIsSplittingException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingPartitionMigration) + { + exception = new PartitionIsMigratingException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Gone : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + else + { + // Have the request URL in the exception message for debugging purposes. + exception = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + response.Headers, + (nSubStatus == 0) ? SubStatusCodes.ServerGenerated410 : null, + response.RequestMessage.RequestUri); + + exception.Headers.Set(HttpConstants.HttpHeaders.ActivityId, + activityId); + break; + } + } + + case HttpStatusCode.Conflict: + { + if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) + { + return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); + } + + exception = new ConflictException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.EntityAlreadyExists : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + + case HttpStatusCode.PreconditionFailed: + { + if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) + { + return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); + } + + exception = new PreconditionFailedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.PreconditionFailed : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + + case HttpStatusCode.RequestEntityTooLarge: + exception = new RequestEntityTooLargeException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.Format(CultureInfo.CurrentUICulture, + RMResources.RequestEntityTooLarge, + HttpConstants.HttpHeaders.PageSize)), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case (HttpStatusCode)423: + exception = new LockedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.Locked : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case HttpStatusCode.ServiceUnavailable: + uint subStatus = HttpTransportClient.GetSubsStatusFromHeader(response); + if (!string.IsNullOrEmpty(errorMessage)) + { + exception = new ServiceUnavailableException( + message: string.Format(CultureInfo.CurrentUICulture, RMResources.ExceptionMessage, errorMessage), + headers: response.Headers, + subStatusCode: (subStatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value + requestUri: response.RequestMessage.RequestUri); + } + else + { + exception = ServiceUnavailableException.Create( + (subStatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value + headers: response.Headers, + requestUri: response.RequestMessage.RequestUri); + } + break; + + case HttpStatusCode.RequestTimeout: + exception = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.RequestTimeout : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case (HttpStatusCode)StatusCodes.RetryWith: + exception = new RetryWithException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.RetryWith : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + case (HttpStatusCode)StatusCodes.TooManyRequests: + if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode)) + { + return await HttpTransportClient.CreateStoreResponseFromHttpResponse(response, includeContent: false); + } + + exception = + new RequestRateTooLargeException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.TooManyRequests : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + + IEnumerable values = null; + try + { + values = response.Headers.GetValues(HttpConstants.HttpHeaders.RetryAfterInMilliseconds); + } + catch (InvalidOperationException) + { + DefaultTrace.TraceWarning("RequestRateTooLargeException being thrown without RetryAfter."); + } + + if (values != null && values.Any()) + { + exception.Headers.Set(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, values.First()); + } + + break; + + case HttpStatusCode.InternalServerError: + exception = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.InternalServerError : errorMessage), + response.Headers, + response.RequestMessage.RequestUri); + break; + + default: + DefaultTrace.TraceCritical("Unrecognized status code {0} returned by backend. ActivityId {1}", statusCode, activityId); + TransportClient.LogException(response.RequestMessage.RequestUri, activityId); + exception = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.InvalidBackendResponse), + response.Headers, + response.RequestMessage.RequestUri); + break; + } + + exception.LSN = responseLSN; + exception.PartitionKeyRangeId = responsePartitionKeyRangeId; + exception.ResourceAddress = resourceAddress; + throw exception; + } + } + + private static uint GetSubsStatusFromHeader(HttpResponseMessage response) + { + uint nSubStatus = 0; + try + { + IEnumerable valueSubStatus = response.Headers.GetValues(WFConstants.BackendHeaders.SubStatus); + if (valueSubStatus != null && valueSubStatus.Any()) + { + if (!uint.TryParse(valueSubStatus.First(), NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) + { + throw new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.InvalidBackendResponse), + response.Headers, + response.RequestMessage.RequestUri); + } + } + } + catch (InvalidOperationException) + { + DefaultTrace.TraceInformation("SubStatus doesn't exist in the header"); + } + + return nSubStatus; + } + + internal static string GetHeader(string[] names, string[] values, string name) + { + for (int idx = 0; idx < names.Length; idx++) + { + if (string.Equals(names[idx], name, StringComparison.Ordinal)) + { + return values[idx]; + } + } + + return null; + } + + public async static Task CreateStoreResponseFromHttpResponse(HttpResponseMessage responseMessage, bool includeContent = true) + { + StoreResponse response = new StoreResponse() + { + Headers = new DictionaryNameValueCollection(StringComparer.OrdinalIgnoreCase) + }; + + using (responseMessage) + { + foreach (KeyValuePair> kvPair in responseMessage.Headers) + { + if (string.Compare(kvPair.Key, HttpConstants.HttpHeaders.OwnerFullName, StringComparison.Ordinal) == 0) + { + response.Headers[kvPair.Key] = Uri.UnescapeDataString(kvPair.Value.SingleOrDefault()); + } + else + { + response.Headers[kvPair.Key] = kvPair.Value.SingleOrDefault(); + } + } + + response.Status = (int)responseMessage.StatusCode; + + if (includeContent && responseMessage.Content != null) + { + Stream bufferredStream = new MemoryStream(); + + await responseMessage.Content.CopyToAsync(bufferredStream); + bufferredStream.Position = 0; + + response.ResponseBody = bufferredStream; + } + return response; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpUtility.cs b/Microsoft.Azure.Cosmos/src/direct/HttpUtility.cs index 7279db65c4..e67d6511ca 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpUtility.cs @@ -1,814 +1,814 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.IO; - using System.Text; - using Microsoft.Azure.Documents.Collections; - - //Just flicked from System.Web; We dont want to fault-in entire System.Web for this utility. - //Stripped out unwanted functionalities like HtmlEncode/Decode and retained only URLEncode/Decode functionalities. - internal sealed class HttpUtility - { - // Fields - private static char[] s_entityEndingChars = new char[] { ';', '&' }; - - // Methods - internal static string AspCompatUrlEncode(string s) - { - s = UrlEncode(s); - s = s.Replace("!", "%21"); - s = s.Replace("*", "%2A"); - s = s.Replace("(", "%28"); - s = s.Replace(")", "%29"); - s = s.Replace("-", "%2D"); - s = s.Replace(".", "%2E"); - s = s.Replace("_", "%5F"); - s = s.Replace(@"\", "%5C"); - return s; - } - - internal static string CollapsePercentUFromStringInternal(string s, Encoding e) - { - int length = s.Length; - UrlDecoder decoder = new UrlDecoder(length, e); - if (s.IndexOf("%u", StringComparison.Ordinal) == -1) - { - return s; - } - for (int i = 0; i < length; i++) - { - char ch = s[i]; - if (((ch == '%') && (i < (length - 5))) && (s[i + 1] == 'u')) - { - int num4 = HexToInt(s[i + 2]); - int num5 = HexToInt(s[i + 3]); - int num6 = HexToInt(s[i + 4]); - int num7 = HexToInt(s[i + 5]); - if (((num4 >= 0) && (num5 >= 0)) && ((num6 >= 0) && (num7 >= 0))) - { - ch = (char)((((num4 << 12) | (num5 << 8)) | (num6 << 4)) | num7); - i += 5; - decoder.AddChar(ch); - continue; - } - } - if ((ch & 0xff80) == 0) - { - decoder.AddByte((byte)ch); - } - else - { - decoder.AddChar(ch); - } - } - return decoder.GetString(); - } - - internal static string FormatHttpCookieDateTime(DateTime dt) - { - if ((dt < DateTime.MaxValue.AddDays(-1.0)) && (dt > DateTime.MinValue.AddDays(1.0))) - { - dt = dt.ToUniversalTime(); - } - return dt.ToString("ddd, dd-MMM-yyyy HH':'mm':'ss 'GMT'", DateTimeFormatInfo.InvariantInfo); - } - - internal static string FormatHttpDateTime(DateTime dt) - { - if ((dt < DateTime.MaxValue.AddDays(-1.0)) && (dt > DateTime.MinValue.AddDays(1.0))) - { - dt = dt.ToUniversalTime(); - } - return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); - } - - internal static string FormatHttpDateTimeUtc(DateTime dt) - { - return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); - } - - internal static string FormatPlainTextAsHtml(string s) - { - if (s == null) - { - return null; - } - StringBuilder sb = new StringBuilder(); - using (StringWriter output = new StringWriter(sb, CultureInfo.InvariantCulture)) - { - FormatPlainTextAsHtml(s, output); - } - return sb.ToString(); - } - - internal static INameValueCollection ParseQueryString(string queryString) - { - INameValueCollection queryParameters = new DictionaryNameValueCollection(); - string[] querySegments = queryString.Split('&'); - foreach (string segment in querySegments) - { - string[] parts = segment.Split('='); - if (parts.Length > 1) - { - string key = HttpUtility.UrlDecode(parts[0].Trim(new char[] { '?', ' ' })); - string val = HttpUtility.UrlDecode(parts[1].Trim()); - - queryParameters.Add(CultureInfo.InvariantCulture.TextInfo.ToLower(key), val); - } - } - return queryParameters; - } - - internal static void FormatPlainTextAsHtml(string s, TextWriter output) - { - if (s != null) - { - int length = s.Length; - char ch = '\0'; - for (int i = 0; i < length; i++) - { - char ch2 = s[i]; - switch (ch2) - { - case '\n': - output.Write("
"); - goto Label_0113; - - case '\r': - goto Label_0113; - - case ' ': - if (ch != ' ') - { - break; - } - output.Write(" "); - goto Label_0113; - - case '"': - output.Write("""); - goto Label_0113; - - case '&': - output.Write("&"); - goto Label_0113; - - case '<': - output.Write("<"); - goto Label_0113; - - case '>': - output.Write(">"); - goto Label_0113; - - default: - if ((ch2 >= '\x00a0') && (ch2 < 'Ā')) - { - output.Write("&#"); - output.Write(((int)ch2).ToString(NumberFormatInfo.InvariantInfo)); - output.Write(';'); - } - else - { - output.Write(ch2); - } - goto Label_0113; - } - output.Write(ch2); - Label_0113: - ch = ch2; - } - } - } - - internal static string FormatPlainTextSpacesAsHtml(string s) - { - if (s == null) - { - return null; - } - StringBuilder sb = new StringBuilder(); - using (StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture)) - { - int length = s.Length; - for (int i = 0; i < length; i++) - { - char ch = s[i]; - if (ch == ' ') - { - writer.Write(" "); - } - else - { - writer.Write(ch); - } - } - } - return sb.ToString(); - } - - private static int HexToInt(char h) - { - if ((h >= '0') && (h <= '9')) - { - return (h - '0'); - } - if ((h >= 'a') && (h <= 'f')) - { - return ((h - 'a') + 10); - } - if ((h >= 'A') && (h <= 'F')) - { - return ((h - 'A') + 10); - } - return -1; - } - - internal static char IntToHex(int n) - { - if (n <= 9) - { - return (char)(n + 0x30); - } - return (char)((n - 10) + 0x61); - } - - private static bool IsNonAsciiByte(byte b) - { - if (b < 0x7f) - { - return (b < 0x20); - } - return true; - } - - internal static bool IsSafe(char ch) - { - if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || ((ch >= '0') && (ch <= '9'))) - { - return true; - } - switch (ch) - { - case '\'': - case '(': - case ')': - case '*': - case '-': - case '.': - case '_': - case '!': - return true; - } - return false; - } - - public static string UrlDecode(string str) - { - if (str == null) - { - return null; - } - return UrlDecode(str, Encoding.UTF8); - } - - public static string UrlDecode(byte[] bytes, Encoding e) - { - if (bytes == null) - { - return null; - } - return UrlDecode(bytes, 0, bytes.Length, e); - } - - public static string UrlDecode(string str, Encoding e) - { - if (str == null) - { - return null; - } - return UrlDecodeStringFromStringInternal(str, e); - } - - public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) - { - if ((bytes == null) && (count == 0)) - { - return null; - } - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - if ((offset < 0) || (offset > bytes.Length)) - { - throw new ArgumentOutOfRangeException("offset"); - } - if ((count < 0) || ((offset + count) > bytes.Length)) - { - throw new ArgumentOutOfRangeException("count"); - } - return UrlDecodeStringFromBytesInternal(bytes, offset, count, e); - } - - private static byte[] UrlDecodeBytesFromBytesInternal(byte[] buf, int offset, int count) - { - int length = 0; - byte[] sourceArray = new byte[count]; - for (int i = 0; i < count; i++) - { - int index = offset + i; - byte num4 = buf[index]; - if (num4 == 0x2b) - { - num4 = 0x20; - } - else if ((num4 == 0x25) && (i < (count - 2))) - { - int num5 = HexToInt((char)buf[index + 1]); - int num6 = HexToInt((char)buf[index + 2]); - if ((num5 >= 0) && (num6 >= 0)) - { - num4 = (byte)((num5 << 4) | num6); - i += 2; - } - } - sourceArray[length++] = num4; - } - if (length < sourceArray.Length) - { - byte[] destinationArray = new byte[length]; - Array.Copy(sourceArray, destinationArray, length); - sourceArray = destinationArray; - } - return sourceArray; - } - - private static string UrlDecodeStringFromBytesInternal(byte[] buf, int offset, int count, Encoding e) - { - UrlDecoder decoder = new UrlDecoder(count, e); - for (int i = 0; i < count; i++) - { - int index = offset + i; - byte b = buf[index]; - if (b == 0x2b) - { - b = 0x20; - } - else if ((b == 0x25) && (i < (count - 2))) - { - if ((buf[index + 1] == 0x75) && (i < (count - 5))) - { - int num4 = HexToInt((char)buf[index + 2]); - int num5 = HexToInt((char)buf[index + 3]); - int num6 = HexToInt((char)buf[index + 4]); - int num7 = HexToInt((char)buf[index + 5]); - if (((num4 < 0) || (num5 < 0)) || ((num6 < 0) || (num7 < 0))) - { - goto Label_00DA; - } - char ch = (char)((((num4 << 12) | (num5 << 8)) | (num6 << 4)) | num7); - i += 5; - decoder.AddChar(ch); - continue; - } - int num8 = HexToInt((char)buf[index + 1]); - int num9 = HexToInt((char)buf[index + 2]); - if ((num8 >= 0) && (num9 >= 0)) - { - b = (byte)((num8 << 4) | num9); - i += 2; - } - } - Label_00DA: - decoder.AddByte(b); - } - return decoder.GetString(); - } - - private static string UrlDecodeStringFromStringInternal(string s, Encoding e) - { - int length = s.Length; - UrlDecoder decoder = new UrlDecoder(length, e); - for (int i = 0; i < length; i++) - { - char ch = s[i]; - if (ch == '+') - { - ch = ' '; - } - else if ((ch == '%') && (i < (length - 2))) - { - if ((s[i + 1] == 'u') && (i < (length - 5))) - { - int num3 = HexToInt(s[i + 2]); - int num4 = HexToInt(s[i + 3]); - int num5 = HexToInt(s[i + 4]); - int num6 = HexToInt(s[i + 5]); - if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0))) - { - goto Label_0106; - } - ch = (char)((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6); - i += 5; - decoder.AddChar(ch); - continue; - } - int num7 = HexToInt(s[i + 1]); - int num8 = HexToInt(s[i + 2]); - if ((num7 >= 0) && (num8 >= 0)) - { - byte b = (byte)((num7 << 4) | num8); - i += 2; - decoder.AddByte(b); - continue; - } - } - Label_0106: - if ((ch & 0xff80) == 0) - { - decoder.AddByte((byte)ch); - } - else - { - decoder.AddChar(ch); - } - } - return decoder.GetString(); - } - - public static byte[] UrlDecodeToBytes(byte[] bytes) - { - if (bytes == null) - { - return null; - } - return UrlDecodeToBytes(bytes, 0, (bytes != null) ? bytes.Length : 0); - } - - public static byte[] UrlDecodeToBytes(string str) - { - if (str == null) - { - return null; - } - return UrlDecodeToBytes(str, Encoding.UTF8); - } - - public static byte[] UrlDecodeToBytes(string str, Encoding e) - { - if (str == null) - { - return null; - } - return UrlDecodeToBytes(e.GetBytes(str)); - } - - public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count) - { - if ((bytes == null) && (count == 0)) - { - return null; - } - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - if ((offset < 0) || (offset > bytes.Length)) - { - throw new ArgumentOutOfRangeException("offset"); - } - if ((count < 0) || ((offset + count) > bytes.Length)) - { - throw new ArgumentOutOfRangeException("count"); - } - return UrlDecodeBytesFromBytesInternal(bytes, offset, count); - } - - public static string UrlEncode(byte[] bytes) - { - if (bytes == null) - { - return null; - } - - byte[] encodedBytes = UrlEncodeToBytes(bytes); - return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); - } - - public static string UrlEncode(string str) - { - if (str == null) - { - return null; - } - return UrlEncode(str, Encoding.UTF8); - } - - public static string UrlEncode(string str, Encoding e) - { - if (str == null) - { - return null; - } - - byte[] encodedBytes = UrlEncodeToBytes(str, e); - return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); - } - - - public static string UrlEncode(byte[] bytes, int offset, int count) - { - if (bytes == null) - { - return null; - } - - byte[] encodedBytes = UrlEncodeToBytes(bytes, offset, count); - return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); - } - - private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) - { - int num = 0; - int num2 = 0; - for (int i = 0; i < count; i++) - { - char ch = (char)bytes[offset + i]; - if (ch == ' ') - { - num++; - } - else if (!IsSafe(ch)) - { - num2++; - } - } - if ((!alwaysCreateReturnValue && (num == 0)) && (num2 == 0)) - { - return bytes; - } - byte[] buffer = new byte[count + (num2 * 2)]; - int num4 = 0; - for (int j = 0; j < count; j++) - { - byte num6 = bytes[offset + j]; - char ch2 = (char)num6; - if (IsSafe(ch2)) - { - buffer[num4++] = num6; - } - else if (ch2 == ' ') - { - buffer[num4++] = 0x2b; - } - else - { - buffer[num4++] = 0x25; - buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15); - buffer[num4++] = (byte)IntToHex(num6 & 15); - } - } - return buffer; - } - - private static byte[] UrlEncodeBytesToBytesInternalNonAscii(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) - { - int num = 0; - for (int i = 0; i < count; i++) - { - if (IsNonAsciiByte(bytes[offset + i])) - { - num++; - } - } - if (!alwaysCreateReturnValue && (num == 0)) - { - return bytes; - } - byte[] buffer = new byte[count + (num * 2)]; - int num3 = 0; - for (int j = 0; j < count; j++) - { - byte b = bytes[offset + j]; - if (IsNonAsciiByte(b)) - { - buffer[num3++] = 0x25; - buffer[num3++] = (byte)IntToHex((b >> 4) & 15); - buffer[num3++] = (byte)IntToHex(b & 15); - } - else - { - buffer[num3++] = b; - } - } - return buffer; - } - - internal static string UrlEncodeNonAscii(string str, Encoding e) - { - if (string.IsNullOrEmpty(str)) - { - return str; - } - if (e == null) - { - e = Encoding.UTF8; - } - byte[] bytes = e.GetBytes(str); - bytes = UrlEncodeBytesToBytesInternalNonAscii(bytes, 0, bytes.Length, false); - - return Encoding.UTF8.GetString(bytes, 0, bytes.Length); - } - - internal static string UrlEncodeSpaces(string str) - { - if ((str != null) && (str.IndexOf(' ') >= 0)) - { - str = str.Replace(" ", "%20"); - } - return str; - } - - public static byte[] UrlEncodeToBytes(string str) - { - if (str == null) - { - return null; - } - return UrlEncodeToBytes(str, Encoding.UTF8); - } - - public static byte[] UrlEncodeToBytes(byte[] bytes) - { - if (bytes == null) - { - return null; - } - return UrlEncodeToBytes(bytes, 0, bytes.Length); - } - - public static byte[] UrlEncodeToBytes(string str, Encoding e) - { - if (str == null) - { - return null; - } - byte[] bytes = e.GetBytes(str); - return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false); - } - - public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) - { - if ((bytes == null) && (count == 0)) - { - return null; - } - if (bytes == null) - { - throw new ArgumentNullException("bytes"); - } - if ((offset < 0) || (offset > bytes.Length)) - { - throw new ArgumentOutOfRangeException("offset"); - } - if ((count < 0) || ((offset + count) > bytes.Length)) - { - throw new ArgumentOutOfRangeException("count"); - } - return UrlEncodeBytesToBytesInternal(bytes, offset, count, true); - } - - public static string UrlEncodeUnicode(string str) - { - if (str == null) - { - return null; - } - return UrlEncodeUnicodeStringToStringInternal(str, false); - } - - private static string UrlEncodeUnicodeStringToStringInternal(string s, bool ignoreAscii) - { - int length = s.Length; - StringBuilder builder = new StringBuilder(length); - for (int i = 0; i < length; i++) - { - char ch = s[i]; - if ((ch & 0xff80) == 0) - { - if (ignoreAscii || IsSafe(ch)) - { - builder.Append(ch); - } - else if (ch == ' ') - { - builder.Append('+'); - } - else - { - builder.Append('%'); - builder.Append(IntToHex((ch >> 4) & '\x000f')); - builder.Append(IntToHex(ch & '\x000f')); - } - } - else - { - builder.Append("%u"); - builder.Append(IntToHex((ch >> 12) & '\x000f')); - builder.Append(IntToHex((ch >> 8) & '\x000f')); - builder.Append(IntToHex((ch >> 4) & '\x000f')); - builder.Append(IntToHex(ch & '\x000f')); - } - } - return builder.ToString(); - } - - public static byte[] UrlEncodeUnicodeToBytes(string str) - { - if (str == null) - { - return null; - } - return Encoding.UTF8.GetBytes(UrlEncodeUnicode(str)); - } - - public static string UrlPathEncode(string str) - { - if (str == null) - { - return null; - } - int index = str.IndexOf('?'); - if (index >= 0) - { - return (UrlPathEncode(str.Substring(0, index)) + str.Substring(index)); - } - return UrlEncodeSpaces(UrlEncodeNonAscii(str, Encoding.UTF8)); - } - - // Nested Types - private class UrlDecoder - { - // Fields - private int _bufferSize; - private byte[] _byteBuffer; - private char[] _charBuffer; - private Encoding _encoding; - private int _numBytes; - private int _numChars; - - // Methods - internal UrlDecoder(int bufferSize, Encoding encoding) - { - this._bufferSize = bufferSize; - this._encoding = encoding; - this._charBuffer = new char[bufferSize]; - } - - internal void AddByte(byte b) - { - if (this._byteBuffer == null) - { - this._byteBuffer = new byte[this._bufferSize]; - } - this._byteBuffer[this._numBytes++] = b; - } - - internal void AddChar(char ch) - { - if (this._numBytes > 0) - { - this.FlushBytes(); - } - this._charBuffer[this._numChars++] = ch; - } - - private void FlushBytes() - { - if (this._numBytes > 0) - { - this._numChars += this._encoding.GetChars(this._byteBuffer, 0, this._numBytes, this._charBuffer, this._numChars); - this._numBytes = 0; - } - } - - internal string GetString() - { - if (this._numBytes > 0) - { - this.FlushBytes(); - } - if (this._numChars > 0) - { - return new string(this._charBuffer, 0, this._numChars); - } - return string.Empty; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.IO; + using System.Text; + using Microsoft.Azure.Documents.Collections; + + //Just flicked from System.Web; We dont want to fault-in entire System.Web for this utility. + //Stripped out unwanted functionalities like HtmlEncode/Decode and retained only URLEncode/Decode functionalities. + internal sealed class HttpUtility + { + // Fields + private static char[] s_entityEndingChars = new char[] { ';', '&' }; + + // Methods + internal static string AspCompatUrlEncode(string s) + { + s = UrlEncode(s); + s = s.Replace("!", "%21"); + s = s.Replace("*", "%2A"); + s = s.Replace("(", "%28"); + s = s.Replace(")", "%29"); + s = s.Replace("-", "%2D"); + s = s.Replace(".", "%2E"); + s = s.Replace("_", "%5F"); + s = s.Replace(@"\", "%5C"); + return s; + } + + internal static string CollapsePercentUFromStringInternal(string s, Encoding e) + { + int length = s.Length; + UrlDecoder decoder = new UrlDecoder(length, e); + if (s.IndexOf("%u", StringComparison.Ordinal) == -1) + { + return s; + } + for (int i = 0; i < length; i++) + { + char ch = s[i]; + if (((ch == '%') && (i < (length - 5))) && (s[i + 1] == 'u')) + { + int num4 = HexToInt(s[i + 2]); + int num5 = HexToInt(s[i + 3]); + int num6 = HexToInt(s[i + 4]); + int num7 = HexToInt(s[i + 5]); + if (((num4 >= 0) && (num5 >= 0)) && ((num6 >= 0) && (num7 >= 0))) + { + ch = (char)((((num4 << 12) | (num5 << 8)) | (num6 << 4)) | num7); + i += 5; + decoder.AddChar(ch); + continue; + } + } + if ((ch & 0xff80) == 0) + { + decoder.AddByte((byte)ch); + } + else + { + decoder.AddChar(ch); + } + } + return decoder.GetString(); + } + + internal static string FormatHttpCookieDateTime(DateTime dt) + { + if ((dt < DateTime.MaxValue.AddDays(-1.0)) && (dt > DateTime.MinValue.AddDays(1.0))) + { + dt = dt.ToUniversalTime(); + } + return dt.ToString("ddd, dd-MMM-yyyy HH':'mm':'ss 'GMT'", DateTimeFormatInfo.InvariantInfo); + } + + internal static string FormatHttpDateTime(DateTime dt) + { + if ((dt < DateTime.MaxValue.AddDays(-1.0)) && (dt > DateTime.MinValue.AddDays(1.0))) + { + dt = dt.ToUniversalTime(); + } + return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); + } + + internal static string FormatHttpDateTimeUtc(DateTime dt) + { + return dt.ToString("R", DateTimeFormatInfo.InvariantInfo); + } + + internal static string FormatPlainTextAsHtml(string s) + { + if (s == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + using (StringWriter output = new StringWriter(sb, CultureInfo.InvariantCulture)) + { + FormatPlainTextAsHtml(s, output); + } + return sb.ToString(); + } + + internal static INameValueCollection ParseQueryString(string queryString) + { + INameValueCollection queryParameters = new DictionaryNameValueCollection(); + string[] querySegments = queryString.Split('&'); + foreach (string segment in querySegments) + { + string[] parts = segment.Split('='); + if (parts.Length > 1) + { + string key = HttpUtility.UrlDecode(parts[0].Trim(new char[] { '?', ' ' })); + string val = HttpUtility.UrlDecode(parts[1].Trim()); + + queryParameters.Add(CultureInfo.InvariantCulture.TextInfo.ToLower(key), val); + } + } + return queryParameters; + } + + internal static void FormatPlainTextAsHtml(string s, TextWriter output) + { + if (s != null) + { + int length = s.Length; + char ch = '\0'; + for (int i = 0; i < length; i++) + { + char ch2 = s[i]; + switch (ch2) + { + case '\n': + output.Write("
"); + goto Label_0113; + + case '\r': + goto Label_0113; + + case ' ': + if (ch != ' ') + { + break; + } + output.Write(" "); + goto Label_0113; + + case '"': + output.Write("""); + goto Label_0113; + + case '&': + output.Write("&"); + goto Label_0113; + + case '<': + output.Write("<"); + goto Label_0113; + + case '>': + output.Write(">"); + goto Label_0113; + + default: + if ((ch2 >= '\x00a0') && (ch2 < 'Ā')) + { + output.Write("&#"); + output.Write(((int)ch2).ToString(NumberFormatInfo.InvariantInfo)); + output.Write(';'); + } + else + { + output.Write(ch2); + } + goto Label_0113; + } + output.Write(ch2); + Label_0113: + ch = ch2; + } + } + } + + internal static string FormatPlainTextSpacesAsHtml(string s) + { + if (s == null) + { + return null; + } + StringBuilder sb = new StringBuilder(); + using (StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture)) + { + int length = s.Length; + for (int i = 0; i < length; i++) + { + char ch = s[i]; + if (ch == ' ') + { + writer.Write(" "); + } + else + { + writer.Write(ch); + } + } + } + return sb.ToString(); + } + + private static int HexToInt(char h) + { + if ((h >= '0') && (h <= '9')) + { + return (h - '0'); + } + if ((h >= 'a') && (h <= 'f')) + { + return ((h - 'a') + 10); + } + if ((h >= 'A') && (h <= 'F')) + { + return ((h - 'A') + 10); + } + return -1; + } + + internal static char IntToHex(int n) + { + if (n <= 9) + { + return (char)(n + 0x30); + } + return (char)((n - 10) + 0x61); + } + + private static bool IsNonAsciiByte(byte b) + { + if (b < 0x7f) + { + return (b < 0x20); + } + return true; + } + + internal static bool IsSafe(char ch) + { + if ((((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) || ((ch >= '0') && (ch <= '9'))) + { + return true; + } + switch (ch) + { + case '\'': + case '(': + case ')': + case '*': + case '-': + case '.': + case '_': + case '!': + return true; + } + return false; + } + + public static string UrlDecode(string str) + { + if (str == null) + { + return null; + } + return UrlDecode(str, Encoding.UTF8); + } + + public static string UrlDecode(byte[] bytes, Encoding e) + { + if (bytes == null) + { + return null; + } + return UrlDecode(bytes, 0, bytes.Length, e); + } + + public static string UrlDecode(string str, Encoding e) + { + if (str == null) + { + return null; + } + return UrlDecodeStringFromStringInternal(str, e); + } + + public static string UrlDecode(byte[] bytes, int offset, int count, Encoding e) + { + if ((bytes == null) && (count == 0)) + { + return null; + } + if (bytes == null) + { + throw new ArgumentNullException("bytes"); + } + if ((offset < 0) || (offset > bytes.Length)) + { + throw new ArgumentOutOfRangeException("offset"); + } + if ((count < 0) || ((offset + count) > bytes.Length)) + { + throw new ArgumentOutOfRangeException("count"); + } + return UrlDecodeStringFromBytesInternal(bytes, offset, count, e); + } + + private static byte[] UrlDecodeBytesFromBytesInternal(byte[] buf, int offset, int count) + { + int length = 0; + byte[] sourceArray = new byte[count]; + for (int i = 0; i < count; i++) + { + int index = offset + i; + byte num4 = buf[index]; + if (num4 == 0x2b) + { + num4 = 0x20; + } + else if ((num4 == 0x25) && (i < (count - 2))) + { + int num5 = HexToInt((char)buf[index + 1]); + int num6 = HexToInt((char)buf[index + 2]); + if ((num5 >= 0) && (num6 >= 0)) + { + num4 = (byte)((num5 << 4) | num6); + i += 2; + } + } + sourceArray[length++] = num4; + } + if (length < sourceArray.Length) + { + byte[] destinationArray = new byte[length]; + Array.Copy(sourceArray, destinationArray, length); + sourceArray = destinationArray; + } + return sourceArray; + } + + private static string UrlDecodeStringFromBytesInternal(byte[] buf, int offset, int count, Encoding e) + { + UrlDecoder decoder = new UrlDecoder(count, e); + for (int i = 0; i < count; i++) + { + int index = offset + i; + byte b = buf[index]; + if (b == 0x2b) + { + b = 0x20; + } + else if ((b == 0x25) && (i < (count - 2))) + { + if ((buf[index + 1] == 0x75) && (i < (count - 5))) + { + int num4 = HexToInt((char)buf[index + 2]); + int num5 = HexToInt((char)buf[index + 3]); + int num6 = HexToInt((char)buf[index + 4]); + int num7 = HexToInt((char)buf[index + 5]); + if (((num4 < 0) || (num5 < 0)) || ((num6 < 0) || (num7 < 0))) + { + goto Label_00DA; + } + char ch = (char)((((num4 << 12) | (num5 << 8)) | (num6 << 4)) | num7); + i += 5; + decoder.AddChar(ch); + continue; + } + int num8 = HexToInt((char)buf[index + 1]); + int num9 = HexToInt((char)buf[index + 2]); + if ((num8 >= 0) && (num9 >= 0)) + { + b = (byte)((num8 << 4) | num9); + i += 2; + } + } + Label_00DA: + decoder.AddByte(b); + } + return decoder.GetString(); + } + + private static string UrlDecodeStringFromStringInternal(string s, Encoding e) + { + int length = s.Length; + UrlDecoder decoder = new UrlDecoder(length, e); + for (int i = 0; i < length; i++) + { + char ch = s[i]; + if (ch == '+') + { + ch = ' '; + } + else if ((ch == '%') && (i < (length - 2))) + { + if ((s[i + 1] == 'u') && (i < (length - 5))) + { + int num3 = HexToInt(s[i + 2]); + int num4 = HexToInt(s[i + 3]); + int num5 = HexToInt(s[i + 4]); + int num6 = HexToInt(s[i + 5]); + if (((num3 < 0) || (num4 < 0)) || ((num5 < 0) || (num6 < 0))) + { + goto Label_0106; + } + ch = (char)((((num3 << 12) | (num4 << 8)) | (num5 << 4)) | num6); + i += 5; + decoder.AddChar(ch); + continue; + } + int num7 = HexToInt(s[i + 1]); + int num8 = HexToInt(s[i + 2]); + if ((num7 >= 0) && (num8 >= 0)) + { + byte b = (byte)((num7 << 4) | num8); + i += 2; + decoder.AddByte(b); + continue; + } + } + Label_0106: + if ((ch & 0xff80) == 0) + { + decoder.AddByte((byte)ch); + } + else + { + decoder.AddChar(ch); + } + } + return decoder.GetString(); + } + + public static byte[] UrlDecodeToBytes(byte[] bytes) + { + if (bytes == null) + { + return null; + } + return UrlDecodeToBytes(bytes, 0, (bytes != null) ? bytes.Length : 0); + } + + public static byte[] UrlDecodeToBytes(string str) + { + if (str == null) + { + return null; + } + return UrlDecodeToBytes(str, Encoding.UTF8); + } + + public static byte[] UrlDecodeToBytes(string str, Encoding e) + { + if (str == null) + { + return null; + } + return UrlDecodeToBytes(e.GetBytes(str)); + } + + public static byte[] UrlDecodeToBytes(byte[] bytes, int offset, int count) + { + if ((bytes == null) && (count == 0)) + { + return null; + } + if (bytes == null) + { + throw new ArgumentNullException("bytes"); + } + if ((offset < 0) || (offset > bytes.Length)) + { + throw new ArgumentOutOfRangeException("offset"); + } + if ((count < 0) || ((offset + count) > bytes.Length)) + { + throw new ArgumentOutOfRangeException("count"); + } + return UrlDecodeBytesFromBytesInternal(bytes, offset, count); + } + + public static string UrlEncode(byte[] bytes) + { + if (bytes == null) + { + return null; + } + + byte[] encodedBytes = UrlEncodeToBytes(bytes); + return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); + } + + public static string UrlEncode(string str) + { + if (str == null) + { + return null; + } + return UrlEncode(str, Encoding.UTF8); + } + + public static string UrlEncode(string str, Encoding e) + { + if (str == null) + { + return null; + } + + byte[] encodedBytes = UrlEncodeToBytes(str, e); + return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); + } + + + public static string UrlEncode(byte[] bytes, int offset, int count) + { + if (bytes == null) + { + return null; + } + + byte[] encodedBytes = UrlEncodeToBytes(bytes, offset, count); + return Encoding.UTF8.GetString(encodedBytes, 0, encodedBytes.Length); + } + + private static byte[] UrlEncodeBytesToBytesInternal(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) + { + int num = 0; + int num2 = 0; + for (int i = 0; i < count; i++) + { + char ch = (char)bytes[offset + i]; + if (ch == ' ') + { + num++; + } + else if (!IsSafe(ch)) + { + num2++; + } + } + if ((!alwaysCreateReturnValue && (num == 0)) && (num2 == 0)) + { + return bytes; + } + byte[] buffer = new byte[count + (num2 * 2)]; + int num4 = 0; + for (int j = 0; j < count; j++) + { + byte num6 = bytes[offset + j]; + char ch2 = (char)num6; + if (IsSafe(ch2)) + { + buffer[num4++] = num6; + } + else if (ch2 == ' ') + { + buffer[num4++] = 0x2b; + } + else + { + buffer[num4++] = 0x25; + buffer[num4++] = (byte)IntToHex((num6 >> 4) & 15); + buffer[num4++] = (byte)IntToHex(num6 & 15); + } + } + return buffer; + } + + private static byte[] UrlEncodeBytesToBytesInternalNonAscii(byte[] bytes, int offset, int count, bool alwaysCreateReturnValue) + { + int num = 0; + for (int i = 0; i < count; i++) + { + if (IsNonAsciiByte(bytes[offset + i])) + { + num++; + } + } + if (!alwaysCreateReturnValue && (num == 0)) + { + return bytes; + } + byte[] buffer = new byte[count + (num * 2)]; + int num3 = 0; + for (int j = 0; j < count; j++) + { + byte b = bytes[offset + j]; + if (IsNonAsciiByte(b)) + { + buffer[num3++] = 0x25; + buffer[num3++] = (byte)IntToHex((b >> 4) & 15); + buffer[num3++] = (byte)IntToHex(b & 15); + } + else + { + buffer[num3++] = b; + } + } + return buffer; + } + + internal static string UrlEncodeNonAscii(string str, Encoding e) + { + if (string.IsNullOrEmpty(str)) + { + return str; + } + if (e == null) + { + e = Encoding.UTF8; + } + byte[] bytes = e.GetBytes(str); + bytes = UrlEncodeBytesToBytesInternalNonAscii(bytes, 0, bytes.Length, false); + + return Encoding.UTF8.GetString(bytes, 0, bytes.Length); + } + + internal static string UrlEncodeSpaces(string str) + { + if ((str != null) && (str.IndexOf(' ') >= 0)) + { + str = str.Replace(" ", "%20"); + } + return str; + } + + public static byte[] UrlEncodeToBytes(string str) + { + if (str == null) + { + return null; + } + return UrlEncodeToBytes(str, Encoding.UTF8); + } + + public static byte[] UrlEncodeToBytes(byte[] bytes) + { + if (bytes == null) + { + return null; + } + return UrlEncodeToBytes(bytes, 0, bytes.Length); + } + + public static byte[] UrlEncodeToBytes(string str, Encoding e) + { + if (str == null) + { + return null; + } + byte[] bytes = e.GetBytes(str); + return UrlEncodeBytesToBytesInternal(bytes, 0, bytes.Length, false); + } + + public static byte[] UrlEncodeToBytes(byte[] bytes, int offset, int count) + { + if ((bytes == null) && (count == 0)) + { + return null; + } + if (bytes == null) + { + throw new ArgumentNullException("bytes"); + } + if ((offset < 0) || (offset > bytes.Length)) + { + throw new ArgumentOutOfRangeException("offset"); + } + if ((count < 0) || ((offset + count) > bytes.Length)) + { + throw new ArgumentOutOfRangeException("count"); + } + return UrlEncodeBytesToBytesInternal(bytes, offset, count, true); + } + + public static string UrlEncodeUnicode(string str) + { + if (str == null) + { + return null; + } + return UrlEncodeUnicodeStringToStringInternal(str, false); + } + + private static string UrlEncodeUnicodeStringToStringInternal(string s, bool ignoreAscii) + { + int length = s.Length; + StringBuilder builder = new StringBuilder(length); + for (int i = 0; i < length; i++) + { + char ch = s[i]; + if ((ch & 0xff80) == 0) + { + if (ignoreAscii || IsSafe(ch)) + { + builder.Append(ch); + } + else if (ch == ' ') + { + builder.Append('+'); + } + else + { + builder.Append('%'); + builder.Append(IntToHex((ch >> 4) & '\x000f')); + builder.Append(IntToHex(ch & '\x000f')); + } + } + else + { + builder.Append("%u"); + builder.Append(IntToHex((ch >> 12) & '\x000f')); + builder.Append(IntToHex((ch >> 8) & '\x000f')); + builder.Append(IntToHex((ch >> 4) & '\x000f')); + builder.Append(IntToHex(ch & '\x000f')); + } + } + return builder.ToString(); + } + + public static byte[] UrlEncodeUnicodeToBytes(string str) + { + if (str == null) + { + return null; + } + return Encoding.UTF8.GetBytes(UrlEncodeUnicode(str)); + } + + public static string UrlPathEncode(string str) + { + if (str == null) + { + return null; + } + int index = str.IndexOf('?'); + if (index >= 0) + { + return (UrlPathEncode(str.Substring(0, index)) + str.Substring(index)); + } + return UrlEncodeSpaces(UrlEncodeNonAscii(str, Encoding.UTF8)); + } + + // Nested Types + private class UrlDecoder + { + // Fields + private int _bufferSize; + private byte[] _byteBuffer; + private char[] _charBuffer; + private Encoding _encoding; + private int _numBytes; + private int _numChars; + + // Methods + internal UrlDecoder(int bufferSize, Encoding encoding) + { + this._bufferSize = bufferSize; + this._encoding = encoding; + this._charBuffer = new char[bufferSize]; + } + + internal void AddByte(byte b) + { + if (this._byteBuffer == null) + { + this._byteBuffer = new byte[this._bufferSize]; + } + this._byteBuffer[this._numBytes++] = b; + } + + internal void AddChar(char ch) + { + if (this._numBytes > 0) + { + this.FlushBytes(); + } + this._charBuffer[this._numChars++] = ch; + } + + private void FlushBytes() + { + if (this._numBytes > 0) + { + this._numChars += this._encoding.GetChars(this._byteBuffer, 0, this._numBytes, this._charBuffer, this._numChars); + this._numBytes = 0; + } + } + + internal string GetString() + { + if (this._numBytes > 0) + { + this.FlushBytes(); + } + if (this._numChars > 0) + { + return new string(this._charBuffer, 0, this._numChars); + } + return string.Empty; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IAddressEnumerator.cs b/Microsoft.Azure.Cosmos/src/direct/IAddressEnumerator.cs index 5c9a4b559a..df653ba093 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IAddressEnumerator.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IAddressEnumerator.cs @@ -1,18 +1,18 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - - /// - /// AddressEnumerator iterates a list of TransportAddressUris. - /// - internal interface IAddressEnumerator - { - IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris, - Lazy> failedEndpoints, - bool replicaAddressValidationEnabled); - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + + /// + /// AddressEnumerator iterates a list of TransportAddressUris. + /// + internal interface IAddressEnumerator + { + IEnumerable GetTransportAddresses(IReadOnlyList transportAddressUris, + Lazy> failedEndpoints, + bool replicaAddressValidationEnabled); + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IAddressResolver.cs b/Microsoft.Azure.Cosmos/src/direct/IAddressResolver.cs index ca2a88a717..fe653bba90 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IAddressResolver.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IAddressResolver.cs @@ -1,23 +1,23 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Documents.Rntbd; - - internal interface IAddressResolver - { - Task ResolveAsync( - DocumentServiceRequest request, - bool forceRefreshPartitionAddresses, - CancellationToken cancellationToken); - - Task UpdateAsync( - ServerKey serverKey, - CancellationToken cancellationToken = default(CancellationToken)); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Documents.Rntbd; + + internal interface IAddressResolver + { + Task ResolveAsync( + DocumentServiceRequest request, + bool forceRefreshPartitionAddresses, + CancellationToken cancellationToken); + + Task UpdateAsync( + ServerKey serverKey, + CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IAddressResolverExtension.cs b/Microsoft.Azure.Cosmos/src/direct/IAddressResolverExtension.cs index 592641649c..94497326d1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IAddressResolverExtension.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IAddressResolverExtension.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Threading; - using System.Threading.Tasks; - - /// - /// Contain the method to open connection to the backend replicas, using Rntbd context negotiation. - /// This is a temporary interface and will eventually be removed once the OpenConnectionsAsync() method - /// is moved into the . - /// - internal interface IAddressResolverExtension : IAddressResolver - { - /// - /// Invokes the gateway address cache and passes the deligate to be invoked from the same. - /// - /// A string containing the name of the database. - /// A string containing the container's link uri. - /// An Instance of the . - Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default); - - /// - /// Sets the instance to a class level readonly - /// field for invoking the open connection request at a later point of time. - /// - /// An instance of - void SetOpenConnectionsHandler( - IOpenConnectionsHandler openConnectionHandler); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Threading; + using System.Threading.Tasks; + + /// + /// Contain the method to open connection to the backend replicas, using Rntbd context negotiation. + /// This is a temporary interface and will eventually be removed once the OpenConnectionsAsync() method + /// is moved into the . + /// + internal interface IAddressResolverExtension : IAddressResolver + { + /// + /// Invokes the gateway address cache and passes the deligate to be invoked from the same. + /// + /// A string containing the name of the database. + /// A string containing the container's link uri. + /// An Instance of the . + Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default); + + /// + /// Sets the instance to a class level readonly + /// field for invoking the open connection request at a later point of time. + /// + /// An instance of + void SetOpenConnectionsHandler( + IOpenConnectionsHandler openConnectionHandler); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IAuthorizationTokenProvider.cs b/Microsoft.Azure.Cosmos/src/direct/IAuthorizationTokenProvider.cs index f18f7d0369..e3bbdda6fb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IAuthorizationTokenProvider.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IAuthorizationTokenProvider.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System.Threading.Tasks; - using Microsoft.Azure.Documents.Collections; - - internal interface IAuthorizationTokenProvider - { - ValueTask<(string token, string payload)> GetUserAuthorizationAsync( - string resourceAddress, - string resourceType, - string requestVerb, - INameValueCollection headers, - AuthorizationTokenType tokenType); - - Task AddSystemAuthorizationHeaderAsync( - DocumentServiceRequest request, - string federationId, - string verb, - string resourceId); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System.Threading.Tasks; + using Microsoft.Azure.Documents.Collections; + + internal interface IAuthorizationTokenProvider + { + ValueTask<(string token, string payload)> GetUserAuthorizationAsync( + string resourceAddress, + string resourceType, + string requestVerb, + INameValueCollection headers, + AuthorizationTokenType tokenType); + + Task AddSystemAuthorizationHeaderAsync( + DocumentServiceRequest request, + string federationId, + string verb, + string resourceId); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IChannel.cs b/Microsoft.Azure.Cosmos/src/direct/IChannel.cs index 32080ddc03..2dcab252a1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IChannel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IChannel.cs @@ -1,31 +1,31 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Threading.Tasks; - - internal interface IChannel - { - Task RequestAsync( - DocumentServiceRequest request, - TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, - Guid activityId, - TransportRequestStats transportRequestStats); - - /// - /// Opens the Rntbd context negotiation channel to - /// the backend replica node. - /// - /// An unique identifier indicating the current activity id. - /// A completed task indicating oncw the channel is opened. - public Task OpenChannelAsync( - Guid activityId); - - bool Healthy { get; } - - void Close(); - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Threading.Tasks; + + internal interface IChannel + { + Task RequestAsync( + DocumentServiceRequest request, + TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, + Guid activityId, + TransportRequestStats transportRequestStats); + + /// + /// Opens the Rntbd context negotiation channel to + /// the backend replica node. + /// + /// An unique identifier indicating the current activity id. + /// A completed task indicating oncw the channel is opened. + public Task OpenChannelAsync( + Guid activityId); + + bool Healthy { get; } + + void Close(); + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IChannelDictionary.cs b/Microsoft.Azure.Cosmos/src/direct/IChannelDictionary.cs index f4c29f79c1..8c24c36863 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IChannelDictionary.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IChannelDictionary.cs @@ -1,20 +1,20 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - - internal interface IChannelDictionary - { - /// - /// Creates or gets an instance of using the server's physical uri. - /// - /// An instance of containing the backend server URI. - /// A boolean flag indicating if the request is targeting the local region. - /// An instance of containing the . - IChannel GetChannel( - Uri requestUri, - bool localRegionRequest); - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + + internal interface IChannelDictionary + { + /// + /// Creates or gets an instance of using the server's physical uri. + /// + /// An instance of containing the backend server URI. + /// A boolean flag indicating if the request is targeting the local region. + /// An instance of containing the . + IChannel GetChannel( + Uri requestUri, + bool localRegionRequest); + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs index 7359b0e856..d8a2e6036d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs @@ -1,57 +1,57 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Net.Http; - using System.Text; - - internal interface IClientSideRequestStatistics - { - List ContactedReplicas { get; set; } - - HashSet FailedReplicas { get;} - - HashSet<(string, Uri)> RegionsContacted { get;} - - bool? IsCpuHigh { get; } - - bool? IsCpuThreadStarvation { get; } - - void RecordRequest(DocumentServiceRequest request); - - // Note - storeResult may be disposed before use here - void RecordResponse( - DocumentServiceRequest request, - StoreResult storeResult, - DateTime startTimeUtc, - DateTime endTimeUtc); - - void RecordException( - DocumentServiceRequest request, - Exception exception, - DateTime startTimeUtc, - DateTime endTimeUtc); - - string RecordAddressResolutionStart(Uri targetEndpoint); - - void RecordAddressResolutionEnd(string identifier); - - TimeSpan? RequestLatency { get; } - - void AppendToBuilder(StringBuilder stringBuilder); - - void RecordHttpResponse(HttpRequestMessage request, - HttpResponseMessage response, - ResourceType resourceType, - DateTime requestStartTimeUtc); - - void RecordHttpException(HttpRequestMessage request, - Exception exception, - ResourceType resourceType, - DateTime requestStartTimeUtc); - } -} - +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Net.Http; + using System.Text; + + internal interface IClientSideRequestStatistics + { + List ContactedReplicas { get; set; } + + HashSet FailedReplicas { get;} + + HashSet<(string, Uri)> RegionsContacted { get;} + + bool? IsCpuHigh { get; } + + bool? IsCpuThreadStarvation { get; } + + void RecordRequest(DocumentServiceRequest request); + + // Note - storeResult may be disposed before use here + void RecordResponse( + DocumentServiceRequest request, + StoreResult storeResult, + DateTime startTimeUtc, + DateTime endTimeUtc); + + void RecordException( + DocumentServiceRequest request, + Exception exception, + DateTime startTimeUtc, + DateTime endTimeUtc); + + string RecordAddressResolutionStart(Uri targetEndpoint); + + void RecordAddressResolutionEnd(string identifier); + + TimeSpan? RequestLatency { get; } + + void AppendToBuilder(StringBuilder stringBuilder); + + void RecordHttpResponse(HttpRequestMessage request, + HttpResponseMessage response, + ResourceType resourceType, + DateTime requestStartTimeUtc); + + void RecordHttpException(HttpRequestMessage request, + Exception exception, + ResourceType resourceType, + DateTime requestStartTimeUtc); + } +} + diff --git a/Microsoft.Azure.Cosmos/src/direct/ICommunicationEventSource.cs b/Microsoft.Azure.Cosmos/src/direct/ICommunicationEventSource.cs index 0a26a0aed9..ae7284f64a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ICommunicationEventSource.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ICommunicationEventSource.cs @@ -1,15 +1,15 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net.Http.Headers; - - internal interface ICommunicationEventSource - { - void Request(Guid activityId, Guid localId, string uri, string resourceType, HttpRequestHeaders requestHeaders); - - void Response(Guid activityId, Guid localId, short statusCode, double milliseconds, HttpResponseHeaders responseHeaders); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net.Http.Headers; + + internal interface ICommunicationEventSource + { + void Request(Guid activityId, Guid localId, string uri, string resourceType, HttpRequestHeaders requestHeaders); + + void Response(Guid activityId, Guid localId, short statusCode, double milliseconds, HttpResponseHeaders responseHeaders); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IConnectionStateListener.cs b/Microsoft.Azure.Cosmos/src/direct/IConnectionStateListener.cs index 1b5146cd78..e82d85d1a6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IConnectionStateListener.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IConnectionStateListener.cs @@ -1,14 +1,14 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - using Microsoft.Azure.Documents.Rntbd; - - internal interface IConnectionStateListener - { - void OnConnectionEvent(ConnectionEvent connectionEvent, DateTime eventTime, ServerKey serverKey); - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + using Microsoft.Azure.Documents.Rntbd; + + internal interface IConnectionStateListener + { + void OnConnectionEvent(ConnectionEvent connectionEvent, DateTime eventTime, ServerKey serverKey); + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IDocumentResponse.cs b/Microsoft.Azure.Cosmos/src/direct/IDocumentResponse.cs index bb24318aed..68c0ec3a76 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IDocumentResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IDocumentResponse.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Interface exposed for mocking purposes for the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - interface IDocumentResponse : IResourceResponseBase - { - /// - /// Gets the document returned in the response. - /// - /// - /// The document returned in the response. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - TDocument Document { get; } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Interface exposed for mocking purposes for the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + interface IDocumentResponse : IResourceResponseBase + { + /// + /// Gets the document returned in the response. + /// + /// + /// The document returned in the response. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + TDocument Document { get; } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IMasterServiceIdentityProvider.cs b/Microsoft.Azure.Cosmos/src/direct/IMasterServiceIdentityProvider.cs index b482735b4c..fc9fc6abcd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IMasterServiceIdentityProvider.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IMasterServiceIdentityProvider.cs @@ -1,18 +1,18 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Threading; - using System.Threading.Tasks; - - internal interface IMasterServiceIdentityProvider - { - ServiceIdentity MasterServiceIdentity { get; } - - Task RefreshAsync( - ServiceIdentity previousMasterService, - CancellationToken cancellationToken); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Threading; + using System.Threading.Tasks; + + internal interface IMasterServiceIdentityProvider + { + ServiceIdentity MasterServiceIdentity { get; } + + Task RefreshAsync( + ServiceIdentity previousMasterService, + CancellationToken cancellationToken); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/INameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/INameValueCollection.cs index 5ff1a078de..8b2ea4dc02 100644 --- a/Microsoft.Azure.Cosmos/src/direct/INameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/INameValueCollection.cs @@ -1,39 +1,39 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Collections -{ - using System.Collections; - using System.Collections.Generic; - using System.Collections.Specialized; - - internal interface INameValueCollection : IEnumerable - { - void Add(string key, string value); - - void Set(string key, string value); - - string Get(string key); - - string this[string key] { get; set; } - - void Remove(string key); - - void Clear(); - - int Count(); - - INameValueCollection Clone(); - - void Add(INameValueCollection collection); - - string[] GetValues(string key); - - string[] AllKeys(); - - IEnumerable Keys(); - - NameValueCollection ToNameValueCollection(); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Collections +{ + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + + internal interface INameValueCollection : IEnumerable + { + void Add(string key, string value); + + void Set(string key, string value); + + string Get(string key); + + string this[string key] { get; set; } + + void Remove(string key); + + void Clear(); + + int Count(); + + INameValueCollection Clone(); + + void Add(INameValueCollection collection); + + string[] GetValues(string key); + + string[] AllKeys(); + + IEnumerable Keys(); + + NameValueCollection ToNameValueCollection(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/INameValueCollectionFactory.cs b/Microsoft.Azure.Cosmos/src/direct/INameValueCollectionFactory.cs index 2349eb105c..d570dee198 100644 --- a/Microsoft.Azure.Cosmos/src/direct/INameValueCollectionFactory.cs +++ b/Microsoft.Azure.Cosmos/src/direct/INameValueCollectionFactory.cs @@ -1,47 +1,47 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Collections -{ - using System; - using System.Collections.Specialized; - - /// - /// - /// - internal interface INameValueCollectionFactory - { - /// - /// - /// - /// - INameValueCollection CreateNewNameValueCollection(); - - /// - /// - /// - /// - INameValueCollection CreateNewNameValueCollection(int capacity); - - /// - /// - /// - /// - INameValueCollection CreateNewNameValueCollection(StringComparer comparer); - - /// - /// - /// - /// - /// - INameValueCollection CreateNewNameValueCollection(NameValueCollection collection); - - /// - /// - /// - /// - /// - INameValueCollection CreateNewNameValueCollection(INameValueCollection collection); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Collections +{ + using System; + using System.Collections.Specialized; + + /// + /// + /// + internal interface INameValueCollectionFactory + { + /// + /// + /// + /// + INameValueCollection CreateNewNameValueCollection(); + + /// + /// + /// + /// + INameValueCollection CreateNewNameValueCollection(int capacity); + + /// + /// + /// + /// + INameValueCollection CreateNewNameValueCollection(StringComparer comparer); + + /// + /// + /// + /// + /// + INameValueCollection CreateNewNameValueCollection(NameValueCollection collection); + + /// + /// + /// + /// + /// + INameValueCollection CreateNewNameValueCollection(INameValueCollection collection); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IOpenConnectionsHandler.cs b/Microsoft.Azure.Cosmos/src/direct/IOpenConnectionsHandler.cs index 85d72edc49..5988ace6c2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IOpenConnectionsHandler.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IOpenConnectionsHandler.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Collections.Generic; - using System.Threading.Tasks; - - /// - /// Handler interface for opening connections to backend replica nodes. - /// - internal interface IOpenConnectionsHandler - { - /// - /// Uses the transport client instance and attempts to open the Rntbd connection - /// and establish Rntbd context negotiation to the backend replica nodes. - /// - /// An enumerable of - /// containing the backend replica addresses. - Task TryOpenRntbdChannelsAsync( - IEnumerable addresses); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Collections.Generic; + using System.Threading.Tasks; + + /// + /// Handler interface for opening connections to backend replica nodes. + /// + internal interface IOpenConnectionsHandler + { + /// + /// Uses the transport client instance and attempts to open the Rntbd connection + /// and establish Rntbd context negotiation to the backend replica nodes. + /// + /// An enumerable of + /// containing the backend replica addresses. + Task TryOpenRntbdChannelsAsync( + IEnumerable addresses); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/IPartitionKeyComponent.cs index 5f2d3b7990..9f79a0a3f5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IPartitionKeyComponent.cs @@ -1,29 +1,29 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System.IO; - - using Newtonsoft.Json; - - internal interface IPartitionKeyComponent - { - int CompareTo(IPartitionKeyComponent other); - - int GetTypeOrdinal(); - - void JsonEncode(JsonWriter writer); - - object ToObject(); - - void WriteForHashing(BinaryWriter binaryWriter); - - void WriteForHashingV2(BinaryWriter binaryWriter); - - void WriteForBinaryEncoding(BinaryWriter binaryWriter); - - IPartitionKeyComponent Truncate(); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System.IO; + + using Newtonsoft.Json; + + internal interface IPartitionKeyComponent + { + int CompareTo(IPartitionKeyComponent other); + + int GetTypeOrdinal(); + + void JsonEncode(JsonWriter writer); + + object ToObject(); + + void WriteForHashing(BinaryWriter binaryWriter); + + void WriteForHashingV2(BinaryWriter binaryWriter); + + void WriteForBinaryEncoding(BinaryWriter binaryWriter); + + IPartitionKeyComponent Truncate(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IRequestRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/IRequestRetryPolicy.cs index bec7a64f37..68cd5ad6dd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IRequestRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IRequestRetryPolicy.cs @@ -1,58 +1,58 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - /// - /// Retry policy to evaluate a Response or Exception through . - /// - /// The will invoke first and based on the result, it will invoke - internal interface IRequestRetryPolicy - { - /// - /// Method that is called to determine from the policy that needs to retry on the Response. - /// - /// Request that generated the Response. - /// Response to be evaluated. - /// Exception, if any, that was captured during execution. - /// - /// - Task ShouldRetryAsync(TRequest request, TResponse response, Exception exception, CancellationToken cancellationToken); - - /// - /// Tries to handle the response or exception synchronously. - /// - /// Response to be evaluated. - /// Request that generated the Response. - /// Exception, if any, that was captured during execution. - /// Populated if the return value is true. - /// If true, use the value of . If false, call ShouldRetryAsync. - bool TryHandleResponseSynchronously(TRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult); - - /// - /// Method to execute before sending the Request. - /// - /// Request to process. - void OnBeforeSendRequest(TRequest request); - } - - /// - /// Retry policy to evaluate a Response through that includes arguments on the execution call. - /// - /// will be passed on each invocation of the delegate. - internal interface IRequestRetryPolicy : IRequestRetryPolicy - { - /// - /// Get the context from the policy to be sent to the execution context call. - /// - TPolicyContext ExecuteContext - { - get; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Retry policy to evaluate a Response or Exception through . + /// + /// The will invoke first and based on the result, it will invoke + internal interface IRequestRetryPolicy + { + /// + /// Method that is called to determine from the policy that needs to retry on the Response. + /// + /// Request that generated the Response. + /// Response to be evaluated. + /// Exception, if any, that was captured during execution. + /// + /// + Task ShouldRetryAsync(TRequest request, TResponse response, Exception exception, CancellationToken cancellationToken); + + /// + /// Tries to handle the response or exception synchronously. + /// + /// Response to be evaluated. + /// Request that generated the Response. + /// Exception, if any, that was captured during execution. + /// Populated if the return value is true. + /// If true, use the value of . If false, call ShouldRetryAsync. + bool TryHandleResponseSynchronously(TRequest request, TResponse response, Exception exception, out ShouldRetryResult shouldRetryResult); + + /// + /// Method to execute before sending the Request. + /// + /// Request to process. + void OnBeforeSendRequest(TRequest request); + } + + /// + /// Retry policy to evaluate a Response through that includes arguments on the execution call. + /// + /// will be passed on each invocation of the delegate. + internal interface IRequestRetryPolicy : IRequestRetryPolicy + { + /// + /// Get the context from the policy to be sent to the execution context call. + /// + TPolicyContext ExecuteContext + { + get; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IResourceResponse.cs b/Microsoft.Azure.Cosmos/src/direct/IResourceResponse.cs index a8a8842aab..89bcac6a83 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IResourceResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IResourceResponse.cs @@ -1,29 +1,29 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Interface exposed for mocking purposes for the Azure Cosmos DB service. - /// - /// The resource type. -#if COSMOSCLIENT - internal -#else - public -#endif - interface IResourceResponse : IResourceResponseBase where TResource : Resource, new() - { - /// - /// Gets the resource returned in the response. - /// - /// - /// The resource returned in the response. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - TResource Resource { get; } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Interface exposed for mocking purposes for the Azure Cosmos DB service. + /// + /// The resource type. +#if COSMOSCLIENT + internal +#else + public +#endif + interface IResourceResponse : IResourceResponseBase where TResource : Resource, new() + { + /// + /// Gets the resource returned in the response. + /// + /// + /// The resource returned in the response. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + TResource Resource { get; } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IResourceResponseBase.cs b/Microsoft.Azure.Cosmos/src/direct/IResourceResponseBase.cs index df0f09be8c..99107f3f88 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IResourceResponseBase.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IResourceResponseBase.cs @@ -1,343 +1,343 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Client -{ - using System.Collections.Specialized; - using System.IO; - using System.Net; - - /// - /// Represents the non-resource specific service response headers returned by any request in the Azure Cosmos DB service. - /// - /// - /// Interface exposed for mocking purposes for the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - interface IResourceResponseBase - { - /// - /// Gets the maximum quota for database resources within the account. - /// - /// - /// The maximum quota for the account. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long DatabaseQuota { get; } - - /// - /// The current number of database resources within the account. - /// - /// - /// The number of databases. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long DatabaseUsage { get; } - - /// - /// Gets the maximum quota for collection resources within an account. - /// - /// - /// The maximum quota for the account. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long CollectionQuota { get; } - - /// - /// The current number of collection resources within the account. - /// - /// - /// The number of collections. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long CollectionUsage { get; } - - /// - /// Gets the maximum quota for user resources within an account. - /// - /// - /// The maximum quota for the account. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long UserQuota { get; } - - /// - /// The current number of user resources within the account. - /// - /// - /// The number of users. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long UserUsage { get; } - - /// - /// Gets the maximum quota for permission resources within an account. - /// - /// - /// The maximum quota for the account. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long PermissionQuota { get; } - - /// - /// The current number of permission resources within the account. - /// - /// - /// The number of permissions. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long PermissionUsage { get; } - - /// - /// Maximum size of a collection in kilobytes. - /// - /// - /// Quota in kilobytes. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long CollectionSizeQuota { get; } - - /// - /// Current size of a collection in kilobytes. - /// - /// - /// Current collection size in kilobytes. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long CollectionSizeUsage { get; } - - /// - /// Maximum size of a documents within a collection in kilobytes. - /// - /// - /// Quota in kilobytes. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long DocumentQuota { get; } - - /// - /// Current size of documents within a collection in kilobytes. - /// - /// - /// Current documents size in kilobytes. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long DocumentUsage { get; } - - /// - /// Gets the maximum quota of stored procedures for a collection. - /// - /// - /// The maximum quota. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long StoredProceduresQuota { get; } - - /// - /// The current number of stored procedures for a collection. - /// - /// - /// Current number of stored procedures. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long StoredProceduresUsage { get; } - - /// - /// Gets the maximum quota of triggers for a collection. - /// - /// - /// The maximum quota. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long TriggersQuota { get; } - - /// - /// The current number of triggers for a collection. - /// - /// - /// Current number of triggers. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long TriggersUsage { get; } - - /// - /// Gets the maximum quota of user defined functions for a collection. - /// - /// - /// Maximum quota. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long UserDefinedFunctionsQuota { get; } - - /// - /// The current number of user defined functions for a collection. - /// - /// - /// Current number of user defined functions. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long UserDefinedFunctionsUsage { get; } - - /// - /// Gets the activity ID for the request. - /// - /// - /// The activity ID for the request. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - string ActivityId { get; } - - /// - /// Gets the session token for use in sesssion consistency reads. - /// - /// - /// The session token for use in session consistency. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - string SessionToken { get; } - - /// - /// Gets the HTTP status code associated with the response. - /// - /// - /// The HTTP status code associated with the response. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - HttpStatusCode StatusCode { get; } - - /// - /// Gets the maximum size limit for this entity. - /// - /// - /// The maximum size limit for this entity. Measured in kilobytes for document resources - /// and in counts for other resources. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - string MaxResourceQuota { get; } - - /// - /// Gets the current size of this entity. - /// - /// - /// The current size for this entity. Measured in kilobytes for document resources - /// and in counts for other resources. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - string CurrentResourceQuotaUsage { get; } - - /// - /// Gets the underlying stream of the response. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - Stream ResponseStream { get; } - - /// - /// Gets the request charge for this request. - /// - /// - /// The request charge measured in reqest units. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - double RequestCharge { get; } - - /// - /// Gets the response headers. - /// - /// - /// The response headers. - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - NameValueCollection ResponseHeaders { get; } - - /// - /// The content parent location, for example, dbs/foo/colls/bar - /// - /// - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - string ContentLocation { get; } - - /// - /// Gets the progress of an index transformation, if one is underway. - /// - /// - /// An integer from 0 to 100 representing percentage completion of the index transformation process. - /// Returns -1 if the index transformation progress header could not be found. - /// - /// - /// An index will be rebuilt when the IndexPolicy of a collection is updated. - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long IndexTransformationProgress { get; } - - /// - /// Gets the progress of lazy indexing. - /// - /// - /// An integer from 0 to 100 representing percentage completion of the lazy indexing process. - /// Returns -1 if the lazy indexing progress header could not be found. - /// - /// - /// Lazy indexing progress only applies to the collection with indexing mode Lazy. - /// This is exposed for mocking purposes for the Azure Cosmos DB service. - /// - long LazyIndexingProgress { get; } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Client +{ + using System.Collections.Specialized; + using System.IO; + using System.Net; + + /// + /// Represents the non-resource specific service response headers returned by any request in the Azure Cosmos DB service. + /// + /// + /// Interface exposed for mocking purposes for the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + interface IResourceResponseBase + { + /// + /// Gets the maximum quota for database resources within the account. + /// + /// + /// The maximum quota for the account. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long DatabaseQuota { get; } + + /// + /// The current number of database resources within the account. + /// + /// + /// The number of databases. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long DatabaseUsage { get; } + + /// + /// Gets the maximum quota for collection resources within an account. + /// + /// + /// The maximum quota for the account. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long CollectionQuota { get; } + + /// + /// The current number of collection resources within the account. + /// + /// + /// The number of collections. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long CollectionUsage { get; } + + /// + /// Gets the maximum quota for user resources within an account. + /// + /// + /// The maximum quota for the account. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long UserQuota { get; } + + /// + /// The current number of user resources within the account. + /// + /// + /// The number of users. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long UserUsage { get; } + + /// + /// Gets the maximum quota for permission resources within an account. + /// + /// + /// The maximum quota for the account. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long PermissionQuota { get; } + + /// + /// The current number of permission resources within the account. + /// + /// + /// The number of permissions. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long PermissionUsage { get; } + + /// + /// Maximum size of a collection in kilobytes. + /// + /// + /// Quota in kilobytes. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long CollectionSizeQuota { get; } + + /// + /// Current size of a collection in kilobytes. + /// + /// + /// Current collection size in kilobytes. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long CollectionSizeUsage { get; } + + /// + /// Maximum size of a documents within a collection in kilobytes. + /// + /// + /// Quota in kilobytes. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long DocumentQuota { get; } + + /// + /// Current size of documents within a collection in kilobytes. + /// + /// + /// Current documents size in kilobytes. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long DocumentUsage { get; } + + /// + /// Gets the maximum quota of stored procedures for a collection. + /// + /// + /// The maximum quota. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long StoredProceduresQuota { get; } + + /// + /// The current number of stored procedures for a collection. + /// + /// + /// Current number of stored procedures. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long StoredProceduresUsage { get; } + + /// + /// Gets the maximum quota of triggers for a collection. + /// + /// + /// The maximum quota. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long TriggersQuota { get; } + + /// + /// The current number of triggers for a collection. + /// + /// + /// Current number of triggers. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long TriggersUsage { get; } + + /// + /// Gets the maximum quota of user defined functions for a collection. + /// + /// + /// Maximum quota. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long UserDefinedFunctionsQuota { get; } + + /// + /// The current number of user defined functions for a collection. + /// + /// + /// Current number of user defined functions. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long UserDefinedFunctionsUsage { get; } + + /// + /// Gets the activity ID for the request. + /// + /// + /// The activity ID for the request. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + string ActivityId { get; } + + /// + /// Gets the session token for use in sesssion consistency reads. + /// + /// + /// The session token for use in session consistency. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + string SessionToken { get; } + + /// + /// Gets the HTTP status code associated with the response. + /// + /// + /// The HTTP status code associated with the response. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + HttpStatusCode StatusCode { get; } + + /// + /// Gets the maximum size limit for this entity. + /// + /// + /// The maximum size limit for this entity. Measured in kilobytes for document resources + /// and in counts for other resources. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + string MaxResourceQuota { get; } + + /// + /// Gets the current size of this entity. + /// + /// + /// The current size for this entity. Measured in kilobytes for document resources + /// and in counts for other resources. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + string CurrentResourceQuotaUsage { get; } + + /// + /// Gets the underlying stream of the response. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + Stream ResponseStream { get; } + + /// + /// Gets the request charge for this request. + /// + /// + /// The request charge measured in reqest units. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + double RequestCharge { get; } + + /// + /// Gets the response headers. + /// + /// + /// The response headers. + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + NameValueCollection ResponseHeaders { get; } + + /// + /// The content parent location, for example, dbs/foo/colls/bar + /// + /// + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + string ContentLocation { get; } + + /// + /// Gets the progress of an index transformation, if one is underway. + /// + /// + /// An integer from 0 to 100 representing percentage completion of the index transformation process. + /// Returns -1 if the index transformation progress header could not be found. + /// + /// + /// An index will be rebuilt when the IndexPolicy of a collection is updated. + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long IndexTransformationProgress { get; } + + /// + /// Gets the progress of lazy indexing. + /// + /// + /// An integer from 0 to 100 representing percentage completion of the lazy indexing process. + /// Returns -1 if the lazy indexing progress header could not be found. + /// + /// + /// Lazy indexing progress only applies to the collection with indexing mode Lazy. + /// This is exposed for mocking purposes for the Azure Cosmos DB service. + /// + long LazyIndexingProgress { get; } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IRetriableResponse.cs b/Microsoft.Azure.Cosmos/src/direct/IRetriableResponse.cs index d55419f9ad..888adce5b5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IRetriableResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IRetriableResponse.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Net; - - /// - /// Service response that can be evaluated through an IRequestRetryPolicy and . - /// - internal interface IRetriableResponse - { - /// - /// in the service response. - /// - HttpStatusCode StatusCode { get; } - - /// - /// in the service response. - /// - SubStatusCodes SubStatusCode { get; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Net; + + /// + /// Service response that can be evaluated through an IRequestRetryPolicy and . + /// + internal interface IRetriableResponse + { + /// + /// in the service response. + /// + HttpStatusCode StatusCode { get; } + + /// + /// in the service response. + /// + SubStatusCodes SubStatusCode { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/IRetryPolicy.cs index 562aa32dc0..8a867bf517 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IRetryPolicy.cs @@ -1,123 +1,123 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Runtime.ExceptionServices; - using System.Threading; - using System.Threading.Tasks; - - internal class ShouldRetryResult - { - private static readonly ShouldRetryResult EmptyNoRetry = new ShouldRetryResult { ShouldRetry = false }; - - protected ShouldRetryResult() - { - } - - public bool ShouldRetry { get; protected set; } - - /// - /// How long to wait before next retry. 0 indicates retry immediately. - /// - public TimeSpan BackoffTime { get; protected set; } - - /// - /// - /// - public Exception ExceptionToThrow { get; protected set; } - - public void ThrowIfDoneTrying(ExceptionDispatchInfo capturedException) - { - if (this.ShouldRetry) - { - return; - } - if (this.ExceptionToThrow == null) - { - capturedException.Throw(); - } - if (capturedException != null && object.ReferenceEquals( - this.ExceptionToThrow, capturedException.SourceException)) - { - capturedException.Throw(); - } - else - { - throw this.ExceptionToThrow; - } - } - - public static ShouldRetryResult NoRetry(Exception exception = null) - { - if (exception == null) - { - return ShouldRetryResult.EmptyNoRetry; - } - - return new ShouldRetryResult { ShouldRetry = false, ExceptionToThrow = exception }; - } - - public static ShouldRetryResult RetryAfter(TimeSpan backoffTime) - { - return new ShouldRetryResult { ShouldRetry = true, BackoffTime = backoffTime }; - } - } - - internal class ShouldRetryResult : ShouldRetryResult - { - private static readonly ShouldRetryResult EmptyNoRetry = new ShouldRetryResult { ShouldRetry = false }; - - /// - /// Argument to be passed to the callback method. - /// - public TPolicyArg1 PolicyArg1 { get; private set; } - - public static new ShouldRetryResult NoRetry(Exception exception = null) - { - if (exception == null) - { - return ShouldRetryResult.EmptyNoRetry; - } - - return new ShouldRetryResult { ShouldRetry = false, ExceptionToThrow = exception }; - } - - public static ShouldRetryResult RetryAfter(TimeSpan backoffTime, TPolicyArg1 policyArg1) - { - return new ShouldRetryResult { ShouldRetry = true, BackoffTime = backoffTime, PolicyArg1 = policyArg1 }; - } - } - - internal interface IRetryPolicy - { - /// - /// Method that is called to determine from the policy that needs to retry on the exception - /// - /// Exception during the callback method invocation - /// - /// If the retry needs to be attempted or not - Task ShouldRetryAsync(Exception exception, CancellationToken cancellationToken); - } - - internal interface IRetryPolicy - { - /// - /// Method that is called to determine from the policy that needs to retry on the exception - /// - /// Exception during the callback method invocation - /// - /// If the retry needs to be attempted or not - Task> ShouldRetryAsync(Exception exception, CancellationToken cancellationToken); - - /// - /// Initial value of the template argument - /// - TPolicyArg1 InitialArgumentValue - { - get; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Runtime.ExceptionServices; + using System.Threading; + using System.Threading.Tasks; + + internal class ShouldRetryResult + { + private static readonly ShouldRetryResult EmptyNoRetry = new ShouldRetryResult { ShouldRetry = false }; + + protected ShouldRetryResult() + { + } + + public bool ShouldRetry { get; protected set; } + + /// + /// How long to wait before next retry. 0 indicates retry immediately. + /// + public TimeSpan BackoffTime { get; protected set; } + + /// + /// + /// + public Exception ExceptionToThrow { get; protected set; } + + public void ThrowIfDoneTrying(ExceptionDispatchInfo capturedException) + { + if (this.ShouldRetry) + { + return; + } + if (this.ExceptionToThrow == null) + { + capturedException.Throw(); + } + if (capturedException != null && object.ReferenceEquals( + this.ExceptionToThrow, capturedException.SourceException)) + { + capturedException.Throw(); + } + else + { + throw this.ExceptionToThrow; + } + } + + public static ShouldRetryResult NoRetry(Exception exception = null) + { + if (exception == null) + { + return ShouldRetryResult.EmptyNoRetry; + } + + return new ShouldRetryResult { ShouldRetry = false, ExceptionToThrow = exception }; + } + + public static ShouldRetryResult RetryAfter(TimeSpan backoffTime) + { + return new ShouldRetryResult { ShouldRetry = true, BackoffTime = backoffTime }; + } + } + + internal class ShouldRetryResult : ShouldRetryResult + { + private static readonly ShouldRetryResult EmptyNoRetry = new ShouldRetryResult { ShouldRetry = false }; + + /// + /// Argument to be passed to the callback method. + /// + public TPolicyArg1 PolicyArg1 { get; private set; } + + public static new ShouldRetryResult NoRetry(Exception exception = null) + { + if (exception == null) + { + return ShouldRetryResult.EmptyNoRetry; + } + + return new ShouldRetryResult { ShouldRetry = false, ExceptionToThrow = exception }; + } + + public static ShouldRetryResult RetryAfter(TimeSpan backoffTime, TPolicyArg1 policyArg1) + { + return new ShouldRetryResult { ShouldRetry = true, BackoffTime = backoffTime, PolicyArg1 = policyArg1 }; + } + } + + internal interface IRetryPolicy + { + /// + /// Method that is called to determine from the policy that needs to retry on the exception + /// + /// Exception during the callback method invocation + /// + /// If the retry needs to be attempted or not + Task ShouldRetryAsync(Exception exception, CancellationToken cancellationToken); + } + + internal interface IRetryPolicy + { + /// + /// Method that is called to determine from the policy that needs to retry on the exception + /// + /// Exception during the callback method invocation + /// + /// If the retry needs to be attempted or not + Task> ShouldRetryAsync(Exception exception, CancellationToken cancellationToken); + + /// + /// Initial value of the template argument + /// + TPolicyArg1 InitialArgumentValue + { + get; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReader.cs b/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReader.cs index ac7c2fd7de..beca8fb310 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReader.cs @@ -1,42 +1,42 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading.Tasks; - - /// - /// Interface for resolving the service settings. - /// Implementations: - /// GatewayServiceConfigurationReader: Client implementation. - /// - internal interface IServiceConfigurationReader - { - string DatabaseAccountId { get; } - - Uri DatabaseAccountApiEndpoint { get; } - - ReplicationPolicy UserReplicationPolicy { get; } - - ReplicationPolicy SystemReplicationPolicy { get; } - - ConsistencyLevel DefaultConsistencyLevel { get; } - - ReadPolicy ReadPolicy {get;} - - string PrimaryMasterKey { get; } - string SecondaryMasterKey { get; } - - string PrimaryReadonlyMasterKey { get; } - - string SecondaryReadonlyMasterKey { get; } - - string ResourceSeedKey { get; } - - string SubscriptionId { get; } - - Task InitializeAsync(); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading.Tasks; + + /// + /// Interface for resolving the service settings. + /// Implementations: + /// GatewayServiceConfigurationReader: Client implementation. + /// + internal interface IServiceConfigurationReader + { + string DatabaseAccountId { get; } + + Uri DatabaseAccountApiEndpoint { get; } + + ReplicationPolicy UserReplicationPolicy { get; } + + ReplicationPolicy SystemReplicationPolicy { get; } + + ConsistencyLevel DefaultConsistencyLevel { get; } + + ReadPolicy ReadPolicy {get;} + + string PrimaryMasterKey { get; } + string SecondaryMasterKey { get; } + + string PrimaryReadonlyMasterKey { get; } + + string SecondaryReadonlyMasterKey { get; } + + string ResourceSeedKey { get; } + + string SubscriptionId { get; } + + Task InitializeAsync(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ISessionContainer.cs b/Microsoft.Azure.Cosmos/src/direct/ISessionContainer.cs index eee5200b7b..d5d53eb2a6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ISessionContainer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ISessionContainer.cs @@ -1,56 +1,56 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Microsoft.Azure.Documents.Collections; - - interface ISessionContainer - { - /// - /// Returns a serialized map of partitionKeyRangeId to session token. If a entity is name based then the method extracts name from - /// ResourceAddress and use it to identify collection otherwise it uses ResourceId. Returns empty string if collection is unknown - /// - string ResolveGlobalSessionToken(DocumentServiceRequest entity); - - /// - /// Returns a session token identified by partitionKeyRangeId(*) from a collection identified either by ResourceAddress (in case - /// of name based entity) or either by ResourceId. - /// (*) If partitionKeyRangeId is not in the collection's partitionKeyRangeId -> token map then method - /// iterates through request.RequestContext.ResolvedPartitionKeyRange.Parents starting from tail and - /// returns a corresponding token if there is a match. - /// - ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest entity, string partitionKeyRangeId); - - /// - /// Atomicly: removes partitionKeyRangeId -> token map assosiated with collectionFullname, maps collectionFullname to resourceId and - /// removes its map as well. - /// - void ClearTokenByCollectionFullname(string collectionFullname); - - /// - /// Atomicly: removes partitionKeyRangeId -> token map assosiated with resourceId, maps resourceId to collectionFullname and removes its map as well - /// - void ClearTokenByResourceId(string resourceId); - - /// - /// Infers collectionName using responseHeaders[HttpConstants.HttpHeaders.OwnerFullName] or request.ResourceAddress, - /// infers resourceId using responseHeaders[HttpConstants.HttpHeaders.OwnerId] or request.ResourceId, - /// and adds responseHeaders[HttpConstants.HttpHeaders.SessionToken] session token to the (collectionName, resourceId)'s - /// partitionKeyRangeId -> token map. - /// NB: Silently does nothing for master queries, or when it's impossible to infer collectionRid and collectionFullname - /// from the request, or then SessionToken is missing in responseHeader. - /// - void SetSessionToken(DocumentServiceRequest request, INameValueCollection responseHeader); - - /// - /// Adds responseHeaders[HttpConstants.HttpHeaders.SessionToken] session token to the (collectionName, collectionRid)'s - /// partitionKeyRangeId -> token map. - /// - /// - /// - /// - void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Microsoft.Azure.Documents.Collections; + + interface ISessionContainer + { + /// + /// Returns a serialized map of partitionKeyRangeId to session token. If a entity is name based then the method extracts name from + /// ResourceAddress and use it to identify collection otherwise it uses ResourceId. Returns empty string if collection is unknown + /// + string ResolveGlobalSessionToken(DocumentServiceRequest entity); + + /// + /// Returns a session token identified by partitionKeyRangeId(*) from a collection identified either by ResourceAddress (in case + /// of name based entity) or either by ResourceId. + /// (*) If partitionKeyRangeId is not in the collection's partitionKeyRangeId -> token map then method + /// iterates through request.RequestContext.ResolvedPartitionKeyRange.Parents starting from tail and + /// returns a corresponding token if there is a match. + /// + ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest entity, string partitionKeyRangeId); + + /// + /// Atomicly: removes partitionKeyRangeId -> token map assosiated with collectionFullname, maps collectionFullname to resourceId and + /// removes its map as well. + /// + void ClearTokenByCollectionFullname(string collectionFullname); + + /// + /// Atomicly: removes partitionKeyRangeId -> token map assosiated with resourceId, maps resourceId to collectionFullname and removes its map as well + /// + void ClearTokenByResourceId(string resourceId); + + /// + /// Infers collectionName using responseHeaders[HttpConstants.HttpHeaders.OwnerFullName] or request.ResourceAddress, + /// infers resourceId using responseHeaders[HttpConstants.HttpHeaders.OwnerId] or request.ResourceId, + /// and adds responseHeaders[HttpConstants.HttpHeaders.SessionToken] session token to the (collectionName, resourceId)'s + /// partitionKeyRangeId -> token map. + /// NB: Silently does nothing for master queries, or when it's impossible to infer collectionRid and collectionFullname + /// from the request, or then SessionToken is missing in responseHeader. + /// + void SetSessionToken(DocumentServiceRequest request, INameValueCollection responseHeader); + + /// + /// Adds responseHeaders[HttpConstants.HttpHeaders.SessionToken] session token to the (collectionName, collectionRid)'s + /// partitionKeyRangeId -> token map. + /// + /// + /// + /// + void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ISessionToken.cs b/Microsoft.Azure.Cosmos/src/direct/ISessionToken.cs index 8a09e3250b..ec7ef25552 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ISessionToken.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ISessionToken.cs @@ -1,43 +1,43 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Models session token. There are two implementations of this interface: - /// 1. available for clients with version onwards - /// 2. available for clients with versions before - /// Internal format/implementation should be opaque to its caller. - /// - /// We make assumption that instances of this interface are immutable (read only after they are constructed), so if you want to change - /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. - /// - internal interface ISessionToken : IEquatable - { - /// - /// Returns true if this instance of session token is valid with respect to session token. - /// This is used to decide if the the client can accept server's response (based on comparison between client's - /// and server's session token) - /// - /// Session token to validate - /// true if this instance of session token is valid with respect to session token; - /// false otherwise - bool IsValid(ISessionToken other); - - /// - /// Returns a new instance of session token obtained by merging this session token with the given session token . - /// - /// Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) - /// - /// Other session token to merge - /// Instance of merged session token - ISessionToken Merge(ISessionToken other); - - long LSN { get; } - - string ConvertToString(); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Models session token. There are two implementations of this interface: + /// 1. available for clients with version onwards + /// 2. available for clients with versions before + /// Internal format/implementation should be opaque to its caller. + /// + /// We make assumption that instances of this interface are immutable (read only after they are constructed), so if you want to change + /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. + /// + internal interface ISessionToken : IEquatable + { + /// + /// Returns true if this instance of session token is valid with respect to session token. + /// This is used to decide if the the client can accept server's response (based on comparison between client's + /// and server's session token) + /// + /// Session token to validate + /// true if this instance of session token is valid with respect to session token; + /// false otherwise + bool IsValid(ISessionToken other); + + /// + /// Returns a new instance of session token obtained by merging this session token with the given session token . + /// + /// Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) + /// + /// Other session token to merge + /// Instance of merged session token + ISessionToken Merge(ISessionToken other); + + long LSN { get; } + + string ConvertToString(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IStoreClient.cs b/Microsoft.Azure.Cosmos/src/direct/IStoreClient.cs index b34c55612a..45bca39cce 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IStoreClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IStoreClient.cs @@ -1,40 +1,40 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - /// - /// Contain the methods responsible for - /// - Opening the Rntbd Direct connection to the backend replica nodes and - /// - Sending the to the backend replica nodes for processing. - /// - internal interface IStoreClient - { - /// - /// Invokes the replicated resource client and returns the document service response from the backend replica nodes. - /// - /// A instance of holding the request payload. - /// An instance of defining the retry policy. - /// An Instance of the . - /// A task of containing the response body. - Task ProcessMessageAsync( - DocumentServiceRequest request, - IRetryPolicy retryPolicy = null, - CancellationToken cancellationToken = default); - - /// - /// Establishes and Initializes the Rntbd Direct connection to the backend replica nodes for the given database name and container. - /// - /// A string containing the name of the database. - /// A string containing the container's link uri - /// An Instance of the . - Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Contain the methods responsible for + /// - Opening the Rntbd Direct connection to the backend replica nodes and + /// - Sending the to the backend replica nodes for processing. + /// + internal interface IStoreClient + { + /// + /// Invokes the replicated resource client and returns the document service response from the backend replica nodes. + /// + /// A instance of holding the request payload. + /// An instance of defining the retry policy. + /// An Instance of the . + /// A task of containing the response body. + Task ProcessMessageAsync( + DocumentServiceRequest request, + IRetryPolicy retryPolicy = null, + CancellationToken cancellationToken = default); + + /// + /// Establishes and Initializes the Rntbd Direct connection to the backend replica nodes for the given database name and container. + /// + /// A string containing the name of the database. + /// A string containing the container's link uri + /// An Instance of the . + Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IStoreClientFactory.cs b/Microsoft.Azure.Cosmos/src/direct/IStoreClientFactory.cs index 0ccb0f525a..dd3d02fd01 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IStoreClientFactory.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IStoreClientFactory.cs @@ -1,23 +1,23 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - internal interface IStoreClientFactory: IDisposable - { - StoreClient CreateStoreClient( - IAddressResolver addressResolver, - ISessionContainer sessionContainer, - IServiceConfigurationReader serviceConfigurationReader, - IAuthorizationTokenProvider authorizationTokenProvider, - bool enableRequestDiagnostics = false, - bool enableReadRequestsFallback = false, - bool useFallbackClient = true, - bool useMultipleWriteLocations = false, - bool detectClientConnectivityIssues = false, - bool enableReplicaValidation = false); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + internal interface IStoreClientFactory: IDisposable + { + StoreClient CreateStoreClient( + IAddressResolver addressResolver, + ISessionContainer sessionContainer, + IServiceConfigurationReader serviceConfigurationReader, + IAuthorizationTokenProvider authorizationTokenProvider, + bool enableRequestDiagnostics = false, + bool enableReadRequestsFallback = false, + bool useFallbackClient = true, + bool useMultipleWriteLocations = false, + bool detectClientConnectivityIssues = false, + bool enableReplicaValidation = false); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IStoreModel.cs b/Microsoft.Azure.Cosmos/src/direct/IStoreModel.cs index acb36af3d1..ee46da4f1e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IStoreModel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IStoreModel.cs @@ -1,14 +1,14 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - internal interface IStoreModel : IDisposable - { - Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + internal interface IStoreModel : IDisposable + { + Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IStoreModelExtension.cs b/Microsoft.Azure.Cosmos/src/direct/IStoreModelExtension.cs index def24d9d33..a553867612 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IStoreModelExtension.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IStoreModelExtension.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - /// - /// Contains the helper methods to open connection to the backend replicas, using Rntbd context negotiation. - /// This is a temporary interface and will eventually be removed once the OpenConnectionsAsync() method - /// is moved into the . - /// - internal interface IStoreModelExtension : IStoreModel - { - /// - /// Establishes and Initializes the Rntbd connection to all the backend replica nodes for the given database name and container. - /// - /// A string containing the name of the database. - /// A string containing the container's link uri - /// An Instance of the . - Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Contains the helper methods to open connection to the backend replicas, using Rntbd context negotiation. + /// This is a temporary interface and will eventually be removed once the OpenConnectionsAsync() method + /// is moved into the . + /// + internal interface IStoreModelExtension : IStoreModel + { + /// + /// Establishes and Initializes the Rntbd connection to all the backend replica nodes for the given database name and container. + /// + /// A string containing the name of the database. + /// A string containing the container's link uri + /// An Instance of the . + Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ITypeResolver.cs b/Microsoft.Azure.Cosmos/src/direct/ITypeResolver.cs index a3bab6b194..04db2f667b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ITypeResolver.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ITypeResolver.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json.Linq; - - /// - /// Type resolver based on an input - /// - /// Type T for which the resolver returns correct object of T in T's hierarchy - internal interface ITypeResolver where T : JsonSerializable - { - /// - /// Returns a reference of an object in T's hierarchy based on a property bag. - /// - /// Property bag used to deserialize T - /// Object of type T - T Resolve(JObject propertyBag); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json.Linq; + + /// + /// Type resolver based on an input + /// + /// Type T for which the resolver returns correct object of T in T's hierarchy + internal interface ITypeResolver where T : JsonSerializable + { + /// + /// Returns a reference of an object in T's hierarchy based on a property bag. + /// + /// Property bag used to deserialize T + /// Object of type T + T Resolve(JObject propertyBag); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs b/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs index 199261cc91..f71f1635c6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs @@ -1,98 +1,98 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - internal class InAccountRestoreParameters : JsonSerializable - { - public InAccountRestoreParameters() - { - } - - /// - /// Gets or sets the after triggering the InAccount Restore as part of RestoreParameters - /// - /// - /// A valid value should have unique InstanceId in restore parameters. - /// - [JsonProperty(PropertyName = Constants.Properties.InstanceId)] - public string InstanceId - { - get { return base.GetValue(Constants.Properties.InstanceId); } - set { base.SetValue(Constants.Properties.InstanceId, value); } - } - - /// - /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters - /// - /// - /// A valid value should have a DateTime Value which represents the restore time - /// - [JsonConverter(typeof(IsoDateTimeConverter))] - [JsonProperty(PropertyName = Constants.Properties.RestoreTimestampInUtc)] - public DateTime RestoreTimestampInUtc - { - get { return base.GetValue(Constants.Properties.RestoreTimestampInUtc); } - set { base.SetValue(Constants.Properties.RestoreTimestampInUtc, value); } - } - - /// - /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters - /// - /// - /// A valid value should have the RestoreSource url with the restorableDatabaseAccount instance id - /// - [JsonProperty(PropertyName = Constants.Properties.RestoreSource)] - public string RestoreSource - { - get { return base.GetValue(Constants.Properties.RestoreSource); } - set { base.SetValue(Constants.Properties.RestoreSource, value); } - } - - /// - /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters - /// - /// - /// A valid value should have location info about the source backup - /// - [JsonProperty(PropertyName = Constants.Properties.SourceBackupLocation)] - public string SourceBackupLocation - { - get { return base.GetValue(Constants.Properties.SourceBackupLocation); } - set { base.SetValue(Constants.Properties.SourceBackupLocation, value); } - } - - /// - /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters - /// - /// - /// A valid value should be true or false - /// - [JsonProperty(PropertyName = Constants.Properties.RestoreWithTTLDisabled)] - public bool RestoreWithTTLDisabled - { - get { return base.GetValue(Constants.Properties.RestoreWithTTLDisabled); } - set { base.SetValue(Constants.Properties.RestoreWithTTLDisabled, value); } - } - - internal override void Validate() - { - base.Validate(); - - if (this.RestoreTimestampInUtc == default) - { - throw new BadRequestException($"{Constants.Properties.RestoreTimestampInUtc} is a required input for in account restore request"); - } - - if (string.IsNullOrEmpty(this.RestoreSource)) - { - throw new BadRequestException($"{Constants.Properties.RestoreSource} is a required input for in account restore request"); - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + internal class InAccountRestoreParameters : JsonSerializable + { + public InAccountRestoreParameters() + { + } + + /// + /// Gets or sets the after triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should have unique InstanceId in restore parameters. + /// + [JsonProperty(PropertyName = Constants.Properties.InstanceId)] + public string InstanceId + { + get { return base.GetValue(Constants.Properties.InstanceId); } + set { base.SetValue(Constants.Properties.InstanceId, value); } + } + + /// + /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should have a DateTime Value which represents the restore time + /// + [JsonConverter(typeof(IsoDateTimeConverter))] + [JsonProperty(PropertyName = Constants.Properties.RestoreTimestampInUtc)] + public DateTime RestoreTimestampInUtc + { + get { return base.GetValue(Constants.Properties.RestoreTimestampInUtc); } + set { base.SetValue(Constants.Properties.RestoreTimestampInUtc, value); } + } + + /// + /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should have the RestoreSource url with the restorableDatabaseAccount instance id + /// + [JsonProperty(PropertyName = Constants.Properties.RestoreSource)] + public string RestoreSource + { + get { return base.GetValue(Constants.Properties.RestoreSource); } + set { base.SetValue(Constants.Properties.RestoreSource, value); } + } + + /// + /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should have location info about the source backup + /// + [JsonProperty(PropertyName = Constants.Properties.SourceBackupLocation)] + public string SourceBackupLocation + { + get { return base.GetValue(Constants.Properties.SourceBackupLocation); } + set { base.SetValue(Constants.Properties.SourceBackupLocation, value); } + } + + /// + /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should be true or false + /// + [JsonProperty(PropertyName = Constants.Properties.RestoreWithTtlDisabled)] + public bool RestoreWithTtlDisabled + { + get { return base.GetValue(Constants.Properties.RestoreWithTtlDisabled); } + set { base.SetValue(Constants.Properties.RestoreWithTtlDisabled, value); } + } + + internal override void Validate() + { + base.Validate(); + + if (this.RestoreTimestampInUtc == default) + { + throw new BadRequestException($"{Constants.Properties.RestoreTimestampInUtc} is a required input for in account restore request"); + } + + if (string.IsNullOrEmpty(this.RestoreSource)) + { + throw new BadRequestException($"{Constants.Properties.RestoreSource} is a required input for in account restore request"); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IncludedPath.cs b/Microsoft.Azure.Cosmos/src/direct/IncludedPath.cs index b5de5185e8..62216eefd7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IncludedPath.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IncludedPath.cs @@ -1,131 +1,131 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - - /// - /// Specifies a path within a JSON document to be included in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class IncludedPath : JsonSerializable, ICloneable - { - private Collection indexes; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public IncludedPath() - { - } - - /// - /// Gets or sets the path to be indexed in the Azure Cosmos DB service. - /// - /// - /// The path to be indexed. - /// - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for how to specify paths. - /// Some valid examples: /"prop"/?, /"prop"/**, /"prop"/"subprop"/?, /"prop"/[]/? - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get - { - return base.GetValue(Constants.Properties.Path); - } - set - { - base.SetValue(Constants.Properties.Path, value); - } - } - - /// - /// Gets or sets the collection of objects to be applied for this included path in the Azure Cosmos DB service. - /// - /// - /// The collection of the objects to be applied for this included path. - /// - [JsonProperty(PropertyName = Constants.Properties.Indexes)] - public Collection Indexes - { - get - { - if (this.indexes == null) - { - this.indexes = base.GetValue>(Constants.Properties.Indexes); - - if (this.indexes == null) - { - this.indexes = new Collection(); - } - } - - return this.indexes; - } - set - { - if (value == null) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, RMResources.PropertyCannotBeNull, "Indexes")); - } - - this.indexes = value; - base.SetValue(Constants.Properties.Indexes, value); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Path); - foreach (Index index in this.Indexes) - { - index.Validate(); - } - } - - internal override void OnSave() - { - if (this.indexes != null) - { - foreach (Index index in this.indexes) - { - index.OnSave(); - } - - base.SetValue(Constants.Properties.Indexes, this.indexes); - } - } - - /// - /// Creates a copy of the included path in the Azure Cosmos DB service. - /// - /// A clone of the included path. - public object Clone() - { - IncludedPath cloned = new IncludedPath() - { - Path = this.Path - }; - - foreach (Index item in this.Indexes) - { - cloned.Indexes.Add(item); - } - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Specifies a path within a JSON document to be included in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class IncludedPath : JsonSerializable, ICloneable + { + private Collection indexes; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public IncludedPath() + { + } + + /// + /// Gets or sets the path to be indexed in the Azure Cosmos DB service. + /// + /// + /// The path to be indexed. + /// + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for how to specify paths. + /// Some valid examples: /"prop"/?, /"prop"/**, /"prop"/"subprop"/?, /"prop"/[]/? + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get + { + return base.GetValue(Constants.Properties.Path); + } + set + { + base.SetValue(Constants.Properties.Path, value); + } + } + + /// + /// Gets or sets the collection of objects to be applied for this included path in the Azure Cosmos DB service. + /// + /// + /// The collection of the objects to be applied for this included path. + /// + [JsonProperty(PropertyName = Constants.Properties.Indexes)] + public Collection Indexes + { + get + { + if (this.indexes == null) + { + this.indexes = base.GetValue>(Constants.Properties.Indexes); + + if (this.indexes == null) + { + this.indexes = new Collection(); + } + } + + return this.indexes; + } + set + { + if (value == null) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, RMResources.PropertyCannotBeNull, "Indexes")); + } + + this.indexes = value; + base.SetValue(Constants.Properties.Indexes, value); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Path); + foreach (Index index in this.Indexes) + { + index.Validate(); + } + } + + internal override void OnSave() + { + if (this.indexes != null) + { + foreach (Index index in this.indexes) + { + index.OnSave(); + } + + base.SetValue(Constants.Properties.Indexes, this.indexes); + } + } + + /// + /// Creates a copy of the included path in the Azure Cosmos DB service. + /// + /// A clone of the included path. + public object Clone() + { + IncludedPath cloned = new IncludedPath() + { + Path = this.Path + }; + + foreach (Index item in this.Indexes) + { + cloned.Indexes.Add(item); + } + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Index.cs b/Microsoft.Azure.Cosmos/src/direct/Index.cs index 3dafde0a9e..d084695208 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Index.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Index.cs @@ -1,159 +1,159 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Base class for IndexingPolicy Indexes in the Azure Cosmos DB service, you should use a concrete Index like HashIndex or RangeIndex. - /// - [JsonConverter(typeof(IndexJsonConverter))] -#if COSMOSCLIENT - internal -#else - public -#endif - abstract class Index : JsonSerializable - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - protected Index(IndexKind kind) - { - this.Kind = kind; - } - - /// - /// Gets or sets the kind of indexing to be applied in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.IndexKind)] - [JsonConverter(typeof(StringEnumConverter))] - public IndexKind Kind - { - get - { - IndexKind result = default(IndexKind); - string strValue = base.GetValue(Constants.Properties.IndexKind); - if (!string.IsNullOrEmpty(strValue)) - { - result = (IndexKind)Enum.Parse(typeof(IndexKind), strValue, true); - } - return result; - } - private set - { - base.SetValue(Constants.Properties.IndexKind, value.ToString()); - } - } - - /// - /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// An instance of type. - /// - /// - /// Here is an example to create RangeIndex instance passing in the DataType: - /// - /// - /// - /// - public static RangeIndex Range(DataType dataType) - { - return new RangeIndex(dataType); - } - - /// - /// Returns an instance of the class with specified DataType and precision for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// Specifies the precision to be used for the data type associated with this index. - /// An instance of type. - /// - /// - /// Here is an example to create RangeIndex instance passing in the DataType and precision: - /// - /// - /// - /// - public static RangeIndex Range(DataType dataType, short precision) - { - return new RangeIndex(dataType, precision); - } - - /// - /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// An instance of type. - /// - /// - /// Here is an example to create HashIndex instance passing in the DataType: - /// - /// - /// - /// - public static HashIndex Hash(DataType dataType) - { - return new HashIndex(dataType); - } - - /// - /// Returns an instance of the class with specified DataType and precision for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// Specifies the precision to be used for the data type associated with this index. - /// An instance of type. - /// - /// - /// Here is an example to create HashIndex instance passing in the DataType and precision: - /// - /// - /// - /// - public static HashIndex Hash(DataType dataType, short precision) - { - return new HashIndex(dataType, precision); - } - - /// - /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// An instance of type. - /// - /// - /// Here is an example to create SpatialIndex instance passing in the DataType: - /// - /// - /// - /// - public static SpatialIndex Spatial(DataType dataType) - { - return new SpatialIndex(dataType); - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.Kind); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Base class for IndexingPolicy Indexes in the Azure Cosmos DB service, you should use a concrete Index like HashIndex or RangeIndex. + /// + [JsonConverter(typeof(IndexJsonConverter))] +#if COSMOSCLIENT + internal +#else + public +#endif + abstract class Index : JsonSerializable + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + protected Index(IndexKind kind) + { + this.Kind = kind; + } + + /// + /// Gets or sets the kind of indexing to be applied in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.IndexKind)] + [JsonConverter(typeof(StringEnumConverter))] + public IndexKind Kind + { + get + { + IndexKind result = default(IndexKind); + string strValue = base.GetValue(Constants.Properties.IndexKind); + if (!string.IsNullOrEmpty(strValue)) + { + result = (IndexKind)Enum.Parse(typeof(IndexKind), strValue, true); + } + return result; + } + private set + { + base.SetValue(Constants.Properties.IndexKind, value.ToString()); + } + } + + /// + /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// An instance of type. + /// + /// + /// Here is an example to create RangeIndex instance passing in the DataType: + /// + /// + /// + /// + public static RangeIndex Range(DataType dataType) + { + return new RangeIndex(dataType); + } + + /// + /// Returns an instance of the class with specified DataType and precision for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// Specifies the precision to be used for the data type associated with this index. + /// An instance of type. + /// + /// + /// Here is an example to create RangeIndex instance passing in the DataType and precision: + /// + /// + /// + /// + public static RangeIndex Range(DataType dataType, short precision) + { + return new RangeIndex(dataType, precision); + } + + /// + /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// An instance of type. + /// + /// + /// Here is an example to create HashIndex instance passing in the DataType: + /// + /// + /// + /// + public static HashIndex Hash(DataType dataType) + { + return new HashIndex(dataType); + } + + /// + /// Returns an instance of the class with specified DataType and precision for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// Specifies the precision to be used for the data type associated with this index. + /// An instance of type. + /// + /// + /// Here is an example to create HashIndex instance passing in the DataType and precision: + /// + /// + /// + /// + public static HashIndex Hash(DataType dataType, short precision) + { + return new HashIndex(dataType, precision); + } + + /// + /// Returns an instance of the class with specified DataType for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// An instance of type. + /// + /// + /// Here is an example to create SpatialIndex instance passing in the DataType: + /// + /// + /// + /// + public static SpatialIndex Spatial(DataType dataType) + { + return new SpatialIndex(dataType); + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.Kind); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IndexJsonConverter.cs b/Microsoft.Azure.Cosmos/src/direct/IndexJsonConverter.cs index 3de06b7f29..68ab56e7dd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IndexJsonConverter.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IndexJsonConverter.cs @@ -1,93 +1,93 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - internal sealed class IndexJsonConverter : JsonConverter - { - public override bool CanConvert(Type objectType) - { - return typeof(Index).IsAssignableFrom(objectType); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if(objectType != typeof(Index)) - { - return null; - } - - JToken indexToken = JToken.Load(reader); - - if(indexToken.Type == JTokenType.Null) - { - return null; - } - - if(indexToken.Type != JTokenType.Object) - { - throw new JsonSerializationException( - string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexSpecFormat) - ); - } - - JToken indexKindToken = indexToken[Constants.Properties.IndexKind]; - if(indexKindToken == null || indexKindToken.Type != JTokenType.String) - { - throw new JsonSerializationException( - string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexSpecFormat) - ); - } - - IndexKind indexKind = IndexKind.Hash; - if(Enum.TryParse(indexKindToken.Value(), true /*ignoreCase*/, out indexKind)) - { - object index = null; - switch (indexKind) - { - case IndexKind.Hash: - index = new HashIndex(); - break; - case IndexKind.Range: - index = new RangeIndex(); - break; - case IndexKind.Spatial: - index = new SpatialIndex(); - break; - default: - throw new JsonSerializationException( - string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexKindValue, indexKind) - ); - } - - serializer.Populate(indexToken.CreateReader(), index); - return index; - } - else - { - throw new JsonSerializationException( - string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexKindValue, indexKindToken.Value()) - ); - } - } - - public override bool CanWrite - { - get - { - return false; - } - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + internal sealed class IndexJsonConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return typeof(Index).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if(objectType != typeof(Index)) + { + return null; + } + + JToken indexToken = JToken.Load(reader); + + if(indexToken.Type == JTokenType.Null) + { + return null; + } + + if(indexToken.Type != JTokenType.Object) + { + throw new JsonSerializationException( + string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexSpecFormat) + ); + } + + JToken indexKindToken = indexToken[Constants.Properties.IndexKind]; + if(indexKindToken == null || indexKindToken.Type != JTokenType.String) + { + throw new JsonSerializationException( + string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexSpecFormat) + ); + } + + IndexKind indexKind = IndexKind.Hash; + if(Enum.TryParse(indexKindToken.Value(), true /*ignoreCase*/, out indexKind)) + { + object index = null; + switch (indexKind) + { + case IndexKind.Hash: + index = new HashIndex(); + break; + case IndexKind.Range: + index = new RangeIndex(); + break; + case IndexKind.Spatial: + index = new SpatialIndex(); + break; + default: + throw new JsonSerializationException( + string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexKindValue, indexKind) + ); + } + + serializer.Populate(indexToken.CreateReader(), index); + return index; + } + else + { + throw new JsonSerializationException( + string.Format(CultureInfo.CurrentCulture, RMResources.InvalidIndexKindValue, indexKindToken.Value()) + ); + } + } + + public override bool CanWrite + { + get + { + return false; + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + throw new NotImplementedException(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IndexKind.cs b/Microsoft.Azure.Cosmos/src/direct/IndexKind.cs index 10a68d2cb2..3710432aa1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IndexKind.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IndexKind.cs @@ -1,43 +1,43 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// These are the indexing types available for indexing a path in the Azure Cosmos DB service. - /// - /// - /// For additional details, refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum IndexKind - { - /// - /// The index entries are hashed to serve point look up queries. - /// - /// - /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop = 5 - /// - Hash, - - /// - /// The index entries are ordered. Range indexes are optimized for inequality predicate queries with efficient range scans. - /// - /// - /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop > 5 - /// - Range, - - /// - /// The index entries are indexed to serve spatial queries. - /// - /// - /// Can be used to serve queries like: SELECT * FROM Root r WHERE ST_DISTANCE({"type":"Point","coordinates":[71.0589,42.3601]}, r.location) $LE 10000 - /// - Spatial - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// These are the indexing types available for indexing a path in the Azure Cosmos DB service. + /// + /// + /// For additional details, refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum IndexKind + { + /// + /// The index entries are hashed to serve point look up queries. + /// + /// + /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop = 5 + /// + Hash, + + /// + /// The index entries are ordered. Range indexes are optimized for inequality predicate queries with efficient range scans. + /// + /// + /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop > 5 + /// + Range, + + /// + /// The index entries are indexed to serve spatial queries. + /// + /// + /// Can be used to serve queries like: SELECT * FROM Root r WHERE ST_DISTANCE({"type":"Point","coordinates":[71.0589,42.3601]}, r.location) $LE 10000 + /// + Spatial + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IndexingDirective.cs b/Microsoft.Azure.Cosmos/src/direct/IndexingDirective.cs index af525d8197..bad5987d97 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IndexingDirective.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IndexingDirective.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Specifies whether or not the resource in the Azure Cosmos DB database is to be indexed. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum IndexingDirective - { - /// - /// Use any pre-defined/pre-configured defaults. - /// - Default, - - /// - /// Index the resource. - /// - Include, - - /// - /// Do not index the resource. - /// - Exclude - } - - internal static class IndexingDirectiveStrings - { - public static readonly string Default = IndexingDirective.Default.ToString(); - public static readonly string Include = IndexingDirective.Include.ToString(); - public static readonly string Exclude = IndexingDirective.Exclude.ToString(); - - public static string FromIndexingDirective(IndexingDirective directive) - { - switch (directive) - { - case IndexingDirective.Default: - return IndexingDirectiveStrings.Default; - case IndexingDirective.Exclude: - return IndexingDirectiveStrings.Exclude; - case IndexingDirective.Include: - return IndexingDirectiveStrings.Include; - default: - throw new ArgumentException(string.Format("Missing indexing directive string for {0}", directive)); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Specifies whether or not the resource in the Azure Cosmos DB database is to be indexed. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum IndexingDirective + { + /// + /// Use any pre-defined/pre-configured defaults. + /// + Default, + + /// + /// Index the resource. + /// + Include, + + /// + /// Do not index the resource. + /// + Exclude + } + + internal static class IndexingDirectiveStrings + { + public static readonly string Default = IndexingDirective.Default.ToString(); + public static readonly string Include = IndexingDirective.Include.ToString(); + public static readonly string Exclude = IndexingDirective.Exclude.ToString(); + + public static string FromIndexingDirective(IndexingDirective directive) + { + switch (directive) + { + case IndexingDirective.Default: + return IndexingDirectiveStrings.Default; + case IndexingDirective.Exclude: + return IndexingDirectiveStrings.Exclude; + case IndexingDirective.Include: + return IndexingDirectiveStrings.Include; + default: + throw new ArgumentException(string.Format("Missing indexing directive string for {0}", directive)); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IndexingMode.cs b/Microsoft.Azure.Cosmos/src/direct/IndexingMode.cs index b7f69dca1f..bd69bcbfd2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IndexingMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IndexingMode.cs @@ -1,46 +1,46 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported indexing modes in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum IndexingMode - { - /// - /// Index is updated synchronously with a create, update or delete operation. - /// - /// - /// With consistent indexing, query consistency is the same as the default consistency level for the database account. - /// The index is always kept up to date with the data. - /// - /// The default IndexingMode is Consistent. - /// - Consistent, - - /// - /// Index is updated asynchronously with respect to a create, update or delete operation. - /// - /// - /// With lazy indexing, queries are eventually consistent. - /// The index is updated when the collection is operating below full throughput capacity (Request units per second). - /// - /// Write operations will consume fewer request units (RequestCharge) at the time of write. - /// - Lazy, - - /// - /// No index is provided. - /// - /// - /// Setting IndexingMode to "None" drops the index. Use this if you don't want to maintain the index for a document collection, to save the storage cost or improve the write throughput. Your queries will degenerate to scans of the entire collection. - /// - None - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported indexing modes in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum IndexingMode + { + /// + /// Index is updated synchronously with a create, update or delete operation. + /// + /// + /// With consistent indexing, query consistency is the same as the default consistency level for the database account. + /// The index is always kept up to date with the data. + /// + /// The default IndexingMode is Consistent. + /// + Consistent, + + /// + /// Index is updated asynchronously with respect to a create, update or delete operation. + /// + /// + /// With lazy indexing, queries are eventually consistent. + /// The index is updated when the collection is operating below full throughput capacity (Request units per second). + /// + /// Write operations will consume fewer request units (RequestCharge) at the time of write. + /// + Lazy, + + /// + /// No index is provided. + /// + /// + /// Setting IndexingMode to "None" drops the index. Use this if you don't want to maintain the index for a document collection, to save the storage cost or improve the write throughput. Your queries will degenerate to scans of the entire collection. + /// + None + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IndexingPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/IndexingPolicy.cs index 86bdb7eda9..1208a5c443 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IndexingPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IndexingPolicy.cs @@ -1,835 +1,835 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents the indexing policy configuration for a collection in the Azure Cosmos DB service. - /// - /// - /// Indexing policies can used to configure which properties (JSON paths) are included/excluded, whether the index is updated consistently - /// or offline (lazy), automatic vs. opt-in per-document, as well as the precision and type of index per path. - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/ for additional information on how to specify - /// indexing policies. - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class IndexingPolicy : JsonSerializable, ICloneable - { - private static readonly string DefaultPath = "/*"; - - private Collection includedPaths; - - private Collection excludedPaths; - - private Collection> compositeIndexes; - - private Collection spatialIndexes; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - /// - /// Indexing mode is set to consistent. - /// - public IndexingPolicy() - { - this.Automatic = true; - this.IndexingMode = IndexingMode.Consistent; - } - - /// - /// Initializes a new instance of the class with the specified set of indexes as - /// default index specifications for the root path for the Azure Cosmos DB service. - /// - /// Comma seperated set of indexes that serve as default index specifications for the root path. - /// - /// - /// The following example shows how to override the default indexingPolicy for root path: - /// - /// - /// - /// - /// - /// If you would like to just override the indexingPolicy for Numbers you can specify just that: - /// - /// - /// - /// - public IndexingPolicy(params Index[] defaultIndexOverrides) - : this() - { - if (defaultIndexOverrides == null) - { - throw new ArgumentNullException("defaultIndexOverrides"); - } - - this.IncludedPaths = new Collection - { - new IncludedPath - { - Path = DefaultPath, - Indexes = new Collection(defaultIndexOverrides) - }, - }; - } - - /// - /// Gets or sets a value that indicates whether automatic indexing is enabled for a collection in the Azure Cosmos DB service. - /// - /// - /// In automatic indexing, documents can be explicitly excluded from indexing using . - /// In manual indexing, documents can be explicitly included. - /// - /// - /// True, if automatic indexing is enabled; otherwise, false. - /// - [JsonProperty(PropertyName = Constants.Properties.Automatic)] - public bool Automatic - { - get - { - return base.GetValue(Constants.Properties.Automatic); - } - set - { - base.SetValue(Constants.Properties.Automatic, value); - } - } - - /// - /// Gets or sets the indexing mode (consistent or lazy) in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.IndexingMode)] - [JsonConverter(typeof(StringEnumConverter))] - public IndexingMode IndexingMode - { - get - { - IndexingMode result = IndexingMode.Lazy; - string strValue = base.GetValue(Constants.Properties.IndexingMode); - if (!string.IsNullOrEmpty(strValue)) - { - result = (IndexingMode)Enum.Parse(typeof(IndexingMode), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.IndexingMode, value.ToString()); - } - } - - /// - /// Gets or sets the collection containing objects in the Azure Cosmos DB service. - /// - /// - /// The collection containing objects. - /// - [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] - public Collection IncludedPaths - { - get - { - if (this.includedPaths == null) - { - this.includedPaths = base.GetValue>(Constants.Properties.IncludedPaths); - if (this.includedPaths == null) - { - this.includedPaths = new Collection(); - } - } - - return this.includedPaths; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "IncludedPaths")); - } - - this.includedPaths = value; - base.SetValue(Constants.Properties.IncludedPaths, this.includedPaths); - } - } - - /// - /// Gets or sets the collection containing objects in the Azure Cosmos DB service. - /// - /// - /// The collection containing objects. - /// - [JsonProperty(PropertyName = Constants.Properties.ExcludedPaths)] - public Collection ExcludedPaths - { - get - { - if (this.excludedPaths == null) - { - this.excludedPaths = base.GetValue>(Constants.Properties.ExcludedPaths); - if (this.excludedPaths == null) - { - this.excludedPaths = new Collection(); - } - } - - return this.excludedPaths; - } - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ExcludedPaths")); - } - - this.excludedPaths = value; - base.SetValue(Constants.Properties.ExcludedPaths, this.excludedPaths); - } - } - - /// - /// Gets or sets the additonal composite indexes - /// - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.CompositeIndexes)] - public Collection> CompositeIndexes - { - get - { - if (this.compositeIndexes == null) - { - this.compositeIndexes = this.GetValue>>(Constants.Properties.CompositeIndexes); - if (this.compositeIndexes == null) - { - this.compositeIndexes = new Collection>(); - } - } - - return this.compositeIndexes; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(this.CompositeIndexes))); - } - - this.compositeIndexes = value; - this.SetValue(Constants.Properties.CompositeIndexes, this.compositeIndexes); - } - } - - /// - /// Gets or sets the additonal spatial indexes - /// - [JsonProperty(PropertyName = Constants.Properties.SpatialIndexes)] - public Collection SpatialIndexes - { - get - { - if (this.spatialIndexes == null) - { - this.spatialIndexes = this.GetValue>(Constants.Properties.SpatialIndexes); - if (this.spatialIndexes == null) - { - this.spatialIndexes = new Collection(); - } - } - - return this.spatialIndexes; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(this.spatialIndexes))); - } - - this.spatialIndexes = value; - this.SetValue(Constants.Properties.SpatialIndexes, this.spatialIndexes); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Automatic); - - Helpers.ValidateEnumProperties(this.IndexingMode); - - foreach (IncludedPath includedPath in this.IncludedPaths) - { - includedPath.Validate(); - } - - foreach (ExcludedPath excludedPath in this.ExcludedPaths) - { - excludedPath.Validate(); - } - - foreach (Collection collectionCompositePaths in this.CompositeIndexes) - { - foreach (CompositePath compositePath in collectionCompositePaths) - { - compositePath.Validate(); - } - } - - foreach (SpatialSpec spatialSpec in this.SpatialIndexes) - { - spatialSpec.Validate(); - } - } - - internal override void OnSave() - { - // If indexing mode is not 'none' and not paths are set, set them to the defaults - if (this.IndexingMode != IndexingMode.None && this.IncludedPaths.Count == 0 && this.ExcludedPaths.Count == 0) - { - this.IncludedPaths.Add(new IncludedPath() { Path = DefaultPath }); - } - - foreach (IncludedPath includedPath in this.IncludedPaths) - { - includedPath.OnSave(); - } - - base.SetValue(Constants.Properties.IncludedPaths, this.IncludedPaths); - - foreach (ExcludedPath excludedPath in this.ExcludedPaths) - { - excludedPath.OnSave(); - } - - base.SetValue(Constants.Properties.ExcludedPaths, this.ExcludedPaths); - - foreach (Collection compositePaths in this.CompositeIndexes) - { - foreach (CompositePath compositePath in compositePaths) - { - compositePath.OnSave(); - } - } - - this.SetValue(Constants.Properties.CompositeIndexes, this.CompositeIndexes); - - foreach (SpatialSpec spatialSpec in this.SpatialIndexes) - { - spatialSpec.OnSave(); - } - - this.SetValue(Constants.Properties.SpatialIndexes, this.spatialIndexes); - } - - /// - /// Performs a deep copy of the indexing policy for the Azure Cosmos DB service. - /// - /// - /// A clone of the indexing policy. - /// - public object Clone() - { - IndexingPolicy cloned = new IndexingPolicy() - { - Automatic = this.Automatic, - IndexingMode = this.IndexingMode - }; - - foreach (IncludedPath item in this.IncludedPaths) - { - cloned.IncludedPaths.Add((IncludedPath)item.Clone()); - } - - foreach (ExcludedPath item in this.ExcludedPaths) - { - cloned.ExcludedPaths.Add((ExcludedPath)item.Clone()); - } - - foreach (Collection compositeIndex in this.CompositeIndexes) - { - Collection clonedCompositeIndex = new Collection(); - foreach (CompositePath compositePath in compositeIndex) - { - CompositePath clonedCompositePath = (CompositePath)compositePath.Clone(); - clonedCompositeIndex.Add(clonedCompositePath); - } - - cloned.CompositeIndexes.Add(clonedCompositeIndex); - } - - Collection clonedSpatialIndexes = new Collection(); - foreach (SpatialSpec spatialSpec in this.SpatialIndexes) - { - SpatialSpec clonedSpatialSpec = (SpatialSpec)spatialSpec.Clone(); - clonedSpatialIndexes.Add(clonedSpatialSpec); - } - - cloned.SpatialIndexes = clonedSpatialIndexes; - - return cloned; - } - - # region EqualityComparers - internal sealed class CompositePathEqualityComparer : IEqualityComparer - { - public static readonly CompositePathEqualityComparer Singleton = new CompositePathEqualityComparer(); - - public bool Equals(CompositePath compositePath1, CompositePath compositePath2) - { - if (Object.ReferenceEquals(compositePath1, compositePath2)) - { - return true; - } - - if (compositePath1 == null || compositePath2 == null) - { - return false; - } - - if (compositePath1.Path == compositePath2.Path && compositePath2.Order == compositePath2.Order) - { - return true; - } - - return false; - } - - public int GetHashCode(CompositePath compositePath) - { - if (compositePath == null) - { - return 0; - } - - return compositePath.Path.GetHashCode() ^ compositePath.Order.GetHashCode(); - } - } - - internal sealed class CompositePathsEqualityComparer : IEqualityComparer> - { - public static readonly CompositePathsEqualityComparer Singleton = new CompositePathsEqualityComparer(); - private static readonly CompositePathEqualityComparer compositePathEqualityComparer = new CompositePathEqualityComparer(); - public bool Equals(HashSet compositePaths1, HashSet compositePaths2) - { - if (Object.ReferenceEquals(compositePaths1, compositePaths2)) - { - return true; - } - - if (compositePaths1 == null || compositePaths2 == null) - { - return false; - } - - return compositePaths1.SetEquals(compositePaths2); - } - - public int GetHashCode(HashSet obj) - { - if (obj == null) - { - return 0; - } - - int hashCode = 0; - foreach (CompositePath compositePath in obj) - { - hashCode ^= compositePathEqualityComparer.GetHashCode(compositePath); - } - - return hashCode; - } - } - - private sealed class CompositeIndexesEqualityComparer : IEqualityComparer>> - { - private static readonly CompositePathEqualityComparer compositePathEqualityComparer = new CompositePathEqualityComparer(); - private static readonly CompositePathsEqualityComparer compositePathsEqualityComparer = new CompositePathsEqualityComparer(); - - public bool Equals(Collection> compositeIndexes1, Collection> compositeIndexes2) - { - if (Object.ReferenceEquals(compositeIndexes1, compositeIndexes2)) - { - return true; - } - - if (compositeIndexes1 == null || compositeIndexes2 == null) - { - return false; - } - - HashSet> hashedCompositeIndexes1 = new HashSet>(compositePathsEqualityComparer); - HashSet> hashedCompositeIndexes2 = new HashSet>(compositePathsEqualityComparer); - - foreach (Collection compositePaths in compositeIndexes1) - { - HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); - hashedCompositeIndexes1.Add(hashedCompositePaths); - } - - foreach (Collection compositePaths in compositeIndexes2) - { - HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); - hashedCompositeIndexes2.Add(hashedCompositePaths); - } - - return hashedCompositeIndexes1.SetEquals(hashedCompositeIndexes2); - } - - public int GetHashCode(Collection> compositeIndexes) - { - int hashCode = 0; - foreach (Collection compositePaths in compositeIndexes) - { - HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); - hashCode = hashCode ^ compositePathsEqualityComparer.GetHashCode(hashedCompositePaths); - } - - return hashCode; - } - } - - internal sealed class SpatialSpecEqualityComparer : IEqualityComparer - { - public static readonly SpatialSpecEqualityComparer Singleton = new SpatialSpecEqualityComparer(); - - public bool Equals(SpatialSpec spatialSpec1, SpatialSpec spatialSpec2) - { - if (object.ReferenceEquals(spatialSpec1, spatialSpec2)) - { - return true; - } - - if (spatialSpec1 == null || spatialSpec2 == null) - { - return false; - } - - if (spatialSpec1.Path != spatialSpec2.Path) - { - return false; - } - - HashSet hashedSpatialTypes1 = new HashSet(spatialSpec1.SpatialTypes); - HashSet hashedSpatialTypes2 = new HashSet(spatialSpec2.SpatialTypes); - - if (!hashedSpatialTypes1.SetEquals(hashedSpatialTypes2)) - { - return false; - } - - return true; - } - - public int GetHashCode(SpatialSpec spatialSpec) - { - int hashCode = 0; - hashCode ^= spatialSpec.Path.GetHashCode(); - foreach (SpatialType spatialType in spatialSpec.SpatialTypes) - { - hashCode ^= spatialType.GetHashCode(); - } - - return hashCode; - } - } - - internal sealed class AdditionalSpatialIndexesEqualityComparer : IEqualityComparer> - { - private static readonly SpatialSpecEqualityComparer spatialSpecEqualityComparer = new SpatialSpecEqualityComparer(); - - public bool Equals(Collection additionalSpatialIndexes1, Collection additionalSpatialIndexes2) - { - if (object.ReferenceEquals(additionalSpatialIndexes1, additionalSpatialIndexes2)) - { - return true; - } - - if (additionalSpatialIndexes1 == null || additionalSpatialIndexes2 == null) - { - return false; - } - - HashSet hashedAdditionalSpatialIndexes1 = new HashSet(additionalSpatialIndexes1, spatialSpecEqualityComparer); - HashSet hashedAdditionalSpatialIndexes2 = new HashSet(additionalSpatialIndexes2, spatialSpecEqualityComparer); - - return hashedAdditionalSpatialIndexes1.SetEquals(additionalSpatialIndexes2); - } - - public int GetHashCode(Collection additionalSpatialIndexes) - { - int hashCode = 0; - foreach (SpatialSpec spatialSpec in additionalSpatialIndexes) - { - hashCode = hashCode ^ spatialSpecEqualityComparer.GetHashCode(spatialSpec); - } - - return hashCode; - } - } - - internal sealed class IndexEqualityComparer : IEqualityComparer - { - public static readonly IndexEqualityComparer Comparer = new IndexEqualityComparer(); - - public bool Equals(Index index1, Index index2) - { - if (object.ReferenceEquals(index1, index2)) - { - return true; - } - - if (index1 == null || index2 == null) - { - return false; - } - - if (index1.Kind != index2.Kind) - { - return false; - } - - switch (index1.Kind) - { - case IndexKind.Hash: - if (((HashIndex)index1).Precision != ((HashIndex)index2).Precision) - { - return false; - } - - if (((HashIndex)index1).DataType != ((HashIndex)index2).DataType) - { - return false; - } - break; - - case IndexKind.Range: - if (((RangeIndex)index1).Precision != ((RangeIndex)index2).Precision) - { - return false; - } - - if (((RangeIndex)index1).DataType != ((RangeIndex)index2).DataType) - { - return false; - } - break; - - case IndexKind.Spatial: - if (((SpatialIndex)index1).DataType != ((SpatialIndex)index2).DataType) - { - return false; - } - break; - - default: - throw new ArgumentException($"Unexpected Kind: {index1.Kind}"); - } - - return true; - } - - public int GetHashCode(Index index) - { - int hashCode = 0; - hashCode = hashCode ^ (int)index.Kind; - - switch (index.Kind) - { - case IndexKind.Hash: - hashCode = hashCode ^ ((HashIndex)index).Precision ?? 0; - hashCode = hashCode ^ ((HashIndex)index).DataType.GetHashCode(); - break; - - case IndexKind.Range: - hashCode = hashCode ^ ((RangeIndex)index).Precision ?? 0; - hashCode = hashCode ^ ((RangeIndex)index).DataType.GetHashCode(); - break; - - case IndexKind.Spatial: - hashCode = hashCode ^ ((SpatialIndex)index).DataType.GetHashCode(); - break; - - default: - throw new ArgumentException($"Unexpected Kind: {index.Kind}"); - } - - return hashCode; - } - } - - internal sealed class IncludedPathEqualityComparer : IEqualityComparer - { - public static readonly IncludedPathEqualityComparer Singleton = new IncludedPathEqualityComparer(); - private static readonly IndexEqualityComparer indexEqualityComparer = new IndexEqualityComparer(); - public bool Equals(IncludedPath includedPath1, IncludedPath includedPath2) - { - if (Object.ReferenceEquals(includedPath1, includedPath2)) - { - return true; - } - - if (includedPath1 == null || includedPath2 == null) - { - return false; - } - - if (includedPath1.Path != includedPath2.Path) - { - return false; - } - - HashSet indexes1 = new HashSet(includedPath1.Indexes, indexEqualityComparer); - HashSet indexes2 = new HashSet(includedPath2.Indexes, indexEqualityComparer); - - return indexes1.SetEquals(indexes2); - } - - public int GetHashCode(IncludedPath includedPath) - { - int hashCode = 0; - hashCode = hashCode ^ includedPath.Path.GetHashCode(); - foreach (Index index in includedPath.Indexes) - { - hashCode = hashCode ^ indexEqualityComparer.GetHashCode(index); - } - - return hashCode; - } - } - - internal sealed class ExcludedPathEqualityComparer : IEqualityComparer - { - public static readonly ExcludedPathEqualityComparer Singleton = new ExcludedPathEqualityComparer(); - - public bool Equals(ExcludedPath excludedPath1, ExcludedPath excludedPath2) - { - if (Object.ReferenceEquals(excludedPath1, excludedPath2)) - { - return true; - } - - if (excludedPath1 == null || excludedPath2 == null) - { - return false; - } - - return (excludedPath1.Path == excludedPath2.Path); - } - - public int GetHashCode(ExcludedPath excludedPath1) - { - return excludedPath1.Path.GetHashCode(); - } - } - - internal sealed class IndexingPolicyEqualityComparer : IEqualityComparer - { - public static readonly IndexingPolicyEqualityComparer Singleton = new IndexingPolicyEqualityComparer(); - private static readonly IncludedPathEqualityComparer includedPathEqualityComparer = new IncludedPathEqualityComparer(); - private static readonly ExcludedPathEqualityComparer excludedPathEqualityComparer = new ExcludedPathEqualityComparer(); - private static readonly CompositeIndexesEqualityComparer compositeIndexesEqualityComparer = new CompositeIndexesEqualityComparer(); - private static readonly AdditionalSpatialIndexesEqualityComparer additionalSpatialIndexesEqualityComparer = new AdditionalSpatialIndexesEqualityComparer(); - - public bool Equals(IndexingPolicy indexingPolicy1, IndexingPolicy indexingPolicy2) - { - if (Object.ReferenceEquals(indexingPolicy1, indexingPolicy2)) - { - return true; - } - - bool isEqual = true; - isEqual &= (indexingPolicy1 != null && indexingPolicy2 != null); - isEqual &= (indexingPolicy1.Automatic == indexingPolicy2.Automatic); - isEqual &= (indexingPolicy1.IndexingMode == indexingPolicy2.IndexingMode); - isEqual &= compositeIndexesEqualityComparer.Equals(indexingPolicy1.CompositeIndexes, indexingPolicy2.CompositeIndexes); - isEqual &= additionalSpatialIndexesEqualityComparer.Equals(indexingPolicy1.SpatialIndexes, indexingPolicy2.SpatialIndexes); - - HashSet includedPaths1 = new HashSet(indexingPolicy1.IncludedPaths, includedPathEqualityComparer); - HashSet includedPaths2 = new HashSet(indexingPolicy2.IncludedPaths, includedPathEqualityComparer); - isEqual &= includedPaths1.SetEquals(includedPaths2); - - HashSet excludedPaths1 = new HashSet(indexingPolicy1.ExcludedPaths, excludedPathEqualityComparer); - HashSet excludedPaths2 = new HashSet(indexingPolicy2.ExcludedPaths, excludedPathEqualityComparer); - isEqual &= excludedPaths1.SetEquals(excludedPaths2); - - return isEqual; - } - - public int GetHashCode(IndexingPolicy indexingPolicy) - { - int hashCode = 0; - hashCode = hashCode ^ indexingPolicy.Automatic.GetHashCode(); - hashCode = hashCode ^ indexingPolicy.IndexingMode.GetHashCode(); - hashCode = hashCode ^ compositeIndexesEqualityComparer.GetHashCode(indexingPolicy.CompositeIndexes); - hashCode = hashCode ^ additionalSpatialIndexesEqualityComparer.GetHashCode(indexingPolicy.SpatialIndexes); - - foreach (IncludedPath includedPath in indexingPolicy.IncludedPaths) - { - hashCode = hashCode ^ includedPathEqualityComparer.GetHashCode(includedPath); - } - - foreach (ExcludedPath excludedPath in indexingPolicy.ExcludedPaths) - { - hashCode = hashCode ^ excludedPathEqualityComparer.GetHashCode(excludedPath); - } - - return hashCode; - } - } - #endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents the indexing policy configuration for a collection in the Azure Cosmos DB service. + /// + /// + /// Indexing policies can used to configure which properties (JSON paths) are included/excluded, whether the index is updated consistently + /// or offline (lazy), automatic vs. opt-in per-document, as well as the precision and type of index per path. + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/ for additional information on how to specify + /// indexing policies. + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class IndexingPolicy : JsonSerializable, ICloneable + { + private static readonly string DefaultPath = "/*"; + + private Collection includedPaths; + + private Collection excludedPaths; + + private Collection> compositeIndexes; + + private Collection spatialIndexes; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// + /// Indexing mode is set to consistent. + /// + public IndexingPolicy() + { + this.Automatic = true; + this.IndexingMode = IndexingMode.Consistent; + } + + /// + /// Initializes a new instance of the class with the specified set of indexes as + /// default index specifications for the root path for the Azure Cosmos DB service. + /// + /// Comma seperated set of indexes that serve as default index specifications for the root path. + /// + /// + /// The following example shows how to override the default indexingPolicy for root path: + /// + /// + /// + /// + /// + /// If you would like to just override the indexingPolicy for Numbers you can specify just that: + /// + /// + /// + /// + public IndexingPolicy(params Index[] defaultIndexOverrides) + : this() + { + if (defaultIndexOverrides == null) + { + throw new ArgumentNullException("defaultIndexOverrides"); + } + + this.IncludedPaths = new Collection + { + new IncludedPath + { + Path = DefaultPath, + Indexes = new Collection(defaultIndexOverrides) + }, + }; + } + + /// + /// Gets or sets a value that indicates whether automatic indexing is enabled for a collection in the Azure Cosmos DB service. + /// + /// + /// In automatic indexing, documents can be explicitly excluded from indexing using . + /// In manual indexing, documents can be explicitly included. + /// + /// + /// True, if automatic indexing is enabled; otherwise, false. + /// + [JsonProperty(PropertyName = Constants.Properties.Automatic)] + public bool Automatic + { + get + { + return base.GetValue(Constants.Properties.Automatic); + } + set + { + base.SetValue(Constants.Properties.Automatic, value); + } + } + + /// + /// Gets or sets the indexing mode (consistent or lazy) in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.IndexingMode)] + [JsonConverter(typeof(StringEnumConverter))] + public IndexingMode IndexingMode + { + get + { + IndexingMode result = IndexingMode.Lazy; + string strValue = base.GetValue(Constants.Properties.IndexingMode); + if (!string.IsNullOrEmpty(strValue)) + { + result = (IndexingMode)Enum.Parse(typeof(IndexingMode), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.IndexingMode, value.ToString()); + } + } + + /// + /// Gets or sets the collection containing objects in the Azure Cosmos DB service. + /// + /// + /// The collection containing objects. + /// + [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] + public Collection IncludedPaths + { + get + { + if (this.includedPaths == null) + { + this.includedPaths = base.GetValue>(Constants.Properties.IncludedPaths); + if (this.includedPaths == null) + { + this.includedPaths = new Collection(); + } + } + + return this.includedPaths; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "IncludedPaths")); + } + + this.includedPaths = value; + base.SetValue(Constants.Properties.IncludedPaths, this.includedPaths); + } + } + + /// + /// Gets or sets the collection containing objects in the Azure Cosmos DB service. + /// + /// + /// The collection containing objects. + /// + [JsonProperty(PropertyName = Constants.Properties.ExcludedPaths)] + public Collection ExcludedPaths + { + get + { + if (this.excludedPaths == null) + { + this.excludedPaths = base.GetValue>(Constants.Properties.ExcludedPaths); + if (this.excludedPaths == null) + { + this.excludedPaths = new Collection(); + } + } + + return this.excludedPaths; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "ExcludedPaths")); + } + + this.excludedPaths = value; + base.SetValue(Constants.Properties.ExcludedPaths, this.excludedPaths); + } + } + + /// + /// Gets or sets the additonal composite indexes + /// + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.CompositeIndexes)] + public Collection> CompositeIndexes + { + get + { + if (this.compositeIndexes == null) + { + this.compositeIndexes = this.GetValue>>(Constants.Properties.CompositeIndexes); + if (this.compositeIndexes == null) + { + this.compositeIndexes = new Collection>(); + } + } + + return this.compositeIndexes; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(this.CompositeIndexes))); + } + + this.compositeIndexes = value; + this.SetValue(Constants.Properties.CompositeIndexes, this.compositeIndexes); + } + } + + /// + /// Gets or sets the additonal spatial indexes + /// + [JsonProperty(PropertyName = Constants.Properties.SpatialIndexes)] + public Collection SpatialIndexes + { + get + { + if (this.spatialIndexes == null) + { + this.spatialIndexes = this.GetValue>(Constants.Properties.SpatialIndexes); + if (this.spatialIndexes == null) + { + this.spatialIndexes = new Collection(); + } + } + + return this.spatialIndexes; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(this.spatialIndexes))); + } + + this.spatialIndexes = value; + this.SetValue(Constants.Properties.SpatialIndexes, this.spatialIndexes); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Automatic); + + Helpers.ValidateEnumProperties(this.IndexingMode); + + foreach (IncludedPath includedPath in this.IncludedPaths) + { + includedPath.Validate(); + } + + foreach (ExcludedPath excludedPath in this.ExcludedPaths) + { + excludedPath.Validate(); + } + + foreach (Collection collectionCompositePaths in this.CompositeIndexes) + { + foreach (CompositePath compositePath in collectionCompositePaths) + { + compositePath.Validate(); + } + } + + foreach (SpatialSpec spatialSpec in this.SpatialIndexes) + { + spatialSpec.Validate(); + } + } + + internal override void OnSave() + { + // If indexing mode is not 'none' and not paths are set, set them to the defaults + if (this.IndexingMode != IndexingMode.None && this.IncludedPaths.Count == 0 && this.ExcludedPaths.Count == 0) + { + this.IncludedPaths.Add(new IncludedPath() { Path = DefaultPath }); + } + + foreach (IncludedPath includedPath in this.IncludedPaths) + { + includedPath.OnSave(); + } + + base.SetValue(Constants.Properties.IncludedPaths, this.IncludedPaths); + + foreach (ExcludedPath excludedPath in this.ExcludedPaths) + { + excludedPath.OnSave(); + } + + base.SetValue(Constants.Properties.ExcludedPaths, this.ExcludedPaths); + + foreach (Collection compositePaths in this.CompositeIndexes) + { + foreach (CompositePath compositePath in compositePaths) + { + compositePath.OnSave(); + } + } + + this.SetValue(Constants.Properties.CompositeIndexes, this.CompositeIndexes); + + foreach (SpatialSpec spatialSpec in this.SpatialIndexes) + { + spatialSpec.OnSave(); + } + + this.SetValue(Constants.Properties.SpatialIndexes, this.spatialIndexes); + } + + /// + /// Performs a deep copy of the indexing policy for the Azure Cosmos DB service. + /// + /// + /// A clone of the indexing policy. + /// + public object Clone() + { + IndexingPolicy cloned = new IndexingPolicy() + { + Automatic = this.Automatic, + IndexingMode = this.IndexingMode + }; + + foreach (IncludedPath item in this.IncludedPaths) + { + cloned.IncludedPaths.Add((IncludedPath)item.Clone()); + } + + foreach (ExcludedPath item in this.ExcludedPaths) + { + cloned.ExcludedPaths.Add((ExcludedPath)item.Clone()); + } + + foreach (Collection compositeIndex in this.CompositeIndexes) + { + Collection clonedCompositeIndex = new Collection(); + foreach (CompositePath compositePath in compositeIndex) + { + CompositePath clonedCompositePath = (CompositePath)compositePath.Clone(); + clonedCompositeIndex.Add(clonedCompositePath); + } + + cloned.CompositeIndexes.Add(clonedCompositeIndex); + } + + Collection clonedSpatialIndexes = new Collection(); + foreach (SpatialSpec spatialSpec in this.SpatialIndexes) + { + SpatialSpec clonedSpatialSpec = (SpatialSpec)spatialSpec.Clone(); + clonedSpatialIndexes.Add(clonedSpatialSpec); + } + + cloned.SpatialIndexes = clonedSpatialIndexes; + + return cloned; + } + + # region EqualityComparers + internal sealed class CompositePathEqualityComparer : IEqualityComparer + { + public static readonly CompositePathEqualityComparer Singleton = new CompositePathEqualityComparer(); + + public bool Equals(CompositePath compositePath1, CompositePath compositePath2) + { + if (Object.ReferenceEquals(compositePath1, compositePath2)) + { + return true; + } + + if (compositePath1 == null || compositePath2 == null) + { + return false; + } + + if (compositePath1.Path == compositePath2.Path && compositePath2.Order == compositePath2.Order) + { + return true; + } + + return false; + } + + public int GetHashCode(CompositePath compositePath) + { + if (compositePath == null) + { + return 0; + } + + return compositePath.Path.GetHashCode() ^ compositePath.Order.GetHashCode(); + } + } + + internal sealed class CompositePathsEqualityComparer : IEqualityComparer> + { + public static readonly CompositePathsEqualityComparer Singleton = new CompositePathsEqualityComparer(); + private static readonly CompositePathEqualityComparer compositePathEqualityComparer = new CompositePathEqualityComparer(); + public bool Equals(HashSet compositePaths1, HashSet compositePaths2) + { + if (Object.ReferenceEquals(compositePaths1, compositePaths2)) + { + return true; + } + + if (compositePaths1 == null || compositePaths2 == null) + { + return false; + } + + return compositePaths1.SetEquals(compositePaths2); + } + + public int GetHashCode(HashSet obj) + { + if (obj == null) + { + return 0; + } + + int hashCode = 0; + foreach (CompositePath compositePath in obj) + { + hashCode ^= compositePathEqualityComparer.GetHashCode(compositePath); + } + + return hashCode; + } + } + + private sealed class CompositeIndexesEqualityComparer : IEqualityComparer>> + { + private static readonly CompositePathEqualityComparer compositePathEqualityComparer = new CompositePathEqualityComparer(); + private static readonly CompositePathsEqualityComparer compositePathsEqualityComparer = new CompositePathsEqualityComparer(); + + public bool Equals(Collection> compositeIndexes1, Collection> compositeIndexes2) + { + if (Object.ReferenceEquals(compositeIndexes1, compositeIndexes2)) + { + return true; + } + + if (compositeIndexes1 == null || compositeIndexes2 == null) + { + return false; + } + + HashSet> hashedCompositeIndexes1 = new HashSet>(compositePathsEqualityComparer); + HashSet> hashedCompositeIndexes2 = new HashSet>(compositePathsEqualityComparer); + + foreach (Collection compositePaths in compositeIndexes1) + { + HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); + hashedCompositeIndexes1.Add(hashedCompositePaths); + } + + foreach (Collection compositePaths in compositeIndexes2) + { + HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); + hashedCompositeIndexes2.Add(hashedCompositePaths); + } + + return hashedCompositeIndexes1.SetEquals(hashedCompositeIndexes2); + } + + public int GetHashCode(Collection> compositeIndexes) + { + int hashCode = 0; + foreach (Collection compositePaths in compositeIndexes) + { + HashSet hashedCompositePaths = new HashSet(compositePaths, compositePathEqualityComparer); + hashCode = hashCode ^ compositePathsEqualityComparer.GetHashCode(hashedCompositePaths); + } + + return hashCode; + } + } + + internal sealed class SpatialSpecEqualityComparer : IEqualityComparer + { + public static readonly SpatialSpecEqualityComparer Singleton = new SpatialSpecEqualityComparer(); + + public bool Equals(SpatialSpec spatialSpec1, SpatialSpec spatialSpec2) + { + if (object.ReferenceEquals(spatialSpec1, spatialSpec2)) + { + return true; + } + + if (spatialSpec1 == null || spatialSpec2 == null) + { + return false; + } + + if (spatialSpec1.Path != spatialSpec2.Path) + { + return false; + } + + HashSet hashedSpatialTypes1 = new HashSet(spatialSpec1.SpatialTypes); + HashSet hashedSpatialTypes2 = new HashSet(spatialSpec2.SpatialTypes); + + if (!hashedSpatialTypes1.SetEquals(hashedSpatialTypes2)) + { + return false; + } + + return true; + } + + public int GetHashCode(SpatialSpec spatialSpec) + { + int hashCode = 0; + hashCode ^= spatialSpec.Path.GetHashCode(); + foreach (SpatialType spatialType in spatialSpec.SpatialTypes) + { + hashCode ^= spatialType.GetHashCode(); + } + + return hashCode; + } + } + + internal sealed class AdditionalSpatialIndexesEqualityComparer : IEqualityComparer> + { + private static readonly SpatialSpecEqualityComparer spatialSpecEqualityComparer = new SpatialSpecEqualityComparer(); + + public bool Equals(Collection additionalSpatialIndexes1, Collection additionalSpatialIndexes2) + { + if (object.ReferenceEquals(additionalSpatialIndexes1, additionalSpatialIndexes2)) + { + return true; + } + + if (additionalSpatialIndexes1 == null || additionalSpatialIndexes2 == null) + { + return false; + } + + HashSet hashedAdditionalSpatialIndexes1 = new HashSet(additionalSpatialIndexes1, spatialSpecEqualityComparer); + HashSet hashedAdditionalSpatialIndexes2 = new HashSet(additionalSpatialIndexes2, spatialSpecEqualityComparer); + + return hashedAdditionalSpatialIndexes1.SetEquals(additionalSpatialIndexes2); + } + + public int GetHashCode(Collection additionalSpatialIndexes) + { + int hashCode = 0; + foreach (SpatialSpec spatialSpec in additionalSpatialIndexes) + { + hashCode = hashCode ^ spatialSpecEqualityComparer.GetHashCode(spatialSpec); + } + + return hashCode; + } + } + + internal sealed class IndexEqualityComparer : IEqualityComparer + { + public static readonly IndexEqualityComparer Comparer = new IndexEqualityComparer(); + + public bool Equals(Index index1, Index index2) + { + if (object.ReferenceEquals(index1, index2)) + { + return true; + } + + if (index1 == null || index2 == null) + { + return false; + } + + if (index1.Kind != index2.Kind) + { + return false; + } + + switch (index1.Kind) + { + case IndexKind.Hash: + if (((HashIndex)index1).Precision != ((HashIndex)index2).Precision) + { + return false; + } + + if (((HashIndex)index1).DataType != ((HashIndex)index2).DataType) + { + return false; + } + break; + + case IndexKind.Range: + if (((RangeIndex)index1).Precision != ((RangeIndex)index2).Precision) + { + return false; + } + + if (((RangeIndex)index1).DataType != ((RangeIndex)index2).DataType) + { + return false; + } + break; + + case IndexKind.Spatial: + if (((SpatialIndex)index1).DataType != ((SpatialIndex)index2).DataType) + { + return false; + } + break; + + default: + throw new ArgumentException($"Unexpected Kind: {index1.Kind}"); + } + + return true; + } + + public int GetHashCode(Index index) + { + int hashCode = 0; + hashCode = hashCode ^ (int)index.Kind; + + switch (index.Kind) + { + case IndexKind.Hash: + hashCode = hashCode ^ ((HashIndex)index).Precision ?? 0; + hashCode = hashCode ^ ((HashIndex)index).DataType.GetHashCode(); + break; + + case IndexKind.Range: + hashCode = hashCode ^ ((RangeIndex)index).Precision ?? 0; + hashCode = hashCode ^ ((RangeIndex)index).DataType.GetHashCode(); + break; + + case IndexKind.Spatial: + hashCode = hashCode ^ ((SpatialIndex)index).DataType.GetHashCode(); + break; + + default: + throw new ArgumentException($"Unexpected Kind: {index.Kind}"); + } + + return hashCode; + } + } + + internal sealed class IncludedPathEqualityComparer : IEqualityComparer + { + public static readonly IncludedPathEqualityComparer Singleton = new IncludedPathEqualityComparer(); + private static readonly IndexEqualityComparer indexEqualityComparer = new IndexEqualityComparer(); + public bool Equals(IncludedPath includedPath1, IncludedPath includedPath2) + { + if (Object.ReferenceEquals(includedPath1, includedPath2)) + { + return true; + } + + if (includedPath1 == null || includedPath2 == null) + { + return false; + } + + if (includedPath1.Path != includedPath2.Path) + { + return false; + } + + HashSet indexes1 = new HashSet(includedPath1.Indexes, indexEqualityComparer); + HashSet indexes2 = new HashSet(includedPath2.Indexes, indexEqualityComparer); + + return indexes1.SetEquals(indexes2); + } + + public int GetHashCode(IncludedPath includedPath) + { + int hashCode = 0; + hashCode = hashCode ^ includedPath.Path.GetHashCode(); + foreach (Index index in includedPath.Indexes) + { + hashCode = hashCode ^ indexEqualityComparer.GetHashCode(index); + } + + return hashCode; + } + } + + internal sealed class ExcludedPathEqualityComparer : IEqualityComparer + { + public static readonly ExcludedPathEqualityComparer Singleton = new ExcludedPathEqualityComparer(); + + public bool Equals(ExcludedPath excludedPath1, ExcludedPath excludedPath2) + { + if (Object.ReferenceEquals(excludedPath1, excludedPath2)) + { + return true; + } + + if (excludedPath1 == null || excludedPath2 == null) + { + return false; + } + + return (excludedPath1.Path == excludedPath2.Path); + } + + public int GetHashCode(ExcludedPath excludedPath1) + { + return excludedPath1.Path.GetHashCode(); + } + } + + internal sealed class IndexingPolicyEqualityComparer : IEqualityComparer + { + public static readonly IndexingPolicyEqualityComparer Singleton = new IndexingPolicyEqualityComparer(); + private static readonly IncludedPathEqualityComparer includedPathEqualityComparer = new IncludedPathEqualityComparer(); + private static readonly ExcludedPathEqualityComparer excludedPathEqualityComparer = new ExcludedPathEqualityComparer(); + private static readonly CompositeIndexesEqualityComparer compositeIndexesEqualityComparer = new CompositeIndexesEqualityComparer(); + private static readonly AdditionalSpatialIndexesEqualityComparer additionalSpatialIndexesEqualityComparer = new AdditionalSpatialIndexesEqualityComparer(); + + public bool Equals(IndexingPolicy indexingPolicy1, IndexingPolicy indexingPolicy2) + { + if (Object.ReferenceEquals(indexingPolicy1, indexingPolicy2)) + { + return true; + } + + bool isEqual = true; + isEqual &= (indexingPolicy1 != null && indexingPolicy2 != null); + isEqual &= (indexingPolicy1.Automatic == indexingPolicy2.Automatic); + isEqual &= (indexingPolicy1.IndexingMode == indexingPolicy2.IndexingMode); + isEqual &= compositeIndexesEqualityComparer.Equals(indexingPolicy1.CompositeIndexes, indexingPolicy2.CompositeIndexes); + isEqual &= additionalSpatialIndexesEqualityComparer.Equals(indexingPolicy1.SpatialIndexes, indexingPolicy2.SpatialIndexes); + + HashSet includedPaths1 = new HashSet(indexingPolicy1.IncludedPaths, includedPathEqualityComparer); + HashSet includedPaths2 = new HashSet(indexingPolicy2.IncludedPaths, includedPathEqualityComparer); + isEqual &= includedPaths1.SetEquals(includedPaths2); + + HashSet excludedPaths1 = new HashSet(indexingPolicy1.ExcludedPaths, excludedPathEqualityComparer); + HashSet excludedPaths2 = new HashSet(indexingPolicy2.ExcludedPaths, excludedPathEqualityComparer); + isEqual &= excludedPaths1.SetEquals(excludedPaths2); + + return isEqual; + } + + public int GetHashCode(IndexingPolicy indexingPolicy) + { + int hashCode = 0; + hashCode = hashCode ^ indexingPolicy.Automatic.GetHashCode(); + hashCode = hashCode ^ indexingPolicy.IndexingMode.GetHashCode(); + hashCode = hashCode ^ compositeIndexesEqualityComparer.GetHashCode(indexingPolicy.CompositeIndexes); + hashCode = hashCode ^ additionalSpatialIndexesEqualityComparer.GetHashCode(indexingPolicy.SpatialIndexes); + + foreach (IncludedPath includedPath in indexingPolicy.IncludedPaths) + { + hashCode = hashCode ^ includedPathEqualityComparer.GetHashCode(includedPath); + } + + foreach (ExcludedPath excludedPath in indexingPolicy.ExcludedPaths) + { + hashCode = hashCode ^ excludedPathEqualityComparer.GetHashCode(excludedPath); + } + + return hashCode; + } + } + #endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/InfinityPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/InfinityPartitionKeyComponent.cs index 4c9fa357a5..5f897e8390 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InfinityPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InfinityPartitionKeyComponent.cs @@ -1,64 +1,64 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class InfinityPartitionKeyComponent : IPartitionKeyComponent - { - public int CompareTo(IPartitionKeyComponent other) - { - InfinityPartitionKeyComponent otherInfinity = other as InfinityPartitionKeyComponent; - if (otherInfinity == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.Infinity; - } - - public IPartitionKeyComponent Truncate() - { - throw new InvalidOperationException(); - } - - public void WriteForHashing(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public override int GetHashCode() - { - return 0; - } - - public void JsonEncode(JsonWriter writer) - { - throw new NotImplementedException(); - } - - public object ToObject() - { - throw new NotImplementedException(); - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.Infinity); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class InfinityPartitionKeyComponent : IPartitionKeyComponent + { + public int CompareTo(IPartitionKeyComponent other) + { + InfinityPartitionKeyComponent otherInfinity = other as InfinityPartitionKeyComponent; + if (otherInfinity == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.Infinity; + } + + public IPartitionKeyComponent Truncate() + { + throw new InvalidOperationException(); + } + + public void WriteForHashing(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public override int GetHashCode() + { + return 0; + } + + public void JsonEncode(JsonWriter writer) + { + throw new NotImplementedException(); + } + + public object ToObject() + { + throw new NotImplementedException(); + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.Infinity); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Int128.cs b/Microsoft.Azure.Cosmos/src/direct/Int128.cs index 2c4894fbb9..f841f85fc5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Int128.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Int128.cs @@ -1,112 +1,112 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.SharedFiles.Routing -{ - using System; - using System.Numerics; - - internal struct Int128 - { - private readonly BigInteger value; - - - private static readonly BigInteger MaxBigIntValue = new BigInteger( - new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }); - - public static readonly Int128 MaxValue = new Int128( new BigInteger( - new byte[] - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F })); - - private Int128(BigInteger value) - { - this.value = value % MaxBigIntValue; - } - - public static implicit operator Int128(int n) - { - return new Int128(new BigInteger(n)); - } - - public Int128(byte[] data) - { - if (data.Length != 16) - { - throw new ArgumentException("data"); - } - - this.value = new BigInteger(data); - - if (this.value > MaxValue.value) - { - throw new ArgumentException(); - } - } - - public static Int128 operator *(Int128 left, Int128 right) - { - return new Int128(left.value * right.value); - } - - public static Int128 operator +(Int128 left, Int128 right) - { - return new Int128(left.value + right.value); - } - - public static Int128 operator -(Int128 left, Int128 right) - { - return new Int128(left.value - right.value); - } - - public static Int128 operator / (Int128 left, Int128 right) - { - return new Int128(left.value / right.value); - } - - public static bool operator >(Int128 left, Int128 right) - { - return left.value > right.value; - } - - public static bool operator <(Int128 left, Int128 right) - { - return left.value < right.value; - } - - public static bool operator ==(Int128 left, Int128 right) - { - return left.value == right.value; - } - - public static bool operator !=(Int128 left, Int128 right) - { - return left.value != right.value; - } - public override int GetHashCode() - { - return value.GetHashCode(); - } - - public override bool Equals(object obj) - { - return obj is Int128 other && this.Equals(other); - } - - public byte[] Bytes - { - get - { - byte[] bytes = this.value.ToByteArray(); - if (bytes.Length < 16) - { - byte[] paddedBytes = new byte[16]; - Buffer.BlockCopy(bytes, 0, paddedBytes, 0, bytes.Length); - return paddedBytes; - } - - return bytes; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.SharedFiles.Routing +{ + using System; + using System.Numerics; + + internal struct Int128 + { + private readonly BigInteger value; + + + private static readonly BigInteger MaxBigIntValue = new BigInteger( + new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }); + + public static readonly Int128 MaxValue = new Int128( new BigInteger( + new byte[] + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F })); + + private Int128(BigInteger value) + { + this.value = value % MaxBigIntValue; + } + + public static implicit operator Int128(int n) + { + return new Int128(new BigInteger(n)); + } + + public Int128(byte[] data) + { + if (data.Length != 16) + { + throw new ArgumentException("data"); + } + + this.value = new BigInteger(data); + + if (this.value > MaxValue.value) + { + throw new ArgumentException(); + } + } + + public static Int128 operator *(Int128 left, Int128 right) + { + return new Int128(left.value * right.value); + } + + public static Int128 operator +(Int128 left, Int128 right) + { + return new Int128(left.value + right.value); + } + + public static Int128 operator -(Int128 left, Int128 right) + { + return new Int128(left.value - right.value); + } + + public static Int128 operator / (Int128 left, Int128 right) + { + return new Int128(left.value / right.value); + } + + public static bool operator >(Int128 left, Int128 right) + { + return left.value > right.value; + } + + public static bool operator <(Int128 left, Int128 right) + { + return left.value < right.value; + } + + public static bool operator ==(Int128 left, Int128 right) + { + return left.value == right.value; + } + + public static bool operator !=(Int128 left, Int128 right) + { + return left.value != right.value; + } + public override int GetHashCode() + { + return value.GetHashCode(); + } + + public override bool Equals(object obj) + { + return obj is Int128 other && this.Equals(other); + } + + public byte[] Bytes + { + get + { + byte[] bytes = this.value.ToByteArray(); + if (bytes.Length < 16) + { + byte[] paddedBytes = new byte[16]; + Buffer.BlockCopy(bytes, 0, paddedBytes, 0, bytes.Length); + return paddedBytes; + } + + return bytes; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/InternalSchemaProperties.cs b/Microsoft.Azure.Cosmos/src/direct/InternalSchemaProperties.cs index 4384ae7e5b..a164bfff3c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InternalSchemaProperties.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InternalSchemaProperties.cs @@ -1,49 +1,49 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - /// - /// Represents internal schema properties of schema policy for a collection in the Azure Cosmos DB service. - /// - /// - internal sealed class InternalSchemaProperties : JsonSerializable, ICloneable - { - /// - /// Gets or sets a value that indicates whether collection schema represented by the schema policy - /// is only used for analytics purposes. - /// - [JsonProperty(PropertyName = Constants.Properties.UseSchemaForAnalyticsOnly)] - internal bool UseSchemaForAnalyticsOnly - { - get - { - return base.GetValue(Constants.Properties.UseSchemaForAnalyticsOnly); - } - set - { - base.SetValue(Constants.Properties.UseSchemaForAnalyticsOnly, value); - } - } - - /// - /// Performs a deep copy of the internal schema properties. - /// - /// - /// A clone of the internal schema properties. - /// - public object Clone() - { - InternalSchemaProperties cloned = new InternalSchemaProperties() - { - UseSchemaForAnalyticsOnly = this.UseSchemaForAnalyticsOnly - }; - - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + /// + /// Represents internal schema properties of schema policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class InternalSchemaProperties : JsonSerializable, ICloneable + { + /// + /// Gets or sets a value that indicates whether collection schema represented by the schema policy + /// is only used for analytics purposes. + /// + [JsonProperty(PropertyName = Constants.Properties.UseSchemaForAnalyticsOnly)] + internal bool UseSchemaForAnalyticsOnly + { + get + { + return base.GetValue(Constants.Properties.UseSchemaForAnalyticsOnly); + } + set + { + base.SetValue(Constants.Properties.UseSchemaForAnalyticsOnly, value); + } + } + + /// + /// Performs a deep copy of the internal schema properties. + /// + /// + /// A clone of the internal schema properties. + /// + public object Clone() + { + InternalSchemaProperties cloned = new InternalSchemaProperties() + { + UseSchemaForAnalyticsOnly = this.UseSchemaForAnalyticsOnly + }; + + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/InternalServerErrorException.cs b/Microsoft.Azure.Cosmos/src/direct/InternalServerErrorException.cs index 2f6a6e86b7..0ae02e6f31 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InternalServerErrorException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InternalServerErrorException.cs @@ -1,85 +1,86 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class InternalServerErrorException : DocumentClientException - { - public InternalServerErrorException() - : this(RMResources.InternalServerError) - { - - } - - public InternalServerErrorException(SubStatusCodes subStatusCode) - : base(message: RMResources.InternalServerError, statusCode: HttpStatusCode.InternalServerError, subStatusCode: subStatusCode) - { - - } - - public InternalServerErrorException(string message, SubStatusCodes subStatusCode) - : base(message, statusCode: HttpStatusCode.InternalServerError, subStatusCode: subStatusCode) - { - - } - - public InternalServerErrorException(string message, Uri requestUri = null) - : this(message, null, null, requestUri) - { - - } - - public InternalServerErrorException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public InternalServerErrorException(Exception innerException) - : this(RMResources.InternalServerError, innerException, null) - { - - } - - public InternalServerErrorException(string message, Exception innerException, Uri requestUri = null) - : this(message, innerException, null, requestUri) - { - - } - - public InternalServerErrorException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.InternalServerError, requestUri) - { - SetDescription(); - } - - public InternalServerErrorException(string message, - Exception innerException, - HttpResponseHeaders headers, - Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.InternalServerError, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private InternalServerErrorException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.InternalServerError) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.InternalServerError; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class InternalServerErrorException : DocumentClientException + { + public InternalServerErrorException() + : this(RMResources.InternalServerError) + { + + } + + public InternalServerErrorException(SubStatusCodes subStatusCode) + : base(message: RMResources.InternalServerError, statusCode: HttpStatusCode.InternalServerError, subStatusCode: subStatusCode) + { + + } + + public InternalServerErrorException(string message, SubStatusCodes subStatusCode) + : base(message, statusCode: HttpStatusCode.InternalServerError, subStatusCode: subStatusCode) + { + + } + + public InternalServerErrorException(string message, Uri requestUri = null, bool rawErrorMessageOnly = false) + : this(message, null, null, requestUri, rawErrorMessageOnly: rawErrorMessageOnly) + { + + } + + public InternalServerErrorException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public InternalServerErrorException(Exception innerException) + : this(RMResources.InternalServerError, innerException, null) + { + + } + + public InternalServerErrorException(string message, Exception innerException, Uri requestUri = null) + : this(message, innerException, null, requestUri) + { + + } + + public InternalServerErrorException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.InternalServerError, requestUri) + { + SetDescription(); + } + + public InternalServerErrorException(string message, + Exception innerException, + HttpResponseHeaders headers, + Uri requestUri = null, + bool rawErrorMessageOnly = false) + : base(message, innerException, headers, HttpStatusCode.InternalServerError, requestUri, rawErrorMessageOnly: rawErrorMessageOnly) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private InternalServerErrorException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.InternalServerError) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.InternalServerError; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/InvalidPartitionException.cs b/Microsoft.Azure.Cosmos/src/direct/InvalidPartitionException.cs index 4f9439e834..761763d7fc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InvalidPartitionException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InvalidPartitionException.cs @@ -1,76 +1,76 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class InvalidPartitionException : DocumentClientException - { - public InvalidPartitionException() - : this(RMResources.Gone) - { - - } - - public InvalidPartitionException(string message) - : this(message, (Exception)null, null) - { - } - - public InvalidPartitionException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - } - - public InvalidPartitionException(string message, Exception innerException) - : this(message, innerException, null) - { - } - - public InvalidPartitionException(Exception innerException) - : this(RMResources.Gone, innerException, null) - { - } - - public InvalidPartitionException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetDescription(); - SetSubStatus(); - } - - public InvalidPartitionException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetDescription(); - SetSubStatus(); - } - -#if !NETSTANDARD16 - private InvalidPartitionException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.Gone) - { - SetDescription(); - SetSubStatus(); - } -#endif - - private void SetSubStatus() - { - this.Headers[WFConstants.BackendHeaders.SubStatus] = - ((uint)SubStatusCodes.NameCacheIsStale).ToString(CultureInfo.InvariantCulture); - } - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class InvalidPartitionException : DocumentClientException + { + public InvalidPartitionException() + : this(RMResources.Gone) + { + + } + + public InvalidPartitionException(string message) + : this(message, (Exception)null, null) + { + } + + public InvalidPartitionException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + } + + public InvalidPartitionException(string message, Exception innerException) + : this(message, innerException, null) + { + } + + public InvalidPartitionException(Exception innerException) + : this(RMResources.Gone, innerException, null) + { + } + + public InvalidPartitionException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetDescription(); + SetSubStatus(); + } + + public InvalidPartitionException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetDescription(); + SetSubStatus(); + } + +#if !NETSTANDARD16 + private InvalidPartitionException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.Gone) + { + SetDescription(); + SetSubStatus(); + } +#endif + + private void SetSubStatus() + { + this.Headers[WFConstants.BackendHeaders.SubStatus] = + ((uint)SubStatusCodes.NameCacheIsStale).ToString(CultureInfo.InvariantCulture); + } + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs b/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs index d1a90e6759..8f08535f5b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs +++ b/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs @@ -1,930 +1,930 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Globalization; - using System.IO; - using System.Text; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Represents the base class for Azure Cosmos DB database objects and provides methods for serializing and deserializing from JSON. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - abstract class JsonSerializable //We introduce this type so that we dont have to expose the Newtonsoft type publically. - { - internal JObject propertyBag; - - private const string POCOSerializationOnly = "POCOSerializationOnly"; - - internal static bool JustPocoSerialization; - - static JsonSerializable() - { - int result; - - if (int.TryParse(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(POCOSerializationOnly)) ? "0" : Environment.GetEnvironmentVariable(POCOSerializationOnly), out result) && result == 1) - { - JustPocoSerialization = true; - } - else - { - JustPocoSerialization = false; - } - } - - internal JsonSerializable() //Prevent external derivation. - { - this.propertyBag = new JObject(); - } - - internal JsonSerializerSettings SerializerSettings { get; set; } - - //Public Serialization Helpers. - /// - /// Saves the object to the specified stream in the Azure Cosmos DB service. - /// - /// Saves the object to this output stream. - /// Uses an optional serialization formatting policy when saving the object. The default policy is set to None. - public void SaveTo(Stream stream, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - this.SaveTo(stream, formattingPolicy, null); - } - - /// - /// Saves the object to the specified stream in the Azure Cosmos DB service. - /// - /// Saves the object to this output stream. - /// Uses a custom serialization formatting policy when saving the object. - /// The serializer settings to use. - public void SaveTo(Stream stream, SerializationFormattingPolicy formattingPolicy, JsonSerializerSettings settings) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - this.SerializerSettings = settings; - JsonSerializer serializer = settings == null ? new JsonSerializer() : JsonSerializer.Create(settings); - JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(stream)); - this.SaveTo(jsonWriter, serializer, formattingPolicy); - } - - internal void SaveTo(JsonWriter writer, JsonSerializer serializer, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - if (writer == null) - { - throw new ArgumentNullException("writer"); - } - - if (serializer == null) - { - throw new ArgumentNullException("serializer"); - } - - if (formattingPolicy == SerializationFormattingPolicy.Indented) - { - writer.Formatting = Newtonsoft.Json.Formatting.Indented; - } - else - { - writer.Formatting = Newtonsoft.Json.Formatting.None; - } - - this.OnSave(); - - if ((typeof(Document).IsAssignableFrom(this.GetType()) && !this.GetType().Equals(typeof(Document))) - || (typeof(Attachment).IsAssignableFrom(this.GetType()) && !this.GetType().Equals(typeof(Attachment)))) - { - serializer.Serialize(writer, this); - } - else - { - if (JsonSerializable.JustPocoSerialization) - { - this.propertyBag.WriteTo(writer); - } - else - { - serializer.Serialize(writer, this.propertyBag); - } - } - writer.Flush(); - } - - /// - /// Saves the object to the specified string builder - /// - /// Saves the object to this output string builder. - /// Uses an optional serialization formatting policy when saving the object. The default policy is set to None. - internal void SaveTo(StringBuilder stringBuilder, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) - { - if (stringBuilder == null) - { - throw new ArgumentNullException("stringBuilder"); - } - - this.SaveTo(new JsonTextWriter(new StringWriter(stringBuilder, CultureInfo.CurrentCulture)), new JsonSerializer(), formattingPolicy); - } - - - /// - /// Loads the object from the specified JSON reader in the Azure Cosmos DB service. - /// - /// Loads the object from this JSON reader. - public virtual void LoadFrom(JsonReader reader) - { - // calling LoadFrom(reader, null) will not work here since this is a virtual method - // and hence that will instead call the overriden LoadFrom method in the derived class - // instead of the below overload of this class - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - this.propertyBag = JObject.Load(reader); - } - - /// - /// Loads the object from the specified JSON reader in the Azure Cosmos DB service. - /// - /// Loads the object from this JSON reader. - /// The JsonSerializerSettings to be used. - public virtual void LoadFrom(JsonReader reader, JsonSerializerSettings serializerSettings) - { - if (reader == null) - { - throw new ArgumentNullException("reader"); - } - - Helpers.SetupJsonReader(reader, serializerSettings); - - this.propertyBag = JObject.Load(reader); - this.SerializerSettings = serializerSettings; - } - - /// - /// Loads the object from the specified stream in the Azure Cosmos DB service. - /// - /// The type of the returning object. - /// The stream to load from. - /// The object loaded from the specified stream. - public static T LoadFrom(Stream stream) where T : JsonSerializable, new() - { - return LoadFrom(stream, null); - } - - /// - /// Loads the object from the specified stream. - /// - /// The type of the returning object. - /// The stream to load from. - /// Used to get a correct object from a stream. - /// The JsonSerializerSettings to be used - /// The object loaded from the specified stream. - internal static T LoadFrom(Stream stream, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - - JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); - - return JsonSerializable.LoadFrom(jsonReader, typeResolver, settings); - } - - /// - /// Loads the object from the specified stream using a Resolver. This method does not use a default constructor of the underlying type, - /// and instead loads the resource from the provided resolver, which is why this method does not impose the new() constraint to T and allows - /// the creation of an abstract class. - /// - /// The type of the returning object. - /// The stream to load from. - /// Used to get a correct object from a stream. - /// The JsonSerializerSettings to be used - /// The object loaded from the specified stream. - internal static T LoadFromWithResolver(Stream stream, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable - { - if (stream == null) - { - throw new ArgumentNullException(nameof(stream)); - } - - if (typeResolver == null) - { - throw new ArgumentNullException(nameof(typeResolver)); - } - - JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); - return JsonSerializable.LoadFromWithResolver(typeResolver, settings, jsonReader); - } - - /// - /// Loads the object from the specified stream using a Resolver. This method does not use a default constructor of the underlying type, - /// and instead loads the resource from the provided resolver, which is why this method does not impose the new() constraint to T and allows - /// the creation of an abstract class. - /// - /// The type of the returning object. - /// Serialized payload. - /// Used to get a correct object from a stream. - /// The JsonSerializerSettings to be used - /// The object loaded from the specified stream. - internal static T LoadFromWithResolver(string serialized, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable - { - if (serialized == null) - { - throw new ArgumentNullException(nameof(serialized)); - } - - if (typeResolver == null) - { - throw new ArgumentNullException(nameof(typeResolver)); - } - - JsonTextReader jsonReader = new JsonTextReader(new StringReader(serialized)); - return JsonSerializable.LoadFromWithResolver(typeResolver, settings, jsonReader); - } - - /// - /// Loads the object from the specified stream. - /// - /// The type of the returning object. - /// Serialized payload. - /// Used to get a correct object from a stream. - /// The JsonSerializerSettings to be used - /// The object loaded from the specified stream. - internal static T LoadFrom(string serialized, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() - { - if (serialized == null) - { - throw new ArgumentNullException("serialized"); - } - - JsonTextReader jsonReader = new JsonTextReader(new StringReader(serialized)); - - return JsonSerializable.LoadFrom(jsonReader, typeResolver, settings); - } - - /// - /// Deserializes the specified stream using the given constructor in the Azure Cosmos DB service. - /// - /// The type of the object. - /// The stream to load from. - /// The constructor used for the returning object. - /// The object loaded from the specified stream. - public static T LoadFromWithConstructor(Stream stream, Func constructorFunction) - { - return LoadFromWithConstructor(stream, constructorFunction, null); - } - - /// - /// Deserializes the specified stream using the given constructor in the Azure Cosmos DB service. - /// - /// The type of the object. - /// The stream to load from. - /// The constructor used for the returning object. - /// The JsonSerializerSettings to be used. - /// The object loaded from the specified stream. - public static T LoadFromWithConstructor(Stream stream, Func constructorFunction, JsonSerializerSettings settings) - { - if (stream == null) - { - throw new ArgumentNullException("stream"); - } - if (!typeof(T).IsSubclassOf(typeof(JsonSerializable))) - { - throw new ArgumentException("type is not serializable"); - } - - T resource = constructorFunction(); - - JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); - ((JsonSerializable)(object)resource).LoadFrom(jsonReader, settings); - return resource; - } - - /// - /// Returns the string representation of the object in the Azure Cosmos DB service. - /// - /// The string representation of the object. - public override string ToString() - { - this.OnSave(); - return this.propertyBag.ToString(); - } - - internal virtual void Validate() - { - } - - #region Protected Signals - /// - /// Get the value associated with the specified property name. - /// - /// - /// - /// - internal T GetValue(string propertyName) - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if (token != null) - { - // Enum Backward compatibility support. This code will not be - // needed with newer Json.Net version which handles enums correctly. - if (typeof(T).IsEnum()) - { - if (token.Type == JTokenType.String) - { - return token.ToObject(JsonSerializer.CreateDefault()); - } - } - return this.SerializerSettings == null ? - token.ToObject() : - token.ToObject(JsonSerializer.Create(this.SerializerSettings)); - } - } - return default(T); - } - - /// - /// Get the value associated with the specified property name. - /// - /// - /// - /// - /// - internal T GetValue(string propertyName, T defaultValue) - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if (token != null) - { - // Enum Backward compatibility support. This code will not be - // needed with newer Json.Net version which handles enums correctly. - if (typeof(T).IsEnum()) - { - if (token.Type == JTokenType.String) - { - return token.ToObject(JsonSerializer.CreateDefault()); - } - } - return this.SerializerSettings == null ? - token.ToObject() : - token.ToObject(JsonSerializer.Create(this.SerializerSettings)); - } - } - return defaultValue; - } - - /// - /// Get the enum value associated with the specified property name. - /// - /// - /// - /// - internal TEnum? GetEnumValue(string propertyName) where TEnum : struct - { - if (!typeof(TEnum).IsEnum()) - { - throw new ArgumentException($"{typeof(TEnum)} is not an Enum."); - } - - string valueString = this.GetValue(propertyName); - - if (string.IsNullOrWhiteSpace(valueString)) - { - return null; - } - - if (!Enum.TryParse(valueString, ignoreCase: true, out TEnum value) - || !Enum.IsDefined(typeof(TEnum), value)) - { - throw new BadRequestException($"Could not parse [{valueString}] as a valid enum value for property [{propertyName}]."); - } - - return value; - } - - /// - /// Get the value associated with the specified property name. - /// - /// - /// Field names which compose a path to the property to be retrieved. - /// - /// - internal T GetValueByPath(string[] fieldNames, T defaultValue) - { - if (fieldNames == null) - { - throw new ArgumentNullException("fieldNames"); - } - - if (fieldNames.Length == 0) - { - throw new ArgumentException("fieldNames is empty."); - } - - if (this.propertyBag != null) - { - JToken token = this.propertyBag[fieldNames[0]]; - for (int i = 1; i < fieldNames.Length; ++i) - { - if (token == null) - { - break; - } - - if (!(token is JObject)) - { - token = null; - } - else - { - token = token[fieldNames[i]]; - } - } - - if (token != null) - { - // Enum Backward compatibility support. This code will not be - // needed with newer Json.Net version which handles enums correctly. - if (typeof(T).IsEnum()) - { - if (token.Type == JTokenType.String) - { - return token.ToObject(JsonSerializer.CreateDefault()); - } - } - - return this.SerializerSettings == null ? - token.ToObject() : - token.ToObject(JsonSerializer.Create(this.SerializerSettings)); - } - } - - return defaultValue; - } - - /// - /// Set the value associated with the specified name. - /// - /// - /// - internal void SetValue(string name, object value) - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - if (value != null) - { - this.propertyBag[name] = JToken.FromObject(value); - } - else - { - this.propertyBag.Remove(name); - } - } - - /// - /// Set the value associated with the specified property name. - /// - /// - /// Field names which compose a path to the property to be retrieved. - /// - /// - /// This will overwrite the existing properties - internal void SetValueByPath(string[] fieldNames, T value) - { - if (fieldNames == null) - { - throw new ArgumentNullException("fieldNames"); - } - - if (fieldNames.Length == 0) - { - throw new ArgumentException("fieldNames is empty."); - } - - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - JToken token = this.propertyBag; - for (int i = 0; i < fieldNames.Length - 1; ++i) - { - if (token[fieldNames[i]] == null) - { - token[fieldNames[i]] = new JObject(); - } - - token = token[fieldNames[i]]; - } - - JObject tokenAsJObject = token as JObject; - if (value == null && tokenAsJObject != null) - { - tokenAsJObject.Remove(fieldNames[fieldNames.Length - 1]); - } - else - { - token[fieldNames[fieldNames.Length - 1]] = value == null ? null : JToken.FromObject(value); - } - } - - internal Collection GetValueCollection(string propertyName) - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if (token != null) - { - Collection jTokenCollection = token.ToObject>(); - Collection valueCollection = new Collection(); - foreach (JToken childToken in jTokenCollection) - { - if (childToken != null) - { - if (typeof(T).IsEnum()) - { - if (childToken.Type == JTokenType.String) - { - valueCollection.Add(childToken.ToObject(JsonSerializer.CreateDefault())); - continue; - } - } - valueCollection.Add( - this.SerializerSettings == null ? - childToken.ToObject() : - childToken.ToObject(JsonSerializer.Create(this.SerializerSettings))); - } - else - { - valueCollection.Add(default(T)); - } - } - return valueCollection; - } - } - return null; - } - - internal void SetValueCollection(string propertyName, Collection value) - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - if (value != null) - { - Collection jTokenCollection = new Collection(); - foreach (T childValue in value) - { - if (childValue != null) - { - jTokenCollection.Add(JToken.FromObject(childValue)); - } - else - { - jTokenCollection.Add(null); - } - } - this.propertyBag[propertyName] = JToken.FromObject(jTokenCollection); - } - else - { - this.propertyBag.Remove(propertyName); - } - } - - /// - /// Gets a deserialized child object with the given property name. - /// - /// The type of the child object, which must be a . - /// The child property name. - /// - /// Determines how an empty child object (i.e. '{}') will be handled. When this is true, an empty JObject will be used to initialize the child TSerializable. - /// When this if false, an empty JOBject will be treated as null, causing null to be returned. - /// - /// The deserialized child object. - internal TSerializable GetObject(string propertyName, bool returnEmptyObject = false) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (token != null && (returnEmptyObject || token.HasValues)) - { - TSerializable result = new TSerializable(); - result.propertyBag = JObject.FromObject(token); - return result; - } - } - - return null; - } - - /// - /// Gets a deserialized child object with the given property name. - /// - /// The type of the child object, which must be a . - /// The child property name. - /// The type resolver for polymorphic types. - /// - /// Determines how an empty child object (i.e. '{}') will be handled. When this is true, an empty JObject will be used to initialize the child TSerializable. - /// When this if false, an empty JOBject will be treated as null, causing null to be returned. - /// - /// The deserialized child object. - internal TSerializable GetObjectWithResolver( - string propertyName, - ITypeResolver typeResolver, - bool returnEmptyObject = false) where TSerializable : JsonSerializable - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (token != null && (returnEmptyObject || token.HasValues)) - { - if (token is JObject) - { - return typeResolver.Resolve(token as JObject); - } - else - { - throw new ArgumentException($"Cannot resolve property type. The property {propertyName} is not an object, it is a {token.Type}."); - } - } - } - - return null; - } - - internal void SetObject(string propertyName, TSerializable value) where TSerializable : JsonSerializable - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - this.propertyBag[propertyName] = value != null ? value.propertyBag : null; - } - - internal Collection GetObjectCollection(string propertyName, Type resourceType = null, string ownerName = null, ITypeResolver typeResolver = null) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (typeResolver == null) - { - typeResolver = GetTypeResolver(); - } - - if (token != null) - { - Collection jobjectCollection = token.ToObject>(); - Collection objectCollection = new Collection(); - foreach (JObject childObject in jobjectCollection) - { - if (childObject == null) - { - continue; - } - TSerializable result = typeResolver != null ? typeResolver.Resolve(childObject) : new TSerializable(); - result.propertyBag = childObject; - - // for public resource, let's add the Altlink - if (PathsHelper.IsPublicResource(typeof(TSerializable))) - { - Resource resource = result as Resource; - resource.AltLink = PathsHelper.GeneratePathForNameBased(resourceType, ownerName, resource.Id); - } - objectCollection.Add(result); - } - return objectCollection; - } - } - return null; - } - - internal Collection GetObjectCollectionWithResolver(string propertyName, ITypeResolver typeResolver) where TSerializable : JsonSerializable - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (token != null) - { - Collection jobjectCollection = token.ToObject>(); - Collection objectCollection = new Collection(); - foreach (JObject childObject in jobjectCollection) - { - if (childObject == null) - { - continue; - } - TSerializable result = typeResolver.Resolve(childObject); - result.propertyBag = childObject; - - objectCollection.Add(result); - } - return objectCollection; - } - } - return null; - } - - internal void SetObjectCollection(string propertyName, Collection value) where TSerializable : JsonSerializable - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - if (value != null) - { - Collection jobjectCollection = new Collection(); - foreach (TSerializable childValue in value) - { - childValue.OnSave(); - jobjectCollection.Add(childValue.propertyBag ?? new JObject()); - } - this.propertyBag[propertyName] = JToken.FromObject(jobjectCollection); - } - } - - internal Dictionary GetObjectDictionary( - string propertyName, - ITypeResolver typeResolver = null, - IEqualityComparer comparer = null) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (typeResolver == null) - { - typeResolver = GetTypeResolver(); - } - - if (token != null) - { - Dictionary objectDictionary; - if(comparer != null) - { - objectDictionary = new Dictionary(comparer); - } - else - { - objectDictionary = new Dictionary(); - } - - Dictionary jobjectDictionary = token.ToObject>(); - foreach (KeyValuePair kvp in jobjectDictionary) - { - TSerializable result = typeResolver != null ? typeResolver.Resolve(kvp.Value) : new TSerializable(); - result.propertyBag = kvp.Value; - - objectDictionary.Add(kvp.Key, result); - } - - return objectDictionary; - } - } - - return null; - } - - internal Dictionary GetObjectDictionaryWithNullableValues(string propertyName) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - - if (token != null) - { - Dictionary jobjectDictionary = token.ToObject>(); - if (jobjectDictionary == null) - { - return null; - } - - Dictionary objectDictionary = new Dictionary(); - foreach (KeyValuePair kvp in jobjectDictionary) - { - TSerializable result; - if (kvp.Value == null) - { - result = null; - } - else - { - result = new TSerializable(); - result.propertyBag = kvp.Value; - } - - objectDictionary.Add(kvp.Key, result); - } - - return objectDictionary; - } - } - return null; - } - - internal void SetObjectDictionary(string propertyName, Dictionary value) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - if (value != null) - { - Dictionary jobjectDictionary = new Dictionary(); - foreach (KeyValuePair kvp in value) - { - kvp.Value.OnSave(); - jobjectDictionary.Add(kvp.Key, kvp.Value.propertyBag ?? new JObject()); - } - this.propertyBag[propertyName] = JToken.FromObject(jobjectDictionary); - } - } - - internal void SetObjectDictionaryWithNullableValues(string propertyName, Dictionary value) where TSerializable : JsonSerializable, new() - { - if (this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - - if (value != null) - { - Dictionary jobjectDictionary = new Dictionary(); - foreach (KeyValuePair kvp in value) - { - if (kvp.Value != null) - { - kvp.Value.OnSave(); - jobjectDictionary.Add(kvp.Key, kvp.Value.propertyBag ?? new JObject()); - } - else - { - jobjectDictionary.Add(kvp.Key, null); - } - } - this.propertyBag[propertyName] = JToken.FromObject(jobjectDictionary); - } - } - - internal virtual void OnSave() - { - - } - - internal static ITypeResolver GetTypeResolver() where TResource : JsonSerializable, new() - { - ITypeResolver typeResolver = null; - if (typeof(TResource) == typeof(Offer)) - { - typeResolver = (ITypeResolver)(OfferTypeResolver.ResponseOfferTypeResolver); - } - - return typeResolver; - } - #endregion - - private static T LoadFrom(JsonTextReader jsonReader, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() - { - T resource = new T(); - - resource.LoadFrom(jsonReader, settings); - resource = (typeResolver != null) ? typeResolver.Resolve(resource.propertyBag) : resource; - return resource; - } - - private static T LoadFromWithResolver(ITypeResolver typeResolver, JsonSerializerSettings settings, JsonTextReader jsonReader) where T : JsonSerializable - { - Helpers.SetupJsonReader(jsonReader, settings); - JObject jObject = JObject.Load(jsonReader); - return typeResolver.Resolve(jObject); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Globalization; + using System.IO; + using System.Text; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents the base class for Azure Cosmos DB database objects and provides methods for serializing and deserializing from JSON. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + abstract class JsonSerializable //We introduce this type so that we dont have to expose the Newtonsoft type publically. + { + internal JObject propertyBag; + + private const string POCOSerializationOnly = "POCOSerializationOnly"; + + internal static bool JustPocoSerialization; + + static JsonSerializable() + { + int result; + + if (int.TryParse(string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(POCOSerializationOnly)) ? "0" : Environment.GetEnvironmentVariable(POCOSerializationOnly), out result) && result == 1) + { + JustPocoSerialization = true; + } + else + { + JustPocoSerialization = false; + } + } + + internal JsonSerializable() //Prevent external derivation. + { + this.propertyBag = new JObject(); + } + + internal JsonSerializerSettings SerializerSettings { get; set; } + + //Public Serialization Helpers. + /// + /// Saves the object to the specified stream in the Azure Cosmos DB service. + /// + /// Saves the object to this output stream. + /// Uses an optional serialization formatting policy when saving the object. The default policy is set to None. + public void SaveTo(Stream stream, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + this.SaveTo(stream, formattingPolicy, null); + } + + /// + /// Saves the object to the specified stream in the Azure Cosmos DB service. + /// + /// Saves the object to this output stream. + /// Uses a custom serialization formatting policy when saving the object. + /// The serializer settings to use. + public void SaveTo(Stream stream, SerializationFormattingPolicy formattingPolicy, JsonSerializerSettings settings) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + this.SerializerSettings = settings; + JsonSerializer serializer = settings == null ? new JsonSerializer() : JsonSerializer.Create(settings); + JsonTextWriter jsonWriter = new JsonTextWriter(new StreamWriter(stream)); + this.SaveTo(jsonWriter, serializer, formattingPolicy); + } + + internal void SaveTo(JsonWriter writer, JsonSerializer serializer, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + if (writer == null) + { + throw new ArgumentNullException("writer"); + } + + if (serializer == null) + { + throw new ArgumentNullException("serializer"); + } + + if (formattingPolicy == SerializationFormattingPolicy.Indented) + { + writer.Formatting = Newtonsoft.Json.Formatting.Indented; + } + else + { + writer.Formatting = Newtonsoft.Json.Formatting.None; + } + + this.OnSave(); + + if ((typeof(Document).IsAssignableFrom(this.GetType()) && !this.GetType().Equals(typeof(Document))) + || (typeof(Attachment).IsAssignableFrom(this.GetType()) && !this.GetType().Equals(typeof(Attachment)))) + { + serializer.Serialize(writer, this); + } + else + { + if (JsonSerializable.JustPocoSerialization) + { + this.propertyBag.WriteTo(writer); + } + else + { + serializer.Serialize(writer, this.propertyBag); + } + } + writer.Flush(); + } + + /// + /// Saves the object to the specified string builder + /// + /// Saves the object to this output string builder. + /// Uses an optional serialization formatting policy when saving the object. The default policy is set to None. + internal void SaveTo(StringBuilder stringBuilder, SerializationFormattingPolicy formattingPolicy = SerializationFormattingPolicy.None) + { + if (stringBuilder == null) + { + throw new ArgumentNullException("stringBuilder"); + } + + this.SaveTo(new JsonTextWriter(new StringWriter(stringBuilder, CultureInfo.CurrentCulture)), new JsonSerializer(), formattingPolicy); + } + + + /// + /// Loads the object from the specified JSON reader in the Azure Cosmos DB service. + /// + /// Loads the object from this JSON reader. + public virtual void LoadFrom(JsonReader reader) + { + // calling LoadFrom(reader, null) will not work here since this is a virtual method + // and hence that will instead call the overriden LoadFrom method in the derived class + // instead of the below overload of this class + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + this.propertyBag = JObject.Load(reader); + } + + /// + /// Loads the object from the specified JSON reader in the Azure Cosmos DB service. + /// + /// Loads the object from this JSON reader. + /// The JsonSerializerSettings to be used. + public virtual void LoadFrom(JsonReader reader, JsonSerializerSettings serializerSettings) + { + if (reader == null) + { + throw new ArgumentNullException("reader"); + } + + Helpers.SetupJsonReader(reader, serializerSettings); + + this.propertyBag = JObject.Load(reader); + this.SerializerSettings = serializerSettings; + } + + /// + /// Loads the object from the specified stream in the Azure Cosmos DB service. + /// + /// The type of the returning object. + /// The stream to load from. + /// The object loaded from the specified stream. + public static T LoadFrom(Stream stream) where T : JsonSerializable, new() + { + return LoadFrom(stream, null); + } + + /// + /// Loads the object from the specified stream. + /// + /// The type of the returning object. + /// The stream to load from. + /// Used to get a correct object from a stream. + /// The JsonSerializerSettings to be used + /// The object loaded from the specified stream. + internal static T LoadFrom(Stream stream, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + + JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); + + return JsonSerializable.LoadFrom(jsonReader, typeResolver, settings); + } + + /// + /// Loads the object from the specified stream using a Resolver. This method does not use a default constructor of the underlying type, + /// and instead loads the resource from the provided resolver, which is why this method does not impose the new() constraint to T and allows + /// the creation of an abstract class. + /// + /// The type of the returning object. + /// The stream to load from. + /// Used to get a correct object from a stream. + /// The JsonSerializerSettings to be used + /// The object loaded from the specified stream. + internal static T LoadFromWithResolver(Stream stream, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable + { + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + if (typeResolver == null) + { + throw new ArgumentNullException(nameof(typeResolver)); + } + + JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); + return JsonSerializable.LoadFromWithResolver(typeResolver, settings, jsonReader); + } + + /// + /// Loads the object from the specified stream using a Resolver. This method does not use a default constructor of the underlying type, + /// and instead loads the resource from the provided resolver, which is why this method does not impose the new() constraint to T and allows + /// the creation of an abstract class. + /// + /// The type of the returning object. + /// Serialized payload. + /// Used to get a correct object from a stream. + /// The JsonSerializerSettings to be used + /// The object loaded from the specified stream. + internal static T LoadFromWithResolver(string serialized, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable + { + if (serialized == null) + { + throw new ArgumentNullException(nameof(serialized)); + } + + if (typeResolver == null) + { + throw new ArgumentNullException(nameof(typeResolver)); + } + + JsonTextReader jsonReader = new JsonTextReader(new StringReader(serialized)); + return JsonSerializable.LoadFromWithResolver(typeResolver, settings, jsonReader); + } + + /// + /// Loads the object from the specified stream. + /// + /// The type of the returning object. + /// Serialized payload. + /// Used to get a correct object from a stream. + /// The JsonSerializerSettings to be used + /// The object loaded from the specified stream. + internal static T LoadFrom(string serialized, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() + { + if (serialized == null) + { + throw new ArgumentNullException("serialized"); + } + + JsonTextReader jsonReader = new JsonTextReader(new StringReader(serialized)); + + return JsonSerializable.LoadFrom(jsonReader, typeResolver, settings); + } + + /// + /// Deserializes the specified stream using the given constructor in the Azure Cosmos DB service. + /// + /// The type of the object. + /// The stream to load from. + /// The constructor used for the returning object. + /// The object loaded from the specified stream. + public static T LoadFromWithConstructor(Stream stream, Func constructorFunction) + { + return LoadFromWithConstructor(stream, constructorFunction, null); + } + + /// + /// Deserializes the specified stream using the given constructor in the Azure Cosmos DB service. + /// + /// The type of the object. + /// The stream to load from. + /// The constructor used for the returning object. + /// The JsonSerializerSettings to be used. + /// The object loaded from the specified stream. + public static T LoadFromWithConstructor(Stream stream, Func constructorFunction, JsonSerializerSettings settings) + { + if (stream == null) + { + throw new ArgumentNullException("stream"); + } + if (!typeof(T).IsSubclassOf(typeof(JsonSerializable))) + { + throw new ArgumentException("type is not serializable"); + } + + T resource = constructorFunction(); + + JsonTextReader jsonReader = new JsonTextReader(new StreamReader(stream)); + ((JsonSerializable)(object)resource).LoadFrom(jsonReader, settings); + return resource; + } + + /// + /// Returns the string representation of the object in the Azure Cosmos DB service. + /// + /// The string representation of the object. + public override string ToString() + { + this.OnSave(); + return this.propertyBag.ToString(); + } + + internal virtual void Validate() + { + } + + #region Protected Signals + /// + /// Get the value associated with the specified property name. + /// + /// + /// + /// + internal T GetValue(string propertyName) + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if (token != null) + { + // Enum Backward compatibility support. This code will not be + // needed with newer Json.Net version which handles enums correctly. + if (typeof(T).IsEnum()) + { + if (token.Type == JTokenType.String) + { + return token.ToObject(JsonSerializer.CreateDefault()); + } + } + return this.SerializerSettings == null ? + token.ToObject() : + token.ToObject(JsonSerializer.Create(this.SerializerSettings)); + } + } + return default(T); + } + + /// + /// Get the value associated with the specified property name. + /// + /// + /// + /// + /// + internal T GetValue(string propertyName, T defaultValue) + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if (token != null) + { + // Enum Backward compatibility support. This code will not be + // needed with newer Json.Net version which handles enums correctly. + if (typeof(T).IsEnum()) + { + if (token.Type == JTokenType.String) + { + return token.ToObject(JsonSerializer.CreateDefault()); + } + } + return this.SerializerSettings == null ? + token.ToObject() : + token.ToObject(JsonSerializer.Create(this.SerializerSettings)); + } + } + return defaultValue; + } + + /// + /// Get the enum value associated with the specified property name. + /// + /// + /// + /// + internal TEnum? GetEnumValue(string propertyName) where TEnum : struct + { + if (!typeof(TEnum).IsEnum()) + { + throw new ArgumentException($"{typeof(TEnum)} is not an Enum."); + } + + string valueString = this.GetValue(propertyName); + + if (string.IsNullOrWhiteSpace(valueString)) + { + return null; + } + + if (!Enum.TryParse(valueString, ignoreCase: true, out TEnum value) + || !Enum.IsDefined(typeof(TEnum), value)) + { + throw new BadRequestException($"Could not parse [{valueString}] as a valid enum value for property [{propertyName}]."); + } + + return value; + } + + /// + /// Get the value associated with the specified property name. + /// + /// + /// Field names which compose a path to the property to be retrieved. + /// + /// + internal T GetValueByPath(string[] fieldNames, T defaultValue) + { + if (fieldNames == null) + { + throw new ArgumentNullException("fieldNames"); + } + + if (fieldNames.Length == 0) + { + throw new ArgumentException("fieldNames is empty."); + } + + if (this.propertyBag != null) + { + JToken token = this.propertyBag[fieldNames[0]]; + for (int i = 1; i < fieldNames.Length; ++i) + { + if (token == null) + { + break; + } + + if (!(token is JObject)) + { + token = null; + } + else + { + token = token[fieldNames[i]]; + } + } + + if (token != null) + { + // Enum Backward compatibility support. This code will not be + // needed with newer Json.Net version which handles enums correctly. + if (typeof(T).IsEnum()) + { + if (token.Type == JTokenType.String) + { + return token.ToObject(JsonSerializer.CreateDefault()); + } + } + + return this.SerializerSettings == null ? + token.ToObject() : + token.ToObject(JsonSerializer.Create(this.SerializerSettings)); + } + } + + return defaultValue; + } + + /// + /// Set the value associated with the specified name. + /// + /// + /// + internal void SetValue(string name, object value) + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + if (value != null) + { + this.propertyBag[name] = JToken.FromObject(value); + } + else + { + this.propertyBag.Remove(name); + } + } + + /// + /// Set the value associated with the specified property name. + /// + /// + /// Field names which compose a path to the property to be retrieved. + /// + /// + /// This will overwrite the existing properties + internal void SetValueByPath(string[] fieldNames, T value) + { + if (fieldNames == null) + { + throw new ArgumentNullException("fieldNames"); + } + + if (fieldNames.Length == 0) + { + throw new ArgumentException("fieldNames is empty."); + } + + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + JToken token = this.propertyBag; + for (int i = 0; i < fieldNames.Length - 1; ++i) + { + if (token[fieldNames[i]] == null) + { + token[fieldNames[i]] = new JObject(); + } + + token = token[fieldNames[i]]; + } + + JObject tokenAsJObject = token as JObject; + if (value == null && tokenAsJObject != null) + { + tokenAsJObject.Remove(fieldNames[fieldNames.Length - 1]); + } + else + { + token[fieldNames[fieldNames.Length - 1]] = value == null ? null : JToken.FromObject(value); + } + } + + internal Collection GetValueCollection(string propertyName) + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if (token != null) + { + Collection jTokenCollection = token.ToObject>(); + Collection valueCollection = new Collection(); + foreach (JToken childToken in jTokenCollection) + { + if (childToken != null) + { + if (typeof(T).IsEnum()) + { + if (childToken.Type == JTokenType.String) + { + valueCollection.Add(childToken.ToObject(JsonSerializer.CreateDefault())); + continue; + } + } + valueCollection.Add( + this.SerializerSettings == null ? + childToken.ToObject() : + childToken.ToObject(JsonSerializer.Create(this.SerializerSettings))); + } + else + { + valueCollection.Add(default(T)); + } + } + return valueCollection; + } + } + return null; + } + + internal void SetValueCollection(string propertyName, Collection value) + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + if (value != null) + { + Collection jTokenCollection = new Collection(); + foreach (T childValue in value) + { + if (childValue != null) + { + jTokenCollection.Add(JToken.FromObject(childValue)); + } + else + { + jTokenCollection.Add(null); + } + } + this.propertyBag[propertyName] = JToken.FromObject(jTokenCollection); + } + else + { + this.propertyBag.Remove(propertyName); + } + } + + /// + /// Gets a deserialized child object with the given property name. + /// + /// The type of the child object, which must be a . + /// The child property name. + /// + /// Determines how an empty child object (i.e. '{}') will be handled. When this is true, an empty JObject will be used to initialize the child TSerializable. + /// When this if false, an empty JOBject will be treated as null, causing null to be returned. + /// + /// The deserialized child object. + internal TSerializable GetObject(string propertyName, bool returnEmptyObject = false) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (token != null && (returnEmptyObject || token.HasValues)) + { + TSerializable result = new TSerializable(); + result.propertyBag = JObject.FromObject(token); + return result; + } + } + + return null; + } + + /// + /// Gets a deserialized child object with the given property name. + /// + /// The type of the child object, which must be a . + /// The child property name. + /// The type resolver for polymorphic types. + /// + /// Determines how an empty child object (i.e. '{}') will be handled. When this is true, an empty JObject will be used to initialize the child TSerializable. + /// When this if false, an empty JOBject will be treated as null, causing null to be returned. + /// + /// The deserialized child object. + internal TSerializable GetObjectWithResolver( + string propertyName, + ITypeResolver typeResolver, + bool returnEmptyObject = false) where TSerializable : JsonSerializable + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (token != null && (returnEmptyObject || token.HasValues)) + { + if (token is JObject) + { + return typeResolver.Resolve(token as JObject); + } + else + { + throw new ArgumentException($"Cannot resolve property type. The property {propertyName} is not an object, it is a {token.Type}."); + } + } + } + + return null; + } + + internal void SetObject(string propertyName, TSerializable value) where TSerializable : JsonSerializable + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + this.propertyBag[propertyName] = value != null ? value.propertyBag : null; + } + + internal Collection GetObjectCollection(string propertyName, Type resourceType = null, string ownerName = null, ITypeResolver typeResolver = null) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (typeResolver == null) + { + typeResolver = GetTypeResolver(); + } + + if (token != null) + { + Collection jobjectCollection = token.ToObject>(); + Collection objectCollection = new Collection(); + foreach (JObject childObject in jobjectCollection) + { + if (childObject == null) + { + continue; + } + TSerializable result = typeResolver != null ? typeResolver.Resolve(childObject) : new TSerializable(); + result.propertyBag = childObject; + + // for public resource, let's add the Altlink + if (PathsHelper.IsPublicResource(typeof(TSerializable))) + { + Resource resource = result as Resource; + resource.AltLink = PathsHelper.GeneratePathForNameBased(resourceType, ownerName, resource.Id); + } + objectCollection.Add(result); + } + return objectCollection; + } + } + return null; + } + + internal Collection GetObjectCollectionWithResolver(string propertyName, ITypeResolver typeResolver) where TSerializable : JsonSerializable + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (token != null) + { + Collection jobjectCollection = token.ToObject>(); + Collection objectCollection = new Collection(); + foreach (JObject childObject in jobjectCollection) + { + if (childObject == null) + { + continue; + } + TSerializable result = typeResolver.Resolve(childObject); + result.propertyBag = childObject; + + objectCollection.Add(result); + } + return objectCollection; + } + } + return null; + } + + internal void SetObjectCollection(string propertyName, Collection value) where TSerializable : JsonSerializable + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + if (value != null) + { + Collection jobjectCollection = new Collection(); + foreach (TSerializable childValue in value) + { + childValue.OnSave(); + jobjectCollection.Add(childValue.propertyBag ?? new JObject()); + } + this.propertyBag[propertyName] = JToken.FromObject(jobjectCollection); + } + } + + internal Dictionary GetObjectDictionary( + string propertyName, + ITypeResolver typeResolver = null, + IEqualityComparer comparer = null) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (typeResolver == null) + { + typeResolver = GetTypeResolver(); + } + + if (token != null) + { + Dictionary objectDictionary; + if(comparer != null) + { + objectDictionary = new Dictionary(comparer); + } + else + { + objectDictionary = new Dictionary(); + } + + Dictionary jobjectDictionary = token.ToObject>(); + foreach (KeyValuePair kvp in jobjectDictionary) + { + TSerializable result = typeResolver != null ? typeResolver.Resolve(kvp.Value) : new TSerializable(); + result.propertyBag = kvp.Value; + + objectDictionary.Add(kvp.Key, result); + } + + return objectDictionary; + } + } + + return null; + } + + internal Dictionary GetObjectDictionaryWithNullableValues(string propertyName) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + + if (token != null) + { + Dictionary jobjectDictionary = token.ToObject>(); + if (jobjectDictionary == null) + { + return null; + } + + Dictionary objectDictionary = new Dictionary(); + foreach (KeyValuePair kvp in jobjectDictionary) + { + TSerializable result; + if (kvp.Value == null) + { + result = null; + } + else + { + result = new TSerializable(); + result.propertyBag = kvp.Value; + } + + objectDictionary.Add(kvp.Key, result); + } + + return objectDictionary; + } + } + return null; + } + + internal void SetObjectDictionary(string propertyName, Dictionary value) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + if (value != null) + { + Dictionary jobjectDictionary = new Dictionary(); + foreach (KeyValuePair kvp in value) + { + kvp.Value.OnSave(); + jobjectDictionary.Add(kvp.Key, kvp.Value.propertyBag ?? new JObject()); + } + this.propertyBag[propertyName] = JToken.FromObject(jobjectDictionary); + } + } + + internal void SetObjectDictionaryWithNullableValues(string propertyName, Dictionary value) where TSerializable : JsonSerializable, new() + { + if (this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + + if (value != null) + { + Dictionary jobjectDictionary = new Dictionary(); + foreach (KeyValuePair kvp in value) + { + if (kvp.Value != null) + { + kvp.Value.OnSave(); + jobjectDictionary.Add(kvp.Key, kvp.Value.propertyBag ?? new JObject()); + } + else + { + jobjectDictionary.Add(kvp.Key, null); + } + } + this.propertyBag[propertyName] = JToken.FromObject(jobjectDictionary); + } + } + + internal virtual void OnSave() + { + + } + + internal static ITypeResolver GetTypeResolver() where TResource : JsonSerializable, new() + { + ITypeResolver typeResolver = null; + if (typeof(TResource) == typeof(Offer)) + { + typeResolver = (ITypeResolver)(OfferTypeResolver.ResponseOfferTypeResolver); + } + + return typeResolver; + } + #endregion + + private static T LoadFrom(JsonTextReader jsonReader, ITypeResolver typeResolver, JsonSerializerSettings settings = null) where T : JsonSerializable, new() + { + T resource = new T(); + + resource.LoadFrom(jsonReader, settings); + resource = (typeResolver != null) ? typeResolver.Resolve(resource.propertyBag) : resource; + return resource; + } + + private static T LoadFromWithResolver(ITypeResolver typeResolver, JsonSerializerSettings settings, JsonTextReader jsonReader) where T : JsonSerializable + { + Helpers.SetupJsonReader(jsonReader, settings); + JObject jObject = JObject.Load(jsonReader); + return typeResolver.Resolve(jObject); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/JsonSerializableList.cs b/Microsoft.Azure.Cosmos/src/direct/JsonSerializableList.cs index b51ca93d15..eee06d87a8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/JsonSerializableList.cs +++ b/Microsoft.Azure.Cosmos/src/direct/JsonSerializableList.cs @@ -1,38 +1,38 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Internal class created for overriding ToString method for List of generic type T. - /// - internal sealed class JsonSerializableList : List - { - public JsonSerializableList(IEnumerable list) - : base(list) - { - } - - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } - - public static List LoadFrom(string serialized) - { - if (serialized == null) - { - throw new ArgumentNullException("serialized"); - } - - JArray array = JArray.Parse(serialized); - return array.ToObject>(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Internal class created for overriding ToString method for List of generic type T. + /// + internal sealed class JsonSerializableList : List + { + public JsonSerializableList(IEnumerable list) + : base(list) + { + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + public static List LoadFrom(string serialized) + { + if (serialized == null) + { + throw new ArgumentNullException("serialized"); + } + + JArray array = JArray.Parse(serialized); + return array.ToObject>(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/KeyWrapMetadata.cs b/Microsoft.Azure.Cosmos/src/direct/KeyWrapMetadata.cs index 963e82f285..f991532c23 100644 --- a/Microsoft.Azure.Cosmos/src/direct/KeyWrapMetadata.cs +++ b/Microsoft.Azure.Cosmos/src/direct/KeyWrapMetadata.cs @@ -1,67 +1,67 @@ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents key wrap metadata associated with a client encryption key. - /// - internal class KeyWrapMetadata : JsonSerializable - { - public KeyWrapMetadata() - { - - } - - [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataName, NullValueHandling = NullValueHandling.Ignore)] - internal string Name - { - get - { - return base.GetValue(Constants.Properties.KeyWrapMetadataName); - } - set - { - base.SetValue(Constants.Properties.KeyWrapMetadataName, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataType, NullValueHandling = NullValueHandling.Ignore)] - internal string Type - { - get - { - return base.GetValue(Constants.Properties.KeyWrapMetadataType); - } - set - { - base.SetValue(Constants.Properties.KeyWrapMetadataType, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataValue, NullValueHandling = NullValueHandling.Ignore)] - internal string Value - { - get - { - return base.GetValue(Constants.Properties.KeyWrapMetadataValue); - } - set - { - base.SetValue(Constants.Properties.KeyWrapMetadataValue, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataAlgorithm, NullValueHandling = NullValueHandling.Ignore)] - internal string Algorithm - { - get - { - return base.GetValue(Constants.Properties.KeyWrapMetadataAlgorithm); - } - set - { - base.SetValue(Constants.Properties.KeyWrapMetadataAlgorithm, value); - } - } - } -} +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents key wrap metadata associated with a client encryption key. + /// + internal class KeyWrapMetadata : JsonSerializable + { + public KeyWrapMetadata() + { + + } + + [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataName, NullValueHandling = NullValueHandling.Ignore)] + internal string Name + { + get + { + return base.GetValue(Constants.Properties.KeyWrapMetadataName); + } + set + { + base.SetValue(Constants.Properties.KeyWrapMetadataName, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataType, NullValueHandling = NullValueHandling.Ignore)] + internal string Type + { + get + { + return base.GetValue(Constants.Properties.KeyWrapMetadataType); + } + set + { + base.SetValue(Constants.Properties.KeyWrapMetadataType, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataValue, NullValueHandling = NullValueHandling.Ignore)] + internal string Value + { + get + { + return base.GetValue(Constants.Properties.KeyWrapMetadataValue); + } + set + { + base.SetValue(Constants.Properties.KeyWrapMetadataValue, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.KeyWrapMetadataAlgorithm, NullValueHandling = NullValueHandling.Ignore)] + internal string Algorithm + { + get + { + return base.GetValue(Constants.Properties.KeyWrapMetadataAlgorithm); + } + set + { + base.SetValue(Constants.Properties.KeyWrapMetadataAlgorithm, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/LbChannelState.cs b/Microsoft.Azure.Cosmos/src/direct/LbChannelState.cs index 3d3e139821..340c16291b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LbChannelState.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LbChannelState.cs @@ -1,96 +1,96 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Threading; - - // This class is thread safe. - sealed class LbChannelState : IDisposable - { - private readonly int maxRequestsPending; - private readonly IChannel channel; - private int requestsPending = 0; // Atomic. - // Atomic. Stays true for as long as IChannel.Healthy keeps returning - // true. Transitions to false exactly once, when IChannel.Healthy starts - // returning false. - private bool cachedHealthy = true; - - public LbChannelState(IChannel channel, int maxRequestsPending) - { - Debug.Assert(channel != null); - this.channel = channel; - Debug.Assert(maxRequestsPending > 0); - this.maxRequestsPending = maxRequestsPending; - } - - // Returns true if the channel is below peak utilization and false - // otherwise. - // If the call returns true, the caller must ensure that Exit() is - // called exactly once. Treat Enter() and Exit() like - // AddRef() and Release(). - public bool Enter() - { - int currentRequests = Interlocked.Increment(ref this.requestsPending); - if (currentRequests > this.maxRequestsPending) - { - currentRequests = Interlocked.Decrement(ref this.requestsPending); - Debug.Assert(currentRequests >= 0); - return false; - } - return true; - } - - // Returns true if the caller held the last reference to the channel - // state. Callers can use the return value to decide when to dispose - // of unhealthy channels. - public bool Exit() - { - int currentRequests = Interlocked.Decrement(ref this.requestsPending); - Debug.Assert(currentRequests >= 0); - return currentRequests == 0; - } - - // Checks the health status of the channel and returns it. This is more - // expensive than ShallowHealthy. Avoid calling it more than once per - // request. - public bool DeepHealthy - { - get - { - if (!this.ShallowHealthy) - { - return false; - } - bool healthy = this.channel.Healthy; - if (!healthy) - { - this.cachedHealthy = false; - Interlocked.MemoryBarrier(); - } - return healthy; - } - } - - // Returns a cached value that reflects the last health status returned - // by the underlying channel. Very cheap compared to DeepHealthy. Can - // be used multiple times per request. - public bool ShallowHealthy - { - get - { - Interlocked.MemoryBarrier(); - return this.cachedHealthy; - } - } - - public IChannel Channel { get { return this.channel; } } - - public void Dispose() - { - this.channel.Close(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Threading; + + // This class is thread safe. + sealed class LbChannelState : IDisposable + { + private readonly int maxRequestsPending; + private readonly IChannel channel; + private int requestsPending = 0; // Atomic. + // Atomic. Stays true for as long as IChannel.Healthy keeps returning + // true. Transitions to false exactly once, when IChannel.Healthy starts + // returning false. + private bool cachedHealthy = true; + + public LbChannelState(IChannel channel, int maxRequestsPending) + { + Debug.Assert(channel != null); + this.channel = channel; + Debug.Assert(maxRequestsPending > 0); + this.maxRequestsPending = maxRequestsPending; + } + + // Returns true if the channel is below peak utilization and false + // otherwise. + // If the call returns true, the caller must ensure that Exit() is + // called exactly once. Treat Enter() and Exit() like + // AddRef() and Release(). + public bool Enter() + { + int currentRequests = Interlocked.Increment(ref this.requestsPending); + if (currentRequests > this.maxRequestsPending) + { + currentRequests = Interlocked.Decrement(ref this.requestsPending); + Debug.Assert(currentRequests >= 0); + return false; + } + return true; + } + + // Returns true if the caller held the last reference to the channel + // state. Callers can use the return value to decide when to dispose + // of unhealthy channels. + public bool Exit() + { + int currentRequests = Interlocked.Decrement(ref this.requestsPending); + Debug.Assert(currentRequests >= 0); + return currentRequests == 0; + } + + // Checks the health status of the channel and returns it. This is more + // expensive than ShallowHealthy. Avoid calling it more than once per + // request. + public bool DeepHealthy + { + get + { + if (!this.ShallowHealthy) + { + return false; + } + bool healthy = this.channel.Healthy; + if (!healthy) + { + this.cachedHealthy = false; + Interlocked.MemoryBarrier(); + } + return healthy; + } + } + + // Returns a cached value that reflects the last health status returned + // by the underlying channel. Very cheap compared to DeepHealthy. Can + // be used multiple times per request. + public bool ShallowHealthy + { + get + { + Interlocked.MemoryBarrier(); + return this.cachedHealthy; + } + } + + public IChannel Channel { get { return this.channel; } } + + public void Dispose() + { + this.channel.Close(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs b/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs index 20103cc8e3..eff52c7e65 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs @@ -1,615 +1,615 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Runtime.InteropServices; - using System.Text; - using Microsoft.Azure.Cosmos.Core.Trace; - using System.Collections.Generic; - - internal sealed class LinuxSystemUtilizationReader : SystemUtilizationReaderBase - { - private readonly ProcStatFileParser procStatFileParser; - private readonly ProcMemInfoFileParser procMemInfoFileParser; - - private ulong lastIdleJiffies; - private ulong lastKernelJiffies; - private ulong lastOtherJiffies; - private ulong lastUserJiffies; - - public LinuxSystemUtilizationReader() : this(procStatFilePath: null, procMemoryInfoPath:null) - { - } - - internal LinuxSystemUtilizationReader(string procStatFilePath, string procMemoryInfoPath) - { - this.procStatFileParser = String.IsNullOrWhiteSpace(procStatFilePath) ? - new ProcStatFileParser() : - new ProcStatFileParser(procStatFilePath); - this.procMemInfoFileParser = String.IsNullOrWhiteSpace(procMemoryInfoPath) ? - new ProcMemInfoFileParser() : - new ProcMemInfoFileParser(procMemoryInfoPath); - this.lastIdleJiffies = 0; - this.lastKernelJiffies = 0; - this.lastOtherJiffies = 0; - this.lastUserJiffies = 0; - } - - protected override float GetSystemWideCpuUsageCore() - { - ulong currentUserJiffies; - ulong currentKernelJiffies; - ulong currentIdleJiffies; - ulong currentOtherJiffies; - if (!this.procStatFileParser.TryParseStatFile( - out currentUserJiffies, - out currentKernelJiffies, - out currentIdleJiffies, - out currentOtherJiffies)) - { - return Single.NaN; - } - - float totalCpuUsage = 0; - - if (this.lastIdleJiffies != 0) - { - ulong kernelJiffiesElapsed = currentKernelJiffies - this.lastKernelJiffies; - ulong userJiffiesElapsed = currentUserJiffies - this.lastUserJiffies; - ulong busyJiffiesElapsed = kernelJiffiesElapsed + - userJiffiesElapsed + - currentOtherJiffies - this.lastOtherJiffies; - - ulong jiffiesElapsed = busyJiffiesElapsed + - currentIdleJiffies - - this.lastIdleJiffies; - - if (jiffiesElapsed == 0) - { - // Can only ever happen when procfs content is identical between two calls - // and not even the idle jiffies have increased. In this case CPU utilization - // cannot be determined and the API isn't meant to be called in a tight loop anyway - return Single.NaN; - } - - totalCpuUsage = 100 * (busyJiffiesElapsed / (float)jiffiesElapsed); - } - - this.lastUserJiffies = currentUserJiffies; - this.lastKernelJiffies = currentKernelJiffies; - this.lastIdleJiffies = currentIdleJiffies; - this.lastOtherJiffies = currentOtherJiffies; - - return totalCpuUsage; - } - - /// - /// MemFree: This is the amount of unused physical memory(RAM). - /// MemAvailable: This is the estimated amount of physical memory(RAM) available for new programs. (from Linux 3.14) - /// - /// - protected override long? GetSystemWideMemoryAvailabiltyCore() - { - if(!procMemInfoFileParser.TryParseMemInfoFile(out long? freeMemory, out long? availableMemory)) - { - return null; - } - - if(availableMemory != null) - { - return availableMemory; - } - // other wise use "free memeory" information - return freeMemory; - } - - private class ProcStatFileParser - { - const string cpuPrefixFirstLine = "cpu"; - private const string DefaultProcStatFilePath = "/proc/stat"; - - private readonly string procStatFilePath; - private readonly ReusableTextReader reusableReader; - - public ProcStatFileParser() : this(DefaultProcStatFilePath) - { - } - - /// - /// Allows customization of the proc stat file path to allow testing this on Non-Linux machines - /// - /// - /// - internal ProcStatFileParser(string procStatFilePath) - { - if (String.IsNullOrWhiteSpace(procStatFilePath)) - { - throw new ArgumentNullException(nameof(procStatFilePath)); - } - - this.reusableReader = new ReusableTextReader(Encoding.UTF8, bufferSize: 256); - this.procStatFilePath = procStatFilePath; - } - - public bool TryParseStatFile( - out ulong userJiffiesElaped, - out ulong kernelJiffiesElapsed, - out ulong idleJiffiesElapsed, - out ulong otherJiffiesElapsed) - { - userJiffiesElaped = 0; - kernelJiffiesElapsed = 0; - idleJiffiesElapsed = 0; - otherJiffiesElapsed = 0; - - string statFileFirstLine; - if (!this.TryReadProcStatFirstLine(this.reusableReader, out statFileFirstLine)) - { - return false; - } - try - { - StringParser parser = new StringParser(statFileFirstLine, ' ', skipEmpty: true); - - string prefix = parser.MoveAndExtractNext(); - if (!cpuPrefixFirstLine.Equals(prefix, StringComparison.OrdinalIgnoreCase)) - { - DefaultTrace.TraceCritical($"Unexpected procfs/cpu-file format. '${statFileFirstLine}'"); - return false; - } - - ulong user = parser.ParseNextUInt64(); - ulong nice = parser.ParseNextUInt64(); - ulong kernel = parser.ParseNextUInt64(); - ulong idle = parser.ParseNextUInt64(); - - // according to http://www.linuxhowtos.org/manpages/5/proc.htm currently the cpu-line - // can have up to 9 columns with different processore state aggregates. It is posisble - // that this will change in later Linux versions and new columns are added - ulong others = 0; - while (parser.HasNext) - { - others += parser.ParseNextUInt64(); - } - - userJiffiesElaped = user + nice; - kernelJiffiesElapsed = kernel; - idleJiffiesElapsed = idle; - otherJiffiesElapsed = others; - - return true; - } - catch (InvalidDataException) - { - return false; - } - } - - private bool TryReadProcStatFirstLine(ReusableTextReader reusableReader, out string firstLine) - { - try - { - // ProcFS is a virtual file system. Content is kept in memory - // so no I/O when reading this FileStream --> not using async - using (FileStream fileStream = new FileStream( - this.procStatFilePath, - FileMode.Open, - FileAccess.Read, - FileShare.Read, - bufferSize: 1, - useAsync: false)) - { - firstLine = reusableReader.ReadJustFirstLine(fileStream); - return true; - } - } - catch (IOException ioException) - { - DefaultTrace.TraceError(ioException.Message); - firstLine = null; - return false; - } - } - } - - /// - /// Read /proc/meminfo file for the memory information. More information can be find here : - /// http://www.linuxhowtos.org/manpages/5/proc.htm - /// - private class ProcMemInfoFileParser - { - private const string DefaultProcMemInfoFilePath = "/proc/meminfo"; - - private readonly string procMemInfoFilePath; - private readonly ReusableTextReader reusableReader; - - public ProcMemInfoFileParser() : this(DefaultProcMemInfoFilePath) - { - } - - /// - /// Allows customization of the proc stat file path to allow testing this on Non-Linux machines - /// - /// - /// - internal ProcMemInfoFileParser(string procMemInfoFilePath) - { - if (String.IsNullOrWhiteSpace(procMemInfoFilePath)) - { - throw new ArgumentNullException(nameof(procMemInfoFilePath)); - } - - this.reusableReader = new ReusableTextReader(Encoding.UTF8, bufferSize: 256); - this.procMemInfoFilePath = procMemInfoFilePath; - } - - public bool TryParseMemInfoFile( - out long? freeMemory, - out long? availableMemory) - { - freeMemory = null; - availableMemory = null; - - if (!this.TryReadProcMemInfo(this.reusableReader, out List data)) - { - DefaultTrace.TraceCritical("Not able to read memory information from /proc/meminfo"); - return false; - } - - try - { - foreach (string dataLine in data) - { - StringParser parser = new StringParser(dataLine, ' ', skipEmpty: true); - string prefix = parser.MoveAndExtractNext(); - if (prefix.Contains("MemFree")) - { - freeMemory = (long)parser.ParseNextUInt64(); - } - else if (dataLine.Contains("MemAvailable")) - { - availableMemory = (long)parser.ParseNextUInt64(); - } - } - - //if either totalmemory information is not there or along with that free memeory information is not there then it should return false - if(freeMemory == null && availableMemory == null) - { - throw new InvalidDataException("Free Memory and Available Memory information is not available."); - } - - return true; - } - catch (InvalidDataException dataException) - { - DefaultTrace.TraceError(dataException.Message); - return false; - } - } - - private bool TryReadProcMemInfo(ReusableTextReader reusableReader, - out List data) - { - try - { - // ProcFS is a virtual file system. Content is kept in memory - // so no I/O when reading this FileStream --> not using async - using (FileStream fileStream = new FileStream( - this.procMemInfoFilePath, - FileMode.Open, - FileAccess.Read, - FileShare.Read, - bufferSize: 1, - useAsync: false)) - { - data = reusableReader.ReadMultipleLines(fileStream); - return true; - } - } - catch (IOException ioException) - { - DefaultTrace.TraceError(ioException.Message); - data = null; - return false; - } - } - } - - /// - /// Provides a string parser that may be used instead of String.Split to avoid unnecessary - /// string and array allocations. - /// - /// - /// This class has been ported from the dotnet/runtime repository here - /// https://github.com/dotnet/corefx/blob/master/src/Common/src/System/IO/StringParser.cs - /// - private struct StringParser - { - /// - /// The string being parsed. - /// - private readonly string buffer; - - /// - /// The separator character used to separate subcomponents of the larger string. - /// - private readonly char separator; - - /// - /// true if empty subcomponents should be skipped; false to treat them as valid entries. - /// - private readonly bool skipEmpty; - - /// - /// The ending index that represents the next index after the last character that's part - /// of the current entry. - /// - private int endIndex; - - /// - /// The starting index from which to parse the current entry. - /// - private int startIndex; - - /// - /// Initialize the StringParser. - /// - /// - /// The string to parse. - /// - /// - /// The separator character used to separate subcomponents of . - /// - /// - /// true if empty subcomponents should be skipped; false to treat them as valid entries. - /// Defaults to false. - /// - public StringParser(string buffer, char separator, bool skipEmpty = false) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - this.buffer = buffer; - this.separator = separator; - this.skipEmpty = skipEmpty; - this.startIndex = -1; - this.endIndex = -1; - } - - public bool HasNext - { - get - { - return this.endIndex < this.buffer.Length; - } - } - - /// - /// Gets the current subcomponent of the string as a string. - /// - public string ExtractCurrent() - { - if (this.buffer == null || this.startIndex == -1) - { - throw new InvalidOperationException(); - } - - return this.buffer.Substring(this.startIndex, this.endIndex - this.startIndex); - } - - /// - /// Moves to the next component of the string and returns it as a string. - /// - /// - /// - public string MoveAndExtractNext() - { - this.MoveNextOrFail(); - return this.buffer.Substring(this.startIndex, this.endIndex - this.startIndex); - } - - /// - /// Moves to the next component of the string. - /// - /// - /// true if there is a next component to be parsed; otherwise, false. - /// - public bool MoveNext() - { - if (this.buffer == null) - { - throw new InvalidOperationException(); - } - - while (true) - { - if (this.endIndex >= this.buffer.Length) - { - this.startIndex = this.endIndex; - return false; - } - - int nextSeparator = this.buffer.IndexOf(this.separator, this.endIndex + 1); - this.startIndex = this.endIndex + 1; - this.endIndex = nextSeparator >= 0 ? nextSeparator : this.buffer.Length; - - if (!this.skipEmpty || this.endIndex >= this.startIndex + 1) - { - return true; - } - } - } - - /// - /// Moves to the next component of the string. If there isn't one, it throws an exception. - /// - public void MoveNextOrFail() - { - if (!this.MoveNext()) - { - ThrowForInvalidData(); - } - } - - /// - /// Moves to the next component and parses it as a UInt64. - /// - public unsafe ulong ParseNextUInt64() - { - this.MoveNextOrFail(); - - ulong result = 0; - fixed (char* bufferPtr = this.buffer) - { - char* p = bufferPtr + this.startIndex; - char* end = bufferPtr + this.endIndex; - while (p != end) - { - int d = *p - '0'; - if (d < 0 || d > 9) - { - ThrowForInvalidData(); - } - result = checked((result * 10ul) + (ulong)d); - - p++; - } - } - - Debug.Assert(result == UInt64.Parse(this.ExtractCurrent(), CultureInfo.InvariantCulture), - "Expected manually parsed result to match Parse result"); - - return result; - } - - /// - /// Throws unconditionally for invalid data. - /// - private static void ThrowForInvalidData() - { - throw new InvalidDataException(); - } - } - - /// - /// Provides a reusable reader for reading all of the text from streams. - /// - private sealed class ReusableTextReader - { - private static readonly char[] lineBreakChars = Environment.NewLine.ToCharArray(); - - /// - /// StringBuilder used to store intermediate text results. - /// - private readonly StringBuilder builder; - - /// - /// Bytes read from the stream. - /// - private readonly byte[] bytes; - - /// - /// Temporary storage from characters converted from the bytes then written to the builder. - /// - private readonly char[] chars; - - /// - /// Decoder used to decode data read from the stream. - /// - private readonly Decoder decoder; - - /// - /// The Encoding to use. Defaults to UTF8. - /// - private readonly Encoding encoding; - - /// - /// Initializes a new reusable reader. - /// - /// - /// The Encoding to use. Defaults to UTF8. - /// - /// - /// The size of the buffer to use when reading from the stream. - /// - public ReusableTextReader(Encoding encoding = null, int bufferSize = 1024) - { - if (encoding == null) - { - this.encoding = Encoding.UTF8; - } - else - { - this.encoding = encoding; - } - - this.builder = new StringBuilder(); - this.decoder = encoding.GetDecoder(); - this.bytes = new byte[bufferSize]; - this.chars = new char[encoding.GetMaxCharCount(this.bytes.Length)]; - } - - public string ReadJustFirstLine(Stream source) - { - int bytesRead; - while ((bytesRead = source.Read(this.bytes, 0, this.bytes.Length)) != 0) - { - int charCount = this.decoder.GetChars(this.bytes, 0, bytesRead, this.chars, 0); - int lineFeedIndex = -1; - - for (int i = 0; i < charCount; i++) - { - // Except in test scenarios lineBreakChars will only contain one character '\n' (Linux) - // when running tests on Windows recognize any of the chars indicating new line '\r\n' - if (lineBreakChars.Contains(this.chars[i])) - { - lineFeedIndex = i; - break; - } - } - - if (lineFeedIndex < 0) - { - this.builder.Append(this.chars, 0, charCount); - } - else - { - this.builder.Append(this.chars, 0, lineFeedIndex); - break; - } - } - - string s = this.builder.ToString(); - - this.builder.Clear(); - this.decoder.Reset(); - - return s; - } - - public List ReadMultipleLines(Stream source) - { - List output = new List(); - using (StreamReader reader = new StreamReader(source, this.encoding)) - { - string line; - while ((line = reader.ReadLine()) != null) - { - output.Add(line); - } - } - - return output; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Runtime.InteropServices; + using System.Text; + using Microsoft.Azure.Cosmos.Core.Trace; + using System.Collections.Generic; + + internal sealed class LinuxSystemUtilizationReader : SystemUtilizationReaderBase + { + private readonly ProcStatFileParser procStatFileParser; + private readonly ProcMemInfoFileParser procMemInfoFileParser; + + private ulong lastIdleJiffies; + private ulong lastKernelJiffies; + private ulong lastOtherJiffies; + private ulong lastUserJiffies; + + public LinuxSystemUtilizationReader() : this(procStatFilePath: null, procMemoryInfoPath:null) + { + } + + internal LinuxSystemUtilizationReader(string procStatFilePath, string procMemoryInfoPath) + { + this.procStatFileParser = String.IsNullOrWhiteSpace(procStatFilePath) ? + new ProcStatFileParser() : + new ProcStatFileParser(procStatFilePath); + this.procMemInfoFileParser = String.IsNullOrWhiteSpace(procMemoryInfoPath) ? + new ProcMemInfoFileParser() : + new ProcMemInfoFileParser(procMemoryInfoPath); + this.lastIdleJiffies = 0; + this.lastKernelJiffies = 0; + this.lastOtherJiffies = 0; + this.lastUserJiffies = 0; + } + + protected override float GetSystemWideCpuUsageCore() + { + ulong currentUserJiffies; + ulong currentKernelJiffies; + ulong currentIdleJiffies; + ulong currentOtherJiffies; + if (!this.procStatFileParser.TryParseStatFile( + out currentUserJiffies, + out currentKernelJiffies, + out currentIdleJiffies, + out currentOtherJiffies)) + { + return Single.NaN; + } + + float totalCpuUsage = 0; + + if (this.lastIdleJiffies != 0) + { + ulong kernelJiffiesElapsed = currentKernelJiffies - this.lastKernelJiffies; + ulong userJiffiesElapsed = currentUserJiffies - this.lastUserJiffies; + ulong busyJiffiesElapsed = kernelJiffiesElapsed + + userJiffiesElapsed + + currentOtherJiffies - this.lastOtherJiffies; + + ulong jiffiesElapsed = busyJiffiesElapsed + + currentIdleJiffies - + this.lastIdleJiffies; + + if (jiffiesElapsed == 0) + { + // Can only ever happen when procfs content is identical between two calls + // and not even the idle jiffies have increased. In this case CPU utilization + // cannot be determined and the API isn't meant to be called in a tight loop anyway + return Single.NaN; + } + + totalCpuUsage = 100 * (busyJiffiesElapsed / (float)jiffiesElapsed); + } + + this.lastUserJiffies = currentUserJiffies; + this.lastKernelJiffies = currentKernelJiffies; + this.lastIdleJiffies = currentIdleJiffies; + this.lastOtherJiffies = currentOtherJiffies; + + return totalCpuUsage; + } + + /// + /// MemFree: This is the amount of unused physical memory(RAM). + /// MemAvailable: This is the estimated amount of physical memory(RAM) available for new programs. (from Linux 3.14) + /// + /// + protected override long? GetSystemWideMemoryAvailabiltyCore() + { + if(!procMemInfoFileParser.TryParseMemInfoFile(out long? freeMemory, out long? availableMemory)) + { + return null; + } + + if(availableMemory != null) + { + return availableMemory; + } + // other wise use "free memeory" information + return freeMemory; + } + + private class ProcStatFileParser + { + const string cpuPrefixFirstLine = "cpu"; + private const string DefaultProcStatFilePath = "/proc/stat"; + + private readonly string procStatFilePath; + private readonly ReusableTextReader reusableReader; + + public ProcStatFileParser() : this(DefaultProcStatFilePath) + { + } + + /// + /// Allows customization of the proc stat file path to allow testing this on Non-Linux machines + /// + /// + /// + internal ProcStatFileParser(string procStatFilePath) + { + if (String.IsNullOrWhiteSpace(procStatFilePath)) + { + throw new ArgumentNullException(nameof(procStatFilePath)); + } + + this.reusableReader = new ReusableTextReader(Encoding.UTF8, bufferSize: 256); + this.procStatFilePath = procStatFilePath; + } + + public bool TryParseStatFile( + out ulong userJiffiesElaped, + out ulong kernelJiffiesElapsed, + out ulong idleJiffiesElapsed, + out ulong otherJiffiesElapsed) + { + userJiffiesElaped = 0; + kernelJiffiesElapsed = 0; + idleJiffiesElapsed = 0; + otherJiffiesElapsed = 0; + + string statFileFirstLine; + if (!this.TryReadProcStatFirstLine(this.reusableReader, out statFileFirstLine)) + { + return false; + } + try + { + StringParser parser = new StringParser(statFileFirstLine, ' ', skipEmpty: true); + + string prefix = parser.MoveAndExtractNext(); + if (!cpuPrefixFirstLine.Equals(prefix, StringComparison.OrdinalIgnoreCase)) + { + DefaultTrace.TraceCritical($"Unexpected procfs/cpu-file format. '${statFileFirstLine}'"); + return false; + } + + ulong user = parser.ParseNextUInt64(); + ulong nice = parser.ParseNextUInt64(); + ulong kernel = parser.ParseNextUInt64(); + ulong idle = parser.ParseNextUInt64(); + + // according to http://www.linuxhowtos.org/manpages/5/proc.htm currently the cpu-line + // can have up to 9 columns with different processore state aggregates. It is posisble + // that this will change in later Linux versions and new columns are added + ulong others = 0; + while (parser.HasNext) + { + others += parser.ParseNextUInt64(); + } + + userJiffiesElaped = user + nice; + kernelJiffiesElapsed = kernel; + idleJiffiesElapsed = idle; + otherJiffiesElapsed = others; + + return true; + } + catch (InvalidDataException) + { + return false; + } + } + + private bool TryReadProcStatFirstLine(ReusableTextReader reusableReader, out string firstLine) + { + try + { + // ProcFS is a virtual file system. Content is kept in memory + // so no I/O when reading this FileStream --> not using async + using (FileStream fileStream = new FileStream( + this.procStatFilePath, + FileMode.Open, + FileAccess.Read, + FileShare.Read, + bufferSize: 1, + useAsync: false)) + { + firstLine = reusableReader.ReadJustFirstLine(fileStream); + return true; + } + } + catch (IOException ioException) + { + DefaultTrace.TraceError(ioException.Message); + firstLine = null; + return false; + } + } + } + + /// + /// Read /proc/meminfo file for the memory information. More information can be find here : + /// http://www.linuxhowtos.org/manpages/5/proc.htm + /// + private class ProcMemInfoFileParser + { + private const string DefaultProcMemInfoFilePath = "/proc/meminfo"; + + private readonly string procMemInfoFilePath; + private readonly ReusableTextReader reusableReader; + + public ProcMemInfoFileParser() : this(DefaultProcMemInfoFilePath) + { + } + + /// + /// Allows customization of the proc stat file path to allow testing this on Non-Linux machines + /// + /// + /// + internal ProcMemInfoFileParser(string procMemInfoFilePath) + { + if (String.IsNullOrWhiteSpace(procMemInfoFilePath)) + { + throw new ArgumentNullException(nameof(procMemInfoFilePath)); + } + + this.reusableReader = new ReusableTextReader(Encoding.UTF8, bufferSize: 256); + this.procMemInfoFilePath = procMemInfoFilePath; + } + + public bool TryParseMemInfoFile( + out long? freeMemory, + out long? availableMemory) + { + freeMemory = null; + availableMemory = null; + + if (!this.TryReadProcMemInfo(this.reusableReader, out List data)) + { + DefaultTrace.TraceCritical("Not able to read memory information from /proc/meminfo"); + return false; + } + + try + { + foreach (string dataLine in data) + { + StringParser parser = new StringParser(dataLine, ' ', skipEmpty: true); + string prefix = parser.MoveAndExtractNext(); + if (prefix.Contains("MemFree")) + { + freeMemory = (long)parser.ParseNextUInt64(); + } + else if (dataLine.Contains("MemAvailable")) + { + availableMemory = (long)parser.ParseNextUInt64(); + } + } + + //if either totalmemory information is not there or along with that free memeory information is not there then it should return false + if(freeMemory == null && availableMemory == null) + { + throw new InvalidDataException("Free Memory and Available Memory information is not available."); + } + + return true; + } + catch (InvalidDataException dataException) + { + DefaultTrace.TraceError(dataException.Message); + return false; + } + } + + private bool TryReadProcMemInfo(ReusableTextReader reusableReader, + out List data) + { + try + { + // ProcFS is a virtual file system. Content is kept in memory + // so no I/O when reading this FileStream --> not using async + using (FileStream fileStream = new FileStream( + this.procMemInfoFilePath, + FileMode.Open, + FileAccess.Read, + FileShare.Read, + bufferSize: 1, + useAsync: false)) + { + data = reusableReader.ReadMultipleLines(fileStream); + return true; + } + } + catch (IOException ioException) + { + DefaultTrace.TraceError(ioException.Message); + data = null; + return false; + } + } + } + + /// + /// Provides a string parser that may be used instead of String.Split to avoid unnecessary + /// string and array allocations. + /// + /// + /// This class has been ported from the dotnet/runtime repository here + /// https://github.com/dotnet/corefx/blob/master/src/Common/src/System/IO/StringParser.cs + /// + private struct StringParser + { + /// + /// The string being parsed. + /// + private readonly string buffer; + + /// + /// The separator character used to separate subcomponents of the larger string. + /// + private readonly char separator; + + /// + /// true if empty subcomponents should be skipped; false to treat them as valid entries. + /// + private readonly bool skipEmpty; + + /// + /// The ending index that represents the next index after the last character that's part + /// of the current entry. + /// + private int endIndex; + + /// + /// The starting index from which to parse the current entry. + /// + private int startIndex; + + /// + /// Initialize the StringParser. + /// + /// + /// The string to parse. + /// + /// + /// The separator character used to separate subcomponents of . + /// + /// + /// true if empty subcomponents should be skipped; false to treat them as valid entries. + /// Defaults to false. + /// + public StringParser(string buffer, char separator, bool skipEmpty = false) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + this.buffer = buffer; + this.separator = separator; + this.skipEmpty = skipEmpty; + this.startIndex = -1; + this.endIndex = -1; + } + + public bool HasNext + { + get + { + return this.endIndex < this.buffer.Length; + } + } + + /// + /// Gets the current subcomponent of the string as a string. + /// + public string ExtractCurrent() + { + if (this.buffer == null || this.startIndex == -1) + { + throw new InvalidOperationException(); + } + + return this.buffer.Substring(this.startIndex, this.endIndex - this.startIndex); + } + + /// + /// Moves to the next component of the string and returns it as a string. + /// + /// + /// + public string MoveAndExtractNext() + { + this.MoveNextOrFail(); + return this.buffer.Substring(this.startIndex, this.endIndex - this.startIndex); + } + + /// + /// Moves to the next component of the string. + /// + /// + /// true if there is a next component to be parsed; otherwise, false. + /// + public bool MoveNext() + { + if (this.buffer == null) + { + throw new InvalidOperationException(); + } + + while (true) + { + if (this.endIndex >= this.buffer.Length) + { + this.startIndex = this.endIndex; + return false; + } + + int nextSeparator = this.buffer.IndexOf(this.separator, this.endIndex + 1); + this.startIndex = this.endIndex + 1; + this.endIndex = nextSeparator >= 0 ? nextSeparator : this.buffer.Length; + + if (!this.skipEmpty || this.endIndex >= this.startIndex + 1) + { + return true; + } + } + } + + /// + /// Moves to the next component of the string. If there isn't one, it throws an exception. + /// + public void MoveNextOrFail() + { + if (!this.MoveNext()) + { + ThrowForInvalidData(); + } + } + + /// + /// Moves to the next component and parses it as a UInt64. + /// + public unsafe ulong ParseNextUInt64() + { + this.MoveNextOrFail(); + + ulong result = 0; + fixed (char* bufferPtr = this.buffer) + { + char* p = bufferPtr + this.startIndex; + char* end = bufferPtr + this.endIndex; + while (p != end) + { + int d = *p - '0'; + if (d < 0 || d > 9) + { + ThrowForInvalidData(); + } + result = checked((result * 10ul) + (ulong)d); + + p++; + } + } + + Debug.Assert(result == UInt64.Parse(this.ExtractCurrent(), CultureInfo.InvariantCulture), + "Expected manually parsed result to match Parse result"); + + return result; + } + + /// + /// Throws unconditionally for invalid data. + /// + private static void ThrowForInvalidData() + { + throw new InvalidDataException(); + } + } + + /// + /// Provides a reusable reader for reading all of the text from streams. + /// + private sealed class ReusableTextReader + { + private static readonly char[] lineBreakChars = Environment.NewLine.ToCharArray(); + + /// + /// StringBuilder used to store intermediate text results. + /// + private readonly StringBuilder builder; + + /// + /// Bytes read from the stream. + /// + private readonly byte[] bytes; + + /// + /// Temporary storage from characters converted from the bytes then written to the builder. + /// + private readonly char[] chars; + + /// + /// Decoder used to decode data read from the stream. + /// + private readonly Decoder decoder; + + /// + /// The Encoding to use. Defaults to UTF8. + /// + private readonly Encoding encoding; + + /// + /// Initializes a new reusable reader. + /// + /// + /// The Encoding to use. Defaults to UTF8. + /// + /// + /// The size of the buffer to use when reading from the stream. + /// + public ReusableTextReader(Encoding encoding = null, int bufferSize = 1024) + { + if (encoding == null) + { + this.encoding = Encoding.UTF8; + } + else + { + this.encoding = encoding; + } + + this.builder = new StringBuilder(); + this.decoder = encoding.GetDecoder(); + this.bytes = new byte[bufferSize]; + this.chars = new char[encoding.GetMaxCharCount(this.bytes.Length)]; + } + + public string ReadJustFirstLine(Stream source) + { + int bytesRead; + while ((bytesRead = source.Read(this.bytes, 0, this.bytes.Length)) != 0) + { + int charCount = this.decoder.GetChars(this.bytes, 0, bytesRead, this.chars, 0); + int lineFeedIndex = -1; + + for (int i = 0; i < charCount; i++) + { + // Except in test scenarios lineBreakChars will only contain one character '\n' (Linux) + // when running tests on Windows recognize any of the chars indicating new line '\r\n' + if (lineBreakChars.Contains(this.chars[i])) + { + lineFeedIndex = i; + break; + } + } + + if (lineFeedIndex < 0) + { + this.builder.Append(this.chars, 0, charCount); + } + else + { + this.builder.Append(this.chars, 0, lineFeedIndex); + break; + } + } + + string s = this.builder.ToString(); + + this.builder.Clear(); + this.decoder.Reset(); + + return s; + } + + public List ReadMultipleLines(Stream source) + { + List output = new List(); + using (StreamReader reader = new StreamReader(source, this.encoding)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + output.Add(line); + } + } + + return output; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingChannel.cs b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingChannel.cs index d9556435fa..7d22937cb3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingChannel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingChannel.cs @@ -1,201 +1,201 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Threading.Tasks; - using Microsoft.Azure.Documents.FaultInjection; - - // LoadBalancingChannel encapsulates the management of channels that connect to a single - // back-end server. It assigns load to each channel, decides when to open more - // channels, and when to close some channels. - // To assign load, this channel uses a simple round-robin approach. It examines - // the next channel available internally, and uses it if it's healthy and has - // request slots available. - internal sealed class LoadBalancingChannel : IChannel, IDisposable - { - private readonly Uri serverUri; - - private readonly LoadBalancingPartition singlePartition; - private readonly LoadBalancingPartition[] partitions; - - private bool disposed = false; - - public LoadBalancingChannel( - Uri serverUri, - ChannelProperties channelProperties, - bool localRegionRequest, - IChaosInterceptor chaosInterceptor = null) - { - this.serverUri = serverUri; - - if ((channelProperties.PartitionCount < 1) || - (channelProperties.PartitionCount > 8)) - { - throw new ArgumentOutOfRangeException( - nameof(channelProperties.PartitionCount), - channelProperties.PartitionCount, - "The partition count must be between 1 and 8"); - } - if (channelProperties.PartitionCount > 1) - { - ChannelProperties partitionProperties = new ChannelProperties( - channelProperties.UserAgent, - channelProperties.CertificateHostNameOverride, - channelProperties.ConnectionStateListener, - channelProperties.RequestTimerPool, - channelProperties.RequestTimeout, - channelProperties.OpenTimeout, - channelProperties.LocalRegionOpenTimeout, - channelProperties.PortReuseMode, - channelProperties.UserPortPool, - MathUtils.CeilingMultiple( - channelProperties.MaxChannels, - channelProperties.PartitionCount) / - channelProperties.PartitionCount, - 1, - channelProperties.MaxRequestsPerChannel, - channelProperties.MaxConcurrentOpeningConnectionCount, - channelProperties.ReceiveHangDetectionTime, - channelProperties.SendHangDetectionTime, - channelProperties.IdleTimeout, - channelProperties.IdleTimerPool, - channelProperties.CallerId, - channelProperties.EnableChannelMultiplexing, - channelProperties.MemoryStreamPool, - channelProperties.RemoteCertificateValidationCallback, - channelProperties.DnsResolutionFunction); - this.partitions = new LoadBalancingPartition[channelProperties.PartitionCount]; - for (int i = 0; i < this.partitions.Length; i++) - { - this.partitions[i] = new LoadBalancingPartition( - serverUri, - partitionProperties, - localRegionRequest, - chaosInterceptor: chaosInterceptor); - } - } - else - { - Debug.Assert(channelProperties.PartitionCount == 1); - this.singlePartition = new LoadBalancingPartition( - serverUri, - channelProperties, - localRegionRequest, - chaosInterceptor: chaosInterceptor); - } - } - - public bool Healthy - { - get - { - this.ThrowIfDisposed(); - return true; - } - } - - public Task RequestAsync( - DocumentServiceRequest request, - TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, - Guid activityId, - TransportRequestStats transportRequestStats) - { - this.ThrowIfDisposed(); - Debug.Assert(this.serverUri.IsBaseOf(physicalAddress.Uri), - string.Format("Expected: {0}.{1}Actual: {2}", - this.serverUri.GetLeftPart(UriPartial.Authority), - Environment.NewLine, - physicalAddress.Uri.GetLeftPart(UriPartial.Authority))); - - if (this.singlePartition != null) - { - Debug.Assert(this.partitions == null); - return this.singlePartition.RequestAsync( - request, physicalAddress, resourceOperation, activityId, transportRequestStats); - } - - Debug.Assert(this.partitions != null); - LoadBalancingPartition partition = this.GetLoadBalancedPartition(activityId); - return partition.RequestAsync( - request, physicalAddress, resourceOperation, activityId, transportRequestStats); - } - - /// - /// Attempts to open the Rntbd channel to the backend replica nodes. - /// - /// An unique identifier indicating the current activity id. - /// A completed task once the channel is opened. - public Task OpenChannelAsync( - Guid activityId) - { - this.ThrowIfDisposed(); - if (this.singlePartition != null) - { - Debug.Assert(this.partitions == null); - return this.singlePartition.OpenChannelAsync(activityId); - } - else - { - Debug.Assert(this.partitions != null); - LoadBalancingPartition partition = this.GetLoadBalancedPartition(activityId); - return partition.OpenChannelAsync( - activityId); - } - } - - /// - /// Gets the load balanced partition from the hash key, - /// generated from the current activity id. - /// - /// An unique identifier indicating the current activity id. - /// An instance of . - private LoadBalancingPartition GetLoadBalancedPartition( - Guid activityId) - { - int hash = activityId.GetHashCode(); - // Drop the sign bit. Operator % can return negative values in C#. - return this.partitions[ - (hash & 0x8FFFFFFF) % this.partitions.Length]; - } - - public void Close() - { - ((IDisposable)this).Dispose(); - } - -#region IDisposable - - void IDisposable.Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - if (this.singlePartition != null) - { - this.singlePartition.Dispose(); - } - if (this.partitions != null) - { - for (int i = 0; i < this.partitions.Length; i++) - { - this.partitions[i].Dispose(); - } - } - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - Debug.Assert(this.serverUri != null); - throw new ObjectDisposedException(string.Format("{0}:{1}", - nameof(LoadBalancingChannel), this.serverUri)); - } - } - -#endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Threading.Tasks; + using Microsoft.Azure.Documents.FaultInjection; + + // LoadBalancingChannel encapsulates the management of channels that connect to a single + // back-end server. It assigns load to each channel, decides when to open more + // channels, and when to close some channels. + // To assign load, this channel uses a simple round-robin approach. It examines + // the next channel available internally, and uses it if it's healthy and has + // request slots available. + internal sealed class LoadBalancingChannel : IChannel, IDisposable + { + private readonly Uri serverUri; + + private readonly LoadBalancingPartition singlePartition; + private readonly LoadBalancingPartition[] partitions; + + private bool disposed = false; + + public LoadBalancingChannel( + Uri serverUri, + ChannelProperties channelProperties, + bool localRegionRequest, + IChaosInterceptor chaosInterceptor = null) + { + this.serverUri = serverUri; + + if ((channelProperties.PartitionCount < 1) || + (channelProperties.PartitionCount > 8)) + { + throw new ArgumentOutOfRangeException( + nameof(channelProperties.PartitionCount), + channelProperties.PartitionCount, + "The partition count must be between 1 and 8"); + } + if (channelProperties.PartitionCount > 1) + { + ChannelProperties partitionProperties = new ChannelProperties( + channelProperties.UserAgent, + channelProperties.CertificateHostNameOverride, + channelProperties.ConnectionStateListener, + channelProperties.RequestTimerPool, + channelProperties.RequestTimeout, + channelProperties.OpenTimeout, + channelProperties.LocalRegionOpenTimeout, + channelProperties.PortReuseMode, + channelProperties.UserPortPool, + MathUtils.CeilingMultiple( + channelProperties.MaxChannels, + channelProperties.PartitionCount) / + channelProperties.PartitionCount, + 1, + channelProperties.MaxRequestsPerChannel, + channelProperties.MaxConcurrentOpeningConnectionCount, + channelProperties.ReceiveHangDetectionTime, + channelProperties.SendHangDetectionTime, + channelProperties.IdleTimeout, + channelProperties.IdleTimerPool, + channelProperties.CallerId, + channelProperties.EnableChannelMultiplexing, + channelProperties.MemoryStreamPool, + channelProperties.RemoteCertificateValidationCallback, + channelProperties.DnsResolutionFunction); + this.partitions = new LoadBalancingPartition[channelProperties.PartitionCount]; + for (int i = 0; i < this.partitions.Length; i++) + { + this.partitions[i] = new LoadBalancingPartition( + serverUri, + partitionProperties, + localRegionRequest, + chaosInterceptor: chaosInterceptor); + } + } + else + { + Debug.Assert(channelProperties.PartitionCount == 1); + this.singlePartition = new LoadBalancingPartition( + serverUri, + channelProperties, + localRegionRequest, + chaosInterceptor: chaosInterceptor); + } + } + + public bool Healthy + { + get + { + this.ThrowIfDisposed(); + return true; + } + } + + public Task RequestAsync( + DocumentServiceRequest request, + TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, + Guid activityId, + TransportRequestStats transportRequestStats) + { + this.ThrowIfDisposed(); + Debug.Assert(this.serverUri.IsBaseOf(physicalAddress.Uri), + string.Format("Expected: {0}.{1}Actual: {2}", + this.serverUri.GetLeftPart(UriPartial.Authority), + Environment.NewLine, + physicalAddress.Uri.GetLeftPart(UriPartial.Authority))); + + if (this.singlePartition != null) + { + Debug.Assert(this.partitions == null); + return this.singlePartition.RequestAsync( + request, physicalAddress, resourceOperation, activityId, transportRequestStats); + } + + Debug.Assert(this.partitions != null); + LoadBalancingPartition partition = this.GetLoadBalancedPartition(activityId); + return partition.RequestAsync( + request, physicalAddress, resourceOperation, activityId, transportRequestStats); + } + + /// + /// Attempts to open the Rntbd channel to the backend replica nodes. + /// + /// An unique identifier indicating the current activity id. + /// A completed task once the channel is opened. + public Task OpenChannelAsync( + Guid activityId) + { + this.ThrowIfDisposed(); + if (this.singlePartition != null) + { + Debug.Assert(this.partitions == null); + return this.singlePartition.OpenChannelAsync(activityId); + } + else + { + Debug.Assert(this.partitions != null); + LoadBalancingPartition partition = this.GetLoadBalancedPartition(activityId); + return partition.OpenChannelAsync( + activityId); + } + } + + /// + /// Gets the load balanced partition from the hash key, + /// generated from the current activity id. + /// + /// An unique identifier indicating the current activity id. + /// An instance of . + private LoadBalancingPartition GetLoadBalancedPartition( + Guid activityId) + { + int hash = activityId.GetHashCode(); + // Drop the sign bit. Operator % can return negative values in C#. + return this.partitions[ + (hash & 0x8FFFFFFF) % this.partitions.Length]; + } + + public void Close() + { + ((IDisposable)this).Dispose(); + } + +#region IDisposable + + void IDisposable.Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + if (this.singlePartition != null) + { + this.singlePartition.Dispose(); + } + if (this.partitions != null) + { + for (int i = 0; i < this.partitions.Length; i++) + { + this.partitions[i].Dispose(); + } + } + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + Debug.Assert(this.serverUri != null); + throw new ObjectDisposedException(string.Format("{0}:{1}", + nameof(LoadBalancingChannel), this.serverUri)); + } + } + +#endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs index 6a5664eb01..de0416c35a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs @@ -1,396 +1,400 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.FaultInjection; - - internal sealed class LoadBalancingPartition : IDisposable - { - private readonly Uri serverUri; - private readonly ChannelProperties channelProperties; - private readonly bool localRegionRequest; - private readonly int maxCapacity; // maxChannels * maxRequestsPerChannel - - private int requestsPending = 0; // Atomic. - // Clock hand. - private readonly SequenceGenerator sequenceGenerator = - new SequenceGenerator(); - - private readonly ReaderWriterLockSlim capacityLock = - new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - // capacity == openChannels.Count * maxRequestsPerChannel. - private int capacity = 0; // Guarded by capacityLock. - private readonly List openChannels = - new List(); // Guarded by capacityLock. - - private readonly SemaphoreSlim concurrentOpeningChannelSlim; - - private readonly IChaosInterceptor chaosInterceptor; - - // This channel factory delegate is meant for unit testing only and a default implementation is provided. - // However it can be extended to support the main line code path if needed. - private readonly Func, IChannel> channelFactory; - - public LoadBalancingPartition( - Uri serverUri, - ChannelProperties channelProperties, - bool localRegionRequest, - Func, IChannel> channelFactory = null, - IChaosInterceptor chaosInterceptor = null) - { - Debug.Assert(serverUri != null); - this.serverUri = serverUri; - Debug.Assert(channelProperties != null); - this.channelProperties = channelProperties; - this.localRegionRequest = localRegionRequest; - - this.maxCapacity = checked(channelProperties.MaxChannels * - channelProperties.MaxRequestsPerChannel); - - this.concurrentOpeningChannelSlim = - new SemaphoreSlim(channelProperties.MaxConcurrentOpeningConnectionCount, channelProperties.MaxConcurrentOpeningConnectionCount); - - this.channelFactory = channelFactory != null - ? channelFactory - : CreateAndInitializeChannel; - - this.chaosInterceptor = chaosInterceptor; - } - - public async Task RequestAsync( - DocumentServiceRequest request, - TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, - Guid activityId, - TransportRequestStats transportRequestStats) - { - int currentPending = Interlocked.Increment( - ref this.requestsPending); - transportRequestStats.NumberOfInflightRequestsToEndpoint = currentPending; - try - { - if (currentPending > this.maxCapacity) - { - throw new RequestRateTooLargeException( - string.Format( - "All connections to {0} are fully utilized. Increase " + - "the maximum number of connections or the maximum number " + - "of requests per connection", this.serverUri), - SubStatusCodes.ClientTcpChannelFull); - } - - transportRequestStats.RecordState(TransportRequestStats.RequestStage.ChannelAcquisitionStarted); - - while (true) - { - LbChannelState channelState = null; - bool addCapacity = false; - - uint sequenceNumber = this.sequenceGenerator.Next(); - - this.capacityLock.EnterReadLock(); - try - { - transportRequestStats.NumberOfOpenConnectionsToEndpoint = this.openChannels.Count; // Lock has already been acquired for openChannels - if (currentPending <= this.capacity) - { - // Enough capacity is available, pick a channel. - int channelIndex = (int) (sequenceNumber % this.openChannels.Count); - LbChannelState candidateChannel = this.openChannels[channelIndex]; - if (candidateChannel.Enter()) - { - // Do not check the health status yet. Do it - // without holding the capacity lock. - channelState = candidateChannel; - } - } - else - { - addCapacity = true; - } - } - finally - { - this.capacityLock.ExitReadLock(); - } - - if (channelState != null) - { - bool healthy = false; - try - { - healthy = channelState.DeepHealthy; - if (healthy) - { - return await channelState.Channel.RequestAsync( - request, - physicalAddress, - resourceOperation, - activityId, - transportRequestStats); - } - - // Unhealthy channel - this.capacityLock.EnterWriteLock(); - try - { - // Other callers might have noticed the channel - // fail at the same time. Do not assume that - // this caller is the only one trying to remove - // it. - if (this.openChannels.Remove(channelState)) - { - this.capacity -= this.channelProperties.MaxRequestsPerChannel; - } - Debug.Assert( - this.capacity == - this.openChannels.Count * - this.channelProperties.MaxRequestsPerChannel); - } - finally - { - this.capacityLock.ExitWriteLock(); - } - } - finally - { - bool lastCaller = channelState.Exit(); - if (lastCaller && !channelState.ShallowHealthy) - { - channelState.Dispose(); - DefaultTrace.TraceInformation( - "Closed unhealthy channel {0}", - channelState.Channel); - } - } - } - else if (addCapacity) - { - int targetCapacity = MathUtils.CeilingMultiple( - currentPending, - this.channelProperties.MaxRequestsPerChannel); - Debug.Assert(targetCapacity % this.channelProperties.MaxRequestsPerChannel == 0); - int targetChannels = targetCapacity / this.channelProperties.MaxRequestsPerChannel; - int channelsCreated = 0; - - this.capacityLock.EnterWriteLock(); - try - { - if (this.openChannels.Count < targetChannels) - { - channelsCreated = targetChannels - this.openChannels.Count; - } - - Action onChannelOpen = - (Guid createId, Guid connectionCorrelationId, Uri serverUri, Channel createdChannel) - => this.chaosInterceptor?.OnChannelOpen(createId, serverUri, request, createdChannel); - - while (this.openChannels.Count < targetChannels) - { - this.OpenChannelAndIncrementCapacity( - activityId: activityId, - onChannelOpen: onChannelOpen); - } - Debug.Assert( - this.capacity == - this.openChannels.Count * - this.channelProperties.MaxRequestsPerChannel); - } - finally - { - this.capacityLock.ExitWriteLock(); - } - if (channelsCreated > 0) - { - DefaultTrace.TraceInformation( - "Opened {0} channels to server {1}", - channelsCreated, this.serverUri); - } - } - } - } - finally - { - currentPending = Interlocked.Decrement( - ref this.requestsPending); - Debug.Assert(currentPending >= 0); - } - } - - /// - /// Open and initializes the . - /// - /// An unique identifier indicating the current activity id. - internal Task OpenChannelAsync(Guid activityId) - { - IChannel channel = null; - this.capacityLock.EnterUpgradeableReadLock(); - try - { - if (this.capacity < this.maxCapacity) - { - foreach (LbChannelState channelState in this.openChannels) - { - if (channelState.DeepHealthy) - { - return Task.FromResult(0); - } - } - - this.capacityLock.EnterWriteLock(); - try - { - channel = this.OpenChannelAndIncrementCapacity( - activityId: activityId); - } - finally - { - this.capacityLock.ExitWriteLock(); - } - } - else - { - string errorMessage = $"Failed to open channels to server {this.serverUri} because the current channel capacity {this.capacity} has exceeded the maaximum channel capacity limit: {this.maxCapacity}"; - - // Converting the error into invalid operation exception. Note that the OpenChannelAsync() method is used today, by the open connection flow - // in RntbdOpenConnectionHandler that is primarily used for the replica validation. Because the replica validation is done deterministically - // to open the Rntbd connections with best effort, throwing an exception from this place won't impact the replica validation flow because it - // will be caught and swallowed by the RntbdOpenConnectionHandler and the replica validation flow will continue. - throw new InvalidOperationException( - message: errorMessage); - } - } - finally - { - this.capacityLock.ExitUpgradeableReadLock(); - } - - if (channel == null) - { - throw new InvalidOperationException( - message: $"Could not open a channel to server {this.serverUri} because a channel instance didn't get created."); - } - - return channel.OpenChannelAsync(activityId); - } - - public void Dispose() - { - this.capacityLock.EnterWriteLock(); - try - { - foreach (LbChannelState channelState in this.openChannels) - { - channelState.Dispose(); - } - } - finally - { - this.capacityLock.ExitWriteLock(); - } - - try - { - this.capacityLock.Dispose(); - } - catch(SynchronizationLockException) - { - // SynchronizationLockException is thrown if there are inflight requests during the disposal of capacityLock - // suspend this exception to avoid crashing disposing other partitions/channels in hierarchical calls - return; - } - } - - /// - /// Open and initializes the and adds - /// the corresponding channel state to the openChannels pool - /// and increment the currrent channel capacity. - /// - /// An unique identifier indicating the current activity id. - /// An action to be invoked when the channel is opened. - /// An instance of . - private IChannel OpenChannelAndIncrementCapacity( - Guid activityId, - Action onChannelOpen = null) - { - Debug.Assert(this.capacityLock.IsWriteLockHeld); - - IChannel newChannel = this.channelFactory( - activityId, - this.serverUri, - this.channelProperties, - this.localRegionRequest, - this.concurrentOpeningChannelSlim, - this.chaosInterceptor, - onChannelOpen); - - if (newChannel == null) - { - throw new ArgumentNullException( - paramName: nameof(newChannel), - message: "Channel can't be null."); - } - - this.openChannels.Add( - new LbChannelState( - newChannel, - this.channelProperties.MaxRequestsPerChannel)); - this.capacity += this.channelProperties.MaxRequestsPerChannel; - - return newChannel; - } - - /// - /// Creates and initializes a new instance of rntbd . - /// - /// A guid containing the activity id for the operation. - /// An instance of containing the physical server uri. - /// An instance of . - /// A boolean flag indicating if the request is intendent for local region. - /// An instance of . - /// The Interceptor for fault injection. Null if not using fault injection - /// An action to be invoked when the channel is opened. - /// An instance of . - private static IChannel CreateAndInitializeChannel( - Guid activityId, - Uri serverUri, - ChannelProperties channelProperties, - bool localRegionRequest, - SemaphoreSlim concurrentOpeningChannelSlim, - IChaosInterceptor chaosInterceptor = null, - Action onChannelOpen = null) - { - return new Channel( - activityId, - serverUri, - channelProperties, - localRegionRequest, - concurrentOpeningChannelSlim, - chaosInterceptor, - onChannelOpen); - } - - private sealed class SequenceGenerator - { - private int current = 0; - - // Returns the next positive integer in the sequence. Wraps around - // when it reaches UInt32.MaxValue. - public uint Next() - { - // Interlocked.Increment only works with signed integer. - // Map the returned value to the unsigned int32 range. - return (uint) ( - ((uint) int.MaxValue) + 1 + - Interlocked.Increment(ref this.current)); - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.FaultInjection; + + internal sealed class LoadBalancingPartition : IDisposable + { + private readonly Uri serverUri; + private readonly ChannelProperties channelProperties; + private readonly bool localRegionRequest; + private readonly int maxCapacity; // maxChannels * maxRequestsPerChannel + + private int requestsPending = 0; // Atomic. + // Clock hand. + private readonly SequenceGenerator sequenceGenerator = + new SequenceGenerator(); + + private readonly ReaderWriterLockSlim capacityLock = + new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); + // capacity == openChannels.Count * maxRequestsPerChannel. + private int capacity = 0; // Guarded by capacityLock. + private readonly List openChannels = + new List(); // Guarded by capacityLock. + + private readonly SemaphoreSlim concurrentOpeningChannelSlim; + + private readonly IChaosInterceptor chaosInterceptor; + + // This channel factory delegate is meant for unit testing only and a default implementation is provided. + // However it can be extended to support the main line code path if needed. + private readonly Func, IChannel> channelFactory; + + public LoadBalancingPartition( + Uri serverUri, + ChannelProperties channelProperties, + bool localRegionRequest, + Func, IChannel> channelFactory = null, + IChaosInterceptor chaosInterceptor = null) + { + Debug.Assert(serverUri != null); + this.serverUri = serverUri; + Debug.Assert(channelProperties != null); + this.channelProperties = channelProperties; + this.localRegionRequest = localRegionRequest; + + this.maxCapacity = checked(channelProperties.MaxChannels * + channelProperties.MaxRequestsPerChannel); + + this.concurrentOpeningChannelSlim = + new SemaphoreSlim(channelProperties.MaxConcurrentOpeningConnectionCount, channelProperties.MaxConcurrentOpeningConnectionCount); + + this.channelFactory = channelFactory != null + ? channelFactory + : CreateAndInitializeChannel; + + this.chaosInterceptor = chaosInterceptor; + } + + public async Task RequestAsync( + DocumentServiceRequest request, + TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, + Guid activityId, + TransportRequestStats transportRequestStats) + { + int currentPending = Interlocked.Increment( + ref this.requestsPending); + transportRequestStats.NumberOfInflightRequestsToEndpoint = currentPending; + try + { + if (currentPending > this.maxCapacity) + { + throw new RequestRateTooLargeException( + string.Format( + "All connections to {0} are fully utilized. Increase " + + "the maximum number of connections or the maximum number " + + "of requests per connection", this.serverUri), + SubStatusCodes.ClientTcpChannelFull); + } + + transportRequestStats.RecordState(TransportRequestStats.RequestStage.ChannelAcquisitionStarted); + + while (true) + { + LbChannelState channelState = null; + bool addCapacity = false; + + uint sequenceNumber = this.sequenceGenerator.Next(); + + this.capacityLock.EnterReadLock(); + try + { + transportRequestStats.NumberOfOpenConnectionsToEndpoint = this.openChannels.Count; // Lock has already been acquired for openChannels + if (currentPending <= this.capacity) + { + // Enough capacity is available, pick a channel. + int channelIndex = (int) (sequenceNumber % this.openChannels.Count); + LbChannelState candidateChannel = this.openChannels[channelIndex]; + if (candidateChannel.Enter()) + { + // Do not check the health status yet. Do it + // without holding the capacity lock. + channelState = candidateChannel; + } + } + else + { + addCapacity = true; + } + } + finally + { + this.capacityLock.ExitReadLock(); + } + + if (channelState != null) + { + bool healthy = false; + try + { + healthy = channelState.DeepHealthy; + if (healthy) + { + return await channelState.Channel.RequestAsync( + request, + physicalAddress, + resourceOperation, + activityId, + transportRequestStats); + } + + // Unhealthy channel + this.capacityLock.EnterWriteLock(); + try + { + // Other callers might have noticed the channel + // fail at the same time. Do not assume that + // this caller is the only one trying to remove + // it. + if (this.openChannels.Remove(channelState)) + { + this.capacity -= this.channelProperties.MaxRequestsPerChannel; + } + Debug.Assert( + this.capacity == + this.openChannels.Count * + this.channelProperties.MaxRequestsPerChannel); + } + finally + { + this.capacityLock.ExitWriteLock(); + } + } + finally + { + bool lastCaller = channelState.Exit(); + if (lastCaller && !channelState.ShallowHealthy) + { + channelState.Dispose(); + DefaultTrace.TraceInformation( + "Closed unhealthy channel {0}", + channelState.Channel); + } + } + } + else if (addCapacity) + { + int targetCapacity = MathUtils.CeilingMultiple( + currentPending, + this.channelProperties.MaxRequestsPerChannel); + Debug.Assert(targetCapacity % this.channelProperties.MaxRequestsPerChannel == 0); + int targetChannels = targetCapacity / this.channelProperties.MaxRequestsPerChannel; + int channelsCreated = 0; + + this.capacityLock.EnterWriteLock(); + try + { + if (this.openChannels.Count < targetChannels) + { + channelsCreated = targetChannels - this.openChannels.Count; + } + + Func onChannelOpen = async (Guid createId, Guid connectionCorrelationId, Uri serverUri, Channel createdChannel) => + { + if (this.chaosInterceptor != null) + { + await this.chaosInterceptor.OnChannelOpenAsync(createId, connectionCorrelationId, serverUri, request, createdChannel); + } + }; + + while (this.openChannels.Count < targetChannels) + { + this.OpenChannelAndIncrementCapacity( + activityId: activityId, + onChannelOpen: onChannelOpen); + } + Debug.Assert( + this.capacity == + this.openChannels.Count * + this.channelProperties.MaxRequestsPerChannel); + } + finally + { + this.capacityLock.ExitWriteLock(); + } + if (channelsCreated > 0) + { + DefaultTrace.TraceInformation( + "Opened {0} channels to server {1}", + channelsCreated, this.serverUri); + } + } + } + } + finally + { + currentPending = Interlocked.Decrement( + ref this.requestsPending); + Debug.Assert(currentPending >= 0); + } + } + + /// + /// Open and initializes the . + /// + /// An unique identifier indicating the current activity id. + internal Task OpenChannelAsync(Guid activityId) + { + IChannel channel = null; + this.capacityLock.EnterUpgradeableReadLock(); + try + { + if (this.capacity < this.maxCapacity) + { + foreach (LbChannelState channelState in this.openChannels) + { + if (channelState.DeepHealthy) + { + return Task.FromResult(0); + } + } + + this.capacityLock.EnterWriteLock(); + try + { + channel = this.OpenChannelAndIncrementCapacity( + activityId: activityId); + } + finally + { + this.capacityLock.ExitWriteLock(); + } + } + else + { + string errorMessage = $"Failed to open channels to server {this.serverUri} because the current channel capacity {this.capacity} has exceeded the maaximum channel capacity limit: {this.maxCapacity}"; + + // Converting the error into invalid operation exception. Note that the OpenChannelAsync() method is used today, by the open connection flow + // in RntbdOpenConnectionHandler that is primarily used for the replica validation. Because the replica validation is done deterministically + // to open the Rntbd connections with best effort, throwing an exception from this place won't impact the replica validation flow because it + // will be caught and swallowed by the RntbdOpenConnectionHandler and the replica validation flow will continue. + throw new InvalidOperationException( + message: errorMessage); + } + } + finally + { + this.capacityLock.ExitUpgradeableReadLock(); + } + + if (channel == null) + { + throw new InvalidOperationException( + message: $"Could not open a channel to server {this.serverUri} because a channel instance didn't get created."); + } + + return channel.OpenChannelAsync(activityId); + } + + public void Dispose() + { + this.capacityLock.EnterWriteLock(); + try + { + foreach (LbChannelState channelState in this.openChannels) + { + channelState.Dispose(); + } + } + finally + { + this.capacityLock.ExitWriteLock(); + } + + try + { + this.capacityLock.Dispose(); + } + catch(SynchronizationLockException) + { + // SynchronizationLockException is thrown if there are inflight requests during the disposal of capacityLock + // suspend this exception to avoid crashing disposing other partitions/channels in hierarchical calls + return; + } + } + + /// + /// Open and initializes the and adds + /// the corresponding channel state to the openChannels pool + /// and increment the currrent channel capacity. + /// + /// An unique identifier indicating the current activity id. + /// An action to be invoked when the channel is opened. + /// An instance of . + private IChannel OpenChannelAndIncrementCapacity( + Guid activityId, + Func onChannelOpen = null) + { + Debug.Assert(this.capacityLock.IsWriteLockHeld); + + IChannel newChannel = this.channelFactory( + activityId, + this.serverUri, + this.channelProperties, + this.localRegionRequest, + this.concurrentOpeningChannelSlim, + this.chaosInterceptor, + onChannelOpen); + + if (newChannel == null) + { + throw new ArgumentNullException( + paramName: nameof(newChannel), + message: "Channel can't be null."); + } + + this.openChannels.Add( + new LbChannelState( + newChannel, + this.channelProperties.MaxRequestsPerChannel)); + this.capacity += this.channelProperties.MaxRequestsPerChannel; + + return newChannel; + } + + /// + /// Creates and initializes a new instance of rntbd . + /// + /// A guid containing the activity id for the operation. + /// An instance of containing the physical server uri. + /// An instance of . + /// A boolean flag indicating if the request is intendent for local region. + /// An instance of . + /// The Interceptor for fault injection. Null if not using fault injection + /// An func to be invoked when the channel is opened. + /// An instance of . + private static IChannel CreateAndInitializeChannel( + Guid activityId, + Uri serverUri, + ChannelProperties channelProperties, + bool localRegionRequest, + SemaphoreSlim concurrentOpeningChannelSlim, + IChaosInterceptor chaosInterceptor = null, + Func onChannelOpen = null) + { + return new Channel( + activityId, + serverUri, + channelProperties, + localRegionRequest, + concurrentOpeningChannelSlim, + chaosInterceptor, + onChannelOpen); + } + + private sealed class SequenceGenerator + { + private int current = 0; + + // Returns the next positive integer in the sequence. Wraps around + // when it reaches UInt32.MaxValue. + public uint Next() + { + // Interlocked.Increment only works with signed integer. + // Map the returned value to the unsigned int32 range. + return (uint) ( + ((uint) int.MaxValue) + 1 + + Interlocked.Increment(ref this.current)); + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs b/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs index c2258d7493..70cf2d52cd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs @@ -1,414 +1,452 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// The LocationNames class contains the names of Azure regions that - /// are currently supported by the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - static class LocationNames - { - /// - /// Name of the Azure West US region in the Azure Cosmos DB service. - /// - public const string WestUS = "West US"; - - /// - /// Name of the Azure West US 2 region in the Azure Cosmos DB service. - /// - public const string WestUS2 = "West US 2"; - - /// - /// Name of the Azure West Central US region in the Azure Cosmos DB service. - /// - public const string WestCentralUS = "West Central US"; - - /// - /// Name of the Azure East US region in the Azure Cosmos DB service. - /// - public const string EastUS = "East US"; - - /// - /// Name of the Azure East US 2 region in the Azure Cosmos DB service. - /// - public const string EastUS2 = "East US 2"; - - /// - /// Name of the Azure Central US region in the Azure Cosmos DB service. - /// - public const string CentralUS = "Central US"; - - /// - /// Name of the Azure Sourth Central US region in the Azure Cosmos DB service. - /// - public const string SouthCentralUS = "South Central US"; - - /// - /// Name of the Azure North Central US region in the Azure Cosmos DB service. - /// - public const string NorthCentralUS = "North Central US"; - - /// - /// Name of the Azure West Europe region in the Azure Cosmos DB service. - /// - public const string WestEurope = "West Europe"; - - /// - /// Name of the Azure North Europe region in the Azure Cosmos DB service. - /// - public const string NorthEurope = "North Europe"; - - /// - /// Name of the Azure East Asia region in the Azure Cosmos DB service. - /// - public const string EastAsia = "East Asia"; - - /// - /// Name of the Azure Southeast Asia region in the Azure Cosmos DB service. - /// - public const string SoutheastAsia = "Southeast Asia"; - - /// - /// Name of the Azure Japan East region in the Azure Cosmos DB service. - /// - public const string JapanEast = "Japan East"; - - /// - /// Name of the Azure Japan West region in the Azure Cosmos DB service. - /// - public const string JapanWest = "Japan West"; - - /// - /// Name of the Azure Australia East region in the Azure Cosmos DB service. - /// - public const string AustraliaEast = "Australia East"; - - /// - /// Name of the Azure Australia Southeast region in the Azure Cosmos DB service. - /// - public const string AustraliaSoutheast = "Australia Southeast"; - - /// - /// Name of the Azure Central India region in the Azure Cosmos DB service. - /// - public const string CentralIndia = "Central India"; - - /// - /// Name of the Azure South India region in the Azure Cosmos DB service. - /// - public const string SouthIndia = "South India"; - - /// - /// Name of the Azure West India region in the Azure Cosmos DB service. - /// - public const string WestIndia = "West India"; - - /// - /// Name of the Azure Canada East region in the Azure Cosmos DB service. - /// - public const string CanadaEast = "Canada East"; - - /// - /// Name of the Azure Canada Central region in the Azure Cosmos DB service. - /// - public const string CanadaCentral = "Canada Central"; - - /// - /// Name of the Azure Germany Central region in the Azure Cosmos DB service. - /// - public const string GermanyCentral = "Germany Central"; - - /// - /// Name of the Azure Germany Northeast region in the Azure Cosmos DB service. - /// - public const string GermanyNortheast = "Germany Northeast"; - - /// - /// Name of the Azure China North region in the Azure Cosmos DB service. - /// - public const string ChinaNorth = "China North"; - - /// - /// Name of the Azure China East region in the Azure Cosmos DB service. - /// - public const string ChinaEast = "China East"; - - /// - /// Name of the Azure China North 2 region in the Azure Cosmos DB service. - /// - public const string ChinaNorth2 = "China North 2"; - - /// - /// Name of the Azure China East 2 region in the Azure Cosmos DB service. - /// - public const string ChinaEast2 = "China East 2"; - - /// - /// Name of the Azure Korea South region in the Azure Cosmos DB service. - /// - public const string KoreaSouth = "Korea South"; - - /// - /// Name of the Azure Korea Central region in the Azure Cosmos DB service. - /// - public const string KoreaCentral = "Korea Central"; - - /// - /// Name of the Azure UK West region in the Azure Cosmos DB service. - /// - public const string UKWest = "UK West"; - - /// - /// Name of the Azure UK South region in the Azure Cosmos DB service. - /// - public const string UKSouth = "UK South"; - - /// - /// Name of the Azure Brazil South region in the Azure Cosmos DB service. - /// - public const string BrazilSouth = "Brazil South"; - - /// - /// Name of the Azure USGov Arizona region in the Azure Cosmos DB service. - /// - public const string USGovArizona = "USGov Arizona"; - - /// - /// Name of the Azure USGov Texas region in the Azure Cosmos DB service. - /// - public const string USGovTexas = "USGov Texas"; - - /// - /// Name of the Azure USGov Virginia region in the Azure Cosmos DB service. - /// - public const string USGovVirginia = "USGov Virginia"; - - /// - /// Name of the Azure East US 2 EUAP region in the Azure Cosmos DB service. - /// - public const string EastUS2EUAP = "East US 2 EUAP"; - - /// - /// Name of the Azure Central US EUAP region in the Azure Cosmos DB service. - /// - public const string CentralUSEUAP = "Central US EUAP"; - - /// - /// Name of the Azure France Central region in the Azure Cosmos DB service. - /// - public const string FranceCentral = "France Central"; - - /// - /// Name of the Azure France South region in the Azure Cosmos DB service. - /// - public const string FranceSouth = "France South"; - - /// - /// Name of the Azure DoD Central region in the Azure Cosmos DB service. - /// - public const string USDoDCentral = "USDoD Central"; - - /// - /// Name of the Azure DoD East region in the Azure Cosmos DB service. - /// - public const string USDoDEast = "USDoD East"; - - /// - /// Name of the Azure Australia Central region in the Azure Cosmos DB service. - /// - public const string AustraliaCentral = "Australia Central"; - - /// - /// Name of the Azure Australia Central 2 region in the Azure Cosmos DB service. - /// - public const string AustraliaCentral2 = "Australia Central 2"; - - /// - /// Name of the Azure South Africa North region in the Azure Cosmos DB service. - /// - public const string SouthAfricaNorth = "South Africa North"; - - /// - /// Name of the Azure South Africa West region in the Azure Cosmos DB service. - /// - public const string SouthAfricaWest = "South Africa West"; - - /// - /// Name of the Azure UAE Central region in the Azure Cosmos DB service. - /// - public const string UAECentral = "UAE Central"; - - /// - /// Name of the Azure UAE North region in the Azure Cosmos DB service. - /// - public const string UAENorth = "UAE North"; - - /// - /// Name of the Azure USNat East region in the Azure Cosmos DB service. - /// - public const string USNatEast = "USNat East"; - - /// - /// Name of the Azure USNat West region in the Azure Cosmos DB service. - /// - public const string USNatWest = "USNat West"; - - /// - /// Name of the Azure USSec East region in the Azure Cosmos DB service. - /// - public const string USSecEast = "USSec East"; - - /// - /// Name of the Azure USNat West region in the Azure Cosmos DB service. - /// - public const string USSecWest = "USSec West"; - - /// - /// Name of the Azure USSec West Central region in the Azure Cosmos DB service. - /// - internal const string USSecWestCentral = "USSec West Central"; - - /// - /// Name of the Azure Switzerland North region in the Azure Cosmos DB service. - /// - public const string SwitzerlandNorth = "Switzerland North"; - - /// - /// Name of the Azure Switzerland West region in the Azure Cosmos DB service. - /// - public const string SwitzerlandWest = "Switzerland West"; - - /// - /// Name of the Azure Germany North region in the Azure Cosmos DB service. - /// - public const string GermanyNorth = "Germany North"; - - /// - /// Name of the Azure Germany West Central region in the Azure Cosmos DB service. - /// - public const string GermanyWestCentral = "Germany West Central"; - - /// - /// Name of the Azure Norway East region in the Azure Cosmos DB service. - /// - public const string NorwayEast = "Norway East"; - - /// - /// Name of the Azure Norway West region in the Azure Cosmos DB service. - /// - public const string NorwayWest = "Norway West"; - - /// - /// Name of the Azure Brazil Southeast region in the Azure Cosmos DB service. - /// - public const string BrazilSoutheast = "Brazil Southeast"; - - /// - /// Name of the Azure West US 3 region in the Azure Cosmos DB service. - /// - public const string WestUS3 = "West US 3"; - - /// - /// Name of the Azure Jio India Central region in the Azure Cosmos DB service. - /// - public const string JioIndiaCentral = "Jio India Central"; - - /// - /// Name of the Azure Jio India West region in the Azure Cosmos DB service. - /// - public const string JioIndiaWest = "Jio India West"; - - /// - /// Name of the Azure East US SLV region in the Azure Cosmos DB service. - /// - public const string EastUSSLV = "East US SLV"; - - /// - /// Name of the Azure Sweden Central region in the Azure Cosmos DB service. - /// - public const string SwedenCentral = "Sweden Central"; - - /// - /// Name of the Azure Sweden South region in the Azure Cosmos DB service. - /// - public const string SwedenSouth = "Sweden South"; - - /// - /// Name of the Azure Qatar Central region in the Azure Cosmos DB service. - /// - public const string QatarCentral = "Qatar Central"; - - /// - /// Name of the Azure China North 3 region in the Azure Cosmos DB service. - /// - public const string ChinaNorth3 = "China North 3"; - - /// - /// Name of the Azure China East 3 region in the Azure Cosmos DB service. - /// - public const string ChinaEast3 = "China East 3"; - - /// - /// Name of the Azure Poland Central region in the Azure Cosmos DB service. - /// - public const string PolandCentral = "Poland Central"; - - /// - /// Name of the Azure Malaysia South region in the Azure Cosmos DB service. - /// - public const string MalaysiaSouth = "Malaysia South"; - - /// - /// Name of the Azure Italy North region in the Azure Cosmos DB service. - /// - public const string ItalyNorth = "Italy North"; - - /// - /// Name of the Azure Israel Central region in the Azure Cosmos DB service. - /// - public const string IsraelCentral = "Israel Central"; - - /// - /// Name of the Azure Mexico Central region in the Azure Cosmos DB service. - /// - public const string MexicoCentral = "Mexico Central"; - - /// - /// Name of the Azure Spain Central region in the Azure Cosmos DB service. - /// - public const string SpainCentral = "Spain Central"; - - /// - /// Name of the Azure Taiwan North region in the Azure Cosmos DB service. - /// - internal const string TaiwanNorth = "Taiwan North"; - - /// - /// Name of the Azure Taiwan Northwest region in the Azure Cosmos DB service. - /// - internal const string TaiwanNorthwest = "Taiwan Northwest"; - - /// - /// Name of the Azure Austria East region in the Azure Cosmos DB service. - /// - internal const string AustriaEast = "Austria East"; - - /// - /// Name of the Azure New Zealand North region in the Azure Cosmos DB service. - /// - internal const string NewZealandNorth = "New Zealand North"; - } -} - - - - - - - +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// The LocationNames class contains the names of Azure regions that + /// are currently supported by the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + static class LocationNames + { + /// + /// Name of the Azure West US region in the Azure Cosmos DB service. + /// + public const string WestUS = "West US"; + + /// + /// Name of the Azure West US 2 region in the Azure Cosmos DB service. + /// + public const string WestUS2 = "West US 2"; + + /// + /// Name of the Azure West Central US region in the Azure Cosmos DB service. + /// + public const string WestCentralUS = "West Central US"; + + /// + /// Name of the Azure East US region in the Azure Cosmos DB service. + /// + public const string EastUS = "East US"; + + /// + /// Name of the Azure East US 2 region in the Azure Cosmos DB service. + /// + public const string EastUS2 = "East US 2"; + + /// + /// Name of the Azure Central US region in the Azure Cosmos DB service. + /// + public const string CentralUS = "Central US"; + + /// + /// Name of the Azure Sourth Central US region in the Azure Cosmos DB service. + /// + public const string SouthCentralUS = "South Central US"; + + /// + /// Name of the Azure North Central US region in the Azure Cosmos DB service. + /// + public const string NorthCentralUS = "North Central US"; + + /// + /// Name of the Azure West Europe region in the Azure Cosmos DB service. + /// + public const string WestEurope = "West Europe"; + + /// + /// Name of the Azure North Europe region in the Azure Cosmos DB service. + /// + public const string NorthEurope = "North Europe"; + + /// + /// Name of the Azure East Asia region in the Azure Cosmos DB service. + /// + public const string EastAsia = "East Asia"; + + /// + /// Name of the Azure Southeast Asia region in the Azure Cosmos DB service. + /// + public const string SoutheastAsia = "Southeast Asia"; + + /// + /// Name of the Azure Japan East region in the Azure Cosmos DB service. + /// + public const string JapanEast = "Japan East"; + + /// + /// Name of the Azure Japan West region in the Azure Cosmos DB service. + /// + public const string JapanWest = "Japan West"; + + /// + /// Name of the Azure Australia East region in the Azure Cosmos DB service. + /// + public const string AustraliaEast = "Australia East"; + + /// + /// Name of the Azure Australia Southeast region in the Azure Cosmos DB service. + /// + public const string AustraliaSoutheast = "Australia Southeast"; + + /// + /// Name of the Azure Central India region in the Azure Cosmos DB service. + /// + public const string CentralIndia = "Central India"; + + /// + /// Name of the Azure South India region in the Azure Cosmos DB service. + /// + public const string SouthIndia = "South India"; + + /// + /// Name of the Azure West India region in the Azure Cosmos DB service. + /// + public const string WestIndia = "West India"; + + /// + /// Name of the Azure Canada East region in the Azure Cosmos DB service. + /// + public const string CanadaEast = "Canada East"; + + /// + /// Name of the Azure Canada Central region in the Azure Cosmos DB service. + /// + public const string CanadaCentral = "Canada Central"; + + /// + /// Name of the Azure Germany Central region in the Azure Cosmos DB service. + /// + public const string GermanyCentral = "Germany Central"; + + /// + /// Name of the Azure Germany Northeast region in the Azure Cosmos DB service. + /// + public const string GermanyNortheast = "Germany Northeast"; + + /// + /// Name of the Azure China North region in the Azure Cosmos DB service. + /// + public const string ChinaNorth = "China North"; + + /// + /// Name of the Azure China East region in the Azure Cosmos DB service. + /// + public const string ChinaEast = "China East"; + + /// + /// Name of the Azure China North 2 region in the Azure Cosmos DB service. + /// + public const string ChinaNorth2 = "China North 2"; + + /// + /// Name of the Azure China East 2 region in the Azure Cosmos DB service. + /// + public const string ChinaEast2 = "China East 2"; + + /// + /// Name of the Azure Korea South region in the Azure Cosmos DB service. + /// + public const string KoreaSouth = "Korea South"; + + /// + /// Name of the Azure Korea Central region in the Azure Cosmos DB service. + /// + public const string KoreaCentral = "Korea Central"; + + /// + /// Name of the Azure UK West region in the Azure Cosmos DB service. + /// + public const string UKWest = "UK West"; + + /// + /// Name of the Azure UK South region in the Azure Cosmos DB service. + /// + public const string UKSouth = "UK South"; + + /// + /// Name of the Azure Brazil South region in the Azure Cosmos DB service. + /// + public const string BrazilSouth = "Brazil South"; + + /// + /// Name of the Azure USGov Arizona region in the Azure Cosmos DB service. + /// + public const string USGovArizona = "USGov Arizona"; + + /// + /// Name of the Azure USGov Texas region in the Azure Cosmos DB service. + /// + public const string USGovTexas = "USGov Texas"; + + /// + /// Name of the Azure USGov Virginia region in the Azure Cosmos DB service. + /// + public const string USGovVirginia = "USGov Virginia"; + + /// + /// Name of the Azure East US 2 EUAP region in the Azure Cosmos DB service. + /// + public const string EastUS2EUAP = "East US 2 EUAP"; + + /// + /// Name of the Azure Central US EUAP region in the Azure Cosmos DB service. + /// + public const string CentralUSEUAP = "Central US EUAP"; + + /// + /// Name of the Azure France Central region in the Azure Cosmos DB service. + /// + public const string FranceCentral = "France Central"; + + /// + /// Name of the Azure France South region in the Azure Cosmos DB service. + /// + public const string FranceSouth = "France South"; + + /// + /// Name of the Azure DoD Central region in the Azure Cosmos DB service. + /// + public const string USDoDCentral = "USDoD Central"; + + /// + /// Name of the Azure DoD East region in the Azure Cosmos DB service. + /// + public const string USDoDEast = "USDoD East"; + + /// + /// Name of the Azure Australia Central region in the Azure Cosmos DB service. + /// + public const string AustraliaCentral = "Australia Central"; + + /// + /// Name of the Azure Australia Central 2 region in the Azure Cosmos DB service. + /// + public const string AustraliaCentral2 = "Australia Central 2"; + + /// + /// Name of the Azure South Africa North region in the Azure Cosmos DB service. + /// + public const string SouthAfricaNorth = "South Africa North"; + + /// + /// Name of the Azure South Africa West region in the Azure Cosmos DB service. + /// + public const string SouthAfricaWest = "South Africa West"; + + /// + /// Name of the Azure UAE Central region in the Azure Cosmos DB service. + /// + public const string UAECentral = "UAE Central"; + + /// + /// Name of the Azure UAE North region in the Azure Cosmos DB service. + /// + public const string UAENorth = "UAE North"; + + /// + /// Name of the Azure USNat East region in the Azure Cosmos DB service. + /// + public const string USNatEast = "USNat East"; + + /// + /// Name of the Azure USNat West region in the Azure Cosmos DB service. + /// + public const string USNatWest = "USNat West"; + + /// + /// Name of the Azure USSec East region in the Azure Cosmos DB service. + /// + public const string USSecEast = "USSec East"; + + /// + /// Name of the Azure USNat West region in the Azure Cosmos DB service. + /// + public const string USSecWest = "USSec West"; + + /// + /// Name of the Azure USSec West Central region in the Azure Cosmos DB service. + /// + public const string USSecWestCentral = "USSec West Central"; + + /// + /// Name of the Azure Switzerland North region in the Azure Cosmos DB service. + /// + public const string SwitzerlandNorth = "Switzerland North"; + + /// + /// Name of the Azure Switzerland West region in the Azure Cosmos DB service. + /// + public const string SwitzerlandWest = "Switzerland West"; + + /// + /// Name of the Azure Germany North region in the Azure Cosmos DB service. + /// + public const string GermanyNorth = "Germany North"; + + /// + /// Name of the Azure Germany West Central region in the Azure Cosmos DB service. + /// + public const string GermanyWestCentral = "Germany West Central"; + + /// + /// Name of the Azure Norway East region in the Azure Cosmos DB service. + /// + public const string NorwayEast = "Norway East"; + + /// + /// Name of the Azure Norway West region in the Azure Cosmos DB service. + /// + public const string NorwayWest = "Norway West"; + + /// + /// Name of the Azure Brazil Southeast region in the Azure Cosmos DB service. + /// + public const string BrazilSoutheast = "Brazil Southeast"; + + /// + /// Name of the Azure West US 3 region in the Azure Cosmos DB service. + /// + public const string WestUS3 = "West US 3"; + + /// + /// Name of the Azure Jio India Central region in the Azure Cosmos DB service. + /// + public const string JioIndiaCentral = "Jio India Central"; + + /// + /// Name of the Azure Jio India West region in the Azure Cosmos DB service. + /// + public const string JioIndiaWest = "Jio India West"; + + /// + /// Name of the Azure East US SLV region in the Azure Cosmos DB service. + /// + public const string EastUSSLV = "East US SLV"; + + /// + /// Name of the Azure Sweden Central region in the Azure Cosmos DB service. + /// + public const string SwedenCentral = "Sweden Central"; + + /// + /// Name of the Azure Sweden South region in the Azure Cosmos DB service. + /// + public const string SwedenSouth = "Sweden South"; + + /// + /// Name of the Azure Qatar Central region in the Azure Cosmos DB service. + /// + public const string QatarCentral = "Qatar Central"; + + /// + /// Name of the Azure China North 3 region in the Azure Cosmos DB service. + /// + public const string ChinaNorth3 = "China North 3"; + + /// + /// Name of the Azure China East 3 region in the Azure Cosmos DB service. + /// + public const string ChinaEast3 = "China East 3"; + + /// + /// Name of the Azure Poland Central region in the Azure Cosmos DB service. + /// + public const string PolandCentral = "Poland Central"; + + /// + /// Name of the Azure Malaysia South region in the Azure Cosmos DB service. + /// + public const string MalaysiaSouth = "Malaysia South"; + + /// + /// Name of the Azure Italy North region in the Azure Cosmos DB service. + /// + public const string ItalyNorth = "Italy North"; + + /// + /// Name of the Azure Israel Central region in the Azure Cosmos DB service. + /// + public const string IsraelCentral = "Israel Central"; + + /// + /// Name of the Azure Mexico Central region in the Azure Cosmos DB service. + /// + public const string MexicoCentral = "Mexico Central"; + + /// + /// Name of the Azure Spain Central region in the Azure Cosmos DB service. + /// + public const string SpainCentral = "Spain Central"; + + /// + /// Name of the Azure Taiwan North region in the Azure Cosmos DB service. + /// + public const string TaiwanNorth = "Taiwan North"; + + /// + /// Name of the Azure Taiwan Northwest region in the Azure Cosmos DB service. + /// + public const string TaiwanNorthwest = "Taiwan Northwest"; + + /// + /// Name of the Azure Austria East region in the Azure Cosmos DB service. + /// + internal const string AustriaEast = "Austria East"; + + /// + /// Name of the Azure New Zealand North region in the Azure Cosmos DB service. + /// + internal const string NewZealandNorth = "New Zealand North"; + + /// + /// Name of the Azure Bleu France Central region in the Azure Cosmos DB service. + /// + internal const string BleuFranceCentral = "Bleu France Central"; + + /// + /// Name of the Azure Bleu France South region in the Azure Cosmos DB service. + /// + internal const string BleuFranceSouth = "Bleu France South"; + + /// + /// Name of the Azure East US STG region in the Azure Cosmos DB service. + /// + internal const string EastUSSTG = "East US STG"; + + /// + /// Name of the Azure South Central US STG region in the Azure Cosmos DB service. + /// + internal const string SouthCentralUSSTG = "South Central US STG"; + + /// + /// Name of the Azure Indonesia Central region in the Azure Cosmos DB service. + /// + internal const string IndonesiaCentral = "Indonesia Central"; + + /// + /// Name of the Azure Southeast US region in the Azure Cosmos DB service. + /// + internal const string SoutheastUS = "Southeast US"; + + /// + /// Name of the Azure Malaysia West region in the Azure Cosmos DB service. + /// + internal const string MalaysiaWest = "Malaysia West"; + } +} + + + + + + + + + + diff --git a/Microsoft.Azure.Cosmos/src/direct/LockedException.cs b/Microsoft.Azure.Cosmos/src/direct/LockedException.cs index f4f4763918..7511be919f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LockedException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LockedException.cs @@ -1,79 +1,79 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class LockedException : DocumentClientException - { - public LockedException() - : this(RMResources.Locked) - { - - } - - public LockedException(string message, SubStatusCodes subStatusCode) - : base(message, (HttpStatusCode)StatusCodes.Locked, subStatusCode) - { - - } - - public LockedException(string message, Uri requestUri = null) - : this(message, null, null, requestUri) - { - - } - - public LockedException(string message, Exception innerException, Uri requestUri = null) - : this(message, innerException, null, requestUri) - { - - } - - public LockedException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public LockedException(Exception innerException) - : this(RMResources.Locked, innerException, null) - { - - } - - public LockedException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.Locked, requestUri) - { - SetDescription(); - } - - public LockedException(string message, - Exception innerException, - HttpResponseHeaders headers, - Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Locked, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private LockedException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.Locked) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.Locked; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class LockedException : DocumentClientException + { + public LockedException() + : this(RMResources.Locked) + { + + } + + public LockedException(string message, SubStatusCodes subStatusCode) + : base(message, (HttpStatusCode)StatusCodes.Locked, subStatusCode) + { + + } + + public LockedException(string message, Uri requestUri = null) + : this(message, null, null, requestUri) + { + + } + + public LockedException(string message, Exception innerException, Uri requestUri = null) + : this(message, innerException, null, requestUri) + { + + } + + public LockedException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public LockedException(Exception innerException) + : this(RMResources.Locked, innerException, null) + { + + } + + public LockedException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.Locked, requestUri) + { + SetDescription(); + } + + public LockedException(string message, + Exception innerException, + HttpResponseHeaders headers, + Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Locked, requestUri) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private LockedException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.Locked) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.Locked; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MaterializedViewDefinition.cs b/Microsoft.Azure.Cosmos/src/direct/MaterializedViewDefinition.cs index 768c84b5db..cf12feb0b3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MaterializedViewDefinition.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MaterializedViewDefinition.cs @@ -1,95 +1,95 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; -#if COSMOSCLIENT - internal -#else - internal -#endif - - sealed class MaterializedViewDefinition : JsonSerializable, ICloneable - { - [JsonProperty(PropertyName = Constants.Properties.SourceCollectionRid)] - public string SourceCollectionRid - { - get - { - return base.GetValue(Constants.Properties.SourceCollectionRid); - } - set - { - this.SetValue(Constants.Properties.SourceCollectionRid, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.SourceCollectionId, NullValueHandling = NullValueHandling.Ignore)] - public string SourceCollectionId - { - get - { - return base.GetValue(Constants.Properties.SourceCollectionId); - } - set - { - this.SetValue(Constants.Properties.SourceCollectionId, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.Definition)] - public string Definition - { - get - { - return base.GetValue(Constants.Properties.Definition); - } - set - { - this.SetValue(Constants.Properties.Definition, value); - } - } - - // This property is used and hence needs to be set only for non-SQL APIs - [JsonProperty(PropertyName = Constants.Properties.ApiSpecificDefinition, NullValueHandling = NullValueHandling.Ignore)] - public string ApiSpecificDefinition - { - get - { - return base.GetValue(Constants.Properties.ApiSpecificDefinition); - } - set - { - this.SetValue(Constants.Properties.ApiSpecificDefinition, value); - } - } - - // This property is used for identifying the collection as cold storage tier collection - [JsonProperty(PropertyName = Constants.Properties.MaterializedViewContainerType, NullValueHandling = NullValueHandling.Ignore)] - public string ContainerType - { - get - { - return base.GetValue(Constants.Properties.MaterializedViewContainerType); - } - set - { - this.SetValue(Constants.Properties.MaterializedViewContainerType, value); - } - } - - public object Clone() - { - MaterializedViewDefinition cloned = new MaterializedViewDefinition() - { - SourceCollectionRid = this.SourceCollectionRid, - Definition = this.Definition, - ApiSpecificDefinition = this.ApiSpecificDefinition, - ContainerType = this.ContainerType - }; - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; +#if COSMOSCLIENT + internal +#else + internal +#endif + + sealed class MaterializedViewDefinition : JsonSerializable, ICloneable + { + [JsonProperty(PropertyName = Constants.Properties.SourceCollectionRid)] + public string SourceCollectionRid + { + get + { + return base.GetValue(Constants.Properties.SourceCollectionRid); + } + set + { + this.SetValue(Constants.Properties.SourceCollectionRid, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.SourceCollectionId, NullValueHandling = NullValueHandling.Ignore)] + public string SourceCollectionId + { + get + { + return base.GetValue(Constants.Properties.SourceCollectionId); + } + set + { + this.SetValue(Constants.Properties.SourceCollectionId, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.Definition)] + public string Definition + { + get + { + return base.GetValue(Constants.Properties.Definition); + } + set + { + this.SetValue(Constants.Properties.Definition, value); + } + } + + // This property is used and hence needs to be set only for non-SQL APIs + [JsonProperty(PropertyName = Constants.Properties.ApiSpecificDefinition, NullValueHandling = NullValueHandling.Ignore)] + public string ApiSpecificDefinition + { + get + { + return base.GetValue(Constants.Properties.ApiSpecificDefinition); + } + set + { + this.SetValue(Constants.Properties.ApiSpecificDefinition, value); + } + } + + // This property is used for identifying the collection as cold storage tier collection + [JsonProperty(PropertyName = Constants.Properties.MaterializedViewContainerType, NullValueHandling = NullValueHandling.Ignore)] + public string ContainerType + { + get + { + return base.GetValue(Constants.Properties.MaterializedViewContainerType); + } + set + { + this.SetValue(Constants.Properties.MaterializedViewContainerType, value); + } + } + + public object Clone() + { + MaterializedViewDefinition cloned = new MaterializedViewDefinition() + { + SourceCollectionRid = this.SourceCollectionRid, + Definition = this.Definition, + ApiSpecificDefinition = this.ApiSpecificDefinition, + ContainerType = this.ContainerType + }; + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MaterializedViews.cs b/Microsoft.Azure.Cosmos/src/direct/MaterializedViews.cs index c8ddffae77..ac7d32dd38 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MaterializedViews.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MaterializedViews.cs @@ -1,47 +1,47 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - - internal sealed class MaterializedViews : JsonSerializable, ICloneable - { - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string Id - { - get - { - return base.GetValue(Constants.Properties.Id); - } - set - { - this.SetValue(Constants.Properties.Id, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.RId)] - public string Rid - { - get - { - return base.GetValue(Constants.Properties.RId); - } - set - { - this.SetValue(Constants.Properties.RId, value); - } - } - - public object Clone() - { - MaterializedViews cloned = new MaterializedViews() - { - Id = this.Id, - Rid = this.Rid, - }; - return cloned; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + + internal sealed class MaterializedViews : JsonSerializable, ICloneable + { + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string Id + { + get + { + return base.GetValue(Constants.Properties.Id); + } + set + { + this.SetValue(Constants.Properties.Id, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.RId)] + public string Rid + { + get + { + return base.GetValue(Constants.Properties.RId); + } + set + { + this.SetValue(Constants.Properties.RId, value); + } + } + + public object Clone() + { + MaterializedViews cloned = new MaterializedViews() + { + Id = this.Id, + Rid = this.Rid, + }; + return cloned; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MathUtils.cs b/Microsoft.Azure.Cosmos/src/direct/MathUtils.cs index dfda99935e..5952bb3e93 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MathUtils.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MathUtils.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - internal static class MathUtils - { - public static int CeilingMultiple(int x, int n) - { - if (x <= 0) - { - throw new ArgumentOutOfRangeException(nameof(x)); - } - if (n <= 0) - { - throw new ArgumentOutOfRangeException(nameof(n)); - } - x--; - return checked(x + n - x % n); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + internal static class MathUtils + { + public static int CeilingMultiple(int x, int n) + { + if (x <= 0) + { + throw new ArgumentOutOfRangeException(nameof(x)); + } + if (n <= 0) + { + throw new ArgumentOutOfRangeException(nameof(n)); + } + x--; + return checked(x + n - x % n); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/MaxNumberPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/MaxNumberPartitionKeyComponent.cs index f5ee1d115f..107672f571 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MaxNumberPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MaxNumberPartitionKeyComponent.cs @@ -1,79 +1,79 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class MaxNumber - { - public static readonly MaxNumber Value = new MaxNumber(); - - private MaxNumber() - { - } - } - - internal sealed class MaxNumberPartitionKeyComponent : IPartitionKeyComponent - { - public static readonly MaxNumberPartitionKeyComponent Value = new MaxNumberPartitionKeyComponent(); - - private MaxNumberPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - MaxNumberPartitionKeyComponent otherNumber = other as MaxNumberPartitionKeyComponent; - if (otherNumber == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.MaxNumber; - } - - public override int GetHashCode() - { - return 0; - } - - public IPartitionKeyComponent Truncate() - { - throw new InvalidOperationException(); - } - - public void WriteForHashing(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void JsonEncode(JsonWriter writer) - { - PartitionKeyInternalJsonConverter.JsonEncode(this, writer); - } - - public object ToObject() - { - return MaxNumber.Value; - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.MaxNumber); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class MaxNumber + { + public static readonly MaxNumber Value = new MaxNumber(); + + private MaxNumber() + { + } + } + + internal sealed class MaxNumberPartitionKeyComponent : IPartitionKeyComponent + { + public static readonly MaxNumberPartitionKeyComponent Value = new MaxNumberPartitionKeyComponent(); + + private MaxNumberPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + MaxNumberPartitionKeyComponent otherNumber = other as MaxNumberPartitionKeyComponent; + if (otherNumber == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.MaxNumber; + } + + public override int GetHashCode() + { + return 0; + } + + public IPartitionKeyComponent Truncate() + { + throw new InvalidOperationException(); + } + + public void WriteForHashing(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void JsonEncode(JsonWriter writer) + { + PartitionKeyInternalJsonConverter.JsonEncode(this, writer); + } + + public object ToObject() + { + return MaxNumber.Value; + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.MaxNumber); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MaxStringPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/MaxStringPartitionKeyComponent.cs index a37fc6cb46..b3877e111c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MaxStringPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MaxStringPartitionKeyComponent.cs @@ -1,78 +1,78 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class MaxString - { - public static readonly MaxString Value = new MaxString(); - - private MaxString() - { - } - } - - internal sealed class MaxStringPartitionKeyComponent : IPartitionKeyComponent - { - public static readonly MaxStringPartitionKeyComponent Value = new MaxStringPartitionKeyComponent(); - - private MaxStringPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - MaxStringPartitionKeyComponent otherString = other as MaxStringPartitionKeyComponent; - if (otherString == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.MaxString; - } - - public override int GetHashCode() - { - return 0; - } - public IPartitionKeyComponent Truncate() - { - throw new InvalidOperationException(); - } - - public void WriteForHashing(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void JsonEncode(JsonWriter writer) - { - PartitionKeyInternalJsonConverter.JsonEncode(this, writer); - } - - public object ToObject() - { - return MaxString.Value; - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.MaxString); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class MaxString + { + public static readonly MaxString Value = new MaxString(); + + private MaxString() + { + } + } + + internal sealed class MaxStringPartitionKeyComponent : IPartitionKeyComponent + { + public static readonly MaxStringPartitionKeyComponent Value = new MaxStringPartitionKeyComponent(); + + private MaxStringPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + MaxStringPartitionKeyComponent otherString = other as MaxStringPartitionKeyComponent; + if (otherString == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.MaxString; + } + + public override int GetHashCode() + { + return 0; + } + public IPartitionKeyComponent Truncate() + { + throw new InvalidOperationException(); + } + + public void WriteForHashing(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void JsonEncode(JsonWriter writer) + { + PartitionKeyInternalJsonConverter.JsonEncode(this, writer); + } + + public object ToObject() + { + return MaxString.Value; + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.MaxString); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MediaIdHelper.cs b/Microsoft.Azure.Cosmos/src/direct/MediaIdHelper.cs index 306833c104..81220dd729 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MediaIdHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MediaIdHelper.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Helper class to generate and parse media id (only used in frontend) - /// - internal sealed class MediaIdHelper - { - public static string NewMediaId(string attachmentId, byte storageIndex) - { - if (storageIndex == 0) - { - return attachmentId; - } - - ResourceId attachmentResourceId = ResourceId.Parse(attachmentId); - byte[] mediaId = new byte[ResourceId.Length + 1]; - attachmentResourceId.Value.CopyTo(mediaId, 0); - mediaId[mediaId.Length - 1] = storageIndex; - return ResourceId.ToBase64String(mediaId); - } - - public static bool TryParseMediaId(string mediaId, out string attachmentId, out byte storageIndex) - { - storageIndex = 0; - attachmentId = string.Empty; - - if (ResourceId.TryDecodeFromBase64String(mediaId, out byte[] mediaIdBytes) == false) - { - return false; - } - - if (mediaIdBytes.Length != ResourceId.Length && mediaIdBytes.Length != (ResourceId.Length + 1)) - { - return false; - } - - if (mediaIdBytes.Length == ResourceId.Length) - { - storageIndex = 0; - attachmentId = mediaId; - return true; - } - - storageIndex = mediaIdBytes[mediaIdBytes.Length - 1]; - attachmentId = ResourceId.ToBase64String(mediaIdBytes, 0, ResourceId.Length); - return true; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Helper class to generate and parse media id (only used in frontend) + /// + internal sealed class MediaIdHelper + { + public static string NewMediaId(string attachmentId, byte storageIndex) + { + if (storageIndex == 0) + { + return attachmentId; + } + + ResourceId attachmentResourceId = ResourceId.Parse(attachmentId); + byte[] mediaId = new byte[ResourceId.Length + 1]; + attachmentResourceId.Value.CopyTo(mediaId, 0); + mediaId[mediaId.Length - 1] = storageIndex; + return ResourceId.ToBase64String(mediaId); + } + + public static bool TryParseMediaId(string mediaId, out string attachmentId, out byte storageIndex) + { + storageIndex = 0; + attachmentId = string.Empty; + + if (ResourceId.TryDecodeFromBase64String(mediaId, out byte[] mediaIdBytes) == false) + { + return false; + } + + if (mediaIdBytes.Length != ResourceId.Length && mediaIdBytes.Length != (ResourceId.Length + 1)) + { + return false; + } + + if (mediaIdBytes.Length == ResourceId.Length) + { + storageIndex = 0; + attachmentId = mediaId; + return true; + } + + storageIndex = mediaIdBytes[mediaIdBytes.Length - 1]; + attachmentId = ResourceId.ToBase64String(mediaIdBytes, 0, ResourceId.Length); + return true; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MemoryStreamPool.cs b/Microsoft.Azure.Cosmos/src/direct/MemoryStreamPool.cs index e6a5df17ef..bc41d8d0b6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MemoryStreamPool.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MemoryStreamPool.cs @@ -1,13 +1,13 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.IO; - - internal interface MemoryStreamPool - { - public bool TryGetMemoryStream(int capacity, out MemoryStream memoryStream); - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.IO; + + internal interface MemoryStreamPool + { + public bool TryGetMemoryStream(int capacity, out MemoryStream memoryStream); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MethodNotAllowedException.cs b/Microsoft.Azure.Cosmos/src/direct/MethodNotAllowedException.cs index 0e9f944737..2af424048b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MethodNotAllowedException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MethodNotAllowedException.cs @@ -1,70 +1,70 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class MethodNotAllowedException : DocumentClientException - { - public MethodNotAllowedException() - : this(RMResources.MethodNotAllowed) - { - - } - - public MethodNotAllowedException(string message) - : this(message, (Exception)null, null) - { - - } - - public MethodNotAllowedException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public MethodNotAllowedException(Exception innerException) - : this(RMResources.MethodNotAllowed, innerException) - { - - } - - public MethodNotAllowedException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.MethodNotAllowed, requestUri) - { - SetDescription(); - } - - public MethodNotAllowedException(string message, Exception innerException) - : base(message, innerException, HttpStatusCode.MethodNotAllowed) - { - SetDescription(); - } - - public MethodNotAllowedException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.MethodNotAllowed, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private MethodNotAllowedException(SerializationInfo info, StreamingContext context) : - base(info, context, HttpStatusCode.MethodNotAllowed) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.MethodNotAllowed; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class MethodNotAllowedException : DocumentClientException + { + public MethodNotAllowedException() + : this(RMResources.MethodNotAllowed) + { + + } + + public MethodNotAllowedException(string message) + : this(message, (Exception)null, null) + { + + } + + public MethodNotAllowedException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public MethodNotAllowedException(Exception innerException) + : this(RMResources.MethodNotAllowed, innerException) + { + + } + + public MethodNotAllowedException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.MethodNotAllowed, requestUri) + { + SetDescription(); + } + + public MethodNotAllowedException(string message, Exception innerException) + : base(message, innerException, HttpStatusCode.MethodNotAllowed) + { + SetDescription(); + } + + public MethodNotAllowedException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, HttpStatusCode.MethodNotAllowed, requestUri) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private MethodNotAllowedException(SerializationInfo info, StreamingContext context) : + base(info, context, HttpStatusCode.MethodNotAllowed) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.MethodNotAllowed; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MigrateCollectionDirective.cs b/Microsoft.Azure.Cosmos/src/direct/MigrateCollectionDirective.cs index f7de278dbe..604fc3f055 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MigrateCollectionDirective.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MigrateCollectionDirective.cs @@ -1,21 +1,21 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies whether or not the resource is to be indexed. - /// - internal enum MigrateCollectionDirective - { - /// - /// Move to SSD - /// - Thaw, - - /// - /// Move to HDD. - /// - Freeze - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies whether or not the resource is to be indexed. + /// + internal enum MigrateCollectionDirective + { + /// + /// Move to SSD + /// + Thaw, + + /// + /// Move to HDD. + /// + Freeze + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MinNumberPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/MinNumberPartitionKeyComponent.cs index 8dcb3c9c1a..f661a356fd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MinNumberPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MinNumberPartitionKeyComponent.cs @@ -1,78 +1,78 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class MinNumber - { - public static readonly MinNumber Value = new MinNumber(); - - private MinNumber() - { - } - } - - internal sealed class MinNumberPartitionKeyComponent : IPartitionKeyComponent - { - public static readonly MinNumberPartitionKeyComponent Value = new MinNumberPartitionKeyComponent(); - - private MinNumberPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - MinNumberPartitionKeyComponent otherNumber = other as MinNumberPartitionKeyComponent; - if (otherNumber == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.MinNumber; - } - - public override int GetHashCode() - { - return 0; - } - public IPartitionKeyComponent Truncate() - { - throw new InvalidOperationException(); - } - - public void WriteForHashing(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void JsonEncode(JsonWriter writer) - { - PartitionKeyInternalJsonConverter.JsonEncode(this, writer); - } - - public object ToObject() - { - return MinNumber.Value; - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.MinNumber); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class MinNumber + { + public static readonly MinNumber Value = new MinNumber(); + + private MinNumber() + { + } + } + + internal sealed class MinNumberPartitionKeyComponent : IPartitionKeyComponent + { + public static readonly MinNumberPartitionKeyComponent Value = new MinNumberPartitionKeyComponent(); + + private MinNumberPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + MinNumberPartitionKeyComponent otherNumber = other as MinNumberPartitionKeyComponent; + if (otherNumber == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.MinNumber; + } + + public override int GetHashCode() + { + return 0; + } + public IPartitionKeyComponent Truncate() + { + throw new InvalidOperationException(); + } + + public void WriteForHashing(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void JsonEncode(JsonWriter writer) + { + PartitionKeyInternalJsonConverter.JsonEncode(this, writer); + } + + public object ToObject() + { + return MinNumber.Value; + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.MinNumber); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MinStringPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/MinStringPartitionKeyComponent.cs index 9f6bbd40ac..9775b31124 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MinStringPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MinStringPartitionKeyComponent.cs @@ -1,79 +1,79 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class MinString - { - public static readonly MinString Value = new MinString(); - - private MinString() - { - } - } - - internal sealed class MinStringPartitionKeyComponent : IPartitionKeyComponent - { - public static readonly MinStringPartitionKeyComponent Value = new MinStringPartitionKeyComponent(); - - private MinStringPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - MinStringPartitionKeyComponent otherString = other as MinStringPartitionKeyComponent; - if (otherString == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.MinString; - } - - public override int GetHashCode() - { - return 0; - } - - public IPartitionKeyComponent Truncate() - { - throw new InvalidOperationException(); - } - - public void WriteForHashing(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - throw new InvalidOperationException(); - } - - public void JsonEncode(JsonWriter writer) - { - PartitionKeyInternalJsonConverter.JsonEncode(this, writer); - } - - public object ToObject() - { - return MinString.Value; - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.MinString); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class MinString + { + public static readonly MinString Value = new MinString(); + + private MinString() + { + } + } + + internal sealed class MinStringPartitionKeyComponent : IPartitionKeyComponent + { + public static readonly MinStringPartitionKeyComponent Value = new MinStringPartitionKeyComponent(); + + private MinStringPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + MinStringPartitionKeyComponent otherString = other as MinStringPartitionKeyComponent; + if (otherString == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.MinString; + } + + public override int GetHashCode() + { + return 0; + } + + public IPartitionKeyComponent Truncate() + { + throw new InvalidOperationException(); + } + + public void WriteForHashing(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + throw new InvalidOperationException(); + } + + public void JsonEncode(JsonWriter writer) + { + PartitionKeyInternalJsonConverter.JsonEncode(this, writer); + } + + public object ToObject() + { + return MinString.Value; + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.MinString); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/MurmurHash.cs b/Microsoft.Azure.Cosmos/src/direct/MurmurHash.cs index e76406705b..8be8f61308 100644 --- a/Microsoft.Azure.Cosmos/src/direct/MurmurHash.cs +++ b/Microsoft.Azure.Cosmos/src/direct/MurmurHash.cs @@ -1,284 +1,284 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -[module: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability Rules", "SA1135", Justification = "Dual Compilation")] - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Diagnostics; - using Documents; - -#pragma warning disable SA1649 // File name should match first type name - internal static class MurmurHash3 -#pragma warning restore SA1649 // File name should match first type name - { - public static uint Hash32(byte[] bytes, long length, uint seed = 0) - { - // MurmurHash3 32bit implementation: - // https://en.wikipedia.org/wiki/MurmurHash - uint c1 = 0xcc9e2d51; - uint c2 = 0x1b873593; - - uint h1 = seed; - - for (int i = 0; i < length - 3; i += 4) - { - uint k1 = BitConverter.ToUInt32(bytes, i); - - k1 *= c1; - k1 = RotateLeft32(k1, 15); - k1 *= c2; - - h1 ^= k1; - h1 = RotateLeft32(h1, 13); - h1 = (h1 * 5) + 0xe6546b64; - } - - // tail - uint k = 0; - - switch (length & 3) - { - case 3: - k ^= (uint)bytes[length - 1] << 16; - k ^= (uint)bytes[length - 2] << 8; - k ^= (uint)bytes[length - 3]; - break; - - case 2: - k ^= (uint)bytes[length - 1] << 8; - k ^= (uint)bytes[length - 2]; - break; - - case 1: - k ^= (uint)bytes[length - 1]; - break; - } - - k *= c1; - k = RotateLeft32(k, 15); - k *= c2; - h1 ^= k; - - // finalization - h1 ^= (uint)length; - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - return h1; - } - - public static ulong Hash64(byte[] bytes, int length, ulong seed = 0) - { - // MurmurHash2 64-bit implementation: - // https://en.wikipedia.org/wiki/MurmurHash - int numBlocks = length / 8; - const ulong c1 = 0x87c37b91114253d5; - const ulong c2 = 0x4cf5ad432745937f; - - ulong h1 = seed; - - // body - int position; - for (position = 0; position < length - 7; position += 8) - { - ulong k1 = BitConverter.ToUInt64(bytes, position); - - // k1, h1 - k1 *= c1; - k1 = MurmurHash3.RotateLeft64(k1, 31); - k1 *= c2; - - h1 ^= k1; - h1 = MurmurHash3.RotateLeft64(h1, 27); - h1 = (h1 * 5) + 0x52dce729; - } - - // tail - { - ulong k1 = 0; - - switch (length & 7) - { - case 7: - k1 ^= ((ulong)bytes[position + 6]) << 48; - break; - case 6: - k1 ^= ((ulong)bytes[position + 5]) << 40; - break; - case 5: - k1 ^= ((ulong)bytes[position + 4]) << 32; - break; - case 4: - k1 ^= ((ulong)bytes[position + 3]) << 24; - break; - case 3: - k1 ^= ((ulong)bytes[position + 2]) << 16; - break; - case 2: - k1 ^= ((ulong)bytes[position + 1]) << 8; - break; - case 1: - k1 ^= ((ulong)bytes[position + 0]) << 0; - break; - default: - break; - } - - k1 *= c1; - k1 = MurmurHash3.RotateLeft64(k1, 31); - k1 *= c2; - h1 ^= k1; - } - - // finalization - h1 ^= (ulong)length; - - h1 ^= h1 >> 33; - h1 *= 0xff51afd7ed558ccd; - h1 ^= h1 >> 33; - h1 *= 0xc4ceb9fe1a85ec53; - h1 ^= h1 >> 33; - - return h1; - } - - public static UInt128 Hash128(byte[] bytes, int length, UInt128 seed) - { - const ulong c1 = 0x87c37b91114253d5; - const ulong c2 = 0x4cf5ad432745937f; - - ulong h1 = seed.GetLow(); - ulong h2 = seed.GetHigh(); - - // body - int position; - for (position = 0; position < length - 15; position += 16) - { - ulong k1 = BitConverter.ToUInt64(bytes, position); - ulong k2 = BitConverter.ToUInt64(bytes, position + 8); - - // k1, h1 - k1 *= c1; - k1 = RotateLeft64(k1, 31); - k1 *= c2; - - h1 ^= k1; - h1 = RotateLeft64(h1, 27); - h1 += h2; - h1 = (h1 * 5) + 0x52dce729; - - // k2, h2 - k2 *= c2; - k2 = RotateLeft64(k2, 33); - k2 *= c1; - - h2 ^= k2; - h2 = RotateLeft64(h2, 31); - h2 += h1; - h2 = (h2 * 5) + 0x38495ab5; - } - - { - // tail - ulong k1 = 0; - ulong k2 = 0; - - int n = length & 15; -#pragma warning disable SA1503 // Braces should not be omitted - if (n >= 15) k2 ^= ((ulong)bytes[position + 14]) << 48; - if (n >= 14) k2 ^= ((ulong)bytes[position + 13]) << 40; - if (n >= 13) k2 ^= ((ulong)bytes[position + 12]) << 32; - if (n >= 12) k2 ^= ((ulong)bytes[position + 11]) << 24; - if (n >= 11) k2 ^= ((ulong)bytes[position + 10]) << 16; - if (n >= 10) k2 ^= ((ulong)bytes[position + 09]) << 8; - if (n >= 9) k2 ^= ((ulong)bytes[position + 08]) << 0; -#pragma warning restore SA1503 // Braces should not be omitted - - k2 *= c2; - k2 = RotateLeft64(k2, 33); - k2 *= c1; - h2 ^= k2; - -#pragma warning disable SA1503 // Braces should not be omitted - if (n >= 8) k1 ^= ((ulong)bytes[position + 7]) << 56; - if (n >= 7) k1 ^= ((ulong)bytes[position + 6]) << 48; - if (n >= 6) k1 ^= ((ulong)bytes[position + 5]) << 40; - if (n >= 5) k1 ^= ((ulong)bytes[position + 4]) << 32; - if (n >= 4) k1 ^= ((ulong)bytes[position + 3]) << 24; - if (n >= 3) k1 ^= ((ulong)bytes[position + 2]) << 16; - if (n >= 2) k1 ^= ((ulong)bytes[position + 1]) << 8; - if (n >= 1) k1 ^= ((ulong)bytes[position + 0]) << 0; -#pragma warning restore SA1503 // Braces should not be omitted - - k1 *= c1; - k1 = RotateLeft64(k1, 31); - k1 *= c2; - h1 ^= k1; - } - - // finalization - h1 ^= (ulong)length; - h2 ^= (ulong)length; - - h1 += h2; - h2 += h1; - - // h1 - h1 ^= h1 >> 33; - h1 *= 0xff51afd7ed558ccd; - h1 ^= h1 >> 33; - h1 *= 0xc4ceb9fe1a85ec53; - h1 ^= h1 >> 33; - - // h2 - h2 ^= h2 >> 33; - h2 *= 0xff51afd7ed558ccd; - h2 ^= h2 >> 33; - h2 *= 0xc4ceb9fe1a85ec53; - h2 ^= h2 >> 33; - - h1 += h2; - h2 += h1; - - if (!BitConverter.IsLittleEndian) - { - h1 = MurmurHash3.Reverse(h1); - h2 = MurmurHash3.Reverse(h2); - } - - return UInt128.Create(h1, h2); - } - - public static ulong Reverse(ulong value) - { - ulong b1 = (value >> 0) & 0xff; - ulong b2 = (value >> 8) & 0xff; - ulong b3 = (value >> 16) & 0xff; - ulong b4 = (value >> 24) & 0xff; - ulong b5 = (value >> 32) & 0xff; - ulong b6 = (value >> 40) & 0xff; - ulong b7 = (value >> 48) & 0xff; - ulong b8 = (value >> 56) & 0xff; - - return b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8 << 0; - } - - private static uint RotateLeft32(uint n, int numBits) - { - Debug.Assert(numBits < 32, "numBits < 32"); - return (n << numBits) | (n >> (32 - numBits)); - } - - private static ulong RotateLeft64(ulong n, int numBits) - { - Debug.Assert(numBits < 64, "numBits < 64"); - return (n << numBits) | (n >> (64 - numBits)); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +[module: System.Diagnostics.CodeAnalysis.SuppressMessage("Readability Rules", "SA1135", Justification = "Dual Compilation")] + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Diagnostics; + using Documents; + +#pragma warning disable SA1649 // File name should match first type name + internal static class MurmurHash3 +#pragma warning restore SA1649 // File name should match first type name + { + public static uint Hash32(byte[] bytes, long length, uint seed = 0) + { + // MurmurHash3 32bit implementation: + // https://en.wikipedia.org/wiki/MurmurHash + uint c1 = 0xcc9e2d51; + uint c2 = 0x1b873593; + + uint h1 = seed; + + for (int i = 0; i < length - 3; i += 4) + { + uint k1 = BitConverter.ToUInt32(bytes, i); + + k1 *= c1; + k1 = RotateLeft32(k1, 15); + k1 *= c2; + + h1 ^= k1; + h1 = RotateLeft32(h1, 13); + h1 = (h1 * 5) + 0xe6546b64; + } + + // tail + uint k = 0; + + switch (length & 3) + { + case 3: + k ^= (uint)bytes[length - 1] << 16; + k ^= (uint)bytes[length - 2] << 8; + k ^= (uint)bytes[length - 3]; + break; + + case 2: + k ^= (uint)bytes[length - 1] << 8; + k ^= (uint)bytes[length - 2]; + break; + + case 1: + k ^= (uint)bytes[length - 1]; + break; + } + + k *= c1; + k = RotateLeft32(k, 15); + k *= c2; + h1 ^= k; + + // finalization + h1 ^= (uint)length; + h1 ^= h1 >> 16; + h1 *= 0x85ebca6b; + h1 ^= h1 >> 13; + h1 *= 0xc2b2ae35; + h1 ^= h1 >> 16; + + return h1; + } + + public static ulong Hash64(byte[] bytes, int length, ulong seed = 0) + { + // MurmurHash2 64-bit implementation: + // https://en.wikipedia.org/wiki/MurmurHash + int numBlocks = length / 8; + const ulong c1 = 0x87c37b91114253d5; + const ulong c2 = 0x4cf5ad432745937f; + + ulong h1 = seed; + + // body + int position; + for (position = 0; position < length - 7; position += 8) + { + ulong k1 = BitConverter.ToUInt64(bytes, position); + + // k1, h1 + k1 *= c1; + k1 = MurmurHash3.RotateLeft64(k1, 31); + k1 *= c2; + + h1 ^= k1; + h1 = MurmurHash3.RotateLeft64(h1, 27); + h1 = (h1 * 5) + 0x52dce729; + } + + // tail + { + ulong k1 = 0; + + switch (length & 7) + { + case 7: + k1 ^= ((ulong)bytes[position + 6]) << 48; + break; + case 6: + k1 ^= ((ulong)bytes[position + 5]) << 40; + break; + case 5: + k1 ^= ((ulong)bytes[position + 4]) << 32; + break; + case 4: + k1 ^= ((ulong)bytes[position + 3]) << 24; + break; + case 3: + k1 ^= ((ulong)bytes[position + 2]) << 16; + break; + case 2: + k1 ^= ((ulong)bytes[position + 1]) << 8; + break; + case 1: + k1 ^= ((ulong)bytes[position + 0]) << 0; + break; + default: + break; + } + + k1 *= c1; + k1 = MurmurHash3.RotateLeft64(k1, 31); + k1 *= c2; + h1 ^= k1; + } + + // finalization + h1 ^= (ulong)length; + + h1 ^= h1 >> 33; + h1 *= 0xff51afd7ed558ccd; + h1 ^= h1 >> 33; + h1 *= 0xc4ceb9fe1a85ec53; + h1 ^= h1 >> 33; + + return h1; + } + + public static UInt128 Hash128(byte[] bytes, int length, UInt128 seed) + { + const ulong c1 = 0x87c37b91114253d5; + const ulong c2 = 0x4cf5ad432745937f; + + ulong h1 = seed.GetLow(); + ulong h2 = seed.GetHigh(); + + // body + int position; + for (position = 0; position < length - 15; position += 16) + { + ulong k1 = BitConverter.ToUInt64(bytes, position); + ulong k2 = BitConverter.ToUInt64(bytes, position + 8); + + // k1, h1 + k1 *= c1; + k1 = RotateLeft64(k1, 31); + k1 *= c2; + + h1 ^= k1; + h1 = RotateLeft64(h1, 27); + h1 += h2; + h1 = (h1 * 5) + 0x52dce729; + + // k2, h2 + k2 *= c2; + k2 = RotateLeft64(k2, 33); + k2 *= c1; + + h2 ^= k2; + h2 = RotateLeft64(h2, 31); + h2 += h1; + h2 = (h2 * 5) + 0x38495ab5; + } + + { + // tail + ulong k1 = 0; + ulong k2 = 0; + + int n = length & 15; +#pragma warning disable SA1503 // Braces should not be omitted + if (n >= 15) k2 ^= ((ulong)bytes[position + 14]) << 48; + if (n >= 14) k2 ^= ((ulong)bytes[position + 13]) << 40; + if (n >= 13) k2 ^= ((ulong)bytes[position + 12]) << 32; + if (n >= 12) k2 ^= ((ulong)bytes[position + 11]) << 24; + if (n >= 11) k2 ^= ((ulong)bytes[position + 10]) << 16; + if (n >= 10) k2 ^= ((ulong)bytes[position + 09]) << 8; + if (n >= 9) k2 ^= ((ulong)bytes[position + 08]) << 0; +#pragma warning restore SA1503 // Braces should not be omitted + + k2 *= c2; + k2 = RotateLeft64(k2, 33); + k2 *= c1; + h2 ^= k2; + +#pragma warning disable SA1503 // Braces should not be omitted + if (n >= 8) k1 ^= ((ulong)bytes[position + 7]) << 56; + if (n >= 7) k1 ^= ((ulong)bytes[position + 6]) << 48; + if (n >= 6) k1 ^= ((ulong)bytes[position + 5]) << 40; + if (n >= 5) k1 ^= ((ulong)bytes[position + 4]) << 32; + if (n >= 4) k1 ^= ((ulong)bytes[position + 3]) << 24; + if (n >= 3) k1 ^= ((ulong)bytes[position + 2]) << 16; + if (n >= 2) k1 ^= ((ulong)bytes[position + 1]) << 8; + if (n >= 1) k1 ^= ((ulong)bytes[position + 0]) << 0; +#pragma warning restore SA1503 // Braces should not be omitted + + k1 *= c1; + k1 = RotateLeft64(k1, 31); + k1 *= c2; + h1 ^= k1; + } + + // finalization + h1 ^= (ulong)length; + h2 ^= (ulong)length; + + h1 += h2; + h2 += h1; + + // h1 + h1 ^= h1 >> 33; + h1 *= 0xff51afd7ed558ccd; + h1 ^= h1 >> 33; + h1 *= 0xc4ceb9fe1a85ec53; + h1 ^= h1 >> 33; + + // h2 + h2 ^= h2 >> 33; + h2 *= 0xff51afd7ed558ccd; + h2 ^= h2 >> 33; + h2 *= 0xc4ceb9fe1a85ec53; + h2 ^= h2 >> 33; + + h1 += h2; + h2 += h1; + + if (!BitConverter.IsLittleEndian) + { + h1 = MurmurHash3.Reverse(h1); + h2 = MurmurHash3.Reverse(h2); + } + + return UInt128.Create(h1, h2); + } + + public static ulong Reverse(ulong value) + { + ulong b1 = (value >> 0) & 0xff; + ulong b2 = (value >> 8) & 0xff; + ulong b3 = (value >> 16) & 0xff; + ulong b4 = (value >> 24) & 0xff; + ulong b5 = (value >> 32) & 0xff; + ulong b6 = (value >> 40) & 0xff; + ulong b7 = (value >> 48) & 0xff; + ulong b8 = (value >> 56) & 0xff; + + return b1 << 56 | b2 << 48 | b3 << 40 | b4 << 32 | b5 << 24 | b6 << 16 | b7 << 8 | b8 << 0; + } + + private static uint RotateLeft32(uint n, int numBits) + { + Debug.Assert(numBits < 32, "numBits < 32"); + return (n << numBits) | (n >> (32 - numBits)); + } + + private static ulong RotateLeft64(ulong n, int numBits) + { + Debug.Assert(numBits < 64, "numBits < 64"); + return (n << numBits) | (n >> (64 - numBits)); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/NameValueCollectionWrapper.cs b/Microsoft.Azure.Cosmos/src/direct/NameValueCollectionWrapper.cs index 34f77a2bb2..73dcf6b526 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NameValueCollectionWrapper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NameValueCollectionWrapper.cs @@ -1,238 +1,238 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Collections -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Specialized; - - /// - /// NameValueCollectionWrapper provides an implementation of INameValueCollection and maintains the behavior of NameValueCollection type. - /// All operations are delegated to an instance of NameValueCollection internally. - /// - internal class NameValueCollectionWrapper : INameValueCollection - { - NameValueCollection collection; - - /// - /// - /// - public NameValueCollectionWrapper() - { - this.collection = new NameValueCollection(); - } - - public NameValueCollectionWrapper(int capacity) - { - this.collection = new NameValueCollection(capacity); - } - - /// - /// - /// - /// - public NameValueCollectionWrapper(StringComparer comparer) - { - this.collection = new NameValueCollection(comparer); - } - - /// - /// - /// - /// - public NameValueCollectionWrapper(NameValueCollectionWrapper values) - { - this.collection = new NameValueCollection(values.collection); - } - - /// - /// - /// - /// - public NameValueCollectionWrapper(NameValueCollection collection) - { - this.collection = new NameValueCollection(collection); - } - - /// - /// - /// - /// - public NameValueCollectionWrapper(INameValueCollection collection) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - this.collection = new NameValueCollection(); - foreach (string key in collection) - { - this.collection.Add(key, collection[key]); - } - } - - /// - /// - /// - /// - /// - public static NameValueCollectionWrapper Create(NameValueCollection collection) - { - NameValueCollectionWrapper wrapper = new NameValueCollectionWrapper(); - wrapper.collection = collection; - return wrapper; - } - - /// - /// - /// - /// - /// - public string this[string key] - { - get - { - return this.collection[key]; - } - - set - { - this.collection[key] = value; - } - } - - public void Add(INameValueCollection c) - { - if (c == null) - { - throw new ArgumentNullException(nameof(c)); - } - - NameValueCollectionWrapper nvc = c as NameValueCollectionWrapper; - if (nvc != null) - { - this.collection.Add(nvc.collection); - } - else - { - foreach (string key in c) - { - foreach (string value in c.GetValues(key)) - { - this.collection.Add(key, value); - } - } - } - } - - /// - /// - /// - /// - /// - public void Add(string key, string value) - { - this.collection.Add(key, value); - } - - /// - /// - /// - /// - public INameValueCollection Clone() - { - return new NameValueCollectionWrapper(this); - } - - /// - /// - /// - /// - /// - public string Get(string key) - { - return this.collection.Get(key); - } - - /// - /// - /// - /// - public IEnumerator GetEnumerator() - { - return this.collection.GetEnumerator(); - } - - /// - /// - /// - /// - /// - public string[] GetValues(string key) - { - return this.collection.GetValues(key); - } - - /// - /// - /// - /// - public void Remove(string key) - { - this.collection.Remove(key); - } - - /// - /// - /// - public void Clear() - { - this.collection.Clear(); - } - - public int Count() - { - return this.collection.Count; - } - - /// - /// - /// - /// - /// - public void Set(string key, string value) - { - this.collection.Set(key, value); - } - - /// - /// - /// - /// - public string[] AllKeys() - { - return this.collection.AllKeys; - } - - public IEnumerable Keys() - { - foreach (string key in this.collection.Keys) - { - yield return key; - } - } - - /// - /// - /// - /// - public NameValueCollection ToNameValueCollection() - { - return this.collection; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Collections +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + + /// + /// NameValueCollectionWrapper provides an implementation of INameValueCollection and maintains the behavior of NameValueCollection type. + /// All operations are delegated to an instance of NameValueCollection internally. + /// + internal class NameValueCollectionWrapper : INameValueCollection + { + NameValueCollection collection; + + /// + /// + /// + public NameValueCollectionWrapper() + { + this.collection = new NameValueCollection(); + } + + public NameValueCollectionWrapper(int capacity) + { + this.collection = new NameValueCollection(capacity); + } + + /// + /// + /// + /// + public NameValueCollectionWrapper(StringComparer comparer) + { + this.collection = new NameValueCollection(comparer); + } + + /// + /// + /// + /// + public NameValueCollectionWrapper(NameValueCollectionWrapper values) + { + this.collection = new NameValueCollection(values.collection); + } + + /// + /// + /// + /// + public NameValueCollectionWrapper(NameValueCollection collection) + { + this.collection = new NameValueCollection(collection); + } + + /// + /// + /// + /// + public NameValueCollectionWrapper(INameValueCollection collection) + { + if (collection == null) + { + throw new ArgumentNullException(nameof(collection)); + } + + this.collection = new NameValueCollection(); + foreach (string key in collection) + { + this.collection.Add(key, collection[key]); + } + } + + /// + /// + /// + /// + /// + public static NameValueCollectionWrapper Create(NameValueCollection collection) + { + NameValueCollectionWrapper wrapper = new NameValueCollectionWrapper(); + wrapper.collection = collection; + return wrapper; + } + + /// + /// + /// + /// + /// + public string this[string key] + { + get + { + return this.collection[key]; + } + + set + { + this.collection[key] = value; + } + } + + public void Add(INameValueCollection c) + { + if (c == null) + { + throw new ArgumentNullException(nameof(c)); + } + + NameValueCollectionWrapper nvc = c as NameValueCollectionWrapper; + if (nvc != null) + { + this.collection.Add(nvc.collection); + } + else + { + foreach (string key in c) + { + foreach (string value in c.GetValues(key)) + { + this.collection.Add(key, value); + } + } + } + } + + /// + /// + /// + /// + /// + public void Add(string key, string value) + { + this.collection.Add(key, value); + } + + /// + /// + /// + /// + public INameValueCollection Clone() + { + return new NameValueCollectionWrapper(this); + } + + /// + /// + /// + /// + /// + public string Get(string key) + { + return this.collection.Get(key); + } + + /// + /// + /// + /// + public IEnumerator GetEnumerator() + { + return this.collection.GetEnumerator(); + } + + /// + /// + /// + /// + /// + public string[] GetValues(string key) + { + return this.collection.GetValues(key); + } + + /// + /// + /// + /// + public void Remove(string key) + { + this.collection.Remove(key); + } + + /// + /// + /// + public void Clear() + { + this.collection.Clear(); + } + + public int Count() + { + return this.collection.Count; + } + + /// + /// + /// + /// + /// + public void Set(string key, string value) + { + this.collection.Set(key, value); + } + + /// + /// + /// + /// + public string[] AllKeys() + { + return this.collection.AllKeys; + } + + public IEnumerable Keys() + { + foreach (string key in this.collection.Keys) + { + yield return key; + } + } + + /// + /// + /// + /// + public NameValueCollection ToNameValueCollection() + { + return this.collection; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Darwin.cs b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Darwin.cs index 4da4258563..023b262bd1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Darwin.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Darwin.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Runtime.InteropServices; - internal static partial class NativeMethods - { - public static class Darwin - { - private const int CTL_KERN = 1; - private const int KERN_OSRELEASE = 2; - - public unsafe static string GetKernelRelease() - { - const uint BUFFER_LENGTH = 32; - - var name = stackalloc int[2]; - name[0] = CTL_KERN; - name[1] = KERN_OSRELEASE; - - var buf = stackalloc byte[(int)BUFFER_LENGTH]; - var len = stackalloc uint[1]; - *len = BUFFER_LENGTH; - - try - { - // If the buffer isn't big enough, it seems sysctl still returns 0 and just sets len to the - // necessary buffer size. This appears to be contrary to the man page, but it's easy to detect - // by simply checking len against the buffer length. - if (sysctl(name, 2, buf, len, IntPtr.Zero, 0) == 0 && *len < BUFFER_LENGTH) - { - return Marshal.PtrToStringAnsi((IntPtr)buf, (int)*len); - } - } - catch (Exception ex) - { - throw new PlatformNotSupportedException("Error reading Darwin Kernel Version", ex); - } - throw new PlatformNotSupportedException("Unknown error reading Darwin Kernel Version"); - } - - [DllImport("libc")] - private unsafe static extern int sysctl( - int* name, - uint namelen, - byte* oldp, - uint* oldlenp, - IntPtr newp, - uint newlen); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Runtime.InteropServices; + internal static partial class NativeMethods + { + public static class Darwin + { + private const int CTL_KERN = 1; + private const int KERN_OSRELEASE = 2; + + public unsafe static string GetKernelRelease() + { + const uint BUFFER_LENGTH = 32; + + var name = stackalloc int[2]; + name[0] = CTL_KERN; + name[1] = KERN_OSRELEASE; + + var buf = stackalloc byte[(int)BUFFER_LENGTH]; + var len = stackalloc uint[1]; + *len = BUFFER_LENGTH; + + try + { + // If the buffer isn't big enough, it seems sysctl still returns 0 and just sets len to the + // necessary buffer size. This appears to be contrary to the man page, but it's easy to detect + // by simply checking len against the buffer length. + if (sysctl(name, 2, buf, len, IntPtr.Zero, 0) == 0 && *len < BUFFER_LENGTH) + { + return Marshal.PtrToStringAnsi((IntPtr)buf, (int)*len); + } + } + catch (Exception ex) + { + throw new PlatformNotSupportedException("Error reading Darwin Kernel Version", ex); + } + throw new PlatformNotSupportedException("Unknown error reading Darwin Kernel Version"); + } + + [DllImport("libc")] + private unsafe static extern int sysctl( + int* name, + uint namelen, + byte* oldp, + uint* oldlenp, + IntPtr newp, + uint newlen); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Unix.cs b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Unix.cs index 3d64fb419a..e8fcc899e4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Unix.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Unix.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Runtime.InteropServices; - internal static partial class NativeMethods - { - public static class Unix - { - public unsafe static string GetUname() - { - // Utsname shouldn't be larger than 2K - var buf = stackalloc byte[2048]; - - try - { - if (uname((IntPtr)buf) == 0) - { - return Marshal.PtrToStringAnsi((IntPtr)buf); - } - } - catch (Exception ex) - { - throw new PlatformNotSupportedException("Error reading Unix name", ex); - } - throw new PlatformNotSupportedException("Unknown error reading Unix name"); - } - - [DllImport("libc")] - private static extern int uname(IntPtr utsname); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Runtime.InteropServices; + internal static partial class NativeMethods + { + public static class Unix + { + public unsafe static string GetUname() + { + // Utsname shouldn't be larger than 2K + var buf = stackalloc byte[2048]; + + try + { + if (uname((IntPtr)buf) == 0) + { + return Marshal.PtrToStringAnsi((IntPtr)buf); + } + } + catch (Exception ex) + { + throw new PlatformNotSupportedException("Error reading Unix name", ex); + } + throw new PlatformNotSupportedException("Unknown error reading Unix name"); + } + + [DllImport("libc")] + private static extern int uname(IntPtr utsname); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Windows.cs b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Windows.cs index 269af1b89a..b729c36394 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Windows.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NativeMethods.Windows.cs @@ -1,43 +1,43 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Runtime.InteropServices; - internal static partial class NativeMethods - { - public static class Windows - { - [StructLayout(LayoutKind.Sequential)] - internal struct RTL_OSVERSIONINFOEX - { - internal uint dwOSVersionInfoSize; - internal uint dwMajorVersion; - internal uint dwMinorVersion; - internal uint dwBuildNumber; - internal uint dwPlatformId; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] - internal string szCSDVersion; - } - - // This call avoids the shimming Windows does to report old versions - [DllImport("ntdll")] - private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation); - - internal static string RtlGetVersion() - { - RTL_OSVERSIONINFOEX osvi = new RTL_OSVERSIONINFOEX(); - osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi); - if (RtlGetVersion(out osvi) == 0) - { - return $"{osvi.dwMajorVersion}.{osvi.dwMinorVersion}.{osvi.dwBuildNumber}"; - } - else - { - return null; - } - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Runtime.InteropServices; + internal static partial class NativeMethods + { + public static class Windows + { + [StructLayout(LayoutKind.Sequential)] + internal struct RTL_OSVERSIONINFOEX + { + internal uint dwOSVersionInfoSize; + internal uint dwMajorVersion; + internal uint dwMinorVersion; + internal uint dwBuildNumber; + internal uint dwPlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + internal string szCSDVersion; + } + + // This call avoids the shimming Windows does to report old versions + [DllImport("ntdll")] + private static extern int RtlGetVersion(out RTL_OSVERSIONINFOEX lpVersionInformation); + + internal static string RtlGetVersion() + { + RTL_OSVERSIONINFOEX osvi = new RTL_OSVERSIONINFOEX(); + osvi.dwOSVersionInfoSize = (uint)Marshal.SizeOf(osvi); + if (RtlGetVersion(out osvi) == 0) + { + return $"{osvi.dwMajorVersion}.{osvi.dwMinorVersion}.{osvi.dwBuildNumber}"; + } + else + { + return null; + } + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/NetUtil.cs b/Microsoft.Azure.Cosmos/src/direct/NetUtil.cs index 2e7e93af3b..290e10e767 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NetUtil.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NetUtil.cs @@ -1,153 +1,153 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.NetworkInformation; - using System.Net.Sockets; - using Microsoft.Azure.Cosmos.Core.Trace; -#if !(NETSTANDARD15 || NETSTANDARD16) - using System.Configuration; -#endif - - internal static class NetUtil - { - // IPv6 Service Tunnel destination prefix for PaasV1 is 2603:10e1:100:2/64 - private static readonly byte[] paasV1Prefix = new byte[] { 0x26, 0x03, 0x10, 0xe1, 0x01, 0x00, 0x00, 0x02 }; - - // IPv6 Service Tunnel destination prefix for PaasV2 is ace:cab:deca::/48 - private static readonly byte[] paasV2Prefix = new byte[] { 0x0a, 0xce, 0x0c, 0xab, 0xde, 0xca }; - - /// - /// Get a single non-loopback (i.e., not 127.0.0.0/8) - /// IP address of the local machine. - /// - /// - public static string GetNonLoopbackIpV4Address() - { - NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); - foreach (NetworkInterface adapter in adapters) - { - // We skip loopback, tunnel adapters etc ... - if (((adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet) || (adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)) && - (adapter.OperationalStatus == OperationalStatus.Up)) - { - IPInterfaceProperties properties = adapter.GetIPProperties(); - foreach (IPAddressInformation ipAddress in properties.UnicastAddresses) - { - if (ipAddress.IsDnsEligible && - (ipAddress.Address.AddressFamily == AddressFamily.InterNetwork)) - { - return ipAddress.Address.ToString(); - } - } - } - } - - // If we reach here, we couldn't find a usable IP address. - string message = "ERROR: Could not locate any usable IPv4 address"; - DefaultTrace.TraceCritical(message); - throw new ConfigurationErrorsException(message); - } - - /// - /// Get a single non-loopback (i.e., not 127.0.0.0/8) - /// IP address of the local machine. Similar to GetNonLoopbackIpV4Address but allows - /// non-dns eligible adapters - /// - /// - public static string GetLocalEmulatorIpV4Address() - { - string bestAddress = null; - - NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); - foreach (NetworkInterface adapter in adapters) - { - // We skip loopback, tunnel adapters etc ... - if ((adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet || adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) && - (adapter.OperationalStatus == OperationalStatus.Up)) - { - IPInterfaceProperties properties = adapter.GetIPProperties(); - foreach (IPAddressInformation ipAddress in properties.UnicastAddresses) - { - if (ipAddress.Address.AddressFamily == AddressFamily.InterNetwork) - { - if (ipAddress.IsDnsEligible) - { - return ipAddress.Address.ToString(); - } - if (bestAddress == null) - { - bestAddress = ipAddress.Address.ToString(); - } - } - } - } - } - - if (bestAddress != null) - { - return bestAddress; - } - - // If we reach here, we couldn't find a usable IP address. - string message = "ERROR: Could not locate any usable IPv4 address for local emulator"; - DefaultTrace.TraceCritical(message); - throw new ConfigurationErrorsException(message); - } - - public static bool GetIPv6ServiceTunnelAddress(bool isEmulated, out IPAddress ipv6LoopbackAddress) - { - if (isEmulated) - { - ipv6LoopbackAddress = IPAddress.IPv6Loopback; - return true; - } - - NetworkInterface[] niList = NetworkInterface.GetAllNetworkInterfaces(); - foreach (NetworkInterface ni in niList) - { - foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) - { - if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 && - NetUtil.IsServiceTunneledIPAddress(ip.Address)) - { - DefaultTrace.TraceInformation("Found VNET service tunnel destination: {0}", ip.Address.ToString()); - ipv6LoopbackAddress = ip.Address; - return true; - } - else - { - DefaultTrace.TraceInformation("{0} is skipped because it is not IPv6 or is not a service tunneled IP address.", ip.Address.ToString()); - } - } - } - - DefaultTrace.TraceInformation("Cannot find the IPv6 address of the Loopback NetworkInterface."); - ipv6LoopbackAddress = null; - return false; - } - - private static bool IsServiceTunneledIPAddress(IPAddress ipAddress) - { - byte[] ipAddressBytes = ipAddress.GetAddressBytes(); - - if (BitConverter.ToUInt64(ipAddressBytes, 0) == BitConverter.ToUInt64(paasV1Prefix, 0)) - { - return true; - } - - for (int i = 0; i < paasV2Prefix.Length; i++) - { - if (paasV2Prefix[i] != ipAddressBytes[i]) - { - return false; - } - } - - return true; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.NetworkInformation; + using System.Net.Sockets; + using Microsoft.Azure.Cosmos.Core.Trace; +#if !(NETSTANDARD15 || NETSTANDARD16) + using System.Configuration; +#endif + + internal static class NetUtil + { + // IPv6 Service Tunnel destination prefix for PaasV1 is 2603:10e1:100:2/64 + private static readonly byte[] paasV1Prefix = new byte[] { 0x26, 0x03, 0x10, 0xe1, 0x01, 0x00, 0x00, 0x02 }; + + // IPv6 Service Tunnel destination prefix for PaasV2 is ace:cab:deca::/48 + private static readonly byte[] paasV2Prefix = new byte[] { 0x0a, 0xce, 0x0c, 0xab, 0xde, 0xca }; + + /// + /// Get a single non-loopback (i.e., not 127.0.0.0/8) + /// IP address of the local machine. + /// + /// + public static string GetNonLoopbackIpV4Address() + { + NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface adapter in adapters) + { + // We skip loopback, tunnel adapters etc ... + if (((adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet) || (adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211)) && + (adapter.OperationalStatus == OperationalStatus.Up)) + { + IPInterfaceProperties properties = adapter.GetIPProperties(); + foreach (IPAddressInformation ipAddress in properties.UnicastAddresses) + { + if (ipAddress.IsDnsEligible && + (ipAddress.Address.AddressFamily == AddressFamily.InterNetwork)) + { + return ipAddress.Address.ToString(); + } + } + } + } + + // If we reach here, we couldn't find a usable IP address. + string message = "ERROR: Could not locate any usable IPv4 address"; + DefaultTrace.TraceCritical(message); + throw new ConfigurationErrorsException(message); + } + + /// + /// Get a single non-loopback (i.e., not 127.0.0.0/8) + /// IP address of the local machine. Similar to GetNonLoopbackIpV4Address but allows + /// non-dns eligible adapters + /// + /// + public static string GetLocalEmulatorIpV4Address() + { + string bestAddress = null; + + NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface adapter in adapters) + { + // We skip loopback, tunnel adapters etc ... + if ((adapter.NetworkInterfaceType == NetworkInterfaceType.Ethernet || adapter.NetworkInterfaceType == NetworkInterfaceType.Wireless80211) && + (adapter.OperationalStatus == OperationalStatus.Up)) + { + IPInterfaceProperties properties = adapter.GetIPProperties(); + foreach (IPAddressInformation ipAddress in properties.UnicastAddresses) + { + if (ipAddress.Address.AddressFamily == AddressFamily.InterNetwork) + { + if (ipAddress.IsDnsEligible) + { + return ipAddress.Address.ToString(); + } + if (bestAddress == null) + { + bestAddress = ipAddress.Address.ToString(); + } + } + } + } + } + + if (bestAddress != null) + { + return bestAddress; + } + + // If we reach here, we couldn't find a usable IP address. + string message = "ERROR: Could not locate any usable IPv4 address for local emulator"; + DefaultTrace.TraceCritical(message); + throw new ConfigurationErrorsException(message); + } + + public static bool GetIPv6ServiceTunnelAddress(bool isEmulated, out IPAddress ipv6LoopbackAddress) + { + if (isEmulated) + { + ipv6LoopbackAddress = IPAddress.IPv6Loopback; + return true; + } + + NetworkInterface[] niList = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface ni in niList) + { + foreach (UnicastIPAddressInformation ip in ni.GetIPProperties().UnicastAddresses) + { + if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 && + NetUtil.IsServiceTunneledIPAddress(ip.Address)) + { + DefaultTrace.TraceInformation("Found VNET service tunnel destination: {0}", ip.Address.ToString()); + ipv6LoopbackAddress = ip.Address; + return true; + } + else + { + DefaultTrace.TraceInformation("{0} is skipped because it is not IPv6 or is not a service tunneled IP address.", ip.Address.ToString()); + } + } + } + + DefaultTrace.TraceInformation("Cannot find the IPv6 address of the Loopback NetworkInterface."); + ipv6LoopbackAddress = null; + return false; + } + + private static bool IsServiceTunneledIPAddress(IPAddress ipAddress) + { + byte[] ipAddressBytes = ipAddress.GetAddressBytes(); + + if (BitConverter.ToUInt64(ipAddressBytes, 0) == BitConverter.ToUInt64(paasV1Prefix, 0)) + { + return true; + } + + for (int i = 0; i < paasV2Prefix.Length; i++) + { + if (paasV2Prefix[i] != ipAddressBytes[i]) + { + return false; + } + } + + return true; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs b/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs index c7b493cdee..ed032ae7e9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs @@ -1,81 +1,81 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class NotFoundException : DocumentClientException - { - public NotFoundException() - : this(RMResources.NotFound) - { - - } - - public NotFoundException(string message) - : this(message, (Exception)null, null) - { - - } - - public NotFoundException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public NotFoundException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public NotFoundException(Exception innerException, bool traceCallStack = true) - : this(RMResources.NotFound, innerException, null, traceCallStack: traceCallStack) - { - - } - - public NotFoundException(Exception innerException, SubStatusCodes subStatusCode, bool traceCallStack = true) - : this(RMResources.NotFound, innerException, headers: null, subStatusCode: subStatusCode, traceCallStack: traceCallStack) - { - } - - public NotFoundException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.NotFound, requestUri) - { - SetDescription(); - } - - public NotFoundException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null, bool traceCallStack = true) - : base(message, innerException, headers, HttpStatusCode.NotFound, requestUri, subStatusCode, traceCallStack) - { - SetDescription(); - } - - public NotFoundException(string message, Exception innerException, INameValueCollection headers, SubStatusCodes? subStatusCode) - : base(message, innerException, headers, HttpStatusCode.NotFound, subStatusCode) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private NotFoundException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.NotFound) - { - - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.NotFound; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class NotFoundException : DocumentClientException + { + public NotFoundException() + : this(RMResources.NotFound) + { + + } + + public NotFoundException(string message) + : this(message, (Exception)null, null) + { + + } + + public NotFoundException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public NotFoundException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public NotFoundException(Exception innerException, bool traceCallStack = true) + : this(RMResources.NotFound, innerException, null, traceCallStack: traceCallStack) + { + + } + + public NotFoundException(Exception innerException, SubStatusCodes subStatusCode, bool traceCallStack = true) + : this(RMResources.NotFound, innerException, headers: null, subStatusCode: subStatusCode, traceCallStack: traceCallStack) + { + } + + public NotFoundException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.NotFound, requestUri) + { + SetDescription(); + } + + public NotFoundException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null, bool traceCallStack = true) + : base(message, innerException, headers, HttpStatusCode.NotFound, requestUri, subStatusCode, traceCallStack) + { + SetDescription(); + } + + public NotFoundException(string message, Exception innerException, INameValueCollection headers, SubStatusCodes? subStatusCode) + : base(message, innerException, headers, HttpStatusCode.NotFound, subStatusCode) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private NotFoundException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.NotFound) + { + + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.NotFound; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/NullPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/NullPartitionKeyComponent.cs index 5f334c6895..833f32921c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NullPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NullPartitionKeyComponent.cs @@ -1,66 +1,66 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - - using Newtonsoft.Json; - - internal sealed class NullPartitionKeyComponent : IPartitionKeyComponent - { - public static readonly NullPartitionKeyComponent Value = new NullPartitionKeyComponent(); - - private NullPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - NullPartitionKeyComponent otherBool = other as NullPartitionKeyComponent; - if (otherBool == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.Null; - } - - public IPartitionKeyComponent Truncate() - { - return this; - } - - public void WriteForHashing(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Null); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Null); - } - - public void JsonEncode(JsonWriter writer) - { - writer.WriteValue((object)null); - } - - public object ToObject() - { - return null; - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.Null); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + + using Newtonsoft.Json; + + internal sealed class NullPartitionKeyComponent : IPartitionKeyComponent + { + public static readonly NullPartitionKeyComponent Value = new NullPartitionKeyComponent(); + + private NullPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + NullPartitionKeyComponent otherBool = other as NullPartitionKeyComponent; + if (otherBool == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.Null; + } + + public IPartitionKeyComponent Truncate() + { + return this; + } + + public void WriteForHashing(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Null); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Null); + } + + public void JsonEncode(JsonWriter writer) + { + writer.WriteValue((object)null); + } + + public object ToObject() + { + return null; + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.Null); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/NullSessionContainer.cs b/Microsoft.Azure.Cosmos/src/direct/NullSessionContainer.cs index e33ff29814..2ad4d225d9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NullSessionContainer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NullSessionContainer.cs @@ -1,38 +1,38 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Microsoft.Azure.Documents.Collections; - - internal class NullSessionContainer : ISessionContainer - { - public string ResolveGlobalSessionToken(DocumentServiceRequest entity) - { - return string.Empty; - } - - public ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest entity, string partitionKeyRangeId) - { - return null; - } - - public void ClearTokenByResourceId(string resourceId) - { - } - - public void ClearTokenByCollectionFullname(string collectionFullname) - { - } - - public void SetSessionToken(DocumentServiceRequest request, INameValueCollection header) - { - } - - public void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders) - { - } - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Microsoft.Azure.Documents.Collections; + + internal class NullSessionContainer : ISessionContainer + { + public string ResolveGlobalSessionToken(DocumentServiceRequest entity) + { + return string.Empty; + } + + public ISessionToken ResolvePartitionLocalSessionToken(DocumentServiceRequest entity, string partitionKeyRangeId) + { + return null; + } + + public void ClearTokenByResourceId(string resourceId) + { + } + + public void ClearTokenByCollectionFullname(string collectionFullname) + { + } + + public void SetSessionToken(DocumentServiceRequest request, INameValueCollection header) + { + } + + public void SetSessionToken(string collectionRid, string collectionFullname, INameValueCollection responseHeaders) + { + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/NumberPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/NumberPartitionKeyComponent.cs index c96f665c06..a28059512c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NumberPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NumberPartitionKeyComponent.cs @@ -1,161 +1,161 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class NumberPartitionKeyComponent : IPartitionKeyComponent - { - private readonly double value; - - public static readonly NumberPartitionKeyComponent Zero = new NumberPartitionKeyComponent(0); - - public NumberPartitionKeyComponent(double value) - { - this.value = value; - } - - public double Value - { - get - { - return this.value; - } - } - - public int CompareTo(IPartitionKeyComponent other) - { - NumberPartitionKeyComponent otherNumber = other as NumberPartitionKeyComponent; - if (otherNumber == null) - { - throw new ArgumentException("other"); - } - - return this.value.CompareTo(otherNumber.value); - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.Number; - } - - public override int GetHashCode() - { - return this.value.GetHashCode(); - } - - public void JsonEncode(JsonWriter writer) - { - writer.WriteValue(this.value); - } - - public object ToObject() - { - return this.value; - } - - public IPartitionKeyComponent Truncate() - { - return this; - } - - public void WriteForHashing(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Number); - writer.Write(this.value); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Number); - writer.Write(this.value); - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.Number); - - UInt64 payload = NumberPartitionKeyComponent.EncodeDoubleAsUInt64(this.value); - - // Encode first chunk with 8-bits of payload - binaryWriter.Write((byte)(payload >> (64 - 8))); - payload <<= 8; - - // Encode remaining chunks with 7 bits of payload followed by single "1" bit each. - byte byteToWrite = 0; - bool firstIteration = true; - do - { - if (!firstIteration) - { - binaryWriter.Write(byteToWrite); - } - else - { - firstIteration = false; - } - - byteToWrite = (byte)((payload >> (64 - 8)) | 0x01); - payload <<= 7; - } while (payload != 0); - - // Except for last chunk that ends with "0" bit. - binaryWriter.Write((byte)(byteToWrite & 0xFE)); - } - - /// - /// Constructs a NumberPartitionKeyComponent from byte string. This is only for testing/debugging. Please do not use in actual product code. - /// - public static IPartitionKeyComponent FromHexEncodedBinaryString(byte[] byteString, ref int byteStringOffset) - { - int offset = 64; - UInt64 payload = 0; - - // Decode first 8-bit chunk - offset -= 8; - payload |= (Convert.ToUInt64(byteString[byteStringOffset++])) << offset; - - // Decode remaining 7-bit chunks - while (true) - { - if (byteStringOffset >= byteString.Length) - { - throw new InvalidDataException("Incorrect byte string without termination"); - } - - byte currentByte = byteString[byteStringOffset++]; - - offset -= 7; - payload |= (Convert.ToUInt64(currentByte >> 1)) << offset; - - if ((currentByte & 0x01) == 0) - { - break; - } - } - - double dblValue = NumberPartitionKeyComponent.DecodeDoubleFromUInt64(payload); - - return new NumberPartitionKeyComponent(dblValue); - } - - // Helpers - private static UInt64 EncodeDoubleAsUInt64(double value) - { - UInt64 valueInUInt64 = (UInt64)BitConverter.DoubleToInt64Bits(value); - UInt64 mask = 0x8000000000000000; - return (valueInUInt64 < mask) ? valueInUInt64 ^ mask : (~valueInUInt64) + 1; - } - - private static double DecodeDoubleFromUInt64(UInt64 value) - { - UInt64 mask = 0x8000000000000000; - value = (value < mask) ? ~(value - 1) : value ^ mask; - return BitConverter.Int64BitsToDouble((Int64)value); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class NumberPartitionKeyComponent : IPartitionKeyComponent + { + private readonly double value; + + public static readonly NumberPartitionKeyComponent Zero = new NumberPartitionKeyComponent(0); + + public NumberPartitionKeyComponent(double value) + { + this.value = value; + } + + public double Value + { + get + { + return this.value; + } + } + + public int CompareTo(IPartitionKeyComponent other) + { + NumberPartitionKeyComponent otherNumber = other as NumberPartitionKeyComponent; + if (otherNumber == null) + { + throw new ArgumentException("other"); + } + + return this.value.CompareTo(otherNumber.value); + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.Number; + } + + public override int GetHashCode() + { + return this.value.GetHashCode(); + } + + public void JsonEncode(JsonWriter writer) + { + writer.WriteValue(this.value); + } + + public object ToObject() + { + return this.value; + } + + public IPartitionKeyComponent Truncate() + { + return this; + } + + public void WriteForHashing(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Number); + writer.Write(this.value); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Number); + writer.Write(this.value); + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.Number); + + UInt64 payload = NumberPartitionKeyComponent.EncodeDoubleAsUInt64(this.value); + + // Encode first chunk with 8-bits of payload + binaryWriter.Write((byte)(payload >> (64 - 8))); + payload <<= 8; + + // Encode remaining chunks with 7 bits of payload followed by single "1" bit each. + byte byteToWrite = 0; + bool firstIteration = true; + do + { + if (!firstIteration) + { + binaryWriter.Write(byteToWrite); + } + else + { + firstIteration = false; + } + + byteToWrite = (byte)((payload >> (64 - 8)) | 0x01); + payload <<= 7; + } while (payload != 0); + + // Except for last chunk that ends with "0" bit. + binaryWriter.Write((byte)(byteToWrite & 0xFE)); + } + + /// + /// Constructs a NumberPartitionKeyComponent from byte string. This is only for testing/debugging. Please do not use in actual product code. + /// + public static IPartitionKeyComponent FromHexEncodedBinaryString(byte[] byteString, ref int byteStringOffset) + { + int offset = 64; + UInt64 payload = 0; + + // Decode first 8-bit chunk + offset -= 8; + payload |= (Convert.ToUInt64(byteString[byteStringOffset++])) << offset; + + // Decode remaining 7-bit chunks + while (true) + { + if (byteStringOffset >= byteString.Length) + { + throw new InvalidDataException("Incorrect byte string without termination"); + } + + byte currentByte = byteString[byteStringOffset++]; + + offset -= 7; + payload |= (Convert.ToUInt64(currentByte >> 1)) << offset; + + if ((currentByte & 0x01) == 0) + { + break; + } + } + + double dblValue = NumberPartitionKeyComponent.DecodeDoubleFromUInt64(payload); + + return new NumberPartitionKeyComponent(dblValue); + } + + // Helpers + private static UInt64 EncodeDoubleAsUInt64(double value) + { + UInt64 valueInUInt64 = (UInt64)BitConverter.DoubleToInt64Bits(value); + UInt64 mask = 0x8000000000000000; + return (valueInUInt64 < mask) ? valueInUInt64 ^ mask : (~valueInUInt64) + 1; + } + + private static double DecodeDoubleFromUInt64(UInt64 value) + { + UInt64 mask = 0x8000000000000000; + value = (value < mask) ? ~(value - 1) : value ^ mask; + return BitConverter.Int64BitsToDouble((Int64)value); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Offer.cs b/Microsoft.Azure.Cosmos/src/direct/Offer.cs index 1bbe990c2a..42665e7ed1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Offer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Offer.cs @@ -1,137 +1,137 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents the offer for a resource (collection) in the Azure Cosmos DB service. - /// - /// - /// Currently, offers are only bound to the collection resource. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Offer : Resource - { - /// - /// Initializes a Resource offer for the Azure Cosmos DB service. - /// - public Offer() - { - this.OfferVersion = Constants.Offers.OfferVersion_V1; - } - - /// - /// Initializes a Resource offer from another offer object for the Azure Cosmos DB service. - /// - public Offer(Offer offer) - : base(offer) - { - this.OfferVersion = Constants.Offers.OfferVersion_V1; - this.ResourceLink = offer.ResourceLink; - this.OfferType = offer.OfferType; - this.OfferResourceId = offer.OfferResourceId; - } - - /// - /// Gets or sets the version of this offer resource in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferVersion, DefaultValueHandling = DefaultValueHandling.Ignore)] - public string OfferVersion - { - get - { - return base.GetValue(Constants.Properties.OfferVersion); - } - internal set - { - base.SetValue(Constants.Properties.OfferVersion, value); - } - } - - /// - /// Gets or sets the self-link of a resource to which the resource offer applies to in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] - public string ResourceLink - { - get - { - return base.GetValue(Constants.Properties.ResourceLink); - } - internal set - { - base.SetValue(Constants.Properties.ResourceLink, value); - } - } - - /// - /// Gets or sets the OfferType for the resource offer in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferType, DefaultValueHandling = DefaultValueHandling.Ignore)] - public string OfferType - { - get - { - return base.GetValue(Constants.Properties.OfferType); - } - set - { - base.SetValue(Constants.Properties.OfferType, value); - } - } - - /// - /// Gets or sets the Id of the resource on which the Offer applies to in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferResourceId)] - internal string OfferResourceId - { - get - { - return base.GetValue(Constants.Properties.OfferResourceId); - } - set - { - base.SetValue(Constants.Properties.OfferResourceId, value); - } - } - - /// - /// Validates the property, by calling it, in case of any errors exception is thrown - /// - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.OfferVersion); - base.GetValue(Constants.Properties.ResourceLink); - base.GetValue(Constants.Properties.OfferType); - } - - /// - /// Compares the offer object with the current offer - /// - /// - /// Boolean representing the equality result - public bool Equals(Offer offer) - { - if (!this.OfferVersion.Equals(offer.OfferVersion) || !this.OfferResourceId.Equals(offer.OfferResourceId)) - { - return false; - } - - if (this.OfferVersion.Equals(Constants.Offers.OfferVersion_V1) && !this.OfferType.Equals(offer.OfferType)) - { - return false; - } - - return true; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents the offer for a resource (collection) in the Azure Cosmos DB service. + /// + /// + /// Currently, offers are only bound to the collection resource. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Offer : Resource + { + /// + /// Initializes a Resource offer for the Azure Cosmos DB service. + /// + public Offer() + { + this.OfferVersion = Constants.Offers.OfferVersion_V1; + } + + /// + /// Initializes a Resource offer from another offer object for the Azure Cosmos DB service. + /// + public Offer(Offer offer) + : base(offer) + { + this.OfferVersion = Constants.Offers.OfferVersion_V1; + this.ResourceLink = offer.ResourceLink; + this.OfferType = offer.OfferType; + this.OfferResourceId = offer.OfferResourceId; + } + + /// + /// Gets or sets the version of this offer resource in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferVersion, DefaultValueHandling = DefaultValueHandling.Ignore)] + public string OfferVersion + { + get + { + return base.GetValue(Constants.Properties.OfferVersion); + } + internal set + { + base.SetValue(Constants.Properties.OfferVersion, value); + } + } + + /// + /// Gets or sets the self-link of a resource to which the resource offer applies to in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] + public string ResourceLink + { + get + { + return base.GetValue(Constants.Properties.ResourceLink); + } + internal set + { + base.SetValue(Constants.Properties.ResourceLink, value); + } + } + + /// + /// Gets or sets the OfferType for the resource offer in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferType, DefaultValueHandling = DefaultValueHandling.Ignore)] + public string OfferType + { + get + { + return base.GetValue(Constants.Properties.OfferType); + } + set + { + base.SetValue(Constants.Properties.OfferType, value); + } + } + + /// + /// Gets or sets the Id of the resource on which the Offer applies to in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferResourceId)] + internal string OfferResourceId + { + get + { + return base.GetValue(Constants.Properties.OfferResourceId); + } + set + { + base.SetValue(Constants.Properties.OfferResourceId, value); + } + } + + /// + /// Validates the property, by calling it, in case of any errors exception is thrown + /// + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.OfferVersion); + base.GetValue(Constants.Properties.ResourceLink); + base.GetValue(Constants.Properties.OfferType); + } + + /// + /// Compares the offer object with the current offer + /// + /// + /// Boolean representing the equality result + public bool Equals(Offer offer) + { + if (!this.OfferVersion.Equals(offer.OfferVersion) || !this.OfferResourceId.Equals(offer.OfferResourceId)) + { + return false; + } + + if (this.OfferVersion.Equals(Constants.Offers.OfferVersion_V1) && !this.OfferType.Equals(offer.OfferType)) + { + return false; + } + + return true; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/OfferContentV2.cs b/Microsoft.Azure.Cosmos/src/direct/OfferContentV2.cs index 639856f625..8f75bcec58 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OfferContentV2.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OfferContentV2.cs @@ -1,415 +1,415 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Collections.ObjectModel; - using Newtonsoft.Json; - - /// - /// Represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class OfferContentV2 : JsonSerializable - { -#if !DOCDBCLIENT - private CollectionThroughputInfo throughputInfo; - private OfferMinimumThroughputParameters minimumThroughputParameters; - private Collection physicalPartitionThroughputInfo; -#endif - - /// - /// Default constructor. - /// - /// - /// The class - /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. - /// - public OfferContentV2() : this(0) - { - } - - /// - /// Constructor accepting offer throughput. - /// - /// - /// The class - /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. - /// - public OfferContentV2(int offerThroughput) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = null; - } - - /// - /// Constructor accepting offer throughput, Request Units(RU)/Minute throughput is enabled or disabled - /// and auto scale is enabled or disabled. - /// - /// - /// The class - /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. - /// - public OfferContentV2(int offerThroughput, bool? offerEnableRUPerMinuteThroughput) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; - } - - /// - /// internal constructor that takes offer throughput, RUPM is enabled/disabled and a reference offer content - /// - internal OfferContentV2(OfferContentV2 content, - int offerThroughput, - bool? offerEnableRUPerMinuteThroughput) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; - -#if !DOCDBCLIENT - // Copy autopilot GA settings. - // Note that we don't copy auto scale V1 settings as it is not meant to be made public. - if (content != null) - { - AutopilotSettings autopilotSettings = content.OfferAutopilotSettings; - if (autopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); - } - } -#endif - } - - /// - /// internal constructor that takes offer throughput, RUPM is enabled/disabled, BgTaskMaxAllowedThroughputPercent and a reference offer content - /// - internal OfferContentV2(OfferContentV2 content, - int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - double? bgTaskMaxAllowedThroughputPercent) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; - - if(bgTaskMaxAllowedThroughputPercent != null) - { - this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; - } - -#if !DOCDBCLIENT - // Copy autopilot GA settings. - // Note that we don't copy auto scale V1 settings as it is not meant to be made public. - if (content != null) - { - AutopilotSettings autopilotSettings = content.OfferAutopilotSettings; - if (autopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); - } - } -#endif - } - -#if !DOCDBCLIENT - /// - /// Constructor accepting autopilot settings. - /// - /// offer autopilot settings - internal OfferContentV2(AutopilotSettings offerAutopilotSettings) - { - if (offerAutopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(offerAutopilotSettings); - } - } - - /// - /// Constructor accepting autopilot settings. - /// - /// offer autopilot settings - /// offer bg-task percentage settings - internal OfferContentV2(AutopilotSettings offerAutopilotSettings, double? bgTaskMaxAllowedThroughputPercent) - { - if (offerAutopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(offerAutopilotSettings); - } - - if(bgTaskMaxAllowedThroughputPercent != null) - { - this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; - } - } - - /// - /// Internal constructor accepting offer throughput, autopilot settings and minimum throughput parameters - /// - internal OfferContentV2(int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings, - OfferMinimumThroughputParameters minThroughputParameters) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; - this.OfferIsAutoScaleEnabled = offerIsAutoScaleV1Enabled; - - if (autopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); - } - - if (minThroughputParameters != null) - { - this.OfferMinimumThroughputParameters = new OfferMinimumThroughputParameters(minThroughputParameters); - } - } - - /// - /// Internal constructor accepting offer throughput, autopilot settings, minimum throughput parameters, bg task throughput percent - /// - internal OfferContentV2(int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings, - OfferMinimumThroughputParameters minThroughputParameters, - double? bgTaskMaxAllowedThroughputPercent) - { - this.OfferThroughput = offerThroughput; - this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; - this.OfferIsAutoScaleEnabled = offerIsAutoScaleV1Enabled; - - if (autopilotSettings != null) - { - this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); - } - - if (minThroughputParameters != null) - { - this.OfferMinimumThroughputParameters = new OfferMinimumThroughputParameters(minThroughputParameters); - } - - if(bgTaskMaxAllowedThroughputPercent != null) - { - this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; - } - } -#endif - - /// - /// Represents customizable throughput chosen by user for his collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferThroughput, DefaultValueHandling = DefaultValueHandling.Ignore)] - public int OfferThroughput - { - get - { - return base.GetValue(Constants.Properties.OfferThroughput); - } - private set - { - base.SetValue(Constants.Properties.OfferThroughput, value); - } - } - - /// - /// Represents customizable maximum allowed throughput budget in percentage chosen by user to run any - /// background task(eg. PK Delete, Creating UniqueIndex policy) for the collection in the Azure Cosmos DB service. - /// In the absence of any background task, the whole throughput is available for use by customer for their workload. - /// But even in absence of user workload, user background task will not utilize over the allotted percentage of throughput. - /// We will have default value of BackgroundTaskMaxAllowedThroughputPercent to be 10 percent if user has not explicitly set it. - /// This helps the background tasks to not starve and at the same time impact on user's workload will be minimal. - /// User can set the value in range (10,100]. - /// - [JsonProperty(PropertyName = Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal double? BackgroundTaskMaxAllowedThroughputPercent - { - get - { - return base.GetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent); - } - private set - { - base.SetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent, value); - } - } - - /// - /// Represents Request Units(RU)/Minute throughput is enabled/disabled for collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferIsRUPerMinuteThroughputEnabled, DefaultValueHandling = DefaultValueHandling.Ignore)] - public bool? OfferIsRUPerMinuteThroughputEnabled - { - get - { - return base.GetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled); - } - private set - { - base.SetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled, value); - } - } - - /// - /// Validates the property, by calling it, in case of any errors exception is thrown - /// - internal override void Validate() - { - base.GetValue(Constants.Properties.OfferThroughput); - base.GetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled); -#if !DOCDBCLIENT - if(this.OfferAutopilotSettings != null) - { - this.OfferAutopilotSettings.Validate(); - } -#endif - base.GetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent); - } - -#if !DOCDBCLIENT - /// - /// Represents auto scale is enabled/disabled for collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferIsAutoScaleEnabled, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal bool? OfferIsAutoScaleEnabled - { - get - { - return base.GetValue(Constants.Properties.OfferIsAutoScaleEnabled); - } - set - { - base.SetValue(Constants.Properties.OfferIsAutoScaleEnabled, value); - } - } - - /// - /// Represents timestamp when offer was last replaced by user for collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferLastReplaceTimestamp, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal long? OfferLastReplaceTimestamp - { - get - { - return base.GetValue(Constants.Properties.OfferLastReplaceTimestamp); - } - set - { - base.SetValue(Constants.Properties.OfferLastReplaceTimestamp, value); - } - } - - /// - /// Represents throughput information relating to the collection that this offer is associated with. - /// This is an internal attribute populated only for purposes of post-split throughput adjustments. - /// - [JsonProperty(PropertyName = Constants.Properties.CollectionThroughputInfo, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal CollectionThroughputInfo CollectionThroughputInfo - { - get - { - if (this.throughputInfo == null) - { - this.throughputInfo = base.GetValue(Constants.Properties.CollectionThroughputInfo); - - if (this.throughputInfo == null) - { - this.throughputInfo = new CollectionThroughputInfo(); - } - } - - return this.throughputInfo; - } - } - - /// - /// Represents information relating to the collection/database that this offer is associated with. - /// This is an internal attribute populated for min RU calculations. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferMinimumThroughputParameters, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal OfferMinimumThroughputParameters OfferMinimumThroughputParameters - { - get - { - if (this.minimumThroughputParameters == null) - { - this.minimumThroughputParameters = base.GetObject(Constants.Properties.OfferMinimumThroughputParameters); - - if (this.minimumThroughputParameters == null) - { - this.minimumThroughputParameters = new OfferMinimumThroughputParameters(); - } - } - - return this.minimumThroughputParameters; - } - set - { - this.minimumThroughputParameters = value; - base.SetObject(Constants.Properties.OfferMinimumThroughputParameters, this.minimumThroughputParameters); - } - } - - /// - /// Represents settings related to auto scale of a collection/database offer. - /// - /// Don't cache this property like we did for CollectionThroughputInfo and OffferMinimumThroughputParameters - /// as it would result in not deserializing autoscale settings correctly. - /// - /// - [JsonProperty(PropertyName = Constants.Properties.AutopilotSettings, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal AutopilotSettings OfferAutopilotSettings - { - get - { - return base.GetObject(Constants.Properties.AutopilotSettings); ; - } - set - { - base.SetObject(Constants.Properties.AutopilotSettings, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.PhysicalPartitionThroughputInfo, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal Collection PhysicalPartitionThroughputInfo - { - get - { - if (this.physicalPartitionThroughputInfo == null) - { - this.physicalPartitionThroughputInfo = base.GetObjectCollection(Constants.Properties.PhysicalPartitionThroughputInfo); - } - - return this.physicalPartitionThroughputInfo; - } - } - - internal override void OnSave() - { - base.OnSave(); - - if (this.throughputInfo != null) - { - this.throughputInfo.OnSave(); - this.SetObject(Constants.Properties.CollectionThroughputInfo, this.throughputInfo); - } - - if (this.minimumThroughputParameters != null) - { - this.minimumThroughputParameters.OnSave(); - this.SetObject(Constants.Properties.OfferMinimumThroughputParameters, this.minimumThroughputParameters); - } - - if (this.physicalPartitionThroughputInfo != null) - { - this.SetObjectCollection(Constants.Properties.PhysicalPartitionThroughputInfo, this.physicalPartitionThroughputInfo); - } - } -#endif - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Collections.ObjectModel; + using Newtonsoft.Json; + + /// + /// Represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class OfferContentV2 : JsonSerializable + { +#if !DOCDBCLIENT + private CollectionThroughputInfo throughputInfo; + private OfferMinimumThroughputParameters minimumThroughputParameters; + private Collection physicalPartitionThroughputInfo; +#endif + + /// + /// Default constructor. + /// + /// + /// The class + /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. + /// + public OfferContentV2() : this(0) + { + } + + /// + /// Constructor accepting offer throughput. + /// + /// + /// The class + /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. + /// + public OfferContentV2(int offerThroughput) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = null; + } + + /// + /// Constructor accepting offer throughput, Request Units(RU)/Minute throughput is enabled or disabled + /// and auto scale is enabled or disabled. + /// + /// + /// The class + /// represents content properties tied to the Standard pricing tier for the Azure Cosmos DB service. + /// + public OfferContentV2(int offerThroughput, bool? offerEnableRUPerMinuteThroughput) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; + } + + /// + /// internal constructor that takes offer throughput, RUPM is enabled/disabled and a reference offer content + /// + internal OfferContentV2(OfferContentV2 content, + int offerThroughput, + bool? offerEnableRUPerMinuteThroughput) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; + +#if !DOCDBCLIENT + // Copy autopilot GA settings. + // Note that we don't copy auto scale V1 settings as it is not meant to be made public. + if (content != null) + { + AutopilotSettings autopilotSettings = content.OfferAutopilotSettings; + if (autopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); + } + } +#endif + } + + /// + /// internal constructor that takes offer throughput, RUPM is enabled/disabled, BgTaskMaxAllowedThroughputPercent and a reference offer content + /// + internal OfferContentV2(OfferContentV2 content, + int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + double? bgTaskMaxAllowedThroughputPercent) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; + + if(bgTaskMaxAllowedThroughputPercent != null) + { + this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; + } + +#if !DOCDBCLIENT + // Copy autopilot GA settings. + // Note that we don't copy auto scale V1 settings as it is not meant to be made public. + if (content != null) + { + AutopilotSettings autopilotSettings = content.OfferAutopilotSettings; + if (autopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); + } + } +#endif + } + +#if !DOCDBCLIENT + /// + /// Constructor accepting autopilot settings. + /// + /// offer autopilot settings + internal OfferContentV2(AutopilotSettings offerAutopilotSettings) + { + if (offerAutopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(offerAutopilotSettings); + } + } + + /// + /// Constructor accepting autopilot settings. + /// + /// offer autopilot settings + /// offer bg-task percentage settings + internal OfferContentV2(AutopilotSettings offerAutopilotSettings, double? bgTaskMaxAllowedThroughputPercent) + { + if (offerAutopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(offerAutopilotSettings); + } + + if(bgTaskMaxAllowedThroughputPercent != null) + { + this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; + } + } + + /// + /// Internal constructor accepting offer throughput, autopilot settings and minimum throughput parameters + /// + internal OfferContentV2(int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings, + OfferMinimumThroughputParameters minThroughputParameters) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; + this.OfferIsAutoScaleEnabled = offerIsAutoScaleV1Enabled; + + if (autopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); + } + + if (minThroughputParameters != null) + { + this.OfferMinimumThroughputParameters = new OfferMinimumThroughputParameters(minThroughputParameters); + } + } + + /// + /// Internal constructor accepting offer throughput, autopilot settings, minimum throughput parameters, bg task throughput percent + /// + internal OfferContentV2(int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings, + OfferMinimumThroughputParameters minThroughputParameters, + double? bgTaskMaxAllowedThroughputPercent) + { + this.OfferThroughput = offerThroughput; + this.OfferIsRUPerMinuteThroughputEnabled = offerEnableRUPerMinuteThroughput; + this.OfferIsAutoScaleEnabled = offerIsAutoScaleV1Enabled; + + if (autopilotSettings != null) + { + this.OfferAutopilotSettings = new AutopilotSettings(autopilotSettings); + } + + if (minThroughputParameters != null) + { + this.OfferMinimumThroughputParameters = new OfferMinimumThroughputParameters(minThroughputParameters); + } + + if(bgTaskMaxAllowedThroughputPercent != null) + { + this.BackgroundTaskMaxAllowedThroughputPercent = bgTaskMaxAllowedThroughputPercent; + } + } +#endif + + /// + /// Represents customizable throughput chosen by user for his collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferThroughput, DefaultValueHandling = DefaultValueHandling.Ignore)] + public int OfferThroughput + { + get + { + return base.GetValue(Constants.Properties.OfferThroughput); + } + private set + { + base.SetValue(Constants.Properties.OfferThroughput, value); + } + } + + /// + /// Represents customizable maximum allowed throughput budget in percentage chosen by user to run any + /// background task(eg. PK Delete, Creating UniqueIndex policy) for the collection in the Azure Cosmos DB service. + /// In the absence of any background task, the whole throughput is available for use by customer for their workload. + /// But even in absence of user workload, user background task will not utilize over the allotted percentage of throughput. + /// We will have default value of BackgroundTaskMaxAllowedThroughputPercent to be 10 percent if user has not explicitly set it. + /// This helps the background tasks to not starve and at the same time impact on user's workload will be minimal. + /// User can set the value in range (10,100]. + /// + [JsonProperty(PropertyName = Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal double? BackgroundTaskMaxAllowedThroughputPercent + { + get + { + return base.GetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent); + } + private set + { + base.SetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent, value); + } + } + + /// + /// Represents Request Units(RU)/Minute throughput is enabled/disabled for collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferIsRUPerMinuteThroughputEnabled, DefaultValueHandling = DefaultValueHandling.Ignore)] + public bool? OfferIsRUPerMinuteThroughputEnabled + { + get + { + return base.GetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled); + } + private set + { + base.SetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled, value); + } + } + + /// + /// Validates the property, by calling it, in case of any errors exception is thrown + /// + internal override void Validate() + { + base.GetValue(Constants.Properties.OfferThroughput); + base.GetValue(Constants.Properties.OfferIsRUPerMinuteThroughputEnabled); +#if !DOCDBCLIENT + if(this.OfferAutopilotSettings != null) + { + this.OfferAutopilotSettings.Validate(); + } +#endif + base.GetValue(Constants.Properties.BackgroundTaskMaxAllowedThroughputPercent); + } + +#if !DOCDBCLIENT + /// + /// Represents auto scale is enabled/disabled for collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferIsAutoScaleEnabled, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal bool? OfferIsAutoScaleEnabled + { + get + { + return base.GetValue(Constants.Properties.OfferIsAutoScaleEnabled); + } + set + { + base.SetValue(Constants.Properties.OfferIsAutoScaleEnabled, value); + } + } + + /// + /// Represents timestamp when offer was last replaced by user for collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferLastReplaceTimestamp, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal long? OfferLastReplaceTimestamp + { + get + { + return base.GetValue(Constants.Properties.OfferLastReplaceTimestamp); + } + set + { + base.SetValue(Constants.Properties.OfferLastReplaceTimestamp, value); + } + } + + /// + /// Represents throughput information relating to the collection that this offer is associated with. + /// This is an internal attribute populated only for purposes of post-split throughput adjustments. + /// + [JsonProperty(PropertyName = Constants.Properties.CollectionThroughputInfo, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal CollectionThroughputInfo CollectionThroughputInfo + { + get + { + if (this.throughputInfo == null) + { + this.throughputInfo = base.GetValue(Constants.Properties.CollectionThroughputInfo); + + if (this.throughputInfo == null) + { + this.throughputInfo = new CollectionThroughputInfo(); + } + } + + return this.throughputInfo; + } + } + + /// + /// Represents information relating to the collection/database that this offer is associated with. + /// This is an internal attribute populated for min RU calculations. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferMinimumThroughputParameters, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal OfferMinimumThroughputParameters OfferMinimumThroughputParameters + { + get + { + if (this.minimumThroughputParameters == null) + { + this.minimumThroughputParameters = base.GetObject(Constants.Properties.OfferMinimumThroughputParameters); + + if (this.minimumThroughputParameters == null) + { + this.minimumThroughputParameters = new OfferMinimumThroughputParameters(); + } + } + + return this.minimumThroughputParameters; + } + set + { + this.minimumThroughputParameters = value; + base.SetObject(Constants.Properties.OfferMinimumThroughputParameters, this.minimumThroughputParameters); + } + } + + /// + /// Represents settings related to auto scale of a collection/database offer. + /// + /// Don't cache this property like we did for CollectionThroughputInfo and OffferMinimumThroughputParameters + /// as it would result in not deserializing autoscale settings correctly. + /// + /// + [JsonProperty(PropertyName = Constants.Properties.AutopilotSettings, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal AutopilotSettings OfferAutopilotSettings + { + get + { + return base.GetObject(Constants.Properties.AutopilotSettings); ; + } + set + { + base.SetObject(Constants.Properties.AutopilotSettings, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.PhysicalPartitionThroughputInfo, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal Collection PhysicalPartitionThroughputInfo + { + get + { + if (this.physicalPartitionThroughputInfo == null) + { + this.physicalPartitionThroughputInfo = base.GetObjectCollection(Constants.Properties.PhysicalPartitionThroughputInfo); + } + + return this.physicalPartitionThroughputInfo; + } + } + + internal override void OnSave() + { + base.OnSave(); + + if (this.throughputInfo != null) + { + this.throughputInfo.OnSave(); + this.SetObject(Constants.Properties.CollectionThroughputInfo, this.throughputInfo); + } + + if (this.minimumThroughputParameters != null) + { + this.minimumThroughputParameters.OnSave(); + this.SetObject(Constants.Properties.OfferMinimumThroughputParameters, this.minimumThroughputParameters); + } + + if (this.physicalPartitionThroughputInfo != null) + { + this.SetObjectCollection(Constants.Properties.PhysicalPartitionThroughputInfo, this.physicalPartitionThroughputInfo); + } + } +#endif + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/OfferTypeResolver.cs b/Microsoft.Azure.Cosmos/src/direct/OfferTypeResolver.cs index 19aaaef502..e1e9880ceb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OfferTypeResolver.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OfferTypeResolver.cs @@ -1,77 +1,77 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Microsoft.Azure.Cosmos.Core.Trace; - using Newtonsoft.Json.Linq; - - /// - /// Offer resolver based on input. - /// - internal sealed class OfferTypeResolver : ITypeResolver - { - public static readonly ITypeResolver RequestOfferTypeResolver = new OfferTypeResolver(false); - public static readonly ITypeResolver ResponseOfferTypeResolver = new OfferTypeResolver(true); - - private readonly bool isResponse; - - /// - /// Constructor with a flag indicating whether this is invoked in response or request path. - /// - /// True if invoked in response path - private OfferTypeResolver(bool isResponse) - { - this.isResponse = isResponse; - } - - /// - /// Returns a reference of an object in Offer's hierarchy based on a property bag. - /// - /// Property bag used to deserialize Offer object - /// Object of type Offer or OfferV2 - Offer ITypeResolver.Resolve(JObject propertyBag) - { - Offer resource; - if (propertyBag != null) - { - resource = new Offer(); - resource.propertyBag = propertyBag; - - switch (resource.OfferVersion ?? String.Empty) - { - case Constants.Offers.OfferVersion_V1: - case Constants.Offers.OfferVersion_None: - break; - - case Constants.Offers.OfferVersion_V2: - { - resource = new OfferV2(); - resource.propertyBag = propertyBag; // convert Offer resource to V2. - } - break; - - default: - { - DefaultTrace.TraceCritical("Unexpected offer version {0}", resource.OfferVersion); - if(!isResponse) - { - throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.UnsupportedOfferVersion, resource.OfferVersion)); - } - - // in case we get unrecognized offer version from server, we return default Offer. - } - break; - } - } - else - { - resource = default(Offer); - } - - return resource; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Microsoft.Azure.Cosmos.Core.Trace; + using Newtonsoft.Json.Linq; + + /// + /// Offer resolver based on input. + /// + internal sealed class OfferTypeResolver : ITypeResolver + { + public static readonly ITypeResolver RequestOfferTypeResolver = new OfferTypeResolver(false); + public static readonly ITypeResolver ResponseOfferTypeResolver = new OfferTypeResolver(true); + + private readonly bool isResponse; + + /// + /// Constructor with a flag indicating whether this is invoked in response or request path. + /// + /// True if invoked in response path + private OfferTypeResolver(bool isResponse) + { + this.isResponse = isResponse; + } + + /// + /// Returns a reference of an object in Offer's hierarchy based on a property bag. + /// + /// Property bag used to deserialize Offer object + /// Object of type Offer or OfferV2 + Offer ITypeResolver.Resolve(JObject propertyBag) + { + Offer resource; + if (propertyBag != null) + { + resource = new Offer(); + resource.propertyBag = propertyBag; + + switch (resource.OfferVersion ?? String.Empty) + { + case Constants.Offers.OfferVersion_V1: + case Constants.Offers.OfferVersion_None: + break; + + case Constants.Offers.OfferVersion_V2: + { + resource = new OfferV2(); + resource.propertyBag = propertyBag; // convert Offer resource to V2. + } + break; + + default: + { + DefaultTrace.TraceCritical("Unexpected offer version {0}", resource.OfferVersion); + if(!isResponse) + { + throw new BadRequestException(string.Format(CultureInfo.CurrentUICulture, RMResources.UnsupportedOfferVersion, resource.OfferVersion)); + } + + // in case we get unrecognized offer version from server, we return default Offer. + } + break; + } + } + else + { + resource = default(Offer); + } + + return resource; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/OfferV2.cs b/Microsoft.Azure.Cosmos/src/direct/OfferV2.cs index 88f4048822..27119ad6ba 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OfferV2.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OfferV2.cs @@ -1,333 +1,333 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents the Standard pricing offer for a resource in the Azure Cosmos DB service. - /// - /// - /// Currently, offers are only bound to the collection resource. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class OfferV2 : Offer - { - /// - /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. - /// - internal OfferV2() - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - } - - /// - /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. - /// - public OfferV2(int offerThroughput) - : this() - { - this.Content = new OfferContentV2(offerThroughput); - } - - /// - /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. - /// - public OfferV2(int offerThroughput, bool? offerEnableRUPerMinuteThroughput) - : this() - { - this.Content = new OfferContentV2(offerThroughput, offerEnableRUPerMinuteThroughput); - } - - /// - /// Initializes a Resource offer with the Standard pricing tier, from a reference Offer object for the Azure Cosmos DB service. - /// - public OfferV2(Offer offer, int offerThroughput) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - - OfferContentV2 contentV2 = null; - if (offer is OfferV2) - { - contentV2 = ((OfferV2)offer).Content; - } - - this.Content = new OfferContentV2(contentV2, offerThroughput, null); - } - - /// - /// Initializes a Resource offer with the Standard pricing tier, from a reference Offer object for the Azure Cosmos DB service. - /// - public OfferV2(Offer offer, int offerThroughput, bool? offerEnableRUPerMinuteThroughput) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - - OfferContentV2 contentV2 = null; - if (offer is OfferV2) - { - contentV2 = ((OfferV2)offer).Content; - } - - this.Content = new OfferContentV2(contentV2, offerThroughput, offerEnableRUPerMinuteThroughput); - } - - /// - /// Initializes a Resource offer with the Standard pricing tier, max allocation for background tasks, from a reference Offer object for the Azure Cosmos DB service. - /// - internal OfferV2(Offer offer, int offerThroughput, double? bgTaskMaxAllowedThroughputPercent) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - - OfferContentV2 contentV2 = null; - if (offer is OfferV2) - { - contentV2 = ((OfferV2)offer).Content; - } - - this.Content = new OfferContentV2(contentV2, offerThroughput, null, bgTaskMaxAllowedThroughputPercent); - } - -#if !DOCDBCLIENT - /// - /// Initializes a Resource offer with the given autopilot settings, from a reference Offer object for the Azue Cosmos DB service. - /// - internal OfferV2(Offer offer, AutopilotSettings autopilotSettings) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - this.Content = new OfferContentV2(autopilotSettings); - } - - /// - /// Initializes a Resource offer with the given autopilot settings for the Azue Cosmos DB service. - /// - internal OfferV2(AutopilotSettings autopilotSettings) - : this() - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - this.Content = new OfferContentV2(autopilotSettings); - } - - /// - /// Initializes a Resource offer with the given given autopilot settings, max allocation for background tasks for the Azue Cosmos DB service. - /// - internal OfferV2(AutopilotSettings autopilotSettings, double? bgTaskMaxAllowedThroughputPercent) - : this() - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - this.Content = new OfferContentV2(autopilotSettings, bgTaskMaxAllowedThroughputPercent); - } - - /// - /// Internal constructor initializes offer with the given throughput and autopilot settings. - /// - internal OfferV2(int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings) - : this() - { - this.Content = new OfferContentV2(offerThroughput, - offerEnableRUPerMinuteThroughput, - offerIsAutoScaleV1Enabled, - autopilotSettings, - null); - } - - /// - /// Internal constructor initializes offer with the the given throughput, autopilot settings and max allocation for background task allocation. - /// - internal OfferV2(int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings, - double? bgTaskMaxAllowedThroughputPercent) - : this() - { - this.Content = new OfferContentV2(offerThroughput, - offerEnableRUPerMinuteThroughput, - offerIsAutoScaleV1Enabled, - autopilotSettings, - null, - bgTaskMaxAllowedThroughputPercent); - } - - /// - /// Internal constructor that initializes offer with the given throughput, autoscale setting and from reference offer object - /// - internal OfferV2(Offer offer, - int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings, - OfferMinimumThroughputParameters minimumThoughputParameters) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - - this.Content = new OfferContentV2(offerThroughput, - offerEnableRUPerMinuteThroughput, - offerIsAutoScaleV1Enabled, - autopilotSettings, - minimumThoughputParameters); - } - - /// - /// Internal constructor that initializes offer with the given throughput, max allowed background task throughput percentage, autoscale setting from reference offer object - /// - internal OfferV2(Offer offer, - int offerThroughput, - bool? offerEnableRUPerMinuteThroughput, - bool? offerIsAutoScaleV1Enabled, - AutopilotSettings autopilotSettings, - OfferMinimumThroughputParameters minimumThoughputParameters, - double? bgTaskMaxAllowedThroughputPercent) - : base(offer) - { - this.OfferType = string.Empty; - this.OfferVersion = Constants.Offers.OfferVersion_V2; - - this.Content = new OfferContentV2(offerThroughput, - offerEnableRUPerMinuteThroughput, - offerIsAutoScaleV1Enabled, - autopilotSettings, - minimumThoughputParameters, - bgTaskMaxAllowedThroughputPercent); - } -#endif - - /// - /// Gets or sets the OfferContent for the resource offer in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.OfferContent, DefaultValueHandling = DefaultValueHandling.Ignore)] - public OfferContentV2 Content - { - get - { - return base.GetObject(Constants.Properties.OfferContent); - } - internal set - { - base.SetObject(Constants.Properties.OfferContent, value); - } - } - - /// - /// Validates the property, by calling it, in case of any errors exception is thrown - /// - internal override void Validate() - { - base.Validate(); - this.Content?.Validate(); - } - - /// - /// Compares the offer object with the current offer - /// - /// - /// Boolean representing the equality result - public bool Equals(OfferV2 offer) - { - if (offer == null) - { - return false; - } - - if (!base.Equals(offer)) - { - return false; - } - - if (this.Content == null && offer.Content == null) - { - return true; - } - else if (this.Content != null && offer.Content != null) - { -#if DOCDBCLIENT - return (this.Content.OfferThroughput == offer.Content.OfferThroughput) && - (this.Content.OfferIsRUPerMinuteThroughputEnabled == offer.Content.OfferIsRUPerMinuteThroughputEnabled); -#else - return (this.GetOfferThroughput(false) == offer.GetOfferThroughput(false)) && - (this.Content.OfferIsRUPerMinuteThroughputEnabled == offer.Content.OfferIsRUPerMinuteThroughputEnabled) && - // Unset or false should be treated the same. In gateway, if offer replace request to store times out we wait a bit - // and read again from master and compare it to see if it is what we expect. If they are equal we treat it as success. - (this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false) == offer.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) && - (this.Content.BackgroundTaskMaxAllowedThroughputPercent.GetValueOrDefault(0.0) == offer.Content.BackgroundTaskMaxAllowedThroughputPercent.GetValueOrDefault(0.0)); -#endif - } - - return false; - } - -#if !DOCDBCLIENT - internal bool IsAutoScaleEnabled() - { - if (this.Content != null) - { - AutopilotSettings autopilotSettings = this.Content.OfferAutopilotSettings; - - // Autoscale V2: uses AutopilotSettings and takes precedencde over autoscale V1 settings - if (autopilotSettings != null) - { - // Presence of AutopilotSettings indicates Autopilot is enabled. - return true; - } - - // Autoscale preview: uses OfferIsAutoScaleEnabled property - if (this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) - { - return true; - } - } - - return false; - } - - internal int? GetOfferThroughput(bool isAutoScaleTriggeredRequest) - { - if (this.Content == null) - { - return null; - } - - int? offerThroughput = this.Content.OfferThroughput; - - if (!isAutoScaleTriggeredRequest) - { - AutopilotSettings autopilotSettings = this.Content.OfferAutopilotSettings; - if (autopilotSettings != null) - { - offerThroughput = 0; // In case of autopilot request, Throughput is based on the Tier. - } - else if(this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) - { - if(this.Content.CollectionThroughputInfo.UserSpecifiedThroughput.HasValue) - { - offerThroughput = this.Content.CollectionThroughputInfo.UserSpecifiedThroughput.Value; - } - } - } - - return offerThroughput; - } -#endif - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents the Standard pricing offer for a resource in the Azure Cosmos DB service. + /// + /// + /// Currently, offers are only bound to the collection resource. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class OfferV2 : Offer + { + /// + /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. + /// + internal OfferV2() + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + } + + /// + /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. + /// + public OfferV2(int offerThroughput) + : this() + { + this.Content = new OfferContentV2(offerThroughput); + } + + /// + /// Initializes a Resource offer with the Standard pricing tier for the Azure Cosmos DB service. + /// + public OfferV2(int offerThroughput, bool? offerEnableRUPerMinuteThroughput) + : this() + { + this.Content = new OfferContentV2(offerThroughput, offerEnableRUPerMinuteThroughput); + } + + /// + /// Initializes a Resource offer with the Standard pricing tier, from a reference Offer object for the Azure Cosmos DB service. + /// + public OfferV2(Offer offer, int offerThroughput) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + + OfferContentV2 contentV2 = null; + if (offer is OfferV2) + { + contentV2 = ((OfferV2)offer).Content; + } + + this.Content = new OfferContentV2(contentV2, offerThroughput, null); + } + + /// + /// Initializes a Resource offer with the Standard pricing tier, from a reference Offer object for the Azure Cosmos DB service. + /// + public OfferV2(Offer offer, int offerThroughput, bool? offerEnableRUPerMinuteThroughput) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + + OfferContentV2 contentV2 = null; + if (offer is OfferV2) + { + contentV2 = ((OfferV2)offer).Content; + } + + this.Content = new OfferContentV2(contentV2, offerThroughput, offerEnableRUPerMinuteThroughput); + } + + /// + /// Initializes a Resource offer with the Standard pricing tier, max allocation for background tasks, from a reference Offer object for the Azure Cosmos DB service. + /// + internal OfferV2(Offer offer, int offerThroughput, double? bgTaskMaxAllowedThroughputPercent) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + + OfferContentV2 contentV2 = null; + if (offer is OfferV2) + { + contentV2 = ((OfferV2)offer).Content; + } + + this.Content = new OfferContentV2(contentV2, offerThroughput, null, bgTaskMaxAllowedThroughputPercent); + } + +#if !DOCDBCLIENT + /// + /// Initializes a Resource offer with the given autopilot settings, from a reference Offer object for the Azue Cosmos DB service. + /// + internal OfferV2(Offer offer, AutopilotSettings autopilotSettings) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + this.Content = new OfferContentV2(autopilotSettings); + } + + /// + /// Initializes a Resource offer with the given autopilot settings for the Azue Cosmos DB service. + /// + internal OfferV2(AutopilotSettings autopilotSettings) + : this() + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + this.Content = new OfferContentV2(autopilotSettings); + } + + /// + /// Initializes a Resource offer with the given given autopilot settings, max allocation for background tasks for the Azue Cosmos DB service. + /// + internal OfferV2(AutopilotSettings autopilotSettings, double? bgTaskMaxAllowedThroughputPercent) + : this() + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + this.Content = new OfferContentV2(autopilotSettings, bgTaskMaxAllowedThroughputPercent); + } + + /// + /// Internal constructor initializes offer with the given throughput and autopilot settings. + /// + internal OfferV2(int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings) + : this() + { + this.Content = new OfferContentV2(offerThroughput, + offerEnableRUPerMinuteThroughput, + offerIsAutoScaleV1Enabled, + autopilotSettings, + null); + } + + /// + /// Internal constructor initializes offer with the the given throughput, autopilot settings and max allocation for background task allocation. + /// + internal OfferV2(int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings, + double? bgTaskMaxAllowedThroughputPercent) + : this() + { + this.Content = new OfferContentV2(offerThroughput, + offerEnableRUPerMinuteThroughput, + offerIsAutoScaleV1Enabled, + autopilotSettings, + null, + bgTaskMaxAllowedThroughputPercent); + } + + /// + /// Internal constructor that initializes offer with the given throughput, autoscale setting and from reference offer object + /// + internal OfferV2(Offer offer, + int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings, + OfferMinimumThroughputParameters minimumThoughputParameters) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + + this.Content = new OfferContentV2(offerThroughput, + offerEnableRUPerMinuteThroughput, + offerIsAutoScaleV1Enabled, + autopilotSettings, + minimumThoughputParameters); + } + + /// + /// Internal constructor that initializes offer with the given throughput, max allowed background task throughput percentage, autoscale setting from reference offer object + /// + internal OfferV2(Offer offer, + int offerThroughput, + bool? offerEnableRUPerMinuteThroughput, + bool? offerIsAutoScaleV1Enabled, + AutopilotSettings autopilotSettings, + OfferMinimumThroughputParameters minimumThoughputParameters, + double? bgTaskMaxAllowedThroughputPercent) + : base(offer) + { + this.OfferType = string.Empty; + this.OfferVersion = Constants.Offers.OfferVersion_V2; + + this.Content = new OfferContentV2(offerThroughput, + offerEnableRUPerMinuteThroughput, + offerIsAutoScaleV1Enabled, + autopilotSettings, + minimumThoughputParameters, + bgTaskMaxAllowedThroughputPercent); + } +#endif + + /// + /// Gets or sets the OfferContent for the resource offer in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.OfferContent, DefaultValueHandling = DefaultValueHandling.Ignore)] + public OfferContentV2 Content + { + get + { + return base.GetObject(Constants.Properties.OfferContent); + } + internal set + { + base.SetObject(Constants.Properties.OfferContent, value); + } + } + + /// + /// Validates the property, by calling it, in case of any errors exception is thrown + /// + internal override void Validate() + { + base.Validate(); + this.Content?.Validate(); + } + + /// + /// Compares the offer object with the current offer + /// + /// + /// Boolean representing the equality result + public bool Equals(OfferV2 offer) + { + if (offer == null) + { + return false; + } + + if (!base.Equals(offer)) + { + return false; + } + + if (this.Content == null && offer.Content == null) + { + return true; + } + else if (this.Content != null && offer.Content != null) + { +#if DOCDBCLIENT + return (this.Content.OfferThroughput == offer.Content.OfferThroughput) && + (this.Content.OfferIsRUPerMinuteThroughputEnabled == offer.Content.OfferIsRUPerMinuteThroughputEnabled); +#else + return (this.GetOfferThroughput(false) == offer.GetOfferThroughput(false)) && + (this.Content.OfferIsRUPerMinuteThroughputEnabled == offer.Content.OfferIsRUPerMinuteThroughputEnabled) && + // Unset or false should be treated the same. In gateway, if offer replace request to store times out we wait a bit + // and read again from master and compare it to see if it is what we expect. If they are equal we treat it as success. + (this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false) == offer.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) && + (this.Content.BackgroundTaskMaxAllowedThroughputPercent.GetValueOrDefault(0.0) == offer.Content.BackgroundTaskMaxAllowedThroughputPercent.GetValueOrDefault(0.0)); +#endif + } + + return false; + } + +#if !DOCDBCLIENT + internal bool IsAutoScaleEnabled() + { + if (this.Content != null) + { + AutopilotSettings autopilotSettings = this.Content.OfferAutopilotSettings; + + // Autoscale V2: uses AutopilotSettings and takes precedencde over autoscale V1 settings + if (autopilotSettings != null) + { + // Presence of AutopilotSettings indicates Autopilot is enabled. + return true; + } + + // Autoscale preview: uses OfferIsAutoScaleEnabled property + if (this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) + { + return true; + } + } + + return false; + } + + internal int? GetOfferThroughput(bool isAutoScaleTriggeredRequest) + { + if (this.Content == null) + { + return null; + } + + int? offerThroughput = this.Content.OfferThroughput; + + if (!isAutoScaleTriggeredRequest) + { + AutopilotSettings autopilotSettings = this.Content.OfferAutopilotSettings; + if (autopilotSettings != null) + { + offerThroughput = 0; // In case of autopilot request, Throughput is based on the Tier. + } + else if(this.Content.OfferIsAutoScaleEnabled.GetValueOrDefault(false)) + { + if(this.Content.CollectionThroughputInfo.UserSpecifiedThroughput.HasValue) + { + offerThroughput = this.Content.CollectionThroughputInfo.UserSpecifiedThroughput.Value; + } + } + } + + return offerThroughput; + } +#endif + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/OperationKind.cs b/Microsoft.Azure.Cosmos/src/direct/OperationKind.cs index e0485b8181..ce167a82da 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OperationKind.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OperationKind.cs @@ -1,48 +1,48 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -using System; -namespace Microsoft.Azure.Documents -{ - /// - /// These are the operation types resulted in a version conflict on a resource. - /// - /// - /// When a version conflict occurs during an async operation, retrieving the instance will allow you - /// to determine which resource and operation caause the conflict. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum OperationKind - { - /// - /// An invalid operation. - /// - Invalid, - - /// - /// A create operation. - /// - Create, - - /// - /// An replace operation. - /// - Replace, - - /// - /// A delete operation. - /// - Delete, - - /// - /// This operation does not apply to Conflict. - /// - [ObsoleteAttribute("This item is obsolete as it does not apply to Conflict.")] - Read - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +using System; +namespace Microsoft.Azure.Documents +{ + /// + /// These are the operation types resulted in a version conflict on a resource. + /// + /// + /// When a version conflict occurs during an async operation, retrieving the instance will allow you + /// to determine which resource and operation caause the conflict. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum OperationKind + { + /// + /// An invalid operation. + /// + Invalid, + + /// + /// A create operation. + /// + Create, + + /// + /// An replace operation. + /// + Replace, + + /// + /// A delete operation. + /// + Delete, + + /// + /// This operation does not apply to Conflict. + /// + [ObsoleteAttribute("This item is obsolete as it does not apply to Conflict.")] + Read + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/OperationType.cs b/Microsoft.Azure.Cosmos/src/direct/OperationType.cs index 65848b4c88..e76f3fd222 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OperationType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OperationType.cs @@ -1,233 +1,233 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - - internal enum OperationType - { - // Keep in sync with RequestOperationType enum in backend native. - Invalid = -1, - Create = 0, - Patch = 1, - Read = 2, - ReadFeed = 3, - Delete = 4, - Replace = 5, -#if !COSMOSCLIENT - Pause = 6, - Resume = 7, - Stop = 8, -#endif - Execute = 9, -#if !COSMOSCLIENT - Recycle = 10, - Crash = 11, - FanoutDelete = 12, -#endif - BatchApply = 13, - SqlQuery = 14, - Query = 15, -#if !COSMOSCLIENT - BindReplica = 16, - JSQuery = 17, -#endif - Head = 18, - HeadFeed = 19, - Upsert = 20, -#if !COSMOSCLIENT - Recreate = 21, - Throttle = 22, - GetSplitPoint = 23, - PreCreateValidation = 24, - ApplyTransactionLogs = 25, - Relocate = 26, - AbortSplit = 27, - CompleteSplit = 28, - WriteValue = 29, - CompletePartitionMigration = 30, - AbortPartitionMigration = 31, - OfferUpdateOperation = 32, - OfferPreGrowValidation = 33, - BatchReportThroughputUtilization = 34, - PreReplaceValidation = 35, - MigratePartition = 36, -#endif - AddComputeGatewayRequestCharges = 37, -#if !COSMOSCLIENT - MasterReplaceOfferOperation = 38, - ProvisionedCollectionOfferUpdateOperation = 39, -#endif - Batch = 40, - QueryPlan = 41, - -#if !COSMOSCLIENT - InitiateDatabaseOfferPartitionShrink = 42, - CompleteDatabaseOfferPartitionShrink = 43, - EnsureSnapshotOperation = 44, - GetSplitPoints = 45, - // AddLogStoreCharge=46 -#endif - -#if !COSMOSCLIENT - CompleteMergeOnTarget = 47, - CompleteMergeOnMaster = 48, - AbortMergeOnTarget = 49, - AbortMergeOnMaster = 50, -#endif - -#if !COSMOSCLIENT - ForcePartitionBackup = 51, -#endif - - CompleteUserTransaction = 52, - -#if !COSMOSCLIENT - SystemOperation = 53, -#endif - MetadataCheckAccess = 54, -#if !COSMOSCLIENT - Prune = 55, - CreateSystemSnapshot = 56, -#endif - - CollectionTruncate = 57, - -#if !COSMOSCLIENT - UpdateFailoverPriorityList = 58, -#endif - -#if !COSMOSCLIENT - GetStorageAuthToken = 59, - CreateClientEncryptionKey = 60, - ReplaceClientEncryptionKey = 61, - UpdatePartitionThroughput = 62, - - // Operation type for recreating RidRange resources during the pitr restore of a multi master partition - CreateRidRangeResources = 64, - Truncate = 65, -#endif - - // These names make it unclear what they map to in RequestOperationType. - ExecuteJavaScript = -2, - GetConfiguration = -8, -#if !COSMOSCLIENT - ForceConfigRefresh = -3, - ReportThroughputUtilization = -4, - ServiceReservation = -5, - ControllerBatchReportCharges = -6, - ControllerBatchGetOutput = -7, - GetStorageAccountKey = -9, - GetFederationConfigurations = -10, - GetDatabaseAccountConfigurations = -11, - GetUnwrappedDek = -12, - ReadReplicaFromMasterPartition = -13, - ReadReplicaFromServerPartition = -14, - MasterInitiatedProgressCoordination = -15, - GetAadGroups = -16, - GetStorageAccountSas = -17, - GetStorageServiceConfigurations = -18, - GetGraphDatabaseAccountConfiguration = -19, - GetCustomerManagedKeyStatus = -20, - GetBatchCustomerManagedKeyStatus = -21, - XPDatabaseAccountMetaData = -22, - ControllerBatchAutoscaleRUsConsumption = -23, - ControllerBatchGetAutoscaleAggregateOutput = -24, - GetDekProperties = -25, -#endif - } - - internal static class OperationTypeExtensions - { - private static readonly Dictionary OperationTypeNames = new Dictionary(); - - static OperationTypeExtensions() - { - foreach (OperationType type in Enum.GetValues(typeof(OperationType))) - { - OperationTypeExtensions.OperationTypeNames[(int)type] = type.ToString(); - } - } - - public static string ToOperationTypeString(this OperationType type) - { - return OperationTypeExtensions.OperationTypeNames[(int)type]; - } - - public static bool IsWriteOperation(this OperationType type) - { - return type == OperationType.Create || - type == OperationType.Patch || - type == OperationType.Delete || - type == OperationType.Replace || - type == OperationType.ExecuteJavaScript || - type == OperationType.BatchApply || - type == OperationType.Batch || - type == OperationType.Upsert || - type == OperationType.CompleteUserTransaction -#if !COSMOSCLIENT - || - type == OperationType.MasterInitiatedProgressCoordination || - type == OperationType.Recreate || - type == OperationType.GetSplitPoint || - type == OperationType.AbortSplit || - type == OperationType.CompleteSplit || - type == OperationType.CompleteMergeOnMaster || - type == OperationType.CompleteMergeOnTarget || - type == OperationType.PreReplaceValidation || - type == OperationType.ReportThroughputUtilization || - type == OperationType.BatchReportThroughputUtilization || - type == OperationType.OfferUpdateOperation || - type == OperationType.CompletePartitionMigration || - type == OperationType.AbortPartitionMigration || - type == OperationType.MigratePartition || - type == OperationType.ForceConfigRefresh || - type == OperationType.MasterReplaceOfferOperation || - type == OperationType.InitiateDatabaseOfferPartitionShrink || - type == OperationType.CompleteDatabaseOfferPartitionShrink || - type == OperationType.EnsureSnapshotOperation || - type == OperationType.GetSplitPoints || - type == OperationType.ForcePartitionBackup || - type == OperationType.CreateSystemSnapshot || - type == OperationType.CreateRidRangeResources || - type == OperationType.UpdateFailoverPriorityList || - type == OperationType.Pause || - type == OperationType.Resume || - type == OperationType.UpdatePartitionThroughput || - type == OperationType.Truncate -#endif - ; - } - - public static bool IsPointOperation(this OperationType type) - { - return type == OperationType.Create || - type == OperationType.Delete || - type == OperationType.Read || - type == OperationType.Patch || - type == OperationType.Upsert || - type == OperationType.Replace; - } - - public static bool IsReadOperation(this OperationType type) - { - return type == OperationType.Read || - type == OperationType.ReadFeed || - type == OperationType.Query || - type == OperationType.SqlQuery || - type == OperationType.Head || - type == OperationType.HeadFeed || - type == OperationType.MetadataCheckAccess || - type == OperationType.QueryPlan -#if !COSMOSCLIENT - || - type == OperationType.GetStorageAuthToken -#endif - ; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + + internal enum OperationType + { + // Keep in sync with RequestOperationType enum in backend native. + Invalid = -1, + Create = 0, + Patch = 1, + Read = 2, + ReadFeed = 3, + Delete = 4, + Replace = 5, +#if !COSMOSCLIENT + Pause = 6, + Resume = 7, + Stop = 8, +#endif + Execute = 9, +#if !COSMOSCLIENT + Recycle = 10, + Crash = 11, + FanoutDelete = 12, +#endif + BatchApply = 13, + SqlQuery = 14, + Query = 15, +#if !COSMOSCLIENT + BindReplica = 16, + JSQuery = 17, +#endif + Head = 18, + HeadFeed = 19, + Upsert = 20, +#if !COSMOSCLIENT + Recreate = 21, + Throttle = 22, + GetSplitPoint = 23, + PreCreateValidation = 24, + ApplyTransactionLogs = 25, + Relocate = 26, + AbortSplit = 27, + CompleteSplit = 28, + WriteValue = 29, + CompletePartitionMigration = 30, + AbortPartitionMigration = 31, + OfferUpdateOperation = 32, + OfferPreGrowValidation = 33, + BatchReportThroughputUtilization = 34, + PreReplaceValidation = 35, + MigratePartition = 36, +#endif + AddComputeGatewayRequestCharges = 37, +#if !COSMOSCLIENT + MasterReplaceOfferOperation = 38, + ProvisionedCollectionOfferUpdateOperation = 39, +#endif + Batch = 40, + QueryPlan = 41, + +#if !COSMOSCLIENT + InitiateDatabaseOfferPartitionShrink = 42, + CompleteDatabaseOfferPartitionShrink = 43, + EnsureSnapshotOperation = 44, + GetSplitPoints = 45, + // AddLogStoreCharge=46 +#endif + +#if !COSMOSCLIENT + CompleteMergeOnTarget = 47, + CompleteMergeOnMaster = 48, + AbortMergeOnTarget = 49, + AbortMergeOnMaster = 50, +#endif + +#if !COSMOSCLIENT + ForcePartitionBackup = 51, +#endif + + CompleteUserTransaction = 52, + +#if !COSMOSCLIENT + SystemOperation = 53, +#endif + MetadataCheckAccess = 54, +#if !COSMOSCLIENT + Prune = 55, + CreateSystemSnapshot = 56, +#endif + + CollectionTruncate = 57, + +#if !COSMOSCLIENT + UpdateFailoverPriorityList = 58, +#endif + +#if !COSMOSCLIENT + GetStorageAuthToken = 59, + CreateClientEncryptionKey = 60, + ReplaceClientEncryptionKey = 61, + UpdatePartitionThroughput = 62, + + // Operation type for recreating RidRange resources during the pitr restore of a multi master partition + CreateRidRangeResources = 64, + Truncate = 65, +#endif + + // These names make it unclear what they map to in RequestOperationType. + ExecuteJavaScript = -2, + GetConfiguration = -8, +#if !COSMOSCLIENT + ForceConfigRefresh = -3, + ReportThroughputUtilization = -4, + ServiceReservation = -5, + ControllerBatchReportCharges = -6, + ControllerBatchGetOutput = -7, + GetStorageAccountKey = -9, + GetFederationConfigurations = -10, + GetDatabaseAccountConfigurations = -11, + GetUnwrappedDek = -12, + ReadReplicaFromMasterPartition = -13, + ReadReplicaFromServerPartition = -14, + MasterInitiatedProgressCoordination = -15, + GetAadGroups = -16, + GetStorageAccountSas = -17, + GetStorageServiceConfigurations = -18, + GetGraphDatabaseAccountConfiguration = -19, + GetCustomerManagedKeyStatus = -20, + GetBatchCustomerManagedKeyStatus = -21, + XPDatabaseAccountMetaData = -22, + ControllerBatchAutoscaleRUsConsumption = -23, + ControllerBatchGetAutoscaleAggregateOutput = -24, + GetDekProperties = -25, +#endif + } + + internal static class OperationTypeExtensions + { + private static readonly Dictionary OperationTypeNames = new Dictionary(); + + static OperationTypeExtensions() + { + foreach (OperationType type in Enum.GetValues(typeof(OperationType))) + { + OperationTypeExtensions.OperationTypeNames[(int)type] = type.ToString(); + } + } + + public static string ToOperationTypeString(this OperationType type) + { + return OperationTypeExtensions.OperationTypeNames[(int)type]; + } + + public static bool IsWriteOperation(this OperationType type) + { + return type == OperationType.Create || + type == OperationType.Patch || + type == OperationType.Delete || + type == OperationType.Replace || + type == OperationType.ExecuteJavaScript || + type == OperationType.BatchApply || + type == OperationType.Batch || + type == OperationType.Upsert || + type == OperationType.CompleteUserTransaction +#if !COSMOSCLIENT + || + type == OperationType.MasterInitiatedProgressCoordination || + type == OperationType.Recreate || + type == OperationType.GetSplitPoint || + type == OperationType.AbortSplit || + type == OperationType.CompleteSplit || + type == OperationType.CompleteMergeOnMaster || + type == OperationType.CompleteMergeOnTarget || + type == OperationType.PreReplaceValidation || + type == OperationType.ReportThroughputUtilization || + type == OperationType.BatchReportThroughputUtilization || + type == OperationType.OfferUpdateOperation || + type == OperationType.CompletePartitionMigration || + type == OperationType.AbortPartitionMigration || + type == OperationType.MigratePartition || + type == OperationType.ForceConfigRefresh || + type == OperationType.MasterReplaceOfferOperation || + type == OperationType.InitiateDatabaseOfferPartitionShrink || + type == OperationType.CompleteDatabaseOfferPartitionShrink || + type == OperationType.EnsureSnapshotOperation || + type == OperationType.GetSplitPoints || + type == OperationType.ForcePartitionBackup || + type == OperationType.CreateSystemSnapshot || + type == OperationType.CreateRidRangeResources || + type == OperationType.UpdateFailoverPriorityList || + type == OperationType.Pause || + type == OperationType.Resume || + type == OperationType.UpdatePartitionThroughput || + type == OperationType.Truncate +#endif + ; + } + + public static bool IsPointOperation(this OperationType type) + { + return type == OperationType.Create || + type == OperationType.Delete || + type == OperationType.Read || + type == OperationType.Patch || + type == OperationType.Upsert || + type == OperationType.Replace; + } + + public static bool IsReadOperation(this OperationType type) + { + return type == OperationType.Read || + type == OperationType.ReadFeed || + type == OperationType.Query || + type == OperationType.SqlQuery || + type == OperationType.Head || + type == OperationType.HeadFeed || + type == OperationType.MetadataCheckAccess || + type == OperationType.QueryPlan +#if !COSMOSCLIENT + || + type == OperationType.GetStorageAuthToken +#endif + ; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionAddressInformation.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionAddressInformation.cs index 225b2a644e..50b73a02a3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionAddressInformation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionAddressInformation.cs @@ -1,100 +1,100 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Linq; - using Microsoft.Azure.Documents.Client; - - internal sealed class PartitionAddressInformation : IEquatable - { - private static readonly int AllProtocolsCount = Enum.GetNames(typeof(Protocol)).Length; - private readonly PerProtocolPartitionAddressInformation[] perProtocolAddressInformation; - private readonly Lazy generateHashCode; - - public IReadOnlyList AllAddresses { get; } - - public bool IsLocalRegion { get; set; } - - public PartitionAddressInformation(IReadOnlyList replicaAddresses) - : this(replicaAddresses, false) - { - - } - - public PartitionAddressInformation( - IReadOnlyList replicaAddresses, - bool inNetworkRequest) - { - if (replicaAddresses == null) - { - throw new ArgumentNullException(nameof(replicaAddresses)); - } - - // Verify the list is sorted. If not sort it. - for(int i = 1; i < replicaAddresses.Count; i++) - { - if(replicaAddresses[i-1].CompareTo(replicaAddresses[i]) > 0) - { - AddressInformation[] clone = replicaAddresses.ToArray(); - Array.Sort(clone); - replicaAddresses = clone; - break; - } - } - - this.AllAddresses = replicaAddresses; - this.generateHashCode = new Lazy(() => - { - int hashCode = 17; - foreach (AddressInformation replicaAddress in this.AllAddresses) - { - hashCode = (hashCode * 397) ^ replicaAddress.GetHashCode(); - } - return hashCode; - }); - - this.perProtocolAddressInformation = new PerProtocolPartitionAddressInformation[PartitionAddressInformation.AllProtocolsCount]; - foreach (Protocol protocol in (Protocol[])Enum.GetValues(typeof(Protocol))) - { - this.perProtocolAddressInformation[(int)protocol] = - new PerProtocolPartitionAddressInformation(protocol, this.AllAddresses); - } - - this.IsLocalRegion = inNetworkRequest; - } - - public Uri GetPrimaryUri(DocumentServiceRequest request, Protocol protocol) - { - return this.perProtocolAddressInformation[(int)protocol].GetPrimaryAddressUri(request).Uri; - } - - public PerProtocolPartitionAddressInformation Get(Protocol protocol) - { - return this.perProtocolAddressInformation[(int)protocol]; - } - - public override int GetHashCode() - { - return this.generateHashCode.Value; - } - - public bool Equals(PartitionAddressInformation other) - { - if (other == null) - { - return false; - } - - if (this.AllAddresses.Count != other.AllAddresses.Count) - { - return false; - } - - return this.GetHashCode() == other.GetHashCode(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Documents.Client; + + internal sealed class PartitionAddressInformation : IEquatable + { + private static readonly int AllProtocolsCount = Enum.GetNames(typeof(Protocol)).Length; + private readonly PerProtocolPartitionAddressInformation[] perProtocolAddressInformation; + private readonly Lazy generateHashCode; + + public IReadOnlyList AllAddresses { get; } + + public bool IsLocalRegion { get; set; } + + public PartitionAddressInformation(IReadOnlyList replicaAddresses) + : this(replicaAddresses, false) + { + + } + + public PartitionAddressInformation( + IReadOnlyList replicaAddresses, + bool inNetworkRequest) + { + if (replicaAddresses == null) + { + throw new ArgumentNullException(nameof(replicaAddresses)); + } + + // Verify the list is sorted. If not sort it. + for(int i = 1; i < replicaAddresses.Count; i++) + { + if(replicaAddresses[i-1].CompareTo(replicaAddresses[i]) > 0) + { + AddressInformation[] clone = replicaAddresses.ToArray(); + Array.Sort(clone); + replicaAddresses = clone; + break; + } + } + + this.AllAddresses = replicaAddresses; + this.generateHashCode = new Lazy(() => + { + int hashCode = 17; + foreach (AddressInformation replicaAddress in this.AllAddresses) + { + hashCode = (hashCode * 397) ^ replicaAddress.GetHashCode(); + } + return hashCode; + }); + + this.perProtocolAddressInformation = new PerProtocolPartitionAddressInformation[PartitionAddressInformation.AllProtocolsCount]; + foreach (Protocol protocol in (Protocol[])Enum.GetValues(typeof(Protocol))) + { + this.perProtocolAddressInformation[(int)protocol] = + new PerProtocolPartitionAddressInformation(protocol, this.AllAddresses); + } + + this.IsLocalRegion = inNetworkRequest; + } + + public Uri GetPrimaryUri(DocumentServiceRequest request, Protocol protocol) + { + return this.perProtocolAddressInformation[(int)protocol].GetPrimaryAddressUri(request).Uri; + } + + public PerProtocolPartitionAddressInformation Get(Protocol protocol) + { + return this.perProtocolAddressInformation[(int)protocol]; + } + + public override int GetHashCode() + { + return this.generateHashCode.Value; + } + + public bool Equals(PartitionAddressInformation other) + { + if (other == null) + { + return false; + } + + if (this.AllAddresses.Count != other.AllAddresses.Count) + { + return false; + } + + return this.GetHashCode() == other.GetHashCode(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionIsMigratingException.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionIsMigratingException.cs index 2877e2df29..e54ca6ebbb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionIsMigratingException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionIsMigratingException.cs @@ -1,83 +1,83 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Collections; - - /// - /// This exception is thrown when DocumentServiceRequest reaches partition which is being migrated - /// and was made unavailable for reads/writes. - /// - /// Gateway/SDK can transparently refresh routing map and retry after some delay. - /// - [Serializable] - internal sealed class PartitionIsMigratingException : DocumentClientException - { - public PartitionIsMigratingException() - : this(RMResources.Gone) - { - - } - - public PartitionIsMigratingException(string message) - : this(message, (Exception)null, null) - { - } - - public PartitionIsMigratingException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - } - - public PartitionIsMigratingException(string message, Exception innerException) - : this(message, innerException, null) - { - } - - public PartitionIsMigratingException(Exception innerException) - : this(RMResources.Gone, innerException, null) - { - } - - public PartitionIsMigratingException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - - public PartitionIsMigratingException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - -#if !NETSTANDARD16 - private PartitionIsMigratingException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.Gone) - { - SetSubstatus(); - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.PartitionMigrating; - } - - private void SetSubstatus() - { - this.Headers[WFConstants.BackendHeaders.SubStatus] = - ((uint)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Collections; + + /// + /// This exception is thrown when DocumentServiceRequest reaches partition which is being migrated + /// and was made unavailable for reads/writes. + /// + /// Gateway/SDK can transparently refresh routing map and retry after some delay. + /// + [Serializable] + internal sealed class PartitionIsMigratingException : DocumentClientException + { + public PartitionIsMigratingException() + : this(RMResources.Gone) + { + + } + + public PartitionIsMigratingException(string message) + : this(message, (Exception)null, null) + { + } + + public PartitionIsMigratingException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + } + + public PartitionIsMigratingException(string message, Exception innerException) + : this(message, innerException, null) + { + } + + public PartitionIsMigratingException(Exception innerException) + : this(RMResources.Gone, innerException, null) + { + } + + public PartitionIsMigratingException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + + public PartitionIsMigratingException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + +#if !NETSTANDARD16 + private PartitionIsMigratingException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.Gone) + { + SetSubstatus(); + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.PartitionMigrating; + } + + private void SetSubstatus() + { + this.Headers[WFConstants.BackendHeaders.SubStatus] = + ((uint)SubStatusCodes.CompletingPartitionMigration).ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKey.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKey.cs index 6798c20781..8bebc441b1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKey.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKey.cs @@ -1,177 +1,177 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using Microsoft.Azure.Documents.Routing; - - /// - /// Represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class PartitionKey - { - /// - /// Instantiate a new instance of the object. - /// - /// - /// Private constructor used internal to create an instance from a JSON string. - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - private PartitionKey() - { - } - - /// - /// Instantiate a new instance of the object. - /// - /// - /// The value of the document property that is specified as the partition key when a collection is created. - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - public PartitionKey(object keyValue) - { - this.InternalKey = PartitionKeyInternal.FromObject(keyValue, true); - } - - /// - /// Instantiate a new instance of the object. - /// - /// - /// Values of the document property that are specified as partition keys when a collection is created. - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - internal PartitionKey(object[] keyValues) - { - this.InternalKey = PartitionKeyInternal.FromObjectArray( keyValues ?? new object[] { null }, true); - } - - /// - /// Instantiate a new instance of the object. - /// - /// - /// The value of the document property that is specified as the partition key - /// when a collection is created, in serialized JSON form. - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - public static PartitionKey FromJsonString(string keyValue) - { - if (string.IsNullOrEmpty(keyValue)) - { - throw new ArgumentException("keyValue must not be null or empty."); - } - - return new PartitionKey { InternalKey = PartitionKeyInternal.FromJsonString(keyValue) }; - } - - /// - /// Instantiates a new instance of the object. - /// - /// - /// The returned object represents a partition key value that allows creating and accessing documents - /// without a value for partition key - /// - public static PartitionKey None => new PartitionKey { InternalKey = PartitionKeyInternal.None }; - - /// - /// The tag name to use in the documents for specifying a partition key value - /// when inserting such documents into a migrated collection - /// - public const string SystemKeyName = "_partitionKey"; - - /// - /// The partition key path in the collection definition for migrated collections - /// - public const string SystemKeyPath = "/_partitionKey"; - - /// - /// Instantiate a new instance of the object. - /// - /// - /// The value of the document property that is specified as the partition key - /// when a collection is created, in PartitionKeyInternal format. - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - internal static PartitionKey FromInternalKey(PartitionKeyInternal keyValue) - { - if (keyValue == null) - { - throw new ArgumentException("keyValue must not be null or empty."); - } - - return new PartitionKey { InternalKey = keyValue }; - } - - - /// - /// Gets the internal object; - /// - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - internal PartitionKeyInternal InternalKey { get; private set; } - - /// - /// Override the base ToString method to output the value of each key component, separated by a space. - /// - /// The string representation of all the key component values. - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - public override string ToString() - { - return this.InternalKey.ToJsonString(); - } - - /// - /// Overrides the Equal operator for object comparisons between two instances of . - /// - /// The object to compare with. - /// True if two object instance are considered equal. - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - public override bool Equals(object other) - { - if (object.ReferenceEquals(null, other)) - { - return false; - } - - if (object.ReferenceEquals(this, other)) - { - return true; - } - - PartitionKey otherKey = other as PartitionKey; - return otherKey != null && this.InternalKey.Equals(otherKey.InternalKey); - } - - /// - /// Hash function to return the hash code for the object. - /// - /// The hash code for this instance - /// - /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. - /// - public override int GetHashCode() - { - return this.InternalKey != null ? this.InternalKey.GetHashCode() : base.GetHashCode(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using Microsoft.Azure.Documents.Routing; + + /// + /// Represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class PartitionKey + { + /// + /// Instantiate a new instance of the object. + /// + /// + /// Private constructor used internal to create an instance from a JSON string. + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + private PartitionKey() + { + } + + /// + /// Instantiate a new instance of the object. + /// + /// + /// The value of the document property that is specified as the partition key when a collection is created. + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + public PartitionKey(object keyValue) + { + this.InternalKey = PartitionKeyInternal.FromObject(keyValue, true); + } + + /// + /// Instantiate a new instance of the object. + /// + /// + /// Values of the document property that are specified as partition keys when a collection is created. + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + internal PartitionKey(object[] keyValues) + { + this.InternalKey = PartitionKeyInternal.FromObjectArray( keyValues ?? new object[] { null }, true); + } + + /// + /// Instantiate a new instance of the object. + /// + /// + /// The value of the document property that is specified as the partition key + /// when a collection is created, in serialized JSON form. + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + public static PartitionKey FromJsonString(string keyValue) + { + if (string.IsNullOrEmpty(keyValue)) + { + throw new ArgumentException("keyValue must not be null or empty."); + } + + return new PartitionKey { InternalKey = PartitionKeyInternal.FromJsonString(keyValue) }; + } + + /// + /// Instantiates a new instance of the object. + /// + /// + /// The returned object represents a partition key value that allows creating and accessing documents + /// without a value for partition key + /// + public static PartitionKey None => new PartitionKey { InternalKey = PartitionKeyInternal.None }; + + /// + /// The tag name to use in the documents for specifying a partition key value + /// when inserting such documents into a migrated collection + /// + public const string SystemKeyName = "_partitionKey"; + + /// + /// The partition key path in the collection definition for migrated collections + /// + public const string SystemKeyPath = "/_partitionKey"; + + /// + /// Instantiate a new instance of the object. + /// + /// + /// The value of the document property that is specified as the partition key + /// when a collection is created, in PartitionKeyInternal format. + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + internal static PartitionKey FromInternalKey(PartitionKeyInternal keyValue) + { + if (keyValue == null) + { + throw new ArgumentException("keyValue must not be null or empty."); + } + + return new PartitionKey { InternalKey = keyValue }; + } + + + /// + /// Gets the internal object; + /// + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + internal PartitionKeyInternal InternalKey { get; private set; } + + /// + /// Override the base ToString method to output the value of each key component, separated by a space. + /// + /// The string representation of all the key component values. + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + public override string ToString() + { + return this.InternalKey.ToJsonString(); + } + + /// + /// Overrides the Equal operator for object comparisons between two instances of . + /// + /// The object to compare with. + /// True if two object instance are considered equal. + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + public override bool Equals(object other) + { + if (object.ReferenceEquals(null, other)) + { + return false; + } + + if (object.ReferenceEquals(this, other)) + { + return true; + } + + PartitionKey otherKey = other as PartitionKey; + return otherKey != null && this.InternalKey.Equals(otherKey.InternalKey); + } + + /// + /// Hash function to return the hash code for the object. + /// + /// The hash code for this instance + /// + /// This class represents a partition key value that identifies the target partition of a collection in the Azure Cosmos DB service. + /// + public override int GetHashCode() + { + return this.InternalKey != null ? this.InternalKey.GetHashCode() : base.GetHashCode(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyComponentType.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyComponentType.cs index e5a6333e76..097f7000dc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyComponentType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyComponentType.cs @@ -1,38 +1,38 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - /// - /// Types of partition key component - /// - /// - /// Some of the values might not be used, but this class to be consistent with the backend enum - /// - internal enum PartitionKeyComponentType - { - Undefined = 0x0, - Null = 0x1, - False = 0x2, - True = 0x3, - MinNumber = 0x4, - Number = 0x5, - MaxNumber = 0x6, - MinString = 0x7, - String = 0x8, - MaxString = 0x9, - Int64 = 0xA, - Int32 = 0xB, - Int16 = 0xC, - Int8 = 0xD, - Uint64 = 0xE, - Uint32 = 0xF, - Uint16 = 0x10, - Uint8 = 0x11, - Binary = 0x12, - Guid = 0x13, - Float = 0x14, - Infinity = 0xFF, - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + /// + /// Types of partition key component + /// + /// + /// Some of the values might not be used, but this class to be consistent with the backend enum + /// + internal enum PartitionKeyComponentType + { + Undefined = 0x0, + Null = 0x1, + False = 0x2, + True = 0x3, + MinNumber = 0x4, + Number = 0x5, + MaxNumber = 0x6, + MinString = 0x7, + String = 0x8, + MaxString = 0x9, + Int64 = 0xA, + Int32 = 0xB, + Int16 = 0xC, + Int8 = 0xD, + Uint64 = 0xE, + Uint32 = 0xF, + Uint16 = 0x10, + Uint8 = 0x11, + Binary = 0x12, + Guid = 0x13, + Float = 0x14, + Infinity = 0xFF, + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinition.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinition.cs index 274ab04749..225f687cdc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinition.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinition.cs @@ -1,164 +1,164 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Linq; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Specifies a partition key definition for a particular path in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class PartitionKeyDefinition : JsonSerializable - { - private Collection paths; - - private PartitionKind? kind; - - /// - /// Gets or sets the paths to be partitioned in the Azure Cosmos DB service. - /// - /// - /// The path to be partitioned. - /// - [JsonProperty(PropertyName = Constants.Properties.Paths)] - public Collection Paths - { - get - { - // Thread safe initialization. Collection is cached and PartitionKey can be looked up from multiple threads. - if (this.paths == null) - { - this.paths = base.GetValue>(Constants.Properties.Paths) ?? new Collection(); - } - - return this.paths; - } - set - { - this.paths = value; - base.SetValue(Constants.Properties.Paths, value); - } - } - - /// - /// Gets or sets the kind of partitioning to be applied in the Azure Cosmos DB service. - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.PartitionKind)] - [JsonConverter(typeof(StringEnumConverter))] - internal PartitionKind Kind - { - get - { - if (!this.kind.HasValue) - { - this.kind = base.GetValue(Constants.Properties.PartitionKind, PartitionKind.Hash); - } - - return this.kind.Value; - } - set - { - this.kind = null; - base.SetValue(Constants.Properties.PartitionKind, value.ToString()); - } - } - - /// - /// Gets or sets version of the partitioning scheme to be applied on the partition key - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.PartitionKeyDefinitionVersion, DefaultValueHandling = DefaultValueHandling.Ignore )] - public PartitionKeyDefinitionVersion? Version - { - get - { - return (PartitionKeyDefinitionVersion?)base.GetValue(Constants.Properties.PartitionKeyDefinitionVersion); - } - set - { - base.SetValue(Constants.Properties.PartitionKeyDefinitionVersion, (int?)value); - } - } - - /// - /// Gets whether the partition key definition in the collection is system inserted key - /// in the Azure Cosmos DB service. - /// - /// - /// - [JsonProperty(PropertyName = Constants.Properties.SystemKey, DefaultValueHandling = DefaultValueHandling.Ignore)] - internal bool? IsSystemKey - { - get - { - return base.GetValue(Constants.Properties.SystemKey); - } - set - { - base.SetValue(Constants.Properties.SystemKey, value); - } - } - - internal override void OnSave() - { - if (this.paths != null) - { - base.SetValue(Constants.Properties.Paths, this.paths); - } - - if (this.kind != null) - { - base.SetValue(Constants.Properties.PartitionKind, this.kind.ToString()); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.PartitionKeyDefinitionVersion); - base.GetValue>(Constants.Properties.Paths); - } - - internal static bool AreEquivalent( - PartitionKeyDefinition pkd1, - PartitionKeyDefinition pkd2) - { - if (pkd1.Kind != pkd2.Kind) - { - return false; - } - - if (pkd1.Version != pkd2.Version) - { - return false; - } - - if (!pkd1.Paths.OrderBy(i => i).SequenceEqual(pkd2.Paths.OrderBy(i => i))) - { - return false; - } - - if (pkd1.IsSystemKey != pkd2.IsSystemKey) - { - return false; - } - - return true; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Linq; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Specifies a partition key definition for a particular path in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class PartitionKeyDefinition : JsonSerializable + { + private Collection paths; + + private PartitionKind? kind; + + /// + /// Gets or sets the paths to be partitioned in the Azure Cosmos DB service. + /// + /// + /// The path to be partitioned. + /// + [JsonProperty(PropertyName = Constants.Properties.Paths)] + public Collection Paths + { + get + { + // Thread safe initialization. Collection is cached and PartitionKey can be looked up from multiple threads. + if (this.paths == null) + { + this.paths = base.GetValue>(Constants.Properties.Paths) ?? new Collection(); + } + + return this.paths; + } + set + { + this.paths = value; + base.SetValue(Constants.Properties.Paths, value); + } + } + + /// + /// Gets or sets the kind of partitioning to be applied in the Azure Cosmos DB service. + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.PartitionKind)] + [JsonConverter(typeof(StringEnumConverter))] + internal PartitionKind Kind + { + get + { + if (!this.kind.HasValue) + { + this.kind = base.GetValue(Constants.Properties.PartitionKind, PartitionKind.Hash); + } + + return this.kind.Value; + } + set + { + this.kind = null; + base.SetValue(Constants.Properties.PartitionKind, value.ToString()); + } + } + + /// + /// Gets or sets version of the partitioning scheme to be applied on the partition key + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.PartitionKeyDefinitionVersion, DefaultValueHandling = DefaultValueHandling.Ignore )] + public PartitionKeyDefinitionVersion? Version + { + get + { + return (PartitionKeyDefinitionVersion?)base.GetValue(Constants.Properties.PartitionKeyDefinitionVersion); + } + set + { + base.SetValue(Constants.Properties.PartitionKeyDefinitionVersion, (int?)value); + } + } + + /// + /// Gets whether the partition key definition in the collection is system inserted key + /// in the Azure Cosmos DB service. + /// + /// + /// + [JsonProperty(PropertyName = Constants.Properties.SystemKey, DefaultValueHandling = DefaultValueHandling.Ignore)] + internal bool? IsSystemKey + { + get + { + return base.GetValue(Constants.Properties.SystemKey); + } + set + { + base.SetValue(Constants.Properties.SystemKey, value); + } + } + + internal override void OnSave() + { + if (this.paths != null) + { + base.SetValue(Constants.Properties.Paths, this.paths); + } + + if (this.kind != null) + { + base.SetValue(Constants.Properties.PartitionKind, this.kind.ToString()); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.PartitionKeyDefinitionVersion); + base.GetValue>(Constants.Properties.Paths); + } + + internal static bool AreEquivalent( + PartitionKeyDefinition pkd1, + PartitionKeyDefinition pkd2) + { + if (pkd1.Kind != pkd2.Kind) + { + return false; + } + + if (pkd1.Version != pkd2.Version) + { + return false; + } + + if (!pkd1.Paths.SequenceEqual(pkd2.Paths)) + { + return false; + } + + if (pkd1.IsSystemKey != pkd2.IsSystemKey) + { + return false; + } + + return true; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinitionVersion.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinitionVersion.cs index b0e408df54..bc0c0b4d7d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinitionVersion.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyDefinitionVersion.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Partitioning version. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum PartitionKeyDefinitionVersion - { - /// - /// Hash partitioning scheme optimized for partition keys that are up to 100 bytes size. - /// - V1 = 1, - - /// - /// Enhanced version of hash partitioning scheme, which supports partition key up to 2KB size. This is the - /// preferred hash function for partition keys with high cardinality. - /// - /// Collections created with V2 version can only be accessed from version 1.18 and above. - V2 = 2, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Partitioning version. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum PartitionKeyDefinitionVersion + { + /// + /// Hash partitioning scheme optimized for partition keys that are up to 100 bytes size. + /// + V1 = 1, + + /// + /// Enhanced version of hash partitioning scheme, which supports partition key up to 2KB size. This is the + /// preferred hash function for partition keys with high cardinality. + /// + /// Collections created with V2 version can only be accessed from version 1.18 and above. + V2 = 2, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs index daa3cd144b..b44069fbf8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs @@ -1,1113 +1,1113 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text; - using Microsoft.Azure.Documents.SharedFiles.Routing; - - using Newtonsoft.Json; - - /// - /// Schema-less Partition Key value. - /// - [JsonConverter(typeof(PartitionKeyInternalJsonConverter))] - [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] - internal sealed class PartitionKeyInternal : IComparable, IEquatable, ICloneable - { - private readonly IReadOnlyList components; - - private static readonly PartitionKeyInternal NonePartitionKey = new PartitionKeyInternal(); - private static readonly PartitionKeyInternal EmptyPartitionKey = new PartitionKeyInternal(new IPartitionKeyComponent[] { }); - private static readonly PartitionKeyInternal InfinityPartitionKey = new PartitionKeyInternal(new[] { new InfinityPartitionKeyComponent() }); - private static readonly PartitionKeyInternal UndefinedPartitionKey = new PartitionKeyInternal(new[] { new UndefinedPartitionKeyComponent() }); - - private const int MaxPartitionKeyBinarySize = ( - 1 /*type marker */ + 9 /* hash value*/ + - 1 /* type marker*/ + StringPartitionKeyComponent.MaxStringBytesToAppend + 1 /*trailing zero*/) * 3; - - private static readonly Int128 MaxHashV2Value = new Int128(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F }); - - public static readonly string MinimumInclusiveEffectivePartitionKey = ToHexEncodedBinaryString(new IPartitionKeyComponent[0]); - - public static readonly string MaximumExclusiveEffectivePartitionKey = ToHexEncodedBinaryString(new[] { new InfinityPartitionKeyComponent() }); - - private static readonly Int32 HashV2EPKLength = 32; // UInt128.Length * 2 (UInt128 gives 16 bytes as output, each byte takes 2 chars after hex-encoding) - - private static readonly JsonSerializer FromJsonStringSerializer = - JsonSerializer.CreateDefault( - new JsonSerializerSettings - { - DateParseHandling = DateParseHandling.None, - MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr - }); - - private static readonly JsonSerializer ToJsonStringSerializer = - JsonSerializer.CreateDefault( - new JsonSerializerSettings - { - StringEscapeHandling = StringEscapeHandling.EscapeNonAscii, - Formatting = Formatting.None, - MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr - }); - - public static PartitionKeyInternal InclusiveMinimum - { - get - { - return PartitionKeyInternal.EmptyPartitionKey; - } - } - - public static PartitionKeyInternal ExclusiveMaximum - { - get - { - return PartitionKeyInternal.InfinityPartitionKey; - } - } - - public static PartitionKeyInternal Empty - { - get - { - return PartitionKeyInternal.EmptyPartitionKey; - } - } - - public static PartitionKeyInternal None - { - get - { - return PartitionKeyInternal.NonePartitionKey; - } - } - - public static PartitionKeyInternal Undefined - { - get - { - return PartitionKeyInternal.UndefinedPartitionKey; - } - } - - public IReadOnlyList Components - { - get - { - return this.components; - } - } - - private PartitionKeyInternal() - { - this.components = null; - } - - public PartitionKeyInternal(IReadOnlyList values) - { - if (values == null) - { - throw new ArgumentNullException("values"); - } - - this.components = values; - } - - /// - /// Constructs instance of from enumerable of objects. - /// - /// Partition key component values. - /// If this is false, unsupported component values will be repliaced with 'Undefined'. If this is true, exception will be thrown. - /// Instance of . - public static PartitionKeyInternal FromObjectArray(IEnumerable values, bool strict) - { - if (values == null) - { - throw new ArgumentNullException("values"); - } - - List components = new List(); - foreach (object value in values) - { - components.Add(PartitionKeyInternal.FromObjectToPartitionKeyComponent(value, strict)); - } - - return new PartitionKeyInternal(components); - } - - /// - /// Constructs instance of from single object. - /// - /// Partition key component value. - /// If this is false, unsupported component values will be repliaced with 'Undefined'. If this is true, exception will be thrown. - /// Instance of . - public static PartitionKeyInternal FromObject(object value, bool strict) - { - List components = new List(1) - { - PartitionKeyInternal.FromObjectToPartitionKeyComponent(value, strict) - }; - - return new PartitionKeyInternal(components); - } - - public object[] ToObjectArray() - { - return this.Components.Select(component => component.ToObject()).ToArray(); - } - - public static PartitionKeyInternal FromJsonString(string partitionKey) - { - if (string.IsNullOrWhiteSpace(partitionKey)) - { - throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, partitionKey)); - } - - using (StringReader stringReader = new StringReader(partitionKey)) - using (JsonTextReader jsonReader = new JsonTextReader(stringReader)) - { - return FromJsonStringSerializer.Deserialize(jsonReader); - } - } - - public string ToJsonString() - { - using (StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture)) - { - using (JsonTextWriter jsonWriter = new JsonTextWriter(stringWriter)) - { - ToJsonStringSerializer.Serialize(jsonWriter, this, objectType: null); - } - - return stringWriter.ToString(); - } - } - - public bool Contains(PartitionKeyInternal nestedPartitionKey) - { - if (this.Components.Count > nestedPartitionKey.Components.Count) - { - return false; - } - - for (int i = 0; i < this.Components.Count; i++) - { - if (this.Components[i].CompareTo(nestedPartitionKey.Components[i]) != 0) - { - return false; - } - } - - return true; - } - - public static PartitionKeyInternal Max(PartitionKeyInternal key1, PartitionKeyInternal key2) - { - if (key1 == null) return key2; - if (key2 == null) return key1; - - return key1.CompareTo(key2) >= 0 ? key1 : key2; - } - - public static PartitionKeyInternal Min(PartitionKeyInternal key1, PartitionKeyInternal key2) - { - if (key1 == null) return key2; - if (key2 == null) return key1; - - return key1.CompareTo(key2) <= 0 ? key1 : key2; - } - - public static string GetMinInclusiveEffectivePartitionKey( - int partitionIndex, - int partitionCount, - PartitionKeyDefinition partitionKeyDefinition, - bool useHashV2asDefault = false) - { - if (partitionKeyDefinition.Paths.Count > 0 && !(partitionKeyDefinition.Kind == PartitionKind.Hash || partitionKeyDefinition.Kind == PartitionKind.MultiHash)) - { - throw new NotImplementedException("Cannot figure out range boundaries"); - } - - if (partitionCount <= 0) - { - throw new ArgumentException("Invalid partition count", "partitionCount"); - } - - if (partitionIndex < 0 || partitionIndex >= partitionCount) - { - throw new ArgumentException("Invalid partition index", "partitionIndex"); - } - - if (partitionIndex == 0) - { - return PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey; - } - - switch (partitionKeyDefinition.Kind) - { - case PartitionKind.Hash: - PartitionKeyDefinitionVersion defaultPartitionKeyDefinitionVersion = useHashV2asDefault ? PartitionKeyDefinitionVersion.V2 : PartitionKeyDefinitionVersion.V1; - switch (partitionKeyDefinition.Version ?? defaultPartitionKeyDefinitionVersion) - { - case PartitionKeyDefinitionVersion.V2: - Int128 val = MaxHashV2Value / partitionCount * partitionIndex; - byte[] bytes = val.Bytes; - Array.Reverse(bytes); - return HexConvert.ToHex(bytes, 0, bytes.Length); - - case PartitionKeyDefinitionVersion.V1: - return ToHexEncodedBinaryString( - new IPartitionKeyComponent[] - { new NumberPartitionKeyComponent(uint.MaxValue / partitionCount * partitionIndex) }); - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - - case PartitionKind.MultiHash: - Int128 max_val = MaxHashV2Value / partitionCount * partitionIndex; - byte[] max_bytes = max_val.Bytes; - Array.Reverse(max_bytes); - return HexConvert.ToHex(max_bytes, 0, max_bytes.Length); - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionKind"); - } - } - - public static string GetMaxExclusiveEffectivePartitionKey( - int partitionIndex, - int partitionCount, - PartitionKeyDefinition partitionKeyDefinition, - bool useHashV2asDefault = false) - { - if (partitionKeyDefinition.Paths.Count > 0 && !(partitionKeyDefinition.Kind == PartitionKind.Hash || partitionKeyDefinition.Kind == PartitionKind.MultiHash)) - { - throw new NotImplementedException("Cannot figure out range boundaries"); - } - - if (partitionCount <= 0) - { - throw new ArgumentException("Invalid partition count", "partitionCount"); - } - - if (partitionIndex < 0 || partitionIndex >= partitionCount) - { - throw new ArgumentException("Invalid partition index", "partitionIndex"); - } - - if (partitionIndex == partitionCount - 1) - { - return PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; - } - - PartitionKeyDefinitionVersion defaultPartitionKeyDefinitionVersion = useHashV2asDefault ? PartitionKeyDefinitionVersion.V2 : PartitionKeyDefinitionVersion.V1; - switch (partitionKeyDefinition.Kind) - { - case PartitionKind.Hash: - switch (partitionKeyDefinition.Version ?? defaultPartitionKeyDefinitionVersion) - { - case PartitionKeyDefinitionVersion.V2: - Int128 val = MaxHashV2Value / partitionCount * (partitionIndex + 1); - byte[] bytes = val.Bytes; - Array.Reverse(bytes); - return HexConvert.ToHex(bytes, 0, bytes.Length); - - case PartitionKeyDefinitionVersion.V1: - return ToHexEncodedBinaryString(new IPartitionKeyComponent[] { new NumberPartitionKeyComponent(uint.MaxValue / partitionCount * (partitionIndex + 1)) }); - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - - case PartitionKind.MultiHash: - - Int128 max_val = MaxHashV2Value / partitionCount * (partitionIndex + 1); - byte[] max_bytes = max_val.Bytes; - Array.Reverse(max_bytes); - return HexConvert.ToHex(max_bytes, 0, max_bytes.Length); - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionKind"); - } - } - public int CompareTo(PartitionKeyInternal other) - { - if (other == null) - { - throw new ArgumentNullException("other"); - } - else if (other.components == null || this.components == null) - { - return Math.Sign((this.components?.Count ?? 0) - (other.components?.Count ?? 0)); - } - - for (int i = 0; i < Math.Min(this.Components.Count, other.Components.Count); i++) - { - int leftOrdinal = this.Components[i].GetTypeOrdinal(); - int rightOrdinal = other.Components[i].GetTypeOrdinal(); - if (leftOrdinal != rightOrdinal) - { - return Math.Sign(leftOrdinal - rightOrdinal); - } - - int result = this.Components[i].CompareTo(other.Components[i]); - if (result != 0) - { - return Math.Sign(result); - } - } - - return Math.Sign(this.Components.Count - other.Components.Count); - } - - public bool Equals(PartitionKeyInternal other) - { - if (object.ReferenceEquals(null, other)) - { - return false; - } - - if (object.ReferenceEquals(this, other)) - { - return true; - } - - return this.CompareTo(other) == 0; - } - - public override bool Equals(object other) - { - return this.Equals(other as PartitionKeyInternal); - } - - public override int GetHashCode() - { - unchecked - { - return this.Components.Aggregate(0, (current, value) => (current * 397) ^ value.GetHashCode()); - } - } - - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } - - - public object Clone() - { - return new PartitionKeyInternal(this.Components); - } - - private static IPartitionKeyComponent FromObjectToPartitionKeyComponent(object value, bool strict) - { - switch (value) - { - case null: - return NullPartitionKeyComponent.Value; - case Undefined _: - return UndefinedPartitionKeyComponent.Value; - case bool b: - return new BoolPartitionKeyComponent(b); - case string s: - return new StringPartitionKeyComponent(s); - case sbyte _: - case byte _: - case short _: - case ushort _: - case int _: - case uint _: - case long _: - case ulong _: - case float _: - case double _: - case decimal _: - return new NumberPartitionKeyComponent(Convert.ToDouble(value, CultureInfo.InvariantCulture)); - case MinNumber _: - return MinNumberPartitionKeyComponent.Value; - case MaxNumber _: - return MaxNumberPartitionKeyComponent.Value; - case MinString _: - return MinStringPartitionKeyComponent.Value; - case MaxString _: - return MaxStringPartitionKeyComponent.Value; - } - - if (strict) - { - throw new InvalidOperationException( - string.Format(CultureInfo.InvariantCulture, RMResources.UnsupportedPartitionKeyComponentValue, value)); - } - - return UndefinedPartitionKeyComponent.Value; - } - - private static string ToHexEncodedBinaryString(IReadOnlyList components) - { - byte[] bufferBytes = new byte[MaxPartitionKeyBinarySize]; - using (MemoryStream ms = new MemoryStream(bufferBytes)) - { - using (BinaryWriter binaryWriter = new BinaryWriter(ms)) - { - for (int index = 0; index < components.Count; index++) - { - components[index].WriteForBinaryEncoding(binaryWriter); - } - - return HexConvert.ToHex(bufferBytes, 0, (int)ms.Position); - } - } - } - - /// - /// Constructs a PartitionKeyInternal from hex-encoded byte string. This is only for testing/debugging. Please do not use in actual product code. - /// - [Obsolete] - internal static PartitionKeyInternal FromHexEncodedBinaryString(string hexEncodedBinaryString) - { - List partitionKeyComponents = new List(); - byte[] byteString = PartitionKeyInternal.HexStringToByteArray(hexEncodedBinaryString); - - int offset = 0; - while (offset < byteString.Length) - { - PartitionKeyComponentType typeMarker = (PartitionKeyComponentType)Enum.Parse(typeof(PartitionKeyComponentType), byteString[offset++].ToString(CultureInfo.InvariantCulture)); - - switch (typeMarker) - { - case PartitionKeyComponentType.Undefined: - partitionKeyComponents.Add(UndefinedPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.Null: - partitionKeyComponents.Add(NullPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.False: - partitionKeyComponents.Add(new BoolPartitionKeyComponent(false)); - break; - - case PartitionKeyComponentType.True: - partitionKeyComponents.Add(new BoolPartitionKeyComponent(true)); - break; - - case PartitionKeyComponentType.MinNumber: - partitionKeyComponents.Add(MinNumberPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.MaxNumber: - partitionKeyComponents.Add(MaxNumberPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.MinString: - partitionKeyComponents.Add(MinStringPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.MaxString: - partitionKeyComponents.Add(MaxStringPartitionKeyComponent.Value); - break; - - case PartitionKeyComponentType.Infinity: - partitionKeyComponents.Add(new InfinityPartitionKeyComponent()); - break; - - case PartitionKeyComponentType.Number: - partitionKeyComponents.Add(NumberPartitionKeyComponent.FromHexEncodedBinaryString(byteString, ref offset)); - break; - - case PartitionKeyComponentType.String: - partitionKeyComponents.Add(StringPartitionKeyComponent.FromHexEncodedBinaryString(byteString, ref offset)); - break; - } - } - - return new PartitionKeyInternal(partitionKeyComponents); - } - - /// - /// Produces effective value. Azure Cosmos DB has global index on effective partition key values. - /// - /// Effective value is produced by applying is range or hash encoding to all the component values, based - /// on partition key definition. - /// - /// String components are hashed and converted to number components. - /// Number components are hashed and remain number component. - /// bool, null, undefined remain unhashed, because indexing policy doesn't specify index type for these types. - /// - public string GetEffectivePartitionKeyString(PartitionKeyDefinition partitionKeyDefinition, bool strict = true) - { - if (this.components == null) - { - throw new ArgumentException(RMResources.TooFewPartitionKeyComponents); - } - - if (this.Equals(EmptyPartitionKey)) - { - return MinimumInclusiveEffectivePartitionKey; - } - - if (this.Equals(InfinityPartitionKey)) - { - return MaximumExclusiveEffectivePartitionKey; - } - - if (this.Components.Count < partitionKeyDefinition.Paths.Count && partitionKeyDefinition.Kind != PartitionKind.MultiHash) - { - throw new ArgumentException(RMResources.TooFewPartitionKeyComponents); - } - - if (this.Components.Count > partitionKeyDefinition.Paths.Count && strict) - { - throw new ArgumentException(RMResources.TooManyPartitionKeyComponents); - } - - switch (partitionKeyDefinition.Kind) - { - case PartitionKind.Hash: - switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) - { - case PartitionKeyDefinitionVersion.V1: - return this.GetEffectivePartitionKeyForHashPartitioning(); - - case PartitionKeyDefinitionVersion.V2: - return this.GetEffectivePartitionKeyForHashPartitioningV2(); - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - case PartitionKind.MultiHash: - return this.GetEffectivePartitionKeyForMultiHashPartitioningV2(); - default: - return ToHexEncodedBinaryString(this.Components); - } - } - - private string GetEffectivePartitionKeyForHashPartitioning() - { - IPartitionKeyComponent[] truncatedComponents = this.Components.ToArray(); - - for (int i = 0; i < truncatedComponents.Length; i++) - { - truncatedComponents[i] = this.Components[i].Truncate(); - } - - double hash; - using (MemoryStream ms = new MemoryStream()) - { - using (BinaryWriter binaryWriter = new BinaryWriter(ms)) - { - for (int i = 0; i < truncatedComponents.Length; i++) - { - truncatedComponents[i].WriteForHashing(binaryWriter); - } - - hash = MurmurHash3.Hash32(ms.GetBuffer(), ms.Length); - } - } - - IPartitionKeyComponent[] partitionKeyComponents = new IPartitionKeyComponent[this.Components.Count + 1]; - partitionKeyComponents[0] = new NumberPartitionKeyComponent(hash); - for (int i = 0; i < truncatedComponents.Length; i++) - { - partitionKeyComponents[i + 1] = truncatedComponents[i]; - } - - return ToHexEncodedBinaryString(partitionKeyComponents); - } - - private string GetEffectivePartitionKeyForMultiHashPartitioningV2() - { - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - for (int i = 0; i < this.Components.Count; i++) - { - byte[] hash = null; - using (MemoryStream ms = new MemoryStream()) - using (BinaryWriter binaryWriter = new BinaryWriter(ms)) - { - this.Components[i].WriteForHashingV2(binaryWriter); - - UInt128 hash128 = MurmurHash3.Hash128(ms.GetBuffer(), (int)ms.Length, UInt128.MinValue); - hash = UInt128.ToByteArray(hash128); - Array.Reverse(hash); - - // Reset 2 most significant bits, as max exclusive value is 'FF'. - // Plus one more just in case. - hash[0] &= 0x3F; - } - - sb.Append(HexConvert.ToHex(hash, 0, hash.Length)); - } - return sb.ToString(); - } - - private string GetEffectivePartitionKeyForHashPartitioningV2() - { - byte[] hash = null; - using (MemoryStream ms = new MemoryStream()) - { - using (BinaryWriter binaryWriter = new BinaryWriter(ms)) - { - for (int i = 0; i < this.Components.Count; i++) - { - this.Components[i].WriteForHashingV2(binaryWriter); - } - - UInt128 hash128 = MurmurHash3.Hash128(ms.GetBuffer(), (int)ms.Length, UInt128.MinValue); - hash = UInt128.ToByteArray(hash128); - Array.Reverse(hash); - - // Reset 2 most significant bits, as max exclusive value is 'FF'. - // Plus one more just in case. - hash[0] &= 0x3F; - } - } - - return HexConvert.ToHex(hash, 0, hash.Length); - } - - private static byte[] HexStringToByteArray(string hex) - { - int numberChars = hex.Length; - if (numberChars % 2 != 0) - { - throw new ArgumentException("Hex string should be even length", "hex"); - } - - byte[] bytes = new byte[numberChars / 2]; - for (int i = 0; i < numberChars; i += 2) - { - bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); - } - - return bytes; - } - - internal static class HexConvert - { - private static readonly ushort[] LookupTable = CreateLookupTable(); - - private static ushort[] CreateLookupTable() - { - ushort[] lookupTable = new ushort[256]; - for (int byteValue = 0; byteValue < 256; byteValue++) - { - string byteAsHexString = byteValue.ToString("X2", CultureInfo.InvariantCulture); - - lookupTable[byteValue] = (ushort)(byteAsHexString[0] + (byteAsHexString[1] << 8)); - } - - return lookupTable; - } - - public static string ToHex(byte[] bytes, int start, int length) - { - char[] result = new char[length * 2]; - for (int i = 0; i < length; i++) - { - ushort encodedByte = LookupTable[bytes[i + start]]; - result[2 * i] = (char)(encodedByte & 0xFF); - result[2 * i + 1] = (char)(encodedByte >> 8); - } - - return new string(result); - } - } - - public static string GetMiddleRangeEffectivePartitionKey(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) => partitionKeyDefinition.Kind switch - { - PartitionKind.Hash => GetMiddleRangeEffectivePartitionKeyForHash(minInclusive, maxExclusive, partitionKeyDefinition), - PartitionKind.MultiHash => GetMiddleRangeEffectivePartitionKeyForMultiHash(minInclusive, maxExclusive, partitionKeyDefinition), - _ => throw new InternalServerErrorException($"Unexpected PartitionKey Kind {partitionKeyDefinition.Kind}. Can determine middle of range only for hash and multihash partitioning.") - }; - - private static string GetMiddleRangeEffectivePartitionKeyForHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) - { - switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) - { - case PartitionKeyDefinitionVersion.V2: - { - Int128 min = 0; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); - Array.Reverse(minBytes); - min = new Int128(minBytes); - } - - Int128 max = MaxHashV2Value; - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); - Array.Reverse(maxBytes); - max = new Int128(maxBytes); - } - - byte[] midBytes = (min + (max - min) / 2).Bytes; - Array.Reverse(midBytes); - return HexConvert.ToHex(midBytes, 0, midBytes.Length); - } - case PartitionKeyDefinitionVersion.V1: - { - long min = 0; - long max = uint.MaxValue; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - return ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent((min + max) / 2) }); - } - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - } - - private static IReadOnlyList GetHashValueFromEPKForMultiHash(string epkValueString, PartitionKeyDefinition partitionKeyDefinition) - { - IList hashes = new List(); - int pathCountInEPK = (epkValueString.Length + (HashV2EPKLength - 1))/HashV2EPKLength; - - for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) - { - if (index < pathCountInEPK) - { - int startIndexForEPK = index * HashV2EPKLength; //Offset it by the length of previously read EPK(s), - - // All EPK value lengths are HashV2EPKLength, however the end EPK value is 'FF' - // FF is a special marker which appears only as a suffix - if (epkValueString.Length - startIndexForEPK < HashV2EPKLength) - { - hashes.Add(MaxHashV2Value); - } - else - { - // Extract the EPK for nth key - string epkSubPart = epkValueString.Substring(startIndexForEPK, HashV2EPKLength); - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(epkSubPart); - Array.Reverse(maxBytes); - hashes.Add(new Int128(maxBytes)); - } - } - else // The EPK has less values than Paths.Count in the PkDef, this is empty partitionkey. - { - hashes.Add(0); - } - } - - return (IReadOnlyList)hashes; - } - - //Refer docs/design/elasticity/SubpartitioningContainerSplit.md for implementation detail - private static string GetMiddleRangeEffectivePartitionKeyForMultiHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) - { - if (partitionKeyDefinition.Version == PartitionKeyDefinitionVersion.V1) - { - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion " + partitionKeyDefinition.Version + " for MultiHash Partition kind"); - } - - IReadOnlyList minInclusiveHashValues = GetHashValueFromEPKForMultiHash(minInclusive, partitionKeyDefinition); - IReadOnlyList maxExclusiveHashValues = GetHashValueFromEPKForMultiHash(maxExclusive, partitionKeyDefinition); - IList midPointHashValues = new List(partitionKeyDefinition.Paths.Count); - - for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) - { - Int128 min = minInclusiveHashValues[index]; - Int128 max = maxExclusiveHashValues[index]; - - if (min == max || min + 1 == max) - { - midPointHashValues.Add(min); - } - else - { - /* It is possible, for Example if MinEPK, MaxEPK are [20, 40], [21, 10] respectively, - * the nMinEPKCurrentSubRange = 40 and nMaxEPKCurrentSubRange = 10 - * Since in the above step we are already setting 20 to be first level midPoint, - * for a valid second level midPoint we must look for it the range [40, HashV2Max] - */ - if (min > max) - { - max = MaxHashV2Value; - } - - Int128 midValue = (min + (max - min) / 2); - midPointHashValues.Add(midValue); - break; - } - } - - StringBuilder midPointEPKBuilder = new StringBuilder() ; - foreach (Int128 value in midPointHashValues) - { - byte[] midBytes = value.Bytes; - Array.Reverse(midBytes); - midPointEPKBuilder.Append(HexConvert.ToHex(midBytes, 0, midBytes.Length)); - } - - return midPointEPKBuilder.ToString(); - } - - public static string[] GetNEqualRangeEffectivePartitionKeys( - string minInclusive, - string maxExclusive, - PartitionKeyDefinition partitionKeyDefinition, - int numberOfSubRanges) - { - if (partitionKeyDefinition.Kind != PartitionKind.Hash) - { - throw new InvalidOperationException("Can determine " + numberOfSubRanges + " ranges only for hash partitioning."); - } - - if (numberOfSubRanges <= 0) - { - throw new InvalidOperationException("Number of sub ranges " + numberOfSubRanges + " cannot be zero or negative"); - } - - switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) - { - case PartitionKeyDefinitionVersion.V2: - { - Int128 min = 0; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); - Array.Reverse(minBytes); - min = new Int128(minBytes); - } - - Int128 max = MaxHashV2Value; - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); - Array.Reverse(maxBytes); - max = new Int128(maxBytes); - } - - if (max - min < numberOfSubRanges) - { - throw new InvalidOperationException("Insufficient range width to produce " + numberOfSubRanges + " equal sub ranges."); - } - - string[] ranges = new string[numberOfSubRanges - 1]; - for (int i = 1; i < numberOfSubRanges; i++) - { - byte[] iBytes = (min + (i * ((max - min) / numberOfSubRanges))).Bytes; - Array.Reverse(iBytes); - ranges[i - 1] = HexConvert.ToHex(iBytes, 0, iBytes.Length); - } - - return ranges; - } - case PartitionKeyDefinitionVersion.V1: - { - long min = 0; - long max = uint.MaxValue; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - if (max - min < numberOfSubRanges) - { - throw new InvalidOperationException("Insufficient range width to produce " + numberOfSubRanges + " equal sub ranges."); - } - - string[] ranges = new string[numberOfSubRanges - 1]; - for (int i = 1; i < numberOfSubRanges; i++) - { - ranges[i - 1] = ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent(min + (i * ((max - min) / numberOfSubRanges))) }); - } - - return ranges; - } - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - } - - private static double GetWidthForHashPartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) - { - //TODO: Assert a hashversion is always passed. - //switch(partitionKeyDefinition.Version) - switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) - { - case PartitionKeyDefinitionVersion.V2: - { - UInt128 min = 0; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); - Array.Reverse(minBytes); - min = UInt128.FromByteArray(minBytes); - } - - UInt128 maxHashV2Value = UInt128.FromByteArray(MaxHashV2Value.Bytes); - UInt128 max = maxHashV2Value; - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); - Array.Reverse(maxBytes); - max = UInt128.FromByteArray(maxBytes); - } - - double width = (1.0 * (max.GetHigh() - min.GetHigh())) / (maxHashV2Value.GetHigh() + 1); - return width; - } - case PartitionKeyDefinitionVersion.V1: - { - long min = 0; - long max = uint.MaxValue; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - double width = (1.0 * (max - min)) / ((long)(UInt32.MaxValue) + 1); - return width; - } - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - } - - private static double GetWidthForRangePartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) - { - throw new InternalServerErrorException("Cannot determine range width for range partitioning."); - } - - private static double GetWidthForMultiHashPartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) - { - //Extract only the first EPK from a multi-path partition key. - minInclusive = minInclusive.Substring(0, Math.Min(minInclusive.Length, HashV2EPKLength)); - maxExclusive = maxExclusive.Substring(0, Math.Min(maxExclusive.Length, HashV2EPKLength)); - - UInt128 min = 0; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); - Array.Reverse(minBytes); - min = UInt128.FromByteArray(minBytes); - } - - UInt128 maxHashV2Value = UInt128.FromByteArray(MaxHashV2Value.Bytes); - UInt128 max = maxHashV2Value; - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); - Array.Reverse(maxBytes); - max = UInt128.FromByteArray(maxBytes); - } - - double width = (1.0 * (max.GetHigh() - min.GetHigh())) / (maxHashV2Value.GetHigh() + 1); - return width; - } - - public static double GetWidth(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) => partitionKeyDefinition.Kind switch - { - PartitionKind.Hash => GetWidthForHashPartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), - PartitionKind.Range => GetWidthForRangePartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), - PartitionKind.MultiHash => GetWidthForMultiHashPartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), - _ => throw new InternalServerErrorException("Unknown PartitionKind values, cannot determine range width.") - }; - - public Range GetEPKRangeForPrefixPartitionKey(PartitionKeyDefinition partitionKeyDefinition) - { - if(partitionKeyDefinition.Kind != PartitionKind.MultiHash) - { - throw new ArgumentException(RMResources.UnsupportedPartitionDefinitionKindForPartialKeyOperations); - } - - if(this.components.Count >= partitionKeyDefinition.Paths.Count) - { - throw new ArgumentException(RMResources.TooManyPartitionKeyComponents); - } - - string minEPK = this.GetEffectivePartitionKeyString(partitionKeyDefinition, false); - string maxEPK = minEPK + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; - return new Range(minEPK, maxEPK, true, false); - } - - private static bool IsPartiallySpecifiedPartitionKeyRange( - PartitionKeyDefinition partitionKeyDefinition, - Range internalRange) - { - //To be a prefixed key, it has to be MultiHash containers with >1 partition key paths. - if (partitionKeyDefinition.Kind != PartitionKind.MultiHash || - partitionKeyDefinition.Paths.Count <= 1) - { - return false; - } - - //Prefixed key should not be fully specified - //Min and Max PartitionKeyValue, should be the same value. - //We do not expect internalRange.Min and Max to have different values - if (internalRange.Min.Components.Count == partitionKeyDefinition.Paths.Count || - internalRange.Max.Components.Count == partitionKeyDefinition.Paths.Count || - !internalRange.Min.Equals(internalRange.Max)) - { - return false; - } - - return true; - } - - public static Range GetEffectivePartitionKeyRange( - PartitionKeyDefinition partitionKeyDefinition, - Range range) - { - if (range == null) - { - throw new ArgumentNullException(nameof(range)); - } - - string minEPK = range.Min.GetEffectivePartitionKeyString(partitionKeyDefinition, false); - string maxEPK = range.Max.GetEffectivePartitionKeyString(partitionKeyDefinition, false); - - if (PartitionKeyInternal.IsPartiallySpecifiedPartitionKeyRange(partitionKeyDefinition, range)) - { - maxEPK = maxEPK + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; - } - - return new Range(minEPK, maxEPK, range.IsMinInclusive, range.IsMaxInclusive); - } - } - -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text; + using Microsoft.Azure.Documents.SharedFiles.Routing; + + using Newtonsoft.Json; + + /// + /// Schema-less Partition Key value. + /// + [JsonConverter(typeof(PartitionKeyInternalJsonConverter))] + [SuppressMessage("", "AvoidMultiLineComments", Justification = "Multi line business logic")] + internal sealed class PartitionKeyInternal : IComparable, IEquatable, ICloneable + { + private readonly IReadOnlyList components; + + private static readonly PartitionKeyInternal NonePartitionKey = new PartitionKeyInternal(); + private static readonly PartitionKeyInternal EmptyPartitionKey = new PartitionKeyInternal(new IPartitionKeyComponent[] { }); + private static readonly PartitionKeyInternal InfinityPartitionKey = new PartitionKeyInternal(new[] { new InfinityPartitionKeyComponent() }); + private static readonly PartitionKeyInternal UndefinedPartitionKey = new PartitionKeyInternal(new[] { new UndefinedPartitionKeyComponent() }); + + private const int MaxPartitionKeyBinarySize = ( + 1 /*type marker */ + 9 /* hash value*/ + + 1 /* type marker*/ + StringPartitionKeyComponent.MaxStringBytesToAppend + 1 /*trailing zero*/) * 3; + + private static readonly Int128 MaxHashV2Value = new Int128(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F }); + + public static readonly string MinimumInclusiveEffectivePartitionKey = ToHexEncodedBinaryString(new IPartitionKeyComponent[0]); + + public static readonly string MaximumExclusiveEffectivePartitionKey = ToHexEncodedBinaryString(new[] { new InfinityPartitionKeyComponent() }); + + private static readonly Int32 HashV2EPKLength = 32; // UInt128.Length * 2 (UInt128 gives 16 bytes as output, each byte takes 2 chars after hex-encoding) + + private static readonly JsonSerializer FromJsonStringSerializer = + JsonSerializer.CreateDefault( + new JsonSerializerSettings + { + DateParseHandling = DateParseHandling.None, + MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr + }); + + private static readonly JsonSerializer ToJsonStringSerializer = + JsonSerializer.CreateDefault( + new JsonSerializerSettings + { + StringEscapeHandling = StringEscapeHandling.EscapeNonAscii, + Formatting = Formatting.None, + MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr + }); + + public static PartitionKeyInternal InclusiveMinimum + { + get + { + return PartitionKeyInternal.EmptyPartitionKey; + } + } + + public static PartitionKeyInternal ExclusiveMaximum + { + get + { + return PartitionKeyInternal.InfinityPartitionKey; + } + } + + public static PartitionKeyInternal Empty + { + get + { + return PartitionKeyInternal.EmptyPartitionKey; + } + } + + public static PartitionKeyInternal None + { + get + { + return PartitionKeyInternal.NonePartitionKey; + } + } + + public static PartitionKeyInternal Undefined + { + get + { + return PartitionKeyInternal.UndefinedPartitionKey; + } + } + + public IReadOnlyList Components + { + get + { + return this.components; + } + } + + private PartitionKeyInternal() + { + this.components = null; + } + + public PartitionKeyInternal(IReadOnlyList values) + { + if (values == null) + { + throw new ArgumentNullException("values"); + } + + this.components = values; + } + + /// + /// Constructs instance of from enumerable of objects. + /// + /// Partition key component values. + /// If this is false, unsupported component values will be repliaced with 'Undefined'. If this is true, exception will be thrown. + /// Instance of . + public static PartitionKeyInternal FromObjectArray(IEnumerable values, bool strict) + { + if (values == null) + { + throw new ArgumentNullException("values"); + } + + List components = new List(); + foreach (object value in values) + { + components.Add(PartitionKeyInternal.FromObjectToPartitionKeyComponent(value, strict)); + } + + return new PartitionKeyInternal(components); + } + + /// + /// Constructs instance of from single object. + /// + /// Partition key component value. + /// If this is false, unsupported component values will be repliaced with 'Undefined'. If this is true, exception will be thrown. + /// Instance of . + public static PartitionKeyInternal FromObject(object value, bool strict) + { + List components = new List(1) + { + PartitionKeyInternal.FromObjectToPartitionKeyComponent(value, strict) + }; + + return new PartitionKeyInternal(components); + } + + public object[] ToObjectArray() + { + return this.Components.Select(component => component.ToObject()).ToArray(); + } + + public static PartitionKeyInternal FromJsonString(string partitionKey) + { + if (string.IsNullOrWhiteSpace(partitionKey)) + { + throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, partitionKey)); + } + + using (StringReader stringReader = new StringReader(partitionKey)) + using (JsonTextReader jsonReader = new JsonTextReader(stringReader)) + { + return FromJsonStringSerializer.Deserialize(jsonReader); + } + } + + public string ToJsonString() + { + using (StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture)) + { + using (JsonTextWriter jsonWriter = new JsonTextWriter(stringWriter)) + { + ToJsonStringSerializer.Serialize(jsonWriter, this, objectType: null); + } + + return stringWriter.ToString(); + } + } + + public bool Contains(PartitionKeyInternal nestedPartitionKey) + { + if (this.Components.Count > nestedPartitionKey.Components.Count) + { + return false; + } + + for (int i = 0; i < this.Components.Count; i++) + { + if (this.Components[i].CompareTo(nestedPartitionKey.Components[i]) != 0) + { + return false; + } + } + + return true; + } + + public static PartitionKeyInternal Max(PartitionKeyInternal key1, PartitionKeyInternal key2) + { + if (key1 == null) return key2; + if (key2 == null) return key1; + + return key1.CompareTo(key2) >= 0 ? key1 : key2; + } + + public static PartitionKeyInternal Min(PartitionKeyInternal key1, PartitionKeyInternal key2) + { + if (key1 == null) return key2; + if (key2 == null) return key1; + + return key1.CompareTo(key2) <= 0 ? key1 : key2; + } + + public static string GetMinInclusiveEffectivePartitionKey( + int partitionIndex, + int partitionCount, + PartitionKeyDefinition partitionKeyDefinition, + bool useHashV2asDefault = false) + { + if (partitionKeyDefinition.Paths.Count > 0 && !(partitionKeyDefinition.Kind == PartitionKind.Hash || partitionKeyDefinition.Kind == PartitionKind.MultiHash)) + { + throw new NotImplementedException("Cannot figure out range boundaries"); + } + + if (partitionCount <= 0) + { + throw new ArgumentException("Invalid partition count", "partitionCount"); + } + + if (partitionIndex < 0 || partitionIndex >= partitionCount) + { + throw new ArgumentException("Invalid partition index", "partitionIndex"); + } + + if (partitionIndex == 0) + { + return PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey; + } + + switch (partitionKeyDefinition.Kind) + { + case PartitionKind.Hash: + PartitionKeyDefinitionVersion defaultPartitionKeyDefinitionVersion = useHashV2asDefault ? PartitionKeyDefinitionVersion.V2 : PartitionKeyDefinitionVersion.V1; + switch (partitionKeyDefinition.Version ?? defaultPartitionKeyDefinitionVersion) + { + case PartitionKeyDefinitionVersion.V2: + Int128 val = MaxHashV2Value / partitionCount * partitionIndex; + byte[] bytes = val.Bytes; + Array.Reverse(bytes); + return HexConvert.ToHex(bytes, 0, bytes.Length); + + case PartitionKeyDefinitionVersion.V1: + return ToHexEncodedBinaryString( + new IPartitionKeyComponent[] + { new NumberPartitionKeyComponent(uint.MaxValue / partitionCount * partitionIndex) }); + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + + case PartitionKind.MultiHash: + Int128 max_val = MaxHashV2Value / partitionCount * partitionIndex; + byte[] max_bytes = max_val.Bytes; + Array.Reverse(max_bytes); + return HexConvert.ToHex(max_bytes, 0, max_bytes.Length); + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionKind"); + } + } + + public static string GetMaxExclusiveEffectivePartitionKey( + int partitionIndex, + int partitionCount, + PartitionKeyDefinition partitionKeyDefinition, + bool useHashV2asDefault = false) + { + if (partitionKeyDefinition.Paths.Count > 0 && !(partitionKeyDefinition.Kind == PartitionKind.Hash || partitionKeyDefinition.Kind == PartitionKind.MultiHash)) + { + throw new NotImplementedException("Cannot figure out range boundaries"); + } + + if (partitionCount <= 0) + { + throw new ArgumentException("Invalid partition count", "partitionCount"); + } + + if (partitionIndex < 0 || partitionIndex >= partitionCount) + { + throw new ArgumentException("Invalid partition index", "partitionIndex"); + } + + if (partitionIndex == partitionCount - 1) + { + return PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; + } + + PartitionKeyDefinitionVersion defaultPartitionKeyDefinitionVersion = useHashV2asDefault ? PartitionKeyDefinitionVersion.V2 : PartitionKeyDefinitionVersion.V1; + switch (partitionKeyDefinition.Kind) + { + case PartitionKind.Hash: + switch (partitionKeyDefinition.Version ?? defaultPartitionKeyDefinitionVersion) + { + case PartitionKeyDefinitionVersion.V2: + Int128 val = MaxHashV2Value / partitionCount * (partitionIndex + 1); + byte[] bytes = val.Bytes; + Array.Reverse(bytes); + return HexConvert.ToHex(bytes, 0, bytes.Length); + + case PartitionKeyDefinitionVersion.V1: + return ToHexEncodedBinaryString(new IPartitionKeyComponent[] { new NumberPartitionKeyComponent(uint.MaxValue / partitionCount * (partitionIndex + 1)) }); + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + + case PartitionKind.MultiHash: + + Int128 max_val = MaxHashV2Value / partitionCount * (partitionIndex + 1); + byte[] max_bytes = max_val.Bytes; + Array.Reverse(max_bytes); + return HexConvert.ToHex(max_bytes, 0, max_bytes.Length); + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionKind"); + } + } + public int CompareTo(PartitionKeyInternal other) + { + if (other == null) + { + throw new ArgumentNullException("other"); + } + else if (other.components == null || this.components == null) + { + return Math.Sign((this.components?.Count ?? 0) - (other.components?.Count ?? 0)); + } + + for (int i = 0; i < Math.Min(this.Components.Count, other.Components.Count); i++) + { + int leftOrdinal = this.Components[i].GetTypeOrdinal(); + int rightOrdinal = other.Components[i].GetTypeOrdinal(); + if (leftOrdinal != rightOrdinal) + { + return Math.Sign(leftOrdinal - rightOrdinal); + } + + int result = this.Components[i].CompareTo(other.Components[i]); + if (result != 0) + { + return Math.Sign(result); + } + } + + return Math.Sign(this.Components.Count - other.Components.Count); + } + + public bool Equals(PartitionKeyInternal other) + { + if (object.ReferenceEquals(null, other)) + { + return false; + } + + if (object.ReferenceEquals(this, other)) + { + return true; + } + + return this.CompareTo(other) == 0; + } + + public override bool Equals(object other) + { + return this.Equals(other as PartitionKeyInternal); + } + + public override int GetHashCode() + { + unchecked + { + return this.Components.Aggregate(0, (current, value) => (current * 397) ^ value.GetHashCode()); + } + } + + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + + public object Clone() + { + return new PartitionKeyInternal(this.Components); + } + + private static IPartitionKeyComponent FromObjectToPartitionKeyComponent(object value, bool strict) + { + switch (value) + { + case null: + return NullPartitionKeyComponent.Value; + case Undefined _: + return UndefinedPartitionKeyComponent.Value; + case bool b: + return new BoolPartitionKeyComponent(b); + case string s: + return new StringPartitionKeyComponent(s); + case sbyte _: + case byte _: + case short _: + case ushort _: + case int _: + case uint _: + case long _: + case ulong _: + case float _: + case double _: + case decimal _: + return new NumberPartitionKeyComponent(Convert.ToDouble(value, CultureInfo.InvariantCulture)); + case MinNumber _: + return MinNumberPartitionKeyComponent.Value; + case MaxNumber _: + return MaxNumberPartitionKeyComponent.Value; + case MinString _: + return MinStringPartitionKeyComponent.Value; + case MaxString _: + return MaxStringPartitionKeyComponent.Value; + } + + if (strict) + { + throw new InvalidOperationException( + string.Format(CultureInfo.InvariantCulture, RMResources.UnsupportedPartitionKeyComponentValue, value)); + } + + return UndefinedPartitionKeyComponent.Value; + } + + private static string ToHexEncodedBinaryString(IReadOnlyList components) + { + byte[] bufferBytes = new byte[MaxPartitionKeyBinarySize]; + using (MemoryStream ms = new MemoryStream(bufferBytes)) + { + using (BinaryWriter binaryWriter = new BinaryWriter(ms)) + { + for (int index = 0; index < components.Count; index++) + { + components[index].WriteForBinaryEncoding(binaryWriter); + } + + return HexConvert.ToHex(bufferBytes, 0, (int)ms.Position); + } + } + } + + /// + /// Constructs a PartitionKeyInternal from hex-encoded byte string. This is only for testing/debugging. Please do not use in actual product code. + /// + [Obsolete] + internal static PartitionKeyInternal FromHexEncodedBinaryString(string hexEncodedBinaryString) + { + List partitionKeyComponents = new List(); + byte[] byteString = PartitionKeyInternal.HexStringToByteArray(hexEncodedBinaryString); + + int offset = 0; + while (offset < byteString.Length) + { + PartitionKeyComponentType typeMarker = (PartitionKeyComponentType)Enum.Parse(typeof(PartitionKeyComponentType), byteString[offset++].ToString(CultureInfo.InvariantCulture)); + + switch (typeMarker) + { + case PartitionKeyComponentType.Undefined: + partitionKeyComponents.Add(UndefinedPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.Null: + partitionKeyComponents.Add(NullPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.False: + partitionKeyComponents.Add(new BoolPartitionKeyComponent(false)); + break; + + case PartitionKeyComponentType.True: + partitionKeyComponents.Add(new BoolPartitionKeyComponent(true)); + break; + + case PartitionKeyComponentType.MinNumber: + partitionKeyComponents.Add(MinNumberPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.MaxNumber: + partitionKeyComponents.Add(MaxNumberPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.MinString: + partitionKeyComponents.Add(MinStringPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.MaxString: + partitionKeyComponents.Add(MaxStringPartitionKeyComponent.Value); + break; + + case PartitionKeyComponentType.Infinity: + partitionKeyComponents.Add(new InfinityPartitionKeyComponent()); + break; + + case PartitionKeyComponentType.Number: + partitionKeyComponents.Add(NumberPartitionKeyComponent.FromHexEncodedBinaryString(byteString, ref offset)); + break; + + case PartitionKeyComponentType.String: + partitionKeyComponents.Add(StringPartitionKeyComponent.FromHexEncodedBinaryString(byteString, ref offset)); + break; + } + } + + return new PartitionKeyInternal(partitionKeyComponents); + } + + /// + /// Produces effective value. Azure Cosmos DB has global index on effective partition key values. + /// + /// Effective value is produced by applying is range or hash encoding to all the component values, based + /// on partition key definition. + /// + /// String components are hashed and converted to number components. + /// Number components are hashed and remain number component. + /// bool, null, undefined remain unhashed, because indexing policy doesn't specify index type for these types. + /// + public string GetEffectivePartitionKeyString(PartitionKeyDefinition partitionKeyDefinition, bool strict = true) + { + if (this.components == null) + { + throw new ArgumentException(RMResources.TooFewPartitionKeyComponents); + } + + if (this.Equals(EmptyPartitionKey)) + { + return MinimumInclusiveEffectivePartitionKey; + } + + if (this.Equals(InfinityPartitionKey)) + { + return MaximumExclusiveEffectivePartitionKey; + } + + if (this.Components.Count < partitionKeyDefinition.Paths.Count && partitionKeyDefinition.Kind != PartitionKind.MultiHash) + { + throw new ArgumentException(RMResources.TooFewPartitionKeyComponents); + } + + if (this.Components.Count > partitionKeyDefinition.Paths.Count && strict) + { + throw new ArgumentException(RMResources.TooManyPartitionKeyComponents); + } + + switch (partitionKeyDefinition.Kind) + { + case PartitionKind.Hash: + switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) + { + case PartitionKeyDefinitionVersion.V1: + return this.GetEffectivePartitionKeyForHashPartitioning(); + + case PartitionKeyDefinitionVersion.V2: + return this.GetEffectivePartitionKeyForHashPartitioningV2(); + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + case PartitionKind.MultiHash: + return this.GetEffectivePartitionKeyForMultiHashPartitioningV2(); + default: + return ToHexEncodedBinaryString(this.Components); + } + } + + private string GetEffectivePartitionKeyForHashPartitioning() + { + IPartitionKeyComponent[] truncatedComponents = this.Components.ToArray(); + + for (int i = 0; i < truncatedComponents.Length; i++) + { + truncatedComponents[i] = this.Components[i].Truncate(); + } + + double hash; + using (MemoryStream ms = new MemoryStream()) + { + using (BinaryWriter binaryWriter = new BinaryWriter(ms)) + { + for (int i = 0; i < truncatedComponents.Length; i++) + { + truncatedComponents[i].WriteForHashing(binaryWriter); + } + + hash = MurmurHash3.Hash32(ms.GetBuffer(), ms.Length); + } + } + + IPartitionKeyComponent[] partitionKeyComponents = new IPartitionKeyComponent[this.Components.Count + 1]; + partitionKeyComponents[0] = new NumberPartitionKeyComponent(hash); + for (int i = 0; i < truncatedComponents.Length; i++) + { + partitionKeyComponents[i + 1] = truncatedComponents[i]; + } + + return ToHexEncodedBinaryString(partitionKeyComponents); + } + + private string GetEffectivePartitionKeyForMultiHashPartitioningV2() + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = 0; i < this.Components.Count; i++) + { + byte[] hash = null; + using (MemoryStream ms = new MemoryStream()) + using (BinaryWriter binaryWriter = new BinaryWriter(ms)) + { + this.Components[i].WriteForHashingV2(binaryWriter); + + UInt128 hash128 = MurmurHash3.Hash128(ms.GetBuffer(), (int)ms.Length, UInt128.MinValue); + hash = UInt128.ToByteArray(hash128); + Array.Reverse(hash); + + // Reset 2 most significant bits, as max exclusive value is 'FF'. + // Plus one more just in case. + hash[0] &= 0x3F; + } + + sb.Append(HexConvert.ToHex(hash, 0, hash.Length)); + } + return sb.ToString(); + } + + private string GetEffectivePartitionKeyForHashPartitioningV2() + { + byte[] hash = null; + using (MemoryStream ms = new MemoryStream()) + { + using (BinaryWriter binaryWriter = new BinaryWriter(ms)) + { + for (int i = 0; i < this.Components.Count; i++) + { + this.Components[i].WriteForHashingV2(binaryWriter); + } + + UInt128 hash128 = MurmurHash3.Hash128(ms.GetBuffer(), (int)ms.Length, UInt128.MinValue); + hash = UInt128.ToByteArray(hash128); + Array.Reverse(hash); + + // Reset 2 most significant bits, as max exclusive value is 'FF'. + // Plus one more just in case. + hash[0] &= 0x3F; + } + } + + return HexConvert.ToHex(hash, 0, hash.Length); + } + + private static byte[] HexStringToByteArray(string hex) + { + int numberChars = hex.Length; + if (numberChars % 2 != 0) + { + throw new ArgumentException("Hex string should be even length", "hex"); + } + + byte[] bytes = new byte[numberChars / 2]; + for (int i = 0; i < numberChars; i += 2) + { + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + } + + return bytes; + } + + internal static class HexConvert + { + private static readonly ushort[] LookupTable = CreateLookupTable(); + + private static ushort[] CreateLookupTable() + { + ushort[] lookupTable = new ushort[256]; + for (int byteValue = 0; byteValue < 256; byteValue++) + { + string byteAsHexString = byteValue.ToString("X2", CultureInfo.InvariantCulture); + + lookupTable[byteValue] = (ushort)(byteAsHexString[0] + (byteAsHexString[1] << 8)); + } + + return lookupTable; + } + + public static string ToHex(byte[] bytes, int start, int length) + { + char[] result = new char[length * 2]; + for (int i = 0; i < length; i++) + { + ushort encodedByte = LookupTable[bytes[i + start]]; + result[2 * i] = (char)(encodedByte & 0xFF); + result[2 * i + 1] = (char)(encodedByte >> 8); + } + + return new string(result); + } + } + + public static string GetMiddleRangeEffectivePartitionKey(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) => partitionKeyDefinition.Kind switch + { + PartitionKind.Hash => GetMiddleRangeEffectivePartitionKeyForHash(minInclusive, maxExclusive, partitionKeyDefinition), + PartitionKind.MultiHash => GetMiddleRangeEffectivePartitionKeyForMultiHash(minInclusive, maxExclusive, partitionKeyDefinition), + _ => throw new InternalServerErrorException($"Unexpected PartitionKey Kind {partitionKeyDefinition.Kind}. Can determine middle of range only for hash and multihash partitioning.") + }; + + private static string GetMiddleRangeEffectivePartitionKeyForHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) + { + case PartitionKeyDefinitionVersion.V2: + { + Int128 min = 0; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); + Array.Reverse(minBytes); + min = new Int128(minBytes); + } + + Int128 max = MaxHashV2Value; + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); + Array.Reverse(maxBytes); + max = new Int128(maxBytes); + } + + byte[] midBytes = (min + (max - min) / 2).Bytes; + Array.Reverse(midBytes); + return HexConvert.ToHex(midBytes, 0, midBytes.Length); + } + case PartitionKeyDefinitionVersion.V1: + { + long min = 0; + long max = uint.MaxValue; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + return ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent((min + max) / 2) }); + } + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + } + + private static IReadOnlyList GetHashValueFromEPKForMultiHash(string epkValueString, PartitionKeyDefinition partitionKeyDefinition) + { + IList hashes = new List(); + int pathCountInEPK = (epkValueString.Length + (HashV2EPKLength - 1))/HashV2EPKLength; + + for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) + { + if (index < pathCountInEPK) + { + int startIndexForEPK = index * HashV2EPKLength; //Offset it by the length of previously read EPK(s), + + // All EPK value lengths are HashV2EPKLength, however the end EPK value is 'FF' + // FF is a special marker which appears only as a suffix + if (epkValueString.Length - startIndexForEPK < HashV2EPKLength) + { + hashes.Add(MaxHashV2Value); + } + else + { + // Extract the EPK for nth key + string epkSubPart = epkValueString.Substring(startIndexForEPK, HashV2EPKLength); + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(epkSubPart); + Array.Reverse(maxBytes); + hashes.Add(new Int128(maxBytes)); + } + } + else // The EPK has less values than Paths.Count in the PkDef, this is empty partitionkey. + { + hashes.Add(0); + } + } + + return (IReadOnlyList)hashes; + } + + //Refer docs/design/elasticity/SubpartitioningContainerSplit.md for implementation detail + private static string GetMiddleRangeEffectivePartitionKeyForMultiHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + if (partitionKeyDefinition.Version == PartitionKeyDefinitionVersion.V1) + { + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion " + partitionKeyDefinition.Version + " for MultiHash Partition kind"); + } + + IReadOnlyList minInclusiveHashValues = GetHashValueFromEPKForMultiHash(minInclusive, partitionKeyDefinition); + IReadOnlyList maxExclusiveHashValues = GetHashValueFromEPKForMultiHash(maxExclusive, partitionKeyDefinition); + IList midPointHashValues = new List(partitionKeyDefinition.Paths.Count); + + for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) + { + Int128 min = minInclusiveHashValues[index]; + Int128 max = maxExclusiveHashValues[index]; + + if (min == max || min + 1 == max) + { + midPointHashValues.Add(min); + } + else + { + /* It is possible, for Example if MinEPK, MaxEPK are [20, 40], [21, 10] respectively, + * the nMinEPKCurrentSubRange = 40 and nMaxEPKCurrentSubRange = 10 + * Since in the above step we are already setting 20 to be first level midPoint, + * for a valid second level midPoint we must look for it the range [40, HashV2Max] + */ + if (min > max) + { + max = MaxHashV2Value; + } + + Int128 midValue = (min + (max - min) / 2); + midPointHashValues.Add(midValue); + break; + } + } + + StringBuilder midPointEPKBuilder = new StringBuilder() ; + foreach (Int128 value in midPointHashValues) + { + byte[] midBytes = value.Bytes; + Array.Reverse(midBytes); + midPointEPKBuilder.Append(HexConvert.ToHex(midBytes, 0, midBytes.Length)); + } + + return midPointEPKBuilder.ToString(); + } + + public static string[] GetNEqualRangeEffectivePartitionKeys( + string minInclusive, + string maxExclusive, + PartitionKeyDefinition partitionKeyDefinition, + int numberOfSubRanges) + { + if (partitionKeyDefinition.Kind != PartitionKind.Hash) + { + throw new InvalidOperationException("Can determine " + numberOfSubRanges + " ranges only for hash partitioning."); + } + + if (numberOfSubRanges <= 0) + { + throw new InvalidOperationException("Number of sub ranges " + numberOfSubRanges + " cannot be zero or negative"); + } + + switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) + { + case PartitionKeyDefinitionVersion.V2: + { + Int128 min = 0; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); + Array.Reverse(minBytes); + min = new Int128(minBytes); + } + + Int128 max = MaxHashV2Value; + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); + Array.Reverse(maxBytes); + max = new Int128(maxBytes); + } + + if (max - min < numberOfSubRanges) + { + throw new InvalidOperationException("Insufficient range width to produce " + numberOfSubRanges + " equal sub ranges."); + } + + string[] ranges = new string[numberOfSubRanges - 1]; + for (int i = 1; i < numberOfSubRanges; i++) + { + byte[] iBytes = (min + (i * ((max - min) / numberOfSubRanges))).Bytes; + Array.Reverse(iBytes); + ranges[i - 1] = HexConvert.ToHex(iBytes, 0, iBytes.Length); + } + + return ranges; + } + case PartitionKeyDefinitionVersion.V1: + { + long min = 0; + long max = uint.MaxValue; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + if (max - min < numberOfSubRanges) + { + throw new InvalidOperationException("Insufficient range width to produce " + numberOfSubRanges + " equal sub ranges."); + } + + string[] ranges = new string[numberOfSubRanges - 1]; + for (int i = 1; i < numberOfSubRanges; i++) + { + ranges[i - 1] = ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent(min + (i * ((max - min) / numberOfSubRanges))) }); + } + + return ranges; + } + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + } + + private static double GetWidthForHashPartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + //TODO: Assert a hashversion is always passed. + //switch(partitionKeyDefinition.Version) + switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) + { + case PartitionKeyDefinitionVersion.V2: + { + UInt128 min = 0; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); + Array.Reverse(minBytes); + min = UInt128.FromByteArray(minBytes); + } + + UInt128 maxHashV2Value = UInt128.FromByteArray(MaxHashV2Value.Bytes); + UInt128 max = maxHashV2Value; + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); + Array.Reverse(maxBytes); + max = UInt128.FromByteArray(maxBytes); + } + + double width = (1.0 * (max.GetHigh() - min.GetHigh())) / (maxHashV2Value.GetHigh() + 1); + return width; + } + case PartitionKeyDefinitionVersion.V1: + { + long min = 0; + long max = uint.MaxValue; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + double width = (1.0 * (max - min)) / ((long)(UInt32.MaxValue) + 1); + return width; + } + + default: + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + } + + private static double GetWidthForRangePartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + throw new InternalServerErrorException("Cannot determine range width for range partitioning."); + } + + private static double GetWidthForMultiHashPartitioningScheme(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + //Extract only the first EPK from a multi-path partition key. + minInclusive = minInclusive.Substring(0, Math.Min(minInclusive.Length, HashV2EPKLength)); + maxExclusive = maxExclusive.Substring(0, Math.Min(maxExclusive.Length, HashV2EPKLength)); + + UInt128 min = 0; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); + Array.Reverse(minBytes); + min = UInt128.FromByteArray(minBytes); + } + + UInt128 maxHashV2Value = UInt128.FromByteArray(MaxHashV2Value.Bytes); + UInt128 max = maxHashV2Value; + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); + Array.Reverse(maxBytes); + max = UInt128.FromByteArray(maxBytes); + } + + double width = (1.0 * (max.GetHigh() - min.GetHigh())) / (maxHashV2Value.GetHigh() + 1); + return width; + } + + public static double GetWidth(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) => partitionKeyDefinition.Kind switch + { + PartitionKind.Hash => GetWidthForHashPartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), + PartitionKind.Range => GetWidthForRangePartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), + PartitionKind.MultiHash => GetWidthForMultiHashPartitioningScheme(minInclusive, maxExclusive, partitionKeyDefinition), + _ => throw new InternalServerErrorException("Unknown PartitionKind values, cannot determine range width.") + }; + + public Range GetEPKRangeForPrefixPartitionKey(PartitionKeyDefinition partitionKeyDefinition) + { + if(partitionKeyDefinition.Kind != PartitionKind.MultiHash) + { + throw new ArgumentException(RMResources.UnsupportedPartitionDefinitionKindForPartialKeyOperations); + } + + if(this.components.Count >= partitionKeyDefinition.Paths.Count) + { + throw new ArgumentException(RMResources.TooManyPartitionKeyComponents); + } + + string minEPK = this.GetEffectivePartitionKeyString(partitionKeyDefinition, false); + string maxEPK = minEPK + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; + return new Range(minEPK, maxEPK, true, false); + } + + private static bool IsPartiallySpecifiedPartitionKeyRange( + PartitionKeyDefinition partitionKeyDefinition, + Range internalRange) + { + //To be a prefixed key, it has to be MultiHash containers with >1 partition key paths. + if (partitionKeyDefinition.Kind != PartitionKind.MultiHash || + partitionKeyDefinition.Paths.Count <= 1) + { + return false; + } + + //Prefixed key should not be fully specified + //Min and Max PartitionKeyValue, should be the same value. + //We do not expect internalRange.Min and Max to have different values + if (internalRange.Min.Components.Count == partitionKeyDefinition.Paths.Count || + internalRange.Max.Components.Count == partitionKeyDefinition.Paths.Count || + !internalRange.Min.Equals(internalRange.Max)) + { + return false; + } + + return true; + } + + public static Range GetEffectivePartitionKeyRange( + PartitionKeyDefinition partitionKeyDefinition, + Range range) + { + if (range == null) + { + throw new ArgumentNullException(nameof(range)); + } + + string minEPK = range.Min.GetEffectivePartitionKeyString(partitionKeyDefinition, false); + string maxEPK = range.Max.GetEffectivePartitionKeyString(partitionKeyDefinition, false); + + if (PartitionKeyInternal.IsPartiallySpecifiedPartitionKeyRange(partitionKeyDefinition, range)) + { + maxEPK = maxEPK + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey; + } + + return new Range(minEPK, maxEPK, range.IsMinInclusive, range.IsMaxInclusive); + } + } + +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternalJsonConverter.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternalJsonConverter.cs index 9985e6177f..30dc213247 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternalJsonConverter.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternalJsonConverter.cs @@ -1,162 +1,162 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - internal sealed class PartitionKeyInternalJsonConverter : JsonConverter - { - private const string Type = "type"; - private const string MinNumber = "MinNumber"; - private const string MaxNumber = "MaxNumber"; - private const string MinString = "MinString"; - private const string MaxString = "MaxString"; - private const string Infinity = "Infinity"; - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - PartitionKeyInternal partitionKey = (PartitionKeyInternal)value; - - if (partitionKey.Equals(PartitionKeyInternal.ExclusiveMaximum)) - { - writer.WriteValue(Infinity); - return; - } - - writer.WriteStartArray(); - - IEnumerable components = partitionKey.Components ?? Enumerable.Empty(); - foreach (IPartitionKeyComponent componentValue in components) - { - componentValue.JsonEncode(writer); - } - - writer.WriteEndArray(); - } - - public override object ReadJson( - JsonReader reader, - Type objectType, - object existingValue, - JsonSerializer serializer) - { - JToken token = JToken.Load(reader); - if (token.Type == JTokenType.String && token.Value() == Infinity) - { - return PartitionKeyInternal.ExclusiveMaximum; - } - - List values = new List(); - - if (token.Type == JTokenType.Array) - { - foreach (JToken item in ((JArray)token)) - { - if (item is JObject) - { - JObject obj = (JObject)item; - - if (!obj.Properties().Any()) - { - values.Add(Undefined.Value); - } - else - { - bool valid = false; - JToken val; - - if (obj.TryGetValue(Type, out val)) - { - if (val.Type == JTokenType.String) - { - valid = true; - - if (val.Value() == MinNumber) - { - values.Add(Microsoft.Azure.Documents.Routing.MinNumber.Value); - } - else if (val.Value() == MaxNumber) - { - values.Add(Microsoft.Azure.Documents.Routing.MaxNumber.Value); - } - else if (val.Value() == MinString) - { - values.Add(Microsoft.Azure.Documents.Routing.MinString.Value); - } - else if (val.Value() == MaxString) - { - values.Add(Microsoft.Azure.Documents.Routing.MaxString.Value); - } - else - { - valid = false; - } - } - } - - if (!valid) - { - throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); - } - } - } - else if (item is JValue) - { - values.Add(((JValue)item).Value); - } - else - { - throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); - } - } - - return PartitionKeyInternal.FromObjectArray(values, true); - } - - throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); - } - - public override bool CanConvert(Type objectType) - { - return typeof(PartitionKeyInternal).IsAssignableFrom(objectType); - } - - public static void JsonEncode(MinNumberPartitionKeyComponent component, JsonWriter writer) - { - JsonEncodeLimit(writer, MinNumber); - } - - public static void JsonEncode(MaxNumberPartitionKeyComponent component, JsonWriter writer) - { - JsonEncodeLimit(writer, MaxNumber); - } - - public static void JsonEncode(MinStringPartitionKeyComponent component, JsonWriter writer) - { - JsonEncodeLimit(writer, MinString); - } - - public static void JsonEncode(MaxStringPartitionKeyComponent component, JsonWriter writer) - { - JsonEncodeLimit(writer, MaxString); - } - - private static void JsonEncodeLimit(JsonWriter writer, string value) - { - writer.WriteStartObject(); - - writer.WritePropertyName(Type); - - writer.WriteValue(value); - - writer.WriteEndObject(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + internal sealed class PartitionKeyInternalJsonConverter : JsonConverter + { + private const string Type = "type"; + private const string MinNumber = "MinNumber"; + private const string MaxNumber = "MaxNumber"; + private const string MinString = "MinString"; + private const string MaxString = "MaxString"; + private const string Infinity = "Infinity"; + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + PartitionKeyInternal partitionKey = (PartitionKeyInternal)value; + + if (partitionKey.Equals(PartitionKeyInternal.ExclusiveMaximum)) + { + writer.WriteValue(Infinity); + return; + } + + writer.WriteStartArray(); + + IEnumerable components = partitionKey.Components ?? Enumerable.Empty(); + foreach (IPartitionKeyComponent componentValue in components) + { + componentValue.JsonEncode(writer); + } + + writer.WriteEndArray(); + } + + public override object ReadJson( + JsonReader reader, + Type objectType, + object existingValue, + JsonSerializer serializer) + { + JToken token = JToken.Load(reader); + if (token.Type == JTokenType.String && token.Value() == Infinity) + { + return PartitionKeyInternal.ExclusiveMaximum; + } + + List values = new List(); + + if (token.Type == JTokenType.Array) + { + foreach (JToken item in ((JArray)token)) + { + if (item is JObject) + { + JObject obj = (JObject)item; + + if (!obj.Properties().Any()) + { + values.Add(Undefined.Value); + } + else + { + bool valid = false; + JToken val; + + if (obj.TryGetValue(Type, out val)) + { + if (val.Type == JTokenType.String) + { + valid = true; + + if (val.Value() == MinNumber) + { + values.Add(Microsoft.Azure.Documents.Routing.MinNumber.Value); + } + else if (val.Value() == MaxNumber) + { + values.Add(Microsoft.Azure.Documents.Routing.MaxNumber.Value); + } + else if (val.Value() == MinString) + { + values.Add(Microsoft.Azure.Documents.Routing.MinString.Value); + } + else if (val.Value() == MaxString) + { + values.Add(Microsoft.Azure.Documents.Routing.MaxString.Value); + } + else + { + valid = false; + } + } + } + + if (!valid) + { + throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); + } + } + } + else if (item is JValue) + { + values.Add(((JValue)item).Value); + } + else + { + throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); + } + } + + return PartitionKeyInternal.FromObjectArray(values, true); + } + + throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, RMResources.UnableToDeserializePartitionKeyValue, token)); + } + + public override bool CanConvert(Type objectType) + { + return typeof(PartitionKeyInternal).IsAssignableFrom(objectType); + } + + public static void JsonEncode(MinNumberPartitionKeyComponent component, JsonWriter writer) + { + JsonEncodeLimit(writer, MinNumber); + } + + public static void JsonEncode(MaxNumberPartitionKeyComponent component, JsonWriter writer) + { + JsonEncodeLimit(writer, MaxNumber); + } + + public static void JsonEncode(MinStringPartitionKeyComponent component, JsonWriter writer) + { + JsonEncodeLimit(writer, MinString); + } + + public static void JsonEncode(MaxStringPartitionKeyComponent component, JsonWriter writer) + { + JsonEncodeLimit(writer, MaxString); + } + + private static void JsonEncodeLimit(JsonWriter writer, string value) + { + writer.WriteStartObject(); + + writer.WritePropertyName(Type); + + writer.WriteValue(value); + + writer.WriteEndObject(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs index 17f3829476..f93307098b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs @@ -1,180 +1,185 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using Microsoft.Azure.Documents.Routing; - using Newtonsoft.Json; - - /// - /// Represents a partition key range in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class PartitionKeyRange : Resource, IEquatable - { - // This is only used in Gateway and corresponds to the value set in the backend. - // Client must not use this value, as it must use whatever comes in address resolution response. - internal const string MasterPartitionKeyRangeId = "M"; - - /// - /// Represents the minimum possible value of a PartitionKeyRange in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.MinInclusive)] - internal string MinInclusive - { - get - { - return base.GetValue(Constants.Properties.MinInclusive); - } - set - { - base.SetValue(Constants.Properties.MinInclusive, value); - } - } - - /// - /// Represents maximum exclusive value of a PartitionKeyRange (the upper, but not including this value, boundary of PartitionKeyRange) - /// in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.MaxExclusive)] - internal string MaxExclusive - { - get - { - return base.GetValue(Constants.Properties.MaxExclusive); - } - set - { - base.SetValue(Constants.Properties.MaxExclusive, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.RidPrefix)] - internal int? RidPrefix - { - get - { - return base.GetValue(Constants.Properties.RidPrefix); - } - set - { - base.SetValue(Constants.Properties.RidPrefix, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.ThroughputFraction)] - internal double ThroughputFraction - { - get - { - return base.GetValue(Constants.Properties.ThroughputFraction); - } - set - { - base.SetValue(Constants.Properties.ThroughputFraction, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.PartitionKeyRangeStatus)] - internal PartitionKeyRangeStatus Status - { - get - { - return base.GetValue(Constants.Properties.PartitionKeyRangeStatus); - } - set - { - base.SetValue(Constants.Properties.PartitionKeyRangeStatus, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.Lsn)] - public long LSN - { - get - { - return base.GetValue(Constants.Properties.Lsn); - } - set - { - base.SetValue(Constants.Properties.Lsn, value); - } - } - - /// - /// Contains ids or parent ranges in the Azure Cosmos DB service. - /// For example if range with id '1' splits into '2' and '3', - /// then Parents for ranges '2' and '3' will be ['1']. - /// If range '3' splits into '4' and '5', then parents for ranges '4' and '5' - /// will be ['1', '3']. - /// - [JsonProperty(PropertyName = Constants.Properties.Parents)] - public Collection Parents - { - get - { - return base.GetValue>(Constants.Properties.Parents); - } - set - { - base.SetValue(Constants.Properties.Parents, value); - } - } - - internal Range ToRange() - { - return new Range(this.MinInclusive, this.MaxExclusive, true, false); - } - - /// - /// Determines whether this instance in the Azure Cosmos DB service and a specified object have the same value. - /// - /// The object to compare to this instance - public override bool Equals(object obj) - { - return this.Equals(obj as PartitionKeyRange); - } - - /// - /// Returns the hash code for this instance in the Azure Cosmos DB service. - /// - /// - /// A 32-bit signed integer hash code. - /// - public override int GetHashCode() - { - unchecked - { - int hash = 0; - hash = (hash * 397) ^ this.Id.GetHashCode(); - hash = (hash * 397) ^ this.MinInclusive.GetHashCode(); - hash = (hash * 397) ^ this.MaxExclusive.GetHashCode(); - return hash; - } - } - - /// - /// Determines whether this instance in the Azure Cosmos DB service and a specified PartitionKeyRange object have the same value. - /// - /// The PartitionKeyRange object to compare to this instance - public bool Equals(PartitionKeyRange other) - { - if (other == null) - { - return false; - } - - return this.Id == other.Id - && this.MinInclusive.Equals(other.MinInclusive) - && this.MaxExclusive.Equals(other.MaxExclusive) - && (this.ThroughputFraction == other.ThroughputFraction); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using Microsoft.Azure.Documents.Routing; + using Newtonsoft.Json; + + /// + /// Represents a partition key range in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class PartitionKeyRange : Resource, IEquatable + { + // This is only used in Gateway and corresponds to the value set in the backend. + // Client must not use this value, as it must use whatever comes in address resolution response. + internal const string MasterPartitionKeyRangeId = "M"; + + /// + /// Represents the minimum possible value of a PartitionKeyRange in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.MinInclusive)] + internal string MinInclusive + { + get + { + return base.GetValue(Constants.Properties.MinInclusive); + } + set + { + base.SetValue(Constants.Properties.MinInclusive, value); + } + } + + /// + /// Represents maximum exclusive value of a PartitionKeyRange (the upper, but not including this value, boundary of PartitionKeyRange) + /// in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.MaxExclusive)] + internal string MaxExclusive + { + get + { + return base.GetValue(Constants.Properties.MaxExclusive); + } + set + { + base.SetValue(Constants.Properties.MaxExclusive, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.RidPrefix)] + internal int? RidPrefix + { + get + { + return base.GetValue(Constants.Properties.RidPrefix); + } + set + { + base.SetValue(Constants.Properties.RidPrefix, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.ThroughputFraction)] + internal double ThroughputFraction + { + get + { + return base.GetValue(Constants.Properties.ThroughputFraction); + } + set + { + base.SetValue(Constants.Properties.ThroughputFraction, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.PartitionKeyRangeStatus)] + internal PartitionKeyRangeStatus Status + { + get + { + return base.GetValue(Constants.Properties.PartitionKeyRangeStatus); + } + set + { + base.SetValue(Constants.Properties.PartitionKeyRangeStatus, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.Lsn)] + public long LSN + { + get + { + return base.GetValue(Constants.Properties.Lsn); + } + set + { + base.SetValue(Constants.Properties.Lsn, value); + } + } + + /// + /// Contains ids or parent ranges in the Azure Cosmos DB service. + /// For example if range with id '1' splits into '2' and '3', + /// then Parents for ranges '2' and '3' will be ['1']. + /// If range '3' splits into '4' and '5', then parents for ranges '4' and '5' + /// will be ['1', '3']. + /// + [JsonProperty(PropertyName = Constants.Properties.Parents)] + public Collection Parents + { + get + { + return base.GetValue>(Constants.Properties.Parents); + } + set + { + base.SetValue(Constants.Properties.Parents, value); + } + } + + internal Range ToRange() + { + return new Range(this.MinInclusive, this.MaxExclusive, true, false); + } + + /// + /// Determines whether this instance in the Azure Cosmos DB service and a specified object have the same value. + /// + /// The object to compare to this instance + public override bool Equals(object obj) + { + return this.Equals(obj as PartitionKeyRange); + } + + /// + /// Returns the hash code for this instance in the Azure Cosmos DB service. + /// + /// + /// A 32-bit signed integer hash code. + /// + public override int GetHashCode() + { + unchecked + { + int hash = 0; + hash = (hash * 397) ^ this.Id.GetHashCode(); + if (!string.IsNullOrEmpty(this.ResourceId)) + { + hash = (hash * 397) ^ this.ResourceId.GetHashCode(); + } + hash = (hash * 397) ^ this.MinInclusive.GetHashCode(); + hash = (hash * 397) ^ this.MaxExclusive.GetHashCode(); + return hash; + } + } + + /// + /// Determines whether this instance in the Azure Cosmos DB service and a specified PartitionKeyRange object have the same value. + /// + /// The PartitionKeyRange object to compare to this instance + public bool Equals(PartitionKeyRange other) + { + if (other == null) + { + return false; + } + + return this.Id == other.Id + && string.Equals(this.ResourceId, other.ResourceId, StringComparison.Ordinal) + && this.MinInclusive.Equals(other.MinInclusive) + && this.MaxExclusive.Equals(other.MaxExclusive) + && (this.ThroughputFraction == other.ThroughputFraction); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeGoneException.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeGoneException.cs index 8a3209f4a6..4661efc3c0 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeGoneException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeGoneException.cs @@ -1,83 +1,83 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - /// - /// This exception is thrown when DocumentServiceRequest contains x-ms-documentdb-partitionkeyrangeid - /// header and such range id doesn't exist. - /// No retries should be made in this case, as either split or merge might have happened and query/readfeed - /// must take appropriate actions. - /// - [Serializable] - internal sealed class PartitionKeyRangeGoneException : DocumentClientException - { - public PartitionKeyRangeGoneException() - : this(RMResources.Gone) - { - - } - - public PartitionKeyRangeGoneException(string message) - : this(message, (Exception)null, null) - { - } - - public PartitionKeyRangeGoneException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - } - - public PartitionKeyRangeGoneException(string message, Exception innerException) - : this(message, innerException, null) - { - } - - public PartitionKeyRangeGoneException(Exception innerException) - : this(RMResources.Gone, innerException, null) - { - } - - public PartitionKeyRangeGoneException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - - public PartitionKeyRangeGoneException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - -#if !NETSTANDARD16 - private PartitionKeyRangeGoneException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.Gone) - { - SetSubstatus(); - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; - } - - private void SetSubstatus() - { - this.Headers[WFConstants.BackendHeaders.SubStatus] = - ((uint)SubStatusCodes.PartitionKeyRangeGone).ToString(CultureInfo.InvariantCulture); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + /// + /// This exception is thrown when DocumentServiceRequest contains x-ms-documentdb-partitionkeyrangeid + /// header and such range id doesn't exist. + /// No retries should be made in this case, as either split or merge might have happened and query/readfeed + /// must take appropriate actions. + /// + [Serializable] + internal sealed class PartitionKeyRangeGoneException : DocumentClientException + { + public PartitionKeyRangeGoneException() + : this(RMResources.Gone) + { + + } + + public PartitionKeyRangeGoneException(string message) + : this(message, (Exception)null, null) + { + } + + public PartitionKeyRangeGoneException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + } + + public PartitionKeyRangeGoneException(string message, Exception innerException) + : this(message, innerException, null) + { + } + + public PartitionKeyRangeGoneException(Exception innerException) + : this(RMResources.Gone, innerException, null) + { + } + + public PartitionKeyRangeGoneException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + + public PartitionKeyRangeGoneException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + +#if !NETSTANDARD16 + private PartitionKeyRangeGoneException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.Gone) + { + SetSubstatus(); + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; + } + + private void SetSubstatus() + { + this.Headers[WFConstants.BackendHeaders.SubStatus] = + ((uint)SubStatusCodes.PartitionKeyRangeGone).ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIdentity.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIdentity.cs index 0ee50f808b..c5ed8b6b80 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIdentity.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIdentity.cs @@ -1,137 +1,137 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - - internal sealed class PartitionKeyRangeIdentity : IEquatable - { - public PartitionKeyRangeIdentity(string collectionRid, string partitionKeyRangeId) - { - if (collectionRid == null) - { - throw new ArgumentNullException("collectionRid"); - } - - if (partitionKeyRangeId == null) - { - throw new ArgumentNullException("partitionKeyRangeId"); - } - - this.CollectionRid = collectionRid; - this.PartitionKeyRangeId = partitionKeyRangeId; - } - - /// - /// This should only be used for user provided partitionKeyRangeId, because in this case - /// he knows what he is doing. If collection was deleted/created with same name - it is his responsibility. - /// - /// If our code infers partitionKeyRangeId automatically and uses collection information from collection cache, - /// we need to ensure that request will reach correct collection. In this case constructor which takes collectionRid MUST - /// be used. - /// - public PartitionKeyRangeIdentity(string partitionKeyRangeId) - { - if (partitionKeyRangeId == null) - { - throw new ArgumentNullException("partitionKeyRangeId"); - } - - this.PartitionKeyRangeId = partitionKeyRangeId; - } - - public static PartitionKeyRangeIdentity FromHeader(string header) - { - // this gets called a lot, so avoid using string.Split() and - // the like - - // header is either - // - partitionKeyRangeId (no commas) - // or - // - collectionId,partitionKeyRangeId (one comma) - - int commaIndex = header.IndexOf(','); - if (commaIndex == -1) - { - // reuse the header string - return new PartitionKeyRangeIdentity(header); - } - - int secondCommaIndex = header.IndexOf(',', commaIndex + 1); - if (secondCommaIndex != -1) - { - throw new BadRequestException(RMResources.InvalidPartitionKeyRangeIdHeader); - } - - string collectionRid = header.Substring(0, commaIndex); - string partionKeyRangeId = header.Substring(commaIndex + 1); - - return new PartitionKeyRangeIdentity(collectionRid, partionKeyRangeId); - } - - public string ToHeader() - { - if (this.CollectionRid != null) - { - return string.Format( - CultureInfo.InvariantCulture, - "{0},{1}", - this.CollectionRid, - this.PartitionKeyRangeId); - } - - return string.Format( - CultureInfo.InvariantCulture, - "{0}", - this.PartitionKeyRangeId); - } - - public string CollectionRid - { - get; - private set; - } - - public string PartitionKeyRangeId - { - get; - private set; - } - - public bool Equals(PartitionKeyRangeIdentity other) - { - if (ReferenceEquals(null, other)) - { - return false; - } - if (ReferenceEquals(this, other)) - { - return true; - } - return StringComparer.Ordinal.Equals(this.CollectionRid, other.CollectionRid) && StringComparer.Ordinal.Equals(this.PartitionKeyRangeId, other.PartitionKeyRangeId); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - if (ReferenceEquals(this, obj)) - { - return true; - } - return obj is PartitionKeyRangeIdentity && Equals((PartitionKeyRangeIdentity)obj); - } - - public override int GetHashCode() - { - unchecked - { - return ((this.CollectionRid != null ? this.CollectionRid.GetHashCode() : 0) * 397) ^ (this.PartitionKeyRangeId != null ? this.PartitionKeyRangeId.GetHashCode() : 0); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + + internal sealed class PartitionKeyRangeIdentity : IEquatable + { + public PartitionKeyRangeIdentity(string collectionRid, string partitionKeyRangeId) + { + if (collectionRid == null) + { + throw new ArgumentNullException("collectionRid"); + } + + if (partitionKeyRangeId == null) + { + throw new ArgumentNullException("partitionKeyRangeId"); + } + + this.CollectionRid = collectionRid; + this.PartitionKeyRangeId = partitionKeyRangeId; + } + + /// + /// This should only be used for user provided partitionKeyRangeId, because in this case + /// he knows what he is doing. If collection was deleted/created with same name - it is his responsibility. + /// + /// If our code infers partitionKeyRangeId automatically and uses collection information from collection cache, + /// we need to ensure that request will reach correct collection. In this case constructor which takes collectionRid MUST + /// be used. + /// + public PartitionKeyRangeIdentity(string partitionKeyRangeId) + { + if (partitionKeyRangeId == null) + { + throw new ArgumentNullException("partitionKeyRangeId"); + } + + this.PartitionKeyRangeId = partitionKeyRangeId; + } + + public static PartitionKeyRangeIdentity FromHeader(string header) + { + // this gets called a lot, so avoid using string.Split() and + // the like + + // header is either + // - partitionKeyRangeId (no commas) + // or + // - collectionId,partitionKeyRangeId (one comma) + + int commaIndex = header.IndexOf(','); + if (commaIndex == -1) + { + // reuse the header string + return new PartitionKeyRangeIdentity(header); + } + + int secondCommaIndex = header.IndexOf(',', commaIndex + 1); + if (secondCommaIndex != -1) + { + throw new BadRequestException(RMResources.InvalidPartitionKeyRangeIdHeader); + } + + string collectionRid = header.Substring(0, commaIndex); + string partionKeyRangeId = header.Substring(commaIndex + 1); + + return new PartitionKeyRangeIdentity(collectionRid, partionKeyRangeId); + } + + public string ToHeader() + { + if (this.CollectionRid != null) + { + return string.Format( + CultureInfo.InvariantCulture, + "{0},{1}", + this.CollectionRid, + this.PartitionKeyRangeId); + } + + return string.Format( + CultureInfo.InvariantCulture, + "{0}", + this.PartitionKeyRangeId); + } + + public string CollectionRid + { + get; + private set; + } + + public string PartitionKeyRangeId + { + get; + private set; + } + + public bool Equals(PartitionKeyRangeIdentity other) + { + if (ReferenceEquals(null, other)) + { + return false; + } + if (ReferenceEquals(this, other)) + { + return true; + } + return StringComparer.Ordinal.Equals(this.CollectionRid, other.CollectionRid) && StringComparer.Ordinal.Equals(this.PartitionKeyRangeId, other.PartitionKeyRangeId); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + return obj is PartitionKeyRangeIdentity && Equals((PartitionKeyRangeIdentity)obj); + } + + public override int GetHashCode() + { + unchecked + { + return ((this.CollectionRid != null ? this.CollectionRid.GetHashCode() : 0) * 397) ^ (this.PartitionKeyRangeId != null ? this.PartitionKeyRangeId.GetHashCode() : 0); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIsSplittingException.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIsSplittingException.cs index 45bd33d790..f75b2df4f5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIsSplittingException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeIsSplittingException.cs @@ -1,83 +1,83 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - /// - /// This exception is thrown when DocumentServiceRequest reaches partition which is being split - /// and was made unavailable for reads/writes. - /// - /// Gateway/SDK can transparently refresh routing map and retry after some delay. - /// - [Serializable] - internal sealed class PartitionKeyRangeIsSplittingException : DocumentClientException - { - public PartitionKeyRangeIsSplittingException() - : this(RMResources.Gone) - { - - } - - public PartitionKeyRangeIsSplittingException(string message) - : this(message, (Exception)null, null) - { - } - - public PartitionKeyRangeIsSplittingException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - } - - public PartitionKeyRangeIsSplittingException(string message, Exception innerException) - : this(message, innerException, null) - { - } - - public PartitionKeyRangeIsSplittingException(Exception innerException) - : this(RMResources.Gone, innerException, null) - { - } - - public PartitionKeyRangeIsSplittingException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - - public PartitionKeyRangeIsSplittingException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) - { - SetSubstatus(); - SetDescription(); - } - -#if !NETSTANDARD16 - private PartitionKeyRangeIsSplittingException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.Gone) - { - SetSubstatus(); - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; - } - - private void SetSubstatus() - { - this.Headers[WFConstants.BackendHeaders.SubStatus] = - ((uint)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + /// + /// This exception is thrown when DocumentServiceRequest reaches partition which is being split + /// and was made unavailable for reads/writes. + /// + /// Gateway/SDK can transparently refresh routing map and retry after some delay. + /// + [Serializable] + internal sealed class PartitionKeyRangeIsSplittingException : DocumentClientException + { + public PartitionKeyRangeIsSplittingException() + : this(RMResources.Gone) + { + + } + + public PartitionKeyRangeIsSplittingException(string message) + : this(message, (Exception)null, null) + { + } + + public PartitionKeyRangeIsSplittingException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + } + + public PartitionKeyRangeIsSplittingException(string message, Exception innerException) + : this(message, innerException, null) + { + } + + public PartitionKeyRangeIsSplittingException(Exception innerException) + : this(RMResources.Gone, innerException, null) + { + } + + public PartitionKeyRangeIsSplittingException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + + public PartitionKeyRangeIsSplittingException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.Gone, requestUri) + { + SetSubstatus(); + SetDescription(); + } + +#if !NETSTANDARD16 + private PartitionKeyRangeIsSplittingException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.Gone) + { + SetSubstatus(); + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.InvalidPartition; + } + + private void SetSubstatus() + { + this.Headers[WFConstants.BackendHeaders.SubStatus] = + ((uint)SubStatusCodes.CompletingSplit).ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatistics.cs index d7c3d8589d..d1ae70d099 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatistics.cs @@ -1,85 +1,85 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Collections.Generic; - using Newtonsoft.Json; - - /// - /// Represents statistics for a partition key range in the Azure Cosmos DB service. - /// - /// - /// For usage, please refer to the example in . - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class PartitionKeyRangeStatistics - { - /// - /// Gets the ID of a partition key range in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.Id)] - public string PartitionKeyRangeId - { - get; - private set; - } - - /// - /// Gets the size in KB of a partition key range in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] - public long SizeInKB - { - get; - private set; - } - - /// - /// Gets the document count of a partition key range in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.DocumentCount)] - public long DocumentCount - { - get; - private set; - } - - /// - /// Gets the distinct partition key count in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.SampledDistinctPartitionKeyCount)] - internal long? SampledDistinctPartitionKeyCount - { - get; - private set; - } - - /// - /// Gets the partition key statistics for a partition key range in the Azure Cosmos DB service. - /// - /// - /// This is reported based on a sub-sampling of partition keys within the partition key range and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. - /// - [JsonProperty(PropertyName = Constants.Properties.PartitionKeys)] - public IReadOnlyList PartitionKeyStatistics - { - get; - private set; - } - - /// - /// Gets the stringified version of object in the Azure Cosmos DB service. - /// - /// - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Collections.Generic; + using Newtonsoft.Json; + + /// + /// Represents statistics for a partition key range in the Azure Cosmos DB service. + /// + /// + /// For usage, please refer to the example in . + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class PartitionKeyRangeStatistics + { + /// + /// Gets the ID of a partition key range in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.Id)] + public string PartitionKeyRangeId + { + get; + private set; + } + + /// + /// Gets the size in KB of a partition key range in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] + public long SizeInKB + { + get; + private set; + } + + /// + /// Gets the document count of a partition key range in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.DocumentCount)] + public long DocumentCount + { + get; + private set; + } + + /// + /// Gets the distinct partition key count in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.SampledDistinctPartitionKeyCount)] + internal long? SampledDistinctPartitionKeyCount + { + get; + private set; + } + + /// + /// Gets the partition key statistics for a partition key range in the Azure Cosmos DB service. + /// + /// + /// This is reported based on a sub-sampling of partition keys within the partition key range and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. + /// + [JsonProperty(PropertyName = Constants.Properties.PartitionKeys)] + public IReadOnlyList PartitionKeyStatistics + { + get; + private set; + } + + /// + /// Gets the stringified version of object in the Azure Cosmos DB service. + /// + /// + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatus.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatus.cs index d8c0181bd0..8a6af85cfc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatus.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRangeStatus.cs @@ -1,29 +1,29 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Runtime.Serialization; - - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - [JsonConverter(typeof(StringEnumConverter))] - internal enum PartitionKeyRangeStatus - { - Invalid, - - [EnumMember(Value = "online")] - Online, - - [EnumMember(Value = "splitting")] - Splitting, - - [EnumMember(Value = "offline")] - Offline, - - [EnumMember(Value = "split")] - Split - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Runtime.Serialization; + + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + [JsonConverter(typeof(StringEnumConverter))] + internal enum PartitionKeyRangeStatus + { + Invalid, + + [EnumMember(Value = "online")] + Online, + + [EnumMember(Value = "splitting")] + Splitting, + + [EnumMember(Value = "offline")] + Offline, + + [EnumMember(Value = "split")] + Split + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyStatistics.cs index 1d8d661c29..924a788c8d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyStatistics.cs @@ -1,62 +1,62 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Microsoft.Azure.Documents.Routing; - using Newtonsoft.Json; - - /// - /// Represents statistics of a partition key in the Azure Cosmos DB service. - /// - /// - /// This is reported based on a sub-sampling of partition keys within the collection and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. - /// For usage, please refer to the example in . - /// - [JsonObject(MemberSerialization.OptIn)] -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class PartitionKeyStatistics - { - /// - /// Gets the partition key in the Azure Cosmos DB service. - /// - public PartitionKey PartitionKey - { - get - { - return PartitionKey.FromInternalKey(this.PartitionKeyInternal); - } - } - - /// - /// Gets the size of the partition key in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] - public long SizeInKB - { - get; - private set; - } - - /// - /// Gets the stringified version of object in the Azure Cosmos DB service. - /// - /// - public override string ToString() - { - return JsonConvert.SerializeObject(this); - } - - [JsonProperty(PropertyName = Constants.Properties.PartitionKey)] - internal PartitionKeyInternal PartitionKeyInternal - { - get; - private set; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Microsoft.Azure.Documents.Routing; + using Newtonsoft.Json; + + /// + /// Represents statistics of a partition key in the Azure Cosmos DB service. + /// + /// + /// This is reported based on a sub-sampling of partition keys within the collection and hence these are approximate. If your partition keys are below 1GB of storage, they may not show up in the reported statistics. + /// For usage, please refer to the example in . + /// + [JsonObject(MemberSerialization.OptIn)] +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class PartitionKeyStatistics + { + /// + /// Gets the partition key in the Azure Cosmos DB service. + /// + public PartitionKey PartitionKey + { + get + { + return PartitionKey.FromInternalKey(this.PartitionKeyInternal); + } + } + + /// + /// Gets the size of the partition key in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] + public long SizeInKB + { + get; + private set; + } + + /// + /// Gets the stringified version of object in the Azure Cosmos DB service. + /// + /// + public override string ToString() + { + return JsonConvert.SerializeObject(this); + } + + [JsonProperty(PropertyName = Constants.Properties.PartitionKey)] + internal PartitionKeyInternal PartitionKeyInternal + { + get; + private set; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKind.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKind.cs index 23db87d3c5..100d427727 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKind.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKind.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// These are the partitioning types available for a partition key definition in the Azure Cosmos DB service. - /// - /// Only PartitionKind.Hash is supported at this time. - internal enum PartitionKind - { - /// - /// The partition key definition path is hashed. - /// - Hash, - - /// - /// The partition key definition path is ordered. - /// - Range, - - /// - /// The partition key definition path has >1 entries, individual values are hashed and concatenated together to generate a single EPK. - /// - MultiHash, - - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// These are the partitioning types available for a partition key definition in the Azure Cosmos DB service. + /// + /// Only PartitionKind.Hash is supported at this time. + internal enum PartitionKind + { + /// + /// The partition key definition path is hashed. + /// + Hash, + + /// + /// The partition key definition path is ordered. + /// + Range, + + /// + /// The partition key definition path has >1 entries, individual values are hashed and concatenated together to generate a single EPK. + /// + MultiHash, + + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionedSystemDocument.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionedSystemDocument.cs index 6937b97847..083a4f418d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionedSystemDocument.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionedSystemDocument.cs @@ -1,17 +1,17 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - /// - /// Represents a Partitioned SystemDocument. - /// It is partitioned across the server partitions like a regular document. - /// - internal class PartitionedSystemDocument : Resource - { - public PartitionedSystemDocument() - { - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Represents a Partitioned SystemDocument. + /// It is partitioned across the server partitions like a regular document. + /// + internal class PartitionedSystemDocument : Resource + { + public PartitionedSystemDocument() + { + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Paths.cs b/Microsoft.Azure.Cosmos/src/direct/Paths.cs index ef077ac631..19df9cc6c4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Paths.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Paths.cs @@ -1,458 +1,458 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal static class Paths - { - //root --------------------------------- - public const string Root = "/"; - - public const string OperationsPathSegment = "operations"; - public const string OperationId = "operationId"; - public const string ReplicaOperations_Pause = "pause"; - public const string ReplicaOperations_Resume = "resume"; - public const string ReplicaOperations_Stop = "stop"; - public const string ReplicaOperations_Recycle = "recycle"; - public const string ReplicaOperations_Crash = "crash"; - public const string ReplicaOperations_ForceConfigRefresh = "forceConfigRefresh"; - public const string ReplicaOperations_ReportThroughputUtilization = "reportthroughpututilization"; - public const string ReplicaOperations_BatchReportThroughputUtilization = "batchreportthroughpututilization"; - public const string Operations_GetFederationConfigurations = "getfederationconfigurations"; - public const string Operations_GetConfiguration = "getconfiguration"; - public const string Operations_GetDatabaseAccountConfigurations = "getdatabaseaccountconfigurations"; - public const string Operations_GetGraphDatabaseAccountConfiguration = "getgraphdatabaseaccountconfiguration"; - public const string Operations_GetStorageServiceConfigurations = "getstorageserviceconfigurations"; - public const string Operations_GetStorageAccountKey = "getstorageaccountkey"; - public const string Operations_GetStorageAccountSas = "getstorageaccountsas"; - public const string Operations_GetUnwrappedDek = "getunwrappeddek"; - public const string Operations_GetDekProperties = "getdekproperties"; - public const string Operations_GetCustomerManagedKeyStatus = "getcustomermanagedkeystatus"; - public const string Operations_ReadReplicaFromMasterPartition = "readreplicafrommasterpartition"; - public const string Operations_ReadReplicaFromServerPartition = "readreplicafromserverpartition"; - public const string Operations_MasterInitiatedProgressCoordination = "masterinitiatedprogresscoordination"; - public const string Operations_GetAadGroups = "getaadgroups"; - public const string Operations_XPDatabaseAccountMetaData = "xpmetadata"; - public const string Operations_MetadataCheckAccess = "metadatacheckaccess"; - - //databases namespace off of root------------------- - - // /subscriptions - public const string SubscriptionsSegment = "subscriptions"; - public const string SubscriptionsSegment_Root = Root + SubscriptionsSegment; - - // /subscriptions/{subscriptionId} - public const string SubscriptionIdSegment = "subscriptionId"; - public const string SubscriptionIdSegment_Root = SubscriptionsSegment_Root + "/{" + SubscriptionIdSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups - public const string ResourceGroupsSegment = "resourceGroups"; - public const string ResourceGroupsSegment_Root = SubscriptionIdSegment_Root + "/" + ResourceGroupsSegment; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup} - public const string ResourceGroupSegment = "resourceGroup"; - public const string ResourceGroupSegment_Root = ResourceGroupsSegment_Root + "/{" + ResourceGroupSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers - public const string ProvidersSegment = "providers"; - public const string ProvidersSegment_Root = ResourceGroupSegment_Root + "/" + ProvidersSegment; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB - public const string CosmosProvider = "Microsoft.DocumentDB"; - public const string CosmosProvider_Root = ProvidersSegment_Root + "/" + CosmosProvider; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts - public const string DatabaseAccountResourceType = "databaseAccounts"; - public const string DatabaseAccountType_Root = CosmosProvider_Root + "/" + DatabaseAccountResourceType; - - // /dbs - public const string DatabasesPathSegment = "dbs"; - public const string Databases_Root = Root + "/" + DatabasesPathSegment + "/"; - - // /dbs/{id} - public const string DatabaseId = "dbId"; - public const string Database_Root = Databases_Root + "{" + DatabaseId + "}"; - - // FedURL/accounts/{id}/dbs - public const string FederationEndpoint_Databases_Root = FederationEndpoint_Root + "/" + Databases_Root; - // FedURL/accounts/{id}/dbs/{id} - public const string FederationEndpoint_Database_Root = FederationEndpoint_Databases_Root + "{" + DatabaseId + "}"; - - // /dbs/{id}/users - public const string UsersPathSegment = "users"; - public const string Users_Root = Database_Root + "/" + UsersPathSegment + "/"; - - // /dbs/{id}/users/{id} - public const string UserId = "userid"; - public const string User_Root = Users_Root + "{" + UserId + "}"; - - // /dbs/{id}/clientencryptionkeys - public const string ClientEncryptionKeysPathSegment = "clientencryptionkeys"; - public const string ClientEncryptionKeys_Root = Database_Root + "/" + ClientEncryptionKeysPathSegment + "/"; - - // /dbs/{id}/clientencryptionkeys/{id} - public const string ClientEncryptionKeyId = "clientencryptionkeyId"; - public const string ClientEncryptionKey_Root = ClientEncryptionKeys_Root + "{" + ClientEncryptionKeyId + "}"; - - // /dbs/{id}/udts - public const string UserDefinedTypesPathSegment = "udts"; - public const string UserDefinedTypes_Root = Database_Root + "/" + UserDefinedTypesPathSegment + "/"; - - // /dbs/{id}/udts/{id} - public const string UserDefinedTypeId = "udtId"; - public const string UserDefinedType_Root = UserDefinedTypes_Root + "{" + UserDefinedTypeId + "}"; - - // /dbs/{id}/users/{id}/permissions - public const string PermissionsPathSegment = "permissions"; - public const string Permissions_Root = User_Root + "/" + PermissionsPathSegment + "/"; - - // /dbs/{id}/users/{id}/permissions/{id} - public const string PermissionId = "permissionId"; - public const string Permission_Root = Permissions_Root + "{" + PermissionId + "}"; - - // /dbs/{id}/colls - public const string CollectionsPathSegment = "colls"; - public const string Collections_Root = Database_Root + "/" + CollectionsPathSegment + "/"; - - // /dbs/{id}/colls/{id} - public const string CollectionId = "collId"; - public const string Collection_Root = Collections_Root + "{" + CollectionId + "}"; - - // FedURL/accounts/{id}/dbs/{id}/colls - public const string FederationEndpoint_Collections_Root = FederationEndpoint_Root + "/" + Collections_Root; - // FedURL/accounts/{id}/dbs/{id}/colls/{id} - public const string FederationEndpoint_Collection_Root = FederationEndpoint_Collections_Root + "{" + CollectionId + "}"; - - // /dbs/{id}/colls/{id}/sprocs - public const string StoredProceduresPathSegment = "sprocs"; - public const string StoredProcedures_Root = Collection_Root + "/" + StoredProceduresPathSegment + "/"; - - // /dbs/{id}/colls/{id}/sprocs/{id} - public const string StoredProcedureId = "sprocId"; - public const string StoredProcedure_Root = StoredProcedures_Root + "{" + StoredProcedureId + "}"; - - // FedURL/accounts/{id}/dbs/{id}/colls/{id}/sprocs - public const string FederationEndpoint_StoredProcedures_Root = FederationEndpoint_Root + "/" + StoredProcedures_Root; - // FedURL/accounts/{id}/dbs/{id}/colls/{id}/sprocs/{id} - public const string FederationEndpoint_StoredProcedure_Root = FederationEndpoint_StoredProcedures_Root + "{" + StoredProcedureId + "}"; - - // /dbs/{id}/colls/{id}/triggers - public const string TriggersPathSegment = "triggers"; - public const string Triggers_Root = Collection_Root + "/" + TriggersPathSegment + "/"; - - // /dbs/{id}/colls/{id}/triggers/{id} - public const string TriggerId = "triggerId"; - public const string Trigger_Root = Triggers_Root + "{" + TriggerId + "}"; - - // /dbs/{id}/colls/{id}/udfs - public const string UserDefinedFunctionsPathSegment = "udfs"; - public const string UserDefinedFunctions_Root = Collection_Root + "/" + UserDefinedFunctionsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/functions/{id} - public const string UserDefinedFunctionId = "udfId"; - public const string UserDefinedFunction_Root = UserDefinedFunctions_Root + "{" + UserDefinedFunctionId + "}"; - - // /dbs/{id}/colls/{id}/conflicts - public const string ConflictsPathSegment = "conflicts"; - public const string Conflicts_Root = Collection_Root + "/" + ConflictsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/conflicts/{id} - public const string ConflictId = "conflictId"; - public const string Conflict_Root = Conflicts_Root + "{" + ConflictId + "}"; - - // /dbs/{id}/colls/{id}/partitionedsystemdocuments - public const string PartitionedSystemDocumentsPathSegment = "partitionedsystemdocuments"; - public const string PartitionedSystemDocuments_Root = Collection_Root + "/" + PartitionedSystemDocumentsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/partitionedsystemdocuments/{id} - public const string PartitionedSystemDocumentId = "partitionedSystemDocumentId"; - public const string PartitionedSystemDocument_Root = PartitionedSystemDocuments_Root + "{" + PartitionedSystemDocumentId + "}"; - - // /dbs/{id}/colls/{id}/systemdocuments - public const string SystemDocumentsPathSegment = "systemdocuments"; - public const string SystemDocuments_Root = Collection_Root + "/" + SystemDocumentsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/systemdocuments/{id} - public const string SystemDocumentId = "systemDocumentId"; - public const string SystemDocument_Root = SystemDocuments_Root + "{" + SystemDocumentId + "}"; - - // /dbs/{id}/colls/{id}/docs - public const string DocumentsPathSegment = "docs"; - public const string Documents_Root = Collection_Root + "/" + DocumentsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/docs/{id} - public const string DocumentId = "docId"; - public const string Document_Root = Documents_Root + "{" + DocumentId + "}"; - - // /dbs/{id}/colls/{id}/docs/{id}/attachments - public const string AttachmentsPathSegment = "attachments"; - public const string Attachments_Root = Document_Root + "/" + AttachmentsPathSegment + "/"; - - // /dbs/{id}/colls/{id}/docs/{id}/attachments/{id} - public const string AttachmentId = "attachmentId"; - public const string Attachment_Root = Attachments_Root + "{" + AttachmentId + "}"; - - // FedURL/accounts/{id}/dbs/{id}/colls/{id}/docs/{id}/attachments - public const string FederationEndpoint_Attachments_Root = FederationEndpoint_Root + "/" + Attachments_Root; - // FedURL/accounts/{id}/dbs/{id}/colls/{id}/docs/{id}/attachments/{id} - public const string FederationEndpoint_Attachment_Root = FederationEndpoint_Attachments_Root + "{" + AttachmentId + "}"; - - // /dbs/{id}/colls/{id}/pkranges - public const string PartitionKeyRangesPathSegment = "pkranges"; - public const string PartitionKeyRanges_Root = Collection_Root + "/" + PartitionKeyRangesPathSegment + "/"; - - // /dbs/{id}/colls/{id}/pkranges/{id} - public const string PartitionKeyRangeId = "pkrangeId"; - public const string PartitionKeyRange_Root = PartitionKeyRanges_Root + "{" + PartitionKeyRangeId + "}"; - - // FedURL/accounts/{id}/dbs/{id}/colls/{id}/pkranges - public const string FederationEndpoint_PartitionKeyRanges_Root = FederationEndpoint_Root + "/" + PartitionKeyRanges_Root; - - // /dbs/{id}/colls/{id}/pkranges/{id}/presplitaction - public const string PartitionKeyRangePreSplitSegment = "presplitaction"; - public const string PartitionKeyRangePreSplit_Root = PartitionKeyRange_Root + "/" + PartitionKeyRangePreSplitSegment + "/"; - - // /dbs/{id}/colls/{id}/pkranges/{id}/postsplitaction - public const string PartitionKeyRangePostSplitSegment = "postsplitaction"; - public const string PartitionKeyRangePostSplit_Root = PartitionKeyRange_Root + "/" + PartitionKeyRangePostSplitSegment + "/"; - - // /dbs/{id}/colls/{id}/pkranges/{id}/split - public const string ParatitionKeyRangeOperations_Split = "split"; - - // /partitions - public const string PartitionsPathSegment = "partitions"; - public const string Partitions_Root = Root + "/" + PartitionsPathSegment + "/"; - - // /databaseAccount - public const string DatabaseAccountSegment = "databaseaccount"; - public const string DatabaseAccount_Root = Root + "/" + DatabaseAccountSegment + "/"; - - // /storageauthtoken - public const string StorageAuthTokenPathSegment = "storageauthtoken"; - public const string StorageAuthToken_Root = Root + "/" + StorageAuthTokenPathSegment + "/"; - - // /files - public const string FilesPathSegment = "files"; - public const string Files_Root = Root + "/" + FilesPathSegment + "/"; - - public const string FileId = "fileId"; - public const string File_Root = Files_Root + "{" + FileId + "}"; - - // /medias - public const string MediaPathSegment = "media"; - public const string Medias_Root = Root + "/" + MediaPathSegment + "/"; - - public const string MediaId = "mediaId"; - public const string Media_Root = Medias_Root + "{" + MediaId + "}"; - - // /address - public const string AddressPathSegment = "addresses"; - public const string Address_Root = Root + "/" + AddressPathSegment + "/"; - - // /xpreplicatoraddress - public const string XPReplicatorAddressPathSegment = "xpreplicatoraddreses"; - public const string XPReplicatorAddress_Root = Root + "/" + XPReplicatorAddressPathSegment + "/"; - - // /offers - public const string OffersPathSegment = "offers"; - public const string Offers_Root = Root + "/" + OffersPathSegment + "/"; - - // /offers/{id} - public const string OfferId = "offerId"; - public const string Offer_Root = Offers_Root + "{" + OfferId + "}"; - - // FedURL/accounts/{id}/offers - public const string FederationEndpoint_Offers_Root = FederationEndpoint_Root + "/" + Offers_Root; - // FedURL/accounts/{id}/offers/{id} - public const string FederationEndpoint_Offer_Root = FederationEndpoint_Offers_Root + "{" + OfferId + "}"; - - // /topology - public const string TopologyPathSegment = "topology"; - public const string Topology_Root = Root + "/" + TopologyPathSegment + "/"; - - // /dbs/{id}/colls/{id}/schemas - public const string SchemasPathSegment = "schemas"; - public const string Schemas_Root = Collection_Root + "/" + SchemasPathSegment + "/"; - - // /dbs/{id}/colls/{id}/schemas/{id} - public const string SchemaId = "schemaId"; - public const string Schema_Root = Schemas_Root + "{" + SchemaId + "}"; - - // /servicereservation - public const string ServiceReservationPathSegment = "serviceReservation"; - public const string ServiceReservation_Root = Root + "/" + ServiceReservationPathSegment + "/"; - - // document explorer - public const string DataExplorerSegment = "_explorer"; - public const string DataExplorerAuthTokenSegment = "authorization"; - - // /ridRange - public const string RidRangePathSegment = "ridranges"; - public const string RidRange_Root = Root + "/" + RidRangePathSegment + "/"; - - // /snapshots - public const string SnapshotsPathSegment = "snapshots"; - public const string Snapshots_Root = Root + "/" + SnapshotsPathSegment + "/"; - - // /snapshots/{id} - public const string SnapshotId = "snapshotId"; - public const string Snapshot_Root = Snapshots_Root + "{" + SnapshotId + "}"; - - public const string DataExplorer_Root = Paths.Root + "/" + DataExplorerSegment; - public const string DataExplorerAuthToken_Root = DataExplorer_Root + "/" + DataExplorerAuthTokenSegment; - public const string DataExplorerAuthToken_WithoutResourceId = DataExplorerAuthToken_Root + "/{verb}/{resourceType}"; - public const string DataExplorerAuthToken_WithResourceId = DataExplorerAuthToken_WithoutResourceId + "/" + "{resourceId}"; - - // compute gateway charge path - internal const string ComputeGatewayChargePathSegment = "computegatewaycharge"; - - // controller service - public const string ControllerOperations_BatchGetOutput = "controllerbatchgetoutput"; - public const string ControllerOperations_BatchReportCharges = "controllerbatchreportcharges"; - public const string ControllerOperations_BatchAutoscaleRUsConsumption = "controllerbatchautoscalerusconsumption"; - public const string ControllerOperations_BatchGetAutoscaleAggregateOutput = "controllerbatchgetautoscaleaggregateoutput"; - - // vector clock - public const string VectorClockPathSegment = "vectorclock"; - - // metadata check access - public const string MetadataCheckAccessPathSegment = "metadatacheckaccess"; - - // partition key delete - public const string PartitionKeyDeletePathSegment = "partitionkeydelete"; - public const string PartitionKeyDelete = Collection_Root + "/" + OperationsPathSegment + "/" + PartitionKeyDeletePathSegment; - - // /roleAssignments - public const string RoleAssignmentsPathSegment = "roleassignments"; - public const string RoleAssignments_Root = Root + "/" + RoleAssignmentsPathSegment + "/"; - - // /roleAssignments/{id} - public const string RoleAssignmentId = "roleassignmentId"; - public const string RoleAssignment_Root = RoleAssignments_Root + "{" + RoleAssignmentId + "}"; - - // /roleDefinitions - public const string RoleDefinitionsPathSegment = "roledefinitions"; - public const string RoleDefinitions_Root = Root + "/" + RoleDefinitionsPathSegment + "/"; - - // /roleDefinitions/{id} - public const string RoleDefinitionId = "roledefinitionId"; - public const string RoleDefinition_Root = RoleDefinitions_Root + "{" + RoleDefinitionId + "}"; - - // /dbs/{id}/colls/{id}/operations/collectiontruncate - public const string CollectionTruncatePathsegment = "collectiontruncate"; - public const string CollectionTruncate = Collection_Root + "/" + OperationsPathSegment + "/" + CollectionTruncatePathsegment; - - // /transactions - public const string TransactionsPathSegment = "transaction"; - public const string Transactions_Root = Root + "/" + TransactionsPathSegment + "/"; - - // /transactions/{id} - public const string TransactionId = "transactionId"; - public const string Transaction_Root = Transactions_Root + "{" + TransactionId + "}"; - - // /authpolicyelements - public const string AuthPolicyElementsPathSegment = "authpolicyelements"; - public const string AuthPolicyElements_Root = Root + "/" + AuthPolicyElementsPathSegment + "/"; - - // /authpolicyelements/{id} - public const string AuthPolicyElementId = "authpolicyelementId"; - public const string AuthPolicyElement_Root = AuthPolicyElements_Root + "{" + AuthPolicyElementId + "}"; - - // /interopUsers - public const string InteropUsersPathSegment = "interopusers"; - public const string InteropUsers_Root = Root + "/" + InteropUsersPathSegment + "/"; - - // /interopUsers/{id} - public const string InteropUserId = "interopuserId"; - public const string InteropUser_Root = InteropUsers_Root + "{" + InteropUserId + "}"; - - // /localemulator - public const string LocalEmulatorPathSegment = "localemulator"; - public const string LocalEmulator_Root = Root + "/" + LocalEmulatorPathSegment + "/"; - - // /emulator/defaultIdentity - public const string LocalEmulatorManagedIdentityPathSegment = "managedIdentity"; - public const string LocalEmulatorManagedIdentity_Root = LocalEmulator_Root + "/" + LocalEmulatorManagedIdentityPathSegment + "/"; - - // /retriablewritecachedresponse - public const string RetriableWriteCachedResponsePathSegment = "retriablewritecachedresponse"; - public const string RetriableWriteCachedResponse_Root = Root + "/" + RetriableWriteCachedResponsePathSegment + "/"; - - // urls like http://hostname/accounts/{id}/address - // /accounts/{id}/ - public const string AccountsPathSegment = "accounts"; - public const string AccountId = "accountId"; - public const string FederationEndpoint_Root = Root + "/" + AccountsPathSegment + "/{" + AccountId + "}"; - - // /accounts/{id}/address - public const string FederationEndpoint_Address_Root = FederationEndpoint_Root + "/" + AddressPathSegment + "/"; - - // /encryptionscopes - public const string EncryptionScopesPathSegment = "encryptionscopes"; - public const string EncryptionScopes_Root = Root + "/" + EncryptionScopesPathSegment + "/"; - - // /clientconfigs - public const string ClientConfigPathSegment = "clientconfigs"; - public const string ClientConfig_Root = Root + ClientConfigPathSegment; - public const string FederationEndpoint_ClientConfig_Root = FederationEndpoint_Root + ClientConfig_Root; - - - // /encryptionscopes/{id} - public const string EncryptionScopeId = "encryptionscopeid"; - public const string EncryptionScope_Root = EncryptionScopes_Root + "{" + EncryptionScopeId + "}"; - - public const string OperationResultsSegment = "operationResults"; - public const string OperationIdSegment = "operationId"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource} - public const string DatabaseAccountResourceSegment = "databaseAccountResource"; - public const string DatabaseAccountResourceSegment_Root = DatabaseAccountType_Root + "/{" + DatabaseAccountResourceSegment + "}"; - - // ----------------- Native Control Plane RBAC for Cassandra ----------------- - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions - public const string CassandraRoleDefinitionResourceType = "cassandraRoleDefinitions"; - public const string CassandraRoleDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + CassandraRoleDefinitionResourceType; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{cassandraRoleDefinitionResource} - public const string CassandraRoleDefinitionResourceSegment = "cassandraRoleDefinitionResource"; - public const string CassandraRoleDefinitionResourceSegment_Root = CassandraRoleDefinitionResourceType_Root + "/{" + CassandraRoleDefinitionResourceSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{cassandraRoleDefinitionResource}/operationResults - public const string CassandraRoleDefinitionOperationResultsSegment_Root = CassandraRoleDefinitionResourceSegment_Root + "/" + OperationResultsSegment; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{mongoRoleDefinitionResource}/operationResults/{operationId} - public const string CassandraRoleDefinitionOperationResultSegment_Root = CassandraRoleDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; - - // ----------------- Native Control Plane RBAC for Mongo ----------------- - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions - public const string MongoDbRoleDefinitionResourceType = "mongodbRoleDefinitions"; - public const string MongoDbRoleDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + MongoDbRoleDefinitionResourceType; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongodbRoleDefinitionResource} - public const string MongoDbRoleDefinitionResourceSegment = "mongodbRoleDefinitionResource"; - public const string MongoDbRoleDefinitionResourceSegment_Root = MongoDbRoleDefinitionResourceType_Root + "/{" + MongoDbRoleDefinitionResourceSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongodbRoleDefinitionResource}/operationResults - public const string MongoDbRoleDefinitionOperationResultsSegment_Root = MongoDbRoleDefinitionResourceSegment_Root + "/" + OperationResultsSegment; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongoRoleDefinitionResource}/operationResults/{operationId} - public const string MongoDbRoleDefinitionOperationResultSegment_Root = MongoDbRoleDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions - public const string MongoDbUserDefinitionResourceType = "mongodbUserDefinitions"; - public const string MongoDbUserDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + MongoDbUserDefinitionResourceType; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource} - public const string MongoDbUserDefinitionResourceSegment = "mongodbUserDefinitionResource"; - public const string MongoDbUserDefinitionResourceSegment_Root = MongoDbUserDefinitionResourceType_Root + "/{" + MongoDbUserDefinitionResourceSegment + "}"; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource}/operationResults - public const string MongoDbUserDefinitionOperationResultsSegment_Root = MongoDbUserDefinitionResourceSegment_Root + "/" + OperationResultsSegment; - - // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource}/operationResults/{operationId} - public const string MongoDbUserDefinitionOperationResultSegment_Root = MongoDbUserDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal static class Paths + { + //root --------------------------------- + public const string Root = "/"; + + public const string OperationsPathSegment = "operations"; + public const string OperationId = "operationId"; + public const string ReplicaOperations_Pause = "pause"; + public const string ReplicaOperations_Resume = "resume"; + public const string ReplicaOperations_Stop = "stop"; + public const string ReplicaOperations_Recycle = "recycle"; + public const string ReplicaOperations_Crash = "crash"; + public const string ReplicaOperations_ForceConfigRefresh = "forceConfigRefresh"; + public const string ReplicaOperations_ReportThroughputUtilization = "reportthroughpututilization"; + public const string ReplicaOperations_BatchReportThroughputUtilization = "batchreportthroughpututilization"; + public const string Operations_GetFederationConfigurations = "getfederationconfigurations"; + public const string Operations_GetConfiguration = "getconfiguration"; + public const string Operations_GetDatabaseAccountConfigurations = "getdatabaseaccountconfigurations"; + public const string Operations_GetGraphDatabaseAccountConfiguration = "getgraphdatabaseaccountconfiguration"; + public const string Operations_GetStorageServiceConfigurations = "getstorageserviceconfigurations"; + public const string Operations_GetStorageAccountKey = "getstorageaccountkey"; + public const string Operations_GetStorageAccountSas = "getstorageaccountsas"; + public const string Operations_GetUnwrappedDek = "getunwrappeddek"; + public const string Operations_GetDekProperties = "getdekproperties"; + public const string Operations_GetCustomerManagedKeyStatus = "getcustomermanagedkeystatus"; + public const string Operations_ReadReplicaFromMasterPartition = "readreplicafrommasterpartition"; + public const string Operations_ReadReplicaFromServerPartition = "readreplicafromserverpartition"; + public const string Operations_MasterInitiatedProgressCoordination = "masterinitiatedprogresscoordination"; + public const string Operations_GetAadGroups = "getaadgroups"; + public const string Operations_XPDatabaseAccountMetaData = "xpmetadata"; + public const string Operations_MetadataCheckAccess = "metadatacheckaccess"; + + //databases namespace off of root------------------- + + // /subscriptions + public const string SubscriptionsSegment = "subscriptions"; + public const string SubscriptionsSegment_Root = Root + SubscriptionsSegment; + + // /subscriptions/{subscriptionId} + public const string SubscriptionIdSegment = "subscriptionId"; + public const string SubscriptionIdSegment_Root = SubscriptionsSegment_Root + "/{" + SubscriptionIdSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups + public const string ResourceGroupsSegment = "resourceGroups"; + public const string ResourceGroupsSegment_Root = SubscriptionIdSegment_Root + "/" + ResourceGroupsSegment; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup} + public const string ResourceGroupSegment = "resourceGroup"; + public const string ResourceGroupSegment_Root = ResourceGroupsSegment_Root + "/{" + ResourceGroupSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers + public const string ProvidersSegment = "providers"; + public const string ProvidersSegment_Root = ResourceGroupSegment_Root + "/" + ProvidersSegment; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB + public const string CosmosProvider = "Microsoft.DocumentDB"; + public const string CosmosProvider_Root = ProvidersSegment_Root + "/" + CosmosProvider; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts + public const string DatabaseAccountResourceType = "databaseAccounts"; + public const string DatabaseAccountType_Root = CosmosProvider_Root + "/" + DatabaseAccountResourceType; + + // /dbs + public const string DatabasesPathSegment = "dbs"; + public const string Databases_Root = Root + "/" + DatabasesPathSegment + "/"; + + // /dbs/{id} + public const string DatabaseId = "dbId"; + public const string Database_Root = Databases_Root + "{" + DatabaseId + "}"; + + // FedURL/accounts/{id}/dbs + public const string FederationEndpoint_Databases_Root = FederationEndpoint_Root + "/" + Databases_Root; + // FedURL/accounts/{id}/dbs/{id} + public const string FederationEndpoint_Database_Root = FederationEndpoint_Databases_Root + "{" + DatabaseId + "}"; + + // /dbs/{id}/users + public const string UsersPathSegment = "users"; + public const string Users_Root = Database_Root + "/" + UsersPathSegment + "/"; + + // /dbs/{id}/users/{id} + public const string UserId = "userid"; + public const string User_Root = Users_Root + "{" + UserId + "}"; + + // /dbs/{id}/clientencryptionkeys + public const string ClientEncryptionKeysPathSegment = "clientencryptionkeys"; + public const string ClientEncryptionKeys_Root = Database_Root + "/" + ClientEncryptionKeysPathSegment + "/"; + + // /dbs/{id}/clientencryptionkeys/{id} + public const string ClientEncryptionKeyId = "clientencryptionkeyId"; + public const string ClientEncryptionKey_Root = ClientEncryptionKeys_Root + "{" + ClientEncryptionKeyId + "}"; + + // /dbs/{id}/udts + public const string UserDefinedTypesPathSegment = "udts"; + public const string UserDefinedTypes_Root = Database_Root + "/" + UserDefinedTypesPathSegment + "/"; + + // /dbs/{id}/udts/{id} + public const string UserDefinedTypeId = "udtId"; + public const string UserDefinedType_Root = UserDefinedTypes_Root + "{" + UserDefinedTypeId + "}"; + + // /dbs/{id}/users/{id}/permissions + public const string PermissionsPathSegment = "permissions"; + public const string Permissions_Root = User_Root + "/" + PermissionsPathSegment + "/"; + + // /dbs/{id}/users/{id}/permissions/{id} + public const string PermissionId = "permissionId"; + public const string Permission_Root = Permissions_Root + "{" + PermissionId + "}"; + + // /dbs/{id}/colls + public const string CollectionsPathSegment = "colls"; + public const string Collections_Root = Database_Root + "/" + CollectionsPathSegment + "/"; + + // /dbs/{id}/colls/{id} + public const string CollectionId = "collId"; + public const string Collection_Root = Collections_Root + "{" + CollectionId + "}"; + + // FedURL/accounts/{id}/dbs/{id}/colls + public const string FederationEndpoint_Collections_Root = FederationEndpoint_Root + "/" + Collections_Root; + // FedURL/accounts/{id}/dbs/{id}/colls/{id} + public const string FederationEndpoint_Collection_Root = FederationEndpoint_Collections_Root + "{" + CollectionId + "}"; + + // /dbs/{id}/colls/{id}/sprocs + public const string StoredProceduresPathSegment = "sprocs"; + public const string StoredProcedures_Root = Collection_Root + "/" + StoredProceduresPathSegment + "/"; + + // /dbs/{id}/colls/{id}/sprocs/{id} + public const string StoredProcedureId = "sprocId"; + public const string StoredProcedure_Root = StoredProcedures_Root + "{" + StoredProcedureId + "}"; + + // FedURL/accounts/{id}/dbs/{id}/colls/{id}/sprocs + public const string FederationEndpoint_StoredProcedures_Root = FederationEndpoint_Root + "/" + StoredProcedures_Root; + // FedURL/accounts/{id}/dbs/{id}/colls/{id}/sprocs/{id} + public const string FederationEndpoint_StoredProcedure_Root = FederationEndpoint_StoredProcedures_Root + "{" + StoredProcedureId + "}"; + + // /dbs/{id}/colls/{id}/triggers + public const string TriggersPathSegment = "triggers"; + public const string Triggers_Root = Collection_Root + "/" + TriggersPathSegment + "/"; + + // /dbs/{id}/colls/{id}/triggers/{id} + public const string TriggerId = "triggerId"; + public const string Trigger_Root = Triggers_Root + "{" + TriggerId + "}"; + + // /dbs/{id}/colls/{id}/udfs + public const string UserDefinedFunctionsPathSegment = "udfs"; + public const string UserDefinedFunctions_Root = Collection_Root + "/" + UserDefinedFunctionsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/functions/{id} + public const string UserDefinedFunctionId = "udfId"; + public const string UserDefinedFunction_Root = UserDefinedFunctions_Root + "{" + UserDefinedFunctionId + "}"; + + // /dbs/{id}/colls/{id}/conflicts + public const string ConflictsPathSegment = "conflicts"; + public const string Conflicts_Root = Collection_Root + "/" + ConflictsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/conflicts/{id} + public const string ConflictId = "conflictId"; + public const string Conflict_Root = Conflicts_Root + "{" + ConflictId + "}"; + + // /dbs/{id}/colls/{id}/partitionedsystemdocuments + public const string PartitionedSystemDocumentsPathSegment = "partitionedsystemdocuments"; + public const string PartitionedSystemDocuments_Root = Collection_Root + "/" + PartitionedSystemDocumentsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/partitionedsystemdocuments/{id} + public const string PartitionedSystemDocumentId = "partitionedSystemDocumentId"; + public const string PartitionedSystemDocument_Root = PartitionedSystemDocuments_Root + "{" + PartitionedSystemDocumentId + "}"; + + // /dbs/{id}/colls/{id}/systemdocuments + public const string SystemDocumentsPathSegment = "systemdocuments"; + public const string SystemDocuments_Root = Collection_Root + "/" + SystemDocumentsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/systemdocuments/{id} + public const string SystemDocumentId = "systemDocumentId"; + public const string SystemDocument_Root = SystemDocuments_Root + "{" + SystemDocumentId + "}"; + + // /dbs/{id}/colls/{id}/docs + public const string DocumentsPathSegment = "docs"; + public const string Documents_Root = Collection_Root + "/" + DocumentsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/docs/{id} + public const string DocumentId = "docId"; + public const string Document_Root = Documents_Root + "{" + DocumentId + "}"; + + // /dbs/{id}/colls/{id}/docs/{id}/attachments + public const string AttachmentsPathSegment = "attachments"; + public const string Attachments_Root = Document_Root + "/" + AttachmentsPathSegment + "/"; + + // /dbs/{id}/colls/{id}/docs/{id}/attachments/{id} + public const string AttachmentId = "attachmentId"; + public const string Attachment_Root = Attachments_Root + "{" + AttachmentId + "}"; + + // FedURL/accounts/{id}/dbs/{id}/colls/{id}/docs/{id}/attachments + public const string FederationEndpoint_Attachments_Root = FederationEndpoint_Root + "/" + Attachments_Root; + // FedURL/accounts/{id}/dbs/{id}/colls/{id}/docs/{id}/attachments/{id} + public const string FederationEndpoint_Attachment_Root = FederationEndpoint_Attachments_Root + "{" + AttachmentId + "}"; + + // /dbs/{id}/colls/{id}/pkranges + public const string PartitionKeyRangesPathSegment = "pkranges"; + public const string PartitionKeyRanges_Root = Collection_Root + "/" + PartitionKeyRangesPathSegment + "/"; + + // /dbs/{id}/colls/{id}/pkranges/{id} + public const string PartitionKeyRangeId = "pkrangeId"; + public const string PartitionKeyRange_Root = PartitionKeyRanges_Root + "{" + PartitionKeyRangeId + "}"; + + // FedURL/accounts/{id}/dbs/{id}/colls/{id}/pkranges + public const string FederationEndpoint_PartitionKeyRanges_Root = FederationEndpoint_Root + "/" + PartitionKeyRanges_Root; + + // /dbs/{id}/colls/{id}/pkranges/{id}/presplitaction + public const string PartitionKeyRangePreSplitSegment = "presplitaction"; + public const string PartitionKeyRangePreSplit_Root = PartitionKeyRange_Root + "/" + PartitionKeyRangePreSplitSegment + "/"; + + // /dbs/{id}/colls/{id}/pkranges/{id}/postsplitaction + public const string PartitionKeyRangePostSplitSegment = "postsplitaction"; + public const string PartitionKeyRangePostSplit_Root = PartitionKeyRange_Root + "/" + PartitionKeyRangePostSplitSegment + "/"; + + // /dbs/{id}/colls/{id}/pkranges/{id}/split + public const string ParatitionKeyRangeOperations_Split = "split"; + + // /partitions + public const string PartitionsPathSegment = "partitions"; + public const string Partitions_Root = Root + "/" + PartitionsPathSegment + "/"; + + // /databaseAccount + public const string DatabaseAccountSegment = "databaseaccount"; + public const string DatabaseAccount_Root = Root + "/" + DatabaseAccountSegment + "/"; + + // /storageauthtoken + public const string StorageAuthTokenPathSegment = "storageauthtoken"; + public const string StorageAuthToken_Root = Root + "/" + StorageAuthTokenPathSegment + "/"; + + // /files + public const string FilesPathSegment = "files"; + public const string Files_Root = Root + "/" + FilesPathSegment + "/"; + + public const string FileId = "fileId"; + public const string File_Root = Files_Root + "{" + FileId + "}"; + + // /medias + public const string MediaPathSegment = "media"; + public const string Medias_Root = Root + "/" + MediaPathSegment + "/"; + + public const string MediaId = "mediaId"; + public const string Media_Root = Medias_Root + "{" + MediaId + "}"; + + // /address + public const string AddressPathSegment = "addresses"; + public const string Address_Root = Root + "/" + AddressPathSegment + "/"; + + // /xpreplicatoraddress + public const string XPReplicatorAddressPathSegment = "xpreplicatoraddreses"; + public const string XPReplicatorAddress_Root = Root + "/" + XPReplicatorAddressPathSegment + "/"; + + // /offers + public const string OffersPathSegment = "offers"; + public const string Offers_Root = Root + "/" + OffersPathSegment + "/"; + + // /offers/{id} + public const string OfferId = "offerId"; + public const string Offer_Root = Offers_Root + "{" + OfferId + "}"; + + // FedURL/accounts/{id}/offers + public const string FederationEndpoint_Offers_Root = FederationEndpoint_Root + "/" + Offers_Root; + // FedURL/accounts/{id}/offers/{id} + public const string FederationEndpoint_Offer_Root = FederationEndpoint_Offers_Root + "{" + OfferId + "}"; + + // /topology + public const string TopologyPathSegment = "topology"; + public const string Topology_Root = Root + "/" + TopologyPathSegment + "/"; + + // /dbs/{id}/colls/{id}/schemas + public const string SchemasPathSegment = "schemas"; + public const string Schemas_Root = Collection_Root + "/" + SchemasPathSegment + "/"; + + // /dbs/{id}/colls/{id}/schemas/{id} + public const string SchemaId = "schemaId"; + public const string Schema_Root = Schemas_Root + "{" + SchemaId + "}"; + + // /servicereservation + public const string ServiceReservationPathSegment = "serviceReservation"; + public const string ServiceReservation_Root = Root + "/" + ServiceReservationPathSegment + "/"; + + // document explorer + public const string DataExplorerSegment = "_explorer"; + public const string DataExplorerAuthTokenSegment = "authorization"; + + // /ridRange + public const string RidRangePathSegment = "ridranges"; + public const string RidRange_Root = Root + "/" + RidRangePathSegment + "/"; + + // /snapshots + public const string SnapshotsPathSegment = "snapshots"; + public const string Snapshots_Root = Root + "/" + SnapshotsPathSegment + "/"; + + // /snapshots/{id} + public const string SnapshotId = "snapshotId"; + public const string Snapshot_Root = Snapshots_Root + "{" + SnapshotId + "}"; + + public const string DataExplorer_Root = Paths.Root + "/" + DataExplorerSegment; + public const string DataExplorerAuthToken_Root = DataExplorer_Root + "/" + DataExplorerAuthTokenSegment; + public const string DataExplorerAuthToken_WithoutResourceId = DataExplorerAuthToken_Root + "/{verb}/{resourceType}"; + public const string DataExplorerAuthToken_WithResourceId = DataExplorerAuthToken_WithoutResourceId + "/" + "{resourceId}"; + + // compute gateway charge path + internal const string ComputeGatewayChargePathSegment = "computegatewaycharge"; + + // controller service + public const string ControllerOperations_BatchGetOutput = "controllerbatchgetoutput"; + public const string ControllerOperations_BatchReportCharges = "controllerbatchreportcharges"; + public const string ControllerOperations_BatchAutoscaleRUsConsumption = "controllerbatchautoscalerusconsumption"; + public const string ControllerOperations_BatchGetAutoscaleAggregateOutput = "controllerbatchgetautoscaleaggregateoutput"; + + // vector clock + public const string VectorClockPathSegment = "vectorclock"; + + // metadata check access + public const string MetadataCheckAccessPathSegment = "metadatacheckaccess"; + + // partition key delete + public const string PartitionKeyDeletePathSegment = "partitionkeydelete"; + public const string PartitionKeyDelete = Collection_Root + "/" + OperationsPathSegment + "/" + PartitionKeyDeletePathSegment; + + // /roleAssignments + public const string RoleAssignmentsPathSegment = "roleassignments"; + public const string RoleAssignments_Root = Root + "/" + RoleAssignmentsPathSegment + "/"; + + // /roleAssignments/{id} + public const string RoleAssignmentId = "roleassignmentId"; + public const string RoleAssignment_Root = RoleAssignments_Root + "{" + RoleAssignmentId + "}"; + + // /roleDefinitions + public const string RoleDefinitionsPathSegment = "roledefinitions"; + public const string RoleDefinitions_Root = Root + "/" + RoleDefinitionsPathSegment + "/"; + + // /roleDefinitions/{id} + public const string RoleDefinitionId = "roledefinitionId"; + public const string RoleDefinition_Root = RoleDefinitions_Root + "{" + RoleDefinitionId + "}"; + + // /dbs/{id}/colls/{id}/operations/collectiontruncate + public const string CollectionTruncatePathsegment = "collectiontruncate"; + public const string CollectionTruncate = Collection_Root + "/" + OperationsPathSegment + "/" + CollectionTruncatePathsegment; + + // /transactions + public const string TransactionsPathSegment = "transaction"; + public const string Transactions_Root = Root + "/" + TransactionsPathSegment + "/"; + + // /transactions/{id} + public const string TransactionId = "transactionId"; + public const string Transaction_Root = Transactions_Root + "{" + TransactionId + "}"; + + // /authpolicyelements + public const string AuthPolicyElementsPathSegment = "authpolicyelements"; + public const string AuthPolicyElements_Root = Root + "/" + AuthPolicyElementsPathSegment + "/"; + + // /authpolicyelements/{id} + public const string AuthPolicyElementId = "authpolicyelementId"; + public const string AuthPolicyElement_Root = AuthPolicyElements_Root + "{" + AuthPolicyElementId + "}"; + + // /interopUsers + public const string InteropUsersPathSegment = "interopusers"; + public const string InteropUsers_Root = Root + "/" + InteropUsersPathSegment + "/"; + + // /interopUsers/{id} + public const string InteropUserId = "interopuserId"; + public const string InteropUser_Root = InteropUsers_Root + "{" + InteropUserId + "}"; + + // /localemulator + public const string LocalEmulatorPathSegment = "localemulator"; + public const string LocalEmulator_Root = Root + "/" + LocalEmulatorPathSegment + "/"; + + // /emulator/defaultIdentity + public const string LocalEmulatorManagedIdentityPathSegment = "managedIdentity"; + public const string LocalEmulatorManagedIdentity_Root = LocalEmulator_Root + "/" + LocalEmulatorManagedIdentityPathSegment + "/"; + + // /retriablewritecachedresponse + public const string RetriableWriteCachedResponsePathSegment = "retriablewritecachedresponse"; + public const string RetriableWriteCachedResponse_Root = Root + "/" + RetriableWriteCachedResponsePathSegment + "/"; + + // urls like http://hostname/accounts/{id}/address + // /accounts/{id}/ + public const string AccountsPathSegment = "accounts"; + public const string AccountId = "accountId"; + public const string FederationEndpoint_Root = Root + "/" + AccountsPathSegment + "/{" + AccountId + "}"; + + // /accounts/{id}/address + public const string FederationEndpoint_Address_Root = FederationEndpoint_Root + "/" + AddressPathSegment + "/"; + + // /encryptionscopes + public const string EncryptionScopesPathSegment = "encryptionscopes"; + public const string EncryptionScopes_Root = Root + "/" + EncryptionScopesPathSegment + "/"; + + // /clientconfigs + public const string ClientConfigPathSegment = "clientconfigs"; + public const string ClientConfig_Root = Root + ClientConfigPathSegment; + public const string FederationEndpoint_ClientConfig_Root = FederationEndpoint_Root + ClientConfig_Root; + + + // /encryptionscopes/{id} + public const string EncryptionScopeId = "encryptionscopeid"; + public const string EncryptionScope_Root = EncryptionScopes_Root + "{" + EncryptionScopeId + "}"; + + public const string OperationResultsSegment = "operationResults"; + public const string OperationIdSegment = "operationId"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource} + public const string DatabaseAccountResourceSegment = "databaseAccountResource"; + public const string DatabaseAccountResourceSegment_Root = DatabaseAccountType_Root + "/{" + DatabaseAccountResourceSegment + "}"; + + // ----------------- Native Control Plane RBAC for Cassandra ----------------- + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions + public const string CassandraRoleDefinitionResourceType = "cassandraRoleDefinitions"; + public const string CassandraRoleDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + CassandraRoleDefinitionResourceType; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{cassandraRoleDefinitionResource} + public const string CassandraRoleDefinitionResourceSegment = "cassandraRoleDefinitionResource"; + public const string CassandraRoleDefinitionResourceSegment_Root = CassandraRoleDefinitionResourceType_Root + "/{" + CassandraRoleDefinitionResourceSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{cassandraRoleDefinitionResource}/operationResults + public const string CassandraRoleDefinitionOperationResultsSegment_Root = CassandraRoleDefinitionResourceSegment_Root + "/" + OperationResultsSegment; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/cassandraRoleDefinitions/{mongoRoleDefinitionResource}/operationResults/{operationId} + public const string CassandraRoleDefinitionOperationResultSegment_Root = CassandraRoleDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; + + // ----------------- Native Control Plane RBAC for Mongo ----------------- + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions + public const string MongoDbRoleDefinitionResourceType = "mongodbRoleDefinitions"; + public const string MongoDbRoleDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + MongoDbRoleDefinitionResourceType; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongodbRoleDefinitionResource} + public const string MongoDbRoleDefinitionResourceSegment = "mongodbRoleDefinitionResource"; + public const string MongoDbRoleDefinitionResourceSegment_Root = MongoDbRoleDefinitionResourceType_Root + "/{" + MongoDbRoleDefinitionResourceSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongodbRoleDefinitionResource}/operationResults + public const string MongoDbRoleDefinitionOperationResultsSegment_Root = MongoDbRoleDefinitionResourceSegment_Root + "/" + OperationResultsSegment; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbRoleDefinitions/{mongoRoleDefinitionResource}/operationResults/{operationId} + public const string MongoDbRoleDefinitionOperationResultSegment_Root = MongoDbRoleDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions + public const string MongoDbUserDefinitionResourceType = "mongodbUserDefinitions"; + public const string MongoDbUserDefinitionResourceType_Root = DatabaseAccountResourceSegment_Root + "/" + MongoDbUserDefinitionResourceType; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource} + public const string MongoDbUserDefinitionResourceSegment = "mongodbUserDefinitionResource"; + public const string MongoDbUserDefinitionResourceSegment_Root = MongoDbUserDefinitionResourceType_Root + "/{" + MongoDbUserDefinitionResourceSegment + "}"; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource}/operationResults + public const string MongoDbUserDefinitionOperationResultsSegment_Root = MongoDbUserDefinitionResourceSegment_Root + "/" + OperationResultsSegment; + + // /subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.DocumentDB/databaseAccounts/{databaseAccountResource}/mongodbUserDefinitions/{mongodbUserDefinitionResource}/operationResults/{operationId} + public const string MongoDbUserDefinitionOperationResultSegment_Root = MongoDbUserDefinitionOperationResultsSegment_Root + "/{" + OperationIdSegment + "}"; + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs b/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs index c1783aa89e..5a9ac176aa 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs @@ -1,2056 +1,2056 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - - internal static class PathsHelper - { - private const char ForwardSlash = '/'; - - private static readonly StringSegment[] EmptyArray = new StringSegment[0]; - - private static readonly char[] PathSeparatorArray = new char[1] { PathsHelper.ForwardSlash }; - - /// - /// The output resourceId can be - /// a: (Rid based) DgJ5AJeIfQABAAAAAAAAAPy3CWY= - /// b: (name based) dbs/dbName/colls/collectionName/docs/documentName/attachments/attachmentName", - /// For name based, it always trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded - /// - /// - /// - /// like dbs, colls - /// - /// - /// - /// - public static bool TryParsePathSegments( - string resourceUrl, - out bool isFeed, - out string resourcePath, - out string resourceIdOrFullName, - out bool isNameBased, - string clientVersion = "") - { - string databaseName = string.Empty; - string collectionName = string.Empty; - - resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); - - if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.Contains(Paths.OperationsPathSegment) && - (resourceUrl.Contains(Paths.PartitionKeyDeletePathSegment) || resourceUrl.Contains(Paths.CollectionTruncatePathsegment))) - { - isFeed = false; - string resourceName = PathsHelper.GetCollectionPath(resourceUrl); - - if(resourceName == null || resourceName.Length < 1) - { - resourcePath = string.Empty; - resourceIdOrFullName = string.Empty; - isNameBased = false; - return false; - } - - resourceIdOrFullName = resourceName[0] == '/' ? resourceName.Substring(1) : resourceName; //ResourceName is expected in the format "dbs/dbname/colls/collname" - resourcePath = Paths.CollectionsPathSegment; - isNameBased = true; - return true; - } - - if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.Contains(Paths.OperationsPathSegment) && - (resourceUrl.Contains(Paths.MetadataCheckAccessPathSegment))) - { - // For metadata check access the, the resource path is always root. - isFeed = false; - resourceIdOrFullName = string.Empty; - resourcePath = Paths.Root; - isNameBased = true; - return true; - } - - return PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionNames(resourceUrl, out isFeed, out resourcePath, out resourceIdOrFullName, out isNameBased, out databaseName, out collectionName, clientVersion, false); - } - - public static bool TryParsePathSegmentsWithDatabaseAndCollectionNames( - string resourceUrl, - out bool isFeed, - out string resourcePath, - out string resourceIdOrFullName, - out bool isNameBased, - out string databaseName, - out string collectionName, - string clientVersion = "", - bool parseDatabaseAndCollectionNames = false) - { - return PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( - resourceUrl, - out isFeed, - out resourcePath, - out resourceIdOrFullName, - out isNameBased, - out databaseName, - out collectionName, - out _, - clientVersion, - parseDatabaseAndCollectionNames); - } - - /// - /// The output resourceId can be - /// a: (Rid based) DgJ5AJeIfQABAAAAAAAAAPy3CWY= - /// b: (name based) dbs/dbName/colls/collectionName/docs/documentName/attachments/attachmentName", - /// For name based, it always trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded - /// - /// - /// - /// like dbs, colls - /// - /// - /// - /// - /// - /// - /// - /// - public static bool TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( - string resourceUrl, - out bool isFeed, - out string resourcePath, - out string resourceIdOrFullName, - out bool isNameBased, - out string databaseName, - out string collectionName, - out string documentName, - string clientVersion = "", - bool parseDatabaseAndCollectionNames = false) - { - resourcePath = string.Empty; - resourceIdOrFullName = string.Empty; - isFeed = false; - isNameBased = false; - databaseName = string.Empty; - collectionName = string.Empty; - documentName = string.Empty; - - if (string.IsNullOrEmpty(resourceUrl)) - { - return false; - } - - resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); - - string[] segments = resourceUrl.Split(PathsHelper.PathSeparatorArray, StringSplitOptions.RemoveEmptyEntries); - - if (segments == null || segments.Length < 1) - { - return false; - } - - int uriSegmentsCount = segments.Length; - StringSegment segmentOne = new StringSegment(segments[uriSegmentsCount - 1]).Trim(PathsHelper.PathSeparatorArray); - StringSegment segmentTwo = new StringSegment(string.Empty); - if (uriSegmentsCount >= 2) - { - segmentTwo = new StringSegment(segments[uriSegmentsCount - 2]).Trim(PathsHelper.PathSeparatorArray); - } - - // handle control operations - if (PathsHelper.IsRootOperation(segmentTwo, segmentOne) - || PathsHelper.IsTopLevelOperationOperation(segmentTwo, segmentOne)) - { - isFeed = false; - resourceIdOrFullName = string.Empty; - resourcePath = Paths.Root; - - return true; - } - - // handle name based operation - if (uriSegmentsCount >= 2) - { - if (segments[segments.Length - 1].Equals(Paths.RetriableWriteCachedResponsePathSegment, StringComparison.OrdinalIgnoreCase)) - { - isNameBased = true; - isFeed = false; - resourcePath = segments[segments.Length - 1]; - StringSegment trimmedSegment = resourceUrl; - resourceIdOrFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(trimmedSegment)).GetString()); - PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out _); - - return true; - } - - // parse the databaseId or snapshotId as RID. If failed, it is name based routing - // mediaId is special, we will treat it always as RID based. - ResourceId rid; - string firstSegment = segments[0]; - if (firstSegment.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsDatabaseId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.EncryptionScopesPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsEncryptionScopeId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.SnapshotsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsSnapshotId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.RoleDefinitionsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsRoleDefinitionId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.RoleAssignmentsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsRoleAssignmentId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsInteropUserId) - { - isNameBased = true; - } - } - else if (firstSegment.Equals(Paths.AuthPolicyElementsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsAuthPolicyElementId) - { - isNameBased = true; - } - } - - if (isNameBased) - { - return TryParseNameSegments(resourceUrl, segments, out isFeed, out resourcePath, out resourceIdOrFullName, out databaseName, out collectionName, out documentName, parseDatabaseAndCollectionNames); - } - } - - // Feed paths have odd number of segments - if ((uriSegmentsCount % 2 != 0) && PathsHelper.IsResourceType(segmentOne)) - { - isFeed = true; - resourcePath = segmentOne.GetString(); - - // The URL for dbs may contain the management endpoint as the segmentTwo which should not be used as resourceId - if (!segmentOne.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) - { - resourceIdOrFullName = segmentTwo.GetString(); - } - } - else if (PathsHelper.IsResourceType(segmentTwo)) - { - isFeed = false; - resourcePath = segmentTwo.GetString(); - resourceIdOrFullName = segmentOne.GetString(); - - // Media ID is not supposed to be used for any ID verification. However, if the old client makes a call for media ID - // we still need to support it. - // For new clients, parse to return the attachment id. For old clients do not modify. - if (!string.IsNullOrEmpty(clientVersion) && - resourcePath.Equals(Paths.MediaPathSegment, StringComparison.OrdinalIgnoreCase)) - { - string attachmentId = null; - byte storeIndex = 0; - if (!MediaIdHelper.TryParseMediaId(resourceIdOrFullName, out attachmentId, out storeIndex)) - { - return false; - } - - resourceIdOrFullName = attachmentId; - } - } - else - { - return false; - } - - return true; - } - - public static void ParseDatabaseNameAndCollectionNameFromUrlSegments( - string[] segments, - out string databaseName, - out string collectionName) - { - PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments( - segments, - out databaseName, - out collectionName, - out _); - } - - public static void ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments( - string[] segments, - out string databaseName, - out string collectionName, - out string documentName) - { - databaseName = string.Empty; - collectionName = string.Empty; - documentName = string.Empty; - - if (segments == null || segments.Length < 2) - { - return; - } - - if (string.Equals(segments[0], Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) - { - databaseName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[1]))).GetString()); - if (segments.Length >= 4 && string.Equals(segments[2], Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - collectionName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[3]))).GetString()); - } - - if (segments.Length >= 6 && string.Equals(segments[4], Paths.DocumentsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - documentName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[5]))).GetString()); - } - } - } - - /// - /// Try to parse resource URL for non root operation. - /// Valid URL example is - /// /dbs/d557cdb4-21ac-46c9-ab17-33285c2ab040/colls/ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0/operations/partitionkeydelete - /// and RID based - /// /dbs/1fIrAA==/colls/1fIrANmsTf4=/operations/partitionkeydelete - /// - /// Resource URL. - /// Indicates resource path. For collection level it will be . - /// Resource name or resourceId. Always trimmed. - /// Database name extracted from the URL. - /// Collection name extracted from the URL. - /// Resource type mapped for the operation. - /// Operation type mapped for the operation. - /// - public static bool TryParsePathSegmentsWithDatabaseAndCollectionAndOperationNames( - string resourceUrl, - out string resourcePath, - out string resourceIdOrFullName, - out bool isNameBased, - out string databaseName, - out string collectionName, - out ResourceType resourceType, - out OperationType operationType) - { - resourcePath = string.Empty; - resourceIdOrFullName = string.Empty; - isNameBased = false; - databaseName = string.Empty; - collectionName = string.Empty; - resourceType = ResourceType.Unknown; - operationType = OperationType.Invalid; - - if (string.IsNullOrEmpty(resourceUrl)) - { - return false; - } - - resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); - - string[] segments = resourceUrl.Split(PathsHelper.PathSeparatorArray, StringSplitOptions.RemoveEmptyEntries); - - if (segments == null || segments.Length != 6) - { - return false; - } - - if (!segments[0].Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) - || !segments[2].Equals(Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase) - || !segments[4].Equals(Paths.OperationsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - switch (segments[5]) - { - case Paths.PartitionKeyDeletePathSegment: - { - resourceType = ResourceType.PartitionKey; - operationType = OperationType.Delete; - break; - } - - case Paths.CollectionTruncatePathsegment: - { - resourceType = ResourceType.Collection; - operationType = OperationType.CollectionTruncate; - break; - } - - default: - { - // Unknown operation. - return false; - } - } - - resourcePath = Paths.CollectionsPathSegment; - databaseName = Uri.UnescapeDataString(segments[1]); - collectionName = Uri.UnescapeDataString(segments[3]); - - if (!ResourceId.TryParse(segments[3], out ResourceId id) || !id.IsDocumentCollectionId) - { - // Resource name includes database and collection resource ids. For example dbs/d557cdb4-21ac-46c9-ab17-33285c2ab040/colls/ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0. - // Concatenation of the segments is done to support repeating slashes on the URL like dbs//d557cdb4-21ac-46c9-ab17-33285c2ab040//colls//ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0. - resourceIdOrFullName = $"{segments[0]}{PathsHelper.ForwardSlash}{segments[1]}{PathsHelper.ForwardSlash}{segments[2]}{PathsHelper.ForwardSlash}{segments[3]}"; - isNameBased = true; - } - else - { - resourceIdOrFullName = segments[3]; - } - - return true; - } - - private static bool TryParseNameSegments( - string resourceUrl, - string[] segments, - out bool isFeed, - out string resourcePath, - out string resourceFullName, - out string databaseName, - out string collectionName, - out string documentName, - bool parseDatabaseAndCollectionNames) - { - isFeed = false; - resourcePath = string.Empty; - resourceFullName = string.Empty; - databaseName = string.Empty; - collectionName = string.Empty; - documentName = string.Empty; - - if (segments == null || segments.Length < 1) - { - return false; - } - - if (segments.Length % 2 == 0) - { - // even number, assume it is individual resource. - if (PathsHelper.IsResourceType(segments[segments.Length - 2])) - { - resourcePath = segments[segments.Length - 2]; - resourceFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(resourceUrl))).GetString()); - if (parseDatabaseAndCollectionNames) - { - PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out documentName); - } - - return true; - } - } - else - { - // odd number, assume it is feed request - if (PathsHelper.IsResourceType(segments[segments.Length - 1])) - { - isFeed = true; - resourcePath = segments[segments.Length - 1]; - // remove the trailing resource type - StringSegment trimmedSegment = resourceUrl; - trimmedSegment = trimmedSegment.Substring(0, UrlUtility.RemoveTrailingSlashes(trimmedSegment).LastIndexOf(Paths.Root[0])); - resourceFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(trimmedSegment)).GetString()); - if (parseDatabaseAndCollectionNames) - { - // feed requests would not point to a document so ignore document Name. - PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out _); - } - - return true; - } - } - - return false; - } - - public static ResourceType GetResourcePathSegment(string resourcePathSegment) - { - if (string.IsNullOrEmpty(resourcePathSegment)) - { - string message = string.Format(CultureInfo.CurrentUICulture, RMResources.StringArgumentNullOrEmpty, "resourcePathSegment"); - Debug.Assert(false, message); - throw new BadRequestException(message); - } - - switch (resourcePathSegment.ToLowerInvariant()) - { - case Paths.AttachmentsPathSegment: - return ResourceType.Attachment; - - case Paths.CollectionsPathSegment: - return ResourceType.Collection; - - case Paths.DatabasesPathSegment: - return ResourceType.Database; - - case Paths.EncryptionScopesPathSegment: - return ResourceType.EncryptionScope; - - case Paths.PermissionsPathSegment: - return ResourceType.Permission; - - case Paths.UsersPathSegment: - return ResourceType.User; - - case Paths.ClientEncryptionKeysPathSegment: - return ResourceType.ClientEncryptionKey; - - case Paths.UserDefinedTypesPathSegment: - return ResourceType.UserDefinedType; - - case Paths.DocumentsPathSegment: - return ResourceType.Document; - - case Paths.StoredProceduresPathSegment: - return ResourceType.StoredProcedure; - - case Paths.UserDefinedFunctionsPathSegment: - return ResourceType.UserDefinedFunction; - - case Paths.TriggersPathSegment: - return ResourceType.Trigger; - - case Paths.ConflictsPathSegment: - return ResourceType.Conflict; - - case Paths.OffersPathSegment: - return ResourceType.Offer; - - case Paths.SchemasPathSegment: - return ResourceType.Schema; - - case Paths.PartitionKeyRangesPathSegment: - return ResourceType.PartitionKeyRange; - - case Paths.MediaPathSegment: - return ResourceType.Media; - - case Paths.AddressPathSegment: - return ResourceType.Address; - - case Paths.SnapshotsPathSegment: - return ResourceType.Snapshot; - - case Paths.RoleDefinitionsPathSegment: - return ResourceType.RoleDefinition; - - case Paths.RoleAssignmentsPathSegment: - return ResourceType.RoleAssignment; - - case Paths.AuthPolicyElementsPathSegment: - return ResourceType.AuthPolicyElement; - - case Paths.SystemDocumentsPathSegment: - return ResourceType.SystemDocument; - - case Paths.PartitionedSystemDocumentsPathSegment: - return ResourceType.PartitionedSystemDocument; - - case Paths.InteropUsersPathSegment: - return ResourceType.InteropUser; - } - - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourcePathSegment); - Debug.Assert(false, errorMessage); - throw new BadRequestException(errorMessage); - } - - public static string GetResourcePath(ResourceType resourceType) - { - switch (resourceType) - { - case ResourceType.Database: - return Paths.DatabasesPathSegment; - - case ResourceType.EncryptionScope: - return Paths.EncryptionScopesPathSegment; - - case ResourceType.Collection: - case ResourceType.PartitionKey: - return Paths.CollectionsPathSegment; - - case ResourceType.Document: - return Paths.DocumentsPathSegment; - - case ResourceType.StoredProcedure: - return Paths.StoredProceduresPathSegment; - - case ResourceType.UserDefinedFunction: - return Paths.UserDefinedFunctionsPathSegment; - - case ResourceType.Trigger: - return Paths.TriggersPathSegment; - - case ResourceType.Conflict: - return Paths.ConflictsPathSegment; - - case ResourceType.Attachment: - return Paths.AttachmentsPathSegment; - - case ResourceType.User: - return Paths.UsersPathSegment; - - case ResourceType.ClientEncryptionKey: - return Paths.ClientEncryptionKeysPathSegment; - - case ResourceType.UserDefinedType: - return Paths.UserDefinedTypesPathSegment; - - case ResourceType.Permission: - return Paths.PermissionsPathSegment; - - case ResourceType.Offer: - return Paths.OffersPathSegment; - - case ResourceType.PartitionKeyRange: - return Paths.PartitionKeyRangesPathSegment; - - case ResourceType.Media: - return Paths.Medias_Root; - - case ResourceType.Schema: - return Paths.SchemasPathSegment; - - case ResourceType.Snapshot: - return Paths.SnapshotsPathSegment; - - case ResourceType.PartitionedSystemDocument: - return Paths.PartitionedSystemDocumentsPathSegment; - - case ResourceType.RoleDefinition: - return Paths.RoleDefinitionsPathSegment; - - case ResourceType.RoleAssignment: - return Paths.RoleAssignmentsPathSegment; - - case ResourceType.Transaction: - return Paths.TransactionsPathSegment; - - case ResourceType.SystemDocument: - return Paths.SystemDocumentsPathSegment; - - case ResourceType.InteropUser: - return Paths.InteropUsersPathSegment; - - case ResourceType.AuthPolicyElement: - return Paths.AuthPolicyElementsPathSegment; - - case ResourceType.RetriableWriteCachedResponse: - return Paths.RetriableWriteCachedResponsePathSegment; - -#if !COSMOSCLIENT - case ResourceType.MasterPartition: - case ResourceType.ServerPartition: - return Paths.PartitionsPathSegment; - - case ResourceType.StorageAuthToken: - return Paths.StorageAuthTokenPathSegment; - - case ResourceType.RidRange: - return Paths.RidRangePathSegment; - - case ResourceType.VectorClock: - return Paths.VectorClockPathSegment; - - case ResourceType.PartitionSetInformation: - case ResourceType.XPReplicatorAddress: - case ResourceType.Topology: - case ResourceType.Replica: - case ResourceType.ServiceFabricService: - case ResourceType.RestoreMetadata: - case ResourceType.Module: - case ResourceType.ModuleCommand: - case ResourceType.TransportControlCommand: -#endif - case ResourceType.DatabaseAccount: - case ResourceType.Address: - case ResourceType.Record: - case ResourceType.BatchApply: - case ResourceType.ControllerService: - return Paths.Root; - - default: - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); - Debug.Assert(false, errorMessage); - throw new BadRequestException(errorMessage); - } - } - - public static string GeneratePath(ResourceType resourceType, DocumentServiceRequest request, bool isFeed, bool notRequireValidation = false) - { - if (request.IsNameBased) - { - return PathsHelper.GeneratePathForNameBased(resourceType, request.ResourceAddress, isFeed, request.OperationType, notRequireValidation); - } - else - { - return PathsHelper.GeneratePath(resourceType, request.ResourceId, isFeed, request.OperationType); - } - } - - public static string GenerateUserDefinedTypePath(string databaseName, string typeName) - { - return Paths.DatabasesPathSegment + "/" + databaseName + "/" + Paths.UserDefinedTypesPathSegment + "/" + typeName; - } - - public static string GetCollectionPath(string resourceFullName) - { - if (resourceFullName != null) - { - int index = resourceFullName.Length > 0 && resourceFullName[0] == '/' ? resourceFullName.IndexOfNth('/', 5) : resourceFullName.IndexOfNth('/', 4); - if (index > 0) - return resourceFullName.Substring(0, index); - } - return resourceFullName; - } - - public static string GetDatabasePath(string resourceFullName) - { - if (resourceFullName != null) - { - int index = resourceFullName.Length > 0 && resourceFullName[0] == '/' ? resourceFullName.IndexOfNth('/', 3) : resourceFullName.IndexOfNth('/', 2); - if (index > 0) - return resourceFullName.Substring(0, index); - } - return resourceFullName; - } - - public static string GetParentByIndex(string resourceFullName, int segmentIndex) - { - int index = resourceFullName.IndexOfNth('/', segmentIndex); - if (index > 0) - return resourceFullName.Substring(0, index); - else - { - index = resourceFullName.IndexOfNth('/', segmentIndex - 1); - if (index > 0) - return resourceFullName; - else - return null; - } - } - - public static string GeneratePathForNameBased(Type resourceType, string resourceOwnerFullName, string resourceName) - { - if (resourceName == null) - return null; - - if (resourceType == typeof(Database)) - { - return Paths.DatabasesPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(Snapshot)) - { - return Paths.SnapshotsPathSegment + "/" + resourceName; - } - else if (resourceOwnerFullName == null) - { - return null; - } - else if (resourceType == typeof(DocumentCollection)) - { - return resourceOwnerFullName + "/" + Paths.CollectionsPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(ClientEncryptionKey)) - { - return resourceOwnerFullName + "/" + Paths.ClientEncryptionKeysPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(StoredProcedure)) - { - return resourceOwnerFullName + "/" + Paths.StoredProceduresPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(UserDefinedFunction)) - { - return resourceOwnerFullName + "/" + Paths.UserDefinedFunctionsPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(Trigger)) - { - return resourceOwnerFullName + "/" + Paths.TriggersPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(Conflict)) - { - return resourceOwnerFullName + "/" + Paths.ConflictsPathSegment + "/" + resourceName; - } - else if (typeof(Attachment).IsAssignableFrom(resourceType)) - { - return resourceOwnerFullName + "/" + Paths.AttachmentsPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(User)) - { - return resourceOwnerFullName + "/" + Paths.UsersPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(UserDefinedType)) - { - return resourceOwnerFullName + "/" + Paths.UserDefinedTypesPathSegment + "/" + resourceName; - } - else if (typeof(Permission).IsAssignableFrom(resourceType)) - { - return resourceOwnerFullName + "/" + Paths.PermissionsPathSegment + "/" + resourceName; - } - else if (typeof(Document).IsAssignableFrom(resourceType)) - { - return resourceOwnerFullName + "/" + Paths.DocumentsPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(Offer)) - { - return Paths.OffersPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(Schema)) - { - return resourceOwnerFullName + "/" + Paths.SchemasPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(SystemDocument)) - { - return resourceOwnerFullName + "/" + Paths.SystemDocumentsPathSegment + "/" + resourceName; - } - else if (resourceType == typeof(PartitionedSystemDocument)) - { - return resourceOwnerFullName + "/" + Paths.PartitionedSystemDocumentsPathSegment + "/" + resourceName; - } - else if (typeof(Resource).IsAssignableFrom(resourceType)) - { - // just generic Resource type. - return null; - } - - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); - Debug.Assert(false, errorMessage); - throw new BadRequestException(errorMessage); - } - - public static string GeneratePathForNamedBasedInternalResources(ResourceType resourceType, string resourceName) - { - if (resourceName == null) - return null; - - return resourceType switch - { - ResourceType.RoleAssignment => Paths.RoleAssignmentsPathSegment + "/" + resourceName, - ResourceType.RoleDefinition => Paths.RoleDefinitionsPathSegment + "/" + resourceName, - ResourceType.InteropUser => Paths.InteropUsersPathSegment + "/" + resourceName, - ResourceType.AuthPolicyElement => Paths.AuthPolicyElementsPathSegment + "/" + resourceName, - ResourceType.EncryptionScope => Paths.EncryptionScopesPathSegment + "/" + resourceName, - _ => null - }; - } - - // for testing to set to verify server side validation - private static bool isClientSideValidationEnabled = true; - - internal static void SetClientSidevalidation(bool validation) - { - isClientSideValidationEnabled = validation; - } - - private static string GeneratePathForNameBased(ResourceType resourceType, string resourceFullName, bool isFeed, OperationType operationType, bool notRequireValidation = false) - { - if (isFeed && - string.IsNullOrEmpty(resourceFullName) && - resourceType != ResourceType.Database && - resourceType != ResourceType.EncryptionScope && - resourceType != ResourceType.Snapshot && - resourceType != ResourceType.RoleDefinition && - resourceType != ResourceType.RoleAssignment && - resourceType != ResourceType.InteropUser && - resourceType != ResourceType.AuthPolicyElement) - { - string errorMessage = string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType); - throw new BadRequestException(errorMessage); - } - - string resourcePath = null; - ResourceType resourceTypeToValidate; - // Validate resourceFullName comply with the intended resource type. - - if (resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete) - { - resourceTypeToValidate = resourceType; - resourceFullName = resourceFullName + "/" + Paths.OperationsPathSegment + "/" + Paths.PartitionKeyDeletePathSegment; - resourcePath = resourceFullName; - } - else if ((resourceType == ResourceType.Collection) && (operationType == OperationType.CollectionTruncate)) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.OperationsPathSegment + "/" + Paths.CollectionTruncatePathsegment; - } - else if (!isFeed) - { - resourceTypeToValidate = resourceType; - resourcePath = resourceFullName; - } - else if (resourceType == ResourceType.Database) - { - return Paths.DatabasesPathSegment; - } - else if (resourceType == ResourceType.EncryptionScope) - { - return Paths.EncryptionScopesPathSegment; - } - else if (resourceType == ResourceType.Collection) - { - resourceTypeToValidate = ResourceType.Database; - resourcePath = resourceFullName + "/" + Paths.CollectionsPathSegment; - } - else if (resourceType == ResourceType.ClientEncryptionKey) - { - resourceTypeToValidate = ResourceType.Database; - resourcePath = resourceFullName + "/" + Paths.ClientEncryptionKeysPathSegment; - } - else if (resourceType == ResourceType.StoredProcedure) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.StoredProceduresPathSegment; - } - else if (resourceType == ResourceType.UserDefinedFunction) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.UserDefinedFunctionsPathSegment; - } - else if (resourceType == ResourceType.Trigger) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.TriggersPathSegment; - } - else if (resourceType == ResourceType.Conflict) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.ConflictsPathSegment; - } - else if (resourceType == ResourceType.Attachment) - { - resourceTypeToValidate = ResourceType.Document; - resourcePath = resourceFullName + "/" + Paths.AttachmentsPathSegment; - } - else if (resourceType == ResourceType.User) - { - resourceTypeToValidate = ResourceType.Database; - resourcePath = resourceFullName + "/" + Paths.UsersPathSegment; - } - else if (resourceType == ResourceType.UserDefinedType) - { - resourceTypeToValidate = ResourceType.Database; - resourcePath = resourceFullName + "/" + Paths.UserDefinedTypesPathSegment; - } - else if (resourceType == ResourceType.Permission) - { - resourceTypeToValidate = ResourceType.User; - resourcePath = resourceFullName + "/" + Paths.PermissionsPathSegment; - } - else if (resourceType == ResourceType.Document) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.DocumentsPathSegment; - } - else if (resourceType == ResourceType.Offer) - { - return resourceFullName + "/" + Paths.OffersPathSegment; - } - else if (resourceType == ResourceType.PartitionKeyRange) - { - return resourceFullName + "/" + Paths.PartitionKeyRangesPathSegment; - } - else if (resourceType == ResourceType.Schema) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.SchemasPathSegment; - } - else if (resourceType == ResourceType.PartitionedSystemDocument) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.PartitionedSystemDocumentsPathSegment; - } - else if (resourceType == ResourceType.Snapshot) - { - return Paths.SnapshotsPathSegment; - } - else if (resourceType == ResourceType.RoleDefinition) - { - return Paths.RoleDefinitionsPathSegment; - } - else if (resourceType == ResourceType.RoleAssignment) - { - return Paths.RoleAssignmentsPathSegment; - } - else if (resourceType == ResourceType.SystemDocument) - { - resourceTypeToValidate = ResourceType.Collection; - resourcePath = resourceFullName + "/" + Paths.SystemDocumentsPathSegment; - } - else if (resourceType == ResourceType.InteropUser) - { - return Paths.InteropUsersPathSegment; - } - else if (resourceType == ResourceType.AuthPolicyElement) - { - return Paths.AuthPolicyElementsPathSegment; - } - else - { - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); - Debug.Assert(false, errorMessage); - throw new BadRequestException(errorMessage); - } - - if (!notRequireValidation && isClientSideValidationEnabled) - { - if (!ValidateResourceFullName(resourceTypeToValidate, resourceFullName)) - { - string errorMessage = string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType); - throw new BadRequestException(errorMessage); - } - } - return resourcePath; - } - - - public static string GeneratePath(ResourceType resourceType, string ownerOrResourceId, bool isFeed, OperationType operationType = default) - { - if (isFeed && string.IsNullOrEmpty(ownerOrResourceId) && - resourceType != ResourceType.Database && - resourceType != ResourceType.EncryptionScope && - resourceType != ResourceType.Offer && - resourceType != ResourceType.DatabaseAccount && - resourceType != ResourceType.Snapshot && - resourceType != ResourceType.RoleAssignment && - resourceType != ResourceType.RoleDefinition && - resourceType != ResourceType.InteropUser && - resourceType != ResourceType.AuthPolicyElement -#if !COSMOSCLIENT - && resourceType != ResourceType.MasterPartition && - resourceType != ResourceType.ServerPartition && - resourceType != ResourceType.Topology && - resourceType != ResourceType.RidRange && - resourceType != ResourceType.VectorClock && - resourceType != ResourceType.StorageAuthToken -#endif - ) - { - throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType)); - } - - if (isFeed && resourceType == ResourceType.EncryptionScope) - { - return Paths.EncryptionScopesPathSegment; - } - else if (resourceType == ResourceType.EncryptionScope) - { - return Paths.EncryptionScopesPathSegment + "/" + ownerOrResourceId.ToString(); - } - - if (isFeed && resourceType == ResourceType.Database) - { - return Paths.DatabasesPathSegment; - } - else if (resourceType == ResourceType.Database) - { - return Paths.DatabasesPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Collection) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment; - } - else if (resourceType == ResourceType.Collection) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Offer) - { - return Paths.OffersPathSegment; - } - else if (resourceType == ResourceType.Offer) - { - return Paths.OffersPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if (isFeed && resourceType == ResourceType.StoredProcedure) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.StoredProceduresPathSegment; - } - else if (resourceType == ResourceType.StoredProcedure) - { - ResourceId storedProcedureId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + storedProcedureId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + storedProcedureId.DocumentCollectionId.ToString() + "/" + - Paths.StoredProceduresPathSegment + "/" + storedProcedureId.StoredProcedureId.ToString(); - } - else if (isFeed && resourceType == ResourceType.UserDefinedFunction) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.UserDefinedFunctionsPathSegment; - } - else if (resourceType == ResourceType.UserDefinedFunction) - { - ResourceId functionId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + functionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + functionId.DocumentCollectionId.ToString() + "/" + - Paths.UserDefinedFunctionsPathSegment + "/" + functionId.UserDefinedFunctionId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Trigger) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.TriggersPathSegment; - } - else if (resourceType == ResourceType.Trigger) - { - ResourceId triggerId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + triggerId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + triggerId.DocumentCollectionId.ToString() + "/" + - Paths.TriggersPathSegment + "/" + triggerId.TriggerId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Conflict) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.ConflictsPathSegment; - } - else if (resourceType == ResourceType.Conflict) - { - ResourceId conflictId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + conflictId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + conflictId.DocumentCollectionId.ToString() + "/" + - Paths.ConflictsPathSegment + "/" + conflictId.ConflictId.ToString(); - } - else if (isFeed && resourceType == ResourceType.PartitionKeyRange) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.PartitionKeyRangesPathSegment; - } - else if (resourceType == ResourceType.PartitionKeyRange) - { - ResourceId partitionKeyRangeId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + partitionKeyRangeId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + partitionKeyRangeId.DocumentCollectionId.ToString() + "/" + - Paths.PartitionKeyRangesPathSegment + "/" + partitionKeyRangeId.PartitionKeyRangeId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Attachment) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.DocumentsPathSegment + "/" + documentCollectionId.DocumentId.ToString() + "/" + - Paths.AttachmentsPathSegment; - } - else if (resourceType == ResourceType.Attachment) - { - ResourceId attachmentId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + attachmentId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + attachmentId.DocumentCollectionId.ToString() + "/" + - Paths.DocumentsPathSegment + "/" + attachmentId.DocumentId.ToString() + "/" + - Paths.AttachmentsPathSegment + "/" + attachmentId.AttachmentId.ToString(); - } - else if (isFeed && resourceType == ResourceType.User) - { - return - Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + - Paths.UsersPathSegment; - } - else if (resourceType == ResourceType.User) - { - ResourceId userId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + userId.DatabaseId.ToString() + "/" + - Paths.UsersPathSegment + "/" + userId.UserId.ToString(); - } - else if (isFeed && resourceType == ResourceType.ClientEncryptionKey) - { - return Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + - Paths.ClientEncryptionKeysPathSegment; - } - else if (resourceType == ResourceType.ClientEncryptionKey) - { - ResourceId clientEncryptionKeyId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + clientEncryptionKeyId.DatabaseId.ToString() + "/" + - Paths.ClientEncryptionKeysPathSegment + "/" + clientEncryptionKeyId.ClientEncryptionKeyId.ToString(); - } - else if (isFeed && resourceType == ResourceType.UserDefinedType) - { - return - Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + - Paths.UserDefinedTypesPathSegment; - } - else if (resourceType == ResourceType.UserDefinedType) - { - ResourceId userDefinedTypeId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + userDefinedTypeId.DatabaseId.ToString() + "/" + - Paths.UserDefinedTypesPathSegment + "/" + userDefinedTypeId.UserDefinedTypeId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Permission) - { - ResourceId userId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + userId.DatabaseId.ToString() + "/" + - Paths.UsersPathSegment + "/" + userId.UserId.ToString() + "/" + - Paths.PermissionsPathSegment; - } - else if (resourceType == ResourceType.Permission) - { - ResourceId permissionId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + permissionId.DatabaseId.ToString() + "/" + - Paths.UsersPathSegment + "/" + permissionId.UserId.ToString() + "/" + - Paths.PermissionsPathSegment + "/" + permissionId.PermissionId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Document) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.DocumentsPathSegment; - } - else if (resourceType == ResourceType.Document) - { - ResourceId documentId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + documentId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentId.DocumentCollectionId.ToString() + "/" + - Paths.DocumentsPathSegment + "/" + documentId.DocumentId.ToString(); - } - else if (isFeed && resourceType == ResourceType.Schema) - { - ResourceId schemaCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + schemaCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + schemaCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.SchemasPathSegment; - } - else if (resourceType == ResourceType.Schema) - { - ResourceId schemaId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + schemaId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + schemaId.DocumentCollectionId.ToString() + "/" + - Paths.SchemasPathSegment + "/" + schemaId.SchemaId.ToString(); - } - else if (isFeed && resourceType == ResourceType.DatabaseAccount) - { - return Paths.DatabaseAccountSegment; - } - else if (resourceType == ResourceType.DatabaseAccount && operationType == OperationType.MetadataCheckAccess) - { - return Paths.OperationsPathSegment + "/" + Paths.Operations_MetadataCheckAccess; - } - else if (resourceType == ResourceType.DatabaseAccount) - { - return Paths.DatabaseAccountSegment + "/" + ownerOrResourceId; - } - else if (isFeed && resourceType == ResourceType.Snapshot) - { - return Paths.SnapshotsPathSegment; - } - else if (resourceType == ResourceType.Snapshot) - { - return Paths.SnapshotsPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if(resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + Paths.OperationsPathSegment + "/" + Paths.PartitionKeyDeletePathSegment; - } - else if (isFeed && resourceType == ResourceType.RoleAssignment) - { - return Paths.RoleAssignmentsPathSegment; - } - else if (isFeed && resourceType == ResourceType.RoleDefinition) - { - return Paths.RoleDefinitionsPathSegment; - } - else if (isFeed && resourceType == ResourceType.AuthPolicyElement) - { - return Paths.AuthPolicyElementsPathSegment; - } - else if (resourceType == ResourceType.RoleAssignment) - { - return Paths.RoleAssignmentsPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if (resourceType == ResourceType.RoleDefinition) - { - return Paths.RoleDefinitionsPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if (resourceType == ResourceType.AuthPolicyElement) - { - return Paths.AuthPolicyElementsPathSegment + "/" + ownerOrResourceId.ToString(); - } - else if (isFeed && resourceType == ResourceType.SystemDocument) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.SystemDocumentsPathSegment; - } - else if (resourceType == ResourceType.SystemDocument) - { - ResourceId sysdocId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + sysdocId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + sysdocId.DocumentCollectionId.ToString() + "/" + - Paths.SystemDocumentsPathSegment + "/" + sysdocId.SystemDocumentId.ToString(); - } - else if (isFeed && resourceType == ResourceType.PartitionedSystemDocument) - { - ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); - - return - Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + - Paths.PartitionedSystemDocumentsPathSegment; - } - else if (resourceType == ResourceType.PartitionedSystemDocument) - { - ResourceId sysdocId = ResourceId.Parse(ownerOrResourceId); - - return Paths.DatabasesPathSegment + "/" + sysdocId.DatabaseId.ToString() + "/" + - Paths.CollectionsPathSegment + "/" + sysdocId.DocumentCollectionId.ToString() + "/" + - Paths.PartitionedSystemDocumentsPathSegment + "/" + sysdocId.PartitionedSystemDocumentId.ToString(); - } - else if (isFeed && resourceType == ResourceType.InteropUser) - { - return Paths.InteropUsersPathSegment; - } - else if (resourceType == ResourceType.InteropUser) - { - return Paths.InteropUsersPathSegment + "/" + ownerOrResourceId.ToString(); - } -#if !COSMOSCLIENT - else if (isFeed && resourceType == ResourceType.MasterPartition) - { - return Paths.PartitionsPathSegment; - } - else if (resourceType == ResourceType.MasterPartition) - { - return Paths.PartitionsPathSegment + "/" + ownerOrResourceId; - } - else if (isFeed && resourceType == ResourceType.ServerPartition) - { - return Paths.PartitionsPathSegment; - } - else if (resourceType == ResourceType.ServerPartition) - { - return Paths.PartitionsPathSegment + "/" + ownerOrResourceId; - } - else if (isFeed && resourceType == ResourceType.Topology) - { - return Paths.TopologyPathSegment; - } - else if (resourceType == ResourceType.Topology) - { - return Paths.TopologyPathSegment + "/" + ownerOrResourceId; - } - else if (resourceType == ResourceType.RidRange) - { - return Paths.RidRangePathSegment + "/" + ownerOrResourceId; - } - else if (resourceType == ResourceType.VectorClock) - { - return Paths.VectorClockPathSegment + "/" + ownerOrResourceId; - } - else if (isFeed && resourceType == ResourceType.StorageAuthToken) - { - return Paths.StorageAuthTokenPathSegment; - } - else if (resourceType == ResourceType.StorageAuthToken) - { - return Paths.StorageAuthTokenPathSegment + "/" + ownerOrResourceId; - } -#endif - - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); - Debug.Assert(false, errorMessage); - throw new BadRequestException(errorMessage); - } - - public static string GenerateRootOperationPath(OperationType operationType) - { - switch (operationType) - { -#if !COSMOSCLIENT - case OperationType.Pause: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Pause; - case OperationType.Recycle: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Recycle; - case OperationType.Resume: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Resume; - case OperationType.Stop: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Stop; - case OperationType.Crash: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Crash; - case OperationType.ForceConfigRefresh: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_ForceConfigRefresh; - case OperationType.ReportThroughputUtilization: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_ReportThroughputUtilization; - case OperationType.BatchReportThroughputUtilization: - return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_BatchReportThroughputUtilization; - case OperationType.ControllerBatchGetOutput: - return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetOutput; - case OperationType.ControllerBatchReportCharges: - return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchReportCharges; - case OperationType.ControllerBatchAutoscaleRUsConsumption: - return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchAutoscaleRUsConsumption; - case OperationType.ControllerBatchGetAutoscaleAggregateOutput: - return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput; - case OperationType.GetConfiguration: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetConfiguration; - case OperationType.GetFederationConfigurations: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetFederationConfigurations; - case OperationType.GetDatabaseAccountConfigurations: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetDatabaseAccountConfigurations; - case OperationType.XPDatabaseAccountMetaData: - return Paths.OperationsPathSegment + "/" + Paths.Operations_XPDatabaseAccountMetaData; - case OperationType.GetGraphDatabaseAccountConfiguration: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetGraphDatabaseAccountConfiguration; - case OperationType.GetStorageServiceConfigurations: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageServiceConfigurations; - case OperationType.GetStorageAccountKey: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageAccountKey; - case OperationType.GetStorageAccountSas: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageAccountSas; - case OperationType.GetUnwrappedDek: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetUnwrappedDek; - case OperationType.GetDekProperties: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetDekProperties; - case OperationType.GetCustomerManagedKeyStatus: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetCustomerManagedKeyStatus; - case OperationType.ReadReplicaFromMasterPartition: - return Paths.OperationsPathSegment + "/" + Paths.Operations_ReadReplicaFromMasterPartition; - case OperationType.ReadReplicaFromServerPartition: - return Paths.OperationsPathSegment + "/" + Paths.Operations_ReadReplicaFromServerPartition; - case OperationType.MasterInitiatedProgressCoordination: - return Paths.OperationsPathSegment + "/" + Paths.Operations_MasterInitiatedProgressCoordination; - case OperationType.GetAadGroups: - return Paths.OperationsPathSegment + "/" + Paths.Operations_GetAadGroups; - case OperationType.MetadataCheckAccess: - return Paths.OperationsPathSegment + "/" + Paths.Operations_MetadataCheckAccess; -#endif - - default: - Debug.Assert(false, "Unsupported operation type for replica"); - throw new NotFoundException(); - } - } - - private static bool IsResourceType(in StringSegment resourcePathSegment) - { - if (resourcePathSegment.IsNullOrEmpty()) - { - return false; - } - - return resourcePathSegment.Equals(Paths.AttachmentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PermissionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.UsersPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.ClientEncryptionKeysPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.StorageAuthTokenPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.UserDefinedTypesPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.DocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.StoredProceduresPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.TriggersPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.UserDefinedFunctionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.ConflictsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.MediaPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.OffersPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PartitionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.DatabaseAccountSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.TopologyPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PartitionKeyRangesPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PartitionKeyRangePreSplitSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PartitionKeyRangePostSplitSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.SchemasPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.RidRangePathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.VectorClockPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.AddressPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.SnapshotsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.PartitionedSystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.RoleDefinitionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.RoleAssignmentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.TransactionsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.SystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.AuthPolicyElementsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.SystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.EncryptionScopesPathSegment, StringComparison.OrdinalIgnoreCase) || - resourcePathSegment.Equals(Paths.RetriableWriteCachedResponsePathSegment, StringComparison.OrdinalIgnoreCase); - } - - private static bool IsRootOperation(in StringSegment operationSegment, in StringSegment operationTypeSegment) - { - if (operationSegment.IsNullOrEmpty()) - { - return false; - } - - if (operationTypeSegment.IsNullOrEmpty()) - { - return false; - } - - if (operationSegment.Compare(Paths.OperationsPathSegment, StringComparison.OrdinalIgnoreCase) != 0) - { - return false; - } - - return operationTypeSegment.Equals(Paths.ReplicaOperations_Pause, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_Resume, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_Stop, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_Recycle, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_Crash, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_ReportThroughputUtilization, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ReplicaOperations_BatchReportThroughputUtilization, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetOutput, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ControllerOperations_BatchReportCharges, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ControllerOperations_BatchAutoscaleRUsConsumption, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetFederationConfigurations, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetStorageServiceConfigurations, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetConfiguration, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetStorageAccountKey, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetStorageAccountSas, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetDatabaseAccountConfigurations, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_XPDatabaseAccountMetaData, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetUnwrappedDek, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetDekProperties, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetCustomerManagedKeyStatus, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromMasterPartition, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromServerPartition, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_MasterInitiatedProgressCoordination, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetAadGroups, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_MetadataCheckAccess, StringComparison.OrdinalIgnoreCase); - } - - private static bool IsTopLevelOperationOperation(in StringSegment replicaSegment, in StringSegment addressSegment) - { - if (replicaSegment.IsNullOrEmpty() && // replica part should be empty - (addressSegment.Compare(Paths.XPReplicatorAddressPathSegment, StringComparison.OrdinalIgnoreCase) == 0 || - addressSegment.Compare(Paths.ComputeGatewayChargePathSegment, StringComparison.OrdinalIgnoreCase) == 0 || - addressSegment.Compare(Paths.ServiceReservationPathSegment, StringComparison.OrdinalIgnoreCase) == 0)) - { - return true; - } - - return false; - } - - public static string RemoveAccountsSegment(string resourceUrl) - { - if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.StartsWith("/accounts/", StringComparison.OrdinalIgnoreCase)) - { - int index = resourceUrl.IndexOfNth('/', 3); - resourceUrl = resourceUrl.Substring(index, resourceUrl.Length - index); - } - - return resourceUrl; - } - - internal static bool IsNameBased(string resourceIdOrFullName) - { - // quick way to tell whether it is resourceId nor not, non conclusively. - if (!string.IsNullOrEmpty(resourceIdOrFullName) && - ((resourceIdOrFullName.Length > 4 && resourceIdOrFullName[3] == '/') || - (resourceIdOrFullName.StartsWith(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase)))) - { - return true; - } - return false; - } - - internal static int IndexOfNth(this string str, char value, int n) - { - if (string.IsNullOrEmpty(str) || n <= 0 || n > str.Length) - { - return -1; - } - - int remaining = n; - for (int i = 0; i < str.Length; i++) - { - if (str[i] == value) - { - if (--remaining == 0) - { - return i; - } - } - } - - return -1; - } - - internal static bool ValidateResourceFullName(ResourceType resourceType, string resourceFullName) - { - string[] segments = resourceFullName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); - - string[] resourcePathArray = GetResourcePathArray(resourceType); - - if (resourcePathArray == null) - return false; - - if (segments.Length != resourcePathArray.Length * 2) - return false; - - for (int i = 0; i < resourcePathArray.Length; i++) - { - if (string.Compare(resourcePathArray[i], segments[2 * i], StringComparison.Ordinal) != 0) - { - return false; - } - } - return true; - } - - internal static string[] GetResourcePathArray(ResourceType resourceType) - { - List segments = new List(); - - if (resourceType == ResourceType.Snapshot) - { - segments.Add(Paths.SnapshotsPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.EncryptionScope) - { - segments.Add(Paths.EncryptionScopesPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.RoleDefinition) - { - segments.Add(Paths.RoleDefinitionsPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.RoleAssignment) - { - segments.Add(Paths.RoleAssignmentsPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.AuthPolicyElement) - { - segments.Add(Paths.AuthPolicyElementsPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.Offer) - { - segments.Add(Paths.OffersPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.Address) - { - segments.Add(Paths.AddressPathSegment); - return segments.ToArray(); - } - - if (resourceType == ResourceType.InteropUser) - { - segments.Add(Paths.InteropUsersPathSegment); - return segments.ToArray(); - } - - segments.Add(Paths.DatabasesPathSegment); - - if (resourceType == ResourceType.Permission || - resourceType == ResourceType.User) - { - segments.Add(Paths.UsersPathSegment); - if (resourceType == ResourceType.Permission) - segments.Add(Paths.PermissionsPathSegment); - } - else if (resourceType == ResourceType.UserDefinedType) - { - segments.Add(Paths.UserDefinedTypesPathSegment); - } - else if (resourceType == ResourceType.ClientEncryptionKey) - { - segments.Add(Paths.ClientEncryptionKeysPathSegment); - } - else if ( - resourceType == ResourceType.Collection || - resourceType == ResourceType.StoredProcedure || - resourceType == ResourceType.UserDefinedFunction || - resourceType == ResourceType.Trigger || - resourceType == ResourceType.Conflict || - resourceType == ResourceType.Attachment || - resourceType == ResourceType.Document || - resourceType == ResourceType.PartitionKeyRange || - resourceType == ResourceType.Schema || - resourceType == ResourceType.PartitionedSystemDocument || - resourceType == ResourceType.SystemDocument) - { - segments.Add(Paths.CollectionsPathSegment); - if (resourceType == ResourceType.StoredProcedure) - segments.Add(Paths.StoredProceduresPathSegment); - else if (resourceType == ResourceType.UserDefinedFunction) - segments.Add(Paths.UserDefinedFunctionsPathSegment); - else if (resourceType == ResourceType.Trigger) - segments.Add(Paths.TriggersPathSegment); - else if (resourceType == ResourceType.Conflict) - segments.Add(Paths.ConflictsPathSegment); - else if (resourceType == ResourceType.Schema) - segments.Add(Paths.SchemasPathSegment); - else if (resourceType == ResourceType.Document || resourceType == ResourceType.Attachment) - { - segments.Add(Paths.DocumentsPathSegment); - if (resourceType == ResourceType.Attachment) - segments.Add(Paths.AttachmentsPathSegment); - } - else if (resourceType == ResourceType.PartitionKeyRange) - { - segments.Add(Paths.PartitionKeyRangesPathSegment); - } - else if(resourceType == ResourceType.PartitionedSystemDocument) - { - segments.Add(Paths.PartitionedSystemDocumentsPathSegment); - } - else if (resourceType == ResourceType.SystemDocument) - { - segments.Add(Paths.SystemDocumentsPathSegment); - } - } - else if (resourceType == ResourceType.PartitionKey) - { - segments.Add(Paths.CollectionsPathSegment); - segments.Add(Paths.OperationsPathSegment); - } - else if (resourceType != ResourceType.Database) - { - return null; - } - - return segments.ToArray(); - } - - - internal static bool ValidateResourceId(ResourceType resourceType, string resourceId) - { - if (resourceType == ResourceType.Conflict) - { - return PathsHelper.ValidateConflictId(resourceId); - } - else if (resourceType == ResourceType.Database) - { - return PathsHelper.ValidateDatabaseId(resourceId); - } - else if (resourceType == ResourceType.EncryptionScope) - { - return PathsHelper.ValidateEncryptionScopeId(resourceId); - } - else if (resourceType == ResourceType.Collection) - { - return PathsHelper.ValidateDocumentCollectionId(resourceId); - } - else if (resourceType == ResourceType.Document) - { - return PathsHelper.ValidateDocumentId(resourceId); - } - else if (resourceType == ResourceType.Permission) - { - return PathsHelper.ValidatePermissionId(resourceId); - } - else if (resourceType == ResourceType.StoredProcedure) - { - return PathsHelper.ValidateStoredProcedureId(resourceId); - } - else if (resourceType == ResourceType.Trigger) - { - return PathsHelper.ValidateTriggerId(resourceId); - } - else if (resourceType == ResourceType.UserDefinedFunction) - { - return PathsHelper.ValidateUserDefinedFunctionId(resourceId); - } - else if (resourceType == ResourceType.User) - { - return PathsHelper.ValidateUserId(resourceId); - } - else if (resourceType == ResourceType.ClientEncryptionKey) - { - return PathsHelper.ValidateClientEncryptionKeyId(resourceId); - } - else if (resourceType == ResourceType.UserDefinedType) - { - return PathsHelper.ValidateUserDefinedTypeId(resourceId); - } - else if (resourceType == ResourceType.Attachment) - { - return PathsHelper.ValidateAttachmentId(resourceId); - } - if (resourceType == ResourceType.Schema) - { - return PathsHelper.ValidateSchemaId(resourceId); - } - if (resourceType == ResourceType.Snapshot) - { - return PathsHelper.ValidateSnapshotId(resourceId); - } - if (resourceType == ResourceType.RoleDefinition) - { - return PathsHelper.ValidateRoleDefinitionId(resourceId); - } - if (resourceType == ResourceType.RoleAssignment) - { - return PathsHelper.ValidateRoleAssignmentId(resourceId); - } - if (resourceType == ResourceType.SystemDocument) - { - return PathsHelper.ValidateSystemDocumentId(resourceId); - } - if (resourceType == ResourceType.PartitionedSystemDocument) - { - return PathsHelper.ValidatePartitionedSystemDocumentId(resourceId); - } - if (resourceType == ResourceType.InteropUser) - { - return PathsHelper.ValidateInteropUserId(resourceId); - } - if (resourceType == ResourceType.AuthPolicyElement) - { - return PathsHelper.ValidateAuthPolicyElementId(resourceId); - } - else - { - Debug.Assert(false, - string.Format(CultureInfo.InvariantCulture, "ValidateResourceId not implemented for Type {0} in ResourceRequestHandler", resourceType.ToString())); - - return false; - } - } - - internal static bool ValidateDatabaseId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Database > 0; - } - - internal static bool ValidateEncryptionScopeId(string resourceIdString) - { - ResourceId resourceId; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.EncryptionScope > 0; - } - - internal static bool ValidateDocumentCollectionId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.DocumentCollection > 0; - } - - internal static bool ValidateDocumentId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Document > 0; - } - - internal static bool ValidateConflictId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Conflict > 0; - } - - internal static bool ValidateAttachmentId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Attachment > 0; - } - - internal static bool ValidatePermissionId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Permission > 0; - } - - internal static bool ValidateStoredProcedureId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.StoredProcedure > 0; - } - - internal static bool ValidateTriggerId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Trigger > 0; - } - - internal static bool ValidateUserDefinedFunctionId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.UserDefinedFunction > 0; - } - - internal static bool ValidateUserId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.User > 0; - } - - internal static bool ValidateClientEncryptionKeyId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.ClientEncryptionKey > 0; - } - - internal static bool ValidateUserDefinedTypeId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.UserDefinedType > 0; - } - - internal static bool ValidateSchemaId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Schema > 0; - } - - internal static bool ValidateSnapshotId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Snapshot > 0; - } - - internal static bool ValidateRoleAssignmentId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.RoleAssignment > 0; - } - - internal static bool ValidateRoleDefinitionId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.RoleDefinition > 0; - } - - internal static bool ValidateAuthPolicyElementId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.AuthPolicyElement > 0; - } - - internal static bool ValidateSystemDocumentId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.SystemDocument > 0; - } - - internal static bool ValidatePartitionedSystemDocumentId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.PartitionedSystemDocument > 0; - } - - internal static bool ValidateInteropUserId(string resourceIdString) - { - ResourceId resourceId = null; - return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.InteropUser > 0; - } - - internal static bool IsPublicResource(Type resourceType) - { - if (resourceType == typeof(Database) || - resourceType == typeof(ClientEncryptionKey) || - resourceType == typeof(DocumentCollection) || - resourceType == typeof(StoredProcedure) || - resourceType == typeof(UserDefinedFunction) || - resourceType == typeof(Trigger) || - resourceType == typeof(Conflict) || - typeof(Attachment).IsAssignableFrom(resourceType) || - resourceType == typeof(User) || - typeof(Permission).IsAssignableFrom(resourceType) || - typeof(Document).IsAssignableFrom(resourceType) || - resourceType == typeof(Offer) || - resourceType == typeof(Schema) || - resourceType == typeof(Snapshot)) - { - return true; - } - else - { - return false; - } - } - - - internal static void ParseCollectionSelfLink(string collectionSelfLink, out string databaseId, out string collectionId) - { - string[] segments = collectionSelfLink.Split(RuntimeConstants.Separators.Url, StringSplitOptions.RemoveEmptyEntries); - - if (segments.Length != 4 - || !string.Equals(segments[0], Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) - || !string.Equals(segments[2], Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase)) - { - throw new ArgumentException(RMResources.BadUrl, nameof(collectionSelfLink)); - } - - databaseId = segments[1]; - collectionId = segments[3]; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + + internal static class PathsHelper + { + private const char ForwardSlash = '/'; + + private static readonly StringSegment[] EmptyArray = new StringSegment[0]; + + private static readonly char[] PathSeparatorArray = new char[1] { PathsHelper.ForwardSlash }; + + /// + /// The output resourceId can be + /// a: (Rid based) DgJ5AJeIfQABAAAAAAAAAPy3CWY= + /// b: (name based) dbs/dbName/colls/collectionName/docs/documentName/attachments/attachmentName", + /// For name based, it always trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded + /// + /// + /// + /// like dbs, colls + /// + /// + /// + /// + public static bool TryParsePathSegments( + string resourceUrl, + out bool isFeed, + out string resourcePath, + out string resourceIdOrFullName, + out bool isNameBased, + string clientVersion = "") + { + string databaseName = string.Empty; + string collectionName = string.Empty; + + resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); + + if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.Contains(Paths.OperationsPathSegment) && + (resourceUrl.Contains(Paths.PartitionKeyDeletePathSegment) || resourceUrl.Contains(Paths.CollectionTruncatePathsegment))) + { + isFeed = false; + string resourceName = PathsHelper.GetCollectionPath(resourceUrl); + + if(resourceName == null || resourceName.Length < 1) + { + resourcePath = string.Empty; + resourceIdOrFullName = string.Empty; + isNameBased = false; + return false; + } + + resourceIdOrFullName = resourceName[0] == '/' ? resourceName.Substring(1) : resourceName; //ResourceName is expected in the format "dbs/dbname/colls/collname" + resourcePath = Paths.CollectionsPathSegment; + isNameBased = true; + return true; + } + + if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.Contains(Paths.OperationsPathSegment) && + (resourceUrl.Contains(Paths.MetadataCheckAccessPathSegment))) + { + // For metadata check access the, the resource path is always root. + isFeed = false; + resourceIdOrFullName = string.Empty; + resourcePath = Paths.Root; + isNameBased = true; + return true; + } + + return PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionNames(resourceUrl, out isFeed, out resourcePath, out resourceIdOrFullName, out isNameBased, out databaseName, out collectionName, clientVersion, false); + } + + public static bool TryParsePathSegmentsWithDatabaseAndCollectionNames( + string resourceUrl, + out bool isFeed, + out string resourcePath, + out string resourceIdOrFullName, + out bool isNameBased, + out string databaseName, + out string collectionName, + string clientVersion = "", + bool parseDatabaseAndCollectionNames = false) + { + return PathsHelper.TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( + resourceUrl, + out isFeed, + out resourcePath, + out resourceIdOrFullName, + out isNameBased, + out databaseName, + out collectionName, + out _, + clientVersion, + parseDatabaseAndCollectionNames); + } + + /// + /// The output resourceId can be + /// a: (Rid based) DgJ5AJeIfQABAAAAAAAAAPy3CWY= + /// b: (name based) dbs/dbName/colls/collectionName/docs/documentName/attachments/attachmentName", + /// For name based, it always trimmed, RemoveTrailingSlashes, RemoveLeadingSlashes, urldecoded + /// + /// + /// + /// like dbs, colls + /// + /// + /// + /// + /// + /// + /// + /// + public static bool TryParsePathSegmentsWithDatabaseAndCollectionAndDocumentNames( + string resourceUrl, + out bool isFeed, + out string resourcePath, + out string resourceIdOrFullName, + out bool isNameBased, + out string databaseName, + out string collectionName, + out string documentName, + string clientVersion = "", + bool parseDatabaseAndCollectionNames = false) + { + resourcePath = string.Empty; + resourceIdOrFullName = string.Empty; + isFeed = false; + isNameBased = false; + databaseName = string.Empty; + collectionName = string.Empty; + documentName = string.Empty; + + if (string.IsNullOrEmpty(resourceUrl)) + { + return false; + } + + resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); + + string[] segments = resourceUrl.Split(PathsHelper.PathSeparatorArray, StringSplitOptions.RemoveEmptyEntries); + + if (segments == null || segments.Length < 1) + { + return false; + } + + int uriSegmentsCount = segments.Length; + StringSegment segmentOne = new StringSegment(segments[uriSegmentsCount - 1]).Trim(PathsHelper.PathSeparatorArray); + StringSegment segmentTwo = new StringSegment(string.Empty); + if (uriSegmentsCount >= 2) + { + segmentTwo = new StringSegment(segments[uriSegmentsCount - 2]).Trim(PathsHelper.PathSeparatorArray); + } + + // handle control operations + if (PathsHelper.IsRootOperation(segmentTwo, segmentOne) + || PathsHelper.IsTopLevelOperationOperation(segmentTwo, segmentOne)) + { + isFeed = false; + resourceIdOrFullName = string.Empty; + resourcePath = Paths.Root; + + return true; + } + + // handle name based operation + if (uriSegmentsCount >= 2) + { + if (segments[segments.Length - 1].Equals(Paths.RetriableWriteCachedResponsePathSegment, StringComparison.OrdinalIgnoreCase)) + { + isNameBased = true; + isFeed = false; + resourcePath = segments[segments.Length - 1]; + StringSegment trimmedSegment = resourceUrl; + resourceIdOrFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(trimmedSegment)).GetString()); + PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out _); + + return true; + } + + // parse the databaseId or snapshotId as RID. If failed, it is name based routing + // mediaId is special, we will treat it always as RID based. + ResourceId rid; + string firstSegment = segments[0]; + if (firstSegment.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsDatabaseId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.EncryptionScopesPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsEncryptionScopeId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.SnapshotsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsSnapshotId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.RoleDefinitionsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsRoleDefinitionId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.RoleAssignmentsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsRoleAssignmentId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsInteropUserId) + { + isNameBased = true; + } + } + else if (firstSegment.Equals(Paths.AuthPolicyElementsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + if (!ResourceId.TryParse(segments[1], out rid) || !rid.IsAuthPolicyElementId) + { + isNameBased = true; + } + } + + if (isNameBased) + { + return TryParseNameSegments(resourceUrl, segments, out isFeed, out resourcePath, out resourceIdOrFullName, out databaseName, out collectionName, out documentName, parseDatabaseAndCollectionNames); + } + } + + // Feed paths have odd number of segments + if ((uriSegmentsCount % 2 != 0) && PathsHelper.IsResourceType(segmentOne)) + { + isFeed = true; + resourcePath = segmentOne.GetString(); + + // The URL for dbs may contain the management endpoint as the segmentTwo which should not be used as resourceId + if (!segmentOne.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) + { + resourceIdOrFullName = segmentTwo.GetString(); + } + } + else if (PathsHelper.IsResourceType(segmentTwo)) + { + isFeed = false; + resourcePath = segmentTwo.GetString(); + resourceIdOrFullName = segmentOne.GetString(); + + // Media ID is not supposed to be used for any ID verification. However, if the old client makes a call for media ID + // we still need to support it. + // For new clients, parse to return the attachment id. For old clients do not modify. + if (!string.IsNullOrEmpty(clientVersion) && + resourcePath.Equals(Paths.MediaPathSegment, StringComparison.OrdinalIgnoreCase)) + { + string attachmentId = null; + byte storeIndex = 0; + if (!MediaIdHelper.TryParseMediaId(resourceIdOrFullName, out attachmentId, out storeIndex)) + { + return false; + } + + resourceIdOrFullName = attachmentId; + } + } + else + { + return false; + } + + return true; + } + + public static void ParseDatabaseNameAndCollectionNameFromUrlSegments( + string[] segments, + out string databaseName, + out string collectionName) + { + PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments( + segments, + out databaseName, + out collectionName, + out _); + } + + public static void ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments( + string[] segments, + out string databaseName, + out string collectionName, + out string documentName) + { + databaseName = string.Empty; + collectionName = string.Empty; + documentName = string.Empty; + + if (segments == null || segments.Length < 2) + { + return; + } + + if (string.Equals(segments[0], Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) + { + databaseName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[1]))).GetString()); + if (segments.Length >= 4 && string.Equals(segments[2], Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + collectionName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[3]))).GetString()); + } + + if (segments.Length >= 6 && string.Equals(segments[4], Paths.DocumentsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + documentName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(segments[5]))).GetString()); + } + } + } + + /// + /// Try to parse resource URL for non root operation. + /// Valid URL example is + /// /dbs/d557cdb4-21ac-46c9-ab17-33285c2ab040/colls/ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0/operations/partitionkeydelete + /// and RID based + /// /dbs/1fIrAA==/colls/1fIrANmsTf4=/operations/partitionkeydelete + /// + /// Resource URL. + /// Indicates resource path. For collection level it will be . + /// Resource name or resourceId. Always trimmed. + /// Database name extracted from the URL. + /// Collection name extracted from the URL. + /// Resource type mapped for the operation. + /// Operation type mapped for the operation. + /// + public static bool TryParsePathSegmentsWithDatabaseAndCollectionAndOperationNames( + string resourceUrl, + out string resourcePath, + out string resourceIdOrFullName, + out bool isNameBased, + out string databaseName, + out string collectionName, + out ResourceType resourceType, + out OperationType operationType) + { + resourcePath = string.Empty; + resourceIdOrFullName = string.Empty; + isNameBased = false; + databaseName = string.Empty; + collectionName = string.Empty; + resourceType = ResourceType.Unknown; + operationType = OperationType.Invalid; + + if (string.IsNullOrEmpty(resourceUrl)) + { + return false; + } + + resourceUrl = PathsHelper.RemoveAccountsSegment(resourceUrl); + + string[] segments = resourceUrl.Split(PathsHelper.PathSeparatorArray, StringSplitOptions.RemoveEmptyEntries); + + if (segments == null || segments.Length != 6) + { + return false; + } + + if (!segments[0].Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) + || !segments[2].Equals(Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase) + || !segments[4].Equals(Paths.OperationsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + switch (segments[5]) + { + case Paths.PartitionKeyDeletePathSegment: + { + resourceType = ResourceType.PartitionKey; + operationType = OperationType.Delete; + break; + } + + case Paths.CollectionTruncatePathsegment: + { + resourceType = ResourceType.Collection; + operationType = OperationType.CollectionTruncate; + break; + } + + default: + { + // Unknown operation. + return false; + } + } + + resourcePath = Paths.CollectionsPathSegment; + databaseName = Uri.UnescapeDataString(segments[1]); + collectionName = Uri.UnescapeDataString(segments[3]); + + if (!ResourceId.TryParse(segments[3], out ResourceId id) || !id.IsDocumentCollectionId) + { + // Resource name includes database and collection resource ids. For example dbs/d557cdb4-21ac-46c9-ab17-33285c2ab040/colls/ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0. + // Concatenation of the segments is done to support repeating slashes on the URL like dbs//d557cdb4-21ac-46c9-ab17-33285c2ab040//colls//ce6ca6b0-c0b0-4f6c-90ce-8eef6d9524e0. + resourceIdOrFullName = $"{segments[0]}{PathsHelper.ForwardSlash}{segments[1]}{PathsHelper.ForwardSlash}{segments[2]}{PathsHelper.ForwardSlash}{segments[3]}"; + isNameBased = true; + } + else + { + resourceIdOrFullName = segments[3]; + } + + return true; + } + + private static bool TryParseNameSegments( + string resourceUrl, + string[] segments, + out bool isFeed, + out string resourcePath, + out string resourceFullName, + out string databaseName, + out string collectionName, + out string documentName, + bool parseDatabaseAndCollectionNames) + { + isFeed = false; + resourcePath = string.Empty; + resourceFullName = string.Empty; + databaseName = string.Empty; + collectionName = string.Empty; + documentName = string.Empty; + + if (segments == null || segments.Length < 1) + { + return false; + } + + if (segments.Length % 2 == 0) + { + // even number, assume it is individual resource. + if (PathsHelper.IsResourceType(segments[segments.Length - 2])) + { + resourcePath = segments[segments.Length - 2]; + resourceFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(new StringSegment(resourceUrl))).GetString()); + if (parseDatabaseAndCollectionNames) + { + PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out documentName); + } + + return true; + } + } + else + { + // odd number, assume it is feed request + if (PathsHelper.IsResourceType(segments[segments.Length - 1])) + { + isFeed = true; + resourcePath = segments[segments.Length - 1]; + // remove the trailing resource type + StringSegment trimmedSegment = resourceUrl; + trimmedSegment = trimmedSegment.Substring(0, UrlUtility.RemoveTrailingSlashes(trimmedSegment).LastIndexOf(Paths.Root[0])); + resourceFullName = Uri.UnescapeDataString(UrlUtility.RemoveTrailingSlashes(UrlUtility.RemoveLeadingSlashes(trimmedSegment)).GetString()); + if (parseDatabaseAndCollectionNames) + { + // feed requests would not point to a document so ignore document Name. + PathsHelper.ParseDatabaseNameAndCollectionAndDocumentNameFromUrlSegments(segments, out databaseName, out collectionName, out _); + } + + return true; + } + } + + return false; + } + + public static ResourceType GetResourcePathSegment(string resourcePathSegment) + { + if (string.IsNullOrEmpty(resourcePathSegment)) + { + string message = string.Format(CultureInfo.CurrentUICulture, RMResources.StringArgumentNullOrEmpty, "resourcePathSegment"); + Debug.Assert(false, message); + throw new BadRequestException(message); + } + + switch (resourcePathSegment.ToLowerInvariant()) + { + case Paths.AttachmentsPathSegment: + return ResourceType.Attachment; + + case Paths.CollectionsPathSegment: + return ResourceType.Collection; + + case Paths.DatabasesPathSegment: + return ResourceType.Database; + + case Paths.EncryptionScopesPathSegment: + return ResourceType.EncryptionScope; + + case Paths.PermissionsPathSegment: + return ResourceType.Permission; + + case Paths.UsersPathSegment: + return ResourceType.User; + + case Paths.ClientEncryptionKeysPathSegment: + return ResourceType.ClientEncryptionKey; + + case Paths.UserDefinedTypesPathSegment: + return ResourceType.UserDefinedType; + + case Paths.DocumentsPathSegment: + return ResourceType.Document; + + case Paths.StoredProceduresPathSegment: + return ResourceType.StoredProcedure; + + case Paths.UserDefinedFunctionsPathSegment: + return ResourceType.UserDefinedFunction; + + case Paths.TriggersPathSegment: + return ResourceType.Trigger; + + case Paths.ConflictsPathSegment: + return ResourceType.Conflict; + + case Paths.OffersPathSegment: + return ResourceType.Offer; + + case Paths.SchemasPathSegment: + return ResourceType.Schema; + + case Paths.PartitionKeyRangesPathSegment: + return ResourceType.PartitionKeyRange; + + case Paths.MediaPathSegment: + return ResourceType.Media; + + case Paths.AddressPathSegment: + return ResourceType.Address; + + case Paths.SnapshotsPathSegment: + return ResourceType.Snapshot; + + case Paths.RoleDefinitionsPathSegment: + return ResourceType.RoleDefinition; + + case Paths.RoleAssignmentsPathSegment: + return ResourceType.RoleAssignment; + + case Paths.AuthPolicyElementsPathSegment: + return ResourceType.AuthPolicyElement; + + case Paths.SystemDocumentsPathSegment: + return ResourceType.SystemDocument; + + case Paths.PartitionedSystemDocumentsPathSegment: + return ResourceType.PartitionedSystemDocument; + + case Paths.InteropUsersPathSegment: + return ResourceType.InteropUser; + } + + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourcePathSegment); + Debug.Assert(false, errorMessage); + throw new BadRequestException(errorMessage); + } + + public static string GetResourcePath(ResourceType resourceType) + { + switch (resourceType) + { + case ResourceType.Database: + return Paths.DatabasesPathSegment; + + case ResourceType.EncryptionScope: + return Paths.EncryptionScopesPathSegment; + + case ResourceType.Collection: + case ResourceType.PartitionKey: + return Paths.CollectionsPathSegment; + + case ResourceType.Document: + return Paths.DocumentsPathSegment; + + case ResourceType.StoredProcedure: + return Paths.StoredProceduresPathSegment; + + case ResourceType.UserDefinedFunction: + return Paths.UserDefinedFunctionsPathSegment; + + case ResourceType.Trigger: + return Paths.TriggersPathSegment; + + case ResourceType.Conflict: + return Paths.ConflictsPathSegment; + + case ResourceType.Attachment: + return Paths.AttachmentsPathSegment; + + case ResourceType.User: + return Paths.UsersPathSegment; + + case ResourceType.ClientEncryptionKey: + return Paths.ClientEncryptionKeysPathSegment; + + case ResourceType.UserDefinedType: + return Paths.UserDefinedTypesPathSegment; + + case ResourceType.Permission: + return Paths.PermissionsPathSegment; + + case ResourceType.Offer: + return Paths.OffersPathSegment; + + case ResourceType.PartitionKeyRange: + return Paths.PartitionKeyRangesPathSegment; + + case ResourceType.Media: + return Paths.Medias_Root; + + case ResourceType.Schema: + return Paths.SchemasPathSegment; + + case ResourceType.Snapshot: + return Paths.SnapshotsPathSegment; + + case ResourceType.PartitionedSystemDocument: + return Paths.PartitionedSystemDocumentsPathSegment; + + case ResourceType.RoleDefinition: + return Paths.RoleDefinitionsPathSegment; + + case ResourceType.RoleAssignment: + return Paths.RoleAssignmentsPathSegment; + + case ResourceType.Transaction: + return Paths.TransactionsPathSegment; + + case ResourceType.SystemDocument: + return Paths.SystemDocumentsPathSegment; + + case ResourceType.InteropUser: + return Paths.InteropUsersPathSegment; + + case ResourceType.AuthPolicyElement: + return Paths.AuthPolicyElementsPathSegment; + + case ResourceType.RetriableWriteCachedResponse: + return Paths.RetriableWriteCachedResponsePathSegment; + +#if !COSMOSCLIENT + case ResourceType.MasterPartition: + case ResourceType.ServerPartition: + return Paths.PartitionsPathSegment; + + case ResourceType.StorageAuthToken: + return Paths.StorageAuthTokenPathSegment; + + case ResourceType.RidRange: + return Paths.RidRangePathSegment; + + case ResourceType.VectorClock: + return Paths.VectorClockPathSegment; + + case ResourceType.PartitionSetInformation: + case ResourceType.XPReplicatorAddress: + case ResourceType.Topology: + case ResourceType.Replica: + case ResourceType.ServiceFabricService: + case ResourceType.RestoreMetadata: + case ResourceType.Module: + case ResourceType.ModuleCommand: + case ResourceType.TransportControlCommand: +#endif + case ResourceType.DatabaseAccount: + case ResourceType.Address: + case ResourceType.Record: + case ResourceType.BatchApply: + case ResourceType.ControllerService: + return Paths.Root; + + default: + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); + Debug.Assert(false, errorMessage); + throw new BadRequestException(errorMessage); + } + } + + public static string GeneratePath(ResourceType resourceType, DocumentServiceRequest request, bool isFeed, bool notRequireValidation = false) + { + if (request.IsNameBased) + { + return PathsHelper.GeneratePathForNameBased(resourceType, request.ResourceAddress, isFeed, request.OperationType, notRequireValidation); + } + else + { + return PathsHelper.GeneratePath(resourceType, request.ResourceId, isFeed, request.OperationType); + } + } + + public static string GenerateUserDefinedTypePath(string databaseName, string typeName) + { + return Paths.DatabasesPathSegment + "/" + databaseName + "/" + Paths.UserDefinedTypesPathSegment + "/" + typeName; + } + + public static string GetCollectionPath(string resourceFullName) + { + if (resourceFullName != null) + { + int index = resourceFullName.Length > 0 && resourceFullName[0] == '/' ? resourceFullName.IndexOfNth('/', 5) : resourceFullName.IndexOfNth('/', 4); + if (index > 0) + return resourceFullName.Substring(0, index); + } + return resourceFullName; + } + + public static string GetDatabasePath(string resourceFullName) + { + if (resourceFullName != null) + { + int index = resourceFullName.Length > 0 && resourceFullName[0] == '/' ? resourceFullName.IndexOfNth('/', 3) : resourceFullName.IndexOfNth('/', 2); + if (index > 0) + return resourceFullName.Substring(0, index); + } + return resourceFullName; + } + + public static string GetParentByIndex(string resourceFullName, int segmentIndex) + { + int index = resourceFullName.IndexOfNth('/', segmentIndex); + if (index > 0) + return resourceFullName.Substring(0, index); + else + { + index = resourceFullName.IndexOfNth('/', segmentIndex - 1); + if (index > 0) + return resourceFullName; + else + return null; + } + } + + public static string GeneratePathForNameBased(Type resourceType, string resourceOwnerFullName, string resourceName) + { + if (resourceName == null) + return null; + + if (resourceType == typeof(Database)) + { + return Paths.DatabasesPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(Snapshot)) + { + return Paths.SnapshotsPathSegment + "/" + resourceName; + } + else if (resourceOwnerFullName == null) + { + return null; + } + else if (resourceType == typeof(DocumentCollection)) + { + return resourceOwnerFullName + "/" + Paths.CollectionsPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(ClientEncryptionKey)) + { + return resourceOwnerFullName + "/" + Paths.ClientEncryptionKeysPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(StoredProcedure)) + { + return resourceOwnerFullName + "/" + Paths.StoredProceduresPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(UserDefinedFunction)) + { + return resourceOwnerFullName + "/" + Paths.UserDefinedFunctionsPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(Trigger)) + { + return resourceOwnerFullName + "/" + Paths.TriggersPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(Conflict)) + { + return resourceOwnerFullName + "/" + Paths.ConflictsPathSegment + "/" + resourceName; + } + else if (typeof(Attachment).IsAssignableFrom(resourceType)) + { + return resourceOwnerFullName + "/" + Paths.AttachmentsPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(User)) + { + return resourceOwnerFullName + "/" + Paths.UsersPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(UserDefinedType)) + { + return resourceOwnerFullName + "/" + Paths.UserDefinedTypesPathSegment + "/" + resourceName; + } + else if (typeof(Permission).IsAssignableFrom(resourceType)) + { + return resourceOwnerFullName + "/" + Paths.PermissionsPathSegment + "/" + resourceName; + } + else if (typeof(Document).IsAssignableFrom(resourceType)) + { + return resourceOwnerFullName + "/" + Paths.DocumentsPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(Offer)) + { + return Paths.OffersPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(Schema)) + { + return resourceOwnerFullName + "/" + Paths.SchemasPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(SystemDocument)) + { + return resourceOwnerFullName + "/" + Paths.SystemDocumentsPathSegment + "/" + resourceName; + } + else if (resourceType == typeof(PartitionedSystemDocument)) + { + return resourceOwnerFullName + "/" + Paths.PartitionedSystemDocumentsPathSegment + "/" + resourceName; + } + else if (typeof(Resource).IsAssignableFrom(resourceType)) + { + // just generic Resource type. + return null; + } + + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); + Debug.Assert(false, errorMessage); + throw new BadRequestException(errorMessage); + } + + public static string GeneratePathForNamedBasedInternalResources(ResourceType resourceType, string resourceName) + { + if (resourceName == null) + return null; + + return resourceType switch + { + ResourceType.RoleAssignment => Paths.RoleAssignmentsPathSegment + "/" + resourceName, + ResourceType.RoleDefinition => Paths.RoleDefinitionsPathSegment + "/" + resourceName, + ResourceType.InteropUser => Paths.InteropUsersPathSegment + "/" + resourceName, + ResourceType.AuthPolicyElement => Paths.AuthPolicyElementsPathSegment + "/" + resourceName, + ResourceType.EncryptionScope => Paths.EncryptionScopesPathSegment + "/" + resourceName, + _ => null + }; + } + + // for testing to set to verify server side validation + private static bool isClientSideValidationEnabled = true; + + internal static void SetClientSidevalidation(bool validation) + { + isClientSideValidationEnabled = validation; + } + + private static string GeneratePathForNameBased(ResourceType resourceType, string resourceFullName, bool isFeed, OperationType operationType, bool notRequireValidation = false) + { + if (isFeed && + string.IsNullOrEmpty(resourceFullName) && + resourceType != ResourceType.Database && + resourceType != ResourceType.EncryptionScope && + resourceType != ResourceType.Snapshot && + resourceType != ResourceType.RoleDefinition && + resourceType != ResourceType.RoleAssignment && + resourceType != ResourceType.InteropUser && + resourceType != ResourceType.AuthPolicyElement) + { + string errorMessage = string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType); + throw new BadRequestException(errorMessage); + } + + string resourcePath = null; + ResourceType resourceTypeToValidate; + // Validate resourceFullName comply with the intended resource type. + + if (resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete) + { + resourceTypeToValidate = resourceType; + resourceFullName = resourceFullName + "/" + Paths.OperationsPathSegment + "/" + Paths.PartitionKeyDeletePathSegment; + resourcePath = resourceFullName; + } + else if ((resourceType == ResourceType.Collection) && (operationType == OperationType.CollectionTruncate)) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.OperationsPathSegment + "/" + Paths.CollectionTruncatePathsegment; + } + else if (!isFeed) + { + resourceTypeToValidate = resourceType; + resourcePath = resourceFullName; + } + else if (resourceType == ResourceType.Database) + { + return Paths.DatabasesPathSegment; + } + else if (resourceType == ResourceType.EncryptionScope) + { + return Paths.EncryptionScopesPathSegment; + } + else if (resourceType == ResourceType.Collection) + { + resourceTypeToValidate = ResourceType.Database; + resourcePath = resourceFullName + "/" + Paths.CollectionsPathSegment; + } + else if (resourceType == ResourceType.ClientEncryptionKey) + { + resourceTypeToValidate = ResourceType.Database; + resourcePath = resourceFullName + "/" + Paths.ClientEncryptionKeysPathSegment; + } + else if (resourceType == ResourceType.StoredProcedure) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.StoredProceduresPathSegment; + } + else if (resourceType == ResourceType.UserDefinedFunction) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.UserDefinedFunctionsPathSegment; + } + else if (resourceType == ResourceType.Trigger) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.TriggersPathSegment; + } + else if (resourceType == ResourceType.Conflict) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.ConflictsPathSegment; + } + else if (resourceType == ResourceType.Attachment) + { + resourceTypeToValidate = ResourceType.Document; + resourcePath = resourceFullName + "/" + Paths.AttachmentsPathSegment; + } + else if (resourceType == ResourceType.User) + { + resourceTypeToValidate = ResourceType.Database; + resourcePath = resourceFullName + "/" + Paths.UsersPathSegment; + } + else if (resourceType == ResourceType.UserDefinedType) + { + resourceTypeToValidate = ResourceType.Database; + resourcePath = resourceFullName + "/" + Paths.UserDefinedTypesPathSegment; + } + else if (resourceType == ResourceType.Permission) + { + resourceTypeToValidate = ResourceType.User; + resourcePath = resourceFullName + "/" + Paths.PermissionsPathSegment; + } + else if (resourceType == ResourceType.Document) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.DocumentsPathSegment; + } + else if (resourceType == ResourceType.Offer) + { + return resourceFullName + "/" + Paths.OffersPathSegment; + } + else if (resourceType == ResourceType.PartitionKeyRange) + { + return resourceFullName + "/" + Paths.PartitionKeyRangesPathSegment; + } + else if (resourceType == ResourceType.Schema) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.SchemasPathSegment; + } + else if (resourceType == ResourceType.PartitionedSystemDocument) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.PartitionedSystemDocumentsPathSegment; + } + else if (resourceType == ResourceType.Snapshot) + { + return Paths.SnapshotsPathSegment; + } + else if (resourceType == ResourceType.RoleDefinition) + { + return Paths.RoleDefinitionsPathSegment; + } + else if (resourceType == ResourceType.RoleAssignment) + { + return Paths.RoleAssignmentsPathSegment; + } + else if (resourceType == ResourceType.SystemDocument) + { + resourceTypeToValidate = ResourceType.Collection; + resourcePath = resourceFullName + "/" + Paths.SystemDocumentsPathSegment; + } + else if (resourceType == ResourceType.InteropUser) + { + return Paths.InteropUsersPathSegment; + } + else if (resourceType == ResourceType.AuthPolicyElement) + { + return Paths.AuthPolicyElementsPathSegment; + } + else + { + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); + Debug.Assert(false, errorMessage); + throw new BadRequestException(errorMessage); + } + + if (!notRequireValidation && isClientSideValidationEnabled) + { + if (!ValidateResourceFullName(resourceTypeToValidate, resourceFullName)) + { + string errorMessage = string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType); + throw new BadRequestException(errorMessage); + } + } + return resourcePath; + } + + + public static string GeneratePath(ResourceType resourceType, string ownerOrResourceId, bool isFeed, OperationType operationType = default) + { + if (isFeed && string.IsNullOrEmpty(ownerOrResourceId) && + resourceType != ResourceType.Database && + resourceType != ResourceType.EncryptionScope && + resourceType != ResourceType.Offer && + resourceType != ResourceType.DatabaseAccount && + resourceType != ResourceType.Snapshot && + resourceType != ResourceType.RoleAssignment && + resourceType != ResourceType.RoleDefinition && + resourceType != ResourceType.InteropUser && + resourceType != ResourceType.AuthPolicyElement +#if !COSMOSCLIENT + && resourceType != ResourceType.MasterPartition && + resourceType != ResourceType.ServerPartition && + resourceType != ResourceType.Topology && + resourceType != ResourceType.RidRange && + resourceType != ResourceType.VectorClock && + resourceType != ResourceType.StorageAuthToken +#endif + ) + { + throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.UnexpectedResourceType, resourceType)); + } + + if (isFeed && resourceType == ResourceType.EncryptionScope) + { + return Paths.EncryptionScopesPathSegment; + } + else if (resourceType == ResourceType.EncryptionScope) + { + return Paths.EncryptionScopesPathSegment + "/" + ownerOrResourceId.ToString(); + } + + if (isFeed && resourceType == ResourceType.Database) + { + return Paths.DatabasesPathSegment; + } + else if (resourceType == ResourceType.Database) + { + return Paths.DatabasesPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Collection) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment; + } + else if (resourceType == ResourceType.Collection) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Offer) + { + return Paths.OffersPathSegment; + } + else if (resourceType == ResourceType.Offer) + { + return Paths.OffersPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if (isFeed && resourceType == ResourceType.StoredProcedure) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.StoredProceduresPathSegment; + } + else if (resourceType == ResourceType.StoredProcedure) + { + ResourceId storedProcedureId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + storedProcedureId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + storedProcedureId.DocumentCollectionId.ToString() + "/" + + Paths.StoredProceduresPathSegment + "/" + storedProcedureId.StoredProcedureId.ToString(); + } + else if (isFeed && resourceType == ResourceType.UserDefinedFunction) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.UserDefinedFunctionsPathSegment; + } + else if (resourceType == ResourceType.UserDefinedFunction) + { + ResourceId functionId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + functionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + functionId.DocumentCollectionId.ToString() + "/" + + Paths.UserDefinedFunctionsPathSegment + "/" + functionId.UserDefinedFunctionId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Trigger) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.TriggersPathSegment; + } + else if (resourceType == ResourceType.Trigger) + { + ResourceId triggerId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + triggerId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + triggerId.DocumentCollectionId.ToString() + "/" + + Paths.TriggersPathSegment + "/" + triggerId.TriggerId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Conflict) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.ConflictsPathSegment; + } + else if (resourceType == ResourceType.Conflict) + { + ResourceId conflictId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + conflictId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + conflictId.DocumentCollectionId.ToString() + "/" + + Paths.ConflictsPathSegment + "/" + conflictId.ConflictId.ToString(); + } + else if (isFeed && resourceType == ResourceType.PartitionKeyRange) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.PartitionKeyRangesPathSegment; + } + else if (resourceType == ResourceType.PartitionKeyRange) + { + ResourceId partitionKeyRangeId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + partitionKeyRangeId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + partitionKeyRangeId.DocumentCollectionId.ToString() + "/" + + Paths.PartitionKeyRangesPathSegment + "/" + partitionKeyRangeId.PartitionKeyRangeId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Attachment) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.DocumentsPathSegment + "/" + documentCollectionId.DocumentId.ToString() + "/" + + Paths.AttachmentsPathSegment; + } + else if (resourceType == ResourceType.Attachment) + { + ResourceId attachmentId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + attachmentId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + attachmentId.DocumentCollectionId.ToString() + "/" + + Paths.DocumentsPathSegment + "/" + attachmentId.DocumentId.ToString() + "/" + + Paths.AttachmentsPathSegment + "/" + attachmentId.AttachmentId.ToString(); + } + else if (isFeed && resourceType == ResourceType.User) + { + return + Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + + Paths.UsersPathSegment; + } + else if (resourceType == ResourceType.User) + { + ResourceId userId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + userId.DatabaseId.ToString() + "/" + + Paths.UsersPathSegment + "/" + userId.UserId.ToString(); + } + else if (isFeed && resourceType == ResourceType.ClientEncryptionKey) + { + return Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + + Paths.ClientEncryptionKeysPathSegment; + } + else if (resourceType == ResourceType.ClientEncryptionKey) + { + ResourceId clientEncryptionKeyId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + clientEncryptionKeyId.DatabaseId.ToString() + "/" + + Paths.ClientEncryptionKeysPathSegment + "/" + clientEncryptionKeyId.ClientEncryptionKeyId.ToString(); + } + else if (isFeed && resourceType == ResourceType.UserDefinedType) + { + return + Paths.DatabasesPathSegment + "/" + ownerOrResourceId + "/" + + Paths.UserDefinedTypesPathSegment; + } + else if (resourceType == ResourceType.UserDefinedType) + { + ResourceId userDefinedTypeId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + userDefinedTypeId.DatabaseId.ToString() + "/" + + Paths.UserDefinedTypesPathSegment + "/" + userDefinedTypeId.UserDefinedTypeId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Permission) + { + ResourceId userId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + userId.DatabaseId.ToString() + "/" + + Paths.UsersPathSegment + "/" + userId.UserId.ToString() + "/" + + Paths.PermissionsPathSegment; + } + else if (resourceType == ResourceType.Permission) + { + ResourceId permissionId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + permissionId.DatabaseId.ToString() + "/" + + Paths.UsersPathSegment + "/" + permissionId.UserId.ToString() + "/" + + Paths.PermissionsPathSegment + "/" + permissionId.PermissionId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Document) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.DocumentsPathSegment; + } + else if (resourceType == ResourceType.Document) + { + ResourceId documentId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + documentId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentId.DocumentCollectionId.ToString() + "/" + + Paths.DocumentsPathSegment + "/" + documentId.DocumentId.ToString(); + } + else if (isFeed && resourceType == ResourceType.Schema) + { + ResourceId schemaCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + schemaCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + schemaCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.SchemasPathSegment; + } + else if (resourceType == ResourceType.Schema) + { + ResourceId schemaId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + schemaId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + schemaId.DocumentCollectionId.ToString() + "/" + + Paths.SchemasPathSegment + "/" + schemaId.SchemaId.ToString(); + } + else if (isFeed && resourceType == ResourceType.DatabaseAccount) + { + return Paths.DatabaseAccountSegment; + } + else if (resourceType == ResourceType.DatabaseAccount && operationType == OperationType.MetadataCheckAccess) + { + return Paths.OperationsPathSegment + "/" + Paths.Operations_MetadataCheckAccess; + } + else if (resourceType == ResourceType.DatabaseAccount) + { + return Paths.DatabaseAccountSegment + "/" + ownerOrResourceId; + } + else if (isFeed && resourceType == ResourceType.Snapshot) + { + return Paths.SnapshotsPathSegment; + } + else if (resourceType == ResourceType.Snapshot) + { + return Paths.SnapshotsPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if(resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + Paths.OperationsPathSegment + "/" + Paths.PartitionKeyDeletePathSegment; + } + else if (isFeed && resourceType == ResourceType.RoleAssignment) + { + return Paths.RoleAssignmentsPathSegment; + } + else if (isFeed && resourceType == ResourceType.RoleDefinition) + { + return Paths.RoleDefinitionsPathSegment; + } + else if (isFeed && resourceType == ResourceType.AuthPolicyElement) + { + return Paths.AuthPolicyElementsPathSegment; + } + else if (resourceType == ResourceType.RoleAssignment) + { + return Paths.RoleAssignmentsPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if (resourceType == ResourceType.RoleDefinition) + { + return Paths.RoleDefinitionsPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if (resourceType == ResourceType.AuthPolicyElement) + { + return Paths.AuthPolicyElementsPathSegment + "/" + ownerOrResourceId.ToString(); + } + else if (isFeed && resourceType == ResourceType.SystemDocument) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.SystemDocumentsPathSegment; + } + else if (resourceType == ResourceType.SystemDocument) + { + ResourceId sysdocId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + sysdocId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + sysdocId.DocumentCollectionId.ToString() + "/" + + Paths.SystemDocumentsPathSegment + "/" + sysdocId.SystemDocumentId.ToString(); + } + else if (isFeed && resourceType == ResourceType.PartitionedSystemDocument) + { + ResourceId documentCollectionId = ResourceId.Parse(ownerOrResourceId); + + return + Paths.DatabasesPathSegment + "/" + documentCollectionId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + documentCollectionId.DocumentCollectionId.ToString() + "/" + + Paths.PartitionedSystemDocumentsPathSegment; + } + else if (resourceType == ResourceType.PartitionedSystemDocument) + { + ResourceId sysdocId = ResourceId.Parse(ownerOrResourceId); + + return Paths.DatabasesPathSegment + "/" + sysdocId.DatabaseId.ToString() + "/" + + Paths.CollectionsPathSegment + "/" + sysdocId.DocumentCollectionId.ToString() + "/" + + Paths.PartitionedSystemDocumentsPathSegment + "/" + sysdocId.PartitionedSystemDocumentId.ToString(); + } + else if (isFeed && resourceType == ResourceType.InteropUser) + { + return Paths.InteropUsersPathSegment; + } + else if (resourceType == ResourceType.InteropUser) + { + return Paths.InteropUsersPathSegment + "/" + ownerOrResourceId.ToString(); + } +#if !COSMOSCLIENT + else if (isFeed && resourceType == ResourceType.MasterPartition) + { + return Paths.PartitionsPathSegment; + } + else if (resourceType == ResourceType.MasterPartition) + { + return Paths.PartitionsPathSegment + "/" + ownerOrResourceId; + } + else if (isFeed && resourceType == ResourceType.ServerPartition) + { + return Paths.PartitionsPathSegment; + } + else if (resourceType == ResourceType.ServerPartition) + { + return Paths.PartitionsPathSegment + "/" + ownerOrResourceId; + } + else if (isFeed && resourceType == ResourceType.Topology) + { + return Paths.TopologyPathSegment; + } + else if (resourceType == ResourceType.Topology) + { + return Paths.TopologyPathSegment + "/" + ownerOrResourceId; + } + else if (resourceType == ResourceType.RidRange) + { + return Paths.RidRangePathSegment + "/" + ownerOrResourceId; + } + else if (resourceType == ResourceType.VectorClock) + { + return Paths.VectorClockPathSegment + "/" + ownerOrResourceId; + } + else if (isFeed && resourceType == ResourceType.StorageAuthToken) + { + return Paths.StorageAuthTokenPathSegment; + } + else if (resourceType == ResourceType.StorageAuthToken) + { + return Paths.StorageAuthTokenPathSegment + "/" + ownerOrResourceId; + } +#endif + + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.UnknownResourceType, resourceType.ToString()); + Debug.Assert(false, errorMessage); + throw new BadRequestException(errorMessage); + } + + public static string GenerateRootOperationPath(OperationType operationType) + { + switch (operationType) + { +#if !COSMOSCLIENT + case OperationType.Pause: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Pause; + case OperationType.Recycle: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Recycle; + case OperationType.Resume: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Resume; + case OperationType.Stop: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Stop; + case OperationType.Crash: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_Crash; + case OperationType.ForceConfigRefresh: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_ForceConfigRefresh; + case OperationType.ReportThroughputUtilization: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_ReportThroughputUtilization; + case OperationType.BatchReportThroughputUtilization: + return Paths.OperationsPathSegment + "/" + Paths.ReplicaOperations_BatchReportThroughputUtilization; + case OperationType.ControllerBatchGetOutput: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetOutput; + case OperationType.ControllerBatchReportCharges: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchReportCharges; + case OperationType.ControllerBatchAutoscaleRUsConsumption: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchAutoscaleRUsConsumption; + case OperationType.ControllerBatchGetAutoscaleAggregateOutput: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput; + case OperationType.GetConfiguration: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetConfiguration; + case OperationType.GetFederationConfigurations: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetFederationConfigurations; + case OperationType.GetDatabaseAccountConfigurations: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetDatabaseAccountConfigurations; + case OperationType.XPDatabaseAccountMetaData: + return Paths.OperationsPathSegment + "/" + Paths.Operations_XPDatabaseAccountMetaData; + case OperationType.GetGraphDatabaseAccountConfiguration: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetGraphDatabaseAccountConfiguration; + case OperationType.GetStorageServiceConfigurations: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageServiceConfigurations; + case OperationType.GetStorageAccountKey: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageAccountKey; + case OperationType.GetStorageAccountSas: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageAccountSas; + case OperationType.GetUnwrappedDek: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetUnwrappedDek; + case OperationType.GetDekProperties: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetDekProperties; + case OperationType.GetCustomerManagedKeyStatus: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetCustomerManagedKeyStatus; + case OperationType.ReadReplicaFromMasterPartition: + return Paths.OperationsPathSegment + "/" + Paths.Operations_ReadReplicaFromMasterPartition; + case OperationType.ReadReplicaFromServerPartition: + return Paths.OperationsPathSegment + "/" + Paths.Operations_ReadReplicaFromServerPartition; + case OperationType.MasterInitiatedProgressCoordination: + return Paths.OperationsPathSegment + "/" + Paths.Operations_MasterInitiatedProgressCoordination; + case OperationType.GetAadGroups: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetAadGroups; + case OperationType.MetadataCheckAccess: + return Paths.OperationsPathSegment + "/" + Paths.Operations_MetadataCheckAccess; +#endif + + default: + Debug.Assert(false, "Unsupported operation type for replica"); + throw new NotFoundException(); + } + } + + private static bool IsResourceType(in StringSegment resourcePathSegment) + { + if (resourcePathSegment.IsNullOrEmpty()) + { + return false; + } + + return resourcePathSegment.Equals(Paths.AttachmentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PermissionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.UsersPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.ClientEncryptionKeysPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.StorageAuthTokenPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.UserDefinedTypesPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.DocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.StoredProceduresPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.TriggersPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.UserDefinedFunctionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.ConflictsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.MediaPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.OffersPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PartitionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.DatabaseAccountSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.TopologyPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PartitionKeyRangesPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PartitionKeyRangePreSplitSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PartitionKeyRangePostSplitSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.SchemasPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.RidRangePathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.VectorClockPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.AddressPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.SnapshotsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.PartitionedSystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.RoleDefinitionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.RoleAssignmentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.TransactionsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.SystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.AuthPolicyElementsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.SystemDocumentsPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.EncryptionScopesPathSegment, StringComparison.OrdinalIgnoreCase) || + resourcePathSegment.Equals(Paths.RetriableWriteCachedResponsePathSegment, StringComparison.OrdinalIgnoreCase); + } + + private static bool IsRootOperation(in StringSegment operationSegment, in StringSegment operationTypeSegment) + { + if (operationSegment.IsNullOrEmpty()) + { + return false; + } + + if (operationTypeSegment.IsNullOrEmpty()) + { + return false; + } + + if (operationSegment.Compare(Paths.OperationsPathSegment, StringComparison.OrdinalIgnoreCase) != 0) + { + return false; + } + + return operationTypeSegment.Equals(Paths.ReplicaOperations_Pause, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_Resume, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_Stop, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_Recycle, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_Crash, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_ReportThroughputUtilization, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ReplicaOperations_BatchReportThroughputUtilization, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetOutput, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchReportCharges, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchAutoscaleRUsConsumption, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetFederationConfigurations, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetStorageServiceConfigurations, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetConfiguration, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetStorageAccountKey, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetStorageAccountSas, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetDatabaseAccountConfigurations, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_XPDatabaseAccountMetaData, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetUnwrappedDek, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetDekProperties, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetCustomerManagedKeyStatus, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromMasterPartition, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromServerPartition, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_MasterInitiatedProgressCoordination, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetAadGroups, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_MetadataCheckAccess, StringComparison.OrdinalIgnoreCase); + } + + private static bool IsTopLevelOperationOperation(in StringSegment replicaSegment, in StringSegment addressSegment) + { + if (replicaSegment.IsNullOrEmpty() && // replica part should be empty + (addressSegment.Compare(Paths.XPReplicatorAddressPathSegment, StringComparison.OrdinalIgnoreCase) == 0 || + addressSegment.Compare(Paths.ComputeGatewayChargePathSegment, StringComparison.OrdinalIgnoreCase) == 0 || + addressSegment.Compare(Paths.ServiceReservationPathSegment, StringComparison.OrdinalIgnoreCase) == 0)) + { + return true; + } + + return false; + } + + public static string RemoveAccountsSegment(string resourceUrl) + { + if (!string.IsNullOrEmpty(resourceUrl) && resourceUrl.StartsWith("/accounts/", StringComparison.OrdinalIgnoreCase)) + { + int index = resourceUrl.IndexOfNth('/', 3); + resourceUrl = resourceUrl.Substring(index, resourceUrl.Length - index); + } + + return resourceUrl; + } + + internal static bool IsNameBased(string resourceIdOrFullName) + { + // quick way to tell whether it is resourceId nor not, non conclusively. + if (!string.IsNullOrEmpty(resourceIdOrFullName) && + ((resourceIdOrFullName.Length > 4 && resourceIdOrFullName[3] == '/') || + (resourceIdOrFullName.StartsWith(Paths.InteropUsersPathSegment, StringComparison.OrdinalIgnoreCase)))) + { + return true; + } + return false; + } + + internal static int IndexOfNth(this string str, char value, int n) + { + if (string.IsNullOrEmpty(str) || n <= 0 || n > str.Length) + { + return -1; + } + + int remaining = n; + for (int i = 0; i < str.Length; i++) + { + if (str[i] == value) + { + if (--remaining == 0) + { + return i; + } + } + } + + return -1; + } + + internal static bool ValidateResourceFullName(ResourceType resourceType, string resourceFullName) + { + string[] segments = resourceFullName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + + string[] resourcePathArray = GetResourcePathArray(resourceType); + + if (resourcePathArray == null) + return false; + + if (segments.Length != resourcePathArray.Length * 2) + return false; + + for (int i = 0; i < resourcePathArray.Length; i++) + { + if (string.Compare(resourcePathArray[i], segments[2 * i], StringComparison.Ordinal) != 0) + { + return false; + } + } + return true; + } + + internal static string[] GetResourcePathArray(ResourceType resourceType) + { + List segments = new List(); + + if (resourceType == ResourceType.Snapshot) + { + segments.Add(Paths.SnapshotsPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.EncryptionScope) + { + segments.Add(Paths.EncryptionScopesPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.RoleDefinition) + { + segments.Add(Paths.RoleDefinitionsPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.RoleAssignment) + { + segments.Add(Paths.RoleAssignmentsPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.AuthPolicyElement) + { + segments.Add(Paths.AuthPolicyElementsPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.Offer) + { + segments.Add(Paths.OffersPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.Address) + { + segments.Add(Paths.AddressPathSegment); + return segments.ToArray(); + } + + if (resourceType == ResourceType.InteropUser) + { + segments.Add(Paths.InteropUsersPathSegment); + return segments.ToArray(); + } + + segments.Add(Paths.DatabasesPathSegment); + + if (resourceType == ResourceType.Permission || + resourceType == ResourceType.User) + { + segments.Add(Paths.UsersPathSegment); + if (resourceType == ResourceType.Permission) + segments.Add(Paths.PermissionsPathSegment); + } + else if (resourceType == ResourceType.UserDefinedType) + { + segments.Add(Paths.UserDefinedTypesPathSegment); + } + else if (resourceType == ResourceType.ClientEncryptionKey) + { + segments.Add(Paths.ClientEncryptionKeysPathSegment); + } + else if ( + resourceType == ResourceType.Collection || + resourceType == ResourceType.StoredProcedure || + resourceType == ResourceType.UserDefinedFunction || + resourceType == ResourceType.Trigger || + resourceType == ResourceType.Conflict || + resourceType == ResourceType.Attachment || + resourceType == ResourceType.Document || + resourceType == ResourceType.PartitionKeyRange || + resourceType == ResourceType.Schema || + resourceType == ResourceType.PartitionedSystemDocument || + resourceType == ResourceType.SystemDocument) + { + segments.Add(Paths.CollectionsPathSegment); + if (resourceType == ResourceType.StoredProcedure) + segments.Add(Paths.StoredProceduresPathSegment); + else if (resourceType == ResourceType.UserDefinedFunction) + segments.Add(Paths.UserDefinedFunctionsPathSegment); + else if (resourceType == ResourceType.Trigger) + segments.Add(Paths.TriggersPathSegment); + else if (resourceType == ResourceType.Conflict) + segments.Add(Paths.ConflictsPathSegment); + else if (resourceType == ResourceType.Schema) + segments.Add(Paths.SchemasPathSegment); + else if (resourceType == ResourceType.Document || resourceType == ResourceType.Attachment) + { + segments.Add(Paths.DocumentsPathSegment); + if (resourceType == ResourceType.Attachment) + segments.Add(Paths.AttachmentsPathSegment); + } + else if (resourceType == ResourceType.PartitionKeyRange) + { + segments.Add(Paths.PartitionKeyRangesPathSegment); + } + else if(resourceType == ResourceType.PartitionedSystemDocument) + { + segments.Add(Paths.PartitionedSystemDocumentsPathSegment); + } + else if (resourceType == ResourceType.SystemDocument) + { + segments.Add(Paths.SystemDocumentsPathSegment); + } + } + else if (resourceType == ResourceType.PartitionKey) + { + segments.Add(Paths.CollectionsPathSegment); + segments.Add(Paths.OperationsPathSegment); + } + else if (resourceType != ResourceType.Database) + { + return null; + } + + return segments.ToArray(); + } + + + internal static bool ValidateResourceId(ResourceType resourceType, string resourceId) + { + if (resourceType == ResourceType.Conflict) + { + return PathsHelper.ValidateConflictId(resourceId); + } + else if (resourceType == ResourceType.Database) + { + return PathsHelper.ValidateDatabaseId(resourceId); + } + else if (resourceType == ResourceType.EncryptionScope) + { + return PathsHelper.ValidateEncryptionScopeId(resourceId); + } + else if (resourceType == ResourceType.Collection) + { + return PathsHelper.ValidateDocumentCollectionId(resourceId); + } + else if (resourceType == ResourceType.Document) + { + return PathsHelper.ValidateDocumentId(resourceId); + } + else if (resourceType == ResourceType.Permission) + { + return PathsHelper.ValidatePermissionId(resourceId); + } + else if (resourceType == ResourceType.StoredProcedure) + { + return PathsHelper.ValidateStoredProcedureId(resourceId); + } + else if (resourceType == ResourceType.Trigger) + { + return PathsHelper.ValidateTriggerId(resourceId); + } + else if (resourceType == ResourceType.UserDefinedFunction) + { + return PathsHelper.ValidateUserDefinedFunctionId(resourceId); + } + else if (resourceType == ResourceType.User) + { + return PathsHelper.ValidateUserId(resourceId); + } + else if (resourceType == ResourceType.ClientEncryptionKey) + { + return PathsHelper.ValidateClientEncryptionKeyId(resourceId); + } + else if (resourceType == ResourceType.UserDefinedType) + { + return PathsHelper.ValidateUserDefinedTypeId(resourceId); + } + else if (resourceType == ResourceType.Attachment) + { + return PathsHelper.ValidateAttachmentId(resourceId); + } + if (resourceType == ResourceType.Schema) + { + return PathsHelper.ValidateSchemaId(resourceId); + } + if (resourceType == ResourceType.Snapshot) + { + return PathsHelper.ValidateSnapshotId(resourceId); + } + if (resourceType == ResourceType.RoleDefinition) + { + return PathsHelper.ValidateRoleDefinitionId(resourceId); + } + if (resourceType == ResourceType.RoleAssignment) + { + return PathsHelper.ValidateRoleAssignmentId(resourceId); + } + if (resourceType == ResourceType.SystemDocument) + { + return PathsHelper.ValidateSystemDocumentId(resourceId); + } + if (resourceType == ResourceType.PartitionedSystemDocument) + { + return PathsHelper.ValidatePartitionedSystemDocumentId(resourceId); + } + if (resourceType == ResourceType.InteropUser) + { + return PathsHelper.ValidateInteropUserId(resourceId); + } + if (resourceType == ResourceType.AuthPolicyElement) + { + return PathsHelper.ValidateAuthPolicyElementId(resourceId); + } + else + { + Debug.Assert(false, + string.Format(CultureInfo.InvariantCulture, "ValidateResourceId not implemented for Type {0} in ResourceRequestHandler", resourceType.ToString())); + + return false; + } + } + + internal static bool ValidateDatabaseId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Database > 0; + } + + internal static bool ValidateEncryptionScopeId(string resourceIdString) + { + ResourceId resourceId; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.EncryptionScope > 0; + } + + internal static bool ValidateDocumentCollectionId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.DocumentCollection > 0; + } + + internal static bool ValidateDocumentId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Document > 0; + } + + internal static bool ValidateConflictId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Conflict > 0; + } + + internal static bool ValidateAttachmentId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Attachment > 0; + } + + internal static bool ValidatePermissionId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Permission > 0; + } + + internal static bool ValidateStoredProcedureId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.StoredProcedure > 0; + } + + internal static bool ValidateTriggerId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Trigger > 0; + } + + internal static bool ValidateUserDefinedFunctionId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.UserDefinedFunction > 0; + } + + internal static bool ValidateUserId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.User > 0; + } + + internal static bool ValidateClientEncryptionKeyId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.ClientEncryptionKey > 0; + } + + internal static bool ValidateUserDefinedTypeId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.UserDefinedType > 0; + } + + internal static bool ValidateSchemaId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Schema > 0; + } + + internal static bool ValidateSnapshotId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.Snapshot > 0; + } + + internal static bool ValidateRoleAssignmentId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.RoleAssignment > 0; + } + + internal static bool ValidateRoleDefinitionId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.RoleDefinition > 0; + } + + internal static bool ValidateAuthPolicyElementId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.AuthPolicyElement > 0; + } + + internal static bool ValidateSystemDocumentId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.SystemDocument > 0; + } + + internal static bool ValidatePartitionedSystemDocumentId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.PartitionedSystemDocument > 0; + } + + internal static bool ValidateInteropUserId(string resourceIdString) + { + ResourceId resourceId = null; + return ResourceId.TryParse(resourceIdString, out resourceId) && resourceId.InteropUser > 0; + } + + internal static bool IsPublicResource(Type resourceType) + { + if (resourceType == typeof(Database) || + resourceType == typeof(ClientEncryptionKey) || + resourceType == typeof(DocumentCollection) || + resourceType == typeof(StoredProcedure) || + resourceType == typeof(UserDefinedFunction) || + resourceType == typeof(Trigger) || + resourceType == typeof(Conflict) || + typeof(Attachment).IsAssignableFrom(resourceType) || + resourceType == typeof(User) || + typeof(Permission).IsAssignableFrom(resourceType) || + typeof(Document).IsAssignableFrom(resourceType) || + resourceType == typeof(Offer) || + resourceType == typeof(Schema) || + resourceType == typeof(Snapshot)) + { + return true; + } + else + { + return false; + } + } + + + internal static void ParseCollectionSelfLink(string collectionSelfLink, out string databaseId, out string collectionId) + { + string[] segments = collectionSelfLink.Split(RuntimeConstants.Separators.Url, StringSplitOptions.RemoveEmptyEntries); + + if (segments.Length != 4 + || !string.Equals(segments[0], Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase) + || !string.Equals(segments[2], Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase)) + { + throw new ArgumentException(RMResources.BadUrl, nameof(collectionSelfLink)); + } + + databaseId = segments[1]; + collectionId = segments[3]; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PerProtocolPartitionAddressInformation.cs b/Microsoft.Azure.Cosmos/src/direct/PerProtocolPartitionAddressInformation.cs index 7fdfa4a601..5842b9ef88 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerProtocolPartitionAddressInformation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerProtocolPartitionAddressInformation.cs @@ -1,124 +1,124 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Net; - using Microsoft.Azure.Documents.Client; - - internal sealed class PerProtocolPartitionAddressInformation - { - public PerProtocolPartitionAddressInformation( - Protocol protocol, - IReadOnlyList replicaAddresses) - { - if (replicaAddresses == null) - { - throw new ArgumentNullException(nameof(replicaAddresses)); - } - - IEnumerable nonEmptyReplicaAddresses = replicaAddresses - .Where(address => !string.IsNullOrEmpty(address.PhysicalUri) && address.Protocol == protocol); - - IEnumerable internalAddresses = nonEmptyReplicaAddresses.Where(address => !address.IsPublic); - this.ReplicaAddresses = internalAddresses.Any() ? internalAddresses.ToList() - : nonEmptyReplicaAddresses.Where(address => address.IsPublic).ToList(); - - this.ReplicaUris = this.ReplicaAddresses - .Select(e => new Uri(e.PhysicalUri)) - .ToList(); - - // The TransportAddressUri object for a replica is expected to be shared across all of the different - // compositions, like the ReplicaTransportAddressUris, NonPrimaryReplicaTransportAddressUris and - // PrimaryReplicaTransportAddressUri. This means that unlike the prior implementation, there will be - // a same object shared across all of the primary and non-primary replica lists and any changes in - // one of the object will be reflected across. - List transportUriHealthStates = new(); - List transportAddressUris = new(), nonPrimaryTransportAddressUris = new(); - foreach (AddressInformation addressInfo in this.ReplicaAddresses) - { - TransportAddressUri transportAddressUri = new (new Uri (addressInfo.PhysicalUri)); - - transportAddressUris.Add(transportAddressUri); - - if (addressInfo.IsPrimary && !addressInfo.PhysicalUri.Contains('[')) - { - this.PrimaryReplicaTransportAddressUri = transportAddressUri; - } - else - { - nonPrimaryTransportAddressUris.Add(transportAddressUri); - } - - transportUriHealthStates.Add(transportAddressUri - .GetCurrentHealthState() - .GetHealthStatusDiagnosticString()); - } - - this.Protocol = protocol; - this.ReplicaTransportAddressUris = transportAddressUris.AsReadOnly(); - this.ReplicaTransportAddressUrisHealthState = transportUriHealthStates.AsReadOnly(); - this.NonPrimaryReplicaTransportAddressUris = nonPrimaryTransportAddressUris.AsReadOnly(); - } - - /// - /// Sets the health state of the transport address uris. This is invoked by the - /// GatewayAddressCache to capture and cache the health state of the transport address uris. - /// - /// A read only list of strings, representing the current health state of the replicas. - public void SetTransportAddressUrisHealthState( - IReadOnlyList replicaHealthStates) - { - this.ReplicaTransportAddressUrisHealthState = replicaHealthStates; - } - - public TransportAddressUri GetPrimaryAddressUri(DocumentServiceRequest request) - { - TransportAddressUri primaryReplicaAddress = null; - // if replicaIndex is not set, or if replicaIndex is 0, we return primary address. - if (!request.DefaultReplicaIndex.HasValue || request.DefaultReplicaIndex.Value == 0) - { - primaryReplicaAddress = this.PrimaryReplicaTransportAddressUri; - } - else - { - if (request.DefaultReplicaIndex.Value > 0 && request.DefaultReplicaIndex.Value < this.ReplicaUris.Count) - { - primaryReplicaAddress = this.ReplicaTransportAddressUris[(int)request.DefaultReplicaIndex.Value]; - } - } - - if (primaryReplicaAddress == null) - { - // Primary endpoint (of the desired protocol) was not found. - throw new GoneException(string.Format(CultureInfo.CurrentUICulture, "The requested resource is no longer available at the server. Returned addresses are {0}", - string.Join(",", this.ReplicaAddresses.Select(address => address.PhysicalUri).ToList())), - SubStatusCodes.ServerGenerated410); - } - - return primaryReplicaAddress; - } - - public Protocol Protocol { get; } - - public IReadOnlyList NonPrimaryReplicaTransportAddressUris { get; } - - public IReadOnlyList ReplicaUris { get; } - - public IReadOnlyList ReplicaTransportAddressUris { get; } - - public IReadOnlyList ReplicaTransportAddressUrisHealthState { get; private set; } - - public Uri PrimaryReplicaUri => this.PrimaryReplicaTransportAddressUri?.Uri; - - public TransportAddressUri PrimaryReplicaTransportAddressUri { get; } - - public IReadOnlyList ReplicaAddresses { get; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Net; + using Microsoft.Azure.Documents.Client; + + internal sealed class PerProtocolPartitionAddressInformation + { + public PerProtocolPartitionAddressInformation( + Protocol protocol, + IReadOnlyList replicaAddresses) + { + if (replicaAddresses == null) + { + throw new ArgumentNullException(nameof(replicaAddresses)); + } + + IEnumerable nonEmptyReplicaAddresses = replicaAddresses + .Where(address => !string.IsNullOrEmpty(address.PhysicalUri) && address.Protocol == protocol); + + IEnumerable internalAddresses = nonEmptyReplicaAddresses.Where(address => !address.IsPublic); + this.ReplicaAddresses = internalAddresses.Any() ? internalAddresses.ToList() + : nonEmptyReplicaAddresses.Where(address => address.IsPublic).ToList(); + + this.ReplicaUris = this.ReplicaAddresses + .Select(e => new Uri(e.PhysicalUri)) + .ToList(); + + // The TransportAddressUri object for a replica is expected to be shared across all of the different + // compositions, like the ReplicaTransportAddressUris, NonPrimaryReplicaTransportAddressUris and + // PrimaryReplicaTransportAddressUri. This means that unlike the prior implementation, there will be + // a same object shared across all of the primary and non-primary replica lists and any changes in + // one of the object will be reflected across. + List transportUriHealthStates = new(); + List transportAddressUris = new(), nonPrimaryTransportAddressUris = new(); + foreach (AddressInformation addressInfo in this.ReplicaAddresses) + { + TransportAddressUri transportAddressUri = new (new Uri (addressInfo.PhysicalUri)); + + transportAddressUris.Add(transportAddressUri); + + if (addressInfo.IsPrimary && !addressInfo.PhysicalUri.Contains('[')) + { + this.PrimaryReplicaTransportAddressUri = transportAddressUri; + } + else + { + nonPrimaryTransportAddressUris.Add(transportAddressUri); + } + + transportUriHealthStates.Add(transportAddressUri + .GetCurrentHealthState() + .GetHealthStatusDiagnosticString()); + } + + this.Protocol = protocol; + this.ReplicaTransportAddressUris = transportAddressUris.AsReadOnly(); + this.ReplicaTransportAddressUrisHealthState = transportUriHealthStates.AsReadOnly(); + this.NonPrimaryReplicaTransportAddressUris = nonPrimaryTransportAddressUris.AsReadOnly(); + } + + /// + /// Sets the health state of the transport address uris. This is invoked by the + /// GatewayAddressCache to capture and cache the health state of the transport address uris. + /// + /// A read only list of strings, representing the current health state of the replicas. + public void SetTransportAddressUrisHealthState( + IReadOnlyList replicaHealthStates) + { + this.ReplicaTransportAddressUrisHealthState = replicaHealthStates; + } + + public TransportAddressUri GetPrimaryAddressUri(DocumentServiceRequest request) + { + TransportAddressUri primaryReplicaAddress = null; + // if replicaIndex is not set, or if replicaIndex is 0, we return primary address. + if (!request.DefaultReplicaIndex.HasValue || request.DefaultReplicaIndex.Value == 0) + { + primaryReplicaAddress = this.PrimaryReplicaTransportAddressUri; + } + else + { + if (request.DefaultReplicaIndex.Value > 0 && request.DefaultReplicaIndex.Value < this.ReplicaUris.Count) + { + primaryReplicaAddress = this.ReplicaTransportAddressUris[(int)request.DefaultReplicaIndex.Value]; + } + } + + if (primaryReplicaAddress == null) + { + // Primary endpoint (of the desired protocol) was not found. + throw new GoneException(string.Format(CultureInfo.CurrentUICulture, "The requested resource is no longer available at the server. Returned addresses are {0}", + string.Join(",", this.ReplicaAddresses.Select(address => address.PhysicalUri).ToList())), + SubStatusCodes.ServerGenerated410); + } + + return primaryReplicaAddress; + } + + public Protocol Protocol { get; } + + public IReadOnlyList NonPrimaryReplicaTransportAddressUris { get; } + + public IReadOnlyList ReplicaUris { get; } + + public IReadOnlyList ReplicaTransportAddressUris { get; } + + public IReadOnlyList ReplicaTransportAddressUrisHealthState { get; private set; } + + public Uri PrimaryReplicaUri => this.PrimaryReplicaTransportAddressUri?.Uri; + + public TransportAddressUri PrimaryReplicaTransportAddressUri { get; } + + public IReadOnlyList ReplicaAddresses { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs b/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs index 77d894adad..a270d41958 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs @@ -1,422 +1,422 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using Microsoft.Azure.Cosmos.ServiceFramework.Core; - - internal sealed class PerfCounters : IDisposable - { - private readonly string performanceCategory; - - private readonly string performanceCategoryHelp; - - private PerformanceCounter frontendRequestsPerSec; - - private PerformanceCounter frontendActiveRequests; - - private PerformanceCounter admissionControlledRequestsPerSec; - - private PerformanceCounter admissionControlledRequests; - - private PerformanceCounter backendRequestsPerSec; - - private PerformanceCounter backendActiveRequests; - - private PerformanceCounter currentFrontendConnections; - - private PerformanceCounter queryRequestsPerSec; - - private PerformanceCounter triggerRequestsPerSec; - - private PerformanceCounter procedureRequestsPerSec; - - private PerformanceCounter averageProcedureRequestsDuration; - - private PerformanceCounter averageProcedureRequestsDurationBase; - - private PerformanceCounter averageQueryRequestsDuration; - - private PerformanceCounter averageQueryRequestsDurationBase; - - private PerformanceCounter backendConnectionOpenAverageLatency; - - private PerformanceCounter backendConnectionOpenAverageLatencyBase; - - private PerformanceCounter routingFailures; - - private PerformanceCounter backendConnectionOpenFailuresDueToSynRetransmitPerSecond; - - private PerfCounters(string category, string categoryHelp) - { - this.performanceCategory = category; - this.performanceCategoryHelp = categoryHelp; - } - - public static PerfCounters Counters { get; } = new PerfCounters("DocDB Gateway", "Counters for DocDB Gateway"); - - public PerformanceCounter FrontendRequestsPerSec - { - get - { - return this.frontendRequestsPerSec; - } - } - - public PerformanceCounter FrontendActiveRequests - { - get - { - return this.frontendActiveRequests; - } - } - - public PerformanceCounter BackendRequestsPerSec - { - get - { - return this.backendRequestsPerSec; - } - } - - public PerformanceCounter BackendActiveRequests - { - get - { - return this.backendActiveRequests; - } - } - - public PerformanceCounter AdmissionControlledRequestsPerSec - { - get - { - return this.admissionControlledRequestsPerSec; - } - } - - public PerformanceCounter AdmissionControlledRequests - { - get - { - return this.admissionControlledRequests; - } - } - - public PerformanceCounter CurrentFrontendConnections - { - get - { - return this.currentFrontendConnections; - } - } - - public PerformanceCounter QueryRequestsPerSec - { - get - { - return this.queryRequestsPerSec; - } - } - - public PerformanceCounter TriggerRequestsPerSec - { - get - { - return this.triggerRequestsPerSec; - } - } - - public PerformanceCounter ProcedureRequestsPerSec - { - get - { - return this.procedureRequestsPerSec; - } - } - - public PerformanceCounter AverageProcedureRequestsDuration - { - get - { - return this.averageProcedureRequestsDuration; - } - } - - public PerformanceCounter AverageProcedureRequestsDurationBase - { - get - { - return this.averageProcedureRequestsDurationBase; - } - } - - public PerformanceCounter AverageQueryRequestsDuration - { - get - { - return this.averageQueryRequestsDuration; - } - } - - public PerformanceCounter AverageQueryRequestsDurationBase - { - get - { - return this.averageQueryRequestsDurationBase; - } - } - - public PerformanceCounter BackendConnectionOpenAverageLatency - { - get - { - return this.backendConnectionOpenAverageLatency; - } - } - - public PerformanceCounter BackendConnectionOpenAverageLatencyBase - { - get - { - return this.backendConnectionOpenAverageLatencyBase; - } - } - - public PerformanceCounter RoutingFailures - { - get - { - return this.routingFailures; - } - } - - public PerformanceCounter BackendConnectionOpenFailuresDueToSynRetransmitPerSecond - { - get - { - return this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond; - } - } - - /// - /// Creates the given performance counter category. - /// - /// Name of the category. - /// Help description. - /// Category type. - /// Counters in the category. - /// - /// Indicates whether machine-wide synchronization should be used to avoid races between different entry-points attempting to create the same category. - /// - /// If the category already exists then it is checked to ensure that the given counters are present. If not, the category is recreated. - internal static void CreatePerfCounterCategory(string category, - string categoryHelp, - PerformanceCounterCategoryType categoryType, - CounterCreationDataCollection counters, - bool useSystemMutex = true) - { - SystemSynchronizationScope syncScope = useSystemMutex ? SystemSynchronizationScope.CreateSynchronizationScope($"CDBPerfCategory-{category}") : default; - - try - { - // If the performance counter category already exists, check if any counters have changed. - if (PerformanceCounterCategory.Exists(category)) - { - PerformanceCounterCategory perfCategory = new PerformanceCounterCategory(category); - bool shouldReturn = true; - foreach (CounterCreationData counter in counters) - { - try - { - if (!perfCategory.CounterExists(counter.CounterName)) - { - shouldReturn = false; - break; - } - } - catch - { - shouldReturn = false; - break; - } - } - - if (shouldReturn) - { - return; - } - else - { - PerformanceCounterCategory.Delete(category); - } - } - - // Create the category. - PerformanceCounterCategory.Create(category, categoryHelp, categoryType, counters); - } - finally - { - syncScope?.Dispose(); - } - } - - /// - /// Creating performance counter category is a privileged operation and - /// hence done in the WinFab service setup entrypoint that is invoked before - /// the service is actually started. - /// - public void InstallCounters() - { - CounterCreationDataCollection counters = new CounterCreationDataCollection(); - - counters.Add(new CounterCreationData("Frontend Requests/sec", "Frontend Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Frontend Active Requests", "Frontend Active Requests", PerformanceCounterType.NumberOfItems32)); - - counters.Add(new CounterCreationData("Admission Controlled Requests/sec", "Admission controlled requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Admission Controlled Requests", "Admission controlled requests", PerformanceCounterType.CounterDelta32)); - - counters.Add(new CounterCreationData("Backend Requests/sec", "Backend Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Backend Active Requests", "Backend Active Requests", PerformanceCounterType.NumberOfItems32)); - - counters.Add(new CounterCreationData("Current Frontend Connections", "Current Connections from Frontend to backend", PerformanceCounterType.NumberOfItems32)); - - counters.Add(new CounterCreationData("Fabric Resolve Service Failures", "Number of failures for resolving a fabric service", PerformanceCounterType.CounterDelta32)); - - counters.Add(new CounterCreationData("Query Requests/sec", "Query Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Trigger Requests/sec", "Trigger Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Procedure Requests/sec", "Procedure Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); - - counters.Add(new CounterCreationData("Average Procedure Requests Duration", "Average Duration of a Procedure Request", PerformanceCounterType.AverageTimer32)); - - counters.Add(new CounterCreationData("Average Procedure Requests Duration Base", "Average Duration of a Procedure Request Base", PerformanceCounterType.AverageBase)); - - counters.Add(new CounterCreationData("Average Query Requests Duration", "Average Duration of a Query Request", PerformanceCounterType.AverageTimer32)); - - counters.Add(new CounterCreationData("Average Query Requests Duration Base", "Average Duration of a Query Request Base", PerformanceCounterType.AverageBase)); - - counters.Add(new CounterCreationData("Backend Connection Open Average Latency", "Average time to open a connection to the backend", PerformanceCounterType.AverageTimer32)); - - counters.Add(new CounterCreationData("Backend Connection Open Average Latency Base", "Average time to open a connection to the backend Base", PerformanceCounterType.AverageBase)); - - counters.Add(new CounterCreationData("Fabric Resolve Service Average Latency", "Average time to resolve a fabric service", PerformanceCounterType.AverageTimer32)); - - counters.Add(new CounterCreationData("Fabric Resolve Service Average Latency Base", "Average time to resolve a fabric service Base", PerformanceCounterType.AverageBase)); - - counters.Add(new CounterCreationData("Routing Failures", "Number of failures for connecting to a stale replica", PerformanceCounterType.CounterDelta32)); - - counters.Add(new CounterCreationData("Backend Connection Open Failures Due To Syn Retransmit Timeout/sec", "Number of failures per second when connecting to a backend node which failed with WSAETIMEDOUT", PerformanceCounterType.RateOfCountsPerSecond32)); - - PerfCounters.CreatePerfCounterCategory(this.performanceCategory, this.performanceCategoryHelp, PerformanceCounterCategoryType.SingleInstance, counters); - } - - public void InitializePerfCounters() - { - this.frontendRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Frontend Requests/sec", false); - this.frontendRequestsPerSec.RawValue = 0; - - this.frontendActiveRequests = new PerformanceCounter(this.performanceCategory, "Frontend Active Requests", false); - this.frontendActiveRequests.RawValue = 0; - - this.admissionControlledRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Admission Controlled Requests/sec", false); - this.admissionControlledRequestsPerSec.RawValue = 0; - - this.admissionControlledRequests = new PerformanceCounter(this.performanceCategory, "Admission Controlled Requests", false); - this.admissionControlledRequests.RawValue = 0; - - this.backendRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Backend Requests/sec", false); - this.backendRequestsPerSec.RawValue = 0; - - this.backendActiveRequests = new PerformanceCounter(this.performanceCategory, "Backend Active Requests", false); - this.backendActiveRequests.RawValue = 0; - - this.currentFrontendConnections = new PerformanceCounter(this.performanceCategory, "Current Frontend Connections", false); - this.currentFrontendConnections.RawValue = 0; - - this.queryRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Query Requests/sec", false); - this.queryRequestsPerSec.RawValue = 0; - - this.triggerRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Trigger Requests/sec", false); - this.triggerRequestsPerSec.RawValue = 0; - - this.procedureRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Procedure Requests/sec", false); - this.procedureRequestsPerSec.RawValue = 0; - - this.averageProcedureRequestsDuration = new PerformanceCounter(this.performanceCategory, "Average Procedure Requests Duration", false); - this.averageProcedureRequestsDuration.RawValue = 0; - - this.averageProcedureRequestsDurationBase = new PerformanceCounter(this.performanceCategory, "Average Procedure Requests Duration Base", false); - this.averageProcedureRequestsDurationBase.RawValue = 0; - - this.averageQueryRequestsDuration = new PerformanceCounter(this.performanceCategory, "Average Query Requests Duration", false); - this.averageQueryRequestsDuration.RawValue = 0; - - this.averageQueryRequestsDurationBase = new PerformanceCounter(this.performanceCategory, "Average Query Requests Duration Base", false); - this.averageQueryRequestsDurationBase.RawValue = 0; - - this.backendConnectionOpenAverageLatency = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Average Latency", false); - this.backendConnectionOpenAverageLatency.RawValue = 0; - - this.backendConnectionOpenAverageLatencyBase = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Average Latency Base", false); - this.backendConnectionOpenAverageLatencyBase.RawValue = 0; - - this.routingFailures = new PerformanceCounter(this.performanceCategory, "Routing Failures", false); - this.routingFailures.RawValue = 0; - - this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Failures Due To Syn Retransmit Timeout/sec", false); - this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond.RawValue = 0; - } - - #region IDisposable Members - - public void Dispose() - { -#pragma warning disable SA1501 - using (this.frontendActiveRequests) { } - - using (this.frontendRequestsPerSec) { } - - using (this.admissionControlledRequests) { } - - using (this.admissionControlledRequestsPerSec) { } - - using (this.backendActiveRequests) { } - - using (this.backendRequestsPerSec) { } - - using (this.currentFrontendConnections) { } - - using (this.queryRequestsPerSec) { } - - using (this.triggerRequestsPerSec) { } - - using (this.procedureRequestsPerSec) { } - - using (this.averageProcedureRequestsDuration) { } - - using (this.averageProcedureRequestsDurationBase) { } - - using (this.averageQueryRequestsDuration) { } - - using (this.averageQueryRequestsDurationBase) { } - - using (this.backendConnectionOpenAverageLatency) { } - - using (this.backendConnectionOpenAverageLatencyBase) { } - - using (this.routingFailures) { } - - using (this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond) { } -#pragma warning restore SA1501 - } - - #endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using Microsoft.Azure.Cosmos.ServiceFramework.Core; + + internal sealed class PerfCounters : IDisposable + { + private readonly string performanceCategory; + + private readonly string performanceCategoryHelp; + + private PerformanceCounter frontendRequestsPerSec; + + private PerformanceCounter frontendActiveRequests; + + private PerformanceCounter admissionControlledRequestsPerSec; + + private PerformanceCounter admissionControlledRequests; + + private PerformanceCounter backendRequestsPerSec; + + private PerformanceCounter backendActiveRequests; + + private PerformanceCounter currentFrontendConnections; + + private PerformanceCounter queryRequestsPerSec; + + private PerformanceCounter triggerRequestsPerSec; + + private PerformanceCounter procedureRequestsPerSec; + + private PerformanceCounter averageProcedureRequestsDuration; + + private PerformanceCounter averageProcedureRequestsDurationBase; + + private PerformanceCounter averageQueryRequestsDuration; + + private PerformanceCounter averageQueryRequestsDurationBase; + + private PerformanceCounter backendConnectionOpenAverageLatency; + + private PerformanceCounter backendConnectionOpenAverageLatencyBase; + + private PerformanceCounter routingFailures; + + private PerformanceCounter backendConnectionOpenFailuresDueToSynRetransmitPerSecond; + + private PerfCounters(string category, string categoryHelp) + { + this.performanceCategory = category; + this.performanceCategoryHelp = categoryHelp; + } + + public static PerfCounters Counters { get; } = new PerfCounters("DocDB Gateway", "Counters for DocDB Gateway"); + + public PerformanceCounter FrontendRequestsPerSec + { + get + { + return this.frontendRequestsPerSec; + } + } + + public PerformanceCounter FrontendActiveRequests + { + get + { + return this.frontendActiveRequests; + } + } + + public PerformanceCounter BackendRequestsPerSec + { + get + { + return this.backendRequestsPerSec; + } + } + + public PerformanceCounter BackendActiveRequests + { + get + { + return this.backendActiveRequests; + } + } + + public PerformanceCounter AdmissionControlledRequestsPerSec + { + get + { + return this.admissionControlledRequestsPerSec; + } + } + + public PerformanceCounter AdmissionControlledRequests + { + get + { + return this.admissionControlledRequests; + } + } + + public PerformanceCounter CurrentFrontendConnections + { + get + { + return this.currentFrontendConnections; + } + } + + public PerformanceCounter QueryRequestsPerSec + { + get + { + return this.queryRequestsPerSec; + } + } + + public PerformanceCounter TriggerRequestsPerSec + { + get + { + return this.triggerRequestsPerSec; + } + } + + public PerformanceCounter ProcedureRequestsPerSec + { + get + { + return this.procedureRequestsPerSec; + } + } + + public PerformanceCounter AverageProcedureRequestsDuration + { + get + { + return this.averageProcedureRequestsDuration; + } + } + + public PerformanceCounter AverageProcedureRequestsDurationBase + { + get + { + return this.averageProcedureRequestsDurationBase; + } + } + + public PerformanceCounter AverageQueryRequestsDuration + { + get + { + return this.averageQueryRequestsDuration; + } + } + + public PerformanceCounter AverageQueryRequestsDurationBase + { + get + { + return this.averageQueryRequestsDurationBase; + } + } + + public PerformanceCounter BackendConnectionOpenAverageLatency + { + get + { + return this.backendConnectionOpenAverageLatency; + } + } + + public PerformanceCounter BackendConnectionOpenAverageLatencyBase + { + get + { + return this.backendConnectionOpenAverageLatencyBase; + } + } + + public PerformanceCounter RoutingFailures + { + get + { + return this.routingFailures; + } + } + + public PerformanceCounter BackendConnectionOpenFailuresDueToSynRetransmitPerSecond + { + get + { + return this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond; + } + } + + /// + /// Creates the given performance counter category. + /// + /// Name of the category. + /// Help description. + /// Category type. + /// Counters in the category. + /// + /// Indicates whether machine-wide synchronization should be used to avoid races between different entry-points attempting to create the same category. + /// + /// If the category already exists then it is checked to ensure that the given counters are present. If not, the category is recreated. + internal static void CreatePerfCounterCategory(string category, + string categoryHelp, + PerformanceCounterCategoryType categoryType, + CounterCreationDataCollection counters, + bool useSystemMutex = true) + { + SystemSynchronizationScope syncScope = useSystemMutex ? SystemSynchronizationScope.CreateSynchronizationScope($"CDBPerfCategory-{category}") : default; + + try + { + // If the performance counter category already exists, check if any counters have changed. + if (PerformanceCounterCategory.Exists(category)) + { + PerformanceCounterCategory perfCategory = new PerformanceCounterCategory(category); + bool shouldReturn = true; + foreach (CounterCreationData counter in counters) + { + try + { + if (!perfCategory.CounterExists(counter.CounterName)) + { + shouldReturn = false; + break; + } + } + catch + { + shouldReturn = false; + break; + } + } + + if (shouldReturn) + { + return; + } + else + { + PerformanceCounterCategory.Delete(category); + } + } + + // Create the category. + PerformanceCounterCategory.Create(category, categoryHelp, categoryType, counters); + } + finally + { + syncScope?.Dispose(); + } + } + + /// + /// Creating performance counter category is a privileged operation and + /// hence done in the WinFab service setup entrypoint that is invoked before + /// the service is actually started. + /// + public void InstallCounters() + { + CounterCreationDataCollection counters = new CounterCreationDataCollection(); + + counters.Add(new CounterCreationData("Frontend Requests/sec", "Frontend Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Frontend Active Requests", "Frontend Active Requests", PerformanceCounterType.NumberOfItems32)); + + counters.Add(new CounterCreationData("Admission Controlled Requests/sec", "Admission controlled requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Admission Controlled Requests", "Admission controlled requests", PerformanceCounterType.CounterDelta32)); + + counters.Add(new CounterCreationData("Backend Requests/sec", "Backend Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Backend Active Requests", "Backend Active Requests", PerformanceCounterType.NumberOfItems32)); + + counters.Add(new CounterCreationData("Current Frontend Connections", "Current Connections from Frontend to backend", PerformanceCounterType.NumberOfItems32)); + + counters.Add(new CounterCreationData("Fabric Resolve Service Failures", "Number of failures for resolving a fabric service", PerformanceCounterType.CounterDelta32)); + + counters.Add(new CounterCreationData("Query Requests/sec", "Query Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Trigger Requests/sec", "Trigger Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Procedure Requests/sec", "Procedure Requests per second", PerformanceCounterType.RateOfCountsPerSecond32)); + + counters.Add(new CounterCreationData("Average Procedure Requests Duration", "Average Duration of a Procedure Request", PerformanceCounterType.AverageTimer32)); + + counters.Add(new CounterCreationData("Average Procedure Requests Duration Base", "Average Duration of a Procedure Request Base", PerformanceCounterType.AverageBase)); + + counters.Add(new CounterCreationData("Average Query Requests Duration", "Average Duration of a Query Request", PerformanceCounterType.AverageTimer32)); + + counters.Add(new CounterCreationData("Average Query Requests Duration Base", "Average Duration of a Query Request Base", PerformanceCounterType.AverageBase)); + + counters.Add(new CounterCreationData("Backend Connection Open Average Latency", "Average time to open a connection to the backend", PerformanceCounterType.AverageTimer32)); + + counters.Add(new CounterCreationData("Backend Connection Open Average Latency Base", "Average time to open a connection to the backend Base", PerformanceCounterType.AverageBase)); + + counters.Add(new CounterCreationData("Fabric Resolve Service Average Latency", "Average time to resolve a fabric service", PerformanceCounterType.AverageTimer32)); + + counters.Add(new CounterCreationData("Fabric Resolve Service Average Latency Base", "Average time to resolve a fabric service Base", PerformanceCounterType.AverageBase)); + + counters.Add(new CounterCreationData("Routing Failures", "Number of failures for connecting to a stale replica", PerformanceCounterType.CounterDelta32)); + + counters.Add(new CounterCreationData("Backend Connection Open Failures Due To Syn Retransmit Timeout/sec", "Number of failures per second when connecting to a backend node which failed with WSAETIMEDOUT", PerformanceCounterType.RateOfCountsPerSecond32)); + + PerfCounters.CreatePerfCounterCategory(this.performanceCategory, this.performanceCategoryHelp, PerformanceCounterCategoryType.SingleInstance, counters); + } + + public void InitializePerfCounters() + { + this.frontendRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Frontend Requests/sec", false); + this.frontendRequestsPerSec.RawValue = 0; + + this.frontendActiveRequests = new PerformanceCounter(this.performanceCategory, "Frontend Active Requests", false); + this.frontendActiveRequests.RawValue = 0; + + this.admissionControlledRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Admission Controlled Requests/sec", false); + this.admissionControlledRequestsPerSec.RawValue = 0; + + this.admissionControlledRequests = new PerformanceCounter(this.performanceCategory, "Admission Controlled Requests", false); + this.admissionControlledRequests.RawValue = 0; + + this.backendRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Backend Requests/sec", false); + this.backendRequestsPerSec.RawValue = 0; + + this.backendActiveRequests = new PerformanceCounter(this.performanceCategory, "Backend Active Requests", false); + this.backendActiveRequests.RawValue = 0; + + this.currentFrontendConnections = new PerformanceCounter(this.performanceCategory, "Current Frontend Connections", false); + this.currentFrontendConnections.RawValue = 0; + + this.queryRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Query Requests/sec", false); + this.queryRequestsPerSec.RawValue = 0; + + this.triggerRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Trigger Requests/sec", false); + this.triggerRequestsPerSec.RawValue = 0; + + this.procedureRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Procedure Requests/sec", false); + this.procedureRequestsPerSec.RawValue = 0; + + this.averageProcedureRequestsDuration = new PerformanceCounter(this.performanceCategory, "Average Procedure Requests Duration", false); + this.averageProcedureRequestsDuration.RawValue = 0; + + this.averageProcedureRequestsDurationBase = new PerformanceCounter(this.performanceCategory, "Average Procedure Requests Duration Base", false); + this.averageProcedureRequestsDurationBase.RawValue = 0; + + this.averageQueryRequestsDuration = new PerformanceCounter(this.performanceCategory, "Average Query Requests Duration", false); + this.averageQueryRequestsDuration.RawValue = 0; + + this.averageQueryRequestsDurationBase = new PerformanceCounter(this.performanceCategory, "Average Query Requests Duration Base", false); + this.averageQueryRequestsDurationBase.RawValue = 0; + + this.backendConnectionOpenAverageLatency = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Average Latency", false); + this.backendConnectionOpenAverageLatency.RawValue = 0; + + this.backendConnectionOpenAverageLatencyBase = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Average Latency Base", false); + this.backendConnectionOpenAverageLatencyBase.RawValue = 0; + + this.routingFailures = new PerformanceCounter(this.performanceCategory, "Routing Failures", false); + this.routingFailures.RawValue = 0; + + this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Failures Due To Syn Retransmit Timeout/sec", false); + this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond.RawValue = 0; + } + + #region IDisposable Members + + public void Dispose() + { +#pragma warning disable SA1501 + using (this.frontendActiveRequests) { } + + using (this.frontendRequestsPerSec) { } + + using (this.admissionControlledRequests) { } + + using (this.admissionControlledRequestsPerSec) { } + + using (this.backendActiveRequests) { } + + using (this.backendRequestsPerSec) { } + + using (this.currentFrontendConnections) { } + + using (this.queryRequestsPerSec) { } + + using (this.triggerRequestsPerSec) { } + + using (this.procedureRequestsPerSec) { } + + using (this.averageProcedureRequestsDuration) { } + + using (this.averageProcedureRequestsDurationBase) { } + + using (this.averageQueryRequestsDuration) { } + + using (this.averageQueryRequestsDurationBase) { } + + using (this.backendConnectionOpenAverageLatency) { } + + using (this.backendConnectionOpenAverageLatencyBase) { } + + using (this.routingFailures) { } + + using (this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond) { } +#pragma warning restore SA1501 + } + + #endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs index 59ad2c2b0c..bbf9dda82b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal sealed class OpenConnectionPerformanceActivity : PerformanceActivity - { - public OpenConnectionPerformanceActivity() - : base(null, null, null, PerfCounters.Counters.BackendConnectionOpenAverageLatency, PerfCounters.Counters.BackendConnectionOpenAverageLatencyBase, "OpenConnection") - { } - } - - internal sealed class QueryRequestPerformanceActivity : PerformanceActivity - { - public QueryRequestPerformanceActivity() - : base(PerfCounters.Counters.QueryRequestsPerSec, null, null, PerfCounters.Counters.AverageQueryRequestsDuration, PerfCounters.Counters.AverageQueryRequestsDurationBase, null) - { } - } - - internal sealed class ProcedureRequestPerformanceActivity : PerformanceActivity - { - public ProcedureRequestPerformanceActivity() - : base(PerfCounters.Counters.ProcedureRequestsPerSec, null, null, PerfCounters.Counters.AverageProcedureRequestsDuration, PerfCounters.Counters.AverageProcedureRequestsDurationBase, null) - { } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal sealed class OpenConnectionPerformanceActivity : PerformanceActivity + { + public OpenConnectionPerformanceActivity() + : base(null, null, null, PerfCounters.Counters.BackendConnectionOpenAverageLatency, PerfCounters.Counters.BackendConnectionOpenAverageLatencyBase, "OpenConnection") + { } + } + + internal sealed class QueryRequestPerformanceActivity : PerformanceActivity + { + public QueryRequestPerformanceActivity() + : base(PerfCounters.Counters.QueryRequestsPerSec, null, null, PerfCounters.Counters.AverageQueryRequestsDuration, PerfCounters.Counters.AverageQueryRequestsDurationBase, null) + { } + } + + internal sealed class ProcedureRequestPerformanceActivity : PerformanceActivity + { + public ProcedureRequestPerformanceActivity() + : base(PerfCounters.Counters.ProcedureRequestsPerSec, null, null, PerfCounters.Counters.AverageProcedureRequestsDuration, PerfCounters.Counters.AverageProcedureRequestsDurationBase, null) + { } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivity.cs b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivity.cs index ed45fc898e..2b6b4b2340 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivity.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivity.cs @@ -1,143 +1,143 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - - internal class PerformanceActivity - { - private bool callCompleted; - private static readonly long MaxTicks = TimeSpan.FromHours(6).Ticks; - private Stopwatch stopWatch; - - private readonly PerformanceCounter requestsCounter; - private readonly PerformanceCounter currentRequestsCounter; - private readonly PerformanceCounter failuresCounter; - - private readonly PerformanceCounter averageTimeCounter; - private readonly PerformanceCounter averageTimeBaseCounter; - - private string operationName; - - public delegate void OperationDurationDelegate(Guid ActivityId, string operation, double milliseconds); - -#pragma warning disable 0649 - /// - /// The delegate is populated by the assembly that desires to trace the . - /// Hence ignore the warning "CS0649: field is never assigned to, and will always have its default value null" - /// - internal static OperationDurationDelegate OperationDuration; -#pragma warning restore 0649 - - protected PerformanceActivity( - PerformanceCounter requestsCounter, - PerformanceCounter currentRequestsCounter, - PerformanceCounter failuresCounter, - PerformanceCounter averageTimeCounter, - PerformanceCounter averageTimeBaseCounter, - string operation - ) - { - this.callCompleted = false; - this.requestsCounter = requestsCounter; - this.currentRequestsCounter = currentRequestsCounter; - this.failuresCounter = failuresCounter; - - this.averageTimeCounter = averageTimeCounter; - this.averageTimeBaseCounter = averageTimeBaseCounter; - this.operationName = operation; - - this.stopWatch = new Stopwatch(); - } - - - protected string OperationName - { - get { return this.operationName; } - set { this.operationName = value; } - } - - public long ElapsedTicks - { - get - { - return stopWatch.ElapsedTicks; - } - } - - public double ElapsedMilliseconds - { - get - { - return stopWatch.Elapsed.TotalMilliseconds; - } - } - - protected Stopwatch StopWatch - { - get - { - return this.stopWatch; - } - } - - public void ActivityStart() - { - stopWatch.Start(); - - if (this.requestsCounter != null) - { - this.requestsCounter.Increment(); - } - - if (this.currentRequestsCounter != null) - { - this.currentRequestsCounter.Increment(); - } - } - - public virtual void ActivityComplete(bool success = true) - { - if (this.callCompleted == true) - { - return; - } - - this.callCompleted = true; - - stopWatch.Stop(); - - long ticks = stopWatch.ElapsedTicks; - - if (this.averageTimeCounter != null && ticks < PerformanceActivity.MaxTicks) - { - this.averageTimeCounter.IncrementBy(ticks); - this.averageTimeBaseCounter.Increment(); - } - - if (this.operationName != null && PerformanceActivity.OperationDuration != null && ticks < PerformanceActivity.MaxTicks) - { - PerformanceActivity.OperationDuration(Trace.CorrelationManager.ActivityId, this.operationName, stopWatch.ElapsedMilliseconds); - } - - if (this.currentRequestsCounter != null) - { - this.currentRequestsCounter.Decrement(); - } - - if (success == false && this.failuresCounter != null) - { - this.failuresCounter.Increment(); - } - } - } - - internal sealed class RequestPerformanceActivity : PerformanceActivity - { - public RequestPerformanceActivity() - : base(null, null, null, null, null, null) - { } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + + internal class PerformanceActivity + { + private bool callCompleted; + private static readonly long MaxTicks = TimeSpan.FromHours(6).Ticks; + private Stopwatch stopWatch; + + private readonly PerformanceCounter requestsCounter; + private readonly PerformanceCounter currentRequestsCounter; + private readonly PerformanceCounter failuresCounter; + + private readonly PerformanceCounter averageTimeCounter; + private readonly PerformanceCounter averageTimeBaseCounter; + + private string operationName; + + public delegate void OperationDurationDelegate(Guid ActivityId, string operation, double milliseconds); + +#pragma warning disable 0649 + /// + /// The delegate is populated by the assembly that desires to trace the . + /// Hence ignore the warning "CS0649: field is never assigned to, and will always have its default value null" + /// + internal static OperationDurationDelegate OperationDuration; +#pragma warning restore 0649 + + protected PerformanceActivity( + PerformanceCounter requestsCounter, + PerformanceCounter currentRequestsCounter, + PerformanceCounter failuresCounter, + PerformanceCounter averageTimeCounter, + PerformanceCounter averageTimeBaseCounter, + string operation + ) + { + this.callCompleted = false; + this.requestsCounter = requestsCounter; + this.currentRequestsCounter = currentRequestsCounter; + this.failuresCounter = failuresCounter; + + this.averageTimeCounter = averageTimeCounter; + this.averageTimeBaseCounter = averageTimeBaseCounter; + this.operationName = operation; + + this.stopWatch = new Stopwatch(); + } + + + protected string OperationName + { + get { return this.operationName; } + set { this.operationName = value; } + } + + public long ElapsedTicks + { + get + { + return stopWatch.ElapsedTicks; + } + } + + public double ElapsedMilliseconds + { + get + { + return stopWatch.Elapsed.TotalMilliseconds; + } + } + + protected Stopwatch StopWatch + { + get + { + return this.stopWatch; + } + } + + public void ActivityStart() + { + stopWatch.Start(); + + if (this.requestsCounter != null) + { + this.requestsCounter.Increment(); + } + + if (this.currentRequestsCounter != null) + { + this.currentRequestsCounter.Increment(); + } + } + + public virtual void ActivityComplete(bool success = true) + { + if (this.callCompleted == true) + { + return; + } + + this.callCompleted = true; + + stopWatch.Stop(); + + long ticks = stopWatch.ElapsedTicks; + + if (this.averageTimeCounter != null && ticks < PerformanceActivity.MaxTicks) + { + this.averageTimeCounter.IncrementBy(ticks); + this.averageTimeBaseCounter.Increment(); + } + + if (this.operationName != null && PerformanceActivity.OperationDuration != null && ticks < PerformanceActivity.MaxTicks) + { + PerformanceActivity.OperationDuration(Trace.CorrelationManager.ActivityId, this.operationName, stopWatch.ElapsedMilliseconds); + } + + if (this.currentRequestsCounter != null) + { + this.currentRequestsCounter.Decrement(); + } + + if (success == false && this.failuresCounter != null) + { + this.failuresCounter.Increment(); + } + } + } + + internal sealed class RequestPerformanceActivity : PerformanceActivity + { + public RequestPerformanceActivity() + : base(null, null, null, null, null, null) + { } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Permission.cs b/Microsoft.Azure.Cosmos/src/direct/Permission.cs index 93c952c7c5..6de7585d6f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Permission.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Permission.cs @@ -1,103 +1,103 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Microsoft.Azure.Documents.Routing; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents a per-User permission to access a specific resource in the Azure Cosmos DB service, for example Document or Collection. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Permission : Resource - { - /// - /// Gets or sets the self-link of resource to which the permission applies in the Azure Cosmos DB service. - /// - /// - /// The self-link of the resource to which the permission applies. - /// - [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] - public string ResourceLink - { - get - { - return base.GetValue(Constants.Properties.ResourceLink); - } - set - { - base.SetValue(Constants.Properties.ResourceLink, value); - } - } - - /// - /// Gets or sets optional partition key value for the permission in the Azure Cosmos DB service. - /// A permission applies to resources when two conditions are met: - /// 1. is prefix of resource's link. - /// For example "/dbs/mydatabase/colls/mycollection" applies to "/dbs/mydatabase/colls/mycollection" and "/dbs/mydatabase/colls/mycollection/docs/mydocument" - /// 2. is superset of resource's partition key. - /// For example absent/empty partition key is superset of all partition keys. - /// - [JsonProperty(PropertyName = Constants.Properties.ResourcePartitionKey)] - public PartitionKey ResourcePartitionKey - { - get - { - PartitionKeyInternal partitionKey = base.GetValue(Constants.Properties.ResourcePartitionKey); - return partitionKey == null ? null : new PartitionKey(partitionKey.ToObjectArray()[0]); - } - set - { - if (value != null) - { - base.SetValue(Constants.Properties.ResourcePartitionKey, value.InternalKey); - } - } - } - - /// - /// Gets or sets the permission mode in the Azure Cosmos DB service. - /// - /// - /// The mode: Read or All. - /// - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty(PropertyName = Constants.Properties.PermissionMode)] - public PermissionMode PermissionMode - { - get - { - return base.GetValue(Constants.Properties.PermissionMode, PermissionMode.All); - } - set - { - base.SetValue(Constants.Properties.PermissionMode, value.ToString()); - } - } - - /// - /// Gets the access token granting the defined permission from the Azure Cosmos DB service. - /// - /// - /// The access token granting the defined permission. - /// - [JsonProperty(PropertyName = Constants.Properties.Token)] - public string Token - { - get - { - return base.GetValue(Constants.Properties.Token); - } - private set - { - base.SetValue(Constants.Properties.Token, value); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Microsoft.Azure.Documents.Routing; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents a per-User permission to access a specific resource in the Azure Cosmos DB service, for example Document or Collection. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Permission : Resource + { + /// + /// Gets or sets the self-link of resource to which the permission applies in the Azure Cosmos DB service. + /// + /// + /// The self-link of the resource to which the permission applies. + /// + [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] + public string ResourceLink + { + get + { + return base.GetValue(Constants.Properties.ResourceLink); + } + set + { + base.SetValue(Constants.Properties.ResourceLink, value); + } + } + + /// + /// Gets or sets optional partition key value for the permission in the Azure Cosmos DB service. + /// A permission applies to resources when two conditions are met: + /// 1. is prefix of resource's link. + /// For example "/dbs/mydatabase/colls/mycollection" applies to "/dbs/mydatabase/colls/mycollection" and "/dbs/mydatabase/colls/mycollection/docs/mydocument" + /// 2. is superset of resource's partition key. + /// For example absent/empty partition key is superset of all partition keys. + /// + [JsonProperty(PropertyName = Constants.Properties.ResourcePartitionKey)] + public PartitionKey ResourcePartitionKey + { + get + { + PartitionKeyInternal partitionKey = base.GetValue(Constants.Properties.ResourcePartitionKey); + return partitionKey == null ? null : new PartitionKey(partitionKey.ToObjectArray()[0]); + } + set + { + if (value != null) + { + base.SetValue(Constants.Properties.ResourcePartitionKey, value.InternalKey); + } + } + } + + /// + /// Gets or sets the permission mode in the Azure Cosmos DB service. + /// + /// + /// The mode: Read or All. + /// + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty(PropertyName = Constants.Properties.PermissionMode)] + public PermissionMode PermissionMode + { + get + { + return base.GetValue(Constants.Properties.PermissionMode, PermissionMode.All); + } + set + { + base.SetValue(Constants.Properties.PermissionMode, value.ToString()); + } + } + + /// + /// Gets the access token granting the defined permission from the Azure Cosmos DB service. + /// + /// + /// The access token granting the defined permission. + /// + [JsonProperty(PropertyName = Constants.Properties.Token)] + public string Token + { + get + { + return base.GetValue(Constants.Properties.Token); + } + private set + { + base.SetValue(Constants.Properties.Token, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PermissionMode.cs b/Microsoft.Azure.Cosmos/src/direct/PermissionMode.cs index dccf023cac..23070e9b53 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PermissionMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PermissionMode.cs @@ -1,32 +1,32 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// These are the access permissions for creating or replacing a resource in the Azure Cosmos DB service. - /// - /// - /// A Permission resource associates an access permission of a user on a particular resource. - /// - [Flags] -#if COSMOSCLIENT - internal -#else - public -#endif - enum PermissionMode : byte - { - /// - /// Read permission mode will provide the user with Read only access to a resource. - /// - Read = 0x1, - - /// - /// All permission mode will provide the user with full access(read, insert, replace and delete) to a resource. - /// - All = 0x2 - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// These are the access permissions for creating or replacing a resource in the Azure Cosmos DB service. + /// + /// + /// A Permission resource associates an access permission of a user on a particular resource. + /// + [Flags] +#if COSMOSCLIENT + internal +#else + public +#endif + enum PermissionMode : byte + { + /// + /// Read permission mode will provide the user with Read only access to a resource. + /// + Read = 0x1, + + /// + /// All permission mode will provide the user with full access(read, insert, replace and delete) to a resource. + /// + All = 0x2 + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Platform.cs b/Microsoft.Azure.Cosmos/src/direct/Platform.cs index 57c2d2cba0..35c3f2bc9f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Platform.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Platform.cs @@ -1,14 +1,14 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum Platform - { - Unknown = 0, - Windows = 1, - Linux = 2, - Darwin = 3 - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum Platform + { + Unknown = 0, + Windows = 1, + Linux = 2, + Darwin = 3 + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PlatformApis.cs b/Microsoft.Azure.Cosmos/src/direct/PlatformApis.cs index 47eda915ee..9a37766fe4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PlatformApis.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PlatformApis.cs @@ -1,162 +1,162 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.IO; - using System.Runtime.InteropServices; - using System.Text.RegularExpressions; - - internal static class PlatformApis - { - private class DistroInfo - { - public string Id; - public string VersionId; - } - - private static readonly Lazy _platform = new Lazy(DetermineOSPlatform); - private static readonly Lazy _distroInfo = new Lazy(LoadDistroInfo); - - public static string GetOSName() - { - switch (GetOSPlatform()) - { - case Platform.Windows: - return "Windows"; - case Platform.Linux: - return GetDistroId() ?? "Linux"; - case Platform.Darwin: - return "Mac OS X"; - default: - return "Unknown"; - } - } - - public static string GetOSVersion() - { - try - { - switch (GetOSPlatform()) - { - case Platform.Windows: - return GetWindowsVersion(RuntimeInformation.OSDescription) ?? string.Empty; - case Platform.Linux: - return GetDistroVersionId() ?? string.Empty; - case Platform.Darwin: - return GetDarwinVersion() ?? string.Empty; - default: - return string.Empty; - } - } - catch - { - return string.Empty; - } - - } - - public static string GetWindowsVersion(string osDescipiton) - { - Regex regex = new Regex(@"([0-9]+\.*)+"); - Match match = regex.Match(osDescipiton); - return match.ToString(); - } - - private static string GetDarwinVersion() - { - Version version; - string kernelRelease = NativeMethods.Darwin.GetKernelRelease(); - if (!Version.TryParse(kernelRelease, out version) || version.Major < 5) - { - // 10.0 covers all versions prior to Darwin 5 - // Similarly, if the version is not a valid version number, but we have still detected that it is Darwin, we just assume - // it is OS X 10.0 - return "10.0"; - } - else - { - // Mac OS X 10.1 mapped to Darwin 5.x, and the mapping continues that way - // So just subtract 4 from the Darwin version. - // https://en.wikipedia.org/wiki/Darwin_%28operating_system%29 - return $"10.{version.Major - 4}"; - } - } - - public static Platform GetOSPlatform() - { - return _platform.Value; - } - - private static string GetDistroId() - { - return _distroInfo.Value?.Id; - } - - private static string GetDistroVersionId() - { - return _distroInfo.Value?.VersionId; - } - - private static DistroInfo LoadDistroInfo() - { - // Sample os-release file: - // NAME="Ubuntu" - // VERSION = "14.04.3 LTS, Trusty Tahr" - // ID = ubuntu - // ID_LIKE = debian - // PRETTY_NAME = "Ubuntu 14.04.3 LTS" - // VERSION_ID = "14.04" - // HOME_URL = "http://www.ubuntu.com/" - // SUPPORT_URL = "http://help.ubuntu.com/" - // BUG_REPORT_URL = "http://bugs.launchpad.net/ubuntu/" - // We use ID and VERSION_ID - - if (File.Exists("/etc/os-release")) - { - string[] lines = File.ReadAllLines("/etc/os-release"); - DistroInfo result = new DistroInfo(); - foreach (string line in lines) - { - if (line.StartsWith("ID=", StringComparison.Ordinal)) - { - result.Id = line.Substring(3).Trim('"', '\''); - } - else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal)) - { - result.VersionId = line.Substring(11).Trim('"', '\''); - } - } - return result; - } - - string osType = File.Exists("/proc/sys/kernel/ostype") - ? File.ReadAllText("/proc/sys/kernel/ostype") - : null; - - string osRelease = File.Exists("/proc/sys/kernel/osrelease") - ? File.ReadAllText("/proc/sys/kernel/osrelease") - : null; - - return new DistroInfo() {Id = osType, VersionId = osRelease}; - } - private static Platform DetermineOSPlatform() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return Platform.Windows; - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return Platform.Linux; - } - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return Platform.Darwin; - } - return Platform.Unknown; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.IO; + using System.Runtime.InteropServices; + using System.Text.RegularExpressions; + + internal static class PlatformApis + { + private class DistroInfo + { + public string Id; + public string VersionId; + } + + private static readonly Lazy _platform = new Lazy(DetermineOSPlatform); + private static readonly Lazy _distroInfo = new Lazy(LoadDistroInfo); + + public static string GetOSName() + { + switch (GetOSPlatform()) + { + case Platform.Windows: + return "Windows"; + case Platform.Linux: + return GetDistroId() ?? "Linux"; + case Platform.Darwin: + return "Mac OS X"; + default: + return "Unknown"; + } + } + + public static string GetOSVersion() + { + try + { + switch (GetOSPlatform()) + { + case Platform.Windows: + return GetWindowsVersion(RuntimeInformation.OSDescription) ?? string.Empty; + case Platform.Linux: + return GetDistroVersionId() ?? string.Empty; + case Platform.Darwin: + return GetDarwinVersion() ?? string.Empty; + default: + return string.Empty; + } + } + catch + { + return string.Empty; + } + + } + + public static string GetWindowsVersion(string osDescipiton) + { + Regex regex = new Regex(@"([0-9]+\.*)+"); + Match match = regex.Match(osDescipiton); + return match.ToString(); + } + + private static string GetDarwinVersion() + { + Version version; + string kernelRelease = NativeMethods.Darwin.GetKernelRelease(); + if (!Version.TryParse(kernelRelease, out version) || version.Major < 5) + { + // 10.0 covers all versions prior to Darwin 5 + // Similarly, if the version is not a valid version number, but we have still detected that it is Darwin, we just assume + // it is OS X 10.0 + return "10.0"; + } + else + { + // Mac OS X 10.1 mapped to Darwin 5.x, and the mapping continues that way + // So just subtract 4 from the Darwin version. + // https://en.wikipedia.org/wiki/Darwin_%28operating_system%29 + return $"10.{version.Major - 4}"; + } + } + + public static Platform GetOSPlatform() + { + return _platform.Value; + } + + private static string GetDistroId() + { + return _distroInfo.Value?.Id; + } + + private static string GetDistroVersionId() + { + return _distroInfo.Value?.VersionId; + } + + private static DistroInfo LoadDistroInfo() + { + // Sample os-release file: + // NAME="Ubuntu" + // VERSION = "14.04.3 LTS, Trusty Tahr" + // ID = ubuntu + // ID_LIKE = debian + // PRETTY_NAME = "Ubuntu 14.04.3 LTS" + // VERSION_ID = "14.04" + // HOME_URL = "http://www.ubuntu.com/" + // SUPPORT_URL = "http://help.ubuntu.com/" + // BUG_REPORT_URL = "http://bugs.launchpad.net/ubuntu/" + // We use ID and VERSION_ID + + if (File.Exists("/etc/os-release")) + { + string[] lines = File.ReadAllLines("/etc/os-release"); + DistroInfo result = new DistroInfo(); + foreach (string line in lines) + { + if (line.StartsWith("ID=", StringComparison.Ordinal)) + { + result.Id = line.Substring(3).Trim('"', '\''); + } + else if (line.StartsWith("VERSION_ID=", StringComparison.Ordinal)) + { + result.VersionId = line.Substring(11).Trim('"', '\''); + } + } + return result; + } + + string osType = File.Exists("/proc/sys/kernel/ostype") + ? File.ReadAllText("/proc/sys/kernel/ostype") + : null; + + string osRelease = File.Exists("/proc/sys/kernel/osrelease") + ? File.ReadAllText("/proc/sys/kernel/osrelease") + : null; + + return new DistroInfo() {Id = osType, VersionId = osRelease}; + } + private static Platform DetermineOSPlatform() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return Platform.Windows; + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return Platform.Linux; + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return Platform.Darwin; + } + return Platform.Unknown; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PooledTimer.cs b/Microsoft.Azure.Cosmos/src/direct/PooledTimer.cs index 23bed4e5a4..032a0967f7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PooledTimer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PooledTimer.cs @@ -1,110 +1,110 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading.Tasks; - - internal sealed class PooledTimer - { - /// - /// keeps track of the timer was started, timeout time is calculated using this - /// - private long beginTicks; - - /// - /// TimeSpan to timeout - /// - private TimeSpan timeoutPeriod; - - /// - /// PooledTimer subscribes to the TimerPool to get notified when the timeout has expired - /// - private TimerPool timerPool; - - /// - /// tcs is set to completed state if the timeout occurs else its set to cancelled state - /// - private readonly TaskCompletionSource tcs; - private readonly Object memberLock; - private bool timerStarted = false; - - public PooledTimer(int timeout, TimerPool timerPool) - : this(TimeSpan.FromSeconds(timeout), timerPool) - { - } - - public PooledTimer(TimeSpan timeout, TimerPool timerPool) - { - this.timeoutPeriod = timeout; - this.tcs = new TaskCompletionSource(); - this.timerPool = timerPool; - this.memberLock = new Object(); - } - - /// - /// this is the expected ticks when this timer should be fired - /// - public long TimeoutTicks - { - get { return this.beginTicks + this.Timeout.Ticks; } - } - - /// - /// amount of time in seconds after which the timeout should be fired - /// - public TimeSpan Timeout - { - get { return timeoutPeriod; } - set { timeoutPeriod = value; } - } - - /// - /// Min supported Timeout for any timer. - /// - public TimeSpan MinSupportedTimeout - { - get { return this.timerPool.MinSupportedTimeout; } - } - - /// - /// Starts the timer for the timeout period specfied in constructor - /// - /// Returns the Task upon which you can await on until completion - public Task StartTimerAsync() - { - lock(this.memberLock) - { - if(this.timerStarted) - { - // use only once enforcement - throw new InvalidOperationException("Timer Already Started"); - } - - this.beginTicks = this.timerPool.SubscribeForTimeouts(this); - this.timerStarted = true; - return this.tcs.Task; - } - } - - /// - /// Cancels the timer by setting the tcs state to cancelled - /// - public bool CancelTimer() - { - return this.tcs.TrySetCanceled(); - } - - /// - /// Invoked by the TimerPool when the timeout period has elapsed - /// If the state is already cancelled, its a noop else it changes the state to completed - /// signalling a timeout on the TaskWaiter - /// - internal bool FireTimeout() - { - return this.tcs.TrySetResult(null); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading.Tasks; + + internal sealed class PooledTimer + { + /// + /// keeps track of the timer was started, timeout time is calculated using this + /// + private long beginTicks; + + /// + /// TimeSpan to timeout + /// + private TimeSpan timeoutPeriod; + + /// + /// PooledTimer subscribes to the TimerPool to get notified when the timeout has expired + /// + private TimerPool timerPool; + + /// + /// tcs is set to completed state if the timeout occurs else its set to cancelled state + /// + private readonly TaskCompletionSource tcs; + private readonly Object memberLock; + private bool timerStarted = false; + + public PooledTimer(int timeout, TimerPool timerPool) + : this(TimeSpan.FromSeconds(timeout), timerPool) + { + } + + public PooledTimer(TimeSpan timeout, TimerPool timerPool) + { + this.timeoutPeriod = timeout; + this.tcs = new TaskCompletionSource(); + this.timerPool = timerPool; + this.memberLock = new Object(); + } + + /// + /// this is the expected ticks when this timer should be fired + /// + public long TimeoutTicks + { + get { return this.beginTicks + this.Timeout.Ticks; } + } + + /// + /// amount of time in seconds after which the timeout should be fired + /// + public TimeSpan Timeout + { + get { return timeoutPeriod; } + set { timeoutPeriod = value; } + } + + /// + /// Min supported Timeout for any timer. + /// + public TimeSpan MinSupportedTimeout + { + get { return this.timerPool.MinSupportedTimeout; } + } + + /// + /// Starts the timer for the timeout period specfied in constructor + /// + /// Returns the Task upon which you can await on until completion + public Task StartTimerAsync() + { + lock(this.memberLock) + { + if(this.timerStarted) + { + // use only once enforcement + throw new InvalidOperationException("Timer Already Started"); + } + + this.beginTicks = this.timerPool.SubscribeForTimeouts(this); + this.timerStarted = true; + return this.tcs.Task; + } + } + + /// + /// Cancels the timer by setting the tcs state to cancelled + /// + public bool CancelTimer() + { + return this.tcs.TrySetCanceled(); + } + + /// + /// Invoked by the TimerPool when the timeout period has elapsed + /// If the state is already cancelled, its a noop else it changes the state to completed + /// signalling a timeout on the TaskWaiter + /// + internal bool FireTimeout() + { + return this.tcs.TrySetResult(null); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/PortReuseMode.cs b/Microsoft.Azure.Cosmos/src/direct/PortReuseMode.cs index 54c1be1df8..205b382e97 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PortReuseMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PortReuseMode.cs @@ -1,15 +1,15 @@ -namespace Microsoft.Azure.Documents -{ -#if COSMOSCLIENT - internal -#else - public -#endif - enum PortReuseMode - { - // Do not rename any of the values. - // They are used as app.config settings by external code. - ReuseUnicastPort = 0, - PrivatePortPool = 1, - } -} +namespace Microsoft.Azure.Documents +{ +#if COSMOSCLIENT + internal +#else + public +#endif + enum PortReuseMode + { + // Do not rename any of the values. + // They are used as app.config settings by external code. + ReuseUnicastPort = 0, + PrivatePortPool = 1, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs b/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs index 96273c0302..6a9c4be04f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs @@ -1,77 +1,77 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - using Newtonsoft.Json; - - [Serializable] - internal sealed class PreconditionFailedException : DocumentClientException - { - public PreconditionFailedException() - : this(RMResources.PreconditionFailed) - { - - } - - public PreconditionFailedException(string message, SubStatusCodes? substatusCode = null) - : this(message, (Exception)null, null, null, substatusCode) - { - - } - - public PreconditionFailedException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public PreconditionFailedException(Exception innerException) - : this(RMResources.PreconditionFailed, innerException, null) - { - - } - - public PreconditionFailedException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public PreconditionFailedException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.PreconditionFailed, requestUri) - { - SetDescription(); - } - - public PreconditionFailedException( - string message, - Exception innerException, - HttpResponseHeaders headers, - Uri requestUri = null, - SubStatusCodes? substatusCode = null) - : base(message, innerException, headers, HttpStatusCode.PreconditionFailed, requestUri, substatusCode) - { - SetDescription(); - } - -#if !NETSTANDARD16 - [JsonConstructor] - private PreconditionFailedException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.PreconditionFailed) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.PreconditionFailed; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + using Newtonsoft.Json; + + [Serializable] + internal class PreconditionFailedException : DocumentClientException + { + public PreconditionFailedException() + : this(RMResources.PreconditionFailed) + { + + } + + public PreconditionFailedException(string message, SubStatusCodes? substatusCode = null) + : this(message, (Exception)null, null, null, substatusCode) + { + + } + + public PreconditionFailedException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public PreconditionFailedException(Exception innerException) + : this(RMResources.PreconditionFailed, innerException, null) + { + + } + + public PreconditionFailedException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public PreconditionFailedException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.PreconditionFailed, requestUri) + { + SetDescription(); + } + + public PreconditionFailedException( + string message, + Exception innerException, + HttpResponseHeaders headers, + Uri requestUri = null, + SubStatusCodes? substatusCode = null) + : base(message, innerException, headers, HttpStatusCode.PreconditionFailed, requestUri, substatusCode) + { + SetDescription(); + } + +#if !NETSTANDARD16 + [JsonConstructor] + private PreconditionFailedException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.PreconditionFailed) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.PreconditionFailed; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PriorityLevel.cs b/Microsoft.Azure.Cosmos/src/direct/PriorityLevel.cs index e0a7967cf3..9e3bbe631f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PriorityLevel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PriorityLevel.cs @@ -1,12 +1,12 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum PriorityLevel - { - High = 1, - Low = 2, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum PriorityLevel + { + High = 1, + Low = 2, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Protocol.cs b/Microsoft.Azure.Cosmos/src/direct/Protocol.cs index d39c452f76..b1ea987c4d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Protocol.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Protocol.cs @@ -1,42 +1,42 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Specifies the protocol to be used by DocumentClient for communicating to the Azure Cosmos DB service. - /// - /// - /// - /// - /// - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum Protocol - { - /// - /// Specifies the HTTPS protocol. - /// - /// Default connectivity. - Https, - - /// - /// Specifies a custom binary protocol on TCP. - /// - /// Better for performance. - Tcp, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Specifies the protocol to be used by DocumentClient for communicating to the Azure Cosmos DB service. + /// + /// + /// + /// + /// + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum Protocol + { + /// + /// Specifies the HTTPS protocol. + /// + /// Default connectivity. + Https, + + /// + /// Specifies a custom binary protocol on TCP. + /// + /// Better for performance. + Tcp, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/QueryPlanGenerationMode.cs b/Microsoft.Azure.Cosmos/src/direct/QueryPlanGenerationMode.cs index 27c25dfba7..9cb1f47358 100644 --- a/Microsoft.Azure.Cosmos/src/direct/QueryPlanGenerationMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/QueryPlanGenerationMode.cs @@ -1,27 +1,27 @@ -namespace Microsoft.Azure.Documents -{ -#if COSMOSCLIENT - internal -#else - public -#endif - enum QueryPlanGenerationMode - { - /// - /// The SDK will auto detect the environment and availability of the ServiceInterop and - /// fallback to resolve the query plan as an HTTP request - /// - DefaultWindowsX64NativeWithFallbackToGateway = 0, - - /// - /// The SDK will only use the local ServiceInterop to generate the query plan. - /// The local ServiceInterop only works on Windows with application running in x64 - /// - WindowsX64NativeOnly = 1, - - /// - /// The SDK will always go to gateway to get the query plan. - /// - GatewayOnly = 2 - } -} +namespace Microsoft.Azure.Documents +{ +#if COSMOSCLIENT + internal +#else + public +#endif + enum QueryPlanGenerationMode + { + /// + /// The SDK will auto detect the environment and availability of the ServiceInterop and + /// fallback to resolve the query plan as an HTTP request + /// + DefaultWindowsX64NativeWithFallbackToGateway = 0, + + /// + /// The SDK will only use the local ServiceInterop to generate the query plan. + /// The local ServiceInterop only works on Windows with application running in x64 + /// + WindowsX64NativeOnly = 1, + + /// + /// The SDK will always go to gateway to get the query plan. + /// + GatewayOnly = 2 + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/QueryResult.cs b/Microsoft.Azure.Cosmos/src/direct/QueryResult.cs index 30d01dd4c5..c5877f3223 100644 --- a/Microsoft.Azure.Cosmos/src/direct/QueryResult.cs +++ b/Microsoft.Azure.Cosmos/src/direct/QueryResult.cs @@ -1,311 +1,311 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Dynamic; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Linq.Expressions; - using System.Reflection; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - //Each object record in Query response is materialized as QueryResult. - //This allows us to convert them to any type via dynamic cast. - internal sealed class QueryResult : IDynamicMetaObjectProvider - { - private readonly JContainer jObject; - private readonly string ownerFullName; - private JsonSerializer jsonSerializer; - - public QueryResult(JContainer jObject, string ownerFullName, JsonSerializer jsonSerializer) - { - this.jObject = jObject; - this.ownerFullName = ownerFullName; - this.jsonSerializer = jsonSerializer; - } - - public QueryResult(JContainer jObject, string ownerFullName, JsonSerializerSettings serializerSettings = null) - : this(jObject, ownerFullName, serializerSettings != null ? JsonSerializer.Create(serializerSettings) : JsonSerializer.Create()) - { - } - - /// - /// Gets the raw payload of this object. - /// To avoid double deserializations. - /// - public JContainer Payload - { - get - { - return this.jObject; - } - } - - public string OwnerFullName - { - get - { - return this.ownerFullName; - } - } - - public JsonSerializer JsonSerializer - { - get - { - return this.jsonSerializer; - } - } - - public override string ToString() - { - using (StringWriter writer = new StringWriter()) - { - jsonSerializer.Serialize(writer, jObject); - return writer.ToString(); - } - } - - // Summary: - // Returns the enumeration of all dynamic member names. - // - // Returns: - // A sequence that contains dynamic member names. - private IEnumerable GetDynamicMemberNames() - { - // Here we don't enumerate this.document.propertyBag, because in Document.FromObject, - // we merge the static defined property into propertyBag - List dynamicMembers = new List(); - - JObject jObjectLocal = this.jObject as JObject; - if (jObjectLocal != null) - { - foreach (KeyValuePair pair in jObjectLocal) - { - dynamicMembers.Add(pair.Key); - } - } - return dynamicMembers.ToList(); - } - - private object Convert(Type type) - { - object result; - if (type == typeof(object)) - { - return this; - } - - if (type == typeof(Database)) - { - result = new Database() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(DocumentCollection)) - { - result = new DocumentCollection() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(User)) - { - result = new User() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(UserDefinedType)) - { - result = new UserDefinedType() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Permission)) - { - result = new Permission() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Attachment)) - { - result = new Attachment() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Document)) - { - result = new Document() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Conflict)) - { - result = new Conflict() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Trigger)) - { - result = new Trigger() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Offer)) - { - result = OfferTypeResolver.ResponseOfferTypeResolver.Resolve(this.jObject as JObject); - } - else if (typeof(Document).IsAssignableFrom(type)) - { - result = (Resource)((this.jsonSerializer == null) ? - this.jObject.ToObject(type) : - this.jObject.ToObject(type, this.jsonSerializer)); - ((Document)result).propertyBag = this.jObject as JObject; - } - else if (typeof(Attachment).IsAssignableFrom(type)) - { - result = (Resource)this.jObject.ToObject(type); - ((Attachment)result).propertyBag = this.jObject as JObject; - } - else if (type == typeof(Schema)) - { - result = new Schema() { propertyBag = this.jObject as JObject }; - } - else if (type == typeof(Snapshot)) - { - result = new Snapshot() { propertyBag = this.jObject as JObject }; - } - else - { - // result - result = (this.jsonSerializer == null) ? - this.jObject.ToObject(type) : - this.jObject.ToObject(type, this.jsonSerializer); - } - - Resource resource = result as Resource; - if (resource != null) - { - resource.AltLink = PathsHelper.GeneratePathForNameBased(type, this.ownerFullName, resource.Id); - } - return result; - } - - //Property Getter/Setter for Expandable User property. - private object GetProperty( - string propertyName, Type returnType) - { - JToken token = this.jObject[propertyName]; - if (token != null) - { - return token.ToObject(returnType); - } - - //Any property not in JSON throw exception rather than returning null. - throw new DocumentClientException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.PropertyNotFound, - propertyName), null, null); - } - - private object SetProperty(string propertyName, object value) - { - if (value != null) - { - this.jObject[propertyName] = JToken.FromObject(value); - return true; - } - - return value; - } - - private T AsType() //To convert Document to any type. - { - return (T)this.Convert(typeof(T)); - } - - DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) - { - return new DocumentDynamicMetaObject(this, parameter); - } - - private class DocumentDynamicMetaObject : DynamicMetaObject - { - private readonly QueryResult queryResult; - - public DocumentDynamicMetaObject(QueryResult queryResult, Expression expression) - : base(expression, BindingRestrictions.Empty, queryResult) - { - this.queryResult = queryResult; - } - - public override DynamicMetaObject BindGetMember(GetMemberBinder binder) - { - //For all non-resource property, thunk the call to GetProperty method in Document. - string methodName = "GetProperty"; - - //Two parameters. - Expression[] parameters = new Expression[] - { - Expression.Constant(binder.Name), //PropertyName - Expression.Constant(binder.ReturnType) //Expected Return Type. - }; - - //Expression: this. - Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); - - //Expression: this.GetProperty(name, returnType); - Expression getPropertyExpression = Expression.Call( - thisExpression, - typeof(QueryResult).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - parameters); - - DynamicMetaObject getProperty = new DynamicMetaObject( - getPropertyExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return getProperty; - } - - public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) - { - //For all non-resource property, thunk the call to this.SetProperty method in Document. - string methodName = "SetProperty"; - - // setup the binding restrictions. - BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); - - //Two params, Name & Value. - Expression[] args = new Expression[2]; - args[0] = Expression.Constant(binder.Name); - args[1] = Expression.Convert(value.Expression, typeof(object)); - - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - // Setup the method call expression - Expression methodCall = Expression.Call(self, - typeof(QueryResult).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), - args); - - // Create a meta object to invoke Set later: - DynamicMetaObject setProperty = new DynamicMetaObject( - methodCall, - restrictions); - // return that dynamic object - return setProperty; - } - - public override DynamicMetaObject BindConvert(ConvertBinder binder) - { - // Setup the 'this' reference - Expression self = Expression.Convert(this.Expression, this.LimitType); - - MethodCallExpression methodExpression = Expression.Call( - self, - typeof(QueryResult).GetMethod("AsType", - BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); - - //Create a meta object to invoke AsType later. - DynamicMetaObject castOperator = new DynamicMetaObject( - methodExpression, - BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); - - return castOperator; - } - - public override IEnumerable GetDynamicMemberNames() - { - return this.queryResult.GetDynamicMemberNames(); - } - } - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Dynamic; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + //Each object record in Query response is materialized as QueryResult. + //This allows us to convert them to any type via dynamic cast. + internal sealed class QueryResult : IDynamicMetaObjectProvider + { + private readonly JContainer jObject; + private readonly string ownerFullName; + private JsonSerializer jsonSerializer; + + public QueryResult(JContainer jObject, string ownerFullName, JsonSerializer jsonSerializer) + { + this.jObject = jObject; + this.ownerFullName = ownerFullName; + this.jsonSerializer = jsonSerializer; + } + + public QueryResult(JContainer jObject, string ownerFullName, JsonSerializerSettings serializerSettings = null) + : this(jObject, ownerFullName, serializerSettings != null ? JsonSerializer.Create(serializerSettings) : JsonSerializer.Create()) + { + } + + /// + /// Gets the raw payload of this object. + /// To avoid double deserializations. + /// + public JContainer Payload + { + get + { + return this.jObject; + } + } + + public string OwnerFullName + { + get + { + return this.ownerFullName; + } + } + + public JsonSerializer JsonSerializer + { + get + { + return this.jsonSerializer; + } + } + + public override string ToString() + { + using (StringWriter writer = new StringWriter()) + { + jsonSerializer.Serialize(writer, jObject); + return writer.ToString(); + } + } + + // Summary: + // Returns the enumeration of all dynamic member names. + // + // Returns: + // A sequence that contains dynamic member names. + private IEnumerable GetDynamicMemberNames() + { + // Here we don't enumerate this.document.propertyBag, because in Document.FromObject, + // we merge the static defined property into propertyBag + List dynamicMembers = new List(); + + JObject jObjectLocal = this.jObject as JObject; + if (jObjectLocal != null) + { + foreach (KeyValuePair pair in jObjectLocal) + { + dynamicMembers.Add(pair.Key); + } + } + return dynamicMembers.ToList(); + } + + private object Convert(Type type) + { + object result; + if (type == typeof(object)) + { + return this; + } + + if (type == typeof(Database)) + { + result = new Database() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(DocumentCollection)) + { + result = new DocumentCollection() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(User)) + { + result = new User() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(UserDefinedType)) + { + result = new UserDefinedType() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Permission)) + { + result = new Permission() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Attachment)) + { + result = new Attachment() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Document)) + { + result = new Document() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Conflict)) + { + result = new Conflict() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Trigger)) + { + result = new Trigger() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Offer)) + { + result = OfferTypeResolver.ResponseOfferTypeResolver.Resolve(this.jObject as JObject); + } + else if (typeof(Document).IsAssignableFrom(type)) + { + result = (Resource)((this.jsonSerializer == null) ? + this.jObject.ToObject(type) : + this.jObject.ToObject(type, this.jsonSerializer)); + ((Document)result).propertyBag = this.jObject as JObject; + } + else if (typeof(Attachment).IsAssignableFrom(type)) + { + result = (Resource)this.jObject.ToObject(type); + ((Attachment)result).propertyBag = this.jObject as JObject; + } + else if (type == typeof(Schema)) + { + result = new Schema() { propertyBag = this.jObject as JObject }; + } + else if (type == typeof(Snapshot)) + { + result = new Snapshot() { propertyBag = this.jObject as JObject }; + } + else + { + // result + result = (this.jsonSerializer == null) ? + this.jObject.ToObject(type) : + this.jObject.ToObject(type, this.jsonSerializer); + } + + Resource resource = result as Resource; + if (resource != null) + { + resource.AltLink = PathsHelper.GeneratePathForNameBased(type, this.ownerFullName, resource.Id); + } + return result; + } + + //Property Getter/Setter for Expandable User property. + private object GetProperty( + string propertyName, Type returnType) + { + JToken token = this.jObject[propertyName]; + if (token != null) + { + return token.ToObject(returnType); + } + + //Any property not in JSON throw exception rather than returning null. + throw new DocumentClientException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.PropertyNotFound, + propertyName), null, null); + } + + private object SetProperty(string propertyName, object value) + { + if (value != null) + { + this.jObject[propertyName] = JToken.FromObject(value); + return true; + } + + return value; + } + + private T AsType() //To convert Document to any type. + { + return (T)this.Convert(typeof(T)); + } + + DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) + { + return new DocumentDynamicMetaObject(this, parameter); + } + + private class DocumentDynamicMetaObject : DynamicMetaObject + { + private readonly QueryResult queryResult; + + public DocumentDynamicMetaObject(QueryResult queryResult, Expression expression) + : base(expression, BindingRestrictions.Empty, queryResult) + { + this.queryResult = queryResult; + } + + public override DynamicMetaObject BindGetMember(GetMemberBinder binder) + { + //For all non-resource property, thunk the call to GetProperty method in Document. + string methodName = "GetProperty"; + + //Two parameters. + Expression[] parameters = new Expression[] + { + Expression.Constant(binder.Name), //PropertyName + Expression.Constant(binder.ReturnType) //Expected Return Type. + }; + + //Expression: this. + Expression thisExpression = Expression.Convert(this.Expression, this.LimitType); + + //Expression: this.GetProperty(name, returnType); + Expression getPropertyExpression = Expression.Call( + thisExpression, + typeof(QueryResult).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + parameters); + + DynamicMetaObject getProperty = new DynamicMetaObject( + getPropertyExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return getProperty; + } + + public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) + { + //For all non-resource property, thunk the call to this.SetProperty method in Document. + string methodName = "SetProperty"; + + // setup the binding restrictions. + BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(Expression, LimitType); + + //Two params, Name & Value. + Expression[] args = new Expression[2]; + args[0] = Expression.Constant(binder.Name); + args[1] = Expression.Convert(value.Expression, typeof(object)); + + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + // Setup the method call expression + Expression methodCall = Expression.Call(self, + typeof(QueryResult).GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance), + args); + + // Create a meta object to invoke Set later: + DynamicMetaObject setProperty = new DynamicMetaObject( + methodCall, + restrictions); + // return that dynamic object + return setProperty; + } + + public override DynamicMetaObject BindConvert(ConvertBinder binder) + { + // Setup the 'this' reference + Expression self = Expression.Convert(this.Expression, this.LimitType); + + MethodCallExpression methodExpression = Expression.Call( + self, + typeof(QueryResult).GetMethod("AsType", + BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(binder.Type)); + + //Create a meta object to invoke AsType later. + DynamicMetaObject castOperator = new DynamicMetaObject( + methodExpression, + BindingRestrictions.GetTypeRestriction(this.Expression, this.LimitType)); + + return castOperator; + } + + public override IEnumerable GetDynamicMemberNames() + { + return this.queryResult.GetDynamicMemberNames(); + } + } + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/QuorumReader.cs b/Microsoft.Azure.Cosmos/src/direct/QuorumReader.cs index 532a62d8cb..2a96228e29 100644 --- a/Microsoft.Azure.Cosmos/src/direct/QuorumReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/QuorumReader.cs @@ -1,859 +1,1006 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Linq; - using System.Runtime.ExceptionServices; - using System.Text; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - //================================================================================================================= - // Strong read logic: - //================================================================================================================= - // - // ------------------- PerformPrimaryRead------------------------------------------------------------- - // | ^ | - // [RetryOnSecondary] | | - // | [QuorumNotSelected] | - // \/ | \/ - // Start-------------------------->SecondaryQuorumRead-------------[QuorumMet]-------------------------------->Result - // | ^ - // [QuorumSelected] | - // | | - // \/ | - // PrimaryReadBarrier------------------------------------------------------------- - // - //================================================================================================================= - // BoundedStaleness quorum read logic: - //================================================================================================================= - // - // ------------------- PerformPrimaryRead------------------------------------------------------------- - // | ^ | - // [RetryOnSecondary] | | - // | [QuorumNotSelected] | - // \/ | \/ - // Start-------------------------->SecondaryQuorumRead-------------[QuorumMet]-------------------------------->Result - // | ^ - // [QuorumSelected] | - // | | - // | | - // --------------------------------------------------------------------------- - /// - /// QuorumReader wraps the client side quorum logic on top of the StoreReader - /// - internal sealed class QuorumReader - { - private const int maxNumberOfReadBarrierReadRetries = 6; - private const int maxNumberOfPrimaryReadRetries = 6; - private const int maxNumberOfReadQuorumRetries = 6; - private const int delayBetweenReadBarrierCallsInMs = 5; - - private const int maxBarrierRetriesForMultiRegion = 30; - private const int barrierRetryIntervalInMsForMultiRegion = 30; - - private const int maxShortBarrierRetriesForMultiRegion = 4; - private const int shortbarrierRetryIntervalInMsForMultiRegion = 10; - - private readonly StoreReader storeReader; - private readonly IServiceConfigurationReader serviceConfigReader; - private readonly IAuthorizationTokenProvider authorizationTokenProvider; - - public QuorumReader( - TransportClient transportClient, - AddressSelector addressSelector, - StoreReader storeReader, - IServiceConfigurationReader serviceConfigReader, - IAuthorizationTokenProvider authorizationTokenProvider) - { - this.storeReader = storeReader; - this.serviceConfigReader = serviceConfigReader; - this.authorizationTokenProvider = authorizationTokenProvider; - } - - public async Task ReadStrongAsync( - DocumentServiceRequest entity, - int readQuorumValue, - ReadMode readMode) - { - int readQuorumRetry = QuorumReader.maxNumberOfReadQuorumRetries; - bool shouldRetryOnSecondary = false; - bool hasPerformedReadFromPrimary = false; - do - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - shouldRetryOnSecondary = false; - using ReadQuorumResult secondaryQuorumReadResult = - await this.ReadQuorumAsync(entity, readQuorumValue, false, readMode); - switch (secondaryQuorumReadResult.QuorumResult) - { - case ReadQuorumResultKind.QuorumMet: - { - return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); - } - - case ReadQuorumResultKind.QuorumSelected: - { - DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync( - entity, - this.authorizationTokenProvider, - secondaryQuorumReadResult.SelectedLsn, - secondaryQuorumReadResult.GlobalCommittedSelectedLsn); - if (await this.WaitForReadBarrierAsync( - barrierRequest, - allowPrimary: true, - readQuorum: readQuorumValue, - readBarrierLsn: secondaryQuorumReadResult.SelectedLsn, - targetGlobalCommittedLSN: secondaryQuorumReadResult.GlobalCommittedSelectedLsn, - readMode: readMode)) - { - return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); - } - - DefaultTrace.TraceWarning( - "QuorumSelected: Could not converge on the LSN {0} GlobalCommittedLSN {3} ReadMode {4} after primary read barrier with read quorum {1} for strong read, Responses: {2}", - secondaryQuorumReadResult.SelectedLsn, - readQuorumValue, - secondaryQuorumReadResult, - secondaryQuorumReadResult.GlobalCommittedSelectedLsn, - readMode); - - entity.RequestContext.UpdateQuorumSelectedStoreResponse(secondaryQuorumReadResult.GetSelectedResponseAndSkipStoreResultDispose()); - entity.RequestContext.QuorumSelectedLSN = secondaryQuorumReadResult.SelectedLsn; - entity.RequestContext.GlobalCommittedSelectedLSN = secondaryQuorumReadResult.GlobalCommittedSelectedLsn; - } - - break; - - case ReadQuorumResultKind.QuorumNotSelected: - { - if (hasPerformedReadFromPrimary) - { - DefaultTrace.TraceWarning("QuorumNotSelected: Primary read already attempted. Quorum could not be selected after retrying on secondaries."); - throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); - } - - DefaultTrace.TraceWarning("QuorumNotSelected: Quorum could not be selected with read quorum of {0}", readQuorumValue); - using ReadPrimaryResult response = await this.ReadPrimaryAsync(entity, readQuorumValue, false); - - if (response.IsSuccessful && response.ShouldRetryOnSecondary) - { - Debug.Assert(false, "QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); - DefaultTrace.TraceCritical("PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); - } - else if (response.IsSuccessful) - { - DefaultTrace.TraceInformation("QuorumNotSelected: ReadPrimary successful"); - return response.GetResponseAndSkipStoreResultDispose(); - } - else if (response.ShouldRetryOnSecondary) - { - shouldRetryOnSecondary = true; - DefaultTrace.TraceWarning("QuorumNotSelected: ReadPrimary did not succeed. Will retry on secondary."); - hasPerformedReadFromPrimary = true; - } - else - { - DefaultTrace.TraceWarning("QuorumNotSelected: Could not get successful response from ReadPrimary"); - throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); - } - } - - break; - - default: - DefaultTrace.TraceCritical("Unknown ReadQuorum result {0}", secondaryQuorumReadResult.QuorumResult.ToString()); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - } while (--readQuorumRetry > 0 && shouldRetryOnSecondary); - - DefaultTrace.TraceWarning("Could not complete read quorum with read quorum value of {0}", readQuorumValue); - - throw new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ReadQuorumNotMet, - readQuorumValue), - SubStatusCodes.Server_ReadQuorumNotMet); - } - - public async Task ReadBoundedStalenessAsync( - DocumentServiceRequest entity, - int readQuorumValue) - { - int readQuorumRetry = QuorumReader.maxNumberOfReadQuorumRetries; - bool shouldRetryOnSecondary = false; - bool hasPerformedReadFromPrimary = false; - do - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - shouldRetryOnSecondary = false; - using ReadQuorumResult secondaryQuorumReadResult = await this.ReadQuorumAsync( - entity, readQuorumValue, false, ReadMode.BoundedStaleness); - switch (secondaryQuorumReadResult.QuorumResult) - { - case ReadQuorumResultKind.QuorumMet: - { - return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); - } - - // We do not perform the read barrier on Primary for BoundedStalenss as it has a - // potential to be always caught up in case of async replication - case ReadQuorumResultKind.QuorumSelected: - - DefaultTrace.TraceWarning( - "QuorumSelected: Could not converge on LSN {0} after barrier with QuorumValue {1} " + - "Will not perform barrier call on Primary for BoundedStaleness, Responses: {2}", - secondaryQuorumReadResult.SelectedLsn, readQuorumValue, secondaryQuorumReadResult); - - entity.RequestContext.UpdateQuorumSelectedStoreResponse(secondaryQuorumReadResult.GetSelectedResponseAndSkipStoreResultDispose()); - entity.RequestContext.QuorumSelectedLSN = secondaryQuorumReadResult.SelectedLsn; - break; - - case ReadQuorumResultKind.QuorumNotSelected: - { - if (hasPerformedReadFromPrimary) - { - DefaultTrace.TraceWarning("QuorumNotSelected: Primary read already attempted. Quorum could not be selected after " + - "retrying on secondaries."); - throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); - } - - DefaultTrace.TraceWarning("QuorumNotSelected: Quorum could not be selected with read quorum of {0}", readQuorumValue); - using ReadPrimaryResult response = await this.ReadPrimaryAsync(entity, readQuorumValue, false); - - if (response.IsSuccessful && response.ShouldRetryOnSecondary) - { - Debug.Assert(false, "QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); - DefaultTrace.TraceCritical("QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); - } - else if (response.IsSuccessful) - { - DefaultTrace.TraceInformation("QuorumNotSelected: ReadPrimary successful"); - return response.GetResponseAndSkipStoreResultDispose(); - } - else if (response.ShouldRetryOnSecondary) - { - shouldRetryOnSecondary = true; - DefaultTrace.TraceWarning("QuorumNotSelected: ReadPrimary did not succeed. Will retry on secondary."); - hasPerformedReadFromPrimary = true; - } - else - { - DefaultTrace.TraceWarning("QuorumNotSelected: Could not get successful response from ReadPrimary"); - throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); - } - } - break; - - default: - DefaultTrace.TraceCritical("Unknown ReadQuorum result {0}", secondaryQuorumReadResult.QuorumResult.ToString()); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - } while (--readQuorumRetry > 0 && shouldRetryOnSecondary); - - DefaultTrace.TraceError("Could not complete read quorum with read quorum value of {0}, RetryCount: {1}", - readQuorumValue, - QuorumReader.maxNumberOfReadQuorumRetries); - - throw new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ReadQuorumNotMet, - readQuorumValue), - SubStatusCodes.Server_ReadQuorumNotMet); - } - - private async Task ReadQuorumAsync( - DocumentServiceRequest entity, - int readQuorum, - bool includePrimary, - ReadMode readMode) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - long readLsn = -1; - long globalCommittedLSN = -1; - ReferenceCountedDisposable storeResult = null; - StoreResult[] responsesForLogging = null; - if (entity.RequestContext.QuorumSelectedStoreResponse == null) - { - using StoreResultList disposableResponseResult = new(await this.storeReader.ReadMultipleReplicaAsync( - entity, - includePrimary: includePrimary, - replicaCountToRead: readQuorum, - requiresValidLsn: true, - useSessionToken: false, - readMode: readMode)); - IList> responseResult = disposableResponseResult.Value; - - responsesForLogging = new StoreResult[responseResult.Count]; - for (int i = 0; i < responseResult.Count; i++) - { - responsesForLogging[i] = responseResult[i].Target; - } - - int responseCount = responseResult.Count(response => response.Target.IsValid); - if (responseCount < readQuorum) - { - return new ReadQuorumResult(entity.RequestContext.RequestChargeTracker, - ReadQuorumResultKind.QuorumNotSelected, -1, -1, null, responsesForLogging); - } - - //either request overrides consistency level with strong, or request does not override and account default consistency level is strong - bool isGlobalStrongReadCandidate = - (ReplicatedResourceClient.IsGlobalStrongEnabled() && this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong) && - (!entity.RequestContext.OriginalRequestConsistencyLevel.HasValue || entity.RequestContext.OriginalRequestConsistencyLevel == ConsistencyLevel.Strong); - - if (isGlobalStrongReadCandidate && readMode != ReadMode.Strong) - { - DefaultTrace.TraceError("Unexpected difference in consistency level isGlobalStrongReadCandidate {0}, ReadMode: {1}", - isGlobalStrongReadCandidate, readMode); - } - - if (this.IsQuorumMet( - responseResult, - readQuorum, - false, - isGlobalStrongReadCandidate, - out readLsn, - out globalCommittedLSN, - out storeResult)) - { - return new ReadQuorumResult( - entity.RequestContext.RequestChargeTracker, - ReadQuorumResultKind.QuorumMet, - readLsn, - globalCommittedLSN, - storeResult, - responsesForLogging); - } - - // at this point, if refresh were necessary, we would have refreshed it in ReadMultipleReplicaAsync - // so set to false here to avoid further refrehses for this request. - entity.RequestContext.ForceRefreshAddressCache = false; - } - else - { - readLsn = entity.RequestContext.QuorumSelectedLSN; - globalCommittedLSN = entity.RequestContext.GlobalCommittedSelectedLSN; - storeResult = entity.RequestContext.QuorumSelectedStoreResponse.TryAddReference(); - } - - // ReadBarrier required - DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(entity, this.authorizationTokenProvider, readLsn, globalCommittedLSN); - if (!await this.WaitForReadBarrierAsync(barrierRequest, false, readQuorum, readLsn, globalCommittedLSN, readMode)) - { - return new ReadQuorumResult( - entity.RequestContext.RequestChargeTracker, - ReadQuorumResultKind.QuorumSelected, - readLsn, - globalCommittedLSN, - storeResult, - responsesForLogging); - } - - return new ReadQuorumResult( - entity.RequestContext.RequestChargeTracker, - ReadQuorumResultKind.QuorumMet, - readLsn, - globalCommittedLSN, - storeResult, - responsesForLogging); - } - - /// - /// Read and get response from Primary - /// - /// - /// - /// - /// - private async Task ReadPrimaryAsync( - DocumentServiceRequest entity, - int readQuorum, - bool useSessionToken) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - // We would have already refreshed address before reaching here. Avoid performing here. - entity.RequestContext.ForceRefreshAddressCache = false; - using ReferenceCountedDisposable disposableStoreResult = await this.storeReader.ReadPrimaryAsync( - entity, - requiresValidLsn: true, - useSessionToken: useSessionToken); - StoreResult storeResult = disposableStoreResult.Target; - if (!storeResult.IsValid) - { - ExceptionDispatchInfo.Capture(storeResult.GetException()).Throw(); - } - - if (storeResult.CurrentReplicaSetSize <= 0 || storeResult.LSN < 0 || storeResult.QuorumAckedLSN < 0) - { - string message = string.Format(CultureInfo.CurrentCulture, - "Invalid value received from response header. CurrentReplicaSetSize {0}, StoreLSN {1}, QuorumAckedLSN {2}", - storeResult.CurrentReplicaSetSize, storeResult.LSN, storeResult.QuorumAckedLSN); - - // trace critical only if LSN / QuorumAckedLSN are not returned, since replica set size - // might not be returned if primary is still building the secondary replicas (during churn) - if (storeResult.CurrentReplicaSetSize <= 0) - { - DefaultTrace.TraceError(message); - } - else - { - DefaultTrace.TraceCritical(message); - } - - // throw exeption instead of returning inconsistent result. - throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); - } - - if (storeResult.CurrentReplicaSetSize > readQuorum) - { - DefaultTrace.TraceWarning( - "Unexpected response. Replica Set size is {0} which is greater than min value {1}", storeResult.CurrentReplicaSetSize, readQuorum); - return new ReadPrimaryResult(requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: true, response: null); - } - - // To accomodate for store latency, where an LSN may be acked by not persisted in the store, we compare the quorum acked LSN and store LSN. - // In case of sync replication, the store LSN will follow the quorum committed LSN - // In case of async replication (if enabled for bounded staleness), the store LSN can be ahead of the quorum committed LSN if the primary is able write to faster than secondary acks. - // We pick higher of the 2 LSN and wait for the other to reach that LSN. - if (storeResult.LSN != storeResult.QuorumAckedLSN) - { - DefaultTrace.TraceWarning("Store LSN {0} and quorum acked LSN {1} don't match", storeResult.LSN, storeResult.QuorumAckedLSN); - long higherLsn = storeResult.LSN > storeResult.QuorumAckedLSN ? storeResult.LSN : storeResult.QuorumAckedLSN; - - DocumentServiceRequest waitForLsnRequest = await BarrierRequestHelper.CreateAsync(entity, this.authorizationTokenProvider, higherLsn, null); - PrimaryReadOutcome primaryWaitForLsnResponse = await this.WaitForPrimaryLsnAsync(waitForLsnRequest, higherLsn, readQuorum); - if (primaryWaitForLsnResponse == PrimaryReadOutcome.QuorumNotMet) - { - return new ReadPrimaryResult( - requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: false, response: null); - } - else if (primaryWaitForLsnResponse == PrimaryReadOutcome.QuorumInconclusive) - { - return new ReadPrimaryResult( - requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: true, response: null); - } - - return new ReadPrimaryResult( - requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: true, shouldRetryOnSecondary: false, response: disposableStoreResult.TryAddReference()); - } - - return new ReadPrimaryResult( - requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: true, shouldRetryOnSecondary: false, response: disposableStoreResult.TryAddReference()); - } - - private async Task WaitForPrimaryLsnAsync( - DocumentServiceRequest barrierRequest, - long lsnToWaitFor, - int readQuorum) - { - int primaryRetries = QuorumReader.maxNumberOfPrimaryReadRetries; - - do // Loop for store and quorum LSN to match - { - barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - // We would have already refreshed address before reaching here. Avoid performing here. - barrierRequest.RequestContext.ForceRefreshAddressCache = false; - using ReferenceCountedDisposable storeResult = await this.storeReader.ReadPrimaryAsync( - barrierRequest, - requiresValidLsn: true, - useSessionToken: false); - if (!storeResult.Target.IsValid) - { - ExceptionDispatchInfo.Capture(storeResult.Target.GetException()).Throw(); - } - - if (storeResult.Target.CurrentReplicaSetSize > readQuorum) - { - DefaultTrace.TraceWarning( - "Unexpected response. Replica Set size is {0} which is greater than min value {1}", storeResult.Target.CurrentReplicaSetSize, readQuorum); - return PrimaryReadOutcome.QuorumInconclusive; - } - - if (storeResult.Target.LSN < lsnToWaitFor || storeResult.Target.QuorumAckedLSN < lsnToWaitFor) - { - DefaultTrace.TraceWarning( - "Store LSN {0} or quorum acked LSN {1} are lower than expected LSN {2}", storeResult.Target.LSN, storeResult.Target.QuorumAckedLSN, lsnToWaitFor); - await Task.Delay(QuorumReader.delayBetweenReadBarrierCallsInMs); - - continue; - } - - return PrimaryReadOutcome.QuorumMet; - - } while (--primaryRetries > 0); - - return PrimaryReadOutcome.QuorumNotMet; - } - - private async Task WaitForReadBarrierAsync( - DocumentServiceRequest barrierRequest, - bool allowPrimary, - int readQuorum, - long readBarrierLsn, - long targetGlobalCommittedLSN, - ReadMode readMode) - { - int readBarrierRetryCount = QuorumReader.maxNumberOfReadBarrierReadRetries; - int readBarrierRetryCountMultiRegion = QuorumReader.maxBarrierRetriesForMultiRegion; - - long maxGlobalCommittedLsn = 0; - - while (readBarrierRetryCount-- > 0) // Retry loop - { - barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - using StoreResultList disposableResponses = new(await this.storeReader.ReadMultipleReplicaAsync( - barrierRequest, - includePrimary: allowPrimary, - replicaCountToRead: readQuorum, - requiresValidLsn: true, - useSessionToken: false, - readMode: readMode, - checkMinLSN: false, - forceReadAll: true)); - IList> responses = disposableResponses.Value; - - long maxGlobalCommittedLsnInResponses = responses.Count > 0 ? responses.Max(response => response.Target.GlobalCommittedLSN) : 0; - if ((responses.Count(response => response.Target.LSN >= readBarrierLsn) >= readQuorum) && - (!(targetGlobalCommittedLSN > 0) || maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN)) - { - return true; - } - - maxGlobalCommittedLsn = maxGlobalCommittedLsn > maxGlobalCommittedLsnInResponses ? - maxGlobalCommittedLsn : maxGlobalCommittedLsnInResponses; - - //only refresh on first barrier call, set to false for subsequent attempts. - barrierRequest.RequestContext.ForceRefreshAddressCache = false; - - if (readBarrierRetryCount == 0) - { - DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - Last barrier for single-region requests. Responses: {0}", - string.Join("; ", responses)); - } - else - { - await Task.Delay(QuorumReader.delayBetweenReadBarrierCallsInMs); - } - } - - // we will go into global strong read barrier mode for global strong requests after regular barrier calls have been exhausted. - if (targetGlobalCommittedLSN > 0) - { - while (readBarrierRetryCountMultiRegion-- > 0) - { - barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - using StoreResultList disposableResponses = new(await this.storeReader.ReadMultipleReplicaAsync( - barrierRequest, - includePrimary: allowPrimary, - replicaCountToRead: readQuorum, - requiresValidLsn: true, - useSessionToken: false, - readMode: readMode, - checkMinLSN: false, - forceReadAll: true)); - IList> responses = disposableResponses.Value; - - long maxGlobalCommittedLsnInResponses = responses.Count > 0 ? responses.Max(response => response.Target.GlobalCommittedLSN) : 0; - if ((responses.Count(response => response.Target.LSN >= readBarrierLsn) >= readQuorum) && - maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN) - { - return true; - } - - maxGlobalCommittedLsn = maxGlobalCommittedLsn > maxGlobalCommittedLsnInResponses ? - maxGlobalCommittedLsn : maxGlobalCommittedLsnInResponses; - - //trace on last retry. - if (readBarrierRetryCountMultiRegion == 0) - { - DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - Last barrier for mult-region strong requests. ReadMode {1} Responses: {0}", - string.Join("; ", responses), readMode); - } - else - { - if ((QuorumReader.maxBarrierRetriesForMultiRegion - readBarrierRetryCountMultiRegion) > QuorumReader.maxShortBarrierRetriesForMultiRegion) - { - await Task.Delay(QuorumReader.barrierRetryIntervalInMsForMultiRegion); - } - else - { - await Task.Delay(QuorumReader.shortbarrierRetryIntervalInMsForMultiRegion); - } - } - } - } - - DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - TargetGlobalCommittedLsn: {0}, MaxGlobalCommittedLsn: {1} ReadMode: {2}.", - targetGlobalCommittedLSN, maxGlobalCommittedLsn, readMode); - return false; - } - - private bool IsQuorumMet( - IList> readResponses, - int readQuorum, - bool isPrimaryIncluded, - bool isGlobalStrongRead, - out long readLsn, - out long globalCommittedLSN, - out ReferenceCountedDisposable selectedResponse) - { - long maxLsn = 0; - long minLsn = long.MaxValue; - int replicaCountMaxLsn = 0; - IEnumerable> validReadResponses = readResponses.Where(response => response.Target.IsValid); - int validResponsesCount = validReadResponses.Count(); - - if (validResponsesCount == 0) - { - readLsn = 0; - globalCommittedLSN = -1; - selectedResponse = null; - - return false; - } - - long numberOfReadRegions = validReadResponses.Max(res => res.Target.NumberOfReadRegions); - bool checkForGlobalStrong = isGlobalStrongRead && numberOfReadRegions > 0; - - // Pick any R replicas in the response and check if they are at the same LSN - foreach (ReferenceCountedDisposable response in validReadResponses) - { - if (response.Target.LSN == maxLsn) - { - replicaCountMaxLsn++; - } - else if (response.Target.LSN > maxLsn) - { - replicaCountMaxLsn = 1; - maxLsn = response.Target.LSN; - } - - if (response.Target.LSN < minLsn) - { - minLsn = response.Target.LSN; - } - } - - selectedResponse = validReadResponses.Where(s => (s.Target.LSN == maxLsn) && (s.Target.StatusCode < StatusCodes.StartingErrorCode)).FirstOrDefault(); - if (selectedResponse == null) - { - selectedResponse = validReadResponses.First(s => s.Target.LSN == maxLsn); - } - - readLsn = selectedResponse.Target.ItemLSN == -1 ? - maxLsn : Math.Min(selectedResponse.Target.ItemLSN, maxLsn); - globalCommittedLSN = checkForGlobalStrong ? readLsn: -1; - - long maxGlobalCommittedLSN = validReadResponses.Max(res => res.Target.GlobalCommittedLSN); - - // quorum is met if one of the following conditions are satisfied: - // 1. readLsn is greater than zero - // AND the number of responses that have the same LSN as the selected response is greater than or equal to the read quorum - // AND if applicable, the max GlobalCommittedLSN of all responses is greater than or equal to the lsn of the selected response. - - // 2. if the request is a point-read request, - // AND there are more than one response in the readResponses - // AND the LSN of the returned resource of the selected response is less than or equal to the minimum lsn of the all the responses, - // AND if applicable, the LSN of the returned resource of the selected response is less than or equal to the minimum globalCommittedLsn of all the responses. - // This means that the returned resource is old enough to have been committed by at least all the received responses, - // which should be larger than or equal to the read quorum, which therefore means we have strong consistency. - bool isQuorumMet = false; - - if ((readLsn > 0 && replicaCountMaxLsn >= readQuorum) && - (!checkForGlobalStrong || maxGlobalCommittedLSN >= maxLsn)) - { - isQuorumMet = true; - } - - if(!isQuorumMet && validResponsesCount >= readQuorum && selectedResponse.Target.ItemLSN != -1 && - (minLsn != long.MaxValue && selectedResponse.Target.ItemLSN <= minLsn) && - (!checkForGlobalStrong || (selectedResponse.Target.ItemLSN <= maxGlobalCommittedLSN))) - { - isQuorumMet = true; - } - - if (!isQuorumMet) - { - DefaultTrace.TraceInformation("QuorumReader: MaxLSN {0} ReplicaCountMaxLSN {1} bCheckGlobalStrong {2} MaxGlobalCommittedLSN {3} NumberOfReadRegions {4} SelectedResponseItemLSN {5}", - maxLsn, replicaCountMaxLsn, checkForGlobalStrong, maxGlobalCommittedLSN, numberOfReadRegions, selectedResponse.Target.ItemLSN); - } - - // `selectedResponse` is an out parameter, so ensure it stays alive. - selectedResponse = selectedResponse.TryAddReference(); - return isQuorumMet; - } - - #region PrivateClasses - private enum ReadQuorumResultKind - { - QuorumMet, - QuorumSelected, - QuorumNotSelected - } - - private abstract class ReadResult : IDisposable - { - private readonly ReferenceCountedDisposable response; - private readonly RequestChargeTracker requestChargeTracker; - private protected bool skipStoreResultDispose; - - protected ReadResult(RequestChargeTracker requestChargeTracker, ReferenceCountedDisposable response) - { - this.requestChargeTracker = requestChargeTracker; - this.response = response; - } - - public void Dispose() - { - if (this.skipStoreResultDispose) - { - return; - } - - this.response?.Dispose(); - } - - public StoreResponse GetResponseAndSkipStoreResultDispose() - { - if (!this.IsValidResult()) - { - DefaultTrace.TraceCritical("GetResponse called for invalid result"); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - - this.skipStoreResultDispose = true; - return this.response.Target.ToResponse(requestChargeTracker); - } - - protected abstract bool IsValidResult(); - } - - private sealed class ReadQuorumResult : ReadResult, IDisposable - { - private ReferenceCountedDisposable selectedResponse; - - /// - /// Only for reporting purposes. - /// Responses in that list will be disposed by the time when they used for reporting. - /// ToString is expected to work on the disposed StoreResult. - /// - private StoreResult[] storeResponses; - - public ReadQuorumResult( - RequestChargeTracker requestChargeTracker, - ReadQuorumResultKind QuorumResult, - long selectedLsn, - long globalCommittedSelectedLsn, - ReferenceCountedDisposable selectedResponse, - StoreResult[] storeResponses) - : base(requestChargeTracker, selectedResponse) - { - this.QuorumResult = QuorumResult; - this.SelectedLsn = selectedLsn; - this.GlobalCommittedSelectedLsn = globalCommittedSelectedLsn; - this.selectedResponse = selectedResponse; - this.storeResponses = storeResponses; - } - - public ReadQuorumResultKind QuorumResult { get; private set; } - - public long SelectedLsn { get; private set; } - - public long GlobalCommittedSelectedLsn { get; private set; } - - /// - /// Response selected to lock on the LSN. This is the response with the highest - /// LSN - /// - public ReferenceCountedDisposable GetSelectedResponseAndSkipStoreResultDispose() - { - this.skipStoreResultDispose = true; - return this.selectedResponse.TryAddReference(); - } - - /// - /// Reports performed calls information. - /// - public override string ToString() - { - if (this.storeResponses == null) return String.Empty; - - // 1 record uses ~1600 chars on average. 2048 will be the eventual capacity builder will come to with extra array re-size operations. - StringBuilder stringBuilder = new(capacity: 2048 * this.storeResponses.Length); - foreach (StoreResult storeResult in this.storeResponses) - { - storeResult.AppendToBuilder(stringBuilder); - } - return stringBuilder.ToString(); - } - - protected override bool IsValidResult() - { - return this.QuorumResult == ReadQuorumResultKind.QuorumMet || this.QuorumResult == ReadQuorumResultKind.QuorumSelected; - } - } - - private sealed class ReadPrimaryResult : ReadResult - { - public ReadPrimaryResult(RequestChargeTracker requestChargeTracker, bool isSuccessful, bool shouldRetryOnSecondary, ReferenceCountedDisposable response) - : base(requestChargeTracker, response) - { - this.IsSuccessful = isSuccessful; - this.ShouldRetryOnSecondary = shouldRetryOnSecondary; - } - - public bool ShouldRetryOnSecondary { get; private set; } - - public bool IsSuccessful { get; private set; } - - protected override bool IsValidResult() - { - return IsSuccessful; - } - } - - private enum PrimaryReadOutcome - { - QuorumNotMet, // Primary LSN is not committed. - QuorumInconclusive, // Secondary replicas are available. Must read R secondary's to deduce current quorum. - QuorumMet, - } - - /// - /// Wrapper for a collection of StoreResult list with ability to call dispose on all the items but one selected to be the response. - /// - private struct StoreResultList : IDisposable - { - public StoreResultList(IList> collection) - { - this.Value = collection; - } - - public IList> Value { get; set; } - - public void Dispose() - { - if (this.Value.Count > 0) - { - foreach (ReferenceCountedDisposable storeResult in this.Value) - { - storeResult?.Dispose(); - } - } - } - } - #endregion - - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Linq; + using System.Runtime.ExceptionServices; + using System.Text; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + //================================================================================================================= + // Strong read logic: + //================================================================================================================= + // + // ------------------- PerformPrimaryRead------------------------------------------------------------- + // | ^ | + // [RetryOnSecondary] | | + // | [QuorumNotSelected] | + // \/ | \/ + // Start-------------------------->SecondaryQuorumRead-------------[QuorumMet]-------------------------------->Result + // | ^ + // [QuorumSelected] | + // | | + // \/ | + // PrimaryReadBarrier------------------------------------------------------------- + // + //================================================================================================================= + // BoundedStaleness quorum read logic: + //================================================================================================================= + // + // ------------------- PerformPrimaryRead------------------------------------------------------------- + // | ^ | + // [RetryOnSecondary] | | + // | [QuorumNotSelected] | + // \/ | \/ + // Start-------------------------->SecondaryQuorumRead-------------[QuorumMet]-------------------------------->Result + // | ^ + // [QuorumSelected] | + // | | + // | | + // --------------------------------------------------------------------------- + /// + /// QuorumReader wraps the client side quorum logic on top of the StoreReader + /// + internal sealed class QuorumReader + { + private const int maxNumberOfReadBarrierReadRetries = 6; + private const int maxNumberOfPrimaryReadRetries = 6; + private const int maxNumberOfReadQuorumRetries = 6; + private const int delayBetweenReadBarrierCallsInMs = 5; + + private const int maxBarrierRetriesForMultiRegion = 30; + private const int barrierRetryIntervalInMsForMultiRegion = 30; + + private const int maxShortBarrierRetriesForMultiRegion = 4; + private const int shortbarrierRetryIntervalInMsForMultiRegion = 10; + + private static readonly TimeSpan[] defaultBarrierRequestDelays = GetDefaultBarrierRequestDelays(); + private static readonly TimeSpan totalAllowedBarrierRequestDelay = GetTotalAllowedBarrierRequestDelay(); + + private readonly StoreReader storeReader; + private readonly IServiceConfigurationReader serviceConfigReader; + private readonly IAuthorizationTokenProvider authorizationTokenProvider; + + public QuorumReader( + TransportClient transportClient, + AddressSelector addressSelector, + StoreReader storeReader, + IServiceConfigurationReader serviceConfigReader, + IAuthorizationTokenProvider authorizationTokenProvider) + { + this.storeReader = storeReader; + this.serviceConfigReader = serviceConfigReader; + this.authorizationTokenProvider = authorizationTokenProvider; + } + + public async Task ReadStrongAsync( + DocumentServiceRequest entity, + int readQuorumValue, + ReadMode readMode) + { + int readQuorumRetry = QuorumReader.maxNumberOfReadQuorumRetries; + bool shouldRetryOnSecondary = false; + bool hasPerformedReadFromPrimary = false; + do + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + shouldRetryOnSecondary = false; + using ReadQuorumResult secondaryQuorumReadResult = + await this.ReadQuorumAsync(entity, readQuorumValue, false, readMode); + switch (secondaryQuorumReadResult.QuorumResult) + { + case ReadQuorumResultKind.QuorumMet: + { + return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); + } + + case ReadQuorumResultKind.QuorumSelected: + { + DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync( + entity, + this.authorizationTokenProvider, + secondaryQuorumReadResult.SelectedLsn, + secondaryQuorumReadResult.GlobalCommittedSelectedLsn); + if (await this.WaitForReadBarrierAsync( + barrierRequest, + allowPrimary: true, + readQuorum: readQuorumValue, + readBarrierLsn: secondaryQuorumReadResult.SelectedLsn, + targetGlobalCommittedLSN: secondaryQuorumReadResult.GlobalCommittedSelectedLsn, + readMode: readMode)) + { + return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); + } + + DefaultTrace.TraceWarning( + "QuorumSelected: Could not converge on the LSN {0} GlobalCommittedLSN {3} ReadMode {4} after primary read barrier with read quorum {1} for strong read, Responses: {2}", + secondaryQuorumReadResult.SelectedLsn, + readQuorumValue, + secondaryQuorumReadResult, + secondaryQuorumReadResult.GlobalCommittedSelectedLsn, + readMode); + + entity.RequestContext.UpdateQuorumSelectedStoreResponse(secondaryQuorumReadResult.GetSelectedResponseAndSkipStoreResultDispose()); + entity.RequestContext.QuorumSelectedLSN = secondaryQuorumReadResult.SelectedLsn; + entity.RequestContext.GlobalCommittedSelectedLSN = secondaryQuorumReadResult.GlobalCommittedSelectedLsn; + } + + break; + + case ReadQuorumResultKind.QuorumNotSelected: + { + if (hasPerformedReadFromPrimary) + { + DefaultTrace.TraceWarning("QuorumNotSelected: Primary read already attempted. Quorum could not be selected after retrying on secondaries."); + throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); + } + + DefaultTrace.TraceWarning("QuorumNotSelected: Quorum could not be selected with read quorum of {0}", readQuorumValue); + using ReadPrimaryResult response = await this.ReadPrimaryAsync(entity, readQuorumValue, false); + + if (response.IsSuccessful && response.ShouldRetryOnSecondary) + { + Debug.Assert(false, "QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); + DefaultTrace.TraceCritical("PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); + } + else if (response.IsSuccessful) + { + DefaultTrace.TraceInformation("QuorumNotSelected: ReadPrimary successful"); + return response.GetResponseAndSkipStoreResultDispose(); + } + else if (response.ShouldRetryOnSecondary) + { + shouldRetryOnSecondary = true; + DefaultTrace.TraceWarning("QuorumNotSelected: ReadPrimary did not succeed. Will retry on secondary."); + hasPerformedReadFromPrimary = true; + } + else + { + DefaultTrace.TraceWarning("QuorumNotSelected: Could not get successful response from ReadPrimary"); + throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); + } + } + + break; + + default: + DefaultTrace.TraceCritical("Unknown ReadQuorum result {0}", secondaryQuorumReadResult.QuorumResult.ToString()); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + } while (--readQuorumRetry > 0 && shouldRetryOnSecondary); + + DefaultTrace.TraceWarning("Could not complete read quorum with read quorum value of {0}", readQuorumValue); + + throw new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ReadQuorumNotMet, + readQuorumValue), + SubStatusCodes.Server_ReadQuorumNotMet); + } + + public async Task ReadBoundedStalenessAsync( + DocumentServiceRequest entity, + int readQuorumValue) + { + int readQuorumRetry = QuorumReader.maxNumberOfReadQuorumRetries; + bool shouldRetryOnSecondary = false; + bool hasPerformedReadFromPrimary = false; + do + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + shouldRetryOnSecondary = false; + using ReadQuorumResult secondaryQuorumReadResult = await this.ReadQuorumAsync( + entity, readQuorumValue, false, ReadMode.BoundedStaleness); + switch (secondaryQuorumReadResult.QuorumResult) + { + case ReadQuorumResultKind.QuorumMet: + { + return secondaryQuorumReadResult.GetResponseAndSkipStoreResultDispose(); + } + + // We do not perform the read barrier on Primary for BoundedStalenss as it has a + // potential to be always caught up in case of async replication + case ReadQuorumResultKind.QuorumSelected: + + DefaultTrace.TraceWarning( + "QuorumSelected: Could not converge on LSN {0} after barrier with QuorumValue {1} " + + "Will not perform barrier call on Primary for BoundedStaleness, Responses: {2}", + secondaryQuorumReadResult.SelectedLsn, readQuorumValue, secondaryQuorumReadResult); + + entity.RequestContext.UpdateQuorumSelectedStoreResponse(secondaryQuorumReadResult.GetSelectedResponseAndSkipStoreResultDispose()); + entity.RequestContext.QuorumSelectedLSN = secondaryQuorumReadResult.SelectedLsn; + break; + + case ReadQuorumResultKind.QuorumNotSelected: + { + if (hasPerformedReadFromPrimary) + { + DefaultTrace.TraceWarning("QuorumNotSelected: Primary read already attempted. Quorum could not be selected after " + + "retrying on secondaries."); + throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); + } + + DefaultTrace.TraceWarning("QuorumNotSelected: Quorum could not be selected with read quorum of {0}", readQuorumValue); + using ReadPrimaryResult response = await this.ReadPrimaryAsync(entity, readQuorumValue, false); + + if (response.IsSuccessful && response.ShouldRetryOnSecondary) + { + Debug.Assert(false, "QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); + DefaultTrace.TraceCritical("QuorumNotSelected: PrimaryResult has both Successful and ShouldRetryOnSecondary flags set"); + } + else if (response.IsSuccessful) + { + DefaultTrace.TraceInformation("QuorumNotSelected: ReadPrimary successful"); + return response.GetResponseAndSkipStoreResultDispose(); + } + else if (response.ShouldRetryOnSecondary) + { + shouldRetryOnSecondary = true; + DefaultTrace.TraceWarning("QuorumNotSelected: ReadPrimary did not succeed. Will retry on secondary."); + hasPerformedReadFromPrimary = true; + } + else + { + DefaultTrace.TraceWarning("QuorumNotSelected: Could not get successful response from ReadPrimary"); + throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); + } + } + break; + + default: + DefaultTrace.TraceCritical("Unknown ReadQuorum result {0}", secondaryQuorumReadResult.QuorumResult.ToString()); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + } while (--readQuorumRetry > 0 && shouldRetryOnSecondary); + + DefaultTrace.TraceError("Could not complete read quorum with read quorum value of {0}, RetryCount: {1}", + readQuorumValue, + QuorumReader.maxNumberOfReadQuorumRetries); + + throw new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ReadQuorumNotMet, + readQuorumValue), + SubStatusCodes.Server_ReadQuorumNotMet); + } + + internal static TimeSpan[] GetDefaultBarrierRequestDelays() + { + TimeSpan[] delays = new TimeSpan[maxNumberOfReadBarrierReadRetries + maxShortBarrierRetriesForMultiRegion + maxBarrierRetriesForMultiRegion]; + for (int i = 0; i < maxNumberOfReadBarrierReadRetries; i++) + { + delays[i] = TimeSpan.FromMilliseconds(delayBetweenReadBarrierCallsInMs); + } + + for (int i = maxNumberOfReadBarrierReadRetries + ; i < maxNumberOfReadBarrierReadRetries + maxShortBarrierRetriesForMultiRegion + ; i++) + { + delays[i] = TimeSpan.FromMilliseconds(shortbarrierRetryIntervalInMsForMultiRegion); + } + + for (int i = maxNumberOfReadBarrierReadRetries + maxShortBarrierRetriesForMultiRegion + ; i < maxNumberOfReadBarrierReadRetries + maxShortBarrierRetriesForMultiRegion + maxBarrierRetriesForMultiRegion + ; i++) + { + delays[i] = TimeSpan.FromMilliseconds(barrierRetryIntervalInMsForMultiRegion); + } + + return delays; + } + + internal static TimeSpan GetTotalAllowedBarrierRequestDelay() + { + TimeSpan totalAllowedDelay = TimeSpan.Zero; + foreach (TimeSpan current in GetDefaultBarrierRequestDelays()) + { + totalAllowedDelay += current; + } + + return totalAllowedDelay; + } + + private async Task ReadQuorumAsync( + DocumentServiceRequest entity, + int readQuorum, + bool includePrimary, + ReadMode readMode) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + long readLsn = -1; + long globalCommittedLSN = -1; + ReferenceCountedDisposable storeResult = null; + StoreResult[] responsesForLogging = null; + if (entity.RequestContext.QuorumSelectedStoreResponse == null) + { + using StoreResultList disposableResponseResult = new(await this.storeReader.ReadMultipleReplicaAsync( + entity, + includePrimary: includePrimary, + replicaCountToRead: readQuorum, + requiresValidLsn: true, + useSessionToken: false, + readMode: readMode)); + IList> responseResult = disposableResponseResult.Value; + + responsesForLogging = new StoreResult[responseResult.Count]; + for (int i = 0; i < responseResult.Count; i++) + { + responsesForLogging[i] = responseResult[i].Target; + } + + int responseCount = responseResult.Count(response => response.Target.IsValid); + if (responseCount < readQuorum) + { + return new ReadQuorumResult(entity.RequestContext.RequestChargeTracker, + ReadQuorumResultKind.QuorumNotSelected, -1, -1, null, responsesForLogging); + } + + //either request overrides consistency level with strong, or request does not override and account default consistency level is strong + bool isGlobalStrongReadCandidate = + (ReplicatedResourceClient.IsGlobalStrongEnabled() && this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong) && + (!entity.RequestContext.OriginalRequestConsistencyLevel.HasValue || entity.RequestContext.OriginalRequestConsistencyLevel == ConsistencyLevel.Strong); + + if (isGlobalStrongReadCandidate && readMode != ReadMode.Strong) + { + DefaultTrace.TraceError("Unexpected difference in consistency level isGlobalStrongReadCandidate {0}, ReadMode: {1}", + isGlobalStrongReadCandidate, readMode); + } + + if (this.IsQuorumMet( + responseResult, + readQuorum, + false, + isGlobalStrongReadCandidate, + out readLsn, + out globalCommittedLSN, + out storeResult)) + { + return new ReadQuorumResult( + entity.RequestContext.RequestChargeTracker, + ReadQuorumResultKind.QuorumMet, + readLsn, + globalCommittedLSN, + storeResult, + responsesForLogging); + } + + // at this point, if refresh were necessary, we would have refreshed it in ReadMultipleReplicaAsync + // so set to false here to avoid further refrehses for this request. + entity.RequestContext.ForceRefreshAddressCache = false; + } + else + { + readLsn = entity.RequestContext.QuorumSelectedLSN; + globalCommittedLSN = entity.RequestContext.GlobalCommittedSelectedLSN; + storeResult = entity.RequestContext.QuorumSelectedStoreResponse.TryAddReference(); + } + + // ReadBarrier required + DocumentServiceRequest barrierRequest = await BarrierRequestHelper.CreateAsync(entity, this.authorizationTokenProvider, readLsn, globalCommittedLSN); + if (!await this.WaitForReadBarrierAsync(barrierRequest, false, readQuorum, readLsn, globalCommittedLSN, readMode)) + { + return new ReadQuorumResult( + entity.RequestContext.RequestChargeTracker, + ReadQuorumResultKind.QuorumSelected, + readLsn, + globalCommittedLSN, + storeResult, + responsesForLogging); + } + + return new ReadQuorumResult( + entity.RequestContext.RequestChargeTracker, + ReadQuorumResultKind.QuorumMet, + readLsn, + globalCommittedLSN, + storeResult, + responsesForLogging); + } + + /// + /// Read and get response from Primary + /// + /// + /// + /// + /// + private async Task ReadPrimaryAsync( + DocumentServiceRequest entity, + int readQuorum, + bool useSessionToken) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + // We would have already refreshed address before reaching here. Avoid performing here. + entity.RequestContext.ForceRefreshAddressCache = false; + using ReferenceCountedDisposable disposableStoreResult = await this.storeReader.ReadPrimaryAsync( + entity, + requiresValidLsn: true, + useSessionToken: useSessionToken); + StoreResult storeResult = disposableStoreResult.Target; + if (!storeResult.IsValid) + { + ExceptionDispatchInfo.Capture(storeResult.GetException()).Throw(); + } + + if (storeResult.CurrentReplicaSetSize <= 0 || storeResult.LSN < 0 || storeResult.QuorumAckedLSN < 0) + { + string message = string.Format(CultureInfo.CurrentCulture, + "Invalid value received from response header. CurrentReplicaSetSize {0}, StoreLSN {1}, QuorumAckedLSN {2}", + storeResult.CurrentReplicaSetSize, storeResult.LSN, storeResult.QuorumAckedLSN); + + // trace critical only if LSN / QuorumAckedLSN are not returned, since replica set size + // might not be returned if primary is still building the secondary replicas (during churn) + if (storeResult.CurrentReplicaSetSize <= 0) + { + DefaultTrace.TraceError(message); + } + else + { + DefaultTrace.TraceCritical(message); + } + + // throw exeption instead of returning inconsistent result. + throw new GoneException(RMResources.ReadQuorumNotMet, SubStatusCodes.Server_ReadQuorumNotMet); + } + + if (storeResult.CurrentReplicaSetSize > readQuorum) + { + DefaultTrace.TraceWarning( + "Unexpected response. Replica Set size is {0} which is greater than min value {1}", storeResult.CurrentReplicaSetSize, readQuorum); + return new ReadPrimaryResult(requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: true, response: null); + } + + // To accomodate for store latency, where an LSN may be acked by not persisted in the store, we compare the quorum acked LSN and store LSN. + // In case of sync replication, the store LSN will follow the quorum committed LSN + // In case of async replication (if enabled for bounded staleness), the store LSN can be ahead of the quorum committed LSN if the primary is able write to faster than secondary acks. + // We pick higher of the 2 LSN and wait for the other to reach that LSN. + if (storeResult.LSN != storeResult.QuorumAckedLSN) + { + DefaultTrace.TraceWarning("Store LSN {0} and quorum acked LSN {1} don't match", storeResult.LSN, storeResult.QuorumAckedLSN); + long higherLsn = storeResult.LSN > storeResult.QuorumAckedLSN ? storeResult.LSN : storeResult.QuorumAckedLSN; + + DocumentServiceRequest waitForLsnRequest = await BarrierRequestHelper.CreateAsync(entity, this.authorizationTokenProvider, higherLsn, null); + PrimaryReadOutcome primaryWaitForLsnResponse = await this.WaitForPrimaryLsnAsync(waitForLsnRequest, higherLsn, readQuorum); + if (primaryWaitForLsnResponse == PrimaryReadOutcome.QuorumNotMet) + { + return new ReadPrimaryResult( + requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: false, response: null); + } + else if (primaryWaitForLsnResponse == PrimaryReadOutcome.QuorumInconclusive) + { + return new ReadPrimaryResult( + requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: false, shouldRetryOnSecondary: true, response: null); + } + + return new ReadPrimaryResult( + requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: true, shouldRetryOnSecondary: false, response: disposableStoreResult.TryAddReference()); + } + + return new ReadPrimaryResult( + requestChargeTracker: entity.RequestContext.RequestChargeTracker, isSuccessful: true, shouldRetryOnSecondary: false, response: disposableStoreResult.TryAddReference()); + } + + private async Task WaitForPrimaryLsnAsync( + DocumentServiceRequest barrierRequest, + long lsnToWaitFor, + int readQuorum) + { + int primaryRetries = QuorumReader.maxNumberOfPrimaryReadRetries; + + do // Loop for store and quorum LSN to match + { + barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + // We would have already refreshed address before reaching here. Avoid performing here. + barrierRequest.RequestContext.ForceRefreshAddressCache = false; + using ReferenceCountedDisposable storeResult = await this.storeReader.ReadPrimaryAsync( + barrierRequest, + requiresValidLsn: true, + useSessionToken: false); + if (!storeResult.Target.IsValid) + { + ExceptionDispatchInfo.Capture(storeResult.Target.GetException()).Throw(); + } + + if (storeResult.Target.CurrentReplicaSetSize > readQuorum) + { + DefaultTrace.TraceWarning( + "Unexpected response. Replica Set size is {0} which is greater than min value {1}", storeResult.Target.CurrentReplicaSetSize, readQuorum); + return PrimaryReadOutcome.QuorumInconclusive; + } + + if (storeResult.Target.LSN < lsnToWaitFor || storeResult.Target.QuorumAckedLSN < lsnToWaitFor) + { + DefaultTrace.TraceWarning( + "Store LSN {0} or quorum acked LSN {1} are lower than expected LSN {2}", storeResult.Target.LSN, storeResult.Target.QuorumAckedLSN, lsnToWaitFor); + await Task.Delay(QuorumReader.delayBetweenReadBarrierCallsInMs); + + continue; + } + + return PrimaryReadOutcome.QuorumMet; + + } while (--primaryRetries > 0); + + return PrimaryReadOutcome.QuorumNotMet; + } + + private Task WaitForReadBarrierAsync( + DocumentServiceRequest barrierRequest, + bool allowPrimary, + int readQuorum, + long readBarrierLsn, + long targetGlobalCommittedLSN, + ReadMode readMode) + { + if (BarrierRequestHelper.IsOldBarrierRequestHandlingEnabled) + { + return this.WaitForReadBarrierOldAsync(barrierRequest, allowPrimary, readQuorum, readBarrierLsn, targetGlobalCommittedLSN, readMode); + } + + return this.WaitForReadBarrierNewAsync(barrierRequest, allowPrimary, readQuorum, readBarrierLsn, targetGlobalCommittedLSN, readMode); + } + + // NOTE this is only temporarily kept to have a feature flag + // (Env variable 'AZURE_COSMOS_OLD_BARRIER_REQUESTS_HANDLING_ENABLED' allowing to fall back + // This old implementation will be removed (and the environment + // variable not been used anymore) after some bake time. + private async Task WaitForReadBarrierOldAsync( + DocumentServiceRequest barrierRequest, + bool allowPrimary, + int readQuorum, + long readBarrierLsn, + long targetGlobalCommittedLSN, + ReadMode readMode) + { + int readBarrierRetryCount = QuorumReader.maxNumberOfReadBarrierReadRetries; + int readBarrierRetryCountMultiRegion = QuorumReader.maxBarrierRetriesForMultiRegion; + + long maxGlobalCommittedLsn = 0; + + while (readBarrierRetryCount-- > 0) // Retry loop + { + barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + using StoreResultList disposableResponses = new(await this.storeReader.ReadMultipleReplicaAsync( + barrierRequest, + includePrimary: allowPrimary, + replicaCountToRead: readQuorum, + requiresValidLsn: true, + useSessionToken: false, + readMode: readMode, + checkMinLSN: false, + forceReadAll: true)); + IList> responses = disposableResponses.Value; + + long maxGlobalCommittedLsnInResponses = responses.Count > 0 ? responses.Max(response => response.Target.GlobalCommittedLSN) : 0; + if ((responses.Count(response => response.Target.LSN >= readBarrierLsn) >= readQuorum) && + (!(targetGlobalCommittedLSN > 0) || maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN)) + { + return true; + } + + maxGlobalCommittedLsn = maxGlobalCommittedLsn > maxGlobalCommittedLsnInResponses ? + maxGlobalCommittedLsn : maxGlobalCommittedLsnInResponses; + + //only refresh on first barrier call, set to false for subsequent attempts. + barrierRequest.RequestContext.ForceRefreshAddressCache = false; + + if (readBarrierRetryCount == 0) + { + DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - Last barrier for single-region requests. Responses: {0}", + string.Join("; ", responses.Select(r => r.Target))); + } + else + { + await Task.Delay(QuorumReader.delayBetweenReadBarrierCallsInMs); + } + } + + // we will go into global strong read barrier mode for global strong requests after regular barrier calls have been exhausted. + if (targetGlobalCommittedLSN > 0) + { + while (readBarrierRetryCountMultiRegion-- > 0) + { + barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + using StoreResultList disposableResponses = new(await this.storeReader.ReadMultipleReplicaAsync( + barrierRequest, + includePrimary: allowPrimary, + replicaCountToRead: readQuorum, + requiresValidLsn: true, + useSessionToken: false, + readMode: readMode, + checkMinLSN: false, + forceReadAll: true)); + IList> responses = disposableResponses.Value; + + long maxGlobalCommittedLsnInResponses = responses.Count > 0 ? responses.Max(response => response.Target.GlobalCommittedLSN) : 0; + if ((responses.Count(response => response.Target.LSN >= readBarrierLsn) >= readQuorum) && + maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN) + { + return true; + } + + maxGlobalCommittedLsn = maxGlobalCommittedLsn > maxGlobalCommittedLsnInResponses ? + maxGlobalCommittedLsn : maxGlobalCommittedLsnInResponses; + + //trace on last retry. + if (readBarrierRetryCountMultiRegion == 0) + { + DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - Last barrier for mult-region strong requests. ReadMode {1} Responses: {0}", + string.Join("; ", responses.Select(r => r.Target)), readMode); + } + else + { + if ((QuorumReader.maxBarrierRetriesForMultiRegion - readBarrierRetryCountMultiRegion) > QuorumReader.maxShortBarrierRetriesForMultiRegion) + { + await Task.Delay(QuorumReader.barrierRetryIntervalInMsForMultiRegion); + } + else + { + await Task.Delay(QuorumReader.shortbarrierRetryIntervalInMsForMultiRegion); + } + } + } + } + + DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - TargetGlobalCommittedLsn: {0}, MaxGlobalCommittedLsn: {1} ReadMode: {2}.", + targetGlobalCommittedLSN, maxGlobalCommittedLsn, readMode); + return false; + } + + private async Task WaitForReadBarrierNewAsync( + DocumentServiceRequest barrierRequest, + bool allowPrimary, + int readQuorum, + long readBarrierLsn, + long targetGlobalCommittedLSN, + ReadMode readMode) + { + TimeSpan remainingDelay = totalAllowedBarrierRequestDelay; + + long maxGlobalCommittedLsn = 0; + bool hasConvergedOnLSN = false; + int readBarrierRetryCount = 0; + while(readBarrierRetryCount < defaultBarrierRequestDelays.Length && remainingDelay >= TimeSpan.Zero) // Retry loop + { + barrierRequest.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + ValueStopwatch barrierRequestStopWatch = ValueStopwatch.StartNew(); + using StoreResultList disposableResponses = new(await this.storeReader.ReadMultipleReplicaAsync( + barrierRequest, + includePrimary: allowPrimary, + replicaCountToRead: hasConvergedOnLSN ? 1 : readQuorum, // for GCLSN a single replica is sufficient + requiresValidLsn: !hasConvergedOnLSN, + useSessionToken: false, + readMode: readMode, + checkMinLSN: false, + forceReadAll: !hasConvergedOnLSN)); // for GCLSN a single replica is sufficient - and requests should be issued sequentially + barrierRequestStopWatch.Stop(); + IList> responses = disposableResponses.Value; + TimeSpan previousBarrierRequestLatency = barrierRequestStopWatch.Elapsed; + + int readBarrierLsnReachedCount = 0; + long maxGlobalCommittedLsnInResponses = 0; + foreach(ReferenceCountedDisposable response in responses) + { + maxGlobalCommittedLsnInResponses = Math.Max(maxGlobalCommittedLsnInResponses, response.Target.GlobalCommittedLSN); + if (!hasConvergedOnLSN && response.Target.LSN >= readBarrierLsn) + { + readBarrierLsnReachedCount++; + } + } + + if (!hasConvergedOnLSN && readBarrierLsnReachedCount >= readQuorum) + { + hasConvergedOnLSN = true; + } + + if (hasConvergedOnLSN && + (targetGlobalCommittedLSN <= 0 || maxGlobalCommittedLsnInResponses >= targetGlobalCommittedLSN)) + { + return true; + } + + maxGlobalCommittedLsn = Math.Max(maxGlobalCommittedLsn, maxGlobalCommittedLsnInResponses); + + //only refresh on first barrier call, set to false for subsequent attempts. + barrierRequest.RequestContext.ForceRefreshAddressCache = false; + + bool shouldDelay = BarrierRequestHelper.ShouldDelayBetweenHeadRequests( + previousBarrierRequestLatency, + responses, + defaultBarrierRequestDelays[readBarrierRetryCount], + out TimeSpan maxDelay); + + readBarrierRetryCount++; + if (readBarrierRetryCount >= defaultBarrierRequestDelays.Length || remainingDelay <= TimeSpan.Zero) + { + //trace on last retry. + DefaultTrace.TraceInformation( + "QuorumReader: WaitForReadBarrierAsync - Last barrier request. ReadMode: {0}, " + + "HasLSNConverged: {1}, BarrierRequestRetryCount: {2}, Responses: {3}", + readMode, + hasConvergedOnLSN, + readBarrierRetryCount, + string.Join("; ", responses.Select(r => r.Target))); + } + else if (shouldDelay) + { + TimeSpan delay =maxDelay < remainingDelay ? maxDelay : remainingDelay; + await Task.Delay(delay); + remainingDelay -= delay; + } + } + + DefaultTrace.TraceInformation("QuorumReader: WaitForReadBarrierAsync - TargetGlobalCommittedLsn: {0}, MaxGlobalCommittedLsn: {1} ReadMode: {2}, HasLSNConverged:{3}.", + targetGlobalCommittedLSN, maxGlobalCommittedLsn, readMode, hasConvergedOnLSN); + return false; + } + + private bool IsQuorumMet( + IList> readResponses, + int readQuorum, + bool isPrimaryIncluded, + bool isGlobalStrongRead, + out long readLsn, + out long globalCommittedLSN, + out ReferenceCountedDisposable selectedResponse) + { + long maxLsn = 0; + long minLsn = long.MaxValue; + int replicaCountMaxLsn = 0; + IEnumerable> validReadResponses = readResponses.Where(response => response.Target.IsValid); + int validResponsesCount = validReadResponses.Count(); + + if (validResponsesCount == 0) + { + readLsn = 0; + globalCommittedLSN = -1; + selectedResponse = null; + + return false; + } + + long numberOfReadRegions = validReadResponses.Max(res => res.Target.NumberOfReadRegions); + bool checkForGlobalStrong = isGlobalStrongRead && numberOfReadRegions > 0; + + // Pick any R replicas in the response and check if they are at the same LSN + foreach (ReferenceCountedDisposable response in validReadResponses) + { + if (response.Target.LSN == maxLsn) + { + replicaCountMaxLsn++; + } + else if (response.Target.LSN > maxLsn) + { + replicaCountMaxLsn = 1; + maxLsn = response.Target.LSN; + } + + if (response.Target.LSN < minLsn) + { + minLsn = response.Target.LSN; + } + } + + selectedResponse = validReadResponses.Where(s => (s.Target.LSN == maxLsn) && (s.Target.StatusCode < StatusCodes.StartingErrorCode)).FirstOrDefault(); + if (selectedResponse == null) + { + selectedResponse = validReadResponses.First(s => s.Target.LSN == maxLsn); + } + + readLsn = selectedResponse.Target.ItemLSN == -1 ? + maxLsn : Math.Min(selectedResponse.Target.ItemLSN, maxLsn); + globalCommittedLSN = checkForGlobalStrong ? readLsn: -1; + + long maxGlobalCommittedLSN = validReadResponses.Max(res => res.Target.GlobalCommittedLSN); + + // quorum is met if one of the following conditions are satisfied: + // 1. readLsn is greater than zero + // AND the number of responses that have the same LSN as the selected response is greater than or equal to the read quorum + // AND if applicable, the max GlobalCommittedLSN of all responses is greater than or equal to the lsn of the selected response. + + // 2. if the request is a point-read request, + // AND there are more than one response in the readResponses + // AND the LSN of the returned resource of the selected response is less than or equal to the minimum lsn of the all the responses, + // AND if applicable, the LSN of the returned resource of the selected response is less than or equal to the minimum globalCommittedLsn of all the responses. + // This means that the returned resource is old enough to have been committed by at least all the received responses, + // which should be larger than or equal to the read quorum, which therefore means we have strong consistency. + bool isQuorumMet = false; + + if ((readLsn > 0 && replicaCountMaxLsn >= readQuorum) && + (!checkForGlobalStrong || maxGlobalCommittedLSN >= maxLsn)) + { + isQuorumMet = true; + } + + if(!isQuorumMet && validResponsesCount >= readQuorum && selectedResponse.Target.ItemLSN != -1 && + (minLsn != long.MaxValue && selectedResponse.Target.ItemLSN <= minLsn) && + (!checkForGlobalStrong || (selectedResponse.Target.ItemLSN <= maxGlobalCommittedLSN))) + { + isQuorumMet = true; + } + + if (!isQuorumMet) + { + DefaultTrace.TraceInformation("QuorumReader: MaxLSN {0} ReplicaCountMaxLSN {1} bCheckGlobalStrong {2} MaxGlobalCommittedLSN {3} NumberOfReadRegions {4} SelectedResponseItemLSN {5}", + maxLsn, replicaCountMaxLsn, checkForGlobalStrong, maxGlobalCommittedLSN, numberOfReadRegions, selectedResponse.Target.ItemLSN); + } + + // `selectedResponse` is an out parameter, so ensure it stays alive. + selectedResponse = selectedResponse.TryAddReference(); + return isQuorumMet; + } + + #region PrivateClasses + private enum ReadQuorumResultKind + { + QuorumMet, + QuorumSelected, + QuorumNotSelected + } + + private abstract class ReadResult : IDisposable + { + private readonly ReferenceCountedDisposable response; + private readonly RequestChargeTracker requestChargeTracker; + private protected bool skipStoreResultDispose; + + protected ReadResult(RequestChargeTracker requestChargeTracker, ReferenceCountedDisposable response) + { + this.requestChargeTracker = requestChargeTracker; + this.response = response; + } + + public void Dispose() + { + if (this.skipStoreResultDispose) + { + return; + } + + this.response?.Dispose(); + } + + public StoreResponse GetResponseAndSkipStoreResultDispose() + { + if (!this.IsValidResult()) + { + DefaultTrace.TraceCritical("GetResponse called for invalid result"); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + + this.skipStoreResultDispose = true; + return this.response.Target.ToResponse(requestChargeTracker); + } + + protected abstract bool IsValidResult(); + } + + private sealed class ReadQuorumResult : ReadResult, IDisposable + { + private readonly ReferenceCountedDisposable selectedResponse; + + /// + /// Only for reporting purposes. + /// Responses in that list will be disposed by the time when they used for reporting. + /// ToString is expected to work on the disposed StoreResult. + /// + private readonly StoreResult[] storeResponses; + + public ReadQuorumResult( + RequestChargeTracker requestChargeTracker, + ReadQuorumResultKind QuorumResult, + long selectedLsn, + long globalCommittedSelectedLsn, + ReferenceCountedDisposable selectedResponse, + StoreResult[] storeResponses) + : base(requestChargeTracker, selectedResponse) + { + this.QuorumResult = QuorumResult; + this.SelectedLsn = selectedLsn; + this.GlobalCommittedSelectedLsn = globalCommittedSelectedLsn; + this.selectedResponse = selectedResponse; + this.storeResponses = storeResponses; + } + + public ReadQuorumResultKind QuorumResult { get; private set; } + + public long SelectedLsn { get; private set; } + + public long GlobalCommittedSelectedLsn { get; private set; } + + /// + /// Response selected to lock on the LSN. This is the response with the highest + /// LSN + /// + public ReferenceCountedDisposable GetSelectedResponseAndSkipStoreResultDispose() + { + this.skipStoreResultDispose = true; + return this.selectedResponse.TryAddReference(); + } + + /// + /// Reports performed calls information. + /// + public override string ToString() + { + if (this.storeResponses == null) return String.Empty; + + // 1 record uses ~1600 chars on average. 2048 will be the eventual capacity builder will come to with extra array re-size operations. + StringBuilder stringBuilder = new(capacity: 2048 * this.storeResponses.Length); + foreach (StoreResult storeResult in this.storeResponses) + { + storeResult.AppendToBuilder(stringBuilder); + } + return stringBuilder.ToString(); + } + + protected override bool IsValidResult() + { + return this.QuorumResult == ReadQuorumResultKind.QuorumMet || this.QuorumResult == ReadQuorumResultKind.QuorumSelected; + } + } + + private sealed class ReadPrimaryResult : ReadResult + { + public ReadPrimaryResult(RequestChargeTracker requestChargeTracker, bool isSuccessful, bool shouldRetryOnSecondary, ReferenceCountedDisposable response) + : base(requestChargeTracker, response) + { + this.IsSuccessful = isSuccessful; + this.ShouldRetryOnSecondary = shouldRetryOnSecondary; + } + + public bool ShouldRetryOnSecondary { get; private set; } + + public bool IsSuccessful { get; private set; } + + protected override bool IsValidResult() + { + return IsSuccessful; + } + } + + private enum PrimaryReadOutcome + { + QuorumNotMet, // Primary LSN is not committed. + QuorumInconclusive, // Secondary replicas are available. Must read R secondary's to deduce current quorum. + QuorumMet, + } + + /// + /// Wrapper for a collection of StoreResult list with ability to call dispose on all the items but one selected to be the response. + /// + private struct StoreResultList : IDisposable + { + public StoreResultList(IList> collection) + { + this.Value = collection; + } + + public IList> Value { get; set; } + + public void Dispose() + { + if (this.Value.Count > 0) + { + foreach (ReferenceCountedDisposable storeResult in this.Value) + { + storeResult?.Dispose(); + } + } + } + } + #endregion + + } + } diff --git a/Microsoft.Azure.Cosmos/src/direct/Range.cs b/Microsoft.Azure.Cosmos/src/direct/Range.cs index 128a906b7e..1e9fcf0062 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Range.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Range.cs @@ -1,214 +1,214 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using Newtonsoft.Json; - - [JsonObject(MemberSerialization.OptIn)] - internal sealed class Range where T: IComparable - { - public static readonly IComparer TComparer = typeof(T) == typeof(string) ? (IComparer)StringComparer.Ordinal : Comparer.Default; - - [JsonConstructor] - public Range(T min, T max, bool isMinInclusive, bool isMaxInclusive) - { - if (min == null) - { - throw new ArgumentNullException("min"); - } - - if (max == null) - { - throw new ArgumentNullException("max"); - } - - this.Min = min; - this.Max = max; - this.IsMinInclusive = isMinInclusive; - this.IsMaxInclusive = isMaxInclusive; - } - - public static Range GetPointRange(T value) - { - return new Range(value, value, true, true); - } - - [JsonProperty("min")] - public T Min { get; private set; } - - [JsonProperty("max")] - public T Max { get; private set; } - - [JsonProperty("isMinInclusive")] - public bool IsMinInclusive { get; private set; } - - [JsonProperty("isMaxInclusive")] - public bool IsMaxInclusive { get; private set; } - - public bool IsSingleValue - { - get - { - return this.IsMinInclusive && this.IsMaxInclusive && TComparer.Compare(this.Min, this.Max) == 0; - } - } - - public bool IsEmpty - { - get - { - return (TComparer.Compare(this.Min, this.Max) == 0) && !(this.IsMinInclusive && this.IsMaxInclusive); - } - } - - public static Range GetEmptyRange(T value) - { - return new Range( - value, - value, - true, - false); - } - - public bool Contains(T value) - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - int minToValueRelation = TComparer.Compare(this.Min, value); - int maxToValueRelation = TComparer.Compare(this.Max, value); - - return ((this.IsMinInclusive && minToValueRelation <= 0) || (!this.IsMinInclusive && minToValueRelation < 0)) - && - ((this.IsMaxInclusive && maxToValueRelation >= 0) || (!this.IsMaxInclusive && maxToValueRelation > 0)); - } - - public static bool CheckOverlapping(Range range1, Range range2) - { - if (range1 == null || range2 == null || range1.IsEmpty || range2.IsEmpty) - { - return false; - } - - int cmp1 = TComparer.Compare(range1.Min, range2.Max); - int cmp2 = TComparer.Compare(range2.Min, range1.Max); - - if (cmp1 <= 0 && cmp2 <= 0) - { - if ((cmp1 == 0 && !(range1.IsMinInclusive && range2.IsMaxInclusive)) - || (cmp2 == 0 && !(range2.IsMinInclusive && range1.IsMaxInclusive))) - { - return false; - } - - return true; - } - - return false; - } - - public override bool Equals(object obj) - { - return this.Equals(obj as Range); - } - - public override int GetHashCode() - { - unchecked - { - int hash = 0; - hash = (hash * 397) ^ this.Min.GetHashCode(); - hash = (hash * 397) ^ this.Max.GetHashCode(); - hash = (hash * 397) ^ Convert.ToInt32(this.IsMinInclusive); - hash = (hash * 397) ^ Convert.ToInt32(this.IsMaxInclusive); - return hash; - } - } - - public bool Equals(Range other) - { - if (other == null) - { - return false; - } - - return TComparer.Compare(this.Min, other.Min) == 0 - && TComparer.Compare(this.Max, other.Max) == 0 - && this.IsMinInclusive == other.IsMinInclusive - && this.IsMaxInclusive == other.IsMaxInclusive; - } - - public override string ToString() - { - return string.Format(CultureInfo.InvariantCulture, "{0}{1},{2}{3}", this.IsMinInclusive ? "[" : "(", this.Min, this.Max, this.IsMaxInclusive ? "]" : ")"); - } - - public class MinComparer : IComparer> - { - public static readonly MinComparer Instance = new MinComparer(TComparer); - - private readonly IComparer boundsComparer; - - private MinComparer(IComparer boundsComparer) - { - this.boundsComparer = boundsComparer; - } - - public int Compare(Range left, Range right) - { - int result = this.boundsComparer.Compare(left.Min, right.Min); - if (result != 0 || left.IsMinInclusive == right.IsMinInclusive) - { - return result; - } - - if (left.IsMinInclusive) - { - return -1; - } - else - { - return 1; - } - } - } - - public class MaxComparer : IComparer> - { - public static readonly MaxComparer Instance = new MaxComparer(TComparer); - - private readonly IComparer boundsComparer; - - private MaxComparer(IComparer boundsComparer) - { - this.boundsComparer = boundsComparer; - } - - public int Compare(Range left, Range right) - { - int result = this.boundsComparer.Compare(left.Max, right.Max); - - if (result != 0 || left.IsMaxInclusive == right.IsMaxInclusive) - { - return result; - } - - if (left.IsMaxInclusive) - { - return 1; - } - else - { - return -1; - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using Newtonsoft.Json; + + [JsonObject(MemberSerialization.OptIn)] + internal sealed class Range where T: IComparable + { + public static readonly IComparer TComparer = typeof(T) == typeof(string) ? (IComparer)StringComparer.Ordinal : Comparer.Default; + + [JsonConstructor] + public Range(T min, T max, bool isMinInclusive, bool isMaxInclusive) + { + if (min == null) + { + throw new ArgumentNullException("min"); + } + + if (max == null) + { + throw new ArgumentNullException("max"); + } + + this.Min = min; + this.Max = max; + this.IsMinInclusive = isMinInclusive; + this.IsMaxInclusive = isMaxInclusive; + } + + public static Range GetPointRange(T value) + { + return new Range(value, value, true, true); + } + + [JsonProperty("min")] + public T Min { get; private set; } + + [JsonProperty("max")] + public T Max { get; private set; } + + [JsonProperty("isMinInclusive")] + public bool IsMinInclusive { get; private set; } + + [JsonProperty("isMaxInclusive")] + public bool IsMaxInclusive { get; private set; } + + public bool IsSingleValue + { + get + { + return this.IsMinInclusive && this.IsMaxInclusive && TComparer.Compare(this.Min, this.Max) == 0; + } + } + + public bool IsEmpty + { + get + { + return (TComparer.Compare(this.Min, this.Max) == 0) && !(this.IsMinInclusive && this.IsMaxInclusive); + } + } + + public static Range GetEmptyRange(T value) + { + return new Range( + value, + value, + true, + false); + } + + public bool Contains(T value) + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + int minToValueRelation = TComparer.Compare(this.Min, value); + int maxToValueRelation = TComparer.Compare(this.Max, value); + + return ((this.IsMinInclusive && minToValueRelation <= 0) || (!this.IsMinInclusive && minToValueRelation < 0)) + && + ((this.IsMaxInclusive && maxToValueRelation >= 0) || (!this.IsMaxInclusive && maxToValueRelation > 0)); + } + + public static bool CheckOverlapping(Range range1, Range range2) + { + if (range1 == null || range2 == null || range1.IsEmpty || range2.IsEmpty) + { + return false; + } + + int cmp1 = TComparer.Compare(range1.Min, range2.Max); + int cmp2 = TComparer.Compare(range2.Min, range1.Max); + + if (cmp1 <= 0 && cmp2 <= 0) + { + if ((cmp1 == 0 && !(range1.IsMinInclusive && range2.IsMaxInclusive)) + || (cmp2 == 0 && !(range2.IsMinInclusive && range1.IsMaxInclusive))) + { + return false; + } + + return true; + } + + return false; + } + + public override bool Equals(object obj) + { + return this.Equals(obj as Range); + } + + public override int GetHashCode() + { + unchecked + { + int hash = 0; + hash = (hash * 397) ^ this.Min.GetHashCode(); + hash = (hash * 397) ^ this.Max.GetHashCode(); + hash = (hash * 397) ^ Convert.ToInt32(this.IsMinInclusive); + hash = (hash * 397) ^ Convert.ToInt32(this.IsMaxInclusive); + return hash; + } + } + + public bool Equals(Range other) + { + if (other == null) + { + return false; + } + + return TComparer.Compare(this.Min, other.Min) == 0 + && TComparer.Compare(this.Max, other.Max) == 0 + && this.IsMinInclusive == other.IsMinInclusive + && this.IsMaxInclusive == other.IsMaxInclusive; + } + + public override string ToString() + { + return string.Format(CultureInfo.InvariantCulture, "{0}{1},{2}{3}", this.IsMinInclusive ? "[" : "(", this.Min, this.Max, this.IsMaxInclusive ? "]" : ")"); + } + + public class MinComparer : IComparer> + { + public static readonly MinComparer Instance = new MinComparer(TComparer); + + private readonly IComparer boundsComparer; + + private MinComparer(IComparer boundsComparer) + { + this.boundsComparer = boundsComparer; + } + + public int Compare(Range left, Range right) + { + int result = this.boundsComparer.Compare(left.Min, right.Min); + if (result != 0 || left.IsMinInclusive == right.IsMinInclusive) + { + return result; + } + + if (left.IsMinInclusive) + { + return -1; + } + else + { + return 1; + } + } + } + + public class MaxComparer : IComparer> + { + public static readonly MaxComparer Instance = new MaxComparer(TComparer); + + private readonly IComparer boundsComparer; + + private MaxComparer(IComparer boundsComparer) + { + this.boundsComparer = boundsComparer; + } + + public int Compare(Range left, Range right) + { + int result = this.boundsComparer.Compare(left.Max, right.Max); + + if (result != 0 || left.IsMaxInclusive == right.IsMaxInclusive) + { + return result; + } + + if (left.IsMaxInclusive) + { + return 1; + } + else + { + return -1; + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RangeIndex.cs b/Microsoft.Azure.Cosmos/src/direct/RangeIndex.cs index b75d1aa3d7..63a447a7f6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RangeIndex.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RangeIndex.cs @@ -1,142 +1,142 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Specifies an instance of the class in the Azure Cosmos DB service. - /// - /// - /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop > 5. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class RangeIndex : Index, ICloneable - { - internal RangeIndex() - : base(IndexKind.Range) - { - } - - /// - /// Initializes a new instance of the class with specified DataType for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// - /// - /// Here is an example to instantiate RangeIndex class passing in the DataType: - /// - /// - /// - /// - public RangeIndex(DataType dataType) - : this() - { - this.DataType = dataType; - } - - /// - /// Initializes a new instance of the class with specified DataType and precision for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification. - /// Specifies the precision to be used for the data type associated with this index. - /// - /// - /// Here is an example to instantiate RangeIndex class passing in the DataType and precision: - /// - /// - /// - /// - public RangeIndex(DataType dataType, short precision) - : this(dataType) - { - this.Precision = precision; - } - - /// - /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. - /// - /// - /// The data type for which this index should be applied. - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. - [JsonProperty(PropertyName = Constants.Properties.DataType)] - [JsonConverter(typeof(StringEnumConverter))] - public DataType DataType - { - get - { - DataType result = Documents.DataType.Number; - string strValue = base.GetValue(Constants.Properties.DataType); - if (!string.IsNullOrEmpty(strValue)) - { - result = (DataType)Enum.Parse(typeof(DataType), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.DataType, value.ToString()); - } - } - - /// - /// Gets or sets the precision for this particular index in the Azure Cosmos DB service. - /// - /// - /// The precision for this particular index. Returns null, if not set. - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. - [JsonProperty(PropertyName = Constants.Properties.Precision, - NullValueHandling = NullValueHandling.Ignore)] - public short? Precision - { - get - { - short? result = null; - string strValue = base.GetValue(Constants.Properties.Precision); - if (!string.IsNullOrEmpty(strValue)) - { - result = Convert.ToInt16(strValue, CultureInfo.InvariantCulture); - } - return result; - } - set - { - base.SetValue(Constants.Properties.Precision, value); - } - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.DataType); - short? precision = this.Precision; - } - - /// - /// Creates a copy of the range index for the Azure Cosmos DB service. - /// - /// A clone of the range index. - public object Clone() - { - return new RangeIndex(this.DataType) - { - Precision = this.Precision - }; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Specifies an instance of the class in the Azure Cosmos DB service. + /// + /// + /// Can be used to serve queries like: SELECT * FROM docs d WHERE d.prop > 5. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class RangeIndex : Index, ICloneable + { + internal RangeIndex() + : base(IndexKind.Range) + { + } + + /// + /// Initializes a new instance of the class with specified DataType for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// + /// + /// Here is an example to instantiate RangeIndex class passing in the DataType: + /// + /// + /// + /// + public RangeIndex(DataType dataType) + : this() + { + this.DataType = dataType; + } + + /// + /// Initializes a new instance of the class with specified DataType and precision for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification. + /// Specifies the precision to be used for the data type associated with this index. + /// + /// + /// Here is an example to instantiate RangeIndex class passing in the DataType and precision: + /// + /// + /// + /// + public RangeIndex(DataType dataType, short precision) + : this(dataType) + { + this.Precision = precision; + } + + /// + /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. + /// + /// + /// The data type for which this index should be applied. + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. + [JsonProperty(PropertyName = Constants.Properties.DataType)] + [JsonConverter(typeof(StringEnumConverter))] + public DataType DataType + { + get + { + DataType result = Documents.DataType.Number; + string strValue = base.GetValue(Constants.Properties.DataType); + if (!string.IsNullOrEmpty(strValue)) + { + result = (DataType)Enum.Parse(typeof(DataType), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.DataType, value.ToString()); + } + } + + /// + /// Gets or sets the precision for this particular index in the Azure Cosmos DB service. + /// + /// + /// The precision for this particular index. Returns null, if not set. + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. + [JsonProperty(PropertyName = Constants.Properties.Precision, + NullValueHandling = NullValueHandling.Ignore)] + public short? Precision + { + get + { + short? result = null; + string strValue = base.GetValue(Constants.Properties.Precision); + if (!string.IsNullOrEmpty(strValue)) + { + result = Convert.ToInt16(strValue, CultureInfo.InvariantCulture); + } + return result; + } + set + { + base.SetValue(Constants.Properties.Precision, value); + } + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.DataType); + short? precision = this.Precision; + } + + /// + /// Creates a copy of the range index for the Azure Cosmos DB service. + /// + /// A clone of the range index. + public object Clone() + { + return new RangeIndex(this.DataType) + { + Precision = this.Precision + }; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ReadFeedKeyType.cs b/Microsoft.Azure.Cosmos/src/direct/ReadFeedKeyType.cs index 8da03f6a42..8399c214ac 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReadFeedKeyType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReadFeedKeyType.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Type of Start and End key for ReadFeedKey - /// - internal enum ReadFeedKeyType - { - /// - /// Use ResourceName - /// - ResourceId, - - /// - /// Use EffectivePartitionKey - /// - EffectivePartitionKey, - - /// - /// Use EffectivePartitionKeyRange - /// - EffectivePartitionKeyRange - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Type of Start and End key for ReadFeedKey + /// + internal enum ReadFeedKeyType + { + /// + /// Use ResourceName + /// + ResourceId, + + /// + /// Use EffectivePartitionKey + /// + EffectivePartitionKey, + + /// + /// Use EffectivePartitionKeyRange + /// + EffectivePartitionKeyRange + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ReadMode.cs b/Microsoft.Azure.Cosmos/src/direct/ReadMode.cs index 195b3ef7f1..a4e0442835 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReadMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReadMode.cs @@ -1,14 +1,14 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum ReadMode - { - Primary, // Test hook - Strong, - BoundedStaleness, - Any - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum ReadMode + { + Primary, // Test hook + Strong, + BoundedStaleness, + Any + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ReadPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/ReadPolicy.cs index 8720196ab1..f92e7604bd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReadPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReadPolicy.cs @@ -1,53 +1,53 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - internal sealed class ReadPolicy : JsonSerializable - { - private const int DefaultPrimaryReadCoefficient = 0; - private const int DefaultSecondaryReadCoefficient = 1; - /// - /// Constructor. - /// - public ReadPolicy() - { - } - - /// - /// Relative weight of primary to serve read requests. Higher the value, it is preferred to issue reads to primary. - /// Direct connectivity client can use this value to dynamically decide where to send reads to effectively use the service. - /// - [JsonProperty(PropertyName = Constants.Properties.PrimaryReadCoefficient)] - public int PrimaryReadCoefficient - { - get - { - return base.GetValue(Constants.Properties.PrimaryReadCoefficient, ReadPolicy.DefaultPrimaryReadCoefficient); - } - set - { - base.SetValue(Constants.Properties.PrimaryReadCoefficient, value); - } - } - - /// - /// Relative weight of secondary to serve read requests. Higher the value, it is preferred to issue reads to secondary. - /// Direct connectivity client can use this value to dynamically decide where to send reads to effectively use the service. - /// - [JsonProperty(PropertyName = Constants.Properties.SecondaryReadCoefficient)] - public int SecondaryReadCoefficient - { - get - { - return base.GetValue(Constants.Properties.SecondaryReadCoefficient, ReadPolicy.DefaultSecondaryReadCoefficient); - } - set - { - base.SetValue(Constants.Properties.SecondaryReadCoefficient, value); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + internal sealed class ReadPolicy : JsonSerializable + { + private const int DefaultPrimaryReadCoefficient = 0; + private const int DefaultSecondaryReadCoefficient = 1; + /// + /// Constructor. + /// + public ReadPolicy() + { + } + + /// + /// Relative weight of primary to serve read requests. Higher the value, it is preferred to issue reads to primary. + /// Direct connectivity client can use this value to dynamically decide where to send reads to effectively use the service. + /// + [JsonProperty(PropertyName = Constants.Properties.PrimaryReadCoefficient)] + public int PrimaryReadCoefficient + { + get + { + return base.GetValue(Constants.Properties.PrimaryReadCoefficient, ReadPolicy.DefaultPrimaryReadCoefficient); + } + set + { + base.SetValue(Constants.Properties.PrimaryReadCoefficient, value); + } + } + + /// + /// Relative weight of secondary to serve read requests. Higher the value, it is preferred to issue reads to secondary. + /// Direct connectivity client can use this value to dynamically decide where to send reads to effectively use the service. + /// + [JsonProperty(PropertyName = Constants.Properties.SecondaryReadCoefficient)] + public int SecondaryReadCoefficient + { + get + { + return base.GetValue(Constants.Properties.SecondaryReadCoefficient, ReadPolicy.DefaultSecondaryReadCoefficient); + } + set + { + base.SetValue(Constants.Properties.SecondaryReadCoefficient, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ReceivedResponseEventArgs.cs b/Microsoft.Azure.Cosmos/src/direct/ReceivedResponseEventArgs.cs index 1eba6aabd7..84cc895403 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReceivedResponseEventArgs.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReceivedResponseEventArgs.cs @@ -1,57 +1,57 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net.Http; - - /// - /// Event arguments on events raised after DocumentServiceResponse/HttpResponseMessage is received on ServerStoreModel or HttpRequestMessageHandler. - /// - internal sealed class ReceivedResponseEventArgs : EventArgs - { - public ReceivedResponseEventArgs(DocumentServiceRequest request, DocumentServiceResponse response) - { - this.DocumentServiceResponse = response; - this.DocumentServiceRequest = request; - } - - public ReceivedResponseEventArgs(HttpRequestMessage request, HttpResponseMessage response) - { - this.HttpResponse = response; - this.HttpRequest = request; - } - - /// - /// The DocumentServiceResponse on which the RecievedResponse event is raised. - /// - public DocumentServiceResponse DocumentServiceResponse { get; } - - /// - /// The HttpResponseMessage on which the RecievedResponse event is raised. - /// - public HttpResponseMessage HttpResponse { get; } - - /// - /// The HttpRequestMessage on which corresponds to the response. - /// - public HttpRequestMessage HttpRequest { get; } - - /// - /// The DocumentServiceRequest which yielded the response. - /// - public DocumentServiceRequest DocumentServiceRequest { get; } - - /// - /// Checks if the SendingRequestEventArgs has HttpRespoonseMessage as its member. - /// - /// Used to check if the message is HttpRespoonseMessage or DocumentServiceRequestMessage. - /// true if the message is HttpRespoonseMessage. otherwise, returns false. - public bool IsHttpResponse() - { - return this.HttpResponse != null; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net.Http; + + /// + /// Event arguments on events raised after DocumentServiceResponse/HttpResponseMessage is received on ServerStoreModel or HttpRequestMessageHandler. + /// + internal sealed class ReceivedResponseEventArgs : EventArgs + { + public ReceivedResponseEventArgs(DocumentServiceRequest request, DocumentServiceResponse response) + { + this.DocumentServiceResponse = response; + this.DocumentServiceRequest = request; + } + + public ReceivedResponseEventArgs(HttpRequestMessage request, HttpResponseMessage response) + { + this.HttpResponse = response; + this.HttpRequest = request; + } + + /// + /// The DocumentServiceResponse on which the RecievedResponse event is raised. + /// + public DocumentServiceResponse DocumentServiceResponse { get; } + + /// + /// The HttpResponseMessage on which the RecievedResponse event is raised. + /// + public HttpResponseMessage HttpResponse { get; } + + /// + /// The HttpRequestMessage on which corresponds to the response. + /// + public HttpRequestMessage HttpRequest { get; } + + /// + /// The DocumentServiceRequest which yielded the response. + /// + public DocumentServiceRequest DocumentServiceRequest { get; } + + /// + /// Checks if the SendingRequestEventArgs has HttpRespoonseMessage as its member. + /// + /// Used to check if the message is HttpRespoonseMessage or DocumentServiceRequestMessage. + /// true if the message is HttpRespoonseMessage. otherwise, returns false. + public bool IsHttpResponse() + { + return this.HttpResponse != null; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ReferenceCountedDisposable.cs b/Microsoft.Azure.Cosmos/src/direct/ReferenceCountedDisposable.cs index 347592fd4a..3d281919cf 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReferenceCountedDisposable.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReferenceCountedDisposable.cs @@ -1,221 +1,221 @@ -// Based on https://github.com/dotnet/roslyn/blob/38e1b12b27bbe15ed5e0da3f90ea73e025ff5c7b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs, -// but with WeakReference functionality removed. - -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - -#nullable enable - /// - /// A reference-counting wrapper which allows multiple uses of a single disposable object in code, which is - /// deterministically released (by calling ) when the last reference is - /// disposed. - /// - /// - /// Each instance of represents a counted reference (also - /// referred to as a reference in the following documentation) to a target object. Each of these - /// references has a lifetime, starting when it is constructed and continuing through its release. During - /// this time, the reference is considered alive. Each reference which is alive owns exactly one - /// reference to the target object, ensuring that it will not be disposed while still in use. A reference is - /// released through either of the following actions: - /// - /// - /// The reference is explicitly released by a call to . - /// The reference is no longer in use by managed code and gets reclaimed by the garbage collector. - /// - /// - /// While each instance of should be explicitly disposed when - /// the object is no longer needed by the code owning the reference, this implementation will not leak resources - /// in the event one or more callers fail to do so. When all references to an object are explicitly released - /// (i.e. by calling ), the target object will itself be deterministically released by a - /// call to when the last reference to it is released. However, in the event - /// one or more references is not explicitly released, the underlying object will still become eligible for - /// non-deterministic release (i.e. finalization) as soon as each reference to it is released by one of the - /// two actions described previously. - /// - /// When using , certain steps must be taken to ensure the - /// target object is not disposed early. - /// - /// - /// Use consistently. In other words, do not mix code using - /// reference-counted wrappers with code that references to the target directly. - /// Only use the constructor one time per target object. - /// Additional references to the same target object must only be obtained by calling - /// . - /// Do not call on the target object directly. It will be called - /// automatically at the appropriate time, as described above. - /// - /// - /// All public methods on this type adhere to their pre- and post-conditions and will not invalidate state - /// even in concurrent execution. - /// - /// The type of disposable object. - internal sealed class ReferenceCountedDisposable : IDisposable - where T : class, IDisposable - { -#if DEBUG_REF_COUNTS - private static int s_nextObjectId = 0; - private readonly int _objectId; -#endif - - /// - /// The target of this reference. This value is initialized to a non- value in the - /// constructor, and set to when the current reference is disposed. - /// - /// - /// This value is only cleared in order to support cases where one or more references is garbage - /// collected without having called. - /// - private T? _instance; - - /// - /// The boxed reference count, which is shared by all references with the same object. - /// - /// - /// This field serves as the synchronization object for the current type, since it is shared among all - /// counted reference to the same target object. Accesses to - /// should only occur when this object is locked. - /// - /// PERF DEV NOTE: A concurrent (but complex) implementation of this type with identical semantics is - /// available in source control history. The use of exclusive locks was not causing any measurable - /// performance overhead even on 28-thread machines at the time this was written. - /// - private readonly BoxedReferenceCount _boxedReferenceCount; - - /// - /// Initializes a new reference counting wrapper around an object. - /// - /// - /// The reference count is initialized to 1. - /// - /// The object owned by this wrapper. - /// - /// If is . - /// - public ReferenceCountedDisposable(T instance) - : this(instance, new BoxedReferenceCount()) - { - } - - private ReferenceCountedDisposable(T instance, BoxedReferenceCount referenceCount) - { -#if DEBUG_REF_COUNTS - this._objectId = Interlocked.Increment(ref s_nextObjectId); -#endif - - this._instance = instance ?? throw new ArgumentNullException(nameof(instance)); - - // The reference count has already been incremented for this instance - this._boxedReferenceCount = referenceCount; - } - - /// - /// Gets the target object. - /// - /// - /// This call is not valid after is called. If this property or the target - /// object is used concurrently with a call to , it is possible for the code to be - /// using a disposed object. After the current instance is disposed, this property throws - /// . However, the exact time when this property starts throwing after - /// is called is unspecified; code is expected to not use this property or the object - /// it returns after any code invokes . - /// - /// The target object. - public T Target => this._instance ?? throw new ObjectDisposedException(nameof(ReferenceCountedDisposable)); - - /// - /// Increments the reference count for the disposable object, and returns a new disposable reference to it. - /// - /// - /// The returned object is an independent reference to the same underlying object. Disposing of the - /// returned value multiple times will only cause the reference count to be decreased once. - /// - /// A new pointing to the same underlying object, if it - /// has not yet been disposed; otherwise, if this reference to the underlying object - /// has already been disposed. - public ReferenceCountedDisposable? TryAddReference() - { - lock (this._boxedReferenceCount) - { - if (this._boxedReferenceCount.Value == 0) - { - // The target is already disposed, and cannot be reused - return null; - } - - if (this._instance == null) - { - // The current reference has been disposed, so even though it isn't disposed yet we don't have a - // reference to the target - return null; - } - - checked - { - this._boxedReferenceCount.Value++; - } - - // Must return a new instance, in order for the Dispose operation on each individual instance to - // be idempotent. - return new ReferenceCountedDisposable(this._instance, this._boxedReferenceCount); - } - } - - /// - /// Releases the current reference, causing the underlying object to be disposed if this was the last - /// reference. - /// - /// - /// After this instance is disposed, the method can no longer be used to - /// obtain a new reference to the target, even if other references to the target object are still in - /// use. - /// - public void Dispose() - { - T? instanceToDispose = null; - lock (this._boxedReferenceCount) - { - if (this._instance == null) - { - // Already disposed; allow multiple without error. - return; - } - - this._boxedReferenceCount.Value--; - if (this._boxedReferenceCount.Value == 0) - { - instanceToDispose = this._instance; - } - - // Ensure multiple calls to Dispose for this instance are a NOP. - this._instance = null; - } - - instanceToDispose?.Dispose(); - } - - private sealed class BoxedReferenceCount - { -#if DEBUG_REF_COUNTS - private static int s_nextObjectId; - private readonly int _objectId; -#endif - public int Value; - - public BoxedReferenceCount() - { -#if DEBUG_REF_COUNTS - this._objectId = Interlocked.Increment(ref s_nextObjectId); -#endif - this.Value = 1; - } - } - } +// Based on https://github.com/dotnet/roslyn/blob/38e1b12b27bbe15ed5e0da3f90ea73e025ff5c7b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/Utilities/ReferenceCountedDisposable.cs, +// but with WeakReference functionality removed. + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + +#nullable enable + /// + /// A reference-counting wrapper which allows multiple uses of a single disposable object in code, which is + /// deterministically released (by calling ) when the last reference is + /// disposed. + /// + /// + /// Each instance of represents a counted reference (also + /// referred to as a reference in the following documentation) to a target object. Each of these + /// references has a lifetime, starting when it is constructed and continuing through its release. During + /// this time, the reference is considered alive. Each reference which is alive owns exactly one + /// reference to the target object, ensuring that it will not be disposed while still in use. A reference is + /// released through either of the following actions: + /// + /// + /// The reference is explicitly released by a call to . + /// The reference is no longer in use by managed code and gets reclaimed by the garbage collector. + /// + /// + /// While each instance of should be explicitly disposed when + /// the object is no longer needed by the code owning the reference, this implementation will not leak resources + /// in the event one or more callers fail to do so. When all references to an object are explicitly released + /// (i.e. by calling ), the target object will itself be deterministically released by a + /// call to when the last reference to it is released. However, in the event + /// one or more references is not explicitly released, the underlying object will still become eligible for + /// non-deterministic release (i.e. finalization) as soon as each reference to it is released by one of the + /// two actions described previously. + /// + /// When using , certain steps must be taken to ensure the + /// target object is not disposed early. + /// + /// + /// Use consistently. In other words, do not mix code using + /// reference-counted wrappers with code that references to the target directly. + /// Only use the constructor one time per target object. + /// Additional references to the same target object must only be obtained by calling + /// . + /// Do not call on the target object directly. It will be called + /// automatically at the appropriate time, as described above. + /// + /// + /// All public methods on this type adhere to their pre- and post-conditions and will not invalidate state + /// even in concurrent execution. + /// + /// The type of disposable object. + internal sealed class ReferenceCountedDisposable : IDisposable + where T : class, IDisposable + { +#if DEBUG_REF_COUNTS + private static int s_nextObjectId = 0; + private readonly int _objectId; +#endif + + /// + /// The target of this reference. This value is initialized to a non- value in the + /// constructor, and set to when the current reference is disposed. + /// + /// + /// This value is only cleared in order to support cases where one or more references is garbage + /// collected without having called. + /// + private T? _instance; + + /// + /// The boxed reference count, which is shared by all references with the same object. + /// + /// + /// This field serves as the synchronization object for the current type, since it is shared among all + /// counted reference to the same target object. Accesses to + /// should only occur when this object is locked. + /// + /// PERF DEV NOTE: A concurrent (but complex) implementation of this type with identical semantics is + /// available in source control history. The use of exclusive locks was not causing any measurable + /// performance overhead even on 28-thread machines at the time this was written. + /// + private readonly BoxedReferenceCount _boxedReferenceCount; + + /// + /// Initializes a new reference counting wrapper around an object. + /// + /// + /// The reference count is initialized to 1. + /// + /// The object owned by this wrapper. + /// + /// If is . + /// + public ReferenceCountedDisposable(T instance) + : this(instance, new BoxedReferenceCount()) + { + } + + private ReferenceCountedDisposable(T instance, BoxedReferenceCount referenceCount) + { +#if DEBUG_REF_COUNTS + this._objectId = Interlocked.Increment(ref s_nextObjectId); +#endif + + this._instance = instance ?? throw new ArgumentNullException(nameof(instance)); + + // The reference count has already been incremented for this instance + this._boxedReferenceCount = referenceCount; + } + + /// + /// Gets the target object. + /// + /// + /// This call is not valid after is called. If this property or the target + /// object is used concurrently with a call to , it is possible for the code to be + /// using a disposed object. After the current instance is disposed, this property throws + /// . However, the exact time when this property starts throwing after + /// is called is unspecified; code is expected to not use this property or the object + /// it returns after any code invokes . + /// + /// The target object. + public T Target => this._instance ?? throw new ObjectDisposedException(nameof(ReferenceCountedDisposable)); + + /// + /// Increments the reference count for the disposable object, and returns a new disposable reference to it. + /// + /// + /// The returned object is an independent reference to the same underlying object. Disposing of the + /// returned value multiple times will only cause the reference count to be decreased once. + /// + /// A new pointing to the same underlying object, if it + /// has not yet been disposed; otherwise, if this reference to the underlying object + /// has already been disposed. + public ReferenceCountedDisposable? TryAddReference() + { + lock (this._boxedReferenceCount) + { + if (this._boxedReferenceCount.Value == 0) + { + // The target is already disposed, and cannot be reused + return null; + } + + if (this._instance == null) + { + // The current reference has been disposed, so even though it isn't disposed yet we don't have a + // reference to the target + return null; + } + + checked + { + this._boxedReferenceCount.Value++; + } + + // Must return a new instance, in order for the Dispose operation on each individual instance to + // be idempotent. + return new ReferenceCountedDisposable(this._instance, this._boxedReferenceCount); + } + } + + /// + /// Releases the current reference, causing the underlying object to be disposed if this was the last + /// reference. + /// + /// + /// After this instance is disposed, the method can no longer be used to + /// obtain a new reference to the target, even if other references to the target object are still in + /// use. + /// + public void Dispose() + { + T? instanceToDispose = null; + lock (this._boxedReferenceCount) + { + if (this._instance == null) + { + // Already disposed; allow multiple without error. + return; + } + + this._boxedReferenceCount.Value--; + if (this._boxedReferenceCount.Value == 0) + { + instanceToDispose = this._instance; + } + + // Ensure multiple calls to Dispose for this instance are a NOP. + this._instance = null; + } + + instanceToDispose?.Dispose(); + } + + private sealed class BoxedReferenceCount + { +#if DEBUG_REF_COUNTS + private static int s_nextObjectId; + private readonly int _objectId; +#endif + public int Value; + + public BoxedReferenceCount() + { +#if DEBUG_REF_COUNTS + this._objectId = Interlocked.Increment(ref s_nextObjectId); +#endif + this.Value = 1; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs b/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs index 7bfb3d9b4e..9008d67871 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs @@ -1,6348 +1,7163 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - - internal static class RegionProximityUtil - { - public static List GetRegionsForLinkType(GeoLinkTypes geoLinkType, List existingRegions) - { - foreach (string existingRegion in existingRegions) - { - if (string.IsNullOrEmpty(existingRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(existingRegion)) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "existingRegion {0} is not a valid region.", existingRegion)); - } - } - - List> regionsSatisfyingLinkTypePerRegion = new List>(); - - foreach (string existingRegion in existingRegions) - { - regionsSatisfyingLinkTypePerRegion.Add(RegionProximityUtil.GetRegionsForLinkType(geoLinkType, existingRegion)); - } - - if(regionsSatisfyingLinkTypePerRegion.Count < 1) - { - return new List(); - } - - IEnumerable regionsSatisfyingAllInputRegions = regionsSatisfyingLinkTypePerRegion[0].AsEnumerable(); - for (int i = 1; i < regionsSatisfyingLinkTypePerRegion.Count; i++) - { - regionsSatisfyingAllInputRegions = regionsSatisfyingAllInputRegions.Intersect(regionsSatisfyingLinkTypePerRegion[i]); - } - - if (existingRegions.Except(regionsSatisfyingAllInputRegions).Any()) - { - return new List(); - } - - return regionsSatisfyingAllInputRegions.ToList(); - } - - public static List GetRegionsForLinkType(GeoLinkTypes geoLinkType, string sourceRegion) - { - if (string.IsNullOrEmpty(sourceRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(sourceRegion)) - { - throw new ArgumentException("sourceRegion is not a valid region."); - } - - List regionsSatisfyingLinkType = new List(); - - long linkTypeThresholdInMs = RegionProximityUtil.GetLinkTypeThresholdInMs(geoLinkType); - - Dictionary roundTripTimeFromSourceRegion = RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs[sourceRegion]; - foreach (string region in roundTripTimeFromSourceRegion.Keys) - { - if (roundTripTimeFromSourceRegion[region] <= linkTypeThresholdInMs) - { - regionsSatisfyingLinkType.Add(region); - } - } - - if (!regionsSatisfyingLinkType.Contains(sourceRegion)) - { - return new List(); - } - - return regionsSatisfyingLinkType; - } - - public static List GeneratePreferredRegionList(string sourceRegion) - { - if (string.IsNullOrEmpty(sourceRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(sourceRegion)) - { - throw new ArgumentException("sourceRegion is not a valid region."); - } - - List> regionRTTList = RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs[sourceRegion].ToList(); - regionRTTList.Sort((x, y) => x.Value.CompareTo(y.Value)); - - List preferredLocationsList = new List(); - foreach (KeyValuePair regionRTT in regionRTTList) - { - preferredLocationsList.Add(regionRTT.Key); - } - - return preferredLocationsList; - } - - internal static Dictionary> SourceRegionToTargetRegionsRTTInMs = new Dictionary>() - { - { - LocationNames.AustraliaCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 0 }, - { LocationNames.AustraliaCentral2, 2 }, - { LocationNames.AustraliaEast, 6 }, - { LocationNames.AustraliaSoutheast, 18 }, - { LocationNames.AustriaEast, 240 }, - { LocationNames.BrazilSouth, 314 }, - { LocationNames.BrazilSoutheast, 314 }, - { LocationNames.CanadaCentral, 204 }, - { LocationNames.CanadaEast, 214 }, - { LocationNames.CentralIndia, 144 }, - { LocationNames.CentralUS, 184 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 120 }, - { LocationNames.EastUS, 205 }, - { LocationNames.EastUS2, 200 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 242 }, - { LocationNames.FranceSouth, 230 }, - { LocationNames.GermanyNorth, 254 }, - { LocationNames.GermanyWestCentral, 246 }, - { LocationNames.IsraelCentral, 168 }, - { LocationNames.ItalyNorth, 240 }, - { LocationNames.JapanEast, 125 }, - { LocationNames.JapanWest, 130 }, - { LocationNames.JioIndiaCentral, 144 }, - { LocationNames.JioIndiaWest, 144 }, - { LocationNames.KoreaCentral, 154 }, - { LocationNames.KoreaSouth, 148 }, - { LocationNames.MalaysiaSouth, 94 }, - { LocationNames.MexicoCentral, 162 }, - { LocationNames.NewZealandNorth, 100 }, - { LocationNames.NorthCentralUS, 192 }, - { LocationNames.NorthEurope, 262 }, - { LocationNames.NorwayEast, 272 }, - { LocationNames.NorwayWest, 266 }, - { LocationNames.PolandCentral, 252 }, - { LocationNames.QatarCentral, 168 }, - { LocationNames.SouthAfricaNorth, 390 }, - { LocationNames.SouthAfricaWest, 394 }, - { LocationNames.SouthCentralUS, 174 }, - { LocationNames.SoutheastAsia, 94 }, - { LocationNames.SouthIndia, 126 }, - { LocationNames.SpainCentral, 242 }, - { LocationNames.SwedenCentral, 272 }, - { LocationNames.SwedenSouth, 272 }, - { LocationNames.SwitzerlandNorth, 240 }, - { LocationNames.SwitzerlandWest, 236 }, - { LocationNames.TaiwanNorth, 120 }, - { LocationNames.TaiwanNorthwest, 120 }, - { LocationNames.UAECentral, 168 }, - { LocationNames.UAENorth, 168 }, - { LocationNames.UKSouth, 250 }, - { LocationNames.UKWest, 252 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 170 }, - { LocationNames.WestEurope, 252 }, - { LocationNames.WestIndia, 142 }, - { LocationNames.WestUS, 142 }, - { LocationNames.WestUS2, 162 }, - { LocationNames.WestUS3, 162 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.AustraliaCentral2, - new Dictionary() - { - { LocationNames.AustraliaCentral, 2 }, - { LocationNames.AustraliaCentral2, 0 }, - { LocationNames.AustraliaEast, 6 }, - { LocationNames.AustraliaSoutheast, 18 }, - { LocationNames.AustriaEast, 240 }, - { LocationNames.BrazilSouth, 313 }, - { LocationNames.BrazilSoutheast, 313 }, - { LocationNames.CanadaCentral, 204 }, - { LocationNames.CanadaEast, 214 }, - { LocationNames.CentralIndia, 144 }, - { LocationNames.CentralUS, 184 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 120 }, - { LocationNames.EastUS, 205 }, - { LocationNames.EastUS2, 200 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 242 }, - { LocationNames.FranceSouth, 230 }, - { LocationNames.GermanyNorth, 256 }, - { LocationNames.GermanyWestCentral, 246 }, - { LocationNames.IsraelCentral, 168 }, - { LocationNames.ItalyNorth, 240 }, - { LocationNames.JapanEast, 124 }, - { LocationNames.JapanWest, 132 }, - { LocationNames.JioIndiaCentral, 144 }, - { LocationNames.JioIndiaWest, 144 }, - { LocationNames.KoreaCentral, 154 }, - { LocationNames.KoreaSouth, 148 }, - { LocationNames.MalaysiaSouth, 92 }, - { LocationNames.MexicoCentral, 162 }, - { LocationNames.NewZealandNorth, 2 }, - { LocationNames.NorthCentralUS, 192 }, - { LocationNames.NorthEurope, 262 }, - { LocationNames.NorwayEast, 272 }, - { LocationNames.NorwayWest, 266 }, - { LocationNames.PolandCentral, 252 }, - { LocationNames.QatarCentral, 168 }, - { LocationNames.SouthAfricaNorth, 391 }, - { LocationNames.SouthAfricaWest, 392 }, - { LocationNames.SouthCentralUS, 174 }, - { LocationNames.SoutheastAsia, 92 }, - { LocationNames.SouthIndia, 124 }, - { LocationNames.SpainCentral, 242 }, - { LocationNames.SwedenCentral, 272 }, - { LocationNames.SwedenSouth, 272 }, - { LocationNames.SwitzerlandNorth, 240 }, - { LocationNames.SwitzerlandWest, 236 }, - { LocationNames.TaiwanNorth, 120 }, - { LocationNames.TaiwanNorthwest, 120 }, - { LocationNames.UAECentral, 168 }, - { LocationNames.UAENorth, 168 }, - { LocationNames.UKSouth, 248 }, - { LocationNames.UKWest, 252 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 170 }, - { LocationNames.WestEurope, 252 }, - { LocationNames.WestIndia, 142 }, - { LocationNames.WestUS, 142 }, - { LocationNames.WestUS2, 162 }, - { LocationNames.WestUS3, 162 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.AustraliaEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 6 }, - { LocationNames.AustraliaCentral2, 6 }, - { LocationNames.AustraliaEast, 0 }, - { LocationNames.AustraliaSoutheast, 14 }, - { LocationNames.AustriaEast, 236 }, - { LocationNames.BrazilSouth, 308 }, - { LocationNames.BrazilSoutheast, 308 }, - { LocationNames.CanadaCentral, 200 }, - { LocationNames.CanadaEast, 210 }, - { LocationNames.CentralIndia, 140 }, - { LocationNames.CentralUS, 180 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 116 }, - { LocationNames.EastUS, 200 }, - { LocationNames.EastUS2, 196 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 238 }, - { LocationNames.FranceSouth, 224 }, - { LocationNames.GermanyNorth, 250 }, - { LocationNames.GermanyWestCentral, 240 }, - { LocationNames.IsraelCentral, 164 }, - { LocationNames.ItalyNorth, 236 }, - { LocationNames.JapanEast, 118 }, - { LocationNames.JapanWest, 126 }, - { LocationNames.JioIndiaCentral, 140 }, - { LocationNames.JioIndiaWest, 140 }, - { LocationNames.KoreaCentral, 150 }, - { LocationNames.KoreaSouth, 143 }, - { LocationNames.MalaysiaSouth, 88 }, - { LocationNames.MexicoCentral, 158 }, - { LocationNames.NewZealandNorth, 6 }, - { LocationNames.NorthCentralUS, 187 }, - { LocationNames.NorthEurope, 258 }, - { LocationNames.NorwayEast, 266 }, - { LocationNames.NorwayWest, 260 }, - { LocationNames.PolandCentral, 248 }, - { LocationNames.QatarCentral, 164 }, - { LocationNames.SouthAfricaNorth, 386 }, - { LocationNames.SouthAfricaWest, 390 }, - { LocationNames.SouthCentralUS, 170 }, - { LocationNames.SoutheastAsia, 88 }, - { LocationNames.SouthIndia, 120 }, - { LocationNames.SpainCentral, 238 }, - { LocationNames.SwedenCentral, 266 }, - { LocationNames.SwedenSouth, 266 }, - { LocationNames.SwitzerlandNorth, 236 }, - { LocationNames.SwitzerlandWest, 232 }, - { LocationNames.TaiwanNorth, 116 }, - { LocationNames.TaiwanNorthwest, 116 }, - { LocationNames.UAECentral, 164 }, - { LocationNames.UAENorth, 163 }, - { LocationNames.UKSouth, 246 }, - { LocationNames.UKWest, 248 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 166 }, - { LocationNames.WestEurope, 248 }, - { LocationNames.WestIndia, 138 }, - { LocationNames.WestUS, 138 }, - { LocationNames.WestUS2, 158 }, - { LocationNames.WestUS3, 158 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.AustraliaSoutheast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 18 }, - { LocationNames.AustraliaCentral2, 18 }, - { LocationNames.AustraliaEast, 14 }, - { LocationNames.AustraliaSoutheast, 0 }, - { LocationNames.AustriaEast, 232 }, - { LocationNames.BrazilSouth, 320 }, - { LocationNames.BrazilSoutheast, 320 }, - { LocationNames.CanadaCentral, 210 }, - { LocationNames.CanadaEast, 220 }, - { LocationNames.CentralIndia, 136 }, - { LocationNames.CentralUS, 190 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 118 }, - { LocationNames.EastUS, 212 }, - { LocationNames.EastUS2, 206 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 235 }, - { LocationNames.FranceSouth, 222 }, - { LocationNames.GermanyNorth, 246 }, - { LocationNames.GermanyWestCentral, 238 }, - { LocationNames.IsraelCentral, 160 }, - { LocationNames.ItalyNorth, 232 }, - { LocationNames.JapanEast, 130 }, - { LocationNames.JapanWest, 138 }, - { LocationNames.JioIndiaCentral, 136 }, - { LocationNames.JioIndiaWest, 136 }, - { LocationNames.KoreaCentral, 146 }, - { LocationNames.KoreaSouth, 140 }, - { LocationNames.MalaysiaSouth, 85 }, - { LocationNames.MexicoCentral, 168 }, - { LocationNames.NewZealandNorth, 18 }, - { LocationNames.NorthCentralUS, 198 }, - { LocationNames.NorthEurope, 260 }, - { LocationNames.NorwayEast, 264 }, - { LocationNames.NorwayWest, 258 }, - { LocationNames.PolandCentral, 244 }, - { LocationNames.QatarCentral, 160 }, - { LocationNames.SouthAfricaNorth, 382 }, - { LocationNames.SouthAfricaWest, 386 }, - { LocationNames.SouthCentralUS, 180 }, - { LocationNames.SoutheastAsia, 85 }, - { LocationNames.SouthIndia, 118 }, - { LocationNames.SpainCentral, 235 }, - { LocationNames.SwedenCentral, 264 }, - { LocationNames.SwedenSouth, 264 }, - { LocationNames.SwitzerlandNorth, 232 }, - { LocationNames.SwitzerlandWest, 228 }, - { LocationNames.TaiwanNorth, 118 }, - { LocationNames.TaiwanNorthwest, 118 }, - { LocationNames.UAECentral, 160 }, - { LocationNames.UAENorth, 160 }, - { LocationNames.UKSouth, 242 }, - { LocationNames.UKWest, 245 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 176 }, - { LocationNames.WestEurope, 244 }, - { LocationNames.WestIndia, 134 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 168 }, - { LocationNames.WestUS3, 168 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.AustriaEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 240 }, - { LocationNames.AustraliaCentral2, 240 }, - { LocationNames.AustraliaEast, 236 }, - { LocationNames.AustraliaSoutheast, 232 }, - { LocationNames.AustriaEast, 0 }, - { LocationNames.BrazilSouth, 198 }, - { LocationNames.BrazilSoutheast, 198 }, - { LocationNames.CanadaCentral, 104 }, - { LocationNames.CanadaEast, 114 }, - { LocationNames.CentralIndia, 112 }, - { LocationNames.CentralUS, 112 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 182 }, - { LocationNames.EastUS, 92 }, - { LocationNames.EastUS2, 94 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 14 }, - { LocationNames.FranceSouth, 10 }, - { LocationNames.GermanyNorth, 16 }, - { LocationNames.GermanyWestCentral, 6 }, - { LocationNames.IsraelCentral, 106 }, - { LocationNames.ItalyNorth, 100 }, - { LocationNames.JapanEast, 216 }, - { LocationNames.JapanWest, 216 }, - { LocationNames.JioIndiaCentral, 112 }, - { LocationNames.JioIndiaWest, 112 }, - { LocationNames.KoreaCentral, 210 }, - { LocationNames.KoreaSouth, 204 }, - { LocationNames.MalaysiaSouth, 148 }, - { LocationNames.MexicoCentral, 154 }, - { LocationNames.NewZealandNorth, 240 }, - { LocationNames.NorthCentralUS, 110 }, - { LocationNames.NorthEurope, 31 }, - { LocationNames.NorwayEast, 32 }, - { LocationNames.NorwayWest, 26 }, - { LocationNames.PolandCentral, 12 }, - { LocationNames.QatarCentral, 106 }, - { LocationNames.SouthAfricaNorth, 172 }, - { LocationNames.SouthAfricaWest, 162 }, - { LocationNames.SouthCentralUS, 118 }, - { LocationNames.SoutheastAsia, 148 }, - { LocationNames.SouthIndia, 126 }, - { LocationNames.SpainCentral, 14 }, - { LocationNames.SwedenCentral, 32 }, - { LocationNames.SwedenSouth, 255 }, - { LocationNames.SwitzerlandNorth, 100 }, - { LocationNames.SwitzerlandWest, 4 }, - { LocationNames.TaiwanNorth, 182 }, - { LocationNames.TaiwanNorthwest, 182 }, - { LocationNames.UAECentral, 106 }, - { LocationNames.UAENorth, 108 }, - { LocationNames.UKSouth, 20 }, - { LocationNames.UKWest, 22 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 134 }, - { LocationNames.WestEurope, 12 }, - { LocationNames.WestIndia, 116 }, - { LocationNames.WestUS, 150 }, - { LocationNames.WestUS2, 154 }, - { LocationNames.WestUS3, 154 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.BrazilSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 314 }, - { LocationNames.AustraliaCentral2, 313 }, - { LocationNames.AustraliaEast, 308 }, - { LocationNames.AustraliaSoutheast, 320 }, - { LocationNames.AustriaEast, 198 }, - { LocationNames.BrazilSouth, 0 }, - { LocationNames.BrazilSoutheast, 10 }, - { LocationNames.CanadaCentral, 132 }, - { LocationNames.CanadaEast, 141 }, - { LocationNames.CentralIndia, 302 }, - { LocationNames.CentralUS, 146 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 320 }, - { LocationNames.EastUS, 118 }, - { LocationNames.EastUS2, 122 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 186 }, - { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyNorth, 198 }, - { LocationNames.GermanyWestCentral, 192 }, - { LocationNames.IsraelCentral, 296 }, - { LocationNames.ItalyNorth, 198 }, - { LocationNames.JapanEast, 262 }, - { LocationNames.JapanWest, 270 }, - { LocationNames.JioIndiaCentral, 302 }, - { LocationNames.JioIndiaWest, 302 }, - { LocationNames.KoreaCentral, 300 }, - { LocationNames.KoreaSouth, 306 }, - { LocationNames.MalaysiaSouth, 328 }, - { LocationNames.MexicoCentral, 182 }, - { LocationNames.NewZealandNorth, 314 }, - { LocationNames.NorthCentralUS, 138 }, - { LocationNames.NorthEurope, 177 }, - { LocationNames.NorwayEast, 208 }, - { LocationNames.NorwayWest, 201 }, - { LocationNames.PolandCentral, 188 }, - { LocationNames.QatarCentral, 296 }, - { LocationNames.SouthAfricaNorth, 342 }, - { LocationNames.SouthAfricaWest, 326 }, - { LocationNames.SouthCentralUS, 140 }, - { LocationNames.SoutheastAsia, 328 }, - { LocationNames.SouthIndia, 314 }, - { LocationNames.SpainCentral, 186 }, - { LocationNames.SwedenCentral, 208 }, - { LocationNames.SwedenSouth, 208 }, - { LocationNames.SwitzerlandNorth, 198 }, - { LocationNames.SwitzerlandWest, 202 }, - { LocationNames.TaiwanNorth, 320 }, - { LocationNames.TaiwanNorthwest, 320 }, - { LocationNames.UAECentral, 296 }, - { LocationNames.UAENorth, 298 }, - { LocationNames.UKSouth, 181 }, - { LocationNames.UKWest, 184 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 160 }, - { LocationNames.WestEurope, 188 }, - { LocationNames.WestIndia, 304 }, - { LocationNames.WestUS, 172 }, - { LocationNames.WestUS2, 182 }, - { LocationNames.WestUS3, 182 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.BrazilSoutheast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 314 }, - { LocationNames.AustraliaCentral2, 313 }, - { LocationNames.AustraliaEast, 308 }, - { LocationNames.AustraliaSoutheast, 320 }, - { LocationNames.AustriaEast, 198 }, - { LocationNames.BrazilSouth, 10 }, - { LocationNames.BrazilSoutheast, 0 }, - { LocationNames.CanadaCentral, 132 }, - { LocationNames.CanadaEast, 141 }, - { LocationNames.CentralIndia, 302 }, - { LocationNames.CentralUS, 146 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 320 }, - { LocationNames.EastUS, 118 }, - { LocationNames.EastUS2, 122 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 186 }, - { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyNorth, 198 }, - { LocationNames.GermanyWestCentral, 192 }, - { LocationNames.IsraelCentral, 296 }, - { LocationNames.ItalyNorth, 198 }, - { LocationNames.JapanEast, 262 }, - { LocationNames.JapanWest, 270 }, - { LocationNames.JioIndiaCentral, 302 }, - { LocationNames.JioIndiaWest, 302 }, - { LocationNames.KoreaCentral, 300 }, - { LocationNames.KoreaSouth, 306 }, - { LocationNames.MalaysiaSouth, 328 }, - { LocationNames.MexicoCentral, 182 }, - { LocationNames.NewZealandNorth, 314 }, - { LocationNames.NorthCentralUS, 138 }, - { LocationNames.NorthEurope, 177 }, - { LocationNames.NorwayEast, 208 }, - { LocationNames.NorwayWest, 201 }, - { LocationNames.PolandCentral, 188 }, - { LocationNames.QatarCentral, 296 }, - { LocationNames.SouthAfricaNorth, 342 }, - { LocationNames.SouthAfricaWest, 326 }, - { LocationNames.SouthCentralUS, 140 }, - { LocationNames.SoutheastAsia, 328 }, - { LocationNames.SouthIndia, 314 }, - { LocationNames.SpainCentral, 186 }, - { LocationNames.SwedenCentral, 208 }, - { LocationNames.SwedenSouth, 208 }, - { LocationNames.SwitzerlandNorth, 198 }, - { LocationNames.SwitzerlandWest, 202 }, - { LocationNames.TaiwanNorth, 320 }, - { LocationNames.TaiwanNorthwest, 320 }, - { LocationNames.UAECentral, 296 }, - { LocationNames.UAENorth, 298 }, - { LocationNames.UKSouth, 181 }, - { LocationNames.UKWest, 184 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 160 }, - { LocationNames.WestEurope, 188 }, - { LocationNames.WestIndia, 304 }, - { LocationNames.WestUS, 172 }, - { LocationNames.WestUS2, 172 }, - { LocationNames.WestUS3, 182 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.CanadaCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 204 }, - { LocationNames.AustraliaCentral2, 204 }, - { LocationNames.AustraliaEast, 200 }, - { LocationNames.AustraliaSoutheast, 210 }, - { LocationNames.AustriaEast, 104 }, - { LocationNames.BrazilSouth, 132 }, - { LocationNames.BrazilSoutheast, 132 }, - { LocationNames.CanadaCentral, 0 }, - { LocationNames.CanadaEast, 12 }, - { LocationNames.CentralIndia, 208 }, - { LocationNames.CentralUS, 21 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 196 }, - { LocationNames.EastUS, 25 }, - { LocationNames.EastUS2, 28 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 92 }, - { LocationNames.FranceSouth, 106 }, - { LocationNames.GermanyNorth, 104 }, - { LocationNames.GermanyWestCentral, 98 }, - { LocationNames.IsraelCentral, 201 }, - { LocationNames.ItalyNorth, 104 }, - { LocationNames.JapanEast, 152 }, - { LocationNames.JapanWest, 160 }, - { LocationNames.JioIndiaCentral, 208 }, - { LocationNames.JioIndiaWest, 208 }, - { LocationNames.KoreaCentral, 178 }, - { LocationNames.KoreaSouth, 182 }, - { LocationNames.MalaysiaSouth, 216 }, - { LocationNames.MexicoCentral, 57 }, - { LocationNames.NewZealandNorth, 204 }, - { LocationNames.NorthCentralUS, 14 }, - { LocationNames.NorthEurope, 84 }, - { LocationNames.NorwayEast, 114 }, - { LocationNames.NorwayWest, 108 }, - { LocationNames.PolandCentral, 94 }, - { LocationNames.QatarCentral, 201 }, - { LocationNames.SouthAfricaNorth, 246 }, - { LocationNames.SouthAfricaWest, 230 }, - { LocationNames.SouthCentralUS, 42 }, - { LocationNames.SoutheastAsia, 216 }, - { LocationNames.SouthIndia, 220 }, - { LocationNames.SpainCentral, 92 }, - { LocationNames.SwedenCentral, 114 }, - { LocationNames.SwedenSouth, 114 }, - { LocationNames.SwitzerlandNorth, 104 }, - { LocationNames.SwitzerlandWest, 108 }, - { LocationNames.TaiwanNorth, 196 }, - { LocationNames.TaiwanNorthwest, 196 }, - { LocationNames.UAECentral, 201 }, - { LocationNames.UAENorth, 204 }, - { LocationNames.UKSouth, 86 }, - { LocationNames.UKWest, 90 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 36 }, - { LocationNames.WestEurope, 94 }, - { LocationNames.WestIndia, 210 }, - { LocationNames.WestUS, 64 }, - { LocationNames.WestUS2, 57 }, - { LocationNames.WestUS3, 57 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.CanadaEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 214 }, - { LocationNames.AustraliaCentral2, 214 }, - { LocationNames.AustraliaEast, 210 }, - { LocationNames.AustraliaSoutheast, 220 }, - { LocationNames.AustriaEast, 114 }, - { LocationNames.BrazilSouth, 141 }, - { LocationNames.BrazilSoutheast, 141 }, - { LocationNames.CanadaCentral, 12 }, - { LocationNames.CanadaEast, 0 }, - { LocationNames.CentralIndia, 218 }, - { LocationNames.CentralUS, 30 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 206 }, - { LocationNames.EastUS, 34 }, - { LocationNames.EastUS2, 38 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 102 }, - { LocationNames.FranceSouth, 116 }, - { LocationNames.GermanyNorth, 114 }, - { LocationNames.GermanyWestCentral, 108 }, - { LocationNames.IsraelCentral, 210 }, - { LocationNames.ItalyNorth, 114 }, - { LocationNames.JapanEast, 162 }, - { LocationNames.JapanWest, 170 }, - { LocationNames.JioIndiaCentral, 218 }, - { LocationNames.JioIndiaWest, 218 }, - { LocationNames.KoreaCentral, 186 }, - { LocationNames.KoreaSouth, 192 }, - { LocationNames.MalaysiaSouth, 224 }, - { LocationNames.MexicoCentral, 66 }, - { LocationNames.NewZealandNorth, 214 }, - { LocationNames.NorthCentralUS, 24 }, - { LocationNames.NorthEurope, 93 }, - { LocationNames.NorwayEast, 124 }, - { LocationNames.NorwayWest, 116 }, - { LocationNames.PolandCentral, 103 }, - { LocationNames.QatarCentral, 210 }, - { LocationNames.SouthAfricaNorth, 256 }, - { LocationNames.SouthAfricaWest, 238 }, - { LocationNames.SouthCentralUS, 52 }, - { LocationNames.SoutheastAsia, 224 }, - { LocationNames.SouthIndia, 230 }, - { LocationNames.SpainCentral, 102 }, - { LocationNames.SwedenCentral, 124 }, - { LocationNames.SwedenSouth, 124 }, - { LocationNames.SwitzerlandNorth, 114 }, - { LocationNames.SwitzerlandWest, 118 }, - { LocationNames.TaiwanNorth, 206 }, - { LocationNames.TaiwanNorthwest, 206 }, - { LocationNames.UAECentral, 210 }, - { LocationNames.UAENorth, 214 }, - { LocationNames.UKSouth, 96 }, - { LocationNames.UKWest, 98 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 44 }, - { LocationNames.WestEurope, 103 }, - { LocationNames.WestIndia, 220 }, - { LocationNames.WestUS, 72 }, - { LocationNames.WestUS2, 66 }, - { LocationNames.WestUS3, 66 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.CentralIndia, - new Dictionary() - { - { LocationNames.AustraliaCentral, 144 }, - { LocationNames.AustraliaCentral2, 144 }, - { LocationNames.AustraliaEast, 140 }, - { LocationNames.AustraliaSoutheast, 136 }, - { LocationNames.AustriaEast, 112 }, - { LocationNames.BrazilSouth, 302 }, - { LocationNames.BrazilSoutheast, 302 }, - { LocationNames.CanadaCentral, 208 }, - { LocationNames.CanadaEast, 218 }, - { LocationNames.CentralIndia, 0 }, - { LocationNames.CentralUS, 222 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 86 }, - { LocationNames.EastUS, 196 }, - { LocationNames.EastUS2, 198 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 116 }, - { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyWestCentral, 118 }, - { LocationNames.IsraelCentral, 30 }, - { LocationNames.ItalyNorth, 112 }, - { LocationNames.JapanEast, 120 }, - { LocationNames.JapanWest, 124 }, - { LocationNames.JioIndiaCentral, 100 }, - { LocationNames.JioIndiaWest, 100 }, - { LocationNames.KoreaCentral, 114 }, - { LocationNames.KoreaSouth, 106 }, - { LocationNames.MalaysiaSouth, 52 }, - { LocationNames.MexicoCentral, 212 }, - { LocationNames.NewZealandNorth, 144 }, - { LocationNames.NorthCentralUS, 216 }, - { LocationNames.NorthEurope, 137 }, - { LocationNames.NorwayEast, 146 }, - { LocationNames.NorwayWest, 136 }, - { LocationNames.PolandCentral, 126 }, - { LocationNames.QatarCentral, 30 }, - { LocationNames.SouthAfricaNorth, 264 }, - { LocationNames.SouthAfricaWest, 267 }, - { LocationNames.SouthCentralUS, 224 }, - { LocationNames.SoutheastAsia, 52 }, - { LocationNames.SouthIndia, 22 }, - { LocationNames.SpainCentral, 116 }, - { LocationNames.SwedenCentral, 146 }, - { LocationNames.SwedenSouth, 146 }, - { LocationNames.SwitzerlandNorth, 112 }, - { LocationNames.SwitzerlandWest, 110 }, - { LocationNames.TaiwanNorth, 86 }, - { LocationNames.TaiwanNorthwest, 86 }, - { LocationNames.UAECentral, 30 }, - { LocationNames.UAENorth, 30 }, - { LocationNames.UKSouth, 122 }, - { LocationNames.UKWest, 126 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 236 }, - { LocationNames.WestEurope, 126 }, - { LocationNames.WestIndia, 4 }, - { LocationNames.WestUS, 218 }, - { LocationNames.WestUS2, 212 }, - { LocationNames.WestUS3, 212 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.CentralUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 184 }, - { LocationNames.AustraliaCentral2, 184 }, - { LocationNames.AustraliaEast, 180 }, - { LocationNames.AustraliaSoutheast, 190 }, - { LocationNames.AustriaEast, 112 }, - { LocationNames.BrazilSouth, 146 }, - { LocationNames.BrazilSoutheast, 146 }, - { LocationNames.CanadaCentral, 21 }, - { LocationNames.CanadaEast, 30 }, - { LocationNames.CentralIndia, 222 }, - { LocationNames.CentralUS, 0 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 176 }, - { LocationNames.EastUS, 23 }, - { LocationNames.EastUS2, 26 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 101 }, - { LocationNames.FranceSouth, 110 }, - { LocationNames.GermanyNorth, 118 }, - { LocationNames.GermanyWestCentral, 112 }, - { LocationNames.IsraelCentral, 216 }, - { LocationNames.ItalyNorth, 112 }, - { LocationNames.JapanEast, 140 }, - { LocationNames.JapanWest, 143 }, - { LocationNames.JioIndiaCentral, 222 }, - { LocationNames.JioIndiaWest, 222 }, - { LocationNames.KoreaCentral, 158 }, - { LocationNames.KoreaSouth, 162 }, - { LocationNames.MalaysiaSouth, 194 }, - { LocationNames.MexicoCentral, 36 }, - { LocationNames.NewZealandNorth, 184 }, - { LocationNames.NorthCentralUS, 8 }, - { LocationNames.NorthEurope, 92 }, - { LocationNames.NorwayEast, 128 }, - { LocationNames.NorwayWest, 121 }, - { LocationNames.PolandCentral, 102 }, - { LocationNames.QatarCentral, 216 }, - { LocationNames.SouthAfricaNorth, 260 }, - { LocationNames.SouthAfricaWest, 244 }, - { LocationNames.SouthCentralUS, 22 }, - { LocationNames.SoutheastAsia, 194 }, - { LocationNames.SouthIndia, 228 }, - { LocationNames.SpainCentral, 101 }, - { LocationNames.SwedenCentral, 128 }, - { LocationNames.SwedenSouth, 128 }, - { LocationNames.SwitzerlandNorth, 112 }, - { LocationNames.SwitzerlandWest, 110 }, - { LocationNames.TaiwanNorth, 176 }, - { LocationNames.TaiwanNorthwest, 176 }, - { LocationNames.UAECentral, 216 }, - { LocationNames.UAENorth, 218 }, - { LocationNames.UKSouth, 96 }, - { LocationNames.UKWest, 96 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 15 }, - { LocationNames.WestEurope, 102 }, - { LocationNames.WestIndia, 224 }, - { LocationNames.WestUS, 44 }, - { LocationNames.WestUS2, 36 }, - { LocationNames.WestUS3, 36 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 0 }, - { LocationNames.ChinaEast2, 255 }, - { LocationNames.ChinaEast3, 255 }, - { LocationNames.ChinaNorth, 35 }, - { LocationNames.ChinaNorth2, 255 }, - { LocationNames.ChinaNorth3, 255 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaEast2, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 255 }, - { LocationNames.ChinaEast2, 0 }, - { LocationNames.ChinaEast3, 255 }, - { LocationNames.ChinaNorth, 255 }, - { LocationNames.ChinaNorth2, 35 }, - { LocationNames.ChinaNorth3, 255 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaEast3, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 255 }, - { LocationNames.ChinaEast2, 255 }, - { LocationNames.ChinaEast3, 0 }, - { LocationNames.ChinaNorth, 255 }, - { LocationNames.ChinaNorth2, 255 }, - { LocationNames.ChinaNorth3, 100 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 35 }, - { LocationNames.ChinaEast2, 255 }, - { LocationNames.ChinaEast3, 255 }, - { LocationNames.ChinaNorth, 0 }, - { LocationNames.ChinaNorth2, 255 }, - { LocationNames.ChinaNorth3, 255 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaNorth2, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 255 }, - { LocationNames.ChinaEast2, 35 }, - { LocationNames.ChinaEast3, 255 }, - { LocationNames.ChinaNorth, 255 }, - { LocationNames.ChinaNorth2, 0 }, - { LocationNames.ChinaNorth3, 255 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ChinaNorth3, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, 255 }, - { LocationNames.ChinaEast2, 255 }, - { LocationNames.ChinaEast3, 100 }, - { LocationNames.ChinaNorth, 255 }, - { LocationNames.ChinaNorth2, 255 }, - { LocationNames.ChinaNorth3, 0 }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.EastAsia, - new Dictionary() - { - { LocationNames.AustraliaCentral, 120 }, - { LocationNames.AustraliaCentral2, 120 }, - { LocationNames.AustraliaEast, 116 }, - { LocationNames.AustraliaSoutheast, 118 }, - { LocationNames.AustriaEast, 182 }, - { LocationNames.BrazilSouth, 320 }, - { LocationNames.BrazilSoutheast, 320 }, - { LocationNames.CanadaCentral, 196 }, - { LocationNames.CanadaEast, 206 }, - { LocationNames.CentralIndia, 86 }, - { LocationNames.CentralUS, 176 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 0 }, - { LocationNames.EastUS, 199 }, - { LocationNames.EastUS2, 210 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 184 }, - { LocationNames.FranceSouth, 172 }, - { LocationNames.GermanyNorth, 196 }, - { LocationNames.GermanyWestCentral, 188 }, - { LocationNames.IsraelCentral, 110 }, - { LocationNames.ItalyNorth, 182 }, - { LocationNames.JapanEast, 50 }, - { LocationNames.JapanWest, 50 }, - { LocationNames.JioIndiaCentral, 86 }, - { LocationNames.JioIndiaWest, 86 }, - { LocationNames.KoreaCentral, 56 }, - { LocationNames.KoreaSouth, 60 }, - { LocationNames.MalaysiaSouth, 33 }, - { LocationNames.MexicoCentral, 140 }, - { LocationNames.NewZealandNorth, 120 }, - { LocationNames.NorthCentralUS, 184 }, - { LocationNames.NorthEurope, 205 }, - { LocationNames.NorwayEast, 214 }, - { LocationNames.NorwayWest, 206 }, - { LocationNames.PolandCentral, 193 }, - { LocationNames.QatarCentral, 110 }, - { LocationNames.SouthAfricaNorth, 332 }, - { LocationNames.SouthAfricaWest, 336 }, - { LocationNames.SouthCentralUS, 182 }, - { LocationNames.SoutheastAsia, 33 }, - { LocationNames.SouthIndia, 66 }, - { LocationNames.SpainCentral, 184 }, - { LocationNames.SwedenCentral, 214 }, - { LocationNames.SwedenSouth, 214 }, - { LocationNames.SwitzerlandNorth, 182 }, - { LocationNames.SwitzerlandWest, 178 }, - { LocationNames.TaiwanNorth, 100 }, - { LocationNames.TaiwanNorthwest, 100 }, - { LocationNames.UAECentral, 110 }, - { LocationNames.UAENorth, 109 }, - { LocationNames.UKSouth, 192 }, - { LocationNames.UKWest, 194 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 162 }, - { LocationNames.WestEurope, 193 }, - { LocationNames.WestIndia, 84 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 140 }, - { LocationNames.WestUS3, 140 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.EastUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 205 }, - { LocationNames.AustraliaCentral2, 205 }, - { LocationNames.AustraliaEast, 200 }, - { LocationNames.AustraliaSoutheast, 212 }, - { LocationNames.AustriaEast, 92 }, - { LocationNames.BrazilSouth, 118 }, - { LocationNames.BrazilSoutheast, 118 }, - { LocationNames.CanadaCentral, 25 }, - { LocationNames.CanadaEast, 34 }, - { LocationNames.CentralIndia, 196 }, - { LocationNames.CentralUS, 23 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 199 }, - { LocationNames.EastUS, 0 }, - { LocationNames.EastUS2, 6 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 80 }, - { LocationNames.FranceSouth, 90 }, - { LocationNames.GermanyNorth, 91 }, - { LocationNames.GermanyWestCentral, 86 }, - { LocationNames.IsraelCentral, 189 }, - { LocationNames.ItalyNorth, 92 }, - { LocationNames.JapanEast, 162 }, - { LocationNames.JapanWest, 168 }, - { LocationNames.JioIndiaCentral, 196 }, - { LocationNames.JioIndiaWest, 196 }, - { LocationNames.KoreaCentral, 182 }, - { LocationNames.KoreaSouth, 186 }, - { LocationNames.MalaysiaSouth, 218 }, - { LocationNames.MexicoCentral, 58 }, - { LocationNames.NewZealandNorth, 205 }, - { LocationNames.NorthCentralUS, 19 }, - { LocationNames.NorthEurope, 76 }, - { LocationNames.NorwayEast, 101 }, - { LocationNames.NorwayWest, 94 }, - { LocationNames.PolandCentral, 81 }, - { LocationNames.QatarCentral, 189 }, - { LocationNames.SouthAfricaNorth, 234 }, - { LocationNames.SouthAfricaWest, 218 }, - { LocationNames.SouthCentralUS, 32 }, - { LocationNames.SoutheastAsia, 218 }, - { LocationNames.SouthIndia, 208 }, - { LocationNames.SpainCentral, 80 }, - { LocationNames.SwedenCentral, 101 }, - { LocationNames.SwedenSouth, 101 }, - { LocationNames.SwitzerlandNorth, 92 }, - { LocationNames.SwitzerlandWest, 88 }, - { LocationNames.TaiwanNorth, 199 }, - { LocationNames.TaiwanNorthwest, 199 }, - { LocationNames.UAECentral, 189 }, - { LocationNames.UAENorth, 192 }, - { LocationNames.UKSouth, 74 }, - { LocationNames.UKWest, 76 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 38 }, - { LocationNames.WestEurope, 81 }, - { LocationNames.WestIndia, 198 }, - { LocationNames.WestUS, 64 }, - { LocationNames.WestUS2, 58 }, - { LocationNames.WestUS3, 58 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.EastUS2, - new Dictionary() - { - { LocationNames.AustraliaCentral, 200 }, - { LocationNames.AustraliaCentral2, 200 }, - { LocationNames.AustraliaEast, 196 }, - { LocationNames.AustraliaSoutheast, 206 }, - { LocationNames.AustriaEast, 94 }, - { LocationNames.BrazilSouth, 122 }, - { LocationNames.BrazilSoutheast, 122 }, - { LocationNames.CanadaCentral, 28 }, - { LocationNames.CanadaEast, 38 }, - { LocationNames.CentralIndia, 198 }, - { LocationNames.CentralUS, 26 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 210 }, - { LocationNames.EastUS, 6 }, - { LocationNames.EastUS2, 0 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 80 }, - { LocationNames.FranceSouth, 90 }, - { LocationNames.GermanyNorth, 94 }, - { LocationNames.GermanyWestCentral, 90 }, - { LocationNames.IsraelCentral, 190 }, - { LocationNames.ItalyNorth, 94 }, - { LocationNames.JapanEast, 164 }, - { LocationNames.JapanWest, 164 }, - { LocationNames.JioIndiaCentral, 198 }, - { LocationNames.JioIndiaWest, 198 }, - { LocationNames.KoreaCentral, 176 }, - { LocationNames.KoreaSouth, 182 }, - { LocationNames.MalaysiaSouth, 226 }, - { LocationNames.MexicoCentral, 68 }, - { LocationNames.NewZealandNorth, 200 }, - { LocationNames.NorthCentralUS, 22 }, - { LocationNames.NorthEurope, 75 }, - { LocationNames.NorwayEast, 104 }, - { LocationNames.NorwayWest, 98 }, - { LocationNames.PolandCentral, 86 }, - { LocationNames.QatarCentral, 190 }, - { LocationNames.SouthAfricaNorth, 240 }, - { LocationNames.SouthAfricaWest, 222 }, - { LocationNames.SouthCentralUS, 26 }, - { LocationNames.SoutheastAsia, 226 }, - { LocationNames.SouthIndia, 210 }, - { LocationNames.SpainCentral, 80 }, - { LocationNames.SwedenCentral, 104 }, - { LocationNames.SwedenSouth, 104 }, - { LocationNames.SwitzerlandNorth, 94 }, - { LocationNames.SwitzerlandWest, 88 }, - { LocationNames.TaiwanNorth, 210 }, - { LocationNames.TaiwanNorthwest, 210 }, - { LocationNames.UAECentral, 190 }, - { LocationNames.UAENorth, 194 }, - { LocationNames.UKSouth, 78 }, - { LocationNames.UKWest, 80 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 47 }, - { LocationNames.WestEurope, 86 }, - { LocationNames.WestIndia, 200 }, - { LocationNames.WestUS, 58 }, - { LocationNames.WestUS2, 68 }, - { LocationNames.WestUS3, 68 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.EastUSSLV, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, 0 }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, 255 }, - { LocationNames.SwedenSouth, 255 }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, 255 }, - { LocationNames.EastUS2EUAP, 255 }, - } - }, - { - LocationNames.FranceCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 242 }, - { LocationNames.AustraliaCentral2, 242 }, - { LocationNames.AustraliaEast, 238 }, - { LocationNames.AustraliaSoutheast, 235 }, - { LocationNames.AustriaEast, 14 }, - { LocationNames.BrazilSouth, 186 }, - { LocationNames.BrazilSoutheast, 186 }, - { LocationNames.CanadaCentral, 92 }, - { LocationNames.CanadaEast, 102 }, - { LocationNames.CentralIndia, 116 }, - { LocationNames.CentralUS, 101 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 184 }, - { LocationNames.EastUS, 80 }, - { LocationNames.EastUS2, 80 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 0 }, - { LocationNames.FranceSouth, 11 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 10 }, - { LocationNames.IsraelCentral, 108 }, - { LocationNames.ItalyNorth, 14 }, - { LocationNames.JapanEast, 218 }, - { LocationNames.JapanWest, 218 }, - { LocationNames.JioIndiaCentral, 116 }, - { LocationNames.JioIndiaWest, 116 }, - { LocationNames.KoreaCentral, 212 }, - { LocationNames.KoreaSouth, 206 }, - { LocationNames.MalaysiaSouth, 150 }, - { LocationNames.MexicoCentral, 140 }, - { LocationNames.NewZealandNorth, 242 }, - { LocationNames.NorthCentralUS, 96 }, - { LocationNames.NorthEurope, 27 }, - { LocationNames.NorwayEast, 30 }, - { LocationNames.NorwayWest, 24 }, - { LocationNames.PolandCentral, 10 }, - { LocationNames.QatarCentral, 108 }, - { LocationNames.SouthAfricaNorth, 166 }, - { LocationNames.SouthAfricaWest, 150 }, - { LocationNames.SouthCentralUS, 106 }, - { LocationNames.SoutheastAsia, 150 }, - { LocationNames.SouthIndia, 128 }, - { LocationNames.SpainCentral, 100 }, - { LocationNames.SwedenCentral, 30 }, - { LocationNames.SwedenSouth, 30 }, - { LocationNames.SwitzerlandNorth, 14 }, - { LocationNames.SwitzerlandWest, 10 }, - { LocationNames.TaiwanNorth, 184 }, - { LocationNames.TaiwanNorthwest, 184 }, - { LocationNames.UAECentral, 108 }, - { LocationNames.UAENorth, 112 }, - { LocationNames.UKSouth, 7 }, - { LocationNames.UKWest, 8 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 119 }, - { LocationNames.WestEurope, 10 }, - { LocationNames.WestIndia, 118 }, - { LocationNames.WestUS, 138 }, - { LocationNames.WestUS2, 140 }, - { LocationNames.WestUS3, 140 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.FranceSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 230 }, - { LocationNames.AustraliaCentral2, 230 }, - { LocationNames.AustraliaEast, 224 }, - { LocationNames.AustraliaSoutheast, 222 }, - { LocationNames.AustriaEast, 10 }, - { LocationNames.BrazilSouth, 200 }, - { LocationNames.BrazilSoutheast, 200 }, - { LocationNames.CanadaCentral, 106 }, - { LocationNames.CanadaEast, 116 }, - { LocationNames.CentralIndia, 102 }, - { LocationNames.CentralUS, 110 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 172 }, - { LocationNames.EastUS, 90 }, - { LocationNames.EastUS2, 90 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 11 }, - { LocationNames.FranceSouth, 0 }, - { LocationNames.GermanyNorth, 26 }, - { LocationNames.GermanyWestCentral, 17 }, - { LocationNames.IsraelCentral, 96 }, - { LocationNames.ItalyNorth, 10 }, - { LocationNames.JapanEast, 204 }, - { LocationNames.JapanWest, 206 }, - { LocationNames.JioIndiaCentral, 102 }, - { LocationNames.JioIndiaWest, 102 }, - { LocationNames.KoreaCentral, 200 }, - { LocationNames.KoreaSouth, 193 }, - { LocationNames.MalaysiaSouth, 138 }, - { LocationNames.MexicoCentral, 146 }, - { LocationNames.NewZealandNorth, 230 }, - { LocationNames.NorthCentralUS, 104 }, - { LocationNames.NorthEurope, 31 }, - { LocationNames.NorwayEast, 42 }, - { LocationNames.NorwayWest, 36 }, - { LocationNames.PolandCentral, 20 }, - { LocationNames.QatarCentral, 96 }, - { LocationNames.SouthAfricaNorth, 162 }, - { LocationNames.SouthAfricaWest, 166 }, - { LocationNames.SouthCentralUS, 116 }, - { LocationNames.SoutheastAsia, 138 }, - { LocationNames.SouthIndia, 114 }, - { LocationNames.SpainCentral, 11 }, - { LocationNames.SwedenCentral, 42 }, - { LocationNames.SwedenSouth, 42 }, - { LocationNames.SwitzerlandNorth, 10 }, - { LocationNames.SwitzerlandWest, 8 }, - { LocationNames.TaiwanNorth, 172 }, - { LocationNames.TaiwanNorthwest, 172 }, - { LocationNames.UAECentral, 96 }, - { LocationNames.UAENorth, 98 }, - { LocationNames.UKSouth, 16 }, - { LocationNames.UKWest, 18 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 126 }, - { LocationNames.WestEurope, 20 }, - { LocationNames.WestIndia, 106 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 146 }, - { LocationNames.WestUS3, 146 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.GermanyNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 254 }, - { LocationNames.AustraliaCentral2, 256 }, - { LocationNames.AustraliaEast, 250 }, - { LocationNames.AustraliaSoutheast, 246 }, - { LocationNames.AustriaEast, 16 }, - { LocationNames.BrazilSouth, 198 }, - { LocationNames.BrazilSoutheast, 198 }, - { LocationNames.CanadaCentral, 104 }, - { LocationNames.CanadaEast, 114 }, - { LocationNames.CentralIndia, 128 }, - { LocationNames.CentralUS, 118 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 196 }, - { LocationNames.EastUS, 91 }, - { LocationNames.EastUS2, 94 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 20 }, - { LocationNames.FranceSouth, 26 }, - { LocationNames.GermanyNorth, 0 }, - { LocationNames.GermanyWestCentral, 10 }, - { LocationNames.IsraelCentral, 120 }, - { LocationNames.ItalyNorth, 16 }, - { LocationNames.JapanEast, 230 }, - { LocationNames.JapanWest, 230 }, - { LocationNames.JioIndiaCentral, 128 }, - { LocationNames.JioIndiaWest, 128 }, - { LocationNames.KoreaCentral, 224 }, - { LocationNames.KoreaSouth, 218 }, - { LocationNames.MalaysiaSouth, 162 }, - { LocationNames.MexicoCentral, 154 }, - { LocationNames.NewZealandNorth, 254 }, - { LocationNames.NorthCentralUS, 112 }, - { LocationNames.NorthEurope, 31 }, - { LocationNames.NorwayEast, 20 }, - { LocationNames.NorwayWest, 26 }, - { LocationNames.PolandCentral, 10 }, - { LocationNames.QatarCentral, 120 }, - { LocationNames.SouthAfricaNorth, 178 }, - { LocationNames.SouthAfricaWest, 162 }, - { LocationNames.SouthCentralUS, 120 }, - { LocationNames.SoutheastAsia, 162 }, - { LocationNames.SouthIndia, 140 }, - { LocationNames.SpainCentral, 20 }, - { LocationNames.SwedenCentral, 20 }, - { LocationNames.SwedenSouth, 20 }, - { LocationNames.SwitzerlandNorth, 16 }, - { LocationNames.SwitzerlandWest, 20 }, - { LocationNames.TaiwanNorth, 196 }, - { LocationNames.TaiwanNorthwest, 196 }, - { LocationNames.UAECentral, 120 }, - { LocationNames.UAENorth, 124 }, - { LocationNames.UKSouth, 20 }, - { LocationNames.UKWest, 22 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 132 }, - { LocationNames.WestEurope, 10 }, - { LocationNames.WestIndia, 130 }, - { LocationNames.WestUS, 153 }, - { LocationNames.WestUS2, 154 }, - { LocationNames.WestUS3, 154 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.GermanyWestCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 246 }, - { LocationNames.AustraliaCentral2, 246 }, - { LocationNames.AustraliaEast, 240 }, - { LocationNames.AustraliaSoutheast, 238 }, - { LocationNames.AustriaEast, 6 }, - { LocationNames.BrazilSouth, 192 }, - { LocationNames.BrazilSoutheast, 192 }, - { LocationNames.CanadaCentral, 98 }, - { LocationNames.CanadaEast, 108 }, - { LocationNames.CentralIndia, 118 }, - { LocationNames.CentralUS, 112 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 188 }, - { LocationNames.EastUS, 86 }, - { LocationNames.EastUS2, 90 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 10 }, - { LocationNames.FranceSouth, 17 }, - { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyWestCentral, 0 }, - { LocationNames.IsraelCentral, 112 }, - { LocationNames.ItalyNorth, 6 }, - { LocationNames.JapanEast, 220 }, - { LocationNames.JapanWest, 220 }, - { LocationNames.JioIndiaCentral, 118 }, - { LocationNames.JioIndiaWest, 118 }, - { LocationNames.KoreaCentral, 216 }, - { LocationNames.KoreaSouth, 209 }, - { LocationNames.MalaysiaSouth, 154 }, - { LocationNames.MexicoCentral, 148 }, - { LocationNames.NewZealandNorth, 246 }, - { LocationNames.NorthCentralUS, 106 }, - { LocationNames.NorthEurope, 25 }, - { LocationNames.NorwayEast, 26 }, - { LocationNames.NorwayWest, 20 }, - { LocationNames.PolandCentral, 8 }, - { LocationNames.QatarCentral, 112 }, - { LocationNames.SouthAfricaNorth, 178 }, - { LocationNames.SouthAfricaWest, 156 }, - { LocationNames.SouthCentralUS, 116 }, - { LocationNames.SoutheastAsia, 154 }, - { LocationNames.SouthIndia, 130 }, - { LocationNames.SpainCentral, 10 }, - { LocationNames.SwedenCentral, 26 }, - { LocationNames.SwedenSouth, 26 }, - { LocationNames.SwitzerlandNorth, 6 }, - { LocationNames.SwitzerlandWest, 10 }, - { LocationNames.TaiwanNorth, 188 }, - { LocationNames.TaiwanNorthwest, 188 }, - { LocationNames.UAECentral, 112 }, - { LocationNames.UAENorth, 114 }, - { LocationNames.UKSouth, 14 }, - { LocationNames.UKWest, 18 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 126 }, - { LocationNames.WestEurope, 8 }, - { LocationNames.WestIndia, 122 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 148 }, - { LocationNames.WestUS3, 148 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.IsraelCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 168 }, - { LocationNames.AustraliaCentral2, 168 }, - { LocationNames.AustraliaEast, 164 }, - { LocationNames.AustraliaSoutheast, 160 }, - { LocationNames.AustriaEast, 106 }, - { LocationNames.BrazilSouth, 296 }, - { LocationNames.BrazilSoutheast, 296 }, - { LocationNames.CanadaCentral, 201 }, - { LocationNames.CanadaEast, 210 }, - { LocationNames.CentralIndia, 30 }, - { LocationNames.CentralUS, 216 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 110 }, - { LocationNames.EastUS, 189 }, - { LocationNames.EastUS2, 190 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 108 }, - { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyWestCentral, 112 }, - { LocationNames.IsraelCentral, 0 }, - { LocationNames.ItalyNorth, 106 }, - { LocationNames.JapanEast, 144 }, - { LocationNames.JapanWest, 149 }, - { LocationNames.JioIndiaCentral, 30 }, - { LocationNames.JioIndiaWest, 30 }, - { LocationNames.KoreaCentral, 138 }, - { LocationNames.KoreaSouth, 132 }, - { LocationNames.MalaysiaSouth, 76 }, - { LocationNames.MexicoCentral, 236 }, - { LocationNames.NewZealandNorth, 168 }, - { LocationNames.NorthCentralUS, 209 }, - { LocationNames.NorthEurope, 129 }, - { LocationNames.NorwayEast, 138 }, - { LocationNames.NorwayWest, 130 }, - { LocationNames.PolandCentral, 118 }, - { LocationNames.QatarCentral, 4 }, - { LocationNames.SouthAfricaNorth, 256 }, - { LocationNames.SouthAfricaWest, 260 }, - { LocationNames.SouthCentralUS, 218 }, - { LocationNames.SoutheastAsia, 76 }, - { LocationNames.SouthIndia, 46 }, - { LocationNames.SpainCentral, 108 }, - { LocationNames.SwedenCentral, 129 }, - { LocationNames.SwedenSouth, 129 }, - { LocationNames.SwitzerlandNorth, 106 }, - { LocationNames.SwitzerlandWest, 102 }, - { LocationNames.TaiwanNorth, 110 }, - { LocationNames.TaiwanNorthwest, 110 }, - { LocationNames.UAECentral, 100 }, - { LocationNames.UAENorth, 4 }, - { LocationNames.UKSouth, 116 }, - { LocationNames.UKWest, 118 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 230 }, - { LocationNames.WestEurope, 118 }, - { LocationNames.WestIndia, 28 }, - { LocationNames.WestUS, 244 }, - { LocationNames.WestUS2, 236 }, - { LocationNames.WestUS3, 236 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.ItalyNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 240 }, - { LocationNames.AustraliaCentral2, 240 }, - { LocationNames.AustraliaEast, 236 }, - { LocationNames.AustraliaSoutheast, 232 }, - { LocationNames.AustriaEast, 100 }, - { LocationNames.BrazilSouth, 198 }, - { LocationNames.BrazilSoutheast, 198 }, - { LocationNames.CanadaCentral, 104 }, - { LocationNames.CanadaEast, 114 }, - { LocationNames.CentralIndia, 112 }, - { LocationNames.CentralUS, 112 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 182 }, - { LocationNames.EastUS, 92 }, - { LocationNames.EastUS2, 94 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 14 }, - { LocationNames.FranceSouth, 10 }, - { LocationNames.GermanyNorth, 16 }, - { LocationNames.GermanyWestCentral, 6 }, - { LocationNames.IsraelCentral, 106 }, - { LocationNames.ItalyNorth, 0 }, - { LocationNames.JapanEast, 216 }, - { LocationNames.JapanWest, 216 }, - { LocationNames.JioIndiaCentral, 112 }, - { LocationNames.JioIndiaWest, 112 }, - { LocationNames.KoreaCentral, 210 }, - { LocationNames.KoreaSouth, 204 }, - { LocationNames.MalaysiaSouth, 148 }, - { LocationNames.MexicoCentral, 154 }, - { LocationNames.NewZealandNorth, 240 }, - { LocationNames.NorthCentralUS, 110 }, - { LocationNames.NorthEurope, 31 }, - { LocationNames.NorwayEast, 32 }, - { LocationNames.NorwayWest, 26 }, - { LocationNames.PolandCentral, 12 }, - { LocationNames.QatarCentral, 106 }, - { LocationNames.SouthAfricaNorth, 172 }, - { LocationNames.SouthAfricaWest, 162 }, - { LocationNames.SouthCentralUS, 118 }, - { LocationNames.SoutheastAsia, 148 }, - { LocationNames.SouthIndia, 126 }, - { LocationNames.SpainCentral, 14 }, - { LocationNames.SwedenCentral, 32 }, - { LocationNames.SwedenSouth, 255 }, - { LocationNames.SwitzerlandNorth, 100 }, - { LocationNames.SwitzerlandWest, 4 }, - { LocationNames.TaiwanNorth, 182 }, - { LocationNames.TaiwanNorthwest, 182 }, - { LocationNames.UAECentral, 106 }, - { LocationNames.UAENorth, 108 }, - { LocationNames.UKSouth, 20 }, - { LocationNames.UKWest, 22 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 134 }, - { LocationNames.WestEurope, 12 }, - { LocationNames.WestIndia, 116 }, - { LocationNames.WestUS, 150 }, - { LocationNames.WestUS2, 154 }, - { LocationNames.WestUS3, 154 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.JapanEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 125 }, - { LocationNames.AustraliaCentral2, 124 }, - { LocationNames.AustraliaEast, 118 }, - { LocationNames.AustraliaSoutheast, 130 }, - { LocationNames.AustriaEast, 216 }, - { LocationNames.BrazilSouth, 262 }, - { LocationNames.BrazilSoutheast, 262 }, - { LocationNames.CanadaCentral, 152 }, - { LocationNames.CanadaEast, 162 }, - { LocationNames.CentralIndia, 120 }, - { LocationNames.CentralUS, 140 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 50 }, - { LocationNames.EastUS, 162 }, - { LocationNames.EastUS2, 164 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 218 }, - { LocationNames.FranceSouth, 204 }, - { LocationNames.GermanyNorth, 230 }, - { LocationNames.GermanyWestCentral, 220 }, - { LocationNames.IsraelCentral, 144 }, - { LocationNames.ItalyNorth, 216 }, - { LocationNames.JapanEast, 0 }, - { LocationNames.JapanWest, 8 }, - { LocationNames.JioIndiaCentral, 120 }, - { LocationNames.JioIndiaWest, 120 }, - { LocationNames.KoreaCentral, 30 }, - { LocationNames.KoreaSouth, 35 }, - { LocationNames.MalaysiaSouth, 68 }, - { LocationNames.MexicoCentral, 112 }, - { LocationNames.NewZealandNorth, 125 }, - { LocationNames.NorthCentralUS, 148 }, - { LocationNames.NorthEurope, 223 }, - { LocationNames.NorwayEast, 254 }, - { LocationNames.NorwayWest, 248 }, - { LocationNames.PolandCentral, 234 }, - { LocationNames.QatarCentral, 144 }, - { LocationNames.SouthAfricaNorth, 366 }, - { LocationNames.SouthAfricaWest, 370 }, - { LocationNames.SouthCentralUS, 138 }, - { LocationNames.SoutheastAsia, 68 }, - { LocationNames.SouthIndia, 100 }, - { LocationNames.SpainCentral, 218 }, - { LocationNames.SwedenCentral, 254 }, - { LocationNames.SwedenSouth, 254 }, - { LocationNames.SwitzerlandNorth, 216 }, - { LocationNames.SwitzerlandWest, 212 }, - { LocationNames.TaiwanNorth, 50 }, - { LocationNames.TaiwanNorthwest, 50 }, - { LocationNames.UAECentral, 144 }, - { LocationNames.UAENorth, 144 }, - { LocationNames.UKSouth, 226 }, - { LocationNames.UKWest, 230 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 126 }, - { LocationNames.WestEurope, 234 }, - { LocationNames.WestIndia, 118 }, - { LocationNames.WestUS, 106 }, - { LocationNames.WestUS2, 112 }, - { LocationNames.WestUS3, 112 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.JapanWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 130 }, - { LocationNames.AustraliaCentral2, 132 }, - { LocationNames.AustraliaEast, 126 }, - { LocationNames.AustraliaSoutheast, 138 }, - { LocationNames.AustriaEast, 216 }, - { LocationNames.BrazilSouth, 270 }, - { LocationNames.BrazilSoutheast, 270 }, - { LocationNames.CanadaCentral, 160 }, - { LocationNames.CanadaEast, 170 }, - { LocationNames.CentralIndia, 124 }, - { LocationNames.CentralUS, 143 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 50 }, - { LocationNames.EastUS, 168 }, - { LocationNames.EastUS2, 164 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 218 }, - { LocationNames.FranceSouth, 206 }, - { LocationNames.GermanyNorth, 230 }, - { LocationNames.GermanyWestCentral, 220 }, - { LocationNames.IsraelCentral, 149 }, - { LocationNames.ItalyNorth, 216 }, - { LocationNames.JapanEast, 8 }, - { LocationNames.JapanWest, 0 }, - { LocationNames.JioIndiaCentral, 124 }, - { LocationNames.JioIndiaWest, 124 }, - { LocationNames.KoreaCentral, 36 }, - { LocationNames.KoreaSouth, 42 }, - { LocationNames.MalaysiaSouth, 74 }, - { LocationNames.MexicoCentral, 112 }, - { LocationNames.NewZealandNorth, 130 }, - { LocationNames.NorthCentralUS, 152 }, - { LocationNames.NorthEurope, 236 }, - { LocationNames.NorwayEast, 248 }, - { LocationNames.NorwayWest, 240 }, - { LocationNames.PolandCentral, 228 }, - { LocationNames.QatarCentral, 149 }, - { LocationNames.SouthAfricaNorth, 366 }, - { LocationNames.SouthAfricaWest, 370 }, - { LocationNames.SouthCentralUS, 138 }, - { LocationNames.SoutheastAsia, 74 }, - { LocationNames.SouthIndia, 104 }, - { LocationNames.SpainCentral, 218 }, - { LocationNames.SwedenCentral, 248 }, - { LocationNames.SwedenSouth, 248 }, - { LocationNames.SwitzerlandNorth, 216 }, - { LocationNames.SwitzerlandWest, 210 }, - { LocationNames.TaiwanNorth, 50 }, - { LocationNames.TaiwanNorthwest, 50 }, - { LocationNames.UAECentral, 149 }, - { LocationNames.UAENorth, 148 }, - { LocationNames.UKSouth, 225 }, - { LocationNames.UKWest, 228 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 128 }, - { LocationNames.WestEurope, 228 }, - { LocationNames.WestIndia, 122 }, - { LocationNames.WestUS, 106 }, - { LocationNames.WestUS2, 112 }, - { LocationNames.WestUS3, 112 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.JioIndiaCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 144 }, - { LocationNames.AustraliaCentral2, 144 }, - { LocationNames.AustraliaEast, 140 }, - { LocationNames.AustraliaSoutheast, 136 }, - { LocationNames.AustriaEast, 112 }, - { LocationNames.BrazilSouth, 302 }, - { LocationNames.BrazilSoutheast, 302 }, - { LocationNames.CanadaCentral, 208 }, - { LocationNames.CanadaEast, 218 }, - { LocationNames.CentralIndia, 100 }, - { LocationNames.CentralUS, 222 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 86 }, - { LocationNames.EastUS, 196 }, - { LocationNames.EastUS2, 198 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 116 }, - { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyWestCentral, 118 }, - { LocationNames.IsraelCentral, 30 }, - { LocationNames.ItalyNorth, 112 }, - { LocationNames.JapanEast, 120 }, - { LocationNames.JapanWest, 124 }, - { LocationNames.JioIndiaCentral, 0 }, - { LocationNames.JioIndiaWest, 100 }, - { LocationNames.KoreaCentral, 114 }, - { LocationNames.KoreaSouth, 106 }, - { LocationNames.MalaysiaSouth, 52 }, - { LocationNames.MexicoCentral, 212 }, - { LocationNames.NewZealandNorth, 144 }, - { LocationNames.NorthCentralUS, 216 }, - { LocationNames.NorthEurope, 137 }, - { LocationNames.NorwayEast, 146 }, - { LocationNames.NorwayWest, 136 }, - { LocationNames.PolandCentral, 126 }, - { LocationNames.QatarCentral, 30 }, - { LocationNames.SouthAfricaNorth, 264 }, - { LocationNames.SouthAfricaWest, 267 }, - { LocationNames.SouthCentralUS, 224 }, - { LocationNames.SoutheastAsia, 52 }, - { LocationNames.SouthIndia, 22 }, - { LocationNames.SpainCentral, 116 }, - { LocationNames.SwedenCentral, 146 }, - { LocationNames.SwedenSouth, 146 }, - { LocationNames.SwitzerlandNorth, 112 }, - { LocationNames.SwitzerlandWest, 110 }, - { LocationNames.TaiwanNorth, 86 }, - { LocationNames.TaiwanNorthwest, 86 }, - { LocationNames.UAECentral, 30 }, - { LocationNames.UAENorth, 30 }, - { LocationNames.UKSouth, 122 }, - { LocationNames.UKWest, 126 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 236 }, - { LocationNames.WestEurope, 126 }, - { LocationNames.WestIndia, 4 }, - { LocationNames.WestUS, 218 }, - { LocationNames.WestUS2, 212 }, - { LocationNames.WestUS3, 212 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.JioIndiaWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 144 }, - { LocationNames.AustraliaCentral2, 144 }, - { LocationNames.AustraliaEast, 140 }, - { LocationNames.AustraliaSoutheast, 136 }, - { LocationNames.AustriaEast, 112 }, - { LocationNames.BrazilSouth, 302 }, - { LocationNames.BrazilSoutheast, 302 }, - { LocationNames.CanadaCentral, 208 }, - { LocationNames.CanadaEast, 218 }, - { LocationNames.CentralIndia, 100 }, - { LocationNames.CentralUS, 222 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 86 }, - { LocationNames.EastUS, 196 }, - { LocationNames.EastUS2, 198 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 116 }, - { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyWestCentral, 118 }, - { LocationNames.IsraelCentral, 30 }, - { LocationNames.ItalyNorth, 112 }, - { LocationNames.JapanEast, 120 }, - { LocationNames.JapanWest, 124 }, - { LocationNames.JioIndiaCentral, 100 }, - { LocationNames.JioIndiaWest, 0 }, - { LocationNames.KoreaCentral, 114 }, - { LocationNames.KoreaSouth, 106 }, - { LocationNames.MalaysiaSouth, 52 }, - { LocationNames.MexicoCentral, 212 }, - { LocationNames.NewZealandNorth, 144 }, - { LocationNames.NorthCentralUS, 216 }, - { LocationNames.NorthEurope, 137 }, - { LocationNames.NorwayEast, 146 }, - { LocationNames.NorwayWest, 136 }, - { LocationNames.PolandCentral, 126 }, - { LocationNames.QatarCentral, 30 }, - { LocationNames.SouthAfricaNorth, 264 }, - { LocationNames.SouthAfricaWest, 267 }, - { LocationNames.SouthCentralUS, 224 }, - { LocationNames.SoutheastAsia, 52 }, - { LocationNames.SouthIndia, 22 }, - { LocationNames.SpainCentral, 116 }, - { LocationNames.SwedenCentral, 146 }, - { LocationNames.SwedenSouth, 146 }, - { LocationNames.SwitzerlandNorth, 112 }, - { LocationNames.SwitzerlandWest, 110 }, - { LocationNames.TaiwanNorth, 86 }, - { LocationNames.TaiwanNorthwest, 86 }, - { LocationNames.UAECentral, 30 }, - { LocationNames.UAENorth, 30 }, - { LocationNames.UKSouth, 122 }, - { LocationNames.UKWest, 126 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 236 }, - { LocationNames.WestEurope, 126 }, - { LocationNames.WestIndia, 4 }, - { LocationNames.WestUS, 218 }, - { LocationNames.WestUS2, 212 }, - { LocationNames.WestUS3, 212 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.KoreaCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 154 }, - { LocationNames.AustraliaCentral2, 154 }, - { LocationNames.AustraliaEast, 150 }, - { LocationNames.AustraliaSoutheast, 146 }, - { LocationNames.AustriaEast, 210 }, - { LocationNames.BrazilSouth, 300 }, - { LocationNames.BrazilSoutheast, 300 }, - { LocationNames.CanadaCentral, 178 }, - { LocationNames.CanadaEast, 186 }, - { LocationNames.CentralIndia, 114 }, - { LocationNames.CentralUS, 158 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 56 }, - { LocationNames.EastUS, 182 }, - { LocationNames.EastUS2, 176 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 212 }, - { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyNorth, 224 }, - { LocationNames.GermanyWestCentral, 216 }, - { LocationNames.IsraelCentral, 138 }, - { LocationNames.ItalyNorth, 210 }, - { LocationNames.JapanEast, 30 }, - { LocationNames.JapanWest, 36 }, - { LocationNames.JioIndiaCentral, 114 }, - { LocationNames.JioIndiaWest, 114 }, - { LocationNames.KoreaCentral, 0 }, - { LocationNames.KoreaSouth, 6 }, - { LocationNames.MalaysiaSouth, 62 }, - { LocationNames.MexicoCentral, 122 }, - { LocationNames.NewZealandNorth, 154 }, - { LocationNames.NorthCentralUS, 165 }, - { LocationNames.NorthEurope, 233 }, - { LocationNames.NorwayEast, 242 }, - { LocationNames.NorwayWest, 236 }, - { LocationNames.PolandCentral, 222 }, - { LocationNames.QatarCentral, 138 }, - { LocationNames.SouthAfricaNorth, 360 }, - { LocationNames.SouthAfricaWest, 364 }, - { LocationNames.SouthCentralUS, 152 }, - { LocationNames.SoutheastAsia, 62 }, - { LocationNames.SouthIndia, 95 }, - { LocationNames.SpainCentral, 212 }, - { LocationNames.SwedenCentral, 242 }, - { LocationNames.SwedenSouth, 242 }, - { LocationNames.SwitzerlandNorth, 210 }, - { LocationNames.SwitzerlandWest, 206 }, - { LocationNames.TaiwanNorth, 56 }, - { LocationNames.TaiwanNorthwest, 56 }, - { LocationNames.UAECentral, 138 }, - { LocationNames.UAENorth, 138 }, - { LocationNames.UKSouth, 220 }, - { LocationNames.UKWest, 222 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 143 }, - { LocationNames.WestEurope, 222 }, - { LocationNames.WestIndia, 112 }, - { LocationNames.WestUS, 130 }, - { LocationNames.WestUS2, 122 }, - { LocationNames.WestUS3, 122 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.KoreaSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 148 }, - { LocationNames.AustraliaCentral2, 148 }, - { LocationNames.AustraliaEast, 143 }, - { LocationNames.AustraliaSoutheast, 140 }, - { LocationNames.AustriaEast, 204 }, - { LocationNames.BrazilSouth, 306 }, - { LocationNames.BrazilSoutheast, 306 }, - { LocationNames.CanadaCentral, 182 }, - { LocationNames.CanadaEast, 192 }, - { LocationNames.CentralIndia, 106 }, - { LocationNames.CentralUS, 162 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 60 }, - { LocationNames.EastUS, 186 }, - { LocationNames.EastUS2, 182 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 206 }, - { LocationNames.FranceSouth, 193 }, - { LocationNames.GermanyNorth, 218 }, - { LocationNames.GermanyWestCentral, 209 }, - { LocationNames.IsraelCentral, 132 }, - { LocationNames.ItalyNorth, 204 }, - { LocationNames.JapanEast, 35 }, - { LocationNames.JapanWest, 42 }, - { LocationNames.JioIndiaCentral, 106 }, - { LocationNames.JioIndiaWest, 106 }, - { LocationNames.KoreaCentral, 6 }, - { LocationNames.KoreaSouth, 0 }, - { LocationNames.MalaysiaSouth, 56 }, - { LocationNames.MexicoCentral, 126 }, - { LocationNames.NewZealandNorth, 148 }, - { LocationNames.NorthCentralUS, 170 }, - { LocationNames.NorthEurope, 226 }, - { LocationNames.NorwayEast, 235 }, - { LocationNames.NorwayWest, 228 }, - { LocationNames.PolandCentral, 216 }, - { LocationNames.QatarCentral, 132 }, - { LocationNames.SouthAfricaNorth, 354 }, - { LocationNames.SouthAfricaWest, 358 }, - { LocationNames.SouthCentralUS, 156 }, - { LocationNames.SoutheastAsia, 56 }, - { LocationNames.SouthIndia, 88 }, - { LocationNames.SpainCentral, 206 }, - { LocationNames.SwedenCentral, 235 }, - { LocationNames.SwedenSouth, 235 }, - { LocationNames.SwitzerlandNorth, 204 }, - { LocationNames.SwitzerlandWest, 200 }, - { LocationNames.TaiwanNorth, 60 }, - { LocationNames.TaiwanNorthwest, 60 }, - { LocationNames.UAECentral, 132 }, - { LocationNames.UAENorth, 130 }, - { LocationNames.UKSouth, 214 }, - { LocationNames.UKWest, 216 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 148 }, - { LocationNames.WestEurope, 216 }, - { LocationNames.WestIndia, 106 }, - { LocationNames.WestUS, 134 }, - { LocationNames.WestUS2, 126 }, - { LocationNames.WestUS3, 126 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.MalaysiaSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 94 }, - { LocationNames.AustraliaCentral2, 92 }, - { LocationNames.AustraliaEast, 88 }, - { LocationNames.AustraliaSoutheast, 85 }, - { LocationNames.AustriaEast, 148 }, - { LocationNames.BrazilSouth, 328 }, - { LocationNames.BrazilSoutheast, 328 }, - { LocationNames.CanadaCentral, 216 }, - { LocationNames.CanadaEast, 224 }, - { LocationNames.CentralIndia, 52 }, - { LocationNames.CentralUS, 194 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 33 }, - { LocationNames.EastUS, 218 }, - { LocationNames.EastUS2, 226 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 150 }, - { LocationNames.FranceSouth, 138 }, - { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyWestCentral, 154 }, - { LocationNames.IsraelCentral, 76 }, - { LocationNames.ItalyNorth, 148 }, - { LocationNames.JapanEast, 68 }, - { LocationNames.JapanWest, 74 }, - { LocationNames.JioIndiaCentral, 52 }, - { LocationNames.JioIndiaWest, 52 }, - { LocationNames.KoreaCentral, 62 }, - { LocationNames.KoreaSouth, 56 }, - { LocationNames.MalaysiaSouth, 0 }, - { LocationNames.MexicoCentral, 160 }, - { LocationNames.NewZealandNorth, 94 }, - { LocationNames.NorthCentralUS, 202 }, - { LocationNames.NorthEurope, 172 }, - { LocationNames.NorwayEast, 180 }, - { LocationNames.NorwayWest, 174 }, - { LocationNames.PolandCentral, 160 }, - { LocationNames.QatarCentral, 76 }, - { LocationNames.SouthAfricaNorth, 298 }, - { LocationNames.SouthAfricaWest, 302 }, - { LocationNames.SouthCentralUS, 200 }, - { LocationNames.SoutheastAsia, 100 }, - { LocationNames.SouthIndia, 34 }, - { LocationNames.SpainCentral, 150 }, - { LocationNames.SwedenCentral, 180 }, - { LocationNames.SwedenSouth, 180 }, - { LocationNames.SwitzerlandNorth, 148 }, - { LocationNames.SwitzerlandWest, 144 }, - { LocationNames.TaiwanNorth, 33 }, - { LocationNames.TaiwanNorthwest, 33 }, - { LocationNames.UAECentral, 76 }, - { LocationNames.UAENorth, 76 }, - { LocationNames.UKSouth, 158 }, - { LocationNames.UKWest, 161 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 180 }, - { LocationNames.WestEurope, 160 }, - { LocationNames.WestIndia, 50 }, - { LocationNames.WestUS, 168 }, - { LocationNames.WestUS2, 160 }, - { LocationNames.WestUS3, 160 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.MexicoCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 162 }, - { LocationNames.AustraliaCentral2, 162 }, - { LocationNames.AustraliaEast, 158 }, - { LocationNames.AustraliaSoutheast, 168 }, - { LocationNames.AustriaEast, 154 }, - { LocationNames.BrazilSouth, 182 }, - { LocationNames.BrazilSoutheast, 182 }, - { LocationNames.CanadaCentral, 57 }, - { LocationNames.CanadaEast, 66 }, - { LocationNames.CentralIndia, 212 }, - { LocationNames.CentralUS, 36 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 140 }, - { LocationNames.EastUS, 58 }, - { LocationNames.EastUS2, 68 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 140 }, - { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyWestCentral, 148 }, - { LocationNames.IsraelCentral, 236 }, - { LocationNames.ItalyNorth, 154 }, - { LocationNames.JapanEast, 112 }, - { LocationNames.JapanWest, 112 }, - { LocationNames.JioIndiaCentral, 212 }, - { LocationNames.JioIndiaWest, 212 }, - { LocationNames.KoreaCentral, 122 }, - { LocationNames.KoreaSouth, 126 }, - { LocationNames.MalaysiaSouth, 160 }, - { LocationNames.MexicoCentral, 0 }, - { LocationNames.NewZealandNorth, 162 }, - { LocationNames.NorthCentralUS, 44 }, - { LocationNames.NorthEurope, 136 }, - { LocationNames.NorwayEast, 164 }, - { LocationNames.NorwayWest, 156 }, - { LocationNames.PolandCentral, 142 }, - { LocationNames.QatarCentral, 236 }, - { LocationNames.SouthAfricaNorth, 296 }, - { LocationNames.SouthAfricaWest, 280 }, - { LocationNames.SouthCentralUS, 44 }, - { LocationNames.SoutheastAsia, 160 }, - { LocationNames.SouthIndia, 192 }, - { LocationNames.SpainCentral, 140 }, - { LocationNames.SwedenCentral, 164 }, - { LocationNames.SwedenSouth, 164 }, - { LocationNames.SwitzerlandNorth, 154 }, - { LocationNames.SwitzerlandWest, 146 }, - { LocationNames.TaiwanNorth, 140 }, - { LocationNames.TaiwanNorthwest, 140 }, - { LocationNames.UAECentral, 236 }, - { LocationNames.UAENorth, 236 }, - { LocationNames.UKSouth, 130 }, - { LocationNames.UKWest, 132 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 142 }, - { LocationNames.WestIndia, 210 }, - { LocationNames.WestUS, 22 }, - { LocationNames.WestUS2, 100 }, - { LocationNames.WestUS3, 100 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.NewZealandNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 100 }, - { LocationNames.AustraliaCentral2, 2 }, - { LocationNames.AustraliaEast, 6 }, - { LocationNames.AustraliaSoutheast, 18 }, - { LocationNames.AustriaEast, 240 }, - { LocationNames.BrazilSouth, 314 }, - { LocationNames.BrazilSoutheast, 314 }, - { LocationNames.CanadaCentral, 204 }, - { LocationNames.CanadaEast, 214 }, - { LocationNames.CentralIndia, 144 }, - { LocationNames.CentralUS, 184 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 120 }, - { LocationNames.EastUS, 205 }, - { LocationNames.EastUS2, 200 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 242 }, - { LocationNames.FranceSouth, 230 }, - { LocationNames.GermanyNorth, 254 }, - { LocationNames.GermanyWestCentral, 246 }, - { LocationNames.IsraelCentral, 168 }, - { LocationNames.ItalyNorth, 240 }, - { LocationNames.JapanEast, 125 }, - { LocationNames.JapanWest, 130 }, - { LocationNames.JioIndiaCentral, 144 }, - { LocationNames.JioIndiaWest, 144 }, - { LocationNames.KoreaCentral, 154 }, - { LocationNames.KoreaSouth, 148 }, - { LocationNames.MalaysiaSouth, 94 }, - { LocationNames.MexicoCentral, 162 }, - { LocationNames.NewZealandNorth, 0 }, - { LocationNames.NorthCentralUS, 192 }, - { LocationNames.NorthEurope, 262 }, - { LocationNames.NorwayEast, 272 }, - { LocationNames.NorwayWest, 266 }, - { LocationNames.PolandCentral, 252 }, - { LocationNames.QatarCentral, 168 }, - { LocationNames.SouthAfricaNorth, 390 }, - { LocationNames.SouthAfricaWest, 394 }, - { LocationNames.SouthCentralUS, 174 }, - { LocationNames.SoutheastAsia, 94 }, - { LocationNames.SouthIndia, 126 }, - { LocationNames.SpainCentral, 242 }, - { LocationNames.SwedenCentral, 272 }, - { LocationNames.SwedenSouth, 272 }, - { LocationNames.SwitzerlandNorth, 240 }, - { LocationNames.SwitzerlandWest, 236 }, - { LocationNames.TaiwanNorth, 120 }, - { LocationNames.TaiwanNorthwest, 120 }, - { LocationNames.UAECentral, 168 }, - { LocationNames.UAENorth, 168 }, - { LocationNames.UKSouth, 250 }, - { LocationNames.UKWest, 252 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 170 }, - { LocationNames.WestEurope, 252 }, - { LocationNames.WestIndia, 142 }, - { LocationNames.WestUS, 142 }, - { LocationNames.WestUS2, 162 }, - { LocationNames.WestUS3, 162 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.NorthCentralUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 192 }, - { LocationNames.AustraliaCentral2, 192 }, - { LocationNames.AustraliaEast, 187 }, - { LocationNames.AustraliaSoutheast, 198 }, - { LocationNames.AustriaEast, 110 }, - { LocationNames.BrazilSouth, 138 }, - { LocationNames.BrazilSoutheast, 138 }, - { LocationNames.CanadaCentral, 14 }, - { LocationNames.CanadaEast, 24 }, - { LocationNames.CentralIndia, 216 }, - { LocationNames.CentralUS, 8 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 184 }, - { LocationNames.EastUS, 19 }, - { LocationNames.EastUS2, 22 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 96 }, - { LocationNames.FranceSouth, 104 }, - { LocationNames.GermanyNorth, 112 }, - { LocationNames.GermanyWestCentral, 106 }, - { LocationNames.IsraelCentral, 209 }, - { LocationNames.ItalyNorth, 110 }, - { LocationNames.JapanEast, 148 }, - { LocationNames.JapanWest, 152 }, - { LocationNames.JioIndiaCentral, 216 }, - { LocationNames.JioIndiaWest, 216 }, - { LocationNames.KoreaCentral, 165 }, - { LocationNames.KoreaSouth, 170 }, - { LocationNames.MalaysiaSouth, 202 }, - { LocationNames.MexicoCentral, 44 }, - { LocationNames.NewZealandNorth, 192 }, - { LocationNames.NorthCentralUS, 0 }, - { LocationNames.NorthEurope, 90 }, - { LocationNames.NorwayEast, 122 }, - { LocationNames.NorwayWest, 114 }, - { LocationNames.PolandCentral, 102 }, - { LocationNames.QatarCentral, 209 }, - { LocationNames.SouthAfricaNorth, 253 }, - { LocationNames.SouthAfricaWest, 236 }, - { LocationNames.SouthCentralUS, 30 }, - { LocationNames.SoutheastAsia, 202 }, - { LocationNames.SouthIndia, 228 }, - { LocationNames.SpainCentral, 96 }, - { LocationNames.SwedenCentral, 122 }, - { LocationNames.SwedenSouth, 122 }, - { LocationNames.SwitzerlandNorth, 110 }, - { LocationNames.SwitzerlandWest, 106 }, - { LocationNames.TaiwanNorth, 184 }, - { LocationNames.TaiwanNorthwest, 184 }, - { LocationNames.UAECentral, 209 }, - { LocationNames.UAENorth, 212 }, - { LocationNames.UKSouth, 90 }, - { LocationNames.UKWest, 92 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 102 }, - { LocationNames.WestIndia, 218 }, - { LocationNames.WestUS, 50 }, - { LocationNames.WestUS2, 44 }, - { LocationNames.WestUS3, 44 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.NorthEurope, - new Dictionary() - { - { LocationNames.AustraliaCentral, 262 }, - { LocationNames.AustraliaCentral2, 262 }, - { LocationNames.AustraliaEast, 258 }, - { LocationNames.AustraliaSoutheast, 260 }, - { LocationNames.AustriaEast, 31 }, - { LocationNames.BrazilSouth, 177 }, - { LocationNames.BrazilSoutheast, 177 }, - { LocationNames.CanadaCentral, 84 }, - { LocationNames.CanadaEast, 93 }, - { LocationNames.CentralIndia, 137 }, - { LocationNames.CentralUS, 92 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 205 }, - { LocationNames.EastUS, 76 }, - { LocationNames.EastUS2, 75 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 27 }, - { LocationNames.FranceSouth, 31 }, - { LocationNames.GermanyNorth, 31 }, - { LocationNames.GermanyWestCentral, 25 }, - { LocationNames.IsraelCentral, 129 }, - { LocationNames.ItalyNorth, 31 }, - { LocationNames.JapanEast, 223 }, - { LocationNames.JapanWest, 236 }, - { LocationNames.JioIndiaCentral, 137 }, - { LocationNames.JioIndiaWest, 137 }, - { LocationNames.KoreaCentral, 233 }, - { LocationNames.KoreaSouth, 226 }, - { LocationNames.MalaysiaSouth, 172 }, - { LocationNames.MexicoCentral, 136 }, - { LocationNames.NewZealandNorth, 262 }, - { LocationNames.NorthCentralUS, 90 }, - { LocationNames.NorthEurope, 0 }, - { LocationNames.NorwayEast, 40 }, - { LocationNames.NorwayWest, 33 }, - { LocationNames.PolandCentral, 22 }, - { LocationNames.QatarCentral, 129 }, - { LocationNames.SouthAfricaNorth, 179 }, - { LocationNames.SouthAfricaWest, 157 }, - { LocationNames.SouthCentralUS, 106 }, - { LocationNames.SoutheastAsia, 172 }, - { LocationNames.SouthIndia, 149 }, - { LocationNames.SpainCentral, 27 }, - { LocationNames.SwedenCentral, 40 }, - { LocationNames.SwedenSouth, 40 }, - { LocationNames.SwitzerlandNorth, 31 }, - { LocationNames.SwitzerlandWest, 30 }, - { LocationNames.TaiwanNorth, 205 }, - { LocationNames.TaiwanNorthwest, 205 }, - { LocationNames.UAECentral, 129 }, - { LocationNames.UAENorth, 132 }, - { LocationNames.UKSouth, 21 }, - { LocationNames.UKWest, 17 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 110 }, - { LocationNames.WestEurope, 22 }, - { LocationNames.WestIndia, 139 }, - { LocationNames.WestUS, 133 }, - { LocationNames.WestUS2, 136 }, - { LocationNames.WestUS3, 136 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.NorwayEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, 272 }, - { LocationNames.AustraliaCentral2, 272 }, - { LocationNames.AustraliaEast, 266 }, - { LocationNames.AustraliaSoutheast, 264 }, - { LocationNames.AustriaEast, 32 }, - { LocationNames.BrazilSouth, 208 }, - { LocationNames.BrazilSoutheast, 208 }, - { LocationNames.CanadaCentral, 114 }, - { LocationNames.CanadaEast, 124 }, - { LocationNames.CentralIndia, 146 }, - { LocationNames.CentralUS, 128 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 214 }, - { LocationNames.EastUS, 101 }, - { LocationNames.EastUS2, 104 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 30 }, - { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 26 }, - { LocationNames.IsraelCentral, 138 }, - { LocationNames.ItalyNorth, 32 }, - { LocationNames.JapanEast, 254 }, - { LocationNames.JapanWest, 248 }, - { LocationNames.JioIndiaCentral, 146 }, - { LocationNames.JioIndiaWest, 146 }, - { LocationNames.KoreaCentral, 242 }, - { LocationNames.KoreaSouth, 235 }, - { LocationNames.MalaysiaSouth, 180 }, - { LocationNames.MexicoCentral, 164 }, - { LocationNames.NewZealandNorth, 272 }, - { LocationNames.NorthCentralUS, 122 }, - { LocationNames.NorthEurope, 40 }, - { LocationNames.NorwayEast, 0 }, - { LocationNames.NorwayWest, 8 }, - { LocationNames.PolandCentral, 22 }, - { LocationNames.QatarCentral, 138 }, - { LocationNames.SouthAfricaNorth, 186 }, - { LocationNames.SouthAfricaWest, 170 }, - { LocationNames.SouthCentralUS, 132 }, - { LocationNames.SoutheastAsia, 180 }, - { LocationNames.SouthIndia, 157 }, - { LocationNames.SpainCentral, 30 }, - { LocationNames.SwedenCentral, 20 }, - { LocationNames.SwedenSouth, 20 }, - { LocationNames.SwitzerlandNorth, 32 }, - { LocationNames.SwitzerlandWest, 36 }, - { LocationNames.TaiwanNorth, 214 }, - { LocationNames.TaiwanNorthwest, 214 }, - { LocationNames.UAECentral, 138 }, - { LocationNames.UAENorth, 140 }, - { LocationNames.UKSouth, 28 }, - { LocationNames.UKWest, 30 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 142 }, - { LocationNames.WestEurope, 22 }, - { LocationNames.WestIndia, 146 }, - { LocationNames.WestUS, 163 }, - { LocationNames.WestUS2, 164 }, - { LocationNames.WestUS3, 164 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.NorwayWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 266 }, - { LocationNames.AustraliaCentral2, 266 }, - { LocationNames.AustraliaEast, 260 }, - { LocationNames.AustraliaSoutheast, 258 }, - { LocationNames.AustriaEast, 26 }, - { LocationNames.BrazilSouth, 201 }, - { LocationNames.BrazilSoutheast, 201 }, - { LocationNames.CanadaCentral, 108 }, - { LocationNames.CanadaEast, 116 }, - { LocationNames.CentralIndia, 136 }, - { LocationNames.CentralUS, 121 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 206 }, - { LocationNames.EastUS, 94 }, - { LocationNames.EastUS2, 98 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 24 }, - { LocationNames.FranceSouth, 36 }, - { LocationNames.GermanyNorth, 26 }, - { LocationNames.GermanyWestCentral, 20 }, - { LocationNames.IsraelCentral, 130 }, - { LocationNames.ItalyNorth, 26 }, - { LocationNames.JapanEast, 248 }, - { LocationNames.JapanWest, 240 }, - { LocationNames.JioIndiaCentral, 136 }, - { LocationNames.JioIndiaWest, 136 }, - { LocationNames.KoreaCentral, 236 }, - { LocationNames.KoreaSouth, 228 }, - { LocationNames.MalaysiaSouth, 174 }, - { LocationNames.MexicoCentral, 156 }, - { LocationNames.NewZealandNorth, 266 }, - { LocationNames.NorthCentralUS, 114 }, - { LocationNames.NorthEurope, 33 }, - { LocationNames.NorwayEast, 8 }, - { LocationNames.NorwayWest, 0 }, - { LocationNames.PolandCentral, 15 }, - { LocationNames.QatarCentral, 130 }, - { LocationNames.SouthAfricaNorth, 179 }, - { LocationNames.SouthAfricaWest, 162 }, - { LocationNames.SouthCentralUS, 124 }, - { LocationNames.SoutheastAsia, 174 }, - { LocationNames.SouthIndia, 150 }, - { LocationNames.SpainCentral, 24 }, - { LocationNames.SwedenCentral, 20 }, - { LocationNames.SwedenSouth, 20 }, - { LocationNames.SwitzerlandNorth, 26 }, - { LocationNames.SwitzerlandWest, 30 }, - { LocationNames.TaiwanNorth, 206 }, - { LocationNames.TaiwanNorthwest, 206 }, - { LocationNames.UAECentral, 130 }, - { LocationNames.UAENorth, 134 }, - { LocationNames.UKSouth, 22 }, - { LocationNames.UKWest, 24 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 136 }, - { LocationNames.WestEurope, 15 }, - { LocationNames.WestIndia, 140 }, - { LocationNames.WestUS, 156 }, - { LocationNames.WestUS2, 156 }, - { LocationNames.WestUS3, 156 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.PolandCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 252 }, - { LocationNames.AustraliaCentral2, 252 }, - { LocationNames.AustraliaEast, 248 }, - { LocationNames.AustraliaSoutheast, 244 }, - { LocationNames.AustriaEast, 12 }, - { LocationNames.BrazilSouth, 188 }, - { LocationNames.BrazilSoutheast, 188 }, - { LocationNames.CanadaCentral, 94 }, - { LocationNames.CanadaEast, 103 }, - { LocationNames.CentralIndia, 126 }, - { LocationNames.CentralUS, 102 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 193 }, - { LocationNames.EastUS, 81 }, - { LocationNames.EastUS2, 86 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 10 }, - { LocationNames.FranceSouth, 20 }, - { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyWestCentral, 8 }, - { LocationNames.IsraelCentral, 118 }, - { LocationNames.ItalyNorth, 12 }, - { LocationNames.JapanEast, 234 }, - { LocationNames.JapanWest, 228 }, - { LocationNames.JioIndiaCentral, 126 }, - { LocationNames.JioIndiaWest, 126 }, - { LocationNames.KoreaCentral, 222 }, - { LocationNames.KoreaSouth, 216 }, - { LocationNames.MalaysiaSouth, 160 }, - { LocationNames.MexicoCentral, 142 }, - { LocationNames.NewZealandNorth, 252 }, - { LocationNames.NorthCentralUS, 102 }, - { LocationNames.NorthEurope, 22 }, - { LocationNames.NorwayEast, 22 }, - { LocationNames.NorwayWest, 15 }, - { LocationNames.PolandCentral, 0 }, - { LocationNames.QatarCentral, 118 }, - { LocationNames.SouthAfricaNorth, 170 }, - { LocationNames.SouthAfricaWest, 152 }, - { LocationNames.SouthCentralUS, 112 }, - { LocationNames.SoutheastAsia, 160 }, - { LocationNames.SouthIndia, 136 }, - { LocationNames.SpainCentral, 10 }, - { LocationNames.SwedenCentral, 22 }, - { LocationNames.SwedenSouth, 22 }, - { LocationNames.SwitzerlandNorth, 12 }, - { LocationNames.SwitzerlandWest, 16 }, - { LocationNames.TaiwanNorth, 193 }, - { LocationNames.TaiwanNorthwest, 193 }, - { LocationNames.UAECentral, 118 }, - { LocationNames.UAENorth, 120 }, - { LocationNames.UKSouth, 10 }, - { LocationNames.UKWest, 12 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 120 }, - { LocationNames.WestEurope, 100 }, - { LocationNames.WestIndia, 128 }, - { LocationNames.WestUS, 144 }, - { LocationNames.WestUS2, 142 }, - { LocationNames.WestUS3, 142 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.QatarCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 168 }, - { LocationNames.AustraliaCentral2, 168 }, - { LocationNames.AustraliaEast, 164 }, - { LocationNames.AustraliaSoutheast, 160 }, - { LocationNames.AustriaEast, 106 }, - { LocationNames.BrazilSouth, 296 }, - { LocationNames.BrazilSoutheast, 296 }, - { LocationNames.CanadaCentral, 201 }, - { LocationNames.CanadaEast, 210 }, - { LocationNames.CentralIndia, 30 }, - { LocationNames.CentralUS, 216 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 110 }, - { LocationNames.EastUS, 189 }, - { LocationNames.EastUS2, 190 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 108 }, - { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyWestCentral, 112 }, - { LocationNames.IsraelCentral, 4 }, - { LocationNames.ItalyNorth, 106 }, - { LocationNames.JapanEast, 144 }, - { LocationNames.JapanWest, 149 }, - { LocationNames.JioIndiaCentral, 30 }, - { LocationNames.JioIndiaWest, 30 }, - { LocationNames.KoreaCentral, 138 }, - { LocationNames.KoreaSouth, 132 }, - { LocationNames.MalaysiaSouth, 76 }, - { LocationNames.MexicoCentral, 236 }, - { LocationNames.NewZealandNorth, 168 }, - { LocationNames.NorthCentralUS, 209 }, - { LocationNames.NorthEurope, 129 }, - { LocationNames.NorwayEast, 138 }, - { LocationNames.NorwayWest, 130 }, - { LocationNames.PolandCentral, 118 }, - { LocationNames.QatarCentral, 0 }, - { LocationNames.SouthAfricaNorth, 256 }, - { LocationNames.SouthAfricaWest, 260 }, - { LocationNames.SouthCentralUS, 218 }, - { LocationNames.SoutheastAsia, 76 }, - { LocationNames.SouthIndia, 46 }, - { LocationNames.SpainCentral, 108 }, - { LocationNames.SwedenCentral, 129 }, - { LocationNames.SwedenSouth, 129 }, - { LocationNames.SwitzerlandNorth, 106 }, - { LocationNames.SwitzerlandWest, 102 }, - { LocationNames.TaiwanNorth, 110 }, - { LocationNames.TaiwanNorthwest, 110 }, - { LocationNames.UAECentral, 4 }, - { LocationNames.UAENorth, 4 }, - { LocationNames.UKSouth, 116 }, - { LocationNames.UKWest, 118 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 230 }, - { LocationNames.WestEurope, 118 }, - { LocationNames.WestIndia, 28 }, - { LocationNames.WestUS, 244 }, - { LocationNames.WestUS2, 236 }, - { LocationNames.WestUS3, 236 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SouthAfricaNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 390 }, - { LocationNames.AustraliaCentral2, 391 }, - { LocationNames.AustraliaEast, 386 }, - { LocationNames.AustraliaSoutheast, 382 }, - { LocationNames.AustriaEast, 172 }, - { LocationNames.BrazilSouth, 342 }, - { LocationNames.BrazilSoutheast, 342 }, - { LocationNames.CanadaCentral, 246 }, - { LocationNames.CanadaEast, 256 }, - { LocationNames.CentralIndia, 264 }, - { LocationNames.CentralUS, 260 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 332 }, - { LocationNames.EastUS, 234 }, - { LocationNames.EastUS2, 240 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 166 }, - { LocationNames.FranceSouth, 162 }, - { LocationNames.GermanyNorth, 178 }, - { LocationNames.GermanyWestCentral, 178 }, - { LocationNames.IsraelCentral, 256 }, - { LocationNames.ItalyNorth, 172 }, - { LocationNames.JapanEast, 366 }, - { LocationNames.JapanWest, 366 }, - { LocationNames.JioIndiaCentral, 264 }, - { LocationNames.JioIndiaWest, 264 }, - { LocationNames.KoreaCentral, 360 }, - { LocationNames.KoreaSouth, 354 }, - { LocationNames.MalaysiaSouth, 298 }, - { LocationNames.MexicoCentral, 296 }, - { LocationNames.NewZealandNorth, 390 }, - { LocationNames.NorthCentralUS, 253 }, - { LocationNames.NorthEurope, 179 }, - { LocationNames.NorwayEast, 186 }, - { LocationNames.NorwayWest, 179 }, - { LocationNames.PolandCentral, 170 }, - { LocationNames.QatarCentral, 256 }, - { LocationNames.SouthAfricaNorth, 0 }, - { LocationNames.SouthAfricaWest, 18 }, - { LocationNames.SouthCentralUS, 264 }, - { LocationNames.SoutheastAsia, 298 }, - { LocationNames.SouthIndia, 276 }, - { LocationNames.SpainCentral, 166 }, - { LocationNames.SwedenCentral, 186 }, - { LocationNames.SwedenSouth, 186 }, - { LocationNames.SwitzerlandNorth, 172 }, - { LocationNames.SwitzerlandWest, 168 }, - { LocationNames.TaiwanNorth, 332 }, - { LocationNames.TaiwanNorthwest, 332 }, - { LocationNames.UAECentral, 256 }, - { LocationNames.UAENorth, 260 }, - { LocationNames.UKSouth, 160 }, - { LocationNames.UKWest, 164 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 274 }, - { LocationNames.WestEurope, 170 }, - { LocationNames.WestIndia, 266 }, - { LocationNames.WestUS, 298 }, - { LocationNames.WestUS2, 296 }, - { LocationNames.WestUS3, 296 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SouthAfricaWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 394 }, - { LocationNames.AustraliaCentral2, 392 }, - { LocationNames.AustraliaEast, 390 }, - { LocationNames.AustraliaSoutheast, 386 }, - { LocationNames.AustriaEast, 162 }, - { LocationNames.BrazilSouth, 326 }, - { LocationNames.BrazilSoutheast, 326 }, - { LocationNames.CanadaCentral, 230 }, - { LocationNames.CanadaEast, 238 }, - { LocationNames.CentralIndia, 267 }, - { LocationNames.CentralUS, 244 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 336 }, - { LocationNames.EastUS, 218 }, - { LocationNames.EastUS2, 222 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 150 }, - { LocationNames.FranceSouth, 166 }, - { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyWestCentral, 156 }, - { LocationNames.IsraelCentral, 260 }, - { LocationNames.ItalyNorth, 162 }, - { LocationNames.JapanEast, 370 }, - { LocationNames.JapanWest, 370 }, - { LocationNames.JioIndiaCentral, 267 }, - { LocationNames.JioIndiaWest, 267 }, - { LocationNames.KoreaCentral, 364 }, - { LocationNames.KoreaSouth, 358 }, - { LocationNames.MalaysiaSouth, 302 }, - { LocationNames.MexicoCentral, 280 }, - { LocationNames.NewZealandNorth, 394 }, - { LocationNames.NorthCentralUS, 236 }, - { LocationNames.NorthEurope, 157 }, - { LocationNames.NorwayEast, 170 }, - { LocationNames.NorwayWest, 162 }, - { LocationNames.PolandCentral, 152 }, - { LocationNames.QatarCentral, 260 }, - { LocationNames.SouthAfricaNorth, 18 }, - { LocationNames.SouthAfricaWest, 0 }, - { LocationNames.SouthCentralUS, 248 }, - { LocationNames.SoutheastAsia, 302 }, - { LocationNames.SouthIndia, 280 }, - { LocationNames.SpainCentral, 150 }, - { LocationNames.SwedenCentral, 170 }, - { LocationNames.SwedenSouth, 170 }, - { LocationNames.SwitzerlandNorth, 162 }, - { LocationNames.SwitzerlandWest, 158 }, - { LocationNames.TaiwanNorth, 336 }, - { LocationNames.TaiwanNorthwest, 336 }, - { LocationNames.UAECentral, 260 }, - { LocationNames.UAENorth, 264 }, - { LocationNames.UKSouth, 144 }, - { LocationNames.UKWest, 146 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 258 }, - { LocationNames.WestEurope, 152 }, - { LocationNames.WestIndia, 270 }, - { LocationNames.WestUS, 280 }, - { LocationNames.WestUS2, 280 }, - { LocationNames.WestUS3, 280 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SouthCentralUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 174 }, - { LocationNames.AustraliaCentral2, 174 }, - { LocationNames.AustraliaEast, 170 }, - { LocationNames.AustraliaSoutheast, 180 }, - { LocationNames.AustriaEast, 118 }, - { LocationNames.BrazilSouth, 140 }, - { LocationNames.BrazilSoutheast, 140 }, - { LocationNames.CanadaCentral, 42 }, - { LocationNames.CanadaEast, 52 }, - { LocationNames.CentralIndia, 224 }, - { LocationNames.CentralUS, 22 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 182 }, - { LocationNames.EastUS, 32 }, - { LocationNames.EastUS2, 26 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 106 }, - { LocationNames.FranceSouth, 116 }, - { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyWestCentral, 116 }, - { LocationNames.IsraelCentral, 218 }, - { LocationNames.ItalyNorth, 118 }, - { LocationNames.JapanEast, 138 }, - { LocationNames.JapanWest, 138 }, - { LocationNames.JioIndiaCentral, 224 }, - { LocationNames.JioIndiaWest, 224 }, - { LocationNames.KoreaCentral, 152 }, - { LocationNames.KoreaSouth, 156 }, - { LocationNames.MalaysiaSouth, 200 }, - { LocationNames.MexicoCentral, 44 }, - { LocationNames.NewZealandNorth, 174 }, - { LocationNames.NorthCentralUS, 30 }, - { LocationNames.NorthEurope, 106 }, - { LocationNames.NorwayEast, 132 }, - { LocationNames.NorwayWest, 124 }, - { LocationNames.PolandCentral, 112 }, - { LocationNames.QatarCentral, 218 }, - { LocationNames.SouthAfricaNorth, 264 }, - { LocationNames.SouthAfricaWest, 248 }, - { LocationNames.SouthCentralUS, 0 }, - { LocationNames.SoutheastAsia, 200 }, - { LocationNames.SouthIndia, 222 }, - { LocationNames.SpainCentral, 106 }, - { LocationNames.SwedenCentral, 132 }, - { LocationNames.SwedenSouth, 132 }, - { LocationNames.SwitzerlandNorth, 118 }, - { LocationNames.SwitzerlandWest, 116 }, - { LocationNames.TaiwanNorth, 182 }, - { LocationNames.TaiwanNorthwest, 182 }, - { LocationNames.UAECentral, 218 }, - { LocationNames.UAENorth, 220 }, - { LocationNames.UKSouth, 104 }, - { LocationNames.UKWest, 106 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 112 }, - { LocationNames.WestIndia, 226 }, - { LocationNames.WestUS, 34 }, - { LocationNames.WestUS2, 44 }, - { LocationNames.WestUS3, 44 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SoutheastAsia, - new Dictionary() - { - { LocationNames.AustraliaCentral, 94 }, - { LocationNames.AustraliaCentral2, 92 }, - { LocationNames.AustraliaEast, 88 }, - { LocationNames.AustraliaSoutheast, 85 }, - { LocationNames.AustriaEast, 148 }, - { LocationNames.BrazilSouth, 328 }, - { LocationNames.BrazilSoutheast, 328 }, - { LocationNames.CanadaCentral, 216 }, - { LocationNames.CanadaEast, 224 }, - { LocationNames.CentralIndia, 52 }, - { LocationNames.CentralUS, 194 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 33 }, - { LocationNames.EastUS, 218 }, - { LocationNames.EastUS2, 226 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 150 }, - { LocationNames.FranceSouth, 138 }, - { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyWestCentral, 154 }, - { LocationNames.IsraelCentral, 76 }, - { LocationNames.ItalyNorth, 148 }, - { LocationNames.JapanEast, 68 }, - { LocationNames.JapanWest, 74 }, - { LocationNames.JioIndiaCentral, 52 }, - { LocationNames.JioIndiaWest, 52 }, - { LocationNames.KoreaCentral, 62 }, - { LocationNames.KoreaSouth, 56 }, - { LocationNames.MalaysiaSouth, 100 }, - { LocationNames.MexicoCentral, 160 }, - { LocationNames.NewZealandNorth, 94 }, - { LocationNames.NorthCentralUS, 202 }, - { LocationNames.NorthEurope, 172 }, - { LocationNames.NorwayEast, 180 }, - { LocationNames.NorwayWest, 174 }, - { LocationNames.PolandCentral, 160 }, - { LocationNames.QatarCentral, 76 }, - { LocationNames.SouthAfricaNorth, 298 }, - { LocationNames.SouthAfricaWest, 302 }, - { LocationNames.SouthCentralUS, 200 }, - { LocationNames.SoutheastAsia, 0 }, - { LocationNames.SouthIndia, 34 }, - { LocationNames.SpainCentral, 150 }, - { LocationNames.SwedenCentral, 180 }, - { LocationNames.SwedenSouth, 180 }, - { LocationNames.SwitzerlandNorth, 148 }, - { LocationNames.SwitzerlandWest, 144 }, - { LocationNames.TaiwanNorth, 33 }, - { LocationNames.TaiwanNorthwest, 33 }, - { LocationNames.UAECentral, 76 }, - { LocationNames.UAENorth, 76 }, - { LocationNames.UKSouth, 158 }, - { LocationNames.UKWest, 161 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 180 }, - { LocationNames.WestEurope, 160 }, - { LocationNames.WestIndia, 50 }, - { LocationNames.WestUS, 168 }, - { LocationNames.WestUS2, 160 }, - { LocationNames.WestUS3, 160 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SouthIndia, - new Dictionary() - { - { LocationNames.AustraliaCentral, 126 }, - { LocationNames.AustraliaCentral2, 124 }, - { LocationNames.AustraliaEast, 120 }, - { LocationNames.AustraliaSoutheast, 118 }, - { LocationNames.AustriaEast, 126 }, - { LocationNames.BrazilSouth, 314 }, - { LocationNames.BrazilSoutheast, 314 }, - { LocationNames.CanadaCentral, 220 }, - { LocationNames.CanadaEast, 230 }, - { LocationNames.CentralIndia, 22 }, - { LocationNames.CentralUS, 228 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 66 }, - { LocationNames.EastUS, 208 }, - { LocationNames.EastUS2, 210 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 128 }, - { LocationNames.FranceSouth, 114 }, - { LocationNames.GermanyNorth, 140 }, - { LocationNames.GermanyWestCentral, 130 }, - { LocationNames.IsraelCentral, 46 }, - { LocationNames.ItalyNorth, 126 }, - { LocationNames.JapanEast, 100 }, - { LocationNames.JapanWest, 104 }, - { LocationNames.JioIndiaCentral, 22 }, - { LocationNames.JioIndiaWest, 22 }, - { LocationNames.KoreaCentral, 95 }, - { LocationNames.KoreaSouth, 88 }, - { LocationNames.MalaysiaSouth, 34 }, - { LocationNames.MexicoCentral, 192 }, - { LocationNames.NewZealandNorth, 126 }, - { LocationNames.NorthCentralUS, 228 }, - { LocationNames.NorthEurope, 149 }, - { LocationNames.NorwayEast, 157 }, - { LocationNames.NorwayWest, 150 }, - { LocationNames.PolandCentral, 136 }, - { LocationNames.QatarCentral, 46 }, - { LocationNames.SouthAfricaNorth, 276 }, - { LocationNames.SouthAfricaWest, 280 }, - { LocationNames.SouthCentralUS, 222 }, - { LocationNames.SoutheastAsia, 34 }, - { LocationNames.SouthIndia, 0 }, - { LocationNames.SpainCentral, 128 }, - { LocationNames.SwedenCentral, 157 }, - { LocationNames.SwedenSouth, 157 }, - { LocationNames.SwitzerlandNorth, 126 }, - { LocationNames.SwitzerlandWest, 122 }, - { LocationNames.TaiwanNorth, 66 }, - { LocationNames.TaiwanNorthwest, 66 }, - { LocationNames.UAECentral, 46 }, - { LocationNames.UAENorth, 46 }, - { LocationNames.UKSouth, 134 }, - { LocationNames.UKWest, 138 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 212 }, - { LocationNames.WestEurope, 136 }, - { LocationNames.WestIndia, 20 }, - { LocationNames.WestUS, 200 }, - { LocationNames.WestUS2, 192 }, - { LocationNames.WestUS3, 192 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SpainCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 242 }, - { LocationNames.AustraliaCentral2, 242 }, - { LocationNames.AustraliaEast, 238 }, - { LocationNames.AustraliaSoutheast, 235 }, - { LocationNames.AustriaEast, 14 }, - { LocationNames.BrazilSouth, 186 }, - { LocationNames.BrazilSoutheast, 186 }, - { LocationNames.CanadaCentral, 92 }, - { LocationNames.CanadaEast, 102 }, - { LocationNames.CentralIndia, 116 }, - { LocationNames.CentralUS, 101 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 184 }, - { LocationNames.EastUS, 80 }, - { LocationNames.EastUS2, 80 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 100 }, - { LocationNames.FranceSouth, 11 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 10 }, - { LocationNames.IsraelCentral, 108 }, - { LocationNames.ItalyNorth, 14 }, - { LocationNames.JapanEast, 218 }, - { LocationNames.JapanWest, 218 }, - { LocationNames.JioIndiaCentral, 116 }, - { LocationNames.JioIndiaWest, 116 }, - { LocationNames.KoreaCentral, 212 }, - { LocationNames.KoreaSouth, 206 }, - { LocationNames.MalaysiaSouth, 150 }, - { LocationNames.MexicoCentral, 140 }, - { LocationNames.NewZealandNorth, 242 }, - { LocationNames.NorthCentralUS, 96 }, - { LocationNames.NorthEurope, 27 }, - { LocationNames.NorwayEast, 30 }, - { LocationNames.NorwayWest, 24 }, - { LocationNames.PolandCentral, 10 }, - { LocationNames.QatarCentral, 108 }, - { LocationNames.SouthAfricaNorth, 166 }, - { LocationNames.SouthAfricaWest, 150 }, - { LocationNames.SouthCentralUS, 106 }, - { LocationNames.SoutheastAsia, 150 }, - { LocationNames.SouthIndia, 128 }, - { LocationNames.SpainCentral, 0 }, - { LocationNames.SwedenCentral, 30 }, - { LocationNames.SwedenSouth, 30 }, - { LocationNames.SwitzerlandNorth, 14 }, - { LocationNames.SwitzerlandWest, 10 }, - { LocationNames.TaiwanNorth, 184 }, - { LocationNames.TaiwanNorthwest, 184 }, - { LocationNames.UAECentral, 108 }, - { LocationNames.UAENorth, 112 }, - { LocationNames.UKSouth, 7 }, - { LocationNames.UKWest, 8 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 119 }, - { LocationNames.WestEurope, 10 }, - { LocationNames.WestIndia, 118 }, - { LocationNames.WestUS, 138 }, - { LocationNames.WestUS2, 140 }, - { LocationNames.WestUS3, 140 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SwedenCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 272 }, - { LocationNames.AustraliaCentral2, 272 }, - { LocationNames.AustraliaEast, 266 }, - { LocationNames.AustraliaSoutheast, 264 }, - { LocationNames.AustriaEast, 32 }, - { LocationNames.BrazilSouth, 208 }, - { LocationNames.BrazilSoutheast, 208 }, - { LocationNames.CanadaCentral, 114 }, - { LocationNames.CanadaEast, 124 }, - { LocationNames.CentralIndia, 146 }, - { LocationNames.CentralUS, 128 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 214 }, - { LocationNames.EastUS, 101 }, - { LocationNames.EastUS2, 104 }, - { LocationNames.EastUSSLV, 255 }, - { LocationNames.FranceCentral, 30 }, - { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 26 }, - { LocationNames.IsraelCentral, 129 }, - { LocationNames.ItalyNorth, 32 }, - { LocationNames.JapanEast, 254 }, - { LocationNames.JapanWest, 248 }, - { LocationNames.JioIndiaCentral, 146 }, - { LocationNames.JioIndiaWest, 146 }, - { LocationNames.KoreaCentral, 242 }, - { LocationNames.KoreaSouth, 235 }, - { LocationNames.MalaysiaSouth, 180 }, - { LocationNames.MexicoCentral, 164 }, - { LocationNames.NewZealandNorth, 272 }, - { LocationNames.NorthCentralUS, 122 }, - { LocationNames.NorthEurope, 40 }, - { LocationNames.NorwayEast, 10 }, - { LocationNames.NorwayWest, 10 }, - { LocationNames.PolandCentral, 22 }, - { LocationNames.QatarCentral, 138 }, - { LocationNames.SouthAfricaNorth, 186 }, - { LocationNames.SouthAfricaWest, 170 }, - { LocationNames.SouthCentralUS, 132 }, - { LocationNames.SoutheastAsia, 180 }, - { LocationNames.SouthIndia, 157 }, - { LocationNames.SpainCentral, 30 }, - { LocationNames.SwedenCentral, 0 }, - { LocationNames.SwedenSouth, 10 }, - { LocationNames.SwitzerlandNorth, 32 }, - { LocationNames.SwitzerlandWest, 36 }, - { LocationNames.TaiwanNorth, 214 }, - { LocationNames.TaiwanNorthwest, 214 }, - { LocationNames.UAECentral, 138 }, - { LocationNames.UAENorth, 140 }, - { LocationNames.UKSouth, 28 }, - { LocationNames.UKWest, 30 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 142 }, - { LocationNames.WestEurope, 22 }, - { LocationNames.WestIndia, 146 }, - { LocationNames.WestUS, 163 }, - { LocationNames.WestUS2, 164 }, - { LocationNames.WestUS3, 164 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SwedenSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 272 }, - { LocationNames.AustraliaCentral2, 272 }, - { LocationNames.AustraliaEast, 266 }, - { LocationNames.AustraliaSoutheast, 264 }, - { LocationNames.AustriaEast, 255 }, - { LocationNames.BrazilSouth, 208 }, - { LocationNames.BrazilSoutheast, 208 }, - { LocationNames.CanadaCentral, 114 }, - { LocationNames.CanadaEast, 124 }, - { LocationNames.CentralIndia, 146 }, - { LocationNames.CentralUS, 128 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 214 }, - { LocationNames.EastUS, 101 }, - { LocationNames.EastUS2, 104 }, - { LocationNames.EastUSSLV, 255 }, - { LocationNames.FranceCentral, 30 }, - { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 26 }, - { LocationNames.IsraelCentral, 129 }, - { LocationNames.ItalyNorth, 255 }, - { LocationNames.JapanEast, 254 }, - { LocationNames.JapanWest, 248 }, - { LocationNames.JioIndiaCentral, 146 }, - { LocationNames.JioIndiaWest, 146 }, - { LocationNames.KoreaCentral, 242 }, - { LocationNames.KoreaSouth, 235 }, - { LocationNames.MalaysiaSouth, 180 }, - { LocationNames.MexicoCentral, 164 }, - { LocationNames.NewZealandNorth, 272 }, - { LocationNames.NorthCentralUS, 122 }, - { LocationNames.NorthEurope, 40 }, - { LocationNames.NorwayEast, 10 }, - { LocationNames.NorwayWest, 10 }, - { LocationNames.PolandCentral, 22 }, - { LocationNames.QatarCentral, 138 }, - { LocationNames.SouthAfricaNorth, 186 }, - { LocationNames.SouthAfricaWest, 170 }, - { LocationNames.SouthCentralUS, 132 }, - { LocationNames.SoutheastAsia, 180 }, - { LocationNames.SouthIndia, 157 }, - { LocationNames.SpainCentral, 30 }, - { LocationNames.SwedenCentral, 5 }, - { LocationNames.SwedenSouth, 0 }, - { LocationNames.SwitzerlandNorth, 32 }, - { LocationNames.SwitzerlandWest, 36 }, - { LocationNames.TaiwanNorth, 214 }, - { LocationNames.TaiwanNorthwest, 214 }, - { LocationNames.UAECentral, 138 }, - { LocationNames.UAENorth, 140 }, - { LocationNames.UKSouth, 28 }, - { LocationNames.UKWest, 28 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 142 }, - { LocationNames.WestEurope, 22 }, - { LocationNames.WestIndia, 146 }, - { LocationNames.WestUS, 163 }, - { LocationNames.WestUS2, 164 }, - { LocationNames.WestUS3, 164 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SwitzerlandNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 240 }, - { LocationNames.AustraliaCentral2, 240 }, - { LocationNames.AustraliaEast, 236 }, - { LocationNames.AustraliaSoutheast, 232 }, - { LocationNames.AustriaEast, 100 }, - { LocationNames.BrazilSouth, 198 }, - { LocationNames.BrazilSoutheast, 198 }, - { LocationNames.CanadaCentral, 104 }, - { LocationNames.CanadaEast, 114 }, - { LocationNames.CentralIndia, 112 }, - { LocationNames.CentralUS, 112 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 182 }, - { LocationNames.EastUS, 92 }, - { LocationNames.EastUS2, 94 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 14 }, - { LocationNames.FranceSouth, 10 }, - { LocationNames.GermanyNorth, 16 }, - { LocationNames.GermanyWestCentral, 6 }, - { LocationNames.IsraelCentral, 106 }, - { LocationNames.ItalyNorth, 100 }, - { LocationNames.JapanEast, 216 }, - { LocationNames.JapanWest, 216 }, - { LocationNames.JioIndiaCentral, 112 }, - { LocationNames.JioIndiaWest, 112 }, - { LocationNames.KoreaCentral, 210 }, - { LocationNames.KoreaSouth, 204 }, - { LocationNames.MalaysiaSouth, 148 }, - { LocationNames.MexicoCentral, 154 }, - { LocationNames.NewZealandNorth, 240 }, - { LocationNames.NorthCentralUS, 110 }, - { LocationNames.NorthEurope, 31 }, - { LocationNames.NorwayEast, 32 }, - { LocationNames.NorwayWest, 26 }, - { LocationNames.PolandCentral, 12 }, - { LocationNames.QatarCentral, 106 }, - { LocationNames.SouthAfricaNorth, 172 }, - { LocationNames.SouthAfricaWest, 162 }, - { LocationNames.SouthCentralUS, 118 }, - { LocationNames.SoutheastAsia, 148 }, - { LocationNames.SouthIndia, 126 }, - { LocationNames.SpainCentral, 14 }, - { LocationNames.SwedenCentral, 32 }, - { LocationNames.SwedenSouth, 255 }, - { LocationNames.SwitzerlandNorth, 0 }, - { LocationNames.SwitzerlandWest, 4 }, - { LocationNames.TaiwanNorth, 182 }, - { LocationNames.TaiwanNorthwest, 182 }, - { LocationNames.UAECentral, 106 }, - { LocationNames.UAENorth, 108 }, - { LocationNames.UKSouth, 20 }, - { LocationNames.UKWest, 22 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 134 }, - { LocationNames.WestEurope, 12 }, - { LocationNames.WestIndia, 116 }, - { LocationNames.WestUS, 150 }, - { LocationNames.WestUS2, 154 }, - { LocationNames.WestUS3, 154 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.SwitzerlandWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 236 }, - { LocationNames.AustraliaCentral2, 236 }, - { LocationNames.AustraliaEast, 232 }, - { LocationNames.AustraliaSoutheast, 228 }, - { LocationNames.AustriaEast, 4 }, - { LocationNames.BrazilSouth, 202 }, - { LocationNames.BrazilSoutheast, 202 }, - { LocationNames.CanadaCentral, 108 }, - { LocationNames.CanadaEast, 118 }, - { LocationNames.CentralIndia, 110 }, - { LocationNames.CentralUS, 110 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 178 }, - { LocationNames.EastUS, 88 }, - { LocationNames.EastUS2, 88 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 10 }, - { LocationNames.FranceSouth, 8 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 10 }, - { LocationNames.IsraelCentral, 102 }, - { LocationNames.ItalyNorth, 4 }, - { LocationNames.JapanEast, 212 }, - { LocationNames.JapanWest, 210 }, - { LocationNames.JioIndiaCentral, 110 }, - { LocationNames.JioIndiaWest, 110 }, - { LocationNames.KoreaCentral, 206 }, - { LocationNames.KoreaSouth, 200 }, - { LocationNames.MalaysiaSouth, 144 }, - { LocationNames.MexicoCentral, 146 }, - { LocationNames.NewZealandNorth, 236 }, - { LocationNames.NorthCentralUS, 106 }, - { LocationNames.NorthEurope, 30 }, - { LocationNames.NorwayEast, 36 }, - { LocationNames.NorwayWest, 30 }, - { LocationNames.PolandCentral, 16 }, - { LocationNames.QatarCentral, 102 }, - { LocationNames.SouthAfricaNorth, 168 }, - { LocationNames.SouthAfricaWest, 158 }, - { LocationNames.SouthCentralUS, 116 }, - { LocationNames.SoutheastAsia, 144 }, - { LocationNames.SouthIndia, 122 }, - { LocationNames.SpainCentral, 10 }, - { LocationNames.SwedenCentral, 36 }, - { LocationNames.SwedenSouth, 36 }, - { LocationNames.SwitzerlandNorth, 4 }, - { LocationNames.SwitzerlandWest, 0 }, - { LocationNames.TaiwanNorth, 178 }, - { LocationNames.TaiwanNorthwest, 178 }, - { LocationNames.UAECentral, 102 }, - { LocationNames.UAENorth, 106 }, - { LocationNames.UKSouth, 16 }, - { LocationNames.UKWest, 18 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 126 }, - { LocationNames.WestEurope, 16 }, - { LocationNames.WestIndia, 112 }, - { LocationNames.WestUS, 147 }, - { LocationNames.WestUS2, 146 }, - { LocationNames.WestUS3, 146 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.TaiwanNorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 120 }, - { LocationNames.AustraliaCentral2, 120 }, - { LocationNames.AustraliaEast, 116 }, - { LocationNames.AustraliaSoutheast, 118 }, - { LocationNames.AustriaEast, 182 }, - { LocationNames.BrazilSouth, 320 }, - { LocationNames.BrazilSoutheast, 320 }, - { LocationNames.CanadaCentral, 196 }, - { LocationNames.CanadaEast, 206 }, - { LocationNames.CentralIndia, 86 }, - { LocationNames.CentralUS, 176 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 100 }, - { LocationNames.EastUS, 199 }, - { LocationNames.EastUS2, 210 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 184 }, - { LocationNames.FranceSouth, 172 }, - { LocationNames.GermanyNorth, 196 }, - { LocationNames.GermanyWestCentral, 188 }, - { LocationNames.IsraelCentral, 110 }, - { LocationNames.ItalyNorth, 182 }, - { LocationNames.JapanEast, 50 }, - { LocationNames.JapanWest, 50 }, - { LocationNames.JioIndiaCentral, 86 }, - { LocationNames.JioIndiaWest, 86 }, - { LocationNames.KoreaCentral, 56 }, - { LocationNames.KoreaSouth, 60 }, - { LocationNames.MalaysiaSouth, 33 }, - { LocationNames.MexicoCentral, 140 }, - { LocationNames.NewZealandNorth, 120 }, - { LocationNames.NorthCentralUS, 184 }, - { LocationNames.NorthEurope, 205 }, - { LocationNames.NorwayEast, 214 }, - { LocationNames.NorwayWest, 206 }, - { LocationNames.PolandCentral, 193 }, - { LocationNames.QatarCentral, 110 }, - { LocationNames.SouthAfricaNorth, 332 }, - { LocationNames.SouthAfricaWest, 336 }, - { LocationNames.SouthCentralUS, 182 }, - { LocationNames.SoutheastAsia, 33 }, - { LocationNames.SouthIndia, 66 }, - { LocationNames.SpainCentral, 184 }, - { LocationNames.SwedenCentral, 214 }, - { LocationNames.SwedenSouth, 214 }, - { LocationNames.SwitzerlandNorth, 182 }, - { LocationNames.SwitzerlandWest, 178 }, - { LocationNames.TaiwanNorth, 0 }, - { LocationNames.TaiwanNorthwest, 100 }, - { LocationNames.UAECentral, 110 }, - { LocationNames.UAENorth, 109 }, - { LocationNames.UKSouth, 192 }, - { LocationNames.UKWest, 194 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 162 }, - { LocationNames.WestEurope, 193 }, - { LocationNames.WestIndia, 84 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 140 }, - { LocationNames.WestUS3, 140 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.TaiwanNorthwest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 120 }, - { LocationNames.AustraliaCentral2, 120 }, - { LocationNames.AustraliaEast, 116 }, - { LocationNames.AustraliaSoutheast, 118 }, - { LocationNames.AustriaEast, 182 }, - { LocationNames.BrazilSouth, 320 }, - { LocationNames.BrazilSoutheast, 320 }, - { LocationNames.CanadaCentral, 196 }, - { LocationNames.CanadaEast, 206 }, - { LocationNames.CentralIndia, 86 }, - { LocationNames.CentralUS, 176 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 100 }, - { LocationNames.EastUS, 199 }, - { LocationNames.EastUS2, 210 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 184 }, - { LocationNames.FranceSouth, 172 }, - { LocationNames.GermanyNorth, 196 }, - { LocationNames.GermanyWestCentral, 188 }, - { LocationNames.IsraelCentral, 110 }, - { LocationNames.ItalyNorth, 182 }, - { LocationNames.JapanEast, 50 }, - { LocationNames.JapanWest, 50 }, - { LocationNames.JioIndiaCentral, 86 }, - { LocationNames.JioIndiaWest, 86 }, - { LocationNames.KoreaCentral, 56 }, - { LocationNames.KoreaSouth, 60 }, - { LocationNames.MalaysiaSouth, 33 }, - { LocationNames.MexicoCentral, 140 }, - { LocationNames.NewZealandNorth, 120 }, - { LocationNames.NorthCentralUS, 184 }, - { LocationNames.NorthEurope, 205 }, - { LocationNames.NorwayEast, 214 }, - { LocationNames.NorwayWest, 206 }, - { LocationNames.PolandCentral, 193 }, - { LocationNames.QatarCentral, 110 }, - { LocationNames.SouthAfricaNorth, 332 }, - { LocationNames.SouthAfricaWest, 336 }, - { LocationNames.SouthCentralUS, 182 }, - { LocationNames.SoutheastAsia, 33 }, - { LocationNames.SouthIndia, 66 }, - { LocationNames.SpainCentral, 184 }, - { LocationNames.SwedenCentral, 214 }, - { LocationNames.SwedenSouth, 214 }, - { LocationNames.SwitzerlandNorth, 182 }, - { LocationNames.SwitzerlandWest, 178 }, - { LocationNames.TaiwanNorth, 100 }, - { LocationNames.TaiwanNorthwest, 0 }, - { LocationNames.UAECentral, 110 }, - { LocationNames.UAENorth, 109 }, - { LocationNames.UKSouth, 192 }, - { LocationNames.UKWest, 194 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 162 }, - { LocationNames.WestEurope, 193 }, - { LocationNames.WestIndia, 84 }, - { LocationNames.WestUS, 148 }, - { LocationNames.WestUS2, 140 }, - { LocationNames.WestUS3, 140 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.UAECentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, 168 }, - { LocationNames.AustraliaCentral2, 168 }, - { LocationNames.AustraliaEast, 164 }, - { LocationNames.AustraliaSoutheast, 160 }, - { LocationNames.AustriaEast, 106 }, - { LocationNames.BrazilSouth, 296 }, - { LocationNames.BrazilSoutheast, 296 }, - { LocationNames.CanadaCentral, 201 }, - { LocationNames.CanadaEast, 210 }, - { LocationNames.CentralIndia, 30 }, - { LocationNames.CentralUS, 216 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 110 }, - { LocationNames.EastUS, 189 }, - { LocationNames.EastUS2, 190 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 108 }, - { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyWestCentral, 112 }, - { LocationNames.IsraelCentral, 100 }, - { LocationNames.ItalyNorth, 106 }, - { LocationNames.JapanEast, 144 }, - { LocationNames.JapanWest, 149 }, - { LocationNames.JioIndiaCentral, 30 }, - { LocationNames.JioIndiaWest, 30 }, - { LocationNames.KoreaCentral, 138 }, - { LocationNames.KoreaSouth, 132 }, - { LocationNames.MalaysiaSouth, 76 }, - { LocationNames.MexicoCentral, 236 }, - { LocationNames.NewZealandNorth, 168 }, - { LocationNames.NorthCentralUS, 209 }, - { LocationNames.NorthEurope, 129 }, - { LocationNames.NorwayEast, 138 }, - { LocationNames.NorwayWest, 130 }, - { LocationNames.PolandCentral, 118 }, - { LocationNames.QatarCentral, 4 }, - { LocationNames.SouthAfricaNorth, 256 }, - { LocationNames.SouthAfricaWest, 260 }, - { LocationNames.SouthCentralUS, 218 }, - { LocationNames.SoutheastAsia, 76 }, - { LocationNames.SouthIndia, 46 }, - { LocationNames.SpainCentral, 108 }, - { LocationNames.SwedenCentral, 129 }, - { LocationNames.SwedenSouth, 129 }, - { LocationNames.SwitzerlandNorth, 106 }, - { LocationNames.SwitzerlandWest, 102 }, - { LocationNames.TaiwanNorth, 110 }, - { LocationNames.TaiwanNorthwest, 110 }, - { LocationNames.UAECentral, 0 }, - { LocationNames.UAENorth, 4 }, - { LocationNames.UKSouth, 116 }, - { LocationNames.UKWest, 118 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 230 }, - { LocationNames.WestEurope, 118 }, - { LocationNames.WestIndia, 28 }, - { LocationNames.WestUS, 244 }, - { LocationNames.WestUS2, 236 }, - { LocationNames.WestUS3, 236 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.UAENorth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 168 }, - { LocationNames.AustraliaCentral2, 168 }, - { LocationNames.AustraliaEast, 163 }, - { LocationNames.AustraliaSoutheast, 160 }, - { LocationNames.AustriaEast, 108 }, - { LocationNames.BrazilSouth, 298 }, - { LocationNames.BrazilSoutheast, 298 }, - { LocationNames.CanadaCentral, 204 }, - { LocationNames.CanadaEast, 214 }, - { LocationNames.CentralIndia, 30 }, - { LocationNames.CentralUS, 218 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 109 }, - { LocationNames.EastUS, 192 }, - { LocationNames.EastUS2, 194 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 112 }, - { LocationNames.FranceSouth, 98 }, - { LocationNames.GermanyNorth, 124 }, - { LocationNames.GermanyWestCentral, 114 }, - { LocationNames.IsraelCentral, 4 }, - { LocationNames.ItalyNorth, 108 }, - { LocationNames.JapanEast, 144 }, - { LocationNames.JapanWest, 148 }, - { LocationNames.JioIndiaCentral, 30 }, - { LocationNames.JioIndiaWest, 30 }, - { LocationNames.KoreaCentral, 138 }, - { LocationNames.KoreaSouth, 130 }, - { LocationNames.MalaysiaSouth, 76 }, - { LocationNames.MexicoCentral, 236 }, - { LocationNames.NewZealandNorth, 168 }, - { LocationNames.NorthCentralUS, 212 }, - { LocationNames.NorthEurope, 132 }, - { LocationNames.NorwayEast, 140 }, - { LocationNames.NorwayWest, 134 }, - { LocationNames.PolandCentral, 120 }, - { LocationNames.QatarCentral, 4 }, - { LocationNames.SouthAfricaNorth, 260 }, - { LocationNames.SouthAfricaWest, 264 }, - { LocationNames.SouthCentralUS, 220 }, - { LocationNames.SoutheastAsia, 76 }, - { LocationNames.SouthIndia, 46 }, - { LocationNames.SpainCentral, 112 }, - { LocationNames.SwedenCentral, 140 }, - { LocationNames.SwedenSouth, 140 }, - { LocationNames.SwitzerlandNorth, 108 }, - { LocationNames.SwitzerlandWest, 106 }, - { LocationNames.TaiwanNorth, 109 }, - { LocationNames.TaiwanNorthwest, 109 }, - { LocationNames.UAECentral, 4 }, - { LocationNames.UAENorth, 0 }, - { LocationNames.UKSouth, 120 }, - { LocationNames.UKWest, 122 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 234 }, - { LocationNames.WestEurope, 120 }, - { LocationNames.WestIndia, 28 }, - { LocationNames.WestUS, 244 }, - { LocationNames.WestUS2, 236 }, - { LocationNames.WestUS3, 236 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.UKSouth, - new Dictionary() - { - { LocationNames.AustraliaCentral, 250 }, - { LocationNames.AustraliaCentral2, 248 }, - { LocationNames.AustraliaEast, 246 }, - { LocationNames.AustraliaSoutheast, 242 }, - { LocationNames.AustriaEast, 20 }, - { LocationNames.BrazilSouth, 181 }, - { LocationNames.BrazilSoutheast, 181 }, - { LocationNames.CanadaCentral, 86 }, - { LocationNames.CanadaEast, 96 }, - { LocationNames.CentralIndia, 122 }, - { LocationNames.CentralUS, 96 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 192 }, - { LocationNames.EastUS, 74 }, - { LocationNames.EastUS2, 78 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 7 }, - { LocationNames.FranceSouth, 16 }, - { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyWestCentral, 14 }, - { LocationNames.IsraelCentral, 116 }, - { LocationNames.ItalyNorth, 20 }, - { LocationNames.JapanEast, 226 }, - { LocationNames.JapanWest, 225 }, - { LocationNames.JioIndiaCentral, 122 }, - { LocationNames.JioIndiaWest, 122 }, - { LocationNames.KoreaCentral, 220 }, - { LocationNames.KoreaSouth, 214 }, - { LocationNames.MalaysiaSouth, 158 }, - { LocationNames.MexicoCentral, 130 }, - { LocationNames.NewZealandNorth, 250 }, - { LocationNames.NorthCentralUS, 90 }, - { LocationNames.NorthEurope, 21 }, - { LocationNames.NorwayEast, 28 }, - { LocationNames.NorwayWest, 22 }, - { LocationNames.PolandCentral, 10 }, - { LocationNames.QatarCentral, 116 }, - { LocationNames.SouthAfricaNorth, 160 }, - { LocationNames.SouthAfricaWest, 144 }, - { LocationNames.SouthCentralUS, 104 }, - { LocationNames.SoutheastAsia, 158 }, - { LocationNames.SouthIndia, 134 }, - { LocationNames.SpainCentral, 7 }, - { LocationNames.SwedenCentral, 21 }, - { LocationNames.SwedenSouth, 21 }, - { LocationNames.SwitzerlandNorth, 20 }, - { LocationNames.SwitzerlandWest, 16 }, - { LocationNames.TaiwanNorth, 192 }, - { LocationNames.TaiwanNorthwest, 192 }, - { LocationNames.UAECentral, 116 }, - { LocationNames.UAENorth, 120 }, - { LocationNames.UKSouth, 0 }, - { LocationNames.UKWest, 4 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 110 }, - { LocationNames.WestEurope, 10 }, - { LocationNames.WestIndia, 126 }, - { LocationNames.WestUS, 136 }, - { LocationNames.WestUS2, 130 }, - { LocationNames.WestUS3, 130 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.UKWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, 252 }, - { LocationNames.AustraliaCentral2, 252 }, - { LocationNames.AustraliaEast, 248 }, - { LocationNames.AustraliaSoutheast, 245 }, - { LocationNames.AustriaEast, 22 }, - { LocationNames.BrazilSouth, 184 }, - { LocationNames.BrazilSoutheast, 184 }, - { LocationNames.CanadaCentral, 90 }, - { LocationNames.CanadaEast, 98 }, - { LocationNames.CentralIndia, 126 }, - { LocationNames.CentralUS, 96 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 194 }, - { LocationNames.EastUS, 76 }, - { LocationNames.EastUS2, 80 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 8 }, - { LocationNames.FranceSouth, 18 }, - { LocationNames.GermanyNorth, 22 }, - { LocationNames.GermanyWestCentral, 18 }, - { LocationNames.IsraelCentral, 118 }, - { LocationNames.ItalyNorth, 22 }, - { LocationNames.JapanEast, 230 }, - { LocationNames.JapanWest, 228 }, - { LocationNames.JioIndiaCentral, 126 }, - { LocationNames.JioIndiaWest, 126 }, - { LocationNames.KoreaCentral, 222 }, - { LocationNames.KoreaSouth, 216 }, - { LocationNames.MalaysiaSouth, 161 }, - { LocationNames.MexicoCentral, 132 }, - { LocationNames.NewZealandNorth, 252 }, - { LocationNames.NorthCentralUS, 92 }, - { LocationNames.NorthEurope, 17 }, - { LocationNames.NorwayEast, 30 }, - { LocationNames.NorwayWest, 24 }, - { LocationNames.PolandCentral, 12 }, - { LocationNames.QatarCentral, 118 }, - { LocationNames.SouthAfricaNorth, 164 }, - { LocationNames.SouthAfricaWest, 146 }, - { LocationNames.SouthCentralUS, 106 }, - { LocationNames.SoutheastAsia, 161 }, - { LocationNames.SouthIndia, 138 }, - { LocationNames.SpainCentral, 8 }, - { LocationNames.SwedenCentral, 30 }, - { LocationNames.SwedenSouth, 30 }, - { LocationNames.SwitzerlandNorth, 22 }, - { LocationNames.SwitzerlandWest, 18 }, - { LocationNames.TaiwanNorth, 194 }, - { LocationNames.TaiwanNorthwest, 194 }, - { LocationNames.UAECentral, 118 }, - { LocationNames.UAENorth, 122 }, - { LocationNames.UKSouth, 4 }, - { LocationNames.UKWest, 0 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 112 }, - { LocationNames.WestEurope, 12 }, - { LocationNames.WestIndia, 128 }, - { LocationNames.WestUS, 138 }, - { LocationNames.WestUS2, 132 }, - { LocationNames.WestUS3, 132 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USDoDCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, 0 }, - { LocationNames.USDoDEast, 44 }, - { LocationNames.USGovArizona, 42 }, - { LocationNames.USGovTexas, 24 }, - { LocationNames.USGovVirginia, 44 }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USDoDEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, 44 }, - { LocationNames.USDoDEast, 0 }, - { LocationNames.USGovArizona, 45 }, - { LocationNames.USGovTexas, 27 }, - { LocationNames.USGovVirginia, 2 }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USGovArizona, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, 42 }, - { LocationNames.USDoDEast, 46 }, - { LocationNames.USGovArizona, 0 }, - { LocationNames.USGovTexas, 20 }, - { LocationNames.USGovVirginia, 45 }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USGovTexas, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, 24 }, - { LocationNames.USDoDEast, 28 }, - { LocationNames.USGovArizona, 20 }, - { LocationNames.USGovTexas, 0 }, - { LocationNames.USGovVirginia, 35 }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USGovVirginia, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, 44 }, - { LocationNames.USDoDEast, 2 }, - { LocationNames.USGovArizona, 45 }, - { LocationNames.USGovTexas, 35 }, - { LocationNames.USGovVirginia, 0 }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USNatEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, 0 }, - { LocationNames.USNatWest, 255 }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USNatWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, 255 }, - { LocationNames.USNatWest, 0 }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USSecEast, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, 0 }, - { LocationNames.USSecWest, 255 }, - { LocationNames.USSecWestCentral, 255 }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USSecWest, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, 255 }, - { LocationNames.USSecWest, 0 }, - { LocationNames.USSecWestCentral, 100 }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.USSecWestCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, 255 }, - { LocationNames.USSecWest, 100 }, - { LocationNames.USSecWestCentral, 0 }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestCentralUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 170 }, - { LocationNames.AustraliaCentral2, 170 }, - { LocationNames.AustraliaEast, 166 }, - { LocationNames.AustraliaSoutheast, 176 }, - { LocationNames.AustriaEast, 134 }, - { LocationNames.BrazilSouth, 160 }, - { LocationNames.BrazilSoutheast, 160 }, - { LocationNames.CanadaCentral, 36 }, - { LocationNames.CanadaEast, 44 }, - { LocationNames.CentralIndia, 236 }, - { LocationNames.CentralUS, 15 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 162 }, - { LocationNames.EastUS, 38 }, - { LocationNames.EastUS2, 47 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 119 }, - { LocationNames.FranceSouth, 126 }, - { LocationNames.GermanyNorth, 132 }, - { LocationNames.GermanyWestCentral, 126 }, - { LocationNames.IsraelCentral, 230 }, - { LocationNames.ItalyNorth, 134 }, - { LocationNames.JapanEast, 126 }, - { LocationNames.JapanWest, 128 }, - { LocationNames.JioIndiaCentral, 236 }, - { LocationNames.JioIndiaWest, 236 }, - { LocationNames.KoreaCentral, 143 }, - { LocationNames.KoreaSouth, 148 }, - { LocationNames.MalaysiaSouth, 180 }, - { LocationNames.MexicoCentral, 22 }, - { LocationNames.NewZealandNorth, 170 }, - { LocationNames.NorthCentralUS, 22 }, - { LocationNames.NorthEurope, 110 }, - { LocationNames.NorwayEast, 142 }, - { LocationNames.NorwayWest, 136 }, - { LocationNames.PolandCentral, 120 }, - { LocationNames.QatarCentral, 230 }, - { LocationNames.SouthAfricaNorth, 274 }, - { LocationNames.SouthAfricaWest, 258 }, - { LocationNames.SouthCentralUS, 22 }, - { LocationNames.SoutheastAsia, 180 }, - { LocationNames.SouthIndia, 212 }, - { LocationNames.SpainCentral, 119 }, - { LocationNames.SwedenCentral, 142 }, - { LocationNames.SwedenSouth, 142 }, - { LocationNames.SwitzerlandNorth, 134 }, - { LocationNames.SwitzerlandWest, 126 }, - { LocationNames.TaiwanNorth, 162 }, - { LocationNames.TaiwanNorthwest, 162 }, - { LocationNames.UAECentral, 230 }, - { LocationNames.UAENorth, 234 }, - { LocationNames.UKSouth, 110 }, - { LocationNames.UKWest, 112 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 0 }, - { LocationNames.WestEurope, 120 }, - { LocationNames.WestIndia, 240 }, - { LocationNames.WestUS, 30 }, - { LocationNames.WestUS2, 22 }, - { LocationNames.WestUS3, 22 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestEurope, - new Dictionary() - { - { LocationNames.AustraliaCentral, 252 }, - { LocationNames.AustraliaCentral2, 252 }, - { LocationNames.AustraliaEast, 248 }, - { LocationNames.AustraliaSoutheast, 244 }, - { LocationNames.AustriaEast, 12 }, - { LocationNames.BrazilSouth, 188 }, - { LocationNames.BrazilSoutheast, 188 }, - { LocationNames.CanadaCentral, 94 }, - { LocationNames.CanadaEast, 103 }, - { LocationNames.CentralIndia, 126 }, - { LocationNames.CentralUS, 102 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 193 }, - { LocationNames.EastUS, 81 }, - { LocationNames.EastUS2, 86 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 10 }, - { LocationNames.FranceSouth, 20 }, - { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyWestCentral, 8 }, - { LocationNames.IsraelCentral, 118 }, - { LocationNames.ItalyNorth, 12 }, - { LocationNames.JapanEast, 234 }, - { LocationNames.JapanWest, 228 }, - { LocationNames.JioIndiaCentral, 126 }, - { LocationNames.JioIndiaWest, 126 }, - { LocationNames.KoreaCentral, 222 }, - { LocationNames.KoreaSouth, 216 }, - { LocationNames.MalaysiaSouth, 160 }, - { LocationNames.MexicoCentral, 142 }, - { LocationNames.NewZealandNorth, 252 }, - { LocationNames.NorthCentralUS, 102 }, - { LocationNames.NorthEurope, 22 }, - { LocationNames.NorwayEast, 22 }, - { LocationNames.NorwayWest, 15 }, - { LocationNames.PolandCentral, 100 }, - { LocationNames.QatarCentral, 118 }, - { LocationNames.SouthAfricaNorth, 170 }, - { LocationNames.SouthAfricaWest, 152 }, - { LocationNames.SouthCentralUS, 112 }, - { LocationNames.SoutheastAsia, 160 }, - { LocationNames.SouthIndia, 136 }, - { LocationNames.SpainCentral, 10 }, - { LocationNames.SwedenCentral, 22 }, - { LocationNames.SwedenSouth, 22 }, - { LocationNames.SwitzerlandNorth, 12 }, - { LocationNames.SwitzerlandWest, 16 }, - { LocationNames.TaiwanNorth, 193 }, - { LocationNames.TaiwanNorthwest, 193 }, - { LocationNames.UAECentral, 118 }, - { LocationNames.UAENorth, 120 }, - { LocationNames.UKSouth, 10 }, - { LocationNames.UKWest, 12 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 120 }, - { LocationNames.WestEurope, 0 }, - { LocationNames.WestIndia, 128 }, - { LocationNames.WestUS, 144 }, - { LocationNames.WestUS2, 142 }, - { LocationNames.WestUS3, 142 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestIndia, - new Dictionary() - { - { LocationNames.AustraliaCentral, 142 }, - { LocationNames.AustraliaCentral2, 142 }, - { LocationNames.AustraliaEast, 138 }, - { LocationNames.AustraliaSoutheast, 134 }, - { LocationNames.AustriaEast, 116 }, - { LocationNames.BrazilSouth, 304 }, - { LocationNames.BrazilSoutheast, 304 }, - { LocationNames.CanadaCentral, 210 }, - { LocationNames.CanadaEast, 220 }, - { LocationNames.CentralIndia, 4 }, - { LocationNames.CentralUS, 224 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 84 }, - { LocationNames.EastUS, 198 }, - { LocationNames.EastUS2, 200 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 118 }, - { LocationNames.FranceSouth, 106 }, - { LocationNames.GermanyNorth, 130 }, - { LocationNames.GermanyWestCentral, 122 }, - { LocationNames.IsraelCentral, 28 }, - { LocationNames.ItalyNorth, 116 }, - { LocationNames.JapanEast, 118 }, - { LocationNames.JapanWest, 122 }, - { LocationNames.JioIndiaCentral, 4 }, - { LocationNames.JioIndiaWest, 4 }, - { LocationNames.KoreaCentral, 112 }, - { LocationNames.KoreaSouth, 106 }, - { LocationNames.MalaysiaSouth, 50 }, - { LocationNames.MexicoCentral, 210 }, - { LocationNames.NewZealandNorth, 142 }, - { LocationNames.NorthCentralUS, 218 }, - { LocationNames.NorthEurope, 139 }, - { LocationNames.NorwayEast, 146 }, - { LocationNames.NorwayWest, 140 }, - { LocationNames.PolandCentral, 128 }, - { LocationNames.QatarCentral, 28 }, - { LocationNames.SouthAfricaNorth, 266 }, - { LocationNames.SouthAfricaWest, 270 }, - { LocationNames.SouthCentralUS, 226 }, - { LocationNames.SoutheastAsia, 50 }, - { LocationNames.SouthIndia, 20 }, - { LocationNames.SpainCentral, 118 }, - { LocationNames.SwedenCentral, 146 }, - { LocationNames.SwedenSouth, 146 }, - { LocationNames.SwitzerlandNorth, 116 }, - { LocationNames.SwitzerlandWest, 112 }, - { LocationNames.TaiwanNorth, 84 }, - { LocationNames.TaiwanNorthwest, 84 }, - { LocationNames.UAECentral, 28 }, - { LocationNames.UAENorth, 28 }, - { LocationNames.UKSouth, 126 }, - { LocationNames.UKWest, 128 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 240 }, - { LocationNames.WestEurope, 128 }, - { LocationNames.WestIndia, 0 }, - { LocationNames.WestUS, 217 }, - { LocationNames.WestUS2, 210 }, - { LocationNames.WestUS3, 210 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestUS, - new Dictionary() - { - { LocationNames.AustraliaCentral, 142 }, - { LocationNames.AustraliaCentral2, 142 }, - { LocationNames.AustraliaEast, 138 }, - { LocationNames.AustraliaSoutheast, 148 }, - { LocationNames.AustriaEast, 150 }, - { LocationNames.BrazilSouth, 172 }, - { LocationNames.BrazilSoutheast, 172 }, - { LocationNames.CanadaCentral, 64 }, - { LocationNames.CanadaEast, 72 }, - { LocationNames.CentralIndia, 218 }, - { LocationNames.CentralUS, 44 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 148 }, - { LocationNames.EastUS, 64 }, - { LocationNames.EastUS2, 58 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 138 }, - { LocationNames.FranceSouth, 148 }, - { LocationNames.GermanyNorth, 153 }, - { LocationNames.GermanyWestCentral, 148 }, - { LocationNames.IsraelCentral, 244 }, - { LocationNames.ItalyNorth, 150 }, - { LocationNames.JapanEast, 106 }, - { LocationNames.JapanWest, 106 }, - { LocationNames.JioIndiaCentral, 218 }, - { LocationNames.JioIndiaWest, 218 }, - { LocationNames.KoreaCentral, 130 }, - { LocationNames.KoreaSouth, 134 }, - { LocationNames.MalaysiaSouth, 168 }, - { LocationNames.MexicoCentral, 22 }, - { LocationNames.NewZealandNorth, 142 }, - { LocationNames.NorthCentralUS, 50 }, - { LocationNames.NorthEurope, 133 }, - { LocationNames.NorwayEast, 163 }, - { LocationNames.NorwayWest, 156 }, - { LocationNames.PolandCentral, 144 }, - { LocationNames.QatarCentral, 244 }, - { LocationNames.SouthAfricaNorth, 298 }, - { LocationNames.SouthAfricaWest, 280 }, - { LocationNames.SouthCentralUS, 34 }, - { LocationNames.SoutheastAsia, 168 }, - { LocationNames.SouthIndia, 200 }, - { LocationNames.SpainCentral, 138 }, - { LocationNames.SwedenCentral, 163 }, - { LocationNames.SwedenSouth, 163 }, - { LocationNames.SwitzerlandNorth, 150 }, - { LocationNames.SwitzerlandWest, 147 }, - { LocationNames.TaiwanNorth, 148 }, - { LocationNames.TaiwanNorthwest, 148 }, - { LocationNames.UAECentral, 244 }, - { LocationNames.UAENorth, 244 }, - { LocationNames.UKSouth, 136 }, - { LocationNames.UKWest, 138 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 30 }, - { LocationNames.WestEurope, 144 }, - { LocationNames.WestIndia, 217 }, - { LocationNames.WestUS, 0 }, - { LocationNames.WestUS2, 22 }, - { LocationNames.WestUS3, 22 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestUS2, - new Dictionary() - { - { LocationNames.AustraliaCentral, 162 }, - { LocationNames.AustraliaCentral2, 162 }, - { LocationNames.AustraliaEast, 158 }, - { LocationNames.AustraliaSoutheast, 168 }, - { LocationNames.AustriaEast, 154 }, - { LocationNames.BrazilSouth, 182 }, - { LocationNames.BrazilSoutheast, 182 }, - { LocationNames.CanadaCentral, 57 }, - { LocationNames.CanadaEast, 66 }, - { LocationNames.CentralIndia, 212 }, - { LocationNames.CentralUS, 36 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 140 }, - { LocationNames.EastUS, 58 }, - { LocationNames.EastUS2, 68 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 140 }, - { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyWestCentral, 148 }, - { LocationNames.IsraelCentral, 236 }, - { LocationNames.ItalyNorth, 154 }, - { LocationNames.JapanEast, 112 }, - { LocationNames.JapanWest, 112 }, - { LocationNames.JioIndiaCentral, 212 }, - { LocationNames.JioIndiaWest, 212 }, - { LocationNames.KoreaCentral, 122 }, - { LocationNames.KoreaSouth, 126 }, - { LocationNames.MalaysiaSouth, 160 }, - { LocationNames.MexicoCentral, 100 }, - { LocationNames.NewZealandNorth, 162 }, - { LocationNames.NorthCentralUS, 44 }, - { LocationNames.NorthEurope, 136 }, - { LocationNames.NorwayEast, 164 }, - { LocationNames.NorwayWest, 156 }, - { LocationNames.PolandCentral, 142 }, - { LocationNames.QatarCentral, 236 }, - { LocationNames.SouthAfricaNorth, 296 }, - { LocationNames.SouthAfricaWest, 280 }, - { LocationNames.SouthCentralUS, 44 }, - { LocationNames.SoutheastAsia, 160 }, - { LocationNames.SouthIndia, 192 }, - { LocationNames.SpainCentral, 140 }, - { LocationNames.SwedenCentral, 164 }, - { LocationNames.SwedenSouth, 164 }, - { LocationNames.SwitzerlandNorth, 154 }, - { LocationNames.SwitzerlandWest, 146 }, - { LocationNames.TaiwanNorth, 140 }, - { LocationNames.TaiwanNorthwest, 140 }, - { LocationNames.UAECentral, 236 }, - { LocationNames.UAENorth, 236 }, - { LocationNames.UKSouth, 130 }, - { LocationNames.UKWest, 132 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 142 }, - { LocationNames.WestIndia, 210 }, - { LocationNames.WestUS, 22 }, - { LocationNames.WestUS2, 0 }, - { LocationNames.WestUS3, 32 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.WestUS3, - new Dictionary() - { - { LocationNames.AustraliaCentral, 162 }, - { LocationNames.AustraliaCentral2, 162 }, - { LocationNames.AustraliaEast, 158 }, - { LocationNames.AustraliaSoutheast, 168 }, - { LocationNames.AustriaEast, 154 }, - { LocationNames.BrazilSouth, 182 }, - { LocationNames.BrazilSoutheast, 182 }, - { LocationNames.CanadaCentral, 57 }, - { LocationNames.CanadaEast, 66 }, - { LocationNames.CentralIndia, 212 }, - { LocationNames.CentralUS, 36 }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, 140 }, - { LocationNames.EastUS, 58 }, - { LocationNames.EastUS2, 68 }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, 140 }, - { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyWestCentral, 148 }, - { LocationNames.IsraelCentral, 236 }, - { LocationNames.ItalyNorth, 154 }, - { LocationNames.JapanEast, 112 }, - { LocationNames.JapanWest, 112 }, - { LocationNames.JioIndiaCentral, 212 }, - { LocationNames.JioIndiaWest, 212 }, - { LocationNames.KoreaCentral, 122 }, - { LocationNames.KoreaSouth, 126 }, - { LocationNames.MalaysiaSouth, 160 }, - { LocationNames.MexicoCentral, 100 }, - { LocationNames.NewZealandNorth, 162 }, - { LocationNames.NorthCentralUS, 44 }, - { LocationNames.NorthEurope, 136 }, - { LocationNames.NorwayEast, 164 }, - { LocationNames.NorwayWest, 156 }, - { LocationNames.PolandCentral, 142 }, - { LocationNames.QatarCentral, 236 }, - { LocationNames.SouthAfricaNorth, 296 }, - { LocationNames.SouthAfricaWest, 280 }, - { LocationNames.SouthCentralUS, 44 }, - { LocationNames.SoutheastAsia, 160 }, - { LocationNames.SouthIndia, 192 }, - { LocationNames.SpainCentral, 140 }, - { LocationNames.SwedenCentral, 164 }, - { LocationNames.SwedenSouth, 164 }, - { LocationNames.SwitzerlandNorth, 154 }, - { LocationNames.SwitzerlandWest, 146 }, - { LocationNames.TaiwanNorth, 140 }, - { LocationNames.TaiwanNorthwest, 140 }, - { LocationNames.UAECentral, 236 }, - { LocationNames.UAENorth, 236 }, - { LocationNames.UKSouth, 130 }, - { LocationNames.UKWest, 132 }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 142 }, - { LocationNames.WestIndia, 210 }, - { LocationNames.WestUS, 22 }, - { LocationNames.WestUS2, 32 }, - { LocationNames.WestUS3, 0 }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, - { - LocationNames.CentralUSEUAP, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, 255 }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, 0 }, - { LocationNames.EastUS2EUAP, 40 }, - } - }, - { - LocationNames.EastUS2EUAP, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.AustriaEast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, 255 }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NewZealandNorth, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SpainCentral, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.TaiwanNorth, long.MaxValue }, - { LocationNames.TaiwanNorthwest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, 40 }, - { LocationNames.EastUS2EUAP, 0 }, - } - } - }; - - private static long GetLinkTypeThresholdInMs(GeoLinkTypes geoLinkType) - { - switch(geoLinkType) - { - case GeoLinkTypes.Strong: - return 100; - case GeoLinkTypes.Medium: - return 200; - case GeoLinkTypes.Weak: - return long.MaxValue; - default: - throw new ArgumentException("GeoLinkType provided is invalid."); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + + internal static class RegionProximityUtil + { + public static List GetRegionsForLinkType(GeoLinkTypes geoLinkType, List existingRegions) + { + foreach (string existingRegion in existingRegions) + { + if (string.IsNullOrEmpty(existingRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(existingRegion)) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "existingRegion {0} is not a valid region.", existingRegion)); + } + } + + List> regionsSatisfyingLinkTypePerRegion = new List>(); + + foreach (string existingRegion in existingRegions) + { + regionsSatisfyingLinkTypePerRegion.Add(RegionProximityUtil.GetRegionsForLinkType(geoLinkType, existingRegion)); + } + + if(regionsSatisfyingLinkTypePerRegion.Count < 1) + { + return new List(); + } + + IEnumerable regionsSatisfyingAllInputRegions = regionsSatisfyingLinkTypePerRegion[0].AsEnumerable(); + for (int i = 1; i < regionsSatisfyingLinkTypePerRegion.Count; i++) + { + regionsSatisfyingAllInputRegions = regionsSatisfyingAllInputRegions.Intersect(regionsSatisfyingLinkTypePerRegion[i]); + } + + if (existingRegions.Except(regionsSatisfyingAllInputRegions).Any()) + { + return new List(); + } + + return regionsSatisfyingAllInputRegions.ToList(); + } + + public static List GetRegionsForLinkType(GeoLinkTypes geoLinkType, string sourceRegion) + { + if (string.IsNullOrEmpty(sourceRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(sourceRegion)) + { + throw new ArgumentException("sourceRegion is not a valid region."); + } + + List regionsSatisfyingLinkType = new List(); + + long linkTypeThresholdInMs = RegionProximityUtil.GetLinkTypeThresholdInMs(geoLinkType); + + Dictionary roundTripTimeFromSourceRegion = RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs[sourceRegion]; + foreach (string region in roundTripTimeFromSourceRegion.Keys) + { + if (roundTripTimeFromSourceRegion[region] <= linkTypeThresholdInMs) + { + regionsSatisfyingLinkType.Add(region); + } + } + + if (!regionsSatisfyingLinkType.Contains(sourceRegion)) + { + return new List(); + } + + return regionsSatisfyingLinkType; + } + + public static List GeneratePreferredRegionList(string sourceRegion) + { + if (string.IsNullOrEmpty(sourceRegion) || !RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs.ContainsKey(sourceRegion)) + { + throw new ArgumentException("sourceRegion is not a valid region."); + } + + List> regionRTTList = RegionProximityUtil.SourceRegionToTargetRegionsRTTInMs[sourceRegion].ToList(); + regionRTTList.Sort((x, y) => x.Value.CompareTo(y.Value)); + + List preferredLocationsList = new List(); + foreach (KeyValuePair regionRTT in regionRTTList) + { + preferredLocationsList.Add(regionRTT.Key); + } + + return preferredLocationsList; + } + + internal static Dictionary> SourceRegionToTargetRegionsRTTInMs = new Dictionary>() + { + { + LocationNames.AustraliaCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 0 }, + { LocationNames.AustraliaCentral2, 2 }, + { LocationNames.AustraliaEast, 6 }, + { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, + { LocationNames.BrazilSouth, 314 }, + { LocationNames.BrazilSoutheast, 314 }, + { LocationNames.CanadaCentral, 204 }, + { LocationNames.CanadaEast, 214 }, + { LocationNames.CentralIndia, 144 }, + { LocationNames.CentralUS, 184 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 120 }, + { LocationNames.EastUS, 205 }, + { LocationNames.EastUS2, 200 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 242 }, + { LocationNames.FranceSouth, 230 }, + { LocationNames.GermanyNorth, 254 }, + { LocationNames.GermanyWestCentral, 246 }, + { LocationNames.IndonesiaCentral, 94 }, + { LocationNames.IsraelCentral, 168 }, + { LocationNames.ItalyNorth, 240 }, + { LocationNames.JapanEast, 125 }, + { LocationNames.JapanWest, 130 }, + { LocationNames.JioIndiaCentral, 144 }, + { LocationNames.JioIndiaWest, 144 }, + { LocationNames.KoreaCentral, 154 }, + { LocationNames.KoreaSouth, 148 }, + { LocationNames.MalaysiaSouth, 94 }, + { LocationNames.MalaysiaWest, 94 }, + { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 100 }, + { LocationNames.NorthCentralUS, 192 }, + { LocationNames.NorthEurope, 262 }, + { LocationNames.NorwayEast, 272 }, + { LocationNames.NorwayWest, 266 }, + { LocationNames.PolandCentral, 252 }, + { LocationNames.QatarCentral, 168 }, + { LocationNames.SouthAfricaNorth, 390 }, + { LocationNames.SouthAfricaWest, 394 }, + { LocationNames.SouthCentralUS, 174 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 94 }, + { LocationNames.SoutheastUS, 162 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 242 }, + { LocationNames.SwedenCentral, 272 }, + { LocationNames.SwedenSouth, 272 }, + { LocationNames.SwitzerlandNorth, 240 }, + { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, + { LocationNames.UAECentral, 168 }, + { LocationNames.UAENorth, 168 }, + { LocationNames.UKSouth, 250 }, + { LocationNames.UKWest, 252 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 170 }, + { LocationNames.WestEurope, 252 }, + { LocationNames.WestIndia, 142 }, + { LocationNames.WestUS, 142 }, + { LocationNames.WestUS2, 162 }, + { LocationNames.WestUS3, 162 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.AustraliaCentral2, + new Dictionary() + { + { LocationNames.AustraliaCentral, 2 }, + { LocationNames.AustraliaCentral2, 0 }, + { LocationNames.AustraliaEast, 6 }, + { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, + { LocationNames.BrazilSouth, 313 }, + { LocationNames.BrazilSoutheast, 313 }, + { LocationNames.CanadaCentral, 204 }, + { LocationNames.CanadaEast, 214 }, + { LocationNames.CentralIndia, 144 }, + { LocationNames.CentralUS, 184 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 120 }, + { LocationNames.EastUS, 205 }, + { LocationNames.EastUS2, 200 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 242 }, + { LocationNames.FranceSouth, 230 }, + { LocationNames.GermanyNorth, 256 }, + { LocationNames.GermanyWestCentral, 246 }, + { LocationNames.IndonesiaCentral, 92 }, + { LocationNames.IsraelCentral, 168 }, + { LocationNames.ItalyNorth, 240 }, + { LocationNames.JapanEast, 124 }, + { LocationNames.JapanWest, 132 }, + { LocationNames.JioIndiaCentral, 144 }, + { LocationNames.JioIndiaWest, 144 }, + { LocationNames.KoreaCentral, 154 }, + { LocationNames.KoreaSouth, 148 }, + { LocationNames.MalaysiaSouth, 92 }, + { LocationNames.MalaysiaWest, 92 }, + { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 2 }, + { LocationNames.NorthCentralUS, 192 }, + { LocationNames.NorthEurope, 262 }, + { LocationNames.NorwayEast, 272 }, + { LocationNames.NorwayWest, 266 }, + { LocationNames.PolandCentral, 252 }, + { LocationNames.QatarCentral, 168 }, + { LocationNames.SouthAfricaNorth, 391 }, + { LocationNames.SouthAfricaWest, 392 }, + { LocationNames.SouthCentralUS, 174 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 92 }, + { LocationNames.SoutheastUS, 162 }, + { LocationNames.SouthIndia, 124 }, + { LocationNames.SpainCentral, 242 }, + { LocationNames.SwedenCentral, 272 }, + { LocationNames.SwedenSouth, 272 }, + { LocationNames.SwitzerlandNorth, 240 }, + { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, + { LocationNames.UAECentral, 168 }, + { LocationNames.UAENorth, 168 }, + { LocationNames.UKSouth, 248 }, + { LocationNames.UKWest, 252 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 170 }, + { LocationNames.WestEurope, 252 }, + { LocationNames.WestIndia, 142 }, + { LocationNames.WestUS, 142 }, + { LocationNames.WestUS2, 162 }, + { LocationNames.WestUS3, 162 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.AustraliaEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 6 }, + { LocationNames.AustraliaCentral2, 6 }, + { LocationNames.AustraliaEast, 0 }, + { LocationNames.AustraliaSoutheast, 14 }, + { LocationNames.AustriaEast, 236 }, + { LocationNames.BrazilSouth, 308 }, + { LocationNames.BrazilSoutheast, 308 }, + { LocationNames.CanadaCentral, 200 }, + { LocationNames.CanadaEast, 210 }, + { LocationNames.CentralIndia, 140 }, + { LocationNames.CentralUS, 180 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 116 }, + { LocationNames.EastUS, 200 }, + { LocationNames.EastUS2, 196 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 238 }, + { LocationNames.FranceSouth, 224 }, + { LocationNames.GermanyNorth, 250 }, + { LocationNames.GermanyWestCentral, 240 }, + { LocationNames.IndonesiaCentral, 88 }, + { LocationNames.IsraelCentral, 164 }, + { LocationNames.ItalyNorth, 236 }, + { LocationNames.JapanEast, 118 }, + { LocationNames.JapanWest, 126 }, + { LocationNames.JioIndiaCentral, 140 }, + { LocationNames.JioIndiaWest, 140 }, + { LocationNames.KoreaCentral, 150 }, + { LocationNames.KoreaSouth, 143 }, + { LocationNames.MalaysiaSouth, 88 }, + { LocationNames.MalaysiaWest, 88 }, + { LocationNames.MexicoCentral, 158 }, + { LocationNames.NewZealandNorth, 6 }, + { LocationNames.NorthCentralUS, 187 }, + { LocationNames.NorthEurope, 258 }, + { LocationNames.NorwayEast, 266 }, + { LocationNames.NorwayWest, 260 }, + { LocationNames.PolandCentral, 248 }, + { LocationNames.QatarCentral, 164 }, + { LocationNames.SouthAfricaNorth, 386 }, + { LocationNames.SouthAfricaWest, 390 }, + { LocationNames.SouthCentralUS, 170 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 88 }, + { LocationNames.SoutheastUS, 158 }, + { LocationNames.SouthIndia, 120 }, + { LocationNames.SpainCentral, 238 }, + { LocationNames.SwedenCentral, 266 }, + { LocationNames.SwedenSouth, 266 }, + { LocationNames.SwitzerlandNorth, 236 }, + { LocationNames.SwitzerlandWest, 232 }, + { LocationNames.TaiwanNorth, 116 }, + { LocationNames.TaiwanNorthwest, 116 }, + { LocationNames.UAECentral, 164 }, + { LocationNames.UAENorth, 163 }, + { LocationNames.UKSouth, 246 }, + { LocationNames.UKWest, 248 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 166 }, + { LocationNames.WestEurope, 248 }, + { LocationNames.WestIndia, 138 }, + { LocationNames.WestUS, 138 }, + { LocationNames.WestUS2, 158 }, + { LocationNames.WestUS3, 158 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.AustraliaSoutheast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 18 }, + { LocationNames.AustraliaCentral2, 18 }, + { LocationNames.AustraliaEast, 14 }, + { LocationNames.AustraliaSoutheast, 0 }, + { LocationNames.AustriaEast, 232 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 210 }, + { LocationNames.CanadaEast, 220 }, + { LocationNames.CentralIndia, 136 }, + { LocationNames.CentralUS, 190 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 118 }, + { LocationNames.EastUS, 212 }, + { LocationNames.EastUS2, 206 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 235 }, + { LocationNames.FranceSouth, 222 }, + { LocationNames.GermanyNorth, 246 }, + { LocationNames.GermanyWestCentral, 238 }, + { LocationNames.IndonesiaCentral, 85 }, + { LocationNames.IsraelCentral, 160 }, + { LocationNames.ItalyNorth, 232 }, + { LocationNames.JapanEast, 130 }, + { LocationNames.JapanWest, 138 }, + { LocationNames.JioIndiaCentral, 136 }, + { LocationNames.JioIndiaWest, 136 }, + { LocationNames.KoreaCentral, 146 }, + { LocationNames.KoreaSouth, 140 }, + { LocationNames.MalaysiaSouth, 85 }, + { LocationNames.MalaysiaWest, 85 }, + { LocationNames.MexicoCentral, 168 }, + { LocationNames.NewZealandNorth, 18 }, + { LocationNames.NorthCentralUS, 198 }, + { LocationNames.NorthEurope, 260 }, + { LocationNames.NorwayEast, 264 }, + { LocationNames.NorwayWest, 258 }, + { LocationNames.PolandCentral, 244 }, + { LocationNames.QatarCentral, 160 }, + { LocationNames.SouthAfricaNorth, 382 }, + { LocationNames.SouthAfricaWest, 386 }, + { LocationNames.SouthCentralUS, 180 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 85 }, + { LocationNames.SoutheastUS, 168 }, + { LocationNames.SouthIndia, 118 }, + { LocationNames.SpainCentral, 235 }, + { LocationNames.SwedenCentral, 264 }, + { LocationNames.SwedenSouth, 264 }, + { LocationNames.SwitzerlandNorth, 232 }, + { LocationNames.SwitzerlandWest, 228 }, + { LocationNames.TaiwanNorth, 118 }, + { LocationNames.TaiwanNorthwest, 118 }, + { LocationNames.UAECentral, 160 }, + { LocationNames.UAENorth, 160 }, + { LocationNames.UKSouth, 242 }, + { LocationNames.UKWest, 245 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 176 }, + { LocationNames.WestEurope, 244 }, + { LocationNames.WestIndia, 134 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 168 }, + { LocationNames.WestUS3, 168 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.AustriaEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 240 }, + { LocationNames.AustraliaCentral2, 240 }, + { LocationNames.AustraliaEast, 236 }, + { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 0 }, + { LocationNames.BrazilSouth, 198 }, + { LocationNames.BrazilSoutheast, 198 }, + { LocationNames.CanadaCentral, 104 }, + { LocationNames.CanadaEast, 114 }, + { LocationNames.CentralIndia, 112 }, + { LocationNames.CentralUS, 112 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 182 }, + { LocationNames.EastUS, 92 }, + { LocationNames.EastUS2, 94 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 14 }, + { LocationNames.FranceSouth, 10 }, + { LocationNames.GermanyNorth, 16 }, + { LocationNames.GermanyWestCentral, 6 }, + { LocationNames.IndonesiaCentral, 148 }, + { LocationNames.IsraelCentral, 106 }, + { LocationNames.ItalyNorth, 100 }, + { LocationNames.JapanEast, 216 }, + { LocationNames.JapanWest, 216 }, + { LocationNames.JioIndiaCentral, 112 }, + { LocationNames.JioIndiaWest, 112 }, + { LocationNames.KoreaCentral, 210 }, + { LocationNames.KoreaSouth, 204 }, + { LocationNames.MalaysiaSouth, 148 }, + { LocationNames.MalaysiaWest, 148 }, + { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, + { LocationNames.NorthCentralUS, 110 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 32 }, + { LocationNames.NorwayWest, 26 }, + { LocationNames.PolandCentral, 12 }, + { LocationNames.QatarCentral, 106 }, + { LocationNames.SouthAfricaNorth, 172 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 118 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 148 }, + { LocationNames.SoutheastUS, 154 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, + { LocationNames.SwedenCentral, 32 }, + { LocationNames.SwedenSouth, 255 }, + { LocationNames.SwitzerlandNorth, 100 }, + { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, + { LocationNames.UAECentral, 106 }, + { LocationNames.UAENorth, 108 }, + { LocationNames.UKSouth, 20 }, + { LocationNames.UKWest, 22 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 134 }, + { LocationNames.WestEurope, 12 }, + { LocationNames.WestIndia, 116 }, + { LocationNames.WestUS, 150 }, + { LocationNames.WestUS2, 154 }, + { LocationNames.WestUS3, 154 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.BrazilSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 314 }, + { LocationNames.AustraliaCentral2, 313 }, + { LocationNames.AustraliaEast, 308 }, + { LocationNames.AustraliaSoutheast, 320 }, + { LocationNames.AustriaEast, 198 }, + { LocationNames.BrazilSouth, 0 }, + { LocationNames.BrazilSoutheast, 10 }, + { LocationNames.CanadaCentral, 132 }, + { LocationNames.CanadaEast, 141 }, + { LocationNames.CentralIndia, 302 }, + { LocationNames.CentralUS, 146 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 320 }, + { LocationNames.EastUS, 118 }, + { LocationNames.EastUS2, 122 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 186 }, + { LocationNames.FranceSouth, 200 }, + { LocationNames.GermanyNorth, 198 }, + { LocationNames.GermanyWestCentral, 192 }, + { LocationNames.IndonesiaCentral, 328 }, + { LocationNames.IsraelCentral, 296 }, + { LocationNames.ItalyNorth, 198 }, + { LocationNames.JapanEast, 262 }, + { LocationNames.JapanWest, 270 }, + { LocationNames.JioIndiaCentral, 302 }, + { LocationNames.JioIndiaWest, 302 }, + { LocationNames.KoreaCentral, 300 }, + { LocationNames.KoreaSouth, 306 }, + { LocationNames.MalaysiaSouth, 328 }, + { LocationNames.MalaysiaWest, 328 }, + { LocationNames.MexicoCentral, 182 }, + { LocationNames.NewZealandNorth, 314 }, + { LocationNames.NorthCentralUS, 138 }, + { LocationNames.NorthEurope, 177 }, + { LocationNames.NorwayEast, 208 }, + { LocationNames.NorwayWest, 201 }, + { LocationNames.PolandCentral, 188 }, + { LocationNames.QatarCentral, 296 }, + { LocationNames.SouthAfricaNorth, 342 }, + { LocationNames.SouthAfricaWest, 326 }, + { LocationNames.SouthCentralUS, 140 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 328 }, + { LocationNames.SoutheastUS, 182 }, + { LocationNames.SouthIndia, 314 }, + { LocationNames.SpainCentral, 186 }, + { LocationNames.SwedenCentral, 208 }, + { LocationNames.SwedenSouth, 208 }, + { LocationNames.SwitzerlandNorth, 198 }, + { LocationNames.SwitzerlandWest, 202 }, + { LocationNames.TaiwanNorth, 320 }, + { LocationNames.TaiwanNorthwest, 320 }, + { LocationNames.UAECentral, 296 }, + { LocationNames.UAENorth, 298 }, + { LocationNames.UKSouth, 181 }, + { LocationNames.UKWest, 184 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 160 }, + { LocationNames.WestEurope, 188 }, + { LocationNames.WestIndia, 304 }, + { LocationNames.WestUS, 172 }, + { LocationNames.WestUS2, 182 }, + { LocationNames.WestUS3, 182 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.BrazilSoutheast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 314 }, + { LocationNames.AustraliaCentral2, 313 }, + { LocationNames.AustraliaEast, 308 }, + { LocationNames.AustraliaSoutheast, 320 }, + { LocationNames.AustriaEast, 198 }, + { LocationNames.BrazilSouth, 10 }, + { LocationNames.BrazilSoutheast, 0 }, + { LocationNames.CanadaCentral, 132 }, + { LocationNames.CanadaEast, 141 }, + { LocationNames.CentralIndia, 302 }, + { LocationNames.CentralUS, 146 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 320 }, + { LocationNames.EastUS, 118 }, + { LocationNames.EastUS2, 122 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 186 }, + { LocationNames.FranceSouth, 200 }, + { LocationNames.GermanyNorth, 198 }, + { LocationNames.GermanyWestCentral, 192 }, + { LocationNames.IndonesiaCentral, 328 }, + { LocationNames.IsraelCentral, 296 }, + { LocationNames.ItalyNorth, 198 }, + { LocationNames.JapanEast, 262 }, + { LocationNames.JapanWest, 270 }, + { LocationNames.JioIndiaCentral, 302 }, + { LocationNames.JioIndiaWest, 302 }, + { LocationNames.KoreaCentral, 300 }, + { LocationNames.KoreaSouth, 306 }, + { LocationNames.MalaysiaSouth, 328 }, + { LocationNames.MalaysiaWest, 328 }, + { LocationNames.MexicoCentral, 182 }, + { LocationNames.NewZealandNorth, 314 }, + { LocationNames.NorthCentralUS, 138 }, + { LocationNames.NorthEurope, 177 }, + { LocationNames.NorwayEast, 208 }, + { LocationNames.NorwayWest, 201 }, + { LocationNames.PolandCentral, 188 }, + { LocationNames.QatarCentral, 296 }, + { LocationNames.SouthAfricaNorth, 342 }, + { LocationNames.SouthAfricaWest, 326 }, + { LocationNames.SouthCentralUS, 140 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 328 }, + { LocationNames.SoutheastUS, 182 }, + { LocationNames.SouthIndia, 314 }, + { LocationNames.SpainCentral, 186 }, + { LocationNames.SwedenCentral, 208 }, + { LocationNames.SwedenSouth, 208 }, + { LocationNames.SwitzerlandNorth, 198 }, + { LocationNames.SwitzerlandWest, 202 }, + { LocationNames.TaiwanNorth, 320 }, + { LocationNames.TaiwanNorthwest, 320 }, + { LocationNames.UAECentral, 296 }, + { LocationNames.UAENorth, 298 }, + { LocationNames.UKSouth, 181 }, + { LocationNames.UKWest, 184 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 160 }, + { LocationNames.WestEurope, 188 }, + { LocationNames.WestIndia, 304 }, + { LocationNames.WestUS, 172 }, + { LocationNames.WestUS2, 172 }, + { LocationNames.WestUS3, 182 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.CanadaCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 204 }, + { LocationNames.AustraliaCentral2, 204 }, + { LocationNames.AustraliaEast, 200 }, + { LocationNames.AustraliaSoutheast, 210 }, + { LocationNames.AustriaEast, 104 }, + { LocationNames.BrazilSouth, 132 }, + { LocationNames.BrazilSoutheast, 132 }, + { LocationNames.CanadaCentral, 0 }, + { LocationNames.CanadaEast, 12 }, + { LocationNames.CentralIndia, 208 }, + { LocationNames.CentralUS, 21 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 196 }, + { LocationNames.EastUS, 25 }, + { LocationNames.EastUS2, 28 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 92 }, + { LocationNames.FranceSouth, 106 }, + { LocationNames.GermanyNorth, 104 }, + { LocationNames.GermanyWestCentral, 98 }, + { LocationNames.IndonesiaCentral, 216 }, + { LocationNames.IsraelCentral, 201 }, + { LocationNames.ItalyNorth, 104 }, + { LocationNames.JapanEast, 152 }, + { LocationNames.JapanWest, 160 }, + { LocationNames.JioIndiaCentral, 208 }, + { LocationNames.JioIndiaWest, 208 }, + { LocationNames.KoreaCentral, 178 }, + { LocationNames.KoreaSouth, 182 }, + { LocationNames.MalaysiaSouth, 216 }, + { LocationNames.MalaysiaWest, 216 }, + { LocationNames.MexicoCentral, 57 }, + { LocationNames.NewZealandNorth, 204 }, + { LocationNames.NorthCentralUS, 14 }, + { LocationNames.NorthEurope, 84 }, + { LocationNames.NorwayEast, 114 }, + { LocationNames.NorwayWest, 108 }, + { LocationNames.PolandCentral, 94 }, + { LocationNames.QatarCentral, 201 }, + { LocationNames.SouthAfricaNorth, 246 }, + { LocationNames.SouthAfricaWest, 230 }, + { LocationNames.SouthCentralUS, 42 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 216 }, + { LocationNames.SoutheastUS, 57 }, + { LocationNames.SouthIndia, 220 }, + { LocationNames.SpainCentral, 92 }, + { LocationNames.SwedenCentral, 114 }, + { LocationNames.SwedenSouth, 114 }, + { LocationNames.SwitzerlandNorth, 104 }, + { LocationNames.SwitzerlandWest, 108 }, + { LocationNames.TaiwanNorth, 196 }, + { LocationNames.TaiwanNorthwest, 196 }, + { LocationNames.UAECentral, 201 }, + { LocationNames.UAENorth, 204 }, + { LocationNames.UKSouth, 86 }, + { LocationNames.UKWest, 90 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 36 }, + { LocationNames.WestEurope, 94 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 64 }, + { LocationNames.WestUS2, 57 }, + { LocationNames.WestUS3, 57 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.CanadaEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 214 }, + { LocationNames.AustraliaCentral2, 214 }, + { LocationNames.AustraliaEast, 210 }, + { LocationNames.AustraliaSoutheast, 220 }, + { LocationNames.AustriaEast, 114 }, + { LocationNames.BrazilSouth, 141 }, + { LocationNames.BrazilSoutheast, 141 }, + { LocationNames.CanadaCentral, 12 }, + { LocationNames.CanadaEast, 0 }, + { LocationNames.CentralIndia, 218 }, + { LocationNames.CentralUS, 30 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 206 }, + { LocationNames.EastUS, 34 }, + { LocationNames.EastUS2, 38 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 102 }, + { LocationNames.FranceSouth, 116 }, + { LocationNames.GermanyNorth, 114 }, + { LocationNames.GermanyWestCentral, 108 }, + { LocationNames.IndonesiaCentral, 224 }, + { LocationNames.IsraelCentral, 210 }, + { LocationNames.ItalyNorth, 114 }, + { LocationNames.JapanEast, 162 }, + { LocationNames.JapanWest, 170 }, + { LocationNames.JioIndiaCentral, 218 }, + { LocationNames.JioIndiaWest, 218 }, + { LocationNames.KoreaCentral, 186 }, + { LocationNames.KoreaSouth, 192 }, + { LocationNames.MalaysiaSouth, 224 }, + { LocationNames.MalaysiaWest, 224 }, + { LocationNames.MexicoCentral, 66 }, + { LocationNames.NewZealandNorth, 214 }, + { LocationNames.NorthCentralUS, 24 }, + { LocationNames.NorthEurope, 93 }, + { LocationNames.NorwayEast, 124 }, + { LocationNames.NorwayWest, 116 }, + { LocationNames.PolandCentral, 103 }, + { LocationNames.QatarCentral, 210 }, + { LocationNames.SouthAfricaNorth, 256 }, + { LocationNames.SouthAfricaWest, 238 }, + { LocationNames.SouthCentralUS, 52 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 224 }, + { LocationNames.SoutheastUS, 66 }, + { LocationNames.SouthIndia, 230 }, + { LocationNames.SpainCentral, 102 }, + { LocationNames.SwedenCentral, 124 }, + { LocationNames.SwedenSouth, 124 }, + { LocationNames.SwitzerlandNorth, 114 }, + { LocationNames.SwitzerlandWest, 118 }, + { LocationNames.TaiwanNorth, 206 }, + { LocationNames.TaiwanNorthwest, 206 }, + { LocationNames.UAECentral, 210 }, + { LocationNames.UAENorth, 214 }, + { LocationNames.UKSouth, 96 }, + { LocationNames.UKWest, 98 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 44 }, + { LocationNames.WestEurope, 103 }, + { LocationNames.WestIndia, 220 }, + { LocationNames.WestUS, 72 }, + { LocationNames.WestUS2, 66 }, + { LocationNames.WestUS3, 66 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.CentralIndia, + new Dictionary() + { + { LocationNames.AustraliaCentral, 144 }, + { LocationNames.AustraliaCentral2, 144 }, + { LocationNames.AustraliaEast, 140 }, + { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, + { LocationNames.BrazilSouth, 302 }, + { LocationNames.BrazilSoutheast, 302 }, + { LocationNames.CanadaCentral, 208 }, + { LocationNames.CanadaEast, 218 }, + { LocationNames.CentralIndia, 0 }, + { LocationNames.CentralUS, 222 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 86 }, + { LocationNames.EastUS, 196 }, + { LocationNames.EastUS2, 198 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 116 }, + { LocationNames.FranceSouth, 102 }, + { LocationNames.GermanyNorth, 128 }, + { LocationNames.GermanyWestCentral, 118 }, + { LocationNames.IndonesiaCentral, 52 }, + { LocationNames.IsraelCentral, 30 }, + { LocationNames.ItalyNorth, 112 }, + { LocationNames.JapanEast, 120 }, + { LocationNames.JapanWest, 124 }, + { LocationNames.JioIndiaCentral, 100 }, + { LocationNames.JioIndiaWest, 100 }, + { LocationNames.KoreaCentral, 114 }, + { LocationNames.KoreaSouth, 106 }, + { LocationNames.MalaysiaSouth, 52 }, + { LocationNames.MalaysiaWest, 52 }, + { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, + { LocationNames.NorthCentralUS, 216 }, + { LocationNames.NorthEurope, 137 }, + { LocationNames.NorwayEast, 146 }, + { LocationNames.NorwayWest, 136 }, + { LocationNames.PolandCentral, 126 }, + { LocationNames.QatarCentral, 30 }, + { LocationNames.SouthAfricaNorth, 264 }, + { LocationNames.SouthAfricaWest, 267 }, + { LocationNames.SouthCentralUS, 224 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 52 }, + { LocationNames.SoutheastUS, 212 }, + { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, + { LocationNames.SwedenCentral, 146 }, + { LocationNames.SwedenSouth, 146 }, + { LocationNames.SwitzerlandNorth, 112 }, + { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, + { LocationNames.UAECentral, 30 }, + { LocationNames.UAENorth, 30 }, + { LocationNames.UKSouth, 122 }, + { LocationNames.UKWest, 126 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 236 }, + { LocationNames.WestEurope, 126 }, + { LocationNames.WestIndia, 4 }, + { LocationNames.WestUS, 218 }, + { LocationNames.WestUS2, 212 }, + { LocationNames.WestUS3, 212 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.CentralUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 184 }, + { LocationNames.AustraliaCentral2, 184 }, + { LocationNames.AustraliaEast, 180 }, + { LocationNames.AustraliaSoutheast, 190 }, + { LocationNames.AustriaEast, 112 }, + { LocationNames.BrazilSouth, 146 }, + { LocationNames.BrazilSoutheast, 146 }, + { LocationNames.CanadaCentral, 21 }, + { LocationNames.CanadaEast, 30 }, + { LocationNames.CentralIndia, 222 }, + { LocationNames.CentralUS, 0 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 176 }, + { LocationNames.EastUS, 23 }, + { LocationNames.EastUS2, 26 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 101 }, + { LocationNames.FranceSouth, 110 }, + { LocationNames.GermanyNorth, 118 }, + { LocationNames.GermanyWestCentral, 112 }, + { LocationNames.IndonesiaCentral, 194 }, + { LocationNames.IsraelCentral, 216 }, + { LocationNames.ItalyNorth, 112 }, + { LocationNames.JapanEast, 140 }, + { LocationNames.JapanWest, 143 }, + { LocationNames.JioIndiaCentral, 222 }, + { LocationNames.JioIndiaWest, 222 }, + { LocationNames.KoreaCentral, 158 }, + { LocationNames.KoreaSouth, 162 }, + { LocationNames.MalaysiaSouth, 194 }, + { LocationNames.MalaysiaWest, 194 }, + { LocationNames.MexicoCentral, 36 }, + { LocationNames.NewZealandNorth, 184 }, + { LocationNames.NorthCentralUS, 8 }, + { LocationNames.NorthEurope, 92 }, + { LocationNames.NorwayEast, 128 }, + { LocationNames.NorwayWest, 121 }, + { LocationNames.PolandCentral, 102 }, + { LocationNames.QatarCentral, 216 }, + { LocationNames.SouthAfricaNorth, 260 }, + { LocationNames.SouthAfricaWest, 244 }, + { LocationNames.SouthCentralUS, 22 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 194 }, + { LocationNames.SoutheastUS, 36 }, + { LocationNames.SouthIndia, 228 }, + { LocationNames.SpainCentral, 101 }, + { LocationNames.SwedenCentral, 128 }, + { LocationNames.SwedenSouth, 128 }, + { LocationNames.SwitzerlandNorth, 112 }, + { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 176 }, + { LocationNames.TaiwanNorthwest, 176 }, + { LocationNames.UAECentral, 216 }, + { LocationNames.UAENorth, 218 }, + { LocationNames.UKSouth, 96 }, + { LocationNames.UKWest, 96 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 15 }, + { LocationNames.WestEurope, 102 }, + { LocationNames.WestIndia, 224 }, + { LocationNames.WestUS, 44 }, + { LocationNames.WestUS2, 36 }, + { LocationNames.WestUS3, 36 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 0 }, + { LocationNames.ChinaEast2, 255 }, + { LocationNames.ChinaEast3, 255 }, + { LocationNames.ChinaNorth, 35 }, + { LocationNames.ChinaNorth2, 255 }, + { LocationNames.ChinaNorth3, 255 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaEast2, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 255 }, + { LocationNames.ChinaEast2, 0 }, + { LocationNames.ChinaEast3, 255 }, + { LocationNames.ChinaNorth, 255 }, + { LocationNames.ChinaNorth2, 35 }, + { LocationNames.ChinaNorth3, 255 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaEast3, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 255 }, + { LocationNames.ChinaEast2, 255 }, + { LocationNames.ChinaEast3, 0 }, + { LocationNames.ChinaNorth, 255 }, + { LocationNames.ChinaNorth2, 255 }, + { LocationNames.ChinaNorth3, 100 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 35 }, + { LocationNames.ChinaEast2, 255 }, + { LocationNames.ChinaEast3, 255 }, + { LocationNames.ChinaNorth, 0 }, + { LocationNames.ChinaNorth2, 255 }, + { LocationNames.ChinaNorth3, 255 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaNorth2, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 255 }, + { LocationNames.ChinaEast2, 35 }, + { LocationNames.ChinaEast3, 255 }, + { LocationNames.ChinaNorth, 255 }, + { LocationNames.ChinaNorth2, 0 }, + { LocationNames.ChinaNorth3, 255 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ChinaNorth3, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, 255 }, + { LocationNames.ChinaEast2, 255 }, + { LocationNames.ChinaEast3, 100 }, + { LocationNames.ChinaNorth, 255 }, + { LocationNames.ChinaNorth2, 255 }, + { LocationNames.ChinaNorth3, 0 }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.EastAsia, + new Dictionary() + { + { LocationNames.AustraliaCentral, 120 }, + { LocationNames.AustraliaCentral2, 120 }, + { LocationNames.AustraliaEast, 116 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 196 }, + { LocationNames.CanadaEast, 206 }, + { LocationNames.CentralIndia, 86 }, + { LocationNames.CentralUS, 176 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 0 }, + { LocationNames.EastUS, 199 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 184 }, + { LocationNames.FranceSouth, 172 }, + { LocationNames.GermanyNorth, 196 }, + { LocationNames.GermanyWestCentral, 188 }, + { LocationNames.IndonesiaCentral, 33 }, + { LocationNames.IsraelCentral, 110 }, + { LocationNames.ItalyNorth, 182 }, + { LocationNames.JapanEast, 50 }, + { LocationNames.JapanWest, 50 }, + { LocationNames.JioIndiaCentral, 86 }, + { LocationNames.JioIndiaWest, 86 }, + { LocationNames.KoreaCentral, 56 }, + { LocationNames.KoreaSouth, 60 }, + { LocationNames.MalaysiaSouth, 33 }, + { LocationNames.MalaysiaWest, 33 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, + { LocationNames.NorthCentralUS, 184 }, + { LocationNames.NorthEurope, 205 }, + { LocationNames.NorwayEast, 214 }, + { LocationNames.NorwayWest, 206 }, + { LocationNames.PolandCentral, 193 }, + { LocationNames.QatarCentral, 110 }, + { LocationNames.SouthAfricaNorth, 332 }, + { LocationNames.SouthAfricaWest, 336 }, + { LocationNames.SouthCentralUS, 182 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 33 }, + { LocationNames.SoutheastUS, 140 }, + { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, + { LocationNames.SwedenCentral, 214 }, + { LocationNames.SwedenSouth, 214 }, + { LocationNames.SwitzerlandNorth, 182 }, + { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 100 }, + { LocationNames.TaiwanNorthwest, 100 }, + { LocationNames.UAECentral, 110 }, + { LocationNames.UAENorth, 109 }, + { LocationNames.UKSouth, 192 }, + { LocationNames.UKWest, 194 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 162 }, + { LocationNames.WestEurope, 193 }, + { LocationNames.WestIndia, 84 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.EastUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 205 }, + { LocationNames.AustraliaCentral2, 205 }, + { LocationNames.AustraliaEast, 200 }, + { LocationNames.AustraliaSoutheast, 212 }, + { LocationNames.AustriaEast, 92 }, + { LocationNames.BrazilSouth, 118 }, + { LocationNames.BrazilSoutheast, 118 }, + { LocationNames.CanadaCentral, 25 }, + { LocationNames.CanadaEast, 34 }, + { LocationNames.CentralIndia, 196 }, + { LocationNames.CentralUS, 23 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 199 }, + { LocationNames.EastUS, 0 }, + { LocationNames.EastUS2, 6 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 0 }, + { LocationNames.FranceCentral, 80 }, + { LocationNames.FranceSouth, 90 }, + { LocationNames.GermanyNorth, 91 }, + { LocationNames.GermanyWestCentral, 86 }, + { LocationNames.IndonesiaCentral, 218 }, + { LocationNames.IsraelCentral, 189 }, + { LocationNames.ItalyNorth, 92 }, + { LocationNames.JapanEast, 162 }, + { LocationNames.JapanWest, 168 }, + { LocationNames.JioIndiaCentral, 196 }, + { LocationNames.JioIndiaWest, 196 }, + { LocationNames.KoreaCentral, 182 }, + { LocationNames.KoreaSouth, 186 }, + { LocationNames.MalaysiaSouth, 218 }, + { LocationNames.MalaysiaWest, 218 }, + { LocationNames.MexicoCentral, 58 }, + { LocationNames.NewZealandNorth, 205 }, + { LocationNames.NorthCentralUS, 19 }, + { LocationNames.NorthEurope, 76 }, + { LocationNames.NorwayEast, 101 }, + { LocationNames.NorwayWest, 94 }, + { LocationNames.PolandCentral, 81 }, + { LocationNames.QatarCentral, 189 }, + { LocationNames.SouthAfricaNorth, 234 }, + { LocationNames.SouthAfricaWest, 218 }, + { LocationNames.SouthCentralUS, 32 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 218 }, + { LocationNames.SoutheastUS, 58 }, + { LocationNames.SouthIndia, 208 }, + { LocationNames.SpainCentral, 80 }, + { LocationNames.SwedenCentral, 101 }, + { LocationNames.SwedenSouth, 101 }, + { LocationNames.SwitzerlandNorth, 92 }, + { LocationNames.SwitzerlandWest, 88 }, + { LocationNames.TaiwanNorth, 199 }, + { LocationNames.TaiwanNorthwest, 199 }, + { LocationNames.UAECentral, 189 }, + { LocationNames.UAENorth, 192 }, + { LocationNames.UKSouth, 74 }, + { LocationNames.UKWest, 76 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 38 }, + { LocationNames.WestEurope, 81 }, + { LocationNames.WestIndia, 198 }, + { LocationNames.WestUS, 64 }, + { LocationNames.WestUS2, 58 }, + { LocationNames.WestUS3, 58 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.EastUS2, + new Dictionary() + { + { LocationNames.AustraliaCentral, 200 }, + { LocationNames.AustraliaCentral2, 200 }, + { LocationNames.AustraliaEast, 196 }, + { LocationNames.AustraliaSoutheast, 206 }, + { LocationNames.AustriaEast, 94 }, + { LocationNames.BrazilSouth, 122 }, + { LocationNames.BrazilSoutheast, 122 }, + { LocationNames.CanadaCentral, 28 }, + { LocationNames.CanadaEast, 38 }, + { LocationNames.CentralIndia, 198 }, + { LocationNames.CentralUS, 26 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 210 }, + { LocationNames.EastUS, 6 }, + { LocationNames.EastUS2, 0 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 6 }, + { LocationNames.FranceCentral, 80 }, + { LocationNames.FranceSouth, 90 }, + { LocationNames.GermanyNorth, 94 }, + { LocationNames.GermanyWestCentral, 90 }, + { LocationNames.IndonesiaCentral, 226 }, + { LocationNames.IsraelCentral, 190 }, + { LocationNames.ItalyNorth, 94 }, + { LocationNames.JapanEast, 164 }, + { LocationNames.JapanWest, 164 }, + { LocationNames.JioIndiaCentral, 198 }, + { LocationNames.JioIndiaWest, 198 }, + { LocationNames.KoreaCentral, 176 }, + { LocationNames.KoreaSouth, 182 }, + { LocationNames.MalaysiaSouth, 226 }, + { LocationNames.MalaysiaWest, 226 }, + { LocationNames.MexicoCentral, 68 }, + { LocationNames.NewZealandNorth, 200 }, + { LocationNames.NorthCentralUS, 22 }, + { LocationNames.NorthEurope, 75 }, + { LocationNames.NorwayEast, 104 }, + { LocationNames.NorwayWest, 98 }, + { LocationNames.PolandCentral, 86 }, + { LocationNames.QatarCentral, 190 }, + { LocationNames.SouthAfricaNorth, 240 }, + { LocationNames.SouthAfricaWest, 222 }, + { LocationNames.SouthCentralUS, 26 }, + { LocationNames.SouthCentralUSSTG, 26 }, + { LocationNames.SoutheastAsia, 226 }, + { LocationNames.SoutheastUS, 68 }, + { LocationNames.SouthIndia, 210 }, + { LocationNames.SpainCentral, 80 }, + { LocationNames.SwedenCentral, 104 }, + { LocationNames.SwedenSouth, 104 }, + { LocationNames.SwitzerlandNorth, 94 }, + { LocationNames.SwitzerlandWest, 88 }, + { LocationNames.TaiwanNorth, 210 }, + { LocationNames.TaiwanNorthwest, 210 }, + { LocationNames.UAECentral, 190 }, + { LocationNames.UAENorth, 194 }, + { LocationNames.UKSouth, 78 }, + { LocationNames.UKWest, 80 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 47 }, + { LocationNames.WestEurope, 86 }, + { LocationNames.WestIndia, 200 }, + { LocationNames.WestUS, 58 }, + { LocationNames.WestUS2, 68 }, + { LocationNames.WestUS3, 68 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.EastUSSLV, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, 0 }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, 255 }, + { LocationNames.SwedenSouth, 255 }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, 255 }, + { LocationNames.EastUS2EUAP, 255 }, + } + }, + { + LocationNames.EastUSSTG, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, 0 }, + { LocationNames.EastUS2, 6 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 0 }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, 218 }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, 218 }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, 19 }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, 32 }, + { LocationNames.SoutheastAsia, 218 }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, 58 }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.FranceCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 242 }, + { LocationNames.AustraliaCentral2, 242 }, + { LocationNames.AustraliaEast, 238 }, + { LocationNames.AustraliaSoutheast, 235 }, + { LocationNames.AustriaEast, 14 }, + { LocationNames.BrazilSouth, 186 }, + { LocationNames.BrazilSoutheast, 186 }, + { LocationNames.CanadaCentral, 92 }, + { LocationNames.CanadaEast, 102 }, + { LocationNames.CentralIndia, 116 }, + { LocationNames.CentralUS, 101 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 184 }, + { LocationNames.EastUS, 80 }, + { LocationNames.EastUS2, 80 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 0 }, + { LocationNames.FranceSouth, 11 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 10 }, + { LocationNames.IndonesiaCentral, 150 }, + { LocationNames.IsraelCentral, 108 }, + { LocationNames.ItalyNorth, 14 }, + { LocationNames.JapanEast, 218 }, + { LocationNames.JapanWest, 218 }, + { LocationNames.JioIndiaCentral, 116 }, + { LocationNames.JioIndiaWest, 116 }, + { LocationNames.KoreaCentral, 212 }, + { LocationNames.KoreaSouth, 206 }, + { LocationNames.MalaysiaSouth, 150 }, + { LocationNames.MalaysiaWest, 150 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 242 }, + { LocationNames.NorthCentralUS, 96 }, + { LocationNames.NorthEurope, 27 }, + { LocationNames.NorwayEast, 30 }, + { LocationNames.NorwayWest, 24 }, + { LocationNames.PolandCentral, 10 }, + { LocationNames.QatarCentral, 108 }, + { LocationNames.SouthAfricaNorth, 166 }, + { LocationNames.SouthAfricaWest, 150 }, + { LocationNames.SouthCentralUS, 106 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 150 }, + { LocationNames.SoutheastUS, 140 }, + { LocationNames.SouthIndia, 128 }, + { LocationNames.SpainCentral, 100 }, + { LocationNames.SwedenCentral, 30 }, + { LocationNames.SwedenSouth, 30 }, + { LocationNames.SwitzerlandNorth, 14 }, + { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, + { LocationNames.UAECentral, 108 }, + { LocationNames.UAENorth, 112 }, + { LocationNames.UKSouth, 7 }, + { LocationNames.UKWest, 8 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 119 }, + { LocationNames.WestEurope, 10 }, + { LocationNames.WestIndia, 118 }, + { LocationNames.WestUS, 138 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.FranceSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 230 }, + { LocationNames.AustraliaCentral2, 230 }, + { LocationNames.AustraliaEast, 224 }, + { LocationNames.AustraliaSoutheast, 222 }, + { LocationNames.AustriaEast, 10 }, + { LocationNames.BrazilSouth, 200 }, + { LocationNames.BrazilSoutheast, 200 }, + { LocationNames.CanadaCentral, 106 }, + { LocationNames.CanadaEast, 116 }, + { LocationNames.CentralIndia, 102 }, + { LocationNames.CentralUS, 110 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 172 }, + { LocationNames.EastUS, 90 }, + { LocationNames.EastUS2, 90 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 11 }, + { LocationNames.FranceSouth, 0 }, + { LocationNames.GermanyNorth, 26 }, + { LocationNames.GermanyWestCentral, 17 }, + { LocationNames.IndonesiaCentral, 138 }, + { LocationNames.IsraelCentral, 96 }, + { LocationNames.ItalyNorth, 10 }, + { LocationNames.JapanEast, 204 }, + { LocationNames.JapanWest, 206 }, + { LocationNames.JioIndiaCentral, 102 }, + { LocationNames.JioIndiaWest, 102 }, + { LocationNames.KoreaCentral, 200 }, + { LocationNames.KoreaSouth, 193 }, + { LocationNames.MalaysiaSouth, 138 }, + { LocationNames.MalaysiaWest, 138 }, + { LocationNames.MexicoCentral, 146 }, + { LocationNames.NewZealandNorth, 230 }, + { LocationNames.NorthCentralUS, 104 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 42 }, + { LocationNames.NorwayWest, 36 }, + { LocationNames.PolandCentral, 20 }, + { LocationNames.QatarCentral, 96 }, + { LocationNames.SouthAfricaNorth, 162 }, + { LocationNames.SouthAfricaWest, 166 }, + { LocationNames.SouthCentralUS, 116 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 138 }, + { LocationNames.SoutheastUS, 146 }, + { LocationNames.SouthIndia, 114 }, + { LocationNames.SpainCentral, 11 }, + { LocationNames.SwedenCentral, 42 }, + { LocationNames.SwedenSouth, 42 }, + { LocationNames.SwitzerlandNorth, 10 }, + { LocationNames.SwitzerlandWest, 8 }, + { LocationNames.TaiwanNorth, 172 }, + { LocationNames.TaiwanNorthwest, 172 }, + { LocationNames.UAECentral, 96 }, + { LocationNames.UAENorth, 98 }, + { LocationNames.UKSouth, 16 }, + { LocationNames.UKWest, 18 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 126 }, + { LocationNames.WestEurope, 20 }, + { LocationNames.WestIndia, 106 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 146 }, + { LocationNames.WestUS3, 146 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.GermanyNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 254 }, + { LocationNames.AustraliaCentral2, 256 }, + { LocationNames.AustraliaEast, 250 }, + { LocationNames.AustraliaSoutheast, 246 }, + { LocationNames.AustriaEast, 16 }, + { LocationNames.BrazilSouth, 198 }, + { LocationNames.BrazilSoutheast, 198 }, + { LocationNames.CanadaCentral, 104 }, + { LocationNames.CanadaEast, 114 }, + { LocationNames.CentralIndia, 128 }, + { LocationNames.CentralUS, 118 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 196 }, + { LocationNames.EastUS, 91 }, + { LocationNames.EastUS2, 94 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 20 }, + { LocationNames.FranceSouth, 26 }, + { LocationNames.GermanyNorth, 0 }, + { LocationNames.GermanyWestCentral, 10 }, + { LocationNames.IndonesiaCentral, 162 }, + { LocationNames.IsraelCentral, 120 }, + { LocationNames.ItalyNorth, 16 }, + { LocationNames.JapanEast, 230 }, + { LocationNames.JapanWest, 230 }, + { LocationNames.JioIndiaCentral, 128 }, + { LocationNames.JioIndiaWest, 128 }, + { LocationNames.KoreaCentral, 224 }, + { LocationNames.KoreaSouth, 218 }, + { LocationNames.MalaysiaSouth, 162 }, + { LocationNames.MalaysiaWest, 162 }, + { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 254 }, + { LocationNames.NorthCentralUS, 112 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 20 }, + { LocationNames.NorwayWest, 26 }, + { LocationNames.PolandCentral, 10 }, + { LocationNames.QatarCentral, 120 }, + { LocationNames.SouthAfricaNorth, 178 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 120 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 162 }, + { LocationNames.SoutheastUS, 154 }, + { LocationNames.SouthIndia, 140 }, + { LocationNames.SpainCentral, 20 }, + { LocationNames.SwedenCentral, 20 }, + { LocationNames.SwedenSouth, 20 }, + { LocationNames.SwitzerlandNorth, 16 }, + { LocationNames.SwitzerlandWest, 20 }, + { LocationNames.TaiwanNorth, 196 }, + { LocationNames.TaiwanNorthwest, 196 }, + { LocationNames.UAECentral, 120 }, + { LocationNames.UAENorth, 124 }, + { LocationNames.UKSouth, 20 }, + { LocationNames.UKWest, 22 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 132 }, + { LocationNames.WestEurope, 10 }, + { LocationNames.WestIndia, 130 }, + { LocationNames.WestUS, 153 }, + { LocationNames.WestUS2, 154 }, + { LocationNames.WestUS3, 154 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.GermanyWestCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 246 }, + { LocationNames.AustraliaCentral2, 246 }, + { LocationNames.AustraliaEast, 240 }, + { LocationNames.AustraliaSoutheast, 238 }, + { LocationNames.AustriaEast, 6 }, + { LocationNames.BrazilSouth, 192 }, + { LocationNames.BrazilSoutheast, 192 }, + { LocationNames.CanadaCentral, 98 }, + { LocationNames.CanadaEast, 108 }, + { LocationNames.CentralIndia, 118 }, + { LocationNames.CentralUS, 112 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 188 }, + { LocationNames.EastUS, 86 }, + { LocationNames.EastUS2, 90 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 10 }, + { LocationNames.FranceSouth, 17 }, + { LocationNames.GermanyNorth, 10 }, + { LocationNames.GermanyWestCentral, 0 }, + { LocationNames.IndonesiaCentral, 154 }, + { LocationNames.IsraelCentral, 112 }, + { LocationNames.ItalyNorth, 6 }, + { LocationNames.JapanEast, 220 }, + { LocationNames.JapanWest, 220 }, + { LocationNames.JioIndiaCentral, 118 }, + { LocationNames.JioIndiaWest, 118 }, + { LocationNames.KoreaCentral, 216 }, + { LocationNames.KoreaSouth, 209 }, + { LocationNames.MalaysiaSouth, 154 }, + { LocationNames.MalaysiaWest, 154 }, + { LocationNames.MexicoCentral, 148 }, + { LocationNames.NewZealandNorth, 246 }, + { LocationNames.NorthCentralUS, 106 }, + { LocationNames.NorthEurope, 25 }, + { LocationNames.NorwayEast, 26 }, + { LocationNames.NorwayWest, 20 }, + { LocationNames.PolandCentral, 8 }, + { LocationNames.QatarCentral, 112 }, + { LocationNames.SouthAfricaNorth, 178 }, + { LocationNames.SouthAfricaWest, 156 }, + { LocationNames.SouthCentralUS, 116 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 154 }, + { LocationNames.SoutheastUS, 148 }, + { LocationNames.SouthIndia, 130 }, + { LocationNames.SpainCentral, 10 }, + { LocationNames.SwedenCentral, 26 }, + { LocationNames.SwedenSouth, 26 }, + { LocationNames.SwitzerlandNorth, 6 }, + { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 188 }, + { LocationNames.TaiwanNorthwest, 188 }, + { LocationNames.UAECentral, 112 }, + { LocationNames.UAENorth, 114 }, + { LocationNames.UKSouth, 14 }, + { LocationNames.UKWest, 18 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 126 }, + { LocationNames.WestEurope, 8 }, + { LocationNames.WestIndia, 122 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 148 }, + { LocationNames.WestUS3, 148 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.IndonesiaCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 94 }, + { LocationNames.AustraliaCentral2, 92 }, + { LocationNames.AustraliaEast, 88 }, + { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, + { LocationNames.BrazilSouth, 328 }, + { LocationNames.BrazilSoutheast, 328 }, + { LocationNames.CanadaCentral, 216 }, + { LocationNames.CanadaEast, 224 }, + { LocationNames.CentralIndia, 52 }, + { LocationNames.CentralUS, 194 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 33 }, + { LocationNames.EastUS, 218 }, + { LocationNames.EastUS2, 226 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 218 }, + { LocationNames.FranceCentral, 150 }, + { LocationNames.FranceSouth, 138 }, + { LocationNames.GermanyNorth, 162 }, + { LocationNames.GermanyWestCentral, 154 }, + { LocationNames.IndonesiaCentral, 0 }, + { LocationNames.IsraelCentral, 76 }, + { LocationNames.ItalyNorth, 148 }, + { LocationNames.JapanEast, 68 }, + { LocationNames.JapanWest, 74 }, + { LocationNames.JioIndiaCentral, 52 }, + { LocationNames.JioIndiaWest, 52 }, + { LocationNames.KoreaCentral, 62 }, + { LocationNames.KoreaSouth, 56 }, + { LocationNames.MalaysiaSouth, 100 }, + { LocationNames.MalaysiaWest, 100 }, + { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, + { LocationNames.NorthCentralUS, 202 }, + { LocationNames.NorthEurope, 172 }, + { LocationNames.NorwayEast, 180 }, + { LocationNames.NorwayWest, 174 }, + { LocationNames.PolandCentral, 160 }, + { LocationNames.QatarCentral, 76 }, + { LocationNames.SouthAfricaNorth, 298 }, + { LocationNames.SouthAfricaWest, 302 }, + { LocationNames.SouthCentralUS, 200 }, + { LocationNames.SouthCentralUSSTG, 200 }, + { LocationNames.SoutheastAsia, 100 }, + { LocationNames.SoutheastUS, 160 }, + { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, + { LocationNames.SwedenCentral, 180 }, + { LocationNames.SwedenSouth, 180 }, + { LocationNames.SwitzerlandNorth, 148 }, + { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, + { LocationNames.UAECentral, 76 }, + { LocationNames.UAENorth, 76 }, + { LocationNames.UKSouth, 158 }, + { LocationNames.UKWest, 161 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 180 }, + { LocationNames.WestEurope, 160 }, + { LocationNames.WestIndia, 50 }, + { LocationNames.WestUS, 168 }, + { LocationNames.WestUS2, 160 }, + { LocationNames.WestUS3, 160 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.IsraelCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 168 }, + { LocationNames.AustraliaCentral2, 168 }, + { LocationNames.AustraliaEast, 164 }, + { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, + { LocationNames.BrazilSouth, 296 }, + { LocationNames.BrazilSoutheast, 296 }, + { LocationNames.CanadaCentral, 201 }, + { LocationNames.CanadaEast, 210 }, + { LocationNames.CentralIndia, 30 }, + { LocationNames.CentralUS, 216 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 110 }, + { LocationNames.EastUS, 189 }, + { LocationNames.EastUS2, 190 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 108 }, + { LocationNames.FranceSouth, 96 }, + { LocationNames.GermanyNorth, 120 }, + { LocationNames.GermanyWestCentral, 112 }, + { LocationNames.IndonesiaCentral, 76 }, + { LocationNames.IsraelCentral, 0 }, + { LocationNames.ItalyNorth, 106 }, + { LocationNames.JapanEast, 144 }, + { LocationNames.JapanWest, 149 }, + { LocationNames.JioIndiaCentral, 30 }, + { LocationNames.JioIndiaWest, 30 }, + { LocationNames.KoreaCentral, 138 }, + { LocationNames.KoreaSouth, 132 }, + { LocationNames.MalaysiaSouth, 76 }, + { LocationNames.MalaysiaWest, 76 }, + { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, + { LocationNames.NorthCentralUS, 209 }, + { LocationNames.NorthEurope, 129 }, + { LocationNames.NorwayEast, 138 }, + { LocationNames.NorwayWest, 130 }, + { LocationNames.PolandCentral, 118 }, + { LocationNames.QatarCentral, 4 }, + { LocationNames.SouthAfricaNorth, 256 }, + { LocationNames.SouthAfricaWest, 260 }, + { LocationNames.SouthCentralUS, 218 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 76 }, + { LocationNames.SoutheastUS, 236 }, + { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, + { LocationNames.SwedenCentral, 129 }, + { LocationNames.SwedenSouth, 129 }, + { LocationNames.SwitzerlandNorth, 106 }, + { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, + { LocationNames.UAECentral, 100 }, + { LocationNames.UAENorth, 4 }, + { LocationNames.UKSouth, 116 }, + { LocationNames.UKWest, 118 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 230 }, + { LocationNames.WestEurope, 118 }, + { LocationNames.WestIndia, 28 }, + { LocationNames.WestUS, 244 }, + { LocationNames.WestUS2, 236 }, + { LocationNames.WestUS3, 236 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.ItalyNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 240 }, + { LocationNames.AustraliaCentral2, 240 }, + { LocationNames.AustraliaEast, 236 }, + { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 100 }, + { LocationNames.BrazilSouth, 198 }, + { LocationNames.BrazilSoutheast, 198 }, + { LocationNames.CanadaCentral, 104 }, + { LocationNames.CanadaEast, 114 }, + { LocationNames.CentralIndia, 112 }, + { LocationNames.CentralUS, 112 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 182 }, + { LocationNames.EastUS, 92 }, + { LocationNames.EastUS2, 94 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 14 }, + { LocationNames.FranceSouth, 10 }, + { LocationNames.GermanyNorth, 16 }, + { LocationNames.GermanyWestCentral, 6 }, + { LocationNames.IndonesiaCentral, 148 }, + { LocationNames.IsraelCentral, 106 }, + { LocationNames.ItalyNorth, 0 }, + { LocationNames.JapanEast, 216 }, + { LocationNames.JapanWest, 216 }, + { LocationNames.JioIndiaCentral, 112 }, + { LocationNames.JioIndiaWest, 112 }, + { LocationNames.KoreaCentral, 210 }, + { LocationNames.KoreaSouth, 204 }, + { LocationNames.MalaysiaSouth, 148 }, + { LocationNames.MalaysiaWest, 148 }, + { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, + { LocationNames.NorthCentralUS, 110 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 32 }, + { LocationNames.NorwayWest, 26 }, + { LocationNames.PolandCentral, 12 }, + { LocationNames.QatarCentral, 106 }, + { LocationNames.SouthAfricaNorth, 172 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 118 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 148 }, + { LocationNames.SoutheastUS, 154 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, + { LocationNames.SwedenCentral, 32 }, + { LocationNames.SwedenSouth, 255 }, + { LocationNames.SwitzerlandNorth, 100 }, + { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, + { LocationNames.UAECentral, 106 }, + { LocationNames.UAENorth, 108 }, + { LocationNames.UKSouth, 20 }, + { LocationNames.UKWest, 22 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 134 }, + { LocationNames.WestEurope, 12 }, + { LocationNames.WestIndia, 116 }, + { LocationNames.WestUS, 150 }, + { LocationNames.WestUS2, 154 }, + { LocationNames.WestUS3, 154 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.JapanEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 125 }, + { LocationNames.AustraliaCentral2, 124 }, + { LocationNames.AustraliaEast, 118 }, + { LocationNames.AustraliaSoutheast, 130 }, + { LocationNames.AustriaEast, 216 }, + { LocationNames.BrazilSouth, 262 }, + { LocationNames.BrazilSoutheast, 262 }, + { LocationNames.CanadaCentral, 152 }, + { LocationNames.CanadaEast, 162 }, + { LocationNames.CentralIndia, 120 }, + { LocationNames.CentralUS, 140 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 50 }, + { LocationNames.EastUS, 162 }, + { LocationNames.EastUS2, 164 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 218 }, + { LocationNames.FranceSouth, 204 }, + { LocationNames.GermanyNorth, 230 }, + { LocationNames.GermanyWestCentral, 220 }, + { LocationNames.IndonesiaCentral, 68 }, + { LocationNames.IsraelCentral, 144 }, + { LocationNames.ItalyNorth, 216 }, + { LocationNames.JapanEast, 0 }, + { LocationNames.JapanWest, 8 }, + { LocationNames.JioIndiaCentral, 120 }, + { LocationNames.JioIndiaWest, 120 }, + { LocationNames.KoreaCentral, 30 }, + { LocationNames.KoreaSouth, 35 }, + { LocationNames.MalaysiaSouth, 68 }, + { LocationNames.MalaysiaWest, 68 }, + { LocationNames.MexicoCentral, 112 }, + { LocationNames.NewZealandNorth, 125 }, + { LocationNames.NorthCentralUS, 148 }, + { LocationNames.NorthEurope, 223 }, + { LocationNames.NorwayEast, 254 }, + { LocationNames.NorwayWest, 248 }, + { LocationNames.PolandCentral, 234 }, + { LocationNames.QatarCentral, 144 }, + { LocationNames.SouthAfricaNorth, 366 }, + { LocationNames.SouthAfricaWest, 370 }, + { LocationNames.SouthCentralUS, 138 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 68 }, + { LocationNames.SoutheastUS, 112 }, + { LocationNames.SouthIndia, 100 }, + { LocationNames.SpainCentral, 218 }, + { LocationNames.SwedenCentral, 254 }, + { LocationNames.SwedenSouth, 254 }, + { LocationNames.SwitzerlandNorth, 216 }, + { LocationNames.SwitzerlandWest, 212 }, + { LocationNames.TaiwanNorth, 50 }, + { LocationNames.TaiwanNorthwest, 50 }, + { LocationNames.UAECentral, 144 }, + { LocationNames.UAENorth, 144 }, + { LocationNames.UKSouth, 226 }, + { LocationNames.UKWest, 230 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 126 }, + { LocationNames.WestEurope, 234 }, + { LocationNames.WestIndia, 118 }, + { LocationNames.WestUS, 106 }, + { LocationNames.WestUS2, 112 }, + { LocationNames.WestUS3, 112 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.JapanWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 130 }, + { LocationNames.AustraliaCentral2, 132 }, + { LocationNames.AustraliaEast, 126 }, + { LocationNames.AustraliaSoutheast, 138 }, + { LocationNames.AustriaEast, 216 }, + { LocationNames.BrazilSouth, 270 }, + { LocationNames.BrazilSoutheast, 270 }, + { LocationNames.CanadaCentral, 160 }, + { LocationNames.CanadaEast, 170 }, + { LocationNames.CentralIndia, 124 }, + { LocationNames.CentralUS, 143 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 50 }, + { LocationNames.EastUS, 168 }, + { LocationNames.EastUS2, 164 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 218 }, + { LocationNames.FranceSouth, 206 }, + { LocationNames.GermanyNorth, 230 }, + { LocationNames.GermanyWestCentral, 220 }, + { LocationNames.IndonesiaCentral, 74 }, + { LocationNames.IsraelCentral, 149 }, + { LocationNames.ItalyNorth, 216 }, + { LocationNames.JapanEast, 8 }, + { LocationNames.JapanWest, 0 }, + { LocationNames.JioIndiaCentral, 124 }, + { LocationNames.JioIndiaWest, 124 }, + { LocationNames.KoreaCentral, 36 }, + { LocationNames.KoreaSouth, 42 }, + { LocationNames.MalaysiaSouth, 74 }, + { LocationNames.MalaysiaWest, 74 }, + { LocationNames.MexicoCentral, 112 }, + { LocationNames.NewZealandNorth, 130 }, + { LocationNames.NorthCentralUS, 152 }, + { LocationNames.NorthEurope, 236 }, + { LocationNames.NorwayEast, 248 }, + { LocationNames.NorwayWest, 240 }, + { LocationNames.PolandCentral, 228 }, + { LocationNames.QatarCentral, 149 }, + { LocationNames.SouthAfricaNorth, 366 }, + { LocationNames.SouthAfricaWest, 370 }, + { LocationNames.SouthCentralUS, 138 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 74 }, + { LocationNames.SoutheastUS, 112 }, + { LocationNames.SouthIndia, 104 }, + { LocationNames.SpainCentral, 218 }, + { LocationNames.SwedenCentral, 248 }, + { LocationNames.SwedenSouth, 248 }, + { LocationNames.SwitzerlandNorth, 216 }, + { LocationNames.SwitzerlandWest, 210 }, + { LocationNames.TaiwanNorth, 50 }, + { LocationNames.TaiwanNorthwest, 50 }, + { LocationNames.UAECentral, 149 }, + { LocationNames.UAENorth, 148 }, + { LocationNames.UKSouth, 225 }, + { LocationNames.UKWest, 228 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 128 }, + { LocationNames.WestEurope, 228 }, + { LocationNames.WestIndia, 122 }, + { LocationNames.WestUS, 106 }, + { LocationNames.WestUS2, 112 }, + { LocationNames.WestUS3, 112 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.JioIndiaCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 144 }, + { LocationNames.AustraliaCentral2, 144 }, + { LocationNames.AustraliaEast, 140 }, + { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, + { LocationNames.BrazilSouth, 302 }, + { LocationNames.BrazilSoutheast, 302 }, + { LocationNames.CanadaCentral, 208 }, + { LocationNames.CanadaEast, 218 }, + { LocationNames.CentralIndia, 100 }, + { LocationNames.CentralUS, 222 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 86 }, + { LocationNames.EastUS, 196 }, + { LocationNames.EastUS2, 198 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 116 }, + { LocationNames.FranceSouth, 102 }, + { LocationNames.GermanyNorth, 128 }, + { LocationNames.GermanyWestCentral, 118 }, + { LocationNames.IndonesiaCentral, 52 }, + { LocationNames.IsraelCentral, 30 }, + { LocationNames.ItalyNorth, 112 }, + { LocationNames.JapanEast, 120 }, + { LocationNames.JapanWest, 124 }, + { LocationNames.JioIndiaCentral, 0 }, + { LocationNames.JioIndiaWest, 100 }, + { LocationNames.KoreaCentral, 114 }, + { LocationNames.KoreaSouth, 106 }, + { LocationNames.MalaysiaSouth, 52 }, + { LocationNames.MalaysiaWest, 52 }, + { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, + { LocationNames.NorthCentralUS, 216 }, + { LocationNames.NorthEurope, 137 }, + { LocationNames.NorwayEast, 146 }, + { LocationNames.NorwayWest, 136 }, + { LocationNames.PolandCentral, 126 }, + { LocationNames.QatarCentral, 30 }, + { LocationNames.SouthAfricaNorth, 264 }, + { LocationNames.SouthAfricaWest, 267 }, + { LocationNames.SouthCentralUS, 224 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 52 }, + { LocationNames.SoutheastUS, 212 }, + { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, + { LocationNames.SwedenCentral, 146 }, + { LocationNames.SwedenSouth, 146 }, + { LocationNames.SwitzerlandNorth, 112 }, + { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, + { LocationNames.UAECentral, 30 }, + { LocationNames.UAENorth, 30 }, + { LocationNames.UKSouth, 122 }, + { LocationNames.UKWest, 126 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 236 }, + { LocationNames.WestEurope, 126 }, + { LocationNames.WestIndia, 4 }, + { LocationNames.WestUS, 218 }, + { LocationNames.WestUS2, 212 }, + { LocationNames.WestUS3, 212 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.JioIndiaWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 144 }, + { LocationNames.AustraliaCentral2, 144 }, + { LocationNames.AustraliaEast, 140 }, + { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, + { LocationNames.BrazilSouth, 302 }, + { LocationNames.BrazilSoutheast, 302 }, + { LocationNames.CanadaCentral, 208 }, + { LocationNames.CanadaEast, 218 }, + { LocationNames.CentralIndia, 100 }, + { LocationNames.CentralUS, 222 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 86 }, + { LocationNames.EastUS, 196 }, + { LocationNames.EastUS2, 198 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 116 }, + { LocationNames.FranceSouth, 102 }, + { LocationNames.GermanyNorth, 128 }, + { LocationNames.GermanyWestCentral, 118 }, + { LocationNames.IndonesiaCentral, 52 }, + { LocationNames.IsraelCentral, 30 }, + { LocationNames.ItalyNorth, 112 }, + { LocationNames.JapanEast, 120 }, + { LocationNames.JapanWest, 124 }, + { LocationNames.JioIndiaCentral, 100 }, + { LocationNames.JioIndiaWest, 0 }, + { LocationNames.KoreaCentral, 114 }, + { LocationNames.KoreaSouth, 106 }, + { LocationNames.MalaysiaSouth, 52 }, + { LocationNames.MalaysiaWest, 52 }, + { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, + { LocationNames.NorthCentralUS, 216 }, + { LocationNames.NorthEurope, 137 }, + { LocationNames.NorwayEast, 146 }, + { LocationNames.NorwayWest, 136 }, + { LocationNames.PolandCentral, 126 }, + { LocationNames.QatarCentral, 30 }, + { LocationNames.SouthAfricaNorth, 264 }, + { LocationNames.SouthAfricaWest, 267 }, + { LocationNames.SouthCentralUS, 224 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 52 }, + { LocationNames.SoutheastUS, 212 }, + { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, + { LocationNames.SwedenCentral, 146 }, + { LocationNames.SwedenSouth, 146 }, + { LocationNames.SwitzerlandNorth, 112 }, + { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, + { LocationNames.UAECentral, 30 }, + { LocationNames.UAENorth, 30 }, + { LocationNames.UKSouth, 122 }, + { LocationNames.UKWest, 126 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 236 }, + { LocationNames.WestEurope, 126 }, + { LocationNames.WestIndia, 4 }, + { LocationNames.WestUS, 218 }, + { LocationNames.WestUS2, 212 }, + { LocationNames.WestUS3, 212 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.KoreaCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 154 }, + { LocationNames.AustraliaCentral2, 154 }, + { LocationNames.AustraliaEast, 150 }, + { LocationNames.AustraliaSoutheast, 146 }, + { LocationNames.AustriaEast, 210 }, + { LocationNames.BrazilSouth, 300 }, + { LocationNames.BrazilSoutheast, 300 }, + { LocationNames.CanadaCentral, 178 }, + { LocationNames.CanadaEast, 186 }, + { LocationNames.CentralIndia, 114 }, + { LocationNames.CentralUS, 158 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 56 }, + { LocationNames.EastUS, 182 }, + { LocationNames.EastUS2, 176 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 212 }, + { LocationNames.FranceSouth, 200 }, + { LocationNames.GermanyNorth, 224 }, + { LocationNames.GermanyWestCentral, 216 }, + { LocationNames.IndonesiaCentral, 62 }, + { LocationNames.IsraelCentral, 138 }, + { LocationNames.ItalyNorth, 210 }, + { LocationNames.JapanEast, 30 }, + { LocationNames.JapanWest, 36 }, + { LocationNames.JioIndiaCentral, 114 }, + { LocationNames.JioIndiaWest, 114 }, + { LocationNames.KoreaCentral, 0 }, + { LocationNames.KoreaSouth, 6 }, + { LocationNames.MalaysiaSouth, 62 }, + { LocationNames.MalaysiaWest, 62 }, + { LocationNames.MexicoCentral, 122 }, + { LocationNames.NewZealandNorth, 154 }, + { LocationNames.NorthCentralUS, 165 }, + { LocationNames.NorthEurope, 233 }, + { LocationNames.NorwayEast, 242 }, + { LocationNames.NorwayWest, 236 }, + { LocationNames.PolandCentral, 222 }, + { LocationNames.QatarCentral, 138 }, + { LocationNames.SouthAfricaNorth, 360 }, + { LocationNames.SouthAfricaWest, 364 }, + { LocationNames.SouthCentralUS, 152 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 62 }, + { LocationNames.SoutheastUS, 122 }, + { LocationNames.SouthIndia, 95 }, + { LocationNames.SpainCentral, 212 }, + { LocationNames.SwedenCentral, 242 }, + { LocationNames.SwedenSouth, 242 }, + { LocationNames.SwitzerlandNorth, 210 }, + { LocationNames.SwitzerlandWest, 206 }, + { LocationNames.TaiwanNorth, 56 }, + { LocationNames.TaiwanNorthwest, 56 }, + { LocationNames.UAECentral, 138 }, + { LocationNames.UAENorth, 138 }, + { LocationNames.UKSouth, 220 }, + { LocationNames.UKWest, 222 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 143 }, + { LocationNames.WestEurope, 222 }, + { LocationNames.WestIndia, 112 }, + { LocationNames.WestUS, 130 }, + { LocationNames.WestUS2, 122 }, + { LocationNames.WestUS3, 122 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.KoreaSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 148 }, + { LocationNames.AustraliaCentral2, 148 }, + { LocationNames.AustraliaEast, 143 }, + { LocationNames.AustraliaSoutheast, 140 }, + { LocationNames.AustriaEast, 204 }, + { LocationNames.BrazilSouth, 306 }, + { LocationNames.BrazilSoutheast, 306 }, + { LocationNames.CanadaCentral, 182 }, + { LocationNames.CanadaEast, 192 }, + { LocationNames.CentralIndia, 106 }, + { LocationNames.CentralUS, 162 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 60 }, + { LocationNames.EastUS, 186 }, + { LocationNames.EastUS2, 182 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 206 }, + { LocationNames.FranceSouth, 193 }, + { LocationNames.GermanyNorth, 218 }, + { LocationNames.GermanyWestCentral, 209 }, + { LocationNames.IndonesiaCentral, 56 }, + { LocationNames.IsraelCentral, 132 }, + { LocationNames.ItalyNorth, 204 }, + { LocationNames.JapanEast, 35 }, + { LocationNames.JapanWest, 42 }, + { LocationNames.JioIndiaCentral, 106 }, + { LocationNames.JioIndiaWest, 106 }, + { LocationNames.KoreaCentral, 6 }, + { LocationNames.KoreaSouth, 0 }, + { LocationNames.MalaysiaSouth, 56 }, + { LocationNames.MalaysiaWest, 56 }, + { LocationNames.MexicoCentral, 126 }, + { LocationNames.NewZealandNorth, 148 }, + { LocationNames.NorthCentralUS, 170 }, + { LocationNames.NorthEurope, 226 }, + { LocationNames.NorwayEast, 235 }, + { LocationNames.NorwayWest, 228 }, + { LocationNames.PolandCentral, 216 }, + { LocationNames.QatarCentral, 132 }, + { LocationNames.SouthAfricaNorth, 354 }, + { LocationNames.SouthAfricaWest, 358 }, + { LocationNames.SouthCentralUS, 156 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 56 }, + { LocationNames.SoutheastUS, 126 }, + { LocationNames.SouthIndia, 88 }, + { LocationNames.SpainCentral, 206 }, + { LocationNames.SwedenCentral, 235 }, + { LocationNames.SwedenSouth, 235 }, + { LocationNames.SwitzerlandNorth, 204 }, + { LocationNames.SwitzerlandWest, 200 }, + { LocationNames.TaiwanNorth, 60 }, + { LocationNames.TaiwanNorthwest, 60 }, + { LocationNames.UAECentral, 132 }, + { LocationNames.UAENorth, 130 }, + { LocationNames.UKSouth, 214 }, + { LocationNames.UKWest, 216 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 148 }, + { LocationNames.WestEurope, 216 }, + { LocationNames.WestIndia, 106 }, + { LocationNames.WestUS, 134 }, + { LocationNames.WestUS2, 126 }, + { LocationNames.WestUS3, 126 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.MalaysiaSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 94 }, + { LocationNames.AustraliaCentral2, 92 }, + { LocationNames.AustraliaEast, 88 }, + { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, + { LocationNames.BrazilSouth, 328 }, + { LocationNames.BrazilSoutheast, 328 }, + { LocationNames.CanadaCentral, 216 }, + { LocationNames.CanadaEast, 224 }, + { LocationNames.CentralIndia, 52 }, + { LocationNames.CentralUS, 194 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 33 }, + { LocationNames.EastUS, 218 }, + { LocationNames.EastUS2, 226 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 150 }, + { LocationNames.FranceSouth, 138 }, + { LocationNames.GermanyNorth, 162 }, + { LocationNames.GermanyWestCentral, 154 }, + { LocationNames.IndonesiaCentral, 100 }, + { LocationNames.IsraelCentral, 76 }, + { LocationNames.ItalyNorth, 148 }, + { LocationNames.JapanEast, 68 }, + { LocationNames.JapanWest, 74 }, + { LocationNames.JioIndiaCentral, 52 }, + { LocationNames.JioIndiaWest, 52 }, + { LocationNames.KoreaCentral, 62 }, + { LocationNames.KoreaSouth, 56 }, + { LocationNames.MalaysiaSouth, 0 }, + { LocationNames.MalaysiaWest, 100 }, + { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, + { LocationNames.NorthCentralUS, 202 }, + { LocationNames.NorthEurope, 172 }, + { LocationNames.NorwayEast, 180 }, + { LocationNames.NorwayWest, 174 }, + { LocationNames.PolandCentral, 160 }, + { LocationNames.QatarCentral, 76 }, + { LocationNames.SouthAfricaNorth, 298 }, + { LocationNames.SouthAfricaWest, 302 }, + { LocationNames.SouthCentralUS, 200 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 100 }, + { LocationNames.SoutheastUS, 160 }, + { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, + { LocationNames.SwedenCentral, 180 }, + { LocationNames.SwedenSouth, 180 }, + { LocationNames.SwitzerlandNorth, 148 }, + { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, + { LocationNames.UAECentral, 76 }, + { LocationNames.UAENorth, 76 }, + { LocationNames.UKSouth, 158 }, + { LocationNames.UKWest, 161 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 180 }, + { LocationNames.WestEurope, 160 }, + { LocationNames.WestIndia, 50 }, + { LocationNames.WestUS, 168 }, + { LocationNames.WestUS2, 160 }, + { LocationNames.WestUS3, 160 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.MalaysiaWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 94 }, + { LocationNames.AustraliaCentral2, 92 }, + { LocationNames.AustraliaEast, 88 }, + { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, + { LocationNames.BrazilSouth, 328 }, + { LocationNames.BrazilSoutheast, 328 }, + { LocationNames.CanadaCentral, 216 }, + { LocationNames.CanadaEast, 224 }, + { LocationNames.CentralIndia, 52 }, + { LocationNames.CentralUS, 194 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 33 }, + { LocationNames.EastUS, 218 }, + { LocationNames.EastUS2, 226 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 218 }, + { LocationNames.FranceCentral, 150 }, + { LocationNames.FranceSouth, 138 }, + { LocationNames.GermanyNorth, 162 }, + { LocationNames.GermanyWestCentral, 154 }, + { LocationNames.IndonesiaCentral, 100 }, + { LocationNames.IsraelCentral, 76 }, + { LocationNames.ItalyNorth, 148 }, + { LocationNames.JapanEast, 68 }, + { LocationNames.JapanWest, 74 }, + { LocationNames.JioIndiaCentral, 52 }, + { LocationNames.JioIndiaWest, 52 }, + { LocationNames.KoreaCentral, 62 }, + { LocationNames.KoreaSouth, 56 }, + { LocationNames.MalaysiaSouth, 100 }, + { LocationNames.MalaysiaWest, 0 }, + { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, + { LocationNames.NorthCentralUS, 202 }, + { LocationNames.NorthEurope, 172 }, + { LocationNames.NorwayEast, 180 }, + { LocationNames.NorwayWest, 174 }, + { LocationNames.PolandCentral, 160 }, + { LocationNames.QatarCentral, 76 }, + { LocationNames.SouthAfricaNorth, 298 }, + { LocationNames.SouthAfricaWest, 302 }, + { LocationNames.SouthCentralUS, 200 }, + { LocationNames.SouthCentralUSSTG, 200 }, + { LocationNames.SoutheastAsia, 100 }, + { LocationNames.SoutheastUS, 160 }, + { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, + { LocationNames.SwedenCentral, 180 }, + { LocationNames.SwedenSouth, 180 }, + { LocationNames.SwitzerlandNorth, 148 }, + { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, + { LocationNames.UAECentral, 76 }, + { LocationNames.UAENorth, 76 }, + { LocationNames.UKSouth, 158 }, + { LocationNames.UKWest, 161 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 180 }, + { LocationNames.WestEurope, 160 }, + { LocationNames.WestIndia, 50 }, + { LocationNames.WestUS, 168 }, + { LocationNames.WestUS2, 160 }, + { LocationNames.WestUS3, 160 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.MexicoCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 162 }, + { LocationNames.AustraliaCentral2, 162 }, + { LocationNames.AustraliaEast, 158 }, + { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, + { LocationNames.BrazilSouth, 182 }, + { LocationNames.BrazilSoutheast, 182 }, + { LocationNames.CanadaCentral, 57 }, + { LocationNames.CanadaEast, 66 }, + { LocationNames.CentralIndia, 212 }, + { LocationNames.CentralUS, 36 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 140 }, + { LocationNames.EastUS, 58 }, + { LocationNames.EastUS2, 68 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 140 }, + { LocationNames.FranceSouth, 146 }, + { LocationNames.GermanyNorth, 154 }, + { LocationNames.GermanyWestCentral, 148 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 236 }, + { LocationNames.ItalyNorth, 154 }, + { LocationNames.JapanEast, 112 }, + { LocationNames.JapanWest, 112 }, + { LocationNames.JioIndiaCentral, 212 }, + { LocationNames.JioIndiaWest, 212 }, + { LocationNames.KoreaCentral, 122 }, + { LocationNames.KoreaSouth, 126 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 0 }, + { LocationNames.NewZealandNorth, 162 }, + { LocationNames.NorthCentralUS, 44 }, + { LocationNames.NorthEurope, 136 }, + { LocationNames.NorwayEast, 164 }, + { LocationNames.NorwayWest, 156 }, + { LocationNames.PolandCentral, 142 }, + { LocationNames.QatarCentral, 236 }, + { LocationNames.SouthAfricaNorth, 296 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 44 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 100 }, + { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, + { LocationNames.SwedenCentral, 164 }, + { LocationNames.SwedenSouth, 164 }, + { LocationNames.SwitzerlandNorth, 154 }, + { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, + { LocationNames.UAECentral, 236 }, + { LocationNames.UAENorth, 236 }, + { LocationNames.UKSouth, 130 }, + { LocationNames.UKWest, 132 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 142 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 22 }, + { LocationNames.WestUS2, 100 }, + { LocationNames.WestUS3, 100 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NewZealandNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 100 }, + { LocationNames.AustraliaCentral2, 2 }, + { LocationNames.AustraliaEast, 6 }, + { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, + { LocationNames.BrazilSouth, 314 }, + { LocationNames.BrazilSoutheast, 314 }, + { LocationNames.CanadaCentral, 204 }, + { LocationNames.CanadaEast, 214 }, + { LocationNames.CentralIndia, 144 }, + { LocationNames.CentralUS, 184 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 120 }, + { LocationNames.EastUS, 205 }, + { LocationNames.EastUS2, 200 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 242 }, + { LocationNames.FranceSouth, 230 }, + { LocationNames.GermanyNorth, 254 }, + { LocationNames.GermanyWestCentral, 246 }, + { LocationNames.IndonesiaCentral, 94 }, + { LocationNames.IsraelCentral, 168 }, + { LocationNames.ItalyNorth, 240 }, + { LocationNames.JapanEast, 125 }, + { LocationNames.JapanWest, 130 }, + { LocationNames.JioIndiaCentral, 144 }, + { LocationNames.JioIndiaWest, 144 }, + { LocationNames.KoreaCentral, 154 }, + { LocationNames.KoreaSouth, 148 }, + { LocationNames.MalaysiaSouth, 94 }, + { LocationNames.MalaysiaWest, 94 }, + { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 0 }, + { LocationNames.NorthCentralUS, 192 }, + { LocationNames.NorthEurope, 262 }, + { LocationNames.NorwayEast, 272 }, + { LocationNames.NorwayWest, 266 }, + { LocationNames.PolandCentral, 252 }, + { LocationNames.QatarCentral, 168 }, + { LocationNames.SouthAfricaNorth, 390 }, + { LocationNames.SouthAfricaWest, 394 }, + { LocationNames.SouthCentralUS, 174 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 94 }, + { LocationNames.SoutheastUS, 162 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 242 }, + { LocationNames.SwedenCentral, 272 }, + { LocationNames.SwedenSouth, 272 }, + { LocationNames.SwitzerlandNorth, 240 }, + { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, + { LocationNames.UAECentral, 168 }, + { LocationNames.UAENorth, 168 }, + { LocationNames.UKSouth, 250 }, + { LocationNames.UKWest, 252 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 170 }, + { LocationNames.WestEurope, 252 }, + { LocationNames.WestIndia, 142 }, + { LocationNames.WestUS, 142 }, + { LocationNames.WestUS2, 162 }, + { LocationNames.WestUS3, 162 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NorthCentralUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 192 }, + { LocationNames.AustraliaCentral2, 192 }, + { LocationNames.AustraliaEast, 187 }, + { LocationNames.AustraliaSoutheast, 198 }, + { LocationNames.AustriaEast, 110 }, + { LocationNames.BrazilSouth, 138 }, + { LocationNames.BrazilSoutheast, 138 }, + { LocationNames.CanadaCentral, 14 }, + { LocationNames.CanadaEast, 24 }, + { LocationNames.CentralIndia, 216 }, + { LocationNames.CentralUS, 8 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 184 }, + { LocationNames.EastUS, 19 }, + { LocationNames.EastUS2, 22 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 19 }, + { LocationNames.FranceCentral, 96 }, + { LocationNames.FranceSouth, 104 }, + { LocationNames.GermanyNorth, 112 }, + { LocationNames.GermanyWestCentral, 106 }, + { LocationNames.IndonesiaCentral, 202 }, + { LocationNames.IsraelCentral, 209 }, + { LocationNames.ItalyNorth, 110 }, + { LocationNames.JapanEast, 148 }, + { LocationNames.JapanWest, 152 }, + { LocationNames.JioIndiaCentral, 216 }, + { LocationNames.JioIndiaWest, 216 }, + { LocationNames.KoreaCentral, 165 }, + { LocationNames.KoreaSouth, 170 }, + { LocationNames.MalaysiaSouth, 202 }, + { LocationNames.MalaysiaWest, 202 }, + { LocationNames.MexicoCentral, 44 }, + { LocationNames.NewZealandNorth, 192 }, + { LocationNames.NorthCentralUS, 0 }, + { LocationNames.NorthEurope, 90 }, + { LocationNames.NorwayEast, 122 }, + { LocationNames.NorwayWest, 114 }, + { LocationNames.PolandCentral, 102 }, + { LocationNames.QatarCentral, 209 }, + { LocationNames.SouthAfricaNorth, 253 }, + { LocationNames.SouthAfricaWest, 236 }, + { LocationNames.SouthCentralUS, 30 }, + { LocationNames.SouthCentralUSSTG, 30 }, + { LocationNames.SoutheastAsia, 202 }, + { LocationNames.SoutheastUS, 44 }, + { LocationNames.SouthIndia, 228 }, + { LocationNames.SpainCentral, 96 }, + { LocationNames.SwedenCentral, 122 }, + { LocationNames.SwedenSouth, 122 }, + { LocationNames.SwitzerlandNorth, 110 }, + { LocationNames.SwitzerlandWest, 106 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, + { LocationNames.UAECentral, 209 }, + { LocationNames.UAENorth, 212 }, + { LocationNames.UKSouth, 90 }, + { LocationNames.UKWest, 92 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 102 }, + { LocationNames.WestIndia, 218 }, + { LocationNames.WestUS, 50 }, + { LocationNames.WestUS2, 44 }, + { LocationNames.WestUS3, 44 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NorthEurope, + new Dictionary() + { + { LocationNames.AustraliaCentral, 262 }, + { LocationNames.AustraliaCentral2, 262 }, + { LocationNames.AustraliaEast, 258 }, + { LocationNames.AustraliaSoutheast, 260 }, + { LocationNames.AustriaEast, 31 }, + { LocationNames.BrazilSouth, 177 }, + { LocationNames.BrazilSoutheast, 177 }, + { LocationNames.CanadaCentral, 84 }, + { LocationNames.CanadaEast, 93 }, + { LocationNames.CentralIndia, 137 }, + { LocationNames.CentralUS, 92 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 205 }, + { LocationNames.EastUS, 76 }, + { LocationNames.EastUS2, 75 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 27 }, + { LocationNames.FranceSouth, 31 }, + { LocationNames.GermanyNorth, 31 }, + { LocationNames.GermanyWestCentral, 25 }, + { LocationNames.IndonesiaCentral, 172 }, + { LocationNames.IsraelCentral, 129 }, + { LocationNames.ItalyNorth, 31 }, + { LocationNames.JapanEast, 223 }, + { LocationNames.JapanWest, 236 }, + { LocationNames.JioIndiaCentral, 137 }, + { LocationNames.JioIndiaWest, 137 }, + { LocationNames.KoreaCentral, 233 }, + { LocationNames.KoreaSouth, 226 }, + { LocationNames.MalaysiaSouth, 172 }, + { LocationNames.MalaysiaWest, 172 }, + { LocationNames.MexicoCentral, 136 }, + { LocationNames.NewZealandNorth, 262 }, + { LocationNames.NorthCentralUS, 90 }, + { LocationNames.NorthEurope, 0 }, + { LocationNames.NorwayEast, 40 }, + { LocationNames.NorwayWest, 33 }, + { LocationNames.PolandCentral, 22 }, + { LocationNames.QatarCentral, 129 }, + { LocationNames.SouthAfricaNorth, 179 }, + { LocationNames.SouthAfricaWest, 157 }, + { LocationNames.SouthCentralUS, 106 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 172 }, + { LocationNames.SoutheastUS, 136 }, + { LocationNames.SouthIndia, 149 }, + { LocationNames.SpainCentral, 27 }, + { LocationNames.SwedenCentral, 40 }, + { LocationNames.SwedenSouth, 40 }, + { LocationNames.SwitzerlandNorth, 31 }, + { LocationNames.SwitzerlandWest, 30 }, + { LocationNames.TaiwanNorth, 205 }, + { LocationNames.TaiwanNorthwest, 205 }, + { LocationNames.UAECentral, 129 }, + { LocationNames.UAENorth, 132 }, + { LocationNames.UKSouth, 21 }, + { LocationNames.UKWest, 17 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 110 }, + { LocationNames.WestEurope, 22 }, + { LocationNames.WestIndia, 139 }, + { LocationNames.WestUS, 133 }, + { LocationNames.WestUS2, 136 }, + { LocationNames.WestUS3, 136 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NorwayEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 272 }, + { LocationNames.AustraliaCentral2, 272 }, + { LocationNames.AustraliaEast, 266 }, + { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 32 }, + { LocationNames.BrazilSouth, 208 }, + { LocationNames.BrazilSoutheast, 208 }, + { LocationNames.CanadaCentral, 114 }, + { LocationNames.CanadaEast, 124 }, + { LocationNames.CentralIndia, 146 }, + { LocationNames.CentralUS, 128 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 214 }, + { LocationNames.EastUS, 101 }, + { LocationNames.EastUS2, 104 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 30 }, + { LocationNames.FranceSouth, 42 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 26 }, + { LocationNames.IndonesiaCentral, 180 }, + { LocationNames.IsraelCentral, 138 }, + { LocationNames.ItalyNorth, 32 }, + { LocationNames.JapanEast, 254 }, + { LocationNames.JapanWest, 248 }, + { LocationNames.JioIndiaCentral, 146 }, + { LocationNames.JioIndiaWest, 146 }, + { LocationNames.KoreaCentral, 242 }, + { LocationNames.KoreaSouth, 235 }, + { LocationNames.MalaysiaSouth, 180 }, + { LocationNames.MalaysiaWest, 180 }, + { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, + { LocationNames.NorthCentralUS, 122 }, + { LocationNames.NorthEurope, 40 }, + { LocationNames.NorwayEast, 0 }, + { LocationNames.NorwayWest, 8 }, + { LocationNames.PolandCentral, 22 }, + { LocationNames.QatarCentral, 138 }, + { LocationNames.SouthAfricaNorth, 186 }, + { LocationNames.SouthAfricaWest, 170 }, + { LocationNames.SouthCentralUS, 132 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 180 }, + { LocationNames.SoutheastUS, 164 }, + { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, + { LocationNames.SwedenCentral, 20 }, + { LocationNames.SwedenSouth, 20 }, + { LocationNames.SwitzerlandNorth, 32 }, + { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, + { LocationNames.UAECentral, 138 }, + { LocationNames.UAENorth, 140 }, + { LocationNames.UKSouth, 28 }, + { LocationNames.UKWest, 30 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 142 }, + { LocationNames.WestEurope, 22 }, + { LocationNames.WestIndia, 146 }, + { LocationNames.WestUS, 163 }, + { LocationNames.WestUS2, 164 }, + { LocationNames.WestUS3, 164 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NorwayWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 266 }, + { LocationNames.AustraliaCentral2, 266 }, + { LocationNames.AustraliaEast, 260 }, + { LocationNames.AustraliaSoutheast, 258 }, + { LocationNames.AustriaEast, 26 }, + { LocationNames.BrazilSouth, 201 }, + { LocationNames.BrazilSoutheast, 201 }, + { LocationNames.CanadaCentral, 108 }, + { LocationNames.CanadaEast, 116 }, + { LocationNames.CentralIndia, 136 }, + { LocationNames.CentralUS, 121 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 206 }, + { LocationNames.EastUS, 94 }, + { LocationNames.EastUS2, 98 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 24 }, + { LocationNames.FranceSouth, 36 }, + { LocationNames.GermanyNorth, 26 }, + { LocationNames.GermanyWestCentral, 20 }, + { LocationNames.IndonesiaCentral, 174 }, + { LocationNames.IsraelCentral, 130 }, + { LocationNames.ItalyNorth, 26 }, + { LocationNames.JapanEast, 248 }, + { LocationNames.JapanWest, 240 }, + { LocationNames.JioIndiaCentral, 136 }, + { LocationNames.JioIndiaWest, 136 }, + { LocationNames.KoreaCentral, 236 }, + { LocationNames.KoreaSouth, 228 }, + { LocationNames.MalaysiaSouth, 174 }, + { LocationNames.MalaysiaWest, 174 }, + { LocationNames.MexicoCentral, 156 }, + { LocationNames.NewZealandNorth, 266 }, + { LocationNames.NorthCentralUS, 114 }, + { LocationNames.NorthEurope, 33 }, + { LocationNames.NorwayEast, 8 }, + { LocationNames.NorwayWest, 0 }, + { LocationNames.PolandCentral, 15 }, + { LocationNames.QatarCentral, 130 }, + { LocationNames.SouthAfricaNorth, 179 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 124 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 174 }, + { LocationNames.SoutheastUS, 156 }, + { LocationNames.SouthIndia, 150 }, + { LocationNames.SpainCentral, 24 }, + { LocationNames.SwedenCentral, 20 }, + { LocationNames.SwedenSouth, 20 }, + { LocationNames.SwitzerlandNorth, 26 }, + { LocationNames.SwitzerlandWest, 30 }, + { LocationNames.TaiwanNorth, 206 }, + { LocationNames.TaiwanNorthwest, 206 }, + { LocationNames.UAECentral, 130 }, + { LocationNames.UAENorth, 134 }, + { LocationNames.UKSouth, 22 }, + { LocationNames.UKWest, 24 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 136 }, + { LocationNames.WestEurope, 15 }, + { LocationNames.WestIndia, 140 }, + { LocationNames.WestUS, 156 }, + { LocationNames.WestUS2, 156 }, + { LocationNames.WestUS3, 156 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.PolandCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 252 }, + { LocationNames.AustraliaCentral2, 252 }, + { LocationNames.AustraliaEast, 248 }, + { LocationNames.AustraliaSoutheast, 244 }, + { LocationNames.AustriaEast, 12 }, + { LocationNames.BrazilSouth, 188 }, + { LocationNames.BrazilSoutheast, 188 }, + { LocationNames.CanadaCentral, 94 }, + { LocationNames.CanadaEast, 103 }, + { LocationNames.CentralIndia, 126 }, + { LocationNames.CentralUS, 102 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 193 }, + { LocationNames.EastUS, 81 }, + { LocationNames.EastUS2, 86 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 10 }, + { LocationNames.FranceSouth, 20 }, + { LocationNames.GermanyNorth, 10 }, + { LocationNames.GermanyWestCentral, 8 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 118 }, + { LocationNames.ItalyNorth, 12 }, + { LocationNames.JapanEast, 234 }, + { LocationNames.JapanWest, 228 }, + { LocationNames.JioIndiaCentral, 126 }, + { LocationNames.JioIndiaWest, 126 }, + { LocationNames.KoreaCentral, 222 }, + { LocationNames.KoreaSouth, 216 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 142 }, + { LocationNames.NewZealandNorth, 252 }, + { LocationNames.NorthCentralUS, 102 }, + { LocationNames.NorthEurope, 22 }, + { LocationNames.NorwayEast, 22 }, + { LocationNames.NorwayWest, 15 }, + { LocationNames.PolandCentral, 0 }, + { LocationNames.QatarCentral, 118 }, + { LocationNames.SouthAfricaNorth, 170 }, + { LocationNames.SouthAfricaWest, 152 }, + { LocationNames.SouthCentralUS, 112 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 142 }, + { LocationNames.SouthIndia, 136 }, + { LocationNames.SpainCentral, 10 }, + { LocationNames.SwedenCentral, 22 }, + { LocationNames.SwedenSouth, 22 }, + { LocationNames.SwitzerlandNorth, 12 }, + { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 193 }, + { LocationNames.TaiwanNorthwest, 193 }, + { LocationNames.UAECentral, 118 }, + { LocationNames.UAENorth, 120 }, + { LocationNames.UKSouth, 10 }, + { LocationNames.UKWest, 12 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 120 }, + { LocationNames.WestEurope, 100 }, + { LocationNames.WestIndia, 128 }, + { LocationNames.WestUS, 144 }, + { LocationNames.WestUS2, 142 }, + { LocationNames.WestUS3, 142 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.QatarCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 168 }, + { LocationNames.AustraliaCentral2, 168 }, + { LocationNames.AustraliaEast, 164 }, + { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, + { LocationNames.BrazilSouth, 296 }, + { LocationNames.BrazilSoutheast, 296 }, + { LocationNames.CanadaCentral, 201 }, + { LocationNames.CanadaEast, 210 }, + { LocationNames.CentralIndia, 30 }, + { LocationNames.CentralUS, 216 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 110 }, + { LocationNames.EastUS, 189 }, + { LocationNames.EastUS2, 190 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 108 }, + { LocationNames.FranceSouth, 96 }, + { LocationNames.GermanyNorth, 120 }, + { LocationNames.GermanyWestCentral, 112 }, + { LocationNames.IndonesiaCentral, 76 }, + { LocationNames.IsraelCentral, 4 }, + { LocationNames.ItalyNorth, 106 }, + { LocationNames.JapanEast, 144 }, + { LocationNames.JapanWest, 149 }, + { LocationNames.JioIndiaCentral, 30 }, + { LocationNames.JioIndiaWest, 30 }, + { LocationNames.KoreaCentral, 138 }, + { LocationNames.KoreaSouth, 132 }, + { LocationNames.MalaysiaSouth, 76 }, + { LocationNames.MalaysiaWest, 76 }, + { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, + { LocationNames.NorthCentralUS, 209 }, + { LocationNames.NorthEurope, 129 }, + { LocationNames.NorwayEast, 138 }, + { LocationNames.NorwayWest, 130 }, + { LocationNames.PolandCentral, 118 }, + { LocationNames.QatarCentral, 0 }, + { LocationNames.SouthAfricaNorth, 256 }, + { LocationNames.SouthAfricaWest, 260 }, + { LocationNames.SouthCentralUS, 218 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 76 }, + { LocationNames.SoutheastUS, 236 }, + { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, + { LocationNames.SwedenCentral, 129 }, + { LocationNames.SwedenSouth, 129 }, + { LocationNames.SwitzerlandNorth, 106 }, + { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, + { LocationNames.UAECentral, 4 }, + { LocationNames.UAENorth, 4 }, + { LocationNames.UKSouth, 116 }, + { LocationNames.UKWest, 118 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 230 }, + { LocationNames.WestEurope, 118 }, + { LocationNames.WestIndia, 28 }, + { LocationNames.WestUS, 244 }, + { LocationNames.WestUS2, 236 }, + { LocationNames.WestUS3, 236 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SouthAfricaNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 390 }, + { LocationNames.AustraliaCentral2, 391 }, + { LocationNames.AustraliaEast, 386 }, + { LocationNames.AustraliaSoutheast, 382 }, + { LocationNames.AustriaEast, 172 }, + { LocationNames.BrazilSouth, 342 }, + { LocationNames.BrazilSoutheast, 342 }, + { LocationNames.CanadaCentral, 246 }, + { LocationNames.CanadaEast, 256 }, + { LocationNames.CentralIndia, 264 }, + { LocationNames.CentralUS, 260 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 332 }, + { LocationNames.EastUS, 234 }, + { LocationNames.EastUS2, 240 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 166 }, + { LocationNames.FranceSouth, 162 }, + { LocationNames.GermanyNorth, 178 }, + { LocationNames.GermanyWestCentral, 178 }, + { LocationNames.IndonesiaCentral, 298 }, + { LocationNames.IsraelCentral, 256 }, + { LocationNames.ItalyNorth, 172 }, + { LocationNames.JapanEast, 366 }, + { LocationNames.JapanWest, 366 }, + { LocationNames.JioIndiaCentral, 264 }, + { LocationNames.JioIndiaWest, 264 }, + { LocationNames.KoreaCentral, 360 }, + { LocationNames.KoreaSouth, 354 }, + { LocationNames.MalaysiaSouth, 298 }, + { LocationNames.MalaysiaWest, 298 }, + { LocationNames.MexicoCentral, 296 }, + { LocationNames.NewZealandNorth, 390 }, + { LocationNames.NorthCentralUS, 253 }, + { LocationNames.NorthEurope, 179 }, + { LocationNames.NorwayEast, 186 }, + { LocationNames.NorwayWest, 179 }, + { LocationNames.PolandCentral, 170 }, + { LocationNames.QatarCentral, 256 }, + { LocationNames.SouthAfricaNorth, 0 }, + { LocationNames.SouthAfricaWest, 18 }, + { LocationNames.SouthCentralUS, 264 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 298 }, + { LocationNames.SoutheastUS, 296 }, + { LocationNames.SouthIndia, 276 }, + { LocationNames.SpainCentral, 166 }, + { LocationNames.SwedenCentral, 186 }, + { LocationNames.SwedenSouth, 186 }, + { LocationNames.SwitzerlandNorth, 172 }, + { LocationNames.SwitzerlandWest, 168 }, + { LocationNames.TaiwanNorth, 332 }, + { LocationNames.TaiwanNorthwest, 332 }, + { LocationNames.UAECentral, 256 }, + { LocationNames.UAENorth, 260 }, + { LocationNames.UKSouth, 160 }, + { LocationNames.UKWest, 164 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 274 }, + { LocationNames.WestEurope, 170 }, + { LocationNames.WestIndia, 266 }, + { LocationNames.WestUS, 298 }, + { LocationNames.WestUS2, 296 }, + { LocationNames.WestUS3, 296 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SouthAfricaWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 394 }, + { LocationNames.AustraliaCentral2, 392 }, + { LocationNames.AustraliaEast, 390 }, + { LocationNames.AustraliaSoutheast, 386 }, + { LocationNames.AustriaEast, 162 }, + { LocationNames.BrazilSouth, 326 }, + { LocationNames.BrazilSoutheast, 326 }, + { LocationNames.CanadaCentral, 230 }, + { LocationNames.CanadaEast, 238 }, + { LocationNames.CentralIndia, 267 }, + { LocationNames.CentralUS, 244 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 336 }, + { LocationNames.EastUS, 218 }, + { LocationNames.EastUS2, 222 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 150 }, + { LocationNames.FranceSouth, 166 }, + { LocationNames.GermanyNorth, 162 }, + { LocationNames.GermanyWestCentral, 156 }, + { LocationNames.IndonesiaCentral, 302 }, + { LocationNames.IsraelCentral, 260 }, + { LocationNames.ItalyNorth, 162 }, + { LocationNames.JapanEast, 370 }, + { LocationNames.JapanWest, 370 }, + { LocationNames.JioIndiaCentral, 267 }, + { LocationNames.JioIndiaWest, 267 }, + { LocationNames.KoreaCentral, 364 }, + { LocationNames.KoreaSouth, 358 }, + { LocationNames.MalaysiaSouth, 302 }, + { LocationNames.MalaysiaWest, 302 }, + { LocationNames.MexicoCentral, 280 }, + { LocationNames.NewZealandNorth, 394 }, + { LocationNames.NorthCentralUS, 236 }, + { LocationNames.NorthEurope, 157 }, + { LocationNames.NorwayEast, 170 }, + { LocationNames.NorwayWest, 162 }, + { LocationNames.PolandCentral, 152 }, + { LocationNames.QatarCentral, 260 }, + { LocationNames.SouthAfricaNorth, 18 }, + { LocationNames.SouthAfricaWest, 0 }, + { LocationNames.SouthCentralUS, 248 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 302 }, + { LocationNames.SoutheastUS, 280 }, + { LocationNames.SouthIndia, 280 }, + { LocationNames.SpainCentral, 150 }, + { LocationNames.SwedenCentral, 170 }, + { LocationNames.SwedenSouth, 170 }, + { LocationNames.SwitzerlandNorth, 162 }, + { LocationNames.SwitzerlandWest, 158 }, + { LocationNames.TaiwanNorth, 336 }, + { LocationNames.TaiwanNorthwest, 336 }, + { LocationNames.UAECentral, 260 }, + { LocationNames.UAENorth, 264 }, + { LocationNames.UKSouth, 144 }, + { LocationNames.UKWest, 146 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 258 }, + { LocationNames.WestEurope, 152 }, + { LocationNames.WestIndia, 270 }, + { LocationNames.WestUS, 280 }, + { LocationNames.WestUS2, 280 }, + { LocationNames.WestUS3, 280 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SouthCentralUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 174 }, + { LocationNames.AustraliaCentral2, 174 }, + { LocationNames.AustraliaEast, 170 }, + { LocationNames.AustraliaSoutheast, 180 }, + { LocationNames.AustriaEast, 118 }, + { LocationNames.BrazilSouth, 140 }, + { LocationNames.BrazilSoutheast, 140 }, + { LocationNames.CanadaCentral, 42 }, + { LocationNames.CanadaEast, 52 }, + { LocationNames.CentralIndia, 224 }, + { LocationNames.CentralUS, 22 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 182 }, + { LocationNames.EastUS, 32 }, + { LocationNames.EastUS2, 26 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 106 }, + { LocationNames.FranceSouth, 116 }, + { LocationNames.GermanyNorth, 120 }, + { LocationNames.GermanyWestCentral, 116 }, + { LocationNames.IndonesiaCentral, 200 }, + { LocationNames.IsraelCentral, 218 }, + { LocationNames.ItalyNorth, 118 }, + { LocationNames.JapanEast, 138 }, + { LocationNames.JapanWest, 138 }, + { LocationNames.JioIndiaCentral, 224 }, + { LocationNames.JioIndiaWest, 224 }, + { LocationNames.KoreaCentral, 152 }, + { LocationNames.KoreaSouth, 156 }, + { LocationNames.MalaysiaSouth, 200 }, + { LocationNames.MalaysiaWest, 200 }, + { LocationNames.MexicoCentral, 44 }, + { LocationNames.NewZealandNorth, 174 }, + { LocationNames.NorthCentralUS, 30 }, + { LocationNames.NorthEurope, 106 }, + { LocationNames.NorwayEast, 132 }, + { LocationNames.NorwayWest, 124 }, + { LocationNames.PolandCentral, 112 }, + { LocationNames.QatarCentral, 218 }, + { LocationNames.SouthAfricaNorth, 264 }, + { LocationNames.SouthAfricaWest, 248 }, + { LocationNames.SouthCentralUS, 0 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 200 }, + { LocationNames.SoutheastUS, 44 }, + { LocationNames.SouthIndia, 222 }, + { LocationNames.SpainCentral, 106 }, + { LocationNames.SwedenCentral, 132 }, + { LocationNames.SwedenSouth, 132 }, + { LocationNames.SwitzerlandNorth, 118 }, + { LocationNames.SwitzerlandWest, 116 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, + { LocationNames.UAECentral, 218 }, + { LocationNames.UAENorth, 220 }, + { LocationNames.UKSouth, 104 }, + { LocationNames.UKWest, 106 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 112 }, + { LocationNames.WestIndia, 226 }, + { LocationNames.WestUS, 34 }, + { LocationNames.WestUS2, 44 }, + { LocationNames.WestUS3, 44 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SouthCentralUSSTG, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, 26 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 32 }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, 200 }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, 200 }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, 30 }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, 0 }, + { LocationNames.SoutheastAsia, 200 }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, 44 }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SoutheastAsia, + new Dictionary() + { + { LocationNames.AustraliaCentral, 94 }, + { LocationNames.AustraliaCentral2, 92 }, + { LocationNames.AustraliaEast, 88 }, + { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, + { LocationNames.BrazilSouth, 328 }, + { LocationNames.BrazilSoutheast, 328 }, + { LocationNames.CanadaCentral, 216 }, + { LocationNames.CanadaEast, 224 }, + { LocationNames.CentralIndia, 52 }, + { LocationNames.CentralUS, 194 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 33 }, + { LocationNames.EastUS, 218 }, + { LocationNames.EastUS2, 226 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 218 }, + { LocationNames.FranceCentral, 150 }, + { LocationNames.FranceSouth, 138 }, + { LocationNames.GermanyNorth, 162 }, + { LocationNames.GermanyWestCentral, 154 }, + { LocationNames.IndonesiaCentral, 100 }, + { LocationNames.IsraelCentral, 76 }, + { LocationNames.ItalyNorth, 148 }, + { LocationNames.JapanEast, 68 }, + { LocationNames.JapanWest, 74 }, + { LocationNames.JioIndiaCentral, 52 }, + { LocationNames.JioIndiaWest, 52 }, + { LocationNames.KoreaCentral, 62 }, + { LocationNames.KoreaSouth, 56 }, + { LocationNames.MalaysiaSouth, 100 }, + { LocationNames.MalaysiaWest, 100 }, + { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, + { LocationNames.NorthCentralUS, 202 }, + { LocationNames.NorthEurope, 172 }, + { LocationNames.NorwayEast, 180 }, + { LocationNames.NorwayWest, 174 }, + { LocationNames.PolandCentral, 160 }, + { LocationNames.QatarCentral, 76 }, + { LocationNames.SouthAfricaNorth, 298 }, + { LocationNames.SouthAfricaWest, 302 }, + { LocationNames.SouthCentralUS, 200 }, + { LocationNames.SouthCentralUSSTG, 200 }, + { LocationNames.SoutheastAsia, 0 }, + { LocationNames.SoutheastUS, 160 }, + { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, + { LocationNames.SwedenCentral, 180 }, + { LocationNames.SwedenSouth, 180 }, + { LocationNames.SwitzerlandNorth, 148 }, + { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, + { LocationNames.UAECentral, 76 }, + { LocationNames.UAENorth, 76 }, + { LocationNames.UKSouth, 158 }, + { LocationNames.UKWest, 161 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 180 }, + { LocationNames.WestEurope, 160 }, + { LocationNames.WestIndia, 50 }, + { LocationNames.WestUS, 168 }, + { LocationNames.WestUS2, 160 }, + { LocationNames.WestUS3, 160 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SoutheastUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 162 }, + { LocationNames.AustraliaCentral2, 162 }, + { LocationNames.AustraliaEast, 158 }, + { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, + { LocationNames.BrazilSouth, 182 }, + { LocationNames.BrazilSoutheast, 182 }, + { LocationNames.CanadaCentral, 57 }, + { LocationNames.CanadaEast, 66 }, + { LocationNames.CentralIndia, 212 }, + { LocationNames.CentralUS, 36 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 140 }, + { LocationNames.EastUS, 58 }, + { LocationNames.EastUS2, 68 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 140 }, + { LocationNames.FranceSouth, 146 }, + { LocationNames.GermanyNorth, 154 }, + { LocationNames.GermanyWestCentral, 148 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 236 }, + { LocationNames.ItalyNorth, 154 }, + { LocationNames.JapanEast, 112 }, + { LocationNames.JapanWest, 112 }, + { LocationNames.JioIndiaCentral, 212 }, + { LocationNames.JioIndiaWest, 212 }, + { LocationNames.KoreaCentral, 122 }, + { LocationNames.KoreaSouth, 126 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 100 }, + { LocationNames.NewZealandNorth, 162 }, + { LocationNames.NorthCentralUS, 44 }, + { LocationNames.NorthEurope, 136 }, + { LocationNames.NorwayEast, 164 }, + { LocationNames.NorwayWest, 156 }, + { LocationNames.PolandCentral, 142 }, + { LocationNames.QatarCentral, 236 }, + { LocationNames.SouthAfricaNorth, 296 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 44 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 0 }, + { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, + { LocationNames.SwedenCentral, 164 }, + { LocationNames.SwedenSouth, 164 }, + { LocationNames.SwitzerlandNorth, 154 }, + { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, + { LocationNames.UAECentral, 236 }, + { LocationNames.UAENorth, 236 }, + { LocationNames.UKSouth, 130 }, + { LocationNames.UKWest, 132 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 142 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 22 }, + { LocationNames.WestUS2, 32 }, + { LocationNames.WestUS3, 100 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SouthIndia, + new Dictionary() + { + { LocationNames.AustraliaCentral, 126 }, + { LocationNames.AustraliaCentral2, 124 }, + { LocationNames.AustraliaEast, 120 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 126 }, + { LocationNames.BrazilSouth, 314 }, + { LocationNames.BrazilSoutheast, 314 }, + { LocationNames.CanadaCentral, 220 }, + { LocationNames.CanadaEast, 230 }, + { LocationNames.CentralIndia, 22 }, + { LocationNames.CentralUS, 228 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 66 }, + { LocationNames.EastUS, 208 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 128 }, + { LocationNames.FranceSouth, 114 }, + { LocationNames.GermanyNorth, 140 }, + { LocationNames.GermanyWestCentral, 130 }, + { LocationNames.IndonesiaCentral, 34 }, + { LocationNames.IsraelCentral, 46 }, + { LocationNames.ItalyNorth, 126 }, + { LocationNames.JapanEast, 100 }, + { LocationNames.JapanWest, 104 }, + { LocationNames.JioIndiaCentral, 22 }, + { LocationNames.JioIndiaWest, 22 }, + { LocationNames.KoreaCentral, 95 }, + { LocationNames.KoreaSouth, 88 }, + { LocationNames.MalaysiaSouth, 34 }, + { LocationNames.MalaysiaWest, 34 }, + { LocationNames.MexicoCentral, 192 }, + { LocationNames.NewZealandNorth, 126 }, + { LocationNames.NorthCentralUS, 228 }, + { LocationNames.NorthEurope, 149 }, + { LocationNames.NorwayEast, 157 }, + { LocationNames.NorwayWest, 150 }, + { LocationNames.PolandCentral, 136 }, + { LocationNames.QatarCentral, 46 }, + { LocationNames.SouthAfricaNorth, 276 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 222 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 34 }, + { LocationNames.SoutheastUS, 192 }, + { LocationNames.SouthIndia, 0 }, + { LocationNames.SpainCentral, 128 }, + { LocationNames.SwedenCentral, 157 }, + { LocationNames.SwedenSouth, 157 }, + { LocationNames.SwitzerlandNorth, 126 }, + { LocationNames.SwitzerlandWest, 122 }, + { LocationNames.TaiwanNorth, 66 }, + { LocationNames.TaiwanNorthwest, 66 }, + { LocationNames.UAECentral, 46 }, + { LocationNames.UAENorth, 46 }, + { LocationNames.UKSouth, 134 }, + { LocationNames.UKWest, 138 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 212 }, + { LocationNames.WestEurope, 136 }, + { LocationNames.WestIndia, 20 }, + { LocationNames.WestUS, 200 }, + { LocationNames.WestUS2, 192 }, + { LocationNames.WestUS3, 192 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SpainCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 242 }, + { LocationNames.AustraliaCentral2, 242 }, + { LocationNames.AustraliaEast, 238 }, + { LocationNames.AustraliaSoutheast, 235 }, + { LocationNames.AustriaEast, 14 }, + { LocationNames.BrazilSouth, 186 }, + { LocationNames.BrazilSoutheast, 186 }, + { LocationNames.CanadaCentral, 92 }, + { LocationNames.CanadaEast, 102 }, + { LocationNames.CentralIndia, 116 }, + { LocationNames.CentralUS, 101 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 184 }, + { LocationNames.EastUS, 80 }, + { LocationNames.EastUS2, 80 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 100 }, + { LocationNames.FranceSouth, 11 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 10 }, + { LocationNames.IndonesiaCentral, 150 }, + { LocationNames.IsraelCentral, 108 }, + { LocationNames.ItalyNorth, 14 }, + { LocationNames.JapanEast, 218 }, + { LocationNames.JapanWest, 218 }, + { LocationNames.JioIndiaCentral, 116 }, + { LocationNames.JioIndiaWest, 116 }, + { LocationNames.KoreaCentral, 212 }, + { LocationNames.KoreaSouth, 206 }, + { LocationNames.MalaysiaSouth, 150 }, + { LocationNames.MalaysiaWest, 150 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 242 }, + { LocationNames.NorthCentralUS, 96 }, + { LocationNames.NorthEurope, 27 }, + { LocationNames.NorwayEast, 30 }, + { LocationNames.NorwayWest, 24 }, + { LocationNames.PolandCentral, 10 }, + { LocationNames.QatarCentral, 108 }, + { LocationNames.SouthAfricaNorth, 166 }, + { LocationNames.SouthAfricaWest, 150 }, + { LocationNames.SouthCentralUS, 106 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 150 }, + { LocationNames.SoutheastUS, 140 }, + { LocationNames.SouthIndia, 128 }, + { LocationNames.SpainCentral, 0 }, + { LocationNames.SwedenCentral, 30 }, + { LocationNames.SwedenSouth, 30 }, + { LocationNames.SwitzerlandNorth, 14 }, + { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, + { LocationNames.UAECentral, 108 }, + { LocationNames.UAENorth, 112 }, + { LocationNames.UKSouth, 7 }, + { LocationNames.UKWest, 8 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 119 }, + { LocationNames.WestEurope, 10 }, + { LocationNames.WestIndia, 118 }, + { LocationNames.WestUS, 138 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SwedenCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 272 }, + { LocationNames.AustraliaCentral2, 272 }, + { LocationNames.AustraliaEast, 266 }, + { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 32 }, + { LocationNames.BrazilSouth, 208 }, + { LocationNames.BrazilSoutheast, 208 }, + { LocationNames.CanadaCentral, 114 }, + { LocationNames.CanadaEast, 124 }, + { LocationNames.CentralIndia, 146 }, + { LocationNames.CentralUS, 128 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 214 }, + { LocationNames.EastUS, 101 }, + { LocationNames.EastUS2, 104 }, + { LocationNames.EastUSSLV, 255 }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 30 }, + { LocationNames.FranceSouth, 42 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 26 }, + { LocationNames.IndonesiaCentral, 180 }, + { LocationNames.IsraelCentral, 129 }, + { LocationNames.ItalyNorth, 32 }, + { LocationNames.JapanEast, 254 }, + { LocationNames.JapanWest, 248 }, + { LocationNames.JioIndiaCentral, 146 }, + { LocationNames.JioIndiaWest, 146 }, + { LocationNames.KoreaCentral, 242 }, + { LocationNames.KoreaSouth, 235 }, + { LocationNames.MalaysiaSouth, 180 }, + { LocationNames.MalaysiaWest, 180 }, + { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, + { LocationNames.NorthCentralUS, 122 }, + { LocationNames.NorthEurope, 40 }, + { LocationNames.NorwayEast, 10 }, + { LocationNames.NorwayWest, 10 }, + { LocationNames.PolandCentral, 22 }, + { LocationNames.QatarCentral, 138 }, + { LocationNames.SouthAfricaNorth, 186 }, + { LocationNames.SouthAfricaWest, 170 }, + { LocationNames.SouthCentralUS, 132 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 180 }, + { LocationNames.SoutheastUS, 164 }, + { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, + { LocationNames.SwedenCentral, 0 }, + { LocationNames.SwedenSouth, 10 }, + { LocationNames.SwitzerlandNorth, 32 }, + { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, + { LocationNames.UAECentral, 138 }, + { LocationNames.UAENorth, 140 }, + { LocationNames.UKSouth, 28 }, + { LocationNames.UKWest, 30 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 142 }, + { LocationNames.WestEurope, 22 }, + { LocationNames.WestIndia, 146 }, + { LocationNames.WestUS, 163 }, + { LocationNames.WestUS2, 164 }, + { LocationNames.WestUS3, 164 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SwedenSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 272 }, + { LocationNames.AustraliaCentral2, 272 }, + { LocationNames.AustraliaEast, 266 }, + { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 255 }, + { LocationNames.BrazilSouth, 208 }, + { LocationNames.BrazilSoutheast, 208 }, + { LocationNames.CanadaCentral, 114 }, + { LocationNames.CanadaEast, 124 }, + { LocationNames.CentralIndia, 146 }, + { LocationNames.CentralUS, 128 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 214 }, + { LocationNames.EastUS, 101 }, + { LocationNames.EastUS2, 104 }, + { LocationNames.EastUSSLV, 255 }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 30 }, + { LocationNames.FranceSouth, 42 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 26 }, + { LocationNames.IndonesiaCentral, 180 }, + { LocationNames.IsraelCentral, 129 }, + { LocationNames.ItalyNorth, 255 }, + { LocationNames.JapanEast, 254 }, + { LocationNames.JapanWest, 248 }, + { LocationNames.JioIndiaCentral, 146 }, + { LocationNames.JioIndiaWest, 146 }, + { LocationNames.KoreaCentral, 242 }, + { LocationNames.KoreaSouth, 235 }, + { LocationNames.MalaysiaSouth, 180 }, + { LocationNames.MalaysiaWest, 180 }, + { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, + { LocationNames.NorthCentralUS, 122 }, + { LocationNames.NorthEurope, 40 }, + { LocationNames.NorwayEast, 10 }, + { LocationNames.NorwayWest, 10 }, + { LocationNames.PolandCentral, 22 }, + { LocationNames.QatarCentral, 138 }, + { LocationNames.SouthAfricaNorth, 186 }, + { LocationNames.SouthAfricaWest, 170 }, + { LocationNames.SouthCentralUS, 132 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 180 }, + { LocationNames.SoutheastUS, 164 }, + { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, + { LocationNames.SwedenCentral, 5 }, + { LocationNames.SwedenSouth, 0 }, + { LocationNames.SwitzerlandNorth, 32 }, + { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, + { LocationNames.UAECentral, 138 }, + { LocationNames.UAENorth, 140 }, + { LocationNames.UKSouth, 28 }, + { LocationNames.UKWest, 28 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 142 }, + { LocationNames.WestEurope, 22 }, + { LocationNames.WestIndia, 146 }, + { LocationNames.WestUS, 163 }, + { LocationNames.WestUS2, 164 }, + { LocationNames.WestUS3, 164 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SwitzerlandNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 240 }, + { LocationNames.AustraliaCentral2, 240 }, + { LocationNames.AustraliaEast, 236 }, + { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 100 }, + { LocationNames.BrazilSouth, 198 }, + { LocationNames.BrazilSoutheast, 198 }, + { LocationNames.CanadaCentral, 104 }, + { LocationNames.CanadaEast, 114 }, + { LocationNames.CentralIndia, 112 }, + { LocationNames.CentralUS, 112 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 182 }, + { LocationNames.EastUS, 92 }, + { LocationNames.EastUS2, 94 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 14 }, + { LocationNames.FranceSouth, 10 }, + { LocationNames.GermanyNorth, 16 }, + { LocationNames.GermanyWestCentral, 6 }, + { LocationNames.IndonesiaCentral, 148 }, + { LocationNames.IsraelCentral, 106 }, + { LocationNames.ItalyNorth, 100 }, + { LocationNames.JapanEast, 216 }, + { LocationNames.JapanWest, 216 }, + { LocationNames.JioIndiaCentral, 112 }, + { LocationNames.JioIndiaWest, 112 }, + { LocationNames.KoreaCentral, 210 }, + { LocationNames.KoreaSouth, 204 }, + { LocationNames.MalaysiaSouth, 148 }, + { LocationNames.MalaysiaWest, 148 }, + { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, + { LocationNames.NorthCentralUS, 110 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 32 }, + { LocationNames.NorwayWest, 26 }, + { LocationNames.PolandCentral, 12 }, + { LocationNames.QatarCentral, 106 }, + { LocationNames.SouthAfricaNorth, 172 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 118 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 148 }, + { LocationNames.SoutheastUS, 154 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, + { LocationNames.SwedenCentral, 32 }, + { LocationNames.SwedenSouth, 255 }, + { LocationNames.SwitzerlandNorth, 0 }, + { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, + { LocationNames.UAECentral, 106 }, + { LocationNames.UAENorth, 108 }, + { LocationNames.UKSouth, 20 }, + { LocationNames.UKWest, 22 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 134 }, + { LocationNames.WestEurope, 12 }, + { LocationNames.WestIndia, 116 }, + { LocationNames.WestUS, 150 }, + { LocationNames.WestUS2, 154 }, + { LocationNames.WestUS3, 154 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.SwitzerlandWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 236 }, + { LocationNames.AustraliaCentral2, 236 }, + { LocationNames.AustraliaEast, 232 }, + { LocationNames.AustraliaSoutheast, 228 }, + { LocationNames.AustriaEast, 4 }, + { LocationNames.BrazilSouth, 202 }, + { LocationNames.BrazilSoutheast, 202 }, + { LocationNames.CanadaCentral, 108 }, + { LocationNames.CanadaEast, 118 }, + { LocationNames.CentralIndia, 110 }, + { LocationNames.CentralUS, 110 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 178 }, + { LocationNames.EastUS, 88 }, + { LocationNames.EastUS2, 88 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 10 }, + { LocationNames.FranceSouth, 8 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 10 }, + { LocationNames.IndonesiaCentral, 144 }, + { LocationNames.IsraelCentral, 102 }, + { LocationNames.ItalyNorth, 4 }, + { LocationNames.JapanEast, 212 }, + { LocationNames.JapanWest, 210 }, + { LocationNames.JioIndiaCentral, 110 }, + { LocationNames.JioIndiaWest, 110 }, + { LocationNames.KoreaCentral, 206 }, + { LocationNames.KoreaSouth, 200 }, + { LocationNames.MalaysiaSouth, 144 }, + { LocationNames.MalaysiaWest, 144 }, + { LocationNames.MexicoCentral, 146 }, + { LocationNames.NewZealandNorth, 236 }, + { LocationNames.NorthCentralUS, 106 }, + { LocationNames.NorthEurope, 30 }, + { LocationNames.NorwayEast, 36 }, + { LocationNames.NorwayWest, 30 }, + { LocationNames.PolandCentral, 16 }, + { LocationNames.QatarCentral, 102 }, + { LocationNames.SouthAfricaNorth, 168 }, + { LocationNames.SouthAfricaWest, 158 }, + { LocationNames.SouthCentralUS, 116 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 144 }, + { LocationNames.SoutheastUS, 146 }, + { LocationNames.SouthIndia, 122 }, + { LocationNames.SpainCentral, 10 }, + { LocationNames.SwedenCentral, 36 }, + { LocationNames.SwedenSouth, 36 }, + { LocationNames.SwitzerlandNorth, 4 }, + { LocationNames.SwitzerlandWest, 0 }, + { LocationNames.TaiwanNorth, 178 }, + { LocationNames.TaiwanNorthwest, 178 }, + { LocationNames.UAECentral, 102 }, + { LocationNames.UAENorth, 106 }, + { LocationNames.UKSouth, 16 }, + { LocationNames.UKWest, 18 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 126 }, + { LocationNames.WestEurope, 16 }, + { LocationNames.WestIndia, 112 }, + { LocationNames.WestUS, 147 }, + { LocationNames.WestUS2, 146 }, + { LocationNames.WestUS3, 146 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.TaiwanNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 120 }, + { LocationNames.AustraliaCentral2, 120 }, + { LocationNames.AustraliaEast, 116 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 196 }, + { LocationNames.CanadaEast, 206 }, + { LocationNames.CentralIndia, 86 }, + { LocationNames.CentralUS, 176 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 100 }, + { LocationNames.EastUS, 199 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 184 }, + { LocationNames.FranceSouth, 172 }, + { LocationNames.GermanyNorth, 196 }, + { LocationNames.GermanyWestCentral, 188 }, + { LocationNames.IndonesiaCentral, 33 }, + { LocationNames.IsraelCentral, 110 }, + { LocationNames.ItalyNorth, 182 }, + { LocationNames.JapanEast, 50 }, + { LocationNames.JapanWest, 50 }, + { LocationNames.JioIndiaCentral, 86 }, + { LocationNames.JioIndiaWest, 86 }, + { LocationNames.KoreaCentral, 56 }, + { LocationNames.KoreaSouth, 60 }, + { LocationNames.MalaysiaSouth, 33 }, + { LocationNames.MalaysiaWest, 33 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, + { LocationNames.NorthCentralUS, 184 }, + { LocationNames.NorthEurope, 205 }, + { LocationNames.NorwayEast, 214 }, + { LocationNames.NorwayWest, 206 }, + { LocationNames.PolandCentral, 193 }, + { LocationNames.QatarCentral, 110 }, + { LocationNames.SouthAfricaNorth, 332 }, + { LocationNames.SouthAfricaWest, 336 }, + { LocationNames.SouthCentralUS, 182 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 33 }, + { LocationNames.SoutheastUS, 140 }, + { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, + { LocationNames.SwedenCentral, 214 }, + { LocationNames.SwedenSouth, 214 }, + { LocationNames.SwitzerlandNorth, 182 }, + { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 0 }, + { LocationNames.TaiwanNorthwest, 100 }, + { LocationNames.UAECentral, 110 }, + { LocationNames.UAENorth, 109 }, + { LocationNames.UKSouth, 192 }, + { LocationNames.UKWest, 194 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 162 }, + { LocationNames.WestEurope, 193 }, + { LocationNames.WestIndia, 84 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.TaiwanNorthwest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 120 }, + { LocationNames.AustraliaCentral2, 120 }, + { LocationNames.AustraliaEast, 116 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 196 }, + { LocationNames.CanadaEast, 206 }, + { LocationNames.CentralIndia, 86 }, + { LocationNames.CentralUS, 176 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 100 }, + { LocationNames.EastUS, 199 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 184 }, + { LocationNames.FranceSouth, 172 }, + { LocationNames.GermanyNorth, 196 }, + { LocationNames.GermanyWestCentral, 188 }, + { LocationNames.IndonesiaCentral, 33 }, + { LocationNames.IsraelCentral, 110 }, + { LocationNames.ItalyNorth, 182 }, + { LocationNames.JapanEast, 50 }, + { LocationNames.JapanWest, 50 }, + { LocationNames.JioIndiaCentral, 86 }, + { LocationNames.JioIndiaWest, 86 }, + { LocationNames.KoreaCentral, 56 }, + { LocationNames.KoreaSouth, 60 }, + { LocationNames.MalaysiaSouth, 33 }, + { LocationNames.MalaysiaWest, 33 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, + { LocationNames.NorthCentralUS, 184 }, + { LocationNames.NorthEurope, 205 }, + { LocationNames.NorwayEast, 214 }, + { LocationNames.NorwayWest, 206 }, + { LocationNames.PolandCentral, 193 }, + { LocationNames.QatarCentral, 110 }, + { LocationNames.SouthAfricaNorth, 332 }, + { LocationNames.SouthAfricaWest, 336 }, + { LocationNames.SouthCentralUS, 182 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 33 }, + { LocationNames.SoutheastUS, 140 }, + { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, + { LocationNames.SwedenCentral, 214 }, + { LocationNames.SwedenSouth, 214 }, + { LocationNames.SwitzerlandNorth, 182 }, + { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 100 }, + { LocationNames.TaiwanNorthwest, 0 }, + { LocationNames.UAECentral, 110 }, + { LocationNames.UAENorth, 109 }, + { LocationNames.UKSouth, 192 }, + { LocationNames.UKWest, 194 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 162 }, + { LocationNames.WestEurope, 193 }, + { LocationNames.WestIndia, 84 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.UAECentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 168 }, + { LocationNames.AustraliaCentral2, 168 }, + { LocationNames.AustraliaEast, 164 }, + { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, + { LocationNames.BrazilSouth, 296 }, + { LocationNames.BrazilSoutheast, 296 }, + { LocationNames.CanadaCentral, 201 }, + { LocationNames.CanadaEast, 210 }, + { LocationNames.CentralIndia, 30 }, + { LocationNames.CentralUS, 216 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 110 }, + { LocationNames.EastUS, 189 }, + { LocationNames.EastUS2, 190 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 108 }, + { LocationNames.FranceSouth, 96 }, + { LocationNames.GermanyNorth, 120 }, + { LocationNames.GermanyWestCentral, 112 }, + { LocationNames.IndonesiaCentral, 76 }, + { LocationNames.IsraelCentral, 100 }, + { LocationNames.ItalyNorth, 106 }, + { LocationNames.JapanEast, 144 }, + { LocationNames.JapanWest, 149 }, + { LocationNames.JioIndiaCentral, 30 }, + { LocationNames.JioIndiaWest, 30 }, + { LocationNames.KoreaCentral, 138 }, + { LocationNames.KoreaSouth, 132 }, + { LocationNames.MalaysiaSouth, 76 }, + { LocationNames.MalaysiaWest, 76 }, + { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, + { LocationNames.NorthCentralUS, 209 }, + { LocationNames.NorthEurope, 129 }, + { LocationNames.NorwayEast, 138 }, + { LocationNames.NorwayWest, 130 }, + { LocationNames.PolandCentral, 118 }, + { LocationNames.QatarCentral, 4 }, + { LocationNames.SouthAfricaNorth, 256 }, + { LocationNames.SouthAfricaWest, 260 }, + { LocationNames.SouthCentralUS, 218 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 76 }, + { LocationNames.SoutheastUS, 236 }, + { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, + { LocationNames.SwedenCentral, 129 }, + { LocationNames.SwedenSouth, 129 }, + { LocationNames.SwitzerlandNorth, 106 }, + { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, + { LocationNames.UAECentral, 0 }, + { LocationNames.UAENorth, 4 }, + { LocationNames.UKSouth, 116 }, + { LocationNames.UKWest, 118 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 230 }, + { LocationNames.WestEurope, 118 }, + { LocationNames.WestIndia, 28 }, + { LocationNames.WestUS, 244 }, + { LocationNames.WestUS2, 236 }, + { LocationNames.WestUS3, 236 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.UAENorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 168 }, + { LocationNames.AustraliaCentral2, 168 }, + { LocationNames.AustraliaEast, 163 }, + { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 108 }, + { LocationNames.BrazilSouth, 298 }, + { LocationNames.BrazilSoutheast, 298 }, + { LocationNames.CanadaCentral, 204 }, + { LocationNames.CanadaEast, 214 }, + { LocationNames.CentralIndia, 30 }, + { LocationNames.CentralUS, 218 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 109 }, + { LocationNames.EastUS, 192 }, + { LocationNames.EastUS2, 194 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 112 }, + { LocationNames.FranceSouth, 98 }, + { LocationNames.GermanyNorth, 124 }, + { LocationNames.GermanyWestCentral, 114 }, + { LocationNames.IndonesiaCentral, 76 }, + { LocationNames.IsraelCentral, 4 }, + { LocationNames.ItalyNorth, 108 }, + { LocationNames.JapanEast, 144 }, + { LocationNames.JapanWest, 148 }, + { LocationNames.JioIndiaCentral, 30 }, + { LocationNames.JioIndiaWest, 30 }, + { LocationNames.KoreaCentral, 138 }, + { LocationNames.KoreaSouth, 130 }, + { LocationNames.MalaysiaSouth, 76 }, + { LocationNames.MalaysiaWest, 76 }, + { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, + { LocationNames.NorthCentralUS, 212 }, + { LocationNames.NorthEurope, 132 }, + { LocationNames.NorwayEast, 140 }, + { LocationNames.NorwayWest, 134 }, + { LocationNames.PolandCentral, 120 }, + { LocationNames.QatarCentral, 4 }, + { LocationNames.SouthAfricaNorth, 260 }, + { LocationNames.SouthAfricaWest, 264 }, + { LocationNames.SouthCentralUS, 220 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 76 }, + { LocationNames.SoutheastUS, 236 }, + { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 112 }, + { LocationNames.SwedenCentral, 140 }, + { LocationNames.SwedenSouth, 140 }, + { LocationNames.SwitzerlandNorth, 108 }, + { LocationNames.SwitzerlandWest, 106 }, + { LocationNames.TaiwanNorth, 109 }, + { LocationNames.TaiwanNorthwest, 109 }, + { LocationNames.UAECentral, 4 }, + { LocationNames.UAENorth, 0 }, + { LocationNames.UKSouth, 120 }, + { LocationNames.UKWest, 122 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 234 }, + { LocationNames.WestEurope, 120 }, + { LocationNames.WestIndia, 28 }, + { LocationNames.WestUS, 244 }, + { LocationNames.WestUS2, 236 }, + { LocationNames.WestUS3, 236 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.UKSouth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 250 }, + { LocationNames.AustraliaCentral2, 248 }, + { LocationNames.AustraliaEast, 246 }, + { LocationNames.AustraliaSoutheast, 242 }, + { LocationNames.AustriaEast, 20 }, + { LocationNames.BrazilSouth, 181 }, + { LocationNames.BrazilSoutheast, 181 }, + { LocationNames.CanadaCentral, 86 }, + { LocationNames.CanadaEast, 96 }, + { LocationNames.CentralIndia, 122 }, + { LocationNames.CentralUS, 96 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 192 }, + { LocationNames.EastUS, 74 }, + { LocationNames.EastUS2, 78 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 7 }, + { LocationNames.FranceSouth, 16 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 14 }, + { LocationNames.IndonesiaCentral, 158 }, + { LocationNames.IsraelCentral, 116 }, + { LocationNames.ItalyNorth, 20 }, + { LocationNames.JapanEast, 226 }, + { LocationNames.JapanWest, 225 }, + { LocationNames.JioIndiaCentral, 122 }, + { LocationNames.JioIndiaWest, 122 }, + { LocationNames.KoreaCentral, 220 }, + { LocationNames.KoreaSouth, 214 }, + { LocationNames.MalaysiaSouth, 158 }, + { LocationNames.MalaysiaWest, 158 }, + { LocationNames.MexicoCentral, 130 }, + { LocationNames.NewZealandNorth, 250 }, + { LocationNames.NorthCentralUS, 90 }, + { LocationNames.NorthEurope, 21 }, + { LocationNames.NorwayEast, 28 }, + { LocationNames.NorwayWest, 22 }, + { LocationNames.PolandCentral, 10 }, + { LocationNames.QatarCentral, 116 }, + { LocationNames.SouthAfricaNorth, 160 }, + { LocationNames.SouthAfricaWest, 144 }, + { LocationNames.SouthCentralUS, 104 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 158 }, + { LocationNames.SoutheastUS, 130 }, + { LocationNames.SouthIndia, 134 }, + { LocationNames.SpainCentral, 7 }, + { LocationNames.SwedenCentral, 21 }, + { LocationNames.SwedenSouth, 21 }, + { LocationNames.SwitzerlandNorth, 20 }, + { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 192 }, + { LocationNames.TaiwanNorthwest, 192 }, + { LocationNames.UAECentral, 116 }, + { LocationNames.UAENorth, 120 }, + { LocationNames.UKSouth, 0 }, + { LocationNames.UKWest, 4 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 110 }, + { LocationNames.WestEurope, 10 }, + { LocationNames.WestIndia, 126 }, + { LocationNames.WestUS, 136 }, + { LocationNames.WestUS2, 130 }, + { LocationNames.WestUS3, 130 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.UKWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 252 }, + { LocationNames.AustraliaCentral2, 252 }, + { LocationNames.AustraliaEast, 248 }, + { LocationNames.AustraliaSoutheast, 245 }, + { LocationNames.AustriaEast, 22 }, + { LocationNames.BrazilSouth, 184 }, + { LocationNames.BrazilSoutheast, 184 }, + { LocationNames.CanadaCentral, 90 }, + { LocationNames.CanadaEast, 98 }, + { LocationNames.CentralIndia, 126 }, + { LocationNames.CentralUS, 96 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 194 }, + { LocationNames.EastUS, 76 }, + { LocationNames.EastUS2, 80 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 8 }, + { LocationNames.FranceSouth, 18 }, + { LocationNames.GermanyNorth, 22 }, + { LocationNames.GermanyWestCentral, 18 }, + { LocationNames.IndonesiaCentral, 161 }, + { LocationNames.IsraelCentral, 118 }, + { LocationNames.ItalyNorth, 22 }, + { LocationNames.JapanEast, 230 }, + { LocationNames.JapanWest, 228 }, + { LocationNames.JioIndiaCentral, 126 }, + { LocationNames.JioIndiaWest, 126 }, + { LocationNames.KoreaCentral, 222 }, + { LocationNames.KoreaSouth, 216 }, + { LocationNames.MalaysiaSouth, 161 }, + { LocationNames.MalaysiaWest, 161 }, + { LocationNames.MexicoCentral, 132 }, + { LocationNames.NewZealandNorth, 252 }, + { LocationNames.NorthCentralUS, 92 }, + { LocationNames.NorthEurope, 17 }, + { LocationNames.NorwayEast, 30 }, + { LocationNames.NorwayWest, 24 }, + { LocationNames.PolandCentral, 12 }, + { LocationNames.QatarCentral, 118 }, + { LocationNames.SouthAfricaNorth, 164 }, + { LocationNames.SouthAfricaWest, 146 }, + { LocationNames.SouthCentralUS, 106 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 161 }, + { LocationNames.SoutheastUS, 132 }, + { LocationNames.SouthIndia, 138 }, + { LocationNames.SpainCentral, 8 }, + { LocationNames.SwedenCentral, 30 }, + { LocationNames.SwedenSouth, 30 }, + { LocationNames.SwitzerlandNorth, 22 }, + { LocationNames.SwitzerlandWest, 18 }, + { LocationNames.TaiwanNorth, 194 }, + { LocationNames.TaiwanNorthwest, 194 }, + { LocationNames.UAECentral, 118 }, + { LocationNames.UAENorth, 122 }, + { LocationNames.UKSouth, 4 }, + { LocationNames.UKWest, 0 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 112 }, + { LocationNames.WestEurope, 12 }, + { LocationNames.WestIndia, 128 }, + { LocationNames.WestUS, 138 }, + { LocationNames.WestUS2, 132 }, + { LocationNames.WestUS3, 132 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USDoDCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, 0 }, + { LocationNames.USDoDEast, 44 }, + { LocationNames.USGovArizona, 42 }, + { LocationNames.USGovTexas, 24 }, + { LocationNames.USGovVirginia, 44 }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USDoDEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, 44 }, + { LocationNames.USDoDEast, 0 }, + { LocationNames.USGovArizona, 45 }, + { LocationNames.USGovTexas, 27 }, + { LocationNames.USGovVirginia, 2 }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USGovArizona, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, 42 }, + { LocationNames.USDoDEast, 46 }, + { LocationNames.USGovArizona, 0 }, + { LocationNames.USGovTexas, 20 }, + { LocationNames.USGovVirginia, 45 }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USGovTexas, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, 24 }, + { LocationNames.USDoDEast, 28 }, + { LocationNames.USGovArizona, 20 }, + { LocationNames.USGovTexas, 0 }, + { LocationNames.USGovVirginia, 35 }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USGovVirginia, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, 44 }, + { LocationNames.USDoDEast, 2 }, + { LocationNames.USGovArizona, 45 }, + { LocationNames.USGovTexas, 35 }, + { LocationNames.USGovVirginia, 0 }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USNatEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, 0 }, + { LocationNames.USNatWest, 255 }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USNatWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, 255 }, + { LocationNames.USNatWest, 0 }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USSecEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, 0 }, + { LocationNames.USSecWest, 255 }, + { LocationNames.USSecWestCentral, 255 }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USSecWest, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, 255 }, + { LocationNames.USSecWest, 0 }, + { LocationNames.USSecWestCentral, 100 }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.USSecWestCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, 255 }, + { LocationNames.USSecWest, 100 }, + { LocationNames.USSecWestCentral, 0 }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestCentralUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 170 }, + { LocationNames.AustraliaCentral2, 170 }, + { LocationNames.AustraliaEast, 166 }, + { LocationNames.AustraliaSoutheast, 176 }, + { LocationNames.AustriaEast, 134 }, + { LocationNames.BrazilSouth, 160 }, + { LocationNames.BrazilSoutheast, 160 }, + { LocationNames.CanadaCentral, 36 }, + { LocationNames.CanadaEast, 44 }, + { LocationNames.CentralIndia, 236 }, + { LocationNames.CentralUS, 15 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 162 }, + { LocationNames.EastUS, 38 }, + { LocationNames.EastUS2, 47 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 119 }, + { LocationNames.FranceSouth, 126 }, + { LocationNames.GermanyNorth, 132 }, + { LocationNames.GermanyWestCentral, 126 }, + { LocationNames.IndonesiaCentral, 180 }, + { LocationNames.IsraelCentral, 230 }, + { LocationNames.ItalyNorth, 134 }, + { LocationNames.JapanEast, 126 }, + { LocationNames.JapanWest, 128 }, + { LocationNames.JioIndiaCentral, 236 }, + { LocationNames.JioIndiaWest, 236 }, + { LocationNames.KoreaCentral, 143 }, + { LocationNames.KoreaSouth, 148 }, + { LocationNames.MalaysiaSouth, 180 }, + { LocationNames.MalaysiaWest, 180 }, + { LocationNames.MexicoCentral, 22 }, + { LocationNames.NewZealandNorth, 170 }, + { LocationNames.NorthCentralUS, 22 }, + { LocationNames.NorthEurope, 110 }, + { LocationNames.NorwayEast, 142 }, + { LocationNames.NorwayWest, 136 }, + { LocationNames.PolandCentral, 120 }, + { LocationNames.QatarCentral, 230 }, + { LocationNames.SouthAfricaNorth, 274 }, + { LocationNames.SouthAfricaWest, 258 }, + { LocationNames.SouthCentralUS, 22 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 180 }, + { LocationNames.SoutheastUS, 22 }, + { LocationNames.SouthIndia, 212 }, + { LocationNames.SpainCentral, 119 }, + { LocationNames.SwedenCentral, 142 }, + { LocationNames.SwedenSouth, 142 }, + { LocationNames.SwitzerlandNorth, 134 }, + { LocationNames.SwitzerlandWest, 126 }, + { LocationNames.TaiwanNorth, 162 }, + { LocationNames.TaiwanNorthwest, 162 }, + { LocationNames.UAECentral, 230 }, + { LocationNames.UAENorth, 234 }, + { LocationNames.UKSouth, 110 }, + { LocationNames.UKWest, 112 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 0 }, + { LocationNames.WestEurope, 120 }, + { LocationNames.WestIndia, 240 }, + { LocationNames.WestUS, 30 }, + { LocationNames.WestUS2, 22 }, + { LocationNames.WestUS3, 22 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestEurope, + new Dictionary() + { + { LocationNames.AustraliaCentral, 252 }, + { LocationNames.AustraliaCentral2, 252 }, + { LocationNames.AustraliaEast, 248 }, + { LocationNames.AustraliaSoutheast, 244 }, + { LocationNames.AustriaEast, 12 }, + { LocationNames.BrazilSouth, 188 }, + { LocationNames.BrazilSoutheast, 188 }, + { LocationNames.CanadaCentral, 94 }, + { LocationNames.CanadaEast, 103 }, + { LocationNames.CentralIndia, 126 }, + { LocationNames.CentralUS, 102 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 193 }, + { LocationNames.EastUS, 81 }, + { LocationNames.EastUS2, 86 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 10 }, + { LocationNames.FranceSouth, 20 }, + { LocationNames.GermanyNorth, 10 }, + { LocationNames.GermanyWestCentral, 8 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 118 }, + { LocationNames.ItalyNorth, 12 }, + { LocationNames.JapanEast, 234 }, + { LocationNames.JapanWest, 228 }, + { LocationNames.JioIndiaCentral, 126 }, + { LocationNames.JioIndiaWest, 126 }, + { LocationNames.KoreaCentral, 222 }, + { LocationNames.KoreaSouth, 216 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 142 }, + { LocationNames.NewZealandNorth, 252 }, + { LocationNames.NorthCentralUS, 102 }, + { LocationNames.NorthEurope, 22 }, + { LocationNames.NorwayEast, 22 }, + { LocationNames.NorwayWest, 15 }, + { LocationNames.PolandCentral, 100 }, + { LocationNames.QatarCentral, 118 }, + { LocationNames.SouthAfricaNorth, 170 }, + { LocationNames.SouthAfricaWest, 152 }, + { LocationNames.SouthCentralUS, 112 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 142 }, + { LocationNames.SouthIndia, 136 }, + { LocationNames.SpainCentral, 10 }, + { LocationNames.SwedenCentral, 22 }, + { LocationNames.SwedenSouth, 22 }, + { LocationNames.SwitzerlandNorth, 12 }, + { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 193 }, + { LocationNames.TaiwanNorthwest, 193 }, + { LocationNames.UAECentral, 118 }, + { LocationNames.UAENorth, 120 }, + { LocationNames.UKSouth, 10 }, + { LocationNames.UKWest, 12 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 120 }, + { LocationNames.WestEurope, 0 }, + { LocationNames.WestIndia, 128 }, + { LocationNames.WestUS, 144 }, + { LocationNames.WestUS2, 142 }, + { LocationNames.WestUS3, 142 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestIndia, + new Dictionary() + { + { LocationNames.AustraliaCentral, 142 }, + { LocationNames.AustraliaCentral2, 142 }, + { LocationNames.AustraliaEast, 138 }, + { LocationNames.AustraliaSoutheast, 134 }, + { LocationNames.AustriaEast, 116 }, + { LocationNames.BrazilSouth, 304 }, + { LocationNames.BrazilSoutheast, 304 }, + { LocationNames.CanadaCentral, 210 }, + { LocationNames.CanadaEast, 220 }, + { LocationNames.CentralIndia, 4 }, + { LocationNames.CentralUS, 224 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 84 }, + { LocationNames.EastUS, 198 }, + { LocationNames.EastUS2, 200 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 118 }, + { LocationNames.FranceSouth, 106 }, + { LocationNames.GermanyNorth, 130 }, + { LocationNames.GermanyWestCentral, 122 }, + { LocationNames.IndonesiaCentral, 50 }, + { LocationNames.IsraelCentral, 28 }, + { LocationNames.ItalyNorth, 116 }, + { LocationNames.JapanEast, 118 }, + { LocationNames.JapanWest, 122 }, + { LocationNames.JioIndiaCentral, 4 }, + { LocationNames.JioIndiaWest, 4 }, + { LocationNames.KoreaCentral, 112 }, + { LocationNames.KoreaSouth, 106 }, + { LocationNames.MalaysiaSouth, 50 }, + { LocationNames.MalaysiaWest, 50 }, + { LocationNames.MexicoCentral, 210 }, + { LocationNames.NewZealandNorth, 142 }, + { LocationNames.NorthCentralUS, 218 }, + { LocationNames.NorthEurope, 139 }, + { LocationNames.NorwayEast, 146 }, + { LocationNames.NorwayWest, 140 }, + { LocationNames.PolandCentral, 128 }, + { LocationNames.QatarCentral, 28 }, + { LocationNames.SouthAfricaNorth, 266 }, + { LocationNames.SouthAfricaWest, 270 }, + { LocationNames.SouthCentralUS, 226 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 50 }, + { LocationNames.SoutheastUS, 210 }, + { LocationNames.SouthIndia, 20 }, + { LocationNames.SpainCentral, 118 }, + { LocationNames.SwedenCentral, 146 }, + { LocationNames.SwedenSouth, 146 }, + { LocationNames.SwitzerlandNorth, 116 }, + { LocationNames.SwitzerlandWest, 112 }, + { LocationNames.TaiwanNorth, 84 }, + { LocationNames.TaiwanNorthwest, 84 }, + { LocationNames.UAECentral, 28 }, + { LocationNames.UAENorth, 28 }, + { LocationNames.UKSouth, 126 }, + { LocationNames.UKWest, 128 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 240 }, + { LocationNames.WestEurope, 128 }, + { LocationNames.WestIndia, 0 }, + { LocationNames.WestUS, 217 }, + { LocationNames.WestUS2, 210 }, + { LocationNames.WestUS3, 210 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestUS, + new Dictionary() + { + { LocationNames.AustraliaCentral, 142 }, + { LocationNames.AustraliaCentral2, 142 }, + { LocationNames.AustraliaEast, 138 }, + { LocationNames.AustraliaSoutheast, 148 }, + { LocationNames.AustriaEast, 150 }, + { LocationNames.BrazilSouth, 172 }, + { LocationNames.BrazilSoutheast, 172 }, + { LocationNames.CanadaCentral, 64 }, + { LocationNames.CanadaEast, 72 }, + { LocationNames.CentralIndia, 218 }, + { LocationNames.CentralUS, 44 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 148 }, + { LocationNames.EastUS, 64 }, + { LocationNames.EastUS2, 58 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 138 }, + { LocationNames.FranceSouth, 148 }, + { LocationNames.GermanyNorth, 153 }, + { LocationNames.GermanyWestCentral, 148 }, + { LocationNames.IndonesiaCentral, 168 }, + { LocationNames.IsraelCentral, 244 }, + { LocationNames.ItalyNorth, 150 }, + { LocationNames.JapanEast, 106 }, + { LocationNames.JapanWest, 106 }, + { LocationNames.JioIndiaCentral, 218 }, + { LocationNames.JioIndiaWest, 218 }, + { LocationNames.KoreaCentral, 130 }, + { LocationNames.KoreaSouth, 134 }, + { LocationNames.MalaysiaSouth, 168 }, + { LocationNames.MalaysiaWest, 168 }, + { LocationNames.MexicoCentral, 22 }, + { LocationNames.NewZealandNorth, 142 }, + { LocationNames.NorthCentralUS, 50 }, + { LocationNames.NorthEurope, 133 }, + { LocationNames.NorwayEast, 163 }, + { LocationNames.NorwayWest, 156 }, + { LocationNames.PolandCentral, 144 }, + { LocationNames.QatarCentral, 244 }, + { LocationNames.SouthAfricaNorth, 298 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 34 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 168 }, + { LocationNames.SoutheastUS, 22 }, + { LocationNames.SouthIndia, 200 }, + { LocationNames.SpainCentral, 138 }, + { LocationNames.SwedenCentral, 163 }, + { LocationNames.SwedenSouth, 163 }, + { LocationNames.SwitzerlandNorth, 150 }, + { LocationNames.SwitzerlandWest, 147 }, + { LocationNames.TaiwanNorth, 148 }, + { LocationNames.TaiwanNorthwest, 148 }, + { LocationNames.UAECentral, 244 }, + { LocationNames.UAENorth, 244 }, + { LocationNames.UKSouth, 136 }, + { LocationNames.UKWest, 138 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 30 }, + { LocationNames.WestEurope, 144 }, + { LocationNames.WestIndia, 217 }, + { LocationNames.WestUS, 0 }, + { LocationNames.WestUS2, 22 }, + { LocationNames.WestUS3, 22 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestUS2, + new Dictionary() + { + { LocationNames.AustraliaCentral, 162 }, + { LocationNames.AustraliaCentral2, 162 }, + { LocationNames.AustraliaEast, 158 }, + { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, + { LocationNames.BrazilSouth, 182 }, + { LocationNames.BrazilSoutheast, 182 }, + { LocationNames.CanadaCentral, 57 }, + { LocationNames.CanadaEast, 66 }, + { LocationNames.CentralIndia, 212 }, + { LocationNames.CentralUS, 36 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 140 }, + { LocationNames.EastUS, 58 }, + { LocationNames.EastUS2, 68 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, 58 }, + { LocationNames.FranceCentral, 140 }, + { LocationNames.FranceSouth, 146 }, + { LocationNames.GermanyNorth, 154 }, + { LocationNames.GermanyWestCentral, 148 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 236 }, + { LocationNames.ItalyNorth, 154 }, + { LocationNames.JapanEast, 112 }, + { LocationNames.JapanWest, 112 }, + { LocationNames.JioIndiaCentral, 212 }, + { LocationNames.JioIndiaWest, 212 }, + { LocationNames.KoreaCentral, 122 }, + { LocationNames.KoreaSouth, 126 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 100 }, + { LocationNames.NewZealandNorth, 162 }, + { LocationNames.NorthCentralUS, 44 }, + { LocationNames.NorthEurope, 136 }, + { LocationNames.NorwayEast, 164 }, + { LocationNames.NorwayWest, 156 }, + { LocationNames.PolandCentral, 142 }, + { LocationNames.QatarCentral, 236 }, + { LocationNames.SouthAfricaNorth, 296 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 44 }, + { LocationNames.SouthCentralUSSTG, 44 }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 32 }, + { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, + { LocationNames.SwedenCentral, 164 }, + { LocationNames.SwedenSouth, 164 }, + { LocationNames.SwitzerlandNorth, 154 }, + { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, + { LocationNames.UAECentral, 236 }, + { LocationNames.UAENorth, 236 }, + { LocationNames.UKSouth, 130 }, + { LocationNames.UKWest, 132 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 142 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 22 }, + { LocationNames.WestUS2, 0 }, + { LocationNames.WestUS3, 32 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.WestUS3, + new Dictionary() + { + { LocationNames.AustraliaCentral, 162 }, + { LocationNames.AustraliaCentral2, 162 }, + { LocationNames.AustraliaEast, 158 }, + { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, + { LocationNames.BrazilSouth, 182 }, + { LocationNames.BrazilSoutheast, 182 }, + { LocationNames.CanadaCentral, 57 }, + { LocationNames.CanadaEast, 66 }, + { LocationNames.CentralIndia, 212 }, + { LocationNames.CentralUS, 36 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 140 }, + { LocationNames.EastUS, 58 }, + { LocationNames.EastUS2, 68 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, 140 }, + { LocationNames.FranceSouth, 146 }, + { LocationNames.GermanyNorth, 154 }, + { LocationNames.GermanyWestCentral, 148 }, + { LocationNames.IndonesiaCentral, 160 }, + { LocationNames.IsraelCentral, 236 }, + { LocationNames.ItalyNorth, 154 }, + { LocationNames.JapanEast, 112 }, + { LocationNames.JapanWest, 112 }, + { LocationNames.JioIndiaCentral, 212 }, + { LocationNames.JioIndiaWest, 212 }, + { LocationNames.KoreaCentral, 122 }, + { LocationNames.KoreaSouth, 126 }, + { LocationNames.MalaysiaSouth, 160 }, + { LocationNames.MalaysiaWest, 160 }, + { LocationNames.MexicoCentral, 100 }, + { LocationNames.NewZealandNorth, 162 }, + { LocationNames.NorthCentralUS, 44 }, + { LocationNames.NorthEurope, 136 }, + { LocationNames.NorwayEast, 164 }, + { LocationNames.NorwayWest, 156 }, + { LocationNames.PolandCentral, 142 }, + { LocationNames.QatarCentral, 236 }, + { LocationNames.SouthAfricaNorth, 296 }, + { LocationNames.SouthAfricaWest, 280 }, + { LocationNames.SouthCentralUS, 44 }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, 160 }, + { LocationNames.SoutheastUS, 100 }, + { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, + { LocationNames.SwedenCentral, 164 }, + { LocationNames.SwedenSouth, 164 }, + { LocationNames.SwitzerlandNorth, 154 }, + { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, + { LocationNames.UAECentral, 236 }, + { LocationNames.UAENorth, 236 }, + { LocationNames.UKSouth, 130 }, + { LocationNames.UKWest, 132 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 142 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 22 }, + { LocationNames.WestUS2, 32 }, + { LocationNames.WestUS3, 0 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.CentralUSEUAP, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, 255 }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, 0 }, + { LocationNames.EastUS2EUAP, 40 }, + } + }, + { + LocationNames.EastUS2EUAP, + new Dictionary() + { + { LocationNames.AustraliaCentral, long.MaxValue }, + { LocationNames.AustraliaCentral2, long.MaxValue }, + { LocationNames.AustraliaEast, long.MaxValue }, + { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, + { LocationNames.BrazilSouth, long.MaxValue }, + { LocationNames.BrazilSoutheast, long.MaxValue }, + { LocationNames.CanadaCentral, long.MaxValue }, + { LocationNames.CanadaEast, long.MaxValue }, + { LocationNames.CentralIndia, long.MaxValue }, + { LocationNames.CentralUS, long.MaxValue }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, long.MaxValue }, + { LocationNames.EastUS, long.MaxValue }, + { LocationNames.EastUS2, long.MaxValue }, + { LocationNames.EastUSSLV, 255 }, + { LocationNames.EastUSSTG, long.MaxValue }, + { LocationNames.FranceCentral, long.MaxValue }, + { LocationNames.FranceSouth, long.MaxValue }, + { LocationNames.GermanyNorth, long.MaxValue }, + { LocationNames.GermanyWestCentral, long.MaxValue }, + { LocationNames.IndonesiaCentral, long.MaxValue }, + { LocationNames.IsraelCentral, long.MaxValue }, + { LocationNames.ItalyNorth, long.MaxValue }, + { LocationNames.JapanEast, long.MaxValue }, + { LocationNames.JapanWest, long.MaxValue }, + { LocationNames.JioIndiaCentral, long.MaxValue }, + { LocationNames.JioIndiaWest, long.MaxValue }, + { LocationNames.KoreaCentral, long.MaxValue }, + { LocationNames.KoreaSouth, long.MaxValue }, + { LocationNames.MalaysiaSouth, long.MaxValue }, + { LocationNames.MalaysiaWest, long.MaxValue }, + { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, + { LocationNames.NorthCentralUS, long.MaxValue }, + { LocationNames.NorthEurope, long.MaxValue }, + { LocationNames.NorwayEast, long.MaxValue }, + { LocationNames.NorwayWest, long.MaxValue }, + { LocationNames.PolandCentral, long.MaxValue }, + { LocationNames.QatarCentral, long.MaxValue }, + { LocationNames.SouthAfricaNorth, long.MaxValue }, + { LocationNames.SouthAfricaWest, long.MaxValue }, + { LocationNames.SouthCentralUS, long.MaxValue }, + { LocationNames.SouthCentralUSSTG, long.MaxValue }, + { LocationNames.SoutheastAsia, long.MaxValue }, + { LocationNames.SoutheastUS, long.MaxValue }, + { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, + { LocationNames.SwedenCentral, long.MaxValue }, + { LocationNames.SwedenSouth, long.MaxValue }, + { LocationNames.SwitzerlandNorth, long.MaxValue }, + { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, + { LocationNames.UAECentral, long.MaxValue }, + { LocationNames.UAENorth, long.MaxValue }, + { LocationNames.UKSouth, long.MaxValue }, + { LocationNames.UKWest, long.MaxValue }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, long.MaxValue }, + { LocationNames.WestEurope, long.MaxValue }, + { LocationNames.WestIndia, long.MaxValue }, + { LocationNames.WestUS, long.MaxValue }, + { LocationNames.WestUS2, long.MaxValue }, + { LocationNames.WestUS3, long.MaxValue }, + { LocationNames.CentralUSEUAP, 40 }, + { LocationNames.EastUS2EUAP, 0 }, + } + } + }; + + private static long GetLinkTypeThresholdInMs(GeoLinkTypes geoLinkType) + { + switch(geoLinkType) + { + case GeoLinkTypes.Strong: + return 100; + case GeoLinkTypes.Medium: + return 200; + case GeoLinkTypes.Weak: + return long.MaxValue; + default: + throw new ArgumentException("GeoLinkType provided is invalid."); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RemoteStorageType.cs b/Microsoft.Azure.Cosmos/src/direct/RemoteStorageType.cs index b062fdc601..e695a6f65f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RemoteStorageType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RemoteStorageType.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies type of storage used - /// - internal enum RemoteStorageType - { - /// - /// Use Standard Storage - /// - NotSpecified, - - /// - /// Use Standard Storage - /// - Standard, - - /// - /// Use Premium Storage - /// - Premium - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies type of storage used + /// + internal enum RemoteStorageType + { + /// + /// Use Standard Storage + /// + NotSpecified, + + /// + /// Use Standard Storage + /// + Standard, + + /// + /// Use Premium Storage + /// + Premium + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ReplicatedResourceClient.cs b/Microsoft.Azure.Cosmos/src/direct/ReplicatedResourceClient.cs index a5b8a801a4..7e19472e83 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReplicatedResourceClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReplicatedResourceClient.cs @@ -1,425 +1,440 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Client; - - /// - /// ReplicatedResourceClient uses the ConsistencyReader to make requests to backend - /// - internal sealed class ReplicatedResourceClient - { - private const string EnableGlobalStrongConfigurationName = "EnableGlobalStrong"; - private const int GoneAndRetryWithRetryTimeoutInSeconds = 30; - private const int StrongGoneAndRetryWithRetryTimeoutInSeconds = 60; - - private readonly TimeSpan minBackoffForFallingBackToOtherRegions = TimeSpan.FromSeconds(1); - - private readonly AddressSelector addressSelector; - private readonly IAddressResolver addressResolver; - private readonly ConsistencyReader consistencyReader; - private readonly ConsistencyWriter consistencyWriter; - private readonly Protocol protocol; - private readonly TransportClient transportClient; - private readonly IServiceConfigurationReader serviceConfigReader; - private readonly bool enableReadRequestsFallback; - private readonly bool useMultipleWriteLocations; - private readonly bool detectClientConnectivityIssues; - private readonly RetryWithConfiguration retryWithConfiguration; - private readonly bool disableRetryWithRetryPolicy; - - private static readonly Lazy enableGlobalStrong = new Lazy(() => { - bool isGlobalStrongEnabled = true; -#if !(NETSTANDARD15 || NETSTANDARD16) -#if NETSTANDARD20 - // GetEntryAssembly returns null when loaded from native netstandard2.0 - if (System.Reflection.Assembly.GetEntryAssembly() != null) - { -#endif - string isGlobalStrongEnabledConfig = System.Configuration.ConfigurationManager.AppSettings[ReplicatedResourceClient.EnableGlobalStrongConfigurationName]; - if (!string.IsNullOrEmpty(isGlobalStrongEnabledConfig)) - { - if (!bool.TryParse(isGlobalStrongEnabledConfig, out isGlobalStrongEnabled)) - { - return false; - } - } -#if NETSTANDARD20 - } -#endif -#endif - return isGlobalStrongEnabled; - }); - - public ReplicatedResourceClient( - IAddressResolver addressResolver, - ISessionContainer sessionContainer, - Protocol protocol, - TransportClient transportClient, - IServiceConfigurationReader serviceConfigReader, - IAuthorizationTokenProvider authorizationTokenProvider, - bool enableReadRequestsFallback, - bool useMultipleWriteLocations, - bool detectClientConnectivityIssues, - bool disableRetryWithRetryPolicy, - bool enableReplicaValidation, - RetryWithConfiguration retryWithConfiguration = null) - { - this.addressResolver = addressResolver; - this.addressSelector = new AddressSelector(addressResolver, protocol); - if (protocol != Protocol.Https && protocol != Protocol.Tcp) - { - throw new ArgumentOutOfRangeException(nameof(protocol)); - } - - this.protocol = protocol; - this.transportClient = transportClient; - this.serviceConfigReader = serviceConfigReader; - - this.consistencyReader = new ConsistencyReader( - this.addressSelector, - sessionContainer, - transportClient, - serviceConfigReader, - authorizationTokenProvider, - enableReplicaValidation); - this.consistencyWriter = new ConsistencyWriter( - this.addressSelector, - sessionContainer, - transportClient, - serviceConfigReader, - authorizationTokenProvider, - useMultipleWriteLocations, - enableReplicaValidation); - this.enableReadRequestsFallback = enableReadRequestsFallback; - this.useMultipleWriteLocations = useMultipleWriteLocations; - this.detectClientConnectivityIssues = detectClientConnectivityIssues; - this.retryWithConfiguration = retryWithConfiguration; - this.disableRetryWithRetryPolicy = disableRetryWithRetryPolicy; - } - - #region Test hooks - public string LastReadAddress - { - get - { - return this.consistencyReader.LastReadAddress; - } - - set - { - this.consistencyReader.LastReadAddress = value; - } - } - - public string LastWriteAddress - { - get - { - return this.consistencyWriter.LastWriteAddress; - } - } - - public bool ForceAddressRefresh - { - get; - set; - } - - /// - /// Overrides retry policy timeout for testing purposes. - /// - public int? GoneAndRetryWithRetryTimeoutInSecondsOverride - { - get; - set; - } - #endregion - - public Task InvokeAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)) - { - Func> funcDelegate = async (GoneAndRetryRequestRetryPolicyContext contextArguments) => - { - request.Headers[HttpConstants.HttpHeaders.ClientRetryAttemptCount] = contextArguments.ClientRetryCount.ToString(CultureInfo.InvariantCulture); - request.Headers[HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest] = contextArguments.RemainingTimeInMsOnClientRequest.TotalMilliseconds.ToString(CultureInfo.InvariantCulture); - - return await this.InvokeAsync( - request, - new TimeoutHelper(contextArguments.RemainingTimeInMsOnClientRequest, cancellationToken), - contextArguments.IsInRetry, - contextArguments.ForceRefresh || this.ForceAddressRefresh, - cancellationToken); - }; - - Func> inBackoffFuncDelegate = null; - - //we will enable fallback to other regions if the following conditions are met: - // 1. request is a read operation AND - // 2. enableReadRequestsFallback is set to true. (can only ever be true if direct mode, on client) - // 3. write requests that can be retried - if ((request.OperationType.IsReadOperation() && this.enableReadRequestsFallback) || - this.CheckWriteRetryable(request)) - { - IClientSideRequestStatistics sharedStatistics = null; - - if (request.RequestContext.ClientRequestStatistics == null) - { - sharedStatistics = new ClientSideRequestStatistics(); - request.RequestContext.ClientRequestStatistics = sharedStatistics; - } - else - { - sharedStatistics = request.RequestContext.ClientRequestStatistics; - } - - //clone all new requests from this fresh clone, as this isnt polluted by interim state. - //also create shared statistics object for use by all clones. - DocumentServiceRequest freshRequest = request.Clone(); - - inBackoffFuncDelegate = async (GoneAndRetryRequestRetryPolicyContext retryContext) => - { - DocumentServiceRequest requestClone = freshRequest.Clone(); - requestClone.RequestContext.ClientRequestStatistics = sharedStatistics; - - DefaultTrace.TraceInformation("Executing inBackoffAlternateCallbackMethod on regionIndex {0}", retryContext.RegionRerouteAttemptCount); - requestClone.RequestContext.RouteToLocation( - retryContext.RegionRerouteAttemptCount, // regionRerouteRetryCount - usePreferredLocations: true); - - return await RequestRetryUtility.ProcessRequestAsync( - (GoneOnlyRequestRetryPolicyContext innerRetryContext) => this.InvokeAsync( - requestClone, - new TimeoutHelper( - innerRetryContext.RemainingTimeInMsOnClientRequest, // timeout - cancellationToken), - innerRetryContext.IsInRetry, // isInRetry - innerRetryContext.ForceRefresh, // forceRefresh - cancellationToken), - prepareRequest: () => { - requestClone.RequestContext.ClientRequestStatistics?.RecordRequest(requestClone); - return requestClone; - }, - policy: new GoneOnlyRequestRetryPolicy( - retryContext.TimeoutForInBackoffRetryPolicy), // backoffTime - cancellationToken: cancellationToken); - }; - } - - int retryTimeout = this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong ? - ReplicatedResourceClient.StrongGoneAndRetryWithRetryTimeoutInSeconds : - ReplicatedResourceClient.GoneAndRetryWithRetryTimeoutInSeconds; - - // Used on test hooks - if (this.GoneAndRetryWithRetryTimeoutInSecondsOverride.HasValue) - { - retryTimeout = this.GoneAndRetryWithRetryTimeoutInSecondsOverride.Value; - } - - return RequestRetryUtility.ProcessRequestAsync( - funcDelegate, - prepareRequest: () => { - request.RequestContext.ClientRequestStatistics?.RecordRequest(request); - return request; - }, - policy: new GoneAndRetryWithRequestRetryPolicy( - disableRetryWithPolicy: this.disableRetryWithRetryPolicy || request.DisableRetryWithPolicy, - waitTimeInSecondsOverride: retryTimeout, - minBackoffForRegionReroute: this.minBackoffForFallingBackToOtherRegions, - detectConnectivityIssues: this.detectClientConnectivityIssues, - retryWithConfiguration: this.retryWithConfiguration), - inBackoffAlternateCallbackMethod: inBackoffFuncDelegate, - minBackoffForInBackoffCallback: this.minBackoffForFallingBackToOtherRegions, - cancellationToken: cancellationToken); - } - - /// - /// Attempts to open a connection to all the replicas for all the available partitions of a given container. - /// - /// A string containing the name of the database. - /// A string containing the container's link uri - /// An Instance of the . - public async Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default) - { - IAddressResolverExtension addressResolverExtension = (IAddressResolverExtension)this.addressResolver; - // This check will eventually be removed, when the OpenConnectionsToAllReplicas() move to the IAddressResolver. - if (addressResolverExtension == null) - { - throw new InvalidOperationException("The Address Resolver provided is not an instance of IAddressResolverExtension."); - } - - await addressResolverExtension.OpenConnectionsToAllReplicasAsync( - databaseName, - containerLinkUri, - cancellationToken); - } - - private Task InvokeAsync(DocumentServiceRequest request, TimeoutHelper timeout, bool isInRetry, bool forceRefresh, CancellationToken cancellationToken) - { - if (request.OperationType == OperationType.ExecuteJavaScript) - { - if (request.IsReadOnlyScript) return this.consistencyReader.ReadAsync(request, timeout, isInRetry, forceRefresh, cancellationToken); - else return this.consistencyWriter.WriteAsync(request, timeout, forceRefresh, cancellationToken); - } - else if (request.OperationType.IsWriteOperation()) - { - return this.consistencyWriter.WriteAsync(request, timeout, forceRefresh, cancellationToken); - } -#if !COSMOSCLIENT - else if (request.OperationType == OperationType.GetStorageAuthToken) - { - return this.HandleGetStorageAuthTokenAsync(request, forceRefresh); - } -#endif - else if (request.OperationType.IsReadOperation()) - { - return this.consistencyReader.ReadAsync(request, timeout, isInRetry, forceRefresh, cancellationToken); - } -#if !COSMOSCLIENT - else if (request.OperationType == OperationType.Throttle - || request.OperationType == OperationType.PreCreateValidation - || request.OperationType == OperationType.OfferPreGrowValidation) - { - return this.HandleThrottlePreCreateOrOfferPreGrowAsync(request, forceRefresh); - } -#endif - else - { - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unexpected operation type {0}", request.OperationType)); - } - } - - private async Task HandleGetStorageAuthTokenAsync(DocumentServiceRequest request, bool forceRefresh) - { - PartitionAddressInformation addressInfo = await this.addressResolver.ResolveAsync(request, forceRefresh, CancellationToken.None); - Uri primaryUri = addressInfo.GetPrimaryUri(request, this.protocol); - - return await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); - } - - private async Task HandleThrottlePreCreateOrOfferPreGrowAsync(DocumentServiceRequest request, bool forceRefresh) - { - DocumentServiceRequest requestReplica = DocumentServiceRequest.Create( - OperationType.Create, - ResourceType.Database, - request.RequestAuthorizationTokenType); - - PartitionAddressInformation addressInfo = await this.addressResolver.ResolveAsync(requestReplica, forceRefresh, CancellationToken.None); - Uri primaryUri = addressInfo.GetPrimaryUri(requestReplica, this.protocol); - - return await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); - } - - private bool CheckWriteRetryable(DocumentServiceRequest request) - { - bool isRetryable = false; - - if (this.useMultipleWriteLocations) - { - if ((request.OperationType == OperationType.Execute && request.ResourceType == ResourceType.StoredProcedure) || - (request.OperationType.IsWriteOperation() && request.ResourceType == ResourceType.Document)) - { - isRetryable = true; - } - } - - return isRetryable; - } - - internal static bool IsGlobalStrongEnabled() - { - bool isGlobalStrongEnabled = true; -#if DOCDBCLIENT -#if !(NETSTANDARD15 || NETSTANDARD16) - isGlobalStrongEnabled = ReplicatedResourceClient.enableGlobalStrong.Value; -#endif -#endif - return isGlobalStrongEnabled; - } - - internal static bool IsReadingFromMaster(ResourceType resourceType, OperationType operationType) - { - if (resourceType == ResourceType.Offer || - resourceType == ResourceType.Database || - resourceType == ResourceType.User || - resourceType == ResourceType.ClientEncryptionKey || - resourceType == ResourceType.UserDefinedType || - resourceType == ResourceType.Permission || - resourceType == ResourceType.DatabaseAccount || - resourceType == ResourceType.Snapshot || - resourceType == ResourceType.RoleAssignment || - resourceType == ResourceType.RoleDefinition || - resourceType == ResourceType.EncryptionScope || - resourceType == ResourceType.AuthPolicyElement || - resourceType == ResourceType.InteropUser || -#if !COSMOSCLIENT - resourceType == ResourceType.Topology || - operationType == OperationType.GetStorageAuthToken || - (resourceType == ResourceType.PartitionKeyRange && operationType != OperationType.GetSplitPoint - && operationType != OperationType.GetSplitPoints && operationType != OperationType.AbortSplit) || -#else - resourceType == ResourceType.PartitionKeyRange || -#endif - (resourceType == ResourceType.Collection && (operationType == OperationType.ReadFeed || operationType == OperationType.Query || operationType == OperationType.SqlQuery)) - ) - { - return true; - } - - return false; - } - - internal static bool IsSessionTokenRequired( - ResourceType resourceType, - OperationType operationType) - { - // Stored procedures CRUD operations are done on master. Stored procedures execute are not a master operation. - return !ReplicatedResourceClient.IsMasterResource(resourceType) && - !ReplicatedResourceClient.IsStoredProcedureCrudOperation(resourceType, operationType) && - operationType != OperationType.QueryPlan; - } - - internal static bool IsStoredProcedureCrudOperation( - ResourceType resourceType, - OperationType operationType) - { - return resourceType == ResourceType.StoredProcedure && - operationType != Documents.OperationType.ExecuteJavaScript; - } - - internal static bool IsMasterResource(ResourceType resourceType) - { - if (resourceType == ResourceType.Offer || - resourceType == ResourceType.Database || - resourceType == ResourceType.User || - resourceType == ResourceType.ClientEncryptionKey || - resourceType == ResourceType.UserDefinedType || - resourceType == ResourceType.Permission || -#if !COSMOSCLIENT - resourceType == ResourceType.Topology || -#endif - resourceType == ResourceType.DatabaseAccount || - resourceType == ResourceType.PartitionKeyRange || - resourceType == ResourceType.Collection || - resourceType == ResourceType.Snapshot || - resourceType == ResourceType.RoleAssignment || - resourceType == ResourceType.RoleDefinition || - resourceType == ResourceType.EncryptionScope || - resourceType == ResourceType.Trigger || - resourceType == ResourceType.UserDefinedFunction) - { - return true; - } - - return false; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Client; + + /// + /// ReplicatedResourceClient uses the ConsistencyReader to make requests to backend + /// + internal sealed class ReplicatedResourceClient + { + private const string EnableGlobalStrongConfigurationName = "EnableGlobalStrong"; + private const int GoneAndRetryWithRetryTimeoutInSeconds = 30; + private const int StrongGoneAndRetryWithRetryTimeoutInSeconds = 60; + + private readonly TimeSpan minBackoffForFallingBackToOtherRegions = TimeSpan.FromSeconds(1); + + private readonly AddressSelector addressSelector; + private readonly IAddressResolver addressResolver; + private readonly ConsistencyReader consistencyReader; + private readonly ConsistencyWriter consistencyWriter; + private readonly Protocol protocol; + private readonly TransportClient transportClient; + private readonly IServiceConfigurationReader serviceConfigReader; + private readonly IServiceConfigurationReaderExtension serviceConfigurationReaderExtension; + private readonly bool enableReadRequestsFallback; + private readonly bool useMultipleWriteLocations; + private readonly bool detectClientConnectivityIssues; + private readonly RetryWithConfiguration retryWithConfiguration; + private readonly bool disableRetryWithRetryPolicy; + + private static readonly Lazy enableGlobalStrong = new Lazy(() => { + bool isGlobalStrongEnabled = true; +#if !(NETSTANDARD15 || NETSTANDARD16) +#if NETSTANDARD20 + // GetEntryAssembly returns null when loaded from native netstandard2.0 + if (System.Reflection.Assembly.GetEntryAssembly() != null) + { +#endif + string isGlobalStrongEnabledConfig = System.Configuration.ConfigurationManager.AppSettings[ReplicatedResourceClient.EnableGlobalStrongConfigurationName]; + if (!string.IsNullOrEmpty(isGlobalStrongEnabledConfig)) + { + if (!bool.TryParse(isGlobalStrongEnabledConfig, out isGlobalStrongEnabled)) + { + return false; + } + } +#if NETSTANDARD20 + } +#endif +#endif + return isGlobalStrongEnabled; + }); + + public ReplicatedResourceClient( + IAddressResolver addressResolver, + ISessionContainer sessionContainer, + Protocol protocol, + TransportClient transportClient, + IServiceConfigurationReader serviceConfigReader, + IAuthorizationTokenProvider authorizationTokenProvider, + bool enableReadRequestsFallback, + bool useMultipleWriteLocations, + bool detectClientConnectivityIssues, + bool disableRetryWithRetryPolicy, + bool enableReplicaValidation, + RetryWithConfiguration retryWithConfiguration = null) + { + this.addressResolver = addressResolver; + this.addressSelector = new AddressSelector(addressResolver, protocol); + if (protocol != Protocol.Https && protocol != Protocol.Tcp) + { + throw new ArgumentOutOfRangeException(nameof(protocol)); + } + + this.protocol = protocol; + this.transportClient = transportClient; + this.serviceConfigReader = serviceConfigReader; + this.serviceConfigurationReaderExtension = serviceConfigReader as IServiceConfigurationReaderExtension; + + this.consistencyReader = new ConsistencyReader( + this.addressSelector, + sessionContainer, + transportClient, + serviceConfigReader, + authorizationTokenProvider, + enableReplicaValidation); + this.consistencyWriter = new ConsistencyWriter( + this.addressSelector, + sessionContainer, + transportClient, + serviceConfigReader, + authorizationTokenProvider, + useMultipleWriteLocations, + enableReplicaValidation); + this.enableReadRequestsFallback = enableReadRequestsFallback; + this.useMultipleWriteLocations = useMultipleWriteLocations; + this.detectClientConnectivityIssues = detectClientConnectivityIssues; + this.retryWithConfiguration = retryWithConfiguration; + this.disableRetryWithRetryPolicy = disableRetryWithRetryPolicy; + } + + #region Test hooks + public string LastReadAddress + { + get + { + return this.consistencyReader.LastReadAddress; + } + + set + { + this.consistencyReader.LastReadAddress = value; + } + } + + public string LastWriteAddress + { + get + { + return this.consistencyWriter.LastWriteAddress; + } + } + + public bool ForceAddressRefresh + { + get; + set; + } + + /// + /// Overrides retry policy timeout for testing purposes. + /// + public int? GoneAndRetryWithRetryTimeoutInSecondsOverride + { + get; + set; + } + #endregion + + public Task InvokeAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)) + { + Func> funcDelegate = async (GoneAndRetryRequestRetryPolicyContext contextArguments) => + { + request.Headers[HttpConstants.HttpHeaders.ClientRetryAttemptCount] = contextArguments.ClientRetryCount.ToString(CultureInfo.InvariantCulture); + request.Headers[HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest] = contextArguments.RemainingTimeInMsOnClientRequest.TotalMilliseconds.ToString(CultureInfo.InvariantCulture); + + return await this.InvokeAsync( + request, + new TimeoutHelper(contextArguments.RemainingTimeInMsOnClientRequest, cancellationToken), + contextArguments.IsInRetry, + contextArguments.ForceRefresh || this.ForceAddressRefresh, + cancellationToken); + }; + + Func> inBackoffFuncDelegate = null; + + //we will enable fallback to other regions if the following conditions are met: + // 1. request is a read operation AND + // 2. enableReadRequestsFallback is set to true. (can only ever be true if direct mode, on client) + // 3. write requests that can be retried + if ((request.OperationType.IsReadOperation() && this.enableReadRequestsFallback) || + this.CheckWriteRetryable(request)) + { + IClientSideRequestStatistics sharedStatistics = null; + + if (request.RequestContext.ClientRequestStatistics == null) + { + sharedStatistics = new ClientSideRequestStatistics(); + request.RequestContext.ClientRequestStatistics = sharedStatistics; + } + else + { + sharedStatistics = request.RequestContext.ClientRequestStatistics; + } + + //clone all new requests from this fresh clone, as this isnt polluted by interim state. + //also create shared statistics object for use by all clones. + DocumentServiceRequest freshRequest = request.Clone(); + + inBackoffFuncDelegate = async (GoneAndRetryRequestRetryPolicyContext retryContext) => + { + DocumentServiceRequest requestClone = freshRequest.Clone(); + requestClone.RequestContext.ClientRequestStatistics = sharedStatistics; + + DefaultTrace.TraceInformation("Executing inBackoffAlternateCallbackMethod on regionIndex {0}", retryContext.RegionRerouteAttemptCount); + requestClone.RequestContext.RouteToLocation( + retryContext.RegionRerouteAttemptCount, // regionRerouteRetryCount + usePreferredLocations: true); + + return await RequestRetryUtility.ProcessRequestAsync( + (GoneOnlyRequestRetryPolicyContext innerRetryContext) => this.InvokeAsync( + requestClone, + new TimeoutHelper( + innerRetryContext.RemainingTimeInMsOnClientRequest, // timeout + cancellationToken), + innerRetryContext.IsInRetry, // isInRetry + innerRetryContext.ForceRefresh, // forceRefresh + cancellationToken), + prepareRequest: () => { + requestClone.RequestContext.ClientRequestStatistics?.RecordRequest(requestClone); + return requestClone; + }, + policy: new GoneOnlyRequestRetryPolicy( + retryContext.TimeoutForInBackoffRetryPolicy), // backoffTime + cancellationToken: cancellationToken); + }; + } + + int retryTimeout = this.serviceConfigReader.DefaultConsistencyLevel == ConsistencyLevel.Strong ? + ReplicatedResourceClient.StrongGoneAndRetryWithRetryTimeoutInSeconds : + ReplicatedResourceClient.GoneAndRetryWithRetryTimeoutInSeconds; + + if (this.serviceConfigurationReaderExtension != null) + { + IServiceRetryParams serviceRetryParams = this.serviceConfigurationReaderExtension.TryGetServiceRetryParams(request); + if (serviceRetryParams != null && + serviceRetryParams.TryGetRetryTimeoutInSeconds(out int retryTimeoutOverride) && + retryTimeoutOverride > 0 && + retryTimeoutOverride <= ReplicatedResourceClient.StrongGoneAndRetryWithRetryTimeoutInSeconds) + { + retryTimeout = retryTimeoutOverride; + DefaultTrace.TraceInformation("ReplicatedResourceClient: Override retryTimeout to {0}", retryTimeout); + } + } + + // Used on test hooks + if (this.GoneAndRetryWithRetryTimeoutInSecondsOverride.HasValue) + { + retryTimeout = this.GoneAndRetryWithRetryTimeoutInSecondsOverride.Value; + } + + return RequestRetryUtility.ProcessRequestAsync( + funcDelegate, + prepareRequest: () => { + request.RequestContext.ClientRequestStatistics?.RecordRequest(request); + return request; + }, + policy: new GoneAndRetryWithRequestRetryPolicy( + disableRetryWithPolicy: this.disableRetryWithRetryPolicy || request.DisableRetryWithPolicy, + waitTimeInSecondsOverride: retryTimeout, + minBackoffForRegionReroute: this.minBackoffForFallingBackToOtherRegions, + detectConnectivityIssues: this.detectClientConnectivityIssues, + retryWithConfiguration: this.retryWithConfiguration), + inBackoffAlternateCallbackMethod: inBackoffFuncDelegate, + minBackoffForInBackoffCallback: this.minBackoffForFallingBackToOtherRegions, + cancellationToken: cancellationToken); + } + + /// + /// Attempts to open a connection to all the replicas for all the available partitions of a given container. + /// + /// A string containing the name of the database. + /// A string containing the container's link uri + /// An Instance of the . + public async Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default) + { + IAddressResolverExtension addressResolverExtension = (IAddressResolverExtension)this.addressResolver; + // This check will eventually be removed, when the OpenConnectionsToAllReplicas() move to the IAddressResolver. + if (addressResolverExtension == null) + { + throw new InvalidOperationException("The Address Resolver provided is not an instance of IAddressResolverExtension."); + } + + await addressResolverExtension.OpenConnectionsToAllReplicasAsync( + databaseName, + containerLinkUri, + cancellationToken); + } + + private Task InvokeAsync(DocumentServiceRequest request, TimeoutHelper timeout, bool isInRetry, bool forceRefresh, CancellationToken cancellationToken) + { + if (request.OperationType == OperationType.ExecuteJavaScript) + { + if (request.IsReadOnlyScript) return this.consistencyReader.ReadAsync(request, timeout, isInRetry, forceRefresh, cancellationToken); + else return this.consistencyWriter.WriteAsync(request, timeout, forceRefresh, cancellationToken); + } + else if (request.OperationType.IsWriteOperation()) + { + return this.consistencyWriter.WriteAsync(request, timeout, forceRefresh, cancellationToken); + } +#if !COSMOSCLIENT + else if (request.OperationType == OperationType.GetStorageAuthToken) + { + return this.HandleGetStorageAuthTokenAsync(request, forceRefresh); + } +#endif + else if (request.OperationType.IsReadOperation()) + { + return this.consistencyReader.ReadAsync(request, timeout, isInRetry, forceRefresh, cancellationToken); + } +#if !COSMOSCLIENT + else if (request.OperationType == OperationType.Throttle + || request.OperationType == OperationType.PreCreateValidation + || request.OperationType == OperationType.OfferPreGrowValidation) + { + return this.HandleThrottlePreCreateOrOfferPreGrowAsync(request, forceRefresh); + } +#endif + else + { + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unexpected operation type {0}", request.OperationType)); + } + } + + private async Task HandleGetStorageAuthTokenAsync(DocumentServiceRequest request, bool forceRefresh) + { + PartitionAddressInformation addressInfo = await this.addressResolver.ResolveAsync(request, forceRefresh, CancellationToken.None); + Uri primaryUri = addressInfo.GetPrimaryUri(request, this.protocol); + + return await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); + } + + private async Task HandleThrottlePreCreateOrOfferPreGrowAsync(DocumentServiceRequest request, bool forceRefresh) + { + DocumentServiceRequest requestReplica = DocumentServiceRequest.Create( + OperationType.Create, + ResourceType.Database, + request.RequestAuthorizationTokenType); + + PartitionAddressInformation addressInfo = await this.addressResolver.ResolveAsync(requestReplica, forceRefresh, CancellationToken.None); + Uri primaryUri = addressInfo.GetPrimaryUri(requestReplica, this.protocol); + + return await this.transportClient.InvokeResourceOperationAsync(primaryUri, request); + } + + private bool CheckWriteRetryable(DocumentServiceRequest request) + { + bool isRetryable = false; + + if (this.useMultipleWriteLocations) + { + if ((request.OperationType == OperationType.Execute && request.ResourceType == ResourceType.StoredProcedure) || + (request.OperationType.IsWriteOperation() && request.ResourceType == ResourceType.Document)) + { + isRetryable = true; + } + } + + return isRetryable; + } + + internal static bool IsGlobalStrongEnabled() + { + bool isGlobalStrongEnabled = true; +#if DOCDBCLIENT +#if !(NETSTANDARD15 || NETSTANDARD16) + isGlobalStrongEnabled = ReplicatedResourceClient.enableGlobalStrong.Value; +#endif +#endif + return isGlobalStrongEnabled; + } + + internal static bool IsReadingFromMaster(ResourceType resourceType, OperationType operationType) + { + if (resourceType == ResourceType.Offer || + resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.ClientEncryptionKey || + resourceType == ResourceType.UserDefinedType || + resourceType == ResourceType.Permission || + resourceType == ResourceType.DatabaseAccount || + resourceType == ResourceType.Snapshot || + resourceType == ResourceType.RoleAssignment || + resourceType == ResourceType.RoleDefinition || + resourceType == ResourceType.EncryptionScope || + resourceType == ResourceType.AuthPolicyElement || + resourceType == ResourceType.InteropUser || +#if !COSMOSCLIENT + resourceType == ResourceType.Topology || + operationType == OperationType.GetStorageAuthToken || + (resourceType == ResourceType.PartitionKeyRange && operationType != OperationType.GetSplitPoint + && operationType != OperationType.GetSplitPoints && operationType != OperationType.AbortSplit) || +#else + resourceType == ResourceType.PartitionKeyRange || +#endif + (resourceType == ResourceType.Collection && (operationType == OperationType.ReadFeed || operationType == OperationType.Query || operationType == OperationType.SqlQuery)) + ) + { + return true; + } + + return false; + } + + internal static bool IsSessionTokenRequired( + ResourceType resourceType, + OperationType operationType) + { + // Stored procedures CRUD operations are done on master. Stored procedures execute are not a master operation. + return !ReplicatedResourceClient.IsMasterResource(resourceType) && + !ReplicatedResourceClient.IsStoredProcedureCrudOperation(resourceType, operationType) && + operationType != OperationType.QueryPlan; + } + + internal static bool IsStoredProcedureCrudOperation( + ResourceType resourceType, + OperationType operationType) + { + return resourceType == ResourceType.StoredProcedure && + operationType != Documents.OperationType.ExecuteJavaScript; + } + + internal static bool IsMasterResource(ResourceType resourceType) + { + if (resourceType == ResourceType.Offer || + resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.ClientEncryptionKey || + resourceType == ResourceType.UserDefinedType || + resourceType == ResourceType.Permission || +#if !COSMOSCLIENT + resourceType == ResourceType.Topology || +#endif + resourceType == ResourceType.DatabaseAccount || + resourceType == ResourceType.PartitionKeyRange || + resourceType == ResourceType.Collection || + resourceType == ResourceType.Snapshot || + resourceType == ResourceType.RoleAssignment || + resourceType == ResourceType.RoleDefinition || + resourceType == ResourceType.EncryptionScope || + resourceType == ResourceType.Trigger || + resourceType == ResourceType.UserDefinedFunction) + { + return true; + } + + return false; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ReplicationPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/ReplicationPolicy.cs index 25a50368d0..b2f82062d4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ReplicationPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ReplicationPolicy.cs @@ -1,80 +1,80 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Replication policy. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class ReplicationPolicy : JsonSerializable - { - private const int DefaultMaxReplicaSetSize = 4; - private const int DefaultMinReplicaSetSize = 3; - private const bool DefaultAsyncReplication = false; - - /// - /// Constructor. - /// - public ReplicationPolicy() - { - } - - /// - /// Maximum number of replicas for the partition. - /// - public int MaxReplicaSetSize - { - get - { - return base.GetValue(Constants.Properties.MaxReplicaSetSize, DefaultMaxReplicaSetSize); - } - set - { - base.SetValue(Constants.Properties.MaxReplicaSetSize, value); - } - } - - /// - /// Minimum number of replicas to ensure availability - /// of the partition. - /// - public int MinReplicaSetSize - { - get - { - return base.GetValue(Constants.Properties.MinReplicaSetSize, DefaultMinReplicaSetSize); - } - set - { - base.SetValue(Constants.Properties.MinReplicaSetSize, value); - } - } - - /// - /// Whether or not async replication is enabled. - /// - public bool AsyncReplication - { - get - { - return base.GetValue(Constants.Properties.AsyncReplication, DefaultAsyncReplication); - } - set - { - base.SetValue(Constants.Properties.AsyncReplication, value); - } - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateNonNegativeInteger(Constants.Properties.MinReplicaSetSize, this.MinReplicaSetSize); - Helpers.ValidateNonNegativeInteger(Constants.Properties.MinReplicaSetSize, this.MaxReplicaSetSize); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Replication policy. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class ReplicationPolicy : JsonSerializable + { + private const int DefaultMaxReplicaSetSize = 4; + private const int DefaultMinReplicaSetSize = 3; + private const bool DefaultAsyncReplication = false; + + /// + /// Constructor. + /// + public ReplicationPolicy() + { + } + + /// + /// Maximum number of replicas for the partition. + /// + public int MaxReplicaSetSize + { + get + { + return base.GetValue(Constants.Properties.MaxReplicaSetSize, DefaultMaxReplicaSetSize); + } + set + { + base.SetValue(Constants.Properties.MaxReplicaSetSize, value); + } + } + + /// + /// Minimum number of replicas to ensure availability + /// of the partition. + /// + public int MinReplicaSetSize + { + get + { + return base.GetValue(Constants.Properties.MinReplicaSetSize, DefaultMinReplicaSetSize); + } + set + { + base.SetValue(Constants.Properties.MinReplicaSetSize, value); + } + } + + /// + /// Whether or not async replication is enabled. + /// + public bool AsyncReplication + { + get + { + return base.GetValue(Constants.Properties.AsyncReplication, DefaultAsyncReplication); + } + set + { + base.SetValue(Constants.Properties.AsyncReplication, value); + } + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateNonNegativeInteger(Constants.Properties.MinReplicaSetSize, this.MinReplicaSetSize); + Helpers.ValidateNonNegativeInteger(Constants.Properties.MinReplicaSetSize, this.MaxReplicaSetSize); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestChargeTracker.cs b/Microsoft.Azure.Cosmos/src/direct/RequestChargeTracker.cs index 258d94421d..0e50cf58ec 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestChargeTracker.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestChargeTracker.cs @@ -1,50 +1,50 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Threading; - - internal sealed class RequestChargeTracker - { - /// - /// Total accumulated Charge that would be presented to the client in the next FeedResponse - /// - private long totalRUsNotServedToClient; - - private long totalRUs; - - /// - /// 100 preserves 2 decimal points, 1000 3 and so on. This is because Interlocked operations are not supported for doubles. - /// - private const int numberOfDecimalPointToReserveFactor = 1000; - - public double TotalRequestCharge - { - get - { - return (double)this.totalRUs / numberOfDecimalPointToReserveFactor; - } - } - - public void AddCharge(double ruUsage) - { - Interlocked.Add(ref this.totalRUsNotServedToClient, (long)(ruUsage * numberOfDecimalPointToReserveFactor)); - Interlocked.Add(ref this.totalRUs, (long)(ruUsage * numberOfDecimalPointToReserveFactor)); - } - - /// - /// Gets the Charge incurred so far in a thread-safe manner, and resets the value to zero. The function effectively returns - /// all charges accumulated so far, which will be returned to client as a part of the feedResponse. And the value is reset to 0 - /// so that we can keep on accumulating any new charges incurred by any new backend calls which returened after the current feedreposnse - /// is served to the user. - /// - /// - public double GetAndResetCharge() - { - long rusSoFar = Interlocked.Exchange(ref this.totalRUsNotServedToClient, 0); - return ((double)rusSoFar / numberOfDecimalPointToReserveFactor); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Threading; + + internal sealed class RequestChargeTracker + { + /// + /// Total accumulated Charge that would be presented to the client in the next FeedResponse + /// + private long totalRUsNotServedToClient; + + private long totalRUs; + + /// + /// 100 preserves 2 decimal points, 1000 3 and so on. This is because Interlocked operations are not supported for doubles. + /// + private const int numberOfDecimalPointToReserveFactor = 1000; + + public double TotalRequestCharge + { + get + { + return (double)this.totalRUs / numberOfDecimalPointToReserveFactor; + } + } + + public void AddCharge(double ruUsage) + { + Interlocked.Add(ref this.totalRUsNotServedToClient, (long)(ruUsage * numberOfDecimalPointToReserveFactor)); + Interlocked.Add(ref this.totalRUs, (long)(ruUsage * numberOfDecimalPointToReserveFactor)); + } + + /// + /// Gets the Charge incurred so far in a thread-safe manner, and resets the value to zero. The function effectively returns + /// all charges accumulated so far, which will be returned to client as a part of the feedResponse. And the value is reset to 0 + /// so that we can keep on accumulating any new charges incurred by any new backend calls which returened after the current feedreposnse + /// is served to the user. + /// + /// + public double GetAndResetCharge() + { + long rusSoFar = Interlocked.Exchange(ref this.totalRUsNotServedToClient, 0); + return ((double)rusSoFar / numberOfDecimalPointToReserveFactor); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestEntityTooLargeException.cs b/Microsoft.Azure.Cosmos/src/direct/RequestEntityTooLargeException.cs index a32f62cd3f..df9dd8ec23 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestEntityTooLargeException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestEntityTooLargeException.cs @@ -1,65 +1,65 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class RequestEntityTooLargeException : DocumentClientException - { - public RequestEntityTooLargeException() - : this(RMResources.RequestEntityTooLarge) - { - - } - - public RequestEntityTooLargeException(string message) - : this(message, (Exception)null, null) - { - - } - - public RequestEntityTooLargeException(string message, HttpResponseHeaders httpHeaders, Uri requestUri = null) - : this(message, null, httpHeaders, requestUri) - { - - } - - public RequestEntityTooLargeException(Exception innerException) - : this(RMResources.RequestEntityTooLarge, innerException, null) - { - - } - - public RequestEntityTooLargeException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.RequestEntityTooLarge, requestUri) - { - SetDescription(); - } - - public RequestEntityTooLargeException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.RequestEntityTooLarge, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private RequestEntityTooLargeException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.RequestEntityTooLarge) - { - SetDescription(); - } - -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.RequestEntityTooLarge; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class RequestEntityTooLargeException : DocumentClientException + { + public RequestEntityTooLargeException() + : this(RMResources.RequestEntityTooLarge) + { + + } + + public RequestEntityTooLargeException(string message) + : this(message, (Exception)null, null) + { + + } + + public RequestEntityTooLargeException(string message, HttpResponseHeaders httpHeaders, Uri requestUri = null) + : this(message, null, httpHeaders, requestUri) + { + + } + + public RequestEntityTooLargeException(Exception innerException) + : this(RMResources.RequestEntityTooLarge, innerException, null) + { + + } + + public RequestEntityTooLargeException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.RequestEntityTooLarge, requestUri) + { + SetDescription(); + } + + public RequestEntityTooLargeException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, HttpStatusCode.RequestEntityTooLarge, requestUri) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private RequestEntityTooLargeException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.RequestEntityTooLarge) + { + SetDescription(); + } + +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.RequestEntityTooLarge; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestHelper.cs b/Microsoft.Azure.Cosmos/src/direct/RequestHelper.cs index a154fc0088..40b9833f72 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestHelper.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - - internal static class RequestHelper - { - public static ConsistencyLevel GetConsistencyLevelToUse(IServiceConfigurationReader serviceConfigReader, DocumentServiceRequest request) - { - ConsistencyLevel consistencyLevelToUse = serviceConfigReader.DefaultConsistencyLevel; - - string requestConsistencyLevelHeaderValue = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]; - - if (!string.IsNullOrEmpty(requestConsistencyLevelHeaderValue)) - { - ConsistencyLevel requestConsistencyLevel; - - if (!Enum.TryParse(requestConsistencyLevelHeaderValue, out requestConsistencyLevel)) - { - throw new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - requestConsistencyLevelHeaderValue, - HttpConstants.HttpHeaders.ConsistencyLevel)); - } - - consistencyLevelToUse = requestConsistencyLevel; - } - - return consistencyLevelToUse; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + + internal static class RequestHelper + { + public static ConsistencyLevel GetConsistencyLevelToUse(IServiceConfigurationReader serviceConfigReader, DocumentServiceRequest request) + { + ConsistencyLevel consistencyLevelToUse = serviceConfigReader.DefaultConsistencyLevel; + + string requestConsistencyLevelHeaderValue = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]; + + if (!string.IsNullOrEmpty(requestConsistencyLevelHeaderValue)) + { + ConsistencyLevel requestConsistencyLevel; + + if (!Enum.TryParse(requestConsistencyLevelHeaderValue, out requestConsistencyLevel)) + { + throw new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + requestConsistencyLevelHeaderValue, + HttpConstants.HttpHeaders.ConsistencyLevel)); + } + + consistencyLevelToUse = requestConsistencyLevel; + } + + return consistencyLevelToUse; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs index 4e2072deb4..ef9bba115e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs @@ -1,7855 +1,8020 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RequestNameValueCollection.tt - -namespace Microsoft.Azure.Documents.Collections -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Linq; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents; - - /// - /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RequestNameValueCollection.tt - /// This should be a one to one mapping with RntbdConstants.Request header token properties. - /// This allows the TransportSerialization to directly set the property and avoid the dictionary overhead. - /// If the property does not exists please update the RequestNameValueCollection.tt list to add the new field - /// - internal class RequestNameValueCollection : INameValueCollection - { - private static readonly StringComparer DefaultStringComparer = StringComparer.OrdinalIgnoreCase; - private Dictionary notCommonHeaders; - - // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. - // However, there are a few APIs stil using the NameValueCollection - // - // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create - // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is - // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. - // - // Therefore, we want to keep the NameValueCollection consistent within the RequestHeaders APIs call. In other words, - // once invoked, the RequestHeaders will return the same NameValueCollection. - private NameValueCollection nameValueCollection = null; - - public string A_IM { get; set; } - public string ActivityId { get; set; } - public string AddResourcePropertiesToResponse { get; set; } - public string AllowDocumentReadsInOfflineRegion { get; set; } - public string AllowRestoreParamsUpdate { get; set; } - public string AllowTentativeWrites { get; set; } - public string Authorization { get; set; } - public string BinaryId { get; set; } - public string BinaryPassthroughRequest { get; set; } - public string BindReplicaDirective { get; set; } - public string BuilderClientIdentifier { get; set; } - public string CanCharge { get; set; } - public string CanOfferReplaceComplete { get; set; } - public string CanThrottle { get; set; } - public string ChangeFeedStartFullFidelityIfNoneMatch { get; set; } - public string ChangeFeedWireFormatVersion { get; set; } - public string ClientIpAddress { get; set; } - public string ClientRetryAttemptCount { get; set; } - public string CollectionChildResourceContentLimitInKB { get; set; } - public string CollectionChildResourceNameLimitInBytes { get; set; } - public string CollectionPartitionIndex { get; set; } - public string CollectionRemoteStorageSecurityIdentifier { get; set; } - public string CollectionRid { get; set; } - public string CollectionServiceIndex { get; set; } - public string CollectionTruncate { get; set; } - public string ConsistencyLevel { get; set; } - public string ContentSerializationFormat { get; set; } - public string Continuation { get; set; } - public string CorrelatedActivityId { get; set; } - public string DisableRUPerMinuteUsage { get; set; } - public string EffectivePartitionKey { get; set; } - public string EmitVerboseTracesInQuery { get; set; } - public string EnableConflictResolutionPolicyUpdate { get; set; } - public string EnableCrossPartitionQuery { get; set; } - public string EnableDynamicRidRangeAllocation { get; set; } - public string EnableLogging { get; set; } - public string EnableLowPrecisionOrderBy { get; set; } - public string EnableScanInQuery { get; set; } - public string EndEpk { get; set; } - public string EndId { get; set; } - public string EntityId { get; set; } - public string EnumerationDirection { get; set; } - public string ExcludeSystemProperties { get; set; } - public string FanoutOperationState { get; set; } - public string FilterBySchemaResourceId { get; set; } - public string ForceDatabaseAccountUpdate { get; set; } - public string ForceQueryScan { get; set; } - public string ForceSideBySideIndexMigration { get; set; } - public string GatewaySignature { get; set; } - public string GetAllPartitionKeyStatistics { get; set; } - public string HighPriorityForcedBackup { get; set; } - public string HttpDate { get; set; } - public string IfMatch { get; set; } - public string IfModifiedSince { get; set; } - public string IfNoneMatch { get; set; } - public string IgnoreSystemLoweringMaxThroughput { get; set; } - public string IncludePhysicalPartitionThroughputInfo { get; set; } - public string IncludeTentativeWrites { get; set; } - public string IndexingDirective { get; set; } - public string IntendedCollectionRid { get; set; } - public string IsAutoScaleRequest { get; set; } - public string IsBatchAtomic { get; set; } - public string IsBatchOrdered { get; set; } - public string IsCassandraAlterTypeRequest { get; set; } - public string IsClientEncrypted { get; set; } - public string IsContinuationExpected { get; set; } - public string IsFanoutRequest { get; set; } - public string IsInternalServerlessRequest { get; set; } - public string IsMaterializedViewBuild { get; set; } - public string IsMaterializedViewSourceSchemaReplaceBatchRequest { get; set; } - public string IsMigratedFixedCollection { get; set; } - public string IsOfferStorageRefreshRequest { get; set; } - public string IsReadOnlyScript { get; set; } - public string IsRequestNotAuthorized { get; set; } - public string IsRetriedWriteRequest { get; set; } - public string IsRUPerGBEnforcementRequest { get; set; } - public string IsServerlessStorageRefreshRequest { get; set; } - public string IsThroughputCapRequest { get; set; } - public string IsUserRequest { get; set; } - public string MaxPollingIntervalMilliseconds { get; set; } - public string MergeCheckPointGLSN { get; set; } - public string MergeStaticId { get; set; } - public string MigrateCollectionDirective { get; set; } - public string MigrateOfferToAutopilot { get; set; } - public string MigrateOfferToManualThroughput { get; set; } - public string NoRetryOn449StatusCode { get; set; } - public string OfferReplaceRURedistribution { get; set; } - public string OptimisticDirectExecute { get; set; } - public string PageSize { get; set; } - public string ParallelizeCrossPartitionQuery { get; set; } - public string PartitionCount { get; set; } - public string PartitionKey { get; set; } - public string PartitionKeyRangeId { get; set; } - public string PartitionResourceFilter { get; set; } - public string PopulateAnalyticalMigrationProgress { get; set; } - public string PopulateByokEncryptionProgress { get; set; } - public string PopulateCapacityType { get; set; } - public string PopulateCollectionThroughputInfo { get; set; } - public string PopulateCurrentPartitionThroughputInfo { get; set; } - public string PopulateHighestTentativeWriteLLSN { get; set; } - public string PopulateIndexMetrics { get; set; } - public string PopulateIndexMetricsV2 { get; set; } - public string PopulateLogStoreInfo { get; set; } - public string PopulateMinGLSNForDocumentOperations { get; set; } - public string PopulateOldestActiveSchemaId { get; set; } - public string PopulatePartitionStatistics { get; set; } - public string PopulateQueryMetrics { get; set; } - public string PopulateQuotaInfo { get; set; } - public string PopulateResourceCount { get; set; } - public string PopulateUnflushedMergeEntryCount { get; set; } - public string PopulateUniqueIndexReIndexProgress { get; set; } - public string PostTriggerExclude { get; set; } - public string PostTriggerInclude { get; set; } - public string Prefer { get; set; } - public string PreserveFullContent { get; set; } - public string PreTriggerExclude { get; set; } - public string PreTriggerInclude { get; set; } - public string PrimaryMasterKey { get; set; } - public string PrimaryReadonlyKey { get; set; } - public string PriorityLevel { get; set; } - public string ProfileRequest { get; set; } - public string PruneCollectionSchemas { get; set; } - public string QueryVersion { get; set; } - public string RbacAction { get; set; } - public string RbacResource { get; set; } - public string RbacUserId { get; set; } - public string ReadFeedKeyType { get; set; } - public string RemainingTimeInMsOnClientRequest { get; set; } - public string RemoteStorageType { get; set; } - public string RequestedCollectionType { get; set; } - public string ResourceId { get; set; } - public string ResourceSchemaName { get; set; } - public string ResourceTokenExpiry { get; set; } - public string ResourceTypes { get; set; } - public string ResponseContinuationTokenLimitInKB { get; set; } - public string RestoreMetadataFilter { get; set; } - public string RestoreParams { get; set; } - public string RetriableWriteRequestId { get; set; } - public string RetriableWriteRequestStartTimestamp { get; set; } - public string SchemaHash { get; set; } - public string SchemaId { get; set; } - public string SchemaOwnerRid { get; set; } - public string SDKSupportedCapabilities { get; set; } - public string SecondaryMasterKey { get; set; } - public string SecondaryReadonlyKey { get; set; } - public string SessionToken { get; set; } - public string SetMasterResourcesDeletionPending { get; set; } - public string ShareThroughput { get; set; } - public string ShouldBatchContinueOnError { get; set; } - public string ShouldReturnCurrentServerDateTime { get; set; } - public string SkipAdjustThroughputFractionsForOfferReplace { get; set; } - public string SkipRefreshDatabaseAccountConfigs { get; set; } - public string SourceCollectionIfMatch { get; set; } - public string SqlQueryForPartitionKeyExtraction { get; set; } - public string StartEpk { get; set; } - public string StartId { get; set; } - public string SupportedQueryFeatures { get; set; } - public string SupportedSerializationFormats { get; set; } - public string SupportSpatialLegacyCoordinates { get; set; } - public string SystemDocumentType { get; set; } - public string SystemRestoreOperation { get; set; } - public string TargetGlobalCommittedLsn { get; set; } - public string TargetLsn { get; set; } - public string TimeToLiveInSeconds { get; set; } - public string TraceParent { get; set; } - public string TraceState { get; set; } - public string TransactionCommit { get; set; } - public string TransactionFirstRequest { get; set; } - public string TransactionId { get; set; } - public string TransportRequestID { get; set; } - public string TruncateMergeLogRequest { get; set; } - public string UniqueIndexNameEncodingMode { get; set; } - public string UniqueIndexReIndexingState { get; set; } - public string UpdateMaxThroughputEverProvisioned { get; set; } - public string UpdateOfferStateToPending { get; set; } - public string UpdateOfferStateToRestorePending { get; set; } - public string UseArchivalPartition { get; set; } - public string UsePolygonsSmallerThanAHemisphere { get; set; } - public string UseSystemBudget { get; set; } - public string UseUserBackgroundBudget { get; set; } - public string Version { get; set; } - public string XDate { get; set; } - - public RequestNameValueCollection() - { - } - - public RequestNameValueCollection(INameValueCollection nameValueCollection) - { - foreach (string key in nameValueCollection) - { - this.UpdateHelper(key, value: nameValueCollection.Get(key), throwIfAlreadyExists: false, ignoreNotCommonHeaders: false); - } - } - - public RequestNameValueCollection(IDictionary requestHeaders) - { - foreach (KeyValuePair keyValuePair in requestHeaders) - { - this.UpdateHelper(key: keyValuePair.Key, value: keyValuePair.Value, throwIfAlreadyExists: false, ignoreNotCommonHeaders: false); - } - } - - /// - /// Only process known headers. - /// - /// - /// Non thread safe. Does not support requestHeaders modification while running this method. - /// - public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnownHeadersOnly(IDictionary requestHeaders) - { - RequestNameValueCollection requestNameValueCollection = new RequestNameValueCollection(); - foreach (KeyValuePair keyValue in requestHeaders) - { - requestNameValueCollection.UpdateHelper(keyValue.Key, value: keyValue.Value, throwIfAlreadyExists: false, ignoreNotCommonHeaders: true); - } - - return requestNameValueCollection; - } - - /// - /// Only process known headers. Ignores nameValueCollection changes by switching to per field assignment if InvalidOperationException happens while iterating over the keys. - /// - public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnownHeadersOnly(INameValueCollection nameValueCollection) - { - RequestNameValueCollection requestNameValueCollection = new RequestNameValueCollection(); - try - { - foreach (string key in nameValueCollection) - { - requestNameValueCollection.UpdateHelper(key, value: nameValueCollection.Get(key), throwIfAlreadyExists: false, ignoreNotCommonHeaders: true); - } - } - catch (InvalidOperationException e) - { - DefaultTrace.TraceWarning($"{nameof(RequestNameValueCollection)} Failed to iterate over nameValueCollection headers in a non thread safe manner: {e.Message}. Switching to the per property approach."); - - // Lookup by value because request headers can be used concurrently - // It will cause an exception of looping over the dictionary and a value is modified - requestNameValueCollection.ResourceId = nameValueCollection[WFConstants.BackendHeaders.ResourceId]; - requestNameValueCollection.Authorization = nameValueCollection[HttpConstants.HttpHeaders.Authorization]; - requestNameValueCollection.HttpDate = nameValueCollection[HttpConstants.HttpHeaders.HttpDate]; - requestNameValueCollection.XDate = nameValueCollection[HttpConstants.HttpHeaders.XDate]; - requestNameValueCollection.PageSize = nameValueCollection[HttpConstants.HttpHeaders.PageSize]; - requestNameValueCollection.SessionToken = nameValueCollection[HttpConstants.HttpHeaders.SessionToken]; - requestNameValueCollection.Continuation = nameValueCollection[HttpConstants.HttpHeaders.Continuation]; - requestNameValueCollection.IndexingDirective = nameValueCollection[HttpConstants.HttpHeaders.IndexingDirective]; - requestNameValueCollection.IfNoneMatch = nameValueCollection[HttpConstants.HttpHeaders.IfNoneMatch]; - requestNameValueCollection.PreTriggerInclude = nameValueCollection[HttpConstants.HttpHeaders.PreTriggerInclude]; - requestNameValueCollection.PostTriggerInclude = nameValueCollection[HttpConstants.HttpHeaders.PostTriggerInclude]; - requestNameValueCollection.IsFanoutRequest = nameValueCollection[WFConstants.BackendHeaders.IsFanoutRequest]; - requestNameValueCollection.CollectionPartitionIndex = nameValueCollection[WFConstants.BackendHeaders.CollectionPartitionIndex]; - requestNameValueCollection.CollectionServiceIndex = nameValueCollection[WFConstants.BackendHeaders.CollectionServiceIndex]; - requestNameValueCollection.PreTriggerExclude = nameValueCollection[HttpConstants.HttpHeaders.PreTriggerExclude]; - requestNameValueCollection.PostTriggerExclude = nameValueCollection[HttpConstants.HttpHeaders.PostTriggerExclude]; - requestNameValueCollection.ConsistencyLevel = nameValueCollection[HttpConstants.HttpHeaders.ConsistencyLevel]; - requestNameValueCollection.EntityId = nameValueCollection[WFConstants.BackendHeaders.EntityId]; - requestNameValueCollection.ResourceSchemaName = nameValueCollection[WFConstants.BackendHeaders.ResourceSchemaName]; - requestNameValueCollection.ResourceTokenExpiry = nameValueCollection[HttpConstants.HttpHeaders.ResourceTokenExpiry]; - requestNameValueCollection.EnableScanInQuery = nameValueCollection[HttpConstants.HttpHeaders.EnableScanInQuery]; - requestNameValueCollection.EmitVerboseTracesInQuery = nameValueCollection[HttpConstants.HttpHeaders.EmitVerboseTracesInQuery]; - requestNameValueCollection.BindReplicaDirective = nameValueCollection[WFConstants.BackendHeaders.BindReplicaDirective]; - requestNameValueCollection.PrimaryMasterKey = nameValueCollection[WFConstants.BackendHeaders.PrimaryMasterKey]; - requestNameValueCollection.SecondaryMasterKey = nameValueCollection[WFConstants.BackendHeaders.SecondaryMasterKey]; - requestNameValueCollection.PrimaryReadonlyKey = nameValueCollection[WFConstants.BackendHeaders.PrimaryReadonlyKey]; - requestNameValueCollection.SecondaryReadonlyKey = nameValueCollection[WFConstants.BackendHeaders.SecondaryReadonlyKey]; - requestNameValueCollection.ProfileRequest = nameValueCollection[HttpConstants.HttpHeaders.ProfileRequest]; - requestNameValueCollection.EnableLowPrecisionOrderBy = nameValueCollection[HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy]; - requestNameValueCollection.Version = nameValueCollection[HttpConstants.HttpHeaders.Version]; - requestNameValueCollection.CanCharge = nameValueCollection[HttpConstants.HttpHeaders.CanCharge]; - requestNameValueCollection.CanThrottle = nameValueCollection[HttpConstants.HttpHeaders.CanThrottle]; - requestNameValueCollection.PartitionKey = nameValueCollection[HttpConstants.HttpHeaders.PartitionKey]; - requestNameValueCollection.PartitionKeyRangeId = nameValueCollection[HttpConstants.HttpHeaders.PartitionKeyRangeId]; - requestNameValueCollection.MigrateCollectionDirective = nameValueCollection[HttpConstants.HttpHeaders.MigrateCollectionDirective]; - requestNameValueCollection.SupportSpatialLegacyCoordinates = nameValueCollection[HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates]; - requestNameValueCollection.PartitionCount = nameValueCollection[HttpConstants.HttpHeaders.PartitionCount]; - requestNameValueCollection.CollectionRid = nameValueCollection[WFConstants.BackendHeaders.CollectionRid]; - requestNameValueCollection.FilterBySchemaResourceId = nameValueCollection[HttpConstants.HttpHeaders.FilterBySchemaResourceId]; - requestNameValueCollection.UsePolygonsSmallerThanAHemisphere = nameValueCollection[HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere]; - requestNameValueCollection.GatewaySignature = nameValueCollection[HttpConstants.HttpHeaders.GatewaySignature]; - requestNameValueCollection.EnableLogging = nameValueCollection[HttpConstants.HttpHeaders.EnableLogging]; - requestNameValueCollection.A_IM = nameValueCollection[HttpConstants.HttpHeaders.A_IM]; - requestNameValueCollection.PopulateQuotaInfo = nameValueCollection[HttpConstants.HttpHeaders.PopulateQuotaInfo]; - requestNameValueCollection.DisableRUPerMinuteUsage = nameValueCollection[HttpConstants.HttpHeaders.DisableRUPerMinuteUsage]; - requestNameValueCollection.PopulateQueryMetrics = nameValueCollection[HttpConstants.HttpHeaders.PopulateQueryMetrics]; - requestNameValueCollection.ResponseContinuationTokenLimitInKB = nameValueCollection[HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB]; - requestNameValueCollection.PopulatePartitionStatistics = nameValueCollection[HttpConstants.HttpHeaders.PopulatePartitionStatistics]; - requestNameValueCollection.RemoteStorageType = nameValueCollection[WFConstants.BackendHeaders.RemoteStorageType]; - requestNameValueCollection.CollectionRemoteStorageSecurityIdentifier = nameValueCollection[HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier]; - requestNameValueCollection.IfModifiedSince = nameValueCollection[HttpConstants.HttpHeaders.IfModifiedSince]; - requestNameValueCollection.PopulateCollectionThroughputInfo = nameValueCollection[HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo]; - requestNameValueCollection.RemainingTimeInMsOnClientRequest = nameValueCollection[HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest]; - requestNameValueCollection.ClientRetryAttemptCount = nameValueCollection[HttpConstants.HttpHeaders.ClientRetryAttemptCount]; - requestNameValueCollection.TargetLsn = nameValueCollection[HttpConstants.HttpHeaders.TargetLsn]; - requestNameValueCollection.TargetGlobalCommittedLsn = nameValueCollection[HttpConstants.HttpHeaders.TargetGlobalCommittedLsn]; - requestNameValueCollection.TransportRequestID = nameValueCollection[HttpConstants.HttpHeaders.TransportRequestID]; - requestNameValueCollection.RestoreMetadataFilter = nameValueCollection[HttpConstants.HttpHeaders.RestoreMetadataFilter]; - requestNameValueCollection.RestoreParams = nameValueCollection[WFConstants.BackendHeaders.RestoreParams]; - requestNameValueCollection.ShareThroughput = nameValueCollection[WFConstants.BackendHeaders.ShareThroughput]; - requestNameValueCollection.PartitionResourceFilter = nameValueCollection[WFConstants.BackendHeaders.PartitionResourceFilter]; - requestNameValueCollection.IsReadOnlyScript = nameValueCollection[HttpConstants.HttpHeaders.IsReadOnlyScript]; - requestNameValueCollection.IsAutoScaleRequest = nameValueCollection[HttpConstants.HttpHeaders.IsAutoScaleRequest]; - requestNameValueCollection.ForceQueryScan = nameValueCollection[HttpConstants.HttpHeaders.ForceQueryScan]; - requestNameValueCollection.CanOfferReplaceComplete = nameValueCollection[HttpConstants.HttpHeaders.CanOfferReplaceComplete]; - requestNameValueCollection.ExcludeSystemProperties = nameValueCollection[WFConstants.BackendHeaders.ExcludeSystemProperties]; - requestNameValueCollection.BinaryId = nameValueCollection[WFConstants.BackendHeaders.BinaryId]; - requestNameValueCollection.TimeToLiveInSeconds = nameValueCollection[WFConstants.BackendHeaders.TimeToLiveInSeconds]; - requestNameValueCollection.EffectivePartitionKey = nameValueCollection[WFConstants.BackendHeaders.EffectivePartitionKey]; - requestNameValueCollection.BinaryPassthroughRequest = nameValueCollection[WFConstants.BackendHeaders.BinaryPassthroughRequest]; - requestNameValueCollection.EnableDynamicRidRangeAllocation = nameValueCollection[WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation]; - requestNameValueCollection.EnumerationDirection = nameValueCollection[HttpConstants.HttpHeaders.EnumerationDirection]; - requestNameValueCollection.StartId = nameValueCollection[HttpConstants.HttpHeaders.StartId]; - requestNameValueCollection.EndId = nameValueCollection[HttpConstants.HttpHeaders.EndId]; - requestNameValueCollection.FanoutOperationState = nameValueCollection[WFConstants.BackendHeaders.FanoutOperationState]; - requestNameValueCollection.StartEpk = nameValueCollection[HttpConstants.HttpHeaders.StartEpk]; - requestNameValueCollection.EndEpk = nameValueCollection[HttpConstants.HttpHeaders.EndEpk]; - requestNameValueCollection.ReadFeedKeyType = nameValueCollection[HttpConstants.HttpHeaders.ReadFeedKeyType]; - requestNameValueCollection.ContentSerializationFormat = nameValueCollection[HttpConstants.HttpHeaders.ContentSerializationFormat]; - requestNameValueCollection.AllowTentativeWrites = nameValueCollection[HttpConstants.HttpHeaders.AllowTentativeWrites]; - requestNameValueCollection.IsUserRequest = nameValueCollection[WFConstants.BackendHeaders.IsUserRequest]; - requestNameValueCollection.PreserveFullContent = nameValueCollection[HttpConstants.HttpHeaders.PreserveFullContent]; - requestNameValueCollection.IncludeTentativeWrites = nameValueCollection[HttpConstants.HttpHeaders.IncludeTentativeWrites]; - requestNameValueCollection.PopulateResourceCount = nameValueCollection[HttpConstants.HttpHeaders.PopulateResourceCount]; - requestNameValueCollection.MergeStaticId = nameValueCollection[HttpConstants.HttpHeaders.MergeStaticId]; - requestNameValueCollection.IsBatchAtomic = nameValueCollection[HttpConstants.HttpHeaders.IsBatchAtomic]; - requestNameValueCollection.ShouldBatchContinueOnError = nameValueCollection[HttpConstants.HttpHeaders.ShouldBatchContinueOnError]; - requestNameValueCollection.IsBatchOrdered = nameValueCollection[HttpConstants.HttpHeaders.IsBatchOrdered]; - requestNameValueCollection.SchemaOwnerRid = nameValueCollection[WFConstants.BackendHeaders.SchemaOwnerRid]; - requestNameValueCollection.SchemaHash = nameValueCollection[WFConstants.BackendHeaders.SchemaHash]; - requestNameValueCollection.IsRUPerGBEnforcementRequest = nameValueCollection[HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest]; - requestNameValueCollection.MaxPollingIntervalMilliseconds = nameValueCollection[HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds]; - requestNameValueCollection.PopulateLogStoreInfo = nameValueCollection[WFConstants.BackendHeaders.PopulateLogStoreInfo]; - requestNameValueCollection.GetAllPartitionKeyStatistics = nameValueCollection[HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics]; - requestNameValueCollection.ForceSideBySideIndexMigration = nameValueCollection[HttpConstants.HttpHeaders.ForceSideBySideIndexMigration]; - requestNameValueCollection.CollectionChildResourceNameLimitInBytes = nameValueCollection[WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes]; - requestNameValueCollection.CollectionChildResourceContentLimitInKB = nameValueCollection[WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB]; - requestNameValueCollection.MergeCheckPointGLSN = nameValueCollection[WFConstants.BackendHeaders.MergeCheckPointGLSN]; - requestNameValueCollection.Prefer = nameValueCollection[HttpConstants.HttpHeaders.Prefer]; - requestNameValueCollection.UniqueIndexNameEncodingMode = nameValueCollection[WFConstants.BackendHeaders.UniqueIndexNameEncodingMode]; - requestNameValueCollection.PopulateUnflushedMergeEntryCount = nameValueCollection[WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount]; - requestNameValueCollection.MigrateOfferToManualThroughput = nameValueCollection[HttpConstants.HttpHeaders.MigrateOfferToManualThroughput]; - requestNameValueCollection.MigrateOfferToAutopilot = nameValueCollection[HttpConstants.HttpHeaders.MigrateOfferToAutopilot]; - requestNameValueCollection.IsClientEncrypted = nameValueCollection[HttpConstants.HttpHeaders.IsClientEncrypted]; - requestNameValueCollection.SystemDocumentType = nameValueCollection[HttpConstants.HttpHeaders.SystemDocumentType]; - requestNameValueCollection.IsOfferStorageRefreshRequest = nameValueCollection[HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest]; - requestNameValueCollection.ResourceTypes = nameValueCollection[WFConstants.BackendHeaders.ResourceTypes]; - requestNameValueCollection.TransactionId = nameValueCollection[WFConstants.BackendHeaders.TransactionId]; - requestNameValueCollection.TransactionFirstRequest = nameValueCollection[WFConstants.BackendHeaders.TransactionFirstRequest]; - requestNameValueCollection.TransactionCommit = nameValueCollection[WFConstants.BackendHeaders.TransactionCommit]; - requestNameValueCollection.UpdateMaxThroughputEverProvisioned = nameValueCollection[HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned]; - requestNameValueCollection.UniqueIndexReIndexingState = nameValueCollection[WFConstants.BackendHeaders.UniqueIndexReIndexingState]; - requestNameValueCollection.UseSystemBudget = nameValueCollection[WFConstants.BackendHeaders.UseSystemBudget]; - requestNameValueCollection.IgnoreSystemLoweringMaxThroughput = nameValueCollection[HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput]; - requestNameValueCollection.TruncateMergeLogRequest = nameValueCollection[HttpConstants.HttpHeaders.TruncateMergeLogRequest]; - requestNameValueCollection.RetriableWriteRequestId = nameValueCollection[WFConstants.BackendHeaders.RetriableWriteRequestId]; - requestNameValueCollection.IsRetriedWriteRequest = nameValueCollection[WFConstants.BackendHeaders.IsRetriedWriteRequest]; - requestNameValueCollection.RetriableWriteRequestStartTimestamp = nameValueCollection[WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp]; - requestNameValueCollection.AddResourcePropertiesToResponse = nameValueCollection[WFConstants.BackendHeaders.AddResourcePropertiesToResponse]; - requestNameValueCollection.ChangeFeedStartFullFidelityIfNoneMatch = nameValueCollection[HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch]; - requestNameValueCollection.SystemRestoreOperation = nameValueCollection[HttpConstants.HttpHeaders.SystemRestoreOperation]; - requestNameValueCollection.SkipRefreshDatabaseAccountConfigs = nameValueCollection[WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs]; - requestNameValueCollection.IntendedCollectionRid = nameValueCollection[WFConstants.BackendHeaders.IntendedCollectionRid]; - requestNameValueCollection.UseArchivalPartition = nameValueCollection[HttpConstants.HttpHeaders.UseArchivalPartition]; - requestNameValueCollection.PopulateUniqueIndexReIndexProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress]; - requestNameValueCollection.SchemaId = nameValueCollection[WFConstants.BackendHeaders.SchemaId]; - requestNameValueCollection.CollectionTruncate = nameValueCollection[HttpConstants.HttpHeaders.CollectionTruncate]; - requestNameValueCollection.SDKSupportedCapabilities = nameValueCollection[HttpConstants.HttpHeaders.SDKSupportedCapabilities]; - requestNameValueCollection.IsMaterializedViewBuild = nameValueCollection[HttpConstants.HttpHeaders.IsMaterializedViewBuild]; - requestNameValueCollection.BuilderClientIdentifier = nameValueCollection[HttpConstants.HttpHeaders.BuilderClientIdentifier]; - requestNameValueCollection.SourceCollectionIfMatch = nameValueCollection[WFConstants.BackendHeaders.SourceCollectionIfMatch]; - requestNameValueCollection.RequestedCollectionType = nameValueCollection[WFConstants.BackendHeaders.RequestedCollectionType]; - requestNameValueCollection.PopulateIndexMetrics = nameValueCollection[HttpConstants.HttpHeaders.PopulateIndexMetrics]; - requestNameValueCollection.PopulateAnalyticalMigrationProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress]; - requestNameValueCollection.ShouldReturnCurrentServerDateTime = nameValueCollection[HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime]; - requestNameValueCollection.RbacUserId = nameValueCollection[HttpConstants.HttpHeaders.RbacUserId]; - requestNameValueCollection.RbacAction = nameValueCollection[HttpConstants.HttpHeaders.RbacAction]; - requestNameValueCollection.RbacResource = nameValueCollection[HttpConstants.HttpHeaders.RbacResource]; - requestNameValueCollection.CorrelatedActivityId = nameValueCollection[HttpConstants.HttpHeaders.CorrelatedActivityId]; - requestNameValueCollection.IsThroughputCapRequest = nameValueCollection[HttpConstants.HttpHeaders.IsThroughputCapRequest]; - requestNameValueCollection.ChangeFeedWireFormatVersion = nameValueCollection[HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion]; - requestNameValueCollection.PopulateByokEncryptionProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateByokEncryptionProgress]; - requestNameValueCollection.UseUserBackgroundBudget = nameValueCollection[WFConstants.BackendHeaders.UseUserBackgroundBudget]; - requestNameValueCollection.IncludePhysicalPartitionThroughputInfo = nameValueCollection[HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo]; - requestNameValueCollection.IsServerlessStorageRefreshRequest = nameValueCollection[HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest]; - requestNameValueCollection.UpdateOfferStateToPending = nameValueCollection[HttpConstants.HttpHeaders.UpdateOfferStateToPending]; - requestNameValueCollection.PopulateOldestActiveSchemaId = nameValueCollection[HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId]; - requestNameValueCollection.IsInternalServerlessRequest = nameValueCollection[HttpConstants.HttpHeaders.IsInternalServerlessRequest]; - requestNameValueCollection.OfferReplaceRURedistribution = nameValueCollection[HttpConstants.HttpHeaders.OfferReplaceRURedistribution]; - requestNameValueCollection.IsCassandraAlterTypeRequest = nameValueCollection[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest]; - requestNameValueCollection.IsMaterializedViewSourceSchemaReplaceBatchRequest = nameValueCollection[HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest]; - requestNameValueCollection.ForceDatabaseAccountUpdate = nameValueCollection[HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate]; - requestNameValueCollection.PriorityLevel = nameValueCollection[HttpConstants.HttpHeaders.PriorityLevel]; - requestNameValueCollection.AllowRestoreParamsUpdate = nameValueCollection[HttpConstants.HttpHeaders.AllowRestoreParamsUpdate]; - requestNameValueCollection.PruneCollectionSchemas = nameValueCollection[HttpConstants.HttpHeaders.PruneCollectionSchemas]; - requestNameValueCollection.PopulateIndexMetricsV2 = nameValueCollection[HttpConstants.HttpHeaders.PopulateIndexMetricsV2]; - requestNameValueCollection.IsMigratedFixedCollection = nameValueCollection[HttpConstants.HttpHeaders.IsMigratedFixedCollection]; - requestNameValueCollection.SupportedSerializationFormats = nameValueCollection[HttpConstants.HttpHeaders.SupportedSerializationFormats]; - requestNameValueCollection.UpdateOfferStateToRestorePending = nameValueCollection[HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending]; - requestNameValueCollection.SetMasterResourcesDeletionPending = nameValueCollection[HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending]; - requestNameValueCollection.HighPriorityForcedBackup = nameValueCollection[HttpConstants.HttpHeaders.HighPriorityForcedBackup]; - requestNameValueCollection.OptimisticDirectExecute = nameValueCollection[HttpConstants.HttpHeaders.OptimisticDirectExecute]; - requestNameValueCollection.PopulateMinGLSNForDocumentOperations = nameValueCollection[WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations]; - requestNameValueCollection.PopulateHighestTentativeWriteLLSN = nameValueCollection[WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN]; - requestNameValueCollection.PopulateCapacityType = nameValueCollection[WFConstants.BackendHeaders.PopulateCapacityType]; - requestNameValueCollection.TraceParent = nameValueCollection[HttpConstants.HttpHeaders.TraceParent]; - requestNameValueCollection.TraceState = nameValueCollection[HttpConstants.HttpHeaders.TraceState]; - requestNameValueCollection.EnableConflictResolutionPolicyUpdate = nameValueCollection[HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate]; - requestNameValueCollection.ClientIpAddress = nameValueCollection[WFConstants.BackendHeaders.ClientIpAddress]; - requestNameValueCollection.IsRequestNotAuthorized = nameValueCollection[WFConstants.BackendHeaders.IsRequestNotAuthorized]; - requestNameValueCollection.PopulateCurrentPartitionThroughputInfo = nameValueCollection[WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo]; - requestNameValueCollection.IfMatch = nameValueCollection[HttpConstants.HttpHeaders.IfMatch]; - requestNameValueCollection.NoRetryOn449StatusCode = nameValueCollection[HttpConstants.HttpHeaders.NoRetryOn449StatusCode]; - requestNameValueCollection.SkipAdjustThroughputFractionsForOfferReplace = nameValueCollection[HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace]; - requestNameValueCollection.SqlQueryForPartitionKeyExtraction = nameValueCollection[HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction]; - requestNameValueCollection.EnableCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.EnableCrossPartitionQuery]; - requestNameValueCollection.IsContinuationExpected = nameValueCollection[HttpConstants.HttpHeaders.IsContinuationExpected]; - requestNameValueCollection.ParallelizeCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery]; - requestNameValueCollection.SupportedQueryFeatures = nameValueCollection[HttpConstants.HttpHeaders.SupportedQueryFeatures]; - requestNameValueCollection.QueryVersion = nameValueCollection[HttpConstants.HttpHeaders.QueryVersion]; - requestNameValueCollection.ActivityId = nameValueCollection[HttpConstants.HttpHeaders.ActivityId]; - } - - return requestNameValueCollection; - } - - public string this[string key] - { - get => this.Get(key); - set => this.Set(key, value); - } - - public void Add(INameValueCollection collection) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - foreach (string key in collection.Keys()) - { - this.Set(key, collection[key]); - } - } - - public string[] AllKeys() - { - return this.Keys().ToArray(); - } - - public void Clear() - { - if (this.notCommonHeaders != null) - { - this.notCommonHeaders.Clear(); - } - - this.A_IM = null; - this.ActivityId = null; - this.AddResourcePropertiesToResponse = null; - this.AllowDocumentReadsInOfflineRegion = null; - this.AllowRestoreParamsUpdate = null; - this.AllowTentativeWrites = null; - this.Authorization = null; - this.BinaryId = null; - this.BinaryPassthroughRequest = null; - this.BindReplicaDirective = null; - this.BuilderClientIdentifier = null; - this.CanCharge = null; - this.CanOfferReplaceComplete = null; - this.CanThrottle = null; - this.ChangeFeedStartFullFidelityIfNoneMatch = null; - this.ChangeFeedWireFormatVersion = null; - this.ClientIpAddress = null; - this.ClientRetryAttemptCount = null; - this.CollectionChildResourceContentLimitInKB = null; - this.CollectionChildResourceNameLimitInBytes = null; - this.CollectionPartitionIndex = null; - this.CollectionRemoteStorageSecurityIdentifier = null; - this.CollectionRid = null; - this.CollectionServiceIndex = null; - this.CollectionTruncate = null; - this.ConsistencyLevel = null; - this.ContentSerializationFormat = null; - this.Continuation = null; - this.CorrelatedActivityId = null; - this.DisableRUPerMinuteUsage = null; - this.EffectivePartitionKey = null; - this.EmitVerboseTracesInQuery = null; - this.EnableConflictResolutionPolicyUpdate = null; - this.EnableCrossPartitionQuery = null; - this.EnableDynamicRidRangeAllocation = null; - this.EnableLogging = null; - this.EnableLowPrecisionOrderBy = null; - this.EnableScanInQuery = null; - this.EndEpk = null; - this.EndId = null; - this.EntityId = null; - this.EnumerationDirection = null; - this.ExcludeSystemProperties = null; - this.FanoutOperationState = null; - this.FilterBySchemaResourceId = null; - this.ForceDatabaseAccountUpdate = null; - this.ForceQueryScan = null; - this.ForceSideBySideIndexMigration = null; - this.GatewaySignature = null; - this.GetAllPartitionKeyStatistics = null; - this.HighPriorityForcedBackup = null; - this.HttpDate = null; - this.IfMatch = null; - this.IfModifiedSince = null; - this.IfNoneMatch = null; - this.IgnoreSystemLoweringMaxThroughput = null; - this.IncludePhysicalPartitionThroughputInfo = null; - this.IncludeTentativeWrites = null; - this.IndexingDirective = null; - this.IntendedCollectionRid = null; - this.IsAutoScaleRequest = null; - this.IsBatchAtomic = null; - this.IsBatchOrdered = null; - this.IsCassandraAlterTypeRequest = null; - this.IsClientEncrypted = null; - this.IsContinuationExpected = null; - this.IsFanoutRequest = null; - this.IsInternalServerlessRequest = null; - this.IsMaterializedViewBuild = null; - this.IsMaterializedViewSourceSchemaReplaceBatchRequest = null; - this.IsMigratedFixedCollection = null; - this.IsOfferStorageRefreshRequest = null; - this.IsReadOnlyScript = null; - this.IsRequestNotAuthorized = null; - this.IsRetriedWriteRequest = null; - this.IsRUPerGBEnforcementRequest = null; - this.IsServerlessStorageRefreshRequest = null; - this.IsThroughputCapRequest = null; - this.IsUserRequest = null; - this.MaxPollingIntervalMilliseconds = null; - this.MergeCheckPointGLSN = null; - this.MergeStaticId = null; - this.MigrateCollectionDirective = null; - this.MigrateOfferToAutopilot = null; - this.MigrateOfferToManualThroughput = null; - this.NoRetryOn449StatusCode = null; - this.OfferReplaceRURedistribution = null; - this.OptimisticDirectExecute = null; - this.PageSize = null; - this.ParallelizeCrossPartitionQuery = null; - this.PartitionCount = null; - this.PartitionKey = null; - this.PartitionKeyRangeId = null; - this.PartitionResourceFilter = null; - this.PopulateAnalyticalMigrationProgress = null; - this.PopulateByokEncryptionProgress = null; - this.PopulateCapacityType = null; - this.PopulateCollectionThroughputInfo = null; - this.PopulateCurrentPartitionThroughputInfo = null; - this.PopulateHighestTentativeWriteLLSN = null; - this.PopulateIndexMetrics = null; - this.PopulateIndexMetricsV2 = null; - this.PopulateLogStoreInfo = null; - this.PopulateMinGLSNForDocumentOperations = null; - this.PopulateOldestActiveSchemaId = null; - this.PopulatePartitionStatistics = null; - this.PopulateQueryMetrics = null; - this.PopulateQuotaInfo = null; - this.PopulateResourceCount = null; - this.PopulateUnflushedMergeEntryCount = null; - this.PopulateUniqueIndexReIndexProgress = null; - this.PostTriggerExclude = null; - this.PostTriggerInclude = null; - this.Prefer = null; - this.PreserveFullContent = null; - this.PreTriggerExclude = null; - this.PreTriggerInclude = null; - this.PrimaryMasterKey = null; - this.PrimaryReadonlyKey = null; - this.PriorityLevel = null; - this.ProfileRequest = null; - this.PruneCollectionSchemas = null; - this.QueryVersion = null; - this.RbacAction = null; - this.RbacResource = null; - this.RbacUserId = null; - this.ReadFeedKeyType = null; - this.RemainingTimeInMsOnClientRequest = null; - this.RemoteStorageType = null; - this.RequestedCollectionType = null; - this.ResourceId = null; - this.ResourceSchemaName = null; - this.ResourceTokenExpiry = null; - this.ResourceTypes = null; - this.ResponseContinuationTokenLimitInKB = null; - this.RestoreMetadataFilter = null; - this.RestoreParams = null; - this.RetriableWriteRequestId = null; - this.RetriableWriteRequestStartTimestamp = null; - this.SchemaHash = null; - this.SchemaId = null; - this.SchemaOwnerRid = null; - this.SDKSupportedCapabilities = null; - this.SecondaryMasterKey = null; - this.SecondaryReadonlyKey = null; - this.SessionToken = null; - this.SetMasterResourcesDeletionPending = null; - this.ShareThroughput = null; - this.ShouldBatchContinueOnError = null; - this.ShouldReturnCurrentServerDateTime = null; - this.SkipAdjustThroughputFractionsForOfferReplace = null; - this.SkipRefreshDatabaseAccountConfigs = null; - this.SourceCollectionIfMatch = null; - this.SqlQueryForPartitionKeyExtraction = null; - this.StartEpk = null; - this.StartId = null; - this.SupportedQueryFeatures = null; - this.SupportedSerializationFormats = null; - this.SupportSpatialLegacyCoordinates = null; - this.SystemDocumentType = null; - this.SystemRestoreOperation = null; - this.TargetGlobalCommittedLsn = null; - this.TargetLsn = null; - this.TimeToLiveInSeconds = null; - this.TraceParent = null; - this.TraceState = null; - this.TransactionCommit = null; - this.TransactionFirstRequest = null; - this.TransactionId = null; - this.TransportRequestID = null; - this.TruncateMergeLogRequest = null; - this.UniqueIndexNameEncodingMode = null; - this.UniqueIndexReIndexingState = null; - this.UpdateMaxThroughputEverProvisioned = null; - this.UpdateOfferStateToPending = null; - this.UpdateOfferStateToRestorePending = null; - this.UseArchivalPartition = null; - this.UsePolygonsSmallerThanAHemisphere = null; - this.UseSystemBudget = null; - this.UseUserBackgroundBudget = null; - this.Version = null; - this.XDate = null; - - } - - public INameValueCollection Clone() - { - RequestNameValueCollection cloneHeaders = new RequestNameValueCollection() - { - A_IM = this.A_IM, - ActivityId = this.ActivityId, - AddResourcePropertiesToResponse = this.AddResourcePropertiesToResponse, - AllowDocumentReadsInOfflineRegion = this.AllowDocumentReadsInOfflineRegion, - AllowRestoreParamsUpdate = this.AllowRestoreParamsUpdate, - AllowTentativeWrites = this.AllowTentativeWrites, - Authorization = this.Authorization, - BinaryId = this.BinaryId, - BinaryPassthroughRequest = this.BinaryPassthroughRequest, - BindReplicaDirective = this.BindReplicaDirective, - BuilderClientIdentifier = this.BuilderClientIdentifier, - CanCharge = this.CanCharge, - CanOfferReplaceComplete = this.CanOfferReplaceComplete, - CanThrottle = this.CanThrottle, - ChangeFeedStartFullFidelityIfNoneMatch = this.ChangeFeedStartFullFidelityIfNoneMatch, - ChangeFeedWireFormatVersion = this.ChangeFeedWireFormatVersion, - ClientIpAddress = this.ClientIpAddress, - ClientRetryAttemptCount = this.ClientRetryAttemptCount, - CollectionChildResourceContentLimitInKB = this.CollectionChildResourceContentLimitInKB, - CollectionChildResourceNameLimitInBytes = this.CollectionChildResourceNameLimitInBytes, - CollectionPartitionIndex = this.CollectionPartitionIndex, - CollectionRemoteStorageSecurityIdentifier = this.CollectionRemoteStorageSecurityIdentifier, - CollectionRid = this.CollectionRid, - CollectionServiceIndex = this.CollectionServiceIndex, - CollectionTruncate = this.CollectionTruncate, - ConsistencyLevel = this.ConsistencyLevel, - ContentSerializationFormat = this.ContentSerializationFormat, - Continuation = this.Continuation, - CorrelatedActivityId = this.CorrelatedActivityId, - DisableRUPerMinuteUsage = this.DisableRUPerMinuteUsage, - EffectivePartitionKey = this.EffectivePartitionKey, - EmitVerboseTracesInQuery = this.EmitVerboseTracesInQuery, - EnableConflictResolutionPolicyUpdate = this.EnableConflictResolutionPolicyUpdate, - EnableCrossPartitionQuery = this.EnableCrossPartitionQuery, - EnableDynamicRidRangeAllocation = this.EnableDynamicRidRangeAllocation, - EnableLogging = this.EnableLogging, - EnableLowPrecisionOrderBy = this.EnableLowPrecisionOrderBy, - EnableScanInQuery = this.EnableScanInQuery, - EndEpk = this.EndEpk, - EndId = this.EndId, - EntityId = this.EntityId, - EnumerationDirection = this.EnumerationDirection, - ExcludeSystemProperties = this.ExcludeSystemProperties, - FanoutOperationState = this.FanoutOperationState, - FilterBySchemaResourceId = this.FilterBySchemaResourceId, - ForceDatabaseAccountUpdate = this.ForceDatabaseAccountUpdate, - ForceQueryScan = this.ForceQueryScan, - ForceSideBySideIndexMigration = this.ForceSideBySideIndexMigration, - GatewaySignature = this.GatewaySignature, - GetAllPartitionKeyStatistics = this.GetAllPartitionKeyStatistics, - HighPriorityForcedBackup = this.HighPriorityForcedBackup, - HttpDate = this.HttpDate, - IfMatch = this.IfMatch, - IfModifiedSince = this.IfModifiedSince, - IfNoneMatch = this.IfNoneMatch, - IgnoreSystemLoweringMaxThroughput = this.IgnoreSystemLoweringMaxThroughput, - IncludePhysicalPartitionThroughputInfo = this.IncludePhysicalPartitionThroughputInfo, - IncludeTentativeWrites = this.IncludeTentativeWrites, - IndexingDirective = this.IndexingDirective, - IntendedCollectionRid = this.IntendedCollectionRid, - IsAutoScaleRequest = this.IsAutoScaleRequest, - IsBatchAtomic = this.IsBatchAtomic, - IsBatchOrdered = this.IsBatchOrdered, - IsCassandraAlterTypeRequest = this.IsCassandraAlterTypeRequest, - IsClientEncrypted = this.IsClientEncrypted, - IsContinuationExpected = this.IsContinuationExpected, - IsFanoutRequest = this.IsFanoutRequest, - IsInternalServerlessRequest = this.IsInternalServerlessRequest, - IsMaterializedViewBuild = this.IsMaterializedViewBuild, - IsMaterializedViewSourceSchemaReplaceBatchRequest = this.IsMaterializedViewSourceSchemaReplaceBatchRequest, - IsMigratedFixedCollection = this.IsMigratedFixedCollection, - IsOfferStorageRefreshRequest = this.IsOfferStorageRefreshRequest, - IsReadOnlyScript = this.IsReadOnlyScript, - IsRequestNotAuthorized = this.IsRequestNotAuthorized, - IsRetriedWriteRequest = this.IsRetriedWriteRequest, - IsRUPerGBEnforcementRequest = this.IsRUPerGBEnforcementRequest, - IsServerlessStorageRefreshRequest = this.IsServerlessStorageRefreshRequest, - IsThroughputCapRequest = this.IsThroughputCapRequest, - IsUserRequest = this.IsUserRequest, - MaxPollingIntervalMilliseconds = this.MaxPollingIntervalMilliseconds, - MergeCheckPointGLSN = this.MergeCheckPointGLSN, - MergeStaticId = this.MergeStaticId, - MigrateCollectionDirective = this.MigrateCollectionDirective, - MigrateOfferToAutopilot = this.MigrateOfferToAutopilot, - MigrateOfferToManualThroughput = this.MigrateOfferToManualThroughput, - NoRetryOn449StatusCode = this.NoRetryOn449StatusCode, - OfferReplaceRURedistribution = this.OfferReplaceRURedistribution, - OptimisticDirectExecute = this.OptimisticDirectExecute, - PageSize = this.PageSize, - ParallelizeCrossPartitionQuery = this.ParallelizeCrossPartitionQuery, - PartitionCount = this.PartitionCount, - PartitionKey = this.PartitionKey, - PartitionKeyRangeId = this.PartitionKeyRangeId, - PartitionResourceFilter = this.PartitionResourceFilter, - PopulateAnalyticalMigrationProgress = this.PopulateAnalyticalMigrationProgress, - PopulateByokEncryptionProgress = this.PopulateByokEncryptionProgress, - PopulateCapacityType = this.PopulateCapacityType, - PopulateCollectionThroughputInfo = this.PopulateCollectionThroughputInfo, - PopulateCurrentPartitionThroughputInfo = this.PopulateCurrentPartitionThroughputInfo, - PopulateHighestTentativeWriteLLSN = this.PopulateHighestTentativeWriteLLSN, - PopulateIndexMetrics = this.PopulateIndexMetrics, - PopulateIndexMetricsV2 = this.PopulateIndexMetricsV2, - PopulateLogStoreInfo = this.PopulateLogStoreInfo, - PopulateMinGLSNForDocumentOperations = this.PopulateMinGLSNForDocumentOperations, - PopulateOldestActiveSchemaId = this.PopulateOldestActiveSchemaId, - PopulatePartitionStatistics = this.PopulatePartitionStatistics, - PopulateQueryMetrics = this.PopulateQueryMetrics, - PopulateQuotaInfo = this.PopulateQuotaInfo, - PopulateResourceCount = this.PopulateResourceCount, - PopulateUnflushedMergeEntryCount = this.PopulateUnflushedMergeEntryCount, - PopulateUniqueIndexReIndexProgress = this.PopulateUniqueIndexReIndexProgress, - PostTriggerExclude = this.PostTriggerExclude, - PostTriggerInclude = this.PostTriggerInclude, - Prefer = this.Prefer, - PreserveFullContent = this.PreserveFullContent, - PreTriggerExclude = this.PreTriggerExclude, - PreTriggerInclude = this.PreTriggerInclude, - PrimaryMasterKey = this.PrimaryMasterKey, - PrimaryReadonlyKey = this.PrimaryReadonlyKey, - PriorityLevel = this.PriorityLevel, - ProfileRequest = this.ProfileRequest, - PruneCollectionSchemas = this.PruneCollectionSchemas, - QueryVersion = this.QueryVersion, - RbacAction = this.RbacAction, - RbacResource = this.RbacResource, - RbacUserId = this.RbacUserId, - ReadFeedKeyType = this.ReadFeedKeyType, - RemainingTimeInMsOnClientRequest = this.RemainingTimeInMsOnClientRequest, - RemoteStorageType = this.RemoteStorageType, - RequestedCollectionType = this.RequestedCollectionType, - ResourceId = this.ResourceId, - ResourceSchemaName = this.ResourceSchemaName, - ResourceTokenExpiry = this.ResourceTokenExpiry, - ResourceTypes = this.ResourceTypes, - ResponseContinuationTokenLimitInKB = this.ResponseContinuationTokenLimitInKB, - RestoreMetadataFilter = this.RestoreMetadataFilter, - RestoreParams = this.RestoreParams, - RetriableWriteRequestId = this.RetriableWriteRequestId, - RetriableWriteRequestStartTimestamp = this.RetriableWriteRequestStartTimestamp, - SchemaHash = this.SchemaHash, - SchemaId = this.SchemaId, - SchemaOwnerRid = this.SchemaOwnerRid, - SDKSupportedCapabilities = this.SDKSupportedCapabilities, - SecondaryMasterKey = this.SecondaryMasterKey, - SecondaryReadonlyKey = this.SecondaryReadonlyKey, - SessionToken = this.SessionToken, - SetMasterResourcesDeletionPending = this.SetMasterResourcesDeletionPending, - ShareThroughput = this.ShareThroughput, - ShouldBatchContinueOnError = this.ShouldBatchContinueOnError, - ShouldReturnCurrentServerDateTime = this.ShouldReturnCurrentServerDateTime, - SkipAdjustThroughputFractionsForOfferReplace = this.SkipAdjustThroughputFractionsForOfferReplace, - SkipRefreshDatabaseAccountConfigs = this.SkipRefreshDatabaseAccountConfigs, - SourceCollectionIfMatch = this.SourceCollectionIfMatch, - SqlQueryForPartitionKeyExtraction = this.SqlQueryForPartitionKeyExtraction, - StartEpk = this.StartEpk, - StartId = this.StartId, - SupportedQueryFeatures = this.SupportedQueryFeatures, - SupportedSerializationFormats = this.SupportedSerializationFormats, - SupportSpatialLegacyCoordinates = this.SupportSpatialLegacyCoordinates, - SystemDocumentType = this.SystemDocumentType, - SystemRestoreOperation = this.SystemRestoreOperation, - TargetGlobalCommittedLsn = this.TargetGlobalCommittedLsn, - TargetLsn = this.TargetLsn, - TimeToLiveInSeconds = this.TimeToLiveInSeconds, - TraceParent = this.TraceParent, - TraceState = this.TraceState, - TransactionCommit = this.TransactionCommit, - TransactionFirstRequest = this.TransactionFirstRequest, - TransactionId = this.TransactionId, - TransportRequestID = this.TransportRequestID, - TruncateMergeLogRequest = this.TruncateMergeLogRequest, - UniqueIndexNameEncodingMode = this.UniqueIndexNameEncodingMode, - UniqueIndexReIndexingState = this.UniqueIndexReIndexingState, - UpdateMaxThroughputEverProvisioned = this.UpdateMaxThroughputEverProvisioned, - UpdateOfferStateToPending = this.UpdateOfferStateToPending, - UpdateOfferStateToRestorePending = this.UpdateOfferStateToRestorePending, - UseArchivalPartition = this.UseArchivalPartition, - UsePolygonsSmallerThanAHemisphere = this.UsePolygonsSmallerThanAHemisphere, - UseSystemBudget = this.UseSystemBudget, - UseUserBackgroundBudget = this.UseUserBackgroundBudget, - Version = this.Version, - XDate = this.XDate, - }; - - if (this.notCommonHeaders != null) - { - cloneHeaders.notCommonHeaders = new Dictionary(this.notCommonHeaders, RequestNameValueCollection.DefaultStringComparer); - } - - return cloneHeaders; - } - - public int Count() - { - return this.Keys().Count(); - } - - public IEnumerator GetEnumerator() - { - return this.Keys().GetEnumerator(); - } - - public string[] GetValues(string key) - { - string value = this.Get(key); - if (value != null) - { - return new string[] { value }; - } - - return null; - } - - public IEnumerable Keys() - { - if (this.ResourceId != null) - { - yield return WFConstants.BackendHeaders.ResourceId; - } - if (this.Authorization != null) - { - yield return HttpConstants.HttpHeaders.Authorization; - } - if (this.HttpDate != null) - { - yield return HttpConstants.HttpHeaders.HttpDate; - } - if (this.XDate != null) - { - yield return HttpConstants.HttpHeaders.XDate; - } - if (this.PageSize != null) - { - yield return HttpConstants.HttpHeaders.PageSize; - } - if (this.SessionToken != null) - { - yield return HttpConstants.HttpHeaders.SessionToken; - } - if (this.Continuation != null) - { - yield return HttpConstants.HttpHeaders.Continuation; - } - if (this.IndexingDirective != null) - { - yield return HttpConstants.HttpHeaders.IndexingDirective; - } - if (this.IfNoneMatch != null) - { - yield return HttpConstants.HttpHeaders.IfNoneMatch; - } - if (this.PreTriggerInclude != null) - { - yield return HttpConstants.HttpHeaders.PreTriggerInclude; - } - if (this.PostTriggerInclude != null) - { - yield return HttpConstants.HttpHeaders.PostTriggerInclude; - } - if (this.IsFanoutRequest != null) - { - yield return WFConstants.BackendHeaders.IsFanoutRequest; - } - if (this.CollectionPartitionIndex != null) - { - yield return WFConstants.BackendHeaders.CollectionPartitionIndex; - } - if (this.CollectionServiceIndex != null) - { - yield return WFConstants.BackendHeaders.CollectionServiceIndex; - } - if (this.PreTriggerExclude != null) - { - yield return HttpConstants.HttpHeaders.PreTriggerExclude; - } - if (this.PostTriggerExclude != null) - { - yield return HttpConstants.HttpHeaders.PostTriggerExclude; - } - if (this.ConsistencyLevel != null) - { - yield return HttpConstants.HttpHeaders.ConsistencyLevel; - } - if (this.EntityId != null) - { - yield return WFConstants.BackendHeaders.EntityId; - } - if (this.ResourceSchemaName != null) - { - yield return WFConstants.BackendHeaders.ResourceSchemaName; - } - if (this.ResourceTokenExpiry != null) - { - yield return HttpConstants.HttpHeaders.ResourceTokenExpiry; - } - if (this.EnableScanInQuery != null) - { - yield return HttpConstants.HttpHeaders.EnableScanInQuery; - } - if (this.EmitVerboseTracesInQuery != null) - { - yield return HttpConstants.HttpHeaders.EmitVerboseTracesInQuery; - } - if (this.BindReplicaDirective != null) - { - yield return WFConstants.BackendHeaders.BindReplicaDirective; - } - if (this.PrimaryMasterKey != null) - { - yield return WFConstants.BackendHeaders.PrimaryMasterKey; - } - if (this.SecondaryMasterKey != null) - { - yield return WFConstants.BackendHeaders.SecondaryMasterKey; - } - if (this.PrimaryReadonlyKey != null) - { - yield return WFConstants.BackendHeaders.PrimaryReadonlyKey; - } - if (this.SecondaryReadonlyKey != null) - { - yield return WFConstants.BackendHeaders.SecondaryReadonlyKey; - } - if (this.ProfileRequest != null) - { - yield return HttpConstants.HttpHeaders.ProfileRequest; - } - if (this.EnableLowPrecisionOrderBy != null) - { - yield return HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy; - } - if (this.Version != null) - { - yield return HttpConstants.HttpHeaders.Version; - } - if (this.CanCharge != null) - { - yield return HttpConstants.HttpHeaders.CanCharge; - } - if (this.CanThrottle != null) - { - yield return HttpConstants.HttpHeaders.CanThrottle; - } - if (this.PartitionKey != null) - { - yield return HttpConstants.HttpHeaders.PartitionKey; - } - if (this.PartitionKeyRangeId != null) - { - yield return HttpConstants.HttpHeaders.PartitionKeyRangeId; - } - if (this.MigrateCollectionDirective != null) - { - yield return HttpConstants.HttpHeaders.MigrateCollectionDirective; - } - if (this.SupportSpatialLegacyCoordinates != null) - { - yield return HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates; - } - if (this.PartitionCount != null) - { - yield return HttpConstants.HttpHeaders.PartitionCount; - } - if (this.CollectionRid != null) - { - yield return WFConstants.BackendHeaders.CollectionRid; - } - if (this.FilterBySchemaResourceId != null) - { - yield return HttpConstants.HttpHeaders.FilterBySchemaResourceId; - } - if (this.UsePolygonsSmallerThanAHemisphere != null) - { - yield return HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere; - } - if (this.GatewaySignature != null) - { - yield return HttpConstants.HttpHeaders.GatewaySignature; - } - if (this.EnableLogging != null) - { - yield return HttpConstants.HttpHeaders.EnableLogging; - } - if (this.A_IM != null) - { - yield return HttpConstants.HttpHeaders.A_IM; - } - if (this.PopulateQuotaInfo != null) - { - yield return HttpConstants.HttpHeaders.PopulateQuotaInfo; - } - if (this.DisableRUPerMinuteUsage != null) - { - yield return HttpConstants.HttpHeaders.DisableRUPerMinuteUsage; - } - if (this.PopulateQueryMetrics != null) - { - yield return HttpConstants.HttpHeaders.PopulateQueryMetrics; - } - if (this.ResponseContinuationTokenLimitInKB != null) - { - yield return HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB; - } - if (this.PopulatePartitionStatistics != null) - { - yield return HttpConstants.HttpHeaders.PopulatePartitionStatistics; - } - if (this.RemoteStorageType != null) - { - yield return WFConstants.BackendHeaders.RemoteStorageType; - } - if (this.CollectionRemoteStorageSecurityIdentifier != null) - { - yield return HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier; - } - if (this.IfModifiedSince != null) - { - yield return HttpConstants.HttpHeaders.IfModifiedSince; - } - if (this.PopulateCollectionThroughputInfo != null) - { - yield return HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo; - } - if (this.RemainingTimeInMsOnClientRequest != null) - { - yield return HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest; - } - if (this.ClientRetryAttemptCount != null) - { - yield return HttpConstants.HttpHeaders.ClientRetryAttemptCount; - } - if (this.TargetLsn != null) - { - yield return HttpConstants.HttpHeaders.TargetLsn; - } - if (this.TargetGlobalCommittedLsn != null) - { - yield return HttpConstants.HttpHeaders.TargetGlobalCommittedLsn; - } - if (this.TransportRequestID != null) - { - yield return HttpConstants.HttpHeaders.TransportRequestID; - } - if (this.RestoreMetadataFilter != null) - { - yield return HttpConstants.HttpHeaders.RestoreMetadataFilter; - } - if (this.RestoreParams != null) - { - yield return WFConstants.BackendHeaders.RestoreParams; - } - if (this.ShareThroughput != null) - { - yield return WFConstants.BackendHeaders.ShareThroughput; - } - if (this.PartitionResourceFilter != null) - { - yield return WFConstants.BackendHeaders.PartitionResourceFilter; - } - if (this.IsReadOnlyScript != null) - { - yield return HttpConstants.HttpHeaders.IsReadOnlyScript; - } - if (this.IsAutoScaleRequest != null) - { - yield return HttpConstants.HttpHeaders.IsAutoScaleRequest; - } - if (this.ForceQueryScan != null) - { - yield return HttpConstants.HttpHeaders.ForceQueryScan; - } - if (this.CanOfferReplaceComplete != null) - { - yield return HttpConstants.HttpHeaders.CanOfferReplaceComplete; - } - if (this.ExcludeSystemProperties != null) - { - yield return WFConstants.BackendHeaders.ExcludeSystemProperties; - } - if (this.BinaryId != null) - { - yield return WFConstants.BackendHeaders.BinaryId; - } - if (this.TimeToLiveInSeconds != null) - { - yield return WFConstants.BackendHeaders.TimeToLiveInSeconds; - } - if (this.EffectivePartitionKey != null) - { - yield return WFConstants.BackendHeaders.EffectivePartitionKey; - } - if (this.BinaryPassthroughRequest != null) - { - yield return WFConstants.BackendHeaders.BinaryPassthroughRequest; - } - if (this.EnableDynamicRidRangeAllocation != null) - { - yield return WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation; - } - if (this.EnumerationDirection != null) - { - yield return HttpConstants.HttpHeaders.EnumerationDirection; - } - if (this.StartId != null) - { - yield return HttpConstants.HttpHeaders.StartId; - } - if (this.EndId != null) - { - yield return HttpConstants.HttpHeaders.EndId; - } - if (this.FanoutOperationState != null) - { - yield return WFConstants.BackendHeaders.FanoutOperationState; - } - if (this.StartEpk != null) - { - yield return HttpConstants.HttpHeaders.StartEpk; - } - if (this.EndEpk != null) - { - yield return HttpConstants.HttpHeaders.EndEpk; - } - if (this.ReadFeedKeyType != null) - { - yield return HttpConstants.HttpHeaders.ReadFeedKeyType; - } - if (this.ContentSerializationFormat != null) - { - yield return HttpConstants.HttpHeaders.ContentSerializationFormat; - } - if (this.AllowTentativeWrites != null) - { - yield return HttpConstants.HttpHeaders.AllowTentativeWrites; - } - if (this.IsUserRequest != null) - { - yield return WFConstants.BackendHeaders.IsUserRequest; - } - if (this.PreserveFullContent != null) - { - yield return HttpConstants.HttpHeaders.PreserveFullContent; - } - if (this.IncludeTentativeWrites != null) - { - yield return HttpConstants.HttpHeaders.IncludeTentativeWrites; - } - if (this.PopulateResourceCount != null) - { - yield return HttpConstants.HttpHeaders.PopulateResourceCount; - } - if (this.MergeStaticId != null) - { - yield return HttpConstants.HttpHeaders.MergeStaticId; - } - if (this.IsBatchAtomic != null) - { - yield return HttpConstants.HttpHeaders.IsBatchAtomic; - } - if (this.ShouldBatchContinueOnError != null) - { - yield return HttpConstants.HttpHeaders.ShouldBatchContinueOnError; - } - if (this.IsBatchOrdered != null) - { - yield return HttpConstants.HttpHeaders.IsBatchOrdered; - } - if (this.SchemaOwnerRid != null) - { - yield return WFConstants.BackendHeaders.SchemaOwnerRid; - } - if (this.SchemaHash != null) - { - yield return WFConstants.BackendHeaders.SchemaHash; - } - if (this.IsRUPerGBEnforcementRequest != null) - { - yield return HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest; - } - if (this.MaxPollingIntervalMilliseconds != null) - { - yield return HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds; - } - if (this.PopulateLogStoreInfo != null) - { - yield return WFConstants.BackendHeaders.PopulateLogStoreInfo; - } - if (this.GetAllPartitionKeyStatistics != null) - { - yield return HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics; - } - if (this.ForceSideBySideIndexMigration != null) - { - yield return HttpConstants.HttpHeaders.ForceSideBySideIndexMigration; - } - if (this.CollectionChildResourceNameLimitInBytes != null) - { - yield return WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes; - } - if (this.CollectionChildResourceContentLimitInKB != null) - { - yield return WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB; - } - if (this.MergeCheckPointGLSN != null) - { - yield return WFConstants.BackendHeaders.MergeCheckPointGLSN; - } - if (this.Prefer != null) - { - yield return HttpConstants.HttpHeaders.Prefer; - } - if (this.UniqueIndexNameEncodingMode != null) - { - yield return WFConstants.BackendHeaders.UniqueIndexNameEncodingMode; - } - if (this.PopulateUnflushedMergeEntryCount != null) - { - yield return WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount; - } - if (this.MigrateOfferToManualThroughput != null) - { - yield return HttpConstants.HttpHeaders.MigrateOfferToManualThroughput; - } - if (this.MigrateOfferToAutopilot != null) - { - yield return HttpConstants.HttpHeaders.MigrateOfferToAutopilot; - } - if (this.IsClientEncrypted != null) - { - yield return HttpConstants.HttpHeaders.IsClientEncrypted; - } - if (this.SystemDocumentType != null) - { - yield return HttpConstants.HttpHeaders.SystemDocumentType; - } - if (this.IsOfferStorageRefreshRequest != null) - { - yield return HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest; - } - if (this.ResourceTypes != null) - { - yield return WFConstants.BackendHeaders.ResourceTypes; - } - if (this.TransactionId != null) - { - yield return WFConstants.BackendHeaders.TransactionId; - } - if (this.TransactionFirstRequest != null) - { - yield return WFConstants.BackendHeaders.TransactionFirstRequest; - } - if (this.TransactionCommit != null) - { - yield return WFConstants.BackendHeaders.TransactionCommit; - } - if (this.UpdateMaxThroughputEverProvisioned != null) - { - yield return HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned; - } - if (this.UniqueIndexReIndexingState != null) - { - yield return WFConstants.BackendHeaders.UniqueIndexReIndexingState; - } - if (this.UseSystemBudget != null) - { - yield return WFConstants.BackendHeaders.UseSystemBudget; - } - if (this.IgnoreSystemLoweringMaxThroughput != null) - { - yield return HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput; - } - if (this.TruncateMergeLogRequest != null) - { - yield return HttpConstants.HttpHeaders.TruncateMergeLogRequest; - } - if (this.RetriableWriteRequestId != null) - { - yield return WFConstants.BackendHeaders.RetriableWriteRequestId; - } - if (this.IsRetriedWriteRequest != null) - { - yield return WFConstants.BackendHeaders.IsRetriedWriteRequest; - } - if (this.RetriableWriteRequestStartTimestamp != null) - { - yield return WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp; - } - if (this.AddResourcePropertiesToResponse != null) - { - yield return WFConstants.BackendHeaders.AddResourcePropertiesToResponse; - } - if (this.ChangeFeedStartFullFidelityIfNoneMatch != null) - { - yield return HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch; - } - if (this.SystemRestoreOperation != null) - { - yield return HttpConstants.HttpHeaders.SystemRestoreOperation; - } - if (this.SkipRefreshDatabaseAccountConfigs != null) - { - yield return WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs; - } - if (this.IntendedCollectionRid != null) - { - yield return WFConstants.BackendHeaders.IntendedCollectionRid; - } - if (this.UseArchivalPartition != null) - { - yield return HttpConstants.HttpHeaders.UseArchivalPartition; - } - if (this.PopulateUniqueIndexReIndexProgress != null) - { - yield return HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress; - } - if (this.SchemaId != null) - { - yield return WFConstants.BackendHeaders.SchemaId; - } - if (this.CollectionTruncate != null) - { - yield return HttpConstants.HttpHeaders.CollectionTruncate; - } - if (this.SDKSupportedCapabilities != null) - { - yield return HttpConstants.HttpHeaders.SDKSupportedCapabilities; - } - if (this.IsMaterializedViewBuild != null) - { - yield return HttpConstants.HttpHeaders.IsMaterializedViewBuild; - } - if (this.BuilderClientIdentifier != null) - { - yield return HttpConstants.HttpHeaders.BuilderClientIdentifier; - } - if (this.SourceCollectionIfMatch != null) - { - yield return WFConstants.BackendHeaders.SourceCollectionIfMatch; - } - if (this.RequestedCollectionType != null) - { - yield return WFConstants.BackendHeaders.RequestedCollectionType; - } - if (this.PopulateIndexMetrics != null) - { - yield return HttpConstants.HttpHeaders.PopulateIndexMetrics; - } - if (this.PopulateAnalyticalMigrationProgress != null) - { - yield return HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress; - } - if (this.ShouldReturnCurrentServerDateTime != null) - { - yield return HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime; - } - if (this.RbacUserId != null) - { - yield return HttpConstants.HttpHeaders.RbacUserId; - } - if (this.RbacAction != null) - { - yield return HttpConstants.HttpHeaders.RbacAction; - } - if (this.RbacResource != null) - { - yield return HttpConstants.HttpHeaders.RbacResource; - } - if (this.CorrelatedActivityId != null) - { - yield return HttpConstants.HttpHeaders.CorrelatedActivityId; - } - if (this.IsThroughputCapRequest != null) - { - yield return HttpConstants.HttpHeaders.IsThroughputCapRequest; - } - if (this.ChangeFeedWireFormatVersion != null) - { - yield return HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion; - } - if (this.PopulateByokEncryptionProgress != null) - { - yield return HttpConstants.HttpHeaders.PopulateByokEncryptionProgress; - } - if (this.UseUserBackgroundBudget != null) - { - yield return WFConstants.BackendHeaders.UseUserBackgroundBudget; - } - if (this.IncludePhysicalPartitionThroughputInfo != null) - { - yield return HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo; - } - if (this.IsServerlessStorageRefreshRequest != null) - { - yield return HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest; - } - if (this.UpdateOfferStateToPending != null) - { - yield return HttpConstants.HttpHeaders.UpdateOfferStateToPending; - } - if (this.PopulateOldestActiveSchemaId != null) - { - yield return HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId; - } - if (this.IsInternalServerlessRequest != null) - { - yield return HttpConstants.HttpHeaders.IsInternalServerlessRequest; - } - if (this.OfferReplaceRURedistribution != null) - { - yield return HttpConstants.HttpHeaders.OfferReplaceRURedistribution; - } - if (this.IsCassandraAlterTypeRequest != null) - { - yield return HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest; - } - if (this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) - { - yield return HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest; - } - if (this.ForceDatabaseAccountUpdate != null) - { - yield return HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate; - } - if (this.PriorityLevel != null) - { - yield return HttpConstants.HttpHeaders.PriorityLevel; - } - if (this.AllowRestoreParamsUpdate != null) - { - yield return HttpConstants.HttpHeaders.AllowRestoreParamsUpdate; - } - if (this.PruneCollectionSchemas != null) - { - yield return HttpConstants.HttpHeaders.PruneCollectionSchemas; - } - if (this.PopulateIndexMetricsV2 != null) - { - yield return HttpConstants.HttpHeaders.PopulateIndexMetricsV2; - } - if (this.IsMigratedFixedCollection != null) - { - yield return HttpConstants.HttpHeaders.IsMigratedFixedCollection; - } - if (this.SupportedSerializationFormats != null) - { - yield return HttpConstants.HttpHeaders.SupportedSerializationFormats; - } - if (this.UpdateOfferStateToRestorePending != null) - { - yield return HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending; - } - if (this.SetMasterResourcesDeletionPending != null) - { - yield return HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending; - } - if (this.HighPriorityForcedBackup != null) - { - yield return HttpConstants.HttpHeaders.HighPriorityForcedBackup; - } - if (this.OptimisticDirectExecute != null) - { - yield return HttpConstants.HttpHeaders.OptimisticDirectExecute; - } - if (this.PopulateMinGLSNForDocumentOperations != null) - { - yield return WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations; - } - if (this.PopulateHighestTentativeWriteLLSN != null) - { - yield return WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN; - } - if (this.PopulateCapacityType != null) - { - yield return WFConstants.BackendHeaders.PopulateCapacityType; - } - if (this.TraceParent != null) - { - yield return HttpConstants.HttpHeaders.TraceParent; - } - if (this.TraceState != null) - { - yield return HttpConstants.HttpHeaders.TraceState; - } - if (this.EnableConflictResolutionPolicyUpdate != null) - { - yield return HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate; - } - if (this.ClientIpAddress != null) - { - yield return WFConstants.BackendHeaders.ClientIpAddress; - } - if (this.IsRequestNotAuthorized != null) - { - yield return WFConstants.BackendHeaders.IsRequestNotAuthorized; - } - if (this.AllowDocumentReadsInOfflineRegion != null) - { - yield return HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion; - } - if (this.PopulateCurrentPartitionThroughputInfo != null) - { - yield return WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo; - } - if (this.IfMatch != null) - { - yield return HttpConstants.HttpHeaders.IfMatch; - } - if (this.NoRetryOn449StatusCode != null) - { - yield return HttpConstants.HttpHeaders.NoRetryOn449StatusCode; - } - if (this.SkipAdjustThroughputFractionsForOfferReplace != null) - { - yield return HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace; - } - if (this.SqlQueryForPartitionKeyExtraction != null) - { - yield return HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction; - } - if (this.EnableCrossPartitionQuery != null) - { - yield return HttpConstants.HttpHeaders.EnableCrossPartitionQuery; - } - if (this.IsContinuationExpected != null) - { - yield return HttpConstants.HttpHeaders.IsContinuationExpected; - } - if (this.ParallelizeCrossPartitionQuery != null) - { - yield return HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery; - } - if (this.SupportedQueryFeatures != null) - { - yield return HttpConstants.HttpHeaders.SupportedQueryFeatures; - } - if (this.QueryVersion != null) - { - yield return HttpConstants.HttpHeaders.QueryVersion; - } - if (this.ActivityId != null) - { - yield return HttpConstants.HttpHeaders.ActivityId; - } - - if (this.notCommonHeaders != null) - { - foreach (string key in this.notCommonHeaders.Keys) - { - yield return key; - } - } - } - - public NameValueCollection ToNameValueCollection() - { - // Note: See comment on line 34 of this file for the implementation. We need to respect current contracts - // for Backend Gateway. - if (this.nameValueCollection == null) - { - lock (this) - { - if (this.nameValueCollection == null) - { - this.nameValueCollection = new NameValueCollection(this.Count(), RequestNameValueCollection.DefaultStringComparer); - - if (this.ResourceId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceId, this.ResourceId); - } - if (this.Authorization != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.Authorization, this.Authorization); - } - if (this.HttpDate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.HttpDate, this.HttpDate); - } - if (this.XDate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.XDate, this.XDate); - } - if (this.PageSize != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PageSize, this.PageSize); - } - if (this.SessionToken != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); - } - if (this.Continuation != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.Continuation, this.Continuation); - } - if (this.IndexingDirective != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); - } - if (this.IfNoneMatch != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfNoneMatch, this.IfNoneMatch); - } - if (this.PreTriggerInclude != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreTriggerInclude, this.PreTriggerInclude); - } - if (this.PostTriggerInclude != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PostTriggerInclude, this.PostTriggerInclude); - } - if (this.IsFanoutRequest != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IsFanoutRequest, this.IsFanoutRequest); - } - if (this.CollectionPartitionIndex != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); - } - if (this.CollectionServiceIndex != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); - } - if (this.PreTriggerExclude != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreTriggerExclude, this.PreTriggerExclude); - } - if (this.PostTriggerExclude != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PostTriggerExclude, this.PostTriggerExclude); - } - if (this.ConsistencyLevel != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ConsistencyLevel, this.ConsistencyLevel); - } - if (this.EntityId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.EntityId, this.EntityId); - } - if (this.ResourceSchemaName != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceSchemaName, this.ResourceSchemaName); - } - if (this.ResourceTokenExpiry != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ResourceTokenExpiry, this.ResourceTokenExpiry); - } - if (this.EnableScanInQuery != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableScanInQuery, this.EnableScanInQuery); - } - if (this.EmitVerboseTracesInQuery != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, this.EmitVerboseTracesInQuery); - } - if (this.BindReplicaDirective != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.BindReplicaDirective, this.BindReplicaDirective); - } - if (this.PrimaryMasterKey != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PrimaryMasterKey, this.PrimaryMasterKey); - } - if (this.SecondaryMasterKey != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SecondaryMasterKey, this.SecondaryMasterKey); - } - if (this.PrimaryReadonlyKey != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PrimaryReadonlyKey, this.PrimaryReadonlyKey); - } - if (this.SecondaryReadonlyKey != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SecondaryReadonlyKey, this.SecondaryReadonlyKey); - } - if (this.ProfileRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ProfileRequest, this.ProfileRequest); - } - if (this.EnableLowPrecisionOrderBy != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, this.EnableLowPrecisionOrderBy); - } - if (this.Version != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.Version, this.Version); - } - if (this.CanCharge != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanCharge, this.CanCharge); - } - if (this.CanThrottle != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanThrottle, this.CanThrottle); - } - if (this.PartitionKey != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionKey, this.PartitionKey); - } - if (this.PartitionKeyRangeId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); - } - if (this.MigrateCollectionDirective != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateCollectionDirective, this.MigrateCollectionDirective); - } - if (this.SupportSpatialLegacyCoordinates != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, this.SupportSpatialLegacyCoordinates); - } - if (this.PartitionCount != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionCount, this.PartitionCount); - } - if (this.CollectionRid != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionRid, this.CollectionRid); - } - if (this.FilterBySchemaResourceId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.FilterBySchemaResourceId, this.FilterBySchemaResourceId); - } - if (this.UsePolygonsSmallerThanAHemisphere != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, this.UsePolygonsSmallerThanAHemisphere); - } - if (this.GatewaySignature != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.GatewaySignature, this.GatewaySignature); - } - if (this.EnableLogging != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableLogging, this.EnableLogging); - } - if (this.A_IM != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.A_IM, this.A_IM); - } - if (this.PopulateQuotaInfo != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateQuotaInfo, this.PopulateQuotaInfo); - } - if (this.DisableRUPerMinuteUsage != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, this.DisableRUPerMinuteUsage); - } - if (this.PopulateQueryMetrics != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateQueryMetrics, this.PopulateQueryMetrics); - } - if (this.ResponseContinuationTokenLimitInKB != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, this.ResponseContinuationTokenLimitInKB); - } - if (this.PopulatePartitionStatistics != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulatePartitionStatistics, this.PopulatePartitionStatistics); - } - if (this.RemoteStorageType != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RemoteStorageType, this.RemoteStorageType); - } - if (this.CollectionRemoteStorageSecurityIdentifier != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, this.CollectionRemoteStorageSecurityIdentifier); - } - if (this.IfModifiedSince != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfModifiedSince, this.IfModifiedSince); - } - if (this.PopulateCollectionThroughputInfo != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, this.PopulateCollectionThroughputInfo); - } - if (this.RemainingTimeInMsOnClientRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, this.RemainingTimeInMsOnClientRequest); - } - if (this.ClientRetryAttemptCount != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ClientRetryAttemptCount, this.ClientRetryAttemptCount); - } - if (this.TargetLsn != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TargetLsn, this.TargetLsn); - } - if (this.TargetGlobalCommittedLsn != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, this.TargetGlobalCommittedLsn); - } - if (this.TransportRequestID != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); - } - if (this.RestoreMetadataFilter != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RestoreMetadataFilter, this.RestoreMetadataFilter); - } - if (this.RestoreParams != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RestoreParams, this.RestoreParams); - } - if (this.ShareThroughput != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); - } - if (this.PartitionResourceFilter != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionResourceFilter, this.PartitionResourceFilter); - } - if (this.IsReadOnlyScript != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsReadOnlyScript, this.IsReadOnlyScript); - } - if (this.IsAutoScaleRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsAutoScaleRequest, this.IsAutoScaleRequest); - } - if (this.ForceQueryScan != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceQueryScan, this.ForceQueryScan); - } - if (this.CanOfferReplaceComplete != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanOfferReplaceComplete, this.CanOfferReplaceComplete); - } - if (this.ExcludeSystemProperties != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ExcludeSystemProperties, this.ExcludeSystemProperties); - } - if (this.BinaryId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.BinaryId, this.BinaryId); - } - if (this.TimeToLiveInSeconds != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); - } - if (this.EffectivePartitionKey != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.EffectivePartitionKey, this.EffectivePartitionKey); - } - if (this.BinaryPassthroughRequest != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.BinaryPassthroughRequest, this.BinaryPassthroughRequest); - } - if (this.EnableDynamicRidRangeAllocation != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, this.EnableDynamicRidRangeAllocation); - } - if (this.EnumerationDirection != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnumerationDirection, this.EnumerationDirection); - } - if (this.StartId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.StartId, this.StartId); - } - if (this.EndId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EndId, this.EndId); - } - if (this.FanoutOperationState != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.FanoutOperationState, this.FanoutOperationState); - } - if (this.StartEpk != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.StartEpk, this.StartEpk); - } - if (this.EndEpk != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EndEpk, this.EndEpk); - } - if (this.ReadFeedKeyType != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ReadFeedKeyType, this.ReadFeedKeyType); - } - if (this.ContentSerializationFormat != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ContentSerializationFormat, this.ContentSerializationFormat); - } - if (this.AllowTentativeWrites != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowTentativeWrites, this.AllowTentativeWrites); - } - if (this.IsUserRequest != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IsUserRequest, this.IsUserRequest); - } - if (this.PreserveFullContent != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreserveFullContent, this.PreserveFullContent); - } - if (this.IncludeTentativeWrites != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IncludeTentativeWrites, this.IncludeTentativeWrites); - } - if (this.PopulateResourceCount != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateResourceCount, this.PopulateResourceCount); - } - if (this.MergeStaticId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MergeStaticId, this.MergeStaticId); - } - if (this.IsBatchAtomic != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsBatchAtomic, this.IsBatchAtomic); - } - if (this.ShouldBatchContinueOnError != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, this.ShouldBatchContinueOnError); - } - if (this.IsBatchOrdered != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsBatchOrdered, this.IsBatchOrdered); - } - if (this.SchemaOwnerRid != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaOwnerRid, this.SchemaOwnerRid); - } - if (this.SchemaHash != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaHash, this.SchemaHash); - } - if (this.IsRUPerGBEnforcementRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, this.IsRUPerGBEnforcementRequest); - } - if (this.MaxPollingIntervalMilliseconds != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, this.MaxPollingIntervalMilliseconds); - } - if (this.PopulateLogStoreInfo != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateLogStoreInfo, this.PopulateLogStoreInfo); - } - if (this.GetAllPartitionKeyStatistics != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, this.GetAllPartitionKeyStatistics); - } - if (this.ForceSideBySideIndexMigration != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, this.ForceSideBySideIndexMigration); - } - if (this.CollectionChildResourceNameLimitInBytes != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, this.CollectionChildResourceNameLimitInBytes); - } - if (this.CollectionChildResourceContentLimitInKB != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, this.CollectionChildResourceContentLimitInKB); - } - if (this.MergeCheckPointGLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.MergeCheckPointGLSN, this.MergeCheckPointGLSN); - } - if (this.Prefer != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.Prefer, this.Prefer); - } - if (this.UniqueIndexNameEncodingMode != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, this.UniqueIndexNameEncodingMode); - } - if (this.PopulateUnflushedMergeEntryCount != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, this.PopulateUnflushedMergeEntryCount); - } - if (this.MigrateOfferToManualThroughput != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, this.MigrateOfferToManualThroughput); - } - if (this.MigrateOfferToAutopilot != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, this.MigrateOfferToAutopilot); - } - if (this.IsClientEncrypted != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsClientEncrypted, this.IsClientEncrypted); - } - if (this.SystemDocumentType != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SystemDocumentType, this.SystemDocumentType); - } - if (this.IsOfferStorageRefreshRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, this.IsOfferStorageRefreshRequest); - } - if (this.ResourceTypes != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceTypes, this.ResourceTypes); - } - if (this.TransactionId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionId, this.TransactionId); - } - if (this.TransactionFirstRequest != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionFirstRequest, this.TransactionFirstRequest); - } - if (this.TransactionCommit != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionCommit, this.TransactionCommit); - } - if (this.UpdateMaxThroughputEverProvisioned != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, this.UpdateMaxThroughputEverProvisioned); - } - if (this.UniqueIndexReIndexingState != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.UniqueIndexReIndexingState, this.UniqueIndexReIndexingState); - } - if (this.UseSystemBudget != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.UseSystemBudget, this.UseSystemBudget); - } - if (this.IgnoreSystemLoweringMaxThroughput != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, this.IgnoreSystemLoweringMaxThroughput); - } - if (this.TruncateMergeLogRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TruncateMergeLogRequest, this.TruncateMergeLogRequest); - } - if (this.RetriableWriteRequestId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RetriableWriteRequestId, this.RetriableWriteRequestId); - } - if (this.IsRetriedWriteRequest != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRetriedWriteRequest, this.IsRetriedWriteRequest); - } - if (this.RetriableWriteRequestStartTimestamp != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, this.RetriableWriteRequestStartTimestamp); - } - if (this.AddResourcePropertiesToResponse != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, this.AddResourcePropertiesToResponse); - } - if (this.ChangeFeedStartFullFidelityIfNoneMatch != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, this.ChangeFeedStartFullFidelityIfNoneMatch); - } - if (this.SystemRestoreOperation != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SystemRestoreOperation, this.SystemRestoreOperation); - } - if (this.SkipRefreshDatabaseAccountConfigs != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, this.SkipRefreshDatabaseAccountConfigs); - } - if (this.IntendedCollectionRid != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IntendedCollectionRid, this.IntendedCollectionRid); - } - if (this.UseArchivalPartition != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.UseArchivalPartition, this.UseArchivalPartition); - } - if (this.PopulateUniqueIndexReIndexProgress != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, this.PopulateUniqueIndexReIndexProgress); - } - if (this.SchemaId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaId, this.SchemaId); - } - if (this.CollectionTruncate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionTruncate, this.CollectionTruncate); - } - if (this.SDKSupportedCapabilities != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SDKSupportedCapabilities, this.SDKSupportedCapabilities); - } - if (this.IsMaterializedViewBuild != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMaterializedViewBuild, this.IsMaterializedViewBuild); - } - if (this.BuilderClientIdentifier != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.BuilderClientIdentifier, this.BuilderClientIdentifier); - } - if (this.SourceCollectionIfMatch != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SourceCollectionIfMatch, this.SourceCollectionIfMatch); - } - if (this.RequestedCollectionType != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RequestedCollectionType, this.RequestedCollectionType); - } - if (this.PopulateIndexMetrics != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateIndexMetrics, this.PopulateIndexMetrics); - } - if (this.PopulateAnalyticalMigrationProgress != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, this.PopulateAnalyticalMigrationProgress); - } - if (this.ShouldReturnCurrentServerDateTime != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, this.ShouldReturnCurrentServerDateTime); - } - if (this.RbacUserId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacUserId, this.RbacUserId); - } - if (this.RbacAction != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacAction, this.RbacAction); - } - if (this.RbacResource != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacResource, this.RbacResource); - } - if (this.CorrelatedActivityId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CorrelatedActivityId, this.CorrelatedActivityId); - } - if (this.IsThroughputCapRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsThroughputCapRequest, this.IsThroughputCapRequest); - } - if (this.ChangeFeedWireFormatVersion != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, this.ChangeFeedWireFormatVersion); - } - if (this.PopulateByokEncryptionProgress != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, this.PopulateByokEncryptionProgress); - } - if (this.UseUserBackgroundBudget != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.UseUserBackgroundBudget, this.UseUserBackgroundBudget); - } - if (this.IncludePhysicalPartitionThroughputInfo != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, this.IncludePhysicalPartitionThroughputInfo); - } - if (this.IsServerlessStorageRefreshRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, this.IsServerlessStorageRefreshRequest); - } - if (this.UpdateOfferStateToPending != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateOfferStateToPending, this.UpdateOfferStateToPending); - } - if (this.PopulateOldestActiveSchemaId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, this.PopulateOldestActiveSchemaId); - } - if (this.IsInternalServerlessRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsInternalServerlessRequest, this.IsInternalServerlessRequest); - } - if (this.OfferReplaceRURedistribution != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, this.OfferReplaceRURedistribution); - } - if (this.IsCassandraAlterTypeRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, this.IsCassandraAlterTypeRequest); - } - if (this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, this.IsMaterializedViewSourceSchemaReplaceBatchRequest); - } - if (this.ForceDatabaseAccountUpdate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, this.ForceDatabaseAccountUpdate); - } - if (this.PriorityLevel != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PriorityLevel, this.PriorityLevel); - } - if (this.AllowRestoreParamsUpdate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, this.AllowRestoreParamsUpdate); - } - if (this.PruneCollectionSchemas != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PruneCollectionSchemas, this.PruneCollectionSchemas); - } - if (this.PopulateIndexMetricsV2 != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, this.PopulateIndexMetricsV2); - } - if (this.IsMigratedFixedCollection != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMigratedFixedCollection, this.IsMigratedFixedCollection); - } - if (this.SupportedSerializationFormats != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportedSerializationFormats, this.SupportedSerializationFormats); - } - if (this.UpdateOfferStateToRestorePending != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, this.UpdateOfferStateToRestorePending); - } - if (this.SetMasterResourcesDeletionPending != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, this.SetMasterResourcesDeletionPending); - } - if (this.HighPriorityForcedBackup != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.HighPriorityForcedBackup, this.HighPriorityForcedBackup); - } - if (this.OptimisticDirectExecute != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.OptimisticDirectExecute, this.OptimisticDirectExecute); - } - if (this.PopulateMinGLSNForDocumentOperations != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, this.PopulateMinGLSNForDocumentOperations); - } - if (this.PopulateHighestTentativeWriteLLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, this.PopulateHighestTentativeWriteLLSN); - } - if (this.PopulateCapacityType != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCapacityType, this.PopulateCapacityType); - } - if (this.TraceParent != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceParent, this.TraceParent); - } - if (this.TraceState != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceState, this.TraceState); - } - if (this.EnableConflictResolutionPolicyUpdate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, this.EnableConflictResolutionPolicyUpdate); - } - if (this.ClientIpAddress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ClientIpAddress, this.ClientIpAddress); - } - if (this.IsRequestNotAuthorized != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRequestNotAuthorized, this.IsRequestNotAuthorized); - } - if (this.AllowDocumentReadsInOfflineRegion != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, this.AllowDocumentReadsInOfflineRegion); - } - if (this.PopulateCurrentPartitionThroughputInfo != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, this.PopulateCurrentPartitionThroughputInfo); - } - if (this.IfMatch != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfMatch, this.IfMatch); - } - if (this.NoRetryOn449StatusCode != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, this.NoRetryOn449StatusCode); - } - if (this.SkipAdjustThroughputFractionsForOfferReplace != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, this.SkipAdjustThroughputFractionsForOfferReplace); - } - if (this.SqlQueryForPartitionKeyExtraction != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, this.SqlQueryForPartitionKeyExtraction); - } - if (this.EnableCrossPartitionQuery != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, this.EnableCrossPartitionQuery); - } - if (this.IsContinuationExpected != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsContinuationExpected, this.IsContinuationExpected); - } - if (this.ParallelizeCrossPartitionQuery != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, this.ParallelizeCrossPartitionQuery); - } - if (this.SupportedQueryFeatures != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportedQueryFeatures, this.SupportedQueryFeatures); - } - if (this.QueryVersion != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.QueryVersion, this.QueryVersion); - } - if (this.ActivityId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); - } - if (this.notCommonHeaders != null) - { - foreach (KeyValuePair keyValuePair in this.notCommonHeaders) - { - this.nameValueCollection.Add(keyValuePair.Key, keyValuePair.Value); - } - } - } - } - } - - return this.nameValueCollection; - } - - public void Remove(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - this.UpdateHelper( - key: key, - value: null, - throwIfAlreadyExists: false, - ignoreNotCommonHeaders: false); - } - - public string Get(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - switch (key.Length) - { - case 4: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.HttpDate, key)) - { - return this.HttpDate; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.A_IM, key)) - { - return this.A_IM; - } - if (string.Equals(HttpConstants.HttpHeaders.HttpDate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.HttpDate; - } - - if (string.Equals(HttpConstants.HttpHeaders.A_IM, key, StringComparison.OrdinalIgnoreCase)) - { - return this.A_IM; - } - - break; - case 6: - if (string.Equals(HttpConstants.HttpHeaders.Prefer, key, StringComparison.OrdinalIgnoreCase)) - { - return this.Prefer; - } - - break; - case 8: - if (string.Equals(HttpConstants.HttpHeaders.IfMatch, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IfMatch; - } - - break; - case 9: - if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.XDate; - } - - break; - case 10: - if (string.Equals(HttpConstants.HttpHeaders.TraceState, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TraceState; - } - - break; - case 11: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) - { - return this.EndId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) - { - return this.TraceParent; - } - if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EndId; - } - - if (string.Equals(HttpConstants.HttpHeaders.TraceParent, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TraceParent; - } - - break; - case 12: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Version, key)) - { - return this.Version; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndEpk, key)) - { - return this.EndEpk; - } - if (string.Equals(HttpConstants.HttpHeaders.Version, key, StringComparison.OrdinalIgnoreCase)) - { - return this.Version; - } - - if (string.Equals(HttpConstants.HttpHeaders.EndEpk, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EndEpk; - } - - break; - case 13: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Authorization, key)) - { - return this.Authorization; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfNoneMatch, key)) - { - return this.IfNoneMatch; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartId, key)) - { - return this.StartId; - } - if (string.Equals(HttpConstants.HttpHeaders.Authorization, key, StringComparison.OrdinalIgnoreCase)) - { - return this.Authorization; - } - - if (string.Equals(HttpConstants.HttpHeaders.IfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IfNoneMatch; - } - - if (string.Equals(HttpConstants.HttpHeaders.StartId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.StartId; - } - - break; - case 14: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanCharge, key)) - { - return this.CanCharge; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryId, key)) - { - return this.BinaryId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartEpk, key)) - { - return this.StartEpk; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaId, key)) - { - return this.SchemaId; - } - if (string.Equals(HttpConstants.HttpHeaders.CanCharge, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CanCharge; - } - - if (string.Equals(WFConstants.BackendHeaders.BinaryId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.BinaryId; - } - - if (string.Equals(HttpConstants.HttpHeaders.StartEpk, key, StringComparison.OrdinalIgnoreCase)) - { - return this.StartEpk; - } - - if (string.Equals(WFConstants.BackendHeaders.SchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SchemaId; - } - - break; - case 15: - if (string.Equals(HttpConstants.HttpHeaders.TargetLsn, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TargetLsn; - } - - break; - case 16: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanThrottle, key)) - { - return this.CanThrottle; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaHash, key)) - { - return this.SchemaHash; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacAction, key)) - { - return this.RbacAction; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key)) - { - return this.NoRetryOn449StatusCode; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) - { - return this.ActivityId; - } - if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CanThrottle; - } - - if (string.Equals(WFConstants.BackendHeaders.SchemaHash, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SchemaHash; - } - - if (string.Equals(HttpConstants.HttpHeaders.RbacAction, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RbacAction; - } - - if (string.Equals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key, StringComparison.OrdinalIgnoreCase)) - { - return this.NoRetryOn449StatusCode; - } - - if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ActivityId; - } - - break; - case 17: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) - { - return this.Continuation; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.EntityId, key)) - { - return this.EntityId; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BindReplicaDirective, key)) - { - return this.BindReplicaDirective; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfModifiedSince, key)) - { - return this.IfModifiedSince; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionId, key)) - { - return this.TransactionId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacUserId, key)) - { - return this.RbacUserId; - } - if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) - { - return this.Continuation; - } - - if (string.Equals(WFConstants.BackendHeaders.EntityId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EntityId; - } - - if (string.Equals(WFConstants.BackendHeaders.BindReplicaDirective, key, StringComparison.OrdinalIgnoreCase)) - { - return this.BindReplicaDirective; - } - - if (string.Equals(HttpConstants.HttpHeaders.IfModifiedSince, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IfModifiedSince; - } - - if (string.Equals(WFConstants.BackendHeaders.TransactionId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TransactionId; - } - - if (string.Equals(HttpConstants.HttpHeaders.RbacUserId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RbacUserId; - } - - break; - case 18: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) - { - return this.SessionToken; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key)) - { - return this.IsAutoScaleRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ReadFeedKeyType, key)) - { - return this.ReadFeedKeyType; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacResource, key)) - { - return this.RbacResource; - } - if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SessionToken; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsAutoScaleRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.ReadFeedKeyType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ReadFeedKeyType; - } - - if (string.Equals(HttpConstants.HttpHeaders.RbacResource, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RbacResource; - } - - break; - case 19: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) - { - return this.ResourceId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PageSize, key)) - { - return this.PageSize; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreParams, key)) - { - return this.RestoreParams; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionFirstRequest, key)) - { - return this.TransactionFirstRequest; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResourceId; - } - - if (string.Equals(HttpConstants.HttpHeaders.PageSize, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PageSize; - } - - if (string.Equals(WFConstants.BackendHeaders.RestoreParams, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RestoreParams; - } - - if (string.Equals(WFConstants.BackendHeaders.TransactionFirstRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TransactionFirstRequest; - } - - break; - case 20: - if (string.Equals(HttpConstants.HttpHeaders.ProfileRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ProfileRequest; - } - - break; - case 21: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) - { - return this.ShareThroughput; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaOwnerRid, key)) - { - return this.SchemaOwnerRid; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionCommit, key)) - { - return this.TransactionCommit; - } - if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ShareThroughput; - } - - if (string.Equals(WFConstants.BackendHeaders.SchemaOwnerRid, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SchemaOwnerRid; - } - - if (string.Equals(WFConstants.BackendHeaders.TransactionCommit, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TransactionCommit; - } - - break; - case 22: - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsFanoutRequest, key)) - { - return this.IsFanoutRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConsistencyLevel, key)) - { - return this.ConsistencyLevel; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.GatewaySignature, key)) - { - return this.GatewaySignature; - } - if (string.Equals(WFConstants.BackendHeaders.IsFanoutRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsFanoutRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.ConsistencyLevel, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ConsistencyLevel; - } - - if (string.Equals(HttpConstants.HttpHeaders.GatewaySignature, key, StringComparison.OrdinalIgnoreCase)) - { - return this.GatewaySignature; - } - - break; - case 23: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IndexingDirective, key)) - { - return this.IndexingDirective; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryMasterKey, key)) - { - return this.PrimaryMasterKey; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsReadOnlyScript, key)) - { - return this.IsReadOnlyScript; - } - if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IndexingDirective; - } - - if (string.Equals(WFConstants.BackendHeaders.PrimaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PrimaryMasterKey; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsReadOnlyScript, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsReadOnlyScript; - } - - break; - case 24: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) - { - return this.CollectionServiceIndex; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RemoteStorageType, key)) - { - return this.RemoteStorageType; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchAtomic, key)) - { - return this.IsBatchAtomic; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionServiceIndex; - } - - if (string.Equals(WFConstants.BackendHeaders.RemoteStorageType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RemoteStorageType; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsBatchAtomic, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsBatchAtomic; - } - - break; - case 25: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceSchemaName, key)) - { - return this.ResourceSchemaName; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryMasterKey, key)) - { - return this.SecondaryMasterKey; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key)) - { - return this.PrimaryReadonlyKey; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) - { - return this.TransportRequestID; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchOrdered, key)) - { - return this.IsBatchOrdered; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceTypes, key)) - { - return this.ResourceTypes; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) - { - return this.QueryVersion; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResourceSchemaName; - } - - if (string.Equals(WFConstants.BackendHeaders.SecondaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SecondaryMasterKey; - } - - if (string.Equals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PrimaryReadonlyKey; - } - - if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TransportRequestID; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsBatchOrdered, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsBatchOrdered; - } - - if (string.Equals(WFConstants.BackendHeaders.ResourceTypes, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResourceTypes; - } - - if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) - { - return this.QueryVersion; - } - - break; - case 26: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) - { - return this.CollectionPartitionIndex; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnumerationDirection, key)) - { - return this.EnumerationDirection; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RequestedCollectionType, key)) - { - return this.RequestedCollectionType; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PriorityLevel, key)) - { - return this.PriorityLevel; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionPartitionIndex; - } - - if (string.Equals(HttpConstants.HttpHeaders.EnumerationDirection, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnumerationDirection; - } - - if (string.Equals(WFConstants.BackendHeaders.RequestedCollectionType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RequestedCollectionType; - } - - if (string.Equals(HttpConstants.HttpHeaders.PriorityLevel, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PriorityLevel; - } - - break; - case 27: - if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key)) - { - return this.SecondaryReadonlyKey; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.FanoutOperationState, key)) - { - return this.FanoutOperationState; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MergeStaticId, key)) - { - return this.MergeStaticId; - } - if (string.Equals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SecondaryReadonlyKey; - } - - if (string.Equals(WFConstants.BackendHeaders.FanoutOperationState, key, StringComparison.OrdinalIgnoreCase)) - { - return this.FanoutOperationState; - } - - if (string.Equals(HttpConstants.HttpHeaders.MergeStaticId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MergeStaticId; - } - - break; - case 28: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKey, key)) - { - return this.PartitionKey; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key)) - { - return this.RestoreMetadataFilter; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key)) - { - return this.TimeToLiveInSeconds; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.EffectivePartitionKey, key)) - { - return this.EffectivePartitionKey; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UseSystemBudget, key)) - { - return this.UseSystemBudget; - } - if (string.Equals(HttpConstants.HttpHeaders.PartitionKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionKey; - } - - if (string.Equals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RestoreMetadataFilter; - } - - if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TimeToLiveInSeconds; - } - - if (string.Equals(WFConstants.BackendHeaders.EffectivePartitionKey, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EffectivePartitionKey; - } - - if (string.Equals(WFConstants.BackendHeaders.UseSystemBudget, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UseSystemBudget; - } - - break; - case 29: - if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ClientIpAddress; - } - - break; - case 30: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) - { - return this.ResourceTokenExpiry; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionCount, key)) - { - return this.PartitionCount; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionRid, key)) - { - return this.CollectionRid; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionResourceFilter, key)) - { - return this.PartitionResourceFilter; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ExcludeSystemProperties, key)) - { - return this.ExcludeSystemProperties; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key)) - { - return this.IsCassandraAlterTypeRequest; - } - if (string.Equals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResourceTokenExpiry; - } - - if (string.Equals(HttpConstants.HttpHeaders.PartitionCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionCount; - } - - if (string.Equals(WFConstants.BackendHeaders.CollectionRid, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionRid; - } - - if (string.Equals(WFConstants.BackendHeaders.PartitionResourceFilter, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionResourceFilter; - } - - if (string.Equals(WFConstants.BackendHeaders.ExcludeSystemProperties, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ExcludeSystemProperties; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsCassandraAlterTypeRequest; - } - - break; - case 31: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key)) - { - return this.ClientRetryAttemptCount; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key)) - { - return this.CanOfferReplaceComplete; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key)) - { - return this.BinaryPassthroughRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsClientEncrypted, key)) - { - return this.IsClientEncrypted; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemDocumentType, key)) - { - return this.SystemDocumentType; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionTruncate, key)) - { - return this.CollectionTruncate; - } - if (string.Equals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ClientRetryAttemptCount; - } - - if (string.Equals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CanOfferReplaceComplete; - } - - if (string.Equals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.BinaryPassthroughRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsClientEncrypted, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsClientEncrypted; - } - - if (string.Equals(HttpConstants.HttpHeaders.SystemDocumentType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SystemDocumentType; - } - - if (string.Equals(HttpConstants.HttpHeaders.CollectionTruncate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionTruncate; - } - - break; - case 32: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key)) - { - return this.MigrateCollectionDirective; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key)) - { - return this.TargetGlobalCommittedLsn; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceQueryScan, key)) - { - return this.ForceQueryScan; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key)) - { - return this.MaxPollingIntervalMilliseconds; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key)) - { - return this.PopulateIndexMetrics; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MigrateCollectionDirective; - } - - if (string.Equals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TargetGlobalCommittedLsn; - } - - if (string.Equals(HttpConstants.HttpHeaders.ForceQueryScan, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ForceQueryScan; - } - - if (string.Equals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MaxPollingIntervalMilliseconds; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateIndexMetrics; - } - - break; - case 33: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableScanInQuery, key)) - { - return this.EnableScanInQuery; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key)) - { - return this.EmitVerboseTracesInQuery; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key)) - { - return this.PopulateQuotaInfo; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreserveFullContent, key)) - { - return this.PreserveFullContent; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key)) - { - return this.PopulateLogStoreInfo; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CorrelatedActivityId, key)) - { - return this.CorrelatedActivityId; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableScanInQuery, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableScanInQuery; - } - - if (string.Equals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EmitVerboseTracesInQuery; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateQuotaInfo; - } - - if (string.Equals(HttpConstants.HttpHeaders.PreserveFullContent, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PreserveFullContent; - } - - if (string.Equals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateLogStoreInfo; - } - - if (string.Equals(HttpConstants.HttpHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CorrelatedActivityId; - } - - break; - case 34: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowTentativeWrites, key)) - { - return this.AllowTentativeWrites; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UseArchivalPartition, key)) - { - return this.UseArchivalPartition; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCapacityType, key)) - { - return this.PopulateCapacityType; - } - if (string.Equals(HttpConstants.HttpHeaders.AllowTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AllowTentativeWrites; - } - - if (string.Equals(HttpConstants.HttpHeaders.UseArchivalPartition, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UseArchivalPartition; - } - - if (string.Equals(WFConstants.BackendHeaders.PopulateCapacityType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateCapacityType; - } - - break; - case 35: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerInclude, key)) - { - return this.PreTriggerInclude; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerExclude, key)) - { - return this.PreTriggerExclude; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key)) - { - return this.PartitionKeyRangeId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key)) - { - return this.FilterBySchemaResourceId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key)) - { - return this.CollectionRemoteStorageSecurityIdentifier; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key)) - { - return this.RemainingTimeInMsOnClientRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key)) - { - return this.ShouldBatchContinueOnError; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IntendedCollectionRid, key)) - { - return this.IntendedCollectionRid; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key)) - { - return this.PopulateIndexMetricsV2; - } - if (string.Equals(HttpConstants.HttpHeaders.PreTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PreTriggerInclude; - } - - if (string.Equals(HttpConstants.HttpHeaders.PreTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PreTriggerExclude; - } - - if (string.Equals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionKeyRangeId; - } - - if (string.Equals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.FilterBySchemaResourceId; - } - - if (string.Equals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionRemoteStorageSecurityIdentifier; - } - - if (string.Equals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RemainingTimeInMsOnClientRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ShouldBatchContinueOnError; - } - - if (string.Equals(WFConstants.BackendHeaders.IntendedCollectionRid, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IntendedCollectionRid; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateIndexMetricsV2; - } - - break; - case 36: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerInclude, key)) - { - return this.PostTriggerInclude; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerExclude, key)) - { - return this.PostTriggerExclude; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key)) - { - return this.PopulateQueryMetrics; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsUserRequest, key)) - { - return this.IsUserRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key)) - { - return this.IncludeTentativeWrites; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key)) - { - return this.IsRetriedWriteRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key)) - { - return this.PruneCollectionSchemas; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) - { - return this.SupportedQueryFeatures; - } - if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PostTriggerInclude; - } - - if (string.Equals(HttpConstants.HttpHeaders.PostTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PostTriggerExclude; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateQueryMetrics; - } - - if (string.Equals(WFConstants.BackendHeaders.IsUserRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsUserRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IncludeTentativeWrites; - } - - if (string.Equals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsRetriedWriteRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PruneCollectionSchemas; - } - - if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SupportedQueryFeatures; - } - - break; - case 37: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) - { - return this.EnableLogging; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateResourceCount, key)) - { - return this.PopulateResourceCount; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key)) - { - return this.SDKSupportedCapabilities; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key)) - { - return this.BuilderClientIdentifier; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) - { - return this.IsRequestNotAuthorized; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableLogging; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateResourceCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateResourceCount; - } - - if (string.Equals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SDKSupportedCapabilities; - } - - if (string.Equals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - return this.BuilderClientIdentifier; - } - - if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsRequestNotAuthorized; - } - - break; - case 38: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) - { - return this.MigrateOfferToAutopilot; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestId, key)) - { - return this.RetriableWriteRequestId; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key)) - { - return this.SourceCollectionIfMatch; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key)) - { - return this.UseUserBackgroundBudget; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MigrateOfferToAutopilot; - } - - if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RetriableWriteRequestId; - } - - if (string.Equals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SourceCollectionIfMatch; - } - - if (string.Equals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UseUserBackgroundBudget; - } - - break; - case 39: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key)) - { - return this.TruncateMergeLogRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key)) - { - return this.IsInternalServerlessRequest; - } - if (string.Equals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TruncateMergeLogRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsInternalServerlessRequest; - } - - break; - case 40: - if (object.ReferenceEquals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key)) - { - return this.EnableDynamicRidRangeAllocation; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key)) - { - return this.UniqueIndexReIndexingState; - } - if (string.Equals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableDynamicRidRangeAllocation; - } - - if (string.Equals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UniqueIndexReIndexingState; - } - - break; - case 41: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key)) - { - return this.ForceDatabaseAccountUpdate; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key)) - { - return this.OptimisticDirectExecute; - } - if (string.Equals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ForceDatabaseAccountUpdate; - } - - if (string.Equals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OptimisticDirectExecute; - } - - break; - case 42: - if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key)) - { - return this.MergeCheckPointGLSN; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key)) - { - return this.ShouldReturnCurrentServerDateTime; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key)) - { - return this.ChangeFeedWireFormatVersion; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) - { - return this.EnableCrossPartitionQuery; - } - if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MergeCheckPointGLSN; - } - - if (string.Equals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ShouldReturnCurrentServerDateTime; - } - - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ChangeFeedWireFormatVersion; - } - - if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableCrossPartitionQuery; - } - - break; - case 43: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) - { - return this.DisableRUPerMinuteUsage; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key)) - { - return this.PopulatePartitionStatistics; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key)) - { - return this.ForceSideBySideIndexMigration; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key)) - { - return this.UniqueIndexNameEncodingMode; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key)) - { - return this.SupportedSerializationFormats; - } - if (string.Equals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key, StringComparison.OrdinalIgnoreCase)) - { - return this.DisableRUPerMinuteUsage; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulatePartitionStatistics; - } - - if (string.Equals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ForceSideBySideIndexMigration; - } - - if (string.Equals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UniqueIndexNameEncodingMode; - } - - if (string.Equals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SupportedSerializationFormats; - } - - break; - case 44: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ContentSerializationFormat, key)) - { - return this.ContentSerializationFormat; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key)) - { - return this.PopulateOldestActiveSchemaId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) - { - return this.IsContinuationExpected; - } - if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ContentSerializationFormat; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateOldestActiveSchemaId; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsContinuationExpected; - } - - break; - case 45: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) - { - return this.ChangeFeedStartFullFidelityIfNoneMatch; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemRestoreOperation, key)) - { - return this.SystemRestoreOperation; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key)) - { - return this.IsThroughputCapRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key)) - { - return this.PopulateByokEncryptionProgress; - } - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ChangeFeedStartFullFidelityIfNoneMatch; - } - - if (string.Equals(HttpConstants.HttpHeaders.SystemRestoreOperation, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SystemRestoreOperation; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsThroughputCapRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateByokEncryptionProgress; - } - - break; - case 46: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key)) - { - return this.MigrateOfferToManualThroughput; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key)) - { - return this.SkipRefreshDatabaseAccountConfigs; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key)) - { - return this.IsMigratedFixedCollection; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MigrateOfferToManualThroughput; - } - - if (string.Equals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SkipRefreshDatabaseAccountConfigs; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsMigratedFixedCollection; - } - - break; - case 47: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key)) - { - return this.SupportSpatialLegacyCoordinates; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key)) - { - return this.CollectionChildResourceNameLimitInBytes; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key)) - { - return this.AddResourcePropertiesToResponse; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key)) - { - return this.IsMaterializedViewBuild; - } - if (string.Equals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SupportSpatialLegacyCoordinates; - } - - if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionChildResourceNameLimitInBytes; - } - - if (string.Equals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AddResourcePropertiesToResponse; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsMaterializedViewBuild; - } - - break; - case 48: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key)) - { - return this.PopulateCollectionThroughputInfo; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key)) - { - return this.GetAllPartitionKeyStatistics; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key)) - { - return this.PopulateUniqueIndexReIndexProgress; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key)) - { - return this.AllowRestoreParamsUpdate; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key)) - { - return this.HighPriorityForcedBackup; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateCollectionThroughputInfo; - } - - if (string.Equals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key, StringComparison.OrdinalIgnoreCase)) - { - return this.GetAllPartitionKeyStatistics; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateUniqueIndexReIndexProgress; - } - - if (string.Equals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AllowRestoreParamsUpdate; - } - - if (string.Equals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key, StringComparison.OrdinalIgnoreCase)) - { - return this.HighPriorityForcedBackup; - } - - break; - case 49: - if (string.Equals(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UsePolygonsSmallerThanAHemisphere; - } - - break; - case 50: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key)) - { - return this.ResponseContinuationTokenLimitInKB; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key)) - { - return this.PopulateAnalyticalMigrationProgress; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key)) - { - return this.UpdateOfferStateToPending; - } - if (string.Equals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResponseContinuationTokenLimitInKB; - } - - if (string.Equals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateAnalyticalMigrationProgress; - } - - if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UpdateOfferStateToPending; - } - - break; - case 51: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key)) - { - return this.EnableLowPrecisionOrderBy; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key)) - { - return this.RetriableWriteRequestStartTimestamp; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableLowPrecisionOrderBy; - } - - if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RetriableWriteRequestStartTimestamp; - } - - break; - case 52: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) - { - return this.OfferReplaceRURedistribution; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) - { - return this.ParallelizeCrossPartitionQuery; - } - if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OfferReplaceRURedistribution; - } - - if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ParallelizeCrossPartitionQuery; - } - - break; - case 53: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) - { - return this.IsRUPerGBEnforcementRequest; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key)) - { - return this.IsOfferStorageRefreshRequest; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key)) - { - return this.PopulateMinGLSNForDocumentOperations; - } - if (string.Equals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsRUPerGBEnforcementRequest; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsOfferStorageRefreshRequest; - } - - if (string.Equals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateMinGLSNForDocumentOperations; - } - - break; - case 54: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key)) - { - return this.IncludePhysicalPartitionThroughputInfo; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key)) - { - return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) - { - return this.PopulateCurrentPartitionThroughputInfo; - } - if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IncludePhysicalPartitionThroughputInfo; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; - } - - if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateCurrentPartitionThroughputInfo; - } - - break; - case 55: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) - { - return this.UpdateOfferStateToRestorePending; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) - { - return this.SqlQueryForPartitionKeyExtraction; - } - if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UpdateOfferStateToRestorePending; - } - - if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SqlQueryForPartitionKeyExtraction; - } - - break; - case 56: - if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionChildResourceContentLimitInKB; - } - - break; - case 57: - if (string.Equals(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateUnflushedMergeEntryCount; - } - - break; - case 58: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key)) - { - return this.IgnoreSystemLoweringMaxThroughput; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key)) - { - return this.SetMasterResourcesDeletionPending; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key)) - { - return this.PopulateHighestTentativeWriteLLSN; - } - if (string.Equals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IgnoreSystemLoweringMaxThroughput; - } - - if (string.Equals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SetMasterResourcesDeletionPending; - } - - if (string.Equals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PopulateHighestTentativeWriteLLSN; - } - - break; - case 59: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) - { - return this.UpdateMaxThroughputEverProvisioned; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) - { - return this.EnableConflictResolutionPolicyUpdate; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) - { - return this.AllowDocumentReadsInOfflineRegion; - } - if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UpdateMaxThroughputEverProvisioned; - } - - if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.EnableConflictResolutionPolicyUpdate; - } - - if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AllowDocumentReadsInOfflineRegion; - } - - break; - case 61: - if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsServerlessStorageRefreshRequest; - } - - break; - case 62: - if (string.Equals(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SkipAdjustThroughputFractionsForOfferReplace; - } - - break; - default: - break; - } - - if (this.notCommonHeaders != null - && this.notCommonHeaders.TryGetValue(key, out string value)) - { - return value; - } - - return null; - } - - public void Add(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.UpdateHelper( - key: key, - value: value, - throwIfAlreadyExists: true, - ignoreNotCommonHeaders: false); - } - - public void Set(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - this.UpdateHelper( - key: key, - value: value, - throwIfAlreadyExists: false, - ignoreNotCommonHeaders: false); - } - - public void UpdateHelper( - string key, - string value, - bool throwIfAlreadyExists, - bool ignoreNotCommonHeaders) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - switch (key.Length) - { - case 4: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.HttpDate, key)) - { - if (throwIfAlreadyExists && this.HttpDate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HttpDate = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.A_IM, key)) - { - if (throwIfAlreadyExists && this.A_IM != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.A_IM = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.HttpDate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.HttpDate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HttpDate = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.A_IM, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.A_IM != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.A_IM = value; - return; - } - break; - case 6: - if (string.Equals(HttpConstants.HttpHeaders.Prefer, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.Prefer != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Prefer = value; - return; - } - break; - case 8: - if (string.Equals(HttpConstants.HttpHeaders.IfMatch, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IfMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IfMatch = value; - return; - } - break; - case 9: - if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.XDate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.XDate = value; - return; - } - break; - case 10: - if (string.Equals(HttpConstants.HttpHeaders.TraceState, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TraceState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TraceState = value; - return; - } - break; - case 11: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) - { - if (throwIfAlreadyExists && this.EndId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EndId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) - { - if (throwIfAlreadyExists && this.TraceParent != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TraceParent = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EndId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EndId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TraceParent, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TraceParent != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TraceParent = value; - return; - } - break; - case 12: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Version, key)) - { - if (throwIfAlreadyExists && this.Version != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Version = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndEpk, key)) - { - if (throwIfAlreadyExists && this.EndEpk != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EndEpk = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.Version, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.Version != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Version = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EndEpk, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EndEpk != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EndEpk = value; - return; - } - break; - case 13: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Authorization, key)) - { - if (throwIfAlreadyExists && this.Authorization != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Authorization = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfNoneMatch, key)) - { - if (throwIfAlreadyExists && this.IfNoneMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IfNoneMatch = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartId, key)) - { - if (throwIfAlreadyExists && this.StartId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.StartId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.Authorization, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.Authorization != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Authorization = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IfNoneMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IfNoneMatch = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.StartId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.StartId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.StartId = value; - return; - } - break; - case 14: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanCharge, key)) - { - if (throwIfAlreadyExists && this.CanCharge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanCharge = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryId, key)) - { - if (throwIfAlreadyExists && this.BinaryId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BinaryId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartEpk, key)) - { - if (throwIfAlreadyExists && this.StartEpk != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.StartEpk = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaId, key)) - { - if (throwIfAlreadyExists && this.SchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CanCharge, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CanCharge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanCharge = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.BinaryId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.BinaryId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BinaryId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.StartEpk, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.StartEpk != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.StartEpk = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaId = value; - return; - } - break; - case 15: - if (string.Equals(HttpConstants.HttpHeaders.TargetLsn, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TargetLsn != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TargetLsn = value; - return; - } - break; - case 16: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanThrottle, key)) - { - if (throwIfAlreadyExists && this.CanThrottle != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanThrottle = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaHash, key)) - { - if (throwIfAlreadyExists && this.SchemaHash != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaHash = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacAction, key)) - { - if (throwIfAlreadyExists && this.RbacAction != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacAction = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key)) - { - if (throwIfAlreadyExists && this.NoRetryOn449StatusCode != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.NoRetryOn449StatusCode = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) - { - if (throwIfAlreadyExists && this.ActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ActivityId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CanThrottle != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanThrottle = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SchemaHash, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SchemaHash != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaHash = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RbacAction, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RbacAction != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacAction = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.NoRetryOn449StatusCode != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.NoRetryOn449StatusCode = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ActivityId = value; - return; - } - break; - case 17: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) - { - if (throwIfAlreadyExists && this.Continuation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Continuation = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.EntityId, key)) - { - if (throwIfAlreadyExists && this.EntityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EntityId = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BindReplicaDirective, key)) - { - if (throwIfAlreadyExists && this.BindReplicaDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BindReplicaDirective = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfModifiedSince, key)) - { - if (throwIfAlreadyExists && this.IfModifiedSince != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IfModifiedSince = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionId, key)) - { - if (throwIfAlreadyExists && this.TransactionId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacUserId, key)) - { - if (throwIfAlreadyExists && this.RbacUserId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacUserId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.Continuation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Continuation = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.EntityId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EntityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EntityId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.BindReplicaDirective, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.BindReplicaDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BindReplicaDirective = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IfModifiedSince, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IfModifiedSince != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IfModifiedSince = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.TransactionId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TransactionId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RbacUserId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RbacUserId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacUserId = value; - return; - } - break; - case 18: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) - { - if (throwIfAlreadyExists && this.SessionToken != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SessionToken = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key)) - { - if (throwIfAlreadyExists && this.IsAutoScaleRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsAutoScaleRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ReadFeedKeyType, key)) - { - if (throwIfAlreadyExists && this.ReadFeedKeyType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReadFeedKeyType = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacResource, key)) - { - if (throwIfAlreadyExists && this.RbacResource != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacResource = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SessionToken != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SessionToken = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsAutoScaleRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsAutoScaleRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ReadFeedKeyType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ReadFeedKeyType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReadFeedKeyType = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RbacResource, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RbacResource != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RbacResource = value; - return; - } - break; - case 19: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) - { - if (throwIfAlreadyExists && this.ResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PageSize, key)) - { - if (throwIfAlreadyExists && this.PageSize != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PageSize = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreParams, key)) - { - if (throwIfAlreadyExists && this.RestoreParams != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreParams = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionFirstRequest, key)) - { - if (throwIfAlreadyExists && this.TransactionFirstRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionFirstRequest = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PageSize, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PageSize != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PageSize = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RestoreParams, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RestoreParams != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreParams = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.TransactionFirstRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TransactionFirstRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionFirstRequest = value; - return; - } - break; - case 20: - if (string.Equals(HttpConstants.HttpHeaders.ProfileRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ProfileRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ProfileRequest = value; - return; - } - break; - case 21: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) - { - if (throwIfAlreadyExists && this.ShareThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShareThroughput = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaOwnerRid, key)) - { - if (throwIfAlreadyExists && this.SchemaOwnerRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaOwnerRid = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionCommit, key)) - { - if (throwIfAlreadyExists && this.TransactionCommit != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionCommit = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ShareThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShareThroughput = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SchemaOwnerRid, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SchemaOwnerRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaOwnerRid = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.TransactionCommit, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TransactionCommit != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransactionCommit = value; - return; - } - break; - case 22: - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsFanoutRequest, key)) - { - if (throwIfAlreadyExists && this.IsFanoutRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsFanoutRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConsistencyLevel, key)) - { - if (throwIfAlreadyExists && this.ConsistencyLevel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ConsistencyLevel = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.GatewaySignature, key)) - { - if (throwIfAlreadyExists && this.GatewaySignature != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GatewaySignature = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IsFanoutRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsFanoutRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsFanoutRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ConsistencyLevel, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ConsistencyLevel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ConsistencyLevel = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.GatewaySignature, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.GatewaySignature != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GatewaySignature = value; - return; - } - break; - case 23: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IndexingDirective, key)) - { - if (throwIfAlreadyExists && this.IndexingDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IndexingDirective = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryMasterKey, key)) - { - if (throwIfAlreadyExists && this.PrimaryMasterKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PrimaryMasterKey = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsReadOnlyScript, key)) - { - if (throwIfAlreadyExists && this.IsReadOnlyScript != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsReadOnlyScript = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IndexingDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IndexingDirective = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PrimaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PrimaryMasterKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PrimaryMasterKey = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsReadOnlyScript, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsReadOnlyScript != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsReadOnlyScript = value; - return; - } - break; - case 24: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) - { - if (throwIfAlreadyExists && this.CollectionServiceIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionServiceIndex = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RemoteStorageType, key)) - { - if (throwIfAlreadyExists && this.RemoteStorageType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RemoteStorageType = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchAtomic, key)) - { - if (throwIfAlreadyExists && this.IsBatchAtomic != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsBatchAtomic = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionServiceIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionServiceIndex = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RemoteStorageType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RemoteStorageType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RemoteStorageType = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsBatchAtomic, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsBatchAtomic != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsBatchAtomic = value; - return; - } - break; - case 25: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceSchemaName, key)) - { - if (throwIfAlreadyExists && this.ResourceSchemaName != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceSchemaName = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryMasterKey, key)) - { - if (throwIfAlreadyExists && this.SecondaryMasterKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SecondaryMasterKey = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key)) - { - if (throwIfAlreadyExists && this.PrimaryReadonlyKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PrimaryReadonlyKey = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) - { - if (throwIfAlreadyExists && this.TransportRequestID != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransportRequestID = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchOrdered, key)) - { - if (throwIfAlreadyExists && this.IsBatchOrdered != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsBatchOrdered = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceTypes, key)) - { - if (throwIfAlreadyExists && this.ResourceTypes != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceTypes = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) - { - if (throwIfAlreadyExists && this.QueryVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryVersion = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResourceSchemaName != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceSchemaName = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SecondaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SecondaryMasterKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SecondaryMasterKey = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PrimaryReadonlyKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PrimaryReadonlyKey = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TransportRequestID != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransportRequestID = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsBatchOrdered, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsBatchOrdered != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsBatchOrdered = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceTypes, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResourceTypes != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceTypes = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.QueryVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryVersion = value; - return; - } - break; - case 26: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) - { - if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionPartitionIndex = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnumerationDirection, key)) - { - if (throwIfAlreadyExists && this.EnumerationDirection != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnumerationDirection = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RequestedCollectionType, key)) - { - if (throwIfAlreadyExists && this.RequestedCollectionType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequestedCollectionType = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PriorityLevel, key)) - { - if (throwIfAlreadyExists && this.PriorityLevel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PriorityLevel = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionPartitionIndex = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnumerationDirection, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnumerationDirection != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnumerationDirection = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RequestedCollectionType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RequestedCollectionType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequestedCollectionType = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PriorityLevel, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PriorityLevel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PriorityLevel = value; - return; - } - break; - case 27: - if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key)) - { - if (throwIfAlreadyExists && this.SecondaryReadonlyKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SecondaryReadonlyKey = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.FanoutOperationState, key)) - { - if (throwIfAlreadyExists && this.FanoutOperationState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.FanoutOperationState = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MergeStaticId, key)) - { - if (throwIfAlreadyExists && this.MergeStaticId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeStaticId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SecondaryReadonlyKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SecondaryReadonlyKey = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.FanoutOperationState, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.FanoutOperationState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.FanoutOperationState = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MergeStaticId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MergeStaticId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeStaticId = value; - return; - } - break; - case 28: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKey, key)) - { - if (throwIfAlreadyExists && this.PartitionKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKey = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key)) - { - if (throwIfAlreadyExists && this.RestoreMetadataFilter != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreMetadataFilter = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key)) - { - if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TimeToLiveInSeconds = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.EffectivePartitionKey, key)) - { - if (throwIfAlreadyExists && this.EffectivePartitionKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EffectivePartitionKey = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UseSystemBudget, key)) - { - if (throwIfAlreadyExists && this.UseSystemBudget != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseSystemBudget = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PartitionKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKey = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RestoreMetadataFilter != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreMetadataFilter = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TimeToLiveInSeconds = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.EffectivePartitionKey, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EffectivePartitionKey != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EffectivePartitionKey = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.UseSystemBudget, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UseSystemBudget != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseSystemBudget = value; - return; - } - break; - case 29: - if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ClientIpAddress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ClientIpAddress = value; - return; - } - break; - case 30: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) - { - if (throwIfAlreadyExists && this.ResourceTokenExpiry != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceTokenExpiry = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionCount, key)) - { - if (throwIfAlreadyExists && this.PartitionCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionCount = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionRid, key)) - { - if (throwIfAlreadyExists && this.CollectionRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionRid = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionResourceFilter, key)) - { - if (throwIfAlreadyExists && this.PartitionResourceFilter != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionResourceFilter = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ExcludeSystemProperties, key)) - { - if (throwIfAlreadyExists && this.ExcludeSystemProperties != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ExcludeSystemProperties = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key)) - { - if (throwIfAlreadyExists && this.IsCassandraAlterTypeRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsCassandraAlterTypeRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResourceTokenExpiry != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceTokenExpiry = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PartitionCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionCount = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionRid, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionRid = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PartitionResourceFilter, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionResourceFilter != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionResourceFilter = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ExcludeSystemProperties, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ExcludeSystemProperties != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ExcludeSystemProperties = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsCassandraAlterTypeRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsCassandraAlterTypeRequest = value; - return; - } - break; - case 31: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key)) - { - if (throwIfAlreadyExists && this.ClientRetryAttemptCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ClientRetryAttemptCount = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key)) - { - if (throwIfAlreadyExists && this.CanOfferReplaceComplete != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanOfferReplaceComplete = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key)) - { - if (throwIfAlreadyExists && this.BinaryPassthroughRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BinaryPassthroughRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsClientEncrypted, key)) - { - if (throwIfAlreadyExists && this.IsClientEncrypted != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsClientEncrypted = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemDocumentType, key)) - { - if (throwIfAlreadyExists && this.SystemDocumentType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SystemDocumentType = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionTruncate, key)) - { - if (throwIfAlreadyExists && this.CollectionTruncate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionTruncate = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ClientRetryAttemptCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ClientRetryAttemptCount = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CanOfferReplaceComplete != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CanOfferReplaceComplete = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.BinaryPassthroughRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BinaryPassthroughRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsClientEncrypted, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsClientEncrypted != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsClientEncrypted = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SystemDocumentType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SystemDocumentType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SystemDocumentType = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CollectionTruncate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionTruncate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionTruncate = value; - return; - } - break; - case 32: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key)) - { - if (throwIfAlreadyExists && this.MigrateCollectionDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateCollectionDirective = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key)) - { - if (throwIfAlreadyExists && this.TargetGlobalCommittedLsn != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TargetGlobalCommittedLsn = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceQueryScan, key)) - { - if (throwIfAlreadyExists && this.ForceQueryScan != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceQueryScan = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key)) - { - if (throwIfAlreadyExists && this.MaxPollingIntervalMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxPollingIntervalMilliseconds = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key)) - { - if (throwIfAlreadyExists && this.PopulateIndexMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateIndexMetrics = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MigrateCollectionDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateCollectionDirective = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TargetGlobalCommittedLsn != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TargetGlobalCommittedLsn = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ForceQueryScan, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ForceQueryScan != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceQueryScan = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MaxPollingIntervalMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxPollingIntervalMilliseconds = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateIndexMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateIndexMetrics = value; - return; - } - break; - case 33: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableScanInQuery, key)) - { - if (throwIfAlreadyExists && this.EnableScanInQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableScanInQuery = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key)) - { - if (throwIfAlreadyExists && this.EmitVerboseTracesInQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EmitVerboseTracesInQuery = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key)) - { - if (throwIfAlreadyExists && this.PopulateQuotaInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateQuotaInfo = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreserveFullContent, key)) - { - if (throwIfAlreadyExists && this.PreserveFullContent != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreserveFullContent = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key)) - { - if (throwIfAlreadyExists && this.PopulateLogStoreInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateLogStoreInfo = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CorrelatedActivityId, key)) - { - if (throwIfAlreadyExists && this.CorrelatedActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CorrelatedActivityId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableScanInQuery, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableScanInQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableScanInQuery = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EmitVerboseTracesInQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EmitVerboseTracesInQuery = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateQuotaInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateQuotaInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PreserveFullContent, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PreserveFullContent != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreserveFullContent = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateLogStoreInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateLogStoreInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CorrelatedActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CorrelatedActivityId = value; - return; - } - break; - case 34: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowTentativeWrites, key)) - { - if (throwIfAlreadyExists && this.AllowTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowTentativeWrites = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UseArchivalPartition, key)) - { - if (throwIfAlreadyExists && this.UseArchivalPartition != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseArchivalPartition = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCapacityType, key)) - { - if (throwIfAlreadyExists && this.PopulateCapacityType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCapacityType = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.AllowTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AllowTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowTentativeWrites = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.UseArchivalPartition, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UseArchivalPartition != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseArchivalPartition = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PopulateCapacityType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateCapacityType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCapacityType = value; - return; - } - break; - case 35: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerInclude, key)) - { - if (throwIfAlreadyExists && this.PreTriggerInclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreTriggerInclude = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerExclude, key)) - { - if (throwIfAlreadyExists && this.PreTriggerExclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreTriggerExclude = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key)) - { - if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKeyRangeId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key)) - { - if (throwIfAlreadyExists && this.FilterBySchemaResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.FilterBySchemaResourceId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key)) - { - if (throwIfAlreadyExists && this.CollectionRemoteStorageSecurityIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionRemoteStorageSecurityIdentifier = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key)) - { - if (throwIfAlreadyExists && this.RemainingTimeInMsOnClientRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RemainingTimeInMsOnClientRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key)) - { - if (throwIfAlreadyExists && this.ShouldBatchContinueOnError != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShouldBatchContinueOnError = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IntendedCollectionRid, key)) - { - if (throwIfAlreadyExists && this.IntendedCollectionRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IntendedCollectionRid = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key)) - { - if (throwIfAlreadyExists && this.PopulateIndexMetricsV2 != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateIndexMetricsV2 = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PreTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PreTriggerInclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreTriggerInclude = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PreTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PreTriggerExclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PreTriggerExclude = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKeyRangeId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.FilterBySchemaResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.FilterBySchemaResourceId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionRemoteStorageSecurityIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionRemoteStorageSecurityIdentifier = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RemainingTimeInMsOnClientRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RemainingTimeInMsOnClientRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ShouldBatchContinueOnError != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShouldBatchContinueOnError = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IntendedCollectionRid, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IntendedCollectionRid != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IntendedCollectionRid = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateIndexMetricsV2 != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateIndexMetricsV2 = value; - return; - } - break; - case 36: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerInclude, key)) - { - if (throwIfAlreadyExists && this.PostTriggerInclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PostTriggerInclude = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerExclude, key)) - { - if (throwIfAlreadyExists && this.PostTriggerExclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PostTriggerExclude = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key)) - { - if (throwIfAlreadyExists && this.PopulateQueryMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateQueryMetrics = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsUserRequest, key)) - { - if (throwIfAlreadyExists && this.IsUserRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsUserRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key)) - { - if (throwIfAlreadyExists && this.IncludeTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IncludeTentativeWrites = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key)) - { - if (throwIfAlreadyExists && this.IsRetriedWriteRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRetriedWriteRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key)) - { - if (throwIfAlreadyExists && this.PruneCollectionSchemas != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PruneCollectionSchemas = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) - { - if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportedQueryFeatures = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PostTriggerInclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PostTriggerInclude = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PostTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PostTriggerExclude != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PostTriggerExclude = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateQueryMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateQueryMetrics = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IsUserRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsUserRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsUserRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IncludeTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IncludeTentativeWrites = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsRetriedWriteRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRetriedWriteRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PruneCollectionSchemas != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PruneCollectionSchemas = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportedQueryFeatures = value; - return; - } - break; - case 37: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) - { - if (throwIfAlreadyExists && this.EnableLogging != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableLogging = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateResourceCount, key)) - { - if (throwIfAlreadyExists && this.PopulateResourceCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateResourceCount = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key)) - { - if (throwIfAlreadyExists && this.SDKSupportedCapabilities != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SDKSupportedCapabilities = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key)) - { - if (throwIfAlreadyExists && this.BuilderClientIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BuilderClientIdentifier = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) - { - if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRequestNotAuthorized = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableLogging != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableLogging = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateResourceCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateResourceCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateResourceCount = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SDKSupportedCapabilities != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SDKSupportedCapabilities = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.BuilderClientIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BuilderClientIdentifier = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRequestNotAuthorized = value; - return; - } - break; - case 38: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) - { - if (throwIfAlreadyExists && this.MigrateOfferToAutopilot != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateOfferToAutopilot = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestId, key)) - { - if (throwIfAlreadyExists && this.RetriableWriteRequestId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetriableWriteRequestId = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key)) - { - if (throwIfAlreadyExists && this.SourceCollectionIfMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SourceCollectionIfMatch = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key)) - { - if (throwIfAlreadyExists && this.UseUserBackgroundBudget != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseUserBackgroundBudget = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MigrateOfferToAutopilot != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateOfferToAutopilot = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RetriableWriteRequestId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetriableWriteRequestId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SourceCollectionIfMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SourceCollectionIfMatch = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UseUserBackgroundBudget != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UseUserBackgroundBudget = value; - return; - } - break; - case 39: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key)) - { - if (throwIfAlreadyExists && this.TruncateMergeLogRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TruncateMergeLogRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key)) - { - if (throwIfAlreadyExists && this.IsInternalServerlessRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsInternalServerlessRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TruncateMergeLogRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TruncateMergeLogRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsInternalServerlessRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsInternalServerlessRequest = value; - return; - } - break; - case 40: - if (object.ReferenceEquals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key)) - { - if (throwIfAlreadyExists && this.EnableDynamicRidRangeAllocation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableDynamicRidRangeAllocation = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key)) - { - if (throwIfAlreadyExists && this.UniqueIndexReIndexingState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UniqueIndexReIndexingState = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableDynamicRidRangeAllocation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableDynamicRidRangeAllocation = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UniqueIndexReIndexingState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UniqueIndexReIndexingState = value; - return; - } - break; - case 41: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key)) - { - if (throwIfAlreadyExists && this.ForceDatabaseAccountUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceDatabaseAccountUpdate = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key)) - { - if (throwIfAlreadyExists && this.OptimisticDirectExecute != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OptimisticDirectExecute = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ForceDatabaseAccountUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceDatabaseAccountUpdate = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OptimisticDirectExecute != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OptimisticDirectExecute = value; - return; - } - break; - case 42: - if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key)) - { - if (throwIfAlreadyExists && this.MergeCheckPointGLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeCheckPointGLSN = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key)) - { - if (throwIfAlreadyExists && this.ShouldReturnCurrentServerDateTime != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShouldReturnCurrentServerDateTime = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key)) - { - if (throwIfAlreadyExists && this.ChangeFeedWireFormatVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedWireFormatVersion = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) - { - if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableCrossPartitionQuery = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MergeCheckPointGLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeCheckPointGLSN = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ShouldReturnCurrentServerDateTime != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShouldReturnCurrentServerDateTime = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ChangeFeedWireFormatVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedWireFormatVersion = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableCrossPartitionQuery = value; - return; - } - break; - case 43: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) - { - if (throwIfAlreadyExists && this.DisableRUPerMinuteUsage != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DisableRUPerMinuteUsage = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key)) - { - if (throwIfAlreadyExists && this.PopulatePartitionStatistics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulatePartitionStatistics = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key)) - { - if (throwIfAlreadyExists && this.ForceSideBySideIndexMigration != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceSideBySideIndexMigration = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key)) - { - if (throwIfAlreadyExists && this.UniqueIndexNameEncodingMode != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UniqueIndexNameEncodingMode = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key)) - { - if (throwIfAlreadyExists && this.SupportedSerializationFormats != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportedSerializationFormats = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.DisableRUPerMinuteUsage != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DisableRUPerMinuteUsage = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulatePartitionStatistics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulatePartitionStatistics = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ForceSideBySideIndexMigration != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ForceSideBySideIndexMigration = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UniqueIndexNameEncodingMode != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UniqueIndexNameEncodingMode = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SupportedSerializationFormats != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportedSerializationFormats = value; - return; - } - break; - case 44: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ContentSerializationFormat, key)) - { - if (throwIfAlreadyExists && this.ContentSerializationFormat != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ContentSerializationFormat = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key)) - { - if (throwIfAlreadyExists && this.PopulateOldestActiveSchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateOldestActiveSchemaId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) - { - if (throwIfAlreadyExists && this.IsContinuationExpected != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsContinuationExpected = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ContentSerializationFormat != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ContentSerializationFormat = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateOldestActiveSchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateOldestActiveSchemaId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsContinuationExpected != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsContinuationExpected = value; - return; - } - break; - case 45: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) - { - if (throwIfAlreadyExists && this.ChangeFeedStartFullFidelityIfNoneMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedStartFullFidelityIfNoneMatch = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemRestoreOperation, key)) - { - if (throwIfAlreadyExists && this.SystemRestoreOperation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SystemRestoreOperation = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key)) - { - if (throwIfAlreadyExists && this.IsThroughputCapRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsThroughputCapRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key)) - { - if (throwIfAlreadyExists && this.PopulateByokEncryptionProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateByokEncryptionProgress = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ChangeFeedStartFullFidelityIfNoneMatch != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedStartFullFidelityIfNoneMatch = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SystemRestoreOperation, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SystemRestoreOperation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SystemRestoreOperation = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsThroughputCapRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsThroughputCapRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateByokEncryptionProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateByokEncryptionProgress = value; - return; - } - break; - case 46: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key)) - { - if (throwIfAlreadyExists && this.MigrateOfferToManualThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateOfferToManualThroughput = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key)) - { - if (throwIfAlreadyExists && this.SkipRefreshDatabaseAccountConfigs != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SkipRefreshDatabaseAccountConfigs = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key)) - { - if (throwIfAlreadyExists && this.IsMigratedFixedCollection != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMigratedFixedCollection = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MigrateOfferToManualThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MigrateOfferToManualThroughput = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SkipRefreshDatabaseAccountConfigs != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SkipRefreshDatabaseAccountConfigs = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsMigratedFixedCollection != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMigratedFixedCollection = value; - return; - } - break; - case 47: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key)) - { - if (throwIfAlreadyExists && this.SupportSpatialLegacyCoordinates != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportSpatialLegacyCoordinates = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key)) - { - if (throwIfAlreadyExists && this.CollectionChildResourceNameLimitInBytes != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionChildResourceNameLimitInBytes = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key)) - { - if (throwIfAlreadyExists && this.AddResourcePropertiesToResponse != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AddResourcePropertiesToResponse = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key)) - { - if (throwIfAlreadyExists && this.IsMaterializedViewBuild != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMaterializedViewBuild = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SupportSpatialLegacyCoordinates != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SupportSpatialLegacyCoordinates = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionChildResourceNameLimitInBytes != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionChildResourceNameLimitInBytes = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AddResourcePropertiesToResponse != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AddResourcePropertiesToResponse = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsMaterializedViewBuild != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMaterializedViewBuild = value; - return; - } - break; - case 48: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key)) - { - if (throwIfAlreadyExists && this.PopulateCollectionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCollectionThroughputInfo = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key)) - { - if (throwIfAlreadyExists && this.GetAllPartitionKeyStatistics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GetAllPartitionKeyStatistics = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key)) - { - if (throwIfAlreadyExists && this.PopulateUniqueIndexReIndexProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateUniqueIndexReIndexProgress = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key)) - { - if (throwIfAlreadyExists && this.AllowRestoreParamsUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowRestoreParamsUpdate = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key)) - { - if (throwIfAlreadyExists && this.HighPriorityForcedBackup != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HighPriorityForcedBackup = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateCollectionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCollectionThroughputInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.GetAllPartitionKeyStatistics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GetAllPartitionKeyStatistics = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateUniqueIndexReIndexProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateUniqueIndexReIndexProgress = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AllowRestoreParamsUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowRestoreParamsUpdate = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.HighPriorityForcedBackup != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HighPriorityForcedBackup = value; - return; - } - break; - case 49: - if (string.Equals(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UsePolygonsSmallerThanAHemisphere != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UsePolygonsSmallerThanAHemisphere = value; - return; - } - break; - case 50: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key)) - { - if (throwIfAlreadyExists && this.ResponseContinuationTokenLimitInKB != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResponseContinuationTokenLimitInKB = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key)) - { - if (throwIfAlreadyExists && this.PopulateAnalyticalMigrationProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateAnalyticalMigrationProgress = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key)) - { - if (throwIfAlreadyExists && this.UpdateOfferStateToPending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateOfferStateToPending = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResponseContinuationTokenLimitInKB != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResponseContinuationTokenLimitInKB = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateAnalyticalMigrationProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateAnalyticalMigrationProgress = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UpdateOfferStateToPending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateOfferStateToPending = value; - return; - } - break; - case 51: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key)) - { - if (throwIfAlreadyExists && this.EnableLowPrecisionOrderBy != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableLowPrecisionOrderBy = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key)) - { - if (throwIfAlreadyExists && this.RetriableWriteRequestStartTimestamp != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetriableWriteRequestStartTimestamp = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableLowPrecisionOrderBy != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableLowPrecisionOrderBy = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RetriableWriteRequestStartTimestamp != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetriableWriteRequestStartTimestamp = value; - return; - } - break; - case 52: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) - { - if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplaceRURedistribution = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) - { - if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ParallelizeCrossPartitionQuery = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplaceRURedistribution = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ParallelizeCrossPartitionQuery = value; - return; - } - break; - case 53: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) - { - if (throwIfAlreadyExists && this.IsRUPerGBEnforcementRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRUPerGBEnforcementRequest = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key)) - { - if (throwIfAlreadyExists && this.IsOfferStorageRefreshRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsOfferStorageRefreshRequest = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key)) - { - if (throwIfAlreadyExists && this.PopulateMinGLSNForDocumentOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateMinGLSNForDocumentOperations = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsRUPerGBEnforcementRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRUPerGBEnforcementRequest = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsOfferStorageRefreshRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsOfferStorageRefreshRequest = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateMinGLSNForDocumentOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateMinGLSNForDocumentOperations = value; - return; - } - break; - case 54: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key)) - { - if (throwIfAlreadyExists && this.IncludePhysicalPartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IncludePhysicalPartitionThroughputInfo = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key)) - { - if (throwIfAlreadyExists && this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) - { - if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCurrentPartitionThroughputInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IncludePhysicalPartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IncludePhysicalPartitionThroughputInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateCurrentPartitionThroughputInfo = value; - return; - } - break; - case 55: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) - { - if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateOfferStateToRestorePending = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) - { - if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SqlQueryForPartitionKeyExtraction = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateOfferStateToRestorePending = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SqlQueryForPartitionKeyExtraction = value; - return; - } - break; - case 56: - if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionChildResourceContentLimitInKB != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionChildResourceContentLimitInKB = value; - return; - } - break; - case 57: - if (string.Equals(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateUnflushedMergeEntryCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateUnflushedMergeEntryCount = value; - return; - } - break; - case 58: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key)) - { - if (throwIfAlreadyExists && this.IgnoreSystemLoweringMaxThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IgnoreSystemLoweringMaxThroughput = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key)) - { - if (throwIfAlreadyExists && this.SetMasterResourcesDeletionPending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SetMasterResourcesDeletionPending = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key)) - { - if (throwIfAlreadyExists && this.PopulateHighestTentativeWriteLLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateHighestTentativeWriteLLSN = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IgnoreSystemLoweringMaxThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IgnoreSystemLoweringMaxThroughput = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SetMasterResourcesDeletionPending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SetMasterResourcesDeletionPending = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PopulateHighestTentativeWriteLLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PopulateHighestTentativeWriteLLSN = value; - return; - } - break; - case 59: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) - { - if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateMaxThroughputEverProvisioned = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) - { - if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableConflictResolutionPolicyUpdate = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) - { - if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowDocumentReadsInOfflineRegion = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UpdateMaxThroughputEverProvisioned = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.EnableConflictResolutionPolicyUpdate = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AllowDocumentReadsInOfflineRegion = value; - return; - } - break; - case 61: - if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsServerlessStorageRefreshRequest != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsServerlessStorageRefreshRequest = value; - return; - } - break; - case 62: - if (string.Equals(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SkipAdjustThroughputFractionsForOfferReplace != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SkipAdjustThroughputFractionsForOfferReplace = value; - return; - } - break; - default: - break; - } - - if (ignoreNotCommonHeaders) - { - return; - } - - if (throwIfAlreadyExists) - { - this.InitializeNotCommonHeadersIfNeeded(); - this.notCommonHeaders.Add(key, value); - } - else - { - if (value == null) - { - if (this.notCommonHeaders != null) - { - this.notCommonHeaders.Remove(key); - } - } - else - { - this.InitializeNotCommonHeadersIfNeeded(); - this.notCommonHeaders[key] = value; - } - } - } - - /// - /// Thread safe initialization is needed to make sure we do not lose headers. - /// - private void InitializeNotCommonHeadersIfNeeded() - { - if (this.notCommonHeaders == null) - { - lock (this) - { - if (this.notCommonHeaders == null) - { - this.notCommonHeaders = new Dictionary(RequestNameValueCollection.DefaultStringComparer); - } - } - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RequestNameValueCollection.tt + +namespace Microsoft.Azure.Documents.Collections +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Linq; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents; + + /// + /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RequestNameValueCollection.tt + /// This should be a one to one mapping with RntbdConstants.Request header token properties. + /// This allows the TransportSerialization to directly set the property and avoid the dictionary overhead. + /// If the property does not exists please update the RequestNameValueCollection.tt list to add the new field + /// + internal class RequestNameValueCollection : INameValueCollection + { + private static readonly StringComparer DefaultStringComparer = StringComparer.OrdinalIgnoreCase; + private Dictionary notCommonHeaders; + + // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. + // However, there are a few APIs stil using the NameValueCollection + // + // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create + // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is + // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. + // + // Therefore, we want to keep the NameValueCollection consistent within the RequestHeaders APIs call. In other words, + // once invoked, the RequestHeaders will return the same NameValueCollection. + private NameValueCollection nameValueCollection = null; + + public string A_IM { get; set; } + public string ActivityId { get; set; } + public string AddResourcePropertiesToResponse { get; set; } + public string AllowDocumentReadsInOfflineRegion { get; set; } + public string AllowRestoreParamsUpdate { get; set; } + public string AllowTentativeWrites { get; set; } + public string Authorization { get; set; } + public string BinaryId { get; set; } + public string BinaryPassthroughRequest { get; set; } + public string BindReplicaDirective { get; set; } + public string BuilderClientIdentifier { get; set; } + public string CanCharge { get; set; } + public string CanOfferReplaceComplete { get; set; } + public string CanThrottle { get; set; } + public string ChangeFeedStartFullFidelityIfNoneMatch { get; set; } + public string ChangeFeedWireFormatVersion { get; set; } + public string ClientIpAddress { get; set; } + public string ClientRetryAttemptCount { get; set; } + public string CollectionChildResourceContentLimitInKB { get; set; } + public string CollectionChildResourceNameLimitInBytes { get; set; } + public string CollectionPartitionIndex { get; set; } + public string CollectionRemoteStorageSecurityIdentifier { get; set; } + public string CollectionRid { get; set; } + public string CollectionServiceIndex { get; set; } + public string CollectionTruncate { get; set; } + public string ConsistencyLevel { get; set; } + public string ContentSerializationFormat { get; set; } + public string Continuation { get; set; } + public string CorrelatedActivityId { get; set; } + public string CosmosGatewayTransactionId { get; set; } + public string DisableRUPerMinuteUsage { get; set; } + public string EffectivePartitionKey { get; set; } + public string EmitVerboseTracesInQuery { get; set; } + public string EnableConflictResolutionPolicyUpdate { get; set; } + public string EnableCrossPartitionQuery { get; set; } + public string EnableDynamicRidRangeAllocation { get; set; } + public string EnableLogging { get; set; } + public string EnableLowPrecisionOrderBy { get; set; } + public string EnableScanInQuery { get; set; } + public string EndEpk { get; set; } + public string EndId { get; set; } + public string EntityId { get; set; } + public string EnumerationDirection { get; set; } + public string ExcludeSystemProperties { get; set; } + public string FanoutOperationState { get; set; } + public string FilterBySchemaResourceId { get; set; } + public string ForceDatabaseAccountUpdate { get; set; } + public string ForceQueryScan { get; set; } + public string ForceSideBySideIndexMigration { get; set; } + public string GatewaySignature { get; set; } + public string GetAllPartitionKeyStatistics { get; set; } + public string HighPriorityForcedBackup { get; set; } + public string HttpDate { get; set; } + public string IfMatch { get; set; } + public string IfModifiedSince { get; set; } + public string IfNoneMatch { get; set; } + public string IgnoreSystemLoweringMaxThroughput { get; set; } + public string IncludePhysicalPartitionThroughputInfo { get; set; } + public string IncludeTentativeWrites { get; set; } + public string IndexingDirective { get; set; } + public string IntendedCollectionRid { get; set; } + public string IsAutoScaleRequest { get; set; } + public string IsBatchAtomic { get; set; } + public string IsBatchOrdered { get; set; } + public string IsCassandraAlterTypeRequest { get; set; } + public string IsClientEncrypted { get; set; } + public string IsContinuationExpected { get; set; } + public string IsFanoutRequest { get; set; } + public string IsInternalServerlessRequest { get; set; } + public string IsMaterializedViewBuild { get; set; } + public string IsMaterializedViewSourceSchemaReplaceBatchRequest { get; set; } + public string IsMigratedFixedCollection { get; set; } + public string IsOfferStorageRefreshRequest { get; set; } + public string IsReadOnlyScript { get; set; } + public string IsRequestNotAuthorized { get; set; } + public string IsRetriedWriteRequest { get; set; } + public string IsRUPerGBEnforcementRequest { get; set; } + public string IsServerlessStorageRefreshRequest { get; set; } + public string IsThroughputCapRequest { get; set; } + public string IsUserRequest { get; set; } + public string MaxPollingIntervalMilliseconds { get; set; } + public string MergeCheckPointGLSN { get; set; } + public string MergeStaticId { get; set; } + public string MigrateCollectionDirective { get; set; } + public string MigrateOfferToAutopilot { get; set; } + public string MigrateOfferToManualThroughput { get; set; } + public string NoRetryOn449StatusCode { get; set; } + public string OfferReplaceRURedistribution { get; set; } + public string OptimisticDirectExecute { get; set; } + public string PageSize { get; set; } + public string ParallelizeCrossPartitionQuery { get; set; } + public string PartitionCount { get; set; } + public string PartitionKey { get; set; } + public string PartitionKeyRangeId { get; set; } + public string PartitionResourceFilter { get; set; } + public string PopulateAnalyticalMigrationProgress { get; set; } + public string PopulateByokEncryptionProgress { get; set; } + public string PopulateCapacityType { get; set; } + public string PopulateCollectionThroughputInfo { get; set; } + public string PopulateCurrentPartitionThroughputInfo { get; set; } + public string PopulateDocumentRecordCount { get; set; } + public string PopulateHighestTentativeWriteLLSN { get; set; } + public string PopulateIndexMetrics { get; set; } + public string PopulateIndexMetricsV2 { get; set; } + public string PopulateLogStoreInfo { get; set; } + public string PopulateMinGLSNForDocumentOperations { get; set; } + public string PopulateOldestActiveSchemaId { get; set; } + public string PopulatePartitionStatistics { get; set; } + public string PopulateQueryMetrics { get; set; } + public string PopulateQuotaInfo { get; set; } + public string PopulateResourceCount { get; set; } + public string PopulateUnflushedMergeEntryCount { get; set; } + public string PopulateUniqueIndexReIndexProgress { get; set; } + public string PopulateUserStrings { get; set; } + public string PostTriggerExclude { get; set; } + public string PostTriggerInclude { get; set; } + public string Prefer { get; set; } + public string PreserveFullContent { get; set; } + public string PreTriggerExclude { get; set; } + public string PreTriggerInclude { get; set; } + public string PrimaryMasterKey { get; set; } + public string PrimaryReadonlyKey { get; set; } + public string PriorityLevel { get; set; } + public string ProfileRequest { get; set; } + public string PruneCollectionSchemas { get; set; } + public string QueryVersion { get; set; } + public string RbacAction { get; set; } + public string RbacResource { get; set; } + public string RbacUserId { get; set; } + public string ReadFeedKeyType { get; set; } + public string RemainingTimeInMsOnClientRequest { get; set; } + public string RemoteStorageType { get; set; } + public string RequestedCollectionType { get; set; } + public string ResourceId { get; set; } + public string ResourceSchemaName { get; set; } + public string ResourceTokenExpiry { get; set; } + public string ResourceTypes { get; set; } + public string ResponseContinuationTokenLimitInKB { get; set; } + public string RestoreMetadataFilter { get; set; } + public string RestoreParams { get; set; } + public string RetriableWriteRequestId { get; set; } + public string RetriableWriteRequestStartTimestamp { get; set; } + public string SchemaHash { get; set; } + public string SchemaId { get; set; } + public string SchemaOwnerRid { get; set; } + public string SDKSupportedCapabilities { get; set; } + public string SecondaryMasterKey { get; set; } + public string SecondaryReadonlyKey { get; set; } + public string SessionToken { get; set; } + public string SetMasterResourcesDeletionPending { get; set; } + public string ShareThroughput { get; set; } + public string ShouldBatchContinueOnError { get; set; } + public string ShouldReturnCurrentServerDateTime { get; set; } + public string SkipAdjustThroughputFractionsForOfferReplace { get; set; } + public string SkipRefreshDatabaseAccountConfigs { get; set; } + public string SkipThroughputCapValidation { get; set; } + public string SourceCollectionIfMatch { get; set; } + public string SqlQueryForPartitionKeyExtraction { get; set; } + public string StartEpk { get; set; } + public string StartId { get; set; } + public string SupportedQueryFeatures { get; set; } + public string SupportedSerializationFormats { get; set; } + public string SupportSpatialLegacyCoordinates { get; set; } + public string SystemDocumentType { get; set; } + public string SystemRestoreOperation { get; set; } + public string TargetGlobalCommittedLsn { get; set; } + public string TargetLsn { get; set; } + public string TimeToLiveInSeconds { get; set; } + public string TraceParent { get; set; } + public string TraceState { get; set; } + public string TransactionCommit { get; set; } + public string TransactionFirstRequest { get; set; } + public string TransactionId { get; set; } + public string TransportRequestID { get; set; } + public string TruncateMergeLogRequest { get; set; } + public string UniqueIndexNameEncodingMode { get; set; } + public string UniqueIndexReIndexingState { get; set; } + public string UpdateMaxThroughputEverProvisioned { get; set; } + public string UpdateOfferStateToPending { get; set; } + public string UpdateOfferStateToRestorePending { get; set; } + public string UseArchivalPartition { get; set; } + public string UsePolygonsSmallerThanAHemisphere { get; set; } + public string UseSystemBudget { get; set; } + public string UseUserBackgroundBudget { get; set; } + public string Version { get; set; } + public string XDate { get; set; } + + public RequestNameValueCollection() + { + } + + public RequestNameValueCollection(INameValueCollection nameValueCollection) + { + foreach (string key in nameValueCollection) + { + this.UpdateHelper(key, value: nameValueCollection.Get(key), throwIfAlreadyExists: false, ignoreNotCommonHeaders: false); + } + } + + public RequestNameValueCollection(IDictionary requestHeaders) + { + foreach (KeyValuePair keyValuePair in requestHeaders) + { + this.UpdateHelper(key: keyValuePair.Key, value: keyValuePair.Value, throwIfAlreadyExists: false, ignoreNotCommonHeaders: false); + } + } + + /// + /// Only process known headers. + /// + /// + /// Non thread safe. Does not support requestHeaders modification while running this method. + /// + public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnownHeadersOnly(IDictionary requestHeaders) + { + RequestNameValueCollection requestNameValueCollection = new RequestNameValueCollection(); + foreach (KeyValuePair keyValue in requestHeaders) + { + requestNameValueCollection.UpdateHelper(keyValue.Key, value: keyValue.Value, throwIfAlreadyExists: false, ignoreNotCommonHeaders: true); + } + + return requestNameValueCollection; + } + + /// + /// Only process known headers. Ignores nameValueCollection changes by switching to per field assignment if InvalidOperationException happens while iterating over the keys. + /// + public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnownHeadersOnly(INameValueCollection nameValueCollection) + { + RequestNameValueCollection requestNameValueCollection = new RequestNameValueCollection(); + try + { + foreach (string key in nameValueCollection) + { + requestNameValueCollection.UpdateHelper(key, value: nameValueCollection.Get(key), throwIfAlreadyExists: false, ignoreNotCommonHeaders: true); + } + } + catch (InvalidOperationException e) + { + DefaultTrace.TraceWarning($"{nameof(RequestNameValueCollection)} Failed to iterate over nameValueCollection headers in a non thread safe manner: {e.Message}. Switching to the per property approach."); + + // Lookup by value because request headers can be used concurrently + // It will cause an exception of looping over the dictionary and a value is modified + requestNameValueCollection.ResourceId = nameValueCollection[WFConstants.BackendHeaders.ResourceId]; + requestNameValueCollection.Authorization = nameValueCollection[HttpConstants.HttpHeaders.Authorization]; + requestNameValueCollection.HttpDate = nameValueCollection[HttpConstants.HttpHeaders.HttpDate]; + requestNameValueCollection.XDate = nameValueCollection[HttpConstants.HttpHeaders.XDate]; + requestNameValueCollection.PageSize = nameValueCollection[HttpConstants.HttpHeaders.PageSize]; + requestNameValueCollection.SessionToken = nameValueCollection[HttpConstants.HttpHeaders.SessionToken]; + requestNameValueCollection.Continuation = nameValueCollection[HttpConstants.HttpHeaders.Continuation]; + requestNameValueCollection.IndexingDirective = nameValueCollection[HttpConstants.HttpHeaders.IndexingDirective]; + requestNameValueCollection.IfNoneMatch = nameValueCollection[HttpConstants.HttpHeaders.IfNoneMatch]; + requestNameValueCollection.PreTriggerInclude = nameValueCollection[HttpConstants.HttpHeaders.PreTriggerInclude]; + requestNameValueCollection.PostTriggerInclude = nameValueCollection[HttpConstants.HttpHeaders.PostTriggerInclude]; + requestNameValueCollection.IsFanoutRequest = nameValueCollection[WFConstants.BackendHeaders.IsFanoutRequest]; + requestNameValueCollection.CollectionPartitionIndex = nameValueCollection[WFConstants.BackendHeaders.CollectionPartitionIndex]; + requestNameValueCollection.CollectionServiceIndex = nameValueCollection[WFConstants.BackendHeaders.CollectionServiceIndex]; + requestNameValueCollection.PreTriggerExclude = nameValueCollection[HttpConstants.HttpHeaders.PreTriggerExclude]; + requestNameValueCollection.PostTriggerExclude = nameValueCollection[HttpConstants.HttpHeaders.PostTriggerExclude]; + requestNameValueCollection.ConsistencyLevel = nameValueCollection[HttpConstants.HttpHeaders.ConsistencyLevel]; + requestNameValueCollection.EntityId = nameValueCollection[WFConstants.BackendHeaders.EntityId]; + requestNameValueCollection.ResourceSchemaName = nameValueCollection[WFConstants.BackendHeaders.ResourceSchemaName]; + requestNameValueCollection.ResourceTokenExpiry = nameValueCollection[HttpConstants.HttpHeaders.ResourceTokenExpiry]; + requestNameValueCollection.EnableScanInQuery = nameValueCollection[HttpConstants.HttpHeaders.EnableScanInQuery]; + requestNameValueCollection.EmitVerboseTracesInQuery = nameValueCollection[HttpConstants.HttpHeaders.EmitVerboseTracesInQuery]; + requestNameValueCollection.BindReplicaDirective = nameValueCollection[WFConstants.BackendHeaders.BindReplicaDirective]; + requestNameValueCollection.PrimaryMasterKey = nameValueCollection[WFConstants.BackendHeaders.PrimaryMasterKey]; + requestNameValueCollection.SecondaryMasterKey = nameValueCollection[WFConstants.BackendHeaders.SecondaryMasterKey]; + requestNameValueCollection.PrimaryReadonlyKey = nameValueCollection[WFConstants.BackendHeaders.PrimaryReadonlyKey]; + requestNameValueCollection.SecondaryReadonlyKey = nameValueCollection[WFConstants.BackendHeaders.SecondaryReadonlyKey]; + requestNameValueCollection.ProfileRequest = nameValueCollection[HttpConstants.HttpHeaders.ProfileRequest]; + requestNameValueCollection.EnableLowPrecisionOrderBy = nameValueCollection[HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy]; + requestNameValueCollection.Version = nameValueCollection[HttpConstants.HttpHeaders.Version]; + requestNameValueCollection.CanCharge = nameValueCollection[HttpConstants.HttpHeaders.CanCharge]; + requestNameValueCollection.CanThrottle = nameValueCollection[HttpConstants.HttpHeaders.CanThrottle]; + requestNameValueCollection.PartitionKey = nameValueCollection[HttpConstants.HttpHeaders.PartitionKey]; + requestNameValueCollection.PartitionKeyRangeId = nameValueCollection[HttpConstants.HttpHeaders.PartitionKeyRangeId]; + requestNameValueCollection.MigrateCollectionDirective = nameValueCollection[HttpConstants.HttpHeaders.MigrateCollectionDirective]; + requestNameValueCollection.SupportSpatialLegacyCoordinates = nameValueCollection[HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates]; + requestNameValueCollection.PartitionCount = nameValueCollection[HttpConstants.HttpHeaders.PartitionCount]; + requestNameValueCollection.CollectionRid = nameValueCollection[WFConstants.BackendHeaders.CollectionRid]; + requestNameValueCollection.FilterBySchemaResourceId = nameValueCollection[HttpConstants.HttpHeaders.FilterBySchemaResourceId]; + requestNameValueCollection.UsePolygonsSmallerThanAHemisphere = nameValueCollection[HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere]; + requestNameValueCollection.GatewaySignature = nameValueCollection[HttpConstants.HttpHeaders.GatewaySignature]; + requestNameValueCollection.EnableLogging = nameValueCollection[HttpConstants.HttpHeaders.EnableLogging]; + requestNameValueCollection.A_IM = nameValueCollection[HttpConstants.HttpHeaders.A_IM]; + requestNameValueCollection.PopulateQuotaInfo = nameValueCollection[HttpConstants.HttpHeaders.PopulateQuotaInfo]; + requestNameValueCollection.DisableRUPerMinuteUsage = nameValueCollection[HttpConstants.HttpHeaders.DisableRUPerMinuteUsage]; + requestNameValueCollection.PopulateQueryMetrics = nameValueCollection[HttpConstants.HttpHeaders.PopulateQueryMetrics]; + requestNameValueCollection.ResponseContinuationTokenLimitInKB = nameValueCollection[HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB]; + requestNameValueCollection.PopulatePartitionStatistics = nameValueCollection[HttpConstants.HttpHeaders.PopulatePartitionStatistics]; + requestNameValueCollection.RemoteStorageType = nameValueCollection[WFConstants.BackendHeaders.RemoteStorageType]; + requestNameValueCollection.CollectionRemoteStorageSecurityIdentifier = nameValueCollection[HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier]; + requestNameValueCollection.IfModifiedSince = nameValueCollection[HttpConstants.HttpHeaders.IfModifiedSince]; + requestNameValueCollection.PopulateCollectionThroughputInfo = nameValueCollection[HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo]; + requestNameValueCollection.RemainingTimeInMsOnClientRequest = nameValueCollection[HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest]; + requestNameValueCollection.ClientRetryAttemptCount = nameValueCollection[HttpConstants.HttpHeaders.ClientRetryAttemptCount]; + requestNameValueCollection.TargetLsn = nameValueCollection[HttpConstants.HttpHeaders.TargetLsn]; + requestNameValueCollection.TargetGlobalCommittedLsn = nameValueCollection[HttpConstants.HttpHeaders.TargetGlobalCommittedLsn]; + requestNameValueCollection.TransportRequestID = nameValueCollection[HttpConstants.HttpHeaders.TransportRequestID]; + requestNameValueCollection.RestoreMetadataFilter = nameValueCollection[HttpConstants.HttpHeaders.RestoreMetadataFilter]; + requestNameValueCollection.RestoreParams = nameValueCollection[WFConstants.BackendHeaders.RestoreParams]; + requestNameValueCollection.ShareThroughput = nameValueCollection[WFConstants.BackendHeaders.ShareThroughput]; + requestNameValueCollection.PartitionResourceFilter = nameValueCollection[WFConstants.BackendHeaders.PartitionResourceFilter]; + requestNameValueCollection.IsReadOnlyScript = nameValueCollection[HttpConstants.HttpHeaders.IsReadOnlyScript]; + requestNameValueCollection.IsAutoScaleRequest = nameValueCollection[HttpConstants.HttpHeaders.IsAutoScaleRequest]; + requestNameValueCollection.ForceQueryScan = nameValueCollection[HttpConstants.HttpHeaders.ForceQueryScan]; + requestNameValueCollection.CanOfferReplaceComplete = nameValueCollection[HttpConstants.HttpHeaders.CanOfferReplaceComplete]; + requestNameValueCollection.ExcludeSystemProperties = nameValueCollection[WFConstants.BackendHeaders.ExcludeSystemProperties]; + requestNameValueCollection.BinaryId = nameValueCollection[WFConstants.BackendHeaders.BinaryId]; + requestNameValueCollection.TimeToLiveInSeconds = nameValueCollection[WFConstants.BackendHeaders.TimeToLiveInSeconds]; + requestNameValueCollection.EffectivePartitionKey = nameValueCollection[WFConstants.BackendHeaders.EffectivePartitionKey]; + requestNameValueCollection.BinaryPassthroughRequest = nameValueCollection[WFConstants.BackendHeaders.BinaryPassthroughRequest]; + requestNameValueCollection.EnableDynamicRidRangeAllocation = nameValueCollection[WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation]; + requestNameValueCollection.EnumerationDirection = nameValueCollection[HttpConstants.HttpHeaders.EnumerationDirection]; + requestNameValueCollection.StartId = nameValueCollection[HttpConstants.HttpHeaders.StartId]; + requestNameValueCollection.EndId = nameValueCollection[HttpConstants.HttpHeaders.EndId]; + requestNameValueCollection.FanoutOperationState = nameValueCollection[WFConstants.BackendHeaders.FanoutOperationState]; + requestNameValueCollection.StartEpk = nameValueCollection[HttpConstants.HttpHeaders.StartEpk]; + requestNameValueCollection.EndEpk = nameValueCollection[HttpConstants.HttpHeaders.EndEpk]; + requestNameValueCollection.ReadFeedKeyType = nameValueCollection[HttpConstants.HttpHeaders.ReadFeedKeyType]; + requestNameValueCollection.ContentSerializationFormat = nameValueCollection[HttpConstants.HttpHeaders.ContentSerializationFormat]; + requestNameValueCollection.AllowTentativeWrites = nameValueCollection[HttpConstants.HttpHeaders.AllowTentativeWrites]; + requestNameValueCollection.IsUserRequest = nameValueCollection[WFConstants.BackendHeaders.IsUserRequest]; + requestNameValueCollection.PreserveFullContent = nameValueCollection[HttpConstants.HttpHeaders.PreserveFullContent]; + requestNameValueCollection.IncludeTentativeWrites = nameValueCollection[HttpConstants.HttpHeaders.IncludeTentativeWrites]; + requestNameValueCollection.PopulateResourceCount = nameValueCollection[HttpConstants.HttpHeaders.PopulateResourceCount]; + requestNameValueCollection.MergeStaticId = nameValueCollection[HttpConstants.HttpHeaders.MergeStaticId]; + requestNameValueCollection.IsBatchAtomic = nameValueCollection[HttpConstants.HttpHeaders.IsBatchAtomic]; + requestNameValueCollection.ShouldBatchContinueOnError = nameValueCollection[HttpConstants.HttpHeaders.ShouldBatchContinueOnError]; + requestNameValueCollection.IsBatchOrdered = nameValueCollection[HttpConstants.HttpHeaders.IsBatchOrdered]; + requestNameValueCollection.SchemaOwnerRid = nameValueCollection[WFConstants.BackendHeaders.SchemaOwnerRid]; + requestNameValueCollection.SchemaHash = nameValueCollection[WFConstants.BackendHeaders.SchemaHash]; + requestNameValueCollection.IsRUPerGBEnforcementRequest = nameValueCollection[HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest]; + requestNameValueCollection.MaxPollingIntervalMilliseconds = nameValueCollection[HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds]; + requestNameValueCollection.PopulateLogStoreInfo = nameValueCollection[WFConstants.BackendHeaders.PopulateLogStoreInfo]; + requestNameValueCollection.GetAllPartitionKeyStatistics = nameValueCollection[HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics]; + requestNameValueCollection.ForceSideBySideIndexMigration = nameValueCollection[HttpConstants.HttpHeaders.ForceSideBySideIndexMigration]; + requestNameValueCollection.CollectionChildResourceNameLimitInBytes = nameValueCollection[WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes]; + requestNameValueCollection.CollectionChildResourceContentLimitInKB = nameValueCollection[WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB]; + requestNameValueCollection.MergeCheckPointGLSN = nameValueCollection[WFConstants.BackendHeaders.MergeCheckPointGLSN]; + requestNameValueCollection.Prefer = nameValueCollection[HttpConstants.HttpHeaders.Prefer]; + requestNameValueCollection.UniqueIndexNameEncodingMode = nameValueCollection[WFConstants.BackendHeaders.UniqueIndexNameEncodingMode]; + requestNameValueCollection.PopulateUnflushedMergeEntryCount = nameValueCollection[WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount]; + requestNameValueCollection.MigrateOfferToManualThroughput = nameValueCollection[HttpConstants.HttpHeaders.MigrateOfferToManualThroughput]; + requestNameValueCollection.MigrateOfferToAutopilot = nameValueCollection[HttpConstants.HttpHeaders.MigrateOfferToAutopilot]; + requestNameValueCollection.IsClientEncrypted = nameValueCollection[HttpConstants.HttpHeaders.IsClientEncrypted]; + requestNameValueCollection.SystemDocumentType = nameValueCollection[HttpConstants.HttpHeaders.SystemDocumentType]; + requestNameValueCollection.IsOfferStorageRefreshRequest = nameValueCollection[HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest]; + requestNameValueCollection.ResourceTypes = nameValueCollection[WFConstants.BackendHeaders.ResourceTypes]; + requestNameValueCollection.TransactionId = nameValueCollection[WFConstants.BackendHeaders.TransactionId]; + requestNameValueCollection.TransactionFirstRequest = nameValueCollection[WFConstants.BackendHeaders.TransactionFirstRequest]; + requestNameValueCollection.TransactionCommit = nameValueCollection[WFConstants.BackendHeaders.TransactionCommit]; + requestNameValueCollection.UpdateMaxThroughputEverProvisioned = nameValueCollection[HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned]; + requestNameValueCollection.UniqueIndexReIndexingState = nameValueCollection[WFConstants.BackendHeaders.UniqueIndexReIndexingState]; + requestNameValueCollection.UseSystemBudget = nameValueCollection[WFConstants.BackendHeaders.UseSystemBudget]; + requestNameValueCollection.IgnoreSystemLoweringMaxThroughput = nameValueCollection[HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput]; + requestNameValueCollection.TruncateMergeLogRequest = nameValueCollection[HttpConstants.HttpHeaders.TruncateMergeLogRequest]; + requestNameValueCollection.RetriableWriteRequestId = nameValueCollection[WFConstants.BackendHeaders.RetriableWriteRequestId]; + requestNameValueCollection.IsRetriedWriteRequest = nameValueCollection[WFConstants.BackendHeaders.IsRetriedWriteRequest]; + requestNameValueCollection.RetriableWriteRequestStartTimestamp = nameValueCollection[WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp]; + requestNameValueCollection.AddResourcePropertiesToResponse = nameValueCollection[WFConstants.BackendHeaders.AddResourcePropertiesToResponse]; + requestNameValueCollection.ChangeFeedStartFullFidelityIfNoneMatch = nameValueCollection[HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch]; + requestNameValueCollection.SystemRestoreOperation = nameValueCollection[HttpConstants.HttpHeaders.SystemRestoreOperation]; + requestNameValueCollection.SkipRefreshDatabaseAccountConfigs = nameValueCollection[WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs]; + requestNameValueCollection.IntendedCollectionRid = nameValueCollection[WFConstants.BackendHeaders.IntendedCollectionRid]; + requestNameValueCollection.UseArchivalPartition = nameValueCollection[HttpConstants.HttpHeaders.UseArchivalPartition]; + requestNameValueCollection.PopulateUniqueIndexReIndexProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress]; + requestNameValueCollection.SchemaId = nameValueCollection[WFConstants.BackendHeaders.SchemaId]; + requestNameValueCollection.CollectionTruncate = nameValueCollection[HttpConstants.HttpHeaders.CollectionTruncate]; + requestNameValueCollection.SDKSupportedCapabilities = nameValueCollection[HttpConstants.HttpHeaders.SDKSupportedCapabilities]; + requestNameValueCollection.IsMaterializedViewBuild = nameValueCollection[HttpConstants.HttpHeaders.IsMaterializedViewBuild]; + requestNameValueCollection.BuilderClientIdentifier = nameValueCollection[HttpConstants.HttpHeaders.BuilderClientIdentifier]; + requestNameValueCollection.SourceCollectionIfMatch = nameValueCollection[WFConstants.BackendHeaders.SourceCollectionIfMatch]; + requestNameValueCollection.RequestedCollectionType = nameValueCollection[WFConstants.BackendHeaders.RequestedCollectionType]; + requestNameValueCollection.PopulateIndexMetrics = nameValueCollection[HttpConstants.HttpHeaders.PopulateIndexMetrics]; + requestNameValueCollection.PopulateAnalyticalMigrationProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress]; + requestNameValueCollection.ShouldReturnCurrentServerDateTime = nameValueCollection[HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime]; + requestNameValueCollection.RbacUserId = nameValueCollection[HttpConstants.HttpHeaders.RbacUserId]; + requestNameValueCollection.RbacAction = nameValueCollection[HttpConstants.HttpHeaders.RbacAction]; + requestNameValueCollection.RbacResource = nameValueCollection[HttpConstants.HttpHeaders.RbacResource]; + requestNameValueCollection.CorrelatedActivityId = nameValueCollection[HttpConstants.HttpHeaders.CorrelatedActivityId]; + requestNameValueCollection.IsThroughputCapRequest = nameValueCollection[HttpConstants.HttpHeaders.IsThroughputCapRequest]; + requestNameValueCollection.ChangeFeedWireFormatVersion = nameValueCollection[HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion]; + requestNameValueCollection.PopulateByokEncryptionProgress = nameValueCollection[HttpConstants.HttpHeaders.PopulateByokEncryptionProgress]; + requestNameValueCollection.UseUserBackgroundBudget = nameValueCollection[WFConstants.BackendHeaders.UseUserBackgroundBudget]; + requestNameValueCollection.IncludePhysicalPartitionThroughputInfo = nameValueCollection[HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo]; + requestNameValueCollection.IsServerlessStorageRefreshRequest = nameValueCollection[HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest]; + requestNameValueCollection.UpdateOfferStateToPending = nameValueCollection[HttpConstants.HttpHeaders.UpdateOfferStateToPending]; + requestNameValueCollection.PopulateOldestActiveSchemaId = nameValueCollection[HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId]; + requestNameValueCollection.IsInternalServerlessRequest = nameValueCollection[HttpConstants.HttpHeaders.IsInternalServerlessRequest]; + requestNameValueCollection.OfferReplaceRURedistribution = nameValueCollection[HttpConstants.HttpHeaders.OfferReplaceRURedistribution]; + requestNameValueCollection.IsCassandraAlterTypeRequest = nameValueCollection[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest]; + requestNameValueCollection.IsMaterializedViewSourceSchemaReplaceBatchRequest = nameValueCollection[HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest]; + requestNameValueCollection.ForceDatabaseAccountUpdate = nameValueCollection[HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate]; + requestNameValueCollection.PriorityLevel = nameValueCollection[HttpConstants.HttpHeaders.PriorityLevel]; + requestNameValueCollection.AllowRestoreParamsUpdate = nameValueCollection[HttpConstants.HttpHeaders.AllowRestoreParamsUpdate]; + requestNameValueCollection.PruneCollectionSchemas = nameValueCollection[HttpConstants.HttpHeaders.PruneCollectionSchemas]; + requestNameValueCollection.PopulateIndexMetricsV2 = nameValueCollection[HttpConstants.HttpHeaders.PopulateIndexMetricsV2]; + requestNameValueCollection.IsMigratedFixedCollection = nameValueCollection[HttpConstants.HttpHeaders.IsMigratedFixedCollection]; + requestNameValueCollection.SupportedSerializationFormats = nameValueCollection[HttpConstants.HttpHeaders.SupportedSerializationFormats]; + requestNameValueCollection.UpdateOfferStateToRestorePending = nameValueCollection[HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending]; + requestNameValueCollection.SetMasterResourcesDeletionPending = nameValueCollection[HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending]; + requestNameValueCollection.HighPriorityForcedBackup = nameValueCollection[HttpConstants.HttpHeaders.HighPriorityForcedBackup]; + requestNameValueCollection.OptimisticDirectExecute = nameValueCollection[HttpConstants.HttpHeaders.OptimisticDirectExecute]; + requestNameValueCollection.PopulateMinGLSNForDocumentOperations = nameValueCollection[WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations]; + requestNameValueCollection.PopulateHighestTentativeWriteLLSN = nameValueCollection[WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN]; + requestNameValueCollection.PopulateCapacityType = nameValueCollection[WFConstants.BackendHeaders.PopulateCapacityType]; + requestNameValueCollection.TraceParent = nameValueCollection[HttpConstants.HttpHeaders.TraceParent]; + requestNameValueCollection.TraceState = nameValueCollection[HttpConstants.HttpHeaders.TraceState]; + requestNameValueCollection.EnableConflictResolutionPolicyUpdate = nameValueCollection[HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate]; + requestNameValueCollection.ClientIpAddress = nameValueCollection[WFConstants.BackendHeaders.ClientIpAddress]; + requestNameValueCollection.IsRequestNotAuthorized = nameValueCollection[WFConstants.BackendHeaders.IsRequestNotAuthorized]; + requestNameValueCollection.AllowDocumentReadsInOfflineRegion = nameValueCollection[HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion]; + requestNameValueCollection.PopulateCurrentPartitionThroughputInfo = nameValueCollection[WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo]; + requestNameValueCollection.SkipThroughputCapValidation = nameValueCollection[WFConstants.BackendHeaders.SkipThroughputCapValidation]; + requestNameValueCollection.PopulateDocumentRecordCount = nameValueCollection[WFConstants.BackendHeaders.PopulateDocumentRecordCount]; + requestNameValueCollection.CosmosGatewayTransactionId = nameValueCollection[WFConstants.BackendHeaders.CosmosGatewayTransactionId]; + requestNameValueCollection.PopulateUserStrings = nameValueCollection[WFConstants.BackendHeaders.PopulateUserStrings]; + requestNameValueCollection.IfMatch = nameValueCollection[HttpConstants.HttpHeaders.IfMatch]; + requestNameValueCollection.NoRetryOn449StatusCode = nameValueCollection[HttpConstants.HttpHeaders.NoRetryOn449StatusCode]; + requestNameValueCollection.SkipAdjustThroughputFractionsForOfferReplace = nameValueCollection[HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace]; + requestNameValueCollection.SqlQueryForPartitionKeyExtraction = nameValueCollection[HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction]; + requestNameValueCollection.EnableCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.EnableCrossPartitionQuery]; + requestNameValueCollection.IsContinuationExpected = nameValueCollection[HttpConstants.HttpHeaders.IsContinuationExpected]; + requestNameValueCollection.ParallelizeCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery]; + requestNameValueCollection.SupportedQueryFeatures = nameValueCollection[HttpConstants.HttpHeaders.SupportedQueryFeatures]; + requestNameValueCollection.QueryVersion = nameValueCollection[HttpConstants.HttpHeaders.QueryVersion]; + requestNameValueCollection.ActivityId = nameValueCollection[HttpConstants.HttpHeaders.ActivityId]; + } + + return requestNameValueCollection; + } + + public string this[string key] + { + get => this.Get(key); + set => this.Set(key, value); + } + + public void Add(INameValueCollection collection) + { + if (collection == null) + { + throw new ArgumentNullException(nameof(collection)); + } + + foreach (string key in collection.Keys()) + { + this.Set(key, collection[key]); + } + } + + public string[] AllKeys() + { + return this.Keys().ToArray(); + } + + public void Clear() + { + if (this.notCommonHeaders != null) + { + this.notCommonHeaders.Clear(); + } + + this.A_IM = null; + this.ActivityId = null; + this.AddResourcePropertiesToResponse = null; + this.AllowDocumentReadsInOfflineRegion = null; + this.AllowRestoreParamsUpdate = null; + this.AllowTentativeWrites = null; + this.Authorization = null; + this.BinaryId = null; + this.BinaryPassthroughRequest = null; + this.BindReplicaDirective = null; + this.BuilderClientIdentifier = null; + this.CanCharge = null; + this.CanOfferReplaceComplete = null; + this.CanThrottle = null; + this.ChangeFeedStartFullFidelityIfNoneMatch = null; + this.ChangeFeedWireFormatVersion = null; + this.ClientIpAddress = null; + this.ClientRetryAttemptCount = null; + this.CollectionChildResourceContentLimitInKB = null; + this.CollectionChildResourceNameLimitInBytes = null; + this.CollectionPartitionIndex = null; + this.CollectionRemoteStorageSecurityIdentifier = null; + this.CollectionRid = null; + this.CollectionServiceIndex = null; + this.CollectionTruncate = null; + this.ConsistencyLevel = null; + this.ContentSerializationFormat = null; + this.Continuation = null; + this.CorrelatedActivityId = null; + this.CosmosGatewayTransactionId = null; + this.DisableRUPerMinuteUsage = null; + this.EffectivePartitionKey = null; + this.EmitVerboseTracesInQuery = null; + this.EnableConflictResolutionPolicyUpdate = null; + this.EnableCrossPartitionQuery = null; + this.EnableDynamicRidRangeAllocation = null; + this.EnableLogging = null; + this.EnableLowPrecisionOrderBy = null; + this.EnableScanInQuery = null; + this.EndEpk = null; + this.EndId = null; + this.EntityId = null; + this.EnumerationDirection = null; + this.ExcludeSystemProperties = null; + this.FanoutOperationState = null; + this.FilterBySchemaResourceId = null; + this.ForceDatabaseAccountUpdate = null; + this.ForceQueryScan = null; + this.ForceSideBySideIndexMigration = null; + this.GatewaySignature = null; + this.GetAllPartitionKeyStatistics = null; + this.HighPriorityForcedBackup = null; + this.HttpDate = null; + this.IfMatch = null; + this.IfModifiedSince = null; + this.IfNoneMatch = null; + this.IgnoreSystemLoweringMaxThroughput = null; + this.IncludePhysicalPartitionThroughputInfo = null; + this.IncludeTentativeWrites = null; + this.IndexingDirective = null; + this.IntendedCollectionRid = null; + this.IsAutoScaleRequest = null; + this.IsBatchAtomic = null; + this.IsBatchOrdered = null; + this.IsCassandraAlterTypeRequest = null; + this.IsClientEncrypted = null; + this.IsContinuationExpected = null; + this.IsFanoutRequest = null; + this.IsInternalServerlessRequest = null; + this.IsMaterializedViewBuild = null; + this.IsMaterializedViewSourceSchemaReplaceBatchRequest = null; + this.IsMigratedFixedCollection = null; + this.IsOfferStorageRefreshRequest = null; + this.IsReadOnlyScript = null; + this.IsRequestNotAuthorized = null; + this.IsRetriedWriteRequest = null; + this.IsRUPerGBEnforcementRequest = null; + this.IsServerlessStorageRefreshRequest = null; + this.IsThroughputCapRequest = null; + this.IsUserRequest = null; + this.MaxPollingIntervalMilliseconds = null; + this.MergeCheckPointGLSN = null; + this.MergeStaticId = null; + this.MigrateCollectionDirective = null; + this.MigrateOfferToAutopilot = null; + this.MigrateOfferToManualThroughput = null; + this.NoRetryOn449StatusCode = null; + this.OfferReplaceRURedistribution = null; + this.OptimisticDirectExecute = null; + this.PageSize = null; + this.ParallelizeCrossPartitionQuery = null; + this.PartitionCount = null; + this.PartitionKey = null; + this.PartitionKeyRangeId = null; + this.PartitionResourceFilter = null; + this.PopulateAnalyticalMigrationProgress = null; + this.PopulateByokEncryptionProgress = null; + this.PopulateCapacityType = null; + this.PopulateCollectionThroughputInfo = null; + this.PopulateCurrentPartitionThroughputInfo = null; + this.PopulateDocumentRecordCount = null; + this.PopulateHighestTentativeWriteLLSN = null; + this.PopulateIndexMetrics = null; + this.PopulateIndexMetricsV2 = null; + this.PopulateLogStoreInfo = null; + this.PopulateMinGLSNForDocumentOperations = null; + this.PopulateOldestActiveSchemaId = null; + this.PopulatePartitionStatistics = null; + this.PopulateQueryMetrics = null; + this.PopulateQuotaInfo = null; + this.PopulateResourceCount = null; + this.PopulateUnflushedMergeEntryCount = null; + this.PopulateUniqueIndexReIndexProgress = null; + this.PopulateUserStrings = null; + this.PostTriggerExclude = null; + this.PostTriggerInclude = null; + this.Prefer = null; + this.PreserveFullContent = null; + this.PreTriggerExclude = null; + this.PreTriggerInclude = null; + this.PrimaryMasterKey = null; + this.PrimaryReadonlyKey = null; + this.PriorityLevel = null; + this.ProfileRequest = null; + this.PruneCollectionSchemas = null; + this.QueryVersion = null; + this.RbacAction = null; + this.RbacResource = null; + this.RbacUserId = null; + this.ReadFeedKeyType = null; + this.RemainingTimeInMsOnClientRequest = null; + this.RemoteStorageType = null; + this.RequestedCollectionType = null; + this.ResourceId = null; + this.ResourceSchemaName = null; + this.ResourceTokenExpiry = null; + this.ResourceTypes = null; + this.ResponseContinuationTokenLimitInKB = null; + this.RestoreMetadataFilter = null; + this.RestoreParams = null; + this.RetriableWriteRequestId = null; + this.RetriableWriteRequestStartTimestamp = null; + this.SchemaHash = null; + this.SchemaId = null; + this.SchemaOwnerRid = null; + this.SDKSupportedCapabilities = null; + this.SecondaryMasterKey = null; + this.SecondaryReadonlyKey = null; + this.SessionToken = null; + this.SetMasterResourcesDeletionPending = null; + this.ShareThroughput = null; + this.ShouldBatchContinueOnError = null; + this.ShouldReturnCurrentServerDateTime = null; + this.SkipAdjustThroughputFractionsForOfferReplace = null; + this.SkipRefreshDatabaseAccountConfigs = null; + this.SkipThroughputCapValidation = null; + this.SourceCollectionIfMatch = null; + this.SqlQueryForPartitionKeyExtraction = null; + this.StartEpk = null; + this.StartId = null; + this.SupportedQueryFeatures = null; + this.SupportedSerializationFormats = null; + this.SupportSpatialLegacyCoordinates = null; + this.SystemDocumentType = null; + this.SystemRestoreOperation = null; + this.TargetGlobalCommittedLsn = null; + this.TargetLsn = null; + this.TimeToLiveInSeconds = null; + this.TraceParent = null; + this.TraceState = null; + this.TransactionCommit = null; + this.TransactionFirstRequest = null; + this.TransactionId = null; + this.TransportRequestID = null; + this.TruncateMergeLogRequest = null; + this.UniqueIndexNameEncodingMode = null; + this.UniqueIndexReIndexingState = null; + this.UpdateMaxThroughputEverProvisioned = null; + this.UpdateOfferStateToPending = null; + this.UpdateOfferStateToRestorePending = null; + this.UseArchivalPartition = null; + this.UsePolygonsSmallerThanAHemisphere = null; + this.UseSystemBudget = null; + this.UseUserBackgroundBudget = null; + this.Version = null; + this.XDate = null; + + } + + public INameValueCollection Clone() + { + RequestNameValueCollection cloneHeaders = new RequestNameValueCollection() + { + A_IM = this.A_IM, + ActivityId = this.ActivityId, + AddResourcePropertiesToResponse = this.AddResourcePropertiesToResponse, + AllowDocumentReadsInOfflineRegion = this.AllowDocumentReadsInOfflineRegion, + AllowRestoreParamsUpdate = this.AllowRestoreParamsUpdate, + AllowTentativeWrites = this.AllowTentativeWrites, + Authorization = this.Authorization, + BinaryId = this.BinaryId, + BinaryPassthroughRequest = this.BinaryPassthroughRequest, + BindReplicaDirective = this.BindReplicaDirective, + BuilderClientIdentifier = this.BuilderClientIdentifier, + CanCharge = this.CanCharge, + CanOfferReplaceComplete = this.CanOfferReplaceComplete, + CanThrottle = this.CanThrottle, + ChangeFeedStartFullFidelityIfNoneMatch = this.ChangeFeedStartFullFidelityIfNoneMatch, + ChangeFeedWireFormatVersion = this.ChangeFeedWireFormatVersion, + ClientIpAddress = this.ClientIpAddress, + ClientRetryAttemptCount = this.ClientRetryAttemptCount, + CollectionChildResourceContentLimitInKB = this.CollectionChildResourceContentLimitInKB, + CollectionChildResourceNameLimitInBytes = this.CollectionChildResourceNameLimitInBytes, + CollectionPartitionIndex = this.CollectionPartitionIndex, + CollectionRemoteStorageSecurityIdentifier = this.CollectionRemoteStorageSecurityIdentifier, + CollectionRid = this.CollectionRid, + CollectionServiceIndex = this.CollectionServiceIndex, + CollectionTruncate = this.CollectionTruncate, + ConsistencyLevel = this.ConsistencyLevel, + ContentSerializationFormat = this.ContentSerializationFormat, + Continuation = this.Continuation, + CorrelatedActivityId = this.CorrelatedActivityId, + CosmosGatewayTransactionId = this.CosmosGatewayTransactionId, + DisableRUPerMinuteUsage = this.DisableRUPerMinuteUsage, + EffectivePartitionKey = this.EffectivePartitionKey, + EmitVerboseTracesInQuery = this.EmitVerboseTracesInQuery, + EnableConflictResolutionPolicyUpdate = this.EnableConflictResolutionPolicyUpdate, + EnableCrossPartitionQuery = this.EnableCrossPartitionQuery, + EnableDynamicRidRangeAllocation = this.EnableDynamicRidRangeAllocation, + EnableLogging = this.EnableLogging, + EnableLowPrecisionOrderBy = this.EnableLowPrecisionOrderBy, + EnableScanInQuery = this.EnableScanInQuery, + EndEpk = this.EndEpk, + EndId = this.EndId, + EntityId = this.EntityId, + EnumerationDirection = this.EnumerationDirection, + ExcludeSystemProperties = this.ExcludeSystemProperties, + FanoutOperationState = this.FanoutOperationState, + FilterBySchemaResourceId = this.FilterBySchemaResourceId, + ForceDatabaseAccountUpdate = this.ForceDatabaseAccountUpdate, + ForceQueryScan = this.ForceQueryScan, + ForceSideBySideIndexMigration = this.ForceSideBySideIndexMigration, + GatewaySignature = this.GatewaySignature, + GetAllPartitionKeyStatistics = this.GetAllPartitionKeyStatistics, + HighPriorityForcedBackup = this.HighPriorityForcedBackup, + HttpDate = this.HttpDate, + IfMatch = this.IfMatch, + IfModifiedSince = this.IfModifiedSince, + IfNoneMatch = this.IfNoneMatch, + IgnoreSystemLoweringMaxThroughput = this.IgnoreSystemLoweringMaxThroughput, + IncludePhysicalPartitionThroughputInfo = this.IncludePhysicalPartitionThroughputInfo, + IncludeTentativeWrites = this.IncludeTentativeWrites, + IndexingDirective = this.IndexingDirective, + IntendedCollectionRid = this.IntendedCollectionRid, + IsAutoScaleRequest = this.IsAutoScaleRequest, + IsBatchAtomic = this.IsBatchAtomic, + IsBatchOrdered = this.IsBatchOrdered, + IsCassandraAlterTypeRequest = this.IsCassandraAlterTypeRequest, + IsClientEncrypted = this.IsClientEncrypted, + IsContinuationExpected = this.IsContinuationExpected, + IsFanoutRequest = this.IsFanoutRequest, + IsInternalServerlessRequest = this.IsInternalServerlessRequest, + IsMaterializedViewBuild = this.IsMaterializedViewBuild, + IsMaterializedViewSourceSchemaReplaceBatchRequest = this.IsMaterializedViewSourceSchemaReplaceBatchRequest, + IsMigratedFixedCollection = this.IsMigratedFixedCollection, + IsOfferStorageRefreshRequest = this.IsOfferStorageRefreshRequest, + IsReadOnlyScript = this.IsReadOnlyScript, + IsRequestNotAuthorized = this.IsRequestNotAuthorized, + IsRetriedWriteRequest = this.IsRetriedWriteRequest, + IsRUPerGBEnforcementRequest = this.IsRUPerGBEnforcementRequest, + IsServerlessStorageRefreshRequest = this.IsServerlessStorageRefreshRequest, + IsThroughputCapRequest = this.IsThroughputCapRequest, + IsUserRequest = this.IsUserRequest, + MaxPollingIntervalMilliseconds = this.MaxPollingIntervalMilliseconds, + MergeCheckPointGLSN = this.MergeCheckPointGLSN, + MergeStaticId = this.MergeStaticId, + MigrateCollectionDirective = this.MigrateCollectionDirective, + MigrateOfferToAutopilot = this.MigrateOfferToAutopilot, + MigrateOfferToManualThroughput = this.MigrateOfferToManualThroughput, + NoRetryOn449StatusCode = this.NoRetryOn449StatusCode, + OfferReplaceRURedistribution = this.OfferReplaceRURedistribution, + OptimisticDirectExecute = this.OptimisticDirectExecute, + PageSize = this.PageSize, + ParallelizeCrossPartitionQuery = this.ParallelizeCrossPartitionQuery, + PartitionCount = this.PartitionCount, + PartitionKey = this.PartitionKey, + PartitionKeyRangeId = this.PartitionKeyRangeId, + PartitionResourceFilter = this.PartitionResourceFilter, + PopulateAnalyticalMigrationProgress = this.PopulateAnalyticalMigrationProgress, + PopulateByokEncryptionProgress = this.PopulateByokEncryptionProgress, + PopulateCapacityType = this.PopulateCapacityType, + PopulateCollectionThroughputInfo = this.PopulateCollectionThroughputInfo, + PopulateCurrentPartitionThroughputInfo = this.PopulateCurrentPartitionThroughputInfo, + PopulateDocumentRecordCount = this.PopulateDocumentRecordCount, + PopulateHighestTentativeWriteLLSN = this.PopulateHighestTentativeWriteLLSN, + PopulateIndexMetrics = this.PopulateIndexMetrics, + PopulateIndexMetricsV2 = this.PopulateIndexMetricsV2, + PopulateLogStoreInfo = this.PopulateLogStoreInfo, + PopulateMinGLSNForDocumentOperations = this.PopulateMinGLSNForDocumentOperations, + PopulateOldestActiveSchemaId = this.PopulateOldestActiveSchemaId, + PopulatePartitionStatistics = this.PopulatePartitionStatistics, + PopulateQueryMetrics = this.PopulateQueryMetrics, + PopulateQuotaInfo = this.PopulateQuotaInfo, + PopulateResourceCount = this.PopulateResourceCount, + PopulateUnflushedMergeEntryCount = this.PopulateUnflushedMergeEntryCount, + PopulateUniqueIndexReIndexProgress = this.PopulateUniqueIndexReIndexProgress, + PopulateUserStrings = this.PopulateUserStrings, + PostTriggerExclude = this.PostTriggerExclude, + PostTriggerInclude = this.PostTriggerInclude, + Prefer = this.Prefer, + PreserveFullContent = this.PreserveFullContent, + PreTriggerExclude = this.PreTriggerExclude, + PreTriggerInclude = this.PreTriggerInclude, + PrimaryMasterKey = this.PrimaryMasterKey, + PrimaryReadonlyKey = this.PrimaryReadonlyKey, + PriorityLevel = this.PriorityLevel, + ProfileRequest = this.ProfileRequest, + PruneCollectionSchemas = this.PruneCollectionSchemas, + QueryVersion = this.QueryVersion, + RbacAction = this.RbacAction, + RbacResource = this.RbacResource, + RbacUserId = this.RbacUserId, + ReadFeedKeyType = this.ReadFeedKeyType, + RemainingTimeInMsOnClientRequest = this.RemainingTimeInMsOnClientRequest, + RemoteStorageType = this.RemoteStorageType, + RequestedCollectionType = this.RequestedCollectionType, + ResourceId = this.ResourceId, + ResourceSchemaName = this.ResourceSchemaName, + ResourceTokenExpiry = this.ResourceTokenExpiry, + ResourceTypes = this.ResourceTypes, + ResponseContinuationTokenLimitInKB = this.ResponseContinuationTokenLimitInKB, + RestoreMetadataFilter = this.RestoreMetadataFilter, + RestoreParams = this.RestoreParams, + RetriableWriteRequestId = this.RetriableWriteRequestId, + RetriableWriteRequestStartTimestamp = this.RetriableWriteRequestStartTimestamp, + SchemaHash = this.SchemaHash, + SchemaId = this.SchemaId, + SchemaOwnerRid = this.SchemaOwnerRid, + SDKSupportedCapabilities = this.SDKSupportedCapabilities, + SecondaryMasterKey = this.SecondaryMasterKey, + SecondaryReadonlyKey = this.SecondaryReadonlyKey, + SessionToken = this.SessionToken, + SetMasterResourcesDeletionPending = this.SetMasterResourcesDeletionPending, + ShareThroughput = this.ShareThroughput, + ShouldBatchContinueOnError = this.ShouldBatchContinueOnError, + ShouldReturnCurrentServerDateTime = this.ShouldReturnCurrentServerDateTime, + SkipAdjustThroughputFractionsForOfferReplace = this.SkipAdjustThroughputFractionsForOfferReplace, + SkipRefreshDatabaseAccountConfigs = this.SkipRefreshDatabaseAccountConfigs, + SkipThroughputCapValidation = this.SkipThroughputCapValidation, + SourceCollectionIfMatch = this.SourceCollectionIfMatch, + SqlQueryForPartitionKeyExtraction = this.SqlQueryForPartitionKeyExtraction, + StartEpk = this.StartEpk, + StartId = this.StartId, + SupportedQueryFeatures = this.SupportedQueryFeatures, + SupportedSerializationFormats = this.SupportedSerializationFormats, + SupportSpatialLegacyCoordinates = this.SupportSpatialLegacyCoordinates, + SystemDocumentType = this.SystemDocumentType, + SystemRestoreOperation = this.SystemRestoreOperation, + TargetGlobalCommittedLsn = this.TargetGlobalCommittedLsn, + TargetLsn = this.TargetLsn, + TimeToLiveInSeconds = this.TimeToLiveInSeconds, + TraceParent = this.TraceParent, + TraceState = this.TraceState, + TransactionCommit = this.TransactionCommit, + TransactionFirstRequest = this.TransactionFirstRequest, + TransactionId = this.TransactionId, + TransportRequestID = this.TransportRequestID, + TruncateMergeLogRequest = this.TruncateMergeLogRequest, + UniqueIndexNameEncodingMode = this.UniqueIndexNameEncodingMode, + UniqueIndexReIndexingState = this.UniqueIndexReIndexingState, + UpdateMaxThroughputEverProvisioned = this.UpdateMaxThroughputEverProvisioned, + UpdateOfferStateToPending = this.UpdateOfferStateToPending, + UpdateOfferStateToRestorePending = this.UpdateOfferStateToRestorePending, + UseArchivalPartition = this.UseArchivalPartition, + UsePolygonsSmallerThanAHemisphere = this.UsePolygonsSmallerThanAHemisphere, + UseSystemBudget = this.UseSystemBudget, + UseUserBackgroundBudget = this.UseUserBackgroundBudget, + Version = this.Version, + XDate = this.XDate, + }; + + if (this.notCommonHeaders != null) + { + cloneHeaders.notCommonHeaders = new Dictionary(this.notCommonHeaders, RequestNameValueCollection.DefaultStringComparer); + } + + return cloneHeaders; + } + + public int Count() + { + return this.Keys().Count(); + } + + public IEnumerator GetEnumerator() + { + return this.Keys().GetEnumerator(); + } + + public string[] GetValues(string key) + { + string value = this.Get(key); + if (value != null) + { + return new string[] { value }; + } + + return null; + } + + public IEnumerable Keys() + { + if (this.ResourceId != null) + { + yield return WFConstants.BackendHeaders.ResourceId; + } + if (this.Authorization != null) + { + yield return HttpConstants.HttpHeaders.Authorization; + } + if (this.HttpDate != null) + { + yield return HttpConstants.HttpHeaders.HttpDate; + } + if (this.XDate != null) + { + yield return HttpConstants.HttpHeaders.XDate; + } + if (this.PageSize != null) + { + yield return HttpConstants.HttpHeaders.PageSize; + } + if (this.SessionToken != null) + { + yield return HttpConstants.HttpHeaders.SessionToken; + } + if (this.Continuation != null) + { + yield return HttpConstants.HttpHeaders.Continuation; + } + if (this.IndexingDirective != null) + { + yield return HttpConstants.HttpHeaders.IndexingDirective; + } + if (this.IfNoneMatch != null) + { + yield return HttpConstants.HttpHeaders.IfNoneMatch; + } + if (this.PreTriggerInclude != null) + { + yield return HttpConstants.HttpHeaders.PreTriggerInclude; + } + if (this.PostTriggerInclude != null) + { + yield return HttpConstants.HttpHeaders.PostTriggerInclude; + } + if (this.IsFanoutRequest != null) + { + yield return WFConstants.BackendHeaders.IsFanoutRequest; + } + if (this.CollectionPartitionIndex != null) + { + yield return WFConstants.BackendHeaders.CollectionPartitionIndex; + } + if (this.CollectionServiceIndex != null) + { + yield return WFConstants.BackendHeaders.CollectionServiceIndex; + } + if (this.PreTriggerExclude != null) + { + yield return HttpConstants.HttpHeaders.PreTriggerExclude; + } + if (this.PostTriggerExclude != null) + { + yield return HttpConstants.HttpHeaders.PostTriggerExclude; + } + if (this.ConsistencyLevel != null) + { + yield return HttpConstants.HttpHeaders.ConsistencyLevel; + } + if (this.EntityId != null) + { + yield return WFConstants.BackendHeaders.EntityId; + } + if (this.ResourceSchemaName != null) + { + yield return WFConstants.BackendHeaders.ResourceSchemaName; + } + if (this.ResourceTokenExpiry != null) + { + yield return HttpConstants.HttpHeaders.ResourceTokenExpiry; + } + if (this.EnableScanInQuery != null) + { + yield return HttpConstants.HttpHeaders.EnableScanInQuery; + } + if (this.EmitVerboseTracesInQuery != null) + { + yield return HttpConstants.HttpHeaders.EmitVerboseTracesInQuery; + } + if (this.BindReplicaDirective != null) + { + yield return WFConstants.BackendHeaders.BindReplicaDirective; + } + if (this.PrimaryMasterKey != null) + { + yield return WFConstants.BackendHeaders.PrimaryMasterKey; + } + if (this.SecondaryMasterKey != null) + { + yield return WFConstants.BackendHeaders.SecondaryMasterKey; + } + if (this.PrimaryReadonlyKey != null) + { + yield return WFConstants.BackendHeaders.PrimaryReadonlyKey; + } + if (this.SecondaryReadonlyKey != null) + { + yield return WFConstants.BackendHeaders.SecondaryReadonlyKey; + } + if (this.ProfileRequest != null) + { + yield return HttpConstants.HttpHeaders.ProfileRequest; + } + if (this.EnableLowPrecisionOrderBy != null) + { + yield return HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy; + } + if (this.Version != null) + { + yield return HttpConstants.HttpHeaders.Version; + } + if (this.CanCharge != null) + { + yield return HttpConstants.HttpHeaders.CanCharge; + } + if (this.CanThrottle != null) + { + yield return HttpConstants.HttpHeaders.CanThrottle; + } + if (this.PartitionKey != null) + { + yield return HttpConstants.HttpHeaders.PartitionKey; + } + if (this.PartitionKeyRangeId != null) + { + yield return HttpConstants.HttpHeaders.PartitionKeyRangeId; + } + if (this.MigrateCollectionDirective != null) + { + yield return HttpConstants.HttpHeaders.MigrateCollectionDirective; + } + if (this.SupportSpatialLegacyCoordinates != null) + { + yield return HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates; + } + if (this.PartitionCount != null) + { + yield return HttpConstants.HttpHeaders.PartitionCount; + } + if (this.CollectionRid != null) + { + yield return WFConstants.BackendHeaders.CollectionRid; + } + if (this.FilterBySchemaResourceId != null) + { + yield return HttpConstants.HttpHeaders.FilterBySchemaResourceId; + } + if (this.UsePolygonsSmallerThanAHemisphere != null) + { + yield return HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere; + } + if (this.GatewaySignature != null) + { + yield return HttpConstants.HttpHeaders.GatewaySignature; + } + if (this.EnableLogging != null) + { + yield return HttpConstants.HttpHeaders.EnableLogging; + } + if (this.A_IM != null) + { + yield return HttpConstants.HttpHeaders.A_IM; + } + if (this.PopulateQuotaInfo != null) + { + yield return HttpConstants.HttpHeaders.PopulateQuotaInfo; + } + if (this.DisableRUPerMinuteUsage != null) + { + yield return HttpConstants.HttpHeaders.DisableRUPerMinuteUsage; + } + if (this.PopulateQueryMetrics != null) + { + yield return HttpConstants.HttpHeaders.PopulateQueryMetrics; + } + if (this.ResponseContinuationTokenLimitInKB != null) + { + yield return HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB; + } + if (this.PopulatePartitionStatistics != null) + { + yield return HttpConstants.HttpHeaders.PopulatePartitionStatistics; + } + if (this.RemoteStorageType != null) + { + yield return WFConstants.BackendHeaders.RemoteStorageType; + } + if (this.CollectionRemoteStorageSecurityIdentifier != null) + { + yield return HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier; + } + if (this.IfModifiedSince != null) + { + yield return HttpConstants.HttpHeaders.IfModifiedSince; + } + if (this.PopulateCollectionThroughputInfo != null) + { + yield return HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo; + } + if (this.RemainingTimeInMsOnClientRequest != null) + { + yield return HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest; + } + if (this.ClientRetryAttemptCount != null) + { + yield return HttpConstants.HttpHeaders.ClientRetryAttemptCount; + } + if (this.TargetLsn != null) + { + yield return HttpConstants.HttpHeaders.TargetLsn; + } + if (this.TargetGlobalCommittedLsn != null) + { + yield return HttpConstants.HttpHeaders.TargetGlobalCommittedLsn; + } + if (this.TransportRequestID != null) + { + yield return HttpConstants.HttpHeaders.TransportRequestID; + } + if (this.RestoreMetadataFilter != null) + { + yield return HttpConstants.HttpHeaders.RestoreMetadataFilter; + } + if (this.RestoreParams != null) + { + yield return WFConstants.BackendHeaders.RestoreParams; + } + if (this.ShareThroughput != null) + { + yield return WFConstants.BackendHeaders.ShareThroughput; + } + if (this.PartitionResourceFilter != null) + { + yield return WFConstants.BackendHeaders.PartitionResourceFilter; + } + if (this.IsReadOnlyScript != null) + { + yield return HttpConstants.HttpHeaders.IsReadOnlyScript; + } + if (this.IsAutoScaleRequest != null) + { + yield return HttpConstants.HttpHeaders.IsAutoScaleRequest; + } + if (this.ForceQueryScan != null) + { + yield return HttpConstants.HttpHeaders.ForceQueryScan; + } + if (this.CanOfferReplaceComplete != null) + { + yield return HttpConstants.HttpHeaders.CanOfferReplaceComplete; + } + if (this.ExcludeSystemProperties != null) + { + yield return WFConstants.BackendHeaders.ExcludeSystemProperties; + } + if (this.BinaryId != null) + { + yield return WFConstants.BackendHeaders.BinaryId; + } + if (this.TimeToLiveInSeconds != null) + { + yield return WFConstants.BackendHeaders.TimeToLiveInSeconds; + } + if (this.EffectivePartitionKey != null) + { + yield return WFConstants.BackendHeaders.EffectivePartitionKey; + } + if (this.BinaryPassthroughRequest != null) + { + yield return WFConstants.BackendHeaders.BinaryPassthroughRequest; + } + if (this.EnableDynamicRidRangeAllocation != null) + { + yield return WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation; + } + if (this.EnumerationDirection != null) + { + yield return HttpConstants.HttpHeaders.EnumerationDirection; + } + if (this.StartId != null) + { + yield return HttpConstants.HttpHeaders.StartId; + } + if (this.EndId != null) + { + yield return HttpConstants.HttpHeaders.EndId; + } + if (this.FanoutOperationState != null) + { + yield return WFConstants.BackendHeaders.FanoutOperationState; + } + if (this.StartEpk != null) + { + yield return HttpConstants.HttpHeaders.StartEpk; + } + if (this.EndEpk != null) + { + yield return HttpConstants.HttpHeaders.EndEpk; + } + if (this.ReadFeedKeyType != null) + { + yield return HttpConstants.HttpHeaders.ReadFeedKeyType; + } + if (this.ContentSerializationFormat != null) + { + yield return HttpConstants.HttpHeaders.ContentSerializationFormat; + } + if (this.AllowTentativeWrites != null) + { + yield return HttpConstants.HttpHeaders.AllowTentativeWrites; + } + if (this.IsUserRequest != null) + { + yield return WFConstants.BackendHeaders.IsUserRequest; + } + if (this.PreserveFullContent != null) + { + yield return HttpConstants.HttpHeaders.PreserveFullContent; + } + if (this.IncludeTentativeWrites != null) + { + yield return HttpConstants.HttpHeaders.IncludeTentativeWrites; + } + if (this.PopulateResourceCount != null) + { + yield return HttpConstants.HttpHeaders.PopulateResourceCount; + } + if (this.MergeStaticId != null) + { + yield return HttpConstants.HttpHeaders.MergeStaticId; + } + if (this.IsBatchAtomic != null) + { + yield return HttpConstants.HttpHeaders.IsBatchAtomic; + } + if (this.ShouldBatchContinueOnError != null) + { + yield return HttpConstants.HttpHeaders.ShouldBatchContinueOnError; + } + if (this.IsBatchOrdered != null) + { + yield return HttpConstants.HttpHeaders.IsBatchOrdered; + } + if (this.SchemaOwnerRid != null) + { + yield return WFConstants.BackendHeaders.SchemaOwnerRid; + } + if (this.SchemaHash != null) + { + yield return WFConstants.BackendHeaders.SchemaHash; + } + if (this.IsRUPerGBEnforcementRequest != null) + { + yield return HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest; + } + if (this.MaxPollingIntervalMilliseconds != null) + { + yield return HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds; + } + if (this.PopulateLogStoreInfo != null) + { + yield return WFConstants.BackendHeaders.PopulateLogStoreInfo; + } + if (this.GetAllPartitionKeyStatistics != null) + { + yield return HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics; + } + if (this.ForceSideBySideIndexMigration != null) + { + yield return HttpConstants.HttpHeaders.ForceSideBySideIndexMigration; + } + if (this.CollectionChildResourceNameLimitInBytes != null) + { + yield return WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes; + } + if (this.CollectionChildResourceContentLimitInKB != null) + { + yield return WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB; + } + if (this.MergeCheckPointGLSN != null) + { + yield return WFConstants.BackendHeaders.MergeCheckPointGLSN; + } + if (this.Prefer != null) + { + yield return HttpConstants.HttpHeaders.Prefer; + } + if (this.UniqueIndexNameEncodingMode != null) + { + yield return WFConstants.BackendHeaders.UniqueIndexNameEncodingMode; + } + if (this.PopulateUnflushedMergeEntryCount != null) + { + yield return WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount; + } + if (this.MigrateOfferToManualThroughput != null) + { + yield return HttpConstants.HttpHeaders.MigrateOfferToManualThroughput; + } + if (this.MigrateOfferToAutopilot != null) + { + yield return HttpConstants.HttpHeaders.MigrateOfferToAutopilot; + } + if (this.IsClientEncrypted != null) + { + yield return HttpConstants.HttpHeaders.IsClientEncrypted; + } + if (this.SystemDocumentType != null) + { + yield return HttpConstants.HttpHeaders.SystemDocumentType; + } + if (this.IsOfferStorageRefreshRequest != null) + { + yield return HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest; + } + if (this.ResourceTypes != null) + { + yield return WFConstants.BackendHeaders.ResourceTypes; + } + if (this.TransactionId != null) + { + yield return WFConstants.BackendHeaders.TransactionId; + } + if (this.TransactionFirstRequest != null) + { + yield return WFConstants.BackendHeaders.TransactionFirstRequest; + } + if (this.TransactionCommit != null) + { + yield return WFConstants.BackendHeaders.TransactionCommit; + } + if (this.UpdateMaxThroughputEverProvisioned != null) + { + yield return HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned; + } + if (this.UniqueIndexReIndexingState != null) + { + yield return WFConstants.BackendHeaders.UniqueIndexReIndexingState; + } + if (this.UseSystemBudget != null) + { + yield return WFConstants.BackendHeaders.UseSystemBudget; + } + if (this.IgnoreSystemLoweringMaxThroughput != null) + { + yield return HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput; + } + if (this.TruncateMergeLogRequest != null) + { + yield return HttpConstants.HttpHeaders.TruncateMergeLogRequest; + } + if (this.RetriableWriteRequestId != null) + { + yield return WFConstants.BackendHeaders.RetriableWriteRequestId; + } + if (this.IsRetriedWriteRequest != null) + { + yield return WFConstants.BackendHeaders.IsRetriedWriteRequest; + } + if (this.RetriableWriteRequestStartTimestamp != null) + { + yield return WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp; + } + if (this.AddResourcePropertiesToResponse != null) + { + yield return WFConstants.BackendHeaders.AddResourcePropertiesToResponse; + } + if (this.ChangeFeedStartFullFidelityIfNoneMatch != null) + { + yield return HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch; + } + if (this.SystemRestoreOperation != null) + { + yield return HttpConstants.HttpHeaders.SystemRestoreOperation; + } + if (this.SkipRefreshDatabaseAccountConfigs != null) + { + yield return WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs; + } + if (this.IntendedCollectionRid != null) + { + yield return WFConstants.BackendHeaders.IntendedCollectionRid; + } + if (this.UseArchivalPartition != null) + { + yield return HttpConstants.HttpHeaders.UseArchivalPartition; + } + if (this.PopulateUniqueIndexReIndexProgress != null) + { + yield return HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress; + } + if (this.SchemaId != null) + { + yield return WFConstants.BackendHeaders.SchemaId; + } + if (this.CollectionTruncate != null) + { + yield return HttpConstants.HttpHeaders.CollectionTruncate; + } + if (this.SDKSupportedCapabilities != null) + { + yield return HttpConstants.HttpHeaders.SDKSupportedCapabilities; + } + if (this.IsMaterializedViewBuild != null) + { + yield return HttpConstants.HttpHeaders.IsMaterializedViewBuild; + } + if (this.BuilderClientIdentifier != null) + { + yield return HttpConstants.HttpHeaders.BuilderClientIdentifier; + } + if (this.SourceCollectionIfMatch != null) + { + yield return WFConstants.BackendHeaders.SourceCollectionIfMatch; + } + if (this.RequestedCollectionType != null) + { + yield return WFConstants.BackendHeaders.RequestedCollectionType; + } + if (this.PopulateIndexMetrics != null) + { + yield return HttpConstants.HttpHeaders.PopulateIndexMetrics; + } + if (this.PopulateAnalyticalMigrationProgress != null) + { + yield return HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress; + } + if (this.ShouldReturnCurrentServerDateTime != null) + { + yield return HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime; + } + if (this.RbacUserId != null) + { + yield return HttpConstants.HttpHeaders.RbacUserId; + } + if (this.RbacAction != null) + { + yield return HttpConstants.HttpHeaders.RbacAction; + } + if (this.RbacResource != null) + { + yield return HttpConstants.HttpHeaders.RbacResource; + } + if (this.CorrelatedActivityId != null) + { + yield return HttpConstants.HttpHeaders.CorrelatedActivityId; + } + if (this.IsThroughputCapRequest != null) + { + yield return HttpConstants.HttpHeaders.IsThroughputCapRequest; + } + if (this.ChangeFeedWireFormatVersion != null) + { + yield return HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion; + } + if (this.PopulateByokEncryptionProgress != null) + { + yield return HttpConstants.HttpHeaders.PopulateByokEncryptionProgress; + } + if (this.UseUserBackgroundBudget != null) + { + yield return WFConstants.BackendHeaders.UseUserBackgroundBudget; + } + if (this.IncludePhysicalPartitionThroughputInfo != null) + { + yield return HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo; + } + if (this.IsServerlessStorageRefreshRequest != null) + { + yield return HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest; + } + if (this.UpdateOfferStateToPending != null) + { + yield return HttpConstants.HttpHeaders.UpdateOfferStateToPending; + } + if (this.PopulateOldestActiveSchemaId != null) + { + yield return HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId; + } + if (this.IsInternalServerlessRequest != null) + { + yield return HttpConstants.HttpHeaders.IsInternalServerlessRequest; + } + if (this.OfferReplaceRURedistribution != null) + { + yield return HttpConstants.HttpHeaders.OfferReplaceRURedistribution; + } + if (this.IsCassandraAlterTypeRequest != null) + { + yield return HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest; + } + if (this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) + { + yield return HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest; + } + if (this.ForceDatabaseAccountUpdate != null) + { + yield return HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate; + } + if (this.PriorityLevel != null) + { + yield return HttpConstants.HttpHeaders.PriorityLevel; + } + if (this.AllowRestoreParamsUpdate != null) + { + yield return HttpConstants.HttpHeaders.AllowRestoreParamsUpdate; + } + if (this.PruneCollectionSchemas != null) + { + yield return HttpConstants.HttpHeaders.PruneCollectionSchemas; + } + if (this.PopulateIndexMetricsV2 != null) + { + yield return HttpConstants.HttpHeaders.PopulateIndexMetricsV2; + } + if (this.IsMigratedFixedCollection != null) + { + yield return HttpConstants.HttpHeaders.IsMigratedFixedCollection; + } + if (this.SupportedSerializationFormats != null) + { + yield return HttpConstants.HttpHeaders.SupportedSerializationFormats; + } + if (this.UpdateOfferStateToRestorePending != null) + { + yield return HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending; + } + if (this.SetMasterResourcesDeletionPending != null) + { + yield return HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending; + } + if (this.HighPriorityForcedBackup != null) + { + yield return HttpConstants.HttpHeaders.HighPriorityForcedBackup; + } + if (this.OptimisticDirectExecute != null) + { + yield return HttpConstants.HttpHeaders.OptimisticDirectExecute; + } + if (this.PopulateMinGLSNForDocumentOperations != null) + { + yield return WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations; + } + if (this.PopulateHighestTentativeWriteLLSN != null) + { + yield return WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN; + } + if (this.PopulateCapacityType != null) + { + yield return WFConstants.BackendHeaders.PopulateCapacityType; + } + if (this.TraceParent != null) + { + yield return HttpConstants.HttpHeaders.TraceParent; + } + if (this.TraceState != null) + { + yield return HttpConstants.HttpHeaders.TraceState; + } + if (this.EnableConflictResolutionPolicyUpdate != null) + { + yield return HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate; + } + if (this.ClientIpAddress != null) + { + yield return WFConstants.BackendHeaders.ClientIpAddress; + } + if (this.IsRequestNotAuthorized != null) + { + yield return WFConstants.BackendHeaders.IsRequestNotAuthorized; + } + if (this.AllowDocumentReadsInOfflineRegion != null) + { + yield return HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion; + } + if (this.PopulateCurrentPartitionThroughputInfo != null) + { + yield return WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo; + } + if (this.SkipThroughputCapValidation != null) + { + yield return WFConstants.BackendHeaders.SkipThroughputCapValidation; + } + if (this.PopulateDocumentRecordCount != null) + { + yield return WFConstants.BackendHeaders.PopulateDocumentRecordCount; + } + if (this.CosmosGatewayTransactionId != null) + { + yield return WFConstants.BackendHeaders.CosmosGatewayTransactionId; + } + if (this.PopulateUserStrings != null) + { + yield return WFConstants.BackendHeaders.PopulateUserStrings; + } + if (this.IfMatch != null) + { + yield return HttpConstants.HttpHeaders.IfMatch; + } + if (this.NoRetryOn449StatusCode != null) + { + yield return HttpConstants.HttpHeaders.NoRetryOn449StatusCode; + } + if (this.SkipAdjustThroughputFractionsForOfferReplace != null) + { + yield return HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace; + } + if (this.SqlQueryForPartitionKeyExtraction != null) + { + yield return HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction; + } + if (this.EnableCrossPartitionQuery != null) + { + yield return HttpConstants.HttpHeaders.EnableCrossPartitionQuery; + } + if (this.IsContinuationExpected != null) + { + yield return HttpConstants.HttpHeaders.IsContinuationExpected; + } + if (this.ParallelizeCrossPartitionQuery != null) + { + yield return HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery; + } + if (this.SupportedQueryFeatures != null) + { + yield return HttpConstants.HttpHeaders.SupportedQueryFeatures; + } + if (this.QueryVersion != null) + { + yield return HttpConstants.HttpHeaders.QueryVersion; + } + if (this.ActivityId != null) + { + yield return HttpConstants.HttpHeaders.ActivityId; + } + + if (this.notCommonHeaders != null) + { + foreach (string key in this.notCommonHeaders.Keys) + { + yield return key; + } + } + } + + public NameValueCollection ToNameValueCollection() + { + // Note: See comment on line 34 of this file for the implementation. We need to respect current contracts + // for Backend Gateway. + if (this.nameValueCollection == null) + { + lock (this) + { + if (this.nameValueCollection == null) + { + this.nameValueCollection = new NameValueCollection(this.Count(), RequestNameValueCollection.DefaultStringComparer); + + if (this.ResourceId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceId, this.ResourceId); + } + if (this.Authorization != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.Authorization, this.Authorization); + } + if (this.HttpDate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.HttpDate, this.HttpDate); + } + if (this.XDate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.XDate, this.XDate); + } + if (this.PageSize != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PageSize, this.PageSize); + } + if (this.SessionToken != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); + } + if (this.Continuation != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.Continuation, this.Continuation); + } + if (this.IndexingDirective != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); + } + if (this.IfNoneMatch != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfNoneMatch, this.IfNoneMatch); + } + if (this.PreTriggerInclude != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreTriggerInclude, this.PreTriggerInclude); + } + if (this.PostTriggerInclude != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PostTriggerInclude, this.PostTriggerInclude); + } + if (this.IsFanoutRequest != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsFanoutRequest, this.IsFanoutRequest); + } + if (this.CollectionPartitionIndex != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); + } + if (this.CollectionServiceIndex != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); + } + if (this.PreTriggerExclude != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreTriggerExclude, this.PreTriggerExclude); + } + if (this.PostTriggerExclude != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PostTriggerExclude, this.PostTriggerExclude); + } + if (this.ConsistencyLevel != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ConsistencyLevel, this.ConsistencyLevel); + } + if (this.EntityId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.EntityId, this.EntityId); + } + if (this.ResourceSchemaName != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceSchemaName, this.ResourceSchemaName); + } + if (this.ResourceTokenExpiry != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ResourceTokenExpiry, this.ResourceTokenExpiry); + } + if (this.EnableScanInQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableScanInQuery, this.EnableScanInQuery); + } + if (this.EmitVerboseTracesInQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, this.EmitVerboseTracesInQuery); + } + if (this.BindReplicaDirective != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.BindReplicaDirective, this.BindReplicaDirective); + } + if (this.PrimaryMasterKey != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PrimaryMasterKey, this.PrimaryMasterKey); + } + if (this.SecondaryMasterKey != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SecondaryMasterKey, this.SecondaryMasterKey); + } + if (this.PrimaryReadonlyKey != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PrimaryReadonlyKey, this.PrimaryReadonlyKey); + } + if (this.SecondaryReadonlyKey != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SecondaryReadonlyKey, this.SecondaryReadonlyKey); + } + if (this.ProfileRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ProfileRequest, this.ProfileRequest); + } + if (this.EnableLowPrecisionOrderBy != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, this.EnableLowPrecisionOrderBy); + } + if (this.Version != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.Version, this.Version); + } + if (this.CanCharge != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanCharge, this.CanCharge); + } + if (this.CanThrottle != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanThrottle, this.CanThrottle); + } + if (this.PartitionKey != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionKey, this.PartitionKey); + } + if (this.PartitionKeyRangeId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); + } + if (this.MigrateCollectionDirective != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateCollectionDirective, this.MigrateCollectionDirective); + } + if (this.SupportSpatialLegacyCoordinates != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, this.SupportSpatialLegacyCoordinates); + } + if (this.PartitionCount != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PartitionCount, this.PartitionCount); + } + if (this.CollectionRid != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionRid, this.CollectionRid); + } + if (this.FilterBySchemaResourceId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.FilterBySchemaResourceId, this.FilterBySchemaResourceId); + } + if (this.UsePolygonsSmallerThanAHemisphere != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, this.UsePolygonsSmallerThanAHemisphere); + } + if (this.GatewaySignature != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.GatewaySignature, this.GatewaySignature); + } + if (this.EnableLogging != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableLogging, this.EnableLogging); + } + if (this.A_IM != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.A_IM, this.A_IM); + } + if (this.PopulateQuotaInfo != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateQuotaInfo, this.PopulateQuotaInfo); + } + if (this.DisableRUPerMinuteUsage != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, this.DisableRUPerMinuteUsage); + } + if (this.PopulateQueryMetrics != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateQueryMetrics, this.PopulateQueryMetrics); + } + if (this.ResponseContinuationTokenLimitInKB != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, this.ResponseContinuationTokenLimitInKB); + } + if (this.PopulatePartitionStatistics != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulatePartitionStatistics, this.PopulatePartitionStatistics); + } + if (this.RemoteStorageType != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RemoteStorageType, this.RemoteStorageType); + } + if (this.CollectionRemoteStorageSecurityIdentifier != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, this.CollectionRemoteStorageSecurityIdentifier); + } + if (this.IfModifiedSince != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfModifiedSince, this.IfModifiedSince); + } + if (this.PopulateCollectionThroughputInfo != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, this.PopulateCollectionThroughputInfo); + } + if (this.RemainingTimeInMsOnClientRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, this.RemainingTimeInMsOnClientRequest); + } + if (this.ClientRetryAttemptCount != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ClientRetryAttemptCount, this.ClientRetryAttemptCount); + } + if (this.TargetLsn != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TargetLsn, this.TargetLsn); + } + if (this.TargetGlobalCommittedLsn != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, this.TargetGlobalCommittedLsn); + } + if (this.TransportRequestID != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); + } + if (this.RestoreMetadataFilter != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RestoreMetadataFilter, this.RestoreMetadataFilter); + } + if (this.RestoreParams != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RestoreParams, this.RestoreParams); + } + if (this.ShareThroughput != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); + } + if (this.PartitionResourceFilter != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionResourceFilter, this.PartitionResourceFilter); + } + if (this.IsReadOnlyScript != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsReadOnlyScript, this.IsReadOnlyScript); + } + if (this.IsAutoScaleRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsAutoScaleRequest, this.IsAutoScaleRequest); + } + if (this.ForceQueryScan != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceQueryScan, this.ForceQueryScan); + } + if (this.CanOfferReplaceComplete != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CanOfferReplaceComplete, this.CanOfferReplaceComplete); + } + if (this.ExcludeSystemProperties != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ExcludeSystemProperties, this.ExcludeSystemProperties); + } + if (this.BinaryId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.BinaryId, this.BinaryId); + } + if (this.TimeToLiveInSeconds != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); + } + if (this.EffectivePartitionKey != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.EffectivePartitionKey, this.EffectivePartitionKey); + } + if (this.BinaryPassthroughRequest != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.BinaryPassthroughRequest, this.BinaryPassthroughRequest); + } + if (this.EnableDynamicRidRangeAllocation != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, this.EnableDynamicRidRangeAllocation); + } + if (this.EnumerationDirection != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnumerationDirection, this.EnumerationDirection); + } + if (this.StartId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.StartId, this.StartId); + } + if (this.EndId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EndId, this.EndId); + } + if (this.FanoutOperationState != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.FanoutOperationState, this.FanoutOperationState); + } + if (this.StartEpk != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.StartEpk, this.StartEpk); + } + if (this.EndEpk != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EndEpk, this.EndEpk); + } + if (this.ReadFeedKeyType != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ReadFeedKeyType, this.ReadFeedKeyType); + } + if (this.ContentSerializationFormat != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ContentSerializationFormat, this.ContentSerializationFormat); + } + if (this.AllowTentativeWrites != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowTentativeWrites, this.AllowTentativeWrites); + } + if (this.IsUserRequest != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsUserRequest, this.IsUserRequest); + } + if (this.PreserveFullContent != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PreserveFullContent, this.PreserveFullContent); + } + if (this.IncludeTentativeWrites != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IncludeTentativeWrites, this.IncludeTentativeWrites); + } + if (this.PopulateResourceCount != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateResourceCount, this.PopulateResourceCount); + } + if (this.MergeStaticId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MergeStaticId, this.MergeStaticId); + } + if (this.IsBatchAtomic != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsBatchAtomic, this.IsBatchAtomic); + } + if (this.ShouldBatchContinueOnError != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, this.ShouldBatchContinueOnError); + } + if (this.IsBatchOrdered != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsBatchOrdered, this.IsBatchOrdered); + } + if (this.SchemaOwnerRid != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaOwnerRid, this.SchemaOwnerRid); + } + if (this.SchemaHash != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaHash, this.SchemaHash); + } + if (this.IsRUPerGBEnforcementRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, this.IsRUPerGBEnforcementRequest); + } + if (this.MaxPollingIntervalMilliseconds != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, this.MaxPollingIntervalMilliseconds); + } + if (this.PopulateLogStoreInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateLogStoreInfo, this.PopulateLogStoreInfo); + } + if (this.GetAllPartitionKeyStatistics != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, this.GetAllPartitionKeyStatistics); + } + if (this.ForceSideBySideIndexMigration != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, this.ForceSideBySideIndexMigration); + } + if (this.CollectionChildResourceNameLimitInBytes != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, this.CollectionChildResourceNameLimitInBytes); + } + if (this.CollectionChildResourceContentLimitInKB != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, this.CollectionChildResourceContentLimitInKB); + } + if (this.MergeCheckPointGLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.MergeCheckPointGLSN, this.MergeCheckPointGLSN); + } + if (this.Prefer != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.Prefer, this.Prefer); + } + if (this.UniqueIndexNameEncodingMode != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, this.UniqueIndexNameEncodingMode); + } + if (this.PopulateUnflushedMergeEntryCount != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, this.PopulateUnflushedMergeEntryCount); + } + if (this.MigrateOfferToManualThroughput != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, this.MigrateOfferToManualThroughput); + } + if (this.MigrateOfferToAutopilot != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, this.MigrateOfferToAutopilot); + } + if (this.IsClientEncrypted != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsClientEncrypted, this.IsClientEncrypted); + } + if (this.SystemDocumentType != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SystemDocumentType, this.SystemDocumentType); + } + if (this.IsOfferStorageRefreshRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, this.IsOfferStorageRefreshRequest); + } + if (this.ResourceTypes != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceTypes, this.ResourceTypes); + } + if (this.TransactionId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionId, this.TransactionId); + } + if (this.TransactionFirstRequest != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionFirstRequest, this.TransactionFirstRequest); + } + if (this.TransactionCommit != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.TransactionCommit, this.TransactionCommit); + } + if (this.UpdateMaxThroughputEverProvisioned != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, this.UpdateMaxThroughputEverProvisioned); + } + if (this.UniqueIndexReIndexingState != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UniqueIndexReIndexingState, this.UniqueIndexReIndexingState); + } + if (this.UseSystemBudget != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UseSystemBudget, this.UseSystemBudget); + } + if (this.IgnoreSystemLoweringMaxThroughput != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, this.IgnoreSystemLoweringMaxThroughput); + } + if (this.TruncateMergeLogRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TruncateMergeLogRequest, this.TruncateMergeLogRequest); + } + if (this.RetriableWriteRequestId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RetriableWriteRequestId, this.RetriableWriteRequestId); + } + if (this.IsRetriedWriteRequest != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRetriedWriteRequest, this.IsRetriedWriteRequest); + } + if (this.RetriableWriteRequestStartTimestamp != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, this.RetriableWriteRequestStartTimestamp); + } + if (this.AddResourcePropertiesToResponse != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, this.AddResourcePropertiesToResponse); + } + if (this.ChangeFeedStartFullFidelityIfNoneMatch != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, this.ChangeFeedStartFullFidelityIfNoneMatch); + } + if (this.SystemRestoreOperation != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SystemRestoreOperation, this.SystemRestoreOperation); + } + if (this.SkipRefreshDatabaseAccountConfigs != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, this.SkipRefreshDatabaseAccountConfigs); + } + if (this.IntendedCollectionRid != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IntendedCollectionRid, this.IntendedCollectionRid); + } + if (this.UseArchivalPartition != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.UseArchivalPartition, this.UseArchivalPartition); + } + if (this.PopulateUniqueIndexReIndexProgress != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, this.PopulateUniqueIndexReIndexProgress); + } + if (this.SchemaId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SchemaId, this.SchemaId); + } + if (this.CollectionTruncate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionTruncate, this.CollectionTruncate); + } + if (this.SDKSupportedCapabilities != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SDKSupportedCapabilities, this.SDKSupportedCapabilities); + } + if (this.IsMaterializedViewBuild != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMaterializedViewBuild, this.IsMaterializedViewBuild); + } + if (this.BuilderClientIdentifier != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.BuilderClientIdentifier, this.BuilderClientIdentifier); + } + if (this.SourceCollectionIfMatch != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SourceCollectionIfMatch, this.SourceCollectionIfMatch); + } + if (this.RequestedCollectionType != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RequestedCollectionType, this.RequestedCollectionType); + } + if (this.PopulateIndexMetrics != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateIndexMetrics, this.PopulateIndexMetrics); + } + if (this.PopulateAnalyticalMigrationProgress != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, this.PopulateAnalyticalMigrationProgress); + } + if (this.ShouldReturnCurrentServerDateTime != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, this.ShouldReturnCurrentServerDateTime); + } + if (this.RbacUserId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacUserId, this.RbacUserId); + } + if (this.RbacAction != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacAction, this.RbacAction); + } + if (this.RbacResource != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RbacResource, this.RbacResource); + } + if (this.CorrelatedActivityId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CorrelatedActivityId, this.CorrelatedActivityId); + } + if (this.IsThroughputCapRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsThroughputCapRequest, this.IsThroughputCapRequest); + } + if (this.ChangeFeedWireFormatVersion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, this.ChangeFeedWireFormatVersion); + } + if (this.PopulateByokEncryptionProgress != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, this.PopulateByokEncryptionProgress); + } + if (this.UseUserBackgroundBudget != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UseUserBackgroundBudget, this.UseUserBackgroundBudget); + } + if (this.IncludePhysicalPartitionThroughputInfo != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, this.IncludePhysicalPartitionThroughputInfo); + } + if (this.IsServerlessStorageRefreshRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, this.IsServerlessStorageRefreshRequest); + } + if (this.UpdateOfferStateToPending != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateOfferStateToPending, this.UpdateOfferStateToPending); + } + if (this.PopulateOldestActiveSchemaId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, this.PopulateOldestActiveSchemaId); + } + if (this.IsInternalServerlessRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsInternalServerlessRequest, this.IsInternalServerlessRequest); + } + if (this.OfferReplaceRURedistribution != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, this.OfferReplaceRURedistribution); + } + if (this.IsCassandraAlterTypeRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, this.IsCassandraAlterTypeRequest); + } + if (this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, this.IsMaterializedViewSourceSchemaReplaceBatchRequest); + } + if (this.ForceDatabaseAccountUpdate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, this.ForceDatabaseAccountUpdate); + } + if (this.PriorityLevel != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PriorityLevel, this.PriorityLevel); + } + if (this.AllowRestoreParamsUpdate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, this.AllowRestoreParamsUpdate); + } + if (this.PruneCollectionSchemas != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PruneCollectionSchemas, this.PruneCollectionSchemas); + } + if (this.PopulateIndexMetricsV2 != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, this.PopulateIndexMetricsV2); + } + if (this.IsMigratedFixedCollection != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsMigratedFixedCollection, this.IsMigratedFixedCollection); + } + if (this.SupportedSerializationFormats != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportedSerializationFormats, this.SupportedSerializationFormats); + } + if (this.UpdateOfferStateToRestorePending != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, this.UpdateOfferStateToRestorePending); + } + if (this.SetMasterResourcesDeletionPending != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, this.SetMasterResourcesDeletionPending); + } + if (this.HighPriorityForcedBackup != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.HighPriorityForcedBackup, this.HighPriorityForcedBackup); + } + if (this.OptimisticDirectExecute != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.OptimisticDirectExecute, this.OptimisticDirectExecute); + } + if (this.PopulateMinGLSNForDocumentOperations != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, this.PopulateMinGLSNForDocumentOperations); + } + if (this.PopulateHighestTentativeWriteLLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, this.PopulateHighestTentativeWriteLLSN); + } + if (this.PopulateCapacityType != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCapacityType, this.PopulateCapacityType); + } + if (this.TraceParent != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceParent, this.TraceParent); + } + if (this.TraceState != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceState, this.TraceState); + } + if (this.EnableConflictResolutionPolicyUpdate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, this.EnableConflictResolutionPolicyUpdate); + } + if (this.ClientIpAddress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ClientIpAddress, this.ClientIpAddress); + } + if (this.IsRequestNotAuthorized != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRequestNotAuthorized, this.IsRequestNotAuthorized); + } + if (this.AllowDocumentReadsInOfflineRegion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, this.AllowDocumentReadsInOfflineRegion); + } + if (this.PopulateCurrentPartitionThroughputInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, this.PopulateCurrentPartitionThroughputInfo); + } + if (this.SkipThroughputCapValidation != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SkipThroughputCapValidation, this.SkipThroughputCapValidation); + } + if (this.PopulateDocumentRecordCount != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateDocumentRecordCount, this.PopulateDocumentRecordCount); + } + if (this.CosmosGatewayTransactionId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CosmosGatewayTransactionId, this.CosmosGatewayTransactionId); + } + if (this.PopulateUserStrings != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateUserStrings, this.PopulateUserStrings); + } + if (this.IfMatch != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IfMatch, this.IfMatch); + } + if (this.NoRetryOn449StatusCode != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, this.NoRetryOn449StatusCode); + } + if (this.SkipAdjustThroughputFractionsForOfferReplace != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, this.SkipAdjustThroughputFractionsForOfferReplace); + } + if (this.SqlQueryForPartitionKeyExtraction != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, this.SqlQueryForPartitionKeyExtraction); + } + if (this.EnableCrossPartitionQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, this.EnableCrossPartitionQuery); + } + if (this.IsContinuationExpected != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsContinuationExpected, this.IsContinuationExpected); + } + if (this.ParallelizeCrossPartitionQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, this.ParallelizeCrossPartitionQuery); + } + if (this.SupportedQueryFeatures != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportedQueryFeatures, this.SupportedQueryFeatures); + } + if (this.QueryVersion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.QueryVersion, this.QueryVersion); + } + if (this.ActivityId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); + } + if (this.notCommonHeaders != null) + { + foreach (KeyValuePair keyValuePair in this.notCommonHeaders) + { + this.nameValueCollection.Add(keyValuePair.Key, keyValuePair.Value); + } + } + } + } + } + + return this.nameValueCollection; + } + + public void Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + this.UpdateHelper( + key: key, + value: null, + throwIfAlreadyExists: false, + ignoreNotCommonHeaders: false); + } + + public string Get(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + switch (key.Length) + { + case 4: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.HttpDate, key)) + { + return this.HttpDate; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.A_IM, key)) + { + return this.A_IM; + } + if (string.Equals(HttpConstants.HttpHeaders.HttpDate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.HttpDate; + } + + if (string.Equals(HttpConstants.HttpHeaders.A_IM, key, StringComparison.OrdinalIgnoreCase)) + { + return this.A_IM; + } + + break; + case 6: + if (string.Equals(HttpConstants.HttpHeaders.Prefer, key, StringComparison.OrdinalIgnoreCase)) + { + return this.Prefer; + } + + break; + case 8: + if (string.Equals(HttpConstants.HttpHeaders.IfMatch, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IfMatch; + } + + break; + case 9: + if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.XDate; + } + + break; + case 10: + if (string.Equals(HttpConstants.HttpHeaders.TraceState, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TraceState; + } + + break; + case 11: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) + { + return this.EndId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) + { + return this.TraceParent; + } + if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EndId; + } + + if (string.Equals(HttpConstants.HttpHeaders.TraceParent, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TraceParent; + } + + break; + case 12: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Version, key)) + { + return this.Version; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndEpk, key)) + { + return this.EndEpk; + } + if (string.Equals(HttpConstants.HttpHeaders.Version, key, StringComparison.OrdinalIgnoreCase)) + { + return this.Version; + } + + if (string.Equals(HttpConstants.HttpHeaders.EndEpk, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EndEpk; + } + + break; + case 13: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Authorization, key)) + { + return this.Authorization; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfNoneMatch, key)) + { + return this.IfNoneMatch; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartId, key)) + { + return this.StartId; + } + if (string.Equals(HttpConstants.HttpHeaders.Authorization, key, StringComparison.OrdinalIgnoreCase)) + { + return this.Authorization; + } + + if (string.Equals(HttpConstants.HttpHeaders.IfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IfNoneMatch; + } + + if (string.Equals(HttpConstants.HttpHeaders.StartId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.StartId; + } + + break; + case 14: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanCharge, key)) + { + return this.CanCharge; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryId, key)) + { + return this.BinaryId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartEpk, key)) + { + return this.StartEpk; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaId, key)) + { + return this.SchemaId; + } + if (string.Equals(HttpConstants.HttpHeaders.CanCharge, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CanCharge; + } + + if (string.Equals(WFConstants.BackendHeaders.BinaryId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.BinaryId; + } + + if (string.Equals(HttpConstants.HttpHeaders.StartEpk, key, StringComparison.OrdinalIgnoreCase)) + { + return this.StartEpk; + } + + if (string.Equals(WFConstants.BackendHeaders.SchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SchemaId; + } + + break; + case 15: + if (string.Equals(HttpConstants.HttpHeaders.TargetLsn, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TargetLsn; + } + + break; + case 16: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanThrottle, key)) + { + return this.CanThrottle; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaHash, key)) + { + return this.SchemaHash; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacAction, key)) + { + return this.RbacAction; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key)) + { + return this.NoRetryOn449StatusCode; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + return this.ActivityId; + } + if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CanThrottle; + } + + if (string.Equals(WFConstants.BackendHeaders.SchemaHash, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SchemaHash; + } + + if (string.Equals(HttpConstants.HttpHeaders.RbacAction, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RbacAction; + } + + if (string.Equals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key, StringComparison.OrdinalIgnoreCase)) + { + return this.NoRetryOn449StatusCode; + } + + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ActivityId; + } + + break; + case 17: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) + { + return this.Continuation; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.EntityId, key)) + { + return this.EntityId; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BindReplicaDirective, key)) + { + return this.BindReplicaDirective; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfModifiedSince, key)) + { + return this.IfModifiedSince; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionId, key)) + { + return this.TransactionId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacUserId, key)) + { + return this.RbacUserId; + } + if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) + { + return this.Continuation; + } + + if (string.Equals(WFConstants.BackendHeaders.EntityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EntityId; + } + + if (string.Equals(WFConstants.BackendHeaders.BindReplicaDirective, key, StringComparison.OrdinalIgnoreCase)) + { + return this.BindReplicaDirective; + } + + if (string.Equals(HttpConstants.HttpHeaders.IfModifiedSince, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IfModifiedSince; + } + + if (string.Equals(WFConstants.BackendHeaders.TransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TransactionId; + } + + if (string.Equals(HttpConstants.HttpHeaders.RbacUserId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RbacUserId; + } + + break; + case 18: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) + { + return this.SessionToken; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key)) + { + return this.IsAutoScaleRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ReadFeedKeyType, key)) + { + return this.ReadFeedKeyType; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacResource, key)) + { + return this.RbacResource; + } + if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SessionToken; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsAutoScaleRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.ReadFeedKeyType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ReadFeedKeyType; + } + + if (string.Equals(HttpConstants.HttpHeaders.RbacResource, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RbacResource; + } + + break; + case 19: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) + { + return this.ResourceId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PageSize, key)) + { + return this.PageSize; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreParams, key)) + { + return this.RestoreParams; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionFirstRequest, key)) + { + return this.TransactionFirstRequest; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResourceId; + } + + if (string.Equals(HttpConstants.HttpHeaders.PageSize, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PageSize; + } + + if (string.Equals(WFConstants.BackendHeaders.RestoreParams, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RestoreParams; + } + + if (string.Equals(WFConstants.BackendHeaders.TransactionFirstRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TransactionFirstRequest; + } + + break; + case 20: + if (string.Equals(HttpConstants.HttpHeaders.ProfileRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ProfileRequest; + } + + break; + case 21: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) + { + return this.ShareThroughput; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaOwnerRid, key)) + { + return this.SchemaOwnerRid; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionCommit, key)) + { + return this.TransactionCommit; + } + if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ShareThroughput; + } + + if (string.Equals(WFConstants.BackendHeaders.SchemaOwnerRid, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SchemaOwnerRid; + } + + if (string.Equals(WFConstants.BackendHeaders.TransactionCommit, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TransactionCommit; + } + + break; + case 22: + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsFanoutRequest, key)) + { + return this.IsFanoutRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConsistencyLevel, key)) + { + return this.ConsistencyLevel; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.GatewaySignature, key)) + { + return this.GatewaySignature; + } + if (string.Equals(WFConstants.BackendHeaders.IsFanoutRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsFanoutRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.ConsistencyLevel, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ConsistencyLevel; + } + + if (string.Equals(HttpConstants.HttpHeaders.GatewaySignature, key, StringComparison.OrdinalIgnoreCase)) + { + return this.GatewaySignature; + } + + break; + case 23: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IndexingDirective, key)) + { + return this.IndexingDirective; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryMasterKey, key)) + { + return this.PrimaryMasterKey; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsReadOnlyScript, key)) + { + return this.IsReadOnlyScript; + } + if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IndexingDirective; + } + + if (string.Equals(WFConstants.BackendHeaders.PrimaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PrimaryMasterKey; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsReadOnlyScript, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsReadOnlyScript; + } + + break; + case 24: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) + { + return this.CollectionServiceIndex; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RemoteStorageType, key)) + { + return this.RemoteStorageType; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchAtomic, key)) + { + return this.IsBatchAtomic; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionServiceIndex; + } + + if (string.Equals(WFConstants.BackendHeaders.RemoteStorageType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RemoteStorageType; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsBatchAtomic, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsBatchAtomic; + } + + break; + case 25: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceSchemaName, key)) + { + return this.ResourceSchemaName; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryMasterKey, key)) + { + return this.SecondaryMasterKey; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key)) + { + return this.PrimaryReadonlyKey; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) + { + return this.TransportRequestID; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchOrdered, key)) + { + return this.IsBatchOrdered; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceTypes, key)) + { + return this.ResourceTypes; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) + { + return this.QueryVersion; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResourceSchemaName; + } + + if (string.Equals(WFConstants.BackendHeaders.SecondaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SecondaryMasterKey; + } + + if (string.Equals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PrimaryReadonlyKey; + } + + if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TransportRequestID; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsBatchOrdered, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsBatchOrdered; + } + + if (string.Equals(WFConstants.BackendHeaders.ResourceTypes, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResourceTypes; + } + + if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QueryVersion; + } + + break; + case 26: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) + { + return this.CollectionPartitionIndex; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnumerationDirection, key)) + { + return this.EnumerationDirection; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RequestedCollectionType, key)) + { + return this.RequestedCollectionType; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PriorityLevel, key)) + { + return this.PriorityLevel; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionPartitionIndex; + } + + if (string.Equals(HttpConstants.HttpHeaders.EnumerationDirection, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnumerationDirection; + } + + if (string.Equals(WFConstants.BackendHeaders.RequestedCollectionType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RequestedCollectionType; + } + + if (string.Equals(HttpConstants.HttpHeaders.PriorityLevel, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PriorityLevel; + } + + break; + case 27: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key)) + { + return this.SecondaryReadonlyKey; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.FanoutOperationState, key)) + { + return this.FanoutOperationState; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MergeStaticId, key)) + { + return this.MergeStaticId; + } + if (string.Equals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SecondaryReadonlyKey; + } + + if (string.Equals(WFConstants.BackendHeaders.FanoutOperationState, key, StringComparison.OrdinalIgnoreCase)) + { + return this.FanoutOperationState; + } + + if (string.Equals(HttpConstants.HttpHeaders.MergeStaticId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MergeStaticId; + } + + break; + case 28: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKey, key)) + { + return this.PartitionKey; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key)) + { + return this.RestoreMetadataFilter; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key)) + { + return this.TimeToLiveInSeconds; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.EffectivePartitionKey, key)) + { + return this.EffectivePartitionKey; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UseSystemBudget, key)) + { + return this.UseSystemBudget; + } + if (string.Equals(HttpConstants.HttpHeaders.PartitionKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionKey; + } + + if (string.Equals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RestoreMetadataFilter; + } + + if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TimeToLiveInSeconds; + } + + if (string.Equals(WFConstants.BackendHeaders.EffectivePartitionKey, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EffectivePartitionKey; + } + + if (string.Equals(WFConstants.BackendHeaders.UseSystemBudget, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UseSystemBudget; + } + + break; + case 29: + if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ClientIpAddress; + } + + break; + case 30: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) + { + return this.ResourceTokenExpiry; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionCount, key)) + { + return this.PartitionCount; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionRid, key)) + { + return this.CollectionRid; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionResourceFilter, key)) + { + return this.PartitionResourceFilter; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ExcludeSystemProperties, key)) + { + return this.ExcludeSystemProperties; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key)) + { + return this.IsCassandraAlterTypeRequest; + } + if (string.Equals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResourceTokenExpiry; + } + + if (string.Equals(HttpConstants.HttpHeaders.PartitionCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionCount; + } + + if (string.Equals(WFConstants.BackendHeaders.CollectionRid, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionRid; + } + + if (string.Equals(WFConstants.BackendHeaders.PartitionResourceFilter, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionResourceFilter; + } + + if (string.Equals(WFConstants.BackendHeaders.ExcludeSystemProperties, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ExcludeSystemProperties; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsCassandraAlterTypeRequest; + } + + break; + case 31: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key)) + { + return this.ClientRetryAttemptCount; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key)) + { + return this.CanOfferReplaceComplete; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key)) + { + return this.BinaryPassthroughRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsClientEncrypted, key)) + { + return this.IsClientEncrypted; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemDocumentType, key)) + { + return this.SystemDocumentType; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionTruncate, key)) + { + return this.CollectionTruncate; + } + if (string.Equals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ClientRetryAttemptCount; + } + + if (string.Equals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CanOfferReplaceComplete; + } + + if (string.Equals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.BinaryPassthroughRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsClientEncrypted, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsClientEncrypted; + } + + if (string.Equals(HttpConstants.HttpHeaders.SystemDocumentType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SystemDocumentType; + } + + if (string.Equals(HttpConstants.HttpHeaders.CollectionTruncate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionTruncate; + } + + break; + case 32: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key)) + { + return this.MigrateCollectionDirective; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key)) + { + return this.TargetGlobalCommittedLsn; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceQueryScan, key)) + { + return this.ForceQueryScan; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key)) + { + return this.MaxPollingIntervalMilliseconds; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key)) + { + return this.PopulateIndexMetrics; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MigrateCollectionDirective; + } + + if (string.Equals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TargetGlobalCommittedLsn; + } + + if (string.Equals(HttpConstants.HttpHeaders.ForceQueryScan, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ForceQueryScan; + } + + if (string.Equals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MaxPollingIntervalMilliseconds; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateIndexMetrics; + } + + break; + case 33: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableScanInQuery, key)) + { + return this.EnableScanInQuery; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key)) + { + return this.EmitVerboseTracesInQuery; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key)) + { + return this.PopulateQuotaInfo; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreserveFullContent, key)) + { + return this.PreserveFullContent; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key)) + { + return this.PopulateLogStoreInfo; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CorrelatedActivityId, key)) + { + return this.CorrelatedActivityId; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableScanInQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableScanInQuery; + } + + if (string.Equals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EmitVerboseTracesInQuery; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateQuotaInfo; + } + + if (string.Equals(HttpConstants.HttpHeaders.PreserveFullContent, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PreserveFullContent; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateLogStoreInfo; + } + + if (string.Equals(HttpConstants.HttpHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CorrelatedActivityId; + } + + break; + case 34: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowTentativeWrites, key)) + { + return this.AllowTentativeWrites; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UseArchivalPartition, key)) + { + return this.UseArchivalPartition; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCapacityType, key)) + { + return this.PopulateCapacityType; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key)) + { + return this.CosmosGatewayTransactionId; + } + if (string.Equals(HttpConstants.HttpHeaders.AllowTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AllowTentativeWrites; + } + + if (string.Equals(HttpConstants.HttpHeaders.UseArchivalPartition, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UseArchivalPartition; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateCapacityType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateCapacityType; + } + + if (string.Equals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CosmosGatewayTransactionId; + } + + break; + case 35: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerInclude, key)) + { + return this.PreTriggerInclude; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerExclude, key)) + { + return this.PreTriggerExclude; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key)) + { + return this.PartitionKeyRangeId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key)) + { + return this.FilterBySchemaResourceId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key)) + { + return this.CollectionRemoteStorageSecurityIdentifier; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key)) + { + return this.RemainingTimeInMsOnClientRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key)) + { + return this.ShouldBatchContinueOnError; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IntendedCollectionRid, key)) + { + return this.IntendedCollectionRid; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key)) + { + return this.PopulateIndexMetricsV2; + } + if (string.Equals(HttpConstants.HttpHeaders.PreTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PreTriggerInclude; + } + + if (string.Equals(HttpConstants.HttpHeaders.PreTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PreTriggerExclude; + } + + if (string.Equals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionKeyRangeId; + } + + if (string.Equals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.FilterBySchemaResourceId; + } + + if (string.Equals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionRemoteStorageSecurityIdentifier; + } + + if (string.Equals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RemainingTimeInMsOnClientRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ShouldBatchContinueOnError; + } + + if (string.Equals(WFConstants.BackendHeaders.IntendedCollectionRid, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IntendedCollectionRid; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateIndexMetricsV2; + } + + break; + case 36: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerInclude, key)) + { + return this.PostTriggerInclude; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerExclude, key)) + { + return this.PostTriggerExclude; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key)) + { + return this.PopulateQueryMetrics; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsUserRequest, key)) + { + return this.IsUserRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key)) + { + return this.IncludeTentativeWrites; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key)) + { + return this.IsRetriedWriteRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key)) + { + return this.PruneCollectionSchemas; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) + { + return this.SupportedQueryFeatures; + } + if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PostTriggerInclude; + } + + if (string.Equals(HttpConstants.HttpHeaders.PostTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PostTriggerExclude; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateQueryMetrics; + } + + if (string.Equals(WFConstants.BackendHeaders.IsUserRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsUserRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IncludeTentativeWrites; + } + + if (string.Equals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsRetriedWriteRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PruneCollectionSchemas; + } + + if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SupportedQueryFeatures; + } + + break; + case 37: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) + { + return this.EnableLogging; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateResourceCount, key)) + { + return this.PopulateResourceCount; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key)) + { + return this.SDKSupportedCapabilities; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key)) + { + return this.BuilderClientIdentifier; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) + { + return this.IsRequestNotAuthorized; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableLogging; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateResourceCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateResourceCount; + } + + if (string.Equals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SDKSupportedCapabilities; + } + + if (string.Equals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + return this.BuilderClientIdentifier; + } + + if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsRequestNotAuthorized; + } + + break; + case 38: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) + { + return this.MigrateOfferToAutopilot; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestId, key)) + { + return this.RetriableWriteRequestId; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key)) + { + return this.SourceCollectionIfMatch; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key)) + { + return this.UseUserBackgroundBudget; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MigrateOfferToAutopilot; + } + + if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RetriableWriteRequestId; + } + + if (string.Equals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SourceCollectionIfMatch; + } + + if (string.Equals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UseUserBackgroundBudget; + } + + break; + case 39: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key)) + { + return this.TruncateMergeLogRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key)) + { + return this.IsInternalServerlessRequest; + } + if (string.Equals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TruncateMergeLogRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsInternalServerlessRequest; + } + + break; + case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key)) + { + return this.EnableDynamicRidRangeAllocation; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key)) + { + return this.UniqueIndexReIndexingState; + } + if (string.Equals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableDynamicRidRangeAllocation; + } + + if (string.Equals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UniqueIndexReIndexingState; + } + + break; + case 41: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key)) + { + return this.ForceDatabaseAccountUpdate; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key)) + { + return this.OptimisticDirectExecute; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipThroughputCapValidation, key)) + { + return this.SkipThroughputCapValidation; + } + if (string.Equals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ForceDatabaseAccountUpdate; + } + + if (string.Equals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OptimisticDirectExecute; + } + + if (string.Equals(WFConstants.BackendHeaders.SkipThroughputCapValidation, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SkipThroughputCapValidation; + } + + break; + case 42: + if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key)) + { + return this.MergeCheckPointGLSN; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key)) + { + return this.ShouldReturnCurrentServerDateTime; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key)) + { + return this.ChangeFeedWireFormatVersion; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateUserStrings, key)) + { + return this.PopulateUserStrings; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) + { + return this.EnableCrossPartitionQuery; + } + if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MergeCheckPointGLSN; + } + + if (string.Equals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ShouldReturnCurrentServerDateTime; + } + + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ChangeFeedWireFormatVersion; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateUserStrings, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateUserStrings; + } + + if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableCrossPartitionQuery; + } + + break; + case 43: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) + { + return this.DisableRUPerMinuteUsage; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key)) + { + return this.PopulatePartitionStatistics; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key)) + { + return this.ForceSideBySideIndexMigration; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key)) + { + return this.UniqueIndexNameEncodingMode; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key)) + { + return this.SupportedSerializationFormats; + } + if (string.Equals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key, StringComparison.OrdinalIgnoreCase)) + { + return this.DisableRUPerMinuteUsage; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulatePartitionStatistics; + } + + if (string.Equals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ForceSideBySideIndexMigration; + } + + if (string.Equals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UniqueIndexNameEncodingMode; + } + + if (string.Equals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SupportedSerializationFormats; + } + + break; + case 44: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ContentSerializationFormat, key)) + { + return this.ContentSerializationFormat; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key)) + { + return this.PopulateOldestActiveSchemaId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) + { + return this.IsContinuationExpected; + } + if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ContentSerializationFormat; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateOldestActiveSchemaId; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsContinuationExpected; + } + + break; + case 45: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) + { + return this.ChangeFeedStartFullFidelityIfNoneMatch; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemRestoreOperation, key)) + { + return this.SystemRestoreOperation; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key)) + { + return this.IsThroughputCapRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key)) + { + return this.PopulateByokEncryptionProgress; + } + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ChangeFeedStartFullFidelityIfNoneMatch; + } + + if (string.Equals(HttpConstants.HttpHeaders.SystemRestoreOperation, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SystemRestoreOperation; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsThroughputCapRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateByokEncryptionProgress; + } + + break; + case 46: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key)) + { + return this.MigrateOfferToManualThroughput; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key)) + { + return this.SkipRefreshDatabaseAccountConfigs; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key)) + { + return this.IsMigratedFixedCollection; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MigrateOfferToManualThroughput; + } + + if (string.Equals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SkipRefreshDatabaseAccountConfigs; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsMigratedFixedCollection; + } + + break; + case 47: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key)) + { + return this.SupportSpatialLegacyCoordinates; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key)) + { + return this.CollectionChildResourceNameLimitInBytes; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key)) + { + return this.AddResourcePropertiesToResponse; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key)) + { + return this.IsMaterializedViewBuild; + } + if (string.Equals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SupportSpatialLegacyCoordinates; + } + + if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionChildResourceNameLimitInBytes; + } + + if (string.Equals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AddResourcePropertiesToResponse; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsMaterializedViewBuild; + } + + break; + case 48: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key)) + { + return this.PopulateCollectionThroughputInfo; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key)) + { + return this.GetAllPartitionKeyStatistics; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key)) + { + return this.PopulateUniqueIndexReIndexProgress; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key)) + { + return this.AllowRestoreParamsUpdate; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key)) + { + return this.HighPriorityForcedBackup; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateCollectionThroughputInfo; + } + + if (string.Equals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key, StringComparison.OrdinalIgnoreCase)) + { + return this.GetAllPartitionKeyStatistics; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateUniqueIndexReIndexProgress; + } + + if (string.Equals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AllowRestoreParamsUpdate; + } + + if (string.Equals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key, StringComparison.OrdinalIgnoreCase)) + { + return this.HighPriorityForcedBackup; + } + + break; + case 49: + if (string.Equals(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UsePolygonsSmallerThanAHemisphere; + } + + break; + case 50: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key)) + { + return this.ResponseContinuationTokenLimitInKB; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key)) + { + return this.PopulateAnalyticalMigrationProgress; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key)) + { + return this.UpdateOfferStateToPending; + } + if (string.Equals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResponseContinuationTokenLimitInKB; + } + + if (string.Equals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateAnalyticalMigrationProgress; + } + + if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UpdateOfferStateToPending; + } + + break; + case 51: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key)) + { + return this.EnableLowPrecisionOrderBy; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key)) + { + return this.RetriableWriteRequestStartTimestamp; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateDocumentRecordCount, key)) + { + return this.PopulateDocumentRecordCount; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableLowPrecisionOrderBy; + } + + if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RetriableWriteRequestStartTimestamp; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateDocumentRecordCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateDocumentRecordCount; + } + + break; + case 52: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) + { + return this.OfferReplaceRURedistribution; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) + { + return this.ParallelizeCrossPartitionQuery; + } + if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OfferReplaceRURedistribution; + } + + if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ParallelizeCrossPartitionQuery; + } + + break; + case 53: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) + { + return this.IsRUPerGBEnforcementRequest; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key)) + { + return this.IsOfferStorageRefreshRequest; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key)) + { + return this.PopulateMinGLSNForDocumentOperations; + } + if (string.Equals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsRUPerGBEnforcementRequest; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsOfferStorageRefreshRequest; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateMinGLSNForDocumentOperations; + } + + break; + case 54: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key)) + { + return this.IncludePhysicalPartitionThroughputInfo; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key)) + { + return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) + { + return this.PopulateCurrentPartitionThroughputInfo; + } + if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IncludePhysicalPartitionThroughputInfo; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateCurrentPartitionThroughputInfo; + } + + break; + case 55: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) + { + return this.UpdateOfferStateToRestorePending; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) + { + return this.SqlQueryForPartitionKeyExtraction; + } + if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UpdateOfferStateToRestorePending; + } + + if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SqlQueryForPartitionKeyExtraction; + } + + break; + case 56: + if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionChildResourceContentLimitInKB; + } + + break; + case 57: + if (string.Equals(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateUnflushedMergeEntryCount; + } + + break; + case 58: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key)) + { + return this.IgnoreSystemLoweringMaxThroughput; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key)) + { + return this.SetMasterResourcesDeletionPending; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key)) + { + return this.PopulateHighestTentativeWriteLLSN; + } + if (string.Equals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IgnoreSystemLoweringMaxThroughput; + } + + if (string.Equals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SetMasterResourcesDeletionPending; + } + + if (string.Equals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateHighestTentativeWriteLLSN; + } + + break; + case 59: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) + { + return this.UpdateMaxThroughputEverProvisioned; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) + { + return this.EnableConflictResolutionPolicyUpdate; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) + { + return this.AllowDocumentReadsInOfflineRegion; + } + if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UpdateMaxThroughputEverProvisioned; + } + + if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableConflictResolutionPolicyUpdate; + } + + if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AllowDocumentReadsInOfflineRegion; + } + + break; + case 61: + if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsServerlessStorageRefreshRequest; + } + + break; + case 62: + if (string.Equals(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SkipAdjustThroughputFractionsForOfferReplace; + } + + break; + default: + break; + } + + if (this.notCommonHeaders != null + && this.notCommonHeaders.TryGetValue(key, out string value)) + { + return value; + } + + return null; + } + + public void Add(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + this.UpdateHelper( + key: key, + value: value, + throwIfAlreadyExists: true, + ignoreNotCommonHeaders: false); + } + + public void Set(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + this.UpdateHelper( + key: key, + value: value, + throwIfAlreadyExists: false, + ignoreNotCommonHeaders: false); + } + + public void UpdateHelper( + string key, + string value, + bool throwIfAlreadyExists, + bool ignoreNotCommonHeaders) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + switch (key.Length) + { + case 4: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.HttpDate, key)) + { + if (throwIfAlreadyExists && this.HttpDate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HttpDate = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.A_IM, key)) + { + if (throwIfAlreadyExists && this.A_IM != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.A_IM = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.HttpDate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.HttpDate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HttpDate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.A_IM, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.A_IM != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.A_IM = value; + return; + } + break; + case 6: + if (string.Equals(HttpConstants.HttpHeaders.Prefer, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.Prefer != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Prefer = value; + return; + } + break; + case 8: + if (string.Equals(HttpConstants.HttpHeaders.IfMatch, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IfMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IfMatch = value; + return; + } + break; + case 9: + if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.XDate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.XDate = value; + return; + } + break; + case 10: + if (string.Equals(HttpConstants.HttpHeaders.TraceState, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TraceState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TraceState = value; + return; + } + break; + case 11: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) + { + if (throwIfAlreadyExists && this.EndId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EndId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) + { + if (throwIfAlreadyExists && this.TraceParent != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TraceParent = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EndId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EndId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TraceParent, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TraceParent != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TraceParent = value; + return; + } + break; + case 12: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Version, key)) + { + if (throwIfAlreadyExists && this.Version != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Version = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndEpk, key)) + { + if (throwIfAlreadyExists && this.EndEpk != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EndEpk = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.Version, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.Version != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Version = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EndEpk, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EndEpk != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EndEpk = value; + return; + } + break; + case 13: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Authorization, key)) + { + if (throwIfAlreadyExists && this.Authorization != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Authorization = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfNoneMatch, key)) + { + if (throwIfAlreadyExists && this.IfNoneMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IfNoneMatch = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartId, key)) + { + if (throwIfAlreadyExists && this.StartId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.StartId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.Authorization, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.Authorization != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Authorization = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IfNoneMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IfNoneMatch = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.StartId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.StartId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.StartId = value; + return; + } + break; + case 14: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanCharge, key)) + { + if (throwIfAlreadyExists && this.CanCharge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanCharge = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryId, key)) + { + if (throwIfAlreadyExists && this.BinaryId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BinaryId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.StartEpk, key)) + { + if (throwIfAlreadyExists && this.StartEpk != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.StartEpk = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaId, key)) + { + if (throwIfAlreadyExists && this.SchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CanCharge, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CanCharge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanCharge = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.BinaryId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.BinaryId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BinaryId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.StartEpk, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.StartEpk != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.StartEpk = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaId = value; + return; + } + break; + case 15: + if (string.Equals(HttpConstants.HttpHeaders.TargetLsn, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TargetLsn != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TargetLsn = value; + return; + } + break; + case 16: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanThrottle, key)) + { + if (throwIfAlreadyExists && this.CanThrottle != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanThrottle = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaHash, key)) + { + if (throwIfAlreadyExists && this.SchemaHash != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaHash = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacAction, key)) + { + if (throwIfAlreadyExists && this.RbacAction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacAction = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key)) + { + if (throwIfAlreadyExists && this.NoRetryOn449StatusCode != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.NoRetryOn449StatusCode = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CanThrottle != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanThrottle = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SchemaHash, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SchemaHash != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaHash = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RbacAction, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RbacAction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacAction = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.NoRetryOn449StatusCode, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.NoRetryOn449StatusCode != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.NoRetryOn449StatusCode = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } + break; + case 17: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) + { + if (throwIfAlreadyExists && this.Continuation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Continuation = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.EntityId, key)) + { + if (throwIfAlreadyExists && this.EntityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EntityId = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BindReplicaDirective, key)) + { + if (throwIfAlreadyExists && this.BindReplicaDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BindReplicaDirective = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IfModifiedSince, key)) + { + if (throwIfAlreadyExists && this.IfModifiedSince != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IfModifiedSince = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionId, key)) + { + if (throwIfAlreadyExists && this.TransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacUserId, key)) + { + if (throwIfAlreadyExists && this.RbacUserId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacUserId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.Continuation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Continuation = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.EntityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EntityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EntityId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.BindReplicaDirective, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.BindReplicaDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BindReplicaDirective = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IfModifiedSince, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IfModifiedSince != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IfModifiedSince = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.TransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RbacUserId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RbacUserId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacUserId = value; + return; + } + break; + case 18: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) + { + if (throwIfAlreadyExists && this.SessionToken != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SessionToken = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key)) + { + if (throwIfAlreadyExists && this.IsAutoScaleRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsAutoScaleRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ReadFeedKeyType, key)) + { + if (throwIfAlreadyExists && this.ReadFeedKeyType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReadFeedKeyType = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RbacResource, key)) + { + if (throwIfAlreadyExists && this.RbacResource != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacResource = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SessionToken != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SessionToken = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsAutoScaleRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsAutoScaleRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsAutoScaleRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ReadFeedKeyType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ReadFeedKeyType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReadFeedKeyType = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RbacResource, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RbacResource != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RbacResource = value; + return; + } + break; + case 19: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) + { + if (throwIfAlreadyExists && this.ResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PageSize, key)) + { + if (throwIfAlreadyExists && this.PageSize != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PageSize = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreParams, key)) + { + if (throwIfAlreadyExists && this.RestoreParams != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreParams = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionFirstRequest, key)) + { + if (throwIfAlreadyExists && this.TransactionFirstRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionFirstRequest = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PageSize, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PageSize != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PageSize = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RestoreParams, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RestoreParams != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreParams = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.TransactionFirstRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TransactionFirstRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionFirstRequest = value; + return; + } + break; + case 20: + if (string.Equals(HttpConstants.HttpHeaders.ProfileRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ProfileRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ProfileRequest = value; + return; + } + break; + case 21: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) + { + if (throwIfAlreadyExists && this.ShareThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShareThroughput = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SchemaOwnerRid, key)) + { + if (throwIfAlreadyExists && this.SchemaOwnerRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaOwnerRid = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TransactionCommit, key)) + { + if (throwIfAlreadyExists && this.TransactionCommit != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionCommit = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ShareThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShareThroughput = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SchemaOwnerRid, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SchemaOwnerRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaOwnerRid = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.TransactionCommit, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TransactionCommit != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransactionCommit = value; + return; + } + break; + case 22: + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsFanoutRequest, key)) + { + if (throwIfAlreadyExists && this.IsFanoutRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsFanoutRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConsistencyLevel, key)) + { + if (throwIfAlreadyExists && this.ConsistencyLevel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ConsistencyLevel = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.GatewaySignature, key)) + { + if (throwIfAlreadyExists && this.GatewaySignature != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GatewaySignature = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IsFanoutRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsFanoutRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsFanoutRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ConsistencyLevel, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ConsistencyLevel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ConsistencyLevel = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.GatewaySignature, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.GatewaySignature != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GatewaySignature = value; + return; + } + break; + case 23: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IndexingDirective, key)) + { + if (throwIfAlreadyExists && this.IndexingDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IndexingDirective = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryMasterKey, key)) + { + if (throwIfAlreadyExists && this.PrimaryMasterKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PrimaryMasterKey = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsReadOnlyScript, key)) + { + if (throwIfAlreadyExists && this.IsReadOnlyScript != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsReadOnlyScript = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IndexingDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IndexingDirective = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PrimaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PrimaryMasterKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PrimaryMasterKey = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsReadOnlyScript, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsReadOnlyScript != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsReadOnlyScript = value; + return; + } + break; + case 24: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) + { + if (throwIfAlreadyExists && this.CollectionServiceIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionServiceIndex = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RemoteStorageType, key)) + { + if (throwIfAlreadyExists && this.RemoteStorageType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RemoteStorageType = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchAtomic, key)) + { + if (throwIfAlreadyExists && this.IsBatchAtomic != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsBatchAtomic = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionServiceIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionServiceIndex = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RemoteStorageType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RemoteStorageType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RemoteStorageType = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsBatchAtomic, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsBatchAtomic != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsBatchAtomic = value; + return; + } + break; + case 25: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceSchemaName, key)) + { + if (throwIfAlreadyExists && this.ResourceSchemaName != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceSchemaName = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryMasterKey, key)) + { + if (throwIfAlreadyExists && this.SecondaryMasterKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SecondaryMasterKey = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key)) + { + if (throwIfAlreadyExists && this.PrimaryReadonlyKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PrimaryReadonlyKey = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) + { + if (throwIfAlreadyExists && this.TransportRequestID != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransportRequestID = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsBatchOrdered, key)) + { + if (throwIfAlreadyExists && this.IsBatchOrdered != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsBatchOrdered = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceTypes, key)) + { + if (throwIfAlreadyExists && this.ResourceTypes != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceTypes = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) + { + if (throwIfAlreadyExists && this.QueryVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryVersion = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResourceSchemaName != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceSchemaName = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SecondaryMasterKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SecondaryMasterKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SecondaryMasterKey = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PrimaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PrimaryReadonlyKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PrimaryReadonlyKey = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TransportRequestID != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransportRequestID = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsBatchOrdered, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsBatchOrdered != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsBatchOrdered = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceTypes, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResourceTypes != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceTypes = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QueryVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryVersion = value; + return; + } + break; + case 26: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) + { + if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionPartitionIndex = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnumerationDirection, key)) + { + if (throwIfAlreadyExists && this.EnumerationDirection != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnumerationDirection = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RequestedCollectionType, key)) + { + if (throwIfAlreadyExists && this.RequestedCollectionType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequestedCollectionType = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PriorityLevel, key)) + { + if (throwIfAlreadyExists && this.PriorityLevel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PriorityLevel = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionPartitionIndex = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnumerationDirection, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnumerationDirection != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnumerationDirection = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RequestedCollectionType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RequestedCollectionType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequestedCollectionType = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PriorityLevel, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PriorityLevel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PriorityLevel = value; + return; + } + break; + case 27: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key)) + { + if (throwIfAlreadyExists && this.SecondaryReadonlyKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SecondaryReadonlyKey = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.FanoutOperationState, key)) + { + if (throwIfAlreadyExists && this.FanoutOperationState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.FanoutOperationState = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MergeStaticId, key)) + { + if (throwIfAlreadyExists && this.MergeStaticId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeStaticId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SecondaryReadonlyKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SecondaryReadonlyKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SecondaryReadonlyKey = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.FanoutOperationState, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.FanoutOperationState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.FanoutOperationState = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MergeStaticId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MergeStaticId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeStaticId = value; + return; + } + break; + case 28: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKey, key)) + { + if (throwIfAlreadyExists && this.PartitionKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKey = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key)) + { + if (throwIfAlreadyExists && this.RestoreMetadataFilter != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreMetadataFilter = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key)) + { + if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TimeToLiveInSeconds = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.EffectivePartitionKey, key)) + { + if (throwIfAlreadyExists && this.EffectivePartitionKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EffectivePartitionKey = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UseSystemBudget, key)) + { + if (throwIfAlreadyExists && this.UseSystemBudget != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseSystemBudget = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PartitionKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKey = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RestoreMetadataFilter, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RestoreMetadataFilter != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreMetadataFilter = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TimeToLiveInSeconds = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.EffectivePartitionKey, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EffectivePartitionKey != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EffectivePartitionKey = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UseSystemBudget, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UseSystemBudget != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseSystemBudget = value; + return; + } + break; + case 29: + if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ClientIpAddress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ClientIpAddress = value; + return; + } + break; + case 30: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) + { + if (throwIfAlreadyExists && this.ResourceTokenExpiry != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceTokenExpiry = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionCount, key)) + { + if (throwIfAlreadyExists && this.PartitionCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionCount = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionRid, key)) + { + if (throwIfAlreadyExists && this.CollectionRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionRid = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionResourceFilter, key)) + { + if (throwIfAlreadyExists && this.PartitionResourceFilter != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionResourceFilter = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ExcludeSystemProperties, key)) + { + if (throwIfAlreadyExists && this.ExcludeSystemProperties != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ExcludeSystemProperties = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key)) + { + if (throwIfAlreadyExists && this.IsCassandraAlterTypeRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsCassandraAlterTypeRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResourceTokenExpiry != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceTokenExpiry = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PartitionCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionCount = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionRid, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionRid = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PartitionResourceFilter, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionResourceFilter != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionResourceFilter = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ExcludeSystemProperties, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ExcludeSystemProperties != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ExcludeSystemProperties = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsCassandraAlterTypeRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsCassandraAlterTypeRequest = value; + return; + } + break; + case 31: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key)) + { + if (throwIfAlreadyExists && this.ClientRetryAttemptCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ClientRetryAttemptCount = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key)) + { + if (throwIfAlreadyExists && this.CanOfferReplaceComplete != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanOfferReplaceComplete = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key)) + { + if (throwIfAlreadyExists && this.BinaryPassthroughRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BinaryPassthroughRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsClientEncrypted, key)) + { + if (throwIfAlreadyExists && this.IsClientEncrypted != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsClientEncrypted = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemDocumentType, key)) + { + if (throwIfAlreadyExists && this.SystemDocumentType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SystemDocumentType = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionTruncate, key)) + { + if (throwIfAlreadyExists && this.CollectionTruncate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionTruncate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ClientRetryAttemptCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ClientRetryAttemptCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ClientRetryAttemptCount = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CanOfferReplaceComplete, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CanOfferReplaceComplete != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CanOfferReplaceComplete = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.BinaryPassthroughRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.BinaryPassthroughRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BinaryPassthroughRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsClientEncrypted, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsClientEncrypted != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsClientEncrypted = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SystemDocumentType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SystemDocumentType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SystemDocumentType = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CollectionTruncate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionTruncate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionTruncate = value; + return; + } + break; + case 32: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key)) + { + if (throwIfAlreadyExists && this.MigrateCollectionDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateCollectionDirective = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key)) + { + if (throwIfAlreadyExists && this.TargetGlobalCommittedLsn != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TargetGlobalCommittedLsn = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceQueryScan, key)) + { + if (throwIfAlreadyExists && this.ForceQueryScan != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceQueryScan = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key)) + { + if (throwIfAlreadyExists && this.MaxPollingIntervalMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxPollingIntervalMilliseconds = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key)) + { + if (throwIfAlreadyExists && this.PopulateIndexMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateIndexMetrics = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateCollectionDirective, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MigrateCollectionDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateCollectionDirective = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TargetGlobalCommittedLsn != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TargetGlobalCommittedLsn = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ForceQueryScan, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ForceQueryScan != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceQueryScan = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MaxPollingIntervalMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxPollingIntervalMilliseconds = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateIndexMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateIndexMetrics = value; + return; + } + break; + case 33: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableScanInQuery, key)) + { + if (throwIfAlreadyExists && this.EnableScanInQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableScanInQuery = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key)) + { + if (throwIfAlreadyExists && this.EmitVerboseTracesInQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EmitVerboseTracesInQuery = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key)) + { + if (throwIfAlreadyExists && this.PopulateQuotaInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateQuotaInfo = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreserveFullContent, key)) + { + if (throwIfAlreadyExists && this.PreserveFullContent != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreserveFullContent = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key)) + { + if (throwIfAlreadyExists && this.PopulateLogStoreInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateLogStoreInfo = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CorrelatedActivityId, key)) + { + if (throwIfAlreadyExists && this.CorrelatedActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CorrelatedActivityId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableScanInQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableScanInQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableScanInQuery = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EmitVerboseTracesInQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EmitVerboseTracesInQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EmitVerboseTracesInQuery = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateQuotaInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateQuotaInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateQuotaInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PreserveFullContent, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PreserveFullContent != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreserveFullContent = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateLogStoreInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateLogStoreInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateLogStoreInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CorrelatedActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CorrelatedActivityId = value; + return; + } + break; + case 34: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowTentativeWrites, key)) + { + if (throwIfAlreadyExists && this.AllowTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowTentativeWrites = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UseArchivalPartition, key)) + { + if (throwIfAlreadyExists && this.UseArchivalPartition != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseArchivalPartition = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCapacityType, key)) + { + if (throwIfAlreadyExists && this.PopulateCapacityType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCapacityType = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key)) + { + if (throwIfAlreadyExists && this.CosmosGatewayTransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CosmosGatewayTransactionId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AllowTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AllowTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowTentativeWrites = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.UseArchivalPartition, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UseArchivalPartition != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseArchivalPartition = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateCapacityType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateCapacityType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCapacityType = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CosmosGatewayTransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CosmosGatewayTransactionId = value; + return; + } + break; + case 35: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerInclude, key)) + { + if (throwIfAlreadyExists && this.PreTriggerInclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreTriggerInclude = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PreTriggerExclude, key)) + { + if (throwIfAlreadyExists && this.PreTriggerExclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreTriggerExclude = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key)) + { + if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKeyRangeId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key)) + { + if (throwIfAlreadyExists && this.FilterBySchemaResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.FilterBySchemaResourceId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key)) + { + if (throwIfAlreadyExists && this.CollectionRemoteStorageSecurityIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionRemoteStorageSecurityIdentifier = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key)) + { + if (throwIfAlreadyExists && this.RemainingTimeInMsOnClientRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RemainingTimeInMsOnClientRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key)) + { + if (throwIfAlreadyExists && this.ShouldBatchContinueOnError != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShouldBatchContinueOnError = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IntendedCollectionRid, key)) + { + if (throwIfAlreadyExists && this.IntendedCollectionRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IntendedCollectionRid = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key)) + { + if (throwIfAlreadyExists && this.PopulateIndexMetricsV2 != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateIndexMetricsV2 = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PreTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PreTriggerInclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreTriggerInclude = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PreTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PreTriggerExclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PreTriggerExclude = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKeyRangeId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.FilterBySchemaResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.FilterBySchemaResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.FilterBySchemaResourceId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CollectionRemoteStorageSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionRemoteStorageSecurityIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionRemoteStorageSecurityIdentifier = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RemainingTimeInMsOnClientRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RemainingTimeInMsOnClientRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ShouldBatchContinueOnError, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ShouldBatchContinueOnError != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShouldBatchContinueOnError = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IntendedCollectionRid, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IntendedCollectionRid != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IntendedCollectionRid = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateIndexMetricsV2, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateIndexMetricsV2 != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateIndexMetricsV2 = value; + return; + } + break; + case 36: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerInclude, key)) + { + if (throwIfAlreadyExists && this.PostTriggerInclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PostTriggerInclude = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PostTriggerExclude, key)) + { + if (throwIfAlreadyExists && this.PostTriggerExclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PostTriggerExclude = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key)) + { + if (throwIfAlreadyExists && this.PopulateQueryMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateQueryMetrics = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsUserRequest, key)) + { + if (throwIfAlreadyExists && this.IsUserRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsUserRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key)) + { + if (throwIfAlreadyExists && this.IncludeTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IncludeTentativeWrites = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key)) + { + if (throwIfAlreadyExists && this.IsRetriedWriteRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRetriedWriteRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key)) + { + if (throwIfAlreadyExists && this.PruneCollectionSchemas != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PruneCollectionSchemas = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) + { + if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedQueryFeatures = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PostTriggerInclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PostTriggerInclude = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PostTriggerExclude, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PostTriggerExclude != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PostTriggerExclude = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateQueryMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateQueryMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateQueryMetrics = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IsUserRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsUserRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsUserRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IncludeTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IncludeTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IncludeTentativeWrites = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IsRetriedWriteRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsRetriedWriteRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRetriedWriteRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PruneCollectionSchemas, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PruneCollectionSchemas != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PruneCollectionSchemas = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedQueryFeatures = value; + return; + } + break; + case 37: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) + { + if (throwIfAlreadyExists && this.EnableLogging != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableLogging = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateResourceCount, key)) + { + if (throwIfAlreadyExists && this.PopulateResourceCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateResourceCount = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key)) + { + if (throwIfAlreadyExists && this.SDKSupportedCapabilities != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SDKSupportedCapabilities = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key)) + { + if (throwIfAlreadyExists && this.BuilderClientIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BuilderClientIdentifier = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) + { + if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRequestNotAuthorized = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableLogging != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableLogging = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateResourceCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateResourceCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateResourceCount = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SDKSupportedCapabilities, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SDKSupportedCapabilities != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SDKSupportedCapabilities = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.BuilderClientIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.BuilderClientIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BuilderClientIdentifier = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRequestNotAuthorized = value; + return; + } + break; + case 38: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) + { + if (throwIfAlreadyExists && this.MigrateOfferToAutopilot != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateOfferToAutopilot = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestId, key)) + { + if (throwIfAlreadyExists && this.RetriableWriteRequestId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetriableWriteRequestId = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key)) + { + if (throwIfAlreadyExists && this.SourceCollectionIfMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SourceCollectionIfMatch = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key)) + { + if (throwIfAlreadyExists && this.UseUserBackgroundBudget != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseUserBackgroundBudget = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MigrateOfferToAutopilot != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateOfferToAutopilot = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RetriableWriteRequestId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetriableWriteRequestId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SourceCollectionIfMatch, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SourceCollectionIfMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SourceCollectionIfMatch = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UseUserBackgroundBudget, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UseUserBackgroundBudget != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UseUserBackgroundBudget = value; + return; + } + break; + case 39: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key)) + { + if (throwIfAlreadyExists && this.TruncateMergeLogRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TruncateMergeLogRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key)) + { + if (throwIfAlreadyExists && this.IsInternalServerlessRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsInternalServerlessRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TruncateMergeLogRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TruncateMergeLogRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TruncateMergeLogRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsInternalServerlessRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsInternalServerlessRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsInternalServerlessRequest = value; + return; + } + break; + case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key)) + { + if (throwIfAlreadyExists && this.EnableDynamicRidRangeAllocation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableDynamicRidRangeAllocation = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key)) + { + if (throwIfAlreadyExists && this.UniqueIndexReIndexingState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UniqueIndexReIndexingState = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableDynamicRidRangeAllocation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableDynamicRidRangeAllocation = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UniqueIndexReIndexingState, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UniqueIndexReIndexingState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UniqueIndexReIndexingState = value; + return; + } + break; + case 41: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key)) + { + if (throwIfAlreadyExists && this.ForceDatabaseAccountUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceDatabaseAccountUpdate = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key)) + { + if (throwIfAlreadyExists && this.OptimisticDirectExecute != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OptimisticDirectExecute = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipThroughputCapValidation, key)) + { + if (throwIfAlreadyExists && this.SkipThroughputCapValidation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SkipThroughputCapValidation = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ForceDatabaseAccountUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceDatabaseAccountUpdate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.OptimisticDirectExecute, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OptimisticDirectExecute != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OptimisticDirectExecute = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SkipThroughputCapValidation, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SkipThroughputCapValidation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SkipThroughputCapValidation = value; + return; + } + break; + case 42: + if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key)) + { + if (throwIfAlreadyExists && this.MergeCheckPointGLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeCheckPointGLSN = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key)) + { + if (throwIfAlreadyExists && this.ShouldReturnCurrentServerDateTime != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShouldReturnCurrentServerDateTime = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key)) + { + if (throwIfAlreadyExists && this.ChangeFeedWireFormatVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedWireFormatVersion = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateUserStrings, key)) + { + if (throwIfAlreadyExists && this.PopulateUserStrings != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateUserStrings = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) + { + if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableCrossPartitionQuery = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MergeCheckPointGLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeCheckPointGLSN = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ShouldReturnCurrentServerDateTime != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShouldReturnCurrentServerDateTime = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ChangeFeedWireFormatVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedWireFormatVersion = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateUserStrings, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateUserStrings != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateUserStrings = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableCrossPartitionQuery = value; + return; + } + break; + case 43: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) + { + if (throwIfAlreadyExists && this.DisableRUPerMinuteUsage != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DisableRUPerMinuteUsage = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key)) + { + if (throwIfAlreadyExists && this.PopulatePartitionStatistics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulatePartitionStatistics = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key)) + { + if (throwIfAlreadyExists && this.ForceSideBySideIndexMigration != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceSideBySideIndexMigration = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key)) + { + if (throwIfAlreadyExists && this.UniqueIndexNameEncodingMode != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UniqueIndexNameEncodingMode = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key)) + { + if (throwIfAlreadyExists && this.SupportedSerializationFormats != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedSerializationFormats = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.DisableRUPerMinuteUsage != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DisableRUPerMinuteUsage = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulatePartitionStatistics, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulatePartitionStatistics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulatePartitionStatistics = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ForceSideBySideIndexMigration, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ForceSideBySideIndexMigration != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ForceSideBySideIndexMigration = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UniqueIndexNameEncodingMode, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UniqueIndexNameEncodingMode != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UniqueIndexNameEncodingMode = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SupportedSerializationFormats, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SupportedSerializationFormats != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedSerializationFormats = value; + return; + } + break; + case 44: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ContentSerializationFormat, key)) + { + if (throwIfAlreadyExists && this.ContentSerializationFormat != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ContentSerializationFormat = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key)) + { + if (throwIfAlreadyExists && this.PopulateOldestActiveSchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateOldestActiveSchemaId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) + { + if (throwIfAlreadyExists && this.IsContinuationExpected != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsContinuationExpected = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ContentSerializationFormat != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ContentSerializationFormat = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateOldestActiveSchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateOldestActiveSchemaId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsContinuationExpected != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsContinuationExpected = value; + return; + } + break; + case 45: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) + { + if (throwIfAlreadyExists && this.ChangeFeedStartFullFidelityIfNoneMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedStartFullFidelityIfNoneMatch = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SystemRestoreOperation, key)) + { + if (throwIfAlreadyExists && this.SystemRestoreOperation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SystemRestoreOperation = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key)) + { + if (throwIfAlreadyExists && this.IsThroughputCapRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsThroughputCapRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key)) + { + if (throwIfAlreadyExists && this.PopulateByokEncryptionProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateByokEncryptionProgress = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ChangeFeedStartFullFidelityIfNoneMatch != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedStartFullFidelityIfNoneMatch = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SystemRestoreOperation, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SystemRestoreOperation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SystemRestoreOperation = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsThroughputCapRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsThroughputCapRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsThroughputCapRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateByokEncryptionProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateByokEncryptionProgress = value; + return; + } + break; + case 46: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key)) + { + if (throwIfAlreadyExists && this.MigrateOfferToManualThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateOfferToManualThroughput = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key)) + { + if (throwIfAlreadyExists && this.SkipRefreshDatabaseAccountConfigs != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SkipRefreshDatabaseAccountConfigs = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key)) + { + if (throwIfAlreadyExists && this.IsMigratedFixedCollection != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMigratedFixedCollection = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MigrateOfferToManualThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MigrateOfferToManualThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MigrateOfferToManualThroughput = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SkipRefreshDatabaseAccountConfigs != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SkipRefreshDatabaseAccountConfigs = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsMigratedFixedCollection, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsMigratedFixedCollection != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMigratedFixedCollection = value; + return; + } + break; + case 47: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key)) + { + if (throwIfAlreadyExists && this.SupportSpatialLegacyCoordinates != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportSpatialLegacyCoordinates = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key)) + { + if (throwIfAlreadyExists && this.CollectionChildResourceNameLimitInBytes != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionChildResourceNameLimitInBytes = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key)) + { + if (throwIfAlreadyExists && this.AddResourcePropertiesToResponse != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AddResourcePropertiesToResponse = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key)) + { + if (throwIfAlreadyExists && this.IsMaterializedViewBuild != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMaterializedViewBuild = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SupportSpatialLegacyCoordinates, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SupportSpatialLegacyCoordinates != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportSpatialLegacyCoordinates = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionChildResourceNameLimitInBytes != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionChildResourceNameLimitInBytes = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.AddResourcePropertiesToResponse, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AddResourcePropertiesToResponse != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AddResourcePropertiesToResponse = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewBuild, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsMaterializedViewBuild != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMaterializedViewBuild = value; + return; + } + break; + case 48: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.PopulateCollectionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCollectionThroughputInfo = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key)) + { + if (throwIfAlreadyExists && this.GetAllPartitionKeyStatistics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GetAllPartitionKeyStatistics = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key)) + { + if (throwIfAlreadyExists && this.PopulateUniqueIndexReIndexProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateUniqueIndexReIndexProgress = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key)) + { + if (throwIfAlreadyExists && this.AllowRestoreParamsUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowRestoreParamsUpdate = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key)) + { + if (throwIfAlreadyExists && this.HighPriorityForcedBackup != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HighPriorityForcedBackup = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateCollectionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateCollectionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCollectionThroughputInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.GetAllPartitionKeyStatistics, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.GetAllPartitionKeyStatistics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GetAllPartitionKeyStatistics = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateUniqueIndexReIndexProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateUniqueIndexReIndexProgress = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AllowRestoreParamsUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowRestoreParamsUpdate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.HighPriorityForcedBackup, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.HighPriorityForcedBackup != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HighPriorityForcedBackup = value; + return; + } + break; + case 49: + if (string.Equals(HttpConstants.HttpHeaders.UsePolygonsSmallerThanAHemisphere, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UsePolygonsSmallerThanAHemisphere != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UsePolygonsSmallerThanAHemisphere = value; + return; + } + break; + case 50: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key)) + { + if (throwIfAlreadyExists && this.ResponseContinuationTokenLimitInKB != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResponseContinuationTokenLimitInKB = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key)) + { + if (throwIfAlreadyExists && this.PopulateAnalyticalMigrationProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateAnalyticalMigrationProgress = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key)) + { + if (throwIfAlreadyExists && this.UpdateOfferStateToPending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateOfferStateToPending = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ResponseContinuationTokenLimitInKB, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResponseContinuationTokenLimitInKB != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResponseContinuationTokenLimitInKB = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateAnalyticalMigrationProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateAnalyticalMigrationProgress = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToPending, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UpdateOfferStateToPending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateOfferStateToPending = value; + return; + } + break; + case 51: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key)) + { + if (throwIfAlreadyExists && this.EnableLowPrecisionOrderBy != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableLowPrecisionOrderBy = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key)) + { + if (throwIfAlreadyExists && this.RetriableWriteRequestStartTimestamp != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetriableWriteRequestStartTimestamp = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateDocumentRecordCount, key)) + { + if (throwIfAlreadyExists && this.PopulateDocumentRecordCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateDocumentRecordCount = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableLowPrecisionOrderBy, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableLowPrecisionOrderBy != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableLowPrecisionOrderBy = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RetriableWriteRequestStartTimestamp != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetriableWriteRequestStartTimestamp = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateDocumentRecordCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateDocumentRecordCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateDocumentRecordCount = value; + return; + } + break; + case 52: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) + { + if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplaceRURedistribution = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) + { + if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ParallelizeCrossPartitionQuery = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplaceRURedistribution = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ParallelizeCrossPartitionQuery = value; + return; + } + break; + case 53: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) + { + if (throwIfAlreadyExists && this.IsRUPerGBEnforcementRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRUPerGBEnforcementRequest = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key)) + { + if (throwIfAlreadyExists && this.IsOfferStorageRefreshRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsOfferStorageRefreshRequest = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key)) + { + if (throwIfAlreadyExists && this.PopulateMinGLSNForDocumentOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateMinGLSNForDocumentOperations = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsRUPerGBEnforcementRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRUPerGBEnforcementRequest = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsOfferStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsOfferStorageRefreshRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsOfferStorageRefreshRequest = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateMinGLSNForDocumentOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateMinGLSNForDocumentOperations = value; + return; + } + break; + case 54: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.IncludePhysicalPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IncludePhysicalPartitionThroughputInfo = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key)) + { + if (throwIfAlreadyExists && this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCurrentPartitionThroughputInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IncludePhysicalPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IncludePhysicalPartitionThroughputInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsMaterializedViewSourceSchemaReplaceBatchRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCurrentPartitionThroughputInfo = value; + return; + } + break; + case 55: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) + { + if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateOfferStateToRestorePending = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) + { + if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SqlQueryForPartitionKeyExtraction = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateOfferStateToRestorePending = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SqlQueryForPartitionKeyExtraction = value; + return; + } + break; + case 56: + if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionChildResourceContentLimitInKB != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionChildResourceContentLimitInKB = value; + return; + } + break; + case 57: + if (string.Equals(WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateUnflushedMergeEntryCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateUnflushedMergeEntryCount = value; + return; + } + break; + case 58: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key)) + { + if (throwIfAlreadyExists && this.IgnoreSystemLoweringMaxThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IgnoreSystemLoweringMaxThroughput = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key)) + { + if (throwIfAlreadyExists && this.SetMasterResourcesDeletionPending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SetMasterResourcesDeletionPending = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key)) + { + if (throwIfAlreadyExists && this.PopulateHighestTentativeWriteLLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateHighestTentativeWriteLLSN = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IgnoreSystemLoweringMaxThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IgnoreSystemLoweringMaxThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IgnoreSystemLoweringMaxThroughput = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SetMasterResourcesDeletionPending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SetMasterResourcesDeletionPending = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateHighestTentativeWriteLLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateHighestTentativeWriteLLSN = value; + return; + } + break; + case 59: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) + { + if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateMaxThroughputEverProvisioned = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) + { + if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableConflictResolutionPolicyUpdate = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) + { + if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowDocumentReadsInOfflineRegion = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateMaxThroughputEverProvisioned = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableConflictResolutionPolicyUpdate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowDocumentReadsInOfflineRegion = value; + return; + } + break; + case 61: + if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsServerlessStorageRefreshRequest != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsServerlessStorageRefreshRequest = value; + return; + } + break; + case 62: + if (string.Equals(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SkipAdjustThroughputFractionsForOfferReplace != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SkipAdjustThroughputFractionsForOfferReplace = value; + return; + } + break; + default: + break; + } + + if (ignoreNotCommonHeaders) + { + return; + } + + if (throwIfAlreadyExists) + { + this.InitializeNotCommonHeadersIfNeeded(); + this.notCommonHeaders.Add(key, value); + } + else + { + if (value == null) + { + if (this.notCommonHeaders != null) + { + this.notCommonHeaders.Remove(key); + } + } + else + { + this.InitializeNotCommonHeadersIfNeeded(); + this.notCommonHeaders[key] = value; + } + } + } + + /// + /// Thread safe initialization is needed to make sure we do not lose headers. + /// + private void InitializeNotCommonHeadersIfNeeded() + { + if (this.notCommonHeaders == null) + { + lock (this) + { + if (this.notCommonHeaders == null) + { + this.notCommonHeaders = new Dictionary(RequestNameValueCollection.DefaultStringComparer); + } + } + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs index a473107bed..1a1cca73b1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs @@ -1,703 +1,708 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - using System; - using System.Collections.Generic; - using System.Threading; - using Newtonsoft.Json; - - /// - /// Encapsulates options that can be specified for different requests issued to the Azure Cosmos DB service. - /// - /// - /// Some of these options are valid for specific operations only. - /// For example, - /// PreTriggerInclude can be used only on create, replace and delete operations on a or . - /// ETag, while valid on Replace* and Delete* operations, would have no impact on a Read*, CreateQuery* or Create* operations. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class RequestOptions - { - /// - /// Gets or sets the trigger to be invoked before the operation in the Azure Cosmos DB service. - /// - /// - /// The trigger to be invoked before the operation. - /// - /// - /// Only valid when used with Create, Replace and Delete methods for documents. - /// Currently only one PreTrigger is permitted per operation. - /// - /// - /// The following example shows how to use RequestOptions to include a PreTrigger to execute before persisting the document. - /// - /// { "validateDocumentContents" } }); - /// ]]> - /// - /// - /// - /// - public IList PreTriggerInclude { get; set; } - - /// - /// Gets or sets the trigger to be invoked after the operation in the Azure Cosmos DB service. - /// - /// - /// The trigger to be invoked after the operation. - /// - /// - /// Only valid when used with Create, Replace and Delete methods for documents. - /// Currently only one PreTrigger is permitted per operation. - /// - /// - /// The following example shows how to use RequestOptions to include a PostTrigger to execute after persisting the document. - /// - /// { "updateMetadata" } }); - /// ]]> - /// - /// - /// - public IList PostTriggerInclude { get; set; } - - /// - /// Gets or sets the condition (ETag) associated with the request in the Azure Cosmos DB service. - /// - /// - /// The condition (ETag) associated with the request. - /// - /// - /// Most commonly used with the Delete* and Replace* methods of such as - /// or methods, - /// but can be used with other methods like for caching scenarios. - /// - /// - /// The following example shows how to use RequestOptions with to - /// specify the set of to be used when updating a document - /// - /// - /// - /// - /// - public AccessCondition AccessCondition { get; set; } - - /// - /// Gets or sets the indexing directive (Include or Exclude) for the request in the Azure Cosmos DB service. - /// - /// - /// The indexing directive to use with a request. - /// - /// - /// The following example shows how to explicitly index a document in a collection with - /// automatic indexing turned off. - /// - /// - /// - /// - /// - /// - public IndexingDirective? IndexingDirective { get; set; } - - /// - /// Gets or sets the consistency level required for the request in the Azure Cosmos DB service. - /// - /// - /// The consistency level required for the request. - /// - /// - /// Azure Cosmos DB offers 5 different consistency levels. Strong, Bounded Staleness, Session, Consistent Prefix and Eventual - in order of strongest to weakest consistency. - /// - /// While this is set at a database account level, Azure Cosmos DB allows a developer to override the default consistency level - /// for each individual request. - /// - /// - /// - /// This example uses RequestOptions to override the consistency level to Eventual for this single Read operation. - /// - /// - /// - /// - /// - public ConsistencyLevel? ConsistencyLevel { get; set; } - - /// - /// Gets or sets the token for use with session consistency in the Azure Cosmos DB service. - /// - /// - /// The token for use with session consistency. - /// - /// - /// - /// One of the for Azure Cosmos DB is Session. In fact, this is the deault level applied to accounts. - /// - /// When working with Session consistency, each new write request to Azure Cosmos DB is assigned a new SessionToken. - /// The DocumentClient will use this token internally with each read/query request to ensure that the set consistency level is maintained. - /// - /// - /// In some scenarios you need to manage this Session yourself; - /// Consider a web application with multiple nodes, each node will have its own instance of - /// If you wanted these nodes to participate in the same session (to be able read your own writes consistently across web tiers) - /// you would have to send the SessionToken from of the write action on one node - /// to the client tier, using a cookie or some other mechanism, and have that token flow back to the web tier for subsequent reads. - /// If you are using a round-robin load balancer which does not maintain session affinity between requests, such as the Azure Load Balancer, - /// the read could potentially land on a different node to the write request, where the session was created. - /// - /// - /// - /// If you do not flow the Azure Cosmos DB SessionToken across as described above you could end up with inconsistent read results for a period of time. - /// - /// - /// - /// - /// - /// - /// This example shows how you can retrieve the SessionToken from a - /// and then use it on a different instance of within - /// This example assumes that the each instance of the client is running from code within a different AppDomain, such as on different nodes in the case of multiple node web application - /// - /// response = client.CreateDocumentAsync(collection.SelfLink, new { id = "an id", value = "some value" }).Result; - /// sessionToken = response.SessionToken; - /// Document created = response.Resource; - /// docSelfLink = created.SelfLink; - /// } - /// - /// using (DocumentClient client = new DocumentClient(new Uri(""), "")) - /// { - /// ResourceResponse read = client.ReadDocumentAsync(docSelfLink, new RequestOptions { SessionToken = sessionToken }).Result; - /// } - /// ]]> - /// - /// - /// - public string SessionToken { get; set; } - - /// - /// Gets or sets the expiry time for resource token. Used when creating/updating/reading permissions in the Azure Cosmos DB service. - /// - /// - /// The expiry time in seconds for the resource token. - /// - /// - /// When working with Azure Cosmos DB Users and Permissions, the way to instantiate an instance of is to - /// get the for the resource the wants to access and pass this - /// to the authKeyOrResourceToken parameter of constructor - /// - /// When requesting this Token, a RequestOption for ResourceTokenExpirySeconds can be used to set the length of time to elapse before the token expires. - /// This value can range from 10 seconds, to 5 hours (or 18,000 seconds) - /// The default value for this, should none be supplied is 1 hour (or 3,600 seconds). - /// - /// - /// - /// - /// - public int? ResourceTokenExpirySeconds { get; set; } - - /// - /// Gets or sets the offer type for the resource in the Azure Cosmos DB service. - /// - /// - /// The offer type value. - /// - /// - /// This option is only valid when creating a document collection. - /// - /// Refer to http://azure.microsoft.comdocumentation/articles/documentdb-performance-levels/ for the list of valid - /// offer types. - /// - /// - /// - /// The followng example shows how to create a collection with the S2 offer. - /// - /// - /// - /// - /// - /// - public string OfferType { get; set; } - - /// - /// Gets or sets the offer throughput provisioned for a collection in measurement of Requests-per-Unit in the Azure Cosmos DB service. - /// - /// - /// The provisioned throughtput for this offer. - /// - /// - /// This option is only valid when creating a document collection. - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-performance-levels/ for details on provision offer throughput. - /// - /// - /// - /// The followng example shows how to create a collection with offer throughtput. - /// - /// - /// - /// - /// - /// - public int? OfferThroughput { get; set; } - - /// - /// Gets or sets the for a collection in the Azure Cosmos DB service - /// - /// - /// Represents Request Units(RU)/Minute throughput is enabled/disabled for a collection in the Azure Cosmos DB service. - /// - /// - /// This option is only valid when creating a document collection. - /// - /// - /// The followng example shows how to create a collection with RU/Minute throughput offer. - /// - /// - /// - /// - /// - /// - public bool OfferEnableRUPerMinuteThroughput { get; set; } - - /// - /// Gets or sets the for a collection in the Azure Cosmos DB service - /// - /// - /// Represents customizable maximum allowed throughput budget in percentage chosen by user to run any - /// background task(eg. PK Delete, Creating UniqueIndex policy) for the collection in the Azure Cosmos DB service. - /// In the absence of any background task, the whole throughput is available for use by customer for their workload. - /// But even in absence of user workload, user background task will not utilize over the allotted percentage of throughput. - /// We will have default value of BackgroundTaskMaxAllowedThroughputPercent to be 10 percent if user has not explicitly set it. - /// This helps the background tasks to not starve and at the same time impact on user's workload will be minimal. - /// User can set the value in range (10,100]. - /// - /// - /// This option is only valid when creating a document collection. - /// - /// - /// The followng example shows how to create a collection with BackgroundTaskMaxAllowedThroughputPercent and throughput offer. - /// - /// - /// - /// - /// - /// - internal double? BackgroundTaskMaxAllowedThroughputPercent { get; set; } - - /// - /// Gets or sets the for the current request in the Azure Cosmos DB service. - /// - /// - /// - /// Partition key is used to identify the target partition for this request. It must be set on read and delete - /// operations for all document requests; create, read, update and delete operations for all document attachment requests; - /// and execute operation on stored producedures. - /// - /// For create and update operations on documents, the partition key is optional. When absent, the client library will - /// extract the partition key from the document before sending the request to the server. - /// - /// - /// - /// The following example shows how to read a document in a partitioned collection using . - /// The example assumes the collection is created with a of the 'id' property in all the documents. - /// - /// - /// - /// - /// - /// - public PartitionKey PartitionKey { get; set; } - - /// - /// Gets or sets the for the current request in the Azure Cosmos DB service. - /// - /// - /// - /// EnableScriptLogging is used to enable/disable logging in JavaScript stored procedures. - /// By default script logging is disabled. - /// The log can also be accessible in response header (x-ms-documentdb-script-log-results). - /// - /// - /// - /// The following example shows how to enable logging in stored procedures using . - /// - /// - /// - /// To log, use the following in store procedure: - /// - /// - /// - /// - /// - public bool EnableScriptLogging { get; set; } - - /// - /// Gets or sets for stored procedure execution requests in Azure Cosmos DB. - /// - /// - /// - /// IsReadOnlyScript indicates whether a script is read-only. Set this value to true only if the stored procedure contains - /// no create, update, or delete operations; otherwise, set this value to false. - /// Setting this value to true enables Azure Cosmos DB to optimize performance of read-only scripts. - /// - /// - internal bool IsReadOnlyScript { get; set; } - - /// - /// Gets or sets for snapshot read requests in Azure Cosmos DB. - /// - /// - /// - /// IncludeSnapshotDirectories is used to populate the snapshot content with storage SAS uris. - /// - /// - internal bool IncludeSnapshotDirectories { get; set; } - - /// - /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. - /// - /// - /// - /// PopulateQuotaInfo is used to enable/disable getting document collection quota related stats for document collection read requests. - /// - /// - public bool PopulateQuotaInfo { get; set; } - - /// - /// Gets or sets the for the current request in the Azure Cosmos DB service. - /// - /// - /// - /// DisableRUPerMinuteUsage is used to enable/disable Request Units(RUs)/minute capacity to serve the request if regular provisioned RUs/second is exhausted. - /// - /// - public bool DisableRUPerMinuteUsage { get; set; } - - /// - /// Gets or sets the for the current request used to deserialize the document. - /// If null, uses the default serializer settings set up in the DocumentClient. - /// - public JsonSerializerSettings JsonSerializerSettings { get; set; } - - /// - /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. - /// - /// - /// - /// is used to enable/disable getting partition key range statistics. - /// - /// - /// - /// For usage, please refer to the example in . - /// - public bool PopulatePartitionKeyRangeStatistics { get; set; } - - /// - /// Gets or sets the for document collection read unique index reindex progress. - /// - /// - /// - /// is used to enable/disable getting unique index reindex progress. - /// - /// - /// - /// For usage, please refer to the example in . - /// - internal bool PopulateUniqueIndexReIndexProgress { get; set; } - - /// - /// Gets or sets the for document collection read requests. - /// - /// - /// - /// is used to enable/disable getting analytical migration progress. - /// - /// - /// - /// For usage, please refer to the example in . - /// - internal bool PopulateAnalyticalMigrationProgress { get; set; } - - /// - /// Gets or sets the for document collection read requests. - /// - /// - /// - /// is used to enable/disable getting byok reencryption progress. - /// - /// - /// - /// For usage, please refer to the example in . - /// - internal bool PopulateBYOKEncryptionProgress { get; set; } - - /// - /// Gets or sets the Remote storage enablement - /// To be used along with Collection creation operation - /// - //internal RemoteStorageType RemoteStorageTypes { get; set; } - internal RemoteStorageType? RemoteStorageType { get; set; } - - /// - /// Gets or sets the partition key range id for the current request. - /// - /// - /// - /// Requests can use this to forward request to specific range. - /// This is useful in case of bulk export scenarios. - /// - /// - /// - /// The following example shows how to read a document feed in a partitioned collection from partition key range "20". - /// - /// - /// - /// - /// - internal string PartitionKeyRangeId { get; set; } - - /// - /// Gets or sets source databse from which to restore. - /// To be used along with RemoteStorageType, SourceCollectionId and RestorePointInTime - /// during Collection creation operation. - /// - internal string SourceDatabaseId { get; set; } - - /// - /// Gets or sets source collection from which to restore. - /// To be used along with RemoteStorageType, SourceDatabaseId and RestorePointInTime - /// during Collection creation operation. - /// - internal string SourceCollectionId { get; set; } - - /// - /// Gets or sets restore point-in-time. - /// To be used along with RemoteStorageType, SourceDatabaseId, SourceCollectionId - /// during Collection creation operation. - /// - internal long? RestorePointInTime { get; set; } - - /// - /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. - /// - /// - /// - /// PopulateRestoreStatus is used to retreieve the status of a collection being restored. - /// - /// - internal bool PopulateRestoreStatus { get; set; } - - /// - /// Gets or sets the for document create requests in the Azure Cosmos DB service. - /// - /// - /// - /// PopulateCapacityType is used to return the capacity type of the request. - /// - /// - internal bool PopulateCapacityType { get; set; } - - /// - /// Gets or sets exclude system properties. - /// ExcludeSystemProperties indicates whether system properties - /// should be excluded from JSON content of a document or not. - /// - internal bool? ExcludeSystemProperties { get; set; } - - /// - /// Gets or sets the InsertSystemPartitionKey option - /// To be used along with Collection creation operation - /// - internal bool InsertSystemPartitionKey { get; set; } - - /// - /// Gets or sets the MergeStaticId - /// To be used along with Read operation when Static Column merge is desired. - /// - internal string MergeStaticId { get; set; } - - /// - /// PreserveFullContent is used to enable/disable getting document collection internal indexing properties. - /// which has information regarding the collection's logicalIndexVersion - /// - internal bool PreserveFullContent { get; set; } - - /// - /// ForceSideBySideIndexMigration is used to force a side by side index migration on a collection replace - /// - internal bool ForceSideBySideIndexMigration { get; set; } - - /// - /// Truncate the Collection - /// - internal bool CollectionTruncate { get; set; } - - /// - /// Represents client-side encryption - /// - internal bool IsClientEncrypted { get; set; } - - /// - /// Gets or sets shared offer throughput on a collection. - /// - /// - /// This option is only valid when creating a document collection that shares offer throughput - /// provisioned at database level. Specifies maximum shared throughput available for collection - /// in the absence of contention. This value should be less than the throughput specified at - /// database level. - /// - /// - /// The followng example shows how to create a collection with offer throughtput. - /// - /// - /// - /// - [Obsolete("Deprecated")] - public int? SharedOfferThroughput { get; set; } - - /// - /// Gets or sets the priority level for the request in the Azure Cosmos DB service. - /// - /// - /// The priority level to use with a request. - /// - /// - /// - internal PriorityLevel? PriorityLevel { get; set; } - -#if !COSMOSCLIENT - /// - /// Gets or sets for a collection/database in the Azure Cosmos DB service - /// - /// - /// Valid values integers starting 1 - /// - /// - /// This option is only valid when creating a document collection or database. - /// - /// - /// The followng example shows how to create a collection with Autopilot Tier. - /// - /// - /// - /// - /// - /// - /// - internal int? OfferAutopilotTier { get; set; } - - /// - /// Gets or sets for a collection/database in the Azure Cosmos DB service - /// - /// - /// Valid values are true, false - /// - /// - /// This option is only valid when creating a document collection or database. - /// - /// - /// The followng example shows how to create a collection with Autopilot Tier and AutoUpgrade option. - /// - /// - /// - /// - /// - /// - /// - internal bool? OfferAutopilotAutoUpgrade { get; set; } - - /// - /// OfferAutopilotSettings is used to control how provisioned throughput for a container - /// or database automatically scales. - /// - /// - /// This option is only valid when creating a document collection or database. - /// - internal AutopilotSettings OfferAutopilotSettings { get; set; } -#endif - - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + using System; + using System.Collections.Generic; + using System.Threading; + using Newtonsoft.Json; + + /// + /// Encapsulates options that can be specified for different requests issued to the Azure Cosmos DB service. + /// + /// + /// Some of these options are valid for specific operations only. + /// For example, + /// PreTriggerInclude can be used only on create, replace and delete operations on a or . + /// ETag, while valid on Replace* and Delete* operations, would have no impact on a Read*, CreateQuery* or Create* operations. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class RequestOptions + { + /// + /// Gets or sets the trigger to be invoked before the operation in the Azure Cosmos DB service. + /// + /// + /// The trigger to be invoked before the operation. + /// + /// + /// Only valid when used with Create, Replace and Delete methods for documents. + /// Currently only one PreTrigger is permitted per operation. + /// + /// + /// The following example shows how to use RequestOptions to include a PreTrigger to execute before persisting the document. + /// + /// { "validateDocumentContents" } }); + /// ]]> + /// + /// + /// + /// + public IList PreTriggerInclude { get; set; } + + /// + /// Gets or sets the trigger to be invoked after the operation in the Azure Cosmos DB service. + /// + /// + /// The trigger to be invoked after the operation. + /// + /// + /// Only valid when used with Create, Replace and Delete methods for documents. + /// Currently only one PreTrigger is permitted per operation. + /// + /// + /// The following example shows how to use RequestOptions to include a PostTrigger to execute after persisting the document. + /// + /// { "updateMetadata" } }); + /// ]]> + /// + /// + /// + public IList PostTriggerInclude { get; set; } + + /// + /// Gets or sets the condition (ETag) associated with the request in the Azure Cosmos DB service. + /// + /// + /// The condition (ETag) associated with the request. + /// + /// + /// Most commonly used with the Delete* and Replace* methods of such as + /// or methods, + /// but can be used with other methods like for caching scenarios. + /// + /// + /// The following example shows how to use RequestOptions with to + /// specify the set of to be used when updating a document + /// + /// + /// + /// + /// + public AccessCondition AccessCondition { get; set; } + + /// + /// Gets or sets the indexing directive (Include or Exclude) for the request in the Azure Cosmos DB service. + /// + /// + /// The indexing directive to use with a request. + /// + /// + /// The following example shows how to explicitly index a document in a collection with + /// automatic indexing turned off. + /// + /// + /// + /// + /// + /// + public IndexingDirective? IndexingDirective { get; set; } + + /// + /// Gets or sets the consistency level required for the request in the Azure Cosmos DB service. + /// + /// + /// The consistency level required for the request. + /// + /// + /// Azure Cosmos DB offers 5 different consistency levels. Strong, Bounded Staleness, Session, Consistent Prefix and Eventual - in order of strongest to weakest consistency. + /// + /// While this is set at a database account level, Azure Cosmos DB allows a developer to override the default consistency level + /// for each individual request. + /// + /// + /// + /// This example uses RequestOptions to override the consistency level to Eventual for this single Read operation. + /// + /// + /// + /// + /// + public ConsistencyLevel? ConsistencyLevel { get; set; } + + /// + /// Gets or sets the token for use with session consistency in the Azure Cosmos DB service. + /// + /// + /// The token for use with session consistency. + /// + /// + /// + /// One of the for Azure Cosmos DB is Session. In fact, this is the deault level applied to accounts. + /// + /// When working with Session consistency, each new write request to Azure Cosmos DB is assigned a new SessionToken. + /// The DocumentClient will use this token internally with each read/query request to ensure that the set consistency level is maintained. + /// + /// + /// In some scenarios you need to manage this Session yourself; + /// Consider a web application with multiple nodes, each node will have its own instance of + /// If you wanted these nodes to participate in the same session (to be able read your own writes consistently across web tiers) + /// you would have to send the SessionToken from of the write action on one node + /// to the client tier, using a cookie or some other mechanism, and have that token flow back to the web tier for subsequent reads. + /// If you are using a round-robin load balancer which does not maintain session affinity between requests, such as the Azure Load Balancer, + /// the read could potentially land on a different node to the write request, where the session was created. + /// + /// + /// + /// If you do not flow the Azure Cosmos DB SessionToken across as described above you could end up with inconsistent read results for a period of time. + /// + /// + /// + /// + /// + /// + /// This example shows how you can retrieve the SessionToken from a + /// and then use it on a different instance of within + /// This example assumes that the each instance of the client is running from code within a different AppDomain, such as on different nodes in the case of multiple node web application + /// + /// response = client.CreateDocumentAsync(collection.SelfLink, new { id = "an id", value = "some value" }).Result; + /// sessionToken = response.SessionToken; + /// Document created = response.Resource; + /// docSelfLink = created.SelfLink; + /// } + /// + /// using (DocumentClient client = new DocumentClient(new Uri(""), "")) + /// { + /// ResourceResponse read = client.ReadDocumentAsync(docSelfLink, new RequestOptions { SessionToken = sessionToken }).Result; + /// } + /// ]]> + /// + /// + /// + public string SessionToken { get; set; } + + /// + /// Gets or sets the expiry time for resource token. Used when creating/updating/reading permissions in the Azure Cosmos DB service. + /// + /// + /// The expiry time in seconds for the resource token. + /// + /// + /// When working with Azure Cosmos DB Users and Permissions, the way to instantiate an instance of is to + /// get the for the resource the wants to access and pass this + /// to the authKeyOrResourceToken parameter of constructor + /// + /// When requesting this Token, a RequestOption for ResourceTokenExpirySeconds can be used to set the length of time to elapse before the token expires. + /// This value can range from 10 seconds, to 5 hours (or 18,000 seconds) + /// The default value for this, should none be supplied is 1 hour (or 3,600 seconds). + /// + /// + /// + /// + /// + public int? ResourceTokenExpirySeconds { get; set; } + + /// + /// Gets or sets the offer type for the resource in the Azure Cosmos DB service. + /// + /// + /// The offer type value. + /// + /// + /// This option is only valid when creating a document collection. + /// + /// Refer to http://azure.microsoft.comdocumentation/articles/documentdb-performance-levels/ for the list of valid + /// offer types. + /// + /// + /// + /// The followng example shows how to create a collection with the S2 offer. + /// + /// + /// + /// + /// + /// + public string OfferType { get; set; } + + /// + /// Gets or sets the offer throughput provisioned for a collection in measurement of Requests-per-Unit in the Azure Cosmos DB service. + /// + /// + /// The provisioned throughtput for this offer. + /// + /// + /// This option is only valid when creating a document collection. + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-performance-levels/ for details on provision offer throughput. + /// + /// + /// + /// The followng example shows how to create a collection with offer throughtput. + /// + /// + /// + /// + /// + /// + public int? OfferThroughput { get; set; } + + /// + /// Gets or sets the for a collection in the Azure Cosmos DB service + /// + /// + /// Represents Request Units(RU)/Minute throughput is enabled/disabled for a collection in the Azure Cosmos DB service. + /// + /// + /// This option is only valid when creating a document collection. + /// + /// + /// The followng example shows how to create a collection with RU/Minute throughput offer. + /// + /// + /// + /// + /// + /// + public bool OfferEnableRUPerMinuteThroughput { get; set; } + + /// + /// Gets or sets the for a collection in the Azure Cosmos DB service + /// + /// + /// Represents customizable maximum allowed throughput budget in percentage chosen by user to run any + /// background task(eg. PK Delete, Creating UniqueIndex policy) for the collection in the Azure Cosmos DB service. + /// In the absence of any background task, the whole throughput is available for use by customer for their workload. + /// But even in absence of user workload, user background task will not utilize over the allotted percentage of throughput. + /// We will have default value of BackgroundTaskMaxAllowedThroughputPercent to be 10 percent if user has not explicitly set it. + /// This helps the background tasks to not starve and at the same time impact on user's workload will be minimal. + /// User can set the value in range (10,100]. + /// + /// + /// This option is only valid when creating a document collection. + /// + /// + /// The followng example shows how to create a collection with BackgroundTaskMaxAllowedThroughputPercent and throughput offer. + /// + /// + /// + /// + /// + /// + internal double? BackgroundTaskMaxAllowedThroughputPercent { get; set; } + + /// + /// Gets or sets the for the current request in the Azure Cosmos DB service. + /// + /// + /// + /// Partition key is used to identify the target partition for this request. It must be set on read and delete + /// operations for all document requests; create, read, update and delete operations for all document attachment requests; + /// and execute operation on stored producedures. + /// + /// For create and update operations on documents, the partition key is optional. When absent, the client library will + /// extract the partition key from the document before sending the request to the server. + /// + /// + /// + /// The following example shows how to read a document in a partitioned collection using . + /// The example assumes the collection is created with a of the 'id' property in all the documents. + /// + /// + /// + /// + /// + /// + public PartitionKey PartitionKey { get; set; } + + /// + /// Gets or sets the for the current request in the Azure Cosmos DB service. + /// + /// + /// + /// EnableScriptLogging is used to enable/disable logging in JavaScript stored procedures. + /// By default script logging is disabled. + /// The log can also be accessible in response header (x-ms-documentdb-script-log-results). + /// + /// + /// + /// The following example shows how to enable logging in stored procedures using . + /// + /// + /// + /// To log, use the following in store procedure: + /// + /// + /// + /// + /// + public bool EnableScriptLogging { get; set; } + + /// + /// Gets or sets for stored procedure execution requests in Azure Cosmos DB. + /// + /// + /// + /// IsReadOnlyScript indicates whether a script is read-only. Set this value to true only if the stored procedure contains + /// no create, update, or delete operations; otherwise, set this value to false. + /// Setting this value to true enables Azure Cosmos DB to optimize performance of read-only scripts. + /// + /// + internal bool IsReadOnlyScript { get; set; } + + /// + /// Gets or sets for snapshot read requests in Azure Cosmos DB. + /// + /// + /// + /// IncludeSnapshotDirectories is used to populate the snapshot content with storage SAS uris. + /// + /// + internal bool IncludeSnapshotDirectories { get; set; } + + /// + /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. + /// + /// + /// + /// PopulateQuotaInfo is used to enable/disable getting document collection quota related stats for document collection read requests. + /// + /// + public bool PopulateQuotaInfo { get; set; } + + /// + /// Gets or sets the for the current request in the Azure Cosmos DB service. + /// + /// + /// + /// DisableRUPerMinuteUsage is used to enable/disable Request Units(RUs)/minute capacity to serve the request if regular provisioned RUs/second is exhausted. + /// + /// + public bool DisableRUPerMinuteUsage { get; set; } + + /// + /// Gets or sets the for the current request used to deserialize the document. + /// If null, uses the default serializer settings set up in the DocumentClient. + /// + public JsonSerializerSettings JsonSerializerSettings { get; set; } + + /// + /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. + /// + /// + /// + /// is used to enable/disable getting partition key range statistics. + /// + /// + /// + /// For usage, please refer to the example in . + /// + public bool PopulatePartitionKeyRangeStatistics { get; set; } + + /// + /// Gets or sets the for document collection read unique index reindex progress. + /// + /// + /// + /// is used to enable/disable getting unique index reindex progress. + /// + /// + /// + /// For usage, please refer to the example in . + /// + internal bool PopulateUniqueIndexReIndexProgress { get; set; } + + /// + /// Gets or sets the for document collection read requests. + /// + /// + /// + /// is used to enable/disable getting analytical migration progress. + /// + /// + /// + /// For usage, please refer to the example in . + /// + internal bool PopulateAnalyticalMigrationProgress { get; set; } + + /// + /// Gets or sets the for document collection read requests. + /// + /// + /// + /// is used to enable/disable getting byok reencryption progress. + /// + /// + /// + /// For usage, please refer to the example in . + /// + internal bool PopulateBYOKEncryptionProgress { get; set; } + + /// + /// Gets or sets the Remote storage enablement + /// To be used along with Collection creation operation + /// + //internal RemoteStorageType RemoteStorageTypes { get; set; } + internal RemoteStorageType? RemoteStorageType { get; set; } + + /// + /// Gets or sets the partition key range id for the current request. + /// + /// + /// + /// Requests can use this to forward request to specific range. + /// This is useful in case of bulk export scenarios. + /// + /// + /// + /// The following example shows how to read a document feed in a partitioned collection from partition key range "20". + /// + /// + /// + /// + /// + internal string PartitionKeyRangeId { get; set; } + + /// + /// Gets or sets source databse from which to restore. + /// To be used along with RemoteStorageType, SourceCollectionId and RestorePointInTime + /// during Collection creation operation. + /// + internal string SourceDatabaseId { get; set; } + + /// + /// Gets or sets source collection from which to restore. + /// To be used along with RemoteStorageType, SourceDatabaseId and RestorePointInTime + /// during Collection creation operation. + /// + internal string SourceCollectionId { get; set; } + + /// + /// Gets or sets restore point-in-time. + /// To be used along with RemoteStorageType, SourceDatabaseId, SourceCollectionId + /// during Collection creation operation. + /// + internal long? RestorePointInTime { get; set; } + + /// + /// Gets or sets the for document collection read requests in the Azure Cosmos DB service. + /// + /// + /// + /// PopulateRestoreStatus is used to retreieve the status of a collection being restored. + /// + /// + internal bool PopulateRestoreStatus { get; set; } + + /// + /// Gets or sets the for document create requests in the Azure Cosmos DB service. + /// + /// + /// + /// PopulateCapacityType is used to return the capacity type of the request. + /// + /// + internal bool PopulateCapacityType { get; set; } + + /// + /// Gets or sets exclude system properties. + /// ExcludeSystemProperties indicates whether system properties + /// should be excluded from JSON content of a document or not. + /// + internal bool? ExcludeSystemProperties { get; set; } + + /// + /// Gets or sets the InsertSystemPartitionKey option + /// To be used along with Collection creation operation + /// + internal bool InsertSystemPartitionKey { get; set; } + + /// + /// Gets or sets the MergeStaticId + /// To be used along with Read operation when Static Column merge is desired. + /// + internal string MergeStaticId { get; set; } + + /// + /// PreserveFullContent is used to enable/disable getting document collection internal indexing properties. + /// which has information regarding the collection's logicalIndexVersion + /// + internal bool PreserveFullContent { get; set; } + + /// + /// ForceSideBySideIndexMigration is used to force a side by side index migration on a collection replace + /// + internal bool ForceSideBySideIndexMigration { get; set; } + + /// + /// Truncate the Collection + /// + internal bool CollectionTruncate { get; set; } + + /// + /// Represents client-side encryption + /// + internal bool IsClientEncrypted { get; set; } + + /// + /// Gets or sets the for document collection read requests. + /// + internal bool PopulateUserStrings { get; set; } + + /// + /// Gets or sets shared offer throughput on a collection. + /// + /// + /// This option is only valid when creating a document collection that shares offer throughput + /// provisioned at database level. Specifies maximum shared throughput available for collection + /// in the absence of contention. This value should be less than the throughput specified at + /// database level. + /// + /// + /// The followng example shows how to create a collection with offer throughtput. + /// + /// + /// + /// + [Obsolete("Deprecated")] + public int? SharedOfferThroughput { get; set; } + + /// + /// Gets or sets the priority level for the request in the Azure Cosmos DB service. + /// + /// + /// The priority level to use with a request. + /// + /// + /// + internal PriorityLevel? PriorityLevel { get; set; } + +#if !COSMOSCLIENT + /// + /// Gets or sets for a collection/database in the Azure Cosmos DB service + /// + /// + /// Valid values integers starting 1 + /// + /// + /// This option is only valid when creating a document collection or database. + /// + /// + /// The followng example shows how to create a collection with Autopilot Tier. + /// + /// + /// + /// + /// + /// + /// + internal int? OfferAutopilotTier { get; set; } + + /// + /// Gets or sets for a collection/database in the Azure Cosmos DB service + /// + /// + /// Valid values are true, false + /// + /// + /// This option is only valid when creating a document collection or database. + /// + /// + /// The followng example shows how to create a collection with Autopilot Tier and AutoUpgrade option. + /// + /// + /// + /// + /// + /// + /// + internal bool? OfferAutopilotAutoUpgrade { get; set; } + + /// + /// OfferAutopilotSettings is used to control how provisioned throughput for a container + /// or database automatically scales. + /// + /// + /// This option is only valid when creating a document collection or database. + /// + internal AutopilotSettings OfferAutopilotSettings { get; set; } +#endif + + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestRateTooLargeException.cs b/Microsoft.Azure.Cosmos/src/direct/RequestRateTooLargeException.cs index 4ce1eebcc9..33a40444c2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestRateTooLargeException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestRateTooLargeException.cs @@ -1,67 +1,67 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class RequestRateTooLargeException : DocumentClientException - { - public RequestRateTooLargeException() - : this(RMResources.TooManyRequests) - { - - } - - public RequestRateTooLargeException(string message) - : this(message, (Exception)null, null) - { - - } - - public RequestRateTooLargeException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public RequestRateTooLargeException(string message, SubStatusCodes subStatus) - : base(message, (HttpStatusCode)StatusCodes.TooManyRequests, subStatus) { } - - public RequestRateTooLargeException(Exception innerException) - : this(RMResources.TooManyRequests, innerException, null) - { - - } - - public RequestRateTooLargeException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, (HttpStatusCode)StatusCodes.TooManyRequests, requestUri) - { - SetDescription(); - } - - public RequestRateTooLargeException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) - : base(message, innerException, headers, (HttpStatusCode)StatusCodes.TooManyRequests, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private RequestRateTooLargeException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.TooManyRequests) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.TooManyRequests; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class RequestRateTooLargeException : DocumentClientException + { + public RequestRateTooLargeException() + : this(RMResources.TooManyRequests) + { + + } + + public RequestRateTooLargeException(string message) + : this(message, (Exception)null, null) + { + + } + + public RequestRateTooLargeException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public RequestRateTooLargeException(string message, SubStatusCodes subStatus) + : base(message, (HttpStatusCode)StatusCodes.TooManyRequests, subStatus) { } + + public RequestRateTooLargeException(Exception innerException) + : this(RMResources.TooManyRequests, innerException, null) + { + + } + + public RequestRateTooLargeException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, (HttpStatusCode)StatusCodes.TooManyRequests, requestUri) + { + SetDescription(); + } + + public RequestRateTooLargeException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null) + : base(message, innerException, headers, (HttpStatusCode)StatusCodes.TooManyRequests, requestUri) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private RequestRateTooLargeException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.TooManyRequests) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.TooManyRequests; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs b/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs index 92cdbfd7de..af664471d8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs @@ -1,169 +1,169 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Runtime.ExceptionServices; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal static class RequestRetryUtility - { - public static Task ProcessRequestAsync( - Func> executeAsync, - Func prepareRequest, - IRequestRetryPolicy policy, - CancellationToken cancellationToken) - { - return RequestRetryUtility.ProcessRequestAsync( - executeAsync: () => executeAsync(policy.ExecuteContext), - prepareRequest: prepareRequest, - policy: policy, - cancellationToken: cancellationToken - ); - } - - public static Task ProcessRequestAsync( - Func> executeAsync, - Func prepareRequest, - IRequestRetryPolicy policy, - Func> inBackoffAlternateCallbackMethod, - TimeSpan minBackoffForInBackoffCallback, - CancellationToken cancellationToken) - { - if (inBackoffAlternateCallbackMethod != null) - { - return RequestRetryUtility.ProcessRequestAsync( - executeAsync: () => executeAsync(policy.ExecuteContext), - prepareRequest: prepareRequest, - policy: policy, - cancellationToken: cancellationToken, - inBackoffAlternateCallbackMethod: () => inBackoffAlternateCallbackMethod(policy.ExecuteContext), - minBackoffForInBackoffCallback: minBackoffForInBackoffCallback - ); - } - - return RequestRetryUtility.ProcessRequestAsync( - executeAsync: () => executeAsync(policy.ExecuteContext), - prepareRequest: prepareRequest, - policy: policy, - cancellationToken: cancellationToken - ); - } - - public static async Task ProcessRequestAsync( - Func> executeAsync, - Func prepareRequest, - IRequestRetryPolicy policy, - CancellationToken cancellationToken, - Func> inBackoffAlternateCallbackMethod = null, - TimeSpan? minBackoffForInBackoffCallback = null) - { - while (true) - { - try - { - IRetriableResponse response = default(IRetriableResponse); - Exception exception = null; - ExceptionDispatchInfo capturedException = null; - TRequest request = default(TRequest); - cancellationToken.ThrowIfCancellationRequested(); - try - { - request = prepareRequest(); - policy.OnBeforeSendRequest(request); - - response = await executeAsync(); - } - catch (Exception ex) - { - // this Yield is to "reset" the stack to avoid stack overflows in Framework - // and to keep the total size of the StackTrace down if we fail - await Task.Yield(); - - capturedException = ExceptionDispatchInfo.Capture(ex); - exception = capturedException.SourceException; - } - - ShouldRetryResult shouldRetry = null; - Debug.Assert(response != null || exception != null); - if (!policy.TryHandleResponseSynchronously(request, response, exception, out shouldRetry)) - { - shouldRetry = await policy.ShouldRetryAsync(request, response, exception, cancellationToken); - } - - if (!shouldRetry.ShouldRetry) - { - if (capturedException != null || shouldRetry.ExceptionToThrow != null) - { - shouldRetry.ThrowIfDoneTrying(capturedException); - } - - return response; - } - - TimeSpan backoffTime = shouldRetry.BackoffTime; - if (inBackoffAlternateCallbackMethod != null && backoffTime >= minBackoffForInBackoffCallback.Value) - { - Stopwatch stopwatch = new Stopwatch(); - try - { - stopwatch.Start(); - IRetriableResponse inBackoffResponse = await inBackoffAlternateCallbackMethod(); - stopwatch.Stop(); - ShouldRetryResult shouldRetryInBackOff = null; - Debug.Assert(inBackoffResponse != null); - if (!policy.TryHandleResponseSynchronously( - request: request, - response: inBackoffResponse, - exception: null, - shouldRetryResult: out shouldRetryInBackOff)) - { - shouldRetryInBackOff = await policy.ShouldRetryAsync( - request: request, - response: inBackoffResponse, - exception: null, - cancellationToken: cancellationToken); - } - - if (!shouldRetryInBackOff.ShouldRetry) - { - return inBackoffResponse; - } - - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with response, proceeding with retry. Time taken: {0}ms", stopwatch.ElapsedMilliseconds); - } - catch (Exception ex) - { - stopwatch.Stop(); - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), stopwatch.ElapsedMilliseconds); - } - - backoffTime = shouldRetry.BackoffTime > stopwatch.Elapsed ? shouldRetry.BackoffTime - stopwatch.Elapsed : TimeSpan.Zero; - } - - if (backoffTime != TimeSpan.Zero) - { - await Task.Delay(backoffTime, cancellationToken); - } - - // if we're going to retry, force an additional async continuation so we don't have a gigantic - // stack built up by all these retries - await Task.Yield(); - } - catch - { - // if we're going to completely fail, we want to toss all the async continuation - // stack frames so we don't have a gigantic stack trace (which has serious performance - // implications) - await Task.Yield(); - - throw; - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Runtime.ExceptionServices; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal static class RequestRetryUtility + { + public static Task ProcessRequestAsync( + Func> executeAsync, + Func prepareRequest, + IRequestRetryPolicy policy, + CancellationToken cancellationToken) + { + return RequestRetryUtility.ProcessRequestAsync( + executeAsync: () => executeAsync(policy.ExecuteContext), + prepareRequest: prepareRequest, + policy: policy, + cancellationToken: cancellationToken + ); + } + + public static Task ProcessRequestAsync( + Func> executeAsync, + Func prepareRequest, + IRequestRetryPolicy policy, + Func> inBackoffAlternateCallbackMethod, + TimeSpan minBackoffForInBackoffCallback, + CancellationToken cancellationToken) + { + if (inBackoffAlternateCallbackMethod != null) + { + return RequestRetryUtility.ProcessRequestAsync( + executeAsync: () => executeAsync(policy.ExecuteContext), + prepareRequest: prepareRequest, + policy: policy, + cancellationToken: cancellationToken, + inBackoffAlternateCallbackMethod: () => inBackoffAlternateCallbackMethod(policy.ExecuteContext), + minBackoffForInBackoffCallback: minBackoffForInBackoffCallback + ); + } + + return RequestRetryUtility.ProcessRequestAsync( + executeAsync: () => executeAsync(policy.ExecuteContext), + prepareRequest: prepareRequest, + policy: policy, + cancellationToken: cancellationToken + ); + } + + public static async Task ProcessRequestAsync( + Func> executeAsync, + Func prepareRequest, + IRequestRetryPolicy policy, + CancellationToken cancellationToken, + Func> inBackoffAlternateCallbackMethod = null, + TimeSpan? minBackoffForInBackoffCallback = null) + { + while (true) + { + try + { + IRetriableResponse response = default(IRetriableResponse); + Exception exception = null; + ExceptionDispatchInfo capturedException = null; + TRequest request = default(TRequest); + cancellationToken.ThrowIfCancellationRequested(); + try + { + request = prepareRequest(); + policy.OnBeforeSendRequest(request); + + response = await executeAsync(); + } + catch (Exception ex) + { + // this Yield is to "reset" the stack to avoid stack overflows in Framework + // and to keep the total size of the StackTrace down if we fail + await Task.Yield(); + + capturedException = ExceptionDispatchInfo.Capture(ex); + exception = capturedException.SourceException; + } + + ShouldRetryResult shouldRetry = null; + Debug.Assert(response != null || exception != null); + if (!policy.TryHandleResponseSynchronously(request, response, exception, out shouldRetry)) + { + shouldRetry = await policy.ShouldRetryAsync(request, response, exception, cancellationToken); + } + + if (!shouldRetry.ShouldRetry) + { + if (capturedException != null || shouldRetry.ExceptionToThrow != null) + { + shouldRetry.ThrowIfDoneTrying(capturedException); + } + + return response; + } + + TimeSpan backoffTime = shouldRetry.BackoffTime; + if (inBackoffAlternateCallbackMethod != null && backoffTime >= minBackoffForInBackoffCallback.Value) + { + Stopwatch stopwatch = new Stopwatch(); + try + { + stopwatch.Start(); + IRetriableResponse inBackoffResponse = await inBackoffAlternateCallbackMethod(); + stopwatch.Stop(); + ShouldRetryResult shouldRetryInBackOff = null; + Debug.Assert(inBackoffResponse != null); + if (!policy.TryHandleResponseSynchronously( + request: request, + response: inBackoffResponse, + exception: null, + shouldRetryResult: out shouldRetryInBackOff)) + { + shouldRetryInBackOff = await policy.ShouldRetryAsync( + request: request, + response: inBackoffResponse, + exception: null, + cancellationToken: cancellationToken); + } + + if (!shouldRetryInBackOff.ShouldRetry) + { + return inBackoffResponse; + } + + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with response, proceeding with retry. Time taken: {0}ms", stopwatch.ElapsedMilliseconds); + } + catch (Exception ex) + { + stopwatch.Stop(); + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), stopwatch.ElapsedMilliseconds); + } + + backoffTime = shouldRetry.BackoffTime > stopwatch.Elapsed ? shouldRetry.BackoffTime - stopwatch.Elapsed : TimeSpan.Zero; + } + + if (backoffTime != TimeSpan.Zero) + { + await Task.Delay(backoffTime, cancellationToken); + } + + // if we're going to retry, force an additional async continuation so we don't have a gigantic + // stack built up by all these retries + await Task.Yield(); + } + catch + { + // if we're going to completely fail, we want to toss all the async continuation + // stack frames so we don't have a gigantic stack trace (which has serious performance + // implications) + await Task.Yield(); + + throw; + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestTimeoutException.cs b/Microsoft.Azure.Cosmos/src/direct/RequestTimeoutException.cs index 9055a012f7..ea28640fd7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestTimeoutException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestTimeoutException.cs @@ -1,104 +1,104 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class RequestTimeoutException : DocumentClientException - { - public RequestTimeoutException() - : this(RMResources.RequestTimeout) - { - - } - - public RequestTimeoutException(string message, Uri requestUri = null) - : this(message, null, null, requestUri) - { - - } - - public RequestTimeoutException(string message, Exception innerException, Uri requestUri = null) - : this(message, innerException, null, requestUri) - { - - } - - public RequestTimeoutException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public RequestTimeoutException(Exception innerException, Uri requestUri = null) - : this(RMResources.RequestTimeout, innerException, requestUri) - { - - } - - public RequestTimeoutException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.RequestTimeout, requestUri) - { - SetDescription(); - } - - public RequestTimeoutException(string message, Exception innerException, Uri requestUri = null, string localIpAddress = null) - : this(message, innerException, (HttpResponseHeaders)null, requestUri) - { - this.LocalIp = localIpAddress; - } - - - public RequestTimeoutException(string message, - Exception innerException, - HttpResponseHeaders headers, - Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.RequestTimeout, requestUri) - { - SetDescription(); - } - - /// - /// - /// Summary: - /// Gets a message that describes the current exception. - /// - /// - public override string Message - { - get - { - if (!string.IsNullOrEmpty(this.LocalIp)) - { - return string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessageAddIpAddress, - base.Message, - this.LocalIp); - } - return base.Message; - } - } - - internal string LocalIp { get; set; } - -#if !NETSTANDARD16 - private RequestTimeoutException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.RequestTimeout) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.RequestTimeout; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class RequestTimeoutException : DocumentClientException + { + public RequestTimeoutException() + : this(RMResources.RequestTimeout) + { + + } + + public RequestTimeoutException(string message, Uri requestUri = null) + : this(message, null, null, requestUri) + { + + } + + public RequestTimeoutException(string message, Exception innerException, Uri requestUri = null) + : this(message, innerException, null, requestUri) + { + + } + + public RequestTimeoutException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public RequestTimeoutException(Exception innerException, Uri requestUri = null) + : this(RMResources.RequestTimeout, innerException, requestUri) + { + + } + + public RequestTimeoutException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.RequestTimeout, requestUri) + { + SetDescription(); + } + + public RequestTimeoutException(string message, Exception innerException, Uri requestUri = null, string localIpAddress = null) + : this(message, innerException, (HttpResponseHeaders)null, requestUri) + { + this.LocalIp = localIpAddress; + } + + + public RequestTimeoutException(string message, + Exception innerException, + HttpResponseHeaders headers, + Uri requestUri = null) + : base(message, innerException, headers, HttpStatusCode.RequestTimeout, requestUri) + { + SetDescription(); + } + + /// + /// + /// Summary: + /// Gets a message that describes the current exception. + /// + /// + public override string Message + { + get + { + if (!string.IsNullOrEmpty(this.LocalIp)) + { + return string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessageAddIpAddress, + base.Message, + this.LocalIp); + } + return base.Message; + } + } + + internal string LocalIp { get; set; } + +#if !NETSTANDARD16 + private RequestTimeoutException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.RequestTimeout) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.RequestTimeout; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestedCollectionType.cs b/Microsoft.Azure.Cosmos/src/direct/RequestedCollectionType.cs index 247a6fea93..19f90eb7ba 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestedCollectionType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestedCollectionType.cs @@ -1,12 +1,12 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal enum RequestedCollectionType - { - All, - Standard, - MaterializedView - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal enum RequestedCollectionType + { + All, + Standard, + MaterializedView + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Resource.cs b/Microsoft.Azure.Cosmos/src/direct/Resource.cs index 04aea3d554..f04a71c0ee 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Resource.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Resource.cs @@ -1,223 +1,223 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.IO; - using Newtonsoft.Json; - - /// - /// Represents an abstract resource type in the Azure Cosmos DB service. - /// All Azure Cosmos DB resources, such as , , and extend this abstract type. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - abstract class Resource : JsonSerializable - { - internal static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - protected Resource() - { - - } - - /// - /// Copy constructor for a used in the Azure Cosmos DB service. - /// - protected Resource(Resource resource) - { - this.Id = resource.Id; - this.ResourceId = resource.ResourceId; - this.SelfLink = resource.SelfLink; - this.AltLink = resource.AltLink; - this.Timestamp = resource.Timestamp; - this.ETag = resource.ETag; - } - - - /// - /// Gets or sets the Id of the resource in the Azure Cosmos DB service. - /// - /// The Id associated with the resource. - /// - /// - /// Every resource within an Azure Cosmos DB database account needs to have a unique identifier. - /// Unlike , which is set internally, this Id is settable by the user and is not immutable. - /// - /// - /// When working with document resources, they too have this settable Id property. - /// If an Id is not supplied by the user the SDK will automatically generate a new GUID and assign its value to this property before - /// persisting the document in the database. - /// You can override this auto Id generation by setting the disableAutomaticIdGeneration parameter on the instance to true. - /// This will prevent the SDK from generating new Ids. - /// - /// - /// The following characters are restricted and cannot be used in the Id property: - /// '/', '\\', '?', '#' - /// - /// - [JsonProperty(PropertyName = Constants.Properties.Id)] - public virtual string Id - { - get - { - return this.GetValue(Constants.Properties.Id); - } - set - { - this.SetValue(Constants.Properties.Id, value); - } - } - - /// - /// Gets or sets the Resource Id associated with the resource in the Azure Cosmos DB service. - /// - /// - /// The Resource Id associated with the resource. - /// - /// - /// A Resource Id is the unique, immutable, identifier assigned to each Azure Cosmos DB - /// resource whether that is a database, a collection or a document. - /// These resource ids are used when building up SelfLinks, a static addressable Uri for each resource within a database account. - /// - [JsonProperty(PropertyName = Constants.Properties.RId)] - public virtual string ResourceId - { - get - { - return this.GetValue(Constants.Properties.RId); - } - set - { - this.SetValue(Constants.Properties.RId, value); - } - } - - /// - /// Gets the self-link associated with the resource from the Azure Cosmos DB service. - /// - /// The self-link associated with the resource. - /// - /// A self-link is a static addressable Uri for each resource within a database account and follows the Azure Cosmos DB resource model. - /// E.g. a self-link for a document could be dbs/db_resourceid/colls/coll_resourceid/documents/doc_resourceid - /// - [JsonProperty(PropertyName = Constants.Properties.SelfLink)] - public string SelfLink - { - get - { - return this.GetValue(Constants.Properties.SelfLink); - } - internal set - { - this.SetValue(Constants.Properties.SelfLink, value); - } - } - - /// - /// Gets the alt-link associated with the resource from the Azure Cosmos DB service. - /// - /// The alt-link associated with the resource. - [JsonIgnore] - public string AltLink - { - get; - set; - } - - /// - /// Gets the last modified timestamp associated with the resource from the Azure Cosmos DB service. - /// - /// The last modified timestamp associated with the resource. - [JsonProperty(PropertyName = Constants.Properties.LastModified)] - [JsonConverter(typeof(UnixDateTimeConverter))] - public virtual DateTime Timestamp - { - get - { - // Add seconds to the unix start time - return UnixStartTime.AddSeconds(this.GetValue(Constants.Properties.LastModified)); - } - internal set - { - this.SetValue(Constants.Properties.LastModified, (ulong)(value - UnixStartTime).TotalSeconds); - } - } - - /// - /// Gets the entity tag associated with the resource from the Azure Cosmos DB service. - /// - /// - /// The entity tag associated with the resource. - /// - /// - /// ETags are used for concurrency checking when updating resources. - /// - [JsonProperty(PropertyName = Constants.Properties.ETag)] - public string ETag - { - get - { - return this.GetValue(Constants.Properties.ETag); - } - internal set - { - this.SetValue(Constants.Properties.ETag, value); - } - } - - /// - /// Sets property value associated with the specified property name in the Azure Cosmos DB service. - /// - /// The name of the property. - /// The property value. - public void SetPropertyValue(string propertyName, object propertyValue) - { - base.SetValue(propertyName, propertyValue); - } - - /// - /// Gets property value associated with the specified property name from the Azure Cosmos DB service. - /// - /// The type of the property. - /// The name of the property. - /// The property value. - public T GetPropertyValue(string propertyName) - { - return base.GetValue(propertyName); - } - - /// - /// Validates the property, by calling it, in case of any errors exception is thrown - /// - internal override void Validate() - { - base.Validate(); - this.GetValue(Constants.Properties.Id); - this.GetValue(Constants.Properties.RId); - this.GetValue(Constants.Properties.SelfLink); - this.GetValue(Constants.Properties.LastModified); - this.GetValue(Constants.Properties.ETag); - } - - /// - /// Serialize to a byte array via SaveTo for the Azure Cosmos DB service. - /// - public byte[] ToByteArray() - { - using (MemoryStream ms = new MemoryStream()) - { - this.SaveTo(ms); - return ms.ToArray(); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.IO; + using Newtonsoft.Json; + + /// + /// Represents an abstract resource type in the Azure Cosmos DB service. + /// All Azure Cosmos DB resources, such as , , and extend this abstract type. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + abstract class Resource : JsonSerializable + { + internal static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + protected Resource() + { + + } + + /// + /// Copy constructor for a used in the Azure Cosmos DB service. + /// + protected Resource(Resource resource) + { + this.Id = resource.Id; + this.ResourceId = resource.ResourceId; + this.SelfLink = resource.SelfLink; + this.AltLink = resource.AltLink; + this.Timestamp = resource.Timestamp; + this.ETag = resource.ETag; + } + + + /// + /// Gets or sets the Id of the resource in the Azure Cosmos DB service. + /// + /// The Id associated with the resource. + /// + /// + /// Every resource within an Azure Cosmos DB database account needs to have a unique identifier. + /// Unlike , which is set internally, this Id is settable by the user and is not immutable. + /// + /// + /// When working with document resources, they too have this settable Id property. + /// If an Id is not supplied by the user the SDK will automatically generate a new GUID and assign its value to this property before + /// persisting the document in the database. + /// You can override this auto Id generation by setting the disableAutomaticIdGeneration parameter on the instance to true. + /// This will prevent the SDK from generating new Ids. + /// + /// + /// The following characters are restricted and cannot be used in the Id property: + /// '/', '\\', '?', '#' + /// + /// + [JsonProperty(PropertyName = Constants.Properties.Id)] + public virtual string Id + { + get + { + return this.GetValue(Constants.Properties.Id); + } + set + { + this.SetValue(Constants.Properties.Id, value); + } + } + + /// + /// Gets or sets the Resource Id associated with the resource in the Azure Cosmos DB service. + /// + /// + /// The Resource Id associated with the resource. + /// + /// + /// A Resource Id is the unique, immutable, identifier assigned to each Azure Cosmos DB + /// resource whether that is a database, a collection or a document. + /// These resource ids are used when building up SelfLinks, a static addressable Uri for each resource within a database account. + /// + [JsonProperty(PropertyName = Constants.Properties.RId)] + public virtual string ResourceId + { + get + { + return this.GetValue(Constants.Properties.RId); + } + set + { + this.SetValue(Constants.Properties.RId, value); + } + } + + /// + /// Gets the self-link associated with the resource from the Azure Cosmos DB service. + /// + /// The self-link associated with the resource. + /// + /// A self-link is a static addressable Uri for each resource within a database account and follows the Azure Cosmos DB resource model. + /// E.g. a self-link for a document could be dbs/db_resourceid/colls/coll_resourceid/documents/doc_resourceid + /// + [JsonProperty(PropertyName = Constants.Properties.SelfLink)] + public string SelfLink + { + get + { + return this.GetValue(Constants.Properties.SelfLink); + } + internal set + { + this.SetValue(Constants.Properties.SelfLink, value); + } + } + + /// + /// Gets the alt-link associated with the resource from the Azure Cosmos DB service. + /// + /// The alt-link associated with the resource. + [JsonIgnore] + public string AltLink + { + get; + set; + } + + /// + /// Gets the last modified timestamp associated with the resource from the Azure Cosmos DB service. + /// + /// The last modified timestamp associated with the resource. + [JsonProperty(PropertyName = Constants.Properties.LastModified)] + [JsonConverter(typeof(UnixDateTimeConverter))] + public virtual DateTime Timestamp + { + get + { + // Add seconds to the unix start time + return UnixStartTime.AddSeconds(this.GetValue(Constants.Properties.LastModified)); + } + internal set + { + this.SetValue(Constants.Properties.LastModified, (ulong)(value - UnixStartTime).TotalSeconds); + } + } + + /// + /// Gets the entity tag associated with the resource from the Azure Cosmos DB service. + /// + /// + /// The entity tag associated with the resource. + /// + /// + /// ETags are used for concurrency checking when updating resources. + /// + [JsonProperty(PropertyName = Constants.Properties.ETag)] + public string ETag + { + get + { + return this.GetValue(Constants.Properties.ETag); + } + internal set + { + this.SetValue(Constants.Properties.ETag, value); + } + } + + /// + /// Sets property value associated with the specified property name in the Azure Cosmos DB service. + /// + /// The name of the property. + /// The property value. + public void SetPropertyValue(string propertyName, object propertyValue) + { + base.SetValue(propertyName, propertyValue); + } + + /// + /// Gets property value associated with the specified property name from the Azure Cosmos DB service. + /// + /// The type of the property. + /// The name of the property. + /// The property value. + public T GetPropertyValue(string propertyName) + { + return base.GetValue(propertyName); + } + + /// + /// Validates the property, by calling it, in case of any errors exception is thrown + /// + internal override void Validate() + { + base.Validate(); + this.GetValue(Constants.Properties.Id); + this.GetValue(Constants.Properties.RId); + this.GetValue(Constants.Properties.SelfLink); + this.GetValue(Constants.Properties.LastModified); + this.GetValue(Constants.Properties.ETag); + } + + /// + /// Serialize to a byte array via SaveTo for the Azure Cosmos DB service. + /// + public byte[] ToByteArray() + { + using (MemoryStream ms = new MemoryStream()) + { + this.SaveTo(ms); + return ms.ToArray(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceId.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceId.cs index 2f5c6f2b57..94f68d5f45 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceId.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceId.cs @@ -1,1292 +1,1292 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Linq; - using System.Text; - using Microsoft.Azure.Cosmos.Core.Trace; - - //Resource ID is 20 byte number. It is not a guid. - //First 4 bytes for DB id -> 2^32 DBs per tenant --> uint - // Next 4 bytes for coll id OR user id -> 2^31 coll/users per DB. the first bit indicates if this is a collection or a user --> uint - // Next 8 bytes for doc id OR permission or sproc/trigger/function or conflicts -> 2^64 permission per user. Note that the disambiguation between collection - // based resources (document/sproc/trigger/function/conflict) and user based resource i.e. permission is based on ownerid. --> ulong - // Disambiguation between document/sproc/conflict is based upon first 4 bits of the highest byte. 0x00 is document, 0x08 is sproc, 0x07 is - // trigger, 0x06 is function and 0x04 is conflict. 2^60 document/sproc/trigger/function/conflict per collection. - // Last 4 bytes for attachment id -> 2^32 attachments per "Document". These bits are used only for document's children. Permission/Sproc/ - // Conflict RID hierarchy is only 16 bytes. - - internal sealed class ResourceId : IEquatable - { - private const int EncryptionScopeIdLength = 5; - private const int OfferIdLength = 3; - private const int RbacResourceIdLength = 6; - private const int SnapshotIdLength = 7; - public static readonly ushort Length = 20; - public static readonly ushort MaxPathFragment = 8; // for public resource - public static readonly ResourceId Empty = new ResourceId(); - - private ResourceId() - { - this.Offer = 0; - this.Database = 0; - this.DocumentCollection = 0; - this.ClientEncryptionKey = 0; - this.StoredProcedure = 0; - this.Trigger = 0; - this.UserDefinedFunction = 0; - this.Document = 0; - this.PartitionKeyRange = 0; - this.User = 0; - this.ClientEncryptionKey = 0; - this.Permission = 0; - this.Attachment = 0; - this.Schema = 0; - this.UserDefinedType = 0; - this.Snapshot = 0; - this.RoleAssignment = 0; - this.RoleDefinition = 0; - this.SystemDocument = 0; - this.PartitionedSystemDocument = 0; - this.EncryptionScope = 0; - } - - public uint Offer - { - get; - private set; - } - - public ResourceId OfferId - { - get - { - ResourceId rid = new ResourceId(); - rid.Offer = this.Offer; - return rid; - } - } - - public uint Database - { - get; - private set; - } - - public ResourceId DatabaseId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - return rid; - } - } - - public bool IsDatabaseId - { - get - { - return this.Database != 0 && (this.DocumentCollection == 0 && this.User == 0 && this.UserDefinedType == 0 && this.ClientEncryptionKey == 0); - } - } - - public bool IsDocumentCollectionId - { - get - { - return this.Database != 0 && this.DocumentCollection != 0 - && (this.Document == 0 && this.PartitionKeyRange == 0 && this.StoredProcedure == 0 && this.Trigger == 0 && this.UserDefinedFunction == 0 - && this.SystemDocument == 0 && this.PartitionedSystemDocument == 0); - } - } - - public bool IsPartitionKeyRangeId - { - get - { - return this.Database != 0 && this.DocumentCollection != 0 && this.PartitionKeyRange != 0 - && (this.Document == 0 && this.StoredProcedure == 0 && this.Trigger == 0 && this.UserDefinedFunction == 0 - && this.SystemDocument == 0 && this.PartitionedSystemDocument == 0); - } - } - - public uint DocumentCollection - { - get; - private set; - } - - public ResourceId DocumentCollectionId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - return rid; - } - } - - public bool IsClientEncryptionKeyId - { - get - { - return (this.Database != 0 && this.ClientEncryptionKey != 0); - } - } - - /// - /// Unique (across all databases) Id for the DocumentCollection. - /// First 4 bytes are DatabaseId and next 4 bytes are CollectionId. - /// - public UInt64 UniqueDocumentCollectionId - { - get - { - return (UInt64)this.Database << 32 | this.DocumentCollection; - } - } - - public UInt64 StoredProcedure - { - get; - private set; - } - - public ResourceId StoredProcedureId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.StoredProcedure = this.StoredProcedure; - return rid; - } - } - - public UInt64 Trigger - { - get; - private set; - } - - public ResourceId TriggerId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.Trigger = this.Trigger; - return rid; - } - } - - public UInt64 UserDefinedFunction - { - get; - private set; - } - - public ResourceId UserDefinedFunctionId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.UserDefinedFunction = this.UserDefinedFunction; - return rid; - } - } - - public UInt64 Conflict - { - get; - private set; - } - - public ResourceId ConflictId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.Conflict = this.Conflict; - return rid; - } - } - - public ulong Document - { - get; - private set; - } - - public ResourceId DocumentId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.Document = this.Document; - return rid; - } - } - - public ulong PartitionKeyRange - { - get; - private set; - } - - public ResourceId PartitionKeyRangeId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.PartitionKeyRange = this.PartitionKeyRange; - return rid; - } - } - - public uint User - { - get; - private set; - } - - public ResourceId UserId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.User = this.User; - return rid; - } - } - - public uint ClientEncryptionKey - { - get; - private set; - } - - - public ResourceId ClientEncryptionKeyId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.ClientEncryptionKey = this.ClientEncryptionKey; - return rid; - } - } - - public uint UserDefinedType - { - get; - private set; - } - - - public ResourceId UserDefinedTypeId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.UserDefinedType = this.UserDefinedType; - return rid; - } - } - - public ulong Permission - { - get; - private set; - } - - - public ResourceId PermissionId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.User = this.User; - rid.Permission = this.Permission; - return rid; - } - } - - public uint Attachment - { - get; - private set; - } - - public ResourceId AttachmentId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.Document = this.Document; - rid.Attachment = this.Attachment; - return rid; - } - } - - public ulong Schema - { - get; - private set; - } - - - public ResourceId SchemaId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.Schema = this.Schema; - return rid; - } - } - - public ulong Snapshot - { - get; - private set; - } - - public ResourceId SnapshotId - { - get - { - ResourceId rid = new ResourceId(); - rid.Snapshot = this.Snapshot; - return rid; - } - } - - public bool IsSnapshotId - { - get - { - return this.Snapshot != 0; - } - } - - public ulong EncryptionScope - { - get; - private set; - } - - public ResourceId EncryptionScopeId - { - get - { - ResourceId rid = new ResourceId(); - rid.EncryptionScope = this.EncryptionScope; - return rid; - } - } - - public bool IsEncryptionScopeId - { - get - { - return this.EncryptionScope != 0; - } - } - - public ulong RoleAssignment - { - get; - private set; - } - - public ResourceId RoleAssignmentId - { - get - { - ResourceId rid = new ResourceId(); - rid.RoleAssignment = this.RoleAssignment; - return rid; - } - } - - public bool IsRoleAssignmentId - { - get - { - return this.RoleAssignment != 0; - } - } - - public ulong RoleDefinition - { - get; - private set; - } - - public ResourceId RoleDefinitionId - { - get - { - ResourceId rid = new ResourceId(); - rid.RoleDefinition = this.RoleDefinition; - return rid; - } - } - - public bool IsRoleDefinitionId - { - get - { - return this.RoleDefinition != 0; - } - } - - public ulong AuthPolicyElement - { - get; - private set; - } - - public ResourceId AuthPolicyElementId - { - get - { - ResourceId rid = new ResourceId(); - rid.AuthPolicyElement = this.AuthPolicyElement; - return rid; - } - } - - public bool IsAuthPolicyElementId - { - get - { - return this.AuthPolicyElement != 0; - } - } - - public UInt64 SystemDocument - { - get; - private set; - } - - public ResourceId SystemDocumentId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.SystemDocument = this.SystemDocument; - return rid; - } - } - - public UInt64 PartitionedSystemDocument - { - get; - private set; - } - - public ResourceId PartitionedSystemDocumentId - { - get - { - ResourceId rid = new ResourceId(); - rid.Database = this.Database; - rid.DocumentCollection = this.DocumentCollection; - rid.PartitionedSystemDocument = this.PartitionedSystemDocument; - return rid; - } - } - - public ulong InteropUser - { - get; - private set; - } - - public ResourceId InteropUserId - { - get - { - ResourceId rid = new ResourceId(); - rid.InteropUser = this.InteropUser; - return rid; - } - } - - public bool IsInteropUserId - { - get - { - return this.InteropUser != 0; - } - } - - public byte[] Value - { - get - { - int len = 0; - if (this.Offer > 0) - len += ResourceId.OfferIdLength; - else if (this.Snapshot > 0) - len += ResourceId.SnapshotIdLength; - else if (this.EncryptionScope > 0) - len += ResourceId.EncryptionScopeIdLength; - else if (this.RoleAssignment > 0) - len += ResourceId.RbacResourceIdLength; - else if (this.RoleDefinition > 0) - len += ResourceId.RbacResourceIdLength; - else if (this.AuthPolicyElement > 0) - len += ResourceId.RbacResourceIdLength; - else if (this.InteropUser > 0) - len += ResourceId.RbacResourceIdLength; - else if (this.Database > 0) - len += 4; - if (this.DocumentCollection > 0 || this.User > 0 || this.UserDefinedType > 0 || this.ClientEncryptionKey > 0) - len += 4; - if (this.Document > 0 || this.Permission > 0 || this.StoredProcedure > 0 || this.Trigger > 0 - || this.UserDefinedFunction > 0 || this.Conflict > 0 || this.PartitionKeyRange > 0 || this.Schema > 0 - || this.UserDefinedType > 0 || this.ClientEncryptionKey > 0 || this.SystemDocument > 0 - || this.PartitionedSystemDocument > 0) - len += 8; - if (this.Attachment > 0) - len += 4; - - byte[] val = new byte[len]; - - if (this.Offer > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Offer), 0, val, 0, ResourceId.OfferIdLength); - else if (this.Database > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Database), 0, val, 0, 4); - else if (this.Snapshot > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Snapshot), 0, val, 0, ResourceId.SnapshotIdLength); - else if (this.EncryptionScope > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.EncryptionScope), 0, val, 0, ResourceId.EncryptionScopeIdLength); - else if (this.AuthPolicyElement > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.AuthPolicyElement), 0, val, 0, 4); - ResourceId.BlockCopy(BitConverter.GetBytes(0x3000), 0, val, 4, 2); - } - else if (this.RoleAssignment > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.RoleAssignment), 0, val, 0, 4); - ResourceId.BlockCopy(BitConverter.GetBytes(0x1000), 0, val, 4, 2); - } - else if (this.RoleDefinition > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.RoleDefinition), 0, val, 0, ResourceId.RbacResourceIdLength); - } - else if (this.InteropUser > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.InteropUser), 0, val, 0, ResourceId.RbacResourceIdLength); - ResourceId.BlockCopy(BitConverter.GetBytes(0x2000), 0, val, 4, 2); - } - - if (this.DocumentCollection > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.DocumentCollection), 0, val, 4, 4); - else if (this.User > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.User), 0, val, 4, 4); - - if (this.StoredProcedure > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.StoredProcedure), 0, val, 8, 8); - else if (this.Trigger > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Trigger), 0, val, 8, 8); - else if (this.UserDefinedFunction > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.UserDefinedFunction), 0, val, 8, 8); - else if (this.Conflict > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Conflict), 0, val, 8, 8); - else if (this.Document > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Document), 0, val, 8, 8); - else if (this.PartitionKeyRange > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.PartitionKeyRange), 0, val, 8, 8); - else if (this.Permission > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Permission), 0, val, 8, 8); - else if(this.Schema > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Schema), 0, val, 8, 8); - else if (this.SystemDocument > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.SystemDocument), 0, val, 8, 8); - else if (this.PartitionedSystemDocument > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.PartitionedSystemDocument), 0, val, 8, 8); - else if (this.UserDefinedType > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.UserDefinedType), 0, val, 8, 4); - ResourceId.BlockCopy(BitConverter.GetBytes((uint)ExtendedDatabaseChildResourceType.UserDefinedType), 0, val, 12, 4); - } - else if(this.ClientEncryptionKey > 0) - { - ResourceId.BlockCopy(BitConverter.GetBytes(this.ClientEncryptionKey), 0, val, 8, 4); - ResourceId.BlockCopy(BitConverter.GetBytes((uint)ExtendedDatabaseChildResourceType.ClientEncryptionKey), 0, val, 12, 4); - } - - if (this.Attachment > 0) - ResourceId.BlockCopy(BitConverter.GetBytes(this.Attachment), 0, val, 16, 4); - - return val; - } - } - - public static ResourceId Parse(string id) - { - ResourceId rid = null; - - bool parsed = ResourceId.TryParse(id, out rid); - - if (!parsed) - throw new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceID, id)); - - return rid; - } - - public static byte[] Parse(ResourceType eResourceType, string id) - { - if (ResourceId.HasNonHierarchicalResourceId(eResourceType)) - { - return Encoding.UTF8.GetBytes(id); - } - - return ResourceId.Parse(id).Value; - } - - public static ResourceId NewDatabaseId(uint dbid) - { - ResourceId resourceId = new ResourceId(); - resourceId.Database = dbid; - return resourceId; - } - - public static ResourceId NewRoleDefinitionId(ulong roleDefinitionId) - { - return new ResourceId() - { - RoleDefinition = roleDefinitionId - }; - } - - public static ResourceId NewRoleAssignmentId(ulong roleAssignmentId) - { - return new ResourceId() - { - RoleAssignment = roleAssignmentId - }; - } - - public static ResourceId NewAuthPolicyElementId(ulong authPolicyElementId) - { - return new ResourceId() - { - AuthPolicyElement = authPolicyElementId - }; - } - - public static ResourceId NewSnapshotId(ulong snapshotId) - { - return new ResourceId() - { - Snapshot = snapshotId - }; - } - - public static ResourceId NewEncryptionScopeId(ulong encryptionScopeId) - { - return new ResourceId() - { - EncryptionScope = encryptionScopeId - }; - } - - public static ResourceId NewInteropUserId(ulong interopUserId) - { - return new ResourceId() - { - InteropUser = interopUserId - }; - } - - public static ResourceId NewDocumentCollectionId(string databaseId, uint collectionId) - { - ResourceId dbId = ResourceId.Parse(databaseId); - - return ResourceId.NewDocumentCollectionId(dbId.Database, collectionId); - } - - public static ResourceId NewDocumentCollectionId(uint databaseId, uint collectionId) - { - ResourceId collectionResourceId = new ResourceId(); - collectionResourceId.Database = databaseId; - collectionResourceId.DocumentCollection = collectionId; - - return collectionResourceId; - } - - public static ResourceId NewClientEncryptionKeyId(string databaseId, uint clientEncryptionKeyId) - { - ResourceId dbId = ResourceId.Parse(databaseId); - - return ResourceId.NewClientEncryptionKeyId(dbId.Database, clientEncryptionKeyId); - } - - public static ResourceId NewClientEncryptionKeyId(uint databaseId, uint clientEncryptionKeyId) - { - ResourceId clientEncryptionKeyResourceId = new ResourceId(); - clientEncryptionKeyResourceId.Database = databaseId; - clientEncryptionKeyResourceId.ClientEncryptionKey = clientEncryptionKeyId; - - return clientEncryptionKeyResourceId; - } - - public static ResourceId NewCollectionChildResourceId(string collectionId, ulong childId, ResourceType resourceType) - { - ResourceId collId = ResourceId.Parse(collectionId); - - if(!collId.IsDocumentCollectionId) - { - string errorMessage = string.Format(CultureInfo.InvariantCulture, "Invalid collection RID '{0}'.", collectionId); - DefaultTrace.TraceError(errorMessage); - throw new ArgumentException(errorMessage); - } - - ResourceId childResourceId = new ResourceId(); - childResourceId.Database = collId.Database; - childResourceId.DocumentCollection = collId.DocumentCollection; - - switch (resourceType) - { - case ResourceType.StoredProcedure: - childResourceId.StoredProcedure = childId; - return childResourceId; - - case ResourceType.Trigger: - childResourceId.Trigger = childId; - return childResourceId; - - case ResourceType.UserDefinedFunction: - childResourceId.UserDefinedFunction = childId; - return childResourceId; - - case ResourceType.PartitionKeyRange: - childResourceId.PartitionKeyRange = childId; - return childResourceId; - - case ResourceType.Document: - childResourceId.Document = childId; - return childResourceId; - - case ResourceType.SystemDocument: - childResourceId.SystemDocument = childId; - return childResourceId; - - case ResourceType.PartitionedSystemDocument: - childResourceId.PartitionedSystemDocument = childId; - return childResourceId; - - default: - string errorMessage = string.Format(CultureInfo.InvariantCulture, "ResourceType '{0}' not a child of Collection.", resourceType); - DefaultTrace.TraceError(errorMessage); - throw new ArgumentException(errorMessage); - } - } - - public static ResourceId NewUserId(string databaseId, uint userId) - { - ResourceId dbId = ResourceId.Parse(databaseId); - - ResourceId userResourceId = new ResourceId(); - userResourceId.Database = dbId.Database; - userResourceId.User = userId; - - return userResourceId; - } - - public static ResourceId NewPermissionId(string userId, ulong permissionId) - { - ResourceId usrId = ResourceId.Parse(userId); - - ResourceId permissionResourceId = new ResourceId(); - permissionResourceId.Database = usrId.Database; - permissionResourceId.User = usrId.User; - permissionResourceId.Permission = permissionId; - return permissionResourceId; - } - - public static ResourceId NewAttachmentId(string documentId, uint attachmentId) - { - ResourceId docId = ResourceId.Parse(documentId); - - ResourceId attachmentResourceId = new ResourceId(); - attachmentResourceId.Database = docId.Database; - attachmentResourceId.DocumentCollection = docId.DocumentCollection; - attachmentResourceId.Document = docId.Document; - attachmentResourceId.Attachment = attachmentId; - - return attachmentResourceId; - } - - public static string CreateNewCollectionChildResourceId(int childResourceIdIndex, ResourceType resourceType, string ownerResourceId) - { - byte[] subCollRes = new byte[8]; - switch (resourceType) - { - case ResourceType.PartitionKeyRange: - subCollRes[7] = (byte)CollectionChildResourceType.PartitionKeyRange << 4; - break; - - case ResourceType.UserDefinedFunction: - subCollRes[7] = (byte)CollectionChildResourceType.UserDefinedFunction << 4; - break; - - case ResourceType.Trigger: - subCollRes[7] = (byte)CollectionChildResourceType.Trigger << 4; - break; - - case ResourceType.StoredProcedure: - subCollRes[7] = (byte)CollectionChildResourceType.StoredProcedure << 4; - break; - - case ResourceType.Document: - subCollRes[7] = (byte)CollectionChildResourceType.Document << 4; - break; - - case ResourceType.SystemDocument: - subCollRes[7] = (byte)CollectionChildResourceType.SystemDocument << 4; - break; - - case ResourceType.PartitionedSystemDocument: - subCollRes[7] = (byte)CollectionChildResourceType.PartitionedSystemDocument << 4; - break; - - default: - string errorMessage = string.Format(CultureInfo.InvariantCulture, "Invalid resource for CreateNewCollectionChildResourceId: '{0}'.", resourceType); - DefaultTrace.TraceError(errorMessage); - throw new ArgumentException(errorMessage); - } - - byte[] childResourceIdIndexAsBytes = BitConverter.GetBytes(childResourceIdIndex); - - if(childResourceIdIndexAsBytes.Length > 6) - { - throw new BadRequestException("ChildResourceIdIndex size is too big to be used as resource id."); - } - - for (int i = 0; i < childResourceIdIndexAsBytes.Length; i++) - { - subCollRes[i] = childResourceIdIndexAsBytes[i]; - } - - int startIndex = 0; - ulong childResourceKey = BitConverter.ToUInt64(subCollRes, startIndex); - - string childResourceId = ResourceId.NewCollectionChildResourceId(ownerResourceId, childResourceKey, resourceType).ToString(); - - return childResourceId; - } - - public static bool TryParse(string id, out ResourceId rid) - { - rid = null; - - try - { - if (string.IsNullOrEmpty(id)) - return false; - - if (id.Length % 4 != 0) - { - // our resourceId string is always padded - return false; - } - - byte[] buffer = null; - - if (ResourceId.Verify(id, out buffer) == false) - return false; - - if (buffer.Length % 4 != 0 && - buffer.Length != ResourceId.OfferIdLength && - buffer.Length != ResourceId.SnapshotIdLength && - buffer.Length != ResourceId.RbacResourceIdLength && - buffer.Length != ResourceId.EncryptionScopeIdLength) - { - return false; - } - - rid = new ResourceId(); - - if (buffer.Length == ResourceId.OfferIdLength) - { - rid.Offer = (uint)ResourceId.ToUnsignedLong(buffer); - return true; - } - - if (buffer.Length == ResourceId.SnapshotIdLength) - { - rid.Snapshot = ResourceId.ToUnsignedLong(buffer); - return true; - } - - if (buffer.Length == ResourceId.RbacResourceIdLength) - { - byte rbacResourceType = buffer[ResourceId.RbacResourceIdLength - 1]; - ulong rbacResourceId = ResourceId.ToUnsignedLong(buffer, 4); - - switch((RbacResourceType)rbacResourceType) - { - case RbacResourceType.RbacResourceType_RoleDefinition: - rid.RoleDefinition = rbacResourceId; - break; - - case RbacResourceType.RbacResourceType_RoleAssignment: - rid.RoleAssignment = rbacResourceId; - break; - - case RbacResourceType.RbacResourceType_AuthPolicyElement: - rid.AuthPolicyElement = rbacResourceId; - break; - - case RbacResourceType.RbacResourceType_InteropUser: - rid.InteropUser = rbacResourceId; - break; - - default: - return false; - } - - return true; - } - - if (buffer.Length == ResourceId.EncryptionScopeIdLength) - { - rid.EncryptionScope = (uint)ResourceId.ToUnsignedLong(buffer); - return true; - } - - if (buffer.Length >= 4) - rid.Database = BitConverter.ToUInt32(buffer, 0); - - if (buffer.Length >= 8) - { - byte[] temp = new byte[4]; - ResourceId.BlockCopy(buffer, 4, temp, 0, 4); - - bool isCollection = (temp[0] & (128)) > 0 ? true : false; - - if (isCollection) - { - rid.DocumentCollection = BitConverter.ToUInt32(temp, 0); - - if (buffer.Length >= 16) - { - byte[] subCollRes = new byte[8]; - ResourceId.BlockCopy(buffer, 8, subCollRes, 0, 8); - - UInt64 subCollectionResource = BitConverter.ToUInt64(buffer, 8); - if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Document) - { - rid.Document = subCollectionResource; - - if (buffer.Length == 20) - { - rid.Attachment = BitConverter.ToUInt32(buffer, 16); - } - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.StoredProcedure) - { - rid.StoredProcedure = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Trigger) - { - rid.Trigger = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.UserDefinedFunction) - { - rid.UserDefinedFunction = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Conflict) - { - rid.Conflict = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.PartitionKeyRange) - { - rid.PartitionKeyRange = subCollectionResource; - } - else if((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Schema) - { - rid.Schema = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.SystemDocument) - { - rid.SystemDocument = subCollectionResource; - } - else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.PartitionedSystemDocument) - { - rid.PartitionedSystemDocument = subCollectionResource; - } - else - { - return false; - } - } - else if (buffer.Length != 8) - { - return false; - } - } - else - { - rid.User = BitConverter.ToUInt32(temp, 0); - - if (buffer.Length == 16) - { - if (rid.User > 0) - { - rid.Permission = BitConverter.ToUInt64(buffer, 8); - } - else - { - uint exDatabaseChildResourceId = BitConverter.ToUInt32(buffer, 8); - ExtendedDatabaseChildResourceType exDatabaseChildResType = (ExtendedDatabaseChildResourceType)BitConverter.ToUInt32(buffer, 12); - - if (exDatabaseChildResType == ExtendedDatabaseChildResourceType.UserDefinedType) - { - rid.UserDefinedType = exDatabaseChildResourceId; - } - else if(exDatabaseChildResType == ExtendedDatabaseChildResourceType.ClientEncryptionKey) - { - rid.ClientEncryptionKey = exDatabaseChildResourceId; - } - else - { - return false; - } - } - } - else if (buffer.Length != 8) - { - return false; - } - } - } - - return true; - } - catch (Exception) - { - return false; - } - } - - public static bool Verify(string id, out byte[] buffer) - { - if (string.IsNullOrEmpty(id)) - throw new ArgumentNullException("id"); - - if (ResourceId.TryDecodeFromBase64String(id, out buffer) == false || buffer.Length > ResourceId.Length) - { - buffer = null; - return false; - } - - return true; - } - - public static bool Verify(string id) - { - byte[] buffer = null; - return Verify(id, out buffer); - } - - public override string ToString() - { - return ResourceId.ToBase64String(this.Value); - } - - public bool Equals(ResourceId other) - { - if (other == null) - { - return false; - } - - return Enumerable.SequenceEqual(this.Value, other.Value); - } - - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) - { - return false; - } - if (ReferenceEquals(this, obj)) - { - return true; - } - return obj is ResourceId && this.Equals((ResourceId)obj); - } - - public override int GetHashCode() - { - throw new NotImplementedException(); - } - - public static bool TryDecodeFromBase64String(string s, out byte[] bytes) - { - return ResourceIdBase64Decoder.TryDecode(s.Replace('-', '/'), out bytes); - } - - public static ulong ToUnsignedLong(byte[] buffer) - { - return ResourceId.ToUnsignedLong(buffer, buffer.Length); - } - - public static ulong ToUnsignedLong(byte[] buffer, int length) - { - ulong value = 0; - - for (int index = 0; index < length; index++) - { - value |= (uint)(buffer[index] << (index * 8)); - } - - return value; - } - - public static string ToBase64String(byte[] buffer) - { - return ResourceId.ToBase64String(buffer, 0, buffer.Length); - } - - public static string ToBase64String(byte[] buffer, int offset, int length) - { - return Convert.ToBase64String(buffer, offset, length).Replace('/', '-'); - } - - #region Private unused, here for conceptual purpose - private static ResourceId NewDocumentId(uint dbId, uint collId) - { - ResourceId rid = new ResourceId(); - - rid.Database = dbId; - rid.DocumentCollection = collId; - - byte[] guidBytes = Guid.NewGuid().ToByteArray(); - rid.Document = BitConverter.ToUInt64(guidBytes, 0); - - return rid; - } - - private static ResourceId NewDocumentCollectionId(uint dbId) - { - ResourceId rid = new ResourceId(); - - rid.Database = dbId; - - byte[] temp = new byte[4]; - byte[] guidBytes = Guid.NewGuid().ToByteArray(); - - //collection has the first bit set - guidBytes[0] |= 128; - - ResourceId.BlockCopy(guidBytes, 0, temp, 0, 4); - - rid.DocumentCollection = BitConverter.ToUInt32(temp, 0); - - rid.Document = 0; - rid.User = 0; - rid.Permission = 0; - - return rid; - } - - private static ResourceId NewDatabaseId() - { - ResourceId rid = new ResourceId(); - - byte[] guidBytes = Guid.NewGuid().ToByteArray(); - rid.Database = BitConverter.ToUInt32(guidBytes, 0); - - rid.DocumentCollection = 0; - rid.Document = 0; - rid.User = 0; - rid.Permission = 0; - - return rid; - } - #endregion - - // Copy the bytes provided with a for loop, faster when there are only a few bytes to copy - public static void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count) - { - int stop = srcOffset + count; - for (int i = srcOffset; i < stop; i++) - dst[dstOffset++] = src[i]; - } - - private static bool HasNonHierarchicalResourceId(ResourceType eResourceType) - { -#if !COSMOSCLIENT - return eResourceType == ResourceType.MasterPartition || - eResourceType == ResourceType.ServerPartition || - eResourceType == ResourceType.RidRange; -#else - return false; -#endif - } - - // Using a byte however, we only need nibble here. - private enum CollectionChildResourceType : byte - { - Document = 0x00, - StoredProcedure = 0x08, - Trigger = 0x07, - UserDefinedFunction = 0x06, - Conflict = 0x04, - PartitionKeyRange = 0x05, - Schema = 0x09, - PartitionedSystemDocument = 0x0A, - SystemDocument = 0x0D - } - - private enum ExtendedDatabaseChildResourceType - { - UserDefinedType = 0x01, - ClientEncryptionKey = 0x02 - } - - internal enum RbacResourceType : byte - { - RbacResourceType_RoleDefinition = 0x00, - RbacResourceType_RoleAssignment = 0x10, - RbacResourceType_InteropUser = 0x20, - RbacResourceType_AuthPolicyElement = 0x30, - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Linq; + using System.Text; + using Microsoft.Azure.Cosmos.Core.Trace; + + //Resource ID is 20 byte number. It is not a guid. + //First 4 bytes for DB id -> 2^32 DBs per tenant --> uint + // Next 4 bytes for coll id OR user id -> 2^31 coll/users per DB. the first bit indicates if this is a collection or a user --> uint + // Next 8 bytes for doc id OR permission or sproc/trigger/function or conflicts -> 2^64 permission per user. Note that the disambiguation between collection + // based resources (document/sproc/trigger/function/conflict) and user based resource i.e. permission is based on ownerid. --> ulong + // Disambiguation between document/sproc/conflict is based upon first 4 bits of the highest byte. 0x00 is document, 0x08 is sproc, 0x07 is + // trigger, 0x06 is function and 0x04 is conflict. 2^60 document/sproc/trigger/function/conflict per collection. + // Last 4 bytes for attachment id -> 2^32 attachments per "Document". These bits are used only for document's children. Permission/Sproc/ + // Conflict RID hierarchy is only 16 bytes. + + internal sealed class ResourceId : IEquatable + { + private const int EncryptionScopeIdLength = 5; + private const int OfferIdLength = 3; + private const int RbacResourceIdLength = 6; + private const int SnapshotIdLength = 7; + public static readonly ushort Length = 20; + public static readonly ushort MaxPathFragment = 8; // for public resource + public static readonly ResourceId Empty = new ResourceId(); + + private ResourceId() + { + this.Offer = 0; + this.Database = 0; + this.DocumentCollection = 0; + this.ClientEncryptionKey = 0; + this.StoredProcedure = 0; + this.Trigger = 0; + this.UserDefinedFunction = 0; + this.Document = 0; + this.PartitionKeyRange = 0; + this.User = 0; + this.ClientEncryptionKey = 0; + this.Permission = 0; + this.Attachment = 0; + this.Schema = 0; + this.UserDefinedType = 0; + this.Snapshot = 0; + this.RoleAssignment = 0; + this.RoleDefinition = 0; + this.SystemDocument = 0; + this.PartitionedSystemDocument = 0; + this.EncryptionScope = 0; + } + + public uint Offer + { + get; + private set; + } + + public ResourceId OfferId + { + get + { + ResourceId rid = new ResourceId(); + rid.Offer = this.Offer; + return rid; + } + } + + public uint Database + { + get; + private set; + } + + public ResourceId DatabaseId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + return rid; + } + } + + public bool IsDatabaseId + { + get + { + return this.Database != 0 && (this.DocumentCollection == 0 && this.User == 0 && this.UserDefinedType == 0 && this.ClientEncryptionKey == 0); + } + } + + public bool IsDocumentCollectionId + { + get + { + return this.Database != 0 && this.DocumentCollection != 0 + && (this.Document == 0 && this.PartitionKeyRange == 0 && this.StoredProcedure == 0 && this.Trigger == 0 && this.UserDefinedFunction == 0 + && this.SystemDocument == 0 && this.PartitionedSystemDocument == 0); + } + } + + public bool IsPartitionKeyRangeId + { + get + { + return this.Database != 0 && this.DocumentCollection != 0 && this.PartitionKeyRange != 0 + && (this.Document == 0 && this.StoredProcedure == 0 && this.Trigger == 0 && this.UserDefinedFunction == 0 + && this.SystemDocument == 0 && this.PartitionedSystemDocument == 0); + } + } + + public uint DocumentCollection + { + get; + private set; + } + + public ResourceId DocumentCollectionId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + return rid; + } + } + + public bool IsClientEncryptionKeyId + { + get + { + return (this.Database != 0 && this.ClientEncryptionKey != 0); + } + } + + /// + /// Unique (across all databases) Id for the DocumentCollection. + /// First 4 bytes are DatabaseId and next 4 bytes are CollectionId. + /// + public UInt64 UniqueDocumentCollectionId + { + get + { + return (UInt64)this.Database << 32 | this.DocumentCollection; + } + } + + public UInt64 StoredProcedure + { + get; + private set; + } + + public ResourceId StoredProcedureId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.StoredProcedure = this.StoredProcedure; + return rid; + } + } + + public UInt64 Trigger + { + get; + private set; + } + + public ResourceId TriggerId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.Trigger = this.Trigger; + return rid; + } + } + + public UInt64 UserDefinedFunction + { + get; + private set; + } + + public ResourceId UserDefinedFunctionId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.UserDefinedFunction = this.UserDefinedFunction; + return rid; + } + } + + public UInt64 Conflict + { + get; + private set; + } + + public ResourceId ConflictId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.Conflict = this.Conflict; + return rid; + } + } + + public ulong Document + { + get; + private set; + } + + public ResourceId DocumentId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.Document = this.Document; + return rid; + } + } + + public ulong PartitionKeyRange + { + get; + private set; + } + + public ResourceId PartitionKeyRangeId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.PartitionKeyRange = this.PartitionKeyRange; + return rid; + } + } + + public uint User + { + get; + private set; + } + + public ResourceId UserId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.User = this.User; + return rid; + } + } + + public uint ClientEncryptionKey + { + get; + private set; + } + + + public ResourceId ClientEncryptionKeyId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.ClientEncryptionKey = this.ClientEncryptionKey; + return rid; + } + } + + public uint UserDefinedType + { + get; + private set; + } + + + public ResourceId UserDefinedTypeId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.UserDefinedType = this.UserDefinedType; + return rid; + } + } + + public ulong Permission + { + get; + private set; + } + + + public ResourceId PermissionId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.User = this.User; + rid.Permission = this.Permission; + return rid; + } + } + + public uint Attachment + { + get; + private set; + } + + public ResourceId AttachmentId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.Document = this.Document; + rid.Attachment = this.Attachment; + return rid; + } + } + + public ulong Schema + { + get; + private set; + } + + + public ResourceId SchemaId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.Schema = this.Schema; + return rid; + } + } + + public ulong Snapshot + { + get; + private set; + } + + public ResourceId SnapshotId + { + get + { + ResourceId rid = new ResourceId(); + rid.Snapshot = this.Snapshot; + return rid; + } + } + + public bool IsSnapshotId + { + get + { + return this.Snapshot != 0; + } + } + + public ulong EncryptionScope + { + get; + private set; + } + + public ResourceId EncryptionScopeId + { + get + { + ResourceId rid = new ResourceId(); + rid.EncryptionScope = this.EncryptionScope; + return rid; + } + } + + public bool IsEncryptionScopeId + { + get + { + return this.EncryptionScope != 0; + } + } + + public ulong RoleAssignment + { + get; + private set; + } + + public ResourceId RoleAssignmentId + { + get + { + ResourceId rid = new ResourceId(); + rid.RoleAssignment = this.RoleAssignment; + return rid; + } + } + + public bool IsRoleAssignmentId + { + get + { + return this.RoleAssignment != 0; + } + } + + public ulong RoleDefinition + { + get; + private set; + } + + public ResourceId RoleDefinitionId + { + get + { + ResourceId rid = new ResourceId(); + rid.RoleDefinition = this.RoleDefinition; + return rid; + } + } + + public bool IsRoleDefinitionId + { + get + { + return this.RoleDefinition != 0; + } + } + + public ulong AuthPolicyElement + { + get; + private set; + } + + public ResourceId AuthPolicyElementId + { + get + { + ResourceId rid = new ResourceId(); + rid.AuthPolicyElement = this.AuthPolicyElement; + return rid; + } + } + + public bool IsAuthPolicyElementId + { + get + { + return this.AuthPolicyElement != 0; + } + } + + public UInt64 SystemDocument + { + get; + private set; + } + + public ResourceId SystemDocumentId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.SystemDocument = this.SystemDocument; + return rid; + } + } + + public UInt64 PartitionedSystemDocument + { + get; + private set; + } + + public ResourceId PartitionedSystemDocumentId + { + get + { + ResourceId rid = new ResourceId(); + rid.Database = this.Database; + rid.DocumentCollection = this.DocumentCollection; + rid.PartitionedSystemDocument = this.PartitionedSystemDocument; + return rid; + } + } + + public ulong InteropUser + { + get; + private set; + } + + public ResourceId InteropUserId + { + get + { + ResourceId rid = new ResourceId(); + rid.InteropUser = this.InteropUser; + return rid; + } + } + + public bool IsInteropUserId + { + get + { + return this.InteropUser != 0; + } + } + + public byte[] Value + { + get + { + int len = 0; + if (this.Offer > 0) + len += ResourceId.OfferIdLength; + else if (this.Snapshot > 0) + len += ResourceId.SnapshotIdLength; + else if (this.EncryptionScope > 0) + len += ResourceId.EncryptionScopeIdLength; + else if (this.RoleAssignment > 0) + len += ResourceId.RbacResourceIdLength; + else if (this.RoleDefinition > 0) + len += ResourceId.RbacResourceIdLength; + else if (this.AuthPolicyElement > 0) + len += ResourceId.RbacResourceIdLength; + else if (this.InteropUser > 0) + len += ResourceId.RbacResourceIdLength; + else if (this.Database > 0) + len += 4; + if (this.DocumentCollection > 0 || this.User > 0 || this.UserDefinedType > 0 || this.ClientEncryptionKey > 0) + len += 4; + if (this.Document > 0 || this.Permission > 0 || this.StoredProcedure > 0 || this.Trigger > 0 + || this.UserDefinedFunction > 0 || this.Conflict > 0 || this.PartitionKeyRange > 0 || this.Schema > 0 + || this.UserDefinedType > 0 || this.ClientEncryptionKey > 0 || this.SystemDocument > 0 + || this.PartitionedSystemDocument > 0) + len += 8; + if (this.Attachment > 0) + len += 4; + + byte[] val = new byte[len]; + + if (this.Offer > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Offer), 0, val, 0, ResourceId.OfferIdLength); + else if (this.Database > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Database), 0, val, 0, 4); + else if (this.Snapshot > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Snapshot), 0, val, 0, ResourceId.SnapshotIdLength); + else if (this.EncryptionScope > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.EncryptionScope), 0, val, 0, ResourceId.EncryptionScopeIdLength); + else if (this.AuthPolicyElement > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.AuthPolicyElement), 0, val, 0, 4); + ResourceId.BlockCopy(BitConverter.GetBytes(0x3000), 0, val, 4, 2); + } + else if (this.RoleAssignment > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.RoleAssignment), 0, val, 0, 4); + ResourceId.BlockCopy(BitConverter.GetBytes(0x1000), 0, val, 4, 2); + } + else if (this.RoleDefinition > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.RoleDefinition), 0, val, 0, ResourceId.RbacResourceIdLength); + } + else if (this.InteropUser > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.InteropUser), 0, val, 0, ResourceId.RbacResourceIdLength); + ResourceId.BlockCopy(BitConverter.GetBytes(0x2000), 0, val, 4, 2); + } + + if (this.DocumentCollection > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.DocumentCollection), 0, val, 4, 4); + else if (this.User > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.User), 0, val, 4, 4); + + if (this.StoredProcedure > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.StoredProcedure), 0, val, 8, 8); + else if (this.Trigger > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Trigger), 0, val, 8, 8); + else if (this.UserDefinedFunction > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.UserDefinedFunction), 0, val, 8, 8); + else if (this.Conflict > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Conflict), 0, val, 8, 8); + else if (this.Document > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Document), 0, val, 8, 8); + else if (this.PartitionKeyRange > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.PartitionKeyRange), 0, val, 8, 8); + else if (this.Permission > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Permission), 0, val, 8, 8); + else if(this.Schema > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Schema), 0, val, 8, 8); + else if (this.SystemDocument > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.SystemDocument), 0, val, 8, 8); + else if (this.PartitionedSystemDocument > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.PartitionedSystemDocument), 0, val, 8, 8); + else if (this.UserDefinedType > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.UserDefinedType), 0, val, 8, 4); + ResourceId.BlockCopy(BitConverter.GetBytes((uint)ExtendedDatabaseChildResourceType.UserDefinedType), 0, val, 12, 4); + } + else if(this.ClientEncryptionKey > 0) + { + ResourceId.BlockCopy(BitConverter.GetBytes(this.ClientEncryptionKey), 0, val, 8, 4); + ResourceId.BlockCopy(BitConverter.GetBytes((uint)ExtendedDatabaseChildResourceType.ClientEncryptionKey), 0, val, 12, 4); + } + + if (this.Attachment > 0) + ResourceId.BlockCopy(BitConverter.GetBytes(this.Attachment), 0, val, 16, 4); + + return val; + } + } + + public static ResourceId Parse(string id) + { + ResourceId rid = null; + + bool parsed = ResourceId.TryParse(id, out rid); + + if (!parsed) + throw new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResourceID, id)); + + return rid; + } + + public static byte[] Parse(ResourceType eResourceType, string id) + { + if (ResourceId.HasNonHierarchicalResourceId(eResourceType)) + { + return Encoding.UTF8.GetBytes(id); + } + + return ResourceId.Parse(id).Value; + } + + public static ResourceId NewDatabaseId(uint dbid) + { + ResourceId resourceId = new ResourceId(); + resourceId.Database = dbid; + return resourceId; + } + + public static ResourceId NewRoleDefinitionId(ulong roleDefinitionId) + { + return new ResourceId() + { + RoleDefinition = roleDefinitionId + }; + } + + public static ResourceId NewRoleAssignmentId(ulong roleAssignmentId) + { + return new ResourceId() + { + RoleAssignment = roleAssignmentId + }; + } + + public static ResourceId NewAuthPolicyElementId(ulong authPolicyElementId) + { + return new ResourceId() + { + AuthPolicyElement = authPolicyElementId + }; + } + + public static ResourceId NewSnapshotId(ulong snapshotId) + { + return new ResourceId() + { + Snapshot = snapshotId + }; + } + + public static ResourceId NewEncryptionScopeId(ulong encryptionScopeId) + { + return new ResourceId() + { + EncryptionScope = encryptionScopeId + }; + } + + public static ResourceId NewInteropUserId(ulong interopUserId) + { + return new ResourceId() + { + InteropUser = interopUserId + }; + } + + public static ResourceId NewDocumentCollectionId(string databaseId, uint collectionId) + { + ResourceId dbId = ResourceId.Parse(databaseId); + + return ResourceId.NewDocumentCollectionId(dbId.Database, collectionId); + } + + public static ResourceId NewDocumentCollectionId(uint databaseId, uint collectionId) + { + ResourceId collectionResourceId = new ResourceId(); + collectionResourceId.Database = databaseId; + collectionResourceId.DocumentCollection = collectionId; + + return collectionResourceId; + } + + public static ResourceId NewClientEncryptionKeyId(string databaseId, uint clientEncryptionKeyId) + { + ResourceId dbId = ResourceId.Parse(databaseId); + + return ResourceId.NewClientEncryptionKeyId(dbId.Database, clientEncryptionKeyId); + } + + public static ResourceId NewClientEncryptionKeyId(uint databaseId, uint clientEncryptionKeyId) + { + ResourceId clientEncryptionKeyResourceId = new ResourceId(); + clientEncryptionKeyResourceId.Database = databaseId; + clientEncryptionKeyResourceId.ClientEncryptionKey = clientEncryptionKeyId; + + return clientEncryptionKeyResourceId; + } + + public static ResourceId NewCollectionChildResourceId(string collectionId, ulong childId, ResourceType resourceType) + { + ResourceId collId = ResourceId.Parse(collectionId); + + if(!collId.IsDocumentCollectionId) + { + string errorMessage = string.Format(CultureInfo.InvariantCulture, "Invalid collection RID '{0}'.", collectionId); + DefaultTrace.TraceError(errorMessage); + throw new ArgumentException(errorMessage); + } + + ResourceId childResourceId = new ResourceId(); + childResourceId.Database = collId.Database; + childResourceId.DocumentCollection = collId.DocumentCollection; + + switch (resourceType) + { + case ResourceType.StoredProcedure: + childResourceId.StoredProcedure = childId; + return childResourceId; + + case ResourceType.Trigger: + childResourceId.Trigger = childId; + return childResourceId; + + case ResourceType.UserDefinedFunction: + childResourceId.UserDefinedFunction = childId; + return childResourceId; + + case ResourceType.PartitionKeyRange: + childResourceId.PartitionKeyRange = childId; + return childResourceId; + + case ResourceType.Document: + childResourceId.Document = childId; + return childResourceId; + + case ResourceType.SystemDocument: + childResourceId.SystemDocument = childId; + return childResourceId; + + case ResourceType.PartitionedSystemDocument: + childResourceId.PartitionedSystemDocument = childId; + return childResourceId; + + default: + string errorMessage = string.Format(CultureInfo.InvariantCulture, "ResourceType '{0}' not a child of Collection.", resourceType); + DefaultTrace.TraceError(errorMessage); + throw new ArgumentException(errorMessage); + } + } + + public static ResourceId NewUserId(string databaseId, uint userId) + { + ResourceId dbId = ResourceId.Parse(databaseId); + + ResourceId userResourceId = new ResourceId(); + userResourceId.Database = dbId.Database; + userResourceId.User = userId; + + return userResourceId; + } + + public static ResourceId NewPermissionId(string userId, ulong permissionId) + { + ResourceId usrId = ResourceId.Parse(userId); + + ResourceId permissionResourceId = new ResourceId(); + permissionResourceId.Database = usrId.Database; + permissionResourceId.User = usrId.User; + permissionResourceId.Permission = permissionId; + return permissionResourceId; + } + + public static ResourceId NewAttachmentId(string documentId, uint attachmentId) + { + ResourceId docId = ResourceId.Parse(documentId); + + ResourceId attachmentResourceId = new ResourceId(); + attachmentResourceId.Database = docId.Database; + attachmentResourceId.DocumentCollection = docId.DocumentCollection; + attachmentResourceId.Document = docId.Document; + attachmentResourceId.Attachment = attachmentId; + + return attachmentResourceId; + } + + public static string CreateNewCollectionChildResourceId(int childResourceIdIndex, ResourceType resourceType, string ownerResourceId) + { + byte[] subCollRes = new byte[8]; + switch (resourceType) + { + case ResourceType.PartitionKeyRange: + subCollRes[7] = (byte)CollectionChildResourceType.PartitionKeyRange << 4; + break; + + case ResourceType.UserDefinedFunction: + subCollRes[7] = (byte)CollectionChildResourceType.UserDefinedFunction << 4; + break; + + case ResourceType.Trigger: + subCollRes[7] = (byte)CollectionChildResourceType.Trigger << 4; + break; + + case ResourceType.StoredProcedure: + subCollRes[7] = (byte)CollectionChildResourceType.StoredProcedure << 4; + break; + + case ResourceType.Document: + subCollRes[7] = (byte)CollectionChildResourceType.Document << 4; + break; + + case ResourceType.SystemDocument: + subCollRes[7] = (byte)CollectionChildResourceType.SystemDocument << 4; + break; + + case ResourceType.PartitionedSystemDocument: + subCollRes[7] = (byte)CollectionChildResourceType.PartitionedSystemDocument << 4; + break; + + default: + string errorMessage = string.Format(CultureInfo.InvariantCulture, "Invalid resource for CreateNewCollectionChildResourceId: '{0}'.", resourceType); + DefaultTrace.TraceError(errorMessage); + throw new ArgumentException(errorMessage); + } + + byte[] childResourceIdIndexAsBytes = BitConverter.GetBytes(childResourceIdIndex); + + if(childResourceIdIndexAsBytes.Length > 6) + { + throw new BadRequestException("ChildResourceIdIndex size is too big to be used as resource id."); + } + + for (int i = 0; i < childResourceIdIndexAsBytes.Length; i++) + { + subCollRes[i] = childResourceIdIndexAsBytes[i]; + } + + int startIndex = 0; + ulong childResourceKey = BitConverter.ToUInt64(subCollRes, startIndex); + + string childResourceId = ResourceId.NewCollectionChildResourceId(ownerResourceId, childResourceKey, resourceType).ToString(); + + return childResourceId; + } + + public static bool TryParse(string id, out ResourceId rid) + { + rid = null; + + try + { + if (string.IsNullOrEmpty(id)) + return false; + + if (id.Length % 4 != 0) + { + // our resourceId string is always padded + return false; + } + + byte[] buffer = null; + + if (ResourceId.Verify(id, out buffer) == false) + return false; + + if (buffer.Length % 4 != 0 && + buffer.Length != ResourceId.OfferIdLength && + buffer.Length != ResourceId.SnapshotIdLength && + buffer.Length != ResourceId.RbacResourceIdLength && + buffer.Length != ResourceId.EncryptionScopeIdLength) + { + return false; + } + + rid = new ResourceId(); + + if (buffer.Length == ResourceId.OfferIdLength) + { + rid.Offer = (uint)ResourceId.ToUnsignedLong(buffer); + return true; + } + + if (buffer.Length == ResourceId.SnapshotIdLength) + { + rid.Snapshot = ResourceId.ToUnsignedLong(buffer); + return true; + } + + if (buffer.Length == ResourceId.RbacResourceIdLength) + { + byte rbacResourceType = buffer[ResourceId.RbacResourceIdLength - 1]; + ulong rbacResourceId = ResourceId.ToUnsignedLong(buffer, 4); + + switch((RbacResourceType)rbacResourceType) + { + case RbacResourceType.RbacResourceType_RoleDefinition: + rid.RoleDefinition = rbacResourceId; + break; + + case RbacResourceType.RbacResourceType_RoleAssignment: + rid.RoleAssignment = rbacResourceId; + break; + + case RbacResourceType.RbacResourceType_AuthPolicyElement: + rid.AuthPolicyElement = rbacResourceId; + break; + + case RbacResourceType.RbacResourceType_InteropUser: + rid.InteropUser = rbacResourceId; + break; + + default: + return false; + } + + return true; + } + + if (buffer.Length == ResourceId.EncryptionScopeIdLength) + { + rid.EncryptionScope = (uint)ResourceId.ToUnsignedLong(buffer); + return true; + } + + if (buffer.Length >= 4) + rid.Database = BitConverter.ToUInt32(buffer, 0); + + if (buffer.Length >= 8) + { + byte[] temp = new byte[4]; + ResourceId.BlockCopy(buffer, 4, temp, 0, 4); + + bool isCollection = (temp[0] & (128)) > 0 ? true : false; + + if (isCollection) + { + rid.DocumentCollection = BitConverter.ToUInt32(temp, 0); + + if (buffer.Length >= 16) + { + byte[] subCollRes = new byte[8]; + ResourceId.BlockCopy(buffer, 8, subCollRes, 0, 8); + + UInt64 subCollectionResource = BitConverter.ToUInt64(buffer, 8); + if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Document) + { + rid.Document = subCollectionResource; + + if (buffer.Length == 20) + { + rid.Attachment = BitConverter.ToUInt32(buffer, 16); + } + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.StoredProcedure) + { + rid.StoredProcedure = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Trigger) + { + rid.Trigger = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.UserDefinedFunction) + { + rid.UserDefinedFunction = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Conflict) + { + rid.Conflict = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.PartitionKeyRange) + { + rid.PartitionKeyRange = subCollectionResource; + } + else if((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.Schema) + { + rid.Schema = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.SystemDocument) + { + rid.SystemDocument = subCollectionResource; + } + else if ((subCollRes[7] >> 4) == (byte)CollectionChildResourceType.PartitionedSystemDocument) + { + rid.PartitionedSystemDocument = subCollectionResource; + } + else + { + return false; + } + } + else if (buffer.Length != 8) + { + return false; + } + } + else + { + rid.User = BitConverter.ToUInt32(temp, 0); + + if (buffer.Length == 16) + { + if (rid.User > 0) + { + rid.Permission = BitConverter.ToUInt64(buffer, 8); + } + else + { + uint exDatabaseChildResourceId = BitConverter.ToUInt32(buffer, 8); + ExtendedDatabaseChildResourceType exDatabaseChildResType = (ExtendedDatabaseChildResourceType)BitConverter.ToUInt32(buffer, 12); + + if (exDatabaseChildResType == ExtendedDatabaseChildResourceType.UserDefinedType) + { + rid.UserDefinedType = exDatabaseChildResourceId; + } + else if(exDatabaseChildResType == ExtendedDatabaseChildResourceType.ClientEncryptionKey) + { + rid.ClientEncryptionKey = exDatabaseChildResourceId; + } + else + { + return false; + } + } + } + else if (buffer.Length != 8) + { + return false; + } + } + } + + return true; + } + catch (Exception) + { + return false; + } + } + + public static bool Verify(string id, out byte[] buffer) + { + if (string.IsNullOrEmpty(id)) + throw new ArgumentNullException("id"); + + if (ResourceId.TryDecodeFromBase64String(id, out buffer) == false || buffer.Length > ResourceId.Length) + { + buffer = null; + return false; + } + + return true; + } + + public static bool Verify(string id) + { + byte[] buffer = null; + return Verify(id, out buffer); + } + + public override string ToString() + { + return ResourceId.ToBase64String(this.Value); + } + + public bool Equals(ResourceId other) + { + if (other == null) + { + return false; + } + + return Enumerable.SequenceEqual(this.Value, other.Value); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + if (ReferenceEquals(this, obj)) + { + return true; + } + return obj is ResourceId && this.Equals((ResourceId)obj); + } + + public override int GetHashCode() + { + throw new NotImplementedException(); + } + + public static bool TryDecodeFromBase64String(string s, out byte[] bytes) + { + return ResourceIdBase64Decoder.TryDecode(s.Replace('-', '/'), out bytes); + } + + public static ulong ToUnsignedLong(byte[] buffer) + { + return ResourceId.ToUnsignedLong(buffer, buffer.Length); + } + + public static ulong ToUnsignedLong(byte[] buffer, int length) + { + ulong value = 0; + + for (int index = 0; index < length; index++) + { + value |= (uint)(buffer[index] << (index * 8)); + } + + return value; + } + + public static string ToBase64String(byte[] buffer) + { + return ResourceId.ToBase64String(buffer, 0, buffer.Length); + } + + public static string ToBase64String(byte[] buffer, int offset, int length) + { + return Convert.ToBase64String(buffer, offset, length).Replace('/', '-'); + } + + #region Private unused, here for conceptual purpose + private static ResourceId NewDocumentId(uint dbId, uint collId) + { + ResourceId rid = new ResourceId(); + + rid.Database = dbId; + rid.DocumentCollection = collId; + + byte[] guidBytes = Guid.NewGuid().ToByteArray(); + rid.Document = BitConverter.ToUInt64(guidBytes, 0); + + return rid; + } + + private static ResourceId NewDocumentCollectionId(uint dbId) + { + ResourceId rid = new ResourceId(); + + rid.Database = dbId; + + byte[] temp = new byte[4]; + byte[] guidBytes = Guid.NewGuid().ToByteArray(); + + //collection has the first bit set + guidBytes[0] |= 128; + + ResourceId.BlockCopy(guidBytes, 0, temp, 0, 4); + + rid.DocumentCollection = BitConverter.ToUInt32(temp, 0); + + rid.Document = 0; + rid.User = 0; + rid.Permission = 0; + + return rid; + } + + private static ResourceId NewDatabaseId() + { + ResourceId rid = new ResourceId(); + + byte[] guidBytes = Guid.NewGuid().ToByteArray(); + rid.Database = BitConverter.ToUInt32(guidBytes, 0); + + rid.DocumentCollection = 0; + rid.Document = 0; + rid.User = 0; + rid.Permission = 0; + + return rid; + } + #endregion + + // Copy the bytes provided with a for loop, faster when there are only a few bytes to copy + public static void BlockCopy(byte[] src, int srcOffset, byte[] dst, int dstOffset, int count) + { + int stop = srcOffset + count; + for (int i = srcOffset; i < stop; i++) + dst[dstOffset++] = src[i]; + } + + private static bool HasNonHierarchicalResourceId(ResourceType eResourceType) + { +#if !COSMOSCLIENT + return eResourceType == ResourceType.MasterPartition || + eResourceType == ResourceType.ServerPartition || + eResourceType == ResourceType.RidRange; +#else + return false; +#endif + } + + // Using a byte however, we only need nibble here. + private enum CollectionChildResourceType : byte + { + Document = 0x00, + StoredProcedure = 0x08, + Trigger = 0x07, + UserDefinedFunction = 0x06, + Conflict = 0x04, + PartitionKeyRange = 0x05, + Schema = 0x09, + PartitionedSystemDocument = 0x0A, + SystemDocument = 0x0D + } + + private enum ExtendedDatabaseChildResourceType + { + UserDefinedType = 0x01, + ClientEncryptionKey = 0x02 + } + + internal enum RbacResourceType : byte + { + RbacResourceType_RoleDefinition = 0x00, + RbacResourceType_RoleAssignment = 0x10, + RbacResourceType_InteropUser = 0x20, + RbacResourceType_AuthPolicyElement = 0x30, + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceIdBase64Decoder.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceIdBase64Decoder.cs index 501272a9ee..c4199c0318 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceIdBase64Decoder.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceIdBase64Decoder.cs @@ -1,248 +1,248 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Runtime.CompilerServices; - - /// - /// Mainly copied from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Convert.Base64.cs - /// Implementation does not support spaces inside the message given is is not a case for ResourceIds. - /// Do not modify this file. Take any changes necessary outside of this code that will be eventually replaced with the runtime implementation. - /// -#if NETSTANDARD2_1 || NETCOREAPP -#error Switch to https://docs.microsoft.com/en-us/dotnet/api/system.convert.tryfrombase64string?view=net-6.0 -#endif - internal static class ResourceIdBase64Decoder - { - public unsafe static bool TryDecode(string base64string, out byte[] bytes) - { - bytes = null; - if (string.IsNullOrEmpty(base64string)) - { - return false; - } - - fixed (char* srcChars = base64string) { - int srcLength = base64string.Length; - - // We need to get rid of any trailing white spaces. - // Otherwise we would be rejecting input such as "abc= ": - while (srcLength > 0) - { - int lastChar = srcChars[srcLength - 1]; - if (lastChar != Space) - { - break; - } - srcLength--; - } - - if (TryComputeResultLength(srcChars, srcLength, out int destLength) == false) - { - return false; - } - bytes = new byte[destLength]; - - int sourceIndex = 0; - int destIndex = 0; - - // Last bytes could have padding characters, so process them separately and treat them as valid. - int maxSrcLength = srcLength - 4; - - while (sourceIndex < maxSrcLength) - { - int result = Decode(srcChars, sourceIndex); - if (result < 0) - { - bytes = default; - return false; - } - WriteThreeLowOrderBytes(bytes, destIndex, result); - destIndex += 3; - sourceIndex += 4; - } - - int i0 = srcChars[srcLength - 4]; - int i1 = srcChars[srcLength - 3]; - int i2 = srcChars[srcLength - 2]; - int i3 = srcChars[srcLength - 1]; - if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0) - { - bytes = default; - return false; - } - - i0 = DecodingMap[i0]; - i1 = DecodingMap[i1]; - - i0 <<= 18; - i1 <<= 12; - - i0 |= i1; - - if (i3 != EncodingPad) - { - i2 = DecodingMap[i2]; - i3 = DecodingMap[i3]; - - i2 <<= 6; - - i0 |= i3; - i0 |= i2; - - if (i0 < 0) - { - bytes = default; - return false; - } - - if (destIndex > destLength - 3) - { - bytes = default; - return false; - } - - WriteThreeLowOrderBytes(bytes, destIndex, i0); - destIndex += 3; - } - else if (i2 != EncodingPad) - { - i2 = DecodingMap[i2]; - - i2 <<= 6; - - i0 |= i2; - - if (i0 < 0) - { - bytes = default; - return false; - } - - if (destIndex > destLength - 2) - { - bytes = default; - return false; - } - - bytes[destIndex] = (byte)(i0 >> 16); - bytes[destIndex + 1] = (byte)(i0 >> 8); - destIndex += 2; - } - else - { - if (i0 < 0) - { - bytes = default; - return false; - } - - if (destIndex > destLength - 1) - { - bytes = default; - return false; - } - - bytes[destIndex] = (byte)(i0 >> 16); - destIndex++; - } - - return true; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe static int Decode(char* encodedChars, int sourceIndex) - { - int i0 = encodedChars[sourceIndex]; - int i1 = encodedChars[sourceIndex + 1]; - int i2 = encodedChars[sourceIndex + 2]; - int i3 = encodedChars[sourceIndex + 3]; - - if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0) - { - return -1; // One or more chars falls outside the 00..ff range. This cannot be a valid Base64 character. - } - - i0 = DecodingMap[i0]; - i1 = DecodingMap[i1]; - i2 = DecodingMap[i2]; - i3 = DecodingMap[i3]; - - i0 <<= 18; - i1 <<= 12; - i2 <<= 6; - - i0 |= i3; - i1 |= i2; - - i0 |= i1; - return i0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteThreeLowOrderBytes(byte[] destination, int destIndex, int value) - { - destination[destIndex] = (byte)(value >> 16); - destination[destIndex + 1] = (byte)(value >> 8); - destination[destIndex + 2] = (byte)value; - } - - /// - /// Compute the number of bytes encoded in the specified Base 64 char array: - /// Walk the entire input counting white spaces and padding chars, then compute result length - /// based on 3 bytes per 4 chars. - /// - private static unsafe bool TryComputeResultLength(char* inputPtr, int inputLength, out int resultLength) - { - resultLength = 0; - - if (inputLength >= 3 && inputPtr[inputLength - 3] == EncodingPad) - { - return false; - } - else if (inputLength >= 2 && inputPtr[inputLength - 2] == EncodingPad) - { - // Two trailing pads - resultLength = ((inputLength - 2) >> 2) * 3 + 1; - } - else if (inputPtr[inputLength - 1] == EncodingPad) - { - // One trailing pad - resultLength = ((inputLength - 1) >> 2) * 3 + 2; - } - else - { - resultLength = (inputLength >> 2) * 3; - } - - return true; - } - - private const byte EncodingPad = (byte)'='; - private const byte Space = (byte)' '; - - // Pre-computing this table using a custom string(s_characters) and GenerateDecodingMapAndVerify (found in tests) - private readonly static sbyte[] DecodingMap = new sbyte[] - { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 62 is placed at index 43 (for +), 63 at index 47 (for /) - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 52-61 are placed at index 48-57 (for 0-9), 64 at index 61 (for =) - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 0-25 are placed at index 65-90 (for A-Z) - -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 26-51 are placed at index 97-122 (for a-z) - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bytes over 122 ('z') are invalid and cannot be decoded - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Hence, padding the map with 255, which indicates invalid input - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - }; - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Runtime.CompilerServices; + + /// + /// Mainly copied from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Convert.Base64.cs + /// Implementation does not support spaces inside the message given is is not a case for ResourceIds. + /// Do not modify this file. Take any changes necessary outside of this code that will be eventually replaced with the runtime implementation. + /// +#if NETSTANDARD2_1 || NETCOREAPP +#error Switch to https://docs.microsoft.com/en-us/dotnet/api/system.convert.tryfrombase64string?view=net-6.0 +#endif + internal static class ResourceIdBase64Decoder + { + public unsafe static bool TryDecode(string base64string, out byte[] bytes) + { + bytes = null; + if (string.IsNullOrEmpty(base64string)) + { + return false; + } + + fixed (char* srcChars = base64string) { + int srcLength = base64string.Length; + + // We need to get rid of any trailing white spaces. + // Otherwise we would be rejecting input such as "abc= ": + while (srcLength > 0) + { + int lastChar = srcChars[srcLength - 1]; + if (lastChar != Space) + { + break; + } + srcLength--; + } + + if (TryComputeResultLength(srcChars, srcLength, out int destLength) == false) + { + return false; + } + bytes = new byte[destLength]; + + int sourceIndex = 0; + int destIndex = 0; + + // Last bytes could have padding characters, so process them separately and treat them as valid. + int maxSrcLength = srcLength - 4; + + while (sourceIndex < maxSrcLength) + { + int result = Decode(srcChars, sourceIndex); + if (result < 0) + { + bytes = default; + return false; + } + WriteThreeLowOrderBytes(bytes, destIndex, result); + destIndex += 3; + sourceIndex += 4; + } + + int i0 = srcChars[srcLength - 4]; + int i1 = srcChars[srcLength - 3]; + int i2 = srcChars[srcLength - 2]; + int i3 = srcChars[srcLength - 1]; + if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0) + { + bytes = default; + return false; + } + + i0 = DecodingMap[i0]; + i1 = DecodingMap[i1]; + + i0 <<= 18; + i1 <<= 12; + + i0 |= i1; + + if (i3 != EncodingPad) + { + i2 = DecodingMap[i2]; + i3 = DecodingMap[i3]; + + i2 <<= 6; + + i0 |= i3; + i0 |= i2; + + if (i0 < 0) + { + bytes = default; + return false; + } + + if (destIndex > destLength - 3) + { + bytes = default; + return false; + } + + WriteThreeLowOrderBytes(bytes, destIndex, i0); + destIndex += 3; + } + else if (i2 != EncodingPad) + { + i2 = DecodingMap[i2]; + + i2 <<= 6; + + i0 |= i2; + + if (i0 < 0) + { + bytes = default; + return false; + } + + if (destIndex > destLength - 2) + { + bytes = default; + return false; + } + + bytes[destIndex] = (byte)(i0 >> 16); + bytes[destIndex + 1] = (byte)(i0 >> 8); + destIndex += 2; + } + else + { + if (i0 < 0) + { + bytes = default; + return false; + } + + if (destIndex > destLength - 1) + { + bytes = default; + return false; + } + + bytes[destIndex] = (byte)(i0 >> 16); + destIndex++; + } + + return true; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private unsafe static int Decode(char* encodedChars, int sourceIndex) + { + int i0 = encodedChars[sourceIndex]; + int i1 = encodedChars[sourceIndex + 1]; + int i2 = encodedChars[sourceIndex + 2]; + int i3 = encodedChars[sourceIndex + 3]; + + if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0) + { + return -1; // One or more chars falls outside the 00..ff range. This cannot be a valid Base64 character. + } + + i0 = DecodingMap[i0]; + i1 = DecodingMap[i1]; + i2 = DecodingMap[i2]; + i3 = DecodingMap[i3]; + + i0 <<= 18; + i1 <<= 12; + i2 <<= 6; + + i0 |= i3; + i1 |= i2; + + i0 |= i1; + return i0; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteThreeLowOrderBytes(byte[] destination, int destIndex, int value) + { + destination[destIndex] = (byte)(value >> 16); + destination[destIndex + 1] = (byte)(value >> 8); + destination[destIndex + 2] = (byte)value; + } + + /// + /// Compute the number of bytes encoded in the specified Base 64 char array: + /// Walk the entire input counting white spaces and padding chars, then compute result length + /// based on 3 bytes per 4 chars. + /// + private static unsafe bool TryComputeResultLength(char* inputPtr, int inputLength, out int resultLength) + { + resultLength = 0; + + if (inputLength >= 3 && inputPtr[inputLength - 3] == EncodingPad) + { + return false; + } + else if (inputLength >= 2 && inputPtr[inputLength - 2] == EncodingPad) + { + // Two trailing pads + resultLength = ((inputLength - 2) >> 2) * 3 + 1; + } + else if (inputPtr[inputLength - 1] == EncodingPad) + { + // One trailing pad + resultLength = ((inputLength - 1) >> 2) * 3 + 2; + } + else + { + resultLength = (inputLength >> 2) * 3; + } + + return true; + } + + private const byte EncodingPad = (byte)'='; + private const byte Space = (byte)' '; + + // Pre-computing this table using a custom string(s_characters) and GenerateDecodingMapAndVerify (found in tests) + private readonly static sbyte[] DecodingMap = new sbyte[] + { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, // 62 is placed at index 43 (for +), 63 at index 47 (for /) + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, // 52-61 are placed at index 48-57 (for 0-9), 64 at index 61 (for =) + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, // 0-25 are placed at index 65-90 (for A-Z) + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, // 26-51 are placed at index 97-122 (for a-z) + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bytes over 122 ('z') are invalid and cannot be decoded + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Hence, padding the map with 255, which indicates invalid input + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + }; + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceOperation.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceOperation.cs index 08938adfb7..7a745df7b5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceOperation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceOperation.cs @@ -1,190 +1,190 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Globalization; - - internal struct ResourceOperation - { - public readonly OperationType operationType; - public readonly ResourceType resourceType; - - public ResourceOperation( - OperationType operationType, - ResourceType resourceType) - { - this.operationType = operationType; - this.resourceType = resourceType; - } - - // TODO, atulk, delete these definitions once the gateway refactoring is completed - public static readonly ResourceOperation CreateOffer = new ResourceOperation(OperationType.Create, ResourceType.Offer); - public static readonly ResourceOperation ReplaceOffer = new ResourceOperation(OperationType.Replace, ResourceType.Offer); - public static readonly ResourceOperation ReadOffer = new ResourceOperation(OperationType.Read, ResourceType.Offer); - public static readonly ResourceOperation DeleteOffer = new ResourceOperation(OperationType.Delete, ResourceType.Offer); - public static readonly ResourceOperation ReadOfferFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Offer); - -#if !COSMOSCLIENT - public static readonly ResourceOperation ReadPartitionSetInformation = new ResourceOperation(OperationType.ReadFeed, ResourceType.PartitionSetInformation); -#endif - - public static readonly ResourceOperation CreateDatabase = new ResourceOperation(OperationType.Create, ResourceType.Database); - public static readonly ResourceOperation UpsertDatabase = new ResourceOperation(OperationType.Upsert, ResourceType.Database); - public static readonly ResourceOperation PatchDatabase = new ResourceOperation(OperationType.Patch, ResourceType.Database); - public static readonly ResourceOperation ReplaceDatabase = new ResourceOperation(OperationType.Replace, ResourceType.Database); - public static readonly ResourceOperation DeleteDatabase = new ResourceOperation(OperationType.Delete, ResourceType.Database); - public static readonly ResourceOperation ReadDatabase = new ResourceOperation(OperationType.Read, ResourceType.Database); - public static readonly ResourceOperation ReadDatabaseFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Database); - public static readonly ResourceOperation HeadDatabaseFeed = new ResourceOperation(OperationType.HeadFeed, ResourceType.Database); - - public static readonly ResourceOperation CreateCollection = new ResourceOperation(OperationType.Create, ResourceType.Collection); - public static readonly ResourceOperation PatchCollection = new ResourceOperation(OperationType.Patch, ResourceType.Collection); - public static readonly ResourceOperation ReplaceCollection = new ResourceOperation(OperationType.Replace, ResourceType.Collection); - public static readonly ResourceOperation DeleteCollection = new ResourceOperation(OperationType.Delete, ResourceType.Collection); - public static readonly ResourceOperation ReadCollection = new ResourceOperation(OperationType.Read, ResourceType.Collection); - public static readonly ResourceOperation HeadCollection = new ResourceOperation(OperationType.Head, ResourceType.Collection); - public static readonly ResourceOperation ReadCollectionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Collection); - - public static readonly ResourceOperation CreateDocument = new ResourceOperation(OperationType.Create, ResourceType.Document); - public static readonly ResourceOperation UpsertDocument = new ResourceOperation(OperationType.Upsert, ResourceType.Document); - public static readonly ResourceOperation PatchDocument = new ResourceOperation(OperationType.Patch, ResourceType.Document); - public static readonly ResourceOperation ReplaceDocument = new ResourceOperation(OperationType.Replace, ResourceType.Document); - public static readonly ResourceOperation DeleteDocument = new ResourceOperation(OperationType.Delete, ResourceType.Document); - public static readonly ResourceOperation ReadDocument = new ResourceOperation(OperationType.Read, ResourceType.Document); - public static readonly ResourceOperation ReadDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Document); - - public static readonly ResourceOperation ExecuteDocumentFeed = new ResourceOperation(OperationType.ExecuteJavaScript, ResourceType.StoredProcedure); - - public static readonly ResourceOperation CreateAttachment = new ResourceOperation(OperationType.Create, ResourceType.Attachment); - public static readonly ResourceOperation UpsertAttachment = new ResourceOperation(OperationType.Upsert, ResourceType.Attachment); - public static readonly ResourceOperation PatchAttachment = new ResourceOperation(OperationType.Patch, ResourceType.Attachment); - public static readonly ResourceOperation ReplaceAttachment = new ResourceOperation(OperationType.Replace, ResourceType.Attachment); - public static readonly ResourceOperation DeleteAttachment = new ResourceOperation(OperationType.Delete, ResourceType.Attachment); - public static readonly ResourceOperation ReadAttachment = new ResourceOperation(OperationType.Read, ResourceType.Attachment); - public static readonly ResourceOperation ReadAttachmentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Attachment); - - public static readonly ResourceOperation CreateStoredProcedure = new ResourceOperation(OperationType.Create, ResourceType.StoredProcedure); - public static readonly ResourceOperation UpsertStoredProcedure = new ResourceOperation(OperationType.Upsert, ResourceType.StoredProcedure); - public static readonly ResourceOperation ReplaceStoredProcedure = new ResourceOperation(OperationType.Replace, ResourceType.StoredProcedure); - public static readonly ResourceOperation DeleteStoredProcedure = new ResourceOperation(OperationType.Delete, ResourceType.StoredProcedure); - public static readonly ResourceOperation ReadStoredProcedure = new ResourceOperation(OperationType.Read, ResourceType.StoredProcedure); - public static readonly ResourceOperation ReadStoredProcedureFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.StoredProcedure); - - public static readonly ResourceOperation CreateUser = new ResourceOperation(OperationType.Create, ResourceType.User); - public static readonly ResourceOperation UpsertUser = new ResourceOperation(OperationType.Upsert, ResourceType.User); - public static readonly ResourceOperation PatchUser = new ResourceOperation(OperationType.Patch, ResourceType.User); - public static readonly ResourceOperation ReplaceUser = new ResourceOperation(OperationType.Replace, ResourceType.User); - public static readonly ResourceOperation DeleteUser = new ResourceOperation(OperationType.Delete, ResourceType.User); - public static readonly ResourceOperation ReadUser = new ResourceOperation(OperationType.Read, ResourceType.User); - public static readonly ResourceOperation ReadUserFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.User); - - public static readonly ResourceOperation CreatePermission = new ResourceOperation(OperationType.Create, ResourceType.Permission); - public static readonly ResourceOperation UpsertPermission = new ResourceOperation(OperationType.Upsert, ResourceType.Permission); - public static readonly ResourceOperation PatchPermission = new ResourceOperation(OperationType.Patch, ResourceType.Permission); - public static readonly ResourceOperation ReplacePermission = new ResourceOperation(OperationType.Replace, ResourceType.Permission); - public static readonly ResourceOperation DeletePermission = new ResourceOperation(OperationType.Delete, ResourceType.Permission); - public static readonly ResourceOperation ReadPermission = new ResourceOperation(OperationType.Read, ResourceType.Permission); - public static readonly ResourceOperation ReadPermissionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Permission); - - public static readonly ResourceOperation CreateClientEncryptionKey = new ResourceOperation(OperationType.Create, ResourceType.ClientEncryptionKey); - public static readonly ResourceOperation ReplaceClientEncryptionKey = new ResourceOperation(OperationType.Replace, ResourceType.ClientEncryptionKey); - public static readonly ResourceOperation DeleteClientEncryptionKey = new ResourceOperation(OperationType.Delete, ResourceType.ClientEncryptionKey); - public static readonly ResourceOperation ReadClientEncryptionKey = new ResourceOperation(OperationType.Read, ResourceType.ClientEncryptionKey); - public static readonly ResourceOperation ReadClientEncryptionKeyFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.ClientEncryptionKey); - - public static readonly ResourceOperation CreateSystemDocument = new ResourceOperation(OperationType.Create, ResourceType.SystemDocument); - public static readonly ResourceOperation ReplaceSystemDocument = new ResourceOperation(OperationType.Replace, ResourceType.SystemDocument); - public static readonly ResourceOperation DeleteSystemDocument = new ResourceOperation(OperationType.Delete, ResourceType.SystemDocument); - public static readonly ResourceOperation ReadSystemDocument = new ResourceOperation(OperationType.Read, ResourceType.SystemDocument); - public static readonly ResourceOperation ReadSystemDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.SystemDocument); - - public static readonly ResourceOperation CreatePartitionedSystemDocument = new ResourceOperation(OperationType.Create, ResourceType.PartitionedSystemDocument); - public static readonly ResourceOperation ReplacePartitionedSystemDocument = new ResourceOperation(OperationType.Replace, ResourceType.PartitionedSystemDocument); - public static readonly ResourceOperation DeletePartitionedSystemDocument = new ResourceOperation(OperationType.Delete, ResourceType.PartitionedSystemDocument); - public static readonly ResourceOperation ReadPartitionedSystemDocument = new ResourceOperation(OperationType.Read, ResourceType.PartitionedSystemDocument); - public static readonly ResourceOperation ReadPartitionedSystemDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.PartitionedSystemDocument); - -#if !COSMOSCLIENT - public static readonly ResourceOperation ReadReplica = new ResourceOperation(OperationType.Read, ResourceType.Replica); - public static readonly ResourceOperation ForceConfigRefresh = new ResourceOperation(OperationType.ForceConfigRefresh, ResourceType.Replica); - - public static readonly ResourceOperation CheckThrottlihg = new ResourceOperation(OperationType.Throttle, ResourceType.Collection); - - public static readonly ResourceOperation ReplaceModule = new ResourceOperation(OperationType.Replace, ResourceType.Module); - public static readonly ResourceOperation ReadModule = new ResourceOperation(OperationType.Read, ResourceType.Module); - - public static readonly ResourceOperation Pause = new ResourceOperation(OperationType.Pause, ResourceType.Replica); - public static readonly ResourceOperation Split = new ResourceOperation(OperationType.GetSplitPoint, ResourceType.PartitionKeyRange); - public static readonly ResourceOperation NWaySplit = new ResourceOperation(OperationType.GetSplitPoints, ResourceType.PartitionKeyRange); - public static readonly ResourceOperation AbortSplit = new ResourceOperation(OperationType.AbortSplit, ResourceType.PartitionKeyRange); - public static readonly ResourceOperation CompleteSplit = new ResourceOperation(OperationType.CompleteSplit, ResourceType.PartitionKeyRange); - public static readonly ResourceOperation Resume = new ResourceOperation(OperationType.Resume, ResourceType.Replica); - public static readonly ResourceOperation Stop = new ResourceOperation(OperationType.Stop, ResourceType.Replica); - public static readonly ResourceOperation Recycle = new ResourceOperation(OperationType.Recycle, ResourceType.Replica); - - // TODO: Add following for master partition once we support master partition migration. - public static readonly ResourceOperation AbortServerPartitionMigration = new ResourceOperation(OperationType.AbortPartitionMigration, ResourceType.ServerPartition); - public static readonly ResourceOperation CompleteServerPartitionMigration = new ResourceOperation(OperationType.CompleteSplit, ResourceType.ServerPartition); - - public static readonly ResourceOperation WatchdogCreateModuleCommand = new ResourceOperation(OperationType.Create, ResourceType.ModuleCommand); - public static readonly ResourceOperation WatchdogReadModuleCommand = new ResourceOperation(OperationType.Read, ResourceType.ModuleCommand); - - public static readonly ResourceOperation WildMemoryAccess = new ResourceOperation(OperationType.Crash, ResourceType.Replica); -#endif - - public static readonly ResourceOperation XDeleteConflict = new ResourceOperation(OperationType.Delete, ResourceType.Conflict); - public static readonly ResourceOperation XReadConflict = new ResourceOperation(OperationType.Read, ResourceType.Conflict); - public static readonly ResourceOperation XReadConflictFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Conflict); - - public static readonly ResourceOperation XReadRecordFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Record); - public static readonly ResourceOperation XCreateRecord = new ResourceOperation(OperationType.Create, ResourceType.Record); - public static readonly ResourceOperation XReadRecord = new ResourceOperation(OperationType.Read, ResourceType.Record); - public static readonly ResourceOperation XUpdateRecord = new ResourceOperation(OperationType.Replace, ResourceType.Record); - public static readonly ResourceOperation XDeleteRecord = new ResourceOperation(OperationType.Delete, ResourceType.Record); - - public static readonly ResourceOperation XXCreateTrigger = new ResourceOperation(OperationType.Create, ResourceType.Trigger); - public static readonly ResourceOperation XXUpsertTrigger = new ResourceOperation(OperationType.Upsert, ResourceType.Trigger); - public static readonly ResourceOperation XXReplaceTrigger = new ResourceOperation(OperationType.Replace, ResourceType.Trigger); - public static readonly ResourceOperation XXDeleteTrigger = new ResourceOperation(OperationType.Delete, ResourceType.Trigger); - public static readonly ResourceOperation XXReadTrigger = new ResourceOperation(OperationType.Read, ResourceType.Trigger); - public static readonly ResourceOperation XXReadTriggerFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Trigger); - - public static readonly ResourceOperation XXCreateUserDefinedFunction = new ResourceOperation(OperationType.Create, ResourceType.UserDefinedFunction); - public static readonly ResourceOperation XXUpsertUserDefinedFunction = new ResourceOperation(OperationType.Upsert, ResourceType.UserDefinedFunction); - public static readonly ResourceOperation XXReplaceUserDefinedFunction = new ResourceOperation(OperationType.Replace, ResourceType.UserDefinedFunction); - public static readonly ResourceOperation XXDeleteUserDefinedFunction = new ResourceOperation(OperationType.Delete, ResourceType.UserDefinedFunction); - public static readonly ResourceOperation XXReadUserDefinedFunction = new ResourceOperation(OperationType.Read, ResourceType.UserDefinedFunction); - public static readonly ResourceOperation XXReadUserDefinedFunctionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.UserDefinedFunction); - - public static readonly ResourceOperation ReadSchema = new ResourceOperation(OperationType.Read, ResourceType.Schema); - public static readonly ResourceOperation ReadSchemaFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Schema); - - public static readonly ResourceOperation CompleteUserTransaction = new ResourceOperation(OperationType.CompleteUserTransaction, ResourceType.Transaction); - -#if !COSMOSCLIENT - public static readonly ResourceOperation ReadRestoreMetadataFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.RestoreMetadata); -#endif - - public static ResourceOperation Query(OperationType operationType, ResourceType resourceType) - { - Debug.Assert( - operationType == OperationType.SqlQuery || - operationType == OperationType.Query); - - return new ResourceOperation(operationType, resourceType); - } - - public override string ToString() - { - return String.Format( - CultureInfo.InvariantCulture, - "(operationType: {0}, resourceType: {1})", - operationType, - resourceType); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Globalization; + + internal struct ResourceOperation + { + public readonly OperationType operationType; + public readonly ResourceType resourceType; + + public ResourceOperation( + OperationType operationType, + ResourceType resourceType) + { + this.operationType = operationType; + this.resourceType = resourceType; + } + + // TODO, atulk, delete these definitions once the gateway refactoring is completed + public static readonly ResourceOperation CreateOffer = new ResourceOperation(OperationType.Create, ResourceType.Offer); + public static readonly ResourceOperation ReplaceOffer = new ResourceOperation(OperationType.Replace, ResourceType.Offer); + public static readonly ResourceOperation ReadOffer = new ResourceOperation(OperationType.Read, ResourceType.Offer); + public static readonly ResourceOperation DeleteOffer = new ResourceOperation(OperationType.Delete, ResourceType.Offer); + public static readonly ResourceOperation ReadOfferFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Offer); + +#if !COSMOSCLIENT + public static readonly ResourceOperation ReadPartitionSetInformation = new ResourceOperation(OperationType.ReadFeed, ResourceType.PartitionSetInformation); +#endif + + public static readonly ResourceOperation CreateDatabase = new ResourceOperation(OperationType.Create, ResourceType.Database); + public static readonly ResourceOperation UpsertDatabase = new ResourceOperation(OperationType.Upsert, ResourceType.Database); + public static readonly ResourceOperation PatchDatabase = new ResourceOperation(OperationType.Patch, ResourceType.Database); + public static readonly ResourceOperation ReplaceDatabase = new ResourceOperation(OperationType.Replace, ResourceType.Database); + public static readonly ResourceOperation DeleteDatabase = new ResourceOperation(OperationType.Delete, ResourceType.Database); + public static readonly ResourceOperation ReadDatabase = new ResourceOperation(OperationType.Read, ResourceType.Database); + public static readonly ResourceOperation ReadDatabaseFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Database); + public static readonly ResourceOperation HeadDatabaseFeed = new ResourceOperation(OperationType.HeadFeed, ResourceType.Database); + + public static readonly ResourceOperation CreateCollection = new ResourceOperation(OperationType.Create, ResourceType.Collection); + public static readonly ResourceOperation PatchCollection = new ResourceOperation(OperationType.Patch, ResourceType.Collection); + public static readonly ResourceOperation ReplaceCollection = new ResourceOperation(OperationType.Replace, ResourceType.Collection); + public static readonly ResourceOperation DeleteCollection = new ResourceOperation(OperationType.Delete, ResourceType.Collection); + public static readonly ResourceOperation ReadCollection = new ResourceOperation(OperationType.Read, ResourceType.Collection); + public static readonly ResourceOperation HeadCollection = new ResourceOperation(OperationType.Head, ResourceType.Collection); + public static readonly ResourceOperation ReadCollectionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Collection); + + public static readonly ResourceOperation CreateDocument = new ResourceOperation(OperationType.Create, ResourceType.Document); + public static readonly ResourceOperation UpsertDocument = new ResourceOperation(OperationType.Upsert, ResourceType.Document); + public static readonly ResourceOperation PatchDocument = new ResourceOperation(OperationType.Patch, ResourceType.Document); + public static readonly ResourceOperation ReplaceDocument = new ResourceOperation(OperationType.Replace, ResourceType.Document); + public static readonly ResourceOperation DeleteDocument = new ResourceOperation(OperationType.Delete, ResourceType.Document); + public static readonly ResourceOperation ReadDocument = new ResourceOperation(OperationType.Read, ResourceType.Document); + public static readonly ResourceOperation ReadDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Document); + + public static readonly ResourceOperation ExecuteDocumentFeed = new ResourceOperation(OperationType.ExecuteJavaScript, ResourceType.StoredProcedure); + + public static readonly ResourceOperation CreateAttachment = new ResourceOperation(OperationType.Create, ResourceType.Attachment); + public static readonly ResourceOperation UpsertAttachment = new ResourceOperation(OperationType.Upsert, ResourceType.Attachment); + public static readonly ResourceOperation PatchAttachment = new ResourceOperation(OperationType.Patch, ResourceType.Attachment); + public static readonly ResourceOperation ReplaceAttachment = new ResourceOperation(OperationType.Replace, ResourceType.Attachment); + public static readonly ResourceOperation DeleteAttachment = new ResourceOperation(OperationType.Delete, ResourceType.Attachment); + public static readonly ResourceOperation ReadAttachment = new ResourceOperation(OperationType.Read, ResourceType.Attachment); + public static readonly ResourceOperation ReadAttachmentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Attachment); + + public static readonly ResourceOperation CreateStoredProcedure = new ResourceOperation(OperationType.Create, ResourceType.StoredProcedure); + public static readonly ResourceOperation UpsertStoredProcedure = new ResourceOperation(OperationType.Upsert, ResourceType.StoredProcedure); + public static readonly ResourceOperation ReplaceStoredProcedure = new ResourceOperation(OperationType.Replace, ResourceType.StoredProcedure); + public static readonly ResourceOperation DeleteStoredProcedure = new ResourceOperation(OperationType.Delete, ResourceType.StoredProcedure); + public static readonly ResourceOperation ReadStoredProcedure = new ResourceOperation(OperationType.Read, ResourceType.StoredProcedure); + public static readonly ResourceOperation ReadStoredProcedureFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.StoredProcedure); + + public static readonly ResourceOperation CreateUser = new ResourceOperation(OperationType.Create, ResourceType.User); + public static readonly ResourceOperation UpsertUser = new ResourceOperation(OperationType.Upsert, ResourceType.User); + public static readonly ResourceOperation PatchUser = new ResourceOperation(OperationType.Patch, ResourceType.User); + public static readonly ResourceOperation ReplaceUser = new ResourceOperation(OperationType.Replace, ResourceType.User); + public static readonly ResourceOperation DeleteUser = new ResourceOperation(OperationType.Delete, ResourceType.User); + public static readonly ResourceOperation ReadUser = new ResourceOperation(OperationType.Read, ResourceType.User); + public static readonly ResourceOperation ReadUserFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.User); + + public static readonly ResourceOperation CreatePermission = new ResourceOperation(OperationType.Create, ResourceType.Permission); + public static readonly ResourceOperation UpsertPermission = new ResourceOperation(OperationType.Upsert, ResourceType.Permission); + public static readonly ResourceOperation PatchPermission = new ResourceOperation(OperationType.Patch, ResourceType.Permission); + public static readonly ResourceOperation ReplacePermission = new ResourceOperation(OperationType.Replace, ResourceType.Permission); + public static readonly ResourceOperation DeletePermission = new ResourceOperation(OperationType.Delete, ResourceType.Permission); + public static readonly ResourceOperation ReadPermission = new ResourceOperation(OperationType.Read, ResourceType.Permission); + public static readonly ResourceOperation ReadPermissionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Permission); + + public static readonly ResourceOperation CreateClientEncryptionKey = new ResourceOperation(OperationType.Create, ResourceType.ClientEncryptionKey); + public static readonly ResourceOperation ReplaceClientEncryptionKey = new ResourceOperation(OperationType.Replace, ResourceType.ClientEncryptionKey); + public static readonly ResourceOperation DeleteClientEncryptionKey = new ResourceOperation(OperationType.Delete, ResourceType.ClientEncryptionKey); + public static readonly ResourceOperation ReadClientEncryptionKey = new ResourceOperation(OperationType.Read, ResourceType.ClientEncryptionKey); + public static readonly ResourceOperation ReadClientEncryptionKeyFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.ClientEncryptionKey); + + public static readonly ResourceOperation CreateSystemDocument = new ResourceOperation(OperationType.Create, ResourceType.SystemDocument); + public static readonly ResourceOperation ReplaceSystemDocument = new ResourceOperation(OperationType.Replace, ResourceType.SystemDocument); + public static readonly ResourceOperation DeleteSystemDocument = new ResourceOperation(OperationType.Delete, ResourceType.SystemDocument); + public static readonly ResourceOperation ReadSystemDocument = new ResourceOperation(OperationType.Read, ResourceType.SystemDocument); + public static readonly ResourceOperation ReadSystemDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.SystemDocument); + + public static readonly ResourceOperation CreatePartitionedSystemDocument = new ResourceOperation(OperationType.Create, ResourceType.PartitionedSystemDocument); + public static readonly ResourceOperation ReplacePartitionedSystemDocument = new ResourceOperation(OperationType.Replace, ResourceType.PartitionedSystemDocument); + public static readonly ResourceOperation DeletePartitionedSystemDocument = new ResourceOperation(OperationType.Delete, ResourceType.PartitionedSystemDocument); + public static readonly ResourceOperation ReadPartitionedSystemDocument = new ResourceOperation(OperationType.Read, ResourceType.PartitionedSystemDocument); + public static readonly ResourceOperation ReadPartitionedSystemDocumentFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.PartitionedSystemDocument); + +#if !COSMOSCLIENT + public static readonly ResourceOperation ReadReplica = new ResourceOperation(OperationType.Read, ResourceType.Replica); + public static readonly ResourceOperation ForceConfigRefresh = new ResourceOperation(OperationType.ForceConfigRefresh, ResourceType.Replica); + + public static readonly ResourceOperation CheckThrottlihg = new ResourceOperation(OperationType.Throttle, ResourceType.Collection); + + public static readonly ResourceOperation ReplaceModule = new ResourceOperation(OperationType.Replace, ResourceType.Module); + public static readonly ResourceOperation ReadModule = new ResourceOperation(OperationType.Read, ResourceType.Module); + + public static readonly ResourceOperation Pause = new ResourceOperation(OperationType.Pause, ResourceType.Replica); + public static readonly ResourceOperation Split = new ResourceOperation(OperationType.GetSplitPoint, ResourceType.PartitionKeyRange); + public static readonly ResourceOperation NWaySplit = new ResourceOperation(OperationType.GetSplitPoints, ResourceType.PartitionKeyRange); + public static readonly ResourceOperation AbortSplit = new ResourceOperation(OperationType.AbortSplit, ResourceType.PartitionKeyRange); + public static readonly ResourceOperation CompleteSplit = new ResourceOperation(OperationType.CompleteSplit, ResourceType.PartitionKeyRange); + public static readonly ResourceOperation Resume = new ResourceOperation(OperationType.Resume, ResourceType.Replica); + public static readonly ResourceOperation Stop = new ResourceOperation(OperationType.Stop, ResourceType.Replica); + public static readonly ResourceOperation Recycle = new ResourceOperation(OperationType.Recycle, ResourceType.Replica); + + // TODO: Add following for master partition once we support master partition migration. + public static readonly ResourceOperation AbortServerPartitionMigration = new ResourceOperation(OperationType.AbortPartitionMigration, ResourceType.ServerPartition); + public static readonly ResourceOperation CompleteServerPartitionMigration = new ResourceOperation(OperationType.CompleteSplit, ResourceType.ServerPartition); + + public static readonly ResourceOperation WatchdogCreateModuleCommand = new ResourceOperation(OperationType.Create, ResourceType.ModuleCommand); + public static readonly ResourceOperation WatchdogReadModuleCommand = new ResourceOperation(OperationType.Read, ResourceType.ModuleCommand); + + public static readonly ResourceOperation WildMemoryAccess = new ResourceOperation(OperationType.Crash, ResourceType.Replica); +#endif + + public static readonly ResourceOperation XDeleteConflict = new ResourceOperation(OperationType.Delete, ResourceType.Conflict); + public static readonly ResourceOperation XReadConflict = new ResourceOperation(OperationType.Read, ResourceType.Conflict); + public static readonly ResourceOperation XReadConflictFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Conflict); + + public static readonly ResourceOperation XReadRecordFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Record); + public static readonly ResourceOperation XCreateRecord = new ResourceOperation(OperationType.Create, ResourceType.Record); + public static readonly ResourceOperation XReadRecord = new ResourceOperation(OperationType.Read, ResourceType.Record); + public static readonly ResourceOperation XUpdateRecord = new ResourceOperation(OperationType.Replace, ResourceType.Record); + public static readonly ResourceOperation XDeleteRecord = new ResourceOperation(OperationType.Delete, ResourceType.Record); + + public static readonly ResourceOperation XXCreateTrigger = new ResourceOperation(OperationType.Create, ResourceType.Trigger); + public static readonly ResourceOperation XXUpsertTrigger = new ResourceOperation(OperationType.Upsert, ResourceType.Trigger); + public static readonly ResourceOperation XXReplaceTrigger = new ResourceOperation(OperationType.Replace, ResourceType.Trigger); + public static readonly ResourceOperation XXDeleteTrigger = new ResourceOperation(OperationType.Delete, ResourceType.Trigger); + public static readonly ResourceOperation XXReadTrigger = new ResourceOperation(OperationType.Read, ResourceType.Trigger); + public static readonly ResourceOperation XXReadTriggerFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Trigger); + + public static readonly ResourceOperation XXCreateUserDefinedFunction = new ResourceOperation(OperationType.Create, ResourceType.UserDefinedFunction); + public static readonly ResourceOperation XXUpsertUserDefinedFunction = new ResourceOperation(OperationType.Upsert, ResourceType.UserDefinedFunction); + public static readonly ResourceOperation XXReplaceUserDefinedFunction = new ResourceOperation(OperationType.Replace, ResourceType.UserDefinedFunction); + public static readonly ResourceOperation XXDeleteUserDefinedFunction = new ResourceOperation(OperationType.Delete, ResourceType.UserDefinedFunction); + public static readonly ResourceOperation XXReadUserDefinedFunction = new ResourceOperation(OperationType.Read, ResourceType.UserDefinedFunction); + public static readonly ResourceOperation XXReadUserDefinedFunctionFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.UserDefinedFunction); + + public static readonly ResourceOperation ReadSchema = new ResourceOperation(OperationType.Read, ResourceType.Schema); + public static readonly ResourceOperation ReadSchemaFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.Schema); + + public static readonly ResourceOperation CompleteUserTransaction = new ResourceOperation(OperationType.CompleteUserTransaction, ResourceType.Transaction); + +#if !COSMOSCLIENT + public static readonly ResourceOperation ReadRestoreMetadataFeed = new ResourceOperation(OperationType.ReadFeed, ResourceType.RestoreMetadata); +#endif + + public static ResourceOperation Query(OperationType operationType, ResourceType resourceType) + { + Debug.Assert( + operationType == OperationType.SqlQuery || + operationType == OperationType.Query); + + return new ResourceOperation(operationType, resourceType); + } + + public override string ToString() + { + return String.Format( + CultureInfo.InvariantCulture, + "(operationType: {0}, resourceType: {1})", + operationType, + resourceType); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceResponse.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceResponse.cs index 2c10c8d361..33aebe31bc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceResponse.cs @@ -1,90 +1,90 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - /// - /// Represents the template class used by methods returning single objects in the Azure Cosmos DB service. - /// - /// the resource type. - /// - /// All responses from creates, reads, updates and deletes of Azure Cosmos DB resources return the response wrapped in a - /// ResourceResponse object. This contains the metadata from the response headers from the Azure Cosmos DB call including - /// the request units (RequestCharge), activity ID and quotas/usage of resources. - /// - /// - /// The following example extracts the request units consumed, activity ID and StatusCode from a CreateDocumentAsync call. - /// - /// response = await client.CreateDocumentAsync(collectionLink, document); - /// Console.WriteLine(response.RequestCharge); - /// Console.WriteLine(response.ActivityId); - /// Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201 - /// ]]> - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class ResourceResponse : ResourceResponseBase, IResourceResponse where TResource : Resource, new() - { - private TResource resource; - private ITypeResolver typeResolver; - - /// - /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. - /// - public ResourceResponse() - { - - } - - /// - /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. - /// - /// - public ResourceResponse(TResource resource) - :this() - { - this.resource = resource; - } - - internal ResourceResponse(DocumentServiceResponse response, ITypeResolver typeResolver = null) - :base(response) - { - this.typeResolver = typeResolver; - } - - /// - /// Gets the resource returned in the response from the Azure Cosmos DB service. - /// - /// - /// The resource returned in the response. - /// - public TResource Resource - { - get - { - if (this.resource == null) - { - this.resource = this.response.GetResource(typeResolver); - } - return this.resource; - } - } - - /// - /// Returns the resource in the response implicitly from the Azure Cosmos DB service. - /// - /// The ResourceResponse source. - /// The resource object. - public static implicit operator TResource(ResourceResponse source) - { - return source.Resource; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + /// + /// Represents the template class used by methods returning single objects in the Azure Cosmos DB service. + /// + /// the resource type. + /// + /// All responses from creates, reads, updates and deletes of Azure Cosmos DB resources return the response wrapped in a + /// ResourceResponse object. This contains the metadata from the response headers from the Azure Cosmos DB call including + /// the request units (RequestCharge), activity ID and quotas/usage of resources. + /// + /// + /// The following example extracts the request units consumed, activity ID and StatusCode from a CreateDocumentAsync call. + /// + /// response = await client.CreateDocumentAsync(collectionLink, document); + /// Console.WriteLine(response.RequestCharge); + /// Console.WriteLine(response.ActivityId); + /// Console.WriteLine(response.StatusCode); // HttpStatusCode.Created or 201 + /// ]]> + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class ResourceResponse : ResourceResponseBase, IResourceResponse where TResource : Resource, new() + { + private TResource resource; + private ITypeResolver typeResolver; + + /// + /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. + /// + public ResourceResponse() + { + + } + + /// + /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. + /// + /// + public ResourceResponse(TResource resource) + :this() + { + this.resource = resource; + } + + internal ResourceResponse(DocumentServiceResponse response, ITypeResolver typeResolver = null) + :base(response) + { + this.typeResolver = typeResolver; + } + + /// + /// Gets the resource returned in the response from the Azure Cosmos DB service. + /// + /// + /// The resource returned in the response. + /// + public TResource Resource + { + get + { + if (this.resource == null) + { + this.resource = this.response.GetResource(typeResolver); + } + return this.resource; + } + } + + /// + /// Returns the resource in the response implicitly from the Azure Cosmos DB service. + /// + /// The ResourceResponse source. + /// The resource object. + public static implicit operator TResource(ResourceResponse source) + { + return source.Resource; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceResponseBase.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceResponseBase.cs index b906e738be..f149890bef 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceResponseBase.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceResponseBase.cs @@ -1,675 +1,675 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Client -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Diagnostics; - using System.Globalization; - using System.IO; - using System.Net; - using Microsoft.Azure.Documents.Collections; - - /// - /// Represents the non-resource specific service response headers returned by any request in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - abstract class ResourceResponseBase : IResourceResponseBase - { - // Ideally response was intended to be marked as protected(to be accessed by sub-classes) but since DocumentServiceResponse class is marked internal, - // it gives Inconsistent accessibility error saying DocumentServiceResponse is less accessible than field ServiceResponse.response if I mark it as protected. - internal DocumentServiceResponse response; - private Dictionary usageHeaders; - private Dictionary quotaHeaders; - - /// - /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. - /// - public ResourceResponseBase() - { - - } - - internal ResourceResponseBase(DocumentServiceResponse response) - { - this.response = response; - this.usageHeaders = new Dictionary(); - this.quotaHeaders = new Dictionary(); - } - - /// - /// Gets the maximum quota for database resources within the account from the Azure Cosmos DB service. - /// - /// - /// The maximum quota for the account. - /// - public long DatabaseQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.Database); - } - } - - /// - /// Gets the current number of database resources within the account from the Azure Cosmos DB service. - /// - /// - /// The number of databases. - /// - public long DatabaseUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.Database); - } - } - - /// - /// Gets the maximum quota for collection resources within an account from the Azure Cosmos DB service. - /// - /// - /// The maximum quota for the account. - /// - public long CollectionQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.Collection); - } - } - - /// - /// Gets the current number of collection resources within the account from the Azure Cosmos DB service. - /// - /// - /// The number of collections. - /// - public long CollectionUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.Collection); - } - } - - /// - /// Gets the maximum quota for user resources within an account from the Azure Cosmos DB service. - /// - /// - /// The maximum quota for the account. - /// - public long UserQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.User); - } - } - - /// - /// Gets the current number of user resources within the account from the Azure Cosmos DB service. - /// - /// - /// The number of users. - /// - public long UserUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.User); - } - } - - /// - /// Gets the maximum quota for permission resources within an account from the Azure Cosmos DB service. - /// - /// - /// The maximum quota for the account. - /// - public long PermissionQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.Permission); - } - } - - /// - /// Gets the current number of permission resources within the account from the Azure Cosmos DB service. - /// - /// - /// The number of permissions. - /// - public long PermissionUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.Permission); - } - } - - /// - /// Gets the maximum size of a collection in kilobytes from the Azure Cosmos DB service. - /// - /// - /// Quota in kilobytes. - /// - public long CollectionSizeQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.CollectionSize); - } - } - - /// - /// Gets the current size of a collection in kilobytes from the Azure Cosmos DB service. - /// - /// - /// Current collection size in kilobytes. - /// - public long CollectionSizeUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.CollectionSize); - } - } - - /// - /// Gets the maximum size of a documents within a collection in kilobytes from the Azure Cosmos DB service. - /// - /// - /// Quota in kilobytes. - /// - public long DocumentQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.DocumentsSize); - } - } - - /// - /// Gets the current size of documents within a collection in kilobytes from the Azure Cosmos DB service. - /// - /// - /// Current documents size in kilobytes. - /// - public long DocumentUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.DocumentsSize); - } - } - - /// - /// Gets the maximum quota of stored procedures for a collection from the Azure Cosmos DB service. - /// - /// - /// The maximum quota. - /// - public long StoredProceduresQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.StoredProcedure); - } - } - - /// - /// Gets the current number of stored procedures for a collection from the Azure Cosmos DB service. - /// - /// - /// Current number of stored procedures. - /// - public long StoredProceduresUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.StoredProcedure); - } - } - - /// - /// Gets the maximum quota of triggers for a collection from the Azure Cosmos DB service. - /// - /// - /// The maximum quota. - /// - public long TriggersQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.Trigger); - } - } - - /// - /// Gets the current number of triggers for a collection from the Azure Cosmos DB service. - /// - /// - /// Current number of triggers. - /// - public long TriggersUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.Trigger); - } - } - - /// - /// Gets the maximum quota of user defined functions for a collection from the Azure Cosmos DB service. - /// - /// - /// The maximum quota. - /// - public long UserDefinedFunctionsQuota - { - get - { - return this.GetMaxQuotaHeader(Constants.Quota.UserDefinedFunction); - } - } - - /// - /// Gets the current number of user defined functions for a collection from the Azure Cosmos DB service. - /// - /// - /// Current number of user defined functions. - /// - public long UserDefinedFunctionsUsage - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.UserDefinedFunction); - } - } - - /// - /// Gets the current count of documents within a collection from the Azure Cosmos DB service. - /// - /// - /// Current count of documents. - /// - internal long DocumentCount - { - get - { - return this.GetCurrentQuotaHeader(Constants.Quota.DocumentsCount); - } - } - - /// - /// Gets the activity ID for the request from the Azure Cosmos DB service. - /// - /// - /// The activity ID for the request. - /// - public string ActivityId - { - get - { - return this.response.Headers[HttpConstants.HttpHeaders.ActivityId]; - } - } - - /// - /// Gets the session token for use in sesssion consistency reads from the Azure Cosmos DB service. - /// - /// - /// The session token for use in session consistency. - /// - public string SessionToken - { - get - { - return this.response.Headers[HttpConstants.HttpHeaders.SessionToken]; - } - } - - /// - /// Gets the HTTP status code associated with the response from the Azure Cosmos DB service. - /// - /// - /// The HTTP status code associated with the response. - /// - public HttpStatusCode StatusCode - { - get - { - return this.response.StatusCode; - } - } - - /// - /// Gets the maximum size limit for this entity from the Azure Cosmos DB service. - /// - /// - /// The maximum size limit for this entity. Measured in kilobytes for document resources - /// and in counts for other resources. - /// - public string MaxResourceQuota - { - get - { - return this.response.Headers[HttpConstants.HttpHeaders.MaxResourceQuota]; - } - } - - /// - /// Gets the current size of this entity from the Azure Cosmos DB service. - /// - /// - /// The current size for this entity. Measured in kilobytes for document resources - /// and in counts for other resources. - /// - public string CurrentResourceQuotaUsage - { - get - { - return this.response.Headers[HttpConstants.HttpHeaders.CurrentResourceQuotaUsage]; - } - } - - /// - /// Gets the underlying stream of the response from the Azure Cosmos DB service. - /// - public Stream ResponseStream - { - get - { - return this.response.ResponseBody; - } - } - - /// - /// Gets the request charge for this request from the Azure Cosmos DB service. - /// - /// - /// The request charge measured in reqest units. - /// - public double RequestCharge - { - get - { - return Helpers.GetHeaderValueDouble( - this.response.Headers, - HttpConstants.HttpHeaders.RequestCharge, - 0); - } - } - - /// - /// Gets the flag associated with the response from the Azure Cosmos DB service whether this request is served from Request Units(RUs)/minute capacity or not. - /// - /// - /// True if this request is served from RUs/minute capacity. Otherwise, false. - /// - public bool IsRUPerMinuteUsed - { - get - { - if (Helpers.GetHeaderValueByte(this.response.Headers, HttpConstants.HttpHeaders.IsRUPerMinuteUsed, 0) != 0) - { - return true; - } - - return false; - } - } - - /// - /// Gets the response headers from the Azure Cosmos DB service. - /// - /// - /// The response headers. - /// - public NameValueCollection ResponseHeaders - { - get - { - return this.response.ResponseHeaders; - } - } - - internal INameValueCollection Headers - { - get { return this.response.Headers; } - } - - /// - /// The content parent location, for example, dbs/foo/colls/bar in the Azure Cosmos DB service. - /// - public string ContentLocation - { - get - { - return this.response.Headers[HttpConstants.HttpHeaders.OwnerFullName]; - } - } - - /// - /// Gets the progress of an index transformation, if one is underway from the Azure Cosmos DB service. - /// - /// - /// An integer from 0 to 100 representing percentage completion of the index transformation process. - /// Returns -1 if the index transformation progress header could not be found. - /// - /// - /// An index will be rebuilt when the IndexPolicy of a collection is updated. - /// - public long IndexTransformationProgress - { - get - { - return Helpers.GetHeaderValueLong(this.response.Headers, HttpConstants.HttpHeaders.CollectionIndexTransformationProgress); - } - } - - /// - /// Gets the progress of lazy indexing from the Azure Cosmos DB service. - /// - /// - /// An integer from 0 to 100 representing percentage completion of the lazy indexing process. - /// Returns -1 if the lazy indexing progress header could not be found. - /// - /// - /// Lazy indexing progress only applies to the collection with indexing mode Lazy. - /// - public long LazyIndexingProgress - { - get - { - return Helpers.GetHeaderValueLong(this.response.Headers, HttpConstants.HttpHeaders.CollectionLazyIndexingProgress); - } - } - - /// - /// Gets the end-to-end request latency for the current request to Azure Cosmos DB service. - /// - /// - /// This field is only valid when the request uses direct connectivity. - /// - public TimeSpan RequestLatency - { - get - { - if (this.response.RequestStats == null || - !this.response.RequestStats.RequestLatency.HasValue) - { - return TimeSpan.Zero; - } - - return this.response.RequestStats.RequestLatency.Value; - } - } - - /// - /// Gets the diagnostics information for the current request to Azure Cosmos DB service. - /// - /// - /// This field is only valid when the request uses direct connectivity. - /// - public string RequestDiagnosticsString - { - get - { - if (this.response.RequestStats == null) - { - return string.Empty; - } - - return this.response.RequestStats.ToString(); - } - } - - /// - /// Gets the request statistics for the current request to Azure Cosmos DB service. - /// - /// - /// This field is only valid when the request uses direct connectivity. - /// - internal IClientSideRequestStatistics RequestStatistics - { - get - { - return this.response.RequestStats; - } - } - - internal long GetCurrentQuotaHeader(string headerName) - { - long headerValue = 0; - if (this.usageHeaders.Count == 0 && !string.IsNullOrEmpty(this.MaxResourceQuota) && !string.IsNullOrEmpty(this.CurrentResourceQuotaUsage)) - { - this.PopulateQuotaHeader(this.MaxResourceQuota, this.CurrentResourceQuotaUsage); - } - - if(this.usageHeaders.TryGetValue(headerName, out headerValue)) - { - return headerValue; - } - - return 0; - } - - internal long GetMaxQuotaHeader(string headerName) - { - long headerValue = 0; - if (this.quotaHeaders.Count == 0 && !string.IsNullOrEmpty(this.MaxResourceQuota) && !string.IsNullOrEmpty(this.CurrentResourceQuotaUsage)) - { - this.PopulateQuotaHeader(this.MaxResourceQuota, this.CurrentResourceQuotaUsage); - } - - if(this.quotaHeaders.TryGetValue(headerName, out headerValue)) - { - return headerValue; - } - - return 0; - } - - private void PopulateQuotaHeader(string headerMaxQuota, string headerCurrentUsage) - { - string[] headerMaxQuotaWords = headerMaxQuota.Split(Constants.Quota.DelimiterChars, StringSplitOptions.RemoveEmptyEntries); - string[] headerCurrentUsageWords = headerCurrentUsage.Split(Constants.Quota.DelimiterChars, StringSplitOptions.RemoveEmptyEntries); - - Debug.Assert(headerMaxQuotaWords.Length == headerCurrentUsageWords.Length, "Headers returned should be consistent for max and current usage"); - - for(int i = 0; i < headerMaxQuotaWords.Length; ++i) - { - if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.Database, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.Database, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.Database, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.Collection, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.Collection, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.Collection, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.User, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.User, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.User, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.Permission, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.Permission, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.Permission, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.CollectionSize, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.CollectionSize, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.CollectionSize, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.DocumentsSize, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.DocumentsSize, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.DocumentsSize, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if (string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.DocumentsCount, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.DocumentsCount, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.DocumentsCount, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if (string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.StoredProcedure, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.StoredProcedure, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.StoredProcedure, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.Trigger, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.Trigger, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.Trigger, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - else if(string.Equals( - headerMaxQuotaWords[i], - Constants.Quota.UserDefinedFunction, - StringComparison.OrdinalIgnoreCase)) - { - this.quotaHeaders.Add(Constants.Quota.UserDefinedFunction, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); - this.usageHeaders.Add(Constants.Quota.UserDefinedFunction, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Client +{ + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Net; + using Microsoft.Azure.Documents.Collections; + + /// + /// Represents the non-resource specific service response headers returned by any request in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + abstract class ResourceResponseBase : IResourceResponseBase + { + // Ideally response was intended to be marked as protected(to be accessed by sub-classes) but since DocumentServiceResponse class is marked internal, + // it gives Inconsistent accessibility error saying DocumentServiceResponse is less accessible than field ServiceResponse.response if I mark it as protected. + internal DocumentServiceResponse response; + private Dictionary usageHeaders; + private Dictionary quotaHeaders; + + /// + /// Constructor exposed for mocking purposes for the Azure Cosmos DB service. + /// + public ResourceResponseBase() + { + + } + + internal ResourceResponseBase(DocumentServiceResponse response) + { + this.response = response; + this.usageHeaders = new Dictionary(); + this.quotaHeaders = new Dictionary(); + } + + /// + /// Gets the maximum quota for database resources within the account from the Azure Cosmos DB service. + /// + /// + /// The maximum quota for the account. + /// + public long DatabaseQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.Database); + } + } + + /// + /// Gets the current number of database resources within the account from the Azure Cosmos DB service. + /// + /// + /// The number of databases. + /// + public long DatabaseUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.Database); + } + } + + /// + /// Gets the maximum quota for collection resources within an account from the Azure Cosmos DB service. + /// + /// + /// The maximum quota for the account. + /// + public long CollectionQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.Collection); + } + } + + /// + /// Gets the current number of collection resources within the account from the Azure Cosmos DB service. + /// + /// + /// The number of collections. + /// + public long CollectionUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.Collection); + } + } + + /// + /// Gets the maximum quota for user resources within an account from the Azure Cosmos DB service. + /// + /// + /// The maximum quota for the account. + /// + public long UserQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.User); + } + } + + /// + /// Gets the current number of user resources within the account from the Azure Cosmos DB service. + /// + /// + /// The number of users. + /// + public long UserUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.User); + } + } + + /// + /// Gets the maximum quota for permission resources within an account from the Azure Cosmos DB service. + /// + /// + /// The maximum quota for the account. + /// + public long PermissionQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.Permission); + } + } + + /// + /// Gets the current number of permission resources within the account from the Azure Cosmos DB service. + /// + /// + /// The number of permissions. + /// + public long PermissionUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.Permission); + } + } + + /// + /// Gets the maximum size of a collection in kilobytes from the Azure Cosmos DB service. + /// + /// + /// Quota in kilobytes. + /// + public long CollectionSizeQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.CollectionSize); + } + } + + /// + /// Gets the current size of a collection in kilobytes from the Azure Cosmos DB service. + /// + /// + /// Current collection size in kilobytes. + /// + public long CollectionSizeUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.CollectionSize); + } + } + + /// + /// Gets the maximum size of a documents within a collection in kilobytes from the Azure Cosmos DB service. + /// + /// + /// Quota in kilobytes. + /// + public long DocumentQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.DocumentsSize); + } + } + + /// + /// Gets the current size of documents within a collection in kilobytes from the Azure Cosmos DB service. + /// + /// + /// Current documents size in kilobytes. + /// + public long DocumentUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.DocumentsSize); + } + } + + /// + /// Gets the maximum quota of stored procedures for a collection from the Azure Cosmos DB service. + /// + /// + /// The maximum quota. + /// + public long StoredProceduresQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.StoredProcedure); + } + } + + /// + /// Gets the current number of stored procedures for a collection from the Azure Cosmos DB service. + /// + /// + /// Current number of stored procedures. + /// + public long StoredProceduresUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.StoredProcedure); + } + } + + /// + /// Gets the maximum quota of triggers for a collection from the Azure Cosmos DB service. + /// + /// + /// The maximum quota. + /// + public long TriggersQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.Trigger); + } + } + + /// + /// Gets the current number of triggers for a collection from the Azure Cosmos DB service. + /// + /// + /// Current number of triggers. + /// + public long TriggersUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.Trigger); + } + } + + /// + /// Gets the maximum quota of user defined functions for a collection from the Azure Cosmos DB service. + /// + /// + /// The maximum quota. + /// + public long UserDefinedFunctionsQuota + { + get + { + return this.GetMaxQuotaHeader(Constants.Quota.UserDefinedFunction); + } + } + + /// + /// Gets the current number of user defined functions for a collection from the Azure Cosmos DB service. + /// + /// + /// Current number of user defined functions. + /// + public long UserDefinedFunctionsUsage + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.UserDefinedFunction); + } + } + + /// + /// Gets the current count of documents within a collection from the Azure Cosmos DB service. + /// + /// + /// Current count of documents. + /// + internal long DocumentCount + { + get + { + return this.GetCurrentQuotaHeader(Constants.Quota.DocumentsCount); + } + } + + /// + /// Gets the activity ID for the request from the Azure Cosmos DB service. + /// + /// + /// The activity ID for the request. + /// + public string ActivityId + { + get + { + return this.response.Headers[HttpConstants.HttpHeaders.ActivityId]; + } + } + + /// + /// Gets the session token for use in sesssion consistency reads from the Azure Cosmos DB service. + /// + /// + /// The session token for use in session consistency. + /// + public string SessionToken + { + get + { + return this.response.Headers[HttpConstants.HttpHeaders.SessionToken]; + } + } + + /// + /// Gets the HTTP status code associated with the response from the Azure Cosmos DB service. + /// + /// + /// The HTTP status code associated with the response. + /// + public HttpStatusCode StatusCode + { + get + { + return this.response.StatusCode; + } + } + + /// + /// Gets the maximum size limit for this entity from the Azure Cosmos DB service. + /// + /// + /// The maximum size limit for this entity. Measured in kilobytes for document resources + /// and in counts for other resources. + /// + public string MaxResourceQuota + { + get + { + return this.response.Headers[HttpConstants.HttpHeaders.MaxResourceQuota]; + } + } + + /// + /// Gets the current size of this entity from the Azure Cosmos DB service. + /// + /// + /// The current size for this entity. Measured in kilobytes for document resources + /// and in counts for other resources. + /// + public string CurrentResourceQuotaUsage + { + get + { + return this.response.Headers[HttpConstants.HttpHeaders.CurrentResourceQuotaUsage]; + } + } + + /// + /// Gets the underlying stream of the response from the Azure Cosmos DB service. + /// + public Stream ResponseStream + { + get + { + return this.response.ResponseBody; + } + } + + /// + /// Gets the request charge for this request from the Azure Cosmos DB service. + /// + /// + /// The request charge measured in reqest units. + /// + public double RequestCharge + { + get + { + return Helpers.GetHeaderValueDouble( + this.response.Headers, + HttpConstants.HttpHeaders.RequestCharge, + 0); + } + } + + /// + /// Gets the flag associated with the response from the Azure Cosmos DB service whether this request is served from Request Units(RUs)/minute capacity or not. + /// + /// + /// True if this request is served from RUs/minute capacity. Otherwise, false. + /// + public bool IsRUPerMinuteUsed + { + get + { + if (Helpers.GetHeaderValueByte(this.response.Headers, HttpConstants.HttpHeaders.IsRUPerMinuteUsed, 0) != 0) + { + return true; + } + + return false; + } + } + + /// + /// Gets the response headers from the Azure Cosmos DB service. + /// + /// + /// The response headers. + /// + public NameValueCollection ResponseHeaders + { + get + { + return this.response.ResponseHeaders; + } + } + + internal INameValueCollection Headers + { + get { return this.response.Headers; } + } + + /// + /// The content parent location, for example, dbs/foo/colls/bar in the Azure Cosmos DB service. + /// + public string ContentLocation + { + get + { + return this.response.Headers[HttpConstants.HttpHeaders.OwnerFullName]; + } + } + + /// + /// Gets the progress of an index transformation, if one is underway from the Azure Cosmos DB service. + /// + /// + /// An integer from 0 to 100 representing percentage completion of the index transformation process. + /// Returns -1 if the index transformation progress header could not be found. + /// + /// + /// An index will be rebuilt when the IndexPolicy of a collection is updated. + /// + public long IndexTransformationProgress + { + get + { + return Helpers.GetHeaderValueLong(this.response.Headers, HttpConstants.HttpHeaders.CollectionIndexTransformationProgress); + } + } + + /// + /// Gets the progress of lazy indexing from the Azure Cosmos DB service. + /// + /// + /// An integer from 0 to 100 representing percentage completion of the lazy indexing process. + /// Returns -1 if the lazy indexing progress header could not be found. + /// + /// + /// Lazy indexing progress only applies to the collection with indexing mode Lazy. + /// + public long LazyIndexingProgress + { + get + { + return Helpers.GetHeaderValueLong(this.response.Headers, HttpConstants.HttpHeaders.CollectionLazyIndexingProgress); + } + } + + /// + /// Gets the end-to-end request latency for the current request to Azure Cosmos DB service. + /// + /// + /// This field is only valid when the request uses direct connectivity. + /// + public TimeSpan RequestLatency + { + get + { + if (this.response.RequestStats == null || + !this.response.RequestStats.RequestLatency.HasValue) + { + return TimeSpan.Zero; + } + + return this.response.RequestStats.RequestLatency.Value; + } + } + + /// + /// Gets the diagnostics information for the current request to Azure Cosmos DB service. + /// + /// + /// This field is only valid when the request uses direct connectivity. + /// + public string RequestDiagnosticsString + { + get + { + if (this.response.RequestStats == null) + { + return string.Empty; + } + + return this.response.RequestStats.ToString(); + } + } + + /// + /// Gets the request statistics for the current request to Azure Cosmos DB service. + /// + /// + /// This field is only valid when the request uses direct connectivity. + /// + internal IClientSideRequestStatistics RequestStatistics + { + get + { + return this.response.RequestStats; + } + } + + internal long GetCurrentQuotaHeader(string headerName) + { + long headerValue = 0; + if (this.usageHeaders.Count == 0 && !string.IsNullOrEmpty(this.MaxResourceQuota) && !string.IsNullOrEmpty(this.CurrentResourceQuotaUsage)) + { + this.PopulateQuotaHeader(this.MaxResourceQuota, this.CurrentResourceQuotaUsage); + } + + if(this.usageHeaders.TryGetValue(headerName, out headerValue)) + { + return headerValue; + } + + return 0; + } + + internal long GetMaxQuotaHeader(string headerName) + { + long headerValue = 0; + if (this.quotaHeaders.Count == 0 && !string.IsNullOrEmpty(this.MaxResourceQuota) && !string.IsNullOrEmpty(this.CurrentResourceQuotaUsage)) + { + this.PopulateQuotaHeader(this.MaxResourceQuota, this.CurrentResourceQuotaUsage); + } + + if(this.quotaHeaders.TryGetValue(headerName, out headerValue)) + { + return headerValue; + } + + return 0; + } + + private void PopulateQuotaHeader(string headerMaxQuota, string headerCurrentUsage) + { + string[] headerMaxQuotaWords = headerMaxQuota.Split(Constants.Quota.DelimiterChars, StringSplitOptions.RemoveEmptyEntries); + string[] headerCurrentUsageWords = headerCurrentUsage.Split(Constants.Quota.DelimiterChars, StringSplitOptions.RemoveEmptyEntries); + + Debug.Assert(headerMaxQuotaWords.Length == headerCurrentUsageWords.Length, "Headers returned should be consistent for max and current usage"); + + for(int i = 0; i < headerMaxQuotaWords.Length; ++i) + { + if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.Database, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.Database, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.Database, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.Collection, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.Collection, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.Collection, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.User, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.User, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.User, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.Permission, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.Permission, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.Permission, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.CollectionSize, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.CollectionSize, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.CollectionSize, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.DocumentsSize, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.DocumentsSize, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.DocumentsSize, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if (string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.DocumentsCount, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.DocumentsCount, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.DocumentsCount, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if (string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.StoredProcedure, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.StoredProcedure, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.StoredProcedure, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.Trigger, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.Trigger, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.Trigger, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + else if(string.Equals( + headerMaxQuotaWords[i], + Constants.Quota.UserDefinedFunction, + StringComparison.OrdinalIgnoreCase)) + { + this.quotaHeaders.Add(Constants.Quota.UserDefinedFunction, long.Parse(headerMaxQuotaWords[i + 1], CultureInfo.InvariantCulture)); + this.usageHeaders.Add(Constants.Quota.UserDefinedFunction, long.Parse(headerCurrentUsageWords[i + 1], CultureInfo.InvariantCulture)); + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ResourceType.cs b/Microsoft.Azure.Cosmos/src/direct/ResourceType.cs index f1c0991d79..c8c2c2d133 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ResourceType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ResourceType.cs @@ -1,144 +1,144 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - - internal enum ResourceType : int - { - // Keep in sync with ResourceType enum in backend native. - Unknown = -1, - Database = 0, - Collection = 1, - Document = 2, - Attachment = 3, - User = 4, - Permission = 5, -#if !COSMOSCLIENT - Progress = 6, - Replica = 7, - Tombstone = 8, - Module = 9, - SmallMaxInvalid = 10, - LargeInvalid = 100, - ModuleCommand = 103, - Index = 104, - IndexBookmark = 105, - IndexSize = 106, -#endif - Conflict = 107, - Record = 108, - StoredProcedure = 109, - Trigger = 110, - UserDefinedFunction = 111, - BatchApply = 112, - Offer = 113, -#if !COSMOSCLIENT - PartitionSetInformation = 114, - XPReplicatorAddress = 115, - Timestamp = 117, -#endif - DatabaseAccount = 118, -#if !COSMOSCLIENT - MasterPartition = 120, - ServerPartition = 121, - Topology = 122, -#endif - SchemaContainer = 123, - Schema = 124, - PartitionKeyRange = 125, -#if !COSMOSCLIENT - LogStoreLogs = 126, - RestoreMetadata = 127, - PreviousImage = 128, - VectorClock = 129, - RidRange = 130, -#endif - ComputeGatewayCharges = 131, - UserDefinedType = 133, - Batch = 135, - PartitionKey = 136, - Snapshot = 137, - PartitionedSystemDocument = 138, - - ClientEncryptionKey = 141, - Transaction = 145, - - RoleDefinition = 146, - RoleAssignment = 147, - SystemDocument = 148, - InteropUser = 149, - AuthPolicyElement = 150, - -#if !COSMOSCLIENT - TransportControlCommand = 151, - StorageAuthToken = 152, -#endif - - RetriableWriteCachedResponse = 153, - - EncryptionScope = 156, - - // These names make it unclear what they map to in ResourceType. - Key = -2, - Media = -3, -#if !COSMOSCLIENT - ServiceFabricService = -4, -#endif - Address = -5, - ControllerService = -6, - Telemetry = 1001 - } - - internal static class ResourceTypeExtensions - { - private static Dictionary resourceTypeNames = new Dictionary(); - - static ResourceTypeExtensions() - { - foreach (ResourceType type in Enum.GetValues(typeof(ResourceType))) - { - ResourceTypeExtensions.resourceTypeNames[(int)type] = type.ToString(); - } - } - - public static string ToResourceTypeString(this ResourceType type) - { - return ResourceTypeExtensions.resourceTypeNames[(int)type]; - } - - /// - /// Resources for which this method returns true, are spread between multiple - /// partitions. - /// - public static bool IsPartitioned(this ResourceType type) - { - return type == ResourceType.Document || - type == ResourceType.Attachment || - type == ResourceType.Conflict || - type == ResourceType.PartitionKey || - type == ResourceType.PartitionedSystemDocument || - type == ResourceType.RetriableWriteCachedResponse; - } - - public static bool IsCollectionChild(this ResourceType type) - { - return type == ResourceType.Document || - type == ResourceType.Attachment || - type == ResourceType.Conflict || - type == ResourceType.Schema || - type == ResourceType.PartitionKey || - type == ResourceType.PartitionedSystemDocument || - type == ResourceType.SystemDocument || - type.IsScript(); - } - - public static bool IsScript(this ResourceType type) - { - return type == ResourceType.UserDefinedFunction || type == ResourceType.Trigger || type == ResourceType.StoredProcedure; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + + internal enum ResourceType : int + { + // Keep in sync with ResourceType enum in backend native. + Unknown = -1, + Database = 0, + Collection = 1, + Document = 2, + Attachment = 3, + User = 4, + Permission = 5, +#if !COSMOSCLIENT + Progress = 6, + Replica = 7, + Tombstone = 8, + Module = 9, + SmallMaxInvalid = 10, + LargeInvalid = 100, + ModuleCommand = 103, + Index = 104, + IndexBookmark = 105, + IndexSize = 106, +#endif + Conflict = 107, + Record = 108, + StoredProcedure = 109, + Trigger = 110, + UserDefinedFunction = 111, + BatchApply = 112, + Offer = 113, +#if !COSMOSCLIENT + PartitionSetInformation = 114, + XPReplicatorAddress = 115, + Timestamp = 117, +#endif + DatabaseAccount = 118, +#if !COSMOSCLIENT + MasterPartition = 120, + ServerPartition = 121, + Topology = 122, +#endif + SchemaContainer = 123, + Schema = 124, + PartitionKeyRange = 125, +#if !COSMOSCLIENT + LogStoreLogs = 126, + RestoreMetadata = 127, + PreviousImage = 128, + VectorClock = 129, + RidRange = 130, +#endif + ComputeGatewayCharges = 131, + UserDefinedType = 133, + Batch = 135, + PartitionKey = 136, + Snapshot = 137, + PartitionedSystemDocument = 138, + + ClientEncryptionKey = 141, + Transaction = 145, + + RoleDefinition = 146, + RoleAssignment = 147, + SystemDocument = 148, + InteropUser = 149, + AuthPolicyElement = 150, + +#if !COSMOSCLIENT + TransportControlCommand = 151, + StorageAuthToken = 152, +#endif + + RetriableWriteCachedResponse = 153, + + EncryptionScope = 156, + + // These names make it unclear what they map to in ResourceType. + Key = -2, + Media = -3, +#if !COSMOSCLIENT + ServiceFabricService = -4, +#endif + Address = -5, + ControllerService = -6, + Telemetry = 1001 + } + + internal static class ResourceTypeExtensions + { + private static Dictionary resourceTypeNames = new Dictionary(); + + static ResourceTypeExtensions() + { + foreach (ResourceType type in Enum.GetValues(typeof(ResourceType))) + { + ResourceTypeExtensions.resourceTypeNames[(int)type] = type.ToString(); + } + } + + public static string ToResourceTypeString(this ResourceType type) + { + return ResourceTypeExtensions.resourceTypeNames[(int)type]; + } + + /// + /// Resources for which this method returns true, are spread between multiple + /// partitions. + /// + public static bool IsPartitioned(this ResourceType type) + { + return type == ResourceType.Document || + type == ResourceType.Attachment || + type == ResourceType.Conflict || + type == ResourceType.PartitionKey || + type == ResourceType.PartitionedSystemDocument || + type == ResourceType.RetriableWriteCachedResponse; + } + + public static bool IsCollectionChild(this ResourceType type) + { + return type == ResourceType.Document || + type == ResourceType.Attachment || + type == ResourceType.Conflict || + type == ResourceType.Schema || + type == ResourceType.PartitionKey || + type == ResourceType.PartitionedSystemDocument || + type == ResourceType.SystemDocument || + type.IsScript(); + } + + public static bool IsScript(this ResourceType type) + { + return type == ResourceType.UserDefinedFunction || type == ResourceType.Trigger || type == ResourceType.StoredProcedure; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RetryWithException.cs b/Microsoft.Azure.Cosmos/src/direct/RetryWithException.cs index 16ced456b8..9ab6be59b6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RetryWithException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RetryWithException.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class RetryWithException : DocumentClientException - { - public RetryWithException(string retryMessage) - : this(retryMessage, (INameValueCollection)null) - { - - } - - public RetryWithException(Exception innerException) - : base( - RMResources.RetryWith, - innerException, - responseHeaders: (HttpResponseHeaders)null, - statusCode: (HttpStatusCode)StatusCodes.RetryWith) - { - } - - public RetryWithException(string retryMessage, HttpResponseHeaders headers, Uri requestUri = null) - : base(retryMessage, null, headers, (HttpStatusCode)StatusCodes.RetryWith, requestUri) - { - SetDescription(); - } - - public RetryWithException(string retryMessage, INameValueCollection headers, Uri requestUri = null) - : base(retryMessage, null, headers, (HttpStatusCode)StatusCodes.RetryWith, requestUri) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private RetryWithException(SerializationInfo info, StreamingContext context) - : base(info, context, (HttpStatusCode)StatusCodes.RetryWith) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.RetryWith; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class RetryWithException : DocumentClientException + { + public RetryWithException(string retryMessage) + : this(retryMessage, (INameValueCollection)null) + { + + } + + public RetryWithException(Exception innerException) + : base( + RMResources.RetryWith, + innerException, + responseHeaders: (HttpResponseHeaders)null, + statusCode: (HttpStatusCode)StatusCodes.RetryWith) + { + } + + public RetryWithException(string retryMessage, HttpResponseHeaders headers, Uri requestUri = null) + : base(retryMessage, null, headers, (HttpStatusCode)StatusCodes.RetryWith, requestUri) + { + SetDescription(); + } + + public RetryWithException(string retryMessage, INameValueCollection headers, Uri requestUri = null) + : base(retryMessage, null, headers, (HttpStatusCode)StatusCodes.RetryWith, requestUri) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private RetryWithException(SerializationInfo info, StreamingContext context) + : base(info, context, (HttpStatusCode)StatusCodes.RetryWith) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.RetryWith; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Rfc1123DateTimeCache.cs b/Microsoft.Azure.Cosmos/src/direct/Rfc1123DateTimeCache.cs index adf1831511..bbf8814eec 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Rfc1123DateTimeCache.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Rfc1123DateTimeCache.cs @@ -1,71 +1,71 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Threading; - - /// - /// Cache which keeps a copy of the current time formatted in RFC1123 (that is, ToString("r")-style) - /// available. - /// - internal static class Rfc1123DateTimeCache - { - private static FormattedTriple Current = new FormattedTriple(DateTime.UtcNow); - private static long Timestamp = Stopwatch.GetTimestamp(); - - /// - /// Approximates DateTime.UtcNow using a cache instance updated once a second. - /// - internal static DateTime Raw() => GetCacheFormattedTriple().Date; - - /// - /// Equivalent to DateTime.UtcNow.ToString("r"), but re-uses a cached instance. - /// - internal static string UtcNow() => GetCacheFormattedTriple().Formatted; - - private static FormattedTriple GetCacheFormattedTriple() - { - FormattedTriple snapshot = Volatile.Read(ref Current); - long nowTimestamp = Stopwatch.GetTimestamp(); - long delta = nowTimestamp - Volatile.Read(ref Timestamp); - - // Frequency == ticks per second, so this is equivalent to >= 1s - if (delta >= Stopwatch.Frequency) - { - FormattedTriple candidate = new FormattedTriple(DateTime.UtcNow); - FormattedTriple updatedSnapshot = Interlocked.CompareExchange(ref Current, candidate, snapshot); - if (updatedSnapshot == snapshot) - { - Volatile.Write(ref Timestamp, nowTimestamp); - // this means we replaced Current, so return our new one - return candidate; - } - // we failed to replace Current, because somebody else did - return what they shoved up there - return updatedSnapshot; - } - else - { - // current cache value is still good - return snapshot; - } - } - - /// -        /// Triple of a DateTime, it's RFC1123 equivalent, and it's .ToLowerInvariant() RFC1123 equivalent. -        /// -        private sealed class FormattedTriple - { - internal string Formatted { get; } - internal DateTime Date { get; } - internal FormattedTriple(DateTime date) - { - this.Date = date; - this.Formatted = date.ToString("r"); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Threading; + + /// + /// Cache which keeps a copy of the current time formatted in RFC1123 (that is, ToString("r")-style) + /// available. + /// + internal static class Rfc1123DateTimeCache + { + private static FormattedTriple Current = new FormattedTriple(DateTime.UtcNow); + private static long Timestamp = Stopwatch.GetTimestamp(); + + /// + /// Approximates DateTime.UtcNow using a cache instance updated once a second. + /// + internal static DateTime Raw() => GetCacheFormattedTriple().Date; + + /// + /// Equivalent to DateTime.UtcNow.ToString("r"), but re-uses a cached instance. + /// + internal static string UtcNow() => GetCacheFormattedTriple().Formatted; + + private static FormattedTriple GetCacheFormattedTriple() + { + FormattedTriple snapshot = Volatile.Read(ref Current); + long nowTimestamp = Stopwatch.GetTimestamp(); + long delta = nowTimestamp - Volatile.Read(ref Timestamp); + + // Frequency == ticks per second, so this is equivalent to >= 1s + if (delta >= Stopwatch.Frequency) + { + FormattedTriple candidate = new FormattedTriple(DateTime.UtcNow); + FormattedTriple updatedSnapshot = Interlocked.CompareExchange(ref Current, candidate, snapshot); + if (updatedSnapshot == snapshot) + { + Volatile.Write(ref Timestamp, nowTimestamp); + // this means we replaced Current, so return our new one + return candidate; + } + // we failed to replace Current, because somebody else did - return what they shoved up there + return updatedSnapshot; + } + else + { + // current cache value is still good + return snapshot; + } + } + + /// +        /// Triple of a DateTime, it's RFC1123 equivalent, and it's .ToLowerInvariant() RFC1123 equivalent. +        /// +        private sealed class FormattedTriple + { + internal string Formatted { get; } + internal DateTime Date { get; } + internal FormattedTriple(DateTime date) + { + this.Date = date; + this.Formatted = date.ToString("r"); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs index 64ead265bc..8888b47c23 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs @@ -1,1299 +1,1318 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RntbdConstants.tt -// This allows the RntbdTokenStreams to be correctly ordered and optimized. -// If you need to add a new RntbdToken to any of the existing types, please do it on the RntbdConstants.tt file - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - - /// - /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RntbdConstants.tt - /// This allows the RntbdTokenStreams to be correctly ordered and optimized. - /// If you need to add a new RntbdToken to any of the existing types, do it on the RntbdConstants.tt file - /// - internal static class RntbdConstants - { - public const UInt32 CurrentProtocolVersion = 0x00000001; - - public enum RntbdResourceType : ushort - { - Connection = 0x0000, - Database = 0x0001, - Collection = 0x0002, - Document = 0x0003, - Attachment = 0x0004, - User = 0x0005, - Permission = 0x0006, - StoredProcedure = 0x0007, - Conflict = 0x0008, - Trigger = 0x0009, - UserDefinedFunction = 0x000A, - Module = 0x000B, - Replica = 0x000C, - ModuleCommand = 0x000D, - Record = 0x000E, - Offer = 0x000F, - PartitionSetInformation = 0x0010, - XPReplicatorAddress = 0x0011, - MasterPartition = 0x0012, - ServerPartition = 0x0013, - DatabaseAccount = 0x0014, - Topology = 0x0015, - PartitionKeyRange = 0x0016, - // not used = 0x0017, timestamp - Schema = 0x0018, - BatchApply = 0x0019, - RestoreMetadata = 0x001A, - ComputeGatewayCharges = 0x001B, - RidRange = 0x001C, - UserDefinedType = 0x001D, - VectorClock = 0x001F, - PartitionKey = 0x0020, - Snapshot = 0x0021, - ClientEncryptionKey = 0x0023, - Transaction = 0x0025, - PartitionedSystemDocument = 0x0026, - RoleDefinition = 0x0027, - RoleAssignment = 0x0028, - SystemDocument = 0x0029, - InteropUser = 0x002A, - TransportControlCommand = 0x002B, - AuthPolicyElement = 0x002C, - StorageAuthToken = 0x002D, - RetriableWriteCachedResponse = 0x002E, - EncryptionScope = 0x0030, - } - - public enum RntbdOperationType : ushort - { - Connection = 0x0000, - Create = 0x0001, - Patch = 0x0002, - Read = 0x0003, - ReadFeed = 0x0004, - Delete = 0x0005, - Replace = 0x0006, - // Deprecated and should not be used JPathQuery = 0x0007, - ExecuteJavaScript = 0x0008, - SQLQuery = 0x0009, - Pause = 0x000A, - Resume = 0x000B, - Stop = 0x000C, - Recycle = 0x000D, - Crash = 0x000E, - Query = 0x000F, - ForceConfigRefresh = 0x0010, - Head = 0x0011, - HeadFeed = 0x0012, - Upsert = 0x0013, - Recreate = 0x0014, - Throttle = 0x0015, - GetSplitPoint = 0x0016, - PreCreateValidation = 0x0017, - BatchApply = 0x0018, - AbortSplit = 0x0019, - CompleteSplit = 0x001A, - OfferUpdateOperation = 0x001B, - OfferPreGrowValidation = 0x001C, - BatchReportThroughputUtilization = 0x001D, - CompletePartitionMigration = 0x001E, - AbortPartitionMigration = 0x001F, - PreReplaceValidation = 0x0020, - AddComputeGatewayRequestCharges = 0x0021, - MigratePartition = 0x0022, - MasterReplaceOfferOperation = 0x023, - ProvisionedCollectionOfferUpdateOperation = 0x024, - Batch = 0x025, - InitiateDatabaseOfferPartitionShrink = 0x026, - CompleteDatabaseOfferPartitionShrink = 0x027, - EnsureSnapshotOperation = 0x028, - GetSplitPoints = 0x0029, - CompleteMergeOnTarget = 0x002A, - CompleteMergeOnMaster = 0x002C, - ForcePartitionBackup = 0x002E, - CompleteUserTransaction = 0x002F, - MasterInitiatedProgressCoordination = 0x0030, - MetadataCheckAccess = 0x0031, - CreateSystemSnapshot = 0x0032, - UpdateFailoverPriorityList = 0x0033, - GetStorageAuthToken = 0x0034, - UpdatePartitionThroughput = 0x0035, - CreateRidRangeResources = 0x0036, - Truncate = 0x0037, - } - - public enum ConnectionContextRequestTokenIdentifiers : ushort - { - ProtocolVersion = 0x0000, - ClientVersion = 0x0001, - UserAgent = 0x0002, - CallerId = 0x0003, - EnableChannelMultiplexing = 0x0004, - } - - public sealed class ConnectionContextRequest : RntbdTokenStream - { - public override int RequiredTokenCount => 3; - - public RntbdToken protocolVersion; - public RntbdToken clientVersion; - public RntbdToken userAgent; - public RntbdToken callerId; - public RntbdToken enableChannelMultiplexing; - - public ConnectionContextRequest() - { - this.protocolVersion = new RntbdToken(true, RntbdTokenTypes.ULong, (ushort)ConnectionContextRequestTokenIdentifiers.ProtocolVersion); - this.clientVersion = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextRequestTokenIdentifiers.ClientVersion); - this.userAgent = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextRequestTokenIdentifiers.UserAgent); - this.callerId = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)ConnectionContextRequestTokenIdentifiers.CallerId); - this.enableChannelMultiplexing = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)ConnectionContextRequestTokenIdentifiers.EnableChannelMultiplexing); - - this.tokens = new RntbdToken[] - { - this.protocolVersion, - this.clientVersion, - this.userAgent, - this.callerId, - this.enableChannelMultiplexing, - }; - } - } - - public enum ConnectionContextResponseTokenIdentifiers : ushort - { - ProtocolVersion = 0x0000, - ClientVersion = 0x0001, - ServerAgent = 0x0002, - ServerVersion = 0x0003, - IdleTimeoutInSeconds = 0x0004, - UnauthenticatedTimeoutInSeconds = 0x0005, - } - - public sealed class ConnectionContextResponse : RntbdTokenStream - { - public override int RequiredTokenCount => 2; - - public RntbdToken protocolVersion; - public RntbdToken clientVersion; - public RntbdToken serverAgent; - public RntbdToken serverVersion; - public RntbdToken idleTimeoutInSeconds; - public RntbdToken unauthenticatedTimeoutInSeconds; - - public ConnectionContextResponse() - { - this.protocolVersion = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.ProtocolVersion); - this.clientVersion = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ClientVersion); - this.serverAgent = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ServerAgent); - this.serverVersion = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ServerVersion); - this.idleTimeoutInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.IdleTimeoutInSeconds); - this.unauthenticatedTimeoutInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.UnauthenticatedTimeoutInSeconds); - - this.tokens = new RntbdToken[] - { - this.protocolVersion, - this.clientVersion, - this.serverAgent, - this.serverVersion, - this.idleTimeoutInSeconds, - this.unauthenticatedTimeoutInSeconds, - }; - } - } - - public enum RntbdIndexingDirective : byte - { - Default = 0x00, - Include = 0x01, - Exclude = 0x02, - - Invalid = 0xFF, - } - - public enum RntbdMigrateCollectionDirective : byte - { - Thaw = 0x00, - Freeze = 0x01, - - Invalid = 0xFF, - } - - public enum RntbdRemoteStorageType : byte - { - Invalid = 0x00, - NotSpecified = 0x01, - Standard = 0x02, - Premium = 0x03, - } - - public enum RntbdConsistencyLevel : byte - { - Strong = 0x00, - BoundedStaleness = 0x01, - Session = 0x02, - Eventual = 0x03, - ConsistentPrefix = 0x04, - - Invalid = 0xFF, - } - - public enum RntdbEnumerationDirection : byte - { - Invalid = 0x00, - Forward = 0x01, - Reverse = 0x02, - } - - public enum RntbdFanoutOperationState : byte - { - Started = 0x01, - Completed = 0x02, - } - - public enum RntdbReadFeedKeyType : byte - { - Invalid = 0x00, - ResourceId = 0x01, - EffectivePartitionKey = 0x02, - EffectivePartitionKeyRange = 0x03, - } - - public enum RntbdContentSerializationFormat : byte - { - JsonText = 0x00, - CosmosBinary = 0x01, - HybridRow = 0x02, - - Invalid = 0xFF, - } - - [Flags] - public enum RntbdSupportedSerializationFormats : byte - { - None = 0x00, - JsonText = 0x01, - CosmosBinary = 0x02, - HybridRow = 0x04, - } - - public enum RntbdSystemDocumentType : byte - { - PartitionKey = 0x00, - MaterializedViewLeaseDocument = 0x01, - MaterializedViewBuilderOwnershipDocument = 0x02, - MaterializedViewLeaseStoreInitDocument = 0x03, - - Invalid = 0xFF, - } - - public enum RntbdRequestedCollectionType : byte - { - All = 0x00, - Standard = 0x01, - MaterializedView = 0x02, - } - - public enum RntbdPriorityLevel : byte - { - High = 0x01, - Low = 0x02, - } - - public enum RequestIdentifiers : ushort - { - ResourceId = 0x0000, - AuthorizationToken = 0x0001, - PayloadPresent = 0x0002, - Date = 0x0003, - PageSize = 0x0004, - SessionToken = 0x0005, - ContinuationToken = 0x0006, - IndexingDirective = 0x0007, - Match = 0x0008, - PreTriggerInclude = 0x0009, - PostTriggerInclude = 0x000A, - IsFanout = 0x000B, - CollectionPartitionIndex = 0x000C, - CollectionServiceIndex = 0x000D, - PreTriggerExclude = 0x000E, - PostTriggerExclude = 0x000F, - ConsistencyLevel = 0x0010, - EntityId = 0x0011, - ResourceSchemaName = 0x0012, - ReplicaPath = 0x0013, - ResourceTokenExpiry = 0x0014, - DatabaseName = 0x0015, - CollectionName = 0x0016, - DocumentName = 0x0017, - AttachmentName = 0x0018, - UserName = 0x0019, - PermissionName = 0x001A, - StoredProcedureName = 0x001B, - UserDefinedFunctionName = 0x001C, - TriggerName = 0x001D, - EnableScanInQuery = 0x001E, - EmitVerboseTracesInQuery = 0x001F, - ConflictName = 0x0020, - BindReplicaDirective = 0x0021, - PrimaryMasterKey = 0x0022, - SecondaryMasterKey = 0x0023, - PrimaryReadonlyKey = 0x0024, - SecondaryReadonlyKey = 0x0025, - ProfileRequest = 0x0026, - EnableLowPrecisionOrderBy = 0x0027, - ClientVersion = 0x0028, - CanCharge = 0x0029, - CanThrottle = 0x002A, - PartitionKey = 0x002B, - PartitionKeyRangeId = 0x002C, - MigrateCollectionDirective = 0x0031, - SupportSpatialLegacyCoordinates = 0x0033, - PartitionCount = 0x0034, - CollectionRid = 0x0035, - PartitionKeyRangeName = 0x0036, - SchemaName = 0x003A, - FilterBySchemaRid = 0x003B, - UsePolygonsSmallerThanAHemisphere = 0x003C, - GatewaySignature = 0x003D, - EnableLogging = 0x003E, - A_IM = 0x003F, - PopulateQuotaInfo = 0x0040, - DisableRUPerMinuteUsage = 0x0041, - PopulateQueryMetrics = 0x0042, - ResponseContinuationTokenLimitInKb = 0x0043, - PopulatePartitionStatistics = 0x0044, - RemoteStorageType = 0x0045, - CollectionRemoteStorageSecurityIdentifier = 0x0046, - IfModifiedSince = 0x0047, - PopulateCollectionThroughputInfo = 0x0048, - RemainingTimeInMsOnClientRequest = 0x0049, - ClientRetryAttemptCount = 0x004A, - TargetLsn = 0x004B, - TargetGlobalCommittedLsn = 0x004C, - TransportRequestID = 0x004D, - RestoreMetadataFilter = 0x004E, - RestoreParams = 0x004F, - ShareThroughput = 0x0050, - PartitionResourceFilter = 0x0051, - IsReadOnlyScript = 0x0052, - IsAutoScaleRequest = 0x0053, - ForceQueryScan = 0x0054, - CanOfferReplaceComplete = 0x0056, - ExcludeSystemProperties = 0x0057, - BinaryId = 0x0058, - TimeToLiveInSeconds = 0x0059, - EffectivePartitionKey = 0x005A, - BinaryPassthroughRequest = 0x005B, - UserDefinedTypeName = 0x005C, - EnableDynamicRidRangeAllocation = 0x005D, - EnumerationDirection = 0x005E, - StartId = 0x005F, - EndId = 0x0060, - FanoutOperationState = 0x0061, - StartEpk = 0x0062, - EndEpk = 0x0063, - ReadFeedKeyType = 0x0064, - ContentSerializationFormat = 0x0065, - AllowTentativeWrites = 0x0066, - IsUserRequest = 0x0067, - PreserveFullContent = 0x0069, - IncludeTentativeWrites = 0x0070, - PopulateResourceCount = 0x0071, - MergeStaticId = 0x0072, - IsBatchAtomic = 0x0073, - ShouldBatchContinueOnError = 0x0074, - IsBatchOrdered = 0x0075, - SchemaOwnerRid = 0x0076, - SchemaHash = 0x0077, - IsRUPerGBEnforcementRequest = 0x0078, - MaxPollingIntervalMilliseconds = 0x0079, - SnapshotName = 0x007A, - PopulateLogStoreInfo = 0x007B, - GetAllPartitionKeyStatistics = 0x007C, - ForceSideBySideIndexMigration = 0x007D, - CollectionChildResourceNameLimitInBytes = 0x007E, - CollectionChildResourceContentLengthLimitInKB = 0x007F, - ClientEncryptionKeyName = 0x0080, - MergeCheckpointGLSNKeyName = 0x0081, - ReturnPreference = 0x0082, - UniqueIndexNameEncodingMode = 0x0083, - PopulateUnflushedMergeEntryCount = 0x0084, - MigrateOfferToManualThroughput = 0x0085, - MigrateOfferToAutopilot = 0x0086, - IsClientEncrypted = 0x0087, - SystemDocumentType = 0x0088, - IsofferStorageRefreshRequest = 0x0089, - ResourceTypes = 0x008A, - TransactionId = 0x008B, - TransactionFirstRequest = 0x008C, - TransactionCommit = 0x008D, - SystemDocumentName = 0x008E, - UpdateMaxThroughputEverProvisioned = 0x008F, - UniqueIndexReIndexingState = 0x0090, - RoleDefinitionName = 0x0091, - RoleAssignmentName = 0x0092, - UseSystemBudget = 0x0093, - IgnoreSystemLoweringMaxThroughput = 0x0094, - TruncateMergeLogRequest = 0x0095, - RetriableWriteRequestId = 0x0096, - IsRetriedWriteRequest = 0x0097, - RetriableWriteRequestStartTimestamp = 0x0098, - AddResourcePropertiesToResponse = 0x0099, - ChangeFeedStartFullFidelityIfNoneMatch = 0x009A, - SystemRestoreOperation = 0x009B, - SkipRefreshDatabaseAccountConfigs = 0x009C, - IntendedCollectionRid = 0x009D, - UseArchivalPartition = 0x009E, - PopulateUniqueIndexReIndexProgress = 0x009F, - CollectionSchemaId = 0x00A0, - CollectionTruncate = 0x00A1, - SDKSupportedCapabilities = 0x00A2, - IsMaterializedViewBuild = 0x00A3, - BuilderClientIdentifier = 0x00A4, - SourceCollectionIfMatch = 0x00A5, - RequestedCollectionType = 0x00A6, - InteropUserName = 0x00A8, - PopulateIndexMetrics = 0x00A9, - PopulateAnalyticalMigrationProgress = 0x00AA, - AuthPolicyElementName = 0x00AB, - ShouldReturnCurrentServerDateTime = 0x00AC, - RbacUserId = 0x00AD, - RbacAction = 0x00AE, - RbacResource = 0x00AF, - CorrelatedActivityId = 0x00B0, - IsThroughputCapRequest = 0x00B1, - ChangeFeedWireFormatVersion = 0x00B2, - PopulateBYOKEncryptionProgress = 0x00B3, - UseUserBackgroundBudget = 0x00B4, - IncludePhysicalPartitionThroughputInfo = 0x00B5, - IsServerlessStorageRefreshRequest = 0x00B6, - UpdateOfferStateToPending = 0x00B7, - PopulateOldestActiveSchemaId = 0x00B8, - IsInternalServerlessRequest = 0x00B9, - OfferReplaceRURedistribution = 0x00BA, - IsCassandraAlterTypeRequest = 0x00BB, - IsMaterializedViewSourceSchemaReplaceBatchRequest = 0x00BC, - ForceDatabaseAccountUpdate = 0x00BD, - EncryptionScopeName = 0x00BE, - PriorityLevel = 0x00BF, - AllowRestoreParamsUpdate = 0x00C0, - PruneCollectionSchemas = 0x00C1, - PopulateIndexMetricsV2 = 0x00C2, - IsMigratedFixedCollection = 0x00C3, - SupportedSerializationFormats = 0x00C4, - UpdateOfferStateToRestorePending = 0x00C5, - SetMasterResourcesDeletionPending = 0x00C6, - HighPriorityForcedBackup = 0x00C7, - OptimisticDirectExecute = 0x00C8, - PopulateMinGLSNForDocumentOperations = 0x00C9, - PopulateHighestTentativeWriteLLSN = 0x00CA, - PopulateCapacityType = 0x00CB, - TraceParent = 0x00CC, - TraceState = 0x00CD, - GlobalDatabaseAccountName = 0x00CE, - EnableConflictResolutionPolicyUpdate = 0x00CF, - ClientIpAddress = 0x00D0, - IsRequestNotAuthorized = 0x00D1, - StartEpkHash = 0x00D2, - EndEpkHash = 0x00D3, - AllowDocumentReadsInOfflineRegion = 0x00D4, - PopulateCurrentPartitionThroughputInfo = 0x00D5, - } - - public sealed class Request : RntbdTokenStream - { - public override int RequiredTokenCount => 2; - - public RntbdToken resourceId; - public RntbdToken authorizationToken; - public RntbdToken payloadPresent; - public RntbdToken date; - public RntbdToken pageSize; - public RntbdToken sessionToken; - public RntbdToken continuationToken; - public RntbdToken indexingDirective; - public RntbdToken match; - public RntbdToken preTriggerInclude; - public RntbdToken postTriggerInclude; - public RntbdToken isFanout; - public RntbdToken collectionPartitionIndex; - public RntbdToken collectionServiceIndex; - public RntbdToken preTriggerExclude; - public RntbdToken postTriggerExclude; - public RntbdToken consistencyLevel; - public RntbdToken entityId; - public RntbdToken resourceSchemaName; - public RntbdToken replicaPath; - public RntbdToken resourceTokenExpiry; - public RntbdToken databaseName; - public RntbdToken collectionName; - public RntbdToken documentName; - public RntbdToken attachmentName; - public RntbdToken userName; - public RntbdToken permissionName; - public RntbdToken storedProcedureName; - public RntbdToken userDefinedFunctionName; - public RntbdToken triggerName; - public RntbdToken enableScanInQuery; - public RntbdToken emitVerboseTracesInQuery; - public RntbdToken conflictName; - public RntbdToken bindReplicaDirective; - public RntbdToken primaryMasterKey; - public RntbdToken secondaryMasterKey; - public RntbdToken primaryReadonlyKey; - public RntbdToken secondaryReadonlyKey; - public RntbdToken profileRequest; - public RntbdToken enableLowPrecisionOrderBy; - public RntbdToken clientVersion; - public RntbdToken canCharge; - public RntbdToken canThrottle; - public RntbdToken partitionKey; - public RntbdToken partitionKeyRangeId; - public RntbdToken migrateCollectionDirective; - public RntbdToken supportSpatialLegacyCoordinates; - public RntbdToken partitionCount; - public RntbdToken collectionRid; - public RntbdToken partitionKeyRangeName; - public RntbdToken schemaName; - public RntbdToken filterBySchemaRid; - public RntbdToken usePolygonsSmallerThanAHemisphere; - public RntbdToken gatewaySignature; - public RntbdToken enableLogging; - public RntbdToken a_IM; - public RntbdToken populateQuotaInfo; - public RntbdToken disableRUPerMinuteUsage; - public RntbdToken populateQueryMetrics; - public RntbdToken responseContinuationTokenLimitInKb; - public RntbdToken populatePartitionStatistics; - public RntbdToken remoteStorageType; - public RntbdToken collectionRemoteStorageSecurityIdentifier; - public RntbdToken ifModifiedSince; - public RntbdToken populateCollectionThroughputInfo; - public RntbdToken remainingTimeInMsOnClientRequest; - public RntbdToken clientRetryAttemptCount; - public RntbdToken targetLsn; - public RntbdToken targetGlobalCommittedLsn; - public RntbdToken transportRequestID; - public RntbdToken restoreMetadataFilter; - public RntbdToken restoreParams; - public RntbdToken shareThroughput; - public RntbdToken partitionResourceFilter; - public RntbdToken isReadOnlyScript; - public RntbdToken isAutoScaleRequest; - public RntbdToken forceQueryScan; - public RntbdToken canOfferReplaceComplete; - public RntbdToken excludeSystemProperties; - public RntbdToken binaryId; - public RntbdToken timeToLiveInSeconds; - public RntbdToken effectivePartitionKey; - public RntbdToken binaryPassthroughRequest; - public RntbdToken userDefinedTypeName; - public RntbdToken enableDynamicRidRangeAllocation; - public RntbdToken enumerationDirection; - public RntbdToken startId; - public RntbdToken endId; - public RntbdToken fanoutOperationState; - public RntbdToken startEpk; - public RntbdToken endEpk; - public RntbdToken readFeedKeyType; - public RntbdToken contentSerializationFormat; - public RntbdToken allowTentativeWrites; - public RntbdToken isUserRequest; - public RntbdToken preserveFullContent; - public RntbdToken includeTentativeWrites; - public RntbdToken populateResourceCount; - public RntbdToken mergeStaticId; - public RntbdToken isBatchAtomic; - public RntbdToken shouldBatchContinueOnError; - public RntbdToken isBatchOrdered; - public RntbdToken schemaOwnerRid; - public RntbdToken schemaHash; - public RntbdToken isRUPerGBEnforcementRequest; - public RntbdToken maxPollingIntervalMilliseconds; - public RntbdToken snapshotName; - public RntbdToken populateLogStoreInfo; - public RntbdToken getAllPartitionKeyStatistics; - public RntbdToken forceSideBySideIndexMigration; - public RntbdToken collectionChildResourceNameLimitInBytes; - public RntbdToken collectionChildResourceContentLengthLimitInKB; - public RntbdToken clientEncryptionKeyName; - public RntbdToken mergeCheckpointGLSNKeyName; - public RntbdToken returnPreference; - public RntbdToken uniqueIndexNameEncodingMode; - public RntbdToken populateUnflushedMergeEntryCount; - public RntbdToken migrateOfferToManualThroughput; - public RntbdToken migrateOfferToAutopilot; - public RntbdToken isClientEncrypted; - public RntbdToken systemDocumentType; - public RntbdToken isofferStorageRefreshRequest; - public RntbdToken resourceTypes; - public RntbdToken transactionId; - public RntbdToken transactionFirstRequest; - public RntbdToken transactionCommit; - public RntbdToken systemDocumentName; - public RntbdToken updateMaxThroughputEverProvisioned; - public RntbdToken uniqueIndexReIndexingState; - public RntbdToken roleDefinitionName; - public RntbdToken roleAssignmentName; - public RntbdToken useSystemBudget; - public RntbdToken ignoreSystemLoweringMaxThroughput; - public RntbdToken truncateMergeLogRequest; - public RntbdToken retriableWriteRequestId; - public RntbdToken isRetriedWriteRequest; - public RntbdToken retriableWriteRequestStartTimestamp; - public RntbdToken addResourcePropertiesToResponse; - public RntbdToken changeFeedStartFullFidelityIfNoneMatch; - public RntbdToken systemRestoreOperation; - public RntbdToken skipRefreshDatabaseAccountConfigs; - public RntbdToken intendedCollectionRid; - public RntbdToken useArchivalPartition; - public RntbdToken populateUniqueIndexReIndexProgress; - public RntbdToken collectionSchemaId; - public RntbdToken collectionTruncate; - public RntbdToken sDKSupportedCapabilities; - public RntbdToken isMaterializedViewBuild; - public RntbdToken builderClientIdentifier; - public RntbdToken sourceCollectionIfMatch; - public RntbdToken requestedCollectionType; - public RntbdToken interopUserName; - public RntbdToken populateIndexMetrics; - public RntbdToken populateAnalyticalMigrationProgress; - public RntbdToken authPolicyElementName; - public RntbdToken shouldReturnCurrentServerDateTime; - public RntbdToken rbacUserId; - public RntbdToken rbacAction; - public RntbdToken rbacResource; - public RntbdToken correlatedActivityId; - public RntbdToken isThroughputCapRequest; - public RntbdToken changeFeedWireFormatVersion; - public RntbdToken populateBYOKEncryptionProgress; - public RntbdToken useUserBackgroundBudget; - public RntbdToken includePhysicalPartitionThroughputInfo; - public RntbdToken isServerlessStorageRefreshRequest; - public RntbdToken updateOfferStateToPending; - public RntbdToken populateOldestActiveSchemaId; - public RntbdToken isInternalServerlessRequest; - public RntbdToken offerReplaceRURedistribution; - public RntbdToken isCassandraAlterTypeRequest; - public RntbdToken isMaterializedViewSourceSchemaReplaceBatchRequest; - public RntbdToken forceDatabaseAccountUpdate; - public RntbdToken encryptionScopeName; - public RntbdToken priorityLevel; - public RntbdToken allowRestoreParamsUpdate; - public RntbdToken pruneCollectionSchemas; - public RntbdToken populateIndexMetricsV2; - public RntbdToken isMigratedFixedCollection; - public RntbdToken supportedSerializationFormats; - public RntbdToken updateOfferStateToRestorePending; - public RntbdToken setMasterResourcesDeletionPending; - public RntbdToken highPriorityForcedBackup; - public RntbdToken optimisticDirectExecute; - public RntbdToken populateMinGLSNForDocumentOperations; - public RntbdToken populateHighestTentativeWriteLLSN; - public RntbdToken populateCapacityType; - public RntbdToken traceParent; - public RntbdToken traceState; - public RntbdToken globalDatabaseAccountName; - public RntbdToken enableConflictResolutionPolicyUpdate; - public RntbdToken clientIpAddress; - public RntbdToken isRequestNotAuthorized; - public RntbdToken startEpkHash; - public RntbdToken endEpkHash; - public RntbdToken allowDocumentReadsInOfflineRegion; - public RntbdToken populateCurrentPartitionThroughputInfo; - - public Request() - { - this.resourceId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.ResourceId); - this.authorizationToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AuthorizationToken); - this.payloadPresent = new RntbdToken(true, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PayloadPresent); - this.date = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.Date); - this.pageSize = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.PageSize); - this.sessionToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SessionToken); - this.continuationToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ContinuationToken); - this.indexingDirective = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IndexingDirective); - this.match = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.Match); - this.preTriggerInclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PreTriggerInclude); - this.postTriggerInclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PostTriggerInclude); - this.isFanout = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsFanout); - this.collectionPartitionIndex = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.CollectionPartitionIndex); - this.collectionServiceIndex = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.CollectionServiceIndex); - this.preTriggerExclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PreTriggerExclude); - this.postTriggerExclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PostTriggerExclude); - this.consistencyLevel = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ConsistencyLevel); - this.entityId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.EntityId); - this.resourceSchemaName = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.ResourceSchemaName); - this.replicaPath = new RntbdToken(true, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ReplicaPath); - this.resourceTokenExpiry = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ResourceTokenExpiry); - this.databaseName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.DatabaseName); - this.collectionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionName); - this.documentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.DocumentName); - this.attachmentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AttachmentName); - this.userName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserName); - this.permissionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PermissionName); - this.storedProcedureName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.StoredProcedureName); - this.userDefinedFunctionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserDefinedFunctionName); - this.triggerName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TriggerName); - this.enableScanInQuery = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableScanInQuery); - this.emitVerboseTracesInQuery = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EmitVerboseTracesInQuery); - this.conflictName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ConflictName); - this.bindReplicaDirective = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.BindReplicaDirective); - this.primaryMasterKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PrimaryMasterKey); - this.secondaryMasterKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SecondaryMasterKey); - this.primaryReadonlyKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PrimaryReadonlyKey); - this.secondaryReadonlyKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SecondaryReadonlyKey); - this.profileRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ProfileRequest); - this.enableLowPrecisionOrderBy = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableLowPrecisionOrderBy); - this.clientVersion = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.ClientVersion); - this.canCharge = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanCharge); - this.canThrottle = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanThrottle); - this.partitionKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKey); - this.partitionKeyRangeId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKeyRangeId); - this.migrateCollectionDirective = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateCollectionDirective); - this.supportSpatialLegacyCoordinates = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SupportSpatialLegacyCoordinates); - this.partitionCount = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.PartitionCount); - this.collectionRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionRid); - this.partitionKeyRangeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKeyRangeName); - this.schemaName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SchemaName); - this.filterBySchemaRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.FilterBySchemaRid); - this.usePolygonsSmallerThanAHemisphere = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UsePolygonsSmallerThanAHemisphere); - this.gatewaySignature = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.GatewaySignature); - this.enableLogging = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableLogging); - this.a_IM = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.A_IM); - this.populateQuotaInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateQuotaInfo); - this.disableRUPerMinuteUsage = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.DisableRUPerMinuteUsage); - this.populateQueryMetrics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateQueryMetrics); - this.responseContinuationTokenLimitInKb = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ResponseContinuationTokenLimitInKb); - this.populatePartitionStatistics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulatePartitionStatistics); - this.remoteStorageType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.RemoteStorageType); - this.collectionRemoteStorageSecurityIdentifier = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionRemoteStorageSecurityIdentifier); - this.ifModifiedSince = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IfModifiedSince); - this.populateCollectionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCollectionThroughputInfo); - this.remainingTimeInMsOnClientRequest = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.RemainingTimeInMsOnClientRequest); - this.clientRetryAttemptCount = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ClientRetryAttemptCount); - this.targetLsn = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.TargetLsn); - this.targetGlobalCommittedLsn = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.TargetGlobalCommittedLsn); - this.transportRequestID = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.TransportRequestID); - this.restoreMetadataFilter = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RestoreMetadataFilter); - this.restoreParams = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RestoreParams); - this.shareThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShareThroughput); - this.partitionResourceFilter = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionResourceFilter); - this.isReadOnlyScript = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsReadOnlyScript); - this.isAutoScaleRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsAutoScaleRequest); - this.forceQueryScan = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceQueryScan); - this.canOfferReplaceComplete = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanOfferReplaceComplete); - this.excludeSystemProperties = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ExcludeSystemProperties); - this.binaryId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.BinaryId); - this.timeToLiveInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.TimeToLiveInSeconds); - this.effectivePartitionKey = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EffectivePartitionKey); - this.binaryPassthroughRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.BinaryPassthroughRequest); - this.userDefinedTypeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserDefinedTypeName); - this.enableDynamicRidRangeAllocation = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableDynamicRidRangeAllocation); - this.enumerationDirection = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnumerationDirection); - this.startId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartId); - this.endId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndId); - this.fanoutOperationState = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.FanoutOperationState); - this.startEpk = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartEpk); - this.endEpk = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndEpk); - this.readFeedKeyType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ReadFeedKeyType); - this.contentSerializationFormat = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ContentSerializationFormat); - this.allowTentativeWrites = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AllowTentativeWrites); - this.isUserRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsUserRequest); - this.preserveFullContent = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PreserveFullContent); - this.includeTentativeWrites = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IncludeTentativeWrites); - this.populateResourceCount = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateResourceCount); - this.mergeStaticId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.MergeStaticId); - this.isBatchAtomic = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsBatchAtomic); - this.shouldBatchContinueOnError = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShouldBatchContinueOnError); - this.isBatchOrdered = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsBatchOrdered); - this.schemaOwnerRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SchemaOwnerRid); - this.schemaHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.SchemaHash); - this.isRUPerGBEnforcementRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRUPerGBEnforcementRequest); - this.maxPollingIntervalMilliseconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.MaxPollingIntervalMilliseconds); - this.snapshotName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SnapshotName); - this.populateLogStoreInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateLogStoreInfo); - this.getAllPartitionKeyStatistics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.GetAllPartitionKeyStatistics); - this.forceSideBySideIndexMigration = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceSideBySideIndexMigration); - this.collectionChildResourceNameLimitInBytes = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.CollectionChildResourceNameLimitInBytes); - this.collectionChildResourceContentLengthLimitInKB = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.CollectionChildResourceContentLengthLimitInKB); - this.clientEncryptionKeyName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ClientEncryptionKeyName); - this.mergeCheckpointGLSNKeyName = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.MergeCheckpointGLSNKeyName); - this.returnPreference = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ReturnPreference); - this.uniqueIndexNameEncodingMode = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UniqueIndexNameEncodingMode); - this.populateUnflushedMergeEntryCount = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateUnflushedMergeEntryCount); - this.migrateOfferToManualThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateOfferToManualThroughput); - this.migrateOfferToAutopilot = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateOfferToAutopilot); - this.isClientEncrypted = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsClientEncrypted); - this.systemDocumentType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SystemDocumentType); - this.isofferStorageRefreshRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsofferStorageRefreshRequest); - this.resourceTypes = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ResourceTypes); - this.transactionId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.TransactionId); - this.transactionFirstRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TransactionFirstRequest); - this.transactionCommit = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TransactionCommit); - this.systemDocumentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SystemDocumentName); - this.updateMaxThroughputEverProvisioned = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.UpdateMaxThroughputEverProvisioned); - this.uniqueIndexReIndexingState = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UniqueIndexReIndexingState); - this.roleDefinitionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RoleDefinitionName); - this.roleAssignmentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RoleAssignmentName); - this.useSystemBudget = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseSystemBudget); - this.ignoreSystemLoweringMaxThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IgnoreSystemLoweringMaxThroughput); - this.truncateMergeLogRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TruncateMergeLogRequest); - this.retriableWriteRequestId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.RetriableWriteRequestId); - this.isRetriedWriteRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRetriedWriteRequest); - this.retriableWriteRequestStartTimestamp = new RntbdToken(false, RntbdTokenTypes.ULongLong, (ushort)RequestIdentifiers.RetriableWriteRequestStartTimestamp); - this.addResourcePropertiesToResponse = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AddResourcePropertiesToResponse); - this.changeFeedStartFullFidelityIfNoneMatch = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ChangeFeedStartFullFidelityIfNoneMatch); - this.systemRestoreOperation = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SystemRestoreOperation); - this.skipRefreshDatabaseAccountConfigs = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SkipRefreshDatabaseAccountConfigs); - this.intendedCollectionRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IntendedCollectionRid); - this.useArchivalPartition = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseArchivalPartition); - this.populateUniqueIndexReIndexProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateUniqueIndexReIndexProgress); - this.collectionSchemaId = new RntbdToken(false, RntbdTokenTypes.Long, (ushort)RequestIdentifiers.CollectionSchemaId); - this.collectionTruncate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CollectionTruncate); - this.sDKSupportedCapabilities = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.SDKSupportedCapabilities); - this.isMaterializedViewBuild = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMaterializedViewBuild); - this.builderClientIdentifier = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.BuilderClientIdentifier); - this.sourceCollectionIfMatch = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SourceCollectionIfMatch); - this.requestedCollectionType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.RequestedCollectionType); - this.interopUserName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.InteropUserName); - this.populateIndexMetrics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateIndexMetrics); - this.populateAnalyticalMigrationProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateAnalyticalMigrationProgress); - this.authPolicyElementName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AuthPolicyElementName); - this.shouldReturnCurrentServerDateTime = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShouldReturnCurrentServerDateTime); - this.rbacUserId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacUserId); - this.rbacAction = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacAction); - this.rbacResource = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacResource); - this.correlatedActivityId = new RntbdToken(false, RntbdTokenTypes.Guid, (ushort)RequestIdentifiers.CorrelatedActivityId); - this.isThroughputCapRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsThroughputCapRequest); - this.changeFeedWireFormatVersion = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ChangeFeedWireFormatVersion); - this.populateBYOKEncryptionProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateBYOKEncryptionProgress); - this.useUserBackgroundBudget = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseUserBackgroundBudget); - this.includePhysicalPartitionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IncludePhysicalPartitionThroughputInfo); - this.isServerlessStorageRefreshRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsServerlessStorageRefreshRequest); - this.updateOfferStateToPending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UpdateOfferStateToPending); - this.populateOldestActiveSchemaId = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateOldestActiveSchemaId); - this.isInternalServerlessRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsInternalServerlessRequest); - this.offerReplaceRURedistribution = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.OfferReplaceRURedistribution); - this.isCassandraAlterTypeRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsCassandraAlterTypeRequest); - this.isMaterializedViewSourceSchemaReplaceBatchRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMaterializedViewSourceSchemaReplaceBatchRequest); - this.forceDatabaseAccountUpdate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceDatabaseAccountUpdate); - this.encryptionScopeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.EncryptionScopeName); - this.priorityLevel = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PriorityLevel); - this.allowRestoreParamsUpdate = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AllowRestoreParamsUpdate); - this.pruneCollectionSchemas = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PruneCollectionSchemas); - this.populateIndexMetricsV2 = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateIndexMetricsV2); - this.isMigratedFixedCollection = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMigratedFixedCollection); - this.supportedSerializationFormats = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SupportedSerializationFormats); - this.updateOfferStateToRestorePending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UpdateOfferStateToRestorePending); - this.setMasterResourcesDeletionPending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SetMasterResourcesDeletionPending); - this.highPriorityForcedBackup = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.HighPriorityForcedBackup); - this.optimisticDirectExecute = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.OptimisticDirectExecute); - this.populateMinGLSNForDocumentOperations = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateMinGLSNForDocumentOperations); - this.populateHighestTentativeWriteLLSN = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateHighestTentativeWriteLLSN); - this.populateCapacityType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCapacityType); - this.traceParent = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceParent); - this.traceState = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceState); - this.globalDatabaseAccountName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.GlobalDatabaseAccountName); - this.enableConflictResolutionPolicyUpdate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableConflictResolutionPolicyUpdate); - this.clientIpAddress = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ClientIpAddress); - this.isRequestNotAuthorized = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRequestNotAuthorized); - this.startEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartEpkHash); - this.endEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndEpkHash); - this.allowDocumentReadsInOfflineRegion = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AllowDocumentReadsInOfflineRegion); - this.populateCurrentPartitionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCurrentPartitionThroughputInfo); - - this.tokens = new RntbdToken[] - { - this.resourceId, - this.authorizationToken, - this.payloadPresent, - this.date, - this.pageSize, - this.sessionToken, - this.continuationToken, - this.indexingDirective, - this.match, - this.preTriggerInclude, - this.postTriggerInclude, - this.isFanout, - this.collectionPartitionIndex, - this.collectionServiceIndex, - this.preTriggerExclude, - this.postTriggerExclude, - this.consistencyLevel, - this.entityId, - this.resourceSchemaName, - this.replicaPath, - this.resourceTokenExpiry, - this.databaseName, - this.collectionName, - this.documentName, - this.attachmentName, - this.userName, - this.permissionName, - this.storedProcedureName, - this.userDefinedFunctionName, - this.triggerName, - this.enableScanInQuery, - this.emitVerboseTracesInQuery, - this.conflictName, - this.bindReplicaDirective, - this.primaryMasterKey, - this.secondaryMasterKey, - this.primaryReadonlyKey, - this.secondaryReadonlyKey, - this.profileRequest, - this.enableLowPrecisionOrderBy, - this.clientVersion, - this.canCharge, - this.canThrottle, - this.partitionKey, - this.partitionKeyRangeId, - null, // 0x002D - null, // 0x002E - null, // 0x002F - null, // 0x0030 - this.migrateCollectionDirective, - null, // 0x0032 - this.supportSpatialLegacyCoordinates, - this.partitionCount, - this.collectionRid, - this.partitionKeyRangeName, - null, // 0x0037 - null, // 0x0038 - null, // 0x0039 - this.schemaName, - this.filterBySchemaRid, - this.usePolygonsSmallerThanAHemisphere, - this.gatewaySignature, - this.enableLogging, - this.a_IM, - this.populateQuotaInfo, - this.disableRUPerMinuteUsage, - this.populateQueryMetrics, - this.responseContinuationTokenLimitInKb, - this.populatePartitionStatistics, - this.remoteStorageType, - this.collectionRemoteStorageSecurityIdentifier, - this.ifModifiedSince, - this.populateCollectionThroughputInfo, - this.remainingTimeInMsOnClientRequest, - this.clientRetryAttemptCount, - this.targetLsn, - this.targetGlobalCommittedLsn, - this.transportRequestID, - this.restoreMetadataFilter, - this.restoreParams, - this.shareThroughput, - this.partitionResourceFilter, - this.isReadOnlyScript, - this.isAutoScaleRequest, - this.forceQueryScan, - null, // 0x0055 - this.canOfferReplaceComplete, - this.excludeSystemProperties, - this.binaryId, - this.timeToLiveInSeconds, - this.effectivePartitionKey, - this.binaryPassthroughRequest, - this.userDefinedTypeName, - this.enableDynamicRidRangeAllocation, - this.enumerationDirection, - this.startId, - this.endId, - this.fanoutOperationState, - this.startEpk, - this.endEpk, - this.readFeedKeyType, - this.contentSerializationFormat, - this.allowTentativeWrites, - this.isUserRequest, - null, // 0x0068 - this.preserveFullContent, - null, // 0x006A - null, // 0x006B - null, // 0x006C - null, // 0x006D - null, // 0x006E - null, // 0x006F - this.includeTentativeWrites, - this.populateResourceCount, - this.mergeStaticId, - this.isBatchAtomic, - this.shouldBatchContinueOnError, - this.isBatchOrdered, - this.schemaOwnerRid, - this.schemaHash, - this.isRUPerGBEnforcementRequest, - this.maxPollingIntervalMilliseconds, - this.snapshotName, - this.populateLogStoreInfo, - this.getAllPartitionKeyStatistics, - this.forceSideBySideIndexMigration, - this.collectionChildResourceNameLimitInBytes, - this.collectionChildResourceContentLengthLimitInKB, - this.clientEncryptionKeyName, - this.mergeCheckpointGLSNKeyName, - this.returnPreference, - this.uniqueIndexNameEncodingMode, - this.populateUnflushedMergeEntryCount, - this.migrateOfferToManualThroughput, - this.migrateOfferToAutopilot, - this.isClientEncrypted, - this.systemDocumentType, - this.isofferStorageRefreshRequest, - this.resourceTypes, - this.transactionId, - this.transactionFirstRequest, - this.transactionCommit, - this.systemDocumentName, - this.updateMaxThroughputEverProvisioned, - this.uniqueIndexReIndexingState, - this.roleDefinitionName, - this.roleAssignmentName, - this.useSystemBudget, - this.ignoreSystemLoweringMaxThroughput, - this.truncateMergeLogRequest, - this.retriableWriteRequestId, - this.isRetriedWriteRequest, - this.retriableWriteRequestStartTimestamp, - this.addResourcePropertiesToResponse, - this.changeFeedStartFullFidelityIfNoneMatch, - this.systemRestoreOperation, - this.skipRefreshDatabaseAccountConfigs, - this.intendedCollectionRid, - this.useArchivalPartition, - this.populateUniqueIndexReIndexProgress, - this.collectionSchemaId, - this.collectionTruncate, - this.sDKSupportedCapabilities, - this.isMaterializedViewBuild, - this.builderClientIdentifier, - this.sourceCollectionIfMatch, - this.requestedCollectionType, - null, // 0x00A7 - this.interopUserName, - this.populateIndexMetrics, - this.populateAnalyticalMigrationProgress, - this.authPolicyElementName, - this.shouldReturnCurrentServerDateTime, - this.rbacUserId, - this.rbacAction, - this.rbacResource, - this.correlatedActivityId, - this.isThroughputCapRequest, - this.changeFeedWireFormatVersion, - this.populateBYOKEncryptionProgress, - this.useUserBackgroundBudget, - this.includePhysicalPartitionThroughputInfo, - this.isServerlessStorageRefreshRequest, - this.updateOfferStateToPending, - this.populateOldestActiveSchemaId, - this.isInternalServerlessRequest, - this.offerReplaceRURedistribution, - this.isCassandraAlterTypeRequest, - this.isMaterializedViewSourceSchemaReplaceBatchRequest, - this.forceDatabaseAccountUpdate, - this.encryptionScopeName, - this.priorityLevel, - this.allowRestoreParamsUpdate, - this.pruneCollectionSchemas, - this.populateIndexMetricsV2, - this.isMigratedFixedCollection, - this.supportedSerializationFormats, - this.updateOfferStateToRestorePending, - this.setMasterResourcesDeletionPending, - this.highPriorityForcedBackup, - this.optimisticDirectExecute, - this.populateMinGLSNForDocumentOperations, - this.populateHighestTentativeWriteLLSN, - this.populateCapacityType, - this.traceParent, - this.traceState, - this.globalDatabaseAccountName, - this.enableConflictResolutionPolicyUpdate, - this.clientIpAddress, - this.isRequestNotAuthorized, - this.startEpkHash, - this.endEpkHash, - this.allowDocumentReadsInOfflineRegion, - this.populateCurrentPartitionThroughputInfo, - }; - } - } - - // Values are generated from the common source where response headers ordered by the chance headers could apper on response. - // This order helps in constracting more performant switch statements in the loop(s) processing response headers. - public enum ResponseIdentifiers : ushort - { - TransportRequestID = 0x0035, - ServerDateTimeUtc = 0x0039, - SubStatus = 0x001C, - ETag = 0x0004, - ResourceName = 0x0047, - RequestCharge = 0x0015, - SessionToken = 0x003E, - ContinuationToken = 0x0003, - LSN = 0x0013, - GlobalCommittedLSN = 0x0029, - ItemLSN = 0x0032, - LocalLSN = 0x003A, - QuorumAckedLocalLSN = 0x003B, - ItemLocalLSN = 0x003C, - PayloadPresent = 0x0000, - LastStateChangeDateTime = 0x0002, - RetryAfterMilliseconds = 0x000C, - IndexingDirective = 0x000D, - StorageMaxResoureQuota = 0x000E, - StorageResourceQuotaUsage = 0x000F, - SchemaVersion = 0x0010, - CollectionPartitionIndex = 0x0011, - CollectionServiceIndex = 0x0012, - ItemCount = 0x0014, - OwnerFullName = 0x0017, - OwnerId = 0x0018, - DatabaseAccountId = 0x0019, - QuorumAckedLSN = 0x001A, - RequestValidationFailure = 0x001B, - CollectionUpdateProgress = 0x001D, - CurrentWriteQuorum = 0x001E, - CurrentReplicaSetSize = 0x001F, - CollectionLazyIndexProgress = 0x0020, - PartitionKeyRangeId = 0x0021, - LogResults = 0x0025, - XPRole = 0x0026, - IsRUPerMinuteUsed = 0x0027, - QueryMetrics = 0x0028, - NumberOfReadRegions = 0x0030, - OfferReplacePending = 0x0031, - RestoreState = 0x0033, - CollectionSecurityIdentifier = 0x0034, - ShareThroughput = 0x0036, - DisableRntbdChannel = 0x0038, - HasTentativeWrites = 0x003D, - ReplicatorLSNToGLSNDelta = 0x003F, - ReplicatorLSNToLLSNDelta = 0x0040, - VectorClockLocalProgress = 0x0041, - MinimumRUsForOffer = 0x0042, - XPConfigurationSessionsCount = 0x0043, - IndexUtilization = 0x0044, - QueryExecutionInfo = 0x0045, - UnflushedMergeLogEntryCount = 0x0046, - TimeToLiveInSeconds = 0x0048, - ReplicaStatusRevoked = 0x0049, - SoftMaxAllowedThroughput = 0x0050, - BackendRequestDurationMilliseconds = 0x0051, - CorrelatedActivityId = 0x0052, - ConfirmedStoreChecksum = 0x0053, - TentativeStoreChecksum = 0x0054, - PendingPKDelete = 0x0055, - AadAppliedRoleAssignmentId = 0x0056, - CollectionUniqueIndexReIndexProgress = 0x0057, - CollectionUniqueKeysUnderReIndex = 0x0058, - AnalyticalMigrationProgress = 0x0059, - TotalAccountThroughput = 0x005A, - BYOKEncryptionProgress = 0x005B, - AppliedPolicyElementId = 0x005C, - MergeProgressBlocked = 0x005D, - ChangeFeedInfo = 0x005E, - ReindexerProgress = 0x005F, - OfferReplacePendingForMerge = 0x0060, - MaxContentLength = 0x0061, - OldestActiveSchemaId = 0x0062, - PhysicalPartitionId = 0x0063, - OfferRestorePending = 0x0064, - InstantScaleUpValue = 0x0065, - RequiresDistribution = 0x0066, - CapacityType = 0x0067, - MinGLSNForDocumentOperations = 0x0068, - MinGLSNForTombstoneOperations = 0x0069, - HighestTentativeWriteLLSN = 0x0070, - PartitionThroughputInfo = 0x0071, - } - - // - // DEVNOTE: This enumeration is used only for the logging purpose. Do not use it for any other purpose. - // - public enum CallerId : byte - { - /// - /// The default caller Id - /// - Anonymous = 0x00, - - /// - /// The connection request is made by Gateway - /// - Gateway = 0x01, - - /// - /// The connection request is made by BackgroundTask - /// - BackgroundTask = 0x02, - - /// - /// The connection request is made by ManagementWorkerRuntime - /// - ManagementWorker = 0x03, - - /// - /// Invalid caller Id - /// - Invalid = 0x04, - } - - internal sealed class RntbdEntityPool - where T : RntbdTokenStream, new() - where TU : Enum - { - public static readonly RntbdEntityPool Instance = new RntbdEntityPool(); - - private readonly ConcurrentQueue entities = new ConcurrentQueue(); - - private RntbdEntityPool() - { - } - - public EntityOwner Get() - { - if (this.entities.TryDequeue(out T entity)) - { - return new EntityOwner(entity); - } - - return new EntityOwner(new T()); - } - - private void Return(T entity) - { - entity.Reset(); - this.entities.Enqueue(entity); - } - - public readonly struct EntityOwner : IDisposable - { - public EntityOwner(T entity) - { - this.Entity = entity; - } - - public T Entity { get; } - - public void Dispose() - { - if (this.Entity != null) - { - RntbdEntityPool.Instance.Return(this.Entity); - } - } - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RntbdConstants.tt +// This allows the RntbdTokenStreams to be correctly ordered and optimized. +// If you need to add a new RntbdToken to any of the existing types, please do it on the RntbdConstants.tt file + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + + /// + /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA RntbdConstants.tt + /// This allows the RntbdTokenStreams to be correctly ordered and optimized. + /// If you need to add a new RntbdToken to any of the existing types, do it on the RntbdConstants.tt file + /// + internal static class RntbdConstants + { + public const UInt32 CurrentProtocolVersion = 0x00000001; + + public enum RntbdResourceType : ushort + { + Connection = 0x0000, + Database = 0x0001, + Collection = 0x0002, + Document = 0x0003, + Attachment = 0x0004, + User = 0x0005, + Permission = 0x0006, + StoredProcedure = 0x0007, + Conflict = 0x0008, + Trigger = 0x0009, + UserDefinedFunction = 0x000A, + Module = 0x000B, + Replica = 0x000C, + ModuleCommand = 0x000D, + Record = 0x000E, + Offer = 0x000F, + PartitionSetInformation = 0x0010, + XPReplicatorAddress = 0x0011, + MasterPartition = 0x0012, + ServerPartition = 0x0013, + DatabaseAccount = 0x0014, + Topology = 0x0015, + PartitionKeyRange = 0x0016, + // not used = 0x0017, timestamp + Schema = 0x0018, + BatchApply = 0x0019, + RestoreMetadata = 0x001A, + ComputeGatewayCharges = 0x001B, + RidRange = 0x001C, + UserDefinedType = 0x001D, + VectorClock = 0x001F, + PartitionKey = 0x0020, + Snapshot = 0x0021, + ClientEncryptionKey = 0x0023, + Transaction = 0x0025, + PartitionedSystemDocument = 0x0026, + RoleDefinition = 0x0027, + RoleAssignment = 0x0028, + SystemDocument = 0x0029, + InteropUser = 0x002A, + TransportControlCommand = 0x002B, + AuthPolicyElement = 0x002C, + StorageAuthToken = 0x002D, + RetriableWriteCachedResponse = 0x002E, + EncryptionScope = 0x0030, + } + + public enum RntbdOperationType : ushort + { + Connection = 0x0000, + Create = 0x0001, + Patch = 0x0002, + Read = 0x0003, + ReadFeed = 0x0004, + Delete = 0x0005, + Replace = 0x0006, + // Deprecated and should not be used JPathQuery = 0x0007, + ExecuteJavaScript = 0x0008, + SQLQuery = 0x0009, + Pause = 0x000A, + Resume = 0x000B, + Stop = 0x000C, + Recycle = 0x000D, + Crash = 0x000E, + Query = 0x000F, + ForceConfigRefresh = 0x0010, + Head = 0x0011, + HeadFeed = 0x0012, + Upsert = 0x0013, + Recreate = 0x0014, + Throttle = 0x0015, + GetSplitPoint = 0x0016, + PreCreateValidation = 0x0017, + BatchApply = 0x0018, + AbortSplit = 0x0019, + CompleteSplit = 0x001A, + OfferUpdateOperation = 0x001B, + OfferPreGrowValidation = 0x001C, + BatchReportThroughputUtilization = 0x001D, + CompletePartitionMigration = 0x001E, + AbortPartitionMigration = 0x001F, + PreReplaceValidation = 0x0020, + AddComputeGatewayRequestCharges = 0x0021, + MigratePartition = 0x0022, + MasterReplaceOfferOperation = 0x023, + ProvisionedCollectionOfferUpdateOperation = 0x024, + Batch = 0x025, + InitiateDatabaseOfferPartitionShrink = 0x026, + CompleteDatabaseOfferPartitionShrink = 0x027, + EnsureSnapshotOperation = 0x028, + GetSplitPoints = 0x0029, + CompleteMergeOnTarget = 0x002A, + CompleteMergeOnMaster = 0x002C, + ForcePartitionBackup = 0x002E, + CompleteUserTransaction = 0x002F, + MasterInitiatedProgressCoordination = 0x0030, + MetadataCheckAccess = 0x0031, + CreateSystemSnapshot = 0x0032, + UpdateFailoverPriorityList = 0x0033, + GetStorageAuthToken = 0x0034, + UpdatePartitionThroughput = 0x0035, + CreateRidRangeResources = 0x0036, + Truncate = 0x0037, + } + + public enum ConnectionContextRequestTokenIdentifiers : ushort + { + ProtocolVersion = 0x0000, + ClientVersion = 0x0001, + UserAgent = 0x0002, + CallerId = 0x0003, + EnableChannelMultiplexing = 0x0004, + } + + public sealed class ConnectionContextRequest : RntbdTokenStream + { + public override int RequiredTokenCount => 3; + + public RntbdToken protocolVersion; + public RntbdToken clientVersion; + public RntbdToken userAgent; + public RntbdToken callerId; + public RntbdToken enableChannelMultiplexing; + + public ConnectionContextRequest() + { + this.protocolVersion = new RntbdToken(true, RntbdTokenTypes.ULong, (ushort)ConnectionContextRequestTokenIdentifiers.ProtocolVersion); + this.clientVersion = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextRequestTokenIdentifiers.ClientVersion); + this.userAgent = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextRequestTokenIdentifiers.UserAgent); + this.callerId = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)ConnectionContextRequestTokenIdentifiers.CallerId); + this.enableChannelMultiplexing = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)ConnectionContextRequestTokenIdentifiers.EnableChannelMultiplexing); + + this.tokens = new RntbdToken[] + { + this.protocolVersion, + this.clientVersion, + this.userAgent, + this.callerId, + this.enableChannelMultiplexing, + }; + } + } + + public enum ConnectionContextResponseTokenIdentifiers : ushort + { + ProtocolVersion = 0x0000, + ClientVersion = 0x0001, + ServerAgent = 0x0002, + ServerVersion = 0x0003, + IdleTimeoutInSeconds = 0x0004, + UnauthenticatedTimeoutInSeconds = 0x0005, + } + + public sealed class ConnectionContextResponse : RntbdTokenStream + { + public override int RequiredTokenCount => 2; + + public RntbdToken protocolVersion; + public RntbdToken clientVersion; + public RntbdToken serverAgent; + public RntbdToken serverVersion; + public RntbdToken idleTimeoutInSeconds; + public RntbdToken unauthenticatedTimeoutInSeconds; + + public ConnectionContextResponse() + { + this.protocolVersion = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.ProtocolVersion); + this.clientVersion = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ClientVersion); + this.serverAgent = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ServerAgent); + this.serverVersion = new RntbdToken(true, RntbdTokenTypes.SmallString, (ushort)ConnectionContextResponseTokenIdentifiers.ServerVersion); + this.idleTimeoutInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.IdleTimeoutInSeconds); + this.unauthenticatedTimeoutInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)ConnectionContextResponseTokenIdentifiers.UnauthenticatedTimeoutInSeconds); + + this.tokens = new RntbdToken[] + { + this.protocolVersion, + this.clientVersion, + this.serverAgent, + this.serverVersion, + this.idleTimeoutInSeconds, + this.unauthenticatedTimeoutInSeconds, + }; + } + } + + public enum RntbdIndexingDirective : byte + { + Default = 0x00, + Include = 0x01, + Exclude = 0x02, + + Invalid = 0xFF, + } + + public enum RntbdMigrateCollectionDirective : byte + { + Thaw = 0x00, + Freeze = 0x01, + + Invalid = 0xFF, + } + + public enum RntbdRemoteStorageType : byte + { + Invalid = 0x00, + NotSpecified = 0x01, + Standard = 0x02, + Premium = 0x03, + } + + public enum RntbdConsistencyLevel : byte + { + Strong = 0x00, + BoundedStaleness = 0x01, + Session = 0x02, + Eventual = 0x03, + ConsistentPrefix = 0x04, + + Invalid = 0xFF, + } + + public enum RntdbEnumerationDirection : byte + { + Invalid = 0x00, + Forward = 0x01, + Reverse = 0x02, + } + + public enum RntbdFanoutOperationState : byte + { + Started = 0x01, + Completed = 0x02, + } + + public enum RntdbReadFeedKeyType : byte + { + Invalid = 0x00, + ResourceId = 0x01, + EffectivePartitionKey = 0x02, + EffectivePartitionKeyRange = 0x03, + } + + public enum RntbdContentSerializationFormat : byte + { + JsonText = 0x00, + CosmosBinary = 0x01, + HybridRow = 0x02, + + Invalid = 0xFF, + } + + [Flags] + public enum RntbdSupportedSerializationFormats : byte + { + None = 0x00, + JsonText = 0x01, + CosmosBinary = 0x02, + HybridRow = 0x04, + } + + public enum RntbdSystemDocumentType : byte + { + PartitionKey = 0x00, + MaterializedViewLeaseDocument = 0x01, + MaterializedViewBuilderOwnershipDocument = 0x02, + MaterializedViewLeaseStoreInitDocument = 0x03, + + Invalid = 0xFF, + } + + public enum RntbdRequestedCollectionType : byte + { + All = 0x00, + Standard = 0x01, + MaterializedView = 0x02, + } + + public enum RntbdPriorityLevel : byte + { + High = 0x01, + Low = 0x02, + } + + public enum RequestIdentifiers : ushort + { + ResourceId = 0x0000, + AuthorizationToken = 0x0001, + PayloadPresent = 0x0002, + Date = 0x0003, + PageSize = 0x0004, + SessionToken = 0x0005, + ContinuationToken = 0x0006, + IndexingDirective = 0x0007, + Match = 0x0008, + PreTriggerInclude = 0x0009, + PostTriggerInclude = 0x000A, + IsFanout = 0x000B, + CollectionPartitionIndex = 0x000C, + CollectionServiceIndex = 0x000D, + PreTriggerExclude = 0x000E, + PostTriggerExclude = 0x000F, + ConsistencyLevel = 0x0010, + EntityId = 0x0011, + ResourceSchemaName = 0x0012, + ReplicaPath = 0x0013, + ResourceTokenExpiry = 0x0014, + DatabaseName = 0x0015, + CollectionName = 0x0016, + DocumentName = 0x0017, + AttachmentName = 0x0018, + UserName = 0x0019, + PermissionName = 0x001A, + StoredProcedureName = 0x001B, + UserDefinedFunctionName = 0x001C, + TriggerName = 0x001D, + EnableScanInQuery = 0x001E, + EmitVerboseTracesInQuery = 0x001F, + ConflictName = 0x0020, + BindReplicaDirective = 0x0021, + PrimaryMasterKey = 0x0022, + SecondaryMasterKey = 0x0023, + PrimaryReadonlyKey = 0x0024, + SecondaryReadonlyKey = 0x0025, + ProfileRequest = 0x0026, + EnableLowPrecisionOrderBy = 0x0027, + ClientVersion = 0x0028, + CanCharge = 0x0029, + CanThrottle = 0x002A, + PartitionKey = 0x002B, + PartitionKeyRangeId = 0x002C, + MigrateCollectionDirective = 0x0031, + SupportSpatialLegacyCoordinates = 0x0033, + PartitionCount = 0x0034, + CollectionRid = 0x0035, + PartitionKeyRangeName = 0x0036, + SchemaName = 0x003A, + FilterBySchemaRid = 0x003B, + UsePolygonsSmallerThanAHemisphere = 0x003C, + GatewaySignature = 0x003D, + EnableLogging = 0x003E, + A_IM = 0x003F, + PopulateQuotaInfo = 0x0040, + DisableRUPerMinuteUsage = 0x0041, + PopulateQueryMetrics = 0x0042, + ResponseContinuationTokenLimitInKb = 0x0043, + PopulatePartitionStatistics = 0x0044, + RemoteStorageType = 0x0045, + CollectionRemoteStorageSecurityIdentifier = 0x0046, + IfModifiedSince = 0x0047, + PopulateCollectionThroughputInfo = 0x0048, + RemainingTimeInMsOnClientRequest = 0x0049, + ClientRetryAttemptCount = 0x004A, + TargetLsn = 0x004B, + TargetGlobalCommittedLsn = 0x004C, + TransportRequestID = 0x004D, + RestoreMetadataFilter = 0x004E, + RestoreParams = 0x004F, + ShareThroughput = 0x0050, + PartitionResourceFilter = 0x0051, + IsReadOnlyScript = 0x0052, + IsAutoScaleRequest = 0x0053, + ForceQueryScan = 0x0054, + CanOfferReplaceComplete = 0x0056, + ExcludeSystemProperties = 0x0057, + BinaryId = 0x0058, + TimeToLiveInSeconds = 0x0059, + EffectivePartitionKey = 0x005A, + BinaryPassthroughRequest = 0x005B, + UserDefinedTypeName = 0x005C, + EnableDynamicRidRangeAllocation = 0x005D, + EnumerationDirection = 0x005E, + StartId = 0x005F, + EndId = 0x0060, + FanoutOperationState = 0x0061, + StartEpk = 0x0062, + EndEpk = 0x0063, + ReadFeedKeyType = 0x0064, + ContentSerializationFormat = 0x0065, + AllowTentativeWrites = 0x0066, + IsUserRequest = 0x0067, + PreserveFullContent = 0x0069, + IncludeTentativeWrites = 0x0070, + PopulateResourceCount = 0x0071, + MergeStaticId = 0x0072, + IsBatchAtomic = 0x0073, + ShouldBatchContinueOnError = 0x0074, + IsBatchOrdered = 0x0075, + SchemaOwnerRid = 0x0076, + SchemaHash = 0x0077, + IsRUPerGBEnforcementRequest = 0x0078, + MaxPollingIntervalMilliseconds = 0x0079, + SnapshotName = 0x007A, + PopulateLogStoreInfo = 0x007B, + GetAllPartitionKeyStatistics = 0x007C, + ForceSideBySideIndexMigration = 0x007D, + CollectionChildResourceNameLimitInBytes = 0x007E, + CollectionChildResourceContentLengthLimitInKB = 0x007F, + ClientEncryptionKeyName = 0x0080, + MergeCheckpointGLSNKeyName = 0x0081, + ReturnPreference = 0x0082, + UniqueIndexNameEncodingMode = 0x0083, + PopulateUnflushedMergeEntryCount = 0x0084, + MigrateOfferToManualThroughput = 0x0085, + MigrateOfferToAutopilot = 0x0086, + IsClientEncrypted = 0x0087, + SystemDocumentType = 0x0088, + IsofferStorageRefreshRequest = 0x0089, + ResourceTypes = 0x008A, + TransactionId = 0x008B, + TransactionFirstRequest = 0x008C, + TransactionCommit = 0x008D, + SystemDocumentName = 0x008E, + UpdateMaxThroughputEverProvisioned = 0x008F, + UniqueIndexReIndexingState = 0x0090, + RoleDefinitionName = 0x0091, + RoleAssignmentName = 0x0092, + UseSystemBudget = 0x0093, + IgnoreSystemLoweringMaxThroughput = 0x0094, + TruncateMergeLogRequest = 0x0095, + RetriableWriteRequestId = 0x0096, + IsRetriedWriteRequest = 0x0097, + RetriableWriteRequestStartTimestamp = 0x0098, + AddResourcePropertiesToResponse = 0x0099, + ChangeFeedStartFullFidelityIfNoneMatch = 0x009A, + SystemRestoreOperation = 0x009B, + SkipRefreshDatabaseAccountConfigs = 0x009C, + IntendedCollectionRid = 0x009D, + UseArchivalPartition = 0x009E, + PopulateUniqueIndexReIndexProgress = 0x009F, + CollectionSchemaId = 0x00A0, + CollectionTruncate = 0x00A1, + SDKSupportedCapabilities = 0x00A2, + IsMaterializedViewBuild = 0x00A3, + BuilderClientIdentifier = 0x00A4, + SourceCollectionIfMatch = 0x00A5, + RequestedCollectionType = 0x00A6, + InteropUserName = 0x00A8, + PopulateIndexMetrics = 0x00A9, + PopulateAnalyticalMigrationProgress = 0x00AA, + AuthPolicyElementName = 0x00AB, + ShouldReturnCurrentServerDateTime = 0x00AC, + RbacUserId = 0x00AD, + RbacAction = 0x00AE, + RbacResource = 0x00AF, + CorrelatedActivityId = 0x00B0, + IsThroughputCapRequest = 0x00B1, + ChangeFeedWireFormatVersion = 0x00B2, + PopulateBYOKEncryptionProgress = 0x00B3, + UseUserBackgroundBudget = 0x00B4, + IncludePhysicalPartitionThroughputInfo = 0x00B5, + IsServerlessStorageRefreshRequest = 0x00B6, + UpdateOfferStateToPending = 0x00B7, + PopulateOldestActiveSchemaId = 0x00B8, + IsInternalServerlessRequest = 0x00B9, + OfferReplaceRURedistribution = 0x00BA, + IsCassandraAlterTypeRequest = 0x00BB, + IsMaterializedViewSourceSchemaReplaceBatchRequest = 0x00BC, + ForceDatabaseAccountUpdate = 0x00BD, + EncryptionScopeName = 0x00BE, + PriorityLevel = 0x00BF, + AllowRestoreParamsUpdate = 0x00C0, + PruneCollectionSchemas = 0x00C1, + PopulateIndexMetricsV2 = 0x00C2, + IsMigratedFixedCollection = 0x00C3, + SupportedSerializationFormats = 0x00C4, + UpdateOfferStateToRestorePending = 0x00C5, + SetMasterResourcesDeletionPending = 0x00C6, + HighPriorityForcedBackup = 0x00C7, + OptimisticDirectExecute = 0x00C8, + PopulateMinGLSNForDocumentOperations = 0x00C9, + PopulateHighestTentativeWriteLLSN = 0x00CA, + PopulateCapacityType = 0x00CB, + TraceParent = 0x00CC, + TraceState = 0x00CD, + GlobalDatabaseAccountName = 0x00CE, + EnableConflictResolutionPolicyUpdate = 0x00CF, + ClientIpAddress = 0x00D0, + IsRequestNotAuthorized = 0x00D1, + StartEpkHash = 0x00D2, + EndEpkHash = 0x00D3, + AllowDocumentReadsInOfflineRegion = 0x00D4, + PopulateCurrentPartitionThroughputInfo = 0x00D5, + PopulateDocumentRecordCount = 0x00D6, + CosmosGatewayTransactionId = 0x00D7, + PopulateUserStrings = 0x00D8, + SkipThroughputCapValidation = 0x00D9, + } + + public sealed class Request : RntbdTokenStream + { + public override int RequiredTokenCount => 2; + + public RntbdToken resourceId; + public RntbdToken authorizationToken; + public RntbdToken payloadPresent; + public RntbdToken date; + public RntbdToken pageSize; + public RntbdToken sessionToken; + public RntbdToken continuationToken; + public RntbdToken indexingDirective; + public RntbdToken match; + public RntbdToken preTriggerInclude; + public RntbdToken postTriggerInclude; + public RntbdToken isFanout; + public RntbdToken collectionPartitionIndex; + public RntbdToken collectionServiceIndex; + public RntbdToken preTriggerExclude; + public RntbdToken postTriggerExclude; + public RntbdToken consistencyLevel; + public RntbdToken entityId; + public RntbdToken resourceSchemaName; + public RntbdToken replicaPath; + public RntbdToken resourceTokenExpiry; + public RntbdToken databaseName; + public RntbdToken collectionName; + public RntbdToken documentName; + public RntbdToken attachmentName; + public RntbdToken userName; + public RntbdToken permissionName; + public RntbdToken storedProcedureName; + public RntbdToken userDefinedFunctionName; + public RntbdToken triggerName; + public RntbdToken enableScanInQuery; + public RntbdToken emitVerboseTracesInQuery; + public RntbdToken conflictName; + public RntbdToken bindReplicaDirective; + public RntbdToken primaryMasterKey; + public RntbdToken secondaryMasterKey; + public RntbdToken primaryReadonlyKey; + public RntbdToken secondaryReadonlyKey; + public RntbdToken profileRequest; + public RntbdToken enableLowPrecisionOrderBy; + public RntbdToken clientVersion; + public RntbdToken canCharge; + public RntbdToken canThrottle; + public RntbdToken partitionKey; + public RntbdToken partitionKeyRangeId; + public RntbdToken migrateCollectionDirective; + public RntbdToken supportSpatialLegacyCoordinates; + public RntbdToken partitionCount; + public RntbdToken collectionRid; + public RntbdToken partitionKeyRangeName; + public RntbdToken schemaName; + public RntbdToken filterBySchemaRid; + public RntbdToken usePolygonsSmallerThanAHemisphere; + public RntbdToken gatewaySignature; + public RntbdToken enableLogging; + public RntbdToken a_IM; + public RntbdToken populateQuotaInfo; + public RntbdToken disableRUPerMinuteUsage; + public RntbdToken populateQueryMetrics; + public RntbdToken responseContinuationTokenLimitInKb; + public RntbdToken populatePartitionStatistics; + public RntbdToken remoteStorageType; + public RntbdToken collectionRemoteStorageSecurityIdentifier; + public RntbdToken ifModifiedSince; + public RntbdToken populateCollectionThroughputInfo; + public RntbdToken remainingTimeInMsOnClientRequest; + public RntbdToken clientRetryAttemptCount; + public RntbdToken targetLsn; + public RntbdToken targetGlobalCommittedLsn; + public RntbdToken transportRequestID; + public RntbdToken restoreMetadataFilter; + public RntbdToken restoreParams; + public RntbdToken shareThroughput; + public RntbdToken partitionResourceFilter; + public RntbdToken isReadOnlyScript; + public RntbdToken isAutoScaleRequest; + public RntbdToken forceQueryScan; + public RntbdToken canOfferReplaceComplete; + public RntbdToken excludeSystemProperties; + public RntbdToken binaryId; + public RntbdToken timeToLiveInSeconds; + public RntbdToken effectivePartitionKey; + public RntbdToken binaryPassthroughRequest; + public RntbdToken userDefinedTypeName; + public RntbdToken enableDynamicRidRangeAllocation; + public RntbdToken enumerationDirection; + public RntbdToken startId; + public RntbdToken endId; + public RntbdToken fanoutOperationState; + public RntbdToken startEpk; + public RntbdToken endEpk; + public RntbdToken readFeedKeyType; + public RntbdToken contentSerializationFormat; + public RntbdToken allowTentativeWrites; + public RntbdToken isUserRequest; + public RntbdToken preserveFullContent; + public RntbdToken includeTentativeWrites; + public RntbdToken populateResourceCount; + public RntbdToken mergeStaticId; + public RntbdToken isBatchAtomic; + public RntbdToken shouldBatchContinueOnError; + public RntbdToken isBatchOrdered; + public RntbdToken schemaOwnerRid; + public RntbdToken schemaHash; + public RntbdToken isRUPerGBEnforcementRequest; + public RntbdToken maxPollingIntervalMilliseconds; + public RntbdToken snapshotName; + public RntbdToken populateLogStoreInfo; + public RntbdToken getAllPartitionKeyStatistics; + public RntbdToken forceSideBySideIndexMigration; + public RntbdToken collectionChildResourceNameLimitInBytes; + public RntbdToken collectionChildResourceContentLengthLimitInKB; + public RntbdToken clientEncryptionKeyName; + public RntbdToken mergeCheckpointGLSNKeyName; + public RntbdToken returnPreference; + public RntbdToken uniqueIndexNameEncodingMode; + public RntbdToken populateUnflushedMergeEntryCount; + public RntbdToken migrateOfferToManualThroughput; + public RntbdToken migrateOfferToAutopilot; + public RntbdToken isClientEncrypted; + public RntbdToken systemDocumentType; + public RntbdToken isofferStorageRefreshRequest; + public RntbdToken resourceTypes; + public RntbdToken transactionId; + public RntbdToken transactionFirstRequest; + public RntbdToken transactionCommit; + public RntbdToken systemDocumentName; + public RntbdToken updateMaxThroughputEverProvisioned; + public RntbdToken uniqueIndexReIndexingState; + public RntbdToken roleDefinitionName; + public RntbdToken roleAssignmentName; + public RntbdToken useSystemBudget; + public RntbdToken ignoreSystemLoweringMaxThroughput; + public RntbdToken truncateMergeLogRequest; + public RntbdToken retriableWriteRequestId; + public RntbdToken isRetriedWriteRequest; + public RntbdToken retriableWriteRequestStartTimestamp; + public RntbdToken addResourcePropertiesToResponse; + public RntbdToken changeFeedStartFullFidelityIfNoneMatch; + public RntbdToken systemRestoreOperation; + public RntbdToken skipRefreshDatabaseAccountConfigs; + public RntbdToken intendedCollectionRid; + public RntbdToken useArchivalPartition; + public RntbdToken populateUniqueIndexReIndexProgress; + public RntbdToken collectionSchemaId; + public RntbdToken collectionTruncate; + public RntbdToken sDKSupportedCapabilities; + public RntbdToken isMaterializedViewBuild; + public RntbdToken builderClientIdentifier; + public RntbdToken sourceCollectionIfMatch; + public RntbdToken requestedCollectionType; + public RntbdToken interopUserName; + public RntbdToken populateIndexMetrics; + public RntbdToken populateAnalyticalMigrationProgress; + public RntbdToken authPolicyElementName; + public RntbdToken shouldReturnCurrentServerDateTime; + public RntbdToken rbacUserId; + public RntbdToken rbacAction; + public RntbdToken rbacResource; + public RntbdToken correlatedActivityId; + public RntbdToken isThroughputCapRequest; + public RntbdToken changeFeedWireFormatVersion; + public RntbdToken populateBYOKEncryptionProgress; + public RntbdToken useUserBackgroundBudget; + public RntbdToken includePhysicalPartitionThroughputInfo; + public RntbdToken isServerlessStorageRefreshRequest; + public RntbdToken updateOfferStateToPending; + public RntbdToken populateOldestActiveSchemaId; + public RntbdToken isInternalServerlessRequest; + public RntbdToken offerReplaceRURedistribution; + public RntbdToken isCassandraAlterTypeRequest; + public RntbdToken isMaterializedViewSourceSchemaReplaceBatchRequest; + public RntbdToken forceDatabaseAccountUpdate; + public RntbdToken encryptionScopeName; + public RntbdToken priorityLevel; + public RntbdToken allowRestoreParamsUpdate; + public RntbdToken pruneCollectionSchemas; + public RntbdToken populateIndexMetricsV2; + public RntbdToken isMigratedFixedCollection; + public RntbdToken supportedSerializationFormats; + public RntbdToken updateOfferStateToRestorePending; + public RntbdToken setMasterResourcesDeletionPending; + public RntbdToken highPriorityForcedBackup; + public RntbdToken optimisticDirectExecute; + public RntbdToken populateMinGLSNForDocumentOperations; + public RntbdToken populateHighestTentativeWriteLLSN; + public RntbdToken populateCapacityType; + public RntbdToken traceParent; + public RntbdToken traceState; + public RntbdToken globalDatabaseAccountName; + public RntbdToken enableConflictResolutionPolicyUpdate; + public RntbdToken clientIpAddress; + public RntbdToken isRequestNotAuthorized; + public RntbdToken startEpkHash; + public RntbdToken endEpkHash; + public RntbdToken allowDocumentReadsInOfflineRegion; + public RntbdToken populateCurrentPartitionThroughputInfo; + public RntbdToken populateDocumentRecordCount; + public RntbdToken cosmosGatewayTransactionId; + public RntbdToken populateUserStrings; + public RntbdToken skipThroughputCapValidation; + + public Request() + { + this.resourceId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.ResourceId); + this.authorizationToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AuthorizationToken); + this.payloadPresent = new RntbdToken(true, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PayloadPresent); + this.date = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.Date); + this.pageSize = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.PageSize); + this.sessionToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SessionToken); + this.continuationToken = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ContinuationToken); + this.indexingDirective = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IndexingDirective); + this.match = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.Match); + this.preTriggerInclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PreTriggerInclude); + this.postTriggerInclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PostTriggerInclude); + this.isFanout = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsFanout); + this.collectionPartitionIndex = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.CollectionPartitionIndex); + this.collectionServiceIndex = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.CollectionServiceIndex); + this.preTriggerExclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PreTriggerExclude); + this.postTriggerExclude = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PostTriggerExclude); + this.consistencyLevel = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ConsistencyLevel); + this.entityId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.EntityId); + this.resourceSchemaName = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.ResourceSchemaName); + this.replicaPath = new RntbdToken(true, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ReplicaPath); + this.resourceTokenExpiry = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ResourceTokenExpiry); + this.databaseName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.DatabaseName); + this.collectionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionName); + this.documentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.DocumentName); + this.attachmentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AttachmentName); + this.userName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserName); + this.permissionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PermissionName); + this.storedProcedureName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.StoredProcedureName); + this.userDefinedFunctionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserDefinedFunctionName); + this.triggerName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TriggerName); + this.enableScanInQuery = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableScanInQuery); + this.emitVerboseTracesInQuery = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EmitVerboseTracesInQuery); + this.conflictName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ConflictName); + this.bindReplicaDirective = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.BindReplicaDirective); + this.primaryMasterKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PrimaryMasterKey); + this.secondaryMasterKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SecondaryMasterKey); + this.primaryReadonlyKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PrimaryReadonlyKey); + this.secondaryReadonlyKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SecondaryReadonlyKey); + this.profileRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ProfileRequest); + this.enableLowPrecisionOrderBy = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableLowPrecisionOrderBy); + this.clientVersion = new RntbdToken(false, RntbdTokenTypes.SmallString, (ushort)RequestIdentifiers.ClientVersion); + this.canCharge = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanCharge); + this.canThrottle = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanThrottle); + this.partitionKey = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKey); + this.partitionKeyRangeId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKeyRangeId); + this.migrateCollectionDirective = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateCollectionDirective); + this.supportSpatialLegacyCoordinates = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SupportSpatialLegacyCoordinates); + this.partitionCount = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.PartitionCount); + this.collectionRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionRid); + this.partitionKeyRangeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionKeyRangeName); + this.schemaName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SchemaName); + this.filterBySchemaRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.FilterBySchemaRid); + this.usePolygonsSmallerThanAHemisphere = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UsePolygonsSmallerThanAHemisphere); + this.gatewaySignature = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.GatewaySignature); + this.enableLogging = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableLogging); + this.a_IM = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.A_IM); + this.populateQuotaInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateQuotaInfo); + this.disableRUPerMinuteUsage = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.DisableRUPerMinuteUsage); + this.populateQueryMetrics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateQueryMetrics); + this.responseContinuationTokenLimitInKb = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ResponseContinuationTokenLimitInKb); + this.populatePartitionStatistics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulatePartitionStatistics); + this.remoteStorageType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.RemoteStorageType); + this.collectionRemoteStorageSecurityIdentifier = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.CollectionRemoteStorageSecurityIdentifier); + this.ifModifiedSince = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IfModifiedSince); + this.populateCollectionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCollectionThroughputInfo); + this.remainingTimeInMsOnClientRequest = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.RemainingTimeInMsOnClientRequest); + this.clientRetryAttemptCount = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.ClientRetryAttemptCount); + this.targetLsn = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.TargetLsn); + this.targetGlobalCommittedLsn = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.TargetGlobalCommittedLsn); + this.transportRequestID = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.TransportRequestID); + this.restoreMetadataFilter = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RestoreMetadataFilter); + this.restoreParams = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RestoreParams); + this.shareThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShareThroughput); + this.partitionResourceFilter = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.PartitionResourceFilter); + this.isReadOnlyScript = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsReadOnlyScript); + this.isAutoScaleRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsAutoScaleRequest); + this.forceQueryScan = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceQueryScan); + this.canOfferReplaceComplete = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CanOfferReplaceComplete); + this.excludeSystemProperties = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ExcludeSystemProperties); + this.binaryId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.BinaryId); + this.timeToLiveInSeconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.TimeToLiveInSeconds); + this.effectivePartitionKey = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EffectivePartitionKey); + this.binaryPassthroughRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.BinaryPassthroughRequest); + this.userDefinedTypeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.UserDefinedTypeName); + this.enableDynamicRidRangeAllocation = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableDynamicRidRangeAllocation); + this.enumerationDirection = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnumerationDirection); + this.startId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartId); + this.endId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndId); + this.fanoutOperationState = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.FanoutOperationState); + this.startEpk = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartEpk); + this.endEpk = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndEpk); + this.readFeedKeyType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ReadFeedKeyType); + this.contentSerializationFormat = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ContentSerializationFormat); + this.allowTentativeWrites = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AllowTentativeWrites); + this.isUserRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsUserRequest); + this.preserveFullContent = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PreserveFullContent); + this.includeTentativeWrites = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IncludeTentativeWrites); + this.populateResourceCount = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateResourceCount); + this.mergeStaticId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.MergeStaticId); + this.isBatchAtomic = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsBatchAtomic); + this.shouldBatchContinueOnError = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShouldBatchContinueOnError); + this.isBatchOrdered = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsBatchOrdered); + this.schemaOwnerRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SchemaOwnerRid); + this.schemaHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.SchemaHash); + this.isRUPerGBEnforcementRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRUPerGBEnforcementRequest); + this.maxPollingIntervalMilliseconds = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.MaxPollingIntervalMilliseconds); + this.snapshotName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SnapshotName); + this.populateLogStoreInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateLogStoreInfo); + this.getAllPartitionKeyStatistics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.GetAllPartitionKeyStatistics); + this.forceSideBySideIndexMigration = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceSideBySideIndexMigration); + this.collectionChildResourceNameLimitInBytes = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.CollectionChildResourceNameLimitInBytes); + this.collectionChildResourceContentLengthLimitInKB = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.CollectionChildResourceContentLengthLimitInKB); + this.clientEncryptionKeyName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ClientEncryptionKeyName); + this.mergeCheckpointGLSNKeyName = new RntbdToken(false, RntbdTokenTypes.LongLong, (ushort)RequestIdentifiers.MergeCheckpointGLSNKeyName); + this.returnPreference = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ReturnPreference); + this.uniqueIndexNameEncodingMode = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UniqueIndexNameEncodingMode); + this.populateUnflushedMergeEntryCount = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateUnflushedMergeEntryCount); + this.migrateOfferToManualThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateOfferToManualThroughput); + this.migrateOfferToAutopilot = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.MigrateOfferToAutopilot); + this.isClientEncrypted = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsClientEncrypted); + this.systemDocumentType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SystemDocumentType); + this.isofferStorageRefreshRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsofferStorageRefreshRequest); + this.resourceTypes = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ResourceTypes); + this.transactionId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.TransactionId); + this.transactionFirstRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TransactionFirstRequest); + this.transactionCommit = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TransactionCommit); + this.systemDocumentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SystemDocumentName); + this.updateMaxThroughputEverProvisioned = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.UpdateMaxThroughputEverProvisioned); + this.uniqueIndexReIndexingState = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UniqueIndexReIndexingState); + this.roleDefinitionName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RoleDefinitionName); + this.roleAssignmentName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RoleAssignmentName); + this.useSystemBudget = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseSystemBudget); + this.ignoreSystemLoweringMaxThroughput = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IgnoreSystemLoweringMaxThroughput); + this.truncateMergeLogRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.TruncateMergeLogRequest); + this.retriableWriteRequestId = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.RetriableWriteRequestId); + this.isRetriedWriteRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRetriedWriteRequest); + this.retriableWriteRequestStartTimestamp = new RntbdToken(false, RntbdTokenTypes.ULongLong, (ushort)RequestIdentifiers.RetriableWriteRequestStartTimestamp); + this.addResourcePropertiesToResponse = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AddResourcePropertiesToResponse); + this.changeFeedStartFullFidelityIfNoneMatch = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ChangeFeedStartFullFidelityIfNoneMatch); + this.systemRestoreOperation = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SystemRestoreOperation); + this.skipRefreshDatabaseAccountConfigs = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SkipRefreshDatabaseAccountConfigs); + this.intendedCollectionRid = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IntendedCollectionRid); + this.useArchivalPartition = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseArchivalPartition); + this.populateUniqueIndexReIndexProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateUniqueIndexReIndexProgress); + this.collectionSchemaId = new RntbdToken(false, RntbdTokenTypes.Long, (ushort)RequestIdentifiers.CollectionSchemaId); + this.collectionTruncate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.CollectionTruncate); + this.sDKSupportedCapabilities = new RntbdToken(false, RntbdTokenTypes.ULong, (ushort)RequestIdentifiers.SDKSupportedCapabilities); + this.isMaterializedViewBuild = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMaterializedViewBuild); + this.builderClientIdentifier = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.BuilderClientIdentifier); + this.sourceCollectionIfMatch = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.SourceCollectionIfMatch); + this.requestedCollectionType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.RequestedCollectionType); + this.interopUserName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.InteropUserName); + this.populateIndexMetrics = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateIndexMetrics); + this.populateAnalyticalMigrationProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateAnalyticalMigrationProgress); + this.authPolicyElementName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AuthPolicyElementName); + this.shouldReturnCurrentServerDateTime = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ShouldReturnCurrentServerDateTime); + this.rbacUserId = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacUserId); + this.rbacAction = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacAction); + this.rbacResource = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.RbacResource); + this.correlatedActivityId = new RntbdToken(false, RntbdTokenTypes.Guid, (ushort)RequestIdentifiers.CorrelatedActivityId); + this.isThroughputCapRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsThroughputCapRequest); + this.changeFeedWireFormatVersion = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ChangeFeedWireFormatVersion); + this.populateBYOKEncryptionProgress = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateBYOKEncryptionProgress); + this.useUserBackgroundBudget = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UseUserBackgroundBudget); + this.includePhysicalPartitionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.IncludePhysicalPartitionThroughputInfo); + this.isServerlessStorageRefreshRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsServerlessStorageRefreshRequest); + this.updateOfferStateToPending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UpdateOfferStateToPending); + this.populateOldestActiveSchemaId = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateOldestActiveSchemaId); + this.isInternalServerlessRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsInternalServerlessRequest); + this.offerReplaceRURedistribution = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.OfferReplaceRURedistribution); + this.isCassandraAlterTypeRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsCassandraAlterTypeRequest); + this.isMaterializedViewSourceSchemaReplaceBatchRequest = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMaterializedViewSourceSchemaReplaceBatchRequest); + this.forceDatabaseAccountUpdate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.ForceDatabaseAccountUpdate); + this.encryptionScopeName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.EncryptionScopeName); + this.priorityLevel = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PriorityLevel); + this.allowRestoreParamsUpdate = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.AllowRestoreParamsUpdate); + this.pruneCollectionSchemas = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PruneCollectionSchemas); + this.populateIndexMetricsV2 = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateIndexMetricsV2); + this.isMigratedFixedCollection = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsMigratedFixedCollection); + this.supportedSerializationFormats = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SupportedSerializationFormats); + this.updateOfferStateToRestorePending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.UpdateOfferStateToRestorePending); + this.setMasterResourcesDeletionPending = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SetMasterResourcesDeletionPending); + this.highPriorityForcedBackup = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.HighPriorityForcedBackup); + this.optimisticDirectExecute = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.OptimisticDirectExecute); + this.populateMinGLSNForDocumentOperations = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateMinGLSNForDocumentOperations); + this.populateHighestTentativeWriteLLSN = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateHighestTentativeWriteLLSN); + this.populateCapacityType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCapacityType); + this.traceParent = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceParent); + this.traceState = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceState); + this.globalDatabaseAccountName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.GlobalDatabaseAccountName); + this.enableConflictResolutionPolicyUpdate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableConflictResolutionPolicyUpdate); + this.clientIpAddress = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ClientIpAddress); + this.isRequestNotAuthorized = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRequestNotAuthorized); + this.startEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartEpkHash); + this.endEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndEpkHash); + this.allowDocumentReadsInOfflineRegion = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AllowDocumentReadsInOfflineRegion); + this.populateCurrentPartitionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCurrentPartitionThroughputInfo); + this.populateDocumentRecordCount = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateDocumentRecordCount); + this.cosmosGatewayTransactionId = new RntbdToken(false, RntbdTokenTypes.Guid, (ushort)RequestIdentifiers.CosmosGatewayTransactionId); + this.populateUserStrings = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateUserStrings); + this.skipThroughputCapValidation = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.SkipThroughputCapValidation); + + this.tokens = new RntbdToken[] + { + this.resourceId, + this.authorizationToken, + this.payloadPresent, + this.date, + this.pageSize, + this.sessionToken, + this.continuationToken, + this.indexingDirective, + this.match, + this.preTriggerInclude, + this.postTriggerInclude, + this.isFanout, + this.collectionPartitionIndex, + this.collectionServiceIndex, + this.preTriggerExclude, + this.postTriggerExclude, + this.consistencyLevel, + this.entityId, + this.resourceSchemaName, + this.replicaPath, + this.resourceTokenExpiry, + this.databaseName, + this.collectionName, + this.documentName, + this.attachmentName, + this.userName, + this.permissionName, + this.storedProcedureName, + this.userDefinedFunctionName, + this.triggerName, + this.enableScanInQuery, + this.emitVerboseTracesInQuery, + this.conflictName, + this.bindReplicaDirective, + this.primaryMasterKey, + this.secondaryMasterKey, + this.primaryReadonlyKey, + this.secondaryReadonlyKey, + this.profileRequest, + this.enableLowPrecisionOrderBy, + this.clientVersion, + this.canCharge, + this.canThrottle, + this.partitionKey, + this.partitionKeyRangeId, + null, // 0x002D + null, // 0x002E + null, // 0x002F + null, // 0x0030 + this.migrateCollectionDirective, + null, // 0x0032 + this.supportSpatialLegacyCoordinates, + this.partitionCount, + this.collectionRid, + this.partitionKeyRangeName, + null, // 0x0037 + null, // 0x0038 + null, // 0x0039 + this.schemaName, + this.filterBySchemaRid, + this.usePolygonsSmallerThanAHemisphere, + this.gatewaySignature, + this.enableLogging, + this.a_IM, + this.populateQuotaInfo, + this.disableRUPerMinuteUsage, + this.populateQueryMetrics, + this.responseContinuationTokenLimitInKb, + this.populatePartitionStatistics, + this.remoteStorageType, + this.collectionRemoteStorageSecurityIdentifier, + this.ifModifiedSince, + this.populateCollectionThroughputInfo, + this.remainingTimeInMsOnClientRequest, + this.clientRetryAttemptCount, + this.targetLsn, + this.targetGlobalCommittedLsn, + this.transportRequestID, + this.restoreMetadataFilter, + this.restoreParams, + this.shareThroughput, + this.partitionResourceFilter, + this.isReadOnlyScript, + this.isAutoScaleRequest, + this.forceQueryScan, + null, // 0x0055 + this.canOfferReplaceComplete, + this.excludeSystemProperties, + this.binaryId, + this.timeToLiveInSeconds, + this.effectivePartitionKey, + this.binaryPassthroughRequest, + this.userDefinedTypeName, + this.enableDynamicRidRangeAllocation, + this.enumerationDirection, + this.startId, + this.endId, + this.fanoutOperationState, + this.startEpk, + this.endEpk, + this.readFeedKeyType, + this.contentSerializationFormat, + this.allowTentativeWrites, + this.isUserRequest, + null, // 0x0068 + this.preserveFullContent, + null, // 0x006A + null, // 0x006B + null, // 0x006C + null, // 0x006D + null, // 0x006E + null, // 0x006F + this.includeTentativeWrites, + this.populateResourceCount, + this.mergeStaticId, + this.isBatchAtomic, + this.shouldBatchContinueOnError, + this.isBatchOrdered, + this.schemaOwnerRid, + this.schemaHash, + this.isRUPerGBEnforcementRequest, + this.maxPollingIntervalMilliseconds, + this.snapshotName, + this.populateLogStoreInfo, + this.getAllPartitionKeyStatistics, + this.forceSideBySideIndexMigration, + this.collectionChildResourceNameLimitInBytes, + this.collectionChildResourceContentLengthLimitInKB, + this.clientEncryptionKeyName, + this.mergeCheckpointGLSNKeyName, + this.returnPreference, + this.uniqueIndexNameEncodingMode, + this.populateUnflushedMergeEntryCount, + this.migrateOfferToManualThroughput, + this.migrateOfferToAutopilot, + this.isClientEncrypted, + this.systemDocumentType, + this.isofferStorageRefreshRequest, + this.resourceTypes, + this.transactionId, + this.transactionFirstRequest, + this.transactionCommit, + this.systemDocumentName, + this.updateMaxThroughputEverProvisioned, + this.uniqueIndexReIndexingState, + this.roleDefinitionName, + this.roleAssignmentName, + this.useSystemBudget, + this.ignoreSystemLoweringMaxThroughput, + this.truncateMergeLogRequest, + this.retriableWriteRequestId, + this.isRetriedWriteRequest, + this.retriableWriteRequestStartTimestamp, + this.addResourcePropertiesToResponse, + this.changeFeedStartFullFidelityIfNoneMatch, + this.systemRestoreOperation, + this.skipRefreshDatabaseAccountConfigs, + this.intendedCollectionRid, + this.useArchivalPartition, + this.populateUniqueIndexReIndexProgress, + this.collectionSchemaId, + this.collectionTruncate, + this.sDKSupportedCapabilities, + this.isMaterializedViewBuild, + this.builderClientIdentifier, + this.sourceCollectionIfMatch, + this.requestedCollectionType, + null, // 0x00A7 + this.interopUserName, + this.populateIndexMetrics, + this.populateAnalyticalMigrationProgress, + this.authPolicyElementName, + this.shouldReturnCurrentServerDateTime, + this.rbacUserId, + this.rbacAction, + this.rbacResource, + this.correlatedActivityId, + this.isThroughputCapRequest, + this.changeFeedWireFormatVersion, + this.populateBYOKEncryptionProgress, + this.useUserBackgroundBudget, + this.includePhysicalPartitionThroughputInfo, + this.isServerlessStorageRefreshRequest, + this.updateOfferStateToPending, + this.populateOldestActiveSchemaId, + this.isInternalServerlessRequest, + this.offerReplaceRURedistribution, + this.isCassandraAlterTypeRequest, + this.isMaterializedViewSourceSchemaReplaceBatchRequest, + this.forceDatabaseAccountUpdate, + this.encryptionScopeName, + this.priorityLevel, + this.allowRestoreParamsUpdate, + this.pruneCollectionSchemas, + this.populateIndexMetricsV2, + this.isMigratedFixedCollection, + this.supportedSerializationFormats, + this.updateOfferStateToRestorePending, + this.setMasterResourcesDeletionPending, + this.highPriorityForcedBackup, + this.optimisticDirectExecute, + this.populateMinGLSNForDocumentOperations, + this.populateHighestTentativeWriteLLSN, + this.populateCapacityType, + this.traceParent, + this.traceState, + this.globalDatabaseAccountName, + this.enableConflictResolutionPolicyUpdate, + this.clientIpAddress, + this.isRequestNotAuthorized, + this.startEpkHash, + this.endEpkHash, + this.allowDocumentReadsInOfflineRegion, + this.populateCurrentPartitionThroughputInfo, + this.populateDocumentRecordCount, + this.cosmosGatewayTransactionId, + this.populateUserStrings, + this.skipThroughputCapValidation, + }; + } + } + + // Values are generated from the common source where response headers ordered by the chance headers could apper on response. + // This order helps in constracting more performant switch statements in the loop(s) processing response headers. + public enum ResponseIdentifiers : ushort + { + TransportRequestID = 0x0035, + ServerDateTimeUtc = 0x0039, + SubStatus = 0x001C, + ETag = 0x0004, + ResourceName = 0x0047, + RequestCharge = 0x0015, + SessionToken = 0x003E, + ContinuationToken = 0x0003, + LSN = 0x0013, + GlobalCommittedLSN = 0x0029, + ItemLSN = 0x0032, + LocalLSN = 0x003A, + QuorumAckedLocalLSN = 0x003B, + ItemLocalLSN = 0x003C, + PayloadPresent = 0x0000, + LastStateChangeDateTime = 0x0002, + RetryAfterMilliseconds = 0x000C, + IndexingDirective = 0x000D, + StorageMaxResoureQuota = 0x000E, + StorageResourceQuotaUsage = 0x000F, + SchemaVersion = 0x0010, + CollectionPartitionIndex = 0x0011, + CollectionServiceIndex = 0x0012, + ItemCount = 0x0014, + OwnerFullName = 0x0017, + OwnerId = 0x0018, + DatabaseAccountId = 0x0019, + QuorumAckedLSN = 0x001A, + RequestValidationFailure = 0x001B, + CollectionUpdateProgress = 0x001D, + CurrentWriteQuorum = 0x001E, + CurrentReplicaSetSize = 0x001F, + CollectionLazyIndexProgress = 0x0020, + PartitionKeyRangeId = 0x0021, + LogResults = 0x0025, + XPRole = 0x0026, + IsRUPerMinuteUsed = 0x0027, + QueryMetrics = 0x0028, + NumberOfReadRegions = 0x0030, + OfferReplacePending = 0x0031, + RestoreState = 0x0033, + CollectionSecurityIdentifier = 0x0034, + ShareThroughput = 0x0036, + DisableRntbdChannel = 0x0038, + HasTentativeWrites = 0x003D, + ReplicatorLSNToGLSNDelta = 0x003F, + ReplicatorLSNToLLSNDelta = 0x0040, + VectorClockLocalProgress = 0x0041, + MinimumRUsForOffer = 0x0042, + XPConfigurationSessionsCount = 0x0043, + IndexUtilization = 0x0044, + QueryExecutionInfo = 0x0045, + UnflushedMergeLogEntryCount = 0x0046, + TimeToLiveInSeconds = 0x0048, + ReplicaStatusRevoked = 0x0049, + SoftMaxAllowedThroughput = 0x0050, + BackendRequestDurationMilliseconds = 0x0051, + CorrelatedActivityId = 0x0052, + ConfirmedStoreChecksum = 0x0053, + TentativeStoreChecksum = 0x0054, + PendingPKDelete = 0x0055, + AadAppliedRoleAssignmentId = 0x0056, + CollectionUniqueIndexReIndexProgress = 0x0057, + CollectionUniqueKeysUnderReIndex = 0x0058, + AnalyticalMigrationProgress = 0x0059, + TotalAccountThroughput = 0x005A, + BYOKEncryptionProgress = 0x005B, + AppliedPolicyElementId = 0x005C, + MergeProgressBlocked = 0x005D, + ChangeFeedInfo = 0x005E, + ReindexerProgress = 0x005F, + OfferReplacePendingForMerge = 0x0060, + MaxContentLength = 0x0061, + OldestActiveSchemaId = 0x0062, + PhysicalPartitionId = 0x0063, + OfferRestorePending = 0x0064, + InstantScaleUpValue = 0x0065, + RequiresDistribution = 0x0066, + CapacityType = 0x0067, + MinGLSNForDocumentOperations = 0x0068, + MinGLSNForTombstoneOperations = 0x0069, + HighestTentativeWriteLLSN = 0x0070, + PartitionThroughputInfo = 0x0071, + DocumentRecordCount = 0x0072, + CosmosGatewayTransactionId = 0x0073, + UserStrings = 0x0074, + } + + // + // DEVNOTE: This enumeration is used only for the logging purpose. Do not use it for any other purpose. + // + public enum CallerId : byte + { + /// + /// The default caller Id + /// + Anonymous = 0x00, + + /// + /// The connection request is made by Gateway + /// + Gateway = 0x01, + + /// + /// The connection request is made by BackgroundTask + /// + BackgroundTask = 0x02, + + /// + /// The connection request is made by ManagementWorkerRuntime + /// + ManagementWorker = 0x03, + + /// + /// Invalid caller Id + /// + Invalid = 0x04, + } + + internal sealed class RntbdEntityPool + where T : RntbdTokenStream, new() + where TU : Enum + { + public static readonly RntbdEntityPool Instance = new RntbdEntityPool(); + + private readonly ConcurrentQueue entities = new ConcurrentQueue(); + + private RntbdEntityPool() + { + } + + public EntityOwner Get() + { + if (this.entities.TryDequeue(out T entity)) + { + return new EntityOwner(entity); + } + + return new EntityOwner(new T()); + } + + private void Return(T entity) + { + entity.Reset(); + this.entities.Enqueue(entity); + } + + public readonly struct EntityOwner : IDisposable + { + public EntityOwner(T entity) + { + this.Entity = entity; + } + + public T Entity { get; } + + public void Dispose() + { + if (this.Entity != null) + { + RntbdEntityPool.Instance.Return(this.Entity); + } + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdOpenConnectionHandler.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdOpenConnectionHandler.cs index 84a3b1ee97..2b9e39f811 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdOpenConnectionHandler.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdOpenConnectionHandler.cs @@ -1,127 +1,127 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents; - -#if !NETSTANDARD16 - using System.Diagnostics; -#endif - - /// - /// Handler class to open Rntbd connections to backend replica nodes. - /// - internal sealed class RntbdOpenConnectionHandler : IOpenConnectionsHandler, IDisposable - { - /// - /// A read-only instance of - /// - private readonly TransportClient transportClient; - - /// - /// A read-only instance of for - /// concurrency control. - /// - private readonly SemaphoreSlim semaphore; - - /// - /// A read-only TimeSpan indicating the semephore timeout in minutes. - /// The default timeout is 10 minutes. - /// - private static readonly TimeSpan SemaphoreAcquireTimeout = TimeSpan.FromMinutes(10); - - /// - /// A booolean flag indicating if the current instance of RntbdOpenConnectionHandler - /// has been disposed. - /// - private bool disposed; - - /// - /// Constructor to initialize the . - /// - /// A reference to the . - public RntbdOpenConnectionHandler( - TransportClient transportClient) - { - this.disposed = false; - this.transportClient = transportClient ?? throw new ArgumentNullException(nameof(transportClient), $"Argument {nameof(transportClient)} can not be null"); - - // The semaphore arguments `initialCount` and `maxCount` are set to match the number of cpu cores, to keep the - // implementation similar to the Java counterpart. - this.semaphore = new SemaphoreSlim( - initialCount: Environment.ProcessorCount, - maxCount: Environment.ProcessorCount); - } - - /// - public async Task TryOpenRntbdChannelsAsync(IEnumerable addresses) - { - foreach (TransportAddressUri address in addresses) - { - bool slimAcquired = false; - DefaultTrace.TraceVerbose("Attempting to open Rntbd connection to backend uri: {0}. '{1}'", - address.Uri, - Trace.CorrelationManager.ActivityId); - try - { - slimAcquired = await this.semaphore - .WaitAsync(RntbdOpenConnectionHandler.SemaphoreAcquireTimeout) - .ConfigureAwait(false); - - if (slimAcquired) - { - await this.transportClient.OpenConnectionAsync( - physicalAddress: address.Uri); - address.SetConnected(); - } - else - { - DefaultTrace.TraceWarning("Failed to open Rntbd connection to backend uri: {0} because" + - "the semaphore couldn't be acquired within the given timeout: {1} minutes. '{2}'", - address.Uri, - RntbdOpenConnectionHandler.SemaphoreAcquireTimeout.TotalMinutes, - Trace.CorrelationManager.ActivityId); - } - } - catch (Exception ex) - { - DefaultTrace.TraceWarning("Failed to open Rntbd connection to backend uri: {0} with exception: {1}. '{2}'", - address.Uri, - ex, - Trace.CorrelationManager.ActivityId); - address.SetUnhealthy(); - } - finally - { - if (slimAcquired) - { - this.semaphore.Release(); - } - } - } - } - - /// - public void Dispose() - { - if (!this.disposed) - { - this.semaphore.Dispose(); - this.disposed = true; - } - else - { - DefaultTrace.TraceVerbose("Failed to dispose the instance of: {0}, because it is already disposed. '{1}'", - nameof(RntbdOpenConnectionHandler), - Trace.CorrelationManager.ActivityId); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents; + +#if !NETSTANDARD16 + using System.Diagnostics; +#endif + + /// + /// Handler class to open Rntbd connections to backend replica nodes. + /// + internal sealed class RntbdOpenConnectionHandler : IOpenConnectionsHandler, IDisposable + { + /// + /// A read-only instance of + /// + private readonly TransportClient transportClient; + + /// + /// A read-only instance of for + /// concurrency control. + /// + private readonly SemaphoreSlim semaphore; + + /// + /// A read-only TimeSpan indicating the semephore timeout in minutes. + /// The default timeout is 10 minutes. + /// + private static readonly TimeSpan SemaphoreAcquireTimeout = TimeSpan.FromMinutes(10); + + /// + /// A booolean flag indicating if the current instance of RntbdOpenConnectionHandler + /// has been disposed. + /// + private bool disposed; + + /// + /// Constructor to initialize the . + /// + /// A reference to the . + public RntbdOpenConnectionHandler( + TransportClient transportClient) + { + this.disposed = false; + this.transportClient = transportClient ?? throw new ArgumentNullException(nameof(transportClient), $"Argument {nameof(transportClient)} can not be null"); + + // The semaphore arguments `initialCount` and `maxCount` are set to match the number of cpu cores, to keep the + // implementation similar to the Java counterpart. + this.semaphore = new SemaphoreSlim( + initialCount: Environment.ProcessorCount, + maxCount: Environment.ProcessorCount); + } + + /// + public async Task TryOpenRntbdChannelsAsync(IEnumerable addresses) + { + foreach (TransportAddressUri address in addresses) + { + bool slimAcquired = false; + DefaultTrace.TraceVerbose("Attempting to open Rntbd connection to backend uri: {0}. '{1}'", + address.Uri, + Trace.CorrelationManager.ActivityId); + try + { + slimAcquired = await this.semaphore + .WaitAsync(RntbdOpenConnectionHandler.SemaphoreAcquireTimeout) + .ConfigureAwait(false); + + if (slimAcquired) + { + await this.transportClient.OpenConnectionAsync( + physicalAddress: address.Uri); + address.SetConnected(); + } + else + { + DefaultTrace.TraceWarning("Failed to open Rntbd connection to backend uri: {0} because" + + "the semaphore couldn't be acquired within the given timeout: {1} minutes. '{2}'", + address.Uri, + RntbdOpenConnectionHandler.SemaphoreAcquireTimeout.TotalMinutes, + Trace.CorrelationManager.ActivityId); + } + } + catch (Exception ex) + { + DefaultTrace.TraceWarning("Failed to open Rntbd connection to backend uri: {0} with exception: {1}. '{2}'", + address.Uri, + ex, + Trace.CorrelationManager.ActivityId); + address.SetUnhealthy(); + } + finally + { + if (slimAcquired) + { + this.semaphore.Release(); + } + } + } + } + + /// + public void Dispose() + { + if (!this.disposed) + { + this.semaphore.Dispose(); + this.disposed = true; + } + else + { + DefaultTrace.TraceVerbose("Failed to dispose the instance of: {0}, because it is already disposed. '{1}'", + nameof(RntbdOpenConnectionHandler), + Trace.CorrelationManager.ActivityId); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdStreamReader.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdStreamReader.cs index 7be205cda1..9631a6820b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdStreamReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdStreamReader.cs @@ -1,189 +1,189 @@ -// ------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -// ------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Rntbd -{ - using System; - using System.Buffers; - using System.Diagnostics; - using System.IO; - using System.Threading.Tasks; - - /// - /// Encapsulates the reading from the network on a TCP connection. - /// - /// - /// RntbdStreamReader does not own the stream that it reads from. - /// It is the callers responsibility to close the stream. - /// - internal sealed class RntbdStreamReader : IDisposable - { - /// - /// The buffer size is picked to be a large enough value that common documents and responses - /// fit in memory, but small enough to avoid LOH. 16k was picked for now; wthis can be updated with more data - /// as needed. - /// - private const int BufferSize = 16384; - - private readonly Stream stream; - private byte[] buffer; - private int offset; - private int length; - - public RntbdStreamReader(Stream stream) - { - this.stream = stream; - this.buffer = ArrayPool.Shared.Rent(RntbdStreamReader.BufferSize); - this.offset = 0; - this.length = 0; - } - - internal int AvailableByteCount => this.length; - - public void Dispose() - { - byte[] bufferToReturn = this.buffer; - this.buffer = null; - ArrayPool.Shared.Return(bufferToReturn); - } - - public ValueTask ReadAsync(byte[] payload, int offset, int count) - { - if (payload.Length < (offset + count)) - { - throw new ArgumentException(nameof(payload)); - } - - if (this.length > 0) - { - return new ValueTask(this.CopyFromAvailableBytes(payload, offset, count)); - } - - return this.PopulateBytesAndReadAsync(payload, offset, count); - } - - public ValueTask ReadAsync(MemoryStream payload, int count) - { - if (this.length > 0) - { - return new ValueTask(this.CopyFromAvailableBytes(payload, count)); - } - - return this.PopulateBytesAndReadAsync(payload, count); - } - - private async ValueTask PopulateBytesAndReadAsync(byte[] payload, int offset, int count) - { - Debug.Assert(this.length == 0); - - // if the count requested is bigger than the buffer just read directly into the target payload. - if (count >= this.buffer.Length) - { - return await this.ReadStreamAsync(payload, offset, count); - } - else - { - this.offset = 0; - this.length = await this.ReadStreamAsync(this.buffer, offset: 0, this.buffer.Length); - if (this.length == 0) - { - // graceful closure. - return this.length; - } - - return this.CopyFromAvailableBytes(payload, offset, count); - } - } - - private async ValueTask PopulateBytesAndReadAsync(MemoryStream payload, int count) - { - Debug.Assert(this.length == 0); - this.offset = 0; - this.length = await this.ReadStreamAsync(this.buffer, offset: 0, this.buffer.Length); - if (this.length == 0) - { - // graceful closure. - return this.length; - } - - return this.CopyFromAvailableBytes(payload, count); - } - - private int CopyFromAvailableBytes(byte[] payload, int offset, int count) - { - // copy any in memory buffer to the target payload. - try - { - if (count >= this.length) - { - // if more bytes than what we've buffered is requested, copy what we have - // and return. The caller can request the remaining separately. - Array.Copy(sourceArray: this.buffer, sourceIndex: this.offset, destinationArray: payload, destinationIndex: offset, length: this.length); - int bytesRead = this.length; - this.length = 0; - this.offset = 0; - return bytesRead; - } - else - { - Array.Copy(sourceArray: this.buffer, sourceIndex: this.offset, destinationArray: payload, destinationIndex: offset, length: count); - this.length -= count; - this.offset += count; - return count; - } - } - catch (Exception e) - { - throw new IOException("Error copying buffered bytes", e); - } - } - - private int CopyFromAvailableBytes(MemoryStream payload, int count) - { - // copy any in memory buffer to the target payload. - try - { - if (count >= this.length) - { - // if more bytes than what we've buffered is requested, copy what we have - // and return. The caller can request the remaining separately. - int bytesRead = this.length; - payload.Write(this.buffer, this.offset, this.length); - this.length = 0; - this.offset = 0; - return bytesRead; - } - else - { - payload.Write(this.buffer, this.offset, count); - this.length -= count; - this.offset += count; - return count; - } - } - catch (Exception e) - { - throw new IOException("Error copying buffered bytes", e); - } - } - - /// - /// Helper, used to ensure we always issue a zero-byte read before a real one. - /// - /// We do this because, as of .NET 6, all built-in streams will avoid pinning - /// memory for long periods of time if we follow this pattern. - /// - /// See: https://github.com/dotnet/runtime/issues/76029 - /// For the precipitating issue. - /// - private async Task ReadStreamAsync(byte[] buffer, int offset, int count) - { - // this should not complete until we have data to read - await this.stream.ReadAsync(Array.Empty(), 0, 0); - - // this should complete almost immediately - return await this.stream.ReadAsync(buffer, offset, count); - } - } -} +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +// ------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Rntbd +{ + using System; + using System.Buffers; + using System.Diagnostics; + using System.IO; + using System.Threading.Tasks; + + /// + /// Encapsulates the reading from the network on a TCP connection. + /// + /// + /// RntbdStreamReader does not own the stream that it reads from. + /// It is the callers responsibility to close the stream. + /// + internal sealed class RntbdStreamReader : IDisposable + { + /// + /// The buffer size is picked to be a large enough value that common documents and responses + /// fit in memory, but small enough to avoid LOH. 16k was picked for now; wthis can be updated with more data + /// as needed. + /// + private const int BufferSize = 16384; + + private readonly Stream stream; + private byte[] buffer; + private int offset; + private int length; + + public RntbdStreamReader(Stream stream) + { + this.stream = stream; + this.buffer = ArrayPool.Shared.Rent(RntbdStreamReader.BufferSize); + this.offset = 0; + this.length = 0; + } + + internal int AvailableByteCount => this.length; + + public void Dispose() + { + byte[] bufferToReturn = this.buffer; + this.buffer = null; + ArrayPool.Shared.Return(bufferToReturn); + } + + public ValueTask ReadAsync(byte[] payload, int offset, int count) + { + if (payload.Length < (offset + count)) + { + throw new ArgumentException(nameof(payload)); + } + + if (this.length > 0) + { + return new ValueTask(this.CopyFromAvailableBytes(payload, offset, count)); + } + + return this.PopulateBytesAndReadAsync(payload, offset, count); + } + + public ValueTask ReadAsync(MemoryStream payload, int count) + { + if (this.length > 0) + { + return new ValueTask(this.CopyFromAvailableBytes(payload, count)); + } + + return this.PopulateBytesAndReadAsync(payload, count); + } + + private async ValueTask PopulateBytesAndReadAsync(byte[] payload, int offset, int count) + { + Debug.Assert(this.length == 0); + + // if the count requested is bigger than the buffer just read directly into the target payload. + if (count >= this.buffer.Length) + { + return await this.ReadStreamAsync(payload, offset, count); + } + else + { + this.offset = 0; + this.length = await this.ReadStreamAsync(this.buffer, offset: 0, this.buffer.Length); + if (this.length == 0) + { + // graceful closure. + return this.length; + } + + return this.CopyFromAvailableBytes(payload, offset, count); + } + } + + private async ValueTask PopulateBytesAndReadAsync(MemoryStream payload, int count) + { + Debug.Assert(this.length == 0); + this.offset = 0; + this.length = await this.ReadStreamAsync(this.buffer, offset: 0, this.buffer.Length); + if (this.length == 0) + { + // graceful closure. + return this.length; + } + + return this.CopyFromAvailableBytes(payload, count); + } + + private int CopyFromAvailableBytes(byte[] payload, int offset, int count) + { + // copy any in memory buffer to the target payload. + try + { + if (count >= this.length) + { + // if more bytes than what we've buffered is requested, copy what we have + // and return. The caller can request the remaining separately. + Array.Copy(sourceArray: this.buffer, sourceIndex: this.offset, destinationArray: payload, destinationIndex: offset, length: this.length); + int bytesRead = this.length; + this.length = 0; + this.offset = 0; + return bytesRead; + } + else + { + Array.Copy(sourceArray: this.buffer, sourceIndex: this.offset, destinationArray: payload, destinationIndex: offset, length: count); + this.length -= count; + this.offset += count; + return count; + } + } + catch (Exception e) + { + throw new IOException("Error copying buffered bytes", e); + } + } + + private int CopyFromAvailableBytes(MemoryStream payload, int count) + { + // copy any in memory buffer to the target payload. + try + { + if (count >= this.length) + { + // if more bytes than what we've buffered is requested, copy what we have + // and return. The caller can request the remaining separately. + int bytesRead = this.length; + payload.Write(this.buffer, this.offset, this.length); + this.length = 0; + this.offset = 0; + return bytesRead; + } + else + { + payload.Write(this.buffer, this.offset, count); + this.length -= count; + this.offset += count; + return count; + } + } + catch (Exception e) + { + throw new IOException("Error copying buffered bytes", e); + } + } + + /// + /// Helper, used to ensure we always issue a zero-byte read before a real one. + /// + /// We do this because, as of .NET 6, all built-in streams will avoid pinning + /// memory for long periods of time if we follow this pattern. + /// + /// See: https://github.com/dotnet/runtime/issues/76029 + /// For the precipitating issue. + /// + private async Task ReadStreamAsync(byte[] buffer, int offset, int count) + { + // this should not complete until we have data to read + await this.stream.ReadAsync(Array.Empty(), 0, 0); + + // this should complete almost immediately + return await this.stream.ReadAsync(buffer, offset, count); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdToken.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdToken.cs index ff7308ef60..e2da4ecf2e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdToken.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdToken.cs @@ -1,212 +1,212 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; -#if COSMOSCLIENT - using System.Buffers; -#endif - using System.Diagnostics; - using System.Runtime.InteropServices; -#if COSMOSCLIENT - using Microsoft.Azure.Cosmos.Rntbd; -#endif - using Microsoft.Azure.Documents.Rntbd; - - internal enum RntbdTokenTypes : byte - { - // All values are encoded as little endian byte sequences. - - // System.Byte, aka byte. - Byte = 0x00, - // System.UInt16, aka ushort. - UShort = 0x01, - // System.UInt32, aka uint. - ULong = 0x02, - // System.Int32, aka int. - Long = 0x03, - // System.UInt64, aka ulong. - ULongLong = 0x04, - // System.Int64, aka long. - LongLong = 0x05, - // GUID (128 bits) stored as a byte array. - Guid = 0x06, - // UTF-8 encoded string. At most 255 bytes. - SmallString = 0x07, - // UTF-8 encoded string. At most 64Ki-1 bytes. - String = 0x08, - // UTF-8 encoded string. At most 4Gi-1 bytes. - ULongString = 0x09, - // Byte array. At most 255 bytes. - SmallBytes = 0x0A, - // Byte array. At most 64Ki-1 bytes. - Bytes = 0x0B, - // Byte array. At most 4Gi-1 bytes. - ULongBytes = 0x0C, - // System.Single, aka float. - Float = 0x0D, - // System.Double, aka double. - Double = 0x0E, - - Invalid = 0xFF, - } - - [StructLayout(LayoutKind.Explicit)] - internal struct RntbdTokenValue - { - [FieldOffset(0)] - public byte valueByte; - [FieldOffset(0)] - public ushort valueUShort; - [FieldOffset(0)] - public UInt32 valueULong; - [FieldOffset(0)] - public UInt64 valueULongLong; - [FieldOffset(0)] - public Int32 valueLong; - [FieldOffset(0)] - public float valueFloat; - [FieldOffset(0)] - public double valueDouble; - [FieldOffset(0)] - public Int64 valueLongLong; - [FieldOffset(8)] - public Guid valueGuid; - - [FieldOffset(24)] -#if COSMOSCLIENT - public ReadOnlyMemory valueBytes; // used for content of all 3 byte types and also all 3 string types (since UTF-8 strings are stored as byte[] in .Net) -#else - public byte[] valueBytes; -#endif - } - - internal sealed class RntbdToken - { - private ushort identifier; - private RntbdTokenTypes type; - private bool isRequired; - - public bool isPresent; - public RntbdTokenValue value; - - public RntbdToken(bool isRequired, RntbdTokenTypes type, ushort identifier) - { - this.isRequired = isRequired; - this.isPresent = false; - this.type = type; - this.identifier = identifier; - this.value = new RntbdTokenValue(); - } - - public RntbdTokenTypes GetTokenType() - { - return this.type; - } - - public ushort GetTokenIdentifier() - { - return this.identifier; - } - - public bool IsRequired() - { - return this.isRequired; - } - - public void SerializeToBinaryWriter(ref BytesSerializer writer, out int written) - { - if(!this.isPresent && this.isRequired) - { - throw new BadRequestException(); - } - - if(this.isPresent) - { - writer.Write((UInt16)this.identifier); - writer.Write((byte)this.type); - - const int tokenOverhead = sizeof(UInt16) + sizeof(byte); - - switch(this.type) - { - case RntbdTokenTypes.Byte: - writer.Write(this.value.valueByte); - written = tokenOverhead + sizeof(byte); - break; - case RntbdTokenTypes.UShort: - writer.Write(this.value.valueUShort); - written = tokenOverhead + sizeof(UInt16); - break; - case RntbdTokenTypes.ULong: - writer.Write(this.value.valueULong); - written = tokenOverhead + sizeof(UInt32); - break; - case RntbdTokenTypes.Long: - writer.Write(this.value.valueLong); - written = tokenOverhead + sizeof(Int32); - break; - case RntbdTokenTypes.ULongLong: - writer.Write(this.value.valueULongLong); - written = tokenOverhead + sizeof(UInt64); - break; - case RntbdTokenTypes.LongLong: - writer.Write(this.value.valueLongLong); - written = tokenOverhead + sizeof(Int64); - break; - case RntbdTokenTypes.Float: - writer.Write(this.value.valueFloat); - written = tokenOverhead + sizeof(float); - break; - case RntbdTokenTypes.Double: - writer.Write(this.value.valueDouble); - written = tokenOverhead + sizeof(double); - break; - case RntbdTokenTypes.Guid: - { - byte[] guidBytes = this.value.valueGuid.ToByteArray(); - writer.Write(guidBytes); - written = tokenOverhead + guidBytes.Length; - break; - } - case RntbdTokenTypes.SmallBytes: - case RntbdTokenTypes.SmallString: - if (this.value.valueBytes.Length > byte.MaxValue) - { - throw new RequestEntityTooLargeException(); - } - - writer.Write((byte)this.value.valueBytes.Length); - writer.Write(this.value.valueBytes); - written = tokenOverhead + sizeof(byte) + this.value.valueBytes.Length; - break; - case RntbdTokenTypes.Bytes: - case RntbdTokenTypes.String: - if (this.value.valueBytes.Length > ushort.MaxValue) - { - throw new RequestEntityTooLargeException(); - } - - writer.Write((UInt16)this.value.valueBytes.Length); - writer.Write(this.value.valueBytes); - written = tokenOverhead + sizeof(UInt16) + this.value.valueBytes.Length; - break; - case RntbdTokenTypes.ULongString: - case RntbdTokenTypes.ULongBytes: - writer.Write((UInt32)this.value.valueBytes.Length); - writer.Write(this.value.valueBytes); - written = tokenOverhead + sizeof(UInt32) + this.value.valueBytes.Length; - break; - default: - Debug.Assert(false, "Unexpected RntbdTokenType", "Unexpected RntbdTokenType to serialize: {0}", this.type); - throw new BadRequestException(); - } - } - else - { - written = 0; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; +#if COSMOSCLIENT + using System.Buffers; +#endif + using System.Diagnostics; + using System.Runtime.InteropServices; +#if COSMOSCLIENT + using Microsoft.Azure.Cosmos.Rntbd; +#endif + using Microsoft.Azure.Documents.Rntbd; + + internal enum RntbdTokenTypes : byte + { + // All values are encoded as little endian byte sequences. + + // System.Byte, aka byte. + Byte = 0x00, + // System.UInt16, aka ushort. + UShort = 0x01, + // System.UInt32, aka uint. + ULong = 0x02, + // System.Int32, aka int. + Long = 0x03, + // System.UInt64, aka ulong. + ULongLong = 0x04, + // System.Int64, aka long. + LongLong = 0x05, + // GUID (128 bits) stored as a byte array. + Guid = 0x06, + // UTF-8 encoded string. At most 255 bytes. + SmallString = 0x07, + // UTF-8 encoded string. At most 64Ki-1 bytes. + String = 0x08, + // UTF-8 encoded string. At most 4Gi-1 bytes. + ULongString = 0x09, + // Byte array. At most 255 bytes. + SmallBytes = 0x0A, + // Byte array. At most 64Ki-1 bytes. + Bytes = 0x0B, + // Byte array. At most 4Gi-1 bytes. + ULongBytes = 0x0C, + // System.Single, aka float. + Float = 0x0D, + // System.Double, aka double. + Double = 0x0E, + + Invalid = 0xFF, + } + + [StructLayout(LayoutKind.Explicit)] + internal struct RntbdTokenValue + { + [FieldOffset(0)] + public byte valueByte; + [FieldOffset(0)] + public ushort valueUShort; + [FieldOffset(0)] + public UInt32 valueULong; + [FieldOffset(0)] + public UInt64 valueULongLong; + [FieldOffset(0)] + public Int32 valueLong; + [FieldOffset(0)] + public float valueFloat; + [FieldOffset(0)] + public double valueDouble; + [FieldOffset(0)] + public Int64 valueLongLong; + [FieldOffset(8)] + public Guid valueGuid; + + [FieldOffset(24)] +#if COSMOSCLIENT + public ReadOnlyMemory valueBytes; // used for content of all 3 byte types and also all 3 string types (since UTF-8 strings are stored as byte[] in .Net) +#else + public byte[] valueBytes; +#endif + } + + internal sealed class RntbdToken + { + private ushort identifier; + private RntbdTokenTypes type; + private bool isRequired; + + public bool isPresent; + public RntbdTokenValue value; + + public RntbdToken(bool isRequired, RntbdTokenTypes type, ushort identifier) + { + this.isRequired = isRequired; + this.isPresent = false; + this.type = type; + this.identifier = identifier; + this.value = new RntbdTokenValue(); + } + + public RntbdTokenTypes GetTokenType() + { + return this.type; + } + + public ushort GetTokenIdentifier() + { + return this.identifier; + } + + public bool IsRequired() + { + return this.isRequired; + } + + public void SerializeToBinaryWriter(ref BytesSerializer writer, out int written) + { + if(!this.isPresent && this.isRequired) + { + throw new BadRequestException(); + } + + if(this.isPresent) + { + writer.Write((UInt16)this.identifier); + writer.Write((byte)this.type); + + const int tokenOverhead = sizeof(UInt16) + sizeof(byte); + + switch(this.type) + { + case RntbdTokenTypes.Byte: + writer.Write(this.value.valueByte); + written = tokenOverhead + sizeof(byte); + break; + case RntbdTokenTypes.UShort: + writer.Write(this.value.valueUShort); + written = tokenOverhead + sizeof(UInt16); + break; + case RntbdTokenTypes.ULong: + writer.Write(this.value.valueULong); + written = tokenOverhead + sizeof(UInt32); + break; + case RntbdTokenTypes.Long: + writer.Write(this.value.valueLong); + written = tokenOverhead + sizeof(Int32); + break; + case RntbdTokenTypes.ULongLong: + writer.Write(this.value.valueULongLong); + written = tokenOverhead + sizeof(UInt64); + break; + case RntbdTokenTypes.LongLong: + writer.Write(this.value.valueLongLong); + written = tokenOverhead + sizeof(Int64); + break; + case RntbdTokenTypes.Float: + writer.Write(this.value.valueFloat); + written = tokenOverhead + sizeof(float); + break; + case RntbdTokenTypes.Double: + writer.Write(this.value.valueDouble); + written = tokenOverhead + sizeof(double); + break; + case RntbdTokenTypes.Guid: + { + byte[] guidBytes = this.value.valueGuid.ToByteArray(); + writer.Write(guidBytes); + written = tokenOverhead + guidBytes.Length; + break; + } + case RntbdTokenTypes.SmallBytes: + case RntbdTokenTypes.SmallString: + if (this.value.valueBytes.Length > byte.MaxValue) + { + throw new RequestEntityTooLargeException(); + } + + writer.Write((byte)this.value.valueBytes.Length); + writer.Write(this.value.valueBytes); + written = tokenOverhead + sizeof(byte) + this.value.valueBytes.Length; + break; + case RntbdTokenTypes.Bytes: + case RntbdTokenTypes.String: + if (this.value.valueBytes.Length > ushort.MaxValue) + { + throw new RequestEntityTooLargeException(); + } + + writer.Write((UInt16)this.value.valueBytes.Length); + writer.Write(this.value.valueBytes); + written = tokenOverhead + sizeof(UInt16) + this.value.valueBytes.Length; + break; + case RntbdTokenTypes.ULongString: + case RntbdTokenTypes.ULongBytes: + writer.Write((UInt32)this.value.valueBytes.Length); + writer.Write(this.value.valueBytes); + written = tokenOverhead + sizeof(UInt32) + this.value.valueBytes.Length; + break; + default: + Debug.Assert(false, "Unexpected RntbdTokenType", "Unexpected RntbdTokenType to serialize: {0}", this.type); + throw new BadRequestException(); + } + } + else + { + written = 0; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdTokenStream.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdTokenStream.cs index df5af05604..74c74c3a1d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdTokenStream.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdTokenStream.cs @@ -1,274 +1,274 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; -#if COSMOSCLIENT - using System.Buffers; -#endif - using System.Collections.Generic; - using System.Diagnostics; - using Microsoft.Azure.Cosmos.Core.Trace; -#if COSMOSCLIENT - using Microsoft.Azure.Cosmos.Rntbd; -#endif - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.Rntbd; - - internal abstract class RntbdTokenStream - where T : Enum - { - internal RntbdToken[] tokens; - - // Ideally we could use MemoryPool but a lot of the APIs for GetBytes() for - // System.Text.Encoding and Write/Read for stream don't take Memory<> in NetStandard - // so we have to use ArrayPool instead. -#if COSMOSCLIENT - private ArrayPool arrayPool = ArrayPool.Create(); - private List borrowedBytes = new List(); -#endif - - public abstract int RequiredTokenCount { get; } - - /// - /// Gets a byte[] of at least bytes from a pool. - /// - /// The length of bytes to retrieve - /// - /// The byte array returned is put back in the pool when the TokenStream is Reset(). - /// Typically this is done when the request is returned to a shared pool of RNTBD requests. - /// - public byte[] GetBytes(int length) - { -#if COSMOSCLIENT - byte[] bytes = this.arrayPool.Rent(length); - this.borrowedBytes.Add(bytes); - return bytes; -#else - return new byte[length]; -#endif - } - - public void Reset() - { - for (int i = 0; i < this.tokens.Length; i++) - { - if (this.tokens[i] == null) - { - continue; - } - - this.tokens[i].isPresent = false; - - // free any pending buffer references. - this.tokens[i].value.valueBytes = default; - } - -#if COSMOSCLIENT - foreach (byte[] bytes in this.borrowedBytes) - { - this.arrayPool.Return(bytes); - } - - this.borrowedBytes.Clear(); -#endif - } - - public int CalculateLength() - { - int total = 0; - foreach(RntbdToken token in this.tokens) - { - if (token == null - || !token.isPresent) - { - continue; - } - - total += sizeof(RntbdTokenTypes); // type - total += 2; // identifier - - // value - switch(token.GetTokenType()) - { - case RntbdTokenTypes.Byte: - total += 1; - break; - case RntbdTokenTypes.UShort: - total += 2; - break; - case RntbdTokenTypes.ULong: - case RntbdTokenTypes.Long: - total += 4; - break; - case RntbdTokenTypes.ULongLong: - case RntbdTokenTypes.LongLong: - total += 8; - break; - case RntbdTokenTypes.Float: - total += 4; - break; - case RntbdTokenTypes.Double: - total += 8; - break; - case RntbdTokenTypes.Guid: - total += 16; - break; - case RntbdTokenTypes.SmallBytes: - case RntbdTokenTypes.SmallString: - total += 1; - total += token.value.valueBytes.Length; - break; - case RntbdTokenTypes.Bytes: - case RntbdTokenTypes.String: - total += 2; - total += token.value.valueBytes.Length; - break; - case RntbdTokenTypes.ULongBytes: - case RntbdTokenTypes.ULongString: - total += 4; - total += token.value.valueBytes.Length; - break; - default: - Debug.Assert(false, "Unexpected RntbdTokenType", "Unexpected RntbdTokenType to serialize: {0}", - token.GetTokenType()); - throw new BadRequestException(); - } - } - - return total; - } - - public void SerializeToBinaryWriter(ref BytesSerializer writer, out int tokensLength) - { - tokensLength = 0; - foreach(RntbdToken token in this.tokens) - { - if (token == null) - { - continue; - } - - int tokenLength = 0; - token.SerializeToBinaryWriter(ref writer, out tokenLength); - tokensLength += tokenLength; - } - } - - public void ParseFrom(ref BytesDeserializer reader) - { - int requiredTokensPresent = 0; - while(reader.Position < reader.Length) - { - ushort identifier = reader.ReadUInt16(); - RntbdTokenTypes type = (RntbdTokenTypes)reader.ReadByte(); - - RntbdToken token; - if (identifier < this.tokens.Length - && this.tokens[identifier] != null) - { - token = this.tokens[identifier]; - } - else - { - token = new RntbdToken(false, type, identifier); // read the token content to a temp, if the token isn't recognized - } - - if (token.isPresent) - { - DefaultTrace.TraceError("Duplicate token with identifier {0} type {1} found in RNTBD token stream", - token.GetTokenIdentifier(), token.GetTokenType()); - - throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); - } - - switch (token.GetTokenType()) - { - case RntbdTokenTypes.Byte: - token.value.valueByte = reader.ReadByte(); - break; - case RntbdTokenTypes.UShort: - token.value.valueUShort = reader.ReadUInt16(); - break; - case RntbdTokenTypes.ULong: - token.value.valueULong = reader.ReadUInt32(); - break; - case RntbdTokenTypes.Long: - token.value.valueLong = reader.ReadInt32(); - break; - case RntbdTokenTypes.ULongLong: - token.value.valueULongLong = reader.ReadUInt64(); - break; - case RntbdTokenTypes.LongLong: - token.value.valueLongLong = reader.ReadInt64(); - break; - case RntbdTokenTypes.Float: - token.value.valueFloat = reader.ReadSingle(); - break; - case RntbdTokenTypes.Double: - token.value.valueDouble = reader.ReadDouble(); - break; - case RntbdTokenTypes.Guid: - token.value.valueGuid = reader.ReadGuid(); - break; - case RntbdTokenTypes.SmallBytes: - case RntbdTokenTypes.SmallString: - { - byte length = reader.ReadByte(); - token.value.valueBytes = reader.ReadBytes(length); - break; - } - case RntbdTokenTypes.Bytes: - case RntbdTokenTypes.String: - { - ushort length = reader.ReadUInt16(); - token.value.valueBytes = reader.ReadBytes(length); - break; - } - case RntbdTokenTypes.ULongBytes: - case RntbdTokenTypes.ULongString: - { - UInt32 length = reader.ReadUInt32(); - token.value.valueBytes = reader.ReadBytes((int)length); - break; - } - default: - DefaultTrace.TraceError("Unrecognized token type {0} with identifier {1} found in RNTBD token stream", - token.GetTokenType(), token.GetTokenIdentifier()); - - throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); - } - - token.isPresent = true; - if (token.IsRequired()) - { - requiredTokensPresent++; - } - } - - if (requiredTokensPresent != this.RequiredTokenCount) - { - foreach (RntbdToken token in this.tokens) - { - if (token != null - && !token.isPresent - && token.IsRequired()) - { - DefaultTrace.TraceError("Required token with identifier {0} not found in RNTBD token stream", - token.GetTokenIdentifier()); - - throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); - } - } - } - } - - private INameValueCollection GetValidationFailureHeader() - { - INameValueCollection validationFailureResponseHeader = new DictionaryNameValueCollection(); - validationFailureResponseHeader.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - return validationFailureResponseHeader; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; +#if COSMOSCLIENT + using System.Buffers; +#endif + using System.Collections.Generic; + using System.Diagnostics; + using Microsoft.Azure.Cosmos.Core.Trace; +#if COSMOSCLIENT + using Microsoft.Azure.Cosmos.Rntbd; +#endif + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.Rntbd; + + internal abstract class RntbdTokenStream + where T : Enum + { + internal RntbdToken[] tokens; + + // Ideally we could use MemoryPool but a lot of the APIs for GetBytes() for + // System.Text.Encoding and Write/Read for stream don't take Memory<> in NetStandard + // so we have to use ArrayPool instead. +#if COSMOSCLIENT + private ArrayPool arrayPool = ArrayPool.Create(); + private List borrowedBytes = new List(); +#endif + + public abstract int RequiredTokenCount { get; } + + /// + /// Gets a byte[] of at least bytes from a pool. + /// + /// The length of bytes to retrieve + /// + /// The byte array returned is put back in the pool when the TokenStream is Reset(). + /// Typically this is done when the request is returned to a shared pool of RNTBD requests. + /// + public byte[] GetBytes(int length) + { +#if COSMOSCLIENT + byte[] bytes = this.arrayPool.Rent(length); + this.borrowedBytes.Add(bytes); + return bytes; +#else + return new byte[length]; +#endif + } + + public void Reset() + { + for (int i = 0; i < this.tokens.Length; i++) + { + if (this.tokens[i] == null) + { + continue; + } + + this.tokens[i].isPresent = false; + + // free any pending buffer references. + this.tokens[i].value.valueBytes = default; + } + +#if COSMOSCLIENT + foreach (byte[] bytes in this.borrowedBytes) + { + this.arrayPool.Return(bytes); + } + + this.borrowedBytes.Clear(); +#endif + } + + public int CalculateLength() + { + int total = 0; + foreach(RntbdToken token in this.tokens) + { + if (token == null + || !token.isPresent) + { + continue; + } + + total += sizeof(RntbdTokenTypes); // type + total += 2; // identifier + + // value + switch(token.GetTokenType()) + { + case RntbdTokenTypes.Byte: + total += 1; + break; + case RntbdTokenTypes.UShort: + total += 2; + break; + case RntbdTokenTypes.ULong: + case RntbdTokenTypes.Long: + total += 4; + break; + case RntbdTokenTypes.ULongLong: + case RntbdTokenTypes.LongLong: + total += 8; + break; + case RntbdTokenTypes.Float: + total += 4; + break; + case RntbdTokenTypes.Double: + total += 8; + break; + case RntbdTokenTypes.Guid: + total += 16; + break; + case RntbdTokenTypes.SmallBytes: + case RntbdTokenTypes.SmallString: + total += 1; + total += token.value.valueBytes.Length; + break; + case RntbdTokenTypes.Bytes: + case RntbdTokenTypes.String: + total += 2; + total += token.value.valueBytes.Length; + break; + case RntbdTokenTypes.ULongBytes: + case RntbdTokenTypes.ULongString: + total += 4; + total += token.value.valueBytes.Length; + break; + default: + Debug.Assert(false, "Unexpected RntbdTokenType", "Unexpected RntbdTokenType to serialize: {0}", + token.GetTokenType()); + throw new BadRequestException(); + } + } + + return total; + } + + public void SerializeToBinaryWriter(ref BytesSerializer writer, out int tokensLength) + { + tokensLength = 0; + foreach(RntbdToken token in this.tokens) + { + if (token == null) + { + continue; + } + + int tokenLength = 0; + token.SerializeToBinaryWriter(ref writer, out tokenLength); + tokensLength += tokenLength; + } + } + + public void ParseFrom(ref BytesDeserializer reader) + { + int requiredTokensPresent = 0; + while(reader.Position < reader.Length) + { + ushort identifier = reader.ReadUInt16(); + RntbdTokenTypes type = (RntbdTokenTypes)reader.ReadByte(); + + RntbdToken token; + if (identifier < this.tokens.Length + && this.tokens[identifier] != null) + { + token = this.tokens[identifier]; + } + else + { + token = new RntbdToken(false, type, identifier); // read the token content to a temp, if the token isn't recognized + } + + if (token.isPresent) + { + DefaultTrace.TraceError("Duplicate token with identifier {0} type {1} found in RNTBD token stream", + token.GetTokenIdentifier(), token.GetTokenType()); + + throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); + } + + switch (token.GetTokenType()) + { + case RntbdTokenTypes.Byte: + token.value.valueByte = reader.ReadByte(); + break; + case RntbdTokenTypes.UShort: + token.value.valueUShort = reader.ReadUInt16(); + break; + case RntbdTokenTypes.ULong: + token.value.valueULong = reader.ReadUInt32(); + break; + case RntbdTokenTypes.Long: + token.value.valueLong = reader.ReadInt32(); + break; + case RntbdTokenTypes.ULongLong: + token.value.valueULongLong = reader.ReadUInt64(); + break; + case RntbdTokenTypes.LongLong: + token.value.valueLongLong = reader.ReadInt64(); + break; + case RntbdTokenTypes.Float: + token.value.valueFloat = reader.ReadSingle(); + break; + case RntbdTokenTypes.Double: + token.value.valueDouble = reader.ReadDouble(); + break; + case RntbdTokenTypes.Guid: + token.value.valueGuid = reader.ReadGuid(); + break; + case RntbdTokenTypes.SmallBytes: + case RntbdTokenTypes.SmallString: + { + byte length = reader.ReadByte(); + token.value.valueBytes = reader.ReadBytes(length); + break; + } + case RntbdTokenTypes.Bytes: + case RntbdTokenTypes.String: + { + ushort length = reader.ReadUInt16(); + token.value.valueBytes = reader.ReadBytes(length); + break; + } + case RntbdTokenTypes.ULongBytes: + case RntbdTokenTypes.ULongString: + { + UInt32 length = reader.ReadUInt32(); + token.value.valueBytes = reader.ReadBytes((int)length); + break; + } + default: + DefaultTrace.TraceError("Unrecognized token type {0} with identifier {1} found in RNTBD token stream", + token.GetTokenType(), token.GetTokenIdentifier()); + + throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); + } + + token.isPresent = true; + if (token.IsRequired()) + { + requiredTokensPresent++; + } + } + + if (requiredTokensPresent != this.RequiredTokenCount) + { + foreach (RntbdToken token in this.tokens) + { + if (token != null + && !token.isPresent + && token.IsRequired()) + { + DefaultTrace.TraceError("Required token with identifier {0} not found in RNTBD token stream", + token.GetTokenIdentifier()); + + throw new InternalServerErrorException(RMResources.InternalServerError, this.GetValidationFailureHeader()); + } + } + } + } + + private INameValueCollection GetValidationFailureHeader() + { + INameValueCollection validationFailureResponseHeader = new DictionaryNameValueCollection(); + validationFailureResponseHeader.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + return validationFailureResponseHeader; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/RuntimeConstants.cs b/Microsoft.Azure.Cosmos/src/direct/RuntimeConstants.cs index ca7d6ed1ff..58688407c7 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RuntimeConstants.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RuntimeConstants.cs @@ -1,85 +1,85 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal static class RuntimeConstants - { - public const string IncludeExceptionDetails = "includeExceptionDetails"; - - internal static class Serialization - { - public const int ChunkSize512 = 512; - public const int ChunkSize1K = 1024; - public const int ChunkSize8K = 8192; - } - - internal static class Separators - { - public static readonly char[] Url = new char[] { '/' }; - public static readonly char[] Quote = new char[] { '\'' }; - public static readonly char[] DomainId = new char[] { '-' }; - public static readonly char[] Query = new char[] { '?', '&', '=' }; - public static readonly char[] Parenthesis = new char[] { '(', ')' }; - public static readonly char[] UserAgentHeader = new char[] { '(', ')', ';', ',' }; - - - //Note that the accept header separator here is ideally comma. Semicolon is used for separators within individual - //header for now cloud moe does not recognize such accept header hence we allow both semicolon or comma separated - //accept header - public static readonly char[] Header = new char[] { ';', ',' }; - public static readonly char[] CookieSeparator = new char[] { ';' }; - public static readonly char[] CookieValueSeparator = new char[] { '=' }; - public static readonly char[] PPMUserToken = new char[] { ':' }; - public static readonly char[] Identifier = new char[] { '-' }; - public static readonly char[] Host = new char[] { '.' }; - public static readonly char[] Version = new char[] { ',' }; - public static readonly char[] Pair = new char[] { ';' }; - public static readonly char[] ETag = new char[] { '#' }; - public static readonly char[] MemberQuery = new char[] { '+' }; - - public const string HeaderEncodingBegin = "=?"; - public const string HeaderEncodingEnd = "?="; - public const string HeaderEncodingSeparator = "?"; - } - - internal static class MediaTypes - { - // http://www.iana.org/assignments/media-types/media-types.xhtml - public const string Any = "*/*"; - public const string Http = "application/http"; - public const string Json = "application/json"; - public const string Xml = "application/xml"; - public const string AtomXml = "application/atom+xml"; - public const string AtomXmlEntry = "application/atom+xml;type=entry"; - public const string OctetStream = "application/octet-stream"; - public const string SQL = "application/sql"; - public const string QueryJson = "application/query+json"; - public const string ImageJpeg = "image/jpeg"; - public const string ImagePng = "image/png"; - public const string TextHtml = "text/html"; - public const string TextPlain = "text/plain"; - public const string JavaScript = "application/x-javascript"; - public const string JsonNoOdataMetadata = "application/json;odata=nometadata"; - public const string JsonMinimalOdataMetadata = "application/json;odata=minimalmetadata"; - public const string JsonFullOdataMetadata = "application/json;odata=fullmetadata"; - public const string MutlipartBatchPrefix = "multipart/mixed"; - public const string FormUrlEncoded = "application/x-www-form-urlencoded"; - public const string MultipartFormData = "multipart/form-data"; - public const string JsonPatch = "application/json-patch+json"; - } - - internal static class Schemes - { - internal const string UuidScheme = "urn:uuid:"; - } - - internal static class Protocols - { - internal const string HTTP = "http"; - internal const string HTTPS = "https"; - internal const string TCP = "net.tcp"; - internal const string RNTBD = "rntbd"; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal static class RuntimeConstants + { + public const string IncludeExceptionDetails = "includeExceptionDetails"; + + internal static class Serialization + { + public const int ChunkSize512 = 512; + public const int ChunkSize1K = 1024; + public const int ChunkSize8K = 8192; + } + + internal static class Separators + { + public static readonly char[] Url = new char[] { '/' }; + public static readonly char[] Quote = new char[] { '\'' }; + public static readonly char[] DomainId = new char[] { '-' }; + public static readonly char[] Query = new char[] { '?', '&', '=' }; + public static readonly char[] Parenthesis = new char[] { '(', ')' }; + public static readonly char[] UserAgentHeader = new char[] { '(', ')', ';', ',' }; + + + //Note that the accept header separator here is ideally comma. Semicolon is used for separators within individual + //header for now cloud moe does not recognize such accept header hence we allow both semicolon or comma separated + //accept header + public static readonly char[] Header = new char[] { ';', ',' }; + public static readonly char[] CookieSeparator = new char[] { ';' }; + public static readonly char[] CookieValueSeparator = new char[] { '=' }; + public static readonly char[] PPMUserToken = new char[] { ':' }; + public static readonly char[] Identifier = new char[] { '-' }; + public static readonly char[] Host = new char[] { '.' }; + public static readonly char[] Version = new char[] { ',' }; + public static readonly char[] Pair = new char[] { ';' }; + public static readonly char[] ETag = new char[] { '#' }; + public static readonly char[] MemberQuery = new char[] { '+' }; + + public const string HeaderEncodingBegin = "=?"; + public const string HeaderEncodingEnd = "?="; + public const string HeaderEncodingSeparator = "?"; + } + + internal static class MediaTypes + { + // http://www.iana.org/assignments/media-types/media-types.xhtml + public const string Any = "*/*"; + public const string Http = "application/http"; + public const string Json = "application/json"; + public const string Xml = "application/xml"; + public const string AtomXml = "application/atom+xml"; + public const string AtomXmlEntry = "application/atom+xml;type=entry"; + public const string OctetStream = "application/octet-stream"; + public const string SQL = "application/sql"; + public const string QueryJson = "application/query+json"; + public const string ImageJpeg = "image/jpeg"; + public const string ImagePng = "image/png"; + public const string TextHtml = "text/html"; + public const string TextPlain = "text/plain"; + public const string JavaScript = "application/x-javascript"; + public const string JsonNoOdataMetadata = "application/json;odata=nometadata"; + public const string JsonMinimalOdataMetadata = "application/json;odata=minimalmetadata"; + public const string JsonFullOdataMetadata = "application/json;odata=fullmetadata"; + public const string MutlipartBatchPrefix = "multipart/mixed"; + public const string FormUrlEncoded = "application/x-www-form-urlencoded"; + public const string MultipartFormData = "multipart/form-data"; + public const string JsonPatch = "application/json-patch+json"; + } + + internal static class Schemes + { + internal const string UuidScheme = "urn:uuid:"; + } + + internal static class Protocols + { + internal const string HTTP = "http"; + internal const string HTTPS = "https"; + internal const string TCP = "net.tcp"; + internal const string RNTBD = "rntbd"; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilities.cs b/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilities.cs index f5cd68a0ac..b5cbc03b07 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilities.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilities.cs @@ -1,15 +1,15 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - [Flags] - internal enum SDKSupportedCapabilities : ulong - { - None = 0, - PartitionMerge = 1 << 0, - ChangeFeedWithStartTimePostMerge = 1 << 1 - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + [Flags] + internal enum SDKSupportedCapabilities : ulong + { + None = 0, + PartitionMerge = 1 << 0, + ChangeFeedWithStartTimePostMerge = 1 << 1 + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilitiesHelpers.cs b/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilitiesHelpers.cs index 19e02450e5..18b54239fc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilitiesHelpers.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SDKSupportedCapabilitiesHelpers.cs @@ -1,23 +1,23 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - internal static class SDKSupportedCapabilitiesHelpers - { - private static readonly ulong sdkSupportedCapabilities; - - static SDKSupportedCapabilitiesHelpers() - { - SDKSupportedCapabilities capabilities = SDKSupportedCapabilities.None; - capabilities |= SDKSupportedCapabilities.PartitionMerge; - - SDKSupportedCapabilitiesHelpers.sdkSupportedCapabilities = (ulong)capabilities; - } - - internal static ulong GetSDKSupportedCapabilities() - { - return SDKSupportedCapabilitiesHelpers.sdkSupportedCapabilities; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + internal static class SDKSupportedCapabilitiesHelpers + { + private static readonly ulong sdkSupportedCapabilities; + + static SDKSupportedCapabilitiesHelpers() + { + SDKSupportedCapabilities capabilities = SDKSupportedCapabilities.None; + capabilities |= SDKSupportedCapabilities.PartitionMerge; + + SDKSupportedCapabilitiesHelpers.sdkSupportedCapabilities = (ulong)capabilities; + } + + internal static ulong GetSDKSupportedCapabilities() + { + return SDKSupportedCapabilitiesHelpers.sdkSupportedCapabilities; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Schema.cs b/Microsoft.Azure.Cosmos/src/direct/Schema.cs index 22c3510c4e..d8c4125cf6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Schema.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Schema.cs @@ -1,117 +1,117 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json.Linq; - - /// - /// Represents a schema in the Azure Cosmos DB service. - /// - /// - /// A schema is a structured JSON document. - /// - internal sealed class Schema : Resource - { - /// - /// Initializes a new instance of the class in the Azure Cosmos DB service. - /// - public Schema() - { - } - - /// - /// Gets the resource link for the schema from the Azure Cosmos DB service. - /// - public string ResourceLink - { - get - { - return base.GetValue(Constants.Properties.ResourceLink); - } - } - - //Helper to materialize Document from any .NET object. - internal static Schema FromObject(object schema) - { - if(schema != null) - { - if(typeof(Schema).IsAssignableFrom(schema.GetType())) - { - return (Schema)schema; - } - else - { - // FromObject: for dynamics, it only go through JsonProperty attribute decorated properties. - // for poco, it will go through all public properties - JObject serializedPropertyBag = JObject.FromObject(schema); - Schema typeSchema = new Schema(); - typeSchema.propertyBag = serializedPropertyBag; - return typeSchema; - } - } - return null; - } - - //Property Getter/Setter for Expandable User property. - private object GetProperty( - string propertyName, Type returnType) - { - if(this.propertyBag != null) - { - JToken token = this.propertyBag[propertyName]; - if(token != null) - { - return token.ToObject(returnType); - } - } - - //Any property not in JSON throw exception rather than returning null. - throw new DocumentClientException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.PropertyNotFound, - propertyName), null, null); - } - - private object SetProperty(string propertyName, object value) - { - if(value != null) - { - if(this.propertyBag == null) - { - this.propertyBag = new JObject(); - } - this.propertyBag[propertyName] = JToken.FromObject(value); - } - else - { - if(this.propertyBag != null) - { - this.propertyBag.Remove(propertyName); - } - } - return value; - } - - private T AsType() //To convert Schema to any type. - { - if(typeof(T) == typeof(Schema) || typeof(T) == typeof(object)) - { - return (T)(object)this; - } - - if(this.propertyBag == null) - { - return default(T); - } - - //Materialize the type. - T result = (T)this.propertyBag.ToObject(); - - return result; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json.Linq; + + /// + /// Represents a schema in the Azure Cosmos DB service. + /// + /// + /// A schema is a structured JSON document. + /// + internal sealed class Schema : Resource + { + /// + /// Initializes a new instance of the class in the Azure Cosmos DB service. + /// + public Schema() + { + } + + /// + /// Gets the resource link for the schema from the Azure Cosmos DB service. + /// + public string ResourceLink + { + get + { + return base.GetValue(Constants.Properties.ResourceLink); + } + } + + //Helper to materialize Document from any .NET object. + internal static Schema FromObject(object schema) + { + if(schema != null) + { + if(typeof(Schema).IsAssignableFrom(schema.GetType())) + { + return (Schema)schema; + } + else + { + // FromObject: for dynamics, it only go through JsonProperty attribute decorated properties. + // for poco, it will go through all public properties + JObject serializedPropertyBag = JObject.FromObject(schema); + Schema typeSchema = new Schema(); + typeSchema.propertyBag = serializedPropertyBag; + return typeSchema; + } + } + return null; + } + + //Property Getter/Setter for Expandable User property. + private object GetProperty( + string propertyName, Type returnType) + { + if(this.propertyBag != null) + { + JToken token = this.propertyBag[propertyName]; + if(token != null) + { + return token.ToObject(returnType); + } + } + + //Any property not in JSON throw exception rather than returning null. + throw new DocumentClientException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.PropertyNotFound, + propertyName), null, null); + } + + private object SetProperty(string propertyName, object value) + { + if(value != null) + { + if(this.propertyBag == null) + { + this.propertyBag = new JObject(); + } + this.propertyBag[propertyName] = JToken.FromObject(value); + } + else + { + if(this.propertyBag != null) + { + this.propertyBag.Remove(propertyName); + } + } + return value; + } + + private T AsType() //To convert Schema to any type. + { + if(typeof(T) == typeof(Schema) || typeof(T) == typeof(object)) + { + return (T)(object)this; + } + + if(this.propertyBag == null) + { + return default(T); + } + + //Materialize the type. + T result = (T)this.propertyBag.ToObject(); + + return result; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SchemaBuilderMode.cs b/Microsoft.Azure.Cosmos/src/direct/SchemaBuilderMode.cs index 524dd7062c..5c73341d2f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SchemaBuilderMode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SchemaBuilderMode.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported schema builder modes. - /// - internal enum SchemaBuilderMode - { - /// - /// SchemaBuilder is active and running lazily. - /// - /// - /// Setting the SchemaBuilderMode to "Lazy" ensures the schema builder will be running in the background either - /// as it's own process (consistent indexing) or with the lazy index processor (lazy indexing) - /// - Lazy, - - /// - /// Schema builder is not active. - /// - /// - /// Setting SchemaBuilderMode to "None" ensures that the schema builder will be disabled and no longer functioning. - /// - None - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported schema builder modes. + /// + internal enum SchemaBuilderMode + { + /// + /// SchemaBuilder is active and running lazily. + /// + /// + /// Setting the SchemaBuilderMode to "Lazy" ensures the schema builder will be running in the background either + /// as it's own process (consistent indexing) or with the lazy index processor (lazy indexing) + /// + Lazy, + + /// + /// Schema builder is not active. + /// + /// + /// Setting SchemaBuilderMode to "None" ensures that the schema builder will be disabled and no longer functioning. + /// + None + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SchemaDiscoveryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/SchemaDiscoveryPolicy.cs index bf1ac9167e..3eec3449d4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SchemaDiscoveryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SchemaDiscoveryPolicy.cs @@ -1,78 +1,78 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents the schema discovery policy configuration for a collection. - /// - /// - /// The schema discovery policy is used to control the schema builder through a collection configuration. - /// - /// - internal sealed class SchemaDiscoveryPolicy : JsonSerializable, ICloneable - { - /// - /// Initializes a new instance of the class. - /// - /// - /// Schema mode is set to none - /// - public SchemaDiscoveryPolicy() - { - this.SchemaBuilderMode = SchemaBuilderMode.None; - } - - /// - /// Gets or sets the indexing mode (consistent or lazy). - /// - /// - /// One of the values of the enumeration. - /// - [JsonProperty(PropertyName = Constants.Properties.SchemaBuilderMode)] - [JsonConverter(typeof(StringEnumConverter))] - public SchemaBuilderMode SchemaBuilderMode - { - get - { - SchemaBuilderMode result = SchemaBuilderMode.Lazy; - string strValue = base.GetValue(Constants.Properties.SchemaBuilderMode); - if(!string.IsNullOrEmpty(strValue)) - { - result = (SchemaBuilderMode)Enum.Parse(typeof(SchemaBuilderMode), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.SchemaBuilderMode, value.ToString()); - } - } - - /// - /// Performs a deep copy of the schema discovery policy. - /// - /// - /// A clone of the schema discovery policy. - /// - public object Clone() - { - SchemaDiscoveryPolicy cloned = new SchemaDiscoveryPolicy() - { - }; - - return cloned; - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.SchemaBuilderMode); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents the schema discovery policy configuration for a collection. + /// + /// + /// The schema discovery policy is used to control the schema builder through a collection configuration. + /// + /// + internal sealed class SchemaDiscoveryPolicy : JsonSerializable, ICloneable + { + /// + /// Initializes a new instance of the class. + /// + /// + /// Schema mode is set to none + /// + public SchemaDiscoveryPolicy() + { + this.SchemaBuilderMode = SchemaBuilderMode.None; + } + + /// + /// Gets or sets the indexing mode (consistent or lazy). + /// + /// + /// One of the values of the enumeration. + /// + [JsonProperty(PropertyName = Constants.Properties.SchemaBuilderMode)] + [JsonConverter(typeof(StringEnumConverter))] + public SchemaBuilderMode SchemaBuilderMode + { + get + { + SchemaBuilderMode result = SchemaBuilderMode.Lazy; + string strValue = base.GetValue(Constants.Properties.SchemaBuilderMode); + if(!string.IsNullOrEmpty(strValue)) + { + result = (SchemaBuilderMode)Enum.Parse(typeof(SchemaBuilderMode), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.SchemaBuilderMode, value.ToString()); + } + } + + /// + /// Performs a deep copy of the schema discovery policy. + /// + /// + /// A clone of the schema discovery policy. + /// + public object Clone() + { + SchemaDiscoveryPolicy cloned = new SchemaDiscoveryPolicy() + { + }; + + return cloned; + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.SchemaBuilderMode); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SendingRequestEventArgs.cs b/Microsoft.Azure.Cosmos/src/direct/SendingRequestEventArgs.cs index 2b7b753549..62cadb2b34 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SendingRequestEventArgs.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SendingRequestEventArgs.cs @@ -1,42 +1,42 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net.Http; - - internal sealed class SendingRequestEventArgs : EventArgs - { - public SendingRequestEventArgs(DocumentServiceRequest request) - { - this.DocumentServiceRequest = request; - } - - public SendingRequestEventArgs(HttpRequestMessage request) - { - this.HttpRequest = request; - } - - /// - /// The HttpRequestMessage on which the SendingRequest event is raised. - /// - public HttpRequestMessage HttpRequest { get; } - - /// - /// The DocumentServiceRequest on which the SendingRequest event is raised. - /// - public DocumentServiceRequest DocumentServiceRequest { get; } - - /// - /// Checks if the SendingRequestEventArgs has HttpRequestMessage as its member. - /// - /// Used to check if the message is HttpRequestMessage or DocumentServiceRequestMessage. - /// true if the message is HttpRequestMessage. otherwise, returns false. - public bool IsHttpRequest() - { - return this.HttpRequest != null; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net.Http; + + internal sealed class SendingRequestEventArgs : EventArgs + { + public SendingRequestEventArgs(DocumentServiceRequest request) + { + this.DocumentServiceRequest = request; + } + + public SendingRequestEventArgs(HttpRequestMessage request) + { + this.HttpRequest = request; + } + + /// + /// The HttpRequestMessage on which the SendingRequest event is raised. + /// + public HttpRequestMessage HttpRequest { get; } + + /// + /// The DocumentServiceRequest on which the SendingRequest event is raised. + /// + public DocumentServiceRequest DocumentServiceRequest { get; } + + /// + /// Checks if the SendingRequestEventArgs has HttpRequestMessage as its member. + /// + /// Used to check if the message is HttpRequestMessage or DocumentServiceRequestMessage. + /// true if the message is HttpRequestMessage. otherwise, returns false. + public bool IsHttpRequest() + { + return this.HttpRequest != null; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SerializableNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/SerializableNameValueCollection.cs index 40a133f3e1..8743fd7629 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SerializableNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SerializableNameValueCollection.cs @@ -1,157 +1,157 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.IO; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - internal sealed class SerializableNameValueCollection : JsonSerializable - { - private Lazy lazyCollection; - - public SerializableNameValueCollection() - { - this.lazyCollection = new Lazy(this.Init); - } - - public SerializableNameValueCollection(NameValueCollection collection) - { - this.lazyCollection = new Lazy(this.Init); - this.Collection.Add(collection); - } - - [JsonIgnore] - public NameValueCollection Collection - { - get - { - return this.lazyCollection.Value; - } - } - - // Helper methods - public static string SaveToString(SerializableNameValueCollection nameValueCollection) - { - if (nameValueCollection == null) - { - return string.Empty; - } - - using (MemoryStream ms = new MemoryStream()) - { - nameValueCollection.SaveTo(ms); - ms.Position = 0; - using (StreamReader reader = new StreamReader(ms)) - { - return reader.ReadToEnd(); - } - } - } - - public static SerializableNameValueCollection LoadFromString(string value) - { - if (!string.IsNullOrEmpty(value)) - { - using (MemoryStream ms = new MemoryStream()) - { - using (StreamWriter writer = new StreamWriter(ms)) - { - writer.Write(value); - writer.Flush(); - ms.Position = 0; - return JsonSerializable.LoadFrom(ms); - } - } - } - - return new SerializableNameValueCollection(); - } - - internal override void OnSave() - { - foreach (string key in this.Collection) - { - base.SetValue(key, this.Collection[key]); - } - } - - private NameValueCollection Init() - { - NameValueCollection collection = new NameValueCollection(); - if (this.propertyBag != null) - { - foreach (KeyValuePair pair in this.propertyBag) - { - JValue value = pair.Value as JValue; - if (value != null) - { - collection.Add(pair.Key, value.ToString()); - } - } - } - - return collection; - } - - public override bool Equals(object obj) - { - return this.Equals(obj as SerializableNameValueCollection); - } - - public bool Equals(SerializableNameValueCollection collection) - { - if (Object.ReferenceEquals(null, collection)) - { - return false; - } - - if (Object.ReferenceEquals(this, collection)) - { - return true; - } - - return this.IsEqual(collection); - } - - private bool IsEqual(SerializableNameValueCollection serializableNameValueCollection) - { - if (this.Collection.Count != serializableNameValueCollection.Collection.Count) - { - return false; - } - else - { - foreach (string key in this.Collection.AllKeys) - { - if (this.Collection[key] != serializableNameValueCollection.Collection[key]) - { - return false; - } - } - - return true; - } - } - - public override int GetHashCode() - { - unchecked - { - int hash = 0; - foreach (string key in this.Collection) - { - hash = (hash * 397) ^ key.GetHashCode(); - hash = (hash * 397) ^ (this.Collection.Get(key) != null ? this.Collection.Get(key).GetHashCode() : 0); - } - - return hash; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.IO; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + internal sealed class SerializableNameValueCollection : JsonSerializable + { + private Lazy lazyCollection; + + public SerializableNameValueCollection() + { + this.lazyCollection = new Lazy(this.Init); + } + + public SerializableNameValueCollection(NameValueCollection collection) + { + this.lazyCollection = new Lazy(this.Init); + this.Collection.Add(collection); + } + + [JsonIgnore] + public NameValueCollection Collection + { + get + { + return this.lazyCollection.Value; + } + } + + // Helper methods + public static string SaveToString(SerializableNameValueCollection nameValueCollection) + { + if (nameValueCollection == null) + { + return string.Empty; + } + + using (MemoryStream ms = new MemoryStream()) + { + nameValueCollection.SaveTo(ms); + ms.Position = 0; + using (StreamReader reader = new StreamReader(ms)) + { + return reader.ReadToEnd(); + } + } + } + + public static SerializableNameValueCollection LoadFromString(string value) + { + if (!string.IsNullOrEmpty(value)) + { + using (MemoryStream ms = new MemoryStream()) + { + using (StreamWriter writer = new StreamWriter(ms)) + { + writer.Write(value); + writer.Flush(); + ms.Position = 0; + return JsonSerializable.LoadFrom(ms); + } + } + } + + return new SerializableNameValueCollection(); + } + + internal override void OnSave() + { + foreach (string key in this.Collection) + { + base.SetValue(key, this.Collection[key]); + } + } + + private NameValueCollection Init() + { + NameValueCollection collection = new NameValueCollection(); + if (this.propertyBag != null) + { + foreach (KeyValuePair pair in this.propertyBag) + { + JValue value = pair.Value as JValue; + if (value != null) + { + collection.Add(pair.Key, value.ToString()); + } + } + } + + return collection; + } + + public override bool Equals(object obj) + { + return this.Equals(obj as SerializableNameValueCollection); + } + + public bool Equals(SerializableNameValueCollection collection) + { + if (Object.ReferenceEquals(null, collection)) + { + return false; + } + + if (Object.ReferenceEquals(this, collection)) + { + return true; + } + + return this.IsEqual(collection); + } + + private bool IsEqual(SerializableNameValueCollection serializableNameValueCollection) + { + if (this.Collection.Count != serializableNameValueCollection.Collection.Count) + { + return false; + } + else + { + foreach (string key in this.Collection.AllKeys) + { + if (this.Collection[key] != serializableNameValueCollection.Collection[key]) + { + return false; + } + } + + return true; + } + } + + public override int GetHashCode() + { + unchecked + { + int hash = 0; + foreach (string key in this.Collection) + { + hash = (hash * 397) ^ key.GetHashCode(); + hash = (hash * 397) ^ (this.Collection.Get(key) != null ? this.Collection.Get(key).GetHashCode() : 0); + } + + return hash; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SerializationFormattingPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/SerializationFormattingPolicy.cs index 82b1d953dc..908aa00298 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SerializationFormattingPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SerializationFormattingPolicy.cs @@ -1,23 +1,23 @@ -namespace Microsoft.Azure.Documents -{ - /// - /// The formatting policy associated with JSON serialization/de-serialization in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum SerializationFormattingPolicy - { - /// - /// No additional formatting required. - /// - None, - - /// - /// Indent the fields appropriately. - /// - Indented - } -} +namespace Microsoft.Azure.Documents +{ + /// + /// The formatting policy associated with JSON serialization/de-serialization in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum SerializationFormattingPolicy + { + /// + /// No additional formatting required. + /// + None, + + /// + /// Indent the fields appropriately. + /// + Indented + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ServerKey.cs b/Microsoft.Azure.Cosmos/src/direct/ServerKey.cs index 42721feeed..b34199fa55 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServerKey.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServerKey.cs @@ -1,75 +1,75 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - - internal sealed class ServerKey - { - public ServerKey(Uri uri) - { - Debug.Assert(uri != null); - this.Server = uri.DnsSafeHost; - this.Port = uri.Port; - } - - public string Server { get; private set; } - - public int Port { get; private set; } - - public override string ToString() - { - return string.Format("{0}:{1}", this.Server, this.Port); - } - - public override bool Equals(object obj) - { - if (obj == null) - { - return false; - } - return this.Equals(obj as ServerKey); - } - - public bool Equals(ServerKey key) - { - return key != null && this.Server.Equals(key.Server) && - this.Port == key.Port; - } - - public override int GetHashCode() - { - // FNV hash. - unchecked - { - const int factor = 0x120D6C21; // Prime number. - int hash = 0x22970BE1; // Prime number. - hash ^= this.Server.GetHashCode(); - hash *= factor; - // int.GetHashCode() returns the value itself, which is a bad hash. - hash ^= ServerKey.HashInt32(this.Port); - hash *= factor; - return hash; - } - } - - private static int HashInt32(int key) - { - // FNV hash. - unchecked - { - const int factor = 0x268E114D; // Prime number. - int hash = 0x0FE669CB; // Prime number. - for (int i = 0; i < 4; i++) - { - hash ^= (key & 0xFF); - hash *= factor; - key >>= 8; - } - return hash; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + + internal sealed class ServerKey + { + public ServerKey(Uri uri) + { + Debug.Assert(uri != null); + this.Server = uri.DnsSafeHost; + this.Port = uri.Port; + } + + public string Server { get; private set; } + + public int Port { get; private set; } + + public override string ToString() + { + return string.Format("{0}:{1}", this.Server, this.Port); + } + + public override bool Equals(object obj) + { + if (obj == null) + { + return false; + } + return this.Equals(obj as ServerKey); + } + + public bool Equals(ServerKey key) + { + return key != null && this.Server.Equals(key.Server) && + this.Port == key.Port; + } + + public override int GetHashCode() + { + // FNV hash. + unchecked + { + const int factor = 0x120D6C21; // Prime number. + int hash = 0x22970BE1; // Prime number. + hash ^= this.Server.GetHashCode(); + hash *= factor; + // int.GetHashCode() returns the value itself, which is a bad hash. + hash ^= ServerKey.HashInt32(this.Port); + hash *= factor; + return hash; + } + } + + private static int HashInt32(int key) + { + // FNV hash. + unchecked + { + const int factor = 0x268E114D; // Prime number. + int hash = 0x0FE669CB; // Prime number. + for (int i = 0; i < 4; i++) + { + hash ^= (key & 0xFF); + hash *= factor; + key >>= 8; + } + return hash; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ServerProperties.cs b/Microsoft.Azure.Cosmos/src/direct/ServerProperties.cs index 21eb74b5a8..b335003f6b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServerProperties.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServerProperties.cs @@ -1,18 +1,18 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - internal sealed class ServerProperties - { - public ServerProperties (string agent, string version) - { - this.Agent = agent; - this.Version = version; - } - - public string Agent { get; private set; } - - public string Version { get; private set; } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + internal sealed class ServerProperties + { + public ServerProperties (string agent, string version) + { + this.Agent = agent; + this.Version = version; + } + + public string Agent { get; private set; } + + public string Version { get; private set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ServerStoreModel.cs b/Microsoft.Azure.Cosmos/src/direct/ServerStoreModel.cs index 7e6c05b698..9c04efa004 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServerStoreModel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServerStoreModel.cs @@ -1,133 +1,133 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Threading; - using System.Threading.Tasks; - - internal sealed class ServerStoreModel : IStoreModelExtension - { - private readonly StoreClient storeClient; - private EventHandler sendingRequest; - private readonly EventHandler receivedResponse; - - public ServerStoreModel(StoreClient storeClient) - { - this.storeClient = storeClient; - } - - public ServerStoreModel(StoreClient storeClient, EventHandler sendingRequest, EventHandler receivedResponse) - : this(storeClient) - { - this.sendingRequest = sendingRequest; - this.receivedResponse = receivedResponse; - } - - #region Test hooks - public uint? DefaultReplicaIndex - { - get; - set; - } - - public string LastReadAddress - { - get - { - return this.storeClient.LastReadAddress; - } - set - { - this.storeClient.LastReadAddress = value; - } - } - - public bool ForceAddressRefresh - { - get - { - return this.storeClient.ForceAddressRefresh; - } - set - { - this.storeClient.ForceAddressRefresh = value; - } - } - #endregion - - public Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)) - { - if (this.DefaultReplicaIndex.HasValue) - { - request.DefaultReplicaIndex = this.DefaultReplicaIndex; - } - - string requestConsistencyLevelHeaderValue = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]; - - request.RequestContext.OriginalRequestConsistencyLevel = null; - - if (!string.IsNullOrEmpty(requestConsistencyLevelHeaderValue)) - { - ConsistencyLevel requestConsistencyLevel; - - if (!Enum.TryParse(requestConsistencyLevelHeaderValue, out requestConsistencyLevel)) - { - throw new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - requestConsistencyLevelHeaderValue, - HttpConstants.HttpHeaders.ConsistencyLevel)); - } - - request.RequestContext.OriginalRequestConsistencyLevel = requestConsistencyLevel; - } - - if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) - { - request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel] = ConsistencyLevel.Strong.ToString(); - } - - this.sendingRequest?.Invoke(this, new SendingRequestEventArgs(request)); - - if (this.receivedResponse != null) - { - return this.ProcessMessageWithReceivedResponseDelegateAsync(request, cancellationToken); - } - else - { - return this.storeClient.ProcessMessageAsync(request, cancellationToken); - } - - } - - /// > - public async Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default) - { - await this.storeClient.OpenConnectionsToAllReplicasAsync( - databaseName, - containerLinkUri, - cancellationToken); - } - - private async Task ProcessMessageWithReceivedResponseDelegateAsync( - DocumentServiceRequest request, - CancellationToken cancellationToken = default(CancellationToken)) - { - - DocumentServiceResponse response = await this.storeClient.ProcessMessageAsync(request, cancellationToken); - this.receivedResponse?.Invoke(this, new ReceivedResponseEventArgs(request, response)); - return response; - } - - public void Dispose() - { - - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Threading; + using System.Threading.Tasks; + + internal sealed class ServerStoreModel : IStoreModelExtension + { + private readonly StoreClient storeClient; + private EventHandler sendingRequest; + private readonly EventHandler receivedResponse; + + public ServerStoreModel(StoreClient storeClient) + { + this.storeClient = storeClient; + } + + public ServerStoreModel(StoreClient storeClient, EventHandler sendingRequest, EventHandler receivedResponse) + : this(storeClient) + { + this.sendingRequest = sendingRequest; + this.receivedResponse = receivedResponse; + } + + #region Test hooks + public uint? DefaultReplicaIndex + { + get; + set; + } + + public string LastReadAddress + { + get + { + return this.storeClient.LastReadAddress; + } + set + { + this.storeClient.LastReadAddress = value; + } + } + + public bool ForceAddressRefresh + { + get + { + return this.storeClient.ForceAddressRefresh; + } + set + { + this.storeClient.ForceAddressRefresh = value; + } + } + #endregion + + public Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)) + { + if (this.DefaultReplicaIndex.HasValue) + { + request.DefaultReplicaIndex = this.DefaultReplicaIndex; + } + + string requestConsistencyLevelHeaderValue = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]; + + request.RequestContext.OriginalRequestConsistencyLevel = null; + + if (!string.IsNullOrEmpty(requestConsistencyLevelHeaderValue)) + { + ConsistencyLevel requestConsistencyLevel; + + if (!Enum.TryParse(requestConsistencyLevelHeaderValue, out requestConsistencyLevel)) + { + throw new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + requestConsistencyLevelHeaderValue, + HttpConstants.HttpHeaders.ConsistencyLevel)); + } + + request.RequestContext.OriginalRequestConsistencyLevel = requestConsistencyLevel; + } + + if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) + { + request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel] = ConsistencyLevel.Strong.ToString(); + } + + this.sendingRequest?.Invoke(this, new SendingRequestEventArgs(request)); + + if (this.receivedResponse != null) + { + return this.ProcessMessageWithReceivedResponseDelegateAsync(request, cancellationToken); + } + else + { + return this.storeClient.ProcessMessageAsync(request, cancellationToken); + } + + } + + /// > + public async Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default) + { + await this.storeClient.OpenConnectionsToAllReplicasAsync( + databaseName, + containerLinkUri, + cancellationToken); + } + + private async Task ProcessMessageWithReceivedResponseDelegateAsync( + DocumentServiceRequest request, + CancellationToken cancellationToken = default(CancellationToken)) + { + + DocumentServiceResponse response = await this.storeClient.ProcessMessageAsync(request, cancellationToken); + this.receivedResponse?.Invoke(this, new ReceivedResponseEventArgs(request, response)); + return response; + } + + public void Dispose() + { + + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs b/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs index 1d82ec0bbd..8b2d501dc0 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs @@ -1,105 +1,105 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - using System; - - internal interface IServiceIdentity - { - string GetFederationId(); - - Uri GetServiceUri(); - - long GetPartitionKey(); - } - - internal sealed class ServiceIdentity : IServiceIdentity - { - /// - /// Needed for TestForWhiteListedPersistedTypes to succeed - /// - [JsonConstructor] - private ServiceIdentity() - { - } - - public ServiceIdentity(string federationId, Uri serviceName, bool isMasterService) - { - this.FederationId = federationId; - this.ServiceName = serviceName; - this.IsMasterService = isMasterService; - } - - [JsonProperty] - public string FederationId - { - get; - private set; - } - - [JsonProperty] - public Uri ServiceName - { - get; - private set; - } - - [JsonProperty] - public bool IsMasterService - { - get; - private set; - } - - public string ApplicationName - { - get - { - if (this.ServiceName == null) - { - return string.Empty; - } - else - { - return this.ServiceName.AbsoluteUri.Substring(0, this.ServiceName.AbsoluteUri.LastIndexOf('/')); - } - } - } - - public string GetFederationId() - { - return this.FederationId; - } - public Uri GetServiceUri() - { - return this.ServiceName; - } - - public long GetPartitionKey() - { - return 0; - } - - public override bool Equals(object obj) - { - ServiceIdentity other = obj as ServiceIdentity; - - return other != null && - string.Compare(this.FederationId, other.FederationId, StringComparison.OrdinalIgnoreCase) == 0 && - Uri.Compare(this.ServiceName, other.ServiceName, UriComponents.AbsoluteUri, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase) == 0; - } - - public override int GetHashCode() - { - return (this.FederationId == null ? 0 : this.FederationId.GetHashCode()) ^ - (this.ServiceName == null ? 0 : this.ServiceName.GetHashCode()); - } - - public override string ToString() - { - return $"FederationId:{this.FederationId},ServiceName:{this.ServiceName},IsMasterService:{this.IsMasterService}"; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + using System; + + internal interface IServiceIdentity + { + string GetFederationId(); + + Uri GetServiceUri(); + + long GetPartitionKey(); + } + + internal sealed class ServiceIdentity : IServiceIdentity + { + [JsonConstructor] + /// + /// Needed for TestForWhiteListedPersistedTypes to succeed + /// + private ServiceIdentity() + { + } + + public ServiceIdentity(string federationId, Uri serviceName, bool isMasterService) + { + this.FederationId = federationId; + this.ServiceName = serviceName; + this.IsMasterService = isMasterService; + } + + [JsonProperty] + public string FederationId + { + get; + private set; + } + + [JsonProperty] + public Uri ServiceName + { + get; + private set; + } + + [JsonProperty] + public bool IsMasterService + { + get; + private set; + } + + public string ApplicationName + { + get + { + if (this.ServiceName == null) + { + return string.Empty; + } + else + { + return this.ServiceName.AbsoluteUri.Substring(0, this.ServiceName.AbsoluteUri.LastIndexOf('/')); + } + } + } + + public string GetFederationId() + { + return this.FederationId; + } + public Uri GetServiceUri() + { + return this.ServiceName; + } + + public long GetPartitionKey() + { + return 0; + } + + public override bool Equals(object obj) + { + ServiceIdentity other = obj as ServiceIdentity; + + return other != null && + string.Compare(this.FederationId, other.FederationId, StringComparison.OrdinalIgnoreCase) == 0 && + Uri.Compare(this.ServiceName, other.ServiceName, UriComponents.AbsoluteUri, UriFormat.UriEscaped, StringComparison.OrdinalIgnoreCase) == 0; + } + + public override int GetHashCode() + { + return (this.FederationId == null ? 0 : this.FederationId.GetHashCode()) ^ + (this.ServiceName == null ? 0 : this.ServiceName.GetHashCode()); + } + + public override string ToString() + { + return $"FederationId:{this.FederationId},ServiceName:{this.ServiceName},IsMasterService:{this.IsMasterService}"; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ServiceInteropWrapper.cs b/Microsoft.Azure.Cosmos/src/direct/ServiceInteropWrapper.cs index 90f3f48900..b082d2176f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServiceInteropWrapper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServiceInteropWrapper.cs @@ -1,322 +1,322 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.IO; - using System.Reflection; - using System.Runtime.InteropServices; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal static class ServiceInteropWrapper - { - internal static Lazy AssembliesExist = new Lazy(() => - { - return ServiceInteropWrapper.CheckIfAssembliesExist(out string _); - }); - - static ServiceInteropWrapper() - { - ServiceInteropWrapper.Is64BitProcess = IntPtr.Size == 8; - -#if NETFX - // Framework only works on Windows - ServiceInteropWrapper.IsWindowsOSPlatform = true; -#else - ServiceInteropWrapper.IsWindowsOSPlatform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); -#endif - } - - internal static readonly bool Is64BitProcess; - - internal static readonly bool IsWindowsOSPlatform; - - // ServiceInterop is client level option based on ConnectionPolicy.QueryPlanGenerationMode - internal static bool UseServiceInterop(QueryPlanGenerationMode queryPlanRetrievalMode) - { - switch (queryPlanRetrievalMode) - { - case QueryPlanGenerationMode.GatewayOnly: - return false; - case QueryPlanGenerationMode.WindowsX64NativeOnly: - return true; - case QueryPlanGenerationMode.DefaultWindowsX64NativeWithFallbackToGateway: - return !CustomTypeExtensions.ByPassQueryParsing(); - default: - Debug.Fail($"Unexpected {nameof(QueryPlanGenerationMode)}: {queryPlanRetrievalMode}"); - return !CustomTypeExtensions.ByPassQueryParsing(); - } - } - - /// - /// Use AssembliesExist for all code paths. - /// This function is used in testing to validate different overrides. - /// - internal static bool CheckIfAssembliesExist(out string validationMessage) - { - validationMessage = string.Empty; - try - { - if (!ServiceInteropWrapper.IsGatewayAllowedToParseQueries()) - { - // Gateway is not allowed, skip validation and let runtime fail in-case of interop DLL non-existence - validationMessage = $"The environment variable {ServiceInteropWrapper.AllowGatewayToParseQueries} is overriding the service interop if exists validation."; - return true; - } - -#if !NETSTANDARD16 - DefaultTrace.TraceInformation($"Assembly location: {Assembly.GetExecutingAssembly().Location}"); - if (Assembly.GetExecutingAssembly().IsDynamic) - { - validationMessage = $"The service interop if exists validation skipped because Assembly.GetExecutingAssembly().IsDynamic is true"; - return true; - } - - string binDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); -#else - DefaultTrace.TraceInformation($"Assembly location: {(typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.Location)}"); - if (typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.IsDynamic) - { - validationMessage = $"The service interop if exists validation skipped because typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.IsDynamic is true"; - return true; - } - - // For NetCore check the entry assembly's path first (if available) since the interop DLL is copied to the application output directory - // (as specified in the Nuget package's target) - Assembly assembly = System.Reflection.Assembly.GetEntryAssembly() ?? typeof(ServiceInteropWrapper).GetTypeInfo().Assembly; - string binDir = Path.GetDirectoryName(assembly.Location); -#endif - - string dll = -#if COSMOSCLIENT - "Microsoft.Azure.Cosmos.ServiceInterop.dll"; -#else - "Microsoft.Azure.Documents.ServiceInterop.dll"; -#endif - - string dllPath = Path.Combine(binDir, dll); - validationMessage = $"The service interop location checked at {dllPath}"; - - if (!File.Exists(dllPath)) - { - DefaultTrace.TraceInformation($"ServiceInteropWrapper assembly not found at {dllPath}"); - return false; - } - - return true; - } - catch (Exception e) - { - // There has been certain environments where attempting to find the ServiceInterop has resulted in an exception. - // Instead of failing the SDK trace the exception and fall back to gateway mode. - DefaultTrace.TraceWarning($"ServiceInteropWrapper: Falling back to gateway. Finding ServiceInterop dll threw an exception {e}"); - } - - if (string.IsNullOrEmpty(validationMessage)) - { - validationMessage = $"An unexpected exception occurred while checking the file location"; - } - - return false; - } - -#if !NETSTANDARD16 - [System.Security.SuppressUnmanagedCodeSecurity] -#endif -#if COSMOSCLIENT - [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#else - [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#endif - public static extern - uint GetPartitionKeyRangesFromQuery( - [In] IntPtr serviceProvider, - [MarshalAs(UnmanagedType.LPWStr)][In] string query, - [In] bool requireFormattableOrderByQuery, - [In] bool isContinuationExpected, - [In] bool allowNonValueAggregateQuery, - [In] bool hasLogicalPartitionKey, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, - [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, - [In] uint partitionKeyDefinitionPathCount, - [In] PartitionKind partitionKind, - [In, Out] IntPtr serializedQueryExecutionInfoBuffer, - [In] uint serializedQueryExecutionInfoBufferLength, - [Out] out uint serializedQueryExecutionInfoResultLength); - -#if !NETSTANDARD16 - [System.Security.SuppressUnmanagedCodeSecurity] -#endif -#if COSMOSCLIENT - [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#else - [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#endif - public static extern - uint GetPartitionKeyRangesFromQuery2( - [In] IntPtr serviceProvider, - [MarshalAs(UnmanagedType.LPWStr)][In] string query, - [In] bool requireFormattableOrderByQuery, - [In] bool isContinuationExpected, - [In] bool allowNonValueAggregateQuery, - [In] bool hasLogicalPartitionKey, - [In] bool bAllowDCount, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, - [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, - [In] uint partitionKeyDefinitionPathCount, - [In] PartitionKind partitionKind, - [In, Out] IntPtr serializedQueryExecutionInfoBuffer, - [In] uint serializedQueryExecutionInfoBufferLength, - [Out] out uint serializedQueryExecutionInfoResultLength); - - // Layout should match corresponding native struct - [StructLayout(LayoutKind.Sequential)] - public struct PartitionKeyRangesApiOptions - { - public Int32 bRequireFormattableOrderByQuery; - - public Int32 bIsContinuationExpected; - - public Int32 bAllowNonValueAggregateQuery; - - public Int32 bHasLogicalPartitionKey; - - public Int32 bAllowDCount; - - public Int32 bUseSystemPrefix; - - public Int32 ePartitionKind; - - public Int32 eGeospatialType; - - // Reserve additional 32 bytes to match size with native PartitionKeyRangesApiOptions. - public Int64 unusedReserved1; - public Int64 unusedReserved2; - public Int64 unusedReserved3; - public Int64 unusedReserved4; - }; - -#if !NETSTANDARD16 - [System.Security.SuppressUnmanagedCodeSecurity] -#endif -#if COSMOSCLIENT - [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#else - [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#endif - public static extern - uint GetPartitionKeyRangesFromQuery3( - [In] IntPtr serviceProvider, - [MarshalAs(UnmanagedType.LPWStr)][In] string query, - [In] PartitionKeyRangesApiOptions partitionKeyRangesApiOptions, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, - [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, - [In] uint partitionKeyDefinitionPathCount, - [In, Out] IntPtr serializedQueryExecutionInfoBuffer, - [In] uint serializedQueryExecutionInfoBufferLength, - [Out] out uint serializedQueryExecutionInfoResultLength); - -#if !NETSTANDARD16 - [System.Security.SuppressUnmanagedCodeSecurity] -#endif -#if COSMOSCLIENT - [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#else - [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#endif - public static extern - uint CreateServiceProvider( - [MarshalAs(UnmanagedType.LPStr)][In] string configJsonString, - [Out] out IntPtr serviceProvider); - -#if !NETSTANDARD16 - [System.Security.SuppressUnmanagedCodeSecurity] -#endif -#if COSMOSCLIENT - [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#else - [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] -#endif - public static extern - uint UpdateServiceProvider( - [In] IntPtr serviceProvider, - [MarshalAs(UnmanagedType.LPStr)][In] string configJsonString); - - private const string DisableSkipInterop = "DisableSkipInterop"; // Used by V2 SDK Only - private const string AllowGatewayToParseQueries = "AllowGatewayToParseQueries"; // Used by V3 SDK Only - internal static bool IsGatewayAllowedToParseQueries() - { - bool? allowGatewayToParseQueries = ServiceInteropWrapper.GetSetting(ServiceInteropWrapper.AllowGatewayToParseQueries); - - if (allowGatewayToParseQueries != null) - { - return allowGatewayToParseQueries.Value; - } -#if !COSMOSCLIENT - // V2 SDK client uses below logic - bool? disableSkipInteropConfig = ServiceInteropWrapper.GetSetting(ServiceInteropWrapper.DisableSkipInterop); - - if (disableSkipInteropConfig != null) - { - return !disableSkipInteropConfig.Value; - } -#endif - // Default allow skip gateway - return true; - } - - // null return is either invalid setting or non-deterministric - private static bool? BoolParse(string boolValueString) - { - if (!string.IsNullOrEmpty(boolValueString)) - { - // Net standard 2.0 & net461 target breaks Boolean.TryParse!! - // Fall back to case in-sensitive string comparison - if (string.Equals(Boolean.TrueString, boolValueString, StringComparison.OrdinalIgnoreCase) - || string.Equals(1.ToString(), boolValueString, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (string.Equals(Boolean.FalseString, boolValueString, StringComparison.OrdinalIgnoreCase) - || string.Equals(0.ToString(), boolValueString, StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - bool parsedBoolValue = false; - if (Boolean.TryParse(boolValueString, out parsedBoolValue)) - { - return parsedBoolValue; - } - } - - return null; - } - - private static bool? GetSetting(string key) - { - string env = Environment.GetEnvironmentVariable(key); - DefaultTrace.TraceInformation($"ServiceInteropWrapper read {key} environment variable as {env}"); - bool? value = ServiceInteropWrapper.BoolParse(env); - DefaultTrace.TraceInformation($"ServiceInteropWrapper read parsed {key} environment variable as {value}"); - - if (value.HasValue) - { - return value.Value; - } - -#if !(NETSTANDARD15 || NETSTANDARD16) - string setting = System.Configuration.ConfigurationManager.AppSettings[key]; - DefaultTrace.TraceInformation($"ServiceInteropWrapper read {key} from AppConfig as {setting} "); - value = ServiceInteropWrapper.BoolParse(setting); - DefaultTrace.TraceInformation($"ServiceInteropWrapper read parsed {key} AppConfig as {value} "); -#endif - - return value; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.IO; + using System.Reflection; + using System.Runtime.InteropServices; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal static class ServiceInteropWrapper + { + internal static Lazy AssembliesExist = new Lazy(() => + { + return ServiceInteropWrapper.CheckIfAssembliesExist(out string _); + }); + + static ServiceInteropWrapper() + { + ServiceInteropWrapper.Is64BitProcess = IntPtr.Size == 8; + +#if NETFX + // Framework only works on Windows + ServiceInteropWrapper.IsWindowsOSPlatform = true; +#else + ServiceInteropWrapper.IsWindowsOSPlatform = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); +#endif + } + + internal static readonly bool Is64BitProcess; + + internal static readonly bool IsWindowsOSPlatform; + + // ServiceInterop is client level option based on ConnectionPolicy.QueryPlanGenerationMode + internal static bool UseServiceInterop(QueryPlanGenerationMode queryPlanRetrievalMode) + { + switch (queryPlanRetrievalMode) + { + case QueryPlanGenerationMode.GatewayOnly: + return false; + case QueryPlanGenerationMode.WindowsX64NativeOnly: + return true; + case QueryPlanGenerationMode.DefaultWindowsX64NativeWithFallbackToGateway: + return !CustomTypeExtensions.ByPassQueryParsing(); + default: + Debug.Fail($"Unexpected {nameof(QueryPlanGenerationMode)}: {queryPlanRetrievalMode}"); + return !CustomTypeExtensions.ByPassQueryParsing(); + } + } + + /// + /// Use AssembliesExist for all code paths. + /// This function is used in testing to validate different overrides. + /// + internal static bool CheckIfAssembliesExist(out string validationMessage) + { + validationMessage = string.Empty; + try + { + if (!ServiceInteropWrapper.IsGatewayAllowedToParseQueries()) + { + // Gateway is not allowed, skip validation and let runtime fail in-case of interop DLL non-existence + validationMessage = $"The environment variable {ServiceInteropWrapper.AllowGatewayToParseQueries} is overriding the service interop if exists validation."; + return true; + } + +#if !NETSTANDARD16 + DefaultTrace.TraceInformation($"Assembly location: {Assembly.GetExecutingAssembly().Location}"); + if (Assembly.GetExecutingAssembly().IsDynamic) + { + validationMessage = $"The service interop if exists validation skipped because Assembly.GetExecutingAssembly().IsDynamic is true"; + return true; + } + + string binDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); +#else + DefaultTrace.TraceInformation($"Assembly location: {(typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.Location)}"); + if (typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.IsDynamic) + { + validationMessage = $"The service interop if exists validation skipped because typeof(ServiceInteropWrapper).GetTypeInfo().Assembly.IsDynamic is true"; + return true; + } + + // For NetCore check the entry assembly's path first (if available) since the interop DLL is copied to the application output directory + // (as specified in the Nuget package's target) + Assembly assembly = System.Reflection.Assembly.GetEntryAssembly() ?? typeof(ServiceInteropWrapper).GetTypeInfo().Assembly; + string binDir = Path.GetDirectoryName(assembly.Location); +#endif + + string dll = +#if COSMOSCLIENT + "Microsoft.Azure.Cosmos.ServiceInterop.dll"; +#else + "Microsoft.Azure.Documents.ServiceInterop.dll"; +#endif + + string dllPath = Path.Combine(binDir, dll); + validationMessage = $"The service interop location checked at {dllPath}"; + + if (!File.Exists(dllPath)) + { + DefaultTrace.TraceInformation($"ServiceInteropWrapper assembly not found at {dllPath}"); + return false; + } + + return true; + } + catch (Exception e) + { + // There has been certain environments where attempting to find the ServiceInterop has resulted in an exception. + // Instead of failing the SDK trace the exception and fall back to gateway mode. + DefaultTrace.TraceWarning($"ServiceInteropWrapper: Falling back to gateway. Finding ServiceInterop dll threw an exception {e}"); + } + + if (string.IsNullOrEmpty(validationMessage)) + { + validationMessage = $"An unexpected exception occurred while checking the file location"; + } + + return false; + } + +#if !NETSTANDARD16 + [System.Security.SuppressUnmanagedCodeSecurity] +#endif +#if COSMOSCLIENT + [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#else + [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#endif + public static extern + uint GetPartitionKeyRangesFromQuery( + [In] IntPtr serviceProvider, + [MarshalAs(UnmanagedType.LPWStr)][In] string query, + [In] bool requireFormattableOrderByQuery, + [In] bool isContinuationExpected, + [In] bool allowNonValueAggregateQuery, + [In] bool hasLogicalPartitionKey, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, + [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, + [In] uint partitionKeyDefinitionPathCount, + [In] PartitionKind partitionKind, + [In, Out] IntPtr serializedQueryExecutionInfoBuffer, + [In] uint serializedQueryExecutionInfoBufferLength, + [Out] out uint serializedQueryExecutionInfoResultLength); + +#if !NETSTANDARD16 + [System.Security.SuppressUnmanagedCodeSecurity] +#endif +#if COSMOSCLIENT + [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#else + [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#endif + public static extern + uint GetPartitionKeyRangesFromQuery2( + [In] IntPtr serviceProvider, + [MarshalAs(UnmanagedType.LPWStr)][In] string query, + [In] bool requireFormattableOrderByQuery, + [In] bool isContinuationExpected, + [In] bool allowNonValueAggregateQuery, + [In] bool hasLogicalPartitionKey, + [In] bool bAllowDCount, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, + [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, + [In] uint partitionKeyDefinitionPathCount, + [In] PartitionKind partitionKind, + [In, Out] IntPtr serializedQueryExecutionInfoBuffer, + [In] uint serializedQueryExecutionInfoBufferLength, + [Out] out uint serializedQueryExecutionInfoResultLength); + + // Layout should match corresponding native struct + [StructLayout(LayoutKind.Sequential)] + public struct PartitionKeyRangesApiOptions + { + public Int32 bRequireFormattableOrderByQuery; + + public Int32 bIsContinuationExpected; + + public Int32 bAllowNonValueAggregateQuery; + + public Int32 bHasLogicalPartitionKey; + + public Int32 bAllowDCount; + + public Int32 bUseSystemPrefix; + + public Int32 ePartitionKind; + + public Int32 eGeospatialType; + + // Reserve additional 32 bytes to match size with native PartitionKeyRangesApiOptions. + public Int64 unusedReserved1; + public Int64 unusedReserved2; + public Int64 unusedReserved3; + public Int64 unusedReserved4; + }; + +#if !NETSTANDARD16 + [System.Security.SuppressUnmanagedCodeSecurity] +#endif +#if COSMOSCLIENT + [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#else + [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#endif + public static extern + uint GetPartitionKeyRangesFromQuery3( + [In] IntPtr serviceProvider, + [MarshalAs(UnmanagedType.LPWStr)][In] string query, + [In] PartitionKeyRangesApiOptions partitionKeyRangesApiOptions, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)][In] string[] partitionKeyDefinitionPathTokens, + [MarshalAs(UnmanagedType.LPArray)][In] uint[] partitionKeyDefinitionPathTokenLengths, + [In] uint partitionKeyDefinitionPathCount, + [In, Out] IntPtr serializedQueryExecutionInfoBuffer, + [In] uint serializedQueryExecutionInfoBufferLength, + [Out] out uint serializedQueryExecutionInfoResultLength); + +#if !NETSTANDARD16 + [System.Security.SuppressUnmanagedCodeSecurity] +#endif +#if COSMOSCLIENT + [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#else + [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#endif + public static extern + uint CreateServiceProvider( + [MarshalAs(UnmanagedType.LPStr)][In] string configJsonString, + [Out] out IntPtr serviceProvider); + +#if !NETSTANDARD16 + [System.Security.SuppressUnmanagedCodeSecurity] +#endif +#if COSMOSCLIENT + [DllImport("Microsoft.Azure.Cosmos.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#else + [DllImport("Microsoft.Azure.Documents.ServiceInterop.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl, BestFitMapping = false, ThrowOnUnmappableChar = true)] +#endif + public static extern + uint UpdateServiceProvider( + [In] IntPtr serviceProvider, + [MarshalAs(UnmanagedType.LPStr)][In] string configJsonString); + + private const string DisableSkipInterop = "DisableSkipInterop"; // Used by V2 SDK Only + private const string AllowGatewayToParseQueries = "AllowGatewayToParseQueries"; // Used by V3 SDK Only + internal static bool IsGatewayAllowedToParseQueries() + { + bool? allowGatewayToParseQueries = ServiceInteropWrapper.GetSetting(ServiceInteropWrapper.AllowGatewayToParseQueries); + + if (allowGatewayToParseQueries != null) + { + return allowGatewayToParseQueries.Value; + } +#if !COSMOSCLIENT + // V2 SDK client uses below logic + bool? disableSkipInteropConfig = ServiceInteropWrapper.GetSetting(ServiceInteropWrapper.DisableSkipInterop); + + if (disableSkipInteropConfig != null) + { + return !disableSkipInteropConfig.Value; + } +#endif + // Default allow skip gateway + return true; + } + + // null return is either invalid setting or non-deterministric + private static bool? BoolParse(string boolValueString) + { + if (!string.IsNullOrEmpty(boolValueString)) + { + // Net standard 2.0 & net461 target breaks Boolean.TryParse!! + // Fall back to case in-sensitive string comparison + if (string.Equals(Boolean.TrueString, boolValueString, StringComparison.OrdinalIgnoreCase) + || string.Equals(1.ToString(), boolValueString, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (string.Equals(Boolean.FalseString, boolValueString, StringComparison.OrdinalIgnoreCase) + || string.Equals(0.ToString(), boolValueString, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + bool parsedBoolValue = false; + if (Boolean.TryParse(boolValueString, out parsedBoolValue)) + { + return parsedBoolValue; + } + } + + return null; + } + + private static bool? GetSetting(string key) + { + string env = Environment.GetEnvironmentVariable(key); + DefaultTrace.TraceInformation($"ServiceInteropWrapper read {key} environment variable as {env}"); + bool? value = ServiceInteropWrapper.BoolParse(env); + DefaultTrace.TraceInformation($"ServiceInteropWrapper read parsed {key} environment variable as {value}"); + + if (value.HasValue) + { + return value.Value; + } + +#if !(NETSTANDARD15 || NETSTANDARD16) + string setting = System.Configuration.ConfigurationManager.AppSettings[key]; + DefaultTrace.TraceInformation($"ServiceInteropWrapper read {key} from AppConfig as {setting} "); + value = ServiceInteropWrapper.BoolParse(setting); + DefaultTrace.TraceInformation($"ServiceInteropWrapper read parsed {key} AppConfig as {value} "); +#endif + + return value; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/ServiceUnavailableException.cs b/Microsoft.Azure.Cosmos/src/direct/ServiceUnavailableException.cs index 3536077157..54c788c089 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServiceUnavailableException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServiceUnavailableException.cs @@ -1,161 +1,168 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class ServiceUnavailableException : DocumentClientException - { - public static ServiceUnavailableException Create(SubStatusCodes? subStatusCode, Exception innerException = null, HttpResponseHeaders headers = null, Uri requestUri = null) - { - subStatusCode ??= GetSubStatus(headers); - return new ServiceUnavailableException(GetExceptionMessage(subStatusCode), innerException, headers, subStatusCode); - } - - public static ServiceUnavailableException Create(INameValueCollection headers, SubStatusCodes? subStatusCode, Uri requestUri = null) - { - subStatusCode ??= GetSubStatus(headers); - return new ServiceUnavailableException(GetExceptionMessage(subStatusCode), headers, subStatusCode, requestUri); - } - - public ServiceUnavailableException() - : this(RMResources.ServiceUnavailable, null, null, SubStatusCodes.Unknown) - { - } - - public ServiceUnavailableException(string message) - : this(message, null, null, SubStatusCodes.Unknown) - { - } - public ServiceUnavailableException(string message, SubStatusCodes subStatusCode, Uri requestUri = null) - : this(message, null, null, subStatusCode, requestUri) - { - } - - public ServiceUnavailableException(string message, Exception innerException, SubStatusCodes subStatusCode, Uri requestUri = null) - : this(message, innerException, null, subStatusCode, requestUri) - { - } - - public ServiceUnavailableException(string message, HttpResponseHeaders headers, SubStatusCodes? subStatusCode, Uri requestUri = null) - : this(message, null, headers, subStatusCode, requestUri) - { - } - - public ServiceUnavailableException(Exception innerException, SubStatusCodes subStatusCode) - : this(RMResources.ServiceUnavailable, innerException, null, subStatusCode) - { - } - public ServiceUnavailableException(string message, INameValueCollection headers, SubStatusCodes? subStatusCode, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.ServiceUnavailable, subStatusCode, requestUri) - { - SetDescription(); - } - - public ServiceUnavailableException(string message, - Exception innerException, - HttpResponseHeaders headers, - SubStatusCodes? subStatusCode, - Uri requestUri = null) - : base(message, innerException, headers, HttpStatusCode.ServiceUnavailable, requestUri, subStatusCode) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private ServiceUnavailableException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.ServiceUnavailable) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.ServiceUnavailable; - } - - private static string GetExceptionMessage(SubStatusCodes? subStatusCode) - { - switch (subStatusCode) - { - case SubStatusCodes.TransportGenerated410: - return RMResources.TransportGenerated410; - case SubStatusCodes.TimeoutGenerated410: - return RMResources.TimeoutGenerated410; - case SubStatusCodes.Client_CPUOverload: - return RMResources.Client_CPUOverload; - case SubStatusCodes.Client_ThreadStarvation: - return RMResources.Client_ThreadStarvation; - case SubStatusCodes.TransportGenerated503: - return RMResources.TransportGenerated503; - case SubStatusCodes.ServerGenerated410: - return RMResources.ServerGenerated410; - case SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet: - return RMResources.Server_GlobalStrongWriteBarrierNotMet; - case SubStatusCodes.Server_ReadQuorumNotMet: - return RMResources.Server_ReadQuorumNotMet; - case SubStatusCodes.ServerGenerated503: - return RMResources.ServerGenerated503; - case SubStatusCodes.Server_NameCacheIsStaleExceededRetryLimit: - return RMResources.Server_NameCacheIsStaleExceededRetryLimit; - case SubStatusCodes.Server_PartitionKeyRangeGoneExceededRetryLimit: - return RMResources.Server_PartitionKeyRangeGoneExceededRetryLimit; - case SubStatusCodes.Server_CompletingSplitExceededRetryLimit: - return RMResources.Server_CompletingSplitExceededRetryLimit; - case SubStatusCodes.Server_CompletingPartitionMigrationExceededRetryLimit: - return RMResources.Server_CompletingPartitionMigrationExceededRetryLimit; - case SubStatusCodes.Server_NoValidStoreResponse: - return RMResources.Server_NoValidStoreResponse; - case SubStatusCodes.Channel_Closed: - return RMResources.ChannelClosed; - default: - return RMResources.ServiceUnavailable; - } - } - - static internal SubStatusCodes GetSubStatus(INameValueCollection responseHeaders) - { - SubStatusCodes? substatus = SubStatusCodes.Unknown; - - string valueSubStatus = responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); - if (!string.IsNullOrEmpty(valueSubStatus)) - { - uint nSubStatus; - if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) - { - substatus = (SubStatusCodes)nSubStatus; - } - } - - return substatus.Value; - } - - static internal SubStatusCodes GetSubStatus(HttpResponseHeaders responseHeaders) - { - if (responseHeaders != null) - { - IEnumerable substatusCodes; - if (responseHeaders.TryGetValues(WFConstants.BackendHeaders.SubStatus, out substatusCodes)) - { - uint nSubStatus; - if (uint.TryParse(substatusCodes.FirstOrDefault(), NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) - { - return (SubStatusCodes)nSubStatus; - } - } - } - - return SubStatusCodes.Unknown; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class ServiceUnavailableException : DocumentClientException + { + public static ServiceUnavailableException Create(SubStatusCodes? subStatusCode, Exception innerException = null, HttpResponseHeaders headers = null, Uri requestUri = null) + { + subStatusCode ??= GetSubStatus(headers); + return new ServiceUnavailableException(GetExceptionMessage(subStatusCode), innerException, headers, subStatusCode); + } + + public static ServiceUnavailableException Create(INameValueCollection headers, SubStatusCodes? subStatusCode, Uri requestUri = null) + { + subStatusCode ??= GetSubStatus(headers); + return new ServiceUnavailableException(GetExceptionMessage(subStatusCode), headers, subStatusCode, requestUri); + } + + public ServiceUnavailableException() + : this(RMResources.ServiceUnavailable, null, null, SubStatusCodes.Unknown) + { + } + + public ServiceUnavailableException(string message) + : this(message, null, null, SubStatusCodes.Unknown) + { + } + + public ServiceUnavailableException(string message, bool rawErrorMessageOnly) + : this(message, null, null, SubStatusCodes.Unknown, rawErrorMessageOnly: rawErrorMessageOnly) + { + } + + public ServiceUnavailableException(string message, SubStatusCodes subStatusCode, Uri requestUri = null, bool rawErrorMessageOnly = false) + : this(message, null, null, subStatusCode, requestUri, rawErrorMessageOnly: rawErrorMessageOnly) + { + } + + public ServiceUnavailableException(string message, Exception innerException, SubStatusCodes subStatusCode, Uri requestUri = null) + : this(message, innerException, null, subStatusCode, requestUri) + { + } + + public ServiceUnavailableException(string message, HttpResponseHeaders headers, SubStatusCodes? subStatusCode, Uri requestUri = null) + : this(message, null, headers, subStatusCode, requestUri) + { + } + + public ServiceUnavailableException(Exception innerException, SubStatusCodes subStatusCode) + : this(RMResources.ServiceUnavailable, innerException, null, subStatusCode) + { + } + public ServiceUnavailableException(string message, INameValueCollection headers, SubStatusCodes? subStatusCode, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.ServiceUnavailable, subStatusCode, requestUri) + { + SetDescription(); + } + + public ServiceUnavailableException(string message, + Exception innerException, + HttpResponseHeaders headers, + SubStatusCodes? subStatusCode, + Uri requestUri = null, + bool rawErrorMessageOnly = false) + : base(message, innerException, headers, HttpStatusCode.ServiceUnavailable, requestUri, subStatusCode, rawErrorMessageOnly: rawErrorMessageOnly) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private ServiceUnavailableException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.ServiceUnavailable) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.ServiceUnavailable; + } + + private static string GetExceptionMessage(SubStatusCodes? subStatusCode) + { + switch (subStatusCode) + { + case SubStatusCodes.TransportGenerated410: + return RMResources.TransportGenerated410; + case SubStatusCodes.TimeoutGenerated410: + return RMResources.TimeoutGenerated410; + case SubStatusCodes.Client_CPUOverload: + return RMResources.Client_CPUOverload; + case SubStatusCodes.Client_ThreadStarvation: + return RMResources.Client_ThreadStarvation; + case SubStatusCodes.TransportGenerated503: + return RMResources.TransportGenerated503; + case SubStatusCodes.ServerGenerated410: + return RMResources.ServerGenerated410; + case SubStatusCodes.Server_GlobalStrongWriteBarrierNotMet: + return RMResources.Server_GlobalStrongWriteBarrierNotMet; + case SubStatusCodes.Server_ReadQuorumNotMet: + return RMResources.Server_ReadQuorumNotMet; + case SubStatusCodes.ServerGenerated503: + return RMResources.ServerGenerated503; + case SubStatusCodes.Server_NameCacheIsStaleExceededRetryLimit: + return RMResources.Server_NameCacheIsStaleExceededRetryLimit; + case SubStatusCodes.Server_PartitionKeyRangeGoneExceededRetryLimit: + return RMResources.Server_PartitionKeyRangeGoneExceededRetryLimit; + case SubStatusCodes.Server_CompletingSplitExceededRetryLimit: + return RMResources.Server_CompletingSplitExceededRetryLimit; + case SubStatusCodes.Server_CompletingPartitionMigrationExceededRetryLimit: + return RMResources.Server_CompletingPartitionMigrationExceededRetryLimit; + case SubStatusCodes.Server_NoValidStoreResponse: + return RMResources.Server_NoValidStoreResponse; + case SubStatusCodes.Channel_Closed: + return RMResources.ChannelClosed; + default: + return RMResources.ServiceUnavailable; + } + } + + static internal SubStatusCodes GetSubStatus(INameValueCollection responseHeaders) + { + SubStatusCodes? substatus = SubStatusCodes.Unknown; + + string valueSubStatus = responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); + if (!string.IsNullOrEmpty(valueSubStatus)) + { + uint nSubStatus; + if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) + { + substatus = (SubStatusCodes)nSubStatus; + } + } + + return substatus.Value; + } + + static internal SubStatusCodes GetSubStatus(HttpResponseHeaders responseHeaders) + { + if (responseHeaders != null) + { + IEnumerable substatusCodes; + if (responseHeaders.TryGetValues(WFConstants.BackendHeaders.SubStatus, out substatusCodes)) + { + uint nSubStatus; + if (uint.TryParse(substatusCodes.FirstOrDefault(), NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) + { + return (SubStatusCodes)nSubStatus; + } + } + } + + return SubStatusCodes.Unknown; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SessionTokenHelper.cs b/Microsoft.Azure.Cosmos/src/direct/SessionTokenHelper.cs index ff4c3107ff..a34171adfe 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SessionTokenHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SessionTokenHelper.cs @@ -1,312 +1,312 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.Globalization; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal static class SessionTokenHelper - { - public static readonly char[] CharArrayWithColon = new char[] { ':' }; - public static readonly char[] CharArrayWithComma = new char[] { ',' }; - private static readonly char[] CharArrayWithCommaAndColon = new char[] { ',', ':' }; - - public static void SetOriginalSessionToken(DocumentServiceRequest request, string originalSessionToken) - { - if (request == null) - { - throw new ArgumentException("request"); - } - - if (originalSessionToken == null) - { - request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); - } - else - { - request.Headers[HttpConstants.HttpHeaders.SessionToken] = originalSessionToken; - } - } - - public static void ValidateAndRemoveSessionToken(DocumentServiceRequest request) - { - string sessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; - if (!string.IsNullOrEmpty(sessionToken)) - { - GetLocalSessionToken(request, sessionToken, string.Empty); - request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); - } - } - - public static void SetPartitionLocalSessionToken(DocumentServiceRequest entity, ISessionContainer sessionContainer) - { - if (entity == null) - { - throw new ArgumentException("entity"); - } - - string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; - string partitionKeyRangeId = entity.RequestContext.ResolvedPartitionKeyRange.Id; - - if (string.IsNullOrEmpty(partitionKeyRangeId)) - { - // AddressCache/address resolution didn't produce partition key range id. - // In this case it is a bug. - throw new InternalServerErrorException(RMResources.PartitionKeyRangeIdAbsentInContext); - } - - if (!string.IsNullOrEmpty(originalSessionToken)) - { - ISessionToken sessionToken = SessionTokenHelper.GetLocalSessionToken(entity, originalSessionToken, partitionKeyRangeId); - entity.RequestContext.SessionToken = sessionToken; - } - else - { - // use ambient session token. - ISessionToken sessionToken = sessionContainer.ResolvePartitionLocalSessionToken(entity, partitionKeyRangeId); - entity.RequestContext.SessionToken = sessionToken; - } - - if (entity.RequestContext.SessionToken == null) - { - entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); - } - else - { - string version = entity.Headers[HttpConstants.HttpHeaders.Version]; - version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; - - if (VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2015_12_16)) - { - entity.Headers[HttpConstants.HttpHeaders.SessionToken] = - SessionTokenHelper.SerializeSessionToken(partitionKeyRangeId, entity.RequestContext.SessionToken); - } - else - { - entity.Headers[HttpConstants.HttpHeaders.SessionToken] = - entity.RequestContext.SessionToken.ConvertToString(); - } - } - } - - internal static ISessionToken GetLocalSessionToken(DocumentServiceRequest request, string globalSessionToken, string partitionKeyRangeId) - { - string version = request.Headers[HttpConstants.HttpHeaders.Version]; - version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; - - if (!VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2015_12_16)) - { - // Pre elastic collection clients send token which is just lsn. - ISessionToken sessionToken; - if (!SimpleSessionToken.TryCreate(globalSessionToken, out sessionToken)) - { - throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, globalSessionToken)); - } - else - { - return sessionToken; - } - } - - // Convert global session token to local - there's no point in sending global token over the wire to the backend. - // Global session token is comma separated array of : pairs. For example: - // 2:425344,748:2341234,99:42344 - // Local session token is single : pair. - // Backend only cares about pair which relates to the range owned by the partition. - HashSet partitionKeyRangeSet = new HashSet(StringComparer.Ordinal); - partitionKeyRangeSet.Add(partitionKeyRangeId); - - ISessionToken highestSessionToken = null; - - if (request.RequestContext.ResolvedPartitionKeyRange != null && request.RequestContext.ResolvedPartitionKeyRange.Parents != null) - { - partitionKeyRangeSet.UnionWith(request.RequestContext.ResolvedPartitionKeyRange.Parents); - } - - foreach (string partitionKeyRangeToken in SessionTokenHelper.SplitPartitionLocalSessionTokens(globalSessionToken)) - { - string[] items = partitionKeyRangeToken.Split(SessionTokenHelper.CharArrayWithColon, StringSplitOptions.RemoveEmptyEntries); - - if (items.Length != 2) - { - throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, partitionKeyRangeToken)); - } - - ISessionToken parsedSessionToken = SessionTokenHelper.Parse(items[1]); - - if (partitionKeyRangeSet.Contains(items[0])) - { - if (highestSessionToken == null) - { - highestSessionToken = parsedSessionToken; - } - else - { - highestSessionToken = highestSessionToken.Merge(parsedSessionToken); - } - } - } - - return highestSessionToken; - } - - internal static ISessionToken ResolvePartitionLocalSessionToken( - DocumentServiceRequest request, - string partitionKeyRangeId, - ConcurrentDictionary partitionKeyRangeIdToTokenMap) - { - ISessionToken sessionToken; - if (partitionKeyRangeIdToTokenMap != null) - { - if (partitionKeyRangeIdToTokenMap.TryGetValue(partitionKeyRangeId, out sessionToken)) - { - return sessionToken; - } - else if (request.RequestContext.ResolvedPartitionKeyRange.Parents != null) - { - ISessionToken parentSessionToken = null; - for (int parentIndex = request.RequestContext.ResolvedPartitionKeyRange.Parents.Count - 1; parentIndex >= 0; parentIndex--) - { - if (partitionKeyRangeIdToTokenMap.TryGetValue(request.RequestContext.ResolvedPartitionKeyRange.Parents[parentIndex], out sessionToken)) - { - // A partition can have more than 1 parent (merge). In that case, we apply Merge to generate a token with both parent's max LSNs - parentSessionToken = parentSessionToken != null ? parentSessionToken.Merge(sessionToken) : sessionToken; - } - } - - // When we don't have the session token for a partition, we can leverage the session token of the parent(s) - if (parentSessionToken != null) - { - return parentSessionToken; - } - } - } - - return null; - } - - internal static ISessionToken Parse(string sessionToken) - { - if (SessionTokenHelper.TryParse(sessionToken, out ISessionToken partitionKeyRangeSessionToken)) - { - return partitionKeyRangeSessionToken; - } - else - { - throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, sessionToken)); - } - } - - internal static bool TryParse(string sessionToken, out ISessionToken parsedSessionToken) - { - return SessionTokenHelper.TryParse(sessionToken, out _, out parsedSessionToken); - } - - internal static bool TryParse(string sessionToken, out string partitionKeyRangeId, out ISessionToken parsedSessionToken) - { - parsedSessionToken = null; - return SessionTokenHelper.TryParse(sessionToken, out partitionKeyRangeId, out string sessionTokenSegment) - && SessionTokenHelper.TryParseSessionToken(sessionTokenSegment, out parsedSessionToken); - } - - internal static bool TryParseSessionToken(string sessionToken, out ISessionToken parsedSessionToken) - { - parsedSessionToken = null; - return !string.IsNullOrEmpty(sessionToken) && - (VectorSessionToken.TryCreate(sessionToken, out parsedSessionToken) - || SimpleSessionToken.TryCreate(sessionToken, out parsedSessionToken)); - } - - internal static bool TryParse(string sessionTokenString, out string partitionKeyRangeId, out string sessionToken) - { - partitionKeyRangeId = null; - if (string.IsNullOrEmpty(sessionTokenString)) - { - sessionToken = null; - return false; - } - - int colonIdx = sessionTokenString.IndexOf(':'); - if (colonIdx < 0) - { - sessionToken = sessionTokenString; - return true; - } - - partitionKeyRangeId = sessionTokenString.Substring(0, colonIdx); - sessionToken = sessionTokenString.Substring(colonIdx + 1); - return true; - } - - internal static ISessionToken Parse(string sessionToken, string version) - { - if (SessionTokenHelper.TryParse(sessionToken, out _, out string sessionTokenSegment)) - { - ISessionToken parsedSessionToken; - if (VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2018_06_18)) - { - if (VectorSessionToken.TryCreate(sessionTokenSegment, out parsedSessionToken)) - { - return parsedSessionToken; - } - } - else - { - if (SimpleSessionToken.TryCreate(sessionTokenSegment, out parsedSessionToken)) - { - return parsedSessionToken; - } - } - } - - DefaultTrace.TraceCritical("Unable to parse session token {0} for version {1}", sessionToken, version); - throw new InternalServerErrorException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, sessionToken)); - } - - internal static bool IsSingleGlobalLsnSessionToken(string sessionToken) - { - return sessionToken?.IndexOfAny(SessionTokenHelper.CharArrayWithCommaAndColon) < 0; - } - - internal static bool TryFindPartitionLocalSessionToken(string sessionTokens, string partitionKeyRangeId, out string partitionLocalSessionToken) - { - foreach (string tokenStr in SessionTokenHelper.SplitPartitionLocalSessionTokens(sessionTokens)) - { - // Assume each id appears only once in the global session token string. - if (SessionTokenHelper.TryParse(tokenStr, out string currPartitionKeyRangeId, out partitionLocalSessionToken) - && currPartitionKeyRangeId == partitionKeyRangeId) - { - return true; - } - } - - partitionLocalSessionToken = null; - return false; - } - - private static IEnumerable SplitPartitionLocalSessionTokens(string sessionTokens) - { - if (sessionTokens != null) - { - foreach (string token in sessionTokens.Split(SessionTokenHelper.CharArrayWithComma, StringSplitOptions.RemoveEmptyEntries)) - { - yield return token; - } - } - } - - internal static string SerializeSessionToken(string partitionKeyRangeId, ISessionToken parsedSessionToken) - { - if (partitionKeyRangeId == null) - { - return parsedSessionToken?.ConvertToString(); - } - - return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", partitionKeyRangeId, parsedSessionToken.ConvertToString()); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Globalization; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal static class SessionTokenHelper + { + public static readonly char[] CharArrayWithColon = new char[] { ':' }; + public static readonly char[] CharArrayWithComma = new char[] { ',' }; + private static readonly char[] CharArrayWithCommaAndColon = new char[] { ',', ':' }; + + public static void SetOriginalSessionToken(DocumentServiceRequest request, string originalSessionToken) + { + if (request == null) + { + throw new ArgumentException("request"); + } + + if (originalSessionToken == null) + { + request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); + } + else + { + request.Headers[HttpConstants.HttpHeaders.SessionToken] = originalSessionToken; + } + } + + public static void ValidateAndRemoveSessionToken(DocumentServiceRequest request) + { + string sessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + if (!string.IsNullOrEmpty(sessionToken)) + { + GetLocalSessionToken(request, sessionToken, string.Empty); + request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); + } + } + + public static void SetPartitionLocalSessionToken(DocumentServiceRequest entity, ISessionContainer sessionContainer) + { + if (entity == null) + { + throw new ArgumentException("entity"); + } + + string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; + string partitionKeyRangeId = entity.RequestContext.ResolvedPartitionKeyRange.Id; + + if (string.IsNullOrEmpty(partitionKeyRangeId)) + { + // AddressCache/address resolution didn't produce partition key range id. + // In this case it is a bug. + throw new InternalServerErrorException(RMResources.PartitionKeyRangeIdAbsentInContext); + } + + if (!string.IsNullOrEmpty(originalSessionToken)) + { + ISessionToken sessionToken = SessionTokenHelper.GetLocalSessionToken(entity, originalSessionToken, partitionKeyRangeId); + entity.RequestContext.SessionToken = sessionToken; + } + else + { + // use ambient session token. + ISessionToken sessionToken = sessionContainer.ResolvePartitionLocalSessionToken(entity, partitionKeyRangeId); + entity.RequestContext.SessionToken = sessionToken; + } + + if (entity.RequestContext.SessionToken == null) + { + entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); + } + else + { + string version = entity.Headers[HttpConstants.HttpHeaders.Version]; + version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; + + if (VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2015_12_16)) + { + entity.Headers[HttpConstants.HttpHeaders.SessionToken] = + SessionTokenHelper.SerializeSessionToken(partitionKeyRangeId, entity.RequestContext.SessionToken); + } + else + { + entity.Headers[HttpConstants.HttpHeaders.SessionToken] = + entity.RequestContext.SessionToken.ConvertToString(); + } + } + } + + internal static ISessionToken GetLocalSessionToken(DocumentServiceRequest request, string globalSessionToken, string partitionKeyRangeId) + { + string version = request.Headers[HttpConstants.HttpHeaders.Version]; + version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; + + if (!VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2015_12_16)) + { + // Pre elastic collection clients send token which is just lsn. + ISessionToken sessionToken; + if (!SimpleSessionToken.TryCreate(globalSessionToken, out sessionToken)) + { + throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, globalSessionToken)); + } + else + { + return sessionToken; + } + } + + // Convert global session token to local - there's no point in sending global token over the wire to the backend. + // Global session token is comma separated array of : pairs. For example: + // 2:425344,748:2341234,99:42344 + // Local session token is single : pair. + // Backend only cares about pair which relates to the range owned by the partition. + HashSet partitionKeyRangeSet = new HashSet(StringComparer.Ordinal); + partitionKeyRangeSet.Add(partitionKeyRangeId); + + ISessionToken highestSessionToken = null; + + if (request.RequestContext.ResolvedPartitionKeyRange != null && request.RequestContext.ResolvedPartitionKeyRange.Parents != null) + { + partitionKeyRangeSet.UnionWith(request.RequestContext.ResolvedPartitionKeyRange.Parents); + } + + foreach (string partitionKeyRangeToken in SessionTokenHelper.SplitPartitionLocalSessionTokens(globalSessionToken)) + { + string[] items = partitionKeyRangeToken.Split(SessionTokenHelper.CharArrayWithColon, StringSplitOptions.RemoveEmptyEntries); + + if (items.Length != 2) + { + throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, partitionKeyRangeToken)); + } + + ISessionToken parsedSessionToken = SessionTokenHelper.Parse(items[1]); + + if (partitionKeyRangeSet.Contains(items[0])) + { + if (highestSessionToken == null) + { + highestSessionToken = parsedSessionToken; + } + else + { + highestSessionToken = highestSessionToken.Merge(parsedSessionToken); + } + } + } + + return highestSessionToken; + } + + internal static ISessionToken ResolvePartitionLocalSessionToken( + DocumentServiceRequest request, + string partitionKeyRangeId, + ConcurrentDictionary partitionKeyRangeIdToTokenMap) + { + ISessionToken sessionToken; + if (partitionKeyRangeIdToTokenMap != null) + { + if (partitionKeyRangeIdToTokenMap.TryGetValue(partitionKeyRangeId, out sessionToken)) + { + return sessionToken; + } + else if (request.RequestContext.ResolvedPartitionKeyRange.Parents != null) + { + ISessionToken parentSessionToken = null; + for (int parentIndex = request.RequestContext.ResolvedPartitionKeyRange.Parents.Count - 1; parentIndex >= 0; parentIndex--) + { + if (partitionKeyRangeIdToTokenMap.TryGetValue(request.RequestContext.ResolvedPartitionKeyRange.Parents[parentIndex], out sessionToken)) + { + // A partition can have more than 1 parent (merge). In that case, we apply Merge to generate a token with both parent's max LSNs + parentSessionToken = parentSessionToken != null ? parentSessionToken.Merge(sessionToken) : sessionToken; + } + } + + // When we don't have the session token for a partition, we can leverage the session token of the parent(s) + if (parentSessionToken != null) + { + return parentSessionToken; + } + } + } + + return null; + } + + internal static ISessionToken Parse(string sessionToken) + { + if (SessionTokenHelper.TryParse(sessionToken, out ISessionToken partitionKeyRangeSessionToken)) + { + return partitionKeyRangeSessionToken; + } + else + { + throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, sessionToken)); + } + } + + internal static bool TryParse(string sessionToken, out ISessionToken parsedSessionToken) + { + return SessionTokenHelper.TryParse(sessionToken, out _, out parsedSessionToken); + } + + internal static bool TryParse(string sessionToken, out string partitionKeyRangeId, out ISessionToken parsedSessionToken) + { + parsedSessionToken = null; + return SessionTokenHelper.TryParse(sessionToken, out partitionKeyRangeId, out string sessionTokenSegment) + && SessionTokenHelper.TryParseSessionToken(sessionTokenSegment, out parsedSessionToken); + } + + internal static bool TryParseSessionToken(string sessionToken, out ISessionToken parsedSessionToken) + { + parsedSessionToken = null; + return !string.IsNullOrEmpty(sessionToken) && + (VectorSessionToken.TryCreate(sessionToken, out parsedSessionToken) + || SimpleSessionToken.TryCreate(sessionToken, out parsedSessionToken)); + } + + internal static bool TryParse(string sessionTokenString, out string partitionKeyRangeId, out string sessionToken) + { + partitionKeyRangeId = null; + if (string.IsNullOrEmpty(sessionTokenString)) + { + sessionToken = null; + return false; + } + + int colonIdx = sessionTokenString.IndexOf(':'); + if (colonIdx < 0) + { + sessionToken = sessionTokenString; + return true; + } + + partitionKeyRangeId = sessionTokenString.Substring(0, colonIdx); + sessionToken = sessionTokenString.Substring(colonIdx + 1); + return true; + } + + internal static ISessionToken Parse(string sessionToken, string version) + { + if (SessionTokenHelper.TryParse(sessionToken, out _, out string sessionTokenSegment)) + { + ISessionToken parsedSessionToken; + if (VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2018_06_18)) + { + if (VectorSessionToken.TryCreate(sessionTokenSegment, out parsedSessionToken)) + { + return parsedSessionToken; + } + } + else + { + if (SimpleSessionToken.TryCreate(sessionTokenSegment, out parsedSessionToken)) + { + return parsedSessionToken; + } + } + } + + DefaultTrace.TraceCritical("Unable to parse session token {0} for version {1}", sessionToken, version); + throw new InternalServerErrorException(string.Format(CultureInfo.InvariantCulture, RMResources.InvalidSessionToken, sessionToken)); + } + + internal static bool IsSingleGlobalLsnSessionToken(string sessionToken) + { + return sessionToken?.IndexOfAny(SessionTokenHelper.CharArrayWithCommaAndColon) < 0; + } + + internal static bool TryFindPartitionLocalSessionToken(string sessionTokens, string partitionKeyRangeId, out string partitionLocalSessionToken) + { + foreach (string tokenStr in SessionTokenHelper.SplitPartitionLocalSessionTokens(sessionTokens)) + { + // Assume each id appears only once in the global session token string. + if (SessionTokenHelper.TryParse(tokenStr, out string currPartitionKeyRangeId, out partitionLocalSessionToken) + && currPartitionKeyRangeId == partitionKeyRangeId) + { + return true; + } + } + + partitionLocalSessionToken = null; + return false; + } + + private static IEnumerable SplitPartitionLocalSessionTokens(string sessionTokens) + { + if (sessionTokens != null) + { + foreach (string token in sessionTokens.Split(SessionTokenHelper.CharArrayWithComma, StringSplitOptions.RemoveEmptyEntries)) + { + yield return token; + } + } + } + + internal static string SerializeSessionToken(string partitionKeyRangeId, ISessionToken parsedSessionToken) + { + if (partitionKeyRangeId == null) + { + return parsedSessionToken?.ConvertToString(); + } + + return string.Format(CultureInfo.InvariantCulture, "{0}:{1}", partitionKeyRangeId, parsedSessionToken.ConvertToString()); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SessionTokenMismatchRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/SessionTokenMismatchRetryPolicy.cs index fe94003668..9db7b64439 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SessionTokenMismatchRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SessionTokenMismatchRetryPolicy.cs @@ -1,143 +1,143 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Net; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal sealed class SessionTokenMismatchRetryPolicy : IRetryPolicy - { - private const string sessionRetryInitialBackoff = "AZURE_COSMOS_SESSION_RETRY_INITIAL_BACKOFF"; - private const string sessionRetryMaximumBackoff = "AZURE_COSMOS_SESSION_RETRY_MAXIMUM_BACKOFF"; - - private const int defaultWaitTimeInMilliSeconds = 5000; - private const int defaultInitialBackoffTimeInMilliseconds = 5; - private const int defaultMaximumBackoffTimeInMilliseconds = 500; - private const int backoffMultiplier = 2; - - private static readonly Lazy sessionRetryInitialBackoffConfig; - private static readonly Lazy sessionRetryMaximumBackoffConfig; - - private int retryCount; - private Stopwatch durationTimer = new Stopwatch(); - private int waitTimeInMilliSeconds; - - private int? currentBackoffInMilliSeconds; - - static SessionTokenMismatchRetryPolicy() - { - // Lazy load the environment variable to avoid the overhead of checking it and parsing the value - sessionRetryInitialBackoffConfig = new Lazy(() => - { - string sessionRetryInitialBackoffConfig = Environment.GetEnvironmentVariable(sessionRetryInitialBackoff); - if (!string.IsNullOrWhiteSpace(sessionRetryInitialBackoffConfig)) - { - if (int.TryParse(sessionRetryInitialBackoffConfig, out int value) && value >= 0) - { - return value; - } - else - { - DefaultTrace.TraceCritical("The value of AZURE_COSMOS_SESSION_RETRY_INITIAL_BACKOFF is invalid. Value: {0}", value); - } - } - - return SessionTokenMismatchRetryPolicy.defaultInitialBackoffTimeInMilliseconds; - }); - - sessionRetryMaximumBackoffConfig = new Lazy(() => - { - string sessionRetryMaximumBackoffConfig = Environment.GetEnvironmentVariable(sessionRetryMaximumBackoff); - if (!string.IsNullOrWhiteSpace(sessionRetryMaximumBackoffConfig)) - { - if (int.TryParse(sessionRetryMaximumBackoffConfig, out int value) && value >= 0) - { - return value; - } - else - { - DefaultTrace.TraceCritical("The value of AZURE_COSMOS_SESSION_RETRY_MAXIMUM_BACKOFF is invalid. Value: {0}", value); - } - } - - return SessionTokenMismatchRetryPolicy.defaultMaximumBackoffTimeInMilliseconds; - }); - } - - public SessionTokenMismatchRetryPolicy(int waitTimeInMilliSeconds = defaultWaitTimeInMilliSeconds) - { - this.durationTimer.Start(); - this.retryCount = 0; - this.waitTimeInMilliSeconds = waitTimeInMilliSeconds; - this.currentBackoffInMilliSeconds = null; - } - - public Task ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) - { - ShouldRetryResult result = ShouldRetryResult.NoRetry(); - - if (exception is DocumentClientException dce) - { - result = this.ShouldRetryInternalAsync( - dce?.StatusCode, - dce?.GetSubStatus()); - } - - return Task.FromResult(result); - } - - private ShouldRetryResult ShouldRetryInternalAsync( - HttpStatusCode? statusCode, - SubStatusCodes? subStatusCode) - { - if (statusCode.HasValue && statusCode.Value == HttpStatusCode.NotFound - && subStatusCode.HasValue && subStatusCode.Value == SubStatusCodes.ReadSessionNotAvailable) - { - int remainingTimeInMilliSeconds = this.waitTimeInMilliSeconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); - - if (remainingTimeInMilliSeconds <= 0) - { - this.durationTimer.Stop(); - DefaultTrace.TraceInformation("SessionTokenMismatchRetryPolicy not retrying because it has exceeded the time limit. Retry count = {0}", this.retryCount); - - return ShouldRetryResult.NoRetry(); - } - - TimeSpan backoffTime = TimeSpan.Zero; - - // Don't penalize first retry with delay - if (this.retryCount > 0) - { - if (!this.currentBackoffInMilliSeconds.HasValue) - { - this.currentBackoffInMilliSeconds = SessionTokenMismatchRetryPolicy.sessionRetryInitialBackoffConfig.Value; - } - - // Get the backoff time by selecting the smallest value between the remaining time and the current back off time - backoffTime = TimeSpan.FromMilliseconds( - Math.Min(this.currentBackoffInMilliSeconds.Value, remainingTimeInMilliSeconds)); - - // Update the current back off time - this.currentBackoffInMilliSeconds = - Math.Min( - this.currentBackoffInMilliSeconds.Value * SessionTokenMismatchRetryPolicy.backoffMultiplier, - SessionTokenMismatchRetryPolicy.sessionRetryMaximumBackoffConfig.Value); - } - - this.retryCount++; - DefaultTrace.TraceInformation("SessionTokenMismatchRetryPolicy will retry. Retry count = {0}. Backoff time = {1} ms", this.retryCount, backoffTime.Milliseconds); - - return ShouldRetryResult.RetryAfter(backoffTime); - } - - this.durationTimer.Stop(); - - return ShouldRetryResult.NoRetry(); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal sealed class SessionTokenMismatchRetryPolicy : IRetryPolicy + { + private const string sessionRetryInitialBackoff = "AZURE_COSMOS_SESSION_RETRY_INITIAL_BACKOFF"; + private const string sessionRetryMaximumBackoff = "AZURE_COSMOS_SESSION_RETRY_MAXIMUM_BACKOFF"; + + private const int defaultWaitTimeInMilliSeconds = 5000; + private const int defaultInitialBackoffTimeInMilliseconds = 5; + private const int defaultMaximumBackoffTimeInMilliseconds = 500; + private const int backoffMultiplier = 2; + + private static readonly Lazy sessionRetryInitialBackoffConfig; + private static readonly Lazy sessionRetryMaximumBackoffConfig; + + private int retryCount; + private Stopwatch durationTimer = new Stopwatch(); + private int waitTimeInMilliSeconds; + + private int? currentBackoffInMilliSeconds; + + static SessionTokenMismatchRetryPolicy() + { + // Lazy load the environment variable to avoid the overhead of checking it and parsing the value + sessionRetryInitialBackoffConfig = new Lazy(() => + { + string sessionRetryInitialBackoffConfig = Environment.GetEnvironmentVariable(sessionRetryInitialBackoff); + if (!string.IsNullOrWhiteSpace(sessionRetryInitialBackoffConfig)) + { + if (int.TryParse(sessionRetryInitialBackoffConfig, out int value) && value >= 0) + { + return value; + } + else + { + DefaultTrace.TraceCritical("The value of AZURE_COSMOS_SESSION_RETRY_INITIAL_BACKOFF is invalid. Value: {0}", value); + } + } + + return SessionTokenMismatchRetryPolicy.defaultInitialBackoffTimeInMilliseconds; + }); + + sessionRetryMaximumBackoffConfig = new Lazy(() => + { + string sessionRetryMaximumBackoffConfig = Environment.GetEnvironmentVariable(sessionRetryMaximumBackoff); + if (!string.IsNullOrWhiteSpace(sessionRetryMaximumBackoffConfig)) + { + if (int.TryParse(sessionRetryMaximumBackoffConfig, out int value) && value >= 0) + { + return value; + } + else + { + DefaultTrace.TraceCritical("The value of AZURE_COSMOS_SESSION_RETRY_MAXIMUM_BACKOFF is invalid. Value: {0}", value); + } + } + + return SessionTokenMismatchRetryPolicy.defaultMaximumBackoffTimeInMilliseconds; + }); + } + + public SessionTokenMismatchRetryPolicy(int waitTimeInMilliSeconds = defaultWaitTimeInMilliSeconds) + { + this.durationTimer.Start(); + this.retryCount = 0; + this.waitTimeInMilliSeconds = waitTimeInMilliSeconds; + this.currentBackoffInMilliSeconds = null; + } + + public Task ShouldRetryAsync(Exception exception, CancellationToken cancellationToken) + { + ShouldRetryResult result = ShouldRetryResult.NoRetry(); + + if (exception is DocumentClientException dce) + { + result = this.ShouldRetryInternalAsync( + dce?.StatusCode, + dce?.GetSubStatus()); + } + + return Task.FromResult(result); + } + + private ShouldRetryResult ShouldRetryInternalAsync( + HttpStatusCode? statusCode, + SubStatusCodes? subStatusCode) + { + if (statusCode.HasValue && statusCode.Value == HttpStatusCode.NotFound + && subStatusCode.HasValue && subStatusCode.Value == SubStatusCodes.ReadSessionNotAvailable) + { + int remainingTimeInMilliSeconds = this.waitTimeInMilliSeconds - Convert.ToInt32(this.durationTimer.Elapsed.TotalMilliseconds); + + if (remainingTimeInMilliSeconds <= 0) + { + this.durationTimer.Stop(); + DefaultTrace.TraceInformation("SessionTokenMismatchRetryPolicy not retrying because it has exceeded the time limit. Retry count = {0}", this.retryCount); + + return ShouldRetryResult.NoRetry(); + } + + TimeSpan backoffTime = TimeSpan.Zero; + + // Don't penalize first retry with delay + if (this.retryCount > 0) + { + if (!this.currentBackoffInMilliSeconds.HasValue) + { + this.currentBackoffInMilliSeconds = SessionTokenMismatchRetryPolicy.sessionRetryInitialBackoffConfig.Value; + } + + // Get the backoff time by selecting the smallest value between the remaining time and the current back off time + backoffTime = TimeSpan.FromMilliseconds( + Math.Min(this.currentBackoffInMilliSeconds.Value, remainingTimeInMilliSeconds)); + + // Update the current back off time + this.currentBackoffInMilliSeconds = + Math.Min( + this.currentBackoffInMilliSeconds.Value * SessionTokenMismatchRetryPolicy.backoffMultiplier, + SessionTokenMismatchRetryPolicy.sessionRetryMaximumBackoffConfig.Value); + } + + this.retryCount++; + DefaultTrace.TraceInformation("SessionTokenMismatchRetryPolicy will retry. Retry count = {0}. Backoff time = {1} ms", this.retryCount, backoffTime.Milliseconds); + + return ShouldRetryResult.RetryAfter(backoffTime); + } + + this.durationTimer.Stop(); + + return ShouldRetryResult.NoRetry(); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SimpleSessionToken.cs b/Microsoft.Azure.Cosmos/src/direct/SimpleSessionToken.cs index 6676f210c2..c894940819 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SimpleSessionToken.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SimpleSessionToken.cs @@ -1,91 +1,91 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - - /// - /// Implements session token with Global LSN - /// - /// We make assumption that instances of this interface are immutable (read only after they are constructed), so if you want to change - /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. - /// - internal sealed class SimpleSessionToken : ISessionToken - { - private readonly long globalLsn; - - public SimpleSessionToken(long globalLsn) - { - this.globalLsn = globalLsn; - } - - public static bool TryCreate(string globalLsn, out ISessionToken parsedSessionToken) - { - parsedSessionToken = null; - long parsedGlobalLsn = -1; - - if (long.TryParse(globalLsn, out parsedGlobalLsn)) - { - parsedSessionToken = new SimpleSessionToken(parsedGlobalLsn); - return true; - } - else - { - return false; - } - } - - public long LSN - { - get - { - return this.globalLsn; - } - } - - public bool Equals(ISessionToken obj) - { - SimpleSessionToken other = obj as SimpleSessionToken; - - if (other == null) - { - return false; - } - - return this.globalLsn.Equals(other.globalLsn); - } - - // Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) - public ISessionToken Merge(ISessionToken obj) - { - SimpleSessionToken other = obj as SimpleSessionToken; - - if (other == null) - { - throw new ArgumentNullException(nameof(obj)); - } - - return new SimpleSessionToken(Math.Max(this.globalLsn, other.globalLsn)); - } - - public bool IsValid(ISessionToken otherSessionToken) - { - SimpleSessionToken other = otherSessionToken as SimpleSessionToken; - - if (other == null) - { - throw new ArgumentNullException(nameof(otherSessionToken)); - } - - return other.globalLsn >= this.globalLsn; - } - - string ISessionToken.ConvertToString() - { - return this.globalLsn.ToString(CultureInfo.InvariantCulture); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + + /// + /// Implements session token with Global LSN + /// + /// We make assumption that instances of this interface are immutable (read only after they are constructed), so if you want to change + /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. + /// + internal sealed class SimpleSessionToken : ISessionToken + { + private readonly long globalLsn; + + public SimpleSessionToken(long globalLsn) + { + this.globalLsn = globalLsn; + } + + public static bool TryCreate(string globalLsn, out ISessionToken parsedSessionToken) + { + parsedSessionToken = null; + long parsedGlobalLsn = -1; + + if (long.TryParse(globalLsn, out parsedGlobalLsn)) + { + parsedSessionToken = new SimpleSessionToken(parsedGlobalLsn); + return true; + } + else + { + return false; + } + } + + public long LSN + { + get + { + return this.globalLsn; + } + } + + public bool Equals(ISessionToken obj) + { + SimpleSessionToken other = obj as SimpleSessionToken; + + if (other == null) + { + return false; + } + + return this.globalLsn.Equals(other.globalLsn); + } + + // Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) + public ISessionToken Merge(ISessionToken obj) + { + SimpleSessionToken other = obj as SimpleSessionToken; + + if (other == null) + { + throw new ArgumentNullException(nameof(obj)); + } + + return new SimpleSessionToken(Math.Max(this.globalLsn, other.globalLsn)); + } + + public bool IsValid(ISessionToken otherSessionToken) + { + SimpleSessionToken other = otherSessionToken as SimpleSessionToken; + + if (other == null) + { + throw new ArgumentNullException(nameof(otherSessionToken)); + } + + return other.globalLsn >= this.globalLsn; + } + + string ISessionToken.ConvertToString() + { + return this.globalLsn.ToString(CultureInfo.InvariantCulture); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs b/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs index bfa014b899..f7638500e6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs @@ -1,323 +1,323 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json; - - /// - /// Represents a snapshot in the Azure Cosmos DB service. - /// A snapshot represents a point in time logical snapshot of all data in an Azure Cosmos DB container. - /// - /// - /// An Azure Cosmos DB container is a repository for documents. A snapshot represents the state of - /// this container at a certain point in time. - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#snapshots for more details on snapshots. - /// - /// - /// The example below starts a creation of a snapshot for a specific container called "myContainer" - /// which lives under a database named "myDatabase". - /// - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - internal -#endif - class Snapshot : Resource - { - private new static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - private SnapshotContent snapshotContent; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public Snapshot() - { - } - - /// - /// Gets or sets the link of the container resource for which the snapshot was created in the Azure Cosmos DB service. - /// - /// - /// The name link of the container resource to which the snapshot applies, for example, "dbs/myDbName/colls/myCollName". - /// - /// - /// dbs/myDbName/colls/myCollName - /// - [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] - public string ResourceLink - { - get - { - return base.GetValue(Constants.Properties.ResourceLink); - } - set - { - base.SetValue(Constants.Properties.ResourceLink, value); - } - } - - /// - /// Gets the associated with the snapshot from the Azure Cosmos DB service. - /// - /// - /// The of this snapshot resource. - /// - [JsonProperty(PropertyName = Constants.Properties.State)] - public SnapshotState State - { - get - { - string strValue = base.GetValue(Constants.Properties.State); - if (string.IsNullOrEmpty(strValue)) - { - return SnapshotState.Invalid; - } - - SnapshotState state = (SnapshotState)Enum.Parse(typeof(SnapshotState), strValue, true); - return state; - } - internal set - { - base.SetValue(Constants.Properties.State, value.ToString()); - } - } - - /// - /// Gets the associated with the snapshot from the Azure Cosmos DB service. - /// - /// - /// The of this snapshot resource. - /// - [JsonProperty(PropertyName = Constants.Properties.Kind)] - public SnapshotKind Kind - { - get - { - string strValue = base.GetValue(Constants.Properties.Kind); - if (string.IsNullOrEmpty(strValue)) - { - return SnapshotKind.Invalid; - } - - SnapshotKind kind = (SnapshotKind)Enum.Parse(typeof(SnapshotKind), strValue, true); - return kind; - } - internal set - { - base.SetValue(Constants.Properties.Kind, value.ToString()); - } - } - - /// - /// Gets the snapshot's timestamp from the Azure Cosmos DB service. - /// - /// The timestamp at which this snapshot was created. - [JsonProperty(PropertyName = Constants.SnapshotProperties.SnapshotTimestamp)] - [JsonConverter(typeof(UnixDateTimeConverter))] - public DateTime SnapshotTimestamp - { - get - { - // Add seconds to the unix start time - return UnixStartTime.AddSeconds(base.GetValue(Constants.SnapshotProperties.SnapshotTimestamp)); - } - set - { - base.SetValue(Constants.SnapshotProperties.SnapshotTimestamp, (ulong)(value - UnixStartTime).TotalSeconds); - } - } - - /// - /// Gets the string of the container for which the snapshot was created. - /// - /// The resource ID of the container for which this snapshot was created. - [JsonProperty(PropertyName = Constants.Properties.OwnerResourceId)] - internal string OwnerResourceId - { - get - { - return base.GetValue(Constants.Properties.OwnerResourceId); - } - set - { - base.SetValue(Constants.Properties.OwnerResourceId, value); - } - } - - /// - /// Gets the size of collection snapshot in kilobytes. - /// - [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] - public ulong SizeInKB - { - get - { - return base.GetValue(Constants.Properties.SizeInKB); - } - internal set - { - base.SetValue(Constants.Properties.SizeInKB, value); - } - } - - /// - /// Gets the compressed size of collection snapshot in kilobytes. - /// - [JsonProperty(PropertyName = Constants.Properties.CompressedSizeInKB)] - public ulong CompressedSizeInKB - { - get - { - return base.GetValue(Constants.Properties.CompressedSizeInKB); - } - internal set - { - base.SetValue(Constants.Properties.CompressedSizeInKB, value); - } - } - - /// - /// Gets the LSN of the snapshot resource. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.LSN)] - internal long LSN - { - get - { - return base.GetValue(Constants.SnapshotProperties.LSN); - } - set - { - base.SetValue(Constants.SnapshotProperties.LSN, value); - } - } - - /// - /// Content of the Snapshot - /// - [JsonProperty(PropertyName = Constants.Properties.Content)] - internal SnapshotContent Content - { - get - { - if (this.snapshotContent == null) - { - this.snapshotContent = base.GetObject(Constants.Properties.Content); - } - return this.snapshotContent; - } - set - { - this.snapshotContent = value; - base.SetObject(Constants.Properties.Content, value); - } - } - - /// - /// Gets the string of the parent for which the snapshot was created. - /// - /// The resource ID of the parent for which this snapshot was created. - [JsonProperty(PropertyName = Constants.Properties.ParentResourceId)] - internal string ParentResourceId - { - get - { - return base.GetValue(Constants.Properties.ParentResourceId); - } - set - { - base.SetValue(Constants.Properties.ParentResourceId, value); - } - } - - internal override void OnSave() - { - base.OnSave(); - - if (this.snapshotContent != null) - { - this.snapshotContent.OnSave(); - base.SetObject(Constants.Properties.Content, this.snapshotContent); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.ResourceLink); - base.GetValue(Constants.Properties.State); - base.GetValue(Constants.Properties.Kind); - base.GetValue(Constants.SnapshotProperties.SnapshotTimestamp); - base.GetValue(Constants.Properties.OwnerResourceId); - base.GetValue(Constants.Properties.SizeInKB); - base.GetValue(Constants.SnapshotProperties.LSN); - base.GetValue(Constants.Properties.CompressedSizeInKB); - base.GetValue(Constants.Properties.ParentResourceId); - - if (this.Content != null) - { - this.Content.Validate(); - } - } - - /// - /// Initializes a new instance of the class from existing snapshot object. - /// - /// - /// - /// - internal static Snapshot CloneSystemSnapshot(Snapshot existingSnapshot, OperationType operationType, bool inheritSnapshotTimestamp) - { - if (existingSnapshot.Kind != SnapshotKind.System) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Invalid snapshot kind {0}", existingSnapshot.Kind)); - } - - Snapshot snapshot = new Snapshot(); - - snapshot.Kind = existingSnapshot.Kind; - snapshot.OwnerResourceId = existingSnapshot.OwnerResourceId; - snapshot.ResourceLink = existingSnapshot.ResourceLink; - snapshot.Content = new SnapshotContent() - { - OperationType = operationType, - SerializedDatabase = existingSnapshot.Content.SerializedDatabase, - SerializedCollection = existingSnapshot.Content.SerializedCollection, - SerializedOffer = existingSnapshot.Content.SerializedOffer, - SerializedPartitionKeyRanges = existingSnapshot.Content.SerializedPartitionKeyRanges, - GeoLinkIdToPKRangeRid = existingSnapshot.Content.GeoLinkIdToPKRangeRid - }; - - if (inheritSnapshotTimestamp) - { - snapshot.SnapshotTimestamp = existingSnapshot.SnapshotTimestamp; - } - else - { - // Setting to Timestamp to UnixStartTime so that the actual epoch timestamp gets zero. - // If actual timestamp is zero, then backend is going to auto-populate the snapshotTimestamp to current timestamp. - snapshot.SnapshotTimestamp = UnixStartTime; - } - - snapshot.State = SnapshotState.Completed; - - return snapshot; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Represents a snapshot in the Azure Cosmos DB service. + /// A snapshot represents a point in time logical snapshot of all data in an Azure Cosmos DB container. + /// + /// + /// An Azure Cosmos DB container is a repository for documents. A snapshot represents the state of + /// this container at a certain point in time. + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-resources/#snapshots for more details on snapshots. + /// + /// + /// The example below starts a creation of a snapshot for a specific container called "myContainer" + /// which lives under a database named "myDatabase". + /// + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + internal +#endif + class Snapshot : Resource + { + private static new DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + private SnapshotContent snapshotContent; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public Snapshot() + { + } + + /// + /// Gets or sets the link of the container resource for which the snapshot was created in the Azure Cosmos DB service. + /// + /// + /// The name link of the container resource to which the snapshot applies, for example, "dbs/myDbName/colls/myCollName". + /// + /// + /// dbs/myDbName/colls/myCollName + /// + [JsonProperty(PropertyName = Constants.Properties.ResourceLink)] + public string ResourceLink + { + get + { + return base.GetValue(Constants.Properties.ResourceLink); + } + set + { + base.SetValue(Constants.Properties.ResourceLink, value); + } + } + + /// + /// Gets the associated with the snapshot from the Azure Cosmos DB service. + /// + /// + /// The of this snapshot resource. + /// + [JsonProperty(PropertyName = Constants.Properties.State)] + public SnapshotState State + { + get + { + string strValue = base.GetValue(Constants.Properties.State); + if (string.IsNullOrEmpty(strValue)) + { + return SnapshotState.Invalid; + } + + SnapshotState state = (SnapshotState)Enum.Parse(typeof(SnapshotState), strValue, true); + return state; + } + internal set + { + base.SetValue(Constants.Properties.State, value.ToString()); + } + } + + /// + /// Gets the associated with the snapshot from the Azure Cosmos DB service. + /// + /// + /// The of this snapshot resource. + /// + [JsonProperty(PropertyName = Constants.Properties.Kind)] + public SnapshotKind Kind + { + get + { + string strValue = base.GetValue(Constants.Properties.Kind); + if (string.IsNullOrEmpty(strValue)) + { + return SnapshotKind.Invalid; + } + + SnapshotKind kind = (SnapshotKind)Enum.Parse(typeof(SnapshotKind), strValue, true); + return kind; + } + internal set + { + base.SetValue(Constants.Properties.Kind, value.ToString()); + } + } + + /// + /// Gets the snapshot's timestamp from the Azure Cosmos DB service. + /// + /// The timestamp at which this snapshot was created. + [JsonProperty(PropertyName = Constants.SnapshotProperties.SnapshotTimestamp)] + [JsonConverter(typeof(UnixDateTimeConverter))] + public DateTime SnapshotTimestamp + { + get + { + // Add seconds to the unix start time + return UnixStartTime.AddSeconds(base.GetValue(Constants.SnapshotProperties.SnapshotTimestamp)); + } + set + { + base.SetValue(Constants.SnapshotProperties.SnapshotTimestamp, (ulong)(value - UnixStartTime).TotalSeconds); + } + } + + /// + /// Gets the string of the container for which the snapshot was created. + /// + /// The resource ID of the container for which this snapshot was created. + [JsonProperty(PropertyName = Constants.Properties.OwnerResourceId)] + internal string OwnerResourceId + { + get + { + return base.GetValue(Constants.Properties.OwnerResourceId); + } + set + { + base.SetValue(Constants.Properties.OwnerResourceId, value); + } + } + + /// + /// Gets the size of collection snapshot in kilobytes. + /// + [JsonProperty(PropertyName = Constants.Properties.SizeInKB)] + public ulong SizeInKB + { + get + { + return base.GetValue(Constants.Properties.SizeInKB); + } + internal set + { + base.SetValue(Constants.Properties.SizeInKB, value); + } + } + + /// + /// Gets the compressed size of collection snapshot in kilobytes. + /// + [JsonProperty(PropertyName = Constants.Properties.CompressedSizeInKB)] + public ulong CompressedSizeInKB + { + get + { + return base.GetValue(Constants.Properties.CompressedSizeInKB); + } + internal set + { + base.SetValue(Constants.Properties.CompressedSizeInKB, value); + } + } + + /// + /// Gets the LSN of the snapshot resource. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.LSN)] + internal long LSN + { + get + { + return base.GetValue(Constants.SnapshotProperties.LSN); + } + set + { + base.SetValue(Constants.SnapshotProperties.LSN, value); + } + } + + /// + /// Content of the Snapshot + /// + [JsonProperty(PropertyName = Constants.Properties.Content)] + internal SnapshotContent Content + { + get + { + if (this.snapshotContent == null) + { + this.snapshotContent = base.GetObject(Constants.Properties.Content); + } + return this.snapshotContent; + } + set + { + this.snapshotContent = value; + base.SetObject(Constants.Properties.Content, value); + } + } + + /// + /// Gets the string of the parent for which the snapshot was created. + /// + /// The resource ID of the parent for which this snapshot was created. + [JsonProperty(PropertyName = Constants.Properties.ParentResourceId)] + internal string ParentResourceId + { + get + { + return base.GetValue(Constants.Properties.ParentResourceId); + } + set + { + base.SetValue(Constants.Properties.ParentResourceId, value); + } + } + + internal override void OnSave() + { + base.OnSave(); + + if (this.snapshotContent != null) + { + this.snapshotContent.OnSave(); + base.SetObject(Constants.Properties.Content, this.snapshotContent); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.ResourceLink); + base.GetValue(Constants.Properties.State); + base.GetValue(Constants.Properties.Kind); + base.GetValue(Constants.SnapshotProperties.SnapshotTimestamp); + base.GetValue(Constants.Properties.OwnerResourceId); + base.GetValue(Constants.Properties.SizeInKB); + base.GetValue(Constants.SnapshotProperties.LSN); + base.GetValue(Constants.Properties.CompressedSizeInKB); + base.GetValue(Constants.Properties.ParentResourceId); + + if (this.Content != null) + { + this.Content.Validate(); + } + } + + /// + /// Initializes a new instance of the class from existing snapshot object. + /// + /// + /// + /// + internal static Snapshot CloneSystemSnapshot(Snapshot existingSnapshot, OperationType operationType, bool inheritSnapshotTimestamp) + { + if (existingSnapshot.Kind != SnapshotKind.System) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Invalid snapshot kind {0}", existingSnapshot.Kind)); + } + + Snapshot snapshot = new Snapshot(); + + snapshot.Kind = existingSnapshot.Kind; + snapshot.OwnerResourceId = existingSnapshot.OwnerResourceId; + snapshot.ResourceLink = existingSnapshot.ResourceLink; + snapshot.Content = new SnapshotContent() + { + OperationType = operationType, + SerializedDatabase = existingSnapshot.Content.SerializedDatabase, + SerializedCollection = existingSnapshot.Content.SerializedCollection, + SerializedOffer = existingSnapshot.Content.SerializedOffer, + SerializedPartitionKeyRanges = existingSnapshot.Content.SerializedPartitionKeyRanges, + GeoLinkIdToPKRangeRid = existingSnapshot.Content.GeoLinkIdToPKRangeRid + }; + + if (inheritSnapshotTimestamp) + { + snapshot.SnapshotTimestamp = existingSnapshot.SnapshotTimestamp; + } + else + { + // Setting to Timestamp to UnixStartTime so that the actual epoch timestamp gets zero. + // If actual timestamp is zero, then backend is going to auto-populate the snapshotTimestamp to current timestamp. + snapshot.SnapshotTimestamp = UnixStartTime; + } + + snapshot.State = SnapshotState.Completed; + + return snapshot; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs b/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs index dc74d8ba14..c26276d2c5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs @@ -1,491 +1,491 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Text; - using Newtonsoft.Json; - - /// - /// SnapshotContent. - /// - - internal sealed class SnapshotContent : JsonSerializable - { - private Database databaseResource; - private DocumentCollection collectionResource; - private IList partitionKeyRanges; - private IList partitionKeyRangeList; - private SerializableNameValueCollection geoLinkIdToPKRangeRid; - - private IList partitionKeyRangeResourceIds; - private IList dataDirectories; - private IList storageAccountUris; - - // If Snapshot contains ClientEncryptionKeys this will be set - private IList serializedClientEncryptionKeys; - private IList clientEncryptionKeysList; - - [JsonConstructor] - public SnapshotContent() - { - - } - - // To instantiate snapshot of provisioned throughput collection - internal SnapshotContent( - OperationType operationType, - string serializedDatabase, - string serializedCollection, - string serializedOffer, - IList serializedPkranges) - { - if (operationType == OperationType.Invalid) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); - } - - this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); - this.ArgumentStringNotNullOrWhiteSpace(serializedCollection, nameof(serializedCollection)); - this.ArgumentStringNotNullOrWhiteSpace(serializedOffer, nameof(serializedOffer)); - - if (serializedPkranges == null || serializedPkranges.Count == 0) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(serializedPkranges))); - } - - this.OperationType = operationType; - this.SerializedDatabase = serializedDatabase; - this.SerializedCollection = serializedCollection; - this.SerializedOffer = serializedOffer; - this.SerializedPartitionKeyRanges = serializedPkranges; - } - - // To instantiate snapshot of a non-shared ru database - internal SnapshotContent( - OperationType operationType, - string serializedDatabase) - { - if (operationType == OperationType.Invalid) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); - } - - this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); - - this.OperationType = operationType; - this.SerializedDatabase = serializedDatabase; - } - - // To instantiate snapshot of a Shared RU database - internal SnapshotContent( - OperationType operationType, - string serializedDatabase, - string serializedOffer, - SerializableNameValueCollection geoLinkIdToPKRangeRid) - { - if (operationType == OperationType.Invalid) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); - } - - this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); - this.ArgumentStringNotNullOrWhiteSpace(serializedOffer, nameof(serializedOffer)); - - if (geoLinkIdToPKRangeRid == null || geoLinkIdToPKRangeRid.Collection.Count == 0) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(geoLinkIdToPKRangeRid))); - } - - this.OperationType = operationType; - this.SerializedDatabase = serializedDatabase; - this.SerializedOffer = serializedOffer; - this.GeoLinkIdToPKRangeRid = geoLinkIdToPKRangeRid; - } - - // To instantiate snapshot of a Shared RU collection - internal SnapshotContent( - OperationType operationType, - string serializedDatabase, - string serializedCollection, - IList serializedPkranges, - SerializableNameValueCollection geoLinkIdToPKRangeRid) - { - if (operationType == OperationType.Invalid) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); - } - - this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); - this.ArgumentStringNotNullOrWhiteSpace(serializedCollection, nameof(serializedCollection)); - - if (serializedPkranges == null || serializedPkranges.Count == 0) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(serializedPkranges))); - } - - if (geoLinkIdToPKRangeRid == null || geoLinkIdToPKRangeRid.Collection.Count == 0) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(geoLinkIdToPKRangeRid))); - } - - this.OperationType = operationType; - this.SerializedDatabase = serializedDatabase; - this.SerializedCollection = serializedCollection; - this.SerializedPartitionKeyRanges = serializedPkranges; - this.GeoLinkIdToPKRangeRid = geoLinkIdToPKRangeRid; - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.OperationType)] - public OperationType OperationType - { - get - { - string strValue = base.GetValue(Constants.Properties.OperationType); - if (string.IsNullOrEmpty(strValue)) - { - return OperationType.Invalid; - } - - OperationType type = (OperationType)Enum.Parse(typeof(OperationType), strValue, true); - return type; - } - internal set - { - base.SetValue(Constants.Properties.OperationType, (int)value); - } - } - - [JsonIgnore] - public Database Database - { - get - { - if (this.databaseResource == null && this.SerializedDatabase != null) - { - this.databaseResource = this.GetResourceIfDeserialized(this.SerializedDatabase); - } - - return this.databaseResource; - } - } - - [JsonIgnore] - public DocumentCollection DocumentCollection - { - get - { - if (this.collectionResource == null && this.SerializedCollection != null) - { - this.collectionResource = this.GetResourceIfDeserialized(this.SerializedCollection); - } - - return this.collectionResource; - } - } - - [JsonIgnore] - public IList PartitionKeyRangeList - { - get - { - if (this.partitionKeyRangeList == null && this.SerializedPartitionKeyRanges != null) - { - this.partitionKeyRangeList = new List(); - foreach (string partitionKeyRange in this.SerializedPartitionKeyRanges) - { - this.partitionKeyRangeList.Add(this.GetResourceIfDeserialized(partitionKeyRange)); - } - } - - return this.partitionKeyRangeList; - } - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.GeoLinkToPKRangeRid)] - public SerializableNameValueCollection GeoLinkIdToPKRangeRid - { - get - { - if (this.geoLinkIdToPKRangeRid == null) - { - this.geoLinkIdToPKRangeRid = base.GetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid); - - if(this.geoLinkIdToPKRangeRid == null) - { - this.geoLinkIdToPKRangeRid = new SerializableNameValueCollection(); - } - } - - return this.geoLinkIdToPKRangeRid; - } - internal set - { - this.geoLinkIdToPKRangeRid = value; - base.SetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid, value); - } - } - - /// - /// Gets the list of PartitionKeyRangeRids. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.PartitionKeyRangeResourceIds)] - public IList PartitionKeyRangeResourceIds - { - get - { - if (this.partitionKeyRangeResourceIds == null) - { - this.partitionKeyRangeResourceIds = base.GetValue>(Constants.SnapshotProperties.PartitionKeyRangeResourceIds); - } - - return this.partitionKeyRangeResourceIds; - } - internal set - { - this.partitionKeyRangeResourceIds = value; - base.SetValue(Constants.SnapshotProperties.PartitionKeyRangeResourceIds, value); - } - } - - /// - /// Gets the list of Data Directories. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.DataDirectories)] - public IList DataDirectories - { - get - { - if (this.dataDirectories == null) - { - this.dataDirectories = base.GetValue>(Constants.SnapshotProperties.DataDirectories); - } - - return this.dataDirectories; - } - internal set - { - this.dataDirectories = value; - base.SetValue(Constants.SnapshotProperties.DataDirectories, value); - } - } - - /// - /// Gets the Metadata Directory. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.MetadataDirectory)] - public string MetadataDirectory - { - get - { - return base.GetValue(Constants.SnapshotProperties.MetadataDirectory); - } - internal set - { - base.SetValue(Constants.SnapshotProperties.MetadataDirectory, value); - } - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.DatabaseContent)] - public string SerializedDatabase - { - get - { - return base.GetValue(Constants.SnapshotProperties.DatabaseContent); - } - internal set - { - base.SetValue(Constants.SnapshotProperties.DatabaseContent, value); - } - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.OfferContent)] - public string SerializedOffer - { - get - { - return base.GetValue(Constants.SnapshotProperties.OfferContent); - } - internal set - { - base.SetValue(Constants.SnapshotProperties.OfferContent, value); - } - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.CollectionContent)] - public string SerializedCollection - { - get - { - return base.GetValue(Constants.SnapshotProperties.CollectionContent); - } - internal set - { - base.SetValue(Constants.SnapshotProperties.CollectionContent, value); - } - } - - [JsonProperty(PropertyName = Constants.SnapshotProperties.IsMasterResourcesDeletionPending)] - public bool? IsMasterResourcesDeletionPending - { - get - { - return base.GetValue(Constants.SnapshotProperties.IsMasterResourcesDeletionPending, null); - } - internal set - { - base.SetValue(Constants.SnapshotProperties.IsMasterResourcesDeletionPending, value); - } - } - - /// - /// Gets the list of PartitionKeyRanges. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.PartitionKeyRanges)] - public IList SerializedPartitionKeyRanges - { - get - { - if (this.partitionKeyRanges == null) - { - this.partitionKeyRanges = base.GetValue>(Constants.SnapshotProperties.PartitionKeyRanges); - } - - return this.partitionKeyRanges; - } - internal set - { - this.partitionKeyRanges = value; - base.SetValue(Constants.SnapshotProperties.PartitionKeyRanges, value); - } - } - - /// - /// Gets the list of serialized ClientEncryptionKeys. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.ClientEncryptionKeyResources)] - public IList SerializedClientEncryptionKeyResources - { - get - { - if (this.serializedClientEncryptionKeys == null) - { - this.serializedClientEncryptionKeys = base.GetValue>(Constants.SnapshotProperties.ClientEncryptionKeyResources); - } - - return this.serializedClientEncryptionKeys; - } - internal set - { - this.serializedClientEncryptionKeys = value; - base.SetValue(Constants.SnapshotProperties.ClientEncryptionKeyResources, value); - } - } - - /// - /// Gets the list of StorageAccountUris. - /// - [JsonProperty(PropertyName = Constants.SnapshotProperties.StorageAccountUris)] - public IList StorageAccountUris - { - get - { - if (this.storageAccountUris == null) - { - this.storageAccountUris = base.GetValue>(Constants.SnapshotProperties.StorageAccountUris); - } - - return this.storageAccountUris; - } - internal set - { - this.storageAccountUris = value; - base.SetValue(Constants.SnapshotProperties.StorageAccountUris, value); - } - } - - [JsonIgnore] - public IList ClientEncryptionKeysList - { - get - { - if (this.clientEncryptionKeysList == null && this.SerializedClientEncryptionKeyResources != null) - { - this.clientEncryptionKeysList = new List(); - foreach (string clientEncryptionKey in this.SerializedClientEncryptionKeyResources) - { - this.clientEncryptionKeysList.Add(this.GetResourceIfDeserialized(clientEncryptionKey)); - } - } - - return this.clientEncryptionKeysList; - } - } - - internal override void OnSave() - { - base.OnSave(); - - // SerializedPartitionKeyRanges, SerializedCollection, SerializedOffer, SerializedDatabase and - // OperationType properties are generated by BE when creating the system snapshot. Hence these properties do not need - // a public setter for it and dont need to saved explicitly in the OnSave (since they will already be part of the propertybag) - if (this.partitionKeyRangeResourceIds != null) - { - base.SetValue(Constants.SnapshotProperties.PartitionKeyRangeResourceIds, this.partitionKeyRangeResourceIds); - } - - if (this.dataDirectories != null) - { - base.SetValue(Constants.SnapshotProperties.DataDirectories, this.dataDirectories); - } - - if (this.geoLinkIdToPKRangeRid != null) - { - this.geoLinkIdToPKRangeRid.OnSave(); - base.SetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid, this.geoLinkIdToPKRangeRid); - } - } - - private T GetResourceIfDeserialized(string body) where T : Resource, new() - { - try - { - byte[] byteArray = Encoding.UTF8.GetBytes(body); - using (MemoryStream stream = new MemoryStream(byteArray)) - { - ITypeResolver typeResolver = JsonSerializable.GetTypeResolver(); - return JsonSerializable.LoadFrom(stream, typeResolver); - } - } - catch (JsonException) - { - return null; - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue>(Constants.SnapshotProperties.PartitionKeyRangeResourceIds); - base.GetValue>(Constants.SnapshotProperties.DataDirectories); - } - - private void ArgumentStringNotNullOrWhiteSpace(string parameter, string parameterName) - { - if (string.IsNullOrWhiteSpace(parameterName)) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(parameterName))); - } - - if (string.IsNullOrWhiteSpace(parameter)) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, parameterName)); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Text; + using Newtonsoft.Json; + + /// + /// SnapshotContent. + /// + + internal sealed class SnapshotContent : JsonSerializable + { + private Database databaseResource; + private DocumentCollection collectionResource; + private IList partitionKeyRanges; + private IList partitionKeyRangeList; + private SerializableNameValueCollection geoLinkIdToPKRangeRid; + + private IList partitionKeyRangeResourceIds; + private IList dataDirectories; + private IList storageAccountUris; + + // If Snapshot contains ClientEncryptionKeys this will be set + private IList serializedClientEncryptionKeys; + private IList clientEncryptionKeysList; + + [JsonConstructor] + public SnapshotContent() + { + + } + + // To instantiate snapshot of provisioned throughput collection + internal SnapshotContent( + OperationType operationType, + string serializedDatabase, + string serializedCollection, + string serializedOffer, + IList serializedPkranges) + { + if (operationType == OperationType.Invalid) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); + } + + this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); + this.ArgumentStringNotNullOrWhiteSpace(serializedCollection, nameof(serializedCollection)); + this.ArgumentStringNotNullOrWhiteSpace(serializedOffer, nameof(serializedOffer)); + + if (serializedPkranges == null || serializedPkranges.Count == 0) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(serializedPkranges))); + } + + this.OperationType = operationType; + this.SerializedDatabase = serializedDatabase; + this.SerializedCollection = serializedCollection; + this.SerializedOffer = serializedOffer; + this.SerializedPartitionKeyRanges = serializedPkranges; + } + + // To instantiate snapshot of a non-shared ru database + internal SnapshotContent( + OperationType operationType, + string serializedDatabase) + { + if (operationType == OperationType.Invalid) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); + } + + this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); + + this.OperationType = operationType; + this.SerializedDatabase = serializedDatabase; + } + + // To instantiate snapshot of a Shared RU database + internal SnapshotContent( + OperationType operationType, + string serializedDatabase, + string serializedOffer, + SerializableNameValueCollection geoLinkIdToPKRangeRid) + { + if (operationType == OperationType.Invalid) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); + } + + this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); + this.ArgumentStringNotNullOrWhiteSpace(serializedOffer, nameof(serializedOffer)); + + if (geoLinkIdToPKRangeRid == null || geoLinkIdToPKRangeRid.Collection.Count == 0) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(geoLinkIdToPKRangeRid))); + } + + this.OperationType = operationType; + this.SerializedDatabase = serializedDatabase; + this.SerializedOffer = serializedOffer; + this.GeoLinkIdToPKRangeRid = geoLinkIdToPKRangeRid; + } + + // To instantiate snapshot of a Shared RU collection + internal SnapshotContent( + OperationType operationType, + string serializedDatabase, + string serializedCollection, + IList serializedPkranges, + SerializableNameValueCollection geoLinkIdToPKRangeRid) + { + if (operationType == OperationType.Invalid) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(operationType))); + } + + this.ArgumentStringNotNullOrWhiteSpace(serializedDatabase, nameof(serializedDatabase)); + this.ArgumentStringNotNullOrWhiteSpace(serializedCollection, nameof(serializedCollection)); + + if (serializedPkranges == null || serializedPkranges.Count == 0) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(serializedPkranges))); + } + + if (geoLinkIdToPKRangeRid == null || geoLinkIdToPKRangeRid.Collection.Count == 0) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(geoLinkIdToPKRangeRid))); + } + + this.OperationType = operationType; + this.SerializedDatabase = serializedDatabase; + this.SerializedCollection = serializedCollection; + this.SerializedPartitionKeyRanges = serializedPkranges; + this.GeoLinkIdToPKRangeRid = geoLinkIdToPKRangeRid; + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.OperationType)] + public OperationType OperationType + { + get + { + string strValue = base.GetValue(Constants.Properties.OperationType); + if (string.IsNullOrEmpty(strValue)) + { + return OperationType.Invalid; + } + + OperationType type = (OperationType)Enum.Parse(typeof(OperationType), strValue, true); + return type; + } + internal set + { + base.SetValue(Constants.Properties.OperationType, (int)value); + } + } + + [JsonIgnore] + public Database Database + { + get + { + if (this.databaseResource == null && this.SerializedDatabase != null) + { + this.databaseResource = this.GetResourceIfDeserialized(this.SerializedDatabase); + } + + return this.databaseResource; + } + } + + [JsonIgnore] + public DocumentCollection DocumentCollection + { + get + { + if (this.collectionResource == null && this.SerializedCollection != null) + { + this.collectionResource = this.GetResourceIfDeserialized(this.SerializedCollection); + } + + return this.collectionResource; + } + } + + [JsonIgnore] + public IList PartitionKeyRangeList + { + get + { + if (this.partitionKeyRangeList == null && this.SerializedPartitionKeyRanges != null) + { + this.partitionKeyRangeList = new List(); + foreach (string partitionKeyRange in this.SerializedPartitionKeyRanges) + { + this.partitionKeyRangeList.Add(this.GetResourceIfDeserialized(partitionKeyRange)); + } + } + + return this.partitionKeyRangeList; + } + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.GeoLinkToPKRangeRid)] + public SerializableNameValueCollection GeoLinkIdToPKRangeRid + { + get + { + if (this.geoLinkIdToPKRangeRid == null) + { + this.geoLinkIdToPKRangeRid = base.GetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid); + + if(this.geoLinkIdToPKRangeRid == null) + { + this.geoLinkIdToPKRangeRid = new SerializableNameValueCollection(); + } + } + + return this.geoLinkIdToPKRangeRid; + } + internal set + { + this.geoLinkIdToPKRangeRid = value; + base.SetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid, value); + } + } + + /// + /// Gets the list of PartitionKeyRangeRids. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.PartitionKeyRangeResourceIds)] + public IList PartitionKeyRangeResourceIds + { + get + { + if (this.partitionKeyRangeResourceIds == null) + { + this.partitionKeyRangeResourceIds = base.GetValue>(Constants.SnapshotProperties.PartitionKeyRangeResourceIds); + } + + return this.partitionKeyRangeResourceIds; + } + internal set + { + this.partitionKeyRangeResourceIds = value; + base.SetValue(Constants.SnapshotProperties.PartitionKeyRangeResourceIds, value); + } + } + + /// + /// Gets the list of Data Directories. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.DataDirectories)] + public IList DataDirectories + { + get + { + if (this.dataDirectories == null) + { + this.dataDirectories = base.GetValue>(Constants.SnapshotProperties.DataDirectories); + } + + return this.dataDirectories; + } + internal set + { + this.dataDirectories = value; + base.SetValue(Constants.SnapshotProperties.DataDirectories, value); + } + } + + /// + /// Gets the Metadata Directory. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.MetadataDirectory)] + public string MetadataDirectory + { + get + { + return base.GetValue(Constants.SnapshotProperties.MetadataDirectory); + } + internal set + { + base.SetValue(Constants.SnapshotProperties.MetadataDirectory, value); + } + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.DatabaseContent)] + public string SerializedDatabase + { + get + { + return base.GetValue(Constants.SnapshotProperties.DatabaseContent); + } + internal set + { + base.SetValue(Constants.SnapshotProperties.DatabaseContent, value); + } + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.OfferContent)] + public string SerializedOffer + { + get + { + return base.GetValue(Constants.SnapshotProperties.OfferContent); + } + internal set + { + base.SetValue(Constants.SnapshotProperties.OfferContent, value); + } + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.CollectionContent)] + public string SerializedCollection + { + get + { + return base.GetValue(Constants.SnapshotProperties.CollectionContent); + } + internal set + { + base.SetValue(Constants.SnapshotProperties.CollectionContent, value); + } + } + + [JsonProperty(PropertyName = Constants.SnapshotProperties.IsMasterResourcesDeletionPending)] + public bool? IsMasterResourcesDeletionPending + { + get + { + return base.GetValue(Constants.SnapshotProperties.IsMasterResourcesDeletionPending, null); + } + internal set + { + base.SetValue(Constants.SnapshotProperties.IsMasterResourcesDeletionPending, value); + } + } + + /// + /// Gets the list of PartitionKeyRanges. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.PartitionKeyRanges)] + public IList SerializedPartitionKeyRanges + { + get + { + if (this.partitionKeyRanges == null) + { + this.partitionKeyRanges = base.GetValue>(Constants.SnapshotProperties.PartitionKeyRanges); + } + + return this.partitionKeyRanges; + } + internal set + { + this.partitionKeyRanges = value; + base.SetValue(Constants.SnapshotProperties.PartitionKeyRanges, value); + } + } + + /// + /// Gets the list of serialized ClientEncryptionKeys. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.ClientEncryptionKeyResources)] + public IList SerializedClientEncryptionKeyResources + { + get + { + if (this.serializedClientEncryptionKeys == null) + { + this.serializedClientEncryptionKeys = base.GetValue>(Constants.SnapshotProperties.ClientEncryptionKeyResources); + } + + return this.serializedClientEncryptionKeys; + } + internal set + { + this.serializedClientEncryptionKeys = value; + base.SetValue(Constants.SnapshotProperties.ClientEncryptionKeyResources, value); + } + } + + /// + /// Gets the list of StorageAccountUris. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.StorageAccountUris)] + public IList StorageAccountUris + { + get + { + if (this.storageAccountUris == null) + { + this.storageAccountUris = base.GetValue>(Constants.SnapshotProperties.StorageAccountUris); + } + + return this.storageAccountUris; + } + internal set + { + this.storageAccountUris = value; + base.SetValue(Constants.SnapshotProperties.StorageAccountUris, value); + } + } + + [JsonIgnore] + public IList ClientEncryptionKeysList + { + get + { + if (this.clientEncryptionKeysList == null && this.SerializedClientEncryptionKeyResources != null) + { + this.clientEncryptionKeysList = new List(); + foreach (string clientEncryptionKey in this.SerializedClientEncryptionKeyResources) + { + this.clientEncryptionKeysList.Add(this.GetResourceIfDeserialized(clientEncryptionKey)); + } + } + + return this.clientEncryptionKeysList; + } + } + + internal override void OnSave() + { + base.OnSave(); + + // SerializedPartitionKeyRanges, SerializedCollection, SerializedOffer, SerializedDatabase and + // OperationType properties are generated by BE when creating the system snapshot. Hence these properties do not need + // a public setter for it and dont need to saved explicitly in the OnSave (since they will already be part of the propertybag) + if (this.partitionKeyRangeResourceIds != null) + { + base.SetValue(Constants.SnapshotProperties.PartitionKeyRangeResourceIds, this.partitionKeyRangeResourceIds); + } + + if (this.dataDirectories != null) + { + base.SetValue(Constants.SnapshotProperties.DataDirectories, this.dataDirectories); + } + + if (this.geoLinkIdToPKRangeRid != null) + { + this.geoLinkIdToPKRangeRid.OnSave(); + base.SetObject(Constants.SnapshotProperties.GeoLinkToPKRangeRid, this.geoLinkIdToPKRangeRid); + } + } + + private T GetResourceIfDeserialized(string body) where T : Resource, new() + { + try + { + byte[] byteArray = Encoding.UTF8.GetBytes(body); + using (MemoryStream stream = new MemoryStream(byteArray)) + { + ITypeResolver typeResolver = JsonSerializable.GetTypeResolver(); + return JsonSerializable.LoadFrom(stream, typeResolver); + } + } + catch (JsonException) + { + return null; + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue>(Constants.SnapshotProperties.PartitionKeyRangeResourceIds); + base.GetValue>(Constants.SnapshotProperties.DataDirectories); + } + + private void ArgumentStringNotNullOrWhiteSpace(string parameter, string parameterName) + { + if (string.IsNullOrWhiteSpace(parameterName)) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, nameof(parameterName))); + } + + if (string.IsNullOrWhiteSpace(parameter)) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, parameterName)); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SnapshotKind.cs b/Microsoft.Azure.Cosmos/src/direct/SnapshotKind.cs index e88c9c431a..c4b55a868b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SnapshotKind.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SnapshotKind.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the supported kinds of resources in the Azure Cosmos DB service. - /// - internal enum SnapshotKind - { - /// - /// Represents snapshots that were initiated by the user through a request to create a snapshot. - /// - OnDemand, - - /// - /// Represents the current state of a container. - /// - Live, - - /// - /// Represents the snapshotted state of a container whenever its partition map changes. - /// - System, - - Invalid - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the supported kinds of resources in the Azure Cosmos DB service. + /// + internal enum SnapshotKind + { + /// + /// Represents snapshots that were initiated by the user through a request to create a snapshot. + /// + OnDemand, + + /// + /// Represents the current state of a container. + /// + Live, + + /// + /// Represents the snapshotted state of a container whenever its partition map changes. + /// + System, + + Invalid + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SnapshotState.cs b/Microsoft.Azure.Cosmos/src/direct/SnapshotState.cs index 602f653e10..43ce96824e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SnapshotState.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SnapshotState.cs @@ -1,28 +1,28 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the possible states of a resource in the Azure Cosmos DB service. - /// - internal enum SnapshotState - { - /// - /// Represents snapshots that are in the process of being created. - /// - Pending, - - /// - /// Represents snapshots that are completely created and ready to be read. - /// - Completed, - - /// - /// Represents snapshots that failed to be created. - /// - Failed, - - Invalid - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the possible states of a resource in the Azure Cosmos DB service. + /// + internal enum SnapshotState + { + /// + /// Represents snapshots that are in the process of being created. + /// + Pending, + + /// + /// Represents snapshots that are completely created and ready to be read. + /// + Completed, + + /// + /// Represents snapshots that failed to be created. + /// + Failed, + + Invalid + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SpatialIndex.cs b/Microsoft.Azure.Cosmos/src/direct/SpatialIndex.cs index 070f7e5221..8eef45fc2e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SpatialIndex.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SpatialIndex.cs @@ -1,90 +1,90 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Specifies an instance of the class in the Azure Cosmos DB service. - /// - /// - /// Can be used to serve spatial queries. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class SpatialIndex : Index, ICloneable - { - internal SpatialIndex() - : base(IndexKind.Spatial) - { - } - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - /// Specifies the target data type for the index path specification - /// - /// - /// Here is an example to instantiate SpatialIndex class passing in the DataType - /// - /// - /// - /// - public SpatialIndex(DataType dataType) - : this() - { - this.DataType = dataType; - } - - /// - /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. - /// - /// - /// The data type for which this index should be applied. - /// - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. - [JsonProperty(PropertyName = Constants.Properties.DataType)] - [JsonConverter(typeof(StringEnumConverter))] - public DataType DataType - { - get - { - DataType result = default(DataType); - string strValue = base.GetValue(Constants.Properties.DataType); - if (!string.IsNullOrEmpty(strValue)) - { - result = (DataType)Enum.Parse(typeof(DataType), strValue, true); - } - return result; - } - set - { - base.SetValue(Constants.Properties.DataType, value.ToString()); - } - } - - internal override void Validate() - { - base.Validate(); - Helpers.ValidateEnumProperties(this.DataType); - } - - /// - /// Creates a copy of the spatial index for the Azure Cosmos DB service. - /// - /// A clone of the spatial index. - public object Clone() - { - return new SpatialIndex(this.DataType); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Specifies an instance of the class in the Azure Cosmos DB service. + /// + /// + /// Can be used to serve spatial queries. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class SpatialIndex : Index, ICloneable + { + internal SpatialIndex() + : base(IndexKind.Spatial) + { + } + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + /// Specifies the target data type for the index path specification + /// + /// + /// Here is an example to instantiate SpatialIndex class passing in the DataType + /// + /// + /// + /// + public SpatialIndex(DataType dataType) + : this() + { + this.DataType = dataType; + } + + /// + /// Gets or sets the data type for which this index should be applied in the Azure Cosmos DB service. + /// + /// + /// The data type for which this index should be applied. + /// + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-indexing-policies/#ConfigPolicy for valid ranges of values. + [JsonProperty(PropertyName = Constants.Properties.DataType)] + [JsonConverter(typeof(StringEnumConverter))] + public DataType DataType + { + get + { + DataType result = default(DataType); + string strValue = base.GetValue(Constants.Properties.DataType); + if (!string.IsNullOrEmpty(strValue)) + { + result = (DataType)Enum.Parse(typeof(DataType), strValue, true); + } + return result; + } + set + { + base.SetValue(Constants.Properties.DataType, value.ToString()); + } + } + + internal override void Validate() + { + base.Validate(); + Helpers.ValidateEnumProperties(this.DataType); + } + + /// + /// Creates a copy of the spatial index for the Azure Cosmos DB service. + /// + /// A clone of the spatial index. + public object Clone() + { + return new SpatialIndex(this.DataType); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SpatialSpec.cs b/Microsoft.Azure.Cosmos/src/direct/SpatialSpec.cs index 73dcde1a25..d42fb853dd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SpatialSpec.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SpatialSpec.cs @@ -1,159 +1,159 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Spatial index specification - /// - /// - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class SpatialSpec : JsonSerializable - { - private Collection spatialTypes; - private BoundingBoxSpec boundingBoxSpec; - - /// - /// Path in JSON document to index - /// - [JsonProperty(PropertyName = Constants.Properties.Path)] - public string Path - { - get - { - return base.GetValue(Constants.Properties.Path); - } - set - { - base.SetValue(Constants.Properties.Path, value); - } - } - - /// - /// Path's spatial type - /// - [JsonProperty(PropertyName = Constants.Properties.Types, ItemConverterType = typeof(StringEnumConverter))] - public Collection SpatialTypes - { - get - { - if (this.spatialTypes == null) - { - this.spatialTypes = base.GetValue>(Constants.Properties.Types); - - if (this.spatialTypes == null) - { - this.spatialTypes = new Collection(); - } - } - - return this.spatialTypes; - } - set - { - if (value == null) - { - throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, RMResources.PropertyCannotBeNull, "SpatialTypes")); - } - - this.spatialTypes = value; - base.SetValue(Constants.Properties.Types, value); - } - } - - /// - /// Gets or sets the bounding box - /// - [JsonProperty(PropertyName = Constants.Properties.BoundingBox, - NullValueHandling = NullValueHandling.Ignore)] - public BoundingBoxSpec BoundingBox - { - get - { - return base.GetValue(Constants.Properties.BoundingBox); - } - set - { - this.boundingBoxSpec = value; - this.SetValue(Constants.Properties.BoundingBox, this.boundingBoxSpec); - } - } - - internal object Clone() - { - SpatialSpec cloned = new SpatialSpec() - { - Path = this.Path - }; - - foreach (SpatialType spatialType in this.SpatialTypes) - { - cloned.SpatialTypes.Add(spatialType); - } - - if (this.boundingBoxSpec != null) - { - cloned.boundingBoxSpec = (BoundingBoxSpec)this.boundingBoxSpec.Clone(); - } - - return cloned; - } - - internal override void Validate() - { - base.Validate(); - base.GetValue(Constants.Properties.Path); - foreach (SpatialType spatialType in this.SpatialTypes) - { - Helpers.ValidateEnumProperties(spatialType); - } - - if (this.boundingBoxSpec != null) - { - boundingBoxSpec.Validate(); - } - } - - internal override void OnSave() - { - if (this.spatialTypes != null) - { - base.SetValue(Constants.Properties.Types, this.spatialTypes); - } - - if (this.boundingBoxSpec != null) - { - boundingBoxSpec.OnSave(); - base.SetValue(Constants.Properties.BoundingBox, this.boundingBoxSpec); - } - - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Spatial index specification + /// + /// + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class SpatialSpec : JsonSerializable + { + private Collection spatialTypes; + private BoundingBoxSpec boundingBoxSpec; + + /// + /// Path in JSON document to index + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get + { + return base.GetValue(Constants.Properties.Path); + } + set + { + base.SetValue(Constants.Properties.Path, value); + } + } + + /// + /// Path's spatial type + /// + [JsonProperty(PropertyName = Constants.Properties.Types, ItemConverterType = typeof(StringEnumConverter))] + public Collection SpatialTypes + { + get + { + if (this.spatialTypes == null) + { + this.spatialTypes = base.GetValue>(Constants.Properties.Types); + + if (this.spatialTypes == null) + { + this.spatialTypes = new Collection(); + } + } + + return this.spatialTypes; + } + set + { + if (value == null) + { + throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, RMResources.PropertyCannotBeNull, "SpatialTypes")); + } + + this.spatialTypes = value; + base.SetValue(Constants.Properties.Types, value); + } + } + + /// + /// Gets or sets the bounding box + /// + [JsonProperty(PropertyName = Constants.Properties.BoundingBox, + NullValueHandling = NullValueHandling.Ignore)] + public BoundingBoxSpec BoundingBox + { + get + { + return base.GetValue(Constants.Properties.BoundingBox); + } + set + { + this.boundingBoxSpec = value; + this.SetValue(Constants.Properties.BoundingBox, this.boundingBoxSpec); + } + } + + internal object Clone() + { + SpatialSpec cloned = new SpatialSpec() + { + Path = this.Path + }; + + foreach (SpatialType spatialType in this.SpatialTypes) + { + cloned.SpatialTypes.Add(spatialType); + } + + if (this.boundingBoxSpec != null) + { + cloned.boundingBoxSpec = (BoundingBoxSpec)this.boundingBoxSpec.Clone(); + } + + return cloned; + } + + internal override void Validate() + { + base.Validate(); + base.GetValue(Constants.Properties.Path); + foreach (SpatialType spatialType in this.SpatialTypes) + { + Helpers.ValidateEnumProperties(spatialType); + } + + if (this.boundingBoxSpec != null) + { + boundingBoxSpec.Validate(); + } + } + + internal override void OnSave() + { + if (this.spatialTypes != null) + { + base.SetValue(Constants.Properties.Types, this.spatialTypes); + } + + if (this.boundingBoxSpec != null) + { + boundingBoxSpec.OnSave(); + base.SetValue(Constants.Properties.BoundingBox, this.boundingBoxSpec); + } + + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SpatialType.cs b/Microsoft.Azure.Cosmos/src/direct/SpatialType.cs index d25d8990ef..2c43458886 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SpatialType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SpatialType.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Defines the target data type of an index path specification in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum SpatialType - { - /// - /// Represent a point data type. - /// - Point, - - /// - /// Represent a line string data type. - /// - LineString, - - /// - /// Represent a polygon data type. - /// - Polygon, - - /// - /// Represent a multi-polygon data type. - /// - MultiPolygon, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Defines the target data type of an index path specification in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum SpatialType + { + /// + /// Represent a point data type. + /// + Point, + + /// + /// Represent a line string data type. + /// + LineString, + + /// + /// Represent a polygon data type. + /// + Polygon, + + /// + /// Represent a multi-polygon data type. + /// + MultiPolygon, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs b/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs index 6248082c74..866c5abb2e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs @@ -1,331 +1,376 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -using System; -using System.Collections.Generic; - -namespace Microsoft.Azure.Documents -{ - internal enum StatusCodes - { - Processing = 102, - - // Success - Ok = 200, - Created = 201, - Accepted = 202, - NoContent = 204, - MultiStatus = 207, - NotModified = 304, - - // Client error - StartingErrorCode = 400, - - BadRequest = 400, - Unauthorized = 401, - Forbidden = 403, - NotFound = 404, - MethodNotAllowed = 405, - RequestTimeout = 408, - Conflict = 409, - Gone = 410, - PreconditionFailed = 412, - RequestEntityTooLarge = 413, - Locked = 423, - FailedDependency = 424, - TooManyRequests = 429, - RetryWith = 449, - - InternalServerError = 500, - BadGateway = 502, - ServiceUnavailable = 503, - - //Operation pause and cancel. These are FAKE status codes for QOS logging purpose only. - OperationPaused = 1200, - OperationCancelled = 1201 - } - - internal enum SubStatusCodes - { - Unknown = 0, - TooManyRequests = 429, - - // 400: Bad Request Substatus - PartitionKeyMismatch = 1001, - CrossPartitionQueryNotServable = 1004, - ScriptCompileError = 0xFFFF, // From ExecuteStoredProcedure. - AnotherOfferReplaceOperationIsInProgress = 3205, - HttpListenerException = 1101, - - // 410: StatusCodeType_Gone: substatus - NameCacheIsStale = 1000, - PartitionKeyRangeGone = 1002, - CompletingSplit = 1007, - CompletingPartitionMigration = 1008, - LeaseNotFound = 1022, - ArchivalPartitionNotPresent = 1024, - - // 404: LSN in session token is higher - ReadSessionNotAvailable = 1002, - OwnerResourceNotFound = 1003, - ConfigurationNameNotFound = 1004, - ConfigurationPropertyNotFound = 1005, - CollectionCreateInProgress = 1013, - StoreNotReady = 1023, - AuthTokenNotFoundInCache = 1030, - - // 404: StatusCodeType_NotFound: substatus - PartitionMigratingCollectionDeleted = 1031, - PartitionMigrationSourcePartitionDeletedInMaster = 1034, - PartitionMigrationSharedThroughputDatabasePartitionResourceNotFoundInMaster = 1035, - PartitionMigrationPartitionResourceNotFoundInMaster = 1036, - PartitionMigrationFailedToUpdateDNS = 1037, - - // 403: Forbidden Substatus. - WriteForbidden = 3, - ProvisionLimitReached = 1005, - DatabaseAccountNotFound = 1008, - RedundantCollectionPut = 1009, - SharedThroughputDatabaseQuotaExceeded = 1010, - SharedThroughputOfferGrowNotNeeded = 1011, - PartitionKeyQuotaOverLimit = 1014, - SharedThroughputDatabaseCollectionCountExceeded = 1019, - SharedThroughputDatabaseCountExceeded = 1020, - ComputeInternalError = 1021, - ThroughputCapQuotaExceeded = 1028, - InvalidThroughputCapValue = 1029, - - // 409: Conflict exception - ConflictWithControlPlane = 1006, - DatabaseNameAlreadyExists = 3206, - ConfigurationNameAlreadyExists = 3207, - PartitionkeyHashCollisionForId = 3302, - - // 409: Partition migration Count mismatch conflict sub status codes - PartitionMigrationDocumentCountMismatchBetweenSourceAndTargetPartition = 3050, - PartitionMigrationDocumentCountMismatchBetweenTargetPartitionReplicas = 3051, - - // 503: Service Unavailable due to region being out of capacity for bindable partitions - InsufficientBindablePartitions = 1007, - ComputeFederationNotFound = 1012, - OperationPaused = 9001, - InsufficientCapacity = 9003, - - // Federation Buildout / Expansion error codes - AggregatedHealthStateError = 6001, // - Aggregated health state is Error - ApplicationHealthStateError = 6002, // - Any application is in Warning or Error state - HealthStateError = 6003, // - Any health events in Error state are found - UnhealthyEventFound = 6004, // - Any unhealthy evaluations are found (except for Warning evaluations on Nodes) - ClusterHealthEmpty = 6005, // Cluster Health States is empty - AllocationFailed = 6006, // Allocation failed for federation - OperationResultNull = 6007, // Null operation result - OperationResultUnexpected = 6008, // Null operation result - - //412: PreCondition Failed - SplitIsDisabled = 2001, - CollectionsInPartitionGotUpdated = 2002, - CanNotAcquirePKRangesLock = 2003, - ResourceNotFound = 2004, - CanNotAcquireOfferOwnerLock = 2005, - CanNotAcquirePKRangeLock = 2007, - CanNotAcquirePartitionLock = 2008, - CanNotAcquireSnapshotOwnerLock = 2005, - StorageSplitConflictingWithNWayThroughputSplit = 2011, - MergeIsDisabled = 2012, - TombstoneRecordsNotFound = 2015, // Tombstone records were not found because they were purged. - InvalidAccountStatus = 2016, - OfferValidationFailed = 2017, - CanNotAquireMasterPartitionAccessLock = 2018, - CanNotAcquireInAccountRestoreInProgressLock = 2019, - CollectionStateChanged = 2020, - OfferScaledUpByUser = 2021, - - //412: PreConditionFailed migration substatus codes - PartitionMigrationCancelledForPendingUserOperation = 2006, - PartitionMigrationCanNotAcquireGlobalPartitionMigrationLock = 2009, - PartitionMigrationCanNotAcquireFederationPartitionMigrationLock = 2010, - PartitionMigrationServiceTypeAndOperationTypeDoesnotMatch = 2020, - PartitionMigrationGlobalDatabaseAccountResourceNotFound = 2021, - PartitionMigrationMasterFederationForWriteRegionNotFound = 2022, - PartitionMigrationMasterFederationForCurrentRegionNotFound = 2023, - PartitionMigrationSourceAndTargetFederationSubregionIsNotSame = 2024, - PartitionMigrationFailedToCreatePartitionMigrationLocks = 2025, - PartitionMigrationFailedToResolvePartitionInformation = 2026, - PartitionMigrationIsDisableOnTheGlobalDatabaseAccount = 2028, - PartitionMigrationIsDisableOnTheRunnerAccount = 2029, - PartitionMigrationCanNotProceedForInactiveRegionalDatabaseAccount = 2030, - PartitionMigrationDidNotCompleteWaitForFullSyncInTenRetries = 2031, - PartitionMigrationCanNotProceedForDeletingRegionalDatabaseAccount = 2032, - PartitionMigrationCanNotProceedForDeletionFailedRegionalDatabaseAccount = 2033, - PartitionMigrationCanNotAcquireRegionalDatabaseAccountPartitionMigrationLock = 2034, - PartitionMigrationIsDisabledOnReadyForDecommissionFederation = 2035, - PartitionMigrationCanNotAcquirePartitionLock = 2036, - PartitionMigrationCanNotAcquirePartitionKeyRangesLock = 2037, - PartitionMigrationCanNotProceedForDeletingGlobalDatabaseAccount = 2038, - PartitionMigrationCanNotProceedForDeletionFailedGlobalDatabaseAccount = 2039, - PartitionMigrationCanNotProceedForRevokedGlobalDatabaseAccount = 2040, - PartitionMigrationMasterServiceTopologyHasWriteRegionEmpty = 2041, - PartitionMigrationWriteRegionServiceTopologyHasWriteRegionEmpty = 2042, - PartitionMigrationIsDisabledOnFinalizingDecommissionFederation = 2043, - - // 500: InternalServerError - ConfigurationNameNotEmpty = 3001, - ConfigurationOperationCancelled = 3002, - InvalidAccountConfiguration = 3003, - FederationDoesnotExistOrIsLocked = 3004, - PartitionFailoverErrorCode = 3010, - - // 429: Request Rate Too Large - PrepareTimeLimitExceeded = 3207, - ClientTcpChannelFull = 3208, - BWTermCountLimitExceeded = 3209, - RUBudgetExceeded = 3200, - GatewayThrottled = 3201, - StoredProcedureConcurrency = 3084, - - // Key Vault Access Client Error Code - AadClientCredentialsGrantFailure = 4000, // Indicated access to AAD failed to get a token - AadServiceUnavailable = 4001, // Aad Service is Unavailable - KeyVaultAuthenticationFailure = 4002, // Indicate the KeyVault doesn't grant permission to the AAD, or the key is disabled. - KeyVaultKeyNotFound = 4003, // Indicate the Key Vault Key is not found - KeyVaultServiceUnavailable = 4004, // Key Vault Service is Unavailable - KeyVaultWrapUnwrapFailure = 4005, // Indicate that Key Vault is unable to Wrap or Unwrap, one possible scenario is KeyVault failed to decoded the encrypted blob using the latest key because customer has rotated the key. - InvalidKeyVaultKeyURI = 4006, // Indicate the Key Vault Key URI is invalid. - InvalidInputBytes = 4007, // The input bytes are not in the format of base64. - KeyVaultInternalServerError = 4008, // Other unknown errors - KeyVaultDNSNotResolved = 4009, // Key Vault DNS name could not be resolved, mostly due to customer enter incorrect KeyVault name. - InvalidKeyVaultCertURI = 4010, // Indicate the Key Vault Cert URI is invalid. - InvalidKeyVaultKeyAndCertURI = 4011, // Indicate the Key Vault Key and Cert URI is invalid. - CustomerKeyRotated = 4012, // Indicates the rewrapped key doesn't match with existing key. - MissingRequestParameter = 4013, // Indicates that the incoming request has missing parameters. - InvalidKeyVaultSecretURI = 4014, // Indicates the Key Vault secret URI is invalid. - UndefinedDefaultIdentity = 4015, // Indicates that the account has an undefined default identity. - NspOutboundDenied = 4016, // Indicates that the account's NSP is blocking outbound requests to Key Vault. - KeyVaultNotFound = 4017, // Indicates that the Key Vault could not be found by the system. - - // Keep in sync with Microsoft.Azure.Cosmos.ServiceFramework.Security.AadAuthentication.AadSubStatusCodes - // 401 : Unauthorized Exception (User-side errors start with 50) - MissingAuthHeader = 5000, - InvalidAuthHeaderFormat = 5001, - AadAuthDisabled = 5002, - AadTokenInvalidFormat = 5003, - AadTokenInvalidSignature = 5004, - AadTokenNotYetValid = 5005, - AadTokenExpired = 5006, - AadTokenInvalidIssuer = 5007, - AadTokenInvalidAudience = 5008, - AadTokenInvalidScope = 5009, - FailedToGetAadToken = 5010, - AadTokenMissingObjectIdentifier = 5011, - - SasTokenAuthDisabled = 5012, - - // 401 : Unauthorized Exception (CosmosDB-side errors start with 52) - AadTokenInvalidSigningKey = 5200, - AadTokenGroupExpansionError = 5201, - LocalAuthDisabled = 5202, - - // 403 Forbidden. Blocked by RBAC authorization. - RbacOperationNotSupported = 5300, - RbacUnauthorizedMetadataRequest = 5301, - RbacUnauthorizedNameBasedDataRequest = 5302, - RbacUnauthorizedRidBasedDataRequest = 5303, - RbacRidCannotBeResolved = 5304, - RbacMissingUserId = 5305, - RbacMissingAction = 5306, - - // 403 Forbidden. (CosmosDB-side errors start with 54) - RbacRequestWasNotAuthorized = 5400, - - // 403 Forbidden. (NSP related errors) - NspInboundDenied = 5307, - NspAuthorizationFailed = 5308, - NspNoResult = 5309, - NspInvalidParam = 5310, - NspInvalidEvalResult = 5311, - NspNotInitiated = 5312, - NspOperationNotSupported = 5313, - - // 200 OK. List feed throttled response. - ListResourceFeedThrottled = 5500, - - // 401 Unauthorized Exception (mutual TLS client auth failed) - MutualTlsClientAuthFailed = 5600, - - // 200 OK.GW response to GET DocService request. - LocationsModified = 5700, // Indicates locations derived from topology have been modified due to region being offlined. - - // SDK Codes (Client) - // IMPORTANT - keep these consistent with Java SDK as well - TransportGenerated410 = 20001, - TimeoutGenerated410 = 20002, - TransportGenerated503 = 20003, - Client_CPUOverload = 20004, - Client_ThreadStarvation = 20005, - Channel_Closed = 20006, - MalformedContinuationToken = 20007, - // EndToEndOperationCancelled = 20008 - cancellation by e2e retry policy - currently only applicable in Java - - //SDK Codes (Server) - // IMPORTANT - keep these consistent with Java SDK as well - Server_NameCacheIsStaleExceededRetryLimit = 21001, - Server_PartitionKeyRangeGoneExceededRetryLimit = 21002, - Server_CompletingSplitExceededRetryLimit = 21003, - Server_CompletingPartitionMigrationExceededRetryLimit = 21004, - ServerGenerated410 = 21005, - Server_GlobalStrongWriteBarrierNotMet = 21006, - Server_ReadQuorumNotMet = 21007, - ServerGenerated503 = 21008, - Server_NoValidStoreResponse = 21009, - // ServerGenerated408 = 21010 - currently only applicable in Java - - // Data Transfer Application related - MissingPartitionKeyInDataTransfer = 22001, - InvalidPartitionKeyInDataTransfer = 22002 - } - - internal static class StatusCodesExtensions - { - private static readonly Dictionary CodeNameMap = new Dictionary(); - - static StatusCodesExtensions() - { - StatusCodesExtensions.CodeNameMap[default(int)] = string.Empty; - foreach (StatusCodes code in Enum.GetValues(typeof(StatusCodes))) - { - StatusCodesExtensions.CodeNameMap[(int)code] = code.ToString(); - } - } - - public static string ToStatusCodeString(this StatusCodes code) - { - return StatusCodesExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); - } - } - - internal static class SubStatusCodesExtensions - { - private static readonly Dictionary CodeNameMap = new Dictionary(); - private static readonly int SDKGeneratedSubStatusStartingCode = 20000; - - static SubStatusCodesExtensions() - { - SubStatusCodesExtensions.CodeNameMap[default(int)] = string.Empty; - foreach (SubStatusCodes code in Enum.GetValues(typeof(SubStatusCodes))) - { - SubStatusCodesExtensions.CodeNameMap[(int)code] = code.ToString(); - } - } - - public static string ToSubStatusCodeString(this SubStatusCodes code) - { - return SubStatusCodesExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); - } - - public static bool IsSDKGeneratedSubStatus(this SubStatusCodes code) - { - return ((int)code > SubStatusCodesExtensions.SDKGeneratedSubStatusStartingCode); - } - } - -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +using System; +using System.Collections.Generic; + +namespace Microsoft.Azure.Documents +{ + internal enum StatusCodes + { + Processing = 102, + + // Success + Ok = 200, + Created = 201, + Accepted = 202, + NoContent = 204, + MultiStatus = 207, + NotModified = 304, + + // Client error + StartingErrorCode = 400, + + BadRequest = 400, + Unauthorized = 401, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + RequestTimeout = 408, + Conflict = 409, + Gone = 410, + PreconditionFailed = 412, + RequestEntityTooLarge = 413, + Locked = 423, + FailedDependency = 424, + TooManyRequests = 429, + RetryWith = 449, + + InternalServerError = 500, + BadGateway = 502, + ServiceUnavailable = 503, + + //Operation pause and cancel. These are FAKE status codes for QOS logging purpose only. + OperationPaused = 1200, + OperationCancelled = 1201, + + // Internal Status Codes for Migration errors + PartitionMigrationOperationException = 2001 + } + + internal enum SubStatusCodes + { + Unknown = 0, + TooManyRequests = 429, + + // 204 Head requests + // Difference from target lsn + MissedTargetLsn = 2001, + MissedTargetLsnOver100 = 2002, + MissedTargetLsnOver1000 = 2003, + MissedTargetLsnOver10000 = 2004, + + // Difference from target global committed lsn + MissedTargetGlobalCommittedLsn = 2011, + MissedTargetGlobalCommittedLsnOver100 = 2012, + MissedTargetGlobalCommittedLsnOver1000 = 2013, + MissedTargetGlobalCommittedLsnOver10000 = 2014, + + // 400: Bad Request Substatus + PartitionKeyMismatch = 1001, + CrossPartitionQueryNotServable = 1004, + ScriptCompileError = 0xFFFF, // From ExecuteStoredProcedure. + AnotherOfferReplaceOperationIsInProgress = 3205, + HttpListenerException = 1101, + + // 410: StatusCodeType_Gone: substatus + NameCacheIsStale = 1000, + PartitionKeyRangeGone = 1002, + CompletingSplit = 1007, + CompletingPartitionMigration = 1008, + LeaseNotFound = 1022, + ArchivalPartitionNotPresent = 1024, + + // 404: LSN in session token is higher + ReadSessionNotAvailable = 1002, + OwnerResourceNotFound = 1003, + ConfigurationNameNotFound = 1004, + ConfigurationPropertyNotFound = 1005, + CollectionCreateInProgress = 1013, + StoreNotReady = 1023, + AuthTokenNotFoundInCache = 1030, + + // 404: StatusCodeType_NotFound: substatus + PartitionMigratingCollectionDeleted = 1031, + PartitionMigrationSourcePartitionDeletedInMaster = 1034, + PartitionMigrationSharedThroughputDatabasePartitionResourceNotFoundInMaster = 1035, + PartitionMigrationPartitionResourceNotFoundInMaster = 1036, + PartitionMigrationFailedToUpdateDNS = 1037, + + // 403: Forbidden Substatus. + WriteForbidden = 3, + ProvisionLimitReached = 1005, + DatabaseAccountNotFound = 1008, + RedundantCollectionPut = 1009, + SharedThroughputDatabaseQuotaExceeded = 1010, + SharedThroughputOfferGrowNotNeeded = 1011, + PartitionKeyQuotaOverLimit = 1014, + SharedThroughputDatabaseCollectionCountExceeded = 1019, + SharedThroughputDatabaseCountExceeded = 1020, + ComputeInternalError = 1021, + ThroughputCapQuotaExceeded = 1028, + InvalidThroughputCapValue = 1029, + + // 409: Conflict exception + ConflictWithControlPlane = 1006, + DatabaseNameAlreadyExists = 3206, + ConfigurationNameAlreadyExists = 3207, + PartitionkeyHashCollisionForId = 3302, + + // 409: Partition migration Count mismatch conflict sub status codes + PartitionMigrationDocumentCountMismatchBetweenSourceAndTargetPartition = 3050, + PartitionMigrationDocumentCountMismatchBetweenTargetPartitionReplicas = 3051, + + // 503: Service Unavailable due to region being out of capacity for bindable partitions + InsufficientBindablePartitions = 1007, + ComputeFederationNotFound = 1012, + OperationPaused = 9001, + InsufficientCapacity = 9003, + + // Federation Buildout / Expansion error codes + AggregatedHealthStateError = 6001, // - Aggregated health state is Error + ApplicationHealthStateError = 6002, // - Any application is in Warning or Error state + HealthStateError = 6003, // - Any health events in Error state are found + UnhealthyEventFound = 6004, // - Any unhealthy evaluations are found (except for Warning evaluations on Nodes) + ClusterHealthEmpty = 6005, // Cluster Health States is empty + AllocationFailed = 6006, // Allocation failed for federation + OperationResultNull = 6007, // Null operation result + OperationResultUnexpected = 6008, // Null operation result + FabricNodesHealthError = 6009, // Fabric Nodes Health Error + + //412: PreCondition Failed + SplitIsDisabled = 2001, + CollectionsInPartitionGotUpdated = 2002, + CanNotAcquirePKRangesLock = 2003, + ResourceNotFound = 2004, + CanNotAcquireOfferOwnerLock = 2005, + CanNotAcquirePKRangeLock = 2007, + CanNotAcquirePartitionLock = 2008, + CanNotAcquireSnapshotOwnerLock = 2005, + StorageSplitConflictingWithNWayThroughputSplit = 2011, + MergeIsDisabled = 2012, + TombstoneRecordsNotFound = 2015, // Tombstone records were not found because they were purged. + InvalidAccountStatus = 2016, + OfferValidationFailed = 2017, + CanNotAquireMasterPartitionAccessLock = 2018, + CanNotAcquireInAccountRestoreInProgressLock = 2019, + CollectionStateChanged = 2020, + OfferScaledUpByUser = 2021, + AccountAlreadyinTargetGateway = 2100, + + //412: PreConditionFailed migration substatus codes + PartitionMigrationCancelledForPendingUserOperation = 2006, + PartitionMigrationCanNotAcquireGlobalPartitionMigrationLock = 2009, + PartitionMigrationCanNotAcquireFederationPartitionMigrationLock = 2010, + PartitionMigrationServiceTypeAndOperationTypeDoesnotMatch = 2020, + PartitionMigrationGlobalDatabaseAccountResourceNotFound = 2021, + PartitionMigrationMasterFederationForWriteRegionNotFound = 2022, + PartitionMigrationMasterFederationForCurrentRegionNotFound = 2023, + PartitionMigrationSourceAndTargetFederationSubregionIsNotSame = 2024, + PartitionMigrationFailedToCreatePartitionMigrationLocks = 2025, + PartitionMigrationFailedToResolvePartitionInformation = 2026, + PartitionMigrationIsDisableOnTheGlobalDatabaseAccount = 2028, + PartitionMigrationIsDisableOnTheRunnerAccount = 2029, + PartitionMigrationCanNotProceedForInactiveRegionalDatabaseAccount = 2030, + PartitionMigrationDidNotCompleteWaitForFullSyncInTenRetries = 2031, + PartitionMigrationCanNotProceedForDeletingRegionalDatabaseAccount = 2032, + PartitionMigrationCanNotProceedForDeletionFailedRegionalDatabaseAccount = 2033, + PartitionMigrationCanNotAcquireRegionalDatabaseAccountPartitionMigrationLock = 2034, + PartitionMigrationIsDisabledOnReadyForDecommissionFederation = 2035, + PartitionMigrationCanNotAcquirePartitionLock = 2036, + PartitionMigrationCanNotAcquirePartitionKeyRangesLock = 2037, + PartitionMigrationCanNotProceedForDeletingGlobalDatabaseAccount = 2038, + PartitionMigrationCanNotProceedForDeletionFailedGlobalDatabaseAccount = 2039, + PartitionMigrationCanNotProceedForRevokedGlobalDatabaseAccount = 2040, + PartitionMigrationMasterServiceTopologyHasWriteRegionEmpty = 2041, + PartitionMigrationWriteRegionServiceTopologyHasWriteRegionEmpty = 2042, + PartitionMigrationIsDisabledOnFinalizingDecommissionFederation = 2043, + PartitionMigrationCanNotProceedForCreationFailedRegionalDatabaseAccount = 2044, + PartitionMigrationCanNotProceedForCreationFailedGlobalDatabaseAccount = 2045, + PartitionMigrationCanNotProceedForOfflineRegionalDatabaseAccount = 2046, + PartitionMigrationCanNotProceedForInitializingOrCreatingRegionalDatabaseAccount = 2047, + PartitionMigrationCanNotProceedForInitializingOrCreatingGlobalDatabaseAccount = 2048, + PartitionMigrationCanNotProceedForRestoringOrRestoreFailedRegionalDatabaseAccount = 2049, + PartitionMigrationCanNotProceedForRestoringOrRestoreFailedGlobalDatabaseAccount = 2050, + PartitionMigrationRequestValidationFailed = 2051, + PartitionMigrationSourceFederationEntityIsNull = 2052, + PartitionMigrationCanNotAcquireTargetFederationPartitionMigrationLock = 2053, + + // 500: InternalServerError + ConfigurationNameNotEmpty = 3001, + ConfigurationOperationCancelled = 3002, + InvalidAccountConfiguration = 3003, + FederationDoesnotExistOrIsLocked = 3004, + PartitionFailoverErrorCode = 3010, + OperationManagerDequeuePumpStopped = 3021, + + // 429: Request Rate Too Large + PrepareTimeLimitExceeded = 3207, + ClientTcpChannelFull = 3208, + BWTermCountLimitExceeded = 3209, + RUBudgetExceeded = 3200, + GatewayThrottled = 3201, + StoredProcedureConcurrency = 3084, + ThottleDueToSplit = 3088, + + // Key Vault Access Client Error Code + AadClientCredentialsGrantFailure = 4000, // Indicated access to AAD failed to get a token + AadServiceUnavailable = 4001, // Aad Service is Unavailable + KeyVaultAuthenticationFailure = 4002, // Indicate the KeyVault doesn't grant permission to the AAD, or the key is disabled. + KeyVaultKeyNotFound = 4003, // Indicate the Key Vault Key is not found + KeyVaultServiceUnavailable = 4004, // Key Vault Service is Unavailable + KeyVaultWrapUnwrapFailure = 4005, // Indicate that Key Vault is unable to Wrap or Unwrap, one possible scenario is KeyVault failed to decoded the encrypted blob using the latest key because customer has rotated the key. + InvalidKeyVaultKeyURI = 4006, // Indicate the Key Vault Key URI is invalid. + InvalidInputBytes = 4007, // The input bytes are not in the format of base64. + KeyVaultInternalServerError = 4008, // Other unknown errors + KeyVaultDNSNotResolved = 4009, // Key Vault DNS name could not be resolved, mostly due to customer enter incorrect KeyVault name. + InvalidKeyVaultCertURI = 4010, // Indicate the Key Vault Cert URI is invalid. + InvalidKeyVaultKeyAndCertURI = 4011, // Indicate the Key Vault Key and Cert URI is invalid. + CustomerKeyRotated = 4012, // Indicates the rewrapped key doesn't match with existing key. + MissingRequestParameter = 4013, // Indicates that the incoming request has missing parameters. + InvalidKeyVaultSecretURI = 4014, // Indicates the Key Vault secret URI is invalid. + UndefinedDefaultIdentity = 4015, // Indicates that the account has an undefined default identity. + NspOutboundDenied = 4016, // Indicates that the account's NSP is blocking outbound requests to Key Vault. + KeyVaultNotFound = 4017, // Indicates that the Key Vault could not be found by the system. + + // Keep in sync with Microsoft.Azure.Cosmos.ServiceFramework.Security.AadAuthentication.AadSubStatusCodes + // 401 : Unauthorized Exception (User-side errors start with 50) + MissingAuthHeader = 5000, + InvalidAuthHeaderFormat = 5001, + AadAuthDisabled = 5002, + AadTokenInvalidFormat = 5003, + AadTokenInvalidSignature = 5004, + AadTokenNotYetValid = 5005, + AadTokenExpired = 5006, + AadTokenInvalidIssuer = 5007, + AadTokenInvalidAudience = 5008, + AadTokenInvalidScope = 5009, + FailedToGetAadToken = 5010, + AadTokenMissingObjectIdentifier = 5011, + + SasTokenAuthDisabled = 5012, + + // 401 : Unauthorized Exception (CosmosDB-side errors start with 52) + AadTokenInvalidSigningKey = 5200, + AadTokenGroupExpansionError = 5201, + LocalAuthDisabled = 5202, + + // 403 Forbidden. Blocked by RBAC authorization. + RbacOperationNotSupported = 5300, + RbacUnauthorizedMetadataRequest = 5301, + RbacUnauthorizedNameBasedDataRequest = 5302, + RbacUnauthorizedRidBasedDataRequest = 5303, + RbacRidCannotBeResolved = 5304, + RbacMissingUserId = 5305, + RbacMissingAction = 5306, + + // 403 Forbidden. (CosmosDB-side errors start with 54) + RbacRequestWasNotAuthorized = 5400, + + // 403 Forbidden. (NSP related errors) + NspInboundDenied = 5307, + NspAuthorizationFailed = 5308, + NspNoResult = 5309, + NspInvalidParam = 5310, + NspInvalidEvalResult = 5311, + NspNotInitiated = 5312, + NspOperationNotSupported = 5313, + + // 200 OK. List feed throttled response. + ListResourceFeedThrottled = 5500, + + // 401 Unauthorized Exception (mutual TLS client auth failed) + MutualTlsClientAuthFailed = 5600, + + // 200 OK.GW response to GET DocService request. + LocationsModified = 5700, // Indicates locations derived from topology have been modified due to region being offlined. + + // 2001: PartitionMigrationOperationError + PartitionMigrationWaitForFullSyncReceivedInternalServerErrorDuringCompleteMigrationFromBackend = 6001, + PartitionMigrationWaitForFullSyncReceivedInternalServerErrorDuringAbortMigrationFromBackend = 6002, + + // SDK Codes (Client) + // IMPORTANT - keep these consistent with Java SDK as well + TransportGenerated410 = 20001, + TimeoutGenerated410 = 20002, + TransportGenerated503 = 20003, + Client_CPUOverload = 20004, + Client_ThreadStarvation = 20005, + Channel_Closed = 20006, + MalformedContinuationToken = 20007, + // EndToEndOperationCancelled = 20008 - cancellation by e2e retry policy - currently only applicable in Java + + // SubStatusCodes for Client generated 500 -currently only applicable in java + // MISSING_PARTITION_KEY_RANGE_ID_IN_CONTEXT = 20902; + // INVALID_REGIONS_IN_SESSION_TOKEN = 20903; + // NON_PARTITIONED_RESOURCES = 20904; + // PARTITION_KEY_IS_NULL = 20905; + // UNKNOWN_AUTHORIZATION_TOKEN_KIND = 20906; + // RECREATE_REQUEST_ON_HTTP_CLIENT = 20907; + // INVALID_BACKEND_RESPONSE = 20908; + // UNKNOWN_QUORUM_RESULT = 20909; + // INVALID_RESULT = 20910; + + //SDK Codes (Server) + // IMPORTANT - keep these consistent with Java SDK as well + Server_NameCacheIsStaleExceededRetryLimit = 21001, + Server_PartitionKeyRangeGoneExceededRetryLimit = 21002, + Server_CompletingSplitExceededRetryLimit = 21003, + Server_CompletingPartitionMigrationExceededRetryLimit = 21004, + ServerGenerated410 = 21005, + Server_GlobalStrongWriteBarrierNotMet = 21006, + Server_ReadQuorumNotMet = 21007, + ServerGenerated503 = 21008, + Server_NoValidStoreResponse = 21009, + // ServerGenerated408 = 21010 - currently only applicable in Java + + // Data Transfer Application related + MissingPartitionKeyInDataTransfer = 22001, + InvalidPartitionKeyInDataTransfer = 22002 + } + + internal static class StatusCodesExtensions + { + private static readonly Dictionary CodeNameMap = new Dictionary(); + + static StatusCodesExtensions() + { + StatusCodesExtensions.CodeNameMap[default(int)] = string.Empty; + foreach (StatusCodes code in Enum.GetValues(typeof(StatusCodes))) + { + StatusCodesExtensions.CodeNameMap[(int)code] = code.ToString(); + } + } + + public static string ToStatusCodeString(this StatusCodes code) + { + return StatusCodesExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); + } + } + + internal static class SubStatusCodesExtensions + { + private static readonly Dictionary CodeNameMap = new Dictionary(); + private static readonly int SDKGeneratedSubStatusStartingCode = 20000; + + static SubStatusCodesExtensions() + { + SubStatusCodesExtensions.CodeNameMap[default(int)] = string.Empty; + foreach (SubStatusCodes code in Enum.GetValues(typeof(SubStatusCodes))) + { + SubStatusCodesExtensions.CodeNameMap[(int)code] = code.ToString(); + } + } + + public static string ToSubStatusCodeString(this SubStatusCodes code) + { + return SubStatusCodesExtensions.CodeNameMap.TryGetValue((int)code, out string value) ? value : code.ToString(); + } + + public static bool IsSDKGeneratedSubStatus(this SubStatusCodes code) + { + return ((int)code > SubStatusCodesExtensions.SDKGeneratedSubStatusStartingCode); + } + } + +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreClient.cs b/Microsoft.Azure.Cosmos/src/direct/StoreClient.cs index 6610ebe338..65ec7963fc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreClient.cs @@ -1,320 +1,320 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.Net; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Rntbd; - using Microsoft.Azure.Documents.Client; - using Microsoft.Azure.Documents.Collections; - using Newtonsoft.Json; - - /// - /// Instantiated to issue direct connectivity requests to the backend on: - /// - Gateway (for gateway mode clients) - /// - Client (for direct mode clients) - /// StoreClient uses the ReplicatedResourceClient to make requests to the backend. - /// - internal sealed class StoreClient : IStoreClient - { - private readonly ISessionContainer sessionContainer; - private readonly ReplicatedResourceClient replicatedResourceClient; - // TODO(ovplaton): Remove transportClient from this class after removing - // AddDisableRntbdChannelCallback. The field isn't used for anything else. - private readonly TransportClient transportClient; - private readonly IServiceConfigurationReader serviceConfigurationReader; - private readonly bool enableRequestDiagnostics; - - public StoreClient( - IAddressResolver addressResolver, - ISessionContainer sessionContainer, - IServiceConfigurationReader serviceConfigurationReader, - IAuthorizationTokenProvider userTokenProvider, - Protocol protocol, - TransportClient transportClient, - bool enableRequestDiagnostics = false, - bool enableReadRequestsFallback = false, - bool useMultipleWriteLocations = false, - bool detectClientConnectivityIssues = false, - bool disableRetryWithRetryPolicy = false, - bool enableReplicaValidation = false, - RetryWithConfiguration retryWithConfiguration = null) - { - this.transportClient = transportClient; - this.serviceConfigurationReader = serviceConfigurationReader; - this.sessionContainer = sessionContainer; - this.enableRequestDiagnostics = enableRequestDiagnostics; - - // Note that, in future, the SetOpenConnectionsHandler() will be moved into IAddressResolver interface - // thus the if-else condition would not be necessary once the methods are moved. - if (addressResolver is IAddressResolverExtension addressResolverExtension) - { - addressResolverExtension.SetOpenConnectionsHandler( - openConnectionHandler: new RntbdOpenConnectionHandler( - transportClient: transportClient)); - } - - this.replicatedResourceClient = new ReplicatedResourceClient( - addressResolver: addressResolver, - sessionContainer: sessionContainer, - protocol: protocol, - transportClient: this.transportClient, - serviceConfigReader: this.serviceConfigurationReader, - authorizationTokenProvider: userTokenProvider, - enableReadRequestsFallback: enableReadRequestsFallback, - useMultipleWriteLocations: useMultipleWriteLocations, - detectClientConnectivityIssues: detectClientConnectivityIssues, - disableRetryWithRetryPolicy: disableRetryWithRetryPolicy, - retryWithConfiguration: retryWithConfiguration, - enableReplicaValidation: enableReplicaValidation); - } - - internal JsonSerializerSettings SerializerSettings { get; set; } - - #region Test hooks - public string LastReadAddress - { - get - { - return this.replicatedResourceClient.LastReadAddress; - } - set - { - this.replicatedResourceClient.LastReadAddress = value; - } - } - - public string LastWriteAddress - { - get - { - return this.replicatedResourceClient.LastWriteAddress; - } - } - - public bool ForceAddressRefresh - { - get - { - return this.replicatedResourceClient.ForceAddressRefresh; - } - set - { - this.replicatedResourceClient.ForceAddressRefresh = value; - } - } - #endregion - - /// > - public Task ProcessMessageAsync(DocumentServiceRequest request, IRetryPolicy retryPolicy = null, CancellationToken cancellationToken = default(CancellationToken)) - { - return this.ProcessMessageAsync(request, cancellationToken, retryPolicy); - } - - // Decides what to execute based on the ResourceOperation property of the DocumentServiceRequest argument - public async Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken, IRetryPolicy retryPolicy = null) - { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } - - await request.EnsureBufferedBodyAsync(); - - StoreResponse storeResponse = null; - try - { - storeResponse = retryPolicy != null - ? await BackoffRetryUtility.ExecuteAsync(() => this.replicatedResourceClient.InvokeAsync(request, cancellationToken), retryPolicy, cancellationToken) - : await this.replicatedResourceClient.InvokeAsync(request, cancellationToken); - } - catch (DocumentClientException exception) - { - if(request.RequestContext.ClientRequestStatistics != null) - { - exception.RequestStatistics = request.RequestContext.ClientRequestStatistics; - } - - this.UpdateResponseHeader(request, exception.Headers); - - if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) && - (exception.StatusCode == HttpStatusCode.PreconditionFailed || exception.StatusCode == HttpStatusCode.Conflict - || (exception.StatusCode == HttpStatusCode.NotFound && exception.GetSubStatus() != SubStatusCodes.ReadSessionNotAvailable))) - { - this.CaptureSessionToken(exception.StatusCode, exception.GetSubStatus(), request, exception.Headers); - } - - throw; - } - - return this.CompleteResponse(storeResponse, request); - } - - /// > - public async Task OpenConnectionsToAllReplicasAsync( - string databaseName, - string containerLinkUri, - CancellationToken cancellationToken = default) - { - await this.replicatedResourceClient.OpenConnectionsToAllReplicasAsync( - databaseName, - containerLinkUri, - cancellationToken); - } - - #region Response/Headers helper - private DocumentServiceResponse CompleteResponse( - StoreResponse storeResponse, - DocumentServiceRequest request) - { - INameValueCollection headersFromStoreResponse = StoreClient.GetHeadersFromStoreResponse(storeResponse); - this.UpdateResponseHeader(request, headersFromStoreResponse); - this.CaptureSessionToken((HttpStatusCode)storeResponse.Status, storeResponse.SubStatusCode, request, headersFromStoreResponse); - - DocumentServiceResponse response = new DocumentServiceResponse( - storeResponse.ResponseBody, - headersFromStoreResponse, - (HttpStatusCode)storeResponse.Status, - this.enableRequestDiagnostics ? request.RequestContext.ClientRequestStatistics : null, - request.SerializerSettings ?? this.SerializerSettings); - - return response; - } - - private long GetLSN(INameValueCollection headers) - { - string value = headers[WFConstants.BackendHeaders.LSN]; - - if (!string.IsNullOrEmpty(value)) - { - if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long result)) - { - return result; - } - } - - return -1; - } - - private void UpdateResponseHeader(DocumentServiceRequest request, INameValueCollection headers) - { - long storeLSN = this.GetLSN(headers); - if (storeLSN == -1) - { - return; - } - - string version = request.Headers[HttpConstants.HttpHeaders.Version]; - version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; - - if (string.Compare(version, HttpConstants.Versions.v2015_12_16, StringComparison.Ordinal) < 0) - { - headers[HttpConstants.HttpHeaders.SessionToken] = string.Format(CultureInfo.InvariantCulture, "{0}", storeLSN); - } - else - { - string partitionKeyRangeId = headers[WFConstants.BackendHeaders.PartitionKeyRangeId]; - - if (string.IsNullOrEmpty(partitionKeyRangeId)) - { - string inputSession = request.Headers[HttpConstants.HttpHeaders.SessionToken]; - if (!string.IsNullOrEmpty(inputSession) && inputSession.IndexOf(":", StringComparison.Ordinal) >= 1) - { - partitionKeyRangeId = inputSession.Substring(0, inputSession.IndexOf(":", StringComparison.Ordinal)); - } - else - { - partitionKeyRangeId = "0"; - } - } - - ISessionToken sessionToken = null; - string sessionTokenResponseHeader = headers[HttpConstants.HttpHeaders.SessionToken]; - if (!string.IsNullOrEmpty(sessionTokenResponseHeader)) - { - sessionToken = SessionTokenHelper.Parse(sessionTokenResponseHeader); - } - else if (!VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2018_06_18)) - { - sessionToken = new SimpleSessionToken(storeLSN); - } - - if (sessionToken != null) - { - headers[HttpConstants.HttpHeaders.SessionToken] = string.Format( - CultureInfo.InvariantCulture, - "{0}:{1}", - partitionKeyRangeId, - sessionToken.ConvertToString()); - } - } - } - - private void CaptureSessionToken(HttpStatusCode? statusCode, SubStatusCodes subStatusCode, DocumentServiceRequest request, INameValueCollection headers) - { - // Exceptionless can try to capture session token from CompleteResponse - if (request.IsValidStatusCodeForExceptionlessRetry((int) statusCode, subStatusCode)) - { - // Not capturing on master resources - if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) - { - return; - } - - // Only capturing on 409, 412, 404 && !1002 - if (statusCode != HttpStatusCode.PreconditionFailed - && statusCode != HttpStatusCode.Conflict - && (statusCode != HttpStatusCode.NotFound || subStatusCode == SubStatusCodes.ReadSessionNotAvailable)) - { - return; - } - } - - if (request.ResourceType == ResourceType.Collection && request.OperationType == OperationType.Delete) - { - string resourceId; - if (request.IsNameBased) - { - resourceId = headers[HttpConstants.HttpHeaders.OwnerId]; - } - else - { - resourceId = request.ResourceId; - } - this.sessionContainer.ClearTokenByResourceId(resourceId); - } - else - { - this.sessionContainer.SetSessionToken(request, headers); - } - } - - private static INameValueCollection GetHeadersFromStoreResponse(StoreResponse storeResponse) - { - return storeResponse.Headers; - } - - #endregion - - #region RNTBD Transition - - // Helper for the transition from RNTBD v1 to v2. Delete it after - // deleting the RNTBD v1 client. - internal void AddDisableRntbdChannelCallback(Action action) - { - Rntbd.TransportClient rntbdTransportClient = - this.transportClient as Rntbd.TransportClient; - if (rntbdTransportClient == null) - { - return; - } - rntbdTransportClient.OnDisableRntbdChannel += action; - } - - #endregion - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Rntbd; + using Microsoft.Azure.Documents.Client; + using Microsoft.Azure.Documents.Collections; + using Newtonsoft.Json; + + /// + /// Instantiated to issue direct connectivity requests to the backend on: + /// - Gateway (for gateway mode clients) + /// - Client (for direct mode clients) + /// StoreClient uses the ReplicatedResourceClient to make requests to the backend. + /// + internal sealed class StoreClient : IStoreClient + { + private readonly ISessionContainer sessionContainer; + private readonly ReplicatedResourceClient replicatedResourceClient; + // TODO(ovplaton): Remove transportClient from this class after removing + // AddDisableRntbdChannelCallback. The field isn't used for anything else. + private readonly TransportClient transportClient; + private readonly IServiceConfigurationReader serviceConfigurationReader; + private readonly bool enableRequestDiagnostics; + + public StoreClient( + IAddressResolver addressResolver, + ISessionContainer sessionContainer, + IServiceConfigurationReader serviceConfigurationReader, + IAuthorizationTokenProvider userTokenProvider, + Protocol protocol, + TransportClient transportClient, + bool enableRequestDiagnostics = false, + bool enableReadRequestsFallback = false, + bool useMultipleWriteLocations = false, + bool detectClientConnectivityIssues = false, + bool disableRetryWithRetryPolicy = false, + bool enableReplicaValidation = false, + RetryWithConfiguration retryWithConfiguration = null) + { + this.transportClient = transportClient; + this.serviceConfigurationReader = serviceConfigurationReader; + this.sessionContainer = sessionContainer; + this.enableRequestDiagnostics = enableRequestDiagnostics; + + // Note that, in future, the SetOpenConnectionsHandler() will be moved into IAddressResolver interface + // thus the if-else condition would not be necessary once the methods are moved. + if (addressResolver is IAddressResolverExtension addressResolverExtension) + { + addressResolverExtension.SetOpenConnectionsHandler( + openConnectionHandler: new RntbdOpenConnectionHandler( + transportClient: transportClient)); + } + + this.replicatedResourceClient = new ReplicatedResourceClient( + addressResolver: addressResolver, + sessionContainer: sessionContainer, + protocol: protocol, + transportClient: this.transportClient, + serviceConfigReader: this.serviceConfigurationReader, + authorizationTokenProvider: userTokenProvider, + enableReadRequestsFallback: enableReadRequestsFallback, + useMultipleWriteLocations: useMultipleWriteLocations, + detectClientConnectivityIssues: detectClientConnectivityIssues, + disableRetryWithRetryPolicy: disableRetryWithRetryPolicy, + retryWithConfiguration: retryWithConfiguration, + enableReplicaValidation: enableReplicaValidation); + } + + internal JsonSerializerSettings SerializerSettings { get; set; } + + #region Test hooks + public string LastReadAddress + { + get + { + return this.replicatedResourceClient.LastReadAddress; + } + set + { + this.replicatedResourceClient.LastReadAddress = value; + } + } + + public string LastWriteAddress + { + get + { + return this.replicatedResourceClient.LastWriteAddress; + } + } + + public bool ForceAddressRefresh + { + get + { + return this.replicatedResourceClient.ForceAddressRefresh; + } + set + { + this.replicatedResourceClient.ForceAddressRefresh = value; + } + } + #endregion + + /// > + public Task ProcessMessageAsync(DocumentServiceRequest request, IRetryPolicy retryPolicy = null, CancellationToken cancellationToken = default(CancellationToken)) + { + return this.ProcessMessageAsync(request, cancellationToken, retryPolicy); + } + + // Decides what to execute based on the ResourceOperation property of the DocumentServiceRequest argument + public async Task ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken, IRetryPolicy retryPolicy = null) + { + if (request == null) + { + throw new ArgumentNullException(nameof(request)); + } + + await request.EnsureBufferedBodyAsync(); + + StoreResponse storeResponse = null; + try + { + storeResponse = retryPolicy != null + ? await BackoffRetryUtility.ExecuteAsync(() => this.replicatedResourceClient.InvokeAsync(request, cancellationToken), retryPolicy, cancellationToken) + : await this.replicatedResourceClient.InvokeAsync(request, cancellationToken); + } + catch (DocumentClientException exception) + { + if(request.RequestContext.ClientRequestStatistics != null) + { + exception.RequestStatistics = request.RequestContext.ClientRequestStatistics; + } + + this.UpdateResponseHeader(request, exception.Headers); + + if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) && + (exception.StatusCode == HttpStatusCode.PreconditionFailed || exception.StatusCode == HttpStatusCode.Conflict + || (exception.StatusCode == HttpStatusCode.NotFound && exception.GetSubStatus() != SubStatusCodes.ReadSessionNotAvailable))) + { + this.CaptureSessionToken(exception.StatusCode, exception.GetSubStatus(), request, exception.Headers); + } + + throw; + } + + return this.CompleteResponse(storeResponse, request); + } + + /// > + public async Task OpenConnectionsToAllReplicasAsync( + string databaseName, + string containerLinkUri, + CancellationToken cancellationToken = default) + { + await this.replicatedResourceClient.OpenConnectionsToAllReplicasAsync( + databaseName, + containerLinkUri, + cancellationToken); + } + + #region Response/Headers helper + private DocumentServiceResponse CompleteResponse( + StoreResponse storeResponse, + DocumentServiceRequest request) + { + INameValueCollection headersFromStoreResponse = StoreClient.GetHeadersFromStoreResponse(storeResponse); + this.UpdateResponseHeader(request, headersFromStoreResponse); + this.CaptureSessionToken((HttpStatusCode)storeResponse.Status, storeResponse.SubStatusCode, request, headersFromStoreResponse); + + DocumentServiceResponse response = new DocumentServiceResponse( + storeResponse.ResponseBody, + headersFromStoreResponse, + (HttpStatusCode)storeResponse.Status, + this.enableRequestDiagnostics ? request.RequestContext.ClientRequestStatistics : null, + request.SerializerSettings ?? this.SerializerSettings); + + return response; + } + + private long GetLSN(INameValueCollection headers) + { + string value = headers[WFConstants.BackendHeaders.LSN]; + + if (!string.IsNullOrEmpty(value)) + { + if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out long result)) + { + return result; + } + } + + return -1; + } + + private void UpdateResponseHeader(DocumentServiceRequest request, INameValueCollection headers) + { + long storeLSN = this.GetLSN(headers); + if (storeLSN == -1) + { + return; + } + + string version = request.Headers[HttpConstants.HttpHeaders.Version]; + version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version; + + if (string.Compare(version, HttpConstants.Versions.v2015_12_16, StringComparison.Ordinal) < 0) + { + headers[HttpConstants.HttpHeaders.SessionToken] = string.Format(CultureInfo.InvariantCulture, "{0}", storeLSN); + } + else + { + string partitionKeyRangeId = headers[WFConstants.BackendHeaders.PartitionKeyRangeId]; + + if (string.IsNullOrEmpty(partitionKeyRangeId)) + { + string inputSession = request.Headers[HttpConstants.HttpHeaders.SessionToken]; + if (!string.IsNullOrEmpty(inputSession) && inputSession.IndexOf(":", StringComparison.Ordinal) >= 1) + { + partitionKeyRangeId = inputSession.Substring(0, inputSession.IndexOf(":", StringComparison.Ordinal)); + } + else + { + partitionKeyRangeId = "0"; + } + } + + ISessionToken sessionToken = null; + string sessionTokenResponseHeader = headers[HttpConstants.HttpHeaders.SessionToken]; + if (!string.IsNullOrEmpty(sessionTokenResponseHeader)) + { + sessionToken = SessionTokenHelper.Parse(sessionTokenResponseHeader); + } + else if (!VersionUtility.IsLaterThan(version, HttpConstants.VersionDates.v2018_06_18)) + { + sessionToken = new SimpleSessionToken(storeLSN); + } + + if (sessionToken != null) + { + headers[HttpConstants.HttpHeaders.SessionToken] = string.Format( + CultureInfo.InvariantCulture, + "{0}:{1}", + partitionKeyRangeId, + sessionToken.ConvertToString()); + } + } + } + + private void CaptureSessionToken(HttpStatusCode? statusCode, SubStatusCodes subStatusCode, DocumentServiceRequest request, INameValueCollection headers) + { + // Exceptionless can try to capture session token from CompleteResponse + if (request.IsValidStatusCodeForExceptionlessRetry((int) statusCode, subStatusCode)) + { + // Not capturing on master resources + if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) + { + return; + } + + // Only capturing on 409, 412, 404 && !1002 + if (statusCode != HttpStatusCode.PreconditionFailed + && statusCode != HttpStatusCode.Conflict + && (statusCode != HttpStatusCode.NotFound || subStatusCode == SubStatusCodes.ReadSessionNotAvailable)) + { + return; + } + } + + if (request.ResourceType == ResourceType.Collection && request.OperationType == OperationType.Delete) + { + string resourceId; + if (request.IsNameBased) + { + resourceId = headers[HttpConstants.HttpHeaders.OwnerId]; + } + else + { + resourceId = request.ResourceId; + } + this.sessionContainer.ClearTokenByResourceId(resourceId); + } + else + { + this.sessionContainer.SetSessionToken(request, headers); + } + } + + private static INameValueCollection GetHeadersFromStoreResponse(StoreResponse storeResponse) + { + return storeResponse.Headers; + } + + #endregion + + #region RNTBD Transition + + // Helper for the transition from RNTBD v1 to v2. Delete it after + // deleting the RNTBD v1 client. + internal void AddDisableRntbdChannelCallback(Action action) + { + Rntbd.TransportClient rntbdTransportClient = + this.transportClient as Rntbd.TransportClient; + if (rntbdTransportClient == null) + { + return; + } + rntbdTransportClient.OnDisableRntbdChannel += action; + } + + #endregion + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreClientFactory.cs b/Microsoft.Azure.Cosmos/src/direct/StoreClientFactory.cs index 7764a9d0f9..3dbe550fa8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreClientFactory.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreClientFactory.cs @@ -1,467 +1,467 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Net.Security; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Client; - using Microsoft.Azure.Documents.FaultInjection; - using Microsoft.Azure.Documents.Telemetry; - - internal sealed class StoreClientFactory : IStoreClientFactory - { - private bool isDisposed = false; - private readonly Protocol protocol; - private readonly RetryWithConfiguration retryWithConfiguration; - private readonly bool disableRetryWithRetryPolicy; - private TransportClient transportClient; - private TransportClient fallbackTransportClient; - private ConnectionStateListener connectionStateListener = null; - - public StoreClientFactory( - Protocol protocol, - int requestTimeoutInSeconds, - int maxConcurrentConnectionOpenRequests, - UserAgentContainer userAgent = null, // optional for both HTTPS and RNTBD - ICommunicationEventSource eventSource = null, // required for HTTPS, not used for RNTBD - string overrideHostNameInCertificate = null, // optional for RNTBD, not used for HTTPS - int openTimeoutInSeconds = 0, // optional for RNTBD, not used for HTTPS - int idleTimeoutInSeconds = -1,// optional for both HTTPS and RNTBD - int timerPoolGranularityInSeconds = 0, // optional for RNTBD, not used for HTTPS - int maxRntbdChannels = ushort.MaxValue, // RNTBD - int rntbdPartitionCount = 1, // RNTBD - int maxRequestsPerRntbdChannel = 30, // RNTBD - PortReuseMode rntbdPortReuseMode = PortReuseMode.ReuseUnicastPort, // RNTBD - int rntbdPortPoolReuseThreshold = 256, // RNTBD - int rntbdPortPoolBindAttempts = 5, // RNTBD - int receiveHangDetectionTimeSeconds = 65, // RNTBD - int sendHangDetectionTimeSeconds = 10, // RNTBD - bool disableRetryWithRetryPolicy = false, - RetryWithConfiguration retryWithConfiguration = null, - RntbdConstants.CallerId callerId = RntbdConstants.CallerId.Anonymous, // replicatedResourceClient - bool enableTcpConnectionEndpointRediscovery = false, - IAddressResolver addressResolver = null, // globalAddressResolver - TimeSpan localRegionOpenTimeout = default, - bool enableChannelMultiplexing = false, - int rntbdMaxConcurrentOpeningConnectionCount = ushort.MaxValue, // Optional for Rntbd - MemoryStreamPool memoryStreamPool = null, - RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, - Func> dnsResolutionFunction = null, // optional override - DistributedTracingOptions distributedTracingOptions = null, // Distributed Tracing Configuration - IChaosInterceptor chaosInterceptor = null) // Fault Injection - { - // <=0 means idle timeout is disabled. - // valid value: >= 10 minutes - if (idleTimeoutInSeconds > 0 && idleTimeoutInSeconds < 600) - { - throw new ArgumentOutOfRangeException(nameof(idleTimeoutInSeconds)); - } - - if (protocol == Protocol.Https) - { - if (eventSource == null) - { - throw new ArgumentOutOfRangeException(nameof(eventSource)); - } - - this.transportClient = new HttpTransportClient(requestTimeoutInSeconds, eventSource, userAgent, idleTimeoutInSeconds); - } - else if (protocol == Protocol.Tcp) - { - if (maxRntbdChannels <= 0) - { - throw new ArgumentOutOfRangeException(nameof(maxRntbdChannels)); - } - - if ((rntbdPartitionCount < 1) || (rntbdPartitionCount > 8)) - { - throw new ArgumentOutOfRangeException(nameof(rntbdPartitionCount)); - } - - if (maxRequestsPerRntbdChannel <= 0) - { - throw new ArgumentOutOfRangeException(nameof(maxRequestsPerRntbdChannel)); - } - - if (maxRntbdChannels > ushort.MaxValue) - { - DefaultTrace.TraceWarning( - "The value of {0} is unreasonably large. Received: {1}. " + - "Use {2} to represent \"effectively infinite\".", - nameof(maxRntbdChannels), - maxRntbdChannels, - ushort.MaxValue); - } - - const int minRecommendedMaxRequestsPerChannel = 6; - const int maxRecommendedMaxRequestsPerChannel = 256; - if (maxRequestsPerRntbdChannel < minRecommendedMaxRequestsPerChannel) - { - DefaultTrace.TraceWarning( - "The value of {0} is unreasonably small. Received: {1}. " + - "Small values of {0} can cause a large number of RNTBD " + - "channels to be opened to the same back-end. Reasonable " + - "values are between {2} and {3}", - nameof(maxRequestsPerRntbdChannel), - maxRequestsPerRntbdChannel, - minRecommendedMaxRequestsPerChannel, - maxRecommendedMaxRequestsPerChannel); - } - - if (maxRequestsPerRntbdChannel > maxRecommendedMaxRequestsPerChannel) - { - DefaultTrace.TraceWarning( - "The value of {0} is unreasonably large. Received: {1}. " + - "Large values of {0} can cause significant head-of-line " + - "blocking over RNTBD channels. Reasonable values are between {2} and {3}", - nameof(maxRequestsPerRntbdChannel), - maxRequestsPerRntbdChannel, - minRecommendedMaxRequestsPerChannel, - maxRecommendedMaxRequestsPerChannel); - } - - // Not related to maxRecommendedMaxRequestsPerChannel. - const int minRequiredSimultaneousRequests = 512; - if (checked(maxRntbdChannels * maxRequestsPerRntbdChannel) < - minRequiredSimultaneousRequests) - { - DefaultTrace.TraceWarning( - "The number of simultaneous requests allowed per backend " + - "is unreasonably small. Received {0} = {1}, {2} = {3}. " + - "Reasonable values are at least {4}", - nameof(maxRntbdChannels), maxRntbdChannels, - nameof(maxRequestsPerRntbdChannel), maxRequestsPerRntbdChannel, - minRequiredSimultaneousRequests); - } - - StoreClientFactory.ValidatePortPoolReuseThreshold(ref rntbdPortPoolReuseThreshold); - StoreClientFactory.ValidatePortPoolBindAttempts(ref rntbdPortPoolBindAttempts); - if (rntbdPortPoolBindAttempts > rntbdPortPoolReuseThreshold) - { - DefaultTrace.TraceWarning( - "Raising the value of {0} from {1} to {2} to match the value of {3}", - nameof(rntbdPortPoolReuseThreshold), rntbdPortPoolReuseThreshold, - rntbdPortPoolBindAttempts + 1, nameof(rntbdPortPoolBindAttempts)); - rntbdPortPoolReuseThreshold = rntbdPortPoolBindAttempts; - } - - const int minReceiveHangDetectionTimeSeconds = 65; - const int maxReceiveHangDetectionTimeSeconds = 180; - if (receiveHangDetectionTimeSeconds < minReceiveHangDetectionTimeSeconds) - { - DefaultTrace.TraceWarning( - "The value of {0} is too small. Received {1}. Adjusting to {2}", - nameof(receiveHangDetectionTimeSeconds), - receiveHangDetectionTimeSeconds, - minReceiveHangDetectionTimeSeconds); - receiveHangDetectionTimeSeconds = minReceiveHangDetectionTimeSeconds; - } - - if (receiveHangDetectionTimeSeconds > maxReceiveHangDetectionTimeSeconds) - { - DefaultTrace.TraceWarning( - "The value of {0} is too large. Received {1}. Adjusting to {2}", - nameof(receiveHangDetectionTimeSeconds), - receiveHangDetectionTimeSeconds, - maxReceiveHangDetectionTimeSeconds); - receiveHangDetectionTimeSeconds = maxReceiveHangDetectionTimeSeconds; - } - - const int minSendHangDetectionTimeSeconds = 2; - const int maxSendHangDetectionTimeSeconds = 60; - if (sendHangDetectionTimeSeconds < minSendHangDetectionTimeSeconds) - { - DefaultTrace.TraceWarning( - "The value of {0} is too small. Received {1}. Adjusting to {2}", - nameof(sendHangDetectionTimeSeconds), - sendHangDetectionTimeSeconds, - minSendHangDetectionTimeSeconds); - sendHangDetectionTimeSeconds = minSendHangDetectionTimeSeconds; - } - - if (sendHangDetectionTimeSeconds > maxSendHangDetectionTimeSeconds) - { - DefaultTrace.TraceWarning( - "The value of {0} is too large. Received {1}. Adjusting to {2}", - nameof(sendHangDetectionTimeSeconds), - sendHangDetectionTimeSeconds, - maxSendHangDetectionTimeSeconds); - sendHangDetectionTimeSeconds = maxSendHangDetectionTimeSeconds; - } - - if (enableTcpConnectionEndpointRediscovery && addressResolver != null) - { - this.connectionStateListener = new ConnectionStateListener(addressResolver); - } - - StoreClientFactory.ValidateRntbdMaxConcurrentOpeningConnectionCount(ref rntbdMaxConcurrentOpeningConnectionCount); - - this.transportClient = new Rntbd.TransportClient( - new Rntbd.TransportClient.Options(TimeSpan.FromSeconds(requestTimeoutInSeconds)) - { - MaxChannels = maxRntbdChannels, - PartitionCount = rntbdPartitionCount, - MaxRequestsPerChannel = maxRequestsPerRntbdChannel, - PortReuseMode = rntbdPortReuseMode, - PortPoolReuseThreshold = rntbdPortPoolReuseThreshold, - PortPoolBindAttempts = rntbdPortPoolBindAttempts, - ReceiveHangDetectionTime = TimeSpan.FromSeconds(receiveHangDetectionTimeSeconds), - SendHangDetectionTime = TimeSpan.FromSeconds(sendHangDetectionTimeSeconds), - UserAgent = userAgent, - CertificateHostNameOverride = overrideHostNameInCertificate, - OpenTimeout = TimeSpan.FromSeconds(openTimeoutInSeconds), - LocalRegionOpenTimeout = localRegionOpenTimeout, - TimerPoolResolution = TimeSpan.FromSeconds(timerPoolGranularityInSeconds), - IdleTimeout = TimeSpan.FromSeconds(idleTimeoutInSeconds), - CallerId = callerId, - ConnectionStateListener = this.connectionStateListener, - EnableChannelMultiplexing = enableChannelMultiplexing, - MaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionCount, - MemoryStreamPool = memoryStreamPool, - RemoteCertificateValidationCallback = remoteCertificateValidationCallback, - DnsResolutionFunction = dnsResolutionFunction, - DistributedTracingOptions = distributedTracingOptions - }, - chaosInterceptor); - - this.fallbackTransportClient = new Rntbd.TransportClient( - new Rntbd.TransportClient.Options(TimeSpan.FromSeconds(requestTimeoutInSeconds)) - { - MaxChannels = maxRntbdChannels, - PartitionCount = rntbdPartitionCount, - MaxRequestsPerChannel = 1, // Legacy RNTBD is 1 request per channel. - PortReuseMode = rntbdPortReuseMode, - PortPoolReuseThreshold = rntbdPortPoolReuseThreshold, - PortPoolBindAttempts = rntbdPortPoolBindAttempts, - ReceiveHangDetectionTime = TimeSpan.FromSeconds(receiveHangDetectionTimeSeconds), - SendHangDetectionTime = TimeSpan.FromSeconds(sendHangDetectionTimeSeconds), - UserAgent = userAgent, - CertificateHostNameOverride = overrideHostNameInCertificate, - OpenTimeout = TimeSpan.FromSeconds(openTimeoutInSeconds), - LocalRegionOpenTimeout = localRegionOpenTimeout, - TimerPoolResolution = TimeSpan.FromSeconds(timerPoolGranularityInSeconds), - IdleTimeout = TimeSpan.FromSeconds(idleTimeoutInSeconds), - CallerId = callerId, - ConnectionStateListener = this.connectionStateListener, - EnableChannelMultiplexing = enableChannelMultiplexing, - MaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionCount, - MemoryStreamPool = memoryStreamPool, - RemoteCertificateValidationCallback = remoteCertificateValidationCallback, - DnsResolutionFunction = dnsResolutionFunction, - DistributedTracingOptions = distributedTracingOptions - }, - chaosInterceptor); - } - else - { - throw new ArgumentOutOfRangeException(nameof(protocol), protocol, "Invalid protocol value"); - } - - this.protocol = protocol; - this.retryWithConfiguration = retryWithConfiguration; - this.disableRetryWithRetryPolicy = disableRetryWithRetryPolicy; - } - - private StoreClientFactory( - Protocol protocol, - RetryWithConfiguration retryWithConfiguration, - TransportClient transportClient, - TransportClient fallbackTransportClient, - ConnectionStateListener connectionStateListener) - { - this.protocol = protocol; - this.retryWithConfiguration = retryWithConfiguration; - this.transportClient = transportClient; - this.fallbackTransportClient = fallbackTransportClient; - this.connectionStateListener = connectionStateListener; - } - - internal StoreClientFactory Clone() - { - return new StoreClientFactory( - this.protocol, - this.retryWithConfiguration, - this.transportClient, - this.fallbackTransportClient, - this.connectionStateListener); - } - - // Interceptor factory (used in V3 SDK by compute to intercept transport interactions for chargeback) - internal void WithTransportInterceptor(Func transportClientHandlerFactory) - { - if (transportClientHandlerFactory == null) - { - throw new ArgumentNullException(nameof(transportClientHandlerFactory)); - } - - this.transportClient = transportClientHandlerFactory(this.transportClient); - this.fallbackTransportClient = transportClientHandlerFactory(this.fallbackTransportClient); - } - - public StoreClient CreateStoreClient( - IAddressResolver addressResolver, - ISessionContainer sessionContainer, - IServiceConfigurationReader serviceConfigurationReader, - IAuthorizationTokenProvider authorizationTokenProvider, - bool enableRequestDiagnostics = false, - bool enableReadRequestsFallback = false, - bool useFallbackClient = true, - bool useMultipleWriteLocations = false, - bool detectClientConnectivityIssues = false, - bool enableReplicaValidation = false) - { - this.ThrowIfDisposed(); - if (useFallbackClient && this.fallbackTransportClient != null) - { - DefaultTrace.TraceInformation("Using fallback TransportClient"); - return new StoreClient( - addressResolver: addressResolver, - sessionContainer: sessionContainer, - serviceConfigurationReader: serviceConfigurationReader, - userTokenProvider: authorizationTokenProvider, - protocol: this.protocol, - transportClient: this.fallbackTransportClient, - enableRequestDiagnostics: enableRequestDiagnostics, - enableReadRequestsFallback: enableReadRequestsFallback, - useMultipleWriteLocations: useMultipleWriteLocations, - detectClientConnectivityIssues: detectClientConnectivityIssues, - disableRetryWithRetryPolicy: this.disableRetryWithRetryPolicy, - retryWithConfiguration: this.retryWithConfiguration, - enableReplicaValidation: enableReplicaValidation); - } - - return new StoreClient( - addressResolver: addressResolver, - sessionContainer: sessionContainer, - serviceConfigurationReader: serviceConfigurationReader, - userTokenProvider: authorizationTokenProvider, - protocol: this.protocol, - transportClient: this.transportClient, - enableRequestDiagnostics: enableRequestDiagnostics, - enableReadRequestsFallback: enableReadRequestsFallback, - useMultipleWriteLocations: useMultipleWriteLocations, - detectClientConnectivityIssues: detectClientConnectivityIssues, - disableRetryWithRetryPolicy: this.disableRetryWithRetryPolicy, - retryWithConfiguration: this.retryWithConfiguration, - enableReplicaValidation: enableReplicaValidation); - } - - #region IDisposable - public void Dispose() - { - if (this.isDisposed) - { - return; - } - - if (this.transportClient != null) - { - this.transportClient.Dispose(); - this.transportClient = null; - } - - if (this.fallbackTransportClient != null) - { - this.fallbackTransportClient.Dispose(); - this.fallbackTransportClient = null; - } - - this.isDisposed = true; - } - - private void ThrowIfDisposed() - { - if (this.isDisposed) - { - throw new ObjectDisposedException("StoreClientFactory"); - } - } - #endregion - - private static void ValidatePortPoolReuseThreshold(ref int rntbdPortPoolReuseThreshold) - { - const int minRntbdPortPoolReuseThreshold = 32; - const int maxRntbdPortPoolReuseThreshold = 2048; - Debug.Assert(minRntbdPortPoolReuseThreshold < maxRntbdPortPoolReuseThreshold); - if (rntbdPortPoolReuseThreshold < minRntbdPortPoolReuseThreshold) - { - DefaultTrace.TraceWarning( - "The value of {0} is too small. Received {1}. Adjusting to {2}", - nameof(rntbdPortPoolReuseThreshold), - rntbdPortPoolReuseThreshold, minRntbdPortPoolReuseThreshold); - rntbdPortPoolReuseThreshold = minRntbdPortPoolReuseThreshold; - } - else if (rntbdPortPoolReuseThreshold > maxRntbdPortPoolReuseThreshold) - { - DefaultTrace.TraceWarning( - "The value of {0} is too large. Received {1}. Adjusting to {2}", - nameof(rntbdPortPoolReuseThreshold), - rntbdPortPoolReuseThreshold, maxRntbdPortPoolReuseThreshold); - rntbdPortPoolReuseThreshold = maxRntbdPortPoolReuseThreshold; - } - } - - private static void ValidatePortPoolBindAttempts(ref int rntbdPortPoolBindAttempts) - { - const int minRntbdPortPoolBindAttempts = 3; - const int maxRntbdPortPoolBindAttempts = 32; - Debug.Assert(minRntbdPortPoolBindAttempts < maxRntbdPortPoolBindAttempts); - if (rntbdPortPoolBindAttempts < minRntbdPortPoolBindAttempts) - { - DefaultTrace.TraceWarning( - "The value of {0} is too small. Received {1}. Adjusting to {2}", - nameof(rntbdPortPoolBindAttempts), - rntbdPortPoolBindAttempts, minRntbdPortPoolBindAttempts); - rntbdPortPoolBindAttempts = minRntbdPortPoolBindAttempts; - } - else if (rntbdPortPoolBindAttempts > maxRntbdPortPoolBindAttempts) - { - DefaultTrace.TraceWarning( - "The value of {0} is too large. Received {1}. Adjusting to {2}", - nameof(rntbdPortPoolBindAttempts), - rntbdPortPoolBindAttempts, maxRntbdPortPoolBindAttempts); - rntbdPortPoolBindAttempts = maxRntbdPortPoolBindAttempts; - } - } - - private static void ValidateRntbdMaxConcurrentOpeningConnectionCount(ref int rntbdMaxConcurrentOpeningConnectionCount) - { - // RntbdMaxConcurrentOpeningConnectionCount is used to control how fast connections can be opened. - // Usually, each upcaller should choose a resonable value for rntbdMaxConcurrentOpeningConnectionCount. - // The RntbdMaxConcurrentOpeningConnectionUpperLimitConfig is added here to add another defense in case we need to mitigate tcp flood issue - // but the upcaller does not have a way to reconfig RntbdMaxConcurrentOpeningConnectionCount. - int rntbdMaxConcurrentOpeningConnectionUpperLimit = ushort.MaxValue; - const string RntbdMaxConcurrentOpeningConnectionUpperLimitConfig = "AZURE_COSMOS_TCP_MAX_CONCURRENT_OPENING_CONNECTION_UPPER_LIMIT"; - - string rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString = Environment.GetEnvironmentVariable(RntbdMaxConcurrentOpeningConnectionUpperLimitConfig); - if (!string.IsNullOrEmpty(rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString)) - { - int rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt = 0; - if (Int32.TryParse(rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString, out rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt)) - { - if (rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt <= 0) - { - throw new ArgumentException("RntbdMaxConcurrentOpeningConnectionUpperLimitConfig should be larger than 0"); - } - - rntbdMaxConcurrentOpeningConnectionUpperLimit = rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt; - } - } - - if (rntbdMaxConcurrentOpeningConnectionCount > rntbdMaxConcurrentOpeningConnectionUpperLimit) - { - DefaultTrace.TraceWarning( - "The value of {0} is too large. Received {1}. Adjusting to {2}", - nameof(rntbdMaxConcurrentOpeningConnectionCount), - rntbdMaxConcurrentOpeningConnectionCount, - rntbdMaxConcurrentOpeningConnectionUpperLimit); - rntbdMaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionUpperLimit; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Net.Security; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Client; + using Microsoft.Azure.Documents.FaultInjection; + using Microsoft.Azure.Documents.Telemetry; + + internal sealed class StoreClientFactory : IStoreClientFactory + { + private bool isDisposed = false; + private readonly Protocol protocol; + private readonly RetryWithConfiguration retryWithConfiguration; + private readonly bool disableRetryWithRetryPolicy; + private TransportClient transportClient; + private TransportClient fallbackTransportClient; + private ConnectionStateListener connectionStateListener = null; + + public StoreClientFactory( + Protocol protocol, + int requestTimeoutInSeconds, + int maxConcurrentConnectionOpenRequests, + UserAgentContainer userAgent = null, // optional for both HTTPS and RNTBD + ICommunicationEventSource eventSource = null, // required for HTTPS, not used for RNTBD + string overrideHostNameInCertificate = null, // optional for RNTBD, not used for HTTPS + int openTimeoutInSeconds = 0, // optional for RNTBD, not used for HTTPS + int idleTimeoutInSeconds = -1,// optional for both HTTPS and RNTBD + int timerPoolGranularityInSeconds = 0, // optional for RNTBD, not used for HTTPS + int maxRntbdChannels = ushort.MaxValue, // RNTBD + int rntbdPartitionCount = 1, // RNTBD + int maxRequestsPerRntbdChannel = 30, // RNTBD + PortReuseMode rntbdPortReuseMode = PortReuseMode.ReuseUnicastPort, // RNTBD + int rntbdPortPoolReuseThreshold = 256, // RNTBD + int rntbdPortPoolBindAttempts = 5, // RNTBD + int receiveHangDetectionTimeSeconds = 65, // RNTBD + int sendHangDetectionTimeSeconds = 10, // RNTBD + bool disableRetryWithRetryPolicy = false, + RetryWithConfiguration retryWithConfiguration = null, + RntbdConstants.CallerId callerId = RntbdConstants.CallerId.Anonymous, // replicatedResourceClient + bool enableTcpConnectionEndpointRediscovery = false, + IAddressResolver addressResolver = null, // globalAddressResolver + TimeSpan localRegionOpenTimeout = default, + bool enableChannelMultiplexing = false, + int rntbdMaxConcurrentOpeningConnectionCount = ushort.MaxValue, // Optional for Rntbd + MemoryStreamPool memoryStreamPool = null, + RemoteCertificateValidationCallback remoteCertificateValidationCallback = null, + Func> dnsResolutionFunction = null, // optional override + DistributedTracingOptions distributedTracingOptions = null, // Distributed Tracing Configuration + IChaosInterceptor chaosInterceptor = null) // Fault Injection + { + // <=0 means idle timeout is disabled. + // valid value: >= 10 minutes + if (idleTimeoutInSeconds > 0 && idleTimeoutInSeconds < 600) + { + throw new ArgumentOutOfRangeException(nameof(idleTimeoutInSeconds)); + } + + if (protocol == Protocol.Https) + { + if (eventSource == null) + { + throw new ArgumentOutOfRangeException(nameof(eventSource)); + } + + this.transportClient = new HttpTransportClient(requestTimeoutInSeconds, eventSource, userAgent, idleTimeoutInSeconds); + } + else if (protocol == Protocol.Tcp) + { + if (maxRntbdChannels <= 0) + { + throw new ArgumentOutOfRangeException(nameof(maxRntbdChannels)); + } + + if ((rntbdPartitionCount < 1) || (rntbdPartitionCount > 8)) + { + throw new ArgumentOutOfRangeException(nameof(rntbdPartitionCount)); + } + + if (maxRequestsPerRntbdChannel <= 0) + { + throw new ArgumentOutOfRangeException(nameof(maxRequestsPerRntbdChannel)); + } + + if (maxRntbdChannels > ushort.MaxValue) + { + DefaultTrace.TraceWarning( + "The value of {0} is unreasonably large. Received: {1}. " + + "Use {2} to represent \"effectively infinite\".", + nameof(maxRntbdChannels), + maxRntbdChannels, + ushort.MaxValue); + } + + const int minRecommendedMaxRequestsPerChannel = 6; + const int maxRecommendedMaxRequestsPerChannel = 256; + if (maxRequestsPerRntbdChannel < minRecommendedMaxRequestsPerChannel) + { + DefaultTrace.TraceWarning( + "The value of {0} is unreasonably small. Received: {1}. " + + "Small values of {0} can cause a large number of RNTBD " + + "channels to be opened to the same back-end. Reasonable " + + "values are between {2} and {3}", + nameof(maxRequestsPerRntbdChannel), + maxRequestsPerRntbdChannel, + minRecommendedMaxRequestsPerChannel, + maxRecommendedMaxRequestsPerChannel); + } + + if (maxRequestsPerRntbdChannel > maxRecommendedMaxRequestsPerChannel) + { + DefaultTrace.TraceWarning( + "The value of {0} is unreasonably large. Received: {1}. " + + "Large values of {0} can cause significant head-of-line " + + "blocking over RNTBD channels. Reasonable values are between {2} and {3}", + nameof(maxRequestsPerRntbdChannel), + maxRequestsPerRntbdChannel, + minRecommendedMaxRequestsPerChannel, + maxRecommendedMaxRequestsPerChannel); + } + + // Not related to maxRecommendedMaxRequestsPerChannel. + const int minRequiredSimultaneousRequests = 512; + if (checked(maxRntbdChannels * maxRequestsPerRntbdChannel) < + minRequiredSimultaneousRequests) + { + DefaultTrace.TraceWarning( + "The number of simultaneous requests allowed per backend " + + "is unreasonably small. Received {0} = {1}, {2} = {3}. " + + "Reasonable values are at least {4}", + nameof(maxRntbdChannels), maxRntbdChannels, + nameof(maxRequestsPerRntbdChannel), maxRequestsPerRntbdChannel, + minRequiredSimultaneousRequests); + } + + StoreClientFactory.ValidatePortPoolReuseThreshold(ref rntbdPortPoolReuseThreshold); + StoreClientFactory.ValidatePortPoolBindAttempts(ref rntbdPortPoolBindAttempts); + if (rntbdPortPoolBindAttempts > rntbdPortPoolReuseThreshold) + { + DefaultTrace.TraceWarning( + "Raising the value of {0} from {1} to {2} to match the value of {3}", + nameof(rntbdPortPoolReuseThreshold), rntbdPortPoolReuseThreshold, + rntbdPortPoolBindAttempts + 1, nameof(rntbdPortPoolBindAttempts)); + rntbdPortPoolReuseThreshold = rntbdPortPoolBindAttempts; + } + + const int minReceiveHangDetectionTimeSeconds = 65; + const int maxReceiveHangDetectionTimeSeconds = 180; + if (receiveHangDetectionTimeSeconds < minReceiveHangDetectionTimeSeconds) + { + DefaultTrace.TraceWarning( + "The value of {0} is too small. Received {1}. Adjusting to {2}", + nameof(receiveHangDetectionTimeSeconds), + receiveHangDetectionTimeSeconds, + minReceiveHangDetectionTimeSeconds); + receiveHangDetectionTimeSeconds = minReceiveHangDetectionTimeSeconds; + } + + if (receiveHangDetectionTimeSeconds > maxReceiveHangDetectionTimeSeconds) + { + DefaultTrace.TraceWarning( + "The value of {0} is too large. Received {1}. Adjusting to {2}", + nameof(receiveHangDetectionTimeSeconds), + receiveHangDetectionTimeSeconds, + maxReceiveHangDetectionTimeSeconds); + receiveHangDetectionTimeSeconds = maxReceiveHangDetectionTimeSeconds; + } + + const int minSendHangDetectionTimeSeconds = 2; + const int maxSendHangDetectionTimeSeconds = 60; + if (sendHangDetectionTimeSeconds < minSendHangDetectionTimeSeconds) + { + DefaultTrace.TraceWarning( + "The value of {0} is too small. Received {1}. Adjusting to {2}", + nameof(sendHangDetectionTimeSeconds), + sendHangDetectionTimeSeconds, + minSendHangDetectionTimeSeconds); + sendHangDetectionTimeSeconds = minSendHangDetectionTimeSeconds; + } + + if (sendHangDetectionTimeSeconds > maxSendHangDetectionTimeSeconds) + { + DefaultTrace.TraceWarning( + "The value of {0} is too large. Received {1}. Adjusting to {2}", + nameof(sendHangDetectionTimeSeconds), + sendHangDetectionTimeSeconds, + maxSendHangDetectionTimeSeconds); + sendHangDetectionTimeSeconds = maxSendHangDetectionTimeSeconds; + } + + if (enableTcpConnectionEndpointRediscovery && addressResolver != null) + { + this.connectionStateListener = new ConnectionStateListener(addressResolver); + } + + StoreClientFactory.ValidateRntbdMaxConcurrentOpeningConnectionCount(ref rntbdMaxConcurrentOpeningConnectionCount); + + this.transportClient = new Rntbd.TransportClient( + new Rntbd.TransportClient.Options(TimeSpan.FromSeconds(requestTimeoutInSeconds)) + { + MaxChannels = maxRntbdChannels, + PartitionCount = rntbdPartitionCount, + MaxRequestsPerChannel = maxRequestsPerRntbdChannel, + PortReuseMode = rntbdPortReuseMode, + PortPoolReuseThreshold = rntbdPortPoolReuseThreshold, + PortPoolBindAttempts = rntbdPortPoolBindAttempts, + ReceiveHangDetectionTime = TimeSpan.FromSeconds(receiveHangDetectionTimeSeconds), + SendHangDetectionTime = TimeSpan.FromSeconds(sendHangDetectionTimeSeconds), + UserAgent = userAgent, + CertificateHostNameOverride = overrideHostNameInCertificate, + OpenTimeout = TimeSpan.FromSeconds(openTimeoutInSeconds), + LocalRegionOpenTimeout = localRegionOpenTimeout, + TimerPoolResolution = TimeSpan.FromSeconds(timerPoolGranularityInSeconds), + IdleTimeout = TimeSpan.FromSeconds(idleTimeoutInSeconds), + CallerId = callerId, + ConnectionStateListener = this.connectionStateListener, + EnableChannelMultiplexing = enableChannelMultiplexing, + MaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionCount, + MemoryStreamPool = memoryStreamPool, + RemoteCertificateValidationCallback = remoteCertificateValidationCallback, + DnsResolutionFunction = dnsResolutionFunction, + DistributedTracingOptions = distributedTracingOptions + }, + chaosInterceptor); + + this.fallbackTransportClient = new Rntbd.TransportClient( + new Rntbd.TransportClient.Options(TimeSpan.FromSeconds(requestTimeoutInSeconds)) + { + MaxChannels = maxRntbdChannels, + PartitionCount = rntbdPartitionCount, + MaxRequestsPerChannel = 1, // Legacy RNTBD is 1 request per channel. + PortReuseMode = rntbdPortReuseMode, + PortPoolReuseThreshold = rntbdPortPoolReuseThreshold, + PortPoolBindAttempts = rntbdPortPoolBindAttempts, + ReceiveHangDetectionTime = TimeSpan.FromSeconds(receiveHangDetectionTimeSeconds), + SendHangDetectionTime = TimeSpan.FromSeconds(sendHangDetectionTimeSeconds), + UserAgent = userAgent, + CertificateHostNameOverride = overrideHostNameInCertificate, + OpenTimeout = TimeSpan.FromSeconds(openTimeoutInSeconds), + LocalRegionOpenTimeout = localRegionOpenTimeout, + TimerPoolResolution = TimeSpan.FromSeconds(timerPoolGranularityInSeconds), + IdleTimeout = TimeSpan.FromSeconds(idleTimeoutInSeconds), + CallerId = callerId, + ConnectionStateListener = this.connectionStateListener, + EnableChannelMultiplexing = enableChannelMultiplexing, + MaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionCount, + MemoryStreamPool = memoryStreamPool, + RemoteCertificateValidationCallback = remoteCertificateValidationCallback, + DnsResolutionFunction = dnsResolutionFunction, + DistributedTracingOptions = distributedTracingOptions + }, + chaosInterceptor); + } + else + { + throw new ArgumentOutOfRangeException(nameof(protocol), protocol, "Invalid protocol value"); + } + + this.protocol = protocol; + this.retryWithConfiguration = retryWithConfiguration; + this.disableRetryWithRetryPolicy = disableRetryWithRetryPolicy; + } + + private StoreClientFactory( + Protocol protocol, + RetryWithConfiguration retryWithConfiguration, + TransportClient transportClient, + TransportClient fallbackTransportClient, + ConnectionStateListener connectionStateListener) + { + this.protocol = protocol; + this.retryWithConfiguration = retryWithConfiguration; + this.transportClient = transportClient; + this.fallbackTransportClient = fallbackTransportClient; + this.connectionStateListener = connectionStateListener; + } + + internal StoreClientFactory Clone() + { + return new StoreClientFactory( + this.protocol, + this.retryWithConfiguration, + this.transportClient, + this.fallbackTransportClient, + this.connectionStateListener); + } + + // Interceptor factory (used in V3 SDK by compute to intercept transport interactions for chargeback) + internal void WithTransportInterceptor(Func transportClientHandlerFactory) + { + if (transportClientHandlerFactory == null) + { + throw new ArgumentNullException(nameof(transportClientHandlerFactory)); + } + + this.transportClient = transportClientHandlerFactory(this.transportClient); + this.fallbackTransportClient = transportClientHandlerFactory(this.fallbackTransportClient); + } + + public StoreClient CreateStoreClient( + IAddressResolver addressResolver, + ISessionContainer sessionContainer, + IServiceConfigurationReader serviceConfigurationReader, + IAuthorizationTokenProvider authorizationTokenProvider, + bool enableRequestDiagnostics = false, + bool enableReadRequestsFallback = false, + bool useFallbackClient = true, + bool useMultipleWriteLocations = false, + bool detectClientConnectivityIssues = false, + bool enableReplicaValidation = false) + { + this.ThrowIfDisposed(); + if (useFallbackClient && this.fallbackTransportClient != null) + { + DefaultTrace.TraceInformation("Using fallback TransportClient"); + return new StoreClient( + addressResolver: addressResolver, + sessionContainer: sessionContainer, + serviceConfigurationReader: serviceConfigurationReader, + userTokenProvider: authorizationTokenProvider, + protocol: this.protocol, + transportClient: this.fallbackTransportClient, + enableRequestDiagnostics: enableRequestDiagnostics, + enableReadRequestsFallback: enableReadRequestsFallback, + useMultipleWriteLocations: useMultipleWriteLocations, + detectClientConnectivityIssues: detectClientConnectivityIssues, + disableRetryWithRetryPolicy: this.disableRetryWithRetryPolicy, + retryWithConfiguration: this.retryWithConfiguration, + enableReplicaValidation: enableReplicaValidation); + } + + return new StoreClient( + addressResolver: addressResolver, + sessionContainer: sessionContainer, + serviceConfigurationReader: serviceConfigurationReader, + userTokenProvider: authorizationTokenProvider, + protocol: this.protocol, + transportClient: this.transportClient, + enableRequestDiagnostics: enableRequestDiagnostics, + enableReadRequestsFallback: enableReadRequestsFallback, + useMultipleWriteLocations: useMultipleWriteLocations, + detectClientConnectivityIssues: detectClientConnectivityIssues, + disableRetryWithRetryPolicy: this.disableRetryWithRetryPolicy, + retryWithConfiguration: this.retryWithConfiguration, + enableReplicaValidation: enableReplicaValidation); + } + + #region IDisposable + public void Dispose() + { + if (this.isDisposed) + { + return; + } + + if (this.transportClient != null) + { + this.transportClient.Dispose(); + this.transportClient = null; + } + + if (this.fallbackTransportClient != null) + { + this.fallbackTransportClient.Dispose(); + this.fallbackTransportClient = null; + } + + this.isDisposed = true; + } + + private void ThrowIfDisposed() + { + if (this.isDisposed) + { + throw new ObjectDisposedException("StoreClientFactory"); + } + } + #endregion + + private static void ValidatePortPoolReuseThreshold(ref int rntbdPortPoolReuseThreshold) + { + const int minRntbdPortPoolReuseThreshold = 32; + const int maxRntbdPortPoolReuseThreshold = 2048; + Debug.Assert(minRntbdPortPoolReuseThreshold < maxRntbdPortPoolReuseThreshold); + if (rntbdPortPoolReuseThreshold < minRntbdPortPoolReuseThreshold) + { + DefaultTrace.TraceWarning( + "The value of {0} is too small. Received {1}. Adjusting to {2}", + nameof(rntbdPortPoolReuseThreshold), + rntbdPortPoolReuseThreshold, minRntbdPortPoolReuseThreshold); + rntbdPortPoolReuseThreshold = minRntbdPortPoolReuseThreshold; + } + else if (rntbdPortPoolReuseThreshold > maxRntbdPortPoolReuseThreshold) + { + DefaultTrace.TraceWarning( + "The value of {0} is too large. Received {1}. Adjusting to {2}", + nameof(rntbdPortPoolReuseThreshold), + rntbdPortPoolReuseThreshold, maxRntbdPortPoolReuseThreshold); + rntbdPortPoolReuseThreshold = maxRntbdPortPoolReuseThreshold; + } + } + + private static void ValidatePortPoolBindAttempts(ref int rntbdPortPoolBindAttempts) + { + const int minRntbdPortPoolBindAttempts = 3; + const int maxRntbdPortPoolBindAttempts = 32; + Debug.Assert(minRntbdPortPoolBindAttempts < maxRntbdPortPoolBindAttempts); + if (rntbdPortPoolBindAttempts < minRntbdPortPoolBindAttempts) + { + DefaultTrace.TraceWarning( + "The value of {0} is too small. Received {1}. Adjusting to {2}", + nameof(rntbdPortPoolBindAttempts), + rntbdPortPoolBindAttempts, minRntbdPortPoolBindAttempts); + rntbdPortPoolBindAttempts = minRntbdPortPoolBindAttempts; + } + else if (rntbdPortPoolBindAttempts > maxRntbdPortPoolBindAttempts) + { + DefaultTrace.TraceWarning( + "The value of {0} is too large. Received {1}. Adjusting to {2}", + nameof(rntbdPortPoolBindAttempts), + rntbdPortPoolBindAttempts, maxRntbdPortPoolBindAttempts); + rntbdPortPoolBindAttempts = maxRntbdPortPoolBindAttempts; + } + } + + private static void ValidateRntbdMaxConcurrentOpeningConnectionCount(ref int rntbdMaxConcurrentOpeningConnectionCount) + { + // RntbdMaxConcurrentOpeningConnectionCount is used to control how fast connections can be opened. + // Usually, each upcaller should choose a resonable value for rntbdMaxConcurrentOpeningConnectionCount. + // The RntbdMaxConcurrentOpeningConnectionUpperLimitConfig is added here to add another defense in case we need to mitigate tcp flood issue + // but the upcaller does not have a way to reconfig RntbdMaxConcurrentOpeningConnectionCount. + int rntbdMaxConcurrentOpeningConnectionUpperLimit = ushort.MaxValue; + const string RntbdMaxConcurrentOpeningConnectionUpperLimitConfig = "AZURE_COSMOS_TCP_MAX_CONCURRENT_OPENING_CONNECTION_UPPER_LIMIT"; + + string rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString = Environment.GetEnvironmentVariable(RntbdMaxConcurrentOpeningConnectionUpperLimitConfig); + if (!string.IsNullOrEmpty(rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString)) + { + int rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt = 0; + if (Int32.TryParse(rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideString, out rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt)) + { + if (rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt <= 0) + { + throw new ArgumentException("RntbdMaxConcurrentOpeningConnectionUpperLimitConfig should be larger than 0"); + } + + rntbdMaxConcurrentOpeningConnectionUpperLimit = rntbdMaxConcurrentOpeningConnectionUpperLimitOverrideInt; + } + } + + if (rntbdMaxConcurrentOpeningConnectionCount > rntbdMaxConcurrentOpeningConnectionUpperLimit) + { + DefaultTrace.TraceWarning( + "The value of {0} is too large. Received {1}. Adjusting to {2}", + nameof(rntbdMaxConcurrentOpeningConnectionCount), + rntbdMaxConcurrentOpeningConnectionCount, + rntbdMaxConcurrentOpeningConnectionUpperLimit); + rntbdMaxConcurrentOpeningConnectionCount = rntbdMaxConcurrentOpeningConnectionUpperLimit; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreReader.cs b/Microsoft.Azure.Cosmos/src/direct/StoreReader.cs index b5c382a8c3..b066c6b16c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreReader.cs @@ -1,680 +1,680 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Net; - using System.Runtime.CompilerServices; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal sealed class StoreReader - { - private readonly TransportClient transportClient; - private readonly AddressSelector addressSelector; - private readonly IAddressEnumerator addressEnumerator; - private readonly ISessionContainer sessionContainer; - private readonly bool canUseLocalLSNBasedHeaders; - private readonly bool isReplicaAddressValidationEnabled; - - public StoreReader( - TransportClient transportClient, - AddressSelector addressSelector, - IAddressEnumerator addressEnumerator, - ISessionContainer sessionContainer, - bool enableReplicaValidation) - { - this.transportClient = transportClient; - this.addressSelector = addressSelector; - this.addressEnumerator = addressEnumerator ?? throw new ArgumentNullException(nameof(addressEnumerator)); - this.sessionContainer = sessionContainer; - this.canUseLocalLSNBasedHeaders = VersionUtility.IsLaterThan(HttpConstants.Versions.CurrentVersion, HttpConstants.Versions.v2018_06_18); - this.isReplicaAddressValidationEnabled = enableReplicaValidation; - } - - // Test hook - internal string LastReadAddress - { - get; - set; - } - - /// - /// Makes requests to multiple replicas at once and returns responses - /// - /// DocumentServiceRequest - /// flag to indicate whether to indicate primary replica in the reads - /// number of replicas to read from - /// flag to indicate whether a valid lsn is required to consider a response as valid - /// flag to indicate whether to use session token - /// Read mode - /// set minimum required session lsn - /// reads from all available replicas to gather result from readsToRead number of replicas - /// ReadReplicaResult which indicates the LSN and whether Quorum was Met / Not Met etc - public async Task>> ReadMultipleReplicaAsync( - DocumentServiceRequest entity, - bool includePrimary, - int replicaCountToRead, - bool requiresValidLsn, - bool useSessionToken, - ReadMode readMode, - bool checkMinLSN = false, - bool forceReadAll = false) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; - try - { - using ReadReplicaResult readQuorumResult = await this.ReadMultipleReplicasInternalAsync( - entity, includePrimary, replicaCountToRead, requiresValidLsn, useSessionToken, readMode, checkMinLSN, forceReadAll); - if (entity.RequestContext.PerformLocalRefreshOnGoneException && - readQuorumResult.RetryWithForceRefresh && - !entity.RequestContext.ForceRefreshAddressCache) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - entity.RequestContext.ForceRefreshAddressCache = true; - using ReadReplicaResult readQuorumResultSecondCall = await this.ReadMultipleReplicasInternalAsync( - entity, - includePrimary: includePrimary, - replicaCountToRead: replicaCountToRead, - requiresValidLsn: requiresValidLsn, - useSessionToken: useSessionToken, - readMode: readMode, - checkMinLSN: false, - forceReadAll: forceReadAll); - return readQuorumResultSecondCall.StoreResultList.GetValueAndDereference(); - } - - return readQuorumResult.StoreResultList.GetValueAndDereference(); - - } - finally - { - SessionTokenHelper.SetOriginalSessionToken(entity, originalSessionToken); - } - } - - public async Task> ReadPrimaryAsync( - DocumentServiceRequest entity, - bool requiresValidLsn, - bool useSessionToken) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; - try - { - using ReadReplicaResult readQuorumResult = await this.ReadPrimaryInternalAsync( - entity, - requiresValidLsn, - useSessionToken, - isRetryAfterRefresh: false); - if (entity.RequestContext.PerformLocalRefreshOnGoneException && - readQuorumResult.RetryWithForceRefresh && - !entity.RequestContext.ForceRefreshAddressCache) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - entity.RequestContext.ForceRefreshAddressCache = true; - using ReadReplicaResult readQuorumResultSecondCall = await this.ReadPrimaryInternalAsync( - entity, - requiresValidLsn, - useSessionToken, - isRetryAfterRefresh: true); - return StoreReader.GetStoreResultOrThrowGoneException(readQuorumResultSecondCall); - } - - return StoreReader.GetStoreResultOrThrowGoneException(readQuorumResult); - } - finally - { - SessionTokenHelper.SetOriginalSessionToken(entity, originalSessionToken); - } - } - - private static ReferenceCountedDisposable GetStoreResultOrThrowGoneException(ReadReplicaResult readReplicaResult) - { - StoreResultList storeResultList = readReplicaResult.StoreResultList; - if (storeResultList.Count == 0) - { - throw new GoneException(RMResources.Gone, SubStatusCodes.Server_NoValidStoreResponse); - } - - return storeResultList.GetFirstStoreResultAndDereference(); - } - - /// - /// Makes requests to multiple replicas at once and returns responses - /// - /// DocumentServiceRequest - /// flag to indicate whether to indicate primary replica in the reads - /// number of replicas to read from - /// flag to indicate whether a valid lsn is required to consider a response as valid - /// flag to indicate whether to use session token - /// Read mode - /// set minimum required session lsn - /// will read from all available replicas to put together result from readsToRead number of replicas - /// ReadReplicaResult which indicates the LSN and whether Quorum was Met / Not Met etc - private async Task ReadMultipleReplicasInternalAsync(DocumentServiceRequest entity, - bool includePrimary, - int replicaCountToRead, - bool requiresValidLsn, - bool useSessionToken, - ReadMode readMode, - bool checkMinLSN = false, - bool forceReadAll = false) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - using StoreResultList storeResultList = new(new List>(replicaCountToRead)); - - string requestedCollectionRid = entity.RequestContext.ResolvedCollectionRid; - - (IReadOnlyList resolveApiResults, IReadOnlyList replicaHealthStatuses) = await this.addressSelector.ResolveAllTransportAddressUriAsync( - entity, - includePrimary, - entity.RequestContext.ForceRefreshAddressCache); - - ISessionToken requestSessionToken = null; - if (useSessionToken) - { - SessionTokenHelper.SetPartitionLocalSessionToken(entity, this.sessionContainer); - if (checkMinLSN) - { - requestSessionToken = entity.RequestContext.SessionToken; - } - } - else - { - entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); - } - - if (resolveApiResults.Count < replicaCountToRead) - { - if (!entity.RequestContext.ForceRefreshAddressCache) - { - return new ReadReplicaResult(retryWithForceRefresh: true, responses: storeResultList.GetValueAndDereference()); - } - - return new ReadReplicaResult(retryWithForceRefresh: false, responses: storeResultList.GetValueAndDereference()); - } - - int replicasToRead = replicaCountToRead; - - string clientVersion = entity.Headers[HttpConstants.HttpHeaders.Version]; - bool enforceSessionCheck = !string.IsNullOrEmpty(clientVersion) && VersionUtility.IsLaterThan(clientVersion, HttpConstants.VersionDates.v2016_05_30); - - this.UpdateContinuationTokenIfReadFeedOrQuery(entity); - - bool hasGoneException = false; - bool hasCancellationException = false; - Exception cancellationException = null; - Exception exceptionToThrow = null; - SubStatusCodes subStatusCodeForException = SubStatusCodes.Unknown; - IEnumerator uriEnumerator = this.addressEnumerator - .GetTransportAddresses(transportAddressUris: resolveApiResults, - failedEndpoints: entity.RequestContext.FailedEndpoints, - replicaAddressValidationEnabled: this.isReplicaAddressValidationEnabled) - .GetEnumerator(); - - // Loop until we have the read quorum number of valid responses or if we have read all the replicas - while (replicasToRead > 0 && uriEnumerator.MoveNext()) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - Dictionary, (TransportAddressUri, DateTime startTime)> readStoreTasks = new Dictionary, (TransportAddressUri, DateTime startTime)>(); - - do - { - readStoreTasks.Add(this.ReadFromStoreAsync( - physicalAddress: uriEnumerator.Current, - request: entity), - (uriEnumerator.Current, DateTime.UtcNow)); - - if (!forceReadAll && readStoreTasks.Count == replicasToRead) - { - break; - } - } while (uriEnumerator.MoveNext()); - - try - { - await Task.WhenAll(readStoreTasks.Keys); - } - catch (Exception exception) - { - exceptionToThrow = exception; - - // Get SubStatusCode - if (exception is DocumentClientException documentClientException) - { - subStatusCodeForException = documentClientException.GetSubStatus(); - } - - //All task exceptions are visited below. - if (exception is DocumentClientException dce && - (dce.StatusCode == HttpStatusCode.NotFound - || dce.StatusCode == HttpStatusCode.Conflict - || (int)dce.StatusCode == (int)StatusCodes.TooManyRequests)) - { - // Only trace message for common scenarios to avoid the overhead of computing the stack trace. - DefaultTrace.TraceInformation("StoreReader.ReadMultipleReplicasInternalAsync exception thrown: StatusCode: {0}; SubStatusCode:{1}; Exception.Message: {2}", - dce.StatusCode, - dce.Headers?.Get(WFConstants.BackendHeaders.SubStatus), - dce.Message); - } - else - { - // Include the full exception for other scenarios for troubleshooting - DefaultTrace.TraceInformation("StoreReader.ReadMultipleReplicasInternalAsync exception thrown: Exception: {0}", exception); - } - } - - foreach (KeyValuePair, (TransportAddressUri uri, DateTime startTime)> readTaskValuePair in readStoreTasks) - { - Task<(StoreResponse response, DateTime endTime)> readTask = readTaskValuePair.Key; - (StoreResponse storeResponse, DateTime endTime) = readTask.Status == TaskStatus.RanToCompletion ? readTask.Result : (null, DateTime.UtcNow); - Exception storeException = readTask.Exception?.InnerException; - TransportAddressUri targetUri = readTaskValuePair.Value.uri; - - if (storeException != null) - { - entity.RequestContext.AddToFailedEndpoints(storeException, targetUri); - } - - // IsCanceled can be true with storeException being null if the async call - // gets canceled before it gets scheduled. - if (readTask.IsCanceled || storeException is OperationCanceledException) - { - hasCancellationException = true; - cancellationException ??= storeException; - continue; - } - - using (ReferenceCountedDisposable disposableStoreResult = StoreResult.CreateStoreResult( - storeResponse, - storeException, - requiresValidLsn, - this.canUseLocalLSNBasedHeaders && readMode != ReadMode.Strong, - replicaHealthStatuses, - targetUri.Uri)) - { - StoreResult storeResult = disposableStoreResult.Target; - entity.RequestContext.RequestChargeTracker.AddCharge(storeResult.RequestCharge); - - if (storeResponse != null) - { - entity.RequestContext.ClientRequestStatistics.ContactedReplicas.Add(targetUri); - } - - if (storeException != null && storeException.InnerException is TransportException) - { - entity.RequestContext.ClientRequestStatistics.FailedReplicas.Add(targetUri); - } - - entity.RequestContext.ClientRequestStatistics.RecordResponse( - entity, - storeResult, - readTaskValuePair.Value.startTime, - endTime); - - if (storeResult.Exception != null) - { - StoreResult.VerifyCanContinueOnException(storeResult.Exception); - } - - if (storeResult.IsValid) - { - if (requestSessionToken == null - || (storeResult.SessionToken != null && requestSessionToken.IsValid(storeResult.SessionToken)) - || (!enforceSessionCheck && storeResult.StatusCode != StatusCodes.NotFound)) - { - storeResultList.Add(disposableStoreResult.TryAddReference()); - } - } - - hasGoneException |= storeResult.StatusCode == StatusCodes.Gone && storeResult.SubStatusCode != SubStatusCodes.NameCacheIsStale; - } - - // Perform address refresh in the background as soon as we hit a GoneException - if (hasGoneException && !entity.RequestContext.PerformedBackgroundAddressRefresh) - { - this.addressSelector.StartBackgroundAddressRefresh(entity); - entity.RequestContext.PerformedBackgroundAddressRefresh = true; - } - } - - if (storeResultList.Count >= replicaCountToRead) - { - return new ReadReplicaResult(false, storeResultList.GetValueAndDereference()); - } - - // Remaining replicas - replicasToRead = replicaCountToRead - storeResultList.Count; - } - - if (storeResultList.Count < replicaCountToRead) - { - DefaultTrace.TraceInformation("Could not get quorum number of responses. " + - "ValidResponsesReceived: {0} ResponsesExpected: {1}, ResolvedAddressCount: {2}, ResponsesString: {3}", - storeResultList.Count, replicaCountToRead, resolveApiResults.Count, String.Join(";", storeResultList.GetValue())); - - if (hasGoneException) - { - if (!entity.RequestContext.PerformLocalRefreshOnGoneException) - { - // If we are not supposed to act upon GoneExceptions here, just throw them - throw new GoneException(exceptionToThrow, subStatusCodeForException); - } - else if (!entity.RequestContext.ForceRefreshAddressCache) - { - // We could not obtain valid read quorum number of responses even when we went through all the secondary addresses - // Attempt force refresh and start over again. - return new ReadReplicaResult(retryWithForceRefresh: true, responses: storeResultList.GetValueAndDereference()); - } - } - else if (hasCancellationException) - { - // We did not get the required number of responses and we encountered task cancellation on some/all of the store read tasks. - // We propagate the first cancellation exception we've found, or a new OperationCanceledException if none. - // The latter case can happen when Task.IsCanceled = true. - throw cancellationException ?? new OperationCanceledException(); - } - } - - return new ReadReplicaResult(false, storeResultList.GetValueAndDereference()); - } - - private async Task ReadPrimaryInternalAsync( - DocumentServiceRequest entity, - bool requiresValidLsn, - bool useSessionToken, - bool isRetryAfterRefresh) - { - entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - - TransportAddressUri primaryUri = await this.addressSelector.ResolvePrimaryTransportAddressUriAsync( - entity, - entity.RequestContext.ForceRefreshAddressCache); - - if (useSessionToken) - { - SessionTokenHelper.SetPartitionLocalSessionToken(entity, this.sessionContainer); - } - else - { - // Remove whatever session token can be there in headers. - // We don't need it. If it is global - backend will not understand it. - // But there's no point in producing partition local session token. - entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); - } - - DateTime startTimeUtc = DateTime.UtcNow; - StrongBox endTimeUtc = new (); - using ReferenceCountedDisposable storeResult = await GetResult(entity, requiresValidLsn, primaryUri, endTimeUtc); - entity.RequestContext.ClientRequestStatistics.RecordResponse( - entity, - storeResult.Target, - startTimeUtc, - endTimeUtc.Value ?? DateTime.UtcNow); - - entity.RequestContext.RequestChargeTracker.AddCharge(storeResult.Target.RequestCharge); - - if (storeResult.Target.Exception != null) - { - StoreResult.VerifyCanContinueOnException(storeResult.Target.Exception); - } - - if (storeResult.Target.StatusCode == StatusCodes.Gone && storeResult.Target.SubStatusCode != SubStatusCodes.NameCacheIsStale) - { - if (isRetryAfterRefresh || - !entity.RequestContext.PerformLocalRefreshOnGoneException || - entity.RequestContext.ForceRefreshAddressCache) - { - // We can throw the exception if we have already performed an address refresh or if PerformLocalRefreshOnGoneException is false - throw new GoneException(RMResources.Gone, storeResult.Target.SubStatusCode); - } - - return new ReadReplicaResult(true, new List>()); - } - - return new ReadReplicaResult(false, new ReferenceCountedDisposable[] { storeResult.TryAddReference() }); - } - - private async Task> GetResult(DocumentServiceRequest entity, bool requiresValidLsn, TransportAddressUri primaryUri, StrongBox endTimeUtc) - { - ReferenceCountedDisposable storeResult; - List primaryReplicaHealthStatus = new () - { - primaryUri - .GetCurrentHealthState() - .GetHealthStatusDiagnosticString(), - }; - - try - { - this.UpdateContinuationTokenIfReadFeedOrQuery(entity); - (StoreResponse storeResponse, DateTime storeResponseEndTimeUtc) = await this.ReadFromStoreAsync( - primaryUri, - entity); - - endTimeUtc.Value = DateTime.UtcNow; - - storeResult = StoreResult.CreateStoreResult( - storeResponse, - null, - requiresValidLsn, - this.canUseLocalLSNBasedHeaders, - replicaHealthStatuses: primaryReplicaHealthStatus, - primaryUri.Uri); - } - catch (Exception exception) - { - DefaultTrace.TraceInformation("Exception {0} is thrown while doing Read Primary", exception); - storeResult = StoreResult.CreateStoreResult( - null, - exception, - requiresValidLsn, - this.canUseLocalLSNBasedHeaders, - replicaHealthStatuses: primaryReplicaHealthStatus, - primaryUri.Uri); - } - - return storeResult; - } - - private async Task<(StoreResponse, DateTime endTime)> ReadFromStoreAsync( - TransportAddressUri physicalAddress, - DocumentServiceRequest request) - { - request.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); - this.LastReadAddress = physicalAddress.ToString(); - - switch (request.OperationType) - { - case OperationType.Read: - case OperationType.Head: - case OperationType.HeadFeed: - case OperationType.SqlQuery: - case OperationType.ExecuteJavaScript: -#if !COSMOSCLIENT - case OperationType.MetadataCheckAccess: - case OperationType.GetStorageAuthToken: -#endif - { - StoreResponse result = await this.transportClient.InvokeResourceOperationAsync( - physicalAddress, - request); - return (result, DateTime.UtcNow); - } - - case OperationType.ReadFeed: - case OperationType.Query: - { - QueryRequestPerformanceActivity activity = CustomTypeExtensions.StartActivity(request); - StoreResponse result = await StoreReader.CompleteActivity(this.transportClient.InvokeResourceOperationAsync( - physicalAddress, - request), - activity); - return (result, DateTime.UtcNow); - } - default: - throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unexpected operation type {0}", request.OperationType)); - } - } - - private void UpdateContinuationTokenIfReadFeedOrQuery(DocumentServiceRequest request) - { - if (request.OperationType != OperationType.ReadFeed && - request.OperationType != OperationType.Query) - { - return; - } - - string continuation = request.Continuation; - if (continuation != null) - { - int firstSemicolonPosition = continuation.IndexOf(';'); - // IndexOf returns -1 if ';' is not found - if (firstSemicolonPosition < 0) - { - return; - } - - int semicolonCount = 1; - for (int i = firstSemicolonPosition + 1; i < continuation.Length; i++) - { - if (continuation[i] == ';') - { - semicolonCount++; - if (semicolonCount >= 3) - { - break; - } - } - } - - if (semicolonCount < 3) - { - throw new BadRequestException(string.Format( - CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - continuation, - HttpConstants.HttpHeaders.Continuation)); - } - - request.Continuation = continuation.Substring(0, firstSemicolonPosition); - } - } - - private static async Task CompleteActivity(Task task, QueryRequestPerformanceActivity activity) - { - if (activity == null) - { - return await task; - } - else - { - StoreResponse response; - try - { - response = await task; - } - catch - { - activity.ActivityComplete(false); - throw; - } - - activity.ActivityComplete(true); - return response; - } - } - - #region PrivateResultClasses - private sealed class ReadReplicaResult : IDisposable - { - public ReadReplicaResult(bool retryWithForceRefresh, IList> responses) - { - this.RetryWithForceRefresh = retryWithForceRefresh; - this.StoreResultList = new(responses); - } - - public bool RetryWithForceRefresh { get; private set; } - - public StoreResultList StoreResultList { get; private set; } - - public void Dispose() - { - this.StoreResultList.Dispose(); - } - } - - /// - /// Disposable list of StoreResult object with ability to skip first object disposal or skip disposal for entire list. - /// - private class StoreResultList : IDisposable - { - private IList> value; - - public StoreResultList(IList> collection) - { - this.value = collection ?? throw new ArgumentNullException(); - } - - public void Add(ReferenceCountedDisposable storeResult) - { - this.GetValueOrThrow().Add(storeResult); - } - - public int Count => this.GetValueOrThrow().Count; - - public ReferenceCountedDisposable GetFirstStoreResultAndDereference() - { - IList> value = this.GetValueOrThrow(); - if (value.Count > 0) - { - ReferenceCountedDisposable result = value[0]; - this.value[0] = null; - return result; - } - - return null; - } - - public IList> GetValue() => this.GetValueOrThrow(); - - public IList> GetValueAndDereference() - { - IList> response = this.GetValueOrThrow(); - this.value = null; - return response; - } - - public void Dispose() - { - if (this.value != null) - { - for (int i = 0; i < this.value.Count; i++) - { - this.value[i]?.Dispose(); - } - } - } - - private IList> GetValueOrThrow() - { - if (this.value == null || (this.value.Count > 0 && this.value[0] == null)) - { - throw new InvalidOperationException("Call on the StoreResultList with deferenced collection"); - } - - return this.value; - } - } - #endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Net; + using System.Runtime.CompilerServices; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal sealed class StoreReader + { + private readonly TransportClient transportClient; + private readonly AddressSelector addressSelector; + private readonly IAddressEnumerator addressEnumerator; + private readonly ISessionContainer sessionContainer; + private readonly bool canUseLocalLSNBasedHeaders; + private readonly bool isReplicaAddressValidationEnabled; + + public StoreReader( + TransportClient transportClient, + AddressSelector addressSelector, + IAddressEnumerator addressEnumerator, + ISessionContainer sessionContainer, + bool enableReplicaValidation) + { + this.transportClient = transportClient; + this.addressSelector = addressSelector; + this.addressEnumerator = addressEnumerator ?? throw new ArgumentNullException(nameof(addressEnumerator)); + this.sessionContainer = sessionContainer; + this.canUseLocalLSNBasedHeaders = VersionUtility.IsLaterThan(HttpConstants.Versions.CurrentVersion, HttpConstants.Versions.v2018_06_18); + this.isReplicaAddressValidationEnabled = enableReplicaValidation; + } + + // Test hook + internal string LastReadAddress + { + get; + set; + } + + /// + /// Makes requests to multiple replicas at once and returns responses + /// + /// DocumentServiceRequest + /// flag to indicate whether to indicate primary replica in the reads + /// number of replicas to read from + /// flag to indicate whether a valid lsn is required to consider a response as valid + /// flag to indicate whether to use session token + /// Read mode + /// set minimum required session lsn + /// reads from all available replicas to gather result from readsToRead number of replicas + /// ReadReplicaResult which indicates the LSN and whether Quorum was Met / Not Met etc + public async Task>> ReadMultipleReplicaAsync( + DocumentServiceRequest entity, + bool includePrimary, + int replicaCountToRead, + bool requiresValidLsn, + bool useSessionToken, + ReadMode readMode, + bool checkMinLSN = false, + bool forceReadAll = false) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; + try + { + using ReadReplicaResult readQuorumResult = await this.ReadMultipleReplicasInternalAsync( + entity, includePrimary, replicaCountToRead, requiresValidLsn, useSessionToken, readMode, checkMinLSN, forceReadAll); + if (entity.RequestContext.PerformLocalRefreshOnGoneException && + readQuorumResult.RetryWithForceRefresh && + !entity.RequestContext.ForceRefreshAddressCache) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + entity.RequestContext.ForceRefreshAddressCache = true; + using ReadReplicaResult readQuorumResultSecondCall = await this.ReadMultipleReplicasInternalAsync( + entity, + includePrimary: includePrimary, + replicaCountToRead: replicaCountToRead, + requiresValidLsn: requiresValidLsn, + useSessionToken: useSessionToken, + readMode: readMode, + checkMinLSN: false, + forceReadAll: forceReadAll); + return readQuorumResultSecondCall.StoreResultList.GetValueAndDereference(); + } + + return readQuorumResult.StoreResultList.GetValueAndDereference(); + + } + finally + { + SessionTokenHelper.SetOriginalSessionToken(entity, originalSessionToken); + } + } + + public async Task> ReadPrimaryAsync( + DocumentServiceRequest entity, + bool requiresValidLsn, + bool useSessionToken) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + string originalSessionToken = entity.Headers[HttpConstants.HttpHeaders.SessionToken]; + try + { + using ReadReplicaResult readQuorumResult = await this.ReadPrimaryInternalAsync( + entity, + requiresValidLsn, + useSessionToken, + isRetryAfterRefresh: false); + if (entity.RequestContext.PerformLocalRefreshOnGoneException && + readQuorumResult.RetryWithForceRefresh && + !entity.RequestContext.ForceRefreshAddressCache) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + entity.RequestContext.ForceRefreshAddressCache = true; + using ReadReplicaResult readQuorumResultSecondCall = await this.ReadPrimaryInternalAsync( + entity, + requiresValidLsn, + useSessionToken, + isRetryAfterRefresh: true); + return StoreReader.GetStoreResultOrThrowGoneException(readQuorumResultSecondCall); + } + + return StoreReader.GetStoreResultOrThrowGoneException(readQuorumResult); + } + finally + { + SessionTokenHelper.SetOriginalSessionToken(entity, originalSessionToken); + } + } + + private static ReferenceCountedDisposable GetStoreResultOrThrowGoneException(ReadReplicaResult readReplicaResult) + { + StoreResultList storeResultList = readReplicaResult.StoreResultList; + if (storeResultList.Count == 0) + { + throw new GoneException(RMResources.Gone, SubStatusCodes.Server_NoValidStoreResponse); + } + + return storeResultList.GetFirstStoreResultAndDereference(); + } + + /// + /// Makes requests to multiple replicas at once and returns responses + /// + /// DocumentServiceRequest + /// flag to indicate whether to indicate primary replica in the reads + /// number of replicas to read from + /// flag to indicate whether a valid lsn is required to consider a response as valid + /// flag to indicate whether to use session token + /// Read mode + /// set minimum required session lsn + /// will read from all available replicas to put together result from readsToRead number of replicas + /// ReadReplicaResult which indicates the LSN and whether Quorum was Met / Not Met etc + private async Task ReadMultipleReplicasInternalAsync(DocumentServiceRequest entity, + bool includePrimary, + int replicaCountToRead, + bool requiresValidLsn, + bool useSessionToken, + ReadMode readMode, + bool checkMinLSN = false, + bool forceReadAll = false) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + using StoreResultList storeResultList = new(new List>(replicaCountToRead)); + + string requestedCollectionRid = entity.RequestContext.ResolvedCollectionRid; + + (IReadOnlyList resolveApiResults, IReadOnlyList replicaHealthStatuses) = await this.addressSelector.ResolveAllTransportAddressUriAsync( + entity, + includePrimary, + entity.RequestContext.ForceRefreshAddressCache); + + ISessionToken requestSessionToken = null; + if (useSessionToken) + { + SessionTokenHelper.SetPartitionLocalSessionToken(entity, this.sessionContainer); + if (checkMinLSN) + { + requestSessionToken = entity.RequestContext.SessionToken; + } + } + else + { + entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); + } + + if (resolveApiResults.Count < replicaCountToRead) + { + if (!entity.RequestContext.ForceRefreshAddressCache) + { + return new ReadReplicaResult(retryWithForceRefresh: true, responses: storeResultList.GetValueAndDereference()); + } + + return new ReadReplicaResult(retryWithForceRefresh: false, responses: storeResultList.GetValueAndDereference()); + } + + int replicasToRead = replicaCountToRead; + + string clientVersion = entity.Headers[HttpConstants.HttpHeaders.Version]; + bool enforceSessionCheck = !string.IsNullOrEmpty(clientVersion) && VersionUtility.IsLaterThan(clientVersion, HttpConstants.VersionDates.v2016_05_30); + + this.UpdateContinuationTokenIfReadFeedOrQuery(entity); + + bool hasGoneException = false; + bool hasCancellationException = false; + Exception cancellationException = null; + Exception exceptionToThrow = null; + SubStatusCodes subStatusCodeForException = SubStatusCodes.Unknown; + IEnumerator uriEnumerator = this.addressEnumerator + .GetTransportAddresses(transportAddressUris: resolveApiResults, + failedEndpoints: entity.RequestContext.FailedEndpoints, + replicaAddressValidationEnabled: this.isReplicaAddressValidationEnabled) + .GetEnumerator(); + + // Loop until we have the read quorum number of valid responses or if we have read all the replicas + while (replicasToRead > 0 && uriEnumerator.MoveNext()) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + Dictionary, (TransportAddressUri, DateTime startTime)> readStoreTasks = new Dictionary, (TransportAddressUri, DateTime startTime)>(); + + do + { + readStoreTasks.Add(this.ReadFromStoreAsync( + physicalAddress: uriEnumerator.Current, + request: entity), + (uriEnumerator.Current, DateTime.UtcNow)); + + if (!forceReadAll && readStoreTasks.Count == replicasToRead) + { + break; + } + } while (uriEnumerator.MoveNext()); + + try + { + await Task.WhenAll(readStoreTasks.Keys); + } + catch (Exception exception) + { + exceptionToThrow = exception; + + // Get SubStatusCode + if (exception is DocumentClientException documentClientException) + { + subStatusCodeForException = documentClientException.GetSubStatus(); + } + + //All task exceptions are visited below. + if (exception is DocumentClientException dce && + (dce.StatusCode == HttpStatusCode.NotFound + || dce.StatusCode == HttpStatusCode.Conflict + || (int)dce.StatusCode == (int)StatusCodes.TooManyRequests)) + { + // Only trace message for common scenarios to avoid the overhead of computing the stack trace. + DefaultTrace.TraceInformation("StoreReader.ReadMultipleReplicasInternalAsync exception thrown: StatusCode: {0}; SubStatusCode:{1}; Exception.Message: {2}", + dce.StatusCode, + dce.Headers?.Get(WFConstants.BackendHeaders.SubStatus), + dce.Message); + } + else + { + // Include the full exception for other scenarios for troubleshooting + DefaultTrace.TraceInformation("StoreReader.ReadMultipleReplicasInternalAsync exception thrown: Exception: {0}", exception); + } + } + + foreach (KeyValuePair, (TransportAddressUri uri, DateTime startTime)> readTaskValuePair in readStoreTasks) + { + Task<(StoreResponse response, DateTime endTime)> readTask = readTaskValuePair.Key; + (StoreResponse storeResponse, DateTime endTime) = readTask.Status == TaskStatus.RanToCompletion ? readTask.Result : (null, DateTime.UtcNow); + Exception storeException = readTask.Exception?.InnerException; + TransportAddressUri targetUri = readTaskValuePair.Value.uri; + + if (storeException != null) + { + entity.RequestContext.AddToFailedEndpoints(storeException, targetUri); + } + + // IsCanceled can be true with storeException being null if the async call + // gets canceled before it gets scheduled. + if (readTask.IsCanceled || storeException is OperationCanceledException) + { + hasCancellationException = true; + cancellationException ??= storeException; + continue; + } + + using (ReferenceCountedDisposable disposableStoreResult = StoreResult.CreateStoreResult( + storeResponse, + storeException, + requiresValidLsn, + this.canUseLocalLSNBasedHeaders && readMode != ReadMode.Strong, + replicaHealthStatuses, + targetUri.Uri)) + { + StoreResult storeResult = disposableStoreResult.Target; + entity.RequestContext.RequestChargeTracker.AddCharge(storeResult.RequestCharge); + + if (storeResponse != null) + { + entity.RequestContext.ClientRequestStatistics.ContactedReplicas.Add(targetUri); + } + + if (storeException != null && storeException.InnerException is TransportException) + { + entity.RequestContext.ClientRequestStatistics.FailedReplicas.Add(targetUri); + } + + entity.RequestContext.ClientRequestStatistics.RecordResponse( + entity, + storeResult, + readTaskValuePair.Value.startTime, + endTime); + + if (storeResult.Exception != null) + { + StoreResult.VerifyCanContinueOnException(storeResult.Exception); + } + + if (storeResult.IsValid) + { + if (requestSessionToken == null + || (storeResult.SessionToken != null && requestSessionToken.IsValid(storeResult.SessionToken)) + || (!enforceSessionCheck && storeResult.StatusCode != StatusCodes.NotFound)) + { + storeResultList.Add(disposableStoreResult.TryAddReference()); + } + } + + hasGoneException |= storeResult.StatusCode == StatusCodes.Gone && storeResult.SubStatusCode != SubStatusCodes.NameCacheIsStale; + } + + // Perform address refresh in the background as soon as we hit a GoneException + if (hasGoneException && !entity.RequestContext.PerformedBackgroundAddressRefresh) + { + this.addressSelector.StartBackgroundAddressRefresh(entity); + entity.RequestContext.PerformedBackgroundAddressRefresh = true; + } + } + + if (storeResultList.Count >= replicaCountToRead) + { + return new ReadReplicaResult(false, storeResultList.GetValueAndDereference()); + } + + // Remaining replicas + replicasToRead = replicaCountToRead - storeResultList.Count; + } + + if (storeResultList.Count < replicaCountToRead) + { + DefaultTrace.TraceInformation("Could not get quorum number of responses. " + + "ValidResponsesReceived: {0} ResponsesExpected: {1}, ResolvedAddressCount: {2}, ResponsesString: {3}", + storeResultList.Count, replicaCountToRead, resolveApiResults.Count, String.Join(";", storeResultList.GetValue())); + + if (hasGoneException) + { + if (!entity.RequestContext.PerformLocalRefreshOnGoneException) + { + // If we are not supposed to act upon GoneExceptions here, just throw them + throw new GoneException(exceptionToThrow, subStatusCodeForException); + } + else if (!entity.RequestContext.ForceRefreshAddressCache) + { + // We could not obtain valid read quorum number of responses even when we went through all the secondary addresses + // Attempt force refresh and start over again. + return new ReadReplicaResult(retryWithForceRefresh: true, responses: storeResultList.GetValueAndDereference()); + } + } + else if (hasCancellationException) + { + // We did not get the required number of responses and we encountered task cancellation on some/all of the store read tasks. + // We propagate the first cancellation exception we've found, or a new OperationCanceledException if none. + // The latter case can happen when Task.IsCanceled = true. + throw cancellationException ?? new OperationCanceledException(); + } + } + + return new ReadReplicaResult(false, storeResultList.GetValueAndDereference()); + } + + private async Task ReadPrimaryInternalAsync( + DocumentServiceRequest entity, + bool requiresValidLsn, + bool useSessionToken, + bool isRetryAfterRefresh) + { + entity.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + + TransportAddressUri primaryUri = await this.addressSelector.ResolvePrimaryTransportAddressUriAsync( + entity, + entity.RequestContext.ForceRefreshAddressCache); + + if (useSessionToken) + { + SessionTokenHelper.SetPartitionLocalSessionToken(entity, this.sessionContainer); + } + else + { + // Remove whatever session token can be there in headers. + // We don't need it. If it is global - backend will not understand it. + // But there's no point in producing partition local session token. + entity.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); + } + + DateTime startTimeUtc = DateTime.UtcNow; + StrongBox endTimeUtc = new (); + using ReferenceCountedDisposable storeResult = await GetResult(entity, requiresValidLsn, primaryUri, endTimeUtc); + entity.RequestContext.ClientRequestStatistics.RecordResponse( + entity, + storeResult.Target, + startTimeUtc, + endTimeUtc.Value ?? DateTime.UtcNow); + + entity.RequestContext.RequestChargeTracker.AddCharge(storeResult.Target.RequestCharge); + + if (storeResult.Target.Exception != null) + { + StoreResult.VerifyCanContinueOnException(storeResult.Target.Exception); + } + + if (storeResult.Target.StatusCode == StatusCodes.Gone && storeResult.Target.SubStatusCode != SubStatusCodes.NameCacheIsStale) + { + if (isRetryAfterRefresh || + !entity.RequestContext.PerformLocalRefreshOnGoneException || + entity.RequestContext.ForceRefreshAddressCache) + { + // We can throw the exception if we have already performed an address refresh or if PerformLocalRefreshOnGoneException is false + throw new GoneException(RMResources.Gone, storeResult.Target.SubStatusCode); + } + + return new ReadReplicaResult(true, new List>()); + } + + return new ReadReplicaResult(false, new ReferenceCountedDisposable[] { storeResult.TryAddReference() }); + } + + private async Task> GetResult(DocumentServiceRequest entity, bool requiresValidLsn, TransportAddressUri primaryUri, StrongBox endTimeUtc) + { + ReferenceCountedDisposable storeResult; + List primaryReplicaHealthStatus = new () + { + primaryUri + .GetCurrentHealthState() + .GetHealthStatusDiagnosticString(), + }; + + try + { + this.UpdateContinuationTokenIfReadFeedOrQuery(entity); + (StoreResponse storeResponse, DateTime storeResponseEndTimeUtc) = await this.ReadFromStoreAsync( + primaryUri, + entity); + + endTimeUtc.Value = DateTime.UtcNow; + + storeResult = StoreResult.CreateStoreResult( + storeResponse, + null, + requiresValidLsn, + this.canUseLocalLSNBasedHeaders, + replicaHealthStatuses: primaryReplicaHealthStatus, + primaryUri.Uri); + } + catch (Exception exception) + { + DefaultTrace.TraceInformation("Exception {0} is thrown while doing Read Primary", exception); + storeResult = StoreResult.CreateStoreResult( + null, + exception, + requiresValidLsn, + this.canUseLocalLSNBasedHeaders, + replicaHealthStatuses: primaryReplicaHealthStatus, + primaryUri.Uri); + } + + return storeResult; + } + + private async Task<(StoreResponse, DateTime endTime)> ReadFromStoreAsync( + TransportAddressUri physicalAddress, + DocumentServiceRequest request) + { + request.RequestContext.TimeoutHelper.ThrowGoneIfElapsed(); + this.LastReadAddress = physicalAddress.ToString(); + + switch (request.OperationType) + { + case OperationType.Read: + case OperationType.Head: + case OperationType.HeadFeed: + case OperationType.SqlQuery: + case OperationType.ExecuteJavaScript: +#if !COSMOSCLIENT + case OperationType.MetadataCheckAccess: + case OperationType.GetStorageAuthToken: +#endif + { + StoreResponse result = await this.transportClient.InvokeResourceOperationAsync( + physicalAddress, + request); + return (result, DateTime.UtcNow); + } + + case OperationType.ReadFeed: + case OperationType.Query: + { + QueryRequestPerformanceActivity activity = CustomTypeExtensions.StartActivity(request); + StoreResponse result = await StoreReader.CompleteActivity(this.transportClient.InvokeResourceOperationAsync( + physicalAddress, + request), + activity); + return (result, DateTime.UtcNow); + } + default: + throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Unexpected operation type {0}", request.OperationType)); + } + } + + private void UpdateContinuationTokenIfReadFeedOrQuery(DocumentServiceRequest request) + { + if (request.OperationType != OperationType.ReadFeed && + request.OperationType != OperationType.Query) + { + return; + } + + string continuation = request.Continuation; + if (continuation != null) + { + int firstSemicolonPosition = continuation.IndexOf(';'); + // IndexOf returns -1 if ';' is not found + if (firstSemicolonPosition < 0) + { + return; + } + + int semicolonCount = 1; + for (int i = firstSemicolonPosition + 1; i < continuation.Length; i++) + { + if (continuation[i] == ';') + { + semicolonCount++; + if (semicolonCount >= 3) + { + break; + } + } + } + + if (semicolonCount < 3) + { + throw new BadRequestException(string.Format( + CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + continuation, + HttpConstants.HttpHeaders.Continuation)); + } + + request.Continuation = continuation.Substring(0, firstSemicolonPosition); + } + } + + private static async Task CompleteActivity(Task task, QueryRequestPerformanceActivity activity) + { + if (activity == null) + { + return await task; + } + else + { + StoreResponse response; + try + { + response = await task; + } + catch + { + activity.ActivityComplete(false); + throw; + } + + activity.ActivityComplete(true); + return response; + } + } + + #region PrivateResultClasses + private sealed class ReadReplicaResult : IDisposable + { + public ReadReplicaResult(bool retryWithForceRefresh, IList> responses) + { + this.RetryWithForceRefresh = retryWithForceRefresh; + this.StoreResultList = new(responses); + } + + public bool RetryWithForceRefresh { get; private set; } + + public StoreResultList StoreResultList { get; private set; } + + public void Dispose() + { + this.StoreResultList.Dispose(); + } + } + + /// + /// Disposable list of StoreResult object with ability to skip first object disposal or skip disposal for entire list. + /// + private class StoreResultList : IDisposable + { + private IList> value; + + public StoreResultList(IList> collection) + { + this.value = collection ?? throw new ArgumentNullException(); + } + + public void Add(ReferenceCountedDisposable storeResult) + { + this.GetValueOrThrow().Add(storeResult); + } + + public int Count => this.GetValueOrThrow().Count; + + public ReferenceCountedDisposable GetFirstStoreResultAndDereference() + { + IList> value = this.GetValueOrThrow(); + if (value.Count > 0) + { + ReferenceCountedDisposable result = value[0]; + this.value[0] = null; + return result; + } + + return null; + } + + public IList> GetValue() => this.GetValueOrThrow(); + + public IList> GetValueAndDereference() + { + IList> response = this.GetValueOrThrow(); + this.value = null; + return response; + } + + public void Dispose() + { + if (this.value != null) + { + for (int i = 0; i < this.value.Count; i++) + { + this.value[i]?.Dispose(); + } + } + } + + private IList> GetValueOrThrow() + { + if (this.value == null || (this.value.Count > 0 && this.value[0] == null)) + { + throw new InvalidOperationException("Call on the StoreResultList with deferenced collection"); + } + + return this.value; + } + } + #endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreResponse.cs b/Microsoft.Azure.Cosmos/src/direct/StoreResponse.cs index 3656b15c65..91ea4c8a0a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreResponse.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreResponse.cs @@ -1,152 +1,152 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.IO; - using System.Net; - using Microsoft.Azure.Documents.Collections; - - internal sealed class StoreResponse : IRetriableResponse - { - public int Status { get; set; } - - public INameValueCollection Headers { get; set; } - - public Stream ResponseBody { get; set; } - - public TransportRequestStats TransportRequestStats { get; set; } - - public long LSN - { - get - { - string value; - long result = -1; - if (this.TryGetHeaderValue(WFConstants.BackendHeaders.LSN, out value)) - { - if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) - { - return result; - } - } - - return -1; - } - } - - public string PartitionKeyRangeId - { - get - { - string value; - if (this.TryGetHeaderValue(WFConstants.BackendHeaders.PartitionKeyRangeId, out value)) - { - return value; - } - - return null; - } - } - - public long CollectionPartitionIndex - { - get - { - string value; - long result = -1; - if (this.TryGetHeaderValue(WFConstants.BackendHeaders.CollectionPartitionIndex, out value)) - { - if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) - { - return result; - } - } - - return -1; - } - } - - public long CollectionServiceIndex - { - get - { - string value; - long result = -1; - if (this.TryGetHeaderValue(WFConstants.BackendHeaders.CollectionServiceIndex, out value)) - { - if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) - { - return result; - } - } - - return -1; - } - } - - public string Continuation - { - get - { - string value; - if (this.TryGetHeaderValue(HttpConstants.HttpHeaders.Continuation, out value)) - { - return value; - } - - return null; - } - } - - public SubStatusCodes SubStatusCode => subStatusCode.Value; - - public HttpStatusCode StatusCode => (HttpStatusCode)this.Status; - - private Lazy subStatusCode; - - public StoreResponse() - { - this.subStatusCode = new Lazy(this.GetSubStatusCode); - } - - public bool TryGetHeaderValue( - string attribute, - out string value) - { - value = null; - if (this.Headers == null) - { - return false; - } - - value = this.Headers.Get(attribute); - return value != null; - } - - public void UpsertHeaderValue( - string headerName, - string headerValue) - { - this.Headers[headerName] = headerValue; - } - - private SubStatusCodes GetSubStatusCode() - { - SubStatusCodes value = SubStatusCodes.Unknown; - string valueSubStatus; - if (this.TryGetHeaderValue(WFConstants.BackendHeaders.SubStatus, out valueSubStatus)) - { - uint subStatus = 0; - if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out subStatus)) - { - value = (SubStatusCodes)subStatus; - } - } - - return value; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.IO; + using System.Net; + using Microsoft.Azure.Documents.Collections; + + internal sealed class StoreResponse : IRetriableResponse + { + public int Status { get; set; } + + public INameValueCollection Headers { get; set; } + + public Stream ResponseBody { get; set; } + + public TransportRequestStats TransportRequestStats { get; set; } + + public long LSN + { + get + { + string value; + long result = -1; + if (this.TryGetHeaderValue(WFConstants.BackendHeaders.LSN, out value)) + { + if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) + { + return result; + } + } + + return -1; + } + } + + public string PartitionKeyRangeId + { + get + { + string value; + if (this.TryGetHeaderValue(WFConstants.BackendHeaders.PartitionKeyRangeId, out value)) + { + return value; + } + + return null; + } + } + + public long CollectionPartitionIndex + { + get + { + string value; + long result = -1; + if (this.TryGetHeaderValue(WFConstants.BackendHeaders.CollectionPartitionIndex, out value)) + { + if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) + { + return result; + } + } + + return -1; + } + } + + public long CollectionServiceIndex + { + get + { + string value; + long result = -1; + if (this.TryGetHeaderValue(WFConstants.BackendHeaders.CollectionServiceIndex, out value)) + { + if (long.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) + { + return result; + } + } + + return -1; + } + } + + public string Continuation + { + get + { + string value; + if (this.TryGetHeaderValue(HttpConstants.HttpHeaders.Continuation, out value)) + { + return value; + } + + return null; + } + } + + public SubStatusCodes SubStatusCode => subStatusCode.Value; + + public HttpStatusCode StatusCode => (HttpStatusCode)this.Status; + + private Lazy subStatusCode; + + public StoreResponse() + { + this.subStatusCode = new Lazy(this.GetSubStatusCode); + } + + public bool TryGetHeaderValue( + string attribute, + out string value) + { + value = null; + if (this.Headers == null) + { + return false; + } + + value = this.Headers.Get(attribute); + return value != null; + } + + public void UpsertHeaderValue( + string headerName, + string headerValue) + { + this.Headers[headerName] = headerValue; + } + + private SubStatusCodes GetSubStatusCode() + { + SubStatusCodes value = SubStatusCodes.Unknown; + string valueSubStatus; + if (this.TryGetHeaderValue(WFConstants.BackendHeaders.SubStatus, out valueSubStatus)) + { + uint subStatus = 0; + if (uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out subStatus)) + { + value = (SubStatusCodes)subStatus; + } + } + + return value; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs index e6fefde124..f852382149 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs @@ -1,3913 +1,4045 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA StoreResponseNameValueCollection.tt - -namespace Microsoft.Azure.Documents.Collections -{ - using System; - using System.Collections; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Linq; - using System.Threading; - using Microsoft.Azure.Documents; - - /// - /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA StoreResponseNameValueCollection.tt - /// This should be a one to one mapping with RntbdConstants.Response header token properties. - /// This allows the TransportSerialization to directly set the property and avoid the dictionary overhead. - /// If the property does not exists please update the StoreResponseNameValueCollection.tt list to add the new field - /// - internal class StoreResponseNameValueCollection : INameValueCollection, IEnumerable> - { - private static readonly StringComparer DefaultStringComparer = StringComparer.OrdinalIgnoreCase; - - // this is null if it's never been added to, and is created in a thread safe manner via GetOrCreateLazyHeaders() - private Dictionary lazyNotCommonHeaders; - - // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. - // However, there are a few public API with NameValueCollection as return type, e.g. DocumentServiceResponse.ResponseHeaders and - // DocumentClientException.ResponseHeaders. - // - // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create - // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is - // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. - // - // Therefore, we want to keep the NameValueCollection consistent within the ResponseHeaders APIs call. In other words, - // once invoked, the ResponseHeaders will return the same NameValueCollection. - private NameValueCollection nameValueCollection = null; - - public string AadAppliedRoleAssignmentId { get; set; } - public string ActivityId { get; set; } - public string AnalyticalMigrationProgress { get; set; } - public string AppliedPolicyElementId { get; set; } - public string BackendRequestDurationMilliseconds { get; set; } - public string ByokEncryptionProgress { get; set; } - public string CapacityType { get; set; } - public string ChangeFeedInfo { get; set; } - public string CollectionIndexTransformationProgress { get; set; } - public string CollectionLazyIndexingProgress { get; set; } - public string CollectionPartitionIndex { get; set; } - public string CollectionSecurityIdentifier { get; set; } - public string CollectionServiceIndex { get; set; } - public string CollectionUniqueIndexReIndexProgress { get; set; } - public string CollectionUniqueKeysUnderReIndex { get; set; } - public string ConfirmedStoreChecksum { get; set; } - public string Continuation { get; set; } - public string CorrelatedActivityId { get; set; } - public string CurrentReplicaSetSize { get; set; } - public string CurrentResourceQuotaUsage { get; set; } - public string CurrentWriteQuorum { get; set; } - public string DatabaseAccountId { get; set; } - public string DisableRntbdChannel { get; set; } - public string ETag { get; set; } - public string GlobalCommittedLSN { get; set; } - public string HasTentativeWrites { get; set; } - public string HighestTentativeWriteLLSN { get; set; } - public string IndexingDirective { get; set; } - public string IndexUtilization { get; set; } - public string InstantScaleUpValue { get; set; } - public string IsOfferRestorePending { get; set; } - public string IsRUPerMinuteUsed { get; set; } - public string ItemCount { get; set; } - public string ItemLocalLSN { get; set; } - public string ItemLSN { get; set; } - public string LastStateChangeUtc { get; set; } - public string LocalLSN { get; set; } - public string LogResults { get; set; } - public string LSN { get; set; } - public string MaxContentLength { get; set; } - public string MaxResourceQuota { get; set; } - public string MergeProgressBlocked { get; set; } - public string MinGLSNForDocumentOperations { get; set; } - public string MinGLSNForTombstoneOperations { get; set; } - public string MinimumRUsForOffer { get; set; } - public string NumberOfReadRegions { get; set; } - public string OfferReplacePending { get; set; } - public string OfferReplacePendingForMerge { get; set; } - public string OldestActiveSchemaId { get; set; } - public string OwnerFullName { get; set; } - public string OwnerId { get; set; } - public string PartitionKeyRangeId { get; set; } - public string PartitionThroughputInfo { get; set; } - public string PendingPKDelete { get; set; } - public string PhysicalPartitionId { get; set; } - public string QueryExecutionInfo { get; set; } - public string QueryMetrics { get; set; } - public string QuorumAckedLocalLSN { get; set; } - public string QuorumAckedLSN { get; set; } - public string ReIndexerProgress { get; set; } - public string ReplicaStatusRevoked { get; set; } - public string ReplicatorLSNToGLSNDelta { get; set; } - public string ReplicatorLSNToLLSNDelta { get; set; } - public string RequestCharge { get; set; } - public string RequestValidationFailure { get; set; } - public string RequiresDistribution { get; set; } - public string ResourceId { get; set; } - public string RestoreState { get; set; } - public string RetryAfterInMilliseconds { get; set; } - public string SchemaVersion { get; set; } - public string ServerVersion { get; set; } - public string SessionToken { get; set; } - public string ShareThroughput { get; set; } - public string SoftMaxAllowedThroughput { get; set; } - public string SubStatus { get; set; } - public string TentativeStoreChecksum { get; set; } - public string TimeToLiveInSeconds { get; set; } - public string TotalAccountThroughput { get; set; } - public string TransportRequestID { get; set; } - public string UnflushedMergLogEntryCount { get; set; } - public string VectorClockLocalProgress { get; set; } - public string XDate { get; set; } - public string XPConfigurationSessionsCount { get; set; } - public string XPRole { get; set; } - - public StoreResponseNameValueCollection() - { - } - - private StoreResponseNameValueCollection(Dictionary lazyNotCommonHeaders) - { - this.lazyNotCommonHeaders = lazyNotCommonHeaders; - } - - public string this[string key] - { - get => this.Get(key); - set => this.Set(key, value); - } - - public void Add(INameValueCollection collection) - { - if (collection == null) - { - throw new ArgumentNullException(nameof(collection)); - } - - foreach (string key in collection.Keys()) - { - this.Set(key, collection[key]); - } - } - - public string[] AllKeys() - { - return this.Keys().ToArray(); - } - - public void Clear() - { - if (this.lazyNotCommonHeaders != null) - { - this.lazyNotCommonHeaders.Clear(); - } - - this.AadAppliedRoleAssignmentId = null; - this.ActivityId = null; - this.AnalyticalMigrationProgress = null; - this.AppliedPolicyElementId = null; - this.BackendRequestDurationMilliseconds = null; - this.ByokEncryptionProgress = null; - this.CapacityType = null; - this.ChangeFeedInfo = null; - this.CollectionIndexTransformationProgress = null; - this.CollectionLazyIndexingProgress = null; - this.CollectionPartitionIndex = null; - this.CollectionSecurityIdentifier = null; - this.CollectionServiceIndex = null; - this.CollectionUniqueIndexReIndexProgress = null; - this.CollectionUniqueKeysUnderReIndex = null; - this.ConfirmedStoreChecksum = null; - this.Continuation = null; - this.CorrelatedActivityId = null; - this.CurrentReplicaSetSize = null; - this.CurrentResourceQuotaUsage = null; - this.CurrentWriteQuorum = null; - this.DatabaseAccountId = null; - this.DisableRntbdChannel = null; - this.ETag = null; - this.GlobalCommittedLSN = null; - this.HasTentativeWrites = null; - this.HighestTentativeWriteLLSN = null; - this.IndexingDirective = null; - this.IndexUtilization = null; - this.InstantScaleUpValue = null; - this.IsOfferRestorePending = null; - this.IsRUPerMinuteUsed = null; - this.ItemCount = null; - this.ItemLocalLSN = null; - this.ItemLSN = null; - this.LastStateChangeUtc = null; - this.LocalLSN = null; - this.LogResults = null; - this.LSN = null; - this.MaxContentLength = null; - this.MaxResourceQuota = null; - this.MergeProgressBlocked = null; - this.MinGLSNForDocumentOperations = null; - this.MinGLSNForTombstoneOperations = null; - this.MinimumRUsForOffer = null; - this.NumberOfReadRegions = null; - this.OfferReplacePending = null; - this.OfferReplacePendingForMerge = null; - this.OldestActiveSchemaId = null; - this.OwnerFullName = null; - this.OwnerId = null; - this.PartitionKeyRangeId = null; - this.PartitionThroughputInfo = null; - this.PendingPKDelete = null; - this.PhysicalPartitionId = null; - this.QueryExecutionInfo = null; - this.QueryMetrics = null; - this.QuorumAckedLocalLSN = null; - this.QuorumAckedLSN = null; - this.ReIndexerProgress = null; - this.ReplicaStatusRevoked = null; - this.ReplicatorLSNToGLSNDelta = null; - this.ReplicatorLSNToLLSNDelta = null; - this.RequestCharge = null; - this.RequestValidationFailure = null; - this.RequiresDistribution = null; - this.ResourceId = null; - this.RestoreState = null; - this.RetryAfterInMilliseconds = null; - this.SchemaVersion = null; - this.ServerVersion = null; - this.SessionToken = null; - this.ShareThroughput = null; - this.SoftMaxAllowedThroughput = null; - this.SubStatus = null; - this.TentativeStoreChecksum = null; - this.TimeToLiveInSeconds = null; - this.TotalAccountThroughput = null; - this.TransportRequestID = null; - this.UnflushedMergLogEntryCount = null; - this.VectorClockLocalProgress = null; - this.XDate = null; - this.XPConfigurationSessionsCount = null; - this.XPRole = null; - - } - - public INameValueCollection Clone() - { - Dictionary cloneNotCommonHeaders = null; - if (this.lazyNotCommonHeaders != null) - { - cloneNotCommonHeaders = new Dictionary(this.lazyNotCommonHeaders, StoreResponseNameValueCollection.DefaultStringComparer); - } - - StoreResponseNameValueCollection cloneHeaders = new StoreResponseNameValueCollection(cloneNotCommonHeaders) - { - AadAppliedRoleAssignmentId = this.AadAppliedRoleAssignmentId, - ActivityId = this.ActivityId, - AnalyticalMigrationProgress = this.AnalyticalMigrationProgress, - AppliedPolicyElementId = this.AppliedPolicyElementId, - BackendRequestDurationMilliseconds = this.BackendRequestDurationMilliseconds, - ByokEncryptionProgress = this.ByokEncryptionProgress, - CapacityType = this.CapacityType, - ChangeFeedInfo = this.ChangeFeedInfo, - CollectionIndexTransformationProgress = this.CollectionIndexTransformationProgress, - CollectionLazyIndexingProgress = this.CollectionLazyIndexingProgress, - CollectionPartitionIndex = this.CollectionPartitionIndex, - CollectionSecurityIdentifier = this.CollectionSecurityIdentifier, - CollectionServiceIndex = this.CollectionServiceIndex, - CollectionUniqueIndexReIndexProgress = this.CollectionUniqueIndexReIndexProgress, - CollectionUniqueKeysUnderReIndex = this.CollectionUniqueKeysUnderReIndex, - ConfirmedStoreChecksum = this.ConfirmedStoreChecksum, - Continuation = this.Continuation, - CorrelatedActivityId = this.CorrelatedActivityId, - CurrentReplicaSetSize = this.CurrentReplicaSetSize, - CurrentResourceQuotaUsage = this.CurrentResourceQuotaUsage, - CurrentWriteQuorum = this.CurrentWriteQuorum, - DatabaseAccountId = this.DatabaseAccountId, - DisableRntbdChannel = this.DisableRntbdChannel, - ETag = this.ETag, - GlobalCommittedLSN = this.GlobalCommittedLSN, - HasTentativeWrites = this.HasTentativeWrites, - HighestTentativeWriteLLSN = this.HighestTentativeWriteLLSN, - IndexingDirective = this.IndexingDirective, - IndexUtilization = this.IndexUtilization, - InstantScaleUpValue = this.InstantScaleUpValue, - IsOfferRestorePending = this.IsOfferRestorePending, - IsRUPerMinuteUsed = this.IsRUPerMinuteUsed, - ItemCount = this.ItemCount, - ItemLocalLSN = this.ItemLocalLSN, - ItemLSN = this.ItemLSN, - LastStateChangeUtc = this.LastStateChangeUtc, - LocalLSN = this.LocalLSN, - LogResults = this.LogResults, - LSN = this.LSN, - MaxContentLength = this.MaxContentLength, - MaxResourceQuota = this.MaxResourceQuota, - MergeProgressBlocked = this.MergeProgressBlocked, - MinGLSNForDocumentOperations = this.MinGLSNForDocumentOperations, - MinGLSNForTombstoneOperations = this.MinGLSNForTombstoneOperations, - MinimumRUsForOffer = this.MinimumRUsForOffer, - NumberOfReadRegions = this.NumberOfReadRegions, - OfferReplacePending = this.OfferReplacePending, - OfferReplacePendingForMerge = this.OfferReplacePendingForMerge, - OldestActiveSchemaId = this.OldestActiveSchemaId, - OwnerFullName = this.OwnerFullName, - OwnerId = this.OwnerId, - PartitionKeyRangeId = this.PartitionKeyRangeId, - PartitionThroughputInfo = this.PartitionThroughputInfo, - PendingPKDelete = this.PendingPKDelete, - PhysicalPartitionId = this.PhysicalPartitionId, - QueryExecutionInfo = this.QueryExecutionInfo, - QueryMetrics = this.QueryMetrics, - QuorumAckedLocalLSN = this.QuorumAckedLocalLSN, - QuorumAckedLSN = this.QuorumAckedLSN, - ReIndexerProgress = this.ReIndexerProgress, - ReplicaStatusRevoked = this.ReplicaStatusRevoked, - ReplicatorLSNToGLSNDelta = this.ReplicatorLSNToGLSNDelta, - ReplicatorLSNToLLSNDelta = this.ReplicatorLSNToLLSNDelta, - RequestCharge = this.RequestCharge, - RequestValidationFailure = this.RequestValidationFailure, - RequiresDistribution = this.RequiresDistribution, - ResourceId = this.ResourceId, - RestoreState = this.RestoreState, - RetryAfterInMilliseconds = this.RetryAfterInMilliseconds, - SchemaVersion = this.SchemaVersion, - ServerVersion = this.ServerVersion, - SessionToken = this.SessionToken, - ShareThroughput = this.ShareThroughput, - SoftMaxAllowedThroughput = this.SoftMaxAllowedThroughput, - SubStatus = this.SubStatus, - TentativeStoreChecksum = this.TentativeStoreChecksum, - TimeToLiveInSeconds = this.TimeToLiveInSeconds, - TotalAccountThroughput = this.TotalAccountThroughput, - TransportRequestID = this.TransportRequestID, - UnflushedMergLogEntryCount = this.UnflushedMergLogEntryCount, - VectorClockLocalProgress = this.VectorClockLocalProgress, - XDate = this.XDate, - XPConfigurationSessionsCount = this.XPConfigurationSessionsCount, - XPRole = this.XPRole, - }; - - return cloneHeaders; - } - - public int Count() - { - return this.Keys().Count(); - } - - public IEnumerator GetEnumerator() - { - return this.Keys().GetEnumerator(); - } - - IEnumerator> IEnumerable>.GetEnumerator() - { - if (this.ActivityId != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); - } - if (this.LastStateChangeUtc != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.LastStateChangeUtc, this.LastStateChangeUtc); - } - if (this.Continuation != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.Continuation, this.Continuation); - } - if (this.ETag != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ETag, this.ETag); - } - if (this.RetryAfterInMilliseconds != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, this.RetryAfterInMilliseconds); - } - if (this.IndexingDirective != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); - } - if (this.MaxResourceQuota != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.MaxResourceQuota, this.MaxResourceQuota); - } - if (this.CurrentResourceQuotaUsage != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, this.CurrentResourceQuotaUsage); - } - if (this.SchemaVersion != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.SchemaVersion, this.SchemaVersion); - } - if (this.CollectionPartitionIndex != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); - } - if (this.CollectionServiceIndex != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); - } - if (this.LSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.LSN, this.LSN); - } - if (this.ItemCount != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ItemCount, this.ItemCount); - } - if (this.RequestCharge != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.RequestCharge, this.RequestCharge); - } - if (this.OwnerFullName != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.OwnerFullName, this.OwnerFullName); - } - if (this.OwnerId != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.OwnerId, this.OwnerId); - } - if (this.DatabaseAccountId != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.DatabaseAccountId, this.DatabaseAccountId); - } - if (this.QuorumAckedLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.QuorumAckedLSN, this.QuorumAckedLSN); - } - if (this.RequestValidationFailure != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.RequestValidationFailure, this.RequestValidationFailure); - } - if (this.SubStatus != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.SubStatus, this.SubStatus); - } - if (this.CollectionIndexTransformationProgress != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, this.CollectionIndexTransformationProgress); - } - if (this.CurrentWriteQuorum != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CurrentWriteQuorum, this.CurrentWriteQuorum); - } - if (this.CurrentReplicaSetSize != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CurrentReplicaSetSize, this.CurrentReplicaSetSize); - } - if (this.CollectionLazyIndexingProgress != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, this.CollectionLazyIndexingProgress); - } - if (this.PartitionKeyRangeId != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); - } - if (this.LogResults != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.LogResults, this.LogResults); - } - if (this.XPRole != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.XPRole, this.XPRole); - } - if (this.IsRUPerMinuteUsed != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.IsRUPerMinuteUsed, this.IsRUPerMinuteUsed); - } - if (this.QueryMetrics != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.QueryMetrics, this.QueryMetrics); - } - if (this.QueryExecutionInfo != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.QueryExecutionInfo, this.QueryExecutionInfo); - } - if (this.IndexUtilization != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.IndexUtilization, this.IndexUtilization); - } - if (this.GlobalCommittedLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.GlobalCommittedLSN, this.GlobalCommittedLSN); - } - if (this.NumberOfReadRegions != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.NumberOfReadRegions, this.NumberOfReadRegions); - } - if (this.OfferReplacePending != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.OfferReplacePending, this.OfferReplacePending); - } - if (this.ItemLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ItemLSN, this.ItemLSN); - } - if (this.RestoreState != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.RestoreState, this.RestoreState); - } - if (this.CollectionSecurityIdentifier != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionSecurityIdentifier, this.CollectionSecurityIdentifier); - } - if (this.TransportRequestID != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); - } - if (this.ShareThroughput != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); - } - if (this.DisableRntbdChannel != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.DisableRntbdChannel, this.DisableRntbdChannel); - } - if (this.XDate != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.XDate, this.XDate); - } - if (this.LocalLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.LocalLSN, this.LocalLSN); - } - if (this.QuorumAckedLocalLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.QuorumAckedLocalLSN, this.QuorumAckedLocalLSN); - } - if (this.ItemLocalLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ItemLocalLSN, this.ItemLocalLSN); - } - if (this.HasTentativeWrites != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.HasTentativeWrites, this.HasTentativeWrites); - } - if (this.SessionToken != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); - } - if (this.ReplicatorLSNToGLSNDelta != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, this.ReplicatorLSNToGLSNDelta); - } - if (this.ReplicatorLSNToLLSNDelta != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, this.ReplicatorLSNToLLSNDelta); - } - if (this.VectorClockLocalProgress != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.VectorClockLocalProgress, this.VectorClockLocalProgress); - } - if (this.MinimumRUsForOffer != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.MinimumRUsForOffer, this.MinimumRUsForOffer); - } - if (this.XPConfigurationSessionsCount != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.XPConfigurationSessionsCount, this.XPConfigurationSessionsCount); - } - if (this.UnflushedMergLogEntryCount != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, this.UnflushedMergLogEntryCount); - } - if (this.ResourceId != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ResourceId, this.ResourceId); - } - if (this.TimeToLiveInSeconds != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); - } - if (this.ReplicaStatusRevoked != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicaStatusRevoked, this.ReplicaStatusRevoked); - } - if (this.SoftMaxAllowedThroughput != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, this.SoftMaxAllowedThroughput); - } - if (this.BackendRequestDurationMilliseconds != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, this.BackendRequestDurationMilliseconds); - } - if (this.ServerVersion != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ServerVersion, this.ServerVersion); - } - if (this.ConfirmedStoreChecksum != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, this.ConfirmedStoreChecksum); - } - if (this.TentativeStoreChecksum != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.TentativeStoreChecksum, this.TentativeStoreChecksum); - } - if (this.CorrelatedActivityId != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CorrelatedActivityId, this.CorrelatedActivityId); - } - if (this.PendingPKDelete != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.PendingPKDelete, this.PendingPKDelete); - } - if (this.AadAppliedRoleAssignmentId != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, this.AadAppliedRoleAssignmentId); - } - if (this.CollectionUniqueIndexReIndexProgress != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, this.CollectionUniqueIndexReIndexProgress); - } - if (this.CollectionUniqueKeysUnderReIndex != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, this.CollectionUniqueKeysUnderReIndex); - } - if (this.AnalyticalMigrationProgress != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.AnalyticalMigrationProgress, this.AnalyticalMigrationProgress); - } - if (this.TotalAccountThroughput != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.TotalAccountThroughput, this.TotalAccountThroughput); - } - if (this.ByokEncryptionProgress != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ByokEncryptionProgress, this.ByokEncryptionProgress); - } - if (this.AppliedPolicyElementId != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.AppliedPolicyElementId, this.AppliedPolicyElementId); - } - if (this.MergeProgressBlocked != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.MergeProgressBlocked, this.MergeProgressBlocked); - } - if (this.ChangeFeedInfo != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.ChangeFeedInfo, this.ChangeFeedInfo); - } - if (this.ReIndexerProgress != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.ReIndexerProgress, this.ReIndexerProgress); - } - if (this.OfferReplacePendingForMerge != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.OfferReplacePendingForMerge, this.OfferReplacePendingForMerge); - } - if (this.OldestActiveSchemaId != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.OldestActiveSchemaId, this.OldestActiveSchemaId); - } - if (this.PhysicalPartitionId != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.PhysicalPartitionId, this.PhysicalPartitionId); - } - if (this.MaxContentLength != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.MaxContentLength, this.MaxContentLength); - } - if (this.IsOfferRestorePending != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.IsOfferRestorePending, this.IsOfferRestorePending); - } - if (this.InstantScaleUpValue != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.InstantScaleUpValue, this.InstantScaleUpValue); - } - if (this.RequiresDistribution != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.RequiresDistribution, this.RequiresDistribution); - } - if (this.CapacityType != null) - { - yield return new KeyValuePair(HttpConstants.HttpHeaders.CapacityType, this.CapacityType); - } - if (this.MinGLSNForTombstoneOperations != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, this.MinGLSNForTombstoneOperations); - } - if (this.MinGLSNForDocumentOperations != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, this.MinGLSNForDocumentOperations); - } - if (this.HighestTentativeWriteLLSN != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); - } - if (this.PartitionThroughputInfo != null) - { - yield return new KeyValuePair(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); - } - - if (this.lazyNotCommonHeaders != null) - { - foreach (KeyValuePair kvp in this.lazyNotCommonHeaders) - { - yield return kvp; - } - } - } - - public string[] GetValues(string key) - { - string value = this.Get(key); - if (value != null) - { - return new string[] { value }; - } - - return null; - } - - public IEnumerable Keys() - { - if (this.ActivityId != null) - { - yield return HttpConstants.HttpHeaders.ActivityId; - } - if (this.LastStateChangeUtc != null) - { - yield return HttpConstants.HttpHeaders.LastStateChangeUtc; - } - if (this.Continuation != null) - { - yield return HttpConstants.HttpHeaders.Continuation; - } - if (this.ETag != null) - { - yield return HttpConstants.HttpHeaders.ETag; - } - if (this.RetryAfterInMilliseconds != null) - { - yield return HttpConstants.HttpHeaders.RetryAfterInMilliseconds; - } - if (this.IndexingDirective != null) - { - yield return HttpConstants.HttpHeaders.IndexingDirective; - } - if (this.MaxResourceQuota != null) - { - yield return HttpConstants.HttpHeaders.MaxResourceQuota; - } - if (this.CurrentResourceQuotaUsage != null) - { - yield return HttpConstants.HttpHeaders.CurrentResourceQuotaUsage; - } - if (this.SchemaVersion != null) - { - yield return HttpConstants.HttpHeaders.SchemaVersion; - } - if (this.CollectionPartitionIndex != null) - { - yield return WFConstants.BackendHeaders.CollectionPartitionIndex; - } - if (this.CollectionServiceIndex != null) - { - yield return WFConstants.BackendHeaders.CollectionServiceIndex; - } - if (this.LSN != null) - { - yield return WFConstants.BackendHeaders.LSN; - } - if (this.ItemCount != null) - { - yield return HttpConstants.HttpHeaders.ItemCount; - } - if (this.RequestCharge != null) - { - yield return HttpConstants.HttpHeaders.RequestCharge; - } - if (this.OwnerFullName != null) - { - yield return HttpConstants.HttpHeaders.OwnerFullName; - } - if (this.OwnerId != null) - { - yield return HttpConstants.HttpHeaders.OwnerId; - } - if (this.DatabaseAccountId != null) - { - yield return WFConstants.BackendHeaders.DatabaseAccountId; - } - if (this.QuorumAckedLSN != null) - { - yield return WFConstants.BackendHeaders.QuorumAckedLSN; - } - if (this.RequestValidationFailure != null) - { - yield return WFConstants.BackendHeaders.RequestValidationFailure; - } - if (this.SubStatus != null) - { - yield return WFConstants.BackendHeaders.SubStatus; - } - if (this.CollectionIndexTransformationProgress != null) - { - yield return HttpConstants.HttpHeaders.CollectionIndexTransformationProgress; - } - if (this.CurrentWriteQuorum != null) - { - yield return WFConstants.BackendHeaders.CurrentWriteQuorum; - } - if (this.CurrentReplicaSetSize != null) - { - yield return WFConstants.BackendHeaders.CurrentReplicaSetSize; - } - if (this.CollectionLazyIndexingProgress != null) - { - yield return HttpConstants.HttpHeaders.CollectionLazyIndexingProgress; - } - if (this.PartitionKeyRangeId != null) - { - yield return WFConstants.BackendHeaders.PartitionKeyRangeId; - } - if (this.LogResults != null) - { - yield return HttpConstants.HttpHeaders.LogResults; - } - if (this.XPRole != null) - { - yield return WFConstants.BackendHeaders.XPRole; - } - if (this.IsRUPerMinuteUsed != null) - { - yield return WFConstants.BackendHeaders.IsRUPerMinuteUsed; - } - if (this.QueryMetrics != null) - { - yield return WFConstants.BackendHeaders.QueryMetrics; - } - if (this.QueryExecutionInfo != null) - { - yield return WFConstants.BackendHeaders.QueryExecutionInfo; - } - if (this.IndexUtilization != null) - { - yield return WFConstants.BackendHeaders.IndexUtilization; - } - if (this.GlobalCommittedLSN != null) - { - yield return WFConstants.BackendHeaders.GlobalCommittedLSN; - } - if (this.NumberOfReadRegions != null) - { - yield return WFConstants.BackendHeaders.NumberOfReadRegions; - } - if (this.OfferReplacePending != null) - { - yield return WFConstants.BackendHeaders.OfferReplacePending; - } - if (this.ItemLSN != null) - { - yield return WFConstants.BackendHeaders.ItemLSN; - } - if (this.RestoreState != null) - { - yield return WFConstants.BackendHeaders.RestoreState; - } - if (this.CollectionSecurityIdentifier != null) - { - yield return WFConstants.BackendHeaders.CollectionSecurityIdentifier; - } - if (this.TransportRequestID != null) - { - yield return HttpConstants.HttpHeaders.TransportRequestID; - } - if (this.ShareThroughput != null) - { - yield return WFConstants.BackendHeaders.ShareThroughput; - } - if (this.DisableRntbdChannel != null) - { - yield return HttpConstants.HttpHeaders.DisableRntbdChannel; - } - if (this.XDate != null) - { - yield return HttpConstants.HttpHeaders.XDate; - } - if (this.LocalLSN != null) - { - yield return WFConstants.BackendHeaders.LocalLSN; - } - if (this.QuorumAckedLocalLSN != null) - { - yield return WFConstants.BackendHeaders.QuorumAckedLocalLSN; - } - if (this.ItemLocalLSN != null) - { - yield return WFConstants.BackendHeaders.ItemLocalLSN; - } - if (this.HasTentativeWrites != null) - { - yield return WFConstants.BackendHeaders.HasTentativeWrites; - } - if (this.SessionToken != null) - { - yield return HttpConstants.HttpHeaders.SessionToken; - } - if (this.ReplicatorLSNToGLSNDelta != null) - { - yield return WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta; - } - if (this.ReplicatorLSNToLLSNDelta != null) - { - yield return WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta; - } - if (this.VectorClockLocalProgress != null) - { - yield return WFConstants.BackendHeaders.VectorClockLocalProgress; - } - if (this.MinimumRUsForOffer != null) - { - yield return WFConstants.BackendHeaders.MinimumRUsForOffer; - } - if (this.XPConfigurationSessionsCount != null) - { - yield return WFConstants.BackendHeaders.XPConfigurationSessionsCount; - } - if (this.UnflushedMergLogEntryCount != null) - { - yield return WFConstants.BackendHeaders.UnflushedMergLogEntryCount; - } - if (this.ResourceId != null) - { - yield return WFConstants.BackendHeaders.ResourceId; - } - if (this.TimeToLiveInSeconds != null) - { - yield return WFConstants.BackendHeaders.TimeToLiveInSeconds; - } - if (this.ReplicaStatusRevoked != null) - { - yield return WFConstants.BackendHeaders.ReplicaStatusRevoked; - } - if (this.SoftMaxAllowedThroughput != null) - { - yield return WFConstants.BackendHeaders.SoftMaxAllowedThroughput; - } - if (this.BackendRequestDurationMilliseconds != null) - { - yield return HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds; - } - if (this.ServerVersion != null) - { - yield return HttpConstants.HttpHeaders.ServerVersion; - } - if (this.ConfirmedStoreChecksum != null) - { - yield return HttpConstants.HttpHeaders.ConfirmedStoreChecksum; - } - if (this.TentativeStoreChecksum != null) - { - yield return HttpConstants.HttpHeaders.TentativeStoreChecksum; - } - if (this.CorrelatedActivityId != null) - { - yield return WFConstants.BackendHeaders.CorrelatedActivityId; - } - if (this.PendingPKDelete != null) - { - yield return WFConstants.BackendHeaders.PendingPKDelete; - } - if (this.AadAppliedRoleAssignmentId != null) - { - yield return HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId; - } - if (this.CollectionUniqueIndexReIndexProgress != null) - { - yield return WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress; - } - if (this.CollectionUniqueKeysUnderReIndex != null) - { - yield return WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex; - } - if (this.AnalyticalMigrationProgress != null) - { - yield return WFConstants.BackendHeaders.AnalyticalMigrationProgress; - } - if (this.TotalAccountThroughput != null) - { - yield return HttpConstants.HttpHeaders.TotalAccountThroughput; - } - if (this.ByokEncryptionProgress != null) - { - yield return WFConstants.BackendHeaders.ByokEncryptionProgress; - } - if (this.AppliedPolicyElementId != null) - { - yield return HttpConstants.HttpHeaders.AppliedPolicyElementId; - } - if (this.MergeProgressBlocked != null) - { - yield return WFConstants.BackendHeaders.MergeProgressBlocked; - } - if (this.ChangeFeedInfo != null) - { - yield return HttpConstants.HttpHeaders.ChangeFeedInfo; - } - if (this.ReIndexerProgress != null) - { - yield return WFConstants.BackendHeaders.ReIndexerProgress; - } - if (this.OfferReplacePendingForMerge != null) - { - yield return WFConstants.BackendHeaders.OfferReplacePendingForMerge; - } - if (this.OldestActiveSchemaId != null) - { - yield return WFConstants.BackendHeaders.OldestActiveSchemaId; - } - if (this.PhysicalPartitionId != null) - { - yield return HttpConstants.HttpHeaders.PhysicalPartitionId; - } - if (this.MaxContentLength != null) - { - yield return HttpConstants.HttpHeaders.MaxContentLength; - } - if (this.IsOfferRestorePending != null) - { - yield return HttpConstants.HttpHeaders.IsOfferRestorePending; - } - if (this.InstantScaleUpValue != null) - { - yield return HttpConstants.HttpHeaders.InstantScaleUpValue; - } - if (this.RequiresDistribution != null) - { - yield return WFConstants.BackendHeaders.RequiresDistribution; - } - if (this.CapacityType != null) - { - yield return HttpConstants.HttpHeaders.CapacityType; - } - if (this.MinGLSNForTombstoneOperations != null) - { - yield return WFConstants.BackendHeaders.MinGLSNForTombstoneOperations; - } - if (this.MinGLSNForDocumentOperations != null) - { - yield return WFConstants.BackendHeaders.MinGLSNForDocumentOperations; - } - if (this.HighestTentativeWriteLLSN != null) - { - yield return WFConstants.BackendHeaders.HighestTentativeWriteLLSN; - } - if (this.PartitionThroughputInfo != null) - { - yield return WFConstants.BackendHeaders.PartitionThroughputInfo; - } - - if (this.lazyNotCommonHeaders != null) - { - foreach (string key in this.lazyNotCommonHeaders.Keys) - { - yield return key; - } - } - } - - public NameValueCollection ToNameValueCollection() - { - // Note: See comment on line 34 of this file for the implementation. We need to respect current contracts - // for Backend Gateway. - if (this.nameValueCollection == null) - { - lock (this) - { - if (this.nameValueCollection == null) - { - this.nameValueCollection = new NameValueCollection(this.Count(), StoreResponseNameValueCollection.DefaultStringComparer); - - if (this.ActivityId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); - } - if (this.LastStateChangeUtc != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.LastStateChangeUtc, this.LastStateChangeUtc); - } - if (this.Continuation != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.Continuation, this.Continuation); - } - if (this.ETag != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ETag, this.ETag); - } - if (this.RetryAfterInMilliseconds != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, this.RetryAfterInMilliseconds); - } - if (this.IndexingDirective != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); - } - if (this.MaxResourceQuota != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxResourceQuota, this.MaxResourceQuota); - } - if (this.CurrentResourceQuotaUsage != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, this.CurrentResourceQuotaUsage); - } - if (this.SchemaVersion != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SchemaVersion, this.SchemaVersion); - } - if (this.CollectionPartitionIndex != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); - } - if (this.CollectionServiceIndex != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); - } - if (this.LSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.LSN, this.LSN); - } - if (this.ItemCount != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ItemCount, this.ItemCount); - } - if (this.RequestCharge != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.RequestCharge, this.RequestCharge); - } - if (this.OwnerFullName != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.OwnerFullName, this.OwnerFullName); - } - if (this.OwnerId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.OwnerId, this.OwnerId); - } - if (this.DatabaseAccountId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.DatabaseAccountId, this.DatabaseAccountId); - } - if (this.QuorumAckedLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.QuorumAckedLSN, this.QuorumAckedLSN); - } - if (this.RequestValidationFailure != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RequestValidationFailure, this.RequestValidationFailure); - } - if (this.SubStatus != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SubStatus, this.SubStatus); - } - if (this.CollectionIndexTransformationProgress != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, this.CollectionIndexTransformationProgress); - } - if (this.CurrentWriteQuorum != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CurrentWriteQuorum, this.CurrentWriteQuorum); - } - if (this.CurrentReplicaSetSize != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CurrentReplicaSetSize, this.CurrentReplicaSetSize); - } - if (this.CollectionLazyIndexingProgress != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, this.CollectionLazyIndexingProgress); - } - if (this.PartitionKeyRangeId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); - } - if (this.LogResults != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.LogResults, this.LogResults); - } - if (this.XPRole != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.XPRole, this.XPRole); - } - if (this.IsRUPerMinuteUsed != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRUPerMinuteUsed, this.IsRUPerMinuteUsed); - } - if (this.QueryMetrics != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.QueryMetrics, this.QueryMetrics); - } - if (this.QueryExecutionInfo != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.QueryExecutionInfo, this.QueryExecutionInfo); - } - if (this.IndexUtilization != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.IndexUtilization, this.IndexUtilization); - } - if (this.GlobalCommittedLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.GlobalCommittedLSN, this.GlobalCommittedLSN); - } - if (this.NumberOfReadRegions != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.NumberOfReadRegions, this.NumberOfReadRegions); - } - if (this.OfferReplacePending != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.OfferReplacePending, this.OfferReplacePending); - } - if (this.ItemLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ItemLSN, this.ItemLSN); - } - if (this.RestoreState != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RestoreState, this.RestoreState); - } - if (this.CollectionSecurityIdentifier != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionSecurityIdentifier, this.CollectionSecurityIdentifier); - } - if (this.TransportRequestID != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); - } - if (this.ShareThroughput != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); - } - if (this.DisableRntbdChannel != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.DisableRntbdChannel, this.DisableRntbdChannel); - } - if (this.XDate != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.XDate, this.XDate); - } - if (this.LocalLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.LocalLSN, this.LocalLSN); - } - if (this.QuorumAckedLocalLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.QuorumAckedLocalLSN, this.QuorumAckedLocalLSN); - } - if (this.ItemLocalLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ItemLocalLSN, this.ItemLocalLSN); - } - if (this.HasTentativeWrites != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.HasTentativeWrites, this.HasTentativeWrites); - } - if (this.SessionToken != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); - } - if (this.ReplicatorLSNToGLSNDelta != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, this.ReplicatorLSNToGLSNDelta); - } - if (this.ReplicatorLSNToLLSNDelta != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, this.ReplicatorLSNToLLSNDelta); - } - if (this.VectorClockLocalProgress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.VectorClockLocalProgress, this.VectorClockLocalProgress); - } - if (this.MinimumRUsForOffer != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.MinimumRUsForOffer, this.MinimumRUsForOffer); - } - if (this.XPConfigurationSessionsCount != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.XPConfigurationSessionsCount, this.XPConfigurationSessionsCount); - } - if (this.UnflushedMergLogEntryCount != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, this.UnflushedMergLogEntryCount); - } - if (this.ResourceId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceId, this.ResourceId); - } - if (this.TimeToLiveInSeconds != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); - } - if (this.ReplicaStatusRevoked != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicaStatusRevoked, this.ReplicaStatusRevoked); - } - if (this.SoftMaxAllowedThroughput != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, this.SoftMaxAllowedThroughput); - } - if (this.BackendRequestDurationMilliseconds != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, this.BackendRequestDurationMilliseconds); - } - if (this.ServerVersion != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ServerVersion, this.ServerVersion); - } - if (this.ConfirmedStoreChecksum != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, this.ConfirmedStoreChecksum); - } - if (this.TentativeStoreChecksum != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TentativeStoreChecksum, this.TentativeStoreChecksum); - } - if (this.CorrelatedActivityId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CorrelatedActivityId, this.CorrelatedActivityId); - } - if (this.PendingPKDelete != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PendingPKDelete, this.PendingPKDelete); - } - if (this.AadAppliedRoleAssignmentId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, this.AadAppliedRoleAssignmentId); - } - if (this.CollectionUniqueIndexReIndexProgress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, this.CollectionUniqueIndexReIndexProgress); - } - if (this.CollectionUniqueKeysUnderReIndex != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, this.CollectionUniqueKeysUnderReIndex); - } - if (this.AnalyticalMigrationProgress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.AnalyticalMigrationProgress, this.AnalyticalMigrationProgress); - } - if (this.TotalAccountThroughput != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.TotalAccountThroughput, this.TotalAccountThroughput); - } - if (this.ByokEncryptionProgress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ByokEncryptionProgress, this.ByokEncryptionProgress); - } - if (this.AppliedPolicyElementId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.AppliedPolicyElementId, this.AppliedPolicyElementId); - } - if (this.MergeProgressBlocked != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.MergeProgressBlocked, this.MergeProgressBlocked); - } - if (this.ChangeFeedInfo != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedInfo, this.ChangeFeedInfo); - } - if (this.ReIndexerProgress != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.ReIndexerProgress, this.ReIndexerProgress); - } - if (this.OfferReplacePendingForMerge != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.OfferReplacePendingForMerge, this.OfferReplacePendingForMerge); - } - if (this.OldestActiveSchemaId != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.OldestActiveSchemaId, this.OldestActiveSchemaId); - } - if (this.PhysicalPartitionId != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.PhysicalPartitionId, this.PhysicalPartitionId); - } - if (this.MaxContentLength != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxContentLength, this.MaxContentLength); - } - if (this.IsOfferRestorePending != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsOfferRestorePending, this.IsOfferRestorePending); - } - if (this.InstantScaleUpValue != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.InstantScaleUpValue, this.InstantScaleUpValue); - } - if (this.RequiresDistribution != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.RequiresDistribution, this.RequiresDistribution); - } - if (this.CapacityType != null) - { - this.nameValueCollection.Add(HttpConstants.HttpHeaders.CapacityType, this.CapacityType); - } - if (this.MinGLSNForTombstoneOperations != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, this.MinGLSNForTombstoneOperations); - } - if (this.MinGLSNForDocumentOperations != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, this.MinGLSNForDocumentOperations); - } - if (this.HighestTentativeWriteLLSN != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); - } - if (this.PartitionThroughputInfo != null) - { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); - } - if(this.lazyNotCommonHeaders != null) - { - foreach (KeyValuePair keyValuePair in this.lazyNotCommonHeaders) - { - this.nameValueCollection.Add(keyValuePair.Key, keyValuePair.Value); - } - } - } - } - } - - return this.nameValueCollection; - } - - public void Remove(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - this.UpdateHelper( - key: key, - value: null, - throwIfAlreadyExists: false); - } - - public string Get(string key) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - switch (key.Length) - { - case 3: - if (string.Equals(WFConstants.BackendHeaders.LSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.LSN; - } - - break; - case 4: - if (string.Equals(HttpConstants.HttpHeaders.ETag, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ETag; - } - - break; - case 9: - if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) - { - return this.XDate; - } - - break; - case 12: - if (string.Equals(WFConstants.BackendHeaders.XPRole, key, StringComparison.OrdinalIgnoreCase)) - { - return this.XPRole; - } - - break; - case 13: - if (string.Equals(WFConstants.BackendHeaders.ItemLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ItemLSN; - } - - break; - case 14: - if (string.Equals(WFConstants.BackendHeaders.SubStatus, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SubStatus; - } - - break; - case 15: - if (string.Equals(HttpConstants.HttpHeaders.ItemCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ItemCount; - } - - break; - case 16: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) - { - return this.ActivityId; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.LocalLSN, key)) - { - return this.LocalLSN; - } - if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ActivityId; - } - - if (string.Equals(WFConstants.BackendHeaders.LocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.LocalLSN; - } - - break; - case 17: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) - { - return this.Continuation; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerId, key)) - { - return this.OwnerId; - } - if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) - { - return this.Continuation; - } - - if (string.Equals(HttpConstants.HttpHeaders.OwnerId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OwnerId; - } - - break; - case 18: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SchemaVersion, key)) - { - return this.SchemaVersion; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreState, key)) - { - return this.RestoreState; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) - { - return this.SessionToken; - } - if (string.Equals(HttpConstants.HttpHeaders.SchemaVersion, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SchemaVersion; - } - - if (string.Equals(WFConstants.BackendHeaders.RestoreState, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RestoreState; - } - - if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SessionToken; - } - - break; - case 19: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key)) - { - return this.RetryAfterInMilliseconds; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxResourceQuota, key)) - { - return this.MaxResourceQuota; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key)) - { - return this.CurrentResourceQuotaUsage; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RequestCharge, key)) - { - return this.RequestCharge; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) - { - return this.ResourceId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ServerVersion, key)) - { - return this.ServerVersion; - } - if (string.Equals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RetryAfterInMilliseconds; - } - - if (string.Equals(HttpConstants.HttpHeaders.MaxResourceQuota, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MaxResourceQuota; - } - - if (string.Equals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CurrentResourceQuotaUsage; - } - - if (string.Equals(HttpConstants.HttpHeaders.RequestCharge, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RequestCharge; - } - - if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ResourceId; - } - - if (string.Equals(HttpConstants.HttpHeaders.ServerVersion, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ServerVersion; - } - - break; - case 21: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerFullName, key)) - { - return this.OwnerFullName; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLSN, key)) - { - return this.QuorumAckedLSN; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) - { - return this.ShareThroughput; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ItemLocalLSN, key)) - { - return this.ItemLocalLSN; - } - if (string.Equals(HttpConstants.HttpHeaders.OwnerFullName, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OwnerFullName; - } - - if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.QuorumAckedLSN; - } - - if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ShareThroughput; - } - - if (string.Equals(WFConstants.BackendHeaders.ItemLocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ItemLocalLSN; - } - - break; - case 23: - if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IndexingDirective; - } - - break; - case 24: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) - { - return this.CollectionServiceIndex; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.DatabaseAccountId, key)) - { - return this.DatabaseAccountId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key)) - { - return this.BackendRequestDurationMilliseconds; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionServiceIndex; - } - - if (string.Equals(WFConstants.BackendHeaders.DatabaseAccountId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.DatabaseAccountId; - } - - if (string.Equals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - return this.BackendRequestDurationMilliseconds; - } - - break; - case 25: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentWriteQuorum, key)) - { - return this.CurrentWriteQuorum; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.GlobalCommittedLSN, key)) - { - return this.GlobalCommittedLSN; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) - { - return this.TransportRequestID; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CapacityType, key)) - { - return this.CapacityType; - } - if (string.Equals(WFConstants.BackendHeaders.CurrentWriteQuorum, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CurrentWriteQuorum; - } - - if (string.Equals(WFConstants.BackendHeaders.GlobalCommittedLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.GlobalCommittedLSN; - } - - if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TransportRequestID; - } - - if (string.Equals(HttpConstants.HttpHeaders.CapacityType, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CapacityType; - } - - break; - case 26: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.LastStateChangeUtc, key)) - { - return this.LastStateChangeUtc; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) - { - return this.CollectionPartitionIndex; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePending, key)) - { - return this.OfferReplacePending; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRntbdChannel, key)) - { - return this.DisableRntbdChannel; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinimumRUsForOffer, key)) - { - return this.MinimumRUsForOffer; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferRestorePending, key)) - { - return this.IsOfferRestorePending; - } - if (string.Equals(HttpConstants.HttpHeaders.LastStateChangeUtc, key, StringComparison.OrdinalIgnoreCase)) - { - return this.LastStateChangeUtc; - } - - if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionPartitionIndex; - } - - if (string.Equals(WFConstants.BackendHeaders.OfferReplacePending, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OfferReplacePending; - } - - if (string.Equals(HttpConstants.HttpHeaders.DisableRntbdChannel, key, StringComparison.OrdinalIgnoreCase)) - { - return this.DisableRntbdChannel; - } - - if (string.Equals(WFConstants.BackendHeaders.MinimumRUsForOffer, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MinimumRUsForOffer; - } - - if (string.Equals(HttpConstants.HttpHeaders.IsOfferRestorePending, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsOfferRestorePending; - } - - break; - case 27: - if (object.ReferenceEquals(WFConstants.BackendHeaders.NumberOfReadRegions, key)) - { - return this.NumberOfReadRegions; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key)) - { - return this.AppliedPolicyElementId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedInfo, key)) - { - return this.ChangeFeedInfo; - } - if (string.Equals(WFConstants.BackendHeaders.NumberOfReadRegions, key, StringComparison.OrdinalIgnoreCase)) - { - return this.NumberOfReadRegions; - } - - if (string.Equals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AppliedPolicyElementId; - } - - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ChangeFeedInfo; - } - - break; - case 28: - if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TimeToLiveInSeconds; - } - - break; - case 29: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key)) - { - return this.CurrentReplicaSetSize; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryMetrics, key)) - { - return this.QueryMetrics; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IndexUtilization, key)) - { - return this.IndexUtilization; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key)) - { - return this.QuorumAckedLocalLSN; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key)) - { - return this.MinGLSNForDocumentOperations; - } - if (string.Equals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CurrentReplicaSetSize; - } - - if (string.Equals(WFConstants.BackendHeaders.QueryMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - return this.QueryMetrics; - } - - if (string.Equals(WFConstants.BackendHeaders.IndexUtilization, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IndexUtilization; - } - - if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.QuorumAckedLocalLSN; - } - - if (string.Equals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MinGLSNForDocumentOperations; - } - - break; - case 30: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReIndexerProgress, key)) - { - return this.ReIndexerProgress; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxContentLength, key)) - { - return this.MaxContentLength; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key)) - { - return this.MinGLSNForTombstoneOperations; - } - if (string.Equals(WFConstants.BackendHeaders.ReIndexerProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ReIndexerProgress; - } - - if (string.Equals(HttpConstants.HttpHeaders.MaxContentLength, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MaxContentLength; - } - - if (string.Equals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MinGLSNForTombstoneOperations; - } - - break; - case 31: - if (string.Equals(WFConstants.BackendHeaders.RequestValidationFailure, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RequestValidationFailure; - } - - break; - case 32: - if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryExecutionInfo, key)) - { - return this.QueryExecutionInfo; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key)) - { - return this.AadAppliedRoleAssignmentId; - } - if (string.Equals(WFConstants.BackendHeaders.QueryExecutionInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.QueryExecutionInfo; - } - - if (string.Equals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AadAppliedRoleAssignmentId; - } - - break; - case 33: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key)) - { - return this.ReplicatorLSNToGLSNDelta; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key)) - { - return this.ReplicatorLSNToLLSNDelta; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CorrelatedActivityId, key)) - { - return this.CorrelatedActivityId; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PhysicalPartitionId, key)) - { - return this.PhysicalPartitionId; - } - if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ReplicatorLSNToGLSNDelta; - } - - if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ReplicatorLSNToLLSNDelta; - } - - if (string.Equals(WFConstants.BackendHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CorrelatedActivityId; - } - - if (string.Equals(HttpConstants.HttpHeaders.PhysicalPartitionId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PhysicalPartitionId; - } - - break; - case 34: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.LogResults, key)) - { - return this.LogResults; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.HasTentativeWrites, key)) - { - return this.HasTentativeWrites; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.InstantScaleUpValue, key)) - { - return this.InstantScaleUpValue; - } - if (string.Equals(HttpConstants.HttpHeaders.LogResults, key, StringComparison.OrdinalIgnoreCase)) - { - return this.LogResults; - } - - if (string.Equals(WFConstants.BackendHeaders.HasTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - return this.HasTentativeWrites; - } - - if (string.Equals(HttpConstants.HttpHeaders.InstantScaleUpValue, key, StringComparison.OrdinalIgnoreCase)) - { - return this.InstantScaleUpValue; - } - - break; - case 35: - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionKeyRangeId, key)) - { - return this.PartitionKeyRangeId; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key)) - { - return this.CollectionSecurityIdentifier; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OldestActiveSchemaId, key)) - { - return this.OldestActiveSchemaId; - } - if (string.Equals(WFConstants.BackendHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionKeyRangeId; - } - - if (string.Equals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionSecurityIdentifier; - } - - if (string.Equals(WFConstants.BackendHeaders.OldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OldestActiveSchemaId; - } - - break; - case 36: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TotalAccountThroughput, key)) - { - return this.TotalAccountThroughput; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ByokEncryptionProgress, key)) - { - return this.ByokEncryptionProgress; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key)) - { - return this.OfferReplacePendingForMerge; - } - if (string.Equals(HttpConstants.HttpHeaders.TotalAccountThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TotalAccountThroughput; - } - - if (string.Equals(WFConstants.BackendHeaders.ByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ByokEncryptionProgress; - } - - if (string.Equals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key, StringComparison.OrdinalIgnoreCase)) - { - return this.OfferReplacePendingForMerge; - } - - break; - case 37: - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key)) - { - return this.IsRUPerMinuteUsed; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key)) - { - return this.ReplicaStatusRevoked; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeProgressBlocked, key)) - { - return this.MergeProgressBlocked; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) - { - return this.PartitionThroughputInfo; - } - if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) - { - return this.IsRUPerMinuteUsed; - } - - if (string.Equals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ReplicaStatusRevoked; - } - - if (string.Equals(WFConstants.BackendHeaders.MergeProgressBlocked, key, StringComparison.OrdinalIgnoreCase)) - { - return this.MergeProgressBlocked; - } - - if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PartitionThroughputInfo; - } - - break; - case 38: - if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) - { - return this.VectorClockLocalProgress; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key)) - { - return this.ConfirmedStoreChecksum; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key)) - { - return this.TentativeStoreChecksum; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RequiresDistribution, key)) - { - return this.RequiresDistribution; - } - if (string.Equals(WFConstants.BackendHeaders.VectorClockLocalProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.VectorClockLocalProgress; - } - - if (string.Equals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) - { - return this.ConfirmedStoreChecksum; - } - - if (string.Equals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) - { - return this.TentativeStoreChecksum; - } - - if (string.Equals(WFConstants.BackendHeaders.RequiresDistribution, key, StringComparison.OrdinalIgnoreCase)) - { - return this.RequiresDistribution; - } - - break; - case 40: - if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) - { - return this.SoftMaxAllowedThroughput; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) - { - return this.HighestTentativeWriteLLSN; - } - if (string.Equals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - return this.SoftMaxAllowedThroughput; - } - - if (string.Equals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) - { - return this.HighestTentativeWriteLLSN; - } - - break; - case 41: - if (string.Equals(WFConstants.BackendHeaders.AnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.AnalyticalMigrationProgress; - } - - break; - case 42: - if (string.Equals(WFConstants.BackendHeaders.XPConfigurationSessionsCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.XPConfigurationSessionsCount; - } - - break; - case 43: - if (string.Equals(WFConstants.BackendHeaders.PendingPKDelete, key, StringComparison.OrdinalIgnoreCase)) - { - return this.PendingPKDelete; - } - - break; - case 48: - if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionUniqueKeysUnderReIndex; - } - - break; - case 49: - if (string.Equals(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionLazyIndexingProgress; - } - - break; - case 52: - if (object.ReferenceEquals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key)) - { - return this.UnflushedMergLogEntryCount; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key)) - { - return this.CollectionUniqueIndexReIndexProgress; - } - if (string.Equals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key, StringComparison.OrdinalIgnoreCase)) - { - return this.UnflushedMergLogEntryCount; - } - - if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionUniqueIndexReIndexProgress; - } - - break; - case 56: - if (string.Equals(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - return this.CollectionIndexTransformationProgress; - } - - break; - default: - break; - } - - if (this.lazyNotCommonHeaders?.TryGetValue(key, out string value) ?? false) - { - return value; - } - - return null; - } - - public void Add(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.UpdateHelper( - key: key, - value: value, - throwIfAlreadyExists: true); - } - - public void Set(string key, string value) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - this.UpdateHelper( - key: key, - value: value, - throwIfAlreadyExists: false); - } - - public void UpdateHelper( - string key, - string value, - bool throwIfAlreadyExists) - { - if (key == null) - { - throw new ArgumentNullException(nameof(key)); - } - - switch (key.Length) - { - case 3: - if (string.Equals(WFConstants.BackendHeaders.LSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.LSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LSN = value; - return; - } - break; - case 4: - if (string.Equals(HttpConstants.HttpHeaders.ETag, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ETag != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ETag = value; - return; - } - break; - case 9: - if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.XDate != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.XDate = value; - return; - } - break; - case 12: - if (string.Equals(WFConstants.BackendHeaders.XPRole, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.XPRole != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.XPRole = value; - return; - } - break; - case 13: - if (string.Equals(WFConstants.BackendHeaders.ItemLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ItemLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ItemLSN = value; - return; - } - break; - case 14: - if (string.Equals(WFConstants.BackendHeaders.SubStatus, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SubStatus != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SubStatus = value; - return; - } - break; - case 15: - if (string.Equals(HttpConstants.HttpHeaders.ItemCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ItemCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ItemCount = value; - return; - } - break; - case 16: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) - { - if (throwIfAlreadyExists && this.ActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ActivityId = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.LocalLSN, key)) - { - if (throwIfAlreadyExists && this.LocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LocalLSN = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ActivityId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.LocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.LocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LocalLSN = value; - return; - } - break; - case 17: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) - { - if (throwIfAlreadyExists && this.Continuation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Continuation = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerId, key)) - { - if (throwIfAlreadyExists && this.OwnerId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OwnerId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.Continuation != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.Continuation = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.OwnerId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OwnerId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OwnerId = value; - return; - } - break; - case 18: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SchemaVersion, key)) - { - if (throwIfAlreadyExists && this.SchemaVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaVersion = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreState, key)) - { - if (throwIfAlreadyExists && this.RestoreState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreState = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) - { - if (throwIfAlreadyExists && this.SessionToken != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SessionToken = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SchemaVersion, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SchemaVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SchemaVersion = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RestoreState, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RestoreState != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RestoreState = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SessionToken != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SessionToken = value; - return; - } - break; - case 19: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key)) - { - if (throwIfAlreadyExists && this.RetryAfterInMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetryAfterInMilliseconds = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxResourceQuota, key)) - { - if (throwIfAlreadyExists && this.MaxResourceQuota != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxResourceQuota = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key)) - { - if (throwIfAlreadyExists && this.CurrentResourceQuotaUsage != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentResourceQuotaUsage = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.RequestCharge, key)) - { - if (throwIfAlreadyExists && this.RequestCharge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequestCharge = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) - { - if (throwIfAlreadyExists && this.ResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ServerVersion, key)) - { - if (throwIfAlreadyExists && this.ServerVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ServerVersion = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RetryAfterInMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RetryAfterInMilliseconds = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MaxResourceQuota, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MaxResourceQuota != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxResourceQuota = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CurrentResourceQuotaUsage != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentResourceQuotaUsage = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.RequestCharge, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RequestCharge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequestCharge = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ResourceId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ResourceId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ServerVersion, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ServerVersion != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ServerVersion = value; - return; - } - break; - case 21: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerFullName, key)) - { - if (throwIfAlreadyExists && this.OwnerFullName != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OwnerFullName = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLSN, key)) - { - if (throwIfAlreadyExists && this.QuorumAckedLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QuorumAckedLSN = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) - { - if (throwIfAlreadyExists && this.ShareThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShareThroughput = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ItemLocalLSN, key)) - { - if (throwIfAlreadyExists && this.ItemLocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ItemLocalLSN = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.OwnerFullName, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OwnerFullName != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OwnerFullName = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.QuorumAckedLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QuorumAckedLSN = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ShareThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ShareThroughput = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ItemLocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ItemLocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ItemLocalLSN = value; - return; - } - break; - case 23: - if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IndexingDirective != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IndexingDirective = value; - return; - } - break; - case 24: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) - { - if (throwIfAlreadyExists && this.CollectionServiceIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionServiceIndex = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.DatabaseAccountId, key)) - { - if (throwIfAlreadyExists && this.DatabaseAccountId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DatabaseAccountId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key)) - { - if (throwIfAlreadyExists && this.BackendRequestDurationMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BackendRequestDurationMilliseconds = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionServiceIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionServiceIndex = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.DatabaseAccountId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.DatabaseAccountId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DatabaseAccountId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.BackendRequestDurationMilliseconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.BackendRequestDurationMilliseconds = value; - return; - } - break; - case 25: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentWriteQuorum, key)) - { - if (throwIfAlreadyExists && this.CurrentWriteQuorum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentWriteQuorum = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.GlobalCommittedLSN, key)) - { - if (throwIfAlreadyExists && this.GlobalCommittedLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GlobalCommittedLSN = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) - { - if (throwIfAlreadyExists && this.TransportRequestID != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransportRequestID = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.CapacityType, key)) - { - if (throwIfAlreadyExists && this.CapacityType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CapacityType = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CurrentWriteQuorum, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CurrentWriteQuorum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentWriteQuorum = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.GlobalCommittedLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.GlobalCommittedLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.GlobalCommittedLSN = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TransportRequestID != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TransportRequestID = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.CapacityType, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CapacityType != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CapacityType = value; - return; - } - break; - case 26: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.LastStateChangeUtc, key)) - { - if (throwIfAlreadyExists && this.LastStateChangeUtc != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LastStateChangeUtc = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) - { - if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionPartitionIndex = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePending, key)) - { - if (throwIfAlreadyExists && this.OfferReplacePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplacePending = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRntbdChannel, key)) - { - if (throwIfAlreadyExists && this.DisableRntbdChannel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DisableRntbdChannel = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinimumRUsForOffer, key)) - { - if (throwIfAlreadyExists && this.MinimumRUsForOffer != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinimumRUsForOffer = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferRestorePending, key)) - { - if (throwIfAlreadyExists && this.IsOfferRestorePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsOfferRestorePending = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.LastStateChangeUtc, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.LastStateChangeUtc != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LastStateChangeUtc = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionPartitionIndex = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.OfferReplacePending, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OfferReplacePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplacePending = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.DisableRntbdChannel, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.DisableRntbdChannel != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.DisableRntbdChannel = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.MinimumRUsForOffer, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MinimumRUsForOffer != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinimumRUsForOffer = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.IsOfferRestorePending, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsOfferRestorePending != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsOfferRestorePending = value; - return; - } - break; - case 27: - if (object.ReferenceEquals(WFConstants.BackendHeaders.NumberOfReadRegions, key)) - { - if (throwIfAlreadyExists && this.NumberOfReadRegions != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.NumberOfReadRegions = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key)) - { - if (throwIfAlreadyExists && this.AppliedPolicyElementId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AppliedPolicyElementId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedInfo, key)) - { - if (throwIfAlreadyExists && this.ChangeFeedInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedInfo = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.NumberOfReadRegions, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.NumberOfReadRegions != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.NumberOfReadRegions = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AppliedPolicyElementId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AppliedPolicyElementId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ChangeFeedInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ChangeFeedInfo = value; - return; - } - break; - case 28: - if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TimeToLiveInSeconds = value; - return; - } - break; - case 29: - if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key)) - { - if (throwIfAlreadyExists && this.CurrentReplicaSetSize != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentReplicaSetSize = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryMetrics, key)) - { - if (throwIfAlreadyExists && this.QueryMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryMetrics = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.IndexUtilization, key)) - { - if (throwIfAlreadyExists && this.IndexUtilization != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IndexUtilization = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key)) - { - if (throwIfAlreadyExists && this.QuorumAckedLocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QuorumAckedLocalLSN = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key)) - { - if (throwIfAlreadyExists && this.MinGLSNForDocumentOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinGLSNForDocumentOperations = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CurrentReplicaSetSize != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CurrentReplicaSetSize = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.QueryMetrics, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.QueryMetrics != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryMetrics = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IndexUtilization, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IndexUtilization != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IndexUtilization = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.QuorumAckedLocalLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QuorumAckedLocalLSN = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MinGLSNForDocumentOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinGLSNForDocumentOperations = value; - return; - } - break; - case 30: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReIndexerProgress, key)) - { - if (throwIfAlreadyExists && this.ReIndexerProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReIndexerProgress = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxContentLength, key)) - { - if (throwIfAlreadyExists && this.MaxContentLength != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxContentLength = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key)) - { - if (throwIfAlreadyExists && this.MinGLSNForTombstoneOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinGLSNForTombstoneOperations = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ReIndexerProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ReIndexerProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReIndexerProgress = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.MaxContentLength, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MaxContentLength != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MaxContentLength = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MinGLSNForTombstoneOperations != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MinGLSNForTombstoneOperations = value; - return; - } - break; - case 31: - if (string.Equals(WFConstants.BackendHeaders.RequestValidationFailure, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RequestValidationFailure != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequestValidationFailure = value; - return; - } - break; - case 32: - if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryExecutionInfo, key)) - { - if (throwIfAlreadyExists && this.QueryExecutionInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryExecutionInfo = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key)) - { - if (throwIfAlreadyExists && this.AadAppliedRoleAssignmentId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AadAppliedRoleAssignmentId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.QueryExecutionInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.QueryExecutionInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.QueryExecutionInfo = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AadAppliedRoleAssignmentId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AadAppliedRoleAssignmentId = value; - return; - } - break; - case 33: - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key)) - { - if (throwIfAlreadyExists && this.ReplicatorLSNToGLSNDelta != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicatorLSNToGLSNDelta = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key)) - { - if (throwIfAlreadyExists && this.ReplicatorLSNToLLSNDelta != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicatorLSNToLLSNDelta = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CorrelatedActivityId, key)) - { - if (throwIfAlreadyExists && this.CorrelatedActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CorrelatedActivityId = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.PhysicalPartitionId, key)) - { - if (throwIfAlreadyExists && this.PhysicalPartitionId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PhysicalPartitionId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ReplicatorLSNToGLSNDelta != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicatorLSNToGLSNDelta = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ReplicatorLSNToLLSNDelta != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicatorLSNToLLSNDelta = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CorrelatedActivityId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CorrelatedActivityId = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.PhysicalPartitionId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PhysicalPartitionId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PhysicalPartitionId = value; - return; - } - break; - case 34: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.LogResults, key)) - { - if (throwIfAlreadyExists && this.LogResults != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LogResults = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.HasTentativeWrites, key)) - { - if (throwIfAlreadyExists && this.HasTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HasTentativeWrites = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.InstantScaleUpValue, key)) - { - if (throwIfAlreadyExists && this.InstantScaleUpValue != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.InstantScaleUpValue = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.LogResults, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.LogResults != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.LogResults = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.HasTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.HasTentativeWrites != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HasTentativeWrites = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.InstantScaleUpValue, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.InstantScaleUpValue != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.InstantScaleUpValue = value; - return; - } - break; - case 35: - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionKeyRangeId, key)) - { - if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKeyRangeId = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key)) - { - if (throwIfAlreadyExists && this.CollectionSecurityIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionSecurityIdentifier = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OldestActiveSchemaId, key)) - { - if (throwIfAlreadyExists && this.OldestActiveSchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OldestActiveSchemaId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionKeyRangeId = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionSecurityIdentifier != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionSecurityIdentifier = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.OldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OldestActiveSchemaId != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OldestActiveSchemaId = value; - return; - } - break; - case 36: - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TotalAccountThroughput, key)) - { - if (throwIfAlreadyExists && this.TotalAccountThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TotalAccountThroughput = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ByokEncryptionProgress, key)) - { - if (throwIfAlreadyExists && this.ByokEncryptionProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ByokEncryptionProgress = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key)) - { - if (throwIfAlreadyExists && this.OfferReplacePendingForMerge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplacePendingForMerge = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TotalAccountThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TotalAccountThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TotalAccountThroughput = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ByokEncryptionProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ByokEncryptionProgress = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.OfferReplacePendingForMerge != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.OfferReplacePendingForMerge = value; - return; - } - break; - case 37: - if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key)) - { - if (throwIfAlreadyExists && this.IsRUPerMinuteUsed != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRUPerMinuteUsed = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key)) - { - if (throwIfAlreadyExists && this.ReplicaStatusRevoked != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicaStatusRevoked = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeProgressBlocked, key)) - { - if (throwIfAlreadyExists && this.MergeProgressBlocked != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeProgressBlocked = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) - { - if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionThroughputInfo = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.IsRUPerMinuteUsed != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.IsRUPerMinuteUsed = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ReplicaStatusRevoked != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ReplicaStatusRevoked = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.MergeProgressBlocked, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.MergeProgressBlocked != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.MergeProgressBlocked = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PartitionThroughputInfo = value; - return; - } - break; - case 38: - if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) - { - if (throwIfAlreadyExists && this.VectorClockLocalProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.VectorClockLocalProgress = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key)) - { - if (throwIfAlreadyExists && this.ConfirmedStoreChecksum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ConfirmedStoreChecksum = value; - return; - } - if (object.ReferenceEquals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key)) - { - if (throwIfAlreadyExists && this.TentativeStoreChecksum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TentativeStoreChecksum = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.RequiresDistribution, key)) - { - if (throwIfAlreadyExists && this.RequiresDistribution != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequiresDistribution = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.VectorClockLocalProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.VectorClockLocalProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.VectorClockLocalProgress = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.ConfirmedStoreChecksum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.ConfirmedStoreChecksum = value; - return; - } - if (string.Equals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.TentativeStoreChecksum != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.TentativeStoreChecksum = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.RequiresDistribution, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.RequiresDistribution != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.RequiresDistribution = value; - return; - } - break; - case 40: - if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) - { - if (throwIfAlreadyExists && this.SoftMaxAllowedThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SoftMaxAllowedThroughput = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) - { - if (throwIfAlreadyExists && this.HighestTentativeWriteLLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HighestTentativeWriteLLSN = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.SoftMaxAllowedThroughput != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.SoftMaxAllowedThroughput = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.HighestTentativeWriteLLSN != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.HighestTentativeWriteLLSN = value; - return; - } - break; - case 41: - if (string.Equals(WFConstants.BackendHeaders.AnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.AnalyticalMigrationProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.AnalyticalMigrationProgress = value; - return; - } - break; - case 42: - if (string.Equals(WFConstants.BackendHeaders.XPConfigurationSessionsCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.XPConfigurationSessionsCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.XPConfigurationSessionsCount = value; - return; - } - break; - case 43: - if (string.Equals(WFConstants.BackendHeaders.PendingPKDelete, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.PendingPKDelete != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.PendingPKDelete = value; - return; - } - break; - case 48: - if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionUniqueKeysUnderReIndex != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionUniqueKeysUnderReIndex = value; - return; - } - break; - case 49: - if (string.Equals(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionLazyIndexingProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionLazyIndexingProgress = value; - return; - } - break; - case 52: - if (object.ReferenceEquals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key)) - { - if (throwIfAlreadyExists && this.UnflushedMergLogEntryCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UnflushedMergLogEntryCount = value; - return; - } - if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key)) - { - if (throwIfAlreadyExists && this.CollectionUniqueIndexReIndexProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionUniqueIndexReIndexProgress = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.UnflushedMergLogEntryCount != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.UnflushedMergLogEntryCount = value; - return; - } - if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionUniqueIndexReIndexProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionUniqueIndexReIndexProgress = value; - return; - } - break; - case 56: - if (string.Equals(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, key, StringComparison.OrdinalIgnoreCase)) - { - if (throwIfAlreadyExists && this.CollectionIndexTransformationProgress != null) - { - throw new ArgumentException($"The {key} already exists in the collection"); - } - - this.CollectionIndexTransformationProgress = value; - return; - } - break; - default: - break; - } - - if (throwIfAlreadyExists) - { - this.GetOrCreateLazyHeaders().Add(key, value); - } - else - { - if (value == null) - { - // don't create lazyNotCommonHeaders if it doesn't already exist - - if (this.lazyNotCommonHeaders != null) - { - this.lazyNotCommonHeaders.Remove(key); - } - } - else - { - this.GetOrCreateLazyHeaders()[key] = value; - } - } - } - - private Dictionary GetOrCreateLazyHeaders() - { - Dictionary lazyHeaders = this.lazyNotCommonHeaders; - - if (lazyHeaders == null) - { - // risk over allocating, but everyone will get the same dictionary in the end - Dictionary newDict = new Dictionary(StoreResponseNameValueCollection.DefaultStringComparer); - - // Either swap newDict in (getting back the old null) or obtain the Dictionary some other thread swapped in - // (and then we drop newDict on the floor). - lazyHeaders = Interlocked.CompareExchange(ref this.lazyNotCommonHeaders, newDict, null) ?? newDict; - } - - return lazyHeaders; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA StoreResponseNameValueCollection.tt + +namespace Microsoft.Azure.Documents.Collections +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Linq; + using System.Threading; + using Microsoft.Azure.Documents; + + /// + /// THIS IS AN AUTOGENERATED FILE. ALL UPDATES SHOULD BE DONE VIA StoreResponseNameValueCollection.tt + /// This should be a one to one mapping with RntbdConstants.Response header token properties. + /// This allows the TransportSerialization to directly set the property and avoid the dictionary overhead. + /// If the property does not exists please update the StoreResponseNameValueCollection.tt list to add the new field + /// + internal class StoreResponseNameValueCollection : INameValueCollection, IEnumerable> + { + private static readonly StringComparer DefaultStringComparer = StringComparer.OrdinalIgnoreCase; + + // this is null if it's never been added to, and is created in a thread safe manner via GetOrCreateLazyHeaders() + private Dictionary lazyNotCommonHeaders; + + // The INameValueCollection interface is expected to be a replacement for NameValueCollection across the projects. + // However, there are a few public API with NameValueCollection as return type, e.g. DocumentServiceResponse.ResponseHeaders and + // DocumentClientException.ResponseHeaders. + // + // As a hybrid approach in those cases, we maintain the headers internally as an instance of the new INameValueCollection and create + // a NameValueCollection for the above public APIs. Keeping the NameValueCollection and the internal INameValueCollection in sync is + // not only cumbersome, it may also defeat the purpose of the new dictionary-based type. + // + // Therefore, we want to keep the NameValueCollection consistent within the ResponseHeaders APIs call. In other words, + // once invoked, the ResponseHeaders will return the same NameValueCollection. + private NameValueCollection nameValueCollection = null; + + public string AadAppliedRoleAssignmentId { get; set; } + public string ActivityId { get; set; } + public string AnalyticalMigrationProgress { get; set; } + public string AppliedPolicyElementId { get; set; } + public string BackendRequestDurationMilliseconds { get; set; } + public string ByokEncryptionProgress { get; set; } + public string CapacityType { get; set; } + public string ChangeFeedInfo { get; set; } + public string CollectionIndexTransformationProgress { get; set; } + public string CollectionLazyIndexingProgress { get; set; } + public string CollectionPartitionIndex { get; set; } + public string CollectionSecurityIdentifier { get; set; } + public string CollectionServiceIndex { get; set; } + public string CollectionUniqueIndexReIndexProgress { get; set; } + public string CollectionUniqueKeysUnderReIndex { get; set; } + public string ConfirmedStoreChecksum { get; set; } + public string Continuation { get; set; } + public string CorrelatedActivityId { get; set; } + public string CosmosGatewayTransactionId { get; set; } + public string CurrentReplicaSetSize { get; set; } + public string CurrentResourceQuotaUsage { get; set; } + public string CurrentWriteQuorum { get; set; } + public string DatabaseAccountId { get; set; } + public string DisableRntbdChannel { get; set; } + public string DocumentRecordCount { get; set; } + public string ETag { get; set; } + public string GlobalCommittedLSN { get; set; } + public string HasTentativeWrites { get; set; } + public string HighestTentativeWriteLLSN { get; set; } + public string IndexingDirective { get; set; } + public string IndexUtilization { get; set; } + public string InstantScaleUpValue { get; set; } + public string IsOfferRestorePending { get; set; } + public string IsRUPerMinuteUsed { get; set; } + public string ItemCount { get; set; } + public string ItemLocalLSN { get; set; } + public string ItemLSN { get; set; } + public string LastStateChangeUtc { get; set; } + public string LocalLSN { get; set; } + public string LogResults { get; set; } + public string LSN { get; set; } + public string MaxContentLength { get; set; } + public string MaxResourceQuota { get; set; } + public string MergeProgressBlocked { get; set; } + public string MinGLSNForDocumentOperations { get; set; } + public string MinGLSNForTombstoneOperations { get; set; } + public string MinimumRUsForOffer { get; set; } + public string NumberOfReadRegions { get; set; } + public string OfferReplacePending { get; set; } + public string OfferReplacePendingForMerge { get; set; } + public string OldestActiveSchemaId { get; set; } + public string OwnerFullName { get; set; } + public string OwnerId { get; set; } + public string PartitionKeyRangeId { get; set; } + public string PartitionThroughputInfo { get; set; } + public string PendingPKDelete { get; set; } + public string PhysicalPartitionId { get; set; } + public string QueryExecutionInfo { get; set; } + public string QueryMetrics { get; set; } + public string QuorumAckedLocalLSN { get; set; } + public string QuorumAckedLSN { get; set; } + public string ReIndexerProgress { get; set; } + public string ReplicaStatusRevoked { get; set; } + public string ReplicatorLSNToGLSNDelta { get; set; } + public string ReplicatorLSNToLLSNDelta { get; set; } + public string RequestCharge { get; set; } + public string RequestValidationFailure { get; set; } + public string RequiresDistribution { get; set; } + public string ResourceId { get; set; } + public string RestoreState { get; set; } + public string RetryAfterInMilliseconds { get; set; } + public string SchemaVersion { get; set; } + public string ServerVersion { get; set; } + public string SessionToken { get; set; } + public string ShareThroughput { get; set; } + public string SoftMaxAllowedThroughput { get; set; } + public string SubStatus { get; set; } + public string TentativeStoreChecksum { get; set; } + public string TimeToLiveInSeconds { get; set; } + public string TotalAccountThroughput { get; set; } + public string TransportRequestID { get; set; } + public string UnflushedMergLogEntryCount { get; set; } + public string UserStrings { get; set; } + public string VectorClockLocalProgress { get; set; } + public string XDate { get; set; } + public string XPConfigurationSessionsCount { get; set; } + public string XPRole { get; set; } + + public StoreResponseNameValueCollection() + { + } + + private StoreResponseNameValueCollection(Dictionary lazyNotCommonHeaders) + { + this.lazyNotCommonHeaders = lazyNotCommonHeaders; + } + + public string this[string key] + { + get => this.Get(key); + set => this.Set(key, value); + } + + public void Add(INameValueCollection collection) + { + if (collection == null) + { + throw new ArgumentNullException(nameof(collection)); + } + + foreach (string key in collection.Keys()) + { + this.Set(key, collection[key]); + } + } + + public string[] AllKeys() + { + return this.Keys().ToArray(); + } + + public void Clear() + { + if (this.lazyNotCommonHeaders != null) + { + this.lazyNotCommonHeaders.Clear(); + } + + this.AadAppliedRoleAssignmentId = null; + this.ActivityId = null; + this.AnalyticalMigrationProgress = null; + this.AppliedPolicyElementId = null; + this.BackendRequestDurationMilliseconds = null; + this.ByokEncryptionProgress = null; + this.CapacityType = null; + this.ChangeFeedInfo = null; + this.CollectionIndexTransformationProgress = null; + this.CollectionLazyIndexingProgress = null; + this.CollectionPartitionIndex = null; + this.CollectionSecurityIdentifier = null; + this.CollectionServiceIndex = null; + this.CollectionUniqueIndexReIndexProgress = null; + this.CollectionUniqueKeysUnderReIndex = null; + this.ConfirmedStoreChecksum = null; + this.Continuation = null; + this.CorrelatedActivityId = null; + this.CosmosGatewayTransactionId = null; + this.CurrentReplicaSetSize = null; + this.CurrentResourceQuotaUsage = null; + this.CurrentWriteQuorum = null; + this.DatabaseAccountId = null; + this.DisableRntbdChannel = null; + this.DocumentRecordCount = null; + this.ETag = null; + this.GlobalCommittedLSN = null; + this.HasTentativeWrites = null; + this.HighestTentativeWriteLLSN = null; + this.IndexingDirective = null; + this.IndexUtilization = null; + this.InstantScaleUpValue = null; + this.IsOfferRestorePending = null; + this.IsRUPerMinuteUsed = null; + this.ItemCount = null; + this.ItemLocalLSN = null; + this.ItemLSN = null; + this.LastStateChangeUtc = null; + this.LocalLSN = null; + this.LogResults = null; + this.LSN = null; + this.MaxContentLength = null; + this.MaxResourceQuota = null; + this.MergeProgressBlocked = null; + this.MinGLSNForDocumentOperations = null; + this.MinGLSNForTombstoneOperations = null; + this.MinimumRUsForOffer = null; + this.NumberOfReadRegions = null; + this.OfferReplacePending = null; + this.OfferReplacePendingForMerge = null; + this.OldestActiveSchemaId = null; + this.OwnerFullName = null; + this.OwnerId = null; + this.PartitionKeyRangeId = null; + this.PartitionThroughputInfo = null; + this.PendingPKDelete = null; + this.PhysicalPartitionId = null; + this.QueryExecutionInfo = null; + this.QueryMetrics = null; + this.QuorumAckedLocalLSN = null; + this.QuorumAckedLSN = null; + this.ReIndexerProgress = null; + this.ReplicaStatusRevoked = null; + this.ReplicatorLSNToGLSNDelta = null; + this.ReplicatorLSNToLLSNDelta = null; + this.RequestCharge = null; + this.RequestValidationFailure = null; + this.RequiresDistribution = null; + this.ResourceId = null; + this.RestoreState = null; + this.RetryAfterInMilliseconds = null; + this.SchemaVersion = null; + this.ServerVersion = null; + this.SessionToken = null; + this.ShareThroughput = null; + this.SoftMaxAllowedThroughput = null; + this.SubStatus = null; + this.TentativeStoreChecksum = null; + this.TimeToLiveInSeconds = null; + this.TotalAccountThroughput = null; + this.TransportRequestID = null; + this.UnflushedMergLogEntryCount = null; + this.UserStrings = null; + this.VectorClockLocalProgress = null; + this.XDate = null; + this.XPConfigurationSessionsCount = null; + this.XPRole = null; + + } + + public INameValueCollection Clone() + { + Dictionary cloneNotCommonHeaders = null; + if (this.lazyNotCommonHeaders != null) + { + cloneNotCommonHeaders = new Dictionary(this.lazyNotCommonHeaders, StoreResponseNameValueCollection.DefaultStringComparer); + } + + StoreResponseNameValueCollection cloneHeaders = new StoreResponseNameValueCollection(cloneNotCommonHeaders) + { + AadAppliedRoleAssignmentId = this.AadAppliedRoleAssignmentId, + ActivityId = this.ActivityId, + AnalyticalMigrationProgress = this.AnalyticalMigrationProgress, + AppliedPolicyElementId = this.AppliedPolicyElementId, + BackendRequestDurationMilliseconds = this.BackendRequestDurationMilliseconds, + ByokEncryptionProgress = this.ByokEncryptionProgress, + CapacityType = this.CapacityType, + ChangeFeedInfo = this.ChangeFeedInfo, + CollectionIndexTransformationProgress = this.CollectionIndexTransformationProgress, + CollectionLazyIndexingProgress = this.CollectionLazyIndexingProgress, + CollectionPartitionIndex = this.CollectionPartitionIndex, + CollectionSecurityIdentifier = this.CollectionSecurityIdentifier, + CollectionServiceIndex = this.CollectionServiceIndex, + CollectionUniqueIndexReIndexProgress = this.CollectionUniqueIndexReIndexProgress, + CollectionUniqueKeysUnderReIndex = this.CollectionUniqueKeysUnderReIndex, + ConfirmedStoreChecksum = this.ConfirmedStoreChecksum, + Continuation = this.Continuation, + CorrelatedActivityId = this.CorrelatedActivityId, + CosmosGatewayTransactionId = this.CosmosGatewayTransactionId, + CurrentReplicaSetSize = this.CurrentReplicaSetSize, + CurrentResourceQuotaUsage = this.CurrentResourceQuotaUsage, + CurrentWriteQuorum = this.CurrentWriteQuorum, + DatabaseAccountId = this.DatabaseAccountId, + DisableRntbdChannel = this.DisableRntbdChannel, + DocumentRecordCount = this.DocumentRecordCount, + ETag = this.ETag, + GlobalCommittedLSN = this.GlobalCommittedLSN, + HasTentativeWrites = this.HasTentativeWrites, + HighestTentativeWriteLLSN = this.HighestTentativeWriteLLSN, + IndexingDirective = this.IndexingDirective, + IndexUtilization = this.IndexUtilization, + InstantScaleUpValue = this.InstantScaleUpValue, + IsOfferRestorePending = this.IsOfferRestorePending, + IsRUPerMinuteUsed = this.IsRUPerMinuteUsed, + ItemCount = this.ItemCount, + ItemLocalLSN = this.ItemLocalLSN, + ItemLSN = this.ItemLSN, + LastStateChangeUtc = this.LastStateChangeUtc, + LocalLSN = this.LocalLSN, + LogResults = this.LogResults, + LSN = this.LSN, + MaxContentLength = this.MaxContentLength, + MaxResourceQuota = this.MaxResourceQuota, + MergeProgressBlocked = this.MergeProgressBlocked, + MinGLSNForDocumentOperations = this.MinGLSNForDocumentOperations, + MinGLSNForTombstoneOperations = this.MinGLSNForTombstoneOperations, + MinimumRUsForOffer = this.MinimumRUsForOffer, + NumberOfReadRegions = this.NumberOfReadRegions, + OfferReplacePending = this.OfferReplacePending, + OfferReplacePendingForMerge = this.OfferReplacePendingForMerge, + OldestActiveSchemaId = this.OldestActiveSchemaId, + OwnerFullName = this.OwnerFullName, + OwnerId = this.OwnerId, + PartitionKeyRangeId = this.PartitionKeyRangeId, + PartitionThroughputInfo = this.PartitionThroughputInfo, + PendingPKDelete = this.PendingPKDelete, + PhysicalPartitionId = this.PhysicalPartitionId, + QueryExecutionInfo = this.QueryExecutionInfo, + QueryMetrics = this.QueryMetrics, + QuorumAckedLocalLSN = this.QuorumAckedLocalLSN, + QuorumAckedLSN = this.QuorumAckedLSN, + ReIndexerProgress = this.ReIndexerProgress, + ReplicaStatusRevoked = this.ReplicaStatusRevoked, + ReplicatorLSNToGLSNDelta = this.ReplicatorLSNToGLSNDelta, + ReplicatorLSNToLLSNDelta = this.ReplicatorLSNToLLSNDelta, + RequestCharge = this.RequestCharge, + RequestValidationFailure = this.RequestValidationFailure, + RequiresDistribution = this.RequiresDistribution, + ResourceId = this.ResourceId, + RestoreState = this.RestoreState, + RetryAfterInMilliseconds = this.RetryAfterInMilliseconds, + SchemaVersion = this.SchemaVersion, + ServerVersion = this.ServerVersion, + SessionToken = this.SessionToken, + ShareThroughput = this.ShareThroughput, + SoftMaxAllowedThroughput = this.SoftMaxAllowedThroughput, + SubStatus = this.SubStatus, + TentativeStoreChecksum = this.TentativeStoreChecksum, + TimeToLiveInSeconds = this.TimeToLiveInSeconds, + TotalAccountThroughput = this.TotalAccountThroughput, + TransportRequestID = this.TransportRequestID, + UnflushedMergLogEntryCount = this.UnflushedMergLogEntryCount, + UserStrings = this.UserStrings, + VectorClockLocalProgress = this.VectorClockLocalProgress, + XDate = this.XDate, + XPConfigurationSessionsCount = this.XPConfigurationSessionsCount, + XPRole = this.XPRole, + }; + + return cloneHeaders; + } + + public int Count() + { + return this.Keys().Count(); + } + + public IEnumerator GetEnumerator() + { + return this.Keys().GetEnumerator(); + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + if (this.ActivityId != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); + } + if (this.LastStateChangeUtc != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.LastStateChangeUtc, this.LastStateChangeUtc); + } + if (this.Continuation != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.Continuation, this.Continuation); + } + if (this.ETag != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ETag, this.ETag); + } + if (this.RetryAfterInMilliseconds != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, this.RetryAfterInMilliseconds); + } + if (this.IndexingDirective != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); + } + if (this.MaxResourceQuota != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.MaxResourceQuota, this.MaxResourceQuota); + } + if (this.CurrentResourceQuotaUsage != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, this.CurrentResourceQuotaUsage); + } + if (this.SchemaVersion != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.SchemaVersion, this.SchemaVersion); + } + if (this.CollectionPartitionIndex != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); + } + if (this.CollectionServiceIndex != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); + } + if (this.LSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.LSN, this.LSN); + } + if (this.ItemCount != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ItemCount, this.ItemCount); + } + if (this.RequestCharge != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.RequestCharge, this.RequestCharge); + } + if (this.OwnerFullName != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.OwnerFullName, this.OwnerFullName); + } + if (this.OwnerId != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.OwnerId, this.OwnerId); + } + if (this.DatabaseAccountId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.DatabaseAccountId, this.DatabaseAccountId); + } + if (this.QuorumAckedLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.QuorumAckedLSN, this.QuorumAckedLSN); + } + if (this.RequestValidationFailure != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.RequestValidationFailure, this.RequestValidationFailure); + } + if (this.SubStatus != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.SubStatus, this.SubStatus); + } + if (this.CollectionIndexTransformationProgress != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, this.CollectionIndexTransformationProgress); + } + if (this.CurrentWriteQuorum != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CurrentWriteQuorum, this.CurrentWriteQuorum); + } + if (this.CurrentReplicaSetSize != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CurrentReplicaSetSize, this.CurrentReplicaSetSize); + } + if (this.CollectionLazyIndexingProgress != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, this.CollectionLazyIndexingProgress); + } + if (this.PartitionKeyRangeId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); + } + if (this.LogResults != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.LogResults, this.LogResults); + } + if (this.XPRole != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.XPRole, this.XPRole); + } + if (this.IsRUPerMinuteUsed != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.IsRUPerMinuteUsed, this.IsRUPerMinuteUsed); + } + if (this.QueryMetrics != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.QueryMetrics, this.QueryMetrics); + } + if (this.QueryExecutionInfo != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.QueryExecutionInfo, this.QueryExecutionInfo); + } + if (this.IndexUtilization != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.IndexUtilization, this.IndexUtilization); + } + if (this.GlobalCommittedLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.GlobalCommittedLSN, this.GlobalCommittedLSN); + } + if (this.NumberOfReadRegions != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.NumberOfReadRegions, this.NumberOfReadRegions); + } + if (this.OfferReplacePending != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.OfferReplacePending, this.OfferReplacePending); + } + if (this.ItemLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ItemLSN, this.ItemLSN); + } + if (this.RestoreState != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.RestoreState, this.RestoreState); + } + if (this.CollectionSecurityIdentifier != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionSecurityIdentifier, this.CollectionSecurityIdentifier); + } + if (this.TransportRequestID != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); + } + if (this.ShareThroughput != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); + } + if (this.DisableRntbdChannel != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.DisableRntbdChannel, this.DisableRntbdChannel); + } + if (this.XDate != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.XDate, this.XDate); + } + if (this.LocalLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.LocalLSN, this.LocalLSN); + } + if (this.QuorumAckedLocalLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.QuorumAckedLocalLSN, this.QuorumAckedLocalLSN); + } + if (this.ItemLocalLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ItemLocalLSN, this.ItemLocalLSN); + } + if (this.HasTentativeWrites != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.HasTentativeWrites, this.HasTentativeWrites); + } + if (this.SessionToken != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); + } + if (this.ReplicatorLSNToGLSNDelta != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, this.ReplicatorLSNToGLSNDelta); + } + if (this.ReplicatorLSNToLLSNDelta != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, this.ReplicatorLSNToLLSNDelta); + } + if (this.VectorClockLocalProgress != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.VectorClockLocalProgress, this.VectorClockLocalProgress); + } + if (this.MinimumRUsForOffer != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.MinimumRUsForOffer, this.MinimumRUsForOffer); + } + if (this.XPConfigurationSessionsCount != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.XPConfigurationSessionsCount, this.XPConfigurationSessionsCount); + } + if (this.UnflushedMergLogEntryCount != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, this.UnflushedMergLogEntryCount); + } + if (this.ResourceId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ResourceId, this.ResourceId); + } + if (this.TimeToLiveInSeconds != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); + } + if (this.ReplicaStatusRevoked != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ReplicaStatusRevoked, this.ReplicaStatusRevoked); + } + if (this.SoftMaxAllowedThroughput != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, this.SoftMaxAllowedThroughput); + } + if (this.BackendRequestDurationMilliseconds != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, this.BackendRequestDurationMilliseconds); + } + if (this.ServerVersion != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ServerVersion, this.ServerVersion); + } + if (this.ConfirmedStoreChecksum != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, this.ConfirmedStoreChecksum); + } + if (this.TentativeStoreChecksum != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.TentativeStoreChecksum, this.TentativeStoreChecksum); + } + if (this.CorrelatedActivityId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CorrelatedActivityId, this.CorrelatedActivityId); + } + if (this.PendingPKDelete != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.PendingPKDelete, this.PendingPKDelete); + } + if (this.AadAppliedRoleAssignmentId != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, this.AadAppliedRoleAssignmentId); + } + if (this.CollectionUniqueIndexReIndexProgress != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, this.CollectionUniqueIndexReIndexProgress); + } + if (this.CollectionUniqueKeysUnderReIndex != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, this.CollectionUniqueKeysUnderReIndex); + } + if (this.AnalyticalMigrationProgress != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.AnalyticalMigrationProgress, this.AnalyticalMigrationProgress); + } + if (this.TotalAccountThroughput != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.TotalAccountThroughput, this.TotalAccountThroughput); + } + if (this.ByokEncryptionProgress != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ByokEncryptionProgress, this.ByokEncryptionProgress); + } + if (this.AppliedPolicyElementId != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.AppliedPolicyElementId, this.AppliedPolicyElementId); + } + if (this.MergeProgressBlocked != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.MergeProgressBlocked, this.MergeProgressBlocked); + } + if (this.ChangeFeedInfo != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.ChangeFeedInfo, this.ChangeFeedInfo); + } + if (this.ReIndexerProgress != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.ReIndexerProgress, this.ReIndexerProgress); + } + if (this.OfferReplacePendingForMerge != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.OfferReplacePendingForMerge, this.OfferReplacePendingForMerge); + } + if (this.OldestActiveSchemaId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.OldestActiveSchemaId, this.OldestActiveSchemaId); + } + if (this.PhysicalPartitionId != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.PhysicalPartitionId, this.PhysicalPartitionId); + } + if (this.MaxContentLength != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.MaxContentLength, this.MaxContentLength); + } + if (this.IsOfferRestorePending != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.IsOfferRestorePending, this.IsOfferRestorePending); + } + if (this.InstantScaleUpValue != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.InstantScaleUpValue, this.InstantScaleUpValue); + } + if (this.RequiresDistribution != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.RequiresDistribution, this.RequiresDistribution); + } + if (this.CapacityType != null) + { + yield return new KeyValuePair(HttpConstants.HttpHeaders.CapacityType, this.CapacityType); + } + if (this.MinGLSNForTombstoneOperations != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, this.MinGLSNForTombstoneOperations); + } + if (this.MinGLSNForDocumentOperations != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, this.MinGLSNForDocumentOperations); + } + if (this.HighestTentativeWriteLLSN != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); + } + if (this.PartitionThroughputInfo != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); + } + if (this.DocumentRecordCount != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.DocumentRecordCount, this.DocumentRecordCount); + } + if (this.CosmosGatewayTransactionId != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.CosmosGatewayTransactionId, this.CosmosGatewayTransactionId); + } + if (this.UserStrings != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.UserStrings, this.UserStrings); + } + + if (this.lazyNotCommonHeaders != null) + { + foreach (KeyValuePair kvp in this.lazyNotCommonHeaders) + { + yield return kvp; + } + } + } + + public string[] GetValues(string key) + { + string value = this.Get(key); + if (value != null) + { + return new string[] { value }; + } + + return null; + } + + public IEnumerable Keys() + { + if (this.ActivityId != null) + { + yield return HttpConstants.HttpHeaders.ActivityId; + } + if (this.LastStateChangeUtc != null) + { + yield return HttpConstants.HttpHeaders.LastStateChangeUtc; + } + if (this.Continuation != null) + { + yield return HttpConstants.HttpHeaders.Continuation; + } + if (this.ETag != null) + { + yield return HttpConstants.HttpHeaders.ETag; + } + if (this.RetryAfterInMilliseconds != null) + { + yield return HttpConstants.HttpHeaders.RetryAfterInMilliseconds; + } + if (this.IndexingDirective != null) + { + yield return HttpConstants.HttpHeaders.IndexingDirective; + } + if (this.MaxResourceQuota != null) + { + yield return HttpConstants.HttpHeaders.MaxResourceQuota; + } + if (this.CurrentResourceQuotaUsage != null) + { + yield return HttpConstants.HttpHeaders.CurrentResourceQuotaUsage; + } + if (this.SchemaVersion != null) + { + yield return HttpConstants.HttpHeaders.SchemaVersion; + } + if (this.CollectionPartitionIndex != null) + { + yield return WFConstants.BackendHeaders.CollectionPartitionIndex; + } + if (this.CollectionServiceIndex != null) + { + yield return WFConstants.BackendHeaders.CollectionServiceIndex; + } + if (this.LSN != null) + { + yield return WFConstants.BackendHeaders.LSN; + } + if (this.ItemCount != null) + { + yield return HttpConstants.HttpHeaders.ItemCount; + } + if (this.RequestCharge != null) + { + yield return HttpConstants.HttpHeaders.RequestCharge; + } + if (this.OwnerFullName != null) + { + yield return HttpConstants.HttpHeaders.OwnerFullName; + } + if (this.OwnerId != null) + { + yield return HttpConstants.HttpHeaders.OwnerId; + } + if (this.DatabaseAccountId != null) + { + yield return WFConstants.BackendHeaders.DatabaseAccountId; + } + if (this.QuorumAckedLSN != null) + { + yield return WFConstants.BackendHeaders.QuorumAckedLSN; + } + if (this.RequestValidationFailure != null) + { + yield return WFConstants.BackendHeaders.RequestValidationFailure; + } + if (this.SubStatus != null) + { + yield return WFConstants.BackendHeaders.SubStatus; + } + if (this.CollectionIndexTransformationProgress != null) + { + yield return HttpConstants.HttpHeaders.CollectionIndexTransformationProgress; + } + if (this.CurrentWriteQuorum != null) + { + yield return WFConstants.BackendHeaders.CurrentWriteQuorum; + } + if (this.CurrentReplicaSetSize != null) + { + yield return WFConstants.BackendHeaders.CurrentReplicaSetSize; + } + if (this.CollectionLazyIndexingProgress != null) + { + yield return HttpConstants.HttpHeaders.CollectionLazyIndexingProgress; + } + if (this.PartitionKeyRangeId != null) + { + yield return WFConstants.BackendHeaders.PartitionKeyRangeId; + } + if (this.LogResults != null) + { + yield return HttpConstants.HttpHeaders.LogResults; + } + if (this.XPRole != null) + { + yield return WFConstants.BackendHeaders.XPRole; + } + if (this.IsRUPerMinuteUsed != null) + { + yield return WFConstants.BackendHeaders.IsRUPerMinuteUsed; + } + if (this.QueryMetrics != null) + { + yield return WFConstants.BackendHeaders.QueryMetrics; + } + if (this.QueryExecutionInfo != null) + { + yield return WFConstants.BackendHeaders.QueryExecutionInfo; + } + if (this.IndexUtilization != null) + { + yield return WFConstants.BackendHeaders.IndexUtilization; + } + if (this.GlobalCommittedLSN != null) + { + yield return WFConstants.BackendHeaders.GlobalCommittedLSN; + } + if (this.NumberOfReadRegions != null) + { + yield return WFConstants.BackendHeaders.NumberOfReadRegions; + } + if (this.OfferReplacePending != null) + { + yield return WFConstants.BackendHeaders.OfferReplacePending; + } + if (this.ItemLSN != null) + { + yield return WFConstants.BackendHeaders.ItemLSN; + } + if (this.RestoreState != null) + { + yield return WFConstants.BackendHeaders.RestoreState; + } + if (this.CollectionSecurityIdentifier != null) + { + yield return WFConstants.BackendHeaders.CollectionSecurityIdentifier; + } + if (this.TransportRequestID != null) + { + yield return HttpConstants.HttpHeaders.TransportRequestID; + } + if (this.ShareThroughput != null) + { + yield return WFConstants.BackendHeaders.ShareThroughput; + } + if (this.DisableRntbdChannel != null) + { + yield return HttpConstants.HttpHeaders.DisableRntbdChannel; + } + if (this.XDate != null) + { + yield return HttpConstants.HttpHeaders.XDate; + } + if (this.LocalLSN != null) + { + yield return WFConstants.BackendHeaders.LocalLSN; + } + if (this.QuorumAckedLocalLSN != null) + { + yield return WFConstants.BackendHeaders.QuorumAckedLocalLSN; + } + if (this.ItemLocalLSN != null) + { + yield return WFConstants.BackendHeaders.ItemLocalLSN; + } + if (this.HasTentativeWrites != null) + { + yield return WFConstants.BackendHeaders.HasTentativeWrites; + } + if (this.SessionToken != null) + { + yield return HttpConstants.HttpHeaders.SessionToken; + } + if (this.ReplicatorLSNToGLSNDelta != null) + { + yield return WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta; + } + if (this.ReplicatorLSNToLLSNDelta != null) + { + yield return WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta; + } + if (this.VectorClockLocalProgress != null) + { + yield return WFConstants.BackendHeaders.VectorClockLocalProgress; + } + if (this.MinimumRUsForOffer != null) + { + yield return WFConstants.BackendHeaders.MinimumRUsForOffer; + } + if (this.XPConfigurationSessionsCount != null) + { + yield return WFConstants.BackendHeaders.XPConfigurationSessionsCount; + } + if (this.UnflushedMergLogEntryCount != null) + { + yield return WFConstants.BackendHeaders.UnflushedMergLogEntryCount; + } + if (this.ResourceId != null) + { + yield return WFConstants.BackendHeaders.ResourceId; + } + if (this.TimeToLiveInSeconds != null) + { + yield return WFConstants.BackendHeaders.TimeToLiveInSeconds; + } + if (this.ReplicaStatusRevoked != null) + { + yield return WFConstants.BackendHeaders.ReplicaStatusRevoked; + } + if (this.SoftMaxAllowedThroughput != null) + { + yield return WFConstants.BackendHeaders.SoftMaxAllowedThroughput; + } + if (this.BackendRequestDurationMilliseconds != null) + { + yield return HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds; + } + if (this.ServerVersion != null) + { + yield return HttpConstants.HttpHeaders.ServerVersion; + } + if (this.ConfirmedStoreChecksum != null) + { + yield return HttpConstants.HttpHeaders.ConfirmedStoreChecksum; + } + if (this.TentativeStoreChecksum != null) + { + yield return HttpConstants.HttpHeaders.TentativeStoreChecksum; + } + if (this.CorrelatedActivityId != null) + { + yield return WFConstants.BackendHeaders.CorrelatedActivityId; + } + if (this.PendingPKDelete != null) + { + yield return WFConstants.BackendHeaders.PendingPKDelete; + } + if (this.AadAppliedRoleAssignmentId != null) + { + yield return HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId; + } + if (this.CollectionUniqueIndexReIndexProgress != null) + { + yield return WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress; + } + if (this.CollectionUniqueKeysUnderReIndex != null) + { + yield return WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex; + } + if (this.AnalyticalMigrationProgress != null) + { + yield return WFConstants.BackendHeaders.AnalyticalMigrationProgress; + } + if (this.TotalAccountThroughput != null) + { + yield return HttpConstants.HttpHeaders.TotalAccountThroughput; + } + if (this.ByokEncryptionProgress != null) + { + yield return WFConstants.BackendHeaders.ByokEncryptionProgress; + } + if (this.AppliedPolicyElementId != null) + { + yield return HttpConstants.HttpHeaders.AppliedPolicyElementId; + } + if (this.MergeProgressBlocked != null) + { + yield return WFConstants.BackendHeaders.MergeProgressBlocked; + } + if (this.ChangeFeedInfo != null) + { + yield return HttpConstants.HttpHeaders.ChangeFeedInfo; + } + if (this.ReIndexerProgress != null) + { + yield return WFConstants.BackendHeaders.ReIndexerProgress; + } + if (this.OfferReplacePendingForMerge != null) + { + yield return WFConstants.BackendHeaders.OfferReplacePendingForMerge; + } + if (this.OldestActiveSchemaId != null) + { + yield return WFConstants.BackendHeaders.OldestActiveSchemaId; + } + if (this.PhysicalPartitionId != null) + { + yield return HttpConstants.HttpHeaders.PhysicalPartitionId; + } + if (this.MaxContentLength != null) + { + yield return HttpConstants.HttpHeaders.MaxContentLength; + } + if (this.IsOfferRestorePending != null) + { + yield return HttpConstants.HttpHeaders.IsOfferRestorePending; + } + if (this.InstantScaleUpValue != null) + { + yield return HttpConstants.HttpHeaders.InstantScaleUpValue; + } + if (this.RequiresDistribution != null) + { + yield return WFConstants.BackendHeaders.RequiresDistribution; + } + if (this.CapacityType != null) + { + yield return HttpConstants.HttpHeaders.CapacityType; + } + if (this.MinGLSNForTombstoneOperations != null) + { + yield return WFConstants.BackendHeaders.MinGLSNForTombstoneOperations; + } + if (this.MinGLSNForDocumentOperations != null) + { + yield return WFConstants.BackendHeaders.MinGLSNForDocumentOperations; + } + if (this.HighestTentativeWriteLLSN != null) + { + yield return WFConstants.BackendHeaders.HighestTentativeWriteLLSN; + } + if (this.PartitionThroughputInfo != null) + { + yield return WFConstants.BackendHeaders.PartitionThroughputInfo; + } + if (this.DocumentRecordCount != null) + { + yield return WFConstants.BackendHeaders.DocumentRecordCount; + } + if (this.CosmosGatewayTransactionId != null) + { + yield return WFConstants.BackendHeaders.CosmosGatewayTransactionId; + } + if (this.UserStrings != null) + { + yield return WFConstants.BackendHeaders.UserStrings; + } + + if (this.lazyNotCommonHeaders != null) + { + foreach (string key in this.lazyNotCommonHeaders.Keys) + { + yield return key; + } + } + } + + public NameValueCollection ToNameValueCollection() + { + // Note: See comment on line 34 of this file for the implementation. We need to respect current contracts + // for Backend Gateway. + if (this.nameValueCollection == null) + { + lock (this) + { + if (this.nameValueCollection == null) + { + this.nameValueCollection = new NameValueCollection(this.Count(), StoreResponseNameValueCollection.DefaultStringComparer); + + if (this.ActivityId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); + } + if (this.LastStateChangeUtc != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.LastStateChangeUtc, this.LastStateChangeUtc); + } + if (this.Continuation != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.Continuation, this.Continuation); + } + if (this.ETag != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ETag, this.ETag); + } + if (this.RetryAfterInMilliseconds != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, this.RetryAfterInMilliseconds); + } + if (this.IndexingDirective != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IndexingDirective, this.IndexingDirective); + } + if (this.MaxResourceQuota != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxResourceQuota, this.MaxResourceQuota); + } + if (this.CurrentResourceQuotaUsage != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, this.CurrentResourceQuotaUsage); + } + if (this.SchemaVersion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SchemaVersion, this.SchemaVersion); + } + if (this.CollectionPartitionIndex != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionPartitionIndex, this.CollectionPartitionIndex); + } + if (this.CollectionServiceIndex != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionServiceIndex, this.CollectionServiceIndex); + } + if (this.LSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.LSN, this.LSN); + } + if (this.ItemCount != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ItemCount, this.ItemCount); + } + if (this.RequestCharge != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.RequestCharge, this.RequestCharge); + } + if (this.OwnerFullName != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.OwnerFullName, this.OwnerFullName); + } + if (this.OwnerId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.OwnerId, this.OwnerId); + } + if (this.DatabaseAccountId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.DatabaseAccountId, this.DatabaseAccountId); + } + if (this.QuorumAckedLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.QuorumAckedLSN, this.QuorumAckedLSN); + } + if (this.RequestValidationFailure != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RequestValidationFailure, this.RequestValidationFailure); + } + if (this.SubStatus != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SubStatus, this.SubStatus); + } + if (this.CollectionIndexTransformationProgress != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, this.CollectionIndexTransformationProgress); + } + if (this.CurrentWriteQuorum != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CurrentWriteQuorum, this.CurrentWriteQuorum); + } + if (this.CurrentReplicaSetSize != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CurrentReplicaSetSize, this.CurrentReplicaSetSize); + } + if (this.CollectionLazyIndexingProgress != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, this.CollectionLazyIndexingProgress); + } + if (this.PartitionKeyRangeId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionKeyRangeId, this.PartitionKeyRangeId); + } + if (this.LogResults != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.LogResults, this.LogResults); + } + if (this.XPRole != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.XPRole, this.XPRole); + } + if (this.IsRUPerMinuteUsed != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRUPerMinuteUsed, this.IsRUPerMinuteUsed); + } + if (this.QueryMetrics != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.QueryMetrics, this.QueryMetrics); + } + if (this.QueryExecutionInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.QueryExecutionInfo, this.QueryExecutionInfo); + } + if (this.IndexUtilization != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IndexUtilization, this.IndexUtilization); + } + if (this.GlobalCommittedLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.GlobalCommittedLSN, this.GlobalCommittedLSN); + } + if (this.NumberOfReadRegions != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.NumberOfReadRegions, this.NumberOfReadRegions); + } + if (this.OfferReplacePending != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.OfferReplacePending, this.OfferReplacePending); + } + if (this.ItemLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ItemLSN, this.ItemLSN); + } + if (this.RestoreState != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RestoreState, this.RestoreState); + } + if (this.CollectionSecurityIdentifier != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionSecurityIdentifier, this.CollectionSecurityIdentifier); + } + if (this.TransportRequestID != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TransportRequestID, this.TransportRequestID); + } + if (this.ShareThroughput != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ShareThroughput, this.ShareThroughput); + } + if (this.DisableRntbdChannel != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.DisableRntbdChannel, this.DisableRntbdChannel); + } + if (this.XDate != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.XDate, this.XDate); + } + if (this.LocalLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.LocalLSN, this.LocalLSN); + } + if (this.QuorumAckedLocalLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.QuorumAckedLocalLSN, this.QuorumAckedLocalLSN); + } + if (this.ItemLocalLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ItemLocalLSN, this.ItemLocalLSN); + } + if (this.HasTentativeWrites != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.HasTentativeWrites, this.HasTentativeWrites); + } + if (this.SessionToken != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SessionToken, this.SessionToken); + } + if (this.ReplicatorLSNToGLSNDelta != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, this.ReplicatorLSNToGLSNDelta); + } + if (this.ReplicatorLSNToLLSNDelta != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, this.ReplicatorLSNToLLSNDelta); + } + if (this.VectorClockLocalProgress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.VectorClockLocalProgress, this.VectorClockLocalProgress); + } + if (this.MinimumRUsForOffer != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.MinimumRUsForOffer, this.MinimumRUsForOffer); + } + if (this.XPConfigurationSessionsCount != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.XPConfigurationSessionsCount, this.XPConfigurationSessionsCount); + } + if (this.UnflushedMergLogEntryCount != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, this.UnflushedMergLogEntryCount); + } + if (this.ResourceId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ResourceId, this.ResourceId); + } + if (this.TimeToLiveInSeconds != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.TimeToLiveInSeconds, this.TimeToLiveInSeconds); + } + if (this.ReplicaStatusRevoked != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ReplicaStatusRevoked, this.ReplicaStatusRevoked); + } + if (this.SoftMaxAllowedThroughput != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, this.SoftMaxAllowedThroughput); + } + if (this.BackendRequestDurationMilliseconds != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, this.BackendRequestDurationMilliseconds); + } + if (this.ServerVersion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ServerVersion, this.ServerVersion); + } + if (this.ConfirmedStoreChecksum != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, this.ConfirmedStoreChecksum); + } + if (this.TentativeStoreChecksum != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TentativeStoreChecksum, this.TentativeStoreChecksum); + } + if (this.CorrelatedActivityId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CorrelatedActivityId, this.CorrelatedActivityId); + } + if (this.PendingPKDelete != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PendingPKDelete, this.PendingPKDelete); + } + if (this.AadAppliedRoleAssignmentId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, this.AadAppliedRoleAssignmentId); + } + if (this.CollectionUniqueIndexReIndexProgress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, this.CollectionUniqueIndexReIndexProgress); + } + if (this.CollectionUniqueKeysUnderReIndex != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, this.CollectionUniqueKeysUnderReIndex); + } + if (this.AnalyticalMigrationProgress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.AnalyticalMigrationProgress, this.AnalyticalMigrationProgress); + } + if (this.TotalAccountThroughput != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.TotalAccountThroughput, this.TotalAccountThroughput); + } + if (this.ByokEncryptionProgress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ByokEncryptionProgress, this.ByokEncryptionProgress); + } + if (this.AppliedPolicyElementId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AppliedPolicyElementId, this.AppliedPolicyElementId); + } + if (this.MergeProgressBlocked != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.MergeProgressBlocked, this.MergeProgressBlocked); + } + if (this.ChangeFeedInfo != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ChangeFeedInfo, this.ChangeFeedInfo); + } + if (this.ReIndexerProgress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ReIndexerProgress, this.ReIndexerProgress); + } + if (this.OfferReplacePendingForMerge != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.OfferReplacePendingForMerge, this.OfferReplacePendingForMerge); + } + if (this.OldestActiveSchemaId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.OldestActiveSchemaId, this.OldestActiveSchemaId); + } + if (this.PhysicalPartitionId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.PhysicalPartitionId, this.PhysicalPartitionId); + } + if (this.MaxContentLength != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.MaxContentLength, this.MaxContentLength); + } + if (this.IsOfferRestorePending != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsOfferRestorePending, this.IsOfferRestorePending); + } + if (this.InstantScaleUpValue != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.InstantScaleUpValue, this.InstantScaleUpValue); + } + if (this.RequiresDistribution != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.RequiresDistribution, this.RequiresDistribution); + } + if (this.CapacityType != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.CapacityType, this.CapacityType); + } + if (this.MinGLSNForTombstoneOperations != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, this.MinGLSNForTombstoneOperations); + } + if (this.MinGLSNForDocumentOperations != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, this.MinGLSNForDocumentOperations); + } + if (this.HighestTentativeWriteLLSN != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); + } + if (this.PartitionThroughputInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); + } + if (this.DocumentRecordCount != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.DocumentRecordCount, this.DocumentRecordCount); + } + if (this.CosmosGatewayTransactionId != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.CosmosGatewayTransactionId, this.CosmosGatewayTransactionId); + } + if (this.UserStrings != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.UserStrings, this.UserStrings); + } + if(this.lazyNotCommonHeaders != null) + { + foreach (KeyValuePair keyValuePair in this.lazyNotCommonHeaders) + { + this.nameValueCollection.Add(keyValuePair.Key, keyValuePair.Value); + } + } + } + } + } + + return this.nameValueCollection; + } + + public void Remove(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + this.UpdateHelper( + key: key, + value: null, + throwIfAlreadyExists: false); + } + + public string Get(string key) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + switch (key.Length) + { + case 3: + if (string.Equals(WFConstants.BackendHeaders.LSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.LSN; + } + + break; + case 4: + if (string.Equals(HttpConstants.HttpHeaders.ETag, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ETag; + } + + break; + case 9: + if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.XDate; + } + + break; + case 12: + if (string.Equals(WFConstants.BackendHeaders.XPRole, key, StringComparison.OrdinalIgnoreCase)) + { + return this.XPRole; + } + + break; + case 13: + if (string.Equals(WFConstants.BackendHeaders.ItemLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ItemLSN; + } + + break; + case 14: + if (string.Equals(WFConstants.BackendHeaders.SubStatus, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SubStatus; + } + + break; + case 15: + if (string.Equals(HttpConstants.HttpHeaders.ItemCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ItemCount; + } + + break; + case 16: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + return this.ActivityId; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.LocalLSN, key)) + { + return this.LocalLSN; + } + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ActivityId; + } + + if (string.Equals(WFConstants.BackendHeaders.LocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.LocalLSN; + } + + break; + case 17: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) + { + return this.Continuation; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerId, key)) + { + return this.OwnerId; + } + if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) + { + return this.Continuation; + } + + if (string.Equals(HttpConstants.HttpHeaders.OwnerId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OwnerId; + } + + break; + case 18: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SchemaVersion, key)) + { + return this.SchemaVersion; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreState, key)) + { + return this.RestoreState; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) + { + return this.SessionToken; + } + if (string.Equals(HttpConstants.HttpHeaders.SchemaVersion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SchemaVersion; + } + + if (string.Equals(WFConstants.BackendHeaders.RestoreState, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RestoreState; + } + + if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SessionToken; + } + + break; + case 19: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key)) + { + return this.RetryAfterInMilliseconds; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxResourceQuota, key)) + { + return this.MaxResourceQuota; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key)) + { + return this.CurrentResourceQuotaUsage; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RequestCharge, key)) + { + return this.RequestCharge; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) + { + return this.ResourceId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ServerVersion, key)) + { + return this.ServerVersion; + } + if (string.Equals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RetryAfterInMilliseconds; + } + + if (string.Equals(HttpConstants.HttpHeaders.MaxResourceQuota, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MaxResourceQuota; + } + + if (string.Equals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CurrentResourceQuotaUsage; + } + + if (string.Equals(HttpConstants.HttpHeaders.RequestCharge, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RequestCharge; + } + + if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ResourceId; + } + + if (string.Equals(HttpConstants.HttpHeaders.ServerVersion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ServerVersion; + } + + break; + case 21: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerFullName, key)) + { + return this.OwnerFullName; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLSN, key)) + { + return this.QuorumAckedLSN; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) + { + return this.ShareThroughput; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ItemLocalLSN, key)) + { + return this.ItemLocalLSN; + } + if (string.Equals(HttpConstants.HttpHeaders.OwnerFullName, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OwnerFullName; + } + + if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QuorumAckedLSN; + } + + if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ShareThroughput; + } + + if (string.Equals(WFConstants.BackendHeaders.ItemLocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ItemLocalLSN; + } + + break; + case 23: + if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IndexingDirective; + } + + break; + case 24: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) + { + return this.CollectionServiceIndex; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.DatabaseAccountId, key)) + { + return this.DatabaseAccountId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key)) + { + return this.BackendRequestDurationMilliseconds; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UserStrings, key)) + { + return this.UserStrings; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionServiceIndex; + } + + if (string.Equals(WFConstants.BackendHeaders.DatabaseAccountId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.DatabaseAccountId; + } + + if (string.Equals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + return this.BackendRequestDurationMilliseconds; + } + + if (string.Equals(WFConstants.BackendHeaders.UserStrings, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UserStrings; + } + + break; + case 25: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentWriteQuorum, key)) + { + return this.CurrentWriteQuorum; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.GlobalCommittedLSN, key)) + { + return this.GlobalCommittedLSN; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) + { + return this.TransportRequestID; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CapacityType, key)) + { + return this.CapacityType; + } + if (string.Equals(WFConstants.BackendHeaders.CurrentWriteQuorum, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CurrentWriteQuorum; + } + + if (string.Equals(WFConstants.BackendHeaders.GlobalCommittedLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.GlobalCommittedLSN; + } + + if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TransportRequestID; + } + + if (string.Equals(HttpConstants.HttpHeaders.CapacityType, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CapacityType; + } + + break; + case 26: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.LastStateChangeUtc, key)) + { + return this.LastStateChangeUtc; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) + { + return this.CollectionPartitionIndex; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePending, key)) + { + return this.OfferReplacePending; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRntbdChannel, key)) + { + return this.DisableRntbdChannel; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinimumRUsForOffer, key)) + { + return this.MinimumRUsForOffer; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferRestorePending, key)) + { + return this.IsOfferRestorePending; + } + if (string.Equals(HttpConstants.HttpHeaders.LastStateChangeUtc, key, StringComparison.OrdinalIgnoreCase)) + { + return this.LastStateChangeUtc; + } + + if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionPartitionIndex; + } + + if (string.Equals(WFConstants.BackendHeaders.OfferReplacePending, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OfferReplacePending; + } + + if (string.Equals(HttpConstants.HttpHeaders.DisableRntbdChannel, key, StringComparison.OrdinalIgnoreCase)) + { + return this.DisableRntbdChannel; + } + + if (string.Equals(WFConstants.BackendHeaders.MinimumRUsForOffer, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MinimumRUsForOffer; + } + + if (string.Equals(HttpConstants.HttpHeaders.IsOfferRestorePending, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsOfferRestorePending; + } + + break; + case 27: + if (object.ReferenceEquals(WFConstants.BackendHeaders.NumberOfReadRegions, key)) + { + return this.NumberOfReadRegions; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key)) + { + return this.AppliedPolicyElementId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedInfo, key)) + { + return this.ChangeFeedInfo; + } + if (string.Equals(WFConstants.BackendHeaders.NumberOfReadRegions, key, StringComparison.OrdinalIgnoreCase)) + { + return this.NumberOfReadRegions; + } + + if (string.Equals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AppliedPolicyElementId; + } + + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ChangeFeedInfo; + } + + break; + case 28: + if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TimeToLiveInSeconds; + } + + break; + case 29: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key)) + { + return this.CurrentReplicaSetSize; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryMetrics, key)) + { + return this.QueryMetrics; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IndexUtilization, key)) + { + return this.IndexUtilization; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key)) + { + return this.QuorumAckedLocalLSN; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key)) + { + return this.MinGLSNForDocumentOperations; + } + if (string.Equals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CurrentReplicaSetSize; + } + + if (string.Equals(WFConstants.BackendHeaders.QueryMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QueryMetrics; + } + + if (string.Equals(WFConstants.BackendHeaders.IndexUtilization, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IndexUtilization; + } + + if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QuorumAckedLocalLSN; + } + + if (string.Equals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MinGLSNForDocumentOperations; + } + + break; + case 30: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReIndexerProgress, key)) + { + return this.ReIndexerProgress; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxContentLength, key)) + { + return this.MaxContentLength; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key)) + { + return this.MinGLSNForTombstoneOperations; + } + if (string.Equals(WFConstants.BackendHeaders.ReIndexerProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ReIndexerProgress; + } + + if (string.Equals(HttpConstants.HttpHeaders.MaxContentLength, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MaxContentLength; + } + + if (string.Equals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MinGLSNForTombstoneOperations; + } + + break; + case 31: + if (string.Equals(WFConstants.BackendHeaders.RequestValidationFailure, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RequestValidationFailure; + } + + break; + case 32: + if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryExecutionInfo, key)) + { + return this.QueryExecutionInfo; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key)) + { + return this.AadAppliedRoleAssignmentId; + } + if (string.Equals(WFConstants.BackendHeaders.QueryExecutionInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QueryExecutionInfo; + } + + if (string.Equals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AadAppliedRoleAssignmentId; + } + + break; + case 33: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key)) + { + return this.ReplicatorLSNToGLSNDelta; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key)) + { + return this.ReplicatorLSNToLLSNDelta; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CorrelatedActivityId, key)) + { + return this.CorrelatedActivityId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PhysicalPartitionId, key)) + { + return this.PhysicalPartitionId; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.DocumentRecordCount, key)) + { + return this.DocumentRecordCount; + } + if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ReplicatorLSNToGLSNDelta; + } + + if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ReplicatorLSNToLLSNDelta; + } + + if (string.Equals(WFConstants.BackendHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CorrelatedActivityId; + } + + if (string.Equals(HttpConstants.HttpHeaders.PhysicalPartitionId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PhysicalPartitionId; + } + + if (string.Equals(WFConstants.BackendHeaders.DocumentRecordCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.DocumentRecordCount; + } + + break; + case 34: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.LogResults, key)) + { + return this.LogResults; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.HasTentativeWrites, key)) + { + return this.HasTentativeWrites; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.InstantScaleUpValue, key)) + { + return this.InstantScaleUpValue; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key)) + { + return this.CosmosGatewayTransactionId; + } + if (string.Equals(HttpConstants.HttpHeaders.LogResults, key, StringComparison.OrdinalIgnoreCase)) + { + return this.LogResults; + } + + if (string.Equals(WFConstants.BackendHeaders.HasTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + return this.HasTentativeWrites; + } + + if (string.Equals(HttpConstants.HttpHeaders.InstantScaleUpValue, key, StringComparison.OrdinalIgnoreCase)) + { + return this.InstantScaleUpValue; + } + + if (string.Equals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CosmosGatewayTransactionId; + } + + break; + case 35: + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionKeyRangeId, key)) + { + return this.PartitionKeyRangeId; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key)) + { + return this.CollectionSecurityIdentifier; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OldestActiveSchemaId, key)) + { + return this.OldestActiveSchemaId; + } + if (string.Equals(WFConstants.BackendHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionKeyRangeId; + } + + if (string.Equals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionSecurityIdentifier; + } + + if (string.Equals(WFConstants.BackendHeaders.OldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OldestActiveSchemaId; + } + + break; + case 36: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TotalAccountThroughput, key)) + { + return this.TotalAccountThroughput; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ByokEncryptionProgress, key)) + { + return this.ByokEncryptionProgress; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key)) + { + return this.OfferReplacePendingForMerge; + } + if (string.Equals(HttpConstants.HttpHeaders.TotalAccountThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TotalAccountThroughput; + } + + if (string.Equals(WFConstants.BackendHeaders.ByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ByokEncryptionProgress; + } + + if (string.Equals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key, StringComparison.OrdinalIgnoreCase)) + { + return this.OfferReplacePendingForMerge; + } + + break; + case 37: + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key)) + { + return this.IsRUPerMinuteUsed; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key)) + { + return this.ReplicaStatusRevoked; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeProgressBlocked, key)) + { + return this.MergeProgressBlocked; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) + { + return this.PartitionThroughputInfo; + } + if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsRUPerMinuteUsed; + } + + if (string.Equals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ReplicaStatusRevoked; + } + + if (string.Equals(WFConstants.BackendHeaders.MergeProgressBlocked, key, StringComparison.OrdinalIgnoreCase)) + { + return this.MergeProgressBlocked; + } + + if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionThroughputInfo; + } + + break; + case 38: + if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) + { + return this.VectorClockLocalProgress; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key)) + { + return this.ConfirmedStoreChecksum; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key)) + { + return this.TentativeStoreChecksum; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RequiresDistribution, key)) + { + return this.RequiresDistribution; + } + if (string.Equals(WFConstants.BackendHeaders.VectorClockLocalProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.VectorClockLocalProgress; + } + + if (string.Equals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ConfirmedStoreChecksum; + } + + if (string.Equals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) + { + return this.TentativeStoreChecksum; + } + + if (string.Equals(WFConstants.BackendHeaders.RequiresDistribution, key, StringComparison.OrdinalIgnoreCase)) + { + return this.RequiresDistribution; + } + + break; + case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) + { + return this.SoftMaxAllowedThroughput; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) + { + return this.HighestTentativeWriteLLSN; + } + if (string.Equals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SoftMaxAllowedThroughput; + } + + if (string.Equals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) + { + return this.HighestTentativeWriteLLSN; + } + + break; + case 41: + if (string.Equals(WFConstants.BackendHeaders.AnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AnalyticalMigrationProgress; + } + + break; + case 42: + if (string.Equals(WFConstants.BackendHeaders.XPConfigurationSessionsCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.XPConfigurationSessionsCount; + } + + break; + case 43: + if (string.Equals(WFConstants.BackendHeaders.PendingPKDelete, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PendingPKDelete; + } + + break; + case 48: + if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionUniqueKeysUnderReIndex; + } + + break; + case 49: + if (string.Equals(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionLazyIndexingProgress; + } + + break; + case 52: + if (object.ReferenceEquals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key)) + { + return this.UnflushedMergLogEntryCount; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key)) + { + return this.CollectionUniqueIndexReIndexProgress; + } + if (string.Equals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key, StringComparison.OrdinalIgnoreCase)) + { + return this.UnflushedMergLogEntryCount; + } + + if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionUniqueIndexReIndexProgress; + } + + break; + case 56: + if (string.Equals(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.CollectionIndexTransformationProgress; + } + + break; + default: + break; + } + + if (this.lazyNotCommonHeaders?.TryGetValue(key, out string value) ?? false) + { + return value; + } + + return null; + } + + public void Add(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + this.UpdateHelper( + key: key, + value: value, + throwIfAlreadyExists: true); + } + + public void Set(string key, string value) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + this.UpdateHelper( + key: key, + value: value, + throwIfAlreadyExists: false); + } + + public void UpdateHelper( + string key, + string value, + bool throwIfAlreadyExists) + { + if (key == null) + { + throw new ArgumentNullException(nameof(key)); + } + + switch (key.Length) + { + case 3: + if (string.Equals(WFConstants.BackendHeaders.LSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.LSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LSN = value; + return; + } + break; + case 4: + if (string.Equals(HttpConstants.HttpHeaders.ETag, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ETag != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ETag = value; + return; + } + break; + case 9: + if (string.Equals(HttpConstants.HttpHeaders.XDate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.XDate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.XDate = value; + return; + } + break; + case 12: + if (string.Equals(WFConstants.BackendHeaders.XPRole, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.XPRole != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.XPRole = value; + return; + } + break; + case 13: + if (string.Equals(WFConstants.BackendHeaders.ItemLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ItemLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ItemLSN = value; + return; + } + break; + case 14: + if (string.Equals(WFConstants.BackendHeaders.SubStatus, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SubStatus != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SubStatus = value; + return; + } + break; + case 15: + if (string.Equals(HttpConstants.HttpHeaders.ItemCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ItemCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ItemCount = value; + return; + } + break; + case 16: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.LocalLSN, key)) + { + if (throwIfAlreadyExists && this.LocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LocalLSN = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.LocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.LocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LocalLSN = value; + return; + } + break; + case 17: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) + { + if (throwIfAlreadyExists && this.Continuation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Continuation = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerId, key)) + { + if (throwIfAlreadyExists && this.OwnerId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OwnerId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.Continuation, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.Continuation != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.Continuation = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.OwnerId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OwnerId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OwnerId = value; + return; + } + break; + case 18: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SchemaVersion, key)) + { + if (throwIfAlreadyExists && this.SchemaVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaVersion = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RestoreState, key)) + { + if (throwIfAlreadyExists && this.RestoreState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreState = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SessionToken, key)) + { + if (throwIfAlreadyExists && this.SessionToken != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SessionToken = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SchemaVersion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SchemaVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SchemaVersion = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RestoreState, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RestoreState != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RestoreState = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.SessionToken, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SessionToken != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SessionToken = value; + return; + } + break; + case 19: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key)) + { + if (throwIfAlreadyExists && this.RetryAfterInMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetryAfterInMilliseconds = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxResourceQuota, key)) + { + if (throwIfAlreadyExists && this.MaxResourceQuota != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxResourceQuota = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key)) + { + if (throwIfAlreadyExists && this.CurrentResourceQuotaUsage != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentResourceQuotaUsage = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.RequestCharge, key)) + { + if (throwIfAlreadyExists && this.RequestCharge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequestCharge = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ResourceId, key)) + { + if (throwIfAlreadyExists && this.ResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ServerVersion, key)) + { + if (throwIfAlreadyExists && this.ServerVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ServerVersion = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RetryAfterInMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RetryAfterInMilliseconds = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MaxResourceQuota, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MaxResourceQuota != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxResourceQuota = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CurrentResourceQuotaUsage, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CurrentResourceQuotaUsage != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentResourceQuotaUsage = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.RequestCharge, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RequestCharge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequestCharge = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ResourceId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ResourceId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ResourceId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ServerVersion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ServerVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ServerVersion = value; + return; + } + break; + case 21: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OwnerFullName, key)) + { + if (throwIfAlreadyExists && this.OwnerFullName != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OwnerFullName = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLSN, key)) + { + if (throwIfAlreadyExists && this.QuorumAckedLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QuorumAckedLSN = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ShareThroughput, key)) + { + if (throwIfAlreadyExists && this.ShareThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShareThroughput = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ItemLocalLSN, key)) + { + if (throwIfAlreadyExists && this.ItemLocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ItemLocalLSN = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.OwnerFullName, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OwnerFullName != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OwnerFullName = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QuorumAckedLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QuorumAckedLSN = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ShareThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ShareThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ShareThroughput = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ItemLocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ItemLocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ItemLocalLSN = value; + return; + } + break; + case 23: + if (string.Equals(HttpConstants.HttpHeaders.IndexingDirective, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IndexingDirective != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IndexingDirective = value; + return; + } + break; + case 24: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionServiceIndex, key)) + { + if (throwIfAlreadyExists && this.CollectionServiceIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionServiceIndex = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.DatabaseAccountId, key)) + { + if (throwIfAlreadyExists && this.DatabaseAccountId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DatabaseAccountId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key)) + { + if (throwIfAlreadyExists && this.BackendRequestDurationMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BackendRequestDurationMilliseconds = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.UserStrings, key)) + { + if (throwIfAlreadyExists && this.UserStrings != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UserStrings = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionServiceIndex, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionServiceIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionServiceIndex = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.DatabaseAccountId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.DatabaseAccountId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DatabaseAccountId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.BackendRequestDurationMilliseconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.BackendRequestDurationMilliseconds = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UserStrings, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UserStrings != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UserStrings = value; + return; + } + break; + case 25: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentWriteQuorum, key)) + { + if (throwIfAlreadyExists && this.CurrentWriteQuorum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentWriteQuorum = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.GlobalCommittedLSN, key)) + { + if (throwIfAlreadyExists && this.GlobalCommittedLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GlobalCommittedLSN = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TransportRequestID, key)) + { + if (throwIfAlreadyExists && this.TransportRequestID != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransportRequestID = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.CapacityType, key)) + { + if (throwIfAlreadyExists && this.CapacityType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CapacityType = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CurrentWriteQuorum, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CurrentWriteQuorum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentWriteQuorum = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.GlobalCommittedLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.GlobalCommittedLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.GlobalCommittedLSN = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TransportRequestID, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TransportRequestID != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TransportRequestID = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.CapacityType, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CapacityType != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CapacityType = value; + return; + } + break; + case 26: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.LastStateChangeUtc, key)) + { + if (throwIfAlreadyExists && this.LastStateChangeUtc != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LastStateChangeUtc = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) + { + if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionPartitionIndex = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePending, key)) + { + if (throwIfAlreadyExists && this.OfferReplacePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplacePending = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRntbdChannel, key)) + { + if (throwIfAlreadyExists && this.DisableRntbdChannel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DisableRntbdChannel = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinimumRUsForOffer, key)) + { + if (throwIfAlreadyExists && this.MinimumRUsForOffer != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinimumRUsForOffer = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsOfferRestorePending, key)) + { + if (throwIfAlreadyExists && this.IsOfferRestorePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsOfferRestorePending = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.LastStateChangeUtc, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.LastStateChangeUtc != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LastStateChangeUtc = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionPartitionIndex, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionPartitionIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionPartitionIndex = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.OfferReplacePending, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OfferReplacePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplacePending = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.DisableRntbdChannel, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.DisableRntbdChannel != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DisableRntbdChannel = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.MinimumRUsForOffer, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MinimumRUsForOffer != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinimumRUsForOffer = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.IsOfferRestorePending, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsOfferRestorePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsOfferRestorePending = value; + return; + } + break; + case 27: + if (object.ReferenceEquals(WFConstants.BackendHeaders.NumberOfReadRegions, key)) + { + if (throwIfAlreadyExists && this.NumberOfReadRegions != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.NumberOfReadRegions = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key)) + { + if (throwIfAlreadyExists && this.AppliedPolicyElementId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AppliedPolicyElementId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedInfo, key)) + { + if (throwIfAlreadyExists && this.ChangeFeedInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedInfo = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.NumberOfReadRegions, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.NumberOfReadRegions != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.NumberOfReadRegions = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AppliedPolicyElementId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AppliedPolicyElementId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AppliedPolicyElementId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ChangeFeedInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ChangeFeedInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ChangeFeedInfo = value; + return; + } + break; + case 28: + if (string.Equals(WFConstants.BackendHeaders.TimeToLiveInSeconds, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TimeToLiveInSeconds != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TimeToLiveInSeconds = value; + return; + } + break; + case 29: + if (object.ReferenceEquals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key)) + { + if (throwIfAlreadyExists && this.CurrentReplicaSetSize != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentReplicaSetSize = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryMetrics, key)) + { + if (throwIfAlreadyExists && this.QueryMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryMetrics = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IndexUtilization, key)) + { + if (throwIfAlreadyExists && this.IndexUtilization != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IndexUtilization = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key)) + { + if (throwIfAlreadyExists && this.QuorumAckedLocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QuorumAckedLocalLSN = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key)) + { + if (throwIfAlreadyExists && this.MinGLSNForDocumentOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinGLSNForDocumentOperations = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CurrentReplicaSetSize, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CurrentReplicaSetSize != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CurrentReplicaSetSize = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.QueryMetrics, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QueryMetrics != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryMetrics = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IndexUtilization, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IndexUtilization != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IndexUtilization = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.QuorumAckedLocalLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QuorumAckedLocalLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QuorumAckedLocalLSN = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.MinGLSNForDocumentOperations, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MinGLSNForDocumentOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinGLSNForDocumentOperations = value; + return; + } + break; + case 30: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReIndexerProgress, key)) + { + if (throwIfAlreadyExists && this.ReIndexerProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReIndexerProgress = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.MaxContentLength, key)) + { + if (throwIfAlreadyExists && this.MaxContentLength != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxContentLength = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key)) + { + if (throwIfAlreadyExists && this.MinGLSNForTombstoneOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinGLSNForTombstoneOperations = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ReIndexerProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ReIndexerProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReIndexerProgress = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.MaxContentLength, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MaxContentLength != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MaxContentLength = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.MinGLSNForTombstoneOperations, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MinGLSNForTombstoneOperations != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MinGLSNForTombstoneOperations = value; + return; + } + break; + case 31: + if (string.Equals(WFConstants.BackendHeaders.RequestValidationFailure, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RequestValidationFailure != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequestValidationFailure = value; + return; + } + break; + case 32: + if (object.ReferenceEquals(WFConstants.BackendHeaders.QueryExecutionInfo, key)) + { + if (throwIfAlreadyExists && this.QueryExecutionInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryExecutionInfo = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key)) + { + if (throwIfAlreadyExists && this.AadAppliedRoleAssignmentId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AadAppliedRoleAssignmentId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.QueryExecutionInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QueryExecutionInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryExecutionInfo = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AadAppliedRoleAssignmentId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AadAppliedRoleAssignmentId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AadAppliedRoleAssignmentId = value; + return; + } + break; + case 33: + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key)) + { + if (throwIfAlreadyExists && this.ReplicatorLSNToGLSNDelta != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicatorLSNToGLSNDelta = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key)) + { + if (throwIfAlreadyExists && this.ReplicatorLSNToLLSNDelta != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicatorLSNToLLSNDelta = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CorrelatedActivityId, key)) + { + if (throwIfAlreadyExists && this.CorrelatedActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CorrelatedActivityId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.PhysicalPartitionId, key)) + { + if (throwIfAlreadyExists && this.PhysicalPartitionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PhysicalPartitionId = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.DocumentRecordCount, key)) + { + if (throwIfAlreadyExists && this.DocumentRecordCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DocumentRecordCount = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToGLSNDelta, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ReplicatorLSNToGLSNDelta != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicatorLSNToGLSNDelta = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ReplicatorLSNToLLSNDelta, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ReplicatorLSNToLLSNDelta != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicatorLSNToLLSNDelta = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CorrelatedActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CorrelatedActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CorrelatedActivityId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.PhysicalPartitionId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PhysicalPartitionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PhysicalPartitionId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.DocumentRecordCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.DocumentRecordCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.DocumentRecordCount = value; + return; + } + break; + case 34: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.LogResults, key)) + { + if (throwIfAlreadyExists && this.LogResults != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LogResults = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.HasTentativeWrites, key)) + { + if (throwIfAlreadyExists && this.HasTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HasTentativeWrites = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.InstantScaleUpValue, key)) + { + if (throwIfAlreadyExists && this.InstantScaleUpValue != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.InstantScaleUpValue = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key)) + { + if (throwIfAlreadyExists && this.CosmosGatewayTransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CosmosGatewayTransactionId = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.LogResults, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.LogResults != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.LogResults = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.HasTentativeWrites, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.HasTentativeWrites != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HasTentativeWrites = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.InstantScaleUpValue, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.InstantScaleUpValue != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.InstantScaleUpValue = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CosmosGatewayTransactionId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CosmosGatewayTransactionId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CosmosGatewayTransactionId = value; + return; + } + break; + case 35: + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionKeyRangeId, key)) + { + if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKeyRangeId = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key)) + { + if (throwIfAlreadyExists && this.CollectionSecurityIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionSecurityIdentifier = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OldestActiveSchemaId, key)) + { + if (throwIfAlreadyExists && this.OldestActiveSchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OldestActiveSchemaId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PartitionKeyRangeId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionKeyRangeId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionKeyRangeId = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionSecurityIdentifier, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionSecurityIdentifier != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionSecurityIdentifier = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.OldestActiveSchemaId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OldestActiveSchemaId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OldestActiveSchemaId = value; + return; + } + break; + case 36: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TotalAccountThroughput, key)) + { + if (throwIfAlreadyExists && this.TotalAccountThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TotalAccountThroughput = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ByokEncryptionProgress, key)) + { + if (throwIfAlreadyExists && this.ByokEncryptionProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ByokEncryptionProgress = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key)) + { + if (throwIfAlreadyExists && this.OfferReplacePendingForMerge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplacePendingForMerge = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TotalAccountThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TotalAccountThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TotalAccountThroughput = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ByokEncryptionProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ByokEncryptionProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ByokEncryptionProgress = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.OfferReplacePendingForMerge, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.OfferReplacePendingForMerge != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplacePendingForMerge = value; + return; + } + break; + case 37: + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key)) + { + if (throwIfAlreadyExists && this.IsRUPerMinuteUsed != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRUPerMinuteUsed = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key)) + { + if (throwIfAlreadyExists && this.ReplicaStatusRevoked != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicaStatusRevoked = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.MergeProgressBlocked, key)) + { + if (throwIfAlreadyExists && this.MergeProgressBlocked != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeProgressBlocked = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionThroughputInfo = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsRUPerMinuteUsed != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRUPerMinuteUsed = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.ReplicaStatusRevoked, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ReplicaStatusRevoked != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ReplicaStatusRevoked = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.MergeProgressBlocked, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.MergeProgressBlocked != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.MergeProgressBlocked = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionThroughputInfo = value; + return; + } + break; + case 38: + if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) + { + if (throwIfAlreadyExists && this.VectorClockLocalProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.VectorClockLocalProgress = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key)) + { + if (throwIfAlreadyExists && this.ConfirmedStoreChecksum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ConfirmedStoreChecksum = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key)) + { + if (throwIfAlreadyExists && this.TentativeStoreChecksum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TentativeStoreChecksum = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.RequiresDistribution, key)) + { + if (throwIfAlreadyExists && this.RequiresDistribution != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequiresDistribution = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.VectorClockLocalProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.VectorClockLocalProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.VectorClockLocalProgress = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.ConfirmedStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ConfirmedStoreChecksum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ConfirmedStoreChecksum = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.TentativeStoreChecksum, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.TentativeStoreChecksum != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TentativeStoreChecksum = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.RequiresDistribution, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.RequiresDistribution != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.RequiresDistribution = value; + return; + } + break; + case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) + { + if (throwIfAlreadyExists && this.SoftMaxAllowedThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SoftMaxAllowedThroughput = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) + { + if (throwIfAlreadyExists && this.HighestTentativeWriteLLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HighestTentativeWriteLLSN = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SoftMaxAllowedThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SoftMaxAllowedThroughput = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.HighestTentativeWriteLLSN != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.HighestTentativeWriteLLSN = value; + return; + } + break; + case 41: + if (string.Equals(WFConstants.BackendHeaders.AnalyticalMigrationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AnalyticalMigrationProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AnalyticalMigrationProgress = value; + return; + } + break; + case 42: + if (string.Equals(WFConstants.BackendHeaders.XPConfigurationSessionsCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.XPConfigurationSessionsCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.XPConfigurationSessionsCount = value; + return; + } + break; + case 43: + if (string.Equals(WFConstants.BackendHeaders.PendingPKDelete, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PendingPKDelete != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PendingPKDelete = value; + return; + } + break; + case 48: + if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueKeysUnderReIndex, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionUniqueKeysUnderReIndex != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionUniqueKeysUnderReIndex = value; + return; + } + break; + case 49: + if (string.Equals(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionLazyIndexingProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionLazyIndexingProgress = value; + return; + } + break; + case 52: + if (object.ReferenceEquals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key)) + { + if (throwIfAlreadyExists && this.UnflushedMergLogEntryCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UnflushedMergLogEntryCount = value; + return; + } + if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key)) + { + if (throwIfAlreadyExists && this.CollectionUniqueIndexReIndexProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionUniqueIndexReIndexProgress = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.UnflushedMergLogEntryCount, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.UnflushedMergLogEntryCount != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UnflushedMergLogEntryCount = value; + return; + } + if (string.Equals(WFConstants.BackendHeaders.CollectionUniqueIndexReIndexProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionUniqueIndexReIndexProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionUniqueIndexReIndexProgress = value; + return; + } + break; + case 56: + if (string.Equals(HttpConstants.HttpHeaders.CollectionIndexTransformationProgress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.CollectionIndexTransformationProgress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.CollectionIndexTransformationProgress = value; + return; + } + break; + default: + break; + } + + if (throwIfAlreadyExists) + { + this.GetOrCreateLazyHeaders().Add(key, value); + } + else + { + if (value == null) + { + // don't create lazyNotCommonHeaders if it doesn't already exist + + if (this.lazyNotCommonHeaders != null) + { + this.lazyNotCommonHeaders.Remove(key); + } + } + else + { + this.GetOrCreateLazyHeaders()[key] = value; + } + } + } + + private Dictionary GetOrCreateLazyHeaders() + { + Dictionary lazyHeaders = this.lazyNotCommonHeaders; + + if (lazyHeaders == null) + { + // risk over allocating, but everyone will get the same dictionary in the end + Dictionary newDict = new Dictionary(StoreResponseNameValueCollection.DefaultStringComparer); + + // Either swap newDict in (getting back the old null) or obtain the Dictionary some other thread swapped in + // (and then we drop newDict on the floor). + lazyHeaders = Interlocked.CompareExchange(ref this.lazyNotCommonHeaders, newDict, null) ?? newDict; + } + + return lazyHeaders; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreResult.cs b/Microsoft.Azure.Cosmos/src/direct/StoreResult.cs index 986bc3d1f6..bdaf4b6a71 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreResult.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreResult.cs @@ -1,570 +1,570 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Linq; - using System.Net; - using System.Runtime.ExceptionServices; - using System.Text; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Routing; - - internal sealed class StoreResult : IDisposable - { - private readonly StoreResponse storeResponse; - - private static bool UseSessionTokenHeader = VersionUtility.IsLaterThan(HttpConstants.Versions.CurrentVersion, HttpConstants.VersionDates.v2018_06_18); - - public static ReferenceCountedDisposable CreateStoreResult( - StoreResponse storeResponse, - Exception responseException, - bool requiresValidLsn, - bool useLocalLSNBasedHeaders, - IEnumerable replicaHealthStatuses, - Uri storePhysicalAddress = null) - { - if (storeResponse == null && responseException == null) - { - throw new ArgumentException("storeResponse or responseException must be populated."); - } - - if (responseException == null) - { - string headerValue = null; - long quorumAckedLSN = -1; - int currentReplicaSetSize = -1; - int currentWriteQuorum = -1; - long globalCommittedLSN = -1; - int numberOfReadRegions = -1; - long itemLSN = -1; - if (storeResponse.TryGetHeaderValue( - useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.QuorumAckedLocalLSN : WFConstants.BackendHeaders.QuorumAckedLSN, - out headerValue)) - { - quorumAckedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - - if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.CurrentReplicaSetSize, out headerValue)) - { - currentReplicaSetSize = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.CurrentWriteQuorum, out headerValue)) - { - currentWriteQuorum = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - double requestCharge = 0; - if (storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.RequestCharge, out headerValue)) - { - requestCharge = double.Parse(headerValue, CultureInfo.InvariantCulture); - } - - if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.NumberOfReadRegions, out headerValue)) - { - numberOfReadRegions = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.GlobalCommittedLSN, out headerValue)) - { - globalCommittedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - - if (storeResponse.TryGetHeaderValue( - useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.ItemLocalLSN : WFConstants.BackendHeaders.ItemLSN, - out headerValue)) - { - itemLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - - long lsn = -1; - if (useLocalLSNBasedHeaders) - { - if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.LocalLSN, out headerValue)) - { - lsn = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - } - else - { - lsn = storeResponse.LSN; - } - - ISessionToken sessionToken = null; - if (StoreResult.UseSessionTokenHeader) - { - // Session token response header is introduced from version HttpConstants.Versions.v2018_06_18 onwards. - // Previously it was only a request header - if (storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.SessionToken, out headerValue)) - { - sessionToken = SessionTokenHelper.Parse(headerValue); - } - } - else - { - sessionToken = new SimpleSessionToken(storeResponse.LSN); - } - - storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.ActivityId, out string activityId); - storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, out string backendRequestDurationMilliseconds); - storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, out string retryAfterInMs); - - return new ReferenceCountedDisposable(new StoreResult( - storeResponse: storeResponse, - exception: null, - partitionKeyRangeId: storeResponse.PartitionKeyRangeId, - lsn: lsn, - quorumAckedLsn: quorumAckedLSN, - requestCharge: requestCharge, - currentReplicaSetSize: currentReplicaSetSize, - currentWriteQuorum: currentWriteQuorum, - isValid: true, - storePhysicalAddress: storePhysicalAddress, - globalCommittedLSN: globalCommittedLSN, - numberOfReadRegions: numberOfReadRegions, - itemLSN: itemLSN, - sessionToken: sessionToken, - usingLocalLSN: useLocalLSNBasedHeaders, - activityId: activityId, - backendRequestDurationInMs: backendRequestDurationMilliseconds, - retryAfterInMs: retryAfterInMs, - transportRequestStats: storeResponse.TransportRequestStats, - replicaHealthStatuses: replicaHealthStatuses)); - } - else - { - DocumentClientException documentClientException = responseException as DocumentClientException; - if (documentClientException != null) - { - long quorumAckedLSN = -1; - int currentReplicaSetSize = -1; - int currentWriteQuorum = -1; - long globalCommittedLSN = -1; - int numberOfReadRegions = -1; - string headerValue = documentClientException.Headers[useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.QuorumAckedLocalLSN : WFConstants.BackendHeaders.QuorumAckedLSN]; - if (!string.IsNullOrEmpty(headerValue)) - { - quorumAckedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - - headerValue = documentClientException.Headers[WFConstants.BackendHeaders.CurrentReplicaSetSize]; - if (!string.IsNullOrEmpty(headerValue)) - { - currentReplicaSetSize = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - headerValue = documentClientException.Headers[WFConstants.BackendHeaders.CurrentWriteQuorum]; - if (!string.IsNullOrEmpty(headerValue)) - { - currentWriteQuorum = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - double requestCharge = 0; - headerValue = documentClientException.Headers[HttpConstants.HttpHeaders.RequestCharge]; - if (!string.IsNullOrEmpty(headerValue)) - { - requestCharge = double.Parse(headerValue, CultureInfo.InvariantCulture); - } - - headerValue = documentClientException.Headers[WFConstants.BackendHeaders.NumberOfReadRegions]; - if (!string.IsNullOrEmpty(headerValue)) - { - numberOfReadRegions = int.Parse(headerValue, CultureInfo.InvariantCulture); - } - - headerValue = documentClientException.Headers[WFConstants.BackendHeaders.GlobalCommittedLSN]; - if (!string.IsNullOrEmpty(headerValue)) - { - globalCommittedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - - long lsn = -1; - if (useLocalLSNBasedHeaders) - { - headerValue = documentClientException.Headers[WFConstants.BackendHeaders.LocalLSN]; - if (!string.IsNullOrEmpty(headerValue)) - { - lsn = long.Parse(headerValue, CultureInfo.InvariantCulture); - } - } - else - { - lsn = documentClientException.LSN; - } - - ISessionToken sessionToken = null; - if (StoreResult.UseSessionTokenHeader) - { - // Session token response header is introduced from version HttpConstants.Versions.v2018_06_18 onwards. - // Previously it was only a request header - headerValue = documentClientException.Headers[HttpConstants.HttpHeaders.SessionToken]; - if (!string.IsNullOrEmpty(headerValue)) - { - sessionToken = SessionTokenHelper.Parse(headerValue); - } - } - else - { - sessionToken = new SimpleSessionToken(documentClientException.LSN); - } - - return new ReferenceCountedDisposable(new StoreResult( - storeResponse: null, - exception: documentClientException, - partitionKeyRangeId: documentClientException.PartitionKeyRangeId, - lsn: lsn, - quorumAckedLsn: quorumAckedLSN, - requestCharge: requestCharge, - currentReplicaSetSize: currentReplicaSetSize, - currentWriteQuorum: currentWriteQuorum, - isValid: !requiresValidLsn - || ((documentClientException.StatusCode != HttpStatusCode.Gone || documentClientException.GetSubStatus() == SubStatusCodes.NameCacheIsStale) - && lsn >= 0), - storePhysicalAddress: storePhysicalAddress == null ? documentClientException.RequestUri : storePhysicalAddress, - globalCommittedLSN: globalCommittedLSN, - numberOfReadRegions: numberOfReadRegions, - itemLSN: -1, - sessionToken: sessionToken, - usingLocalLSN: useLocalLSNBasedHeaders, - activityId: documentClientException.ActivityId, - backendRequestDurationInMs: documentClientException.Headers[HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds], - retryAfterInMs: documentClientException.Headers[HttpConstants.HttpHeaders.RetryAfterInMilliseconds], - transportRequestStats: documentClientException.TransportRequestStats, - replicaHealthStatuses: replicaHealthStatuses)); - } - else - { - DefaultTrace.TraceCritical("Unexpected exception {0} received while reading from store.", responseException); - return new ReferenceCountedDisposable(new StoreResult( - storeResponse: null, - exception: new InternalServerErrorException(RMResources.InternalServerError, responseException), - partitionKeyRangeId: null, - lsn: -1, - quorumAckedLsn: -1, - requestCharge: 0, - currentReplicaSetSize: 0, - currentWriteQuorum: 0, - isValid: false, - storePhysicalAddress: storePhysicalAddress, - globalCommittedLSN: -1, - numberOfReadRegions: 0, - itemLSN: -1, - sessionToken: null, - usingLocalLSN: useLocalLSNBasedHeaders, - activityId: null, - backendRequestDurationInMs: null, - retryAfterInMs: null, - transportRequestStats: null, - replicaHealthStatuses: replicaHealthStatuses)); - } - } - } - - public static ReferenceCountedDisposable CreateForTesting(StoreResponse storeResponse) - { - return new ReferenceCountedDisposable( - new StoreResult( - storeResponse, exception: null, null, default, default, default, default, default, default, - default, default, default, default, default, default, default, default, default, default, default)); - } - - public static ReferenceCountedDisposable CreateForTesting(TransportRequestStats transportRequestStats) - { - return new ReferenceCountedDisposable(new Documents.StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: 42.ToString(), - lsn: 1337, - quorumAckedLsn: 23, - requestCharge: 3.14, - currentReplicaSetSize: 4, - currentWriteQuorum: 3, - isValid: true, - storePhysicalAddress: new Uri("http://storephysicaladdress.com"), - globalCommittedLSN: 1234, - numberOfReadRegions: 13, - itemLSN: 15, - sessionToken: new SimpleSessionToken(42), - usingLocalLSN: true, - activityId: Guid.Empty.ToString(), - backendRequestDurationInMs: "4.2", - retryAfterInMs: "9000", - transportRequestStats: transportRequestStats, - replicaHealthStatuses: new List() - { - "http://storephysicaladdress-1p.com:Connected", - "http://storephysicaladdress-2s.com:Unknown", - "http://storephysicaladdress-3s.com:Unhealthy", - "http://storephysicaladdress-4s.com:Unknown" - })); - } - - public static ReferenceCountedDisposable CreateForTesting(string partitionKeyRangeId) - { - return new ReferenceCountedDisposable(new StoreResult( - storeResponse: new StoreResponse(), - exception: null, - partitionKeyRangeId: partitionKeyRangeId, - lsn: 0, - quorumAckedLsn: 0, - requestCharge: 0, - currentReplicaSetSize: 0, - currentWriteQuorum: 0, - isValid: true, - storePhysicalAddress: null, - globalCommittedLSN: 0, - numberOfReadRegions: 0, - itemLSN: 0, - sessionToken: null, - usingLocalLSN: true, - activityId: Guid.NewGuid().ToString(), - backendRequestDurationInMs: "10", - retryAfterInMs: "20", - transportRequestStats: new TransportRequestStats(), - replicaHealthStatuses: null)); - } - - private StoreResult( - StoreResponse storeResponse, - DocumentClientException exception, - string partitionKeyRangeId, - long lsn, - long quorumAckedLsn, - double requestCharge, - int currentReplicaSetSize, - int currentWriteQuorum, - bool isValid, - Uri storePhysicalAddress, - long globalCommittedLSN, - int numberOfReadRegions, - long itemLSN, - ISessionToken sessionToken, - bool usingLocalLSN, - string activityId, - string backendRequestDurationInMs, - string retryAfterInMs, - TransportRequestStats transportRequestStats, - IEnumerable replicaHealthStatuses) - { - if (storeResponse == null && exception == null) - { - throw new ArgumentException("storeResponse or responseException must be populated."); - } - - this.storeResponse = storeResponse; - this.Exception = exception; - this.PartitionKeyRangeId = partitionKeyRangeId; - this.LSN = lsn; - this.QuorumAckedLSN = quorumAckedLsn; - this.RequestCharge = requestCharge; - this.CurrentReplicaSetSize = currentReplicaSetSize; - this.CurrentWriteQuorum = currentWriteQuorum; - this.IsValid = isValid; - - this.StorePhysicalAddress = storePhysicalAddress; - this.GlobalCommittedLSN = globalCommittedLSN; - this.NumberOfReadRegions = numberOfReadRegions; - this.ItemLSN = itemLSN; - this.SessionToken = sessionToken; - this.UsingLocalLSN = usingLocalLSN; - this.ActivityId = activityId; - this.BackendRequestDurationInMs = backendRequestDurationInMs; - this.RetryAfterInMs = retryAfterInMs; - this.TransportRequestStats = transportRequestStats; - this.ReplicaHealthStatuses = replicaHealthStatuses; - - this.StatusCode = (StatusCodes) (this.storeResponse != null ? this.storeResponse.StatusCode : - ((this.Exception != null && this.Exception.StatusCode.HasValue) ? this.Exception.StatusCode : 0)); - - this.SubStatusCode = this.storeResponse != null ? this.storeResponse.SubStatusCode : - (this.Exception != null ? this.Exception.GetSubStatus() : SubStatusCodes.Unknown); - } - - public DocumentClientException Exception { get; } - - public long LSN { get; private set; } - - public string PartitionKeyRangeId { get; private set; } - - public long QuorumAckedLSN { get; private set; } - - public long GlobalCommittedLSN { get; private set; } - - public long NumberOfReadRegions { get; private set; } - - public long ItemLSN { get; private set; } - - public ISessionToken SessionToken { get; private set; } - - public bool UsingLocalLSN { get; private set; } - - public double RequestCharge { get; private set; } - - public int CurrentReplicaSetSize { get; private set; } - - public int CurrentWriteQuorum { get; private set; } - - public bool IsValid { get; private set; } - - public Uri StorePhysicalAddress { get; private set; } - - public StatusCodes StatusCode { get; private set; } - - public SubStatusCodes SubStatusCode { get; private set; } - - public string ActivityId { get; private set; } - - public string BackendRequestDurationInMs { get; private set;} - - public string RetryAfterInMs { get; private set; } - - public TransportRequestStats TransportRequestStats { get; private set; } - - public IEnumerable ReplicaHealthStatuses { get; private set; } - - public DocumentClientException GetException() - { - if (this.Exception == null) - { - string message = "Exception should be available but found none"; - Debug.Assert(false, message); - DefaultTrace.TraceCritical(message); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - - return this.Exception; - } - - public StoreResponse ToResponse(RequestChargeTracker requestChargeTracker = null) - { - if (!this.IsValid) - { - if (this.Exception == null) - { - DefaultTrace.TraceCritical("Exception not set for invalid response"); - throw new InternalServerErrorException(RMResources.InternalServerError); - } - - throw this.Exception; - } - - if (requestChargeTracker != null) - { - StoreResult.SetRequestCharge(this.storeResponse, this.Exception, requestChargeTracker.TotalRequestCharge); - } - - if (this.Exception != null) - { - throw Exception; - } - - return this.storeResponse; - } - - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder(); - this.AppendToBuilder(stringBuilder); - return stringBuilder.ToString(); - } - - public void AppendToBuilder(StringBuilder stringBuilder) - { - if (stringBuilder == null) - { - throw new ArgumentNullException(nameof(stringBuilder)); - } - - stringBuilder.AppendFormat( - CultureInfo.InvariantCulture, - "StorePhysicalAddress: {0}, LSN: {1}, GlobalCommittedLsn: {2}, PartitionKeyRangeId: {3}, IsValid: {4}, StatusCode: {5}, SubStatusCode: {6}, " + - "RequestCharge: {7}, ItemLSN: {8}, SessionToken: {9}, UsingLocalLSN: {10}, TransportException: {11}, BELatencyMs: {12}, ActivityId: {13}, RetryAfterInMs: {14}", - this.StorePhysicalAddress, - this.LSN, - this.GlobalCommittedLSN, - this.PartitionKeyRangeId, - this.IsValid, - (int) this.StatusCode, - (int) this.SubStatusCode, - this.RequestCharge, - this.ItemLSN, - this.SessionToken?.ConvertToString(), - this.UsingLocalLSN, - this.Exception?.InnerException is TransportException ? this.Exception.InnerException.Message : "null", - this.BackendRequestDurationInMs, - this.ActivityId, - this.RetryAfterInMs); - - if (this.ReplicaHealthStatuses != null && this.ReplicaHealthStatuses.Any()) - { - stringBuilder - .Append(", ReplicaHealthStatuses: ["); - - int low = 0, high = this.ReplicaHealthStatuses.Count(); - foreach(string replicaHealthStatus in this.ReplicaHealthStatuses) - { - stringBuilder.Append(replicaHealthStatus); - if(low++ < high-1) - { - stringBuilder.Append(","); - } - } - stringBuilder.Append("]"); - } - - if (this.TransportRequestStats != null) - { - stringBuilder.Append(", TransportRequestTimeline: "); - this.TransportRequestStats.AppendJsonString(stringBuilder); - } - - stringBuilder.Append(";"); - } - - private static void SetRequestCharge(StoreResponse response, DocumentClientException documentClientException, double totalRequestCharge) - { - if (documentClientException != null) - { - documentClientException.Headers[HttpConstants.HttpHeaders.RequestCharge] = totalRequestCharge.ToString(CultureInfo.InvariantCulture); - } - // Set total charge as final charge for the response. - else if (response.Headers?.Get(HttpConstants.HttpHeaders.RequestCharge) != null) - { - response.Headers[HttpConstants.HttpHeaders.RequestCharge] = totalRequestCharge.ToString(CultureInfo.InvariantCulture); - } - } - - internal static void VerifyCanContinueOnException(DocumentClientException ex) - { - if ((ex is PartitionKeyRangeGoneException) || - (ex is PartitionKeyRangeIsSplittingException) || - (ex is PartitionIsMigratingException)) - { - ExceptionDispatchInfo.Capture(ex).Throw(); - } - - string value = ex.Headers[HttpConstants.HttpHeaders.RequestValidationFailure]; - if (string.IsNullOrWhiteSpace(value)) - { - return; - } - - int result; - if (int.TryParse(ex.Headers.GetValues(HttpConstants.HttpHeaders.RequestValidationFailure)[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out result) && result == 1) - { - ExceptionDispatchInfo.Capture(ex).Throw(); - } - } - - public void Dispose() - { - this.storeResponse?.ResponseBody?.Dispose(); - } - } - -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Linq; + using System.Net; + using System.Runtime.ExceptionServices; + using System.Text; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Routing; + + internal sealed class StoreResult : IDisposable + { + private readonly StoreResponse storeResponse; + + private static bool UseSessionTokenHeader = VersionUtility.IsLaterThan(HttpConstants.Versions.CurrentVersion, HttpConstants.VersionDates.v2018_06_18); + + public static ReferenceCountedDisposable CreateStoreResult( + StoreResponse storeResponse, + Exception responseException, + bool requiresValidLsn, + bool useLocalLSNBasedHeaders, + IEnumerable replicaHealthStatuses, + Uri storePhysicalAddress = null) + { + if (storeResponse == null && responseException == null) + { + throw new ArgumentException("storeResponse or responseException must be populated."); + } + + if (responseException == null) + { + string headerValue = null; + long quorumAckedLSN = -1; + int currentReplicaSetSize = -1; + int currentWriteQuorum = -1; + long globalCommittedLSN = -1; + int numberOfReadRegions = -1; + long itemLSN = -1; + if (storeResponse.TryGetHeaderValue( + useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.QuorumAckedLocalLSN : WFConstants.BackendHeaders.QuorumAckedLSN, + out headerValue)) + { + quorumAckedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + + if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.CurrentReplicaSetSize, out headerValue)) + { + currentReplicaSetSize = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.CurrentWriteQuorum, out headerValue)) + { + currentWriteQuorum = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + double requestCharge = 0; + if (storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.RequestCharge, out headerValue)) + { + requestCharge = double.Parse(headerValue, CultureInfo.InvariantCulture); + } + + if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.NumberOfReadRegions, out headerValue)) + { + numberOfReadRegions = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.GlobalCommittedLSN, out headerValue)) + { + globalCommittedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + + if (storeResponse.TryGetHeaderValue( + useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.ItemLocalLSN : WFConstants.BackendHeaders.ItemLSN, + out headerValue)) + { + itemLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + + long lsn = -1; + if (useLocalLSNBasedHeaders) + { + if (storeResponse.TryGetHeaderValue(WFConstants.BackendHeaders.LocalLSN, out headerValue)) + { + lsn = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + } + else + { + lsn = storeResponse.LSN; + } + + ISessionToken sessionToken = null; + if (StoreResult.UseSessionTokenHeader) + { + // Session token response header is introduced from version HttpConstants.Versions.v2018_06_18 onwards. + // Previously it was only a request header + if (storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.SessionToken, out headerValue)) + { + sessionToken = SessionTokenHelper.Parse(headerValue); + } + } + else + { + sessionToken = new SimpleSessionToken(storeResponse.LSN); + } + + storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.ActivityId, out string activityId); + storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds, out string backendRequestDurationMilliseconds); + storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.RetryAfterInMilliseconds, out string retryAfterInMs); + + return new ReferenceCountedDisposable(new StoreResult( + storeResponse: storeResponse, + exception: null, + partitionKeyRangeId: storeResponse.PartitionKeyRangeId, + lsn: lsn, + quorumAckedLsn: quorumAckedLSN, + requestCharge: requestCharge, + currentReplicaSetSize: currentReplicaSetSize, + currentWriteQuorum: currentWriteQuorum, + isValid: true, + storePhysicalAddress: storePhysicalAddress, + globalCommittedLSN: globalCommittedLSN, + numberOfReadRegions: numberOfReadRegions, + itemLSN: itemLSN, + sessionToken: sessionToken, + usingLocalLSN: useLocalLSNBasedHeaders, + activityId: activityId, + backendRequestDurationInMs: backendRequestDurationMilliseconds, + retryAfterInMs: retryAfterInMs, + transportRequestStats: storeResponse.TransportRequestStats, + replicaHealthStatuses: replicaHealthStatuses)); + } + else + { + DocumentClientException documentClientException = responseException as DocumentClientException; + if (documentClientException != null) + { + long quorumAckedLSN = -1; + int currentReplicaSetSize = -1; + int currentWriteQuorum = -1; + long globalCommittedLSN = -1; + int numberOfReadRegions = -1; + string headerValue = documentClientException.Headers[useLocalLSNBasedHeaders ? WFConstants.BackendHeaders.QuorumAckedLocalLSN : WFConstants.BackendHeaders.QuorumAckedLSN]; + if (!string.IsNullOrEmpty(headerValue)) + { + quorumAckedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + + headerValue = documentClientException.Headers[WFConstants.BackendHeaders.CurrentReplicaSetSize]; + if (!string.IsNullOrEmpty(headerValue)) + { + currentReplicaSetSize = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + headerValue = documentClientException.Headers[WFConstants.BackendHeaders.CurrentWriteQuorum]; + if (!string.IsNullOrEmpty(headerValue)) + { + currentWriteQuorum = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + double requestCharge = 0; + headerValue = documentClientException.Headers[HttpConstants.HttpHeaders.RequestCharge]; + if (!string.IsNullOrEmpty(headerValue)) + { + requestCharge = double.Parse(headerValue, CultureInfo.InvariantCulture); + } + + headerValue = documentClientException.Headers[WFConstants.BackendHeaders.NumberOfReadRegions]; + if (!string.IsNullOrEmpty(headerValue)) + { + numberOfReadRegions = int.Parse(headerValue, CultureInfo.InvariantCulture); + } + + headerValue = documentClientException.Headers[WFConstants.BackendHeaders.GlobalCommittedLSN]; + if (!string.IsNullOrEmpty(headerValue)) + { + globalCommittedLSN = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + + long lsn = -1; + if (useLocalLSNBasedHeaders) + { + headerValue = documentClientException.Headers[WFConstants.BackendHeaders.LocalLSN]; + if (!string.IsNullOrEmpty(headerValue)) + { + lsn = long.Parse(headerValue, CultureInfo.InvariantCulture); + } + } + else + { + lsn = documentClientException.LSN; + } + + ISessionToken sessionToken = null; + if (StoreResult.UseSessionTokenHeader) + { + // Session token response header is introduced from version HttpConstants.Versions.v2018_06_18 onwards. + // Previously it was only a request header + headerValue = documentClientException.Headers[HttpConstants.HttpHeaders.SessionToken]; + if (!string.IsNullOrEmpty(headerValue)) + { + sessionToken = SessionTokenHelper.Parse(headerValue); + } + } + else + { + sessionToken = new SimpleSessionToken(documentClientException.LSN); + } + + return new ReferenceCountedDisposable(new StoreResult( + storeResponse: null, + exception: documentClientException, + partitionKeyRangeId: documentClientException.PartitionKeyRangeId, + lsn: lsn, + quorumAckedLsn: quorumAckedLSN, + requestCharge: requestCharge, + currentReplicaSetSize: currentReplicaSetSize, + currentWriteQuorum: currentWriteQuorum, + isValid: !requiresValidLsn + || ((documentClientException.StatusCode != HttpStatusCode.Gone || documentClientException.GetSubStatus() == SubStatusCodes.NameCacheIsStale) + && lsn >= 0), + storePhysicalAddress: storePhysicalAddress == null ? documentClientException.RequestUri : storePhysicalAddress, + globalCommittedLSN: globalCommittedLSN, + numberOfReadRegions: numberOfReadRegions, + itemLSN: -1, + sessionToken: sessionToken, + usingLocalLSN: useLocalLSNBasedHeaders, + activityId: documentClientException.ActivityId, + backendRequestDurationInMs: documentClientException.Headers[HttpConstants.HttpHeaders.BackendRequestDurationMilliseconds], + retryAfterInMs: documentClientException.Headers[HttpConstants.HttpHeaders.RetryAfterInMilliseconds], + transportRequestStats: documentClientException.TransportRequestStats, + replicaHealthStatuses: replicaHealthStatuses)); + } + else + { + DefaultTrace.TraceCritical("Unexpected exception {0} received while reading from store.", responseException); + return new ReferenceCountedDisposable(new StoreResult( + storeResponse: null, + exception: new InternalServerErrorException(RMResources.InternalServerError, responseException), + partitionKeyRangeId: null, + lsn: -1, + quorumAckedLsn: -1, + requestCharge: 0, + currentReplicaSetSize: 0, + currentWriteQuorum: 0, + isValid: false, + storePhysicalAddress: storePhysicalAddress, + globalCommittedLSN: -1, + numberOfReadRegions: 0, + itemLSN: -1, + sessionToken: null, + usingLocalLSN: useLocalLSNBasedHeaders, + activityId: null, + backendRequestDurationInMs: null, + retryAfterInMs: null, + transportRequestStats: null, + replicaHealthStatuses: replicaHealthStatuses)); + } + } + } + + public static ReferenceCountedDisposable CreateForTesting(StoreResponse storeResponse) + { + return new ReferenceCountedDisposable( + new StoreResult( + storeResponse, exception: null, null, default, default, default, default, default, default, + default, default, default, default, default, default, default, default, default, default, default)); + } + + public static ReferenceCountedDisposable CreateForTesting(TransportRequestStats transportRequestStats) + { + return new ReferenceCountedDisposable(new Documents.StoreResult( + storeResponse: new StoreResponse(), + exception: null, + partitionKeyRangeId: 42.ToString(), + lsn: 1337, + quorumAckedLsn: 23, + requestCharge: 3.14, + currentReplicaSetSize: 4, + currentWriteQuorum: 3, + isValid: true, + storePhysicalAddress: new Uri("http://storephysicaladdress.com"), + globalCommittedLSN: 1234, + numberOfReadRegions: 13, + itemLSN: 15, + sessionToken: new SimpleSessionToken(42), + usingLocalLSN: true, + activityId: Guid.Empty.ToString(), + backendRequestDurationInMs: "4.2", + retryAfterInMs: "9000", + transportRequestStats: transportRequestStats, + replicaHealthStatuses: new List() + { + "http://storephysicaladdress-1p.com:Connected", + "http://storephysicaladdress-2s.com:Unknown", + "http://storephysicaladdress-3s.com:Unhealthy", + "http://storephysicaladdress-4s.com:Unknown" + })); + } + + public static ReferenceCountedDisposable CreateForTesting(string partitionKeyRangeId) + { + return new ReferenceCountedDisposable(new StoreResult( + storeResponse: new StoreResponse(), + exception: null, + partitionKeyRangeId: partitionKeyRangeId, + lsn: 0, + quorumAckedLsn: 0, + requestCharge: 0, + currentReplicaSetSize: 0, + currentWriteQuorum: 0, + isValid: true, + storePhysicalAddress: null, + globalCommittedLSN: 0, + numberOfReadRegions: 0, + itemLSN: 0, + sessionToken: null, + usingLocalLSN: true, + activityId: Guid.NewGuid().ToString(), + backendRequestDurationInMs: "10", + retryAfterInMs: "20", + transportRequestStats: new TransportRequestStats(), + replicaHealthStatuses: null)); + } + + private StoreResult( + StoreResponse storeResponse, + DocumentClientException exception, + string partitionKeyRangeId, + long lsn, + long quorumAckedLsn, + double requestCharge, + int currentReplicaSetSize, + int currentWriteQuorum, + bool isValid, + Uri storePhysicalAddress, + long globalCommittedLSN, + int numberOfReadRegions, + long itemLSN, + ISessionToken sessionToken, + bool usingLocalLSN, + string activityId, + string backendRequestDurationInMs, + string retryAfterInMs, + TransportRequestStats transportRequestStats, + IEnumerable replicaHealthStatuses) + { + if (storeResponse == null && exception == null) + { + throw new ArgumentException("storeResponse or responseException must be populated."); + } + + this.storeResponse = storeResponse; + this.Exception = exception; + this.PartitionKeyRangeId = partitionKeyRangeId; + this.LSN = lsn; + this.QuorumAckedLSN = quorumAckedLsn; + this.RequestCharge = requestCharge; + this.CurrentReplicaSetSize = currentReplicaSetSize; + this.CurrentWriteQuorum = currentWriteQuorum; + this.IsValid = isValid; + + this.StorePhysicalAddress = storePhysicalAddress; + this.GlobalCommittedLSN = globalCommittedLSN; + this.NumberOfReadRegions = numberOfReadRegions; + this.ItemLSN = itemLSN; + this.SessionToken = sessionToken; + this.UsingLocalLSN = usingLocalLSN; + this.ActivityId = activityId; + this.BackendRequestDurationInMs = backendRequestDurationInMs; + this.RetryAfterInMs = retryAfterInMs; + this.TransportRequestStats = transportRequestStats; + this.ReplicaHealthStatuses = replicaHealthStatuses; + + this.StatusCode = (StatusCodes) (this.storeResponse != null ? this.storeResponse.StatusCode : + ((this.Exception != null && this.Exception.StatusCode.HasValue) ? this.Exception.StatusCode : 0)); + + this.SubStatusCode = this.storeResponse != null ? this.storeResponse.SubStatusCode : + (this.Exception != null ? this.Exception.GetSubStatus() : SubStatusCodes.Unknown); + } + + public DocumentClientException Exception { get; } + + public long LSN { get; private set; } + + public string PartitionKeyRangeId { get; private set; } + + public long QuorumAckedLSN { get; private set; } + + public long GlobalCommittedLSN { get; private set; } + + public long NumberOfReadRegions { get; private set; } + + public long ItemLSN { get; private set; } + + public ISessionToken SessionToken { get; private set; } + + public bool UsingLocalLSN { get; private set; } + + public double RequestCharge { get; private set; } + + public int CurrentReplicaSetSize { get; private set; } + + public int CurrentWriteQuorum { get; private set; } + + public bool IsValid { get; private set; } + + public Uri StorePhysicalAddress { get; private set; } + + public StatusCodes StatusCode { get; private set; } + + public SubStatusCodes SubStatusCode { get; private set; } + + public string ActivityId { get; private set; } + + public string BackendRequestDurationInMs { get; private set;} + + public string RetryAfterInMs { get; private set; } + + public TransportRequestStats TransportRequestStats { get; private set; } + + public IEnumerable ReplicaHealthStatuses { get; private set; } + + public DocumentClientException GetException() + { + if (this.Exception == null) + { + string message = "Exception should be available but found none"; + Debug.Assert(false, message); + DefaultTrace.TraceCritical(message); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + + return this.Exception; + } + + public StoreResponse ToResponse(RequestChargeTracker requestChargeTracker = null) + { + if (!this.IsValid) + { + if (this.Exception == null) + { + DefaultTrace.TraceCritical("Exception not set for invalid response"); + throw new InternalServerErrorException(RMResources.InternalServerError); + } + + throw this.Exception; + } + + if (requestChargeTracker != null) + { + StoreResult.SetRequestCharge(this.storeResponse, this.Exception, requestChargeTracker.TotalRequestCharge); + } + + if (this.Exception != null) + { + throw Exception; + } + + return this.storeResponse; + } + + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + this.AppendToBuilder(stringBuilder); + return stringBuilder.ToString(); + } + + public void AppendToBuilder(StringBuilder stringBuilder) + { + if (stringBuilder == null) + { + throw new ArgumentNullException(nameof(stringBuilder)); + } + + stringBuilder.AppendFormat( + CultureInfo.InvariantCulture, + "StorePhysicalAddress: {0}, LSN: {1}, GlobalCommittedLsn: {2}, PartitionKeyRangeId: {3}, IsValid: {4}, StatusCode: {5}, SubStatusCode: {6}, " + + "RequestCharge: {7}, ItemLSN: {8}, SessionToken: {9}, UsingLocalLSN: {10}, TransportException: {11}, BELatencyMs: {12}, ActivityId: {13}, RetryAfterInMs: {14}", + this.StorePhysicalAddress, + this.LSN, + this.GlobalCommittedLSN, + this.PartitionKeyRangeId, + this.IsValid, + (int) this.StatusCode, + (int) this.SubStatusCode, + this.RequestCharge, + this.ItemLSN, + this.SessionToken?.ConvertToString(), + this.UsingLocalLSN, + this.Exception?.InnerException is TransportException ? this.Exception.InnerException.Message : "null", + this.BackendRequestDurationInMs, + this.ActivityId, + this.RetryAfterInMs); + + if (this.ReplicaHealthStatuses != null && this.ReplicaHealthStatuses.Any()) + { + stringBuilder + .Append(", ReplicaHealthStatuses: ["); + + int low = 0, high = this.ReplicaHealthStatuses.Count(); + foreach(string replicaHealthStatus in this.ReplicaHealthStatuses) + { + stringBuilder.Append(replicaHealthStatus); + if(low++ < high-1) + { + stringBuilder.Append(","); + } + } + stringBuilder.Append("]"); + } + + if (this.TransportRequestStats != null) + { + stringBuilder.Append(", TransportRequestTimeline: "); + this.TransportRequestStats.AppendJsonString(stringBuilder); + } + + stringBuilder.Append(";"); + } + + private static void SetRequestCharge(StoreResponse response, DocumentClientException documentClientException, double totalRequestCharge) + { + if (documentClientException != null) + { + documentClientException.Headers[HttpConstants.HttpHeaders.RequestCharge] = totalRequestCharge.ToString(CultureInfo.InvariantCulture); + } + // Set total charge as final charge for the response. + else if (response.Headers?.Get(HttpConstants.HttpHeaders.RequestCharge) != null) + { + response.Headers[HttpConstants.HttpHeaders.RequestCharge] = totalRequestCharge.ToString(CultureInfo.InvariantCulture); + } + } + + internal static void VerifyCanContinueOnException(DocumentClientException ex) + { + if ((ex is PartitionKeyRangeGoneException) || + (ex is PartitionKeyRangeIsSplittingException) || + (ex is PartitionIsMigratingException)) + { + ExceptionDispatchInfo.Capture(ex).Throw(); + } + + string value = ex.Headers[HttpConstants.HttpHeaders.RequestValidationFailure]; + if (string.IsNullOrWhiteSpace(value)) + { + return; + } + + int result; + if (int.TryParse(ex.Headers.GetValues(HttpConstants.HttpHeaders.RequestValidationFailure)[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out result) && result == 1) + { + ExceptionDispatchInfo.Capture(ex).Throw(); + } + } + + public void Dispose() + { + this.storeResponse?.ResponseBody?.Dispose(); + } + } + +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StoredProcedure.cs b/Microsoft.Azure.Cosmos/src/direct/StoredProcedure.cs index decda6abdb..cfe14e18d2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoredProcedure.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoredProcedure.cs @@ -1,48 +1,48 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents a stored procedure in the Azure Cosmos DB service. - /// - /// - /// Azure Cosmos DB allows application logic written entirely in JavaScript to be executed directly inside the database engine under the database transaction. - /// For additional details, refer to the server-side JavaScript API documentation. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class StoredProcedure : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public StoredProcedure() - { - } - - /// - /// Gets or sets the body of the Azure Cosmos DB stored procedure. - /// - /// The body of the stored procedure. - /// Must be a valid JavaScript function. For e.g. "function () { getContext().getResponse().setBody('Hello World!'); }" - [JsonProperty(PropertyName = Constants.Properties.Body)] - public string Body - { - get - { - return base.GetValue(Constants.Properties.Body); - } - set - { - base.SetValue(Constants.Properties.Body, value); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents a stored procedure in the Azure Cosmos DB service. + /// + /// + /// Azure Cosmos DB allows application logic written entirely in JavaScript to be executed directly inside the database engine under the database transaction. + /// For additional details, refer to the server-side JavaScript API documentation. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class StoredProcedure : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public StoredProcedure() + { + } + + /// + /// Gets or sets the body of the Azure Cosmos DB stored procedure. + /// + /// The body of the stored procedure. + /// Must be a valid JavaScript function. For e.g. "function () { getContext().getResponse().setBody('Hello World!'); }" + [JsonProperty(PropertyName = Constants.Properties.Body)] + public string Body + { + get + { + return base.GetValue(Constants.Properties.Body); + } + set + { + base.SetValue(Constants.Properties.Body, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StreamExtension.cs b/Microsoft.Azure.Cosmos/src/direct/StreamExtension.cs index 2690ba818d..2c83c0bebe 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StreamExtension.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StreamExtension.cs @@ -1,100 +1,100 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.IO; - using System.Threading.Tasks; - - internal static class StreamExtension - { - async public static Task CopyToAsync(this Stream srcStream, - Stream destinationStream, - long maxSizeToCopy = long.MaxValue) - { - if (srcStream == null) - { - throw new ArgumentNullException("srcStream"); - } - - if (destinationStream == null) - { - throw new ArgumentNullException("destinationStream"); - } - - byte[] buffer = new byte[RuntimeConstants.Serialization.ChunkSize1K]; //Copy them in chunks of 1 KB. - - long numberOfBytesRead = 0; - - while(true) - { - int bytesRead = await srcStream.ReadAsync(buffer, 0, RuntimeConstants.Serialization.ChunkSize1K); - - if (bytesRead <= 0) - { - return; - } - - numberOfBytesRead += bytesRead; - - if(numberOfBytesRead > maxSizeToCopy) - { - throw new RequestEntityTooLargeException( - RMResources.RequestTooLarge); - } - await destinationStream.WriteAsync(buffer, 0, bytesRead); - } - } - - /// - /// Creates a nonwritable MemoryStream with exposable buffer which enables TryGetBuffer to reduce allocations. - /// - public static MemoryStream CreateExportableMemoryStream(byte[] body) - { - return new MemoryStream(buffer: body, - index: 0, - count: body.Length, - writable: false, - publiclyVisible: true); - } - -#if NETFX45 || NETSTANDARD15 || NETSTANDARD16 - public static Task AsClonableStreamAsync(Stream mediaStream, bool allowUnsafeDataAccess = true) - { - return StreamExtension.CopyStreamAndReturnAsync(mediaStream); - } -#else - public static Task AsClonableStreamAsync(Stream mediaStream, bool allowUnsafeDataAccess = true) - { - MemoryStream memoryStream = mediaStream as MemoryStream; - if (memoryStream != null) - { - if (memoryStream is ICloneable cloneableStream) - { - return Task.FromResult(new CloneableStream((MemoryStream)cloneableStream.Clone(), allowUnsafeDataAccess)); - } - else if (allowUnsafeDataAccess && memoryStream.TryGetBuffer(out ArraySegment buffer)) - { - return Task.FromResult(new CloneableStream(memoryStream, allowUnsafeDataAccess)); - } - } - - return StreamExtension.CopyStreamAndReturnAsync(mediaStream); - } -#endif - - private static async Task CopyStreamAndReturnAsync(Stream mediaStream) - { - MemoryStream memoryStreamClone = new MemoryStream(); - if (mediaStream.CanSeek) - { - mediaStream.Position = 0; - } - - await mediaStream.CopyToAsync(memoryStreamClone); - memoryStreamClone.Position = 0; - return new CloneableStream(memoryStreamClone); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.IO; + using System.Threading.Tasks; + + internal static class StreamExtension + { + async public static Task CopyToAsync(this Stream srcStream, + Stream destinationStream, + long maxSizeToCopy = long.MaxValue) + { + if (srcStream == null) + { + throw new ArgumentNullException("srcStream"); + } + + if (destinationStream == null) + { + throw new ArgumentNullException("destinationStream"); + } + + byte[] buffer = new byte[RuntimeConstants.Serialization.ChunkSize1K]; //Copy them in chunks of 1 KB. + + long numberOfBytesRead = 0; + + while(true) + { + int bytesRead = await srcStream.ReadAsync(buffer, 0, RuntimeConstants.Serialization.ChunkSize1K); + + if (bytesRead <= 0) + { + return; + } + + numberOfBytesRead += bytesRead; + + if(numberOfBytesRead > maxSizeToCopy) + { + throw new RequestEntityTooLargeException( + RMResources.RequestTooLarge); + } + await destinationStream.WriteAsync(buffer, 0, bytesRead); + } + } + + /// + /// Creates a nonwritable MemoryStream with exposable buffer which enables TryGetBuffer to reduce allocations. + /// + public static MemoryStream CreateExportableMemoryStream(byte[] body) + { + return new MemoryStream(buffer: body, + index: 0, + count: body.Length, + writable: false, + publiclyVisible: true); + } + +#if NETFX45 || NETSTANDARD15 || NETSTANDARD16 + public static Task AsClonableStreamAsync(Stream mediaStream, bool allowUnsafeDataAccess = true) + { + return StreamExtension.CopyStreamAndReturnAsync(mediaStream); + } +#else + public static Task AsClonableStreamAsync(Stream mediaStream, bool allowUnsafeDataAccess = true) + { + MemoryStream memoryStream = mediaStream as MemoryStream; + if (memoryStream != null) + { + if (memoryStream is ICloneable cloneableStream) + { + return Task.FromResult(new CloneableStream((MemoryStream)cloneableStream.Clone(), allowUnsafeDataAccess)); + } + else if (allowUnsafeDataAccess && memoryStream.TryGetBuffer(out ArraySegment buffer)) + { + return Task.FromResult(new CloneableStream(memoryStream, allowUnsafeDataAccess)); + } + } + + return StreamExtension.CopyStreamAndReturnAsync(mediaStream); + } +#endif + + private static async Task CopyStreamAndReturnAsync(Stream mediaStream) + { + MemoryStream memoryStreamClone = new MemoryStream(); + if (mediaStream.CanSeek) + { + mediaStream.Position = 0; + } + + await mediaStream.CopyToAsync(memoryStreamClone); + memoryStreamClone.Position = 0; + return new CloneableStream(memoryStreamClone); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StringPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/StringPartitionKeyComponent.cs index 7f35abc994..d65d0b7cb3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StringPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StringPartitionKeyComponent.cs @@ -1,122 +1,122 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using System.Text; - using Newtonsoft.Json; - - internal sealed class StringPartitionKeyComponent : IPartitionKeyComponent - { - public const int MaxStringChars = 100; - public const int MaxStringBytesToAppend = 100; - private readonly string value; - private readonly byte[] utf8Value; - - public StringPartitionKeyComponent(string value) - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - this.value = value; - this.utf8Value = Encoding.UTF8.GetBytes(value); - } - - public void JsonEncode(JsonWriter writer) - { - writer.WriteValue(this.value); - } - - public object ToObject() - { - return this.value; - } - - public int CompareTo(IPartitionKeyComponent other) - { - StringPartitionKeyComponent otherString = other as StringPartitionKeyComponent; - if (otherString == null) - { - throw new ArgumentException("other"); - } - - return string.CompareOrdinal(this.value, otherString.value); - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.String; - } - - public override int GetHashCode() - { - return this.value.GetHashCode(); - } - - public IPartitionKeyComponent Truncate() - { - if (this.value.Length > MaxStringChars) - { - return new StringPartitionKeyComponent(this.value.Substring(0, MaxStringChars)); - } - - return this; - } - - public void WriteForHashing(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.String); - writer.Write(this.utf8Value); - writer.Write((byte)0); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.String); - writer.Write(this.utf8Value); - writer.Write((byte)0xFF); - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.String); - - bool shortString = this.utf8Value.Length <= MaxStringBytesToAppend; - - for (int index = 0; index < (shortString ? this.utf8Value.Length : MaxStringBytesToAppend + 1); index++) - { - byte charByte = this.utf8Value[index]; - if (charByte < 0xFF) charByte++; - binaryWriter.Write(charByte); - } - - if (shortString) - { - binaryWriter.Write((byte)0x00); - } - } - - /// - /// Constructs a StringPartitionKeyComponent from byte string. This is only for testing/debugging. Please do not use in actual product code. - /// - public static IPartitionKeyComponent FromHexEncodedBinaryString(byte[] byteString, ref int offset) - { - StringBuilder stringBuilder = new StringBuilder(); - for (int index = 0; index <= MaxStringBytesToAppend; index++) - { - byte currentByte = byteString[offset++]; - if (currentByte == 0x00) break; - char currentChar = (char)(currentByte - 1); - - stringBuilder.Append(currentChar); - } - - return new StringPartitionKeyComponent(stringBuilder.ToString()); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using System.Text; + using Newtonsoft.Json; + + internal sealed class StringPartitionKeyComponent : IPartitionKeyComponent + { + public const int MaxStringChars = 100; + public const int MaxStringBytesToAppend = 100; + private readonly string value; + private readonly byte[] utf8Value; + + public StringPartitionKeyComponent(string value) + { + if (value == null) + { + throw new ArgumentNullException("value"); + } + + this.value = value; + this.utf8Value = Encoding.UTF8.GetBytes(value); + } + + public void JsonEncode(JsonWriter writer) + { + writer.WriteValue(this.value); + } + + public object ToObject() + { + return this.value; + } + + public int CompareTo(IPartitionKeyComponent other) + { + StringPartitionKeyComponent otherString = other as StringPartitionKeyComponent; + if (otherString == null) + { + throw new ArgumentException("other"); + } + + return string.CompareOrdinal(this.value, otherString.value); + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.String; + } + + public override int GetHashCode() + { + return this.value.GetHashCode(); + } + + public IPartitionKeyComponent Truncate() + { + if (this.value.Length > MaxStringChars) + { + return new StringPartitionKeyComponent(this.value.Substring(0, MaxStringChars)); + } + + return this; + } + + public void WriteForHashing(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.String); + writer.Write(this.utf8Value); + writer.Write((byte)0); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.String); + writer.Write(this.utf8Value); + writer.Write((byte)0xFF); + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.String); + + bool shortString = this.utf8Value.Length <= MaxStringBytesToAppend; + + for (int index = 0; index < (shortString ? this.utf8Value.Length : MaxStringBytesToAppend + 1); index++) + { + byte charByte = this.utf8Value[index]; + if (charByte < 0xFF) charByte++; + binaryWriter.Write(charByte); + } + + if (shortString) + { + binaryWriter.Write((byte)0x00); + } + } + + /// + /// Constructs a StringPartitionKeyComponent from byte string. This is only for testing/debugging. Please do not use in actual product code. + /// + public static IPartitionKeyComponent FromHexEncodedBinaryString(byte[] byteString, ref int offset) + { + StringBuilder stringBuilder = new StringBuilder(); + for (int index = 0; index <= MaxStringBytesToAppend; index++) + { + byte currentByte = byteString[offset++]; + if (currentByte == 0x00) break; + char currentChar = (char)(currentByte - 1); + + stringBuilder.Append(currentChar); + } + + return new StringPartitionKeyComponent(stringBuilder.ToString()); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/StringSegment.cs b/Microsoft.Azure.Cosmos/src/direct/StringSegment.cs index 48725dea24..451130b2fd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StringSegment.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StringSegment.cs @@ -1,168 +1,168 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Wrapper around a string that provides alloc-free methods for - /// SubString, Trim, and comparisons. - /// - /// - /// This is used over the standard .net ReadOnlyMemory{char} or StringSegment - /// as Documents.Common's and Document.Client references to System.Buffers was deemed to be too expensive - /// to add and maintain. if these references get fixed, this struct can be deleted in favor of the one from the - /// BCL. - /// - internal readonly struct StringSegment - { - private readonly string value; - - public StringSegment(string value) - { - this.value = value; - this.Start = 0; - this.Length = value?.Length ?? 0; - } - - public StringSegment(string value, int start, int length) - { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (start < 0 || (start >= value.Length && value.Length > 0)) - { - throw new ArgumentException(nameof(start)); - } - - if (length < 0 || (start + length) > value.Length) - { - throw new ArgumentException(nameof(length)); - } - - this.value = value; - this.Start = start; - this.Length = length; - } - - private int Start { get; } - - public int Length { get; } - - public static implicit operator StringSegment(string b) => new StringSegment(b); - - public bool IsNullOrEmpty() - { - return string.IsNullOrEmpty(this.value) || this.Length == 0; - } - public int Compare(string other, StringComparison comparison) - { - return string.Compare(this.value, this.Start, other, 0, Math.Max(this.Length, other.Length), comparison); - } - - public int Compare(StringSegment other, StringComparison comparison) - { - return string.Compare(this.value, this.Start, other.value, other.Start, Math.Max(this.Length, other.Length), comparison); - } - - public bool Equals(string other, StringComparison comparison) - { - return this.Compare(other, comparison) == 0; - } - - public StringSegment Substring(int start, int length) - { - if (length == 0) - { - return new StringSegment(string.Empty); - } - - if (start > this.Length) - { - throw new ArgumentException(nameof(start)); - } - - if ((start + length) > this.Length) - { - throw new ArgumentException(nameof(length)); - } - - return new StringSegment(this.value, start + this.Start, length); - } - - public int LastIndexOf(char segment) - { - if (this.IsNullOrEmpty()) - { - return -1; - } - - int index = this.value.LastIndexOf(segment, (this.Start + this.Length - 1)); - if (index >= 0) - { - return index - this.Start; - } - - return index; - } - - public StringSegment Trim(char[] trimChars) - { - return this.TrimStart(trimChars).TrimEnd(trimChars); - } - - public StringSegment TrimStart(char[] trimChars) - { - if (this.Length == 0) - { - return new StringSegment(string.Empty, 0, 0); - } - - int newStart = this.Start; - int newLength = this.Length; - while (newLength > 0 && this.value.IndexOfAny(trimChars, newStart, 1) == newStart) - { - newStart++; - newLength--; - } - - return new StringSegment(this.value, newStart, newLength); - } - - public StringSegment TrimEnd(char[] trimChars) - { - if (this.Length == 0) - { - return new StringSegment(string.Empty, 0, 0); - } - - int newLength = this.Length; - int newEndIndex = this.Start + this.Length - 1; - while (newLength > 0 && this.value.LastIndexOfAny(trimChars, newEndIndex, 1) == newEndIndex) - { - newLength--; - newEndIndex--; - } - - return new StringSegment(this.value, this.Start, newLength); - } - - public string GetString() - { - if (this.Length == 0) - { - return string.Empty; - } - - if (this.Length == this.value.Length) - { - return this.value; - } - - return this.value.Substring(this.Start, this.Length); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Wrapper around a string that provides alloc-free methods for + /// SubString, Trim, and comparisons. + /// + /// + /// This is used over the standard .net ReadOnlyMemory{char} or StringSegment + /// as Documents.Common's and Document.Client references to System.Buffers was deemed to be too expensive + /// to add and maintain. if these references get fixed, this struct can be deleted in favor of the one from the + /// BCL. + /// + internal readonly struct StringSegment + { + private readonly string value; + + public StringSegment(string value) + { + this.value = value; + this.Start = 0; + this.Length = value?.Length ?? 0; + } + + public StringSegment(string value, int start, int length) + { + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (start < 0 || (start >= value.Length && value.Length > 0)) + { + throw new ArgumentException(nameof(start)); + } + + if (length < 0 || (start + length) > value.Length) + { + throw new ArgumentException(nameof(length)); + } + + this.value = value; + this.Start = start; + this.Length = length; + } + + private int Start { get; } + + public int Length { get; } + + public static implicit operator StringSegment(string b) => new StringSegment(b); + + public bool IsNullOrEmpty() + { + return string.IsNullOrEmpty(this.value) || this.Length == 0; + } + public int Compare(string other, StringComparison comparison) + { + return string.Compare(this.value, this.Start, other, 0, Math.Max(this.Length, other.Length), comparison); + } + + public int Compare(StringSegment other, StringComparison comparison) + { + return string.Compare(this.value, this.Start, other.value, other.Start, Math.Max(this.Length, other.Length), comparison); + } + + public bool Equals(string other, StringComparison comparison) + { + return this.Compare(other, comparison) == 0; + } + + public StringSegment Substring(int start, int length) + { + if (length == 0) + { + return new StringSegment(string.Empty); + } + + if (start > this.Length) + { + throw new ArgumentException(nameof(start)); + } + + if ((start + length) > this.Length) + { + throw new ArgumentException(nameof(length)); + } + + return new StringSegment(this.value, start + this.Start, length); + } + + public int LastIndexOf(char segment) + { + if (this.IsNullOrEmpty()) + { + return -1; + } + + int index = this.value.LastIndexOf(segment, (this.Start + this.Length - 1)); + if (index >= 0) + { + return index - this.Start; + } + + return index; + } + + public StringSegment Trim(char[] trimChars) + { + return this.TrimStart(trimChars).TrimEnd(trimChars); + } + + public StringSegment TrimStart(char[] trimChars) + { + if (this.Length == 0) + { + return new StringSegment(string.Empty, 0, 0); + } + + int newStart = this.Start; + int newLength = this.Length; + while (newLength > 0 && this.value.IndexOfAny(trimChars, newStart, 1) == newStart) + { + newStart++; + newLength--; + } + + return new StringSegment(this.value, newStart, newLength); + } + + public StringSegment TrimEnd(char[] trimChars) + { + if (this.Length == 0) + { + return new StringSegment(string.Empty, 0, 0); + } + + int newLength = this.Length; + int newEndIndex = this.Start + this.Length - 1; + while (newLength > 0 && this.value.LastIndexOfAny(trimChars, newEndIndex, 1) == newEndIndex) + { + newLength--; + newEndIndex--; + } + + return new StringSegment(this.value, this.Start, newLength); + } + + public string GetString() + { + if (this.Length == 0) + { + return string.Empty; + } + + if (this.Length == this.value.Length) + { + return this.value; + } + + return this.value.Substring(this.Start, this.Length); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SupportedSerializationFormats.cs b/Microsoft.Azure.Cosmos/src/direct/SupportedSerializationFormats.cs index c472e29e30..45d7a0a2ca 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SupportedSerializationFormats.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SupportedSerializationFormats.cs @@ -1,29 +1,29 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -using System; - -namespace Microsoft.Azure.Documents -{ - [Flags] - internal enum SupportedSerializationFormats - { - None = 0, - - /// - /// Standard JSON RFC UTF-8 text. - /// - JsonText = 1 << 0, - - /// - /// Custom binary for Cosmos DB that encodes a superset of JSON values. - /// - CosmosBinary = 1 << 1, - - /// - /// HybridRow format. - /// - HybridRow = 1 << 2, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +using System; + +namespace Microsoft.Azure.Documents +{ + [Flags] + internal enum SupportedSerializationFormats + { + None = 0, + + /// + /// Standard JSON RFC UTF-8 text. + /// + JsonText = 1 << 0, + + /// + /// Custom binary for Cosmos DB that encodes a superset of JSON values. + /// + CosmosBinary = 1 << 1, + + /// + /// HybridRow format. + /// + HybridRow = 1 << 2, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemDocument.cs b/Microsoft.Azure.Cosmos/src/direct/SystemDocument.cs index f9abd31861..335f1fa6aa 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemDocument.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemDocument.cs @@ -1,17 +1,17 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - /// - /// Represents a NonPartitioned SystemDocument. - /// It is replicated on all the server partitions. - /// - internal class SystemDocument : Resource - { - public SystemDocument() - { - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Represents a NonPartitioned SystemDocument. + /// It is replicated on all the server partitions. + /// + internal class SystemDocument : Resource + { + public SystemDocument() + { + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemDocumentType.cs b/Microsoft.Azure.Cosmos/src/direct/SystemDocumentType.cs index 032efe2aef..05fa394115 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemDocumentType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemDocumentType.cs @@ -1,33 +1,33 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal enum SystemDocumentType - { - /// - /// Set the SystemDocumentType to PartitionKey - /// Partitioned SystemDocument - /// - PartitionKey, - - /// - /// Set the SystemDocumentType as MaterializedViewLeaseDocument - /// Partitioned SystemDocument - /// - MaterializedViewLeaseDocument, - - /// - /// Set the SystemDocumentType as MaterializedViewBuilderOwnershipDocument - /// NonPartitionedSystemDocument - /// - MaterializedViewBuilderOwnershipDocument, - - /// - /// Set the SystemDocumentType as MaterializedViewLeaseStoreInitDocument - /// PartitionedSystemDocument - /// - MaterializedViewLeaseStoreInitDocument, - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal enum SystemDocumentType + { + /// + /// Set the SystemDocumentType to PartitionKey + /// Partitioned SystemDocument + /// + PartitionKey, + + /// + /// Set the SystemDocumentType as MaterializedViewLeaseDocument + /// Partitioned SystemDocument + /// + MaterializedViewLeaseDocument, + + /// + /// Set the SystemDocumentType as MaterializedViewBuilderOwnershipDocument + /// NonPartitionedSystemDocument + /// + MaterializedViewBuilderOwnershipDocument, + + /// + /// Set the SystemDocumentType as MaterializedViewLeaseStoreInitDocument + /// PartitionedSystemDocument + /// + MaterializedViewLeaseStoreInitDocument, + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemSynchronizationScope.cs b/Microsoft.Azure.Cosmos/src/direct/SystemSynchronizationScope.cs index 1d3363cb8b..c3bd8438d8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemSynchronizationScope.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemSynchronizationScope.cs @@ -1,158 +1,158 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.ServiceFramework.Core -{ - using System; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - - /// - /// Encapsulates a system mutex that can be used for inter-process synchronization of operations. - /// - internal sealed class SystemSynchronizationScope : IDisposable - { - private readonly Mutex mutex; - private readonly bool isOwned; - - /// - /// Initializes a new instance of the class. - /// - /// Name of the mutex. - /// Time to wait to acquire the mutex. - public SystemSynchronizationScope(string name, TimeSpan timeout = default) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentException("Name should not be null or empty", nameof(name)); - } - - this.MutexName = name; - Mutex tempMutex = default; - try - { - tempMutex = new Mutex(initiallyOwned: true, this.MutexName, out bool createdNew); - if (!createdNew) - { - DefaultTrace.TraceInformation($"{this.TraceId}: Acquiring existing system mutex '{this.MutexName}'"); - try - { - timeout = timeout == default ? Timeout.InfiniteTimeSpan : timeout; - this.isOwned = tempMutex.WaitOne(timeout); - if (!this.isOwned) - { - throw new TimeoutException($"Timed out waiting for system mutex '{this.MutexName}'"); - } - - DefaultTrace.TraceInformation($"{this.TraceId}: Acquired existing system mutex '{this.MutexName}'"); - } - catch (AbandonedMutexException amEx) - { - DefaultTrace.TraceWarning($"{this.TraceId}: {nameof(AbandonedMutexException)} waiting for mutex '{this.MutexName}': {amEx}"); - this.isOwned = true; - } - } - else - { - this.isOwned = true; - DefaultTrace.TraceInformation($"{this.TraceId}: Created system mutex '{this.MutexName}'"); - } - - this.mutex = tempMutex; - tempMutex = default; - } - finally - { - this.ReleaseAndDisposeMutexSave(tempMutex); - } - } - - /// - /// Gets the name of the system mutex. - /// - public string MutexName { get; } - - private string TraceId => $"{nameof(SystemSynchronizationScope)}[{Environment.CurrentManagedThreadId}]"; - - /// - /// Creates a synchronization object based on a mutex of the given name to guarantee that the code within the scope executes synchronously - /// across processes. - /// - /// Name of the scope mutex. - /// Time to wait to acquire the mutex. - /// Object which releases the scope mutex when disposed. - public static SystemSynchronizationScope CreateSynchronizationScope(string name, TimeSpan timeout = default) - => new SystemSynchronizationScope(name, timeout); - - /// - /// Executes an operation within a system mutex synchronization scope. - /// - /// Name of the scope mutex. - /// Operation to be executed. - /// Time to wait to acquire the mutex. - /// Result of the . - /// Thrown if the is null. - public static TResult ExecuteWithSynchronization(string name, Func function, TimeSpan timeout = default) - { - if (function == null) - { - throw new ArgumentNullException(nameof(name)); - } - - using (SystemSynchronizationScope.CreateSynchronizationScope(name, timeout)) - { - return function.Invoke(); - } - } - - /// - /// Executes an operation within a system mutex synchronization scope. - /// - /// Name of the scope mutex. - /// Operation to be executed. - /// Time to wait to acquire the mutex. - /// Thrown if the is null. - public static void ExecuteWithSynchronization(string name, Action action, TimeSpan timeout = default) - { - SystemSynchronizationScope.ExecuteWithSynchronization(name, - function: () => - { - action.Invoke(); - return true; - }, - timeout); - } - - public void Dispose() - { - this.ReleaseAndDisposeMutexSave(this.mutex); - } - - private void ReleaseAndDisposeMutexSave(Mutex mutex) - { - if (mutex != null) - { - try - { - // If we already have the mutex then release it. - if (this.isOwned) - { - DefaultTrace.TraceInformation($"{this.TraceId}: Releasing system mutex '{this.MutexName}'"); - mutex.ReleaseMutex(); - } - } - catch (AbandonedMutexException amEx) - { - DefaultTrace.TraceWarning($"{this.TraceId}: {nameof(AbandonedMutexException)} waiting for mutex '{this.MutexName}': {amEx}"); - } - catch (ApplicationException appEx) - { - DefaultTrace.TraceWarning($"{this.TraceId}: Exception releasing system mutex '{this.MutexName}': {appEx}"); - } - - mutex.Dispose(); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.ServiceFramework.Core +{ + using System; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// Encapsulates a system mutex that can be used for inter-process synchronization of operations. + /// + internal sealed class SystemSynchronizationScope : IDisposable + { + private readonly Mutex mutex; + private readonly bool isOwned; + + /// + /// Initializes a new instance of the class. + /// + /// Name of the mutex. + /// Time to wait to acquire the mutex. + public SystemSynchronizationScope(string name, TimeSpan timeout = default) + { + if (string.IsNullOrWhiteSpace(name)) + { + throw new ArgumentException("Name should not be null or empty", nameof(name)); + } + + this.MutexName = name; + Mutex tempMutex = default; + try + { + tempMutex = new Mutex(initiallyOwned: true, this.MutexName, out bool createdNew); + if (!createdNew) + { + DefaultTrace.TraceInformation($"{this.TraceId}: Acquiring existing system mutex '{this.MutexName}'"); + try + { + timeout = timeout == default ? Timeout.InfiniteTimeSpan : timeout; + this.isOwned = tempMutex.WaitOne(timeout); + if (!this.isOwned) + { + throw new TimeoutException($"Timed out waiting for system mutex '{this.MutexName}'"); + } + + DefaultTrace.TraceInformation($"{this.TraceId}: Acquired existing system mutex '{this.MutexName}'"); + } + catch (AbandonedMutexException amEx) + { + DefaultTrace.TraceWarning($"{this.TraceId}: {nameof(AbandonedMutexException)} waiting for mutex '{this.MutexName}': {amEx}"); + this.isOwned = true; + } + } + else + { + this.isOwned = true; + DefaultTrace.TraceInformation($"{this.TraceId}: Created system mutex '{this.MutexName}'"); + } + + this.mutex = tempMutex; + tempMutex = default; + } + finally + { + this.ReleaseAndDisposeMutexSave(tempMutex); + } + } + + /// + /// Gets the name of the system mutex. + /// + public string MutexName { get; } + + private string TraceId => $"{nameof(SystemSynchronizationScope)}[{Environment.CurrentManagedThreadId}]"; + + /// + /// Creates a synchronization object based on a mutex of the given name to guarantee that the code within the scope executes synchronously + /// across processes. + /// + /// Name of the scope mutex. + /// Time to wait to acquire the mutex. + /// Object which releases the scope mutex when disposed. + public static SystemSynchronizationScope CreateSynchronizationScope(string name, TimeSpan timeout = default) + => new SystemSynchronizationScope(name, timeout); + + /// + /// Executes an operation within a system mutex synchronization scope. + /// + /// Name of the scope mutex. + /// Operation to be executed. + /// Time to wait to acquire the mutex. + /// Result of the . + /// Thrown if the is null. + public static TResult ExecuteWithSynchronization(string name, Func function, TimeSpan timeout = default) + { + if (function == null) + { + throw new ArgumentNullException(nameof(name)); + } + + using (SystemSynchronizationScope.CreateSynchronizationScope(name, timeout)) + { + return function.Invoke(); + } + } + + /// + /// Executes an operation within a system mutex synchronization scope. + /// + /// Name of the scope mutex. + /// Operation to be executed. + /// Time to wait to acquire the mutex. + /// Thrown if the is null. + public static void ExecuteWithSynchronization(string name, Action action, TimeSpan timeout = default) + { + SystemSynchronizationScope.ExecuteWithSynchronization(name, + function: () => + { + action.Invoke(); + return true; + }, + timeout); + } + + public void Dispose() + { + this.ReleaseAndDisposeMutexSave(this.mutex); + } + + private void ReleaseAndDisposeMutexSave(Mutex mutex) + { + if (mutex != null) + { + try + { + // If we already have the mutex then release it. + if (this.isOwned) + { + DefaultTrace.TraceInformation($"{this.TraceId}: Releasing system mutex '{this.MutexName}'"); + mutex.ReleaseMutex(); + } + } + catch (AbandonedMutexException amEx) + { + DefaultTrace.TraceWarning($"{this.TraceId}: {nameof(AbandonedMutexException)} waiting for mutex '{this.MutexName}': {amEx}"); + } + catch (ApplicationException appEx) + { + DefaultTrace.TraceWarning($"{this.TraceId}: Exception releasing system mutex '{this.MutexName}': {appEx}"); + } + + mutex.Dispose(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemUsageHistory.cs b/Microsoft.Azure.Cosmos/src/direct/SystemUsageHistory.cs index 3079d70764..c9c2626f2e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemUsageHistory.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemUsageHistory.cs @@ -1,162 +1,162 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Threading; - using System.Linq; - using System.Text; - - internal class SystemUsageHistory - { - internal ReadOnlyCollection Values { get; } - - private readonly TimeSpan monitoringInterval; - private readonly Lazy loadHistory; - private readonly Lazy cpuHigh; - private readonly Lazy cpuThreadStarvation; - - public SystemUsageHistory(ReadOnlyCollection data, - TimeSpan monitoringInterval) - { - this.Values = data ?? throw new ArgumentNullException(nameof(data)); - if(this.Values.Count > 0) - { - this.LastTimestamp = this.Values.Last().Timestamp; - } - else - { - this.LastTimestamp = DateTime.MinValue; - } - - this.loadHistory = new Lazy(() => { - if(this.Values == null || this.Values.Count == 0) - { - return "{\"systemHistory\":\"Empty\"}"; - } - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.Append("{\"systemHistory\":["); - foreach (SystemUsageLoad systemUsage in this.Values) - { - systemUsage.AppendJsonString(stringBuilder); - stringBuilder.Append(","); - } - - stringBuilder.Length--; // Remove the extra comma at the end - stringBuilder.Append("]}"); - - return stringBuilder.ToString(); - }); - - if (monitoringInterval <= TimeSpan.Zero) - { - throw new ArgumentOutOfRangeException( - nameof(monitoringInterval), - monitoringInterval, - string.Format("{0} must be strictly positive", nameof(monitoringInterval))); - } - - this.monitoringInterval = monitoringInterval; - this.cpuHigh = new Lazy(this.GetCpuHigh, - LazyThreadSafetyMode.ExecutionAndPublication); - this.cpuThreadStarvation = new Lazy(this.GetCpuThreadStarvation, - LazyThreadSafetyMode.ExecutionAndPublication); - } - - internal DateTime LastTimestamp { get; } - - public override string ToString() - { - return this.loadHistory.Value; - } - - /// - /// Use the cached string since the system load will be the same - /// for multiple requests. - /// - public void AppendJsonString(StringBuilder stringBuilder) - { - stringBuilder.Append(this.ToString()); - } - - public bool? IsCpuHigh - { - get - { - return this.cpuHigh.Value; - } - } - - public bool? IsCpuThreadStarvation - { - get - { - return this.cpuThreadStarvation.Value; - } - } - - private bool? GetCpuHigh() - { - if(this.Values.Count == 0) - { - return null; - } - - // If the CPU value is not set return null. - bool? isCpuHigh = null; - foreach(SystemUsageLoad systemUsageLoad in this.Values) - { - if (!systemUsageLoad.CpuUsage.HasValue) - { - continue; - } - - if(systemUsageLoad.CpuUsage.Value > 90.0) - { - return true; - } - else - { - isCpuHigh = false; - } - } - - return isCpuHigh; - } - - private bool? GetCpuThreadStarvation() - { - if (this.Values.Count == 0) - { - return null; - } - - // If the CPU value is not set return null. - bool? isThreadStarvation = null; - foreach (SystemUsageLoad systemUsageLoad in this.Values) - { - if (systemUsageLoad.ThreadInfo == null - || !systemUsageLoad.ThreadInfo.IsThreadStarving.HasValue) - { - continue; - } - - if (systemUsageLoad.ThreadInfo.IsThreadStarving.Value) - { - return true; - } - else - { - isThreadStarvation = false; - } - } - - return isThreadStarvation; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Threading; + using System.Linq; + using System.Text; + + internal class SystemUsageHistory + { + internal ReadOnlyCollection Values { get; } + + private readonly TimeSpan monitoringInterval; + private readonly Lazy loadHistory; + private readonly Lazy cpuHigh; + private readonly Lazy cpuThreadStarvation; + + public SystemUsageHistory(ReadOnlyCollection data, + TimeSpan monitoringInterval) + { + this.Values = data ?? throw new ArgumentNullException(nameof(data)); + if(this.Values.Count > 0) + { + this.LastTimestamp = this.Values.Last().Timestamp; + } + else + { + this.LastTimestamp = DateTime.MinValue; + } + + this.loadHistory = new Lazy(() => { + if(this.Values == null || this.Values.Count == 0) + { + return "{\"systemHistory\":\"Empty\"}"; + } + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Append("{\"systemHistory\":["); + foreach (SystemUsageLoad systemUsage in this.Values) + { + systemUsage.AppendJsonString(stringBuilder); + stringBuilder.Append(","); + } + + stringBuilder.Length--; // Remove the extra comma at the end + stringBuilder.Append("]}"); + + return stringBuilder.ToString(); + }); + + if (monitoringInterval <= TimeSpan.Zero) + { + throw new ArgumentOutOfRangeException( + nameof(monitoringInterval), + monitoringInterval, + string.Format("{0} must be strictly positive", nameof(monitoringInterval))); + } + + this.monitoringInterval = monitoringInterval; + this.cpuHigh = new Lazy(this.GetCpuHigh, + LazyThreadSafetyMode.ExecutionAndPublication); + this.cpuThreadStarvation = new Lazy(this.GetCpuThreadStarvation, + LazyThreadSafetyMode.ExecutionAndPublication); + } + + internal DateTime LastTimestamp { get; } + + public override string ToString() + { + return this.loadHistory.Value; + } + + /// + /// Use the cached string since the system load will be the same + /// for multiple requests. + /// + public void AppendJsonString(StringBuilder stringBuilder) + { + stringBuilder.Append(this.ToString()); + } + + public bool? IsCpuHigh + { + get + { + return this.cpuHigh.Value; + } + } + + public bool? IsCpuThreadStarvation + { + get + { + return this.cpuThreadStarvation.Value; + } + } + + private bool? GetCpuHigh() + { + if(this.Values.Count == 0) + { + return null; + } + + // If the CPU value is not set return null. + bool? isCpuHigh = null; + foreach(SystemUsageLoad systemUsageLoad in this.Values) + { + if (!systemUsageLoad.CpuUsage.HasValue) + { + continue; + } + + if(systemUsageLoad.CpuUsage.Value > 90.0) + { + return true; + } + else + { + isCpuHigh = false; + } + } + + return isCpuHigh; + } + + private bool? GetCpuThreadStarvation() + { + if (this.Values.Count == 0) + { + return null; + } + + // If the CPU value is not set return null. + bool? isThreadStarvation = null; + foreach (SystemUsageLoad systemUsageLoad in this.Values) + { + if (systemUsageLoad.ThreadInfo == null + || !systemUsageLoad.ThreadInfo.IsThreadStarving.HasValue) + { + continue; + } + + if (systemUsageLoad.ThreadInfo.IsThreadStarving.Value) + { + return true; + } + else + { + isThreadStarvation = false; + } + } + + return isThreadStarvation; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemUsageLoad.cs b/Microsoft.Azure.Cosmos/src/direct/SystemUsageLoad.cs index 6484ac9c90..ba96e7c166 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemUsageLoad.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemUsageLoad.cs @@ -1,61 +1,61 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Globalization; - using System.Text; - - internal struct SystemUsageLoad - { - public readonly DateTime Timestamp; - public readonly float? CpuUsage; - public readonly long? MemoryAvailable; - public readonly ThreadInformation ThreadInfo; - public readonly int? NumberOfOpenTcpConnections; - - public SystemUsageLoad(DateTime timestamp, - ThreadInformation threadInfo, - float? cpuUsage = null, - long? memoryAvailable = null, - int? numberOfOpenTcpConnection = 0) - { - this.Timestamp = timestamp; - this.CpuUsage = cpuUsage; - this.MemoryAvailable = memoryAvailable; - this.ThreadInfo = threadInfo ?? throw new ArgumentNullException("Thread Information can not be null"); - this.NumberOfOpenTcpConnections = numberOfOpenTcpConnection; - } - - public void AppendJsonString(StringBuilder stringBuilder) - { - stringBuilder.Append("{\"dateUtc\":\""); - stringBuilder.Append(this.Timestamp.ToString("O", CultureInfo.InvariantCulture)); - stringBuilder.Append("\",\"cpu\":"); - stringBuilder.Append(this.CpuUsage.HasValue && !float.IsNaN(this.CpuUsage.Value) ? this.CpuUsage.Value.ToString("F3", CultureInfo.InvariantCulture) : "\"no info\""); - stringBuilder.Append(",\"memory\":"); - stringBuilder.Append(this.MemoryAvailable.HasValue ? this.MemoryAvailable.Value.ToString("F3", CultureInfo.InvariantCulture) : "\"no info\""); - stringBuilder.Append(",\"threadInfo\":"); - if(this.ThreadInfo != null) - { - this.ThreadInfo.AppendJsonString(stringBuilder); - } - else - { - stringBuilder.Append("\"no info\""); - } - stringBuilder.Append(",\"numberOfOpenTcpConnection\":"); - stringBuilder.Append(this.NumberOfOpenTcpConnections.HasValue ? this.NumberOfOpenTcpConnections.Value.ToString(CultureInfo.InvariantCulture) : "\"no info\""); - - stringBuilder.Append("}"); - } - - public override string ToString() - { - return string.Format( - CultureInfo.InvariantCulture, "({0:O} => CpuUsage :{1:F3}, MemoryAvailable :{2:F3} {3:F3}, NumberOfOpenTcpConnection : {4} )", - this.Timestamp, this.CpuUsage, this.MemoryAvailable, this.ThreadInfo.ToString(), this.NumberOfOpenTcpConnections); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Globalization; + using System.Text; + + internal struct SystemUsageLoad + { + public readonly DateTime Timestamp; + public readonly float? CpuUsage; + public readonly long? MemoryAvailable; + public readonly ThreadInformation ThreadInfo; + public readonly int? NumberOfOpenTcpConnections; + + public SystemUsageLoad(DateTime timestamp, + ThreadInformation threadInfo, + float? cpuUsage = null, + long? memoryAvailable = null, + int? numberOfOpenTcpConnection = 0) + { + this.Timestamp = timestamp; + this.CpuUsage = cpuUsage; + this.MemoryAvailable = memoryAvailable; + this.ThreadInfo = threadInfo ?? throw new ArgumentNullException("Thread Information can not be null"); + this.NumberOfOpenTcpConnections = numberOfOpenTcpConnection; + } + + public void AppendJsonString(StringBuilder stringBuilder) + { + stringBuilder.Append("{\"dateUtc\":\""); + stringBuilder.Append(this.Timestamp.ToString("O", CultureInfo.InvariantCulture)); + stringBuilder.Append("\",\"cpu\":"); + stringBuilder.Append(this.CpuUsage.HasValue && !float.IsNaN(this.CpuUsage.Value) ? this.CpuUsage.Value.ToString("F3", CultureInfo.InvariantCulture) : "\"no info\""); + stringBuilder.Append(",\"memory\":"); + stringBuilder.Append(this.MemoryAvailable.HasValue ? this.MemoryAvailable.Value.ToString("F3", CultureInfo.InvariantCulture) : "\"no info\""); + stringBuilder.Append(",\"threadInfo\":"); + if(this.ThreadInfo != null) + { + this.ThreadInfo.AppendJsonString(stringBuilder); + } + else + { + stringBuilder.Append("\"no info\""); + } + stringBuilder.Append(",\"numberOfOpenTcpConnection\":"); + stringBuilder.Append(this.NumberOfOpenTcpConnections.HasValue ? this.NumberOfOpenTcpConnections.Value.ToString(CultureInfo.InvariantCulture) : "\"no info\""); + + stringBuilder.Append("}"); + } + + public override string ToString() + { + return string.Format( + CultureInfo.InvariantCulture, "({0:O} => CpuUsage :{1:F3}, MemoryAvailable :{2:F3} {3:F3}, NumberOfOpenTcpConnection : {4} )", + this.Timestamp, this.CpuUsage, this.MemoryAvailable, this.ThreadInfo.ToString(), this.NumberOfOpenTcpConnections); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemUsageMonitor.cs b/Microsoft.Azure.Cosmos/src/direct/SystemUsageMonitor.cs index 1c12c380ba..628b4d7858 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemUsageMonitor.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemUsageMonitor.cs @@ -1,226 +1,226 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Diagnostics; - using System.Linq; - using System.Runtime.InteropServices; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using static Microsoft.Azure.Documents.Rntbd.SystemUsageMonitor; -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - internal sealed class SystemUsageMonitor : IDisposable - { - private readonly SystemUtilizationReaderBase systemUtilizationReader = SystemUtilizationReaderBase.SingletonInstance; - private readonly IDictionary recorders = new Dictionary(); - private readonly Stopwatch watch = new Stopwatch(); - - private int pollDelayInMilliSeconds; - private CancellationTokenSource cancellation; - - private Task periodicTask { set; get; } - private bool disposed { set; get; } - - internal int PollDelayInMs => pollDelayInMilliSeconds; - public bool IsRunning() => (this.periodicTask.Status == TaskStatus.Running); - - internal bool TryGetBackgroundTaskException(out AggregateException aggregateException) - { - aggregateException = this.periodicTask?.Exception; - return aggregateException != null; - } - - public static SystemUsageMonitor CreateAndStart(IReadOnlyList usageRecorders) - { - SystemUsageMonitor monitor = new SystemUsageMonitor(usageRecorders); - monitor.Start(); - - return monitor; - } - - private SystemUsageMonitor(IReadOnlyList recorders) - { - if (recorders.Count == 0) - { - throw new ArgumentException("No Recorders are configured so nothing to process"); - } - - int pollDelay = 0; - foreach (SystemUsageRecorder recorder in recorders) - { - this.recorders.Add(recorder.identifier, recorder); - pollDelay = this.GCD((int)recorder.refreshInterval.TotalMilliseconds, pollDelay); - } - - this.pollDelayInMilliSeconds = pollDelay; - } - - /// - /// This Function gives GCD of given 2 numbers. - /// - /// - /// - /// - private int GCD(int timeInterval1, int timeInterval2) - { - return timeInterval2 == 0 ? - timeInterval1 : - this.GCD(timeInterval2, timeInterval1 % timeInterval2); - } - - private void Start() - { - this.ThrowIfDisposed(); - if (this.periodicTask != null) - { - throw new InvalidOperationException(nameof(SystemUsageMonitor) + " already started"); - } - - this.cancellation = new CancellationTokenSource(); - this.periodicTask = Task.Run( - () => this.RefreshLoopAsync(this.cancellation.Token), - this.cancellation.Token); - - this.periodicTask.ContinueWith( - t => - { - DefaultTrace.TraceError( - "The CPU and Memory usage monitoring refresh task failed. Exception: {0}", - t.Exception); - }, - TaskContinuationOptions.OnlyOnFaulted); - - this.periodicTask.ContinueWith( - t => - { - DefaultTrace.TraceWarning( - "The CPU and Memory usage monitoring refresh task stopped. Status: {0}", - t.Status); - }, - TaskContinuationOptions.NotOnFaulted); - - DefaultTrace.TraceInformation(nameof(SystemUsageMonitor) + " started"); - } - - /// - /// Stop the Monitoring - /// - public void Stop() - { - this.ThrowIfDisposed(); - - if (this.periodicTask == null) - { - throw new InvalidOperationException(nameof(SystemUsageMonitor) + " not running"); - } - - CancellationTokenSource cancel = this.cancellation; - Task backgroundTask = this.periodicTask; - - this.watch.Stop(); - - this.cancellation = null; - this.periodicTask = null; - - cancel.Cancel(); - try - { - backgroundTask.Wait(); - } - catch (AggregateException) - { } - cancel.Dispose(); - DefaultTrace.TraceInformation(nameof(SystemUsageMonitor) + " stopped"); - } - - public SystemUsageRecorder GetRecorder(string recorderKey) - { - this.ThrowIfDisposed(); - - if (this.periodicTask == null) - { - DefaultTrace.TraceError(nameof(SystemUsageMonitor) + " is not started"); - throw new InvalidOperationException(nameof(SystemUsageMonitor) + " was not started"); - } - - return this.recorders.TryGetValue(recorderKey, out SystemUsageRecorder recorder) ? - recorder : - throw new ArgumentException("Recorder Identifier not present i.e. " + recorderKey); - } - - public void Dispose() - { - this.ThrowIfDisposed(); - if (this.periodicTask != null) - { - this.Stop(); - } - - this.disposed = true; - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException(nameof(SystemUsageMonitor)); - } - - } - - /// - /// Keep Running and keep record the System Usage. - /// - /// - private void RefreshLoopAsync(CancellationToken cancellationToken) - { - while (!cancellationToken.IsCancellationRequested) - { - if (!this.watch.IsRunning) - { - this.watch.Start(); - } - - // reset value on each iteration - Nullable usageData = null; - - foreach (SystemUsageRecorder recorder in this.recorders.Values) - { - if(recorder.IsEligibleForRecording(this.watch)) - { - // Getting CPU and Memory Usage from utilization reader if its not there only first time, use this value for all the recorders - if (usageData == null) - { - DateTime now = DateTime.UtcNow; - usageData = new SystemUsageLoad( - timestamp: now, - threadInfo: ThreadInformation.Get(), - cpuUsage: systemUtilizationReader.GetSystemWideCpuUsage(), - memoryAvailable: systemUtilizationReader.GetSystemWideMemoryAvailabilty(), - numberOfOpenTcpConnection: Connection.NumberOfOpenTcpConnections); - } - - // record the above calculated usage if eligible - recorder.RecordUsage(usageData.Value, this.watch); - } - } - - #if NETSTANDARD15 || NETSTANDARD16 - Task.Delay(this.pollDelayInMilliSeconds).Wait(); - #else - Thread.Sleep(this.pollDelayInMilliSeconds); - #endif - - } - } - - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Linq; + using System.Runtime.InteropServices; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using static Microsoft.Azure.Documents.Rntbd.SystemUsageMonitor; +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + internal sealed class SystemUsageMonitor : IDisposable + { + private readonly SystemUtilizationReaderBase systemUtilizationReader = SystemUtilizationReaderBase.SingletonInstance; + private readonly IDictionary recorders = new Dictionary(); + private readonly Stopwatch watch = new Stopwatch(); + + private int pollDelayInMilliSeconds; + private CancellationTokenSource cancellation; + + private Task periodicTask { set; get; } + private bool disposed { set; get; } + + internal int PollDelayInMs => pollDelayInMilliSeconds; + public bool IsRunning() => (this.periodicTask.Status == TaskStatus.Running); + + internal bool TryGetBackgroundTaskException(out AggregateException aggregateException) + { + aggregateException = this.periodicTask?.Exception; + return aggregateException != null; + } + + public static SystemUsageMonitor CreateAndStart(IReadOnlyList usageRecorders) + { + SystemUsageMonitor monitor = new SystemUsageMonitor(usageRecorders); + monitor.Start(); + + return monitor; + } + + private SystemUsageMonitor(IReadOnlyList recorders) + { + if (recorders.Count == 0) + { + throw new ArgumentException("No Recorders are configured so nothing to process"); + } + + int pollDelay = 0; + foreach (SystemUsageRecorder recorder in recorders) + { + this.recorders.Add(recorder.identifier, recorder); + pollDelay = this.GCD((int)recorder.refreshInterval.TotalMilliseconds, pollDelay); + } + + this.pollDelayInMilliSeconds = pollDelay; + } + + /// + /// This Function gives GCD of given 2 numbers. + /// + /// + /// + /// + private int GCD(int timeInterval1, int timeInterval2) + { + return timeInterval2 == 0 ? + timeInterval1 : + this.GCD(timeInterval2, timeInterval1 % timeInterval2); + } + + private void Start() + { + this.ThrowIfDisposed(); + if (this.periodicTask != null) + { + throw new InvalidOperationException(nameof(SystemUsageMonitor) + " already started"); + } + + this.cancellation = new CancellationTokenSource(); + this.periodicTask = Task.Run( + () => this.RefreshLoopAsync(this.cancellation.Token), + this.cancellation.Token); + + this.periodicTask.ContinueWith( + t => + { + DefaultTrace.TraceError( + "The CPU and Memory usage monitoring refresh task failed. Exception: {0}", + t.Exception); + }, + TaskContinuationOptions.OnlyOnFaulted); + + this.periodicTask.ContinueWith( + t => + { + DefaultTrace.TraceWarning( + "The CPU and Memory usage monitoring refresh task stopped. Status: {0}", + t.Status); + }, + TaskContinuationOptions.NotOnFaulted); + + DefaultTrace.TraceInformation(nameof(SystemUsageMonitor) + " started"); + } + + /// + /// Stop the Monitoring + /// + public void Stop() + { + this.ThrowIfDisposed(); + + if (this.periodicTask == null) + { + throw new InvalidOperationException(nameof(SystemUsageMonitor) + " not running"); + } + + CancellationTokenSource cancel = this.cancellation; + Task backgroundTask = this.periodicTask; + + this.watch.Stop(); + + this.cancellation = null; + this.periodicTask = null; + + cancel.Cancel(); + try + { + backgroundTask.Wait(); + } + catch (AggregateException) + { } + cancel.Dispose(); + DefaultTrace.TraceInformation(nameof(SystemUsageMonitor) + " stopped"); + } + + public SystemUsageRecorder GetRecorder(string recorderKey) + { + this.ThrowIfDisposed(); + + if (this.periodicTask == null) + { + DefaultTrace.TraceError(nameof(SystemUsageMonitor) + " is not started"); + throw new InvalidOperationException(nameof(SystemUsageMonitor) + " was not started"); + } + + return this.recorders.TryGetValue(recorderKey, out SystemUsageRecorder recorder) ? + recorder : + throw new ArgumentException("Recorder Identifier not present i.e. " + recorderKey); + } + + public void Dispose() + { + this.ThrowIfDisposed(); + if (this.periodicTask != null) + { + this.Stop(); + } + + this.disposed = true; + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + throw new ObjectDisposedException(nameof(SystemUsageMonitor)); + } + + } + + /// + /// Keep Running and keep record the System Usage. + /// + /// + private void RefreshLoopAsync(CancellationToken cancellationToken) + { + while (!cancellationToken.IsCancellationRequested) + { + if (!this.watch.IsRunning) + { + this.watch.Start(); + } + + // reset value on each iteration + Nullable usageData = null; + + foreach (SystemUsageRecorder recorder in this.recorders.Values) + { + if(recorder.IsEligibleForRecording(this.watch)) + { + // Getting CPU and Memory Usage from utilization reader if its not there only first time, use this value for all the recorders + if (usageData == null) + { + DateTime now = DateTime.UtcNow; + usageData = new SystemUsageLoad( + timestamp: now, + threadInfo: ThreadInformation.Get(), + cpuUsage: systemUtilizationReader.GetSystemWideCpuUsage(), + memoryAvailable: systemUtilizationReader.GetSystemWideMemoryAvailabilty(), + numberOfOpenTcpConnection: Connection.NumberOfOpenTcpConnections); + } + + // record the above calculated usage if eligible + recorder.RecordUsage(usageData.Value, this.watch); + } + } + + #if NETSTANDARD15 || NETSTANDARD16 + Task.Delay(this.pollDelayInMilliSeconds).Wait(); + #else + Thread.Sleep(this.pollDelayInMilliSeconds); + #endif + + } + } + + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemUsageRecorder.cs b/Microsoft.Azure.Cosmos/src/direct/SystemUsageRecorder.cs index 7ec98c2a31..bd35ffccd2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemUsageRecorder.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemUsageRecorder.cs @@ -1,72 +1,72 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Diagnostics; - using System.Linq; - using System.Runtime.InteropServices; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using static Microsoft.Azure.Documents.Rntbd.SystemUsageMonitor; -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - internal sealed class SystemUsageRecorder - { - internal readonly string identifier; - private readonly int historyLength; - internal readonly TimeSpan refreshInterval; - - private readonly Queue historyQueue; - - private TimeSpan nextTimeStamp; - - public SystemUsageHistory Data { private set; get; } - - internal SystemUsageRecorder(string identifier, - int historyLength, - TimeSpan refreshInterval) - { - this.identifier = String.IsNullOrEmpty(identifier) ? throw new ArgumentException("Identifier can not be null.") : identifier; - this.historyLength = (historyLength <= 0) ? throw new ArgumentOutOfRangeException("historyLength can not be less than or equal to zero.") : historyLength; - this.refreshInterval = (refreshInterval <= TimeSpan.Zero) ? throw new ArgumentException("refreshInterval timespan can not be zero.") : refreshInterval; - - this.historyQueue = new Queue(this.historyLength); - } - - /// - /// Record System usage (i.e. CPU, Memory, Thread Availability) - /// for UnSupported Reader CPU usage is NaN and Memory Usage will be null. - /// Thread Information will be calculated for both kind of readers. - /// Although for netstandard 1.5 and 1.6 It will just give Thread Starvation information and for other frameworks/environments it gives Available Thread/Minimum Thread/Maximum Thread - /// - /// - /// - internal void RecordUsage(SystemUsageLoad systemUsageLoad, Stopwatch watch) - { - this.nextTimeStamp = watch.Elapsed.Add(refreshInterval); - this.Data = new SystemUsageHistory(this.Collect(systemUsageLoad), this.refreshInterval); - } - - private ReadOnlyCollection Collect(SystemUsageLoad loadData) - { - if(historyQueue.Count == historyLength) - { - historyQueue.Dequeue(); - } - historyQueue.Enqueue(loadData); - - return new ReadOnlyCollection(historyQueue.ToList()); - } - - internal bool IsEligibleForRecording(Stopwatch watch) => TimeSpan.Compare(watch.Elapsed, nextTimeStamp) >= 0; - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Linq; + using System.Runtime.InteropServices; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using static Microsoft.Azure.Documents.Rntbd.SystemUsageMonitor; +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + internal sealed class SystemUsageRecorder + { + internal readonly string identifier; + private readonly int historyLength; + internal readonly TimeSpan refreshInterval; + + private readonly Queue historyQueue; + + private TimeSpan nextTimeStamp; + + public SystemUsageHistory Data { private set; get; } + + internal SystemUsageRecorder(string identifier, + int historyLength, + TimeSpan refreshInterval) + { + this.identifier = String.IsNullOrEmpty(identifier) ? throw new ArgumentException("Identifier can not be null.") : identifier; + this.historyLength = (historyLength <= 0) ? throw new ArgumentOutOfRangeException("historyLength can not be less than or equal to zero.") : historyLength; + this.refreshInterval = (refreshInterval <= TimeSpan.Zero) ? throw new ArgumentException("refreshInterval timespan can not be zero.") : refreshInterval; + + this.historyQueue = new Queue(this.historyLength); + } + + /// + /// Record System usage (i.e. CPU, Memory, Thread Availability) + /// for UnSupported Reader CPU usage is NaN and Memory Usage will be null. + /// Thread Information will be calculated for both kind of readers. + /// Although for netstandard 1.5 and 1.6 It will just give Thread Starvation information and for other frameworks/environments it gives Available Thread/Minimum Thread/Maximum Thread + /// + /// + /// + internal void RecordUsage(SystemUsageLoad systemUsageLoad, Stopwatch watch) + { + this.nextTimeStamp = watch.Elapsed.Add(refreshInterval); + this.Data = new SystemUsageHistory(this.Collect(systemUsageLoad), this.refreshInterval); + } + + private ReadOnlyCollection Collect(SystemUsageLoad loadData) + { + if(historyQueue.Count == historyLength) + { + historyQueue.Dequeue(); + } + historyQueue.Enqueue(loadData); + + return new ReadOnlyCollection(historyQueue.ToList()); + } + + internal bool IsEligibleForRecording(Stopwatch watch) => TimeSpan.Compare(watch.Elapsed, nextTimeStamp) >= 0; + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/SystemUtilizationReaderBase.cs b/Microsoft.Azure.Cosmos/src/direct/SystemUtilizationReaderBase.cs index eec7dd3f6c..e1c533b937 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SystemUtilizationReaderBase.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SystemUtilizationReaderBase.cs @@ -1,139 +1,139 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Diagnostics.CodeAnalysis; - using System.Runtime.InteropServices; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - - internal abstract class SystemUtilizationReaderBase - { - private float cachedCpuUtilization = Single.NaN; - private long lastCpuUsageReadTimeTicks = DateTime.MinValue.Ticks; - private static readonly Lazy singletonInstance = new Lazy( - SystemUtilizationReaderBase.Create, - LazyThreadSafetyMode.ExecutionAndPublication); - - // Just for testing purposes - no need to be thread-safe - private static SystemUtilizationReaderBase singletonOverride; - - protected SystemUtilizationReaderBase() - { - } - - public static SystemUtilizationReaderBase SingletonInstance - { - get - { - SystemUtilizationReaderBase snapshot; - if ((snapshot = singletonOverride) != null) - { - return snapshot; - } - - return singletonInstance.Value; - } - } - - internal static void ApplySingletonOverride(SystemUtilizationReaderBase readerOverride) - { - singletonOverride = readerOverride; - } - - /// - /// Caches the CPU utilization for an user defined eviction time period and evicts the cache atomically based on - /// the eviction time period. - /// - /// A containing the cache eviction time in seconds. - /// A float value containing the cached cpu usage. - public float GetSystemWideCpuUsageCached( - TimeSpan cacheEvictionTimeInSeconds) - { - long snapshotTimestampTicks = Volatile.Read(ref this.lastCpuUsageReadTimeTicks); - long currentTimestampTicks = Stopwatch.GetTimestamp(); - long delta = currentTimestampTicks - snapshotTimestampTicks; - - if (delta >= cacheEvictionTimeInSeconds.Ticks) - { - long updatedLastCpuUsageReadTimeTicks = Interlocked.CompareExchange( - location1: ref this.lastCpuUsageReadTimeTicks, - value: currentTimestampTicks, - comparand: snapshotTimestampTicks); - - // This means that the value was not updated by any other thread and the compare exchange operation was atomically successful. - if (updatedLastCpuUsageReadTimeTicks == snapshotTimestampTicks) - { - Volatile.Write(ref this.cachedCpuUtilization, this.GetSystemWideCpuUsage()); - } - } - - return Volatile.Read(ref this.cachedCpuUtilization); - } - - [SuppressMessage( - "Design", - "CA1031:Do not catch general exception types", - Justification = "Intentional catch-all-rethrow here t log exception")] - public float GetSystemWideCpuUsage() - { - try - { - return this.GetSystemWideCpuUsageCore(); - } - catch (Exception exception) - { - DefaultTrace.TraceError( - "Reading the system-wide CPU usage failed. Exception: {0}", - exception); - - return Single.NaN; - } - } - - public long? GetSystemWideMemoryAvailabilty() - { - try - { - return this.GetSystemWideMemoryAvailabiltyCore(); - } - catch (Exception exception) - { - DefaultTrace.TraceError( - "Reading the system-wide Memory availability failed. Exception: {0}", - exception); - - return null; - } - } - -#if NETFX - private static SystemUtilizationReaderBase Create() - { - return new WindowsSystemUtilizationReader(); - } -#else - private static SystemUtilizationReaderBase Create() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - return new WindowsSystemUtilizationReader(); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return new LinuxSystemUtilizationReader(); - } else - { - return new UnsupportedSystemUtilizationReader(); - } - } -#endif // NETFX - - protected abstract float GetSystemWideCpuUsageCore(); - - protected abstract long? GetSystemWideMemoryAvailabiltyCore(); - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Runtime.InteropServices; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + + internal abstract class SystemUtilizationReaderBase + { + private float cachedCpuUtilization = Single.NaN; + private long lastCpuUsageReadTimeTicks = DateTime.MinValue.Ticks; + private static readonly Lazy singletonInstance = new Lazy( + SystemUtilizationReaderBase.Create, + LazyThreadSafetyMode.ExecutionAndPublication); + + // Just for testing purposes - no need to be thread-safe + private static SystemUtilizationReaderBase singletonOverride; + + protected SystemUtilizationReaderBase() + { + } + + public static SystemUtilizationReaderBase SingletonInstance + { + get + { + SystemUtilizationReaderBase snapshot; + if ((snapshot = singletonOverride) != null) + { + return snapshot; + } + + return singletonInstance.Value; + } + } + + internal static void ApplySingletonOverride(SystemUtilizationReaderBase readerOverride) + { + singletonOverride = readerOverride; + } + + /// + /// Caches the CPU utilization for an user defined eviction time period and evicts the cache atomically based on + /// the eviction time period. + /// + /// A containing the cache eviction time in seconds. + /// A float value containing the cached cpu usage. + public float GetSystemWideCpuUsageCached( + TimeSpan cacheEvictionTimeInSeconds) + { + long snapshotTimestampTicks = Volatile.Read(ref this.lastCpuUsageReadTimeTicks); + long currentTimestampTicks = Stopwatch.GetTimestamp(); + long delta = currentTimestampTicks - snapshotTimestampTicks; + + if (delta >= cacheEvictionTimeInSeconds.Ticks) + { + long updatedLastCpuUsageReadTimeTicks = Interlocked.CompareExchange( + location1: ref this.lastCpuUsageReadTimeTicks, + value: currentTimestampTicks, + comparand: snapshotTimestampTicks); + + // This means that the value was not updated by any other thread and the compare exchange operation was atomically successful. + if (updatedLastCpuUsageReadTimeTicks == snapshotTimestampTicks) + { + Volatile.Write(ref this.cachedCpuUtilization, this.GetSystemWideCpuUsage()); + } + } + + return Volatile.Read(ref this.cachedCpuUtilization); + } + + [SuppressMessage( + "Design", + "CA1031:Do not catch general exception types", + Justification = "Intentional catch-all-rethrow here t log exception")] + public float GetSystemWideCpuUsage() + { + try + { + return this.GetSystemWideCpuUsageCore(); + } + catch (Exception exception) + { + DefaultTrace.TraceError( + "Reading the system-wide CPU usage failed. Exception: {0}", + exception); + + return Single.NaN; + } + } + + public long? GetSystemWideMemoryAvailabilty() + { + try + { + return this.GetSystemWideMemoryAvailabiltyCore(); + } + catch (Exception exception) + { + DefaultTrace.TraceError( + "Reading the system-wide Memory availability failed. Exception: {0}", + exception); + + return null; + } + } + +#if NETFX + private static SystemUtilizationReaderBase Create() + { + return new WindowsSystemUtilizationReader(); + } +#else + private static SystemUtilizationReaderBase Create() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return new WindowsSystemUtilizationReader(); + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return new LinuxSystemUtilizationReader(); + } else + { + return new UnsupportedSystemUtilizationReader(); + } + } +#endif // NETFX + + protected abstract float GetSystemWideCpuUsageCore(); + + protected abstract long? GetSystemWideMemoryAvailabiltyCore(); + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/TaskFactoryExtensions.cs b/Microsoft.Azure.Cosmos/src/direct/TaskFactoryExtensions.cs index 99223173c7..90881148cb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TaskFactoryExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TaskFactoryExtensions.cs @@ -1,92 +1,92 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -#if COSMOS_CORE -namespace Microsoft.Azure.Cosmos.Core -#else -namespace Microsoft.Azure.Documents -#endif -{ - using System; - using System.Threading; - using System.Threading.Tasks; - - /// - /// Extensions to task factory methods that are meant to be used as patterns of invocation of asynchronous operations - /// inside compute gateway ensuring continuity of execution on the current task scheduler. - /// Task scheduler is used to track resource consumption per tenant so it is critical that all async activity - /// pertaining to the tenant runs on the same task scheduler. - /// - internal static class TaskFactoryExtensions - { - /// Creates and starts a on the current task scheduler. - /// The started . - /// Instance of the to use for starting the task. - /// The action delegate to execute asynchronously. - /// The exception that is thrown when the argument is null. - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action) - { - return taskFactory.StartNew(action, default(CancellationToken), TaskCreationOptions.None, TaskScheduler.Current); - } - - /// Creates and starts a on the current task scheduler. - /// The started . - /// Instance of the to use for starting the task. - /// The action delegate to execute asynchronously. - /// The that will be assigned to the new task. - /// The provided has already been disposed. - /// The exception that is thrown when the argument is null. - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action, CancellationToken cancellationToken) - { - return taskFactory.StartNew(action, cancellationToken, TaskCreationOptions.None, TaskScheduler.Current); - } - - /// Creates and starts a on the current task scheduler. - /// The started . - /// Instance of the to use for starting the task. - /// The action delegate to execute asynchronously. - /// A TaskCreationOptions value that controls the behavior of the created . - /// The provided has already been disposed. - /// The exception that is thrown when the argument is null. - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action, TaskCreationOptions creationOptions) - { - return taskFactory.StartNew(action, default(CancellationToken), creationOptions, TaskScheduler.Current); - } - - /// Creates and starts a on the current task scheduler. - /// The started . - /// Instance of the to use for starting the task. - /// A function delegate that returns the future result to be available through the . - /// The type of the result available through the . - /// The exception that is thrown when the argument is null. - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function) - { - return taskFactory.StartNew(function, default(CancellationToken), TaskCreationOptions.None, TaskScheduler.Current); - } - - /// Creates and starts a on the current task scheduler. - /// The started . - /// Instance of the to use for starting the task. - /// A function delegate that returns the future result to be available through the . - /// The that will be assigned to the new task. - /// The type of the result available through the . - /// The exception that is thrown when the argument is null. - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function, CancellationToken cancellationToken) - { - return taskFactory.StartNew(function, cancellationToken, TaskCreationOptions.None, TaskScheduler.Current); - } - - /// Creates and starts a . - /// The started . - /// Instance of the to use for starting the task. - /// A function delegate that returns the future result to be available through the . - /// A TaskCreationOptions value that controls the behavior of the created . - /// The type of the result available through the . - /// The exception that is thrown when the argument is null. - /// The exception that is thrown when the argument specifies an invalid TaskCreationOptions value. The exception that is thrown when the argument specifies an invalid TaskCreationOptions value. For more information, see the Remarks for . - public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function, TaskCreationOptions creationOptions) - { - return taskFactory.StartNew(function, default(CancellationToken), creationOptions, TaskScheduler.Current); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +#if COSMOS_CORE +namespace Microsoft.Azure.Cosmos.Core +#else +namespace Microsoft.Azure.Documents +#endif +{ + using System; + using System.Threading; + using System.Threading.Tasks; + + /// + /// Extensions to task factory methods that are meant to be used as patterns of invocation of asynchronous operations + /// inside compute gateway ensuring continuity of execution on the current task scheduler. + /// Task scheduler is used to track resource consumption per tenant so it is critical that all async activity + /// pertaining to the tenant runs on the same task scheduler. + /// + internal static class TaskFactoryExtensions + { + /// Creates and starts a on the current task scheduler. + /// The started . + /// Instance of the to use for starting the task. + /// The action delegate to execute asynchronously. + /// The exception that is thrown when the argument is null. + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action) + { + return taskFactory.StartNew(action, default(CancellationToken), TaskCreationOptions.None, TaskScheduler.Current); + } + + /// Creates and starts a on the current task scheduler. + /// The started . + /// Instance of the to use for starting the task. + /// The action delegate to execute asynchronously. + /// The that will be assigned to the new task. + /// The provided has already been disposed. + /// The exception that is thrown when the argument is null. + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action, CancellationToken cancellationToken) + { + return taskFactory.StartNew(action, cancellationToken, TaskCreationOptions.None, TaskScheduler.Current); + } + + /// Creates and starts a on the current task scheduler. + /// The started . + /// Instance of the to use for starting the task. + /// The action delegate to execute asynchronously. + /// A TaskCreationOptions value that controls the behavior of the created . + /// The provided has already been disposed. + /// The exception that is thrown when the argument is null. + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Action action, TaskCreationOptions creationOptions) + { + return taskFactory.StartNew(action, default(CancellationToken), creationOptions, TaskScheduler.Current); + } + + /// Creates and starts a on the current task scheduler. + /// The started . + /// Instance of the to use for starting the task. + /// A function delegate that returns the future result to be available through the . + /// The type of the result available through the . + /// The exception that is thrown when the argument is null. + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function) + { + return taskFactory.StartNew(function, default(CancellationToken), TaskCreationOptions.None, TaskScheduler.Current); + } + + /// Creates and starts a on the current task scheduler. + /// The started . + /// Instance of the to use for starting the task. + /// A function delegate that returns the future result to be available through the . + /// The that will be assigned to the new task. + /// The type of the result available through the . + /// The exception that is thrown when the argument is null. + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function, CancellationToken cancellationToken) + { + return taskFactory.StartNew(function, cancellationToken, TaskCreationOptions.None, TaskScheduler.Current); + } + + /// Creates and starts a . + /// The started . + /// Instance of the to use for starting the task. + /// A function delegate that returns the future result to be available through the . + /// A TaskCreationOptions value that controls the behavior of the created . + /// The type of the result available through the . + /// The exception that is thrown when the argument is null. + /// The exception that is thrown when the argument specifies an invalid TaskCreationOptions value. The exception that is thrown when the argument specifies an invalid TaskCreationOptions value. For more information, see the Remarks for . + public static Task StartNewOnCurrentTaskSchedulerAsync(this TaskFactory taskFactory, Func function, TaskCreationOptions creationOptions) + { + return taskFactory.StartNew(function, default(CancellationToken), creationOptions, TaskScheduler.Current); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ThreadInformation.cs b/Microsoft.Azure.Cosmos/src/direct/ThreadInformation.cs index 36b90fcaf8..4600d3db96 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ThreadInformation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ThreadInformation.cs @@ -1,174 +1,174 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Rntbd -{ - using Microsoft.Azure.Cosmos.Core.Trace; - using System.Diagnostics; - using System.Globalization; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - - internal sealed class ThreadInformation - { - private static readonly object lockObject = new object(); - - internal int? AvailableThreads { get; } - internal int? MinThreads { get; } - internal int? MaxThreads { get; } - internal bool? IsThreadStarving { get; } - internal double? ThreadWaitIntervalInMs { get; } - - private static Stopwatch watch; - private static Task task; - - public static ThreadInformation Get() - { - int? avlWorkerThreads = null; - int? minWorkerThreads = null; - int? maxWorkerThreads = null; - - ThreadInformation threadInfo = null; - - lock (lockObject) - { - -#if !(NETSTANDARD15 || NETSTANDARD16) - ThreadPool.GetAvailableThreads(out int tempAvlWorkerThreads, out _); - avlWorkerThreads = tempAvlWorkerThreads; - ThreadPool.GetMinThreads(out int tempMinWorkerThreads, out _); - minWorkerThreads = tempMinWorkerThreads; - ThreadPool.GetMaxThreads(out int tempMaxWorkerThreads, out _); - maxWorkerThreads = tempMaxWorkerThreads; -#endif - - bool? isThreadStarving = null; - double? threadWaitIntervalInMs = null; - - //First time watch and task will be null - if (ThreadInformation.watch != null && ThreadInformation.task != null) - { - threadWaitIntervalInMs = ThreadInformation.watch.Elapsed.TotalMilliseconds; - - // its thread starvation - // a) if total elapsed time for stopwatch was more than 1s - // b) last task failed due to some error - isThreadStarving = (threadWaitIntervalInMs > 1000 || ThreadInformation.task.IsFaulted); - - // If task is faulted, stop the watch manually. otherwise keep it running - if(ThreadInformation.task.IsFaulted && ThreadInformation.watch.IsRunning) - { - DefaultTrace.TraceError("Thread Starvation detection task failed. Exception: {0}", ThreadInformation.task.Exception); - ThreadInformation.watch.Stop(); - } - } - - // First time isThreadStarving, threadWaitIntervalInMs will be null. - threadInfo = new ThreadInformation( - availableThreads: avlWorkerThreads, - minThreads: minWorkerThreads, - maxThreads: maxWorkerThreads, - isThreadStarving: isThreadStarving, - threadWaitIntervalInMs: threadWaitIntervalInMs); - - // if previous task is still not started running yet then do not reinitialize the watch (or new task). - if (ThreadInformation.watch == null || !ThreadInformation.watch.IsRunning) - { - // if last watch was stopped then reinitialize it - ThreadInformation.watch = Stopwatch.StartNew(); - - ThreadInformation.task = Task.Factory.StartNew(() => - { - ThreadInformation.watch.Stop(); - }); - } - } - - return threadInfo; - } - - private ThreadInformation( - int? availableThreads, - int? minThreads, - int? maxThreads, - bool? isThreadStarving, - double? threadWaitIntervalInMs) - { - this.AvailableThreads = availableThreads; - this.MinThreads = minThreads; - this.MaxThreads = maxThreads; - this.IsThreadStarving = isThreadStarving; - this.ThreadWaitIntervalInMs = threadWaitIntervalInMs; - } - - public void AppendJsonString(StringBuilder stringBuilder) - { - stringBuilder.Append("{\"isThreadStarving\":\""); - if (this.IsThreadStarving.HasValue) - { - stringBuilder.Append(this.IsThreadStarving.Value).Append("\","); - } - else - { - stringBuilder.Append("no info\","); - } - - if (this.ThreadWaitIntervalInMs.HasValue) - { - stringBuilder.Append("\"threadWaitIntervalInMs\":").Append(this.ThreadWaitIntervalInMs.Value.ToString(CultureInfo.InvariantCulture)).Append(","); - } - - if (this.AvailableThreads.HasValue) - { - stringBuilder.Append("\"availableThreads\":").Append(this.AvailableThreads.Value).Append(","); - } - - if (this.MinThreads.HasValue) - { - stringBuilder.Append("\"minThreads\":").Append(this.MinThreads.Value).Append(","); - } - - if (this.MaxThreads.HasValue) - { - stringBuilder.Append("\"maxThreads\":").Append(this.MaxThreads.Value).Append(","); - } - - stringBuilder.Length--; // Remove the extra comma at the end - stringBuilder.Append("}"); - } - - public override string ToString() - { - StringBuilder builder = new StringBuilder(); - - if (this.IsThreadStarving.HasValue) - { - builder.Append("IsThreadStarving :").Append(this.IsThreadStarving.Value); - } - - if (this.ThreadWaitIntervalInMs.HasValue) - { - builder.Append(" ThreadWaitIntervalInMs :").Append(this.ThreadWaitIntervalInMs.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (this.AvailableThreads.HasValue) - { - builder.Append(" AvailableThreads :").Append(this.AvailableThreads.Value); - } - - if (this.MinThreads.HasValue) - { - builder.Append(" MinThreads :").Append(this.MinThreads.Value); - } - - if (this.MaxThreads.HasValue) - { - builder.Append(" MaxThreads :").Append(this.MaxThreads.Value); - } - - return builder.ToString(); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Rntbd +{ + using Microsoft.Azure.Cosmos.Core.Trace; + using System.Diagnostics; + using System.Globalization; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + + internal sealed class ThreadInformation + { + private static readonly object lockObject = new object(); + + internal int? AvailableThreads { get; } + internal int? MinThreads { get; } + internal int? MaxThreads { get; } + internal bool? IsThreadStarving { get; } + internal double? ThreadWaitIntervalInMs { get; } + + private static Stopwatch watch; + private static Task task; + + public static ThreadInformation Get() + { + int? avlWorkerThreads = null; + int? minWorkerThreads = null; + int? maxWorkerThreads = null; + + ThreadInformation threadInfo = null; + + lock (lockObject) + { + +#if !(NETSTANDARD15 || NETSTANDARD16) + ThreadPool.GetAvailableThreads(out int tempAvlWorkerThreads, out _); + avlWorkerThreads = tempAvlWorkerThreads; + ThreadPool.GetMinThreads(out int tempMinWorkerThreads, out _); + minWorkerThreads = tempMinWorkerThreads; + ThreadPool.GetMaxThreads(out int tempMaxWorkerThreads, out _); + maxWorkerThreads = tempMaxWorkerThreads; +#endif + + bool? isThreadStarving = null; + double? threadWaitIntervalInMs = null; + + //First time watch and task will be null + if (ThreadInformation.watch != null && ThreadInformation.task != null) + { + threadWaitIntervalInMs = ThreadInformation.watch.Elapsed.TotalMilliseconds; + + // its thread starvation + // a) if total elapsed time for stopwatch was more than 1s + // b) last task failed due to some error + isThreadStarving = (threadWaitIntervalInMs > 1000 || ThreadInformation.task.IsFaulted); + + // If task is faulted, stop the watch manually. otherwise keep it running + if(ThreadInformation.task.IsFaulted && ThreadInformation.watch.IsRunning) + { + DefaultTrace.TraceError("Thread Starvation detection task failed. Exception: {0}", ThreadInformation.task.Exception); + ThreadInformation.watch.Stop(); + } + } + + // First time isThreadStarving, threadWaitIntervalInMs will be null. + threadInfo = new ThreadInformation( + availableThreads: avlWorkerThreads, + minThreads: minWorkerThreads, + maxThreads: maxWorkerThreads, + isThreadStarving: isThreadStarving, + threadWaitIntervalInMs: threadWaitIntervalInMs); + + // if previous task is still not started running yet then do not reinitialize the watch (or new task). + if (ThreadInformation.watch == null || !ThreadInformation.watch.IsRunning) + { + // if last watch was stopped then reinitialize it + ThreadInformation.watch = Stopwatch.StartNew(); + + ThreadInformation.task = Task.Factory.StartNew(() => + { + ThreadInformation.watch.Stop(); + }); + } + } + + return threadInfo; + } + + private ThreadInformation( + int? availableThreads, + int? minThreads, + int? maxThreads, + bool? isThreadStarving, + double? threadWaitIntervalInMs) + { + this.AvailableThreads = availableThreads; + this.MinThreads = minThreads; + this.MaxThreads = maxThreads; + this.IsThreadStarving = isThreadStarving; + this.ThreadWaitIntervalInMs = threadWaitIntervalInMs; + } + + public void AppendJsonString(StringBuilder stringBuilder) + { + stringBuilder.Append("{\"isThreadStarving\":\""); + if (this.IsThreadStarving.HasValue) + { + stringBuilder.Append(this.IsThreadStarving.Value).Append("\","); + } + else + { + stringBuilder.Append("no info\","); + } + + if (this.ThreadWaitIntervalInMs.HasValue) + { + stringBuilder.Append("\"threadWaitIntervalInMs\":").Append(this.ThreadWaitIntervalInMs.Value.ToString(CultureInfo.InvariantCulture)).Append(","); + } + + if (this.AvailableThreads.HasValue) + { + stringBuilder.Append("\"availableThreads\":").Append(this.AvailableThreads.Value).Append(","); + } + + if (this.MinThreads.HasValue) + { + stringBuilder.Append("\"minThreads\":").Append(this.MinThreads.Value).Append(","); + } + + if (this.MaxThreads.HasValue) + { + stringBuilder.Append("\"maxThreads\":").Append(this.MaxThreads.Value).Append(","); + } + + stringBuilder.Length--; // Remove the extra comma at the end + stringBuilder.Append("}"); + } + + public override string ToString() + { + StringBuilder builder = new StringBuilder(); + + if (this.IsThreadStarving.HasValue) + { + builder.Append("IsThreadStarving :").Append(this.IsThreadStarving.Value); + } + + if (this.ThreadWaitIntervalInMs.HasValue) + { + builder.Append(" ThreadWaitIntervalInMs :").Append(this.ThreadWaitIntervalInMs.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (this.AvailableThreads.HasValue) + { + builder.Append(" AvailableThreads :").Append(this.AvailableThreads.Value); + } + + if (this.MinThreads.HasValue) + { + builder.Append(" MinThreads :").Append(this.MinThreads.Value); + } + + if (this.MaxThreads.HasValue) + { + builder.Append(" MaxThreads :").Append(this.MaxThreads.Value); + } + + return builder.ToString(); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/TimeoutHelper.cs b/Microsoft.Azure.Cosmos/src/direct/TimeoutHelper.cs index ea8c87d3a5..103fa7ed84 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TimeoutHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TimeoutHelper.cs @@ -1,55 +1,55 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Threading; - - /// - /// Tracks remaining timespan. - /// - internal sealed class TimeoutHelper - { - private readonly DateTime startTime; - private readonly TimeSpan timeOut; - private readonly CancellationToken cancellationToken; - - public TimeoutHelper(TimeSpan timeOut, CancellationToken cancellationToken = default(CancellationToken)) - { - this.startTime = DateTime.UtcNow; - this.timeOut = timeOut; - this.cancellationToken = cancellationToken; - } - - public bool IsElapsed() - { - TimeSpan elapsed = DateTime.UtcNow.Subtract(this.startTime); - return elapsed >= this.timeOut; - } - - public TimeSpan GetRemainingTime() - { - TimeSpan elapsed = DateTime.UtcNow.Subtract(this.startTime); - return this.timeOut.Subtract(elapsed); - } - - public void ThrowTimeoutIfElapsed() - { - if(this.IsElapsed()) - { - throw new RequestTimeoutException(RMResources.RequestTimeout); - } - } - - public void ThrowGoneIfElapsed() - { - this.cancellationToken.ThrowIfCancellationRequested(); - if (this.IsElapsed()) - { - throw new GoneException(RMResources.Gone, SubStatusCodes.TimeoutGenerated410); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Threading; + + /// + /// Tracks remaining timespan. + /// + internal sealed class TimeoutHelper + { + private readonly DateTime startTime; + private readonly TimeSpan timeOut; + private readonly CancellationToken cancellationToken; + + public TimeoutHelper(TimeSpan timeOut, CancellationToken cancellationToken = default(CancellationToken)) + { + this.startTime = DateTime.UtcNow; + this.timeOut = timeOut; + this.cancellationToken = cancellationToken; + } + + public bool IsElapsed() + { + TimeSpan elapsed = DateTime.UtcNow.Subtract(this.startTime); + return elapsed >= this.timeOut; + } + + public TimeSpan GetRemainingTime() + { + TimeSpan elapsed = DateTime.UtcNow.Subtract(this.startTime); + return this.timeOut.Subtract(elapsed); + } + + public void ThrowTimeoutIfElapsed() + { + if(this.IsElapsed()) + { + throw new RequestTimeoutException(RMResources.RequestTimeout); + } + } + + public void ThrowGoneIfElapsed() + { + this.cancellationToken.ThrowIfCancellationRequested(); + if (this.IsElapsed()) + { + throw new GoneException(RMResources.Gone, SubStatusCodes.TimeoutGenerated410); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs b/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs index 3c8d6166a5..bd60654ba1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs @@ -1,247 +1,247 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Concurrent; - using System.Collections.Generic; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - - /// - /// This class reduces the overhead associated with creating and disposing timers created for shortlived activities - /// It creates a PooledTimer which when started, returns a Task that you can await on and which will complete if the timeout expires - /// This is preferred over DelayTaskTimer since it only creates a single timer which is used for the lifetime of the pool. - /// It can *only* fire the timers at the minimum granularity configured. - /// - internal sealed class TimerPool : IDisposable - { - [ThreadStatic] - private static Random PooledTimerBucketSelector; - - private readonly Timer timer; - private readonly ConcurrentDictionary>[] pooledTimersByTimeout; - private readonly TimeSpan minSupportedTimeout; - private readonly object timerConcurrencyLock; // protects isRunning to reject concurrent timer callback. Irrelevant to subscriptionLock. - private bool isRunning = false; - private bool isDisposed = false; - - public TimeSpan MinSupportedTimeout - { - get { return minSupportedTimeout; } - } - - public TimerPool(int minSupportedTimerDelayInSeconds, int maxBucketsForPools = -1) - { - this.timerConcurrencyLock = new Object(); - this.minSupportedTimeout = TimeSpan.FromSeconds(minSupportedTimerDelayInSeconds > 0 ? minSupportedTimerDelayInSeconds : 1); - - maxBucketsForPools = maxBucketsForPools > 0 ? maxBucketsForPools : Environment.ProcessorCount; - - this.pooledTimersByTimeout = new ConcurrentDictionary>[maxBucketsForPools]; - for (int i = 0; i < maxBucketsForPools; i++) - { - this.pooledTimersByTimeout[i] = new ConcurrentDictionary>(); - } - - TimerCallback timerDelegate = new TimerCallback(OnTimer); - this.timer = new Timer(timerDelegate, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(minSupportedTimerDelayInSeconds)); - DefaultTrace.TraceInformation("TimerPool Created with minSupportedTimerDelayInSeconds = {0}", minSupportedTimerDelayInSeconds); - } - - public void Dispose() - { - if (this.isDisposed) - { - return; - } - - this.DisposeAllPooledTimers(); - - this.isDisposed = true; - } - - private void ThrowIfDisposed() - { - if (this.isDisposed) - { - throw new ObjectDisposedException("TimerPool"); - } - } - - private void DisposeAllPooledTimers() - { - DefaultTrace.TraceInformation("TimerPool Disposing"); - - foreach (ConcurrentDictionary> timers in this.pooledTimersByTimeout) - { - foreach (KeyValuePair> kv in timers) - { - ConcurrentQueue pooledTimerQueue = kv.Value; - PooledTimer timer; - while (pooledTimerQueue.TryDequeue(out timer)) - { - timer.CancelTimer(); - } - } - - } - - this.timer.Dispose(); - DefaultTrace.TraceInformation("TimePool Disposed"); - } - - private void OnTimer(Object stateInfo) - { - lock(this.timerConcurrencyLock) - { - if(!this.isRunning) - { - this.isRunning = true; - } - else - { - return; - } - } - try - { - // get the current tick count which will be used to compare to - // timeout duration and fire timeouts - long currentTicks = DateTime.UtcNow.Ticks; - - foreach (ConcurrentDictionary> timerBucket in this.pooledTimersByTimeout) - { - foreach (KeyValuePair> kv in timerBucket) - { - ConcurrentQueue pooledTimerQueue = kv.Value; - int count = kv.Value.Count; - long lastTicks = 0; - - for (int nIndex = 0; nIndex < count; nIndex++) - { - PooledTimer pooledTimer; - - // We keeping peeking, firing timeouts, and dequeuing until reach hit the first - // element whose timeout has not occcured. - if (pooledTimerQueue.TryPeek(out pooledTimer)) - { - if (currentTicks >= pooledTimer.TimeoutTicks) - { - if (pooledTimer.TimeoutTicks < lastTicks) - { - // Queue of timers should have expiry in increasing tick order - DefaultTrace.TraceCritical("LastTicks: {0}, PooledTimer.Ticks: {1}", - lastTicks, - pooledTimer.TimeoutTicks); - } - - pooledTimer.FireTimeout(); - lastTicks = pooledTimer.TimeoutTicks; - PooledTimer timer; - if (pooledTimerQueue.TryDequeue(out timer)) - { - // this is purely a correctness check - if (!ReferenceEquals(timer, pooledTimer)) - { - // should never occur since there can only be 1 thread in this code at time. - DefaultTrace.TraceCritical( - "Timer objects peeked and dequeued are not equal"); - pooledTimerQueue.Enqueue(timer); - } - } - } - else - { - // reached the element whose timeout has not yet expired, - // break out and move to the next queue. - break; - } - } - } - } - } - } - catch(Exception ex) - { - DefaultTrace.TraceCritical("Hit exception ex: {0}\n, stack: {1}", ex.Message, ex.StackTrace); - } - finally - { - lock(timerConcurrencyLock) - { - isRunning = false; - } - } - } - - internal ConcurrentDictionary>[] PooledTimersByTimeout - { - get - { - return this.pooledTimersByTimeout; - } - } - - /// - /// get a timer with timeout specified in seconds - /// - /// - /// - public PooledTimer GetPooledTimer(int timeoutInSeconds) - { - this.ThrowIfDisposed(); - return new PooledTimer(timeoutInSeconds, this); - } - - /// - /// get a timer with timeout specified as a TimeSpan - /// - /// - /// - public PooledTimer GetPooledTimer(TimeSpan timeout) - { - this.ThrowIfDisposed(); - return new PooledTimer(timeout, this); - } - - /// - /// Start the countdown for timeout - /// - /// - /// the begin ticks of the timer - public long SubscribeForTimeouts(PooledTimer pooledTimer) - { - this.ThrowIfDisposed(); - if(pooledTimer.Timeout < this.minSupportedTimeout) - { - DefaultTrace.TraceWarning("Timer timeoutinSeconds {0} is less than minSupportedTimeoutInSeconds {1}, will use the minsupported value", - pooledTimer.Timeout.TotalSeconds, - this.minSupportedTimeout.TotalSeconds); - pooledTimer.Timeout = this.minSupportedTimeout; - } - - if (TimerPool.PooledTimerBucketSelector == null) - { - TimerPool.PooledTimerBucketSelector = new Random(); - } - - int bucketIndex = TimerPool.PooledTimerBucketSelector.Next(this.pooledTimersByTimeout.Length); - - if (!this.pooledTimersByTimeout[bucketIndex].TryGetValue((int)pooledTimer.Timeout.TotalSeconds, out ConcurrentQueue timerQueue)) - { - timerQueue = this.pooledTimersByTimeout[bucketIndex].GetOrAdd((int)pooledTimer.Timeout.TotalSeconds, - (_) => new ConcurrentQueue()); - } - - // in order to enqueue timers into a queue by their TimeoutTicks, do TimeoutTicks generation and enqueue atomically. - lock (timerQueue) - { - timerQueue.Enqueue(pooledTimer); - return DateTime.UtcNow.Ticks; - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// This class reduces the overhead associated with creating and disposing timers created for shortlived activities + /// It creates a PooledTimer which when started, returns a Task that you can await on and which will complete if the timeout expires + /// This is preferred over DelayTaskTimer since it only creates a single timer which is used for the lifetime of the pool. + /// It can *only* fire the timers at the minimum granularity configured. + /// + internal sealed class TimerPool : IDisposable + { + [ThreadStatic] + private static Random PooledTimerBucketSelector; + + private readonly Timer timer; + private readonly ConcurrentDictionary>[] pooledTimersByTimeout; + private readonly TimeSpan minSupportedTimeout; + private readonly object timerConcurrencyLock; // protects isRunning to reject concurrent timer callback. Irrelevant to subscriptionLock. + private bool isRunning = false; + private bool isDisposed = false; + + public TimeSpan MinSupportedTimeout + { + get { return minSupportedTimeout; } + } + + public TimerPool(int minSupportedTimerDelayInSeconds, int maxBucketsForPools = -1) + { + this.timerConcurrencyLock = new Object(); + this.minSupportedTimeout = TimeSpan.FromSeconds(minSupportedTimerDelayInSeconds > 0 ? minSupportedTimerDelayInSeconds : 1); + + maxBucketsForPools = maxBucketsForPools > 0 ? maxBucketsForPools : Environment.ProcessorCount; + + this.pooledTimersByTimeout = new ConcurrentDictionary>[maxBucketsForPools]; + for (int i = 0; i < maxBucketsForPools; i++) + { + this.pooledTimersByTimeout[i] = new ConcurrentDictionary>(); + } + + TimerCallback timerDelegate = new TimerCallback(OnTimer); + this.timer = new Timer(timerDelegate, null, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(minSupportedTimerDelayInSeconds)); + DefaultTrace.TraceInformation("TimerPool Created with minSupportedTimerDelayInSeconds = {0}", minSupportedTimerDelayInSeconds); + } + + public void Dispose() + { + if (this.isDisposed) + { + return; + } + + this.DisposeAllPooledTimers(); + + this.isDisposed = true; + } + + private void ThrowIfDisposed() + { + if (this.isDisposed) + { + throw new ObjectDisposedException("TimerPool"); + } + } + + private void DisposeAllPooledTimers() + { + DefaultTrace.TraceInformation("TimerPool Disposing"); + + foreach (ConcurrentDictionary> timers in this.pooledTimersByTimeout) + { + foreach (KeyValuePair> kv in timers) + { + ConcurrentQueue pooledTimerQueue = kv.Value; + PooledTimer timer; + while (pooledTimerQueue.TryDequeue(out timer)) + { + timer.CancelTimer(); + } + } + + } + + this.timer.Dispose(); + DefaultTrace.TraceInformation("TimePool Disposed"); + } + + private void OnTimer(Object stateInfo) + { + lock(this.timerConcurrencyLock) + { + if(!this.isRunning) + { + this.isRunning = true; + } + else + { + return; + } + } + try + { + // get the current tick count which will be used to compare to + // timeout duration and fire timeouts + long currentTicks = DateTime.UtcNow.Ticks; + + foreach (ConcurrentDictionary> timerBucket in this.pooledTimersByTimeout) + { + foreach (KeyValuePair> kv in timerBucket) + { + ConcurrentQueue pooledTimerQueue = kv.Value; + int count = kv.Value.Count; + long lastTicks = 0; + + for (int nIndex = 0; nIndex < count; nIndex++) + { + PooledTimer pooledTimer; + + // We keeping peeking, firing timeouts, and dequeuing until reach hit the first + // element whose timeout has not occcured. + if (pooledTimerQueue.TryPeek(out pooledTimer)) + { + if (currentTicks >= pooledTimer.TimeoutTicks) + { + if (pooledTimer.TimeoutTicks < lastTicks) + { + // Queue of timers should have expiry in increasing tick order + DefaultTrace.TraceCritical("LastTicks: {0}, PooledTimer.Ticks: {1}", + lastTicks, + pooledTimer.TimeoutTicks); + } + + pooledTimer.FireTimeout(); + lastTicks = pooledTimer.TimeoutTicks; + PooledTimer timer; + if (pooledTimerQueue.TryDequeue(out timer)) + { + // this is purely a correctness check + if (!ReferenceEquals(timer, pooledTimer)) + { + // should never occur since there can only be 1 thread in this code at time. + DefaultTrace.TraceCritical( + "Timer objects peeked and dequeued are not equal"); + pooledTimerQueue.Enqueue(timer); + } + } + } + else + { + // reached the element whose timeout has not yet expired, + // break out and move to the next queue. + break; + } + } + } + } + } + } + catch(Exception ex) + { + DefaultTrace.TraceCritical("Hit exception ex: {0}\n, stack: {1}", ex.Message, ex.StackTrace); + } + finally + { + lock(timerConcurrencyLock) + { + isRunning = false; + } + } + } + + internal ConcurrentDictionary>[] PooledTimersByTimeout + { + get + { + return this.pooledTimersByTimeout; + } + } + + /// + /// get a timer with timeout specified in seconds + /// + /// + /// + public PooledTimer GetPooledTimer(int timeoutInSeconds) + { + this.ThrowIfDisposed(); + return new PooledTimer(timeoutInSeconds, this); + } + + /// + /// get a timer with timeout specified as a TimeSpan + /// + /// + /// + public PooledTimer GetPooledTimer(TimeSpan timeout) + { + this.ThrowIfDisposed(); + return new PooledTimer(timeout, this); + } + + /// + /// Start the countdown for timeout + /// + /// + /// the begin ticks of the timer + public long SubscribeForTimeouts(PooledTimer pooledTimer) + { + this.ThrowIfDisposed(); + if(pooledTimer.Timeout < this.minSupportedTimeout) + { + DefaultTrace.TraceWarning("Timer timeoutinSeconds {0} is less than minSupportedTimeoutInSeconds {1}, will use the minsupported value", + pooledTimer.Timeout.TotalSeconds, + this.minSupportedTimeout.TotalSeconds); + pooledTimer.Timeout = this.minSupportedTimeout; + } + + if (TimerPool.PooledTimerBucketSelector == null) + { + TimerPool.PooledTimerBucketSelector = new Random(); + } + + int bucketIndex = TimerPool.PooledTimerBucketSelector.Next(this.pooledTimersByTimeout.Length); + + if (!this.pooledTimersByTimeout[bucketIndex].TryGetValue((int)pooledTimer.Timeout.TotalSeconds, out ConcurrentQueue timerQueue)) + { + timerQueue = this.pooledTimersByTimeout[bucketIndex].GetOrAdd((int)pooledTimer.Timeout.TotalSeconds, + (_) => new ConcurrentQueue()); + } + + // in order to enqueue timers into a queue by their TimeoutTicks, do TimeoutTicks generation and enqueue atomically. + lock (timerQueue) + { + timerQueue.Enqueue(pooledTimer); + return DateTime.UtcNow.Ticks; + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportAddressHealthState.cs b/Microsoft.Azure.Cosmos/src/direct/TransportAddressHealthState.cs index e29e013c52..92da958bfa 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportAddressHealthState.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportAddressHealthState.cs @@ -1,153 +1,153 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - - /// - /// Wraps the different health statuses and their corresponding last known timestamps - /// for a transport address uri. - /// - internal sealed class TransportAddressHealthState - { - /// - /// A read-only field containing the last unknown timestamp. - /// - private readonly DateTime? lastUnknownTimestamp; - - /// - /// A read-only field containing the last unhealthy pending timestamp. - /// - private readonly DateTime? lastUnhealthyPendingTimestamp; - - /// - /// A read-only field containing the last unhealthy timestamp. - /// - private readonly DateTime? lastUnhealthyTimestamp; - - /// - /// The read-only health status Enum containing the transport address health status. - /// - private readonly HealthStatus healthStatus; - - /// - /// The read-only health status diagnostic string containing the URI and health status information. - /// - private readonly string healthStatusDiagnosticString; - - /// - /// A read-only list of health status diagnostic string. - /// - private readonly IReadOnlyList healthStatusDiagnosticEnumerable; - - /// - /// The constructor for initializing the . - /// - /// An instance off containing the physical uri. - /// An instance of containing - /// the current health status of the transport address. - /// The last unknown timestamp. - /// The last unhealthy pending timestamp. - /// The last unhealthy timestamp. - public TransportAddressHealthState( - Uri transportUri, - HealthStatus healthStatus, - DateTime? lastUnknownTimestamp, - DateTime? lastUnhealthyPendingTimestamp, - DateTime? lastUnhealthyTimestamp) - { - if (transportUri is null) - { - throw new ArgumentNullException( - paramName: nameof(transportUri), - message: $"Argument {nameof(transportUri)} can not be null"); - } - - this.healthStatus = healthStatus; - this.lastUnknownTimestamp = lastUnknownTimestamp; - this.lastUnhealthyPendingTimestamp = lastUnhealthyPendingTimestamp; - this.lastUnhealthyTimestamp = lastUnhealthyTimestamp; - this.healthStatusDiagnosticString = $"(port: {transportUri.Port} | status: {healthStatus} | lkt: {this.GetLastKnownTimestampByHealthStatus(healthStatus)})"; - - List healthStatusList = new () - { - this.healthStatusDiagnosticString, - }; - this.healthStatusDiagnosticEnumerable = healthStatusList.AsReadOnly(); - } - - /// - /// Gets the current health status of the transport address uri. - /// - /// An instance of containing - /// the current health status. - public HealthStatus GetHealthStatus() - { - return this.healthStatus; - } - - /// - /// Gets the Transport Address Uri health status diagnostic string. - /// - /// A string containing the health status diagnostics information. - public string GetHealthStatusDiagnosticString() - { - return this.healthStatusDiagnosticString; - } - - /// - /// Gets the Transport Address Uri health status diagnostics as a read-only . - /// - /// An containing the health status diagnostics information. - public IEnumerable GetHealthStatusDiagnosticsAsReadOnlyEnumerable() - { - return this.healthStatusDiagnosticEnumerable; - } - - /// - /// Gets the last known timestamp of the uri health status. - /// - /// The current health status of the transport address. - /// The last known timestamp of the uri health status - internal DateTime? GetLastKnownTimestampByHealthStatus(HealthStatus healthStatus) - { - return healthStatus switch - { - HealthStatus.Unhealthy => this.lastUnhealthyTimestamp, - HealthStatus.UnhealthyPending => this.lastUnhealthyPendingTimestamp, - HealthStatus.Unknown => this.lastUnknownTimestamp, - HealthStatus.Connected => DateTime.UtcNow, - _ => throw new ArgumentException( - message: $"Unsupported Health Status: {healthStatus}"), - }; - } - - /// - /// Enum containing the health statuses of - /// - public enum HealthStatus - { - /// - /// Indicates a healthy status. - /// - Connected = 100, - - /// - /// Indicates an unknown status. - /// - Unknown = 200, - - /// - /// Indicates an unhealthy pending status. - /// - UnhealthyPending = 300, - - /// - /// Indicates an unhealthy status. - /// - Unhealthy = 400, - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + + /// + /// Wraps the different health statuses and their corresponding last known timestamps + /// for a transport address uri. + /// + internal sealed class TransportAddressHealthState + { + /// + /// A read-only field containing the last unknown timestamp. + /// + private readonly DateTime? lastUnknownTimestamp; + + /// + /// A read-only field containing the last unhealthy pending timestamp. + /// + private readonly DateTime? lastUnhealthyPendingTimestamp; + + /// + /// A read-only field containing the last unhealthy timestamp. + /// + private readonly DateTime? lastUnhealthyTimestamp; + + /// + /// The read-only health status Enum containing the transport address health status. + /// + private readonly HealthStatus healthStatus; + + /// + /// The read-only health status diagnostic string containing the URI and health status information. + /// + private readonly string healthStatusDiagnosticString; + + /// + /// A read-only list of health status diagnostic string. + /// + private readonly IReadOnlyList healthStatusDiagnosticEnumerable; + + /// + /// The constructor for initializing the . + /// + /// An instance off containing the physical uri. + /// An instance of containing + /// the current health status of the transport address. + /// The last unknown timestamp. + /// The last unhealthy pending timestamp. + /// The last unhealthy timestamp. + public TransportAddressHealthState( + Uri transportUri, + HealthStatus healthStatus, + DateTime? lastUnknownTimestamp, + DateTime? lastUnhealthyPendingTimestamp, + DateTime? lastUnhealthyTimestamp) + { + if (transportUri is null) + { + throw new ArgumentNullException( + paramName: nameof(transportUri), + message: $"Argument {nameof(transportUri)} can not be null"); + } + + this.healthStatus = healthStatus; + this.lastUnknownTimestamp = lastUnknownTimestamp; + this.lastUnhealthyPendingTimestamp = lastUnhealthyPendingTimestamp; + this.lastUnhealthyTimestamp = lastUnhealthyTimestamp; + this.healthStatusDiagnosticString = $"(port: {transportUri.Port} | status: {healthStatus} | lkt: {this.GetLastKnownTimestampByHealthStatus(healthStatus)})"; + + List healthStatusList = new () + { + this.healthStatusDiagnosticString, + }; + this.healthStatusDiagnosticEnumerable = healthStatusList.AsReadOnly(); + } + + /// + /// Gets the current health status of the transport address uri. + /// + /// An instance of containing + /// the current health status. + public HealthStatus GetHealthStatus() + { + return this.healthStatus; + } + + /// + /// Gets the Transport Address Uri health status diagnostic string. + /// + /// A string containing the health status diagnostics information. + public string GetHealthStatusDiagnosticString() + { + return this.healthStatusDiagnosticString; + } + + /// + /// Gets the Transport Address Uri health status diagnostics as a read-only . + /// + /// An containing the health status diagnostics information. + public IEnumerable GetHealthStatusDiagnosticsAsReadOnlyEnumerable() + { + return this.healthStatusDiagnosticEnumerable; + } + + /// + /// Gets the last known timestamp of the uri health status. + /// + /// The current health status of the transport address. + /// The last known timestamp of the uri health status + internal DateTime? GetLastKnownTimestampByHealthStatus(HealthStatus healthStatus) + { + return healthStatus switch + { + HealthStatus.Unhealthy => this.lastUnhealthyTimestamp, + HealthStatus.UnhealthyPending => this.lastUnhealthyPendingTimestamp, + HealthStatus.Unknown => this.lastUnknownTimestamp, + HealthStatus.Connected => DateTime.UtcNow, + _ => throw new ArgumentException( + message: $"Unsupported Health Status: {healthStatus}"), + }; + } + + /// + /// Enum containing the health statuses of + /// + public enum HealthStatus + { + /// + /// Indicates a healthy status. + /// + Connected = 100, + + /// + /// Indicates an unknown status. + /// + Unknown = 200, + + /// + /// Indicates an unhealthy pending status. + /// + UnhealthyPending = 300, + + /// + /// Indicates an unhealthy status. + /// + Unhealthy = 400, + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportAddressUri.cs b/Microsoft.Azure.Cosmos/src/direct/TransportAddressUri.cs index d3fe82650c..9858fbc1e8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportAddressUri.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportAddressUri.cs @@ -1,353 +1,353 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Rntbd; - - /// - /// Wraps around the 'uri' for RNTBD requests. - /// - /// - /// RNTBD calls many heavily allocating methods for Uri Path and query etc - /// for every request. This caches the result of that for any given URI and returns - /// the post-processed value. - /// This improves performance as this can be cached in the AddressSelector (which is long lived). - /// - internal sealed class TransportAddressUri : IEquatable - { - /// - /// A read-only indicating the idle time in minutes for address state transitions. - /// The default value for idle time is one minute. - /// - private static readonly TimeSpan idleTimeInMinutes = TimeSpan.FromMinutes(1); - - /// - /// A read-only string containing the physical uri. - /// - private readonly string uriToString; - - /// - /// A field containing the failed timestamp. - /// - private DateTime? lastFailedRequestUtc; - - /// - /// The health status Enum containing the transport address health status. - /// - private TransportAddressHealthState healthState; - - /// - /// The constructor for initializing the . - /// - /// An containing the physical uri of the replica. - public TransportAddressUri(Uri addressUri) - { - this.Uri = addressUri ?? throw new ArgumentNullException(paramName: nameof(addressUri)); - this.ReplicaServerKey = new (uri: addressUri); - this.uriToString = addressUri.ToString(); - this.PathAndQuery = addressUri.PathAndQuery.TrimEnd(TransportSerialization.UrlTrim); - this.healthState = new ( - transportUri: addressUri, - healthStatus: TransportAddressHealthState.HealthStatus.Unknown, - lastUnknownTimestamp: DateTime.UtcNow, - lastUnhealthyPendingTimestamp: null, - lastUnhealthyTimestamp: null); - this.lastFailedRequestUtc = null; - } - - /// - /// Gets the backend physical Uri. - /// - public Uri Uri { get; } - - /// - /// Gets the current path and query as string. - /// - public string PathAndQuery { get; } - - /// - /// An instance of containing the replica host and port details. - /// - public ServerKey ReplicaServerKey { get; } - - /// - /// Is a flag to determine if the replica the URI is pointing to is unhealthy. - /// The unhealthy status is reset after 1 minutes to prevent a replica from - /// being permenatly marked as unhealthy. - /// - public bool IsUnhealthy() - { - DateTime? dateTime = this.lastFailedRequestUtc; - if (dateTime == null || !dateTime.HasValue) - { - return false; - } - - // The 1 minutes give it a buffer for the multiple retries to succeed. - // Worst case a future request will fail from stale cache and mark it unhealthy - if (dateTime.Value + TransportAddressUri.idleTimeInMinutes > DateTime.UtcNow) - { - return true; - } - - // The Uri has been marked unhealthy for over 1 minute. - // Remove the flag. - this.lastFailedRequestUtc = null; - return false; - } - - /// - /// Sets the current health status to unhealthy and logs the unhealthy timestamp. - /// - public void SetUnhealthy() - { - TransportAddressHealthState snapshot = this.healthState; - this.SetHealthStatus( - previousState: snapshot, - status: TransportAddressHealthState.HealthStatus.Unhealthy); - this.lastFailedRequestUtc = DateTime.UtcNow; - } - - /// - /// Sets the current health status to connected. - /// - public void SetConnected() - { - TransportAddressHealthState snapshot = this.healthState; - if (snapshot.GetHealthStatus() != TransportAddressHealthState.HealthStatus.Connected) - { - this.SetHealthStatus( - previousState: snapshot, - status: TransportAddressHealthState.HealthStatus.Connected); - } - } - - /// - /// Sets the current health status to unhealthy pending and logs the timestamp. - /// - public void SetRefreshedIfUnhealthy() - { - TransportAddressHealthState snapshot = this.healthState; - if (snapshot.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy) - { - this.SetHealthStatus( - previousState: snapshot, - status: TransportAddressHealthState.HealthStatus.UnhealthyPending); - } - } - - /// - public override int GetHashCode() - { - return this.Uri.GetHashCode(); - } - - /// - public override string ToString() - { - return this.uriToString; - } - - /// - public bool Equals(TransportAddressUri other) - { - if (object.ReferenceEquals(this, other)) - { - return true; - } - - return this.Uri.Equals(other?.Uri); - } - - /// - public override bool Equals(object obj) - { - return object.ReferenceEquals(this, obj) || (obj is TransportAddressUri other && this.Equals(other)); - } - - /// - /// Resets the health status and timestamps of the transport address uri with that of the - /// provided health status and timestamps. - /// - /// The requested health status to be updated. - /// The requested last unknown timestamp to be updated. - /// The requested last unhealthy pending timestamp to be updated. - /// The requested last unhealthy timestamp to be updated. - public void ResetHealthStatus( - TransportAddressHealthState.HealthStatus status, - DateTime? lastUnknownTimestamp, - DateTime? lastUnhealthyPendingTimestamp, - DateTime? lastUnhealthyTimestamp) - { - this.CreateAndUpdateCurrentHealthState( - healthStatus: status, - lastUnknownTimestamp: lastUnknownTimestamp, - lastUnhealthyPendingTimestamp: lastUnhealthyPendingTimestamp, - lastUnhealthyTimestamp: lastUnhealthyTimestamp, - previousState: this.healthState); - } - - /// - /// Gets the current health state of the transport address uri. - /// - /// An instance of containing - /// the current health state of the uri. - public TransportAddressHealthState GetCurrentHealthState() - { - return this.healthState; - } - - /// - /// In , it could de-prioritize the TransportAddressUri in UnhealthyPending/Unhealthy health status (depending on - /// whether replica validation is enabled). If the replica is stuck in those statuses for too long (more than a minute in reality), - /// then in order to avoid replica usage skew, we are going to mark them into healthy category, so it's status can be re-validated - /// by requests again. - /// - /// An instance of indicating the effective health status. - public TransportAddressHealthState.HealthStatus GetEffectiveHealthStatus() - { - TransportAddressHealthState snapshot = this.healthState; - switch (snapshot.GetHealthStatus()) - { - case TransportAddressHealthState.HealthStatus.Connected: - case TransportAddressHealthState.HealthStatus.Unhealthy: - return snapshot.GetHealthStatus(); - - case TransportAddressHealthState.HealthStatus.Unknown: - if (DateTime.UtcNow > snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown) + TransportAddressUri.idleTimeInMinutes) - { - return TransportAddressHealthState.HealthStatus.Connected; - } - return snapshot.GetHealthStatus(); - - case TransportAddressHealthState.HealthStatus.UnhealthyPending: - if (DateTime.UtcNow > snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending) + TransportAddressUri.idleTimeInMinutes) - { - return TransportAddressHealthState.HealthStatus.Connected; - } - return snapshot.GetHealthStatus(); - - default: - throw new ArgumentException( - message: $"Unknown status :{snapshot.GetHealthStatus()}"); - } - } - - /// - /// Returns a boolean flag indicating if a health status refresh could possibly - /// be done for any replica that remains unhealthy for more than one minute. - /// - /// A boolean flag indicating if the health status could be refreshed. - public bool ShouldRefreshHealthStatus() - { - TransportAddressHealthState snapshot = this.healthState; - return snapshot.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy - && DateTime.UtcNow >= (snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy) + TransportAddressUri.idleTimeInMinutes); - } - - /// - /// Sets the transport address uri health status. - /// - /// The previous health state of the transport address. - /// The current health status of the transport address. - private void SetHealthStatus( - TransportAddressHealthState previousState, - TransportAddressHealthState.HealthStatus status) - { - switch (status) - { - case TransportAddressHealthState.HealthStatus.Unhealthy: - - this.CreateAndUpdateCurrentHealthState( - healthStatus: TransportAddressHealthState.HealthStatus.Unhealthy, - lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), - lastUnhealthyPendingTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending), - lastUnhealthyTimestamp: DateTime.UtcNow, - previousState: previousState); - break; - - case TransportAddressHealthState.HealthStatus.UnhealthyPending: - if (previousState.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy || previousState.GetHealthStatus() == TransportAddressHealthState.HealthStatus.UnhealthyPending) - { - this.CreateAndUpdateCurrentHealthState( - healthStatus: TransportAddressHealthState.HealthStatus.UnhealthyPending, - lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), - lastUnhealthyPendingTimestamp: DateTime.UtcNow, - lastUnhealthyTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy), - previousState: previousState); - } - else - { - Debug.Assert( - condition: false, - message: $"Invalid state transition. Previous status: {previousState.GetHealthStatus()}, current status: {status}"); - } - break; - - case TransportAddressHealthState.HealthStatus.Connected: - - this.CreateAndUpdateCurrentHealthState( - healthStatus: TransportAddressHealthState.HealthStatus.Connected, - lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), - lastUnhealthyPendingTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending), - lastUnhealthyTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy), - previousState: previousState); - break; - - case TransportAddressHealthState.HealthStatus.Unknown: - default: - throw new ArgumentException( - message: $"Cannot set an unsupported health status: {status}"); - } - } - - /// - /// Creates a new health state and - /// attempts to update the current state atomically with the newly created one. - /// - /// The desired health status to be updated. - /// The requested last unknown timestamp to be updated. - /// The requested last unhealthy pending timestamp to be updated. - /// The requested last unhealthy timestamp to be updated. - /// The previous health state of the transport address uri. - private void CreateAndUpdateCurrentHealthState( - TransportAddressHealthState.HealthStatus healthStatus, - DateTime? lastUnknownTimestamp, - DateTime? lastUnhealthyPendingTimestamp, - DateTime? lastUnhealthyTimestamp, - TransportAddressHealthState previousState) - { - TransportAddressHealthState snapshot = previousState; - TransportAddressHealthState nextState = new ( - transportUri: this.Uri, - healthStatus: healthStatus, - lastUnknownTimestamp: lastUnknownTimestamp, - lastUnhealthyPendingTimestamp: lastUnhealthyPendingTimestamp, - lastUnhealthyTimestamp: lastUnhealthyTimestamp); - - while (true) - { - TransportAddressHealthState currentState = Interlocked.CompareExchange( - location1: ref this.healthState, - value: nextState, - comparand: snapshot); - - if (currentState == snapshot || currentState == nextState) - { - break; - } - - snapshot = currentState; - DefaultTrace.TraceVerbose( - "Re-attempting to update the current health state. Previous health status: {0}, current health status: {1}", - previousState.GetHealthStatus(), - currentState.GetHealthStatus()); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Rntbd; + + /// + /// Wraps around the 'uri' for RNTBD requests. + /// + /// + /// RNTBD calls many heavily allocating methods for Uri Path and query etc + /// for every request. This caches the result of that for any given URI and returns + /// the post-processed value. + /// This improves performance as this can be cached in the AddressSelector (which is long lived). + /// + internal sealed class TransportAddressUri : IEquatable + { + /// + /// A read-only indicating the idle time in minutes for address state transitions. + /// The default value for idle time is one minute. + /// + private static readonly TimeSpan idleTimeInMinutes = TimeSpan.FromMinutes(1); + + /// + /// A read-only string containing the physical uri. + /// + private readonly string uriToString; + + /// + /// A field containing the failed timestamp. + /// + private DateTime? lastFailedRequestUtc; + + /// + /// The health status Enum containing the transport address health status. + /// + private TransportAddressHealthState healthState; + + /// + /// The constructor for initializing the . + /// + /// An containing the physical uri of the replica. + public TransportAddressUri(Uri addressUri) + { + this.Uri = addressUri ?? throw new ArgumentNullException(paramName: nameof(addressUri)); + this.ReplicaServerKey = new (uri: addressUri); + this.uriToString = addressUri.ToString(); + this.PathAndQuery = addressUri.PathAndQuery.TrimEnd(TransportSerialization.UrlTrim); + this.healthState = new ( + transportUri: addressUri, + healthStatus: TransportAddressHealthState.HealthStatus.Unknown, + lastUnknownTimestamp: DateTime.UtcNow, + lastUnhealthyPendingTimestamp: null, + lastUnhealthyTimestamp: null); + this.lastFailedRequestUtc = null; + } + + /// + /// Gets the backend physical Uri. + /// + public Uri Uri { get; } + + /// + /// Gets the current path and query as string. + /// + public string PathAndQuery { get; } + + /// + /// An instance of containing the replica host and port details. + /// + public ServerKey ReplicaServerKey { get; } + + /// + /// Is a flag to determine if the replica the URI is pointing to is unhealthy. + /// The unhealthy status is reset after 1 minutes to prevent a replica from + /// being permenatly marked as unhealthy. + /// + public bool IsUnhealthy() + { + DateTime? dateTime = this.lastFailedRequestUtc; + if (dateTime == null || !dateTime.HasValue) + { + return false; + } + + // The 1 minutes give it a buffer for the multiple retries to succeed. + // Worst case a future request will fail from stale cache and mark it unhealthy + if (dateTime.Value + TransportAddressUri.idleTimeInMinutes > DateTime.UtcNow) + { + return true; + } + + // The Uri has been marked unhealthy for over 1 minute. + // Remove the flag. + this.lastFailedRequestUtc = null; + return false; + } + + /// + /// Sets the current health status to unhealthy and logs the unhealthy timestamp. + /// + public void SetUnhealthy() + { + TransportAddressHealthState snapshot = this.healthState; + this.SetHealthStatus( + previousState: snapshot, + status: TransportAddressHealthState.HealthStatus.Unhealthy); + this.lastFailedRequestUtc = DateTime.UtcNow; + } + + /// + /// Sets the current health status to connected. + /// + public void SetConnected() + { + TransportAddressHealthState snapshot = this.healthState; + if (snapshot.GetHealthStatus() != TransportAddressHealthState.HealthStatus.Connected) + { + this.SetHealthStatus( + previousState: snapshot, + status: TransportAddressHealthState.HealthStatus.Connected); + } + } + + /// + /// Sets the current health status to unhealthy pending and logs the timestamp. + /// + public void SetRefreshedIfUnhealthy() + { + TransportAddressHealthState snapshot = this.healthState; + if (snapshot.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy) + { + this.SetHealthStatus( + previousState: snapshot, + status: TransportAddressHealthState.HealthStatus.UnhealthyPending); + } + } + + /// + public override int GetHashCode() + { + return this.Uri.GetHashCode(); + } + + /// + public override string ToString() + { + return this.uriToString; + } + + /// + public bool Equals(TransportAddressUri other) + { + if (object.ReferenceEquals(this, other)) + { + return true; + } + + return this.Uri.Equals(other?.Uri); + } + + /// + public override bool Equals(object obj) + { + return object.ReferenceEquals(this, obj) || (obj is TransportAddressUri other && this.Equals(other)); + } + + /// + /// Resets the health status and timestamps of the transport address uri with that of the + /// provided health status and timestamps. + /// + /// The requested health status to be updated. + /// The requested last unknown timestamp to be updated. + /// The requested last unhealthy pending timestamp to be updated. + /// The requested last unhealthy timestamp to be updated. + public void ResetHealthStatus( + TransportAddressHealthState.HealthStatus status, + DateTime? lastUnknownTimestamp, + DateTime? lastUnhealthyPendingTimestamp, + DateTime? lastUnhealthyTimestamp) + { + this.CreateAndUpdateCurrentHealthState( + healthStatus: status, + lastUnknownTimestamp: lastUnknownTimestamp, + lastUnhealthyPendingTimestamp: lastUnhealthyPendingTimestamp, + lastUnhealthyTimestamp: lastUnhealthyTimestamp, + previousState: this.healthState); + } + + /// + /// Gets the current health state of the transport address uri. + /// + /// An instance of containing + /// the current health state of the uri. + public TransportAddressHealthState GetCurrentHealthState() + { + return this.healthState; + } + + /// + /// In , it could de-prioritize the TransportAddressUri in UnhealthyPending/Unhealthy health status (depending on + /// whether replica validation is enabled). If the replica is stuck in those statuses for too long (more than a minute in reality), + /// then in order to avoid replica usage skew, we are going to mark them into healthy category, so it's status can be re-validated + /// by requests again. + /// + /// An instance of indicating the effective health status. + public TransportAddressHealthState.HealthStatus GetEffectiveHealthStatus() + { + TransportAddressHealthState snapshot = this.healthState; + switch (snapshot.GetHealthStatus()) + { + case TransportAddressHealthState.HealthStatus.Connected: + case TransportAddressHealthState.HealthStatus.Unhealthy: + return snapshot.GetHealthStatus(); + + case TransportAddressHealthState.HealthStatus.Unknown: + if (DateTime.UtcNow > snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown) + TransportAddressUri.idleTimeInMinutes) + { + return TransportAddressHealthState.HealthStatus.Connected; + } + return snapshot.GetHealthStatus(); + + case TransportAddressHealthState.HealthStatus.UnhealthyPending: + if (DateTime.UtcNow > snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending) + TransportAddressUri.idleTimeInMinutes) + { + return TransportAddressHealthState.HealthStatus.Connected; + } + return snapshot.GetHealthStatus(); + + default: + throw new ArgumentException( + message: $"Unknown status :{snapshot.GetHealthStatus()}"); + } + } + + /// + /// Returns a boolean flag indicating if a health status refresh could possibly + /// be done for any replica that remains unhealthy for more than one minute. + /// + /// A boolean flag indicating if the health status could be refreshed. + public bool ShouldRefreshHealthStatus() + { + TransportAddressHealthState snapshot = this.healthState; + return snapshot.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy + && DateTime.UtcNow >= (snapshot.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy) + TransportAddressUri.idleTimeInMinutes); + } + + /// + /// Sets the transport address uri health status. + /// + /// The previous health state of the transport address. + /// The current health status of the transport address. + private void SetHealthStatus( + TransportAddressHealthState previousState, + TransportAddressHealthState.HealthStatus status) + { + switch (status) + { + case TransportAddressHealthState.HealthStatus.Unhealthy: + + this.CreateAndUpdateCurrentHealthState( + healthStatus: TransportAddressHealthState.HealthStatus.Unhealthy, + lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), + lastUnhealthyPendingTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending), + lastUnhealthyTimestamp: DateTime.UtcNow, + previousState: previousState); + break; + + case TransportAddressHealthState.HealthStatus.UnhealthyPending: + if (previousState.GetHealthStatus() == TransportAddressHealthState.HealthStatus.Unhealthy || previousState.GetHealthStatus() == TransportAddressHealthState.HealthStatus.UnhealthyPending) + { + this.CreateAndUpdateCurrentHealthState( + healthStatus: TransportAddressHealthState.HealthStatus.UnhealthyPending, + lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), + lastUnhealthyPendingTimestamp: DateTime.UtcNow, + lastUnhealthyTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy), + previousState: previousState); + } + else + { + Debug.Assert( + condition: false, + message: $"Invalid state transition. Previous status: {previousState.GetHealthStatus()}, current status: {status}"); + } + break; + + case TransportAddressHealthState.HealthStatus.Connected: + + this.CreateAndUpdateCurrentHealthState( + healthStatus: TransportAddressHealthState.HealthStatus.Connected, + lastUnknownTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unknown), + lastUnhealthyPendingTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.UnhealthyPending), + lastUnhealthyTimestamp: previousState.GetLastKnownTimestampByHealthStatus(TransportAddressHealthState.HealthStatus.Unhealthy), + previousState: previousState); + break; + + case TransportAddressHealthState.HealthStatus.Unknown: + default: + throw new ArgumentException( + message: $"Cannot set an unsupported health status: {status}"); + } + } + + /// + /// Creates a new health state and + /// attempts to update the current state atomically with the newly created one. + /// + /// The desired health status to be updated. + /// The requested last unknown timestamp to be updated. + /// The requested last unhealthy pending timestamp to be updated. + /// The requested last unhealthy timestamp to be updated. + /// The previous health state of the transport address uri. + private void CreateAndUpdateCurrentHealthState( + TransportAddressHealthState.HealthStatus healthStatus, + DateTime? lastUnknownTimestamp, + DateTime? lastUnhealthyPendingTimestamp, + DateTime? lastUnhealthyTimestamp, + TransportAddressHealthState previousState) + { + TransportAddressHealthState snapshot = previousState; + TransportAddressHealthState nextState = new ( + transportUri: this.Uri, + healthStatus: healthStatus, + lastUnknownTimestamp: lastUnknownTimestamp, + lastUnhealthyPendingTimestamp: lastUnhealthyPendingTimestamp, + lastUnhealthyTimestamp: lastUnhealthyTimestamp); + + while (true) + { + TransportAddressHealthState currentState = Interlocked.CompareExchange( + location1: ref this.healthState, + value: nextState, + comparand: snapshot); + + if (currentState == snapshot || currentState == nextState) + { + break; + } + + snapshot = currentState; + DefaultTrace.TraceVerbose( + "Re-attempting to update the current health state. Previous health status: {0}, current health status: {1}", + previousState.GetHealthStatus(), + currentState.GetHealthStatus()); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportClient.cs b/Microsoft.Azure.Cosmos/src/direct/TransportClient.cs index 12d6d7905e..222305a252 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportClient.cs @@ -1,1241 +1,1241 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using System.IO; - using System.Net.Http; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - using Microsoft.Azure.Documents.Routing; - - internal abstract class TransportClient : IDisposable - { - protected TransportClient() - { - - } - - public virtual void Dispose() - { - } - - // Uses requests's ResourceOperation to determine the operation - public virtual Task InvokeResourceOperationAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress, new ResourceOperation(request.OperationType, request.ResourceType), request); - } - - // Uses requests's ResourceOperation to determine the operation - public virtual Task InvokeResourceOperationAsync(TransportAddressUri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress, new ResourceOperation(request.OperationType, request.ResourceType), request); - } - - #region Offer Operations - - public Task CreateOfferAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateOffer, - request); - } - - public Task GetOfferAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadOffer, - request); - } - - public Task ListOffersAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadOfferFeed, - request); - } - - public Task DeleteOfferAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteOffer, - request); - } - - public Task ReplaceOfferAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceOffer, - request); - } - - public Task QueryOfferAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Offer, - request); - } - - #endregion - -#if !COSMOSCLIENT - #region CrossPartitionReplicaSetInformation Operations - public Task GetPartitionSetAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadPartitionSetInformation, - request); - } - - public Task GetRestoreMetadataFeedAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadRestoreMetadataFeed, - request); - } - #endregion - -#region Replica Operations - public Task GetReplicaAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadReplica, - request); - } -#endregion -#endif - -#region Database Operations - public Task ListDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress, ResourceOperation.ReadDatabaseFeed, request); - } - public Task HeadDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress, ResourceOperation.HeadDatabaseFeed, request); - } - public Task GetDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadDatabase, - request); - } - public Task CreateDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateDatabase, - request); - } - public Task UpsertDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertDatabase, - request); - } - public Task PatchDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.PatchDatabase, - request); - } - public Task ReplaceDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceDatabase, - request); - } - public Task DeleteDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteDatabase, - request); - } - public Task QueryDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Database, - request); - } -#endregion - -#region DocumentCollection Operations - public Task ListDocumentCollectionsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadCollectionFeed, - request); - } - - public Task GetDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadCollection, - request); - } - public Task HeadDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.HeadCollection, - request); - } - public Task CreateDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateCollection, - request); - } - public Task PatchDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.PatchCollection, - request); - } - public Task ReplaceDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceCollection, - request); - } - public Task DeleteDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteCollection, - request); - } - public Task QueryDocumentCollectionsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Collection, - request); - } - #endregion - - #region EncryptionKey Operations - - public Task CreateClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateClientEncryptionKey, - request); - } - - public Task ReadClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadClientEncryptionKey, - request); - } - - public Task DeleteClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteClientEncryptionKey, - request); - } - - public Task ReadClientEncryptionKeyFeedAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadClientEncryptionKeyFeed, - request); - } - - public Task ReplaceClientEncryptionKeyFeedAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceClientEncryptionKey, - request); - } - - #endregion - - #region Sproc Operations - public Task ListStoredProceduresAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadStoredProcedureFeed, - request); - } - - public Task GetStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadStoredProcedure, - request); - } - - public Task CreateStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateStoredProcedure, - request); - } - - public Task UpsertStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertStoredProcedure, - request); - } - - public Task ReplaceStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceStoredProcedure, - request); - } - public Task DeleteStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteStoredProcedure, - request); - } - public Task QueryStoredProceduresAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.StoredProcedure, - request); - } -#endregion - -#region Trigger Operations - public Task ListTriggersAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReadTriggerFeed, - request); - } - - public Task GetTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReadTrigger, - request); - } - - public Task CreateTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXCreateTrigger, - request); - } - - public Task UpsertTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXUpsertTrigger, - request); - } - - public Task ReplaceTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReplaceTrigger, - request); - } - public Task DeleteTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXDeleteTrigger, - request); - } - public Task QueryTriggersAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Trigger, - request); - } -#endregion - -#region UDF Operations - public Task ListUserDefinedFunctionsAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReadUserDefinedFunctionFeed, - request); - } - - public Task GetUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReadUserDefinedFunction, - request); - } - - public Task CreateUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXCreateUserDefinedFunction, - request); - } - - public Task UpsertUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXUpsertUserDefinedFunction, - request); - } - - public Task ReplaceUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXReplaceUserDefinedFunction, - request); - } - public Task DeleteUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XXDeleteUserDefinedFunction, - request); - } - public Task QueryUserDefinedFunctionsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.UserDefinedFunction, - request); - } -#endregion - -#region SystemDocumentOperations Operations - internal Task ListSystemDocumentsAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadSystemDocumentFeed, - request); - } - - internal Task GetSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadSystemDocument, - request); - } - - internal Task CreateSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateSystemDocument, - request); - } - - internal Task ReplaceSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceSystemDocument, - request); - } - - internal Task DeleteSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteSystemDocument, - request); - } -#endregion - -#region Conflict Operations - public Task ListConflictsAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XReadConflictFeed, - request); - } - - public Task GetConflictAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XReadConflict, - request); - } - - public Task DeleteConflictAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XDeleteConflict, - request); - } - public Task QueryConflictsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Conflict, - request); - } -#endregion - -#region Document Operations - public Task ListDocumentsAsync(Uri physicalAddress, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadDocumentFeed, - request); - } - - public Task GetDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadDocument, - request); - } - - public Task CreateDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateDocument, - request); - } - - public Task UpsertDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertDocument, - request); - } - - public Task PatchDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.PatchDocument, - request); - } - public Task ReplaceDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceDocument, - request); - } - public Task DeleteDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteDocument, - request); - } - public Task QueryDocumentsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Document, - request); - } -#endregion - -#region Attachment Operations - public Task ListAttachmentsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadAttachmentFeed, - request); - } - - public Task GetAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadAttachment, - request); - } - - public Task CreateAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateAttachment, - request); - } - - public Task UpsertAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertAttachment, - request); - } - - public Task ReplaceAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceAttachment, - request); - } - - public Task DeleteAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteAttachment, - request); - } - - public Task QueryAttachmentsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Attachment, - request); - } -#endregion - -#region User Operations - - public Task ListUsersAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress, - ResourceOperation.ReadUserFeed, - request); - } - public Task GetUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadUser, - request); - } - public Task CreateUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreateUser, - request); - } - - public Task UpsertUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertUser, - request); - } - public Task PatchUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.PatchUser, - request); - } - public Task ReplaceUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplaceUser, - request); - } - public Task DeleteUserAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeleteUser, - request); - } - - public Task QueryUsersAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.User, - request); - } - -#endregion - -#region Permission Operations - - public Task ListPermissionsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadPermissionFeed, - request); - } - public Task GetPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReadPermission, - request); - } - public Task CreatePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CreatePermission, - request); - } - public Task UpsertPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.UpsertPermission, - request); - } - public Task PatchPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.PatchPermission, - request); - } - public Task ReplacePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ReplacePermission, - request); - } - public Task DeletePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.DeletePermission, - request); - } - - public Task QueryPermissionsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeQueryStoreAsync( - physicalAddress, - ResourceType.Permission, - request); - } -#endregion - -#region Row Operations - public Task ListRecordsAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XReadRecordFeed, - request); - } - - public Task CreateRecordAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XCreateRecord, - request); - } - - public Task ReadRecordAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XReadRecord, - request); - } - - public Task PatchRecordAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XUpdateRecord, - request); - } - - public Task DeleteRecordAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.XDeleteRecord, - request); - } -#endregion - -#region Execute Operations - - public Task ExecuteAsync(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.ExecuteDocumentFeed, - request); - } - -#endregion - -#region Transaction Operations - - public Task CompleteUserTransaction(Uri physicalAddress, DocumentServiceRequest request) - { - return this.InvokeStoreAsync( - physicalAddress, - ResourceOperation.CompleteUserTransaction, - request); - } -#endregion - - public static void ThrowServerException(string resourceAddress, StoreResponse storeResponse, Uri physicalAddress, Guid activityId, DocumentServiceRequest request = null) - { - INameValueCollection responseHeaders; - string errorMessage = null; - - // If the status code is < 300 or 304 NotModified (we treat not modified as success) then it means that it's a success code and shouldn't throw. - // NotFound, PreconditionFailed and Conflict should not throw either if useStatusCodeForFailures is set - if (storeResponse.Status < 300 - || (StatusCodes)storeResponse.Status == StatusCodes.NotModified - || (request != null && request.IsValidStatusCodeForExceptionlessRetry(storeResponse.Status, storeResponse.SubStatusCode)) - ) - { - return; - } - - DocumentClientException exception; - - switch ((StatusCodes)storeResponse.Status) - { - case StatusCodes.Unauthorized: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Unauthorized, out responseHeaders); - exception = new UnauthorizedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.Forbidden: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Forbidden, out responseHeaders); - exception = new ForbiddenException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.NotFound: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.NotFound, out responseHeaders); - exception = new NotFoundException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.BadRequest: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.BadRequest, out responseHeaders); - exception = new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.MethodNotAllowed: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.MethodNotAllowed, out responseHeaders); - exception = new MethodNotAllowedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.Gone: - { -#if NETFX - if (PerfCounters.Counters.RoutingFailures != null) - { - PerfCounters.Counters.RoutingFailures.Increment(); - } -#endif - - TransportClient.LogGoneException(physicalAddress, activityId.ToString()); - errorMessage = TransportClient.GetErrorResponse(storeResponse, - RMResources.Gone, - out responseHeaders); - - uint nSubStatus = TransportClient.GetExceptionSubStatus(responseHeaders, errorMessage, physicalAddress); - - if ((SubStatusCodes)nSubStatus == SubStatusCodes.NameCacheIsStale) - { - exception = new InvalidPartitionException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.PartitionKeyRangeGone) - { - exception = new PartitionKeyRangeGoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingSplit) - { - exception = new PartitionKeyRangeIsSplittingException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - } - else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingPartitionMigration) - { - exception = new PartitionIsMigratingException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - } - else - { - // Have the request URL in the exception message for debugging purposes. - // Activity ID should already be there in the response headers. - exception = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - responseHeaders, - (nSubStatus == 0) ? SubStatusCodes.ServerGenerated410 : null, // if substatus is not zero we pass null because the headers will have the correct value - physicalAddress); - break; - } - } - - case StatusCodes.Conflict: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.EntityAlreadyExists, out responseHeaders); - exception = new ConflictException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.PreconditionFailed: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.PreconditionFailed, out responseHeaders); - exception = new PreconditionFailedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.RequestEntityTooLarge: - errorMessage = TransportClient.GetErrorResponse(storeResponse, string.Format(CultureInfo.CurrentUICulture, - RMResources.RequestEntityTooLarge, - HttpConstants.HttpHeaders.PageSize), - out responseHeaders); - exception = new RequestEntityTooLargeException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.Locked: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Locked, out responseHeaders); - exception = new LockedException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.TooManyRequests: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.TooManyRequests, out responseHeaders); - exception = new RequestRateTooLargeException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.ServiceUnavailable: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.ServiceUnavailable, out responseHeaders); - uint substatus = TransportClient.GetExceptionSubStatus(responseHeaders, errorMessage, physicalAddress); - if (!string.IsNullOrEmpty(errorMessage)) - { - exception = new ServiceUnavailableException( - message: string.Format(CultureInfo.CurrentUICulture, RMResources.ExceptionMessage, errorMessage), - headers: responseHeaders, - subStatusCode: (substatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value - requestUri: physicalAddress); - } - else - { - exception = ServiceUnavailableException.Create( - headers: responseHeaders, - subStatusCode: (substatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value - requestUri: physicalAddress); - } - break; - - case StatusCodes.RequestTimeout: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.RequestTimeout, out responseHeaders); - exception = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.RetryWith: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.RetryWith, out responseHeaders); - exception = new RetryWithException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - case StatusCodes.InternalServerError: - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.InternalServerError, out responseHeaders); - exception = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - break; - - default: - { - DefaultTrace.TraceCritical("Unrecognized status code {0} returned by backend. ActivityId {1}", storeResponse.Status, activityId); - TransportClient.LogException(null, physicalAddress, resourceAddress, activityId); - errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.InvalidBackendResponse, out responseHeaders); - exception = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - errorMessage), - responseHeaders, - physicalAddress); - } - break; - } - - exception.LSN = storeResponse.LSN; - exception.PartitionKeyRangeId = storeResponse.PartitionKeyRangeId; - exception.ResourceAddress = resourceAddress; - exception.TransportRequestStats = storeResponse.TransportRequestStats; - throw exception; - } - - protected Task InvokeQueryStoreAsync( - Uri physicalAddress, - ResourceType resourceType, - DocumentServiceRequest request) - { - string contentType = request.Headers[HttpConstants.HttpHeaders.ContentType]; - - OperationType operationType; - if (string.Equals(contentType, RuntimeConstants.MediaTypes.SQL, StringComparison.Ordinal)) - { - operationType = OperationType.SqlQuery; - } - else - { - operationType = OperationType.Query; - } - - return InvokeStoreAsync( - physicalAddress, - ResourceOperation.Query(operationType, resourceType), - request); - } - - internal virtual Task InvokeStoreAsync( - TransportAddressUri physicalAddress, - ResourceOperation resourceOperation, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync(physicalAddress.Uri, resourceOperation, request); - } - - internal abstract Task InvokeStoreAsync( - Uri physicalAddress, - ResourceOperation resourceOperation, - DocumentServiceRequest request); - - /// - /// Uses the rntbd context negotiation and opens the connection to the backend replica nodes. - /// - /// An instance of containing the - /// uri of the backend server's physical address. - internal virtual Task OpenConnectionAsync( - Uri physicalAddress) - { - throw new NotImplementedException(); - } - - protected async static Task GetErrorResponseAsync(HttpResponseMessage responseMessage) - { - if (responseMessage.Content != null) - { - Stream responseStream = await responseMessage.Content.ReadAsStreamAsync(); - return TransportClient.GetErrorFromStream(responseStream); - } - else - { - return ""; - } - } - - protected static string GetErrorResponse(StoreResponse storeResponse, string defaultMessage, out INameValueCollection responseHeaders) - { - string result = null; - responseHeaders = storeResponse.Headers; - - if (storeResponse.ResponseBody != null) - { - result = TransportClient.GetErrorFromStream(storeResponse.ResponseBody); - } - - return string.IsNullOrEmpty(result) ? defaultMessage : result; - } - - protected static string GetErrorFromStream(Stream responseStream) - { - using (responseStream) - { - return new StreamReader(responseStream).ReadToEnd(); - } - } - - protected static void LogException(Uri physicalAddress, string activityId) - { - DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, "Store Request Failed. Store Physical Address {0} ActivityId {1}", - physicalAddress, activityId)); - } - - protected static void LogException(Exception exception, Uri physicalAddress, string rid, Guid activityId) - { - if (exception != null) - { - DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, - "Store Request Failed. Exception {0} Store Physical Address {1} RID {2} ActivityId {3}", - exception.Message, physicalAddress, rid, activityId.ToString())); - } - else - { - DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, - "Store Request Failed. Store Physical Address {0} RID {1} ActivityId {2}", - physicalAddress, rid, activityId.ToString())); - } - } - - protected static void LogGoneException(Uri physicalAddress, string activityId) - { - DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, "Listener not found. Store Physical Address {0} ActivityId {1}", - physicalAddress, activityId)); - } - - protected static uint GetExceptionSubStatus(INameValueCollection responseHeaders, string errorMessage, Uri physicalAddress) - { - uint nSubStatus = 0; - if (responseHeaders == null) - { - return 0; - } - - string valueSubStatus = responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); - if (!string.IsNullOrEmpty(valueSubStatus)) - { - if (!uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) - { - throw new BadRequestException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - string.IsNullOrEmpty(errorMessage) ? RMResources.BadRequest : errorMessage), - responseHeaders, - physicalAddress); - } - } - - return nSubStatus; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using System.IO; + using System.Net.Http; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + using Microsoft.Azure.Documents.Routing; + + internal abstract class TransportClient : IDisposable + { + protected TransportClient() + { + + } + + public virtual void Dispose() + { + } + + // Uses requests's ResourceOperation to determine the operation + public virtual Task InvokeResourceOperationAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress, new ResourceOperation(request.OperationType, request.ResourceType), request); + } + + // Uses requests's ResourceOperation to determine the operation + public virtual Task InvokeResourceOperationAsync(TransportAddressUri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress, new ResourceOperation(request.OperationType, request.ResourceType), request); + } + + #region Offer Operations + + public Task CreateOfferAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateOffer, + request); + } + + public Task GetOfferAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadOffer, + request); + } + + public Task ListOffersAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadOfferFeed, + request); + } + + public Task DeleteOfferAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteOffer, + request); + } + + public Task ReplaceOfferAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceOffer, + request); + } + + public Task QueryOfferAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Offer, + request); + } + + #endregion + +#if !COSMOSCLIENT + #region CrossPartitionReplicaSetInformation Operations + public Task GetPartitionSetAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadPartitionSetInformation, + request); + } + + public Task GetRestoreMetadataFeedAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadRestoreMetadataFeed, + request); + } + #endregion + +#region Replica Operations + public Task GetReplicaAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadReplica, + request); + } +#endregion +#endif + +#region Database Operations + public Task ListDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress, ResourceOperation.ReadDatabaseFeed, request); + } + public Task HeadDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress, ResourceOperation.HeadDatabaseFeed, request); + } + public Task GetDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadDatabase, + request); + } + public Task CreateDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateDatabase, + request); + } + public Task UpsertDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertDatabase, + request); + } + public Task PatchDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.PatchDatabase, + request); + } + public Task ReplaceDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceDatabase, + request); + } + public Task DeleteDatabaseAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteDatabase, + request); + } + public Task QueryDatabasesAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Database, + request); + } +#endregion + +#region DocumentCollection Operations + public Task ListDocumentCollectionsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadCollectionFeed, + request); + } + + public Task GetDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadCollection, + request); + } + public Task HeadDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.HeadCollection, + request); + } + public Task CreateDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateCollection, + request); + } + public Task PatchDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.PatchCollection, + request); + } + public Task ReplaceDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceCollection, + request); + } + public Task DeleteDocumentCollectionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteCollection, + request); + } + public Task QueryDocumentCollectionsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Collection, + request); + } + #endregion + + #region EncryptionKey Operations + + public Task CreateClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateClientEncryptionKey, + request); + } + + public Task ReadClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadClientEncryptionKey, + request); + } + + public Task DeleteClientEncryptionKeyAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteClientEncryptionKey, + request); + } + + public Task ReadClientEncryptionKeyFeedAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadClientEncryptionKeyFeed, + request); + } + + public Task ReplaceClientEncryptionKeyFeedAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceClientEncryptionKey, + request); + } + + #endregion + + #region Sproc Operations + public Task ListStoredProceduresAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadStoredProcedureFeed, + request); + } + + public Task GetStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadStoredProcedure, + request); + } + + public Task CreateStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateStoredProcedure, + request); + } + + public Task UpsertStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertStoredProcedure, + request); + } + + public Task ReplaceStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceStoredProcedure, + request); + } + public Task DeleteStoredProcedureAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteStoredProcedure, + request); + } + public Task QueryStoredProceduresAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.StoredProcedure, + request); + } +#endregion + +#region Trigger Operations + public Task ListTriggersAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReadTriggerFeed, + request); + } + + public Task GetTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReadTrigger, + request); + } + + public Task CreateTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXCreateTrigger, + request); + } + + public Task UpsertTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXUpsertTrigger, + request); + } + + public Task ReplaceTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReplaceTrigger, + request); + } + public Task DeleteTriggerAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXDeleteTrigger, + request); + } + public Task QueryTriggersAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Trigger, + request); + } +#endregion + +#region UDF Operations + public Task ListUserDefinedFunctionsAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReadUserDefinedFunctionFeed, + request); + } + + public Task GetUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReadUserDefinedFunction, + request); + } + + public Task CreateUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXCreateUserDefinedFunction, + request); + } + + public Task UpsertUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXUpsertUserDefinedFunction, + request); + } + + public Task ReplaceUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXReplaceUserDefinedFunction, + request); + } + public Task DeleteUserDefinedFunctionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XXDeleteUserDefinedFunction, + request); + } + public Task QueryUserDefinedFunctionsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.UserDefinedFunction, + request); + } +#endregion + +#region SystemDocumentOperations Operations + internal Task ListSystemDocumentsAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadSystemDocumentFeed, + request); + } + + internal Task GetSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadSystemDocument, + request); + } + + internal Task CreateSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateSystemDocument, + request); + } + + internal Task ReplaceSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceSystemDocument, + request); + } + + internal Task DeleteSystemDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteSystemDocument, + request); + } +#endregion + +#region Conflict Operations + public Task ListConflictsAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XReadConflictFeed, + request); + } + + public Task GetConflictAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XReadConflict, + request); + } + + public Task DeleteConflictAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XDeleteConflict, + request); + } + public Task QueryConflictsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Conflict, + request); + } +#endregion + +#region Document Operations + public Task ListDocumentsAsync(Uri physicalAddress, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadDocumentFeed, + request); + } + + public Task GetDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadDocument, + request); + } + + public Task CreateDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateDocument, + request); + } + + public Task UpsertDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertDocument, + request); + } + + public Task PatchDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.PatchDocument, + request); + } + public Task ReplaceDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceDocument, + request); + } + public Task DeleteDocumentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteDocument, + request); + } + public Task QueryDocumentsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Document, + request); + } +#endregion + +#region Attachment Operations + public Task ListAttachmentsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadAttachmentFeed, + request); + } + + public Task GetAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadAttachment, + request); + } + + public Task CreateAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateAttachment, + request); + } + + public Task UpsertAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertAttachment, + request); + } + + public Task ReplaceAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceAttachment, + request); + } + + public Task DeleteAttachmentAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteAttachment, + request); + } + + public Task QueryAttachmentsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Attachment, + request); + } +#endregion + +#region User Operations + + public Task ListUsersAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress, + ResourceOperation.ReadUserFeed, + request); + } + public Task GetUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadUser, + request); + } + public Task CreateUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreateUser, + request); + } + + public Task UpsertUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertUser, + request); + } + public Task PatchUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.PatchUser, + request); + } + public Task ReplaceUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplaceUser, + request); + } + public Task DeleteUserAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeleteUser, + request); + } + + public Task QueryUsersAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.User, + request); + } + +#endregion + +#region Permission Operations + + public Task ListPermissionsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadPermissionFeed, + request); + } + public Task GetPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReadPermission, + request); + } + public Task CreatePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CreatePermission, + request); + } + public Task UpsertPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.UpsertPermission, + request); + } + public Task PatchPermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.PatchPermission, + request); + } + public Task ReplacePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ReplacePermission, + request); + } + public Task DeletePermissionAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.DeletePermission, + request); + } + + public Task QueryPermissionsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeQueryStoreAsync( + physicalAddress, + ResourceType.Permission, + request); + } +#endregion + +#region Row Operations + public Task ListRecordsAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XReadRecordFeed, + request); + } + + public Task CreateRecordAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XCreateRecord, + request); + } + + public Task ReadRecordAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XReadRecord, + request); + } + + public Task PatchRecordAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XUpdateRecord, + request); + } + + public Task DeleteRecordAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.XDeleteRecord, + request); + } +#endregion + +#region Execute Operations + + public Task ExecuteAsync(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.ExecuteDocumentFeed, + request); + } + +#endregion + +#region Transaction Operations + + public Task CompleteUserTransaction(Uri physicalAddress, DocumentServiceRequest request) + { + return this.InvokeStoreAsync( + physicalAddress, + ResourceOperation.CompleteUserTransaction, + request); + } +#endregion + + public static void ThrowServerException(string resourceAddress, StoreResponse storeResponse, Uri physicalAddress, Guid activityId, DocumentServiceRequest request = null) + { + INameValueCollection responseHeaders; + string errorMessage = null; + + // If the status code is < 300 or 304 NotModified (we treat not modified as success) then it means that it's a success code and shouldn't throw. + // NotFound, PreconditionFailed and Conflict should not throw either if useStatusCodeForFailures is set + if (storeResponse.Status < 300 + || (StatusCodes)storeResponse.Status == StatusCodes.NotModified + || (request != null && request.IsValidStatusCodeForExceptionlessRetry(storeResponse.Status, storeResponse.SubStatusCode)) + ) + { + return; + } + + DocumentClientException exception; + + switch ((StatusCodes)storeResponse.Status) + { + case StatusCodes.Unauthorized: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Unauthorized, out responseHeaders); + exception = new UnauthorizedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.Forbidden: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Forbidden, out responseHeaders); + exception = new ForbiddenException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.NotFound: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.NotFound, out responseHeaders); + exception = new NotFoundException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.BadRequest: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.BadRequest, out responseHeaders); + exception = new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.MethodNotAllowed: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.MethodNotAllowed, out responseHeaders); + exception = new MethodNotAllowedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.Gone: + { +#if NETFX + if (PerfCounters.Counters.RoutingFailures != null) + { + PerfCounters.Counters.RoutingFailures.Increment(); + } +#endif + + TransportClient.LogGoneException(physicalAddress, activityId.ToString()); + errorMessage = TransportClient.GetErrorResponse(storeResponse, + RMResources.Gone, + out responseHeaders); + + uint nSubStatus = TransportClient.GetExceptionSubStatus(responseHeaders, errorMessage, physicalAddress); + + if ((SubStatusCodes)nSubStatus == SubStatusCodes.NameCacheIsStale) + { + exception = new InvalidPartitionException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.PartitionKeyRangeGone) + { + exception = new PartitionKeyRangeGoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingSplit) + { + exception = new PartitionKeyRangeIsSplittingException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + } + else if ((SubStatusCodes)nSubStatus == SubStatusCodes.CompletingPartitionMigration) + { + exception = new PartitionIsMigratingException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + } + else + { + // Have the request URL in the exception message for debugging purposes. + // Activity ID should already be there in the response headers. + exception = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + responseHeaders, + (nSubStatus == 0) ? SubStatusCodes.ServerGenerated410 : null, // if substatus is not zero we pass null because the headers will have the correct value + physicalAddress); + break; + } + } + + case StatusCodes.Conflict: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.EntityAlreadyExists, out responseHeaders); + exception = new ConflictException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.PreconditionFailed: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.PreconditionFailed, out responseHeaders); + exception = new PreconditionFailedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.RequestEntityTooLarge: + errorMessage = TransportClient.GetErrorResponse(storeResponse, string.Format(CultureInfo.CurrentUICulture, + RMResources.RequestEntityTooLarge, + HttpConstants.HttpHeaders.PageSize), + out responseHeaders); + exception = new RequestEntityTooLargeException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.Locked: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.Locked, out responseHeaders); + exception = new LockedException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.TooManyRequests: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.TooManyRequests, out responseHeaders); + exception = new RequestRateTooLargeException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.ServiceUnavailable: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.ServiceUnavailable, out responseHeaders); + uint substatus = TransportClient.GetExceptionSubStatus(responseHeaders, errorMessage, physicalAddress); + if (!string.IsNullOrEmpty(errorMessage)) + { + exception = new ServiceUnavailableException( + message: string.Format(CultureInfo.CurrentUICulture, RMResources.ExceptionMessage, errorMessage), + headers: responseHeaders, + subStatusCode: (substatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value + requestUri: physicalAddress); + } + else + { + exception = ServiceUnavailableException.Create( + headers: responseHeaders, + subStatusCode: (substatus == 0) ? SubStatusCodes.ServerGenerated503 : null, // if substatus is not zero we pass null because the headers will have the correct value + requestUri: physicalAddress); + } + break; + + case StatusCodes.RequestTimeout: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.RequestTimeout, out responseHeaders); + exception = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.RetryWith: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.RetryWith, out responseHeaders); + exception = new RetryWithException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + case StatusCodes.InternalServerError: + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.InternalServerError, out responseHeaders); + exception = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + break; + + default: + { + DefaultTrace.TraceCritical("Unrecognized status code {0} returned by backend. ActivityId {1}", storeResponse.Status, activityId); + TransportClient.LogException(null, physicalAddress, resourceAddress, activityId); + errorMessage = TransportClient.GetErrorResponse(storeResponse, RMResources.InvalidBackendResponse, out responseHeaders); + exception = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + errorMessage), + responseHeaders, + physicalAddress); + } + break; + } + + exception.LSN = storeResponse.LSN; + exception.PartitionKeyRangeId = storeResponse.PartitionKeyRangeId; + exception.ResourceAddress = resourceAddress; + exception.TransportRequestStats = storeResponse.TransportRequestStats; + throw exception; + } + + protected Task InvokeQueryStoreAsync( + Uri physicalAddress, + ResourceType resourceType, + DocumentServiceRequest request) + { + string contentType = request.Headers[HttpConstants.HttpHeaders.ContentType]; + + OperationType operationType; + if (string.Equals(contentType, RuntimeConstants.MediaTypes.SQL, StringComparison.Ordinal)) + { + operationType = OperationType.SqlQuery; + } + else + { + operationType = OperationType.Query; + } + + return InvokeStoreAsync( + physicalAddress, + ResourceOperation.Query(operationType, resourceType), + request); + } + + internal virtual Task InvokeStoreAsync( + TransportAddressUri physicalAddress, + ResourceOperation resourceOperation, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync(physicalAddress.Uri, resourceOperation, request); + } + + internal abstract Task InvokeStoreAsync( + Uri physicalAddress, + ResourceOperation resourceOperation, + DocumentServiceRequest request); + + /// + /// Uses the rntbd context negotiation and opens the connection to the backend replica nodes. + /// + /// An instance of containing the + /// uri of the backend server's physical address. + internal virtual Task OpenConnectionAsync( + Uri physicalAddress) + { + throw new NotImplementedException(); + } + + protected async static Task GetErrorResponseAsync(HttpResponseMessage responseMessage) + { + if (responseMessage.Content != null) + { + Stream responseStream = await responseMessage.Content.ReadAsStreamAsync(); + return TransportClient.GetErrorFromStream(responseStream); + } + else + { + return ""; + } + } + + protected static string GetErrorResponse(StoreResponse storeResponse, string defaultMessage, out INameValueCollection responseHeaders) + { + string result = null; + responseHeaders = storeResponse.Headers; + + if (storeResponse.ResponseBody != null) + { + result = TransportClient.GetErrorFromStream(storeResponse.ResponseBody); + } + + return string.IsNullOrEmpty(result) ? defaultMessage : result; + } + + protected static string GetErrorFromStream(Stream responseStream) + { + using (responseStream) + { + return new StreamReader(responseStream).ReadToEnd(); + } + } + + protected static void LogException(Uri physicalAddress, string activityId) + { + DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, "Store Request Failed. Store Physical Address {0} ActivityId {1}", + physicalAddress, activityId)); + } + + protected static void LogException(Exception exception, Uri physicalAddress, string rid, Guid activityId) + { + if (exception != null) + { + DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, + "Store Request Failed. Exception {0} Store Physical Address {1} RID {2} ActivityId {3}", + exception.Message, physicalAddress, rid, activityId.ToString())); + } + else + { + DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, + "Store Request Failed. Store Physical Address {0} RID {1} ActivityId {2}", + physicalAddress, rid, activityId.ToString())); + } + } + + protected static void LogGoneException(Uri physicalAddress, string activityId) + { + DefaultTrace.TraceInformation(string.Format(CultureInfo.InvariantCulture, "Listener not found. Store Physical Address {0} ActivityId {1}", + physicalAddress, activityId)); + } + + protected static uint GetExceptionSubStatus(INameValueCollection responseHeaders, string errorMessage, Uri physicalAddress) + { + uint nSubStatus = 0; + if (responseHeaders == null) + { + return 0; + } + + string valueSubStatus = responseHeaders.Get(WFConstants.BackendHeaders.SubStatus); + if (!string.IsNullOrEmpty(valueSubStatus)) + { + if (!uint.TryParse(valueSubStatus, NumberStyles.Integer, CultureInfo.InvariantCulture, out nSubStatus)) + { + throw new BadRequestException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + string.IsNullOrEmpty(errorMessage) ? RMResources.BadRequest : errorMessage), + responseHeaders, + physicalAddress); + } + } + + return nSubStatus; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportErrorCode.cs b/Microsoft.Azure.Cosmos/src/direct/TransportErrorCode.cs index 0440a77727..e3cdc549f6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportErrorCode.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportErrorCode.cs @@ -1,80 +1,80 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - // When adding a new code: - // - Give it an explicit value. Do not rely on implicit values. Do not - // reuse values from older codes that might have been retired. - // - Add a resource string. - // - Update TransportException.IsTimeout if appropriate. By default, error - // codes are not treated as timeouts. - // - Update TransportExceptionTests. - // - // When retiring a code, avoid removing it altogether. Rename "Foo" to - // "ObsoleteFoo" instead. - // - // Do not re-number error codes. - // - // Avoid renaming error codes. Prefer adding new names with the same - // value. This also prevents accidental indirect re-numbering. - // - // Keep this in sync with the documentation at - // ${ENLISTMENT_ROOT}\docs\tsg\tsg914.md. - internal enum TransportErrorCode - { - // This error code must never be used. It serves as a default - // value. Its presence indicates that some code throws - // TransportException but didn't set its code correctly. - Unknown = 0, - - // Generic error code used when channel initialization fails. - // Examine the inner exception to determine the cause of the error. - ChannelOpenFailed = 1, - - // Generic error code that indicates creating a channel timed out. - // It serves as a default value. Code that throws TransportException - // must use a more specific code for connection establishment - // timeouts. - ChannelOpenTimeout = 2, - - DnsResolutionFailed = 3, - DnsResolutionTimeout = 4, - ConnectFailed = 5, - ConnectTimeout = 6, - SslNegotiationFailed = 7, - SslNegotiationTimeout = 8, - - // Generic error code that indicates negotiating the RNTBD parameters - // timed out. It serves as a default value. Code that throws - // TransportException must use a more specific code for negotiation - // timeouts. - TransportNegotiationTimeout = 9, - - // Generic error code that indicates an RNTBD call timed out. It - // serves as a default value. Code that throws TransportException - // must use a more specific code for request timeouts. - RequestTimeout = 10, - - // The RNTBD Dispatcher failed and no longer accepts new requests. - ChannelMultiplexerClosed = 11, - SendFailed = 12, - SendLockTimeout = 13, - SendTimeout = 14, - ReceiveFailed = 15, - ReceiveTimeout = 16, - - // The remote process closed the connection. - ReceiveStreamClosed = 17, - // The underlying connection is no longer usable. - ConnectionBroken = 18, - - // Concurrent opening channel is limit by MaxConcurrentOpeningConnectionCount, error code to indicate - // channel failed to enter the openingSlim within a certain period - ChannelWaitingToOpenTimeout = 19, - - // Keep this in sync with the documentation at - // ${ENLISTMENT_ROOT}\docs\tsg\tsg914.md. - // Insert new values above this comment. - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + // When adding a new code: + // - Give it an explicit value. Do not rely on implicit values. Do not + // reuse values from older codes that might have been retired. + // - Add a resource string. + // - Update TransportException.IsTimeout if appropriate. By default, error + // codes are not treated as timeouts. + // - Update TransportExceptionTests. + // + // When retiring a code, avoid removing it altogether. Rename "Foo" to + // "ObsoleteFoo" instead. + // + // Do not re-number error codes. + // + // Avoid renaming error codes. Prefer adding new names with the same + // value. This also prevents accidental indirect re-numbering. + // + // Keep this in sync with the documentation at + // ${ENLISTMENT_ROOT}\docs\tsg\tsg914.md. + internal enum TransportErrorCode + { + // This error code must never be used. It serves as a default + // value. Its presence indicates that some code throws + // TransportException but didn't set its code correctly. + Unknown = 0, + + // Generic error code used when channel initialization fails. + // Examine the inner exception to determine the cause of the error. + ChannelOpenFailed = 1, + + // Generic error code that indicates creating a channel timed out. + // It serves as a default value. Code that throws TransportException + // must use a more specific code for connection establishment + // timeouts. + ChannelOpenTimeout = 2, + + DnsResolutionFailed = 3, + DnsResolutionTimeout = 4, + ConnectFailed = 5, + ConnectTimeout = 6, + SslNegotiationFailed = 7, + SslNegotiationTimeout = 8, + + // Generic error code that indicates negotiating the RNTBD parameters + // timed out. It serves as a default value. Code that throws + // TransportException must use a more specific code for negotiation + // timeouts. + TransportNegotiationTimeout = 9, + + // Generic error code that indicates an RNTBD call timed out. It + // serves as a default value. Code that throws TransportException + // must use a more specific code for request timeouts. + RequestTimeout = 10, + + // The RNTBD Dispatcher failed and no longer accepts new requests. + ChannelMultiplexerClosed = 11, + SendFailed = 12, + SendLockTimeout = 13, + SendTimeout = 14, + ReceiveFailed = 15, + ReceiveTimeout = 16, + + // The remote process closed the connection. + ReceiveStreamClosed = 17, + // The underlying connection is no longer usable. + ConnectionBroken = 18, + + // Concurrent opening channel is limit by MaxConcurrentOpeningConnectionCount, error code to indicate + // channel failed to enter the openingSlim within a certain period + ChannelWaitingToOpenTimeout = 19, + + // Keep this in sync with the documentation at + // ${ENLISTMENT_ROOT}\docs\tsg\tsg914.md. + // Insert new values above this comment. + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportException.cs b/Microsoft.Azure.Cosmos/src/direct/TransportException.cs index ee678dfe8d..9d5e27b19f 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportException.cs @@ -1,258 +1,258 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.ComponentModel; - using System.Diagnostics; - using System.Globalization; - using System.Net.Sockets; - using System.Threading; - using Microsoft.Azure.Cosmos.Core.Trace; - using Rntbd; - - [Serializable] - internal sealed class TransportException : Exception - { - private static readonly Lazy> lazyMessageMap = - new Lazy>( - TransportException.GetErrorTextMap, - LazyThreadSafetyMode.ExecutionAndPublication); - - private static TransportExceptionCounters transportExceptionCounters = new TransportExceptionCounters(); - - private readonly object mutex = new object(); - - public TransportException( - TransportErrorCode errorCode, - Exception innerException, - Guid activityId, - Uri requestUri, - string sourceDescription, - bool userPayload, - bool payloadSent) : - base(TransportException.LoadMessage(errorCode), innerException) - { - this.Timestamp = DateTime.UtcNow; - this.ErrorCode = errorCode; - this.ActivityId = activityId; - this.RequestUri = requestUri; - this.Source = sourceDescription; - this.UserRequestSent = TransportException.IsUserRequestSent( - errorCode, userPayload, payloadSent); - TransportException.UpdateCounters(requestUri, innerException); - } - - public override string Message - { - get - { - string baseError; - Exception baseException = this.GetBaseException(); - { - SocketException socketException = baseException as SocketException; - if (socketException != null) - { - baseError = string.Format( - CultureInfo.InvariantCulture, - "socket error {0} [0x{1:X8}]", - socketException.SocketErrorCode, - (int)socketException.SocketErrorCode); - } - else - { - Win32Exception win32Exception = baseException as Win32Exception; - if (win32Exception != null) - { - baseError = string.Format( - CultureInfo.InvariantCulture, - "Windows error 0x{0:X8}", - win32Exception.NativeErrorCode); - } - else - { - baseError = string.Format( - CultureInfo.InvariantCulture, - "HRESULT 0x{0:X8}", - baseException.HResult); - } - } - } - - return string.Format( - CultureInfo.InvariantCulture, - "{0} (Time: {1:o}, activity ID: {2}, error code: {3} [0x{4:X4}], " + - "base error: {5}, URI: {6}, connection: {7}, payload sent: {8})", - base.Message, - this.Timestamp, - this.ActivityId, - this.ErrorCode, (int)this.ErrorCode, - baseError, - this.RequestUri, - this.Source, - this.UserRequestSent); - } - } - - public DateTime Timestamp { get; private set; } - - public DateTime? RequestStartTime { get; set; } - - public DateTime? RequestEndTime { get; set; } - - public ResourceType ResourceType { get; set; } - - public OperationType OperationType { get; set; } - - public TransportErrorCode ErrorCode { get; private set; } - - public Guid ActivityId { get; private set; } - - public Uri RequestUri { get; private set; } - - public bool UserRequestSent { get; private set; } - - public static bool IsTimeout(TransportErrorCode errorCode) - { - return - (errorCode == TransportErrorCode.ChannelOpenTimeout) || - (errorCode == TransportErrorCode.DnsResolutionTimeout) || - (errorCode == TransportErrorCode.ConnectTimeout) || - (errorCode == TransportErrorCode.SslNegotiationTimeout) || - (errorCode == TransportErrorCode.TransportNegotiationTimeout) || - (errorCode == TransportErrorCode.RequestTimeout) || - (errorCode == TransportErrorCode.SendLockTimeout) || - (errorCode == TransportErrorCode.SendTimeout) || - (errorCode == TransportErrorCode.ReceiveTimeout) || - (errorCode == TransportErrorCode.ChannelWaitingToOpenTimeout); - } - - private static bool IsUserRequestSent( - TransportErrorCode errorCode, bool userPayload, bool payloadSent) - { - // It doesn't matter what the error was, if it didn't occur while - // handling the user's request (e.g. if it occurred while doing SSL - // or RNTBD negotiation). - if (!userPayload) - { - return false; - } - return payloadSent || TransportException.IsTimeout(errorCode); - } - - private static string LoadMessage(TransportErrorCode errorCode) - { - return string.Format( - CultureInfo.CurrentUICulture, - RMResources.TransportExceptionMessage, - TransportException.GetErrorText(errorCode)); - } - - private static string GetErrorText(TransportErrorCode errorCode) - { - string errorText; - if (TransportException.lazyMessageMap.Value.TryGetValue( - errorCode, out errorText)) - { - return errorText; - } - Debug.Assert( - false, - string.Format( - CultureInfo.InvariantCulture, - "Error code {0} not found in the error text map. Please update {1}", - errorCode, nameof(GetErrorTextMap))); - return string.Format(CultureInfo.InvariantCulture, "{0}", errorCode); - } - - private static Dictionary GetErrorTextMap() - { - return new Dictionary - { - { TransportErrorCode.ChannelMultiplexerClosed, RMResources.ChannelMultiplexerClosedTransportError }, - { TransportErrorCode.ChannelOpenFailed, RMResources.ChannelOpenFailedTransportError }, - { TransportErrorCode.ChannelOpenTimeout, RMResources.ChannelOpenTimeoutTransportError }, - { TransportErrorCode.ConnectFailed, RMResources.ConnectFailedTransportError }, - { TransportErrorCode.ConnectTimeout, RMResources.ConnectTimeoutTransportError }, - { TransportErrorCode.ConnectionBroken, RMResources.ConnectionBrokenTransportError }, - { TransportErrorCode.DnsResolutionFailed, RMResources.DnsResolutionFailedTransportError }, - { TransportErrorCode.DnsResolutionTimeout, RMResources.DnsResolutionTimeoutTransportError }, - { TransportErrorCode.ReceiveFailed, RMResources.ReceiveFailedTransportError }, - { TransportErrorCode.ReceiveStreamClosed, RMResources.ReceiveStreamClosedTransportError }, - { TransportErrorCode.ReceiveTimeout, RMResources.ReceiveTimeoutTransportError }, - { TransportErrorCode.RequestTimeout, RMResources.RequestTimeoutTransportError }, - { TransportErrorCode.SendFailed, RMResources.SendFailedTransportError }, - { TransportErrorCode.SendLockTimeout, RMResources.SendLockTimeoutTransportError }, - { TransportErrorCode.SendTimeout, RMResources.SendTimeoutTransportError }, - { TransportErrorCode.SslNegotiationFailed, RMResources.SslNegotiationFailedTransportError }, - { TransportErrorCode.SslNegotiationTimeout, RMResources.SslNegotiationTimeoutTransportError }, - { TransportErrorCode.TransportNegotiationTimeout, RMResources.TransportNegotiationTimeoutTransportError }, - { TransportErrorCode.ChannelWaitingToOpenTimeout, RMResources.ChannelWaitingToOpenTimeoutException }, - { TransportErrorCode.Unknown, RMResources.UnknownTransportError } - }; - } - - private static void UpdateCounters(Uri requestUri, Exception innerException) - { - const int SEC_E_DECRYPT_FAILURE = unchecked((int)0x80090330); - - if (innerException == null) - { - return; - } - if (innerException is TransportException) - { - return; - } - innerException = innerException.GetBaseException(); - SocketException socketException = innerException as SocketException; - if (socketException != null) - { - switch (socketException.SocketErrorCode) - { - case SocketError.NoBufferSpaceAvailable: - TransportException.transportExceptionCounters.IncrementEphemeralPortExhaustion(); - break; - } - } - else - { - Win32Exception win32Exception = innerException as Win32Exception; - if (win32Exception != null) - { - switch (win32Exception.NativeErrorCode) - { - // This code is fragile but it works for now. - // It's the best I could do given the quality of our dependencies: - // You'd expect Win32Exception to deal with Win32 error codes. - // However, it also accepts HRESULT - sort of. For this exception, - // Win32Exception.ErrorCode and Win32Exception.HResult - // return E_FAIL. - case SEC_E_DECRYPT_FAILURE: - DefaultTrace.TraceWarning( - "Decryption failure. Exception text: {0}. Native error code: 0x{1:X8}. Remote endpoint: {2}", - win32Exception.Message, - win32Exception.NativeErrorCode, - string.Format( - CultureInfo.InvariantCulture, - "{0}:{1}", - requestUri.DnsSafeHost, requestUri.Port)); - TransportException.transportExceptionCounters.IncrementDecryptionFailures(); - break; - } - } - } - } - - internal static void SetCounters(TransportExceptionCounters transportExceptionCounters) - { - if (transportExceptionCounters == null) - { - throw new ArgumentNullException(nameof(transportExceptionCounters)); - } - TransportException.transportExceptionCounters = transportExceptionCounters; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.ComponentModel; + using System.Diagnostics; + using System.Globalization; + using System.Net.Sockets; + using System.Threading; + using Microsoft.Azure.Cosmos.Core.Trace; + using Rntbd; + + [Serializable] + internal sealed class TransportException : Exception + { + private static readonly Lazy> lazyMessageMap = + new Lazy>( + TransportException.GetErrorTextMap, + LazyThreadSafetyMode.ExecutionAndPublication); + + private static TransportExceptionCounters transportExceptionCounters = new TransportExceptionCounters(); + + private readonly object mutex = new object(); + + public TransportException( + TransportErrorCode errorCode, + Exception innerException, + Guid activityId, + Uri requestUri, + string sourceDescription, + bool userPayload, + bool payloadSent) : + base(TransportException.LoadMessage(errorCode), innerException) + { + this.Timestamp = DateTime.UtcNow; + this.ErrorCode = errorCode; + this.ActivityId = activityId; + this.RequestUri = requestUri; + this.Source = sourceDescription; + this.UserRequestSent = TransportException.IsUserRequestSent( + errorCode, userPayload, payloadSent); + TransportException.UpdateCounters(requestUri, innerException); + } + + public override string Message + { + get + { + string baseError; + Exception baseException = this.GetBaseException(); + { + SocketException socketException = baseException as SocketException; + if (socketException != null) + { + baseError = string.Format( + CultureInfo.InvariantCulture, + "socket error {0} [0x{1:X8}]", + socketException.SocketErrorCode, + (int)socketException.SocketErrorCode); + } + else + { + Win32Exception win32Exception = baseException as Win32Exception; + if (win32Exception != null) + { + baseError = string.Format( + CultureInfo.InvariantCulture, + "Windows error 0x{0:X8}", + win32Exception.NativeErrorCode); + } + else + { + baseError = string.Format( + CultureInfo.InvariantCulture, + "HRESULT 0x{0:X8}", + baseException.HResult); + } + } + } + + return string.Format( + CultureInfo.InvariantCulture, + "{0} (Time: {1:o}, activity ID: {2}, error code: {3} [0x{4:X4}], " + + "base error: {5}, URI: {6}, connection: {7}, payload sent: {8})", + base.Message, + this.Timestamp, + this.ActivityId, + this.ErrorCode, (int)this.ErrorCode, + baseError, + this.RequestUri, + this.Source, + this.UserRequestSent); + } + } + + public DateTime Timestamp { get; private set; } + + public DateTime? RequestStartTime { get; set; } + + public DateTime? RequestEndTime { get; set; } + + public ResourceType ResourceType { get; set; } + + public OperationType OperationType { get; set; } + + public TransportErrorCode ErrorCode { get; private set; } + + public Guid ActivityId { get; private set; } + + public Uri RequestUri { get; private set; } + + public bool UserRequestSent { get; private set; } + + public static bool IsTimeout(TransportErrorCode errorCode) + { + return + (errorCode == TransportErrorCode.ChannelOpenTimeout) || + (errorCode == TransportErrorCode.DnsResolutionTimeout) || + (errorCode == TransportErrorCode.ConnectTimeout) || + (errorCode == TransportErrorCode.SslNegotiationTimeout) || + (errorCode == TransportErrorCode.TransportNegotiationTimeout) || + (errorCode == TransportErrorCode.RequestTimeout) || + (errorCode == TransportErrorCode.SendLockTimeout) || + (errorCode == TransportErrorCode.SendTimeout) || + (errorCode == TransportErrorCode.ReceiveTimeout) || + (errorCode == TransportErrorCode.ChannelWaitingToOpenTimeout); + } + + private static bool IsUserRequestSent( + TransportErrorCode errorCode, bool userPayload, bool payloadSent) + { + // It doesn't matter what the error was, if it didn't occur while + // handling the user's request (e.g. if it occurred while doing SSL + // or RNTBD negotiation). + if (!userPayload) + { + return false; + } + return payloadSent || TransportException.IsTimeout(errorCode); + } + + private static string LoadMessage(TransportErrorCode errorCode) + { + return string.Format( + CultureInfo.CurrentUICulture, + RMResources.TransportExceptionMessage, + TransportException.GetErrorText(errorCode)); + } + + private static string GetErrorText(TransportErrorCode errorCode) + { + string errorText; + if (TransportException.lazyMessageMap.Value.TryGetValue( + errorCode, out errorText)) + { + return errorText; + } + Debug.Assert( + false, + string.Format( + CultureInfo.InvariantCulture, + "Error code {0} not found in the error text map. Please update {1}", + errorCode, nameof(GetErrorTextMap))); + return string.Format(CultureInfo.InvariantCulture, "{0}", errorCode); + } + + private static Dictionary GetErrorTextMap() + { + return new Dictionary + { + { TransportErrorCode.ChannelMultiplexerClosed, RMResources.ChannelMultiplexerClosedTransportError }, + { TransportErrorCode.ChannelOpenFailed, RMResources.ChannelOpenFailedTransportError }, + { TransportErrorCode.ChannelOpenTimeout, RMResources.ChannelOpenTimeoutTransportError }, + { TransportErrorCode.ConnectFailed, RMResources.ConnectFailedTransportError }, + { TransportErrorCode.ConnectTimeout, RMResources.ConnectTimeoutTransportError }, + { TransportErrorCode.ConnectionBroken, RMResources.ConnectionBrokenTransportError }, + { TransportErrorCode.DnsResolutionFailed, RMResources.DnsResolutionFailedTransportError }, + { TransportErrorCode.DnsResolutionTimeout, RMResources.DnsResolutionTimeoutTransportError }, + { TransportErrorCode.ReceiveFailed, RMResources.ReceiveFailedTransportError }, + { TransportErrorCode.ReceiveStreamClosed, RMResources.ReceiveStreamClosedTransportError }, + { TransportErrorCode.ReceiveTimeout, RMResources.ReceiveTimeoutTransportError }, + { TransportErrorCode.RequestTimeout, RMResources.RequestTimeoutTransportError }, + { TransportErrorCode.SendFailed, RMResources.SendFailedTransportError }, + { TransportErrorCode.SendLockTimeout, RMResources.SendLockTimeoutTransportError }, + { TransportErrorCode.SendTimeout, RMResources.SendTimeoutTransportError }, + { TransportErrorCode.SslNegotiationFailed, RMResources.SslNegotiationFailedTransportError }, + { TransportErrorCode.SslNegotiationTimeout, RMResources.SslNegotiationTimeoutTransportError }, + { TransportErrorCode.TransportNegotiationTimeout, RMResources.TransportNegotiationTimeoutTransportError }, + { TransportErrorCode.ChannelWaitingToOpenTimeout, RMResources.ChannelWaitingToOpenTimeoutException }, + { TransportErrorCode.Unknown, RMResources.UnknownTransportError } + }; + } + + private static void UpdateCounters(Uri requestUri, Exception innerException) + { + const int SEC_E_DECRYPT_FAILURE = unchecked((int)0x80090330); + + if (innerException == null) + { + return; + } + if (innerException is TransportException) + { + return; + } + innerException = innerException.GetBaseException(); + SocketException socketException = innerException as SocketException; + if (socketException != null) + { + switch (socketException.SocketErrorCode) + { + case SocketError.NoBufferSpaceAvailable: + TransportException.transportExceptionCounters.IncrementEphemeralPortExhaustion(); + break; + } + } + else + { + Win32Exception win32Exception = innerException as Win32Exception; + if (win32Exception != null) + { + switch (win32Exception.NativeErrorCode) + { + // This code is fragile but it works for now. + // It's the best I could do given the quality of our dependencies: + // You'd expect Win32Exception to deal with Win32 error codes. + // However, it also accepts HRESULT - sort of. For this exception, + // Win32Exception.ErrorCode and Win32Exception.HResult + // return E_FAIL. + case SEC_E_DECRYPT_FAILURE: + DefaultTrace.TraceWarning( + "Decryption failure. Exception text: {0}. Native error code: 0x{1:X8}. Remote endpoint: {2}", + win32Exception.Message, + win32Exception.NativeErrorCode, + string.Format( + CultureInfo.InvariantCulture, + "{0}:{1}", + requestUri.DnsSafeHost, requestUri.Port)); + TransportException.transportExceptionCounters.IncrementDecryptionFailures(); + break; + } + } + } + } + + internal static void SetCounters(TransportExceptionCounters transportExceptionCounters) + { + if (transportExceptionCounters == null) + { + throw new ArgumentNullException(nameof(transportExceptionCounters)); + } + TransportException.transportExceptionCounters = transportExceptionCounters; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportExceptionCounters.cs b/Microsoft.Azure.Cosmos/src/direct/TransportExceptionCounters.cs index 7c2c4ac284..0b7ed9e3f8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportExceptionCounters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportExceptionCounters.cs @@ -1,17 +1,17 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - internal class TransportExceptionCounters - { - internal virtual void IncrementDecryptionFailures() - { - } - - internal virtual void IncrementEphemeralPortExhaustion() - { - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + internal class TransportExceptionCounters + { + internal virtual void IncrementDecryptionFailures() + { + } + + internal virtual void IncrementEphemeralPortExhaustion() + { + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportExceptions.cs b/Microsoft.Azure.Cosmos/src/direct/TransportExceptions.cs index eb3656a10e..35ba982d04 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportExceptions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportExceptions.cs @@ -1,221 +1,221 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - internal static class TransportExceptions - { - internal static string LocalIpv4Address; - private static bool AddSourceIpAddressInNetworkExceptionMessagePrivate = false; - - // This will default to false, to avoid privacy concerns in general. We can explicitly enable it - // inside processes running in our datacenter, to get useful detail in our traces (paired source - // and target IP address have been needed in the past for CloudNet investigations, for example) - public static bool AddSourceIpAddressInNetworkExceptionMessage - { - get - { - return TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate; - } - set - { - if (value && !TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate) - { - // From false to true, reset the IP address for logging - TransportExceptions.LocalIpv4Address = NetUtil.GetNonLoopbackIpV4Address() ?? string.Empty; - } - - TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate = value; - } - } - - internal static GoneException GetGoneException( - Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) - { - Trace.CorrelationManager.ActivityId = activityId; - - GoneException ex; - if (inner == null) - { - if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) - { - ex = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - inner, - SubStatusCodes.TransportGenerated410, - targetAddress, - TransportExceptions.LocalIpv4Address); - } - else - { - ex = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - inner, - SubStatusCodes.TransportGenerated410, - targetAddress); - } - } - else - { - if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) - { - ex = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - inner, - SubStatusCodes.TransportGenerated410, - targetAddress, - TransportExceptions.LocalIpv4Address); - } - else - { - ex = new GoneException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.Gone), - inner, - SubStatusCodes.TransportGenerated410, - targetAddress); - } - } - - ex.Headers.Set(HttpConstants.HttpHeaders.ActivityId, activityId.ToString()); - ex.TransportRequestStats = transportRequestStats; - return ex; - } - - internal static RequestTimeoutException GetRequestTimeoutException( - Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) - { - Trace.CorrelationManager.ActivityId = activityId; - RequestTimeoutException timeoutException; - - if (inner == null) - { - if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) - { - timeoutException = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.RequestTimeout), - inner, - targetAddress, - TransportExceptions.LocalIpv4Address); - } - else - { - timeoutException = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.RequestTimeout), - inner, - targetAddress); - } - } - else - { - if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) - { - timeoutException = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.RequestTimeout), - inner, - targetAddress, - TransportExceptions.LocalIpv4Address); - } - else - { - timeoutException = new RequestTimeoutException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.RequestTimeout), - inner, - targetAddress); - } - } - - timeoutException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - timeoutException.TransportRequestStats = transportRequestStats; - return timeoutException; - } - - internal static ServiceUnavailableException GetServiceUnavailableException( - Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) - { - Trace.CorrelationManager.ActivityId = activityId; - ServiceUnavailableException serviceUnavailableException; - - if (inner == null) - { - serviceUnavailableException = ServiceUnavailableException.Create( - SubStatusCodes.Channel_Closed, - requestUri: targetAddress); - } - else - { - serviceUnavailableException = ServiceUnavailableException.Create( - SubStatusCodes.Channel_Closed, - innerException: inner, - requestUri: targetAddress); - } - - serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - serviceUnavailableException.TransportRequestStats = transportRequestStats; - return serviceUnavailableException; - } - - internal static InternalServerErrorException GetInternalServerErrorException( - Uri targetAddress, Guid activityId, Exception inner = null) - { - Trace.CorrelationManager.ActivityId = activityId; - InternalServerErrorException internalServerErrorException; - - if (inner == null) - { - internalServerErrorException = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.ChannelClosed), - targetAddress); - } - else - { - internalServerErrorException = new InternalServerErrorException( - string.Format(CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - RMResources.ChannelClosed), - inner, - targetAddress); - } - - internalServerErrorException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - return internalServerErrorException; - } - - internal static InternalServerErrorException GetInternalServerErrorException( - Uri targetAddress, string exceptionMessage) - { - InternalServerErrorException exception = new InternalServerErrorException( - string.Format( - CultureInfo.CurrentUICulture, - RMResources.ExceptionMessage, - exceptionMessage), - targetAddress); - exception.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); - return exception; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + internal static class TransportExceptions + { + internal static string LocalIpv4Address; + private static bool AddSourceIpAddressInNetworkExceptionMessagePrivate = false; + + // This will default to false, to avoid privacy concerns in general. We can explicitly enable it + // inside processes running in our datacenter, to get useful detail in our traces (paired source + // and target IP address have been needed in the past for CloudNet investigations, for example) + public static bool AddSourceIpAddressInNetworkExceptionMessage + { + get + { + return TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate; + } + set + { + if (value && !TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate) + { + // From false to true, reset the IP address for logging + TransportExceptions.LocalIpv4Address = NetUtil.GetNonLoopbackIpV4Address() ?? string.Empty; + } + + TransportExceptions.AddSourceIpAddressInNetworkExceptionMessagePrivate = value; + } + } + + internal static GoneException GetGoneException( + Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) + { + Trace.CorrelationManager.ActivityId = activityId; + + GoneException ex; + if (inner == null) + { + if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) + { + ex = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + inner, + SubStatusCodes.TransportGenerated410, + targetAddress, + TransportExceptions.LocalIpv4Address); + } + else + { + ex = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + inner, + SubStatusCodes.TransportGenerated410, + targetAddress); + } + } + else + { + if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) + { + ex = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + inner, + SubStatusCodes.TransportGenerated410, + targetAddress, + TransportExceptions.LocalIpv4Address); + } + else + { + ex = new GoneException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.Gone), + inner, + SubStatusCodes.TransportGenerated410, + targetAddress); + } + } + + ex.Headers.Set(HttpConstants.HttpHeaders.ActivityId, activityId.ToString()); + ex.TransportRequestStats = transportRequestStats; + return ex; + } + + internal static RequestTimeoutException GetRequestTimeoutException( + Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) + { + Trace.CorrelationManager.ActivityId = activityId; + RequestTimeoutException timeoutException; + + if (inner == null) + { + if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) + { + timeoutException = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.RequestTimeout), + inner, + targetAddress, + TransportExceptions.LocalIpv4Address); + } + else + { + timeoutException = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.RequestTimeout), + inner, + targetAddress); + } + } + else + { + if (TransportExceptions.AddSourceIpAddressInNetworkExceptionMessage) + { + timeoutException = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.RequestTimeout), + inner, + targetAddress, + TransportExceptions.LocalIpv4Address); + } + else + { + timeoutException = new RequestTimeoutException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.RequestTimeout), + inner, + targetAddress); + } + } + + timeoutException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + timeoutException.TransportRequestStats = transportRequestStats; + return timeoutException; + } + + internal static ServiceUnavailableException GetServiceUnavailableException( + Uri targetAddress, Guid activityId, Exception inner = null, TransportRequestStats transportRequestStats = null) + { + Trace.CorrelationManager.ActivityId = activityId; + ServiceUnavailableException serviceUnavailableException; + + if (inner == null) + { + serviceUnavailableException = ServiceUnavailableException.Create( + SubStatusCodes.Channel_Closed, + requestUri: targetAddress); + } + else + { + serviceUnavailableException = ServiceUnavailableException.Create( + SubStatusCodes.Channel_Closed, + innerException: inner, + requestUri: targetAddress); + } + + serviceUnavailableException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + serviceUnavailableException.TransportRequestStats = transportRequestStats; + return serviceUnavailableException; + } + + internal static InternalServerErrorException GetInternalServerErrorException( + Uri targetAddress, Guid activityId, Exception inner = null) + { + Trace.CorrelationManager.ActivityId = activityId; + InternalServerErrorException internalServerErrorException; + + if (inner == null) + { + internalServerErrorException = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.ChannelClosed), + targetAddress); + } + else + { + internalServerErrorException = new InternalServerErrorException( + string.Format(CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + RMResources.ChannelClosed), + inner, + targetAddress); + } + + internalServerErrorException.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + return internalServerErrorException; + } + + internal static InternalServerErrorException GetInternalServerErrorException( + Uri targetAddress, string exceptionMessage) + { + InternalServerErrorException exception = new InternalServerErrorException( + string.Format( + CultureInfo.CurrentUICulture, + RMResources.ExceptionMessage, + exceptionMessage), + targetAddress); + exception.Headers.Add(HttpConstants.HttpHeaders.RequestValidationFailure, "1"); + return exception; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportPerformanceCounters.cs b/Microsoft.Azure.Cosmos/src/direct/TransportPerformanceCounters.cs index 1af2e8910f..db1db915ed 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportPerformanceCounters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportPerformanceCounters.cs @@ -1,36 +1,36 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// The Transport performance counter. - /// As sdk-MDM integration is currently not available, this will ignore all metrics - /// - internal class TransportPerformanceCounters - { - internal virtual void IncrementRntbdRequestCount(ResourceType resourceType, OperationType operationType) - { - } - - internal virtual void IncrementRntbdResponseCount(ResourceType resourceType, OperationType operationType, int statusCode) - { - } - - internal virtual void IncrementRntbdConnectionEstablishedCount() - { - } - - internal virtual void IncrementRntbdConnectionClosedCount() - { - } - - internal virtual void LogRntbdBytesSentCount(ResourceType resourceType, OperationType operationType, long? bytes) - { - } - - internal virtual void LogRntbdBytesReceivedCount(ResourceType resourceType, OperationType operationType, long? bytes) - { - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// The Transport performance counter. + /// As sdk-MDM integration is currently not available, this will ignore all metrics + /// + internal class TransportPerformanceCounters + { + internal virtual void IncrementRntbdRequestCount(ResourceType resourceType, OperationType operationType) + { + } + + internal virtual void IncrementRntbdResponseCount(ResourceType resourceType, OperationType operationType, int statusCode) + { + } + + internal virtual void IncrementRntbdConnectionEstablishedCount() + { + } + + internal virtual void IncrementRntbdConnectionClosedCount() + { + } + + internal virtual void LogRntbdBytesSentCount(ResourceType resourceType, OperationType operationType, long? bytes) + { + } + + internal virtual void LogRntbdBytesReceivedCount(ResourceType resourceType, OperationType operationType, long? bytes) + { + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportRequestStats.cs b/Microsoft.Azure.Cosmos/src/direct/TransportRequestStats.cs index 187e5e8594..e89fd9ee91 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportRequestStats.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportRequestStats.cs @@ -1,310 +1,310 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.Text; - - internal sealed class TransportRequestStats - { - private const string RequestStageCreated = "Created"; - private const string RequestStageChannelAcquisitionStarted = "ChannelAcquisitionStarted"; - private const string RequestStagePipelined = "Pipelined"; - private const string RequestStageSent = "Transit Time"; - private const string RequestStageReceived = "Received"; - private const string RequestStageCompleted = "Completed"; - private const string RequestStageFailed = "Failed"; - - private readonly ValueStopwatch stopwatch; - private readonly DateTime requestCreatedTime; - - // measured in TimeSpan from start time - private TimeSpan? channelAcquisitionStartedTime; - private TimeSpan? requestPipelinedTime; - private TimeSpan? requestSentTime; - private TimeSpan? requestReceivedTime; - private TimeSpan? requestCompletedTime; - private TimeSpan? requestFailedTime; - - // New Object created everytime in TransportClient and thus not worrying about thread safety. - public TransportRequestStats() - { - this.CurrentStage = RequestStage.Created; - this.requestCreatedTime = DateTime.UtcNow; - this.stopwatch = ValueStopwatch.StartNew(); - } - - public RequestStage CurrentStage { get; private set; } - - // Request Response Size Stats - public long? RequestSizeInBytes { get; set; } - public long? RequestBodySizeInBytes { get; set; } - public long? ResponseMetadataSizeInBytes { get; set; } - public long? ResponseBodySizeInBytes { get; set; } - - // Service Endpoint Stats (to a single endpoint) - public int? NumberOfInflightRequestsToEndpoint { get; set; } - public int? NumberOfOpenConnectionsToEndpoint { get; set; } // after this request is assigned to a connection - - // Connection Stats (the connection the request is assigned to) - public bool? RequestWaitingForConnectionInitialization { get; set; } - public int? NumberOfInflightRequestsInConnection { get; set; } - public DateTime? ConnectionLastSendAttemptTime { get; set; } - public DateTime? ConnectionLastSendTime { get; set; } - public DateTime? ConnectionLastReceiveTime { get; set; } - - public void RecordState(RequestStage requestStage) - { - TimeSpan elapsedTime = this.stopwatch.Elapsed; - switch (requestStage) - { - case RequestStage.ChannelAcquisitionStarted: - Debug.Assert(this.CurrentStage == RequestStage.Created, - $"Expected Transition from CREATED to CHANNEL_ACQUISITION_STARTED and not from {this.CurrentStage}"); - this.channelAcquisitionStartedTime = elapsedTime; - this.CurrentStage = RequestStage.ChannelAcquisitionStarted; - break; - case RequestStage.Pipelined: - Debug.Assert(this.CurrentStage == RequestStage.ChannelAcquisitionStarted, - $"Expected Transition from CHANNELACQUISITIONSTARTED to PIPELINED and not from {this.CurrentStage}"); - this.requestPipelinedTime = elapsedTime; - this.CurrentStage = RequestStage.Pipelined; - break; - case RequestStage.Sent: - this.requestSentTime = elapsedTime; - this.CurrentStage = RequestStage.Sent; - break; - case RequestStage.Received: - this.requestReceivedTime = elapsedTime; - this.CurrentStage = RequestStage.Received; - break; - case RequestStage.Completed: - this.requestCompletedTime = elapsedTime; - this.CurrentStage = RequestStage.Completed; - break; - case RequestStage.Failed: - this.requestFailedTime = elapsedTime; - this.CurrentStage = RequestStage.Failed; - break; - default: - throw new InvalidOperationException($"No transition to {requestStage}"); - } - } - - public override string ToString() - { - StringBuilder stringBuilder = new StringBuilder(); - this.AppendJsonString(stringBuilder); - return stringBuilder.ToString(); - } - - public void AppendJsonString(StringBuilder stringBuilder) - { - stringBuilder.Append("{\"requestTimeline\":["); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageCreated, - this.requestCreatedTime, - TimeSpan.Zero, - this.channelAcquisitionStartedTime, - this.requestFailedTime); - - if (this.channelAcquisitionStartedTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageChannelAcquisitionStarted, - this.requestCreatedTime, - this.channelAcquisitionStartedTime.Value, - this.requestPipelinedTime, - this.requestFailedTime); - } - - if (this.requestPipelinedTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStagePipelined, - this.requestCreatedTime, - this.requestPipelinedTime.Value, - this.requestSentTime, - this.requestFailedTime); - } - - if (this.requestSentTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageSent, - this.requestCreatedTime, - this.requestSentTime.Value, - this.requestReceivedTime, - this.requestFailedTime); - } - - if (this.requestReceivedTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageReceived, - this.requestCreatedTime, - this.requestReceivedTime.Value, - this.requestCompletedTime, - this.requestFailedTime); - } - - if (this.requestCompletedTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageCompleted, - this.requestCreatedTime, - this.requestCompletedTime.Value, - this.requestCompletedTime, - this.requestFailedTime); - } - - if (this.requestFailedTime.HasValue) - { - stringBuilder.Append(","); - TransportRequestStats.AppendRequestStats( - stringBuilder, - TransportRequestStats.RequestStageFailed, - this.requestCreatedTime, - this.requestFailedTime.Value, - this.requestFailedTime, - this.requestFailedTime); - } - - stringBuilder.Append("]"); - - this.AppendServiceEndpointStats(stringBuilder); - this.AppendConnectionStats(stringBuilder); - - if (this.RequestSizeInBytes.HasValue) - { - stringBuilder.Append(",\"requestSizeInBytes\":"); - stringBuilder.Append(this.RequestSizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (this.RequestBodySizeInBytes.HasValue) - { - stringBuilder.Append(",\"requestBodySizeInBytes\":"); - stringBuilder.Append(this.RequestBodySizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (this.ResponseMetadataSizeInBytes.HasValue) - { - stringBuilder.Append(",\"responseMetadataSizeInBytes\":"); - stringBuilder.Append(this.ResponseMetadataSizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (this.ResponseBodySizeInBytes.HasValue) - { - stringBuilder.Append(",\"responseBodySizeInBytes\":"); - stringBuilder.Append(this.ResponseBodySizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); - } - - stringBuilder.Append("}"); - } - - private void AppendServiceEndpointStats(StringBuilder stringBuilder) - { - stringBuilder.Append($",\"serviceEndpointStats\":"); - stringBuilder.Append("{"); - if (this.NumberOfInflightRequestsToEndpoint.HasValue) - { - stringBuilder.Append($"\"inflightRequests\":"); - stringBuilder.Append(this.NumberOfInflightRequestsToEndpoint.Value.ToString(CultureInfo.InvariantCulture)); - } - if (this.NumberOfOpenConnectionsToEndpoint.HasValue) - { - stringBuilder.Append($",\"openConnections\":"); - stringBuilder.Append(this.NumberOfOpenConnectionsToEndpoint.Value.ToString(CultureInfo.InvariantCulture)); - } - stringBuilder.Append("}"); - } - - private void AppendConnectionStats(StringBuilder stringBuilder) - { - stringBuilder.Append($",\"connectionStats\":"); - stringBuilder.Append("{"); - if (this.RequestWaitingForConnectionInitialization.HasValue) - { - stringBuilder.Append("\"waitforConnectionInit\":\""); - stringBuilder.Append(this.RequestWaitingForConnectionInitialization.Value.ToString()); - stringBuilder.Append("\""); - } - if (this.NumberOfInflightRequestsInConnection.HasValue) - { - stringBuilder.Append(",\"callsPendingReceive\":"); - stringBuilder.Append(this.NumberOfInflightRequestsInConnection.Value.ToString(CultureInfo.InvariantCulture)); - } - if (this.ConnectionLastSendAttemptTime.HasValue) - { - stringBuilder.Append(",\"lastSendAttempt\":\""); - stringBuilder.Append(this.ConnectionLastSendAttemptTime.Value.ToString("o", CultureInfo.InvariantCulture)); - stringBuilder.Append("\""); - } - if (this.ConnectionLastSendTime.HasValue) - { - stringBuilder.Append(",\"lastSend\":\""); - stringBuilder.Append(this.ConnectionLastSendTime.Value.ToString("o", CultureInfo.InvariantCulture)); - stringBuilder.Append("\""); - } - if (this.ConnectionLastReceiveTime.HasValue) - { - stringBuilder.Append(",\"lastReceive\":\""); - stringBuilder.Append(this.ConnectionLastReceiveTime.Value.ToString("o", CultureInfo.InvariantCulture)); - stringBuilder.Append("\""); - } - stringBuilder.Append("}"); - } - - private static void AppendRequestStats( - StringBuilder stringBuilder, - string eventName, - DateTime requestStartTime, - TimeSpan startTime, - TimeSpan? endTime, - TimeSpan? failedTime) - { - stringBuilder.Append("{\"event\": \""); - stringBuilder.Append(eventName); - stringBuilder.Append("\", \"startTimeUtc\": \""); - stringBuilder.Append((requestStartTime + startTime).ToString("o", CultureInfo.InvariantCulture)); - stringBuilder.Append("\", \"durationInMs\": "); - TimeSpan? duration = endTime ?? failedTime; - if (duration.HasValue) - { - stringBuilder.Append((duration.Value - startTime).TotalMilliseconds.ToString(CultureInfo.InvariantCulture)); - } - else - { - stringBuilder.Append("\"Not Set\""); - } - - stringBuilder.Append("}"); - } - - public enum RequestStage - { - Created, - ChannelAcquisitionStarted, - Pipelined, - Sent, - Received, - Completed, - Failed - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.Text; + + internal sealed class TransportRequestStats + { + private const string RequestStageCreated = "Created"; + private const string RequestStageChannelAcquisitionStarted = "ChannelAcquisitionStarted"; + private const string RequestStagePipelined = "Pipelined"; + private const string RequestStageSent = "Transit Time"; + private const string RequestStageReceived = "Received"; + private const string RequestStageCompleted = "Completed"; + private const string RequestStageFailed = "Failed"; + + private readonly ValueStopwatch stopwatch; + private readonly DateTime requestCreatedTime; + + // measured in TimeSpan from start time + private TimeSpan? channelAcquisitionStartedTime; + private TimeSpan? requestPipelinedTime; + private TimeSpan? requestSentTime; + private TimeSpan? requestReceivedTime; + private TimeSpan? requestCompletedTime; + private TimeSpan? requestFailedTime; + + // New Object created everytime in TransportClient and thus not worrying about thread safety. + public TransportRequestStats() + { + this.CurrentStage = RequestStage.Created; + this.requestCreatedTime = DateTime.UtcNow; + this.stopwatch = ValueStopwatch.StartNew(); + } + + public RequestStage CurrentStage { get; private set; } + + // Request Response Size Stats + public long? RequestSizeInBytes { get; set; } + public long? RequestBodySizeInBytes { get; set; } + public long? ResponseMetadataSizeInBytes { get; set; } + public long? ResponseBodySizeInBytes { get; set; } + + // Service Endpoint Stats (to a single endpoint) + public int? NumberOfInflightRequestsToEndpoint { get; set; } + public int? NumberOfOpenConnectionsToEndpoint { get; set; } // after this request is assigned to a connection + + // Connection Stats (the connection the request is assigned to) + public bool? RequestWaitingForConnectionInitialization { get; set; } + public int? NumberOfInflightRequestsInConnection { get; set; } + public DateTime? ConnectionLastSendAttemptTime { get; set; } + public DateTime? ConnectionLastSendTime { get; set; } + public DateTime? ConnectionLastReceiveTime { get; set; } + + public void RecordState(RequestStage requestStage) + { + TimeSpan elapsedTime = this.stopwatch.Elapsed; + switch (requestStage) + { + case RequestStage.ChannelAcquisitionStarted: + Debug.Assert(this.CurrentStage == RequestStage.Created, + $"Expected Transition from CREATED to CHANNEL_ACQUISITION_STARTED and not from {this.CurrentStage}"); + this.channelAcquisitionStartedTime = elapsedTime; + this.CurrentStage = RequestStage.ChannelAcquisitionStarted; + break; + case RequestStage.Pipelined: + Debug.Assert(this.CurrentStage == RequestStage.ChannelAcquisitionStarted, + $"Expected Transition from CHANNELACQUISITIONSTARTED to PIPELINED and not from {this.CurrentStage}"); + this.requestPipelinedTime = elapsedTime; + this.CurrentStage = RequestStage.Pipelined; + break; + case RequestStage.Sent: + this.requestSentTime = elapsedTime; + this.CurrentStage = RequestStage.Sent; + break; + case RequestStage.Received: + this.requestReceivedTime = elapsedTime; + this.CurrentStage = RequestStage.Received; + break; + case RequestStage.Completed: + this.requestCompletedTime = elapsedTime; + this.CurrentStage = RequestStage.Completed; + break; + case RequestStage.Failed: + this.requestFailedTime = elapsedTime; + this.CurrentStage = RequestStage.Failed; + break; + default: + throw new InvalidOperationException($"No transition to {requestStage}"); + } + } + + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + this.AppendJsonString(stringBuilder); + return stringBuilder.ToString(); + } + + public void AppendJsonString(StringBuilder stringBuilder) + { + stringBuilder.Append("{\"requestTimeline\":["); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageCreated, + this.requestCreatedTime, + TimeSpan.Zero, + this.channelAcquisitionStartedTime, + this.requestFailedTime); + + if (this.channelAcquisitionStartedTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageChannelAcquisitionStarted, + this.requestCreatedTime, + this.channelAcquisitionStartedTime.Value, + this.requestPipelinedTime, + this.requestFailedTime); + } + + if (this.requestPipelinedTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStagePipelined, + this.requestCreatedTime, + this.requestPipelinedTime.Value, + this.requestSentTime, + this.requestFailedTime); + } + + if (this.requestSentTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageSent, + this.requestCreatedTime, + this.requestSentTime.Value, + this.requestReceivedTime, + this.requestFailedTime); + } + + if (this.requestReceivedTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageReceived, + this.requestCreatedTime, + this.requestReceivedTime.Value, + this.requestCompletedTime, + this.requestFailedTime); + } + + if (this.requestCompletedTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageCompleted, + this.requestCreatedTime, + this.requestCompletedTime.Value, + this.requestCompletedTime, + this.requestFailedTime); + } + + if (this.requestFailedTime.HasValue) + { + stringBuilder.Append(","); + TransportRequestStats.AppendRequestStats( + stringBuilder, + TransportRequestStats.RequestStageFailed, + this.requestCreatedTime, + this.requestFailedTime.Value, + this.requestFailedTime, + this.requestFailedTime); + } + + stringBuilder.Append("]"); + + this.AppendServiceEndpointStats(stringBuilder); + this.AppendConnectionStats(stringBuilder); + + if (this.RequestSizeInBytes.HasValue) + { + stringBuilder.Append(",\"requestSizeInBytes\":"); + stringBuilder.Append(this.RequestSizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (this.RequestBodySizeInBytes.HasValue) + { + stringBuilder.Append(",\"requestBodySizeInBytes\":"); + stringBuilder.Append(this.RequestBodySizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (this.ResponseMetadataSizeInBytes.HasValue) + { + stringBuilder.Append(",\"responseMetadataSizeInBytes\":"); + stringBuilder.Append(this.ResponseMetadataSizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (this.ResponseBodySizeInBytes.HasValue) + { + stringBuilder.Append(",\"responseBodySizeInBytes\":"); + stringBuilder.Append(this.ResponseBodySizeInBytes.Value.ToString(CultureInfo.InvariantCulture)); + } + + stringBuilder.Append("}"); + } + + private void AppendServiceEndpointStats(StringBuilder stringBuilder) + { + stringBuilder.Append($",\"serviceEndpointStats\":"); + stringBuilder.Append("{"); + if (this.NumberOfInflightRequestsToEndpoint.HasValue) + { + stringBuilder.Append($"\"inflightRequests\":"); + stringBuilder.Append(this.NumberOfInflightRequestsToEndpoint.Value.ToString(CultureInfo.InvariantCulture)); + } + if (this.NumberOfOpenConnectionsToEndpoint.HasValue) + { + stringBuilder.Append($",\"openConnections\":"); + stringBuilder.Append(this.NumberOfOpenConnectionsToEndpoint.Value.ToString(CultureInfo.InvariantCulture)); + } + stringBuilder.Append("}"); + } + + private void AppendConnectionStats(StringBuilder stringBuilder) + { + stringBuilder.Append($",\"connectionStats\":"); + stringBuilder.Append("{"); + if (this.RequestWaitingForConnectionInitialization.HasValue) + { + stringBuilder.Append("\"waitforConnectionInit\":\""); + stringBuilder.Append(this.RequestWaitingForConnectionInitialization.Value.ToString()); + stringBuilder.Append("\""); + } + if (this.NumberOfInflightRequestsInConnection.HasValue) + { + stringBuilder.Append(",\"callsPendingReceive\":"); + stringBuilder.Append(this.NumberOfInflightRequestsInConnection.Value.ToString(CultureInfo.InvariantCulture)); + } + if (this.ConnectionLastSendAttemptTime.HasValue) + { + stringBuilder.Append(",\"lastSendAttempt\":\""); + stringBuilder.Append(this.ConnectionLastSendAttemptTime.Value.ToString("o", CultureInfo.InvariantCulture)); + stringBuilder.Append("\""); + } + if (this.ConnectionLastSendTime.HasValue) + { + stringBuilder.Append(",\"lastSend\":\""); + stringBuilder.Append(this.ConnectionLastSendTime.Value.ToString("o", CultureInfo.InvariantCulture)); + stringBuilder.Append("\""); + } + if (this.ConnectionLastReceiveTime.HasValue) + { + stringBuilder.Append(",\"lastReceive\":\""); + stringBuilder.Append(this.ConnectionLastReceiveTime.Value.ToString("o", CultureInfo.InvariantCulture)); + stringBuilder.Append("\""); + } + stringBuilder.Append("}"); + } + + private static void AppendRequestStats( + StringBuilder stringBuilder, + string eventName, + DateTime requestStartTime, + TimeSpan startTime, + TimeSpan? endTime, + TimeSpan? failedTime) + { + stringBuilder.Append("{\"event\": \""); + stringBuilder.Append(eventName); + stringBuilder.Append("\", \"startTimeUtc\": \""); + stringBuilder.Append((requestStartTime + startTime).ToString("o", CultureInfo.InvariantCulture)); + stringBuilder.Append("\", \"durationInMs\": "); + TimeSpan? duration = endTime ?? failedTime; + if (duration.HasValue) + { + stringBuilder.Append((duration.Value - startTime).TotalMilliseconds.ToString(CultureInfo.InvariantCulture)); + } + else + { + stringBuilder.Append("\"Not Set\""); + } + + stringBuilder.Append("}"); + } + + public enum RequestStage + { + Created, + ChannelAcquisitionStarted, + Pipelined, + Sent, + Received, + Completed, + Failed + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs b/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs index 0ddfdc2f3c..1cffb5f7f9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs @@ -1,2680 +1,2701 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.IO; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; -#if COSMOSCLIENT - using Microsoft.Azure.Cosmos.Rntbd; -#endif - using Microsoft.Azure.Documents.Collections; - using RequestPool = RntbdConstants.RntbdEntityPool; - - internal static class TransportSerialization - { - // Path format - internal static readonly char[] UrlTrim = { '/' }; - - internal class RntbdHeader - { - public RntbdHeader(StatusCodes status, Guid activityId) - { - this.Status = status; - this.ActivityId = activityId; - } - - public StatusCodes Status { get; private set; } - public Guid ActivityId { get; private set; } - } - - internal sealed class SerializedRequest : IDisposable - { - private readonly BufferProvider.DisposableBuffer requestHeader; - - private readonly CloneableStream requestBody; - - public SerializedRequest(BufferProvider.DisposableBuffer requestHeader, CloneableStream requestBody) - { - this.requestHeader = requestHeader; - this.requestBody = requestBody; - } - - public int RequestSize => this.requestHeader.Buffer.Count + (int)(this.requestBody?.Length ?? 0); - - public void Dispose() - { - this.requestHeader.Dispose(); - this.requestBody?.Dispose(); - } - - /// - /// Copies the contents of the serialized request to the target buffer. - /// - /// - /// This method is not thread-safe. It is assumed that this is the only - /// method writing to this buffer. The caller is responsible for ensuring - /// ownership of the buffer before calling this method. - /// - internal void CopyTo(ArraySegment buffer) - { - if (buffer.Count < this.RequestSize) - { - throw new ArgumentException("Buffer should at least be as big as the request size"); - } - - Array.Copy( - this.requestHeader.Buffer.Array, - this.requestHeader.Buffer.Offset, - buffer.Array, - buffer.Offset, - this.requestHeader.Buffer.Count); - - if (this.requestBody != null) - { - this.requestBody.CopyBufferTo(buffer.Array, buffer.Offset + this.requestHeader.Buffer.Count); - } - } - - /// - /// Copies the contents of the serialized request to the target stream. - /// - /// - /// This method is not thread-safe. It is assumed that this is the only - /// method writing to this stream. The caller is responsible for ensuring - /// ownership of the stream before calling this method. - /// - internal async Task CopyToStreamAsync(Stream stream) - { - await stream.WriteAsync(this.requestHeader.Buffer.Array, this.requestHeader.Buffer.Offset, this.requestHeader.Buffer.Count); - - if (this.requestBody != null) - { - this.requestBody.Position = 0; - await this.requestBody.CopyToAsync(stream); - } - } - } - - /// - /// Builds the RNTBD request needed for the Photon (ThinClient) protocol - /// - internal static SerializedRequest BuildRequestForProxy( - DocumentServiceRequest request, - ResourceOperation resourceOperation, - Guid activityId, - BufferProvider bufferProvider, - string globalDatabaseAccountName, - out int headerSize, - out int? bodySize) - { - if (string.IsNullOrEmpty(globalDatabaseAccountName)) - { - throw new ArgumentNullException(nameof(globalDatabaseAccountName)); - } - - RntbdConstants.Request rntbdRequest = new(); - - // for proxy, transportRequestId and replicapath are optional. - int tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.replicaPath); - rntbdRequest.replicaPath = new RntbdToken(false, rntbdRequest.replicaPath.GetTokenType(), rntbdRequest.replicaPath.GetTokenIdentifier()); - rntbdRequest.tokens[tokenIndex] = rntbdRequest.replicaPath; - - tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.transportRequestID); - rntbdRequest.transportRequestID = new RntbdToken(false, rntbdRequest.transportRequestID.GetTokenType(), rntbdRequest.transportRequestID.GetTokenIdentifier()); - rntbdRequest.tokens[tokenIndex] = rntbdRequest.transportRequestID; - - // make the EPK the first token - tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.effectivePartitionKey); - rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[0]; - rntbdRequest.tokens[0] = rntbdRequest.effectivePartitionKey; - - // Account name is the second token - tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.globalDatabaseAccountName); - rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[1]; - rntbdRequest.tokens[1] = rntbdRequest.globalDatabaseAccountName; - rntbdRequest.globalDatabaseAccountName.value.valueBytes = BytesSerializer.GetBytesForString(globalDatabaseAccountName, rntbdRequest); - rntbdRequest.globalDatabaseAccountName.isPresent = true; - - return BuildRequestCore( - request, - ref rntbdRequest, - replicaPathForDiagnostics: "thinClientReplica", - resourceOperation, - activityId, - bufferProvider, - out headerSize, - out bodySize); - } - - internal static SerializedRequest BuildRequest( - DocumentServiceRequest request, - string replicaPath, - ResourceOperation resourceOperation, - Guid activityId, - BufferProvider bufferProvider, - string transportRequestIDOverride, - out int headerSize, - out int? bodySize) - { - using RequestPool.EntityOwner owner = RequestPool.Instance.Get(); - RntbdConstants.Request rntbdRequest = owner.Entity; - - rntbdRequest.replicaPath.value.valueBytes = BytesSerializer.GetBytesForString(replicaPath, rntbdRequest); - rntbdRequest.replicaPath.isPresent = true; - - //When timeouts occur, "request" or requestHeaders can end up being referenced by multiple threads. - // Passing in TransportId as a parameter instead of using the property on the requestHeaders helps - // to prevent race conditions where the requestHeader property for one thread could be mutate by another. - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TransportRequestID, transportRequestIDOverride, rntbdRequest.transportRequestID, rntbdRequest); - - return BuildRequestCore( - request, - ref rntbdRequest, - replicaPath, - resourceOperation, - activityId, - bufferProvider, - out headerSize, - out bodySize); - } - - private static SerializedRequest BuildRequestCore( - DocumentServiceRequest request, - ref RntbdConstants.Request rntbdRequest, - string replicaPathForDiagnostics, - ResourceOperation resourceOperation, - Guid activityId, - BufferProvider bufferProvider, - out int headerSize, - out int? bodySize) - { - RntbdConstants.RntbdOperationType operationType = GetRntbdOperationType(resourceOperation.operationType); - RntbdConstants.RntbdResourceType resourceType = GetRntbdResourceType(resourceOperation.resourceType); - - // NOTE: when request.Headers is a "RequestNameValueCollection", requestHeaders is a reference to request.Headers - // and not a clone. It's important to keep this in mind when dealing with multiple threads that share the - // same request object. - if (request.Headers is not RequestNameValueCollection requestHeaders) - { - requestHeaders = RequestNameValueCollection.BuildRequestNameValueCollectionWithKnownHeadersOnly(request.Headers); - } - - // special-case headers (ones that don't come from request.headers, or ones that are a merge of - // merging multiple request.headers, or ones that are parsed from a string to an enum). - TransportSerialization.AddResourceIdOrPathHeaders(request, rntbdRequest); - TransportSerialization.AddDateHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddContinuation(requestHeaders, rntbdRequest); - TransportSerialization.AddMatchHeader(requestHeaders, operationType, rntbdRequest); - TransportSerialization.AddIfModifiedSinceHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddA_IMHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddIndexingDirectiveHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddMigrateCollectionDirectiveHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddConsistencyLevelHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddIsFanout(requestHeaders, rntbdRequest); - TransportSerialization.AddEntityId(request, rntbdRequest); - TransportSerialization.AddAllowScanOnQuery(requestHeaders, rntbdRequest); - TransportSerialization.AddEmitVerboseTracesInQuery(requestHeaders, rntbdRequest); - TransportSerialization.AddCanCharge(requestHeaders, rntbdRequest); - TransportSerialization.AddCanThrottle(requestHeaders, rntbdRequest); - TransportSerialization.AddProfileRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddEnableLowPrecisionOrderBy(requestHeaders, rntbdRequest); - TransportSerialization.AddPageSize(requestHeaders, rntbdRequest); - TransportSerialization.AddSupportSpatialLegacyCoordinates(requestHeaders, rntbdRequest); - TransportSerialization.AddUsePolygonsSmallerThanAHemisphere(requestHeaders, rntbdRequest); - TransportSerialization.AddEnableLogging(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateQuotaInfo(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateResourceCount(requestHeaders, rntbdRequest); - TransportSerialization.AddDisableRUPerMinuteUsage(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateQueryMetrics(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateQueryMetricsIndexUtilization(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateIndexMetricsV2(requestHeaders, rntbdRequest); - TransportSerialization.AddOptimisticDirectExecute(requestHeaders, rntbdRequest); - TransportSerialization.AddQueryForceScan(requestHeaders, rntbdRequest); - TransportSerialization.AddResponseContinuationTokenLimitInKb(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulatePartitionStatistics(requestHeaders, rntbdRequest); - TransportSerialization.AddRemoteStorageType(requestHeaders, rntbdRequest); - TransportSerialization.AddCollectionRemoteStorageSecurityIdentifier(requestHeaders, rntbdRequest); - TransportSerialization.AddCollectionChildResourceNameLimitInBytes(requestHeaders, rntbdRequest); - TransportSerialization.AddCollectionChildResourceContentLengthLimitInKB(requestHeaders, rntbdRequest); - TransportSerialization.AddUniqueIndexNameEncodingMode(requestHeaders, rntbdRequest); - TransportSerialization.AddUniqueIndexReIndexingState(requestHeaders, rntbdRequest); - TransportSerialization.AddCorrelatedActivityId(requestHeaders, rntbdRequest); - TransportSerialization.AddPopulateCollectionThroughputInfo(requestHeaders, rntbdRequest); - TransportSerialization.AddShareThroughput(requestHeaders, rntbdRequest); - TransportSerialization.AddIsReadOnlyScript(requestHeaders, rntbdRequest); -#if !COSMOSCLIENT - TransportSerialization.AddIsAutoScaleRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddIsServerlessEnabledStorageRefreshRequest(requestHeaders, rntbdRequest); -#endif - TransportSerialization.AddCanOfferReplaceComplete(requestHeaders, rntbdRequest); - TransportSerialization.AddIgnoreSystemLoweringMaxThroughput(requestHeaders, rntbdRequest); - TransportSerialization.AddExcludeSystemProperties(requestHeaders, rntbdRequest); - TransportSerialization.AddEnumerationDirection(request, requestHeaders, rntbdRequest); - TransportSerialization.AddFanoutOperationStateHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddStartAndEndKeys(request, requestHeaders, rntbdRequest); - TransportSerialization.AddContentSerializationFormat(requestHeaders, rntbdRequest); - TransportSerialization.AddSupportedSerializationFormats(requestHeaders, rntbdRequest); - TransportSerialization.AddIsUserRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddPreserveFullContent(requestHeaders, rntbdRequest); - TransportSerialization.AddIsRUPerGBEnforcementRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddIsOfferStorageRefreshRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddGetAllPartitionKeyStatistics(requestHeaders, rntbdRequest); - TransportSerialization.AddForceSideBySideIndexMigration(requestHeaders, rntbdRequest); - TransportSerialization.AddIsMigrateOfferToManualThroughputRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddIsMigrateOfferToAutopilotRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddSystemDocumentTypeHeader(requestHeaders, rntbdRequest); - TransportSerialization.AddTransactionMetaData(request, rntbdRequest); - TransportSerialization.AddTransactionCompletionFlag(request, rntbdRequest); - TransportSerialization.AddResourceTypes(requestHeaders, rntbdRequest); - TransportSerialization.AddUpdateMaxthroughputEverProvisioned(requestHeaders, rntbdRequest); - TransportSerialization.AddUseSystemBudget(requestHeaders, rntbdRequest); - TransportSerialization.AddTruncateMergeLogRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddRetriableWriteRequestMetadata(request, rntbdRequest); - TransportSerialization.AddRequestedCollectionType(requestHeaders, rntbdRequest); - TransportSerialization.AddIsThroughputCapRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddUpdateOfferStateToPending(requestHeaders, rntbdRequest); - TransportSerialization.AddUpdateOfferStateToRestorePending(requestHeaders, rntbdRequest); - TransportSerialization.AddMasterResourcesDeletionPending(requestHeaders, rntbdRequest); - TransportSerialization.AddIsInternalServerlessRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddOfferReplaceRURedistribution(requestHeaders, rntbdRequest); - TransportSerialization.AddIsMaterializedViewSourceSchemaReplaceBatchRequest(requestHeaders, rntbdRequest); - TransportSerialization.AddIsCassandraAlterTypeRequest(request, rntbdRequest); - TransportSerialization.AddHighPriorityForcedBackup(requestHeaders, rntbdRequest); - TransportSerialization.AddEnableConflictResolutionPolicyUpdate(requestHeaders, rntbdRequest); - TransportSerialization.AddAllowDocumentReadsInOfflineRegion(requestHeaders, rntbdRequest); - - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.Authorization, requestHeaders.Authorization, rntbdRequest.authorizationToken, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SessionToken, requestHeaders.SessionToken, rntbdRequest.sessionToken, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PreTriggerInclude, requestHeaders.PreTriggerInclude, rntbdRequest.preTriggerInclude, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PreTriggerExclude, requestHeaders.PreTriggerExclude, rntbdRequest.preTriggerExclude, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PostTriggerInclude, requestHeaders.PostTriggerInclude, rntbdRequest.postTriggerInclude, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PostTriggerExclude, requestHeaders.PostTriggerExclude, rntbdRequest.postTriggerExclude, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PartitionKey, requestHeaders.PartitionKey, rntbdRequest.partitionKey, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PartitionKeyRangeId, requestHeaders.PartitionKeyRangeId, rntbdRequest.partitionKeyRangeId, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ResourceTokenExpiry, requestHeaders.ResourceTokenExpiry, rntbdRequest.resourceTokenExpiry, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.FilterBySchemaResourceId, requestHeaders.FilterBySchemaResourceId, rntbdRequest.filterBySchemaRid, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ShouldBatchContinueOnError, requestHeaders.ShouldBatchContinueOnError, rntbdRequest.shouldBatchContinueOnError, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsBatchOrdered, requestHeaders.IsBatchOrdered, rntbdRequest.isBatchOrdered, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsBatchAtomic, requestHeaders.IsBatchAtomic, rntbdRequest.isBatchAtomic, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionPartitionIndex, requestHeaders.CollectionPartitionIndex, rntbdRequest.collectionPartitionIndex, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionServiceIndex, requestHeaders.CollectionServiceIndex, rntbdRequest.collectionServiceIndex, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.ResourceSchemaName, requestHeaders.ResourceSchemaName, rntbdRequest.resourceSchemaName, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.BindReplicaDirective, requestHeaders.BindReplicaDirective, rntbdRequest.bindReplicaDirective, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PrimaryMasterKey, requestHeaders.PrimaryMasterKey, rntbdRequest.primaryMasterKey, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SecondaryMasterKey, requestHeaders.SecondaryMasterKey, rntbdRequest.secondaryMasterKey, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PrimaryReadonlyKey, requestHeaders.PrimaryReadonlyKey, rntbdRequest.primaryReadonlyKey, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SecondaryReadonlyKey, requestHeaders.SecondaryReadonlyKey, rntbdRequest.secondaryReadonlyKey, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PartitionCount, requestHeaders.PartitionCount, rntbdRequest.partitionCount, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionRid, requestHeaders.CollectionRid, rntbdRequest.collectionRid, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.GatewaySignature, requestHeaders.GatewaySignature, rntbdRequest.gatewaySignature, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, requestHeaders.RemainingTimeInMsOnClientRequest, rntbdRequest.remainingTimeInMsOnClientRequest, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ClientRetryAttemptCount, requestHeaders.ClientRetryAttemptCount, rntbdRequest.clientRetryAttemptCount, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TargetLsn, requestHeaders.TargetLsn, rntbdRequest.targetLsn, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, requestHeaders.TargetGlobalCommittedLsn, rntbdRequest.targetGlobalCommittedLsn, rntbdRequest); - - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RestoreMetadataFilter, requestHeaders.RestoreMetadataFilter, rntbdRequest.restoreMetadataFilter, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.RestoreParams, requestHeaders.RestoreParams, rntbdRequest.restoreParams, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PartitionResourceFilter, requestHeaders.PartitionResourceFilter, rntbdRequest.partitionResourceFilter, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, requestHeaders.EnableDynamicRidRangeAllocation, rntbdRequest.enableDynamicRidRangeAllocation, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaOwnerRid, requestHeaders.SchemaOwnerRid, rntbdRequest.schemaOwnerRid, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaHash, requestHeaders.SchemaHash, rntbdRequest.schemaHash, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaId, requestHeaders.SchemaId, rntbdRequest.collectionSchemaId, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsClientEncrypted, requestHeaders.IsClientEncrypted, rntbdRequest.isClientEncrypted, rntbdRequest); - - TransportSerialization.AddReturnPreferenceIfPresent(requestHeaders, rntbdRequest); - TransportSerialization.AddBinaryIdIfPresent(request, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.TimeToLiveInSeconds, requestHeaders.TimeToLiveInSeconds, rntbdRequest.timeToLiveInSeconds, rntbdRequest); - TransportSerialization.AddEffectivePartitionKeyIfPresent(request, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.BinaryPassthroughRequest, requestHeaders.BinaryPassthroughRequest, rntbdRequest.binaryPassthroughRequest, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.AllowTentativeWrites, requestHeaders.AllowTentativeWrites, rntbdRequest.allowTentativeWrites, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IncludeTentativeWrites, requestHeaders.IncludeTentativeWrites, rntbdRequest.includeTentativeWrites, rntbdRequest); TransportSerialization.AddMergeStaticIdIfPresent(request, rntbdRequest); - TransportSerialization.AddMergeStaticIdIfPresent(request, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, requestHeaders.MaxPollingIntervalMilliseconds, rntbdRequest.maxPollingIntervalMilliseconds, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateLogStoreInfo, requestHeaders.PopulateLogStoreInfo, rntbdRequest.populateLogStoreInfo, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.MergeCheckPointGLSN, requestHeaders.MergeCheckPointGLSN, rntbdRequest.mergeCheckpointGLSNKeyName, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, requestHeaders.PopulateUnflushedMergeEntryCount, rntbdRequest.populateUnflushedMergeEntryCount, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.AddResourcePropertiesToResponse, requestHeaders.AddResourcePropertiesToResponse, rntbdRequest.addResourcePropertiesToResponse, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SystemRestoreOperation, requestHeaders.SystemRestoreOperation, rntbdRequest.systemRestoreOperation, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, requestHeaders.ChangeFeedStartFullFidelityIfNoneMatch, rntbdRequest.changeFeedStartFullFidelityIfNoneMatch, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, requestHeaders.SkipRefreshDatabaseAccountConfigs, rntbdRequest.skipRefreshDatabaseAccountConfigs, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.IntendedCollectionRid, requestHeaders.IntendedCollectionRid, rntbdRequest.intendedCollectionRid, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.UseArchivalPartition, requestHeaders.UseArchivalPartition, rntbdRequest.useArchivalPartition, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.CollectionTruncate, requestHeaders.CollectionTruncate, rntbdRequest.collectionTruncate, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SDKSupportedCapabilities, requestHeaders.SDKSupportedCapabilities, rntbdRequest.sDKSupportedCapabilities, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, requestHeaders.PopulateUniqueIndexReIndexProgress, rntbdRequest.populateUniqueIndexReIndexProgress, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsMaterializedViewBuild, requestHeaders.IsMaterializedViewBuild, rntbdRequest.isMaterializedViewBuild, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.BuilderClientIdentifier, requestHeaders.BuilderClientIdentifier, rntbdRequest.builderClientIdentifier, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SourceCollectionIfMatch, requestHeaders.SourceCollectionIfMatch, rntbdRequest.sourceCollectionIfMatch, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, requestHeaders.PopulateAnalyticalMigrationProgress, rntbdRequest.populateAnalyticalMigrationProgress, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, requestHeaders.ShouldReturnCurrentServerDateTime, rntbdRequest.shouldReturnCurrentServerDateTime, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacUserId, requestHeaders.RbacUserId, rntbdRequest.rbacUserId, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacAction, requestHeaders.RbacAction, rntbdRequest.rbacAction, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacResource, requestHeaders.RbacResource, rntbdRequest.rbacResource, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, requestHeaders.ChangeFeedWireFormatVersion, rntbdRequest.changeFeedWireFormatVersion, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, requestHeaders.PopulateByokEncryptionProgress, rntbdRequest.populateBYOKEncryptionProgress, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.UseUserBackgroundBudget, requestHeaders.UseUserBackgroundBudget, rntbdRequest.useUserBackgroundBudget, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, requestHeaders.IncludePhysicalPartitionThroughputInfo, rntbdRequest.includePhysicalPartitionThroughputInfo, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, requestHeaders.PopulateOldestActiveSchemaId, rntbdRequest.populateOldestActiveSchemaId, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, requestHeaders.ForceDatabaseAccountUpdate, rntbdRequest.forceDatabaseAccountUpdate, rntbdRequest); - TransportSerialization.AddPriorityLevelHeader(request, HttpConstants.HttpHeaders.PriorityLevel, requestHeaders.PriorityLevel, requestHeaders, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, requestHeaders.AllowRestoreParamsUpdate, rntbdRequest.allowRestoreParamsUpdate, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PruneCollectionSchemas, requestHeaders.PruneCollectionSchemas, rntbdRequest.pruneCollectionSchemas, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsMigratedFixedCollection, requestHeaders.IsMigratedFixedCollection, rntbdRequest.isMigratedFixedCollection, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, requestHeaders.PopulateMinGLSNForDocumentOperations, rntbdRequest.populateMinGLSNForDocumentOperations, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, requestHeaders.PopulateHighestTentativeWriteLLSN, rntbdRequest.populateHighestTentativeWriteLLSN, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCapacityType, requestHeaders.PopulateCapacityType, rntbdRequest.populateCapacityType, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceParent, requestHeaders.TraceParent, rntbdRequest.traceParent, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceState, requestHeaders.TraceState, rntbdRequest.traceState, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.ClientIpAddress, requestHeaders.ClientIpAddress, rntbdRequest.clientIpAddress, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.IsRequestNotAuthorized, requestHeaders.IsRequestNotAuthorized, rntbdRequest.isRequestNotAuthorized, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.StartEpkHash, headerStringValue: null, rntbdRequest.startEpkHash, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.EndEpkHash, headerStringValue: null, rntbdRequest.endEpkHash, rntbdRequest); - TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, requestHeaders.PopulateCurrentPartitionThroughputInfo, rntbdRequest.populateCurrentPartitionThroughputInfo, rntbdRequest); - - // will be null in case of direct, which is fine - BE will use the value from the connection context message. - // When this is used in Gateway, the header value will be populated with the proxied HTTP request's header, and - // BE will respect the per-request value. - TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.Version, requestHeaders.Version, rntbdRequest.clientVersion, rntbdRequest); - - int metadataLength = (sizeof(uint) + sizeof(ushort) + sizeof(ushort) + BytesSerializer.GetSizeOfGuid()); - int headerAndMetadataLength = metadataLength; - - int allocationLength = 0; - - bodySize = null; - int bodyLength = 0; - CloneableStream clonedStream = null; - if (request.CloneableBody != null) - { - clonedStream = request.CloneableBody.Clone(); - bodyLength = (int)clonedStream.Length; - } - - BufferProvider.DisposableBuffer contextMessage; - - if (bodyLength > 0) - { - allocationLength += sizeof(uint); - - rntbdRequest.payloadPresent.value.valueByte = 0x01; - rntbdRequest.payloadPresent.isPresent = true; - } - else - { - rntbdRequest.payloadPresent.value.valueByte = 0x00; - rntbdRequest.payloadPresent.isPresent = true; - } - - // Once all metadata tokens are set, we can calculate the length. - headerAndMetadataLength += rntbdRequest.CalculateLength(); // metadata tokens - allocationLength += headerAndMetadataLength; - - contextMessage = bufferProvider.GetBuffer(allocationLength); - - BytesSerializer writer = new BytesSerializer(contextMessage.Buffer.Array, allocationLength); - - // header - writer.Write((uint)headerAndMetadataLength); - writer.Write((ushort)resourceType); - writer.Write((ushort)operationType); - writer.Write(activityId); - int actualWritten = metadataLength; - - // metadata - rntbdRequest.SerializeToBinaryWriter(ref writer, out int tokensLength); - actualWritten += tokensLength; - - if (actualWritten != headerAndMetadataLength) - { - clonedStream?.Dispose(); - DefaultTrace.TraceCritical( - "Bug in RNTBD token serialization. Calculated header size: {0}. Actual header size: {1}", - headerAndMetadataLength, actualWritten); - throw new InternalServerErrorException(); - } - - if (bodyLength > 0) - { - writer.Write((UInt32)bodyLength); - bodySize = sizeof(UInt32) + bodyLength; - } - - headerSize = headerAndMetadataLength; - - const int HeaderSizeWarningThreshold = 128 * 1024; - const int BodySizeWarningThreshold = 16 * 1024 * 1024; - if (headerSize > HeaderSizeWarningThreshold) - { - DefaultTrace.TraceWarning( - "The request header is large. Header size: {0}. Warning threshold: {1}. " + - "RID: {2}. Resource type: {3}. Operation: {4}. Address: {5}", - headerSize, HeaderSizeWarningThreshold, request.ResourceAddress, - request.ResourceType, resourceOperation, replicaPathForDiagnostics); - } - if (bodySize > BodySizeWarningThreshold) - { - DefaultTrace.TraceWarning( - "The request body is large. Body size: {0}. Warning threshold: {1}. " + - "RID: {2}. Resource type: {3}. Operation: {4}. Address: {5}", - bodySize, BodySizeWarningThreshold, request.ResourceAddress, - request.ResourceType, resourceOperation, replicaPathForDiagnostics); - } - - return new SerializedRequest(contextMessage, clonedStream); - } - - internal static byte[] BuildContextRequest(Guid activityId, UserAgentContainer userAgent, RntbdConstants.CallerId callerId, bool enableChannelMultiplexing) - { - byte[] activityIdBytes = activityId.ToByteArray(); - - RntbdConstants.ConnectionContextRequest request = new RntbdConstants.ConnectionContextRequest(); - request.protocolVersion.value.valueULong = RntbdConstants.CurrentProtocolVersion; - request.protocolVersion.isPresent = true; - - request.clientVersion.value.valueBytes = HttpConstants.Versions.CurrentVersionUTF8; - request.clientVersion.isPresent = true; - - request.userAgent.value.valueBytes = userAgent.UserAgentUTF8; - request.userAgent.isPresent = true; - - request.callerId.isPresent = false; - if(callerId != RntbdConstants.CallerId.Invalid) - { - request.callerId.value.valueByte = (byte)callerId; - request.callerId.isPresent = true; - } - - request.enableChannelMultiplexing.isPresent = true; - request.enableChannelMultiplexing.value.valueByte = enableChannelMultiplexing ? (byte)1 : (byte)0; - - int length = (sizeof(UInt32) + sizeof(UInt16) + sizeof(UInt16) + activityIdBytes.Length); // header - length += request.CalculateLength(); // tokens - - byte[] contextMessage = new byte[length]; - - BytesSerializer writer = new BytesSerializer(contextMessage, length); - - // header - writer.Write(length); - writer.Write((ushort)RntbdConstants.RntbdResourceType.Connection); - writer.Write((ushort)RntbdConstants.RntbdOperationType.Connection); - writer.Write(activityIdBytes); - - // metadata - request.SerializeToBinaryWriter(ref writer, out _); - - return contextMessage; - } - - internal static StoreResponse MakeStoreResponse( - StatusCodes status, - Guid activityId, - Stream body, - string serverVersion, - ref BytesDeserializer rntbdHeaderReader) => new() - { - Headers = HeadersTransportSerialization.BuildStoreResponseNameValueCollection( - activityId, - serverVersion, - ref rntbdHeaderReader), - ResponseBody = body, - Status = (int)status - }; - - internal static RntbdHeader DecodeRntbdHeader(byte[] header) - { - StatusCodes status = (StatusCodes) BitConverter.ToUInt32(header, 4); - Guid activityId = BytesSerializer.ReadGuidFromBytes(new ArraySegment(header, 8, 16)); - return new RntbdHeader(status, activityId); - } - - private static RntbdConstants.RntbdOperationType GetRntbdOperationType(OperationType operationType) - { - switch (operationType) - { - case OperationType.Create: - return RntbdConstants.RntbdOperationType.Create; - case OperationType.Delete: - return RntbdConstants.RntbdOperationType.Delete; - case OperationType.ExecuteJavaScript: - return RntbdConstants.RntbdOperationType.ExecuteJavaScript; - case OperationType.Query: - return RntbdConstants.RntbdOperationType.Query; - case OperationType.Read: - return RntbdConstants.RntbdOperationType.Read; - case OperationType.ReadFeed: - return RntbdConstants.RntbdOperationType.ReadFeed; - case OperationType.Replace: - return RntbdConstants.RntbdOperationType.Replace; - case OperationType.SqlQuery: - return RntbdConstants.RntbdOperationType.SQLQuery; - case OperationType.Patch: - return RntbdConstants.RntbdOperationType.Patch; - case OperationType.Head: - return RntbdConstants.RntbdOperationType.Head; - case OperationType.HeadFeed: - return RntbdConstants.RntbdOperationType.HeadFeed; - case OperationType.Upsert: - return RntbdConstants.RntbdOperationType.Upsert; - case OperationType.BatchApply: - return RntbdConstants.RntbdOperationType.BatchApply; - case OperationType.Batch: - return RntbdConstants.RntbdOperationType.Batch; - case OperationType.CompleteUserTransaction: - return RntbdConstants.RntbdOperationType.CompleteUserTransaction; - case OperationType.MetadataCheckAccess: - return RntbdConstants.RntbdOperationType.MetadataCheckAccess; -#if !COSMOSCLIENT - case OperationType.Crash: - return RntbdConstants.RntbdOperationType.Crash; - case OperationType.Pause: - return RntbdConstants.RntbdOperationType.Pause; - case OperationType.Recreate: - return RntbdConstants.RntbdOperationType.Recreate; - case OperationType.Recycle: - return RntbdConstants.RntbdOperationType.Recycle; - case OperationType.Resume: - return RntbdConstants.RntbdOperationType.Resume; - case OperationType.Stop: - return RntbdConstants.RntbdOperationType.Stop; - case OperationType.ForceConfigRefresh: - return RntbdConstants.RntbdOperationType.ForceConfigRefresh; - case OperationType.Throttle: - return RntbdConstants.RntbdOperationType.Throttle; - case OperationType.PreCreateValidation: - return RntbdConstants.RntbdOperationType.PreCreateValidation; - case OperationType.GetSplitPoint: - return RntbdConstants.RntbdOperationType.GetSplitPoint; - case OperationType.AbortSplit: - return RntbdConstants.RntbdOperationType.AbortSplit; - case OperationType.CompleteSplit: - return RntbdConstants.RntbdOperationType.CompleteSplit; - case OperationType.CompleteMergeOnMaster: - return RntbdConstants.RntbdOperationType.CompleteMergeOnMaster; - case OperationType.CompleteMergeOnTarget: - return RntbdConstants.RntbdOperationType.CompleteMergeOnTarget; - case OperationType.OfferUpdateOperation: - return RntbdConstants.RntbdOperationType.OfferUpdateOperation; - case OperationType.OfferPreGrowValidation: - return RntbdConstants.RntbdOperationType.OfferPreGrowValidation; - case OperationType.BatchReportThroughputUtilization: - return RntbdConstants.RntbdOperationType.BatchReportThroughputUtilization; - case OperationType.AbortPartitionMigration: - return RntbdConstants.RntbdOperationType.AbortPartitionMigration; - case OperationType.CompletePartitionMigration: - return RntbdConstants.RntbdOperationType.CompletePartitionMigration; - case OperationType.PreReplaceValidation: - return RntbdConstants.RntbdOperationType.PreReplaceValidation; - case OperationType.MigratePartition: - return RntbdConstants.RntbdOperationType.MigratePartition; - case OperationType.MasterReplaceOfferOperation: - return RntbdConstants.RntbdOperationType.MasterReplaceOfferOperation; - case OperationType.ProvisionedCollectionOfferUpdateOperation: - return RntbdConstants.RntbdOperationType.ProvisionedCollectionOfferUpdateOperation; - case OperationType.InitiateDatabaseOfferPartitionShrink: - return RntbdConstants.RntbdOperationType.InitiateDatabaseOfferPartitionShrink; - case OperationType.CompleteDatabaseOfferPartitionShrink: - return RntbdConstants.RntbdOperationType.CompleteDatabaseOfferPartitionShrink; - case OperationType.EnsureSnapshotOperation: - return RntbdConstants.RntbdOperationType.EnsureSnapshotOperation; - case OperationType.GetSplitPoints: - return RntbdConstants.RntbdOperationType.GetSplitPoints; - case OperationType.ForcePartitionBackup: - return RntbdConstants.RntbdOperationType.ForcePartitionBackup; - case OperationType.MasterInitiatedProgressCoordination: - return RntbdConstants.RntbdOperationType.MasterInitiatedProgressCoordination; - case OperationType.CreateSystemSnapshot: - return RntbdConstants.RntbdOperationType.CreateSystemSnapshot; - case OperationType.CreateRidRangeResources: - return RntbdConstants.RntbdOperationType.CreateRidRangeResources; - case OperationType.UpdateFailoverPriorityList: - return RntbdConstants.RntbdOperationType.UpdateFailoverPriorityList; - case OperationType.GetStorageAuthToken: - return RntbdConstants.RntbdOperationType.GetStorageAuthToken; - case OperationType.UpdatePartitionThroughput: - return RntbdConstants.RntbdOperationType.UpdatePartitionThroughput; - case OperationType.Truncate: - return RntbdConstants.RntbdOperationType.Truncate; -#endif - case OperationType.AddComputeGatewayRequestCharges: - return RntbdConstants.RntbdOperationType.AddComputeGatewayRequestCharges; - default: - throw new ArgumentException( - string.Format(CultureInfo.InvariantCulture, "Invalid operation type: {0}", operationType), - "operationType"); - } - } - - private static RntbdConstants.RntbdResourceType GetRntbdResourceType(ResourceType resourceType) - { - switch (resourceType) - { - case ResourceType.Attachment: - return RntbdConstants.RntbdResourceType.Attachment; - case ResourceType.Collection: - return RntbdConstants.RntbdResourceType.Collection; - case ResourceType.Conflict: - return RntbdConstants.RntbdResourceType.Conflict; - case ResourceType.Database: - return RntbdConstants.RntbdResourceType.Database; - case ResourceType.Document: - return RntbdConstants.RntbdResourceType.Document; - case ResourceType.Record: - return RntbdConstants.RntbdResourceType.Record; - case ResourceType.Permission: - return RntbdConstants.RntbdResourceType.Permission; - case ResourceType.StoredProcedure: - return RntbdConstants.RntbdResourceType.StoredProcedure; - case ResourceType.Trigger: - return RntbdConstants.RntbdResourceType.Trigger; - case ResourceType.User: - return RntbdConstants.RntbdResourceType.User; - case ResourceType.ClientEncryptionKey: - return RntbdConstants.RntbdResourceType.ClientEncryptionKey; - case ResourceType.UserDefinedType: - return RntbdConstants.RntbdResourceType.UserDefinedType; - case ResourceType.UserDefinedFunction: - return RntbdConstants.RntbdResourceType.UserDefinedFunction; - case ResourceType.Offer: - return RntbdConstants.RntbdResourceType.Offer; - case ResourceType.DatabaseAccount: - return RntbdConstants.RntbdResourceType.DatabaseAccount; - case ResourceType.PartitionKeyRange: - return RntbdConstants.RntbdResourceType.PartitionKeyRange; - case ResourceType.Schema: - return RntbdConstants.RntbdResourceType.Schema; - case ResourceType.BatchApply: - return RntbdConstants.RntbdResourceType.BatchApply; - case ResourceType.ComputeGatewayCharges: - return RntbdConstants.RntbdResourceType.ComputeGatewayCharges; - case ResourceType.PartitionKey: - return RntbdConstants.RntbdResourceType.PartitionKey; - case ResourceType.PartitionedSystemDocument: - return RntbdConstants.RntbdResourceType.PartitionedSystemDocument; - case ResourceType.SystemDocument: - return RntbdConstants.RntbdResourceType.SystemDocument; - case ResourceType.RoleDefinition: - return RntbdConstants.RntbdResourceType.RoleDefinition; - case ResourceType.RoleAssignment: - return RntbdConstants.RntbdResourceType.RoleAssignment; - case ResourceType.Transaction: - return RntbdConstants.RntbdResourceType.Transaction; - case ResourceType.InteropUser: - return RntbdConstants.RntbdResourceType.InteropUser; - case ResourceType.AuthPolicyElement: - return RntbdConstants.RntbdResourceType.AuthPolicyElement; - case ResourceType.RetriableWriteCachedResponse: - return RntbdConstants.RntbdResourceType.RetriableWriteCachedResponse; - case ResourceType.EncryptionScope: - return RntbdConstants.RntbdResourceType.EncryptionScope; -#if !COSMOSCLIENT - case ResourceType.Module: - return RntbdConstants.RntbdResourceType.Module; - case ResourceType.ModuleCommand: - return RntbdConstants.RntbdResourceType.ModuleCommand; - case ResourceType.TransportControlCommand: - return RntbdConstants.RntbdResourceType.TransportControlCommand; - case ResourceType.Replica: - return RntbdConstants.RntbdResourceType.Replica; - case ResourceType.PartitionSetInformation: - return RntbdConstants.RntbdResourceType.PartitionSetInformation; - case ResourceType.XPReplicatorAddress: - return RntbdConstants.RntbdResourceType.XPReplicatorAddress; - case ResourceType.MasterPartition: - return RntbdConstants.RntbdResourceType.MasterPartition; - case ResourceType.ServerPartition: - return RntbdConstants.RntbdResourceType.ServerPartition; - case ResourceType.Topology: - return RntbdConstants.RntbdResourceType.Topology; - case ResourceType.RestoreMetadata: - return RntbdConstants.RntbdResourceType.RestoreMetadata; - case ResourceType.RidRange: - return RntbdConstants.RntbdResourceType.RidRange; - case ResourceType.VectorClock: - return RntbdConstants.RntbdResourceType.VectorClock; - case ResourceType.Snapshot: - return RntbdConstants.RntbdResourceType.Snapshot; - case ResourceType.StorageAuthToken: - return RntbdConstants.RntbdResourceType.StorageAuthToken; - -#endif - default: - throw new ArgumentException( - string.Format(CultureInfo.InvariantCulture, "Invalid resource type: {0}", resourceType), - "resourceType"); - } - } - - private static void AddMatchHeader(RequestNameValueCollection requestHeaders, RntbdConstants.RntbdOperationType operationType, RntbdConstants.Request rntbdRequest) - { - string match; - switch (operationType) - { - case RntbdConstants.RntbdOperationType.Read: - case RntbdConstants.RntbdOperationType.ReadFeed: - match = requestHeaders.IfNoneMatch; - break; - default: - match = requestHeaders.IfMatch; - break; - } - - if (!string.IsNullOrEmpty(match)) - { - rntbdRequest.match.value.valueBytes = BytesSerializer.GetBytesForString(match, rntbdRequest); - rntbdRequest.match.isPresent = true; - } - } - - private static void AddIfModifiedSinceHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.IfModifiedSince; - if (!string.IsNullOrEmpty(headerValue)) - { - rntbdRequest.ifModifiedSince.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); - rntbdRequest.ifModifiedSince.isPresent = true; - } - } - - private static void AddA_IMHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.A_IM; - if (!string.IsNullOrEmpty(headerValue)) - { - rntbdRequest.a_IM.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); - rntbdRequest.a_IM.isPresent = true; - } - } - - private static void AddDateHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string dateHeader = Helpers.GetDateHeader(requestHeaders); - if (!string.IsNullOrEmpty(dateHeader)) - { - rntbdRequest.date.value.valueBytes = BytesSerializer.GetBytesForString(dateHeader, rntbdRequest); - rntbdRequest.date.isPresent = true; - } - } - - private static void AddContinuation(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.Continuation)) - { - rntbdRequest.continuationToken.value.valueBytes = BytesSerializer.GetBytesForString(requestHeaders.Continuation, rntbdRequest); - rntbdRequest.continuationToken.isPresent = true; - } - } - - private static void AddResourceIdOrPathHeaders(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(request.ResourceId)) - { - // name based can also have ResourceId because gateway might generate it. - rntbdRequest.resourceId.value.valueBytes = ResourceId.Parse(request.ResourceType, request.ResourceId); - rntbdRequest.resourceId.isPresent = true; - } - - if (request.IsNameBased) - { - // short-cut, if resourcetype == document, and the names are parsed out of the URI then use parsed values and avoid - // reparsing and allocating. - if (request.ResourceType == ResourceType.Document && request.IsResourceNameParsedFromUri) - { - TransportSerialization.SetResourceIdHeadersFromDocumentServiceRequest(request, rntbdRequest); - } - else - { - TransportSerialization.SetResourceIdHeadersFromUri(request, rntbdRequest); - } - } - } - - private static void SetResourceIdHeadersFromUri(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - // Assumption: format is like "dbs/dbName/colls/collName/docs/docName" or "/dbs/dbName/colls/collName", - // not "apps/appName/partitions/partitionKey/replicas/replicaId/dbs/dbName" - string[] fragments = request.ResourceAddress.Split( - TransportSerialization.UrlTrim, - StringSplitOptions.RemoveEmptyEntries); - - if (fragments.Length >= 2) - { - switch (fragments[0]) - { - case Paths.DatabasesPathSegment: - rntbdRequest.databaseName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.databaseName.isPresent = true; - break; - case Paths.SnapshotsPathSegment: - rntbdRequest.snapshotName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.snapshotName.isPresent = true; - break; - case Paths.RoleDefinitionsPathSegment: - rntbdRequest.roleDefinitionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.roleDefinitionName.isPresent = true; - break; - case Paths.RoleAssignmentsPathSegment: - rntbdRequest.roleAssignmentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.roleAssignmentName.isPresent = true; - break; - case Paths.InteropUsersPathSegment: - rntbdRequest.interopUserName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.interopUserName.isPresent = true; - break; - case Paths.AuthPolicyElementsPathSegment: - rntbdRequest.authPolicyElementName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.authPolicyElementName.isPresent = true; - break; - case Paths.EncryptionScopesPathSegment: - rntbdRequest.encryptionScopeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); - rntbdRequest.encryptionScopeName.isPresent = true; - break; - default: - throw new BadRequestException(); - } - } - - if (fragments.Length >= 4) - { - switch (fragments[2]) - { - case Paths.CollectionsPathSegment: - rntbdRequest.collectionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); - rntbdRequest.collectionName.isPresent = true; - break; - case Paths.ClientEncryptionKeysPathSegment: - rntbdRequest.clientEncryptionKeyName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); - rntbdRequest.clientEncryptionKeyName.isPresent = true; - break; - case Paths.UsersPathSegment: - rntbdRequest.userName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); - rntbdRequest.userName.isPresent = true; - break; - case Paths.UserDefinedTypesPathSegment: - rntbdRequest.userDefinedTypeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); - rntbdRequest.userDefinedTypeName.isPresent = true; - break; - } - } - - if (fragments.Length >= 6) - { - switch (fragments[4]) - { - case Paths.DocumentsPathSegment: - rntbdRequest.documentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.documentName.isPresent = true; - break; - case Paths.StoredProceduresPathSegment: - rntbdRequest.storedProcedureName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.storedProcedureName.isPresent = true; - break; - case Paths.PermissionsPathSegment: - rntbdRequest.permissionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.permissionName.isPresent = true; - break; - case Paths.UserDefinedFunctionsPathSegment: - rntbdRequest.userDefinedFunctionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.userDefinedFunctionName.isPresent = true; - break; - case Paths.TriggersPathSegment: - rntbdRequest.triggerName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.triggerName.isPresent = true; - break; - case Paths.ConflictsPathSegment: - rntbdRequest.conflictName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.conflictName.isPresent = true; - break; - case Paths.PartitionKeyRangesPathSegment: - rntbdRequest.partitionKeyRangeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.partitionKeyRangeName.isPresent = true; - break; - case Paths.SchemasPathSegment: - rntbdRequest.schemaName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.schemaName.isPresent = true; - break; - case Paths.PartitionedSystemDocumentsPathSegment: - rntbdRequest.systemDocumentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.systemDocumentName.isPresent = true; - break; - case Paths.SystemDocumentsPathSegment: - rntbdRequest.systemDocumentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); - rntbdRequest.systemDocumentName.isPresent = true; - break; - } - } - - if (fragments.Length >= 8) - { - switch (fragments[6]) - { - case Paths.AttachmentsPathSegment: - rntbdRequest.attachmentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[7], rntbdRequest); - rntbdRequest.attachmentName.isPresent = true; - break; - } - } - } - - private static void SetResourceIdHeadersFromDocumentServiceRequest(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (string.IsNullOrEmpty(request.DatabaseName)) - { - throw new ArgumentException(nameof(request.DatabaseName)); - } - - rntbdRequest.databaseName.value.valueBytes = BytesSerializer.GetBytesForString(request.DatabaseName, rntbdRequest); - rntbdRequest.databaseName.isPresent = true; - - if (string.IsNullOrEmpty(request.CollectionName)) - { - throw new ArgumentException(nameof(request.CollectionName)); - } - - rntbdRequest.collectionName.value.valueBytes = BytesSerializer.GetBytesForString(request.CollectionName, rntbdRequest); - rntbdRequest.collectionName.isPresent = true; - - // even though it's a document request, the Request URI can be made against the collection (e.g. for Upserts) - // if document name specified then add it. - if (!string.IsNullOrEmpty(request.DocumentName)) - { - rntbdRequest.documentName.value.valueBytes = BytesSerializer.GetBytesForString(request.DocumentName, rntbdRequest); - rntbdRequest.documentName.isPresent = true; - } - } - - private static void AddBinaryIdIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - object binaryPayload; - if (request.Properties != null && request.Properties.TryGetValue(WFConstants.BackendHeaders.BinaryId, out binaryPayload)) - { - if (binaryPayload is byte[] binaryBytesData) - { - rntbdRequest.binaryId.value.valueBytes = binaryBytesData; - } -#if COSMOSCLIENT - else if (binaryPayload is ReadOnlyMemory binaryRomBytesData) - { - rntbdRequest.binaryId.value.valueBytes = binaryRomBytesData; - } -#endif - else - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.BinaryId); - } - - rntbdRequest.binaryId.isPresent = true; - } - else if (TransportSerialization.TryGetHeaderValueString(request, WFConstants.BackendHeaders.BinaryId, out string binaryId)) - { - rntbdRequest.binaryId.value.valueBytes = System.Convert.FromBase64String(binaryId); - rntbdRequest.binaryId.isPresent = true; - } - } - - private static void AddReturnPreferenceIfPresent(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string value = requestHeaders.Prefer; - - if (!string.IsNullOrEmpty(value)) - { - if (string.Equals(value, HttpConstants.HttpHeaderValues.PreferReturnMinimal, StringComparison.OrdinalIgnoreCase)) - { - rntbdRequest.returnPreference.value.valueByte = (byte)0x01; - rntbdRequest.returnPreference.isPresent = true; - } - else if (string.Equals(value, HttpConstants.HttpHeaderValues.PreferReturnRepresentation, StringComparison.OrdinalIgnoreCase)) - { - rntbdRequest.returnPreference.value.valueByte = (byte)0x00; - rntbdRequest.returnPreference.isPresent = true; - } - } - } - - private static void AddEffectivePartitionKeyIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (request.Properties == null) - { - return; - } - - object binaryPayload; - if (request.Properties.TryGetValue(WFConstants.BackendHeaders.EffectivePartitionKey, out binaryPayload)) - { - byte[] binaryData = binaryPayload as byte[]; - if (binaryData == null) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.EffectivePartitionKey); - } - - rntbdRequest.effectivePartitionKey.value.valueBytes = binaryData; - rntbdRequest.effectivePartitionKey.isPresent = true; - } - } - - private static bool TryGetHeaderValueString(DocumentServiceRequest request, string headerName, out string headerValue) - { - headerValue = null; - - if (request.Headers != null) - { - headerValue = request.Headers.Get(headerName); - } - - return !string.IsNullOrWhiteSpace(headerValue); - } - - private static void AddMergeStaticIdIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (request.Properties == null) - { - return; - } - - object binaryPayload; - if (request.Properties.TryGetValue(WFConstants.BackendHeaders.MergeStaticId, out binaryPayload)) - { - if (binaryPayload is byte[] binaryData) - { - rntbdRequest.mergeStaticId.value.valueBytes = binaryData; - } -#if COSMOSCLIENT - else if (binaryPayload is ReadOnlyMemory binaryRomData) - { - rntbdRequest.mergeStaticId.value.valueBytes = binaryRomData; - } -#endif - else - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.MergeStaticId); - } - - rntbdRequest.mergeStaticId.isPresent = true; - } - } - - private static void AddEntityId(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(request.EntityId)) - { - rntbdRequest.entityId.value.valueBytes = BytesSerializer.GetBytesForString(request.EntityId, rntbdRequest); - rntbdRequest.entityId.isPresent = true; - } - } - - private static void AddIndexingDirectiveHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IndexingDirective)) - { - RntbdConstants.RntbdIndexingDirective rntbdDirective = RntbdConstants.RntbdIndexingDirective.Invalid; - IndexingDirective directive; - if (!Enum.TryParse(requestHeaders.IndexingDirective, true, out directive)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.IndexingDirective, typeof(IndexingDirective).Name)); - } - - switch (directive) - { - case IndexingDirective.Default: - rntbdDirective = RntbdConstants.RntbdIndexingDirective.Default; - break; - case IndexingDirective.Exclude: - rntbdDirective = RntbdConstants.RntbdIndexingDirective.Exclude; - break; - case IndexingDirective.Include: - rntbdDirective = RntbdConstants.RntbdIndexingDirective.Include; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.IndexingDirective, typeof(IndexingDirective).Name)); - } - - rntbdRequest.indexingDirective.value.valueByte = (byte) rntbdDirective; - rntbdRequest.indexingDirective.isPresent = true; - } - } - - private static void AddMigrateCollectionDirectiveHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.MigrateCollectionDirective)) - { - RntbdConstants.RntbdMigrateCollectionDirective rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Invalid; - MigrateCollectionDirective directive; - if (!Enum.TryParse(requestHeaders.MigrateCollectionDirective, true, out directive)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.MigrateCollectionDirective, typeof(MigrateCollectionDirective).Name)); - } - - switch (directive) - { - case MigrateCollectionDirective.Freeze: - rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Freeze; - break; - case MigrateCollectionDirective.Thaw: - rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Thaw; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.MigrateCollectionDirective, typeof(MigrateCollectionDirective).Name)); - } - - rntbdRequest.migrateCollectionDirective.value.valueByte = (byte) rntbdDirective; - rntbdRequest.migrateCollectionDirective.isPresent = true; - } - } - - private static void AddConsistencyLevelHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ConsistencyLevel)) - { - RntbdConstants.RntbdConsistencyLevel rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Invalid; - ConsistencyLevel consistencyLevel; - if (!Enum.TryParse(requestHeaders.ConsistencyLevel, true, out consistencyLevel)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ConsistencyLevel, typeof(ConsistencyLevel).Name)); - } - - switch (consistencyLevel) - { - case ConsistencyLevel.Strong: - rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Strong; - break; - case ConsistencyLevel.BoundedStaleness: - rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.BoundedStaleness; - break; - case ConsistencyLevel.Session: - rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Session; - break; - case ConsistencyLevel.Eventual: - rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Eventual; - break; - case ConsistencyLevel.ConsistentPrefix: - rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.ConsistentPrefix; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ConsistencyLevel, typeof(ConsistencyLevel).Name)); - } - - rntbdRequest.consistencyLevel.value.valueByte = (byte) rntbdConsistencyLevel; - rntbdRequest.consistencyLevel.isPresent = true; - } - } - - private static void AddIsThroughputCapRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsThroughputCapRequest)) - { - rntbdRequest.isThroughputCapRequest.value.valueByte = (requestHeaders.IsThroughputCapRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isThroughputCapRequest.isPresent = true; - } - } - - private static void AddIsFanout(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsFanoutRequest)) - { - rntbdRequest.isFanout.value.valueByte = (requestHeaders.IsFanoutRequest.Equals(bool.TrueString)) ? (byte) 0x01 : (byte) 0x00; - rntbdRequest.isFanout.isPresent = true; - } - } - - private static void AddAllowScanOnQuery(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.EnableScanInQuery)) - { - rntbdRequest.enableScanInQuery.value.valueByte = (requestHeaders.EnableScanInQuery. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.enableScanInQuery.isPresent = true; - } - } - - private static void AddEnableLowPrecisionOrderBy(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.EnableLowPrecisionOrderBy)) - { - rntbdRequest.enableLowPrecisionOrderBy.value.valueByte = (requestHeaders.EnableLowPrecisionOrderBy. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.enableLowPrecisionOrderBy.isPresent = true; - } - } - - private static void AddEmitVerboseTracesInQuery(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.EmitVerboseTracesInQuery)) - { - rntbdRequest.emitVerboseTracesInQuery.value.valueByte = (requestHeaders.EmitVerboseTracesInQuery. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.emitVerboseTracesInQuery.isPresent = true; - } - } - - private static void AddCanCharge(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.CanCharge)) - { - rntbdRequest.canCharge.value.valueByte = (requestHeaders.CanCharge. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.canCharge.isPresent = true; - } - } - - private static void AddCanThrottle(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.CanThrottle)) - { - rntbdRequest.canThrottle.value.valueByte = (requestHeaders.CanThrottle. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.canThrottle.isPresent = true; - } - } - - private static void AddProfileRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ProfileRequest)) - { - rntbdRequest.profileRequest.value.valueByte = (requestHeaders.ProfileRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.profileRequest.isPresent = true; - } - } - - private static void AddPageSize(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string value = requestHeaders.PageSize; - - if (!string.IsNullOrEmpty(value)) - { - int valueInt; - if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueInt)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); - } - - if (valueInt == -1) - { - rntbdRequest.pageSize.value.valueULong = UInt32.MaxValue; - } - else if (valueInt >= 0) - { - rntbdRequest.pageSize.value.valueULong = (UInt32) valueInt; - } - else - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); - } - - rntbdRequest.pageSize.isPresent = true; - } - } - - private static void AddEnableLogging(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.EnableLogging)) - { - rntbdRequest.enableLogging.value.valueByte = (requestHeaders.EnableLogging. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.enableLogging.isPresent = true; - } - } - - private static void AddSupportSpatialLegacyCoordinates(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.SupportSpatialLegacyCoordinates)) - { - rntbdRequest.supportSpatialLegacyCoordinates.value.valueByte = (requestHeaders.SupportSpatialLegacyCoordinates. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.supportSpatialLegacyCoordinates.isPresent = true; - } - } - - private static void AddUsePolygonsSmallerThanAHemisphere(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.UsePolygonsSmallerThanAHemisphere)) - { - rntbdRequest.usePolygonsSmallerThanAHemisphere.value.valueByte = (requestHeaders.UsePolygonsSmallerThanAHemisphere. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.usePolygonsSmallerThanAHemisphere.isPresent = true; - } - } - - private static void AddPopulateQuotaInfo(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateQuotaInfo)) - { - rntbdRequest.populateQuotaInfo.value.valueByte = (requestHeaders.PopulateQuotaInfo. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.populateQuotaInfo.isPresent = true; - } - } - - private static void AddPopulateResourceCount(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateResourceCount)) - { - rntbdRequest.populateResourceCount.value.valueByte = (requestHeaders.PopulateResourceCount. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.populateResourceCount.isPresent = true; - } - } - - private static void AddPopulatePartitionStatistics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulatePartitionStatistics)) - { - rntbdRequest.populatePartitionStatistics.value.valueByte = (requestHeaders.PopulatePartitionStatistics. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.populatePartitionStatistics.isPresent = true; - } - } - - private static void AddDisableRUPerMinuteUsage(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.DisableRUPerMinuteUsage)) - { - rntbdRequest.disableRUPerMinuteUsage.value.valueByte = (requestHeaders.DisableRUPerMinuteUsage. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.disableRUPerMinuteUsage.isPresent = true; - } - } - - private static void AddPopulateQueryMetrics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateQueryMetrics)) - { - rntbdRequest.populateQueryMetrics.value.valueByte = (requestHeaders.PopulateQueryMetrics. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.populateQueryMetrics.isPresent = true; - } - } - - private static void AddPopulateQueryMetricsIndexUtilization(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateIndexMetrics)) - { - rntbdRequest.populateIndexMetrics.value.valueByte = (requestHeaders.PopulateIndexMetrics. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.populateIndexMetrics.isPresent = true; - } - } - - private static void AddPopulateIndexMetricsV2(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateIndexMetricsV2)) - { - rntbdRequest.populateIndexMetricsV2.value.valueByte = (requestHeaders.PopulateIndexMetricsV2. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.populateIndexMetricsV2.isPresent = true; - } - } - - private static void AddOptimisticDirectExecute(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.OptimisticDirectExecute)) - { - rntbdRequest.optimisticDirectExecute.value.valueByte = (requestHeaders.OptimisticDirectExecute. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.optimisticDirectExecute.isPresent = true; - } - } - - private static void AddQueryForceScan(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ForceQueryScan)) - { - rntbdRequest.forceQueryScan.value.valueByte = (requestHeaders.ForceQueryScan. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.forceQueryScan.isPresent = true; - } - } - - private static void AddPopulateCollectionThroughputInfo(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PopulateCollectionThroughputInfo)) - { - rntbdRequest.populateCollectionThroughputInfo.value.valueByte = (requestHeaders.PopulateCollectionThroughputInfo. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.populateCollectionThroughputInfo.isPresent = true; - } - } - - private static void AddShareThroughput(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ShareThroughput)) - { - rntbdRequest.shareThroughput.value.valueByte = (requestHeaders.ShareThroughput. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.shareThroughput.isPresent = true; - } - } - - private static void AddIsReadOnlyScript(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsReadOnlyScript)) - { - rntbdRequest.isReadOnlyScript.value.valueByte = (requestHeaders.IsReadOnlyScript. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isReadOnlyScript.isPresent = true; - } - } - -#if !COSMOSCLIENT - private static void AddIsAutoScaleRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsAutoScaleRequest)) - { - rntbdRequest.isAutoScaleRequest.value.valueByte = (requestHeaders.IsAutoScaleRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isAutoScaleRequest.isPresent = true; - } - } -#endif - - private static void AddCanOfferReplaceComplete(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.CanOfferReplaceComplete)) - { - rntbdRequest.canOfferReplaceComplete.value.valueByte = (requestHeaders.CanOfferReplaceComplete. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.canOfferReplaceComplete.isPresent = true; - } - } - - private static void AddIgnoreSystemLoweringMaxThroughput(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IgnoreSystemLoweringMaxThroughput)) - { - rntbdRequest.ignoreSystemLoweringMaxThroughput.value.valueByte = (requestHeaders.IgnoreSystemLoweringMaxThroughput. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.ignoreSystemLoweringMaxThroughput.isPresent = true; - } - } - - private static void AddUpdateMaxthroughputEverProvisioned(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.UpdateMaxThroughputEverProvisioned)) - { - string value = requestHeaders.UpdateMaxThroughputEverProvisioned; - int valueInt; - if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueInt)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidUpdateMaxthroughputEverProvisioned, value)); - } - - if (valueInt >= 0) - { - rntbdRequest.updateMaxThroughputEverProvisioned.value.valueULong = (UInt32)valueInt; - } - else - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidUpdateMaxthroughputEverProvisioned, value)); - } - - rntbdRequest.updateMaxThroughputEverProvisioned.isPresent = true; - } - } - - private static void AddGetAllPartitionKeyStatistics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.GetAllPartitionKeyStatistics)) - { - rntbdRequest.getAllPartitionKeyStatistics.value.valueByte = (requestHeaders.GetAllPartitionKeyStatistics. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.getAllPartitionKeyStatistics.isPresent = true; - } - } - - private static void AddResponseContinuationTokenLimitInKb(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ResponseContinuationTokenLimitInKB)) - { - string value = requestHeaders.ResponseContinuationTokenLimitInKB; - if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int valueInt)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); - } - - if (valueInt >= 0) - { - rntbdRequest.responseContinuationTokenLimitInKb.value.valueULong = (UInt32) valueInt; - } - else - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResponseContinuationTokenLimit, value)); - } - - rntbdRequest.responseContinuationTokenLimitInKb.isPresent = true; - } - } - - private static void AddRemoteStorageType(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.RemoteStorageType)) - { - RntbdConstants.RntbdRemoteStorageType rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Invalid; - if (!Enum.TryParse(requestHeaders.RemoteStorageType, true, out RemoteStorageType remoteStorageType)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.RemoteStorageType, typeof(RemoteStorageType).Name)); - } - - switch (remoteStorageType) - { - case RemoteStorageType.Standard: - rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Standard; - break; - case RemoteStorageType.Premium: - rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Premium; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.RemoteStorageType, typeof(RemoteStorageType).Name)); - } - - rntbdRequest.remoteStorageType.value.valueByte = (byte) rntbdRemoteStorageType; - rntbdRequest.remoteStorageType.isPresent = true; - } - } - - private static void AddCollectionChildResourceNameLimitInBytes(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.CollectionChildResourceNameLimitInBytes; - if (!string.IsNullOrEmpty(headerValue)) - { - if (!Int32.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.collectionChildResourceNameLimitInBytes.value.valueLong)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - headerValue, - WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes)); - } - - rntbdRequest.collectionChildResourceNameLimitInBytes.isPresent = true; - } - } - - private static void AddCollectionChildResourceContentLengthLimitInKB(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.CollectionChildResourceContentLimitInKB; - if (!string.IsNullOrEmpty(headerValue)) - { - if (!Int32.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.collectionChildResourceContentLengthLimitInKB.value.valueLong)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - headerValue, - WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB)); - } - - rntbdRequest.collectionChildResourceContentLengthLimitInKB.isPresent = true; - } - } - - private static void AddUniqueIndexNameEncodingMode(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.UniqueIndexNameEncodingMode; - if (!string.IsNullOrEmpty(headerValue)) - { - if (!Byte.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.uniqueIndexNameEncodingMode.value.valueByte)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - headerValue, - WFConstants.BackendHeaders.UniqueIndexNameEncodingMode)); - } - - rntbdRequest.uniqueIndexNameEncodingMode.isPresent = true; - } - } - - private static void AddUniqueIndexReIndexingState(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.UniqueIndexReIndexingState; - if (!string.IsNullOrEmpty(headerValue)) - { - if (!Byte.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.uniqueIndexReIndexingState.value.valueByte)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - headerValue, - WFConstants.BackendHeaders.UniqueIndexReIndexingState)); - } - - rntbdRequest.uniqueIndexReIndexingState.isPresent = true; - } - } - - private static void AddIsInternalServerlessRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsInternalServerlessRequest)) - { - rntbdRequest.isInternalServerlessRequest.value.valueByte = (requestHeaders.IsInternalServerlessRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isInternalServerlessRequest.isPresent = true; - } - } - - private static void AddCorrelatedActivityId(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.CorrelatedActivityId; - if (!string.IsNullOrEmpty(headerValue)) - { - if (!Guid.TryParse(headerValue, out rntbdRequest.correlatedActivityId.value.valueGuid)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, - RMResources.InvalidHeaderValue, - headerValue, - WFConstants.BackendHeaders.CorrelatedActivityId)); - } - - rntbdRequest.correlatedActivityId.isPresent = true; - } - } - - private static void AddCollectionRemoteStorageSecurityIdentifier(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.CollectionRemoteStorageSecurityIdentifier; - if (!string.IsNullOrEmpty(headerValue)) - { - rntbdRequest.collectionRemoteStorageSecurityIdentifier.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); - rntbdRequest.collectionRemoteStorageSecurityIdentifier.isPresent = true; - } - } - - private static void AddIsUserRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsUserRequest)) - { - rntbdRequest.isUserRequest.value.valueByte = (requestHeaders.IsUserRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isUserRequest.isPresent = true; - } - } - - private static void AddPreserveFullContent(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.PreserveFullContent)) - { - rntbdRequest.preserveFullContent.value.valueByte = (requestHeaders.PreserveFullContent. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte) 0x01 - : (byte) 0x00; - rntbdRequest.preserveFullContent.isPresent = true; - } - } - - private static void AddForceSideBySideIndexMigration(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ForceSideBySideIndexMigration)) - { - rntbdRequest.forceSideBySideIndexMigration.value.valueByte = (requestHeaders.ForceSideBySideIndexMigration. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.forceSideBySideIndexMigration.isPresent = true; - } - } - private static void AddPopulateUniqueIndexReIndexProgress(object headerObjectValue, RntbdConstants.Request rntbdRequest) - { - if (headerObjectValue is string headerValue && - !string.IsNullOrEmpty(headerValue)) - { - if (string.Equals(bool.TrueString, headerValue, StringComparison.OrdinalIgnoreCase)) - { - rntbdRequest.populateUniqueIndexReIndexProgress.value.valueByte = (byte)0x01; - } - else - { - rntbdRequest.populateUniqueIndexReIndexProgress.value.valueByte = (byte)0x00; - } - - rntbdRequest.populateUniqueIndexReIndexProgress.isPresent = true; - } - } - - private static void AddIsRUPerGBEnforcementRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsRUPerGBEnforcementRequest)) - { - rntbdRequest.isRUPerGBEnforcementRequest.value.valueByte = (requestHeaders.IsRUPerGBEnforcementRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isRUPerGBEnforcementRequest.isPresent = true; - } - } - - private static void AddIsOfferStorageRefreshRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsOfferStorageRefreshRequest)) - { - rntbdRequest.isofferStorageRefreshRequest.value.valueByte = (requestHeaders.IsOfferStorageRefreshRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isofferStorageRefreshRequest.isPresent = true; - } - } - -#if !COSMOSCLIENT - private static void AddIsServerlessEnabledStorageRefreshRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsServerlessStorageRefreshRequest)) - { - rntbdRequest.isServerlessStorageRefreshRequest.value.valueByte = (requestHeaders.IsServerlessStorageRefreshRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isServerlessStorageRefreshRequest.isPresent = true; - } - } -#endif - - private static void AddIsMigrateOfferToManualThroughputRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.MigrateOfferToManualThroughput)) - { - rntbdRequest.migrateOfferToManualThroughput.value.valueByte = (requestHeaders.MigrateOfferToManualThroughput. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.migrateOfferToManualThroughput.isPresent = true; - } - } - - private static void AddIsMigrateOfferToAutopilotRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.MigrateOfferToAutopilot)) - { - rntbdRequest.migrateOfferToAutopilot.value.valueByte = (requestHeaders.MigrateOfferToAutopilot. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.migrateOfferToAutopilot.isPresent = true; - } - } - - private static void AddTruncateMergeLogRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.TruncateMergeLogRequest)) - { - rntbdRequest.truncateMergeLogRequest.value.valueByte = (requestHeaders.TruncateMergeLogRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.truncateMergeLogRequest.isPresent = true; - } - } - - private static void AddEnumerationDirection(DocumentServiceRequest request, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (request.Properties != null && request.Properties.TryGetValue( - HttpConstants.HttpHeaders.EnumerationDirection, - out object enumerationDirectionObject)) - { - byte? scanDirection = enumerationDirectionObject as byte?; - if (scanDirection == null) - { - throw new BadRequestException( - String.Format( - CultureInfo.CurrentUICulture, - RMResources.InvalidEnumValue, - HttpConstants.HttpHeaders.EnumerationDirection, - nameof(EnumerationDirection))); - } - else - { - rntbdRequest.enumerationDirection.value.valueByte = scanDirection.Value; - rntbdRequest.enumerationDirection.isPresent = true; - } - } - else if (!string.IsNullOrEmpty(requestHeaders.EnumerationDirection)) - { - RntbdConstants.RntdbEnumerationDirection rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Invalid; - if (!Enum.TryParse(requestHeaders.EnumerationDirection, true, out EnumerationDirection enumerationDirection)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.EnumerationDirection, nameof(EnumerationDirection))); - } - - switch (enumerationDirection) - { - case EnumerationDirection.Forward: - rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Forward; - break; - case EnumerationDirection.Reverse: - rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Reverse; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.EnumerationDirection, typeof(EnumerationDirection).Name)); - } - - rntbdRequest.enumerationDirection.value.valueByte = (byte)rntdbEnumerationDirection; - rntbdRequest.enumerationDirection.isPresent = true; - } - } - - private static void AddStartAndEndKeys(DocumentServiceRequest request, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (request.Properties == null - || !string.IsNullOrEmpty(requestHeaders.ReadFeedKeyType)) - { - TransportSerialization.AddStartAndEndKeysFromHeaders(requestHeaders, rntbdRequest); - return; - } - - RntbdConstants.RntdbReadFeedKeyType? readFeedKeyType = null; - if (request.Properties.TryGetValue(HttpConstants.HttpHeaders.ReadFeedKeyType, out object requestObject)) - { - if (!(requestObject is byte)) - { - throw new ArgumentOutOfRangeException(HttpConstants.HttpHeaders.ReadFeedKeyType); - } - - rntbdRequest.readFeedKeyType.value.valueByte = (byte)requestObject; - rntbdRequest.readFeedKeyType.isPresent = true; - readFeedKeyType = (RntbdConstants.RntdbReadFeedKeyType)requestObject; - } - - if (readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.ResourceId) - { - TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.StartId, rntbdRequest.startId); - TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.EndId, rntbdRequest.endId); - } - else if (readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKey || - readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKeyRange) - { - - TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.StartEpk, rntbdRequest.startEpk); - TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.EndEpk, rntbdRequest.endEpk); - } - } - - private static void AddStartAndEndKeysFromHeaders(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - bool keepsAsHexString = false; - if (!string.IsNullOrEmpty(requestHeaders.ReadFeedKeyType)) - { - RntbdConstants.RntdbReadFeedKeyType rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.Invalid; - if (!Enum.TryParse(requestHeaders.ReadFeedKeyType, true, out ReadFeedKeyType readFeedKeyType)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ReadFeedKeyType, nameof(ReadFeedKeyType))); - } - - switch (readFeedKeyType) - { - case ReadFeedKeyType.ResourceId: - rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.ResourceId; - break; - case ReadFeedKeyType.EffectivePartitionKey: - rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKey; - break; - case ReadFeedKeyType.EffectivePartitionKeyRange: - rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKeyRange; - keepsAsHexString = true; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ReadFeedKeyType, typeof(ReadFeedKeyType).Name)); - } - - rntbdRequest.readFeedKeyType.value.valueByte = (byte)rntdbReadFeedKeyType; - rntbdRequest.readFeedKeyType.isPresent = true; - } - - string startId = requestHeaders.StartId; - if (!string.IsNullOrEmpty(startId)) - { - rntbdRequest.startId.value.valueBytes = System.Convert.FromBase64String(startId); - rntbdRequest.startId.isPresent = true; - } - - string endId = requestHeaders.EndId; - if (!string.IsNullOrEmpty(endId)) - { - rntbdRequest.endId.value.valueBytes = System.Convert.FromBase64String(endId); - rntbdRequest.endId.isPresent = true; - } - - string startEpk = requestHeaders.StartEpk; - if (!string.IsNullOrEmpty(startEpk)) - { - rntbdRequest.startEpk.value.valueBytes = keepsAsHexString ? BytesSerializer.GetBytesForString(startEpk, rntbdRequest) : System.Convert.FromBase64String(startEpk); - rntbdRequest.startEpk.isPresent = true; - } - - string endEpk = requestHeaders.EndEpk; - if (!string.IsNullOrEmpty(endEpk)) - { - rntbdRequest.endEpk.value.valueBytes = keepsAsHexString ? BytesSerializer.GetBytesForString(endEpk, rntbdRequest) : System.Convert.FromBase64String(endEpk); - rntbdRequest.endEpk.isPresent = true; - } - } - - private static void SetBytesValue(DocumentServiceRequest request, string headerName, RntbdToken token) - { - if (request.Properties.TryGetValue(headerName, out object requestObject)) - { - if (requestObject is byte[] endEpk) - { - token.value.valueBytes = endEpk; - } -#if COSMOSCLIENT - else if (requestObject is ReadOnlyMemory endEpkRom) - { - token.value.valueBytes = endEpkRom; - } -#endif - else - { - throw new ArgumentOutOfRangeException(headerName); - } - - - token.isPresent = true; - } - } - - private static void AddContentSerializationFormat(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ContentSerializationFormat)) - { - RntbdConstants.RntbdContentSerializationFormat rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.Invalid; - - if (!Enum.TryParse(requestHeaders.ContentSerializationFormat, true, out ContentSerializationFormat contentSerializationFormat)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ContentSerializationFormat, nameof(ContentSerializationFormat))); - } - - switch (contentSerializationFormat) - { - case ContentSerializationFormat.JsonText: - rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.JsonText; - break; - case ContentSerializationFormat.CosmosBinary: - rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.CosmosBinary; - break; - case ContentSerializationFormat.HybridRow: - rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.HybridRow; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.ContentSerializationFormat, nameof(ContentSerializationFormat))); - } - - rntbdRequest.contentSerializationFormat.value.valueByte = (byte)rntbdContentSerializationFormat; - rntbdRequest.contentSerializationFormat.isPresent = true; - } - } - - [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Roslyn Baseline 12/12/2022 16:40")] - private static void AddSupportedSerializationFormats(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (requestHeaders.SupportedSerializationFormats != null) - { - RntbdConstants.RntbdSupportedSerializationFormats rntbdSupportedSerializationFormats = RntbdConstants.RntbdSupportedSerializationFormats.None; - - // Making empty header value check consistent with http request. If header value is empty throw exception. - if (requestHeaders.SupportedSerializationFormats.Length == 0 || !Enum.TryParse(requestHeaders.SupportedSerializationFormats, true, out SupportedSerializationFormats supportedSerializationFormats)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.SupportedSerializationFormats, nameof(SupportedSerializationFormats))); - } - - if(supportedSerializationFormats.HasFlag(SupportedSerializationFormats.JsonText)) - { - rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.JsonText; - } - - if(supportedSerializationFormats.HasFlag(SupportedSerializationFormats.CosmosBinary)) - { - rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.CosmosBinary; - } - - if (supportedSerializationFormats.HasFlag(SupportedSerializationFormats.HybridRow)) - { - rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.HybridRow; - } - - if((supportedSerializationFormats & - ~(SupportedSerializationFormats.JsonText | SupportedSerializationFormats.CosmosBinary | SupportedSerializationFormats.HybridRow)) != SupportedSerializationFormats.None) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.SupportedSerializationFormats, nameof(SupportedSerializationFormats))); - } - - rntbdRequest.supportedSerializationFormats.value.valueByte = (byte)rntbdSupportedSerializationFormats; - rntbdRequest.supportedSerializationFormats.isPresent = true; - } - } - - private static void FillTokenFromHeader(DocumentServiceRequest request, string headerName, string headerStringValue, RntbdToken token, RntbdConstants.Request rntbdRequest) - { - object headerValue = null; - if (string.IsNullOrEmpty(headerStringValue)) - { - if (request.Properties == null || !request.Properties.TryGetValue(headerName, out headerValue)) - { - return; - } - - if (headerValue == null) - { - return; - } - - if (headerValue is string valueString) - { - headerStringValue = valueString; - if (string.IsNullOrEmpty(headerStringValue)) - { - return; - } - } - } - - switch (token.GetTokenType()) - { - case RntbdTokenTypes.SmallString: - case RntbdTokenTypes.String: - case RntbdTokenTypes.ULongString: - if (headerStringValue == null) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - - token.value.valueBytes = BytesSerializer.GetBytesForString(headerStringValue, rntbdRequest); - break; - case RntbdTokenTypes.ULong: - uint valueULong; - if (headerStringValue != null) - { - if (!uint.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueULong)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - } - else - { - if (!(headerValue is uint uintValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueULong = uintValue; - } - - token.value.valueULong = valueULong; - break; - case RntbdTokenTypes.Long: - int valueLong; - if (headerStringValue != null) - { - if (!int.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueLong)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - } - else - { - if (!(headerValue is int intValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueLong = intValue; - } - - token.value.valueLong = valueLong; - break; - case RntbdTokenTypes.Double: - double valueDouble; - if (headerStringValue != null) - { - if (!double.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueDouble)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - } - else - { - if (!(headerValue is double doubleValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueDouble = doubleValue; - } - - token.value.valueDouble = valueDouble; - break; - case RntbdTokenTypes.LongLong: - long valueLongLong; - if (headerStringValue != null) - { - if (!long.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueLongLong)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - } - else - { - if (!(headerValue is long longLongValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueLongLong = longLongValue; - } - - token.value.valueLongLong = valueLongLong; - break; - case RntbdTokenTypes.Byte: - bool valueBool; - if (headerStringValue != null) - { - valueBool = string.Equals(headerStringValue, bool.TrueString, StringComparison.OrdinalIgnoreCase); - } - else - { - if (!(headerValue is bool boolValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueBool = boolValue; - } - - token.value.valueByte = valueBool ? (byte)0x01 : (byte)0x00; - break; - case RntbdTokenTypes.Bytes: - byte[] valueBytes; - if (headerStringValue != null) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - else - { - if (!(headerValue is byte[] bytesValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueBytes = bytesValue; - } - - token.value.valueBytes = valueBytes; - break; - case RntbdTokenTypes.Guid: - Guid valueGuid; - if (headerStringValue != null) - { - if (!Guid.TryParse(headerStringValue, out valueGuid)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); - } - } - else - { - if (!(headerValue is Guid guidValue)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); - } - - valueGuid = guidValue; - } - - token.value.valueGuid = valueGuid; - break; - default: - Debug.Assert(false, "Recognized header has neither special-case nor default handling to convert" - + " from header string to RNTBD token."); - throw new BadRequestException(); - } - - token.isPresent = true; - } - - private static void AddExcludeSystemProperties(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.ExcludeSystemProperties)) - { - rntbdRequest.excludeSystemProperties.value.valueByte = (requestHeaders.ExcludeSystemProperties. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.excludeSystemProperties.isPresent = true; - } - } - - private static void AddFanoutOperationStateHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string value = requestHeaders.FanoutOperationState; - if (!string.IsNullOrEmpty(value)) - { - if (!Enum.TryParse(value, true, out FanoutOperationState state)) - { - throw new BadRequestException( - String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(FanoutOperationState))); - } - - RntbdConstants.RntbdFanoutOperationState rntbdState; - switch (state) - { - case FanoutOperationState.Started: - rntbdState = RntbdConstants.RntbdFanoutOperationState.Started; - break; - - case FanoutOperationState.Completed: - rntbdState = RntbdConstants.RntbdFanoutOperationState.Completed; - break; - - default: - throw new BadRequestException( - String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(FanoutOperationState))); - } - - rntbdRequest.fanoutOperationState.value.valueByte = (byte)rntbdState; - rntbdRequest.fanoutOperationState.isPresent = true; - } - } - - private static void AddResourceTypes(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string headerValue = requestHeaders.ResourceTypes; - if (!string.IsNullOrEmpty(headerValue)) - { - rntbdRequest.resourceTypes.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); - rntbdRequest.resourceTypes.isPresent = true; - } - } - - private static void AddSystemDocumentTypeHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.SystemDocumentType)) - { - RntbdConstants.RntbdSystemDocumentType rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.Invalid; - if (!Enum.TryParse(requestHeaders.SystemDocumentType, true, out SystemDocumentType systemDocumentType)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.SystemDocumentType, nameof(SystemDocumentType))); - } - - switch (systemDocumentType) - { - case SystemDocumentType.MaterializedViewLeaseDocument: - rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewLeaseDocument; - break; - case SystemDocumentType.MaterializedViewBuilderOwnershipDocument: - rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewBuilderOwnershipDocument; - break; - case SystemDocumentType.MaterializedViewLeaseStoreInitDocument: - rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewLeaseStoreInitDocument; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.SystemDocumentType, typeof(SystemDocumentType).Name)); - } - - rntbdRequest.systemDocumentType.value.valueByte = (byte)rntbdSystemDocumentType; - rntbdRequest.systemDocumentType.isPresent = true; - } - } - - private static void AddTransactionMetaData(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (request.Properties != null && - request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionId, out object transactionIdValue) && - request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionFirstRequest, out object isFirstRequestValue)) - { - // read transaction id - byte[] transactionId = transactionIdValue as byte[]; - if (transactionId == null) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionId); - } - - // read initial transactional request flag - bool? isFirstRequest = isFirstRequestValue as bool?; - if (!isFirstRequest.HasValue) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionFirstRequest); - } - - // set transaction id and initial request flag - rntbdRequest.transactionId.value.valueBytes = transactionId; - rntbdRequest.transactionId.isPresent = true; - - rntbdRequest.transactionFirstRequest.value.valueByte = ((bool)isFirstRequest) ? (byte)0x01 : (byte)0x00; - rntbdRequest.transactionFirstRequest.isPresent = true; - } - } - - private static void AddTransactionCompletionFlag(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (request.Properties != null && - request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionCommit, out object isCommit)) - { - bool? boolData = isCommit as bool?; - if (!boolData.HasValue) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionCommit); - } - - rntbdRequest.transactionCommit.value.valueByte = ((bool)boolData) ? (byte)0x01 : (byte)0x00; - rntbdRequest.transactionCommit.isPresent = true; - } - } - - private static void AddRetriableWriteRequestMetadata(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (request.Properties != null && - request.Properties.TryGetValue(WFConstants.BackendHeaders.RetriableWriteRequestId, out object retriableWriteRequestId)) - { - byte[] requestId = retriableWriteRequestId as byte[]; - if (requestId == null) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.RetriableWriteRequestId); - } - - rntbdRequest.retriableWriteRequestId.value.valueBytes = requestId; - rntbdRequest.retriableWriteRequestId.isPresent = true; - - if (request.Properties.TryGetValue(WFConstants.BackendHeaders.IsRetriedWriteRequest, out object isRetriedWriteRequestValue)) - { - bool? isRetriedWriteRequest = isRetriedWriteRequestValue as bool?; - if (!isRetriedWriteRequest.HasValue) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.IsRetriedWriteRequest); - } - - rntbdRequest.isRetriedWriteRequest.value.valueByte = ((bool)isRetriedWriteRequest) ? (byte)0x01 : (byte)0x00; - rntbdRequest.isRetriedWriteRequest.isPresent = true; - } - - if (request.Properties.TryGetValue(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, out object retriableWriteRequestStartTimestamp)) - { - if (!UInt64.TryParse(retriableWriteRequestStartTimestamp.ToString(), out UInt64 requestStartTimestamp) || requestStartTimestamp <= 0) - { - throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp); - } - - rntbdRequest.retriableWriteRequestStartTimestamp.value.valueULongLong = requestStartTimestamp; - rntbdRequest.retriableWriteRequestStartTimestamp.isPresent = true; - } - } - } - - private static void AddUseSystemBudget(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.UseSystemBudget)) - { - rntbdRequest.useSystemBudget.value.valueByte = (requestHeaders.UseSystemBudget. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.useSystemBudget.isPresent = true; - } - } - - private static void AddRequestedCollectionType(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - string value = requestHeaders.RequestedCollectionType; - if (!string.IsNullOrEmpty(value)) - { - if (!Enum.TryParse(value, true, out RequestedCollectionType collectionType)) - { - throw new BadRequestException( - String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(RequestedCollectionType))); - } - - RntbdConstants.RntbdRequestedCollectionType rntbdCollectionType; - switch (collectionType) - { - case RequestedCollectionType.All: - rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.All; - break; - - case RequestedCollectionType.Standard: - rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.Standard; - break; - - case RequestedCollectionType.MaterializedView: - rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.MaterializedView; - break; - - default: - throw new BadRequestException( - String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(RequestedCollectionType))); - } - - rntbdRequest.requestedCollectionType.value.valueByte = (byte)rntbdCollectionType; - rntbdRequest.requestedCollectionType.isPresent = true; - } - } - - private static void AddUpdateOfferStateToPending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.UpdateOfferStateToPending)) - { - rntbdRequest.updateOfferStateToPending.value.valueByte = (requestHeaders.UpdateOfferStateToPending. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.updateOfferStateToPending.isPresent = true; - } - } - - private static void AddUpdateOfferStateToRestorePending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.UpdateOfferStateToRestorePending)) - { - rntbdRequest.updateOfferStateToRestorePending.value.valueByte = (requestHeaders.UpdateOfferStateToRestorePending. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.updateOfferStateToRestorePending.isPresent = true; - } - } - - private static void AddMasterResourcesDeletionPending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.SetMasterResourcesDeletionPending)) - { - rntbdRequest.setMasterResourcesDeletionPending.value.valueByte = (requestHeaders.SetMasterResourcesDeletionPending. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.setMasterResourcesDeletionPending.isPresent = true; - } - } - - private static void AddOfferReplaceRURedistribution(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if(!string.IsNullOrEmpty(requestHeaders.OfferReplaceRURedistribution)) - { - rntbdRequest.offerReplaceRURedistribution.value.valueByte = (requestHeaders.OfferReplaceRURedistribution - .Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.offerReplaceRURedistribution.isPresent = true; - } - } - - private static void AddIsMaterializedViewSourceSchemaReplaceBatchRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest)) - { - rntbdRequest.isMaterializedViewSourceSchemaReplaceBatchRequest.value.valueByte = (requestHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isMaterializedViewSourceSchemaReplaceBatchRequest.isPresent = true; - } - } - - private static void AddIsCassandraAlterTypeRequest(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest])) - { - rntbdRequest.isCassandraAlterTypeRequest.value.valueByte = (request.Headers[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest]. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.isCassandraAlterTypeRequest.isPresent = true; - } - } - - private static void AddHighPriorityForcedBackup(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.HighPriorityForcedBackup)) - { - rntbdRequest.highPriorityForcedBackup.value.valueByte = (requestHeaders.HighPriorityForcedBackup. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.highPriorityForcedBackup.isPresent = true; - } - } - - private static void AddEnableConflictResolutionPolicyUpdate(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.EnableConflictResolutionPolicyUpdate)) - { - rntbdRequest.enableConflictResolutionPolicyUpdate.value.valueByte = (requestHeaders.EnableConflictResolutionPolicyUpdate. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.enableConflictResolutionPolicyUpdate.isPresent = true; - } - } - - private static void AddPriorityLevelHeader(DocumentServiceRequest request, string headerName, string headerStringValue, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - PriorityLevel priorityLevel = PriorityLevel.High; - RntbdConstants.RntbdPriorityLevel rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.High; - - if (string.IsNullOrEmpty(headerStringValue)) - { - object headerValue = null; - if (request.Properties == null || !request.Properties.TryGetValue(headerName, out headerValue)) - { - return; - } - - if (headerValue == null) - { - return; - } - - if (headerValue is Enum valueString) - { - priorityLevel = (PriorityLevel)valueString; - } - } - else - { - if (!Enum.TryParse(requestHeaders.PriorityLevel, true, out priorityLevel)) - { - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.PriorityLevel, typeof(PriorityLevel).Name)); - } - } - switch (priorityLevel) - { - case PriorityLevel.Low: - rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.Low; - break; - case PriorityLevel.High: - rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.High; - break; - default: - throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, - requestHeaders.PriorityLevel, typeof(PriorityLevel).Name)); - } - - rntbdRequest.priorityLevel.value.valueByte = (byte) rntbdPriorityLevel; - rntbdRequest.priorityLevel.isPresent = true; - } - - private static void AddAllowDocumentReadsInOfflineRegion(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) - { - if (!string.IsNullOrEmpty(requestHeaders.AllowDocumentReadsInOfflineRegion)) - { - rntbdRequest.allowDocumentReadsInOfflineRegion.value.valueByte = (requestHeaders.AllowDocumentReadsInOfflineRegion. - Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) - ? (byte)0x01 - : (byte)0x00; - rntbdRequest.allowDocumentReadsInOfflineRegion.isPresent = true; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; +#if COSMOSCLIENT + using Microsoft.Azure.Cosmos.Rntbd; +#endif + using Microsoft.Azure.Documents.Collections; + using RequestPool = RntbdConstants.RntbdEntityPool; + + internal static class TransportSerialization + { + // Path format + internal static readonly char[] UrlTrim = { '/' }; + + internal class RntbdHeader + { + public RntbdHeader(StatusCodes status, Guid activityId) + { + this.Status = status; + this.ActivityId = activityId; + } + + public StatusCodes Status { get; private set; } + public Guid ActivityId { get; private set; } + } + + internal sealed class SerializedRequest : IDisposable + { + private readonly BufferProvider.DisposableBuffer requestHeader; + + private readonly CloneableStream requestBody; + + public SerializedRequest(BufferProvider.DisposableBuffer requestHeader, CloneableStream requestBody) + { + this.requestHeader = requestHeader; + this.requestBody = requestBody; + } + + public int RequestSize => this.requestHeader.Buffer.Count + (int)(this.requestBody?.Length ?? 0); + + public void Dispose() + { + this.requestHeader.Dispose(); + this.requestBody?.Dispose(); + } + + /// + /// Copies the contents of the serialized request to the target buffer. + /// + /// + /// This method is not thread-safe. It is assumed that this is the only + /// method writing to this buffer. The caller is responsible for ensuring + /// ownership of the buffer before calling this method. + /// + internal void CopyTo(ArraySegment buffer) + { + if (buffer.Count < this.RequestSize) + { + throw new ArgumentException("Buffer should at least be as big as the request size"); + } + + Array.Copy( + this.requestHeader.Buffer.Array, + this.requestHeader.Buffer.Offset, + buffer.Array, + buffer.Offset, + this.requestHeader.Buffer.Count); + + if (this.requestBody != null) + { + this.requestBody.CopyBufferTo(buffer.Array, buffer.Offset + this.requestHeader.Buffer.Count); + } + } + + /// + /// Copies the contents of the serialized request to the target stream. + /// + /// + /// This method is not thread-safe. It is assumed that this is the only + /// method writing to this stream. The caller is responsible for ensuring + /// ownership of the stream before calling this method. + /// + internal async Task CopyToStreamAsync(Stream stream) + { + await stream.WriteAsync(this.requestHeader.Buffer.Array, this.requestHeader.Buffer.Offset, this.requestHeader.Buffer.Count); + + if (this.requestBody != null) + { + this.requestBody.Position = 0; + await this.requestBody.CopyToAsync(stream); + } + } + } + + /// + /// Builds the RNTBD request needed for the Photon (ThinClient) protocol + /// + internal static SerializedRequest BuildRequestForProxy( + DocumentServiceRequest request, + ResourceOperation resourceOperation, + Guid activityId, + BufferProvider bufferProvider, + string globalDatabaseAccountName, + out int headerSize, + out int? bodySize) + { + if (string.IsNullOrEmpty(globalDatabaseAccountName)) + { + throw new ArgumentNullException(nameof(globalDatabaseAccountName)); + } + + RntbdConstants.Request rntbdRequest = new(); + + // for proxy, transportRequestId and replicapath are optional. + int tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.replicaPath); + rntbdRequest.replicaPath = new RntbdToken(false, rntbdRequest.replicaPath.GetTokenType(), rntbdRequest.replicaPath.GetTokenIdentifier()); + rntbdRequest.tokens[tokenIndex] = rntbdRequest.replicaPath; + + tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.transportRequestID); + rntbdRequest.transportRequestID = new RntbdToken(false, rntbdRequest.transportRequestID.GetTokenType(), rntbdRequest.transportRequestID.GetTokenIdentifier()); + rntbdRequest.tokens[tokenIndex] = rntbdRequest.transportRequestID; + + // make the EPK the first token + tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.effectivePartitionKey); + rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[0]; + rntbdRequest.tokens[0] = rntbdRequest.effectivePartitionKey; + + // Account name is the second token + tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.globalDatabaseAccountName); + rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[1]; + rntbdRequest.tokens[1] = rntbdRequest.globalDatabaseAccountName; + rntbdRequest.globalDatabaseAccountName.value.valueBytes = BytesSerializer.GetBytesForString(globalDatabaseAccountName, rntbdRequest); + rntbdRequest.globalDatabaseAccountName.isPresent = true; + + return BuildRequestCore( + request, + ref rntbdRequest, + replicaPathForDiagnostics: "thinClientReplica", + resourceOperation, + activityId, + bufferProvider, + out headerSize, + out bodySize); + } + + internal static SerializedRequest BuildRequest( + DocumentServiceRequest request, + string replicaPath, + ResourceOperation resourceOperation, + Guid activityId, + BufferProvider bufferProvider, + string transportRequestIDOverride, + out int headerSize, + out int? bodySize) + { + using RequestPool.EntityOwner owner = RequestPool.Instance.Get(); + RntbdConstants.Request rntbdRequest = owner.Entity; + + rntbdRequest.replicaPath.value.valueBytes = BytesSerializer.GetBytesForString(replicaPath, rntbdRequest); + rntbdRequest.replicaPath.isPresent = true; + + //When timeouts occur, "request" or requestHeaders can end up being referenced by multiple threads. + // Passing in TransportId as a parameter instead of using the property on the requestHeaders helps + // to prevent race conditions where the requestHeader property for one thread could be mutate by another. + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TransportRequestID, transportRequestIDOverride, rntbdRequest.transportRequestID, rntbdRequest); + + return BuildRequestCore( + request, + ref rntbdRequest, + replicaPath, + resourceOperation, + activityId, + bufferProvider, + out headerSize, + out bodySize); + } + + private static SerializedRequest BuildRequestCore( + DocumentServiceRequest request, + ref RntbdConstants.Request rntbdRequest, + string replicaPathForDiagnostics, + ResourceOperation resourceOperation, + Guid activityId, + BufferProvider bufferProvider, + out int headerSize, + out int? bodySize) + { + RntbdConstants.RntbdOperationType operationType = GetRntbdOperationType(resourceOperation.operationType); + RntbdConstants.RntbdResourceType resourceType = GetRntbdResourceType(resourceOperation.resourceType); + + // NOTE: when request.Headers is a "RequestNameValueCollection", requestHeaders is a reference to request.Headers + // and not a clone. It's important to keep this in mind when dealing with multiple threads that share the + // same request object. + if (request.Headers is not RequestNameValueCollection requestHeaders) + { + requestHeaders = RequestNameValueCollection.BuildRequestNameValueCollectionWithKnownHeadersOnly(request.Headers); + } + + // special-case headers (ones that don't come from request.headers, or ones that are a merge of + // merging multiple request.headers, or ones that are parsed from a string to an enum). + TransportSerialization.AddResourceIdOrPathHeaders(request, rntbdRequest); + TransportSerialization.AddDateHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddContinuation(requestHeaders, rntbdRequest); + TransportSerialization.AddMatchHeader(requestHeaders, operationType, rntbdRequest); + TransportSerialization.AddIfModifiedSinceHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddA_IMHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddIndexingDirectiveHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddMigrateCollectionDirectiveHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddConsistencyLevelHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddIsFanout(requestHeaders, rntbdRequest); + TransportSerialization.AddEntityId(request, rntbdRequest); + TransportSerialization.AddAllowScanOnQuery(requestHeaders, rntbdRequest); + TransportSerialization.AddEmitVerboseTracesInQuery(requestHeaders, rntbdRequest); + TransportSerialization.AddCanCharge(requestHeaders, rntbdRequest); + TransportSerialization.AddCanThrottle(requestHeaders, rntbdRequest); + TransportSerialization.AddProfileRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddEnableLowPrecisionOrderBy(requestHeaders, rntbdRequest); + TransportSerialization.AddPageSize(requestHeaders, rntbdRequest); + TransportSerialization.AddSupportSpatialLegacyCoordinates(requestHeaders, rntbdRequest); + TransportSerialization.AddUsePolygonsSmallerThanAHemisphere(requestHeaders, rntbdRequest); + TransportSerialization.AddEnableLogging(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateQuotaInfo(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateResourceCount(requestHeaders, rntbdRequest); + TransportSerialization.AddDisableRUPerMinuteUsage(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateQueryMetrics(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateQueryMetricsIndexUtilization(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateIndexMetricsV2(requestHeaders, rntbdRequest); + TransportSerialization.AddOptimisticDirectExecute(requestHeaders, rntbdRequest); + TransportSerialization.AddQueryForceScan(requestHeaders, rntbdRequest); + TransportSerialization.AddResponseContinuationTokenLimitInKb(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulatePartitionStatistics(requestHeaders, rntbdRequest); + TransportSerialization.AddRemoteStorageType(requestHeaders, rntbdRequest); + TransportSerialization.AddCollectionRemoteStorageSecurityIdentifier(requestHeaders, rntbdRequest); + TransportSerialization.AddCollectionChildResourceNameLimitInBytes(requestHeaders, rntbdRequest); + TransportSerialization.AddCollectionChildResourceContentLengthLimitInKB(requestHeaders, rntbdRequest); + TransportSerialization.AddUniqueIndexNameEncodingMode(requestHeaders, rntbdRequest); + TransportSerialization.AddUniqueIndexReIndexingState(requestHeaders, rntbdRequest); + TransportSerialization.AddCorrelatedActivityId(requestHeaders, rntbdRequest); + TransportSerialization.AddPopulateCollectionThroughputInfo(requestHeaders, rntbdRequest); + TransportSerialization.AddShareThroughput(requestHeaders, rntbdRequest); + TransportSerialization.AddIsReadOnlyScript(requestHeaders, rntbdRequest); +#if !COSMOSCLIENT + TransportSerialization.AddIsAutoScaleRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddIsServerlessEnabledStorageRefreshRequest(requestHeaders, rntbdRequest); +#endif + TransportSerialization.AddCanOfferReplaceComplete(requestHeaders, rntbdRequest); + TransportSerialization.AddIgnoreSystemLoweringMaxThroughput(requestHeaders, rntbdRequest); + TransportSerialization.AddExcludeSystemProperties(requestHeaders, rntbdRequest); + TransportSerialization.AddEnumerationDirection(request, requestHeaders, rntbdRequest); + TransportSerialization.AddFanoutOperationStateHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddStartAndEndKeys(request, requestHeaders, rntbdRequest); + TransportSerialization.AddContentSerializationFormat(requestHeaders, rntbdRequest); + TransportSerialization.AddSupportedSerializationFormats(requestHeaders, rntbdRequest); + TransportSerialization.AddIsUserRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddPreserveFullContent(requestHeaders, rntbdRequest); + TransportSerialization.AddIsRUPerGBEnforcementRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddIsOfferStorageRefreshRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddGetAllPartitionKeyStatistics(requestHeaders, rntbdRequest); + TransportSerialization.AddForceSideBySideIndexMigration(requestHeaders, rntbdRequest); + TransportSerialization.AddIsMigrateOfferToManualThroughputRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddIsMigrateOfferToAutopilotRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddSystemDocumentTypeHeader(requestHeaders, rntbdRequest); + TransportSerialization.AddTransactionMetaData(request, rntbdRequest); + TransportSerialization.AddTransactionCompletionFlag(request, rntbdRequest); + TransportSerialization.AddResourceTypes(requestHeaders, rntbdRequest); + TransportSerialization.AddUpdateMaxthroughputEverProvisioned(requestHeaders, rntbdRequest); + TransportSerialization.AddUseSystemBudget(requestHeaders, rntbdRequest); + TransportSerialization.AddTruncateMergeLogRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddRetriableWriteRequestMetadata(request, rntbdRequest); + TransportSerialization.AddRequestedCollectionType(requestHeaders, rntbdRequest); + TransportSerialization.AddIsThroughputCapRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddUpdateOfferStateToPending(requestHeaders, rntbdRequest); + TransportSerialization.AddUpdateOfferStateToRestorePending(requestHeaders, rntbdRequest); + TransportSerialization.AddMasterResourcesDeletionPending(requestHeaders, rntbdRequest); + TransportSerialization.AddIsInternalServerlessRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddOfferReplaceRURedistribution(requestHeaders, rntbdRequest); + TransportSerialization.AddIsMaterializedViewSourceSchemaReplaceBatchRequest(requestHeaders, rntbdRequest); + TransportSerialization.AddIsCassandraAlterTypeRequest(request, rntbdRequest); + TransportSerialization.AddHighPriorityForcedBackup(requestHeaders, rntbdRequest); + TransportSerialization.AddEnableConflictResolutionPolicyUpdate(requestHeaders, rntbdRequest); + TransportSerialization.AddAllowDocumentReadsInOfflineRegion(requestHeaders, rntbdRequest); + TransportSerialization.AddCosmosGatewayTransactionId(requestHeaders, rntbdRequest); + + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.Authorization, requestHeaders.Authorization, rntbdRequest.authorizationToken, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SessionToken, requestHeaders.SessionToken, rntbdRequest.sessionToken, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PreTriggerInclude, requestHeaders.PreTriggerInclude, rntbdRequest.preTriggerInclude, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PreTriggerExclude, requestHeaders.PreTriggerExclude, rntbdRequest.preTriggerExclude, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PostTriggerInclude, requestHeaders.PostTriggerInclude, rntbdRequest.postTriggerInclude, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PostTriggerExclude, requestHeaders.PostTriggerExclude, rntbdRequest.postTriggerExclude, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PartitionKey, requestHeaders.PartitionKey, rntbdRequest.partitionKey, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PartitionKeyRangeId, requestHeaders.PartitionKeyRangeId, rntbdRequest.partitionKeyRangeId, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ResourceTokenExpiry, requestHeaders.ResourceTokenExpiry, rntbdRequest.resourceTokenExpiry, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.FilterBySchemaResourceId, requestHeaders.FilterBySchemaResourceId, rntbdRequest.filterBySchemaRid, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ShouldBatchContinueOnError, requestHeaders.ShouldBatchContinueOnError, rntbdRequest.shouldBatchContinueOnError, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsBatchOrdered, requestHeaders.IsBatchOrdered, rntbdRequest.isBatchOrdered, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsBatchAtomic, requestHeaders.IsBatchAtomic, rntbdRequest.isBatchAtomic, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionPartitionIndex, requestHeaders.CollectionPartitionIndex, rntbdRequest.collectionPartitionIndex, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionServiceIndex, requestHeaders.CollectionServiceIndex, rntbdRequest.collectionServiceIndex, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.ResourceSchemaName, requestHeaders.ResourceSchemaName, rntbdRequest.resourceSchemaName, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.BindReplicaDirective, requestHeaders.BindReplicaDirective, rntbdRequest.bindReplicaDirective, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PrimaryMasterKey, requestHeaders.PrimaryMasterKey, rntbdRequest.primaryMasterKey, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SecondaryMasterKey, requestHeaders.SecondaryMasterKey, rntbdRequest.secondaryMasterKey, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PrimaryReadonlyKey, requestHeaders.PrimaryReadonlyKey, rntbdRequest.primaryReadonlyKey, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SecondaryReadonlyKey, requestHeaders.SecondaryReadonlyKey, rntbdRequest.secondaryReadonlyKey, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PartitionCount, requestHeaders.PartitionCount, rntbdRequest.partitionCount, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.CollectionRid, requestHeaders.CollectionRid, rntbdRequest.collectionRid, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.GatewaySignature, requestHeaders.GatewaySignature, rntbdRequest.gatewaySignature, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RemainingTimeInMsOnClientRequest, requestHeaders.RemainingTimeInMsOnClientRequest, rntbdRequest.remainingTimeInMsOnClientRequest, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ClientRetryAttemptCount, requestHeaders.ClientRetryAttemptCount, rntbdRequest.clientRetryAttemptCount, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TargetLsn, requestHeaders.TargetLsn, rntbdRequest.targetLsn, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TargetGlobalCommittedLsn, requestHeaders.TargetGlobalCommittedLsn, rntbdRequest.targetGlobalCommittedLsn, rntbdRequest); + + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RestoreMetadataFilter, requestHeaders.RestoreMetadataFilter, rntbdRequest.restoreMetadataFilter, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.RestoreParams, requestHeaders.RestoreParams, rntbdRequest.restoreParams, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PartitionResourceFilter, requestHeaders.PartitionResourceFilter, rntbdRequest.partitionResourceFilter, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.EnableDynamicRidRangeAllocation, requestHeaders.EnableDynamicRidRangeAllocation, rntbdRequest.enableDynamicRidRangeAllocation, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaOwnerRid, requestHeaders.SchemaOwnerRid, rntbdRequest.schemaOwnerRid, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaHash, requestHeaders.SchemaHash, rntbdRequest.schemaHash, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SchemaId, requestHeaders.SchemaId, rntbdRequest.collectionSchemaId, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsClientEncrypted, requestHeaders.IsClientEncrypted, rntbdRequest.isClientEncrypted, rntbdRequest); + + TransportSerialization.AddReturnPreferenceIfPresent(requestHeaders, rntbdRequest); + TransportSerialization.AddBinaryIdIfPresent(request, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.TimeToLiveInSeconds, requestHeaders.TimeToLiveInSeconds, rntbdRequest.timeToLiveInSeconds, rntbdRequest); + TransportSerialization.AddEffectivePartitionKeyIfPresent(request, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.BinaryPassthroughRequest, requestHeaders.BinaryPassthroughRequest, rntbdRequest.binaryPassthroughRequest, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.AllowTentativeWrites, requestHeaders.AllowTentativeWrites, rntbdRequest.allowTentativeWrites, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IncludeTentativeWrites, requestHeaders.IncludeTentativeWrites, rntbdRequest.includeTentativeWrites, rntbdRequest); TransportSerialization.AddMergeStaticIdIfPresent(request, rntbdRequest); + TransportSerialization.AddMergeStaticIdIfPresent(request, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.MaxPollingIntervalMilliseconds, requestHeaders.MaxPollingIntervalMilliseconds, rntbdRequest.maxPollingIntervalMilliseconds, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateLogStoreInfo, requestHeaders.PopulateLogStoreInfo, rntbdRequest.populateLogStoreInfo, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.MergeCheckPointGLSN, requestHeaders.MergeCheckPointGLSN, rntbdRequest.mergeCheckpointGLSNKeyName, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateUnflushedMergeEntryCount, requestHeaders.PopulateUnflushedMergeEntryCount, rntbdRequest.populateUnflushedMergeEntryCount, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.AddResourcePropertiesToResponse, requestHeaders.AddResourcePropertiesToResponse, rntbdRequest.addResourcePropertiesToResponse, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SystemRestoreOperation, requestHeaders.SystemRestoreOperation, rntbdRequest.systemRestoreOperation, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, requestHeaders.ChangeFeedStartFullFidelityIfNoneMatch, rntbdRequest.changeFeedStartFullFidelityIfNoneMatch, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SkipRefreshDatabaseAccountConfigs, requestHeaders.SkipRefreshDatabaseAccountConfigs, rntbdRequest.skipRefreshDatabaseAccountConfigs, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.IntendedCollectionRid, requestHeaders.IntendedCollectionRid, rntbdRequest.intendedCollectionRid, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.UseArchivalPartition, requestHeaders.UseArchivalPartition, rntbdRequest.useArchivalPartition, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.CollectionTruncate, requestHeaders.CollectionTruncate, rntbdRequest.collectionTruncate, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SDKSupportedCapabilities, requestHeaders.SDKSupportedCapabilities, rntbdRequest.sDKSupportedCapabilities, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateUniqueIndexReIndexProgress, requestHeaders.PopulateUniqueIndexReIndexProgress, rntbdRequest.populateUniqueIndexReIndexProgress, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsMaterializedViewBuild, requestHeaders.IsMaterializedViewBuild, rntbdRequest.isMaterializedViewBuild, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.BuilderClientIdentifier, requestHeaders.BuilderClientIdentifier, rntbdRequest.builderClientIdentifier, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SourceCollectionIfMatch, requestHeaders.SourceCollectionIfMatch, rntbdRequest.sourceCollectionIfMatch, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateAnalyticalMigrationProgress, requestHeaders.PopulateAnalyticalMigrationProgress, rntbdRequest.populateAnalyticalMigrationProgress, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ShouldReturnCurrentServerDateTime, requestHeaders.ShouldReturnCurrentServerDateTime, rntbdRequest.shouldReturnCurrentServerDateTime, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacUserId, requestHeaders.RbacUserId, rntbdRequest.rbacUserId, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacAction, requestHeaders.RbacAction, rntbdRequest.rbacAction, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.RbacResource, requestHeaders.RbacResource, rntbdRequest.rbacResource, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ChangeFeedWireFormatVersion, requestHeaders.ChangeFeedWireFormatVersion, rntbdRequest.changeFeedWireFormatVersion, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateByokEncryptionProgress, requestHeaders.PopulateByokEncryptionProgress, rntbdRequest.populateBYOKEncryptionProgress, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.UseUserBackgroundBudget, requestHeaders.UseUserBackgroundBudget, rntbdRequest.useUserBackgroundBudget, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, requestHeaders.IncludePhysicalPartitionThroughputInfo, rntbdRequest.includePhysicalPartitionThroughputInfo, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PopulateOldestActiveSchemaId, requestHeaders.PopulateOldestActiveSchemaId, rntbdRequest.populateOldestActiveSchemaId, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.ForceDatabaseAccountUpdate, requestHeaders.ForceDatabaseAccountUpdate, rntbdRequest.forceDatabaseAccountUpdate, rntbdRequest); + TransportSerialization.AddPriorityLevelHeader(request, HttpConstants.HttpHeaders.PriorityLevel, requestHeaders.PriorityLevel, requestHeaders, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.AllowRestoreParamsUpdate, requestHeaders.AllowRestoreParamsUpdate, rntbdRequest.allowRestoreParamsUpdate, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.PruneCollectionSchemas, requestHeaders.PruneCollectionSchemas, rntbdRequest.pruneCollectionSchemas, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.IsMigratedFixedCollection, requestHeaders.IsMigratedFixedCollection, rntbdRequest.isMigratedFixedCollection, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations, requestHeaders.PopulateMinGLSNForDocumentOperations, rntbdRequest.populateMinGLSNForDocumentOperations, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, requestHeaders.PopulateHighestTentativeWriteLLSN, rntbdRequest.populateHighestTentativeWriteLLSN, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCapacityType, requestHeaders.PopulateCapacityType, rntbdRequest.populateCapacityType, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceParent, requestHeaders.TraceParent, rntbdRequest.traceParent, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceState, requestHeaders.TraceState, rntbdRequest.traceState, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.ClientIpAddress, requestHeaders.ClientIpAddress, rntbdRequest.clientIpAddress, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.IsRequestNotAuthorized, requestHeaders.IsRequestNotAuthorized, rntbdRequest.isRequestNotAuthorized, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.StartEpkHash, headerStringValue: null, rntbdRequest.startEpkHash, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.EndEpkHash, headerStringValue: null, rntbdRequest.endEpkHash, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, requestHeaders.PopulateCurrentPartitionThroughputInfo, rntbdRequest.populateCurrentPartitionThroughputInfo, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateDocumentRecordCount, requestHeaders.PopulateDocumentRecordCount, rntbdRequest.populateDocumentRecordCount, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateUserStrings, requestHeaders.PopulateUserStrings, rntbdRequest.populateUserStrings, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.SkipThroughputCapValidation, requestHeaders.SkipThroughputCapValidation, rntbdRequest.skipThroughputCapValidation, rntbdRequest); + + // will be null in case of direct, which is fine - BE will use the value from the connection context message. + // When this is used in Gateway, the header value will be populated with the proxied HTTP request's header, and + // BE will respect the per-request value. + TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.Version, requestHeaders.Version, rntbdRequest.clientVersion, rntbdRequest); + + int metadataLength = (sizeof(uint) + sizeof(ushort) + sizeof(ushort) + BytesSerializer.GetSizeOfGuid()); + int headerAndMetadataLength = metadataLength; + + int allocationLength = 0; + + bodySize = null; + int bodyLength = 0; + CloneableStream clonedStream = null; + if (request.CloneableBody != null) + { + clonedStream = request.CloneableBody.Clone(); + bodyLength = (int)clonedStream.Length; + } + + BufferProvider.DisposableBuffer contextMessage; + + if (bodyLength > 0) + { + allocationLength += sizeof(uint); + + rntbdRequest.payloadPresent.value.valueByte = 0x01; + rntbdRequest.payloadPresent.isPresent = true; + } + else + { + rntbdRequest.payloadPresent.value.valueByte = 0x00; + rntbdRequest.payloadPresent.isPresent = true; + } + + // Once all metadata tokens are set, we can calculate the length. + headerAndMetadataLength += rntbdRequest.CalculateLength(); // metadata tokens + allocationLength += headerAndMetadataLength; + + contextMessage = bufferProvider.GetBuffer(allocationLength); + + BytesSerializer writer = new BytesSerializer(contextMessage.Buffer.Array, allocationLength); + + // header + writer.Write((uint)headerAndMetadataLength); + writer.Write((ushort)resourceType); + writer.Write((ushort)operationType); + writer.Write(activityId); + int actualWritten = metadataLength; + + // metadata + rntbdRequest.SerializeToBinaryWriter(ref writer, out int tokensLength); + actualWritten += tokensLength; + + if (actualWritten != headerAndMetadataLength) + { + clonedStream?.Dispose(); + DefaultTrace.TraceCritical( + "Bug in RNTBD token serialization. Calculated header size: {0}. Actual header size: {1}", + headerAndMetadataLength, actualWritten); + throw new InternalServerErrorException(); + } + + if (bodyLength > 0) + { + writer.Write((UInt32)bodyLength); + bodySize = sizeof(UInt32) + bodyLength; + } + + headerSize = headerAndMetadataLength; + + const int HeaderSizeWarningThreshold = 128 * 1024; + const int BodySizeWarningThreshold = 16 * 1024 * 1024; + if (headerSize > HeaderSizeWarningThreshold) + { + DefaultTrace.TraceWarning( + "The request header is large. Header size: {0}. Warning threshold: {1}. " + + "RID: {2}. Resource type: {3}. Operation: {4}. Address: {5}", + headerSize, HeaderSizeWarningThreshold, request.ResourceAddress, + request.ResourceType, resourceOperation, replicaPathForDiagnostics); + } + if (bodySize > BodySizeWarningThreshold) + { + DefaultTrace.TraceWarning( + "The request body is large. Body size: {0}. Warning threshold: {1}. " + + "RID: {2}. Resource type: {3}. Operation: {4}. Address: {5}", + bodySize, BodySizeWarningThreshold, request.ResourceAddress, + request.ResourceType, resourceOperation, replicaPathForDiagnostics); + } + + return new SerializedRequest(contextMessage, clonedStream); + } + + internal static byte[] BuildContextRequest(Guid activityId, UserAgentContainer userAgent, RntbdConstants.CallerId callerId, bool enableChannelMultiplexing) + { + byte[] activityIdBytes = activityId.ToByteArray(); + + RntbdConstants.ConnectionContextRequest request = new RntbdConstants.ConnectionContextRequest(); + request.protocolVersion.value.valueULong = RntbdConstants.CurrentProtocolVersion; + request.protocolVersion.isPresent = true; + + request.clientVersion.value.valueBytes = HttpConstants.Versions.CurrentVersionUTF8; + request.clientVersion.isPresent = true; + + request.userAgent.value.valueBytes = userAgent.UserAgentUTF8; + request.userAgent.isPresent = true; + + request.callerId.isPresent = false; + if(callerId != RntbdConstants.CallerId.Invalid) + { + request.callerId.value.valueByte = (byte)callerId; + request.callerId.isPresent = true; + } + + request.enableChannelMultiplexing.isPresent = true; + request.enableChannelMultiplexing.value.valueByte = enableChannelMultiplexing ? (byte)1 : (byte)0; + + int length = (sizeof(UInt32) + sizeof(UInt16) + sizeof(UInt16) + activityIdBytes.Length); // header + length += request.CalculateLength(); // tokens + + byte[] contextMessage = new byte[length]; + + BytesSerializer writer = new BytesSerializer(contextMessage, length); + + // header + writer.Write(length); + writer.Write((ushort)RntbdConstants.RntbdResourceType.Connection); + writer.Write((ushort)RntbdConstants.RntbdOperationType.Connection); + writer.Write(activityIdBytes); + + // metadata + request.SerializeToBinaryWriter(ref writer, out _); + + return contextMessage; + } + + internal static StoreResponse MakeStoreResponse( + StatusCodes status, + Guid activityId, + Stream body, + string serverVersion, + ref BytesDeserializer rntbdHeaderReader) => new() + { + Headers = HeadersTransportSerialization.BuildStoreResponseNameValueCollection( + activityId, + serverVersion, + ref rntbdHeaderReader), + ResponseBody = body, + Status = (int)status + }; + + internal static RntbdHeader DecodeRntbdHeader(byte[] header) + { + StatusCodes status = (StatusCodes) BitConverter.ToUInt32(header, 4); + Guid activityId = BytesSerializer.ReadGuidFromBytes(new ArraySegment(header, 8, 16)); + return new RntbdHeader(status, activityId); + } + + internal static RntbdConstants.RntbdOperationType GetRntbdOperationType(OperationType operationType) + { + switch (operationType) + { + case OperationType.Create: + return RntbdConstants.RntbdOperationType.Create; + case OperationType.Delete: + return RntbdConstants.RntbdOperationType.Delete; + case OperationType.ExecuteJavaScript: + return RntbdConstants.RntbdOperationType.ExecuteJavaScript; + case OperationType.Query: + return RntbdConstants.RntbdOperationType.Query; + case OperationType.Read: + return RntbdConstants.RntbdOperationType.Read; + case OperationType.ReadFeed: + return RntbdConstants.RntbdOperationType.ReadFeed; + case OperationType.Replace: + return RntbdConstants.RntbdOperationType.Replace; + case OperationType.SqlQuery: + return RntbdConstants.RntbdOperationType.SQLQuery; + case OperationType.Patch: + return RntbdConstants.RntbdOperationType.Patch; + case OperationType.Head: + return RntbdConstants.RntbdOperationType.Head; + case OperationType.HeadFeed: + return RntbdConstants.RntbdOperationType.HeadFeed; + case OperationType.Upsert: + return RntbdConstants.RntbdOperationType.Upsert; + case OperationType.BatchApply: + return RntbdConstants.RntbdOperationType.BatchApply; + case OperationType.Batch: + return RntbdConstants.RntbdOperationType.Batch; + case OperationType.CompleteUserTransaction: + return RntbdConstants.RntbdOperationType.CompleteUserTransaction; + case OperationType.MetadataCheckAccess: + return RntbdConstants.RntbdOperationType.MetadataCheckAccess; +#if !COSMOSCLIENT + case OperationType.Crash: + return RntbdConstants.RntbdOperationType.Crash; + case OperationType.Pause: + return RntbdConstants.RntbdOperationType.Pause; + case OperationType.Recreate: + return RntbdConstants.RntbdOperationType.Recreate; + case OperationType.Recycle: + return RntbdConstants.RntbdOperationType.Recycle; + case OperationType.Resume: + return RntbdConstants.RntbdOperationType.Resume; + case OperationType.Stop: + return RntbdConstants.RntbdOperationType.Stop; + case OperationType.ForceConfigRefresh: + return RntbdConstants.RntbdOperationType.ForceConfigRefresh; + case OperationType.Throttle: + return RntbdConstants.RntbdOperationType.Throttle; + case OperationType.PreCreateValidation: + return RntbdConstants.RntbdOperationType.PreCreateValidation; + case OperationType.GetSplitPoint: + return RntbdConstants.RntbdOperationType.GetSplitPoint; + case OperationType.AbortSplit: + return RntbdConstants.RntbdOperationType.AbortSplit; + case OperationType.CompleteSplit: + return RntbdConstants.RntbdOperationType.CompleteSplit; + case OperationType.CompleteMergeOnMaster: + return RntbdConstants.RntbdOperationType.CompleteMergeOnMaster; + case OperationType.CompleteMergeOnTarget: + return RntbdConstants.RntbdOperationType.CompleteMergeOnTarget; + case OperationType.OfferUpdateOperation: + return RntbdConstants.RntbdOperationType.OfferUpdateOperation; + case OperationType.OfferPreGrowValidation: + return RntbdConstants.RntbdOperationType.OfferPreGrowValidation; + case OperationType.BatchReportThroughputUtilization: + return RntbdConstants.RntbdOperationType.BatchReportThroughputUtilization; + case OperationType.AbortPartitionMigration: + return RntbdConstants.RntbdOperationType.AbortPartitionMigration; + case OperationType.CompletePartitionMigration: + return RntbdConstants.RntbdOperationType.CompletePartitionMigration; + case OperationType.PreReplaceValidation: + return RntbdConstants.RntbdOperationType.PreReplaceValidation; + case OperationType.MigratePartition: + return RntbdConstants.RntbdOperationType.MigratePartition; + case OperationType.MasterReplaceOfferOperation: + return RntbdConstants.RntbdOperationType.MasterReplaceOfferOperation; + case OperationType.ProvisionedCollectionOfferUpdateOperation: + return RntbdConstants.RntbdOperationType.ProvisionedCollectionOfferUpdateOperation; + case OperationType.InitiateDatabaseOfferPartitionShrink: + return RntbdConstants.RntbdOperationType.InitiateDatabaseOfferPartitionShrink; + case OperationType.CompleteDatabaseOfferPartitionShrink: + return RntbdConstants.RntbdOperationType.CompleteDatabaseOfferPartitionShrink; + case OperationType.EnsureSnapshotOperation: + return RntbdConstants.RntbdOperationType.EnsureSnapshotOperation; + case OperationType.GetSplitPoints: + return RntbdConstants.RntbdOperationType.GetSplitPoints; + case OperationType.ForcePartitionBackup: + return RntbdConstants.RntbdOperationType.ForcePartitionBackup; + case OperationType.MasterInitiatedProgressCoordination: + return RntbdConstants.RntbdOperationType.MasterInitiatedProgressCoordination; + case OperationType.CreateSystemSnapshot: + return RntbdConstants.RntbdOperationType.CreateSystemSnapshot; + case OperationType.CreateRidRangeResources: + return RntbdConstants.RntbdOperationType.CreateRidRangeResources; + case OperationType.UpdateFailoverPriorityList: + return RntbdConstants.RntbdOperationType.UpdateFailoverPriorityList; + case OperationType.GetStorageAuthToken: + return RntbdConstants.RntbdOperationType.GetStorageAuthToken; + case OperationType.UpdatePartitionThroughput: + return RntbdConstants.RntbdOperationType.UpdatePartitionThroughput; + case OperationType.Truncate: + return RntbdConstants.RntbdOperationType.Truncate; +#endif + case OperationType.AddComputeGatewayRequestCharges: + return RntbdConstants.RntbdOperationType.AddComputeGatewayRequestCharges; + default: + throw new ArgumentException( + string.Format(CultureInfo.InvariantCulture, "Invalid operation type: {0}", operationType), + "operationType"); + } + } + + internal static RntbdConstants.RntbdResourceType GetRntbdResourceType(ResourceType resourceType) + { + switch (resourceType) + { + case ResourceType.Attachment: + return RntbdConstants.RntbdResourceType.Attachment; + case ResourceType.Collection: + return RntbdConstants.RntbdResourceType.Collection; + case ResourceType.Conflict: + return RntbdConstants.RntbdResourceType.Conflict; + case ResourceType.Database: + return RntbdConstants.RntbdResourceType.Database; + case ResourceType.Document: + return RntbdConstants.RntbdResourceType.Document; + case ResourceType.Record: + return RntbdConstants.RntbdResourceType.Record; + case ResourceType.Permission: + return RntbdConstants.RntbdResourceType.Permission; + case ResourceType.StoredProcedure: + return RntbdConstants.RntbdResourceType.StoredProcedure; + case ResourceType.Trigger: + return RntbdConstants.RntbdResourceType.Trigger; + case ResourceType.User: + return RntbdConstants.RntbdResourceType.User; + case ResourceType.ClientEncryptionKey: + return RntbdConstants.RntbdResourceType.ClientEncryptionKey; + case ResourceType.UserDefinedType: + return RntbdConstants.RntbdResourceType.UserDefinedType; + case ResourceType.UserDefinedFunction: + return RntbdConstants.RntbdResourceType.UserDefinedFunction; + case ResourceType.Offer: + return RntbdConstants.RntbdResourceType.Offer; + case ResourceType.DatabaseAccount: + return RntbdConstants.RntbdResourceType.DatabaseAccount; + case ResourceType.PartitionKeyRange: + return RntbdConstants.RntbdResourceType.PartitionKeyRange; + case ResourceType.Schema: + return RntbdConstants.RntbdResourceType.Schema; + case ResourceType.BatchApply: + return RntbdConstants.RntbdResourceType.BatchApply; + case ResourceType.ComputeGatewayCharges: + return RntbdConstants.RntbdResourceType.ComputeGatewayCharges; + case ResourceType.PartitionKey: + return RntbdConstants.RntbdResourceType.PartitionKey; + case ResourceType.PartitionedSystemDocument: + return RntbdConstants.RntbdResourceType.PartitionedSystemDocument; + case ResourceType.SystemDocument: + return RntbdConstants.RntbdResourceType.SystemDocument; + case ResourceType.RoleDefinition: + return RntbdConstants.RntbdResourceType.RoleDefinition; + case ResourceType.RoleAssignment: + return RntbdConstants.RntbdResourceType.RoleAssignment; + case ResourceType.Transaction: + return RntbdConstants.RntbdResourceType.Transaction; + case ResourceType.InteropUser: + return RntbdConstants.RntbdResourceType.InteropUser; + case ResourceType.AuthPolicyElement: + return RntbdConstants.RntbdResourceType.AuthPolicyElement; + case ResourceType.RetriableWriteCachedResponse: + return RntbdConstants.RntbdResourceType.RetriableWriteCachedResponse; + case ResourceType.EncryptionScope: + return RntbdConstants.RntbdResourceType.EncryptionScope; +#if !COSMOSCLIENT + case ResourceType.Module: + return RntbdConstants.RntbdResourceType.Module; + case ResourceType.ModuleCommand: + return RntbdConstants.RntbdResourceType.ModuleCommand; + case ResourceType.TransportControlCommand: + return RntbdConstants.RntbdResourceType.TransportControlCommand; + case ResourceType.Replica: + return RntbdConstants.RntbdResourceType.Replica; + case ResourceType.PartitionSetInformation: + return RntbdConstants.RntbdResourceType.PartitionSetInformation; + case ResourceType.XPReplicatorAddress: + return RntbdConstants.RntbdResourceType.XPReplicatorAddress; + case ResourceType.MasterPartition: + return RntbdConstants.RntbdResourceType.MasterPartition; + case ResourceType.ServerPartition: + return RntbdConstants.RntbdResourceType.ServerPartition; + case ResourceType.Topology: + return RntbdConstants.RntbdResourceType.Topology; + case ResourceType.RestoreMetadata: + return RntbdConstants.RntbdResourceType.RestoreMetadata; + case ResourceType.RidRange: + return RntbdConstants.RntbdResourceType.RidRange; + case ResourceType.VectorClock: + return RntbdConstants.RntbdResourceType.VectorClock; + case ResourceType.Snapshot: + return RntbdConstants.RntbdResourceType.Snapshot; + case ResourceType.StorageAuthToken: + return RntbdConstants.RntbdResourceType.StorageAuthToken; + +#endif + default: + throw new ArgumentException( + string.Format(CultureInfo.InvariantCulture, "Invalid resource type: {0}", resourceType), + "resourceType"); + } + } + + private static void AddMatchHeader(RequestNameValueCollection requestHeaders, RntbdConstants.RntbdOperationType operationType, RntbdConstants.Request rntbdRequest) + { + string match; + switch (operationType) + { + case RntbdConstants.RntbdOperationType.Read: + case RntbdConstants.RntbdOperationType.ReadFeed: + match = requestHeaders.IfNoneMatch; + break; + default: + match = requestHeaders.IfMatch; + break; + } + + if (!string.IsNullOrEmpty(match)) + { + rntbdRequest.match.value.valueBytes = BytesSerializer.GetBytesForString(match, rntbdRequest); + rntbdRequest.match.isPresent = true; + } + } + + private static void AddIfModifiedSinceHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.IfModifiedSince; + if (!string.IsNullOrEmpty(headerValue)) + { + rntbdRequest.ifModifiedSince.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); + rntbdRequest.ifModifiedSince.isPresent = true; + } + } + + private static void AddA_IMHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.A_IM; + if (!string.IsNullOrEmpty(headerValue)) + { + rntbdRequest.a_IM.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); + rntbdRequest.a_IM.isPresent = true; + } + } + + private static void AddDateHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string dateHeader = Helpers.GetDateHeader(requestHeaders); + if (!string.IsNullOrEmpty(dateHeader)) + { + rntbdRequest.date.value.valueBytes = BytesSerializer.GetBytesForString(dateHeader, rntbdRequest); + rntbdRequest.date.isPresent = true; + } + } + + private static void AddContinuation(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.Continuation)) + { + rntbdRequest.continuationToken.value.valueBytes = BytesSerializer.GetBytesForString(requestHeaders.Continuation, rntbdRequest); + rntbdRequest.continuationToken.isPresent = true; + } + } + + private static void AddResourceIdOrPathHeaders(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(request.ResourceId)) + { + // name based can also have ResourceId because gateway might generate it. + rntbdRequest.resourceId.value.valueBytes = ResourceId.Parse(request.ResourceType, request.ResourceId); + rntbdRequest.resourceId.isPresent = true; + } + + if (request.IsNameBased) + { + // short-cut, if resourcetype == document, and the names are parsed out of the URI then use parsed values and avoid + // reparsing and allocating. + if (request.ResourceType == ResourceType.Document && request.IsResourceNameParsedFromUri) + { + TransportSerialization.SetResourceIdHeadersFromDocumentServiceRequest(request, rntbdRequest); + } + else + { + TransportSerialization.SetResourceIdHeadersFromUri(request, rntbdRequest); + } + } + } + + private static void SetResourceIdHeadersFromUri(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + // Assumption: format is like "dbs/dbName/colls/collName/docs/docName" or "/dbs/dbName/colls/collName", + // not "apps/appName/partitions/partitionKey/replicas/replicaId/dbs/dbName" + string[] fragments = request.ResourceAddress.Split( + TransportSerialization.UrlTrim, + StringSplitOptions.RemoveEmptyEntries); + + if (fragments.Length >= 2) + { + switch (fragments[0]) + { + case Paths.DatabasesPathSegment: + rntbdRequest.databaseName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.databaseName.isPresent = true; + break; + case Paths.SnapshotsPathSegment: + rntbdRequest.snapshotName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.snapshotName.isPresent = true; + break; + case Paths.RoleDefinitionsPathSegment: + rntbdRequest.roleDefinitionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.roleDefinitionName.isPresent = true; + break; + case Paths.RoleAssignmentsPathSegment: + rntbdRequest.roleAssignmentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.roleAssignmentName.isPresent = true; + break; + case Paths.InteropUsersPathSegment: + rntbdRequest.interopUserName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.interopUserName.isPresent = true; + break; + case Paths.AuthPolicyElementsPathSegment: + rntbdRequest.authPolicyElementName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.authPolicyElementName.isPresent = true; + break; + case Paths.EncryptionScopesPathSegment: + rntbdRequest.encryptionScopeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[1], rntbdRequest); + rntbdRequest.encryptionScopeName.isPresent = true; + break; + default: + throw new BadRequestException(); + } + } + + if (fragments.Length >= 4) + { + switch (fragments[2]) + { + case Paths.CollectionsPathSegment: + rntbdRequest.collectionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); + rntbdRequest.collectionName.isPresent = true; + break; + case Paths.ClientEncryptionKeysPathSegment: + rntbdRequest.clientEncryptionKeyName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); + rntbdRequest.clientEncryptionKeyName.isPresent = true; + break; + case Paths.UsersPathSegment: + rntbdRequest.userName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); + rntbdRequest.userName.isPresent = true; + break; + case Paths.UserDefinedTypesPathSegment: + rntbdRequest.userDefinedTypeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[3], rntbdRequest); + rntbdRequest.userDefinedTypeName.isPresent = true; + break; + } + } + + if (fragments.Length >= 6) + { + switch (fragments[4]) + { + case Paths.DocumentsPathSegment: + rntbdRequest.documentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.documentName.isPresent = true; + break; + case Paths.StoredProceduresPathSegment: + rntbdRequest.storedProcedureName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.storedProcedureName.isPresent = true; + break; + case Paths.PermissionsPathSegment: + rntbdRequest.permissionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.permissionName.isPresent = true; + break; + case Paths.UserDefinedFunctionsPathSegment: + rntbdRequest.userDefinedFunctionName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.userDefinedFunctionName.isPresent = true; + break; + case Paths.TriggersPathSegment: + rntbdRequest.triggerName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.triggerName.isPresent = true; + break; + case Paths.ConflictsPathSegment: + rntbdRequest.conflictName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.conflictName.isPresent = true; + break; + case Paths.PartitionKeyRangesPathSegment: + rntbdRequest.partitionKeyRangeName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.partitionKeyRangeName.isPresent = true; + break; + case Paths.SchemasPathSegment: + rntbdRequest.schemaName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.schemaName.isPresent = true; + break; + case Paths.PartitionedSystemDocumentsPathSegment: + rntbdRequest.systemDocumentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.systemDocumentName.isPresent = true; + break; + case Paths.SystemDocumentsPathSegment: + rntbdRequest.systemDocumentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[5], rntbdRequest); + rntbdRequest.systemDocumentName.isPresent = true; + break; + } + } + + if (fragments.Length >= 8) + { + switch (fragments[6]) + { + case Paths.AttachmentsPathSegment: + rntbdRequest.attachmentName.value.valueBytes = BytesSerializer.GetBytesForString(fragments[7], rntbdRequest); + rntbdRequest.attachmentName.isPresent = true; + break; + } + } + } + + private static void SetResourceIdHeadersFromDocumentServiceRequest(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (string.IsNullOrEmpty(request.DatabaseName)) + { + throw new ArgumentException(nameof(request.DatabaseName)); + } + + rntbdRequest.databaseName.value.valueBytes = BytesSerializer.GetBytesForString(request.DatabaseName, rntbdRequest); + rntbdRequest.databaseName.isPresent = true; + + if (string.IsNullOrEmpty(request.CollectionName)) + { + throw new ArgumentException(nameof(request.CollectionName)); + } + + rntbdRequest.collectionName.value.valueBytes = BytesSerializer.GetBytesForString(request.CollectionName, rntbdRequest); + rntbdRequest.collectionName.isPresent = true; + + // even though it's a document request, the Request URI can be made against the collection (e.g. for Upserts) + // if document name specified then add it. + if (!string.IsNullOrEmpty(request.DocumentName)) + { + rntbdRequest.documentName.value.valueBytes = BytesSerializer.GetBytesForString(request.DocumentName, rntbdRequest); + rntbdRequest.documentName.isPresent = true; + } + } + + private static void AddBinaryIdIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + object binaryPayload; + if (request.Properties != null && request.Properties.TryGetValue(WFConstants.BackendHeaders.BinaryId, out binaryPayload)) + { + if (binaryPayload is byte[] binaryBytesData) + { + rntbdRequest.binaryId.value.valueBytes = binaryBytesData; + } +#if COSMOSCLIENT + else if (binaryPayload is ReadOnlyMemory binaryRomBytesData) + { + rntbdRequest.binaryId.value.valueBytes = binaryRomBytesData; + } +#endif + else + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.BinaryId); + } + + rntbdRequest.binaryId.isPresent = true; + } + else if (TransportSerialization.TryGetHeaderValueString(request, WFConstants.BackendHeaders.BinaryId, out string binaryId)) + { + rntbdRequest.binaryId.value.valueBytes = System.Convert.FromBase64String(binaryId); + rntbdRequest.binaryId.isPresent = true; + } + } + + private static void AddReturnPreferenceIfPresent(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string value = requestHeaders.Prefer; + + if (!string.IsNullOrEmpty(value)) + { + if (string.Equals(value, HttpConstants.HttpHeaderValues.PreferReturnMinimal, StringComparison.OrdinalIgnoreCase)) + { + rntbdRequest.returnPreference.value.valueByte = (byte)0x01; + rntbdRequest.returnPreference.isPresent = true; + } + else if (string.Equals(value, HttpConstants.HttpHeaderValues.PreferReturnRepresentation, StringComparison.OrdinalIgnoreCase)) + { + rntbdRequest.returnPreference.value.valueByte = (byte)0x00; + rntbdRequest.returnPreference.isPresent = true; + } + } + } + + private static void AddEffectivePartitionKeyIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (request.Properties == null) + { + return; + } + + object binaryPayload; + if (request.Properties.TryGetValue(WFConstants.BackendHeaders.EffectivePartitionKey, out binaryPayload)) + { + byte[] binaryData = binaryPayload as byte[]; + if (binaryData == null) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.EffectivePartitionKey); + } + + rntbdRequest.effectivePartitionKey.value.valueBytes = binaryData; + rntbdRequest.effectivePartitionKey.isPresent = true; + } + } + + private static bool TryGetHeaderValueString(DocumentServiceRequest request, string headerName, out string headerValue) + { + headerValue = null; + + if (request.Headers != null) + { + headerValue = request.Headers.Get(headerName); + } + + return !string.IsNullOrWhiteSpace(headerValue); + } + + private static void AddMergeStaticIdIfPresent(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (request.Properties == null) + { + return; + } + + object binaryPayload; + if (request.Properties.TryGetValue(WFConstants.BackendHeaders.MergeStaticId, out binaryPayload)) + { + if (binaryPayload is byte[] binaryData) + { + rntbdRequest.mergeStaticId.value.valueBytes = binaryData; + } +#if COSMOSCLIENT + else if (binaryPayload is ReadOnlyMemory binaryRomData) + { + rntbdRequest.mergeStaticId.value.valueBytes = binaryRomData; + } +#endif + else + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.MergeStaticId); + } + + rntbdRequest.mergeStaticId.isPresent = true; + } + } + + private static void AddEntityId(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(request.EntityId)) + { + rntbdRequest.entityId.value.valueBytes = BytesSerializer.GetBytesForString(request.EntityId, rntbdRequest); + rntbdRequest.entityId.isPresent = true; + } + } + + private static void AddIndexingDirectiveHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IndexingDirective)) + { + RntbdConstants.RntbdIndexingDirective rntbdDirective = RntbdConstants.RntbdIndexingDirective.Invalid; + IndexingDirective directive; + if (!Enum.TryParse(requestHeaders.IndexingDirective, true, out directive)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.IndexingDirective, typeof(IndexingDirective).Name)); + } + + switch (directive) + { + case IndexingDirective.Default: + rntbdDirective = RntbdConstants.RntbdIndexingDirective.Default; + break; + case IndexingDirective.Exclude: + rntbdDirective = RntbdConstants.RntbdIndexingDirective.Exclude; + break; + case IndexingDirective.Include: + rntbdDirective = RntbdConstants.RntbdIndexingDirective.Include; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.IndexingDirective, typeof(IndexingDirective).Name)); + } + + rntbdRequest.indexingDirective.value.valueByte = (byte) rntbdDirective; + rntbdRequest.indexingDirective.isPresent = true; + } + } + + private static void AddMigrateCollectionDirectiveHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.MigrateCollectionDirective)) + { + RntbdConstants.RntbdMigrateCollectionDirective rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Invalid; + MigrateCollectionDirective directive; + if (!Enum.TryParse(requestHeaders.MigrateCollectionDirective, true, out directive)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.MigrateCollectionDirective, typeof(MigrateCollectionDirective).Name)); + } + + switch (directive) + { + case MigrateCollectionDirective.Freeze: + rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Freeze; + break; + case MigrateCollectionDirective.Thaw: + rntbdDirective = RntbdConstants.RntbdMigrateCollectionDirective.Thaw; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.MigrateCollectionDirective, typeof(MigrateCollectionDirective).Name)); + } + + rntbdRequest.migrateCollectionDirective.value.valueByte = (byte) rntbdDirective; + rntbdRequest.migrateCollectionDirective.isPresent = true; + } + } + + private static void AddConsistencyLevelHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ConsistencyLevel)) + { + RntbdConstants.RntbdConsistencyLevel rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Invalid; + ConsistencyLevel consistencyLevel; + if (!Enum.TryParse(requestHeaders.ConsistencyLevel, true, out consistencyLevel)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ConsistencyLevel, typeof(ConsistencyLevel).Name)); + } + + switch (consistencyLevel) + { + case ConsistencyLevel.Strong: + rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Strong; + break; + case ConsistencyLevel.BoundedStaleness: + rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.BoundedStaleness; + break; + case ConsistencyLevel.Session: + rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Session; + break; + case ConsistencyLevel.Eventual: + rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.Eventual; + break; + case ConsistencyLevel.ConsistentPrefix: + rntbdConsistencyLevel = RntbdConstants.RntbdConsistencyLevel.ConsistentPrefix; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ConsistencyLevel, typeof(ConsistencyLevel).Name)); + } + + rntbdRequest.consistencyLevel.value.valueByte = (byte) rntbdConsistencyLevel; + rntbdRequest.consistencyLevel.isPresent = true; + } + } + + private static void AddIsThroughputCapRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsThroughputCapRequest)) + { + rntbdRequest.isThroughputCapRequest.value.valueByte = (requestHeaders.IsThroughputCapRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isThroughputCapRequest.isPresent = true; + } + } + + private static void AddIsFanout(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsFanoutRequest)) + { + rntbdRequest.isFanout.value.valueByte = (requestHeaders.IsFanoutRequest.Equals(bool.TrueString)) ? (byte) 0x01 : (byte) 0x00; + rntbdRequest.isFanout.isPresent = true; + } + } + + private static void AddAllowScanOnQuery(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EnableScanInQuery)) + { + rntbdRequest.enableScanInQuery.value.valueByte = (requestHeaders.EnableScanInQuery. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.enableScanInQuery.isPresent = true; + } + } + + private static void AddEnableLowPrecisionOrderBy(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EnableLowPrecisionOrderBy)) + { + rntbdRequest.enableLowPrecisionOrderBy.value.valueByte = (requestHeaders.EnableLowPrecisionOrderBy. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.enableLowPrecisionOrderBy.isPresent = true; + } + } + + private static void AddEmitVerboseTracesInQuery(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EmitVerboseTracesInQuery)) + { + rntbdRequest.emitVerboseTracesInQuery.value.valueByte = (requestHeaders.EmitVerboseTracesInQuery. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.emitVerboseTracesInQuery.isPresent = true; + } + } + + private static void AddCanCharge(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.CanCharge)) + { + rntbdRequest.canCharge.value.valueByte = (requestHeaders.CanCharge. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.canCharge.isPresent = true; + } + } + + private static void AddCanThrottle(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.CanThrottle)) + { + rntbdRequest.canThrottle.value.valueByte = (requestHeaders.CanThrottle. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.canThrottle.isPresent = true; + } + } + + private static void AddProfileRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ProfileRequest)) + { + rntbdRequest.profileRequest.value.valueByte = (requestHeaders.ProfileRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.profileRequest.isPresent = true; + } + } + + private static void AddPageSize(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string value = requestHeaders.PageSize; + + if (!string.IsNullOrEmpty(value)) + { + int valueInt; + if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueInt)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); + } + + if (valueInt == -1) + { + rntbdRequest.pageSize.value.valueULong = UInt32.MaxValue; + } + else if (valueInt >= 0) + { + rntbdRequest.pageSize.value.valueULong = (UInt32) valueInt; + } + else + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); + } + + rntbdRequest.pageSize.isPresent = true; + } + } + + private static void AddEnableLogging(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EnableLogging)) + { + rntbdRequest.enableLogging.value.valueByte = (requestHeaders.EnableLogging. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.enableLogging.isPresent = true; + } + } + + private static void AddSupportSpatialLegacyCoordinates(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.SupportSpatialLegacyCoordinates)) + { + rntbdRequest.supportSpatialLegacyCoordinates.value.valueByte = (requestHeaders.SupportSpatialLegacyCoordinates. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.supportSpatialLegacyCoordinates.isPresent = true; + } + } + + private static void AddUsePolygonsSmallerThanAHemisphere(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.UsePolygonsSmallerThanAHemisphere)) + { + rntbdRequest.usePolygonsSmallerThanAHemisphere.value.valueByte = (requestHeaders.UsePolygonsSmallerThanAHemisphere. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.usePolygonsSmallerThanAHemisphere.isPresent = true; + } + } + + private static void AddPopulateQuotaInfo(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateQuotaInfo)) + { + rntbdRequest.populateQuotaInfo.value.valueByte = (requestHeaders.PopulateQuotaInfo. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.populateQuotaInfo.isPresent = true; + } + } + + private static void AddPopulateResourceCount(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateResourceCount)) + { + rntbdRequest.populateResourceCount.value.valueByte = (requestHeaders.PopulateResourceCount. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.populateResourceCount.isPresent = true; + } + } + + private static void AddPopulatePartitionStatistics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulatePartitionStatistics)) + { + rntbdRequest.populatePartitionStatistics.value.valueByte = (requestHeaders.PopulatePartitionStatistics. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.populatePartitionStatistics.isPresent = true; + } + } + + private static void AddDisableRUPerMinuteUsage(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.DisableRUPerMinuteUsage)) + { + rntbdRequest.disableRUPerMinuteUsage.value.valueByte = (requestHeaders.DisableRUPerMinuteUsage. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.disableRUPerMinuteUsage.isPresent = true; + } + } + + private static void AddPopulateQueryMetrics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateQueryMetrics)) + { + rntbdRequest.populateQueryMetrics.value.valueByte = (requestHeaders.PopulateQueryMetrics. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.populateQueryMetrics.isPresent = true; + } + } + + private static void AddPopulateQueryMetricsIndexUtilization(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateIndexMetrics)) + { + rntbdRequest.populateIndexMetrics.value.valueByte = (requestHeaders.PopulateIndexMetrics. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.populateIndexMetrics.isPresent = true; + } + } + + private static void AddPopulateIndexMetricsV2(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateIndexMetricsV2)) + { + rntbdRequest.populateIndexMetricsV2.value.valueByte = (requestHeaders.PopulateIndexMetricsV2. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.populateIndexMetricsV2.isPresent = true; + } + } + + private static void AddOptimisticDirectExecute(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.OptimisticDirectExecute)) + { + rntbdRequest.optimisticDirectExecute.value.valueByte = (requestHeaders.OptimisticDirectExecute. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.optimisticDirectExecute.isPresent = true; + } + } + + private static void AddQueryForceScan(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ForceQueryScan)) + { + rntbdRequest.forceQueryScan.value.valueByte = (requestHeaders.ForceQueryScan. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.forceQueryScan.isPresent = true; + } + } + + private static void AddPopulateCollectionThroughputInfo(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PopulateCollectionThroughputInfo)) + { + rntbdRequest.populateCollectionThroughputInfo.value.valueByte = (requestHeaders.PopulateCollectionThroughputInfo. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.populateCollectionThroughputInfo.isPresent = true; + } + } + + private static void AddShareThroughput(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ShareThroughput)) + { + rntbdRequest.shareThroughput.value.valueByte = (requestHeaders.ShareThroughput. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.shareThroughput.isPresent = true; + } + } + + private static void AddIsReadOnlyScript(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsReadOnlyScript)) + { + rntbdRequest.isReadOnlyScript.value.valueByte = (requestHeaders.IsReadOnlyScript. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isReadOnlyScript.isPresent = true; + } + } + +#if !COSMOSCLIENT + private static void AddIsAutoScaleRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsAutoScaleRequest)) + { + rntbdRequest.isAutoScaleRequest.value.valueByte = (requestHeaders.IsAutoScaleRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isAutoScaleRequest.isPresent = true; + } + } +#endif + + private static void AddCanOfferReplaceComplete(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.CanOfferReplaceComplete)) + { + rntbdRequest.canOfferReplaceComplete.value.valueByte = (requestHeaders.CanOfferReplaceComplete. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.canOfferReplaceComplete.isPresent = true; + } + } + + private static void AddIgnoreSystemLoweringMaxThroughput(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IgnoreSystemLoweringMaxThroughput)) + { + rntbdRequest.ignoreSystemLoweringMaxThroughput.value.valueByte = (requestHeaders.IgnoreSystemLoweringMaxThroughput. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.ignoreSystemLoweringMaxThroughput.isPresent = true; + } + } + + private static void AddUpdateMaxthroughputEverProvisioned(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.UpdateMaxThroughputEverProvisioned)) + { + string value = requestHeaders.UpdateMaxThroughputEverProvisioned; + int valueInt; + if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueInt)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidUpdateMaxthroughputEverProvisioned, value)); + } + + if (valueInt >= 0) + { + rntbdRequest.updateMaxThroughputEverProvisioned.value.valueULong = (UInt32)valueInt; + } + else + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidUpdateMaxthroughputEverProvisioned, value)); + } + + rntbdRequest.updateMaxThroughputEverProvisioned.isPresent = true; + } + } + + private static void AddGetAllPartitionKeyStatistics(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.GetAllPartitionKeyStatistics)) + { + rntbdRequest.getAllPartitionKeyStatistics.value.valueByte = (requestHeaders.GetAllPartitionKeyStatistics. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.getAllPartitionKeyStatistics.isPresent = true; + } + } + + private static void AddResponseContinuationTokenLimitInKb(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ResponseContinuationTokenLimitInKB)) + { + string value = requestHeaders.ResponseContinuationTokenLimitInKB; + if (!Int32.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int valueInt)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidPageSize, value)); + } + + if (valueInt >= 0) + { + rntbdRequest.responseContinuationTokenLimitInKb.value.valueULong = (UInt32) valueInt; + } + else + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidResponseContinuationTokenLimit, value)); + } + + rntbdRequest.responseContinuationTokenLimitInKb.isPresent = true; + } + } + + private static void AddRemoteStorageType(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.RemoteStorageType)) + { + RntbdConstants.RntbdRemoteStorageType rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Invalid; + if (!Enum.TryParse(requestHeaders.RemoteStorageType, true, out RemoteStorageType remoteStorageType)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.RemoteStorageType, typeof(RemoteStorageType).Name)); + } + + switch (remoteStorageType) + { + case RemoteStorageType.Standard: + rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Standard; + break; + case RemoteStorageType.Premium: + rntbdRemoteStorageType = RntbdConstants.RntbdRemoteStorageType.Premium; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.RemoteStorageType, typeof(RemoteStorageType).Name)); + } + + rntbdRequest.remoteStorageType.value.valueByte = (byte) rntbdRemoteStorageType; + rntbdRequest.remoteStorageType.isPresent = true; + } + } + + private static void AddCollectionChildResourceNameLimitInBytes(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.CollectionChildResourceNameLimitInBytes; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Int32.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.collectionChildResourceNameLimitInBytes.value.valueLong)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.CollectionChildResourceNameLimitInBytes)); + } + + rntbdRequest.collectionChildResourceNameLimitInBytes.isPresent = true; + } + } + + private static void AddCollectionChildResourceContentLengthLimitInKB(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.CollectionChildResourceContentLimitInKB; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Int32.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.collectionChildResourceContentLengthLimitInKB.value.valueLong)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB)); + } + + rntbdRequest.collectionChildResourceContentLengthLimitInKB.isPresent = true; + } + } + + private static void AddUniqueIndexNameEncodingMode(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.UniqueIndexNameEncodingMode; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Byte.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.uniqueIndexNameEncodingMode.value.valueByte)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.UniqueIndexNameEncodingMode)); + } + + rntbdRequest.uniqueIndexNameEncodingMode.isPresent = true; + } + } + + private static void AddUniqueIndexReIndexingState(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.UniqueIndexReIndexingState; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Byte.TryParse(headerValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out rntbdRequest.uniqueIndexReIndexingState.value.valueByte)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.UniqueIndexReIndexingState)); + } + + rntbdRequest.uniqueIndexReIndexingState.isPresent = true; + } + } + + private static void AddIsInternalServerlessRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsInternalServerlessRequest)) + { + rntbdRequest.isInternalServerlessRequest.value.valueByte = (requestHeaders.IsInternalServerlessRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isInternalServerlessRequest.isPresent = true; + } + } + + private static void AddCorrelatedActivityId(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.CorrelatedActivityId; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Guid.TryParse(headerValue, out rntbdRequest.correlatedActivityId.value.valueGuid)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.CorrelatedActivityId)); + } + + rntbdRequest.correlatedActivityId.isPresent = true; + } + } + + private static void AddCosmosGatewayTransactionId(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.CosmosGatewayTransactionId; + if (!string.IsNullOrEmpty(headerValue)) + { + if (!Guid.TryParse(headerValue, out rntbdRequest.cosmosGatewayTransactionId.value.valueGuid)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, + RMResources.InvalidHeaderValue, + headerValue, + WFConstants.BackendHeaders.CosmosGatewayTransactionId)); + } + + rntbdRequest.cosmosGatewayTransactionId.isPresent = true; + } + } + + private static void AddCollectionRemoteStorageSecurityIdentifier(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.CollectionRemoteStorageSecurityIdentifier; + if (!string.IsNullOrEmpty(headerValue)) + { + rntbdRequest.collectionRemoteStorageSecurityIdentifier.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); + rntbdRequest.collectionRemoteStorageSecurityIdentifier.isPresent = true; + } + } + + private static void AddIsUserRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsUserRequest)) + { + rntbdRequest.isUserRequest.value.valueByte = (requestHeaders.IsUserRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isUserRequest.isPresent = true; + } + } + + private static void AddPreserveFullContent(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.PreserveFullContent)) + { + rntbdRequest.preserveFullContent.value.valueByte = (requestHeaders.PreserveFullContent. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte) 0x01 + : (byte) 0x00; + rntbdRequest.preserveFullContent.isPresent = true; + } + } + + private static void AddForceSideBySideIndexMigration(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ForceSideBySideIndexMigration)) + { + rntbdRequest.forceSideBySideIndexMigration.value.valueByte = (requestHeaders.ForceSideBySideIndexMigration. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.forceSideBySideIndexMigration.isPresent = true; + } + } + private static void AddPopulateUniqueIndexReIndexProgress(object headerObjectValue, RntbdConstants.Request rntbdRequest) + { + if (headerObjectValue is string headerValue && + !string.IsNullOrEmpty(headerValue)) + { + if (string.Equals(bool.TrueString, headerValue, StringComparison.OrdinalIgnoreCase)) + { + rntbdRequest.populateUniqueIndexReIndexProgress.value.valueByte = (byte)0x01; + } + else + { + rntbdRequest.populateUniqueIndexReIndexProgress.value.valueByte = (byte)0x00; + } + + rntbdRequest.populateUniqueIndexReIndexProgress.isPresent = true; + } + } + + private static void AddIsRUPerGBEnforcementRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsRUPerGBEnforcementRequest)) + { + rntbdRequest.isRUPerGBEnforcementRequest.value.valueByte = (requestHeaders.IsRUPerGBEnforcementRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isRUPerGBEnforcementRequest.isPresent = true; + } + } + + private static void AddIsOfferStorageRefreshRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsOfferStorageRefreshRequest)) + { + rntbdRequest.isofferStorageRefreshRequest.value.valueByte = (requestHeaders.IsOfferStorageRefreshRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isofferStorageRefreshRequest.isPresent = true; + } + } + +#if !COSMOSCLIENT + private static void AddIsServerlessEnabledStorageRefreshRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsServerlessStorageRefreshRequest)) + { + rntbdRequest.isServerlessStorageRefreshRequest.value.valueByte = (requestHeaders.IsServerlessStorageRefreshRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isServerlessStorageRefreshRequest.isPresent = true; + } + } +#endif + + private static void AddIsMigrateOfferToManualThroughputRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.MigrateOfferToManualThroughput)) + { + rntbdRequest.migrateOfferToManualThroughput.value.valueByte = (requestHeaders.MigrateOfferToManualThroughput. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.migrateOfferToManualThroughput.isPresent = true; + } + } + + private static void AddIsMigrateOfferToAutopilotRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.MigrateOfferToAutopilot)) + { + rntbdRequest.migrateOfferToAutopilot.value.valueByte = (requestHeaders.MigrateOfferToAutopilot. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.migrateOfferToAutopilot.isPresent = true; + } + } + + private static void AddTruncateMergeLogRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.TruncateMergeLogRequest)) + { + rntbdRequest.truncateMergeLogRequest.value.valueByte = (requestHeaders.TruncateMergeLogRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.truncateMergeLogRequest.isPresent = true; + } + } + + private static void AddEnumerationDirection(DocumentServiceRequest request, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (request.Properties != null && request.Properties.TryGetValue( + HttpConstants.HttpHeaders.EnumerationDirection, + out object enumerationDirectionObject)) + { + byte? scanDirection = enumerationDirectionObject as byte?; + if (scanDirection == null) + { + throw new BadRequestException( + String.Format( + CultureInfo.CurrentUICulture, + RMResources.InvalidEnumValue, + HttpConstants.HttpHeaders.EnumerationDirection, + nameof(EnumerationDirection))); + } + else + { + rntbdRequest.enumerationDirection.value.valueByte = scanDirection.Value; + rntbdRequest.enumerationDirection.isPresent = true; + } + } + else if (!string.IsNullOrEmpty(requestHeaders.EnumerationDirection)) + { + RntbdConstants.RntdbEnumerationDirection rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Invalid; + if (!Enum.TryParse(requestHeaders.EnumerationDirection, true, out EnumerationDirection enumerationDirection)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.EnumerationDirection, nameof(EnumerationDirection))); + } + + switch (enumerationDirection) + { + case EnumerationDirection.Forward: + rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Forward; + break; + case EnumerationDirection.Reverse: + rntdbEnumerationDirection = RntbdConstants.RntdbEnumerationDirection.Reverse; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.EnumerationDirection, typeof(EnumerationDirection).Name)); + } + + rntbdRequest.enumerationDirection.value.valueByte = (byte)rntdbEnumerationDirection; + rntbdRequest.enumerationDirection.isPresent = true; + } + } + + private static void AddStartAndEndKeys(DocumentServiceRequest request, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (request.Properties == null + || !string.IsNullOrEmpty(requestHeaders.ReadFeedKeyType)) + { + TransportSerialization.AddStartAndEndKeysFromHeaders(requestHeaders, rntbdRequest); + return; + } + + RntbdConstants.RntdbReadFeedKeyType? readFeedKeyType = null; + if (request.Properties.TryGetValue(HttpConstants.HttpHeaders.ReadFeedKeyType, out object requestObject)) + { + if (!(requestObject is byte)) + { + throw new ArgumentOutOfRangeException(HttpConstants.HttpHeaders.ReadFeedKeyType); + } + + rntbdRequest.readFeedKeyType.value.valueByte = (byte)requestObject; + rntbdRequest.readFeedKeyType.isPresent = true; + readFeedKeyType = (RntbdConstants.RntdbReadFeedKeyType)requestObject; + } + + if (readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.ResourceId) + { + TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.StartId, rntbdRequest.startId); + TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.EndId, rntbdRequest.endId); + } + else if (readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKey || + readFeedKeyType == RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKeyRange) + { + + TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.StartEpk, rntbdRequest.startEpk); + TransportSerialization.SetBytesValue(request, HttpConstants.HttpHeaders.EndEpk, rntbdRequest.endEpk); + } + } + + private static void AddStartAndEndKeysFromHeaders(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + bool keepsAsHexString = false; + if (!string.IsNullOrEmpty(requestHeaders.ReadFeedKeyType)) + { + RntbdConstants.RntdbReadFeedKeyType rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.Invalid; + if (!Enum.TryParse(requestHeaders.ReadFeedKeyType, true, out ReadFeedKeyType readFeedKeyType)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ReadFeedKeyType, nameof(ReadFeedKeyType))); + } + + switch (readFeedKeyType) + { + case ReadFeedKeyType.ResourceId: + rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.ResourceId; + break; + case ReadFeedKeyType.EffectivePartitionKey: + rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKey; + break; + case ReadFeedKeyType.EffectivePartitionKeyRange: + rntdbReadFeedKeyType = RntbdConstants.RntdbReadFeedKeyType.EffectivePartitionKeyRange; + keepsAsHexString = true; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ReadFeedKeyType, typeof(ReadFeedKeyType).Name)); + } + + rntbdRequest.readFeedKeyType.value.valueByte = (byte)rntdbReadFeedKeyType; + rntbdRequest.readFeedKeyType.isPresent = true; + } + + string startId = requestHeaders.StartId; + if (!string.IsNullOrEmpty(startId)) + { + rntbdRequest.startId.value.valueBytes = System.Convert.FromBase64String(startId); + rntbdRequest.startId.isPresent = true; + } + + string endId = requestHeaders.EndId; + if (!string.IsNullOrEmpty(endId)) + { + rntbdRequest.endId.value.valueBytes = System.Convert.FromBase64String(endId); + rntbdRequest.endId.isPresent = true; + } + + string startEpk = requestHeaders.StartEpk; + if (!string.IsNullOrEmpty(startEpk)) + { + rntbdRequest.startEpk.value.valueBytes = keepsAsHexString ? BytesSerializer.GetBytesForString(startEpk, rntbdRequest) : System.Convert.FromBase64String(startEpk); + rntbdRequest.startEpk.isPresent = true; + } + + string endEpk = requestHeaders.EndEpk; + if (!string.IsNullOrEmpty(endEpk)) + { + rntbdRequest.endEpk.value.valueBytes = keepsAsHexString ? BytesSerializer.GetBytesForString(endEpk, rntbdRequest) : System.Convert.FromBase64String(endEpk); + rntbdRequest.endEpk.isPresent = true; + } + } + + private static void SetBytesValue(DocumentServiceRequest request, string headerName, RntbdToken token) + { + if (request.Properties.TryGetValue(headerName, out object requestObject)) + { + if (requestObject is byte[] endEpk) + { + token.value.valueBytes = endEpk; + } +#if COSMOSCLIENT + else if (requestObject is ReadOnlyMemory endEpkRom) + { + token.value.valueBytes = endEpkRom; + } +#endif + else + { + throw new ArgumentOutOfRangeException(headerName); + } + + + token.isPresent = true; + } + } + + private static void AddContentSerializationFormat(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ContentSerializationFormat)) + { + RntbdConstants.RntbdContentSerializationFormat rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.Invalid; + + if (!Enum.TryParse(requestHeaders.ContentSerializationFormat, true, out ContentSerializationFormat contentSerializationFormat)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ContentSerializationFormat, nameof(ContentSerializationFormat))); + } + + switch (contentSerializationFormat) + { + case ContentSerializationFormat.JsonText: + rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.JsonText; + break; + case ContentSerializationFormat.CosmosBinary: + rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.CosmosBinary; + break; + case ContentSerializationFormat.HybridRow: + rntbdContentSerializationFormat = RntbdConstants.RntbdContentSerializationFormat.HybridRow; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.ContentSerializationFormat, nameof(ContentSerializationFormat))); + } + + rntbdRequest.contentSerializationFormat.value.valueByte = (byte)rntbdContentSerializationFormat; + rntbdRequest.contentSerializationFormat.isPresent = true; + } + } + + [System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "Roslyn Baseline 12/12/2022 16:40")] + private static void AddSupportedSerializationFormats(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (requestHeaders.SupportedSerializationFormats != null) + { + RntbdConstants.RntbdSupportedSerializationFormats rntbdSupportedSerializationFormats = RntbdConstants.RntbdSupportedSerializationFormats.None; + + // Making empty header value check consistent with http request. If header value is empty throw exception. + if (requestHeaders.SupportedSerializationFormats.Length == 0 || !Enum.TryParse(requestHeaders.SupportedSerializationFormats, true, out SupportedSerializationFormats supportedSerializationFormats)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.SupportedSerializationFormats, nameof(SupportedSerializationFormats))); + } + + if(supportedSerializationFormats.HasFlag(SupportedSerializationFormats.JsonText)) + { + rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.JsonText; + } + + if(supportedSerializationFormats.HasFlag(SupportedSerializationFormats.CosmosBinary)) + { + rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.CosmosBinary; + } + + if (supportedSerializationFormats.HasFlag(SupportedSerializationFormats.HybridRow)) + { + rntbdSupportedSerializationFormats |= RntbdConstants.RntbdSupportedSerializationFormats.HybridRow; + } + + if((supportedSerializationFormats & + ~(SupportedSerializationFormats.JsonText | SupportedSerializationFormats.CosmosBinary | SupportedSerializationFormats.HybridRow)) != SupportedSerializationFormats.None) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.SupportedSerializationFormats, nameof(SupportedSerializationFormats))); + } + + rntbdRequest.supportedSerializationFormats.value.valueByte = (byte)rntbdSupportedSerializationFormats; + rntbdRequest.supportedSerializationFormats.isPresent = true; + } + } + + private static void FillTokenFromHeader(DocumentServiceRequest request, string headerName, string headerStringValue, RntbdToken token, RntbdConstants.Request rntbdRequest) + { + object headerValue = null; + if (string.IsNullOrEmpty(headerStringValue)) + { + if (request.Properties == null || !request.Properties.TryGetValue(headerName, out headerValue)) + { + return; + } + + if (headerValue == null) + { + return; + } + + if (headerValue is string valueString) + { + headerStringValue = valueString; + if (string.IsNullOrEmpty(headerStringValue)) + { + return; + } + } + } + + switch (token.GetTokenType()) + { + case RntbdTokenTypes.SmallString: + case RntbdTokenTypes.String: + case RntbdTokenTypes.ULongString: + if (headerStringValue == null) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + + token.value.valueBytes = BytesSerializer.GetBytesForString(headerStringValue, rntbdRequest); + break; + case RntbdTokenTypes.ULong: + uint valueULong; + if (headerStringValue != null) + { + if (!uint.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueULong)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + } + else + { + if (!(headerValue is uint uintValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueULong = uintValue; + } + + token.value.valueULong = valueULong; + break; + case RntbdTokenTypes.Long: + int valueLong; + if (headerStringValue != null) + { + if (!int.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueLong)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + } + else + { + if (!(headerValue is int intValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueLong = intValue; + } + + token.value.valueLong = valueLong; + break; + case RntbdTokenTypes.Double: + double valueDouble; + if (headerStringValue != null) + { + if (!double.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueDouble)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + } + else + { + if (!(headerValue is double doubleValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueDouble = doubleValue; + } + + token.value.valueDouble = valueDouble; + break; + case RntbdTokenTypes.LongLong: + long valueLongLong; + if (headerStringValue != null) + { + if (!long.TryParse(headerStringValue, NumberStyles.Integer, CultureInfo.InvariantCulture, out valueLongLong)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + } + else + { + if (!(headerValue is long longLongValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueLongLong = longLongValue; + } + + token.value.valueLongLong = valueLongLong; + break; + case RntbdTokenTypes.Byte: + bool valueBool; + if (headerStringValue != null) + { + valueBool = string.Equals(headerStringValue, bool.TrueString, StringComparison.OrdinalIgnoreCase); + } + else + { + if (!(headerValue is bool boolValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueBool = boolValue; + } + + token.value.valueByte = valueBool ? (byte)0x01 : (byte)0x00; + break; + case RntbdTokenTypes.Bytes: + byte[] valueBytes; + if (headerStringValue != null) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + else + { + if (!(headerValue is byte[] bytesValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueBytes = bytesValue; + } + + token.value.valueBytes = valueBytes; + break; + case RntbdTokenTypes.Guid: + Guid valueGuid; + if (headerStringValue != null) + { + if (!Guid.TryParse(headerStringValue, out valueGuid)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerStringValue, headerName)); + } + } + else + { + if (!(headerValue is Guid guidValue)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidHeaderValue, headerValue, headerName)); + } + + valueGuid = guidValue; + } + + token.value.valueGuid = valueGuid; + break; + default: + Debug.Assert(false, "Recognized header has neither special-case nor default handling to convert" + + " from header string to RNTBD token."); + throw new BadRequestException(); + } + + token.isPresent = true; + } + + private static void AddExcludeSystemProperties(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.ExcludeSystemProperties)) + { + rntbdRequest.excludeSystemProperties.value.valueByte = (requestHeaders.ExcludeSystemProperties. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.excludeSystemProperties.isPresent = true; + } + } + + private static void AddFanoutOperationStateHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string value = requestHeaders.FanoutOperationState; + if (!string.IsNullOrEmpty(value)) + { + if (!Enum.TryParse(value, true, out FanoutOperationState state)) + { + throw new BadRequestException( + String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(FanoutOperationState))); + } + + RntbdConstants.RntbdFanoutOperationState rntbdState; + switch (state) + { + case FanoutOperationState.Started: + rntbdState = RntbdConstants.RntbdFanoutOperationState.Started; + break; + + case FanoutOperationState.Completed: + rntbdState = RntbdConstants.RntbdFanoutOperationState.Completed; + break; + + default: + throw new BadRequestException( + String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(FanoutOperationState))); + } + + rntbdRequest.fanoutOperationState.value.valueByte = (byte)rntbdState; + rntbdRequest.fanoutOperationState.isPresent = true; + } + } + + private static void AddResourceTypes(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string headerValue = requestHeaders.ResourceTypes; + if (!string.IsNullOrEmpty(headerValue)) + { + rntbdRequest.resourceTypes.value.valueBytes = BytesSerializer.GetBytesForString(headerValue, rntbdRequest); + rntbdRequest.resourceTypes.isPresent = true; + } + } + + private static void AddSystemDocumentTypeHeader(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.SystemDocumentType)) + { + RntbdConstants.RntbdSystemDocumentType rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.Invalid; + if (!Enum.TryParse(requestHeaders.SystemDocumentType, true, out SystemDocumentType systemDocumentType)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.SystemDocumentType, nameof(SystemDocumentType))); + } + + switch (systemDocumentType) + { + case SystemDocumentType.MaterializedViewLeaseDocument: + rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewLeaseDocument; + break; + case SystemDocumentType.MaterializedViewBuilderOwnershipDocument: + rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewBuilderOwnershipDocument; + break; + case SystemDocumentType.MaterializedViewLeaseStoreInitDocument: + rntbdSystemDocumentType = RntbdConstants.RntbdSystemDocumentType.MaterializedViewLeaseStoreInitDocument; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.SystemDocumentType, typeof(SystemDocumentType).Name)); + } + + rntbdRequest.systemDocumentType.value.valueByte = (byte)rntbdSystemDocumentType; + rntbdRequest.systemDocumentType.isPresent = true; + } + } + + private static void AddTransactionMetaData(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (request.Properties != null && + request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionId, out object transactionIdValue) && + request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionFirstRequest, out object isFirstRequestValue)) + { + // read transaction id + byte[] transactionId = transactionIdValue as byte[]; + if (transactionId == null) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionId); + } + + // read initial transactional request flag + bool? isFirstRequest = isFirstRequestValue as bool?; + if (!isFirstRequest.HasValue) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionFirstRequest); + } + + // set transaction id and initial request flag + rntbdRequest.transactionId.value.valueBytes = transactionId; + rntbdRequest.transactionId.isPresent = true; + + rntbdRequest.transactionFirstRequest.value.valueByte = ((bool)isFirstRequest) ? (byte)0x01 : (byte)0x00; + rntbdRequest.transactionFirstRequest.isPresent = true; + } + } + + private static void AddTransactionCompletionFlag(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (request.Properties != null && + request.Properties.TryGetValue(WFConstants.BackendHeaders.TransactionCommit, out object isCommit)) + { + bool? boolData = isCommit as bool?; + if (!boolData.HasValue) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.TransactionCommit); + } + + rntbdRequest.transactionCommit.value.valueByte = ((bool)boolData) ? (byte)0x01 : (byte)0x00; + rntbdRequest.transactionCommit.isPresent = true; + } + } + + private static void AddRetriableWriteRequestMetadata(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (request.Properties != null && + request.Properties.TryGetValue(WFConstants.BackendHeaders.RetriableWriteRequestId, out object retriableWriteRequestId)) + { + byte[] requestId = retriableWriteRequestId as byte[]; + if (requestId == null) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.RetriableWriteRequestId); + } + + rntbdRequest.retriableWriteRequestId.value.valueBytes = requestId; + rntbdRequest.retriableWriteRequestId.isPresent = true; + + if (request.Properties.TryGetValue(WFConstants.BackendHeaders.IsRetriedWriteRequest, out object isRetriedWriteRequestValue)) + { + bool? isRetriedWriteRequest = isRetriedWriteRequestValue as bool?; + if (!isRetriedWriteRequest.HasValue) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.IsRetriedWriteRequest); + } + + rntbdRequest.isRetriedWriteRequest.value.valueByte = ((bool)isRetriedWriteRequest) ? (byte)0x01 : (byte)0x00; + rntbdRequest.isRetriedWriteRequest.isPresent = true; + } + + if (request.Properties.TryGetValue(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp, out object retriableWriteRequestStartTimestamp)) + { + if (!UInt64.TryParse(retriableWriteRequestStartTimestamp.ToString(), out UInt64 requestStartTimestamp) || requestStartTimestamp <= 0) + { + throw new ArgumentOutOfRangeException(WFConstants.BackendHeaders.RetriableWriteRequestStartTimestamp); + } + + rntbdRequest.retriableWriteRequestStartTimestamp.value.valueULongLong = requestStartTimestamp; + rntbdRequest.retriableWriteRequestStartTimestamp.isPresent = true; + } + } + } + + private static void AddUseSystemBudget(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.UseSystemBudget)) + { + rntbdRequest.useSystemBudget.value.valueByte = (requestHeaders.UseSystemBudget. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.useSystemBudget.isPresent = true; + } + } + + private static void AddRequestedCollectionType(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + string value = requestHeaders.RequestedCollectionType; + if (!string.IsNullOrEmpty(value)) + { + if (!Enum.TryParse(value, true, out RequestedCollectionType collectionType)) + { + throw new BadRequestException( + String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(RequestedCollectionType))); + } + + RntbdConstants.RntbdRequestedCollectionType rntbdCollectionType; + switch (collectionType) + { + case RequestedCollectionType.All: + rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.All; + break; + + case RequestedCollectionType.Standard: + rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.Standard; + break; + + case RequestedCollectionType.MaterializedView: + rntbdCollectionType = RntbdConstants.RntbdRequestedCollectionType.MaterializedView; + break; + + default: + throw new BadRequestException( + String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, value, nameof(RequestedCollectionType))); + } + + rntbdRequest.requestedCollectionType.value.valueByte = (byte)rntbdCollectionType; + rntbdRequest.requestedCollectionType.isPresent = true; + } + } + + private static void AddUpdateOfferStateToPending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.UpdateOfferStateToPending)) + { + rntbdRequest.updateOfferStateToPending.value.valueByte = (requestHeaders.UpdateOfferStateToPending. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.updateOfferStateToPending.isPresent = true; + } + } + + private static void AddUpdateOfferStateToRestorePending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.UpdateOfferStateToRestorePending)) + { + rntbdRequest.updateOfferStateToRestorePending.value.valueByte = (requestHeaders.UpdateOfferStateToRestorePending. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.updateOfferStateToRestorePending.isPresent = true; + } + } + + private static void AddMasterResourcesDeletionPending(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.SetMasterResourcesDeletionPending)) + { + rntbdRequest.setMasterResourcesDeletionPending.value.valueByte = (requestHeaders.SetMasterResourcesDeletionPending. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.setMasterResourcesDeletionPending.isPresent = true; + } + } + + private static void AddOfferReplaceRURedistribution(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if(!string.IsNullOrEmpty(requestHeaders.OfferReplaceRURedistribution)) + { + rntbdRequest.offerReplaceRURedistribution.value.valueByte = (requestHeaders.OfferReplaceRURedistribution + .Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.offerReplaceRURedistribution.isPresent = true; + } + } + + private static void AddIsMaterializedViewSourceSchemaReplaceBatchRequest(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest)) + { + rntbdRequest.isMaterializedViewSourceSchemaReplaceBatchRequest.value.valueByte = (requestHeaders.IsMaterializedViewSourceSchemaReplaceBatchRequest. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isMaterializedViewSourceSchemaReplaceBatchRequest.isPresent = true; + } + } + + private static void AddIsCassandraAlterTypeRequest(DocumentServiceRequest request, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest])) + { + rntbdRequest.isCassandraAlterTypeRequest.value.valueByte = (request.Headers[HttpConstants.HttpHeaders.IsCassandraAlterTypeRequest]. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.isCassandraAlterTypeRequest.isPresent = true; + } + } + + private static void AddHighPriorityForcedBackup(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.HighPriorityForcedBackup)) + { + rntbdRequest.highPriorityForcedBackup.value.valueByte = (requestHeaders.HighPriorityForcedBackup. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.highPriorityForcedBackup.isPresent = true; + } + } + + private static void AddEnableConflictResolutionPolicyUpdate(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EnableConflictResolutionPolicyUpdate)) + { + rntbdRequest.enableConflictResolutionPolicyUpdate.value.valueByte = (requestHeaders.EnableConflictResolutionPolicyUpdate. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.enableConflictResolutionPolicyUpdate.isPresent = true; + } + } + + private static void AddPriorityLevelHeader(DocumentServiceRequest request, string headerName, string headerStringValue, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + PriorityLevel priorityLevel = PriorityLevel.High; + RntbdConstants.RntbdPriorityLevel rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.High; + + if (string.IsNullOrEmpty(headerStringValue)) + { + object headerValue = null; + if (request.Properties == null || !request.Properties.TryGetValue(headerName, out headerValue)) + { + return; + } + + if (headerValue == null) + { + return; + } + + if (headerValue is Enum valueString) + { + priorityLevel = (PriorityLevel)valueString; + } + } + else + { + if (!Enum.TryParse(requestHeaders.PriorityLevel, true, out priorityLevel)) + { + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.PriorityLevel, typeof(PriorityLevel).Name)); + } + } + switch (priorityLevel) + { + case PriorityLevel.Low: + rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.Low; + break; + case PriorityLevel.High: + rntbdPriorityLevel = RntbdConstants.RntbdPriorityLevel.High; + break; + default: + throw new BadRequestException(String.Format(CultureInfo.CurrentUICulture, RMResources.InvalidEnumValue, + requestHeaders.PriorityLevel, typeof(PriorityLevel).Name)); + } + + rntbdRequest.priorityLevel.value.valueByte = (byte) rntbdPriorityLevel; + rntbdRequest.priorityLevel.isPresent = true; + } + + private static void AddAllowDocumentReadsInOfflineRegion(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.AllowDocumentReadsInOfflineRegion)) + { + rntbdRequest.allowDocumentReadsInOfflineRegion.value.valueByte = (requestHeaders.AllowDocumentReadsInOfflineRegion. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.allowDocumentReadsInOfflineRegion.isPresent = true; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/Trigger.cs b/Microsoft.Azure.Cosmos/src/direct/Trigger.cs index 0904d58fb5..fe9449dcef 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Trigger.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Trigger.cs @@ -1,86 +1,86 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Represents a trigger in the Azure Cosmos DB service. - /// - /// - /// Azure Cosmos DB supports pre and post triggers written in JavaScript to be executed on creates, updates and deletes. - /// For additional details, refer to the server-side JavaScript API documentation. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class Trigger : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public Trigger() - { - } - - /// - /// Gets or sets the body of the trigger for the Azure Cosmos DB service. - /// - /// The body of the trigger. - [JsonProperty(PropertyName = Constants.Properties.Body)] - public string Body - { - get - { - return base.GetValue(Constants.Properties.Body); - } - set - { - base.SetValue(Constants.Properties.Body, value); - } - } - - /// - /// Get or set the type of the trigger for the Azure Cosmos DB service. - /// - /// The body of the trigger. - /// - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty(PropertyName = Constants.Properties.TriggerType)] - public TriggerType TriggerType - { - get - { - return base.GetValue(Constants.Properties.TriggerType, TriggerType.Pre); - } - set - { - base.SetValue(Constants.Properties.TriggerType, value.ToString()); - } - } - - /// - /// Gets or sets the operation the trigger is associated with for the Azure Cosmos DB service. - /// - /// The operation the trigger is associated with. - /// - [JsonConverter(typeof(StringEnumConverter))] - [JsonProperty(PropertyName = Constants.Properties.TriggerOperation)] - public TriggerOperation TriggerOperation - { - get - { - return base.GetValue(Constants.Properties.TriggerOperation, TriggerOperation.All); - } - set - { - base.SetValue(Constants.Properties.TriggerOperation, value.ToString()); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Represents a trigger in the Azure Cosmos DB service. + /// + /// + /// Azure Cosmos DB supports pre and post triggers written in JavaScript to be executed on creates, updates and deletes. + /// For additional details, refer to the server-side JavaScript API documentation. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class Trigger : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public Trigger() + { + } + + /// + /// Gets or sets the body of the trigger for the Azure Cosmos DB service. + /// + /// The body of the trigger. + [JsonProperty(PropertyName = Constants.Properties.Body)] + public string Body + { + get + { + return base.GetValue(Constants.Properties.Body); + } + set + { + base.SetValue(Constants.Properties.Body, value); + } + } + + /// + /// Get or set the type of the trigger for the Azure Cosmos DB service. + /// + /// The body of the trigger. + /// + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty(PropertyName = Constants.Properties.TriggerType)] + public TriggerType TriggerType + { + get + { + return base.GetValue(Constants.Properties.TriggerType, TriggerType.Pre); + } + set + { + base.SetValue(Constants.Properties.TriggerType, value.ToString()); + } + } + + /// + /// Gets or sets the operation the trigger is associated with for the Azure Cosmos DB service. + /// + /// The operation the trigger is associated with. + /// + [JsonConverter(typeof(StringEnumConverter))] + [JsonProperty(PropertyName = Constants.Properties.TriggerOperation)] + public TriggerOperation TriggerOperation + { + get + { + return base.GetValue(Constants.Properties.TriggerOperation, TriggerOperation.All); + } + set + { + base.SetValue(Constants.Properties.TriggerOperation, value.ToString()); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs b/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs index d9d183730a..5a84a7eb3e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs @@ -1,46 +1,46 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the operations on which a trigger should be executed in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum TriggerOperation : short - { - /// - /// Specifies all operations. - /// - All = 0x0, - - /// - /// Specifies create operations only. - /// - Create = 0x1, - - /// - /// Specifies update operations only. - /// - Update = 0x2, - - /// - /// Specifies delete operations only. - /// - Delete = 0x3, - - /// - /// Specifies replace operations only. - /// - Replace = 0x4, - - /// - /// Specifies upsert operations only. - /// - Upsert = 0x5 - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the operations on which a trigger should be executed in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum TriggerOperation : short + { + /// + /// Specifies all operations. + /// + All = 0x0, + + /// + /// Specifies create operations only. + /// + Create = 0x1, + + /// + /// Specifies update operations only. + /// + Update = 0x2, + + /// + /// Specifies delete operations only. + /// + Delete = 0x3, + + /// + /// Specifies replace operations only. + /// + Replace = 0x4, + + /// + /// Specifies upsert operations only. + /// + Upsert = 0x5 + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/TriggerType.cs b/Microsoft.Azure.Cosmos/src/direct/TriggerType.cs index 12f4368441..472ae2ccd8 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TriggerType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TriggerType.cs @@ -1,26 +1,26 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - /// - /// Specifies the type of the trigger in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - enum TriggerType : byte - { - /// - /// Trigger should be executed before the associated operation(s). - /// - Pre = 0x0, - - /// - /// Trigger should be executed after the associated operation(s). - /// - Post = 0x1 - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + /// + /// Specifies the type of the trigger in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + enum TriggerType : byte + { + /// + /// Trigger should be executed before the associated operation(s). + /// + Pre = 0x0, + + /// + /// Trigger should be executed after the associated operation(s). + /// + Post = 0x1 + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UInt128.cs b/Microsoft.Azure.Cosmos/src/direct/UInt128.cs index 7209df692e..766ac21662 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UInt128.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UInt128.cs @@ -1,372 +1,372 @@ -//----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -//----------------------------------------------------------------------- -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Struct that represents a 128 bit unsigned integer. - /// - internal struct UInt128 : IComparable, IComparable, IEquatable - { - /// - /// Maximum UInt128. - /// - public static readonly UInt128 MaxValue = new UInt128(ulong.MaxValue, ulong.MaxValue); - - /// - /// Maximum UInt128. - /// - public static readonly UInt128 MinValue = 0; - - /// - /// The length of this struct in bytes. - /// - private const int Length = 16; - - /// - /// The lowest 64 bits of the UInt128. - /// - private readonly ulong low; - - /// - /// The highest 64 bits of the UInt128. - /// - private readonly ulong high; - - /// - /// Initializes a new instance of the struct. - /// - /// The lowest 64 bits of the UInt128. - /// The highest 64 bits of the UInt128. - private UInt128(ulong low, ulong high) - { - this.low = low; - this.high = high; - } - - /// - /// Implicitly converts an int to UInt128. - /// - /// The int to convert. - public static implicit operator UInt128(int value) - { - return new UInt128((ulong)value, 0); - } - - /// - /// Implicitly converts a long to UInt128. - /// - /// The int to convert. - public static implicit operator UInt128(long value) - { - return new UInt128((ulong)value, 0); - } - - /// - /// Implicitly converts an unsigned int to UInt128. - /// - /// The unsigned int to convert. - public static implicit operator UInt128(uint value) - { - return new UInt128((ulong)value, 0); - } - - /// - /// Implicitly converts an unsigned long to UInt128. - /// - /// The unsigned long to convert. - public static implicit operator UInt128(ulong value) - { - return new UInt128(value, 0); - } - - /// - /// Adds two instances of UInt128 together. - /// - /// The augend. - /// The addend. - /// The augend + addend. - public static UInt128 operator +(UInt128 augend, UInt128 addend) - { - ulong low = augend.low + addend.low; - ulong high = augend.high + addend.high; - - if (low < augend.low) - { - high++; - } - - return new UInt128(low, high); - } - - /// - /// Takes the difference between two UInt128. - /// - /// The minuend. - /// The subtrahend. - /// minuend - subtrahend. - public static UInt128 operator -(UInt128 minuend, UInt128 subtrahend) - { - ulong low = minuend.low - subtrahend.low; - ulong high = minuend.high - subtrahend.high; - - if (low > minuend.low) - { - high--; - } - - return new UInt128(low, high); - } - - /// - /// Returns if one UInt128 is less than another UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether left is less than right. - public static bool operator <(UInt128 left, UInt128 right) - { - return (left.high < right.high) - || ((left.high == right.high) && (left.low < right.low)); - } - - /// - /// Returns if one UInt128 is greater than another UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether left is greater than right. - public static bool operator >(UInt128 left, UInt128 right) - { - return right < left; - } - - /// - /// Returns if one UInt128 is less than or equal to another UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether left is less than or equal to the right. - public static bool operator <=(UInt128 left, UInt128 right) - { - return !(right < left); - } - - /// - /// Returns if one UInt128 is greater than or equal to another UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether left is greater than or equal to the right. - public static bool operator >=(UInt128 left, UInt128 right) - { - return !(left < right); - } - - /// - /// Returns if two UInt128 are equal. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether the left is equal to the right. - public static bool operator ==(UInt128 left, UInt128 right) - { - return (left.high == right.high) && (left.low == right.low); - } - - /// - /// Returns if two UInt128 are not equal. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// Whether the left is not equal to the right. - public static bool operator !=(UInt128 left, UInt128 right) - { - return !(left == right); - } - - /// - /// Takes the bitwise and of two instance of UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// The bitwise and of two instance of UInt128.. - public static UInt128 operator &(UInt128 left, UInt128 right) - { - return new UInt128(left.low & right.low, left.high & right.high); - } - - /// - /// Takes the bitwise or of two instance of UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// The bitwise or of two instance of UInt128.. - public static UInt128 operator |(UInt128 left, UInt128 right) - { - return new UInt128(left.low | right.low, left.high | right.high); - } - - /// - /// Takes the bitwise x or of two instance of UInt128. - /// - /// The left hand side of the operator. - /// The right hand side of the operator. - /// The bitwise x or of two instance of UInt128.. - public static UInt128 operator ^(UInt128 left, UInt128 right) - { - return new UInt128(left.low ^ right.low, left.high ^ right.high); - } - - /// - /// Creates a UInt128 from two ulong. - /// - /// The lower 64 bits of the UInt128. - /// The upper 64 bits of the UInt128. - /// A UInt128 from the two ulong. - public static UInt128 Create(ulong low, ulong high) - { - return new UInt128(low, high); - } - - /// - /// Creates a UInt128 from a byte array. - /// - /// The bytes. - /// The starting index. - /// The UInt128 from the byte array. - public static UInt128 FromByteArray(byte[] bytes, int start = 0) - { - ulong low = BitConverter.ToUInt64(bytes, start); - ulong high = BitConverter.ToUInt64(bytes, start + 8); - - return new UInt128(low, high); - } - - /// - /// Converts the UInt128 to a byte array. - /// - /// The UInt128 to convert. - /// The byte array representation of this UInt128. - public static byte[] ToByteArray(UInt128 uint128) - { - byte[] bytes = new byte[UInt128.Length]; - byte[] lowBytes = BitConverter.GetBytes(uint128.low); - byte[] highBytes = BitConverter.GetBytes(uint128.high); - lowBytes.CopyTo(bytes, 0); - highBytes.CopyTo(bytes, 8); - - return bytes; - } - - /// - /// Compares this value to an object. - /// - /// The value to compare to. - /// The comparison. - public int CompareTo(object value) - { - if (value == null) - { - return 1; - } - - if (value is UInt128) - { - return this.CompareTo((UInt128)value); - } - - throw new ArgumentException("Value must be a UInt128."); - } - - /// - /// Compares this UInt128 to another instance of the UInt128 type. - /// - /// The other instance to compare to. - /// - /// A negative number if this instance is less than the other instance. - /// Zero if they are the same. - /// A positive number if this instance is greater than the other instance. - /// - public int CompareTo(UInt128 other) - { - if (this < other) - { - return -1; - } - - if (this > other) - { - return 1; - } - - return 0; - } - - /// - /// Returns whether this instance equals another object. - /// - /// The object to compare to. - /// Whether this instance equals another object. - public override bool Equals(object obj) - { - if (obj is UInt128) - { - return this.Equals((UInt128)obj); - } - - return false; - } - - /// - /// Returns whether this UInt128 equals another UInt128. - /// - /// The UInt128 to compare to. - /// Whether this UInt128 equals another UInt128. - public bool Equals(UInt128 other) - { - return this == other; - } - - /// - /// Gets a hash code for this instance. - /// - /// The hash code for this instance. - public override int GetHashCode() - { - return (int)(this.low.GetHashCode() ^ this.high.GetHashCode()); - } - - /// - /// Gets the string representation of a UInt128 as a hex dump. - /// - /// The string representation of a UInt128 as a hex dump. - public override string ToString() - { - byte[] bytes = UInt128.ToByteArray(this); - return BitConverter.ToString(bytes); - } - - /// - /// Returns the high 64 bits of the UInt128.cs. - /// - /// The high 64 bits of the UInt128.cs. - public ulong GetHigh() - { - return this.high; - } - - /// - /// Returns the low 64 bits of the UInt128.cs. - /// - /// The low 64 bits of the UInt128.cs. - public ulong GetLow() - { - return this.low; - } - } -} +//----------------------------------------------------------------------- +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//----------------------------------------------------------------------- +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Struct that represents a 128 bit unsigned integer. + /// + internal struct UInt128 : IComparable, IComparable, IEquatable + { + /// + /// Maximum UInt128. + /// + public static readonly UInt128 MaxValue = new UInt128(ulong.MaxValue, ulong.MaxValue); + + /// + /// Maximum UInt128. + /// + public static readonly UInt128 MinValue = 0; + + /// + /// The length of this struct in bytes. + /// + private const int Length = 16; + + /// + /// The lowest 64 bits of the UInt128. + /// + private readonly ulong low; + + /// + /// The highest 64 bits of the UInt128. + /// + private readonly ulong high; + + /// + /// Initializes a new instance of the struct. + /// + /// The lowest 64 bits of the UInt128. + /// The highest 64 bits of the UInt128. + private UInt128(ulong low, ulong high) + { + this.low = low; + this.high = high; + } + + /// + /// Implicitly converts an int to UInt128. + /// + /// The int to convert. + public static implicit operator UInt128(int value) + { + return new UInt128((ulong)value, 0); + } + + /// + /// Implicitly converts a long to UInt128. + /// + /// The int to convert. + public static implicit operator UInt128(long value) + { + return new UInt128((ulong)value, 0); + } + + /// + /// Implicitly converts an unsigned int to UInt128. + /// + /// The unsigned int to convert. + public static implicit operator UInt128(uint value) + { + return new UInt128((ulong)value, 0); + } + + /// + /// Implicitly converts an unsigned long to UInt128. + /// + /// The unsigned long to convert. + public static implicit operator UInt128(ulong value) + { + return new UInt128(value, 0); + } + + /// + /// Adds two instances of UInt128 together. + /// + /// The augend. + /// The addend. + /// The augend + addend. + public static UInt128 operator +(UInt128 augend, UInt128 addend) + { + ulong low = augend.low + addend.low; + ulong high = augend.high + addend.high; + + if (low < augend.low) + { + high++; + } + + return new UInt128(low, high); + } + + /// + /// Takes the difference between two UInt128. + /// + /// The minuend. + /// The subtrahend. + /// minuend - subtrahend. + public static UInt128 operator -(UInt128 minuend, UInt128 subtrahend) + { + ulong low = minuend.low - subtrahend.low; + ulong high = minuend.high - subtrahend.high; + + if (low > minuend.low) + { + high--; + } + + return new UInt128(low, high); + } + + /// + /// Returns if one UInt128 is less than another UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether left is less than right. + public static bool operator <(UInt128 left, UInt128 right) + { + return (left.high < right.high) + || ((left.high == right.high) && (left.low < right.low)); + } + + /// + /// Returns if one UInt128 is greater than another UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether left is greater than right. + public static bool operator >(UInt128 left, UInt128 right) + { + return right < left; + } + + /// + /// Returns if one UInt128 is less than or equal to another UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether left is less than or equal to the right. + public static bool operator <=(UInt128 left, UInt128 right) + { + return !(right < left); + } + + /// + /// Returns if one UInt128 is greater than or equal to another UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether left is greater than or equal to the right. + public static bool operator >=(UInt128 left, UInt128 right) + { + return !(left < right); + } + + /// + /// Returns if two UInt128 are equal. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether the left is equal to the right. + public static bool operator ==(UInt128 left, UInt128 right) + { + return (left.high == right.high) && (left.low == right.low); + } + + /// + /// Returns if two UInt128 are not equal. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// Whether the left is not equal to the right. + public static bool operator !=(UInt128 left, UInt128 right) + { + return !(left == right); + } + + /// + /// Takes the bitwise and of two instance of UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// The bitwise and of two instance of UInt128.. + public static UInt128 operator &(UInt128 left, UInt128 right) + { + return new UInt128(left.low & right.low, left.high & right.high); + } + + /// + /// Takes the bitwise or of two instance of UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// The bitwise or of two instance of UInt128.. + public static UInt128 operator |(UInt128 left, UInt128 right) + { + return new UInt128(left.low | right.low, left.high | right.high); + } + + /// + /// Takes the bitwise x or of two instance of UInt128. + /// + /// The left hand side of the operator. + /// The right hand side of the operator. + /// The bitwise x or of two instance of UInt128.. + public static UInt128 operator ^(UInt128 left, UInt128 right) + { + return new UInt128(left.low ^ right.low, left.high ^ right.high); + } + + /// + /// Creates a UInt128 from two ulong. + /// + /// The lower 64 bits of the UInt128. + /// The upper 64 bits of the UInt128. + /// A UInt128 from the two ulong. + public static UInt128 Create(ulong low, ulong high) + { + return new UInt128(low, high); + } + + /// + /// Creates a UInt128 from a byte array. + /// + /// The bytes. + /// The starting index. + /// The UInt128 from the byte array. + public static UInt128 FromByteArray(byte[] bytes, int start = 0) + { + ulong low = BitConverter.ToUInt64(bytes, start); + ulong high = BitConverter.ToUInt64(bytes, start + 8); + + return new UInt128(low, high); + } + + /// + /// Converts the UInt128 to a byte array. + /// + /// The UInt128 to convert. + /// The byte array representation of this UInt128. + public static byte[] ToByteArray(UInt128 uint128) + { + byte[] bytes = new byte[UInt128.Length]; + byte[] lowBytes = BitConverter.GetBytes(uint128.low); + byte[] highBytes = BitConverter.GetBytes(uint128.high); + lowBytes.CopyTo(bytes, 0); + highBytes.CopyTo(bytes, 8); + + return bytes; + } + + /// + /// Compares this value to an object. + /// + /// The value to compare to. + /// The comparison. + public int CompareTo(object value) + { + if (value == null) + { + return 1; + } + + if (value is UInt128) + { + return this.CompareTo((UInt128)value); + } + + throw new ArgumentException("Value must be a UInt128."); + } + + /// + /// Compares this UInt128 to another instance of the UInt128 type. + /// + /// The other instance to compare to. + /// + /// A negative number if this instance is less than the other instance. + /// Zero if they are the same. + /// A positive number if this instance is greater than the other instance. + /// + public int CompareTo(UInt128 other) + { + if (this < other) + { + return -1; + } + + if (this > other) + { + return 1; + } + + return 0; + } + + /// + /// Returns whether this instance equals another object. + /// + /// The object to compare to. + /// Whether this instance equals another object. + public override bool Equals(object obj) + { + if (obj is UInt128) + { + return this.Equals((UInt128)obj); + } + + return false; + } + + /// + /// Returns whether this UInt128 equals another UInt128. + /// + /// The UInt128 to compare to. + /// Whether this UInt128 equals another UInt128. + public bool Equals(UInt128 other) + { + return this == other; + } + + /// + /// Gets a hash code for this instance. + /// + /// The hash code for this instance. + public override int GetHashCode() + { + return (int)(this.low.GetHashCode() ^ this.high.GetHashCode()); + } + + /// + /// Gets the string representation of a UInt128 as a hex dump. + /// + /// The string representation of a UInt128 as a hex dump. + public override string ToString() + { + byte[] bytes = UInt128.ToByteArray(this); + return BitConverter.ToString(bytes); + } + + /// + /// Returns the high 64 bits of the UInt128.cs. + /// + /// The high 64 bits of the UInt128.cs. + public ulong GetHigh() + { + return this.high; + } + + /// + /// Returns the low 64 bits of the UInt128.cs. + /// + /// The low 64 bits of the UInt128.cs. + public ulong GetLow() + { + return this.low; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UnauthorizedException.cs b/Microsoft.Azure.Cosmos/src/direct/UnauthorizedException.cs index d762ad230a..3f6b8821a1 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UnauthorizedException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UnauthorizedException.cs @@ -1,86 +1,86 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Net; - using System.Net.Http.Headers; - using System.Runtime.Serialization; - using Microsoft.Azure.Documents.Collections; - - [Serializable] - internal sealed class UnauthorizedException : DocumentClientException - { - public UnauthorizedException() - : this(RMResources.Unauthorized) - { - - } - - public UnauthorizedException(string message) - : this(message, (Exception)null, (HttpResponseHeaders)null) - { - - } - - public UnauthorizedException(string message, SubStatusCodes subStatusCode) - : this(message, (Exception)null, (HttpResponseHeaders)null, null, subStatusCode) - { - - } - - public UnauthorizedException(string message, HttpResponseHeaders headers, Uri requestUri = null) - : this(message, null, headers, requestUri) - { - - } - - public UnauthorizedException(Exception innerException) - : this(RMResources.Unauthorized, innerException, null) - { - - } - - public UnauthorizedException(string message, Exception innerException) - : this(message, innerException, null) - { - - } - - public UnauthorizedException(string message, Exception innerException, SubStatusCodes subStatusCode) - : this(message, innerException, null, null, subStatusCode) - { - - } - - public UnauthorizedException(string message, INameValueCollection headers, Uri requestUri = null) - : base(message, null, headers, HttpStatusCode.Unauthorized, requestUri) - { - SetDescription(); - } - - public UnauthorizedException(string message, - Exception innerException, - HttpResponseHeaders headers, - Uri requestUri = null, - SubStatusCodes? subStatusCode = null) - : base(message, innerException, headers, HttpStatusCode.Unauthorized, requestUri, subStatusCode) - { - SetDescription(); - } - -#if !NETSTANDARD16 - private UnauthorizedException(SerializationInfo info, StreamingContext context) - : base(info, context, HttpStatusCode.Unauthorized) - { - SetDescription(); - } -#endif - - private void SetDescription() - { - this.StatusDescription = HttpConstants.HttpStatusDescriptions.Unauthorized; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Net; + using System.Net.Http.Headers; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents.Collections; + + [Serializable] + internal sealed class UnauthorizedException : DocumentClientException + { + public UnauthorizedException() + : this(RMResources.Unauthorized) + { + + } + + public UnauthorizedException(string message) + : this(message, (Exception)null, (HttpResponseHeaders)null) + { + + } + + public UnauthorizedException(string message, SubStatusCodes subStatusCode) + : this(message, (Exception)null, (HttpResponseHeaders)null, null, subStatusCode) + { + + } + + public UnauthorizedException(string message, HttpResponseHeaders headers, Uri requestUri = null) + : this(message, null, headers, requestUri) + { + + } + + public UnauthorizedException(Exception innerException) + : this(RMResources.Unauthorized, innerException, null) + { + + } + + public UnauthorizedException(string message, Exception innerException) + : this(message, innerException, null) + { + + } + + public UnauthorizedException(string message, Exception innerException, SubStatusCodes subStatusCode) + : this(message, innerException, null, null, subStatusCode) + { + + } + + public UnauthorizedException(string message, INameValueCollection headers, Uri requestUri = null) + : base(message, null, headers, HttpStatusCode.Unauthorized, requestUri) + { + SetDescription(); + } + + public UnauthorizedException(string message, + Exception innerException, + HttpResponseHeaders headers, + Uri requestUri = null, + SubStatusCodes? subStatusCode = null) + : base(message, innerException, headers, HttpStatusCode.Unauthorized, requestUri, subStatusCode) + { + SetDescription(); + } + +#if !NETSTANDARD16 + private UnauthorizedException(SerializationInfo info, StreamingContext context) + : base(info, context, HttpStatusCode.Unauthorized) + { + SetDescription(); + } +#endif + + private void SetDescription() + { + this.StatusDescription = HttpConstants.HttpStatusDescriptions.Unauthorized; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Undefined.cs b/Microsoft.Azure.Cosmos/src/direct/Undefined.cs index dd73bb9240..f5a7eaf301 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Undefined.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Undefined.cs @@ -1,64 +1,64 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - - /// - /// Instance of the class can be supplied as part of Partition Key Value to denote a value which is absent in the Azure Cosmos DB document. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class Undefined : IEquatable - { - /// - /// singleton to help reuse the object. - /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Undefined is infact immutable")] - public static readonly Undefined Value = new Undefined(); - - private Undefined() - { - } - - /// - /// Determines whether is from the Azure Cosmos DB service. - /// - /// - /// true if the specified object is equal to the current object; otherwise, false. - /// - /// The object to compare with the current object. - public bool Equals(Undefined other) - { - return other != null; - } - - /// - /// Determines whether other is from the Azure Cosmos DB service. - /// - /// - /// true if the specified object is equal to the current object; otherwise, false. - /// - /// The object to compare with the current object. - public override bool Equals(object other) - { - return this.Equals(other as Undefined); - } - - /// - /// Serves as a hash function for the Azure Cosmos DB database type. - /// - /// - /// A hash code value. - /// - public override int GetHashCode() - { - return 0; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + + /// + /// Instance of the class can be supplied as part of Partition Key Value to denote a value which is absent in the Azure Cosmos DB document. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class Undefined : IEquatable + { + /// + /// singleton to help reuse the object. + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "Undefined is infact immutable")] + public static readonly Undefined Value = new Undefined(); + + private Undefined() + { + } + + /// + /// Determines whether is from the Azure Cosmos DB service. + /// + /// + /// true if the specified object is equal to the current object; otherwise, false. + /// + /// The object to compare with the current object. + public bool Equals(Undefined other) + { + return other != null; + } + + /// + /// Determines whether other is from the Azure Cosmos DB service. + /// + /// + /// true if the specified object is equal to the current object; otherwise, false. + /// + /// The object to compare with the current object. + public override bool Equals(object other) + { + return this.Equals(other as Undefined); + } + + /// + /// Serves as a hash function for the Azure Cosmos DB database type. + /// + /// + /// A hash code value. + /// + public override int GetHashCode() + { + return 0; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UndefinedPartitionKeyComponent.cs b/Microsoft.Azure.Cosmos/src/direct/UndefinedPartitionKeyComponent.cs index 47342b00b7..f0c654f702 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UndefinedPartitionKeyComponent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UndefinedPartitionKeyComponent.cs @@ -1,76 +1,76 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents.Routing -{ - using System; - using System.IO; - using Newtonsoft.Json; - - internal sealed class UndefinedPartitionKeyComponent: IPartitionKeyComponent - { - public static readonly UndefinedPartitionKeyComponent Value = new UndefinedPartitionKeyComponent(); - - internal UndefinedPartitionKeyComponent() - { - } - - public int CompareTo(IPartitionKeyComponent other) - { - UndefinedPartitionKeyComponent otherUndefined = other as UndefinedPartitionKeyComponent; - if (otherUndefined == null) - { - throw new ArgumentException("other"); - } - - return 0; - } - - public int GetTypeOrdinal() - { - return (int)PartitionKeyComponentType.Undefined; - } - - public double GetHashValue() - { - return 0; - } - - public override int GetHashCode() - { - return 0; - } - - public void JsonEncode(JsonWriter writer) - { - writer.WriteStartObject(); - writer.WriteEndObject(); - } - - public object ToObject() - { - return Undefined.Value; - } - - public IPartitionKeyComponent Truncate() - { - return this; - } - - public void WriteForHashing(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Undefined); - } - - public void WriteForHashingV2(BinaryWriter writer) - { - writer.Write((byte)PartitionKeyComponentType.Undefined); - } - - public void WriteForBinaryEncoding(BinaryWriter binaryWriter) - { - binaryWriter.Write((byte)PartitionKeyComponentType.Undefined); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Routing +{ + using System; + using System.IO; + using Newtonsoft.Json; + + internal sealed class UndefinedPartitionKeyComponent: IPartitionKeyComponent + { + public static readonly UndefinedPartitionKeyComponent Value = new UndefinedPartitionKeyComponent(); + + internal UndefinedPartitionKeyComponent() + { + } + + public int CompareTo(IPartitionKeyComponent other) + { + UndefinedPartitionKeyComponent otherUndefined = other as UndefinedPartitionKeyComponent; + if (otherUndefined == null) + { + throw new ArgumentException("other"); + } + + return 0; + } + + public int GetTypeOrdinal() + { + return (int)PartitionKeyComponentType.Undefined; + } + + public double GetHashValue() + { + return 0; + } + + public override int GetHashCode() + { + return 0; + } + + public void JsonEncode(JsonWriter writer) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + } + + public object ToObject() + { + return Undefined.Value; + } + + public IPartitionKeyComponent Truncate() + { + return this; + } + + public void WriteForHashing(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Undefined); + } + + public void WriteForHashingV2(BinaryWriter writer) + { + writer.Write((byte)PartitionKeyComponentType.Undefined); + } + + public void WriteForBinaryEncoding(BinaryWriter binaryWriter) + { + binaryWriter.Write((byte)PartitionKeyComponentType.Undefined); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UniqueIndexReIndexContext.cs b/Microsoft.Azure.Cosmos/src/direct/UniqueIndexReIndexContext.cs index 450738b1fc..89611a94dd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UniqueIndexReIndexContext.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UniqueIndexReIndexContext.cs @@ -1,79 +1,79 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - - internal sealed class UniqueIndexReIndexContext : JsonSerializable - { - private Collection uniqueKeys; - - [JsonProperty(PropertyName = Constants.Properties.UniqueKeys)] - public Collection UniqueKeys - { - get - { - if (this.uniqueKeys == null) - { - this.uniqueKeys = base.GetValue>(Constants.Properties.UniqueKeys); - if (this.uniqueKeys == null) - { - this.uniqueKeys = new Collection(); - } - } - - return this.uniqueKeys; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeys")); - } - - this.uniqueKeys = value; - base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); - } - } - - [JsonProperty(PropertyName = Constants.Properties.LastDocumentGLSN)] - public ulong LastDocumentGLSN - { - get - { - return base.GetValue(Constants.Properties.LastDocumentGLSN); - } - set - { - base.SetValue(Constants.Properties.LastDocumentGLSN, value); - } - } - - internal override void OnSave() - { - if (this.uniqueKeys != null) - { - foreach (UniqueKey uniqueKey in this.uniqueKeys) - { - uniqueKey.OnSave(); - } - - base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); - } - } - - internal override void Validate() - { - base.Validate(); - foreach (UniqueKey uniqueKey in this.UniqueKeys) - { - uniqueKey.Validate(); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + internal sealed class UniqueIndexReIndexContext : JsonSerializable + { + private Collection uniqueKeys; + + [JsonProperty(PropertyName = Constants.Properties.UniqueKeys)] + public Collection UniqueKeys + { + get + { + if (this.uniqueKeys == null) + { + this.uniqueKeys = base.GetValue>(Constants.Properties.UniqueKeys); + if (this.uniqueKeys == null) + { + this.uniqueKeys = new Collection(); + } + } + + return this.uniqueKeys; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeys")); + } + + this.uniqueKeys = value; + base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); + } + } + + [JsonProperty(PropertyName = Constants.Properties.LastDocumentGLSN)] + public ulong LastDocumentGLSN + { + get + { + return base.GetValue(Constants.Properties.LastDocumentGLSN); + } + set + { + base.SetValue(Constants.Properties.LastDocumentGLSN, value); + } + } + + internal override void OnSave() + { + if (this.uniqueKeys != null) + { + foreach (UniqueKey uniqueKey in this.uniqueKeys) + { + uniqueKey.OnSave(); + } + + base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); + } + } + + internal override void Validate() + { + base.Validate(); + foreach (UniqueKey uniqueKey in this.UniqueKeys) + { + uniqueKey.Validate(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UniqueKey.cs b/Microsoft.Azure.Cosmos/src/direct/UniqueKey.cs index a65fc287cc..14036dd8e4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UniqueKey.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UniqueKey.cs @@ -1,141 +1,141 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System.Collections.ObjectModel; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - - /// - /// Represents a unique key on that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service. - /// - /// - /// 1) For partitioned collections, the value of partition key is implicitly a part of each unique key. - /// 2) Uniqueness constraint is also enforced for missing values. - /// For instance, if unique key policy defines a unique key with single property path, there could be only one document that has missing value for this property. - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class UniqueKey : JsonSerializable - { - private Collection paths; - private JObject filter; - /// - /// Gets or sets the paths, a set of which must be unique for each document in the Azure Cosmos DB service. - /// - /// - /// - /// - /// - /// { "/name/first", "/name/last" }; - /// ]]> - /// - [JsonProperty(PropertyName = Constants.Properties.Paths)] - public Collection Paths - { - get - { - if (this.paths == null) - { - this.paths = base.GetValue>(Constants.Properties.Paths); - if (this.paths == null) - { - this.paths = new Collection(); - } - } - - return this.paths; - } - set - { - this.paths = value; - base.SetValue(Constants.Properties.Paths, value); - } - } - - [JsonProperty(PropertyName = Constants.Properties.Filter, NullValueHandling = NullValueHandling.Ignore)] - internal JObject Filter - { - get - { - this.filter = this.GetValue(Constants.Properties.Filter); - return this.filter; - } - set - { - this.filter = value; - this.SetValue(Constants.Properties.Filter, value); - } - } - - internal override void Validate() - { - base.Validate(); - base.GetValue>(Constants.Properties.Paths); - base.GetValue(Constants.Properties.Filter); - } - - public override bool Equals(object obj) - { - if (!(obj is UniqueKey uniqueKey)) - { - return false; - } - - if (this.Paths.Count != uniqueKey.Paths.Count) return false; - - foreach (string path in uniqueKey.paths) - { - if (!this.Paths.Contains(path)) - { - return false; - } - } - - if (this.Filter == null && uniqueKey.Filter == null) return true; - - if (this.Filter != null && uniqueKey.Filter != null) - { - JTokenEqualityComparer comparer = new JTokenEqualityComparer(); - return comparer.Equals(this.Filter, uniqueKey.Filter); - } - - return false; - } - - public override int GetHashCode() - { - int hashCode = 0; - foreach (string token in this.Paths) - { - hashCode = hashCode ^ token.GetHashCode(); - } - - if (this.Filter != null) - { - JTokenEqualityComparer comparer = new JTokenEqualityComparer(); - hashCode = hashCode ^ comparer.GetHashCode(this.Filter.GetHashCode()); - } - - return hashCode; - } - - internal override void OnSave() - { - if (this.paths != null) - { - base.SetValue(Constants.Properties.Paths, this.paths); - } - if (this.filter != null) - { - base.SetValue(Constants.Properties.Filter, this.filter); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System.Collections.ObjectModel; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + /// + /// Represents a unique key on that enforces uniqueness constraint on documents in the collection in the Azure Cosmos DB service. + /// + /// + /// 1) For partitioned collections, the value of partition key is implicitly a part of each unique key. + /// 2) Uniqueness constraint is also enforced for missing values. + /// For instance, if unique key policy defines a unique key with single property path, there could be only one document that has missing value for this property. + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class UniqueKey : JsonSerializable + { + private Collection paths; + private JObject filter; + /// + /// Gets or sets the paths, a set of which must be unique for each document in the Azure Cosmos DB service. + /// + /// + /// + /// + /// + /// { "/name/first", "/name/last" }; + /// ]]> + /// + [JsonProperty(PropertyName = Constants.Properties.Paths)] + public Collection Paths + { + get + { + if (this.paths == null) + { + this.paths = base.GetValue>(Constants.Properties.Paths); + if (this.paths == null) + { + this.paths = new Collection(); + } + } + + return this.paths; + } + set + { + this.paths = value; + base.SetValue(Constants.Properties.Paths, value); + } + } + + [JsonProperty(PropertyName = Constants.Properties.Filter, NullValueHandling = NullValueHandling.Ignore)] + internal JObject Filter + { + get + { + this.filter = this.GetValue(Constants.Properties.Filter); + return this.filter; + } + set + { + this.filter = value; + this.SetValue(Constants.Properties.Filter, value); + } + } + + internal override void Validate() + { + base.Validate(); + base.GetValue>(Constants.Properties.Paths); + base.GetValue(Constants.Properties.Filter); + } + + public override bool Equals(object obj) + { + if (!(obj is UniqueKey uniqueKey)) + { + return false; + } + + if (this.Paths.Count != uniqueKey.Paths.Count) return false; + + foreach (string path in uniqueKey.paths) + { + if (!this.Paths.Contains(path)) + { + return false; + } + } + + if (this.Filter == null && uniqueKey.Filter == null) return true; + + if (this.Filter != null && uniqueKey.Filter != null) + { + JTokenEqualityComparer comparer = new JTokenEqualityComparer(); + return comparer.Equals(this.Filter, uniqueKey.Filter); + } + + return false; + } + + public override int GetHashCode() + { + int hashCode = 0; + foreach (string token in this.Paths) + { + hashCode = hashCode ^ token.GetHashCode(); + } + + if (this.Filter != null) + { + JTokenEqualityComparer comparer = new JTokenEqualityComparer(); + hashCode = hashCode ^ comparer.GetHashCode(this.Filter.GetHashCode()); + } + + return hashCode; + } + + internal override void OnSave() + { + if (this.paths != null) + { + base.SetValue(Constants.Properties.Paths, this.paths); + } + if (this.filter != null) + { + base.SetValue(Constants.Properties.Filter, this.filter); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UniqueKeyPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/UniqueKeyPolicy.cs index 0f37cbeab7..a20696e8a5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UniqueKeyPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UniqueKeyPolicy.cs @@ -1,167 +1,167 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.ObjectModel; - using System.Globalization; - using Newtonsoft.Json; - - /// - /// Represents the unique key policy configuration for specifying uniqueness constraints on documents in the collection in the Azure Cosmos DB service. - /// - /// - /// { - /// // pair is unique. - /// new UniqueKey { Paths = new Collection { "/name/first", "/name/last" } }, - /// // /address is unique. - /// new UniqueKey { Paths = new Collection { "/address" } }, - /// } - /// } - /// }; - /// DocumentCollection collection = await client.CreateDocumentCollectionAsync(databaseLink, collectionSpec }); - /// - /// var doc = JObject.Parse("{\"name\": { \"first\": \"John\", \"last\": \"Smith\" }, \"alias\":\"johnsmith\" }"); - /// await client.CreateDocumentAsync(collection.SelfLink, doc); - /// - /// doc = JObject.Parse("{\"name\": { \"first\": \"James\", \"last\": \"Smith\" }, \"alias\":\"jamessmith\" }"); - /// await client.CreateDocumentAsync(collection.SelfLink, doc); - /// - /// try - /// { - /// // Error: first+last name is not unique. - /// doc = JObject.Parse("{\"name\": { \"first\": \"John\", \"last\": \"Smith\" }, \"alias\":\"johnsmith1\" }"); - /// await client.CreateDocumentAsync(collection.SelfLink, doc); - /// throw new Exception("CreateDocumentAsync should have thrown exception/conflict"); - /// } - /// catch (DocumentClientException ex) - /// { - /// if (ex.StatusCode != System.Net.HttpStatusCode.Conflict) throw; - /// } - /// - /// try - /// { - /// // Error: alias is not unique. - /// doc = JObject.Parse("{\"name\": { \"first\": \"James Jr\", \"last\": \"Smith\" }, \"alias\":\"jamessmith\" }"); - /// await client.CreateDocumentAsync(collection.SelfLink, doc); - /// throw new Exception("CreateDocumentAsync should have thrown exception/conflict"); - /// } - /// catch (DocumentClientException ex) - /// { - /// if (ex.StatusCode != System.Net.HttpStatusCode.Conflict) throw; - /// } - /// ]]> - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class UniqueKeyPolicy : JsonSerializable - { - private Collection uniqueKeys; - - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public UniqueKeyPolicy() - { - } - - /// - /// Gets or sets collection of that guarantee uniqueness of documents in collection in the Azure Cosmos DB service. - /// - [JsonProperty(PropertyName = Constants.Properties.UniqueKeys)] - public Collection UniqueKeys - { - get - { - if (this.uniqueKeys == null) - { - this.uniqueKeys = base.GetValue>(Constants.Properties.UniqueKeys); - if (this.uniqueKeys == null) - { - this.uniqueKeys = new Collection(); - } - } - - return this.uniqueKeys; - } - - set - { - if (value == null) - { - throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeys")); - } - - this.uniqueKeys = value; - base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); - } - } - - public override bool Equals(object obj) - { - if (!(obj is UniqueKeyPolicy uniqueKeyPolicy)) - { - return false; - } - - if (this.UniqueKeys.Count != uniqueKeyPolicy.UniqueKeys.Count) - { - return false; - } - - foreach (UniqueKey uniqueKey in this.uniqueKeys) - { - if (!uniqueKeyPolicy.UniqueKeys.Contains(uniqueKey)) - { - return false; - } - } - - return true; - } - - public override int GetHashCode() - { - int hashcode = 0; - - foreach (UniqueKey uniqueKey in this.uniqueKeys) - { - hashcode ^= uniqueKey.GetHashCode(); - } - - return hashcode; - } - - internal override void OnSave() - { - if (this.uniqueKeys != null) - { - foreach (UniqueKey uniqueKey in this.uniqueKeys) - { - uniqueKey.OnSave(); - } - - base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); - } - } - - internal override void Validate() - { - base.Validate(); - foreach (UniqueKey uniqueKey in this.UniqueKeys) - { - uniqueKey.Validate(); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Represents the unique key policy configuration for specifying uniqueness constraints on documents in the collection in the Azure Cosmos DB service. + /// + /// + /// { + /// // pair is unique. + /// new UniqueKey { Paths = new Collection { "/name/first", "/name/last" } }, + /// // /address is unique. + /// new UniqueKey { Paths = new Collection { "/address" } }, + /// } + /// } + /// }; + /// DocumentCollection collection = await client.CreateDocumentCollectionAsync(databaseLink, collectionSpec }); + /// + /// var doc = JObject.Parse("{\"name\": { \"first\": \"John\", \"last\": \"Smith\" }, \"alias\":\"johnsmith\" }"); + /// await client.CreateDocumentAsync(collection.SelfLink, doc); + /// + /// doc = JObject.Parse("{\"name\": { \"first\": \"James\", \"last\": \"Smith\" }, \"alias\":\"jamessmith\" }"); + /// await client.CreateDocumentAsync(collection.SelfLink, doc); + /// + /// try + /// { + /// // Error: first+last name is not unique. + /// doc = JObject.Parse("{\"name\": { \"first\": \"John\", \"last\": \"Smith\" }, \"alias\":\"johnsmith1\" }"); + /// await client.CreateDocumentAsync(collection.SelfLink, doc); + /// throw new Exception("CreateDocumentAsync should have thrown exception/conflict"); + /// } + /// catch (DocumentClientException ex) + /// { + /// if (ex.StatusCode != System.Net.HttpStatusCode.Conflict) throw; + /// } + /// + /// try + /// { + /// // Error: alias is not unique. + /// doc = JObject.Parse("{\"name\": { \"first\": \"James Jr\", \"last\": \"Smith\" }, \"alias\":\"jamessmith\" }"); + /// await client.CreateDocumentAsync(collection.SelfLink, doc); + /// throw new Exception("CreateDocumentAsync should have thrown exception/conflict"); + /// } + /// catch (DocumentClientException ex) + /// { + /// if (ex.StatusCode != System.Net.HttpStatusCode.Conflict) throw; + /// } + /// ]]> + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class UniqueKeyPolicy : JsonSerializable + { + private Collection uniqueKeys; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public UniqueKeyPolicy() + { + } + + /// + /// Gets or sets collection of that guarantee uniqueness of documents in collection in the Azure Cosmos DB service. + /// + [JsonProperty(PropertyName = Constants.Properties.UniqueKeys)] + public Collection UniqueKeys + { + get + { + if (this.uniqueKeys == null) + { + this.uniqueKeys = base.GetValue>(Constants.Properties.UniqueKeys); + if (this.uniqueKeys == null) + { + this.uniqueKeys = new Collection(); + } + } + + return this.uniqueKeys; + } + + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueKeys")); + } + + this.uniqueKeys = value; + base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); + } + } + + public override bool Equals(object obj) + { + if (!(obj is UniqueKeyPolicy uniqueKeyPolicy)) + { + return false; + } + + if (this.UniqueKeys.Count != uniqueKeyPolicy.UniqueKeys.Count) + { + return false; + } + + foreach (UniqueKey uniqueKey in this.uniqueKeys) + { + if (!uniqueKeyPolicy.UniqueKeys.Contains(uniqueKey)) + { + return false; + } + } + + return true; + } + + public override int GetHashCode() + { + int hashcode = 0; + + foreach (UniqueKey uniqueKey in this.uniqueKeys) + { + hashcode ^= uniqueKey.GetHashCode(); + } + + return hashcode; + } + + internal override void OnSave() + { + if (this.uniqueKeys != null) + { + foreach (UniqueKey uniqueKey in this.uniqueKeys) + { + uniqueKey.OnSave(); + } + + base.SetValue(Constants.Properties.UniqueKeys, this.uniqueKeys); + } + } + + internal override void Validate() + { + base.Validate(); + foreach (UniqueKey uniqueKey in this.UniqueKeys) + { + uniqueKey.Validate(); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UnixDateTimeConverter.cs b/Microsoft.Azure.Cosmos/src/direct/UnixDateTimeConverter.cs index 86ea7c4ae0..be6bdc96a2 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UnixDateTimeConverter.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UnixDateTimeConverter.cs @@ -1,76 +1,76 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Globalization; - using Newtonsoft.Json; - using Newtonsoft.Json.Converters; - - /// - /// Converts a DateTime object to and from JSON. - /// DateTime is represented as the total number of seconds - /// that have elapsed since January 1, 1970 (midnight UTC/GMT), - /// not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). - /// -#if COSMOSCLIENT - internal -#else - public -#endif - sealed class UnixDateTimeConverter : DateTimeConverterBase - { - private static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); - - /// - /// Writes the JSON representation of the DateTime object. - /// - /// The Newtonsoft.Json.JsonWriter to write to. - /// The value. - /// The calling serializer. - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - if (value is DateTime) - { - Int64 totalSeconds = (Int64) ((DateTime)value - UnixStartTime).TotalSeconds; - writer.WriteValue(totalSeconds); - } - else - { - throw new ArgumentException(RMResources.DateTimeConverterInvalidDateTime, "value"); - } - } - - /// - /// Reads the JSON representation of the DateTime object. - /// - /// The Newtonsoft.Json.JsonReader to read from. - /// Type of the object. - /// The existing value of object being read. - /// The calling serializer. - /// - /// The DateTime object value. - /// - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - if (reader.TokenType != Newtonsoft.Json.JsonToken.Integer) - { - throw new Exception(RMResources.DateTimeConverterInvalidReaderValue); - } - - double totalSeconds = 0; - - try - { - totalSeconds = Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture); - } - catch - { - throw new Exception(RMResources.DateTimeConveterInvalidReaderDoubleValue); - } - - return UnixStartTime.AddSeconds(totalSeconds); - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Globalization; + using Newtonsoft.Json; + using Newtonsoft.Json.Converters; + + /// + /// Converts a DateTime object to and from JSON. + /// DateTime is represented as the total number of seconds + /// that have elapsed since January 1, 1970 (midnight UTC/GMT), + /// not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z). + /// +#if COSMOSCLIENT + internal +#else + public +#endif + sealed class UnixDateTimeConverter : DateTimeConverterBase + { + private static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + + /// + /// Writes the JSON representation of the DateTime object. + /// + /// The Newtonsoft.Json.JsonWriter to write to. + /// The value. + /// The calling serializer. + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value is DateTime) + { + Int64 totalSeconds = (Int64) ((DateTime)value - UnixStartTime).TotalSeconds; + writer.WriteValue(totalSeconds); + } + else + { + throw new ArgumentException(RMResources.DateTimeConverterInvalidDateTime, "value"); + } + } + + /// + /// Reads the JSON representation of the DateTime object. + /// + /// The Newtonsoft.Json.JsonReader to read from. + /// Type of the object. + /// The existing value of object being read. + /// The calling serializer. + /// + /// The DateTime object value. + /// + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType != Newtonsoft.Json.JsonToken.Integer) + { + throw new Exception(RMResources.DateTimeConverterInvalidReaderValue); + } + + double totalSeconds = 0; + + try + { + totalSeconds = Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture); + } + catch + { + throw new Exception(RMResources.DateTimeConveterInvalidReaderDoubleValue); + } + + return UnixStartTime.AddSeconds(totalSeconds); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UnsupportedSystemUtilizationReader.cs b/Microsoft.Azure.Cosmos/src/direct/UnsupportedSystemUtilizationReader.cs index bff659911c..660a3d5230 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UnsupportedSystemUtilizationReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UnsupportedSystemUtilizationReader.cs @@ -1,24 +1,24 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - - internal sealed class UnsupportedSystemUtilizationReader : SystemUtilizationReaderBase - { - public UnsupportedSystemUtilizationReader() : base() - { - } - - protected override float GetSystemWideCpuUsageCore() - { - return Single.NaN; - } - - protected override long? GetSystemWideMemoryAvailabiltyCore() - { - return null; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + + internal sealed class UnsupportedSystemUtilizationReader : SystemUtilizationReaderBase + { + public UnsupportedSystemUtilizationReader() : base() + { + } + + protected override float GetSystemWideCpuUsageCore() + { + return Single.NaN; + } + + protected override long? GetSystemWideMemoryAvailabiltyCore() + { + return null; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/UriUtility.cs b/Microsoft.Azure.Cosmos/src/direct/UriUtility.cs index caa7b59e8f..d391a42714 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UriUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UriUtility.cs @@ -1,505 +1,505 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.Specialized; - using System.Net; - using System.Net.NetworkInformation; - using System.Text; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.Collections; - - internal static class UrlUtility - { - internal static string ConcatenateUrlsString(string baseUrl, params string[] relativeParts) - { - StringBuilder urlStringBuilder = new StringBuilder(RemoveTrailingSlash(baseUrl)); - foreach (string urlPart in relativeParts) - { - urlStringBuilder.Append(RuntimeConstants.Separators.Url[0]); - urlStringBuilder.Append(RemoveLeadingSlash(urlPart)); - } - return urlStringBuilder.ToString(); - } - - internal static string ConcatenateUrlsString(string baseUrl, string relativePart) - { - return AddTrailingSlash(baseUrl) + RemoveLeadingSlash(relativePart); - } - - internal static string ConcatenateUrlsString(Uri baseUrl, string relativePart) - { - return UrlUtility.ConcatenateUrlsString(GetLeftPartOfPath(baseUrl), relativePart); - } - - internal static void ExtractTargetInfo(Uri uri, out string tenantId, out string applicationName, out string serviceId, out string partitionKey, out string replicaId) - { - if (uri.Segments == null || uri.Segments.Length < 9) - { - // uri could contains more segments (e.g. replicas etc), hence - // for the purpose of this call, it is safe to relax from != 9 to < 9 - DefaultTrace.TraceError("Uri {0} is invalid", uri); - throw new ArgumentException("uri"); - } - - //net.tcp: (or) http://cluster.docdb.cloudapp.net:[Port]/apps//services/databases0/partitions//replicas/ - tenantId = ExtractTenantIdFromUri(uri); - applicationName = uri.Segments[2].Substring(0, uri.Segments[2].Length - 1); - serviceId = uri.Segments[4].Substring(0, uri.Segments[4].Length - 1); - partitionKey = uri.Segments[6].Substring(0, uri.Segments[6].Length - 1); //Not PartitionId. - replicaId = uri.Segments[8].Substring(0, uri.Segments[8].Length); - } - - internal static string ConcatenateUrlsString(Uri baseUrl, Uri relativePart) - { - if (relativePart.IsAbsoluteUri) - return relativePart.ToString(); - - return ConcatenateUrlsString(GetLeftPartOfPath(baseUrl), relativePart.OriginalString); - } - - internal static Uri ConcatenateUrls(string baseUrl, string relativePart) - { - return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); - } - - internal static Uri ConcatenateUrls(Uri baseUrl, string relativePart) - { - return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); - } - - internal static Uri ConcatenateUrls(Uri baseUrl, Uri relativePart) - { - if (relativePart.IsAbsoluteUri) - return relativePart; - - return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); - } - - internal static NameValueCollection ParseQuery(string queryString) - { - NameValueCollection result = null; - - queryString = UrlUtility.RemoveLeadingQuestionMark(queryString); - if (string.IsNullOrEmpty(queryString)) - result = new NameValueCollection(0); - else - { - string[] queries = SplitAndRemoveEmptyEntries(queryString, new char[] { RuntimeConstants.Separators.Query[1] }); - result = new NameValueCollection(queries.Length); - for (int index = 0; index < queries.Length; ++index) - { - string[] nameValue = SplitAndRemoveEmptyEntries(queries[index], new char[] { RuntimeConstants.Separators.Query[2] }, 2); - result.Add(nameValue[0], nameValue.Length > 1 ? nameValue[1] : null); - } - } - - return result; - } - - internal static string CreateQuery(INameValueCollection parsedQuery) - { - if (parsedQuery == null) - return string.Empty; - - StringBuilder queryString = new StringBuilder(); - - int count = parsedQuery.Count(); - foreach (string key in parsedQuery) - { - string value = parsedQuery[key]; - if (!string.IsNullOrEmpty(key)) - { - if (queryString.Length > 0) - queryString.Append(RuntimeConstants.Separators.Query[1]); - - queryString.Append(key); - - if (value != null) - { - queryString.Append(RuntimeConstants.Separators.Query[2]); - queryString.Append(value); - } - } - } - - return queryString.ToString(); - } - - internal static Uri SetQuery(Uri url, string query) - { - if (url == null) throw new ArgumentNullException("url"); - - string urlSansQuery; - UriKind resultKind; - if (url.IsAbsoluteUri) - { - urlSansQuery = url.GetComponents(UriComponents.AbsoluteUri & (~UriComponents.Query) & (~UriComponents.Fragment), UriFormat.Unescaped); - resultKind = UriKind.Absolute; - } - else - { - resultKind = UriKind.Relative; - urlSansQuery = url.ToString(); - int lastQuestionMarkIndex = urlSansQuery.LastIndexOf(RuntimeConstants.Separators.Query[0]); - if (lastQuestionMarkIndex >= 0) - urlSansQuery = urlSansQuery.Remove(lastQuestionMarkIndex, urlSansQuery.Length - lastQuestionMarkIndex); - } - - query = UrlUtility.RemoveLeadingQuestionMark(query); - if (!string.IsNullOrEmpty(query)) - return new Uri(UrlUtility.AddTrailingSlash(urlSansQuery) + RuntimeConstants.Separators.Query[0] + query, resultKind); - else - return new Uri(UrlUtility.AddTrailingSlash(urlSansQuery), resultKind); - } - - internal static string RemoveLeadingQuestionMark(string path) - { - if (string.IsNullOrEmpty(path)) - return path; - - if (path[0] == RuntimeConstants.Separators.Query[0]) - return path.Remove(0, 1); - - return path; - } - - internal static string RemoveTrailingSlash(string path) - { - if (string.IsNullOrEmpty(path)) - return path; - - int length = path.Length; - if (path[length - 1] == RuntimeConstants.Separators.Url[0]) - return path.Remove(length - 1, 1); - - return path; - } - internal static StringSegment RemoveTrailingSlashes(StringSegment path) - { - if (path.IsNullOrEmpty()) - return path; - - return path.TrimEnd(RuntimeConstants.Separators.Url); - } - - internal static string RemoveTrailingSlashes(string path) - { - if (string.IsNullOrEmpty(path)) - return path; - - return path.TrimEnd(RuntimeConstants.Separators.Url); - } - - internal static StringSegment RemoveLeadingSlashes(StringSegment path) - { - if (path.IsNullOrEmpty()) - return path; - - return path.TrimStart(RuntimeConstants.Separators.Url); - } - - internal static string RemoveLeadingSlash(string path) - { - if (string.IsNullOrEmpty(path)) - return path; - - if (path[0] == RuntimeConstants.Separators.Url[0]) - return path.Remove(0, 1); - - return path; - } - - internal static string RemoveLeadingSlashes(string path) - { - if (string.IsNullOrEmpty(path)) - return path; - - return path.TrimStart(RuntimeConstants.Separators.Url); - } - - internal static string AddTrailingSlash(string path) - { - if (string.IsNullOrEmpty(path)) - path = new string(RuntimeConstants.Separators.Url); - else if (path[path.Length - 1] != RuntimeConstants.Separators.Url[0]) - path = path + RuntimeConstants.Separators.Url[0]; - - return path; - } - - internal static string AddLeadingSlash(string path) - { - if (string.IsNullOrEmpty(path)) - path = new string(RuntimeConstants.Separators.Url); - else if (path[0] != RuntimeConstants.Separators.Url[0]) - path = RuntimeConstants.Separators.Url[0] + path; - - return path; - } - - internal static string GetLeftPartOfAuthority(Uri uri) - { - return uri.GetLeftPart(UriPartial.Authority); - } - - internal static string GetLeftPartOfPath(Uri uri) - { - return uri.GetLeftPart(UriPartial.Path); - } - - public static string[] SplitAndRemoveEmptyEntries(string str, char[] seperators) - { - return SplitAndRemoveEmptyEntries(str, seperators, int.MaxValue); - } - - public static string[] SplitAndRemoveEmptyEntries(string str, char[] seperators, int count) - { - return str.Split(seperators, count, StringSplitOptions.RemoveEmptyEntries); - } - - //ID Segment Parsing Helper. - internal static string ExtractIdFromItemUri(Uri uri, int i) - { - string id = uri.Segments[i]; - return UrlUtility.RemoveTrailingSlash(id); - } - - // Extract the tenant id from the dns name - // All our supported domain names are have more then one dns zone so they we only need accept names with at least one zone in them - // ie, we do not have to supoprt http://localhost/ as a value uri with tenant information but we will for ease of use - // Also support http://hostname/accounts/{id}/operation/... - internal static string ExtractTenantIdFromUri(Uri uri) - { - if (UrlUtility.IsAccountsPathSegmentPartOfFirstItem(uri)) - { - return UrlUtility.ExtractIdFromItemUri(uri, 2); - } - - return UrlUtility.ExtractTenantIdFromUriIgnoreAccountsPattern(uri); - } - - // Extract the tenant id from the dns name - // Support for extract federationname from the format http://federationname.documents.azure.com/accounts/{id}/operation/... - internal static string ExtractTenantIdFromUriIgnoreAccountsPattern(Uri uri) - { - string hostName = uri.DnsSafeHost; - int firstPeriod = hostName.IndexOf('.'); - - if (firstPeriod != -1) - { - return hostName.Substring(0, firstPeriod); - } - else - { - return hostName; - } - } - - internal static string ExtractIdOrFullNameFromUri(string path, out bool isNameBased) - { - bool isFeed; - string resourceIdOrFullName; - string resourcePath; - if (PathsHelper.TryParsePathSegments(path, out isFeed, out resourcePath, out resourceIdOrFullName, out isNameBased)) - { - return resourceIdOrFullName; - } - - return null; - } - - internal static string ExtractIdFromItemUri(Uri uri) - { - string id = uri.Segments[uri.Segments.Length - 1]; - return UrlUtility.RemoveTrailingSlash(id); - } - - internal static string ExtractIdFromCollectionUri(Uri uri) - { - string ownerId = uri.Segments[uri.Segments.Length - 2]; - return UrlUtility.RemoveTrailingSlash(ownerId); - } - - internal static string ExtractItemIdAndCollectionIdFromUri(Uri uri, out string collectionId) - { - collectionId = UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 3]); - return UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 1]); - } - - internal static string ExtractFileNameFromUri(Uri uri) - { - return UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 1]); - } - - // expected uri http (or) tcp://:/ - internal static bool IsLocalHostUri(Uri uri) - { - IPAddress ipAddress; - if (!IPAddress.TryParse(uri.DnsSafeHost, out ipAddress)) - { - throw new ArgumentException("uri"); - } - - if (IPAddress.IsLoopback(ipAddress)) - { - return true; - } - - List Addresses = new List(); - NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); - foreach (NetworkInterface adapter in adapters) - { - IPInterfaceProperties properties = adapter.GetIPProperties(); - foreach (IPAddressInformation localIpInfo in properties.UnicastAddresses) - { - if (localIpInfo.Address.Equals(ipAddress)) - { - return true; - } - } - } - - return false; - } - - // Parsing urls like http://hostname/accounts/{id}/operation/... - private static bool IsAccountsPathSegmentPartOfFirstItem(Uri uri) - { - if (uri.Segments.Length < 3) - { - return false; - } - - string firstPart = UrlUtility.ExtractIdFromItemUri(uri, 1); - return string.Equals(firstPart, Paths.AccountsPathSegment, StringComparison.Ordinal); - } - - #region Astoria Url Parsing functions - internal static bool IsAstoriaUrl(Uri url) - { - return (url.AbsolutePath.IndexOf(RuntimeConstants.Separators.Parenthesis[0]) != -1 && url.AbsolutePath.IndexOf(RuntimeConstants.Separators.Parenthesis[1]) != -1); - } - - internal static Uri ToNativeUrl(Uri astoriaUrl) - { - Uri baseUri = null; - - if (astoriaUrl.IsAbsoluteUri) - baseUri = new Uri(UrlUtility.GetLeftPartOfAuthority(astoriaUrl)); - - string query = astoriaUrl.Query; - string path = astoriaUrl.AbsolutePath; - string nativeUrl = null; - Element[] elements = null; - if (!UrlUtility.ParseAstoriaUrl(path, out elements)) - { - // Astoria Parse Failed, we return the same Url - return astoriaUrl; - } - - List parts = new List(); - foreach (Element element in elements) - { - if (!string.IsNullOrEmpty(element.Name)) - parts.Add(element.Name); - - if (!string.IsNullOrEmpty(element.Id)) - { - string elementId = element.Id.Trim(RuntimeConstants.Separators.Quote); - - if (elementId.StartsWith(RuntimeConstants.Schemes.UuidScheme, StringComparison.Ordinal)) - { - elementId = elementId.Substring(RuntimeConstants.Schemes.UuidScheme.Length); - } - parts.Add(elementId); - } - } - - string firstPart = parts[0]; - parts.RemoveAt(0); - nativeUrl = UrlUtility.ConcatenateUrlsString(firstPart, parts.ToArray()); - - Uri nativeUri = null; - if (baseUri != null) - nativeUri = new Uri(baseUri, nativeUrl); - else - nativeUri = new Uri(nativeUrl, UriKind.Relative); - - if (!string.IsNullOrEmpty(query)) - UrlUtility.SetQuery(nativeUri, query); - - return nativeUri; - } - - private static bool ParseAstoriaUrl(string astoriaUrl, out Element[] urlElements) - { - urlElements = null; - - if (astoriaUrl == null) - return false; - - string[] segments = UrlUtility.SplitAndRemoveEmptyEntries(astoriaUrl, RuntimeConstants.Separators.Url); - if ((segments == null) || (segments.Length < 1)) - return false; // InValid Url - - List elements = new List(); - foreach (string segment in segments) - { - string name; - string id; - if (!UrlUtility.ParseAstoriaUrlPart(segment, out name, out id)) - return false; // InValid Url - - elements.Add(new Element(name, id)); - } - - urlElements = elements.ToArray(); - return true; - } - - private static bool ParseAstoriaUrlPart(string urlPart, out string name, out string id) - { - name = null; - id = null; - - int parameterStart = urlPart.IndexOf(RuntimeConstants.Separators.Parenthesis[0]); - int parameterEnd = urlPart.IndexOf(RuntimeConstants.Separators.Parenthesis[1]); - - if (parameterStart == -1) - { - if (parameterEnd != -1) - return false; - - name = urlPart; - } - else - { - if (parameterEnd == -1 || parameterEnd != urlPart.Length - 1) - return false; - - name = urlPart.Substring(0, parameterStart); - id = urlPart.Substring(parameterStart, parameterEnd - parameterStart).Trim(RuntimeConstants.Separators.Parenthesis); - } - - return true; - } - - private class Element - { - public Element() { } - public Element(string name, string id) - { - this.Name = name; - this.Id = id; - } - - public string Name { get; set; } - public string Id { get; set; } - } - #endregion - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Net; + using System.Net.NetworkInformation; + using System.Text; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.Collections; + + internal static class UrlUtility + { + internal static string ConcatenateUrlsString(string baseUrl, params string[] relativeParts) + { + StringBuilder urlStringBuilder = new StringBuilder(RemoveTrailingSlash(baseUrl)); + foreach (string urlPart in relativeParts) + { + urlStringBuilder.Append(RuntimeConstants.Separators.Url[0]); + urlStringBuilder.Append(RemoveLeadingSlash(urlPart)); + } + return urlStringBuilder.ToString(); + } + + internal static string ConcatenateUrlsString(string baseUrl, string relativePart) + { + return AddTrailingSlash(baseUrl) + RemoveLeadingSlash(relativePart); + } + + internal static string ConcatenateUrlsString(Uri baseUrl, string relativePart) + { + return UrlUtility.ConcatenateUrlsString(GetLeftPartOfPath(baseUrl), relativePart); + } + + internal static void ExtractTargetInfo(Uri uri, out string tenantId, out string applicationName, out string serviceId, out string partitionKey, out string replicaId) + { + if (uri.Segments == null || uri.Segments.Length < 9) + { + // uri could contains more segments (e.g. replicas etc), hence + // for the purpose of this call, it is safe to relax from != 9 to < 9 + DefaultTrace.TraceError("Uri {0} is invalid", uri); + throw new ArgumentException("uri"); + } + + //net.tcp: (or) http://cluster.docdb.cloudapp.net:[Port]/apps//services/databases0/partitions//replicas/ + tenantId = ExtractTenantIdFromUri(uri); + applicationName = uri.Segments[2].Substring(0, uri.Segments[2].Length - 1); + serviceId = uri.Segments[4].Substring(0, uri.Segments[4].Length - 1); + partitionKey = uri.Segments[6].Substring(0, uri.Segments[6].Length - 1); //Not PartitionId. + replicaId = uri.Segments[8].Substring(0, uri.Segments[8].Length); + } + + internal static string ConcatenateUrlsString(Uri baseUrl, Uri relativePart) + { + if (relativePart.IsAbsoluteUri) + return relativePart.ToString(); + + return ConcatenateUrlsString(GetLeftPartOfPath(baseUrl), relativePart.OriginalString); + } + + internal static Uri ConcatenateUrls(string baseUrl, string relativePart) + { + return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); + } + + internal static Uri ConcatenateUrls(Uri baseUrl, string relativePart) + { + return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); + } + + internal static Uri ConcatenateUrls(Uri baseUrl, Uri relativePart) + { + if (relativePart.IsAbsoluteUri) + return relativePart; + + return new Uri(ConcatenateUrlsString(baseUrl, relativePart)); + } + + internal static NameValueCollection ParseQuery(string queryString) + { + NameValueCollection result = null; + + queryString = UrlUtility.RemoveLeadingQuestionMark(queryString); + if (string.IsNullOrEmpty(queryString)) + result = new NameValueCollection(0); + else + { + string[] queries = SplitAndRemoveEmptyEntries(queryString, new char[] { RuntimeConstants.Separators.Query[1] }); + result = new NameValueCollection(queries.Length); + for (int index = 0; index < queries.Length; ++index) + { + string[] nameValue = SplitAndRemoveEmptyEntries(queries[index], new char[] { RuntimeConstants.Separators.Query[2] }, 2); + result.Add(nameValue[0], nameValue.Length > 1 ? nameValue[1] : null); + } + } + + return result; + } + + internal static string CreateQuery(INameValueCollection parsedQuery) + { + if (parsedQuery == null) + return string.Empty; + + StringBuilder queryString = new StringBuilder(); + + int count = parsedQuery.Count(); + foreach (string key in parsedQuery) + { + string value = parsedQuery[key]; + if (!string.IsNullOrEmpty(key)) + { + if (queryString.Length > 0) + queryString.Append(RuntimeConstants.Separators.Query[1]); + + queryString.Append(key); + + if (value != null) + { + queryString.Append(RuntimeConstants.Separators.Query[2]); + queryString.Append(value); + } + } + } + + return queryString.ToString(); + } + + internal static Uri SetQuery(Uri url, string query) + { + if (url == null) throw new ArgumentNullException("url"); + + string urlSansQuery; + UriKind resultKind; + if (url.IsAbsoluteUri) + { + urlSansQuery = url.GetComponents(UriComponents.AbsoluteUri & (~UriComponents.Query) & (~UriComponents.Fragment), UriFormat.Unescaped); + resultKind = UriKind.Absolute; + } + else + { + resultKind = UriKind.Relative; + urlSansQuery = url.ToString(); + int lastQuestionMarkIndex = urlSansQuery.LastIndexOf(RuntimeConstants.Separators.Query[0]); + if (lastQuestionMarkIndex >= 0) + urlSansQuery = urlSansQuery.Remove(lastQuestionMarkIndex, urlSansQuery.Length - lastQuestionMarkIndex); + } + + query = UrlUtility.RemoveLeadingQuestionMark(query); + if (!string.IsNullOrEmpty(query)) + return new Uri(UrlUtility.AddTrailingSlash(urlSansQuery) + RuntimeConstants.Separators.Query[0] + query, resultKind); + else + return new Uri(UrlUtility.AddTrailingSlash(urlSansQuery), resultKind); + } + + internal static string RemoveLeadingQuestionMark(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + if (path[0] == RuntimeConstants.Separators.Query[0]) + return path.Remove(0, 1); + + return path; + } + + internal static string RemoveTrailingSlash(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + int length = path.Length; + if (path[length - 1] == RuntimeConstants.Separators.Url[0]) + return path.Remove(length - 1, 1); + + return path; + } + internal static StringSegment RemoveTrailingSlashes(StringSegment path) + { + if (path.IsNullOrEmpty()) + return path; + + return path.TrimEnd(RuntimeConstants.Separators.Url); + } + + internal static string RemoveTrailingSlashes(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + return path.TrimEnd(RuntimeConstants.Separators.Url); + } + + internal static StringSegment RemoveLeadingSlashes(StringSegment path) + { + if (path.IsNullOrEmpty()) + return path; + + return path.TrimStart(RuntimeConstants.Separators.Url); + } + + internal static string RemoveLeadingSlash(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + if (path[0] == RuntimeConstants.Separators.Url[0]) + return path.Remove(0, 1); + + return path; + } + + internal static string RemoveLeadingSlashes(string path) + { + if (string.IsNullOrEmpty(path)) + return path; + + return path.TrimStart(RuntimeConstants.Separators.Url); + } + + internal static string AddTrailingSlash(string path) + { + if (string.IsNullOrEmpty(path)) + path = new string(RuntimeConstants.Separators.Url); + else if (path[path.Length - 1] != RuntimeConstants.Separators.Url[0]) + path = path + RuntimeConstants.Separators.Url[0]; + + return path; + } + + internal static string AddLeadingSlash(string path) + { + if (string.IsNullOrEmpty(path)) + path = new string(RuntimeConstants.Separators.Url); + else if (path[0] != RuntimeConstants.Separators.Url[0]) + path = RuntimeConstants.Separators.Url[0] + path; + + return path; + } + + internal static string GetLeftPartOfAuthority(Uri uri) + { + return uri.GetLeftPart(UriPartial.Authority); + } + + internal static string GetLeftPartOfPath(Uri uri) + { + return uri.GetLeftPart(UriPartial.Path); + } + + public static string[] SplitAndRemoveEmptyEntries(string str, char[] seperators) + { + return SplitAndRemoveEmptyEntries(str, seperators, int.MaxValue); + } + + public static string[] SplitAndRemoveEmptyEntries(string str, char[] seperators, int count) + { + return str.Split(seperators, count, StringSplitOptions.RemoveEmptyEntries); + } + + //ID Segment Parsing Helper. + internal static string ExtractIdFromItemUri(Uri uri, int i) + { + string id = uri.Segments[i]; + return UrlUtility.RemoveTrailingSlash(id); + } + + // Extract the tenant id from the dns name + // All our supported domain names are have more then one dns zone so they we only need accept names with at least one zone in them + // ie, we do not have to supoprt http://localhost/ as a value uri with tenant information but we will for ease of use + // Also support http://hostname/accounts/{id}/operation/... + internal static string ExtractTenantIdFromUri(Uri uri) + { + if (UrlUtility.IsAccountsPathSegmentPartOfFirstItem(uri)) + { + return UrlUtility.ExtractIdFromItemUri(uri, 2); + } + + return UrlUtility.ExtractTenantIdFromUriIgnoreAccountsPattern(uri); + } + + // Extract the tenant id from the dns name + // Support for extract federationname from the format http://federationname.documents.azure.com/accounts/{id}/operation/... + internal static string ExtractTenantIdFromUriIgnoreAccountsPattern(Uri uri) + { + string hostName = uri.DnsSafeHost; + int firstPeriod = hostName.IndexOf('.'); + + if (firstPeriod != -1) + { + return hostName.Substring(0, firstPeriod); + } + else + { + return hostName; + } + } + + internal static string ExtractIdOrFullNameFromUri(string path, out bool isNameBased) + { + bool isFeed; + string resourceIdOrFullName; + string resourcePath; + if (PathsHelper.TryParsePathSegments(path, out isFeed, out resourcePath, out resourceIdOrFullName, out isNameBased)) + { + return resourceIdOrFullName; + } + + return null; + } + + internal static string ExtractIdFromItemUri(Uri uri) + { + string id = uri.Segments[uri.Segments.Length - 1]; + return UrlUtility.RemoveTrailingSlash(id); + } + + internal static string ExtractIdFromCollectionUri(Uri uri) + { + string ownerId = uri.Segments[uri.Segments.Length - 2]; + return UrlUtility.RemoveTrailingSlash(ownerId); + } + + internal static string ExtractItemIdAndCollectionIdFromUri(Uri uri, out string collectionId) + { + collectionId = UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 3]); + return UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 1]); + } + + internal static string ExtractFileNameFromUri(Uri uri) + { + return UrlUtility.RemoveTrailingSlash(uri.Segments[uri.Segments.Length - 1]); + } + + // expected uri http (or) tcp://:/ + internal static bool IsLocalHostUri(Uri uri) + { + IPAddress ipAddress; + if (!IPAddress.TryParse(uri.DnsSafeHost, out ipAddress)) + { + throw new ArgumentException("uri"); + } + + if (IPAddress.IsLoopback(ipAddress)) + { + return true; + } + + List Addresses = new List(); + NetworkInterface[] adapters = NetworkInterface.GetAllNetworkInterfaces(); + foreach (NetworkInterface adapter in adapters) + { + IPInterfaceProperties properties = adapter.GetIPProperties(); + foreach (IPAddressInformation localIpInfo in properties.UnicastAddresses) + { + if (localIpInfo.Address.Equals(ipAddress)) + { + return true; + } + } + } + + return false; + } + + // Parsing urls like http://hostname/accounts/{id}/operation/... + private static bool IsAccountsPathSegmentPartOfFirstItem(Uri uri) + { + if (uri.Segments.Length < 3) + { + return false; + } + + string firstPart = UrlUtility.ExtractIdFromItemUri(uri, 1); + return string.Equals(firstPart, Paths.AccountsPathSegment, StringComparison.Ordinal); + } + + #region Astoria Url Parsing functions + internal static bool IsAstoriaUrl(Uri url) + { + return (url.AbsolutePath.IndexOf(RuntimeConstants.Separators.Parenthesis[0]) != -1 && url.AbsolutePath.IndexOf(RuntimeConstants.Separators.Parenthesis[1]) != -1); + } + + internal static Uri ToNativeUrl(Uri astoriaUrl) + { + Uri baseUri = null; + + if (astoriaUrl.IsAbsoluteUri) + baseUri = new Uri(UrlUtility.GetLeftPartOfAuthority(astoriaUrl)); + + string query = astoriaUrl.Query; + string path = astoriaUrl.AbsolutePath; + string nativeUrl = null; + Element[] elements = null; + if (!UrlUtility.ParseAstoriaUrl(path, out elements)) + { + // Astoria Parse Failed, we return the same Url + return astoriaUrl; + } + + List parts = new List(); + foreach (Element element in elements) + { + if (!string.IsNullOrEmpty(element.Name)) + parts.Add(element.Name); + + if (!string.IsNullOrEmpty(element.Id)) + { + string elementId = element.Id.Trim(RuntimeConstants.Separators.Quote); + + if (elementId.StartsWith(RuntimeConstants.Schemes.UuidScheme, StringComparison.Ordinal)) + { + elementId = elementId.Substring(RuntimeConstants.Schemes.UuidScheme.Length); + } + parts.Add(elementId); + } + } + + string firstPart = parts[0]; + parts.RemoveAt(0); + nativeUrl = UrlUtility.ConcatenateUrlsString(firstPart, parts.ToArray()); + + Uri nativeUri = null; + if (baseUri != null) + nativeUri = new Uri(baseUri, nativeUrl); + else + nativeUri = new Uri(nativeUrl, UriKind.Relative); + + if (!string.IsNullOrEmpty(query)) + UrlUtility.SetQuery(nativeUri, query); + + return nativeUri; + } + + private static bool ParseAstoriaUrl(string astoriaUrl, out Element[] urlElements) + { + urlElements = null; + + if (astoriaUrl == null) + return false; + + string[] segments = UrlUtility.SplitAndRemoveEmptyEntries(astoriaUrl, RuntimeConstants.Separators.Url); + if ((segments == null) || (segments.Length < 1)) + return false; // InValid Url + + List elements = new List(); + foreach (string segment in segments) + { + string name; + string id; + if (!UrlUtility.ParseAstoriaUrlPart(segment, out name, out id)) + return false; // InValid Url + + elements.Add(new Element(name, id)); + } + + urlElements = elements.ToArray(); + return true; + } + + private static bool ParseAstoriaUrlPart(string urlPart, out string name, out string id) + { + name = null; + id = null; + + int parameterStart = urlPart.IndexOf(RuntimeConstants.Separators.Parenthesis[0]); + int parameterEnd = urlPart.IndexOf(RuntimeConstants.Separators.Parenthesis[1]); + + if (parameterStart == -1) + { + if (parameterEnd != -1) + return false; + + name = urlPart; + } + else + { + if (parameterEnd == -1 || parameterEnd != urlPart.Length - 1) + return false; + + name = urlPart.Substring(0, parameterStart); + id = urlPart.Substring(parameterStart, parameterEnd - parameterStart).Trim(RuntimeConstants.Separators.Parenthesis); + } + + return true; + } + + private class Element + { + public Element() { } + public Element(string name, string id) + { + this.Name = name; + this.Id = id; + } + + public string Name { get; set; } + public string Id { get; set; } + } + #endregion + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/User.cs b/Microsoft.Azure.Cosmos/src/direct/User.cs index 042c164548..5ef6d515a3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/User.cs +++ b/Microsoft.Azure.Cosmos/src/direct/User.cs @@ -1,38 +1,38 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - /// - /// Represents a user in the Azure Cosmos DB service. - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class User : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public User() - { - - } - - /// - /// Gets the self-link of the permissions associated with the user for the Azure Cosmos DB service. - /// - /// The self-link of the permissions associated with the user. - - public string PermissionsLink - { - get - { - return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.PermissionsLink); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Represents a user in the Azure Cosmos DB service. + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class User : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public User() + { + + } + + /// + /// Gets the self-link of the permissions associated with the user for the Azure Cosmos DB service. + /// + /// The self-link of the permissions associated with the user. + + public string PermissionsLink + { + get + { + return this.SelfLink.TrimEnd('/') + "/" + base.GetValue(Constants.Properties.PermissionsLink); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UserAgentContainer.cs b/Microsoft.Azure.Cosmos/src/direct/UserAgentContainer.cs index ac2c4f84b6..4b03dc8ddd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UserAgentContainer.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UserAgentContainer.cs @@ -1,78 +1,78 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System.Text; - - internal class UserAgentContainer - { - private static readonly string baseUserAgent; - private string userAgent; - private byte[] userAgentUTF8; - private string suffix; - private const int maxSuffixLength = 64; - - static UserAgentContainer() - { - UserAgentContainer.baseUserAgent = CustomTypeExtensions.GenerateBaseUserAgentString(); - } - - public UserAgentContainer() - { - this.userAgent = this.BaseUserAgent; - this.userAgentUTF8 = Encoding.UTF8.GetBytes(this.BaseUserAgent); - } - - public UserAgentContainer(string suffix) : this() - { - this.Suffix = suffix; - } - - public string UserAgent - { - get - { - return this.userAgent; - } - } - - public byte[] UserAgentUTF8 - { - get - { - return this.userAgentUTF8; - } - } - - public string Suffix - { - get - { - return this.suffix; - } - set - { - this.suffix = value; - - // Take only the first 64 characters of the user-agent. - if (this.suffix.Length > maxSuffixLength) - { - this.suffix = this.suffix.Substring(0, 64); - } - - this.userAgent = this.BaseUserAgent + suffix; - this.userAgentUTF8 = Encoding.UTF8.GetBytes(this.userAgent); - } - } - - internal virtual string BaseUserAgent - { - get - { - return UserAgentContainer.baseUserAgent; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System.Text; + + internal class UserAgentContainer + { + private static readonly string baseUserAgent; + private string userAgent; + private byte[] userAgentUTF8; + private string suffix; + private const int maxSuffixLength = 64; + + static UserAgentContainer() + { + UserAgentContainer.baseUserAgent = CustomTypeExtensions.GenerateBaseUserAgentString(); + } + + public UserAgentContainer() + { + this.userAgent = this.BaseUserAgent; + this.userAgentUTF8 = Encoding.UTF8.GetBytes(this.BaseUserAgent); + } + + public UserAgentContainer(string suffix) : this() + { + this.Suffix = suffix; + } + + public string UserAgent + { + get + { + return this.userAgent; + } + } + + public byte[] UserAgentUTF8 + { + get + { + return this.userAgentUTF8; + } + } + + public string Suffix + { + get + { + return this.suffix; + } + set + { + this.suffix = value; + + // Take only the first 64 characters of the user-agent. + if (this.suffix.Length > maxSuffixLength) + { + this.suffix = this.suffix.Substring(0, 64); + } + + this.userAgent = this.BaseUserAgent + suffix; + this.userAgentUTF8 = Encoding.UTF8.GetBytes(this.userAgent); + } + } + + internal virtual string BaseUserAgent + { + get + { + return UserAgentContainer.baseUserAgent; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/UserDefinedFunction.cs b/Microsoft.Azure.Cosmos/src/direct/UserDefinedFunction.cs index c0f024134b..8198054737 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UserDefinedFunction.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UserDefinedFunction.cs @@ -1,68 +1,68 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using Newtonsoft.Json; - - /// - /// Represents a user defined function in the Azure Cosmos DB service. - /// - /// - /// Azure Cosmos DB supports JavaScript user defined functions (UDFs) which are stored in the database and can be used inside queries. - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-sql-query/#javascript-integration for how to use UDFs within queries. - /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-programming/#udf for more details about implementing UDFs in JavaScript. - /// - /// - /// The following examples show how to register and use UDFs. - /// - /// (collectionLink, "SELECT VALUE udf.calculateTax(b.price) FROM books b"); - /// client.CreateDocumentQuery(collectionLink, new SqlQuerySpec("SELECT VALUE udf.calculateTax(b.price) FROM books b")); - /// client.CreateDocumentQuery(collectionLink).Select(b => UserDefinedFunctionProvider.Invoke("calculateTax", b.Price)); - /// - /// await client.CreateUserDefinedFunctionAsync(collectionLink, new UserDefinedFunction { Id = "toLowerCase", Body = @"function(s) { return s.ToLowerCase(); }" }); - /// client.CreateDocumentQuery(collectionLink, "SELECT * FROM books b WHERE b.toLowerCase = 'war and peace'"); - /// client.CreateDocumentQuery(collectionLink, new SqlQuerySpec( - /// "SELECT * FROM books b WHERE b.toLowerCase = @bookNameLowerCase", - /// new SqlParameterCollection(new SqlParameter[] {new SqlParameter { Name = "@bookNameLowerCase", Value = "War And Peace".ToLower() - /// }}))); - /// client.CreateDocumentQuery(collectionLink).Where(b => UserDefinedFunctionProvider.Invoke("toLowerCase", b.Title) == "war and peace"); - /// ]]> - /// - /// -#if COSMOSCLIENT - internal -#else - public -#endif - class UserDefinedFunction : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public UserDefinedFunction() - { - } - - /// - /// Gets or sets the body of the user defined function for the Azure Cosmos DB service. - /// - /// The body of the user defined function. - /// This must be a valid JavaScript function e.g. "function (input) { return input.toLowerCase(); }". - [JsonProperty(PropertyName = Constants.Properties.Body)] - public string Body - { - get - { - return base.GetValue(Constants.Properties.Body); - } - set - { - base.SetValue(Constants.Properties.Body, value); - } - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + /// + /// Represents a user defined function in the Azure Cosmos DB service. + /// + /// + /// Azure Cosmos DB supports JavaScript user defined functions (UDFs) which are stored in the database and can be used inside queries. + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-sql-query/#javascript-integration for how to use UDFs within queries. + /// Refer to http://azure.microsoft.com/documentation/articles/documentdb-programming/#udf for more details about implementing UDFs in JavaScript. + /// + /// + /// The following examples show how to register and use UDFs. + /// + /// (collectionLink, "SELECT VALUE udf.calculateTax(b.price) FROM books b"); + /// client.CreateDocumentQuery(collectionLink, new SqlQuerySpec("SELECT VALUE udf.calculateTax(b.price) FROM books b")); + /// client.CreateDocumentQuery(collectionLink).Select(b => UserDefinedFunctionProvider.Invoke("calculateTax", b.Price)); + /// + /// await client.CreateUserDefinedFunctionAsync(collectionLink, new UserDefinedFunction { Id = "toLowerCase", Body = @"function(s) { return s.ToLowerCase(); }" }); + /// client.CreateDocumentQuery(collectionLink, "SELECT * FROM books b WHERE b.toLowerCase = 'war and peace'"); + /// client.CreateDocumentQuery(collectionLink, new SqlQuerySpec( + /// "SELECT * FROM books b WHERE b.toLowerCase = @bookNameLowerCase", + /// new SqlParameterCollection(new SqlParameter[] {new SqlParameter { Name = "@bookNameLowerCase", Value = "War And Peace".ToLower() + /// }}))); + /// client.CreateDocumentQuery(collectionLink).Where(b => UserDefinedFunctionProvider.Invoke("toLowerCase", b.Title) == "war and peace"); + /// ]]> + /// + /// +#if COSMOSCLIENT + internal +#else + public +#endif + class UserDefinedFunction : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public UserDefinedFunction() + { + } + + /// + /// Gets or sets the body of the user defined function for the Azure Cosmos DB service. + /// + /// The body of the user defined function. + /// This must be a valid JavaScript function e.g. "function (input) { return input.toLowerCase(); }". + [JsonProperty(PropertyName = Constants.Properties.Body)] + public string Body + { + get + { + return base.GetValue(Constants.Properties.Body); + } + set + { + base.SetValue(Constants.Properties.Body, value); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UserDefinedType.cs b/Microsoft.Azure.Cosmos/src/direct/UserDefinedType.cs index 35772273ce..f9fab51a32 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UserDefinedType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UserDefinedType.cs @@ -1,19 +1,19 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - /// - /// Represents a user defined type in the Azure Cosmos DB service. - /// - internal sealed class UserDefinedType : Resource - { - /// - /// Initializes a new instance of the class for the Azure Cosmos DB service. - /// - public UserDefinedType() - { - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Represents a user defined type in the Azure Cosmos DB service. + /// + internal sealed class UserDefinedType : Resource + { + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public UserDefinedType() + { + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/UserPortPool.cs b/Microsoft.Azure.Cosmos/src/direct/UserPortPool.cs index c1dd5aca5f..37f6b6bd7e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/UserPortPool.cs +++ b/Microsoft.Azure.Cosmos/src/direct/UserPortPool.cs @@ -1,262 +1,262 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Globalization; - using System.Net.Sockets; - using Microsoft.Azure.Cosmos.Core.Trace; - - // User-mode implementation of a reusable port pool. - // This class is thread safe. - internal sealed class UserPortPool - { - private readonly int portReuseThreshold; - private readonly int candidatePortCount; - - private readonly Pool ipv4Pool = new Pool(); - private readonly Pool ipv6Pool = new Pool(); - - public UserPortPool(int portReuseThreshold, int candidatePortCount) - { - if (portReuseThreshold <= 0) - { - throw new ArgumentException("The port reuse threshold must be positive"); - } - if (candidatePortCount <= 0) - { - throw new ArgumentException("The candidate port count must be positive"); - } - if (candidatePortCount > portReuseThreshold) - { - throw new ArgumentException( - "The candidate port count must be less than or equal to the port reuse threshold"); - } - this.portReuseThreshold = portReuseThreshold; - this.candidatePortCount = candidatePortCount; - } - - public ushort[] GetCandidatePorts(AddressFamily addressFamily) - { - Pool pool = this.GetPool(addressFamily); - - lock (pool.mutex) - { - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - if (pool.usablePortCount < this.portReuseThreshold) - { - return null; - } - Debug.Assert(this.candidatePortCount <= pool.usablePortCount); - // This approach is O(n) (for a bounded, but non-trivial n). - // Replace with something faster if it's a problem. - return UserPortPool.GetRandomSample( - pool.ports, this.candidatePortCount, pool.rand); - } - } - - public void AddReference(AddressFamily addressFamily, ushort port) - { - Pool pool = this.GetPool(addressFamily); - - lock (pool.mutex) - { - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - PortState state = null; - if (pool.ports.TryGetValue(port, out state)) - { - state.referenceCount++; - } - else - { - state = new PortState(); - state.referenceCount++; - pool.ports.Add(port, state); - pool.usablePortCount++; - - DefaultTrace.TraceInformation("PrivatePortPool: Port is added to port pool: {0}", port); - } - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - } - } - - public void RemoveReference(AddressFamily addressFamily, ushort port) - { - Pool pool = this.GetPool(addressFamily); - - lock (pool.mutex) - { - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - - PortState state = null; - if (!pool.ports.TryGetValue(port, out state)) - { - Debug.Assert(false); - return; - } - Debug.Assert(state != null); - Debug.Assert(state.referenceCount > 0); - state.referenceCount--; - if (state.referenceCount == 0) - { - bool result = pool.ports.Remove(port); - Debug.Assert(result); - if (state.usable) - { - pool.usablePortCount--; - } - else - { - pool.unusablePortCount--; - } - - DefaultTrace.TraceInformation("PrivatePortPool: Port is removed from port pool: {0}", port); - } - - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - } - } - - public void MarkUnusable(AddressFamily addressFamily, ushort port) - { - Pool pool = this.GetPool(addressFamily); - - lock (pool.mutex) - { - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - - PortState state = null; - if (!pool.ports.TryGetValue(port, out state)) { - return; - } - - Debug.Assert(state != null); - state.usable = false; - pool.usablePortCount--; - pool.unusablePortCount++; - - DefaultTrace.TraceInformation("PrivatePortPool: Port is marked as unusable: {0}", port); - Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); - } - } - - public string DumpStatus() - { - return string.Format("portReuseThreshold:{0};candidatePortCount:{1};ipv4Pool:{2};ipv6Pool:{3}", - this.portReuseThreshold, - this.candidatePortCount, - this.DumpPoolStatus(this.ipv4Pool), - this.DumpPoolStatus(this.ipv6Pool)); - } - - private string DumpPoolStatus(Pool pool) - { - lock (pool.mutex) - { - return string.Format("{0} totalPorts.{1} usablePorts.", pool.ports.Count, pool.usablePortCount); - } - } - - private Pool GetPool(AddressFamily af) - { - switch (af) - { - case AddressFamily.InterNetwork: - return this.ipv4Pool; - - case AddressFamily.InterNetworkV6: - return this.ipv6Pool; - - default: - throw new NotSupportedException( - string.Format( - CultureInfo.InvariantCulture, - "Address family {0} not supported", af)); - } - } - - private static ushort[] GetRandomSample( - Dictionary pool, - int candidatePortCount, Random rng) - { - ushort[] sample = UserPortPool.ReservoirSample(pool, candidatePortCount, rng); - Debug.Assert(sample != null); - Debug.Assert(sample.Length == candidatePortCount); - UserPortPool.Shuffle(rng, sample); - return sample; - } - - private static ushort[] ReservoirSample(Dictionary pool, int candidatePortCount, Random rng) - { - IEnumerable keys = pool.Keys; - ushort[] sample = new ushort[candidatePortCount]; - int i = 0; - int j = 0; - foreach (ushort port in keys) - { - if (!pool[port].usable) - { - // Continue without incrementing i and j. - continue; - } - if (j < sample.Length) - { - sample[j] = port; - j++; - } - else - { - int k = rng.Next(i + 1); - if (k < sample.Length) - { - sample[k] = port; - } - } - i++; - } -#if DEBUG - Debug.Assert(j == sample.Length); - foreach (ushort p in sample) - { - Debug.Assert(p != 0); - } -#endif // DEBUG - return sample; - } - - private static void Shuffle(Random rng, ushort[] sample) - { - // Fisher-Yates shuffle (aka Knuth shuffle). - // For each i from i-1 down to 1, pick a random integer j such that - // 0 <= j <= i; exchange sample[i] and sample[j]. - // This is necessary because ports are tried in the order returned. - for (int i = sample.Length - 1; i > 0; i--) - { - int j = rng.Next(i + 1); - ushort temp = sample[j]; - sample[j] = sample[i]; - sample[i] = temp; - } - } - - private sealed class Pool - { - public readonly object mutex = new object(); - // All fields are guarded by mutex. - public readonly Dictionary ports = - new Dictionary(192); - public readonly Random rand = new Random(); - // usablePortCount + unusablePortCount = ports.Count - public int usablePortCount = 0; - public int unusablePortCount = 0; - } - - private sealed class PortState { - public int referenceCount = 0; - public bool usable = true; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Net.Sockets; + using Microsoft.Azure.Cosmos.Core.Trace; + + // User-mode implementation of a reusable port pool. + // This class is thread safe. + internal sealed class UserPortPool + { + private readonly int portReuseThreshold; + private readonly int candidatePortCount; + + private readonly Pool ipv4Pool = new Pool(); + private readonly Pool ipv6Pool = new Pool(); + + public UserPortPool(int portReuseThreshold, int candidatePortCount) + { + if (portReuseThreshold <= 0) + { + throw new ArgumentException("The port reuse threshold must be positive"); + } + if (candidatePortCount <= 0) + { + throw new ArgumentException("The candidate port count must be positive"); + } + if (candidatePortCount > portReuseThreshold) + { + throw new ArgumentException( + "The candidate port count must be less than or equal to the port reuse threshold"); + } + this.portReuseThreshold = portReuseThreshold; + this.candidatePortCount = candidatePortCount; + } + + public ushort[] GetCandidatePorts(AddressFamily addressFamily) + { + Pool pool = this.GetPool(addressFamily); + + lock (pool.mutex) + { + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + if (pool.usablePortCount < this.portReuseThreshold) + { + return null; + } + Debug.Assert(this.candidatePortCount <= pool.usablePortCount); + // This approach is O(n) (for a bounded, but non-trivial n). + // Replace with something faster if it's a problem. + return UserPortPool.GetRandomSample( + pool.ports, this.candidatePortCount, pool.rand); + } + } + + public void AddReference(AddressFamily addressFamily, ushort port) + { + Pool pool = this.GetPool(addressFamily); + + lock (pool.mutex) + { + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + PortState state = null; + if (pool.ports.TryGetValue(port, out state)) + { + state.referenceCount++; + } + else + { + state = new PortState(); + state.referenceCount++; + pool.ports.Add(port, state); + pool.usablePortCount++; + + DefaultTrace.TraceInformation("PrivatePortPool: Port is added to port pool: {0}", port); + } + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + } + } + + public void RemoveReference(AddressFamily addressFamily, ushort port) + { + Pool pool = this.GetPool(addressFamily); + + lock (pool.mutex) + { + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + + PortState state = null; + if (!pool.ports.TryGetValue(port, out state)) + { + Debug.Assert(false); + return; + } + Debug.Assert(state != null); + Debug.Assert(state.referenceCount > 0); + state.referenceCount--; + if (state.referenceCount == 0) + { + bool result = pool.ports.Remove(port); + Debug.Assert(result); + if (state.usable) + { + pool.usablePortCount--; + } + else + { + pool.unusablePortCount--; + } + + DefaultTrace.TraceInformation("PrivatePortPool: Port is removed from port pool: {0}", port); + } + + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + } + } + + public void MarkUnusable(AddressFamily addressFamily, ushort port) + { + Pool pool = this.GetPool(addressFamily); + + lock (pool.mutex) + { + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + + PortState state = null; + if (!pool.ports.TryGetValue(port, out state)) { + return; + } + + Debug.Assert(state != null); + state.usable = false; + pool.usablePortCount--; + pool.unusablePortCount++; + + DefaultTrace.TraceInformation("PrivatePortPool: Port is marked as unusable: {0}", port); + Debug.Assert(pool.usablePortCount + pool.unusablePortCount == pool.ports.Count); + } + } + + public string DumpStatus() + { + return string.Format("portReuseThreshold:{0};candidatePortCount:{1};ipv4Pool:{2};ipv6Pool:{3}", + this.portReuseThreshold, + this.candidatePortCount, + this.DumpPoolStatus(this.ipv4Pool), + this.DumpPoolStatus(this.ipv6Pool)); + } + + private string DumpPoolStatus(Pool pool) + { + lock (pool.mutex) + { + return string.Format("{0} totalPorts.{1} usablePorts.", pool.ports.Count, pool.usablePortCount); + } + } + + private Pool GetPool(AddressFamily af) + { + switch (af) + { + case AddressFamily.InterNetwork: + return this.ipv4Pool; + + case AddressFamily.InterNetworkV6: + return this.ipv6Pool; + + default: + throw new NotSupportedException( + string.Format( + CultureInfo.InvariantCulture, + "Address family {0} not supported", af)); + } + } + + private static ushort[] GetRandomSample( + Dictionary pool, + int candidatePortCount, Random rng) + { + ushort[] sample = UserPortPool.ReservoirSample(pool, candidatePortCount, rng); + Debug.Assert(sample != null); + Debug.Assert(sample.Length == candidatePortCount); + UserPortPool.Shuffle(rng, sample); + return sample; + } + + private static ushort[] ReservoirSample(Dictionary pool, int candidatePortCount, Random rng) + { + IEnumerable keys = pool.Keys; + ushort[] sample = new ushort[candidatePortCount]; + int i = 0; + int j = 0; + foreach (ushort port in keys) + { + if (!pool[port].usable) + { + // Continue without incrementing i and j. + continue; + } + if (j < sample.Length) + { + sample[j] = port; + j++; + } + else + { + int k = rng.Next(i + 1); + if (k < sample.Length) + { + sample[k] = port; + } + } + i++; + } +#if DEBUG + Debug.Assert(j == sample.Length); + foreach (ushort p in sample) + { + Debug.Assert(p != 0); + } +#endif // DEBUG + return sample; + } + + private static void Shuffle(Random rng, ushort[] sample) + { + // Fisher-Yates shuffle (aka Knuth shuffle). + // For each i from i-1 down to 1, pick a random integer j such that + // 0 <= j <= i; exchange sample[i] and sample[j]. + // This is necessary because ports are tried in the order returned. + for (int i = sample.Length - 1; i > 0; i--) + { + int j = rng.Next(i + 1); + ushort temp = sample[j]; + sample[j] = sample[i]; + sample[i] = temp; + } + } + + private sealed class Pool + { + public readonly object mutex = new object(); + // All fields are guarded by mutex. + public readonly Dictionary ports = + new Dictionary(192); + public readonly Random rand = new Random(); + // usablePortCount + unusablePortCount = ports.Count + public int usablePortCount = 0; + public int unusablePortCount = 0; + } + + private sealed class PortState { + public int referenceCount = 0; + public bool usable = true; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs b/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs index 852456c5e3..b76147fb33 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs @@ -1,175 +1,175 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Diagnostics; - - /// - /// ValueType equivalent of . - /// - /// Used to avoid allocating when we need stopwatch-y functionality. - /// - /// Deviates from in one semi-significant ways: - /// - rapidly calling Start() and then Stop() rapidly (allowing less than 1 tick to elapse) is going to drift - /// * this is weird thing to do, don't do it - /// - /// - internal struct ValueStopwatch - { - private static readonly double ToTimeSpanTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency; - private static readonly double ToMilliseconds = 1_000 / (double)Stopwatch.Frequency; - - /// - public static readonly long Frequency = Stopwatch.Frequency; - /// - public static readonly bool IsHighResolution = Stopwatch.IsHighResolution; - - /// - /// We pack everything into a single long, so using this doesn't inflate any objects with it as a field. - /// - /// State is interpreted as follows - /// - state == 0 - /// * IsRunning == false - /// * We have never started - /// - state > 0 - /// * IsRunning == true - /// - state < 0 - /// * IsRunning == false - /// * We have been started and stopped - /// * ElapsedTicks == Math.Abs(state) - /// - /// We handle restarting the timer by backdating our start - /// to account for any existing duration. - /// - private long state; - - /// - public readonly bool IsRunning - => this.state > 0; - - /// - public readonly long ElapsedTicks - { - get - { - long stateCopy = this.state; - - if (stateCopy == 0) - { - // haven't started - return 0; - } - - if (stateCopy < 0) - { - // we are stopped, the duration is stored in the - // magnitude of state - return Math.Abs(stateCopy); - } - - long effectiveStop = Stopwatch.GetTimestamp(); - - long delta = effectiveStop - stateCopy; - - return delta; - } - } - - /// - public readonly long ElapsedMilliseconds - => (long)(this.ElapsedTicks * ValueStopwatch.ToMilliseconds); - - /// - public readonly TimeSpan Elapsed - { - get - { - long stopwatchTicks = this.ElapsedTicks; - long timeSpanTicks = (long)(stopwatchTicks * ValueStopwatch.ToTimeSpanTicks); - - return new TimeSpan(timeSpanTicks); - } - } - - /// - public void Reset() - { - this.state = 0; - } - - /// - public void Restart() - { - this.Reset(); - this.Start(); - } - - /// - public void Start() - { - long stateCopy = this.state; - if (stateCopy > 0) - { - // already started - return; - } - - long now = Stopwatch.GetTimestamp(); - - // if stateCopy == 0, we've never started so just store now - // if stateCopy < 0 then Abs(stateCopy) == duration of last run - // so (now + stateCopy) backdates now so duration is preserved - this.state = now + stateCopy; - } - - /// - public void Stop() - { - long stateCopy = this.state; - if (stateCopy <= 0) - { - // already stopped (or never started) - return; - } - - long effectiveStop = Stopwatch.GetTimestamp(); - - long delta = effectiveStop - stateCopy; - - // when measuring small periods - // delta can be < 0 due to bugs - // in BIOS or HAL - // - // force delta to be non-negative - // - // this mimics behavior in the BCL's - // Stopwatch class - delta = Math.Max(delta, 0); - - // if delta > 0 then some time has passed, - // and we'll store -delta which Elapsed - // will correctly deal with - // - // if delta == 0... then state == 0 which - // will look like a new, unstarted, stopwatch - // which ALSO has Elapsed == 0 and is fine - this.state = -delta; - } - - /// - public static long GetTimestamp() - => Stopwatch.GetTimestamp(); - - /// - public static ValueStopwatch StartNew() - { - ValueStopwatch ret = default; - ret.Start(); - - return ret; - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Diagnostics; + + /// + /// ValueType equivalent of . + /// + /// Used to avoid allocating when we need stopwatch-y functionality. + /// + /// Deviates from in one semi-significant ways: + /// - rapidly calling Start() and then Stop() rapidly (allowing less than 1 tick to elapse) is going to drift + /// * this is weird thing to do, don't do it + /// + /// + internal struct ValueStopwatch + { + private static readonly double ToTimeSpanTicks = TimeSpan.TicksPerSecond / (double)Stopwatch.Frequency; + private static readonly double ToMilliseconds = 1_000 / (double)Stopwatch.Frequency; + + /// + public static readonly long Frequency = Stopwatch.Frequency; + /// + public static readonly bool IsHighResolution = Stopwatch.IsHighResolution; + + /// + /// We pack everything into a single long, so using this doesn't inflate any objects with it as a field. + /// + /// State is interpreted as follows + /// - state == 0 + /// * IsRunning == false + /// * We have never started + /// - state > 0 + /// * IsRunning == true + /// - state less than 0 + /// * IsRunning == false + /// * We have been started and stopped + /// * ElapsedTicks == Math.Abs(state) + /// + /// We handle restarting the timer by backdating our start + /// to account for any existing duration. + /// + private long state; + + /// + public readonly bool IsRunning + => this.state > 0; + + /// + public readonly long ElapsedTicks + { + get + { + long stateCopy = this.state; + + if (stateCopy == 0) + { + // haven't started + return 0; + } + + if (stateCopy < 0) + { + // we are stopped, the duration is stored in the + // magnitude of state + return Math.Abs(stateCopy); + } + + long effectiveStop = Stopwatch.GetTimestamp(); + + long delta = effectiveStop - stateCopy; + + return delta; + } + } + + /// + public readonly long ElapsedMilliseconds + => (long)(this.ElapsedTicks * ValueStopwatch.ToMilliseconds); + + /// + public readonly TimeSpan Elapsed + { + get + { + long stopwatchTicks = this.ElapsedTicks; + long timeSpanTicks = (long)(stopwatchTicks * ValueStopwatch.ToTimeSpanTicks); + + return new TimeSpan(timeSpanTicks); + } + } + + /// + public void Reset() + { + this.state = 0; + } + + /// + public void Restart() + { + this.Reset(); + this.Start(); + } + + /// + public void Start() + { + long stateCopy = this.state; + if (stateCopy > 0) + { + // already started + return; + } + + long now = Stopwatch.GetTimestamp(); + + // if stateCopy == 0, we've never started so just store now + // if stateCopy < 0 then Abs(stateCopy) == duration of last run + // so (now + stateCopy) backdates now so duration is preserved + this.state = now + stateCopy; + } + + /// + public void Stop() + { + long stateCopy = this.state; + if (stateCopy <= 0) + { + // already stopped (or never started) + return; + } + + long effectiveStop = Stopwatch.GetTimestamp(); + + long delta = effectiveStop - stateCopy; + + // when measuring small periods + // delta can be < 0 due to bugs + // in BIOS or HAL + // + // force delta to be non-negative + // + // this mimics behavior in the BCL's + // Stopwatch class + delta = Math.Max(delta, 0); + + // if delta > 0 then some time has passed, + // and we'll store -delta which Elapsed + // will correctly deal with + // + // if delta == 0... then state == 0 which + // will look like a new, unstarted, stopwatch + // which ALSO has Elapsed == 0 and is fine + this.state = -delta; + } + + /// + public static long GetTimestamp() + => Stopwatch.GetTimestamp(); + + /// + public static ValueStopwatch StartNew() + { + ValueStopwatch ret = default; + ret.Start(); + + return ret; + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/VectorSessionToken.cs b/Microsoft.Azure.Cosmos/src/direct/VectorSessionToken.cs index 9de5873fa8..d94ec612bb 100644 --- a/Microsoft.Azure.Cosmos/src/direct/VectorSessionToken.cs +++ b/Microsoft.Azure.Cosmos/src/direct/VectorSessionToken.cs @@ -1,481 +1,481 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq; - using Microsoft.Azure.Cosmos.Core.Trace; - - /// - /// Models vector clock bases session token. Session token has the following format: - /// {Version}#{GlobalLSN}#{RegionId1}={LocalLsn1}#{RegionId2}={LocalLsn2}....#{RegionIdN}={LocalLsnN} - /// 'Version' captures the configuration number of the partition which returned this session token. - /// 'Version' is incremented everytime topology of the partition is updated (say due to Add/Remove/Failover). - /// - /// The choice of separators '#' and '=' is important. Separators ';' and ',' are used to delimit - /// per-partitionKeyRange session token - /// session - /// - /// We make assumption that instances of this class are immutable (read only after they are constructed), so if you want to change - /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. - /// - internal sealed class VectorSessionToken : ISessionToken - { - private static readonly IReadOnlyDictionary DefaultLocalLsnByRegion = new Dictionary(0); - private const char SegmentSeparator = '#'; - private const string SegmentSeparatorString = "#"; - private const char RegionProgressSeparator = '='; - private readonly string sessionToken; - private readonly long version; -#pragma warning disable IDE0032 // Use auto property - private readonly long globalLsn; -#pragma warning restore IDE0032 // Use auto property - private readonly IReadOnlyDictionary localLsnByRegion; - - private VectorSessionToken(long version, long globalLsn, IReadOnlyDictionary localLsnByRegion, string sessionToken = null) - { - this.version = version; - this.globalLsn = globalLsn; - this.localLsnByRegion = localLsnByRegion; - this.sessionToken = sessionToken; - - if (this.sessionToken == null) - { - string regionProgress = null; - if (localLsnByRegion.Any()) - { - regionProgress = string.Join( - VectorSessionToken.SegmentSeparatorString, - localLsnByRegion.Select(kvp => string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", kvp.Key, VectorSessionToken.RegionProgressSeparator, kvp.Value))); - } - - if (string.IsNullOrEmpty(regionProgress)) - { - this.sessionToken = string.Format( - CultureInfo.InvariantCulture, - "{0}{1}{2}", - this.version, - VectorSessionToken.SegmentSeparatorString, - this.globalLsn); - } - else - { - this.sessionToken = string.Format( - CultureInfo.InvariantCulture, - "{0}{1}{2}{3}{4}", - this.version, - VectorSessionToken.SegmentSeparatorString, - this.globalLsn, - VectorSessionToken.SegmentSeparatorString, - regionProgress); - } - } - } - - public VectorSessionToken(VectorSessionToken other, long globalLSN) - : this(other.version, globalLSN, other.localLsnByRegion) - { - } - - public static bool TryCreate(string sessionToken, out ISessionToken parsedSessionToken) - { - parsedSessionToken = null; - - if (VectorSessionToken.TryParseSessionToken( - sessionToken, - out long version, - out long globalLsn, - out IReadOnlyDictionary localLsnByRegion)) - { - parsedSessionToken = new VectorSessionToken(version, globalLsn, localLsnByRegion, sessionToken); - return true; - } - else - { - return false; - } - } - - public long LSN => this.globalLsn; - - public bool Equals(ISessionToken obj) - { - if (!(obj is VectorSessionToken other)) - { - return false; - } - - return this.version == other.version - && this.globalLsn == other.globalLsn - && this.AreRegionProgressEqual(other.localLsnByRegion); - } - - public bool IsValid(ISessionToken otherSessionToken) - { - if (!(otherSessionToken is VectorSessionToken other)) - { - throw new ArgumentNullException(nameof(otherSessionToken)); - } - - if (other.version < this.version || other.globalLsn < this.globalLsn) - { - return false; - } - - if (other.version == this.version && other.localLsnByRegion.Count != this.localLsnByRegion.Count) - { - throw new InternalServerErrorException( - string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); - } - - foreach (KeyValuePair kvp in other.localLsnByRegion) - { - uint regionId = kvp.Key; - long otherLocalLsn = kvp.Value; - long localLsn = -1; - - if (!this.localLsnByRegion.TryGetValue(regionId, out localLsn)) - { - // Region mismatch: other session token has progress for a region which is missing in this session token - // Region mismatch can be ignored only if this session token version is smaller than other session token version - if (this.version == other.version) - { - throw new InternalServerErrorException( - string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); - } - else - { - // ignore missing region as other session token version > this session token version - } - } - else - { - // region is present in both session tokens. - if (otherLocalLsn < localLsn) - { - return false; - } - } - } - - return true; - } - - // Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) - public ISessionToken Merge(ISessionToken obj) - { - if (!(obj is VectorSessionToken other)) - { - throw new ArgumentNullException(nameof(obj)); - } - - if (this.version == other.version && this.localLsnByRegion.Count != other.localLsnByRegion.Count) - { - throw new InternalServerErrorException( - string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); - } - - // If one of the existing tokens has the all the max values then - // just return it instead of creating a new one. - if (this.version >= other.version && - this.globalLsn > other.globalLsn) - { - if (VectorSessionToken.AreAllLocalLsnByRegionsGreaterThanOrEqual( - higherToken: this, - lowerToken: other)) - { - return this; - } - - } - else if (other.version >= this.version && - other.globalLsn >= this.globalLsn) - { - if (VectorSessionToken.AreAllLocalLsnByRegionsGreaterThanOrEqual( - higherToken: other, - lowerToken: this)) - { - return other; - } - } - - VectorSessionToken sessionTokenWithHigherVersion; - VectorSessionToken sessionTokenWithLowerVersion; - - if (this.version < other.version) - { - sessionTokenWithLowerVersion = this; - sessionTokenWithHigherVersion = other; - } - else - { - sessionTokenWithLowerVersion = other; - sessionTokenWithHigherVersion = this; - } - - // Create a new token with the highest values of both - Dictionary highestLocalLsnByRegion = new Dictionary(sessionTokenWithHigherVersion.localLsnByRegion.Count); - foreach (KeyValuePair kvp in sessionTokenWithHigherVersion.localLsnByRegion) - { - uint regionId = kvp.Key; - long localLsn1 = kvp.Value; - long localLsn2 = -1; - - if (sessionTokenWithLowerVersion.localLsnByRegion.TryGetValue(regionId, out localLsn2)) - { - highestLocalLsnByRegion[regionId] = Math.Max(localLsn1, localLsn2); - } - else if (this.version == other.version) - { - throw new InternalServerErrorException( - string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); - } - else - { - highestLocalLsnByRegion[regionId] = localLsn1; - } - } - - return new VectorSessionToken( - Math.Max(this.version, other.version), - Math.Max(this.globalLsn, other.globalLsn), - highestLocalLsnByRegion); - } - - string ISessionToken.ConvertToString() - { - return this.sessionToken; - } - - private bool AreRegionProgressEqual(IReadOnlyDictionary other) - { - if (this.localLsnByRegion.Count != other.Count) - { - return false; - } - - foreach (KeyValuePair kvp in this.localLsnByRegion) - { - uint regionId = kvp.Key; - long localLsn1 = kvp.Value; - if (other.TryGetValue(regionId, out long localLsn2)) - { - if (localLsn1 != localLsn2) - { - return false; - } - } - } - - return true; - } - - private static bool AreAllLocalLsnByRegionsGreaterThanOrEqual( - VectorSessionToken higherToken, - VectorSessionToken lowerToken) - { - if (higherToken.localLsnByRegion.Count != lowerToken.localLsnByRegion.Count) - { - return false; - } - - if (!higherToken.localLsnByRegion.Any()) - { - return true; - } - - foreach (KeyValuePair kvp in higherToken.localLsnByRegion) - { - uint higherRegionId = kvp.Key; - long higherLocalLsn = kvp.Value; - if (lowerToken.localLsnByRegion.TryGetValue(higherRegionId, out long lowerLocalLsn)) - { - if (lowerLocalLsn > higherLocalLsn) - { - return false; - } - } - else - { - // Both dictionaries have the same count so this means they both - // have a region that does not exist in the other. - return false; - } - } - - return true; - } - - private static bool TryParseSessionToken( - string sessionToken, - out long version, - out long globalLsn, - out IReadOnlyDictionary localLsnByRegion) - { - version = 0; - localLsnByRegion = null; - globalLsn = -1; - - if (string.IsNullOrEmpty(sessionToken)) - { - DefaultTrace.TraceWarning("Session token is empty"); - return false; - } - - int index = 0; - if (!TryParseLongSegment( - sessionToken, - ref index, - out version)) - { - DefaultTrace.TraceWarning($"Unexpected session token version number from token: {sessionToken} ."); - return false; - } - - // There is only 1 number in the session token. - // This represents a simple session token instead of a vector session token - if(index >= sessionToken.Length) - { - return false; - } - - if (!TryParseLongSegment( - sessionToken, - ref index, - out globalLsn)) - { - DefaultTrace.TraceWarning($"Unexpected session token global lsn from token: {sessionToken} ."); - return false; - } - - if (index >= sessionToken.Length) - { - localLsnByRegion = VectorSessionToken.DefaultLocalLsnByRegion; - return true; - } - - Dictionary lsnByRegion = new Dictionary(); - - while (index < sessionToken.Length) - { - if (!TryParseUintTillRegionProgressSeparator( - sessionToken, - ref index, - out uint regionId)) - { - DefaultTrace.TraceWarning($"Unexpected region progress segment in session token: {sessionToken}."); - return false; - } - - if (!TryParseLongSegment( - sessionToken, - ref index, - out long localLsn)) - { - DefaultTrace.TraceWarning($"Unexpected local lsn for region id {regionId.ToString(CultureInfo.InvariantCulture)} for segment in session token: {sessionToken}."); - return false; - } - - lsnByRegion[regionId] = localLsn; - } - - localLsnByRegion = lsnByRegion; - - return true; - } - - private static bool TryParseUintTillRegionProgressSeparator( - string input, - ref int index, - out uint value) - { - value = 0; - if (index >= input.Length) - { - return false; - } - - long longValue = 0; - while (index < input.Length) - { - char c = input[index]; - if (c >= '0' && c <= '9') - { - longValue = (longValue * 10) + (c - '0'); - index++; - } - else - { - if (c == VectorSessionToken.RegionProgressSeparator) - { - // Always increase index pass stop character - index++; - break; - } - - return false; - } - } - - if (longValue > uint.MaxValue || - longValue < 0) - { - return false; - } - - value = (uint)longValue; - return true; - } - - private static bool TryParseLongSegment( - string input, - ref int index, - out long value) - { - value = 0; - if (index >= input.Length) - { - return false; - } - - bool isNegative = false; - if (input[index] == '-') - { - index++; - isNegative = true; - } - - while (index < input.Length) - { - char c = input[index]; - if (c >= '0' && c <= '9') - { - value = (value * 10) + (c - '0'); - index++; - } - else - { - if (c == VectorSessionToken.SegmentSeparator) - { - // Always increase index pass stop character - index++; - break; - } - - return false; - } - } - - if (isNegative) - { - value *= -1; - } - - return true; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Linq; + using Microsoft.Azure.Cosmos.Core.Trace; + + /// + /// Models vector clock bases session token. Session token has the following format: + /// {Version}#{GlobalLSN}#{RegionId1}={LocalLsn1}#{RegionId2}={LocalLsn2}....#{RegionIdN}={LocalLsnN} + /// 'Version' captures the configuration number of the partition which returned this session token. + /// 'Version' is incremented everytime topology of the partition is updated (say due to Add/Remove/Failover). + /// + /// The choice of separators '#' and '=' is important. Separators ';' and ',' are used to delimit + /// per-partitionKeyRange session token + /// session + /// + /// We make assumption that instances of this class are immutable (read only after they are constructed), so if you want to change + /// this behaviour please review all of its uses and make sure that mutability doesn't break anything. + /// + internal sealed class VectorSessionToken : ISessionToken + { + private static readonly IReadOnlyDictionary DefaultLocalLsnByRegion = new Dictionary(0); + private const char SegmentSeparator = '#'; + private const string SegmentSeparatorString = "#"; + private const char RegionProgressSeparator = '='; + private readonly string sessionToken; + private readonly long version; +#pragma warning disable IDE0032 // Use auto property + private readonly long globalLsn; +#pragma warning restore IDE0032 // Use auto property + private readonly IReadOnlyDictionary localLsnByRegion; + + private VectorSessionToken(long version, long globalLsn, IReadOnlyDictionary localLsnByRegion, string sessionToken = null) + { + this.version = version; + this.globalLsn = globalLsn; + this.localLsnByRegion = localLsnByRegion; + this.sessionToken = sessionToken; + + if (this.sessionToken == null) + { + string regionProgress = null; + if (localLsnByRegion.Any()) + { + regionProgress = string.Join( + VectorSessionToken.SegmentSeparatorString, + localLsnByRegion.Select(kvp => string.Format(CultureInfo.InvariantCulture, "{0}{1}{2}", kvp.Key, VectorSessionToken.RegionProgressSeparator, kvp.Value))); + } + + if (string.IsNullOrEmpty(regionProgress)) + { + this.sessionToken = string.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}", + this.version, + VectorSessionToken.SegmentSeparatorString, + this.globalLsn); + } + else + { + this.sessionToken = string.Format( + CultureInfo.InvariantCulture, + "{0}{1}{2}{3}{4}", + this.version, + VectorSessionToken.SegmentSeparatorString, + this.globalLsn, + VectorSessionToken.SegmentSeparatorString, + regionProgress); + } + } + } + + public VectorSessionToken(VectorSessionToken other, long globalLSN) + : this(other.version, globalLSN, other.localLsnByRegion) + { + } + + public static bool TryCreate(string sessionToken, out ISessionToken parsedSessionToken) + { + parsedSessionToken = null; + + if (VectorSessionToken.TryParseSessionToken( + sessionToken, + out long version, + out long globalLsn, + out IReadOnlyDictionary localLsnByRegion)) + { + parsedSessionToken = new VectorSessionToken(version, globalLsn, localLsnByRegion, sessionToken); + return true; + } + else + { + return false; + } + } + + public long LSN => this.globalLsn; + + public bool Equals(ISessionToken obj) + { + if (!(obj is VectorSessionToken other)) + { + return false; + } + + return this.version == other.version + && this.globalLsn == other.globalLsn + && this.AreRegionProgressEqual(other.localLsnByRegion); + } + + public bool IsValid(ISessionToken otherSessionToken) + { + if (!(otherSessionToken is VectorSessionToken other)) + { + throw new ArgumentNullException(nameof(otherSessionToken)); + } + + if (other.version < this.version || other.globalLsn < this.globalLsn) + { + return false; + } + + if (other.version == this.version && other.localLsnByRegion.Count != this.localLsnByRegion.Count) + { + throw new InternalServerErrorException( + string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); + } + + foreach (KeyValuePair kvp in other.localLsnByRegion) + { + uint regionId = kvp.Key; + long otherLocalLsn = kvp.Value; + long localLsn = -1; + + if (!this.localLsnByRegion.TryGetValue(regionId, out localLsn)) + { + // Region mismatch: other session token has progress for a region which is missing in this session token + // Region mismatch can be ignored only if this session token version is smaller than other session token version + if (this.version == other.version) + { + throw new InternalServerErrorException( + string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); + } + else + { + // ignore missing region as other session token version > this session token version + } + } + else + { + // region is present in both session tokens. + if (otherLocalLsn < localLsn) + { + return false; + } + } + } + + return true; + } + + // Merge is commutative operation, so a.Merge(b).Equals(b.Merge(a)) + public ISessionToken Merge(ISessionToken obj) + { + if (!(obj is VectorSessionToken other)) + { + throw new ArgumentNullException(nameof(obj)); + } + + if (this.version == other.version && this.localLsnByRegion.Count != other.localLsnByRegion.Count) + { + throw new InternalServerErrorException( + string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); + } + + // If one of the existing tokens has the all the max values then + // just return it instead of creating a new one. + if (this.version >= other.version && + this.globalLsn > other.globalLsn) + { + if (VectorSessionToken.AreAllLocalLsnByRegionsGreaterThanOrEqual( + higherToken: this, + lowerToken: other)) + { + return this; + } + + } + else if (other.version >= this.version && + other.globalLsn >= this.globalLsn) + { + if (VectorSessionToken.AreAllLocalLsnByRegionsGreaterThanOrEqual( + higherToken: other, + lowerToken: this)) + { + return other; + } + } + + VectorSessionToken sessionTokenWithHigherVersion; + VectorSessionToken sessionTokenWithLowerVersion; + + if (this.version < other.version) + { + sessionTokenWithLowerVersion = this; + sessionTokenWithHigherVersion = other; + } + else + { + sessionTokenWithLowerVersion = other; + sessionTokenWithHigherVersion = this; + } + + // Create a new token with the highest values of both + Dictionary highestLocalLsnByRegion = new Dictionary(sessionTokenWithHigherVersion.localLsnByRegion.Count); + foreach (KeyValuePair kvp in sessionTokenWithHigherVersion.localLsnByRegion) + { + uint regionId = kvp.Key; + long localLsn1 = kvp.Value; + long localLsn2 = -1; + + if (sessionTokenWithLowerVersion.localLsnByRegion.TryGetValue(regionId, out localLsn2)) + { + highestLocalLsnByRegion[regionId] = Math.Max(localLsn1, localLsn2); + } + else if (this.version == other.version) + { + throw new InternalServerErrorException( + string.Format(CultureInfo.InvariantCulture, RMResources.InvalidRegionsInSessionToken, this.sessionToken, other.sessionToken)); + } + else + { + highestLocalLsnByRegion[regionId] = localLsn1; + } + } + + return new VectorSessionToken( + Math.Max(this.version, other.version), + Math.Max(this.globalLsn, other.globalLsn), + highestLocalLsnByRegion); + } + + string ISessionToken.ConvertToString() + { + return this.sessionToken; + } + + private bool AreRegionProgressEqual(IReadOnlyDictionary other) + { + if (this.localLsnByRegion.Count != other.Count) + { + return false; + } + + foreach (KeyValuePair kvp in this.localLsnByRegion) + { + uint regionId = kvp.Key; + long localLsn1 = kvp.Value; + if (other.TryGetValue(regionId, out long localLsn2)) + { + if (localLsn1 != localLsn2) + { + return false; + } + } + } + + return true; + } + + private static bool AreAllLocalLsnByRegionsGreaterThanOrEqual( + VectorSessionToken higherToken, + VectorSessionToken lowerToken) + { + if (higherToken.localLsnByRegion.Count != lowerToken.localLsnByRegion.Count) + { + return false; + } + + if (!higherToken.localLsnByRegion.Any()) + { + return true; + } + + foreach (KeyValuePair kvp in higherToken.localLsnByRegion) + { + uint higherRegionId = kvp.Key; + long higherLocalLsn = kvp.Value; + if (lowerToken.localLsnByRegion.TryGetValue(higherRegionId, out long lowerLocalLsn)) + { + if (lowerLocalLsn > higherLocalLsn) + { + return false; + } + } + else + { + // Both dictionaries have the same count so this means they both + // have a region that does not exist in the other. + return false; + } + } + + return true; + } + + private static bool TryParseSessionToken( + string sessionToken, + out long version, + out long globalLsn, + out IReadOnlyDictionary localLsnByRegion) + { + version = 0; + localLsnByRegion = null; + globalLsn = -1; + + if (string.IsNullOrEmpty(sessionToken)) + { + DefaultTrace.TraceWarning("Session token is empty"); + return false; + } + + int index = 0; + if (!TryParseLongSegment( + sessionToken, + ref index, + out version)) + { + DefaultTrace.TraceWarning($"Unexpected session token version number from token: {sessionToken} ."); + return false; + } + + // There is only 1 number in the session token. + // This represents a simple session token instead of a vector session token + if(index >= sessionToken.Length) + { + return false; + } + + if (!TryParseLongSegment( + sessionToken, + ref index, + out globalLsn)) + { + DefaultTrace.TraceWarning($"Unexpected session token global lsn from token: {sessionToken} ."); + return false; + } + + if (index >= sessionToken.Length) + { + localLsnByRegion = VectorSessionToken.DefaultLocalLsnByRegion; + return true; + } + + Dictionary lsnByRegion = new Dictionary(); + + while (index < sessionToken.Length) + { + if (!TryParseUintTillRegionProgressSeparator( + sessionToken, + ref index, + out uint regionId)) + { + DefaultTrace.TraceWarning($"Unexpected region progress segment in session token: {sessionToken}."); + return false; + } + + if (!TryParseLongSegment( + sessionToken, + ref index, + out long localLsn)) + { + DefaultTrace.TraceWarning($"Unexpected local lsn for region id {regionId.ToString(CultureInfo.InvariantCulture)} for segment in session token: {sessionToken}."); + return false; + } + + lsnByRegion[regionId] = localLsn; + } + + localLsnByRegion = lsnByRegion; + + return true; + } + + private static bool TryParseUintTillRegionProgressSeparator( + string input, + ref int index, + out uint value) + { + value = 0; + if (index >= input.Length) + { + return false; + } + + long longValue = 0; + while (index < input.Length) + { + char c = input[index]; + if (c >= '0' && c <= '9') + { + longValue = (longValue * 10) + (c - '0'); + index++; + } + else + { + if (c == VectorSessionToken.RegionProgressSeparator) + { + // Always increase index pass stop character + index++; + break; + } + + return false; + } + } + + if (longValue > uint.MaxValue || + longValue < 0) + { + return false; + } + + value = (uint)longValue; + return true; + } + + private static bool TryParseLongSegment( + string input, + ref int index, + out long value) + { + value = 0; + if (index >= input.Length) + { + return false; + } + + bool isNegative = false; + if (input[index] == '-') + { + index++; + isNegative = true; + } + + while (index < input.Length) + { + char c = input[index]; + if (c >= '0' && c <= '9') + { + value = (value * 10) + (c - '0'); + index++; + } + else + { + if (c == VectorSessionToken.SegmentSeparator) + { + // Always increase index pass stop character + index++; + break; + } + + return false; + } + } + + if (isNegative) + { + value *= -1; + } + + return true; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/VersionUtility.cs b/Microsoft.Azure.Cosmos/src/direct/VersionUtility.cs index 1ece2be716..af36161fb0 100644 --- a/Microsoft.Azure.Cosmos/src/direct/VersionUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/VersionUtility.cs @@ -1,121 +1,121 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.Globalization; - - internal static class VersionUtility - { - private const string versionDateTimeFormat = "yyyy-MM-dd"; - private const string previewVersionDateTimeFormat = "yyyy-MM-dd-preview"; - - private static readonly IReadOnlyDictionary KnownDateTimes; - - static VersionUtility() - { - Dictionary knownDateTimesDict = new Dictionary(StringComparer.OrdinalIgnoreCase); - VersionUtility.KnownDateTimes = new ReadOnlyDictionary(knownDateTimesDict); - foreach (string versionString in HttpConstants.Versions.SupportedRuntimeAPIVersions) - { - if (VersionUtility.TryParseApiVersion(versionString, out DateTime apiVersionDate)) - { - knownDateTimesDict[versionString] = apiVersionDate; - } - } - } - -#if !CLIENT // once OSS SDK Move to the DateTime version flip this off everywhere. - // Format is YYYY-MM-DD - // true if compareVersion >= baseVersion. - internal static bool IsLaterThan(string compareVersion, string baseVersion) - { - if (VersionUtility.IsPreviewApiVersion(baseVersion) - && !VersionUtility.IsPreviewApiVersion(compareVersion)) - { - // Only another preview API version can be considered to be later than a base preview API version - return false; - } - - if (!VersionUtility.TryParseApiVersion(baseVersion, out DateTime baseVersionDate)) - { - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "base", baseVersion); - throw new BadRequestException(errorMessage); - } - - return VersionUtility.IsLaterThan(compareVersion, baseVersionDate); - } -#endif - - internal static bool IsValidApiVersion(string apiVersion) - { - return TryParseApiVersion(apiVersion, out _); - } - - internal static bool IsPreviewApiVersion(string apiVersion) - { - return apiVersion.ToLowerInvariant().Contains("preview"); - } - - // Format is YYYY-MM-DD - // true if compareVersion >= baseVersion. - internal static bool IsLaterThan(string compareVersion, DateTime baseVersion) - { - if (!VersionUtility.TryParseApiVersion(compareVersion, out DateTime compareVersionDate)) - { - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "compare", compareVersion); - throw new BadRequestException(errorMessage); - } - - return compareVersionDate.CompareTo(baseVersion) >= 0; - } - - // Format is YYYY-MM-DD - // true if compareVersion > baseVersion. - internal static bool IsLaterThanNotEqualTo(string compareVersion, DateTime baseVersion) - { - if (!VersionUtility.TryParseApiVersion(compareVersion, out DateTime compareVersionDate)) - { - string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "compare", compareVersion); - throw new BadRequestException(errorMessage); - } - - return compareVersionDate.CompareTo(baseVersion) > 0; - } - - internal static DateTime ParseNonPreviewDateTimeExact(string apiVersion) - { - return DateTime.ParseExact( - apiVersion, VersionUtility.versionDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None); - } - - private static bool TryParseApiVersion(string apiVersion, out DateTime apiVersionDate) - { - if (!VersionUtility.KnownDateTimes.TryGetValue(apiVersion, out apiVersionDate)) - { - return TryParseApiVersionCore(apiVersion, out apiVersionDate); - } - - return true; - } - - private static bool TryParseApiVersionCore(string apiVersion, out DateTime apiVersionDate) - { - string dateTimeFormat; - if (apiVersion.ToLowerInvariant().Contains("preview")) - { - dateTimeFormat = VersionUtility.previewVersionDateTimeFormat; - } - else - { - dateTimeFormat = VersionUtility.versionDateTimeFormat; - } - - return DateTime.TryParseExact( - apiVersion, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out apiVersionDate); - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Globalization; + + internal static class VersionUtility + { + private const string versionDateTimeFormat = "yyyy-MM-dd"; + private const string previewVersionDateTimeFormat = "yyyy-MM-dd-preview"; + + private static readonly IReadOnlyDictionary KnownDateTimes; + + static VersionUtility() + { + Dictionary knownDateTimesDict = new Dictionary(StringComparer.OrdinalIgnoreCase); + VersionUtility.KnownDateTimes = new ReadOnlyDictionary(knownDateTimesDict); + foreach (string versionString in HttpConstants.Versions.SupportedRuntimeAPIVersions) + { + if (VersionUtility.TryParseApiVersion(versionString, out DateTime apiVersionDate)) + { + knownDateTimesDict[versionString] = apiVersionDate; + } + } + } + +#if !CLIENT // once OSS SDK Move to the DateTime version flip this off everywhere. + // Format is YYYY-MM-DD + // true if compareVersion >= baseVersion. + internal static bool IsLaterThan(string compareVersion, string baseVersion) + { + if (VersionUtility.IsPreviewApiVersion(baseVersion) + && !VersionUtility.IsPreviewApiVersion(compareVersion)) + { + // Only another preview API version can be considered to be later than a base preview API version + return false; + } + + if (!VersionUtility.TryParseApiVersion(baseVersion, out DateTime baseVersionDate)) + { + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "base", baseVersion); + throw new BadRequestException(errorMessage); + } + + return VersionUtility.IsLaterThan(compareVersion, baseVersionDate); + } +#endif + + internal static bool IsValidApiVersion(string apiVersion) + { + return TryParseApiVersion(apiVersion, out _); + } + + internal static bool IsPreviewApiVersion(string apiVersion) + { + return apiVersion.ToLowerInvariant().Contains("preview"); + } + + // Format is YYYY-MM-DD + // true if compareVersion >= baseVersion. + internal static bool IsLaterThan(string compareVersion, DateTime baseVersion) + { + if (!VersionUtility.TryParseApiVersion(compareVersion, out DateTime compareVersionDate)) + { + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "compare", compareVersion); + throw new BadRequestException(errorMessage); + } + + return compareVersionDate.CompareTo(baseVersion) >= 0; + } + + // Format is YYYY-MM-DD + // true if compareVersion > baseVersion. + internal static bool IsLaterThanNotEqualTo(string compareVersion, DateTime baseVersion) + { + if (!VersionUtility.TryParseApiVersion(compareVersion, out DateTime compareVersionDate)) + { + string errorMessage = string.Format(CultureInfo.CurrentUICulture, RMResources.InvalidVersionFormat, "compare", compareVersion); + throw new BadRequestException(errorMessage); + } + + return compareVersionDate.CompareTo(baseVersion) > 0; + } + + internal static DateTime ParseNonPreviewDateTimeExact(string apiVersion) + { + return DateTime.ParseExact( + apiVersion, VersionUtility.versionDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None); + } + + private static bool TryParseApiVersion(string apiVersion, out DateTime apiVersionDate) + { + if (!VersionUtility.KnownDateTimes.TryGetValue(apiVersion, out apiVersionDate)) + { + return TryParseApiVersionCore(apiVersion, out apiVersionDate); + } + + return true; + } + + private static bool TryParseApiVersionCore(string apiVersion, out DateTime apiVersionDate) + { + string dateTimeFormat; + if (apiVersion.ToLowerInvariant().Contains("preview")) + { + dateTimeFormat = VersionUtility.previewVersionDateTimeFormat; + } + else + { + dateTimeFormat = VersionUtility.versionDateTimeFormat; + } + + return DateTime.TryParseExact( + apiVersion, dateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out apiVersionDate); + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/WFConstants.cs b/Microsoft.Azure.Cosmos/src/direct/WFConstants.cs index 918c6cad9b81641ebdc0952c77abeb8636e47746..8227a58006a7650c2e3017193b697d8cc149863e 100644 GIT binary patch delta 388 zcmdmSj`7ZQ#tj+C(k=}749N_o47m)c40#MC3_(CT87Nl7kTUroyW(U6BbmtuoP{Qb z$O!Q20!0zB^=zT+!3^09nG6M!C#s6_J2NCQ6flGV$sC|q%H+3p+U&(p`GczB!pUHH zU4}B43WmhVbL9dFx}brNYciV!y6yR#;gbWL`8H=HOEFKLU~VE>4D>=iLotIp(D)Ld zGs}T=<>c$G)~e~qA`H4f*&?7w9#Cx}(5odt$L2HSO - /// Returns the sum of teh designated times across all processors since - /// system start in 100-nanosecond intervals - /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes - /// - /// The amount of time that the system has been idle - /// - /// The amount of time that the system has spent executing in Kernel mode - /// (including all threads in all processes, on all processors). This time value also includes - /// the amount of time the system has been idle. - /// - /// - /// The amount of time that the system has spent executing in User mode (including all threads - /// in all processes, on all processors). - /// - /// - [DllImport("kernel32.dll", SetLastError = true)] - internal static extern bool GetSystemTimes(out long idle, out long kernel, out long user); - - /// - /// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex - /// - /// - /// - /// - /// - [DllImport("kernel32.dll", SetLastError = true)] - internal static extern bool GlobalMemoryStatusEx(out MemoryInfo memInfo); - - [StructLayout(LayoutKind.Sequential)] - internal struct MemoryInfo - { - internal uint dwLength; - internal uint dwMemoryLoad; - internal ulong ullTotalPhys; - internal ulong ullAvailPhys; - internal ulong ullTotalPageFile; - internal ulong ullAvailPageFile; - internal ulong ullTotalVirtual; - internal ulong ullAvailVirtual; - internal ulong ullAvailExtendedVirtual; - } - } - } +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Runtime.InteropServices; + + internal sealed class WindowsSystemUtilizationReader : SystemUtilizationReaderBase + { + private long lastIdleTime; + private long lastKernelTime; + private long lastUserTime; + + public WindowsSystemUtilizationReader() + { + this.lastIdleTime = 0; + this.lastKernelTime = 0; + this.lastUserTime = 0; + } + + protected override float GetSystemWideCpuUsageCore() + { + long currentIdleTime; + long currentKernelTime; + long currentUserTime; + + if (!NativeMethods.GetSystemTimes( + out currentIdleTime, out currentKernelTime, out currentUserTime)) + { + return Single.NaN; + } + + long idleTimeElapsed = currentIdleTime - this.lastIdleTime; + long kernelTimeElapsed = currentKernelTime - this.lastKernelTime; + long userTimeElapsed = currentUserTime - this.lastUserTime; + + this.lastIdleTime = currentIdleTime; + this.lastUserTime = currentUserTime; + this.lastKernelTime = currentKernelTime; + + long timeElapsed = userTimeElapsed + kernelTimeElapsed; + if (timeElapsed == 0) + { + return Single.NaN; + } + + long busyTimeElapsed = userTimeElapsed + kernelTimeElapsed - idleTimeElapsed; + + return 100 * busyTimeElapsed / (float)timeElapsed; + } + + protected override long? GetSystemWideMemoryAvailabiltyCore() + { + NativeMethods.MemoryInfo memInfo = new NativeMethods.MemoryInfo(); + memInfo.dwLength = (uint)Marshal.SizeOf(memInfo); + + NativeMethods.GlobalMemoryStatusEx(out memInfo); + + return (long)memInfo.ullAvailPhys/1024; + } + + private static class NativeMethods + { + + /// + /// Returns the sum of teh designated times across all processors since + /// system start in 100-nanosecond intervals + /// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getsystemtimes + /// + /// The amount of time that the system has been idle + /// + /// The amount of time that the system has spent executing in Kernel mode + /// (including all threads in all processes, on all processors). This time value also includes + /// the amount of time the system has been idle. + /// + /// + /// The amount of time that the system has spent executing in User mode (including all threads + /// in all processes, on all processors). + /// + /// + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern bool GetSystemTimes(out long idle, out long kernel, out long user); + + /// + /// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex + /// + /// + /// + /// + /// + [DllImport("kernel32.dll", SetLastError = true)] + internal static extern bool GlobalMemoryStatusEx(out MemoryInfo memInfo); + + [StructLayout(LayoutKind.Sequential)] + internal struct MemoryInfo + { + internal uint dwLength; + internal uint dwMemoryLoad; + internal ulong ullTotalPhys; + internal ulong ullAvailPhys; + internal ulong ullTotalPageFile; + internal ulong ullAvailPageFile; + internal ulong ullTotalVirtual; + internal ulong ullAvailVirtual; + internal ulong ullAvailExtendedVirtual; + } + } + } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/msdata_sync.ps1 b/Microsoft.Azure.Cosmos/src/direct/msdata_sync.ps1 index 2783a7f840..84c4e9e1c5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/msdata_sync.ps1 +++ b/Microsoft.Azure.Cosmos/src/direct/msdata_sync.ps1 @@ -1,4 +1,4 @@ -$baseDir = "C:\stash\CosmosDB" +$baseDir = "C:\src\CosmosDB" $sourceDir = @( "\Product\SDK\.net\Microsoft.Azure.Cosmos.Direct\src\", diff --git a/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs b/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs index 87ec56777d..753724c3c6 100644 --- a/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs @@ -1,609 +1,609 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Documents.Rntbd -{ - using System; - using System.Diagnostics; - using System.Globalization; - using System.Net.Security; - using System.Text; - using System.Threading; - using System.Threading.Tasks; - using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Documents.FaultInjection; - using Microsoft.Azure.Documents.Telemetry; -#if NETSTANDARD15 || NETSTANDARD16 - using Trace = Microsoft.Azure.Documents.Trace; -#endif - - internal sealed class TransportClient : - Microsoft.Azure.Documents.TransportClient, IDisposable - { - private enum TransportResponseStatusCode - { - Success = 0, - DocumentClientException = -1, - UnknownException = -2 - } - private static TransportPerformanceCounters transportPerformanceCounters = new TransportPerformanceCounters(); - - private readonly TimerPool TimerPool; - private readonly TimerPool IdleTimerPool; - private readonly ChannelDictionary channelDictionary; - private bool disposed = false; - - private readonly DistributedTracingOptions DistributedTracingOptions; - - #region RNTBD Transition - - // Transitional state while migrating SDK users from the old RNTBD stack - // to the new version. Delete these fields when the old stack is deleted. - private readonly object disableRntbdChannelLock = new object(); - // Guarded by disableRntbdChannelLock - private bool disableRntbdChannel = false; - -#endregion - - public TransportClient(Options clientOptions, IChaosInterceptor chaosInterceptor = null) - { - if (clientOptions == null) - { - throw new ArgumentNullException(nameof(clientOptions)); - } - - TransportClient.LogClientOptions(clientOptions); - - UserPortPool userPortPool = null; - if (clientOptions.PortReuseMode == PortReuseMode.PrivatePortPool) - { - userPortPool = new UserPortPool( - clientOptions.PortPoolReuseThreshold, - clientOptions.PortPoolBindAttempts); - } - - this.TimerPool = new TimerPool((int)clientOptions.TimerPoolResolution.TotalSeconds); - if (clientOptions.IdleTimeout > TimeSpan.Zero) - { - this.IdleTimerPool = new TimerPool(minSupportedTimerDelayInSeconds: 30); - } - else - { - this.IdleTimerPool = null; - } - - this.DistributedTracingOptions = clientOptions.DistributedTracingOptions; - - this.channelDictionary = new ChannelDictionary( - new ChannelProperties( - clientOptions.UserAgent, - clientOptions.CertificateHostNameOverride, - clientOptions.ConnectionStateListener, - this.TimerPool, - clientOptions.RequestTimeout, - clientOptions.OpenTimeout, - clientOptions.LocalRegionOpenTimeout, - clientOptions.PortReuseMode, - userPortPool, - clientOptions.MaxChannels, - clientOptions.PartitionCount, - clientOptions.MaxRequestsPerChannel, - clientOptions.MaxConcurrentOpeningConnectionCount, - clientOptions.ReceiveHangDetectionTime, - clientOptions.SendHangDetectionTime, - clientOptions.IdleTimeout, - this.IdleTimerPool, - clientOptions.CallerId, - clientOptions.EnableChannelMultiplexing, - clientOptions.MemoryStreamPool, - clientOptions.RemoteCertificateValidationCallback, - clientOptions.DnsResolutionFunction), - chaosInterceptor); - } - - internal override Task InvokeStoreAsync( - Uri physicalAddress, - ResourceOperation resourceOperation, - DocumentServiceRequest request) - { - return this.InvokeStoreAsync(new TransportAddressUri(physicalAddress), resourceOperation, request); - } - - internal override async Task InvokeStoreAsync( - TransportAddressUri physicalAddress, ResourceOperation resourceOperation, - DocumentServiceRequest request) - { - this.ThrowIfDisposed(); - Guid activityId = Trace.CorrelationManager.ActivityId; - - if (!request.IsBodySeekableClonableAndCountable) - { - throw new InternalServerErrorException(); - } - - StoreResponse storeResponse = null; - TransportRequestStats transportRequestStats = new TransportRequestStats(); - string operation = "Unknown operation"; - DateTime requestStartTime = DateTime.UtcNow; - int transportResponseStatusCode = (int)TransportResponseStatusCode.Success; - -#if NETSTANDARD2_0_OR_GREATER - using OpenTelemetryRecorder recorder = OpenTelemetryRecorderFactory.CreateRecorder( - options: this.DistributedTracingOptions, - request: request); -#endif - try - { - TransportClient.IncrementCounters(); - - operation = "GetChannel"; - // Treat all retries as out of region request for open timeout. This is to prevent too many retries because of the shorter time duration. - bool localRegionRequest = request.RequestContext.IsRetry ? false : request.RequestContext.LocalRegionRequest; - IChannel channel = this.channelDictionary.GetChannel(physicalAddress.Uri, localRegionRequest); - - TransportClient.GetTransportPerformanceCounters().IncrementRntbdRequestCount(resourceOperation.resourceType, resourceOperation.operationType); - - operation = "RequestAsync"; - storeResponse = await channel.RequestAsync(request, physicalAddress, - resourceOperation, activityId, transportRequestStats); - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Completed); - storeResponse.TransportRequestStats = transportRequestStats; - } - catch (TransportException ex) - { - // App-compat shim: On transport failure, TransportClient callers - // expect one of: - // - GoneException - widely abused to mean "refresh the address - // cache and try again". - // - RequestTimeoutException - means what it says, but it's a - // non-retriable error. - // - ServiceUnavailableException - abused to mean "non-retriable - // error other than timeout". Endless source of customer - // confusion. - // - // Traditionally, the transport client has converted timeouts to - // RequestTimeoutException or GoneException based on whether - // the request was a write (non-retriable) or a read (retriable). - // This design leads to a low-level piece of code driving a - // component much higher in the stack (the retry loop) - // based on high-level information (request types). - // Low-level code should only return errors describing what went - // wrong at its level and provide enough information that callers - // can decide what to do. - // - // Until the retry loop can be fixed so that it handles - // TransportException directly, don't allow TransportException - // to escape, and wrap it in an expected DocumentClientException - // instead. Tracked in backlog item 303368. - - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Failed); - transportResponseStatusCode = (int) ex.ErrorCode; - ex.RequestStartTime = requestStartTime; - ex.RequestEndTime = DateTime.UtcNow; - ex.OperationType = resourceOperation.operationType; - ex.ResourceType = resourceOperation.resourceType; - TransportClient.GetTransportPerformanceCounters().IncrementRntbdResponseCount(resourceOperation.resourceType, - resourceOperation.operationType, (int) ex.ErrorCode); - - DefaultTrace.TraceInformation( - "{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + - "Exception: {5}", - operation, request.ResourceAddress, request.ResourceType, - resourceOperation, physicalAddress, ex); - if (request.IsReadOnlyRequest) - { - DefaultTrace.TraceInformation("Converting to Gone (read-only request)"); - GoneException goneExcepetion = TransportExceptions.GetGoneException( - physicalAddress.Uri, activityId, ex, transportRequestStats); -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, documentClientException: goneExcepetion); -#endif - throw goneExcepetion; - } - if (!ex.UserRequestSent) - { - DefaultTrace.TraceInformation("Converting to Gone (write request, not sent)"); - GoneException goneExcepetion = TransportExceptions.GetGoneException( - physicalAddress.Uri, activityId, ex, transportRequestStats); -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, documentClientException: goneExcepetion); -#endif - throw goneExcepetion; - } - if (TransportException.IsTimeout(ex.ErrorCode)) - { - DefaultTrace.TraceInformation("Converting to RequestTimeout"); - RequestTimeoutException requestTimeoutException = TransportExceptions.GetRequestTimeoutException( - physicalAddress.Uri, activityId, ex, transportRequestStats); -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, documentClientException: requestTimeoutException); -#endif - throw requestTimeoutException; - } - DefaultTrace.TraceInformation("Converting to ServiceUnavailable"); - ServiceUnavailableException serviceUnavailableException = TransportExceptions.GetServiceUnavailableException( - physicalAddress.Uri, activityId, ex, transportRequestStats); -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, documentClientException: serviceUnavailableException); -#endif - throw serviceUnavailableException; - - } - catch (DocumentClientException ex) - { - transportResponseStatusCode = (int)TransportResponseStatusCode.DocumentClientException; - DefaultTrace.TraceInformation("{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + - "Exception: {5}", operation, request.ResourceAddress, request.ResourceType, resourceOperation, - physicalAddress, ex); - transportRequestStats.RecordState(TransportRequestStats.RequestStage.Failed); - ex.TransportRequestStats = transportRequestStats; -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, documentClientException: ex); -#endif - throw; - } - catch (Exception ex) - { - transportResponseStatusCode = (int)TransportResponseStatusCode.UnknownException; - DefaultTrace.TraceInformation("{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + - "Exception: {5}", operation, request.ResourceAddress, request.ResourceType, resourceOperation, - physicalAddress, ex); -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, exception: ex); -#endif - throw; - } - finally - { - TransportClient.DecrementCounters(); - TransportClient.GetTransportPerformanceCounters().IncrementRntbdResponseCount(resourceOperation.resourceType, - resourceOperation.operationType, transportResponseStatusCode); - this.RaiseProtocolDowngradeRequest(storeResponse); - } - - try - { - TransportClient.ThrowServerException(request.ResourceAddress, storeResponse, physicalAddress.Uri, activityId, request); - } -#if NETSTANDARD2_0_OR_GREATER - catch (DocumentClientException exception) - { - recorder?.Record(physicalAddress.Uri, documentClientException: exception); - throw; - } - - // Record the information of the sucessfull response in the end, it also make sure it is not getting called twice. - recorder?.Record(physicalAddress.Uri, storeResponse: storeResponse); -#else - catch (DocumentClientException) - { - throw; - } -#endif - return storeResponse; - } - - public override void Dispose() - { - this.ThrowIfDisposed(); - this.disposed = true; - this.channelDictionary.Dispose(); - - if (this.IdleTimerPool != null) - { - this.IdleTimerPool.Dispose(); - } - - this.TimerPool.Dispose(); - - base.Dispose(); - - DefaultTrace.TraceInformation("Rntbd.TransportClient disposed."); - } - - private void ThrowIfDisposed() - { - if (this.disposed) - { - throw new ObjectDisposedException(nameof(TransportClient)); - } - } - - private static void LogClientOptions(Options clientOptions) - { - DefaultTrace.TraceInformation("Creating RNTBD TransportClient with options {0}", clientOptions.ToString()); - } - - private static void IncrementCounters() - { -#if NETFX - if (PerfCounters.Counters.BackendActiveRequests != null) - { - PerfCounters.Counters.BackendActiveRequests.Increment(); - } - if (PerfCounters.Counters.BackendRequestsPerSec != null) - { - PerfCounters.Counters.BackendRequestsPerSec.Increment(); - } -#endif - } - - private static void DecrementCounters() - { -#if NETFX - if (PerfCounters.Counters.BackendActiveRequests != null) - { - PerfCounters.Counters.BackendActiveRequests.Decrement(); - } -#endif - } - - /// - internal override Task OpenConnectionAsync( - Uri physicalAddress) - { - IChannel channel = this.channelDictionary.GetChannel( - requestUri: physicalAddress, - localRegionRequest: false); - - return channel.OpenChannelAsync( - activityId: Trace.CorrelationManager.ActivityId); - } - -#region RNTBD Transition - - public event Action OnDisableRntbdChannel; - - // Examines storeResponse and raises an event if this is the first time - // this transport client sees the "disable RNTBD channel" header set to - // true by the back-end. - private void RaiseProtocolDowngradeRequest(StoreResponse storeResponse) - { - if (storeResponse == null) - { - return; - } - string disableRntbdChannelHeader = null; - if (!storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.DisableRntbdChannel, out disableRntbdChannelHeader)) - { - return; - } - if (!string.Equals(disableRntbdChannelHeader, "true")) - { - return; - } - - bool raiseRntbdChannelDisable = false; - lock (this.disableRntbdChannelLock) - { - if (this.disableRntbdChannel) - { - return; - } - this.disableRntbdChannel = true; - raiseRntbdChannelDisable = true; - } - if (!raiseRntbdChannelDisable) - { - return; - } - - // Schedule execution on current .NET task scheduler. - // Compute gateway uses custom task scheduler to track tenant resource utilization. - // Task.Run() switches to default task scheduler for entire sub-tree of tasks making compute gateway incapable of tracking resource usage accurately. - // Task.Factory.StartNew() allows specifying task scheduler to use. - Task.Factory.StartNewOnCurrentTaskSchedulerAsync(() => - { - this.OnDisableRntbdChannel?.Invoke(); - }) - .ContinueWith( - failedTask => - { - DefaultTrace.TraceError( - "RNTBD channel callback failed: {0}", - failedTask.Exception); - }, - default(CancellationToken), - TaskContinuationOptions.OnlyOnFaulted, - TaskScheduler.Current); - } - -#endregion - - public sealed class Options - { - private UserAgentContainer userAgent = null; - private TimeSpan openTimeout = TimeSpan.Zero; - private TimeSpan localRegionOpenTimeout = TimeSpan.Zero; - private TimeSpan timerPoolResolution = TimeSpan.Zero; - - public Options(TimeSpan requestTimeout) - { - Debug.Assert(requestTimeout > TimeSpan.Zero); - this.RequestTimeout = requestTimeout; - this.MaxChannels = ushort.MaxValue; - this.PartitionCount = 1; - this.MaxRequestsPerChannel = 30; - this.PortReuseMode = PortReuseMode.ReuseUnicastPort; - this.PortPoolReuseThreshold = 256; - this.PortPoolBindAttempts = 5; - this.ReceiveHangDetectionTime = TimeSpan.FromSeconds(65.0); - this.SendHangDetectionTime = TimeSpan.FromSeconds(10.0); - this.IdleTimeout = TimeSpan.FromSeconds(1800); - this.CallerId = RntbdConstants.CallerId.Anonymous; - this.EnableChannelMultiplexing = false; - this.MaxConcurrentOpeningConnectionCount = ushort.MaxValue; - this.DnsResolutionFunction = null; - this.DistributedTracingOptions = null; - } - - public TimeSpan RequestTimeout { get; private set; } - public int MaxChannels { get; set; } - public int PartitionCount { get; set; } - public int MaxRequestsPerChannel { get; set; } - public TimeSpan ReceiveHangDetectionTime { get; set; } - public TimeSpan SendHangDetectionTime { get; set; } - public TimeSpan IdleTimeout { get; set; } - public RntbdConstants.CallerId CallerId { get; set; } - public bool EnableChannelMultiplexing { get; set; } - - public Microsoft.Azure.Documents.MemoryStreamPool MemoryStreamPool { get; set; } - - public UserAgentContainer UserAgent - { - get - { - if (this.userAgent != null) - { - return this.userAgent; - } - this.userAgent = new UserAgentContainer(); - return this.userAgent; - } - set { this.userAgent = value; } - } - - public string CertificateHostNameOverride { get; set; } - - public IConnectionStateListener ConnectionStateListener { get; set; } - - public TimeSpan OpenTimeout - { - get - { - if (this.openTimeout > TimeSpan.Zero) - { - return this.openTimeout; - } - return this.RequestTimeout; - } - set { this.openTimeout = value; } - } - - public TimeSpan LocalRegionOpenTimeout - { - get - { - if (this.localRegionOpenTimeout > TimeSpan.Zero) - { - return this.localRegionOpenTimeout; - } - return this.OpenTimeout; - } - set { this.localRegionOpenTimeout = value; } - } - - public PortReuseMode PortReuseMode { get; set; } - - public int PortPoolReuseThreshold { get; internal set; } - - public int PortPoolBindAttempts { get; internal set; } - - public TimeSpan TimerPoolResolution - { - get - { - return Options.GetTimerPoolResolutionSeconds( - this.timerPoolResolution, this.RequestTimeout, this.openTimeout); - } - set { this.timerPoolResolution = value; } - } - - public int MaxConcurrentOpeningConnectionCount { get; set; } - - public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; internal set; } - - /// - /// Override for DNS resolution callbacks for RNTBD connections. - /// - public Func> DnsResolutionFunction { get; internal set; } - - /// - /// Distributed Tracing Options - /// - public DistributedTracingOptions DistributedTracingOptions { get; set; } - - public override string ToString() - { - StringBuilder s = new StringBuilder(); - s.AppendLine("Rntbd.TransportClient.Options"); - s.Append(" OpenTimeout: "); - s.AppendLine(this.OpenTimeout.ToString("c")); - s.Append(" RequestTimeout: "); - s.AppendLine(this.RequestTimeout.ToString("c")); - s.Append(" TimerPoolResolution: "); - s.AppendLine(this.TimerPoolResolution.ToString("c")); - s.Append(" MaxChannels: "); - s.AppendLine(this.MaxChannels.ToString(CultureInfo.InvariantCulture)); - s.Append(" PartitionCount: "); - s.AppendLine(this.PartitionCount.ToString(CultureInfo.InvariantCulture)); - s.Append(" MaxRequestsPerChannel: "); - s.AppendLine(this.MaxRequestsPerChannel.ToString(CultureInfo.InvariantCulture)); - s.Append(" ReceiveHangDetectionTime: "); - s.AppendLine(this.ReceiveHangDetectionTime.ToString("c")); - s.Append(" SendHangDetectionTime: "); - s.AppendLine(this.SendHangDetectionTime.ToString("c")); - s.Append(" IdleTimeout: "); - s.AppendLine(this.IdleTimeout.ToString("c")); - s.Append(" UserAgent: "); - s.Append(this.UserAgent.UserAgent); - s.Append(" Suffix: "); - s.AppendLine(this.UserAgent.Suffix); - s.Append(" CertificateHostNameOverride: "); - s.AppendLine(this.CertificateHostNameOverride); - s.Append(" LocalRegionTimeout: "); - s.AppendLine(this.LocalRegionOpenTimeout.ToString("c")); - s.Append(" EnableChannelMultiplexing: "); - s.AppendLine(this.EnableChannelMultiplexing.ToString()); - s.Append(" MaxConcurrentOpeningConnectionCount: "); - s.AppendLine(this.MaxConcurrentOpeningConnectionCount.ToString(CultureInfo.InvariantCulture)); - s.Append(" Use_RecyclableMemoryStream: "); - s.AppendLine(this.MemoryStreamPool != null ? bool.TrueString : bool.FalseString); - s.Append(" Use_CustomDnsResolution: "); - s.AppendLine(this.DnsResolutionFunction != null ? bool.TrueString : bool.FalseString); - s.Append(" IsDistributedTracingEnabled: "); -#if NETSTANDARD2_0_OR_GREATER - s.AppendLine(this.DistributedTracingOptions?.IsDistributedTracingEnabled.ToString()); -#else - s.AppendLine("false"); -#endif - return s.ToString(); - } - - private static TimeSpan GetTimerPoolResolutionSeconds( - TimeSpan timerPoolResolution, TimeSpan requestTimeout, TimeSpan openTimeout) - { - Debug.Assert(timerPoolResolution > TimeSpan.Zero || - openTimeout > TimeSpan.Zero || - requestTimeout > TimeSpan.Zero); - if (timerPoolResolution > TimeSpan.Zero && - timerPoolResolution < openTimeout && - timerPoolResolution < requestTimeout) - { - return timerPoolResolution; - } - if (openTimeout > TimeSpan.Zero && requestTimeout > TimeSpan.Zero) - { - return openTimeout < requestTimeout ? openTimeout : requestTimeout; - } - return openTimeout > TimeSpan.Zero ? openTimeout : requestTimeout; - } - - } - - internal static void SetTransportPerformanceCounters(TransportPerformanceCounters transportPerformanceCounters) - { - if (transportPerformanceCounters == null) - { - throw new ArgumentNullException(nameof(transportPerformanceCounters)); - } - - TransportClient.transportPerformanceCounters = transportPerformanceCounters; - } - - internal static TransportPerformanceCounters GetTransportPerformanceCounters() - { - return transportPerformanceCounters; - } - } -} +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Documents.Rntbd +{ + using System; + using System.Diagnostics; + using System.Globalization; + using System.Net.Security; + using System.Text; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Core.Trace; + using Microsoft.Azure.Documents.FaultInjection; + using Microsoft.Azure.Documents.Telemetry; +#if NETSTANDARD15 || NETSTANDARD16 + using Trace = Microsoft.Azure.Documents.Trace; +#endif + + internal sealed class TransportClient : + Microsoft.Azure.Documents.TransportClient, IDisposable + { + private enum TransportResponseStatusCode + { + Success = 0, + DocumentClientException = -1, + UnknownException = -2 + } + private static TransportPerformanceCounters transportPerformanceCounters = new TransportPerformanceCounters(); + + private readonly TimerPool TimerPool; + private readonly TimerPool IdleTimerPool; + private readonly ChannelDictionary channelDictionary; + private bool disposed = false; + + private readonly DistributedTracingOptions DistributedTracingOptions; + + #region RNTBD Transition + + // Transitional state while migrating SDK users from the old RNTBD stack + // to the new version. Delete these fields when the old stack is deleted. + private readonly object disableRntbdChannelLock = new object(); + // Guarded by disableRntbdChannelLock + private bool disableRntbdChannel = false; + +#endregion + + public TransportClient(Options clientOptions, IChaosInterceptor chaosInterceptor = null) + { + if (clientOptions == null) + { + throw new ArgumentNullException(nameof(clientOptions)); + } + + TransportClient.LogClientOptions(clientOptions); + + UserPortPool userPortPool = null; + if (clientOptions.PortReuseMode == PortReuseMode.PrivatePortPool) + { + userPortPool = new UserPortPool( + clientOptions.PortPoolReuseThreshold, + clientOptions.PortPoolBindAttempts); + } + + this.TimerPool = new TimerPool((int)clientOptions.TimerPoolResolution.TotalSeconds); + if (clientOptions.IdleTimeout > TimeSpan.Zero) + { + this.IdleTimerPool = new TimerPool(minSupportedTimerDelayInSeconds: 30); + } + else + { + this.IdleTimerPool = null; + } + + this.DistributedTracingOptions = clientOptions.DistributedTracingOptions; + + this.channelDictionary = new ChannelDictionary( + new ChannelProperties( + clientOptions.UserAgent, + clientOptions.CertificateHostNameOverride, + clientOptions.ConnectionStateListener, + this.TimerPool, + clientOptions.RequestTimeout, + clientOptions.OpenTimeout, + clientOptions.LocalRegionOpenTimeout, + clientOptions.PortReuseMode, + userPortPool, + clientOptions.MaxChannels, + clientOptions.PartitionCount, + clientOptions.MaxRequestsPerChannel, + clientOptions.MaxConcurrentOpeningConnectionCount, + clientOptions.ReceiveHangDetectionTime, + clientOptions.SendHangDetectionTime, + clientOptions.IdleTimeout, + this.IdleTimerPool, + clientOptions.CallerId, + clientOptions.EnableChannelMultiplexing, + clientOptions.MemoryStreamPool, + clientOptions.RemoteCertificateValidationCallback, + clientOptions.DnsResolutionFunction), + chaosInterceptor); + } + + internal override Task InvokeStoreAsync( + Uri physicalAddress, + ResourceOperation resourceOperation, + DocumentServiceRequest request) + { + return this.InvokeStoreAsync(new TransportAddressUri(physicalAddress), resourceOperation, request); + } + + internal override async Task InvokeStoreAsync( + TransportAddressUri physicalAddress, ResourceOperation resourceOperation, + DocumentServiceRequest request) + { + this.ThrowIfDisposed(); + Guid activityId = Trace.CorrelationManager.ActivityId; + + if (!request.IsBodySeekableClonableAndCountable) + { + throw new InternalServerErrorException(); + } + + StoreResponse storeResponse = null; + TransportRequestStats transportRequestStats = new TransportRequestStats(); + string operation = "Unknown operation"; + DateTime requestStartTime = DateTime.UtcNow; + int transportResponseStatusCode = (int)TransportResponseStatusCode.Success; + +#if NETSTANDARD2_0_OR_GREATER + using OpenTelemetryRecorder recorder = OpenTelemetryRecorderFactory.CreateRecorder( + options: this.DistributedTracingOptions, + request: request); +#endif + try + { + TransportClient.IncrementCounters(); + + operation = "GetChannel"; + // Treat all retries as out of region request for open timeout. This is to prevent too many retries because of the shorter time duration. + bool localRegionRequest = request.RequestContext.IsRetry ? false : request.RequestContext.LocalRegionRequest; + IChannel channel = this.channelDictionary.GetChannel(physicalAddress.Uri, localRegionRequest); + + TransportClient.GetTransportPerformanceCounters().IncrementRntbdRequestCount(resourceOperation.resourceType, resourceOperation.operationType); + + operation = "RequestAsync"; + storeResponse = await channel.RequestAsync(request, physicalAddress, + resourceOperation, activityId, transportRequestStats); + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Completed); + storeResponse.TransportRequestStats = transportRequestStats; + } + catch (TransportException ex) + { + // App-compat shim: On transport failure, TransportClient callers + // expect one of: + // - GoneException - widely abused to mean "refresh the address + // cache and try again". + // - RequestTimeoutException - means what it says, but it's a + // non-retriable error. + // - ServiceUnavailableException - abused to mean "non-retriable + // error other than timeout". Endless source of customer + // confusion. + // + // Traditionally, the transport client has converted timeouts to + // RequestTimeoutException or GoneException based on whether + // the request was a write (non-retriable) or a read (retriable). + // This design leads to a low-level piece of code driving a + // component much higher in the stack (the retry loop) + // based on high-level information (request types). + // Low-level code should only return errors describing what went + // wrong at its level and provide enough information that callers + // can decide what to do. + // + // Until the retry loop can be fixed so that it handles + // TransportException directly, don't allow TransportException + // to escape, and wrap it in an expected DocumentClientException + // instead. Tracked in backlog item 303368. + + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Failed); + transportResponseStatusCode = (int) ex.ErrorCode; + ex.RequestStartTime = requestStartTime; + ex.RequestEndTime = DateTime.UtcNow; + ex.OperationType = resourceOperation.operationType; + ex.ResourceType = resourceOperation.resourceType; + TransportClient.GetTransportPerformanceCounters().IncrementRntbdResponseCount(resourceOperation.resourceType, + resourceOperation.operationType, (int) ex.ErrorCode); + + DefaultTrace.TraceInformation( + "{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + + "Exception: {5}", + operation, request.ResourceAddress, request.ResourceType, + resourceOperation, physicalAddress, ex); + if (request.IsReadOnlyRequest) + { + DefaultTrace.TraceInformation("Converting to Gone (read-only request)"); + GoneException goneExcepetion = TransportExceptions.GetGoneException( + physicalAddress.Uri, activityId, ex, transportRequestStats); +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: goneExcepetion); +#endif + throw goneExcepetion; + } + if (!ex.UserRequestSent) + { + DefaultTrace.TraceInformation("Converting to Gone (write request, not sent)"); + GoneException goneExcepetion = TransportExceptions.GetGoneException( + physicalAddress.Uri, activityId, ex, transportRequestStats); +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: goneExcepetion); +#endif + throw goneExcepetion; + } + if (TransportException.IsTimeout(ex.ErrorCode)) + { + DefaultTrace.TraceInformation("Converting to RequestTimeout"); + RequestTimeoutException requestTimeoutException = TransportExceptions.GetRequestTimeoutException( + physicalAddress.Uri, activityId, ex, transportRequestStats); +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: requestTimeoutException); +#endif + throw requestTimeoutException; + } + DefaultTrace.TraceInformation("Converting to ServiceUnavailable"); + ServiceUnavailableException serviceUnavailableException = TransportExceptions.GetServiceUnavailableException( + physicalAddress.Uri, activityId, ex, transportRequestStats); +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: serviceUnavailableException); +#endif + throw serviceUnavailableException; + + } + catch (DocumentClientException ex) + { + transportResponseStatusCode = (int)TransportResponseStatusCode.DocumentClientException; + DefaultTrace.TraceInformation("{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + + "Exception: {5}", operation, request.ResourceAddress, request.ResourceType, resourceOperation, + physicalAddress, ex); + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Failed); + ex.TransportRequestStats = transportRequestStats; +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: ex); +#endif + throw; + } + catch (Exception ex) + { + transportResponseStatusCode = (int)TransportResponseStatusCode.UnknownException; + DefaultTrace.TraceInformation("{0} failed: RID: {1}, Resource Type: {2}, Op: {3}, Address: {4}, " + + "Exception: {5}", operation, request.ResourceAddress, request.ResourceType, resourceOperation, + physicalAddress, ex); +#if NETSTANDARD2_0_OR_GREATER + recorder?.Record(physicalAddress.Uri, exception: ex); +#endif + throw; + } + finally + { + TransportClient.DecrementCounters(); + TransportClient.GetTransportPerformanceCounters().IncrementRntbdResponseCount(resourceOperation.resourceType, + resourceOperation.operationType, transportResponseStatusCode); + this.RaiseProtocolDowngradeRequest(storeResponse); + } + + try + { + TransportClient.ThrowServerException(request.ResourceAddress, storeResponse, physicalAddress.Uri, activityId, request); + } +#if NETSTANDARD2_0_OR_GREATER + catch (DocumentClientException exception) + { + recorder?.Record(physicalAddress.Uri, exception: exception); + throw; + } + + // Record the information of the sucessfull response in the end, it also make sure it is not getting called twice. + recorder?.Record(physicalAddress.Uri, storeResponse: storeResponse); +#else + catch (DocumentClientException) + { + throw; + } +#endif + return storeResponse; + } + + public override void Dispose() + { + this.ThrowIfDisposed(); + this.disposed = true; + this.channelDictionary.Dispose(); + + if (this.IdleTimerPool != null) + { + this.IdleTimerPool.Dispose(); + } + + this.TimerPool.Dispose(); + + base.Dispose(); + + DefaultTrace.TraceInformation("Rntbd.TransportClient disposed."); + } + + private void ThrowIfDisposed() + { + if (this.disposed) + { + throw new ObjectDisposedException(nameof(TransportClient)); + } + } + + private static void LogClientOptions(Options clientOptions) + { + DefaultTrace.TraceInformation("Creating RNTBD TransportClient with options {0}", clientOptions.ToString()); + } + + private static void IncrementCounters() + { +#if NETFX + if (PerfCounters.Counters.BackendActiveRequests != null) + { + PerfCounters.Counters.BackendActiveRequests.Increment(); + } + if (PerfCounters.Counters.BackendRequestsPerSec != null) + { + PerfCounters.Counters.BackendRequestsPerSec.Increment(); + } +#endif + } + + private static void DecrementCounters() + { +#if NETFX + if (PerfCounters.Counters.BackendActiveRequests != null) + { + PerfCounters.Counters.BackendActiveRequests.Decrement(); + } +#endif + } + + /// + internal override Task OpenConnectionAsync( + Uri physicalAddress) + { + IChannel channel = this.channelDictionary.GetChannel( + requestUri: physicalAddress, + localRegionRequest: false); + + return channel.OpenChannelAsync( + activityId: Trace.CorrelationManager.ActivityId); + } + +#region RNTBD Transition + + public event Action OnDisableRntbdChannel; + + // Examines storeResponse and raises an event if this is the first time + // this transport client sees the "disable RNTBD channel" header set to + // true by the back-end. + private void RaiseProtocolDowngradeRequest(StoreResponse storeResponse) + { + if (storeResponse == null) + { + return; + } + string disableRntbdChannelHeader = null; + if (!storeResponse.TryGetHeaderValue(HttpConstants.HttpHeaders.DisableRntbdChannel, out disableRntbdChannelHeader)) + { + return; + } + if (!string.Equals(disableRntbdChannelHeader, "true")) + { + return; + } + + bool raiseRntbdChannelDisable = false; + lock (this.disableRntbdChannelLock) + { + if (this.disableRntbdChannel) + { + return; + } + this.disableRntbdChannel = true; + raiseRntbdChannelDisable = true; + } + if (!raiseRntbdChannelDisable) + { + return; + } + + // Schedule execution on current .NET task scheduler. + // Compute gateway uses custom task scheduler to track tenant resource utilization. + // Task.Run() switches to default task scheduler for entire sub-tree of tasks making compute gateway incapable of tracking resource usage accurately. + // Task.Factory.StartNew() allows specifying task scheduler to use. + Task.Factory.StartNewOnCurrentTaskSchedulerAsync(() => + { + this.OnDisableRntbdChannel?.Invoke(); + }) + .ContinueWith( + failedTask => + { + DefaultTrace.TraceError( + "RNTBD channel callback failed: {0}", + failedTask.Exception); + }, + default(CancellationToken), + TaskContinuationOptions.OnlyOnFaulted, + TaskScheduler.Current); + } + +#endregion + + public sealed class Options + { + private UserAgentContainer userAgent = null; + private TimeSpan openTimeout = TimeSpan.Zero; + private TimeSpan localRegionOpenTimeout = TimeSpan.Zero; + private TimeSpan timerPoolResolution = TimeSpan.Zero; + + public Options(TimeSpan requestTimeout) + { + Debug.Assert(requestTimeout > TimeSpan.Zero); + this.RequestTimeout = requestTimeout; + this.MaxChannels = ushort.MaxValue; + this.PartitionCount = 1; + this.MaxRequestsPerChannel = 30; + this.PortReuseMode = PortReuseMode.ReuseUnicastPort; + this.PortPoolReuseThreshold = 256; + this.PortPoolBindAttempts = 5; + this.ReceiveHangDetectionTime = TimeSpan.FromSeconds(65.0); + this.SendHangDetectionTime = TimeSpan.FromSeconds(10.0); + this.IdleTimeout = TimeSpan.FromSeconds(1800); + this.CallerId = RntbdConstants.CallerId.Anonymous; + this.EnableChannelMultiplexing = false; + this.MaxConcurrentOpeningConnectionCount = ushort.MaxValue; + this.DnsResolutionFunction = null; + this.DistributedTracingOptions = null; + } + + public TimeSpan RequestTimeout { get; private set; } + public int MaxChannels { get; set; } + public int PartitionCount { get; set; } + public int MaxRequestsPerChannel { get; set; } + public TimeSpan ReceiveHangDetectionTime { get; set; } + public TimeSpan SendHangDetectionTime { get; set; } + public TimeSpan IdleTimeout { get; set; } + public RntbdConstants.CallerId CallerId { get; set; } + public bool EnableChannelMultiplexing { get; set; } + + public Microsoft.Azure.Documents.MemoryStreamPool MemoryStreamPool { get; set; } + + public UserAgentContainer UserAgent + { + get + { + if (this.userAgent != null) + { + return this.userAgent; + } + this.userAgent = new UserAgentContainer(); + return this.userAgent; + } + set { this.userAgent = value; } + } + + public string CertificateHostNameOverride { get; set; } + + public IConnectionStateListener ConnectionStateListener { get; set; } + + public TimeSpan OpenTimeout + { + get + { + if (this.openTimeout > TimeSpan.Zero) + { + return this.openTimeout; + } + return this.RequestTimeout; + } + set { this.openTimeout = value; } + } + + public TimeSpan LocalRegionOpenTimeout + { + get + { + if (this.localRegionOpenTimeout > TimeSpan.Zero) + { + return this.localRegionOpenTimeout; + } + return this.OpenTimeout; + } + set { this.localRegionOpenTimeout = value; } + } + + public PortReuseMode PortReuseMode { get; set; } + + public int PortPoolReuseThreshold { get; internal set; } + + public int PortPoolBindAttempts { get; internal set; } + + public TimeSpan TimerPoolResolution + { + get + { + return Options.GetTimerPoolResolutionSeconds( + this.timerPoolResolution, this.RequestTimeout, this.openTimeout); + } + set { this.timerPoolResolution = value; } + } + + public int MaxConcurrentOpeningConnectionCount { get; set; } + + public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; internal set; } + + /// + /// Override for DNS resolution callbacks for RNTBD connections. + /// + public Func> DnsResolutionFunction { get; internal set; } + + /// + /// Distributed Tracing Options + /// + public DistributedTracingOptions DistributedTracingOptions { get; set; } + + public override string ToString() + { + StringBuilder s = new StringBuilder(); + s.AppendLine("Rntbd.TransportClient.Options"); + s.Append(" OpenTimeout: "); + s.AppendLine(this.OpenTimeout.ToString("c")); + s.Append(" RequestTimeout: "); + s.AppendLine(this.RequestTimeout.ToString("c")); + s.Append(" TimerPoolResolution: "); + s.AppendLine(this.TimerPoolResolution.ToString("c")); + s.Append(" MaxChannels: "); + s.AppendLine(this.MaxChannels.ToString(CultureInfo.InvariantCulture)); + s.Append(" PartitionCount: "); + s.AppendLine(this.PartitionCount.ToString(CultureInfo.InvariantCulture)); + s.Append(" MaxRequestsPerChannel: "); + s.AppendLine(this.MaxRequestsPerChannel.ToString(CultureInfo.InvariantCulture)); + s.Append(" ReceiveHangDetectionTime: "); + s.AppendLine(this.ReceiveHangDetectionTime.ToString("c")); + s.Append(" SendHangDetectionTime: "); + s.AppendLine(this.SendHangDetectionTime.ToString("c")); + s.Append(" IdleTimeout: "); + s.AppendLine(this.IdleTimeout.ToString("c")); + s.Append(" UserAgent: "); + s.Append(this.UserAgent.UserAgent); + s.Append(" Suffix: "); + s.AppendLine(this.UserAgent.Suffix); + s.Append(" CertificateHostNameOverride: "); + s.AppendLine(this.CertificateHostNameOverride); + s.Append(" LocalRegionTimeout: "); + s.AppendLine(this.LocalRegionOpenTimeout.ToString("c")); + s.Append(" EnableChannelMultiplexing: "); + s.AppendLine(this.EnableChannelMultiplexing.ToString()); + s.Append(" MaxConcurrentOpeningConnectionCount: "); + s.AppendLine(this.MaxConcurrentOpeningConnectionCount.ToString(CultureInfo.InvariantCulture)); + s.Append(" Use_RecyclableMemoryStream: "); + s.AppendLine(this.MemoryStreamPool != null ? bool.TrueString : bool.FalseString); + s.Append(" Use_CustomDnsResolution: "); + s.AppendLine(this.DnsResolutionFunction != null ? bool.TrueString : bool.FalseString); + s.Append(" IsDistributedTracingEnabled: "); +#if NETSTANDARD2_0_OR_GREATER + s.AppendLine(this.DistributedTracingOptions?.IsDistributedTracingEnabled.ToString()); +#else + s.AppendLine("false"); +#endif + return s.ToString(); + } + + private static TimeSpan GetTimerPoolResolutionSeconds( + TimeSpan timerPoolResolution, TimeSpan requestTimeout, TimeSpan openTimeout) + { + Debug.Assert(timerPoolResolution > TimeSpan.Zero || + openTimeout > TimeSpan.Zero || + requestTimeout > TimeSpan.Zero); + if (timerPoolResolution > TimeSpan.Zero && + timerPoolResolution < openTimeout && + timerPoolResolution < requestTimeout) + { + return timerPoolResolution; + } + if (openTimeout > TimeSpan.Zero && requestTimeout > TimeSpan.Zero) + { + return openTimeout < requestTimeout ? openTimeout : requestTimeout; + } + return openTimeout > TimeSpan.Zero ? openTimeout : requestTimeout; + } + + } + + internal static void SetTransportPerformanceCounters(TransportPerformanceCounters transportPerformanceCounters) + { + if (transportPerformanceCounters == null) + { + throw new ArgumentNullException(nameof(transportPerformanceCounters)); + } + + TransportClient.transportPerformanceCounters = transportPerformanceCounters; + } + + internal static TransportPerformanceCounters GetTransportPerformanceCounters() + { + return transportPerformanceCounters; + } + } +} From 039be0c983ec945f341c48c8271a7d5f822db5be Mon Sep 17 00:00:00 2001 From: "Nalu Tripician (from Dev Box)" Date: Thu, 2 May 2024 15:18:25 -0700 Subject: [PATCH 337/337] update direct --- .../Azure.Core/AppContextSwitchHelper.cs | 47 +++++++++++++++++++ .../IServiceConfigurationReaderExtension.cs | 16 +++++++ .../src/direct/IServiceRetryParams.cs | 15 ++++++ .../src/direct/PerformanceCounter.cs | 22 +++++++++ 4 files changed, 100 insertions(+) create mode 100644 Microsoft.Azure.Cosmos/src/direct/Azure.Core/AppContextSwitchHelper.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReaderExtension.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/IServiceRetryParams.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/PerformanceCounter.cs diff --git a/Microsoft.Azure.Cosmos/src/direct/Azure.Core/AppContextSwitchHelper.cs b/Microsoft.Azure.Cosmos/src/direct/Azure.Core/AppContextSwitchHelper.cs new file mode 100644 index 0000000000..ccef18f40c --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/Azure.Core/AppContextSwitchHelper.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +// This File is copied from Azure.Core repo i.e. https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/AppContextSwitchHelper.cs + +#nullable enable +#if NETSTANDARD2_0_OR_GREATER +namespace Azure.Core +{ + using System; + /// + /// Helper for interacting with AppConfig settings and their related Environment variable settings. + /// + internal static class AppContextSwitchHelper + { + /// + /// Determines if either an AppContext switch or its corresponding Environment Variable is set + /// + /// Name of the AppContext switch. + /// Name of the Environment variable. + /// If the AppContext switch has been set, returns the value of the switch. + /// If the AppContext switch has not been set, returns the value of the environment variable. + /// False if neither is set. + /// + public static bool GetConfigValue(string appContexSwitchName, string environmentVariableName) + { + // First check for the AppContext switch, giving it priority over the environment variable. + if (AppContext.TryGetSwitch(appContexSwitchName, out bool value)) + { + return value; + } + // AppContext switch wasn't used. Check the environment variable. + string? envVar = Environment.GetEnvironmentVariable(environmentVariableName); + if (envVar != null + && (envVar.Equals("true", StringComparison.OrdinalIgnoreCase) + || envVar.Equals("1", StringComparison.OrdinalIgnoreCase))) + { + return true; + } + + // Default to false. + return false; + } + } +} +#endif \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReaderExtension.cs b/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReaderExtension.cs new file mode 100644 index 0000000000..c947dedb9a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/IServiceConfigurationReaderExtension.cs @@ -0,0 +1,16 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Interface extension for IServiceConfigurationReader, should be consolidated with IServiceConfigurationReader in the future + /// This is needed because the way compute uses SDK is using a V3 OSS clone of our public v3 repo. + /// So, the moment you change some interface in the Direct/ Shared Files, it immediately gets reflected in the OSS code path + /// + internal interface IServiceConfigurationReaderExtension : IServiceConfigurationReader + { + IServiceRetryParams TryGetServiceRetryParams(DocumentServiceRequest documentServiceRequest); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/IServiceRetryParams.cs b/Microsoft.Azure.Cosmos/src/direct/IServiceRetryParams.cs new file mode 100644 index 0000000000..4c800d114e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/IServiceRetryParams.cs @@ -0,0 +1,15 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + /// + /// Retry params that every service can configure + /// Add more api's that control retry as needed, currently only exposes overall timeout + /// + internal interface IServiceRetryParams + { + public bool TryGetRetryTimeoutInSeconds(out int retryTimeoutInSeconds); + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/PerformanceCounter.cs b/Microsoft.Azure.Cosmos/src/direct/PerformanceCounter.cs new file mode 100644 index 0000000000..ec3d0cd9b0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/PerformanceCounter.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents.Test.Analytics +{ + using System; + + [Serializable] + public sealed class PerformanceCounter + { + public string CounterName { get; set; } + + public double Average { get; set; } + + public double Percentile10 { get; set; } + + public double Percentile90 { get; set; } + + public double Percentile99 { get; set; } + } +}
@@ -45,17 +82,8 @@ public MetricsCollectorProvider(BenchmarkConfig config, MeterProvider meterProvi /// Benchmark configuration. /// Metrics collector. /// Thrown if provided benchmark operation is not covered supported to collect metrics. - public IMetricsCollector GetMetricsCollector(IBenchmarkOperation benchmarkOperation, BenchmarkConfig config) + public IMetricsCollector GetMetricsCollector(IBenchmarkOperation benchmarkOperation) { - MetricCollectionWindow metricCollectionWindow = this.metricCollectionWindow; - - // Reset metricCollectionWindow and flush. - if (!metricCollectionWindow.IsValid) - { - this.meterProvider.ForceFlush(); - metricCollectionWindow.Reset(config); - } - return benchmarkOperation.OperationType switch { BenchmarkOperationType.Insert => this.insertOperationMetricsCollector, diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs index 2348d4a995..d32052e3fe 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs @@ -43,6 +43,7 @@ await warmupExecutor.ExecuteAsync( benchmarkConfig, metricsCollectorProvider); + Utility.TeePrint("Starting execution {0} tasks", serialExecutorConcurrency); IExecutor[] executors = new IExecutor[serialExecutorConcurrency]; for (int i = 0; i < serialExecutorConcurrency; i++) { @@ -113,9 +114,8 @@ private async Task LogOutputStats( using (ConsoleColorContext ct = new ConsoleColorContext(ConsoleColor.Green)) { - Console.WriteLine(); - Console.WriteLine("Summary:"); - Console.WriteLine("--------------------------------------------------------------------- "); + Utility.TeeTraceInformation("Summary:"); + Utility.TeeTraceInformation("--------------------------------------------------------------------- "); lastSummary.Print(lastSummary.failedOpsCount + lastSummary.successfulOpsCount); // Skip first 5 and last 5 counters as outliers @@ -128,7 +128,6 @@ private async Task LogOutputStats( if (summaryCounters.Length > 10) { - Console.WriteLine(); Utility.TeeTraceInformation("After Excluding outliers"); runSummary.Top10PercentAverageRps = Math.Round(summaryCounters.Take((int)(0.1 * summaryCounters.Length)).Average(), 0); @@ -160,7 +159,7 @@ private async Task LogOutputStats( Utility.TeeTraceInformation("Please adjust ItemCount high to run of at-least 1M"); } - Console.WriteLine("--------------------------------------------------------------------- "); + Utility.TeeTraceInformation("--------------------------------------------------------------------- "); return runSummary; } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs index b33218f65b..3bb84e26fa 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs @@ -50,8 +50,7 @@ public async Task ExecuteAsync( int currentIterationCount = 0; do { - IMetricsCollector metricsCollector = metricsCollectorProvider.GetMetricsCollector(this.operation, benchmarkConfig); - + IMetricsCollector metricsCollector = metricsCollectorProvider.GetMetricsCollector(this.operation); OperationResult? operationResult = null; await this.operation.PrepareAsync(); @@ -115,7 +114,8 @@ public async Task ExecuteAsync( } catch (Exception e) { - Trace.TraceInformation($"Error: {e.Message}"); + Utility.TraceError("Error:", e); + } finally { diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs index fff2acac3e..4f8785860d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs @@ -63,11 +63,11 @@ public void Dispose() if(this.isFailed) { - this.recordSuccessOpLatencyAction?.Invoke(TimeSpan.FromMilliseconds(this.stopwatch.Elapsed.TotalMilliseconds)); + this.recordSuccessOpLatencyAction?.Invoke(this.stopwatch.Elapsed); } else { - this.recordSuccessOpLatencyAction?.Invoke(TimeSpan.FromMilliseconds(this.stopwatch.Elapsed.TotalMilliseconds)); + this.recordSuccessOpLatencyAction?.Invoke(this.stopwatch.Elapsed); } } @@ -76,7 +76,9 @@ public void Dispose() operationResult.DatabseName, operationResult.ContainerName, (int)this.stopwatch.ElapsedMilliseconds, - operationResult.LazyDiagnostics); + operationResult.LazyDiagnostics, + this.benchmarkConfig.DiagnosticLatencyThresholdInMs); + } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs index 2e7687932f..744d53f2af 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs @@ -7,6 +7,7 @@ namespace CosmosBenchmark using System; using System.Collections.Generic; using System.Diagnostics; + using System.Diagnostics.Tracing; using System.IO; using System.Linq; using System.Net; @@ -15,6 +16,7 @@ namespace CosmosBenchmark using System.Threading; using System.Threading.Tasks; using Azure.Monitor.OpenTelemetry.Exporter; + using CosmosBenchmark.Fx; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; @@ -44,6 +46,12 @@ public static async Task Main(string[] args) ThreadPool.SetMinThreads(config.MinThreadPoolSize, config.MinThreadPoolSize); + DiagnosticDataListener diagnosticDataListener = null; + if (!string.IsNullOrEmpty(config.DiagnosticsStorageConnectionString)) + { + diagnosticDataListener = new DiagnosticDataListener(config); + } + if (config.EnableLatencyPercentiles) { TelemetrySpan.IncludePercentile = true; @@ -55,13 +63,22 @@ public static async Task Main(string[] args) Program program = new Program(); RunSummary runSummary = await program.ExecuteAsync(config, metricsCollectorProvider); + + if (!string.IsNullOrEmpty(config.DiagnosticsStorageConnectionString)) + { + diagnosticDataListener.UploadDiagnostcs(); + } + } + catch (Exception e) + { + Utility.TeeTraceInformation("Exception ocured:" + e.ToString()); } finally { - Console.WriteLine($"{nameof(CosmosBenchmark)} completed successfully."); + Utility.TeeTraceInformation($"{nameof(CosmosBenchmark)} completed successfully."); if (Debugger.IsAttached) { - Console.WriteLine("Press any key to exit..."); + Utility.TeeTraceInformation("Press any key to exit..."); Console.ReadLine(); } } @@ -113,11 +130,11 @@ private static async Task AddAzureInfoToRunSummary() JObject jObject = JObject.Parse(jsonVmInfo); RunSummary.AzureVmInfo = jObject; RunSummary.Location = jObject["compute"]["location"].ToString(); - Console.WriteLine($"Azure VM Location:{RunSummary.Location}"); + Utility.TeeTraceInformation($"Azure VM Location:{RunSummary.Location}"); } - catch(Exception e) + catch (Exception e) { - Console.WriteLine("Failed to get Azure VM info:" + e.ToString()); + Utility.TeeTraceInformation("Failed to get Azure VM info:" + e.ToString()); } } @@ -151,11 +168,15 @@ private async Task ExecuteAsync(BenchmarkConfig config, $"Container {config.Container} must have a configured throughput."); } - Console.WriteLine($"Using container {config.Container} with {currentContainerThroughput} RU/s"); + Container resultContainer = await GetResultContainer(config, cosmosClient); + + BenchmarkProgress benchmarkProgressItem = await CreateBenchmarkProgressItem(resultContainer); + + Utility.TeeTraceInformation($"Using container {config.Container} with {currentContainerThroughput} RU/s"); int taskCount = config.GetTaskCount(currentContainerThroughput.Value); - Console.WriteLine("Starting Inserts with {0} tasks", taskCount); - Console.WriteLine(); + Utility.TeePrint("Starting Inserts with {0} tasks", taskCount); + string partitionKeyPath = containerResponse.Resource.PartitionKeyPath; int opsPerTask = config.ItemCount / taskCount; @@ -184,7 +205,7 @@ private async Task ExecuteAsync(BenchmarkConfig config, if (config.CleanupOnFinish) { - Console.WriteLine($"Deleting Database {config.Database}"); + Utility.TeeTraceInformation($"Deleting Database {config.Database}"); await database.DeleteStreamAsync(); } @@ -196,8 +217,11 @@ private async Task ExecuteAsync(BenchmarkConfig config, } runSummary.ConsistencyLevel = consistencyLevel; + + BenchmarkProgress benchmarkProgress = await CompleteBenchmarkProgressStatus(benchmarkProgressItem, resultContainer); if (config.PublishResults) { + Utility.TeeTraceInformation("Publishing results"); runSummary.Diagnostics = CosmosDiagnosticsLogger.GetDiagnostics(); await this.PublishResults( config, @@ -228,6 +252,7 @@ private async Task PublishResults( Container resultContainer = cosmosClient.GetContainer(config.ResultsDatabase, config.ResultsContainer); await resultContainer.CreateItemAsync(runSummary, new PartitionKey(runSummary.pk)); } + } private Func GetBenchmarkFactory( @@ -301,24 +326,60 @@ private static async Task CreatePartitionedContainerAsync(Ben { Microsoft.Azure.Cosmos.Database database = await cosmosClient.CreateDatabaseIfNotExistsAsync(options.Database); - Container container = database.GetContainer(options.Container); + // Show user cost of running this test + double estimatedCostPerMonth = 0.06 * options.Throughput; + double estimatedCostPerHour = estimatedCostPerMonth / (24 * 30); + Utility.TeeTraceInformation($"The container will cost an estimated ${Math.Round(estimatedCostPerHour, 2)} per hour (${Math.Round(estimatedCostPerMonth, 2)} per month)"); + Utility.TeeTraceInformation("Press enter to continue ..."); + Console.ReadLine(); - try - { - return await container.ReadContainerAsync(); - } - catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound) + string partitionKeyPath = options.PartitionKeyPath; + return await database.CreateContainerIfNotExistsAsync(options.Container, partitionKeyPath, options.Throughput); + } + + /// + /// Creating a progress item in ComsosDb when the benchmark start + /// + /// An instance of that represents operations performed on a database container. + private static async Task CreateBenchmarkProgressItem(Container resultContainer) + { + BenchmarkProgress benchmarkProgress = new BenchmarkProgress { - // Show user cost of running this test - double estimatedCostPerMonth = 0.06 * options.Throughput; - double estimatedCostPerHour = estimatedCostPerMonth / (24 * 30); - Console.WriteLine($"The container will cost an estimated ${Math.Round(estimatedCostPerHour, 2)} per hour (${Math.Round(estimatedCostPerMonth, 2)} per month)"); - Console.WriteLine("Press enter to continue ..."); - Console.ReadLine(); - - string partitionKeyPath = options.PartitionKeyPath; - return await database.CreateContainerAsync(options.Container, partitionKeyPath, options.Throughput); - } + id = Environment.MachineName, + MachineName = Environment.MachineName, + JobStatus = "STARTED", + JobStartTime = DateTime.Now + }; + + ItemResponse itemResponse = await resultContainer.UpsertItemAsync( + benchmarkProgress, new PartitionKey(benchmarkProgress.id)); + + return itemResponse.Resource; + } + + /// + /// Change a progress item status to Complete in ComsosDb when the benchmark compleated + /// + /// An instance of that represents operations performed on a database container. + /// An instance of that represents the document to be modified. + public static async Task CompleteBenchmarkProgressStatus(BenchmarkProgress benchmarkProgress, Container resultContainer) + { + benchmarkProgress.JobStatus = "COMPLETED"; + benchmarkProgress.JobEndTime = DateTime.Now; + ItemResponse itemResponse = await resultContainer.UpsertItemAsync(benchmarkProgress); + return itemResponse.Resource; + } + + /// + /// Configure and prepare the Cosmos DB Container instance for the result container. + /// + /// An instance of containing the benchmark tool input parameters. + /// An instance of that represents operations performed on a CosmosDb database. + private static async Task GetResultContainer(BenchmarkConfig config, CosmosClient cosmosClient) + { + Database database = cosmosClient.GetDatabase(config.ResultsDatabase ?? config.Database); + ContainerResponse containerResponse = await database.CreateContainerIfNotExistsAsync(id: config.ResultsContainer, partitionKeyPath: "/id"); + return containerResponse.Container; } private static void ClearCoreSdkListeners() diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md index 8aac52daad..5a2bac1937 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md @@ -54,6 +54,7 @@ cd 'azure-cosmos-dotnet-v3/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark' dotnet build --configuration Release -p:"OSSProjectRef=true;ShouldUnsetParentConfigurationAndPlatform=false" ``` + For PerfRuns with reports (INTERNAL) ``` @@ -127,3 +128,7 @@ Copyright (C) 2019 CosmosBenchmark ## Running on Azure If you want to quickly get results, you can use our [guide to leverage Azure Container Instances](./AzureContainerInstances/README.md) to execute the benchmarks in any number of Azure regions with very little setup required. + +## Running on Azure VM + +If you want to execute benchmarking on multiple machines with one ARM Template, you can use our [guide to leverage Azure Virtual Machines](./AzureVmBenchmark/README.md). diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Utility.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Utility.cs index d743bd391d..6d278f3d3a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Utility.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Utility.cs @@ -16,6 +16,12 @@ public static void TeeTraceInformation(string payload) Trace.TraceInformation(payload); } + public static void TraceError(string payload, Exception e) + { + Console.WriteLine($"{payload}: {e.Message} {e.StackTrace}"); + Trace.TraceError(payload); + } + public static void TeePrint(string format, params object[] arg) { string payload = string.Format(format, arg); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/CosmosBenchmarkTests.csproj b/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/CosmosBenchmarkTests.csproj new file mode 100644 index 0000000000..7da26827a5 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/CosmosBenchmarkTests.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + + + + + + + + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/Fx/DiagnosticDataListenerTests.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/Fx/DiagnosticDataListenerTests.cs new file mode 100644 index 0000000000..9c453cf2e6 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CosmosBenchmarkTests/Fx/DiagnosticDataListenerTests.cs @@ -0,0 +1,54 @@ +namespace CosmosBenchmark.Fx.Tests +{ + using CosmosBenchmark.Fx; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using System.IO; + using Moq; + using Azure.Storage.Blobs; + + [TestClass] + public class DiagnosticDataListenerTests + { + private DiagnosticDataListener listener; + + [TestInitialize] + public void Setup() + { + this.listener = new DiagnosticDataListener(); + } + + [TestCleanup] + public void Cleanup() + { + string[] diagnosticFiles = Directory.GetFiles(".", "BenchmarkDiagnostics.out*"); + foreach (string file in diagnosticFiles) + { + File.Delete(file); + } + } + + + /// + /// The scenario tested here is to ensure + /// that all created files with captured diagnostic + /// data are successfully uploaded to the Blob storage + /// + [TestMethod] + public void UploadDiagnostics_WhenFilesExist_ShouldUploadFilesToBlobStorage() + { + for (int i = 0; i < 10; i++) + { + string fileName = $"BenchmarkDiagnostics.out-{i}"; + File.Create(fileName).Close(); + } + int filesCount = Directory.GetFiles(".", $"{DiagnosticDataListener.DiagnosticsFileName}*").Length; + + Mock mockContainer = new Mock(); + Mock mockClient = new Mock(); + mockContainer.Setup(mock => mock.GetBlobClient(It.IsAny())).Returns(mockClient.Object); + + this.listener.UploadDiagnostcs(mockContainer.Object, "prefix"); + mockClient.Verify(mock => mock.Upload(It.IsAny(), true, default), Times.Exactly(filesCount)); + } + } +} From 3aced24beac2bc63f0ad84944bcb87ea3429d9a6 Mon Sep 17 00:00:00 2001 From: David Chaava Date: Tue, 29 Aug 2023 21:04:53 +0200 Subject: [PATCH 182/337] [Internal] Benchmark tool: Adds feature to the dashboard that generate plots queries for metrics with a workload name prefix, depending on the benchmark workload type. #4048 (#4053) * Merge remote-tracking branch 'origin/master' into users/v-dchaava/benchmark-diagnostics/3889 * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md * add metrics prefixes * fix chart metrics names * fix dashboard queries according selected workload type --------- Co-authored-by: David Chaava --- .../Benchmark/AzureVmBenchmark/azuredeploy.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json index 347857cf82..594d4c9756 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json @@ -209,10 +209,11 @@ "customScriptUrl": "[concat('https://raw.githubusercontent.com/Azure/azure-cosmos-dotnet-v3/',parameters('benchmarkingToolsBranchName'),'/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh')]", "vmScriptExtensionScriptName": "execute.sh", "convertedDatetime": "[dateTimeFromEpoch(parameters('startDate'))]", + "metricsPrefix" : "[if(startsWith(parameters('workloadType'), 'Read'), 'Read', if(startsWith(parameters('workloadType'), 'Query'), 'Query', if(startsWith(parameters('workloadType'), 'Insert'), 'Insert', '')))]", "appInsightsResourceIds": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', resourceGroup().name, '/providers/microsoft.insights/components/', parameters('applicationInsightsName'))]", - "chart0Expression": "[concat('customMetrics\n| where name == \"ReadOperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 50),\n percentile(value, 75),\n percentile(value, 90),\n percentile(value, 95)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", - "chart1Expression": "[concat('customMetrics\n| where name == \"ReadOperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 99),\n percentile(value, 99.9),\n percentile(value, 99.99)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", - "chart2Expression": "[concat('customMetrics\n| where name == \"ReadOperationRps\" and timestamp > ago(1d)\n| summarize\n avg(value)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]" + "chart0Expression": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 50),\n percentile(value, 75),\n percentile(value, 90),\n percentile(value, 95)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", + "chart1Expression": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationLatencyInMs\" and timestamp > ago(1d)\n| summarize\n percentile(value, 99),\n percentile(value, 99.9),\n percentile(value, 99.99)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]", + "chart2Expression": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationRps\" and timestamp > ago(1d)\n| summarize\n avg(value)\n by ts = bin(timestamp, ', parameters('metricsReportingIntervalInSec'), 's)\n| render timechart \n\n')]" }, "resources": [ @@ -776,7 +777,7 @@ }, { "name": "Query", - "value": "customMetrics\n| where name == \"ReadOperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n", + "value": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n')]", "isOptional": true }, { @@ -834,7 +835,7 @@ "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", "settings": { "content": { - "Query": "customMetrics\n| where name == \"ReadOperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n", + "Query": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationFailure\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n')]", "Dimensions": { "xAxis": { "name": "ts", @@ -903,7 +904,7 @@ }, { "name": "Query", - "value": "customMetrics\n| where name == \"ReadOperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n", + "value": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n')]", "isOptional": true }, { @@ -961,7 +962,7 @@ "type": "Extension/Microsoft_OperationsManagementSuite_Workspace/PartType/LogsDashboardPart", "settings": { "content": { - "Query": "customMetrics\n| where name == \"ReadOperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n", + "Query": "[concat('customMetrics\n| where name == \"', variables('metricsPrefix'), 'OperationSuccess\" and timestamp > ago(1d)\n| summarize\n sum(value)\n by ts = bin(timestamp, 1s)\n | render timechart\n\n')]", "Dimensions": { "xAxis": { "name": "ts", From c72ebc85746ea0c0c0ee3689e83ad23027751e2a Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Thu, 31 Aug 2023 23:25:30 +0530 Subject: [PATCH 183/337] [Internal] Client Telemetry: Adds client config api call to get latest flag status (#4050) * first draft * tets fix * fix dependent projects * reduce refresh time in tests * fix tests and added comments * fix diagnostic handler fix * fix test * adding test * ret pushmove console * fix test * provide options to enable/disable this featire in benchmark and ctl proj * updated trace message Co-authored-by: Matias Quaranta * remove import * updated traces Co-authored-by: Matias Quaranta * test fix * remove null assignment * fix test --------- Co-authored-by: Matias Quaranta --- .../Tools/Benchmark/BenchmarkConfig.cs | 40 ++----- .../Tools/CTL/CTLConfig.cs | 11 +- .../Tools/CTL/Program.cs | 14 --- .../src/ConnectionPolicy.cs | 5 +- .../src/Handler/DiagnosticsHandler.cs | 4 +- .../src/Handler/DiagnosticsHandlerHelper.cs | 59 +++++++--- .../Settings/AccountClientConfiguration.cs | 29 +++++ .../Settings/ClientTelemetryConfiguration.cs | 27 +++++ .../src/Telemetry/ClientTelemetry.cs | 16 ++- .../src/Telemetry/ClientTelemetryOptions.cs | 67 +---------- .../src/Telemetry/ClientTelemetryProcessor.cs | 12 +- .../src/Telemetry/TelemetryToServiceHelper.cs | 110 ++++++++++++++---- .../ClientSideRequestStatisticsTraceDatum.cs | 2 +- .../ClientTelemetryReleaseTests.cs | 11 +- .../ClientTelemetryTests.cs | 27 ++++- .../ClientTelemetryTestsBase.cs | 74 ++++-------- .../SynchronizationContextTests.cs | 43 +++++-- .../Utils/HttpHandlerHelper.cs | 2 + .../Utils/Util.cs | 14 --- .../Mocks/HttpHandlerHelper.cs | 67 +++++++++++ .../Mocks/MockDocumentClient.cs | 42 ++++++- .../DiagnosticHandlerHelperTests.cs | 75 ++++++++++++ .../Telemetry/ClientTelemetryTests.cs | 22 +--- 23 files changed, 500 insertions(+), 273 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/AccountClientConfiguration.cs create mode 100644 Microsoft.Azure.Cosmos/src/Resource/Settings/ClientTelemetryConfiguration.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/HttpHandlerHelper.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index f69c305096..e3ec5c23bb 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -10,6 +10,7 @@ namespace CosmosBenchmark using System.Linq; using System.Runtime; using CommandLine; + using Microsoft.Azure.Cosmos.Telemetry; using Microsoft.Azure.Documents.Client; using Newtonsoft.Json; @@ -102,18 +103,12 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Disable core SDK logging")] public bool DisableCoreSdkLogging { get; set; } - [Option(Required = false, HelpText = "Enable Client Telemetry")] - public bool EnableTelemetry { get; set; } - [Option(Required = false, HelpText = "Enable Distributed Tracing")] public bool EnableDistributedTracing { get; set; } [Option(Required = false, HelpText = "Client Telemetry Schedule in Seconds")] public int TelemetryScheduleInSec { get; set; } - [Option(Required = false, HelpText = "Client Telemetry Endpoint")] - public string TelemetryEndpoint { get; set; } - [Option(Required = false, HelpText = "Endpoint to publish results to")] public string ResultsEndpoint { get; set; } @@ -143,6 +138,9 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Application Insights connection string")] public string AppInsightsConnectionString { get; set; } + [Option(Required = false, HelpText = "Enable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] + public bool EnableClientTelemetry { get; set; } = true; + internal int GetTaskCount(int containerThroughput) { int taskCount = this.DegreeOfParallelism; @@ -210,35 +208,21 @@ private string GetUserAgentPrefix() internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKey) { + // Overwrite the default timespan if configured + if(this.TelemetryScheduleInSec > 0) + { + ClientTelemetryOptions.DefaultIntervalForTelemetryJob = TimeSpan.FromSeconds(this.TelemetryScheduleInSec); + } + Microsoft.Azure.Cosmos.CosmosClientOptions clientOptions = new Microsoft.Azure.Cosmos.CosmosClientOptions() { ApplicationName = this.GetUserAgentPrefix(), MaxRetryAttemptsOnRateLimitedRequests = 0, MaxRequestsPerTcpConnection = this.MaxRequestsPerTcpConnection, - MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint + MaxTcpConnectionsPerEndpoint = this.MaxTcpConnectionsPerEndpoint, + EnableClientTelemetry = this.EnableClientTelemetry }; - if (this.EnableTelemetry) - { - Environment.SetEnvironmentVariable( - Microsoft.Azure.Cosmos.Telemetry.ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, - "true"); - - if (this.TelemetryScheduleInSec > 0) - { - Environment.SetEnvironmentVariable( - Microsoft.Azure.Cosmos.Telemetry.ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, - Convert.ToString(this.TelemetryScheduleInSec)); - } - - if (!string.IsNullOrEmpty(this.TelemetryEndpoint)) - { - Environment.SetEnvironmentVariable( - Microsoft.Azure.Cosmos.Telemetry.ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, - this.TelemetryEndpoint); - } - } - if (!string.IsNullOrWhiteSpace(this.ConsistencyLevel)) { clientOptions.ConsistencyLevel = (Microsoft.Azure.Cosmos.ConsistencyLevel)Enum.Parse(typeof(Microsoft.Azure.Cosmos.ConsistencyLevel), this.ConsistencyLevel, ignoreCase: true); diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs index 05064003ce..98bba7b700 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs @@ -97,18 +97,15 @@ public string DiagnosticsThresholdDuration [Option("ctl_logging_context", Required = false, HelpText = "Defines a custom context to use on metrics")] public string LogginContext { get; set; } = string.Empty; - [Option("ctl_telemetry_endpoint", Required = false, HelpText = "telemetry juno end point")] - public string TelemetryEndpoint { get; set; } - - [Option("ctl_telemetry_schedule_in_sec", Required = false, HelpText = "telemetry task schedule time in sec")] - public string TelemetryScheduleInSeconds { get; set; } - [Option("ctl_reservoir_type", Required = false, HelpText = "Defines the reservoir type. Valid values are: Uniform, SlidingWindow and ExponentialDecay. The default value is SlidingWindow.")] public ReservoirTypes ReservoirType { get; set; } = ReservoirTypes.SlidingWindow; [Option("ctl_reservoir_sample_size", Required = false, HelpText = "The reservoir sample size.")] public int ReservoirSampleSize { get; set; } = 1028; + [Option("ctl_enable_client_telemetry", Required = false, HelpText = "Enable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] + public bool EnableClientTelemetry { get; set; } = true; + internal TimeSpan RunningTimeDurationAsTimespan { get; private set; } = TimeSpan.FromHours(10); internal TimeSpan DiagnosticsThresholdDurationAsTimespan { get; private set; } = TimeSpan.FromSeconds(60); @@ -133,7 +130,7 @@ internal CosmosClient CreateCosmosClient() CosmosClientOptions clientOptions = new CosmosClientOptions() { ApplicationName = CTLConfig.UserAgentSuffix, - EnableClientTelemetry = true + EnableClientTelemetry = this.EnableClientTelemetry }; if (this.UseGatewayMode) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Program.cs index 62f1eb913f..b42f651df1 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/Program.cs @@ -29,8 +29,6 @@ public static async Task Main(string[] args) { CTLConfig config = CTLConfig.From(args); - SetEnvironmentVariables(config); - if (config.OutputEventTraces) { EnableTraceSourcesToConsole(); @@ -54,12 +52,6 @@ await scenario.InitializeAsync( logger.LogInformation("Initialization completed."); - if(client.ClientOptions.EnableClientTelemetry.GetValueOrDefault()) { - logger.LogInformation("Telemetry is enabled for CTL."); - } else { - logger.LogInformation("Telemetry is disabled for CTL."); - } - List tasks = new List { scenario.RunAsync( @@ -148,12 +140,6 @@ await scenario.InitializeAsync( } } - private static void SetEnvironmentVariables(CTLConfig config) - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, config.TelemetryEndpoint); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, config.TelemetryScheduleInSeconds); - } - private static IMetricsRoot ConfigureReporting( CTLConfig config, ILogger logger) diff --git a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs index c8c1d9db93..8451918e9b 100644 --- a/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ConnectionPolicy.cs @@ -48,7 +48,7 @@ public ConnectionPolicy() this.MaxConnectionLimit = defaultMaxConcurrentConnectionLimit; this.RetryOptions = new RetryOptions(); this.EnableReadRequestsFallback = null; - this.EnableClientTelemetry = ClientTelemetryOptions.IsClientTelemetryEnabled(); + this.EnableClientTelemetry = false; // by default feature flag is off this.ServerCertificateCustomValidationCallback = null; } @@ -211,6 +211,9 @@ public bool EnableTcpConnectionEndpointRediscovery set; } + /// + /// Gets or sets the flag to enable client telemetry feature. + /// internal bool EnableClientTelemetry { get; diff --git a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandler.cs b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandler.cs index f361987f92..de93fca27b 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandler.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandler.cs @@ -4,6 +4,7 @@ namespace Microsoft.Azure.Cosmos.Handlers { + using System; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Handler; @@ -25,7 +26,8 @@ public override async Task SendAsync( ResponseMessage responseMessage = await base.SendAsync(request, cancellationToken); // Record the diagnostics on the response to get the CPU of when the request was executing - SystemUsageHistory systemUsageHistory = DiagnosticsHandlerHelper.Instance.GetDiagnosticsSystemHistory(); + SystemUsageHistory systemUsageHistory = DiagnosticsHandlerHelper.GetInstance().GetDiagnosticsSystemHistory(); + if (systemUsageHistory != null) { request.Trace.AddDatum( diff --git a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs index 1007234125..cdc3c2bac3 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs @@ -8,7 +8,6 @@ namespace Microsoft.Azure.Cosmos.Handler using System.Collections.Generic; using Documents.Rntbd; using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.Telemetry; /// /// This is a helper class that creates a single static instance to avoid each @@ -22,34 +21,69 @@ internal class DiagnosticsHandlerHelper private const string Telemetrykey = "telemetry"; public static readonly TimeSpan DiagnosticsRefreshInterval = TimeSpan.FromSeconds(10); - private readonly SystemUsageRecorder diagnosticSystemUsageRecorder = new SystemUsageRecorder( + private static readonly SystemUsageRecorder DiagnosticSystemUsageRecorder = new SystemUsageRecorder( identifier: Diagnostickey, historyLength: 6, refreshInterval: DiagnosticsHandlerHelper.DiagnosticsRefreshInterval); private static readonly TimeSpan ClientTelemetryRefreshInterval = TimeSpan.FromSeconds(5); - private readonly SystemUsageRecorder telemetrySystemUsageRecorder = new SystemUsageRecorder( + private static readonly SystemUsageRecorder TelemetrySystemUsageRecorder = new SystemUsageRecorder( identifier: Telemetrykey, historyLength: 120, refreshInterval: DiagnosticsHandlerHelper.ClientTelemetryRefreshInterval); - private static bool isDiagnosticsMonitoringEnabled = false; - private static bool isTelemetryMonitoringEnabled = false; - /// /// Singleton to make sure only one instance of DiagnosticHandlerHelper is there. /// The system usage collection is disabled for internal builds so it is set to null to avoid /// compute for accidentally creating an instance or trying to use it. /// - public static readonly DiagnosticsHandlerHelper Instance = + private static DiagnosticsHandlerHelper Instance = #if INTERNAL null; #else new DiagnosticsHandlerHelper(); #endif + private static bool isDiagnosticsMonitoringEnabled; + private static bool isTelemetryMonitoringEnabled; + private readonly SystemUsageMonitor systemUsageMonitor = null; + public static DiagnosticsHandlerHelper GetInstance() + { + return DiagnosticsHandlerHelper.Instance; + } + + /// + /// Restart the monitor with client telemetry recorder if telemetry is enabled + /// + /// + public static void Refresh(bool isClientTelemetryEnabled) + { + if (isClientTelemetryEnabled != DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled) + { + DiagnosticsHandlerHelper.Instance.StopSystemMonitor(); + + // Update telemetry flag + DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled = isClientTelemetryEnabled; + + // Create new instance, it will start a new system monitor job + DiagnosticsHandlerHelper.Instance = new DiagnosticsHandlerHelper(); + } + } + + private void StopSystemMonitor() + { + try + { + this.systemUsageMonitor?.Dispose(); + } + catch (ObjectDisposedException ex) + { + DefaultTrace.TraceError($"Error while stopping system usage monitor. {0} ", ex); + } + } + /// /// Start System Usage Monitor with Diagnostic and Telemetry Recorder if Telemetry is enabled /// Otherwise Start System Usage Monitor with only Diagnostic Recorder @@ -61,16 +95,14 @@ private DiagnosticsHandlerHelper() // If the CPU monitor fails for some reason don't block the application try { - DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled = ClientTelemetryOptions.IsClientTelemetryEnabled(); - List recorders = new List() { - this.diagnosticSystemUsageRecorder, + DiagnosticsHandlerHelper.DiagnosticSystemUsageRecorder, }; if (DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled) { - recorders.Add(this.telemetrySystemUsageRecorder); + recorders.Add(DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder); } this.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(recorders); @@ -82,7 +114,6 @@ private DiagnosticsHandlerHelper() DefaultTrace.TraceError(ex.Message); DiagnosticsHandlerHelper.isDiagnosticsMonitoringEnabled = false; - DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled = false; } } @@ -99,7 +130,7 @@ public SystemUsageHistory GetDiagnosticsSystemHistory() try { - return this.diagnosticSystemUsageRecorder.Data; + return DiagnosticsHandlerHelper.DiagnosticSystemUsageRecorder.Data; } catch (Exception ex) { @@ -123,7 +154,7 @@ public SystemUsageHistory GetClientTelemetrySystemHistory() try { - return this.telemetrySystemUsageRecorder.Data; + return DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder.Data; } catch (Exception ex) { diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/AccountClientConfiguration.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/AccountClientConfiguration.cs new file mode 100644 index 0000000000..fd7d125dac --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/AccountClientConfiguration.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + internal class AccountClientConfiguration + { + [JsonProperty(PropertyName = Constants.Properties.ClientTelemetryConfiguration)] + public ClientTelemetryConfiguration ClientTelemetryConfiguration { get; set; } + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + + internal bool IsClientTelemetryEnabled() + { + return this.ClientTelemetryConfiguration.IsEnabled && this.ClientTelemetryConfiguration.Endpoint != null; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientTelemetryConfiguration.cs b/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientTelemetryConfiguration.cs new file mode 100644 index 0000000000..3229b69fa2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Resource/Settings/ClientTelemetryConfiguration.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + + internal class ClientTelemetryConfiguration + { + [JsonProperty(PropertyName = Constants.Properties.ClientTelemetryEnabled)] + public bool IsEnabled { get; set; } + + [JsonProperty(PropertyName = Constants.Properties.ClientTelemetryEndpoint)] + public string Endpoint { get; set; } + + /// + /// This contains additional values for scenarios where the SDK is not aware of new fields. + /// This ensures that if resource is read and updated none of the fields will be lost in the process. + /// + [JsonExtensionData] + internal IDictionary AdditionalProperties { get; private set; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs index 2dfcbab496..8460998711 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetry.cs @@ -26,11 +26,12 @@ namespace Microsoft.Azure.Cosmos.Telemetry /// internal class ClientTelemetry : IDisposable { - private static readonly TimeSpan observingWindow = ClientTelemetryOptions.GetScheduledTimeSpan(); + private static readonly TimeSpan observingWindow = ClientTelemetryOptions.DefaultIntervalForTelemetryJob; private readonly ClientTelemetryProperties clientTelemetryInfo; private readonly ClientTelemetryProcessor processor; private readonly DiagnosticsHandlerHelper diagnosticsHelper; + private readonly string endpointUrl; private readonly NetworkDataRecorder networkDataRecorder; private readonly CancellationTokenSource cancellationTokenSource; @@ -63,6 +64,7 @@ internal ClientTelemetry() /// /// /// + /// /// ClientTelemetry public static ClientTelemetry CreateAndStartBackgroundTelemetry( string clientId, @@ -72,7 +74,8 @@ public static ClientTelemetry CreateAndStartBackgroundTelemetry( AuthorizationTokenProvider authorizationTokenProvider, DiagnosticsHandlerHelper diagnosticsHelper, IReadOnlyList preferredRegions, - GlobalEndpointManager globalEndpointManager) + GlobalEndpointManager globalEndpointManager, + string endpointUrl ) { DefaultTrace.TraceInformation("Initiating telemetry with background task."); @@ -84,7 +87,8 @@ public static ClientTelemetry CreateAndStartBackgroundTelemetry( authorizationTokenProvider, diagnosticsHelper, preferredRegions, - globalEndpointManager); + globalEndpointManager, + endpointUrl); clientTelemetry.StartObserverTask(); @@ -99,9 +103,12 @@ internal ClientTelemetry( AuthorizationTokenProvider authorizationTokenProvider, DiagnosticsHandlerHelper diagnosticsHelper, IReadOnlyList preferredRegions, - GlobalEndpointManager globalEndpointManager) + GlobalEndpointManager globalEndpointManager, + string endpointUrl) { this.diagnosticsHelper = diagnosticsHelper ?? throw new ArgumentNullException(nameof(diagnosticsHelper)); + this.endpointUrl = endpointUrl ?? throw new ArgumentNullException(nameof(endpointUrl)); + this.globalEndpointManager = globalEndpointManager; this.processor = new ClientTelemetryProcessor(httpClient, authorizationTokenProvider); @@ -177,6 +184,7 @@ ConcurrentDictionary cacheRefreshInfo operationInfoSnapshot: operationInfoSnapshot, cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, requestInfoSnapshot: requestInfoSnapshot, + endpointUrl: this.endpointUrl, cancellationToken: cancellationToken.Token), cancellationToken.Token); // Initiating Telemetry Data Processor task which will serialize and send telemetry information to Client Telemetry Service diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs index 2aeaadca63..84a47e1081 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryOptions.cs @@ -72,17 +72,13 @@ internal static class ClientTelemetryOptions internal const string IsThreadStarvingName = "SystemPool_IsThreadStarving_True"; internal const string IsThreadStarvingUnit = "Count"; - internal const double DefaultTimeStampInSeconds = 600; internal const double Percentile50 = 50.0; internal const double Percentile90 = 90.0; internal const double Percentile95 = 95.0; internal const double Percentile99 = 99.0; internal const double Percentile999 = 99.9; internal const string DateFormat = "yyyy-MM-ddTHH:mm:ssZ"; - internal const string EnvPropsClientTelemetrySchedulingInSeconds = "COSMOS.CLIENT_TELEMETRY_SCHEDULING_IN_SECONDS"; - internal const string EnvPropsClientTelemetryEnabled = "COSMOS.CLIENT_TELEMETRY_ENABLED"; - internal const string EnvPropsClientTelemetryVmMetadataUrl = "COSMOS.VM_METADATA_URL"; - internal const string EnvPropsClientTelemetryEndpoint = "COSMOS.CLIENT_TELEMETRY_ENDPOINT"; + internal const string EnvPropsClientTelemetryEnvironmentName = "COSMOS.ENVIRONMENT_NAME"; internal static readonly ResourceType AllowedResourceTypes = ResourceType.Document; @@ -99,53 +95,11 @@ internal static class ClientTelemetryOptions internal static readonly List ExcludedStatusCodes = new List { 404, 409, 412 }; internal static readonly int NetworkTelemetrySampleSize = 200; + internal static TimeSpan DefaultIntervalForTelemetryJob = TimeSpan.FromMinutes(10); internal static int PayloadSizeThreshold = 1024 * 1024 * 2; // 2MB internal static TimeSpan ClientTelemetryProcessorTimeOut = TimeSpan.FromMinutes(5); - private static Uri clientTelemetryEndpoint; private static string environmentName; - private static TimeSpan scheduledTimeSpan = TimeSpan.Zero; - - internal static bool IsClientTelemetryEnabled() - { - bool isTelemetryEnabled = ConfigurationManager - .GetEnvironmentVariable(ClientTelemetryOptions - .EnvPropsClientTelemetryEnabled, false); - - DefaultTrace.TraceInformation($"Telemetry Flag is set to {isTelemetryEnabled}"); - - return isTelemetryEnabled; - } - - internal static TimeSpan GetScheduledTimeSpan() - { - if (scheduledTimeSpan.Equals(TimeSpan.Zero)) - { - double scheduledTimeInSeconds = ClientTelemetryOptions.DefaultTimeStampInSeconds; - try - { - scheduledTimeInSeconds = ConfigurationManager - .GetEnvironmentVariable( - ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, - ClientTelemetryOptions.DefaultTimeStampInSeconds); - - if (scheduledTimeInSeconds <= 0) - { - throw new ArgumentException("Telemetry Scheduled time can not be less than or equal to 0."); - } - } - catch (Exception ex) - { - DefaultTrace.TraceError($"Error while getting telemetry scheduling configuration : {ex.Message}. Falling back to default configuration i.e. {scheduledTimeInSeconds}" ); - } - - scheduledTimeSpan = TimeSpan.FromSeconds(scheduledTimeInSeconds); - - DefaultTrace.TraceInformation($"Telemetry Scheduled in Seconds {scheduledTimeSpan.TotalSeconds}"); - - } - return scheduledTimeSpan; - } internal static string GetHostInformation(Compute vmInformation) { @@ -155,23 +109,6 @@ internal static string GetHostInformation(Compute vmInformation) vmInformation?.AzEnvironment); } - internal static Uri GetClientTelemetryEndpoint() - { - if (clientTelemetryEndpoint == null) - { - string uriProp = ConfigurationManager - .GetEnvironmentVariable( - ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); - if (!String.IsNullOrEmpty(uriProp)) - { - clientTelemetryEndpoint = new Uri(uriProp); - } - - DefaultTrace.TraceInformation($"Telemetry Endpoint URL is {uriProp}"); - } - return clientTelemetryEndpoint; - } - internal static string GetEnvironmentName() { if (String.IsNullOrEmpty(environmentName)) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs index c9511cb4e4..ffa74c2466 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/ClientTelemetryProcessor.cs @@ -19,8 +19,6 @@ namespace Microsoft.Azure.Cosmos.Telemetry internal class ClientTelemetryProcessor { - private static readonly Uri endpointUrl = ClientTelemetryOptions.GetClientTelemetryEndpoint(); - private readonly AuthorizationTokenProvider tokenProvider; private readonly CosmosHttpClient httpClient; @@ -39,6 +37,7 @@ internal async Task ProcessAndSendAsync( ConcurrentDictionary operationInfoSnapshot, ConcurrentDictionary cacheRefreshInfoSnapshot, IReadOnlyList requestInfoSnapshot, + string endpointUrl, CancellationToken cancellationToken) { try @@ -48,7 +47,7 @@ await ClientTelemetryPayloadWriter.SerializedPayloadChunksAsync( operationInfoSnapshot: operationInfoSnapshot, cacheRefreshInfoSnapshot: cacheRefreshInfoSnapshot, sampledRequestInfo: requestInfoSnapshot, - callback: async (payload) => await this.SendAsync(clientTelemetryInfo.GlobalDatabaseAccountName, payload, cancellationToken)); + callback: async (payload) => await this.SendAsync(clientTelemetryInfo.GlobalDatabaseAccountName, payload, endpointUrl, cancellationToken)); } catch (Exception ex) { @@ -67,6 +66,7 @@ await ClientTelemetryPayloadWriter.SerializedPayloadChunksAsync( private async Task SendAsync( string globalDatabaseAccountName, string jsonPayload, + string endpointUrl, CancellationToken cancellationToken) { if (endpointUrl == null) @@ -77,12 +77,12 @@ private async Task SendAsync( try { - DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl.AbsoluteUri); + DefaultTrace.TraceInformation("Sending Telemetry Data to {0}", endpointUrl); using HttpRequestMessage request = new HttpRequestMessage { Method = HttpMethod.Post, - RequestUri = endpointUrl, + RequestUri = new Uri(endpointUrl), Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json") }; @@ -91,7 +91,7 @@ async ValueTask CreateRequestMessage() INameValueCollection headersCollection = new StoreResponseNameValueCollection(); await this.tokenProvider.AddAuthorizationHeaderAsync( headersCollection, - endpointUrl, + new Uri(endpointUrl), "POST", AuthorizationTokenType.PrimaryMasterKey); diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs index 2f78df0913..9212457951 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs @@ -5,12 +5,17 @@ namespace Microsoft.Azure.Cosmos.Telemetry { using System; + using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; using Microsoft.Azure.Cosmos.Handler; + using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Routing; using Microsoft.Azure.Cosmos.Telemetry.Collector; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Collections; internal class TelemetryToServiceHelper : IDisposable { @@ -70,12 +75,69 @@ public static TelemetryToServiceHelper CreateAndInitializeClientConfigAndTelemet TelemetryToServiceHelper helper = new TelemetryToServiceHelper( clientId, connectionPolicy, cosmosAuthorization, httpClient, serviceEndpoint, globalEndpointManager, cancellationTokenSource); - helper.InitializeClientTelemetry(); + _ = helper.RetrieveConfigAndInitiateTelemetryAsync(); // Let it run in backgroud return helper; #endif } + private async Task RetrieveConfigAndInitiateTelemetryAsync() + { + try + { + Uri serviceEndpointWithPath = new Uri(this.serviceEnpoint + Paths.ClientConfigPathSegment); + + TryCatch databaseAccountClientConfigs = await this.GetDatabaseAccountClientConfigAsync(this.cosmosAuthorization, this.httpClient, serviceEndpointWithPath); + if (databaseAccountClientConfigs.Succeeded) + { + this.InitializeClientTelemetry(databaseAccountClientConfigs.Result); + } + else if (!this.cancellationTokenSource.IsCancellationRequested) + { + DefaultTrace.TraceWarning($"Exception while calling client config " + databaseAccountClientConfigs.Exception.ToString()); + } + } + catch (Exception ex) + { + DefaultTrace.TraceWarning($"Exception while running client config job " + ex.ToString()); + } + } + + private async Task> GetDatabaseAccountClientConfigAsync(AuthorizationTokenProvider cosmosAuthorization, + CosmosHttpClient httpClient, + Uri clientConfigEndpoint) + { + INameValueCollection headers = new RequestNameValueCollection(); + await cosmosAuthorization.AddAuthorizationHeaderAsync( + headersCollection: headers, + clientConfigEndpoint, + HttpConstants.HttpMethods.Get, + AuthorizationTokenType.PrimaryMasterKey); + + using (ITrace trace = Trace.GetRootTrace("Account Client Config Read", TraceComponent.Transport, TraceLevel.Info)) + { + try + { + using (HttpResponseMessage responseMessage = await httpClient.GetAsync( + uri: clientConfigEndpoint, + additionalHeaders: headers, + resourceType: ResourceType.DatabaseAccount, + timeoutPolicy: HttpTimeoutPolicyControlPlaneRead.Instance, + clientSideRequestStatistics: null, + cancellationToken: default)) + using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage)) + { + return TryCatch.FromResult(CosmosResource.FromStream(documentServiceResponse)); + } + } + catch (Exception ex) + { + DefaultTrace.TraceWarning($"Exception while calling client config " + ex.StackTrace); + return TryCatch.FromException(ex); + } + } + } + public ITelemetryCollector GetCollector() { return this.collector; @@ -89,28 +151,34 @@ public bool IsClientTelemetryJobRunning() /// /// Trigger Client Telemetry job when it is enabled and not already running. /// - private void InitializeClientTelemetry() + private void InitializeClientTelemetry(AccountClientConfiguration clientConfig) { - try - { - this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( - clientId: this.clientId, - httpClient: this.httpClient, - userAgent: this.connectionPolicy.UserAgentContainer.BaseUserAgent, - connectionMode: this.connectionPolicy.ConnectionMode, - authorizationTokenProvider: this.cosmosAuthorization, - diagnosticsHelper: DiagnosticsHandlerHelper.Instance, - preferredRegions: this.connectionPolicy.PreferredLocations, - globalEndpointManager: this.globalEndpointManager); - - this.collector = new TelemetryCollector(this.clientTelemetry, this.connectionPolicy); - - DefaultTrace.TraceVerbose("Client Telemetry Enabled."); - } - catch (Exception ex) + DiagnosticsHandlerHelper.Refresh(clientConfig.IsClientTelemetryEnabled()); + + if (clientConfig.IsClientTelemetryEnabled()) { - DefaultTrace.TraceWarning($"Error While starting Telemetry Job : {0}. Hence disabling Client Telemetry", ex.Message); - this.connectionPolicy.EnableClientTelemetry = false; + try + { + this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( + clientId: this.clientId, + httpClient: this.httpClient, + userAgent: this.connectionPolicy.UserAgentContainer.BaseUserAgent, + connectionMode: this.connectionPolicy.ConnectionMode, + authorizationTokenProvider: this.cosmosAuthorization, + diagnosticsHelper: DiagnosticsHandlerHelper.GetInstance(), + preferredRegions: this.connectionPolicy.PreferredLocations, + globalEndpointManager: this.globalEndpointManager, + endpointUrl: clientConfig.ClientTelemetryConfiguration.Endpoint); + + this.collector = new TelemetryCollector(this.clientTelemetry, this.connectionPolicy); + + DefaultTrace.TraceVerbose("Client Telemetry Enabled."); + } + catch (Exception ex) + { + DefaultTrace.TraceWarning($"Error While starting Telemetry Job : {0}. Hence disabling Client Telemetry", ex); + this.connectionPolicy.EnableClientTelemetry = false; + } } } diff --git a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs index def12c8262..829899c4b1 100644 --- a/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs +++ b/Microsoft.Azure.Cosmos/src/Tracing/TraceData/ClientSideRequestStatisticsTraceDatum.cs @@ -419,7 +419,7 @@ public void UpdateSystemUsage() this.systemUsageHistory.Values.Count == 0 || this.systemUsageHistory.LastTimestamp + DiagnosticsHandlerHelper.DiagnosticsRefreshInterval < DateTime.UtcNow) { - this.systemUsageHistory = DiagnosticsHandlerHelper.Instance.GetDiagnosticsSystemHistory(); + this.systemUsageHistory = DiagnosticsHandlerHelper.GetInstance().GetDiagnosticsSystemHistory(); } #endif } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs index d31c95bfe8..7a54f490c0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryReleaseTests.cs @@ -36,20 +36,15 @@ public override Task HttpHandlerRequestCallbackChecks(HttpR } [ClassInitialize] - public static new void ClassInitialize(TestContext context) + public static void ClassInit(TestContext context) { ClientTelemetryTestsBase.ClassInitialize(context); - - // It will go away in next PR - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "true"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "https://tools.cosmos.azure.com/api/clienttelemetry/trace"); } [ClassCleanup] - public static new void FinalCleanup() + public static void ClassCleanUp() { - ClientTelemetryTestsBase.FinalCleanup(); + ClientTelemetryTestsBase.ClassCleanup(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs index 2ffc60f5f4..ffa3e6eda1 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTests.cs @@ -5,11 +5,13 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using Microsoft.Azure.Cosmos.Fluent; - using Microsoft.Azure.Cosmos.Telemetry; using System.Net.Http; using System.Net; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using System.Text; + using Microsoft.Azure.Documents; /// /// In Emulator Mode, Run test against emulator and mock client telemetry service calls. @@ -21,10 +23,25 @@ public class ClientTelemetryTests : ClientTelemetryTestsBase { public override Task HttpHandlerRequestCallbackChecks(HttpRequestMessage request) { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NoContent)); // In Emulator test, send hardcoded response status code as there is no real communication happens with client telemetry service } + else if (request.RequestUri.AbsoluteUri.Contains(Paths.ClientConfigPathSegment)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = true, + Endpoint = telemetryServiceEndpoint.AbsoluteUri + } + }; + string payload = JsonConvert.SerializeObject(clientConfigProperties); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + return Task.FromResult(result); + } return null; } @@ -35,15 +52,15 @@ public override CosmosClientBuilder GetBuilder() } [ClassInitialize] - public static new void ClassInitialize(TestContext context) + public static void ClassInit(TestContext context) { ClientTelemetryTestsBase.ClassInitialize(context); } [ClassCleanup] - public static new void FinalCleanup() + public static void ClassCleanUp() { - ClientTelemetryTestsBase.FinalCleanup(); + ClientTelemetryTestsBase.ClassCleanup(); } [TestInitialize] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs index da4b131cdb..30c239a036 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryTestsBase.cs @@ -27,7 +27,8 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests public abstract class ClientTelemetryTestsBase : BaseCosmosClientHelper { - private static SystemUsageMonitor systemUsageMonitor; + protected static readonly Uri telemetryServiceEndpoint = new Uri("http://dummy.telemetry.service/api/url"); + private static readonly List preferredRegionList = new List { Regions.EastUS, @@ -53,13 +54,13 @@ public abstract class ClientTelemetryTestsBase : BaseCosmosClientHelper public static void ClassInitialize(TestContext _) { - Util.EnableClientTelemetryEnvironmentVariables(); - - SystemUsageMonitor oldSystemUsageMonitor = (SystemUsageMonitor)typeof(DiagnosticsHandlerHelper) - .GetField("systemUsageMonitor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(DiagnosticsHandlerHelper.Instance); - oldSystemUsageMonitor.Stop(); + ClientTelemetryOptions.DefaultIntervalForTelemetryJob = TimeSpan.FromSeconds(1); + } - ClientTelemetryTestsBase.ResetSystemUsageMonitor(true); + public static void ClassCleanup() + { + //undone the changes done in ClassInitialize + ClientTelemetryOptions.DefaultIntervalForTelemetryJob = TimeSpan.FromMinutes(10); } public virtual void TestInitialize() @@ -70,7 +71,7 @@ public virtual void TestInitialize() { RequestCallBack = (request, cancellation) => { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); @@ -83,7 +84,7 @@ public virtual void TestInitialize() }, ResponseIntercepter = (response) => { - if (response.RequestMessage.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (response.RequestMessage != null && response.RequestMessage.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); } @@ -92,7 +93,7 @@ public virtual void TestInitialize() }, ExceptionIntercepter = (request, exception) => { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { this.isClientTelemetryAPICallFailed = true; } @@ -109,7 +110,7 @@ public virtual void TestInitialize() return Task.FromResult(result); } - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); @@ -123,7 +124,7 @@ public virtual void TestInitialize() }, ResponseIntercepter = (response) => { - if (response.RequestMessage.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (response.RequestMessage != null && response.RequestMessage.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { Assert.AreEqual(HttpStatusCode.NoContent, response.StatusCode); } @@ -131,7 +132,7 @@ public virtual void TestInitialize() }, ExceptionIntercepter = (request, exception) => { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { this.isClientTelemetryAPICallFailed = true; } @@ -139,6 +140,7 @@ public virtual void TestInitialize() }; this.cosmosClientBuilder = this.GetBuilder() + .WithTelemetryEnabled() .WithApplicationPreferredRegions(ClientTelemetryTestsBase.preferredRegionList); } @@ -146,34 +148,6 @@ public virtual void TestInitialize() public abstract CosmosClientBuilder GetBuilder(); - private static void ResetSystemUsageMonitor(bool isTelemetryEnabled) - { - ClientTelemetryTestsBase.systemUsageMonitor?.Stop(); - - FieldInfo diagnosticsHandlerHelperInstance = typeof(DiagnosticsHandlerHelper) - .GetField("isTelemetryMonitoringEnabled", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); - diagnosticsHandlerHelperInstance.SetValue(null, isTelemetryEnabled); - - List recorders = new List() - { - (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) - .GetField("diagnosticSystemUsageRecorder", - BindingFlags.Instance | BindingFlags.NonPublic) - .GetValue(DiagnosticsHandlerHelper.Instance) - }; - - if (isTelemetryEnabled) - { - recorders.Add( - (SystemUsageRecorder)typeof(DiagnosticsHandlerHelper) - .GetField("telemetrySystemUsageRecorder", - BindingFlags.Instance | BindingFlags.NonPublic) - .GetValue(DiagnosticsHandlerHelper.Instance)); - } - - ClientTelemetryTestsBase.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(recorders); - } - public virtual async Task Cleanup() { FieldInfo isInitializedField = typeof(VmMetadataApiHandler).GetField("isInitialized", @@ -185,16 +159,12 @@ public virtual async Task Cleanup() BindingFlags.Static | BindingFlags.NonPublic); azMetadataField.SetValue(null, null); + await base.TestCleanup(); - Assert.IsFalse(this.isClientTelemetryAPICallFailed, $"Call to client telemetry service endpoint (i.e. {ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri}) failed"); + Assert.IsFalse(this.isClientTelemetryAPICallFailed, $"Call to client telemetry service endpoint (i.e. {telemetryServiceEndpoint}) failed"); } - public static void FinalCleanup() - { - ClientTelemetryTestsBase.ResetSystemUsageMonitor(false); - } - public virtual async Task PointSuccessOperationsTest(ConnectionMode mode, bool isAzureInstance) { Container container = await this.CreateClientAndContainer( @@ -414,8 +384,6 @@ await this.WaitAndAssert( public virtual async Task QueryOperationSinglePartitionTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - Container container = await this.CreateClientAndContainer(mode); ToDoActivity testItem = ToDoActivity.CreateRandomToDoActivity("MyTestPkValue", "MyTestItemId"); @@ -471,7 +439,6 @@ await this.WaitAndAssert(expectedOperationCount: 4, public virtual async Task QueryMultiPageSinglePartitionOperationTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); Container container = await this.CreateClientAndContainer(mode: mode); ItemRequestOptions requestOptions = new ItemRequestOptions() @@ -532,8 +499,6 @@ await this.WaitAndAssert( public virtual async Task QueryOperationCrossPartitionTest(ConnectionMode mode) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "20"); - ContainerInternal itemsCore = (ContainerInternal)await this.CreateClientAndContainer( mode: mode, isLargeContainer: true); @@ -674,7 +639,7 @@ public virtual async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) httpHandler.RequestCallBack = (request, cancellation) => { - if (request.RequestUri.AbsoluteUri.Equals(ClientTelemetryOptions.GetClientTelemetryEndpoint().AbsoluteUri)) + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) { string jsonObject = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); @@ -696,11 +661,12 @@ public virtual async Task CreateItemWithSubStatusCodeTest(ConnectionMode mode) return Task.FromResult(result); } - return null; + return this.HttpHandlerRequestCallbackChecks(request); }; // Replacing originally initialized cosmos Builder with this one with new handler this.cosmosClientBuilder = this.cosmosClientBuilder + .WithTelemetryEnabled() .WithHttpClientFactory(() => new HttpClient(httpHandler)); Container container = await this.CreateClientAndContainer( diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs index a8ae6ce1a4..1c5676a46a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/SynchronizationContextTests.cs @@ -6,9 +6,15 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests { using System; using System.Linq; + using System.Net; + using System.Net.Http; + using System.Text; using System.Threading; + using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Microsoft.Azure.Documents; [TestClass] public class SynchronizationContextTests @@ -19,10 +25,29 @@ public class SynchronizationContextTests [Timeout(30000)] public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) { - if (withClientTelemetry) + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper { - Util.EnableClientTelemetryEnvironmentVariables(); - } + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Contains(Paths.ClientConfigPathSegment)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = withClientTelemetry, + Endpoint = withClientTelemetry? "http://dummy.telemetry.endpoint/" : null + } + }; + string payload = JsonConvert.SerializeObject(clientConfigProperties); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + return Task.FromResult(result); + } + + return null; + } + }; string databaseId = Guid.NewGuid().ToString(); SynchronizationContext prevContext = SynchronizationContext.Current; @@ -32,7 +57,10 @@ public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) SynchronizationContext.SetSynchronizationContext(syncContext); syncContext.Post(_ => { - using (CosmosClient client = TestCommon.CreateCosmosClient()) + using (CosmosClient client = TestCommon.CreateCosmosClient( + customizeClientBuilder: (builder) => builder + .WithTelemetryEnabled() + .WithHttpClientFactory(() => new HttpClient(httpHandler)))) { Cosmos.Database database = client.CreateDatabaseAsync(databaseId).GetAwaiter().GetResult(); database = client.CreateDatabaseIfNotExistsAsync(databaseId).GetAwaiter().GetResult(); @@ -124,7 +152,7 @@ public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) double cost = container.GetItemLinqQueryable( allowSynchronousQueryExecution: true).Select(x => x.cost).Sum(); - + ItemResponse deleteResponse = container.DeleteItemAsync(partitionKey: new Cosmos.PartitionKey(testItem.pk), id: testItem.id).ConfigureAwait(false).GetAwaiter().GetResult(); Assert.IsNotNull(deleteResponse); } @@ -138,11 +166,6 @@ public void VerifySynchronizationContextDoesNotLock(bool withClientTelemetry) { client.GetDatabase(databaseId).DeleteAsync().GetAwaiter().GetResult(); } - - if (withClientTelemetry) - { - Util.DisableClientTelemetryEnvironmentVariables(); - } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs index 9b78eb573c..aead33feef 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs @@ -52,6 +52,8 @@ protected override async Task SendAsync(HttpRequestMessage throw; } this.ExceptionIntercepter.Invoke(request, ex); + + throw; // Anyway throw this exception } if (this.ResponseIntercepter != null) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs index 366cc68811..ea360ea285 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/Util.cs @@ -522,20 +522,6 @@ internal static void LogRequestOptions(RequestOptions options, bool shouldLogOff options.OfferThroughput); } - internal static void EnableClientTelemetryEnvironmentVariables() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "true"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, "1"); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); - } - - internal static void DisableClientTelemetryEnvironmentVariables() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetrySchedulingInSeconds, null); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); - } - private static TracerProvider OTelTracerProvider; private static CustomListener TestListener; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/HttpHandlerHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/HttpHandlerHelper.cs new file mode 100644 index 0000000000..65fb15e012 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/HttpHandlerHelper.cs @@ -0,0 +1,67 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Performance.Tests +{ + using System; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + public class HttpClientHandlerHelper : DelegatingHandler + { + public HttpClientHandlerHelper() : base(new HttpClientHandler()) + { + } + + public Func> RequestCallBack { get; set; } + + public Func> ResponseIntercepter { get; set; } + + public Action ExceptionIntercepter { get; set; } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + HttpResponseMessage httpResponse = null; + if (this.RequestCallBack != null) + { + Task response = this.RequestCallBack(request, cancellationToken); + if(response != null) + { + httpResponse = await response; + if (httpResponse != null) + { + if (this.ResponseIntercepter != null) + { + httpResponse = await this.ResponseIntercepter(httpResponse); + } + return httpResponse; + } + } + } + + try + { + httpResponse = await base.SendAsync(request, cancellationToken); + } + catch (Exception ex) { + + if (this.ExceptionIntercepter == null) + { + throw; + } + this.ExceptionIntercepter.Invoke(request, ex); + + throw; // Anyway throw this exception + } + + if (this.ResponseIntercepter != null) + { + httpResponse = await this.ResponseIntercepter(httpResponse); + } + + return httpResponse; + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs index 3403269950..3484abb3ae 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Mocks/MockDocumentClient.cs @@ -22,6 +22,9 @@ namespace Microsoft.Azure.Cosmos.Performance.Tests using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; using Newtonsoft.Json; using Microsoft.Azure.Cosmos.Telemetry; + using System.Net.Http; + using System.Net; + using System.Text; internal class MockDocumentClient : DocumentClient, ICosmosAuthorizationTokenProvider { @@ -51,7 +54,7 @@ public static CosmosClient CreateMockCosmosClient( { policy = new ConnectionPolicy { - EnableClientTelemetry = isClientTelemetryEnabled.Value + EnableClientTelemetry = true // feature flag is always true }; } @@ -59,6 +62,43 @@ public static CosmosClient CreateMockCosmosClient( MockDocumentClient documentClient = new MockDocumentClient(policy); CosmosClientBuilder cosmosClientBuilder = new CosmosClientBuilder("http://localhost", Convert.ToBase64String(Guid.NewGuid().ToByteArray())); cosmosClientBuilder.WithConnectionModeDirect(); + + Uri telemetryServiceEndpoint = new Uri("https://dummy.endpoint.com/"); + + if (isClientTelemetryEnabled.HasValue) + { + // mock external calls + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(telemetryServiceEndpoint.AbsoluteUri)) + { + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.NoContent)); // In Emulator test, send hardcoded response status code as there is no real communication happens with client telemetry service + } + else if (request.RequestUri.AbsoluteUri.Contains(Paths.ClientConfigPathSegment)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = isClientTelemetryEnabled.Value, + Endpoint = isClientTelemetryEnabled.Value?telemetryServiceEndpoint.AbsoluteUri: null + } + }; + string payload = JsonConvert.SerializeObject(clientConfigProperties); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + return Task.FromResult(result); + } + + return null; + } + }; + + cosmosClientBuilder.WithHttpClientFactory(() => new HttpClient(httpHandler)); + } + customizeClientBuilder?.Invoke(cosmosClientBuilder); if (useCustomSerializer) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs new file mode 100644 index 0000000000..23c813d826 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs @@ -0,0 +1,75 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Diagnostics +{ + using System; + using System.Reflection; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Handler; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class DiagnosticHandlerHelperTests + { + [ClassInitialize] + public static void Initialize(TestContext _) + { + DiagnosticHandlerHelperTests.ResetDiagnosticsHandlerHelper(); + } + + private static void ResetDiagnosticsHandlerHelper() + { + //Stop the job + DiagnosticsHandlerHelper helper = DiagnosticsHandlerHelper.GetInstance(); + MethodInfo iMethod = helper.GetType().GetMethod("StopSystemMonitor", BindingFlags.NonPublic | BindingFlags.Instance); + iMethod.Invoke(helper, new object[] { }); + + //Reset the instance woth original value + FieldInfo field = typeof(DiagnosticsHandlerHelper).GetField("Instance", + BindingFlags.Static | + BindingFlags.NonPublic); + field.SetValue(null, Activator.CreateInstance(typeof(DiagnosticsHandlerHelper), true)); + } + + [TestMethod] + public void SingletonTest() + { + DiagnosticsHandlerHelper diagnosticHandlerHelper1 = DiagnosticsHandlerHelper.GetInstance(); + DiagnosticsHandlerHelper diagnosticHandlerHelper2 = DiagnosticsHandlerHelper.GetInstance(); + + Assert.IsNotNull(diagnosticHandlerHelper1); + Assert.IsNotNull(diagnosticHandlerHelper2); + Assert.AreEqual(diagnosticHandlerHelper1, diagnosticHandlerHelper2, "Not Singleton"); + } + + [TestMethod] + public async Task RefreshTestAsync() + { + // Get default instance of DiagnosticsHandlerHelper with client telemetry disabled (default) + DiagnosticsHandlerHelper diagnosticHandlerHelper1 = DiagnosticsHandlerHelper.GetInstance(); + await Task.Delay(10000); // warm up + Assert.IsNotNull(diagnosticHandlerHelper1.GetDiagnosticsSystemHistory()); + int countBeforeRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; + + // Refresh instance of DiagnosticsHandlerHelper with client telemetry enabled + DiagnosticsHandlerHelper.Refresh(true); + DiagnosticsHandlerHelper diagnosticHandlerHelper2 = DiagnosticsHandlerHelper.GetInstance(); + int countAfterRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; + + Console.WriteLine(countBeforeRefresh + " " + countAfterRefresh); + Assert.IsTrue(countBeforeRefresh <= countAfterRefresh, "After Refresh count should be greater than or equal to before refresh count"); + + Assert.AreNotEqual(diagnosticHandlerHelper1, diagnosticHandlerHelper2); + + Assert.IsNotNull(diagnosticHandlerHelper2.GetDiagnosticsSystemHistory()); + Assert.IsNotNull(diagnosticHandlerHelper2.GetClientTelemetrySystemHistory()); + + // Refresh instance of DiagnosticsHandlerHelper with client telemetry disabled + DiagnosticsHandlerHelper.Refresh(false); + DiagnosticsHandlerHelper diagnosticHandlerHelper3 = DiagnosticsHandlerHelper.GetInstance(); + Assert.IsNotNull(diagnosticHandlerHelper3.GetDiagnosticsSystemHistory()); + Assert.IsNull(diagnosticHandlerHelper3.GetClientTelemetrySystemHistory()); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs index 9308d22806..6005ec3045 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Telemetry/ClientTelemetryTests.cs @@ -26,13 +26,6 @@ namespace Microsoft.Azure.Cosmos.Tests.Telemetry [TestClass] public class ClientTelemetryTests { - [TestCleanup] - public void Cleanup() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, null); - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, null); - } - [TestMethod] public void CheckMetricsAggregationLogic() { @@ -126,7 +119,6 @@ public void CheckJsonSerializerContractWithPreferredRegions() [DataRow(150, 0, 0)] // When only operation info is there in payload public async Task CheckIfPayloadIsDividedCorrectlyAsync(int expectedOperationInfoSize, int expectedCacheRefreshInfoSize, int expectedRequestInfoSize) { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); ClientTelemetryOptions.PayloadSizeThreshold = 1024 * 15; //15 Kb string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); @@ -245,7 +237,8 @@ await processor.ProcessAndSendAsync( clientTelemetryProperties, operationInfoSnapshot, cacheRefreshInfoSnapshot, - requestInfoList, + requestInfoList, + "http://dummy.telemetry.endpoint/", new CancellationTokenSource(ClientTelemetryOptions.ClientTelemetryProcessorTimeOut).Token); Assert.AreEqual(expectedOperationInfoSize, actualOperationInfoSize, "Operation Info is not correct"); @@ -256,8 +249,6 @@ await processor.ProcessAndSendAsync( [TestMethod] public async Task ClientTelmetryProcessor_should_timeout() { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEndpoint, "http://dummy.telemetry.endpoint/"); - string data = File.ReadAllText("Telemetry/ClientTelemetryPayloadWithoutMetrics.json", Encoding.UTF8); ClientTelemetryProperties clientTelemetryProperties = JsonConvert.DeserializeObject(data); @@ -344,6 +335,7 @@ await processor.ProcessAndSendAsync(clientTelemetryProperties, operationInfoSnapshot, cacheRefreshInfoSnapshot, default, + "http://dummy.telemetry.endpoint/", cts.Token); }); @@ -352,13 +344,5 @@ await Assert.ThrowsExceptionAsync(() => ClientTeleme processingTask: processorTask, timeout: TimeSpan.FromTicks(1))); } - - [TestMethod] - [ExpectedException(typeof(FormatException))] - public void CheckMisconfiguredTelemetry_should_fail() - { - Environment.SetEnvironmentVariable(ClientTelemetryOptions.EnvPropsClientTelemetryEnabled, "non-boolean"); - using CosmosClient client = MockCosmosUtil.CreateMockCosmosClient(); - } } } From 7c3f5e1decc47a5888feaee2f79c8f4b2ad4bf63 Mon Sep 17 00:00:00 2001 From: David Chaava Date: Tue, 5 Sep 2023 21:55:18 +0200 Subject: [PATCH 184/337] [Internal] Benchmark tool: Fixes benchmark run command using OSSProjectRef parameter (#4066) * fix benchmark run command using OSSProjectRef parameter * remove ShouldUnsetParentConfigurationAndPlatform=false --------- Co-authored-by: David Chaava --- .../Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh index 2b41d4d0e4..8ae5662144 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh @@ -14,10 +14,10 @@ git checkout ${BENCHMARKING_TOOLS_BRANCH_NAME} cd 'Microsoft.Azure.Cosmos.Samples/Tools/Benchmark' echo "########## Build benckmark tool ##########" -dotnet build --configuration Release -p:"OSSProjectRef=true;ShouldUnsetParentConfigurationAndPlatform=false" +dotnet build --configuration Release -p:"OSSProjectRef=true" echo "########## Run benchmark ##########" -nohup dotnet run -c Release -e ${COSMOS_URI} -k ${COSMOS_KEY} -t ${THROUGHPUT} -n ${DOCUMENTS} --pl ${PARALLELISM} \ +nohup dotnet run -c Release -p:"OSSProjectRef=true" -e ${COSMOS_URI} -k ${COSMOS_KEY} -t ${THROUGHPUT} -n ${DOCUMENTS} --pl ${PARALLELISM} \ --enablelatencypercentiles true --resultscontainer ${RESULTS_CONTAINER} --resultspartitionkeyvalue "pk" \ --DiagnosticsStorageConnectionString ${DIAGNOSTICS_STORAGE_CONNECTION_STRING} \ --DiagnosticLatencyThresholdInMs ${DIAGNOSTICS_LATENCY_THRESHOLD_IN_MS} \ From b7b1064ab7e8bb0d90825c95125c5e1e2d74cb50 Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Fri, 8 Sep 2023 12:39:48 -0700 Subject: [PATCH 185/337] [Query] Adds public backend metrics property to Diagnostics (#4001) * initial commit * some pr comments, WIP * Refactor * more * Public constructors and modify accumulators * accumulator updates and undo test changes * add test * PR comments * bug fix * ToString() refactor * contract updates * test updates * small fixes * text fix * Update accumulators * fix * PR comments * small fix * Rename BE -> ServerSide * more renaming * Update API and tests * separate public and internal classes * API update * change namespace * Pr comments * public constructors and bug fix * API updates * renaming and test updates * PR comments * more PR comments * PR comments, test additions * API updates and more tests * tests and pkrangeid update * PR comments * more PR comments * smol test fix * PR comments - renaming properties and constructor rehash * contract update * seal classes and private fields. * update indexHitRatio calc * mocking refactor to abstract classes * contract updates * PR comments - Update documentation --- .../src/Diagnostics/CosmosDiagnostics.cs | 13 + .../src/Diagnostics/CosmosTraceDiagnostics.cs | 24 +- .../src/Query/Core/Metrics/BackendMetrics.cs | 237 ------------------ .../Query/Core/Metrics/ClientSideMetrics.cs | 38 --- .../Metrics/ClientSideMetricsAccumulator.cs | 47 ++++ .../Core/Metrics/IndexUtilizationInfo.cs | 38 --- .../IndexUtilizationInfoAccumulator.cs | 51 ++++ .../src/Query/Core/Metrics/QueryMetrics.cs | 70 ++---- .../Core/Metrics/QueryMetricsAccumulator.cs | 48 ++++ .../Core/Metrics/QueryMetricsTextWriter.cs | 4 +- .../Query/Core/Metrics/QueryMetricsWriter.cs | 28 +-- .../Core/Metrics/QueryPreparationTimes.cs | 104 -------- .../QueryPreparationTimesAccumulator.cs | 51 ++++ .../Metrics/QueryPreparationTimesInternal.cs | 65 +++++ .../Core/Metrics/RuntimeExecutionTimes.cs | 91 ------- .../RuntimeExecutionTimesAccumulator.cs | 48 ++++ .../Metrics/RuntimeExecutionTimesInternal.cs | 56 +++++ .../Metrics/ServerSideCumulativeMetrics.cs | 23 ++ .../ServerSideCumulativeMetricsInternal.cs | 29 +++ .../Query/Core/Metrics/ServerSideMetrics.cs | 74 ++++++ .../Core/Metrics/ServerSideMetricsInternal.cs | 153 +++++++++++ .../ServerSideMetricsInternalAccumulator.cs | 146 +++++++++++ ...csParser.cs => ServerSideMetricsParser.cs} | 164 ++++++------ ...nizer.cs => ServerSideMetricsTokenizer.cs} | 4 +- .../Core/Metrics/ServerSideMetricsUtils.cs | 13 + .../Metrics/ServerSidePartitionedMetrics.cs | 27 ++ .../ServerSidePartitionedMetricsInternal.cs | 40 +++ .../CosmosItemTests.cs | 134 +++++++++- .../QueryStatisticsDatumVisitor.cs | 14 +- .../QueryTests.cs | 26 +- .../Query/Metrics/Performance.cs | 2 +- .../TraceWriterBaselineTests.TraceData.xml | 2 +- .../Contracts/DotNetSDKAPI.json | 193 ++++++++++++++ .../Query/Metrics/ClientSideMetricsTests.cs | 8 +- .../Metrics/IndexUtilizationInfoTests.cs | 9 +- .../Query/Metrics/QueryMetricsTests.cs | 16 +- ...ricsTests.cs => ServerSideMetricsTests.cs} | 68 ++--- .../Tracing/TraceWriterBaselineTests.cs | 4 +- 38 files changed, 1420 insertions(+), 742 deletions(-) delete mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetrics.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetricsAccumulator.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfoAccumulator.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsAccumulator.cs delete mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimes.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesAccumulator.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesInternal.cs delete mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimes.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesAccumulator.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesInternal.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetrics.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs rename Microsoft.Azure.Cosmos/src/Query/Core/Metrics/{BackendMetricsParser.cs => ServerSideMetricsParser.cs} (53%) rename Microsoft.Azure.Cosmos/src/Query/Core/Metrics/{BackendMetricsTokenizer.cs => ServerSideMetricsTokenizer.cs} (98%) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsUtils.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/{BackendMetricsTests.cs => ServerSideMetricsTests.cs} (78%) diff --git a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs index a82ef2ecc2..b88eaa8efe 100644 --- a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosDiagnostics.cs @@ -43,6 +43,19 @@ public virtual int GetFailedRequestCount() throw new NotImplementedException($"{nameof(CosmosDiagnostics)}.{nameof(GetFailedRequestCount)}"); } + /// + /// This represents the backend query metrics for the request. + /// + /// + /// This is only applicable for query operations. For all other operations this will return null. + /// + /// The accumulated backend metrics for the request. + public virtual ServerSideCumulativeMetrics GetQueryMetrics() + { + // Default implementation avoids breaking change for users upgrading. + throw new NotImplementedException($"{nameof(CosmosDiagnostics)}.{nameof(GetQueryMetrics)}"); + } + /// /// Gets the string field instance in the Azure Cosmos DB database service. /// diff --git a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs index 07e340f0ac..2d92a2cfb7 100644 --- a/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs +++ b/Microsoft.Azure.Cosmos/src/Diagnostics/CosmosTraceDiagnostics.cs @@ -9,12 +9,15 @@ namespace Microsoft.Azure.Cosmos.Diagnostics using System.Linq; using System.Text; using Microsoft.Azure.Cosmos.Json; + using Microsoft.Azure.Cosmos.Query.Core.Metrics; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Cosmos.Tracing.TraceData; using static Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum; internal sealed class CosmosTraceDiagnostics : CosmosDiagnostics { + private readonly Lazy accumulatedMetrics; + public CosmosTraceDiagnostics(ITrace trace) { if (trace == null) @@ -30,6 +33,7 @@ public CosmosTraceDiagnostics(ITrace trace) } this.Value = rootTrace; + this.accumulatedMetrics = new Lazy(() => PopulateServerSideCumulativeMetrics(this.Value)); } public ITrace Value { get; } @@ -49,6 +53,11 @@ public override TimeSpan GetClientElapsedTime() return this.Value?.Summary?.RegionsContacted; } + public override ServerSideCumulativeMetrics GetQueryMetrics() + { + return this.accumulatedMetrics.Value; + } + internal bool IsGoneExceptionHit() { return this.WalkTraceTreeForGoneException(this.Value); @@ -61,9 +70,9 @@ private bool WalkTraceTreeForGoneException(ITrace currentTrace) return false; } - foreach (object datums in currentTrace.Data.Values) + foreach (object datum in currentTrace.Data.Values) { - if (datums is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) + if (datum is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) { foreach (StoreResponseStatistics responseStatistics in clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList) { @@ -99,6 +108,17 @@ private ReadOnlyMemory WriteTraceToJsonWriter(JsonSerializationFormat json return jsonTextWriter.GetResult(); } + private static ServerSideCumulativeMetrics PopulateServerSideCumulativeMetrics(ITrace trace) + { + ServerSideMetricsInternalAccumulator accumulator = new ServerSideMetricsInternalAccumulator(); + ServerSideMetricsInternalAccumulator.WalkTraceTreeForQueryMetrics(trace, accumulator); + + IReadOnlyList serverSideMetricsList = accumulator.GetPartitionedServerSideMetrics().Select(metrics => new ServerSidePartitionedMetricsInternal(metrics)).ToList(); + + ServerSideCumulativeMetrics accumulatedMetrics = new ServerSideCumulativeMetricsInternal(serverSideMetricsList); + return accumulatedMetrics.PartitionedMetrics.Count != 0 ? accumulatedMetrics : null; + } + public override DateTime? GetStartTimeUtc() { if (this.Value == null || this.Value.StartTime == null) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetrics.cs deleted file mode 100644 index e958aee949..0000000000 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetrics.cs +++ /dev/null @@ -1,237 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace Microsoft.Azure.Cosmos.Query.Core.Metrics -{ - using System; - using System.Collections.Generic; - - /// - /// Metrics received for queries from the backend. - /// -#if INTERNAL -#pragma warning disable SA1600 -#pragma warning disable CS1591 - public -#else - internal -#endif - sealed class BackendMetrics - { - /// - /// QueryMetrics that with all members having default (but not null) members. - /// - public static readonly BackendMetrics Empty = new BackendMetrics( - retrievedDocumentCount: default, - retrievedDocumentSize: default, - outputDocumentCount: default, - outputDocumentSize: default, - indexHitRatio: default, - totalQueryExecutionTime: default, - queryPreparationTimes: QueryPreparationTimes.Zero, - indexLookupTime: default, - documentLoadTime: default, - vmExecutionTime: default, - runtimeExecutionTimes: RuntimeExecutionTimes.Empty, - documentWriteTime: default); - - public BackendMetrics( - long retrievedDocumentCount, - long retrievedDocumentSize, - long outputDocumentCount, - long outputDocumentSize, - double indexHitRatio, - TimeSpan totalQueryExecutionTime, - QueryPreparationTimes queryPreparationTimes, - TimeSpan indexLookupTime, - TimeSpan documentLoadTime, - TimeSpan vmExecutionTime, - RuntimeExecutionTimes runtimeExecutionTimes, - TimeSpan documentWriteTime) - { - this.RetrievedDocumentCount = retrievedDocumentCount; - this.RetrievedDocumentSize = retrievedDocumentSize; - this.OutputDocumentCount = outputDocumentCount; - this.OutputDocumentSize = outputDocumentSize; - this.IndexHitRatio = indexHitRatio; - this.TotalTime = totalQueryExecutionTime; - this.QueryPreparationTimes = queryPreparationTimes ?? throw new ArgumentNullException($"{nameof(queryPreparationTimes)} can not be null."); - this.IndexLookupTime = indexLookupTime; - this.DocumentLoadTime = documentLoadTime; - this.VMExecutionTime = vmExecutionTime; - this.RuntimeExecutionTimes = runtimeExecutionTimes ?? throw new ArgumentNullException($"{nameof(runtimeExecutionTimes)} can not be null."); - this.DocumentWriteTime = documentWriteTime; - } - - /// - /// Gets the total query time in the Azure Cosmos database service. - /// - public TimeSpan TotalTime { get; } - - /// - /// Gets the number of documents retrieved during query in the Azure Cosmos database service. - /// - public long RetrievedDocumentCount { get; } - - /// - /// Gets the size of documents retrieved in bytes during query in the Azure Cosmos DB service. - /// - public long RetrievedDocumentSize { get; } - - /// - /// Gets the number of documents returned by query in the Azure Cosmos DB service. - /// - public long OutputDocumentCount { get; } - - /// - /// Gets the size of documents outputted in bytes during query in the Azure Cosmos database service. - /// - public long OutputDocumentSize { get; } - - /// - /// Gets the query QueryPreparationTimes in the Azure Cosmos database service. - /// - public QueryPreparationTimes QueryPreparationTimes { get; } - - /// - /// Gets the query index lookup time in the Azure Cosmos database service. - /// - public TimeSpan IndexLookupTime { get; } - - /// - /// Gets the document loading time during query in the Azure Cosmos database service. - /// - public TimeSpan DocumentLoadTime { get; } - - /// - /// Gets the query runtime execution times during query in the Azure Cosmos database service. - /// - public RuntimeExecutionTimes RuntimeExecutionTimes { get; } - - /// - /// Gets the output writing/serializing time during query in the Azure Cosmos database service. - /// - public TimeSpan DocumentWriteTime { get; } - - /// - /// Gets the index hit ratio by query in the Azure Cosmos database service. - /// - public double IndexHitRatio { get; } - - /// - /// Gets the VMExecution Time. - /// - public TimeSpan VMExecutionTime { get; } - - public override string ToString() - { - return $"totalExecutionTimeInMs={this.TotalTime.TotalMilliseconds};queryCompileTimeInMs={this.QueryPreparationTimes.QueryCompilationTime.TotalMilliseconds};queryLogicalPlanBuildTimeInMs={this.QueryPreparationTimes.LogicalPlanBuildTime.TotalMilliseconds};queryPhysicalPlanBuildTimeInMs={this.QueryPreparationTimes.PhysicalPlanBuildTime.TotalMilliseconds};queryOptimizationTimeInMs={this.QueryPreparationTimes.QueryOptimizationTime.TotalMilliseconds};indexLookupTimeInMs={this.IndexLookupTime.TotalMilliseconds};documentLoadTimeInMs={this.DocumentLoadTime.TotalMilliseconds};systemFunctionExecuteTimeInMs={this.RuntimeExecutionTimes.SystemFunctionExecutionTime.TotalMilliseconds};userFunctionExecuteTimeInMs={this.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime.TotalMilliseconds};retrievedDocumentCount={this.RetrievedDocumentCount};retrievedDocumentSize={this.RetrievedDocumentSize};outputDocumentCount={this.OutputDocumentCount};outputDocumentSize={this.OutputDocumentSize};writeOutputTimeInMs={this.DocumentWriteTime.TotalMilliseconds};indexUtilizationRatio={this.IndexHitRatio}"; - } - - public static BackendMetrics CreateFromIEnumerable(IEnumerable backendMetricsEnumerable) - { - BackendMetrics.Accumulator accumulator = default; - foreach (BackendMetrics backendMetrics in backendMetricsEnumerable) - { - accumulator = accumulator.Accumulate(backendMetrics); - } - - return BackendMetrics.Accumulator.ToBackendMetrics(accumulator); - } - - public static bool TryParseFromDelimitedString(string delimitedString, out BackendMetrics backendMetrics) - { - return BackendMetricsParser.TryParse(delimitedString, out backendMetrics); - } - - public static BackendMetrics ParseFromDelimitedString(string delimitedString) - { - if (!BackendMetricsParser.TryParse(delimitedString, out BackendMetrics backendMetrics)) - { - throw new FormatException(); - } - - return backendMetrics; - } - - public ref struct Accumulator - { - public Accumulator( - TimeSpan totalTime, - long retrievedDocumentCount, - long retrievedDocumentSize, - long outputDocumentCount, - long outputDocumentSize, - double indexHitRatio, - QueryPreparationTimes.Accumulator queryPreparationTimesAccumulator, - TimeSpan indexLookupTime, - TimeSpan documentLoadTime, - RuntimeExecutionTimes.Accumulator runtimeExecutionTimesAccumulator, - TimeSpan documentWriteTime, - TimeSpan vmExecutionTime) - { - this.TotalTime = totalTime; - this.RetrievedDocumentCount = retrievedDocumentCount; - this.RetrievedDocumentSize = retrievedDocumentSize; - this.OutputDocumentCount = outputDocumentCount; - this.OutputDocumentSize = outputDocumentSize; - this.IndexHitRatio = indexHitRatio; - this.QueryPreparationTimesAccumulator = queryPreparationTimesAccumulator; - this.IndexLookupTime = indexLookupTime; - this.DocumentLoadTime = documentLoadTime; - this.RuntimeExecutionTimesAccumulator = runtimeExecutionTimesAccumulator; - this.DocumentWriteTime = documentWriteTime; - this.VMExecutionTime = vmExecutionTime; - } - - public TimeSpan TotalTime { get; } - public long RetrievedDocumentCount { get; } - public long RetrievedDocumentSize { get; } - public long OutputDocumentCount { get; } - public long OutputDocumentSize { get; } - public double IndexHitRatio { get; } - public QueryPreparationTimes.Accumulator QueryPreparationTimesAccumulator { get; } - public TimeSpan IndexLookupTime { get; } - public TimeSpan DocumentLoadTime { get; } - public RuntimeExecutionTimes.Accumulator RuntimeExecutionTimesAccumulator { get; } - public TimeSpan DocumentWriteTime { get; } - public TimeSpan VMExecutionTime { get; } - - public Accumulator Accumulate(BackendMetrics backendMetrics) - { - return new Accumulator( - totalTime: this.TotalTime + backendMetrics.TotalTime, - retrievedDocumentCount: this.RetrievedDocumentCount + backendMetrics.RetrievedDocumentCount, - retrievedDocumentSize: this.RetrievedDocumentSize + backendMetrics.RetrievedDocumentSize, - outputDocumentCount: this.OutputDocumentCount + backendMetrics.OutputDocumentCount, - outputDocumentSize: this.OutputDocumentSize + backendMetrics.OutputDocumentSize, - indexHitRatio: ((this.OutputDocumentCount * this.IndexHitRatio) + (backendMetrics.OutputDocumentCount * backendMetrics.IndexHitRatio)) / (this.RetrievedDocumentCount + backendMetrics.RetrievedDocumentCount), - queryPreparationTimesAccumulator: this.QueryPreparationTimesAccumulator.Accumulate(backendMetrics.QueryPreparationTimes), - indexLookupTime: this.IndexLookupTime + backendMetrics.IndexLookupTime, - documentLoadTime: this.DocumentLoadTime + backendMetrics.DocumentLoadTime, - runtimeExecutionTimesAccumulator: this.RuntimeExecutionTimesAccumulator.Accumulate(backendMetrics.RuntimeExecutionTimes), - documentWriteTime: this.DocumentWriteTime + backendMetrics.DocumentWriteTime, - vmExecutionTime: this.VMExecutionTime + backendMetrics.VMExecutionTime); - - } - - public static BackendMetrics ToBackendMetrics(BackendMetrics.Accumulator accumulator) - { - return new BackendMetrics( - retrievedDocumentCount: accumulator.RetrievedDocumentCount, - retrievedDocumentSize: accumulator.RetrievedDocumentSize, - outputDocumentCount: accumulator.OutputDocumentCount, - outputDocumentSize: accumulator.OutputDocumentSize, - indexHitRatio: accumulator.IndexHitRatio, - totalQueryExecutionTime: accumulator.TotalTime, - queryPreparationTimes: QueryPreparationTimes.Accumulator.ToQueryPreparationTimes(accumulator.QueryPreparationTimesAccumulator), - indexLookupTime: accumulator.IndexLookupTime, - documentLoadTime: accumulator.DocumentLoadTime, - vmExecutionTime: accumulator.VMExecutionTime, - runtimeExecutionTimes: RuntimeExecutionTimes.Accumulator.ToRuntimeExecutionTimes(accumulator.RuntimeExecutionTimesAccumulator), - documentWriteTime: accumulator.DocumentWriteTime); - } - } - } -} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetrics.cs index e69f4c5808..ff68271a69 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetrics.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetrics.cs @@ -5,7 +5,6 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics { using System; using System.Collections.Generic; - using System.Linq; /// /// Stores client side QueryMetrics. @@ -54,42 +53,5 @@ public ClientSideMetrics( /// Gets the Fetch Execution Ranges for this continuation of the query. /// public IEnumerable FetchExecutionRanges { get; } - - public ref struct Accumulator - { - public Accumulator(long retries, double requestCharge, IEnumerable fetchExecutionRanges) - { - this.Retries = retries; - this.RequestCharge = requestCharge; - this.FetchExecutionRanges = fetchExecutionRanges; - } - - public long Retries { get; } - - public double RequestCharge { get; } - - public IEnumerable FetchExecutionRanges { get; } - - public Accumulator Accumulate(ClientSideMetrics clientSideMetrics) - { - if (clientSideMetrics == null) - { - throw new ArgumentNullException(nameof(clientSideMetrics)); - } - - return new Accumulator( - retries: this.Retries + clientSideMetrics.Retries, - requestCharge: this.RequestCharge + clientSideMetrics.RequestCharge, - fetchExecutionRanges: (this.FetchExecutionRanges ?? Enumerable.Empty()).Concat(clientSideMetrics.FetchExecutionRanges)); - } - - public static ClientSideMetrics ToClientSideMetrics(Accumulator accumulator) - { - return new ClientSideMetrics( - retries: accumulator.Retries, - requestCharge: accumulator.RequestCharge, - fetchExecutionRanges: accumulator.FetchExecutionRanges); - } - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetricsAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetricsAccumulator.cs new file mode 100644 index 0000000000..57816580b6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ClientSideMetricsAccumulator.cs @@ -0,0 +1,47 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + internal sealed class ClientSideMetricsAccumulator + { + private readonly List clientSideMetricsList; + + public ClientSideMetricsAccumulator() + { + this.clientSideMetricsList = new List(); + } + + public void Accumulate(ClientSideMetrics clientSideMetrics) + { + if (clientSideMetrics == null) + { + throw new ArgumentNullException(nameof(clientSideMetrics)); + } + + this.clientSideMetricsList.Add(clientSideMetrics); + } + + public ClientSideMetrics GetClientSideMetrics() + { + long retries = 0; + double requestCharge = 0; + List fetchExecutionRanges = new List(); + + foreach (ClientSideMetrics clientSideMetrics in this.clientSideMetricsList) + { + retries += clientSideMetrics.Retries; + requestCharge += clientSideMetrics.RequestCharge; + fetchExecutionRanges.AddRange(clientSideMetrics.FetchExecutionRanges); + } + + return new ClientSideMetrics( + retries: retries, + requestCharge: requestCharge, + fetchExecutionRanges: fetchExecutionRanges); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs index 2dba73132e..e34a7902ad 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfo.cs @@ -125,43 +125,5 @@ public static IndexUtilizationInfo CreateFromString(string delimitedString, bool return indexUtilizationInfo; } - - public ref struct Accumulator - { - public Accumulator( - IEnumerable utilizedSingleIndexes, - IEnumerable potentialSingleIndexes, - IEnumerable utilizedCompositeIndexes, - IEnumerable potentialCompositeIndexes) - { - this.UtilizedSingleIndexes = utilizedSingleIndexes; - this.PotentialSingleIndexes = potentialSingleIndexes; - this.UtilizedCompositeIndexes = utilizedCompositeIndexes; - this.PotentialCompositeIndexes = potentialCompositeIndexes; - } - - public IEnumerable UtilizedSingleIndexes { get; } - public IEnumerable PotentialSingleIndexes { get; } - public IEnumerable UtilizedCompositeIndexes { get; } - public IEnumerable PotentialCompositeIndexes { get; } - - public Accumulator Accumulate(IndexUtilizationInfo indexUtilizationInfo) - { - return new Accumulator( - utilizedSingleIndexes: (this.UtilizedSingleIndexes ?? Enumerable.Empty()).Concat(indexUtilizationInfo.UtilizedSingleIndexes), - potentialSingleIndexes: (this.PotentialSingleIndexes ?? Enumerable.Empty()).Concat(indexUtilizationInfo.PotentialSingleIndexes), - utilizedCompositeIndexes: (this.UtilizedCompositeIndexes ?? Enumerable.Empty()).Concat(indexUtilizationInfo.UtilizedCompositeIndexes), - potentialCompositeIndexes: (this.PotentialCompositeIndexes ?? Enumerable.Empty()).Concat(indexUtilizationInfo.PotentialCompositeIndexes)); - } - - public static IndexUtilizationInfo ToIndexUtilizationInfo(Accumulator accumulator) - { - return new IndexUtilizationInfo( - utilizedSingleIndexes: accumulator.UtilizedSingleIndexes.ToList(), - potentialSingleIndexes: accumulator.PotentialSingleIndexes.ToList(), - utilizedCompositeIndexes: accumulator.UtilizedCompositeIndexes.ToList(), - potentialCompositeIndexes: accumulator.PotentialCompositeIndexes.ToList()); - } - } } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfoAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfoAccumulator.cs new file mode 100644 index 0000000000..978abba77a --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexUtilizationInfoAccumulator.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + internal sealed class IndexUtilizationInfoAccumulator + { + private readonly List indexUtilizationInfoList; + + public IndexUtilizationInfoAccumulator() + { + this.indexUtilizationInfoList = new List(); + } + + public void Accumulate(IndexUtilizationInfo indexUtilizationInfo) + { + if (indexUtilizationInfo == null) + { + throw new ArgumentNullException(nameof(indexUtilizationInfo)); + } + + this.indexUtilizationInfoList.Add(indexUtilizationInfo); + } + + public IndexUtilizationInfo GetIndexUtilizationInfo() + { + List utilizedSingleIndexes = new List(); + List potentialSingleIndexes = new List(); + List utilizedCompositeIndexes = new List(); + List potentialCompositeIndexes = new List(); + + foreach (IndexUtilizationInfo indexUtilizationInfo in this.indexUtilizationInfoList) + { + utilizedSingleIndexes.AddRange(indexUtilizationInfo.UtilizedSingleIndexes); + potentialSingleIndexes.AddRange(indexUtilizationInfo.PotentialSingleIndexes); + utilizedCompositeIndexes.AddRange(indexUtilizationInfo.UtilizedCompositeIndexes); + potentialCompositeIndexes.AddRange(indexUtilizationInfo.PotentialCompositeIndexes); + } + + return new IndexUtilizationInfo( + utilizedSingleIndexes: utilizedSingleIndexes, + potentialSingleIndexes: potentialSingleIndexes, + utilizedCompositeIndexes: utilizedCompositeIndexes, + potentialCompositeIndexes: potentialCompositeIndexes); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetrics.cs index 5a7e9377ed..ed3993d47e 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetrics.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetrics.cs @@ -29,11 +29,11 @@ sealed class QueryMetrics clientSideMetrics: ClientSideMetrics.Empty); public QueryMetrics( - BackendMetrics backendMetrics, - IndexUtilizationInfo indexUtilizationInfo, - ClientSideMetrics clientSideMetrics) + ServerSideMetricsInternal serverSideMetrics, + IndexUtilizationInfo indexUtilizationInfo, + ClientSideMetrics clientSideMetrics) { - this.BackendMetrics = backendMetrics ?? throw new ArgumentNullException(nameof(backendMetrics)); + this.ServerSideMetrics = serverSideMetrics ?? throw new ArgumentNullException(nameof(serverSideMetrics)); this.IndexUtilizationInfo = indexUtilizationInfo ?? throw new ArgumentNullException(nameof(indexUtilizationInfo)); this.ClientSideMetrics = clientSideMetrics ?? throw new ArgumentNullException(nameof(clientSideMetrics)); } @@ -43,13 +43,13 @@ public QueryMetrics( IndexUtilizationInfo indexUtilizationInfo, ClientSideMetrics clientSideMetrics) : this(!String.IsNullOrWhiteSpace(deliminatedString) && - BackendMetricsParser.TryParse(deliminatedString, out BackendMetrics backendMetrics) - ? backendMetrics - : BackendMetrics.Empty, indexUtilizationInfo, clientSideMetrics) + ServerSideMetricsParser.TryParse(deliminatedString, out ServerSideMetricsInternal serverSideMetrics) + ? serverSideMetrics + : ServerSideMetricsInternal.Empty, indexUtilizationInfo, clientSideMetrics) { } - public BackendMetrics BackendMetrics { get; } + public ServerSideMetricsInternal ServerSideMetrics { get; } public IndexUtilizationInfo IndexUtilizationInfo { get; } @@ -63,11 +63,11 @@ public QueryMetrics( /// A new instance that is the sum of two instances public static QueryMetrics operator +(QueryMetrics queryMetrics1, QueryMetrics queryMetrics2) { - QueryMetrics.Accumulator queryMetricsAccumulator = new QueryMetrics.Accumulator(); - queryMetricsAccumulator = queryMetricsAccumulator.Accumulate(queryMetrics1); - queryMetricsAccumulator = queryMetricsAccumulator.Accumulate(queryMetrics2); + QueryMetricsAccumulator queryMetricsAccumulator = new QueryMetricsAccumulator(); + queryMetricsAccumulator.Accumulate(queryMetrics1); + queryMetricsAccumulator.Accumulate(queryMetrics2); - return QueryMetrics.Accumulator.ToQueryMetrics(queryMetricsAccumulator); + return queryMetricsAccumulator.GetQueryMetrics(); } /// @@ -94,53 +94,13 @@ public static QueryMetrics CreateFromIEnumerable(IEnumerable query throw new ArgumentNullException(nameof(queryMetricsList)); } - QueryMetrics.Accumulator queryMetricsAccumulator = new QueryMetrics.Accumulator(); + QueryMetricsAccumulator queryMetricsAccumulator = new QueryMetricsAccumulator(); foreach (QueryMetrics queryMetrics in queryMetricsList) { - queryMetricsAccumulator = queryMetricsAccumulator.Accumulate(queryMetrics); + queryMetricsAccumulator.Accumulate(queryMetrics); } - return QueryMetrics.Accumulator.ToQueryMetrics(queryMetricsAccumulator); - } - - public ref struct Accumulator - { - public Accumulator( - BackendMetrics.Accumulator backendMetricsAccumulator, - IndexUtilizationInfo.Accumulator indexUtilizationInfoAccumulator, - ClientSideMetrics.Accumulator clientSideMetricsAccumulator) - { - this.BackendMetricsAccumulator = backendMetricsAccumulator; - this.IndexUtilizationInfoAccumulator = indexUtilizationInfoAccumulator; - this.ClientSideMetricsAccumulator = clientSideMetricsAccumulator; - } - - public BackendMetrics.Accumulator BackendMetricsAccumulator { get; } - - public IndexUtilizationInfo.Accumulator IndexUtilizationInfoAccumulator { get; } - - public ClientSideMetrics.Accumulator ClientSideMetricsAccumulator { get; } - - public Accumulator Accumulate(QueryMetrics queryMetrics) - { - if (queryMetrics == null) - { - throw new ArgumentNullException(nameof(queryMetrics)); - } - - return new Accumulator( - backendMetricsAccumulator: this.BackendMetricsAccumulator.Accumulate(queryMetrics.BackendMetrics), - indexUtilizationInfoAccumulator: this.IndexUtilizationInfoAccumulator.Accumulate(queryMetrics.IndexUtilizationInfo), - clientSideMetricsAccumulator: this.ClientSideMetricsAccumulator.Accumulate(queryMetrics.ClientSideMetrics)); - } - - public static QueryMetrics ToQueryMetrics(Accumulator accumulator) - { - return new QueryMetrics( - BackendMetrics.Accumulator.ToBackendMetrics(accumulator.BackendMetricsAccumulator), - IndexUtilizationInfo.Accumulator.ToIndexUtilizationInfo(accumulator.IndexUtilizationInfoAccumulator), - ClientSideMetrics.Accumulator.ToClientSideMetrics(accumulator.ClientSideMetricsAccumulator)); - } + return queryMetricsAccumulator.GetQueryMetrics(); } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsAccumulator.cs new file mode 100644 index 0000000000..b6b817e95d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsAccumulator.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + internal sealed class QueryMetricsAccumulator + { + private readonly List queryMetricsList; + + public QueryMetricsAccumulator() + { + this.queryMetricsList = new List(); + } + + public void Accumulate(QueryMetrics queryMetrics) + { + if (queryMetrics == null) + { + throw new ArgumentNullException(nameof(queryMetrics)); + } + + this.queryMetricsList.Add(queryMetrics); + } + + public QueryMetrics GetQueryMetrics() + { + ServerSideMetricsInternalAccumulator serverSideMetricsAccumulator = new ServerSideMetricsInternalAccumulator(); + IndexUtilizationInfoAccumulator indexUtilizationInfoAccumulator = new IndexUtilizationInfoAccumulator(); + ClientSideMetricsAccumulator clientSideMetricsAccumulator = new ClientSideMetricsAccumulator(); + + foreach (QueryMetrics queryMetrics in this.queryMetricsList) + { + serverSideMetricsAccumulator.Accumulate(queryMetrics.ServerSideMetrics); + indexUtilizationInfoAccumulator.Accumulate(queryMetrics.IndexUtilizationInfo); + clientSideMetricsAccumulator.Accumulate(queryMetrics.ClientSideMetrics); + } + + return new QueryMetrics( + serverSideMetricsAccumulator.GetServerSideMetrics(), + indexUtilizationInfoAccumulator.GetIndexUtilizationInfo(), + clientSideMetricsAccumulator.GetClientSideMetrics()); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsTextWriter.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsTextWriter.cs index bd634815e9..1802e60e28 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsTextWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsTextWriter.cs @@ -215,7 +215,7 @@ protected override void WriteTotalQueryExecutionTime(TimeSpan totalQueryExecutio indentLevel: 0); } - protected override void WriteQueryPreparationTime(QueryPreparationTimes queryPreparationTimes) + protected override void WriteQueryPreparationTime(QueryPreparationTimesInternal queryPreparationTimes) { QueryMetricsTextWriter.AppendTimeSpanToStringBuilder( this.stringBuilder, @@ -250,7 +250,7 @@ protected override void WriteVMExecutionTime(TimeSpan vmExecutionTime) // Do Nothing } - protected override void WriteRuntimeExecutionTime(RuntimeExecutionTimes runtimeExecutionTimes) + protected override void WriteRuntimeExecutionTime(RuntimeExecutionTimesInternal runtimeExecutionTimes) { QueryMetricsTextWriter.AppendTimeSpanToStringBuilder( this.stringBuilder, diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsWriter.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsWriter.cs index 2fbb455152..f0d6f7b0fa 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsWriter.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryMetricsWriter.cs @@ -23,25 +23,25 @@ public void WriteQueryMetrics(QueryMetrics queryMetrics) this.WriteBeforeQueryMetrics(); // Top Level Properties - this.WriteRetrievedDocumentCount(queryMetrics.BackendMetrics.RetrievedDocumentCount); - this.WriteRetrievedDocumentSize(queryMetrics.BackendMetrics.RetrievedDocumentSize); - this.WriteOutputDocumentCount(queryMetrics.BackendMetrics.OutputDocumentCount); - this.WriteOutputDocumentSize(queryMetrics.BackendMetrics.OutputDocumentSize); - this.WriteIndexHitRatio(queryMetrics.BackendMetrics.IndexHitRatio); + this.WriteRetrievedDocumentCount(queryMetrics.ServerSideMetrics.RetrievedDocumentCount); + this.WriteRetrievedDocumentSize(queryMetrics.ServerSideMetrics.RetrievedDocumentSize); + this.WriteOutputDocumentCount(queryMetrics.ServerSideMetrics.OutputDocumentCount); + this.WriteOutputDocumentSize(queryMetrics.ServerSideMetrics.OutputDocumentSize); + this.WriteIndexHitRatio(queryMetrics.ServerSideMetrics.IndexHitRatio); - this.WriteTotalQueryExecutionTime(queryMetrics.BackendMetrics.TotalTime); + this.WriteTotalQueryExecutionTime(queryMetrics.ServerSideMetrics.TotalTime); // QueryPreparationTimes - this.WriteQueryPreparationTime(queryMetrics.BackendMetrics.QueryPreparationTimes); + this.WriteQueryPreparationTime(queryMetrics.ServerSideMetrics.QueryPreparationTimes); - this.WriteIndexLookupTime(queryMetrics.BackendMetrics.IndexLookupTime); - this.WriteDocumentLoadTime(queryMetrics.BackendMetrics.DocumentLoadTime); - this.WriteVMExecutionTime(queryMetrics.BackendMetrics.VMExecutionTime); + this.WriteIndexLookupTime(queryMetrics.ServerSideMetrics.IndexLookupTime); + this.WriteDocumentLoadTime(queryMetrics.ServerSideMetrics.DocumentLoadTime); + this.WriteVMExecutionTime(queryMetrics.ServerSideMetrics.VMExecutionTime); // RuntimesExecutionTimes - this.WriteRuntimeExecutionTime(queryMetrics.BackendMetrics.RuntimeExecutionTimes); + this.WriteRuntimeExecutionTime(queryMetrics.ServerSideMetrics.RuntimeExecutionTimes); - this.WriteDocumentWriteTime(queryMetrics.BackendMetrics.DocumentWriteTime); + this.WriteDocumentWriteTime(queryMetrics.ServerSideMetrics.DocumentWriteTime); #if false // ClientSideMetrics this.WriteClientSideMetrics(queryMetrics.ClientSideMetrics); @@ -70,7 +70,7 @@ public void WriteQueryMetrics(QueryMetrics queryMetrics) protected abstract void WriteTotalQueryExecutionTime(TimeSpan totalQueryExecutionTime); - protected abstract void WriteQueryPreparationTime(QueryPreparationTimes queryPreparationTimes); + protected abstract void WriteQueryPreparationTime(QueryPreparationTimesInternal queryPreparationTimes); protected abstract void WriteIndexLookupTime(TimeSpan indexLookupTime); @@ -78,7 +78,7 @@ public void WriteQueryMetrics(QueryMetrics queryMetrics) protected abstract void WriteVMExecutionTime(TimeSpan vMExecutionTime); - protected abstract void WriteRuntimeExecutionTime(RuntimeExecutionTimes runtimeExecutionTimes); + protected abstract void WriteRuntimeExecutionTime(RuntimeExecutionTimesInternal runtimeExecutionTimes); protected abstract void WriteDocumentWriteTime(TimeSpan documentWriteTime); diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimes.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimes.cs deleted file mode 100644 index 4b2d3b1b20..0000000000 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimes.cs +++ /dev/null @@ -1,104 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Cosmos.Query.Core.Metrics -{ - using System; - - /// - /// Query preparation metrics in the Azure DocumentDB database service. - /// -#if INTERNAL -#pragma warning disable SA1600 -#pragma warning disable CS1591 - public -#else - internal -#endif - sealed class QueryPreparationTimes - { - public static readonly QueryPreparationTimes Zero = new QueryPreparationTimes( - queryCompilationTime: default, - logicalPlanBuildTime: default, - physicalPlanBuildTime: default, - queryOptimizationTime: default); - - /// - /// Initializes a new instance of the QueryPreparationTimes class. - /// - /// Query compile and optimization time - /// Query logical plan build time - /// Query physical plan build time - /// Query optimization time - public QueryPreparationTimes( - TimeSpan queryCompilationTime, - TimeSpan logicalPlanBuildTime, - TimeSpan physicalPlanBuildTime, - TimeSpan queryOptimizationTime) - { - this.QueryCompilationTime = queryCompilationTime; - this.LogicalPlanBuildTime = logicalPlanBuildTime; - this.PhysicalPlanBuildTime = physicalPlanBuildTime; - this.QueryOptimizationTime = queryOptimizationTime; - } - - /// - /// Gets the query compile time in the Azure DocumentDB database service. - /// - public TimeSpan QueryCompilationTime { get; } - - /// - /// Gets the query logical plan build time in the Azure DocumentDB database service. - /// - public TimeSpan LogicalPlanBuildTime { get; } - - /// - /// Gets the query physical plan build time in the Azure DocumentDB database service. - /// - public TimeSpan PhysicalPlanBuildTime { get; } - - /// - /// Gets the query optimization time in the Azure DocumentDB database service. - /// - public TimeSpan QueryOptimizationTime { get; } - - public ref struct Accumulator - { - public Accumulator(TimeSpan queryCompliationTime, TimeSpan logicalPlanBuildTime, TimeSpan physicalPlanBuildTime, TimeSpan queryOptimizationTime) - { - this.QueryCompilationTime = queryCompliationTime; - this.LogicalPlanBuildTime = logicalPlanBuildTime; - this.PhysicalPlanBuildTime = physicalPlanBuildTime; - this.QueryOptimizationTime = queryOptimizationTime; - } - - public TimeSpan QueryCompilationTime { get; } - public TimeSpan LogicalPlanBuildTime { get; } - public TimeSpan PhysicalPlanBuildTime { get; } - public TimeSpan QueryOptimizationTime { get; } - - public Accumulator Accumulate(QueryPreparationTimes queryPreparationTimes) - { - if (queryPreparationTimes == null) - { - throw new ArgumentNullException(nameof(queryPreparationTimes)); - } - - return new Accumulator( - queryCompliationTime: this.QueryCompilationTime + queryPreparationTimes.QueryCompilationTime, - logicalPlanBuildTime: this.LogicalPlanBuildTime + queryPreparationTimes.LogicalPlanBuildTime, - physicalPlanBuildTime: this.PhysicalPlanBuildTime + queryPreparationTimes.PhysicalPlanBuildTime, - queryOptimizationTime: this.QueryOptimizationTime + queryPreparationTimes.QueryOptimizationTime); - } - - public static QueryPreparationTimes ToQueryPreparationTimes(QueryPreparationTimes.Accumulator accumulator) - { - return new QueryPreparationTimes( - queryCompilationTime: accumulator.QueryCompilationTime, - logicalPlanBuildTime: accumulator.LogicalPlanBuildTime, - physicalPlanBuildTime: accumulator.PhysicalPlanBuildTime, - queryOptimizationTime: accumulator.QueryOptimizationTime); - } - } - } -} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesAccumulator.cs new file mode 100644 index 0000000000..6b79e8c1f8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesAccumulator.cs @@ -0,0 +1,51 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + internal sealed class QueryPreparationTimesAccumulator + { + private readonly List queryPreparationTimesList; + + public QueryPreparationTimesAccumulator() + { + this.queryPreparationTimesList = new List(); + } + + public void Accumulate(QueryPreparationTimesInternal queryPreparationTimes) + { + if (queryPreparationTimes == null) + { + throw new ArgumentNullException(nameof(queryPreparationTimes)); + } + + this.queryPreparationTimesList.Add(queryPreparationTimes); + } + + public QueryPreparationTimesInternal GetQueryPreparationTimes() + { + TimeSpan queryCompilationTime = TimeSpan.Zero; + TimeSpan logicalPlanBuildTime = TimeSpan.Zero; + TimeSpan physicalPlanBuildTime = TimeSpan.Zero; + TimeSpan queryOptimizationTime = TimeSpan.Zero; + + foreach (QueryPreparationTimesInternal queryPreparationTimes in this.queryPreparationTimesList) + { + queryCompilationTime += queryPreparationTimes.QueryCompilationTime; + logicalPlanBuildTime += queryPreparationTimes.LogicalPlanBuildTime; + physicalPlanBuildTime += queryPreparationTimes.PhysicalPlanBuildTime; + queryOptimizationTime += queryPreparationTimes.QueryOptimizationTime; + } + + return new QueryPreparationTimesInternal( + queryCompilationTime: queryCompilationTime, + logicalPlanBuildTime: logicalPlanBuildTime, + physicalPlanBuildTime: physicalPlanBuildTime, + queryOptimizationTime: queryOptimizationTime); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesInternal.cs new file mode 100644 index 0000000000..4e8ee38276 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/QueryPreparationTimesInternal.cs @@ -0,0 +1,65 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + + /// + /// Query preparation metrics in the Azure DocumentDB database service. + /// +#if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class QueryPreparationTimesInternal + { + public static readonly QueryPreparationTimesInternal Zero = new QueryPreparationTimesInternal( + queryCompilationTime: TimeSpan.Zero, + logicalPlanBuildTime: TimeSpan.Zero, + physicalPlanBuildTime: TimeSpan.Zero, + queryOptimizationTime: TimeSpan.Zero); + + /// + /// Initializes a new instance of the QueryPreparationTimes class. + /// + /// Query compile and optimization time + /// Query logical plan build time + /// Query physical plan build time + /// Query optimization time + public QueryPreparationTimesInternal( + TimeSpan queryCompilationTime, + TimeSpan logicalPlanBuildTime, + TimeSpan physicalPlanBuildTime, + TimeSpan queryOptimizationTime) + { + this.QueryCompilationTime = queryCompilationTime; + this.LogicalPlanBuildTime = logicalPlanBuildTime; + this.PhysicalPlanBuildTime = physicalPlanBuildTime; + this.QueryOptimizationTime = queryOptimizationTime; + } + + /// + /// Gets the query compile time in the Azure DocumentDB database service. + /// + public TimeSpan QueryCompilationTime { get; } + + /// + /// Gets the query logical plan build time in the Azure DocumentDB database service. + /// + public TimeSpan LogicalPlanBuildTime { get; } + + /// + /// Gets the query physical plan build time in the Azure DocumentDB database service. + /// + public TimeSpan PhysicalPlanBuildTime { get; } + + /// + /// Gets the query optimization time in the Azure DocumentDB database service. + /// + public TimeSpan QueryOptimizationTime { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimes.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimes.cs deleted file mode 100644 index 0fd8dc22f0..0000000000 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimes.cs +++ /dev/null @@ -1,91 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ -namespace Microsoft.Azure.Cosmos.Query.Core.Metrics -{ - using System; - - /// - /// Query runtime execution times in the Azure Cosmos DB service. - /// -#if INTERNAL -#pragma warning disable SA1600 -#pragma warning disable CS1591 - public -#else - internal -#endif - sealed class RuntimeExecutionTimes - { - public static readonly RuntimeExecutionTimes Empty = new RuntimeExecutionTimes( - queryEngineExecutionTime: default, - systemFunctionExecutionTime: default, - userDefinedFunctionExecutionTime: default); - - /// - /// Initializes a new instance of the RuntimeExecutionTimes class. - /// - /// Query end - to - end execution time - /// Total time spent executing system functions - /// Total time spent executing user - defined functions - public RuntimeExecutionTimes( - TimeSpan queryEngineExecutionTime, - TimeSpan systemFunctionExecutionTime, - TimeSpan userDefinedFunctionExecutionTime) - { - this.QueryEngineExecutionTime = queryEngineExecutionTime; - this.SystemFunctionExecutionTime = systemFunctionExecutionTime; - this.UserDefinedFunctionExecutionTime = userDefinedFunctionExecutionTime; - } - - /// - /// Gets the total query runtime execution time in the Azure Cosmos DB service. - /// - public TimeSpan QueryEngineExecutionTime { get; } - - /// - /// Gets the query system function execution time in the Azure Cosmos DB service. - /// - public TimeSpan SystemFunctionExecutionTime { get; } - - /// - /// Gets the query user defined function execution time in the Azure Cosmos DB service. - /// - public TimeSpan UserDefinedFunctionExecutionTime { get; } - - public ref struct Accumulator - { - public Accumulator(TimeSpan queryEngineExecutionTime, TimeSpan systemFunctionExecutionTime, TimeSpan userDefinedFunctionExecutionTimes) - { - this.QueryEngineExecutionTime = queryEngineExecutionTime; - this.SystemFunctionExecutionTime = systemFunctionExecutionTime; - this.UserDefinedFunctionExecutionTime = userDefinedFunctionExecutionTimes; - } - - public TimeSpan QueryEngineExecutionTime { get; set; } - public TimeSpan SystemFunctionExecutionTime { get; set; } - public TimeSpan UserDefinedFunctionExecutionTime { get; set; } - - public Accumulator Accumulate(RuntimeExecutionTimes runtimeExecutionTimes) - { - if (runtimeExecutionTimes == null) - { - throw new ArgumentNullException(nameof(runtimeExecutionTimes)); - } - - return new Accumulator( - queryEngineExecutionTime: this.QueryEngineExecutionTime + runtimeExecutionTimes.QueryEngineExecutionTime, - systemFunctionExecutionTime: this.SystemFunctionExecutionTime + runtimeExecutionTimes.SystemFunctionExecutionTime, - userDefinedFunctionExecutionTimes: this.UserDefinedFunctionExecutionTime + runtimeExecutionTimes.UserDefinedFunctionExecutionTime); - } - - public static RuntimeExecutionTimes ToRuntimeExecutionTimes(Accumulator accumulator) - { - return new RuntimeExecutionTimes( - queryEngineExecutionTime: accumulator.QueryEngineExecutionTime, - systemFunctionExecutionTime: accumulator.SystemFunctionExecutionTime, - userDefinedFunctionExecutionTime: accumulator.UserDefinedFunctionExecutionTime); - } - } - } -} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesAccumulator.cs new file mode 100644 index 0000000000..60f5e37573 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesAccumulator.cs @@ -0,0 +1,48 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + internal sealed class RuntimeExecutionTimesAccumulator + { + private readonly List runtimeExecutionTimesList; + + public RuntimeExecutionTimesAccumulator() + { + this.runtimeExecutionTimesList = new List(); + } + + public void Accumulate(RuntimeExecutionTimesInternal runtimeExecutionTimes) + { + if (runtimeExecutionTimes == null) + { + throw new ArgumentNullException(nameof(runtimeExecutionTimes)); + } + + this.runtimeExecutionTimesList.Add(runtimeExecutionTimes); + } + + public RuntimeExecutionTimesInternal GetRuntimeExecutionTimes() + { + TimeSpan queryEngineExecutionTime = TimeSpan.Zero; + TimeSpan systemFunctionExecutionTime = TimeSpan.Zero; + TimeSpan userDefinedFunctionExecutionTime = TimeSpan.Zero; + + foreach (RuntimeExecutionTimesInternal runtimeExecutionTimes in this.runtimeExecutionTimesList) + { + queryEngineExecutionTime += runtimeExecutionTimes.QueryEngineExecutionTime; + systemFunctionExecutionTime += runtimeExecutionTimes.SystemFunctionExecutionTime; + userDefinedFunctionExecutionTime += runtimeExecutionTimes.UserDefinedFunctionExecutionTime; + } + + return new RuntimeExecutionTimesInternal( + queryEngineExecutionTime: queryEngineExecutionTime, + systemFunctionExecutionTime: systemFunctionExecutionTime, + userDefinedFunctionExecutionTime: userDefinedFunctionExecutionTime); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesInternal.cs new file mode 100644 index 0000000000..bbd97ca45d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/RuntimeExecutionTimesInternal.cs @@ -0,0 +1,56 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + + /// + /// Query runtime execution times in the Azure Cosmos DB service. + /// +#if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class RuntimeExecutionTimesInternal + { + public static readonly RuntimeExecutionTimesInternal Empty = new RuntimeExecutionTimesInternal( + queryEngineExecutionTime: TimeSpan.Zero, + systemFunctionExecutionTime: TimeSpan.Zero, + userDefinedFunctionExecutionTime: TimeSpan.Zero); + + /// + /// Initializes a new instance of the RuntimeExecutionTimes class. + /// + /// Query end - to - end execution time + /// Total time spent executing system functions + /// Total time spent executing user - defined functions + public RuntimeExecutionTimesInternal( + TimeSpan queryEngineExecutionTime, + TimeSpan systemFunctionExecutionTime, + TimeSpan userDefinedFunctionExecutionTime) + { + this.QueryEngineExecutionTime = queryEngineExecutionTime; + this.SystemFunctionExecutionTime = systemFunctionExecutionTime; + this.UserDefinedFunctionExecutionTime = userDefinedFunctionExecutionTime; + } + + /// + /// Gets the total query runtime execution time in the Azure Cosmos DB service. + /// + public TimeSpan QueryEngineExecutionTime { get; } + + /// + /// Gets the query system function execution time in the Azure Cosmos DB service. + /// + public TimeSpan SystemFunctionExecutionTime { get; } + + /// + /// Gets the query user defined function execution time in the Azure Cosmos DB service. + /// + public TimeSpan UserDefinedFunctionExecutionTime { get; } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs new file mode 100644 index 0000000000..3e7364f957 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetrics.cs @@ -0,0 +1,23 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + + /// + /// Metrics received for queries from the backend. + /// + public abstract class ServerSideCumulativeMetrics + { + /// + /// Gets the ServerSideMetrics accumulated for a single round trip. + /// + public abstract ServerSideMetrics CumulativeMetrics { get; } + + /// + /// Gets the list of ServerSideMetrics, one for for each partition. + /// + public abstract IReadOnlyList PartitionedMetrics { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs new file mode 100644 index 0000000000..5405482bb5 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideCumulativeMetricsInternal.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos +{ + using System.Collections.Generic; + using System.Linq; + using Microsoft.Azure.Cosmos.Query.Core.Metrics; + + /// + /// Internal implementation of metrics received for queries from the backend. + /// + internal class ServerSideCumulativeMetricsInternal : ServerSideCumulativeMetrics + { + /// + /// Initializes a new instance of the class. + /// + /// + internal ServerSideCumulativeMetricsInternal(IEnumerable serverSideMetricsList) + { + this.PartitionedMetrics = serverSideMetricsList.ToList(); + this.CumulativeMetrics = ServerSideMetricsInternal.Create(serverSideMetricsList.Select(partitionedMetrics => partitionedMetrics.ServerSideMetricsInternal)); + } + + public override ServerSideMetrics CumulativeMetrics { get; } + + public override IReadOnlyList PartitionedMetrics { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetrics.cs new file mode 100644 index 0000000000..ff215a582e --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetrics.cs @@ -0,0 +1,74 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using System; + + /// + /// Metrics received for queries from the backend. + /// + public abstract class ServerSideMetrics + { + /// + /// Gets the total query time in the Azure Cosmos database service. + /// + public abstract TimeSpan TotalTime { get; } + + /// + /// Gets the number of documents retrieved during query in the Azure Cosmos database service. + /// + public abstract long RetrievedDocumentCount { get; } + + /// + /// Gets the size of documents retrieved in bytes during query in the Azure Cosmos DB service. + /// + public abstract long RetrievedDocumentSize { get; } + + /// + /// Gets the number of documents returned by query in the Azure Cosmos DB service. + /// + public abstract long OutputDocumentCount { get; } + + /// + /// Gets the size of documents outputted in bytes during query in the Azure Cosmos database service. + /// + public abstract long OutputDocumentSize { get; } + + /// + /// Gets the query preparation time in the Azure Cosmos database service. + /// + public abstract TimeSpan QueryPreparationTime { get; } + + /// + /// Gets the query index lookup time in the Azure Cosmos database service. + /// + public abstract TimeSpan IndexLookupTime { get; } + + /// + /// Gets the document loading time during query in the Azure Cosmos database service. + /// + public abstract TimeSpan DocumentLoadTime { get; } + + /// + /// Gets the query runtime execution time during query in the Azure Cosmos database service. + /// + public abstract TimeSpan RuntimeExecutionTime { get; } + + /// + /// Gets the output writing/serializing time during query in the Azure Cosmos database service. + /// + public abstract TimeSpan DocumentWriteTime { get; } + + /// + /// Gets the index hit ratio by query in the Azure Cosmos database service. Value is within the range [0,1]. + /// + public abstract double IndexHitRatio { get; } + + /// + /// Gets the VMExecution Time. + /// + public abstract TimeSpan VMExecutionTime { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs new file mode 100644 index 0000000000..6e80de06a5 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternal.cs @@ -0,0 +1,153 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + + /// + /// internal implementation of metrics received for queries from the backend. + /// +#if INTERNAL +#pragma warning disable SA1600 +#pragma warning disable CS1591 + public +#else + internal +#endif + sealed class ServerSideMetricsInternal : ServerSideMetrics + { + /// + /// QueryMetrics with all members having default (but not null) members. + /// + public static readonly ServerSideMetricsInternal Empty = new ServerSideMetricsInternal( + retrievedDocumentCount: 0, + retrievedDocumentSize: 0, + outputDocumentCount: 0, + outputDocumentSize: 0, + indexHitRatio: 0, + totalQueryExecutionTime: TimeSpan.Zero, + queryPreparationTimes: QueryPreparationTimesInternal.Zero, + indexLookupTime: TimeSpan.Zero, + documentLoadTime: TimeSpan.Zero, + vmExecutionTime: TimeSpan.Zero, + runtimeExecutionTimes: RuntimeExecutionTimesInternal.Empty, + documentWriteTime: TimeSpan.Zero); + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public ServerSideMetricsInternal( + long retrievedDocumentCount, + long retrievedDocumentSize, + long outputDocumentCount, + long outputDocumentSize, + double indexHitRatio, + TimeSpan totalQueryExecutionTime, + QueryPreparationTimesInternal queryPreparationTimes, + TimeSpan indexLookupTime, + TimeSpan documentLoadTime, + TimeSpan vmExecutionTime, + RuntimeExecutionTimesInternal runtimeExecutionTimes, + TimeSpan documentWriteTime, + string feedRange = null, + int? partitionKeyRangeId = null) + { + this.RetrievedDocumentCount = retrievedDocumentCount; + this.RetrievedDocumentSize = retrievedDocumentSize; + this.OutputDocumentCount = outputDocumentCount; + this.OutputDocumentSize = outputDocumentSize; + this.IndexHitRatio = indexHitRatio; + this.TotalTime = totalQueryExecutionTime; + this.QueryPreparationTimes = queryPreparationTimes ?? throw new ArgumentNullException($"{nameof(queryPreparationTimes)} can not be null."); + this.IndexLookupTime = indexLookupTime; + this.DocumentLoadTime = documentLoadTime; + this.VMExecutionTime = vmExecutionTime; + this.RuntimeExecutionTimes = runtimeExecutionTimes ?? throw new ArgumentNullException($"{nameof(runtimeExecutionTimes)} can not be null."); + this.DocumentWriteTime = documentWriteTime; + this.FeedRange = feedRange; + this.PartitionKeyRangeId = partitionKeyRangeId; + } + + public override TimeSpan TotalTime { get; } + + public override long RetrievedDocumentCount { get; } + + public override long RetrievedDocumentSize { get; } + + public override long OutputDocumentCount { get; } + + public override long OutputDocumentSize { get; } + + public QueryPreparationTimesInternal QueryPreparationTimes { get; } + + public override TimeSpan QueryPreparationTime => + this.QueryPreparationTimes.LogicalPlanBuildTime + + this.QueryPreparationTimes.PhysicalPlanBuildTime + + this.QueryPreparationTimes.QueryCompilationTime + + this.QueryPreparationTimes.QueryOptimizationTime; + + public override TimeSpan IndexLookupTime { get; } + + public override TimeSpan DocumentLoadTime { get; } + + public RuntimeExecutionTimesInternal RuntimeExecutionTimes { get; } + + public override TimeSpan RuntimeExecutionTime => + this.RuntimeExecutionTimes.QueryEngineExecutionTime + + this.RuntimeExecutionTimes.SystemFunctionExecutionTime + + this.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime; + + public override TimeSpan DocumentWriteTime { get; } + + public override double IndexHitRatio { get; } + + public override TimeSpan VMExecutionTime { get; } + + public string FeedRange { get; set; } + + public int? PartitionKeyRangeId { get; set; } + + public static ServerSideMetricsInternal Create(IEnumerable serverSideMetricsEnumerable) + { + ServerSideMetricsInternalAccumulator accumulator = new ServerSideMetricsInternalAccumulator(); + foreach (ServerSideMetricsInternal serverSideMetrics in serverSideMetricsEnumerable) + { + accumulator.Accumulate(serverSideMetrics); + } + + return accumulator.GetServerSideMetrics(); + } + + public static bool TryParseFromDelimitedString(string delimitedString, out ServerSideMetricsInternal serverSideMetrics) + { + return ServerSideMetricsParser.TryParse(delimitedString, out serverSideMetrics); + } + + public static ServerSideMetricsInternal ParseFromDelimitedString(string delimitedString) + { + if (!ServerSideMetricsParser.TryParse(delimitedString, out ServerSideMetricsInternal serverSideMetrics)) + { + throw new FormatException(); + } + + return serverSideMetrics; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs new file mode 100644 index 0000000000..64be05e6b8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsInternalAccumulator.cs @@ -0,0 +1,146 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Tracing.TraceData; + + internal sealed class ServerSideMetricsInternalAccumulator + { + private readonly List serverSideMetricsList; + + public ServerSideMetricsInternalAccumulator() + { + this.serverSideMetricsList = new List(); + } + + public void Accumulate(ServerSideMetricsInternal serverSideMetrics) + { + if (serverSideMetrics == null) + { + throw new ArgumentNullException(nameof(serverSideMetrics)); + } + + this.serverSideMetricsList.Add(serverSideMetrics); + } + + public ServerSideMetricsInternal GetServerSideMetrics() + { + TimeSpan totalTime = TimeSpan.Zero; + long retrievedDocumentCount = 0; + long retrievedDocumentSize = 0; + long outputDocumentCount = 0; + long outputDocumentSize = 0; + double indexHitRatio = 0; + QueryPreparationTimesAccumulator queryPreparationTimesAccumulator = new QueryPreparationTimesAccumulator(); + TimeSpan indexLookupTime = TimeSpan.Zero; + TimeSpan documentLoadTime = TimeSpan.Zero; + RuntimeExecutionTimesAccumulator runtimeExecutionTimesAccumulator = new RuntimeExecutionTimesAccumulator(); + TimeSpan documentWriteTime = TimeSpan.Zero; + TimeSpan vMExecutionTime = TimeSpan.Zero; + + foreach (ServerSideMetricsInternal serverSideMetrics in this.serverSideMetricsList) + { + indexHitRatio = (retrievedDocumentCount + serverSideMetrics.RetrievedDocumentCount) != 0 ? + ((retrievedDocumentCount * indexHitRatio) + (serverSideMetrics.RetrievedDocumentCount * serverSideMetrics.IndexHitRatio)) / (retrievedDocumentCount + serverSideMetrics.RetrievedDocumentCount) : + 0; + totalTime += serverSideMetrics.TotalTime; + retrievedDocumentCount += serverSideMetrics.RetrievedDocumentCount; + retrievedDocumentSize += serverSideMetrics.RetrievedDocumentSize; + outputDocumentCount += serverSideMetrics.OutputDocumentCount; + outputDocumentSize += serverSideMetrics.OutputDocumentSize; + queryPreparationTimesAccumulator.Accumulate(serverSideMetrics.QueryPreparationTimes); + indexLookupTime += serverSideMetrics.IndexLookupTime; + documentLoadTime += serverSideMetrics.DocumentLoadTime; + runtimeExecutionTimesAccumulator.Accumulate(serverSideMetrics.RuntimeExecutionTimes); + documentWriteTime += serverSideMetrics.DocumentWriteTime; + vMExecutionTime += serverSideMetrics.VMExecutionTime; + } + + return new ServerSideMetricsInternal( + retrievedDocumentCount: retrievedDocumentCount, + retrievedDocumentSize: retrievedDocumentSize, + outputDocumentCount: outputDocumentCount, + outputDocumentSize: outputDocumentSize, + indexHitRatio: indexHitRatio, + totalQueryExecutionTime: totalTime, + queryPreparationTimes: queryPreparationTimesAccumulator.GetQueryPreparationTimes(), + indexLookupTime: indexLookupTime, + documentLoadTime: documentLoadTime, + vmExecutionTime: vMExecutionTime, + runtimeExecutionTimes: runtimeExecutionTimesAccumulator.GetRuntimeExecutionTimes(), + documentWriteTime: documentWriteTime); + } + + public List GetPartitionedServerSideMetrics() + { + return this.serverSideMetricsList; + } + + public static void WalkTraceTreeForQueryMetrics(ITrace currentTrace, ServerSideMetricsInternalAccumulator accumulator) + { + if (currentTrace == null) + { + return; + } + + foreach (object datum in currentTrace.Data.Values) + { + if (datum is QueryMetricsTraceDatum queryMetricsTraceDatum) + { + queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.FeedRange = currentTrace.Name; + queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.PartitionKeyRangeId = WalkTraceTreeForPartitionKeyRangeId(currentTrace); + accumulator.Accumulate(queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics); + return; + } + } + + foreach (ITrace childTrace in currentTrace.Children) + { + WalkTraceTreeForQueryMetrics(childTrace, accumulator); + } + + return; + } + + private static int? WalkTraceTreeForPartitionKeyRangeId(ITrace currentTrace) + { + if (currentTrace == null) + { + return null; + } + + foreach (Object datum in currentTrace.Data.Values) + { + if (datum is ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) + { + if (clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList.Count > 0) + { + return int.TryParse(clientSideRequestStatisticsTraceDatum.StoreResponseStatisticsList[0].StoreResult.PartitionKeyRangeId, out int pKRangeId) + ? pKRangeId + : null; + } + else + { + return null; + } + } + } + + foreach (ITrace childTrace in currentTrace.Children) + { + int? partitionKeyRangeId = WalkTraceTreeForPartitionKeyRangeId(childTrace); + if (partitionKeyRangeId != null) + { + return partitionKeyRangeId; + } + } + + return null; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsParser.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsParser.cs similarity index 53% rename from Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsParser.cs rename to Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsParser.cs index ecd5becdd4..eeba3c6c85 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsParser.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsParser.cs @@ -8,7 +8,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics using System.Text; /// - /// Parser for . + /// Parser for . /// #if INTERNAL #pragma warning disable SA1600 @@ -17,9 +17,9 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics #else internal #endif - static class BackendMetricsParser + static class ServerSideMetricsParser { - public static unsafe bool TryParse(string deliminatedString, out BackendMetrics backendMetrics) + public static unsafe bool TryParse(string deliminatedString, out ServerSideMetricsInternal serverSideMetrics) { if (deliminatedString == null) { @@ -30,7 +30,7 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics { // Stack allocating a zero length buffer returns a null pointer // so we special case the zero length string. - backendMetrics = BackendMetrics.Empty; + serverSideMetrics = ServerSideMetricsInternal.Empty; return true; } @@ -72,7 +72,7 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics while (!corpus.IsEmpty) { - (BackendMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = BackendMetricsTokenizer.Read(corpus); + (ServerSideMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = ServerSideMetricsTokenizer.Read(corpus); int bytesConsumed; if (!tokenType.HasValue) @@ -95,162 +95,162 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics { switch (tokenType.Value) { - case BackendMetricsTokenizer.TokenType.DocumentLoadTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.DocumentLoadTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out documentLoadTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.DocumentLoadTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.DocumentLoadTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out documentLoadTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.WriteOutputTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.WriteOutputTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out documentWriteTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.WriteOutputTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.WriteOutputTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out documentWriteTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.IndexLookupTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.IndexLookupTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out indexLookupTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.IndexLookupTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.IndexLookupTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out indexLookupTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.IndexUtilizationRatio: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.IndexUtilizationRatio.Length); - if (!BackendMetricsParser.TryParseDoubleField(corpus, out indexHitRatio, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.IndexUtilizationRatio: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.IndexUtilizationRatio.Length); + if (!ServerSideMetricsParser.TryParseDoubleField(corpus, out indexHitRatio, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.QueryLogicalPlanBuildTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.QueryLogicalPlanBuildTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out logicalPlanBuildTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.QueryLogicalPlanBuildTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.QueryLogicalPlanBuildTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out logicalPlanBuildTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.OutputDocumentCount: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.OutputDocumentCount.Length); - if (!BackendMetricsParser.TryParseLongField(corpus, out outputDocumentCount, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.OutputDocumentCount: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.OutputDocumentCount.Length); + if (!ServerSideMetricsParser.TryParseLongField(corpus, out outputDocumentCount, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.OutputDocumentSize: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.OutputDocumentSize.Length); - if (!BackendMetricsParser.TryParseLongField(corpus, out outputDocumentSize, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.OutputDocumentSize: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.OutputDocumentSize.Length); + if (!ServerSideMetricsParser.TryParseLongField(corpus, out outputDocumentSize, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.QueryPhysicalPlanBuildTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.QueryPhysicalPlanBuildTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out physicalPlanBuildTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.QueryPhysicalPlanBuildTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.QueryPhysicalPlanBuildTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out physicalPlanBuildTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.QueryCompileTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.QueryCompileTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out queryCompilationTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.QueryCompileTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.QueryCompileTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out queryCompilationTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.QueryOptimizationTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.QueryOptimizationTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out queryOptimizationTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.QueryOptimizationTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.QueryOptimizationTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out queryOptimizationTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.RetrievedDocumentCount: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.RetrievedDocumentCount.Length); - if (!BackendMetricsParser.TryParseLongField(corpus, out retrievedDocumentCount, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.RetrievedDocumentCount: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.RetrievedDocumentCount.Length); + if (!ServerSideMetricsParser.TryParseLongField(corpus, out retrievedDocumentCount, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.RetrievedDocumentSize: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.RetrievedDocumentSize.Length); - if (!BackendMetricsParser.TryParseLongField(corpus, out retrievedDocumentSize, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.RetrievedDocumentSize: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.RetrievedDocumentSize.Length); + if (!ServerSideMetricsParser.TryParseLongField(corpus, out retrievedDocumentSize, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.SystemFunctionExecuteTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.SystemFunctionExecuteTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out systemFunctionExecutionTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.SystemFunctionExecuteTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.SystemFunctionExecuteTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out systemFunctionExecutionTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.TotalExecutionTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.TotalExecutionTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out totalQueryExecutionTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.TotalExecutionTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.TotalExecutionTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out totalQueryExecutionTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.UserFunctionExecuteTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.UserFunctionExecuteTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out userDefinedFunctionExecutionTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.UserFunctionExecuteTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.UserFunctionExecuteTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out userDefinedFunctionExecutionTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; - case BackendMetricsTokenizer.TokenType.VMExecutionTimeInMs: - corpus = corpus.Slice(BackendMetricsTokenizer.TokenBuffers.VMExecutionTimeInMs.Length); - if (!BackendMetricsParser.TryParseTimeSpanField(corpus, out vmExecutionTime, out bytesConsumed)) + case ServerSideMetricsTokenizer.TokenType.VMExecutionTimeInMs: + corpus = corpus.Slice(ServerSideMetricsTokenizer.TokenBuffers.VMExecutionTimeInMs.Length); + if (!ServerSideMetricsParser.TryParseTimeSpanField(corpus, out vmExecutionTime, out bytesConsumed)) { - backendMetrics = default; + serverSideMetrics = default; return false; } break; default: - backendMetrics = default; + serverSideMetrics = default; return false; } } corpus = corpus.Slice(bytesConsumed); if (!corpus.IsEmpty) { - (BackendMetricsTokenizer.TokenType? semicolonToken, ReadOnlyMemory semicolonBuffer) = BackendMetricsTokenizer.Read(corpus); - if (!semicolonToken.HasValue || (semicolonToken != BackendMetricsTokenizer.TokenType.SemiColonDelimiter)) + (ServerSideMetricsTokenizer.TokenType? semicolonToken, ReadOnlyMemory semicolonBuffer) = ServerSideMetricsTokenizer.Read(corpus); + if (!semicolonToken.HasValue || (semicolonToken != ServerSideMetricsTokenizer.TokenType.SemiColonDelimiter)) { - backendMetrics = default; + serverSideMetrics = default; return false; } @@ -258,14 +258,14 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics } } - backendMetrics = new BackendMetrics( + serverSideMetrics = new ServerSideMetricsInternal( retrievedDocumentCount: retrievedDocumentCount, retrievedDocumentSize: retrievedDocumentSize, outputDocumentCount: outputDocumentCount, outputDocumentSize: outputDocumentSize, indexHitRatio: indexHitRatio, totalQueryExecutionTime: totalQueryExecutionTime, - queryPreparationTimes: new QueryPreparationTimes( + queryPreparationTimes: new QueryPreparationTimesInternal( queryCompilationTime: queryCompilationTime, logicalPlanBuildTime: logicalPlanBuildTime, physicalPlanBuildTime: physicalPlanBuildTime, @@ -273,7 +273,7 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics indexLookupTime: indexLookupTime, documentLoadTime: documentLoadTime, vmExecutionTime: vmExecutionTime, - runtimeExecutionTimes: new RuntimeExecutionTimes( + runtimeExecutionTimes: new RuntimeExecutionTimesInternal( queryEngineExecutionTime: vmExecutionTime - indexLookupTime - documentLoadTime - documentWriteTime, systemFunctionExecutionTime: systemFunctionExecutionTime, userDefinedFunctionExecutionTime: userDefinedFunctionExecutionTime), @@ -283,8 +283,8 @@ public static unsafe bool TryParse(string deliminatedString, out BackendMetrics private static bool TryParseTimeSpanField(ReadOnlySpan corpus, out TimeSpan timeSpan, out int bytesConsumed) { - (BackendMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = BackendMetricsTokenizer.Read(corpus); - if (!tokenType.HasValue || (tokenType.Value != BackendMetricsTokenizer.TokenType.EqualsDelimiter)) + (ServerSideMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = ServerSideMetricsTokenizer.Read(corpus); + if (!tokenType.HasValue || (tokenType.Value != ServerSideMetricsTokenizer.TokenType.EqualsDelimiter)) { timeSpan = default; bytesConsumed = default; @@ -306,8 +306,8 @@ private static bool TryParseTimeSpanField(ReadOnlySpan corpus, out TimeSpa private static bool TryParseLongField(ReadOnlySpan corpus, out long value, out int bytesConsumed) { - (BackendMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = BackendMetricsTokenizer.Read(corpus); - if (!tokenType.HasValue || (tokenType.Value != BackendMetricsTokenizer.TokenType.EqualsDelimiter)) + (ServerSideMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = ServerSideMetricsTokenizer.Read(corpus); + if (!tokenType.HasValue || (tokenType.Value != ServerSideMetricsTokenizer.TokenType.EqualsDelimiter)) { value = default; bytesConsumed = default; @@ -327,8 +327,8 @@ private static bool TryParseLongField(ReadOnlySpan corpus, out long value, private static bool TryParseDoubleField(ReadOnlySpan corpus, out double value, out int bytesConsumed) { - (BackendMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = BackendMetricsTokenizer.Read(corpus); - if (!tokenType.HasValue || (tokenType.Value != BackendMetricsTokenizer.TokenType.EqualsDelimiter)) + (ServerSideMetricsTokenizer.TokenType? tokenType, ReadOnlyMemory buffer) = ServerSideMetricsTokenizer.Read(corpus); + if (!tokenType.HasValue || (tokenType.Value != ServerSideMetricsTokenizer.TokenType.EqualsDelimiter)) { value = default; bytesConsumed = default; diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsTokenizer.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTokenizer.cs similarity index 98% rename from Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsTokenizer.cs rename to Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTokenizer.cs index f17e6afbf4..431f3add64 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/BackendMetricsTokenizer.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsTokenizer.cs @@ -8,7 +8,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics using System.Text; /// - /// Tokenizer for + /// Tokenizer for /// #if INTERNAL #pragma warning disable SA1600 @@ -18,7 +18,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Metrics #else internal #endif - static class BackendMetricsTokenizer + static class ServerSideMetricsTokenizer { public enum TokenType { diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsUtils.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsUtils.cs new file mode 100644 index 0000000000..a439bdfd57 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSideMetricsUtils.cs @@ -0,0 +1,13 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Query.Core.Metrics +{ + internal static class ServerSideMetricsUtils + { + public static string FormatTrace(this ServerSideMetricsInternal serverSideMetrics) + { + return $"totalExecutionTimeInMs={serverSideMetrics.TotalTime.TotalMilliseconds};queryCompileTimeInMs={serverSideMetrics.QueryPreparationTimes.QueryCompilationTime.TotalMilliseconds};queryLogicalPlanBuildTimeInMs={serverSideMetrics.QueryPreparationTimes.LogicalPlanBuildTime.TotalMilliseconds};queryPhysicalPlanBuildTimeInMs={serverSideMetrics.QueryPreparationTimes.PhysicalPlanBuildTime.TotalMilliseconds};queryOptimizationTimeInMs={serverSideMetrics.QueryPreparationTimes.QueryOptimizationTime.TotalMilliseconds};indexLookupTimeInMs={serverSideMetrics.IndexLookupTime.TotalMilliseconds};documentLoadTimeInMs={serverSideMetrics.DocumentLoadTime.TotalMilliseconds};systemFunctionExecuteTimeInMs={serverSideMetrics.RuntimeExecutionTimes.SystemFunctionExecutionTime.TotalMilliseconds};userFunctionExecuteTimeInMs={serverSideMetrics.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime.TotalMilliseconds};retrievedDocumentCount={serverSideMetrics.RetrievedDocumentCount};retrievedDocumentSize={serverSideMetrics.RetrievedDocumentSize};outputDocumentCount={serverSideMetrics.OutputDocumentCount};outputDocumentSize={serverSideMetrics.OutputDocumentSize};writeOutputTimeInMs={serverSideMetrics.DocumentWriteTime.TotalMilliseconds};indexUtilizationRatio={serverSideMetrics.IndexHitRatio}"; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs new file mode 100644 index 0000000000..3fd1f47094 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetrics.cs @@ -0,0 +1,27 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + /// + /// Represents server side metrics specific for a single partition. + /// + public abstract class ServerSidePartitionedMetrics + { + /// + /// Gets the backend metrics for the request. + /// + public abstract ServerSideMetrics ServerSideMetrics { get; } + + /// + /// Gets the FeedRange for the partition. + /// + public abstract string FeedRange { get; } + + /// + /// Gets the partition key range id for the partition. + /// + public abstract int? PartitionKeyRangeId { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs new file mode 100644 index 0000000000..9ed30963a6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Metrics/ServerSidePartitionedMetricsInternal.cs @@ -0,0 +1,40 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos +{ + using Microsoft.Azure.Cosmos.Query.Core.Metrics; + + /// + /// The internal implementation for server side metrics specific for a single partition. + /// + internal class ServerSidePartitionedMetricsInternal : ServerSidePartitionedMetrics + { + internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSideMetricsInternal) + : this(serverSideMetricsInternal, serverSideMetricsInternal.FeedRange, serverSideMetricsInternal.PartitionKeyRangeId) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + internal ServerSidePartitionedMetricsInternal(ServerSideMetricsInternal serverSideMetricsInternal, string feedRange, int? partitionKeyRangeId) + { + this.ServerSideMetricsInternal = serverSideMetricsInternal; + this.FeedRange = feedRange; + this.PartitionKeyRangeId = partitionKeyRangeId; + } + + public ServerSideMetricsInternal ServerSideMetricsInternal { get; } + + public override ServerSideMetrics ServerSideMetrics => this.ServerSideMetricsInternal; + + public override string FeedRange { get; } + + public override int? PartitionKeyRangeId { get; } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index b237c68c2a..dd09fde938 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -33,6 +33,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using System.Reflection; using System.Text.RegularExpressions; using Microsoft.Azure.Cosmos.Diagnostics; + using Microsoft.Azure.Cosmos.Query.Core.Metrics; [TestClass] public class CosmosItemTests : BaseCosmosClientHelper @@ -141,6 +142,7 @@ public async Task CreateDropItemTest() Assert.IsFalse(string.IsNullOrEmpty(diagnostics.ToString())); Assert.IsTrue(diagnostics.GetClientElapsedTime() > TimeSpan.Zero); Assert.AreEqual(0, response.Diagnostics.GetFailedRequestCount()); + Assert.IsNull(response.Diagnostics.GetQueryMetrics()); response = await this.Container.ReadItemAsync(testItem.id, new Cosmos.PartitionKey(testItem.pk)); Assert.IsNotNull(response); @@ -158,6 +160,7 @@ public async Task CreateDropItemTest() Assert.IsNotNull(response.Diagnostics); Assert.IsFalse(string.IsNullOrEmpty(response.Diagnostics.ToString())); Assert.IsTrue(response.Diagnostics.GetClientElapsedTime() > TimeSpan.Zero); + Assert.IsNull(response.Diagnostics.GetQueryMetrics()); } [TestMethod] @@ -386,6 +389,7 @@ public async Task CreateDropItemMultiPartPartitionKeyTest() ItemResponse response = await multiPartPkContainer.CreateItemAsync(item: testItem); Assert.IsNotNull(response); Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); + Assert.IsNull(response.Diagnostics.GetQueryMetrics()); ItemResponse readResponse = await multiPartPkContainer.ReadItemAsync(id: testItem.id, partitionKey: new Cosmos.PartitionKey("pk1")); Assert.IsNotNull(readResponse); @@ -603,6 +607,7 @@ public async Task UpsertItemTest() Assert.IsNotNull(response); Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); Assert.IsNotNull(response.Headers.Session); + Assert.IsNull(response.Diagnostics.GetQueryMetrics()); } { @@ -613,6 +618,7 @@ public async Task UpsertItemTest() Assert.IsNotNull(response); Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); Assert.IsNotNull(response.Headers.Session); + Assert.IsNull(response.Diagnostics.GetQueryMetrics()); } } @@ -703,6 +709,7 @@ await feedIterator.ReadNextAsync(this.cancellationToken)) } } + Assert.IsNull(responseMessage.Diagnostics.GetQueryMetrics()); } } @@ -842,7 +849,7 @@ public async Task PartitionKeyDeleteTestForSubpartitionedContainer() } [TestMethod] - public async Task ItemCustomSerialzierTest() + public async Task ItemCustomSerializerTest() { DateTime createDateTime = DateTime.UtcNow; Dictionary keyValuePairs = new Dictionary() @@ -1278,6 +1285,22 @@ public async Task QuerySinglePartitionItemStreamTest(int perPKItemCount, int max System.Diagnostics.Trace.TraceInformation($"ContinuationToken: {lastContinuationToken}"); Newtonsoft.Json.JsonSerializer serializer = new Newtonsoft.Json.JsonSerializer(); + ServerSideCumulativeMetrics metrics = response.Diagnostics.GetQueryMetrics(); + Assert.IsTrue(metrics.PartitionedMetrics.Count == 1); + Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + + if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) + { + Assert.IsTrue(metrics.CumulativeMetrics.RetrievedDocumentSize > 0); + Assert.IsTrue(metrics.CumulativeMetrics.DocumentLoadTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.RuntimeExecutionTime > TimeSpan.Zero); + } + else + { + Assert.AreEqual(0, metrics.CumulativeMetrics.RetrievedDocumentSize); + } + using (StreamReader sr = new StreamReader(response.Content)) using (JsonTextReader jtr = new JsonTextReader(sr)) { @@ -1317,9 +1340,9 @@ public async Task QuerySinglePartitionItemStreamTest(int perPKItemCount, int max [TestMethod] public async Task ItemMultiplePartitionQuery() { - IList deleteList = await ToDoActivity.CreateRandomItems(this.Container, 3, randomPartitionKey: true); + IList itemList = await ToDoActivity.CreateRandomItems(this.Container, 3, randomPartitionKey: true); - ToDoActivity find = deleteList.First(); + ToDoActivity find = itemList.First(); QueryDefinition sql = new QueryDefinition("select * from toDoActivity t where t.id = '" + find.id + "'"); QueryRequestOptions requestOptions = new QueryRequestOptions() @@ -1345,6 +1368,111 @@ public async Task ItemMultiplePartitionQuery() ToDoActivity response = iter.First(); Assert.AreEqual(find.id, response.id); } + + ServerSideCumulativeMetrics metrics = iter.Diagnostics.GetQueryMetrics(); + + if (metrics != null) + { + Assert.IsTrue(metrics.PartitionedMetrics.Count == 3); + Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + + foreach (ServerSidePartitionedMetrics partitionedMetrics in metrics.PartitionedMetrics) + { + Assert.IsNotNull(partitionedMetrics); + Assert.IsNotNull(partitionedMetrics.PartitionKeyRangeId); + } + + if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) + { + Assert.IsTrue(metrics.CumulativeMetrics.RetrievedDocumentSize > 0); + Assert.IsTrue(metrics.CumulativeMetrics.DocumentLoadTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.RuntimeExecutionTime > TimeSpan.Zero); + } + else + { + Assert.AreEqual(0, metrics.CumulativeMetrics.RetrievedDocumentSize); + } + } + else + { + string diag = iter.Diagnostics.ToString(); + Assert.IsNotNull(diag); + } + } + + Assert.IsTrue(found); + } + + /// + /// Validate single partition query using gateway mode. + /// + [TestMethod] + public async Task ItemSinglePartitionQueryGateway() + { + ContainerResponse containerResponse = await this.database.CreateContainerAsync( + new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: "/pk")); + + Container createdContainer = (ContainerInlineCore)containerResponse; + CosmosClient client1 = TestCommon.CreateCosmosClient(useGateway: true); + + Container container = client1.GetContainer(this.database.Id, createdContainer.Id); + + string findId = "id2002"; + ToDoActivity item = ToDoActivity.CreateRandomToDoActivity("pk2002", findId); + await container.CreateItemAsync(item); + + QueryDefinition sql = new QueryDefinition("select * from toDoActivity t where t.id = '" + findId + "'"); + + QueryRequestOptions requestOptions = new QueryRequestOptions() + { + MaxBufferedItemCount = 10, + ResponseContinuationTokenLimitInKb = 500, + MaxItemCount = 1, + MaxConcurrency = 1, + }; + + FeedIterator feedIterator = container.GetItemQueryIterator( + sql, + requestOptions: requestOptions); + + bool found = false; + while (feedIterator.HasMoreResults) + { + FeedResponse iter = await feedIterator.ReadNextAsync(); + Assert.IsTrue(iter.Count() <= 1); + if (iter.Count() == 1) + { + found = true; + ToDoActivity response = iter.First(); + Assert.AreEqual(findId, response.id); + } + + ServerSideCumulativeMetrics metrics = iter.Diagnostics.GetQueryMetrics(); + + if (metrics != null) + { + Assert.IsTrue(metrics.PartitionedMetrics.Count == 1); + Assert.IsTrue(metrics.CumulativeMetrics.TotalTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.QueryPreparationTime > TimeSpan.Zero); + + foreach (ServerSidePartitionedMetrics partitionedMetrics in metrics.PartitionedMetrics) + { + Assert.IsNotNull(partitionedMetrics); + Assert.IsNull(partitionedMetrics.PartitionKeyRangeId); + } + + if (metrics.CumulativeMetrics.RetrievedDocumentCount >= 1) + { + Assert.IsTrue(metrics.CumulativeMetrics.RetrievedDocumentSize > 0); + Assert.IsTrue(metrics.CumulativeMetrics.DocumentLoadTime > TimeSpan.Zero); + Assert.IsTrue(metrics.CumulativeMetrics.RuntimeExecutionTime > TimeSpan.Zero); + } + else + { + Assert.AreEqual(0, metrics.CumulativeMetrics.RetrievedDocumentSize); + } + } } Assert.IsTrue(found); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsDatumVisitor.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsDatumVisitor.cs index 200150875b..c100146bdb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsDatumVisitor.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryPerfTest/QueryStatisticsDatumVisitor.cs @@ -41,13 +41,13 @@ public void AddGetCosmosElementResponseTime(double time) public void Visit(QueryMetricsTraceDatum queryMetricsTraceDatum) { - this.queryMetrics.RetrievedDocumentCount = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.RetrievedDocumentCount; - this.queryMetrics.RetrievedDocumentSize = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.RetrievedDocumentSize; - this.queryMetrics.OutputDocumentCount = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.OutputDocumentCount; - this.queryMetrics.OutputDocumentSize = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.OutputDocumentSize; - this.queryMetrics.TotalQueryExecutionTime = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.TotalTime.TotalMilliseconds; - this.queryMetrics.DocumentLoadTime = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.DocumentLoadTime.TotalMilliseconds; - this.queryMetrics.DocumentWriteTime = queryMetricsTraceDatum.QueryMetrics.BackendMetrics.DocumentWriteTime.TotalMilliseconds; + this.queryMetrics.RetrievedDocumentCount = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.RetrievedDocumentCount; + this.queryMetrics.RetrievedDocumentSize = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.RetrievedDocumentSize; + this.queryMetrics.OutputDocumentCount = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.OutputDocumentCount; + this.queryMetrics.OutputDocumentSize = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.OutputDocumentSize; + this.queryMetrics.TotalQueryExecutionTime = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.TotalTime.TotalMilliseconds; + this.queryMetrics.DocumentLoadTime = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.DocumentLoadTime.TotalMilliseconds; + this.queryMetrics.DocumentWriteTime = queryMetricsTraceDatum.QueryMetrics.ServerSideMetrics.DocumentWriteTime.TotalMilliseconds; } public void Visit(ClientSideRequestStatisticsTraceDatum clientSideRequestStatisticsTraceDatum) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index afc25ec771..d971223f09 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -1870,11 +1870,11 @@ public async Task TestQueryMetricsNonZero() QueryMetrics queryMetrics = QueryMetrics.CreateFromIEnumerable(feedResonse.QueryMetrics.Values); - Assert.IsTrue(queryMetrics.BackendMetrics.RetrievedDocumentCount > 0); - Assert.IsTrue(queryMetrics.BackendMetrics.RetrievedDocumentSize > 0); - Assert.IsTrue(queryMetrics.BackendMetrics.OutputDocumentCount > 0); - Assert.IsTrue(queryMetrics.BackendMetrics.OutputDocumentSize > 0); - Assert.IsTrue(queryMetrics.BackendMetrics.IndexHitRatio > 0); + Assert.IsTrue(queryMetrics.ServerSideMetrics.RetrievedDocumentCount > 0); + Assert.IsTrue(queryMetrics.ServerSideMetrics.RetrievedDocumentSize > 0); + Assert.IsTrue(queryMetrics.ServerSideMetrics.OutputDocumentCount > 0); + Assert.IsTrue(queryMetrics.ServerSideMetrics.OutputDocumentSize > 0); + Assert.IsTrue(queryMetrics.ServerSideMetrics.IndexHitRatio > 0); await client.DeleteDatabaseAsync(database); } @@ -1960,7 +1960,7 @@ private void TestForceQueryScanHeaders(Database database, bool partitionedCollec query, feedOptions).AsDocumentQuery().ExecuteNextAsync().Result; queryMetrics = result.QueryMetrics.Values.Aggregate((curr, acc) => curr + acc); - Assert.AreEqual(TimeSpan.Zero, queryMetrics.BackendMetrics.IndexLookupTime); + Assert.AreEqual(TimeSpan.Zero, queryMetrics.ServerSideMetrics.IndexLookupTime); // Without ForceQueryScan feedOptions = new FeedOptions() @@ -1976,7 +1976,7 @@ private void TestForceQueryScanHeaders(Database database, bool partitionedCollec query, feedOptions).AsDocumentQuery().ExecuteNextAsync().Result; queryMetrics = result.QueryMetrics.Values.Aggregate((curr, acc) => curr + acc); - Assert.AreNotEqual(TimeSpan.Zero, queryMetrics.BackendMetrics.IndexLookupTime); + Assert.AreNotEqual(TimeSpan.Zero, queryMetrics.ServerSideMetrics.IndexLookupTime); } private void TestFeedOptionInput( @@ -2315,19 +2315,19 @@ private void ValidateQueryMetrics(QueryMetrics metrics) Assert.AreEqual(0, metrics.ClientSideMetrics.Retries); //We are not checking VMExecutionTime, since that is not a public property //Assert.IsTrue(metrics.QueryEngineTimes.VMExecutionTime.TotalMilliseconds > 0, "Expected VMExecutionTimeInMs to be > 0, metrics = {0}", metrics); - Assert.IsTrue(metrics.BackendMetrics.QueryPreparationTimes.QueryCompilationTime.TotalMilliseconds > 0, "Expected CompileTimeInMs to be > 0, metrics = {0}", metrics); + Assert.IsTrue(metrics.ServerSideMetrics.QueryPreparationTimes.QueryCompilationTime.TotalMilliseconds > 0, "Expected CompileTimeInMs to be > 0, metrics = {0}", metrics); //We are not checking DocumentLoadTime and RetrievedDocumentCount, since some queries don't return any documents (especially in the last continuation). //Assert.IsTrue(metrics.QueryEngineTimes.DocumentLoadTime.TotalMilliseconds > 0, "Expected DocumentLoadTimeInMs to be > 0, metrics = {0}", metrics); //Assert.IsTrue(metrics.RetrievedDocumentCount > 0, "Expected RetrievedDocumentCount to be > 0, metrics = {0}", metrics); - Assert.IsTrue(metrics.BackendMetrics.TotalTime.TotalMilliseconds > 0, "Expected TotalExecutionTimeInMs to be > 0, metrics = {0}", metrics); + Assert.IsTrue(metrics.ServerSideMetrics.TotalTime.TotalMilliseconds > 0, "Expected TotalExecutionTimeInMs to be > 0, metrics = {0}", metrics); //Assert.IsTrue(metrics.QueryEngineTimes.WriteOutputTime.TotalMilliseconds > 0, "Expected WriteOutputTimeInMs to be > 0, metrics = {0}", metrics); //Assert.IsTrue(metrics.RetrievedDocumentSize > 0, "Expected RetrievedDocumentSize to be > 0, metrics = {0}", metrics); - Assert.IsTrue(metrics.BackendMetrics.IndexLookupTime.TotalMilliseconds > 0, "Expected IndexLookupTimeInMs to be > 0, metrics = {0}", metrics); - Assert.IsTrue(metrics.BackendMetrics.QueryPreparationTimes.LogicalPlanBuildTime.TotalMilliseconds > 0, "Expected LogicalPlanBuildTimeInMs to be > 0, metrics = {0}", metrics); + Assert.IsTrue(metrics.ServerSideMetrics.IndexLookupTime.TotalMilliseconds > 0, "Expected IndexLookupTimeInMs to be > 0, metrics = {0}", metrics); + Assert.IsTrue(metrics.ServerSideMetrics.QueryPreparationTimes.LogicalPlanBuildTime.TotalMilliseconds > 0, "Expected LogicalPlanBuildTimeInMs to be > 0, metrics = {0}", metrics); //Assert.AreEqual(metrics.QueryEngineTimes.VMExecutionTime - metrics.QueryEngineTimes.IndexLookupTime - metrics.QueryEngineTimes.DocumentLoadTime - metrics.QueryEngineTimes.WriteOutputTime, // metrics.QueryEngineTimes.RuntimeExecutionTimes.TotalTime); - Assert.IsTrue(metrics.BackendMetrics.RuntimeExecutionTimes.QueryEngineExecutionTime >= metrics.BackendMetrics.RuntimeExecutionTimes.SystemFunctionExecutionTime + metrics.BackendMetrics.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime, - "Expected Query VM Execution Time to be > {0}, metrics = {1}", metrics.BackendMetrics.RuntimeExecutionTimes.SystemFunctionExecutionTime + metrics.BackendMetrics.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime, metrics); + Assert.IsTrue(metrics.ServerSideMetrics.RuntimeExecutionTimes.QueryEngineExecutionTime >= metrics.ServerSideMetrics.RuntimeExecutionTimes.SystemFunctionExecutionTime + metrics.ServerSideMetrics.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime, + "Expected Query VM Execution Time to be > {0}, metrics = {1}", metrics.ServerSideMetrics.RuntimeExecutionTimes.SystemFunctionExecutionTime + metrics.ServerSideMetrics.RuntimeExecutionTimes.UserDefinedFunctionExecutionTime, metrics); //Assert.IsTrue(metrics.QueryEngineTimes.VMExecutionTime >= metrics.QueryEngineTimes.RuntimeExecutionTimes.TotalTime, // "Expected Query VM Execution Time to be > {0}, metrics = {1}", metrics.QueryEngineTimes.RuntimeExecutionTimes.TotalTime, metrics); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/Metrics/Performance.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/Metrics/Performance.cs index 6d5db62d6d..40484e792c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/Metrics/Performance.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Query/Metrics/Performance.cs @@ -37,7 +37,7 @@ public void TestParse() ValueStopwatch stopwatch = ValueStopwatch.StartNew(); for (int i = 0; i < 100000; i++) { - BackendMetricsParser.TryParse(delimitedString, out BackendMetrics backendMetrics); + ServerSideMetricsParser.TryParse(delimitedString, out ServerSideMetricsInternal serverSideMetrics); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml index d1dee72a0f..75cd9894de 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/TraceWriterBaselineTests.TraceData.xml @@ -126,7 +126,7 @@ { QueryMetricsTraceDatum datum = new QueryMetricsTraceDatum( new Lazy(() => new QueryMetrics( - BackendMetricsTests.MockBackendMetrics, + ServerSideMetricsTests.ServerSideMetrics, IndexUtilizationInfoTests.MockIndexUtilizationInfo, ClientSideMetricsTests.MockClientSideMetrics))); rootTrace.AddDatum("Query Metrics", datum); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 7fde376d49..759762f21f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -3124,6 +3124,11 @@ "Attributes": [], "MethodInfo": "Int32 GetFailedRequestCount();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Microsoft.Azure.Cosmos.ServerSideCumulativeMetrics GetQueryMetrics()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ServerSideCumulativeMetrics GetQueryMetrics();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[System.String,System.Uri]] GetContactedRegions()": { "Type": "Method", "Attributes": [], @@ -9029,6 +9034,194 @@ }, "NestedTypes": {} }, + "Microsoft.Azure.Cosmos.ServerSideCumulativeMetrics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.ServerSideMetrics CumulativeMetrics": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ServerSideMetrics CumulativeMetrics;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ServerSideMetrics get_CumulativeMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ServerSideMetrics get_CumulativeMetrics()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ServerSideMetrics get_CumulativeMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.IReadOnlyList`1[Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics] get_PartitionedMetrics()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics] get_PartitionedMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.IReadOnlyList`1[Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics] PartitionedMetrics": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.IReadOnlyList`1[Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics] PartitionedMetrics;CanRead:True;CanWrite:False;System.Collections.Generic.IReadOnlyList`1[Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics] get_PartitionedMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.ServerSideMetrics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Double get_IndexHitRatio()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double get_IndexHitRatio();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double IndexHitRatio": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Double IndexHitRatio;CanRead:True;CanWrite:False;Double get_IndexHitRatio();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 get_OutputDocumentCount()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int64 get_OutputDocumentCount();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 get_OutputDocumentSize()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int64 get_OutputDocumentSize();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 get_RetrievedDocumentCount()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int64 get_RetrievedDocumentCount();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 get_RetrievedDocumentSize()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int64 get_RetrievedDocumentSize();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 OutputDocumentCount": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Int64 OutputDocumentCount;CanRead:True;CanWrite:False;Int64 get_OutputDocumentCount();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 OutputDocumentSize": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Int64 OutputDocumentSize;CanRead:True;CanWrite:False;Int64 get_OutputDocumentSize();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 RetrievedDocumentCount": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Int64 RetrievedDocumentCount;CanRead:True;CanWrite:False;Int64 get_RetrievedDocumentCount();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int64 RetrievedDocumentSize": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Int64 RetrievedDocumentSize;CanRead:True;CanWrite:False;Int64 get_RetrievedDocumentSize();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan DocumentLoadTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan DocumentLoadTime;CanRead:True;CanWrite:False;System.TimeSpan get_DocumentLoadTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan DocumentWriteTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan DocumentWriteTime;CanRead:True;CanWrite:False;System.TimeSpan get_DocumentWriteTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_DocumentLoadTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_DocumentLoadTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_DocumentWriteTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_DocumentWriteTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_IndexLookupTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_IndexLookupTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_QueryPreparationTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_QueryPreparationTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_RuntimeExecutionTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_RuntimeExecutionTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_TotalTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_TotalTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan get_VMExecutionTime()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.TimeSpan get_VMExecutionTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan IndexLookupTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan IndexLookupTime;CanRead:True;CanWrite:False;System.TimeSpan get_IndexLookupTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan QueryPreparationTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan QueryPreparationTime;CanRead:True;CanWrite:False;System.TimeSpan get_QueryPreparationTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan RuntimeExecutionTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan RuntimeExecutionTime;CanRead:True;CanWrite:False;System.TimeSpan get_RuntimeExecutionTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan TotalTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan TotalTime;CanRead:True;CanWrite:False;System.TimeSpan get_TotalTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.TimeSpan VMExecutionTime": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.TimeSpan VMExecutionTime;CanRead:True;CanWrite:False;System.TimeSpan get_VMExecutionTime();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.ServerSidePartitionedMetrics;System.Object;IsAbstract:True;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { + "Subclasses": {}, + "Members": { + "Microsoft.Azure.Cosmos.ServerSideMetrics get_ServerSideMetrics()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ServerSideMetrics get_ServerSideMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.ServerSideMetrics ServerSideMetrics": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.ServerSideMetrics ServerSideMetrics;CanRead:True;CanWrite:False;Microsoft.Azure.Cosmos.ServerSideMetrics get_ServerSideMetrics();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_PartitionKeyRangeId()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Int32] get_PartitionKeyRangeId();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] PartitionKeyRangeId": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Nullable`1[System.Int32] PartitionKeyRangeId;CanRead:True;CanWrite:False;System.Nullable`1[System.Int32] get_PartitionKeyRangeId();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String FeedRange": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.String FeedRange;CanRead:True;CanWrite:False;System.String get_FeedRange();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_FeedRange()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String get_FeedRange();IsAbstract:True;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, "Microsoft.Azure.Cosmos.Spatial.BoundingBox;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:False": { "Subclasses": {}, "Members": { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ClientSideMetricsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ClientSideMetricsTests.cs index 4a446bb933..90f9fec8ad 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ClientSideMetricsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ClientSideMetricsTests.cs @@ -21,11 +21,11 @@ public class ClientSideMetricsTests [TestMethod] public void TestAccumulator() { - ClientSideMetrics.Accumulator accumulator = new ClientSideMetrics.Accumulator(); - accumulator = accumulator.Accumulate(MockClientSideMetrics); - accumulator = accumulator.Accumulate(MockClientSideMetrics); + ClientSideMetricsAccumulator accumulator = new ClientSideMetricsAccumulator(); + accumulator.Accumulate(MockClientSideMetrics); + accumulator.Accumulate(MockClientSideMetrics); - ClientSideMetrics doubleMetrics = ClientSideMetrics.Accumulator.ToClientSideMetrics(accumulator); + ClientSideMetrics doubleMetrics = accumulator.GetClientSideMetrics(); Assert.AreEqual(2 * MockClientSideMetrics.Retries, doubleMetrics.Retries); Assert.AreEqual(2 * MockClientSideMetrics.RequestCharge, doubleMetrics.RequestCharge); Assert.AreEqual(2 * MockClientSideMetrics.FetchExecutionRanges.Count(), doubleMetrics.FetchExecutionRanges.Count()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs index 13702de3b5..9fe272a6bd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/IndexUtilizationInfoTests.cs @@ -8,7 +8,6 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Metrics using VisualStudio.TestTools.UnitTesting; using Microsoft.Azure.Cosmos.Query.Core.Metrics; using System.Collections.Generic; - using System.Text; [TestClass] public class IndexUtilizationInfoTests @@ -35,11 +34,11 @@ public class IndexUtilizationInfoTests [TestMethod] public void TestAccumulator() { - IndexUtilizationInfo.Accumulator accumulator = new IndexUtilizationInfo.Accumulator(); - accumulator = accumulator.Accumulate(MockIndexUtilizationInfo); - accumulator = accumulator.Accumulate(MockIndexUtilizationInfo); + IndexUtilizationInfoAccumulator accumulator = new IndexUtilizationInfoAccumulator(); + accumulator.Accumulate(MockIndexUtilizationInfo); + accumulator.Accumulate(MockIndexUtilizationInfo); - IndexUtilizationInfo doubleInfo = IndexUtilizationInfo.Accumulator.ToIndexUtilizationInfo(accumulator); + IndexUtilizationInfo doubleInfo = accumulator.GetIndexUtilizationInfo(); Assert.AreEqual(2 * MockIndexUtilizationInfo.PotentialSingleIndexes.Count, doubleInfo.PotentialSingleIndexes.Count); Assert.AreEqual(2 * MockIndexUtilizationInfo.UtilizedSingleIndexes.Count, doubleInfo.UtilizedSingleIndexes.Count); Assert.AreEqual(2 * MockIndexUtilizationInfo.PotentialCompositeIndexes.Count, doubleInfo.PotentialCompositeIndexes.Count); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/QueryMetricsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/QueryMetricsTests.cs index d655de097a..17f73616c2 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/QueryMetricsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/QueryMetricsTests.cs @@ -12,21 +12,21 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Metrics public class QueryMetricsTests { private static readonly QueryMetrics MockQueryMetrics = new QueryMetrics( - BackendMetricsTests.MockBackendMetrics, + ServerSideMetricsTests.ServerSideMetrics, IndexUtilizationInfoTests.MockIndexUtilizationInfo, ClientSideMetricsTests.MockClientSideMetrics); [TestMethod] public void TestAccumulator() { - QueryMetrics.Accumulator accumulator = new QueryMetrics.Accumulator(); - accumulator = accumulator.Accumulate(MockQueryMetrics); - accumulator = accumulator.Accumulate(MockQueryMetrics); + QueryMetricsAccumulator accumulator = new QueryMetricsAccumulator(); + accumulator.Accumulate(MockQueryMetrics); + accumulator.Accumulate(MockQueryMetrics); - QueryMetrics doubleQueryMetrics = QueryMetrics.Accumulator.ToQueryMetrics(accumulator); + QueryMetrics doubleQueryMetrics = accumulator.GetQueryMetrics(); // Spot check - Assert.AreEqual(2 * BackendMetricsTests.MockBackendMetrics.IndexLookupTime, doubleQueryMetrics.BackendMetrics.IndexLookupTime); + Assert.AreEqual(2 * ServerSideMetricsTests.ServerSideMetrics.IndexLookupTime, doubleQueryMetrics.ServerSideMetrics.IndexLookupTime); Assert.AreEqual(2 * IndexUtilizationInfoTests.MockIndexUtilizationInfo.PotentialSingleIndexes.Count, doubleQueryMetrics.IndexUtilizationInfo.PotentialSingleIndexes.Count); Assert.AreEqual(2 * ClientSideMetricsTests.MockClientSideMetrics.RequestCharge, doubleQueryMetrics.ClientSideMetrics.RequestCharge); } @@ -37,7 +37,7 @@ public void TestAddition() QueryMetrics doubleQueryMetrics = MockQueryMetrics + MockQueryMetrics; // Spot check - Assert.AreEqual(2 * BackendMetricsTests.MockBackendMetrics.IndexLookupTime, doubleQueryMetrics.BackendMetrics.IndexLookupTime); + Assert.AreEqual(2 * ServerSideMetricsTests.ServerSideMetrics.IndexLookupTime, doubleQueryMetrics.ServerSideMetrics.IndexLookupTime); Assert.AreEqual(2 * IndexUtilizationInfoTests.MockIndexUtilizationInfo.PotentialSingleIndexes.Count, doubleQueryMetrics.IndexUtilizationInfo.PotentialSingleIndexes.Count); Assert.AreEqual(2 * ClientSideMetricsTests.MockClientSideMetrics.RequestCharge, doubleQueryMetrics.ClientSideMetrics.RequestCharge); } @@ -48,7 +48,7 @@ public void TestCreateFromEnumerable() QueryMetrics tripleQueryMetrics = QueryMetrics.CreateFromIEnumerable(new List() { MockQueryMetrics, MockQueryMetrics, MockQueryMetrics }); // Spot check - Assert.AreEqual(3 * BackendMetricsTests.MockBackendMetrics.IndexLookupTime, tripleQueryMetrics.BackendMetrics.IndexLookupTime); + Assert.AreEqual(3 * ServerSideMetricsTests.ServerSideMetrics.IndexLookupTime, tripleQueryMetrics.ServerSideMetrics.IndexLookupTime); Assert.AreEqual(3 * IndexUtilizationInfoTests.MockIndexUtilizationInfo.PotentialSingleIndexes.Count, tripleQueryMetrics.IndexUtilizationInfo.PotentialSingleIndexes.Count); Assert.AreEqual(3 * ClientSideMetricsTests.MockClientSideMetrics.RequestCharge, tripleQueryMetrics.ClientSideMetrics.RequestCharge); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/BackendMetricsTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ServerSideMetricsTests.cs similarity index 78% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/BackendMetricsTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ServerSideMetricsTests.cs index 221057790d..4c6e382ebf 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/BackendMetricsTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Metrics/ServerSideMetricsTests.cs @@ -7,11 +7,10 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Metrics using System; using VisualStudio.TestTools.UnitTesting; using Microsoft.Azure.Cosmos.Query.Core.Metrics; - using System.Diagnostics; using System.Collections.Generic; [TestClass] - public class BackendMetricsTests + public class ServerSideMetricsTests { private static readonly TimeSpan totalExecutionTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * 33.67)); private static readonly TimeSpan queryCompileTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * 0.06)); @@ -32,14 +31,14 @@ public class BackendMetricsTests private static readonly string delimitedString = $"totalExecutionTimeInMs={totalExecutionTime.TotalMilliseconds};queryCompileTimeInMs={queryCompileTime.TotalMilliseconds};queryLogicalPlanBuildTimeInMs={logicalPlanBuildTime.TotalMilliseconds};queryPhysicalPlanBuildTimeInMs={physicalPlanBuildTime.TotalMilliseconds};queryOptimizationTimeInMs={queryOptimizationTime.TotalMilliseconds};VMExecutionTimeInMs={vmExecutionTime.TotalMilliseconds};indexLookupTimeInMs={indexLookupTime.TotalMilliseconds};documentLoadTimeInMs={documentLoadTime.TotalMilliseconds};systemFunctionExecuteTimeInMs={systemFunctionExecuteTime.TotalMilliseconds};userFunctionExecuteTimeInMs={userFunctionExecuteTime.TotalMilliseconds};retrievedDocumentCount={retrievedDocumentCount};retrievedDocumentSize={retrievedDocumentSize};outputDocumentCount={outputDocumentCount};outputDocumentSize={outputDocumentSize};writeOutputTimeInMs={documentWriteTime.TotalMilliseconds};indexUtilizationRatio={indexHitRatio}"; - internal static readonly BackendMetrics MockBackendMetrics = new BackendMetrics( + internal static readonly ServerSideMetricsInternal ServerSideMetrics = new ServerSideMetricsInternal( retrievedDocumentCount, retrievedDocumentSize, outputDocumentCount, outputDocumentSize, indexHitRatio, totalExecutionTime, - new QueryPreparationTimes( + new QueryPreparationTimesInternal( queryCompileTime, logicalPlanBuildTime, physicalPlanBuildTime, @@ -47,7 +46,7 @@ public class BackendMetricsTests indexLookupTime, documentLoadTime, vmExecutionTime, - new RuntimeExecutionTimes( + new RuntimeExecutionTimesInternal( totalExecutionTime - systemFunctionExecuteTime - userFunctionExecuteTime, systemFunctionExecuteTime, userFunctionExecuteTime), @@ -57,13 +56,13 @@ public class BackendMetricsTests [TestMethod] public void TestParse() { - BackendMetricsTests.ValidateParse(delimitedString, MockBackendMetrics); + ServerSideMetricsTests.ValidateParse(delimitedString, ServerSideMetrics); } [TestMethod] public void TestParseEmptyString() { - BackendMetricsTests.ValidateParse(string.Empty, BackendMetrics.Empty); + ServerSideMetricsTests.ValidateParse(string.Empty, ServerSideMetricsInternal.Empty); } [TestMethod] @@ -72,14 +71,14 @@ public void TestParseStringWithMissingFields() TimeSpan totalExecutionTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * 33.67)); string delimitedString = $"totalExecutionTimeInMs={totalExecutionTime.TotalMilliseconds}"; - BackendMetrics expected = new BackendMetrics( + ServerSideMetricsInternal expected = new ServerSideMetricsInternal( default(long), default(long), default(long), default(long), default(double), totalExecutionTime, - new QueryPreparationTimes( + new QueryPreparationTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan), @@ -87,27 +86,27 @@ public void TestParseStringWithMissingFields() default(TimeSpan), default(TimeSpan), default(TimeSpan), - new RuntimeExecutionTimes( + new RuntimeExecutionTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan)), default(TimeSpan)); - BackendMetricsTests.ValidateParse(delimitedString, expected); + ServerSideMetricsTests.ValidateParse(delimitedString, expected); } [TestMethod] public void TestParseStringWithTrailingUnknownField() { string delimitedString = $"thisIsNotAKnownField=asdf"; - BackendMetrics expected = new BackendMetrics( + ServerSideMetricsInternal expected = new ServerSideMetricsInternal( default(long), default(long), default(long), default(long), default(double), default(TimeSpan), - new QueryPreparationTimes( + new QueryPreparationTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan), @@ -115,13 +114,13 @@ public void TestParseStringWithTrailingUnknownField() default(TimeSpan), default(TimeSpan), default(TimeSpan), - new RuntimeExecutionTimes( + new RuntimeExecutionTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan)), default(TimeSpan)); - BackendMetricsTests.ValidateParse(delimitedString, expected); + ServerSideMetricsTests.ValidateParse(delimitedString, expected); } [TestMethod] @@ -129,7 +128,7 @@ public void TestParseStringWithTrailingUnknownField() [DataRow("totalExecutionTimeInMs=33.6+totalExecutionTimeInMs=33.6", DisplayName = "Wrong Delimiter")] public void TestNegativeCases(string delimitedString) { - Assert.IsFalse(BackendMetricsParser.TryParse(delimitedString, out BackendMetrics backendMetrics)); + Assert.IsFalse(ServerSideMetricsParser.TryParse(delimitedString, out ServerSideMetricsInternal serverSideMetrics)); } [TestMethod] @@ -137,14 +136,14 @@ public void TestParseStringWithUnknownField() { TimeSpan totalExecutionTime = TimeSpan.FromTicks((long)(TimeSpan.TicksPerMillisecond * 33.67)); string delimitedString = $"totalExecutionTimeInMs={totalExecutionTime.TotalMilliseconds};thisIsNotAKnownField={totalExecutionTime.TotalMilliseconds};totalExecutionTimeInMs={totalExecutionTime.TotalMilliseconds}"; - BackendMetrics expected = new BackendMetrics( + ServerSideMetricsInternal expected = new ServerSideMetricsInternal( default(long), default(long), default(long), default(long), default(double), totalExecutionTime, - new QueryPreparationTimes( + new QueryPreparationTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan), @@ -152,31 +151,34 @@ public void TestParseStringWithUnknownField() default(TimeSpan), default(TimeSpan), default(TimeSpan), - new RuntimeExecutionTimes( + new RuntimeExecutionTimesInternal( default(TimeSpan), default(TimeSpan), default(TimeSpan)), default(TimeSpan)); - BackendMetricsTests.ValidateParse(delimitedString, expected); + ServerSideMetricsTests.ValidateParse(delimitedString, expected); } [TestMethod] public void TestAccumulator() { - BackendMetrics.Accumulator accumulator = new BackendMetrics.Accumulator(); - accumulator = accumulator.Accumulate(MockBackendMetrics); - accumulator = accumulator.Accumulate(MockBackendMetrics); + ServerSideMetricsInternalAccumulator accumulator = new ServerSideMetricsInternalAccumulator(); + accumulator.Accumulate(ServerSideMetrics); + accumulator.Accumulate(ServerSideMetrics); + ServerSideMetricsInternal serverSideMetricsFromAddition = accumulator.GetServerSideMetrics(); - BackendMetrics backendMetricsFromAddition = BackendMetrics.Accumulator.ToBackendMetrics(accumulator); - BackendMetrics expected = new BackendMetrics( + List metricsList = new List { ServerSideMetrics, ServerSideMetrics }; + ServerSideMetricsInternal serverSideMetricsFromCreate = ServerSideMetricsInternal.Create(metricsList); + + ServerSideMetricsInternal expected = new ServerSideMetricsInternal( retrievedDocumentCount * 2, retrievedDocumentSize * 2, outputDocumentCount * 2, outputDocumentSize * 2, indexHitRatio, totalExecutionTime * 2, - new QueryPreparationTimes( + new QueryPreparationTimesInternal( queryCompileTime * 2, logicalPlanBuildTime * 2, physicalPlanBuildTime * 2, @@ -184,22 +186,22 @@ public void TestAccumulator() indexLookupTime * 2, documentLoadTime * 2, vmExecutionTime * 2, - new RuntimeExecutionTimes( + new RuntimeExecutionTimesInternal( (totalExecutionTime - systemFunctionExecuteTime - userFunctionExecuteTime) * 2, systemFunctionExecuteTime * 2, userFunctionExecuteTime * 2), documentWriteTime * 2); - BackendMetricsTests.ValidateBackendMetricsEquals(expected, backendMetricsFromAddition); + ServerSideMetricsTests.ValidateServerSideMetricsEquals(expected, serverSideMetricsFromAddition); + ServerSideMetricsTests.ValidateServerSideMetricsEquals(expected, serverSideMetricsFromCreate); } - - private static void ValidateParse(string delimitedString, BackendMetrics expected) + private static void ValidateParse(string delimitedString, ServerSideMetricsInternal expected) { - Assert.IsTrue(BackendMetricsParser.TryParse(delimitedString, out BackendMetrics actual)); - BackendMetricsTests.ValidateBackendMetricsEquals(expected, actual); + Assert.IsTrue(ServerSideMetricsParser.TryParse(delimitedString, out ServerSideMetricsInternal actual)); + ServerSideMetricsTests.ValidateServerSideMetricsEquals(expected, actual); } - private static void ValidateBackendMetricsEquals(BackendMetrics expected, BackendMetrics actual) + private static void ValidateServerSideMetricsEquals(ServerSideMetricsInternal expected, ServerSideMetricsInternal actual) { Assert.AreEqual(expected.DocumentLoadTime, actual.DocumentLoadTime); Assert.AreEqual(expected.DocumentWriteTime, actual.DocumentWriteTime); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs index fe3dc7054f..2d69341182 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Tracing/TraceWriterBaselineTests.cs @@ -41,7 +41,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Tracing public sealed class TraceWriterBaselineTests : BaselineTests { private static readonly Lazy MockQueryMetrics = new Lazy(() => new QueryMetrics( - BackendMetricsTests.MockBackendMetrics, + ServerSideMetricsTests.ServerSideMetrics, IndexUtilizationInfoTests.MockIndexUtilizationInfo, ClientSideMetricsTests.MockClientSideMetrics)); @@ -316,7 +316,7 @@ public void TraceData() { QueryMetricsTraceDatum datum = new QueryMetricsTraceDatum( new Lazy(() => new QueryMetrics( - BackendMetricsTests.MockBackendMetrics, + ServerSideMetricsTests.ServerSideMetrics, IndexUtilizationInfoTests.MockIndexUtilizationInfo, ClientSideMetricsTests.MockClientSideMetrics))); rootTrace.AddDatum("Query Metrics", datum); From 4111caed99a5d00acd466bfc6dc2141c3bb106f8 Mon Sep 17 00:00:00 2001 From: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Date: Mon, 11 Sep 2023 08:29:16 -0700 Subject: [PATCH 186/337] [Query][Internal] Adds tests for aggregate queries with invalid continuation tokens (#4052) * partial test * Tests and error handling update * update error message * typo * update original err msg * combine tests * test cleanup * undo error message update --- .../CosmosItemLinqTests.cs | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs index b3dc7afa41..efffeae1cb 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemLinqTests.cs @@ -878,9 +878,65 @@ async Task TestSearch(Expression> expression, string ex await TestSearch(x => x.description.Contains("todo"), "CONTAINS", false, 0); await TestSearch(x => x.description.Contains("tOdO", StringComparison.OrdinalIgnoreCase), "CONTAINS", true, 200); - } + [TestMethod] + public async Task LinqAggregatesWithContinuationTokenTest() + { + await ToDoActivity.CreateRandomItems(container: this.Container, pkCount: 1, perPKItemCount: 2, randomPartitionKey: true); + + QueryRequestOptions requestOptions = new QueryRequestOptions() + { + MaxItemCount = 1 + }; + + IOrderedQueryable firstQuery = this.Container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, requestOptions: requestOptions); + + int count = await firstQuery.CountAsync(); + double average = firstQuery.Average(x => x.taskNum); + + string continuationToken = null; + + FeedIterator firstFeedIterator = firstQuery.ToFeedIterator(); + + // if instead of while loop in order to retrieve continuation token + if (firstFeedIterator.HasMoreResults) + { + FeedResponse firstFeedResponse = await firstFeedIterator.ReadNextAsync(); + + continuationToken = firstFeedResponse.ContinuationToken; + } + + Assert.AreEqual(2, count); + Assert.IsNotNull(continuationToken); + + IOrderedQueryable secondQuery = this.Container.GetItemLinqQueryable(allowSynchronousQueryExecution: true, continuationToken: continuationToken, requestOptions: requestOptions); + + try + { + count = await secondQuery.CountAsync(); + Assert.Fail("Expected Count query to return exception"); + } + catch (CosmosException exception) + { + Assert.IsTrue(exception.StatusCode == System.Net.HttpStatusCode.BadRequest); + Assert.IsTrue(exception.SubStatusCode == (int)Documents.SubStatusCodes.MalformedContinuationToken); + Assert.IsTrue(exception.Message.Contains("ParallelCrossPartitionQueryPipelineStage")); + } + + try + { + average = secondQuery.Average(x => x.taskNum); + Assert.Fail("Expected Average query to return exception"); + } + catch (CosmosException exception) + { + Assert.IsTrue(exception.StatusCode == System.Net.HttpStatusCode.BadRequest); + Assert.IsTrue(exception.SubStatusCode == (int)Documents.SubStatusCodes.MalformedContinuationToken); + Assert.IsTrue(exception.Message.Contains("ParallelCrossPartitionQueryPipelineStage")); + } + } + [TestMethod] public async Task LinqSelectEverythingWithoutQueryableTest() { @@ -911,7 +967,6 @@ private class NumberLinqItem public decimal decimaleValue; public bool booleanValue; public NumberLinqItem[] children; - } private async Task> FetchResults(QueryDefinition queryDefinition) From b909bd7ee4b00ee4d6a28f744ab300138aa37ad3 Mon Sep 17 00:00:00 2001 From: Kiran Kumar Kolli Date: Mon, 11 Sep 2023 12:48:13 -0700 Subject: [PATCH 187/337] [Internal] Benchmark tool: Fixes code refractoring to model the metrics as EventSource (#4040) * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Fixing code review points. * make MetrcisCollectorProvider non static and remove locks * fix * fixes * use static class name TelemetrySpan.IncludePercentile * use app insights connection string * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * rename AppInsightsConnectionString * fix * fix comments * fix if AppInsights c string is not set * summary * fix * remove unnecessary collector types * remove unnecesary metere provicer * add event source * remove folder * fix * split success and failed latencies * Code refractor to use EvenSource design pattern for metrics * Fixing build breaks * Removing BenchmarkExecutionEventSource * Fixign misc things * Some extra cleanup * use TimeSpan except milliseconds * fix metrics publication * fix metrics publication * move tests to benchmark folder * move back benchmark test * use background task for flushing metrics * remove sync metrics flushing * split failed and success operations * fix latenclies charts * fix benchmark run command * remove ShouldUnsetParentConfigurationAndPlatform=false --------- Co-authored-by: Mikhail Lipin Co-authored-by: David Chaava Co-authored-by: David Chaava --- .../AzureVmBenchmark/system/cloud-init.txt | 3 - .../Benchmark/BenchmarkLatencyEventSource.cs | 12 +++ .../Benchmark/CosmosBenchmarkEventListener.cs | 92 ++++++++++++++++++ .../Benchmark/Fx/DiagnosticDataListener.cs | 15 +-- .../Tools/Benchmark/Fx/IExecutionStrategy.cs | 3 +- .../Tools/Benchmark/Fx/IExecutor.cs | 3 +- .../Tools/Benchmark/Fx/IMetricsCollector.cs | 20 +--- .../Tools/Benchmark/Fx/MetricsCollector.cs | 59 +++++++----- .../Benchmark/Fx/MetricsCollectorProvider.cs | 96 ------------------- .../Tools/Benchmark/Fx/OperationResult.cs | 1 + .../Benchmark/Fx/ParallelExecutionStrategy.cs | 11 +-- .../Benchmark/Fx/SerialOperationExecutor.cs | 21 +--- .../Tools/Benchmark/Fx/TelemetrySpan.cs | 52 +++++----- .../Tools/Benchmark/MetricCollectionWindow.cs | 25 +++-- .../Tools/Benchmark/Program.cs | 48 +++++----- .../v2/InsertV2BenchmarkOperation.cs | 1 + ...QueryStreamSinglePkV2BenchmarkOperation.cs | 1 + .../v2/QueryTSinglePkV2BenchmarkOperation.cs | 1 + .../v2/ReadFeedStreamV2BenchmarkOperation.cs | 1 + .../v2/ReadNotExistsV2BenchmarkOperation.cs | 1 + .../ReadStreamExistsV2BenchmarkOperation.cs | 1 + .../v2/ReadTExistsV2BenchmarkOperation.cs | 1 + .../v3/InsertV3BenchmarkOperation.cs | 1 + .../v3/QueryTV3BenchmarkOperation.cs | 1 + .../v3/ReadFeedStreamV3BenchmarkOperation.cs | 1 + .../v3/ReadNotExistsV3BenchmarkOperation.cs | 1 + .../ReadStreamExistsV3BenchmarkOperation.cs | 1 + ...istsWithDiagnosticsV3BenchmarkOperation.cs | 1 + .../v3/ReadTExistsV3BenchmarkOperation.cs | 1 + 29 files changed, 238 insertions(+), 237 deletions(-) create mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmarkEventListener.cs delete mode 100644 Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt index 6821dcaa15..b6a0419fd5 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/system/cloud-init.txt @@ -4,9 +4,6 @@ packages: - azure-cli runcmd: - - wget https://aka.ms/downloadazcopy-v10-linux - - tar -xvf downloadazcopy-v10-linux - - sudo cp ./azcopy_linux_amd64_*/azcopy /usr/bin/ - wget https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb - sudo dpkg -i packages-microsoft-prod.deb - sudo apt update diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs index 5a945d21da..6b1b6d03d7 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkLatencyEventSource.cs @@ -45,5 +45,17 @@ public void LatencyDiagnostics( this.WriteEvent(1, dbName, containerName, durationInMs, lazyDiagnostics()); } } + + [Event(2, Level = EventLevel.Informational)] + public void OnOperationSuccess(int operationType, double durationInMs) + { + this.WriteEvent(2, operationType, durationInMs); + } + + [Event(3, Level = EventLevel.Informational)] + public void OnOperationFailure(int operationType, double durationInMs) + { + this.WriteEvent(3, operationType, durationInMs); + } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmarkEventListener.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmarkEventListener.cs new file mode 100644 index 0000000000..d12cb6c476 --- /dev/null +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/CosmosBenchmarkEventListener.cs @@ -0,0 +1,92 @@ +namespace CosmosBenchmark +{ + using System; + using System.Diagnostics.Tracing; + using System.Threading; + using System.Threading.Tasks; + using OpenTelemetry.Metrics; + + internal class CosmosBenchmarkEventListener : EventListener + { + static readonly string CosmosBenchmarkEventSourceName = "Azure.Cosmos.Benchmark"; + + private readonly MeterProvider meterProvider; + private readonly MetricsCollector[] metricsCollectors; + private readonly MetricCollectionWindow metricCollectionWindow; + private const int WindowCheckInterval = 10; + + public CosmosBenchmarkEventListener(MeterProvider meterProvider, BenchmarkConfig config) + { + this.meterProvider = meterProvider; + this.metricCollectionWindow ??= new MetricCollectionWindow(config.MetricsReportingIntervalInSec); + + this.metricsCollectors = new MetricsCollector[Enum.GetValues().Length]; + foreach (BenchmarkOperationType entry in Enum.GetValues()) + { + this.metricsCollectors[(int)entry] = new MetricsCollector(entry); + } + + /// + /// Flush metrics every + /// + ThreadPool.QueueUserWorkItem(async state => + { + while (true) + { + // Reset metricCollectionWindow and flush. + if (this.metricCollectionWindow.IsInvalid()) + { + this.meterProvider.ForceFlush(); + this.metricCollectionWindow.Reset(); + } + await Task.Delay(TimeSpan.FromMilliseconds(CosmosBenchmarkEventListener.WindowCheckInterval)); + } + }); + } + + + + /// + /// Override this method to get a list of all the eventSources that exist. + /// + protected override void OnEventSourceCreated(EventSource eventSource) + { + // Because we want to turn on every EventSource, we subscribe to a callback that triggers + // when new EventSources are created. It is also fired when the EventListener is created + // for all pre-existing EventSources. Thus this callback get called once for every + // EventSource regardless of the order of EventSource and EventListener creation. + + // For any EventSource we learn about, turn it on. + if (eventSource.Name == CosmosBenchmarkEventSourceName) + { + this.EnableEvents(eventSource, EventLevel.Informational, EventKeywords.All); + } + } + + /// + /// We override this method to get a callback on every event we subscribed to with EnableEvents + /// + /// + protected override void OnEventWritten(EventWrittenEventArgs eventData) + { + if (eventData.EventId == 2 // Successful + || eventData.EventId == 3) // Failure + { + int operationTypeIndex = (int)eventData.Payload[0]; + double durationInMs = (double)eventData.Payload[1]; + + switch (eventData.EventId) + { + case 2: + this.metricsCollectors[operationTypeIndex].OnOperationSuccess(durationInMs); + break; + case 3: + this.metricsCollectors[operationTypeIndex].OnOperationFailure(durationInMs); + break; + default: + break; + } + } + } + } +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs index 1171a05faa..fe7da4a2e2 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs @@ -131,13 +131,16 @@ public DiagnosticDataListener(BenchmarkConfig config) /// An instance of containing the request latency and diagnostics. protected override void OnEventWritten(EventWrittenEventArgs eventData) { - try + if (eventData.EventId == 1) { - this.Writer.WriteLine($"{eventData.Payload[2]} ; {eventData.Payload[3]}"); - } - catch (Exception ex) - { - Utility.TraceError("An exception ocured while writing diagnostic data to the file", ex); + try + { + this.Writer.WriteLine($"{eventData.Payload[2]} ; {eventData.Payload[3]}"); + } + catch (Exception ex) + { + Utility.TraceError("An exception ocured while writing diagnostic data to the file", ex); + } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs index ed1400026b..e517439419 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutionStrategy.cs @@ -20,7 +20,6 @@ public Task ExecuteAsync( BenchmarkConfig benchmarkConfig, int serialExecutorConcurrency, int serialExecutorIterationCount, - double warmupFraction, - MetricsCollectorProvider metricsCollectorProvider); + double warmupFraction); } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs index 235a54199b..c4d1c765e7 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IExecutor.cs @@ -18,7 +18,6 @@ public Task ExecuteAsync( bool isWarmup, bool traceFailures, Action completionCallback, - BenchmarkConfig benchmarkConfig, - MetricsCollectorProvider metricsCollectorProvider); + BenchmarkConfig benchmarkConfig); } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs index 58af9d0b19..fa5558c31b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/IMetricsCollector.cs @@ -12,25 +12,13 @@ namespace CosmosBenchmark public interface IMetricsCollector { /// - /// Collects the number of successful operations. + /// Successful operation with latency /// - void CollectMetricsOnSuccess(); + void OnOperationSuccess(double operationLatencyInMs); /// - /// Collects the number of failed operations. + /// Failed operation with latency /// - void CollectMetricsOnFailure(); - - /// - /// Records latency for success operations in milliseconda. - /// - /// The number of milliseconds to record. - void RecordSuccessOpLatencyAndRps(TimeSpan timeSpan); - - /// - /// Records latency for failed operations in milliseconda. - /// - /// The number of milliseconds to record. - void RecordFailedOpLatencyAndRps(TimeSpan timeSpan); + void OnOperationFailure(double operationLatencyInMs); } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs index 1676dd0052..4f1fc68257 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollector.cs @@ -5,6 +5,7 @@ namespace CosmosBenchmark { using System; + using System.Collections.Generic; using System.Diagnostics.Metrics; /// @@ -96,45 +97,55 @@ internal class MetricsCollector : IMetricsCollector /// Initialize new instance of . /// /// OpenTelemetry meter. - public MetricsCollector(Meter meter, string prefix) + public MetricsCollector(BenchmarkOperationType operationType) { - this.meter = meter; - this.rpsMetricNameHistogram = meter.CreateHistogram($"{prefix}OperationRpsHistogram"); - this.operationLatencyHistogram = meter.CreateHistogram($"{prefix}OperationLatencyInMsHistogram"); + this.meter = new Meter($"CosmosBenchmark{operationType}OperationMeter"); + this.rpsMetricNameHistogram = this.meter.CreateHistogram($"{operationType}OperationRpsHistogram"); + this.operationLatencyHistogram = this.meter.CreateHistogram($"{operationType}OperationLatencyInMsHistogram"); - this.rpsFailedMetricNameHistogram = meter.CreateHistogram($"{prefix}FailedOperationRpsHistogram"); - this.operationFailedLatencyHistogram = meter.CreateHistogram($"{prefix}FailedOperationLatencyInMsHistogram"); + this.rpsFailedMetricNameHistogram = this.meter.CreateHistogram($"{operationType}FailedOperationRpsHistogram"); + this.operationFailedLatencyHistogram = this.meter.CreateHistogram($"{operationType}FailedOperationLatencyInMsHistogram"); - this.successOperationCounter = meter.CreateCounter($"{prefix}OperationSuccess"); - this.failureOperationCounter = meter.CreateCounter($"{prefix}OperationFailure"); + this.successOperationCounter = this.meter.CreateCounter($"{operationType}OperationSuccess"); + this.failureOperationCounter = this.meter.CreateCounter($"{operationType}OperationFailure"); - this.latencyInMsMetricNameGauge = this.meter.CreateObservableGauge($"{prefix}OperationLatencyInMs", + this.latencyInMsMetricNameGauge = this.meter.CreateObservableGauge($"{operationType}OperationLatencyInMs", () => new Measurement(this.latencyInMs)); - this.rpsNameGauge = this.meter.CreateObservableGauge($"{prefix}OperationRps", + this.rpsNameGauge = this.meter.CreateObservableGauge($"{operationType}OperationRps", () => new Measurement(this.rps)); - this.latencyInMsFailedMetricNameGauge = this.meter.CreateObservableGauge($"{prefix}FailedOperationLatencyInMs", - () => new Measurement(this.latencyInMs)); + this.latencyInMsFailedMetricNameGauge = this.meter.CreateObservableGauge($"{operationType}FailedOperationLatencyInMs", + () => new Measurement(this.latencyFailedInMs)); - this.rpsFailedNameGauge = this.meter.CreateObservableGauge($"{prefix}FailedOperationRps", - () => new Measurement(this.rps)); + this.rpsFailedNameGauge = this.meter.CreateObservableGauge($"{operationType}FailedOperationRps", + () => new Measurement(this.rpsFailed)); + } + + internal static IEnumerable GetBenchmarkMeterNames() + { + foreach (BenchmarkOperationType entry in Enum.GetValues()) + { + yield return $"CosmosBenchmark{entry}OperationMeter"; + } } /// - /// Collects the number of successful operations. + /// Successful operation with latency /// - public void CollectMetricsOnSuccess() + public void OnOperationSuccess(double operationLatencyInMs) { this.successOperationCounter.Add(1); + this.RecordSuccessOpLatencyAndRps(operationLatencyInMs); } /// - /// Collects the number of failed operations. + /// Failed operation with latency /// - public void CollectMetricsOnFailure() + public void OnOperationFailure(double operationLatencyInMs) { this.failureOperationCounter.Add(1); + this.RecordFailedOpLatencyAndRps(operationLatencyInMs); } /// @@ -142,10 +153,10 @@ public void CollectMetricsOnFailure() /// /// The number of milliseconds to record. public void RecordSuccessOpLatencyAndRps( - TimeSpan timeSpan) + double operationLatencyInMs) { - this.rps = timeSpan.TotalMilliseconds != 0 ? 1000 / timeSpan.TotalMilliseconds : 0; - this.latencyInMs = timeSpan.TotalMilliseconds; + this.rps = operationLatencyInMs != 0 ? 1000 / operationLatencyInMs : 0; + this.latencyInMs = operationLatencyInMs; this.rpsMetricNameHistogram.Record(this.rps); this.operationLatencyHistogram.Record(this.latencyInMs); } @@ -155,10 +166,10 @@ public void RecordSuccessOpLatencyAndRps( /// /// The number of milliseconds to record. public void RecordFailedOpLatencyAndRps( - TimeSpan timeSpan) + double operationLatencyInMs) { - this.rpsFailed = timeSpan.TotalMilliseconds != 0 ? 1000 / timeSpan.TotalMilliseconds : 0; - this.latencyFailedInMs = timeSpan.TotalMilliseconds; + this.rpsFailed = operationLatencyInMs != 0 ? 1000 / operationLatencyInMs : 0; + this.latencyFailedInMs = operationLatencyInMs; this.rpsFailedMetricNameHistogram.Record(this.rpsFailed); this.operationFailedLatencyHistogram.Record(this.latencyFailedInMs); } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs deleted file mode 100644 index f49d9ec571..0000000000 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/MetricsCollectorProvider.cs +++ /dev/null @@ -1,96 +0,0 @@ -//------------------------------------------------------------ -// Copyright (c) Microsoft Corporation. All rights reserved. -//------------------------------------------------------------ - -namespace CosmosBenchmark -{ - using System; - using System.Diagnostics.Metrics; - using System.Threading; - using System.Threading.Tasks; - using OpenTelemetry.Metrics; - - /// - /// Represents the metrics collector provider. - /// - internal class MetricsCollectorProvider - { - private const int WindowCheckInterval = 10; - private MetricCollectionWindow metricCollectionWindow; - - private static readonly object metricCollectionWindowLock = new object(); - - private readonly MetricsCollector insertOperationMetricsCollector; - - private readonly MetricsCollector queryOperationMetricsCollector; - - private readonly MetricsCollector readOperationMetricsCollector; - - private readonly Meter insertOperationMeter = new("CosmosBenchmarkInsertOperationMeter"); - - private readonly Meter queryOperationMeter = new("CosmosBenchmarkQueryOperationMeter"); - - private readonly Meter readOperationMeter = new("CosmosBenchmarkReadOperationMeter"); - - private readonly MeterProvider meterProvider; - - public MetricsCollectorProvider(BenchmarkConfig config, MeterProvider meterProvider) - { - this.meterProvider = meterProvider; - this.insertOperationMetricsCollector ??= new MetricsCollector(this.insertOperationMeter, "Insert"); - this.queryOperationMetricsCollector ??= new MetricsCollector(this.queryOperationMeter, "Query"); - this.readOperationMetricsCollector ??= new MetricsCollector(this.readOperationMeter, "Read"); - this.metricCollectionWindow ??= new MetricCollectionWindow(config); - - /// - /// Flush metrics every - /// - ThreadPool.QueueUserWorkItem(async state => - { - while (true) - { - MetricCollectionWindow metricCollectionWindow = this.GetCurrentMetricCollectionWindow(config); - - // Reset metricCollectionWindow and flush. - if (!metricCollectionWindow.IsValid) - { - this.meterProvider.ForceFlush(); - this.metricCollectionWindow.Reset(config); - } - await Task.Delay(TimeSpan.FromMilliseconds(MetricsCollectorProvider.WindowCheckInterval)); - } - }); - } - - private MetricCollectionWindow GetCurrentMetricCollectionWindow(BenchmarkConfig config) - { - if (this.metricCollectionWindow is null || !this.metricCollectionWindow.IsValid) - { - lock (metricCollectionWindowLock) - { - this.metricCollectionWindow ??= new MetricCollectionWindow(config); - } - } - - return this.metricCollectionWindow; - } - - /// - /// Gets the metric collector. - /// - /// Benchmark operation. - /// Benchmark configuration. - /// Metrics collector. - /// Thrown if provided benchmark operation is not covered supported to collect metrics. - public IMetricsCollector GetMetricsCollector(IBenchmarkOperation benchmarkOperation) - { - return benchmarkOperation.OperationType switch - { - BenchmarkOperationType.Insert => this.insertOperationMetricsCollector, - BenchmarkOperationType.Query => this.queryOperationMetricsCollector, - BenchmarkOperationType.Read => this.readOperationMetricsCollector, - _ => throw new NotSupportedException($"The type of {nameof(benchmarkOperation)} is not supported for collecting metrics."), - }; - } - } -} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/OperationResult.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/OperationResult.cs index 0e87c33b35..a7f34b8bb0 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/OperationResult.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/OperationResult.cs @@ -7,6 +7,7 @@ internal struct OperationResult { public string DatabseName { get; set; } public string ContainerName { get; set; } + public BenchmarkOperationType OperationType { get; set; } public double RuCharges { get; set; } public Func LazyDiagnostics { get; set; } public CosmosDiagnostics CosmosDiagnostics { get; set; } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs index d32052e3fe..018f7f1615 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/ParallelExecutionStrategy.cs @@ -29,8 +29,7 @@ public async Task ExecuteAsync( BenchmarkConfig benchmarkConfig, int serialExecutorConcurrency, int serialExecutorIterationCount, - double warmupFraction, - MetricsCollectorProvider metricsCollectorProvider) + double warmupFraction) { IExecutor warmupExecutor = new SerialOperationExecutor( executorId: "Warmup", @@ -39,9 +38,8 @@ await warmupExecutor.ExecuteAsync( (int)(serialExecutorIterationCount * warmupFraction), isWarmup: true, traceFailures: benchmarkConfig.TraceFailures, - completionCallback: () => { }, - benchmarkConfig, - metricsCollectorProvider); + completionCallback: () => { }, + benchmarkConfig); Utility.TeePrint("Starting execution {0} tasks", serialExecutorConcurrency); IExecutor[] executors = new IExecutor[serialExecutorConcurrency]; @@ -60,8 +58,7 @@ await warmupExecutor.ExecuteAsync( isWarmup: false, traceFailures: benchmarkConfig.TraceFailures, completionCallback: () => Interlocked.Decrement(ref this.pendingExecutorCount), - benchmarkConfig, - metricsCollectorProvider); + benchmarkConfig); } return await this.LogOutputStats( diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs index 3bb84e26fa..200a647e77 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/SerialOperationExecutor.cs @@ -13,7 +13,6 @@ namespace CosmosBenchmark internal class SerialOperationExecutor : IExecutor { private readonly IBenchmarkOperation operation; - private readonly string executorId; public SerialOperationExecutor( @@ -28,7 +27,6 @@ public SerialOperationExecutor( } public int SuccessOperationCount { get; private set; } - public int FailedOperationCount { get; private set; } public double TotalRuCharges { get; private set; } @@ -38,19 +36,15 @@ public async Task ExecuteAsync( bool isWarmup, bool traceFailures, Action completionCallback, - BenchmarkConfig benchmarkConfig, - MetricsCollectorProvider metricsCollectorProvider) + BenchmarkConfig benchmarkConfig) { Trace.TraceInformation($"Executor {this.executorId} started"); - Trace.TraceInformation("Initializing counters and metrics."); - try { int currentIterationCount = 0; do { - IMetricsCollector metricsCollector = metricsCollectorProvider.GetMetricsCollector(this.operation); OperationResult? operationResult = null; await this.operation.PrepareAsync(); @@ -58,15 +52,12 @@ public async Task ExecuteAsync( using (ITelemetrySpan telemetrySpan = TelemetrySpan.StartNew( benchmarkConfig, () => operationResult.Value, - disableTelemetry: isWarmup, - metricsCollector.RecordSuccessOpLatencyAndRps, - metricsCollector.RecordFailedOpLatencyAndRps)) + disableTelemetry: isWarmup)) { try { operationResult = await this.operation.ExecuteOnceAsync(); - - metricsCollector.CollectMetricsOnSuccess(); + telemetrySpan.MarkSuccess(); // Success case this.SuccessOperationCount++; @@ -79,13 +70,11 @@ public async Task ExecuteAsync( } catch (Exception ex) { + telemetrySpan.MarkFailed(); if (traceFailures) { Trace.TraceInformation(ex.ToString()); } - telemetrySpan.MarkFailed(); - - metricsCollector.CollectMetricsOnFailure(); // failure case this.FailedOperationCount++; @@ -123,4 +112,4 @@ public async Task ExecuteAsync( } } } -} \ No newline at end of file +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs index 4f8785860d..ae03edcfa3 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/TelemetrySpan.cs @@ -19,8 +19,6 @@ internal class TelemetrySpan : ITelemetrySpan private Stopwatch stopwatch; private Func lazyOperationResult; - private Action recordFailedOpLatencyAction; - private Action recordSuccessOpLatencyAction; private bool disableTelemetry; private bool isFailed = false; private BenchmarkConfig benchmarkConfig; @@ -28,9 +26,7 @@ internal class TelemetrySpan : ITelemetrySpan public static ITelemetrySpan StartNew( BenchmarkConfig benchmarkConfig, Func lazyOperationResult, - bool disableTelemetry, - Action recordSuccessOpLatencyAction, - Action recordFailedOpLatencyAction) + bool disableTelemetry) { if (disableTelemetry || !TelemetrySpan.IncludePercentile) { @@ -42,17 +38,25 @@ public static ITelemetrySpan StartNew( benchmarkConfig = benchmarkConfig, stopwatch = Stopwatch.StartNew(), lazyOperationResult = lazyOperationResult, - recordSuccessOpLatencyAction = recordSuccessOpLatencyAction, - recordFailedOpLatencyAction = recordFailedOpLatencyAction, disableTelemetry = disableTelemetry }; } - public void MarkFailed() { this.isFailed = true; } + public void MarkFailed() + { + this.isFailed = true; + this.stopwatch.Stop(); + } - public void Dispose() + public void MarkSuccess() { + this.isFailed = false; this.stopwatch.Stop(); + } + + public void Dispose() + { + this.stopwatch.Stop(); // No-op in-case of MarkFailed or MarkSuccess prior call if (!this.disableTelemetry) { OperationResult operationResult = this.lazyOperationResult(); @@ -61,14 +65,13 @@ public void Dispose() { RecordLatency(this.stopwatch.Elapsed.TotalMilliseconds); - if(this.isFailed) + if (this.isFailed) { - this.recordSuccessOpLatencyAction?.Invoke(this.stopwatch.Elapsed); + BenchmarkLatencyEventSource.Instance.OnOperationFailure((int)operationResult.OperationType, this.stopwatch.Elapsed.TotalMilliseconds); } else { - this.recordSuccessOpLatencyAction?.Invoke(this.stopwatch.Elapsed); - + BenchmarkLatencyEventSource.Instance.OnOperationSuccess((int)operationResult.OperationType, this.stopwatch.Elapsed.TotalMilliseconds); } } @@ -76,9 +79,8 @@ public void Dispose() operationResult.DatabseName, operationResult.ContainerName, (int)this.stopwatch.ElapsedMilliseconds, - operationResult.LazyDiagnostics, + operationResult.LazyDiagnostics, this.benchmarkConfig.DiagnosticLatencyThresholdInMs); - } } @@ -104,16 +106,6 @@ internal static void ResetLatencyHistogram(int totalNumberOfIterations) return MathNet.Numerics.Statistics.Statistics.Percentile(latencyHistogram.Take(latencyIndex + 1), percentile); } - internal static double? GetLatencyQuantile(double quantile) - { - if (TelemetrySpan.latencyHistogram == null) - { - return null; - } - - return MathNet.Numerics.Statistics.Statistics.Quantile(latencyHistogram.Take(latencyIndex + 1), quantile); - } - private class NoOpDisposable : ITelemetrySpan { public static readonly NoOpDisposable Instance = new NoOpDisposable(); @@ -122,13 +114,19 @@ public void Dispose() { } + public void MarkSuccess() + { + } + public void MarkFailed() { } } - public interface ITelemetrySpan : IDisposable { + public interface ITelemetrySpan : IDisposable + { + void MarkSuccess(); void MarkFailed(); } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs index 948ade075e..fabdcfc75d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/MetricCollectionWindow.cs @@ -11,38 +11,35 @@ namespace CosmosBenchmark /// internal class MetricCollectionWindow { - /// - /// The timestamp when window span is started. - /// - public DateTime Started { get; private set; } + private DateTime ValidTill { get; set; } - /// - /// The timestamp until which the current window span is not elapsed. - /// - public DateTime ValidTill { get; private set; } + private int MetricsReportingIntervalInSec { get; set; } /// /// Creates the instance of . /// /// Cosmos Benchmark configuration. - public MetricCollectionWindow(BenchmarkConfig config) + public MetricCollectionWindow(int metricsReportingIntervalInSec) { - this.Reset(config); + this.MetricsReportingIntervalInSec = metricsReportingIntervalInSec; + this.Reset(); } /// /// Indicates whether the current window is valid. /// - public bool IsValid => DateTime.UtcNow > this.ValidTill; + public bool IsInvalid() + { + return DateTime.UtcNow > this.ValidTill; + } /// /// Resets the started timestamp and valid till timespan. /// /// - public void Reset(BenchmarkConfig config) + public void Reset() { - this.Started = DateTime.UtcNow; - this.ValidTill = this.Started.AddSeconds(config.MetricsReportingIntervalInSec); + this.ValidTill = DateTime.UtcNow.AddSeconds(this.MetricsReportingIntervalInSec); } } } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs index 744d53f2af..d1f8677cc6 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs @@ -41,8 +41,7 @@ public static async Task Main(string[] args) await AddAzureInfoToRunSummary(); MeterProvider meterProvider = BuildMeterProvider(config); - - MetricsCollectorProvider metricsCollectorProvider = new MetricsCollectorProvider(config, meterProvider); + CosmosBenchmarkEventListener listener = new CosmosBenchmarkEventListener(meterProvider, config); ThreadPool.SetMinThreads(config.MinThreadPoolSize, config.MinThreadPoolSize); @@ -62,7 +61,7 @@ public static async Task Main(string[] args) Program program = new Program(); - RunSummary runSummary = await program.ExecuteAsync(config, metricsCollectorProvider); + RunSummary runSummary = await program.ExecuteAsync(config); if (!string.IsNullOrEmpty(config.DiagnosticsStorageConnectionString)) { @@ -90,25 +89,28 @@ public static async Task Main(string[] args) /// private static MeterProvider BuildMeterProvider(BenchmarkConfig config) { + MeterProviderBuilder meterProviderBuilder = Sdk.CreateMeterProviderBuilder(); if (string.IsNullOrWhiteSpace(config.AppInsightsConnectionString)) { - return Sdk.CreateMeterProviderBuilder() - .AddMeter("CosmosBenchmarkInsertOperationMeter") - .AddMeter("CosmosBenchmarkQueryOperationMeter") - .AddMeter("CosmosBenchmarkReadOperationMeter") - .Build(); + foreach(string benchmarkName in MetricsCollector.GetBenchmarkMeterNames()) + { + meterProviderBuilder = meterProviderBuilder.AddMeter(benchmarkName); + }; + + return meterProviderBuilder.Build(); } OpenTelemetry.Trace.TracerProviderBuilder tracerProviderBuilder = Sdk.CreateTracerProviderBuilder() .AddAzureMonitorTraceExporter(); - return Sdk.CreateMeterProviderBuilder() - .AddAzureMonitorMetricExporter(configure: new Action( - (options) => options.ConnectionString = config.AppInsightsConnectionString)) - .AddMeter("CosmosBenchmarkInsertOperationMeter") - .AddMeter("CosmosBenchmarkQueryOperationMeter") - .AddMeter("CosmosBenchmarkReadOperationMeter") - .Build(); + meterProviderBuilder = meterProviderBuilder.AddAzureMonitorMetricExporter(configure: new Action( + (options) => options.ConnectionString = config.AppInsightsConnectionString)); + foreach (string benchmarkName in MetricsCollector.GetBenchmarkMeterNames()) + { + meterProviderBuilder = meterProviderBuilder.AddMeter(benchmarkName); + }; + + return meterProviderBuilder.Build(); } /// @@ -138,13 +140,11 @@ private static async Task AddAzureInfoToRunSummary() } } - /// /// Executing benchmarks for V2/V3 cosmosdb SDK. /// /// a Task object. - private async Task ExecuteAsync(BenchmarkConfig config, - MetricsCollectorProvider metricsCollectorProvider) + private async Task ExecuteAsync(BenchmarkConfig config) { // V3 SDK client initialization using (CosmosClient cosmosClient = config.CreateCosmosClient(config.Key)) @@ -200,7 +200,7 @@ private async Task ExecuteAsync(BenchmarkConfig config, } IExecutionStrategy execution = IExecutionStrategy.StartNew(benchmarkOperationFactory); - runSummary = await execution.ExecuteAsync(config, taskCount, opsPerTask, 0.01, metricsCollectorProvider); + runSummary = await execution.ExecuteAsync(config, taskCount, opsPerTask, 0.01); } if (config.CleanupOnFinish) @@ -224,8 +224,8 @@ private async Task ExecuteAsync(BenchmarkConfig config, Utility.TeeTraceInformation("Publishing results"); runSummary.Diagnostics = CosmosDiagnosticsLogger.GetDiagnostics(); await this.PublishResults( - config, - runSummary, + config, + runSummary, cosmosClient); } @@ -234,8 +234,8 @@ await this.PublishResults( } private async Task PublishResults( - BenchmarkConfig config, - RunSummary runSummary, + BenchmarkConfig config, + RunSummary runSummary, CosmosClient benchmarkClient) { if (string.IsNullOrEmpty(config.ResultsEndpoint)) @@ -390,4 +390,4 @@ private static void ClearCoreSdkListeners() traceSource.Listeners.Clear(); } } -} \ No newline at end of file +} diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs index 124c841085..aafe6d4d4e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/InsertV2BenchmarkOperation.cs @@ -55,6 +55,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = ruCharges, LazyDiagnostics = () => itemResponse.RequestDiagnosticsString, }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs index b0f071f6de..222fa5fa3f 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryStreamSinglePkV2BenchmarkOperation.cs @@ -82,6 +82,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = totalCharge, LazyDiagnostics = lastDiagnostics, }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs index cd50a789b8..7abb881ba1 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/QueryTSinglePkV2BenchmarkOperation.cs @@ -90,6 +90,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = totalCharge, LazyDiagnostics = lastDiagnostics, }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs index 0a9b9e3d7f..49e92195ce 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadFeedStreamV2BenchmarkOperation.cs @@ -54,6 +54,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = ruCharges, LazyDiagnostics = () => feedResponse.QueryMetrics.ToString(), }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs index 1d8b99449e..825d10ab60 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadNotExistsV2BenchmarkOperation.cs @@ -61,6 +61,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = dce.RequestCharge, LazyDiagnostics = () => dce.ToString(), }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs index c7419db811..041d9e4ffd 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadStreamExistsV2BenchmarkOperation.cs @@ -58,6 +58,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = ruCharges, LazyDiagnostics = () => itemResponse.RequestDiagnosticsString, }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs index 7e161f8ffc..7058f07f66 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v2/ReadTExistsV2BenchmarkOperation.cs @@ -59,6 +59,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = ruCharges, LazyDiagnostics = () => itemResponse.RequestDiagnosticsString, }; diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs index 504148bfda..cb3acc5d7b 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/InsertV3BenchmarkOperation.cs @@ -55,6 +55,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databaseName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = ruCharges, CosmosDiagnostics = itemResponse.Diagnostics, LazyDiagnostics = () => itemResponse.Diagnostics.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs index f78153034b..a40a8d0834 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/QueryTV3BenchmarkOperation.cs @@ -108,6 +108,7 @@ private async Task ExecuteOnceAsyncDefault() { DatabseName = databaseName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = totalCharge, CosmosDiagnostics = lastDiagnostics, LazyDiagnostics = () => lastDiagnostics?.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs index 3b9c5cd800..cc69305450 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadFeedStreamV3BenchmarkOperation.cs @@ -59,6 +59,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = feedResponse.Headers.RequestCharge, CosmosDiagnostics = feedResponse.Diagnostics, LazyDiagnostics = () => feedResponse.Diagnostics.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs index 1804ea9852..c3a24f8dcd 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadNotExistsV3BenchmarkOperation.cs @@ -49,6 +49,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = itemResponse.Headers.RequestCharge, CosmosDiagnostics = itemResponse.Diagnostics, LazyDiagnostics = () => itemResponse.Diagnostics.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs index fabe8f20bd..752a773bdc 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsV3BenchmarkOperation.cs @@ -56,6 +56,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = itemResponse.Headers.RequestCharge, CosmosDiagnostics = itemResponse.Diagnostics, LazyDiagnostics = () => itemResponse.Diagnostics.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs index 74f2ac67f7..5963f04c3a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadStreamExistsWithDiagnosticsV3BenchmarkOperation.cs @@ -62,6 +62,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = itemResponse.Headers.RequestCharge, CosmosDiagnostics = itemResponse.Diagnostics, LazyDiagnostics = () => itemResponse.Diagnostics.ToString(), diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs index bb6295356e..1a1feccb82 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/v3/ReadTExistsV3BenchmarkOperation.cs @@ -55,6 +55,7 @@ public async Task ExecuteOnceAsync() { DatabseName = databsaeName, ContainerName = containerName, + OperationType = this.OperationType, RuCharges = itemResponse.Headers.RequestCharge, CosmosDiagnostics = itemResponse.Diagnostics, LazyDiagnostics = () => itemResponse.Diagnostics.ToString(), From be0c0981b80c2ba18b73588520a80e9437b289de Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Tue, 12 Sep 2023 16:30:41 +0530 Subject: [PATCH 188/337] first draft (#4079) --- .../Filters/DiagnosticsFilterHelper.cs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs index 60fb86fa5c..a5ca0215cb 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/OpenTelemetry/Filters/DiagnosticsFilterHelper.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Telemetry.Diagnostics { using System; using Documents; + using static Antlr4.Runtime.TokenStreamRewriter; internal static class DiagnosticsFilterHelper { @@ -26,7 +27,9 @@ public static bool IsLatencyThresholdCrossed( } else { - latencyThreshold = operationType == OperationType.Query ? DistributedTracingOptions.DefaultQueryTimeoutThreshold : DistributedTracingOptions.DefaultCrudLatencyThreshold; + latencyThreshold = DiagnosticsFilterHelper.IsPointOperation(operationType) ? + DistributedTracingOptions.DefaultCrudLatencyThreshold : + DistributedTracingOptions.DefaultQueryTimeoutThreshold; } return response.Diagnostics.GetClientElapsedTime() > latencyThreshold; @@ -44,5 +47,19 @@ public static bool IsSuccessfulResponse(OpenTelemetryAttributes response) || (response.StatusCode == System.Net.HttpStatusCode.Conflict && response.SubStatusCode == 0) || (response.StatusCode == System.Net.HttpStatusCode.PreconditionFailed && response.SubStatusCode == 0); } + + /// + /// Check if passed operation type is a point operation + /// + /// + public static bool IsPointOperation(OperationType operationType) + { + return operationType == OperationType.Create || + operationType == OperationType.Delete || + operationType == OperationType.Replace || + operationType == OperationType.Upsert || + operationType == OperationType.Patch || + operationType == OperationType.Read; + } } } From 391c3d9872aff6615c00dffaa313aaa7013b69a0 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:35:07 -0700 Subject: [PATCH 189/337] Subpartitioning: Fixes bug for queries on subpartitioned containers (#3934) * initial fix, needs testing on prod * test fix * clean up pr * query rework * refactors previous changes * requested changes and bug fixes * nits * requested changes * bug fixes * start of test * added test * nit: changed name of EffectivePartitionKeyRanges to EffectiveRangesForPartitionKey * Address code comments * Address code comments * saving work * addresses code comments * nit, spacing * PartitionKeyHash fixes * Fixes bugs in tests * Removed bad method, added additional test coverage * Removed EffectivePartitionKeyString use * test fix * requested changes * Requested changes * fixed test * Test fix * Added comment --------- Co-authored-by: SrinikhilReddy --- .../CosmosQueryExecutionContextFactory.cs | 94 +++++----- .../QueryClient/ContainerQueryProperties.cs | 11 +- .../Core/QueryClient/CosmosQueryClient.cs | 9 +- .../Query/v3Query/CosmosQueryClientCore.cs | 35 ++-- .../src/Routing/PartitionKeyHash.cs | 30 +++- .../src/Routing/PartitionKeyHashRange.cs | 2 +- .../src/Routing/PartitionKeyHashRanges.cs | 14 +- .../CosmosItemTests.cs | 4 +- .../CosmosQueryClientCoreTest.cs | 2 +- .../PartitionKeyHashBaselineTest.Lists.xml | 32 ++++ .../Microsoft.Azure.Cosmos.Tests.csproj | 3 + .../Pagination/InMemoryContainer.cs | 164 ++++++++++++++---- ...misticDirectExecutionQueryBaselineTests.cs | 23 ++- .../Query/SplitPartitionQueryTests.cs | 77 ++++++++ .../Routing/PartitionKeyHashBaselineTest.cs | 63 +++++++ .../PartitionKeyHashRangeSplitterAndMerger.cs | 49 +++++- 16 files changed, 471 insertions(+), 141 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SplitPartitionQueryTests.cs rename Microsoft.Azure.Cosmos/{src => tests/Microsoft.Azure.Cosmos.Tests}/Routing/PartitionKeyHashRangeSplitterAndMerger.cs (73%) diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index 43ebf6a2d8..01ed10a627 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext using System.Linq; using System.Threading; using System.Threading.Tasks; + using global::Azure; using Microsoft.Azure.Cosmos; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; @@ -27,6 +28,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext using Microsoft.Azure.Cosmos.SqlObjects; using Microsoft.Azure.Cosmos.SqlObjects.Visitors; using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents.Routing; internal static class CosmosQueryExecutionContextFactory { @@ -211,10 +213,10 @@ private static async Task> TryCreateCoreContextAsy // Only thing that matters is that we target the correct range. Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - List targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( + List targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, - containerQueryProperties.EffectivePartitionKeyString, + containerQueryProperties.EffectiveRangesForPartitionKey, forceRefresh: false, createQueryPipelineTrace); @@ -635,67 +637,54 @@ private static async Task GetPartitionedQueryExec ITrace trace) { List targetRanges; - if (containerQueryProperties.EffectivePartitionKeyString != null) + if (containerQueryProperties.EffectiveRangesForPartitionKey != null) { - targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( resourceLink, containerQueryProperties.ResourceId, - containerQueryProperties.EffectivePartitionKeyString, + containerQueryProperties.EffectiveRangesForPartitionKey, forceRefresh: false, trace); } else if (TryGetEpkProperty(properties, out string effectivePartitionKeyString)) { - targetRanges = await queryClient.GetTargetPartitionKeyRangesByEpkStringAsync( + //Note that here we have no way to consume the EPK string as there is no way to convert + //the string to the partition key type to evaulate the number of components which needs to be done for the + //multihahs methods/classes. This is particually important for queries with prefix partition key. + //the EPK sting header is only for internal use but this needs to be fixed in the future. + List> effectiveRanges = new List> + { Range.GetPointRange(effectivePartitionKeyString) }; + + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( resourceLink, containerQueryProperties.ResourceId, - effectivePartitionKeyString, + effectiveRanges, forceRefresh: false, trace); } else if (feedRangeInternal != null) { targetRanges = await queryClient.GetTargetPartitionKeyRangeByFeedRangeAsync( - resourceLink, - containerQueryProperties.ResourceId, - containerQueryProperties.PartitionKeyDefinition, - feedRangeInternal, - forceRefresh: false, - trace); + resourceLink, + containerQueryProperties.ResourceId, + containerQueryProperties.PartitionKeyDefinition, + feedRangeInternal, + forceRefresh: false, + trace); } else { - targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( - resourceLink, - containerQueryProperties.ResourceId, - partitionedQueryExecutionInfo.QueryRanges, - forceRefresh: false, - trace); + targetRanges = await queryClient.GetTargetPartitionKeyRangesAsync( + resourceLink, + containerQueryProperties.ResourceId, + partitionedQueryExecutionInfo.QueryRanges, + forceRefresh: false, + trace); } return targetRanges; } - private static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) - { - TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; - if (responseStats != null) - { - if (pipelineType == OptimisticDirectExecution) - { - responseStats.PipelineType = TestInjections.PipelineType.OptimisticDirectExecution; - } - else if (pipelineType == Specialized) - { - responseStats.PipelineType = TestInjections.PipelineType.Specialized; - } - else - { - responseStats.PipelineType = TestInjections.PipelineType.Passthrough; - } - } - } - private static bool TryGetEpkProperty( IReadOnlyDictionary properties, out string effectivePartitionKeyString) @@ -718,6 +707,26 @@ private static bool TryGetEpkProperty( return false; } + private static void SetTestInjectionPipelineType(InputParameters inputParameters, string pipelineType) + { + TestInjections.ResponseStats responseStats = inputParameters?.TestInjections?.Stats; + if (responseStats != null) + { + if (pipelineType == OptimisticDirectExecution) + { + responseStats.PipelineType = TestInjections.PipelineType.OptimisticDirectExecution; + } + else if (pipelineType == Specialized) + { + responseStats.PipelineType = TestInjections.PipelineType.Specialized; + } + else + { + responseStats.PipelineType = TestInjections.PipelineType.Passthrough; + } + } + } + private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputParameters inputParameters, ContainerQueryProperties containerQueryProperties) { //todo:elasticcollections this may rely on information from collection cache which is outdated @@ -781,14 +790,13 @@ private static Documents.PartitionKeyDefinition GetPartitionKeyDefinition(InputP else { Documents.PartitionKeyDefinition partitionKeyDefinition = GetPartitionKeyDefinition(inputParameters, containerQueryProperties); - if (inputParameters.PartitionKey != null) + if (inputParameters.PartitionKey.HasValue) { Debug.Assert(partitionKeyDefinition != null, "CosmosQueryExecutionContextFactory Assert!", "PartitionKeyDefinition cannot be null if partitionKey is defined"); - - targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesByEpkStringAsync( + targetRanges = await cosmosQueryContext.QueryClient.GetTargetPartitionKeyRangesAsync( cosmosQueryContext.ResourceLink, containerQueryProperties.ResourceId, - containerQueryProperties.EffectivePartitionKeyString, + containerQueryProperties.EffectiveRangesForPartitionKey, forceRefresh: false, trace); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs index 0baaceb9c6..279b7585b9 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/ContainerQueryProperties.cs @@ -4,24 +4,29 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryClient { + using System.Collections.Generic; using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Routing; internal readonly struct ContainerQueryProperties { public ContainerQueryProperties( string resourceId, - string effectivePartitionKeyString, + IReadOnlyList> effectivePartitionKeyRanges, PartitionKeyDefinition partitionKeyDefinition, Cosmos.GeospatialType geospatialType) { this.ResourceId = resourceId; - this.EffectivePartitionKeyString = effectivePartitionKeyString; + this.EffectiveRangesForPartitionKey = effectivePartitionKeyRanges; this.PartitionKeyDefinition = partitionKeyDefinition; this.GeospatialType = geospatialType; } public string ResourceId { get; } - public string EffectivePartitionKeyString { get; } + + //A PartitionKey has one range when it is a full PartitionKey value. + //It can span many it is a prefix PartitionKey for a sub-partitioned container. + public IReadOnlyList> EffectiveRangesForPartitionKey { get; } public PartitionKeyDefinition PartitionKeyDefinition { get; } public Cosmos.GeospatialType GeospatialType { get; } } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs index 3fa4cb90e7..d9dc0ac976 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryClient/CosmosQueryClient.cs @@ -76,13 +76,6 @@ public abstract Task ExecuteQueryPlanRequestAsync public abstract void ClearSessionTokenCache(string collectionFullName); - public abstract Task> GetTargetPartitionKeyRangesByEpkStringAsync( - string resourceLink, - string collectionResourceId, - string effectivePartitionKeyString, - bool forceRefresh, - ITrace trace); - public abstract Task> GetTargetPartitionKeyRangeByFeedRangeAsync( string resourceLink, string collectionResourceId, @@ -94,7 +87,7 @@ public abstract Task ExecuteQueryPlanRequestAsync public abstract Task> GetTargetPartitionKeyRangesAsync( string resourceLink, string collectionResourceId, - List> providedRanges, + IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace); diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs index cce1a5268a..a392632649 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/CosmosQueryClientCore.cs @@ -63,17 +63,26 @@ public override async Task GetCachedContainerQueryProp trace, cancellationToken); - string effectivePartitionKeyString = null; + List> effectivePartitionKeyRange = null; if (partitionKey != null) { // Dis-ambiguate the NonePK if used PartitionKeyInternal partitionKeyInternal = partitionKey.Value.IsNone ? containerProperties.GetNoneValue() : partitionKey.Value.InternalKey; - effectivePartitionKeyString = partitionKeyInternal.GetEffectivePartitionKeyString(containerProperties.PartitionKey); + effectivePartitionKeyRange = new List> + { + PartitionKeyInternal.GetEffectivePartitionKeyRange( + containerProperties.PartitionKey, + new Range( + min: partitionKeyInternal, + max: partitionKeyInternal, + isMinInclusive: true, + isMaxInclusive: true)) + }; } return new ContainerQueryProperties( containerProperties.ResourceId, - effectivePartitionKeyString, + effectivePartitionKeyRange, containerProperties.PartitionKey, containerProperties.GeospatialConfig.GeospatialType); } @@ -200,24 +209,6 @@ public override async Task ExecuteQueryPlanReques return partitionedQueryExecutionInfo; } - public override Task> GetTargetPartitionKeyRangesByEpkStringAsync( - string resourceLink, - string collectionResourceId, - string effectivePartitionKeyString, - bool forceRefresh, - ITrace trace) - { - return this.GetTargetPartitionKeyRangesAsync( - resourceLink, - collectionResourceId, - new List> - { - Range.GetPointRange(effectivePartitionKeyString) - }, - forceRefresh, - trace); - } - public override async Task> GetTargetPartitionKeyRangeByFeedRangeAsync( string resourceLink, string collectionResourceId, @@ -243,7 +234,7 @@ public override async Task> GetTargetPartitionKeyRangeBy public override async Task> GetTargetPartitionKeyRangesAsync( string resourceLink, string collectionResourceId, - List> providedRanges, + IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) { diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHash.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHash.cs index 42ef970915..0d7189abb2 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHash.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHash.cs @@ -5,7 +5,7 @@ namespace Microsoft.Azure.Cosmos.Routing { using System; - using System.Runtime.CompilerServices; + using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using Microsoft.Azure.Documents.Routing; @@ -35,12 +35,34 @@ namespace Microsoft.Azure.Cosmos.Routing /// internal readonly struct PartitionKeyHash : IComparable, IEquatable { + private readonly IReadOnlyList values; + public PartitionKeyHash(UInt128 value) + : this(new UInt128[] { value }) { - this.Value = value; } - public UInt128 Value { get; } + public PartitionKeyHash(UInt128[] values) + { + StringBuilder stringBuilder = new StringBuilder(); + foreach (UInt128 value in values) + { + if (stringBuilder.Length > 0) + { + stringBuilder.Append('-'); + } + stringBuilder.Append(value.ToString()); + } + + this.Value = stringBuilder.ToString(); + this.values = values; + } + + public readonly static PartitionKeyHash None = new PartitionKeyHash(0); + + public string Value { get; } + + internal readonly IReadOnlyList HashValues => this.values; public int CompareTo(PartitionKeyHash other) { @@ -66,7 +88,7 @@ public override bool Equals(object obj) public override int GetHashCode() => this.Value.GetHashCode(); - public override string ToString() => this.Value.ToString(); + public override string ToString() => this.Value; public static bool TryParse(string value, out PartitionKeyHash parsedValue) { diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRange.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRange.cs index 21e257b49a..7e8265e470 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRange.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRange.cs @@ -181,4 +181,4 @@ public override string ToString() return stringBuilder.ToString(); } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRanges.cs b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRanges.cs index a927fcba87..f15556a23d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRanges.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRanges.cs @@ -132,9 +132,9 @@ public static CreateOutcome TryCreate( { if (partitionKeyHashRange.StartInclusive.HasValue) { - if (partitionKeyHashRange.StartInclusive.Value.Value < minStart) + if (partitionKeyHashRange.StartInclusive.Value.HashValues[0] < minStart) { - minStart = partitionKeyHashRange.StartInclusive.Value.Value; + minStart = partitionKeyHashRange.StartInclusive.Value.HashValues[0]; } } else @@ -144,9 +144,9 @@ public static CreateOutcome TryCreate( if (partitionKeyHashRange.EndExclusive.HasValue) { - if (partitionKeyHashRange.EndExclusive.Value.Value > maxEnd) + if (partitionKeyHashRange.EndExclusive.Value.HashValues[0] > maxEnd) { - maxEnd = partitionKeyHashRange.EndExclusive.Value.Value; + maxEnd = partitionKeyHashRange.EndExclusive.Value.HashValues[0]; } } else @@ -154,8 +154,8 @@ public static CreateOutcome TryCreate( maxEnd = UInt128.MaxValue; } - UInt128 width = partitionKeyHashRange.EndExclusive.GetValueOrDefault(new PartitionKeyHash(UInt128.MaxValue)).Value - - partitionKeyHashRange.StartInclusive.GetValueOrDefault(new PartitionKeyHash(UInt128.MinValue)).Value; + UInt128 width = partitionKeyHashRange.EndExclusive.GetValueOrDefault(new PartitionKeyHash(UInt128.MaxValue)).HashValues[0] + - partitionKeyHashRange.StartInclusive.GetValueOrDefault(new PartitionKeyHash(UInt128.MinValue)).HashValues[0]; sumOfWidth += width; if (sumOfWidth < width) { @@ -223,4 +223,4 @@ public enum CreateOutcome Success, } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs index dd09fde938..607b552b83 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosItemTests.cs @@ -1664,7 +1664,6 @@ public async Task EpkPointReadTest() epk = new PartitionKey("test") .InternalKey .GetEffectivePartitionKeyString(this.containerSettings.PartitionKey); - properties = new Dictionary() { { WFConstants.BackendHeaders.EffectivePartitionKeyString, epk }, @@ -1714,9 +1713,11 @@ public async Task ItemEpkQuerySingleKeyRangeValidation() // If this fails the RUs of the container needs to be increased to ensure at least 2 partitions. Assert.IsTrue(ranges.Count > 1, " RUs of the container needs to be increased to ensure at least 2 partitions."); + ContainerQueryProperties containerQueryProperties = new ContainerQueryProperties( containerResponse.Resource.ResourceId, null, + //new List> { new Documents.Routing.Range("AA", "AA", true, true) }, containerResponse.Resource.PartitionKey, containerResponse.Resource.GeospatialConfig.GeospatialType); @@ -1734,6 +1735,7 @@ public async Task ItemEpkQuerySingleKeyRangeValidation() trace: NoOpTrace.Singleton); Assert.IsTrue(partitionKeyRanges.Count == 1, "Only 1 partition key range should be selected since the EPK option is set."); + } finally { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosQueryClientCoreTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosQueryClientCoreTest.cs index 21a8b4ad59..3f325eef9a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosQueryClientCoreTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosQueryClientCoreTest.cs @@ -51,7 +51,7 @@ public async Task TryGetOverlappingRangesAsyncTest() Assert.IsNotNull(containerProperties); Assert.IsNotNull(containerProperties.ResourceId); - Assert.IsNotNull(containerProperties.EffectivePartitionKeyString); + Assert.IsNotNull(containerProperties.EffectiveRangesForPartitionKey); IReadOnlyList pkRange = await this.queryClientCore.TryGetOverlappingRangesAsync( collectionResourceId: containerProperties.ResourceId, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml new file mode 100644 index 0000000000..3f7faa9f26 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/PartitionKeyHashBaselineTest.Lists.xml @@ -0,0 +1,32 @@ + + + + 1 Path List + ["/path1"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05 + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12 + + + + + 2 Path List + ["/path1","/path2"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78 + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C + + + + + 3 Path List + ["/path1","/path2","/path3"] + + + 00-00-00-00-00-00-00-00-00-00-00-00-0A-A1-CC-05-00-00-00-00-00-00-00-00-00-00-00-00-C9-1E-F0-78-00-00-00-00-00-00-00-00-00-00-00-00-9A-B4-68-CD + B6-3D-B6-C4-3A-4F-1B-01-4C-63-B0-C2-E6-28-E8-12-A6-0C-6C-BE-5A-2D-38-6E-5D-AE-1A-AC-94-21-6B-6C-88-A6-18-5D-2D-D5-1C-96-D0-47-75-B7-2E-FA-BE-08 + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 4d25f7e5a7..5b429468d8 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -115,6 +115,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs index f2201d3cc4..5c6e8961e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Pagination/InMemoryContainer.cs @@ -31,6 +31,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Pagination using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using ResourceIdentifier = Cosmos.Pagination.ResourceIdentifier; + using UInt128 = UInt128; // Collection useful for mocking requests and repartitioning (splits / merge). internal class InMemoryContainer : IMonadicDocumentContainer @@ -280,8 +281,8 @@ static Task> CreateNotFoundException(CosmosElement partitionKey requestCharge: 42))); } - PartitionKeyHash partitionKeyHash = GetHashFromPartitionKey( - partitionKey, + PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys( + new List { partitionKey }, this.partitionKeyDefinition); if (!this.partitionedRecords.TryGetValue(partitionKeyHash, out Records records)) @@ -797,9 +798,20 @@ public Task MonadicSplitAsync( } // Split the range space - PartitionKeyHashRanges partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange( - parentRange, - rangeCount: 2); + PartitionKeyHashRanges partitionKeyHashRanges; + if (this.partitionKeyDefinition.Kind == PartitionKind.MultiHash && + this.partitionKeyDefinition.Paths.Count > 1) + { + //For MultiHash, to help with testing we will split using the median partition key among documents. + PartitionKeyHash midPoint = this.ComputeMedianSplitPointAmongDocumentsInPKRange(parentRange); + partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange(parentRange, midPoint); + } + else + { + partitionKeyHashRanges = PartitionKeyHashRangeSplitterAndMerger.SplitRange( + parentRange, + rangeCount: 2); + } // Update the partition routing map int maxPartitionKeyRangeId = this.partitionKeyRangeIdToHashRange.Keys.Max(); @@ -1084,16 +1096,16 @@ private static PartitionKeyHash GetHashFromPayload( CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) { - CosmosElement partitionKey = GetPartitionKeyFromPayload(payload, partitionKeyDefinition); - return GetHashFromPartitionKey(partitionKey, partitionKeyDefinition); + IList partitionKey = GetPartitionKeysFromPayload(payload, partitionKeyDefinition); + return GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); } private static PartitionKeyHash GetHashFromObjectModel( Cosmos.PartitionKey payload, PartitionKeyDefinition partitionKeyDefinition) { - CosmosElement partitionKey = GetPartitionKeyFromObjectModel(payload); - return GetHashFromPartitionKey(partitionKey, partitionKeyDefinition); + IList partitionKeys = GetPartitionKeysFromObjectModel(payload); + return GetHashFromPartitionKeys(partitionKeys, partitionKeyDefinition); } private static CosmosElement GetPartitionKeyFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) @@ -1131,23 +1143,56 @@ private static CosmosElement GetPartitionKeyFromPayload(CosmosObject payload, Pa return partitionKey; } - private static CosmosElement GetPartitionKeyFromObjectModel(Cosmos.PartitionKey payload) + private static IList GetPartitionKeysFromPayload(CosmosObject payload, PartitionKeyDefinition partitionKeyDefinition) { - CosmosArray partitionKeyPayload = CosmosArray.Parse(payload.ToJsonString()); - if (partitionKeyPayload.Count != 1) + // Restrict the partition key definition for now to keep things simple + if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) { - throw new ArgumentOutOfRangeException("Can only support a single partition key path."); + throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); + } + + if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) + { + throw new ArgumentOutOfRangeException("Can only support hash v2"); + } + + IList cosmosElements = new List(); + foreach (string partitionKeyPath in partitionKeyDefinition.Paths) + { + IEnumerable tokens = partitionKeyPath.Split("/").Skip(1); + CosmosElement partitionKey = payload; + foreach (string token in tokens) + { + if (partitionKey != default) + { + if (!payload.TryGetValue(token, out partitionKey)) + { + partitionKey = default; + } + } + } + cosmosElements.Add(partitionKey); } + return cosmosElements; + } - return partitionKeyPayload[0]; + private static IList GetPartitionKeysFromObjectModel(Cosmos.PartitionKey payload) + { + CosmosArray partitionKeyPayload = CosmosArray.Parse(payload.ToJsonString()); + List cosmosElemementPayload = new List(); + foreach (CosmosElement element in partitionKeyPayload) + { + cosmosElemementPayload.Add(element); + } + return cosmosElemementPayload; } - private static PartitionKeyHash GetHashFromPartitionKey(CosmosElement partitionKey, PartitionKeyDefinition partitionKeyDefinition) + private static PartitionKeyHash GetHashFromPartitionKeys(IList partitionKeys, PartitionKeyDefinition partitionKeyDefinition) { // Restrict the partition key definition for now to keep things simple - if (partitionKeyDefinition.Kind != PartitionKind.Hash) + if (partitionKeyDefinition.Kind != PartitionKind.MultiHash && partitionKeyDefinition.Kind != PartitionKind.Hash) { - throw new ArgumentOutOfRangeException("Can only support hash partitioning"); + throw new ArgumentOutOfRangeException("Can only support Hash/MultiHash partitioning"); } if (partitionKeyDefinition.Version != Documents.PartitionKeyDefinitionVersion.V2) @@ -1155,21 +1200,41 @@ private static PartitionKeyHash GetHashFromPartitionKey(CosmosElement partitionK throw new ArgumentOutOfRangeException("Can only support hash v2"); } - if (partitionKeyDefinition.Paths.Count != 1) + IList partitionKeyHashValues = new List(); + + foreach (CosmosElement partitionKey in partitionKeys) { - throw new ArgumentOutOfRangeException("Can only support a single partition key path."); + if (partitionKey is CosmosArray cosmosArray) + { + foreach (CosmosElement element in cosmosArray) + { + PartitionKeyHash elementHash = element switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V2.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValues.Add(elementHash.HashValues[0]); + } + continue; + } + + PartitionKeyHash partitionKeyHash = partitionKey switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V2.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValues.Add(partitionKeyHash.HashValues[0]); } - PartitionKeyHash partitionKeyHash = partitionKey switch - { - null => PartitionKeyHash.V2.HashUndefined(), - CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), - CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), - CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), - CosmosNull _ => PartitionKeyHash.V2.HashNull(), - _ => throw new ArgumentOutOfRangeException(), - }; - return partitionKeyHash; + return new PartitionKeyHash(partitionKeyHashValues.ToArray()); } private static CosmosObject ConvertRecordToCosmosElement(Record record) @@ -1196,9 +1261,16 @@ private static bool IsRecordWithinFeedRange( { if (feedRange is FeedRangePartitionKey feedRangePartitionKey) { - CosmosElement partitionKey = GetPartitionKeyFromObjectModel(feedRangePartitionKey.PartitionKey); - CosmosElement partitionKeyFromRecord = GetPartitionKeyFromPayload(record.Payload, partitionKeyDefinition); - return partitionKey.Equals(partitionKeyFromRecord); + IList partitionKey = GetPartitionKeysFromObjectModel(feedRangePartitionKey.PartitionKey); + IList partitionKeyFromRecord = GetPartitionKeysFromPayload(record.Payload, partitionKeyDefinition); + if (partitionKeyDefinition.Kind == PartitionKind.MultiHash) + { + PartitionKeyHash partitionKeyHash = GetHashFromPartitionKeys(partitionKey, partitionKeyDefinition); + PartitionKeyHash partitionKeyFromRecordHash = GetHashFromPartitionKeys(partitionKeyFromRecord, partitionKeyDefinition); + + return partitionKeyHash.Equals(partitionKeyFromRecordHash) || partitionKeyFromRecordHash.Value.StartsWith(partitionKeyHash.Value); + } + return partitionKey.SequenceEqual(partitionKeyFromRecord); } else if (feedRange is FeedRangeEpk feedRangeEpk) { @@ -1301,6 +1373,32 @@ private static FeedRangeEpk HashRangeToFeedRangeEpk(PartitionKeyHashRange hashRa isMaxInclusive: false)); } + private PartitionKeyHash ComputeMedianSplitPointAmongDocumentsInPKRange(PartitionKeyHashRange hashRange) + { + if (!this.partitionedRecords.TryGetValue(hashRange, out Records parentRecords)) + { + throw new InvalidOperationException("failed to find the range."); + } + + List partitionKeyHashes = new List(); + foreach (Record record in parentRecords) + { + PartitionKeyHash partitionKeyHash = GetHashFromPayload(record.Payload, this.partitionKeyDefinition); + partitionKeyHashes.Add(partitionKeyHash); + } + + partitionKeyHashes.Sort(); + PartitionKeyHash medianPkHash = partitionKeyHashes[partitionKeyHashes.Count / 2]; + + // For MultiHash Collection, split at top level to ensure documents for top level key exist across partitions + // after split + if (medianPkHash.HashValues.Count > 1) + { + return new PartitionKeyHash(medianPkHash.HashValues[0]); + } + + return medianPkHash; + } public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) { return Task.FromResult(TryCatch.FromResult("AYIMAMmFOw8YAAAAAAAAAA==")); @@ -1516,4 +1614,4 @@ public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) } } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 5c0e66f1a6..cc4a2c7718 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -1003,9 +1003,16 @@ public override Task ForceRefreshCollectionCacheAsync(string collectionLink, Can public override Task GetCachedContainerQueryPropertiesAsync(string containerLink, Cosmos.PartitionKey? partitionKey, ITrace trace, CancellationToken cancellationToken) { - return Task.FromResult(new ContainerQueryProperties( + return Task.FromResult(new ContainerQueryProperties( "test", - WFConstants.BackendHeaders.EffectivePartitionKeyString, + new List> + { + new Range( + PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, + PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey, + true, + true) + }, new PartitionKeyDefinition(), Cosmos.GeospatialType.Geometry)); } @@ -1015,17 +1022,7 @@ public override Task> GetTargetPartitionKeyRangeByFeedRa throw new NotImplementedException(); } - public override Task> GetTargetPartitionKeyRangesAsync(string resourceLink, string collectionResourceId, List> providedRanges, bool forceRefresh, ITrace trace) - { - return Task.FromResult(new List{new PartitionKeyRange() - { - MinInclusive = PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, - MaxExclusive = PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey - } - }); - } - - public override Task> GetTargetPartitionKeyRangesByEpkStringAsync(string resourceLink, string collectionResourceId, string effectivePartitionKeyString, bool forceRefresh, ITrace trace) + public override Task> GetTargetPartitionKeyRangesAsync(string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) { return Task.FromResult(new List{new PartitionKeyRange() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SplitPartitionQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SplitPartitionQueryTests.cs new file mode 100644 index 0000000000..4dd4ed1bd8 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/SplitPartitionQueryTests.cs @@ -0,0 +1,77 @@ +namespace Microsoft.Azure.Cosmos.Tests.Query +{ + using System; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.Tests.Pagination; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.Query.Core.Monads; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + + [TestClass] + public class SplitPartitionQueryTests + { + [TestMethod] + public async Task PrefixPartitionKeyQueryOnSplitParitionTest() + { + int numItems = 500; + IDocumentContainer documentContainer = await CreateSplitDocumentContainerAsync(numItems); + + string query = "SELECT * FROM c"; + for(int i = 0; i < 5; i++) + { + Cosmos.PartitionKey partitionKey = new PartitionKeyBuilder() + .Add(i.ToString()) + .Build(); + + QueryPage queryPage = await documentContainer.QueryAsync( + sqlQuerySpec: new Cosmos.Query.Core.SqlQuerySpec(query), + feedRangeState: new FeedRangeState(new FeedRangePartitionKey(partitionKey), state: null), + queryPaginationOptions: new QueryPaginationOptions(pageSizeHint: int.MaxValue), + trace: NoOpTrace.Singleton, + cancellationToken: default); + + Assert.AreEqual(numItems / 5, queryPage.Documents.Count); + } + } + + private static async Task CreateSplitDocumentContainerAsync(int numItems) + { + PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition() + { + Paths = new System.Collections.ObjectModel.Collection() + { + "/id", + "/value1", + "/value2" + }, + Kind = PartitionKind.MultiHash, + Version = PartitionKeyDefinitionVersion.V2, + }; + + IMonadicDocumentContainer monadicDocumentContainer = new InMemoryContainer(partitionKeyDefinition); + DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); + + for (int i = 0; i < numItems; i++) + { + // Insert an item + CosmosObject item = CosmosObject.Parse($"{{\"id\" : \"{i%5}\", \"value1\" : \"{Guid.NewGuid()}\", \"value2\" : \"{i}\" }}"); + while (true) + { + TryCatch monadicCreateRecord = await documentContainer.MonadicCreateItemAsync(item, cancellationToken: default); + if (monadicCreateRecord.Succeeded) + { + break; + } + } + } + + await documentContainer.SplitAsync(FeedRangeEpk.FullRange, cancellationToken: default); + + return documentContainer; + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashBaselineTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashBaselineTest.cs index 4fb7b5b53f..f60d0849ca 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashBaselineTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashBaselineTest.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Tests.Routing { using System; using System.Collections.Generic; + using System.Linq; using System.Numerics; using System.Xml; using Microsoft.Azure.Cosmos.CosmosElements; @@ -126,6 +127,37 @@ public void Numbers() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void Lists() + { + List inputs = new List() + { + new Input( + description: "1 Path List", + partitionKeyValue: CosmosArray.Create(new List() + { + CosmosString.Create("/path1") + })), + new Input( + description: "2 Path List", + partitionKeyValue: CosmosArray.Create(new List() + { + CosmosString.Create("/path1"), + CosmosString.Create("/path2") + })), + new Input( + description: "3 Path List", + partitionKeyValue: CosmosArray.Create(new List() + { + CosmosString.Create("/path1"), + CosmosString.Create("/path2"), + CosmosString.Create("/path3") + })), + }; + + this.ExecuteTestSuite(inputs); + } + public override Output ExecuteTest(Input input) { CosmosElement value = input.PartitionKeyValue; @@ -159,7 +191,38 @@ public override Output ExecuteTest(Input input) partitionKeyHashV1 = PartitionKeyHash.V1.Hash(Number64.ToDouble(cosmosNumber.Value)); partitionKeyHashV2 = PartitionKeyHash.V2.Hash(Number64.ToDouble(cosmosNumber.Value)); break; + case CosmosArray cosmosArray: + IList partitionKeyHashValuesV1 = new List(); + IList partitionKeyHashValuesV2 = new List(); + foreach (CosmosElement element in cosmosArray) + { + PartitionKeyHash elementHashV1 = element switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V1.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V1.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V1.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V1.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValuesV1.Add(elementHashV1.HashValues[0]); + + PartitionKeyHash elementHashV2 = element switch + { + null => PartitionKeyHash.V2.HashUndefined(), + CosmosString stringPartitionKey => PartitionKeyHash.V2.Hash(stringPartitionKey.Value), + CosmosNumber numberPartitionKey => PartitionKeyHash.V2.Hash(Number64.ToDouble(numberPartitionKey.Value)), + CosmosBoolean cosmosBoolean => PartitionKeyHash.V2.Hash(cosmosBoolean.Value), + CosmosNull _ => PartitionKeyHash.V2.HashNull(), + _ => throw new ArgumentOutOfRangeException(), + }; + partitionKeyHashValuesV2.Add(elementHashV2.HashValues[0]); + } + + partitionKeyHashV1 = new PartitionKeyHash(partitionKeyHashValuesV1.ToArray()); + partitionKeyHashV2 = new PartitionKeyHash(partitionKeyHashValuesV2.ToArray()); + break; default: throw new ArgumentOutOfRangeException($"Unknown {nameof(CosmosElement)} type: {value.GetType()}."); } diff --git a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRangeSplitterAndMerger.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashRangeSplitterAndMerger.cs similarity index 73% rename from Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRangeSplitterAndMerger.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashRangeSplitterAndMerger.cs index 54b72ae3a2..af005b1515 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/PartitionKeyHashRangeSplitterAndMerger.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/PartitionKeyHashRangeSplitterAndMerger.cs @@ -39,8 +39,8 @@ public static SplitOutcome TrySplitRange(PartitionKeyHashRange partitionKeyHashR return SplitOutcome.NumRangesNeedsToBeGreaterThanZero; } - UInt128 actualEnd = partitionKeyHashRange.EndExclusive.HasValue ? partitionKeyHashRange.EndExclusive.Value.Value : UInt128.MaxValue; - UInt128 actualStart = partitionKeyHashRange.StartInclusive.HasValue ? partitionKeyHashRange.StartInclusive.Value.Value : UInt128.MinValue; + UInt128 actualEnd = partitionKeyHashRange.EndExclusive.HasValue ? partitionKeyHashRange.EndExclusive.Value.HashValues[0] : UInt128.MaxValue; + UInt128 actualStart = partitionKeyHashRange.StartInclusive.HasValue ? partitionKeyHashRange.StartInclusive.Value.HashValues[0] : UInt128.MinValue; UInt128 rangeLength = actualEnd - actualStart; if (rangeLength < rangeCount) { @@ -67,7 +67,7 @@ public static SplitOutcome TrySplitRange(PartitionKeyHashRange partitionKeyHashR for (int i = 1; i < rangeCount - 1; i++) { PartitionKeyHash start = new PartitionKeyHash(actualStart + (childRangeLength * i)); - PartitionKeyHash end = new PartitionKeyHash(start.Value + childRangeLength); + PartitionKeyHash end = new PartitionKeyHash(start.HashValues[0] + childRangeLength); childRanges.Add(new PartitionKeyHashRange(start, end)); } @@ -82,6 +82,39 @@ public static SplitOutcome TrySplitRange(PartitionKeyHashRange partitionKeyHashR return SplitOutcome.Success; } + public static PartitionKeyHashRanges SplitRange(PartitionKeyHashRange partitionKeyHashRange, PartitionKeyHash explicitSplitPoint) + { + SplitOutcome splitOutcome = PartitionKeyHashRangeSplitterAndMerger.TrySplitRange( + partitionKeyHashRange, + explicitSplitPoint, + out PartitionKeyHashRanges splitRanges); + + return splitOutcome switch + { + SplitOutcome.Success => splitRanges, + _ => throw new RangeSplitException($"Splitting range failed because {splitOutcome}"), + }; + } + + public static SplitOutcome TrySplitRange(PartitionKeyHashRange partitionKeyHashRange, PartitionKeyHash explicitSplitPoint, out PartitionKeyHashRanges splitRanges) + { + if (explicitSplitPoint < (partitionKeyHashRange.StartInclusive != null ? partitionKeyHashRange.StartInclusive : PartitionKeyHash.None) || + explicitSplitPoint > partitionKeyHashRange.EndExclusive) + { + splitRanges = default; + return SplitOutcome.RangeNotWideEnough; + } + + IList childRanges = new List + { + new PartitionKeyHashRange(partitionKeyHashRange.StartInclusive, explicitSplitPoint), + new PartitionKeyHashRange(explicitSplitPoint, partitionKeyHashRange.EndExclusive) + }; + + splitRanges = PartitionKeyHashRanges.Create(childRanges); + return SplitOutcome.Success; + } + public static PartitionKeyHashRange MergeRanges(PartitionKeyHashRanges partitionedSortedEffectiveRanges) { if (partitionedSortedEffectiveRanges == null) @@ -111,7 +144,13 @@ private sealed class V2 : PartitionKeyHashRangeSplitterAndMerger public override PartitionKeyHashRange FullRange => PartitionKeyHashRangeSplitterAndMerger.V2.fullRange; } - + private sealed class RangeSplitException : Exception + { + public RangeSplitException(string message) + : base(message) + { + } + } public enum SplitOutcome { Success, @@ -119,4 +158,4 @@ public enum SplitOutcome RangeNotWideEnough, } } -} +} \ No newline at end of file From 0a0e5ae69dc942d1625d3454a8d51467493d9e96 Mon Sep 17 00:00:00 2001 From: leminh98 Date: Thu, 14 Sep 2023 23:51:18 -0700 Subject: [PATCH 190/337] [Internal] Query: Fixes LINQ Test Organization (#4076) * preliminary change * Add some more boiler plate code * move all linq test to the same folder; add some groupBy test * fix references error in test refactoring add code for group by substitution. Still need to adjust binding post groupby * preliminary for the groupby functions with key and value selector * trying to change collection inputs for group by * Undo the LINQ GROUP BY part * fix accidental changes --------- Co-authored-by: Minh Le --- .../LinqAggregateFunctionsBaselineTests.cs | 8 +- .../LinqAttributeContractBaselineTests.cs | 0 .../LinqConstantFoldingBaselineTests.cs | 0 .../{ => Linq}/LinqGeneralBaselineTests.cs | 85 ++++++++++--------- .../LinqSQLTranslationBaselineTests.cs | 20 +++-- .../{ => Linq}/LinqTestData.cs | 2 +- .../{ => Linq}/LinqTestsCommon.cs | 0 .../LinqTranslationBaselineTests.cs | 9 +- 8 files changed, 63 insertions(+), 61 deletions(-) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqAggregateFunctionsBaselineTests.cs (98%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqAttributeContractBaselineTests.cs (100%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqConstantFoldingBaselineTests.cs (100%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqGeneralBaselineTests.cs (98%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqSQLTranslationBaselineTests.cs (96%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqTestData.cs (98%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqTestsCommon.cs (100%) rename Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/{ => Linq}/LinqTranslationBaselineTests.cs (99%) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAggregateFunctionsBaselineTests.cs similarity index 98% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAggregateFunctionsBaselineTests.cs index 0734f4dfad..b957b0a740 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAggregateFunctionsBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAggregateFunctionsBaselineTests.cs @@ -38,7 +38,7 @@ public async static Task Initialize(TestContext textContext) // Set a callback to get the handle of the last executed query to do the verification // This is neede because aggregate queries return type is a scalar so it can't be used // to verify the translated LINQ directly as other queries type. - client.DocumentClient.OnExecuteScalarQueryCallback = q => LinqAggregateFunctionBaselineTests.lastExecutedScalarQuery = q; + client.DocumentClient.OnExecuteScalarQueryCallback = q => lastExecutedScalarQuery = q; string dbName = $"{nameof(LinqAggregateFunctionBaselineTests)}-{Guid.NewGuid().ToString("N")}"; testDb = await client.CreateDatabaseAsync(dbName); @@ -501,7 +501,7 @@ public void TestAggregateAvg() public override LinqAggregateOutput ExecuteTest(LinqAggregateInput input) { - LinqAggregateFunctionBaselineTests.lastExecutedScalarQuery = null; + lastExecutedScalarQuery = null; Func compiledQuery = input.expression.Compile(); string errorMessage = null; @@ -515,10 +515,10 @@ public override LinqAggregateOutput ExecuteTest(LinqAggregateInput input) } finally { - Assert.IsNotNull(LinqAggregateFunctionBaselineTests.lastExecutedScalarQuery, "lastExecutedScalarQuery is not set"); + Assert.IsNotNull(lastExecutedScalarQuery, "lastExecutedScalarQuery is not set"); query = JObject - .Parse(LinqAggregateFunctionBaselineTests.lastExecutedScalarQuery.ToString()) + .Parse(lastExecutedScalarQuery.ToString()) .GetValue("query", StringComparison.Ordinal) .ToString(); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs similarity index 100% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqAttributeContractBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqConstantFoldingBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqConstantFoldingBaselineTests.cs similarity index 100% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqConstantFoldingBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqConstantFoldingBaselineTests.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs similarity index 98% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs index 3fc3aff900..e76b2827be 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqGeneralBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqGeneralBaselineTests.cs @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using BaselineTest; using Microsoft.Azure.Documents; using Microsoft.Azure.Cosmos.Scripts; + using static Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests.LinqGeneralBaselineTests; [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] public class LinqGeneralBaselineTests : BaselineTests @@ -242,19 +243,19 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "Select(OrderBy)", b => getQuery(b) .Select(f => f.Children.OrderBy(c => c.Pets.Count())))); - + inputs.Add(new LinqTestInput( "Select(Take)", b => getQuery(b) .Select(f => f.Children.Take(2)))); - + inputs.Add(new LinqTestInput( "Select(Where)", b => getQuery(b) .Select(f => f.Children.Where(c => c.Pets.Count() > 0)))); - + inputs.Add(new LinqTestInput( "Select(Distinct)", b => getQuery(b) .Select(f => f.Children.Distinct()))); - + inputs.Add(new LinqTestInput( "Select(Count)", b => getQuery(b) .Select(f => f.Children.Count(c => c.Grade > 80)))); @@ -378,7 +379,7 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "Select(binary with Count)", b => getQuery(b) .Select(f => 5 + f.Children.Count(c => c.Pets.Count() > 0)))); - + inputs.Add(new LinqTestInput( "Select(constant + Where -> Count)", b => getQuery(b) .Select(f => 5 + f.Children.Where(c => c.Pets.Count() > 0).Count()))); @@ -473,7 +474,7 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "Select(Select) -> Where", b => getQuery(b).Select(f => f.Children.Select(c => c.Pets.Count())).Where(x => x.Count() > 0))); - + // Customer requested scenario inputs.Add(new LinqTestInput( "Select(new w/ Where) -> Where -> OrderBy -> Take", b => getQuery(b) @@ -631,7 +632,7 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "Take -> Select(Select)", b => getQuery(b) .Take(10).Select(f => f.Children.Select(c => c.Pets.Count())))); - + // ------------------ // Any in lambda // ------------------ @@ -639,23 +640,23 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "Select(Any w const array)", b => getQuery(b) .Select(f => new int[] { 1, 2, 3 }.Any()))); - + inputs.Add(new LinqTestInput( "Select(Any)", b => getQuery(b) .Select(f => f.Children.Any()))); - + inputs.Add(new LinqTestInput( "Select(Any w lambda)", b => getQuery(b) .Select(f => f.Children.Any(c => c.Grade > 80)))); - + inputs.Add(new LinqTestInput( "Select(new Any)", b => getQuery(b) .Select(f => new { f.FamilyId, HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - + inputs.Add(new LinqTestInput( "Select(new 2 Any)", b => getQuery(b) .Select(f => new { HasChildrenWithPets = f.Children.Any(c => c.Pets.Count() > 0), HasGoodChildren = f.Children.Any(c => c.Grade > 80) }))); - + inputs.Add(new LinqTestInput( "Select(Nested Any)", b => getQuery(b) .Select(f => f.Children.Any(c => c.Pets.Any(p => p.GivenName.Count() > 10))))); @@ -672,7 +673,7 @@ public void TestSubquery() inputs.Add(new LinqTestInput( "OrderBy(Any)", b => getQuery(b) .OrderBy(f => f.Children.Any(c => c.Pets.Count() > 3)))); - + // ------------------------------------------------ // SelectMany with Take and OrderBy in lambda // ------------------------------------------------ @@ -700,7 +701,7 @@ public void TestSubquery() [Ignore] public void DebuggingTest() { - + } [TestMethod] @@ -1929,7 +1930,7 @@ public void ValidateDynamicLinq() [TestMethod] public async Task ValidateLinqQueries() { - Container container = await testDb.CreateContainerAsync(new ContainerProperties (id : Guid.NewGuid().ToString("N"), partitionKeyPath : "/id" )); + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: Guid.NewGuid().ToString("N"), partitionKeyPath: "/id")); Parent mother = new Parent { FamilyName = "Wakefield", GivenName = "Robin" }; Parent father = new Parent { FamilyName = "Miller", GivenName = "Ben" }; @@ -1945,13 +1946,13 @@ public async Task ValidateLinqQueries() }; Address address = new Address { State = "NY", County = "Manhattan", City = "NY" }; - Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5 , Id = "WakefieldFamily"}; + Family family = new Family { FamilyId = "WakefieldFamily", Parents = new Parent[] { mother, father }, Children = new Child[] { child }, IsRegistered = false, Int = 3, NullableInt = 5, Id = "WakefieldFamily" }; List fList = new List(); fList.Add(family); container.CreateItemAsync(family).Wait(); - IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable query = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); IEnumerable q1 = query.Select(f => f.Parents[0].FamilyName); Assert.AreEqual(q1.FirstOrDefault(), family.Parents[0].FamilyName); @@ -2009,7 +2010,7 @@ public async Task ValidateLinqQueries() ListArrayClass arrayObject = new ListArrayClass() { Id = "arrayObject", ArrayField = new int[] { 1, 2, 3 } }; container.CreateItemAsync(arrayObject).Wait(); - IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable listArrayQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); IEnumerable q13 = listArrayQuery.Where(a => a.ArrayField == arrayObject.ArrayField); Assert.AreEqual(q13.FirstOrDefault().Id, arrayObject.Id); @@ -2061,9 +2062,9 @@ public async Task ValidateLinqQueries() Document doubleQoutesDocument = new Document() { Id = doc1Id }; container.CreateItemAsync(doubleQoutesDocument).Wait(); - IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution : true) - where book.Id == doc1Id - select book; + IQueryable docQuery = from book in container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) + where book.Id == doc1Id + select book; Assert.AreEqual(docQuery.AsEnumerable().Single().Id, doc1Id); @@ -2072,7 +2073,7 @@ public async Task ValidateLinqQueries() container.CreateItemAsync(greatGreatFamily).Wait(); List greatGreatFamilyData = new List() { greatGreatFamily }; - IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable queryable = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); IEnumerable q16 = queryable.SelectMany(gf => gf.GreatFamily.Family.Children.Where(c => c.GivenName == "Jesse").Select(c => gf)); @@ -2082,7 +2083,7 @@ public async Task ValidateLinqQueries() container.CreateItemAsync(sport).Wait(); List sportData = new List() { sport }; - IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable sportQuery = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); IEnumerable q17 = sportQuery.Where(s => s.SportName == "Tennis"); @@ -2178,8 +2179,8 @@ private async Task ValidateBasicQueryAsync() List queryResults = new List(); //Simple Equality IQueryable dbQuery = from db in client.CreateDatabaseQuery() - where db.Id == databaseName - select db; + where db.Id == databaseName + select db; IDocumentQuery documentQuery = dbQuery.AsDocumentQuery(); while (documentQuery.HasMoreResults) @@ -2288,32 +2289,32 @@ public void ValidateDynamicDocumentQuery() //Ensure query on custom property of }; //Unfiltered execution. - IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable bookDocQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); Func> getBookQuery = useQuery => useQuery ? bookDocQuery : new List().AsQueryable(); List inputs = new List(); inputs.Add(new LinqTestInput("Simple Equality on custom property", b => from book in getBookQuery(b) - where book.Title == "My Book" - select book)); + where book.Title == "My Book" + select book)); inputs.Add(new LinqTestInput("Nested Property access", b => from book in getBookQuery(b) - where book.Author.Name == "Don" - select book)); + where book.Author.Name == "Don" + select book)); inputs.Add(new LinqTestInput("Array references & Project Author out..", b => from book in getBookQuery(b) - where book.Languages[0].Name == "English" - select book.Author)); + where book.Languages[0].Name == "English" + select book.Author)); inputs.Add(new LinqTestInput("SelectMany", b => getBookQuery(b).SelectMany(book => book.Languages).Where(lang => lang.Name == "French").Select(lang => lang.Copyright))); inputs.Add(new LinqTestInput("NumericRange query", b => from book in getBookQuery(b) - where book.Price < 10 - select book.Author)); + where book.Price < 10 + select book.Author)); inputs.Add(new LinqTestInput("Or query", b => from book in getBookQuery(b) - where book.Title == "My Book" || book.Author.Name == "Don" - select book)); + where book.Title == "My Book" || book.Author.Name == "Don" + select book)); inputs.Add(new LinqTestInput("SelectMany query on a List type.", b => getBookQuery(b).SelectMany(book => book.Editions).Select(ed => ed.Name))); // Below samples are strictly speaking not Any equivalent. But they join and filter "all" @@ -2334,7 +2335,7 @@ where book.Price < 10 [TestMethod] public void ValidateDynamicAttachmentQuery() //Ensure query on custom property of attachment. { - IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable attachmentQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); Document myDocument = new Document(); Func> getAttachmentQuery = useQuery => useQuery ? attachmentQuery : new List().AsQueryable(); @@ -2401,7 +2402,7 @@ public QueryHelper(Container container) public IQueryable Query() where T : BaseDocument { - IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution : true) + IQueryable query = this.container.GetItemLinqQueryable(allowSynchronousQueryExecution: true) .Where(d => d.TypeName == "Hello"); string queryString = query.ToString(); return query; @@ -2411,7 +2412,7 @@ public IQueryable Query() where T : BaseDocument [TestMethod] public async Task ValidateLinqOnDataDocumentType() { - Container container = await testDb.CreateContainerAsync(new ContainerProperties(id : nameof(ValidateLinqOnDataDocumentType), partitionKeyPath : "/id")); + Container container = await testDb.CreateContainerAsync(new ContainerProperties(id: nameof(ValidateLinqOnDataDocumentType), partitionKeyPath: "/id")); DataDocument doc = new DataDocument() { Id = Guid.NewGuid().ToString("N"), Number = 0, TypeName = "Hello" }; container.CreateItemAsync(doc).Wait(); @@ -2424,10 +2425,10 @@ public async Task ValidateLinqOnDataDocumentType() Assert.AreEqual(doc.Id, baseDocument.Id); BaseDocument iDocument = doc; - IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable q = container.GetItemLinqQueryable(allowSynchronousQueryExecution: true); IEnumerable iresult = from f in q - where f.Id == iDocument.Id + where f.Id == iDocument.Id select f; DataDocument id = iresult.FirstOrDefault(); Assert.AreEqual(doc.Id, id.Id); @@ -2504,7 +2505,7 @@ function callback(err, docCreated) { StoredProcedureExecuteResponse scriptResponse = null; int totalNumberOfDocuments = GatewayTests.CreateExecuteAndDeleteCosmosProcedure(collection, script, out scriptResponse, "My Book"); - IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution : true); + IOrderedQueryable linqQueryable = collection.GetItemLinqQueryable(allowSynchronousQueryExecution: true); int totalHit = linqQueryable.Where(book => book.Title == "My Book").Count(); Assert.AreEqual(totalHit, totalNumberOfDocuments, "Didnt get all the documents"); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqSQLTranslationBaselineTests.cs similarity index 96% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqSQLTranslationBaselineTests.cs index 230e2599a3..d38cede2b3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqSQLTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqSQLTranslationBaselineTests.cs @@ -16,6 +16,7 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests using System.Threading.Tasks; using System.Net; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests; [Microsoft.Azure.Cosmos.SDK.EmulatorTests.TestClass] public class LinqSQLTranslationBaselineTest : BaselineTests @@ -32,7 +33,8 @@ static Expression Lambda(Expression> func) [ClassInitialize] public async static Task Initialize(TestContext textContext) { - cosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) => { + cosmosClient = TestCommon.CreateCosmosClient((cosmosClientBuilder) => + { cosmosClientBuilder.WithCustomSerializer(new CustomJsonSerializer(new JsonSerializerSettings() { ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, @@ -76,7 +78,7 @@ struct simple public string pk; public simple(int x, int y) - { this.x = x; this.y = y; this.id = Guid.NewGuid().ToString(); this.pk = "Test"; } + { this.x = x; this.y = y; this.id = Guid.NewGuid().ToString(); this.pk = "Test"; } } struct nested @@ -246,13 +248,13 @@ public void ValidateSQLTranslation() inputs.Add(new LinqTestInput("Select identity", b => dataQuery(b).Select(x => x))); inputs.Add(new LinqTestInput("Select simple property", b => dataQuery(b).Select(x => x.x))); inputs.Add(new LinqTestInput("Select extension data", b => dataQuery(b).Select(x => new complex() { - NewtonsoftExtensionData = new() { + NewtonsoftExtensionData = new() { { "test", 1.5 } }, - NetExtensionData = new() { + NetExtensionData = new() { { "OtherTest", 1.5 } } - } ))); + }))); this.ExecuteTestSuite(inputs); } @@ -280,9 +282,9 @@ public void ValidateSQLTranslationComplexData() obj.str = random.NextDouble() < 0.1 ? "5" : LinqTestsCommon.RandomString(random, random.Next(MaxStringLength)); obj.id = Guid.NewGuid().ToString(); obj.pk = "Test"; - obj.NewtonsoftExtensionData = new Dictionary() { + obj.NewtonsoftExtensionData = new Dictionary() { ["age"] = 32, - ["tags"] = new [] { "item-1", "item-2" } + ["tags"] = new[] { "item-1", "item-2" } }; return obj; }; @@ -307,11 +309,11 @@ public void ValidateSQLTranslationComplexData() inputs.Add(new LinqTestInput("SelectMany array", b => getQuery(b).SelectMany(x => x.dblArray))); inputs.Add(new LinqTestInput("Select where extensiondata", b => getQuery(b).Where(p => (int)p.NewtonsoftExtensionData["age"] > 18).Select(x => new { Age = (int)x.NewtonsoftExtensionData["age"] }))); - inputs.Add(new LinqTestInput("Select where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).Select(x => (string[])x.NewtonsoftExtensionData["tags"] ))); + inputs.Add(new LinqTestInput("Select where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).Select(x => (string[])x.NewtonsoftExtensionData["tags"]))); // TODO: SelectMany does not currently work with Dictionary objects, the snapshot represents // the current (broken) behavior - inputs.Add(new LinqTestInput("SelectMany where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).SelectMany(x => (object[])x.NewtonsoftExtensionData["tags"] ))); + inputs.Add(new LinqTestInput("SelectMany where extensiondata contains", b => getQuery(b).Where(p => ((string[])p.NewtonsoftExtensionData["tags"]).Contains("item-1")).SelectMany(x => (object[])x.NewtonsoftExtensionData["tags"]))); this.ExecuteTestSuite(inputs); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestData.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs similarity index 98% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestData.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs index f302655613..a543a00418 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestData.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestData.cs @@ -71,7 +71,7 @@ public class Transaction : LinqTestObject { public DateTime Date; public long Amount; - public TransactionType Type; + public TransactionType Type; } public enum TransactionType diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs similarity index 100% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTestsCommon.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTestsCommon.cs diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs similarity index 99% rename from Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs rename to Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs index 4c8d6c423f..d6e4ee4767 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/LinqTranslationBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqTranslationBaselineTests.cs @@ -17,7 +17,6 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using BaselineTest; using System.Linq.Dynamic; using System.Text; - using Microsoft.Azure.Documents; using Microsoft.Azure.Cosmos.SDK.EmulatorTests; using System.Threading.Tasks; @@ -622,7 +621,7 @@ public void TestMemberAccess() List testData = new List(); IOrderedQueryable constantQuery = testContainer.GetItemLinqQueryable(allowSynchronousQueryExecution: true); Func> getQuery = useQuery => useQuery ? constantQuery : testData.AsQueryable(); - + List inputs = new List { // This test case will use the legacy delegate compilation expression evaluator @@ -683,7 +682,7 @@ private Func> CreateDataTestStringFunctions() StringField = sb.ToString(), Id = Guid.NewGuid().ToString(), Pk = "Test", - + // For ToString tests ArrayField = new int[] {}, Point = new Point(0, 0) @@ -805,9 +804,9 @@ public void TestStringFunctions() new LinqTestInput("ToUpper", b => getQuery(b).Select(doc => doc.StringField.ToUpper())) }; this.ExecuteTestSuite(inputs); - } + } - [TestMethod] + [TestMethod] public void TestArrayFunctions() { const int Records = 100; From 52d04361049a41e9d66d811bba5a3206792fb4cf Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Fri, 15 Sep 2023 21:07:47 +0530 Subject: [PATCH 191/337] ClientTelemetry : Adds logic to call client config in every 10 minutes (#4071) * first draft * fix tests * fixes * fix tests * remove consoles * added exception * remove comment * fix tests * fix test * rev comments * rev comments * refactor code * remove log from api exception --- .../src/Handler/DiagnosticsHandlerHelper.cs | 35 ++- .../src/Telemetry/TelemetryToServiceHelper.cs | 90 ++++-- .../ClientTelemetryConfigurationTest.cs | 265 ++++++++++++++++++ .../DiagnosticHandlerHelperTests.cs | 29 +- 4 files changed, 385 insertions(+), 34 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs diff --git a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs index cdc3c2bac3..266524e38b 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/DiagnosticsHandlerHelper.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Handler { using System; using System.Collections.Generic; + using System.Threading.Tasks; using Documents.Rntbd; using Microsoft.Azure.Cosmos.Core.Trace; @@ -21,16 +22,14 @@ internal class DiagnosticsHandlerHelper private const string Telemetrykey = "telemetry"; public static readonly TimeSpan DiagnosticsRefreshInterval = TimeSpan.FromSeconds(10); - private static readonly SystemUsageRecorder DiagnosticSystemUsageRecorder = new SystemUsageRecorder( + private static readonly TimeSpan ClientTelemetryRefreshInterval = TimeSpan.FromSeconds(5); + + // Need to reset it in Tests hence kept it non-readonly. + private static SystemUsageRecorder DiagnosticSystemUsageRecorder = new SystemUsageRecorder( identifier: Diagnostickey, historyLength: 6, refreshInterval: DiagnosticsHandlerHelper.DiagnosticsRefreshInterval); - - private static readonly TimeSpan ClientTelemetryRefreshInterval = TimeSpan.FromSeconds(5); - private static readonly SystemUsageRecorder TelemetrySystemUsageRecorder = new SystemUsageRecorder( - identifier: Telemetrykey, - historyLength: 120, - refreshInterval: DiagnosticsHandlerHelper.ClientTelemetryRefreshInterval); + private static SystemUsageRecorder TelemetrySystemUsageRecorder = null; /// /// Singleton to make sure only one instance of DiagnosticHandlerHelper is there. @@ -62,13 +61,13 @@ public static void Refresh(bool isClientTelemetryEnabled) { if (isClientTelemetryEnabled != DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled) { - DiagnosticsHandlerHelper.Instance.StopSystemMonitor(); + DiagnosticsHandlerHelper tempInstance = DiagnosticsHandlerHelper.Instance; - // Update telemetry flag DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled = isClientTelemetryEnabled; - - // Create new instance, it will start a new system monitor job DiagnosticsHandlerHelper.Instance = new DiagnosticsHandlerHelper(); + + // Stopping the monitor is a blocking call so we do it in a separate thread + _ = Task.Run(() => tempInstance.StopSystemMonitor()); } } @@ -80,7 +79,7 @@ private void StopSystemMonitor() } catch (ObjectDisposedException ex) { - DefaultTrace.TraceError($"Error while stopping system usage monitor. {0} ", ex); + DefaultTrace.TraceError("Error while stopping system usage monitor. {0} ", ex); } } @@ -102,8 +101,18 @@ private DiagnosticsHandlerHelper() if (DiagnosticsHandlerHelper.isTelemetryMonitoringEnabled) { + // re-initialize a fresh telemetry recorder when feature is switched on + DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder = new SystemUsageRecorder( + identifier: Telemetrykey, + historyLength: 120, + refreshInterval: DiagnosticsHandlerHelper.ClientTelemetryRefreshInterval); + recorders.Add(DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder); } + else + { + DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder = null; + } this.systemUsageMonitor = SystemUsageMonitor.CreateAndStart(recorders); @@ -154,7 +163,7 @@ public SystemUsageHistory GetClientTelemetrySystemHistory() try { - return DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder.Data; + return DiagnosticsHandlerHelper.TelemetrySystemUsageRecorder?.Data; } catch (Exception ex) { diff --git a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs index 9212457951..f358076b25 100644 --- a/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs +++ b/Microsoft.Azure.Cosmos/src/Telemetry/TelemetryToServiceHelper.cs @@ -21,7 +21,8 @@ internal class TelemetryToServiceHelper : IDisposable { private ITelemetryCollector collector = new TelemetryCollectorNoOp(); - internal static int DefaultBackgroundRefreshClientConfigTimeIntervalInMS = (int)TimeSpan.FromMinutes(10).TotalMilliseconds; + internal static TimeSpan DefaultBackgroundRefreshClientConfigTimeInterval + = TimeSpan.FromMinutes(10); private readonly AuthorizationTokenProvider cosmosAuthorization; private readonly CosmosHttpClient httpClient; @@ -73,7 +74,13 @@ public static TelemetryToServiceHelper CreateAndInitializeClientConfigAndTelemet } TelemetryToServiceHelper helper = new TelemetryToServiceHelper( - clientId, connectionPolicy, cosmosAuthorization, httpClient, serviceEndpoint, globalEndpointManager, cancellationTokenSource); + clientId: clientId, + connectionPolicy: connectionPolicy, + cosmosAuthorization: cosmosAuthorization, + httpClient: httpClient, + serviceEndpoint: serviceEndpoint, + globalEndpointManager: globalEndpointManager, + cancellationTokenSource: cancellationTokenSource); _ = helper.RetrieveConfigAndInitiateTelemetryAsync(); // Let it run in backgroud @@ -86,20 +93,36 @@ private async Task RetrieveConfigAndInitiateTelemetryAsync() try { Uri serviceEndpointWithPath = new Uri(this.serviceEnpoint + Paths.ClientConfigPathSegment); - - TryCatch databaseAccountClientConfigs = await this.GetDatabaseAccountClientConfigAsync(this.cosmosAuthorization, this.httpClient, serviceEndpointWithPath); - if (databaseAccountClientConfigs.Succeeded) - { - this.InitializeClientTelemetry(databaseAccountClientConfigs.Result); - } - else if (!this.cancellationTokenSource.IsCancellationRequested) + while (!this.cancellationTokenSource.IsCancellationRequested) { - DefaultTrace.TraceWarning($"Exception while calling client config " + databaseAccountClientConfigs.Exception.ToString()); + TryCatch databaseAccountClientConfigs = await this.GetDatabaseAccountClientConfigAsync( + cosmosAuthorization: this.cosmosAuthorization, + httpClient: this.httpClient, + clientConfigEndpoint: serviceEndpointWithPath); + + if (databaseAccountClientConfigs.Succeeded) + { + this.InitializeClientTelemetry( + clientConfig: databaseAccountClientConfigs.Result); + } + else if (databaseAccountClientConfigs.Exception is ObjectDisposedException) + { + DefaultTrace.TraceWarning("Client is being disposed for {0} at {1}", serviceEndpointWithPath, DateTime.UtcNow); + break; + } + else if (!this.cancellationTokenSource.IsCancellationRequested) + { + DefaultTrace.TraceWarning("Exception while calling client config {0} ", databaseAccountClientConfigs.Exception); + } + + await Task.Delay( + delay: TelemetryToServiceHelper.DefaultBackgroundRefreshClientConfigTimeInterval, + cancellationToken: this.cancellationTokenSource.Token); } } catch (Exception ex) { - DefaultTrace.TraceWarning($"Exception while running client config job " + ex.ToString()); + DefaultTrace.TraceWarning("Exception while running client config job: {0}", ex); } } @@ -125,14 +148,25 @@ await cosmosAuthorization.AddAuthorizationHeaderAsync( timeoutPolicy: HttpTimeoutPolicyControlPlaneRead.Instance, clientSideRequestStatistics: null, cancellationToken: default)) - using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage)) { - return TryCatch.FromResult(CosmosResource.FromStream(documentServiceResponse)); + // It means feature flag is off at gateway, then log the exception and retry after defined interval. + // If feature flag is OFF at gateway, SDK won't refresh the latest state of the flag. + if (responseMessage.StatusCode == System.Net.HttpStatusCode.BadRequest) + { + string responseFromGateway = await responseMessage.Content.ReadAsStringAsync(); + return TryCatch.FromException( + new InvalidOperationException($"Client Config API is not enabled at compute gateway. Response is {responseFromGateway}")); + } + + using (DocumentServiceResponse documentServiceResponse = await ClientExtensions.ParseResponseAsync(responseMessage)) + { + return TryCatch.FromResult( + CosmosResource.FromStream(documentServiceResponse)); + } } } catch (Exception ex) { - DefaultTrace.TraceWarning($"Exception while calling client config " + ex.StackTrace); return TryCatch.FromException(ex); } } @@ -153,10 +187,16 @@ public bool IsClientTelemetryJobRunning() /// private void InitializeClientTelemetry(AccountClientConfiguration clientConfig) { + // If state of the job is same as state of the flag, then no need to do anything. + if (clientConfig.IsClientTelemetryEnabled() == this.IsClientTelemetryJobRunning()) + { + return; + } + DiagnosticsHandlerHelper.Refresh(clientConfig.IsClientTelemetryEnabled()); if (clientConfig.IsClientTelemetryEnabled()) - { + { try { this.clientTelemetry = ClientTelemetry.CreateAndStartBackgroundTelemetry( @@ -180,6 +220,11 @@ private void InitializeClientTelemetry(AccountClientConfiguration clientConfig) this.connectionPolicy.EnableClientTelemetry = false; } } + else + { + this.StopClientTelemetry(); + DefaultTrace.TraceVerbose("Client Telemetry Disabled."); + } } public void Dispose() @@ -193,10 +238,19 @@ public void Dispose() /// private void StopClientTelemetry() { - this.collector = new TelemetryCollectorNoOp(); + try + { + this.collector = new TelemetryCollectorNoOp(); + + this.clientTelemetry?.Dispose(); + this.clientTelemetry = null; - this.clientTelemetry?.Dispose(); - this.clientTelemetry = null; + DiagnosticsHandlerHelper.Refresh(isClientTelemetryEnabled: false); + } + catch (Exception ex) + { + DefaultTrace.TraceWarning($"Error While stopping Telemetry Job : {0}", ex); + } } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs new file mode 100644 index 0000000000..57b5357055 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTelemetryConfigurationTest.cs @@ -0,0 +1,265 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests +{ + using System.Net.Http; + using System.Net; + using System.Text; + using System.Threading.Tasks; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using Newtonsoft.Json; + using Microsoft.Azure.Cosmos.Fluent; + using System; + using Microsoft.Azure.Cosmos.Routing; + using System.Reflection; + using System.Threading; + using Microsoft.Azure.Cosmos.Telemetry; + + [TestClass] + public class ClientTelemetryConfigurationTest : BaseCosmosClientHelper + { + private const string EndpointUrl = "http://dummy.test.com/"; + private CosmosClientBuilder cosmosClientBuilder; + + private readonly TimeSpan OriginalDefaultBackgroundRefreshClientConfigTimeInterval = TelemetryToServiceHelper.DefaultBackgroundRefreshClientConfigTimeInterval; + + [TestInitialize] + public void TestInitialize() + { + TelemetryToServiceHelper.DefaultBackgroundRefreshClientConfigTimeInterval + = TimeSpan.FromMilliseconds(100); + + this.cosmosClientBuilder = TestCommon.GetDefaultConfiguration(); + } + + [TestCleanup] + public async Task Cleanup() + { + await base.TestCleanup(); + + // Resetting time intervals + TelemetryToServiceHelper.DefaultBackgroundRefreshClientConfigTimeInterval + = this.OriginalDefaultBackgroundRefreshClientConfigTimeInterval; + } + + [TestMethod] + public async Task Validate_ClientTelemetryJob_Status_if_Disabled_At_Instance_LevelAsync() + { + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(EndpointUrl)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + return Task.FromResult(result); + } + else if (request.RequestUri.AbsoluteUri.Contains(Documents.Paths.ClientConfigPathSegment)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + + AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = true, + Endpoint = EndpointUrl + } + }; + + string payload = JsonConvert.SerializeObject(clientConfigProperties); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + + return Task.FromResult(result); + } + return null; + } + }; + + this.cosmosClientBuilder + .WithHttpClientFactory(() => new HttpClient(httpHandler)) + .WithTelemetryDisabled(); + + this.SetClient(this.cosmosClientBuilder.Build()); + + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); + + DocumentClient documentClient = this.GetClient().DocumentClient; + + Assert.IsNotNull(documentClient.telemetryToServiceHelper); + Assert.IsFalse(documentClient.telemetryToServiceHelper.IsClientTelemetryJobRunning()); + + ClientCollectionCache collCache = (ClientCollectionCache)documentClient + .GetType() + .GetField("collectionCache", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) + .GetValue(documentClient); + + TelemetryToServiceHelper telemetryToServiceHelper = (TelemetryToServiceHelper)collCache + .GetType() + .GetField("telemetryToServiceHelper", BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(collCache); + + Assert.IsNotNull(telemetryToServiceHelper); + Assert.IsFalse(telemetryToServiceHelper.IsClientTelemetryJobRunning()); + } + + [TestMethod] + [DataRow(true, HttpStatusCode.OK)] + [DataRow(false, HttpStatusCode.OK)] + [DataRow(false, HttpStatusCode.BadRequest)] // Errored Client Config API + public async Task Validate_ClientTelemetryJob_Status_with_Client_Config_Api_States_Async(bool clientTelemetryFlagEnabled, HttpStatusCode clientConfigApiStatus) + { + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Equals(EndpointUrl)) + { + HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); + return Task.FromResult(result); + } + else if (request.RequestUri.AbsoluteUri.Contains(Documents.Paths.ClientConfigPathSegment)) + { + HttpResponseMessage result = new HttpResponseMessage(clientConfigApiStatus); + + AccountClientConfiguration clientConfigProperties = new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = clientTelemetryFlagEnabled, + Endpoint = clientTelemetryFlagEnabled ? EndpointUrl : null + } + }; + + string payload = JsonConvert.SerializeObject(clientConfigProperties); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + + return Task.FromResult(result); + } + return null; + } + }; + + this.cosmosClientBuilder + .WithHttpClientFactory(() => new HttpClient(httpHandler)) + .WithTelemetryEnabled(); + + this.SetClient(this.cosmosClientBuilder.Build()); + + this.database = await this.GetClient().CreateDatabaseAsync(Guid.NewGuid().ToString()); + + DocumentClient documentClient = this.GetClient().DocumentClient; + + ClientCollectionCache collCache = (ClientCollectionCache)documentClient + .GetType() + .GetField("collectionCache", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) + .GetValue(documentClient); + + TelemetryToServiceHelper telemetryToServiceHelperFromCollectionCache = (TelemetryToServiceHelper)collCache + .GetType() + .GetField("telemetryToServiceHelper", BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(collCache); + + Assert.AreEqual(clientTelemetryFlagEnabled, documentClient.telemetryToServiceHelper.IsClientTelemetryJobRunning()); + Assert.AreEqual(clientTelemetryFlagEnabled, telemetryToServiceHelperFromCollectionCache.IsClientTelemetryJobRunning()); + } + + [TestMethod] + [DataRow(true, false, HttpStatusCode.OK)] + [DataRow(false, true, HttpStatusCode.OK)] + [DataRow(true, false, HttpStatusCode.BadRequest)] + [DataRow(false, true, HttpStatusCode.BadRequest)] + public async Task Validate_ClientTelemetryJob_When_Flag_Is_Switched(bool flagState1, bool flagState2, HttpStatusCode clientConfigApiStatusAfterSwitch) + { + using ManualResetEvent manualResetEvent = new ManualResetEvent(false); + + int counter = 0; + HttpClientHandlerHelper httpHandler = new HttpClientHandlerHelper + { + RequestCallBack = (request, cancellation) => + { + if (request.RequestUri.AbsoluteUri.Contains(Documents.Paths.ClientConfigPathSegment)) + { + if (counter == 10) + { + manualResetEvent.Set(); + } + + counter++; + + bool isEnabled = counter < 5 ? flagState1 : flagState2; + HttpStatusCode apiStatusCode = counter < 5 ? HttpStatusCode.OK : clientConfigApiStatusAfterSwitch; + + HttpResponseMessage result = new HttpResponseMessage(apiStatusCode); + string payload = JsonConvert.SerializeObject(new AccountClientConfiguration + { + ClientTelemetryConfiguration = new ClientTelemetryConfiguration + { + IsEnabled = isEnabled, + Endpoint = isEnabled ? EndpointUrl : null + } + }); + result.Content = new StringContent(payload, Encoding.UTF8, "application/json"); + + return Task.FromResult(result); + } + + return null; + } + }; + + this.cosmosClientBuilder + .WithHttpClientFactory(() => new HttpClient(httpHandler)) + .WithTelemetryEnabled(); + + this.SetClient(this.cosmosClientBuilder.Build()); + + this.database = await this.GetClient() + .CreateDatabaseAsync(Guid.NewGuid().ToString()); + + DocumentClient documentClient = this.GetClient().DocumentClient; + + ClientCollectionCache collCache = (ClientCollectionCache)documentClient + .GetType() + .GetField("collectionCache", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) + .GetValue(documentClient); + + TelemetryToServiceHelper telemetryToServiceHelperFromCollectionCache + = (TelemetryToServiceHelper)collCache + .GetType() + .GetField("telemetryToServiceHelper", BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(collCache); + + Assert.AreEqual(flagState1, documentClient.telemetryToServiceHelper.IsClientTelemetryJobRunning()); + Assert.AreEqual(flagState1, telemetryToServiceHelperFromCollectionCache.IsClientTelemetryJobRunning()); + + manualResetEvent.WaitOne(TimeSpan.FromSeconds(1)); + + collCache = (ClientCollectionCache)documentClient + .GetType() + .GetField("collectionCache", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static) + .GetValue(documentClient); + + telemetryToServiceHelperFromCollectionCache = (TelemetryToServiceHelper)collCache + .GetType() + .GetField("telemetryToServiceHelper", BindingFlags.Instance | BindingFlags.NonPublic) + .GetValue(collCache); + + if (clientConfigApiStatusAfterSwitch == HttpStatusCode.OK) + { + Assert.AreEqual(flagState2, documentClient.telemetryToServiceHelper.IsClientTelemetryJobRunning()); + Assert.AreEqual(flagState2, telemetryToServiceHelperFromCollectionCache.IsClientTelemetryJobRunning()); + } + else + { + // If the client config api errored out, the flag should not be changed + Assert.AreEqual(flagState1, documentClient.telemetryToServiceHelper.IsClientTelemetryJobRunning()); + Assert.AreEqual(flagState1, telemetryToServiceHelperFromCollectionCache.IsClientTelemetryJobRunning()); + } + + + } + } +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs index 23c813d826..c620b726e7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Diagnostics/DiagnosticHandlerHelperTests.cs @@ -25,11 +25,21 @@ private static void ResetDiagnosticsHandlerHelper() MethodInfo iMethod = helper.GetType().GetMethod("StopSystemMonitor", BindingFlags.NonPublic | BindingFlags.Instance); iMethod.Invoke(helper, new object[] { }); - //Reset the instance woth original value + //Reset the DiagnosticSystemUsageRecorder with original value + FieldInfo DiagnosticSystemUsageRecorderField = typeof(DiagnosticsHandlerHelper).GetField("DiagnosticSystemUsageRecorder", + BindingFlags.Static | + BindingFlags.NonPublic); + DiagnosticSystemUsageRecorderField.SetValue(null, new Documents.Rntbd.SystemUsageRecorder( + identifier: "diagnostic", + historyLength: 6, + refreshInterval: DiagnosticsHandlerHelper.DiagnosticsRefreshInterval)); + + //Reset the instance with original value FieldInfo field = typeof(DiagnosticsHandlerHelper).GetField("Instance", BindingFlags.Static | BindingFlags.NonPublic); field.SetValue(null, Activator.CreateInstance(typeof(DiagnosticsHandlerHelper), true)); + } [TestMethod] @@ -50,14 +60,20 @@ public async Task RefreshTestAsync() DiagnosticsHandlerHelper diagnosticHandlerHelper1 = DiagnosticsHandlerHelper.GetInstance(); await Task.Delay(10000); // warm up Assert.IsNotNull(diagnosticHandlerHelper1.GetDiagnosticsSystemHistory()); + Assert.IsTrue(diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count > 0); int countBeforeRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; + FieldInfo TelemetrySystemUsageRecorderField1 = typeof(DiagnosticsHandlerHelper).GetField("TelemetrySystemUsageRecorder", + BindingFlags.Static | + BindingFlags.NonPublic); + Assert.IsNull(TelemetrySystemUsageRecorderField1.GetValue(null)); + // Refresh instance of DiagnosticsHandlerHelper with client telemetry enabled DiagnosticsHandlerHelper.Refresh(true); + await Task.Delay(5000); // warm up again to populate telemetry data DiagnosticsHandlerHelper diagnosticHandlerHelper2 = DiagnosticsHandlerHelper.GetInstance(); int countAfterRefresh = diagnosticHandlerHelper1.GetDiagnosticsSystemHistory().Values.Count; - - Console.WriteLine(countBeforeRefresh + " " + countAfterRefresh); + Assert.IsTrue(countBeforeRefresh <= countAfterRefresh, "After Refresh count should be greater than or equal to before refresh count"); Assert.AreNotEqual(diagnosticHandlerHelper1, diagnosticHandlerHelper2); @@ -65,11 +81,18 @@ public async Task RefreshTestAsync() Assert.IsNotNull(diagnosticHandlerHelper2.GetDiagnosticsSystemHistory()); Assert.IsNotNull(diagnosticHandlerHelper2.GetClientTelemetrySystemHistory()); + Assert.IsTrue(diagnosticHandlerHelper2.GetClientTelemetrySystemHistory().Values.Count > 0); + // Refresh instance of DiagnosticsHandlerHelper with client telemetry disabled DiagnosticsHandlerHelper.Refresh(false); DiagnosticsHandlerHelper diagnosticHandlerHelper3 = DiagnosticsHandlerHelper.GetInstance(); Assert.IsNotNull(diagnosticHandlerHelper3.GetDiagnosticsSystemHistory()); Assert.IsNull(diagnosticHandlerHelper3.GetClientTelemetrySystemHistory()); + + FieldInfo TelemetrySystemUsageRecorderField3 = typeof(DiagnosticsHandlerHelper).GetField("TelemetrySystemUsageRecorder", + BindingFlags.Static | + BindingFlags.NonPublic); + Assert.IsNull(TelemetrySystemUsageRecorderField3.GetValue(null)); } } } From 83509cc173f01fc7cbf20a0eb8d06da53f5f3b94 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:35:33 -0700 Subject: [PATCH 192/337] SDK 3.35.4: Adds version bump and changelog (#4087) * bump version and changelog * added apis * Update changelog.md --- Directory.Build.props | 4 +- .../contracts/API_3.35.4-preview.txt | 1563 +++++++++++++++++ .../contracts/API_3.35.4.txt | 1502 ++++++++++++++++ changelog.md | 8 +- 4 files changed, 3074 insertions(+), 3 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.4-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.35.4.txt diff --git a/Directory.Build.props b/Directory.Build.props index 044a7ec7d9..404becc428 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.35.3 - 3.35.3 + 3.35.4 + 3.35.4 preview 3.31.4 2.0.3 diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.4-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.4-preview.txt new file mode 100644 index 0000000000..6c989053fd --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.4-preview.txt @@ -0,0 +1,1563 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool IsDistributedTracingEnabled { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithDistributedTracing(bool isEnabled=true); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.35.4.txt b/Microsoft.Azure.Cosmos/contracts/API_3.35.4.txt new file mode 100644 index 0000000000..c0dc3e280f --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.35.4.txt @@ -0,0 +1,1502 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/changelog.md b/changelog.md index 27ec98fae0..d6ca1007c1 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,6 @@ ## Recommended version -The **minimum recommended version is [3.33.0](#3.33.0) when using Direct mode and [3.35.1](#3.35.1) for Gateway mode**. +The **minimum recommended version is [3.35.4](#3.35.4)**. Make sure that your applications, when using the .NET V3 SDK, are using at least the version described here to have all the critical fixes. @@ -13,6 +13,12 @@ Preview features are treated as a separate branch and will not be included in th The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +### [3.35.4-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.4-preview) - 2023-09-15 +### [3.35.4](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.4) - 2023-09-15 + +#### Fixed +- [3934](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/3934) Subpartitioning: Fixes bug for queries on subpartitioned containers with split physical partitions + ### [3.35.3-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3-preview) - 2023-08-10 ### [3.35.3](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.35.3) - 2023-08-10 From 258d960ae3caa3ad989f60d5e656544c35006d0a Mon Sep 17 00:00:00 2001 From: Aditya Date: Mon, 18 Sep 2023 11:56:55 -0700 Subject: [PATCH 193/337] [Internal] Query: Fixes escaped string parsing in SqlParser (#4054) * Initial commit * Addressed comments. --- .../src/Query/Core/Parser/CstToAstVisitor.cs | 42 ++++++++++++++++++- .../BaselineTest/BaselineTests.cs | 4 +- ...onSqlParserBaselineTests.StringLiteral.xml | 38 +++++++++++++++++ .../Microsoft.Azure.Cosmos.Tests.csproj | 3 ++ .../ScalarExpressionSqlParserBaselineTests.cs | 24 +++++++++++ 5 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.StringLiteral.xml diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs index 7ca3a60a71..fd92b233a8 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Parser/CstToAstVisitor.cs @@ -9,6 +9,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.Parser using System.Collections.Immutable; using System.Diagnostics.Contracts; using System.Globalization; + using System.Text; using Antlr4.Runtime.Misc; using Antlr4.Runtime.Tree; using Microsoft.Azure.Cosmos.SqlObjects; @@ -950,8 +951,45 @@ public UnknownSqlObjectException(SqlObject sqlObject, Exception innerException = private static string GetStringValueFromNode(IParseTree parseTree) { string text = parseTree.GetText(); - string textWithoutQuotes = text.Substring(1, text.Length - 2).Replace("\\\"", "\""); - return textWithoutQuotes; + + // 1. Remove leading and trailing (single or double) quotes. + // 2. Unescape following characters: + // \" => " + // \\ => \ + // \/ => / + // Based on the documentation, we should also escape single quote \'. + // https://learn.microsoft.com/en-us/azure/cosmos-db/nosql/query/constants#remarks + // However that's failing in the parser (before reaching this point) and will be fixed separately (after checking server's behavior). + StringBuilder stringBuilder = new StringBuilder(text.Length); + for (int index = 1; index < text.Length - 1; index++) + { + switch (text[index]) + { + case '\\': + if ((index + 1) < (text.Length - 1)) + { + switch (text[index + 1]) + { + case '"': + case '\\': + case '/': + stringBuilder.Append(text[index + 1]); + index++; + break; + default: + stringBuilder.Append(text[index]); + break; + } + } + break; + + default: + stringBuilder.Append(text[index]); + break; + } + } + + return stringBuilder.ToString(); } private static Number64 GetNumber64ValueFromNode(IParseTree parseTree) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/BaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/BaselineTests.cs index 6e2162ee2f..419a29229b 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/BaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/BaselineTests.cs @@ -135,8 +135,8 @@ public void ExecuteTestSuite(IEnumerable inputs, [CallerMemberName] stri Assert.IsTrue( matched, - $@" Baseline File {baselinePath}, - Output File {outputPath}, + $@" Baseline File {Path.GetFullPath(baselinePath)}, + Output File {Path.GetFullPath(outputPath)}, Expected: {baselineTextSuffix}, Actual: {outputTextSuffix}"); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.StringLiteral.xml b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.StringLiteral.xml new file mode 100644 index 0000000000..df9e44ceda --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/BaselineTest/TestBaseline/ScalarExpressionSqlParserBaselineTests.StringLiteral.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index 5b429468d8..88450d8984 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -82,6 +82,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs index 43377f0074..10f6fe3ee0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Parser/ScalarExpressionSqlParserBaselineTests.cs @@ -520,6 +520,30 @@ public void OrderOfOperation() this.ExecuteTestSuite(inputs); } + [TestMethod] + public void StringLiteral() + { + List inputs = new List() + { + // Single quoted string literals do not allow ' even when it's escaped. + // Parser currently fails with Antlr4.Runtime.NoViableAltException + CreateInput( + description: @"Single quoted string literals with escape seqence", + scalarExpression: @"['\""DoubleQuote', '\\ReverseSolidus', '\/solidus', '\bBackspace', '\fSeparatorFeed', '\nLineFeed', '\rCarriageReturn', '\tTab', '\u1234']"), + CreateInput( + description: @"Double quoted string literals with escape seqence", + scalarExpression: @"[""'SingleQuote"", ""\""DoubleQuote"", ""\\ReverseSolidus"", ""\/solidus"", ""\bBackspace"", ""\fSeparatorFeed"", ""\nLineFeed"", ""\rCarriageReturn"", ""\tTab"", ""\u1234""]"), + CreateInput( + description: @"Single quoted string literals special cases", + scalarExpression: @"['\""', '\""\""', '\\', '\\\\', '\/', '\/\/', '\b', '\b\b', '\f', '\f\f', '\n', '\n\n', '\r', '\r\r', '\t', '\t\t', '\u1234', '\u1234\u1234']"), + CreateInput( + description: @"Double quoted string literals special cases", + scalarExpression: @"[""\"""", ""\""\"""", ""\\"", ""\\\\"", ""\/"", ""\/\/"", ""\b"", ""\b\b"", ""\f"", ""\f\f"", ""\n"", ""\n\n"", ""\r"", ""\r\r"", ""\t"", ""\t\t"", ""\u1234"", ""\u1234\u1234""]"), + }; + + this.ExecuteTestSuite(inputs); + } + public static SqlParserBaselineTestInput CreateInput(string description, string scalarExpression) { return new SqlParserBaselineTestInput(description, $"SELECT VALUE {scalarExpression}"); From 373ab9ec9d3576bc4bac491f5fd4fead3767370e Mon Sep 17 00:00:00 2001 From: Sourabh Jain Date: Wed, 20 Sep 2023 20:32:15 +0530 Subject: [PATCH 194/337] Bechmark : Fixes benchmark runs (#4088) * pk to result container * set pk * pk value fix * update run.sh * remove changes value * remove telemetry service end point * cleanup --- .../Tools/Benchmark/BenchmarkProgress.cs | 7 ++++++- .../Tools/Benchmark/Program.cs | 12 +++++++----- .../Tools/Benchmark/README.md | 4 ++-- .../Tools/Benchmark/loop.sh | 1 - .../Tools/Benchmark/run.sh | 18 ++++++------------ 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs index 6a7650a5cd..584f9e7a29 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkProgress.cs @@ -15,13 +15,18 @@ namespace CosmosBenchmark /// public class BenchmarkProgress { - /// /// Record item id /// [JsonProperty] public string id { get; set; } + /// + /// Record item pk + /// + [JsonProperty] + public string pk { get; set; } + /// /// Machine name /// diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs index d1f8677cc6..9bbb33b9fd 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs @@ -177,7 +177,6 @@ private async Task ExecuteAsync(BenchmarkConfig config) Utility.TeePrint("Starting Inserts with {0} tasks", taskCount); - string partitionKeyPath = containerResponse.Resource.PartitionKeyPath; int opsPerTask = config.ItemCount / taskCount; @@ -217,7 +216,6 @@ private async Task ExecuteAsync(BenchmarkConfig config) } runSummary.ConsistencyLevel = consistencyLevel; - BenchmarkProgress benchmarkProgress = await CompleteBenchmarkProgressStatus(benchmarkProgressItem, resultContainer); if (config.PublishResults) { @@ -348,11 +346,12 @@ private static async Task CreateBenchmarkProgressItem(Contain id = Environment.MachineName, MachineName = Environment.MachineName, JobStatus = "STARTED", - JobStartTime = DateTime.Now + JobStartTime = DateTime.Now, + pk = Environment.MachineName }; ItemResponse itemResponse = await resultContainer.UpsertItemAsync( - benchmarkProgress, new PartitionKey(benchmarkProgress.id)); + benchmarkProgress, new PartitionKey(benchmarkProgress.pk)); return itemResponse.Resource; } @@ -378,7 +377,10 @@ public static async Task CompleteBenchmarkProgressStatus(Benc private static async Task GetResultContainer(BenchmarkConfig config, CosmosClient cosmosClient) { Database database = cosmosClient.GetDatabase(config.ResultsDatabase ?? config.Database); - ContainerResponse containerResponse = await database.CreateContainerIfNotExistsAsync(id: config.ResultsContainer, partitionKeyPath: "/id"); + ContainerResponse containerResponse = await database + .CreateContainerIfNotExistsAsync( + id: config.ResultsContainer, + partitionKeyPath: "/pk"); return containerResponse.Container; } diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md index 5a2bac1937..afbaf84bc6 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md @@ -114,9 +114,9 @@ Copyright (C) 2019 CosmosBenchmark --branchname Branch name, only for publish --resultspartitionkeyvalue Partitionkey, only for publish --disablecoresdklogging Disable core SDK logging - --enabletelemetry Enable Telemetry + --enabletelemetry Enable Telemetry Feature --telemetryscheduleinsec Telemetry Schedule in Seconds - --telemetryendpoint Telemetry Endpoint + --enableDistributedTracing Enable Distributed Tracing Feature --resultsendpoint Endpoint to publish results to --resultskey Key to publish results to --resultsdatabase Database to publish results to diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/loop.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/loop.sh index 845f1c0022..11ff4ebf8a 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/loop.sh +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/loop.sh @@ -7,7 +7,6 @@ export PL=18 #These must be configured export ACCOUNT_ENDPOINT= export ACCOUNT_KEY= -export TELEMETRY_ENDPOINT= #Loop forever i=0 diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh index 81cafc4a4a..71b647d72d 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/run.sh @@ -24,12 +24,6 @@ then exit -1 fi -if [ -z "$TELEMETRY_ENDPOINT" ] -then - echo "Missing TELEMETRY_ENDPOINT" - exit -1 -fi - if [ -z "$INCLUDE_QUERY" ] then echo "Missing INCLUDE_QUERY" @@ -47,26 +41,26 @@ echo $COMMIT_TIME echo $BRANCH_NAME # Client telemetry disabled ReadStreamExistsV3 -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --disableClientTelemetry --disableDistributedTracing --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 10 #Wait # Client telemetry enabled ReadStreamExistsV3. This is needed to see the impact of client telemetry. -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithTelemetry --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithTelemetry --telemetryScheduleInSec 60 --disableDistributedTracing --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 10 #Wait # Open telemetry enabled ReadStreamExistsV3. This is needed to see the impact of distributed tracing (without listener) -dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithDistributedTracingWOListener --enableDistributedTracing --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk +dotnet run -c Release -- -n 2000000 -w ReadStreamExistsV3 --WorkloadName ReadStreamExistsV3WithDistributedTracingWOListener --disableClientTelemetry --tcp 10 --pl $PL -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 10 #Wait #Point read operations for WORKLOAD_NAME in ReadNotExistsV3 ReadTExistsV3 ReadStreamExistsWithDiagnosticsV3 do - dotnet run -c Release -- -n 2000000 -w $WORKLOAD_NAME --pl $PL --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk + dotnet run -c Release -- -n 2000000 -w $WORKLOAD_NAME --pl $PL --telemetryScheduleInSec 60 --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 10 #Wait done #Insert operation -dotnet run -c Release -- -n 2000000 -w InsertV3 --pl 30 --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 1 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk +dotnet run -c Release -- -n 2000000 -w InsertV3 --pl 30 --telemetryScheduleInSec 60 --tcp 1 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 45 #Wait if [ "$INCLUDE_QUERY" = true ] @@ -76,7 +70,7 @@ then # pl is 16 because 18 was casuing a small amount of thorrtles. for WORKLOAD_NAME in ReadFeedStreamV3 QueryTSinglePkV3 QueryTSinglePkOrderByWithPaginationV3 QueryTSinglePkOrderByFullDrainV3 QueryTCrossPkV3 QueryTCrossPkOrderByWithPaginationV3 QueryTCrossPkOrderByFullDrainV3 QueryStreamSinglePkV3 QueryStreamSinglePkOrderByWithPaginationV3 QueryStreamSinglePkOrderByFullDrainV3 QueryStreamCrossPkV3 QueryStreamCrossPkOrderByWithPaginationV3 QueryStreamCrossPkOrderByFullDrainV3 do - dotnet run -c Release -- -n 200000 -w $WORKLOAD_NAME --pl 16 --enableTelemetry --telemetryScheduleInSec 60 --telemetryEndpoint $TELEMETRY_ENDPOINT --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --container testcol --partitionkeypath /pk + dotnet run -c Release -- -n 200000 -w $WORKLOAD_NAME --pl 16 --telemetryScheduleInSec 60 --tcp 10 -e $ACCOUNT_ENDPOINT -k $ACCOUNT_KEY --enablelatencypercentiles --disablecoresdklogging --publishresults --resultspartitionkeyvalue $RESULTS_PK --commitid $COMMIT_ID --commitdate $COMMIT_DATE --committime $COMMIT_TIME --branchname $BRANCH_NAME --database testdb --partitionkeypath /pk --container testcol sleep 10 #Wait done fi \ No newline at end of file From 9f8d84860d3170d8a95b278a51ac2792a927a1ab Mon Sep 17 00:00:00 2001 From: leminh98 Date: Wed, 20 Sep 2023 12:00:09 -0700 Subject: [PATCH 195/337] [Internal] Query: Adds Index Metrics V2 Object Model (#4058) * making necessary ownership change * made change to ownerships * header test * Call to TryCreate instead of Create in Responsemessage * Add baseline test infra for index metric parser * update baseline files * Add parse retry logic * Update headers test * address code review * address code review * fix tests * Update csproj file * Adopt the new header * update the response to parse with text instead of base 64 * test for headers adoption of uri escape * Add URI Decode logic * Update baseline * Update with the new header name from back end * update the query parsing requirement * New Index Metrics DOM * fix build error * Code clean up * Address code review * Turn off switching to V2 * Fix test * fix test errors * Address code review comment * addressed code review * removed the empty entity * update test parse * update test --------- Co-authored-by: Minh Le --- .../src/Handler/ResponseMessage.cs | 22 +++-- .../Metrics/CompositeIndexIndexMetrics.cs | 48 +++++++++++ .../Query/Core/Metrics/IndexMetricsInfo.cs | 83 +++++++++++++++++++ .../Core/Metrics/IndexMetricsInfoEntity.cs | 43 ++++++++++ ...xMetricWriter.cs => IndexMetricsWriter.cs} | 34 ++++---- .../Core/Metrics/IndexUtilizationInfo.cs | 42 +++------- .../Core/Metrics/SingleIndexIndexMetrics.cs | 47 +++++++++++ .../DefaultDocumentQueryExecutionContext.cs | 2 +- .../src/Query/v3Query/QueryResponse.cs | 9 +- .../src/RequestOptions/QueryRequestOptions.cs | 1 + .../IndexMetricsParserBaselineTest.cs | 1 + .../Query/PopulateIndexMetricsTest.cs | 10 --- .../QueryTests.cs | 2 +- .../Metrics/IndexUtilizationInfoTests.cs | 4 +- 14 files changed, 276 insertions(+), 72 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/CompositeIndexIndexMetrics.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfo.cs create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/IndexMetricsInfoEntity.cs rename Microsoft.Azure.Cosmos/src/Query/Core/Metrics/{IndexMetricWriter.cs => IndexMetricsWriter.cs} (65%) create mode 100644 Microsoft.Azure.Cosmos/src/Query/Core/Metrics/SingleIndexIndexMetrics.cs diff --git a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs index 9694a14713..60ff675172 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs @@ -251,21 +251,27 @@ private void CheckDisposed() /// Decode the Index Metrics from the response headers, if exists. ///